From d8e328b3bd65fdefc9c49a27ee80c28e0a44b653 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 20 May 2012 00:08:13 -0600 Subject: [PATCH 0001/5711] spi: Add "spi:" prefix to modalias attribute of spi devices The modalias attribute of spi devices doesn't have the "spi:" prefix that is used in the UEVENT and in spi device drivers. This patch adds the prefix so the modprobe can correctly match modules to devices. Reported-by: David Daney Signed-off-by: Grant Likely --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1041cb83d67a..84c2861d6f4d 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -53,7 +53,7 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) { const struct spi_device *spi = to_spi_device(dev); - return sprintf(buf, "%s\n", spi->modalias); + return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); } static struct device_attribute spi_dev_attrs[] = { -- GitLab From adca473021dc8cb2397929918038f76b56a4595d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:31 +0100 Subject: [PATCH 0002/5711] drm/i915: All members of gen4 have hotplug, so unconditionally enable its irq Also as we set the HOTPLUG_EN to 0 during pre-install, we can simply set it during post-install, and nor do we wish to enable unwanted hotplug events. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 75 ++++++++++++++------------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index cc4a63307611..e31515aded8c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2320,10 +2320,8 @@ static void i965_irq_preinstall(struct drm_device * dev) atomic_set(&dev_priv->irq_received, 0); - if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - } + I915_WRITE(PORT_HOTPLUG_EN, 0); + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xeffe); for_each_pipe(pipe) @@ -2336,11 +2334,13 @@ static void i965_irq_preinstall(struct drm_device * dev) static int i965_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 hotplug_en; u32 enable_mask; u32 error_mask; /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | + I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | @@ -2356,13 +2356,6 @@ static int i965_irq_postinstall(struct drm_device *dev) dev_priv->pipestat[0] = 0; dev_priv->pipestat[1] = 0; - if (I915_HAS_HOTPLUG(dev)) { - /* Enable in IER... */ - enable_mask |= I915_DISPLAY_PORT_INTERRUPT; - /* and unmask in IMR */ - dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; - } - /* * Enable some error detection, note the instruction error mask * bit is reserved, so we leave it masked. @@ -2382,36 +2375,33 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_WRITE(IER, enable_mask); POSTING_READ(IER); - if (I915_HAS_HOTPLUG(dev)) { - u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - - /* Note HDMI and DP share bits */ - if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIB_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) - hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { - hotplug_en |= CRT_HOTPLUG_INT_EN; + /* Note HDMI and DP share hotplug bits */ + hotplug_en = 0; + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { + hotplug_en |= CRT_HOTPLUG_INT_EN; - /* Programming the CRT detection parameters tends - to generate a spurious hotplug event about three - seconds later. So just do it once. - */ - if (IS_G4X(dev)) - hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - } + /* Programming the CRT detection parameters tends + to generate a spurious hotplug event about three + seconds later. So just do it once. + */ + if (IS_G4X(dev)) + hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; + hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; + } - /* Ignore TV since it's buggy */ + /* Ignore TV since it's buggy */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - } + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); intel_opregion_enable_asle(dev); @@ -2469,8 +2459,7 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS) ret = IRQ_HANDLED; /* Consume port. Then clear IIR or we'll miss events */ - if ((I915_HAS_HOTPLUG(dev)) && - (iir & I915_DISPLAY_PORT_INTERRUPT)) { + if (iir & I915_DISPLAY_PORT_INTERRUPT) { u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", @@ -2543,10 +2532,8 @@ static void i965_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - } + I915_WRITE(PORT_HOTPLUG_EN, 0); + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xffffffff); for_each_pipe(pipe) -- GitLab From 10f76a38166cd51160b3cd7ba2f16339dd381589 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:32 +0100 Subject: [PATCH 0003/5711] drm/i915: Inspect the right status bits for DP/HDMI hotplug on gen4 The status bits corresponding to the interrupt enable bits are the "live" hotplug status bits, and reflect the current status of the port (high for a detected connection, low for a disconnect). The actual bits corresponding to the interrupt source are elsewhere. The actual event is then determined by a combination of the interrupt flag and the current live status (if the interrupt is active, but the current status is not, then we have detected a disconnect.) Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 21 +++++++++++++++------ drivers/gpu/drm/i915/intel_dp.c | 12 +++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2d49b9507ed0..7e0977b0ff2b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1558,12 +1558,21 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) #define PORT_HOTPLUG_STAT 0x61114 -#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) -#define DPB_HOTPLUG_INT_STATUS (1 << 29) -#define HDMIC_HOTPLUG_INT_STATUS (1 << 28) -#define DPC_HOTPLUG_INT_STATUS (1 << 28) -#define HDMID_HOTPLUG_INT_STATUS (1 << 27) -#define DPD_HOTPLUG_INT_STATUS (1 << 27) +/* HDMI/DP bits are gen4+ */ +#define DPB_HOTPLUG_LIVE_STATUS (1 << 29) +#define DPC_HOTPLUG_LIVE_STATUS (1 << 28) +#define DPD_HOTPLUG_LIVE_STATUS (1 << 27) +#define DPD_HOTPLUG_INT_STATUS (3 << 21) +#define DPC_HOTPLUG_INT_STATUS (3 << 19) +#define DPB_HOTPLUG_INT_STATUS (3 << 17) +/* HDMI bits are shared with the DP bits */ +#define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29) +#define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28) +#define HDMID_HOTPLUG_LIVE_STATUS (1 << 27) +#define HDMID_HOTPLUG_INT_STATUS (3 << 21) +#define HDMIC_HOTPLUG_INT_STATUS (3 << 19) +#define HDMIB_HOTPLUG_INT_STATUS (3 << 17) +/* CRT/TV/SDVO common between gen3+ */ #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a1a5ce71558a..c686393abe6d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2066,25 +2066,23 @@ g4x_dp_detect(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t temp, bit; + uint32_t bit; switch (intel_dp->output_reg) { case DP_B: - bit = DPB_HOTPLUG_INT_STATUS; + bit = DPB_HOTPLUG_LIVE_STATUS; break; case DP_C: - bit = DPC_HOTPLUG_INT_STATUS; + bit = DPC_HOTPLUG_LIVE_STATUS; break; case DP_D: - bit = DPD_HOTPLUG_INT_STATUS; + bit = DPD_HOTPLUG_LIVE_STATUS; break; default: return connector_status_unknown; } - temp = I915_READ(PORT_HOTPLUG_STAT); - - if ((temp & bit) == 0) + if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) return connector_status_disconnected; return intel_dp_detect_dpcd(intel_dp); -- GitLab From 084b612ecf8e59973576b2f644e6949609c79375 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:33 +0100 Subject: [PATCH 0004/5711] drm/i915: SDVO hotplug have different interrupt status bits for i915/i965/g4x Note that gen3 is the only platform where we've got the bit definitions right, hence the workaround of disabling sdvo hotplug support on i945g/gm is not due to misdiagnosis of broken hotplug irq handling ... Signed-off-by: Chris Wilson [danvet: add some blurb about sdvo hotplug fail on i945g/gm I've wondered about while reviewing.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 19 +++++++++++++------ drivers/gpu/drm/i915/i915_reg.h | 11 ++++++++--- drivers/gpu/drm/i915/intel_sdvo.c | 17 +++++++++++++---- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e31515aded8c..5134a62ff82f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2158,9 +2158,9 @@ static int i915_irq_postinstall(struct drm_device *dev) hotplug_en |= HDMIC_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) hotplug_en |= SDVOB_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { hotplug_en |= CRT_HOTPLUG_INT_EN; @@ -2383,10 +2383,17 @@ static int i965_irq_postinstall(struct drm_device *dev) hotplug_en |= HDMIC_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (IS_G4X(dev)) { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } else { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { hotplug_en |= CRT_HOTPLUG_INT_EN; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7e0977b0ff2b..0f45a18a5e41 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1572,15 +1572,20 @@ #define HDMID_HOTPLUG_INT_STATUS (3 << 21) #define HDMIC_HOTPLUG_INT_STATUS (3 << 19) #define HDMIB_HOTPLUG_INT_STATUS (3 << 17) -/* CRT/TV/SDVO common between gen3+ */ +/* CRT/TV common between gen3+ */ #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) -#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +/* SDVO is different across gen3/4 */ +#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) +#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) +#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) /* SDVO port control */ #define SDVOB 0x61140 diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 125228e77c50..e0c93e022995 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2511,6 +2511,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; + u32 hotplug_mask; int i; intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); @@ -2542,10 +2543,18 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) } } - if (intel_sdvo->is_sdvob) - dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; - else - dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; + hotplug_mask = 0; + if (IS_G4X(dev)) { + hotplug_mask = intel_sdvo->is_sdvob ? + SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; + } else if (IS_GEN4(dev)) { + hotplug_mask = intel_sdvo->is_sdvob ? + SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; + } else { + hotplug_mask = intel_sdvo->is_sdvob ? + SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; + } + dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); -- GitLab From 8ec22b214d76773c9d89f4040505ce10f677ed9a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:34 +0100 Subject: [PATCH 0005/5711] drm/i915/hdmi: Query the live connector status bit for G4x Similar to g4x_dp_detect() we should probe the PORT_HOTPLUG_STATUS as to whether the connector is active prior to attempting to retrieve the EDID. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2ead3bf7c21d..77f0f8fb9e35 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -452,6 +452,30 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, return true; } +static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) +{ + struct drm_device *dev = intel_hdmi->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t bit; + + switch (intel_hdmi->sdvox_reg) { + case HDMIB: + bit = HDMIB_HOTPLUG_LIVE_STATUS; + break; + case HDMIC: + bit = HDMIC_HOTPLUG_LIVE_STATUS; + break; + case HDMID: + bit = HDMID_HOTPLUG_LIVE_STATUS; + break; + default: + bit = 0; + break; + } + + return I915_READ(PORT_HOTPLUG_STAT) & bit; +} + static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { @@ -460,6 +484,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) struct edid *edid; enum drm_connector_status status = connector_status_disconnected; + if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) + return status; + intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; edid = drm_get_edid(connector, -- GitLab From 78d56d78c3ab5eeca35c6fcb10301418eda8c405 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:35 +0100 Subject: [PATCH 0006/5711] drm/i915/dp: For consistency use the DP hotplug synonyms Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c686393abe6d..9b2effcc90e5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2462,19 +2462,19 @@ intel_dp_init(struct drm_device *dev, int output_reg) case DP_B: case PCH_DP_B: dev_priv->hotplug_supported_mask |= - HDMIB_HOTPLUG_INT_STATUS; + DPB_HOTPLUG_INT_STATUS; name = "DPDDC-B"; break; case DP_C: case PCH_DP_C: dev_priv->hotplug_supported_mask |= - HDMIC_HOTPLUG_INT_STATUS; + DPC_HOTPLUG_INT_STATUS; name = "DPDDC-C"; break; case DP_D: case PCH_DP_D: dev_priv->hotplug_supported_mask |= - HDMID_HOTPLUG_INT_STATUS; + DPD_HOTPLUG_INT_STATUS; name = "DPDDC-D"; break; } -- GitLab From c9a2969830ae6f8c548f4960751dbb243f6f1f5e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 10 Apr 2012 13:55:47 +0200 Subject: [PATCH 0007/5711] drm/i915: clarify preferred sdvo input mode code - kill intel_sdvo->input_dtd, it's only used as a temporary variable, we store the preferred input mode in the adjusted mode at mode_fixup time. - rename the function to make it clear what we want it to do (get the preferred mode) and say in a comment what it unfortunately does as a side-effect (set the new output timings). Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e0c93e022995..7d4d01786daa 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -140,9 +140,6 @@ struct intel_sdvo { /* DDC bus used by this SDVO encoder */ uint8_t ddc_bus; - - /* Input timings for adjusted_mode */ - struct intel_sdvo_dtd input_dtd; }; struct intel_sdvo_connector { @@ -949,11 +946,15 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, return true; } +/* Asks the sdvo controller for the preferred input mode given the output mode. + * Unfortunately we have to set up the full output mode to do that. */ static bool -intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { + struct intel_sdvo_dtd input_dtd; + /* Reset the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) return false; @@ -965,10 +966,10 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, return false; if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, - &intel_sdvo->input_dtd)) + &input_dtd)) return false; - intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); + intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); return true; } @@ -989,17 +990,17 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) return false; - (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, - mode, - adjusted_mode); + (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, + mode, + adjusted_mode); } else if (intel_sdvo->is_lvds) { if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, intel_sdvo->sdvo_lvds_fixed_mode)) return false; - (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, - mode, - adjusted_mode); + (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, + mode, + adjusted_mode); } /* Make the CRTC code factor in the SDVO pixel multiplier. The -- GitLab From c8d4bb54c11c66610aaf8829acff6aa0506c7c29 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 10 Apr 2012 13:55:48 +0200 Subject: [PATCH 0008/5711] drm/i915: don't silently ignore sdvo mode_set failures Unfortunately we can't abort a mode_set, but at least tell the user that something might have gone wrong when setting the sdvo input or output timing fails. Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 7d4d01786daa..a1840f44941b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1054,7 +1054,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo->sdvo_lvds_fixed_mode); else intel_sdvo_get_dtd_from_mode(&output_dtd, mode); - (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); + if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd)) + DRM_INFO("Setting output timings on %s failed\n", + SDVO_NAME(intel_sdvo)); /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) @@ -1076,7 +1078,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, * adjusted_mode. */ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); + if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) + DRM_INFO("Setting input timings on %s failed\n", + SDVO_NAME(intel_sdvo)); switch (pixel_multiplier) { default: -- GitLab From 0bc77f3f06fcf2ca7b7fad782d70926cd4d235f1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 May 2012 09:55:57 -0300 Subject: [PATCH 0009/5711] [media] mt9t001: Implement V4L2_CID_PIXEL_RATE control The pixel rate control is required by the OMAP3 ISP driver and should be implemented by all media controller-compatible sensor drivers. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9t001.c | 13 +++++++++++-- include/media/mt9t001.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c index 49ca3cbfc6f1..6d343adf891d 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/video/mt9t001.c @@ -691,7 +691,7 @@ static int mt9t001_video_probe(struct i2c_client *client) return ret; /* Configure the pixel clock polarity */ - if (pdata && pdata->clk_pol) { + if (pdata->clk_pol) { ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK, MT9T001_PIXEL_CLOCK_INVERT); if (ret < 0) @@ -715,10 +715,16 @@ static int mt9t001_video_probe(struct i2c_client *client) static int mt9t001_probe(struct i2c_client *client, const struct i2c_device_id *did) { + struct mt9t001_platform_data *pdata = client->dev.platform_data; struct mt9t001 *mt9t001; unsigned int i; int ret; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { dev_warn(&client->adapter->dev, @@ -735,7 +741,7 @@ static int mt9t001_probe(struct i2c_client *client, return -ENOMEM; v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) + - ARRAY_SIZE(mt9t001_gains) + 2); + ARRAY_SIZE(mt9t001_gains) + 3); v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN, @@ -743,6 +749,9 @@ static int mt9t001_probe(struct i2c_client *client, MT9T001_SHUTTER_WIDTH_DEF); v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1); + v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, + V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk, + 1, pdata->ext_clk); for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i) v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL); diff --git a/include/media/mt9t001.h b/include/media/mt9t001.h index e839a78bb9c5..03fd63edd133 100644 --- a/include/media/mt9t001.h +++ b/include/media/mt9t001.h @@ -3,6 +3,7 @@ struct mt9t001_platform_data { unsigned int clk_pol:1; + unsigned int ext_clk; }; #endif -- GitLab From 8d690c4a4e88297451edd027d37291676bc5b9c4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 May 2012 09:55:58 -0300 Subject: [PATCH 0010/5711] [media] mt9p031: Implement V4L2_CID_PIXEL_RATE control The pixel rate control is required by the OMAP3 ISP driver and should be implemented by all media controller-compatible sensor drivers. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9p031.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c index 8f061d9ac443..3be537ef22d2 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/video/mt9p031.c @@ -950,7 +950,7 @@ static int mt9p031_probe(struct i2c_client *client, mt9p031->model = did->driver_data; mt9p031->reset = -1; - v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4); + v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5); v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN, @@ -963,6 +963,9 @@ static int mt9p031_probe(struct i2c_client *client, V4L2_CID_HFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, + V4L2_CID_PIXEL_RATE, pdata->target_freq, + pdata->target_freq, 1, pdata->target_freq); for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i) v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); -- GitLab From 5472d3f17845c4398c6a510b46855820920c2181 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 May 2012 09:55:59 -0300 Subject: [PATCH 0011/5711] [media] mt9m032: Implement V4L2_CID_PIXEL_RATE control The pixel rate control is required by the OMAP3 ISP driver and should be implemented by all media controller-compatible sensor drivers. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m032.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/mt9m032.c b/drivers/media/video/mt9m032.c index 3c1e626139b7..445359c96113 100644 --- a/drivers/media/video/mt9m032.c +++ b/drivers/media/video/mt9m032.c @@ -688,11 +688,17 @@ static const struct v4l2_subdev_ops mt9m032_ops = { static int mt9m032_probe(struct i2c_client *client, const struct i2c_device_id *devid) { + struct mt9m032_platform_data *pdata = client->dev.platform_data; struct i2c_adapter *adapter = client->adapter; struct mt9m032 *sensor; int chip_version; int ret; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { dev_warn(&client->dev, "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); @@ -708,7 +714,7 @@ static int mt9m032_probe(struct i2c_client *client, mutex_init(&sensor->lock); - sensor->pdata = client->dev.platform_data; + sensor->pdata = pdata; v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -738,7 +744,7 @@ static int mt9m032_probe(struct i2c_client *client, sensor->format.field = V4L2_FIELD_NONE; sensor->format.colorspace = V4L2_COLORSPACE_SRGB; - v4l2_ctrl_handler_init(&sensor->ctrls, 4); + v4l2_ctrl_handler_init(&sensor->ctrls, 5); v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, V4L2_CID_GAIN, 0, 127, 1, 64); @@ -754,6 +760,9 @@ static int mt9m032_probe(struct i2c_client *client, V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, MT9M032_SHUTTER_WIDTH_MAX, 1, MT9M032_SHUTTER_WIDTH_DEF); + v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, + V4L2_CID_PIXEL_RATE, pdata->pix_clock, + pdata->pix_clock, 1, pdata->pix_clock); if (sensor->ctrls.error) { ret = sensor->ctrls.error; -- GitLab From 5c81fe85dad3c8c2bcec03e3fc2bfd4ea198763c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 May 2012 15:03:08 -0700 Subject: [PATCH 0012/5711] drm/i915: timeout parameter for seqno wait Insert a wait parameter in the code so we can possibly timeout on a seqno wait if need be. The code should be functionally the same as before because all the callers will continue to retry if an arbitrary timeout elapses. We'd like to have nanosecond granularity, but the only way to do this is with hrtimer, and that doesn't fit well with the needs of this code. v2: Fix rebase error (Chris) Return proper time even in wedged + signal case (Chris + Ben) Use timespec constructs (Ben) Didn't take Daniel's advice regarding the Frankenstein-ness of the function. I did try his advice, but in the end I liked the way the original code looked, better. v3: Make wakeups far less frequent for infinite waits (Chris) v4: Remove dummy_wait variable (Daniel) Use raw monotonic time instead of jiffies (made the code a bit cleaner) (Ben) Added a couple of warnings (Ben) v5: Remove warnings (Daniel) Use more accurate time diff for default case (Daniel) Bikeshed for setting the return timespec in timeout case (Daniel) s/jiffies/time in one of the comments Signed-off-by: Ben Widawsky Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 70 +++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6d2180cf3da5..c8a5b04bc8d5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1869,34 +1869,82 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) return ret; } +/** + * __wait_seqno - wait until execution of seqno has finished + * @ring: the ring expected to report seqno + * @seqno: duh! + * @interruptible: do an interruptible wait (normally yes) + * @timeout: in - how long to wait (NULL forever); out - how much time remaining + * + * Returns 0 if the seqno was found within the alloted time. Else returns the + * errno with remaining time filled in timeout argument. + */ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, - bool interruptible) + bool interruptible, struct timespec *timeout) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - int ret = 0; + struct timespec before, now, wait_time={1,0}; + unsigned long timeout_jiffies; + long end; + bool wait_forever = true; if (i915_seqno_passed(ring->get_seqno(ring), seqno)) return 0; trace_i915_gem_request_wait_begin(ring, seqno); + + if (timeout != NULL) { + wait_time = *timeout; + wait_forever = false; + } + + timeout_jiffies = timespec_to_jiffies(&wait_time); + if (WARN_ON(!ring->irq_get(ring))) return -ENODEV; + /* Record current time in case interrupted by signal, or wedged * */ + getrawmonotonic(&before); + #define EXIT_COND \ (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ atomic_read(&dev_priv->mm.wedged)) + do { + if (interruptible) + end = wait_event_interruptible_timeout(ring->irq_queue, + EXIT_COND, + timeout_jiffies); + else + end = wait_event_timeout(ring->irq_queue, EXIT_COND, + timeout_jiffies); - if (interruptible) - ret = wait_event_interruptible(ring->irq_queue, - EXIT_COND); - else - wait_event(ring->irq_queue, EXIT_COND); + if (atomic_read(&dev_priv->mm.wedged)) + end = -EAGAIN; + } while (end == 0 && wait_forever); + + getrawmonotonic(&now); ring->irq_put(ring); trace_i915_gem_request_wait_end(ring, seqno); #undef EXIT_COND - return ret; + if (timeout) { + struct timespec sleep_time = timespec_sub(now, before); + *timeout = timespec_sub(*timeout, sleep_time); + } + + switch (end) { + case -EAGAIN: /* Wedged */ + case -ERESTARTSYS: /* Signal */ + return (int)end; + case 0: /* Timeout */ + if (timeout) + set_normalized_timespec(timeout, 0, 0); + return -ETIME; + default: /* Completed */ + WARN_ON(end < 0); /* We're not aware of other errors */ + return 0; + } } /** @@ -1920,9 +1968,7 @@ i915_wait_request(struct intel_ring_buffer *ring, if (ret) return ret; - ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible); - if (atomic_read(&dev_priv->mm.wedged)) - ret = -EAGAIN; + ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL); return ret; } @@ -3002,7 +3048,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (seqno == 0) return 0; - ret = __wait_seqno(ring, seqno, true); + ret = __wait_seqno(ring, seqno, true, NULL); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); -- GitLab From f3fd37683cc406ffaccf097de0433130c85c8651 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 May 2012 15:03:09 -0700 Subject: [PATCH 0013/5711] drm/i915: improve i915_wait_request_begin trace The trace events adds whether or not the wait was blocking. Blocking in this case means to hold struct_mutex (ie. no new work can be submitted during the wait). The information is inherently racy. The blocking information is racy since mutex_is_locked doesn't check that the current thread holds the lock. The only other option would be to pass the boolean information of whether or not the class was blocking down through the stack which is less desirable. v2: Don't do a trace event per loop. (Chris) Only get blocking/non-blocking info (Chris) v3: updated comment in code as well as commit msg (Daniel) Add "(NB)" to trace information to remind us in 6 months (Ben) Signed-off-by: Ben Widawsky Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_trace.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index dac7bba4d9da..fe90b3a84a6d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -311,9 +311,33 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, TP_ARGS(ring, seqno) ); -DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, +TRACE_EVENT(i915_gem_request_wait_begin, TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), - TP_ARGS(ring, seqno) + TP_ARGS(ring, seqno), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u32, ring) + __field(u32, seqno) + __field(bool, blocking) + ), + + /* NB: the blocking information is racy since mutex_is_locked + * doesn't check that the current thread holds the lock. The only + * other option would be to pass the boolean information of whether + * or not the class was blocking down through the stack which is + * less desirable. + */ + TP_fast_assign( + __entry->dev = ring->dev->primary->index; + __entry->ring = ring->id; + __entry->seqno = seqno; + __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); + ), + + TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", + __entry->dev, __entry->ring, __entry->seqno, + __entry->blocking ? "yes (NB)" : "no") ); DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, -- GitLab From 23ba4fd0a42a46551041e379712e808ad496ba45 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 May 2012 15:03:10 -0700 Subject: [PATCH 0014/5711] drm/i915: wait render timeout ioctl This helps implement GL_ARB_sync but stops short of allowing full blown sync objects. Finally we can use the new timed seqno waiting function to allow userspace to wait on a buffer object with a timeout. This implements that interface. The IOCTL will take as input a buffer object handle, and a timeout in nanoseconds (flags is currently optional but will likely be used for permutations of flush operations). Users may specify 0 nanoseconds to instantly check. The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any non-zero timeout parameter the wait ioctl will wait for the given number of nanoseconds on an object becoming unbusy. Since the wait itself does so holding struct_mutex the object may become re-busied before this completes. A similar but shorter race condition exists in the busy ioctl. v2: ETIME/ERESTARTSYS instead of changing to EBUSY, and EGAIN (Chris) Flush the object from the gpu write domain (Chris + Daniel) Fix leaked refcount in good case (Chris) Naturally align ioctl struct (Chris) v3: Drop lock after getting seqno to avoid ugly dance (Chris) v4: check for 0 timeout after olr check to allow polling (Chris) v5: Updated the comment. (Chris) v6: Return -ETIME instead of -EBUSY when timeout_ns is 0 (Daniel) Fix the commit message comment to be less ugly (Ben) Add a warning to check the return timespec (Ben) v7: Use DRM_AUTH for the ioctl. (Eugeni) Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_gem.c | 86 +++++++++++++++++++++++++++++++++ include/drm/i915_drm.h | 10 ++++ 4 files changed, 99 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f94792626b94..262a74d1f852 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1803,6 +1803,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 11c7a6a330c1..8ac10e8c0cdb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1229,6 +1229,8 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data, struct drm_file *file_priv); 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(struct drm_device *dev); int i915_gem_init_object(struct drm_gem_object *obj); int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8a5b04bc8d5..a0d740fac240 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2000,6 +2000,92 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) return 0; } +/** + * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT + * @DRM_IOCTL_ARGS: standard ioctl arguments + * + * Returns 0 if successful, else an error is returned with the remaining time in + * the timeout parameter. + * -ETIME: object is still busy after timeout + * -ERESTARTSYS: signal interrupted the wait + * -ENONENT: object doesn't exist + * Also possible, but rare: + * -EAGAIN: GPU wedged + * -ENOMEM: damn + * -ENODEV: Internal IRQ fail + * -E?: The add request failed + * + * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any + * non-zero timeout parameter the wait ioctl will wait for the given number of + * nanoseconds on an object becoming unbusy. Since the wait itself does so + * without holding struct_mutex the object may become re-busied before this + * function completes. A similar but shorter * race condition exists in the busy + * ioctl + */ +int +i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct drm_i915_gem_wait *args = data; + struct drm_i915_gem_object *obj; + struct intel_ring_buffer *ring = NULL; + struct timespec timeout; + u32 seqno = 0; + int ret = 0; + + timeout = ns_to_timespec(args->timeout_ns); + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + return ret; + + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle)); + if (&obj->base == NULL) { + mutex_unlock(&dev->struct_mutex); + return -ENOENT; + } + + /* Need to make sure the object is flushed first. This non-obvious + * flush is required to enforce that (active && !olr) == no wait + * necessary. + */ + ret = i915_gem_object_flush_gpu_write_domain(obj); + if (ret) + goto out; + + if (obj->active) { + seqno = obj->last_rendering_seqno; + ring = obj->ring; + } + + if (seqno == 0) + goto out; + + ret = i915_gem_check_olr(ring, seqno); + if (ret) + goto out; + + /* Do this after OLR check to make sure we make forward progress polling + * on this IOCTL with a 0 timeout (like busy ioctl) + */ + if (!args->timeout_ns) { + ret = -ETIME; + goto out; + } + + drm_gem_object_unreference(&obj->base); + mutex_unlock(&dev->struct_mutex); + + ret = __wait_seqno(ring, seqno, true, &timeout); + WARN_ON(!timespec_valid(&timeout)); + args->timeout_ns = timespec_to_ns(&timeout); + return ret; + +out: + drm_gem_object_unreference(&obj->base); + mutex_unlock(&dev->struct_mutex); + return ret; +} + /** * i915_gem_object_sync - sync an object to a ring. * diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index f3f82242bf1d..bab174334da5 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -200,6 +200,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_EXECBUFFER2 0x29 #define DRM_I915_GET_SPRITE_COLORKEY 0x2a #define DRM_I915_SET_SPRITE_COLORKEY 0x2b +#define DRM_I915_GEM_WAIT 0x2c #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -243,6 +244,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -886,4 +888,12 @@ struct drm_intel_sprite_colorkey { __u32 flags; }; +struct drm_i915_gem_wait { + /** Handle of BO we shall wait on */ + __u32 bo_handle; + __u32 flags; + /** Number of nanoseconds to wait, Returns time remaining. */ + __u64 timeout_ns; +}; + #endif /* _I915_DRM_H_ */ -- GitLab From 199b2bc25ba587f666a712e9d8475d691d9cec4c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 May 2012 15:03:11 -0700 Subject: [PATCH 0015/5711] drm/i915: s/i915_wait_request/i915_wait_seqno/g Wait request is poorly named IMO. After working with these functions for some time, I feel it's much clearer to name the functions more appropriately. Of course we must update the callers to use the new name as well. This leaves room within our namespace for a *real* wait request function at some point. Note to maintainer: this patch is optional. Signed-off-by: Ben Widawsky Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 9 ++++----- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8ac10e8c0cdb..a17e31e91951 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1315,8 +1315,8 @@ int __must_check i915_gem_idle(struct drm_device *dev); int __must_check i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, struct drm_i915_gem_request *request); -int __must_check i915_wait_request(struct intel_ring_buffer *ring, - uint32_t seqno); +int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, + uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int __must_check i915_gem_object_set_to_gtt_domain(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 a0d740fac240..d2eaa008573b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1952,8 +1952,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, * request and object lists appropriately for that event. */ int -i915_wait_request(struct intel_ring_buffer *ring, - uint32_t seqno) +i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) { drm_i915_private_t *dev_priv = ring->dev->dev_private; int ret = 0; @@ -1991,7 +1990,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) * it. */ if (obj->active) { - ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); + ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno); if (ret) return ret; i915_gem_retire_requests_ring(obj->ring); @@ -2264,7 +2263,7 @@ static int i915_ring_idle(struct intel_ring_buffer *ring) return ret; } - return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); + return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring)); } int i915_gpu_idle(struct drm_device *dev) @@ -2468,7 +2467,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj) } if (obj->last_fenced_seqno) { - ret = i915_wait_request(obj->ring, obj->last_fenced_seqno); + ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 458743da3774..830d0dd610e1 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -226,7 +226,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, } overlay->last_flip_req = request->seqno; overlay->flip_tail = tail; - ret = i915_wait_request(ring, overlay->last_flip_req); + ret = i915_wait_seqno(ring, overlay->last_flip_req); if (ret) return ret; i915_gem_retire_requests(dev); @@ -452,7 +452,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) if (overlay->last_flip_req == 0) return 0; - ret = i915_wait_request(ring, overlay->last_flip_req); + ret = i915_wait_seqno(ring, overlay->last_flip_req); if (ret) return ret; i915_gem_retire_requests(dev); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b59b6d5b7583..1df1694835a1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1085,7 +1085,7 @@ static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) was_interruptible = dev_priv->mm.interruptible; dev_priv->mm.interruptible = false; - ret = i915_wait_request(ring, seqno); + ret = i915_wait_seqno(ring, seqno); dev_priv->mm.interruptible = was_interruptible; if (!ret) -- GitLab From eeafaaca763408c099d2ade3a69e0716f296a97b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 25 May 2012 10:23:37 +0100 Subject: [PATCH 0016/5711] drm/i915/hdmi: Fix reg values for g4x_hdmi_connected Paulo pointed out that gen4 re-used the SDVO registers for HDMI (the separate HDMI registers where introduced with the first PCH) and so g4x_hdmi_connected() never selected the right bit and always returned disconnected. Regression in commit 8ec22b214d76773c9d89f4040505ce10f677ed9a Author: Chris Wilson Date: Fri May 11 18:01:34 2012 +0100 drm/i915/hdmi: Query the live connector status bit for G4x Cc: Paulo Zanoni Reviewed-by: Paulo Zanoni Tested-by: Paulo Zanoni Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 77f0f8fb9e35..4c6f1411b28a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -459,15 +459,12 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) uint32_t bit; switch (intel_hdmi->sdvox_reg) { - case HDMIB: + case SDVOB: bit = HDMIB_HOTPLUG_LIVE_STATUS; break; - case HDMIC: + case SDVOC: bit = HDMIC_HOTPLUG_LIVE_STATUS; break; - case HDMID: - bit = HDMID_HOTPLUG_LIVE_STATUS; - break; default: bit = 0; break; -- GitLab From 0df2c999f748c9528f6629f45baaa86118d60cd1 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 25 May 2012 21:36:15 +0800 Subject: [PATCH 0017/5711] gpio/of: fix a typo of comment message Signed-off-by: Dong Aisheng Signed-off-by: Grant Likely --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d18068a9f3ec..8389d4a0ec45 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -21,7 +21,7 @@ #include #include -/* Private data structure for of_gpiochip_is_match */ +/* Private data structure for of_gpiochip_find_and_xlate */ struct gg_data { enum of_gpio_flags *flags; struct of_phandle_args gpiospec; -- GitLab From 96b70641b937e99c1579cb6ebbcdb7b0af98cdd0 Mon Sep 17 00:00:00 2001 From: Andreas Schallenberg Date: Mon, 21 May 2012 09:52:43 +0200 Subject: [PATCH 0018/5711] gpio/tca6424: merge I2C transactions, remove cast This is a follow-up to ae79c1904 "[PATCH v2] Add support for TCA6424" merged in the v3.5 merge window. It fixes comments made when the patch was merged. - Use 3 byte transfers instead of two separate transfers (2+1 byte) - An unnecessary cast removed Signed-off-by: Andreas Schallenberg Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 1c313c710be3..de24af202447 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -98,12 +98,11 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val) if (chip->gpio_chip.ngpio <= 8) ret = i2c_smbus_write_byte_data(chip->client, reg, val); else if (chip->gpio_chip.ngpio == 24) { - ret = i2c_smbus_write_word_data(chip->client, + cpu_to_le32s(&val); + ret = i2c_smbus_write_i2c_block_data(chip->client, (reg << 2) | REG_ADDR_AI, - val & 0xffff); - ret = i2c_smbus_write_byte_data(chip->client, - (reg << 2) + 2, - (val & 0xff0000) >> 16); + 3, + (u8 *) &val); } else { switch (chip->chip_type) { @@ -135,22 +134,27 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val) { int ret; - if (chip->gpio_chip.ngpio <= 8) + if (chip->gpio_chip.ngpio <= 8) { ret = i2c_smbus_read_byte_data(chip->client, reg); - else if (chip->gpio_chip.ngpio == 24) { - ret = i2c_smbus_read_word_data(chip->client, reg << 2); - ret |= (i2c_smbus_read_byte_data(chip->client, - (reg << 2) + 2)<<16); + *val = ret; } - else + else if (chip->gpio_chip.ngpio == 24) { + *val = 0; + ret = i2c_smbus_read_i2c_block_data(chip->client, + (reg << 2) | REG_ADDR_AI, + 3, + (u8 *) val); + le32_to_cpus(val); + } else { ret = i2c_smbus_read_word_data(chip->client, reg << 1); + *val = ret; + } if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; } - *val = (u32)ret; return 0; } -- GitLab From 188726ecb66f022e92ec110ca85c62a937184636 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 24 May 2012 19:28:17 +0200 Subject: [PATCH 0019/5711] firewire: core: make address handler length 64 bits The type of the length field of the fw_address_handler structure was size_t, which restricted it to 32 bits on 32-bit architectures. While making it u32 would match the userspace API, all calculations on this field use 64 bits anyway, and the ability to use 4 GB or larger address ranges is useful in the kernel. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- include/linux/firewire.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 584826ba2eb7..d77f60c6d1ed 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -307,7 +307,7 @@ struct fw_transaction { struct fw_address_handler { u64 offset; - size_t length; + u64 length; fw_address_callback_t address_callback; void *callback_data; struct list_head link; -- GitLab From f07d42ac7f2a7d650125d0cd7a79631c4522edaf Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 24 May 2012 19:28:58 +0200 Subject: [PATCH 0020/5711] firewire: core: allocate the low memory region Prevent userspace applications from allocating low memory address ranges. Otherwise, if some application happens to allocate such a range and intends for a remote node to access it, and if that node also implements SBP-2 (which will become more likely with the upcoming SBP-2 target support), these accesses would be routed by the physical DMA unit to some wrong memory address. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 1c4980c32f90..fc2ad654e1ad 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -525,9 +525,10 @@ const struct fw_address_region fw_high_memory_region = { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, }; EXPORT_SYMBOL(fw_high_memory_region); -#if 0 -const struct fw_address_region fw_low_memory_region = +static const struct fw_address_region low_memory_region = { .start = 0x000000000000ULL, .end = 0x000100000000ULL, }; + +#if 0 const struct fw_address_region fw_private_region = { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, }; const struct fw_address_region fw_csr_region = @@ -1189,6 +1190,23 @@ static struct fw_address_handler registers = { .address_callback = handle_registers, }; +static void handle_low_memory(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, int generation, + unsigned long long offset, void *payload, size_t length, + void *callback_data) +{ + /* + * This catches requests not handled by the physical DMA unit, + * i.e., wrong transaction types or unauthorized source nodes. + */ + fw_send_response(card, request, RCODE_TYPE_ERROR); +} + +static struct fw_address_handler low_memory = { + .length = 0x000100000000ULL, + .address_callback = handle_low_memory, +}; + MODULE_AUTHOR("Kristian Hoegsberg "); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); @@ -1250,6 +1268,7 @@ static int __init fw_core_init(void) fw_core_add_address_handler(&topology_map, &topology_map_region); fw_core_add_address_handler(®isters, ®isters_region); + fw_core_add_address_handler(&low_memory, &low_memory_region); fw_core_add_descriptor(&vendor_id_descriptor); fw_core_add_descriptor(&model_id_descriptor); -- GitLab From 9d60ef2bd87f201c509cfae13ba6c9013446673d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 24 May 2012 19:29:19 +0200 Subject: [PATCH 0021/5711] firewire: ohci: lazy bus time initialization The Bus_Time CSR is virtually never used, so we can avoid burning CPU in interrupt context for 1 or 3 IsochronousCycleTimer accesses every minute by not tracking the bus time until the CSR is actually accessed for the first time. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c1af05e834b6..1c365b827815 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -191,6 +191,7 @@ struct fw_ohci { unsigned quirks; unsigned int pri_req_max; u32 bus_time; + bool bus_time_running; bool is_root; bool csr_state_setclear_abdicate; int n_ir; @@ -1726,6 +1727,13 @@ static u32 update_bus_time(struct fw_ohci *ohci) { u32 cycle_time_seconds = get_cycle_time(ohci) >> 25; + if (unlikely(!ohci->bus_time_running)) { + reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_cycle64Seconds); + ohci->bus_time = (lower_32_bits(get_seconds()) & ~0x7f) | + (cycle_time_seconds & 0x40); + ohci->bus_time_running = true; + } + if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40)) ohci->bus_time += 0x40; @@ -2213,7 +2221,7 @@ static int ohci_enable(struct fw_card *card, { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - u32 lps, seconds, version, irqs; + u32 lps, version, irqs; int i, ret; if (software_reset(ohci)) { @@ -2269,9 +2277,7 @@ static int ohci_enable(struct fw_card *card, (OHCI1394_MAX_PHYS_RESP_RETRIES << 8) | (200 << 16)); - seconds = lower_32_bits(get_seconds()); - reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); - ohci->bus_time = seconds & ~0x3f; + ohci->bus_time_running = false; version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; if (version >= OHCI_VERSION_1_1) { @@ -2369,7 +2375,6 @@ static int ohci_enable(struct fw_card *card, OHCI1394_postedWriteErr | OHCI1394_selfIDComplete | OHCI1394_regAccessFail | - OHCI1394_cycle64Seconds | OHCI1394_cycleInconsistent | OHCI1394_unrecoverableError | OHCI1394_cycleTooLong | @@ -2658,7 +2663,8 @@ static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value) case CSR_BUS_TIME: spin_lock_irqsave(&ohci->lock, flags); - ohci->bus_time = (ohci->bus_time & 0x7f) | (value & ~0x7f); + ohci->bus_time = (update_bus_time(ohci) & 0x40) | + (value & ~0x7f); spin_unlock_irqrestore(&ohci->lock, flags); break; -- GitLab From 687f4d06dbb1cf3c8f9f6050cd7aad24dc0ce978 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:48 -0300 Subject: [PATCH 0022/5711] drm/i915: add set_infoframes to struct intel_hdmi We need a function that is able to fully 'set' the state of the DIP registers to a known state. Currently, we have the write_infoframe function that is called twice: once for AVI and once for SPD. The problem is that write_infoframe tries to keep the state of the DIP register as it is, changing only the minimum necessary bits. The second problem is that write_infoframe does twice (once for each time it is called) some work that should be done only once (like waiting for vblank and setting the port). If we add even more DIPs, it will do even more repeated work. This patch only adds the infrastructure keeping the code behavior the same as before. v2: add static keywords Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 3 +- drivers/gpu/drm/i915/intel_drv.h | 5 ++-- drivers/gpu/drm/i915/intel_hdmi.c | 47 ++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 46d1e886c692..f33fe1a1c33e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -726,8 +726,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, I915_WRITE(DDI_FUNC_CTL(pipe), temp); - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); + intel_hdmi->set_infoframes(encoder, adjusted_mode); } void intel_ddi_dpms(struct drm_encoder *encoder, int mode) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3e0918834e7e..39d7b07c1e8b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -301,6 +301,8 @@ struct intel_hdmi { enum hdmi_force_audio force_audio; void (*write_infoframe)(struct drm_encoder *encoder, struct dip_infoframe *frame); + void (*set_infoframes)(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode); }; static inline struct drm_crtc * @@ -343,9 +345,6 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector) extern void intel_crt_init(struct drm_device *dev); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); -extern void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode); -extern void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder); extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4c6f1411b28a..8d892b0cd8a1 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -315,7 +315,7 @@ static void intel_set_infoframe(struct drm_encoder *encoder, intel_hdmi->write_infoframe(encoder, frame); } -void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, +static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct dip_infoframe avi_if = { @@ -330,7 +330,7 @@ void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, intel_set_infoframe(encoder, &avi_if); } -void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) +static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) { struct dip_infoframe spd_if; @@ -345,6 +345,41 @@ void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) intel_set_infoframe(encoder, &spd_if); } +static void g4x_set_infoframes(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); +} + +static void ibx_set_infoframes(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); +} + +static void cpt_set_infoframes(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); +} + +static void vlv_set_infoframes(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); +} + +static void hsw_set_infoframes(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); +} + static void intel_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -388,8 +423,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, I915_WRITE(intel_hdmi->sdvox_reg, sdvox); POSTING_READ(intel_hdmi->sdvox_reg); - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); + intel_hdmi->set_infoframes(encoder, adjusted_mode); } static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) @@ -734,9 +768,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = g4x_write_infoframe; + intel_hdmi->set_infoframes = g4x_set_infoframes; I915_WRITE(VIDEO_DIP_CTL, 0); } else if (IS_VALLEYVIEW(dev)) { intel_hdmi->write_infoframe = vlv_write_infoframe; + intel_hdmi->set_infoframes = vlv_set_infoframes; for_each_pipe(i) I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); } else if (IS_HASWELL(dev)) { @@ -744,14 +780,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) * just doing the minimal required for HDMI to work at this stage. */ intel_hdmi->write_infoframe = hsw_write_infoframe; + intel_hdmi->set_infoframes = hsw_set_infoframes; for_each_pipe(i) I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); } else if (HAS_PCH_IBX(dev)) { intel_hdmi->write_infoframe = ibx_write_infoframe; + intel_hdmi->set_infoframes = ibx_set_infoframes; for_each_pipe(i) I915_WRITE(TVIDEO_DIP_CTL(i), 0); } else { intel_hdmi->write_infoframe = cpt_write_infoframe; + intel_hdmi->set_infoframes = cpt_set_infoframes; for_each_pipe(i) I915_WRITE(TVIDEO_DIP_CTL(i), 0); } -- GitLab From 0c14c7f957e70c3cb100e3fd6553b0ebea557571 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:49 -0300 Subject: [PATCH 0023/5711] drm/i915: properly alternate between DVI and HDMI This solves problems that happen when you alternate between HDMI and DVI on the same port. I can reproduce these problems using DP->HDMI and DP->DVI adapters on a DP port. When you first plug HDMI and then plug DVI, you need to stop sending DIPs, even if the port is in DVI mode (see the HDMI register spec). If you don't stop sending DIPs, you'll see a pink vertical line on the left side of the screen, some modes will give you a black screen, some modes won't work correctly. When you first plug DVI and then plug HDMI, you need to properly enable the DIPs, otherwise the HW won't send them. After spending a lot of time investigating this, I concluded that if the DIPs are disabled, we should not write to the DIP register again because when we do this, we also set the AVI InfoFrame frequency to "once", and this seems to really confuse our hardware. Since this problem was not exactly easy to debug, I'm adopting the defensive behavior and not just avoing the "disable twice" sequence, but also explicitly selecting the AVI InfoFrame and setting its frequency to a correct one. Also, move the "is_dvi" check from intel_set_infoframe to the set_infoframes functions since now they're going to be the first ones to deal with the DIP registers. This patch adds the code to fix the problem, but it depends on the removal of some code that can't be removed right now and will come later in the patch series. The patch that we need is: - drm/i915: don't write 0 to DIP control at HDMI init [danvet: Paulo clarified that this additional patch is only required to make the fix complete, this patch here alone doesn't introduce a regression but only partially solves the problem of randomly clearing the dip registers.] V2: Be even more defensive by selecting AVI and setting its frequency outside the "is_dvi" check. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 88 +++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 8d892b0cd8a1..2f2adc4e511c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -308,9 +308,6 @@ static void intel_set_infoframe(struct drm_encoder *encoder, { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - if (!intel_hdmi->has_hdmi_sink) - return; - intel_dip_infoframe_csum(frame); intel_hdmi->write_infoframe(encoder, frame); } @@ -348,6 +345,30 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) static void g4x_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + u32 reg = VIDEO_DIP_CTL; + u32 val = I915_READ(reg); + + /* If the registers were not initialized yet, they might be zeroes, + * which means we're selecting the AVI DIP and we're setting its + * frequency to once. This seems to really confuse the HW and make + * things stop working (the register spec says the AVI always needs to + * be sent every VSync). So here we avoid writing to the register more + * than we need and also explicitly select the AVI DIP and explicitly + * set its frequency to every VSync. Avoiding to write it twice seems to + * be enough to solve the problem, but being defensive shouldn't hurt us + * either. */ + val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; + + if (!intel_hdmi->has_hdmi_sink) { + if (!(val & VIDEO_DIP_ENABLE)) + return; + val &= ~VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); + return; + } + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -355,6 +376,23 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, static void ibx_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + u32 val = I915_READ(reg); + + /* See the big comment in g4x_set_infoframes() */ + val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; + + if (!intel_hdmi->has_hdmi_sink) { + if (!(val & VIDEO_DIP_ENABLE)) + return; + val &= ~VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); + return; + } + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -362,6 +400,23 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, static void cpt_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + u32 val = I915_READ(reg); + + /* See the big comment in g4x_set_infoframes() */ + val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; + + if (!intel_hdmi->has_hdmi_sink) { + if (!(val & VIDEO_DIP_ENABLE)) + return; + val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); + I915_WRITE(reg, val); + return; + } + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -369,6 +424,23 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, static void vlv_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); + u32 val = I915_READ(reg); + + /* See the big comment in g4x_set_infoframes() */ + val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; + + if (!intel_hdmi->has_hdmi_sink) { + if (!(val & VIDEO_DIP_ENABLE)) + return; + val &= ~VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); + return; + } + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -376,6 +448,16 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, static void hsw_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); + + if (!intel_hdmi->has_hdmi_sink) { + I915_WRITE(reg, 0); + return; + } + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } -- GitLab From f278d97215d3cca43aa1569b5ae712cc17e74702 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:50 -0300 Subject: [PATCH 0024/5711] drm/i915: only set the HDMI port on the DIP once Not once for each InfoFrame. Now we have a function that allows us to do this. [danvet: Paulo clarified on irc that a later bugfix patch needs this cleanup.] Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 56 +++++++++++++++++-------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2f2adc4e511c..1df1ec764a01 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -121,18 +121,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, uint32_t *data = (uint32_t *)frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 val = I915_READ(VIDEO_DIP_CTL); unsigned i, len = DIP_HEADER_SIZE + frame->len; - val &= ~VIDEO_DIP_PORT_MASK; - if (intel_hdmi->sdvox_reg == SDVOB) - val |= VIDEO_DIP_PORT_B; - else if (intel_hdmi->sdvox_reg == SDVOC) - val |= VIDEO_DIP_PORT_C; - else - return; - val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); @@ -160,26 +151,10 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); - val &= ~VIDEO_DIP_PORT_MASK; - switch (intel_hdmi->sdvox_reg) { - case HDMIB: - val |= VIDEO_DIP_PORT_B; - break; - case HDMIC: - val |= VIDEO_DIP_PORT_C; - break; - case HDMID: - val |= VIDEO_DIP_PORT_D; - break; - default: - return; - } - intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ @@ -369,6 +344,20 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, return; } + val &= ~VIDEO_DIP_PORT_MASK; + switch (intel_hdmi->sdvox_reg) { + case SDVOB: + val |= VIDEO_DIP_PORT_B; + break; + case SDVOC: + val |= VIDEO_DIP_PORT_C; + break; + default: + return; + } + + I915_WRITE(reg, val); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -393,6 +382,23 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, return; } + val &= ~VIDEO_DIP_PORT_MASK; + switch (intel_hdmi->sdvox_reg) { + case HDMIB: + val |= VIDEO_DIP_PORT_B; + break; + case HDMIC: + val |= VIDEO_DIP_PORT_C; + break; + case HDMID: + val |= VIDEO_DIP_PORT_D; + break; + default: + return; + } + + I915_WRITE(reg, val); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } -- GitLab From 822974aea875348e69fb6b6d2078ae8372eeec66 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:51 -0300 Subject: [PATCH 0025/5711] drm/i915: enable DIP before enabling each InfoFrame So the write_infoframe function can assume the DIP is on. V2: Be more defensive and add WARN(). Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 1df1ec764a01..de6f4c2c82ac 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -124,11 +124,12 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, u32 val = I915_READ(VIDEO_DIP_CTL); unsigned i, len = DIP_HEADER_SIZE + frame->len; + WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); - val |= VIDEO_DIP_ENABLE; I915_WRITE(VIDEO_DIP_CTL, val); @@ -155,13 +156,14 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); + WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); - val |= VIDEO_DIP_ENABLE; I915_WRITE(reg, val); @@ -188,6 +190,8 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); + WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ @@ -195,13 +199,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, /* The DIP control register spec says that we need to update the AVI * infoframe without clearing its enable bit */ - if (frame->type == DIP_TYPE_AVI) - val |= VIDEO_DIP_ENABLE_AVI; - else + if (frame->type != DIP_TYPE_AVI) val &= ~g4x_infoframe_enable(frame); - val |= VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); for (i = 0; i < len; i += 4) { @@ -227,13 +227,14 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); + WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); - val |= VIDEO_DIP_ENABLE; I915_WRITE(reg, val); @@ -356,6 +357,8 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, return; } + val |= VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); @@ -397,6 +400,8 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, return; } + val |= VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); @@ -423,6 +428,11 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, return; } + /* Set both together, unset both together: see the spec. */ + val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; + + I915_WRITE(reg, val); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } @@ -447,6 +457,10 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, return; } + val |= VIDEO_DIP_ENABLE; + + I915_WRITE(reg, val); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } -- GitLab From 5cde2a62e8adf12b02e47cf15630e87d4ba8ad5e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:52 -0300 Subject: [PATCH 0026/5711] drm/i915: don't wait for vblank while writing InfoFrames This function is called when the pipe is disabled, so it always gets the 50ms timeout. This function is called once for each InfoFrame, so we actually get a 100ms timeout. Will be more if we add more InfoFrames. Also, the spec says we need to "wait for a VSync to ensure completion of any pending DIP transmissions", not for a VBlank. OTOH, the register documentation suggests that the DIPs are sent *during* the VSync, so shouldn't we be waiting until *after* the VSync to ensure all DIPs are sent? So this wait_for_vblank seems, besides useless, totally wrong. If we ever want to change some specific InfoFrame on-the-fly (outside of the modeset code), the code that changes the InfoFrame will have to do the waiting itself, and properly. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index de6f4c2c82ac..614d83fb6738 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -158,8 +158,6 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); - intel_wait_for_vblank(dev, intel_crtc->pipe); - val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); @@ -192,8 +190,6 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); - intel_wait_for_vblank(dev, intel_crtc->pipe); - val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); @@ -229,8 +225,6 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); - intel_wait_for_vblank(dev, intel_crtc->pipe); - val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); @@ -265,8 +259,6 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, if (data_reg == 0) return; - intel_wait_for_vblank(dev, intel_crtc->pipe); - val &= ~hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); -- GitLab From 0dd87d2084fc9e1f663d3a2c24f0e3f94b7f20e4 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:53 -0300 Subject: [PATCH 0027/5711] drm/i915: explicitly disable the DIPs we're not using From this point on, the 'set_infoframe' functions always set the DIP registers to a known state, so anything done will always be undone at the modeset. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_hdmi.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0f45a18a5e41..1855ac732718 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1717,8 +1717,10 @@ #define VIDEO_DIP_PORT_C (2 << 29) #define VIDEO_DIP_PORT_D (3 << 29) #define VIDEO_DIP_PORT_MASK (3 << 29) +#define VIDEO_DIP_ENABLE_GCP (1 << 25) #define VIDEO_DIP_ENABLE_AVI (1 << 21) #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) +#define VIDEO_DIP_ENABLE_GAMUT (4 << 21) #define VIDEO_DIP_ENABLE_SPD (8 << 21) #define VIDEO_DIP_SELECT_AVI (0 << 19) #define VIDEO_DIP_SELECT_VENDOR (1 << 19) @@ -1729,7 +1731,11 @@ #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) #define VIDEO_DIP_FREQ_MASK (3 << 16) /* HSW and later: */ +#define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) +#define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) +#define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) +#define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) /* Panel power sequencing */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 614d83fb6738..620b0dba9e7a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -350,6 +350,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, } val |= VIDEO_DIP_ENABLE; + val &= ~VIDEO_DIP_ENABLE_VENDOR; I915_WRITE(reg, val); @@ -393,6 +394,8 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, } val |= VIDEO_DIP_ENABLE; + val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | + VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); @@ -422,6 +425,8 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, /* Set both together, unset both together: see the spec. */ val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; + val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | + VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); @@ -450,6 +455,8 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, } val |= VIDEO_DIP_ENABLE; + val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | + VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); @@ -464,12 +471,18 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); + u32 val = I915_READ(reg); if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); return; } + val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | + VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); + + I915_WRITE(reg, val); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); } -- GitLab From 72b78c9d19ee3e69988424c499498e50eaba0859 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:54 -0300 Subject: [PATCH 0028/5711] drm/i915: disable DIP while changing the port The register specification says we need to do this. V2: Only write the register if the port is enabled. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 32 ++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 620b0dba9e7a..c858da986fdd 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -317,6 +317,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 reg = VIDEO_DIP_CTL; u32 val = I915_READ(reg); + u32 port; /* If the registers were not initialized yet, they might be zeroes, * which means we're selecting the AVI DIP and we're setting its @@ -337,18 +338,26 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, return; } - val &= ~VIDEO_DIP_PORT_MASK; switch (intel_hdmi->sdvox_reg) { case SDVOB: - val |= VIDEO_DIP_PORT_B; + port = VIDEO_DIP_PORT_B; break; case SDVOC: - val |= VIDEO_DIP_PORT_C; + port = VIDEO_DIP_PORT_C; break; default: return; } + if (port != (val & VIDEO_DIP_PORT_MASK)) { + if (val & VIDEO_DIP_ENABLE) { + val &= ~VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); + } + val &= ~VIDEO_DIP_PORT_MASK; + val |= port; + } + val |= VIDEO_DIP_ENABLE; val &= ~VIDEO_DIP_ENABLE_VENDOR; @@ -366,6 +375,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + u32 port; /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; @@ -378,21 +388,29 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, return; } - val &= ~VIDEO_DIP_PORT_MASK; switch (intel_hdmi->sdvox_reg) { case HDMIB: - val |= VIDEO_DIP_PORT_B; + port = VIDEO_DIP_PORT_B; break; case HDMIC: - val |= VIDEO_DIP_PORT_C; + port = VIDEO_DIP_PORT_C; break; case HDMID: - val |= VIDEO_DIP_PORT_D; + port = VIDEO_DIP_PORT_D; break; default: return; } + if (port != (val & VIDEO_DIP_PORT_MASK)) { + if (val & VIDEO_DIP_ENABLE) { + val &= ~VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); + } + val &= ~VIDEO_DIP_PORT_MASK; + val |= port; + } + val |= VIDEO_DIP_ENABLE; val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); -- GitLab From 9d32d1653db10eaba3140dd1a2f8dad51122f0b5 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:55 -0300 Subject: [PATCH 0029/5711] drm/i915: don't write 0 to DIP control at HDMI init At this time, the HDMI port is enabled, and the DIP control register specification says we need to disable the port *before* disabling the DIPs. Also, while doing this we risk telling the HW to send the AVI DIPs once (not every VSync), which really seems to confuse the HW and trigger bugs where the DIPs are not sent. This code was here just to set the DIP register to a 'known state' before using it, but since now the set_infoframes functions already set the control registers to a known state, this code can go away. Also, the previous code disables *all* the DIP registers for *each* HDMI port, so we end disabling each DIP register more than once. This patch solves a problem I can reproduce on my IVB machine. When I boot it with just a single HDMI monitor, the AVI InfoFrames are not sent. With this patch, the InfoFrames are sent. Previously, I wrote a patch to 'touch the DIP registers after we enable the HDMI port' to solve this same problem, but that patch doesn't seem to be needed anymore after this patch. All this patch does is revert a chunk of the following commit: commit 64a8fc0145a1d0fdc25fc9367c2e6c621955fb3b Author: Jesse Barnes Date: Thu Sep 22 11:16:00 2011 +0530 drm/i915: fix ILK+ infoframe support So bugs that can be bisected to that commit may be fixed now. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43256 Acked-by: Jesse Barnes Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c858da986fdd..65af12ee98b1 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -816,7 +816,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; struct intel_hdmi *intel_hdmi; - int i; intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); if (!intel_hdmi) @@ -894,30 +893,21 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = g4x_write_infoframe; intel_hdmi->set_infoframes = g4x_set_infoframes; - I915_WRITE(VIDEO_DIP_CTL, 0); } else if (IS_VALLEYVIEW(dev)) { intel_hdmi->write_infoframe = vlv_write_infoframe; intel_hdmi->set_infoframes = vlv_set_infoframes; - for_each_pipe(i) - I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); } else if (IS_HASWELL(dev)) { /* FIXME: Haswell has a new set of DIP frame registers, but we are * just doing the minimal required for HDMI to work at this stage. */ intel_hdmi->write_infoframe = hsw_write_infoframe; intel_hdmi->set_infoframes = hsw_set_infoframes; - for_each_pipe(i) - I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); } else if (HAS_PCH_IBX(dev)) { intel_hdmi->write_infoframe = ibx_write_infoframe; intel_hdmi->set_infoframes = ibx_set_infoframes; - for_each_pipe(i) - I915_WRITE(TVIDEO_DIP_CTL(i), 0); } else { intel_hdmi->write_infoframe = cpt_write_infoframe; intel_hdmi->set_infoframes = cpt_set_infoframes; - for_each_pipe(i) - I915_WRITE(TVIDEO_DIP_CTL(i), 0); } if (IS_HASWELL(dev)) -- GitLab From b659c3dbe17714485a1756b74e92c27301571a80 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:56 -0300 Subject: [PATCH 0030/5711] drm/i915: don't set SDVO_BORDER_ENABLE when we're HDMI The register that controls the HDMI port can be used to control the sDVO port. Some bits are defined only for sDVO, and SDVO_BORDER_ENABLE is one of those: HDMI ports that can't be used in sDVO mode don't even have this bit defined in their specifications. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 65af12ee98b1..194b453b052c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -515,7 +515,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 sdvox; - sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; + sdvox = SDVO_ENCODING_HDMI; if (!HAS_PCH_SPLIT(dev)) sdvox |= intel_hdmi->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) -- GitLab From c30b61109021ecbc81966573862cf98f655e3531 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:42:58 -0300 Subject: [PATCH 0031/5711] drm/i915: remove comment about HSW HDMI DIPs HSW support is now just like all the other generations: we send AVI and SPD InfoFrames. There are other DIPs for HSW, but there are other DIPs for the previous generations too. For each gen, we can see which DIPs are missing by looking at the 'set_infoframes' function: we explicitly disable the DIPs we're not using. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 194b453b052c..5cb1d100dc84 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -897,9 +897,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) intel_hdmi->write_infoframe = vlv_write_infoframe; intel_hdmi->set_infoframes = vlv_set_infoframes; } else if (IS_HASWELL(dev)) { - /* FIXME: Haswell has a new set of DIP frame registers, but we are - * just doing the minimal required for HDMI to work at this stage. - */ intel_hdmi->write_infoframe = hsw_write_infoframe; intel_hdmi->set_infoframes = hsw_set_infoframes; } else if (HAS_PCH_IBX(dev)) { -- GitLab From 9d9740f099f2eaf309c4c9cbc0d732507140db28 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:43:00 -0300 Subject: [PATCH 0032/5711] drm/i915: add some barriers when changing DIPs On IVB and older, we basically have two registers: the control and the data register. We write a few consecutitve times to the control register, and we need these writes to arrive exactly in the specified order. Also, when we're changing the data register, we need to guarantee that anything written to the control register already arrived (since changing the control register can change where the data register points to). Also, we need to make sure all the writes to the data register happen exactly in the specified order, and we also *can't* read the data register during this process, since reading and/or writing it will change the place it points to. So invoke the "better safe than sorry" rule and just be careful and put barriers everywhere :) On HSW we still have a control register that we write many times, but we have many data registers. Demanded-by: Chris Wilson Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 5cb1d100dc84..b507d38faa10 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -133,16 +133,19 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, I915_WRITE(VIDEO_DIP_CTL, val); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VIDEO_DIP_DATA, *data); data++; } + mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(VIDEO_DIP_CTL, val); + POSTING_READ(VIDEO_DIP_CTL); } static void ibx_write_infoframe(struct drm_encoder *encoder, @@ -165,16 +168,19 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, I915_WRITE(reg, val); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); + POSTING_READ(reg); } static void cpt_write_infoframe(struct drm_encoder *encoder, @@ -200,16 +206,19 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, I915_WRITE(reg, val); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); + POSTING_READ(reg); } static void vlv_write_infoframe(struct drm_encoder *encoder, @@ -232,16 +241,19 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, I915_WRITE(reg, val); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); + POSTING_READ(reg); } static void hsw_write_infoframe(struct drm_encoder *encoder, @@ -262,13 +274,16 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, val &= ~hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } + mmiowb(); val |= hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); + POSTING_READ(ctl_reg); } static void intel_set_infoframe(struct drm_encoder *encoder, @@ -335,6 +350,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, return; val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); + POSTING_READ(reg); return; } @@ -353,6 +369,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, if (val & VIDEO_DIP_ENABLE) { val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); + POSTING_READ(reg); } val &= ~VIDEO_DIP_PORT_MASK; val |= port; @@ -362,6 +379,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, val &= ~VIDEO_DIP_ENABLE_VENDOR; I915_WRITE(reg, val); + POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); @@ -385,6 +403,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, return; val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); + POSTING_READ(reg); return; } @@ -406,6 +425,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, if (val & VIDEO_DIP_ENABLE) { val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); + POSTING_READ(reg); } val &= ~VIDEO_DIP_PORT_MASK; val |= port; @@ -416,6 +436,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); + POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); @@ -438,6 +459,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, return; val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); I915_WRITE(reg, val); + POSTING_READ(reg); return; } @@ -447,6 +469,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); + POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); @@ -469,6 +492,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, return; val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); + POSTING_READ(reg); return; } @@ -477,6 +501,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); + POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); @@ -493,6 +518,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); + POSTING_READ(reg); return; } @@ -500,6 +526,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); I915_WRITE(reg, val); + POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); -- GitLab From e5153dc09c2be01670c6dce7ac6a454f23d5c2b6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 May 2012 17:15:45 +0200 Subject: [PATCH 0033/5711] drm/i915: there's no cxsr on ilk Already discovered in commit 5a117db77e47e3946d1aaa7ce8deafafd9d76746 Author: Eugeni Dodonov Date: Thu Jan 5 09:34:29 2012 -0200 drm/i915: there is no pipe CxSR on ironlake but we've failed to rip out the code from the ironlake specific code. Reviewed-by: Eugeni Dodonov Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c71850ddf20..83ae2c889ff7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4652,16 +4652,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds && has_reduced_clock && i915_powersave) { I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); intel_crtc->lowfreq_avail = true; - if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG_KMS("enabling CxSR downclocking\n"); - pipeconf |= PIPECONF_CXSR_DOWNCLOCK; - } } else { I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); - if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG_KMS("disabling CxSR downclocking\n"); - pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; - } } } -- GitLab From 61e9653f0d9a18a0ceecbc0acb93b3297fbb8196 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 May 2012 14:52:26 +0200 Subject: [PATCH 0034/5711] drm/i915: reuse the sdvo tv clock adjustment in ilk mode_set Jesse extracted this nice helper in his i9xx_crtc_mode_set refactor, but we have the identical code in ironlake_ccrtc_mode_set. And that function is huge, so extracting some code full of magic numbers is always nice. Noticed while trying to get a handle on our dp clock code. Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 83ae2c889ff7..1d801724c1db 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4395,25 +4395,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, &clock, &reduced_clock); } - /* SDVO TV has fixed PLL values depend on its clock range, - this mirrors vbios setting. */ - if (is_sdvo && is_tv) { - if (adjusted_mode->clock >= 100000 - && adjusted_mode->clock < 140500) { - clock.p1 = 2; - clock.p2 = 10; - clock.n = 3; - clock.m1 = 16; - clock.m2 = 8; - } else if (adjusted_mode->clock >= 140500 - && adjusted_mode->clock <= 200000) { - clock.p1 = 1; - clock.p2 = 10; - clock.n = 6; - clock.m1 = 12; - clock.m2 = 8; - } - } + + if (is_sdvo && is_tv) + i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); + /* FDI link */ pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); -- GitLab From 6c982376de3f81e046e380d27079b823acadf6ad Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 24 May 2012 21:26:49 +0200 Subject: [PATCH 0035/5711] drm/i915: s/mdelay/msleep/ in the sdvo detect function A 30 ms delay is simply way too big to waste cpu cycles on. Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a1840f44941b..ca3c6e128594 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1371,7 +1371,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) /* add 30ms delay when the output type might be TV */ if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) - mdelay(30); + msleep(30); if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) return connector_status_unknown; -- GitLab From e36891900855b3bed5d9cc9209655e6dfa435a5f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 25 May 2012 16:56:22 -0700 Subject: [PATCH 0036/5711] drm/i915: Dynamic Parity Detection handling On IVB hardware we are given an interrupt whenever a L3 parity error occurs in the L3 cache. The L3 cache is used by internal GPU clients only. This is a very rare occurrence (in fact to test this I need to use specially instrumented silicon). When a row in the L3 cache detects a parity error the HW generates an interrupt. The interrupt is masked in GTIMR until we get a chance to read some registers and alert userspace via a uevent. With this information userspace can use a sysfs interface (follow-up patch) to remap those rows. Way above my level of understanding, but if a given row fails, it is statistically more likely to fail again than a row which has not failed. Therefore it is desirable for an operating system to maintain a lifelong list of failing rows and always remap any bad rows on driver load. Hardware limits the number of rows that are remappable per bank/subbank, and should more than that many rows detect parity errors, software should maintain a list of the most frequent errors, and remap those rows. V2: Drop WARN_ON(IS_GEN6) (Jesse) DRM_DEBUG row/bank/subbank on errror (Jesse) Comment updates (Jesse) Reviewed-by: Jesse Barnes Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_irq.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 17 +++++++ 3 files changed, 105 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a17e31e91951..504f53ee2f8a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -816,6 +816,8 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; + + struct work_struct parity_error_work; } drm_i915_private_t; /* Iterate over initialised rings */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5134a62ff82f..c5266355973b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -398,6 +398,86 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_unlock(&dev_priv->dev->struct_mutex); } + +/** + * ivybridge_parity_work - Workqueue called when a parity error interrupt + * occurred. + * @work: workqueue struct + * + * Doesn't actually do anything except notify userspace. As a consequence of + * this event, userspace should try to remap the bad rows since statistically + * it is likely the same row is more likely to go bad again. + */ +static void ivybridge_parity_work(struct work_struct *work) +{ + drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, + parity_error_work); + u32 error_status, row, bank, subbank; + char *parity_event[5]; + uint32_t misccpctl; + unsigned long flags; + + /* We must turn off DOP level clock gating to access the L3 registers. + * In order to prevent a get/put style interface, acquire struct mutex + * any time we access those registers. + */ + mutex_lock(&dev_priv->dev->struct_mutex); + + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + POSTING_READ(GEN7_MISCCPCTL); + + error_status = I915_READ(GEN7_L3CDERRST1); + row = GEN7_PARITY_ERROR_ROW(error_status); + bank = GEN7_PARITY_ERROR_BANK(error_status); + subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); + + I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | + GEN7_L3CDERRST1_ENABLE); + POSTING_READ(GEN7_L3CDERRST1); + + I915_WRITE(GEN7_MISCCPCTL, misccpctl); + + spin_lock_irqsave(&dev_priv->irq_lock, flags); + dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + I915_WRITE(GTIMR, dev_priv->gt_irq_mask); + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); + + mutex_unlock(&dev_priv->dev->struct_mutex); + + parity_event[0] = "L3_PARITY_ERROR=1"; + parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); + parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); + parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); + parity_event[4] = NULL; + + kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, + KOBJ_CHANGE, parity_event); + + DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", + row, bank, subbank); + + kfree(parity_event[3]); + kfree(parity_event[2]); + kfree(parity_event[1]); +} + +void ivybridge_handle_parity_error(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long flags; + + if (!IS_IVYBRIDGE(dev)) + return; + + spin_lock_irqsave(&dev_priv->irq_lock, flags); + dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + I915_WRITE(GTIMR, dev_priv->gt_irq_mask); + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); + + queue_work(dev_priv->wq, &dev_priv->parity_error_work); +} + static void snb_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 gt_iir) @@ -417,6 +497,9 @@ static void snb_gt_irq_handler(struct drm_device *dev, DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); i915_handle_error(dev, false); } + + if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT) + ivybridge_handle_parity_error(dev); } static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, @@ -1641,6 +1724,9 @@ static void ironlake_irq_preinstall(struct drm_device *dev) atomic_set(&dev_priv->irq_received, 0); + if (IS_IVYBRIDGE(dev)) + INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); + I915_WRITE(HWSTAM, 0xeffe); /* XXX hotplug from PCH */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1855ac732718..2f31df0dde48 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4094,6 +4094,23 @@ #define GEN6_RC6 3 #define GEN6_RC7 4 +#define GEN7_MISCCPCTL (0x9424) +#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) + +/* IVYBRIDGE DPF */ +#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ +#define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) +#define GEN7_PARITY_ERROR_VALID (1<<13) +#define GEN7_L3CDERRST1_BANK_MASK (3<<11) +#define GEN7_L3CDERRST1_SUBBANK_MASK (7<<8) +#define GEN7_PARITY_ERROR_ROW(reg) \ + ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14) +#define GEN7_PARITY_ERROR_BANK(reg) \ + ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11) +#define GEN7_PARITY_ERROR_SUBBANK(reg) \ + ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) +#define GEN7_L3CDERRST1_ENABLE (1<<7) + #define G4X_AUD_VID_DID 0x62020 #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 -- GitLab From 15b9f80e008f584d1a3835bb5eba194080e4e750 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 25 May 2012 16:56:23 -0700 Subject: [PATCH 0037/5711] drm/i915: enable parity error interrupts The previous patch put all the code, and handlers in place. It should now be safe to enable the parity error interrupt. The parity error must be unmasked in both the GTIMR, and the CS IMR. Unfortunately, the docs aren't clear about this; nevertheless it's the truth. Reviewed-by: Jesse Barnes Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c5266355973b..4a457521d76e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1889,13 +1889,13 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) DE_PIPEA_VBLANK_IVB); POSTING_READ(DEIER); - dev_priv->gt_irq_mask = ~0; + dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIMR, dev_priv->gt_irq_mask); render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | - GEN6_BLITTER_USER_INTERRUPT; + GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIER, render_irqs); POSTING_READ(GTIER); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1df1694835a1..89a5e7f89d7a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -427,6 +427,9 @@ static int init_render_ring(struct intel_ring_buffer *ring) if (INTEL_INFO(dev)->gen >= 6) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); + if (IS_IVYBRIDGE(dev)) + I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + return ret; } @@ -814,7 +817,11 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); + if (IS_IVYBRIDGE(dev) && ring->id == RCS) + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | + GEN6_RENDER_L3_PARITY_ERROR)); + else + I915_WRITE_IMR(ring, ~ring->irq_enable_mask); dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -833,7 +840,10 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { - I915_WRITE_IMR(ring, ~0); + if (IS_IVYBRIDGE(dev) && ring->id == RCS) + I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + else + I915_WRITE_IMR(ring, ~0); dev_priv->gt_irq_mask |= ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); -- GitLab From b9524a1e1c48cf461768914345ec94be6a15e710 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 25 May 2012 16:56:24 -0700 Subject: [PATCH 0038/5711] drm/i915: remap l3 on hw init If any l3 rows have been previously remapped, we must remap them after GPU reset/resume too. v2: Just return (no warn) on remapping init if not IVB (Jesse) Move the check of schizo userspace to i915_gem_l3_remap (Jesse) Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_gem.c | 34 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 3 +++ 3 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 504f53ee2f8a..470c73219e6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -656,6 +656,8 @@ typedef struct drm_i915_private { /** PPGTT used for aliasing the PPGTT with the GTT */ struct i915_hw_ppgtt *aliasing_ppgtt; + u32 *l3_remap_info; + struct shrinker inactive_shrinker; /** @@ -1309,6 +1311,7 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); +void i915_gem_l3_remap(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_init_ppgtt(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d2eaa008573b..1c08e0900eff 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3527,6 +3527,38 @@ i915_gem_idle(struct drm_device *dev) return 0; } +void i915_gem_l3_remap(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 misccpctl; + int i; + + if (!IS_IVYBRIDGE(dev)) + return; + + if (!dev_priv->mm.l3_remap_info) + return; + + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + POSTING_READ(GEN7_MISCCPCTL); + + for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { + u32 remap = I915_READ(GEN7_L3LOG_BASE + i); + if (remap && remap != dev_priv->mm.l3_remap_info[i/4]) + DRM_DEBUG("0x%x was already programmed to %x\n", + GEN7_L3LOG_BASE + i, remap); + if (remap && !dev_priv->mm.l3_remap_info[i/4]) + DRM_DEBUG_DRIVER("Clearing remapped register\n"); + I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]); + } + + /* Make sure all the writes land before disabling dop clock gating */ + POSTING_READ(GEN7_L3LOG_BASE); + + I915_WRITE(GEN7_MISCCPCTL, misccpctl); +} + void i915_gem_init_swizzling(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -3616,6 +3648,8 @@ i915_gem_init_hw(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; int ret; + i915_gem_l3_remap(dev); + i915_gem_init_swizzling(dev); ret = intel_init_render_ring_buffer(dev); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f31df0dde48..7dcc04f2143e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4111,6 +4111,9 @@ ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) #define GEN7_L3CDERRST1_ENABLE (1<<7) +#define GEN7_L3LOG_BASE 0xB070 +#define GEN7_L3LOG_SIZE 0x80 + #define G4X_AUD_VID_DID 0x62020 #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 -- GitLab From 84bc758124127a5b16b30f9a8bf5f1a981affc6b Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 25 May 2012 16:56:25 -0700 Subject: [PATCH 0039/5711] drm/i915: l3 parity sysfs interface Dumb binary interfaces which allow root-only updates of the cache remapping registers. As mentioned in a previous patch, software using this interface needs to know about HW limits, and other programming considerations as the kernel interface does no checking for these things on the root-only interface. v1: Drop extra posting reads (Chris) Return negative values in the sysfs interfaces on errors (Chris) v2: Return -EINVAL for offset % 4 (Jesse) Move schizo userspace check out (Jesse) Cleaner sysfs item initializers (Daniel) Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_sysfs.c | 121 +++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 79f83445afa0..c2013273a4c6 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -29,6 +29,7 @@ #include #include #include +#include "intel_drv.h" #include "i915_drv.h" static u32 calc_residency(struct drm_device *dev, const u32 reg) @@ -92,20 +93,136 @@ static struct attribute_group rc6_attr_group = { .attrs = rc6_attrs }; +static int l3_access_valid(struct drm_device *dev, loff_t offset) +{ + if (!IS_IVYBRIDGE(dev)) + return -EPERM; + + if (offset % 4 != 0) + return -EINVAL; + + if (offset >= GEN7_L3LOG_SIZE) + return -ENXIO; + + return 0; +} + +static ssize_t +i915_l3_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); + struct drm_device *drm_dev = dminor->dev; + struct drm_i915_private *dev_priv = drm_dev->dev_private; + uint32_t misccpctl; + int i, ret; + + ret = l3_access_valid(drm_dev, offset); + if (ret) + return ret; + + ret = i915_mutex_lock_interruptible(drm_dev); + if (ret) + return ret; + + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + + for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) + *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i); + + I915_WRITE(GEN7_MISCCPCTL, misccpctl); + + mutex_unlock(&drm_dev->struct_mutex); + + return i - offset; +} + +static ssize_t +i915_l3_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); + struct drm_device *drm_dev = dminor->dev; + struct drm_i915_private *dev_priv = drm_dev->dev_private; + u32 *temp = NULL; /* Just here to make handling failures easy */ + int ret; + + ret = l3_access_valid(drm_dev, offset); + if (ret) + return ret; + + ret = i915_mutex_lock_interruptible(drm_dev); + if (ret) + return ret; + + if (!dev_priv->mm.l3_remap_info) { + temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); + if (!temp) { + mutex_unlock(&drm_dev->struct_mutex); + return -ENOMEM; + } + } + + ret = i915_gpu_idle(drm_dev); + if (ret) { + kfree(temp); + mutex_unlock(&drm_dev->struct_mutex); + return ret; + } + + /* TODO: Ideally we really want a GPU reset here to make sure errors + * aren't propagated. Since I cannot find a stable way to reset the GPU + * at this point it is left as a TODO. + */ + if (temp) + dev_priv->mm.l3_remap_info = temp; + + memcpy(dev_priv->mm.l3_remap_info + (offset/4), + buf + (offset/4), + count); + + i915_gem_l3_remap(drm_dev); + + mutex_unlock(&drm_dev->struct_mutex); + + return count; +} + +static struct bin_attribute dpf_attrs = { + .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, + .size = GEN7_L3LOG_SIZE, + .read = i915_l3_read, + .write = i915_l3_write, + .mmap = NULL +}; + void i915_setup_sysfs(struct drm_device *dev) { int ret; - /* ILK doesn't have any residency information */ + /* ILK and below don't yet have relevant sysfs files */ if (INTEL_INFO(dev)->gen < 6) return; ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); if (ret) - DRM_ERROR("sysfs setup failed\n"); + DRM_ERROR("RC6 residency sysfs setup failed\n"); + + if (!IS_IVYBRIDGE(dev)) + return; + + ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); + if (ret) + DRM_ERROR("l3 parity sysfs setup failed\n"); } void i915_teardown_sysfs(struct drm_device *dev) { + device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); } -- GitLab From 6faa68337b0c90923a1405ae9c196cee64921b7e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:51 -0500 Subject: [PATCH 0040/5711] slub: Use freelist instead of "object" in __slab_alloc The variable "object" really refers to a list of objects that we are handling. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 80848cd3901c..83f258298de7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2127,7 +2127,7 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { - void *object; + void *freelist; struct kmem_cache_cpu *c; struct page *page = new_slab(s, flags, node); @@ -2140,7 +2140,7 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * No other reference to the page yet so we can * muck around with it freely without cmpxchg */ - object = page->freelist; + freelist = page->freelist; page->freelist = NULL; stat(s, ALLOC_SLAB); @@ -2148,9 +2148,9 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, c->page = page; *pc = c; } else - object = NULL; + freelist = NULL; - return object; + return freelist; } /* @@ -2170,6 +2170,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) do { freelist = page->freelist; counters = page->counters; + new.counters = counters; VM_BUG_ON(!new.frozen); @@ -2203,7 +2204,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { - void **object; + void *freelist; unsigned long flags; local_irq_save(flags); @@ -2219,6 +2220,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, if (!c->page) goto new_slab; redo: + if (unlikely(!node_match(c, node))) { stat(s, ALLOC_NODE_MISMATCH); deactivate_slab(s, c); @@ -2226,15 +2228,15 @@ redo: } /* must check again c->freelist in case of cpu migration or IRQ */ - object = c->freelist; - if (object) + freelist = c->freelist; + if (freelist) goto load_freelist; stat(s, ALLOC_SLOWPATH); - object = get_freelist(s, c->page); + freelist = get_freelist(s, c->page); - if (!object) { + if (!freelist) { c->page = NULL; stat(s, DEACTIVATE_BYPASS); goto new_slab; @@ -2243,10 +2245,10 @@ redo: stat(s, ALLOC_REFILL); load_freelist: - c->freelist = get_freepointer(s, object); + c->freelist = get_freepointer(s, freelist); c->tid = next_tid(c->tid); local_irq_restore(flags); - return object; + return freelist; new_slab: @@ -2260,13 +2262,13 @@ new_slab: } /* Then do expensive stuff like retrieving pages from the partial lists */ - object = get_partial(s, gfpflags, node, c); + freelist = get_partial(s, gfpflags, node, c); - if (unlikely(!object)) { + if (unlikely(!freelist)) { - object = new_slab_objects(s, gfpflags, node, &c); + freelist = new_slab_objects(s, gfpflags, node, &c); - if (unlikely(!object)) { + if (unlikely(!freelist)) { if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) slab_out_of_memory(s, gfpflags, node); @@ -2279,14 +2281,14 @@ new_slab: goto load_freelist; /* Only entered in the debug case */ - if (!alloc_debug_processing(s, c->page, object, addr)) + if (!alloc_debug_processing(s, c->page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - c->freelist = get_freepointer(s, object); + c->freelist = get_freepointer(s, freelist); deactivate_slab(s, c); c->node = NUMA_NO_NODE; local_irq_restore(flags); - return object; + return freelist; } /* -- GitLab From 507effeaba29bf724dfe38317fbd11d0fe25fa40 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:52 -0500 Subject: [PATCH 0041/5711] slub: Add frozen check in __slab_alloc Verify that objects returned from __slab_alloc come from slab pages in the correct state. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/slub.c b/mm/slub.c index 83f258298de7..a3395c28f561 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2245,6 +2245,12 @@ redo: stat(s, ALLOC_REFILL); load_freelist: + /* + * freelist is pointing to the list of objects to be used. + * page is pointing to the page from which the objects are obtained. + * That page must be frozen for per cpu allocations to work. + */ + VM_BUG_ON(!c->page->frozen); c->freelist = get_freepointer(s, freelist); c->tid = next_tid(c->tid); local_irq_restore(flags); -- GitLab From 7ced3719719669ad6bd279b45fa3c1a517b2e057 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:53 -0500 Subject: [PATCH 0042/5711] slub: Acquire_slab() avoid loop Avoid the loop in acquire slab and simply fail if there is a conflict. This will cause the next page on the list to be considered. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index a3395c28f561..9892775349bf 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1490,12 +1490,12 @@ static inline void remove_partial(struct kmem_cache_node *n, } /* - * Lock slab, remove from the partial list and put the object into the - * per cpu freelist. + * Remove slab from the partial list, freeze it and + * return the pointer to the freelist. * * Returns a list of objects or NULL if it fails. * - * Must hold list_lock. + * Must hold list_lock since we modify the partial list. */ static inline void *acquire_slab(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page, @@ -1510,22 +1510,24 @@ static inline void *acquire_slab(struct kmem_cache *s, * The old freelist is the list of objects for the * per cpu allocation list. */ - do { - freelist = page->freelist; - counters = page->counters; - new.counters = counters; - if (mode) - new.inuse = page->objects; + freelist = page->freelist; + counters = page->counters; + new.counters = counters; + if (mode) + new.inuse = page->objects; - VM_BUG_ON(new.frozen); - new.frozen = 1; + VM_BUG_ON(new.frozen); + new.frozen = 1; - } while (!__cmpxchg_double_slab(s, page, + if (!__cmpxchg_double_slab(s, page, freelist, counters, NULL, new.counters, - "lock and freeze")); + "acquire_slab")) + + return NULL; remove_partial(n, page); + WARN_ON(!freelist); return freelist; } -- GitLab From f469743673ceda5181970eb6b8090ba728c956fb Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:54 -0500 Subject: [PATCH 0043/5711] slub: Simplify control flow in __slab_alloc() Simplify control flow a bit avoiding nesting. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 9892775349bf..5aacd434e2cb 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2272,17 +2272,15 @@ new_slab: /* Then do expensive stuff like retrieving pages from the partial lists */ freelist = get_partial(s, gfpflags, node, c); - if (unlikely(!freelist)) { - + if (!freelist) freelist = new_slab_objects(s, gfpflags, node, &c); - if (unlikely(!freelist)) { - if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) - slab_out_of_memory(s, gfpflags, node); + if (unlikely(!freelist)) { + if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) + slab_out_of_memory(s, gfpflags, node); - local_irq_restore(flags); - return NULL; - } + local_irq_restore(flags); + return NULL; } if (likely(!kmem_cache_debug(s))) -- GitLab From 188fd063208942a4681d8e8a4484ad0d4ae0fda1 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:55 -0500 Subject: [PATCH 0044/5711] slub: new_slab_objects() can also get objects from partial list Moving the attempt to get a slab page from the partial lists simplifies __slab_alloc which is rather complicated. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 5aacd434e2cb..b29246bc7392 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2130,9 +2130,15 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { void *freelist; - struct kmem_cache_cpu *c; - struct page *page = new_slab(s, flags, node); + struct kmem_cache_cpu *c = *pc; + struct page *page; + + freelist = get_partial(s, flags, node, c); + if (freelist) + return freelist; + + page = new_slab(s, flags, node); if (page) { c = __this_cpu_ptr(s->cpu_slab); if (c->page) @@ -2269,11 +2275,7 @@ new_slab: goto redo; } - /* Then do expensive stuff like retrieving pages from the partial lists */ - freelist = get_partial(s, gfpflags, node, c); - - if (!freelist) - freelist = new_slab_objects(s, gfpflags, node, &c); + freelist = new_slab_objects(s, gfpflags, node, &c); if (unlikely(!freelist)) { if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) -- GitLab From ec3ab083a7a004282ee374bdaeb0aa603521b8eb Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:56 -0500 Subject: [PATCH 0045/5711] slub: Get rid of the node field The node field is always page_to_nid(c->page). So its rather easy to replace. Note that there maybe slightly more overhead in various hot paths due to the need to shift the bits from page->flags. However, that is mostly compensated for by a smaller footprint of the kmem_cache_cpu structure (this patch reduces that to 3 words per cache) which allows better caching. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slub_def.h | 1 - mm/slub.c | 35 ++++++++++++++++------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index c2f8c8bc56ed..ebdcf4ba42ee 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -48,7 +48,6 @@ struct kmem_cache_cpu { unsigned long tid; /* Globally unique transaction id */ struct page *page; /* The slab from which we are allocating */ struct page *partial; /* Partially allocated frozen slabs */ - int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS unsigned stat[NR_SLUB_STAT_ITEMS]; #endif diff --git a/mm/slub.c b/mm/slub.c index b29246bc7392..aed879276410 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1561,7 +1561,6 @@ static void *get_partial_node(struct kmem_cache *s, if (!object) { c->page = page; - c->node = page_to_nid(page); stat(s, ALLOC_FROM_PARTIAL); object = t; available = page->objects - page->inuse; @@ -2057,7 +2056,7 @@ static void flush_all(struct kmem_cache *s) static inline int node_match(struct kmem_cache_cpu *c, int node) { #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE && c->node != node) + if (node != NUMA_NO_NODE && page_to_nid(c->page) != node) return 0; #endif return 1; @@ -2152,7 +2151,6 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, page->freelist = NULL; stat(s, ALLOC_SLAB); - c->node = page_to_nid(page); c->page = page; *pc = c; } else @@ -2269,7 +2267,6 @@ new_slab: if (c->partial) { c->page = c->partial; c->partial = c->page->next; - c->node = page_to_nid(c->page); stat(s, CPU_PARTIAL_ALLOC); c->freelist = NULL; goto redo; @@ -2294,7 +2291,6 @@ new_slab: c->freelist = get_freepointer(s, freelist); deactivate_slab(s, c); - c->node = NUMA_NO_NODE; local_irq_restore(flags); return freelist; } @@ -4507,30 +4503,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, for_each_possible_cpu(cpu) { struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); - int node = ACCESS_ONCE(c->node); + int node; struct page *page; - if (node < 0) - continue; page = ACCESS_ONCE(c->page); - if (page) { - if (flags & SO_TOTAL) - x = page->objects; - else if (flags & SO_OBJECTS) - x = page->inuse; - else - x = 1; + if (!page) + continue; - total += x; - nodes[node] += x; - } - page = c->partial; + node = page_to_nid(page); + if (flags & SO_TOTAL) + x = page->objects; + else if (flags & SO_OBJECTS) + x = page->inuse; + else + x = 1; + + total += x; + nodes[node] += x; + page = ACCESS_ONCE(c->partial); if (page) { x = page->pobjects; total += x; nodes[node] += x; } + per_cpu[node]++; } } -- GitLab From c17dda40a6a4ed95f035db38b7ba4fab0d99da44 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:57 -0500 Subject: [PATCH 0046/5711] slub: Separate out kmem_cache_cpu processing from deactivate_slab Processing on fields of kmem_cache_cpu is cleaner if code working on fields of this struct is taken out of deactivate_slab(). Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index aed879276410..2389a016577e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1729,14 +1729,12 @@ void init_kmem_cache_cpus(struct kmem_cache *s) /* * Remove the cpu slab */ -static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) +static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist) { enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; - struct page *page = c->page; struct kmem_cache_node *n = get_node(s, page_to_nid(page)); int lock = 0; enum slab_modes l = M_NONE, m = M_NONE; - void *freelist; void *nextfree; int tail = DEACTIVATE_TO_HEAD; struct page new; @@ -1747,11 +1745,6 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) tail = DEACTIVATE_TO_TAIL; } - c->tid = next_tid(c->tid); - c->page = NULL; - freelist = c->freelist; - c->freelist = NULL; - /* * Stage one: Free all available per cpu objects back * to the page freelist while it is still frozen. Leave the @@ -2009,7 +2002,11 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { stat(s, CPUSLAB_FLUSH); - deactivate_slab(s, c); + deactivate_slab(s, c->page, c->freelist); + + c->tid = next_tid(c->tid); + c->page = NULL; + c->freelist = NULL; } /* @@ -2229,7 +2226,9 @@ redo: if (unlikely(!node_match(c, node))) { stat(s, ALLOC_NODE_MISMATCH); - deactivate_slab(s, c); + deactivate_slab(s, c->page, c->freelist); + c->page = NULL; + c->freelist = NULL; goto new_slab; } @@ -2289,8 +2288,9 @@ new_slab: if (!alloc_debug_processing(s, c->page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - c->freelist = get_freepointer(s, freelist); - deactivate_slab(s, c); + deactivate_slab(s, c->page, get_freepointer(s, freelist)); + c->page = NULL; + c->freelist = NULL; local_irq_restore(flags); return freelist; } -- GitLab From f6e7def7f7d749759e4bf36dcc25ae289a20d868 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:58 -0500 Subject: [PATCH 0047/5711] slub: Use page variable instead of c->page. Store the value of c->page to avoid additional fetches from per cpu data. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 2389a016577e..6b60fc907a71 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2208,6 +2208,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { void *freelist; + struct page *page; unsigned long flags; local_irq_save(flags); @@ -2220,13 +2221,14 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, c = this_cpu_ptr(s->cpu_slab); #endif - if (!c->page) + page = c->page; + if (!page) goto new_slab; redo: if (unlikely(!node_match(c, node))) { stat(s, ALLOC_NODE_MISMATCH); - deactivate_slab(s, c->page, c->freelist); + deactivate_slab(s, page, c->freelist); c->page = NULL; c->freelist = NULL; goto new_slab; @@ -2239,7 +2241,7 @@ redo: stat(s, ALLOC_SLOWPATH); - freelist = get_freelist(s, c->page); + freelist = get_freelist(s, page); if (!freelist) { c->page = NULL; @@ -2264,8 +2266,8 @@ load_freelist: new_slab: if (c->partial) { - c->page = c->partial; - c->partial = c->page->next; + page = c->page = c->partial; + c->partial = page->next; stat(s, CPU_PARTIAL_ALLOC); c->freelist = NULL; goto redo; @@ -2281,14 +2283,15 @@ new_slab: return NULL; } + page = c->page; if (likely(!kmem_cache_debug(s))) goto load_freelist; /* Only entered in the debug case */ - if (!alloc_debug_processing(s, c->page, freelist, addr)) + if (!alloc_debug_processing(s, page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - deactivate_slab(s, c->page, get_freepointer(s, freelist)); + deactivate_slab(s, page, get_freepointer(s, freelist)); c->page = NULL; c->freelist = NULL; local_irq_restore(flags); -- GitLab From 57d437d2aa680f42d75cef45205834d5f605550a Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2012 10:09:59 -0500 Subject: [PATCH 0048/5711] slub: pass page to node_match() instead of kmem_cache_cpu structure Avoid passing the kmem_cache_cpu pointer to node_match. This makes the node_match function more generic and easier to understand. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 6b60fc907a71..719509eaa467 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2050,10 +2050,10 @@ static void flush_all(struct kmem_cache *s) * Check if the objects in a per cpu structure fit numa * locality expectations. */ -static inline int node_match(struct kmem_cache_cpu *c, int node) +static inline int node_match(struct page *page, int node) { #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE && page_to_nid(c->page) != node) + if (node != NUMA_NO_NODE && page_to_nid(page) != node) return 0; #endif return 1; @@ -2226,7 +2226,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, goto new_slab; redo: - if (unlikely(!node_match(c, node))) { + if (unlikely(!node_match(page, node))) { stat(s, ALLOC_NODE_MISMATCH); deactivate_slab(s, page, c->freelist); c->page = NULL; @@ -2313,6 +2313,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, { void **object; struct kmem_cache_cpu *c; + struct page *page; unsigned long tid; if (slab_pre_alloc_hook(s, gfpflags)) @@ -2338,7 +2339,8 @@ redo: barrier(); object = c->freelist; - if (unlikely(!object || !node_match(c, node))) + page = c->page; + if (unlikely(!object || !node_match(page, node))) object = __slab_alloc(s, gfpflags, node, addr, c); -- GitLab From d2ba8470ccfc90e0966c802632f8bb552f11143a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 31 May 2012 14:57:41 +0200 Subject: [PATCH 0049/5711] drm/i915: ivybridge_handle_parity_error should be static Notice by Fengguang Wu's automatic sparse checker. Reported-by: Fengguang Wu Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4a457521d76e..53356f44aba3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -462,7 +462,7 @@ static void ivybridge_parity_work(struct work_struct *work) kfree(parity_event[1]); } -void ivybridge_handle_parity_error(struct drm_device *dev) +static void ivybridge_handle_parity_error(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long flags; -- GitLab From 98fd81cd64674545a30a4f95388f086a626d37d2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 31 May 2012 14:57:42 +0200 Subject: [PATCH 0050/5711] drm/i915: initialize the parity work only once This fixes an (albeit really hard to hit) race resulting in an oops: - The parity work get scheduled. - We re-init the irq state and call INIT_WORK again. - The workqueue code tries to run the work item and stumbles over a work item that should be on it's runlist. Also initiliaze the work item unconditionally like all the others, it's simpler. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 53356f44aba3..6553dcc2ca79 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1723,10 +1723,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev) atomic_set(&dev_priv->irq_received, 0); - - if (IS_IVYBRIDGE(dev)) - INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); - I915_WRITE(HWSTAM, 0xeffe); /* XXX hotplug from PCH */ @@ -2647,6 +2643,7 @@ void intel_irq_init(struct drm_device *dev) INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); + INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ -- GitLab From 112abd291db7d47974f166e742104d761bc76977 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 31 May 2012 14:57:43 +0200 Subject: [PATCH 0051/5711] drm/i915: simplify sysfs setup code Positively checking for the required feature/gen is simpler than build a cascade of negative "we need to bail" checks. And the later won't scale if we add more stuff that doesn't fit in nicely. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_sysfs.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index c2013273a4c6..2f5388af8df9 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -205,20 +205,18 @@ void i915_setup_sysfs(struct drm_device *dev) { int ret; - /* ILK and below don't yet have relevant sysfs files */ - if (INTEL_INFO(dev)->gen < 6) - return; - - ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); - if (ret) - DRM_ERROR("RC6 residency sysfs setup failed\n"); - - if (!IS_IVYBRIDGE(dev)) - return; + if (INTEL_INFO(dev)->gen >= 6) { + ret = sysfs_merge_group(&dev->primary->kdev.kobj, + &rc6_attr_group); + if (ret) + DRM_ERROR("RC6 residency sysfs setup failed\n"); + } - ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); - if (ret) - DRM_ERROR("l3 parity sysfs setup failed\n"); + if (IS_IVYBRIDGE(dev)) { + ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); + if (ret) + DRM_ERROR("l3 parity sysfs setup failed\n"); + } } void i915_teardown_sysfs(struct drm_device *dev) -- GitLab From 28c0254ede13ab575d2df5c6585ed3d4817c3e6b Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 28 May 2012 14:44:30 +0800 Subject: [PATCH 0052/5711] ceph: check PG_Private flag before accessing page->private I got lots of NULL pointer dereference Oops when compiling kernel on ceph. The bug is because the kernel page migration routine replaces some pages in the page cache with new pages, these new pages' private can be non-zero. Signed-off-by: Zheng Yan Signed-off-by: Sage Weil --- fs/ceph/addr.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 173b1d22e59b..8b67304e4b80 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -54,7 +54,12 @@ (CONGESTION_ON_THRESH(congestion_kb) - \ (CONGESTION_ON_THRESH(congestion_kb) >> 2)) - +static inline struct ceph_snap_context *page_snap_context(struct page *page) +{ + if (PagePrivate(page)) + return (void *)page->private; + return NULL; +} /* * Dirty a page. Optimistically adjust accounting, on the assumption @@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct page *page, unsigned long offset) { struct inode *inode; struct ceph_inode_info *ci; - struct ceph_snap_context *snapc = (void *)page->private; + struct ceph_snap_context *snapc = page_snap_context(page); BUG_ON(!PageLocked(page)); - BUG_ON(!page->private); BUG_ON(!PagePrivate(page)); BUG_ON(!page->mapping); @@ -182,7 +186,6 @@ static int ceph_releasepage(struct page *page, gfp_t g) struct inode *inode = page->mapping ? page->mapping->host : NULL; dout("%p releasepage %p idx %lu\n", inode, page, page->index); WARN_ON(PageDirty(page)); - WARN_ON(page->private); WARN_ON(PagePrivate(page)); return 0; } @@ -443,7 +446,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) osdc = &fsc->client->osdc; /* verify this is a writeable snap context */ - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc == NULL) { dout("writepage %p page %p not dirty?\n", inode, page); goto out; @@ -451,7 +454,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) oldest = get_oldest_context(inode, &snap_size); if (snapc->seq > oldest->seq) { dout("writepage %p page %p snapc %p not writeable - noop\n", - inode, page, (void *)page->private); + inode, page, snapc); /* we should only noop if called by kswapd */ WARN_ON((current->flags & PF_MEMALLOC) == 0); ceph_put_snap_context(oldest); @@ -591,7 +594,7 @@ static void writepages_finish(struct ceph_osd_request *req, clear_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC); - ceph_put_snap_context((void *)page->private); + ceph_put_snap_context(page_snap_context(page)); page->private = 0; ClearPagePrivate(page); dout("unlocking %d %p\n", i, page); @@ -795,7 +798,7 @@ get_more_pages: } /* only if matching snap context */ - pgsnapc = (void *)page->private; + pgsnapc = page_snap_context(page); if (pgsnapc->seq > snapc->seq) { dout("page snapc %p %lld > oldest %p %lld\n", pgsnapc, pgsnapc->seq, snapc, snapc->seq); @@ -984,7 +987,7 @@ retry_locked: BUG_ON(!ci->i_snap_realm); down_read(&mdsc->snap_rwsem); BUG_ON(!ci->i_snap_realm->cached_context); - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc && snapc != ci->i_head_snapc) { /* * this page is already dirty in another (older) snap -- GitLab From e5e372da9a469dfe3ece40277090a7056c566838 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 0053/5711] libceph: eliminate connection state "DEAD" The ceph connection state "DEAD" is never set and is therefore not needed. Eliminate it. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh --- include/linux/ceph/messenger.h | 1 - net/ceph/messenger.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 2521a95fa6d9..aa506cadea67 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -119,7 +119,6 @@ struct ceph_msg_pos { #define CLOSED 10 /* we've closed the connection */ #define SOCK_CLOSED 11 /* socket state changed to closed */ #define OPENING 13 /* open connection w/ (possibly new) peer */ -#define DEAD 14 /* dead, about to kfree */ #define BACKOFF 15 /* diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1a80907282cc..42ca8aab6dcf 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2087,12 +2087,6 @@ bad_tag: */ static void queue_con(struct ceph_connection *con) { - if (test_bit(DEAD, &con->state)) { - dout("queue_con %p ignoring: DEAD\n", - con); - return; - } - if (!con->ops->get(con)) { dout("queue_con %p ref count 0\n", con); return; -- GitLab From 6384bb8b8e88a9c6bf2ae0d9517c2c0199177c34 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 29 May 2012 21:47:38 -0500 Subject: [PATCH 0054/5711] libceph: kill bad_proto ceph connection op No code sets a bad_proto method in its ceph connection operations vector, so just get rid of it. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh --- include/linux/ceph/messenger.h | 3 --- net/ceph/messenger.c | 5 ----- 2 files changed, 8 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index aa506cadea67..74f6c9bd8074 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -31,9 +31,6 @@ struct ceph_connection_operations { int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*invalidate_authorizer)(struct ceph_connection *con); - /* protocol version mismatch */ - void (*bad_proto) (struct ceph_connection *con); - /* there was some error on the socket (disconnect, whatever) */ void (*fault) (struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 42ca8aab6dcf..07af9948e3f7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1356,11 +1356,6 @@ static void fail_protocol(struct ceph_connection *con) { reset_connection(con); set_bit(CLOSED, &con->state); /* in case there's queued work */ - - mutex_unlock(&con->mutex); - if (con->ops->bad_proto) - con->ops->bad_proto(con); - mutex_lock(&con->mutex); } static int process_connect(struct ceph_connection *con) -- GitLab From 327800bdc2cb9b71f4b458ca07aa9d522668dde0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 0055/5711] libceph: rename socket callbacks Change the names of the three socket callback functions to make it more obvious they're specifically associated with a connection's socket (not the ceph connection that uses it). Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil --- net/ceph/messenger.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 07af9948e3f7..545255823de2 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -153,46 +153,46 @@ EXPORT_SYMBOL(ceph_msgr_flush); */ /* data available on socket, or listen socket received a connect */ -static void ceph_data_ready(struct sock *sk, int count_unused) +static void ceph_sock_data_ready(struct sock *sk, int count_unused) { struct ceph_connection *con = sk->sk_user_data; if (sk->sk_state != TCP_CLOSE_WAIT) { - dout("ceph_data_ready on %p state = %lu, queueing work\n", + dout("%s on %p state = %lu, queueing work\n", __func__, con, con->state); queue_con(con); } } /* socket has buffer space for writing */ -static void ceph_write_space(struct sock *sk) +static void ceph_sock_write_space(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; /* only queue to workqueue if there is data we want to write, * and there is sufficient space in the socket buffer to accept - * more data. clear SOCK_NOSPACE so that ceph_write_space() + * more data. clear SOCK_NOSPACE so that ceph_sock_write_space() * doesn't get called again until try_write() fills the socket * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ if (test_bit(WRITE_PENDING, &con->state)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { - dout("ceph_write_space %p queueing write work\n", con); + dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); queue_con(con); } } else { - dout("ceph_write_space %p nothing to write\n", con); + dout("%s %p nothing to write\n", __func__, con); } } /* socket's state has changed */ -static void ceph_state_change(struct sock *sk) +static void ceph_sock_state_change(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; - dout("ceph_state_change %p state = %lu sk_state = %u\n", + dout("%s %p state = %lu sk_state = %u\n", __func__, con, con->state, sk->sk_state); if (test_bit(CLOSED, &con->state)) @@ -200,9 +200,9 @@ static void ceph_state_change(struct sock *sk) switch (sk->sk_state) { case TCP_CLOSE: - dout("ceph_state_change TCP_CLOSE\n"); + dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: - dout("ceph_state_change TCP_CLOSE_WAIT\n"); + dout("%s TCP_CLOSE_WAIT\n", __func__); if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; @@ -212,7 +212,7 @@ static void ceph_state_change(struct sock *sk) } break; case TCP_ESTABLISHED: - dout("ceph_state_change TCP_ESTABLISHED\n"); + dout("%s TCP_ESTABLISHED\n", __func__); queue_con(con); break; default: /* Everything else is uninteresting */ @@ -228,9 +228,9 @@ static void set_sock_callbacks(struct socket *sock, { struct sock *sk = sock->sk; sk->sk_user_data = con; - sk->sk_data_ready = ceph_data_ready; - sk->sk_write_space = ceph_write_space; - sk->sk_state_change = ceph_state_change; + sk->sk_data_ready = ceph_sock_data_ready; + sk->sk_write_space = ceph_sock_write_space; + sk->sk_state_change = ceph_sock_state_change; } -- GitLab From e22004235a900213625acd6583ac913d5a30c155 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 0056/5711] libceph: rename kvec_reset and kvec_add functions The functions ceph_con_out_kvec_reset() and ceph_con_out_kvec_add() are entirely private functions, so drop the "ceph_" prefix in their name to make them slightly more wieldy. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil --- net/ceph/messenger.c | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 545255823de2..2ca491fc50e2 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -486,14 +486,14 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) return ret; } -static void ceph_con_out_kvec_reset(struct ceph_connection *con) +static void con_out_kvec_reset(struct ceph_connection *con) { con->out_kvec_left = 0; con->out_kvec_bytes = 0; con->out_kvec_cur = &con->out_kvec[0]; } -static void ceph_con_out_kvec_add(struct ceph_connection *con, +static void con_out_kvec_add(struct ceph_connection *con, size_t size, void *data) { int index; @@ -534,7 +534,7 @@ static void prepare_write_message(struct ceph_connection *con) struct ceph_msg *m; u32 crc; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); con->out_kvec_is_msg = true; con->out_msg_done = false; @@ -542,9 +542,9 @@ static void prepare_write_message(struct ceph_connection *con) * TCP packet that's a good thing. */ if (con->in_seq > con->in_seq_acked) { con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); } @@ -572,12 +572,12 @@ static void prepare_write_message(struct ceph_connection *con) BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); /* tag + hdr + front + middle */ - ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); - ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); - ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); + con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); + con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); + con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); if (m->middle) - ceph_con_out_kvec_add(con, m->middle->vec.iov_len, + con_out_kvec_add(con, m->middle->vec.iov_len, m->middle->vec.iov_base); /* fill in crc (except data pages), footer */ @@ -626,12 +626,12 @@ static void prepare_write_ack(struct ceph_connection *con) con->in_seq_acked, con->in_seq); con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ @@ -644,8 +644,8 @@ static void prepare_write_ack(struct ceph_connection *con) static void prepare_write_keepalive(struct ceph_connection *con) { dout("prepare_write_keepalive %p\n", con); - ceph_con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); + con_out_kvec_reset(con); + con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); set_bit(WRITE_PENDING, &con->state); } @@ -690,8 +690,8 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection */ static void prepare_write_banner(struct ceph_connection *con) { - ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); - ceph_con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), + con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); + con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), &con->msgr->my_enc_addr); con->out_more = 0; @@ -738,10 +738,10 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; - ceph_con_out_kvec_add(con, sizeof (con->out_connect), + con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) - ceph_con_out_kvec_add(con, auth->authorizer_buf_len, + con_out_kvec_add(con, auth->authorizer_buf_len, auth->authorizer_buf); con->out_more = 0; @@ -935,7 +935,7 @@ static int write_partial_msg_pages(struct ceph_connection *con) /* prepare and queue up footer, too */ if (!do_datacrc) con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); prepare_write_message_footer(con); ret = 1; out: @@ -1398,7 +1398,7 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1419,7 +1419,7 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1445,7 +1445,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1462,7 +1462,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1869,7 +1869,7 @@ more: /* open the socket first? */ if (con->sock == NULL) { - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); prepare_write_banner(con); ret = prepare_write_connect(con); if (ret < 0) -- GitLab From 15d9882c336db2db73ccf9871ae2398e452f694c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 0057/5711] libceph: embed ceph messenger structure in ceph_client A ceph client has a pointer to a ceph messenger structure in it. There is always exactly one ceph messenger for a ceph client, so there is no need to allocate it separate from the ceph client structure. Switch the ceph_client structure to embed its ceph_messenger structure. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil --- fs/ceph/mds_client.c | 2 +- include/linux/ceph/libceph.h | 2 +- include/linux/ceph/messenger.h | 9 +++++---- net/ceph/ceph_common.c | 18 +++++------------- net/ceph/messenger.c | 30 +++++++++--------------------- net/ceph/mon_client.c | 6 +++--- net/ceph/osd_client.c | 4 ++-- 7 files changed, 26 insertions(+), 45 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 200bc87eceb1..ad30261cd4c0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,7 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(mdsc->fsc->client->msgr, &s->s_con); + ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con); s->s_con.private = s; s->s_con.ops = &mds_con_ops; s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 92eef7c3d3c5..927361c4b0a8 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -131,7 +131,7 @@ struct ceph_client { u32 supported_features; u32 required_features; - struct ceph_messenger *msgr; /* messenger instance */ + struct ceph_messenger msgr; /* messenger instance */ struct ceph_mon_client monc; struct ceph_osd_client osdc; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 74f6c9bd8074..3fbd4be804ed 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -211,10 +211,11 @@ extern int ceph_msgr_init(void); extern void ceph_msgr_exit(void); extern void ceph_msgr_flush(void); -extern struct ceph_messenger *ceph_messenger_create( - struct ceph_entity_addr *myaddr, - u32 features, u32 required); -extern void ceph_messenger_destroy(struct ceph_messenger *); +extern void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc); extern void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con); diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cc913193d992..2de3ea1bbd64 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -468,19 +468,15 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, /* msgr */ if (ceph_test_opt(client, MYIP)) myaddr = &client->options->my_addr; - client->msgr = ceph_messenger_create(myaddr, - client->supported_features, - client->required_features); - if (IS_ERR(client->msgr)) { - err = PTR_ERR(client->msgr); - goto fail; - } - client->msgr->nocrc = ceph_test_opt(client, NOCRC); + ceph_messenger_init(&client->msgr, myaddr, + client->supported_features, + client->required_features, + ceph_test_opt(client, NOCRC)); /* subsystems */ err = ceph_monc_init(&client->monc, client); if (err < 0) - goto fail_msgr; + goto fail; err = ceph_osdc_init(&client->osdc, client); if (err < 0) goto fail_monc; @@ -489,8 +485,6 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, fail_monc: ceph_monc_stop(&client->monc); -fail_msgr: - ceph_messenger_destroy(client->msgr); fail: kfree(client); return ERR_PTR(err); @@ -515,8 +509,6 @@ void ceph_destroy_client(struct ceph_client *client) ceph_debugfs_client_cleanup(client); - ceph_messenger_destroy(client->msgr); - ceph_destroy_options(client->options); kfree(client); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 2ca491fc50e2..d8423a3f6698 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2245,18 +2245,14 @@ out: /* - * create a new messenger instance + * initialize a new messenger instance */ -struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, - u32 supported_features, - u32 required_features) +void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc) { - struct ceph_messenger *msgr; - - msgr = kzalloc(sizeof(*msgr), GFP_KERNEL); - if (msgr == NULL) - return ERR_PTR(-ENOMEM); - msgr->supported_features = supported_features; msgr->required_features = required_features; @@ -2269,19 +2265,11 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, msgr->inst.addr.type = 0; get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce)); encode_my_addr(msgr); + msgr->nocrc = nocrc; - dout("messenger_create %p\n", msgr); - return msgr; -} -EXPORT_SYMBOL(ceph_messenger_create); - -void ceph_messenger_destroy(struct ceph_messenger *msgr) -{ - dout("destroy %p\n", msgr); - kfree(msgr); - dout("destroyed messenger %p\n", msgr); + dout("%s %p\n", __func__, msgr); } -EXPORT_SYMBOL(ceph_messenger_destroy); +EXPORT_SYMBOL(ceph_messenger_init); static void clear_standby(struct ceph_connection *con) { diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1845cde26227..704dc95dc620 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -763,7 +763,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); if (!monc->con) goto out_monmap; - ceph_con_init(monc->client->msgr, monc->con); + ceph_con_init(&monc->client->msgr, monc->con); monc->con->private = monc; monc->con->ops = &mon_con_ops; @@ -880,8 +880,8 @@ static void handle_auth_reply(struct ceph_mon_client *monc, } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { dout("authenticated, starting session\n"); - monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; - monc->client->msgr->inst.name.num = + monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT; + monc->client->msgr.inst.name.num = cpu_to_le64(monc->auth->global_id); __send_subscribe(monc); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b098e7b591f0..cca4c7f1c780 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -639,7 +639,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(osdc->client->msgr, &osd->o_con); + ceph_con_init(&osdc->client->msgr, &osd->o_con); osd->o_con.private = osd; osd->o_con.ops = &osd_con_ops; osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; @@ -1391,7 +1391,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) epoch, maplen); newmap = osdmap_apply_incremental(&p, next, osdc->osdmap, - osdc->client->msgr); + &osdc->client->msgr); if (IS_ERR(newmap)) { err = PTR_ERR(newmap); goto bad; -- GitLab From 928443cd9644e7cfd46f687dbeffda2d1a357ff9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 0058/5711] libceph: start separating connection flags from state A ceph_connection holds a mixture of connection state (as in "state machine" state) and connection flags in a single "state" field. To make the distinction more clear, define a new "flags" field and use it rather than the "state" field to hold Boolean flag values. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 18 ++++++++---- net/ceph/messenger.c | 50 +++++++++++++++++----------------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 3fbd4be804ed..920235e114ad 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -103,20 +103,25 @@ struct ceph_msg_pos { #define MAX_DELAY_INTERVAL (5 * 60 * HZ) /* - * ceph_connection state bit flags + * ceph_connection flag bits */ + #define LOSSYTX 0 /* we can close channel or drop messages on errors */ -#define CONNECTING 1 -#define NEGOTIATING 2 #define KEEPALIVE_PENDING 3 #define WRITE_PENDING 4 /* we have data ready to send */ +#define SOCK_CLOSED 11 /* socket state changed to closed */ +#define BACKOFF 15 + +/* + * ceph_connection states + */ +#define CONNECTING 1 +#define NEGOTIATING 2 #define STANDBY 8 /* no outgoing messages, socket closed. we keep * the ceph_connection around to maintain shared * state with the peer. */ #define CLOSED 10 /* we've closed the connection */ -#define SOCK_CLOSED 11 /* socket state changed to closed */ #define OPENING 13 /* open connection w/ (possibly new) peer */ -#define BACKOFF 15 /* * A single connection with another host. @@ -133,7 +138,8 @@ struct ceph_connection { struct ceph_messenger *msgr; struct socket *sock; - unsigned long state; /* connection state (see flags above) */ + unsigned long flags; + unsigned long state; const char *error_msg; /* error message, if any */ struct ceph_entity_addr peer_addr; /* peer address */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index d8423a3f6698..e84e4fd86bb7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -176,7 +176,7 @@ static void ceph_sock_write_space(struct sock *sk) * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ - if (test_bit(WRITE_PENDING, &con->state)) { + if (test_bit(WRITE_PENDING, &con->flags)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); @@ -203,7 +203,7 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); - if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { + if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; else @@ -395,9 +395,9 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); set_bit(CLOSED, &con->state); /* in case there's queued work */ clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ - clear_bit(LOSSYTX, &con->state); /* so we retry next connect */ - clear_bit(KEEPALIVE_PENDING, &con->state); - clear_bit(WRITE_PENDING, &con->state); + clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ + clear_bit(KEEPALIVE_PENDING, &con->flags); + clear_bit(WRITE_PENDING, &con->flags); mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; @@ -614,7 +614,7 @@ static void prepare_write_message(struct ceph_connection *con) prepare_write_message_footer(con); } - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -635,7 +635,7 @@ static void prepare_write_ack(struct ceph_connection *con) &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -646,7 +646,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) dout("prepare_write_keepalive %p\n", con); con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -675,7 +675,7 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection if (IS_ERR(auth)) return auth; - if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) + if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags)) return ERR_PTR(-EAGAIN); con->auth_reply_buf = auth->authorizer_reply_buf; @@ -695,7 +695,7 @@ static void prepare_write_banner(struct ceph_connection *con) &con->msgr->my_enc_addr); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } static int prepare_write_connect(struct ceph_connection *con) @@ -745,7 +745,7 @@ static int prepare_write_connect(struct ceph_connection *con) auth->authorizer_buf); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); return 0; } @@ -1492,7 +1492,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.connect_seq)); if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) - set_bit(LOSSYTX, &con->state); + set_bit(LOSSYTX, &con->flags); prepare_read_tag(con); break; @@ -1933,14 +1933,14 @@ do_next: prepare_write_ack(con); goto more; } - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) { + if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) { prepare_write_keepalive(con); goto more; } } /* Nothing to do! */ - clear_bit(WRITE_PENDING, &con->state); + clear_bit(WRITE_PENDING, &con->flags); dout("try_write nothing else to write.\n"); ret = 0; out: @@ -2106,7 +2106,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(BACKOFF, &con->state)) { + if (test_and_clear_bit(BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, round_jiffies_relative(con->delay))) { @@ -2135,7 +2135,7 @@ restart: con_close_socket(con); } - if (test_and_clear_bit(SOCK_CLOSED, &con->state)) + if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) goto fault; ret = try_read(con); @@ -2174,7 +2174,7 @@ static void ceph_fault(struct ceph_connection *con) dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(LOSSYTX, &con->state)) { + if (test_bit(LOSSYTX, &con->flags)) { dout("fault on LOSSYTX channel\n"); goto out; } @@ -2196,9 +2196,9 @@ static void ceph_fault(struct ceph_connection *con) /* If there are no messages queued or keepalive pending, place * the connection in a STANDBY state */ if (list_empty(&con->out_queue) && - !test_bit(KEEPALIVE_PENDING, &con->state)) { + !test_bit(KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); - clear_bit(WRITE_PENDING, &con->state); + clear_bit(WRITE_PENDING, &con->flags); set_bit(STANDBY, &con->state); } else { /* retry after a delay. */ @@ -2222,7 +2222,7 @@ static void ceph_fault(struct ceph_connection *con) * that when con_work restarts we schedule the * delay then. */ - set_bit(BACKOFF, &con->state); + set_bit(BACKOFF, &con->flags); } } @@ -2278,8 +2278,8 @@ static void clear_standby(struct ceph_connection *con) mutex_lock(&con->mutex); dout("clear_standby %p and ++connect_seq\n", con); con->connect_seq++; - WARN_ON(test_bit(WRITE_PENDING, &con->state)); - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state)); + WARN_ON(test_bit(WRITE_PENDING, &con->flags)); + WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); mutex_unlock(&con->mutex); } } @@ -2317,7 +2317,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* if there wasn't anything waiting to send before, queue * new work */ clear_standby(con); - if (test_and_set_bit(WRITE_PENDING, &con->state) == 0) + if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_send); @@ -2384,8 +2384,8 @@ void ceph_con_keepalive(struct ceph_connection *con) { dout("con_keepalive %p\n", con); clear_standby(con); - if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 && - test_and_set_bit(WRITE_PENDING, &con->state) == 0) + if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && + test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_keepalive); -- GitLab From ce2c8903e76e690846a00a0284e4bd9ee954d680 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 22:15:49 -0500 Subject: [PATCH 0059/5711] libceph: start tracking connection socket state Start explicitly keeping track of the state of a ceph connection's socket, separate from the state of the connection itself. Create placeholder functions to encapsulate the state transitions. -------- | NEW* | transient initial state -------- | con_sock_state_init() v ---------- | CLOSED | initialized, but no socket (and no ---------- TCP connection) ^ \ | \ con_sock_state_connecting() | ---------------------- | \ + con_sock_state_closed() \ |\ \ | \ \ | ----------- \ | | CLOSING | socket event; \ | ----------- await close \ | ^ | | | | | + con_sock_state_closing() | | / \ | | / --------------- | | / \ v | / -------------- | / -----------------| CONNECTING | socket created, TCP | | / -------------- connect initiated | | | con_sock_state_connected() | | v ------------- | CONNECTED | TCP connection established ------------- Make the socket state an atomic variable, reinforcing that it's a distinct transtion with no possible "intermediate/both" states. This is almost certainly overkill at this point, though the transitions into CONNECTED and CLOSING state do get called via socket callback (the rest of the transitions occur with the connection mutex held). We can back out the atomicity later. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 8 +++-- net/ceph/messenger.c | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 920235e114ad..5e852f444f68 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -137,14 +137,18 @@ struct ceph_connection { const struct ceph_connection_operations *ops; struct ceph_messenger *msgr; + + atomic_t sock_state; struct socket *sock; + struct ceph_entity_addr peer_addr; /* peer address */ + struct ceph_entity_addr peer_addr_for_me; + unsigned long flags; unsigned long state; const char *error_msg; /* error message, if any */ - struct ceph_entity_addr peer_addr; /* peer address */ struct ceph_entity_name peer_name; /* peer name */ - struct ceph_entity_addr peer_addr_for_me; + unsigned peer_features; u32 connect_seq; /* identify the most recent connection attempt for this connection, client */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e84e4fd86bb7..a4ac3deec161 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -29,6 +29,14 @@ * the sender. */ +/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */ + +#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ +#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ +#define CON_SOCK_STATE_CONNECTING 2 /* -> CONNECTED or -> CLOSING */ +#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ +#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ + /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; static char tag_ack = CEPH_MSGR_TAG_ACK; @@ -147,6 +155,55 @@ void ceph_msgr_flush(void) } EXPORT_SYMBOL(ceph_msgr_flush); +/* Connection socket state transition functions */ + +static void con_sock_state_init(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_connecting(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); + if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_connected(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_closing(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSING); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_closed(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} /* * socket callback functions @@ -203,6 +260,7 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); + con_sock_state_closing(con); if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; @@ -213,6 +271,7 @@ static void ceph_sock_state_change(struct sock *sk) break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); + con_sock_state_connected(con); queue_con(con); break; default: /* Everything else is uninteresting */ @@ -277,6 +336,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } con->sock = sock; + con_sock_state_connecting(con); return 0; } @@ -343,6 +403,7 @@ static int con_close_socket(struct ceph_connection *con) sock_release(con->sock); con->sock = NULL; clear_bit(SOCK_CLOSED, &con->state); + con_sock_state_closed(con); return rc; } @@ -462,6 +523,9 @@ void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) memset(con, 0, sizeof(*con)); atomic_set(&con->nref, 1); con->msgr = msgr; + + con_sock_state_init(con); + mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); -- GitLab From e10006f807ffc4d5b1d861305d18d9e8145891ca Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 0060/5711] libceph: provide osd number when creating osd Pass the osd number to the create_osd() routine, and move the initialization of fields that depend on it therein. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/osd_client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index cca4c7f1c780..e30efbcc6388 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -624,7 +624,7 @@ static void osd_reset(struct ceph_connection *con) /* * Track open sessions with osds. */ -static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) +static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) { struct ceph_osd *osd; @@ -634,6 +634,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) atomic_set(&osd->o_ref, 1); osd->o_osdc = osdc; + osd->o_osd = onum; INIT_LIST_HEAD(&osd->o_requests); INIT_LIST_HEAD(&osd->o_linger_requests); INIT_LIST_HEAD(&osd->o_osd_lru); @@ -643,6 +644,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) osd->o_con.private = osd; osd->o_con.ops = &osd_con_ops; osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; + osd->o_con.peer_name.num = cpu_to_le64(onum); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; @@ -998,15 +1000,13 @@ static int __map_request(struct ceph_osd_client *osdc, req->r_osd = __lookup_osd(osdc, o); if (!req->r_osd && o >= 0) { err = -ENOMEM; - req->r_osd = create_osd(osdc); + req->r_osd = create_osd(osdc, o); if (!req->r_osd) { list_move(&req->r_req_lru_item, &osdc->req_notarget); goto out; } dout("map_request osd %p is osd%d\n", req->r_osd, o); - req->r_osd->o_osd = o; - req->r_osd->o_con.peer_name.num = cpu_to_le64(o); __insert_osd(osdc, req->r_osd); ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); -- GitLab From a5988c490ef66cb04ea2f610681949b25c773b3c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 29 May 2012 11:04:58 -0500 Subject: [PATCH 0061/5711] libceph: set CLOSED state bit in con_init Once a connection is fully initialized, it is really in a CLOSED state, so make that explicit by setting the bit in its state field. It is possible for a connection in NEGOTIATING state to get a failure, leading to ceph_fault() and ultimately ceph_con_close(). Clear that bits if it is set in that case, to reflect that the connection truly is closed and is no longer participating in a connect sequence. Issue a warning if ceph_con_open() is called on a connection that is not in CLOSED state. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index a4ac3deec161..36b440a00cc2 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -454,11 +454,14 @@ void ceph_con_close(struct ceph_connection *con) { dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); - set_bit(CLOSED, &con->state); /* in case there's queued work */ + clear_bit(NEGOTIATING, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ + set_bit(CLOSED, &con->state); + clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(KEEPALIVE_PENDING, &con->flags); clear_bit(WRITE_PENDING, &con->flags); + mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; @@ -475,7 +478,8 @@ void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) { dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); - clear_bit(CLOSED, &con->state); + WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ queue_con(con); @@ -530,6 +534,8 @@ void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); INIT_DELAYED_WORK(&con->work, con_work); + + set_bit(CLOSED, &con->state); } EXPORT_SYMBOL(ceph_con_init); @@ -1933,14 +1939,15 @@ more: /* open the socket first? */ if (con->sock == NULL) { + clear_bit(NEGOTIATING, &con->state); + set_bit(CONNECTING, &con->state); + con_out_kvec_reset(con); prepare_write_banner(con); ret = prepare_write_connect(con); if (ret < 0) goto out; prepare_read_banner(con); - set_bit(CONNECTING, &con->state); - clear_bit(NEGOTIATING, &con->state); BUG_ON(con->in_msg); con->in_tag = CEPH_MSGR_TAG_READY; -- GitLab From 6af1c4fc5227af65092ebc848989693562bfa3e8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 3 May 2012 09:38:10 +0800 Subject: [PATCH 0062/5711] ACPICA: AML Parser: Fix two possible memory leaks in error path Fixes a couple of memory leaks in the error recovery path. Signed-off-by: Jesper Juhl Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/psargs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 5ac36aba507c..a683d6606e2e 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -618,6 +618,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); if (!arg) { + acpi_ps_free_op(field); return_PTR(NULL); } @@ -662,6 +663,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state } else { arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); if (!arg) { + acpi_ps_free_op(field); return_PTR(NULL); } -- GitLab From 579e3820bd1381d36b2c41485e9e7a94216bb7ed Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 3 May 2012 09:41:41 +0800 Subject: [PATCH 0063/5711] ACPICA: Object dump routines: Use common function for string output For ACPI string objects, always use the common string dump function, acpi_ut_print_string. This function surrounds the string with quotes and handles allowed escape sequences. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/exdump.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 2a6ac0a3bc1e..836fe76e65d0 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -926,9 +926,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_STRING: acpi_os_printf("[String] Value: "); - for (i = 0; i < obj_desc->string.length; i++) { - acpi_os_printf("%c", obj_desc->string.pointer[i]); - } + acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf("\n"); break; -- GitLab From 5134abfcfb4a8a9ef42c82dabad05762fbf04376 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 3 May 2012 09:43:21 +0800 Subject: [PATCH 0064/5711] ACPICA: Lint fixes for acpi_write, no functional changes acpi_write was widened to 64-bit data, this change eliminates some lint warnings. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwesleep.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 29e859293edd..3680c45b0827 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -117,7 +117,8 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) /* Clear wake status (WAK_STS) */ - status = acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); + status = + acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -147,7 +148,7 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & ACPI_X_SLEEP_TYPE_MASK); - status = acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE), + status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), &acpi_gbl_FADT.sleep_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -195,7 +196,7 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & ACPI_X_SLEEP_TYPE_MASK); - (void)acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE), + (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), &acpi_gbl_FADT.sleep_control); } @@ -239,7 +240,7 @@ acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags) * and use it to determine whether the system is rebooting or * resuming. Clear WAK_STS for compatibility. */ - (void)acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); + (void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); acpi_gbl_system_awake_and_running = TRUE; acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); -- GitLab From 86ed4bc83abf530cf2019044b74f89a39dfd6425 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 3 May 2012 11:08:19 +0800 Subject: [PATCH 0065/5711] ACPICA: Add support for multiple notify handlers This change adds support to allow multiple notify handlers on Device, ThermalZone, and Processor objects. Also re-worked and restructured the entire notify support code for handler installation, handler removal, notify event queuing, and notify dispatch to handler. Extends and updates original commit 3f0be67("ACPI / ACPICA: Multiple system notify handlers per device") by Rafael Wysocki. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acglobal.h | 3 +- drivers/acpi/acpica/aclocal.h | 13 +- drivers/acpi/acpica/acobject.h | 9 +- drivers/acpi/acpica/evmisc.c | 185 +++++--------- drivers/acpi/acpica/evxface.c | 440 +++++++++++---------------------- drivers/acpi/acpica/exdump.c | 25 +- drivers/acpi/acpica/utdelete.c | 24 +- drivers/acpi/acpica/utglobal.c | 4 +- include/acpi/actypes.h | 4 + 9 files changed, 266 insertions(+), 441 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 4f7d3f57d05c..dec7994d405c 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -278,8 +278,7 @@ ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; /* Global handlers */ -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; +ACPI_EXTERN struct acpi_global_notify_handler acpi_gbl_global_notify[2]; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index e3922ca20e7f..28f677834bfd 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -600,13 +600,22 @@ acpi_status(*acpi_parse_downwards) (struct acpi_walk_state * walk_state, typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state); +/* Global handlers for AML Notifies */ + +struct acpi_global_notify_handler { + acpi_notify_handler handler; + void *context; +}; + /* * Notify info - used to pass info to the deferred notify * handler/dispatcher. */ struct acpi_notify_info { - ACPI_STATE_COMMON struct acpi_namespace_node *node; - union acpi_operand_object *handler_obj; + ACPI_STATE_COMMON u8 handler_list_id; + struct acpi_namespace_node *node; + union acpi_operand_object *handler_list_head; + struct acpi_global_notify_handler *global; }; /* Generic state is union of structs above */ diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index c065078ca83b..39a2b84120be 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -206,8 +206,7 @@ struct acpi_object_method { * Common fields for objects that support ASL notifications */ #define ACPI_COMMON_NOTIFY_INFO \ - union acpi_operand_object *system_notify; /* Handler for system notifies */\ - union acpi_operand_object *device_notify; /* Handler for driver notifies */\ + union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\ union acpi_operand_object *handler; /* Handler for Address space */ struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ @@ -296,10 +295,10 @@ struct acpi_object_buffer_field { struct acpi_object_notify_handler { ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ - u32 handler_type; - acpi_notify_handler handler; + u32 handler_type; /* Type: Device/System/Both */ + acpi_notify_handler handler; /* Handler address */ void *context; - struct acpi_object_notify_handler *next; + union acpi_operand_object *next[2]; /* Device and System handler lists */ }; struct acpi_object_addr_handler { diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 51ef9f5e002d..381fce93a561 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -101,102 +101,77 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, u32 notify_value) { union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj = NULL; - union acpi_generic_state *notify_info; + union acpi_operand_object *handler_list_head = NULL; + union acpi_generic_state *info; + u8 handler_list_id = 0; acpi_status status = AE_OK; ACPI_FUNCTION_NAME(ev_queue_notify_request); - /* - * For value 0x03 (Ejection Request), may need to run a device method. - * For value 0x02 (Device Wake), if _PRW exists, may need to run - * the _PS0 method. - * For value 0x80 (Status Change) on the power button or sleep button, - * initiate soft-off or sleep operation. - * - * For all cases, simply dispatch the notify to the handler. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", - acpi_ut_get_node_name(node), - acpi_ut_get_type_name(node->type), notify_value, - acpi_ut_get_notify_name(notify_value), node)); + /* Are Notifies allowed on this object? */ - /* Get the notify object attached to the NS Node */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* We have the notify object, Get the correct handler */ - - switch (node->type) { + if (!acpi_ev_is_notify_object(node)) { + return (AE_TYPE); + } - /* Notify is allowed only on these types */ + /* Get the correct notify list type (System or Device) */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_PROCESSOR: + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + handler_list_id = ACPI_SYSTEM_HANDLER_LIST; + } else { + handler_list_id = ACPI_DEVICE_HANDLER_LIST; + } - if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = - obj_desc->common_notify.system_notify; - } else { - handler_obj = - obj_desc->common_notify.device_notify; - } - break; + /* Get the notify object attached to the namespace Node */ - default: + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { - /* All other types are not supported */ + /* We have an attached object, Get the correct handler list */ - return (AE_TYPE); - } + handler_list_head = + obj_desc->common_notify.notify_list[handler_list_id]; } /* - * If there is a handler to run, schedule the dispatcher. - * Check for: - * 1) Global system notify handler - * 2) Global device notify handler - * 3) Per-device notify handler + * If there is no notify handler (Global or Local) + * for this object, just ignore the notify */ - if ((acpi_gbl_system_notify.handler && - (notify_value <= ACPI_MAX_SYS_NOTIFY)) || - (acpi_gbl_device_notify.handler && - (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { - notify_info = acpi_ut_create_generic_state(); - if (!notify_info) { - return (AE_NO_MEMORY); - } + if (!acpi_gbl_global_notify[handler_list_id].handler + && !handler_list_head) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), notify_value, + node)); - if (!handler_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Executing system notify handler for Notify (%4.4s, %X) " - "node %p\n", - acpi_ut_get_node_name(node), - notify_value, node)); - } + return (AE_OK); + } - notify_info->common.descriptor_type = - ACPI_DESC_TYPE_STATE_NOTIFY; - notify_info->notify.node = node; - notify_info->notify.value = (u16) notify_value; - notify_info->notify.handler_obj = handler_obj; + /* Setup notify info and schedule the notify dispatcher */ - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); - } - } else { - /* There is no notify handler (per-device or system) for this device */ + info = acpi_ut_create_generic_state(); + if (!info) { + return (AE_NO_MEMORY); + } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No notify handler for Notify (%4.4s, %X) node %p\n", - acpi_ut_get_node_name(node), notify_value, - node)); + info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; + + info->notify.node = node; + info->notify.value = (u16)notify_value; + info->notify.handler_list_id = handler_list_id; + info->notify.handler_list_head = handler_list_head; + info->notify.global = &acpi_gbl_global_notify[handler_list_id]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(node->type), notify_value, + acpi_ut_get_notify_name(notify_value), node)); + + status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, + info); + if (ACPI_FAILURE(status)) { + acpi_ut_delete_generic_state(info); } return (status); @@ -217,60 +192,34 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) { - union acpi_generic_state *notify_info = - (union acpi_generic_state *)context; - acpi_notify_handler global_handler = NULL; - void *global_context = NULL; + union acpi_generic_state *info = (union acpi_generic_state *)context; union acpi_operand_object *handler_obj; ACPI_FUNCTION_ENTRY(); - /* - * We will invoke a global notify handler if installed. This is done - * _before_ we invoke the per-device handler attached to the device. - */ - if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { - - /* Global system notification handler */ - - if (acpi_gbl_system_notify.handler) { - global_handler = acpi_gbl_system_notify.handler; - global_context = acpi_gbl_system_notify.context; - } - } else { - /* Global driver notification handler */ - - if (acpi_gbl_device_notify.handler) { - global_handler = acpi_gbl_device_notify.handler; - global_context = acpi_gbl_device_notify.context; - } - } - - /* Invoke the system handler first, if present */ + /* Invoke a global notify handler if installed */ - if (global_handler) { - global_handler(notify_info->notify.node, - notify_info->notify.value, global_context); + if (info->notify.global->handler) { + info->notify.global->handler(info->notify.node, + info->notify.value, + info->notify.global->context); } - /* Now invoke the per-device handler, if present */ + /* Now invoke the local notify handler(s) if any are installed */ - handler_obj = notify_info->notify.handler_obj; - if (handler_obj) { - struct acpi_object_notify_handler *notifier; + handler_obj = info->notify.handler_list_head; + while (handler_obj) { + handler_obj->notify.handler(info->notify.node, + info->notify.value, + handler_obj->notify.context); - notifier = &handler_obj->notify; - while (notifier) { - notifier->handler(notify_info->notify.node, - notify_info->notify.value, - notifier->context); - notifier = notifier->next; - } + handler_obj = + handler_obj->notify.next[info->notify.handler_list_id]; } /* All done with the info object */ - acpi_ut_delete_generic_state(notify_info); + acpi_ut_delete_generic_state(info); } #if (!ACPI_REDUCED_HARDWARE) diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 44bef5744ebb..90ae6d193645 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -52,88 +52,27 @@ ACPI_MODULE_NAME("evxface") -/******************************************************************************* - * - * FUNCTION: acpi_populate_handler_object - * - * PARAMETERS: handler_obj - Handler object to populate - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * handler - Address of the handler - * context - Value passed to the handler on each GPE - * next - Address of a handler object to link to - * - * RETURN: None - * - * DESCRIPTION: Populate a handler object. - * - ******************************************************************************/ -static void -acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj, - u32 handler_type, - acpi_notify_handler handler, void *context, - struct acpi_object_notify_handler *next) -{ - handler_obj->handler_type = handler_type; - handler_obj->handler = handler; - handler_obj->context = context; - handler_obj->next = next; -} - -/******************************************************************************* - * - * FUNCTION: acpi_add_handler_object - * - * PARAMETERS: parent_obj - Parent of the new object - * handler - Address of the handler - * context - Value passed to the handler on each GPE - * - * RETURN: Status - * - * DESCRIPTION: Create a new handler object and populate it. - * - ******************************************************************************/ -static acpi_status -acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, - acpi_notify_handler handler, void *context) -{ - struct acpi_object_notify_handler *handler_obj; - - /* The parent must not be a defice notify handler object. */ - if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY) - return AE_BAD_PARAMETER; - - handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); - if (!handler_obj) - return AE_NO_MEMORY; - - acpi_populate_handler_object(handler_obj, - ACPI_SYSTEM_NOTIFY, - handler, context, - parent_obj->next); - parent_obj->next = handler_obj; - - return AE_OK; -} - - /******************************************************************************* * * FUNCTION: acpi_install_notify_handler * * PARAMETERS: Device - The device for which notifies will be handled * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) + * ACPI_ALL_NOTIFY: Both System and Device * Handler - Address of the handler * Context - Value passed to the handler on each GPE * * RETURN: Status * - * DESCRIPTION: Install a handler for notifies on an ACPI device + * DESCRIPTION: Install a handler for notifications on an ACPI Device, + * thermal_zone, or Processor object. + * + * NOTES: The Root namespace object may have only one handler for each + * type of notify (System/Device). Device/Thermal/Processor objects + * may have one device notify handler, and multiple system notify + * handlers. * ******************************************************************************/ acpi_status @@ -141,17 +80,19 @@ acpi_install_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler, void *context) { + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, device); union acpi_operand_object *obj_desc; - union acpi_operand_object *notify_obj; - struct acpi_namespace_node *node; + union acpi_operand_object *handler_obj; acpi_status status; + u32 i; ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + if ((!device) || (!handler) || (!handler_type) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -160,144 +101,112 @@ acpi_install_notify_handler(acpi_handle device, return_ACPI_STATUS(status); } - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that - * only one global handler can be regsitered (per notify type). + * only one global handler can be registered per notify type. + * Ensure that a handler is not already installed. */ if (device == ACPI_ROOT_OBJECT) { + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + if (acpi_gbl_global_notify[i].handler) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } - /* Make sure the handler is not already installed */ - - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - acpi_gbl_device_notify.handler)) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = node; - acpi_gbl_system_notify.handler = handler; - acpi_gbl_system_notify.context = context; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = node; - acpi_gbl_device_notify.handler = handler; - acpi_gbl_device_notify.context = context; + acpi_gbl_global_notify[i].handler = handler; + acpi_gbl_global_notify[i].context = context; + } } - /* Global notify handler installed */ + goto unlock_and_exit; /* Global notify handler installed, all done */ } /* * All Other Objects: - * Caller will only receive notifications specific to the target object. - * Note that only certain object types can receive notifications. + * Caller will only receive notifications specific to the target + * object. Note that only certain object types are allowed to + * receive notifications. */ - else { - /* Notifies allowed on this object? */ - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } + /* Are Notifies allowed on this object? */ - /* Check for an existing internal object */ + if (!acpi_ev_is_notify_object(node)) { + status = AE_TYPE; + goto unlock_and_exit; + } - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { + /* Check for an existing internal object, might not exist */ - /* Object exists. */ + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { - /* For a device notify, make sure there's no handler. */ - if ((handler_type & ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.device_notify) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } + /* Create a new object */ - /* System notifies may have more handlers installed. */ - notify_obj = obj_desc->common_notify.system_notify; + obj_desc = acpi_ut_create_internal_object(node->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } - if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { - struct acpi_object_notify_handler *parent_obj; + /* Attach new object to the Node, remove local reference */ - if (handler_type & ACPI_DEVICE_NOTIFY) { + status = acpi_ns_attach_object(device, obj_desc, node->type); + acpi_ut_remove_reference(obj_desc); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + /* Ensure that the handler is not already installed in the lists */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + handler_obj = obj_desc->common_notify.notify_list[i]; + while (handler_obj) { + if (handler_obj->notify.handler == handler) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - parent_obj = ¬ify_obj->notify; - status = acpi_add_handler_object(parent_obj, - handler, - context); - goto unlock_and_exit; - } - } else { - /* Create a new object */ - - obj_desc = acpi_ut_create_internal_object(node->type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Attach new object to the Node */ - - status = - acpi_ns_attach_object(device, obj_desc, node->type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; + handler_obj = handler_obj->notify.next[i]; } } + } - /* Install the handler */ + /* Create and populate a new notify handler object */ - notify_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); - if (!notify_obj) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } + handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } - acpi_populate_handler_object(¬ify_obj->notify, - handler_type, - handler, context, - NULL); + handler_obj->notify.node = node; + handler_obj->notify.handler_type = handler_type; + handler_obj->notify.handler = handler; + handler_obj->notify.context = context; - if (handler_type & ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.system_notify = notify_obj; - } + /* Install the handler at the list head(s) */ - if (handler_type & ACPI_DEVICE_NOTIFY) { - obj_desc->common_notify.device_notify = notify_obj; - } + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + handler_obj->notify.next[i] = + obj_desc->common_notify.notify_list[i]; - if (handler_type == ACPI_ALL_NOTIFY) { + obj_desc->common_notify.notify_list[i] = handler_obj; + } + } - /* Extra ref if installed in both */ + /* Add an extra reference if handler was installed in both lists */ - acpi_ut_add_reference(notify_obj); - } + if (handler_type == ACPI_ALL_NOTIFY) { + acpi_ut_add_reference(handler_obj); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -308,11 +217,11 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) * * FUNCTION: acpi_remove_notify_handler * - * PARAMETERS: Device - The device for which notifies will be handled + * PARAMETERS: Device - The device for which the handler is installed * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) + * ACPI_ALL_NOTIFY: Both System and Device * Handler - Address of the handler * * RETURN: Status @@ -324,165 +233,106 @@ acpi_status acpi_remove_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler) { - union acpi_operand_object *notify_obj; + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, device); union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; + union acpi_operand_object *handler_obj; + union acpi_operand_object *previous_handler_obj; acpi_status status; + u32 i; ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); /* Parameter validation */ - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - status = AE_BAD_PARAMETER; - goto exit; + if ((!device) || (!handler) || (!handler_type) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - - /* Make sure all deferred tasks are completed */ + acpi_os_wait_events_complete(NULL); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; + return_ACPI_STATUS(status); } - /* Root Object */ + /* Root Object. Global handlers are removed here */ if (device == ACPI_ROOT_OBJECT) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Removing notify handler for namespace root object\n")); + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + if (!acpi_gbl_global_notify[i].handler || + (acpi_gbl_global_notify[i].handler != + handler)) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - !acpi_gbl_device_notify.handler)) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Removing global notify handler\n")); - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = NULL; - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_system_notify.context = NULL; + acpi_gbl_global_notify[i].handler = NULL; + acpi_gbl_global_notify[i].context = NULL; + } } - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = NULL; - acpi_gbl_device_notify.handler = NULL; - acpi_gbl_device_notify.context = NULL; - } + goto unlock_and_exit; } - /* All Other Objects */ - - else { - /* Notifies allowed on this object? */ + /* All other objects: Are Notifies allowed on this object? */ - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } + if (!acpi_ev_is_notify_object(node)) { + status = AE_TYPE; + goto unlock_and_exit; + } - /* Check for an existing internal object */ + /* Must have an existing internal object */ - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } - /* Object exists - make sure there's an existing handler */ + /* Internal object exists. Find the handler and remove it */ - if (handler_type & ACPI_SYSTEM_NOTIFY) { - struct acpi_object_notify_handler *handler_obj; - struct acpi_object_notify_handler *parent_obj; + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + handler_obj = obj_desc->common_notify.notify_list[i]; + previous_handler_obj = NULL; - notify_obj = obj_desc->common_notify.system_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + /* Attempt to find the handler in the handler list */ - handler_obj = ¬ify_obj->notify; - parent_obj = NULL; - while (handler_obj->handler != handler) { - if (handler_obj->next) { - parent_obj = handler_obj; - handler_obj = handler_obj->next; - } else { - break; - } + while (handler_obj && + (handler_obj->notify.handler != handler)) { + previous_handler_obj = handler_obj; + handler_obj = handler_obj->notify.next[i]; } - if (handler_obj->handler != handler) { - status = AE_BAD_PARAMETER; + if (!handler_obj) { + status = AE_NOT_EXIST; goto unlock_and_exit; } - /* - * Remove the handler. There are three possible cases. - * First, we may need to remove a non-embedded object. - * Second, we may need to remove the embedded object's - * handler data, while non-embedded objects exist. - * Finally, we may need to remove the embedded object - * entirely along with its container. - */ - if (parent_obj) { - /* Non-embedded object is being removed. */ - parent_obj->next = handler_obj->next; - ACPI_FREE(handler_obj); - } else if (notify_obj->notify.next) { - /* - * The handler matches the embedded object, but - * there are more handler objects in the list. - * Replace the embedded object's data with the - * first next object's data and remove that - * object. - */ - parent_obj = ¬ify_obj->notify; - handler_obj = notify_obj->notify.next; - *parent_obj = *handler_obj; - ACPI_FREE(handler_obj); - } else { - /* No more handler objects in the list. */ - obj_desc->common_notify.system_notify = NULL; - acpi_ut_remove_reference(notify_obj); - } - } + /* Remove the handler object from the list */ - if (handler_type & ACPI_DEVICE_NOTIFY) { - notify_obj = obj_desc->common_notify.device_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + if (previous_handler_obj) { /* Handler is not at the list head */ + previous_handler_obj->notify.next[i] = + handler_obj->notify.next[i]; + } else { /* Handler is at the list head */ - if (notify_obj->notify.handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; + obj_desc->common_notify.notify_list[i] = + handler_obj->notify.next[i]; } - /* Remove the handler */ - obj_desc->common_notify.device_notify = NULL; - acpi_ut_remove_reference(notify_obj); + acpi_ut_remove_reference(handler_obj); } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - exit: - if (ACPI_FAILURE(status)) - ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 836fe76e65d0..26c56545804d 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -109,9 +109,9 @@ static struct acpi_exdump_info acpi_ex_dump_package[5] = { static struct acpi_exdump_info acpi_ex_dump_device[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[1]), "Device Notify"} }; @@ -158,9 +158,9 @@ static struct acpi_exdump_info acpi_ex_dump_power[5] = { "System Level"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), "Resource Order"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[1]), "Device Notify"} }; @@ -169,18 +169,18 @@ static struct acpi_exdump_info acpi_ex_dump_processor[7] = { {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[1]), "Device Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[1]), "Device Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} }; @@ -241,10 +241,15 @@ static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} }; -static struct acpi_exdump_info acpi_ex_dump_notify[3] = { +static struct acpi_exdump_info acpi_ex_dump_notify[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(notify.handler_type), "Handler Type"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[0]), + "Next System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[1]), "Next Device Notify"} }; /* Miscellaneous tables */ diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 2a6c3e183697..0d50f2c6bac2 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -152,7 +152,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: - /* Walk the notify handler list for this object */ + /* Walk the address handler list for this object */ handler_desc = object->common_notify.handler; while (handler_desc) { @@ -480,6 +480,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; union acpi_operand_object *next_object = NULL; + union acpi_operand_object *prev_object; union acpi_generic_state *state; u32 i; @@ -505,12 +506,21 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: - /* Update the notify objects for these types (if present) */ - - acpi_ut_update_ref_count(object->common_notify. - system_notify, action); - acpi_ut_update_ref_count(object->common_notify. - device_notify, action); + /* + * Update the notify objects for these types (if present) + * Two lists, system and device notify handlers. + */ + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + prev_object = + object->common_notify.notify_list[i]; + while (prev_object) { + next_object = + prev_object->notify.next[i]; + acpi_ut_update_ref_count(prev_object, + action); + prev_object = next_object; + } + } break; case ACPI_TYPE_PACKAGE: diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 90f53b42eca9..78cf1fe390b3 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -304,8 +304,8 @@ acpi_status acpi_ut_init_globals(void) /* Global handlers */ - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_device_notify.handler = NULL; + acpi_gbl_global_notify[0].handler = NULL; + acpi_gbl_global_notify[1].handler = NULL; acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; acpi_gbl_table_handler = NULL; diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e8bcc4742e0e..0339a2d93f1d 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -706,10 +706,14 @@ typedef u32 acpi_event_status; #define ACPI_DEVICE_NOTIFY 0x2 #define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY) #define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 +#define ACPI_NUM_NOTIFY_TYPES 2 #define ACPI_MAX_SYS_NOTIFY 0x7F #define ACPI_MAX_DEVICE_SPECIFIC_NOTIFY 0xBF +#define ACPI_SYSTEM_HANDLER_LIST 0 /* Used as index, must be SYSTEM_NOTIFY -1 */ +#define ACPI_DEVICE_HANDLER_LIST 1 /* Used as index, must be DEVICE_NOTIFY -1 */ + /* Address Space (Operation Region) Types */ typedef u8 acpi_adr_space_type; -- GitLab From 9fd7522570449bd10f6a6377cf5cb542ef527dd5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 3 May 2012 10:50:54 +0800 Subject: [PATCH 0066/5711] ACPICA: Update to version 20120420 Version 20120420. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 982110134672..a323a7cc1224 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20120320 +#define ACPI_CA_VERSION 0x20120420 #include "acconfig.h" #include "actypes.h" -- GitLab From 6ccd7b5acc418e02953a8dd8a3c17e04907aacff Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 22 May 2012 16:22:01 +0800 Subject: [PATCH 0067/5711] ACPICA: Disassembler: Add support for Operation Region externals Adds missing support for operation regions defined in another table, but referenced via a Field or BankField operator. Generate the correct External statement. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/dsfield.c | 81 +++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index cd243cf2cab2..809843923d64 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -53,11 +53,79 @@ ACPI_MODULE_NAME("dsfield") /* Local prototypes */ +#ifdef ACPI_ASL_COMPILER +#include "acdisasm.h" +static acpi_status +acpi_ds_create_external_region(acpi_status lookup_status, + union acpi_parse_object *op, + char *path, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **node); +#endif + static acpi_status acpi_ds_get_field_names(struct acpi_create_field_info *info, struct acpi_walk_state *walk_state, union acpi_parse_object *arg); +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_external_region (i_aSL Disassembler only) + * + * PARAMETERS: lookup_status - Status from ns_lookup operation + * Op - Op containing the Field definition and args + * Path - Pathname of the region + * ` walk_state - Current method state + * Node - Where the new region node is returned + * + * RETURN: Status + * + * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new + * region node/object. + * + ******************************************************************************/ + +static acpi_status +acpi_ds_create_external_region(acpi_status lookup_status, + union acpi_parse_object *op, + char *path, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **node) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + + if (lookup_status != AE_NOT_FOUND) { + return (lookup_status); + } + + /* + * Table disassembly: + * operation_region not found. Generate an External for it, and + * insert the name into the namespace. + */ + acpi_dm_add_to_external_list(op, path, ACPI_TYPE_REGION, 0); + status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, + walk_state, node); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Must create and install a region object for the new node */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->region.node = *node; + status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); + return (status); +} +#endif + /******************************************************************************* * * FUNCTION: acpi_ds_create_buffer_field @@ -413,12 +481,19 @@ acpi_ds_create_field(union acpi_parse_object *op, /* First arg is the name of the parent op_region (must already exist) */ arg = op->common.value.arg; + if (!region_node) { status = acpi_ns_lookup(walk_state->scope_info, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); +#ifdef ACPI_ASL_COMPILER + status = acpi_ds_create_external_region(status, arg, + arg->common.value.name, + walk_state, + ®ion_node); +#endif if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); @@ -591,6 +666,12 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); +#ifdef ACPI_ASL_COMPILER + status = acpi_ds_create_external_region(status, arg, + arg->common.value.name, + walk_state, + ®ion_node); +#endif if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); -- GitLab From 43e1c6892c88ae0730cb0eb7bd5a2812b960c32a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 22 May 2012 16:23:21 +0800 Subject: [PATCH 0068/5711] ACPICA: ACPI 5/iASL: Add support for PCC keyword Adds support for the PCC keyword for the Register() resource descriptor macro. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/actypes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 0339a2d93f1d..376c9ed739d4 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -728,8 +728,9 @@ typedef u8 acpi_adr_space_type; #define ACPI_ADR_SPACE_IPMI (acpi_adr_space_type) 7 #define ACPI_ADR_SPACE_GPIO (acpi_adr_space_type) 8 #define ACPI_ADR_SPACE_GSBUS (acpi_adr_space_type) 9 +#define ACPI_ADR_SPACE_PLATFORM_COMM (acpi_adr_space_type) 10 -#define ACPI_NUM_PREDEFINED_REGIONS 10 +#define ACPI_NUM_PREDEFINED_REGIONS 11 /* * Special Address Spaces -- GitLab From c6e1733e6fc384ff1a219d7dfcb8b072030ae792 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 22 May 2012 16:26:53 +0800 Subject: [PATCH 0069/5711] ACPICA: iASL: Improved pathname support For include files, merge the prefix pathname with the file pathname. Convert backslashes in all pathnames to forward slashes, for readability. Include file pathname changes affect both #include and Include() type operators. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acutils.h | 2 ++ drivers/acpi/acpica/utmisc.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 925ccf22101b..5035327ebccc 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -460,6 +460,8 @@ acpi_ut_short_divide(u64 in_dividend, /* * utmisc */ +void ut_convert_backslashes(char *pathname); + const char *acpi_ut_validate_exception(acpi_status status); u8 acpi_ut_is_pci_root_bridge(char *id); diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 86f19db74e05..e86f897767e8 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -50,6 +50,34 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") +/******************************************************************************* + * + * FUNCTION: ut_convert_backslashes + * + * PARAMETERS: Pathname - File pathname string to be converted + * + * RETURN: Modifies the input Pathname + * + * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within + * the entire input file pathname string. + * + ******************************************************************************/ +void ut_convert_backslashes(char *pathname) +{ + + if (!pathname) { + return; + } + + while (*pathname) { + if (*pathname == '\\') { + *pathname = '/'; + } + + pathname++; + } +} + /******************************************************************************* * * FUNCTION: acpi_ut_validate_exception @@ -63,6 +91,7 @@ ACPI_MODULE_NAME("utmisc") * an ASCII string. * ******************************************************************************/ + const char *acpi_ut_validate_exception(acpi_status status) { u32 sub_status; -- GitLab From bd6f10a5f984e48cb56a39f2698cd58e7a33d56b Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Tue, 22 May 2012 16:43:49 +0800 Subject: [PATCH 0070/5711] ACPICA: Remove argument of acpi_os_wait_events_complete Remove the unused argument of acpi_os_wait_events_complete. Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/acpica/evxface.c | 4 ++-- drivers/acpi/osl.c | 4 ++-- drivers/acpi/sleep.c | 2 +- include/acpi/acpiosxf.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 90ae6d193645..6a8b53789be4 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -251,7 +251,7 @@ acpi_remove_notify_handler(acpi_handle device, } /* Make sure all deferred tasks are completed */ - acpi_os_wait_events_complete(NULL); + acpi_os_wait_events_complete(); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -699,7 +699,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, /* Make sure all deferred tasks are completed */ - acpi_os_wait_events_complete(NULL); + acpi_os_wait_events_complete(); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c3881b2eb8b2..9eaf708f5885 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -891,7 +891,7 @@ static void acpi_os_execute_deferred(struct work_struct *work) struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); if (dpc->wait) - acpi_os_wait_events_complete(NULL); + acpi_os_wait_events_complete(); dpc->function(dpc->context); kfree(dpc); @@ -987,7 +987,7 @@ acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, return __acpi_os_execute(0, function, context, 1); } -void acpi_os_wait_events_complete(void *context) +void acpi_os_wait_events_complete(void) { flush_workqueue(kacpid_wq); flush_workqueue(kacpi_notify_wq); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index eb6fd233764b..9a14f90d98ec 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -144,7 +144,7 @@ void __init acpi_old_suspend_ordering(void) static int acpi_pm_freeze(void) { acpi_disable_all_gpes(); - acpi_os_wait_events_complete(NULL); + acpi_os_wait_events_complete(); acpi_ec_block_transactions(); return 0; } diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 21a5548c6686..f3746f7e0f40 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -205,7 +205,7 @@ acpi_os_execute(acpi_execute_type type, acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context); -void acpi_os_wait_events_complete(void *context); +void acpi_os_wait_events_complete(void); void acpi_os_sleep(u64 milliseconds); -- GitLab From 66be71ff477389ff12c9c43dc6ee176cf8e1dd3a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 22 May 2012 16:35:00 +0800 Subject: [PATCH 0071/5711] ACPICA: Add FADT error message for GAS BitWidth overflow Error for possible overflow during conversion from 32-bit legacy register addresses to GAS format. The GAS struct contains a one-byte BitWidth field, meaning that the maximum length of a register is 255 bits. ACPICA BZ 953. https://www.acpica.org/bugzilla/show_bug.cgi?id=953 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 4c9c760db4a4..d919f4055dba 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -49,9 +49,10 @@ ACPI_MODULE_NAME("tbfadt") /* Local prototypes */ -static ACPI_INLINE void +static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address); + u8 space_id, + u8 byte_width, u64 address, char *register_name); static void acpi_tb_convert_fadt(void); @@ -182,10 +183,25 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { * ******************************************************************************/ -static ACPI_INLINE void +static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address) + u8 space_id, + u8 byte_width, u64 address, char *register_name) { + u8 bit_width; + + /* Bit width field in the GAS is only one byte long, 255 max */ + + bit_width = (u8)(byte_width * 8); + + if (byte_width > 31) { /* (31*8)=248 */ + ACPI_ERROR((AE_INFO, + "%s - 32-bit FADT register is too long (%u bytes, %u bits) " + "to convert to GAS struct - 255 bits max, truncating", + register_name, byte_width, (byte_width * 8))); + + bit_width = 255; + } /* * The 64-bit Address field is non-aligned in the byte packed @@ -196,7 +212,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, /* All other fields are byte-wide */ generic_address->space_id = space_id; - generic_address->bit_width = (u8)ACPI_MUL_8(byte_width); + generic_address->bit_width = bit_width; generic_address->bit_offset = 0; generic_address->access_width = 0; /* Access width ANY */ } @@ -456,7 +472,8 @@ static void acpi_tb_convert_fadt(void) &acpi_gbl_FADT, fadt_info_table [i].length), - (u64) address32); + (u64) address32, + fadt_info_table[i].name); } } } @@ -670,7 +687,8 @@ static void acpi_tb_setup_fadt_registers(void) source64->address + (fadt_pm_info_table[i]. register_num * - pm1_register_byte_width)); + pm1_register_byte_width), + "PmRegisters"); } } } -- GitLab From 9748f313101c95dcc65f5dddd1c2ea99b7ce3e9b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 22 May 2012 16:44:42 +0800 Subject: [PATCH 0072/5711] ACPICA: Update to version 20120518 Version string 20120518. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index a323a7cc1224..381c94008536 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20120420 +#define ACPI_CA_VERSION 0x20120518 #include "acconfig.h" #include "actypes.h" -- GitLab From 493a708179469e3978e50f59902e9d47b6f3dabd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 May 2012 12:31:56 +0200 Subject: [PATCH 0073/5711] drm/i915: clarify IBX dp workaround Instead of checking for !CPT, check for IBX to make it clearer that this is a IBX-specific workaround. No functional change because we smash the PPT PCH into the HAS_PCH_CPT check and atm DP isn't enabled on the haswell LPT PCH yet. See Bspec Vol 3, Part 3, Section 4.[3-5].1 about DP[BCD], bit 30 for details of this workaround. Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c71e7890e6f6..ade98e0bca84 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1914,7 +1914,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DP |= DP_LINK_TRAIN_OFF; } - if (!HAS_PCH_CPT(dev) && + if (HAS_PCH_IBX(dev) && I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { struct drm_crtc *crtc = intel_dp->base.base.crtc; -- GitLab From 0aeb9cac6f8a6fc68acfb07d30b62ad6106a6384 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Fri, 4 May 2012 14:06:02 -0700 Subject: [PATCH 0074/5711] cpuidle: remove unused hrtimer_peek_ahead_timers() call commit 9a6558371bcd01c2973b7638181db4ccc34eab4f Author: Arjan van de Ven Date: Sun Nov 9 12:45:10 2008 -0800 regression: disable timer peek-ahead for 2.6.28 It's showing up as regressions; disabling it very likely just papers over an underlying issue, but time is running out for 2.6.28, lets get back to this for 2.6.29 Many years has passed since 2008, so it seems ok to remove whole `#if 0' block. Signed-off-by: Sergey Senozhatsky Cc: Kevin Hilman Cc: Trinabh Gupta Cc: Deepthi Dharwar Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/cpuidle/cpuidle.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2f0083a51a9a..588b44aa1de4 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -124,15 +124,6 @@ int cpuidle_idle_call(void) if (!dev || !dev->enabled) return -EBUSY; -#if 0 - /* shows regressions, re-enable for 2.6.29 */ - /* - * run any timers that can be run now, at this point - * before calculating the idle duration etc. - */ - hrtimer_peek_ahead_timers(); -#endif - /* ask the governor for the next state */ next_state = cpuidle_curr_governor->select(drv, dev); if (need_resched()) { -- GitLab From 1b0a0e9a15b976d91f3b5ae619c6a8964c2818eb Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Fri, 4 May 2012 14:06:02 -0700 Subject: [PATCH 0075/5711] cpuidle: add checks to avoid NULL pointer dereference The existing check for dev == NULL in __cpuidle_register_device() is rendered useless because dev is dereferenced before the check itself. Moreover, correctly speaking, it is the job of the callers of this function, i.e., cpuidle_register_device() & cpuidle_enable_device() (which also happen to be exported functions) to ensure that __cpuidle_register_device() is called with a non-NULL dev. So add the necessary dev == NULL checks in the two callers and remove the (useless) check from __cpuidle_register_device(). Signed-off-by: Srivatsa S. Bhat Acked-by: Daniel Lezcano Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/cpuidle/cpuidle.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 588b44aa1de4..8ffef26ffdcf 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -285,6 +285,9 @@ int cpuidle_enable_device(struct cpuidle_device *dev) int ret, i; struct cpuidle_driver *drv = cpuidle_get_driver(); + if (!dev) + return -EINVAL; + if (dev->enabled) return 0; if (!drv || !cpuidle_curr_governor) @@ -369,8 +372,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); - if (!dev) - return -EINVAL; if (!try_module_get(cpuidle_driver->owner)) return -EINVAL; @@ -395,6 +396,9 @@ int cpuidle_register_device(struct cpuidle_device *dev) { int ret; + if (!dev) + return -EINVAL; + mutex_lock(&cpuidle_lock); if ((ret = __cpuidle_register_device(dev))) { -- GitLab From a58e1150225cc9e554b76da5519b2bb5bb6e46ff Mon Sep 17 00:00:00 2001 From: srinivas pandruvada Date: Thu, 5 Apr 2012 17:38:54 -0700 Subject: [PATCH 0076/5711] ACPI Battery: Added capacity Added Capacity field, which is a pre-defined power_supply property. Calculating capacity using current charge/energy and full charge/energy. Some user mode implementations are relying on capacity field to show battery strength and power down decision. Signed-off-by: srinivas pandruvada Signed-off-by: Len Brown --- drivers/acpi/battery.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7dd3f9fb9f3f..5662d64e6733 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -250,6 +250,13 @@ static int acpi_battery_get_property(struct power_supply *psy, else val->intval = battery->capacity_now * 1000; break; + case POWER_SUPPLY_PROP_CAPACITY: + if (battery->capacity_now && battery->full_charge_capacity) + val->intval = battery->capacity_now * 100/ + battery->full_charge_capacity; + else + val->intval = 0; + break; case POWER_SUPPLY_PROP_MODEL_NAME: val->strval = battery->model_number; break; @@ -276,6 +283,7 @@ static enum power_supply_property charge_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_SERIAL_NUMBER, @@ -292,6 +300,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_SERIAL_NUMBER, -- GitLab From 56cfbf74a17c40f3a741398103c9f5d5a6806715 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 7 May 2012 17:57:39 -0700 Subject: [PATCH 0077/5711] cpuidle: refactor out cpuidle_enter_state Split the code to enter a state and update the stats into a helper function, cpuidle_enter_state, and export it. This function will be called by the coupled state code to handle entering the safe state and the final coupled state. Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Colin Cross Reviewed-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/cpuidle/cpuidle.c | 42 +++++++++++++++++++++++++++------------ drivers/cpuidle/cpuidle.h | 2 ++ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2f0083a51a9a..3e3e3e4d9581 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -102,6 +102,34 @@ int cpuidle_play_dead(void) return -ENODEV; } +/** + * cpuidle_enter_state - enter the state and update stats + * @dev: cpuidle device for this cpu + * @drv: cpuidle driver for this cpu + * @next_state: index into drv->states of the state to enter + */ +int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, + int next_state) +{ + int entered_state; + + entered_state = cpuidle_enter_ops(dev, drv, next_state); + + if (entered_state >= 0) { + /* Update cpuidle counters */ + /* This can be moved to within driver enter routine + * but that results in multiple copies of same code. + */ + dev->states_usage[entered_state].time += + (unsigned long long)dev->last_residency; + dev->states_usage[entered_state].usage++; + } else { + dev->last_residency = 0; + } + + return entered_state; +} + /** * cpuidle_idle_call - the main idle loop * @@ -143,23 +171,11 @@ int cpuidle_idle_call(void) trace_power_start_rcuidle(POWER_CSTATE, next_state, dev->cpu); trace_cpu_idle_rcuidle(next_state, dev->cpu); - entered_state = cpuidle_enter_ops(dev, drv, next_state); + entered_state = cpuidle_enter_state(dev, drv, next_state); trace_power_end_rcuidle(dev->cpu); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); - if (entered_state >= 0) { - /* Update cpuidle counters */ - /* This can be moved to within driver enter routine - * but that results in multiple copies of same code. - */ - dev->states_usage[entered_state].time += - (unsigned long long)dev->last_residency; - dev->states_usage[entered_state].usage++; - } else { - dev->last_residency = 0; - } - /* give the governor an opportunity to reflect on the outcome */ if (cpuidle_curr_governor->reflect) cpuidle_curr_governor->reflect(dev, entered_state); diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h index 7db186685c27..d8a3ccce8281 100644 --- a/drivers/cpuidle/cpuidle.h +++ b/drivers/cpuidle/cpuidle.h @@ -14,6 +14,8 @@ extern struct list_head cpuidle_detected_devices; extern struct mutex cpuidle_lock; extern spinlock_t cpuidle_driver_lock; extern int cpuidle_disabled(void); +extern int cpuidle_enter_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int next_state); /* idle loop */ extern void cpuidle_install_idle_handler(void); -- GitLab From 3af272ab75c7a0c7fa5ae5507724d961f7e7718b Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 7 May 2012 17:57:40 -0700 Subject: [PATCH 0078/5711] cpuidle: fix error handling in __cpuidle_register_device Fix the error handling in __cpuidle_register_device to include the missing list_del. Move it to a label, which will simplify the error handling when coupled states are added. Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Colin Cross Reviewed-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/cpuidle/cpuidle.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 3e3e3e4d9581..4540672a2e1c 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -403,13 +403,18 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); - if ((ret = cpuidle_add_sysfs(cpu_dev))) { - module_put(cpuidle_driver->owner); - return ret; - } + ret = cpuidle_add_sysfs(cpu_dev); + if (ret) + goto err_sysfs; dev->registered = 1; return 0; + +err_sysfs: + list_del(&dev->device_list); + per_cpu(cpuidle_devices, dev->cpu) = NULL; + module_put(cpuidle_driver->owner); + return ret; } /** -- GitLab From 4126c0197bc8c58a0bb7fcda07b01b596b6fb4c5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 7 May 2012 17:57:41 -0700 Subject: [PATCH 0079/5711] cpuidle: add support for states that affect multiple cpus On some ARM SMP SoCs (OMAP4460, Tegra 2, and probably more), the cpus cannot be independently powered down, either due to sequencing restrictions (on Tegra 2, cpu 0 must be the last to power down), or due to HW bugs (on OMAP4460, a cpu powering up will corrupt the gic state unless the other cpu runs a work around). Each cpu has a power state that it can enter without coordinating with the other cpu (usually Wait For Interrupt, or WFI), and one or more "coupled" power states that affect blocks shared between the cpus (L2 cache, interrupt controller, and sometimes the whole SoC). Entering a coupled power state must be tightly controlled on both cpus. The easiest solution to implementing coupled cpu power states is to hotplug all but one cpu whenever possible, usually using a cpufreq governor that looks at cpu load to determine when to enable the secondary cpus. This causes problems, as hotplug is an expensive operation, so the number of hotplug transitions must be minimized, leading to very slow response to loads, often on the order of seconds. This file implements an alternative solution, where each cpu will wait in the WFI state until all cpus are ready to enter a coupled state, at which point the coupled state function will be called on all cpus at approximately the same time. Once all cpus are ready to enter idle, they are woken by an smp cross call. At this point, there is a chance that one of the cpus will find work to do, and choose not to enter idle. A final pass is needed to guarantee that all cpus will call the power state enter function at the same time. During this pass, each cpu will increment the ready counter, and continue once the ready counter matches the number of online coupled cpus. If any cpu exits idle, the other cpus will decrement their counter and retry. To use coupled cpuidle states, a cpuidle driver must: Set struct cpuidle_device.coupled_cpus to the mask of all coupled cpus, usually the same as cpu_possible_mask if all cpus are part of the same cluster. The coupled_cpus mask must be set in the struct cpuidle_device for each cpu. Set struct cpuidle_device.safe_state to a state that is not a coupled state. This is usually WFI. Set CPUIDLE_FLAG_COUPLED in struct cpuidle_state.flags for each state that affects multiple cpus. Provide a struct cpuidle_state.enter function for each state that affects multiple cpus. This function is guaranteed to be called on all cpus at approximately the same time. The driver should ensure that the cpus all abort together if any cpu tries to abort once the function is called. update1: cpuidle: coupled: fix count of online cpus online_count was never incremented on boot, and was also counting cpus that were not part of the coupled set. Fix both issues by introducting a new function that counts online coupled cpus, and call it from register as well as the hotplug notifier. update2: cpuidle: coupled: fix decrementing ready count cpuidle_coupled_set_not_ready sometimes refuses to decrement the ready count in order to prevent a race condition. This makes it unsuitable for use when finished with idle. Add a new function cpuidle_coupled_set_done that decrements both the ready count and waiting count, and call it after idle is complete. Cc: Amit Kucheria Cc: Arjan van de Ven Cc: Trinabh Gupta Cc: Deepthi Dharwar Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Colin Cross Acked-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/cpuidle/Kconfig | 3 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/coupled.c | 678 ++++++++++++++++++++++++++++++++++++++ drivers/cpuidle/cpuidle.c | 15 +- drivers/cpuidle/cpuidle.h | 30 ++ include/linux/cpuidle.h | 7 + 6 files changed, 733 insertions(+), 1 deletion(-) create mode 100644 drivers/cpuidle/coupled.c diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 78a666d1e5f5..a76b689e553b 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -18,3 +18,6 @@ config CPU_IDLE_GOV_MENU bool depends on CPU_IDLE && NO_HZ default y + +config ARCH_NEEDS_CPU_IDLE_COUPLED + def_bool n diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 5634f88379df..38c8f69f30cf 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -3,3 +3,4 @@ # obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ +obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c new file mode 100644 index 000000000000..aab6bba8daec --- /dev/null +++ b/drivers/cpuidle/coupled.c @@ -0,0 +1,678 @@ +/* + * coupled.c - helper functions to enter the same idle state on multiple cpus + * + * Copyright (c) 2011 Google, Inc. + * + * Author: Colin Cross + * + * 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 "cpuidle.h" + +/** + * DOC: Coupled cpuidle states + * + * On some ARM SMP SoCs (OMAP4460, Tegra 2, and probably more), the + * cpus cannot be independently powered down, either due to + * sequencing restrictions (on Tegra 2, cpu 0 must be the last to + * power down), or due to HW bugs (on OMAP4460, a cpu powering up + * will corrupt the gic state unless the other cpu runs a work + * around). Each cpu has a power state that it can enter without + * coordinating with the other cpu (usually Wait For Interrupt, or + * WFI), and one or more "coupled" power states that affect blocks + * shared between the cpus (L2 cache, interrupt controller, and + * sometimes the whole SoC). Entering a coupled power state must + * be tightly controlled on both cpus. + * + * This file implements a solution, where each cpu will wait in the + * WFI state until all cpus are ready to enter a coupled state, at + * which point the coupled state function will be called on all + * cpus at approximately the same time. + * + * Once all cpus are ready to enter idle, they are woken by an smp + * cross call. At this point, there is a chance that one of the + * cpus will find work to do, and choose not to enter idle. A + * final pass is needed to guarantee that all cpus will call the + * power state enter function at the same time. During this pass, + * each cpu will increment the ready counter, and continue once the + * ready counter matches the number of online coupled cpus. If any + * cpu exits idle, the other cpus will decrement their counter and + * retry. + * + * requested_state stores the deepest coupled idle state each cpu + * is ready for. It is assumed that the states are indexed from + * shallowest (highest power, lowest exit latency) to deepest + * (lowest power, highest exit latency). The requested_state + * variable is not locked. It is only written from the cpu that + * it stores (or by the on/offlining cpu if that cpu is offline), + * and only read after all the cpus are ready for the coupled idle + * state are are no longer updating it. + * + * Three atomic counters are used. alive_count tracks the number + * of cpus in the coupled set that are currently or soon will be + * online. waiting_count tracks the number of cpus that are in + * the waiting loop, in the ready loop, or in the coupled idle state. + * ready_count tracks the number of cpus that are in the ready loop + * or in the coupled idle state. + * + * To use coupled cpuidle states, a cpuidle driver must: + * + * Set struct cpuidle_device.coupled_cpus to the mask of all + * coupled cpus, usually the same as cpu_possible_mask if all cpus + * are part of the same cluster. The coupled_cpus mask must be + * set in the struct cpuidle_device for each cpu. + * + * Set struct cpuidle_device.safe_state to a state that is not a + * coupled state. This is usually WFI. + * + * Set CPUIDLE_FLAG_COUPLED in struct cpuidle_state.flags for each + * state that affects multiple cpus. + * + * Provide a struct cpuidle_state.enter function for each state + * that affects multiple cpus. This function is guaranteed to be + * called on all cpus at approximately the same time. The driver + * should ensure that the cpus all abort together if any cpu tries + * to abort once the function is called. The function should return + * with interrupts still disabled. + */ + +/** + * struct cpuidle_coupled - data for set of cpus that share a coupled idle state + * @coupled_cpus: mask of cpus that are part of the coupled set + * @requested_state: array of requested states for cpus in the coupled set + * @ready_waiting_counts: combined count of cpus in ready or waiting loops + * @online_count: count of cpus that are online + * @refcnt: reference count of cpuidle devices that are using this struct + * @prevent: flag to prevent coupled idle while a cpu is hotplugging + */ +struct cpuidle_coupled { + cpumask_t coupled_cpus; + int requested_state[NR_CPUS]; + atomic_t ready_waiting_counts; + int online_count; + int refcnt; + int prevent; +}; + +#define WAITING_BITS 16 +#define MAX_WAITING_CPUS (1 << WAITING_BITS) +#define WAITING_MASK (MAX_WAITING_CPUS - 1) +#define READY_MASK (~WAITING_MASK) + +#define CPUIDLE_COUPLED_NOT_IDLE (-1) + +static DEFINE_MUTEX(cpuidle_coupled_lock); +static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb); + +/* + * The cpuidle_coupled_poked_mask mask is used to avoid calling + * __smp_call_function_single with the per cpu call_single_data struct already + * in use. This prevents a deadlock where two cpus are waiting for each others + * call_single_data struct to be available + */ +static cpumask_t cpuidle_coupled_poked_mask; + +/** + * cpuidle_state_is_coupled - check if a state is part of a coupled set + * @dev: struct cpuidle_device for the current cpu + * @drv: struct cpuidle_driver for the platform + * @state: index of the target state in drv->states + * + * Returns true if the target state is coupled with cpus besides this one + */ +bool cpuidle_state_is_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int state) +{ + return drv->states[state].flags & CPUIDLE_FLAG_COUPLED; +} + +/** + * cpuidle_coupled_set_ready - mark a cpu as ready + * @coupled: the struct coupled that contains the current cpu + */ +static inline void cpuidle_coupled_set_ready(struct cpuidle_coupled *coupled) +{ + atomic_add(MAX_WAITING_CPUS, &coupled->ready_waiting_counts); +} + +/** + * cpuidle_coupled_set_not_ready - mark a cpu as not ready + * @coupled: the struct coupled that contains the current cpu + * + * Decrements the ready counter, unless the ready (and thus the waiting) counter + * is equal to the number of online cpus. Prevents a race where one cpu + * decrements the waiting counter and then re-increments it just before another + * cpu has decremented its ready counter, leading to the ready counter going + * down from the number of online cpus without going through the coupled idle + * state. + * + * Returns 0 if the counter was decremented successfully, -EINVAL if the ready + * counter was equal to the number of online cpus. + */ +static +inline int cpuidle_coupled_set_not_ready(struct cpuidle_coupled *coupled) +{ + int all; + int ret; + + all = coupled->online_count || (coupled->online_count << WAITING_BITS); + ret = atomic_add_unless(&coupled->ready_waiting_counts, + -MAX_WAITING_CPUS, all); + + return ret ? 0 : -EINVAL; +} + +/** + * cpuidle_coupled_no_cpus_ready - check if no cpus in a coupled set are ready + * @coupled: the struct coupled that contains the current cpu + * + * Returns true if all of the cpus in a coupled set are out of the ready loop. + */ +static inline int cpuidle_coupled_no_cpus_ready(struct cpuidle_coupled *coupled) +{ + int r = atomic_read(&coupled->ready_waiting_counts) >> WAITING_BITS; + return r == 0; +} + +/** + * cpuidle_coupled_cpus_ready - check if all cpus in a coupled set are ready + * @coupled: the struct coupled that contains the current cpu + * + * Returns true if all cpus coupled to this target state are in the ready loop + */ +static inline bool cpuidle_coupled_cpus_ready(struct cpuidle_coupled *coupled) +{ + int r = atomic_read(&coupled->ready_waiting_counts) >> WAITING_BITS; + return r == coupled->online_count; +} + +/** + * cpuidle_coupled_cpus_waiting - check if all cpus in a coupled set are waiting + * @coupled: the struct coupled that contains the current cpu + * + * Returns true if all cpus coupled to this target state are in the wait loop + */ +static inline bool cpuidle_coupled_cpus_waiting(struct cpuidle_coupled *coupled) +{ + int w = atomic_read(&coupled->ready_waiting_counts) & WAITING_MASK; + return w == coupled->online_count; +} + +/** + * cpuidle_coupled_no_cpus_waiting - check if no cpus in coupled set are waiting + * @coupled: the struct coupled that contains the current cpu + * + * Returns true if all of the cpus in a coupled set are out of the waiting loop. + */ +static inline int cpuidle_coupled_no_cpus_waiting(struct cpuidle_coupled *coupled) +{ + int w = atomic_read(&coupled->ready_waiting_counts) & WAITING_MASK; + return w == 0; +} + +/** + * cpuidle_coupled_get_state - determine the deepest idle state + * @dev: struct cpuidle_device for this cpu + * @coupled: the struct coupled that contains the current cpu + * + * Returns the deepest idle state that all coupled cpus can enter + */ +static inline int cpuidle_coupled_get_state(struct cpuidle_device *dev, + struct cpuidle_coupled *coupled) +{ + int i; + int state = INT_MAX; + + /* + * Read barrier ensures that read of requested_state is ordered after + * reads of ready_count. Matches the write barriers + * cpuidle_set_state_waiting. + */ + smp_rmb(); + + for_each_cpu_mask(i, coupled->coupled_cpus) + if (cpu_online(i) && coupled->requested_state[i] < state) + state = coupled->requested_state[i]; + + return state; +} + +static void cpuidle_coupled_poked(void *info) +{ + int cpu = (unsigned long)info; + cpumask_clear_cpu(cpu, &cpuidle_coupled_poked_mask); +} + +/** + * cpuidle_coupled_poke - wake up a cpu that may be waiting + * @cpu: target cpu + * + * Ensures that the target cpu exits it's waiting idle state (if it is in it) + * and will see updates to waiting_count before it re-enters it's waiting idle + * state. + * + * If cpuidle_coupled_poked_mask is already set for the target cpu, that cpu + * either has or will soon have a pending IPI that will wake it out of idle, + * or it is currently processing the IPI and is not in idle. + */ +static void cpuidle_coupled_poke(int cpu) +{ + struct call_single_data *csd = &per_cpu(cpuidle_coupled_poke_cb, cpu); + + if (!cpumask_test_and_set_cpu(cpu, &cpuidle_coupled_poked_mask)) + __smp_call_function_single(cpu, csd, 0); +} + +/** + * cpuidle_coupled_poke_others - wake up all other cpus that may be waiting + * @dev: struct cpuidle_device for this cpu + * @coupled: the struct coupled that contains the current cpu + * + * Calls cpuidle_coupled_poke on all other online cpus. + */ +static void cpuidle_coupled_poke_others(int this_cpu, + struct cpuidle_coupled *coupled) +{ + int cpu; + + for_each_cpu_mask(cpu, coupled->coupled_cpus) + if (cpu != this_cpu && cpu_online(cpu)) + cpuidle_coupled_poke(cpu); +} + +/** + * cpuidle_coupled_set_waiting - mark this cpu as in the wait loop + * @dev: struct cpuidle_device for this cpu + * @coupled: the struct coupled that contains the current cpu + * @next_state: the index in drv->states of the requested state for this cpu + * + * Updates the requested idle state for the specified cpuidle device, + * poking all coupled cpus out of idle if necessary to let them see the new + * state. + */ +static void cpuidle_coupled_set_waiting(int cpu, + struct cpuidle_coupled *coupled, int next_state) +{ + int w; + + coupled->requested_state[cpu] = next_state; + + /* + * If this is the last cpu to enter the waiting state, poke + * all the other cpus out of their waiting state so they can + * enter a deeper state. This can race with one of the cpus + * exiting the waiting state due to an interrupt and + * decrementing waiting_count, see comment below. + * + * The atomic_inc_return provides a write barrier to order the write + * to requested_state with the later write that increments ready_count. + */ + w = atomic_inc_return(&coupled->ready_waiting_counts) & WAITING_MASK; + if (w == coupled->online_count) + cpuidle_coupled_poke_others(cpu, coupled); +} + +/** + * cpuidle_coupled_set_not_waiting - mark this cpu as leaving the wait loop + * @dev: struct cpuidle_device for this cpu + * @coupled: the struct coupled that contains the current cpu + * + * Removes the requested idle state for the specified cpuidle device. + */ +static void cpuidle_coupled_set_not_waiting(int cpu, + struct cpuidle_coupled *coupled) +{ + /* + * Decrementing waiting count can race with incrementing it in + * cpuidle_coupled_set_waiting, but that's OK. Worst case, some + * cpus will increment ready_count and then spin until they + * notice that this cpu has cleared it's requested_state. + */ + atomic_dec(&coupled->ready_waiting_counts); + + coupled->requested_state[cpu] = CPUIDLE_COUPLED_NOT_IDLE; +} + +/** + * cpuidle_coupled_set_done - mark this cpu as leaving the ready loop + * @cpu: the current cpu + * @coupled: the struct coupled that contains the current cpu + * + * Marks this cpu as no longer in the ready and waiting loops. Decrements + * the waiting count first to prevent another cpu looping back in and seeing + * this cpu as waiting just before it exits idle. + */ +static void cpuidle_coupled_set_done(int cpu, struct cpuidle_coupled *coupled) +{ + cpuidle_coupled_set_not_waiting(cpu, coupled); + atomic_sub(MAX_WAITING_CPUS, &coupled->ready_waiting_counts); +} + +/** + * cpuidle_coupled_clear_pokes - spin until the poke interrupt is processed + * @cpu - this cpu + * + * Turns on interrupts and spins until any outstanding poke interrupts have + * been processed and the poke bit has been cleared. + * + * Other interrupts may also be processed while interrupts are enabled, so + * need_resched() must be tested after turning interrupts off again to make sure + * the interrupt didn't schedule work that should take the cpu out of idle. + * + * Returns 0 if need_resched was false, -EINTR if need_resched was true. + */ +static int cpuidle_coupled_clear_pokes(int cpu) +{ + local_irq_enable(); + while (cpumask_test_cpu(cpu, &cpuidle_coupled_poked_mask)) + cpu_relax(); + local_irq_disable(); + + return need_resched() ? -EINTR : 0; +} + +/** + * cpuidle_enter_state_coupled - attempt to enter a state with coupled cpus + * @dev: struct cpuidle_device for the current cpu + * @drv: struct cpuidle_driver for the platform + * @next_state: index of the requested state in drv->states + * + * Coordinate with coupled cpus to enter the target state. This is a two + * stage process. In the first stage, the cpus are operating independently, + * and may call into cpuidle_enter_state_coupled at completely different times. + * To save as much power as possible, the first cpus to call this function will + * go to an intermediate state (the cpuidle_device's safe state), and wait for + * all the other cpus to call this function. Once all coupled cpus are idle, + * the second stage will start. Each coupled cpu will spin until all cpus have + * guaranteed that they will call the target_state. + * + * This function must be called with interrupts disabled. It may enable + * interrupts while preparing for idle, and it will always return with + * interrupts enabled. + */ +int cpuidle_enter_state_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int next_state) +{ + int entered_state = -1; + struct cpuidle_coupled *coupled = dev->coupled; + + if (!coupled) + return -EINVAL; + + while (coupled->prevent) { + if (cpuidle_coupled_clear_pokes(dev->cpu)) { + local_irq_enable(); + return entered_state; + } + entered_state = cpuidle_enter_state(dev, drv, + dev->safe_state_index); + } + + /* Read barrier ensures online_count is read after prevent is cleared */ + smp_rmb(); + + cpuidle_coupled_set_waiting(dev->cpu, coupled, next_state); + +retry: + /* + * Wait for all coupled cpus to be idle, using the deepest state + * allowed for a single cpu. + */ + while (!cpuidle_coupled_cpus_waiting(coupled)) { + if (cpuidle_coupled_clear_pokes(dev->cpu)) { + cpuidle_coupled_set_not_waiting(dev->cpu, coupled); + goto out; + } + + if (coupled->prevent) { + cpuidle_coupled_set_not_waiting(dev->cpu, coupled); + goto out; + } + + entered_state = cpuidle_enter_state(dev, drv, + dev->safe_state_index); + } + + if (cpuidle_coupled_clear_pokes(dev->cpu)) { + cpuidle_coupled_set_not_waiting(dev->cpu, coupled); + goto out; + } + + /* + * All coupled cpus are probably idle. There is a small chance that + * one of the other cpus just became active. Increment the ready count, + * and spin until all coupled cpus have incremented the counter. Once a + * cpu has incremented the ready counter, it cannot abort idle and must + * spin until either all cpus have incremented the ready counter, or + * another cpu leaves idle and decrements the waiting counter. + */ + + cpuidle_coupled_set_ready(coupled); + while (!cpuidle_coupled_cpus_ready(coupled)) { + /* Check if any other cpus bailed out of idle. */ + if (!cpuidle_coupled_cpus_waiting(coupled)) + if (!cpuidle_coupled_set_not_ready(coupled)) + goto retry; + + cpu_relax(); + } + + /* all cpus have acked the coupled state */ + next_state = cpuidle_coupled_get_state(dev, coupled); + + entered_state = cpuidle_enter_state(dev, drv, next_state); + + cpuidle_coupled_set_done(dev->cpu, coupled); + +out: + /* + * Normal cpuidle states are expected to return with irqs enabled. + * That leads to an inefficiency where a cpu receiving an interrupt + * that brings it out of idle will process that interrupt before + * exiting the idle enter function and decrementing ready_count. All + * other cpus will need to spin waiting for the cpu that is processing + * the interrupt. If the driver returns with interrupts disabled, + * all other cpus will loop back into the safe idle state instead of + * spinning, saving power. + * + * Calling local_irq_enable here allows coupled states to return with + * interrupts disabled, but won't cause problems for drivers that + * exit with interrupts enabled. + */ + local_irq_enable(); + + /* + * Wait until all coupled cpus have exited idle. There is no risk that + * a cpu exits and re-enters the ready state because this cpu has + * already decremented its waiting_count. + */ + while (!cpuidle_coupled_no_cpus_ready(coupled)) + cpu_relax(); + + return entered_state; +} + +static void cpuidle_coupled_update_online_cpus(struct cpuidle_coupled *coupled) +{ + cpumask_t cpus; + cpumask_and(&cpus, cpu_online_mask, &coupled->coupled_cpus); + coupled->online_count = cpumask_weight(&cpus); +} + +/** + * cpuidle_coupled_register_device - register a coupled cpuidle device + * @dev: struct cpuidle_device for the current cpu + * + * Called from cpuidle_register_device to handle coupled idle init. Finds the + * cpuidle_coupled struct for this set of coupled cpus, or creates one if none + * exists yet. + */ +int cpuidle_coupled_register_device(struct cpuidle_device *dev) +{ + int cpu; + struct cpuidle_device *other_dev; + struct call_single_data *csd; + struct cpuidle_coupled *coupled; + + if (cpumask_empty(&dev->coupled_cpus)) + return 0; + + for_each_cpu_mask(cpu, dev->coupled_cpus) { + other_dev = per_cpu(cpuidle_devices, cpu); + if (other_dev && other_dev->coupled) { + coupled = other_dev->coupled; + goto have_coupled; + } + } + + /* No existing coupled info found, create a new one */ + coupled = kzalloc(sizeof(struct cpuidle_coupled), GFP_KERNEL); + if (!coupled) + return -ENOMEM; + + coupled->coupled_cpus = dev->coupled_cpus; + +have_coupled: + dev->coupled = coupled; + if (WARN_ON(!cpumask_equal(&dev->coupled_cpus, &coupled->coupled_cpus))) + coupled->prevent++; + + cpuidle_coupled_update_online_cpus(coupled); + + coupled->refcnt++; + + csd = &per_cpu(cpuidle_coupled_poke_cb, dev->cpu); + csd->func = cpuidle_coupled_poked; + csd->info = (void *)(unsigned long)dev->cpu; + + return 0; +} + +/** + * cpuidle_coupled_unregister_device - unregister a coupled cpuidle device + * @dev: struct cpuidle_device for the current cpu + * + * Called from cpuidle_unregister_device to tear down coupled idle. Removes the + * cpu from the coupled idle set, and frees the cpuidle_coupled_info struct if + * this was the last cpu in the set. + */ +void cpuidle_coupled_unregister_device(struct cpuidle_device *dev) +{ + struct cpuidle_coupled *coupled = dev->coupled; + + if (cpumask_empty(&dev->coupled_cpus)) + return; + + if (--coupled->refcnt) + kfree(coupled); + dev->coupled = NULL; +} + +/** + * cpuidle_coupled_prevent_idle - prevent cpus from entering a coupled state + * @coupled: the struct coupled that contains the cpu that is changing state + * + * Disables coupled cpuidle on a coupled set of cpus. Used to ensure that + * cpu_online_mask doesn't change while cpus are coordinating coupled idle. + */ +static void cpuidle_coupled_prevent_idle(struct cpuidle_coupled *coupled) +{ + int cpu = get_cpu(); + + /* Force all cpus out of the waiting loop. */ + coupled->prevent++; + cpuidle_coupled_poke_others(cpu, coupled); + put_cpu(); + while (!cpuidle_coupled_no_cpus_waiting(coupled)) + cpu_relax(); +} + +/** + * cpuidle_coupled_allow_idle - allows cpus to enter a coupled state + * @coupled: the struct coupled that contains the cpu that is changing state + * + * Enables coupled cpuidle on a coupled set of cpus. Used to ensure that + * cpu_online_mask doesn't change while cpus are coordinating coupled idle. + */ +static void cpuidle_coupled_allow_idle(struct cpuidle_coupled *coupled) +{ + int cpu = get_cpu(); + + /* + * Write barrier ensures readers see the new online_count when they + * see prevent == 0. + */ + smp_wmb(); + coupled->prevent--; + /* Force cpus out of the prevent loop. */ + cpuidle_coupled_poke_others(cpu, coupled); + put_cpu(); +} + +/** + * cpuidle_coupled_cpu_notify - notifier called during hotplug transitions + * @nb: notifier block + * @action: hotplug transition + * @hcpu: target cpu number + * + * Called when a cpu is brought on or offline using hotplug. Updates the + * coupled cpu set appropriately + */ +static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, + unsigned long action, void *hcpu) +{ + int cpu = (unsigned long)hcpu; + struct cpuidle_device *dev; + + mutex_lock(&cpuidle_lock); + + dev = per_cpu(cpuidle_devices, cpu); + if (!dev->coupled) + goto out; + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + case CPU_DOWN_PREPARE: + cpuidle_coupled_prevent_idle(dev->coupled); + break; + case CPU_ONLINE: + case CPU_DEAD: + cpuidle_coupled_update_online_cpus(dev->coupled); + /* Fall through */ + case CPU_UP_CANCELED: + case CPU_DOWN_FAILED: + cpuidle_coupled_allow_idle(dev->coupled); + break; + } + +out: + mutex_unlock(&cpuidle_lock); + return NOTIFY_OK; +} + +static struct notifier_block cpuidle_coupled_cpu_notifier = { + .notifier_call = cpuidle_coupled_cpu_notify, +}; + +static int __init cpuidle_coupled_init(void) +{ + return register_cpu_notifier(&cpuidle_coupled_cpu_notifier); +} +core_initcall(cpuidle_coupled_init); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 4540672a2e1c..e81cfda295a5 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -171,7 +171,11 @@ int cpuidle_idle_call(void) trace_power_start_rcuidle(POWER_CSTATE, next_state, dev->cpu); trace_cpu_idle_rcuidle(next_state, dev->cpu); - entered_state = cpuidle_enter_state(dev, drv, next_state); + if (cpuidle_state_is_coupled(dev, drv, next_state)) + entered_state = cpuidle_enter_state_coupled(dev, drv, + next_state); + else + entered_state = cpuidle_enter_state(dev, drv, next_state); trace_power_end_rcuidle(dev->cpu); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); @@ -407,9 +411,16 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) if (ret) goto err_sysfs; + ret = cpuidle_coupled_register_device(dev); + if (ret) + goto err_coupled; + dev->registered = 1; return 0; +err_coupled: + cpuidle_remove_sysfs(cpu_dev); + wait_for_completion(&dev->kobj_unregister); err_sysfs: list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; @@ -464,6 +475,8 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) wait_for_completion(&dev->kobj_unregister); per_cpu(cpuidle_devices, dev->cpu) = NULL; + cpuidle_coupled_unregister_device(dev); + cpuidle_resume_and_unlock(); module_put(cpuidle_driver->owner); diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h index d8a3ccce8281..76e7f696ad8c 100644 --- a/drivers/cpuidle/cpuidle.h +++ b/drivers/cpuidle/cpuidle.h @@ -32,4 +32,34 @@ extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device); extern int cpuidle_add_sysfs(struct device *dev); extern void cpuidle_remove_sysfs(struct device *dev); +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED +bool cpuidle_state_is_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int state); +int cpuidle_enter_state_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int next_state); +int cpuidle_coupled_register_device(struct cpuidle_device *dev); +void cpuidle_coupled_unregister_device(struct cpuidle_device *dev); +#else +static inline bool cpuidle_state_is_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int state) +{ + return false; +} + +static inline int cpuidle_enter_state_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int next_state) +{ + return -1; +} + +static inline int cpuidle_coupled_register_device(struct cpuidle_device *dev) +{ + return 0; +} + +static inline void cpuidle_coupled_unregister_device(struct cpuidle_device *dev) +{ +} +#endif + #endif /* __DRIVER_CPUIDLE_H */ diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e03..603844835bc7 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -57,6 +57,7 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ +#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) @@ -100,6 +101,12 @@ struct cpuidle_device { struct list_head device_list; struct kobject kobj; struct completion kobj_unregister; + +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED + int safe_state_index; + cpumask_t coupled_cpus; + struct cpuidle_coupled *coupled; +#endif }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -- GitLab From 20ff51a36b2cd25ee7eb3216b6d02b68935435ba Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 7 May 2012 17:57:42 -0700 Subject: [PATCH 0080/5711] cpuidle: coupled: add parallel barrier function Adds cpuidle_coupled_parallel_barrier, which can be used by coupled cpuidle state enter functions to handle resynchronization after determining if any cpu needs to abort. The normal use case will be: static bool abort_flag; static atomic_t abort_barrier; int arch_cpuidle_enter(struct cpuidle_device *dev, ...) { if (arch_turn_off_irq_controller()) { /* returns an error if an irq is pending and would be lost if idle continued and turned off power */ abort_flag = true; } cpuidle_coupled_parallel_barrier(dev, &abort_barrier); if (abort_flag) { /* One of the cpus didn't turn off it's irq controller */ arch_turn_on_irq_controller(); return -EINTR; } /* continue with idle */ ... } This will cause all cpus to abort idle together if one of them needs to abort. Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Colin Cross Signed-off-by: Len Brown --- drivers/cpuidle/coupled.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/cpuidle.h | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index aab6bba8daec..2c9bf2692232 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -129,6 +129,43 @@ static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb); */ static cpumask_t cpuidle_coupled_poked_mask; +/** + * cpuidle_coupled_parallel_barrier - synchronize all online coupled cpus + * @dev: cpuidle_device of the calling cpu + * @a: atomic variable to hold the barrier + * + * No caller to this function will return from this function until all online + * cpus in the same coupled group have called this function. Once any caller + * has returned from this function, the barrier is immediately available for + * reuse. + * + * The atomic variable a must be initialized to 0 before any cpu calls + * this function, will be reset to 0 before any cpu returns from this function. + * + * Must only be called from within a coupled idle state handler + * (state.enter when state.flags has CPUIDLE_FLAG_COUPLED set). + * + * Provides full smp barrier semantics before and after calling. + */ +void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a) +{ + int n = dev->coupled->online_count; + + smp_mb__before_atomic_inc(); + atomic_inc(a); + + while (atomic_read(a) < n) + cpu_relax(); + + if (atomic_inc_return(a) == n * 2) { + atomic_set(a, 0); + return; + } + + while (atomic_read(a) > n) + cpu_relax(); +} + /** * cpuidle_state_is_coupled - check if a state is part of a coupled set * @dev: struct cpuidle_device for the current cpu diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 603844835bc7..5ab7183313ce 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -183,6 +183,10 @@ static inline int cpuidle_play_dead(void) {return -ENODEV; } #endif +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED +void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a); +#endif + /****************************** * CPUIDLE GOVERNOR INTERFACE * ******************************/ -- GitLab From b9c7aff481f19dd655ae3ce6513817d625e2d47c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 29 May 2012 11:18:51 -0700 Subject: [PATCH 0081/5711] drivers/thermal/spear_thermal.c: add Device Tree probing capability SPEAr platforms now support DT and so must convert all drivers to support DT. This patch adds DT probing support for SPEAr thermal sensor driver and updates its documentation too. Also, as SPEAr is the only user of this driver and is only available with DT, make this an only DT driver. So, platform_data is completely removed and passed via DT now. Signed-off-by: Viresh Kumar Cc: Dan Carpenter Reviewed-by: Vincenzo Frascino Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- .../bindings/thermal/spear-thermal.txt | 14 ++++++++++ drivers/thermal/Kconfig | 1 + drivers/thermal/spear_thermal.c | 26 ++++++++++++------- include/linux/platform_data/spear_thermal.h | 26 ------------------- 4 files changed, 31 insertions(+), 36 deletions(-) create mode 100644 Documentation/devicetree/bindings/thermal/spear-thermal.txt delete mode 100644 include/linux/platform_data/spear_thermal.h diff --git a/Documentation/devicetree/bindings/thermal/spear-thermal.txt b/Documentation/devicetree/bindings/thermal/spear-thermal.txt new file mode 100644 index 000000000000..93e3b67c102d --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/spear-thermal.txt @@ -0,0 +1,14 @@ +* SPEAr Thermal + +Required properties: +- compatible : "st,thermal-spear1340" +- reg : Address range of the thermal registers +- st,thermal-flags: flags used to enable thermal sensor + +Example: + + thermal@fc000000 { + compatible = "st,thermal-spear1340"; + reg = <0xfc000000 0x1000>; + st,thermal-flags = <0x7000>; + }; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 514a691abea0..3ab2bd540b54 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -23,6 +23,7 @@ config SPEAR_THERMAL bool "SPEAr thermal sensor driver" depends on THERMAL depends on PLAT_SPEAR + depends on OF help Enable this to plug the SPEAr thermal sensor driver into the Linux thermal framework diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index c2e32df3b164..ca40d36d0ba8 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -20,9 +20,9 @@ #include #include #include +#include #include #include -#include #include #define MD_FACTOR 1000 @@ -103,21 +103,20 @@ static int spear_thermal_probe(struct platform_device *pdev) { struct thermal_zone_device *spear_thermal = NULL; struct spear_thermal_dev *stdev; - struct spear_thermal_pdata *pdata; - int ret = 0; + struct device_node *np = pdev->dev.of_node; struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + int ret = 0, val; + + if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { + dev_err(&pdev->dev, "Failed: DT Pdata not passed\n"); + return -EINVAL; + } if (!stres) { dev_err(&pdev->dev, "memory resource missing\n"); return -ENODEV; } - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "platform data is NULL\n"); - return -EINVAL; - } - stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); if (!stdev) { dev_err(&pdev->dev, "kzalloc fail\n"); @@ -144,7 +143,7 @@ static int spear_thermal_probe(struct platform_device *pdev) goto put_clk; } - stdev->flags = pdata->thermal_flags; + stdev->flags = val; writel_relaxed(stdev->flags, stdev->thermal_base); spear_thermal = thermal_zone_device_register("spear_thermal", 0, @@ -189,6 +188,12 @@ static int spear_thermal_exit(struct platform_device *pdev) return 0; } +static const struct of_device_id spear_thermal_id_table[] = { + { .compatible = "st,thermal-spear1340" }, + {} +}; +MODULE_DEVICE_TABLE(of, spear_thermal_id_table); + static struct platform_driver spear_thermal_driver = { .probe = spear_thermal_probe, .remove = spear_thermal_exit, @@ -196,6 +201,7 @@ static struct platform_driver spear_thermal_driver = { .name = "spear_thermal", .owner = THIS_MODULE, .pm = &spear_thermal_pm_ops, + .of_match_table = of_match_ptr(spear_thermal_id_table), }, }; diff --git a/include/linux/platform_data/spear_thermal.h b/include/linux/platform_data/spear_thermal.h deleted file mode 100644 index 724f2e1cbbcb..000000000000 --- a/include/linux/platform_data/spear_thermal.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPEAr thermal driver platform data. - * - * Copyright (C) 2011-2012 ST Microelectronics - * Author: Vincenzo Frascino - * - * 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 SPEAR_THERMAL_H -#define SPEAR_THERMAL_H - -/* SPEAr Thermal Sensor Platform Data */ -struct spear_thermal_pdata { - /* flags used to enable thermal sensor */ - unsigned int thermal_flags; -}; - -#endif /* SPEAR_THERMAL_H */ -- GitLab From 30dfebf34b9930277d83b25ec740510007cc4c6d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 1 Jun 2012 15:21:23 +0200 Subject: [PATCH 0082/5711] drm/i915: extract object active state flushing code Both busy_ioctl and the new wait_ioct need to do the same dance (or at least should). Some slight changes: - busy_ioctl now unconditionally checks for olr. Before emitting a require flush would have prevent the olr check and hence required a second call to the busy ioctl to really emit the request. - the timeout wait now also retires request. Not really required for abi-reasons, but makes a notch more sense imo. I've tested this by pimping the i-g-t test some more and also checking the polling behviour of the wait_rendering_timeout ioctl versus what busy_ioctl returns. v2: Too many people complained about unplug, new color is flush_active. v3: Kill the comment about the unplug moniker. v4: s/un-active/inactive/ Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 61 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a20ac438b8ef..af67803e635f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2029,6 +2029,31 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) return 0; } +/** + * Ensures that an object will eventually get non-busy by flushing any required + * write domains, emitting any outstanding lazy request and retiring and + * completed requests. + */ +static int +i915_gem_object_flush_active(struct drm_i915_gem_object *obj) +{ + int ret; + + if (obj->active) { + ret = i915_gem_object_flush_gpu_write_domain(obj); + if (ret) + return ret; + + ret = i915_gem_check_olr(obj->ring, + obj->last_rendering_seqno); + if (ret) + return ret; + i915_gem_retire_requests_ring(obj->ring); + } + + return 0; +} + /** * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT * @DRM_IOCTL_ARGS: standard ioctl arguments @@ -2073,11 +2098,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) return -ENOENT; } - /* Need to make sure the object is flushed first. This non-obvious - * flush is required to enforce that (active && !olr) == no wait - * necessary. - */ - ret = i915_gem_object_flush_gpu_write_domain(obj); + /* Need to make sure the object gets inactive eventually. */ + ret = i915_gem_object_flush_active(obj); if (ret) goto out; @@ -2089,10 +2111,6 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (seqno == 0) goto out; - ret = i915_gem_check_olr(ring, seqno); - if (ret) - goto out; - /* Do this after OLR check to make sure we make forward progress polling * on this IOCTL with a 0 timeout (like busy ioctl) */ @@ -3330,30 +3348,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * become non-busy without any further actions, therefore emit any * necessary flushes here. */ - args->busy = obj->active; - if (args->busy) { - /* Unconditionally flush objects, even when the gpu still uses this - * object. Userspace calling this function indicates that it wants to - * use this buffer rather sooner than later, so issuing the required - * flush earlier is beneficial. - */ - if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { - ret = i915_gem_flush_ring(obj->ring, - 0, obj->base.write_domain); - } else { - ret = i915_gem_check_olr(obj->ring, - obj->last_rendering_seqno); - } + ret = i915_gem_object_flush_active(obj); - /* Update the active list for the hardware's current position. - * Otherwise this only updates on a delayed timer or when irqs - * are actually unmasked, and our working set ends up being - * larger than required. - */ - i915_gem_retire_requests_ring(obj->ring); - - args->busy = obj->active; - } + args->busy = obj->active; drm_gem_object_unreference(&obj->base); unlock: -- GitLab From 92a9f14b8b8e5ade5b49bcd6b95fc05f85a39e90 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 30 May 2012 21:16:16 +0100 Subject: [PATCH 0083/5711] Fix comment typo multipy -> multiply Signed-off-by: Ralf Baechle Signed-off-by: Jiri Kosina --- drivers/input/misc/cma3000_d0x.c | 2 +- sound/oss/vwsnd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index a3735a01e9fd..df9b756594f8 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -58,7 +58,7 @@ /* * Bit weights in mg for bit 0, other bits need - * multipy factor 2^n. Eight bit is the sign bit. + * multiply factor 2^n. Eight bit is the sign bit. */ #define BIT_TO_2G 18 #define BIT_TO_8G 71 diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 643f1113b1d8..7e814a5c3677 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -438,7 +438,7 @@ static __inline__ void li_writeb(lithium_t *lith, int off, unsigned char val) * * Observe that (mask & -mask) is (1 << low_set_bit_of(mask)). * As long as mask is constant, we trust the compiler will change the - * multipy and divide into shifts. + * multiply and divide into shifts. */ #define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask)) -- GitLab From d2582a7afcf732cf234adbf14aa7d11a08e30e09 Mon Sep 17 00:00:00 2001 From: Kazuo Moriwaka Date: Mon, 28 May 2012 12:06:44 +0900 Subject: [PATCH 0084/5711] Doc: document max raw dev number Documenting description about max minor number of raw devices. Signed-off-by: Kazuo Moriwaka Signed-off-by: Jiri Kosina --- Documentation/devices.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 47a154f30290..b6251cca9263 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -2416,6 +2416,8 @@ Your cooperation is appreciated. 1 = /dev/raw/raw1 First raw I/O device 2 = /dev/raw/raw2 Second raw I/O device ... + max minor number of raw device is set by kernel config + MAX_RAW_DEVS or raw module parameter 'max_raw_devs' 163 char -- GitLab From 0bf79ef2c303cc70d036c9fb355aeb468e8efb62 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:52 -0600 Subject: [PATCH 0085/5711] ASoC: wm8903: init GPIOs during I2C probe not codec probe This allows the GPIOs to be available as soon as the I2C device has probed, which in turn enables machine drivers to request the GPIOs in their probe(), rather than deferring this to their ASoC machine init function, i.e. after the whole sound card has been constructed, and hence the WM8903 codec is available. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 48 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 86b8a2926591..f6a3fc5f09c0 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2,7 +2,7 @@ * wm8903.c -- WM8903 ALSA SoC Audio driver * * Copyright 2008 Wolfson Microelectronics - * Copyright 2011 NVIDIA, Inc. + * Copyright 2011-2012 NVIDIA, Inc. * * Author: Mark Brown * @@ -116,6 +116,7 @@ static const struct reg_default wm8903_reg_defaults[] = { struct wm8903_priv { struct wm8903_platform_data *pdata; + struct device *dev; struct snd_soc_codec *codec; struct regmap *regmap; @@ -1774,7 +1775,6 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; unsigned int mask, val; int ret; @@ -1782,8 +1782,8 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | WM8903_GP1_DIR; - ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - mask, val); + ret = regmap_update_bits(wm8903->regmap, + WM8903_GPIO_CONTROL_1 + offset, mask, val); if (ret < 0) return ret; @@ -1793,10 +1793,9 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) { struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - int reg; + unsigned int reg; - reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); + regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; } @@ -1805,7 +1804,6 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; unsigned int mask, val; int ret; @@ -1813,8 +1811,8 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | (value << WM8903_GP2_LVL_SHIFT); - ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - mask, val); + ret = regmap_update_bits(wm8903->regmap, + WM8903_GPIO_CONTROL_1 + offset, mask, val); if (ret < 0) return ret; @@ -1824,11 +1822,10 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - WM8903_GP1_LVL_MASK, - !!value << WM8903_GP1_LVL_SHIFT); + regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, + WM8903_GP1_LVL_MASK, + !!value << WM8903_GP1_LVL_SHIFT); } static struct gpio_chip wm8903_template_chip = { @@ -1842,15 +1839,14 @@ static struct gpio_chip wm8903_template_chip = { .can_sleep = 1, }; -static void wm8903_init_gpio(struct snd_soc_codec *codec) +static void wm8903_init_gpio(struct wm8903_priv *wm8903) { - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); struct wm8903_platform_data *pdata = wm8903->pdata; int ret; wm8903->gpio_chip = wm8903_template_chip; wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; - wm8903->gpio_chip.dev = codec->dev; + wm8903->gpio_chip.dev = wm8903->dev; if (pdata->gpio_base) wm8903->gpio_chip.base = pdata->gpio_base; @@ -1859,24 +1855,23 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec) ret = gpiochip_add(&wm8903->gpio_chip); if (ret != 0) - dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); + dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); } -static void wm8903_free_gpio(struct snd_soc_codec *codec) +static void wm8903_free_gpio(struct wm8903_priv *wm8903) { - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); int ret; ret = gpiochip_remove(&wm8903->gpio_chip); if (ret != 0) - dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); + dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); } #else -static void wm8903_init_gpio(struct snd_soc_codec *codec) +static void wm8903_init_gpio(struct wm8903_priv *wm8903) { } -static void wm8903_free_gpio(struct snd_soc_codec *codec) +static void wm8903_free_gpio(struct wm8903_priv *wm8903) { } #endif @@ -2000,8 +1995,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); - wm8903_init_gpio(codec); - return ret; } @@ -2010,7 +2003,6 @@ static int wm8903_remove(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - wm8903_free_gpio(codec); wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); if (wm8903->irq) free_irq(wm8903->irq, codec); @@ -2130,6 +2122,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, GFP_KERNEL); if (wm8903 == NULL) return -ENOMEM; + wm8903->dev = &i2c->dev; wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); if (IS_ERR(wm8903->regmap)) { @@ -2189,6 +2182,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, /* Reset the device */ regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); + wm8903_init_gpio(wm8903); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8903, &wm8903_dai, 1); if (ret != 0) @@ -2204,6 +2199,7 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) { struct wm8903_priv *wm8903 = i2c_get_clientdata(client); + wm8903_free_gpio(wm8903); regmap_exit(wm8903->regmap); snd_soc_unregister_codec(&client->dev); -- GitLab From f51022f1aedc4d1a02d0dfa8fde47f6a8291f618 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:54 -0600 Subject: [PATCH 0086/5711] ASoC: tegra+wm8903: move all GPIO setup into probe Now that deferred probe exists, we can parse device tree and request GPIOs from probe(), rather than deferring this to the DAI link's init(). Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 162 +++++++++++++++++---------------- 1 file changed, 83 insertions(+), 79 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0b0df49d9d33..a8a3103ab4cb 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -245,80 +245,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = &machine->pdata; - struct device_node *np = card->dev->of_node; - int ret; - - if (card->dev->platform_data) { - memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); - } else if (np) { - /* - * This part must be in init() rather than probe() in order to - * guarantee that the WM8903 has been probed, and hence its - * GPIO controller registered, which is a pre-condition for - * of_get_named_gpio() to be able to map the phandles in the - * properties to the controller node. Given this, all - * pdata handling is in init() for consistency. - */ - pdata->gpio_spkr_en = of_get_named_gpio(np, - "nvidia,spkr-en-gpios", 0); - pdata->gpio_hp_mute = of_get_named_gpio(np, - "nvidia,hp-mute-gpios", 0); - pdata->gpio_hp_det = of_get_named_gpio(np, - "nvidia,hp-det-gpios", 0); - pdata->gpio_int_mic_en = of_get_named_gpio(np, - "nvidia,int-mic-en-gpios", 0); - pdata->gpio_ext_mic_en = of_get_named_gpio(np, - "nvidia,ext-mic-en-gpios", 0); - } else { - dev_err(card->dev, "No platform data supplied\n"); - return -EINVAL; - } - - if (gpio_is_valid(pdata->gpio_spkr_en)) { - ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); - if (ret) { - dev_err(card->dev, "cannot get spkr_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_SPKR_EN; - - gpio_direction_output(pdata->gpio_spkr_en, 0); - } - - if (gpio_is_valid(pdata->gpio_hp_mute)) { - ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); - if (ret) { - dev_err(card->dev, "cannot get hp_mute gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_HP_MUTE; - - gpio_direction_output(pdata->gpio_hp_mute, 1); - } - - if (gpio_is_valid(pdata->gpio_int_mic_en)) { - ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); - if (ret) { - dev_err(card->dev, "cannot get int_mic_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_INT_MIC_EN; - - /* Disable int mic; enable signal is active-high */ - gpio_direction_output(pdata->gpio_int_mic_en, 0); - } - - if (gpio_is_valid(pdata->gpio_ext_mic_en)) { - ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); - if (ret) { - dev_err(card->dev, "cannot get ext_mic_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_EXT_MIC_EN; - - /* Enable ext mic; enable signal is active-low */ - gpio_direction_output(pdata->gpio_ext_mic_en, 0); - } if (gpio_is_valid(pdata->gpio_hp_det)) { tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; @@ -372,8 +298,10 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = { static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_card *card = &snd_soc_tegra_wm8903; struct tegra_wm8903 *machine; + struct tegra_wm8903_platform_data *pdata; int ret; if (!pdev->dev.platform_data && !pdev->dev.of_node) { @@ -388,12 +316,42 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) ret = -ENOMEM; goto err; } + pdata = &machine->pdata; card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - if (pdev->dev.of_node) { + if (pdev->dev.platform_data) { + memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); + } else if (np) { + pdata->gpio_spkr_en = of_get_named_gpio(np, + "nvidia,spkr-en-gpios", 0); + if (pdata->gpio_spkr_en == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_hp_mute = of_get_named_gpio(np, + "nvidia,hp-mute-gpios", 0); + if (pdata->gpio_hp_mute == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_hp_det = of_get_named_gpio(np, + "nvidia,hp-det-gpios", 0); + if (pdata->gpio_hp_det == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_int_mic_en = of_get_named_gpio(np, + "nvidia,int-mic-en-gpios", 0); + if (pdata->gpio_int_mic_en == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_ext_mic_en = of_get_named_gpio(np, + "nvidia,ext-mic-en-gpios", 0); + if (pdata->gpio_ext_mic_en == -ENODEV) + return -EPROBE_DEFER; + } + + if (np) { ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) goto err; @@ -404,8 +362,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) goto err; tegra_wm8903_dai.codec_name = NULL; - tegra_wm8903_dai.codec_of_node = of_parse_phandle( - pdev->dev.of_node, "nvidia,audio-codec", 0); + tegra_wm8903_dai.codec_of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); if (!tegra_wm8903_dai.codec_of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); @@ -414,8 +372,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } tegra_wm8903_dai.cpu_dai_name = NULL; - tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle( - pdev->dev.of_node, "nvidia,i2s-controller", 0); + tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(np, + "nvidia,i2s-controller", 0); if (!tegra_wm8903_dai.cpu_dai_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); @@ -442,6 +400,52 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } } + if (gpio_is_valid(pdata->gpio_spkr_en)) { + ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); + if (ret) { + dev_err(card->dev, "cannot get spkr_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_SPKR_EN; + + gpio_direction_output(pdata->gpio_spkr_en, 0); + } + + if (gpio_is_valid(pdata->gpio_hp_mute)) { + ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); + if (ret) { + dev_err(card->dev, "cannot get hp_mute gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_HP_MUTE; + + gpio_direction_output(pdata->gpio_hp_mute, 1); + } + + if (gpio_is_valid(pdata->gpio_int_mic_en)) { + ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); + if (ret) { + dev_err(card->dev, "cannot get int_mic_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_INT_MIC_EN; + + /* Disable int mic; enable signal is active-high */ + gpio_direction_output(pdata->gpio_int_mic_en, 0); + } + + if (gpio_is_valid(pdata->gpio_ext_mic_en)) { + ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); + if (ret) { + dev_err(card->dev, "cannot get ext_mic_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_EXT_MIC_EN; + + /* Enable ext mic; enable signal is active-low */ + gpio_direction_output(pdata->gpio_ext_mic_en, 0); + } + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; -- GitLab From e2d287c179a12a6069bc3b746e2e34edcddf81b3 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:55 -0600 Subject: [PATCH 0087/5711] ASoC: tegra+wm8903: Use devm_gpio_request_one By using this function, the driver no longer needs to explicitly free the GPIOs. Hence, we can also remove the flags we use to track whether we allocated these GPIOs. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 42 ++++++++-------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index a8a3103ab4cb..5ef2063e0ab1 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -50,10 +50,6 @@ #define DRV_NAME "tegra-snd-wm8903" -#define GPIO_SPKR_EN BIT(0) -#define GPIO_HP_MUTE BIT(1) -#define GPIO_INT_MIC_EN BIT(2) -#define GPIO_EXT_MIC_EN BIT(3) #define GPIO_HP_DET BIT(4) struct tegra_wm8903 { @@ -401,49 +397,41 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } if (gpio_is_valid(pdata->gpio_spkr_en)) { - ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en, + GPIOF_OUT_INIT_LOW, "spkr_en"); if (ret) { dev_err(card->dev, "cannot get spkr_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_SPKR_EN; - - gpio_direction_output(pdata->gpio_spkr_en, 0); } if (gpio_is_valid(pdata->gpio_hp_mute)) { - ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute, + GPIOF_OUT_INIT_HIGH, "hp_mute"); if (ret) { dev_err(card->dev, "cannot get hp_mute gpio\n"); return ret; } - machine->gpio_requested |= GPIO_HP_MUTE; - - gpio_direction_output(pdata->gpio_hp_mute, 1); } if (gpio_is_valid(pdata->gpio_int_mic_en)) { - ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); + /* Disable int mic; enable signal is active-high */ + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en, + GPIOF_OUT_INIT_LOW, "int_mic_en"); if (ret) { dev_err(card->dev, "cannot get int_mic_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_INT_MIC_EN; - - /* Disable int mic; enable signal is active-high */ - gpio_direction_output(pdata->gpio_int_mic_en, 0); } if (gpio_is_valid(pdata->gpio_ext_mic_en)) { - ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); + /* Enable ext mic; enable signal is active-low */ + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en, + GPIOF_OUT_INIT_LOW, "ext_mic_en"); if (ret) { dev_err(card->dev, "cannot get ext_mic_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_EXT_MIC_EN; - - /* Enable ext mic; enable signal is active-low */ - gpio_direction_output(pdata->gpio_ext_mic_en, 0); } ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); @@ -469,21 +457,11 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - struct tegra_wm8903_platform_data *pdata = &machine->pdata; if (machine->gpio_requested & GPIO_HP_DET) snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); - if (machine->gpio_requested & GPIO_EXT_MIC_EN) - gpio_free(pdata->gpio_ext_mic_en); - if (machine->gpio_requested & GPIO_INT_MIC_EN) - gpio_free(pdata->gpio_int_mic_en); - if (machine->gpio_requested & GPIO_HP_MUTE) - gpio_free(pdata->gpio_hp_mute); - if (machine->gpio_requested & GPIO_SPKR_EN) - gpio_free(pdata->gpio_spkr_en); - machine->gpio_requested = 0; snd_soc_unregister_card(card); -- GitLab From e44fbbd45896e684d44391aaf881dd3e36bd1a16 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:56 -0600 Subject: [PATCH 0088/5711] ASoC: tegra+wm8903: unconditionally free jack GPIOs in remove The headphone jack GPIOs are added/initialized in the DAI link's init() method, and hence in theory may not always have been added before remove() is called in some unusual cases. In order to prevent calling snd_soc_jack_free_gpios() if snd_soc_jack_add_gpios() had not been, the code kept track of the initialization state to avoid the free call when necessary. However, it appears that snd_soc_jack_free_gpios() is robust in the face of being called without snd_soc_jack_add_gpios() first succeeding, so there is little point manually tracking this information. Hence, remove the tracking code. Almost all other machine drivers already operate this way. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 5ef2063e0ab1..9059525f3b08 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -50,12 +50,9 @@ #define DRV_NAME "tegra-snd-wm8903" -#define GPIO_HP_DET BIT(4) - struct tegra_wm8903 { struct tegra_wm8903_platform_data pdata; struct tegra_asoc_utils_data util_data; - int gpio_requested; }; static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, @@ -252,7 +249,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); - machine->gpio_requested |= GPIO_HP_DET; } snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, @@ -458,10 +454,8 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) struct snd_soc_card *card = platform_get_drvdata(pdev); struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - if (machine->gpio_requested & GPIO_HP_DET) - snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, - 1, - &tegra_wm8903_hp_jack_gpio); + snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1, + &tegra_wm8903_hp_jack_gpio); snd_soc_unregister_card(card); -- GitLab From aef9a37c01a63a132d43d65d231dfe515d0f918a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:09:51 -0600 Subject: [PATCH 0089/5711] ASoC: tegra+alc5632: move all GPIO setup into probe Now that deferred probe exists, we can parse device tree and request GPIOs from probe(), rather than deferring this to the DAI link's init(). Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 32de7006daf0..facf6f00c6b0 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -1,5 +1,5 @@ /* - * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver +* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver * * Copyright (C) 2011 The AC100 Kernel Team * Copyright (C) 2012 - NVIDIA, Inc. @@ -110,7 +110,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - struct device_node *np = codec->card->dev->of_node; struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, @@ -119,8 +118,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) ARRAY_SIZE(tegra_alc5632_hs_jack_pins), tegra_alc5632_hs_jack_pins); - machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); - if (gpio_is_valid(machine->gpio_hp_det)) { tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, @@ -159,6 +156,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = { static __devinit int tegra_alc5632_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_card *card = &snd_soc_tegra_alc5632; struct tegra_alc5632 *alc5632; int ret; @@ -181,6 +179,10 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) goto err; } + alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); + if (alc5632->gpio_hp_det == -ENODEV) + return -EPROBE_DEFER; + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) goto err; -- GitLab From 9f6328d910ef8df8176ed433aa2de037eba1f656 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:09:52 -0600 Subject: [PATCH 0090/5711] ASoC: tegra+alc5632: unconditionally free jack GPIOs in remove The headphone jack GPIOs are added/initialized in the DAI link's init() method, and hence in theory may not always have been added before remove() is called in some unusual cases. In order to prevent calling snd_soc_jack_free_gpios() if snd_soc_jack_add_gpios() had not been, the code kept track of the initialization state to avoid the free call when necessary. However, it appears that snd_soc_jack_free_gpios() is robust in the face of being called without snd_soc_jack_add_gpios() first succeeding, so there is little point manually tracking this information. Hence, remove the tracking code. All other machine drivers already operate this way. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index facf6f00c6b0..15669570ae31 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -33,11 +33,8 @@ #define DRV_NAME "tegra-alc5632" -#define GPIO_HP_DET BIT(0) - struct tegra_alc5632 { struct tegra_asoc_utils_data util_data; - int gpio_requested; int gpio_hp_det; }; @@ -123,7 +120,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, 1, &tegra_alc5632_hp_jack_gpio); - machine->gpio_requested |= GPIO_HP_DET; } snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); @@ -236,11 +232,8 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev) struct snd_soc_card *card = platform_get_drvdata(pdev); struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); - if (machine->gpio_requested & GPIO_HP_DET) - snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, - 1, - &tegra_alc5632_hp_jack_gpio); - machine->gpio_requested = 0; + snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 1, + &tegra_alc5632_hp_jack_gpio); snd_soc_unregister_card(card); -- GitLab From 14df415a38234aa483219335bc6c1ee899b85e10 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:53 -0600 Subject: [PATCH 0091/5711] ASoC: tegra+wm8903: simplify gpio tests in widget callbacks By the time any widget callbacks could be called, if the GPIO ID they will manipulate is valid, it must have already been requested, or the card would have failed to probe or initialize. So, testing for GPIO validity is equivalent to testing whether the GPIO was successfully requested at this point in the code. Making this change will allow later patches to remove the gpio_requested variable. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 9059525f3b08..1fd6a41b9162 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -153,7 +153,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = &machine->pdata; - if (!(machine->gpio_requested & GPIO_SPKR_EN)) + if (!gpio_is_valid(pdata->gpio_spkr_en)) return 0; gpio_set_value_cansleep(pdata->gpio_spkr_en, @@ -170,7 +170,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = &machine->pdata; - if (!(machine->gpio_requested & GPIO_HP_MUTE)) + if (!gpio_is_valid(pdata->gpio_hp_mute)) return 0; gpio_set_value_cansleep(pdata->gpio_hp_mute, -- GitLab From b350ecbe4c2e4639ed3a716ec67accb744e4417d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:11:19 -0600 Subject: [PATCH 0092/5711] ASoC: tegra+wm8903: remove non-DT support for Seaboard In kernel 3.6, Seaboard will only be supported when booting using device tree; the board files are being removed. Hence, remove the non-DT support for Seaboard and derivatives Kaen and Aebl from the audio driver. Harmony is the only remaining board supported by this driver when not using DT. This support is currently scheduled for removal in 3.7. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 48 ++-------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 1fd6a41b9162..b75e0e8db1d0 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -28,8 +28,6 @@ * */ -#include - #include #include #include @@ -196,37 +194,6 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = { {"IN1L", NULL, "Mic Jack"}, }; -static const struct snd_soc_dapm_route seaboard_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "ROP"}, - {"Int Spk", NULL, "RON"}, - {"Int Spk", NULL, "LOP"}, - {"Int Spk", NULL, "LON"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN1R", NULL, "Mic Jack"}, -}; - -static const struct snd_soc_dapm_route kaen_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "ROP"}, - {"Int Spk", NULL, "RON"}, - {"Int Spk", NULL, "LOP"}, - {"Int Spk", NULL, "LON"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN2R", NULL, "Mic Jack"}, -}; - -static const struct snd_soc_dapm_route aebl_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "LINEOUTR"}, - {"Int Spk", NULL, "LINEOUTL"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN1R", NULL, "Mic Jack"}, -}; - static const struct snd_kcontrol_new tegra_wm8903_controls[] = { SOC_DAPM_PIN_SWITCH("Int Spk"), }; @@ -377,19 +344,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) tegra_wm8903_dai.platform_of_node = tegra_wm8903_dai.cpu_dai_of_node; } else { - if (machine_is_harmony()) { - card->dapm_routes = harmony_audio_map; - card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); - } else if (machine_is_seaboard()) { - card->dapm_routes = seaboard_audio_map; - card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); - } else if (machine_is_kaen()) { - card->dapm_routes = kaen_audio_map; - card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); - } else { - card->dapm_routes = aebl_audio_map; - card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); - } + card->dapm_routes = harmony_audio_map; + card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); } if (gpio_is_valid(pdata->gpio_spkr_en)) { -- GitLab From 656baaebf92ae9b16644c7e10a273d8dfe1ba1f6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 23 May 2012 12:39:07 +0100 Subject: [PATCH 0093/5711] ASoC: codecs: Refresh copyrights for Wolfson drivers Signed-off-by: Mark Brown --- sound/soc/codecs/wm2000.c | 2 +- sound/soc/codecs/wm5100-tables.c | 2 +- sound/soc/codecs/wm5100.c | 2 +- sound/soc/codecs/wm8350.c | 2 +- sound/soc/codecs/wm8400.c | 2 +- sound/soc/codecs/wm8580.c | 2 +- sound/soc/codecs/wm8731.c | 1 + sound/soc/codecs/wm8741.c | 2 +- sound/soc/codecs/wm8753.c | 2 +- sound/soc/codecs/wm8776.c | 2 +- sound/soc/codecs/wm8804.c | 2 +- sound/soc/codecs/wm8903.c | 2 +- sound/soc/codecs/wm8904.c | 2 +- sound/soc/codecs/wm8960.c | 2 ++ sound/soc/codecs/wm8961.c | 2 ++ sound/soc/codecs/wm8962.c | 2 +- sound/soc/codecs/wm8993.c | 2 +- sound/soc/codecs/wm8994.c | 2 +- sound/soc/codecs/wm8996.c | 2 +- sound/soc/codecs/wm9081.c | 2 +- sound/soc/codecs/wm9090.c | 2 +- sound/soc/codecs/wm9712.c | 2 +- sound/soc/codecs/wm9713.c | 2 +- sound/soc/codecs/wm_hubs.c | 2 +- 24 files changed, 26 insertions(+), 21 deletions(-) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a75c3766aede..52f0a19217c4 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -1,7 +1,7 @@ /* * wm2000.c -- WM2000 ALSA Soc Audio driver * - * Copyright 2008-2010 Wolfson Microelectronics PLC. + * Copyright 2008-2011 Wolfson Microelectronics PLC. * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c index e167207a19cc..e239f4bf2460 100644 --- a/sound/soc/codecs/wm5100-tables.c +++ b/sound/soc/codecs/wm5100-tables.c @@ -1,7 +1,7 @@ /* * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data * - * Copyright 2011 Wolfson Microelectronics plc + * Copyright 2011-2 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index cb6d5372103a..3823af362912 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1,7 +1,7 @@ /* * wm5100.c -- WM5100 ALSA SoC Audio driver * - * Copyright 2011 Wolfson Microelectronics plc + * Copyright 2011-2 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 555ee146ae0d..e782a5aa2a31 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1,7 +1,7 @@ /* * wm8350.c -- WM8350 ALSA SoC audio driver * - * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. + * Copyright (C) 2007-12 Wolfson Microelectronics PLC. * * Author: Liam Girdwood * diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 5dc31ebcd0e7..5d277a915f81 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1,7 +1,7 @@ /* * wm8400.c -- WM8400 ALSA Soc Audio driver * - * Copyright 2008, 2009 Wolfson Microelectronics PLC. + * Copyright 2008-11 Wolfson Microelectronics PLC. * Author: Mark Brown * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 211285164d70..7c68226376e4 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -1,7 +1,7 @@ /* * wm8580.c -- WM8580 ALSA Soc Audio driver * - * Copyright 2008, 2009 Wolfson Microelectronics PLC. + * Copyright 2008-11 Wolfson Microelectronics PLC. * * 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 diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 9d1b9b0271f1..bb1d26919b10 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -2,6 +2,7 @@ * wm8731.c -- WM8731 ALSA SoC Audio driver * * Copyright 2005 Openedhand Ltd. + * Copyright 2006-12 Wolfson Microelectronics, plc * * Author: Richard Purdie * diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 6e849cb04243..35f3d23200e0 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -1,7 +1,7 @@ /* * wm8741.c -- WM8741 ALSA SoC Audio driver * - * Copyright 2010 Wolfson Microelectronics plc + * Copyright 2010-1 Wolfson Microelectronics plc * * Author: Ian Lartey * diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a26482cd7654..13bff87ddcf5 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1,7 +1,7 @@ /* * wm8753.c -- WM8753 ALSA Soc Audio driver * - * Copyright 2003 Wolfson Microelectronics PLC. + * Copyright 2003-11 Wolfson Microelectronics PLC. * Author: Liam Girdwood * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index a19db5a0a17a..879c356a9045 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -1,7 +1,7 @@ /* * wm8776.c -- WM8776 ALSA SoC Audio driver * - * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6bd1b767b138..c088020172ab 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -1,7 +1,7 @@ /* * wm8804.c -- WM8804 S/PDIF transceiver driver * - * Copyright 2010 Wolfson Microelectronics plc + * Copyright 2010-11 Wolfson Microelectronics plc * * Author: Dimitris Papastamos * diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f6a3fc5f09c0..304b5cff3482 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1,7 +1,7 @@ /* * wm8903.c -- WM8903 ALSA SoC Audio driver * - * Copyright 2008 Wolfson Microelectronics + * Copyright 2008-11 Wolfson Microelectronics * Copyright 2011-2012 NVIDIA, Inc. * * Author: Mark Brown diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 65d525d74c54..db94d10b5c1a 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1,7 +1,7 @@ /* * wm8904.c -- WM8904 ALSA SoC Audio driver * - * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 8bc659d8dd2e..96518ac8e24c 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1,6 +1,8 @@ /* * wm8960.c -- WM8960 ALSA SoC Audio driver * + * Copyright 2007-11 Wolfson Microelectronics, plc + * * Author: Liam Girdwood * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 05ea7c274093..01edbcc754d2 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -1,6 +1,8 @@ /* * wm8961.c -- WM8961 ALSA SoC Audio driver * + * Copyright 2009-10 Wolfson Microelectronics, plc + * * Author: Mark Brown * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 0cfce9999c89..27da4d722edc 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1,7 +1,7 @@ /* * wm8962.c -- WM8962 ALSA SoC Audio driver * - * Copyright 2010 Wolfson Microelectronics plc + * Copyright 2010-2 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 36acfccab999..9fd80d688979 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1,7 +1,7 @@ /* * wm8993.c -- WM8993 ALSA SoC audio driver * - * Copyright 2009, 2010 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 993639d694ce..5d4d7df8d339 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1,7 +1,7 @@ /* * wm8994.c -- WM8994 ALSA SoC Audio driver * - * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 8af422e38fd0..efc4e9d0903b 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1,7 +1,7 @@ /* * wm8996.c - WM8996 audio codec interface * - * Copyright 2011 Wolfson Microelectronics PLC. + * Copyright 2011-2 Wolfson Microelectronics PLC. * Author: Mark Brown * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 9328270df16c..2de74e1ea225 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -3,7 +3,7 @@ * * Author: Mark Brown * - * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * 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 diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 4b263b6edf13..2c2346fdd637 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -1,7 +1,7 @@ /* * ALSA SoC WM9090 driver * - * Copyright 2009, 2010 Wolfson Microelectronics + * Copyright 2009-12 Wolfson Microelectronics * * Author: Mark Brown * diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index a1541414d904..099e6ec32125 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -1,7 +1,7 @@ /* * wm9712.c -- ALSA Soc WM9712 codec support * - * Copyright 2006 Wolfson Microelectronics PLC. + * Copyright 2006-12 Wolfson Microelectronics PLC. * Author: Liam Girdwood * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 2d22cc70d536..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1,7 +1,7 @@ /* * wm9713.c -- ALSA Soc WM9713 codec support * - * Copyright 2006 Wolfson Microelectronics PLC. + * Copyright 2006-10 Wolfson Microelectronics PLC. * Author: Liam Girdwood * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index dfe957a47f29..61baa48823cb 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -1,7 +1,7 @@ /* * wm_hubs.c -- WM8993/4 common code * - * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown * -- GitLab From 1aad779fccdbb4d79af7b9de93dfd2bfe807e052 Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 24 May 2012 15:26:03 +0200 Subject: [PATCH 0094/5711] ALSA: pcm: Add debug-print helper function Adds a function getting the stream-name as a string for a specific stream. Signed-off-by: Ola Lilja Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- include/sound/pcm.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 0d1112815be3..a55d5db7eb5a 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1073,4 +1073,15 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); +/** + * Get a string naming the direction of a stream + */ +static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return "Playback"; + else + return "Capture"; +} + #endif /* __SOUND_PCM_H */ -- GitLab From d7e7eb91551ad99244b989d71d092cb0375648fa Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 24 May 2012 15:26:25 +0200 Subject: [PATCH 0095/5711] ASoC: core: Add widget SND_SOC_DAPM_CLOCK_SUPPLY Adds a supply-widget variant for connection to the clock-framework. This widget-type corresponds to the variant for regulators. Signed-off-by: Ola Lilja Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 10 ++++++++++ sound/soc/soc-dapm.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index e3833d9f1914..05559e571d44 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -229,6 +229,10 @@ struct device; { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ .shift = wshift, .invert = winvert, \ .event = wevent, .event_flags = wflags} +#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ +{ .id = snd_soc_dapm_clock_supply, .name = wname, \ + .reg = SND_SOC_NOPM, .event = dapm_clock_event, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } /* generic widgets */ #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ @@ -245,6 +249,7 @@ struct device; .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } + /* dapm kcontrol types */ #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -327,6 +332,8 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +int dapm_clock_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); /* dapm controls */ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, @@ -432,6 +439,7 @@ enum snd_soc_dapm_type { snd_soc_dapm_post, /* machine specific post widget - exec last */ snd_soc_dapm_supply, /* power/clock supply */ snd_soc_dapm_regulator_supply, /* external regulator */ + snd_soc_dapm_clock_supply, /* external clock */ snd_soc_dapm_aif_in, /* audio interface input */ snd_soc_dapm_aif_out, /* audio interface output */ snd_soc_dapm_siggen, /* signal generator */ @@ -537,6 +545,8 @@ struct snd_soc_dapm_widget { struct list_head dirty; int inputs; int outputs; + + struct clk *clk; }; struct snd_soc_dapm_update { diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 90ee77d2409d..3bb7a6f058d0 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ static int dapm_up_seq[] = { [snd_soc_dapm_pre] = 0, [snd_soc_dapm_supply] = 1, [snd_soc_dapm_regulator_supply] = 1, + [snd_soc_dapm_clock_supply] = 1, [snd_soc_dapm_micbias] = 2, [snd_soc_dapm_dai_link] = 2, [snd_soc_dapm_dai] = 3, @@ -92,6 +94,7 @@ static int dapm_down_seq[] = { [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai] = 10, [snd_soc_dapm_dai_link] = 11, + [snd_soc_dapm_clock_supply] = 12, [snd_soc_dapm_regulator_supply] = 12, [snd_soc_dapm_supply] = 12, [snd_soc_dapm_post] = 13, @@ -391,6 +394,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_vmid: case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: case snd_soc_dapm_aif_in: case snd_soc_dapm_aif_out: case snd_soc_dapm_dai: @@ -764,6 +768,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, switch (widget->id) { case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: return 0; default: break; @@ -850,6 +855,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, switch (widget->id) { case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: return 0; default: break; @@ -996,6 +1002,24 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(dapm_regulator_event); +/* + * Handler for clock supply widget. + */ +int dapm_clock_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (!w->clk) + return -EIO; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + return clk_enable(w->clk); + } else { + clk_disable(w->clk); + return 0; + } +} +EXPORT_SYMBOL_GPL(dapm_clock_event); + static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) { if (w->power_checked) @@ -1487,6 +1511,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, switch (w->id) { case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: /* Supplies can't affect their outputs, only their inputs */ break; default: @@ -1587,6 +1612,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) break; case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: case snd_soc_dapm_micbias: if (d->target_bias_level < SND_SOC_BIAS_STANDBY) d->target_bias_level = SND_SOC_BIAS_STANDBY; @@ -1941,6 +1967,7 @@ static ssize_t dapm_widget_show(struct device *dev, case snd_soc_dapm_mixer_named_ctl: case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: if (w->name) count += sprintf(buf + count, "%s: %s\n", w->name, w->power ? "On":"Off"); @@ -2187,6 +2214,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, case snd_soc_dapm_post: case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: case snd_soc_dapm_aif_in: case snd_soc_dapm_aif_out: case snd_soc_dapm_dai: @@ -2873,6 +2901,15 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, return NULL; } break; + case snd_soc_dapm_clock_supply: + w->clk = clk_get(dapm->dev, w->name); + if (IS_ERR(w->clk)) { + ret = PTR_ERR(w->clk); + dev_err(dapm->dev, "Failed to request %s: %d\n", + w->name, ret); + return NULL; + } + break; default: break; } @@ -2924,6 +2961,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, break; case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: + case snd_soc_dapm_clock_supply: w->power_check = dapm_supply_check_power; break; case snd_soc_dapm_dai: -- GitLab From 01a0c1139c2bd075d005253093e7060022c5d0cb Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 24 May 2012 15:26:32 +0200 Subject: [PATCH 0096/5711] ASoC: Ux500: Add platform-driver Add platform-driver handling all DMA-activities. Signed-off-by: Ola Lilja Signed-off-by: Mark Brown --- sound/soc/ux500/Kconfig | 7 + sound/soc/ux500/Makefile | 3 + sound/soc/ux500/ux500_pcm.c | 318 ++++++++++++++++++++++++++++++++++++ sound/soc/ux500/ux500_pcm.h | 35 ++++ 4 files changed, 363 insertions(+) create mode 100644 sound/soc/ux500/ux500_pcm.c create mode 100644 sound/soc/ux500/ux500_pcm.h diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig index 44cf43404cd9..1d385150064f 100644 --- a/sound/soc/ux500/Kconfig +++ b/sound/soc/ux500/Kconfig @@ -12,3 +12,10 @@ menuconfig SND_SOC_UX500 config SND_SOC_UX500_PLAT_MSP_I2S tristate depends on SND_SOC_UX500 + +config SND_SOC_UX500_PLAT_DMA + tristate "Platform - DB8500 (DMA)" + depends on SND_SOC_UX500 + select SND_SOC_DMAENGINE_PCM + help + Say Y if you want to enable the Ux500 platform-driver. diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile index 19974c5a2ea1..4634bf015f62 100644 --- a/sound/soc/ux500/Makefile +++ b/sound/soc/ux500/Makefile @@ -2,3 +2,6 @@ snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o + +snd-soc-ux500-plat-dma-objs := ux500_pcm.o +obj-$(CONFIG_SND_SOC_UX500_PLAT_DMA) += snd-soc-ux500-plat-dma.o diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c new file mode 100644 index 000000000000..66b080e5de96 --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja , + * Roger Nilsson + * for ST-Ericsson. + * + * License terms: + * + * 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 "ux500_msp_i2s.h" +#include "ux500_pcm.h" + +static struct snd_pcm_hardware ux500_pcm_hw_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, + .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, + .channels_min = UX500_PLATFORM_MIN_CHANNELS, + .channels_max = UX500_PLATFORM_MAX_CHANNELS, + .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, + .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, + .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, + .periods_min = UX500_PLATFORM_PERIODS_MIN, + .periods_max = UX500_PLATFORM_PERIODS_MAX, +}; + +static struct snd_pcm_hardware ux500_pcm_hw_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, + .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, + .channels_min = UX500_PLATFORM_MIN_CHANNELS, + .channels_max = UX500_PLATFORM_MAX_CHANNELS, + .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, + .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, + .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, + .periods_min = UX500_PLATFORM_PERIODS_MIN, + .periods_max = UX500_PLATFORM_PERIODS_MAX, +}; + +static void ux500_pcm_dma_hw_free(struct device *dev, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dma_buffer *buf = runtime->dma_buffer_p; + + if (runtime->dma_area == NULL) + return; + + if (buf != &substream->dma_buffer) { + dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, + buf->addr); + kfree(runtime->dma_buffer_p); + } + + snd_pcm_set_runtime_buffer(substream, NULL); +} + +static int ux500_pcm_open(struct snd_pcm_substream *substream) +{ + int stream_id = substream->pstr->stream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai = rtd->cpu_dai; + struct device *dev = dai->dev; + int ret; + struct ux500_msp_dma_params *dma_params; + u16 per_data_width, mem_data_width; + struct stedma40_chan_cfg *dma_cfg; + + dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, + snd_pcm_stream_str(substream)); + + dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_set_runtime_hwparams(substream, + &ux500_pcm_hw_playback); + else + snd_soc_set_runtime_hwparams(substream, + &ux500_pcm_hw_capture); + + /* ensure that buffer size is a multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n", + __func__, ret); + return ret; + } + + dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__, + snd_pcm_stream_str(substream)); + runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? + ux500_pcm_hw_playback : ux500_pcm_hw_capture; + + mem_data_width = STEDMA40_HALFWORD_WIDTH; + + dma_params = snd_soc_dai_get_dma_data(dai, substream); + switch (dma_params->data_size) { + case 32: + per_data_width = STEDMA40_WORD_WIDTH; + break; + case 16: + per_data_width = STEDMA40_HALFWORD_WIDTH; + break; + case 8: + per_data_width = STEDMA40_BYTE_WIDTH; + break; + default: + per_data_width = STEDMA40_WORD_WIDTH; + dev_warn(rtd->platform->dev, + "%s: Unknown data-size (%d)! Assuming 32 bits.\n", + __func__, dma_params->data_size); + } + + dma_cfg = dma_params->dma_cfg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_cfg->src_info.data_width = mem_data_width; + dma_cfg->dst_info.data_width = per_data_width; + } else { + dma_cfg->src_info.data_width = per_data_width; + dma_cfg->dst_info.data_width = mem_data_width; + } + + + ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg); + if (ret) { + dev_dbg(dai->dev, + "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n", + __func__, ret); + return ret; + } + + snd_dmaengine_pcm_set_data(substream, dma_cfg); + + return 0; +} + +static int ux500_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai = rtd->cpu_dai; + + dev_dbg(dai->dev, "%s: Enter\n", __func__); + + snd_dmaengine_pcm_close(substream); + + return 0; +} + +static int ux500_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dma_buffer *buf = runtime->dma_buffer_p; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int ret = 0; + int size; + + dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); + + size = params_buffer_bytes(hw_params); + + if (buf) { + if (buf->bytes >= size) + goto out; + ux500_pcm_dma_hw_free(NULL, substream); + } + + if (substream->dma_buffer.area != NULL && + substream->dma_buffer.bytes >= size) { + buf = &substream->dma_buffer; + } else { + buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); + if (!buf) + goto nomem; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = NULL; + buf->area = dma_alloc_coherent(NULL, size, &buf->addr, + GFP_KERNEL); + buf->bytes = size; + buf->private_data = NULL; + + if (!buf->area) + goto free; + } + snd_pcm_set_runtime_buffer(substream, buf); + ret = 1; + out: + runtime->dma_bytes = size; + return ret; + + free: + kfree(buf); + nomem: + return -ENOMEM; +} + +static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); + + ux500_pcm_dma_hw_free(NULL, substream); + + return 0; +} + +static int ux500_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__); + + return dma_mmap_coherent(NULL, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); +} + +static struct snd_pcm_ops ux500_pcm_ops = { + .open = ux500_pcm_open, + .close = ux500_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = ux500_pcm_hw_params, + .hw_free = ux500_pcm_hw_free, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = ux500_pcm_mmap +}; + +int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + + dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__, + pcm->id); + + pcm->info_flags = 0; + + return 0; +} + +static struct snd_soc_platform_driver ux500_pcm_soc_drv = { + .ops = &ux500_pcm_ops, + .pcm_new = ux500_pcm_new, +}; + +static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev) +{ + int ret; + + ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv); + if (ret < 0) { + dev_err(&pdev->dev, + "%s: ERROR: Failed to register platform '%s' (%d)!\n", + __func__, pdev->name, ret); + return ret; + } + + return 0; +} + +static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + + return 0; +} + +static struct platform_driver ux500_pcm_driver = { + .driver = { + .name = "ux500-pcm", + .owner = THIS_MODULE, + }, + + .probe = ux500_pcm_drv_probe, + .remove = __devexit_p(ux500_pcm_drv_remove), +}; +module_platform_driver(ux500_pcm_driver); + +MODULE_LICENSE("GPLv2"); diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h new file mode 100644 index 000000000000..77ed44d371e9 --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja , + * Roger Nilsson + * for ST-Ericsson. + * + * License terms: + * + * 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 UX500_PCM_H +#define UX500_PCM_H + +#include + +#include + +#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000 +#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000 +#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000 +#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000 + +#define UX500_PLATFORM_MIN_CHANNELS 1 +#define UX500_PLATFORM_MAX_CHANNELS 8 + +#define UX500_PLATFORM_PERIODS_BYTES_MIN 128 +#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) +#define UX500_PLATFORM_PERIODS_MIN 2 +#define UX500_PLATFORM_PERIODS_MAX 48 +#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) + +#endif -- GitLab From 5514efdfe0384576ef38c66b1672b6826696fbf3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 28 May 2012 23:29:36 -0700 Subject: [PATCH 0097/5711] ASoC: fsi: use dmaengine helper functions This patch used dmaengine helper functions instead of using hand setting. And reduced local variables Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2ef98536f1da..fcaa6b8abb0c 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1089,13 +1089,10 @@ static void fsi_dma_do_tasklet(unsigned long data) { struct fsi_stream *io = (struct fsi_stream *)data; struct fsi_priv *fsi = fsi_stream_to_priv(io); - struct dma_chan *chan; struct snd_soc_dai *dai; struct dma_async_tx_descriptor *desc; - struct scatterlist sg; struct snd_pcm_runtime *runtime; enum dma_data_direction dir; - dma_cookie_t cookie; int is_play = fsi_stream_is_play(fsi, io); int len; dma_addr_t buf; @@ -1104,7 +1101,6 @@ static void fsi_dma_do_tasklet(unsigned long data) return; dai = fsi_get_dai(io->substream); - chan = io->chan; runtime = io->substream->runtime; dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; len = samples_to_bytes(runtime, io->period_samples); @@ -1112,14 +1108,8 @@ static void fsi_dma_do_tasklet(unsigned long data) dma_sync_single_for_device(dai->dev, buf, len, dir); - sg_init_table(&sg, 1); - sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), - len , offset_in_page(buf)); - sg_dma_address(&sg) = buf; - sg_dma_len(&sg) = len; - - desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); return; @@ -1128,13 +1118,12 @@ static void fsi_dma_do_tasklet(unsigned long data) desc->callback = fsi_dma_complete; desc->callback_param = io; - cookie = desc->tx_submit(desc); - if (cookie < 0) { + if (dmaengine_submit(desc) < 0) { dev_err(dai->dev, "tx_submit() fail\n"); return; } - dma_async_issue_pending(chan); + dma_async_issue_pending(io->chan); /* * FIXME -- GitLab From b1226dc59d55ecde7fc9a338d8cb2a313821fac0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 May 2012 23:56:19 -0700 Subject: [PATCH 0098/5711] ASoC: fsi: use PIO handler if DMA handler was invalid PIO handler is not good performance, but works on all platform. So, switch to PIO handler if DMA handler was invalid case. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index fcaa6b8abb0c..53486ff9c2af 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -247,7 +247,7 @@ struct fsi_priv { struct fsi_stream_handler { int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); - int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, @@ -571,16 +571,16 @@ static int fsi_stream_transfer(struct fsi_stream *io) #define fsi_stream_stop(fsi, io)\ fsi_stream_handler_call(io, start_stop, fsi, io, 0) -static int fsi_stream_probe(struct fsi_priv *fsi) +static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev) { struct fsi_stream *io; int ret1, ret2; io = &fsi->playback; - ret1 = fsi_stream_handler_call(io, probe, fsi, io); + ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev); io = &fsi->capture; - ret2 = fsi_stream_handler_call(io, probe, fsi, io); + ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev); if (ret1 < 0) return ret1; @@ -1173,7 +1173,7 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); } -static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) +static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) { dma_cap_mask_t mask; @@ -1181,8 +1181,19 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) dma_cap_set(DMA_SLAVE, mask); io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); - if (!io->chan) - return -EIO; + if (!io->chan) { + + /* switch to PIO handler */ + if (fsi_stream_is_play(fsi, io)) + fsi->playback.handler = &fsi_pio_push_handler; + else + fsi->capture.handler = &fsi_pio_pop_handler; + + dev_info(dev, "switch handler (dma => pio)\n"); + + /* probe again */ + return fsi_stream_probe(fsi, dev); + } tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); @@ -1672,7 +1683,7 @@ static int fsi_probe(struct platform_device *pdev) master->fsia.master = master; master->fsia.info = &info->port_a; fsi_handler_init(&master->fsia); - ret = fsi_stream_probe(&master->fsia); + ret = fsi_stream_probe(&master->fsia, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIA stream probe failed\n"); goto exit_iounmap; @@ -1683,7 +1694,7 @@ static int fsi_probe(struct platform_device *pdev) master->fsib.master = master; master->fsib.info = &info->port_b; fsi_handler_init(&master->fsib); - ret = fsi_stream_probe(&master->fsib); + ret = fsi_stream_probe(&master->fsib, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIB stream probe failed\n"); goto exit_fsia; -- GitLab From 14a95fe865c0b2ede6f386f52413f6396c010833 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 28 May 2012 22:09:02 +0300 Subject: [PATCH 0099/5711] ASoC: tlv320aic3x: Change Class-D amplifier gain control name ALSA mixers cannot classify this "Class-D Amplifier Gain" speaker output gain control as a playback control. Fix this by changing the name as "Class-D Playback Volume". Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 64d2a4fa34b2..58ef59dfbae9 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -368,7 +368,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = - SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); + SOC_DOUBLE_TLV("Class-D Playback Volume", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); /* Left DAC Mux */ static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = -- GitLab From 0561c1bf354c4a8230a1e0ada43362f54e60b2f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 30 May 2012 13:20:17 +0100 Subject: [PATCH 0100/5711] ASoC: ac97: Remove empty remove() function Signed-off-by: Mark Brown --- sound/soc/codecs/ac97.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 2023c749f232..ea06b834a7de 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -91,11 +91,6 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) return 0; } -static int ac97_soc_remove(struct snd_soc_codec *codec) -{ - return 0; -} - #ifdef CONFIG_PM static int ac97_soc_suspend(struct snd_soc_codec *codec) { @@ -119,7 +114,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { .write = ac97_write, .read = ac97_read, .probe = ac97_soc_probe, - .remove = ac97_soc_remove, .suspend = ac97_soc_suspend, .resume = ac97_soc_resume, }; -- GitLab From 51cc7ed3e378a60a3413a7e424f536e4dec3f39d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 31 May 2012 14:48:07 +0100 Subject: [PATCH 0101/5711] ASoC: wm2000: Add register readability information Signed-off-by: Mark Brown --- sound/soc/codecs/wm2000.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 52f0a19217c4..78a148f0a8ef 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -691,9 +691,39 @@ static int wm2000_resume(struct snd_soc_codec *codec) #define wm2000_resume NULL #endif +static bool wm2000_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM2000_REG_SYS_START: + case WM2000_REG_SPEECH_CLARITY: + case WM2000_REG_SYS_WATCHDOG: + case WM2000_REG_ANA_VMID_PD_TIME: + case WM2000_REG_ANA_VMID_PU_TIME: + case WM2000_REG_CAT_FLTR_INDX: + case WM2000_REG_CAT_GAIN_0: + case WM2000_REG_SYS_STATUS: + case WM2000_REG_SYS_MODE_CNTRL: + case WM2000_REG_SYS_START0: + case WM2000_REG_SYS_START1: + case WM2000_REG_ID1: + case WM2000_REG_ID2: + case WM2000_REG_REVISON: + case WM2000_REG_SYS_CTL1: + case WM2000_REG_SYS_CTL2: + case WM2000_REG_ANC_STAT: + case WM2000_REG_IF_CTL: + return true; + default: + return false; + } +} + static const struct regmap_config wm2000_regmap = { .reg_bits = 8, .val_bits = 8, + + .max_register = WM2000_REG_IF_CTL, + .readable_reg = wm2000_readable_reg, }; static int wm2000_probe(struct snd_soc_codec *codec) -- GitLab From 210cb67cb5b9f9a23b7ce91de50bab357440ba9d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 17:46:36 +0100 Subject: [PATCH 0102/5711] ASoC: io: Use dev_get_regmap() if driver doesn't provide a regmap Less error prone and one less line of code in drivers. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 4d8dc6a27d4d..44d0174b4d97 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -142,6 +142,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, case SND_SOC_REGMAP: /* Device has made its own regmap arrangements */ codec->using_regmap = true; + if (!codec->control_data) + codec->control_data = dev_get_regmap(codec->dev, NULL); ret = regmap_get_val_bytes(codec->control_data); /* Errors are legitimate for non-integer byte multiples */ -- GitLab From bc92657a11c0982783979bbb84ceaf58ba222124 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 25 May 2012 18:22:11 -0600 Subject: [PATCH 0103/5711] ASoC: make snd_soc_dai_link more symmetrical Prior to this patch, the CPU side of a DAI link was specified using a single name. Often, this was the result of calling dev_name() on the device providing the DAI, but in the case of a CPU DAI driver that provided multiple DAIs, it needed to mix together both the device name and some device-relative name, in order to form a single globally unique name. However, the CODEC side of the DAI link was specified using separate fields for device (name or OF node) and device-relative DAI name. This patch allows the CPU side of a DAI link to be specified in the same way as the CODEC side, separating concepts of device and device-relative DAI name. I believe this will be important in multi-codec and/or dynamic PCM scenarios, where a single CPU driver provides multiple DAIs, while also booting using device tree, with accompanying desire not to hard-code the CPU side device's name into the original .cpu_dai_name field. Ideally, both the CPU DAI and CODEC DAI loops in soc_bind_dai_link() would now be identical. However, two things prevent that at present: 1) The need to save rtd->codec for the CODEC side, which means we have to search for the CODEC explicitly, and not just the CODEC side DAI. 2) Since we know the CODEC side DAI is part of a codec, and not just a standalone DAI, it's slightly more efficient to convert .codec_name/ .codec_of_node into a codec first, and then compare each DAI's .codec field, since this avoids strcmp() on each DAI's CODEC's name within the loop. However, the two loops are essentially semantically equivalent. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/sound/soc.h | 33 ++++++++++++++++++++++---- sound/soc/mxs/mxs-sgtl5000.c | 2 +- sound/soc/soc-core.c | 42 ++++++++++++++++++++++++--------- sound/soc/tegra/tegra_alc5632.c | 6 ++--- sound/soc/tegra/tegra_wm8753.c | 6 ++--- sound/soc/tegra/tegra_wm8903.c | 6 ++--- sound/soc/tegra/trimslice.c | 6 ++--- 7 files changed, 72 insertions(+), 29 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index c703871f5f65..23c4efbe13a6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -785,13 +785,36 @@ struct snd_soc_dai_link { /* config - must be set by machine driver */ const char *name; /* Codec name */ const char *stream_name; /* Stream name */ - const char *codec_name; /* for multi-codec */ - const struct device_node *codec_of_node; - const char *platform_name; /* for multi-platform */ - const struct device_node *platform_of_node; + /* + * You MAY specify the link's CPU-side device, either by device name, + * or by DT/OF node, but not both. If this information is omitted, + * the CPU-side DAI is matched using .cpu_dai_name only, which hence + * must be globally unique. These fields are currently typically used + * only for codec to codec links, or systems using device tree. + */ + const char *cpu_name; + const struct device_node *cpu_of_node; + /* + * You MAY specify the DAI name of the CPU DAI. If this information is + * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node + * only, which only works well when that device exposes a single DAI. + */ const char *cpu_dai_name; - const struct device_node *cpu_dai_of_node; + /* + * You MUST specify the link's codec, either by device name, or by + * DT/OF node, but not both. + */ + const char *codec_name; + const struct device_node *codec_of_node; + /* You MUST specify the DAI name within the codec */ const char *codec_dai_name; + /* + * You MAY specify the link's platform/PCM/DMA driver, either by + * device name, or by DT/OF node, but not both. Some forms of link + * do not need a platform. + */ + const char *platform_name; + const struct device_node *platform_of_node; int be_id; /* optional ID for machine driver BE identification */ const struct snd_soc_pcm_stream *params; diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 3e6e8764b2e6..215113b05f7d 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -133,7 +133,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev) mxs_sgtl5000_dai[i].codec_name = NULL; mxs_sgtl5000_dai[i].codec_of_node = codec_np; mxs_sgtl5000_dai[i].cpu_dai_name = NULL; - mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i]; + mxs_sgtl5000_dai[i].cpu_of_node = saif_np[i]; mxs_sgtl5000_dai[i].platform_name = NULL; mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b37ee8077ed1..ec8350570346 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -812,13 +812,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) /* Find CPU DAI from registered DAIs*/ list_for_each_entry(cpu_dai, &dai_list, list) { - if (dai_link->cpu_dai_of_node) { - if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) - continue; - } else { - if (strcmp(cpu_dai->name, dai_link->cpu_dai_name)) - continue; - } + if (dai_link->cpu_of_node && + (cpu_dai->dev->of_node != dai_link->cpu_of_node)) + continue; + if (dai_link->cpu_name && + strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) + continue; + if (dai_link->cpu_dai_name && + strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + continue; rtd->cpu_dai = cpu_dai; } @@ -3346,6 +3348,12 @@ int snd_soc_register_card(struct snd_soc_card *card) link->name); return -EINVAL; } + /* Codec DAI name must be specified */ + if (!link->codec_dai_name) { + dev_err(card->dev, "codec_dai_name not set for %s\n", + link->name); + return -EINVAL; + } /* * Platform may be specified by either name or OF node, but @@ -3358,12 +3366,24 @@ int snd_soc_register_card(struct snd_soc_card *card) } /* - * CPU DAI must be specified by 1 of name or OF node, - * not both or neither. + * CPU device may be specified by either name or OF node, but + * can be left unspecified, and will be matched based on DAI + * name alone.. + */ + if (link->cpu_name && link->cpu_of_node) { + dev_err(card->dev, + "Neither/both cpu name/of_node are set for %s\n", + link->name); + return -EINVAL; + } + /* + * At least one of CPU DAI name or CPU device name/node must be + * specified */ - if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) { + if (!link->cpu_dai_name && + !(link->cpu_name || link->cpu_of_node)) { dev_err(card->dev, - "Neither/both cpu_dai name/of_node are set for %s\n", + "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", link->name); return -EINVAL; } diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 15669570ae31..417b09b83fdf 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -197,16 +197,16 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) goto err; } - tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle( + tegra_alc5632_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!tegra_alc5632_dai.cpu_dai_of_node) { + if (!tegra_alc5632_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node; + tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node; ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); if (ret) diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 4e77026807a2..02bd5a8e8544 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -157,9 +157,9 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) goto err; } - tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle( + tegra_wm8753_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!tegra_wm8753_dai.cpu_dai_of_node) { + if (!tegra_wm8753_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -167,7 +167,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) } tegra_wm8753_dai.platform_of_node = - tegra_wm8753_dai.cpu_dai_of_node; + tegra_wm8753_dai.cpu_of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index b75e0e8db1d0..1fd71e5a9eb9 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -331,9 +331,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } tegra_wm8903_dai.cpu_dai_name = NULL; - tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(np, + tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_wm8903_dai.cpu_dai_of_node) { + if (!tegra_wm8903_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -342,7 +342,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) tegra_wm8903_dai.platform_name = NULL; tegra_wm8903_dai.platform_of_node = - tegra_wm8903_dai.cpu_dai_of_node; + tegra_wm8903_dai.cpu_of_node; } else { card->dapm_routes = harmony_audio_map; card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 4a8d5b672c9f..5815430e8521 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -162,9 +162,9 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) } trimslice_tlv320aic23_dai.cpu_dai_name = NULL; - trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle( + trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) { + if (!trimslice_tlv320aic23_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -173,7 +173,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) trimslice_tlv320aic23_dai.platform_name = NULL; trimslice_tlv320aic23_dai.platform_of_node = - trimslice_tlv320aic23_dai.cpu_dai_of_node; + trimslice_tlv320aic23_dai.cpu_of_node; } ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); -- GitLab From 6c9d8cf6372ed2995a3d982f5c1f966e842101cc Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 31 May 2012 15:18:01 +0100 Subject: [PATCH 0104/5711] ASoC: core: Add single controls with specified range of values Control type added for cases where a specific range of values within a register are required for control. Added convenience macros: SOC_SINGLE_RANGE SOC_SINGLE_RANGE_TLV Added accessor implementations: snd_soc_info_volsw_range snd_soc_put_volsw_range snd_soc_get_volsw_range Signed-off-by: Michal Hajduk Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- include/sound/soc.h | 23 +++++++++++ sound/soc/soc-core.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 23c4efbe13a6..e4348d25fca3 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -47,6 +47,13 @@ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } +#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ + .put = snd_soc_put_volsw_range, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = xshift, .min = xmin,\ + .max = xmax, .platform_max = xmax, .invert = xinvert} } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -67,6 +74,16 @@ {.reg = xreg, .rreg = xreg, \ .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin} } +#define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw_range, \ + .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = xshift, .min = xmin,\ + .max = xmax, .platform_max = xmax, .invert = xinvert} } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ @@ -460,6 +477,12 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); int snd_soc_limit_volume(struct snd_soc_codec *codec, const char *name, int max); int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ec8350570346..3d803f3cd272 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2791,6 +2791,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); +/** + * snd_soc_info_volsw_range - single mixer info callback with range. + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to provide information, within a range, about a single + * mixer control. + * + * returns 0 for success. + */ +int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int platform_max; + int min = mc->min; + + if (!mc->platform_max) + mc->platform_max = mc->max; + platform_max = mc->platform_max; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = platform_max - min; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); + +/** + * snd_soc_put_volsw_range - single mixer put value callback with range. + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to set the value, within a range, for a single mixer control. + * + * Returns 0 for success. + */ +int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + int min = mc->min; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val, val_mask; + + val = ((ucontrol->value.integer.value[0] + min) & mask); + if (invert) + val = max - val; + val_mask = mask << shift; + val = val << shift; + + return snd_soc_update_bits_locked(codec, reg, val_mask, val); +} +EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); + +/** + * snd_soc_get_volsw_range - single mixer get callback with range + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value, within a range, of a single mixer control. + * + * Returns 0 for success. + */ +int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + int min = mc->min; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + + ucontrol->value.integer.value[0] = + (snd_soc_read(codec, reg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[0] = + max - ucontrol->value.integer.value[0]; + ucontrol->value.integer.value[0] = + ucontrol->value.integer.value[0] - min; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); + /** * snd_soc_limit_volume - Set new limit to an existing volume control. * -- GitLab From f59fef441753cdd07ffe7268b0801ec48cac7b1d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Apr 2012 20:26:41 +0100 Subject: [PATCH 0105/5711] ASoC: wm8350: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8350.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index e782a5aa2a31..d26c8ae4e6d9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -71,20 +71,6 @@ struct wm8350_data { int fll_freq_in; }; -static unsigned int wm8350_codec_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct wm8350 *wm8350 = codec->control_data; - return wm8350_reg_read(wm8350, reg); -} - -static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct wm8350 *wm8350 = codec->control_data; - return wm8350_reg_write(wm8350, reg, value); -} - /* * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. */ @@ -1519,7 +1505,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) if (ret != 0) return ret; - codec->control_data = wm8350; + codec->control_data = wm8350->regmap; + + snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); /* Put the codec into reset if it wasn't already */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); @@ -1629,8 +1617,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { .remove = wm8350_codec_remove, .suspend = wm8350_suspend, .resume = wm8350_resume, - .read = wm8350_codec_read, - .write = wm8350_codec_write, .set_bias_level = wm8350_set_bias_level, .controls = wm8350_snd_controls, -- GitLab From 4552a0ca61cb2133bc77dc432ea20538ea28638a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 May 2012 09:19:31 +0300 Subject: [PATCH 0106/5711] usb: dwc3: fix a WARN and a comment we're now have DWC3_EP0_BOUNCE_SIZE to tell us the actual size of the bufer. Let's use that instead of ep0 wMaxPacketSize. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9e8a3dce69fd..e6ca218ef130 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -821,14 +821,14 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, return; } - WARN_ON(req->request.length > dep->endpoint.maxpacket); + WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); dwc->ep0_bounced = true; /* - * REVISIT in case request length is bigger than EP0 - * wMaxPacketSize, we will need two chained TRBs to handle - * the transfer. + * REVISIT in case request length is bigger than + * DWC3_EP0_BOUNCE_SIZE we will need two chained + * TRBs to handle the transfer. */ ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, dwc->ep0_bounce_addr, dep->endpoint.maxpacket, -- GitLab From a0807881af93646b5d94b5594119df609e756945 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 4 May 2012 13:03:54 +0300 Subject: [PATCH 0107/5711] usb: dwc3: handle pending unaligned Control OUT data phase correctly When DWC3_EP_PENDING_REQUEST flag is set for a Control OUT Data phase transfer, we would be missing the proper handling for unaligned OUT requests, thus hanging a transfer. Since proper handling is already done on dwc3_ep0_do_control_data(), we simply re-factor that function so it can be re-used from __dwc3_gadget_ep0_queue(). Reported-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 72 +++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e6ca218ef130..15ec36eb461b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -55,6 +55,8 @@ #include "io.h" static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum); +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) { @@ -150,9 +152,8 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, return 0; } - ret = dwc3_ep0_start_trans(dwc, direction, - req->request.dma, req->request.length, - DWC3_TRBCTL_CONTROL_DATA); + __dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req); + dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); } else if (dwc->delayed_status) { @@ -787,35 +788,23 @@ static void dwc3_ep0_do_control_setup(struct dwc3 *dwc, dwc3_ep0_out_start(dwc); } -static void dwc3_ep0_do_control_data(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) +static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, + struct dwc3_ep *dep, struct dwc3_request *req) { - struct dwc3_ep *dep; - struct dwc3_request *req; int ret; - dep = dwc->eps[0]; - - if (list_empty(&dep->request_list)) { - dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); - dep->flags |= DWC3_EP_PENDING_REQUEST; - - if (event->endpoint_number) - dep->flags |= DWC3_EP0_DIR_IN; - return; - } - - req = next_request(&dep->request_list); - req->direction = !!event->endpoint_number; + req->direction = !!dep->number; if (req->request.length == 0) { - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, + ret = dwc3_ep0_start_trans(dwc, dep->number, dwc->ctrl_req_addr, 0, DWC3_TRBCTL_CONTROL_DATA); } else if ((req->request.length % dep->endpoint.maxpacket) - && (event->endpoint_number == 0)) { + && (dep->number == 0)) { + u32 transfer_size; + ret = usb_gadget_map_request(&dwc->gadget, &req->request, - event->endpoint_number); + dep->number); if (ret) { dev_dbg(dwc->dev, "failed to map request\n"); return; @@ -823,6 +812,9 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); + transfer_size = roundup(req->request.length, + (u32) dep->endpoint.maxpacket); + dwc->ep0_bounced = true; /* @@ -830,25 +822,47 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, * DWC3_EP0_BOUNCE_SIZE we will need two chained * TRBs to handle the transfer. */ - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, - dwc->ep0_bounce_addr, dep->endpoint.maxpacket, + ret = dwc3_ep0_start_trans(dwc, dep->number, + dwc->ep0_bounce_addr, transfer_size, DWC3_TRBCTL_CONTROL_DATA); } else { ret = usb_gadget_map_request(&dwc->gadget, &req->request, - event->endpoint_number); + dep->number); if (ret) { dev_dbg(dwc->dev, "failed to map request\n"); return; } - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, - req->request.dma, req->request.length, - DWC3_TRBCTL_CONTROL_DATA); + ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, + req->request.length, DWC3_TRBCTL_CONTROL_DATA); } WARN_ON(ret < 0); } +static void dwc3_ep0_do_control_data(struct dwc3 *dwc, + const struct dwc3_event_depevt *event) +{ + struct dwc3_ep *dep; + struct dwc3_request *req; + + dep = dwc->eps[0]; + + if (list_empty(&dep->request_list)) { + dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); + dep->flags |= DWC3_EP_PENDING_REQUEST; + + if (event->endpoint_number) + dep->flags |= DWC3_EP0_DIR_IN; + return; + } + + req = next_request(&dep->request_list); + dep = dwc->eps[event->endpoint_number]; + + __dwc3_ep0_do_control_data(dwc, dep, req); +} + static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) { struct dwc3 *dwc = dep->dwc; -- GitLab From c74c6d4a024d95e81283ee4c38be6fa7baee27f9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 4 May 2012 13:08:22 +0300 Subject: [PATCH 0108/5711] usb: dwc3: ep0: switch over to IS_ALIGNED IS_ALIGNED provides a much faster operation for checking proper size alignment then a modulo operation. Let's use it. Reported-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 15ec36eb461b..477127aecb98 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -799,7 +799,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, ret = dwc3_ep0_start_trans(dwc, dep->number, dwc->ctrl_req_addr, 0, DWC3_TRBCTL_CONTROL_DATA); - } else if ((req->request.length % dep->endpoint.maxpacket) + } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && (dep->number == 0)) { u32 transfer_size; -- GitLab From 788a23f49686d82fa95b83ac7752d6322f1dad44 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 May 2012 14:22:41 +0300 Subject: [PATCH 0109/5711] usb: dwc3: ep0: align on function signature On our Transfer Not Ready handlers, only dwc3_ep0_do_control_status() had a different list of parameters. Align on the parameters in order to keep consistency. No functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 477127aecb98..75d5722db93b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -54,7 +54,7 @@ #include "gadget.h" #include "io.h" -static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum); +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); @@ -160,7 +160,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, dwc->delayed_status = false; if (dwc->ep0state == EP0_STATUS_PHASE) - dwc3_ep0_do_control_status(dwc, 1); + __dwc3_ep0_do_control_status(dwc, dwc->eps[1]); else dev_dbg(dwc->dev, "too early for delayed status\n"); } @@ -875,10 +875,8 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) dwc->ctrl_req_addr, 0, type); } -static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) +static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) { - struct dwc3_ep *dep = dwc->eps[epnum]; - if (dwc->resize_fifos) { dev_dbg(dwc->dev, "starting to resize fifos\n"); dwc3_gadget_resize_tx_fifos(dwc); @@ -888,6 +886,14 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) WARN_ON(dwc3_ep0_start_control_status(dep)); } +static void dwc3_ep0_do_control_status(struct dwc3 *dwc, + const struct dwc3_event_depevt *event) +{ + struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; + + __dwc3_ep0_do_control_status(dwc, dep); +} + static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { @@ -988,7 +994,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, return; } - dwc3_ep0_do_control_status(dwc, event->endpoint_number); + dwc3_ep0_do_control_status(dwc, event); } } -- GitLab From 33b84c2c06d25a3321326d91438e106b4fd5ad9f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 May 2012 14:35:17 +0300 Subject: [PATCH 0110/5711] usb: dwc3: ep0: fix a typo in comment s/has/have. No functional changes, just a typo fix on a code comment. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 75d5722db93b..e31bcd65e7ec 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -900,7 +900,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, dwc->setup_packet_pending = true; /* - * This part is very tricky: If we has just handled + * This part is very tricky: If we have just handled * XferNotReady(Setup) and we're now expecting a * XferComplete but, instead, we receive another * XferNotReady(Setup), we should STALL and restart -- GitLab From a092532483e3200a53c8b1170b3988cc668c07ef Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 22 May 2012 10:24:11 +0300 Subject: [PATCH 0111/5711] usb: dwc3: gadget: remove trailing semicolon That semicolon doesn't do anything, it's not needed and should be removed. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3df1a1973b05..045799356a29 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1032,7 +1032,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) dev_dbg(dwc->dev, "%s: failed to kick transfers\n", dep->name); } - }; + } return 0; } -- GitLab From 2c61a8efce75951148fa07f2cd7ec53ad9d9fbb3 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Wed, 15 Feb 2012 18:56:58 -0800 Subject: [PATCH 0112/5711] usb: dwc3: add definitions for new registers This patch adds definitions for some new registers that have been added to later versions of the controller, up to v2.10a. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 94 +++++++++++++++++++++++++++++++-------- drivers/usb/dwc3/gadget.h | 5 +++ 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index f69c877add09..4d5c63dae14d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -67,6 +67,7 @@ #define DWC3_DEVICE_EVENT_CONNECT_DONE 2 #define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE 3 #define DWC3_DEVICE_EVENT_WAKEUP 4 +#define DWC3_DEVICE_EVENT_HIBER_REQ 5 #define DWC3_DEVICE_EVENT_EOPF 6 #define DWC3_DEVICE_EVENT_SOF 7 #define DWC3_DEVICE_EVENT_ERRATIC_ERROR 9 @@ -171,28 +172,36 @@ #define DWC3_GCTL_PRTCAP_DEVICE 2 #define DWC3_GCTL_PRTCAP_OTG 3 -#define DWC3_GCTL_CORESOFTRESET (1 << 11) -#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) -#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) -#define DWC3_GCTL_DISSCRAMBLE (1 << 3) -#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) +#define DWC3_GCTL_CORESOFTRESET (1 << 11) +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) +#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) /* Global USB2 PHY Configuration Register */ -#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) -#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) +#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) +#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) /* Global USB3 PIPE Control Register */ -#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) -#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) +#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) +#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) /* Global TX Fifo Size Register */ -#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) -#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) +#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) +#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) /* Global HWPARAMS1 Register */ #define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) #define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 +#define DWC3_GHWPARAMS1_EN_PWROPT_HIB 2 +#define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24) +#define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3) + +/* Global HWPARAMS4 Register */ +#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13) +#define DWC3_MAX_HIBER_SCRATCHBUFS 15 /* Device Configuration Register */ #define DWC3_DCFG_LPM_CAP (1 << 22) @@ -206,6 +215,8 @@ #define DWC3_DCFG_LOWSPEED (2 << 0) #define DWC3_DCFG_FULLSPEED1 (3 << 0) +#define DWC3_DCFG_LPM_CAP (1 << 22) + /* Device Control Register */ #define DWC3_DCTL_RUN_STOP (1 << 31) #define DWC3_DCTL_CSFTRST (1 << 30) @@ -216,14 +227,20 @@ #define DWC3_DCTL_APPL1RES (1 << 23) -#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) -#define DWC3_DCTL_TRGTULST(n) ((n) << 17) - -#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) -#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) -#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) -#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) -#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) +/* These apply for core versions 1.87a and earlier */ +#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) +#define DWC3_DCTL_TRGTULST(n) ((n) << 17) +#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) +#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) +#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) +#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) +#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) + +/* These apply for core versions 1.94a and later */ +#define DWC3_DCTL_KEEP_CONNECT (1 << 19) +#define DWC3_DCTL_L1_HIBER_EN (1 << 18) +#define DWC3_DCTL_CRS (1 << 17) +#define DWC3_DCTL_CSS (1 << 16) #define DWC3_DCTL_INITU2ENA (1 << 12) #define DWC3_DCTL_ACCEPTU2ENA (1 << 11) @@ -249,6 +266,7 @@ #define DWC3_DEVTEN_ERRTICERREN (1 << 9) #define DWC3_DEVTEN_SOFEN (1 << 7) #define DWC3_DEVTEN_EOPFEN (1 << 6) +#define DWC3_DEVTEN_HIBERNATIONREQEVTEN (1 << 5) #define DWC3_DEVTEN_WKUPEVTEN (1 << 4) #define DWC3_DEVTEN_ULSTCNGEN (1 << 3) #define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) @@ -256,7 +274,15 @@ #define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) /* Device Status Register */ +#define DWC3_DSTS_DCNRD (1 << 29) + +/* This applies for core versions 1.87a and earlier */ #define DWC3_DSTS_PWRUPREQ (1 << 24) + +/* These apply for core versions 1.94a and later */ +#define DWC3_DSTS_RSS (1 << 25) +#define DWC3_DSTS_SSS (1 << 24) + #define DWC3_DSTS_COREIDLE (1 << 23) #define DWC3_DSTS_DEVCTRLHLT (1 << 22) @@ -280,6 +306,11 @@ #define DWC3_DGCMD_SET_LMP 0x01 #define DWC3_DGCMD_SET_PERIODIC_PAR 0x02 #define DWC3_DGCMD_XMIT_FUNCTION 0x03 + +/* These apply for core versions 1.94a and later */ +#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO 0x04 +#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI 0x05 + #define DWC3_DGCMD_SELECTED_FIFO_FLUSH 0x09 #define DWC3_DGCMD_ALL_FIFO_FLUSH 0x0a #define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c @@ -287,6 +318,15 @@ #define DWC3_DGCMD_STATUS(n) (((n) >> 15) & 1) #define DWC3_DGCMD_CMDACT (1 << 10) +#define DWC3_DGCMD_CMDIOC (1 << 8) + +/* Device Generic Command Parameter Register */ +#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT (1 << 0) +#define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0) +#define DWC3_DGCMDPAR_RX_FIFO (0 << 5) +#define DWC3_DGCMDPAR_TX_FIFO (1 << 5) +#define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0) +#define DWC3_DGCMDPAR_LOOPBACK_ENA (1 << 0) /* Device Endpoint Command Register */ #define DWC3_DEPCMD_PARAM_SHIFT 16 @@ -303,7 +343,10 @@ #define DWC3_DEPCMD_STARTTRANSFER (0x06 << 0) #define DWC3_DEPCMD_CLEARSTALL (0x05 << 0) #define DWC3_DEPCMD_SETSTALL (0x04 << 0) +/* This applies for core versions 1.90a and earlier */ #define DWC3_DEPCMD_GETSEQNUMBER (0x03 << 0) +/* This applies for core versions 1.94a and later */ +#define DWC3_DEPCMD_GETEPSTATE (0x03 << 0) #define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) #define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) @@ -437,6 +480,8 @@ enum dwc3_link_state { DWC3_LINK_STATE_HRESET = 0x09, DWC3_LINK_STATE_CMPLY = 0x0a, DWC3_LINK_STATE_LPBK = 0x0b, + DWC3_LINK_STATE_RESET = 0x0e, + DWC3_LINK_STATE_RESUME = 0x0f, DWC3_LINK_STATE_MASK = 0x0f, }; @@ -455,6 +500,7 @@ enum dwc3_device_state { #define DWC3_TRBSTS_OK 0 #define DWC3_TRBSTS_MISSED_ISOC 1 #define DWC3_TRBSTS_SETUP_PENDING 2 +#define DWC3_TRB_STS_XFER_IN_PROG 4 /* TRB Control */ #define DWC3_TRB_CTRL_HWO (1 << 0) @@ -543,6 +589,14 @@ struct dwc3_request { unsigned queued:1; }; +/* + * struct dwc3_scratchpad_array - hibernation scratchpad array + * (format defined by hw) + */ +struct dwc3_scratchpad_array { + __le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS]; +}; + /** * struct dwc3 - representation of our controller * @ctrl_req: usb control request which is used for ep0 @@ -624,8 +678,10 @@ struct dwc3 { #define DWC3_REVISION_180A 0x5533180a #define DWC3_REVISION_183A 0x5533183a #define DWC3_REVISION_185A 0x5533185a +#define DWC3_REVISION_187A 0x5533187a #define DWC3_REVISION_188A 0x5533188a #define DWC3_REVISION_190A 0x5533190a +#define DWC3_REVISION_194A 0x5533194a #define DWC3_REVISION_200A 0x5533200a #define DWC3_REVISION_202A 0x5533202a #define DWC3_REVISION_210A 0x5533210a diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 95ef6a2f7764..39ced0b08515 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -66,7 +66,12 @@ struct dwc3; #define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) #define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) +/* This applies for core versions earlier than 1.94a */ #define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) +/* These apply for core versions 1.94a and later */ +#define DWC3_DEPCFG_ACTION_INIT (0 << 30) +#define DWC3_DEPCFG_ACTION_RESTORE (1 << 30) +#define DWC3_DEPCFG_ACTION_MODIFY (2 << 30) /* DEPXFERCFG parameter 0 */ #define DWC3_DEPXFERCFG_NUM_XFER_RES(n) ((n) & 0xffff) -- GitLab From aed430e5139af3e2c251f52db7fc6c5e2ce2b714 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 27 Apr 2012 12:52:01 +0300 Subject: [PATCH 0113/5711] usb: dwc3: gadget: reinitialize retries retries is used twice without being reinitialized. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 045799356a29..c21516aef5e4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -108,6 +108,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) dwc3_writel(dwc->regs, DWC3_DCTL, reg); /* wait for a change in DSTS */ + retries = 10000; while (--retries) { reg = dwc3_readl(dwc->regs, DWC3_DSTS); -- GitLab From d7a46a8dfc45191b39daa19c05d3ff74d1881f15 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 27 Apr 2012 12:54:05 +0300 Subject: [PATCH 0114/5711] usb: dwc3: gadget: rename phy_power() to phy_suspend() those two functions don't power PHYs, they simply put them in suspend state. Rename to reflect better what functions actually do. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c21516aef5e4..852bde5cc139 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1894,30 +1894,30 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc->setup_packet_pending = false; } -static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on) +static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) { u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - if (on) - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - else + if (suspend) reg |= DWC3_GUSB3PIPECTL_SUSPHY; + else + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); } -static void dwc3_gadget_usb2_phy_power(struct dwc3 *dwc, int on) +static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend) { u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - if (on) - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - else + if (suspend) reg |= DWC3_GUSB2PHYCFG_SUSPHY; + else + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } @@ -1962,9 +1962,9 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) /* after reset -> Default State */ dwc->dev_state = DWC3_DEFAULT_STATE; - /* Enable PHYs */ - dwc3_gadget_usb2_phy_power(dwc, true); - dwc3_gadget_usb3_phy_power(dwc, true); + /* Resume PHYs */ + dwc3_gadget_usb2_phy_suspend(dwc, false); + dwc3_gadget_usb3_phy_suspend(dwc, false); if (dwc->gadget.speed != USB_SPEED_UNKNOWN) dwc3_disconnect_gadget(dwc); @@ -2010,16 +2010,16 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) dwc3_writel(dwc->regs, DWC3_GCTL, reg); } -static void dwc3_gadget_disable_phy(struct dwc3 *dwc, u8 speed) +static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed) { switch (speed) { case USB_SPEED_SUPER: - dwc3_gadget_usb2_phy_power(dwc, false); + dwc3_gadget_usb2_phy_suspend(dwc, true); break; case USB_SPEED_HIGH: case USB_SPEED_FULL: case USB_SPEED_LOW: - dwc3_gadget_usb3_phy_power(dwc, false); + dwc3_gadget_usb3_phy_suspend(dwc, true); break; } } @@ -2082,8 +2082,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) break; } - /* Disable unneded PHY */ - dwc3_gadget_disable_phy(dwc, dwc->gadget.speed); + /* Suspend unneded PHY */ + dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed); dep = dwc->eps[0]; ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); -- GitLab From 802fde983e8a3391e059bd41fc272993ae642816 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 27 Apr 2012 13:10:52 +0300 Subject: [PATCH 0115/5711] usb: dwc3: support new revisions of DWC3 core Recent cores (>= 1.94a) have a set of new features, commands and a slightly different programming model. This patch aims to support those changes. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 83 +++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 852bde5cc139..04048333ec1a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -100,6 +100,23 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) int retries = 10000; u32 reg; + /* + * Wait until device controller is ready. Only applies to 1.94a and + * later RTL. + */ + if (dwc->revision >= DWC3_REVISION_194A) { + while (--retries) { + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + if (reg & DWC3_DSTS_DCNRD) + udelay(5); + else + break; + } + + if (retries <= 0) + return -ETIMEDOUT; + } + reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; @@ -107,6 +124,13 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) reg |= DWC3_DCTL_ULSTCHNGREQ(state); dwc3_writel(dwc->regs, DWC3_DCTL, reg); + /* + * The following code is racy when called from dwc3_gadget_wakeup, + * and is not needed, at least on newer versions + */ + if (dwc->revision >= DWC3_REVISION_194A) + return 0; + /* wait for a change in DSTS */ retries = 10000; while (--retries) { @@ -266,8 +290,8 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd) return "Clear Stall"; case DWC3_DEPCMD_SETSTALL: return "Set Stall"; - case DWC3_DEPCMD_GETSEQNUMBER: - return "Get Data Sequence Number"; + case DWC3_DEPCMD_GETEPSTATE: + return "Get Endpoint State"; case DWC3_DEPCMD_SETTRANSFRESOURCE: return "Set Endpoint Transfer Resource"; case DWC3_DEPCMD_SETEPCONFIG: @@ -1280,9 +1304,12 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) goto out; } - /* write zeroes to Link Change Request */ - reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + /* Recent versions do this automatically */ + if (dwc->revision < DWC3_REVISION_194A) { + /* write zeroes to Link Change Request */ + reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + } /* poll until Link State changes to ON */ timeout = jiffies + msecs_to_jiffies(100); @@ -1326,9 +1353,14 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (is_on) { - reg &= ~DWC3_DCTL_TRGTULST_MASK; - reg |= (DWC3_DCTL_RUN_STOP - | DWC3_DCTL_TRGTULST_RX_DET); + if (dwc->revision <= DWC3_REVISION_187A) { + reg &= ~DWC3_DCTL_TRGTULST_MASK; + reg |= DWC3_DCTL_TRGTULST_RX_DET; + } + + if (dwc->revision >= DWC3_REVISION_194A) + reg &= ~DWC3_DCTL_KEEP_CONNECT; + reg |= DWC3_DCTL_RUN_STOP; } else { reg &= ~DWC3_DCTL_RUN_STOP; } @@ -1468,6 +1500,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g, return 0; } + static const struct usb_gadget_ops dwc3_gadget_ops = { .get_frame = dwc3_gadget_get_frame, .wakeup = dwc3_gadget_wakeup, @@ -1962,9 +1995,12 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) /* after reset -> Default State */ dwc->dev_state = DWC3_DEFAULT_STATE; - /* Resume PHYs */ - dwc3_gadget_usb2_phy_suspend(dwc, false); - dwc3_gadget_usb3_phy_suspend(dwc, false); + /* Recent versions support automatic phy suspend and don't need this */ + if (dwc->revision < DWC3_REVISION_194A) { + /* Resume PHYs */ + dwc3_gadget_usb2_phy_suspend(dwc, false); + dwc3_gadget_usb3_phy_suspend(dwc, false); + } if (dwc->gadget.speed != USB_SPEED_UNKNOWN) dwc3_disconnect_gadget(dwc); @@ -2082,8 +2118,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) break; } - /* Suspend unneded PHY */ - dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed); + /* Recent versions support automatic phy suspend and don't need this */ + if (dwc->revision < DWC3_REVISION_194A) { + /* Suspend unneeded PHY */ + dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed); + } dep = dwc->eps[0]; ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); @@ -2389,6 +2428,24 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) DWC3_DEVTEN_DISCONNEVTEN); dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); + /* Enable USB2 LPM and automatic phy suspend only on recent versions */ + if (dwc->revision >= DWC3_REVISION_194A) { + reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg |= DWC3_DCFG_LPM_CAP; + dwc3_writel(dwc->regs, DWC3_DCFG, reg); + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); + + /* TODO: This should be configurable */ + reg |= DWC3_DCTL_HIRD_THRES(31); + + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + dwc3_gadget_usb2_phy_suspend(dwc, true); + dwc3_gadget_usb3_phy_suspend(dwc, true); + } + ret = device_register(&dwc->gadget.dev); if (ret) { dev_err(dwc->dev, "failed to register gadget device\n"); -- GitLab From 7acd85e0eb2ed300edf123178445237059b35fb9 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 27 Apr 2012 14:28:02 +0300 Subject: [PATCH 0116/5711] usb: dwc3: core: make sure evt->lpos is correctly initialized The same event buffers will be reused when coming out of hibernation, so we must reinitialize them properly to avoid any mistakes. While at that, also take dwc3_event_buffers_setup() out of __devinit section. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1040bdb8dc88..49c060205c9a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -255,7 +255,7 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) * * Returns 0 on success otherwise negative errno. */ -static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) +static int dwc3_event_buffers_setup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; int n; @@ -266,6 +266,8 @@ static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) evt->buf, (unsigned long long) evt->dma, evt->length); + evt->lpos = 0; + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), lower_32_bits(evt->dma)); dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), @@ -285,6 +287,9 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) for (n = 0; n < dwc->num_event_buffers; n++) { evt = dwc->ev_buffs[n]; + + evt->lpos = 0; + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); -- GitLab From fcc023c726b5879d8f3f0f0f48c45d09055272c4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 May 2012 10:27:56 +0300 Subject: [PATCH 0117/5711] usb: dwc3: gadget: prevent DCTL register corruption If we don't read out the contents of the register (in order to reinitialize 'reg' variable) we will be writing unknown contents to the DCTL register whenever we try to use dwc3_gadget_wakeup() function. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 04048333ec1a..867c476853ec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1307,6 +1307,7 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) /* Recent versions do this automatically */ if (dwc->revision < DWC3_REVISION_194A) { /* write zeroes to Link Change Request */ + reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; dwc3_writel(dwc->regs, DWC3_DCTL, reg); } -- GitLab From c4430a26948b84c0d820e83f8c640229f960d3b6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 May 2012 10:30:01 +0300 Subject: [PATCH 0118/5711] usb: dwc3: gadget: disable U1/U2 on disconnect If we get a disconnect IRQ, we should take the core out of low power mode so we can reconnect afterwards. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 867c476853ec..054ee5ec5c13 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1906,11 +1906,9 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) { + int reg; + dev_vdbg(dwc->dev, "%s\n", __func__); -#if 0 - XXX - U1/U2 is powersave optimization. Skip it for now. Anyway we need to - enable it before we can disable it. reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_INITU1ENA; @@ -1918,7 +1916,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) reg &= ~DWC3_DCTL_INITU2ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); -#endif dwc3_stop_active_transfers(dwc); dwc3_disconnect_gadget(dwc); -- GitLab From 5cbe8c220c1e126dd0855ad57fe4491b267132b9 Mon Sep 17 00:00:00 2001 From: Gerard CAUVY Date: Thu, 24 May 2012 12:47:36 +0300 Subject: [PATCH 0119/5711] usb: dwc3: gadget: move AcceptU1Ena and AcceptU2Ena to Reset IRQ According to the databook, the DWC3 Core will reset those bits to 0 on USB Bus Reset. This means we must re-enable those bits on every reset interrupt. Because we will always get a Reset interrupt after loading a gadget driver, we can, instead of re-enabling something that was just lost, move the handling of those bits to the Reset Interrupt. This patch fixes USB30CV U1/U2 Test. Signed-off-by: Gerard CAUVY Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 054ee5ec5c13..a9fc7c4a5a20 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2006,6 +2006,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_TSTCTRL_MASK; reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA); + reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc->test_mode = false; @@ -2410,10 +2411,6 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) reg |= DWC3_DCFG_LPM_CAP; dwc3_writel(dwc->regs, DWC3_DCFG, reg); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - /* Enable all but Start and End of Frame IRQs */ reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | DWC3_DEVTEN_EVNTOVERFLOWEN | -- GitLab From ef21ede65ee3e0dfd8f2cb37de8892816e2f1257 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 31 May 2012 10:29:49 +0300 Subject: [PATCH 0120/5711] usb: dwc3: ep0: simplify error handling on dwc3_ep0_inspect_setup There's no need for returning early. Instead, we can call dwc3_ep0_stall_and_restart() conditionally. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e31bcd65e7ec..83fcf392dda7 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -641,11 +641,11 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct usb_ctrlrequest *ctrl = dwc->ctrl_req; - int ret; + int ret = -EINVAL; u32 len; if (!dwc->gadget_driver) - goto err; + goto out; len = le16_to_cpu(ctrl->wLength); if (!len) { @@ -666,11 +666,9 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, if (ret == USB_GADGET_DELAYED_STATUS) dwc->delayed_status = true; - if (ret >= 0) - return; - -err: - dwc3_ep0_stall_and_restart(dwc); +out: + if (ret < 0) + dwc3_ep0_stall_and_restart(dwc); } static void dwc3_ep0_complete_data(struct dwc3 *dwc, -- GitLab From c8cf7af452ad2eb49cad13450090cdc432b5a06d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 31 May 2012 11:00:28 +0300 Subject: [PATCH 0121/5711] usb: dwc3: ep0: be careful with endianness on SetSEL command USB is always little endian, but this driver could run on non little endian cpus. Let's be carefull with that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 83fcf392dda7..3185fe14591b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -515,8 +515,8 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) dwc->u1sel = timing.u1sel; dwc->u1pel = timing.u1pel; - dwc->u2sel = timing.u2sel; - dwc->u2pel = timing.u2pel; + dwc->u2sel = le16_to_cpu(timing.u2sel); + dwc->u2pel = le16_to_cpu(timing.u2pel); reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (reg & DWC3_DCTL_INITU2ENA) -- GitLab From 85a781019b9b4b935f6b1792a1f48f1a3aee988f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 31 May 2012 12:32:37 +0300 Subject: [PATCH 0122/5711] usb: dwc3: ep0: rename dwc3_ep0_complete_req to dwc3_ep0_complete_status That's a much more intuitive name as that function is only called at the completion of a Status Phase. It also matches dwc3_ep0_complete_data() for the completion of Data Phase. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3185fe14591b..90eb1ba65454 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -722,7 +722,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, } } -static void dwc3_ep0_complete_req(struct dwc3 *dwc, +static void dwc3_ep0_complete_status(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct dwc3_request *r; @@ -773,7 +773,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, case EP0_STATUS_PHASE: dev_vdbg(dwc->dev, "Status Phase\n"); - dwc3_ep0_complete_req(dwc, event); + dwc3_ep0_complete_status(dwc, event); break; default: WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state); -- GitLab From ae3725716edf5a73ab66831c0808542c21fa3bba Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 21 May 2012 12:01:11 -0700 Subject: [PATCH 0123/5711] usb: gadget: omap_udc: Remove omap2 support There are no active users of this code for omap2 as the boards in use have either TUSB or MUSB controller. While at it, also fix warnings related to uninitialized dc_clk and hhc_clk. Cc: linux-usb@vger.kernel.org Cc: Kyungmin Park Signed-off-by: Tony Lindgren Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 113 +++++++--------------------------- 1 file changed, 23 insertions(+), 90 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 7ba32469c5bd..24d81dcb7b4b 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -61,9 +61,6 @@ #define DMA_ADDR_INVALID (~(dma_addr_t)0) -#define OMAP2_DMA_CH(ch) (((ch) - 1) << 1) -#define OMAP24XX_DMA(name, ch) (OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch)) - /* * The OMAP UDC needs _very_ early endpoint setup: before enabling the * D+ pullup to allow enumeration. That's too early for the gadget @@ -536,12 +533,8 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) : OMAP_DMA_SYNC_ELEMENT; int dma_trigger = 0; - if (cpu_is_omap24xx()) - dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel); - /* measure length in either bytes or packets */ if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC) - || (cpu_is_omap24xx() && length < ep->maxpacket) || (cpu_is_omap15xx() && length < ep->maxpacket)) { txdma_ctrl = UDC_TXN_EOT | length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, @@ -600,28 +593,14 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) int dma_trigger = 0; u16 w; - if (cpu_is_omap24xx()) - dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel); - - /* NOTE: we filtered out "short reads" before, so we know - * the buffer has only whole numbers of packets. - * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode - */ - if (cpu_is_omap24xx() && packets < ep->maxpacket) { - omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, - packets, 1, OMAP_DMA_SYNC_ELEMENT, - dma_trigger, 0); - req->dma_bytes = packets; - } else { - /* set up this DMA transfer, enable the fifo, start */ - packets /= ep->ep.maxpacket; - packets = min(packets, (unsigned)UDC_RXN_TC + 1); - req->dma_bytes = packets * ep->ep.maxpacket; - omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, - ep->ep.maxpacket >> 1, packets, - OMAP_DMA_SYNC_ELEMENT, - dma_trigger, 0); - } + /* set up this DMA transfer, enable the fifo, start */ + packets /= ep->ep.maxpacket; + packets = min(packets, (unsigned)UDC_RXN_TC + 1); + req->dma_bytes = packets * ep->ep.maxpacket; + omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, + ep->ep.maxpacket >> 1, packets, + OMAP_DMA_SYNC_ELEMENT, + dma_trigger, 0); omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, 0, 0); @@ -760,10 +739,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) ep->dma_channel = channel; if (is_in) { - if (cpu_is_omap24xx()) - dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel); - else - dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel; + dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel; status = omap_request_dma(dma_channel, ep->ep.name, dma_error, ep, &ep->lch); if (status == 0) { @@ -780,11 +756,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) 0, 0); } } else { - if (cpu_is_omap24xx()) - dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel); - else - dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel; - + dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel; status = omap_request_dma(dma_channel, ep->ep.name, dma_error, ep, &ep->lch); if (status == 0) { @@ -808,7 +780,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ); /* channel type P: hw synch (fifo) */ - if (cpu_class_is_omap1() && !cpu_is_omap15xx()) + if (!cpu_is_omap15xx()) omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P); } @@ -928,13 +900,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* this isn't bogus, but OMAP DMA isn't the only hardware to * have a hard time with partial packet reads... reject it. - * Except OMAP2 can handle the small packets. */ if (use_dma && ep->has_dma && ep->bEndpointAddress != 0 && (ep->bEndpointAddress & USB_DIR_IN) == 0 - && !cpu_class_is_omap2() && (req->req.length % ep->ep.maxpacket) != 0) { DBG("%s, no partial packet OUT reads\n", __func__); return -EMSGSIZE; @@ -2090,10 +2060,6 @@ static inline int machine_without_vbus_sense(void) { return (machine_is_omap_innovator() || machine_is_omap_osk() - || machine_is_omap_apollon() -#ifndef CONFIG_MACH_OMAP_H4_OTG - || machine_is_omap_h4() -#endif || machine_is_sx1() || cpu_is_omap7xx() /* No known omap7xx boards with vbus sense */ ); @@ -2307,12 +2273,9 @@ static int proc_otg_show(struct seq_file *s) u32 trans = 0; char *ctrl_name = "(UNKNOWN)"; - /* XXX This needs major revision for OMAP2+ */ tmp = omap_readl(OTG_REV); - if (cpu_class_is_omap1()) { - ctrl_name = "tranceiver_ctrl"; - trans = omap_readw(USB_TRANSCEIVER_CTRL); - } + ctrl_name = "tranceiver_ctrl"; + trans = omap_readw(USB_TRANSCEIVER_CTRL); seq_printf(s, "\nOTG rev %d.%d, %s %05x\n", tmp >> 4, tmp & 0xf, ctrl_name, trans); tmp = omap_readw(OTG_SYSCON_1); @@ -2399,14 +2362,12 @@ static int proc_udc_show(struct seq_file *s, void *_) HMC, udc->transceiver ? udc->transceiver->label - : ((cpu_is_omap1710() || cpu_is_omap24xx()) + : (cpu_is_omap1710() ? "external" : "(none)")); - if (cpu_class_is_omap1()) { - seq_printf(s, "ULPD control %04x req %04x status %04x\n", - omap_readw(ULPD_CLOCK_CTRL), - omap_readw(ULPD_SOFT_REQ), - omap_readw(ULPD_STATUS_REQ)); - } + seq_printf(s, "ULPD control %04x req %04x status %04x\n", + omap_readw(ULPD_CLOCK_CTRL), + omap_readw(ULPD_SOFT_REQ), + omap_readw(ULPD_STATUS_REQ)); /* OTG controller registers */ if (!cpu_is_omap15xx()) @@ -2591,7 +2552,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, * and ignored for PIO-IN on newer chips * (for more reliable behavior) */ - if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx()) + if (!use_dma || cpu_is_omap15xx()) dbuf = 0; switch (maxp) { @@ -2795,8 +2756,8 @@ static int __init omap_udc_probe(struct platform_device *pdev) struct usb_phy *xceiv = NULL; const char *type = NULL; struct omap_usb_config *config = pdev->dev.platform_data; - struct clk *dc_clk; - struct clk *hhc_clk; + struct clk *dc_clk = NULL; + struct clk *hhc_clk = NULL; /* NOTE: "knows" the order of the resources! */ if (!request_mem_region(pdev->resource[0].start, @@ -2816,16 +2777,6 @@ static int __init omap_udc_probe(struct platform_device *pdev) udelay(100); } - if (cpu_is_omap24xx()) { - dc_clk = clk_get(&pdev->dev, "usb_fck"); - hhc_clk = clk_get(&pdev->dev, "usb_l4_ick"); - BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); - /* can't use omap_udc_enable_clock yet */ - clk_enable(dc_clk); - clk_enable(hhc_clk); - udelay(100); - } - if (cpu_is_omap7xx()) { dc_clk = clk_get(&pdev->dev, "usb_dc_ck"); hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck"); @@ -2875,14 +2826,6 @@ static int __init omap_udc_probe(struct platform_device *pdev) hmc = HMC_1610; - if (cpu_is_omap24xx()) { - /* this could be transceiverless in one of the - * "we don't need to know" modes. - */ - type = "external"; - goto known; - } - switch (hmc) { case 0: /* POWERUP DEFAULT == 0 */ case 4: @@ -2921,7 +2864,7 @@ bad_on_1710: goto cleanup0; } } -known: + INFO("hmc mode %d, %s transceiver\n", hmc, type); /* a "gadget" abstracts/virtualizes the controller */ @@ -2975,16 +2918,6 @@ known: clk_disable(dc_clk); } - if (cpu_is_omap24xx()) { - udc->dc_clk = dc_clk; - udc->hhc_clk = hhc_clk; - /* FIXME OMAP2 don't release hhc & dc clock */ -#if 0 - clk_disable(hhc_clk); - clk_disable(dc_clk); -#endif - } - create_proc_file(); status = device_add(&udc->gadget.dev); if (status) @@ -3013,7 +2946,7 @@ cleanup0: if (xceiv) usb_put_transceiver(xceiv); - if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) { + if (cpu_is_omap16xx() || cpu_is_omap7xx()) { clk_disable(hhc_clk); clk_disable(dc_clk); clk_put(hhc_clk); -- GitLab From 80dd1358d33e6c85018e1e1c5d78b29ac466221a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:26:09 +0300 Subject: [PATCH 0124/5711] usb: gadget: omap_udc: make checkpatch.pl happy This patch is just a cleanup patch to make checkpatch.pl a little happier with the omap_udc.c driver. No functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 201 ++++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 80 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 24d81dcb7b4b..aa2d174a2521 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -36,9 +36,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -84,14 +84,14 @@ #ifdef USE_ISO static unsigned fifo_mode = 3; #else -static unsigned fifo_mode = 0; +static unsigned fifo_mode; #endif /* "modprobe omap_udc fifo_mode=42", or else as a kernel * boot parameter "omap_udc:fifo_mode=42" */ -module_param (fifo_mode, uint, 0); -MODULE_PARM_DESC (fifo_mode, "endpoint configuration"); +module_param(fifo_mode, uint, 0); +MODULE_PARM_DESC(fifo_mode, "endpoint configuration"); #ifdef USE_DMA static bool use_dma = 1; @@ -99,8 +99,8 @@ static bool use_dma = 1; /* "modprobe omap_udc use_dma=y", or else as a kernel * boot parameter "omap_udc:use_dma=y" */ -module_param (use_dma, bool, 0); -MODULE_PARM_DESC (use_dma, "enable/disable DMA"); +module_param(use_dma, bool, 0); +MODULE_PARM_DESC(use_dma, "enable/disable DMA"); #else /* !USE_DMA */ /* save a bit of code */ @@ -108,8 +108,8 @@ MODULE_PARM_DESC (use_dma, "enable/disable DMA"); #endif /* !USE_DMA */ -static const char driver_name [] = "omap_udc"; -static const char driver_desc [] = DRIVER_DESC; +static const char driver_name[] = "omap_udc"; +static const char driver_desc[] = DRIVER_DESC; /*-------------------------------------------------------------------------*/ @@ -247,7 +247,7 @@ static int omap_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&ep->udc->lock, flags); ep->ep.desc = NULL; - nuke (ep, -ESHUTDOWN); + nuke(ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; ep->has_dma = 0; omap_writew(UDC_SET_HALT, UDC_CTRL); @@ -270,7 +270,7 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) req = kzalloc(sizeof(*req), gfp_flags); if (req) { req->req.dma = DMA_ADDR_INVALID; - INIT_LIST_HEAD (&req->queue); + INIT_LIST_HEAD(&req->queue); } return &req->req; } @@ -281,7 +281,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) struct omap_req *req = container_of(_req, struct omap_req, req); if (_req) - kfree (req); + kfree(req); } /*-------------------------------------------------------------------------*/ @@ -361,10 +361,10 @@ write_packet(u8 *buf, struct omap_req *req, unsigned max) return len; } -// FIXME change r/w fifo calling convention +/* FIXME change r/w fifo calling convention */ -// return: 0 = still running, 1 = completed, negative = errno +/* return: 0 = still running, 1 = completed, negative = errno */ static int write_fifo(struct omap_ep *ep, struct omap_req *req) { u8 *buf; @@ -426,7 +426,7 @@ read_packet(u8 *buf, struct omap_req *req, unsigned avail) return len; } -// return: 0 = still running, 1 = queue empty, negative = errno +/* return: 0 = still running, 1 = queue empty, negative = errno */ static int read_fifo(struct omap_ep *ep, struct omap_req *req) { u8 *buf; @@ -662,7 +662,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) } omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC); - if (!list_empty (&ep->queue)) { + if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct omap_req, queue); next_in_dma(ep, req); @@ -681,7 +681,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) } omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC); - if (!list_empty (&ep->queue)) { + if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct omap_req, queue); next_out_dma(ep, req); @@ -954,7 +954,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) int is_in; if (ep->bEndpointAddress == 0) { - if (!udc->ep0_pending || !list_empty (&ep->queue)) { + if (!udc->ep0_pending || !list_empty(&ep->queue)) { spin_unlock_irqrestore(&udc->lock, flags); return -EL2HLT; } @@ -981,7 +981,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) * always an IN ... even for IN transfers, * a weird case which seem to stall OMAP. */ - omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); + omap_writew(UDC_EP_SEL | UDC_EP_DIR, + UDC_EP_NUM); omap_writew(UDC_CLR_EP, UDC_CTRL); omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); omap_writew(UDC_EP_DIR, UDC_EP_NUM); @@ -993,7 +994,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* non-empty DATA stage */ } else if (is_in) { - omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); + omap_writew(UDC_EP_SEL | UDC_EP_DIR, + UDC_EP_NUM); } else { if (udc->ep0_setup) goto irq_wait; @@ -1041,7 +1043,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) spin_lock_irqsave(&ep->udc->lock, flags); /* make sure it's actually queued on this endpoint */ - list_for_each_entry (req, &ep->queue, queue) { + list_for_each_entry(req, &ep->queue, queue) { if (&req->req == _req) break; } @@ -1148,8 +1150,8 @@ static struct usb_ep_ops omap_ep_ops = { .dequeue = omap_ep_dequeue, .set_halt = omap_ep_set_halt, - // fifo_status ... report bytes in fifo - // fifo_flush ... flush fifo + /* fifo_status ... report bytes in fifo */ + /* fifo_flush ... flush fifo */ }; /*-------------------------------------------------------------------------*/ @@ -1379,7 +1381,7 @@ static void udc_quiesce(struct omap_udc *udc) udc->gadget.speed = USB_SPEED_UNKNOWN; nuke(&udc->ep[0], -ESHUTDOWN); - list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) nuke(ep, -ESHUTDOWN); } @@ -1495,7 +1497,8 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) /* read next OUT packet of request, maybe * reactiviting the fifo; stall on errors. */ - if (!req || (stat = read_fifo(ep0, req)) < 0) { + stat = read_fifo(ep0, req); + if (!req || stat < 0) { omap_writew(UDC_STALL_CMD, UDC_SYSCON2); udc->ep0_pending = 0; stat = 0; @@ -1628,7 +1631,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) /* this has rude side-effects (aborts) and * can't really work if DMA-IN is active */ - DBG("%s host set_halt, NYET \n", ep->name); + DBG("%s host set_halt, NYET\n", ep->name); goto do_stall; } use_ep(ep, 0); @@ -1719,7 +1722,7 @@ delegate: */ udc->ep0_setup = 1; spin_unlock(&udc->lock); - status = udc->driver->setup (&udc->gadget, &u.r); + status = udc->driver->setup(&udc->gadget, &u.r); spin_lock(&udc->lock); udc->ep0_setup = 0; } @@ -1764,7 +1767,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) VDBG("connect\n"); if (!udc->transceiver) pullup_enable(udc); - // if (driver->connect) call it + /* if (driver->connect) call it */ } else if (udc->gadget.speed != USB_SPEED_UNKNOWN) { udc->gadget.speed = USB_SPEED_UNKNOWN; if (!udc->transceiver) @@ -1796,7 +1799,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) } if (change & UDC_SUS) { if (udc->gadget.speed != USB_SPEED_UNKNOWN) { - // FIXME tell isp1301 to suspend/resume (?) + /* FIXME tell isp1301 to suspend/resume (?) */ if (devstat & UDC_SUS) { VDBG("suspend\n"); update_otg(udc); @@ -1999,7 +2002,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) spin_lock_irqsave(&udc->lock, flags); /* handle all non-DMA ISO transfers */ - list_for_each_entry (ep, &udc->iso, iso) { + list_for_each_entry(ep, &udc->iso, iso) { u16 stat; struct omap_req *req; @@ -2058,11 +2061,11 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) static inline int machine_without_vbus_sense(void) { - return (machine_is_omap_innovator() + return machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_sx1() - || cpu_is_omap7xx() /* No known omap7xx boards with vbus sense */ - ); + /* No known omap7xx boards with vbus sense */ + || cpu_is_omap7xx(); } static int omap_udc_start(struct usb_gadget_driver *driver, @@ -2076,7 +2079,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, if (!udc) return -ENODEV; if (!driver - // FIXME if otg, check: driver->is_otg + /* FIXME if otg, check: driver->is_otg */ || driver->max_speed < USB_SPEED_FULL || !bind || !driver->setup) return -EINVAL; @@ -2088,7 +2091,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, } /* reset state */ - list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { ep->irqs = 0; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) continue; @@ -2126,7 +2129,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, if (status < 0) { ERR("can't bind to transceiver\n"); if (driver->unbind) { - driver->unbind (&udc->gadget); + driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; udc->driver = NULL; } @@ -2134,9 +2137,9 @@ static int omap_udc_start(struct usb_gadget_driver *driver, } } else { if (can_pullup(udc)) - pullup_enable (udc); + pullup_enable(udc); else - pullup_disable (udc); + pullup_disable(udc); } /* boards that don't have VBUS sensing can't autogate 48MHz; @@ -2195,7 +2198,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver) static const char proc_filename[] = "driver/udc"; #define FOURBITS "%s%s%s%s" -#define EIGHTBITS FOURBITS FOURBITS +#define EIGHTBITS "%s%s%s%s%s%s%s%s" static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) { @@ -2217,12 +2220,21 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n", ep->name, buf, ep->double_buf ? "dbuf " : "", - ({char *s; switch(ep->ackwait){ - case 0: s = ""; break; - case 1: s = "(ackw) "; break; - case 2: s = "(ackw2) "; break; - default: s = "(?) "; break; - } s;}), + ({ char *s; + switch (ep->ackwait) { + case 0: + s = ""; + break; + case 1: + s = "(ackw) "; + break; + case 2: + s = "(ackw2) "; + break; + default: + s = "(?) "; + break; + } s; }), ep->irqs, stat_flg, (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "", (stat_flg & UDC_MISS_IN) ? "miss_in " : "", @@ -2238,10 +2250,10 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) (stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "", (stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : ""); - if (list_empty (&ep->queue)) + if (list_empty(&ep->queue)) seq_printf(s, "\t(queue empty)\n"); else - list_for_each_entry (req, &ep->queue, queue) { + list_for_each_entry(req, &ep->queue, queue) { unsigned length = req->req.actual; if (use_dma && buf[0]) { @@ -2259,11 +2271,16 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) static char *trx_mode(unsigned m, int enabled) { switch (m) { - case 0: return enabled ? "*6wire" : "unused"; - case 1: return "4wire"; - case 2: return "3wire"; - case 3: return "6wire"; - default: return "unknown"; + case 0: + return enabled ? "*6wire" : "unused"; + case 1: + return "4wire"; + case 2: + return "3wire"; + case 3: + return "6wire"; + default: + return "unknown"; } } @@ -2295,7 +2312,7 @@ static int proc_otg_show(struct seq_file *s) " b_ase_brst=%d hmc=%d\n", tmp, (tmp & OTG_EN) ? " otg_en" : "", (tmp & USBX_SYNCHRO) ? " synchro" : "", - // much more SRP stuff + /* much more SRP stuff */ (tmp & SRP_DATA) ? " srp_data" : "", (tmp & SRP_VBUS) ? " srp_vbus" : "", (tmp & OTG_PADEN) ? " otg_paden" : "", @@ -2383,7 +2400,7 @@ static int proc_udc_show(struct seq_file *s, void *_) (tmp & UDC_SELF_PWR) ? " self_pwr" : "", (tmp & UDC_SOFF_DIS) ? " soff_dis" : "", (tmp & UDC_PULLUP_EN) ? " PULLUP" : ""); - // syscon2 is write-only + /* syscon2 is write-only */ /* UDC controller registers */ if (!(tmp & UDC_PULLUP_EN)) { @@ -2467,7 +2484,7 @@ static int proc_udc_show(struct seq_file *s, void *_) if (tmp & UDC_ATT) { proc_ep_show(s, &udc->ep[0]); if (tmp & UDC_ADD) { - list_for_each_entry (ep, &udc->gadget.ep_list, + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { if (ep->ep.desc) proc_ep_show(s, ep); @@ -2536,14 +2553,29 @@ omap_ep_setup(char *name, u8 addr, u8 type, /* chip setup ... bit values are same for IN, OUT */ if (type == USB_ENDPOINT_XFER_ISOC) { switch (maxp) { - case 8: epn_rxtx = 0 << 12; break; - case 16: epn_rxtx = 1 << 12; break; - case 32: epn_rxtx = 2 << 12; break; - case 64: epn_rxtx = 3 << 12; break; - case 128: epn_rxtx = 4 << 12; break; - case 256: epn_rxtx = 5 << 12; break; - case 512: epn_rxtx = 6 << 12; break; - default: BUG(); + case 8: + epn_rxtx = 0 << 12; + break; + case 16: + epn_rxtx = 1 << 12; + break; + case 32: + epn_rxtx = 2 << 12; + break; + case 64: + epn_rxtx = 3 << 12; + break; + case 128: + epn_rxtx = 4 << 12; + break; + case 256: + epn_rxtx = 5 << 12; + break; + case 512: + epn_rxtx = 6 << 12; + break; + default: + BUG(); } epn_rxtx |= UDC_EPN_RX_ISO; dbuf = 1; @@ -2556,11 +2588,20 @@ omap_ep_setup(char *name, u8 addr, u8 type, dbuf = 0; switch (maxp) { - case 8: epn_rxtx = 0 << 12; break; - case 16: epn_rxtx = 1 << 12; break; - case 32: epn_rxtx = 2 << 12; break; - case 64: epn_rxtx = 3 << 12; break; - default: BUG(); + case 8: + epn_rxtx = 0 << 12; + break; + case 16: + epn_rxtx = 1 << 12; + break; + case 32: + epn_rxtx = 2 << 12; + break; + case 64: + epn_rxtx = 3 << 12; + break; + default: + BUG(); } if (dbuf && addr) epn_rxtx |= UDC_EPN_RX_DB; @@ -2600,7 +2641,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, ep->ep.name = ep->name; ep->ep.ops = &omap_ep_ops; ep->ep.maxpacket = ep->maxpacket = maxp; - list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list); + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); return buf; } @@ -2608,7 +2649,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, static void omap_udc_release(struct device *dev) { complete(udc->done); - kfree (udc); + kfree(udc); udc = NULL; } @@ -2626,13 +2667,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) omap_writew(0, UDC_TXDMA_CFG); /* UDC_PULLUP_EN gates the chip clock */ - // OTG_SYSCON_1 |= DEV_IDLE_EN; + /* OTG_SYSCON_1 |= DEV_IDLE_EN; */ udc = kzalloc(sizeof(*udc), GFP_KERNEL); if (!udc) return -ENOMEM; - spin_lock_init (&udc->lock); + spin_lock_init(&udc->lock); udc->gadget.ops = &omap_gadget_ops; udc->gadget.ep0 = &udc->ep[0].ep; @@ -2662,13 +2703,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) omap_writew(0, UDC_EP_TX(tmp)); } -#define OMAP_BULK_EP(name,addr) \ +#define OMAP_BULK_EP(name, addr) \ buf = omap_ep_setup(name "-bulk", addr, \ USB_ENDPOINT_XFER_BULK, buf, 64, 1); -#define OMAP_INT_EP(name,addr, maxp) \ +#define OMAP_INT_EP(name, addr, maxp) \ buf = omap_ep_setup(name "-int", addr, \ USB_ENDPOINT_XFER_INT, buf, maxp, 0); -#define OMAP_ISO_EP(name,addr, maxp) \ +#define OMAP_ISO_EP(name, addr, maxp) \ buf = omap_ep_setup(name "-iso", addr, \ USB_ENDPOINT_XFER_ISOC, buf, maxp, 1); @@ -2869,11 +2910,11 @@ bad_on_1710: /* a "gadget" abstracts/virtualizes the controller */ status = omap_udc_setup(pdev, xceiv); - if (status) { + if (status) goto cleanup0; - } + xceiv = NULL; - // "udc" is now valid + /* "udc" is now valid */ pullup_disable(udc); #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) udc->gadget.is_otg = (config->otg != 0); @@ -2887,7 +2928,7 @@ bad_on_1710: /* USB general purpose IRQ: ep0, state changes, dma, etc */ status = request_irq(pdev->resource[1].start, omap_udc_irq, - IRQF_SAMPLE_RANDOM, driver_name, udc); + 0, driver_name, udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[1].start, status); @@ -2896,7 +2937,7 @@ bad_on_1710: /* USB "non-iso" IRQ (PIO for all but ep0) */ status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, - IRQF_SAMPLE_RANDOM, "omap_udc pio", udc); + 0, "omap_udc pio", udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[2].start, status); @@ -2939,7 +2980,7 @@ cleanup2: free_irq(pdev->resource[1].start, udc); cleanup1: - kfree (udc); + kfree(udc); udc = NULL; cleanup0: -- GitLab From 5b6d84b78930a4fa3f8380dc0ec4ac427d620201 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:27:52 +0300 Subject: [PATCH 0125/5711] usb: gadget: omap_udc: remove useless print that print isn't needed at all. Remove it and move the use_dma reinitialization to probe() function. Note that ideally we would drop all cpu_is_* and machine_is_* checks from this driver instead. Later patches will come to get rid of those. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index aa2d174a2521..5e7b8912ef31 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2800,6 +2800,9 @@ static int __init omap_udc_probe(struct platform_device *pdev) struct clk *dc_clk = NULL; struct clk *hhc_clk = NULL; + if (cpu_is_omap7xx()) + use_dma = 0; + /* NOTE: "knows" the order of the resources! */ if (!request_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1, @@ -3096,16 +3099,6 @@ static struct platform_driver udc_driver = { static int __init udc_init(void) { - /* Disable DMA for omap7xx -- it doesn't work right. */ - if (cpu_is_omap7xx()) - use_dma = 0; - - INFO("%s, version: " DRIVER_VERSION -#ifdef USE_ISO - " (iso)" -#endif - "%s\n", driver_desc, - use_dma ? " (dma)" : ""); return platform_driver_probe(&udc_driver, omap_udc_probe); } module_init(udc_init); -- GitLab From dc1737cdd75b692dbdec0e0e22439a0ce1089488 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:33:30 +0300 Subject: [PATCH 0126/5711] usb: gadget: omap_udc: let it work as a module this also helps removing a few lines of boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 5e7b8912ef31..814aafbed000 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2535,7 +2535,7 @@ static inline void remove_proc_file(void) {} * UDC_SYSCON_1.CFG_LOCK is set can now work. We won't use that * capability yet though. */ -static unsigned __init +static unsigned __devinit omap_ep_setup(char *name, u8 addr, u8 type, unsigned buf, unsigned maxp, int dbuf) { @@ -2653,7 +2653,7 @@ static void omap_udc_release(struct device *dev) udc = NULL; } -static int __init +static int __devinit omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) { unsigned tmp, buf; @@ -2790,7 +2790,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) return 0; } -static int __init omap_udc_probe(struct platform_device *pdev) +static int __devinit omap_udc_probe(struct platform_device *pdev) { int status = -ENODEV; int hmc; @@ -3003,7 +3003,7 @@ cleanup0: return status; } -static int __exit omap_udc_remove(struct platform_device *pdev) +static int __devexit omap_udc_remove(struct platform_device *pdev) { DECLARE_COMPLETION_ONSTACK(done); @@ -3088,7 +3088,8 @@ static int omap_udc_resume(struct platform_device *dev) /*-------------------------------------------------------------------------*/ static struct platform_driver udc_driver = { - .remove = __exit_p(omap_udc_remove), + .probe = omap_udc_probe, + .remove = __devexit_p(omap_udc_remove), .suspend = omap_udc_suspend, .resume = omap_udc_resume, .driver = { @@ -3097,17 +3098,7 @@ static struct platform_driver udc_driver = { }, }; -static int __init udc_init(void) -{ - return platform_driver_probe(&udc_driver, omap_udc_probe); -} -module_init(udc_init); - -static void __exit udc_exit(void) -{ - platform_driver_unregister(&udc_driver); -} -module_exit(udc_exit); +module_platform_driver(udc_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -- GitLab From 70617db7ad7395498e6bc54c634199bf895426c6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:36:42 +0300 Subject: [PATCH 0127/5711] usb: gadget: omap_udc: remove possiblity of NULL pointer de-reference when allocating a request, it's better programming practice to make sure we return NULL if allocation failed. This will ensure that, if struct usb_request isn't the first member on our structure, we don't cheat the gadget driver into thinking allocating worked because pointer isn't 0. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 814aafbed000..f13bcdc75676 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -268,10 +268,12 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) struct omap_req *req; req = kzalloc(sizeof(*req), gfp_flags); - if (req) { - req->req.dma = DMA_ADDR_INVALID; - INIT_LIST_HEAD(&req->queue); - } + if (!req) + return NULL; + + req->req.dma = DMA_ADDR_INVALID; + INIT_LIST_HEAD(&req->queue); + return &req->req; } -- GitLab From 23673d7d26d81bd17cde3ed74c57b3f39585325f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:38:32 +0300 Subject: [PATCH 0128/5711] usb: gadget: omap_udc: kfree(NULL) is safe we don't need to check for _req because kfree(NULL) is safe. Also, if someone actually passes a NULL pointer to be freed by usb_ep_free_request(), he deserves any issue he faces. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index f13bcdc75676..50e8490867ed 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -282,8 +282,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) { struct omap_req *req = container_of(_req, struct omap_req, req); - if (_req) - kfree(req); + kfree(req); } /*-------------------------------------------------------------------------*/ -- GitLab From dd8e93814a357d8f032a93b6d17216436c762e9f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 May 2012 14:42:56 +0300 Subject: [PATCH 0129/5711] usb: gadget: omap_udc: use generic map/unmap routines This patch makes use of the generic map/unmap routines on the omap_udc driver. Removes some useless and duplicated code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 46 ++++++----------------------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 50e8490867ed..b6cc8b19f39f 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -59,8 +59,6 @@ #define DRIVER_DESC "OMAP UDC driver" #define DRIVER_VERSION "4 October 2004" -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - /* * The OMAP UDC needs _very_ early endpoint setup: before enabling the * D+ pullup to allow enumeration. That's too early for the gadget @@ -271,7 +269,6 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) if (!req) return NULL; - req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); return &req->req; @@ -290,6 +287,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) static void done(struct omap_ep *ep, struct omap_req *req, int status) { + struct omap_udc *udc = ep->udc; unsigned stopped = ep->stopped; list_del_init(&req->queue); @@ -299,22 +297,9 @@ done(struct omap_ep *ep, struct omap_req *req, int status) else status = req->req.status; - if (use_dma && ep->has_dma) { - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - (ep->bEndpointAddress & USB_DIR_IN) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else - dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - (ep->bEndpointAddress & USB_DIR_IN) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - } + if (use_dma && ep->has_dma) + usb_gadget_unmap_request(&udc->gadget, &req->req, + (ep->bEndpointAddress & USB_DIR_IN)); #ifndef USB_TRACE if (status && status != -ESHUTDOWN) @@ -915,26 +900,9 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - if (use_dma && ep->has_dma) { - if (req->req.dma == DMA_ADDR_INVALID) { - req->req.dma = dma_map_single( - ep->udc->gadget.dev.parent, - req->req.buf, - req->req.length, - (ep->bEndpointAddress & USB_DIR_IN) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 1; - } else { - dma_sync_single_for_device( - ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - (ep->bEndpointAddress & USB_DIR_IN) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 0; - } - } + if (use_dma && ep->has_dma) + usb_gadget_map_request(&udc->gadget, &req->req, + (ep->bEndpointAddress & USB_DIR_IN)); VDBG("%s queue req %p, len %d buf %p\n", ep->ep.name, _req, _req->length, _req->buf); -- GitLab From bcccc50ce8fcc833cfed4bb71ede211a6ef5b84a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 13 Mar 2012 15:34:17 +0100 Subject: [PATCH 0130/5711] ARM: 7420/1: Improve build environment isolation Increasingly distributions are setting default build environments to have LDFLAGS with hardening options. There seems to be an assumption with those options that LDFLAGS are passed to the compiler frontend rather than used directly with ld (which the kernel build process assumes) To prevent build failures in such environments this patch changes the ARM architecture Makefile to override the LDFLAGS from the environment similar to the behaviour on other common architectures e.g. x86 Signed-off-by: Vincent Sanders Signed-off-by: Russell King --- arch/arm/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 0298b00fe241..f8ebf1e97027 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -10,6 +10,9 @@ # # Copyright (C) 1995-2001 by Russell King +# Ensure linker flags are correct +LDFLAGS := + LDFLAGS_vmlinux :=-p --no-undefined -X ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 -- GitLab From 275c58d77062bbb85dbeb3843ba04f34aa50cf8e Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:19 -0600 Subject: [PATCH 0131/5711] ACPI: Add an interface to evaluate _OST Added acpi_evaluate_hotplug_opt(). All ACPI hotplug handlers must call this function when evaluating _OST for hotplug operations. If the platform does not support _OST, this function returns AE_NOT_FOUND and has no effect on the platform. ACPI_HOTPLUG_OST is defined when all relevant ACPI hotplug operations, such as CPU, memory and container hotplug, are enabled. This assures consistent behavior among the hotplug operations with regarding the _OST support. When ACPI_HOTPLUG_OST is not defined, this function is a no-op. ACPI PCI hotplug is not enhanced to support _OST at this time since it is a legacy method being replaced by PCIe native hotplug. _OST support for ACPI PCI hotplug may be added in future if necessary. Some platforms may require the OS to support _OST in order to support ACPI hotplug operations. For example, if a platform has the management console where user can request a hotplug operation from, this _OST support would be required for the management console to show the result of the hotplug request to user. Added macro definitions of _OST source events and status codes. Also renamed OSC_SB_CPUHP_OST_SUPPORT to OSC_SB_HOTPLUG_OST_SUPPORT since this _OSC bit is not specific to CPU hotplug. This bit is defined in Table 6-147 of ACPI 5.0 as follows. Bits: 3 Field Name: Insertion / Ejection _OST Processing Support Definition: This bit is set if OSPM will evaluate the _OST object defined under a device when processing insertion and ejection source event codes. Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/utils.c | 42 +++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 3 +++ include/linux/acpi.h | 40 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index adbbc1c80a26..3e87c9c538aa 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -412,3 +412,45 @@ out: return status; } EXPORT_SYMBOL(acpi_get_physical_device_location); + +/** + * acpi_evaluate_hotplug_ost: Evaluate _OST for hotplug operations + * @handle: ACPI device handle + * @source_event: source event code + * @status_code: status code + * @status_buf: optional detailed information (NULL if none) + * + * Evaluate _OST for hotplug operations. All ACPI hotplug handlers + * must call this function when evaluating _OST for hotplug operations. + * When the platform does not support _OST, this function has no effect. + */ +acpi_status +acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, + u32 status_code, struct acpi_buffer *status_buf) +{ +#ifdef ACPI_HOTPLUG_OST + union acpi_object params[3] = { + {.type = ACPI_TYPE_INTEGER,}, + {.type = ACPI_TYPE_INTEGER,}, + {.type = ACPI_TYPE_BUFFER,} + }; + struct acpi_object_list arg_list = {3, params}; + acpi_status status; + + params[0].integer.value = source_event; + params[1].integer.value = status_code; + if (status_buf != NULL) { + params[2].buffer.pointer = status_buf->pointer; + params[2].buffer.length = status_buf->length; + } else { + params[2].buffer.pointer = NULL; + params[2].buffer.length = 0; + } + + status = acpi_evaluate_object(handle, "_OST", &arg_list, NULL); + return status; +#else + return AE_OK; +#endif +} +EXPORT_SYMBOL(acpi_evaluate_hotplug_ost); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b0d62820ada1..1139f3a01209 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -50,6 +50,9 @@ acpi_evaluate_reference(acpi_handle handle, acpi_string pathname, struct acpi_object_list *arguments, struct acpi_handle_list *list); +acpi_status +acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, + u32 status_code, struct acpi_buffer *status_buf); struct acpi_pld { unsigned int revision:7; /* 0 */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f421dd84f29d..b2b4d2ad7103 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -277,7 +277,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_PAD_SUPPORT 1 #define OSC_SB_PPC_OST_SUPPORT 2 #define OSC_SB_PR3_SUPPORT 4 -#define OSC_SB_CPUHP_OST_SUPPORT 8 +#define OSC_SB_HOTPLUG_OST_SUPPORT 8 #define OSC_SB_APEI_SUPPORT 16 extern bool osc_sb_apei_support_acked; @@ -309,6 +309,44 @@ extern bool osc_sb_apei_support_acked; extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req); + +/* Enable _OST when all relevant hotplug operations are enabled */ +#if defined(CONFIG_ACPI_HOTPLUG_CPU) && \ + (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \ + defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) && \ + (defined(CONFIG_ACPI_CONTAINER) || \ + defined(CONFIG_ACPI_CONTAINER_MODULE)) +#define ACPI_HOTPLUG_OST +#endif + +/* _OST Source Event Code (OSPM Action) */ +#define ACPI_OST_EC_OSPM_SHUTDOWN 0x100 +#define ACPI_OST_EC_OSPM_EJECT 0x103 +#define ACPI_OST_EC_OSPM_INSERTION 0x200 + +/* _OST General Processing Status Code */ +#define ACPI_OST_SC_SUCCESS 0x0 +#define ACPI_OST_SC_NON_SPECIFIC_FAILURE 0x1 +#define ACPI_OST_SC_UNRECOGNIZED_NOTIFY 0x2 + +/* _OST OS Shutdown Processing (0x100) Status Code */ +#define ACPI_OST_SC_OS_SHUTDOWN_DENIED 0x80 +#define ACPI_OST_SC_OS_SHUTDOWN_IN_PROGRESS 0x81 +#define ACPI_OST_SC_OS_SHUTDOWN_COMPLETED 0x82 +#define ACPI_OST_SC_OS_SHUTDOWN_NOT_SUPPORTED 0x83 + +/* _OST Ejection Request (0x3, 0x103) Status Code */ +#define ACPI_OST_SC_EJECT_NOT_SUPPORTED 0x80 +#define ACPI_OST_SC_DEVICE_IN_USE 0x81 +#define ACPI_OST_SC_DEVICE_BUSY 0x82 +#define ACPI_OST_SC_EJECT_DEPENDENCY_BUSY 0x83 +#define ACPI_OST_SC_EJECT_IN_PROGRESS 0x84 + +/* _OST Insertion Request (0x200) Status Code */ +#define ACPI_OST_SC_INSERT_IN_PROGRESS 0x80 +#define ACPI_OST_SC_DRIVER_LOAD_FAILURE 0x81 +#define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82 + extern void acpi_early_init(void); extern int acpi_nvs_register(__u64 start, __u64 size); -- GitLab From c4753e57b78b213f2384fa0dbafa348b087114fa Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:20 -0600 Subject: [PATCH 0132/5711] ACPI: Add _OST support for sysfs eject Changed acpi_bus_hot_remove_device() to support _OST. This function is also changed to global so that it can be called from hotplug notify handlers to perform hot-remove operation. Changed acpi_eject_store(), which is the sysfs eject handler. It checks eject_pending to see if the request was originated from ACPI eject notification. If not, it calls _OST(0x103,84,) per Figure 6-37 in ACPI 5.0 spec. Added eject_pending bit to acpi_device_flags. This bit is set when the kernel has received an ACPI eject notification, but does not initiate its hot-remove operation by itself. Added struct acpi_eject_event. This structure is used to pass extended information to acpi_bus_hot_remove_device(), which has a single argument to support asynchronous call Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/scan.c | 58 ++++++++++++++++++++++++++++++++++------- include/acpi/acpi_bus.h | 9 ++++++- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 85cbfdccc97c..bea3ab6b524f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -83,19 +83,29 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static void acpi_bus_hot_remove_device(void *context) +/** + * acpi_bus_hot_remove_device: hot-remove a device and its children + * @context: struct acpi_eject_event pointer (freed in this func) + * + * Hot-remove a device and its children. This function frees up the + * memory space passed by arg context, so that the caller may call + * this function asynchronously through acpi_os_hotplug_execute(). + */ +void acpi_bus_hot_remove_device(void *context) { + struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; struct acpi_device *device; - acpi_handle handle = context; + acpi_handle handle = ej_event->handle; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ if (acpi_bus_get_device(handle, &device)) - return; + goto err_out; if (!device) - return; + goto err_out; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); @@ -103,7 +113,7 @@ static void acpi_bus_hot_remove_device(void *context) if (acpi_bus_trim(device, 1)) { printk(KERN_ERR PREFIX "Removing device failed\n"); - return; + goto err_out; } /* power off device */ @@ -129,10 +139,21 @@ static void acpi_bus_hot_remove_device(void *context) * TBD: _EJD support. */ status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) - printk(KERN_WARNING PREFIX - "Eject device failed\n"); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + printk(KERN_WARNING PREFIX + "Eject device failed\n"); + goto err_out; + } + + kfree(context); + return; +err_out: + /* Inform firmware the hot-remove operation has completed w/ error */ + (void) acpi_evaluate_hotplug_ost(handle, + ej_event->event, ost_code, NULL); + kfree(context); return; } @@ -144,6 +165,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, acpi_status status; acpi_object_type type = 0; struct acpi_device *acpi_device = to_acpi_device(d); + struct acpi_eject_event *ej_event; if ((!count) || (buf[0] != '1')) { return -EINVAL; @@ -160,7 +182,25 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle); + ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); + if (!ej_event) { + ret = -ENOMEM; + goto err; + } + + ej_event->handle = acpi_device->handle; + if (acpi_device->flags.eject_pending) { + /* event originated from ACPI eject notification */ + ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + acpi_device->flags.eject_pending = 0; + } else { + /* event originated from user */ + ej_event->event = ACPI_OST_EC_OSPM_EJECT; + (void) acpi_evaluate_hotplug_ost(ej_event->handle, + ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); + } + + acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); err: return ret; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 1139f3a01209..62eb514f8e3a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -182,7 +182,8 @@ struct acpi_device_flags { u32 suprise_removal_ok:1; u32 power_manageable:1; u32 performance_manageable:1; - u32 reserved:24; + u32 eject_pending:1; + u32 reserved:23; }; /* File System */ @@ -334,6 +335,11 @@ struct acpi_bus_event { u32 data; }; +struct acpi_eject_event { + acpi_handle handle; + u32 event; +}; + extern struct kobject *acpi_kobj; extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); void acpi_bus_private_data_handler(acpi_handle, void *); @@ -371,6 +377,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); +void acpi_bus_hot_remove_device(void *context); int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_start(struct acpi_device *device); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); -- GitLab From 51af3b9202ccffe0476899d5c29f0ae7e6bfdcea Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:21 -0600 Subject: [PATCH 0133/5711] ACPI: Add _OST support for ACPI CPU hotplug Changed acpi_processor_hotplug_notify() to call ACPI _OST method when ACPI CPU hotplug operation has completed. Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/processor_driver.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0734086537b8..971c45474703 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -701,9 +701,9 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, { struct acpi_processor *pr; struct acpi_device *device = NULL; + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ int result; - switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: @@ -715,14 +715,18 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!is_processor_present(handle)) break; - if (acpi_bus_get_device(handle, &device)) { - result = acpi_processor_device_add(handle, &device); - if (result) - printk(KERN_ERR PREFIX - "Unable to add the device\n"); + if (!acpi_bus_get_device(handle, &device)) + break; + + result = acpi_processor_device_add(handle, &device); + if (result) { + printk(KERN_ERR PREFIX "Unable to add the device\n"); break; } + + ost_code = ACPI_OST_SC_SUCCESS; break; + case ACPI_NOTIFY_EJECT_REQUEST: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "received ACPI_NOTIFY_EJECT_REQUEST\n")); @@ -736,15 +740,23 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!pr) { printk(KERN_ERR PREFIX "Driver data is NULL, dropping EJECT\n"); - return; + break; } + + /* REVISIT: update when eject is supported */ + ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; break; + default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); - break; + + /* non-hotplug event; possibly handled by other handler */ + return; } + /* Inform firmware that the hotplug operation has completed */ + (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); return; } -- GitLab From b1f00de66f8809b451a33ce47e461ef0e33c09e8 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:22 -0600 Subject: [PATCH 0134/5711] ACPI: Add _OST support for ACPI memory hotplug Changed acpi_memory_device_notify() to call ACPI _OST method when ACPI memory hotplug operation has completed. Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/acpi_memhotplug.c | 43 +++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index d98571385656..24c807f96636 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -341,7 +341,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_memory_device *mem_device; struct acpi_device *device; - + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ switch (event) { case ACPI_NOTIFY_BUS_CHECK: @@ -354,15 +354,20 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) "\nReceived DEVICE CHECK notification for device\n")); if (acpi_memory_get_device(handle, &mem_device)) { printk(KERN_ERR PREFIX "Cannot find driver data\n"); - return; + break; } - if (!acpi_memory_check_device(mem_device)) { - if (acpi_memory_enable_device(mem_device)) - printk(KERN_ERR PREFIX - "Cannot enable memory device\n"); + if (acpi_memory_check_device(mem_device)) + break; + + if (acpi_memory_enable_device(mem_device)) { + printk(KERN_ERR PREFIX "Cannot enable memory device\n"); + break; } + + ost_code = ACPI_OST_SC_SUCCESS; break; + case ACPI_NOTIFY_EJECT_REQUEST: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived EJECT REQUEST notification for device\n")); @@ -383,19 +388,35 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) * TBD: Can also be disabled by Callback registration * with generic sysfs driver */ - if (acpi_memory_disable_device(mem_device)) - printk(KERN_ERR PREFIX - "Disable memory device\n"); + if (acpi_memory_disable_device(mem_device)) { + printk(KERN_ERR PREFIX "Disable memory device\n"); + /* + * If _EJ0 was called but failed, _OST is not + * necessary. + */ + if (mem_device->state == MEMORY_INVALID_STATE) + return; + + break; + } + /* * TBD: Invoke acpi_bus_remove to cleanup data structures */ - break; + + /* _EJ0 succeeded; _OST is not necessary */ + return; + default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); - break; + + /* non-hotplug event; possibly handled by other handler */ + return; } + /* Inform firmware that the hotplug operation has completed */ + (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); return; } -- GitLab From 0c67dc242cf73b9c99a05bfd0122fc9ba1970d37 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:23 -0600 Subject: [PATCH 0135/5711] ACPI: Add _OST support for ACPI container hotplug Changed container_notify_cb() to call ACPI _OST method when ACPI container hotplug operation has completed. Slightly restructured the code with the same logic. The function sets eject_pending bit for an eject request since it does not initiate hot-remove operation. This bit is checked by the sysfs eject handler to determine if the request is originated from an ACPI eject notification. Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/container.c | 43 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 45cd03b4630e..1f9f7d7d7bc5 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -158,9 +158,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) int result; int present; acpi_status status; - - - present = is_device_present(handle); + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ switch (type) { case ACPI_NOTIFY_BUS_CHECK: @@ -169,32 +167,47 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) printk(KERN_WARNING "Container driver received %s event\n", (type == ACPI_NOTIFY_BUS_CHECK) ? "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); + + present = is_device_present(handle); status = acpi_bus_get_device(handle, &device); - if (present) { - if (ACPI_FAILURE(status) || !device) { - result = container_device_add(&device, handle); - if (!result) - kobject_uevent(&device->dev.kobj, - KOBJ_ONLINE); - else - printk(KERN_WARNING - "Failed to add container\n"); - } - } else { + if (!present) { if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ + device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + return; } + break; + } + + if (!ACPI_FAILURE(status) || device) + break; + + result = container_device_add(&device, handle); + if (result) { + printk(KERN_WARNING "Failed to add container\n"); + break; } + + kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); + ost_code = ACPI_OST_SC_SUCCESS; break; + case ACPI_NOTIFY_EJECT_REQUEST: if (!acpi_bus_get_device(handle, &device) && device) { + device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + return; } break; + default: - break; + /* non-hotplug event; possibly handled by other handler */ + return; } + + /* Inform firmware that the hotplug operation has completed */ + (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); return; } -- GitLab From c2f4191a9c4dbbb5c8bc7f2c0eb5023b97dd2a49 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 May 2012 20:25:24 -0600 Subject: [PATCH 0136/5711] ACPI: Set hotplug _OST support bit to _OSC When ACPI_HOTPLUG_OST is defined, set hotplug _OST support bit OSC_SB_HOTPLUG_OST_SUPPORT to indicate that the OS supports hotplug _OST by calling the platform-wide ACPI Operating System Capabilities (_OSC). Signed-off-by: Toshi Kani Signed-off-by: Len Brown --- drivers/acpi/bus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 3188da3df8da..3d4fc7af02f7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -548,6 +548,10 @@ static void acpi_bus_osc_support(void) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; #endif +#ifdef ACPI_HOTPLUG_OST + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT; +#endif + if (!ghes_disable) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) -- GitLab From 695594f1b79d3b88e99e28f06afaab32c4d65853 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jun 2012 08:14:13 +0100 Subject: [PATCH 0137/5711] ASoC: dapm: Use devm_clk_get() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 3bb7a6f058d0..a66379accec9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2902,7 +2902,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, } break; case snd_soc_dapm_clock_supply: - w->clk = clk_get(dapm->dev, w->name); + w->clk = devm_clk_get(dapm->dev, w->name); if (IS_ERR(w->clk)) { ret = PTR_ERR(w->clk); dev_err(dapm->dev, "Failed to request %s: %d\n", -- GitLab From ec02995adad5a7b428f46c1a87fae1bc93d6dfe3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jun 2012 08:16:20 +0100 Subject: [PATCH 0138/5711] ASoC: dapm: Bodge for lack of a widely available clk API Reported-by: Stephen Rothwell Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-dapm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a66379accec9..39e8c2fdf50e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1011,12 +1011,14 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w, if (!w->clk) return -EIO; +#ifdef CONFIG_HAVE_CLK if (SND_SOC_DAPM_EVENT_ON(event)) { return clk_enable(w->clk); } else { clk_disable(w->clk); return 0; } +#endif } EXPORT_SYMBOL_GPL(dapm_clock_event); @@ -2902,6 +2904,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, } break; case snd_soc_dapm_clock_supply: +#ifdef CONFIG_HAVE_CLK w->clk = devm_clk_get(dapm->dev, w->name); if (IS_ERR(w->clk)) { ret = PTR_ERR(w->clk); @@ -2909,6 +2912,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->name, ret); return NULL; } +#else + return NULL; +#endif break; default: break; -- GitLab From 014e5b56702575c5cd8ffc4b1a7924cfdfe0f1ea Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 4 Jun 2012 09:42:53 +0800 Subject: [PATCH 0139/5711] ASoC: fsl_ssi: convert to use devm_clk_get Signed-off-by: Richard Zhao Acked-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 4ed2afd47782..b10a427a8098 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -725,7 +725,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) u32 dma_events[2]; ssi_private->ssi_on_imx = true; - ssi_private->clk = clk_get(&pdev->dev, NULL); + ssi_private->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi_private->clk)) { ret = PTR_ERR(ssi_private->clk); dev_err(&pdev->dev, "could not get clock: %d\n", ret); @@ -842,10 +842,8 @@ error_dev: device_remove_file(&pdev->dev, dev_attr); error_clk: - if (ssi_private->ssi_on_imx) { + if (ssi_private->ssi_on_imx) clk_disable_unprepare(ssi_private->clk); - clk_put(ssi_private->clk); - } error_irq: free_irq(ssi_private->irq, ssi_private); @@ -871,7 +869,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) if (ssi_private->ssi_on_imx) { platform_device_unregister(ssi_private->imx_pcm_pdev); clk_disable_unprepare(ssi_private->clk); - clk_put(ssi_private->clk); } snd_soc_unregister_dai(&pdev->dev); device_remove_file(&pdev->dev, &ssi_private->dev_attr); -- GitLab From 7376bde8945fe20d35aa51f493a7e43b60a39dbe Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 3 Jun 2012 22:50:18 +0530 Subject: [PATCH 0140/5711] ASoC: cs42l52: Remove version.h header file inclusion version.h header file is no longer needed. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index a7109413aef1..ec03abc79a9a 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include -- GitLab From 2bce133c3b00020f4bc146cea94ff5d4de9a8a0f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 3 Jun 2012 22:58:40 +0530 Subject: [PATCH 0141/5711] ASoC: lm49453: Remove version.h header file inclusion version.h header file is no longer required. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 802b9f176b16..c1bc9458906b 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include -- GitLab From 27c347d64f5e4a7e141f6bdb85bbf59e0f1dcde6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Jun 2012 16:28:48 +0530 Subject: [PATCH 0142/5711] Input: MT - fix null pointer warning Fixes the following sparse warning: drivers/input/input-mt.c:138:40: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Henrik Rydberg --- drivers/input/input-mt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index f658086fbbe0..70a16c7da8cc 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -135,7 +135,7 @@ EXPORT_SYMBOL(input_mt_report_finger_count); */ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) { - struct input_mt_slot *oldest = 0; + struct input_mt_slot *oldest = NULL; int oldid = dev->trkid; int count = 0; int i; -- GitLab From 338edabcd879320f0f86cc701161b95277be6b5d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 18 May 2012 14:33:46 +0530 Subject: [PATCH 0143/5711] usb: s3c-hsotg: Use devm_* functions in s3c-hsotg.c file devm_* functions are used to replace kzalloc, request_mem_region, ioremap and request_irq functions in probe call. With the usage of devm_* functions explicit freeing and unmapping is not required. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 51 ++++++++-------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index f4abb0ed9872..d37585105bb4 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -136,7 +136,6 @@ struct s3c_hsotg_ep { * @driver: USB gadget driver * @plat: The platform specific configuration data. * @regs: The memory area mapped for accessing registers. - * @regs_res: The resource that was allocated when claiming register space. * @irq: The IRQ number we are using * @supplies: Definition of USB power supplies * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. @@ -158,7 +157,6 @@ struct s3c_hsotg { struct s3c_hsotg_plat *plat; void __iomem *regs; - struct resource *regs_res; int irq; struct clk *clk; @@ -3477,7 +3475,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) return -EINVAL; } - hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL); + hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL); if (!hsotg) { dev_err(dev, "cannot get memory\n"); return -ENOMEM; @@ -3489,46 +3487,33 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->clk = clk_get(&pdev->dev, "otg"); if (IS_ERR(hsotg->clk)) { dev_err(dev, "cannot get otg clock\n"); - ret = PTR_ERR(hsotg->clk); - goto err_mem; + return PTR_ERR(hsotg->clk); } platform_set_drvdata(pdev, hsotg); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "cannot find register resource 0\n"); - ret = -EINVAL; - goto err_clk; - } - - hsotg->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!hsotg->regs_res) { - dev_err(dev, "cannot reserve registers\n"); - ret = -ENOENT; - goto err_clk; - } - hsotg->regs = ioremap(res->start, resource_size(res)); + hsotg->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hsotg->regs) { dev_err(dev, "cannot map registers\n"); ret = -ENXIO; - goto err_regs_res; + goto err_clk; } ret = platform_get_irq(pdev, 0); if (ret < 0) { dev_err(dev, "cannot find IRQ\n"); - goto err_regs; + goto err_clk; } hsotg->irq = ret; - ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg); + ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, + dev_name(dev), hsotg); if (ret < 0) { dev_err(dev, "cannot claim IRQ\n"); - goto err_regs; + goto err_clk; } dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); @@ -3558,7 +3543,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->supplies); if (ret) { dev_err(dev, "failed to request supplies: %d\n", ret); - goto err_irq; + goto err_clk; } ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), @@ -3642,19 +3627,11 @@ err_ep_mem: err_supplies: s3c_hsotg_phy_disable(hsotg); regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); -err_irq: - free_irq(hsotg->irq, hsotg); -err_regs: - iounmap(hsotg->regs); - -err_regs_res: - release_resource(hsotg->regs_res); - kfree(hsotg->regs_res); + err_clk: clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); -err_mem: - kfree(hsotg); + return ret; } @@ -3675,12 +3652,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) usb_gadget_unregister_driver(hsotg->driver); } - free_irq(hsotg->irq, hsotg); - iounmap(hsotg->regs); - - release_resource(hsotg->regs_res); - kfree(hsotg->regs_res); - s3c_hsotg_phy_disable(hsotg); regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); -- GitLab From fa84c57516f6da93ebc2601348043e9bcb7b4b4d Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sat, 26 May 2012 16:32:39 -0700 Subject: [PATCH 0144/5711] usb: gadget: f_mass_storage: change default value of the removable parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit changes the default value of the removable module parameter from “y” to “n”. This comes with line with file_storag's default and seems to be a better default. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_mass_storage.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index f67b453740bd..72116fa49ffb 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -124,7 +124,7 @@ * backing storage. * ro=b[,b...] Default false, boolean for read-only access. * removable=b[,b...] - * Default true, boolean for removable media. + * Default false, boolean for removable media. * cdrom=b[,b...] Default false, boolean for whether to emulate * a CD-ROM drive. * nofua=b[,b...] Default false, booleans for ignore FUA flag @@ -3167,8 +3167,7 @@ fsg_config_from_params(struct fsg_config *cfg, for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) { lun->ro = !!params->ro[i]; lun->cdrom = !!params->cdrom[i]; - lun->removable = /* Removable by default */ - params->removable_count <= i || params->removable[i]; + lun->removable = !!params->removable[i]; lun->filename = params->file_count > i && params->file[i][0] ? params->file[i] @@ -3203,4 +3202,3 @@ fsg_common_from_params(struct fsg_common *common, fsg_config_from_params(&cfg, params); return fsg_common_init(common, cdev, &cfg); } - -- GitLab From d3c568c302ed0e3b2d51f0335f304ca4d85de54b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 28 May 2012 23:31:39 -0700 Subject: [PATCH 0145/5711] usb: renesas_usbhs: add DMAEngine ID specification note renesas_usbhs DMAEngine uses D0FIFO/D1FIFO, but the data transfer direction should be fixed for keeping consistency. This patch explain about it on renesas_usbhs.h Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- include/linux/usb/renesas_usbhs.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 547e59cc00ea..c5d36c65c33b 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -132,6 +132,14 @@ struct renesas_usbhs_driver_param { * option: * * dma id for dmaengine + * The data transfer direction on D0FIFO/D1FIFO should be + * fixed for keeping consistency. + * So, the platform id settings will be.. + * .d0_tx_id = xx_TX, + * .d1_rx_id = xx_RX, + * or + * .d1_tx_id = xx_TX, + * .d0_rx_id = xx_RX, */ int d0_tx_id; int d0_rx_id; -- GitLab From 560f1187990c6c548756bf2f1183aa19d9c97413 Mon Sep 17 00:00:00 2001 From: Koen Beel Date: Wed, 30 May 2012 20:43:37 +0200 Subject: [PATCH 0146/5711] usb: gadget: ffs: add HID descriptor support. When writing the descriptors to the ep0 file of functionfs, the HID descriptors where not recognized which caused the initialization from user space to fail. Signed-off-by: Koen Beel Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index dcd1c7fbb016..8adc79d1b402 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -1671,6 +1672,12 @@ static int __must_check ffs_do_desc(char *data, unsigned len, } break; + case HID_DT_HID: + pr_vdebug("hid descriptor\n"); + if (length != sizeof(struct hid_descriptor)) + goto inv_length; + break; + case USB_DT_OTG: if (length != sizeof(struct usb_otg_descriptor)) goto inv_length; -- GitLab From 0a00790ff4755f2e3eab907a43725cff59fc074b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 May 2012 13:25:57 -0700 Subject: [PATCH 0147/5711] usb: gadget: pch_udc: Fix likely misuse of | for & Using | with a constant is always true. Likely this should have be &. Signed-off-by: Joe Perches Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 1cfcc9ecbfbc..f4fb71c9ae08 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2208,7 +2208,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep) return; } if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE) - if (td->status | PCH_UDC_DMA_LAST) { + if (td->status & PCH_UDC_DMA_LAST) { count = td->status & PCH_UDC_RXTX_BYTES; break; } -- GitLab From 3de6e63f7845e99981e489ddccf70b3ec02fe00a Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Jun 2012 15:08:54 +0530 Subject: [PATCH 0148/5711] usb: gadget: uvc: Fix string descriptor STALL issue when multiple uvc functions are added to a configuration This patch solved the string descriptor STALL issue when we add multiple UVC functions in a single configuration using a 'webcam.c' like composite driver. Signed-off-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 2022fe492148..054c35a22fbf 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -619,22 +619,28 @@ uvc_bind_config(struct usb_configuration *c, uvc->desc.fs_streaming = fs_streaming; uvc->desc.hs_streaming = hs_streaming; - /* Allocate string descriptor numbers. */ - if ((ret = usb_string_id(c->cdev)) < 0) - goto error; - uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; - uvc_iad.iFunction = ret; - - if ((ret = usb_string_id(c->cdev)) < 0) - goto error; - uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; - uvc_control_intf.iInterface = ret; - - if ((ret = usb_string_id(c->cdev)) < 0) - goto error; - uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; - uvc_streaming_intf_alt0.iInterface = ret; - uvc_streaming_intf_alt1.iInterface = ret; + /* maybe allocate device-global string IDs, and patch descriptors */ + if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { + /* Allocate string descriptor numbers. */ + ret = usb_string_id(c->cdev); + if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; + uvc_iad.iFunction = ret; + + ret = usb_string_id(c->cdev); + if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; + uvc_control_intf.iInterface = ret; + + ret = usb_string_id(c->cdev); + if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; + uvc_streaming_intf_alt0.iInterface = ret; + uvc_streaming_intf_alt1.iInterface = ret; + } /* Register the function. */ uvc->func.name = "uvc"; -- GitLab From 5797663674b0d802f275761e71593b32b0849242 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Jun 2012 15:08:55 +0530 Subject: [PATCH 0149/5711] usb: gadget: uvc: Use macro for interrupt endpoint status size instead of using a MAGIC number This patch adds a MACRO for the UVC video control status (interrupt) endpoint and removes the magic number which was being used earlier. Some UDCs have issues supporting an interrupt IN endpoint having a max packet size less than a particular value (say 32). It is easier in that case to simply change the MACRO value instead of changing the max packet size value at a number of locations. Signed-off-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 054c35a22fbf..dd7d7a98ed43 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -59,6 +59,8 @@ static struct usb_gadget_strings *uvc_function_strings[] = { #define UVC_INTF_VIDEO_CONTROL 0 #define UVC_INTF_VIDEO_STREAMING 1 +#define STATUS_BYTECOUNT 16 /* 16 bytes status */ + static struct usb_interface_assoc_descriptor uvc_iad __initdata = { .bLength = sizeof(uvc_iad), .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, @@ -87,7 +89,7 @@ static struct usb_endpoint_descriptor uvc_control_ep __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(16), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = 8, }; @@ -95,7 +97,7 @@ static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, .bDescriptorType = USB_DT_CS_ENDPOINT, .bDescriptorSubType = UVC_EP_INTERRUPT, - .wMaxTransferSize = cpu_to_le16(16), + .wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT), }; static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { -- GitLab From fbcaba0e3dcec8451cccdc1fa92fcddbde2bc3f2 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Jun 2012 15:08:56 +0530 Subject: [PATCH 0150/5711] usb: gadget: uvc: Add super-speed support to UVC webcam gadget This patch adds super-speed support to UVC webcam gadget. Also in this patch: - We add the configurability to pass bInterval, bMaxBurst, mult factors for video streaming endpoint (ISOC IN) through module parameters. - We use config_ep_by_speed helper routine to configure video streaming endpoint. Signed-off-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 241 ++++++++++++++++++++++++++++++++---- drivers/usb/gadget/f_uvc.h | 8 +- drivers/usb/gadget/uvc.h | 4 +- drivers/usb/gadget/webcam.c | 29 ++++- 4 files changed, 247 insertions(+), 35 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index dd7d7a98ed43..2a8bf0655c60 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -29,6 +29,25 @@ unsigned int uvc_gadget_trace_param; +/*-------------------------------------------------------------------------*/ + +/* module parameters specific to the Video streaming endpoint */ +static unsigned streaming_interval = 1; +module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_interval, "1 - 16"); + +static unsigned streaming_maxpacket = 1024; +module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); + +static unsigned streaming_mult; +module_param(streaming_mult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)"); + +static unsigned streaming_maxburst; +module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); + /* -------------------------------------------------------------------------- * Function descriptors */ @@ -84,7 +103,7 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { .iInterface = 0, }; -static struct usb_endpoint_descriptor uvc_control_ep __initdata = { +static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -124,7 +143,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { .iInterface = 0, }; -static struct usb_endpoint_descriptor uvc_streaming_ep = { +static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -133,15 +152,72 @@ static struct usb_endpoint_descriptor uvc_streaming_ep = { .bInterval = 1, }; +static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 1, +}; + +/* super speed support */ +static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = 8, +}; + +static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { + .bLength = sizeof uvc_ss_control_comp, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 3 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ + .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), +}; + +static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { + .bLength = sizeof uvc_ss_streaming_comp, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 3 values can be tweaked if necessary */ + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), +}; + static const struct usb_descriptor_header * const uvc_fs_streaming[] = { (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, - (struct usb_descriptor_header *) &uvc_streaming_ep, + (struct usb_descriptor_header *) &uvc_fs_streaming_ep, NULL, }; static const struct usb_descriptor_header * const uvc_hs_streaming[] = { (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, - (struct usb_descriptor_header *) &uvc_streaming_ep, + (struct usb_descriptor_header *) &uvc_hs_streaming_ep, + NULL, +}; + +static const struct usb_descriptor_header * const uvc_ss_streaming[] = { + (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, + (struct usb_descriptor_header *) &uvc_ss_streaming_ep, + (struct usb_descriptor_header *) &uvc_ss_streaming_comp, NULL, }; @@ -217,6 +293,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) struct uvc_device *uvc = to_uvc(f); struct v4l2_event v4l2_event; struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; + int ret; INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); @@ -264,7 +341,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) return 0; if (uvc->video.ep) { - uvc->video.ep->desc = &uvc_streaming_ep; + ret = config_ep_by_speed(f->config->cdev->gadget, + &(uvc->func), uvc->video.ep); + if (ret) + return ret; usb_ep_enable(uvc->video.ep); } @@ -370,9 +450,11 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) { struct uvc_input_header_descriptor *uvc_streaming_header; struct uvc_header_descriptor *uvc_control_header; + const struct uvc_descriptor_header * const *uvc_control_desc; const struct uvc_descriptor_header * const *uvc_streaming_cls; const struct usb_descriptor_header * const *uvc_streaming_std; const struct usb_descriptor_header * const *src; + static struct usb_endpoint_descriptor *uvc_control_ep; struct usb_descriptor_header **dst; struct usb_descriptor_header **hdr; unsigned int control_size; @@ -381,10 +463,29 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) unsigned int bytes; void *mem; - uvc_streaming_cls = (speed == USB_SPEED_FULL) - ? uvc->desc.fs_streaming : uvc->desc.hs_streaming; - uvc_streaming_std = (speed == USB_SPEED_FULL) - ? uvc_fs_streaming : uvc_hs_streaming; + switch (speed) { + case USB_SPEED_SUPER: + uvc_control_desc = uvc->desc.ss_control; + uvc_streaming_cls = uvc->desc.ss_streaming; + uvc_streaming_std = uvc_ss_streaming; + uvc_control_ep = &uvc_ss_control_ep; + break; + + case USB_SPEED_HIGH: + uvc_control_desc = uvc->desc.fs_control; + uvc_streaming_cls = uvc->desc.hs_streaming; + uvc_streaming_std = uvc_hs_streaming; + uvc_control_ep = &uvc_fs_control_ep; + break; + + case USB_SPEED_FULL: + default: + uvc_control_desc = uvc->desc.fs_control; + uvc_streaming_cls = uvc->desc.fs_streaming; + uvc_streaming_std = uvc_fs_streaming; + uvc_control_ep = &uvc_fs_control_ep; + break; + } /* Descriptors layout * @@ -402,16 +503,24 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) control_size = 0; streaming_size = 0; bytes = uvc_iad.bLength + uvc_control_intf.bLength - + uvc_control_ep.bLength + uvc_control_cs_ep.bLength + + uvc_control_ep->bLength + uvc_control_cs_ep.bLength + uvc_streaming_intf_alt0.bLength; - n_desc = 5; - for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) { + if (speed == USB_SPEED_SUPER) { + bytes += uvc_ss_control_comp.bLength; + n_desc = 6; + } else { + n_desc = 5; + } + + for (src = (const struct usb_descriptor_header **)uvc_control_desc; + *src; ++src) { control_size += (*src)->bLength; bytes += (*src)->bLength; n_desc++; } - for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) { + for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; + *src; ++src) { streaming_size += (*src)->bLength; bytes += (*src)->bLength; n_desc++; @@ -435,12 +544,15 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) uvc_control_header = mem; UVC_COPY_DESCRIPTORS(mem, dst, - (const struct usb_descriptor_header**)uvc->desc.control); + (const struct usb_descriptor_header **)uvc_control_desc); uvc_control_header->wTotalLength = cpu_to_le16(control_size); uvc_control_header->bInCollection = 1; uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; - UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); + UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep); + if (speed == USB_SPEED_SUPER) + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep); UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0); @@ -448,7 +560,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) UVC_COPY_DESCRIPTORS(mem, dst, (const struct usb_descriptor_header**)uvc_streaming_cls); uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); - uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress; + uvc_streaming_header->bEndpointAddress = + uvc_fs_streaming_ep.bEndpointAddress; UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); @@ -484,6 +597,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) kfree(f->descriptors); kfree(f->hs_descriptors); + kfree(f->ss_descriptors); kfree(uvc); } @@ -498,8 +612,26 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "uvc_function_bind\n"); + /* sanity check the streaming endpoint module parameters */ + if (streaming_interval < 1) + streaming_interval = 1; + if (streaming_interval > 16) + streaming_interval = 16; + if (streaming_mult > 2) + streaming_mult = 2; + if (streaming_maxburst > 15) + streaming_maxburst = 15; + + /* + * fill in the FS video streaming specific descriptors from the + * module parameters + */ + uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? + 1023 : streaming_maxpacket; + uvc_fs_streaming_ep.bInterval = streaming_interval; + /* Allocate endpoints. */ - ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; @@ -507,7 +639,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->control_ep = ep; ep->driver_data = uvc; - ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep); + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; @@ -528,9 +660,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; - /* Copy descriptors. */ + /* sanity check the streaming endpoint module parameters */ + if (streaming_maxpacket > 1024) + streaming_maxpacket = 1024; + + /* Copy descriptors for FS. */ f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); - f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); + + /* support high speed hardware */ + if (gadget_is_dualspeed(cdev->gadget)) { + /* + * Fill in the HS descriptors from the module parameters for the + * Video Streaming endpoint. + * NOTE: We assume that the user knows what they are doing and + * won't give parameters that their UDC doesn't support. + */ + uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; + uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; + uvc_hs_streaming_ep.bInterval = streaming_interval; + uvc_hs_streaming_ep.bEndpointAddress = + uvc_fs_streaming_ep.bEndpointAddress; + + /* Copy descriptors. */ + f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); + } + + /* support super speed hardware */ + if (gadget_is_superspeed(c->cdev->gadget)) { + /* + * Fill in the SS descriptors from the module parameters for the + * Video Streaming endpoint. + * NOTE: We assume that the user knows what they are doing and + * won't give parameters that their UDC doesn't support. + */ + uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; + uvc_ss_streaming_ep.bInterval = streaming_interval; + uvc_ss_streaming_comp.bmAttributes = streaming_mult; + uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; + uvc_ss_streaming_comp.wBytesPerInterval = + streaming_maxpacket * (streaming_mult + 1) * + (streaming_maxburst + 1); + uvc_ss_streaming_ep.bEndpointAddress = + uvc_fs_streaming_ep.bEndpointAddress; + + /* Copy descriptors. */ + f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); + } /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); @@ -585,9 +760,11 @@ error: */ int __init uvc_bind_config(struct usb_configuration *c, - const struct uvc_descriptor_header * const *control, + const struct uvc_descriptor_header * const *fs_control, + const struct uvc_descriptor_header * const *ss_control, const struct uvc_descriptor_header * const *fs_streaming, - const struct uvc_descriptor_header * const *hs_streaming) + const struct uvc_descriptor_header * const *hs_streaming, + const struct uvc_descriptor_header * const *ss_streaming) { struct uvc_device *uvc; int ret = 0; @@ -605,21 +782,31 @@ uvc_bind_config(struct usb_configuration *c, uvc->state = UVC_STATE_DISCONNECTED; /* Validate the descriptors. */ - if (control == NULL || control[0] == NULL || - control[0]->bDescriptorSubType != UVC_VC_HEADER) + if (fs_control == NULL || fs_control[0] == NULL || + fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) + goto error; + + if (ss_control == NULL || ss_control[0] == NULL || + ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) goto error; if (fs_streaming == NULL || fs_streaming[0] == NULL || - fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; if (hs_streaming == NULL || hs_streaming[0] == NULL || - hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + goto error; + + if (ss_streaming == NULL || ss_streaming[0] == NULL || + ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; - uvc->desc.control = control; + uvc->desc.fs_control = fs_control; + uvc->desc.ss_control = ss_control; uvc->desc.fs_streaming = fs_streaming; uvc->desc.hs_streaming = hs_streaming; + uvc->desc.ss_streaming = ss_streaming; /* maybe allocate device-global string IDs, and patch descriptors */ if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h index abf832935134..c3d258d30188 100644 --- a/drivers/usb/gadget/f_uvc.h +++ b/drivers/usb/gadget/f_uvc.h @@ -17,9 +17,11 @@ #include extern int uvc_bind_config(struct usb_configuration *c, - const struct uvc_descriptor_header * const *control, - const struct uvc_descriptor_header * const *fs_streaming, - const struct uvc_descriptor_header * const *hs_streaming); + const struct uvc_descriptor_header * const *fs_control, + const struct uvc_descriptor_header * const *hs_control, + const struct uvc_descriptor_header * const *fs_streaming, + const struct uvc_descriptor_header * const *hs_streaming, + const struct uvc_descriptor_header * const *ss_streaming); #endif /* _F_UVC_H_ */ diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index ca4e03a1c73a..93b0c1191115 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -153,9 +153,11 @@ struct uvc_device /* Descriptors */ struct { - const struct uvc_descriptor_header * const *control; + const struct uvc_descriptor_header * const *fs_control; + const struct uvc_descriptor_header * const *ss_control; const struct uvc_descriptor_header * const *fs_streaming; const struct uvc_descriptor_header * const *hs_streaming; + const struct uvc_descriptor_header * const *ss_streaming; } desc; unsigned int control_intf; diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 668fe128f2ef..120e134e805e 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -272,7 +272,15 @@ static const struct uvc_color_matching_descriptor uvc_color_matching = { .bMatrixCoefficients = 4, }; -static const struct uvc_descriptor_header * const uvc_control_cls[] = { +static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = { + (const struct uvc_descriptor_header *) &uvc_control_header, + (const struct uvc_descriptor_header *) &uvc_camera_terminal, + (const struct uvc_descriptor_header *) &uvc_processing, + (const struct uvc_descriptor_header *) &uvc_output_terminal, + NULL, +}; + +static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { (const struct uvc_descriptor_header *) &uvc_control_header, (const struct uvc_descriptor_header *) &uvc_camera_terminal, (const struct uvc_descriptor_header *) &uvc_processing, @@ -304,6 +312,18 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { NULL, }; +static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { + (const struct uvc_descriptor_header *) &uvc_input_header, + (const struct uvc_descriptor_header *) &uvc_format_yuv, + (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, + (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, + (const struct uvc_descriptor_header *) &uvc_format_mjpg, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, +}; + /* -------------------------------------------------------------------------- * USB configuration */ @@ -311,8 +331,9 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { static int __init webcam_config_bind(struct usb_configuration *c) { - return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, - uvc_hs_streaming_cls); + return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls, + uvc_fs_streaming_cls, uvc_hs_streaming_cls, + uvc_ss_streaming_cls); } static struct usb_configuration webcam_config_driver = { @@ -373,7 +394,7 @@ static struct usb_composite_driver webcam_driver = { .name = "g_webcam", .dev = &webcam_device_descriptor, .strings = webcam_device_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .unbind = webcam_unbind, }; -- GitLab From 206dd69a62a06197b308fa0decfd0b649fcc2811 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Mon, 21 May 2012 12:42:54 +0530 Subject: [PATCH 0151/5711] USB: DWC3: Generate interrupt on each TRB as default option Currently in case of isoc, interrupt is programmed after each TRB_NUM/4 ie 8th TRB. A TRB is programmed against each submitted request from gadget. If we do not want to limit the minimum number of necessary request to be submitted from gadget then we must receive interrupt on each TRB submission. There can be such situation with a gadget working with ping-pong buffer. If a gadget does not want to receive interrupt after each request completion then it may set no_interrupt flag. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a9fc7c4a5a20..be87e82b36c7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -766,8 +766,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, case USB_ENDPOINT_XFER_ISOC: trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; - /* IOC every DWC3_TRB_NUM / 4 so we can refill */ - if (!(cur_slot % (DWC3_TRB_NUM / 4))) + if (!req->request.no_interrupt) trb->ctrl |= DWC3_TRB_CTRL_IOC; break; -- GitLab From 389f2828bb2a5f2acde9bdeffde02743684c1d86 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Mon, 21 May 2012 12:46:26 +0530 Subject: [PATCH 0152/5711] USB: DWC3: Correct DWC3_TRB_SIZE_TRBSTS definition Correct define for DWC3_TRB_SIZE_TRBSTS. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4d5c63dae14d..ce43b1f5f341 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -495,7 +495,7 @@ enum dwc3_device_state { #define DWC3_TRB_SIZE_MASK (0x00ffffff) #define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) #define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24) -#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28) >> 28)) +#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28)) >> 28) #define DWC3_TRBSTS_OK 0 #define DWC3_TRBSTS_MISSED_ISOC 1 -- GitLab From d05b81824e672a48b3566634622849866de2b787 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Mon, 21 May 2012 14:51:30 +0530 Subject: [PATCH 0153/5711] USB: DWC3: Correct DWC3_DSTS_SOFFN_MASK definition SOF Number is bit16:3 of DSTS. Correct the mask accordingly. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index ce43b1f5f341..e402022b9e15 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -291,7 +291,7 @@ #define DWC3_DSTS_RXFIFOEMPTY (1 << 17) -#define DWC3_DSTS_SOFFN_MASK (0x3ff << 3) +#define DWC3_DSTS_SOFFN_MASK (0x3fff << 3) #define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) #define DWC3_DSTS_CONNECTSPD (7 << 0) -- GitLab From d6d6ec7b8854ab62f7f3907656d5d29eb47532e7 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 25 May 2012 18:54:56 +0530 Subject: [PATCH 0154/5711] usb: dwc3: Fix missed isoc IN transaction If an IN transfer is missed on isoc endpoint, then driver must insure that next ep_queue is properly handled. This patch fixes this issue by starting a new transfer for next queued request. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 3 ++ drivers/usb/dwc3/gadget.c | 73 ++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e402022b9e15..fcb8be2ec1c9 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -405,6 +405,7 @@ struct dwc3_event_buffer { * @number: endpoint number (1 - 15) * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK * @res_trans_idx: Resource transfer index + * @current_uf: Current uf received through last event parameter * @interval: the intervall on which the ISOC transfer is started * @name: a human readable name e.g. ep1out-bulk * @direction: true for TX, false for RX @@ -428,6 +429,7 @@ struct dwc3_ep { #define DWC3_EP_WEDGE (1 << 2) #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST (1 << 5) +#define DWC3_EP_MISSED_ISOC (1 << 6) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN (1 << 31) @@ -437,6 +439,7 @@ struct dwc3_ep { u8 number; u8 type; u8 res_trans_idx; + u16 current_uf; u32 interval; char name[20]; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index be87e82b36c7..0cab69e51380 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -990,6 +990,34 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, return 0; } +static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, + struct dwc3_ep *dep, u32 cur_uf) +{ + u32 uf; + + if (list_empty(&dep->request_list)) { + dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", + dep->name); + return; + } + + /* 4 micro frames in the future */ + uf = cur_uf + dep->interval * 4; + + __dwc3_gadget_kick_transfer(dep, uf, 1); +} + +static void dwc3_gadget_start_isoc(struct dwc3 *dwc, + struct dwc3_ep *dep, const struct dwc3_event_depevt *event) +{ + u32 cur_uf, mask; + + mask = ~(dep->interval - 1); + cur_uf = event->parameters & mask; + + __dwc3_gadget_start_isoc(dwc, dep, cur_uf); +} + static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; @@ -1019,8 +1047,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) list_add_tail(&req->list, &dep->request_list); - if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY)) - dep->flags |= DWC3_EP_PENDING_REQUEST; + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + if (dep->flags & DWC3_EP_BUSY) { + dep->flags |= DWC3_EP_PENDING_REQUEST; + } else if (dep->flags & DWC3_EP_MISSED_ISOC) { + __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf); + dep->flags &= ~DWC3_EP_MISSED_ISOC; + } + } /* * There are two special cases: @@ -1591,6 +1625,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_trb *trb; unsigned int count; unsigned int s_pkt = 0; + unsigned int trb_status; do { req = next_request(&dep->req_queued); @@ -1616,9 +1651,18 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, if (dep->direction) { if (count) { - dev_err(dwc->dev, "incomplete IN transfer %s\n", - dep->name); - status = -ECONNRESET; + trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size); + if (trb_status == DWC3_TRBSTS_MISSED_ISOC) { + dev_dbg(dwc->dev, "incomplete IN transfer %s\n", + dep->name); + dep->current_uf = event->parameters & + ~(dep->interval - 1); + dep->flags |= DWC3_EP_MISSED_ISOC; + } else { + dev_err(dwc->dev, "incomplete IN transfer %s\n", + dep->name); + status = -ECONNRESET; + } } } else { if (count && (event->status & DEPEVT_STATUS_SHORT)) @@ -1690,25 +1734,6 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, } } -static void dwc3_gadget_start_isoc(struct dwc3 *dwc, - struct dwc3_ep *dep, const struct dwc3_event_depevt *event) -{ - u32 uf, mask; - - if (list_empty(&dep->request_list)) { - dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", - dep->name); - return; - } - - mask = ~(dep->interval - 1); - uf = event->parameters & mask; - /* 4 micro frames in the future */ - uf += dep->interval * 4; - - __dwc3_gadget_kick_transfer(dep, uf, 1); -} - static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { -- GitLab From 70b674bfeb735557fc03cdc125ffe6d34218fcfd Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Sun, 3 Jun 2012 19:43:19 +0530 Subject: [PATCH 0155/5711] usb: dwc3: Fix break from cleanup request loop If event status says that its last completed TRB but TRB is still owned by HW then break from the loop, because we are not going to get correct TRB status from trb control/size register. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0cab69e51380..854f3a3c8832 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1681,7 +1681,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, if (s_pkt) break; if ((event->status & DEPEVT_STATUS_LST) && - (trb->ctrl & DWC3_TRB_CTRL_LST)) + (trb->ctrl & (DWC3_TRB_CTRL_LST | + DWC3_TRB_CTRL_HWO))) break; if ((event->status & DEPEVT_STATUS_IOC) && (trb->ctrl & DWC3_TRB_CTRL_IOC)) -- GitLab From abf710e655fe843afe0ab6a56e344567d933b018 Mon Sep 17 00:00:00 2001 From: Vikram Pandita Date: Fri, 18 May 2012 13:48:04 -0700 Subject: [PATCH 0156/5711] usb: musb: handle nuked ep dma interrupt User can trigger disabling of gadget at run time while the transfers are going on. Eg: 1: rmmod of musb driver while transfers are going on Eg: 2: On android doing: echo 0 > /sys/class/android_usb/android0/enable While a big file transfer is going on via PTP/MTP. In such a case, musb_gadget_disable() calls nuke() but the dma interrupt may still happen for an endpoint since hw would raise the interrupt in anycase. This can result in a NULL pointer access crash: [ 314.030426] PC is at txstate+0x74/0x20c [ 314.034759] LR is at musb_g_tx+0x140/0x204 [ 314.039489] pc : [] lr : [] psr: 20000193 [ 314.039520] sp : c783bc68 ip : 00000002 fp : c783bc9c [ 314.052429] r10: 00000018 r9 : 00000000 r8 : 00000200 [ 314.058258] r7 : 00000000 r6 : fc0ab130 r5 : c781a410 r4 : c6caf640 [ 314.065643] r3 : 00000000 r2 : 00000000 r1 : 00000000 r0 : c781a000 [ 315.083251] Backtrace: [ 315.086242] [] (txstate+0x0/0x20c) from [] (musb_g_tx+0x140/0x204) [ 315.095123] [] (musb_g_tx+0x0/0x204) from [] (musb_dma_completion+0x40/0x54) [ 315.104980] [] (musb_dma_completion+0x0/0x54) from [] (dma_controller_irq+0x118/0x184) [ 315.115661] [] (dma_controller_irq+0x0/0x184) from [] (handle_irq_event_percpu+0x54/0x188) So put protection in code to handle possiblity of getting an interrupt for an endpoint that might have been already nuked. Reported-by: Todd Poynor Signed-off-by: Vikram Pandita Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index f42c29b11f71..695c892e70e7 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -328,6 +328,13 @@ static void txstate(struct musb *musb, struct musb_request *req) musb_ep = req->ep; + /* Check if EP is disabled */ + if (!musb_ep->desc) { + dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", + musb_ep->end_point.name); + return; + } + /* we shouldn't get here while DMA is active ... but we do ... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { dev_dbg(musb->controller, "dma pending...\n"); @@ -650,6 +657,13 @@ static void rxstate(struct musb *musb, struct musb_request *req) len = musb_ep->packet_sz; + /* Check if EP is disabled */ + if (!musb_ep->desc) { + dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", + musb_ep->end_point.name); + return; + } + /* We shouldn't get here while DMA is active, but we do... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { dev_dbg(musb->controller, "DMA pending...\n"); -- GitLab From 2ed9127cff9a255b7671b8d3d938109f68a87961 Mon Sep 17 00:00:00 2001 From: Mantesh Sarasetti Date: Fri, 1 Jun 2012 14:54:30 +0300 Subject: [PATCH 0157/5711] usb: musb: host: Disable MUSB DMA mode incase of DMA channel request failure Currently in case of MUSB DMA channel request failure we are not clearing MUSB_RXCSR_DMAENAB, MUSB_RXCSR_H_AUTOREQ and MUSB_RXCSR_AUTOCLEAR bits of MUSB RXCSR of MUSB DMA. Which is causing failure in receipt of data packets in next transfer. Fix is to disable the MUSB DMA mode and related bits incase of DMA channel request fails Signed-off-by: Mantesh Sarashetti Signed-off-by: Ruslan Bilovol Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index ef8d744800ac..33fc45151b8f 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1736,7 +1736,11 @@ void musb_host_rx(struct musb *musb, u8 epnum) c->channel_release(dma); hw_ep->rx_channel = NULL; dma = NULL; - /* REVISIT reset CSR */ + val = musb_readw(epio, MUSB_RXCSR); + val &= ~(MUSB_RXCSR_DMAENAB + | MUSB_RXCSR_H_AUTOREQ + | MUSB_RXCSR_AUTOCLEAR); + musb_writew(epio, MUSB_RXCSR, val); } } #endif /* Mentor DMA */ -- GitLab From 79d6680f017a8084ae746f5d845a4fdc4f3a5e43 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 20 Apr 2012 15:29:20 -0600 Subject: [PATCH 0158/5711] usb: otg: isp1301_omap: resolve unused variable warning from gcc Resolve this build warning: drivers/usb/otg/isp1301_omap.c: In function 'isp1301_set_peripheral': drivers/usb/otg/isp1301_omap.c:1340:6: warning: unused variable 'l' This shows up when building with the 'omap1_defconfig' and '5912osk_testconfig' configs from git://git.pwsan.com/omap_kconfigs. Compile-tested only. Cc: Heikki Krogerus Cc: Felipe Balbi Signed-off-by: Paul Walmsley Signed-off-by: Felipe Balbi --- drivers/usb/otg/isp1301_omap.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 70cf5d7bca48..33cd709b084e 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -1336,9 +1336,6 @@ static int isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); -#ifndef CONFIG_USB_OTG - u32 l; -#endif if (!otg || isp != the_transceiver) return -ENODEV; @@ -1365,10 +1362,14 @@ isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) otg->gadget = gadget; // FIXME update its refcount - l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; - l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); - l |= OTG_ID; - omap_writel(l, OTG_CTRL); + { + u32 l; + + l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; + l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); + l |= OTG_ID; + omap_writel(l, OTG_CTRL); + } power_up(isp); isp->phy.state = OTG_STATE_B_IDLE; -- GitLab From 94bf2cedbc22f8952ebbbaa085620d7d0328fced Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Jun 2012 18:39:19 +0200 Subject: [PATCH 0159/5711] drm/i915: compute the target_clock for edp directly ... instead of abusing mode->clock by storing it in there - we shouldn't touch that one at all. This patch is the first prep step to constify the mode argument of the intel_dp_mode_fixup function. The next patch will stop us from modifying mode->clock. Reviewed-by: Chris Wilson Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_dp.c | 12 ++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9f5148acf73c..0161d947ab81 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4416,16 +4416,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* CPU eDP doesn't require FDI link, so just set DP M/N according to current link config */ if (is_cpu_edp) { - target_clock = mode->clock; intel_edp_link_config(edp_encoder, &lane, &link_bw); } else { - /* [e]DP over FDI requires target mode clock - instead of link clock */ - if (is_dp) - target_clock = mode->clock; - else - target_clock = adjusted_mode->clock; - /* FDI is a binary signal running at ~2.7GHz, encoding * each output octet as 10 bits. The actual frequency * is stored as a divider into a 100MHz clock, and the @@ -4436,6 +4428,14 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; } + /* [e]DP over FDI requires target mode clock instead of link clock. */ + if (edp_encoder) + target_clock = intel_edp_target_clock(edp_encoder, mode); + else if (is_dp) + target_clock = mode->clock; + else + target_clock = adjusted_mode->clock; + /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ade98e0bca84..ae7c62340129 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -152,6 +152,18 @@ intel_edp_link_config(struct intel_encoder *intel_encoder, *link_bw = 270000; } +int +intel_edp_target_clock(struct intel_encoder *intel_encoder, + struct drm_display_mode *mode) +{ + struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); + + if (intel_dp->panel_fixed_mode) + return intel_dp->panel_fixed_mode->clock; + else + return mode->clock; +} + static int intel_dp_max_lane_count(struct intel_dp *intel_dp) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 39d7b07c1e8b..6a2ae30ee519 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -359,6 +359,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern bool intel_dpd_is_edp(struct drm_device *dev); extern void intel_edp_link_config(struct intel_encoder *, int *, int *); +extern int intel_edp_target_clock(struct intel_encoder *, + struct drm_display_mode *mode); extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, -- GitLab From 71244653a8fb0f46bc12ae421f1d5f72af6a75da Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Jun 2012 18:39:20 +0200 Subject: [PATCH 0160/5711] drm/i915: adjusted_mode->clock in the dp mode_fixup ... instead of changing mode->clock, which we should leave as-is. After the previous patch we only touch that if it's a panel, and then adjusted mode->clock equals adjusted_mode->clock. Outside of intel_dp.c we only use ajusted_mode->clock in the mode_set functions. Within intel_dp.c we only use it to calculate the dp dithering and link bw parameters, so that's the only thing we need to fix up. As a temporary ugliness (until the cleanup in the next patch) we pass the adjusted_mode into dp_dither for both parameters (because that one still looks at mode->clock). Note that we do overwrite adjusted_mode->clock with the selected dp link clock, but that only happens after we've calculated everything we need based on the dotclock of the adjusted output configuration. Outside of intel_dp.c only intel_display.c uses adjusted_mode->clock, and that stays the same after this patch (still equals the selected dp link clock). intel_display.c also needs the actual dotclock (as target_clock), but that has been fixed up in the previous patch. v2: Adjust the debug message to also use adjusted_mode->clock. Reviewed-by: Chris Wilson Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ae7c62340129..90cb39e89e61 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -710,11 +710,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, mode, adjusted_mode); - /* - * the mode->clock is used to calculate the Data&Link M/N - * of the pipe. For the eDP the fixed clock should be used. - */ - mode->clock = intel_dp->panel_fixed_mode->clock; } if (mode->flags & DRM_MODE_FLAG_DBLCLK) @@ -722,13 +717,13 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", - max_lane_count, bws[max_clock], mode->clock); + max_lane_count, bws[max_clock], adjusted_mode->clock); - if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) + if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, adjusted_mode)) return false; bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; - mode_rate = intel_dp_link_required(mode->clock, bpp); + mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (clock = 0; clock <= max_clock; clock++) { -- GitLab From cb1793ce921c7e073f9055847a5bc868ab84244c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Jun 2012 18:39:21 +0200 Subject: [PATCH 0161/5711] drm/i915: don't chnage the original mode in dp_mode_fixup We should only frob adjusted_mode. This is in preparation of a massive patch by Laurent Pinchart to make the mode argument const. After the previous two prep patches the only thing left is to clean up things a bit. I've opted to pass in an adjust_mode param to dp_adjust_dithering because that way we can be sure to avoid duplicating this logic between mode_valid and mode_fixup - which was the cause behind a dp link bw calculation bug in the past. Also mark the mode argument of pch_panel_fitting const. v2: Split up the mode->clock => adjusted_mode->clock change, as suggested by Chris Wilson. Reported-by: Laurent Pinchart Reviewed-by: Chris Wilson Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 12 ++++++------ drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 90cb39e89e61..6538c46fe959 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -234,7 +234,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) static bool intel_dp_adjust_dithering(struct intel_dp *intel_dp, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + bool adjust_mode) { int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_lanes = intel_dp_max_lane_count(intel_dp); @@ -248,8 +248,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp, if (mode_rate > max_rate) return false; - if (adjusted_mode) - adjusted_mode->private_flags + if (adjust_mode) + mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; return true; @@ -272,7 +272,7 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) + if (!intel_dp_adjust_dithering(intel_dp, mode, false)) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -712,14 +712,14 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, mode, adjusted_mode); } - if (mode->flags & DRM_MODE_FLAG_DBLCLK) + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) return false; DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", max_lane_count, bws[max_clock], adjusted_mode->clock); - if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, adjusted_mode)) + if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true)) return false; bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6a2ae30ee519..c35edd7ca84d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -373,7 +373,7 @@ extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode); extern void intel_pch_panel_fitting(struct drm_device *dev, int fitting_mode, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern u32 intel_panel_get_max_backlight(struct drm_device *dev); extern u32 intel_panel_get_backlight(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 2a1625d84a69..7180cc828f94 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -56,7 +56,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, void intel_pch_panel_fitting(struct drm_device *dev, int fitting_mode, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = dev->dev_private; -- GitLab From 1523c310b3ed964b71a8db16f70c3bc21cc0642e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 25 May 2012 12:34:54 -0700 Subject: [PATCH 0162/5711] drm/i915: add min freq control to debugfs This makes for easier benchmarking and testing. One can set a fixed frequency by setting min and max to the same value. v2: fix whitespace & comment (Eugeni) Signed-off-by: Jesse Barnes Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5363e9c66c27..4fa00fcfbc96 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1764,6 +1764,64 @@ static const struct file_operations i915_max_freq_fops = { .llseek = default_llseek, }; +static ssize_t +i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[80]; + int len; + + len = snprintf(buf, sizeof(buf), + "min freq: %d\n", dev_priv->min_delay * 50); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(ubuf, max, ppos, buf, len); +} + +static ssize_t +i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + struct drm_i915_private *dev_priv = dev->dev_private; + char buf[20]; + int val = 1; + + if (cnt > 0) { + if (cnt > sizeof(buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, cnt)) + return -EFAULT; + buf[cnt] = 0; + + val = simple_strtoul(buf, NULL, 0); + } + + DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val); + + /* + * Turbo will still be enabled, but won't go below the set value. + */ + dev_priv->min_delay = val / 50; + + gen6_set_rps(dev, val / 50); + + return cnt; +} + +static const struct file_operations i915_min_freq_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = i915_min_freq_read, + .write = i915_min_freq_write, + .llseek = default_llseek, +}; + static ssize_t i915_cache_sharing_read(struct file *filp, char __user *ubuf, @@ -1996,6 +2054,12 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; + ret = i915_debugfs_create(minor->debugfs_root, minor, + "i915_min_freq", + &i915_min_freq_fops); + if (ret) + return ret; + ret = i915_debugfs_create(minor->debugfs_root, minor, "i915_cache_sharing", &i915_cache_sharing_fops); @@ -2028,6 +2092,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, 1, minor); + drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops, + 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, -- GitLab From 7baab9acfb25934a32541d617cbc676abd1fbf5b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 4 Jun 2012 21:28:07 +0200 Subject: [PATCH 0163/5711] firewire: ohci: sanity-check MMIO resource pci_request_region() does not fail on resources that have not been allocated by the BIOS or by the kernel, so to avoid accessing registers that are not there, we have to check for this explicitly. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 1c365b827815..922cd26b25e3 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -3545,6 +3545,13 @@ static int __devinit pci_probe(struct pci_dev *dev, INIT_WORK(&ohci->bus_reset_work, bus_reset_work); + if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) || + pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) { + dev_err(&dev->dev, "invalid MMIO resource\n"); + err = -ENXIO; + goto fail_disable; + } + err = pci_request_region(dev, 0, ohci_driver_name); if (err) { dev_err(&dev->dev, "MMIO resource unavailable\n"); -- GitLab From 55c03cff7fd73349473cc0a964df9d55b312dbbc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 17:12:12 -0700 Subject: [PATCH 0164/5711] staging: comedi: remove private header comedi_pci.h Remove the private header, comedi_pci.h, by moving the two helper functions into divers.c and providing the prototypes in comedidev.h. This allows the comedi_pci_enable/disable helper functions to be shared instead of having an inline version in every comedi pci driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 5 +- drivers/staging/comedi/drivers.c | 34 +++++++++++ .../drivers/addi-data/addi_amcc_s5933.h | 2 - drivers/staging/comedi/drivers/adl_pci6208.c | 1 - drivers/staging/comedi/drivers/adl_pci7230.c | 1 - drivers/staging/comedi/drivers/adl_pci7296.c | 1 - drivers/staging/comedi/drivers/adl_pci7432.c | 1 - drivers/staging/comedi/drivers/adl_pci8164.c | 1 - drivers/staging/comedi/drivers/adl_pci9111.c | 1 - drivers/staging/comedi/drivers/adl_pci9118.c | 1 - drivers/staging/comedi/drivers/adv_pci1710.c | 2 - drivers/staging/comedi/drivers/adv_pci1723.c | 2 - drivers/staging/comedi/drivers/adv_pci_dio.c | 1 - drivers/staging/comedi/drivers/amplc_dio200.c | 2 - drivers/staging/comedi/drivers/amplc_pc236.c | 2 - drivers/staging/comedi/drivers/amplc_pc263.c | 2 - drivers/staging/comedi/drivers/amplc_pci224.c | 2 - drivers/staging/comedi/drivers/amplc_pci230.c | 1 - drivers/staging/comedi/drivers/cb_pcidas.c | 1 - drivers/staging/comedi/drivers/cb_pcidas64.c | 1 - drivers/staging/comedi/drivers/cb_pcidda.c | 2 - drivers/staging/comedi/drivers/cb_pcidio.c | 1 - drivers/staging/comedi/drivers/cb_pcimdas.c | 1 - drivers/staging/comedi/drivers/cb_pcimdda.c | 2 - drivers/staging/comedi/drivers/comedi_pci.h | 60 ------------------- .../staging/comedi/drivers/contec_pci_dio.c | 2 - drivers/staging/comedi/drivers/daqboard2000.c | 1 - drivers/staging/comedi/drivers/das08.c | 1 - drivers/staging/comedi/drivers/dt3000.c | 2 - drivers/staging/comedi/drivers/dyna_pci10xx.c | 1 - drivers/staging/comedi/drivers/gsc_hpdi.c | 1 - drivers/staging/comedi/drivers/icp_multi.h | 1 - drivers/staging/comedi/drivers/jr3_pci.c | 1 - drivers/staging/comedi/drivers/ke_counter.c | 2 - drivers/staging/comedi/drivers/me4000.c | 1 - drivers/staging/comedi/drivers/me_daq.c | 2 - drivers/staging/comedi/drivers/mite.c | 1 - drivers/staging/comedi/drivers/rtd520.c | 1 - drivers/staging/comedi/drivers/s626.c | 2 - 39 files changed, 37 insertions(+), 112 deletions(-) delete mode 100644 drivers/staging/comedi/drivers/comedi_pci.h diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 134be93eaa6d..9cd2b5117106 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -40,6 +40,7 @@ #include #include #include +#include #include "comedi.h" @@ -180,7 +181,6 @@ struct comedi_async { unsigned int x); }; -struct pci_dev; struct usb_interface; struct comedi_driver { @@ -310,7 +310,8 @@ int comedi_driver_unregister(struct comedi_driver *); module_driver(__comedi_driver, comedi_driver_register, \ comedi_driver_unregister) -struct pci_driver; +int comedi_pci_enable(struct pci_dev *, const char *); +void comedi_pci_disable(struct pci_dev *); int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *); void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 1c3d6386ea36..7289dcb5c32c 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -908,6 +908,40 @@ static void comedi_auto_unconfig(struct device *hardware_device) comedi_free_board_minor(minor); } +/** + * comedi_pci_enable() - Enable the PCI device and request the regions. + * @pdev: pci_dev struct + * @res_name: name for the requested reqource + */ +int comedi_pci_enable(struct pci_dev *pdev, const char *res_name) +{ + int rc; + + rc = pci_enable_device(pdev); + if (rc < 0) + return rc; + + rc = pci_request_regions(pdev, res_name); + if (rc < 0) + pci_disable_device(pdev); + + return rc; +} +EXPORT_SYMBOL_GPL(comedi_pci_enable); + +/** + * comedi_pci_disable() - Release the regions and disable the PCI device. + * @pdev: pci_dev struct + * + * This must be matched with a previous successful call to comedi_pci_enable(). + */ +void comedi_pci_disable(struct pci_dev *pdev) +{ + pci_release_regions(pdev); + pci_disable_device(pdev); +} +EXPORT_SYMBOL_GPL(comedi_pci_disable); + static int comedi_old_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver) { diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h index 35a3ea19359f..d70ac8bb6228 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h @@ -22,8 +22,6 @@ #include "../../comedidev.h" -#include "../comedi_pci.h" - #ifdef PCI_SUPPORT_VER1 #error No support for 2.1.55 and older #endif diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index de8c68af3210..2f48dc72b20e 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -52,7 +52,6 @@ References: * options that are used with comedi_config. */ #include "../comedidev.h" -#include "comedi_pci.h" /* Board descriptions */ struct pci6208_board { diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index e8053bc825f4..e7eb2290106a 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -36,7 +36,6 @@ Configuration Options: #include "../comedidev.h" #include -#include "comedi_pci.h" #define PCI7230_DI 0x00 #define PCI7230_DO 0x00 diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index b4dae3b7598b..bf2f7fb86d77 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -37,7 +37,6 @@ Configuration Options: #include "../comedidev.h" #include -#include "comedi_pci.h" #include "8255.h" /* #include "8253.h" */ diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index 9cbfb61a4478..2fc1dbbd81e4 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -36,7 +36,6 @@ Configuration Options: #include "../comedidev.h" #include -#include "comedi_pci.h" #define PCI7432_DI 0x00 #define PCI7432_DO 0x00 diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 409ef13ad090..fbc859e6c201 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -38,7 +38,6 @@ Configuration Options: #include #include #include "comedi_fc.h" -#include "comedi_pci.h" #include "8253.h" #define PCI8164_AXIS_X 0x00 diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index ccfb1a52154e..308cca76cb82 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -81,7 +81,6 @@ TODO: #include #include "8253.h" -#include "comedi_pci.h" #include "comedi_fc.h" #define PCI9111_DRIVER_NAME "adl_pci9111" diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 78645863297b..aa4244e5f918 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -71,7 +71,6 @@ Configuration options: #include "amcc_s5933.h" #include "8253.h" -#include "comedi_pci.h" #include "comedi_fc.h" #define PCI_VENDOR_ID_AMCC 0x10e8 diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index de8c98cfe367..db9f0a56f79f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -45,8 +45,6 @@ Configuration options: #include "../comedidev.h" -#include "comedi_pci.h" - #include "8253.h" #include "amcc_s5933.h" diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 336addcbce3a..b8768b54e943 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -50,8 +50,6 @@ TODO: #include "../comedidev.h" -#include "comedi_pci.h" - #define PCI_VENDOR_ID_ADVANTECH 0x13fe /* Advantech PCI vendor ID */ /* hardware types of the cards */ diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 43a32dc12cde..df8236c952e7 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -33,7 +33,6 @@ Configuration options: #include -#include "comedi_pci.h" #include "8255.h" #include "8253.h" diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index c9c5d97b3ca2..f6f6144344b4 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -210,8 +210,6 @@ order they appear in the channel list. #include "../comedidev.h" -#include "comedi_pci.h" - #include "8255.h" #include "8253.h" diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 57ba3228b1a9..6cb06ec1b30d 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -56,8 +56,6 @@ unused. #include "../comedidev.h" -#include "comedi_pci.h" - #include "8255.h" #include "plx9052.h" diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 974d7450051e..086579f756ff 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -46,8 +46,6 @@ The state of the outputs can be read. #include "../comedidev.h" -#include "comedi_pci.h" - #define PC263_DRIVER_NAME "amplc_pc263" #ifdef CONFIG_COMEDI_AMPLC_PC263_ISA_MODULE diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index fbf19cae8747..0d1f9cc50ef3 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -108,8 +108,6 @@ Caveats: #include "../comedidev.h" -#include "comedi_pci.h" - #include "comedi_fc.h" #include "8253.h" diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index d4c80b1281f2..b05a684b80ba 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -193,7 +193,6 @@ for (or detection of) various hardware problems added by Ian Abbott. #include #include -#include "comedi_pci.h" #include "8253.h" #include "8255.h" diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index ee9e084bb96c..7f88d08ee579 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -77,7 +77,6 @@ analog triggering on 1602 series #include "8253.h" #include "8255.h" #include "amcc_s5933.h" -#include "comedi_pci.h" #include "comedi_fc.h" #undef CB_PCIDAS_DEBUG /* disable debugging code */ diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 9d0b8754ff5b..1e30f227e98e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -87,7 +87,6 @@ TODO: #include #include -#include "comedi_pci.h" #include "8253.h" #include "8255.h" #include "plx9080.h" diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 25ebca11eadc..dc4cf0b030ef 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -48,10 +48,8 @@ Please report success/failure with other different cards to #include "../comedidev.h" -#include "comedi_pci.h" #include "8255.h" - /* PCI vendor number of ComputerBoards */ #define PCI_VENDOR_ID_CB 0x1307 #define EEPROM_SIZE 128 /* number of entries in eeprom */ diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 713132c8dbb5..58d5a3d257bd 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -41,7 +41,6 @@ Passing a zero for an option is the same as leaving it unspecified. /*------------------------------ HEADER FILES ---------------------------------*/ #include "../comedidev.h" -#include "comedi_pci.h" #include "8255.h" /*-------------------------- MACROS and DATATYPES -----------------------------*/ diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 5f834d02ec24..a06b67a0b36d 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -45,7 +45,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details. #include #include -#include "comedi_pci.h" #include "plx9052.h" #include "8255.h" diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index b339685e234d..bec250bf15bb 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -86,8 +86,6 @@ Configuration Options: #include "../comedidev.h" -#include "comedi_pci.h" - #include "8255.h" /* device ids of the cards we support -- currently only 1 card supported */ diff --git a/drivers/staging/comedi/drivers/comedi_pci.h b/drivers/staging/comedi/drivers/comedi_pci.h deleted file mode 100644 index c14a036a0536..000000000000 --- a/drivers/staging/comedi/drivers/comedi_pci.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - comedi/drivers/comedi_pci.h - Various PCI functions for drivers. - - Copyright (C) 2007 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - 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. - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef _COMEDI_PCI_H_ -#define _COMEDI_PCI_H_ - -#include - -/* - * Enable the PCI device and request the regions. - */ -static inline int comedi_pci_enable(struct pci_dev *pdev, const char *res_name) -{ - int rc; - - rc = pci_enable_device(pdev); - if (rc < 0) - return rc; - - rc = pci_request_regions(pdev, res_name); - if (rc < 0) - pci_disable_device(pdev); - - return rc; -} - -/* - * Release the regions and disable the PCI device. - * - * This must be matched with a previous successful call to comedi_pci_enable(). - */ -static inline void comedi_pci_disable(struct pci_dev *pdev) -{ - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -#endif diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index b8bac80f2baf..2cd7407adbea 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -36,8 +36,6 @@ Configuration Options: #include "../comedidev.h" -#include "comedi_pci.h" - enum contec_model { PIO1616L = 0, }; diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 696b58ca2e59..d84794ca4380 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -118,7 +118,6 @@ Configuration options: #include #include -#include "comedi_pci.h" #include "8255.h" #define DAQBOARD2000_SUBSYSTEM_IDS2 0x00021616 /* Daqboard/2000 - 2 Dacs */ diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 1f319435e23f..f53e59776a37 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -55,7 +55,6 @@ #include -#include "comedi_pci.h" #include "8255.h" #include "das08.h" diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 0d273269b572..2c1c6140f38f 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -63,8 +63,6 @@ AO commands are not supported. #include "../comedidev.h" #include -#include "comedi_pci.h" - #define PCI_VENDOR_ID_DT 0x1116 static const struct comedi_lrange range_dt3000_ai = { 4, { diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index b0cec7b1b0c9..9586f24ded73 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -38,7 +38,6 @@ */ #include "../comedidev.h" -#include "comedi_pci.h" #include #define PCI_VENDOR_ID_DYNALOG 0x10b5 diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 8aece08bd0dd..79e22b13f734 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -49,7 +49,6 @@ support could be added to this driver. #include "../comedidev.h" #include -#include "comedi_pci.h" #include "plx9080.h" #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h index 68acefe16888..dbf9908cfde6 100644 --- a/drivers/staging/comedi/drivers/icp_multi.h +++ b/drivers/staging/comedi/drivers/icp_multi.h @@ -11,7 +11,6 @@ #define _ICP_MULTI_H_ #include "../comedidev.h" -#include "comedi_pci.h" /****************************************************************************/ diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index d536a11edb95..e8dfc367aa8d 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -49,7 +49,6 @@ Devices: [JR3] PCI force sensor board (jr3_pci) #include #include #include -#include "comedi_pci.h" #include "jr3_pci.h" #define PCI_VENDOR_ID_JR3 0x1762 diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 09d191844bf8..9f92420dd826 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -40,8 +40,6 @@ Kolter Electronic PCI Counter Card. #include "../comedidev.h" -#include "comedi_pci.h" - #define CNT_DRIVER_NAME "ke_counter" #define PCI_VENDOR_ID_KOLTER 0x1001 #define CNT_CARD_DEVICE_ID 0x0014 diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 8ca1b54600db..cb6bf8c5fb45 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -58,7 +58,6 @@ broken. #include #include -#include "comedi_pci.h" #include "me4000.h" #if 0 /* file removed due to GPL incompatibility */ diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index ffe251250e6f..fcadb0fcd1d0 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -54,8 +54,6 @@ from http://www.comedi.org #include #include "../comedidev.h" -#include "comedi_pci.h" - /*#include "me2600_fw.h" */ #define ME_DRIVER_NAME "me_daq" diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 13e9c8071696..a93166d6a8f8 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -52,7 +52,6 @@ #include "mite.h" #include "comedi_fc.h" -#include "comedi_pci.h" #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 1678a0ccb8c1..d3e2786f07cb 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -105,7 +105,6 @@ Configuration options: #include #include "../comedidev.h" -#include "comedi_pci.h" #define DRV_NAME "rtd520" diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 7beb8f6853af..516037009dcd 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -74,8 +74,6 @@ INSN_CONFIG instructions: #include "../comedidev.h" -#include "comedi_pci.h" - #include "comedi_fc.h" #include "s626.h" -- GitLab From 85a15d5bcab6dbae638fb51e2bc93217c7c3b23c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 17:43:31 -0700 Subject: [PATCH 0165/5711] staging: comedi: dt3000: io_addr is a void __iomem * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The io_addr variable in struct dt3k_private is an ioremap'ed pci resource and should be void __iomem * not a void *. This quiets a lot of sparse warings for the writew and readw calls like: warning: incorrect type in argument 1 (different address spaces)    expected void const volatile [noderef] *addr    got void * warning: incorrect type in argument 2 (different address spaces)    expected void volatile [noderef] *addr    got void * Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt3000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 2c1c6140f38f..af0202474127 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -252,7 +252,7 @@ struct dt3k_private { struct pci_dev *pci_dev; resource_size_t phys_addr; - void *io_addr; + void __iomem *io_addr; unsigned int lock; unsigned int ao_readback[2]; unsigned int ai_front; -- GitLab From ff450314d5ef05843d3b3bd33fc65f7aaea3b2df Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 17:52:07 -0700 Subject: [PATCH 0166/5711] staging: comedi: gsc_hpdi: plx9080_iobase and hpdi_iobase are void __iomem * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The plx9080_iobase and hpdi_iobase variables in struct hpdi_private are ioremap'ed pci resource and should be void __iomem * not void *. This quiets a lot of sparse warings for the writel and readl calls like: warning: incorrect type in argument 1 (different address spaces)    expected void const volatile [noderef] *addr    got void * warning: incorrect type in argument 2 (different address spaces)    expected void volatile [noderef] *addr    got void * Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/gsc_hpdi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 79e22b13f734..eeb05553e1a7 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -296,8 +296,8 @@ struct hpdi_private { resource_size_t plx9080_phys_iobase; resource_size_t hpdi_phys_iobase; /* base addresses (ioremapped) */ - void *plx9080_iobase; - void *hpdi_iobase; + void __iomem *plx9080_iobase; + void __iomem *hpdi_iobase; uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ /* physical addresses of dma buffers */ dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; @@ -363,7 +363,7 @@ static void disable_plx_interrupts(struct comedi_device *dev) static void init_plx9080(struct comedi_device *dev) { uint32_t bits; - void *plx_iobase = priv(dev)->plx9080_iobase; + void __iomem *plx_iobase = priv(dev)->plx9080_iobase; /* plx9080 dump */ DEBUG_PRINT(" plx interrupt status 0x%x\n", @@ -672,10 +672,10 @@ static void hpdi_detach(struct comedi_device *dev) if ((priv(dev)) && (priv(dev)->hw_dev)) { if (priv(dev)->plx9080_iobase) { disable_plx_interrupts(dev); - iounmap((void *)priv(dev)->plx9080_iobase); + iounmap(priv(dev)->plx9080_iobase); } if (priv(dev)->hpdi_iobase) - iounmap((void *)priv(dev)->hpdi_iobase); + iounmap(priv(dev)->hpdi_iobase); /* free pci dma buffers */ for (i = 0; i < NUM_DMA_BUFFERS; i++) { if (priv(dev)->dio_buffer[i]) @@ -902,7 +902,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) uint32_t next_transfer_addr; int j; int num_samples = 0; - void *pci_addr_reg; + void __iomem *pci_addr_reg; if (channel) pci_addr_reg = -- GitLab From 86a5eb8ccef09916e622b43f97f115c2526d7d2e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 17:55:33 -0700 Subject: [PATCH 0167/5711] staging: comedi: icp_multi: io_addr is a void __iomem * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The io_addr variable in struct dt3k_private is an ioremap'ed pci resource and should be void __iomem * not a void *. This quiets a lot of sparse warings for the writew and readw calls like: warning: incorrect type in argument 1 (different address spaces)    expected void const volatile [noderef] *addr    got void * warning: incorrect type in argument 2 (different address spaces)    expected void volatile [noderef] *addr    got void * Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/icp_multi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index fdc596fb0990..f870d3da0324 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -148,7 +148,7 @@ struct boardtype { struct icp_multi_private { struct pcilst_struct *card; /* pointer to card */ char valid; /* card is usable */ - void *io_addr; /* Pointer to mapped io address */ + void __iomem *io_addr; /* Pointer to mapped io address */ resource_size_t phys_iobase; /* Physical io address */ unsigned int AdcCmdStatus; /* ADC Command/Status register */ unsigned int DacCmdStatus; /* DAC Command/Status register */ -- GitLab From 4aa7419e082ef5ca38f8934d38fda5909a27962b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 18:10:07 -0700 Subject: [PATCH 0168/5711] staging: comedi: ii_pci20kc: iobase and ioaddr are void __iomem * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iobase variables in struct pci20xxx_subdev_private and ioaddr variable in struct pci20xxx_private should be void __iomem * not void *. This quiets a lot of sparse warings for the writeb and readb calls like: warning: incorrect type in argument 1 (different address spaces)    expected void const volatile [noderef] *addr    got void * warning: incorrect type in argument 2 (different address spaces)    expected void volatile [noderef] *addr    got void * Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index f0a579a04a7d..6f6947602398 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -135,15 +135,15 @@ options for PCI-20341M: #define PCI20341_SCANLIST 0x80 /* Channel/Gain Scan List */ union pci20xxx_subdev_private { - void *iobase; + void __iomem *iobase; struct { - void *iobase; + void __iomem *iobase; const struct comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ unsigned int last_data[2]; } pci20006; struct { - void *iobase; + void __iomem *iobase; int timebase; int settling_time; int ai_gain; @@ -152,7 +152,7 @@ union pci20xxx_subdev_private { struct pci20xxx_private { - void *ioaddr; + void __iomem *ioaddr; union pci20xxx_subdev_private subdev_private[PCI20000_MODULES]; }; @@ -210,7 +210,7 @@ static int pci20xxx_attach(struct comedi_device *dev, if (ret < 0) return ret; - devpriv->ioaddr = (void *)(unsigned long)it->options[0]; + devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; dev->board_name = "pci20kc"; /* Check PCI-20001 C-2A Carrier Board ID */ -- GitLab From 42caa910f286e2be0763a6fb8aa7a998e10c6e02 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 May 2012 18:21:39 -0700 Subject: [PATCH 0169/5711] staging: comedi: s626: base_addr is a void __iomem * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The base_addr variable in struct s626_private is an ioremap'ed pci resource and should be void __iomem * not a void *. This quiets a lot of sparse warings for the writel and readl calls like: warning: incorrect type in argument 1 (different address spaces)    expected void const volatile [noderef] *addr    got void * warning: incorrect type in argument 2 (different address spaces)    expected void volatile [noderef] *addr    got void * Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 516037009dcd..d6dc3381205a 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -118,7 +118,7 @@ static const struct s626_board s626_boards[] = { struct s626_private { struct pci_dev *pdev; - void *base_addr; + void __iomem *base_addr; int got_regions; short allocatedBuf; uint8_t ai_cmd_running; /* ai_cmd is running */ -- GitLab From ad401db6684bef91aca6304e640d63c9c858de2b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 18:08:36 -0700 Subject: [PATCH 0170/5711] staging: comedi: remove thisboard macro in the ssv_dnp driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ssv_dnp.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 16c4f5a757bb..de580958e32a 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -59,9 +59,6 @@ struct dnp_board { int have_dio; }; -/* Useful for shorthand access to the particular board structure ----------- */ -#define thisboard ((const struct dnp_board *)dev->board_ptr) - /* This structure is for data unique to the DNP driver --------------------- */ struct dnp_private_data { @@ -188,18 +185,12 @@ static int dnp_dio_insn_config(struct comedi_device *dev, static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct dnp_board *board = comedi_board(dev); struct comedi_subdevice *s; printk(KERN_INFO "comedi%d: dnp: ", dev->minor); - /* Autoprobing: this should find out which board we have. Currently */ - /* only the 1486 board is supported and autoprobing is not */ - /* implemented :-) */ - /* dev->board_ptr = dnp_probe(dev); */ - - /* Initialize the name of the board. */ - /* We can use the "thisboard" macro now. */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* Allocate the private structure area. alloc_private() is a */ /* convenient macro defined in comedidev.h. */ -- GitLab From 609dd342fb7eab79d42350455c2d86238c7dc15f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 18:04:18 -0700 Subject: [PATCH 0171/5711] staging: comedi: remove this_board macro in the serial2002 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 6342bc5ddb3e..9200310dce5d 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -47,11 +47,6 @@ struct serial2002_board { const char *name; }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct serial2002_board *)dev->board_ptr) - struct serial2002_range_table_t { /* HACK... */ @@ -783,10 +778,11 @@ static int serial2002_ei_rinsn(struct comedi_device *dev, static int serial2002_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct serial2002_board *board = comedi_board(dev); struct comedi_subdevice *s; dev_dbg(dev->hw_dev, "comedi%d: attached\n", dev->minor); - dev->board_name = thisboard->name; + dev->board_name = board->name; if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) return -ENOMEM; dev->open = serial_2002_open; -- GitLab From 354c00a67697fc7a56b540647ef7fe93333ed903 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:59:07 -0700 Subject: [PATCH 0172/5711] staging: comedi: remove this_board macro in the rti800 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rti800.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index f0eb52a77881..04a23687ae3e 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -138,8 +138,6 @@ struct rti800_board { int has_ao; }; -#define this_board ((const struct rti800_board *)dev->board_ptr) - static irqreturn_t rti800_interrupt(int irq, void *dev); struct rti800_private { @@ -309,6 +307,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev, static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct rti800_board *board = comedi_board(dev); unsigned int irq; unsigned long iobase; int ret; @@ -347,7 +346,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "( no irq )\n"); } - dev->board_name = this_board->name; + dev->board_name = board->name; ret = alloc_subdevices(dev, 4); if (ret < 0) @@ -386,7 +385,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) } s++; - if (this_board->has_ao) { + if (board->has_ao) { /* ao subdevice (only on rti815) */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; -- GitLab From d5016e242b3ca919e3be7fa98dbb2b35e61c1efe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:54:46 -0700 Subject: [PATCH 0173/5711] staging: comedi: remove this_board macro in the poc driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/poc.c | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index e7120480687b..95e348fa89c8 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -57,8 +57,6 @@ struct boarddef_struct { const struct comedi_lrange *range; }; -#define this_board ((const struct boarddef_struct *)dev->board_ptr) - static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { @@ -137,22 +135,23 @@ static int pcl734_insn_bits(struct comedi_device *dev, static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct boarddef_struct *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; unsigned int iosize; iobase = it->options[0]; printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor, - this_board->name, iobase); + board->name, iobase); - dev->board_name = this_board->name; + dev->board_name = board->name; if (iobase == 0) { printk(KERN_ERR "io base address required\n"); return -EINVAL; } - iosize = this_board->iosize; + iosize = board->iosize; /* check if io addresses are available */ if (!request_region(iobase, iosize, "dac02")) { printk(KERN_ERR "I/O port conflict: failed to allocate ports " @@ -163,18 +162,18 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_subdevices(dev, 1) < 0) return -ENOMEM; - if (alloc_private(dev, sizeof(unsigned int) * this_board->n_chan) < 0) + if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0) return -ENOMEM; /* analog output subdevice */ s = dev->subdevices + 0; - s->type = this_board->type; - s->n_chan = this_board->n_chan; - s->maxdata = (1 << this_board->n_bits) - 1; - s->range_table = this_board->range; - s->insn_write = this_board->winsn; - s->insn_read = this_board->rinsn; - s->insn_bits = this_board->insnbits; + s->type = board->type; + s->n_chan = board->n_chan; + s->maxdata = (1 << board->n_bits) - 1; + s->range_table = board->range; + s->insn_write = board->winsn; + s->insn_read = board->rinsn; + s->insn_bits = board->insnbits; if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO) s->subdev_flags = SDF_WRITABLE; @@ -183,8 +182,10 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void poc_detach(struct comedi_device *dev) { + const struct boarddef_struct *board = comedi_board(dev); + if (dev->iobase) - release_region(dev->iobase, this_board->iosize); + release_region(dev->iobase, board->iosize); } static const struct boarddef_struct boards[] = { -- GitLab From a28b59957d3ad01481c2ea87aca50cfdb85417f2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:51:35 -0700 Subject: [PATCH 0174/5711] staging: comedi: remove this_board macro in the pcmuio driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 623381d50dac..b1a9bed38551 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -155,11 +155,6 @@ struct pcmuio_board { const int num_ports; }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct pcmuio_board *)dev->board_ptr) - /* this structure is for data unique to this subdevice. */ struct pcmuio_subdev_private { /* mapping of halfwords (bytes) in port/chanarray to iobase */ @@ -354,7 +349,9 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev, static void switch_page(struct comedi_device *dev, int asic, int page) { - if (asic < 0 || asic >= thisboard->num_asics) + const struct pcmuio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->num_asics) return; /* paranoia */ if (page < 0 || page >= NUM_PAGES) return; /* more paranoia */ @@ -370,9 +367,10 @@ static void switch_page(struct comedi_device *dev, int asic, int page) static void init_asics(struct comedi_device *dev) { /* sets up an ASIC chip to defaults */ + const struct pcmuio_board *board = comedi_board(dev); int asic; - for (asic = 0; asic < thisboard->num_asics; ++asic) { + for (asic = 0; asic < board->num_asics; ++asic) { int port, page; unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE; @@ -407,7 +405,9 @@ static void init_asics(struct comedi_device *dev) #ifdef notused static void lock_port(struct comedi_device *dev, int asic, int port) { - if (asic < 0 || asic >= thisboard->num_asics) + const struct pcmuio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->num_asics) return; /* paranoia */ if (port < 0 || port >= PORTS_PER_ASIC) return; /* more paranoia */ @@ -420,7 +420,9 @@ static void lock_port(struct comedi_device *dev, int asic, int port) static void unlock_port(struct comedi_device *dev, int asic, int port) { - if (asic < 0 || asic >= thisboard->num_asics) + const struct pcmuio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->num_asics) return; /* paranoia */ if (port < 0 || port >= PORTS_PER_ASIC) return; /* more paranoia */ @@ -747,6 +749,7 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcmuio_board *board = comedi_board(dev); struct comedi_subdevice *s; int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; unsigned long iobase; @@ -762,17 +765,13 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; if (!iobase || !request_region(iobase, - thisboard->num_asics * ASIC_IOSIZE, + board->num_asics * ASIC_IOSIZE, dev->driver->driver_name)) { dev_err(dev->hw_dev, "I/O port conflict\n"); return -EIO; } -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a @@ -792,7 +791,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) spin_lock_init(&devpriv->asics[asic].spinlock); } - chans_left = CHANS_PER_ASIC * thisboard->num_asics; + chans_left = CHANS_PER_ASIC * board->num_asics; n_subdevs = CALC_N_SUBDEVS(chans_left); devpriv->sprivs = kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private), @@ -881,7 +880,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { if (irq[asic] && request_irq(irq[asic], interrupt_pcmuio, - IRQF_SHARED, thisboard->name, dev)) { + IRQF_SHARED, board->name, dev)) { int i; /* unroll the allocated irqs.. */ for (i = asic - 1; i >= 0; --i) { @@ -898,7 +897,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (irq[0]) { dev_dbg(dev->hw_dev, "irq: %u\n", irq[0]); - if (irq[1] && thisboard->num_asics == 2) + if (irq[1] && board->num_asics == 2) dev_dbg(dev->hw_dev, "second ASIC irq: %u\n", irq[1]); } else { dev_dbg(dev->hw_dev, "(IRQ mode disabled)\n"); @@ -910,10 +909,11 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcmuio_detach(struct comedi_device *dev) { + const struct pcmuio_board *board = comedi_board(dev); int i; if (dev->iobase) - release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics); + release_region(dev->iobase, ASIC_IOSIZE * board->num_asics); for (i = 0; i < MAX_ASICS; ++i) { if (devpriv->asics[i].irq) free_irq(devpriv->asics[i].irq, dev); -- GitLab From 57bbeb3b9bc32f1ee4b14439e11ed475deab1263 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:46:56 -0700 Subject: [PATCH 0175/5711] staging: comedi: remove this_board macro in the pcmmio driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 56 ++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index efed168d2bac..c4482ae9d08b 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -183,11 +183,6 @@ static const struct comedi_lrange ranges_ao = { RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)} }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct pcmmio_board *)dev->board_ptr) - /* this structure is for data unique to this subdevice. */ struct pcmmio_subdev_private { @@ -423,7 +418,9 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev, static void switch_page(struct comedi_device *dev, int asic, int page) { - if (asic < 0 || asic >= thisboard->dio_num_asics) + const struct pcmmio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->dio_num_asics) return; /* paranoia */ if (page < 0 || page >= NUM_PAGES) return; /* more paranoia */ @@ -439,9 +436,10 @@ static void switch_page(struct comedi_device *dev, int asic, int page) static void init_asics(struct comedi_device *dev) { /* sets up an ASIC chip to defaults */ + const struct pcmmio_board *board = comedi_board(dev); int asic; - for (asic = 0; asic < thisboard->dio_num_asics; ++asic) { + for (asic = 0; asic < board->dio_num_asics; ++asic) { int port, page; unsigned long baseaddr = devpriv->asics[asic].iobase; @@ -476,7 +474,9 @@ static void init_asics(struct comedi_device *dev) #ifdef notused static void lock_port(struct comedi_device *dev, int asic, int port) { - if (asic < 0 || asic >= thisboard->dio_num_asics) + const struct pcmmio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->dio_num_asics) return; /* paranoia */ if (port < 0 || port >= PORTS_PER_ASIC) return; /* more paranoia */ @@ -490,7 +490,9 @@ static void lock_port(struct comedi_device *dev, int asic, int port) static void unlock_port(struct comedi_device *dev, int asic, int port) { - if (asic < 0 || asic >= thisboard->dio_num_asics) + const struct pcmmio_board *board = comedi_board(dev); + + if (asic < 0 || asic >= board->dio_num_asics) return; /* paranoia */ if (port < 0 || port >= PORTS_PER_ASIC) return; /* more paranoia */ @@ -1012,6 +1014,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcmmio_board *board = comedi_board(dev); struct comedi_subdevice *s; int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic, thisasic_chanct = 0; @@ -1027,17 +1030,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; if (!iobase || !request_region(iobase, - thisboard->total_iosize, + board->total_iosize, dev->driver->driver_name)) { printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); return -EIO; } -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a @@ -1061,7 +1060,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) spin_lock_init(&devpriv->asics[asic].spinlock); } - chans_left = CHANS_PER_ASIC * thisboard->dio_num_asics; + chans_left = CHANS_PER_ASIC * board->dio_num_asics; n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left); n_subdevs = n_dio_subdevs + 2; devpriv->sprivs = @@ -1088,13 +1087,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) sdev_no = 0; s = dev->subdevices + sdev_no; s->private = devpriv->sprivs + sdev_no; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ai_range_table; + s->maxdata = (1 << board->ai_bits) - 1; + s->range_table = board->ai_range_table; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->type = COMEDI_SUBD_AI; - s->n_chan = thisboard->n_ai_chans; + s->n_chan = board->n_ai_chans; s->len_chanlist = s->n_chan; - s->insn_read = thisboard->ai_rinsn; + s->insn_read = board->ai_rinsn; subpriv->iobase = dev->iobase + 0; /* initialize the resource enable register by clearing it */ outb(0, subpriv->iobase + 3); @@ -1104,14 +1103,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) ++sdev_no; s = dev->subdevices + sdev_no; s->private = devpriv->sprivs + sdev_no; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ao_range_table; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_range_table; s->subdev_flags = SDF_READABLE; s->type = COMEDI_SUBD_AO; - s->n_chan = thisboard->n_ao_chans; + s->n_chan = board->n_ao_chans; s->len_chanlist = s->n_chan; - s->insn_read = thisboard->ao_rinsn; - s->insn_write = thisboard->ao_winsn; + s->insn_read = board->ao_rinsn; + s->insn_write = board->ao_winsn; subpriv->iobase = dev->iobase + 8; /* initialize the resource enable register by clearing it */ outb(0, subpriv->iobase + 3); @@ -1192,7 +1191,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { if (irq[asic] && request_irq(irq[asic], interrupt_pcmmio, - IRQF_SHARED, thisboard->name, dev)) { + IRQF_SHARED, board->name, dev)) { int i; /* unroll the allocated irqs.. */ for (i = asic - 1; i >= 0; --i) { @@ -1211,7 +1210,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (irq[0]) { printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]); - if (thisboard->dio_num_asics == 2 && irq[1]) + if (board->dio_num_asics == 2 && irq[1]) printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n", dev->minor, irq[1]); } else { @@ -1225,10 +1224,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcmmio_detach(struct comedi_device *dev) { + const struct pcmmio_board *board = comedi_board(dev); int i; if (dev->iobase) - release_region(dev->iobase, thisboard->total_iosize); + release_region(dev->iobase, board->total_iosize); for (i = 0; i < MAX_ASICS; ++i) { if (devpriv && devpriv->asics[i].irq) free_irq(devpriv->asics[i].irq, dev); -- GitLab From 2fbffee0604fd3f6f9e3aa56e3fe1aa061a32ca6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:42:55 -0700 Subject: [PATCH 0176/5711] staging: comedi: remove thisboard macro in the pcmda12 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmda12.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 4786148b4fd0..f49c66afe5fc 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -80,11 +80,6 @@ static const struct comedi_lrange pcmda12_ranges = { } }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct pcmda12_board *)dev->board_ptr) - struct pcmda12_private { unsigned int ao_readback[CHANS]; @@ -167,6 +162,7 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcmda12_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcmda12_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; @@ -181,11 +177,7 @@ static int pcmda12_attach(struct comedi_device *dev, } dev->iobase = iobase; -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a -- GitLab From 449b683c6b4f92af648447f9eb449fd52ce6d56b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:39:22 -0700 Subject: [PATCH 0177/5711] staging: comedi: remove this_board macro in the pcmad driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmad.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 1ec7d5cb346a..2ec0b2e63c35 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -58,8 +58,6 @@ struct pcmad_board_struct { int n_ai_bits; }; -#define this_board ((const struct pcmad_board_struct *)(dev->board_ptr)) - struct pcmad_priv_struct { int differential; int twos_comp; @@ -72,6 +70,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct pcmad_board_struct *board = comedi_board(dev); int i; int chan; int n; @@ -89,7 +88,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev, data[n] |= (inb(dev->iobase + PCMAD_MSB) << 8); if (devpriv->twos_comp) - data[n] ^= (1 << (this_board->n_ai_bits - 1)); + data[n] ^= (1 << (board->n_ai_bits - 1)); } return n; @@ -104,6 +103,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev, */ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcmad_board_struct *board = comedi_board(dev); int ret; struct comedi_subdevice *s; unsigned long iobase; @@ -125,7 +125,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - dev->board_name = this_board->name; + dev->board_name = board->name; s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; @@ -133,7 +133,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->n_chan = 16; /* XXX */ s->len_chanlist = 1; s->insn_read = pcmad_ai_insn_read; - s->maxdata = (1 << this_board->n_ai_bits) - 1; + s->maxdata = (1 << board->n_ai_bits) - 1; s->range_table = &range_unknown; return 0; -- GitLab From 3cff0f1249f9be93c44ea071bafd9f28f673898d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:26:43 -0700 Subject: [PATCH 0178/5711] staging: comedi: remove this_board macro in the pcm3724 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcm3724.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 7492b8f1d499..9eee708e8442 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -76,10 +76,6 @@ struct priv_pcm3724 { int dio_2; }; -#define this_board ((const struct pcm3724_board *)dev->board_ptr) - -/* (setq c-basic-offset 8) */ - static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) { unsigned long iobase = arg; @@ -234,12 +230,13 @@ static int subdev_3724_insn_config(struct comedi_device *dev, static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcm3724_board *board = comedi_board(dev); unsigned long iobase; unsigned int iorange; int ret, i, n_subdevices; iobase = it->options[0]; - iorange = this_board->io_range; + iorange = board->io_range; ret = alloc_private(dev, sizeof(struct priv_pcm3724)); if (ret < 0) @@ -249,17 +246,17 @@ static int pcm3724_attach(struct comedi_device *dev, ((struct priv_pcm3724 *)(dev->private))->dio_2 = 0; printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor, - this_board->name, iobase); + board->name, iobase); if (!iobase || !request_region(iobase, iorange, "pcm3724")) { printk("I/O port conflict\n"); return -EIO; } dev->iobase = iobase; - dev->board_name = this_board->name; + dev->board_name = board->name; printk(KERN_INFO "\n"); - n_subdevices = this_board->numofports; + n_subdevices = board->numofports; ret = alloc_subdevices(dev, n_subdevices); if (ret < 0) @@ -275,6 +272,7 @@ static int pcm3724_attach(struct comedi_device *dev, static void pcm3724_detach(struct comedi_device *dev) { + const struct pcm3724_board *board = comedi_board(dev); int i; if (dev->subdevices) { @@ -282,7 +280,7 @@ static void pcm3724_detach(struct comedi_device *dev) subdev_8255_cleanup(dev, dev->subdevices + i); } if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } static const struct pcm3724_board boardtypes[] = { -- GitLab From dd8a4b478846c2cd38c09dcc564a8b964da185d0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:22:48 -0700 Subject: [PATCH 0179/5711] staging: comedi: remove this_board macro in the pcl818 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 74 +++++++++++++------------ 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 1406c9720f5d..6c84b29a8dad 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -326,7 +326,6 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0 }; #define devpriv ((struct pcl818_private *)dev->private) -#define this_board ((const struct pcl818_board *)dev->board_ptr) /* ============================================================================== @@ -1264,6 +1263,7 @@ static int check_single_ended(unsigned int port) static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct pcl818_board *board = comedi_board(dev); int err = 0; int tmp, divisor1 = 0, divisor2 = 0; @@ -1334,8 +1334,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < this_board->ns_min) { - cmd->convert_arg = this_board->ns_min; + if (cmd->convert_arg < board->ns_min) { + cmd->convert_arg = board->ns_min; err++; } } else { /* TRIG_EXT */ @@ -1371,8 +1371,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - if (cmd->convert_arg < this_board->ns_min) - cmd->convert_arg = this_board->ns_min; + if (cmd->convert_arg < board->ns_min) + cmd->convert_arg = board->ns_min; if (tmp != cmd->convert_arg) err++; } @@ -1519,6 +1519,8 @@ static int pcl818_check(unsigned long iobase) */ static void pcl818_reset(struct comedi_device *dev) { + const struct pcl818_board *board = comedi_board(dev); + if (devpriv->usefifo) { /* FIFO shutdown */ outb(0, dev->iobase + PCL818_FI_INTCLR); outb(0, dev->iobase + PCL818_FI_FLUSH); @@ -1537,7 +1539,7 @@ static void pcl818_reset(struct comedi_device *dev) outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */ outb(0x70, dev->iobase + PCL818_CTRCTL); outb(0x30, dev->iobase + PCL818_CTRCTL); - if (this_board->is_818) { + if (board->is_818) { outb(0, dev->iobase + PCL818_RANGE); } else { outb(0, dev->iobase + PCL718_DA2_LO); @@ -1636,6 +1638,7 @@ static int rtc_setfreq_irq(int freq) static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl818_board *board = comedi_board(dev); int ret; unsigned long iobase; unsigned int irq; @@ -1651,9 +1654,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase = it->options[0]; printk ("comedi%d: pcl818: board=%s, ioport=0x%03lx", - dev->minor, this_board->name, iobase); - devpriv->io_range = this_board->io_range; - if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */ + dev->minor, board->name, iobase); + devpriv->io_range = board->io_range; + if ((board->fifo) && (it->options[2] == -1)) { + /* we've board with FIFO and we want to use FIFO */ devpriv->io_range = PCLx1xFIFO_RANGE; devpriv->usefifo = 1; } @@ -1669,14 +1673,14 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EIO; } - /* set up some name stuff */ - dev->board_name = this_board->name; + dev->board_name = board->name; + /* grab our IRQ */ irq = 0; - if (this_board->IRQbits != 0) { /* board support IRQ */ + if (board->IRQbits != 0) { /* board support IRQ */ irq = it->options[1]; if (irq) { /* we want to use IRQ */ - if (((1 << irq) & this_board->IRQbits) == 0) { + if (((1 << irq) & board->IRQbits) == 0) { printk (", IRQ %u is out of allowed range, DISABLING IT", irq); @@ -1740,11 +1744,11 @@ no_rtc: devpriv->dma = dma; if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) goto no_dma; /* if we haven't IRQ, we can't use DMA */ - if (this_board->DMAbits != 0) { /* board support DMA */ + if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; if (dma < 1) goto no_dma; /* DMA disabled */ - if (((1 << dma) & this_board->DMAbits) == 0) { + if (((1 << dma) & board->DMAbits) == 0) { printk(KERN_ERR "DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } @@ -1779,24 +1783,24 @@ no_dma: return ret; s = dev->subdevices + 0; - if (!this_board->n_aichan_se) { + if (!board->n_aichan_se) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_AI; devpriv->sub_ai = s; s->subdev_flags = SDF_READABLE; if (check_single_ended(dev->iobase)) { - s->n_chan = this_board->n_aichan_se; + s->n_chan = board->n_aichan_se; s->subdev_flags |= SDF_COMMON | SDF_GROUND; printk(", %dchans S.E. DAC", s->n_chan); } else { - s->n_chan = this_board->n_aichan_diff; + s->n_chan = board->n_aichan_diff; s->subdev_flags |= SDF_DIFF; printk(", %dchans DIFF DAC", s->n_chan); } - s->maxdata = this_board->ai_maxdata; + s->maxdata = board->ai_maxdata; s->len_chanlist = s->n_chan; - s->range_table = this_board->ai_range_type; + s->range_table = board->ai_range_type; s->cancel = pcl818_ai_cancel; s->insn_read = pcl818_ai_insn_read; if ((irq) || (devpriv->dma_rtc)) { @@ -1805,7 +1809,7 @@ no_dma: s->do_cmdtest = ai_cmdtest; s->do_cmd = ai_cmd; } - if (this_board->is_818) { + if (board->is_818) { if ((it->options[4] == 1) || (it->options[4] == 10)) s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */ } else { @@ -1845,15 +1849,15 @@ no_dma: } s = dev->subdevices + 1; - if (!this_board->n_aochan) { + if (!board->n_aochan) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = this_board->n_aochan; - s->maxdata = this_board->ao_maxdata; - s->len_chanlist = this_board->n_aochan; - s->range_table = this_board->ao_range_type; + s->n_chan = board->n_aochan; + s->maxdata = board->ao_maxdata; + s->len_chanlist = board->n_aochan; + s->range_table = board->ao_range_type; s->insn_read = pcl818_ao_insn_read; s->insn_write = pcl818_ao_insn_write; #ifdef unused @@ -1864,7 +1868,7 @@ no_dma: } #endif #endif - if (this_board->is_818) { + if (board->is_818) { if ((it->options[4] == 1) || (it->options[4] == 10)) s->range_table = &range_unipolar10; if (it->options[4] == 2) @@ -1878,27 +1882,27 @@ no_dma: } s = dev->subdevices + 2; - if (!this_board->n_dichan) { + if (!board->n_dichan) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->n_dichan; + s->n_chan = board->n_dichan; s->maxdata = 1; - s->len_chanlist = this_board->n_dichan; + s->len_chanlist = board->n_dichan; s->range_table = &range_digital; s->insn_bits = pcl818_di_insn_bits; } s = dev->subdevices + 3; - if (!this_board->n_dochan) { + if (!board->n_dochan) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_dochan; + s->n_chan = board->n_dochan; s->maxdata = 1; - s->len_chanlist = this_board->n_dochan; + s->len_chanlist = board->n_dochan; s->range_table = &range_digital; s->insn_bits = pcl818_do_insn_bits; } @@ -1910,9 +1914,9 @@ no_dma: devpriv->i8253_osc_base = 1000; /* max sampling speed */ - devpriv->ns_min = this_board->ns_min; + devpriv->ns_min = board->ns_min; - if (!this_board->is_818) { + if (!board->is_818) { if ((it->options[6] == 1) || (it->options[6] == 100)) devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ } -- GitLab From 240c6e6a7125fd7a6ebcbdd8fbbf646df0f69186 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:14:14 -0700 Subject: [PATCH 0180/5711] staging: comedi: remove this_board macro in the pcl816 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 71 +++++++++++++------------ 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index cc67b6d46059..277a23ece6fa 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -126,7 +126,6 @@ struct pcl816_board { }; #define devpriv ((struct pcl816_private *)dev->private) -#define this_board ((const struct pcl816_board *)dev->board_ptr) #ifdef unused static int RTC_lock; /* RTC lock */ @@ -451,6 +450,7 @@ static void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd) static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct pcl816_board *board = comedi_board(dev); int err = 0; int tmp, divisor1 = 0, divisor2 = 0; @@ -531,8 +531,8 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, err++; } if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < this_board->ai_ns_min) { - cmd->convert_arg = this_board->ai_ns_min; + if (cmd->convert_arg < board->ai_ns_min) { + cmd->convert_arg = board->ai_ns_min; err++; } } else { /* TRIG_EXT */ @@ -565,12 +565,12 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(this_board->i8254_osc_base, + i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; + if (cmd->convert_arg < board->ai_ns_min) + cmd->convert_arg = board->ai_ns_min; if (tmp != cmd->convert_arg) err++; } @@ -592,6 +592,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct pcl816_board *board = comedi_board(dev); unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq; struct comedi_cmd *cmd = &s->async->cmd; unsigned int seglen; @@ -609,10 +610,10 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EBUSY; if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; + if (cmd->convert_arg < board->ai_ns_min) + cmd->convert_arg = board->ai_ns_min; - i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, + i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); @@ -1028,6 +1029,7 @@ static int set_rtc_irq_bit(unsigned char bit) static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl816_board *board = comedi_board(dev); int ret; unsigned long iobase; unsigned int irq, dma; @@ -1038,9 +1040,9 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* claim our I/O space */ iobase = it->options[0]; printk("comedi%d: pcl816: board=%s, ioport=0x%03lx", dev->minor, - this_board->name, iobase); + board->name, iobase); - if (!request_region(iobase, this_board->io_range, "pcl816")) { + if (!request_region(iobase, board->io_range, "pcl816")) { printk("I/O port conflict\n"); return -EIO; } @@ -1056,15 +1058,14 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; /* Can't alloc mem */ - /* set up some name stuff */ - dev->board_name = this_board->name; + dev->board_name = board->name; /* grab our IRQ */ irq = 0; - if (this_board->IRQbits != 0) { /* board support IRQ */ + if (board->IRQbits != 0) { /* board support IRQ */ irq = it->options[1]; if (irq) { /* we want to use IRQ */ - if (((1 << irq) & this_board->IRQbits) == 0) { + if (((1 << irq) & board->IRQbits) == 0) { printk (", IRQ %u is out of allowed range, " "DISABLING IT", irq); @@ -1134,12 +1135,12 @@ no_rtc: if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) goto no_dma; /* if we haven't IRQ, we can't use DMA */ - if (this_board->DMAbits != 0) { /* board support DMA */ + if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; if (dma < 1) goto no_dma; /* DMA disabled */ - if (((1 << dma) & this_board->DMAbits) == 0) { + if (((1 << dma) & board->DMAbits) == 0) { printk(", DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } @@ -1185,11 +1186,11 @@ no_rtc: no_dma: -/* if (this_board->n_aochan > 0) +/* if (board->n_aochan > 0) subdevs[1] = COMEDI_SUBD_AO; - if (this_board->n_dichan > 0) + if (board->n_dichan > 0) subdevs[2] = COMEDI_SUBD_DI; - if (this_board->n_dochan > 0) + if (board->n_dochan > 0) subdevs[3] = COMEDI_SUBD_DO; */ @@ -1198,17 +1199,17 @@ no_dma: return ret; s = dev->subdevices + 0; - if (this_board->n_aichan > 0) { + if (board->n_aichan > 0) { s->type = COMEDI_SUBD_AI; devpriv->sub_ai = s; dev->read_subdev = s; s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->subdev_flags |= SDF_DIFF; /* printk (", %dchans DIFF DAC - %d", s->n_chan, i); */ - s->maxdata = this_board->ai_maxdata; - s->len_chanlist = this_board->ai_chanlist; - s->range_table = this_board->ai_range_type; + s->maxdata = board->ai_maxdata; + s->len_chanlist = board->ai_chanlist; + s->range_table = board->ai_range_type; s->cancel = pcl816_ai_cancel; s->do_cmdtest = pcl816_ai_cmdtest; s->do_cmd = pcl816_ai_cmd; @@ -1221,25 +1222,25 @@ no_dma: #if 0 case COMEDI_SUBD_AO: s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = this_board->n_aochan; - s->maxdata = this_board->ao_maxdata; - s->len_chanlist = this_board->ao_chanlist; - s->range_table = this_board->ao_range_type; + s->n_chan = board->n_aochan; + s->maxdata = board->ao_maxdata; + s->len_chanlist = board->ao_chanlist; + s->range_table = board->ao_range_type; break; case COMEDI_SUBD_DI: s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->n_dichan; + s->n_chan = board->n_dichan; s->maxdata = 1; - s->len_chanlist = this_board->n_dichan; + s->len_chanlist = board->n_dichan; s->range_table = &range_digital; break; case COMEDI_SUBD_DO: s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_dochan; + s->n_chan = board->n_dochan; s->maxdata = 1; - s->len_chanlist = this_board->n_dochan; + s->len_chanlist = board->n_dochan; s->range_table = &range_digital; break; #endif @@ -1253,6 +1254,8 @@ case COMEDI_SUBD_DO: static void pcl816_detach(struct comedi_device *dev) { + const struct pcl816_board *board = comedi_board(dev); + if (dev->private) { pcl816_ai_cancel(dev, devpriv->sub_ai); pcl816_reset(dev); @@ -1275,7 +1278,7 @@ static void pcl816_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); #ifdef unused if (devpriv->dma_rtc) RTC_lock--; -- GitLab From 3cb08e08fbeab09fa5f3ba1cf27176dd41f5b70f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:09:03 -0700 Subject: [PATCH 0181/5711] staging: comedi: remove this_board macro in the pcl812 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 98 +++++++++++++------------ 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 51f4ca9f7927..28780ede1ee5 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -336,8 +336,6 @@ struct pcl812_board { unsigned char haveMPC508; /* 1=board use MPC508A multiplexor */ }; -#define this_board ((const struct pcl812_board *)dev->board_ptr) - struct pcl812_private { unsigned char valid; /* =1 device is OK */ @@ -560,6 +558,7 @@ static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd) static int pcl812_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct pcl812_board *board = comedi_board(dev); int err = 0; int tmp, divisor1, divisor2; @@ -666,8 +665,8 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < this_board->ai_ns_min) { - cmd->convert_arg = this_board->ai_ns_min; + if (cmd->convert_arg < board->ai_ns_min) { + cmd->convert_arg = board->ai_ns_min; err++; } } else { /* TRIG_EXT */ @@ -682,7 +681,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, err++; } if (cmd->chanlist_len > MAX_CHANLIST_LEN) { - cmd->chanlist_len = this_board->n_aichan; + cmd->chanlist_len = board->n_aichan; err++; } if (cmd->scan_end_arg != cmd->chanlist_len) { @@ -715,11 +714,11 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, + i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; + if (cmd->convert_arg < board->ai_ns_min) + cmd->convert_arg = board->ai_ns_min; if (tmp != cmd->convert_arg) err++; } @@ -741,6 +740,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, */ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct pcl812_board *board = comedi_board(dev); unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes; struct comedi_cmd *cmd = &s->async->cmd; @@ -767,9 +767,9 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EINVAL; if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; - i8253_cascade_ns_to_timer(this_board->i8254_osc_base, + if (cmd->convert_arg < board->ai_ns_min) + cmd->convert_arg = board->ai_ns_min; + i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); @@ -1192,6 +1192,7 @@ static void start_pacer(struct comedi_device *dev, int mode, */ static void free_resources(struct comedi_device *dev) { + const struct pcl812_board *board = comedi_board(dev); if (dev->private) { if (devpriv->dmabuf[0]) @@ -1204,7 +1205,7 @@ static void free_resources(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } /* @@ -1234,6 +1235,8 @@ static int pcl812_ai_cancel(struct comedi_device *dev, */ static void pcl812_reset(struct comedi_device *dev) { + const struct pcl812_board *board = comedi_board(dev); + #ifdef PCL812_EXTDEBUG printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_reset(...)\n"); #endif @@ -1242,7 +1245,7 @@ static void pcl812_reset(struct comedi_device *dev) devpriv->old_chan_reg = -1; /* invalidate chain/gain memory */ devpriv->old_gain_reg = -1; - switch (this_board->board_type) { + switch (board->board_type) { case boardPCL812PG: case boardPCL812: case boardACL8112: @@ -1273,6 +1276,7 @@ static void pcl812_reset(struct comedi_device *dev) static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl812_board *board = comedi_board(dev); int ret, subdev; unsigned long iobase; unsigned int irq; @@ -1283,9 +1287,9 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase = it->options[0]; printk(KERN_INFO "comedi%d: pcl812: board=%s, ioport=0x%03lx", - dev->minor, this_board->name, iobase); + dev->minor, board->name, iobase); - if (!request_region(iobase, this_board->io_range, "pcl812")) { + if (!request_region(iobase, board->io_range, "pcl812")) { printk("I/O port conflict\n"); return -EIO; } @@ -1297,13 +1301,13 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* Can't alloc mem */ } - dev->board_name = this_board->name; + dev->board_name = board->name; irq = 0; - if (this_board->IRQbits != 0) { /* board support IRQ */ + if (board->IRQbits != 0) { /* board support IRQ */ irq = it->options[1]; if (irq) { /* we want to use IRQ */ - if (((1 << irq) & this_board->IRQbits) == 0) { + if (((1 << irq) & board->IRQbits) == 0) { printk (", IRQ %u is out of allowed range, " "DISABLING IT", irq); @@ -1328,9 +1332,9 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dma = dma; if (!dev->irq) goto no_dma; /* if we haven't IRQ, we can't use DMA */ - if (this_board->DMAbits != 0) { /* board support DMA */ + if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; - if (((1 << dma) & this_board->DMAbits) == 0) { + if (((1 << dma) & board->DMAbits) == 0) { printk(", DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } @@ -1369,13 +1373,13 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) no_dma: n_subdevices = 0; - if (this_board->n_aichan > 0) + if (board->n_aichan > 0) n_subdevices++; - if (this_board->n_aochan > 0) + if (board->n_aochan > 0) n_subdevices++; - if (this_board->n_dichan > 0) + if (board->n_dichan > 0) n_subdevices++; - if (this_board->n_dochan > 0) + if (board->n_dochan > 0) n_subdevices++; ret = alloc_subdevices(dev, n_subdevices); @@ -1387,46 +1391,46 @@ no_dma: subdev = 0; /* analog input */ - if (this_board->n_aichan > 0) { + if (board->n_aichan > 0) { s = dev->subdevices + subdev; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE; - switch (this_board->board_type) { + switch (board->board_type) { case boardA821: if (it->options[2] == 1) { - s->n_chan = this_board->n_aichan_diff; + s->n_chan = board->n_aichan_diff; s->subdev_flags |= SDF_DIFF; devpriv->use_diff = 1; } else { - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->subdev_flags |= SDF_GROUND; } break; case boardACL8112: case boardACL8216: if (it->options[4] == 1) { - s->n_chan = this_board->n_aichan_diff; + s->n_chan = board->n_aichan_diff; s->subdev_flags |= SDF_DIFF; devpriv->use_diff = 1; } else { - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->subdev_flags |= SDF_GROUND; } break; default: - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->subdev_flags |= SDF_GROUND; break; } - s->maxdata = this_board->ai_maxdata; + s->maxdata = board->ai_maxdata; s->len_chanlist = MAX_CHANLIST_LEN; - s->range_table = this_board->rangelist_ai; - if (this_board->board_type == boardACL8216) + s->range_table = board->rangelist_ai; + if (board->board_type == boardACL8216) s->insn_read = acl8216_ai_insn_read; else s->insn_read = pcl812_ai_insn_read; - devpriv->use_MPC = this_board->haveMPC508; + devpriv->use_MPC = board->haveMPC508; s->cancel = pcl812_ai_cancel; if (dev->irq) { dev->read_subdev = s; @@ -1435,7 +1439,7 @@ no_dma: s->do_cmd = pcl812_ai_cmd; s->poll = pcl812_ai_poll; } - switch (this_board->board_type) { + switch (board->board_type) { case boardPCL812PG: if (it->options[4] == 1) s->range_table = &range_pcl812pg2_ai; @@ -1529,17 +1533,17 @@ no_dma: } /* analog output */ - if (this_board->n_aochan > 0) { + if (board->n_aochan > 0) { s = dev->subdevices + subdev; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = this_board->n_aochan; + s->n_chan = board->n_aochan; s->maxdata = 0xfff; s->len_chanlist = 1; - s->range_table = this_board->rangelist_ao; + s->range_table = board->rangelist_ao; s->insn_read = pcl812_ao_insn_read; s->insn_write = pcl812_ao_insn_write; - switch (this_board->board_type) { + switch (board->board_type) { case boardA821: if (it->options[3] == 1) s->range_table = &range_unipolar10; @@ -1558,32 +1562,32 @@ no_dma: } /* digital input */ - if (this_board->n_dichan > 0) { + if (board->n_dichan > 0) { s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->n_dichan; + s->n_chan = board->n_dichan; s->maxdata = 1; - s->len_chanlist = this_board->n_dichan; + s->len_chanlist = board->n_dichan; s->range_table = &range_digital; s->insn_bits = pcl812_di_insn_bits; subdev++; } /* digital output */ - if (this_board->n_dochan > 0) { + if (board->n_dochan > 0) { s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_dochan; + s->n_chan = board->n_dochan; s->maxdata = 1; - s->len_chanlist = this_board->n_dochan; + s->len_chanlist = board->n_dochan; s->range_table = &range_digital; s->insn_bits = pcl812_do_insn_bits; subdev++; } - switch (this_board->board_type) { + switch (board->board_type) { case boardACL8216: devpriv->ai_is16b = 1; case boardPCL812PG: -- GitLab From 6f929aeb175fd634f5d1ea54c045cf632a052557 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 17:03:19 -0700 Subject: [PATCH 0182/5711] staging: comedi: remove this_board macro in the pcl730 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl730.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index e11704addedb..02a4386e1031 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -32,8 +32,6 @@ struct pcl730_board { unsigned int io_range; /* len of I/O space */ }; -#define this_board ((const struct pcl730_board *)dev->board_ptr) - static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { @@ -70,19 +68,20 @@ static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl730_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; unsigned int iorange; iobase = it->options[0]; - iorange = this_board->io_range; + iorange = board->io_range; printk(KERN_INFO "comedi%d: pcl730: board=%s 0x%04lx ", dev->minor, - this_board->name, iobase); + board->name, iobase); if (!request_region(iobase, iorange, "pcl730")) { printk("I/O port conflict\n"); return -EIO; } - dev->board_name = this_board->name; + dev->board_name = board->name; dev->iobase = iobase; dev->irq = 0; @@ -136,8 +135,10 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl730_detach(struct comedi_device *dev) { + const struct pcl730_board *board = comedi_board(dev); + if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } static const struct pcl730_board boardtypes[] = { -- GitLab From d877269ed3c539b4cfcd738b5e705267d95bd5fd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:59:57 -0700 Subject: [PATCH 0183/5711] staging: comedi: remove this_board macro in the pcl726 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl726.c | 39 ++++++++++++++----------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index d25c30c694e3..e9449bb2ba00 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -145,8 +145,6 @@ static const struct pcl726_board boardtypes[] = { &rangelist_728[0],}, }; -#define this_board ((const struct pcl726_board *)dev->board_ptr) - struct pcl726_private { int bipolar[12]; @@ -197,11 +195,13 @@ static int pcl726_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct pcl726_board *board = comedi_board(dev); + if (insn->n != 2) return -EINVAL; - data[1] = inb(dev->iobase + this_board->di_lo) | - (inb(dev->iobase + this_board->di_hi) << 8); + data[1] = inb(dev->iobase + board->di_lo) | + (inb(dev->iobase + board->di_hi) << 8); return 2; } @@ -210,6 +210,8 @@ static int pcl726_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct pcl726_board *board = comedi_board(dev); + if (insn->n != 2) return -EINVAL; @@ -218,9 +220,9 @@ static int pcl726_do_insn_bits(struct comedi_device *dev, s->state |= data[0] & data[1]; } if (data[1] & 0x00ff) - outb(s->state & 0xff, dev->iobase + this_board->do_lo); + outb(s->state & 0xff, dev->iobase + board->do_lo); if (data[1] & 0xff00) - outb((s->state >> 8), dev->iobase + this_board->do_hi); + outb((s->state >> 8), dev->iobase + board->do_hi); data[1] = s->state; @@ -229,6 +231,7 @@ static int pcl726_do_insn_bits(struct comedi_device *dev, static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl726_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; unsigned int iorange; @@ -238,9 +241,9 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif iobase = it->options[0]; - iorange = this_board->io_range; + iorange = board->io_range; printk(KERN_WARNING "comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, - this_board->name, iobase); + board->name, iobase); if (!request_region(iobase, iorange, "pcl726")) { printk(KERN_WARNING "I/O port conflict\n"); return -EIO; @@ -248,7 +251,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; - dev->board_name = this_board->name; + dev->board_name = board->name; ret = alloc_private(dev, sizeof(struct pcl726_private)); if (ret < 0) @@ -297,23 +300,23 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* ao */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = this_board->n_aochan; + s->n_chan = board->n_aochan; s->maxdata = 0xfff; s->len_chanlist = 1; s->insn_write = pcl726_ao_insn; s->insn_read = pcl726_ao_insn_read; s->range_table_list = devpriv->rangelist; - for (i = 0; i < this_board->n_aochan; i++) { + for (i = 0; i < board->n_aochan; i++) { int j; j = it->options[2 + 1]; - if ((j < 0) || (j >= this_board->num_of_ranges)) { + if ((j < 0) || (j >= board->num_of_ranges)) { printk ("Invalid range for channel %d! Must be 0<=%d<%d\n", - i, j, this_board->num_of_ranges - 1); + i, j, board->num_of_ranges - 1); j = 0; } - devpriv->rangelist[i] = this_board->range_type_list[j]; + devpriv->rangelist[i] = board->range_type_list[j]; if (devpriv->rangelist[i]->range[0].min == -devpriv->rangelist[i]->range[0].max) devpriv->bipolar[i] = 1; /* bipolar range */ @@ -321,7 +324,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 1; /* di */ - if (!this_board->have_dio) { + if (!board->have_dio) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_DI; @@ -335,7 +338,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 2; /* do */ - if (!this_board->have_dio) { + if (!board->have_dio) { s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_DO; @@ -352,12 +355,14 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl726_detach(struct comedi_device *dev) { + const struct pcl726_board *board = comedi_board(dev); + #ifdef ACL6126_IRQ if (dev->irq) free_irq(dev->irq, dev); #endif if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } static struct comedi_driver pcl726_driver = { -- GitLab From f21b15be885ca3e14199773c9a9f52c90804fdb9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:55:37 -0700 Subject: [PATCH 0184/5711] staging: comedi: remove this_board macro in the pcl724 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl724.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 1f66fe1c7d5e..4136a03a5125 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -67,8 +67,6 @@ struct pcl724_board { char is_pet48; }; -#define this_board ((const struct pcl724_board *)dev->board_ptr) - static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) { unsigned long iobase = arg; @@ -100,6 +98,7 @@ static int subdev_8255mapped_cb(int dir, int port, int data, static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl724_board *board = comedi_board(dev); unsigned long iobase; unsigned int iorange; int ret, i, n_subdevices; @@ -108,12 +107,12 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif iobase = it->options[0]; - iorange = this_board->io_range; - if ((this_board->can_have96) && ((it->options[1] == 1) + iorange = board->io_range; + if ((board->can_have96) && ((it->options[1] == 1) || (it->options[1] == 96))) iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */ printk(KERN_INFO "comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor, - this_board->name, iobase); + board->name, iobase); if (!request_region(iobase, iorange, "pcl724")) { printk("I/O port conflict\n"); return -EIO; @@ -121,14 +120,14 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; - dev->board_name = this_board->name; + dev->board_name = board->name; #ifdef PCL724_IRQ irq = 0; - if (this_board->IRQbits != 0) { /* board support IRQ */ + if (board->IRQbits != 0) { /* board support IRQ */ irq = it->options[1]; if (irq) { /* we want to use IRQ */ - if (((1 << irq) & this_board->IRQbits) == 0) { + if (((1 << irq) & board->IRQbits) == 0) { printk(KERN_WARNING ", IRQ %u is out of allowed range, " "DISABLING IT", irq); @@ -152,8 +151,8 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk("\n"); - n_subdevices = this_board->numofports; - if ((this_board->can_have96) && ((it->options[1] == 1) + n_subdevices = board->numofports; + if ((board->can_have96) && ((it->options[1] == 1) || (it->options[1] == 96))) n_subdevices = 4; /* PCL-724 in 96 DIO configuration */ @@ -162,7 +161,7 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; for (i = 0; i < dev->n_subdevices; i++) { - if (this_board->is_pet48) { + if (board->is_pet48) { subdev_8255_init(dev, dev->subdevices + i, subdev_8255mapped_cb, (unsigned long)(dev->iobase + @@ -179,6 +178,7 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl724_detach(struct comedi_device *dev) { + const struct pcl724_board *board = comedi_board(dev); int i; for (i = 0; i < dev->n_subdevices; i++) @@ -187,7 +187,7 @@ static void pcl724_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); #endif - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } static const struct pcl724_board boardtypes[] = { -- GitLab From 90d662e3f1b42145f6d1ae9e58a423c859ed284d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:52:00 -0700 Subject: [PATCH 0185/5711] staging: comedi: remove this_board macro in the pcl711 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl711.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 2e7753f988aa..e943b52d04a8 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -148,8 +148,6 @@ struct pcl711_board { const struct comedi_lrange *ai_range_type; }; -#define this_board ((const struct pcl711_board *)dev->board_ptr) - struct pcl711_private { int board; @@ -169,6 +167,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) int lo, hi; int data; struct comedi_device *dev = d; + const struct pcl711_board *board = comedi_board(dev); struct comedi_subdevice *s = dev->subdevices + 0; if (!dev->attached) { @@ -184,7 +183,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) /* FIXME! Nothing else sets ntrig! */ if (!(--devpriv->ntrig)) { - if (this_board->is_8112) + if (board->is_8112) outb(1, dev->iobase + PCL711_MODE); else outb(0, dev->iobase + PCL711_MODE); @@ -197,13 +196,14 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) static void pcl711_set_changain(struct comedi_device *dev, int chan) { + const struct pcl711_board *board = comedi_board(dev); int chan_register; outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN); chan_register = CR_CHAN(chan); - if (this_board->is_8112) { + if (board->is_8112) { /* * Set the correct channel. The two channel banks are switched @@ -225,6 +225,7 @@ static void pcl711_set_changain(struct comedi_device *dev, int chan) static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct pcl711_board *board = comedi_board(dev); int i, n; int hi, lo; @@ -237,7 +238,7 @@ static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, */ outb(1, dev->iobase + PCL711_MODE); - if (!this_board->is_8112) + if (!board->is_8112) outb(0, dev->iobase + PCL711_SOFTTRIG); i = PCL711_TIMEOUT; @@ -481,6 +482,7 @@ static int pcl711_do_insn_bits(struct comedi_device *dev, static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pcl711_board *board = comedi_board(dev); int ret; unsigned long iobase; unsigned int irq; @@ -498,12 +500,11 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* there should be a sanity check here */ - /* set up some name stuff */ - dev->board_name = this_board->name; + dev->board_name = board->name; /* grab our IRQ */ irq = it->options[1]; - if (irq > this_board->maxirq) { + if (irq > board->maxirq) { printk(KERN_ERR "irq out of range\n"); return -EINVAL; } @@ -529,10 +530,10 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* AI subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->maxdata = 0xfff; s->len_chanlist = 1; - s->range_table = this_board->ai_range_type; + s->range_table = board->ai_range_type; s->insn_read = pcl711_ai_insn; if (irq) { dev->read_subdev = s; @@ -545,7 +546,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* AO subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_aochan; + s->n_chan = board->n_aochan; s->maxdata = 0xfff; s->len_chanlist = 1; s->range_table = &range_bipolar5; @@ -577,7 +578,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) this is the "base value" for the mode register, which is used for the irq on the PCL711 */ - if (this_board->is_pcl711b) + if (board->is_pcl711b) devpriv->mode = (dev->irq << 4); /* clear DAC */ -- GitLab From 27b40b89e83aa3db99e392694c46b053ad804bba Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:46:07 -0700 Subject: [PATCH 0186/5711] staging: comedi: remove boardtype macro in the ni_atmio16d driver The 'boardtype' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 4f6145326747..a0890ee202f4 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -110,8 +110,6 @@ struct atmio16_board_t { int has_8255; }; -#define boardtype ((const struct atmio16_board_t *)dev->board_ptr) - /* range structs */ static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { 4, { BIP_RANGE @@ -693,6 +691,7 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev, static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct atmio16_board_t *board = comedi_board(dev); unsigned int irq; unsigned long iobase; int ret; @@ -708,8 +707,7 @@ static int atmio16d_attach(struct comedi_device *dev, } dev->iobase = iobase; - /* board name */ - dev->board_name = boardtype->name; + dev->board_name = board->name; ret = alloc_subdevices(dev, 4); if (ret < 0) @@ -811,7 +809,7 @@ static int atmio16d_attach(struct comedi_device *dev, /* 8255 subdevice */ s++; - if (boardtype->has_8255) + if (board->has_8255) subdev_8255_init(dev, s, NULL, dev->iobase); else s->type = COMEDI_SUBD_UNUSED; @@ -831,7 +829,9 @@ static int atmio16d_attach(struct comedi_device *dev, static void atmio16d_detach(struct comedi_device *dev) { - if (dev->subdevices && boardtype->has_8255) + const struct atmio16_board_t *board = comedi_board(dev); + + if (dev->subdevices && board->has_8255) subdev_8255_cleanup(dev, dev->subdevices + 3); if (dev->irq) free_irq(dev->irq, dev); -- GitLab From 75b9ad9e902a51edc90cfcb4dd84c53683554de2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:41:39 -0700 Subject: [PATCH 0187/5711] staging: comedi: remove thisboard macro in the ni_at_ao driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_at_ao.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index c43dd8ada1da..bfe7fb79880d 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -157,8 +157,6 @@ struct atao_board { int n_ao_chans; }; -#define thisboard ((struct atao_board *)dev->board_ptr) - struct atao_private { unsigned short cfg1; @@ -335,6 +333,7 @@ static int atao_calib_insn_write(struct comedi_device *dev, static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct atao_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; int ao_unipolar; @@ -352,9 +351,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->iobase = iobase; - /* dev->board_ptr = atao_probe(dev); */ - - dev->board_name = thisboard->name; + dev->board_name = board->name; if (alloc_private(dev, sizeof(struct atao_private)) < 0) return -ENOMEM; @@ -366,7 +363,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->n_ao_chans; + s->n_chan = board->n_ao_chans; s->maxdata = (1 << 12) - 1; if (ao_unipolar) s->range_table = &range_unipolar10; -- GitLab From 061319698271bc80155cf3a67f0d5afed4024705 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:33:51 -0700 Subject: [PATCH 0188/5711] staging: comedi: remove this_board macro in the dt282x driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 736d8facaee8..eefda3c064d3 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -221,8 +221,6 @@ struct dt282x_board { int dabits; }; -#define this_board ((const struct dt282x_board *)dev->board_ptr) - struct dt282x_private { int ad_2scomp; /* we have 2's comp jumper set */ int da0_2scomp; /* same, for DAC0 */ @@ -580,6 +578,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, static int dt282x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct dt282x_board *board = comedi_board(dev); int err = 0; int tmp; @@ -658,8 +657,8 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, cmd->convert_arg = SLOWEST_TIMER; err++; } - if (cmd->convert_arg < this_board->ai_speed) { - cmd->convert_arg = this_board->ai_speed; + if (cmd->convert_arg < board->ai_speed) { + cmd->convert_arg = board->ai_speed; err++; } if (cmd->scan_end_arg != cmd->chanlist_len) { @@ -694,6 +693,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct dt282x_board *board = comedi_board(dev); struct comedi_cmd *cmd = &s->async->cmd; int timer; @@ -706,8 +706,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dt282x_disable_dma(dev); - if (cmd->convert_arg < this_board->ai_speed) - cmd->convert_arg = this_board->ai_speed; + if (cmd->convert_arg < board->ai_speed) + cmd->convert_arg = board->ai_speed; timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST); outw(timer, dev->iobase + DT2821_TMRCTR); @@ -1176,12 +1176,13 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) */ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct dt282x_board *board = comedi_board(dev); int i, irq; int ret; struct comedi_subdevice *s; unsigned long iobase; - dev->board_name = this_board->name; + dev->board_name = board->name; iobase = it->options[opt_iobase]; if (!iobase) -- GitLab From 5a011d61ed5ca531470493acf19756fc4e894675 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:28:02 -0700 Subject: [PATCH 0189/5711] staging: comedi: remove this_board macro in the dt2811 driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2811.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 106ffea30b95..727da9e19206 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -211,8 +211,6 @@ struct dt2811_board { const struct comedi_lrange *unip_5; }; -#define this_board ((const struct dt2811_board *)dev->board_ptr) - enum { card_2811_pgh, card_2811_pgl }; struct dt2811_private { @@ -404,6 +402,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* unsigned long irqs; */ /* long flags; */ + const struct dt2811_board *board = comedi_board(dev); int ret; struct comedi_subdevice *s; unsigned long iobase; @@ -418,7 +417,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->iobase = iobase; - dev->board_name = this_board->name; + dev->board_name = board->name; #if 0 outb(0, dev->iobase + DT2811_ADCSR); @@ -527,13 +526,13 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) switch (it->options[3]) { case 0: default: - s->range_table = this_board->bip_5; + s->range_table = board->bip_5; break; case 1: - s->range_table = this_board->bip_2_5; + s->range_table = board->bip_2_5; break; case 2: - s->range_table = this_board->unip_5; + s->range_table = board->unip_5; break; } -- GitLab From df9d33493474a342c866119c28204e0a790de5c0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:23:09 -0700 Subject: [PATCH 0190/5711] staging: comedi: remove thisboard macro in the dmm32at driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 39 ++++++++---------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 83828903db4b..5be99b5d22e4 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -189,11 +189,6 @@ static const struct dmm32at_board dmm32at_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct dmm32at_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If * several hardware drivers keep similar information in this structure, * feel free to suggest moving the variable to the struct comedi_device struct. @@ -290,6 +285,7 @@ void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec); static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct dmm32at_board *board = comedi_board(dev); int ret; struct comedi_subdevice *s; unsigned char aihi, ailo, fifostat, aistat, intstat, airback; @@ -304,7 +300,7 @@ static int dmm32at_attach(struct comedi_device *dev, iobase, irq); /* register address space */ - if (!request_region(iobase, DMM32AT_MEMSIZE, thisboard->name)) { + if (!request_region(iobase, DMM32AT_MEMSIZE, board->name)) { printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n", dev->minor); return -EIO; @@ -358,7 +354,7 @@ static int dmm32at_attach(struct comedi_device *dev, /* board is there, register interrupt */ if (irq) { - ret = request_irq(irq, dmm32at_isr, 0, thisboard->name, dev); + ret = request_irq(irq, dmm32at_isr, 0, board->name, dev); if (ret < 0) { printk(KERN_ERR "dmm32at: irq conflict\n"); return ret; @@ -366,18 +362,7 @@ static int dmm32at_attach(struct comedi_device *dev, dev->irq = irq; } -/* - * If you can probe the device to determine what device in a series - * it is, this is the place to do it. Otherwise, dev->board_ptr - * should already be initialized. - */ - /* dev->board_ptr = dmm32at_probe(dev); */ - -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a @@ -399,9 +384,9 @@ static int dmm32at_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AI; /* we support single-ended (ground) and differential */ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; - s->n_chan = thisboard->ai_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ai_ranges; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; + s->range_table = board->ai_ranges; s->len_chanlist = 32; /* This is the maximum chanlist length that the board can handle */ s->insn_read = dmm32at_ai_rinsn; @@ -413,15 +398,15 @@ static int dmm32at_attach(struct comedi_device *dev, /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ao_ranges; + s->n_chan = board->ao_chans; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_ranges; s->insn_write = dmm32at_ao_winsn; s->insn_read = dmm32at_ao_rinsn; s = dev->subdevices + 2; /* digital i/o subdevice */ - if (thisboard->have_dio) { + if (board->have_dio) { /* get access to the DIO regs */ dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); @@ -433,7 +418,7 @@ static int dmm32at_attach(struct comedi_device *dev, /* set up the subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = thisboard->dio_chans; + s->n_chan = board->dio_chans; s->maxdata = 1; s->state = 0; s->range_table = &range_digital; -- GitLab From 4c354b492eeb257e65886329ba5acfb1fde81dec Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:13:38 -0700 Subject: [PATCH 0191/5711] staging: comedi: remove thisboard macro in the das16m1 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16m1.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index d2e1490cd808..e468ff14aa52 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -150,7 +150,6 @@ struct das16m1_private_struct { unsigned int divisor2; /* divides master clock to obtain conversion speed */ }; #define devpriv ((struct das16m1_private_struct *)(dev->private)) -#define thisboard ((const struct das16m1_board *)(dev->board_ptr)) static inline short munge_sample(short data) { @@ -168,6 +167,7 @@ static void munge_sample_array(short *array, unsigned int num_elements) static int das16m1_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct das16m1_board *board = comedi_board(dev); unsigned int err = 0, tmp, i; /* make sure triggers are valid */ @@ -225,8 +225,8 @@ static int das16m1_cmd_test(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < thisboard->ai_speed) { - cmd->convert_arg = thisboard->ai_speed; + if (cmd->convert_arg < board->ai_speed) { + cmd->convert_arg = board->ai_speed; err++; } } @@ -600,6 +600,7 @@ static int das16m1_irq_bits(unsigned int irq) static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das16m1_board *board = comedi_board(dev); struct comedi_subdevice *s; int ret; unsigned int irq; @@ -611,7 +612,7 @@ static int das16m1_attach(struct comedi_device *dev, if (ret < 0) return ret; - dev->board_name = thisboard->name; + dev->board_name = board->name; if (!request_region(iobase, DAS16M1_SIZE, dev->driver->driver_name)) { comedi_error(dev, "I/O port conflict\n"); -- GitLab From d493f213ab2bfcc41792f904abee75ecfd6afc10 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 16:09:58 -0700 Subject: [PATCH 0192/5711] staging: comedi: remove thisboard macro in the das16 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 106 ++++++++++++++----------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 998444c1ba32..61705366dd40 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -393,11 +393,11 @@ struct das16_private_struct { volatile short timer_mode; /* true if using timer mode */ }; #define devpriv ((struct das16_private_struct *)(dev->private)) -#define thisboard ((struct das16_board *)(dev->board_ptr)) static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct das16_board *board = comedi_board(dev); int err = 0, tmp; int gain, start_chan, i; int mask; @@ -411,7 +411,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, tmp = cmd->scan_begin_src; mask = TRIG_FOLLOW; /* if board supports burst mode */ - if (thisboard->size > 0x400) + if (board->size > 0x400) mask |= TRIG_TIMER | TRIG_EXT; cmd->scan_begin_src &= mask; if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) @@ -420,7 +420,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, tmp = cmd->convert_src; mask = TRIG_TIMER | TRIG_EXT; /* if board supports burst mode */ - if (thisboard->size > 0x400) + if (board->size > 0x400) mask |= TRIG_NOW; cmd->convert_src &= mask; if (!cmd->convert_src || tmp != cmd->convert_src) @@ -483,15 +483,15 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, /* check against maximum frequency */ if (cmd->scan_begin_src == TRIG_TIMER) { if (cmd->scan_begin_arg < - thisboard->ai_speed * cmd->chanlist_len) { + board->ai_speed * cmd->chanlist_len) { cmd->scan_begin_arg = - thisboard->ai_speed * cmd->chanlist_len; + board->ai_speed * cmd->chanlist_len; err++; } } if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < thisboard->ai_speed) { - cmd->convert_arg = thisboard->ai_speed; + if (cmd->convert_arg < board->ai_speed) { + cmd->convert_arg = board->ai_speed; err++; } } @@ -614,6 +614,7 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct das16_board *board = comedi_board(dev); struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int byte; @@ -637,7 +638,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); /* disable conversions for das1600 mode */ - if (thisboard->size > 0x400) + if (board->size > 0x400) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV); /* set scan limits */ @@ -648,9 +649,9 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) /* set gain (this is also burst rate register but according to * computer boards manual, burst rate does nothing, even on * keithley cards) */ - if (thisboard->ai_pg != das16_pg_none) { + if (board->ai_pg != das16_pg_none) { range = CR_RANGE(cmd->chanlist[0]); - outb((das16_gainlists[thisboard->ai_pg])[range], + outb((das16_gainlists[board->ai_pg])[range], dev->iobase + DAS16_GAIN); } @@ -663,7 +664,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) /* enable counters */ byte = 0; /* Enable burst mode if appropriate. */ - if (thisboard->size > 0x400) { + if (board->size > 0x400) { if (cmd->convert_src == TRIG_NOW) { outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST); /* set burst length */ @@ -710,7 +711,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); /* Enable conversions if using das1600 mode */ - if (thisboard->size > 0x400) + if (board->size > 0x400) outb(0, dev->iobase + DAS1600_CONV); @@ -719,6 +720,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct das16_board *board = comedi_board(dev); unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); @@ -735,7 +737,7 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) } /* disable burst mode */ - if (thisboard->size > 0x400) + if (board->size > 0x400) outb(0, dev->iobase + DAS1600_BURST); @@ -755,6 +757,7 @@ static void das16_reset(struct comedi_device *dev) static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct das16_board *board = comedi_board(dev); int i, n; int range; int chan; @@ -770,9 +773,9 @@ static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, outb(chan, dev->iobase + DAS16_MUX); /* set gain */ - if (thisboard->ai_pg != das16_pg_none) { + if (board->ai_pg != das16_pg_none) { range = CR_RANGE(insn->chanspec); - outb((das16_gainlists[thisboard->ai_pg])[range], + outb((das16_gainlists[board->ai_pg])[range], dev->iobase + DAS16_GAIN); } @@ -790,7 +793,7 @@ static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } msb = inb(dev->iobase + DAS16_AI_MSB); lsb = inb(dev->iobase + DAS16_AI_LSB); - if (thisboard->ai_nbits == 12) + if (board->ai_nbits == 12) data[n] = ((lsb >> 4) & 0xf) | (msb << 4); else data[n] = lsb | (msb << 8); @@ -835,6 +838,7 @@ static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct das16_board *board = comedi_board(dev); int i; int lsb, msb; int chan; @@ -842,7 +846,7 @@ static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) { - if (thisboard->ao_nbits == 12) { + if (board->ao_nbits == 12) { lsb = (data[i] << 4) & 0xff; msb = (data[i] >> 4) & 0xff; } else { @@ -892,6 +896,7 @@ static int disable_dma_on_even(struct comedi_device *dev) static void das16_interrupt(struct comedi_device *dev) { + const struct das16_board *board = comedi_board(dev); unsigned long dma_flags, spin_flags; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; @@ -953,7 +958,7 @@ static void das16_interrupt(struct comedi_device *dev) set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); /* reenable conversions for das1600 mode, (stupid hardware) */ - if (thisboard->size > 0x400 && devpriv->timer_mode == 0) + if (board->size > 0x400 && devpriv->timer_mode == 0) outb(0x00, dev->iobase + DAS1600_CONV); } @@ -1015,6 +1020,7 @@ static void reg_dump(struct comedi_device *dev) static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das16_board *board = comedi_board(dev); int status; int diobits; @@ -1039,9 +1045,9 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) diobits = inb(dev->iobase + DAS16_DIO) & 0xf0; printk(KERN_INFO " id bits are 0x%02x\n", diobits); - if (thisboard->id != diobits) { + if (board->id != diobits) { printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n", - thisboard->id); + board->id); } return 0; @@ -1071,12 +1077,13 @@ static void das16_ai_munge(struct comedi_device *dev, unsigned int num_bytes, unsigned int start_chan_index) { + const struct das16_board *board = comedi_board(dev); unsigned int i, num_samples = num_bytes / sizeof(short); short *data = array; for (i = 0; i < num_samples; i++) { data[i] = le16_to_cpu(data[i]); - if (thisboard->ai_nbits == 12) + if (board->ai_nbits == 12) data[i] = (data[i] >> 4) & 0xfff; } @@ -1092,6 +1099,7 @@ static void das16_ai_munge(struct comedi_device *dev, */ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das16_board *board = comedi_board(dev); struct comedi_subdevice *s; int ret; unsigned int irq; @@ -1130,9 +1138,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - if (thisboard->size < 0x400) { - printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size); - if (!request_region(iobase, thisboard->size, "das16")) { + if (board->size < 0x400) { + printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size); + if (!request_region(iobase, board->size, "das16")) { printk(KERN_ERR " I/O port conflict\n"); return -EIO; } @@ -1140,18 +1148,18 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO " 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n", iobase, iobase + 0x0f, iobase + 0x400, - iobase + 0x400 + (thisboard->size & 0x3ff)); + iobase + 0x400 + (board->size & 0x3ff)); if (!request_region(iobase, 0x10, "das16")) { printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n", iobase, iobase + 0x0f); return -EIO; } - if (!request_region(iobase + 0x400, thisboard->size & 0x3ff, + if (!request_region(iobase + 0x400, board->size & 0x3ff, "das16")) { release_region(iobase, 0x10); printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n", iobase + 0x400, - iobase + 0x400 + (thisboard->size & 0x3ff)); + iobase + 0x400 + (board->size & 0x3ff)); return -EIO; } } @@ -1163,10 +1171,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_ERR " id bits do not match selected board, aborting\n"); return -EINVAL; } - dev->board_name = thisboard->name; + dev->board_name = board->name; /* get master clock speed */ - if (thisboard->size < 0x400) { + if (board->size < 0x400) { if (it->options[3]) devpriv->clockbase = 1000 / it->options[3]; else @@ -1222,7 +1230,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* get any user-defined input range */ - if (thisboard->ai_pg == das16_pg_none && + if (board->ai_pg == das16_pg_none && (it->options[4] || it->options[5])) { /* allocate single-range range table */ devpriv->user_ai_range_table = @@ -1263,7 +1271,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 0; dev->read_subdev = s; /* ai */ - if (thisboard->ai) { + if (board->ai) { s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_CMD_READ; if (devpriv->ai_singleended) { @@ -1275,15 +1283,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 8; s->subdev_flags |= SDF_DIFF; } - s->maxdata = (1 << thisboard->ai_nbits) - 1; + s->maxdata = (1 << board->ai_nbits) - 1; if (devpriv->user_ai_range_table) { /* user defined ai range */ s->range_table = devpriv->user_ai_range_table; } else if (devpriv->ai_unipolar) { - s->range_table = das16_ai_uni_lranges[thisboard->ai_pg]; + s->range_table = das16_ai_uni_lranges[board->ai_pg]; } else { - s->range_table = das16_ai_bip_lranges[thisboard->ai_pg]; + s->range_table = das16_ai_bip_lranges[board->ai_pg]; } - s->insn_read = thisboard->ai; + s->insn_read = board->ai; s->do_cmdtest = das16_cmd_test; s->do_cmd = das16_cmd_exec; s->cancel = das16_cancel; @@ -1294,44 +1302,44 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 1; /* ao */ - if (thisboard->ao) { + if (board->ao) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; - s->maxdata = (1 << thisboard->ao_nbits) - 1; + s->maxdata = (1 << board->ao_nbits) - 1; /* user defined ao range */ if (devpriv->user_ao_range_table) s->range_table = devpriv->user_ao_range_table; else s->range_table = &range_unknown; - s->insn_write = thisboard->ao; + s->insn_write = board->ao; } else { s->type = COMEDI_SUBD_UNUSED; } s = dev->subdevices + 2; /* di */ - if (thisboard->di) { + if (board->di) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = thisboard->di; + s->insn_bits = board->di; } else { s->type = COMEDI_SUBD_UNUSED; } s = dev->subdevices + 3; /* do */ - if (thisboard->do_) { + if (board->do_) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = thisboard->do_; + s->insn_bits = board->do_; /* initialize digital output lines */ outb(s->state, dev->iobase + DAS16_DIO); } else { @@ -1340,9 +1348,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 4; /* 8255 */ - if (thisboard->i8255_offset != 0) { + if (board->i8255_offset != 0) { subdev_8255_init(dev, s, NULL, (dev->iobase + - thisboard->i8255_offset)); + board->i8255_offset)); } else { s->type = COMEDI_SUBD_UNUSED; } @@ -1353,7 +1361,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); /* turn on das1600 mode if available */ - if (thisboard->size > 0x400) { + if (board->size > 0x400) { outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); outb(0, dev->iobase + DAS1600_CONV); outb(0, dev->iobase + DAS1600_BURST); @@ -1364,6 +1372,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void das16_detach(struct comedi_device *dev) { + const struct das16_board *board = comedi_board(dev); + das16_reset(dev); if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 4); @@ -1384,12 +1394,12 @@ static void das16_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (dev->iobase) { - if (thisboard->size < 0x400) { - release_region(dev->iobase, thisboard->size); + if (board->size < 0x400) { + release_region(dev->iobase, board->size); } else { release_region(dev->iobase, 0x10); release_region(dev->iobase + 0x400, - thisboard->size & 0x3ff); + board->size & 0x3ff); } } } -- GitLab From bf4683bdbdfafc02f5f4d3170efcd25ff9f00c6b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 15:58:28 -0700 Subject: [PATCH 0193/5711] staging: comedi: remove thisboard macro in the comedi_test driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/comedi_test.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 873e37450bba..9f3c3d5d02a4 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -67,8 +67,6 @@ struct waveform_board { #define N_CHANS 8 -#define thisboard ((const struct waveform_board *)dev->board_ptr) - /* Data unique to this driver */ struct waveform_private { struct timer_list timer; @@ -429,12 +427,13 @@ static int waveform_ao_insn_write(struct comedi_device *dev, static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct waveform_board *board = comedi_board(dev); struct comedi_subdevice *s; int amplitude = it->options[0]; int period = it->options[1]; int i; - dev->board_name = thisboard->name; + dev->board_name = board->name; if (alloc_private(dev, sizeof(struct waveform_private)) < 0) return -ENOMEM; @@ -457,8 +456,8 @@ static int waveform_attach(struct comedi_device *dev, /* analog input subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - s->n_chan = thisboard->ai_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; s->range_table = &waveform_ai_ranges; s->len_chanlist = s->n_chan * 2; s->insn_read = waveform_ai_insn_read; @@ -471,8 +470,8 @@ static int waveform_attach(struct comedi_device *dev, /* analog output subdevice (loopback) */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND; - s->n_chan = thisboard->ai_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; s->range_table = &waveform_ai_ranges; s->len_chanlist = s->n_chan * 2; s->insn_write = waveform_ao_insn_write; -- GitLab From b74055465ce47c75b3ebf667c2ff0661828d7a11 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 15:51:14 -0700 Subject: [PATCH 0194/5711] staging: comedi: remove thisboard macro in the aio_iiro_16 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/aio_iiro_16.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 04f6f94b1f47..5c1548b385f4 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -57,8 +57,6 @@ static const struct aio_iiro_16_board aio_iiro_16_boards[] = { .do_ = 16}, }; -#define thisboard ((const struct aio_iiro_16_board *) dev->board_ptr) - struct aio_iiro_16_private { int data; struct pci_dev *pci_dev; @@ -106,12 +104,13 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct aio_iiro_16_board *board = comedi_board(dev); int iobase; struct comedi_subdevice *s; printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor); - dev->board_name = thisboard->name; + dev->board_name = board->name; iobase = it->options[0]; -- GitLab From 797ef32ba35589393f993bb2f18698d4bc3ad07d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 15:46:02 -0700 Subject: [PATCH 0195/5711] staging: comedi: remove this_board macro in the aio_aio12_8 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/aio_aio12_8.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 64d82bc4ffe4..d215ae16668b 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -80,8 +80,6 @@ static const struct aio12_8_boardtype board_types[] = { .name = "aio_aio12_8"}, }; -#define thisboard ((const struct aio12_8_boardtype *) dev->board_ptr) - struct aio12_8_private { unsigned int ao_readback[4]; }; @@ -167,6 +165,7 @@ static const struct comedi_lrange range_aio_aio12_8 = { static int aio_aio12_8_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct aio12_8_boardtype *board = comedi_board(dev); int iobase; struct comedi_subdevice *s; @@ -176,7 +175,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev, return -EIO; } - dev->board_name = thisboard->name; + dev->board_name = board->name; dev->iobase = iobase; -- GitLab From b13ff04654b406618f96e59168006c530f4774aa Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 15:41:29 -0700 Subject: [PATCH 0196/5711] staging: comedi: remove thisboard macro in the adq12b driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adq12b.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 7d585a12050f..1da298967413 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -125,8 +125,6 @@ struct adq12b_board { int do_chans; }; -#define thisboard ((const struct adq12b_board *)dev->board_ptr) - struct adq12b_private { int unipolar; /* option 2 of comedi_config (1 is iobase) */ int differential; /* option 3 of comedi_config */ @@ -222,6 +220,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct adq12b_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; int unipolar, differential; @@ -250,11 +249,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->iobase = iobase; -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a @@ -284,10 +279,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_AI; if (differential) { s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = thisboard->ai_diff_chans; + s->n_chan = board->ai_diff_chans; } else { s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = thisboard->ai_se_chans; + s->n_chan = board->ai_se_chans; } if (unipolar) @@ -295,7 +290,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) else s->range_table = &range_adq12b_ai_bipolar; - s->maxdata = (1 << thisboard->ai_bits) - 1; + s->maxdata = (1 << board->ai_bits) - 1; s->len_chanlist = 4; /* This is the maximum chanlist length that the board can handle */ @@ -305,7 +300,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital input subdevice */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = thisboard->di_chans; + s->n_chan = board->di_chans; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = adq12b_di_insn_bits; @@ -314,7 +309,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital output subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->do_chans; + s->n_chan = board->do_chans; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = adq12b_do_insn_bits; -- GitLab From 960ca1ae1e0676dfef699c37362dad1d4fee5397 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 15:31:41 -0700 Subject: [PATCH 0197/5711] staging: comedi: remove this_board macro in the acl7225b driver The 'this_board' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/acl7225b.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index 4e4fc418655f..c1963add660d 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -27,8 +27,6 @@ struct boardtype { int io_range; /* len of I/O space */ }; -#define this_board ((const struct boardtype *)dev->board_ptr) - static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -67,19 +65,20 @@ static int acl7225b_di_insn(struct comedi_device *dev, static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct boardtype *board = comedi_board(dev); struct comedi_subdevice *s; int iobase, iorange; iobase = it->options[0]; - iorange = this_board->io_range; + iorange = board->io_range; printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor, - this_board->name, iobase); + board->name, iobase); if (!request_region(iobase, iorange, "acl7225b")) { printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n", dev->minor); return -EIO; } - dev->board_name = this_board->name; + dev->board_name = board->name; dev->iobase = iobase; dev->irq = 0; @@ -121,8 +120,10 @@ static int acl7225b_attach(struct comedi_device *dev, static void acl7225b_detach(struct comedi_device *dev) { + const struct boardtype *board = comedi_board(dev); + if (dev->iobase) - release_region(dev->iobase, this_board->io_range); + release_region(dev->iobase, board->io_range); } static const struct boardtype boardtypes[] = { -- GitLab From 5254cbe795c3bb9ef28d61a474d707385fc87178 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 May 2012 18:20:10 -0700 Subject: [PATCH 0198/5711] staging: comedi: remove this_board macro in the s526 driver The 'thisboard' macro depends on having a local variable with a magic name. The CodingStyle document suggests not doing this to avoid confusion. Remove the macro and use the comedi_board() inline helper to get the dev->board_ptr information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s526.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 7a56434eb224..3c8e9799824e 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -200,11 +200,6 @@ static const struct s526_board s526_boards[] = { #define ADDR_REG(reg) (dev->iobase + (reg)) #define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8) -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct s526_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device @@ -744,6 +739,7 @@ static int s526_dio_insn_config(struct comedi_device *dev, static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct s526_board *board = comedi_board(dev); struct comedi_subdevice *s; int iobase; int i, n; @@ -754,7 +750,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "comedi%d: s526: ", dev->minor); iobase = it->options[0]; - if (!iobase || !request_region(iobase, S526_IOSIZE, thisboard->name)) { + if (!iobase || !request_region(iobase, S526_IOSIZE, board->name)) { comedi_error(dev, "I/O port conflict"); return -EIO; } @@ -769,13 +765,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) } ***/ -/* - * Initialize dev->board_name. Note that we can use the "thisboard" - * macro now, since we just initialized it in the last line. - */ - dev->board_ptr = &s526_boards[0]; - - dev->board_name = thisboard->name; + dev->board_name = board->name; /* * Allocate the private structure area. alloc_private() is a @@ -797,7 +787,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */ - s->n_chan = thisboard->gpct_chans; + s->n_chan = board->gpct_chans; s->maxdata = 0x00ffffff; /* 24 bit counter */ s->insn_read = s526_gpct_rinsn; s->insn_config = s526_gpct_insn_config; @@ -838,7 +828,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = dev->subdevices + 3; /* digital i/o subdevice */ - if (thisboard->have_dio) { + if (board->have_dio) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; -- GitLab From 1c9de58acc06cba56b5f1bd17a5a74a66427f8b1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 26 May 2012 15:14:45 +0300 Subject: [PATCH 0199/5711] staging: comedi: cleanup comedi_recognize() This function is more complicated than it needs to be because of the consts. It's not worth saving them when we drop the consts anyway when we return (void *)name_ptr. Signed-off-by: Dan Carpenter Cc: Ian Abbott Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 7289dcb5c32c..438c52a313b1 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -304,14 +304,13 @@ static int postconfig(struct comedi_device *dev) * that register their supported board names */ static void *comedi_recognize(struct comedi_driver *driv, const char *name) { - unsigned i; - const char *const *name_ptr = driv->board_name; + char **name_ptr = (char **)driv->board_name; + int i; + for (i = 0; i < driv->num_names; i++) { if (strcmp(*name_ptr, name) == 0) - return (void *)name_ptr; - name_ptr = - (const char *const *)((const char *)name_ptr + - driv->offset); + return name_ptr; + name_ptr = (void *)name_ptr + driv->offset; } return NULL; -- GitLab From 8d0300a1d983a10cd3358f47b4317eca62c9b96b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 14:14:13 -0700 Subject: [PATCH 0200/5711] staging: comedi: adl_pci7230: factor out the find PCI device code Factor out the code that finds a matching PCI device from attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci7230.c | 53 +++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index e7eb2290106a..2c8349273d7f 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -80,18 +80,38 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev, return 2; } -static int adl_pci7230_attach(struct comedi_device *dev, +static struct pci_dev *adl_pci7230_find_pci(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7230) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + +static int adl_pci7230_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ struct comedi_subdevice *s; - int bus, slot; printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor); dev->board_name = "pci7230"; - bus = it->options[0]; - slot = it->options[1]; if (alloc_private(dev, sizeof(struct adl_pci7230_private)) < 0) return -ENOMEM; @@ -99,31 +119,16 @@ static int adl_pci7230_attach(struct comedi_device *dev, if (alloc_subdevices(dev, 2) < 0) return -ENOMEM; - for_each_pci_dev(pcidev) { - if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && - pcidev->device == PCI_DEVICE_ID_PCI7230) { - if (bus || slot) { - /* requested particular bus/slot */ - if (pcidev->bus->number != bus || - PCI_SLOT(pcidev->devfn) != slot) { - continue; - } - } - devpriv->pci_dev = pcidev; - break; - } - } - if (pcidev == NULL) { - printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); + devpriv->pci_dev = adl_pci7230_find_pci(dev, it); + if (!devpriv->pci_dev) return -EIO; - } - if (comedi_pci_enable(pcidev, "adl_pci7230") < 0) { + + if (comedi_pci_enable(devpriv->pci_dev, "adl_pci7230") < 0) { printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", dev->minor); return -EIO; } - dev->iobase = pci_resource_start(pcidev, 2); + dev->iobase = pci_resource_start(devpriv->pci_dev, 2); printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase); s = dev->subdevices + 0; -- GitLab From 93b6e4790ecd3025a1a38d3758ee1ac0b264799c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 16:34:58 -0700 Subject: [PATCH 0201/5711] staging: comedi: adl_pci9118: factor out the find PCI device code Factor out the code that finds a matching PCI device from attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9118.c | 99 +++++++++----------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index aa4244e5f918..f2135bfca290 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2110,6 +2110,44 @@ static int pci9118_reset(struct comedi_device *dev) return 0; } +static struct pci_dev *pci9118_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_AMCC) + continue; + if (pcidev->device != this_board->device_id) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + /* + * Look for device that isn't in use. + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, "adl_pci9118")) + continue; + printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", + pcidev->bus->number, + PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), + (unsigned long)pci_resource_start(pcidev, 2), + (unsigned long)pci_resource_start(pcidev, 0)); + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it) { @@ -2117,17 +2155,10 @@ static int pci9118_attach(struct comedi_device *dev, int ret, pages, i; unsigned short master; unsigned int irq; - unsigned long iobase_a, iobase_9; - struct pci_dev *pcidev; - int opt_bus, opt_slot; - const char *errstr; - unsigned char pci_bus, pci_slot, pci_func; u16 u16w; printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name); - opt_bus = it->options[0]; - opt_slot = it->options[1]; if (it->options[3] & 1) master = 0; /* user don't want use bus master */ else @@ -2139,61 +2170,19 @@ static int pci9118_attach(struct comedi_device *dev, return -ENOMEM; } - /* Look for matching PCI device */ - errstr = "not found!"; - pcidev = NULL; - while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC, - this_board->device_id, - pcidev))) { - /* Found matching vendor/device. */ - if (opt_bus || opt_slot) { - /* Check bus/slot. */ - if (opt_bus != pcidev->bus->number - || opt_slot != PCI_SLOT(pcidev->devfn)) - continue; /* no match */ - } - /* - * Look for device that isn't in use. - * Enable PCI device and request regions. - */ - if (comedi_pci_enable(pcidev, "adl_pci9118")) { - errstr = - "failed to enable PCI device and request regions!"; - continue; - } - break; - } - - if (!pcidev) { - if (opt_bus || opt_slot) { - printk(KERN_ERR " - Card at b:s %d:%d %s\n", - opt_bus, opt_slot, errstr); - } else { - printk(KERN_ERR " - Card %s\n", errstr); - } + devpriv->pcidev = pci9118_find_pci(dev, it); + if (!devpriv->pcidev) return -EIO; - } if (master) - pci_set_master(pcidev); + pci_set_master(devpriv->pcidev); + irq = devpriv->pcidev->irq; + devpriv->iobase_a = pci_resource_start(devpriv->pcidev, 0); + dev->iobase = pci_resource_start(devpriv->pcidev, 2); - pci_bus = pcidev->bus->number; - pci_slot = PCI_SLOT(pcidev->devfn); - pci_func = PCI_FUNC(pcidev->devfn); - irq = pcidev->irq; - iobase_a = pci_resource_start(pcidev, 0); - iobase_9 = pci_resource_start(pcidev, 2); - - printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus, - pci_slot, pci_func, iobase_9, iobase_a); - - dev->iobase = iobase_9; dev->board_name = this_board->name; - devpriv->pcidev = pcidev; - devpriv->iobase_a = iobase_a; - pci9118_reset(dev); if (it->options[3] & 2) -- GitLab From 1158244e013eeac80ad418ab8042cfc4462ee278 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 16:06:39 -0700 Subject: [PATCH 0202/5711] staging: comedi: adl_pci9111: factor out the find PCI device code Factor out the code that finds a matching PCI device from attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9111.c | 107 +++++++++---------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 308cca76cb82..410bbf9f5a95 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1209,17 +1209,47 @@ static int pci9111_reset(struct comedi_device *dev) return 0; } -/* Attach */ -/* - Register PCI device */ -/* - Declare device driver capability */ +static struct pci_dev *pci9111_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK) + continue; + for (i = 0; i < pci9111_board_nbr; i++) { + if (pcidev->device != pci9111_boards[i].device_id) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + dev->board_ptr = pci9111_boards + i; + printk(KERN_ERR + "comedi%d: found %s (b:s:f=%d:%d:%d), irq=%d\n", + dev->minor, pci9111_boards[i].name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), pcidev->irq); + return pcidev; + } + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} static int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *subdevice; unsigned long io_base, io_range, lcr_io_base, lcr_io_range; - struct pci_dev *pci_device = NULL; - int error, i; + int error; const struct pci9111_board *board; if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) @@ -1229,65 +1259,25 @@ static int pci9111_attach(struct comedi_device *dev, printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor); - for_each_pci_dev(pci_device) { - if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) { - for (i = 0; i < pci9111_board_nbr; i++) { - if (pci9111_boards[i].device_id == - pci_device->device) { - /* was a particular bus/slot - * requested? */ - if ((it->options[0] != 0) - || (it->options[1] != 0)) { - /* are we on the wrong - * bus/slot? */ - if (pci_device->bus->number != - it->options[0] - || - PCI_SLOT(pci_device->devfn) - != it->options[1]) { - continue; - } - } - - dev->board_ptr = pci9111_boards + i; - board = - (struct pci9111_board *) - dev->board_ptr; - dev_private->pci_device = pci_device; - goto found; - } - } - } - } - - printk(KERN_ERR - "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, it->options[0], it->options[1]); - return -EIO; - -found: - - printk(KERN_ERR "comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n", - dev->minor, - pci9111_boards[i].name, - pci_device->bus->number, - PCI_SLOT(pci_device->devfn), - PCI_FUNC(pci_device->devfn), pci_device->irq); + dev_private->pci_device = pci9111_find_pci(dev, it); + if (!dev_private->pci_device) + return -EIO; + board = (struct pci9111_board *)dev->board_ptr; /* TODO: Warn about non-tested boards. */ /* Read local configuration register base address * [PCI_BASE_ADDRESS #1]. */ - lcr_io_base = pci_resource_start(pci_device, 1); - lcr_io_range = pci_resource_len(pci_device, 1); + lcr_io_base = pci_resource_start(dev_private->pci_device, 1); + lcr_io_range = pci_resource_len(dev_private->pci_device, 1); printk ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", dev->minor, lcr_io_base, lcr_io_range); /* Enable PCI device and request regions */ - if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) { + if (comedi_pci_enable(dev_private->pci_device, PCI9111_DRIVER_NAME) < 0) { printk ("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); @@ -1295,8 +1285,8 @@ found: } /* Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */ - io_base = pci_resource_start(pci_device, 2); - io_range = pci_resource_len(pci_device, 2); + io_base = pci_resource_start(dev_private->pci_device, 2); + io_range = pci_resource_len(dev_private->pci_device, 2); printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n", dev->minor, io_base, io_range); @@ -1313,16 +1303,17 @@ found: /* Irq setup */ dev->irq = 0; - if (pci_device->irq > 0) { - if (request_irq(pci_device->irq, pci9111_interrupt, + if (dev_private->pci_device->irq > 0) { + dev->irq = dev_private->pci_device->irq; + + if (request_irq(dev->irq, pci9111_interrupt, IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) { printk(KERN_ERR "comedi%d: unable to allocate irq %u\n", - dev->minor, pci_device->irq); + dev->minor, dev->irq); return -EINVAL; } } - dev->irq = pci_device->irq; /* TODO: Add external multiplexer setup (according to option[2]). */ -- GitLab From d3ff7b93ee8b619f777a73f34812e66de07ecd93 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 15:44:10 -0700 Subject: [PATCH 0203/5711] staging: comedi: adl_pci8164: factor out the PCI device code Factor out the code that finds a matching PCI device from attach function. This allows reducing the indent level of the remaining code in the attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci8164.c | 149 ++++++++++--------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index fbc859e6c201..344754877892 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -223,19 +223,40 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev, return 2; } +static struct pci_dev *adl_pci8164_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI8164) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct pci_dev *pcidev = NULL; struct comedi_subdevice *s; - int bus, slot; printk(KERN_INFO "comedi: attempt to attach...\n"); printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor); dev->board_name = "pci8164"; - bus = it->options[0]; - slot = it->options[1]; if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0) return -ENOMEM; @@ -243,74 +264,60 @@ static int adl_pci8164_attach(struct comedi_device *dev, if (alloc_subdevices(dev, 4) < 0) return -ENOMEM; - for_each_pci_dev(pcidev) { - if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && - pcidev->device == PCI_DEVICE_ID_PCI8164) { - if (bus || slot) { - /* requested particular bus/slot */ - if (pcidev->bus->number != bus - || PCI_SLOT(pcidev->devfn) != slot) - continue; - } - devpriv->pci_dev = pcidev; - if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) { - printk(KERN_ERR "comedi%d: Failed to enable " - "PCI device and request regions\n", dev->minor); - return -EIO; - } - dev->iobase = pci_resource_start(pcidev, 2); - printk(KERN_DEBUG "comedi: base addr %4lx\n", - dev->iobase); - - s = dev->subdevices + 0; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_msts; - s->insn_write = adl_pci8164_insn_write_cmd; - - s = dev->subdevices + 1; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_ssts; - s->insn_write = adl_pci8164_insn_write_otp; - - s = dev->subdevices + 2; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_buf0; - s->insn_write = adl_pci8164_insn_write_buf0; - - s = dev->subdevices + 3; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_buf1; - s->insn_write = adl_pci8164_insn_write_buf1; - - printk(KERN_INFO "comedi: attached\n"); - - return 1; - } - } + devpriv->pci_dev = adl_pci8164_find_pci(dev, it); + if (!devpriv->pci_dev) + return -EIO; - printk(KERN_ERR "comedi%d: no supported board found!" - "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot); - return -EIO; + if (comedi_pci_enable(devpriv->pci_dev, "adl_pci8164") < 0) { + printk(KERN_ERR "comedi%d: Failed to enable " + "PCI device and request regions\n", dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(devpriv->pci_dev, 2); + printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + /* s->range_table = &range_axis; */ + s->insn_read = adl_pci8164_insn_read_msts; + s->insn_write = adl_pci8164_insn_write_cmd; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + /* s->range_table = &range_axis; */ + s->insn_read = adl_pci8164_insn_read_ssts; + s->insn_write = adl_pci8164_insn_write_otp; + + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + /* s->range_table = &range_axis; */ + s->insn_read = adl_pci8164_insn_read_buf0; + s->insn_write = adl_pci8164_insn_write_buf0; + + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + /* s->range_table = &range_axis; */ + s->insn_read = adl_pci8164_insn_read_buf1; + s->insn_write = adl_pci8164_insn_write_buf1; + + printk(KERN_INFO "comedi: attached\n"); + return 0; } static void adl_pci8164_detach(struct comedi_device *dev) -- GitLab From fc330f458941df0f1651964e8e1207e62fb6db51 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 14:38:33 -0700 Subject: [PATCH 0204/5711] staging: comedi: adl_pci7432: factor out the PCI device code Factor out the code that finds a matching PCI device from attach function. This allows reducing the indent level of the remaining code in the attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci7432.c | 112 ++++++++++--------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index 2fc1dbbd81e4..dd818f1b75ae 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -88,18 +88,39 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, return 2; } +static struct pci_dev *adl_pci7432_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7432) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct pci_dev *pcidev = NULL; struct comedi_subdevice *s; - int bus, slot; printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); dev->board_name = "pci7432"; - bus = it->options[0]; - slot = it->options[1]; if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0) return -ENOMEM; @@ -107,57 +128,40 @@ static int adl_pci7432_attach(struct comedi_device *dev, if (alloc_subdevices(dev, 2) < 0) return -ENOMEM; - for_each_pci_dev(pcidev) { - if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && - pcidev->device == PCI_DEVICE_ID_PCI7432) { - if (bus || slot) { - /* requested particular bus/slot */ - if (pcidev->bus->number != bus - || PCI_SLOT(pcidev->devfn) != slot) { - continue; - } - } - devpriv->pci_dev = pcidev; - if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) { - printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", - dev->minor); - return -EIO; - } - dev->iobase = pci_resource_start(pcidev, 2); - printk(KERN_INFO "comedi: base addr %4lx\n", - dev->iobase); - - s = dev->subdevices + 0; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = - SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 32; - s->maxdata = 1; - s->len_chanlist = 32; - s->io_bits = 0x00000000; - s->range_table = &range_digital; - s->insn_bits = adl_pci7432_di_insn_bits; - - s = dev->subdevices + 1; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = - SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 32; - s->maxdata = 1; - s->len_chanlist = 32; - s->io_bits = 0xffffffff; - s->range_table = &range_digital; - s->insn_bits = adl_pci7432_do_insn_bits; - - printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", - dev->minor); - return 1; - } - } + devpriv->pci_dev = adl_pci7432_find_pci(dev, it); + if (!devpriv->pci_dev) + return -EIO; - printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); - return -EIO; + if (comedi_pci_enable(devpriv->pci_dev, "adl_pci7432") < 0) { + printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(devpriv->pci_dev, 2); + printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0x00000000; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0xffffffff; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_do_insn_bits; + + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor); + return 0; } static void adl_pci7432_detach(struct comedi_device *dev) -- GitLab From 262ea0d476049fa393509a70c9ecfa06df403b4a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 14:28:47 -0700 Subject: [PATCH 0205/5711] staging: comedi: adl_pci7296: factor out the PCI device code Factor out the code that finds a matching PCI device from attach function. This allows reducing the indent level of the remaining code in the attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci7296.c | 121 ++++++++++--------- 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index bf2f7fb86d77..0b8b27983122 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -54,19 +54,40 @@ struct adl_pci7296_private { #define devpriv ((struct adl_pci7296_private *)dev->private) +static struct pci_dev *adl_pci7296_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7296) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + static int adl_pci7296_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct pci_dev *pcidev = NULL; struct comedi_subdevice *s; - int bus, slot; int ret; printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); dev->board_name = "pci7432"; - bus = it->options[0]; - slot = it->options[1]; if (alloc_private(dev, sizeof(struct adl_pci7296_private)) < 0) return -ENOMEM; @@ -74,63 +95,45 @@ static int adl_pci7296_attach(struct comedi_device *dev, if (alloc_subdevices(dev, 4) < 0) return -ENOMEM; - for_each_pci_dev(pcidev) { - if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && - pcidev->device == PCI_DEVICE_ID_PCI7296) { - if (bus || slot) { - /* requested particular bus/slot */ - if (pcidev->bus->number != bus - || PCI_SLOT(pcidev->devfn) != slot) { - continue; - } - } - devpriv->pci_dev = pcidev; - if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) { - printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", - dev->minor); - return -EIO; - } - - dev->iobase = pci_resource_start(pcidev, 2); - printk(KERN_INFO "comedi: base addr %4lx\n", - dev->iobase); - - /* four 8255 digital io subdevices */ - s = dev->subdevices + 0; - subdev_8255_init(dev, s, NULL, - (unsigned long)(dev->iobase)); - - s = dev->subdevices + 1; - ret = subdev_8255_init(dev, s, NULL, - (unsigned long)(dev->iobase + - PORT2A)); - if (ret < 0) - return ret; - - s = dev->subdevices + 2; - ret = subdev_8255_init(dev, s, NULL, - (unsigned long)(dev->iobase + - PORT3A)); - if (ret < 0) - return ret; - - s = dev->subdevices + 3; - ret = subdev_8255_init(dev, s, NULL, - (unsigned long)(dev->iobase + - PORT4A)); - if (ret < 0) - return ret; - - printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", - dev->minor); - - return 1; - } + devpriv->pci_dev = adl_pci7296_find_pci(dev, it); + if (!devpriv->pci_dev) + return -EIO; + + if (comedi_pci_enable(devpriv->pci_dev, "adl_pci7296") < 0) { + printk(KERN_ERR + "comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; } - printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); - return -EIO; + dev->iobase = pci_resource_start(devpriv->pci_dev, 2); + printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase); + + /* four 8255 digital io subdevices */ + s = dev->subdevices + 0; + subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase)); + + s = dev->subdevices + 1; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT2A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 2; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT3A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 3; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT4A)); + if (ret < 0) + return ret; + + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor); + + return 0; } static void adl_pci7296_detach(struct comedi_device *dev) -- GitLab From c98d90fd1fb9a5ff612e05766198cb09a1dd63b7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 18:31:48 -0700 Subject: [PATCH 0206/5711] staging: comedi: rtd520 complete the refactor to remove all forward declarations Complete the refactor of the rtd520 driver to remove all the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rtd520.c | 2704 +++++++++++------------ 1 file changed, 1337 insertions(+), 1367 deletions(-) diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index d3e2786f07cb..84b28b6b99d6 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -702,1616 +702,1586 @@ struct rtdPrivate { #define RtdDma1Status(dev) \ readb(devpriv->lcfg+LCFG_DMACSR1) -static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int rtd_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int rtd_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); /* - * static int rtd_ai_poll(struct comedi_device *dev, - * struct comedi_subdevice *s); - */ -static int rtd_ns_to_timer(unsigned int *ns, int roundMode); -static irqreturn_t rtd_interrupt(int irq, void *d); -static int rtd520_probe_fifo_depth(struct comedi_device *dev); + Given a desired period and the clock period (both in ns), + return the proper counter value (divider-1). + Sets the original period to be the true value. + Note: you have to check if the value is larger than the counter range! +*/ +static int rtd_ns_to_timer_base(unsigned int *nanosec, /* desired period (in ns) */ + int round_mode, int base) +{ /* clock period (in ns) */ + int divider; + + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + divider = (*nanosec + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*nanosec) / base; + break; + case TRIG_ROUND_UP: + divider = (*nanosec + base - 1) / base; + break; + } + if (divider < 2) + divider = 2; /* min is divide by 2 */ + + /* Note: we don't check for max, because different timers + have different ranges */ + + *nanosec = base * divider; + return divider - 1; /* countdown is divisor+1 */ +} /* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ /* board name and options flags */ - struct comedi_subdevice *s; - struct pci_dev *pcidev; - int ret; - resource_size_t physLas0; /* configuration */ - resource_size_t physLas1; /* data area */ - resource_size_t physLcfg; /* PLX9080 */ -#ifdef USE_DMA - int index; -#endif + Given a desired period (in ns), + return the proper counter value (divider-1) for the internal clock. + Sets the original period to be the true value. +*/ +static int rtd_ns_to_timer(unsigned int *ns, int round_mode) +{ + return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE); +} - printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor); +/* + Convert a single comedi channel-gain entry to a RTD520 table entry +*/ +static unsigned short rtdConvertChanGain(struct comedi_device *dev, + unsigned int comediChan, int chanIndex) +{ /* index in channel list */ + unsigned int chan, range, aref; + unsigned short r = 0; -#if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA) - /* You can set this a load time: modprobe comedi comedi_debug=1 */ - if (0 == comedi_debug) /* force DMA debug printks */ - comedi_debug = 1; -#endif + chan = CR_CHAN(comediChan); + range = CR_RANGE(comediChan); + aref = CR_AREF(comediChan); - /* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ - if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0) - return -ENOMEM; + r |= chan & 0xf; - /* - * Probe the device to determine what device in the series it is. - */ - for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL); - pcidev != NULL; - pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) { - int i; + /* Note: we also setup the channel list bipolar flag array */ + if (range < thisboard->range10Start) { /* first batch are +-5 */ + r |= 0x000; /* +-5 range */ + r |= (range & 0x7) << 4; /* gain */ + CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); + } else if (range < thisboard->rangeUniStart) { /* second batch are +-10 */ + r |= 0x100; /* +-10 range */ + /* gain */ + r |= ((range - thisboard->range10Start) & 0x7) << 4; + CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); + } else { /* last batch is +10 */ + r |= 0x200; /* +10 range */ + /* gain */ + r |= ((range - thisboard->rangeUniStart) & 0x7) << 4; + CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex); + } - if (it->options[0] || it->options[1]) { - if (pcidev->bus->number != it->options[0] - || PCI_SLOT(pcidev->devfn) != it->options[1]) { - continue; - } - } - for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i) { - if (pcidev->device == rtd520Boards[i].device_id) { - dev->board_ptr = &rtd520Boards[i]; - break; - } + switch (aref) { + case AREF_GROUND: /* on-board ground */ + break; + + case AREF_COMMON: + r |= 0x80; /* ref external analog common */ + break; + + case AREF_DIFF: + r |= 0x400; /* differential inputs */ + break; + + case AREF_OTHER: /* ??? */ + break; + } + /*printk ("chan=%d r=%d a=%d -> 0x%x\n", + chan, range, aref, r); */ + return r; +} + +/* + Setup the channel-gain table from a comedi list +*/ +static void rtd_load_channelgain_list(struct comedi_device *dev, + unsigned int n_chan, unsigned int *list) +{ + if (n_chan > 1) { /* setup channel gain table */ + int ii; + RtdClearCGT(dev); + RtdEnableCGT(dev, 1); /* enable table */ + for (ii = 0; ii < n_chan; ii++) { + RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii], + ii)); } - if (dev->board_ptr) - break; /* found one */ + } else { /* just use the channel gain latch */ + RtdEnableCGT(dev, 0); /* disable table, enable latch */ + RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0)); } - if (!pcidev) { - if (it->options[0] && it->options[1]) { - printk(KERN_INFO "No RTD card at bus=%d slot=%d.\n", - it->options[0], it->options[1]); - } else { - printk(KERN_INFO "No RTD card found.\n"); +} + +/* determine fifo size by doing adc conversions until the fifo half +empty status flag clears */ +static int rtd520_probe_fifo_depth(struct comedi_device *dev) +{ + unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); + unsigned i; + static const unsigned limit = 0x2000; + unsigned fifo_size = 0; + + RtdAdcClearFifo(dev); + rtd_load_channelgain_list(dev, 1, &chanspec); + RtdAdcConversionSource(dev, 0); /* software */ + /* convert samples */ + for (i = 0; i < limit; ++i) { + unsigned fifo_status; + /* trigger conversion */ + RtdAdcStart(dev); + udelay(1); + fifo_status = RtdFifoStatus(dev); + if ((fifo_status & FS_ADC_HEMPTY) == 0) { + fifo_size = 2 * i; + break; } + } + if (i == limit) { + printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n", + DRV_NAME); return -EIO; } - devpriv->pci_dev = pcidev; - dev->board_name = thisboard->name; - - ret = comedi_pci_enable(pcidev, DRV_NAME); - if (ret < 0) { - printk(KERN_INFO "Failed to enable PCI device and request regions.\n"); - return ret; + RtdAdcClearFifo(dev); + if (fifo_size != 0x400 && fifo_size != 0x2000) { + printk + (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n", + DRV_NAME, fifo_size); + return -EIO; } - devpriv->got_regions = 1; - - /* - * Initialize base addresses - */ - /* Get the physical address from PCI config */ - physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX); - physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX); - physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX); - /* Now have the kernel map this into memory */ - /* ASSUME page aligned */ - devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE); - devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); - devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); + return fifo_size; +} - if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) - return -ENOMEM; +/* + "instructions" read/write data in "one-shot" or "software-triggered" + mode (simplest case). + This doesn't use interrupts. + Note, we don't do any settling delays. Use a instruction list to + select, delay, then read. + */ +static int rtd_ai_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) +{ + int n, ii; + int stat; - DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name, - (unsigned long long)physLas0, (unsigned long long)physLas1, - (unsigned long long)physLcfg); - { /* The RTD driver does this */ - unsigned char pci_latency; - u16 revision; - /*uint32_t epld_version; */ + /* clear any old fifo data */ + RtdAdcClearFifo(dev); - pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID, - &revision); - DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision); + /* write channel to multiplexer and clear channel gain table */ + rtd_load_channelgain_list(dev, 1, &insn->chanspec); - pci_read_config_byte(devpriv->pci_dev, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 32) { - printk(KERN_INFO "%s: PCI latency changed from %d to %d\n", - dev->board_name, pci_latency, 32); - pci_write_config_byte(devpriv->pci_dev, - PCI_LATENCY_TIMER, 32); - } else { - DPRINTK("rtd520: PCI latency = %d\n", pci_latency); - } + /* set conversion source */ + RtdAdcConversionSource(dev, 0); /* software */ - /* - * Undocumented EPLD version (doesn't match RTD driver results) - */ - /*DPRINTK ("rtd520: Reading epld from %p\n", - devpriv->las0+0); - epld_version = readl (devpriv->las0+0); - if ((epld_version & 0xF0) >> 4 == 0x0F) { - DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version); - } else { - DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4); - } */ + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + s16 d; + /* trigger conversion */ + RtdAdcStart(dev); + + for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) { + stat = RtdFifoStatus(dev); + if (stat & FS_ADC_NOT_EMPTY) /* 1 -> not empty */ + break; + WAIT_QUIETLY; + } + if (ii >= RTD_ADC_TIMEOUT) { + DPRINTK + ("rtd520: Error: ADC never finished! FifoStatus=0x%x\n", + stat ^ 0x6666); + return -ETIMEDOUT; + } + + /* read data */ + d = RtdAdcFifoGet(dev); /* get 2s comp value */ + /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */ + d = d >> 3; /* low 3 bits are marker lines */ + if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) + /* convert to comedi unsigned data */ + data[n] = d + 2048; + else + data[n] = d; } - /* Show board configuration */ - printk(KERN_INFO "%s:", dev->board_name); + /* return the number of samples read/written */ + return n; +} - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ - if (alloc_subdevices(dev, 4) < 0) - return -ENOMEM; +/* + Get what we know is there.... Fast! + This uses 1/2 the bus cycles of read_dregs (below). + The manual claims that we can do a lword read, but it doesn't work here. +*/ +static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, + int count) +{ + int ii; - s = dev->subdevices + 0; - dev->read_subdev = s; - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = - SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ; - s->n_chan = thisboard->aiChans; - s->maxdata = (1 << thisboard->aiBits) - 1; - if (thisboard->aiMaxGain <= 32) - s->range_table = &rtd_ai_7520_range; - else - s->range_table = &rtd_ai_4520_range; + for (ii = 0; ii < count; ii++) { + short sample; + s16 d; - s->len_chanlist = RTD_MAX_CHANLIST; /* devpriv->fifoLen */ - s->insn_read = rtd_ai_rinsn; - s->do_cmd = rtd_ai_cmd; - s->do_cmdtest = rtd_ai_cmdtest; - s->cancel = rtd_ai_cancel; - /* s->poll = rtd_ai_poll; *//* not ready yet */ + if (0 == devpriv->aiCount) { /* done */ + d = RtdAdcFifoGet(dev); /* Read N and discard */ + continue; + } +#if 0 + if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) { /* DEBUG */ + DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1, + count); + break; + } +#endif + d = RtdAdcFifoGet(dev); /* get 2s comp value */ - s = dev->subdevices + 1; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->maxdata = (1 << thisboard->aiBits) - 1; - s->range_table = &rtd_ao_range; - s->insn_write = rtd_ao_winsn; - s->insn_read = rtd_ao_rinsn; + d = d >> 3; /* low 3 bits are marker lines */ + if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { + /* convert to comedi unsigned data */ + sample = d + 2048; + } else + sample = d; - s = dev->subdevices + 2; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - /* we only support port 0 right now. Ignoring port 1 and user IO */ - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = rtd_dio_insn_bits; - s->insn_config = rtd_dio_insn_config; + if (!comedi_buf_put(s->async, sample)) + return -1; - /* timer/counter subdevices (not currently supported) */ - s = dev->subdevices + 3; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 3; - s->maxdata = 0xffff; + if (devpriv->aiCount > 0) /* < 0, means read forever */ + devpriv->aiCount--; + } + return 0; +} - /* initialize board, per RTD spec */ - /* also, initialize shadow registers */ - RtdResetBoard(dev); - udelay(100); /* needed? */ - RtdPlxInterruptWrite(dev, 0); - RtdInterruptMask(dev, 0); /* and sets shadow */ - RtdInterruptClearMask(dev, ~0); /* and sets shadow */ - RtdInterruptClear(dev); /* clears bits set by mask */ - RtdInterruptOverrunClear(dev); - RtdClearCGT(dev); - RtdAdcClearFifo(dev); - RtdDacClearFifo(dev, 0); - RtdDacClearFifo(dev, 1); - /* clear digital IO fifo */ - RtdDioStatusWrite(dev, 0); /* safe state, set shadow */ - RtdUtcCtrlPut(dev, 0, 0x30); /* safe state, set shadow */ - RtdUtcCtrlPut(dev, 1, 0x30); /* safe state, set shadow */ - RtdUtcCtrlPut(dev, 2, 0x30); /* safe state, set shadow */ - RtdUtcCtrlPut(dev, 3, 0); /* safe state, set shadow */ - /* TODO: set user out source ??? */ +/* + unknown amout of data is waiting in fifo. +*/ +static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) +{ + while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */ + short sample; + s16 d = RtdAdcFifoGet(dev); /* get 2s comp value */ - /* check if our interrupt is available and get it */ - ret = request_irq(devpriv->pci_dev->irq, rtd_interrupt, - IRQF_SHARED, DRV_NAME, dev); + if (0 == devpriv->aiCount) { /* done */ + continue; /* read rest */ + } - if (ret < 0) { - printk("Could not get interrupt! (%u)\n", - devpriv->pci_dev->irq); - return ret; - } - dev->irq = devpriv->pci_dev->irq; - printk(KERN_INFO "( irq=%u )", dev->irq); + d = d >> 3; /* low 3 bits are marker lines */ + if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { + /* convert to comedi unsigned data */ + sample = d + 2048; + } else + sample = d; - ret = rtd520_probe_fifo_depth(dev); - if (ret < 0) - return ret; + if (!comedi_buf_put(s->async, sample)) + return -1; - devpriv->fifoLen = ret; - printk("( fifoLen=%d )", devpriv->fifoLen); + if (devpriv->aiCount > 0) /* < 0, means read forever */ + devpriv->aiCount--; + } + return 0; +} #ifdef USE_DMA - if (dev->irq > 0) { - printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT); - /* - * The PLX9080 has 2 DMA controllers, but there could be - * 4 sources: ADC, digital, DAC1, and DAC2. Since only the - * ADC supports cmd mode right now, this isn't an issue (yet) - */ - devpriv->dma0Offset = 0; +/* + Terminate a DMA transfer and wait for everything to quiet down +*/ +void abort_dma(struct comedi_device *dev, unsigned int channel) +{ /* DMA channel 0, 1 */ + unsigned long dma_cs_addr; /* the control/status register */ + uint8_t status; + unsigned int ii; + /* unsigned long flags; */ - for (index = 0; index < DMA_CHAIN_COUNT; index++) { - devpriv->dma0Buff[index] = - pci_alloc_consistent(devpriv->pci_dev, - sizeof(u16) * - devpriv->fifoLen / 2, - &devpriv-> - dma0BuffPhysAddr[index]); - if (devpriv->dma0Buff[index] == NULL) { - ret = -ENOMEM; - goto rtd_attach_die_error; - } - /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n", - index, - devpriv->dma0Buff[index], - devpriv->dma0BuffPhysAddr[index]); */ - } + dma_cs_addr = (unsigned long)devpriv->lcfg + + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1); - /* - * setup DMA descriptor ring (use cpu_to_le32 for byte - * ordering?) - */ - devpriv->dma0Chain = - pci_alloc_consistent(devpriv->pci_dev, - sizeof(struct plx_dma_desc) * - DMA_CHAIN_COUNT, - &devpriv->dma0ChainPhysAddr); - for (index = 0; index < DMA_CHAIN_COUNT; index++) { - devpriv->dma0Chain[index].pci_start_addr = - devpriv->dma0BuffPhysAddr[index]; - devpriv->dma0Chain[index].local_start_addr = - DMALADDR_ADC; - devpriv->dma0Chain[index].transfer_size = - sizeof(u16) * devpriv->fifoLen / 2; - devpriv->dma0Chain[index].next = - (devpriv->dma0ChainPhysAddr + ((index + - 1) % - (DMA_CHAIN_COUNT)) - * sizeof(devpriv->dma0Chain[0])) - | DMA_TRANSFER_BITS; - /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n", - index, - ((long)devpriv->dma0ChainPhysAddr - + (index * sizeof(devpriv->dma0Chain[0]))), - devpriv->dma0Chain[index].pci_start_addr, - devpriv->dma0Chain[index].local_start_addr, - devpriv->dma0Chain[index].transfer_size, - devpriv->dma0Chain[index].next); */ - } + /* spinlock for plx dma control/status reg */ + /* spin_lock_irqsave( &dev->spinlock, flags ); */ - if (devpriv->dma0Chain == NULL) { - ret = -ENOMEM; - goto rtd_attach_die_error; - } + /* abort dma transfer if necessary */ + status = readb(dma_cs_addr); + if ((status & PLX_DMA_EN_BIT) == 0) { /* not enabled (Error?) */ + DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n", + channel, status); + goto abortDmaExit; + } - RtdDma0Mode(dev, DMA_MODE_BITS); - /* set DMA trigger source */ - RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); - } else { - printk(KERN_INFO "( no IRQ->no DMA )"); + /* wait to make sure done bit is zero (needed?) */ + for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) { + WAIT_QUIETLY; + status = readb(dma_cs_addr); + } + if (status & PLX_DMA_DONE_BIT) { + printk("rtd520: Timeout waiting for dma %i done clear\n", + channel); + goto abortDmaExit; } -#endif /* USE_DMA */ - if (dev->irq) { /* enable plx9080 interrupts */ - RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); + /* disable channel (required) */ + writeb(0, dma_cs_addr); + udelay(1); /* needed?? */ + /* set abort bit for channel */ + writeb(PLX_DMA_ABORT_BIT, dma_cs_addr); + + /* wait for dma done bit to be set */ + status = readb(dma_cs_addr); + for (ii = 0; + (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; ii++) { + status = readb(dma_cs_addr); + WAIT_QUIETLY; + } + if ((status & PLX_DMA_DONE_BIT) == 0) { + printk("rtd520: Timeout waiting for dma %i done set\n", + channel); } - printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor); +abortDmaExit: + /* spin_unlock_irqrestore( &dev->spinlock, flags ); */ +} - return 1; +/* + Process what is in the DMA transfer buffer and pass to comedi + Note: this is not re-entrant +*/ +static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s) +{ + int ii, n; + s16 *dp; -#if 0 - /* hit an error, clean up memory and return ret */ -/* rtd_attach_die_error: */ -#ifdef USE_DMA - for (index = 0; index < DMA_CHAIN_COUNT; index++) { - if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */ - pci_free_consistent(devpriv->pci_dev, - sizeof(u16) * devpriv->fifoLen / 2, - devpriv->dma0Buff[index], - devpriv->dma0BuffPhysAddr[index]); - devpriv->dma0Buff[index] = NULL; + if (devpriv->aiCount == 0) /* transfer already complete */ + return 0; + + dp = devpriv->dma0Buff[devpriv->dma0Offset]; + for (ii = 0; ii < devpriv->fifoLen / 2;) { /* convert samples */ + short sample; + + if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { + sample = (*dp >> 3) + 2048; /* convert to comedi unsigned data */ + else + sample = *dp >> 3; /* low 3 bits are marker lines */ + + *dp++ = sample; /* put processed value back */ + + if (++s->async->cur_chan >= s->async->cmd.chanlist_len) + s->async->cur_chan = 0; + + ++ii; /* number ready to transfer */ + if (devpriv->aiCount > 0) { /* < 0, means read forever */ + if (--devpriv->aiCount == 0) { /* done */ + /*DPRINTK ("rtd520: Final %d samples\n", ii); */ + break; + } } } - if (NULL != devpriv->dma0Chain) { - pci_free_consistent(devpriv->pci_dev, - sizeof(struct plx_dma_desc) - * DMA_CHAIN_COUNT, - devpriv->dma0Chain, - devpriv->dma0ChainPhysAddr); - devpriv->dma0Chain = NULL; - } -#endif /* USE_DMA */ - /* subdevices and priv are freed by the core */ - if (dev->irq) { - /* disable interrupt controller */ - RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) - & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E)); - free_irq(dev->irq, dev); + + /* now pass the whole array to the comedi buffer */ + dp = devpriv->dma0Buff[devpriv->dma0Offset]; + n = comedi_buf_write_alloc(s->async, ii * sizeof(s16)); + if (n < (ii * sizeof(s16))) { /* any residual is an error */ + DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n", + ii - (n / sizeof(s16))); + s->async->events |= COMEDI_CB_ERROR; + return -1; } + comedi_buf_memcpy_to(s->async, 0, dp, n); + comedi_buf_write_free(s->async, n); - /* release all regions that were allocated */ - if (devpriv->las0) - iounmap(devpriv->las0); + /* + * always at least 1 scan -- 1/2 FIFO is larger than our max scan list + */ + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - if (devpriv->las1) - iounmap(devpriv->las1); + if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */ + devpriv->dma0Offset = 0; + } + return 0; +} +#endif /* USE_DMA */ - if (devpriv->lcfg) - iounmap(devpriv->lcfg); +/* + Handle all rtd520 interrupts. + Runs atomically and is never re-entered. + This is a "slow handler"; other interrupts may be active. + The data conversion may someday happen in a "bottom half". +*/ +static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ + void *d) +{ /* our data *//* cpu context (ignored) */ + struct comedi_device *dev = d; /* must be called "dev" for devpriv */ + u16 status; + u16 fifoStatus; + struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ - if (devpriv->pci_dev) - pci_dev_put(devpriv->pci_dev); + if (!dev->attached) + return IRQ_NONE; - return ret; -#endif -} + devpriv->intCount++; /* DEBUG statistics */ -static void rtd_detach(struct comedi_device *dev) -{ + fifoStatus = RtdFifoStatus(dev); + /* check for FIFO full, this automatically halts the ADC! */ + if (!(fifoStatus & FS_ADC_NOT_FULL)) { /* 0 -> full */ + DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */ + goto abortTransfer; + } #ifdef USE_DMA - int index; -#endif + if (devpriv->flags & DMA0_ACTIVE) { /* Check DMA */ + u32 istatus = RtdPlxInterruptRead(dev); - if (devpriv) { - /* Shut down any board ops by resetting it */ -#ifdef USE_DMA - if (devpriv->lcfg) { - RtdDma0Control(dev, 0); /* disable DMA */ - RtdDma1Control(dev, 0); /* disable DMA */ - RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); - } -#endif /* USE_DMA */ - if (devpriv->las0) { - RtdResetBoard(dev); - RtdInterruptMask(dev, 0); - RtdInterruptClearMask(dev, ~0); - RtdInterruptClear(dev); /* clears bits set by mask */ - } -#ifdef USE_DMA - /* release DMA */ - for (index = 0; index < DMA_CHAIN_COUNT; index++) { - if (NULL != devpriv->dma0Buff[index]) { - pci_free_consistent(devpriv->pci_dev, - sizeof(u16) * - devpriv->fifoLen / 2, - devpriv->dma0Buff[index], - devpriv-> - dma0BuffPhysAddr[index]); - devpriv->dma0Buff[index] = NULL; + if (istatus & ICS_DMA0_A) { + if (ai_process_dma(dev, s) < 0) { + DPRINTK + ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n", + devpriv->aiCount); + RtdDma0Control(dev, + (devpriv->dma0Control & + ~PLX_DMA_START_BIT) + | PLX_CLEAR_DMA_INTR_BIT); + goto abortTransfer; } + + /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n", + devpriv->aiCount, istatus); */ + RtdDma0Control(dev, + (devpriv-> + dma0Control & ~PLX_DMA_START_BIT) + | PLX_CLEAR_DMA_INTR_BIT); + if (0 == devpriv->aiCount) { /* counted down */ + DPRINTK("rtd520: Samples Done (DMA).\n"); + goto transferDone; + } + comedi_event(dev, s); + } else { + /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */ } - if (NULL != devpriv->dma0Chain) { - pci_free_consistent(devpriv->pci_dev, - sizeof(struct plx_dma_desc) * - DMA_CHAIN_COUNT, devpriv->dma0Chain, - devpriv->dma0ChainPhysAddr); - devpriv->dma0Chain = NULL; - } + } + /* Fall through and check for other interrupt sources */ #endif /* USE_DMA */ - if (dev->irq) { - RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) - & ~(ICS_PLIE | ICS_DMA0_E | - ICS_DMA1_E)); - free_irq(dev->irq, dev); - } - if (devpriv->las0) - iounmap(devpriv->las0); - if (devpriv->las1) - iounmap(devpriv->las1); - if (devpriv->lcfg) - iounmap(devpriv->lcfg); - if (devpriv->pci_dev) { - if (devpriv->got_regions) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); + + status = RtdInterruptStatus(dev); + /* if interrupt was not caused by our board, or handled above */ + if (0 == status) + return IRQ_HANDLED; + + if (status & IRQM_ADC_ABOUT_CNT) { /* sample count -> read FIFO */ + /* since the priority interrupt controller may have queued a sample + counter interrupt, even though we have already finished, + we must handle the possibility that there is no data here */ + if (!(fifoStatus & FS_ADC_HEMPTY)) { /* 0 -> 1/2 full */ + /*DPRINTK("rtd520: Sample int, reading 1/2FIFO. fifo_status 0x%x\n", + (fifoStatus ^ 0x6666) & 0x7777); */ + if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) { + DPRINTK + ("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n", + devpriv->aiCount); + goto abortTransfer; + } + if (0 == devpriv->aiCount) { /* counted down */ + DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */ + goto transferDone; + } + comedi_event(dev, s); + } else if (devpriv->transCount > 0) { /* read often */ + /*DPRINTK("rtd520: Sample int, reading %d fifo_status 0x%x\n", + devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */ + if (fifoStatus & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */ + if (ai_read_n(dev, s, devpriv->transCount) < 0) { + DPRINTK + ("rtd520: comedi read buffer overflow (N) with %ld to go!\n", + devpriv->aiCount); + goto abortTransfer; + } + if (0 == devpriv->aiCount) { /* counted down */ + DPRINTK + ("rtd520: Samples Done (N). fifo_status was 0x%x\n", + (fifoStatus ^ 0x6666) & 0x7777); + goto transferDone; + } + comedi_event(dev, s); + } + } else { /* wait for 1/2 FIFO (old) */ + DPRINTK + ("rtd520: Sample int. Wait for 1/2. fifo_status 0x%x\n", + (fifoStatus ^ 0x6666) & 0x7777); } + } else { + DPRINTK("rtd520: unknown interrupt source!\n"); } -} -/* - Convert a single comedi channel-gain entry to a RTD520 table entry -*/ -static unsigned short rtdConvertChanGain(struct comedi_device *dev, - unsigned int comediChan, int chanIndex) -{ /* index in channel list */ - unsigned int chan, range, aref; - unsigned short r = 0; + if (0xffff & RtdInterruptOverrunStatus(dev)) { /* interrupt overrun */ + DPRINTK + ("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n", + devpriv->aiCount, 0xffff & RtdInterruptOverrunStatus(dev)); + goto abortTransfer; + } - chan = CR_CHAN(comediChan); - range = CR_RANGE(comediChan); - aref = CR_AREF(comediChan); + /* clear the interrupt */ + RtdInterruptClearMask(dev, status); + RtdInterruptClear(dev); + return IRQ_HANDLED; - r |= chan & 0xf; +abortTransfer: + RtdAdcClearFifo(dev); /* clears full flag */ + s->async->events |= COMEDI_CB_ERROR; + devpriv->aiCount = 0; /* stop and don't transfer any more */ + /* fall into transferDone */ - /* Note: we also setup the channel list bipolar flag array */ - if (range < thisboard->range10Start) { /* first batch are +-5 */ - r |= 0x000; /* +-5 range */ - r |= (range & 0x7) << 4; /* gain */ - CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); - } else if (range < thisboard->rangeUniStart) { /* second batch are +-10 */ - r |= 0x100; /* +-10 range */ - /* gain */ - r |= ((range - thisboard->range10Start) & 0x7) << 4; - CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); - } else { /* last batch is +10 */ - r |= 0x200; /* +10 range */ - /* gain */ - r |= ((range - thisboard->rangeUniStart) & 0x7) << 4; - CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex); +transferDone: + RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */ + RtdPacerStop(dev); /* Stop PACER */ + RtdAdcConversionSource(dev, 0); /* software trigger only */ + RtdInterruptMask(dev, 0); /* mask out SAMPLE */ +#ifdef USE_DMA + if (devpriv->flags & DMA0_ACTIVE) { + RtdPlxInterruptWrite(dev, /* disable any more interrupts */ + RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); + abort_dma(dev, 0); + devpriv->flags &= ~DMA0_ACTIVE; + /* if Using DMA, then we should have read everything by now */ + if (devpriv->aiCount > 0) { + DPRINTK("rtd520: Lost DMA data! %ld remain\n", + devpriv->aiCount); + } } +#endif /* USE_DMA */ - switch (aref) { - case AREF_GROUND: /* on-board ground */ - break; + if (devpriv->aiCount > 0) { /* there shouldn't be anything left */ + fifoStatus = RtdFifoStatus(dev); + DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777); /* should read all 0s */ + ai_read_dregs(dev, s); /* read anything left in FIFO */ + } - case AREF_COMMON: - r |= 0x80; /* ref external analog common */ - break; + s->async->events |= COMEDI_CB_EOA; /* signal end to comedi */ + comedi_event(dev, s); - case AREF_DIFF: - r |= 0x400; /* differential inputs */ - break; + /* clear the interrupt */ + status = RtdInterruptStatus(dev); + RtdInterruptClearMask(dev, status); + RtdInterruptClear(dev); - case AREF_OTHER: /* ??? */ - break; - } - /*printk ("chan=%d r=%d a=%d -> 0x%x\n", - chan, range, aref, r); */ - return r; + fifoStatus = RtdFifoStatus(dev); /* DEBUG */ + DPRINTK + ("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n", + devpriv->intCount, status, + 0xffff & RtdInterruptOverrunStatus(dev)); + + return IRQ_HANDLED; } +#if 0 /* - Setup the channel-gain table from a comedi list + return the number of samples available */ -static void rtd_load_channelgain_list(struct comedi_device *dev, - unsigned int n_chan, unsigned int *list) +static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { - if (n_chan > 1) { /* setup channel gain table */ - int ii; - RtdClearCGT(dev); - RtdEnableCGT(dev, 1); /* enable table */ - for (ii = 0; ii < n_chan; ii++) { - RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii], - ii)); - } - } else { /* just use the channel gain latch */ - RtdEnableCGT(dev, 0); /* disable table, enable latch */ - RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0)); - } + /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */ + /* Not sure what to do if DMA is active */ + return s->async->buf_write_count - s->async->buf_read_count; } +#endif -/* determine fifo size by doing adc conversions until the fifo half -empty status flag clears */ -static int rtd520_probe_fifo_depth(struct comedi_device *dev) +/* + cmdtest tests a particular command to see if it is valid. + Using the cmdtest ioctl, a user can create a valid cmd + and then have it executed by the cmd ioctl (asyncronously). + + cmdtest returns 1,2,3,4 or 0, depending on which tests + the command passes. +*/ + +static int rtd_ai_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { - unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); - unsigned i; - static const unsigned limit = 0x2000; - unsigned fifo_size = 0; + int err = 0; + int tmp; - RtdAdcClearFifo(dev); - rtd_load_channelgain_list(dev, 1, &chanspec); - RtdAdcConversionSource(dev, 0); /* software */ - /* convert samples */ - for (i = 0; i < limit; ++i) { - unsigned fifo_status; - /* trigger conversion */ - RtdAdcStart(dev); - udelay(1); - fifo_status = RtdFifoStatus(dev); - if ((fifo_status & FS_ADC_HEMPTY) == 0) { - fifo_size = 2 * i; - break; - } - } - if (i == limit) { - printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n", - DRV_NAME); - return -EIO; - } - RtdAdcClearFifo(dev); - if (fifo_size != 0x400 && fifo_size != 0x2000) { - printk - (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n", - DRV_NAME, fifo_size); - return -EIO; - } - return fifo_size; -} + /* step 1: make sure trigger sources are trivially valid */ -/* - "instructions" read/write data in "one-shot" or "software-triggered" - mode (simplest case). - This doesn't use interrupts. + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - Note, we don't do any settling delays. Use a instruction list to - select, delay, then read. - */ -static int rtd_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - int n, ii; - int stat; + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - /* clear any old fifo data */ - RtdAdcClearFifo(dev); - /* write channel to multiplexer and clear channel gain table */ - rtd_load_channelgain_list(dev, 1, &insn->chanspec); + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* set conversion source */ - RtdAdcConversionSource(dev, 0); /* software */ - /* convert n samples */ - for (n = 0; n < insn->n; n++) { - s16 d; - /* trigger conversion */ - RtdAdcStart(dev); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) { - stat = RtdFifoStatus(dev); - if (stat & FS_ADC_NOT_EMPTY) /* 1 -> not empty */ - break; - WAIT_QUIETLY; - } - if (ii >= RTD_ADC_TIMEOUT) { - DPRINTK - ("rtd520: Error: ADC never finished! FifoStatus=0x%x\n", - stat ^ 0x6666); - return -ETIMEDOUT; - } - /* read data */ - d = RtdAdcFifoGet(dev); /* get 2s comp value */ - /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */ - d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) - /* convert to comedi unsigned data */ - data[n] = d + 2048; - else - data[n] = d; + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique + and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) { + err++; } + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; - /* return the number of samples read/written */ - return n; -} + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; -/* - Get what we know is there.... Fast! - This uses 1/2 the bus cycles of read_dregs (below). + if (err) + return 2; - The manual claims that we can do a lword read, but it doesn't work here. -*/ -static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, - int count) -{ - int ii; + /* step 3: make sure arguments are trivially compatible */ - for (ii = 0; ii < count; ii++) { - short sample; - s16 d; + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } - if (0 == devpriv->aiCount) { /* done */ - d = RtdAdcFifoGet(dev); /* Read N and discard */ - continue; + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Note: these are time periods, not actual rates */ + if (1 == cmd->chanlist_len) { /* no scanning */ + if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) { + cmd->scan_begin_arg = RTD_MAX_SPEED_1; + rtd_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_UP); + err++; + } + if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) { + cmd->scan_begin_arg = RTD_MIN_SPEED_1; + rtd_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_DOWN); + err++; + } + } else { + if (cmd->scan_begin_arg < RTD_MAX_SPEED) { + cmd->scan_begin_arg = RTD_MAX_SPEED; + rtd_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_UP); + err++; + } + if (cmd->scan_begin_arg > RTD_MIN_SPEED) { + cmd->scan_begin_arg = RTD_MIN_SPEED; + rtd_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_DOWN); + err++; + } } -#if 0 - if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) { /* DEBUG */ - DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1, - count); - break; + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if (cmd->scan_begin_arg > 9) { + cmd->scan_begin_arg = 9; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (1 == cmd->chanlist_len) { /* no scanning */ + if (cmd->convert_arg < RTD_MAX_SPEED_1) { + cmd->convert_arg = RTD_MAX_SPEED_1; + rtd_ns_to_timer(&cmd->convert_arg, + TRIG_ROUND_UP); + err++; + } + if (cmd->convert_arg > RTD_MIN_SPEED_1) { + cmd->convert_arg = RTD_MIN_SPEED_1; + rtd_ns_to_timer(&cmd->convert_arg, + TRIG_ROUND_DOWN); + err++; + } + } else { + if (cmd->convert_arg < RTD_MAX_SPEED) { + cmd->convert_arg = RTD_MAX_SPEED; + rtd_ns_to_timer(&cmd->convert_arg, + TRIG_ROUND_UP); + err++; + } + if (cmd->convert_arg > RTD_MIN_SPEED) { + cmd->convert_arg = RTD_MIN_SPEED; + rtd_ns_to_timer(&cmd->convert_arg, + TRIG_ROUND_DOWN); + err++; + } + } + } else { + /* external trigger */ + /* see above */ + if (cmd->convert_arg > 9) { + cmd->convert_arg = 9; + err++; } + } + +#if 0 + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } #endif - d = RtdAdcFifoGet(dev); /* get 2s comp value */ + if (cmd->stop_src == TRIG_COUNT) { + /* TODO check for rounding error due to counter wrap */ - d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { - /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } - if (!comedi_buf_put(s->async, sample)) - return -1; + if (err) + return 3; - if (devpriv->aiCount > 0) /* < 0, means read forever */ - devpriv->aiCount--; + + /* step 4: fix up any arguments */ + + if (cmd->chanlist_len > RTD_MAX_CHANLIST) { + cmd->chanlist_len = RTD_MAX_CHANLIST; + err++; } - return 0; -} + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + rtd_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; -/* - unknown amout of data is waiting in fifo. -*/ -static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) -{ - while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */ - short sample; - s16 d = RtdAdcFifoGet(dev); /* get 2s comp value */ + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + rtd_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; - if (0 == devpriv->aiCount) { /* done */ - continue; /* read rest */ + if (cmd->scan_begin_src == TRIG_TIMER + && (cmd->scan_begin_arg + < (cmd->convert_arg * cmd->scan_end_arg))) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; } + } - d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { - /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; - - if (!comedi_buf_put(s->async, sample)) - return -1; + if (err) + return 4; - if (devpriv->aiCount > 0) /* < 0, means read forever */ - devpriv->aiCount--; - } return 0; } -#ifdef USE_DMA /* - Terminate a DMA transfer and wait for everything to quiet down + Execute a analog in command with many possible triggering options. + The data get stored in the async structure of the subdevice. + This is usually done by an interrupt handler. + Userland gets to the data using read calls. */ -void abort_dma(struct comedi_device *dev, unsigned int channel) -{ /* DMA channel 0, 1 */ - unsigned long dma_cs_addr; /* the control/status register */ - uint8_t status; - unsigned int ii; - /* unsigned long flags; */ - - dma_cs_addr = (unsigned long)devpriv->lcfg - + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1); - - /* spinlock for plx dma control/status reg */ - /* spin_lock_irqsave( &dev->spinlock, flags ); */ +static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int timer; - /* abort dma transfer if necessary */ - status = readb(dma_cs_addr); - if ((status & PLX_DMA_EN_BIT) == 0) { /* not enabled (Error?) */ - DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n", - channel, status); - goto abortDmaExit; + /* stop anything currently running */ + RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */ + RtdPacerStop(dev); /* make sure PACER is stopped */ + RtdAdcConversionSource(dev, 0); /* software trigger only */ + RtdInterruptMask(dev, 0); +#ifdef USE_DMA + if (devpriv->flags & DMA0_ACTIVE) { /* cancel anything running */ + RtdPlxInterruptWrite(dev, /* disable any more interrupts */ + RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); + abort_dma(dev, 0); + devpriv->flags &= ~DMA0_ACTIVE; + if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) { /*clear pending int */ + RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT); + } } + RtdDma0Reset(dev); /* reset onboard state */ +#endif /* USE_DMA */ + RtdAdcClearFifo(dev); /* clear any old data */ + RtdInterruptOverrunClear(dev); + devpriv->intCount = 0; - /* wait to make sure done bit is zero (needed?) */ - for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) { - WAIT_QUIETLY; - status = readb(dma_cs_addr); - } - if (status & PLX_DMA_DONE_BIT) { - printk("rtd520: Timeout waiting for dma %i done clear\n", - channel); - goto abortDmaExit; + if (!dev->irq) { /* we need interrupts for this */ + DPRINTK("rtd520: ERROR! No interrupt available!\n"); + return -ENXIO; } - /* disable channel (required) */ - writeb(0, dma_cs_addr); - udelay(1); /* needed?? */ - /* set abort bit for channel */ - writeb(PLX_DMA_ABORT_BIT, dma_cs_addr); + /* start configuration */ + /* load channel list and reset CGT */ + rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist); - /* wait for dma done bit to be set */ - status = readb(dma_cs_addr); - for (ii = 0; - (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; ii++) { - status = readb(dma_cs_addr); - WAIT_QUIETLY; + /* setup the common case and override if needed */ + if (cmd->chanlist_len > 1) { + /*DPRINTK ("rtd520: Multi channel setup\n"); */ + RtdPacerStartSource(dev, 0); /* software triggers pacer */ + RtdBurstStartSource(dev, 1); /* PACER triggers burst */ + RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */ + } else { /* single channel */ + /*DPRINTK ("rtd520: single channel setup\n"); */ + RtdPacerStartSource(dev, 0); /* software triggers pacer */ + RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */ } - if ((status & PLX_DMA_DONE_BIT) == 0) { - printk("rtd520: Timeout waiting for dma %i done set\n", - channel); + RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */ + + if (TRIG_TIMER == cmd->scan_begin_src) { + /* scan_begin_arg is in nanoseconds */ + /* find out how many samples to wait before transferring */ + if (cmd->flags & TRIG_WAKE_EOS) { + /* this may generate un-sustainable interrupt rates */ + /* the application is responsible for doing the right thing */ + devpriv->transCount = cmd->chanlist_len; + devpriv->flags |= SEND_EOS; + } else { + /* arrange to transfer data periodically */ + devpriv->transCount + = + (TRANS_TARGET_PERIOD * cmd->chanlist_len) / + cmd->scan_begin_arg; + if (devpriv->transCount < cmd->chanlist_len) { + /* transfer after each scan (and avoid 0) */ + devpriv->transCount = cmd->chanlist_len; + } else { /* make a multiple of scan length */ + devpriv->transCount = + (devpriv->transCount + + cmd->chanlist_len - 1) + / cmd->chanlist_len; + devpriv->transCount *= cmd->chanlist_len; + } + devpriv->flags |= SEND_EOS; + } + if (devpriv->transCount >= (devpriv->fifoLen / 2)) { + /* out of counter range, use 1/2 fifo instead */ + devpriv->transCount = 0; + devpriv->flags &= ~SEND_EOS; + } else { + /* interrupt for each transfer */ + RtdAboutCounter(dev, devpriv->transCount - 1); + } + + DPRINTK + ("rtd520: scanLen=%d transferCount=%d fifoLen=%d\n scanTime(ns)=%d flags=0x%x\n", + cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen, + cmd->scan_begin_arg, devpriv->flags); + } else { /* unknown timing, just use 1/2 FIFO */ + devpriv->transCount = 0; + devpriv->flags &= ~SEND_EOS; } + RtdPacerClockSource(dev, 1); /* use INTERNAL 8Mhz clock source */ + RtdAboutStopEnable(dev, 1); /* just interrupt, dont stop */ -abortDmaExit: - /* spin_unlock_irqrestore( &dev->spinlock, flags ); */ -} + /* BUG??? these look like enumerated values, but they are bit fields */ -/* - Process what is in the DMA transfer buffer and pass to comedi - Note: this is not re-entrant -*/ -static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s) -{ - int ii, n; - s16 *dp; + /* First, setup when to stop */ + switch (cmd->stop_src) { + case TRIG_COUNT: /* stop after N scans */ + devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len; + if ((devpriv->transCount > 0) + && (devpriv->transCount > devpriv->aiCount)) { + devpriv->transCount = devpriv->aiCount; + } + break; - if (devpriv->aiCount == 0) /* transfer already complete */ - return 0; + case TRIG_NONE: /* stop when cancel is called */ + devpriv->aiCount = -1; /* read forever */ + break; - dp = devpriv->dma0Buff[devpriv->dma0Offset]; - for (ii = 0; ii < devpriv->fifoLen / 2;) { /* convert samples */ - short sample; + default: + DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n", + cmd->stop_src); + } + + /* Scan timing */ + switch (cmd->scan_begin_src) { + case TRIG_TIMER: /* periodic scanning */ + timer = rtd_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_NEAREST); + /* set PACER clock */ + /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */ + RtdPacerCounter(dev, timer); - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { - sample = (*dp >> 3) + 2048; /* convert to comedi unsigned data */ - else - sample = *dp >> 3; /* low 3 bits are marker lines */ + break; - *dp++ = sample; /* put processed value back */ + case TRIG_EXT: + RtdPacerStartSource(dev, 1); /* EXTERNALy trigger pacer */ + break; - if (++s->async->cur_chan >= s->async->cmd.chanlist_len) - s->async->cur_chan = 0; + default: + DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n", + cmd->scan_begin_src); + } - ++ii; /* number ready to transfer */ - if (devpriv->aiCount > 0) { /* < 0, means read forever */ - if (--devpriv->aiCount == 0) { /* done */ - /*DPRINTK ("rtd520: Final %d samples\n", ii); */ - break; - } + /* Sample timing within a scan */ + switch (cmd->convert_src) { + case TRIG_TIMER: /* periodic */ + if (cmd->chanlist_len > 1) { /* only needed for multi-channel */ + timer = rtd_ns_to_timer(&cmd->convert_arg, + TRIG_ROUND_NEAREST); + /* setup BURST clock */ + /*DPRINTK ("rtd520: loading %d into burst\n", timer); */ + RtdBurstCounter(dev, timer); } - } - /* now pass the whole array to the comedi buffer */ - dp = devpriv->dma0Buff[devpriv->dma0Offset]; - n = comedi_buf_write_alloc(s->async, ii * sizeof(s16)); - if (n < (ii * sizeof(s16))) { /* any residual is an error */ - DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n", - ii - (n / sizeof(s16))); - s->async->events |= COMEDI_CB_ERROR; - return -1; - } - comedi_buf_memcpy_to(s->async, 0, dp, n); - comedi_buf_write_free(s->async, n); + break; - /* - * always at least 1 scan -- 1/2 FIFO is larger than our max scan list - */ - s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + case TRIG_EXT: /* external */ + RtdBurstStartSource(dev, 2); /* EXTERNALy trigger burst */ + break; - if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */ - devpriv->dma0Offset = 0; + default: + DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n", + cmd->convert_src); } - return 0; -} -#endif /* USE_DMA */ - -/* - Handle all rtd520 interrupts. - Runs atomically and is never re-entered. - This is a "slow handler"; other interrupts may be active. - The data conversion may someday happen in a "bottom half". -*/ -static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ - void *d) -{ /* our data *//* cpu context (ignored) */ - struct comedi_device *dev = d; /* must be called "dev" for devpriv */ - u16 status; - u16 fifoStatus; - struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ - - if (!dev->attached) - return IRQ_NONE; + /* end configuration */ - devpriv->intCount++; /* DEBUG statistics */ + /* This doesn't seem to work. There is no way to clear an interrupt + that the priority controller has queued! */ + RtdInterruptClearMask(dev, ~0); /* clear any existing flags */ + RtdInterruptClear(dev); - fifoStatus = RtdFifoStatus(dev); - /* check for FIFO full, this automatically halts the ADC! */ - if (!(fifoStatus & FS_ADC_NOT_FULL)) { /* 0 -> full */ - DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */ - goto abortTransfer; - } + /* TODO: allow multiple interrupt sources */ + if (devpriv->transCount > 0) { /* transfer every N samples */ + RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT); + DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount); + } else { /* 1/2 FIFO transfers */ #ifdef USE_DMA - if (devpriv->flags & DMA0_ACTIVE) { /* Check DMA */ - u32 istatus = RtdPlxInterruptRead(dev); + devpriv->flags |= DMA0_ACTIVE; - if (istatus & ICS_DMA0_A) { - if (ai_process_dma(dev, s) < 0) { - DPRINTK - ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n", - devpriv->aiCount); - RtdDma0Control(dev, - (devpriv->dma0Control & - ~PLX_DMA_START_BIT) - | PLX_CLEAR_DMA_INTR_BIT); - goto abortTransfer; - } + /* point to first transfer in ring */ + devpriv->dma0Offset = 0; + RtdDma0Mode(dev, DMA_MODE_BITS); + RtdDma0Next(dev, /* point to first block */ + devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next); + RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */ - /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n", - devpriv->aiCount, istatus); */ - RtdDma0Control(dev, - (devpriv-> - dma0Control & ~PLX_DMA_START_BIT) - | PLX_CLEAR_DMA_INTR_BIT); - if (0 == devpriv->aiCount) { /* counted down */ - DPRINTK("rtd520: Samples Done (DMA).\n"); - goto transferDone; - } - comedi_event(dev, s); - } else { - /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */ - } - } - /* Fall through and check for other interrupt sources */ + RtdPlxInterruptWrite(dev, /* enable interrupt */ + RtdPlxInterruptRead(dev) | ICS_DMA0_E); + /* Must be 2 steps. See PLX app note about "Starting a DMA transfer" */ + RtdDma0Control(dev, PLX_DMA_EN_BIT); /* enable DMA (clear INTR?) */ + RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT); /*start DMA */ + DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n", + RtdPlxInterruptRead(dev), devpriv->intMask); +#else /* USE_DMA */ + RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT); + DPRINTK("rtd520: Transferring every 1/2 FIFO\n"); #endif /* USE_DMA */ - - status = RtdInterruptStatus(dev); - /* if interrupt was not caused by our board, or handled above */ - if (0 == status) - return IRQ_HANDLED; - - if (status & IRQM_ADC_ABOUT_CNT) { /* sample count -> read FIFO */ - /* since the priority interrupt controller may have queued a sample - counter interrupt, even though we have already finished, - we must handle the possibility that there is no data here */ - if (!(fifoStatus & FS_ADC_HEMPTY)) { /* 0 -> 1/2 full */ - /*DPRINTK("rtd520: Sample int, reading 1/2FIFO. fifo_status 0x%x\n", - (fifoStatus ^ 0x6666) & 0x7777); */ - if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) { - DPRINTK - ("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n", - devpriv->aiCount); - goto abortTransfer; - } - if (0 == devpriv->aiCount) { /* counted down */ - DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */ - goto transferDone; - } - comedi_event(dev, s); - } else if (devpriv->transCount > 0) { /* read often */ - /*DPRINTK("rtd520: Sample int, reading %d fifo_status 0x%x\n", - devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */ - if (fifoStatus & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */ - if (ai_read_n(dev, s, devpriv->transCount) < 0) { - DPRINTK - ("rtd520: comedi read buffer overflow (N) with %ld to go!\n", - devpriv->aiCount); - goto abortTransfer; - } - if (0 == devpriv->aiCount) { /* counted down */ - DPRINTK - ("rtd520: Samples Done (N). fifo_status was 0x%x\n", - (fifoStatus ^ 0x6666) & 0x7777); - goto transferDone; - } - comedi_event(dev, s); - } - } else { /* wait for 1/2 FIFO (old) */ - DPRINTK - ("rtd520: Sample int. Wait for 1/2. fifo_status 0x%x\n", - (fifoStatus ^ 0x6666) & 0x7777); - } - } else { - DPRINTK("rtd520: unknown interrupt source!\n"); - } - - if (0xffff & RtdInterruptOverrunStatus(dev)) { /* interrupt overrun */ - DPRINTK - ("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n", - devpriv->aiCount, 0xffff & RtdInterruptOverrunStatus(dev)); - goto abortTransfer; } - /* clear the interrupt */ - RtdInterruptClearMask(dev, status); - RtdInterruptClear(dev); - return IRQ_HANDLED; + /* BUG: start_src is ASSUMED to be TRIG_NOW */ + /* BUG? it seems like things are running before the "start" */ + RtdPacerStart(dev); /* Start PACER */ + return 0; +} -abortTransfer: - RtdAdcClearFifo(dev); /* clears full flag */ - s->async->events |= COMEDI_CB_ERROR; - devpriv->aiCount = 0; /* stop and don't transfer any more */ - /* fall into transferDone */ +/* + Stop a running data acquisition. +*/ +static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +{ + u16 status; -transferDone: RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */ RtdPacerStop(dev); /* Stop PACER */ RtdAdcConversionSource(dev, 0); /* software trigger only */ - RtdInterruptMask(dev, 0); /* mask out SAMPLE */ + RtdInterruptMask(dev, 0); + devpriv->aiCount = 0; /* stop and don't transfer any more */ #ifdef USE_DMA if (devpriv->flags & DMA0_ACTIVE) { RtdPlxInterruptWrite(dev, /* disable any more interrupts */ RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); abort_dma(dev, 0); devpriv->flags &= ~DMA0_ACTIVE; - /* if Using DMA, then we should have read everything by now */ - if (devpriv->aiCount > 0) { - DPRINTK("rtd520: Lost DMA data! %ld remain\n", - devpriv->aiCount); - } } #endif /* USE_DMA */ - - if (devpriv->aiCount > 0) { /* there shouldn't be anything left */ - fifoStatus = RtdFifoStatus(dev); - DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777); /* should read all 0s */ - ai_read_dregs(dev, s); /* read anything left in FIFO */ - } - - s->async->events |= COMEDI_CB_EOA; /* signal end to comedi */ - comedi_event(dev, s); - - /* clear the interrupt */ status = RtdInterruptStatus(dev); - RtdInterruptClearMask(dev, status); - RtdInterruptClear(dev); - - fifoStatus = RtdFifoStatus(dev); /* DEBUG */ DPRINTK - ("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n", - devpriv->intCount, status, - 0xffff & RtdInterruptOverrunStatus(dev)); - - return IRQ_HANDLED; -} - -#if 0 -/* - return the number of samples available -*/ -static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) -{ - /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */ - /* Not sure what to do if DMA is active */ - return s->async->buf_write_count - s->async->buf_read_count; + ("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n", + devpriv->intCount, status, + 0xffff & RtdInterruptOverrunStatus(dev)); + return 0; } -#endif /* - cmdtest tests a particular command to see if it is valid. - Using the cmdtest ioctl, a user can create a valid cmd - and then have it executed by the cmd ioctl (asyncronously). - - cmdtest returns 1,2,3,4 or 0, depending on which tests - the command passes. + Output one (or more) analog values to a single port as fast as possible. */ - -static int rtd_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) +static int rtd_ao_winsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) { - int err = 0; - int tmp; - - /* step 1: make sure trigger sources are trivially valid */ - - tmp = cmd->start_src; - cmd->start_src &= TRIG_NOW; - if (!cmd->start_src || tmp != cmd->start_src) - err++; - - tmp = cmd->scan_begin_src; - cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; - if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) - err++; - - - tmp = cmd->convert_src; - cmd->convert_src &= TRIG_TIMER | TRIG_EXT; - if (!cmd->convert_src || tmp != cmd->convert_src) - err++; - - - tmp = cmd->scan_end_src; - cmd->scan_end_src &= TRIG_COUNT; - if (!cmd->scan_end_src || tmp != cmd->scan_end_src) - err++; - - - tmp = cmd->stop_src; - cmd->stop_src &= TRIG_COUNT | TRIG_NONE; - if (!cmd->stop_src || tmp != cmd->stop_src) - err++; + int i; + int chan = CR_CHAN(insn->chanspec); + int range = CR_RANGE(insn->chanspec); + /* Configure the output range (table index matches the range values) */ + RtdDacRange(dev, chan, range); - if (err) - return 1; + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; ++i) { + int val = data[i] << 3; + int stat = 0; /* initialize to avoid bogus warning */ + int ii; - /* step 2: make sure trigger sources are unique - and mutually compatible */ - /* note that mutual compatibility is not an issue here */ - if (cmd->scan_begin_src != TRIG_TIMER && - cmd->scan_begin_src != TRIG_EXT) { - err++; - } - if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) - err++; + /* VERIFY: comedi range and offset conversions */ - if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) - err++; + if ((range > 1) /* bipolar */ + && (data[i] < 2048)) { + /* offset and sign extend */ + val = (((int)data[i]) - 2048) << 3; + } else { /* unipolor */ + val = data[i] << 3; + } - if (err) - return 2; + DPRINTK + ("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n", + chan, range, data[i], val); - /* step 3: make sure arguments are trivially compatible */ + /* a typical programming sequence */ + RtdDacFifoPut(dev, chan, val); /* put the value in */ + RtdDacUpdate(dev, chan); /* trigger the conversion */ - if (cmd->start_arg != 0) { - cmd->start_arg = 0; - err++; - } + devpriv->aoValue[chan] = data[i]; /* save for read back */ - if (cmd->scan_begin_src == TRIG_TIMER) { - /* Note: these are time periods, not actual rates */ - if (1 == cmd->chanlist_len) { /* no scanning */ - if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) { - cmd->scan_begin_arg = RTD_MAX_SPEED_1; - rtd_ns_to_timer(&cmd->scan_begin_arg, - TRIG_ROUND_UP); - err++; - } - if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) { - cmd->scan_begin_arg = RTD_MIN_SPEED_1; - rtd_ns_to_timer(&cmd->scan_begin_arg, - TRIG_ROUND_DOWN); - err++; - } - } else { - if (cmd->scan_begin_arg < RTD_MAX_SPEED) { - cmd->scan_begin_arg = RTD_MAX_SPEED; - rtd_ns_to_timer(&cmd->scan_begin_arg, - TRIG_ROUND_UP); - err++; - } - if (cmd->scan_begin_arg > RTD_MIN_SPEED) { - cmd->scan_begin_arg = RTD_MIN_SPEED; - rtd_ns_to_timer(&cmd->scan_begin_arg, - TRIG_ROUND_DOWN); - err++; - } - } - } else { - /* external trigger */ - /* should be level/edge, hi/lo specification here */ - /* should specify multiple external triggers */ - if (cmd->scan_begin_arg > 9) { - cmd->scan_begin_arg = 9; - err++; - } - } - if (cmd->convert_src == TRIG_TIMER) { - if (1 == cmd->chanlist_len) { /* no scanning */ - if (cmd->convert_arg < RTD_MAX_SPEED_1) { - cmd->convert_arg = RTD_MAX_SPEED_1; - rtd_ns_to_timer(&cmd->convert_arg, - TRIG_ROUND_UP); - err++; - } - if (cmd->convert_arg > RTD_MIN_SPEED_1) { - cmd->convert_arg = RTD_MIN_SPEED_1; - rtd_ns_to_timer(&cmd->convert_arg, - TRIG_ROUND_DOWN); - err++; - } - } else { - if (cmd->convert_arg < RTD_MAX_SPEED) { - cmd->convert_arg = RTD_MAX_SPEED; - rtd_ns_to_timer(&cmd->convert_arg, - TRIG_ROUND_UP); - err++; - } - if (cmd->convert_arg > RTD_MIN_SPEED) { - cmd->convert_arg = RTD_MIN_SPEED; - rtd_ns_to_timer(&cmd->convert_arg, - TRIG_ROUND_DOWN); - err++; - } + for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) { + stat = RtdFifoStatus(dev); + /* 1 -> not empty */ + if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY : + FS_DAC2_NOT_EMPTY)) + break; + WAIT_QUIETLY; } - } else { - /* external trigger */ - /* see above */ - if (cmd->convert_arg > 9) { - cmd->convert_arg = 9; - err++; + if (ii >= RTD_DAC_TIMEOUT) { + DPRINTK + ("rtd520: Error: DAC never finished! FifoStatus=0x%x\n", + stat ^ 0x6666); + return -ETIMEDOUT; } } -#if 0 - if (cmd->scan_end_arg != cmd->chanlist_len) { - cmd->scan_end_arg = cmd->chanlist_len; - err++; - } -#endif - if (cmd->stop_src == TRIG_COUNT) { - /* TODO check for rounding error due to counter wrap */ + /* return the number of samples read/written */ + return i; +} - } else { - /* TRIG_NONE */ - if (cmd->stop_arg != 0) { - cmd->stop_arg = 0; - err++; - } - } +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int rtd_ao_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); - if (err) - return 3; + for (i = 0; i < insn->n; i++) + data[i] = devpriv->aoValue[chan]; - /* step 4: fix up any arguments */ + return i; +} - if (cmd->chanlist_len > RTD_MAX_CHANLIST) { - cmd->chanlist_len = RTD_MAX_CHANLIST; - err++; - } - if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - rtd_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; +/* + Write a masked set of bits and the read back the port. + We track what the bits should be (i.e. we don't read the port first). - } - if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - rtd_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; + DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write + */ +static int rtd_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + if (insn->n != 2) + return -EINVAL; - if (cmd->scan_begin_src == TRIG_TIMER - && (cmd->scan_begin_arg - < (cmd->convert_arg * cmd->scan_end_arg))) { - cmd->scan_begin_arg = - cmd->convert_arg * cmd->scan_end_arg; - err++; - } + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + + /* Write out the new digital output lines */ + RtdDio0Write(dev, s->state); } + /* on return, data[1] contains the value of the digital + * input lines. */ + data[1] = RtdDio0Read(dev); - if (err) - return 4; + /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */ - return 0; + return 2; } /* - Execute a analog in command with many possible triggering options. - The data get stored in the async structure of the subdevice. - This is usually done by an interrupt handler. - Userland gets to the data using read calls. + Configure one bit on a IO port as Input or Output (hence the name :-). */ -static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +static int rtd_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - struct comedi_cmd *cmd = &s->async->cmd; - int timer; - - /* stop anything currently running */ - RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */ - RtdPacerStop(dev); /* make sure PACER is stopped */ - RtdAdcConversionSource(dev, 0); /* software trigger only */ - RtdInterruptMask(dev, 0); -#ifdef USE_DMA - if (devpriv->flags & DMA0_ACTIVE) { /* cancel anything running */ - RtdPlxInterruptWrite(dev, /* disable any more interrupts */ - RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); - abort_dma(dev, 0); - devpriv->flags &= ~DMA0_ACTIVE; - if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) { /*clear pending int */ - RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT); - } - } - RtdDma0Reset(dev); /* reset onboard state */ -#endif /* USE_DMA */ - RtdAdcClearFifo(dev); /* clear any old data */ - RtdInterruptOverrunClear(dev); - devpriv->intCount = 0; - - if (!dev->irq) { /* we need interrupts for this */ - DPRINTK("rtd520: ERROR! No interrupt available!\n"); - return -ENXIO; - } - - /* start configuration */ - /* load channel list and reset CGT */ - rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist); + int chan = CR_CHAN(insn->chanspec); - /* setup the common case and override if needed */ - if (cmd->chanlist_len > 1) { - /*DPRINTK ("rtd520: Multi channel setup\n"); */ - RtdPacerStartSource(dev, 0); /* software triggers pacer */ - RtdBurstStartSource(dev, 1); /* PACER triggers burst */ - RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */ - } else { /* single channel */ - /*DPRINTK ("rtd520: single channel setup\n"); */ - RtdPacerStartSource(dev, 0); /* software triggers pacer */ - RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */ + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << chan; /* 1 means Out */ + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << chan); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; } - RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */ - if (TRIG_TIMER == cmd->scan_begin_src) { - /* scan_begin_arg is in nanoseconds */ - /* find out how many samples to wait before transferring */ - if (cmd->flags & TRIG_WAKE_EOS) { - /* this may generate un-sustainable interrupt rates */ - /* the application is responsible for doing the right thing */ - devpriv->transCount = cmd->chanlist_len; - devpriv->flags |= SEND_EOS; - } else { - /* arrange to transfer data periodically */ - devpriv->transCount - = - (TRANS_TARGET_PERIOD * cmd->chanlist_len) / - cmd->scan_begin_arg; - if (devpriv->transCount < cmd->chanlist_len) { - /* transfer after each scan (and avoid 0) */ - devpriv->transCount = cmd->chanlist_len; - } else { /* make a multiple of scan length */ - devpriv->transCount = - (devpriv->transCount + - cmd->chanlist_len - 1) - / cmd->chanlist_len; - devpriv->transCount *= cmd->chanlist_len; - } - devpriv->flags |= SEND_EOS; - } - if (devpriv->transCount >= (devpriv->fifoLen / 2)) { - /* out of counter range, use 1/2 fifo instead */ - devpriv->transCount = 0; - devpriv->flags &= ~SEND_EOS; - } else { - /* interrupt for each transfer */ - RtdAboutCounter(dev, devpriv->transCount - 1); - } + DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits); + /* TODO support digital match interrupts and strobes */ + RtdDioStatusWrite(dev, 0x01); /* make Dio0Ctrl point to direction */ + RtdDio0CtrlWrite(dev, s->io_bits); /* set direction 1 means Out */ + RtdDioStatusWrite(dev, 0); /* make Dio0Ctrl clear interrupts */ - DPRINTK - ("rtd520: scanLen=%d transferCount=%d fifoLen=%d\n scanTime(ns)=%d flags=0x%x\n", - cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen, - cmd->scan_begin_arg, devpriv->flags); - } else { /* unknown timing, just use 1/2 FIFO */ - devpriv->transCount = 0; - devpriv->flags &= ~SEND_EOS; - } - RtdPacerClockSource(dev, 1); /* use INTERNAL 8Mhz clock source */ - RtdAboutStopEnable(dev, 1); /* just interrupt, dont stop */ + /* port1 can only be all input or all output */ - /* BUG??? these look like enumerated values, but they are bit fields */ + /* there are also 2 user input lines and 2 user output lines */ - /* First, setup when to stop */ - switch (cmd->stop_src) { - case TRIG_COUNT: /* stop after N scans */ - devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len; - if ((devpriv->transCount > 0) - && (devpriv->transCount > devpriv->aiCount)) { - devpriv->transCount = devpriv->aiCount; - } - break; + return 1; +} - case TRIG_NONE: /* stop when cancel is called */ - devpriv->aiCount = -1; /* read forever */ - break; +static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ /* board name and options flags */ + struct comedi_subdevice *s; + struct pci_dev *pcidev; + int ret; + resource_size_t physLas0; /* configuration */ + resource_size_t physLas1; /* data area */ + resource_size_t physLcfg; /* PLX9080 */ +#ifdef USE_DMA + int index; +#endif - default: - DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n", - cmd->stop_src); - } + printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor); - /* Scan timing */ - switch (cmd->scan_begin_src) { - case TRIG_TIMER: /* periodic scanning */ - timer = rtd_ns_to_timer(&cmd->scan_begin_arg, - TRIG_ROUND_NEAREST); - /* set PACER clock */ - /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */ - RtdPacerCounter(dev, timer); +#if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA) + /* You can set this a load time: modprobe comedi comedi_debug=1 */ + if (0 == comedi_debug) /* force DMA debug printks */ + comedi_debug = 1; +#endif - break; + /* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0) + return -ENOMEM; - case TRIG_EXT: - RtdPacerStartSource(dev, 1); /* EXTERNALy trigger pacer */ - break; + /* + * Probe the device to determine what device in the series it is. + */ + for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) { + int i; - default: - DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n", - cmd->scan_begin_src); + if (it->options[0] || it->options[1]) { + if (pcidev->bus->number != it->options[0] + || PCI_SLOT(pcidev->devfn) != it->options[1]) { + continue; + } + } + for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i) { + if (pcidev->device == rtd520Boards[i].device_id) { + dev->board_ptr = &rtd520Boards[i]; + break; + } + } + if (dev->board_ptr) + break; /* found one */ } - - /* Sample timing within a scan */ - switch (cmd->convert_src) { - case TRIG_TIMER: /* periodic */ - if (cmd->chanlist_len > 1) { /* only needed for multi-channel */ - timer = rtd_ns_to_timer(&cmd->convert_arg, - TRIG_ROUND_NEAREST); - /* setup BURST clock */ - /*DPRINTK ("rtd520: loading %d into burst\n", timer); */ - RtdBurstCounter(dev, timer); + if (!pcidev) { + if (it->options[0] && it->options[1]) { + printk(KERN_INFO "No RTD card at bus=%d slot=%d.\n", + it->options[0], it->options[1]); + } else { + printk(KERN_INFO "No RTD card found.\n"); } + return -EIO; + } + devpriv->pci_dev = pcidev; + dev->board_name = thisboard->name; - break; - - case TRIG_EXT: /* external */ - RtdBurstStartSource(dev, 2); /* EXTERNALy trigger burst */ - break; - - default: - DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n", - cmd->convert_src); + ret = comedi_pci_enable(pcidev, DRV_NAME); + if (ret < 0) { + printk(KERN_INFO "Failed to enable PCI device and request regions.\n"); + return ret; } - /* end configuration */ + devpriv->got_regions = 1; - /* This doesn't seem to work. There is no way to clear an interrupt - that the priority controller has queued! */ - RtdInterruptClearMask(dev, ~0); /* clear any existing flags */ - RtdInterruptClear(dev); + /* + * Initialize base addresses + */ + /* Get the physical address from PCI config */ + physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX); + physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX); + physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX); + /* Now have the kernel map this into memory */ + /* ASSUME page aligned */ + devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE); + devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); + devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); - /* TODO: allow multiple interrupt sources */ - if (devpriv->transCount > 0) { /* transfer every N samples */ - RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT); - DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount); - } else { /* 1/2 FIFO transfers */ -#ifdef USE_DMA - devpriv->flags |= DMA0_ACTIVE; + if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) + return -ENOMEM; - /* point to first transfer in ring */ - devpriv->dma0Offset = 0; - RtdDma0Mode(dev, DMA_MODE_BITS); - RtdDma0Next(dev, /* point to first block */ - devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next); - RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */ - RtdPlxInterruptWrite(dev, /* enable interrupt */ - RtdPlxInterruptRead(dev) | ICS_DMA0_E); - /* Must be 2 steps. See PLX app note about "Starting a DMA transfer" */ - RtdDma0Control(dev, PLX_DMA_EN_BIT); /* enable DMA (clear INTR?) */ - RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT); /*start DMA */ - DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n", - RtdPlxInterruptRead(dev), devpriv->intMask); -#else /* USE_DMA */ - RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT); - DPRINTK("rtd520: Transferring every 1/2 FIFO\n"); -#endif /* USE_DMA */ - } + DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name, + (unsigned long long)physLas0, (unsigned long long)physLas1, + (unsigned long long)physLcfg); + { /* The RTD driver does this */ + unsigned char pci_latency; + u16 revision; + /*uint32_t epld_version; */ - /* BUG: start_src is ASSUMED to be TRIG_NOW */ - /* BUG? it seems like things are running before the "start" */ - RtdPacerStart(dev); /* Start PACER */ - return 0; -} + pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID, + &revision); + DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision); -/* - Stop a running data acquisition. -*/ -static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) -{ - u16 status; + pci_read_config_byte(devpriv->pci_dev, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < 32) { + printk(KERN_INFO "%s: PCI latency changed from %d to %d\n", + dev->board_name, pci_latency, 32); + pci_write_config_byte(devpriv->pci_dev, + PCI_LATENCY_TIMER, 32); + } else { + DPRINTK("rtd520: PCI latency = %d\n", pci_latency); + } - RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */ - RtdPacerStop(dev); /* Stop PACER */ - RtdAdcConversionSource(dev, 0); /* software trigger only */ - RtdInterruptMask(dev, 0); - devpriv->aiCount = 0; /* stop and don't transfer any more */ -#ifdef USE_DMA - if (devpriv->flags & DMA0_ACTIVE) { - RtdPlxInterruptWrite(dev, /* disable any more interrupts */ - RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); - abort_dma(dev, 0); - devpriv->flags &= ~DMA0_ACTIVE; + /* + * Undocumented EPLD version (doesn't match RTD driver results) + */ + /*DPRINTK ("rtd520: Reading epld from %p\n", + devpriv->las0+0); + epld_version = readl (devpriv->las0+0); + if ((epld_version & 0xF0) >> 4 == 0x0F) { + DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version); + } else { + DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4); + } */ } -#endif /* USE_DMA */ - status = RtdInterruptStatus(dev); - DPRINTK - ("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n", - devpriv->intCount, status, - 0xffff & RtdInterruptOverrunStatus(dev)); - return 0; -} -/* - Given a desired period and the clock period (both in ns), - return the proper counter value (divider-1). - Sets the original period to be the true value. - Note: you have to check if the value is larger than the counter range! -*/ -static int rtd_ns_to_timer_base(unsigned int *nanosec, /* desired period (in ns) */ - int round_mode, int base) -{ /* clock period (in ns) */ - int divider; + /* Show board configuration */ + printk(KERN_INFO "%s:", dev->board_name); - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - divider = (*nanosec + base / 2) / base; - break; - case TRIG_ROUND_DOWN: - divider = (*nanosec) / base; - break; - case TRIG_ROUND_UP: - divider = (*nanosec + base - 1) / base; - break; - } - if (divider < 2) - divider = 2; /* min is divide by 2 */ + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; - /* Note: we don't check for max, because different timers - have different ranges */ - *nanosec = base * divider; - return divider - 1; /* countdown is divisor+1 */ -} + s = dev->subdevices + 0; + dev->read_subdev = s; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = + SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ; + s->n_chan = thisboard->aiChans; + s->maxdata = (1 << thisboard->aiBits) - 1; + if (thisboard->aiMaxGain <= 32) + s->range_table = &rtd_ai_7520_range; + else + s->range_table = &rtd_ai_4520_range; -/* - Given a desired period (in ns), - return the proper counter value (divider-1) for the internal clock. - Sets the original period to be the true value. -*/ -static int rtd_ns_to_timer(unsigned int *ns, int round_mode) -{ - return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE); -} + s->len_chanlist = RTD_MAX_CHANLIST; /* devpriv->fifoLen */ + s->insn_read = rtd_ai_rinsn; + s->do_cmd = rtd_ai_cmd; + s->do_cmdtest = rtd_ai_cmdtest; + s->cancel = rtd_ai_cancel; + /* s->poll = rtd_ai_poll; *//* not ready yet */ -/* - Output one (or more) analog values to a single port as fast as possible. -*/ -static int rtd_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - int i; - int chan = CR_CHAN(insn->chanspec); - int range = CR_RANGE(insn->chanspec); + s = dev->subdevices + 1; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = (1 << thisboard->aiBits) - 1; + s->range_table = &rtd_ao_range; + s->insn_write = rtd_ao_winsn; + s->insn_read = rtd_ao_rinsn; - /* Configure the output range (table index matches the range values) */ - RtdDacRange(dev, chan, range); + s = dev->subdevices + 2; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + /* we only support port 0 right now. Ignoring port 1 and user IO */ + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = rtd_dio_insn_bits; + s->insn_config = rtd_dio_insn_config; - /* Writing a list of values to an AO channel is probably not - * very useful, but that's how the interface is defined. */ - for (i = 0; i < insn->n; ++i) { - int val = data[i] << 3; - int stat = 0; /* initialize to avoid bogus warning */ - int ii; + /* timer/counter subdevices (not currently supported) */ + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 3; + s->maxdata = 0xffff; - /* VERIFY: comedi range and offset conversions */ + /* initialize board, per RTD spec */ + /* also, initialize shadow registers */ + RtdResetBoard(dev); + udelay(100); /* needed? */ + RtdPlxInterruptWrite(dev, 0); + RtdInterruptMask(dev, 0); /* and sets shadow */ + RtdInterruptClearMask(dev, ~0); /* and sets shadow */ + RtdInterruptClear(dev); /* clears bits set by mask */ + RtdInterruptOverrunClear(dev); + RtdClearCGT(dev); + RtdAdcClearFifo(dev); + RtdDacClearFifo(dev, 0); + RtdDacClearFifo(dev, 1); + /* clear digital IO fifo */ + RtdDioStatusWrite(dev, 0); /* safe state, set shadow */ + RtdUtcCtrlPut(dev, 0, 0x30); /* safe state, set shadow */ + RtdUtcCtrlPut(dev, 1, 0x30); /* safe state, set shadow */ + RtdUtcCtrlPut(dev, 2, 0x30); /* safe state, set shadow */ + RtdUtcCtrlPut(dev, 3, 0); /* safe state, set shadow */ + /* TODO: set user out source ??? */ - if ((range > 1) /* bipolar */ - && (data[i] < 2048)) { - /* offset and sign extend */ - val = (((int)data[i]) - 2048) << 3; - } else { /* unipolor */ - val = data[i] << 3; - } + /* check if our interrupt is available and get it */ + ret = request_irq(devpriv->pci_dev->irq, rtd_interrupt, + IRQF_SHARED, DRV_NAME, dev); - DPRINTK - ("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n", - chan, range, data[i], val); + if (ret < 0) { + printk("Could not get interrupt! (%u)\n", + devpriv->pci_dev->irq); + return ret; + } + dev->irq = devpriv->pci_dev->irq; + printk(KERN_INFO "( irq=%u )", dev->irq); - /* a typical programming sequence */ - RtdDacFifoPut(dev, chan, val); /* put the value in */ - RtdDacUpdate(dev, chan); /* trigger the conversion */ + ret = rtd520_probe_fifo_depth(dev); + if (ret < 0) + return ret; - devpriv->aoValue[chan] = data[i]; /* save for read back */ + devpriv->fifoLen = ret; + printk("( fifoLen=%d )", devpriv->fifoLen); + +#ifdef USE_DMA + if (dev->irq > 0) { + printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT); + /* + * The PLX9080 has 2 DMA controllers, but there could be + * 4 sources: ADC, digital, DAC1, and DAC2. Since only the + * ADC supports cmd mode right now, this isn't an issue (yet) + */ + devpriv->dma0Offset = 0; - for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) { - stat = RtdFifoStatus(dev); - /* 1 -> not empty */ - if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY : - FS_DAC2_NOT_EMPTY)) - break; - WAIT_QUIETLY; + for (index = 0; index < DMA_CHAIN_COUNT; index++) { + devpriv->dma0Buff[index] = + pci_alloc_consistent(devpriv->pci_dev, + sizeof(u16) * + devpriv->fifoLen / 2, + &devpriv-> + dma0BuffPhysAddr[index]); + if (devpriv->dma0Buff[index] == NULL) { + ret = -ENOMEM; + goto rtd_attach_die_error; + } + /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n", + index, + devpriv->dma0Buff[index], + devpriv->dma0BuffPhysAddr[index]); */ } - if (ii >= RTD_DAC_TIMEOUT) { - DPRINTK - ("rtd520: Error: DAC never finished! FifoStatus=0x%x\n", - stat ^ 0x6666); - return -ETIMEDOUT; + + /* + * setup DMA descriptor ring (use cpu_to_le32 for byte + * ordering?) + */ + devpriv->dma0Chain = + pci_alloc_consistent(devpriv->pci_dev, + sizeof(struct plx_dma_desc) * + DMA_CHAIN_COUNT, + &devpriv->dma0ChainPhysAddr); + for (index = 0; index < DMA_CHAIN_COUNT; index++) { + devpriv->dma0Chain[index].pci_start_addr = + devpriv->dma0BuffPhysAddr[index]; + devpriv->dma0Chain[index].local_start_addr = + DMALADDR_ADC; + devpriv->dma0Chain[index].transfer_size = + sizeof(u16) * devpriv->fifoLen / 2; + devpriv->dma0Chain[index].next = + (devpriv->dma0ChainPhysAddr + ((index + + 1) % + (DMA_CHAIN_COUNT)) + * sizeof(devpriv->dma0Chain[0])) + | DMA_TRANSFER_BITS; + /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n", + index, + ((long)devpriv->dma0ChainPhysAddr + + (index * sizeof(devpriv->dma0Chain[0]))), + devpriv->dma0Chain[index].pci_start_addr, + devpriv->dma0Chain[index].local_start_addr, + devpriv->dma0Chain[index].transfer_size, + devpriv->dma0Chain[index].next); */ } - } - /* return the number of samples read/written */ - return i; -} + if (devpriv->dma0Chain == NULL) { + ret = -ENOMEM; + goto rtd_attach_die_error; + } -/* AO subdevices should have a read insn as well as a write insn. - * Usually this means copying a value stored in devpriv. */ -static int rtd_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - int i; - int chan = CR_CHAN(insn->chanspec); + RtdDma0Mode(dev, DMA_MODE_BITS); + /* set DMA trigger source */ + RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); + } else { + printk(KERN_INFO "( no IRQ->no DMA )"); + } +#endif /* USE_DMA */ - for (i = 0; i < insn->n; i++) - data[i] = devpriv->aoValue[chan]; + if (dev->irq) { /* enable plx9080 interrupts */ + RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); + } + printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor); - return i; -} + return 1; -/* - Write a masked set of bits and the read back the port. - We track what the bits should be (i.e. we don't read the port first). +#if 0 + /* hit an error, clean up memory and return ret */ +/* rtd_attach_die_error: */ +#ifdef USE_DMA + for (index = 0; index < DMA_CHAIN_COUNT; index++) { + if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */ + pci_free_consistent(devpriv->pci_dev, + sizeof(u16) * devpriv->fifoLen / 2, + devpriv->dma0Buff[index], + devpriv->dma0BuffPhysAddr[index]); + devpriv->dma0Buff[index] = NULL; + } + } + if (NULL != devpriv->dma0Chain) { + pci_free_consistent(devpriv->pci_dev, + sizeof(struct plx_dma_desc) + * DMA_CHAIN_COUNT, + devpriv->dma0Chain, + devpriv->dma0ChainPhysAddr); + devpriv->dma0Chain = NULL; + } +#endif /* USE_DMA */ + /* subdevices and priv are freed by the core */ + if (dev->irq) { + /* disable interrupt controller */ + RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) + & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E)); + free_irq(dev->irq, dev); + } - DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write - */ -static int rtd_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - if (insn->n != 2) - return -EINVAL; + /* release all regions that were allocated */ + if (devpriv->las0) + iounmap(devpriv->las0); - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + if (devpriv->las1) + iounmap(devpriv->las1); - /* Write out the new digital output lines */ - RtdDio0Write(dev, s->state); - } - /* on return, data[1] contains the value of the digital - * input lines. */ - data[1] = RtdDio0Read(dev); + if (devpriv->lcfg) + iounmap(devpriv->lcfg); - /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */ + if (devpriv->pci_dev) + pci_dev_put(devpriv->pci_dev); - return 2; + return ret; +#endif } -/* - Configure one bit on a IO port as Input or Output (hence the name :-). -*/ -static int rtd_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static void rtd_detach(struct comedi_device *dev) { - int chan = CR_CHAN(insn->chanspec); +#ifdef USE_DMA + int index; +#endif - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ - switch (data[0]) { - case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= 1 << chan; /* 1 means Out */ - break; - case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~(1 << chan); - break; - case INSN_CONFIG_DIO_QUERY: - data[1] = - (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; - return insn->n; - break; - default: - return -EINVAL; + if (devpriv) { + /* Shut down any board ops by resetting it */ +#ifdef USE_DMA + if (devpriv->lcfg) { + RtdDma0Control(dev, 0); /* disable DMA */ + RtdDma1Control(dev, 0); /* disable DMA */ + RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); + } +#endif /* USE_DMA */ + if (devpriv->las0) { + RtdResetBoard(dev); + RtdInterruptMask(dev, 0); + RtdInterruptClearMask(dev, ~0); + RtdInterruptClear(dev); /* clears bits set by mask */ + } +#ifdef USE_DMA + /* release DMA */ + for (index = 0; index < DMA_CHAIN_COUNT; index++) { + if (NULL != devpriv->dma0Buff[index]) { + pci_free_consistent(devpriv->pci_dev, + sizeof(u16) * + devpriv->fifoLen / 2, + devpriv->dma0Buff[index], + devpriv-> + dma0BuffPhysAddr[index]); + devpriv->dma0Buff[index] = NULL; + } + } + if (NULL != devpriv->dma0Chain) { + pci_free_consistent(devpriv->pci_dev, + sizeof(struct plx_dma_desc) * + DMA_CHAIN_COUNT, devpriv->dma0Chain, + devpriv->dma0ChainPhysAddr); + devpriv->dma0Chain = NULL; + } +#endif /* USE_DMA */ + if (dev->irq) { + RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) + & ~(ICS_PLIE | ICS_DMA0_E | + ICS_DMA1_E)); + free_irq(dev->irq, dev); + } + if (devpriv->las0) + iounmap(devpriv->las0); + if (devpriv->las1) + iounmap(devpriv->las1); + if (devpriv->lcfg) + iounmap(devpriv->lcfg); + if (devpriv->pci_dev) { + if (devpriv->got_regions) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } } - - DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits); - /* TODO support digital match interrupts and strobes */ - RtdDioStatusWrite(dev, 0x01); /* make Dio0Ctrl point to direction */ - RtdDio0CtrlWrite(dev, s->io_bits); /* set direction 1 means Out */ - RtdDioStatusWrite(dev, 0); /* make Dio0Ctrl clear interrupts */ - - /* port1 can only be all input or all output */ - - /* there are also 2 user input lines and 2 user output lines */ - - return 1; } static struct comedi_driver rtd520_driver = { -- GitLab From 73e183c347242c90524f8913f1af5fc481ad5370 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 May 2012 18:19:17 -0700 Subject: [PATCH 0207/5711] staging: comedi: das1800: complete the refactor to remove all forward declarations Complete the refactor of the das1800 driver to remove all the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das1800.c | 1242 +++++++++++----------- 1 file changed, 598 insertions(+), 644 deletions(-) diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 2ac344354c1d..079fb06de215 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -183,46 +183,6 @@ enum { das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao }; -static int das1800_probe(struct comedi_device *dev); -static int das1800_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); -static irqreturn_t das1800_interrupt(int irq, void *d); -static int das1800_ai_poll(struct comedi_device *dev, - struct comedi_subdevice *s); -static void das1800_ai_handler(struct comedi_device *dev); -static void das1800_handle_dma(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int status); -static void das1800_flush_dma(struct comedi_device *dev, - struct comedi_subdevice *s); -static void das1800_flush_dma_channel(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int channel, uint16_t *buffer); -static void das1800_handle_fifo_half_full(struct comedi_device *dev, - struct comedi_subdevice *s); -static void das1800_handle_fifo_not_empty(struct comedi_device *dev, - struct comedi_subdevice *s); -static int das1800_ai_do_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int das1800_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); -static int das1800_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das1800_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das1800_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das1800_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - -static int das1800_set_frequency(struct comedi_device *dev); -static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode); -static unsigned int suggest_transfer_size(struct comedi_cmd *cmd); - /* analog input ranges */ static const struct comedi_lrange range_ai_das1801 = { 8, @@ -515,421 +475,203 @@ static const struct comedi_lrange range_ao_2 = { }; */ -static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, - unsigned int dma1) +static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, + uint16_t sample) { - unsigned long flags; - - /* need an irq to do dma */ - if (dev->irq && dma0) { - /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ - switch ((dma0 & 0x7) | (dma1 << 4)) { - case 0x5: /* dma0 == 5 */ - devpriv->dma_bits |= DMA_CH5; - break; - case 0x6: /* dma0 == 6 */ - devpriv->dma_bits |= DMA_CH6; - break; - case 0x7: /* dma0 == 7 */ - devpriv->dma_bits |= DMA_CH7; - break; - case 0x65: /* dma0 == 5, dma1 == 6 */ - devpriv->dma_bits |= DMA_CH5_CH6; - break; - case 0x76: /* dma0 == 6, dma1 == 7 */ - devpriv->dma_bits |= DMA_CH6_CH7; - break; - case 0x57: /* dma0 == 7, dma1 == 5 */ - devpriv->dma_bits |= DMA_CH7_CH5; - break; - default: - dev_err(dev->hw_dev, " only supports dma channels 5 through 7\n" - " Dual dma only allows the following combinations:\n" - " dma 5,6 / 6,7 / or 7,5\n"); - return -EINVAL; - break; - } - if (request_dma(dma0, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", - dma0); - return -EINVAL; - } - devpriv->dma0 = dma0; - devpriv->dma_current = dma0; - if (dma1) { - if (request_dma(dma1, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", - dma1); - return -EINVAL; - } - devpriv->dma1 = dma1; - } - devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - devpriv->dma_current_buf = devpriv->ai_buf0; - if (dma1) { - devpriv->ai_buf1 = - kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf1 == NULL) - return -ENOMEM; - } - flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - set_dma_mode(devpriv->dma0, DMA_MODE_READ); - if (dma1) { - disable_dma(devpriv->dma1); - set_dma_mode(devpriv->dma1, DMA_MODE_READ); - } - release_dma_lock(flags); - } - return 0; + sample += 1 << (thisboard->resolution - 1); + return sample; } -static int das1800_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static void munge_data(struct comedi_device *dev, uint16_t * array, + unsigned int num_elements) { - struct comedi_subdevice *s; - unsigned long iobase = it->options[0]; - unsigned int irq = it->options[1]; - unsigned int dma0 = it->options[2]; - unsigned int dma1 = it->options[3]; - unsigned long iobase2; - int board; - int retval; + unsigned int i; + int unipolar; - /* allocate and initialize dev->private */ - if (alloc_private(dev, sizeof(struct das1800_private)) < 0) - return -ENOMEM; + /* see if card is using a unipolar or bipolar range so we can munge data correctly */ + unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; - printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor, - dev->driver->driver_name, iobase); - if (irq) { - printk(KERN_CONT ", irq %u", irq); - if (dma0) { - printk(KERN_CONT ", dma %u", dma0); - if (dma1) - printk(KERN_CONT " and %u", dma1); - } + /* convert to unsigned type if we are in a bipolar mode */ + if (!unipolar) { + for (i = 0; i < num_elements; i++) + array[i] = munge_bipolar_sample(dev, array[i]); } - printk(KERN_CONT "\n"); +} - if (iobase == 0) { - dev_err(dev->hw_dev, "io base address required\n"); - return -EINVAL; - } +static void das1800_handle_fifo_half_full(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + int numPoints = 0; /* number of points to read */ + struct comedi_cmd *cmd = &s->async->cmd; - /* check if io addresses are available */ - if (!request_region(iobase, DAS1800_SIZE, dev->driver->driver_name)) { - printk - (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", - iobase, iobase + DAS1800_SIZE - 1); - return -EIO; - } - dev->iobase = iobase; + numPoints = FIFO_SIZE / 2; + /* if we only need some of the points */ + if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) + numPoints = devpriv->count; + insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints); + munge_data(dev, devpriv->ai_buf0, numPoints); + cfc_write_array_to_buffer(s, devpriv->ai_buf0, + numPoints * sizeof(devpriv->ai_buf0[0])); + if (cmd->stop_src == TRIG_COUNT) + devpriv->count -= numPoints; + return; +} - board = das1800_probe(dev); - if (board < 0) { - dev_err(dev->hw_dev, "unable to determine board type\n"); - return -ENODEV; - } +static void das1800_handle_fifo_not_empty(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + short dpnt; + int unipolar; + struct comedi_cmd *cmd = &s->async->cmd; - dev->board_ptr = das1800_boards + board; - dev->board_name = thisboard->name; + unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; - /* if it is an 'ao' board with fancy analog out then we need extra io ports */ - if (thisboard->ao_ability == 2) { - iobase2 = iobase + IOBASE2; - if (!request_region(iobase2, DAS1800_SIZE, - dev->driver->driver_name)) { - printk - (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", - iobase2, iobase2 + DAS1800_SIZE - 1); - return -EIO; - } - devpriv->iobase2 = iobase2; + while (inb(dev->iobase + DAS1800_STATUS) & FNE) { + if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) + break; + dpnt = inw(dev->iobase + DAS1800_FIFO); + /* convert to unsigned type if we are in a bipolar mode */ + if (!unipolar) + ; + dpnt = munge_bipolar_sample(dev, dpnt); + cfc_write_to_buffer(s, dpnt); + if (cmd->stop_src == TRIG_COUNT) + devpriv->count--; } - /* grab our IRQ */ - if (irq) { - if (request_irq(irq, das1800_interrupt, 0, - dev->driver->driver_name, dev)) { - dev_dbg(dev->hw_dev, "unable to allocate irq %u\n", - irq); - return -EINVAL; - } - } - dev->irq = irq; + return; +} - /* set bits that tell card which irq to use */ - switch (irq) { - case 0: - break; - case 3: - devpriv->irq_dma_bits |= 0x8; - break; - case 5: - devpriv->irq_dma_bits |= 0x10; - break; - case 7: - devpriv->irq_dma_bits |= 0x18; - break; - case 10: - devpriv->irq_dma_bits |= 0x28; - break; - case 11: - devpriv->irq_dma_bits |= 0x30; - break; - case 15: - devpriv->irq_dma_bits |= 0x38; - break; - default: - dev_err(dev->hw_dev, "irq out of range\n"); - return -EINVAL; - break; - } +/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). + * Assumes dma lock is held */ +static void das1800_flush_dma_channel(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int channel, uint16_t *buffer) +{ + unsigned int num_bytes, num_samples; + struct comedi_cmd *cmd = &s->async->cmd; - retval = das1800_init_dma(dev, dma0, dma1); - if (retval < 0) - return retval; + disable_dma(channel); - if (devpriv->ai_buf0 == NULL) { - devpriv->ai_buf0 = - kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - } + /* clear flip-flop to make sure 2-byte registers + * get set correctly */ + clear_dma_ff(channel); - if (alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + /* figure out how many points to read */ + num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel); + num_samples = num_bytes / sizeof(short); - /* analog input subdevice */ - s = dev->subdevices + 0; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; - if (thisboard->common) - s->subdev_flags |= SDF_COMMON; - s->n_chan = thisboard->qram_len; - s->len_chanlist = thisboard->qram_len; - s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = thisboard->range_ai; - s->do_cmd = das1800_ai_do_cmd; - s->do_cmdtest = das1800_ai_do_cmdtest; - s->insn_read = das1800_ai_rinsn; - s->poll = das1800_ai_poll; - s->cancel = das1800_cancel; - - /* analog out */ - s = dev->subdevices + 1; - if (thisboard->ao_ability == 1) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_n_chan; - s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = &range_ao_1; - s->insn_write = das1800_ao_winsn; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + /* if we only need some of the points */ + if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples) + num_samples = devpriv->count; - /* di */ - s = dev->subdevices + 2; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = das1800_di_rbits; + munge_data(dev, buffer, num_samples); + cfc_write_array_to_buffer(s, buffer, num_bytes); + if (s->async->cmd.stop_src == TRIG_COUNT) + devpriv->count -= num_samples; - /* do */ - s = dev->subdevices + 3; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = thisboard->do_n_chan; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = das1800_do_wbits; + return; +} - das1800_cancel(dev, dev->read_subdev); +/* flushes remaining data from board when external trigger has stopped acquisition + * and we are using dma transfers */ +static void das1800_flush_dma(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned long flags; + const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - /* initialize digital out channels */ - outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + flags = claim_dma_lock(); + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); - /* initialize analog out channels */ - if (thisboard->ao_ability == 1) { - /* select 'update' dac channel for baseAddress + 0x0 */ - outb(DAC(thisboard->ao_n_chan - 1), - dev->iobase + DAS1800_SELECT); - outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); + if (dual_dma) { + /* switch to other channel and flush it */ + if (devpriv->dma_current == devpriv->dma0) { + devpriv->dma_current = devpriv->dma1; + devpriv->dma_current_buf = devpriv->ai_buf1; + } else { + devpriv->dma_current = devpriv->dma0; + devpriv->dma_current_buf = devpriv->ai_buf0; + } + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); } - return 0; -}; + release_dma_lock(flags); -static void das1800_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DAS1800_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->private) { - if (devpriv->iobase2) - release_region(devpriv->iobase2, DAS1800_SIZE); - if (devpriv->dma0) - free_dma(devpriv->dma0); - if (devpriv->dma1) - free_dma(devpriv->dma1); - kfree(devpriv->ai_buf0); - kfree(devpriv->ai_buf1); - } -}; + /* get any remaining samples in fifo */ + das1800_handle_fifo_not_empty(dev, s); -/* probes and checks das-1800 series board type - */ -static int das1800_probe(struct comedi_device *dev) + return; +} + +static void das1800_handle_dma(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int status) { - int id; - int board; + unsigned long flags; + const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */ - board = ((struct das1800_board *)dev->board_ptr) - das1800_boards; + flags = claim_dma_lock(); + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); + /* re-enable dma channel */ + set_dma_addr(devpriv->dma_current, + virt_to_bus(devpriv->dma_current_buf)); + set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_current); + release_dma_lock(flags); - switch (id) { - case 0x3: - if (board == das1801st_da || board == das1802st_da || - board == das1701st_da || board == das1702st_da) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800st-da series\n"); - return das1801st; - break; - case 0x4: - if (board == das1802hr_da || board == das1702hr_da) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1802hr-da\n"); - return das1802hr; - break; - case 0x5: - if (board == das1801ao || board == das1802ao || - board == das1701ao || board == das1702ao) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800ao series\n"); - return das1801ao; - break; - case 0x6: - if (board == das1802hr || board == das1702hr) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1802hr\n"); - return das1802hr; - break; - case 0x7: - if (board == das1801st || board == das1802st || - board == das1701st || board == das1702st) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800st series\n"); - return das1801st; - break; - case 0x8: - if (board == das1801hc || board == das1802hc) { - dev_dbg(dev->hw_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; + if (status & DMATC) { + /* clear DMATC interrupt bit */ + outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); + /* switch dma channels for next time, if appropriate */ + if (dual_dma) { + /* read data from the other channel next time */ + if (devpriv->dma_current == devpriv->dma0) { + devpriv->dma_current = devpriv->dma1; + devpriv->dma_current_buf = devpriv->ai_buf1; + } else { + devpriv->dma_current = devpriv->dma0; + devpriv->dma_current_buf = devpriv->ai_buf0; + } } - printk - (" Board model (probed, not recommended): das-1800hc series\n"); - return das1801hc; - break; - default: - printk - (" Board model: probe returned 0x%x (unknown, please report)\n", - id); - return board; - break; } - return -1; + + return; } -static int das1800_ai_poll(struct comedi_device *dev, - struct comedi_subdevice *s) +static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned long flags; - - /* prevent race with interrupt handler */ - spin_lock_irqsave(&dev->spinlock, flags); - das1800_ai_handler(dev); - spin_unlock_irqrestore(&dev->spinlock, flags); - - return s->async->buf_write_count - s->async->buf_read_count; + outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ + outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ + outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ + if (devpriv->dma0) + disable_dma(devpriv->dma0); + if (devpriv->dma1) + disable_dma(devpriv->dma1); + return 0; } -static irqreturn_t das1800_interrupt(int irq, void *d) +/* the guts of the interrupt handler, that is shared with das1800_ai_poll */ +static void das1800_ai_handler(struct comedi_device *dev) { - struct comedi_device *dev = d; - unsigned int status; + struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int status = inb(dev->iobase + DAS1800_STATUS); - if (dev->attached == 0) { - comedi_error(dev, "premature interrupt"); - return IRQ_HANDLED; - } - - /* Prevent race with das1800_ai_poll() on multi processor systems. - * Also protects indirect addressing in das1800_ai_handler */ - spin_lock(&dev->spinlock); - status = inb(dev->iobase + DAS1800_STATUS); - - /* if interrupt was not caused by das-1800 */ - if (!(status & INT)) { - spin_unlock(&dev->spinlock); - return IRQ_NONE; - } - /* clear the interrupt status bit INT */ - outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS); - /* handle interrupt */ - das1800_ai_handler(dev); - - spin_unlock(&dev->spinlock); - return IRQ_HANDLED; -} - -/* the guts of the interrupt handler, that is shared with das1800_ai_poll */ -static void das1800_ai_handler(struct comedi_device *dev) -{ - struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */ - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; - unsigned int status = inb(dev->iobase + DAS1800_STATUS); - - async->events = 0; - /* select adc for base address + 0 */ - outb(ADC, dev->iobase + DAS1800_SELECT); - /* dma buffer full */ - if (devpriv->irq_dma_bits & DMA_ENABLED) { - /* look for data from dma transfer even if dma terminal count hasn't happened yet */ - das1800_handle_dma(dev, s, status); - } else if (status & FHF) { /* if fifo half full */ - das1800_handle_fifo_half_full(dev, s); - } else if (status & FNE) { /* if fifo not empty */ - das1800_handle_fifo_not_empty(dev, s); + async->events = 0; + /* select adc for base address + 0 */ + outb(ADC, dev->iobase + DAS1800_SELECT); + /* dma buffer full */ + if (devpriv->irq_dma_bits & DMA_ENABLED) { + /* look for data from dma transfer even if dma terminal count hasn't happened yet */ + das1800_handle_dma(dev, s, status); + } else if (status & FHF) { /* if fifo half full */ + das1800_handle_fifo_half_full(dev, s); + } else if (status & FNE) { /* if fifo not empty */ + das1800_handle_fifo_not_empty(dev, s); } async->events |= COMEDI_CB_BLOCK; @@ -965,182 +707,75 @@ static void das1800_ai_handler(struct comedi_device *dev) return; } -static void das1800_handle_dma(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int status) +static int das1800_ai_poll(struct comedi_device *dev, + struct comedi_subdevice *s) { unsigned long flags; - const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - - flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); - /* re-enable dma channel */ - set_dma_addr(devpriv->dma_current, - virt_to_bus(devpriv->dma_current_buf)); - set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_current); - release_dma_lock(flags); - - if (status & DMATC) { - /* clear DMATC interrupt bit */ - outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); - /* switch dma channels for next time, if appropriate */ - if (dual_dma) { - /* read data from the other channel next time */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - } - } - return; -} + /* prevent race with interrupt handler */ + spin_lock_irqsave(&dev->spinlock, flags); + das1800_ai_handler(dev); + spin_unlock_irqrestore(&dev->spinlock, flags); -static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, - uint16_t sample) -{ - sample += 1 << (thisboard->resolution - 1); - return sample; + return s->async->buf_write_count - s->async->buf_read_count; } -static void munge_data(struct comedi_device *dev, uint16_t * array, - unsigned int num_elements) +static irqreturn_t das1800_interrupt(int irq, void *d) { - unsigned int i; - int unipolar; - - /* see if card is using a unipolar or bipolar range so we can munge data correctly */ - unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; + struct comedi_device *dev = d; + unsigned int status; - /* convert to unsigned type if we are in a bipolar mode */ - if (!unipolar) { - for (i = 0; i < num_elements; i++) - array[i] = munge_bipolar_sample(dev, array[i]); + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; } -} - -/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). - * Assumes dma lock is held */ -static void das1800_flush_dma_channel(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int channel, uint16_t *buffer) -{ - unsigned int num_bytes, num_samples; - struct comedi_cmd *cmd = &s->async->cmd; - - disable_dma(channel); - - /* clear flip-flop to make sure 2-byte registers - * get set correctly */ - clear_dma_ff(channel); - - /* figure out how many points to read */ - num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel); - num_samples = num_bytes / sizeof(short); - - /* if we only need some of the points */ - if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples) - num_samples = devpriv->count; - - munge_data(dev, buffer, num_samples); - cfc_write_array_to_buffer(s, buffer, num_bytes); - if (s->async->cmd.stop_src == TRIG_COUNT) - devpriv->count -= num_samples; - return; -} - -/* flushes remaining data from board when external trigger has stopped acquisition - * and we are using dma transfers */ -static void das1800_flush_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned long flags; - const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - - flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + /* Prevent race with das1800_ai_poll() on multi processor systems. + * Also protects indirect addressing in das1800_ai_handler */ + spin_lock(&dev->spinlock); + status = inb(dev->iobase + DAS1800_STATUS); - if (dual_dma) { - /* switch to other channel and flush it */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + /* if interrupt was not caused by das-1800 */ + if (!(status & INT)) { + spin_unlock(&dev->spinlock); + return IRQ_NONE; } + /* clear the interrupt status bit INT */ + outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS); + /* handle interrupt */ + das1800_ai_handler(dev); - release_dma_lock(flags); - - /* get any remaining samples in fifo */ - das1800_handle_fifo_not_empty(dev, s); - - return; -} - -static void das1800_handle_fifo_half_full(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - int numPoints = 0; /* number of points to read */ - struct comedi_cmd *cmd = &s->async->cmd; - - numPoints = FIFO_SIZE / 2; - /* if we only need some of the points */ - if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) - numPoints = devpriv->count; - insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints); - munge_data(dev, devpriv->ai_buf0, numPoints); - cfc_write_array_to_buffer(s, devpriv->ai_buf0, - numPoints * sizeof(devpriv->ai_buf0[0])); - if (cmd->stop_src == TRIG_COUNT) - devpriv->count -= numPoints; - return; + spin_unlock(&dev->spinlock); + return IRQ_HANDLED; } -static void das1800_handle_fifo_not_empty(struct comedi_device *dev, - struct comedi_subdevice *s) +/* converts requested conversion timing to timing compatible with + * hardware, used only when card is in 'burst mode' + */ +static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) { - short dpnt; - int unipolar; - struct comedi_cmd *cmd = &s->async->cmd; + unsigned int micro_sec; - unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; + /* in burst mode, the maximum conversion time is 64 microseconds */ + if (convert_arg > 64000) + convert_arg = 64000; - while (inb(dev->iobase + DAS1800_STATUS) & FNE) { - if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) - break; - dpnt = inw(dev->iobase + DAS1800_FIFO); - /* convert to unsigned type if we are in a bipolar mode */ - if (!unipolar) - ; - dpnt = munge_bipolar_sample(dev, dpnt); - cfc_write_to_buffer(s, dpnt); - if (cmd->stop_src == TRIG_COUNT) - devpriv->count--; + /* the conversion time must be an integral number of microseconds */ + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + micro_sec = (convert_arg + 500) / 1000; + break; + case TRIG_ROUND_DOWN: + micro_sec = convert_arg / 1000; + break; + case TRIG_ROUND_UP: + micro_sec = (convert_arg - 1) / 1000 + 1; + break; } - return; -} - -static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) -{ - outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ - outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ - outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ - if (devpriv->dma0) - disable_dma(devpriv->dma0); - if (devpriv->dma1) - disable_dma(devpriv->dma1); - return 0; + /* return number of nanoseconds */ + return micro_sec * 1000; } /* test analog input cmd */ @@ -1322,10 +957,6 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, return 0; } -/* analog input cmd interface */ - -/* first, some utility functions used in the main ai_do_cmd() */ - /* returns appropriate bits for control register a, depending on command */ static int control_a_bits(struct comedi_cmd cmd) { @@ -1396,15 +1027,34 @@ static int control_c_bits(struct comedi_cmd cmd) return control_c; } -/* sets up counters */ -static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) +/* loads counters with divisor1, divisor2 from private structure */ +static int das1800_set_frequency(struct comedi_device *dev) { - /* setup cascaded counters for conversion/scan frequency */ - switch (cmd.scan_begin_src) { - case TRIG_FOLLOW: /* not in burst mode */ - if (cmd.convert_src == TRIG_TIMER) { - /* set conversion frequency */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, + int err = 0; + + /* counter 1, mode 2 */ + if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1, + 2)) + err++; + /* counter 2, mode 2 */ + if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2, + 2)) + err++; + if (err) + return -1; + + return 0; +} + +/* sets up counters */ +static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) +{ + /* setup cascaded counters for conversion/scan frequency */ + switch (cmd.scan_begin_src) { + case TRIG_FOLLOW: /* not in burst mode */ + if (cmd.convert_src == TRIG_TIMER) { + /* set conversion frequency */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), &(devpriv->divisor2), &(cmd.convert_arg), @@ -1436,6 +1086,44 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) return 0; } +/* utility function that suggests a dma transfer size based on the conversion period 'ns' */ +static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) +{ + unsigned int size = DMA_BUF_SIZE; + static const int sample_size = 2; /* size in bytes of one sample from board */ + unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ + unsigned int max_size; /* maximum size we will allow for a transfer */ + + /* make dma buffer fill in 0.3 seconds for timed modes */ + switch (cmd->scan_begin_src) { + case TRIG_FOLLOW: /* not in burst mode */ + if (cmd->convert_src == TRIG_TIMER) + size = (fill_time / cmd->convert_arg) * sample_size; + break; + case TRIG_TIMER: + size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * + sample_size; + break; + default: + size = DMA_BUF_SIZE; + break; + } + + /* set a minimum and maximum size allowed */ + max_size = DMA_BUF_SIZE; + /* if we are taking limited number of conversions, limit transfer size to that */ + if (cmd->stop_src == TRIG_COUNT && + cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) + max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; + + if (size > max_size) + size = max_size; + if (size < sample_size) + size = sample_size; + + return size; +} + /* sets up dma */ static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd) { @@ -1689,91 +1377,357 @@ static int das1800_do_wbits(struct comedi_device *dev, return 2; } -/* loads counters with divisor1, divisor2 from private structure */ -static int das1800_set_frequency(struct comedi_device *dev) +static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, + unsigned int dma1) { - int err = 0; - - /* counter 1, mode 2 */ - if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1, - 2)) - err++; - /* counter 2, mode 2 */ - if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2, - 2)) - err++; - if (err) - return -1; + unsigned long flags; + /* need an irq to do dma */ + if (dev->irq && dma0) { + /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ + switch ((dma0 & 0x7) | (dma1 << 4)) { + case 0x5: /* dma0 == 5 */ + devpriv->dma_bits |= DMA_CH5; + break; + case 0x6: /* dma0 == 6 */ + devpriv->dma_bits |= DMA_CH6; + break; + case 0x7: /* dma0 == 7 */ + devpriv->dma_bits |= DMA_CH7; + break; + case 0x65: /* dma0 == 5, dma1 == 6 */ + devpriv->dma_bits |= DMA_CH5_CH6; + break; + case 0x76: /* dma0 == 6, dma1 == 7 */ + devpriv->dma_bits |= DMA_CH6_CH7; + break; + case 0x57: /* dma0 == 7, dma1 == 5 */ + devpriv->dma_bits |= DMA_CH7_CH5; + break; + default: + dev_err(dev->hw_dev, " only supports dma channels 5 through 7\n" + " Dual dma only allows the following combinations:\n" + " dma 5,6 / 6,7 / or 7,5\n"); + return -EINVAL; + break; + } + if (request_dma(dma0, dev->driver->driver_name)) { + dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", + dma0); + return -EINVAL; + } + devpriv->dma0 = dma0; + devpriv->dma_current = dma0; + if (dma1) { + if (request_dma(dma1, dev->driver->driver_name)) { + dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", + dma1); + return -EINVAL; + } + devpriv->dma1 = dma1; + } + devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf0 == NULL) + return -ENOMEM; + devpriv->dma_current_buf = devpriv->ai_buf0; + if (dma1) { + devpriv->ai_buf1 = + kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf1 == NULL) + return -ENOMEM; + } + flags = claim_dma_lock(); + disable_dma(devpriv->dma0); + set_dma_mode(devpriv->dma0, DMA_MODE_READ); + if (dma1) { + disable_dma(devpriv->dma1); + set_dma_mode(devpriv->dma1, DMA_MODE_READ); + } + release_dma_lock(flags); + } return 0; } -/* converts requested conversion timing to timing compatible with - * hardware, used only when card is in 'burst mode' - */ -static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) +static int das1800_probe(struct comedi_device *dev) { - unsigned int micro_sec; + int id; + int board; - /* in burst mode, the maximum conversion time is 64 microseconds */ - if (convert_arg > 64000) - convert_arg = 64000; + id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */ + board = ((struct das1800_board *)dev->board_ptr) - das1800_boards; - /* the conversion time must be an integral number of microseconds */ - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - micro_sec = (convert_arg + 500) / 1000; + switch (id) { + case 0x3: + if (board == das1801st_da || board == das1802st_da || + board == das1701st_da || board == das1702st_da) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1800st-da series\n"); + return das1801st; break; - case TRIG_ROUND_DOWN: - micro_sec = convert_arg / 1000; + case 0x4: + if (board == das1802hr_da || board == das1702hr_da) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1802hr-da\n"); + return das1802hr; break; - case TRIG_ROUND_UP: - micro_sec = (convert_arg - 1) / 1000 + 1; + case 0x5: + if (board == das1801ao || board == das1802ao || + board == das1701ao || board == das1702ao) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1800ao series\n"); + return das1801ao; + break; + case 0x6: + if (board == das1802hr || board == das1702hr) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1802hr\n"); + return das1802hr; + break; + case 0x7: + if (board == das1801st || board == das1802st || + board == das1701st || board == das1702st) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1800st series\n"); + return das1801st; + break; + case 0x8: + if (board == das1801hc || board == das1802hc) { + dev_dbg(dev->hw_dev, "Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk + (" Board model (probed, not recommended): das-1800hc series\n"); + return das1801hc; + break; + default: + printk + (" Board model: probe returned 0x%x (unknown, please report)\n", + id); + return board; break; } - - /* return number of nanoseconds */ - return micro_sec * 1000; + return -1; } -/* utility function that suggests a dma transfer size based on the conversion period 'ns' */ -static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) +static int das1800_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - unsigned int size = DMA_BUF_SIZE; - static const int sample_size = 2; /* size in bytes of one sample from board */ - unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ - unsigned int max_size; /* maximum size we will allow for a transfer */ + struct comedi_subdevice *s; + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + unsigned int dma0 = it->options[2]; + unsigned int dma1 = it->options[3]; + unsigned long iobase2; + int board; + int retval; - /* make dma buffer fill in 0.3 seconds for timed modes */ - switch (cmd->scan_begin_src) { - case TRIG_FOLLOW: /* not in burst mode */ - if (cmd->convert_src == TRIG_TIMER) - size = (fill_time / cmd->convert_arg) * sample_size; + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct das1800_private)) < 0) + return -ENOMEM; + + printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor, + dev->driver->driver_name, iobase); + if (irq) { + printk(KERN_CONT ", irq %u", irq); + if (dma0) { + printk(KERN_CONT ", dma %u", dma0); + if (dma1) + printk(KERN_CONT " and %u", dma1); + } + } + printk(KERN_CONT "\n"); + + if (iobase == 0) { + dev_err(dev->hw_dev, "io base address required\n"); + return -EINVAL; + } + + /* check if io addresses are available */ + if (!request_region(iobase, DAS1800_SIZE, dev->driver->driver_name)) { + printk + (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", + iobase, iobase + DAS1800_SIZE - 1); + return -EIO; + } + dev->iobase = iobase; + + board = das1800_probe(dev); + if (board < 0) { + dev_err(dev->hw_dev, "unable to determine board type\n"); + return -ENODEV; + } + + dev->board_ptr = das1800_boards + board; + dev->board_name = thisboard->name; + + /* if it is an 'ao' board with fancy analog out then we need extra io ports */ + if (thisboard->ao_ability == 2) { + iobase2 = iobase + IOBASE2; + if (!request_region(iobase2, DAS1800_SIZE, + dev->driver->driver_name)) { + printk + (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", + iobase2, iobase2 + DAS1800_SIZE - 1); + return -EIO; + } + devpriv->iobase2 = iobase2; + } + + /* grab our IRQ */ + if (irq) { + if (request_irq(irq, das1800_interrupt, 0, + dev->driver->driver_name, dev)) { + dev_dbg(dev->hw_dev, "unable to allocate irq %u\n", + irq); + return -EINVAL; + } + } + dev->irq = irq; + + /* set bits that tell card which irq to use */ + switch (irq) { + case 0: break; - case TRIG_TIMER: - size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * - sample_size; + case 3: + devpriv->irq_dma_bits |= 0x8; + break; + case 5: + devpriv->irq_dma_bits |= 0x10; + break; + case 7: + devpriv->irq_dma_bits |= 0x18; + break; + case 10: + devpriv->irq_dma_bits |= 0x28; + break; + case 11: + devpriv->irq_dma_bits |= 0x30; + break; + case 15: + devpriv->irq_dma_bits |= 0x38; break; default: - size = DMA_BUF_SIZE; + dev_err(dev->hw_dev, "irq out of range\n"); + return -EINVAL; break; } - /* set a minimum and maximum size allowed */ - max_size = DMA_BUF_SIZE; - /* if we are taking limited number of conversions, limit transfer size to that */ - if (cmd->stop_src == TRIG_COUNT && - cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) - max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; + retval = das1800_init_dma(dev, dma0, dma1); + if (retval < 0) + return retval; - if (size > max_size) - size = max_size; - if (size < sample_size) - size = sample_size; + if (devpriv->ai_buf0 == NULL) { + devpriv->ai_buf0 = + kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); + if (devpriv->ai_buf0 == NULL) + return -ENOMEM; + } - return size; -} + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + /* analog input subdevice */ + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; + if (thisboard->common) + s->subdev_flags |= SDF_COMMON; + s->n_chan = thisboard->qram_len; + s->len_chanlist = thisboard->qram_len; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = thisboard->range_ai; + s->do_cmd = das1800_ai_do_cmd; + s->do_cmdtest = das1800_ai_do_cmdtest; + s->insn_read = das1800_ai_rinsn; + s->poll = das1800_ai_poll; + s->cancel = das1800_cancel; + + /* analog out */ + s = dev->subdevices + 1; + if (thisboard->ao_ability == 1) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_n_chan; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = &range_ao_1; + s->insn_write = das1800_ao_winsn; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* di */ + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das1800_di_rbits; + + /* do */ + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = thisboard->do_n_chan; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das1800_do_wbits; + + das1800_cancel(dev, dev->read_subdev); + + /* initialize digital out channels */ + outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + + /* initialize analog out channels */ + if (thisboard->ao_ability == 1) { + /* select 'update' dac channel for baseAddress + 0x0 */ + outb(DAC(thisboard->ao_n_chan - 1), + dev->iobase + DAS1800_SELECT); + outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); + } + + return 0; +}; + +static void das1800_detach(struct comedi_device *dev) +{ + if (dev->iobase) + release_region(dev->iobase, DAS1800_SIZE); + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->private) { + if (devpriv->iobase2) + release_region(devpriv->iobase2, DAS1800_SIZE); + if (devpriv->dma0) + free_dma(devpriv->dma0); + if (devpriv->dma1) + free_dma(devpriv->dma1); + kfree(devpriv->ai_buf0); + kfree(devpriv->ai_buf1); + } +}; static struct comedi_driver das1800_driver = { .driver_name = "das1800", -- GitLab From 4b5c0f106e7eb588e904184d9bc16427111c486f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:11 +0100 Subject: [PATCH 0208/5711] staging: comedi: das08: Use IS_ENABLED() Change conditional compilation on kernel config options to use the IS_ENABLED() macro. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 50 +++++++++++--------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index f53e59776a37..d921bee3bbc3 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -60,17 +60,7 @@ #define DRV_NAME "das08" -#ifdef CONFIG_COMEDI_DAS08_ISA_MODULE -#define CONFIG_COMEDI_DAS08_ISA -#endif -#ifdef CONFIG_COMEDI_DAS08_PCI_MODULE -#define CONFIG_COMEDI_DAS08_PCI -#endif -#ifdef CONFIG_COMEDI_DAS08_CS_MODULE -#define CONFIG_COMEDI_DAS08_CS -#endif - -#if defined(CONFIG_COMEDI_DAS08_ISA) || defined(CONFIG_COMEDI_DAS08_PCI) +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) || IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) #define DO_COMEDI_DRIVER_REGISTER #endif @@ -173,7 +163,7 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) static int das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); @@ -270,7 +260,7 @@ static const int *const das08_gainlists[] = { #ifdef DO_COMEDI_DRIVER_REGISTER static const struct das08_board_struct das08_boards[] = { -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) { .name = "isa-das08", /* cio-das08.pdf */ .bustype = isa, @@ -460,8 +450,8 @@ static const struct das08_board_struct das08_boards[] = { .name = "das08-pga-g2", /* a KM board */ }, #endif -#endif /* CONFIG_COMEDI_DAS08_ISA */ -#ifdef CONFIG_COMEDI_DAS08_PCI +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */ +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) { .name = "das08", /* pci-das08 */ .id = PCI_DEVICE_ID_PCIDAS08, @@ -479,11 +469,11 @@ static const struct das08_board_struct das08_boards[] = { .i8254_offset = 4, .iosize = 8, }, -#endif /* CONFIG_COMEDI_DAS08_PCI */ +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ }; #endif /* DO_COMEDI_DRIVER_REGISTER */ -#ifdef CONFIG_COMEDI_DAS08_CS +#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { { .name = "pcm-das08", @@ -523,7 +513,7 @@ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { }; #endif -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) }, {0} @@ -638,7 +628,7 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, return 2; } -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) static int das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -650,7 +640,7 @@ static int das08jr_di_rbits(struct comedi_device *dev, } #endif -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) static int das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -667,7 +657,7 @@ static int das08jr_do_wbits(struct comedi_device *dev, } #endif -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) static int das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -704,7 +694,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev, * a different method to force an update. * */ -#ifdef CONFIG_COMEDI_DAS08_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) static int das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1006,7 +996,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; unsigned long iobase; -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) unsigned long pci_iobase = 0; struct pci_dev *pdev = NULL; #endif @@ -1016,7 +1006,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; printk(KERN_INFO "comedi%d: das08: ", dev->minor); -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) /* deal with a pci board */ if (thisboard->bustype == pci) { if (it->options[0] || it->options[1]) { @@ -1068,7 +1058,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); #endif } else -#endif /* CONFIG_COMEDI_DAS08_PCI */ +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ { iobase = it->options[0]; } @@ -1086,7 +1076,7 @@ void das08_common_detach(struct comedi_device *dev) if (dev->iobase) release_region(dev->iobase, thisboard->iosize); } -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) if (devpriv) { if (devpriv->pdev) { if (devpriv->pci_iobase) @@ -1099,7 +1089,7 @@ void das08_common_detach(struct comedi_device *dev) } EXPORT_SYMBOL_GPL(das08_common_detach); -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static int __devinit driver_das08_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { @@ -1127,7 +1117,7 @@ static int __init driver_das08_init_module(void) if (retval < 0) return retval; #endif -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) driver_das08_pci_driver.name = (char *)driver_das08.driver_name; retval = pci_register_driver(&driver_das08_pci_driver); #endif @@ -1136,7 +1126,7 @@ static int __init driver_das08_init_module(void) static void __exit driver_das08_cleanup_module(void) { -#ifdef CONFIG_COMEDI_DAS08_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) pci_unregister_driver(&driver_das08_pci_driver); #endif #ifdef DO_COMEDI_DRIVER_REGISTER @@ -1147,7 +1137,7 @@ static void __exit driver_das08_cleanup_module(void) module_init(driver_das08_init_module); module_exit(driver_das08_cleanup_module); -#ifdef CONFIG_COMEDI_DAS08_CS +#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) EXPORT_SYMBOL_GPL(das08_cs_boards); #endif -- GitLab From d60d9f34d37775fa64695a22b405e58ac3cda39c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:12 +0100 Subject: [PATCH 0209/5711] staging: comedi: das08: Move I/O resource (de)allocation. Don't deal with allocation and deallocation of I/O resources and PCI enabling/disabling in the exported functions das08_common_attach() and das08_common_detach(). Do it in das08_attach() and new function das08_detach() (which is now the comedi detach() hook for this driver). This keeps things more symmetrical. Callers of das08_common_attach() and das08_common_detach() are now responsible for allocation of their own I/O resources and enabling of their own devices. The only external caller of das08_common_attach() and das08_common_detach() is the das08_cs module, which looks after its own I/O resources. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 57 ++++++++++++-------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index d921bee3bbc3..c69df87c5751 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -861,12 +861,13 @@ static int das08_counter_config(struct comedi_device *dev, #ifdef DO_COMEDI_DRIVER_REGISTER static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static void das08_detach(struct comedi_device *dev); static struct comedi_driver driver_das08 = { .driver_name = DRV_NAME, .module = THIS_MODULE, .attach = das08_attach, - .detach = das08_common_detach, + .detach = das08_detach, .board_name = &das08_boards[0].name, .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct), .offset = sizeof(struct das08_board_struct), @@ -878,14 +879,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) struct comedi_subdevice *s; int ret; - /* allocate ioports for non-pcmcia, non-pci boards */ - if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { - printk(KERN_INFO " iobase 0x%lx\n", iobase); - if (!request_region(iobase, thisboard->iosize, DRV_NAME)) { - printk(KERN_ERR " I/O port conflict\n"); - return -EIO; - } - } dev->iobase = iobase; dev->board_name = thisboard->name; @@ -996,19 +989,15 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; unsigned long iobase; -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - unsigned long pci_iobase = 0; - struct pci_dev *pdev = NULL; -#endif ret = alloc_private(dev, sizeof(struct das08_private_struct)); if (ret < 0) return ret; printk(KERN_INFO "comedi%d: das08: ", dev->minor); -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - /* deal with a pci board */ - if (thisboard->bustype == pci) { + if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { + unsigned long pci_iobase = 0; + struct pci_dev *pdev = NULL; if (it->options[0] || it->options[1]) { printk("bus %i slot %i ", it->options[0], it->options[1]); @@ -1057,13 +1046,16 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Enable local interrupt 1 and pci interrupt */ outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); #endif - } else -#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ - { + } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && + (thisboard->bustype == isa || thisboard->bustype == pc104)) { iobase = it->options[0]; - } - printk(KERN_INFO "\n"); - + printk(KERN_INFO " iobase 0x%lx\n", iobase); + if (!request_region(iobase, thisboard->iosize, DRV_NAME)) { + printk(KERN_ERR " I/O port conflict\n"); + return -EIO; + } + } else + return -EIO; return das08_common_attach(dev, iobase); } #endif /* DO_COMEDI_DRIVER_REGISTER */ @@ -1072,22 +1064,27 @@ void das08_common_detach(struct comedi_device *dev) { if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 4); - if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { +} +EXPORT_SYMBOL_GPL(das08_common_detach); + +#ifdef DO_COMEDI_DRIVER_REGISTER +static void das08_detach(struct comedi_device *dev) +{ + das08_common_detach(dev); + if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && + (thisboard->bustype == isa || thisboard->bustype == pc104)) { if (dev->iobase) release_region(dev->iobase, thisboard->iosize); - } -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - if (devpriv) { - if (devpriv->pdev) { + } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && + thisboard->bustype == pci) { + if (devpriv && devpriv->pdev) { if (devpriv->pci_iobase) comedi_pci_disable(devpriv->pdev); - pci_dev_put(devpriv->pdev); } } -#endif } -EXPORT_SYMBOL_GPL(das08_common_detach); +#endif /* DO_COMEDI_DRIVER_REGISTER */ #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static int __devinit driver_das08_pci_probe(struct pci_dev *dev, -- GitLab From 1e576a5707c95a4fb5927d97ed21582a55f75a82 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:13 +0100 Subject: [PATCH 0210/5711] staging: comedi: das08: Use module_comedi_{pci_, }driver If PCI boards are supported, use the module_comedi_pci_driver() macro to register the module as a comedi driver and a PCI driver. Otherwise, if ISA (or PC/104) boards are supported, use the module_comedi_driver() macro to register the module as a comedi driver. Otherwise, this is only a helper module for an external comedi driver (das08_cs). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 46 +++++++++++--------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c69df87c5751..3e0c02122270 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -863,7 +863,7 @@ static int das08_counter_config(struct comedi_device *dev, static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it); static void das08_detach(struct comedi_device *dev); -static struct comedi_driver driver_das08 = { +static struct comedi_driver das08_driver = { .driver_name = DRV_NAME, .module = THIS_MODULE, .attach = das08_attach, @@ -1087,52 +1087,44 @@ static void das08_detach(struct comedi_device *dev) #endif /* DO_COMEDI_DRIVER_REGISTER */ #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) -static int __devinit driver_das08_pci_probe(struct pci_dev *dev, +static int __devinit das08_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &driver_das08); + return comedi_pci_auto_config(dev, &das08_driver); } -static void __devexit driver_das08_pci_remove(struct pci_dev *dev) +static void __devexit das08_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver driver_das08_pci_driver = { +static struct pci_driver das08_pci_driver = { .id_table = das08_pci_table, - .probe = &driver_das08_pci_probe, - .remove = __devexit_p(&driver_das08_pci_remove) + .name = DRV_NAME, + .probe = &das08_pci_probe, + .remove = __devexit_p(&das08_pci_remove) }; #endif /* CONFIG_COMEDI_DAS08_PCI */ -static int __init driver_das08_init_module(void) -{ - int retval = 0; - #ifdef DO_COMEDI_DRIVER_REGISTER - retval = comedi_driver_register(&driver_das08); - if (retval < 0) - return retval; -#endif #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - driver_das08_pci_driver.name = (char *)driver_das08.driver_name; - retval = pci_register_driver(&driver_das08_pci_driver); +module_comedi_pci_driver(das08_driver, das08_pci_driver); +#else +module_comedi_driver(das08_driver); #endif - return retval; +#else /* DO_COMEDI_DRIVER_REGISTER */ +static int __init das08_init(void) +{ + return 0; } -static void __exit driver_das08_cleanup_module(void) +static void __exit das08_exit(void) { -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - pci_unregister_driver(&driver_das08_pci_driver); -#endif -#ifdef DO_COMEDI_DRIVER_REGISTER - comedi_driver_unregister(&driver_das08); -#endif } -module_init(driver_das08_init_module); -module_exit(driver_das08_cleanup_module); +module_init(das08_init); +module_exit(das08_exit); +#endif /* DO_COMEDI_DRIVER_REGISTER */ #if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) EXPORT_SYMBOL_GPL(das08_cs_boards); -- GitLab From d8fdaea5c9cd422f87cf0257c191e030a54d71e2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:14 +0100 Subject: [PATCH 0211/5711] staging: comedi: das08: Remove forward function declarations. Moved some functions to avoid forward declarations. Moved a few other bits at the same time to keep EXPORT_SYMBOL{,_GPL}() close to the symbol being exported, and PCI table close to the code that refers to it. Changed whitespace in das08_board[] and das08_cs_board[] initializers. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 585 ++++++++++++------------- 1 file changed, 277 insertions(+), 308 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 3e0c02122270..901411e616d3 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -157,29 +157,6 @@ /* gainlist same as _pgx_ below */ -static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -static int das08jr_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das08jr_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das08jr_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int das08ao_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -#endif -static void i8254_set_mode_low(unsigned int base, int channel, - unsigned int mode); - static const struct comedi_lrange range_das08_pgl = { 9, { BIP_RANGE(10), BIP_RANGE(5), @@ -258,270 +235,6 @@ static const int *const das08_gainlists[] = { das08_pgm_gainlist, }; -#ifdef DO_COMEDI_DRIVER_REGISTER -static const struct das08_board_struct das08_boards[] = { -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) - { - .name = "isa-das08", /* cio-das08.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, - .ao = NULL, - .ao_nbits = 12, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 8, - .i8254_offset = 4, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-pgm", /* cio-das08pgx.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgm, - .ai_encoding = das08_encode12, - .ao = NULL, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-pgh", /* cio-das08pgx.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgh, - .ai_encoding = das08_encode12, - .ao = NULL, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-pgl", /* cio-das08pgx.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgl, - .ai_encoding = das08_encode12, - .ao = NULL, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-aoh", /* cio-das08_aox.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgh, - .ai_encoding = das08_encode12, - .ao = das08ao_ao_winsn, /* 8 */ - .ao_nbits = 12, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0x0c, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-aol", /* cio-das08_aox.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgl, - .ai_encoding = das08_encode12, - .ao = das08ao_ao_winsn, /* 8 */ - .ao_nbits = 12, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0x0c, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08-aom", /* cio-das08_aox.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pgm, - .ai_encoding = das08_encode12, - .ao = das08ao_ao_winsn, /* 8 */ - .ao_nbits = 12, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0x0c, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08/jr-ao", /* cio-das08-jr-ao.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, - .ao = das08jr_ao_winsn, - .ao_nbits = 12, - .di = das08jr_di_rbits, - .do_ = das08jr_do_wbits, - .do_nchan = 8, - .i8255_offset = 0, - .i8254_offset = 0, - .iosize = 16, /* unchecked */ - }, - { - .name = "das08jr-16-ao", /* cio-das08jr-16-ao.pdf */ - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 16, - .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, - .ao = das08jr_ao_winsn, - .ao_nbits = 16, - .di = das08jr_di_rbits, - .do_ = das08jr_do_wbits, - .do_nchan = 8, - .i8255_offset = 0, - .i8254_offset = 0x04, - .iosize = 16, /* unchecked */ - }, - { - .name = "pc104-das08", - .bustype = pc104, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, - .ao = NULL, - .ao_nbits = 0, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0, - .i8254_offset = 4, - .iosize = 16, /* unchecked */ - }, -#if 0 - { - .name = "das08/f", - }, - { - .name = "das08jr", - }, -#endif - { - .name = "das08jr/16", - .bustype = isa, - .ai = das08_ai_rinsn, - .ai_nbits = 16, - .ai_pg = das08_pg_none, - .ai_encoding = das08_encode16, - .ao = NULL, - .ao_nbits = 0, - .di = das08jr_di_rbits, - .do_ = das08jr_do_wbits, - .do_nchan = 8, - .i8255_offset = 0, - .i8254_offset = 0, - .iosize = 16, /* unchecked */ - }, -#if 0 - { - .name = "das48-pga", /* cio-das48-pga.pdf */ - }, - { - .name = "das08-pga-g2", /* a KM board */ - }, -#endif -#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */ -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) - { - .name = "das08", /* pci-das08 */ - .id = PCI_DEVICE_ID_PCIDAS08, - .bustype = pci, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_bipolar5, - .ai_encoding = das08_encode12, - .ao = NULL, - .ao_nbits = 0, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 4, - .i8255_offset = 0, - .i8254_offset = 4, - .iosize = 8, - }, -#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ -}; -#endif /* DO_COMEDI_DRIVER_REGISTER */ - -#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) -struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { - { - .name = "pcm-das08", - .id = 0x0, /* XXX */ - .bustype = pcmcia, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_bipolar5, - .ai_encoding = das08_pcm_encode12, - .ao = NULL, - .ao_nbits = 0, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 3, - .i8255_offset = 0, - .i8254_offset = 0, - .iosize = 16, - }, - /* duplicate so driver name can be used also */ - { - .name = "das08_cs", - .id = 0x0, /* XXX */ - .bustype = pcmcia, - .ai = das08_ai_rinsn, - .ai_nbits = 12, - .ai_pg = das08_bipolar5, - .ai_encoding = das08_pcm_encode12, - .ao = NULL, - .ao_nbits = 0, - .di = das08_di_rbits, - .do_ = das08_do_wbits, - .do_nchan = 3, - .i8255_offset = 0, - .i8254_offset = 0, - .iosize = 16, - }, -}; -#endif - -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) -static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, das08_pci_table); -#endif - #define devpriv ((struct das08_private_struct *)dev->private) #define thisboard ((const struct das08_board_struct *)dev->board_ptr) @@ -776,13 +489,6 @@ static void i8254_write_channel(struct i8254_struct *st, int channel, i8254_write_channel_low(st->iobase, chan, value); } -static void i8254_initialize(struct i8254_struct *st) -{ - int i; - for (i = 0; i < 3; ++i) - i8254_set_mode_low(st->iobase, i, st->mode[i]); -} - static void i8254_set_mode_low(unsigned int base, int channel, unsigned int mode) { @@ -811,6 +517,13 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel) return i8254_read_status_low(st->iobase, chan); } +static void i8254_initialize(struct i8254_struct *st) +{ + int i; + for (i = 0; i < 3; ++i) + i8254_set_mode_low(st->iobase, i, st->mode[i]); +} + static int das08_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -860,18 +573,259 @@ static int das08_counter_config(struct comedi_device *dev, } #ifdef DO_COMEDI_DRIVER_REGISTER -static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it); -static void das08_detach(struct comedi_device *dev); +static const struct das08_board_struct das08_boards[] = { +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) + { + .name = "isa-das08", /* cio-das08.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pg_none, + .ai_encoding = das08_encode12, + .ao = NULL, + .ao_nbits = 12, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 8, + .i8254_offset = 4, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-pgm", /* cio-das08pgx.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgm, + .ai_encoding = das08_encode12, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-pgh", /* cio-das08pgx.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgh, + .ai_encoding = das08_encode12, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-pgl", /* cio-das08pgx.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgl, + .ai_encoding = das08_encode12, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-aoh", /* cio-das08_aox.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgh, + .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ + .ao_nbits = 12, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0x0c, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-aol", /* cio-das08_aox.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgl, + .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ + .ao_nbits = 12, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0x0c, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08-aom", /* cio-das08_aox.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pgm, + .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ + .ao_nbits = 12, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0x0c, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08/jr-ao", /* cio-das08-jr-ao.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pg_none, + .ai_encoding = das08_encode12, + .ao = das08jr_ao_winsn, + .ao_nbits = 12, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, + .do_nchan = 8, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, /* unchecked */ + }, + { + .name = "das08jr-16-ao", /* cio-das08jr-16-ao.pdf */ + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 16, + .ai_pg = das08_pg_none, + .ai_encoding = das08_encode12, + .ao = das08jr_ao_winsn, + .ao_nbits = 16, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, + .do_nchan = 8, + .i8255_offset = 0, + .i8254_offset = 0x04, + .iosize = 16, /* unchecked */ + }, + { + .name = "pc104-das08", + .bustype = pc104, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_pg_none, + .ai_encoding = das08_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0, + .i8254_offset = 4, + .iosize = 16, /* unchecked */ + }, +#if 0 + { + .name = "das08/f", + }, + { + .name = "das08jr", + }, +#endif + { + .name = "das08jr/16", + .bustype = isa, + .ai = das08_ai_rinsn, + .ai_nbits = 16, + .ai_pg = das08_pg_none, + .ai_encoding = das08_encode16, + .ao = NULL, + .ao_nbits = 0, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, + .do_nchan = 8, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, /* unchecked */ + }, +#if 0 + { + .name = "das48-pga", /* cio-das48-pga.pdf */ + }, + { + .name = "das08-pga-g2", /* a KM board */ + }, +#endif +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */ +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) + { + .name = "das08", /* pci-das08 */ + .id = PCI_DEVICE_ID_PCIDAS08, + .bustype = pci, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_bipolar5, + .ai_encoding = das08_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 4, + .i8255_offset = 0, + .i8254_offset = 4, + .iosize = 8, + }, +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ +}; +#endif /* DO_COMEDI_DRIVER_REGISTER */ -static struct comedi_driver das08_driver = { - .driver_name = DRV_NAME, - .module = THIS_MODULE, - .attach = das08_attach, - .detach = das08_detach, - .board_name = &das08_boards[0].name, - .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct), - .offset = sizeof(struct das08_board_struct), +#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) +struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { + { + .name = "pcm-das08", + .id = 0x0, /* XXX */ + .bustype = pcmcia, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_bipolar5, + .ai_encoding = das08_pcm_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 3, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, + }, + /* duplicate so driver name can be used also */ + { + .name = "das08_cs", + .id = 0x0, /* XXX */ + .bustype = pcmcia, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_bipolar5, + .ai_encoding = das08_pcm_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 3, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, + }, }; +EXPORT_SYMBOL_GPL(das08_cs_boards); #endif int das08_common_attach(struct comedi_device *dev, unsigned long iobase) @@ -1086,7 +1040,26 @@ static void das08_detach(struct comedi_device *dev) } #endif /* DO_COMEDI_DRIVER_REGISTER */ +#ifdef DO_COMEDI_DRIVER_REGISTER +static struct comedi_driver das08_driver = { + .driver_name = DRV_NAME, + .module = THIS_MODULE, + .attach = das08_attach, + .detach = das08_detach, + .board_name = &das08_boards[0].name, + .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct), + .offset = sizeof(struct das08_board_struct), +}; +#endif + #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) +static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) }, + {0} +}; + +MODULE_DEVICE_TABLE(pci, das08_pci_table); + static int __devinit das08_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { @@ -1126,10 +1099,6 @@ module_init(das08_init); module_exit(das08_exit); #endif /* DO_COMEDI_DRIVER_REGISTER */ -#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) -EXPORT_SYMBOL_GPL(das08_cs_boards); -#endif - MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -- GitLab From 33fba3b7841b0cf7565e4352a2bab69fc5f4288f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:15 +0100 Subject: [PATCH 0212/5711] staging: comedi: das08: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. Some of the printk strings were missing newlines on the end. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 30 ++++++++++---------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 901411e616d3..680384c8e099 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -274,7 +274,7 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, /* clear over-range bits for 16-bit boards */ if (thisboard->ai_nbits == 16) if (inb(dev->iobase + DAS08_MSB) & 0x80) - printk(KERN_INFO "das08: over-range\n"); + dev_info(dev->class_dev, "over-range\n"); /* trigger conversion */ outb_p(0, dev->iobase + DAS08_TRIG_12BIT); @@ -284,7 +284,7 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, break; } if (i == TIMEOUT) { - printk(KERN_ERR "das08: timeout\n"); + dev_err(dev->class_dev, "timeout\n"); return -ETIME; } msb = inb(dev->iobase + DAS08_MSB); @@ -529,11 +529,7 @@ static int das08_counter_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int chan = insn->chanspec; - - /* printk("Reading counter channel %d ",chan); */ data[0] = i8254_read_channel(&devpriv->i8254, chan); - /* printk("=> 0x%08X\n",data[0]); */ - return 1; } @@ -542,10 +538,7 @@ static int das08_counter_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int chan = insn->chanspec; - - /* printk("Writing counter channel %d with 0x%04X\n",chan,data[0]); */ i8254_write_channel(&devpriv->i8254, chan, data[0]); - return 1; } @@ -948,15 +941,14 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - printk(KERN_INFO "comedi%d: das08: ", dev->minor); + dev_info(dev->class_dev, "attach\n"); if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { unsigned long pci_iobase = 0; struct pci_dev *pdev = NULL; if (it->options[0] || it->options[1]) { - printk("bus %i slot %i ", + dev_info(dev->class_dev, "pci bus %i slot %i\n", it->options[0], it->options[1]); } - printk("\n"); /* find card */ for_each_pci_dev(pdev) { if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS @@ -973,21 +965,21 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } if (!pdev) { - printk(KERN_ERR "No pci das08 cards found\n"); + dev_err(dev->class_dev, "No pci das08 cards found\n"); return -EIO; } devpriv->pdev = pdev; /* enable PCI device and reserve I/O spaces */ if (comedi_pci_enable(pdev, DRV_NAME)) { - printk(KERN_ERR " Error enabling PCI device and " - "requesting regions\n"); + dev_err(dev->class_dev, + "Error enabling PCI device and requesting regions\n"); return -EIO; } /* read base addresses */ pci_iobase = pci_resource_start(pdev, 1); iobase = pci_resource_start(pdev, 2); - printk(KERN_INFO "pcibase 0x%lx iobase 0x%lx\n", - pci_iobase, iobase); + dev_info(dev->class_dev, "pcibase 0x%lx iobase 0x%lx\n", + pci_iobase, iobase); devpriv->pci_iobase = pci_iobase; #if 0 /* We could enable to pci-das08's interrupt here to make it possible @@ -1003,9 +995,9 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && (thisboard->bustype == isa || thisboard->bustype == pc104)) { iobase = it->options[0]; - printk(KERN_INFO " iobase 0x%lx\n", iobase); + dev_info(dev->class_dev, "iobase 0x%lx\n", iobase); if (!request_region(iobase, thisboard->iosize, DRV_NAME)) { - printk(KERN_ERR " I/O port conflict\n"); + dev_err(dev->class_dev, "I/O port conflict\n"); return -EIO; } } else -- GitLab From 282f3528e21cd35f85e8ea3cb7dbcd285a6e5379 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:16 +0100 Subject: [PATCH 0213/5711] staging: comedi: das08: Remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 680384c8e099..8ebb56d9682e 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -235,14 +235,13 @@ static const int *const das08_gainlists[] = { das08_pgm_gainlist, }; -#define devpriv ((struct das08_private_struct *)dev->private) -#define thisboard ((const struct das08_board_struct *)dev->board_ptr) - #define TIMEOUT 100000 static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct das08_board_struct *thisboard = comedi_board(dev); + struct das08_private_struct *devpriv = dev->private; int i, n; int chan; int range; @@ -320,6 +319,7 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct das08_private_struct *devpriv = dev->private; int wbits; /* get current settings of digital output lines */ @@ -358,6 +358,8 @@ static int das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct das08_private_struct *devpriv = dev->private; + /* null bits we are going to set */ devpriv->do_bits &= ~data[0]; /* set new bit values */ @@ -528,6 +530,7 @@ static int das08_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; data[0] = i8254_read_channel(&devpriv->i8254, chan); return 1; @@ -537,6 +540,7 @@ static int das08_counter_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; i8254_write_channel(&devpriv->i8254, chan, data[0]); return 1; @@ -546,6 +550,7 @@ static int das08_counter_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; if (insn->n != 2) @@ -823,6 +828,8 @@ EXPORT_SYMBOL_GPL(das08_cs_boards); int das08_common_attach(struct comedi_device *dev, unsigned long iobase) { + const struct das08_board_struct *thisboard = comedi_board(dev); + struct das08_private_struct *devpriv = dev->private; struct comedi_subdevice *s; int ret; @@ -934,12 +941,15 @@ EXPORT_SYMBOL_GPL(das08_common_attach); #ifdef DO_COMEDI_DRIVER_REGISTER static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das08_board_struct *thisboard = comedi_board(dev); + struct das08_private_struct *devpriv; int ret; unsigned long iobase; ret = alloc_private(dev, sizeof(struct das08_private_struct)); if (ret < 0) return ret; + devpriv = dev->private; dev_info(dev->class_dev, "attach\n"); if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { @@ -1016,6 +1026,9 @@ EXPORT_SYMBOL_GPL(das08_common_detach); #ifdef DO_COMEDI_DRIVER_REGISTER static void das08_detach(struct comedi_device *dev) { + const struct das08_board_struct *thisboard = comedi_board(dev); + struct das08_private_struct *devpriv = dev->private; + das08_common_detach(dev); if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && (thisboard->bustype == isa || thisboard->bustype == pc104)) { -- GitLab From f86b0d7da3ab15f73723d98f6685d6d8ef48c166 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:17 +0100 Subject: [PATCH 0214/5711] staging: comedi: das08: Support multiple PCI card types in future Rename the existing board entry named "das08" for the PCI-DAS08 board to "pci-das08". Add a new wildcard board entry called "das08" that will match any supported PCI board. If 'dev->board_ptr' points to the wildcard board entry in the ->attach() routine, it will be replaced with a supported PCI board entry if there are any (taking into account the bus and slot specified by the device config options passed in to the function). Split the code that finds a matching PCI device into a new function das08_find_pci(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 96 +++++++++++++++++++------- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 8ebb56d9682e..7324461e3f27 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -32,7 +32,7 @@ * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), - * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08), + * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08 or das08), * PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16) * Status: works * @@ -765,7 +765,7 @@ static const struct das08_board_struct das08_boards[] = { #endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */ #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) { - .name = "das08", /* pci-das08 */ + .name = "pci-das08", /* pci-das08 */ .id = PCI_DEVICE_ID_PCIDAS08, .bustype = pci, .ai = das08_ai_rinsn, @@ -781,6 +781,11 @@ static const struct das08_board_struct das08_boards[] = { .i8254_offset = 4, .iosize = 8, }, + { /* wildcard entry matches any supported PCI device */ + .name = DRV_NAME, + .id = PCI_ANY_ID, + .bustype = pci, + }, #endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ }; #endif /* DO_COMEDI_DRIVER_REGISTER */ @@ -938,6 +943,66 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) } EXPORT_SYMBOL_GPL(das08_common_attach); +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) +static struct pci_dev *das08_find_pci(struct comedi_device *dev, + int bus, int slot) +{ + const struct das08_board_struct *thisboard = comedi_board(dev); + struct pci_dev *pdev; + unsigned int matchid; + + if (bus || slot) + dev_dbg(dev->class_dev, "Looking for %s at PCI %02X:%02X\n", + thisboard->name, bus, slot); + else + dev_dbg(dev->class_dev, "Looking for %s on PCI buses\n", + thisboard->name); + + matchid = thisboard->id; + pdev = NULL; + for_each_pci_dev(pdev) { + if ((bus || slot) && + (bus != pdev->bus->number || slot != PCI_SLOT(pdev->devfn))) + continue; + if (pdev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + if (matchid == PCI_ANY_ID) { + /* wildcard board matches any supported PCI board */ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(das08_boards); i++) { + if (das08_boards[i].bustype != pci) + continue; + if (pdev->device == das08_boards[i].id) { + /* replace wildcard board_ptr */ + dev->board_ptr = &das08_boards[i]; + thisboard = comedi_board(dev); + break; + } + } + if (i == ARRAY_SIZE(das08_boards)) + continue; + } else { + /* match specific PCI board */ + if (pdev->device != matchid) + continue; + } + /* found a match */ + dev_info(dev->class_dev, "Found %s at PCI %s\n", + thisboard->name, pci_name(pdev)); + return pdev; + } + /* no match found */ + if (bus || slot) + dev_err(dev->class_dev, + "No %s cards found at PCI %02X:%02X\n", + thisboard->name, bus, slot); + else + dev_err(dev->class_dev, "No %s cards found on PCI buses\n", + thisboard->name); + return NULL; +} +#endif + #ifdef DO_COMEDI_DRIVER_REGISTER static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) { @@ -954,30 +1019,11 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_info(dev->class_dev, "attach\n"); if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { unsigned long pci_iobase = 0; - struct pci_dev *pdev = NULL; - if (it->options[0] || it->options[1]) { - dev_info(dev->class_dev, "pci bus %i slot %i\n", - it->options[0], it->options[1]); - } - /* find card */ - for_each_pci_dev(pdev) { - if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS - && pdev->device == PCI_DEVICE_ID_PCIDAS08) { - if (it->options[0] || it->options[1]) { - if (pdev->bus->number == it->options[0] - && PCI_SLOT(pdev->devfn) == - it->options[1]) { - break; - } - } else { - break; - } - } - } - if (!pdev) { - dev_err(dev->class_dev, "No pci das08 cards found\n"); + struct pci_dev *pdev; + pdev = das08_find_pci(dev, it->options[0], it->options[1]); + if (pdev == NULL) return -EIO; - } + thisboard = comedi_board(dev); /* replaced wildcard board */ devpriv->pdev = pdev; /* enable PCI device and reserve I/O spaces */ if (comedi_pci_enable(pdev, DRV_NAME)) { -- GitLab From 8b7d417c406bafacedeae6cc3e110b11640d14e5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 24 May 2012 17:27:18 +0100 Subject: [PATCH 0215/5711] staging: comedi: das08: Add attach_pci() hook Implement the attach_pci() hook. This is called by comedi_pci_auto_config() in preference to the old attach() hook and avoids searching for the probed PCI device. Factor out some common code used by both the attach() and attach_pci() hooks into a couple of new functions, das08_pci_attach_common() and das08_find_pci_board(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 118 +++++++++++++++++-------- 1 file changed, 79 insertions(+), 39 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 7324461e3f27..fa2784d65569 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -943,6 +943,75 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) } EXPORT_SYMBOL_GPL(das08_common_attach); +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) +static int das08_pci_attach_common(struct comedi_device *dev, + struct pci_dev *pdev) +{ + unsigned long iobase; + unsigned long pci_iobase; + struct das08_private_struct *devpriv = dev->private; + + devpriv->pdev = pdev; + /* enable PCI device and reserve I/O spaces */ + if (comedi_pci_enable(pdev, dev->driver->driver_name)) { + dev_err(dev->class_dev, + "Error enabling PCI device and requesting regions\n"); + return -EIO; + } + /* read base addresses */ + pci_iobase = pci_resource_start(pdev, 1); + iobase = pci_resource_start(pdev, 2); + dev_info(dev->class_dev, "pcibase 0x%lx iobase 0x%lx\n", + pci_iobase, iobase); + devpriv->pci_iobase = pci_iobase; +#if 0 + /* We could enable pci-das08's interrupt here to make it possible + * to do timed input in this driver, but there is little point since + * conversions would have to be started by the interrupt handler + * so you might as well use comedi_rt_timer to emulate commands + */ + /* set source of interrupt trigger to counter2 output */ + outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL); + /* Enable local interrupt 1 and pci interrupt */ + outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); +#endif + return das08_common_attach(dev, iobase); +} +#endif + +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) +static const struct das08_board_struct * +das08_find_pci_board(struct pci_dev *pdev) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(das08_boards); i++) + if (das08_boards[i].bustype == pci && + pdev->device == das08_boards[i].id) + return &das08_boards[i]; + return NULL; +} +#endif + +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) +/* only called in the PCI probe path, via comedi_pci_auto_config() */ +static int __devinit das08_attach_pci(struct comedi_device *dev, + struct pci_dev *pdev) +{ + int ret; + + ret = alloc_private(dev, sizeof(struct das08_private_struct)); + if (ret < 0) + return ret; + dev_info(dev->class_dev, "attach pci %s\n", pci_name(pdev)); + dev->board_ptr = das08_find_pci_board(pdev); + if (dev->board_ptr == NULL) { + dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); + return -EINVAL; + } + return das08_pci_attach_common(dev, pdev); +} +#endif + #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static struct pci_dev *das08_find_pci(struct comedi_device *dev, int bus, int slot) @@ -968,19 +1037,12 @@ static struct pci_dev *das08_find_pci(struct comedi_device *dev, continue; if (matchid == PCI_ANY_ID) { /* wildcard board matches any supported PCI board */ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(das08_boards); i++) { - if (das08_boards[i].bustype != pci) - continue; - if (pdev->device == das08_boards[i].id) { - /* replace wildcard board_ptr */ - dev->board_ptr = &das08_boards[i]; - thisboard = comedi_board(dev); - break; - } - } - if (i == ARRAY_SIZE(das08_boards)) + const struct das08_board_struct *foundboard; + foundboard = das08_find_pci_board(pdev); + if (foundboard == NULL) continue; + /* replace wildcard board_ptr */ + dev->board_ptr = thisboard = foundboard; } else { /* match specific PCI board */ if (pdev->device != matchid) @@ -1018,36 +1080,11 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_info(dev->class_dev, "attach\n"); if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { - unsigned long pci_iobase = 0; struct pci_dev *pdev; pdev = das08_find_pci(dev, it->options[0], it->options[1]); if (pdev == NULL) return -EIO; - thisboard = comedi_board(dev); /* replaced wildcard board */ - devpriv->pdev = pdev; - /* enable PCI device and reserve I/O spaces */ - if (comedi_pci_enable(pdev, DRV_NAME)) { - dev_err(dev->class_dev, - "Error enabling PCI device and requesting regions\n"); - return -EIO; - } - /* read base addresses */ - pci_iobase = pci_resource_start(pdev, 1); - iobase = pci_resource_start(pdev, 2); - dev_info(dev->class_dev, "pcibase 0x%lx iobase 0x%lx\n", - pci_iobase, iobase); - devpriv->pci_iobase = pci_iobase; -#if 0 -/* We could enable to pci-das08's interrupt here to make it possible - * to do timed input in this driver, but there is little point since - * conversions would have to be started by the interrupt handler - * so you might as well use comedi_rt_timer to emulate commands - */ - /* set source of interrupt trigger to counter2 output */ - outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL); - /* Enable local interrupt 1 and pci interrupt */ - outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); -#endif + return das08_pci_attach_common(dev, pdev); } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && (thisboard->bustype == isa || thisboard->bustype == pc104)) { iobase = it->options[0]; @@ -1056,9 +1093,9 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_err(dev->class_dev, "I/O port conflict\n"); return -EIO; } + return das08_common_attach(dev, iobase); } else return -EIO; - return das08_common_attach(dev, iobase); } #endif /* DO_COMEDI_DRIVER_REGISTER */ @@ -1096,6 +1133,9 @@ static struct comedi_driver das08_driver = { .driver_name = DRV_NAME, .module = THIS_MODULE, .attach = das08_attach, +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) + .attach_pci = das08_attach_pci, +#endif .detach = das08_detach, .board_name = &das08_boards[0].name, .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct), -- GitLab From bc04bec0e0c982dfc90e206ea51f19bd650ccee2 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 27 May 2012 01:45:19 +0900 Subject: [PATCH 0216/5711] staging: comedi: Fix typo in comedi Correct spelling typo in comments within staging/comedi. Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas.c | 4 ++-- drivers/staging/comedi/drivers/das800.c | 2 +- drivers/staging/comedi/drivers/dyna_pci10xx.c | 2 +- drivers/staging/comedi/drivers/gsc_hpdi.c | 2 +- drivers/staging/comedi/drivers/icp_multi.c | 2 +- drivers/staging/comedi/drivers/usbduxsigma.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index f2135bfca290..3670ebdbcd81 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -299,7 +299,7 @@ struct pci9118_private { short *ai_data; short ao_data[2]; /* data output buffer */ unsigned int ai_scans; /* number of scans to do */ - char dma_doublebuf; /* we can use double buffring */ + char dma_doublebuf; /* we can use double buffering */ unsigned int dma_actbuf; /* which buffer is used now */ short *dmabuf_virt[2]; /* * pointers to begin of diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 7f88d08ee579..074feeef829b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -57,8 +57,8 @@ range and aref. AI Triggering: For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used. For 1602 series, the start_arg is interpreted as follows: - start_arg == 0 => gated triger (level high) - start_arg == CR_INVERT => gated triger (level low) + start_arg == 0 => gated trigger (level high) + start_arg == CR_INVERT => gated trigger (level low) start_arg == CR_EDGE => Rising edge start_arg == CR_EDGE | CR_INVERT => Falling edge For the other boards the trigger will be done on rising edge diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index a3a54e1c5c98..4e33b2a28d97 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -450,7 +450,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) /* otherwise, stop taking data */ } else { spin_unlock_irqrestore(&dev->spinlock, irq_flags); - disable_das800(dev); /* diable hardware triggered conversions */ + disable_das800(dev); /* disable hardware triggered conversions */ async->events |= COMEDI_CB_EOA; } comedi_event(dev, s); diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 9586f24ded73..367a7c88a0fd 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -141,7 +141,7 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev, for (counter = 0; counter < READ_TIMEOUT; counter++) { d = inw_p(devpriv->BADR2); - /* check if read is successfull if the EOC bit is set */ + /* check if read is successful if the EOC bit is set */ if (d & (1 << 15)) goto conv_finish; } diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index eeb05553e1a7..fe1fd2f75f0d 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -631,7 +631,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_WARNING " irq %u\n", dev->irq); - /* alocate pci dma buffers */ + /* allocate pci dma buffers */ for (i = 0; i < NUM_DMA_BUFFERS; i++) { priv(dev)->dio_buffer[i] = pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE, diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index f870d3da0324..1f254f480a66 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -835,7 +835,7 @@ static int icp_multi_attach(struct comedi_device *dev, printk(KERN_WARNING "icp_multi EDBG: BGN: icp_multi_attach(...)\n"); - /* Alocate private data storage space */ + /* Allocate private data storage space */ ret = alloc_private(dev, sizeof(struct icp_multi_private)); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 465afbdf4069..441ccef4c110 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1358,7 +1358,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, /* 32 bits big endian from the A/D converter */ one = be32_to_cpu(*((int32_t *) ((this_usbduxsub->insnBuffer)+1))); - /* mask out the staus byte */ + /* mask out the status byte */ one = one & 0x00ffffff; /* turn it into an unsigned integer */ one = one ^ 0x00800000; -- GitLab From 856ff77e3307eb89ba68e7cc3c1fa91112efff89 Mon Sep 17 00:00:00 2001 From: Dimitrios Semitsoglou-Tsiapos Date: Tue, 29 May 2012 00:51:44 +0300 Subject: [PATCH 0217/5711] staging: comedi: cb_pcidas64: Fixed coding style errors Fixed a few coding style errors in cb_pcidas64. Signed-off-by: Dimitrios Semitsoglou-Tsiapos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 1e30f227e98e..5bcadcb00c99 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1152,7 +1152,7 @@ static int eeprom_read_insn(struct comedi_device *dev, static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd); static unsigned int get_divisor(unsigned int ns, unsigned int flags); static void i2c_write(struct comedi_device *dev, unsigned int address, - const uint8_t * data, unsigned int length); + const uint8_t *data, unsigned int length); static void caldac_write(struct comedi_device *dev, unsigned int channel, unsigned int value); static int caldac_8800_write(struct comedi_device *dev, unsigned int address, @@ -1229,7 +1229,7 @@ static unsigned int hw_revision(const struct comedi_device *dev, } static void set_dac_range_bits(struct comedi_device *dev, - volatile uint16_t * bits, unsigned int channel, + volatile uint16_t *bits, unsigned int channel, unsigned int range) { unsigned int code = board(dev)->ao_range_code[range]; @@ -4190,7 +4190,7 @@ static void i2c_stop(struct comedi_device *dev) } static void i2c_write(struct comedi_device *dev, unsigned int address, - const uint8_t * data, unsigned int length) + const uint8_t *data, unsigned int length) { unsigned int i; uint8_t bitstream; -- GitLab From 5b28e55eb15f88920cd509332a22f80d72d55284 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 May 2012 15:30:18 -0700 Subject: [PATCH 0218/5711] staging: comedi: Make COMEDI_FC a hidden Kconfig option The COMEDI_FC Kconfig option is selected by the relevant drivers when needed. Since it only contains shared functions, selecting it manually serves no purpose. Just make it a hidden selection. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 3bbe3fd103f3..54e32da55c7c 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -1305,15 +1305,8 @@ config COMEDI_8255 called 8255. config COMEDI_FC - tristate "Comedi shared functions for low-level driver support" + tristate depends on COMEDI - ---help--- - Enable support for shared functions for low-level drivers. - This module is not used directly by end-users. Rather, it - is used by many other comedi drivers. - - To compile this driver as a module, choose M here: the module will be - called comedi_fc. config COMEDI_AMPLC_DIO200 tristate -- GitLab From 1364b02fbf6e2d298ff2428ace81f9c6517b4bd8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 31 May 2012 13:56:28 -0700 Subject: [PATCH 0219/5711] staging: comedi: drivers.c: remove unused inline functions Remove the inline functions uvirt_to_kva and kvirt_to_kva, they are not referenced by any of the drivers.c code. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 33 -------------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 438c52a313b1..9d2b206251ac 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -383,39 +383,6 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, return 1; } -static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - pud_t *pud; - - if (!pgd_none(*pgd)) { - pud = pud_offset(pgd, adr); - pmd = pmd_offset(pud, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset_kernel(pmd, adr); - pte = *ptep; - if (pte_present(pte)) { - ret = (unsigned long) - page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); - } - } - } - return ret; -} - -static inline unsigned long kvirt_to_kva(unsigned long adr) -{ - unsigned long va, kva; - - va = adr; - kva = uvirt_to_kva(pgd_offset_k(va), va); - - return kva; -} - int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { -- GitLab From 1bb6dfc407b7c29d22dc9b5d21db86f50653b46e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:28 +0100 Subject: [PATCH 0220/5711] staging: comedi: amplc_pc236: Use IS_ENABLED() Change conditional compilation on kernel config options to use the IS_ENABLED() macro. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 48 ++++++++------------ 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 6cb06ec1b30d..5f1caacbce13 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -61,14 +61,6 @@ unused. #define PC236_DRIVER_NAME "amplc_pc236" -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA_MODULE -#define CONFIG_COMEDI_AMPLC_PC236_ISA -#endif - -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI_MODULE -#define CONFIG_COMEDI_AMPLC_PC236_PCI -#endif - /* PCI236 PCI configuration register information */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009 @@ -112,7 +104,7 @@ struct pc236_board { enum pc236_model model; }; static const struct pc236_board pc236_boards[] = { -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) { .name = "pc36at", .fancy_name = "PC36AT", @@ -120,7 +112,7 @@ static const struct pc236_board pc236_boards[] = { .model = pc36at_model, }, #endif -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) { .name = "pci236", .fancy_name = "PCI236", @@ -138,7 +130,7 @@ static const struct pc236_board pc236_boards[] = { #endif }; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, {0} @@ -157,7 +149,7 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table); feel free to suggest moving the variable to the struct comedi_device struct. */ struct pc236_private { -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) /* PCI device */ struct pci_dev *pci_dev; unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ @@ -185,7 +177,7 @@ static struct comedi_driver driver_amplc_pc236 = { .num_names = ARRAY_SIZE(pc236_boards), }; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) @@ -240,7 +232,7 @@ module_init(driver_amplc_pc236_init_module); module_exit(driver_amplc_pc236_cleanup_module); #endif -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) static int pc236_request_region(unsigned minor, unsigned long from, unsigned long extent); #endif @@ -263,7 +255,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d); * This function looks for a PCI device matching the requested board name, * bus and slot. */ -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static int pc236_find_pci(struct comedi_device *dev, int bus, int slot, struct pci_dev **pci_dev_p) @@ -332,7 +324,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase = 0; unsigned int irq = 0; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) struct pci_dev *pci_dev = NULL; int bus = 0, slot = 0; #endif @@ -353,14 +345,14 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Process options. */ switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) case isa_bustype: iobase = it->options[0]; irq = it->options[1]; share_irq = 0; break; #endif -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) case pci_bustype: bus = it->options[0]; slot = it->options[1]; @@ -386,7 +378,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; /* Enable device and reserve I/O spaces. */ -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) if (pci_dev) { ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); @@ -402,7 +394,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) } else #endif { -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE); if (ret < 0) return ret; @@ -452,12 +444,12 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) } printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) case isa_bustype: printk("(base %#lx) ", iobase); break; #endif -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) case pci_bustype: printk("(pci %s) ", pci_name(pci_dev)); break; @@ -484,7 +476,7 @@ static void pc236_detach(struct comedi_device *dev) if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 0); if (devpriv) { -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) if (devpriv->pci_dev) { if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); @@ -492,7 +484,7 @@ static void pc236_detach(struct comedi_device *dev) } else #endif { -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) if (dev->iobase) release_region(dev->iobase, PC236_IO_SIZE); #endif @@ -504,7 +496,7 @@ static void pc236_detach(struct comedi_device *dev) * This function checks and requests an I/O region, reporting an error * if there is a conflict. */ -#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) static int pc236_request_region(unsigned minor, unsigned long from, unsigned long extent) { @@ -528,7 +520,7 @@ static void pc236_intr_disable(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 0; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) if (devpriv->lcr_iobase) outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR); #endif @@ -546,7 +538,7 @@ static void pc236_intr_enable(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 1; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) if (devpriv->lcr_iobase) outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR); #endif @@ -568,7 +560,7 @@ static int pc236_intr_check(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->enable_irq) { retval = 1; -#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) if (devpriv->lcr_iobase) { if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR) & PLX9052_INTCSR_LI1STAT_MASK) -- GitLab From c25386f5db48ee5d94b6ff3b1dc43ea6c87c9560 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:29 +0100 Subject: [PATCH 0221/5711] staging: comedi: amplc_pc236: Use module_comedi_{pci,}_driver() If PCI boards are supported, use the module_comedi_pci_driver() macro to register the module as a comedi driver and a PCI driver. Otherwise, only ISA boards are supported so use the module_comedi_driver() macro to register the module as a comedi driver. Renamed 'driver_amplc_pc236' to 'amplc_pc236_driver' and removed 'driver_' prefix from PCI related functions and variables, purely for aesthetic reasons. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 50 ++++---------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 5f1caacbce13..afd08f043403 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -167,7 +167,7 @@ struct pc236_private { */ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it); static void pc236_detach(struct comedi_device *dev); -static struct comedi_driver driver_amplc_pc236 = { +static struct comedi_driver amplc_pc236_driver = { .driver_name = PC236_DRIVER_NAME, .module = THIS_MODULE, .attach = pc236_attach, @@ -178,58 +178,28 @@ static struct comedi_driver driver_amplc_pc236 = { }; #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) -static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev, +static int __devinit amplc_pc236_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &driver_amplc_pc236); + return comedi_pci_auto_config(dev, &lc_pc236_driver); } -static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev) +static void __devexit amplc_pc236_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver driver_amplc_pc236_pci_driver = { +static struct pci_driver amplc_pc236_pci_driver = { + .name = PC236_DRIVER_NAME, .id_table = pc236_pci_table, - .probe = &driver_amplc_pc236_pci_probe, - .remove = __devexit_p(&driver_amplc_pc236_pci_remove) + .probe = &lc_pc236_pci_probe, + .remove = __devexit_p(&lc_pc236_pci_remove) }; -static int __init driver_amplc_pc236_init_module(void) -{ - int retval; - - retval = comedi_driver_register(&driver_amplc_pc236); - if (retval < 0) - return retval; - - driver_amplc_pc236_pci_driver.name = - (char *)driver_amplc_pc236.driver_name; - return pci_register_driver(&driver_amplc_pc236_pci_driver); -} - -static void __exit driver_amplc_pc236_cleanup_module(void) -{ - pci_unregister_driver(&driver_amplc_pc236_pci_driver); - comedi_driver_unregister(&driver_amplc_pc236); -} - -module_init(driver_amplc_pc236_init_module); -module_exit(driver_amplc_pc236_cleanup_module); +module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver); #else -static int __init driver_amplc_pc236_init_module(void) -{ - return comedi_driver_register(&driver_amplc_pc236); -} - -static void __exit driver_amplc_pc236_cleanup_module(void) -{ - comedi_driver_unregister(&driver_amplc_pc236); -} - -module_init(driver_amplc_pc236_init_module); -module_exit(driver_amplc_pc236_cleanup_module); +module_comedi_driver(amplc_pc236_driver); #endif #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) -- GitLab From 7bd06f69f3f52fcd04999790a2a9d66f1a8cd0c9 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:30 +0100 Subject: [PATCH 0222/5711] staging: comedi: amplc_pc236: Remove forward function declarations Moved some functions and variables to avoid forward declarations. Moved PCI table closer to the struct pci_driver that refers to it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 476 +++++++++---------- 1 file changed, 226 insertions(+), 250 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index afd08f043403..007b45bef7b0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -130,15 +130,6 @@ static const struct pc236_board pc236_boards[] = { #endif }; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) -static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, pc236_pci_table); -#endif /* CONFIG_COMEDI_AMPLC_PC236_PCI */ - /* * Useful for shorthand access to the particular board structure */ @@ -159,68 +150,6 @@ struct pc236_private { #define devpriv ((struct pc236_private *)dev->private) -/* - * The struct comedi_driver structure tells the Comedi core module - * which functions to call to configure/deconfigure (attach/detach) - * the board, and also about the kernel module that contains - * the device code. - */ -static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it); -static void pc236_detach(struct comedi_device *dev); -static struct comedi_driver amplc_pc236_driver = { - .driver_name = PC236_DRIVER_NAME, - .module = THIS_MODULE, - .attach = pc236_attach, - .detach = pc236_detach, - .board_name = &pc236_boards[0].name, - .offset = sizeof(struct pc236_board), - .num_names = ARRAY_SIZE(pc236_boards), -}; - -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) -static int __devinit amplc_pc236_pci_probe(struct pci_dev *dev, - const struct pci_device_id - *ent) -{ - return comedi_pci_auto_config(dev, &lc_pc236_driver); -} - -static void __devexit amplc_pc236_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static struct pci_driver amplc_pc236_pci_driver = { - .name = PC236_DRIVER_NAME, - .id_table = pc236_pci_table, - .probe = &lc_pc236_pci_probe, - .remove = __devexit_p(&lc_pc236_pci_remove) -}; - -module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver); -#else -module_comedi_driver(amplc_pc236_driver); -#endif - -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) -static int pc236_request_region(unsigned minor, unsigned long from, - unsigned long extent); -#endif -static void pc236_intr_disable(struct comedi_device *dev); -static void pc236_intr_enable(struct comedi_device *dev); -static int pc236_intr_check(struct comedi_device *dev); -static int pc236_intr_insn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int pc236_intr_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int pc236_intr_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); -static int pc236_intr_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); -static irqreturn_t pc236_interrupt(int irq, void *d); - /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -283,185 +212,6 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot, } #endif -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ - struct comedi_subdevice *s; - unsigned long iobase = 0; - unsigned int irq = 0; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - struct pci_dev *pci_dev = NULL; - int bus = 0, slot = 0; -#endif - int share_irq = 0; - int ret; - - printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, - PC236_DRIVER_NAME); -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ - ret = alloc_private(dev, sizeof(struct pc236_private)); - if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); - return ret; - } - /* Process options. */ - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: - iobase = it->options[0]; - irq = it->options[1]; - share_irq = 0; - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: - bus = it->options[0]; - slot = it->options[1]; - share_irq = 1; - - ret = pc236_find_pci(dev, bus, slot, &pci_dev); - if (ret < 0) - return ret; - devpriv->pci_dev = pci_dev; - break; -#endif - default: - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, PC236_DRIVER_NAME); - return -EINVAL; - break; - } - -/* - * Initialize dev->board_name. - */ - dev->board_name = thisboard->name; - - /* Enable device and reserve I/O spaces. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (pci_dev) { - - ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); - if (ret < 0) { - printk(KERN_ERR - "comedi%d: error! cannot enable PCI device and request regions!\n", - dev->minor); - return ret; - } - devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); - iobase = pci_resource_start(pci_dev, 2); - irq = pci_dev->irq; - } else -#endif - { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE); - if (ret < 0) - return ret; -#endif - } - dev->iobase = iobase; - -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ - ret = alloc_subdevices(dev, 2); - if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); - return ret; - } - - s = dev->subdevices + 0; - /* digital i/o subdevice (8255) */ - ret = subdev_8255_init(dev, s, NULL, iobase); - if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); - return ret; - } - s = dev->subdevices + 1; - dev->read_subdev = s; - s->type = COMEDI_SUBD_UNUSED; - pc236_intr_disable(dev); - if (irq) { - unsigned long flags = share_irq ? IRQF_SHARED : 0; - - if (request_irq(irq, pc236_interrupt, flags, - PC236_DRIVER_NAME, dev) >= 0) { - dev->irq = irq; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pc236_intr_insn; - s->do_cmdtest = pc236_intr_cmdtest; - s->do_cmd = pc236_intr_cmd; - s->cancel = pc236_intr_cancel; - } - } - printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: - printk("(base %#lx) ", iobase); - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: - printk("(pci %s) ", pci_name(pci_dev)); - break; -#endif - default: - break; - } - if (irq) - printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); - else - printk("(no irq) "); - - printk("attached\n"); - - return 1; -} - -static void pc236_detach(struct comedi_device *dev) -{ - if (devpriv) - pc236_intr_disable(dev); - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->subdevices) - subdev_8255_cleanup(dev, dev->subdevices + 0); - if (devpriv) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (devpriv->pci_dev) { - if (dev->iobase) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); - } else -#endif - { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - if (dev->iobase) - release_region(dev->iobase, PC236_IO_SIZE); -#endif - } - } -} - /* * This function checks and requests an I/O region, reporting an error * if there is a conflict. @@ -681,6 +431,232 @@ static irqreturn_t pc236_interrupt(int irq, void *d) return IRQ_RETVAL(handled); } +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; + unsigned int irq = 0; +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + struct pci_dev *pci_dev = NULL; + int bus = 0, slot = 0; +#endif + int share_irq = 0; + int ret; + + printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, + PC236_DRIVER_NAME); +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + ret = alloc_private(dev, sizeof(struct pc236_private)); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + /* Process options. */ + switch (thisboard->bustype) { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + case isa_bustype: + iobase = it->options[0]; + irq = it->options[1]; + share_irq = 0; + break; +#endif +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + case pci_bustype: + bus = it->options[0]; + slot = it->options[1]; + share_irq = 1; + + ret = pc236_find_pci(dev, bus, slot, &pci_dev); + if (ret < 0) + return ret; + devpriv->pci_dev = pci_dev; + break; +#endif + default: + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, PC236_DRIVER_NAME); + return -EINVAL; + break; + } + +/* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + + /* Enable device and reserve I/O spaces. */ +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + if (pci_dev) { + + ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); + if (ret < 0) { + printk(KERN_ERR + "comedi%d: error! cannot enable PCI device and request regions!\n", + dev->minor); + return ret; + } + devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); + iobase = pci_resource_start(pci_dev, 2); + irq = pci_dev->irq; + } else +#endif + { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE); + if (ret < 0) + return ret; +#endif + } + dev->iobase = iobase; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + ret = alloc_subdevices(dev, 2); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + s = dev->subdevices + 0; + /* digital i/o subdevice (8255) */ + ret = subdev_8255_init(dev, s, NULL, iobase); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + s = dev->subdevices + 1; + dev->read_subdev = s; + s->type = COMEDI_SUBD_UNUSED; + pc236_intr_disable(dev); + if (irq) { + unsigned long flags = share_irq ? IRQF_SHARED : 0; + + if (request_irq(irq, pc236_interrupt, flags, + PC236_DRIVER_NAME, dev) >= 0) { + dev->irq = irq; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc236_intr_insn; + s->do_cmdtest = pc236_intr_cmdtest; + s->do_cmd = pc236_intr_cmd; + s->cancel = pc236_intr_cancel; + } + } + printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); + switch (thisboard->bustype) { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + case isa_bustype: + printk("(base %#lx) ", iobase); + break; +#endif +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + case pci_bustype: + printk("(pci %s) ", pci_name(pci_dev)); + break; +#endif + default: + break; + } + if (irq) + printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); + else + printk("(no irq) "); + + printk("attached\n"); + + return 1; +} + +static void pc236_detach(struct comedi_device *dev) +{ + if (devpriv) + pc236_intr_disable(dev); + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 0); + if (devpriv) { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + if (devpriv->pci_dev) { + if (dev->iobase) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } else +#endif + { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + if (dev->iobase) + release_region(dev->iobase, PC236_IO_SIZE); +#endif + } + } +} + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static struct comedi_driver amplc_pc236_driver = { + .driver_name = PC236_DRIVER_NAME, + .module = THIS_MODULE, + .attach = pc236_attach, + .detach = pc236_detach, + .board_name = &pc236_boards[0].name, + .offset = sizeof(struct pc236_board), + .num_names = ARRAY_SIZE(pc236_boards), +}; + +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) +static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pc236_pci_table); + +static int __devinit amplc_pc236_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &lc_pc236_driver); +} + +static void __devexit amplc_pc236_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver amplc_pc236_pci_driver = { + .name = PC236_DRIVER_NAME, + .id_table = pc236_pci_table, + .probe = &lc_pc236_pci_probe, + .remove = __devexit_p(&lc_pc236_pci_remove) +}; + +module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver); +#else +module_comedi_driver(amplc_pc236_driver); +#endif + MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -- GitLab From 62bc23d145d636f0de2bf412dcf31a33fcf16046 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:31 +0100 Subject: [PATCH 0223/5711] staging: comedi: amplc_pc236: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. There were some consecutive printk calls without newlines which now scnprintf into a temporary buffer and this bit of code has been factored out into new function pc236_report_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 108 +++++++++---------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 007b45bef7b0..b56881c7e603 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -201,12 +201,12 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot, } /* No match found. */ if (bus || slot) { - printk(KERN_ERR - "comedi%d: error! no %s found at pci %02x:%02x!\n", - dev->minor, thisboard->name, bus, slot); + dev_err(dev->class_dev, + "error! no %s found at pci %02x:%02x!\n", + thisboard->name, bus, slot); } else { - printk(KERN_ERR "comedi%d: error! no %s found!\n", - dev->minor, thisboard->name); + dev_err(dev->class_dev, "error! no %s found!\n", + thisboard->name); } return -EIO; } @@ -217,12 +217,12 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot, * if there is a conflict. */ #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) -static int pc236_request_region(unsigned minor, unsigned long from, +static int pc236_request_region(struct comedi_device *dev, unsigned long from, unsigned long extent) { if (!from || !request_region(from, extent, PC236_DRIVER_NAME)) { - printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", - minor, from, extent); + dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", + from, extent); return -EIO; } return 0; @@ -431,6 +431,39 @@ static irqreturn_t pc236_interrupt(int irq, void *d) return IRQ_RETVAL(handled); } +static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) +{ + char tmpbuf[60]; + int tmplen; + + switch (thisboard->bustype) { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + case isa_bustype: + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(base %#lx) ", dev->iobase); + break; +#endif +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + case pci_bustype: + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(pci %s) ", pci_name(devpriv->pci_dev)); + break; +#endif + default: + tmplen = 0; + break; + } + if (irq) + tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, + "(irq %u%s) ", irq, + (dev->irq ? "" : " UNAVAILABLE")); + else + tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, + "(no irq) "); + dev_info(dev->class_dev, "%s %sattached\n", + dev->board_name, tmpbuf); +} + /* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array @@ -449,16 +482,10 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) int share_irq = 0; int ret; - printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, - PC236_DRIVER_NAME); -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ + dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n"); ret = alloc_private(dev, sizeof(struct pc236_private)); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } /* Process options. */ @@ -483,16 +510,13 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; #endif default: - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, PC236_DRIVER_NAME); + dev_err(dev->class_dev, PC236_DRIVER_NAME + ": BUG! cannot determine board type!\n"); return -EINVAL; break; } -/* - * Initialize dev->board_name. - */ + /* Initialize dev->board_name. */ dev->board_name = thisboard->name; /* Enable device and reserve I/O spaces. */ @@ -501,9 +525,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); if (ret < 0) { - printk(KERN_ERR - "comedi%d: error! cannot enable PCI device and request regions!\n", - dev->minor); + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); return ret; } devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); @@ -513,21 +536,16 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif { #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE); + ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); if (ret < 0) return ret; #endif } dev->iobase = iobase; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ ret = alloc_subdevices(dev, 2); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -535,8 +553,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital i/o subdevice (8255) */ ret = subdev_8255_init(dev, s, NULL, iobase); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } s = dev->subdevices + 1; @@ -560,28 +577,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = pc236_intr_cancel; } } - printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: - printk("(base %#lx) ", iobase); - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: - printk("(pci %s) ", pci_name(pci_dev)); - break; -#endif - default: - break; - } - if (irq) - printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); - else - printk("(no irq) "); - - printk("attached\n"); - + pc236_report_attach(dev, irq); return 1; } -- GitLab From 916d7028a91a6a0e4b76e7cfb97819f294cbd803 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:32 +0100 Subject: [PATCH 0224/5711] staging: comedi: amplc_pc236: Remove unused fancy_name Remove fancy_name member from struct pc236_board. It is initialized in pc235_boards[] but not used anywhere else. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 32 +++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index b56881c7e603..79265696ac52 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -98,7 +98,6 @@ enum pc236_model { pc36at_model, pci236_model, anypci_model }; struct pc236_board { const char *name; - const char *fancy_name; unsigned short devid; enum pc236_bustype bustype; enum pc236_model model; @@ -106,27 +105,24 @@ struct pc236_board { static const struct pc236_board pc236_boards[] = { #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) { - .name = "pc36at", - .fancy_name = "PC36AT", - .bustype = isa_bustype, - .model = pc36at_model, - }, + .name = "pc36at", + .bustype = isa_bustype, + .model = pc36at_model, + }, #endif #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) { - .name = "pci236", - .fancy_name = "PCI236", - .devid = PCI_DEVICE_ID_AMPLICON_PCI236, - .bustype = pci_bustype, - .model = pci236_model, - }, + .name = "pci236", + .devid = PCI_DEVICE_ID_AMPLICON_PCI236, + .bustype = pci_bustype, + .model = pci236_model, + }, { - .name = PC236_DRIVER_NAME, - .fancy_name = PC236_DRIVER_NAME, - .devid = PCI_DEVICE_ID_INVALID, - .bustype = pci_bustype, - .model = anypci_model, /* wildcard */ - }, + .name = PC236_DRIVER_NAME, + .devid = PCI_DEVICE_ID_INVALID, + .bustype = pci_bustype, + .model = anypci_model, /* wildcard */ + }, #endif }; -- GitLab From 273ba547da12406d609795bc8976cb2464b15d82 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:33 +0100 Subject: [PATCH 0225/5711] staging: comedi: amplc_pc236: Change return type of pc236_find_pci() pc236_find_pci() finds a supported PCI device, returning 0 on success or -EIO on failure and returning the pointer to the PCI device via a struct pci_dev ** parameter. Change it to return the struct pci_dev * on success or NULL on failure. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 79265696ac52..a94ac0e668a9 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -151,14 +151,11 @@ struct pc236_private { * bus and slot. */ #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) -static int -pc236_find_pci(struct comedi_device *dev, int bus, int slot, - struct pci_dev **pci_dev_p) +struct pci_dev * +pc236_find_pci(struct comedi_device *dev, int bus, int slot) { struct pci_dev *pci_dev = NULL; - *pci_dev_p = NULL; - /* Look for matching PCI device. */ for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); pci_dev != NULL; @@ -192,8 +189,7 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot, } /* Found a match. */ - *pci_dev_p = pci_dev; - return 0; + return pci_dev; } /* No match found. */ if (bus || slot) { @@ -204,7 +200,7 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot, dev_err(dev->class_dev, "error! no %s found!\n", thisboard->name); } - return -EIO; + return NULL; } #endif @@ -499,9 +495,9 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) slot = it->options[1]; share_irq = 1; - ret = pc236_find_pci(dev, bus, slot, &pci_dev); - if (ret < 0) - return ret; + pci_dev = pc236_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; devpriv->pci_dev = pci_dev; break; #endif -- GitLab From 24ffe74c93ac93bae84b2e44b868bbfd2c7954c3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:34 +0100 Subject: [PATCH 0226/5711] staging: comedi: amplc_pc236: Remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 27 ++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index a94ac0e668a9..d52c7280d8d4 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -126,11 +126,6 @@ static const struct pc236_board pc236_boards[] = { #endif }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct pc236_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. @@ -144,8 +139,6 @@ struct pc236_private { int enable_irq; }; -#define devpriv ((struct pc236_private *)dev->private) - /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -154,6 +147,7 @@ struct pc236_private { struct pci_dev * pc236_find_pci(struct comedi_device *dev, int bus, int slot) { + const struct pc236_board *thisboard = comedi_board(dev); struct pci_dev *pci_dev = NULL; /* Look for matching PCI device. */ @@ -177,6 +171,7 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot) if (pci_dev->device == pc236_boards[i].devid) { /* Change board_ptr to matched board. */ dev->board_ptr = &pc236_boards[i]; + thisboard = comedi_board(dev); break; } } @@ -228,6 +223,7 @@ static int pc236_request_region(struct comedi_device *dev, unsigned long from, */ static void pc236_intr_disable(struct comedi_device *dev) { + struct pc236_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); @@ -246,6 +242,7 @@ static void pc236_intr_disable(struct comedi_device *dev) */ static void pc236_intr_enable(struct comedi_device *dev) { + struct pc236_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); @@ -266,6 +263,7 @@ static void pc236_intr_enable(struct comedi_device *dev) */ static int pc236_intr_check(struct comedi_device *dev) { + struct pc236_private *devpriv = dev->private; int retval = 0; unsigned long flags; @@ -425,6 +423,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d) static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) { + const struct pc236_board *thisboard = comedi_board(dev); char tmpbuf[60]; int tmplen; @@ -436,9 +435,12 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) break; #endif #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: - tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), - "(pci %s) ", pci_name(devpriv->pci_dev)); + case pci_bustype: { + struct pc236_private *devpriv = dev->private; + struct pci_dev *pci_dev = devpriv->pci_dev; + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(pci %s) ", pci_name(pci_dev)); + } break; #endif default: @@ -464,10 +466,12 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) */ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pc236_board *thisboard = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase = 0; unsigned int irq = 0; #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + struct pc236_private *devpriv = dev->private; struct pci_dev *pci_dev = NULL; int bus = 0, slot = 0; #endif @@ -498,6 +502,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) pci_dev = pc236_find_pci(dev, bus, slot); if (pci_dev == NULL) return -EIO; + thisboard = comedi_board(dev); /* replaced wildcard board */ devpriv->pci_dev = pci_dev; break; #endif @@ -575,6 +580,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pc236_detach(struct comedi_device *dev) { + struct pc236_private *devpriv = dev->private; + if (devpriv) pc236_intr_disable(dev); if (dev->irq) -- GitLab From 18e41de083075b3b6a0bd55e00f1662d045efb49 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 May 2012 14:49:35 +0100 Subject: [PATCH 0227/5711] staging: comedi: amplc_pc236: Add attach_pci() hook Implement the attach_pci() hook as function pc236_attach_pci(). This is called bu comedi_pci_auto_config() in preference to the old attach() hook (implemented by pc236_attach()) and avoids searching for the probed PCI device. Factor out code common to pc236_find_pci() and pc236_attach_pci() into new function pc236_find_pci_board(). Factor out most code common to pc236_attach() and pc236_attach_pci() into new functions pc236_pci_common_attach() and pc236_common_attach(). Also #if out member 'devid' from struct pc236_board unless PCI boards are supported as it is not used for ISA boards. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 220 +++++++++++-------- 1 file changed, 129 insertions(+), 91 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index d52c7280d8d4..f1199066d14f 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -98,7 +98,9 @@ enum pc236_model { pc36at_model, pci236_model, anypci_model }; struct pc236_board { const char *name; +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) unsigned short devid; +#endif enum pc236_bustype bustype; enum pc236_model model; }; @@ -139,6 +141,22 @@ struct pc236_private { int enable_irq; }; +/* + * This function looks for a board matching the supplied PCI device. + */ +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) +static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) + if (pc236_boards[i].bustype == pci_bustype && + pci_dev->device == pc236_boards[i].devid) + return &pc236_boards[i]; + return NULL; +} +#endif + /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -162,21 +180,13 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot) continue; } if (thisboard->model == anypci_model) { - /* Match any supported model. */ - int i; - - for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) { - if (pc236_boards[i].bustype != pci_bustype) - continue; - if (pci_dev->device == pc236_boards[i].devid) { - /* Change board_ptr to matched board. */ - dev->board_ptr = &pc236_boards[i]; - thisboard = comedi_board(dev); - break; - } - } - if (i == ARRAY_SIZE(pc236_boards)) + /* Wildcard board matches any supported PCI board. */ + const struct pc236_board *foundboard; + foundboard = pc236_find_pci_board(pci_dev); + if (foundboard == NULL) continue; + /* Replace wildcard board_ptr. */ + dev->board_ptr = thisboard = foundboard; } else { /* Match specific model name. */ if (pci_dev->device != thisboard->devid) @@ -458,86 +468,14 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) dev->board_name, tmpbuf); } -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, + unsigned int irq, unsigned long req_irq_flags) { const struct pc236_board *thisboard = comedi_board(dev); struct comedi_subdevice *s; - unsigned long iobase = 0; - unsigned int irq = 0; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - struct pc236_private *devpriv = dev->private; - struct pci_dev *pci_dev = NULL; - int bus = 0, slot = 0; -#endif - int share_irq = 0; int ret; - dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n"); - ret = alloc_private(dev, sizeof(struct pc236_private)); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); - return ret; - } - /* Process options. */ - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: - iobase = it->options[0]; - irq = it->options[1]; - share_irq = 0; - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: - bus = it->options[0]; - slot = it->options[1]; - share_irq = 1; - - pci_dev = pc236_find_pci(dev, bus, slot); - if (pci_dev == NULL) - return -EIO; - thisboard = comedi_board(dev); /* replaced wildcard board */ - devpriv->pci_dev = pci_dev; - break; -#endif - default: - dev_err(dev->class_dev, PC236_DRIVER_NAME - ": BUG! cannot determine board type!\n"); - return -EINVAL; - break; - } - - /* Initialize dev->board_name. */ dev->board_name = thisboard->name; - - /* Enable device and reserve I/O spaces. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (pci_dev) { - - ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); - return ret; - } - devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); - iobase = pci_resource_start(pci_dev, 2); - irq = pci_dev->irq; - } else -#endif - { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); - if (ret < 0) - return ret; -#endif - } dev->iobase = iobase; ret = alloc_subdevices(dev, 2); @@ -558,9 +496,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; pc236_intr_disable(dev); if (irq) { - unsigned long flags = share_irq ? IRQF_SHARED : 0; - - if (request_irq(irq, pc236_interrupt, flags, + if (request_irq(irq, pc236_interrupt, req_irq_flags, PC236_DRIVER_NAME, dev) >= 0) { dev->irq = irq; s->type = COMEDI_SUBD_DI; @@ -578,6 +514,105 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 1; } +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) +static int pc236_pci_common_attach(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + struct pc236_private *devpriv = dev->private; + unsigned long iobase; + int ret; + + devpriv->pci_dev = pci_dev; + ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); + if (ret < 0) { + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); + return ret; + } + devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); + iobase = pci_resource_start(pci_dev, 2); + return pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); +} +#endif + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + const struct pc236_board *thisboard = comedi_board(dev); + int ret; + + dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n"); + ret = alloc_private(dev, sizeof(struct pc236_private)); + if (ret < 0) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return ret; + } + /* Process options according to bus type. */ + switch (thisboard->bustype) { +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + case isa_bustype: { + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); + if (ret < 0) + return ret; + return pc236_common_attach(dev, iobase, irq, 0); + } + break; +#endif +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + case pci_bustype: { + int bus = it->options[0]; + int slot = it->options[1]; + struct pci_dev *pci_dev; + + pci_dev = pc236_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; + return pc236_pci_common_attach(dev, pci_dev); + } + break; +#endif + default: + dev_err(dev->class_dev, PC236_DRIVER_NAME + ": BUG! cannot determine board type!\n"); + break; + } + return -EINVAL; +} + +/* + * The attach_pci hook (if non-NULL) is called at PCI probe time in preference + * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should + * be a board entry matching the supplied PCI device. + */ +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) +static int __devinit pc236_attach_pci(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + int ret; + + dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n", + pci_name(pci_dev)); + ret = alloc_private(dev, sizeof(struct pc236_private)); + if (ret < 0) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return ret; + } + dev->board_ptr = pc236_find_pci_board(pci_dev); + if (dev->board_ptr == NULL) { + dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); + return -EINVAL; + } + return pc236_pci_common_attach(dev, pci_dev); +} +#endif + static void pc236_detach(struct comedi_device *dev) { struct pc236_private *devpriv = dev->private; @@ -615,6 +650,9 @@ static struct comedi_driver amplc_pc236_driver = { .driver_name = PC236_DRIVER_NAME, .module = THIS_MODULE, .attach = pc236_attach, +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) + .attach_pci = pc236_attach_pci, +#endif .detach = pc236_detach, .board_name = &pc236_boards[0].name, .offset = sizeof(struct pc236_board), -- GitLab From a46e759fc05a048530da43f241c8f07e0624232c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 14:37:52 +0100 Subject: [PATCH 0228/5711] staging: comedi: amplc_pc236: Remove most #if lines Remove most of the #if IS_ENABLED(xxx) lines, but add extra if (IS_ENABLED(xxx)) tests so the compiler can remove unreachable code. The pci_driver stuff and device table is still conditionally compiled. Also made pc236_find_pci() static as it was accidentally made non-static by an earlier patch, so the compiler wouldn't remove it when it was unreachable. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 118 +++++++------------ 1 file changed, 40 insertions(+), 78 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index f1199066d14f..9cf514e54a58 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -98,9 +98,7 @@ enum pc236_model { pc36at_model, pci236_model, anypci_model }; struct pc236_board { const char *name; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) unsigned short devid; -#endif enum pc236_bustype bustype; enum pc236_model model; }; @@ -133,18 +131,15 @@ static const struct pc236_board pc236_boards[] = { feel free to suggest moving the variable to the struct comedi_device struct. */ struct pc236_private { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) /* PCI device */ struct pci_dev *pci_dev; unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ -#endif int enable_irq; }; /* * This function looks for a board matching the supplied PCI device. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev) { unsigned int i; @@ -155,14 +150,12 @@ static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev) return &pc236_boards[i]; return NULL; } -#endif /* * This function looks for a PCI device matching the requested board name, * bus and slot. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) -struct pci_dev * +static struct pci_dev * pc236_find_pci(struct comedi_device *dev, int bus, int slot) { const struct pc236_board *thisboard = comedi_board(dev); @@ -207,13 +200,11 @@ pc236_find_pci(struct comedi_device *dev, int bus, int slot) } return NULL; } -#endif /* * This function checks and requests an I/O region, reporting an error * if there is a conflict. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) static int pc236_request_region(struct comedi_device *dev, unsigned long from, unsigned long extent) { @@ -224,7 +215,6 @@ static int pc236_request_region(struct comedi_device *dev, unsigned long from, } return 0; } -#endif /* * This function is called to mark the interrupt as disabled (no command @@ -238,10 +228,8 @@ static void pc236_intr_disable(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 0; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (devpriv->lcr_iobase) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase) outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR); -#endif spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -257,10 +245,8 @@ static void pc236_intr_enable(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 1; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (devpriv->lcr_iobase) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase) outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR); -#endif spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -280,8 +266,8 @@ static int pc236_intr_check(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->enable_irq) { retval = 1; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (devpriv->lcr_iobase) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + devpriv->lcr_iobase) { if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR) & PLX9052_INTCSR_LI1STAT_MASK) == PLX9052_INTCSR_LI1STAT_INACTIVE) { @@ -292,7 +278,6 @@ static int pc236_intr_check(struct comedi_device *dev) devpriv->lcr_iobase + PLX9052_INTCSR); } } -#endif } spin_unlock_irqrestore(&dev->spinlock, flags); @@ -437,26 +422,18 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) char tmpbuf[60]; int tmplen; - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) && + thisboard->bustype == isa_bustype) tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: { - struct pc236_private *devpriv = dev->private; - struct pci_dev *pci_dev = devpriv->pci_dev; - tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), - "(pci %s) ", pci_name(pci_dev)); - } - break; -#endif - default: + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + thisboard->bustype == pci_bustype) { + struct pc236_private *devpriv = dev->private; + struct pci_dev *pci_dev = devpriv->pci_dev; + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(pci %s) ", pci_name(pci_dev)); + } else tmplen = 0; - break; - } if (irq) tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, "(irq %u%s) ", irq, @@ -514,7 +491,6 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, return 1; } -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static int pc236_pci_common_attach(struct comedi_device *dev, struct pci_dev *pci_dev) { @@ -533,7 +509,6 @@ static int pc236_pci_common_attach(struct comedi_device *dev, iobase = pci_resource_start(pci_dev, 2); return pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); } -#endif /* * Attach is called by the Comedi core to configure the driver @@ -553,37 +528,29 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } /* Process options according to bus type. */ - switch (thisboard->bustype) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) - case isa_bustype: { - unsigned long iobase = it->options[0]; - unsigned int irq = it->options[1]; - ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); - if (ret < 0) - return ret; - return pc236_common_attach(dev, iobase, irq, 0); - } - break; -#endif -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - case pci_bustype: { - int bus = it->options[0]; - int slot = it->options[1]; - struct pci_dev *pci_dev; - - pci_dev = pc236_find_pci(dev, bus, slot); - if (pci_dev == NULL) - return -EIO; - return pc236_pci_common_attach(dev, pci_dev); - } - break; -#endif - default: + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) && + thisboard->bustype == isa_bustype) { + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); + if (ret < 0) + return ret; + return pc236_common_attach(dev, iobase, irq, 0); + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + thisboard->bustype == pci_bustype) { + int bus = it->options[0]; + int slot = it->options[1]; + struct pci_dev *pci_dev; + + pci_dev = pc236_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; + return pc236_pci_common_attach(dev, pci_dev); + } else { dev_err(dev->class_dev, PC236_DRIVER_NAME ": BUG! cannot determine board type!\n"); - break; + return -EINVAL; } - return -EINVAL; } /* @@ -591,12 +558,14 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should * be a board entry matching the supplied PCI device. */ -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static int __devinit pc236_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) { int ret; + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)) + return -EINVAL; + dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n", pci_name(pci_dev)); ret = alloc_private(dev, sizeof(struct pc236_private)); @@ -611,7 +580,6 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, } return pc236_pci_common_attach(dev, pci_dev); } -#endif static void pc236_detach(struct comedi_device *dev) { @@ -624,18 +592,14 @@ static void pc236_detach(struct comedi_device *dev) if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 0); if (devpriv) { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - if (devpriv->pci_dev) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + devpriv->pci_dev) { if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); - } else -#endif - { -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)) { if (dev->iobase) release_region(dev->iobase, PC236_IO_SIZE); -#endif } } } @@ -650,9 +614,7 @@ static struct comedi_driver amplc_pc236_driver = { .driver_name = PC236_DRIVER_NAME, .module = THIS_MODULE, .attach = pc236_attach, -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) .attach_pci = pc236_attach_pci, -#endif .detach = pc236_detach, .board_name = &pc236_boards[0].name, .offset = sizeof(struct pc236_board), -- GitLab From 9f989000b54fe3131104bb26f1cc7bd0fab92e40 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:35 +0100 Subject: [PATCH 0229/5711] staging: comedi: amplc_pc263: Correct initial state The initial state of the relays is being read incorrectly. It's reading a single 8-bit port twice, but should be reading two consecutive 8-bit ports. Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 086579f756ff..e2dbf74be81a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -330,8 +330,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* all outputs */ s->io_bits = 0xffff; /* read initial relay state */ - s->state = inb(dev->iobase); - s->state = s->state | (inb(dev->iobase) << 8); + s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); switch (thisboard->bustype) { -- GitLab From d35a73e099fd9900208ebdbc3adaba76d30acac4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:36 +0100 Subject: [PATCH 0230/5711] staging: comedi: amplc_pc263: Change DIO subdevice to DO This is a relay output card with no inputs. It's single subdevice is currently a digital input/output subdevice (COMEDI_SUBD_DIO). It should really be a digital output subdevice (COMEDI_SUBD_DO). Change the subdevice type and remove the insn_config() hook as it doesn't do anything useful. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 38 +++++--------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index e2dbf74be81a..a6a25436fadc 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -154,12 +154,9 @@ static struct comedi_driver driver_amplc_pc263 = { static int pc263_request_region(unsigned minor, unsigned long from, unsigned long extent); #endif -static int pc263_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int pc263_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); +static int pc263_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); /* * This function looks for a PCI device matching the requested board name, @@ -319,16 +316,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) } s = dev->subdevices + 0; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; + /* digital output subdevice */ + s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = pc263_dio_insn_bits; - s->insn_config = pc263_dio_insn_config; - /* all outputs */ - s->io_bits = 0xffff; + s->insn_bits = pc263_do_insn_bits; /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); @@ -391,14 +385,9 @@ static int pc263_request_region(unsigned minor, unsigned long from, } #endif -/* DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write */ -static int pc263_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pc263_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (insn->n != 2) return -EINVAL; @@ -422,15 +411,6 @@ static int pc263_dio_insn_bits(struct comedi_device *dev, return 2; } -static int pc263_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - if (insn->n != 1) - return -EINVAL; - return 1; -} - /* * A convenient macro that defines init_module() and cleanup_module(), * as necessary. -- GitLab From 61f5a223155d278c9731f2406513847b8fe0bddc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:37 +0100 Subject: [PATCH 0231/5711] staging: comedi: amplc_pc263: Add a missing case There is a missing case label in the switch statement that prints out details of the attached device in pc263_attach(). Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index a6a25436fadc..f38a56ea4af7 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -334,6 +334,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; #endif #ifdef CONFIG_COMEDI_AMPLC_PC263_PCI + case pci_bustype: printk("(pci %s) ", pci_name(pci_dev)); break; #endif -- GitLab From b4843c19be4cbae48dc002080bdf49c274f26796 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:38 +0100 Subject: [PATCH 0232/5711] staging: comedi: amplc_pc263: Use IS_ENABLED() Change conditional compilation on kernel options to use the IS_ENABLED() macro. Remove most of the #ifdef lines and add extra if (IS_ENABLED(xxx)) tests so the compiler can remove unreachable code. The pci_driver stuff and device table is still conditionally compiled. In pc263_attach() move the call to alloc_private() as it is only used for PCI devices. (In pc263_detach(), for ISA devices a non-zero dev->iobase means the I/O region needs releasing.) Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 181 ++++++------------- 1 file changed, 59 insertions(+), 122 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index f38a56ea4af7..f33eb0d43274 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -48,14 +48,6 @@ The state of the outputs can be read. #define PC263_DRIVER_NAME "amplc_pc263" -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA_MODULE -#define CONFIG_COMEDI_AMPLC_PC263_ISA -#endif - -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI_MODULE -#define CONFIG_COMEDI_AMPLC_PC263_PCI -#endif - /* PCI263 PCI configuration register information */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c @@ -79,33 +71,33 @@ struct pc263_board { enum pc263_model model; }; static const struct pc263_board pc263_boards[] = { -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) { - .name = "pc263", - .fancy_name = "PC263", - .bustype = isa_bustype, - .model = pc263_model, - }, + .name = "pc263", + .fancy_name = "PC263", + .bustype = isa_bustype, + .model = pc263_model, + }, #endif -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) { - .name = "pci263", - .fancy_name = "PCI263", - .devid = PCI_DEVICE_ID_AMPLICON_PCI263, - .bustype = pci_bustype, - .model = pci263_model, - }, + .name = "pci263", + .fancy_name = "PCI263", + .devid = PCI_DEVICE_ID_AMPLICON_PCI263, + .bustype = pci_bustype, + .model = pci263_model, + }, { - .name = PC263_DRIVER_NAME, - .fancy_name = PC263_DRIVER_NAME, - .devid = PCI_DEVICE_ID_INVALID, - .bustype = pci_bustype, - .model = anypci_model, /* wildcard */ - }, + .name = PC263_DRIVER_NAME, + .fancy_name = PC263_DRIVER_NAME, + .devid = PCI_DEVICE_ID_INVALID, + .bustype = pci_bustype, + .model = anypci_model, /* wildcard */ + }, #endif }; -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, {0} @@ -123,14 +115,12 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table); several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI struct pc263_private { /* PCI device. */ struct pci_dev *pci_dev; }; #define devpriv ((struct pc263_private *)dev->private) -#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */ /* * The struct comedi_driver structure tells the Comedi core module @@ -150,10 +140,8 @@ static struct comedi_driver driver_amplc_pc263 = { .num_names = ARRAY_SIZE(pc263_boards), }; -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA static int pc263_request_region(unsigned minor, unsigned long from, unsigned long extent); -#endif static int pc263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); @@ -162,7 +150,6 @@ static int pc263_do_insn_bits(struct comedi_device *dev, * This function looks for a PCI device matching the requested board name, * bus and slot. */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI static int pc263_find_pci(struct comedi_device *dev, int bus, int slot, struct pci_dev **pci_dev_p) @@ -218,7 +205,6 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, } return -EIO; } -#endif /* * Attach is called by the Comedi core to configure the driver @@ -230,60 +216,35 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned long iobase = 0; -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - struct pci_dev *pci_dev = NULL; - int bus = 0, slot = 0; -#endif int ret; printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, PC263_DRIVER_NAME); -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - ret = alloc_private(dev, sizeof(struct pc263_private)); - if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); - return ret; - } -#endif - /* Process options. */ - switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA - case isa_bustype: + + /* Process options and reserve resources according to bus type. */ + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && + thisboard->bustype == isa_bustype) { iobase = it->options[0]; - break; -#endif -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - case pci_bustype: + ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE); + if (ret < 0) + return ret; + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && + thisboard->bustype == pci_bustype) { + struct pci_dev *pci_dev = NULL; + int bus, slot; + + ret = alloc_private(dev, sizeof(struct pc263_private)); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } bus = it->options[0]; slot = it->options[1]; - ret = pc263_find_pci(dev, bus, slot, &pci_dev); if (ret < 0) return ret; devpriv->pci_dev = pci_dev; - break; -#endif - default: - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, PC263_DRIVER_NAME); - return -EINVAL; - break; - } - -/* - * Initialize dev->board_name. - */ - dev->board_name = thisboard->name; - - /* Enable device and reserve I/O spaces. */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - if (pci_dev) { ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); if (ret < 0) { printk(KERN_ERR @@ -293,21 +254,16 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } iobase = pci_resource_start(pci_dev, 2); - } else -#endif - { -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA - ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE); - if (ret < 0) - return ret; -#endif + } else { + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, PC263_DRIVER_NAME); + return -EINVAL; } + + dev->board_name = thisboard->name; dev->iobase = iobase; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ ret = alloc_subdevices(dev, 1); if (ret < 0) { printk(KERN_ERR "comedi%d: error! out of memory!\n", @@ -327,20 +283,12 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA - case isa_bustype: + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && + thisboard->bustype == isa_bustype) printk("(base %#lx) ", iobase); - break; -#endif -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - case pci_bustype: - printk("(pci %s) ", pci_name(pci_dev)); - break; -#endif - default: - break; - } + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && + thisboard->bustype == pci_bustype) + printk("(pci %s) ", pci_name(devpriv->pci_dev)); printk("attached\n"); @@ -349,23 +297,14 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pc263_detach(struct comedi_device *dev) { -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - if (devpriv) -#endif - { -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI - if (devpriv->pci_dev) { - if (dev->iobase) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); - } else -#endif - { -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA - if (dev->iobase) - release_region(dev->iobase, PC263_IO_SIZE); -#endif - } + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && devpriv && + devpriv->pci_dev) { + if (dev->iobase) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA)) { + if (dev->iobase) + release_region(dev->iobase, PC263_IO_SIZE); } } @@ -373,7 +312,6 @@ static void pc263_detach(struct comedi_device *dev) * This function checks and requests an I/O region, reporting an error * if there is a conflict. */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA static int pc263_request_region(unsigned minor, unsigned long from, unsigned long extent) { @@ -384,7 +322,6 @@ static int pc263_request_region(unsigned minor, unsigned long from, } return 0; } -#endif static int pc263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, @@ -416,7 +353,7 @@ static int pc263_do_insn_bits(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -- GitLab From 40372f5f66c4d123b8bd17b785fadecd19eb2bd1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:39 +0100 Subject: [PATCH 0233/5711] staging: comedi: amplc_pc263: Use module_comedi_{pci, }_driver() If PCI boards are supported, use the module_comedi_pci_driver() macro to register the module as a comedi driver and a PCI driver. Otherwise, only ISA boards are supported so use the module_comedi_driver() macro to register the module as a comedi driver. Renamed 'driver_amplc_pc263' to 'amplc_pc263_driver' and removed 'driver_' prefix from PCI related functions and variables, purely for aesthetic reasons. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 55 ++++---------------- 1 file changed, 10 insertions(+), 45 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index f33eb0d43274..f3cab3547bde 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -130,7 +130,7 @@ struct pc263_private { */ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it); static void pc263_detach(struct comedi_device *dev); -static struct comedi_driver driver_amplc_pc263 = { +static struct comedi_driver amplc_pc263_driver = { .driver_name = PC263_DRIVER_NAME, .module = THIS_MODULE, .attach = pc263_attach, @@ -349,63 +349,28 @@ static int pc263_do_insn_bits(struct comedi_device *dev, return 2; } -/* - * A convenient macro that defines init_module() and cleanup_module(), - * as necessary. - */ #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) -static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev, +static int __devinit amplc_pc263_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &driver_amplc_pc263); + return comedi_pci_auto_config(dev, &lc_pc263_driver); } -static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev) +static void __devexit amplc_pc263_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver driver_amplc_pc263_pci_driver = { +static struct pci_driver amplc_pc263_pci_driver = { + .name = PC263_DRIVER_NAME, .id_table = pc263_pci_table, - .probe = &driver_amplc_pc263_pci_probe, - .remove = __devexit_p(&driver_amplc_pc263_pci_remove) + .probe = &lc_pc263_pci_probe, + .remove = __devexit_p(&lc_pc263_pci_remove) }; - -static int __init driver_amplc_pc263_init_module(void) -{ - int retval; - - retval = comedi_driver_register(&driver_amplc_pc263); - if (retval < 0) - return retval; - - driver_amplc_pc263_pci_driver.name = - (char *)driver_amplc_pc263.driver_name; - return pci_register_driver(&driver_amplc_pc263_pci_driver); -} - -static void __exit driver_amplc_pc263_cleanup_module(void) -{ - pci_unregister_driver(&driver_amplc_pc263_pci_driver); - comedi_driver_unregister(&driver_amplc_pc263); -} - -module_init(driver_amplc_pc263_init_module); -module_exit(driver_amplc_pc263_cleanup_module); +module_comedi_pci_driver(amplc_pc263_driver, amplc_pc263_pci_driver); #else -static int __init driver_amplc_pc263_init_module(void) -{ - return comedi_driver_register(&driver_amplc_pc263); -} - -static void __exit driver_amplc_pc263_cleanup_module(void) -{ - comedi_driver_unregister(&driver_amplc_pc263); -} - -module_init(driver_amplc_pc263_init_module); -module_exit(driver_amplc_pc263_cleanup_module); +module_comedi_driver(amplc_pc263_driver); #endif MODULE_AUTHOR("Comedi http://www.comedi.org"); -- GitLab From ba7914cd133cff9ac73e3434ba6980f2ac97a362 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:40 +0100 Subject: [PATCH 0234/5711] staging: comedi: amplc_pc263: Remove forward function declarations Moved some functions and variables to avoid forward declarations. Moved PCI table closer to the struct pci_driver that refers to it. Also removed some useless comments from pc263_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 123 ++++++++----------- 1 file changed, 52 insertions(+), 71 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index f3cab3547bde..5d5d9a280cea 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -97,15 +97,6 @@ static const struct pc263_board pc263_boards[] = { #endif }; -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) -static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, pc263_pci_table); -#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */ - /* * Useful for shorthand access to the particular board structure */ @@ -122,30 +113,6 @@ struct pc263_private { #define devpriv ((struct pc263_private *)dev->private) -/* - * The struct comedi_driver structure tells the Comedi core module - * which functions to call to configure/deconfigure (attach/detach) - * the board, and also about the kernel module that contains - * the device code. - */ -static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it); -static void pc263_detach(struct comedi_device *dev); -static struct comedi_driver amplc_pc263_driver = { - .driver_name = PC263_DRIVER_NAME, - .module = THIS_MODULE, - .attach = pc263_attach, - .detach = pc263_detach, - .board_name = &pc263_boards[0].name, - .offset = sizeof(struct pc263_board), - .num_names = ARRAY_SIZE(pc263_boards), -}; - -static int pc263_request_region(unsigned minor, unsigned long from, - unsigned long extent); -static int pc263_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -205,6 +172,39 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, } return -EIO; } +/* + * This function checks and requests an I/O region, reporting an error + * if there is a conflict. + */ +static int pc263_request_region(unsigned minor, unsigned long from, + unsigned long extent) +{ + if (!from || !request_region(from, extent, PC263_DRIVER_NAME)) { + printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", + minor, from, extent); + return -EIO; + } + return 0; +} + +static int pc263_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + outb(s->state & 0xFF, dev->iobase); + outb(s->state >> 8, dev->iobase + 1); + } + return 2; +} /* * Attach is called by the Comedi core to configure the driver @@ -309,47 +309,28 @@ static void pc263_detach(struct comedi_device *dev) } /* - * This function checks and requests an I/O region, reporting an error - * if there is a conflict. + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. */ -static int pc263_request_region(unsigned minor, unsigned long from, - unsigned long extent) -{ - if (!from || !request_region(from, extent, PC263_DRIVER_NAME)) { - printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", - minor, from, extent); - return -EIO; - } - return 0; -} - -static int pc263_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - if (insn->n != 2) - return -EINVAL; - - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - /* Write out the new digital output lines */ - outb(s->state & 0xFF, dev->iobase); - outb(s->state >> 8, dev->iobase + 1); - } - - /* on return, data[1] contains the value of the digital - * input and output lines. */ - /* or we could just return the software copy of the output values if - * it was a purely digital output subdevice */ - data[1] = s->state; - - return 2; -} +static struct comedi_driver amplc_pc263_driver = { + .driver_name = PC263_DRIVER_NAME, + .module = THIS_MODULE, + .attach = pc263_attach, + .detach = pc263_detach, + .board_name = &pc263_boards[0].name, + .offset = sizeof(struct pc263_board), + .num_names = ARRAY_SIZE(pc263_boards), +}; #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) +static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, + {0} +}; +MODULE_DEVICE_TABLE(pci, pc263_pci_table); + static int __devinit amplc_pc263_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -- GitLab From 03668b101362b031b74a7cde865fa7346b44eb30 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:41 +0100 Subject: [PATCH 0235/5711] staging: comedi: amplc_pc263: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. There were some consecutive printk calls without newlines which now snprintf into a temporary buffer and this bit of code has been factored out into new function pc263_report_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 65 ++++++++++---------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 5d5d9a280cea..b504c430cb37 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -163,12 +163,12 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, } /* No match found. */ if (bus || slot) { - printk(KERN_ERR - "comedi%d: error! no %s found at pci %02x:%02x!\n", - dev->minor, thisboard->name, bus, slot); + dev_err(dev->class_dev, + "error! no %s found at pci %02x:%02x!\n", + thisboard->name, bus, slot); } else { - printk(KERN_ERR "comedi%d: error! no %s found!\n", - dev->minor, thisboard->name); + dev_err(dev->class_dev, "error! no %s found!\n", + thisboard->name); } return -EIO; } @@ -176,12 +176,12 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, * This function checks and requests an I/O region, reporting an error * if there is a conflict. */ -static int pc263_request_region(unsigned minor, unsigned long from, +static int pc263_request_region(struct comedi_device *dev, unsigned long from, unsigned long extent) { if (!from || !request_region(from, extent, PC263_DRIVER_NAME)) { - printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", - minor, from, extent); + dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", + from, extent); return -EIO; } return 0; @@ -206,6 +206,22 @@ static int pc263_do_insn_bits(struct comedi_device *dev, return 2; } +static void pc263_report_attach(struct comedi_device *dev) +{ + char tmpbuf[40]; + + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && + thisboard->bustype == isa_bustype) + snprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && + thisboard->bustype == pci_bustype) + snprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ", + pci_name(devpriv->pci_dev)); + else + tmpbuf[0] = '\0'; + dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); +} + /* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array @@ -218,14 +234,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned long iobase = 0; int ret; - printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, - PC263_DRIVER_NAME); + dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n"); /* Process options and reserve resources according to bus type. */ if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && thisboard->bustype == isa_bustype) { iobase = it->options[0]; - ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE); + ret = pc263_request_region(dev, iobase, PC263_IO_SIZE); if (ret < 0) return ret; } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && @@ -235,8 +250,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = alloc_private(dev, sizeof(struct pc263_private)); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } bus = it->options[0]; @@ -247,17 +261,14 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); if (ret < 0) { - printk(KERN_ERR - "comedi%d: error! cannot enable PCI device and " - "request regions!\n", - dev->minor); + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); return ret; } iobase = pci_resource_start(pci_dev, 2); } else { - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, PC263_DRIVER_NAME); + dev_err(dev->class_dev, PC263_DRIVER_NAME + ": BUG! cannot determine board type!\n"); return -EINVAL; } @@ -266,8 +277,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = alloc_subdevices(dev, 1); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -282,16 +292,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); - printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && - thisboard->bustype == isa_bustype) - printk("(base %#lx) ", iobase); - else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && - thisboard->bustype == pci_bustype) - printk("(pci %s) ", pci_name(devpriv->pci_dev)); - - printk("attached\n"); - + pc263_report_attach(dev); return 1; } -- GitLab From 6ac682520ec3318f0a43582f642c0444ad5e3314 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:42 +0100 Subject: [PATCH 0236/5711] staging: comedi: amplc_pc263: Remove unused fancy_name Remove fancy_name member from struct pc263_board. It is initialized in pc263_boards[] but not used anywhere else. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index b504c430cb37..9fa98c4d27e0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -65,7 +65,6 @@ enum pc263_model { pc263_model, pci263_model, anypci_model }; struct pc263_board { const char *name; - const char *fancy_name; unsigned short devid; enum pc263_bustype bustype; enum pc263_model model; @@ -74,7 +73,6 @@ static const struct pc263_board pc263_boards[] = { #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) { .name = "pc263", - .fancy_name = "PC263", .bustype = isa_bustype, .model = pc263_model, }, @@ -82,14 +80,12 @@ static const struct pc263_board pc263_boards[] = { #if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) { .name = "pci263", - .fancy_name = "PCI263", .devid = PCI_DEVICE_ID_AMPLICON_PCI263, .bustype = pci_bustype, .model = pci263_model, }, { .name = PC263_DRIVER_NAME, - .fancy_name = PC263_DRIVER_NAME, .devid = PCI_DEVICE_ID_INVALID, .bustype = pci_bustype, .model = anypci_model, /* wildcard */ -- GitLab From 7ac75ba4f364fb655c89b4f9ccf1cfbdf9dfd370 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:43 +0100 Subject: [PATCH 0237/5711] staging: comedi: amplc_pc263: Change return type of pc263_find_pci() pc263_find_pci() finds a supported PCI device, returning 0 on success or -EIO on failure and returning the pointer to the PCI device via a struct pci_dev ** parameter. Change it to return the struct pci_dev * on success or NULL on failure. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 9fa98c4d27e0..dd0b4b20582b 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -113,14 +113,11 @@ struct pc263_private { * This function looks for a PCI device matching the requested board name, * bus and slot. */ -static int -pc263_find_pci(struct comedi_device *dev, int bus, int slot, - struct pci_dev **pci_dev_p) +static struct pci_dev * +pc263_find_pci(struct comedi_device *dev, int bus, int slot) { struct pci_dev *pci_dev = NULL; - *pci_dev_p = NULL; - /* Look for matching PCI device. */ for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); pci_dev != NULL; @@ -154,8 +151,7 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, } /* Found a match. */ - *pci_dev_p = pci_dev; - return 0; + return pci_dev; } /* No match found. */ if (bus || slot) { @@ -166,7 +162,7 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot, dev_err(dev->class_dev, "error! no %s found!\n", thisboard->name); } - return -EIO; + return NULL; } /* * This function checks and requests an I/O region, reporting an error @@ -251,9 +247,9 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) } bus = it->options[0]; slot = it->options[1]; - ret = pc263_find_pci(dev, bus, slot, &pci_dev); - if (ret < 0) - return ret; + pci_dev = pc263_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); if (ret < 0) { -- GitLab From 04d66968b34e3e22a524064df387c9fe906c6efa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:44 +0100 Subject: [PATCH 0238/5711] staging: comedi: amplc_pc263: Remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index dd0b4b20582b..62fc335c4ea0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -93,11 +93,6 @@ static const struct pc263_board pc263_boards[] = { #endif }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct pc263_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. @@ -107,8 +102,6 @@ struct pc263_private { struct pci_dev *pci_dev; }; -#define devpriv ((struct pc263_private *)dev->private) - /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -116,6 +109,7 @@ struct pc263_private { static struct pci_dev * pc263_find_pci(struct comedi_device *dev, int bus, int slot) { + const struct pc263_board *thisboard = comedi_board(dev); struct pci_dev *pci_dev = NULL; /* Look for matching PCI device. */ @@ -139,6 +133,7 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot) if (pci_dev->device == pc263_boards[i].devid) { /* Change board_ptr to matched board. */ dev->board_ptr = &pc263_boards[i]; + thisboard = comedi_board(dev); break; } } @@ -200,6 +195,8 @@ static int pc263_do_insn_bits(struct comedi_device *dev, static void pc263_report_attach(struct comedi_device *dev) { + const struct pc263_board *thisboard = comedi_board(dev); + struct pc263_private *devpriv = dev->private; char tmpbuf[40]; if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && @@ -222,6 +219,7 @@ static void pc263_report_attach(struct comedi_device *dev) */ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pc263_board *thisboard = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase = 0; int ret; @@ -237,6 +235,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && thisboard->bustype == pci_bustype) { + struct pc263_private *devpriv; struct pci_dev *pci_dev = NULL; int bus, slot; @@ -245,11 +244,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } + devpriv = dev->private; bus = it->options[0]; slot = it->options[1]; pci_dev = pc263_find_pci(dev, bus, slot); if (pci_dev == NULL) return -EIO; + thisboard = comedi_board(dev); /* replaced wildcard board */ devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); if (ret < 0) { @@ -290,6 +291,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pc263_detach(struct comedi_device *dev) { + struct pc263_private *devpriv = dev->private; + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && devpriv && devpriv->pci_dev) { if (dev->iobase) -- GitLab From d8967b6ed676c697da3c05ab917a8eaae7a14f81 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 30 May 2012 19:04:45 +0100 Subject: [PATCH 0239/5711] staging: comedi: amplc_pc263: Add attach_pci() hook Implement the attach_pci() hook as function pc263_attach_pci(). This is called bu comedi_pci_auto_config() in preference to the old attach() hook (implemented by pc263_attach()) and avoids searching for the probed PCI device. Factor out code common to pc263_find_pci() and pc263_attach_pci() into new function pc263_find_pci_board(). Factor out most code common to pc263_attach() and pc263_attach_pci() into new functions pc263_pci_common_attach() and pc263_common_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 141 +++++++++++++------ 1 file changed, 95 insertions(+), 46 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 62fc335c4ea0..7020907f1af7 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -102,6 +102,21 @@ struct pc263_private { struct pci_dev *pci_dev; }; +/* + * This function looks for a board matching the supplied PCI device. + */ +static const struct pc263_board *pc263_find_pci_board(struct pci_dev *pci_dev) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pc263_boards); i++) + if (pc263_boards[i].bustype == pci_bustype && + pci_dev->device == pc263_boards[i].devid) + return &pc263_boards[i]; + return NULL; +} + + /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -124,21 +139,13 @@ pc263_find_pci(struct comedi_device *dev, int bus, int slot) continue; } if (thisboard->model == anypci_model) { - /* Match any supported model. */ - int i; - - for (i = 0; i < ARRAY_SIZE(pc263_boards); i++) { - if (pc263_boards[i].bustype != pci_bustype) - continue; - if (pci_dev->device == pc263_boards[i].devid) { - /* Change board_ptr to matched board. */ - dev->board_ptr = &pc263_boards[i]; - thisboard = comedi_board(dev); - break; - } - } - if (i == ARRAY_SIZE(pc263_boards)) + /* Wildcard board matches any supported PCI board. */ + const struct pc263_board *foundboard; + foundboard = pc263_find_pci_board(pci_dev); + if (foundboard == NULL) continue; + /* Replace wildcard board_ptr. */ + dev->board_ptr = thisboard = foundboard; } else { /* Match specific model name. */ if (pci_dev->device != thisboard->devid) @@ -211,6 +218,54 @@ static void pc263_report_attach(struct comedi_device *dev) dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); } +static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) +{ + const struct pc263_board *thisboard = comedi_board(dev); + struct comedi_subdevice *s; + int ret; + + dev->board_name = thisboard->name; + dev->iobase = iobase; + + ret = alloc_subdevices(dev, 1); + if (ret < 0) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return ret; + } + + s = dev->subdevices + 0; + /* digital output subdevice */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc263_do_insn_bits; + /* read initial relay state */ + s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); + + pc263_report_attach(dev); + return 1; +} + +static int pc263_pci_common_attach(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + struct pc263_private *devpriv = dev->private; + unsigned long iobase; + int ret; + + devpriv->pci_dev = pci_dev; + ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); + if (ret < 0) { + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); + return ret; + } + iobase = pci_resource_start(pci_dev, 2); + return pc263_common_attach(dev, iobase); +} + /* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array @@ -220,8 +275,6 @@ static void pc263_report_attach(struct comedi_device *dev) static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pc263_board *thisboard = comedi_board(dev); - struct comedi_subdevice *s; - unsigned long iobase = 0; int ret; dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n"); @@ -229,14 +282,14 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Process options and reserve resources according to bus type. */ if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && thisboard->bustype == isa_bustype) { - iobase = it->options[0]; + unsigned long iobase = it->options[0]; ret = pc263_request_region(dev, iobase, PC263_IO_SIZE); if (ret < 0) return ret; + return pc263_common_attach(dev, iobase); } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && thisboard->bustype == pci_bustype) { - struct pc263_private *devpriv; - struct pci_dev *pci_dev = NULL; + struct pci_dev *pci_dev; int bus, slot; ret = alloc_private(dev, sizeof(struct pc263_private)); @@ -244,49 +297,44 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } - devpriv = dev->private; bus = it->options[0]; slot = it->options[1]; pci_dev = pc263_find_pci(dev, bus, slot); if (pci_dev == NULL) return -EIO; - thisboard = comedi_board(dev); /* replaced wildcard board */ - devpriv->pci_dev = pci_dev; - ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); - return ret; - } - iobase = pci_resource_start(pci_dev, 2); + return pc263_pci_common_attach(dev, pci_dev); } else { dev_err(dev->class_dev, PC263_DRIVER_NAME ": BUG! cannot determine board type!\n"); return -EINVAL; } +} +/* + * The attach_pci hook (if non-NULL) is called at PCI probe time in preference + * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should + * be a board entry matching the supplied PCI device. + */ +static int __devinit pc263_attach_pci(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + int ret; - dev->board_name = thisboard->name; - dev->iobase = iobase; + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)) + return -EINVAL; - ret = alloc_subdevices(dev, 1); + dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n", + pci_name(pci_dev)); + ret = alloc_private(dev, sizeof(struct pc263_private)); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } - - s = dev->subdevices + 0; - /* digital output subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pc263_do_insn_bits; - /* read initial relay state */ - s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); - - pc263_report_attach(dev); - return 1; + dev->board_ptr = pc263_find_pci_board(pci_dev); + if (dev->board_ptr == NULL) { + dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); + return -EINVAL; + } + return pc263_pci_common_attach(dev, pci_dev); } static void pc263_detach(struct comedi_device *dev) @@ -314,6 +362,7 @@ static struct comedi_driver amplc_pc263_driver = { .driver_name = PC263_DRIVER_NAME, .module = THIS_MODULE, .attach = pc263_attach, + .attach_pci = pc263_attach_pci, .detach = pc263_detach, .board_name = &pc263_boards[0].name, .offset = sizeof(struct pc263_board), -- GitLab From a6e11e3b9ffe994f1f2f8ab74ebdc9d1937c16e0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:31 +0100 Subject: [PATCH 0240/5711] staging: comedi: amplc_dio200: Use IS_ENABLED() Change conditional compilation on kernel options to use the IS_ENABLED() macro. Remove most of the #ifdef lines and add extra if (IS_ENABLED(xxx)) tests so the compiler can remove unreachable code. The pci_driver stuff and device table and some of the static const data is still conditionally compiled. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 122 ++++++------------ 1 file changed, 41 insertions(+), 81 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index f6f6144344b4..95d4370bf7af 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -215,14 +215,6 @@ order they appear in the channel list. #define DIO200_DRIVER_NAME "amplc_dio200" -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA_MODULE -#define CONFIG_COMEDI_AMPLC_DIO200_ISA -#endif - -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI_MODULE -#define CONFIG_COMEDI_AMPLC_DIO200_PCI -#endif - /* PCI IDs */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a @@ -280,12 +272,12 @@ enum dio200_model { }; enum dio200_layout { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) pc212_layout, pc214_layout, #endif pc215_layout, -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) pc218_layout, #endif pc272_layout @@ -300,7 +292,7 @@ struct dio200_board { }; static const struct dio200_board dio200_boards[] = { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) { .name = "pc212e", .bustype = isa_bustype, @@ -332,7 +324,7 @@ static const struct dio200_board dio200_boards[] = { .layout = pc272_layout, }, #endif -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) { .name = "pci215", .devid = PCI_DEVICE_ID_AMPLICON_PCI215, @@ -375,7 +367,7 @@ struct dio200_layout_struct { }; static const struct dio200_layout_struct dio200_layouts[] = { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) [pc212_layout] = { .n_subdevs = 6, .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, @@ -404,7 +396,7 @@ static const struct dio200_layout_struct dio200_layouts[] = { .has_int_sce = 1, .has_clk_gat_sce = 1, }, -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) [pc218_layout] = { .n_subdevs = 7, .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, @@ -431,7 +423,7 @@ static const struct dio200_layout_struct dio200_layouts[] = { * PCI driver table. */ -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) }, { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) }, @@ -453,9 +445,7 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table); feel free to suggest moving the variable to the struct comedi_device struct. */ struct dio200_private { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI struct pci_dev *pci_dev; /* PCI device */ -#endif int intr_sd; }; @@ -502,7 +492,7 @@ static struct comedi_driver driver_amplc_dio200 = { .num_names = ARRAY_SIZE(dio200_boards), }; -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) @@ -561,7 +551,6 @@ module_exit(driver_amplc_dio200_cleanup_module); * This function looks for a PCI device matching the requested board name, * bus and slot. */ -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI static int dio200_find_pci(struct comedi_device *dev, int bus, int slot, struct pci_dev **pci_dev_p) @@ -617,13 +606,11 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot, } return -EIO; } -#endif /* * This function checks and requests an I/O region, reporting an error * if there is a conflict. */ -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA static int dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) { @@ -634,7 +621,6 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) } return 0; } -#endif /* * 'insn_bits' function for an 'INTERRUPT' subdevice. @@ -1346,10 +1332,6 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase = 0; unsigned int irq = 0; -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI - struct pci_dev *pci_dev = NULL; - int bus = 0, slot = 0; -#endif const struct dio200_layout_struct *layout; int share_irq = 0; int sdx; @@ -1366,40 +1348,27 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } - /* Process options. */ - switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA - case isa_bustype: + /* Process options and reserve resources according to bus type. */ + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) { iobase = it->options[0]; irq = it->options[1]; share_irq = 0; - break; -#endif -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI - case pci_bustype: + ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); + if (ret < 0) + return ret; + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) { + struct pci_dev *pci_dev = NULL; + int bus, slot; + bus = it->options[0]; slot = it->options[1]; share_irq = 1; - ret = dio200_find_pci(dev, bus, slot, &pci_dev); if (ret < 0) return ret; devpriv->pci_dev = pci_dev; - break; -#endif - default: - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, DIO200_DRIVER_NAME); - return -EINVAL; - break; - } - - devpriv->intr_sd = -1; - - /* Enable device and reserve I/O spaces. */ -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI - if (pci_dev) { ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); if (ret < 0) { printk(KERN_ERR @@ -1409,15 +1378,15 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) } iobase = pci_resource_start(pci_dev, 2); irq = pci_dev->irq; - } else -#endif - { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA - ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); - if (ret < 0) - return ret; -#endif + } else { + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, DIO200_DRIVER_NAME); + return -EINVAL; } + + devpriv->intr_sd = -1; + dev->iobase = iobase; layout = thislayout; @@ -1492,20 +1461,12 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) } printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - switch (thisboard->bustype) { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA - case isa_bustype: + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) printk("(base %#lx) ", iobase); - break; -#endif -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI - case pci_bustype: - printk("(pci %s) ", pci_name(pci_dev)); - break; -#endif - default: - break; - } + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) + printk("(pci %s) ", pci_name(devpriv->pci_dev)); if (irq) printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); else @@ -1543,18 +1504,17 @@ static void dio200_detach(struct comedi_device *dev) } } if (devpriv) { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI - if (devpriv->pci_dev) { - if (dev->iobase) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); - } else -#endif - { -#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) { + if (devpriv->pci_dev) { + if (dev->iobase) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) { if (dev->iobase) release_region(dev->iobase, DIO200_IO_SIZE); -#endif } } } -- GitLab From d22e9306c3e119ebc058d5b77306042d6603b231 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:32 +0100 Subject: [PATCH 0241/5711] staging: comedi: amplc_dio200: Use module_comedi_{pci,}_driver() If PCI boards are supported, use the module_comedi_pci_driver() macro to register the module as a comedi driver and a PCI driver. Otherwise, only ISA boards are supported so use the module_comedi_driver() macro to register the module as a comedi driver. Renamed 'driver_amplc_dio200' to 'amplc_dio200_driver' and removed 'driver_' prefix from PCI related functions and variables, purely for aesthetic reasons. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 51 ++++--------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 95d4370bf7af..598e51a0cd21 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -482,7 +482,7 @@ struct dio200_subdev_intr { static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it); static void dio200_detach(struct comedi_device *dev); -static struct comedi_driver driver_amplc_dio200 = { +static struct comedi_driver amplc_dio200_driver = { .driver_name = DIO200_DRIVER_NAME, .module = THIS_MODULE, .attach = dio200_attach, @@ -493,58 +493,27 @@ static struct comedi_driver driver_amplc_dio200 = { }; #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) -static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev, +static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &driver_amplc_dio200); + return comedi_pci_auto_config(dev, &lc_dio200_driver); } -static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev) +static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver driver_amplc_dio200_pci_driver = { +static struct pci_driver amplc_dio200_pci_driver = { + .name = DIO200_DRIVER_NAME, .id_table = dio200_pci_table, - .probe = &driver_amplc_dio200_pci_probe, - .remove = __devexit_p(&driver_amplc_dio200_pci_remove) + .probe = &lc_dio200_pci_probe, + .remove = __devexit_p(&lc_dio200_pci_remove) }; - -static int __init driver_amplc_dio200_init_module(void) -{ - int retval; - - retval = comedi_driver_register(&driver_amplc_dio200); - if (retval < 0) - return retval; - - driver_amplc_dio200_pci_driver.name = - (char *)driver_amplc_dio200.driver_name; - return pci_register_driver(&driver_amplc_dio200_pci_driver); -} - -static void __exit driver_amplc_dio200_cleanup_module(void) -{ - pci_unregister_driver(&driver_amplc_dio200_pci_driver); - comedi_driver_unregister(&driver_amplc_dio200); -} - -module_init(driver_amplc_dio200_init_module); -module_exit(driver_amplc_dio200_cleanup_module); +module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver); #else -static int __init driver_amplc_dio200_init_module(void) -{ - return comedi_driver_register(&driver_amplc_dio200); -} - -static void __exit driver_amplc_dio200_cleanup_module(void) -{ - comedi_driver_unregister(&driver_amplc_dio200); -} - -module_init(driver_amplc_dio200_init_module); -module_exit(driver_amplc_dio200_cleanup_module); +module_comedi_driver(amplc_dio200_driver); #endif /* -- GitLab From fd97962b4142fc3460d3628c3842be6d33b9aa94 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:33 +0100 Subject: [PATCH 0242/5711] staging: comedi: amplc_dio200: Remove forward function declarations Moved some functions and variables to avoid forward declarations. Moved PCI table closer to the struct pci_driver that refers to it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 105 ++++++++---------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 598e51a0cd21..8b31ab9ce90f 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -419,20 +419,6 @@ static const struct dio200_layout_struct dio200_layouts[] = { }, }; -/* - * PCI driver table. - */ - -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) -static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, dio200_pci_table); -#endif /* CONFIG_COMEDI_AMPLC_DIO200_PCI */ - /* * Useful for shorthand access to the particular board structure */ @@ -473,49 +459,6 @@ struct dio200_subdev_intr { int continuous; }; -/* - * The struct comedi_driver structure tells the Comedi core module - * which functions to call to configure/deconfigure (attach/detach) - * the board, and also about the kernel module that contains - * the device code. - */ -static int dio200_attach(struct comedi_device *dev, - struct comedi_devconfig *it); -static void dio200_detach(struct comedi_device *dev); -static struct comedi_driver amplc_dio200_driver = { - .driver_name = DIO200_DRIVER_NAME, - .module = THIS_MODULE, - .attach = dio200_attach, - .detach = dio200_detach, - .board_name = &dio200_boards[0].name, - .offset = sizeof(struct dio200_board), - .num_names = ARRAY_SIZE(dio200_boards), -}; - -#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) -static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev, - const struct pci_device_id - *ent) -{ - return comedi_pci_auto_config(dev, &lc_dio200_driver); -} - -static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static struct pci_driver amplc_dio200_pci_driver = { - .name = DIO200_DRIVER_NAME, - .id_table = dio200_pci_table, - .probe = &lc_dio200_pci_probe, - .remove = __devexit_p(&lc_dio200_pci_remove) -}; -module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver); -#else -module_comedi_driver(amplc_dio200_driver); -#endif - /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -1488,6 +1431,54 @@ static void dio200_detach(struct comedi_device *dev) } } +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static struct comedi_driver amplc_dio200_driver = { + .driver_name = DIO200_DRIVER_NAME, + .module = THIS_MODULE, + .attach = dio200_attach, + .detach = dio200_detach, + .board_name = &dio200_boards[0].name, + .offset = sizeof(struct dio200_board), + .num_names = ARRAY_SIZE(dio200_boards), +}; + +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) +static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) }, + {0} +}; + +MODULE_DEVICE_TABLE(pci, dio200_pci_table); + +static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, &lc_dio200_driver); +} + +static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver amplc_dio200_pci_driver = { + .name = DIO200_DRIVER_NAME, + .id_table = dio200_pci_table, + .probe = &lc_dio200_pci_probe, + .remove = __devexit_p(&lc_dio200_pci_remove) +}; +module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver); +#else +module_comedi_driver(amplc_dio200_driver); +#endif + MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -- GitLab From 485455d01b26e849d30c2b20ce20a4d6fc50555e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:34 +0100 Subject: [PATCH 0243/5711] staging: comedi: amplc_dio200: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. There were some consecutive printk calls without newlines which now scnprintf into a temporary buffer and this bit of code has been factored out into new function dio200_report_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 89 ++++++++++--------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 8b31ab9ce90f..be932e88895a 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -509,12 +509,12 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot, } /* No match found. */ if (bus || slot) { - printk(KERN_ERR - "comedi%d: error! no %s found at pci %02x:%02x!\n", - dev->minor, thisboard->name, bus, slot); + dev_err(dev->class_dev, + "error! no %s found at pci %02x:%02x!\n", + thisboard->name, bus, slot); } else { - printk(KERN_ERR "comedi%d: error! no %s found!\n", - dev->minor, thisboard->name); + dev_err(dev->class_dev, "error! no %s found!\n", + thisboard->name); } return -EIO; } @@ -524,11 +524,12 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot, * if there is a conflict. */ static int -dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) +dio200_request_region(struct comedi_device *dev, + unsigned long from, unsigned long extent) { if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) { - printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", - minor, from, extent); + dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", + from, extent); return -EIO; } return 0; @@ -926,8 +927,7 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s, subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); if (!subpriv) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return -ENOMEM; } subpriv->iobase = iobase; @@ -1180,8 +1180,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); if (!subpriv) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return -ENOMEM; } @@ -1233,6 +1232,31 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev, kfree(subpriv); } +static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) +{ + char tmpbuf[60]; + int tmplen; + + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(base %#lx) ", dev->iobase); + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) + tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), + "(pci %s) ", pci_name(devpriv->pci_dev)); + else + tmplen = 0; + if (irq) + tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, + "(irq %u%s) ", irq, + (dev->irq ? "" : " UNAVAILABLE")); + else + tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, + "(no irq) "); + dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); +} + /* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array @@ -1250,13 +1274,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned n; int ret; - printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, - DIO200_DRIVER_NAME); + dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n"); ret = alloc_private(dev, sizeof(struct dio200_private)); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -1266,7 +1288,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase = it->options[0]; irq = it->options[1]; share_irq = 0; - ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); + ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE); if (ret < 0) return ret; } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && @@ -1283,17 +1305,15 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); if (ret < 0) { - printk(KERN_ERR - "comedi%d: error! cannot enable PCI device and request regions!\n", - dev->minor); + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); return ret; } iobase = pci_resource_start(pci_dev, 2); irq = pci_dev->irq; } else { - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, DIO200_DRIVER_NAME); + dev_err(dev->class_dev, DIO200_DRIVER_NAME + ": BUG! cannot determine board type!\n"); return -EINVAL; } @@ -1305,8 +1325,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = alloc_subdevices(dev, layout->n_subdevs); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -1366,26 +1385,12 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) DIO200_DRIVER_NAME, dev) >= 0) { dev->irq = irq; } else { - printk(KERN_WARNING - "comedi%d: warning! irq %u unavailable!\n", - dev->minor, irq); + dev_warn(dev->class_dev, + "warning! irq %u unavailable!\n", irq); } } - printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && - thisboard->bustype == isa_bustype) - printk("(base %#lx) ", iobase); - else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && - thisboard->bustype == pci_bustype) - printk("(pci %s) ", pci_name(devpriv->pci_dev)); - if (irq) - printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); - else - printk("(no irq) "); - - printk("attached\n"); - + dio200_report_attach(dev, irq); return 1; } -- GitLab From 181ad5edbf6d3c244263b770e9dd4eda645de5bf Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:35 +0100 Subject: [PATCH 0244/5711] staging: comedi: amplc_dio200: Change return type of dio200_find_pci() dio200_find_pci() finds a supported PCI device, returning 0 on success or -EIO on failure and returning the pointer to the PCI device via a struct pci_dev ** parameter. Change it to return the struct pci_dev * on success or NULL on failure. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index be932e88895a..6d04378f553f 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -463,14 +463,11 @@ struct dio200_subdev_intr { * This function looks for a PCI device matching the requested board name, * bus and slot. */ -static int -dio200_find_pci(struct comedi_device *dev, int bus, int slot, - struct pci_dev **pci_dev_p) +static struct pci_dev * +dio200_find_pci(struct comedi_device *dev, int bus, int slot) { struct pci_dev *pci_dev = NULL; - *pci_dev_p = NULL; - /* Look for matching PCI device. */ for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); pci_dev != NULL; @@ -504,8 +501,7 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot, } /* Found a match. */ - *pci_dev_p = pci_dev; - return 0; + return pci_dev; } /* No match found. */ if (bus || slot) { @@ -516,7 +512,7 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot, dev_err(dev->class_dev, "error! no %s found!\n", thisboard->name); } - return -EIO; + return NULL; } /* @@ -1293,15 +1289,15 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && thisboard->bustype == pci_bustype) { - struct pci_dev *pci_dev = NULL; + struct pci_dev *pci_dev; int bus, slot; bus = it->options[0]; slot = it->options[1]; share_irq = 1; - ret = dio200_find_pci(dev, bus, slot, &pci_dev); - if (ret < 0) - return ret; + pci_dev = dio200_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); if (ret < 0) { -- GitLab From adb4601a82343e846997320b41d5b7d49137fe42 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:36 +0100 Subject: [PATCH 0245/5711] staging: comedi: amplc_dio200: Remove thisboard, thislayout and devpriv macros The 'thisboard', 'thislayout' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 6d04378f553f..5b8c6775dbc9 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -419,13 +419,6 @@ static const struct dio200_layout_struct dio200_layouts[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct dio200_board *)dev->board_ptr) -#define thislayout (&dio200_layouts[((struct dio200_board *) \ - dev->board_ptr)->layout]) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. @@ -435,8 +428,6 @@ struct dio200_private { int intr_sd; }; -#define devpriv ((struct dio200_private *)dev->private) - struct dio200_subdev_8254 { unsigned long iobase; /* Counter base address */ unsigned long clk_sce_iobase; /* CLK_SCE base address */ @@ -466,6 +457,7 @@ struct dio200_subdev_intr { static struct pci_dev * dio200_find_pci(struct comedi_device *dev, int bus, int slot) { + const struct dio200_board *thisboard = comedi_board(dev); struct pci_dev *pci_dev = NULL; /* Look for matching PCI device. */ @@ -489,6 +481,7 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot) if (pci_dev->device == dio200_boards[i].devid) { /* Change board_ptr to matched board. */ dev->board_ptr = &dio200_boards[i]; + thisboard = comedi_board(dev); break; } } @@ -972,6 +965,7 @@ dio200_subdev_intr_cleanup(struct comedi_device *dev, static irqreturn_t dio200_interrupt(int irq, void *d) { struct comedi_device *dev = d; + struct dio200_private *devpriv = dev->private; int handled; if (!dev->attached) @@ -1230,6 +1224,8 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev, static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) { + const struct dio200_board *thisboard = comedi_board(dev); + struct dio200_private *devpriv = dev->private; char tmpbuf[60]; int tmplen; @@ -1261,6 +1257,8 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) */ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct dio200_board *thisboard = comedi_board(dev); + struct dio200_private *devpriv; struct comedi_subdevice *s; unsigned long iobase = 0; unsigned int irq = 0; @@ -1277,6 +1275,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } + devpriv = dev->private; /* Process options and reserve resources according to bus type. */ if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && @@ -1298,6 +1297,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) pci_dev = dio200_find_pci(dev, bus, slot); if (pci_dev == NULL) return -EIO; + thisboard = comedi_board(dev); /* replaced wildcard board */ devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); if (ret < 0) { @@ -1317,7 +1317,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; - layout = thislayout; + layout = &dio200_layouts[thisboard->layout]; ret = alloc_subdevices(dev, layout->n_subdevs); if (ret < 0) { @@ -1392,13 +1392,15 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void dio200_detach(struct comedi_device *dev) { + const struct dio200_board *thisboard = comedi_board(dev); + struct dio200_private *devpriv = dev->private; const struct dio200_layout_struct *layout; unsigned n; if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) { - layout = thislayout; + layout = &dio200_layouts[thisboard->layout]; for (n = 0; n < dev->n_subdevices; n++) { struct comedi_subdevice *s = &dev->subdevices[n]; switch (layout->sdtype[n]) { -- GitLab From c894ec8da05aa8a58830297d1564675f3e1174cc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 14:08:37 +0100 Subject: [PATCH 0246/5711] staging: comedi: amplc_dio200: Add attach_pci() hook Implement the attach_pci() hook as function dio200_attach_pci(). This is called by comedi_pci_auto_config() in preference to the old attach() hook (implemented by dio200_attach()) and avoids searching for the probed PCI device. Factor out code common to dio200_find_pci() and dio200_attach_pci() into new function dio200_find_pci_board(). Factor out most code common to dio200_attach() and dio200_attach_pci() into new functions dio200_pci_common_attach() and dio200_common_attach(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 215 +++++++++++------- 1 file changed, 127 insertions(+), 88 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 5b8c6775dbc9..3afebb24b26b 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -450,6 +450,21 @@ struct dio200_subdev_intr { int continuous; }; +/* + * This function looks for a board matching the supplied PCI device. + */ +static const struct dio200_board * +dio200_find_pci_board(struct pci_dev *pci_dev) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) + if (dio200_boards[i].bustype == pci_bustype && + pci_dev->device == dio200_boards[i].devid) + return &dio200_boards[i]; + return NULL; +} + /* * This function looks for a PCI device matching the requested board name, * bus and slot. @@ -472,21 +487,15 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot) continue; } if (thisboard->model == anypci_model) { - /* Match any supported model. */ - int i; - - for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) { - if (dio200_boards[i].bustype != pci_bustype) - continue; - if (pci_dev->device == dio200_boards[i].devid) { - /* Change board_ptr to matched board. */ - dev->board_ptr = &dio200_boards[i]; - thisboard = comedi_board(dev); - break; - } - } - if (i == ARRAY_SIZE(dio200_boards)) + /* Wildcard board matches any supported PCI board. */ + const struct dio200_board *foundboard; + + foundboard = dio200_find_pci_board(pci_dev); + if (foundboard == NULL) continue; + /* Replace wildcard board_ptr. */ + dev->board_ptr = foundboard; + thisboard = comedi_board(dev); } else { /* Match specific model name. */ if (pci_dev->device != thisboard->devid) @@ -1249,82 +1258,26 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); } -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase, + unsigned int irq, unsigned long req_irq_flags) { const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv; + struct dio200_private *devpriv = dev->private; + const struct dio200_layout_struct *layout = + &dio200_layouts[thisboard->layout]; struct comedi_subdevice *s; - unsigned long iobase = 0; - unsigned int irq = 0; - const struct dio200_layout_struct *layout; - int share_irq = 0; int sdx; - unsigned n; + unsigned int n; int ret; - dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n"); - - ret = alloc_private(dev, sizeof(struct dio200_private)); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); - return ret; - } - devpriv = dev->private; - - /* Process options and reserve resources according to bus type. */ - if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && - thisboard->bustype == isa_bustype) { - iobase = it->options[0]; - irq = it->options[1]; - share_irq = 0; - ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE); - if (ret < 0) - return ret; - } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && - thisboard->bustype == pci_bustype) { - struct pci_dev *pci_dev; - int bus, slot; - - bus = it->options[0]; - slot = it->options[1]; - share_irq = 1; - pci_dev = dio200_find_pci(dev, bus, slot); - if (pci_dev == NULL) - return -EIO; - thisboard = comedi_board(dev); /* replaced wildcard board */ - devpriv->pci_dev = pci_dev; - ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); - return ret; - } - iobase = pci_resource_start(pci_dev, 2); - irq = pci_dev->irq; - } else { - dev_err(dev->class_dev, DIO200_DRIVER_NAME - ": BUG! cannot determine board type!\n"); - return -EINVAL; - } - devpriv->intr_sd = -1; - dev->iobase = iobase; - - layout = &dio200_layouts[thisboard->layout]; - + dev->board_name = thisboard->name; ret = alloc_subdevices(dev, layout->n_subdevs); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } - for (n = 0; n < dev->n_subdevices; n++) { s = &dev->subdevices[n]; switch (layout->sdtype[n]) { @@ -1335,7 +1288,6 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) layout->has_clk_gat_sce); if (ret < 0) return ret; - break; case sd_8255: /* digital i/o subdevice (8255) */ @@ -1343,7 +1295,6 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase + layout->sdinfo[n]); if (ret < 0) return ret; - break; case sd_intr: /* 'INTERRUPT' subdevice */ @@ -1356,7 +1307,6 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) has_int_sce); if (ret < 0) return ret; - devpriv->intr_sd = n; } else { s->type = COMEDI_SUBD_UNUSED; @@ -1367,17 +1317,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; } } - sdx = devpriv->intr_sd; if (sdx >= 0 && sdx < dev->n_subdevices) dev->read_subdev = &dev->subdevices[sdx]; - - dev->board_name = thisboard->name; - if (irq) { - unsigned long flags = share_irq ? IRQF_SHARED : 0; - - if (request_irq(irq, dio200_interrupt, flags, + if (request_irq(irq, dio200_interrupt, req_irq_flags, DIO200_DRIVER_NAME, dev) >= 0) { dev->irq = irq; } else { @@ -1385,11 +1329,105 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) "warning! irq %u unavailable!\n", irq); } } - dio200_report_attach(dev, irq); return 1; } +static int dio200_pci_common_attach(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + struct dio200_private *devpriv = dev->private; + unsigned long iobase; + int ret; + + devpriv->pci_dev = pci_dev; + ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); + if (ret < 0) { + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n"); + return ret; + } + iobase = pci_resource_start(pci_dev, 2); + return dio200_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + const struct dio200_board *thisboard = comedi_board(dev); + int ret; + + dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n"); + + ret = alloc_private(dev, sizeof(struct dio200_private)); + if (ret < 0) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return ret; + } + + /* Process options and reserve resources according to bus type. */ + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) { + unsigned long iobase; + unsigned int irq; + + iobase = it->options[0]; + irq = it->options[1]; + ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE); + if (ret < 0) + return ret; + return dio200_common_attach(dev, iobase, irq, 0); + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) { + struct pci_dev *pci_dev; + int bus, slot; + + bus = it->options[0]; + slot = it->options[1]; + pci_dev = dio200_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; + return dio200_pci_common_attach(dev, pci_dev); + } else { + dev_err(dev->class_dev, DIO200_DRIVER_NAME + ": BUG! cannot determine board type!\n"); + return -EINVAL; + } +} + +/* + * The attach_pci hook (if non-NULL) is called at PCI probe time in preference + * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should + * be a board entry matching the supplied PCI device. + */ +static int __devinit dio200_attach_pci(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + int ret; + + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)) + return -EINVAL; + + dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n", + pci_name(pci_dev)); + ret = alloc_private(dev, sizeof(struct dio200_private)); + if (ret < 0) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return ret; + } + dev->board_ptr = dio200_find_pci_board(pci_dev); + if (dev->board_ptr == NULL) { + dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); + return -EINVAL; + } + return dio200_pci_common_attach(dev, pci_dev); +} + static void dio200_detach(struct comedi_device *dev) { const struct dio200_board *thisboard = comedi_board(dev); @@ -1444,6 +1482,7 @@ static struct comedi_driver amplc_dio200_driver = { .driver_name = DIO200_DRIVER_NAME, .module = THIS_MODULE, .attach = dio200_attach, + .attach_pci = dio200_attach_pci, .detach = dio200_detach, .board_name = &dio200_boards[0].name, .offset = sizeof(struct dio200_board), -- GitLab From 52954abcee66f9a3c5c2416a89c8b2affd2f5a2b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 16:02:02 +0100 Subject: [PATCH 0247/5711] staging: comedi: amplc_pci224: __devinit pci224_attach_pci() pci224_attach_pci() is only called during PCI probe, indirectly via comedi_pci_auto_config(), so it can be marked __devinit. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 0d1f9cc50ef3..96a9d341fa15 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1495,7 +1495,7 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it) return pci224_attach_common(dev, pci_dev, it->options); } -static int +static int __devinit pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) { int ret; -- GitLab From eedc1b7be2ea7c8350f359ff9afa568cb89a70d7 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 16:02:03 +0100 Subject: [PATCH 0248/5711] staging: comedi: amplc_pci224: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. There were some consecutive printk calls without newlines which now scnprintf into a temporary buffer and this bit of code has been factored out into new function pci224_report_attach(). A couple of DPRINTK() macro calls which may result in printk() calls have been left alone to be tackled en masse at a later date. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 80 +++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 96a9d341fa15..a07546e0622e 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -626,8 +626,7 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev, /* Nothing left to put in the FIFO. */ pci224_ao_stop(dev, s); s->async->events |= COMEDI_CB_OVERFLOW; - printk(KERN_ERR "comedi%d: " - "AO buffer underrun\n", dev->minor); + dev_err(dev->class_dev, "AO buffer underrun\n"); } } /* Determine how many new scans can be put in the FIFO. */ @@ -1295,16 +1294,29 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot, } /* No match found. */ if (bus || slot) { - printk(KERN_ERR "comedi%d: error! " - "no %s found at pci %02x:%02x!\n", - dev->minor, thisboard->name, bus, slot); + dev_err(dev->class_dev, + "error! no %s found at pci %02x:%02x!\n", + thisboard->name, bus, slot); } else { - printk(KERN_ERR "comedi%d: error! no %s found!\n", - dev->minor, thisboard->name); + dev_err(dev->class_dev, "error! no %s found!\n", + thisboard->name); } return -EIO; } +static void pci224_report_attach(struct comedi_device *dev, unsigned int irq) +{ + char tmpbuf[30]; + + if (irq) + snprintf(tmpbuf, sizeof(tmpbuf), "irq %u%s", irq, + (dev->irq ? "" : " UNAVAILABLE")); + else + snprintf(tmpbuf, sizeof(tmpbuf), "no irq"); + dev_info(dev->class_dev, "%s (pci %s) (%s) attached\n", + dev->board_name, pci_name(devpriv->pci_dev), tmpbuf); +} + /* * Common part of attach and attach_pci. */ @@ -1319,9 +1331,9 @@ static int pci224_attach_common(struct comedi_device *dev, devpriv->pci_dev = pci_dev; ret = comedi_pci_enable(pci_dev, DRIVER_NAME); if (ret < 0) { - printk(KERN_ERR - "comedi%d: error! cannot enable PCI device " - "and request regions!\n", dev->minor); + dev_err(dev->class_dev, + "error! cannot enable PCI device and request regions!\n" + ); return ret; } spin_lock_init(&devpriv->ao_spinlock); @@ -1368,8 +1380,7 @@ static int pci224_attach_common(struct comedi_device *dev, /* Allocate subdevices. There is only one! */ ret = alloc_subdevices(dev, 1); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -1403,10 +1414,9 @@ static int pci224_attach_common(struct comedi_device *dev, if (options) { for (n = 2; n < 3 + s->n_chan; n++) { if (options[n] < 0 || options[n] > 1) { - printk(KERN_WARNING - "comedi%d: %s: warning! bad options[%u]=%d\n", - dev->minor, DRIVER_NAME, n, - options[n]); + dev_warn(dev->class_dev, DRIVER_NAME + ": warning! bad options[%u]=%d\n", + n, options[n]); } } } @@ -1435,9 +1445,9 @@ static int pci224_attach_common(struct comedi_device *dev, devpriv->hwrange = hwrange_pci224_external; } else { if (options && options[2] != 0) { - printk(KERN_WARNING "comedi%d: %s: warning! " - "bad options[2]=%d\n", - dev->minor, DRIVER_NAME, options[2]); + dev_warn(dev->class_dev, DRIVER_NAME + ": warning! bad options[2]=%d\n", + options[2]); } s->range_table = &range_pci224_internal; devpriv->hwrange = hwrange_pci224_internal; @@ -1450,24 +1460,15 @@ static int pci224_attach_common(struct comedi_device *dev, ret = request_irq(irq, pci224_interrupt, IRQF_SHARED, DRIVER_NAME, dev); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! " - "unable to allocate irq %u\n", dev->minor, irq); + dev_err(dev->class_dev, + "error! unable to allocate irq %u\n", irq); return ret; } else { dev->irq = irq; } } - printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); - printk("(pci %s) ", pci_name(pci_dev)); - if (irq) - printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); - else - printk("(no irq) "); - - - printk("attached\n"); - + pci224_report_attach(dev, irq); return 1; } @@ -1477,14 +1478,13 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it) int bus, slot; int ret; - printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME); + dev_info(dev->class_dev, DRIVER_NAME ": attach\n"); bus = it->options[0]; slot = it->options[1]; ret = alloc_private(dev, sizeof(struct pci224_private)); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } @@ -1500,21 +1500,19 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) { int ret; - printk(KERN_DEBUG "comedi%d: %s: attach_pci %s\n", dev->minor, - DRIVER_NAME, pci_name(pci_dev)); + dev_info(dev->class_dev, DRIVER_NAME ": attach_pci %s\n", + pci_name(pci_dev)); ret = alloc_private(dev, sizeof(struct pci224_private)); if (ret < 0) { - printk(KERN_ERR "comedi%d: error! out of memory!\n", - dev->minor); + dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } dev->board_ptr = pci224_find_pci_board(pci_dev); if (dev->board_ptr == NULL) { - printk(KERN_ERR - "comedi%d: %s: BUG! cannot determine board type!\n", - dev->minor, DRIVER_NAME); + dev_err(dev->class_dev, + DRIVER_NAME ": BUG! cannot determine board type!\n"); return -EINVAL; } return pci224_attach_common(dev, pci_dev, NULL); -- GitLab From 01ea83bce2d5219a71a044a084e3cecd6f0ad28e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 16:02:04 +0100 Subject: [PATCH 0249/5711] staging: comedi: amplc_pci224: Change return type of pci224_find_pci() pci224_find_pci() finds a supported PCI device, returning 0 on success or -EIO on failure and returning the pointer to the PCI device via a struct pci_dev ** parameter. Change it to return the struct pci_dev * on success or NULL on failure. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index a07546e0622e..4c41c289696c 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1255,14 +1255,11 @@ static const struct pci224_board * This function looks for a PCI device matching the requested board name, * bus and slot. */ -static int -pci224_find_pci(struct comedi_device *dev, int bus, int slot, - struct pci_dev **pci_dev_p) +static struct pci_dev * +pci224_find_pci(struct comedi_device *dev, int bus, int slot) { struct pci_dev *pci_dev = NULL; - *pci_dev_p = NULL; - /* Look for matching PCI device. */ for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); pci_dev != NULL; @@ -1289,8 +1286,7 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot, } /* Found a match. */ - *pci_dev_p = pci_dev; - return 0; + return pci_dev; } /* No match found. */ if (bus || slot) { @@ -1301,7 +1297,7 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot, dev_err(dev->class_dev, "error! no %s found!\n", thisboard->name); } - return -EIO; + return NULL; } static void pci224_report_attach(struct comedi_device *dev, unsigned int irq) @@ -1488,9 +1484,9 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } - ret = pci224_find_pci(dev, bus, slot, &pci_dev); - if (ret < 0) - return ret; + pci_dev = pci224_find_pci(dev, bus, slot); + if (pci_dev == NULL) + return -EIO; return pci224_attach_common(dev, pci_dev, it->options); } -- GitLab From 9dc5a822ea8eaa2397f95aace504fcc657a6cd8b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 31 May 2012 16:02:05 +0100 Subject: [PATCH 0250/5711] staging: comedi: amplc_pci224: Remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4c41c289696c..43f07f8f365e 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -377,11 +377,6 @@ static const struct pci224_board pci224_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((struct pci224_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ @@ -405,8 +400,6 @@ struct pci224_private { unsigned char intsce; }; -#define devpriv ((struct pci224_private *)dev->private) - /* * Called from the 'insn_write' function to perform a single write. */ @@ -414,6 +407,8 @@ static void pci224_ao_set_data(struct comedi_device *dev, int chan, int range, unsigned int data) { + const struct pci224_board *thisboard = comedi_board(dev); + struct pci224_private *devpriv = dev->private; unsigned short mangled; /* Store unmangled data for readback. */ @@ -476,6 +471,7 @@ static int pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci224_private *devpriv = dev->private; int i; int chan; @@ -504,6 +500,7 @@ pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2, static void pci224_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci224_private *devpriv = dev->private; unsigned long flags; if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state)) @@ -547,6 +544,7 @@ static void pci224_ao_stop(struct comedi_device *dev, static void pci224_ao_start(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci224_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; @@ -575,6 +573,7 @@ static void pci224_ao_start(struct comedi_device *dev, static void pci224_ao_handle_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci224_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int num_scans; unsigned int room; @@ -721,6 +720,7 @@ static int pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + struct pci224_private *devpriv = dev->private; int err = 0; unsigned int tmp; @@ -991,6 +991,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, */ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci224_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int range; unsigned int i, j; @@ -1163,6 +1164,8 @@ static void pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int chan_index) { + const struct pci224_board *thisboard = comedi_board(dev); + struct pci224_private *devpriv = dev->private; struct comedi_async *async = s->async; short *array = data; unsigned int length = num_bytes / sizeof(*array); @@ -1193,6 +1196,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, static irqreturn_t pci224_interrupt(int irq, void *d) { struct comedi_device *dev = d; + struct pci224_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; struct comedi_cmd *cmd; unsigned char intstat, valid_intstat; @@ -1258,6 +1262,7 @@ static const struct pci224_board static struct pci_dev * pci224_find_pci(struct comedi_device *dev, int bus, int slot) { + const struct pci224_board *thisboard = comedi_board(dev); struct pci_dev *pci_dev = NULL; /* Look for matching PCI device. */ @@ -1279,6 +1284,7 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot) continue; /* Change board_ptr to matched board. */ dev->board_ptr = board_ptr; + thisboard = comedi_board(dev); } else { /* Match specific model name. */ if (thisboard->devid != pci_dev->device) @@ -1302,6 +1308,7 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot) static void pci224_report_attach(struct comedi_device *dev, unsigned int irq) { + struct pci224_private *devpriv = dev->private; char tmpbuf[30]; if (irq) @@ -1319,6 +1326,8 @@ static void pci224_report_attach(struct comedi_device *dev, unsigned int irq) static int pci224_attach_common(struct comedi_device *dev, struct pci_dev *pci_dev, int *options) { + const struct pci224_board *thisboard = comedi_board(dev); + struct pci224_private *devpriv = dev->private; struct comedi_subdevice *s; unsigned int irq; unsigned n; @@ -1516,6 +1525,8 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) static void pci224_detach(struct comedi_device *dev) { + struct pci224_private *devpriv = dev->private; + if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) { -- GitLab From 4b05d17d8dcea60ccb1c39aaec60164dccdbc3e5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:39 +0100 Subject: [PATCH 0251/5711] staging: comedi: amplc_pci230: Replace printk calls Replace the printk calls with dev_info, dev_err, etc. A load of DPRINTK() macro calls which may result in printk() calls have been left alone to be tackled en masse at a later date. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index b05a684b80ba..512ead739895 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -697,8 +697,8 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pci_dev *pci_dev = NULL; int i = 0, irq_hdl, rc; - printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor, - thisboard->name, it->options[0], it->options[1]); + dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n", + thisboard->name, it->options[0], it->options[1]); /* Allocate the private structure area using alloc_private(). * Macro defined in comedidev.h - memsets struct fields to 0. */ @@ -772,8 +772,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } if (!pci_dev) { - printk("comedi%d: No %s card found\n", dev->minor, - thisboard->name); + dev_err(dev->class_dev, "No %s card found\n", thisboard->name); return -EIO; } devpriv->pci_dev = pci_dev; @@ -785,8 +784,8 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Enable PCI device and reserve I/O spaces. */ if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) { - printk("comedi%d: failed to enable PCI device " - "and request regions\n", dev->minor); + dev_err(dev->class_dev, + "failed to enable PCI device and request regions\n"); return -EIO; } @@ -795,8 +794,9 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase1 = pci_resource_start(pci_dev, 2); iobase2 = pci_resource_start(pci_dev, 3); - printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", - dev->minor, dev->board_name, iobase1, iobase2); + dev_dbg(dev->class_dev, + "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", + dev->board_name, iobase1, iobase2); devpriv->iobase1 = iobase1; dev->iobase = iobase2; @@ -811,10 +811,10 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->hwver = inw(dev->iobase + PCI230P_HWVER); if (devpriv->hwver < thisboard->min_hwver) { - printk("comedi%d: %s - bad hardware version " - "- got %u, need %u\n", dev->minor, - dev->board_name, devpriv->hwver, - thisboard->min_hwver); + dev_err(dev->class_dev, + "%s - bad hardware version - got %u, need %u\n", + dev->board_name, devpriv->hwver, + thisboard->min_hwver); return -EIO; } if (devpriv->hwver > 0) { @@ -862,13 +862,13 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt, IRQF_SHARED, "amplc_pci230", dev); if (irq_hdl < 0) { - printk("comedi%d: unable to register irq, " - "commands will not be available %d\n", dev->minor, - devpriv->pci_dev->irq); + dev_warn(dev->class_dev, + "unable to register irq %u, commands will not be available\n", + devpriv->pci_dev->irq); } else { dev->irq = devpriv->pci_dev->irq; - printk("comedi%d: registered irq %u\n", dev->minor, - devpriv->pci_dev->irq); + dev_dbg(dev->class_dev, "registered irq %u\n", + devpriv->pci_dev->irq); } /* @@ -931,7 +931,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - printk("comedi%d: attached\n", dev->minor); + dev_info(dev->class_dev, "attached\n"); return 1; } @@ -1117,9 +1117,7 @@ static int pci230_ai_rinsn(struct comedi_device *dev, udelay(1); } if (i == TIMEOUT) { - /* printk() should be used instead of printk() - * whenever the code can be called from real-time. */ - printk("timeout\n"); + dev_err(dev->class_dev, "timeout\n"); return -ETIMEDOUT; } @@ -1992,13 +1990,9 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, (s->n_chan / 2) - 1); } if ((errors & buggy_chan0_err) != 0) { - /* Use printk instead of DPRINTK here. */ - printk("comedi: comedi%d: amplc_pci230: " - "ai_cmdtest: Buggy PCI230+/260+ " - "h/w version %u requires first channel " - "of multi-channel sequence to be 0 " - "(corrected in h/w version 4)\n", - dev->minor, devpriv->hwver); + dev_info(dev->class_dev, + "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n", + devpriv->hwver); } } } -- GitLab From 967bfbc2c90e456bdfc0ef045dd1e81221461c06 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:40 +0100 Subject: [PATCH 0252/5711] staging: comedi: amplc_pci230: Remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables wherever they occur. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 512ead739895..6d3c6c9dff00 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -499,11 +499,7 @@ static const struct pci230_board pci230_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ #define n_pci230_boards ARRAY_SIZE(pci230_boards) -#define thisboard ((const struct pci230_board *)dev->board_ptr) /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, @@ -548,8 +544,6 @@ struct pci230_private { unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */ }; -#define devpriv ((struct pci230_private *)dev->private) - /* PCI230 clock source periods in ns */ static const unsigned int pci230_timebase[8] = { [CLK_10MHZ] = TIMEBASE_10MHZ, @@ -627,9 +621,12 @@ static void pci230_handle_ai(struct comedi_device *dev, static short pci230_ai_read(struct comedi_device *dev) { - /* Read sample. */ - short data = (short)inw(dev->iobase + PCI230_ADCDATA); + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; + short data; + /* Read sample. */ + data = (short)inw(dev->iobase + PCI230_ADCDATA); /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower * four bits reserved for expansion). */ /* PCI230+ is 16 bit AI. */ @@ -646,12 +643,14 @@ static short pci230_ai_read(struct comedi_device *dev) static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, short datum) { + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; + /* If a bipolar range was specified, mangle it (straight binary->twos * complement). */ if (devpriv->ao_bipolar) datum ^= 1 << (thisboard->ao_bits - 1); - /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower * four bits reserved for expansion). */ /* PCI230+ is also 12 bit AO. */ @@ -662,6 +661,8 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, static inline void pci230_ao_write_nofifo(struct comedi_device *dev, short datum, unsigned int chan) { + struct pci230_private *devpriv = dev->private; + /* Store unmangled datum to be read back later. */ devpriv->ao_readback[chan] = datum; @@ -675,6 +676,8 @@ static inline void pci230_ao_write_nofifo(struct comedi_device *dev, static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum, unsigned int chan) { + struct pci230_private *devpriv = dev->private; + /* Store unmangled datum to be read back later. */ devpriv->ao_readback[chan] = datum; @@ -691,6 +694,8 @@ static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum, */ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv; struct comedi_subdevice *s; unsigned long iobase1, iobase2; /* PCI230's I/O spaces 1 and 2 respectively. */ @@ -704,6 +709,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Macro defined in comedidev.h - memsets struct fields to 0. */ if ((alloc_private(dev, sizeof(struct pci230_private))) < 0) return -ENOMEM; + devpriv = dev->private; spin_lock_init(&devpriv->isr_spinlock); spin_lock_init(&devpriv->res_spinlock); @@ -742,6 +748,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Change board_ptr to matched board */ dev->board_ptr = &pci230_boards[i]; + thisboard = comedi_board(dev); break; } } @@ -938,6 +945,9 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pci230_detach(struct comedi_device *dev) { + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; + if (dev->subdevices && thisboard->have_dio) subdev_8255_cleanup(dev, dev->subdevices + 2); if (dev->irq) @@ -954,6 +964,7 @@ static void pci230_detach(struct comedi_device *dev) static int get_resources(struct comedi_device *dev, unsigned int res_mask, unsigned char owner) { + struct pci230_private *devpriv = dev->private; int ok; unsigned int i; unsigned int b; @@ -996,6 +1007,7 @@ static inline int get_one_resource(struct comedi_device *dev, static void put_resources(struct comedi_device *dev, unsigned int res_mask, unsigned char owner) { + struct pci230_private *devpriv = dev->private; unsigned int i; unsigned int b; unsigned long irqflags; @@ -1032,6 +1044,7 @@ static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci230_private *devpriv = dev->private; unsigned int n, i; unsigned int chan, range, aref; unsigned int gainshift; @@ -1136,6 +1149,7 @@ static int pci230_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci230_private *devpriv = dev->private; int i; int chan, range; @@ -1165,6 +1179,7 @@ static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci230_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -1177,6 +1192,8 @@ static int pci230_ao_rinsn(struct comedi_device *dev, static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; int err = 0; unsigned int tmp; @@ -1390,6 +1407,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; if (trig_num != 0) @@ -1422,6 +1440,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, static void pci230_ao_start(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long irqflags; @@ -1523,6 +1542,7 @@ static int pci230_ao_inttrig_start(struct comedi_device *dev, static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned short daccon; unsigned int range; @@ -1625,6 +1645,8 @@ static int pci230_ai_check_scan_period(struct comedi_cmd *cmd) static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; int err = 0; unsigned int tmp; @@ -2006,6 +2028,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int scanlen = cmd->scan_end_arg; unsigned int wake; @@ -2050,6 +2073,7 @@ static int pci230_ai_inttrig_convert(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; if (trig_num != 0) @@ -2092,6 +2116,7 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; unsigned char zgat; @@ -2114,6 +2139,7 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, static void pci230_ai_start(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; unsigned short conv; struct comedi_async *async = s->async; @@ -2264,6 +2290,7 @@ static int pci230_ai_inttrig_start(struct comedi_device *dev, static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned int i, chan, range, diff; unsigned int res_mask; unsigned short adccon, adcen; @@ -2509,6 +2536,7 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, unsigned int mode, uint64_t ns, unsigned int round) { + struct pci230_private *devpriv = dev->private; unsigned int clk_src; unsigned int count; @@ -2527,6 +2555,8 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct) { + struct pci230_private *devpriv = dev->private; + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, I8254_MODE1); /* Counter ct, 8254 mode 1, initial count not written. */ @@ -2537,6 +2567,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d) { unsigned char status_int, valid_status_int; struct comedi_device *dev = (struct comedi_device *)d; + struct pci230_private *devpriv = dev->private; struct comedi_subdevice *s; unsigned long irqflags; @@ -2599,6 +2630,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d) static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; short data; int i, ret; struct comedi_async *async = s->async; @@ -2637,6 +2669,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int num_scans; @@ -2742,6 +2775,7 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned int events = 0; unsigned int status_fifo; unsigned int i; @@ -2842,6 +2876,7 @@ static void pci230_handle_ai(struct comedi_device *dev, static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; unsigned char intsrc; int started; @@ -2905,6 +2940,7 @@ static int pci230_ao_cancel(struct comedi_device *dev, static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci230_private *devpriv = dev->private; unsigned long irqflags; struct comedi_cmd *cmd; int started; -- GitLab From ba54fa6893aa72159c046c6099f7644df745feea Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:41 +0100 Subject: [PATCH 0253/5711] staging: comedi: amplc_pci230: Add attach_pci() hook Implement the attach_pci() hook as function pci230_attach_pci(). This is called by comedi_pci_auto_config() in preference to the old attach() hook (implemented by pci230_attach() and still required for "manual" configuration of comedi devices). The advantage of the attach_pci() hook is that it avoids searching for the PCI device. Refactor pci230_attach() and factor out code common to pci230_attach() and pci230_attach_pci() into new functions pci230_match_pci_board(), pci230_find_pci_board(), pci230_find_pci(), pci230_alloc_private() and pci230_attach_common(). Finally, move pci230_attach() and pci230_detach() along with all the new functions towards the bottom of the file as it makes the patch much cleaner (though longer) and I plan to move things around soon to get rid of the remaining forward references. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 578 +++++++++--------- 1 file changed, 301 insertions(+), 277 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 6d3c6c9dff00..fbc9da99c6f5 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -499,8 +499,6 @@ static const struct pci230_board pci230_boards[] = { }, }; -#define n_pci230_boards ARRAY_SIZE(pci230_boards) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ @@ -686,281 +684,6 @@ static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum, dev->iobase + PCI230P2_DACDATA); } -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ - const struct pci230_board *thisboard = comedi_board(dev); - struct pci230_private *devpriv; - struct comedi_subdevice *s; - unsigned long iobase1, iobase2; - /* PCI230's I/O spaces 1 and 2 respectively. */ - struct pci_dev *pci_dev = NULL; - int i = 0, irq_hdl, rc; - - dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n", - thisboard->name, it->options[0], it->options[1]); - - /* Allocate the private structure area using alloc_private(). - * Macro defined in comedidev.h - memsets struct fields to 0. */ - if ((alloc_private(dev, sizeof(struct pci230_private))) < 0) - return -ENOMEM; - devpriv = dev->private; - - spin_lock_init(&devpriv->isr_spinlock); - spin_lock_init(&devpriv->res_spinlock); - spin_lock_init(&devpriv->ai_stop_spinlock); - spin_lock_init(&devpriv->ao_stop_spinlock); - /* Find card */ - for_each_pci_dev(pci_dev) { - if (it->options[0] || it->options[1]) { - /* Match against bus/slot options. */ - if (it->options[0] != pci_dev->bus->number || - it->options[1] != PCI_SLOT(pci_dev->devfn)) - continue; - } - if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON) - continue; - if (thisboard->id == PCI_DEVICE_ID_INVALID) { - /* The name was specified as "amplc_pci230" which is - * used to match any supported device. Replace the - * current dev->board_ptr with one that matches the - * PCI device ID. */ - for (i = 0; i < n_pci230_boards; i++) { - if (pci_dev->device == pci230_boards[i].id) { - if (pci230_boards[i].min_hwver > 0) { - /* Check for a '+' model. - * First check length of - * registers. */ - if (pci_resource_len(pci_dev, 3) - < 32) { - /* Not a '+' model. */ - continue; - } - /* TODO: temporarily enable the - * PCI device and read the - * hardware version register. - * For now assume it's okay. */ - } - /* Change board_ptr to matched board */ - dev->board_ptr = &pci230_boards[i]; - thisboard = comedi_board(dev); - break; - } - } - if (i < n_pci230_boards) - break; - } else { - /* The name was specified as a specific device name. - * The current dev->board_ptr is correct. Check - * whether it matches the PCI device ID. */ - if (thisboard->id == pci_dev->device) { - /* Check minimum hardware version. */ - if (thisboard->min_hwver > 0) { - /* Looking for a '+' model. First - * check length of registers. */ - if (pci_resource_len(pci_dev, 3) < 32) { - /* Not a '+' model. */ - continue; - } - /* TODO: temporarily enable the PCI - * device and read the hardware version - * register. For now, assume it's - * okay. */ - break; - } else { - break; - } - } - } - } - if (!pci_dev) { - dev_err(dev->class_dev, "No %s card found\n", thisboard->name); - return -EIO; - } - devpriv->pci_dev = pci_dev; - - /* - * Initialize dev->board_name. - */ - dev->board_name = thisboard->name; - - /* Enable PCI device and reserve I/O spaces. */ - if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) { - dev_err(dev->class_dev, - "failed to enable PCI device and request regions\n"); - return -EIO; - } - - /* Read base addresses of the PCI230's two I/O regions from PCI - * configuration register. */ - iobase1 = pci_resource_start(pci_dev, 2); - iobase2 = pci_resource_start(pci_dev, 3); - - dev_dbg(dev->class_dev, - "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", - dev->board_name, iobase1, iobase2); - - devpriv->iobase1 = iobase1; - dev->iobase = iobase2; - - /* Read bits of DACCON register - only the output range. */ - devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK; - - /* Read hardware version register and set extended function register - * if they exist. */ - if (pci_resource_len(pci_dev, 3) >= 32) { - unsigned short extfunc = 0; - - devpriv->hwver = inw(dev->iobase + PCI230P_HWVER); - if (devpriv->hwver < thisboard->min_hwver) { - dev_err(dev->class_dev, - "%s - bad hardware version - got %u, need %u\n", - dev->board_name, devpriv->hwver, - thisboard->min_hwver); - return -EIO; - } - if (devpriv->hwver > 0) { - if (!thisboard->have_dio) { - /* No DIO ports. Route counters' external gates - * to the EXTTRIG signal (PCI260+ pin 17). - * (Otherwise, they would be routed to DIO - * inputs PC0, PC1 and PC2 which don't exist - * on PCI260[+].) */ - extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; - } - if ((thisboard->ao_chans > 0) - && (devpriv->hwver >= 2)) { - /* Enable DAC FIFO functionality. */ - extfunc |= PCI230P2_EXTFUNC_DACFIFO; - } - } - outw(extfunc, dev->iobase + PCI230P_EXTFUNC); - if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) { - /* Temporarily enable DAC FIFO, reset it and disable - * FIFO wraparound. */ - outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN - | PCI230P2_DAC_FIFO_RESET, - dev->iobase + PCI230_DACCON); - /* Clear DAC FIFO channel enable register. */ - outw(0, dev->iobase + PCI230P2_DACEN); - /* Disable DAC FIFO. */ - outw(devpriv->daccon, dev->iobase + PCI230_DACCON); - } - } - - /* Disable board's interrupts. */ - outb(0, devpriv->iobase1 + PCI230_INT_SCE); - - /* Set ADC to a reasonable state. */ - devpriv->adcg = 0; - devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE - | PCI230_ADC_IR_BIP; - outw(1 << 0, dev->iobase + PCI230_ADCEN); - outw(devpriv->adcg, dev->iobase + PCI230_ADCG); - outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, - dev->iobase + PCI230_ADCCON); - - /* Register the interrupt handler. */ - irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt, - IRQF_SHARED, "amplc_pci230", dev); - if (irq_hdl < 0) { - dev_warn(dev->class_dev, - "unable to register irq %u, commands will not be available\n", - devpriv->pci_dev->irq); - } else { - dev->irq = devpriv->pci_dev->irq; - dev_dbg(dev->class_dev, "registered irq %u\n", - devpriv->pci_dev->irq); - } - - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ - if (alloc_subdevices(dev, 3) < 0) - return -ENOMEM; - - s = dev->subdevices + 0; - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; - s->n_chan = thisboard->ai_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = &pci230_ai_range; - s->insn_read = &pci230_ai_rinsn; - s->len_chanlist = 256; /* but there are restrictions. */ - /* Only register commands if the interrupt handler is installed. */ - if (irq_hdl == 0) { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->do_cmd = &pci230_ai_cmd; - s->do_cmdtest = &pci230_ai_cmdtest; - s->cancel = pci230_ai_cancel; - } - - s = dev->subdevices + 1; - /* analog output subdevice */ - if (thisboard->ao_chans > 0) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = thisboard->ao_chans; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = &pci230_ao_range; - s->insn_write = &pci230_ao_winsn; - s->insn_read = &pci230_ao_rinsn; - s->len_chanlist = thisboard->ao_chans; - /* Only register commands if the interrupt handler is - * installed. */ - if (irq_hdl == 0) { - dev->write_subdev = s; - s->subdev_flags |= SDF_CMD_WRITE; - s->do_cmd = &pci230_ao_cmd; - s->do_cmdtest = &pci230_ao_cmdtest; - s->cancel = pci230_ao_cancel; - } - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - s = dev->subdevices + 2; - /* digital i/o subdevice */ - if (thisboard->have_dio) { - rc = subdev_8255_init(dev, s, NULL, - (devpriv->iobase1 + PCI230_PPI_X_BASE)); - if (rc < 0) - return rc; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - dev_info(dev->class_dev, "attached\n"); - - return 1; -} - -static void pci230_detach(struct comedi_device *dev) -{ - const struct pci230_board *thisboard = comedi_board(dev); - struct pci230_private *devpriv = dev->private; - - if (dev->subdevices && thisboard->have_dio) - subdev_8255_cleanup(dev, dev->subdevices + 2); - if (dev->irq) - free_irq(dev->irq, dev); - if (devpriv) { - if (devpriv->pci_dev) { - if (dev->iobase) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); - } - } -} - static int get_resources(struct comedi_device *dev, unsigned int res_mask, unsigned char owner) { @@ -2995,10 +2718,311 @@ static int pci230_ai_cancel(struct comedi_device *dev, return 0; } +/* Check if PCI device matches a specific board. */ +static bool pci230_match_pci_board(const struct pci230_board *board, + struct pci_dev *pci_dev) +{ + /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */ + if (board->id != pci_dev->device) + return false; + if (board->min_hwver == 0) + return true; + /* Looking for a '+' model. First check length of registers. */ + if (pci_resource_len(pci_dev, 3) < 32) + return false; /* Not a '+' model. */ + /* TODO: temporarily enable PCI device and read the hardware version + * register. For now, assume it's okay. */ + return true; +} + +/* Look for board matching PCI device. */ +static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pci230_boards); i++) + if (pci230_match_pci_board(&pci230_boards[i], pci_dev)) + return &pci230_boards[i]; + return NULL; +} + +/* Look for PCI device matching requested board name, bus and slot. */ +static struct pci_dev *pci230_find_pci(struct comedi_device *dev, + int bus, int slot) +{ + const struct pci230_board *thisboard = comedi_board(dev); + struct pci_dev *pci_dev = NULL; + + for_each_pci_dev(pci_dev) { + /* Check vendor ID (same for all supported PCI boards). */ + if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON) + continue; + /* If bus/slot specified, check them. */ + if ((bus || slot) && + (bus != pci_dev->bus->number || + slot != PCI_SLOT(pci_dev->devfn))) + continue; + if (thisboard->id == PCI_DEVICE_ID_INVALID) { + /* Wildcard board matches any supported PCI board. */ + const struct pci230_board *foundboard; + + foundboard = pci230_find_pci_board(pci_dev); + if (foundboard == NULL) + continue; + /* Replace wildcard board_ptr. */ + dev->board_ptr = foundboard; + thisboard = comedi_board(dev); + } else { + /* Need to match a specific board. */ + if (!pci230_match_pci_board(thisboard, pci_dev)) + continue; + } + /* Found a matching PCI device. */ + return pci_dev; + } + /* No matching PCI device found. */ + if (bus || slot) + dev_err(dev->class_dev, + "error! no %s found at pci %02x:%02x\n", + thisboard->name, bus, slot); + else + dev_err(dev->class_dev, + "error! no %s found\n", thisboard->name); + return NULL; +} + +static int pci230_alloc_private(struct comedi_device *dev) +{ + struct pci230_private *devpriv; + int err; + + /* sets dev->private to allocated memory */ + err = alloc_private(dev, sizeof(struct pci230_private)); + if (err) { + dev_err(dev->class_dev, "error! out of memory!\n"); + return err; + } + devpriv = dev->private; + spin_lock_init(&devpriv->isr_spinlock); + spin_lock_init(&devpriv->res_spinlock); + spin_lock_init(&devpriv->ai_stop_spinlock); + spin_lock_init(&devpriv->ao_stop_spinlock); + return 0; +} + +/* Common part of attach and attach_pci. */ +static int pci230_attach_common(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; + struct comedi_subdevice *s; + unsigned long iobase1, iobase2; + /* PCI230's I/O spaces 1 and 2 respectively. */ + int irq_hdl, rc; + + devpriv->pci_dev = pci_dev; + dev->board_name = thisboard->name; + /* Enable PCI device and reserve I/O spaces. */ + if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) { + dev_err(dev->class_dev, + "failed to enable PCI device and request regions\n"); + return -EIO; + } + /* Read base addresses of the PCI230's two I/O regions from PCI + * configuration register. */ + iobase1 = pci_resource_start(pci_dev, 2); + iobase2 = pci_resource_start(pci_dev, 3); + dev_dbg(dev->class_dev, + "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", + dev->board_name, iobase1, iobase2); + devpriv->iobase1 = iobase1; + dev->iobase = iobase2; + /* Read bits of DACCON register - only the output range. */ + devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK; + /* Read hardware version register and set extended function register + * if they exist. */ + if (pci_resource_len(pci_dev, 3) >= 32) { + unsigned short extfunc = 0; + + devpriv->hwver = inw(dev->iobase + PCI230P_HWVER); + if (devpriv->hwver < thisboard->min_hwver) { + dev_err(dev->class_dev, + "%s - bad hardware version - got %u, need %u\n", + dev->board_name, devpriv->hwver, + thisboard->min_hwver); + return -EIO; + } + if (devpriv->hwver > 0) { + if (!thisboard->have_dio) { + /* No DIO ports. Route counters' external gates + * to the EXTTRIG signal (PCI260+ pin 17). + * (Otherwise, they would be routed to DIO + * inputs PC0, PC1 and PC2 which don't exist + * on PCI260[+].) */ + extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; + } + if ((thisboard->ao_chans > 0) + && (devpriv->hwver >= 2)) { + /* Enable DAC FIFO functionality. */ + extfunc |= PCI230P2_EXTFUNC_DACFIFO; + } + } + outw(extfunc, dev->iobase + PCI230P_EXTFUNC); + if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) { + /* Temporarily enable DAC FIFO, reset it and disable + * FIFO wraparound. */ + outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN + | PCI230P2_DAC_FIFO_RESET, + dev->iobase + PCI230_DACCON); + /* Clear DAC FIFO channel enable register. */ + outw(0, dev->iobase + PCI230P2_DACEN); + /* Disable DAC FIFO. */ + outw(devpriv->daccon, dev->iobase + PCI230_DACCON); + } + } + /* Disable board's interrupts. */ + outb(0, devpriv->iobase1 + PCI230_INT_SCE); + /* Set ADC to a reasonable state. */ + devpriv->adcg = 0; + devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE + | PCI230_ADC_IR_BIP; + outw(1 << 0, dev->iobase + PCI230_ADCEN); + outw(devpriv->adcg, dev->iobase + PCI230_ADCG); + outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, + dev->iobase + PCI230_ADCCON); + /* Register the interrupt handler. */ + irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt, + IRQF_SHARED, "amplc_pci230", dev); + if (irq_hdl < 0) { + dev_warn(dev->class_dev, + "unable to register irq %u, commands will not be available\n", + devpriv->pci_dev->irq); + } else { + dev->irq = devpriv->pci_dev->irq; + dev_dbg(dev->class_dev, "registered irq %u\n", + devpriv->pci_dev->irq); + } + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + s = dev->subdevices + 0; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; + s->n_chan = thisboard->ai_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &pci230_ai_range; + s->insn_read = &pci230_ai_rinsn; + s->len_chanlist = 256; /* but there are restrictions. */ + /* Only register commands if the interrupt handler is installed. */ + if (irq_hdl == 0) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmd = &pci230_ai_cmd; + s->do_cmdtest = &pci230_ai_cmdtest; + s->cancel = pci230_ai_cancel; + } + s = dev->subdevices + 1; + /* analog output subdevice */ + if (thisboard->ao_chans > 0) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = thisboard->ao_chans; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = &pci230_ao_range; + s->insn_write = &pci230_ao_winsn; + s->insn_read = &pci230_ao_rinsn; + s->len_chanlist = thisboard->ao_chans; + /* Only register commands if the interrupt handler is + * installed. */ + if (irq_hdl == 0) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->do_cmd = &pci230_ao_cmd; + s->do_cmdtest = &pci230_ao_cmdtest; + s->cancel = pci230_ao_cancel; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->have_dio) { + rc = subdev_8255_init(dev, s, NULL, + (devpriv->iobase1 + PCI230_PPI_X_BASE)); + if (rc < 0) + return rc; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + dev_info(dev->class_dev, "attached\n"); + return 1; +} + +static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + const struct pci230_board *thisboard = comedi_board(dev); + struct pci_dev *pci_dev; + int rc; + + dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n", + thisboard->name, it->options[0], it->options[1]); + rc = pci230_alloc_private(dev); /* sets dev->private */ + if (rc) + return rc; + /* Find card. */ + pci_dev = pci230_find_pci(dev, it->options[0], it->options[1]); + if (!pci_dev) + return -EIO; + return pci230_attach_common(dev, pci_dev); +} + +static int __devinit pci230_attach_pci(struct comedi_device *dev, + struct pci_dev *pci_dev) +{ + int rc; + + dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n", + pci_name(pci_dev)); + rc = pci230_alloc_private(dev); /* sets dev->private */ + if (rc) + return rc; + dev->board_ptr = pci230_find_pci_board(pci_dev); + if (dev->board_ptr == NULL) { + dev_err(dev->class_dev, + "amplc_pci230: BUG! cannot determine board type!\n"); + return -EINVAL; + } + return pci230_attach_common(dev, pci_dev); +} + +static void pci230_detach(struct comedi_device *dev) +{ + const struct pci230_board *thisboard = comedi_board(dev); + struct pci230_private *devpriv = dev->private; + + if (dev->subdevices && thisboard->have_dio) + subdev_8255_cleanup(dev, dev->subdevices + 2); + if (dev->irq) + free_irq(dev->irq, dev); + if (devpriv) { + if (devpriv->pci_dev) { + if (dev->iobase) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } + } +} + static struct comedi_driver amplc_pci230_driver = { .driver_name = "amplc_pci230", .module = THIS_MODULE, .attach = pci230_attach, + .attach_pci = pci230_attach_pci, .detach = pci230_detach, .board_name = &pci230_boards[0].name, .offset = sizeof(pci230_boards[0]), -- GitLab From 027ee06835e96d425998003fe0b60ab128581fd6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:42 +0100 Subject: [PATCH 0254/5711] staging: comedi: amplc_pci230: Remove forward declarations 1 Remove the redundant forward function declarations. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index fbc9da99c6f5..a99e90f7b556 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -579,39 +579,17 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static int pci230_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int pci230_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int pci230_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, unsigned int mode, uint64_t ns, unsigned int round); static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round); static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct); -static irqreturn_t pci230_interrupt(int irq, void *d); -static int pci230_ao_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int pci230_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s); static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s); static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s); -static int pci230_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int pci230_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s); static void pci230_handle_ai(struct comedi_device *dev, -- GitLab From 091e8d8ff434f5e6e67dcfd742e2df8cac999ce4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:43 +0100 Subject: [PATCH 0255/5711] staging: comedi: amplc_pci230: Remove forward declarations 2 Remove some forward function declarations: pci230_ct_setup_ns_mode(), pci230_ns_to_single_timer(), pci230_cancel_ct(). Also need to move: divide_ns(). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 165 +++++++++--------- 1 file changed, 80 insertions(+), 85 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index a99e90f7b556..d028962a5384 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -579,11 +579,6 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, - unsigned int mode, uint64_t ns, - unsigned int round); -static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round); -static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct); static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s); static void pci230_handle_ao_nofifo(struct comedi_device *dev, @@ -738,6 +733,86 @@ static inline void put_all_resources(struct comedi_device *dev, put_resources(dev, (1U << NUM_RESOURCES) - 1, owner); } +static unsigned int divide_ns(uint64_t ns, unsigned int timebase, + unsigned int round_mode) +{ + uint64_t div; + unsigned int rem; + + div = ns; + rem = do_div(div, timebase); + round_mode &= TRIG_ROUND_MASK; + switch (round_mode) { + default: + case TRIG_ROUND_NEAREST: + div += (rem + (timebase / 2)) / timebase; + break; + case TRIG_ROUND_DOWN: + break; + case TRIG_ROUND_UP: + div += (rem + timebase - 1) / timebase; + break; + } + return div > UINT_MAX ? UINT_MAX : (unsigned int)div; +} + +/* Given desired period in ns, returns the required internal clock source + * and gets the initial count. */ +static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count, + unsigned int round_mode) +{ + unsigned int clk_src, cnt; + + for (clk_src = CLK_10MHZ;; clk_src++) { + cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode); + if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) + break; + + } + *count = cnt; + return clk_src; +} + +static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round) +{ + unsigned int count; + unsigned int clk_src; + + clk_src = pci230_choose_clk_count(*ns, &count, round); + *ns = count * pci230_timebase[clk_src]; + return; +} + +static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, + unsigned int mode, uint64_t ns, + unsigned int round) +{ + struct pci230_private *devpriv = dev->private; + unsigned int clk_src; + unsigned int count; + + /* Set mode. */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode); + /* Determine clock source and count. */ + clk_src = pci230_choose_clk_count(ns, &count, round); + /* Program clock source. */ + outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE); + /* Set initial count. */ + if (count >= 65536) + count = 0; + + i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count); +} + +static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct) +{ + struct pci230_private *devpriv = dev->private; + + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, + I8254_MODE1); + /* Counter ct, 8254 mode 1, initial count not written. */ +} + /* * COMEDI_SUBD_AI instruction; */ @@ -2183,86 +2258,6 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static unsigned int divide_ns(uint64_t ns, unsigned int timebase, - unsigned int round_mode) -{ - uint64_t div; - unsigned int rem; - - div = ns; - rem = do_div(div, timebase); - round_mode &= TRIG_ROUND_MASK; - switch (round_mode) { - default: - case TRIG_ROUND_NEAREST: - div += (rem + (timebase / 2)) / timebase; - break; - case TRIG_ROUND_DOWN: - break; - case TRIG_ROUND_UP: - div += (rem + timebase - 1) / timebase; - break; - } - return div > UINT_MAX ? UINT_MAX : (unsigned int)div; -} - -/* Given desired period in ns, returns the required internal clock source - * and gets the initial count. */ -static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count, - unsigned int round_mode) -{ - unsigned int clk_src, cnt; - - for (clk_src = CLK_10MHZ;; clk_src++) { - cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode); - if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) - break; - - } - *count = cnt; - return clk_src; -} - -static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round) -{ - unsigned int count; - unsigned int clk_src; - - clk_src = pci230_choose_clk_count(*ns, &count, round); - *ns = count * pci230_timebase[clk_src]; - return; -} - -static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, - unsigned int mode, uint64_t ns, - unsigned int round) -{ - struct pci230_private *devpriv = dev->private; - unsigned int clk_src; - unsigned int count; - - /* Set mode. */ - i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode); - /* Determine clock source and count. */ - clk_src = pci230_choose_clk_count(ns, &count, round); - /* Program clock source. */ - outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE); - /* Set initial count. */ - if (count >= 65536) - count = 0; - - i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count); -} - -static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct) -{ - struct pci230_private *devpriv = dev->private; - - i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, - I8254_MODE1); - /* Counter ct, 8254 mode 1, initial count not written. */ -} - /* Interrupt handler */ static irqreturn_t pci230_interrupt(int irq, void *d) { -- GitLab From bd4447e597e0609fccb91aeeb2add40a7fcf3289 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:44 +0100 Subject: [PATCH 0256/5711] staging: comedi: amplc_pci230: Remove forward declarations 3 Move these functions and remove their forward declarations: pci230_ao_stop(), pci230_handle_ao_nofifo(), pci230_handle_ao_fifo(). Also move pci230_ao_cancel() for aesthetic reasons. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 412 +++++++++--------- 1 file changed, 197 insertions(+), 215 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index d028962a5384..0e9c4ba6e6c0 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -579,12 +579,6 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static void pci230_ao_stop(struct comedi_device *dev, - struct comedi_subdevice *s); -static void pci230_handle_ao_nofifo(struct comedi_device *dev, - struct comedi_subdevice *s); -static int pci230_handle_ao_fifo(struct comedi_device *dev, - struct comedi_subdevice *s); static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s); static void pci230_handle_ai(struct comedi_device *dev, @@ -1179,6 +1173,196 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, return 0; } +static void pci230_ao_stop(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci230_private *devpriv = dev->private; + unsigned long irqflags; + unsigned char intsrc; + int started; + struct comedi_cmd *cmd; + + spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); + started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state); + spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); + if (!started) + return; + cmd = &s->async->cmd; + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Stop scan rate generator. */ + pci230_cancel_ct(dev, 1); + } + /* Determine interrupt source. */ + if (devpriv->hwver < 2) { + /* Not using DAC FIFO. Using CT1 interrupt. */ + intsrc = PCI230_INT_ZCLK_CT1; + } else { + /* Using DAC FIFO interrupt. */ + intsrc = PCI230P2_INT_DAC; + } + /* Disable interrupt and wait for interrupt routine to finish running + * unless we are called from the interrupt routine. */ + spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + devpriv->int_en &= ~intsrc; + while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { + spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + } + if (devpriv->ier != devpriv->int_en) { + devpriv->ier = devpriv->int_en; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + } + spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + if (devpriv->hwver >= 2) { + /* Using DAC FIFO. Reset FIFO, clear underrun error, + * disable FIFO. */ + devpriv->daccon &= PCI230_DAC_OR_MASK; + outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET + | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, + dev->iobase + PCI230_DACCON); + } + /* Release resources. */ + put_all_resources(dev, OWNER_AOCMD); +} + +static void pci230_handle_ao_nofifo(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci230_private *devpriv = dev->private; + short data; + int i, ret; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) + return; + for (i = 0; i < cmd->chanlist_len; i++) { + /* Read sample from Comedi's circular buffer. */ + ret = comedi_buf_get(s->async, &data); + if (ret == 0) { + s->async->events |= COMEDI_CB_OVERFLOW; + pci230_ao_stop(dev, s); + comedi_error(dev, "AO buffer underrun"); + return; + } + /* Write value to DAC. */ + pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i])); + } + async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + if (!devpriv->ao_continuous) { + devpriv->ao_scan_count--; + if (devpriv->ao_scan_count == 0) { + /* End of acquisition. */ + async->events |= COMEDI_CB_EOA; + pci230_ao_stop(dev, s); + } + } +} + +/* Loads DAC FIFO (if using it) from buffer. */ +/* Returns 0 if AO finished due to completion or error, 1 if still going. */ +static int pci230_handle_ao_fifo(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci230_private *devpriv = dev->private; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int num_scans; + unsigned int room; + unsigned short dacstat; + unsigned int i, n; + unsigned int bytes_per_scan; + unsigned int events = 0; + int running; + + /* Get DAC FIFO status. */ + dacstat = inw(dev->iobase + PCI230_DACCON); + /* Determine number of scans available in buffer. */ + bytes_per_scan = cmd->chanlist_len * sizeof(short); + num_scans = comedi_buf_read_n_available(async) / bytes_per_scan; + if (!devpriv->ao_continuous) { + /* Fixed number of scans. */ + if (num_scans > devpriv->ao_scan_count) + num_scans = devpriv->ao_scan_count; + if (devpriv->ao_scan_count == 0) { + /* End of acquisition. */ + events |= COMEDI_CB_EOA; + } + } + if (events == 0) { + /* Check for FIFO underrun. */ + if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { + comedi_error(dev, "AO FIFO underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + /* Check for buffer underrun if FIFO less than half full + * (otherwise there will be loads of "DAC FIFO not half full" + * interrupts). */ + if ((num_scans == 0) + && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) { + comedi_error(dev, "AO buffer underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + } + if (events == 0) { + /* Determine how much room is in the FIFO (in samples). */ + if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) + room = PCI230P2_DAC_FIFOROOM_FULL; + else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) + room = PCI230P2_DAC_FIFOROOM_HALFTOFULL; + else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) + room = PCI230P2_DAC_FIFOROOM_EMPTY; + else + room = PCI230P2_DAC_FIFOROOM_ONETOHALF; + /* Convert room to number of scans that can be added. */ + room /= cmd->chanlist_len; + /* Determine number of scans to process. */ + if (num_scans > room) + num_scans = room; + /* Process scans. */ + for (n = 0; n < num_scans; n++) { + for (i = 0; i < cmd->chanlist_len; i++) { + short datum; + + comedi_buf_get(async, &datum); + pci230_ao_write_fifo(dev, datum, + CR_CHAN(cmd->chanlist[i])); + } + } + events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK; + if (!devpriv->ao_continuous) { + devpriv->ao_scan_count -= num_scans; + if (devpriv->ao_scan_count == 0) { + /* All data for the command has been written + * to FIFO. Set FIFO interrupt trigger level + * to 'empty'. */ + devpriv->daccon = (devpriv->daccon + & + ~PCI230P2_DAC_INT_FIFO_MASK) + | PCI230P2_DAC_INT_FIFO_EMPTY; + outw(devpriv->daccon, + dev->iobase + PCI230_DACCON); + } + } + /* Check if FIFO underrun occurred while writing to FIFO. */ + dacstat = inw(dev->iobase + PCI230_DACCON); + if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { + comedi_error(dev, "AO FIFO underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + } + if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) + != 0) { + /* Stopping AO due to completion or error. */ + pci230_ao_stop(dev, s); + running = 0; + } else { + running = 1; + } + async->events |= events; + return running; +} + static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) @@ -1394,6 +1578,13 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +static int pci230_ao_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + pci230_ao_stop(dev, s); + return 0; +} + static int pci230_ai_check_scan_period(struct comedi_cmd *cmd) { unsigned int min_scan_period, chanlist_len; @@ -2323,151 +2514,6 @@ static irqreturn_t pci230_interrupt(int irq, void *d) return IRQ_HANDLED; } -static void pci230_handle_ao_nofifo(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci230_private *devpriv = dev->private; - short data; - int i, ret; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; - - if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) - return; - - - for (i = 0; i < cmd->chanlist_len; i++) { - /* Read sample from Comedi's circular buffer. */ - ret = comedi_buf_get(s->async, &data); - if (ret == 0) { - s->async->events |= COMEDI_CB_OVERFLOW; - pci230_ao_stop(dev, s); - comedi_error(dev, "AO buffer underrun"); - return; - } - /* Write value to DAC. */ - pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i])); - } - - async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - if (!devpriv->ao_continuous) { - devpriv->ao_scan_count--; - if (devpriv->ao_scan_count == 0) { - /* End of acquisition. */ - async->events |= COMEDI_CB_EOA; - pci230_ao_stop(dev, s); - } - } -} - -/* Loads DAC FIFO (if using it) from buffer. */ -/* Returns 0 if AO finished due to completion or error, 1 if still going. */ -static int pci230_handle_ao_fifo(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci230_private *devpriv = dev->private; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; - unsigned int num_scans; - unsigned int room; - unsigned short dacstat; - unsigned int i, n; - unsigned int bytes_per_scan; - unsigned int events = 0; - int running; - - /* Get DAC FIFO status. */ - dacstat = inw(dev->iobase + PCI230_DACCON); - - /* Determine number of scans available in buffer. */ - bytes_per_scan = cmd->chanlist_len * sizeof(short); - num_scans = comedi_buf_read_n_available(async) / bytes_per_scan; - if (!devpriv->ao_continuous) { - /* Fixed number of scans. */ - if (num_scans > devpriv->ao_scan_count) - num_scans = devpriv->ao_scan_count; - - if (devpriv->ao_scan_count == 0) { - /* End of acquisition. */ - events |= COMEDI_CB_EOA; - } - } - if (events == 0) { - /* Check for FIFO underrun. */ - if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { - comedi_error(dev, "AO FIFO underrun"); - events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; - } - /* Check for buffer underrun if FIFO less than half full - * (otherwise there will be loads of "DAC FIFO not half full" - * interrupts). */ - if ((num_scans == 0) - && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) { - comedi_error(dev, "AO buffer underrun"); - events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; - } - } - if (events == 0) { - /* Determine how much room is in the FIFO (in samples). */ - if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) - room = PCI230P2_DAC_FIFOROOM_FULL; - else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) - room = PCI230P2_DAC_FIFOROOM_HALFTOFULL; - else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) - room = PCI230P2_DAC_FIFOROOM_EMPTY; - else - room = PCI230P2_DAC_FIFOROOM_ONETOHALF; - - /* Convert room to number of scans that can be added. */ - room /= cmd->chanlist_len; - /* Determine number of scans to process. */ - if (num_scans > room) - num_scans = room; - - /* Process scans. */ - for (n = 0; n < num_scans; n++) { - for (i = 0; i < cmd->chanlist_len; i++) { - short datum; - - comedi_buf_get(async, &datum); - pci230_ao_write_fifo(dev, datum, - CR_CHAN(cmd->chanlist[i])); - } - } - events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK; - if (!devpriv->ao_continuous) { - devpriv->ao_scan_count -= num_scans; - if (devpriv->ao_scan_count == 0) { - /* All data for the command has been written - * to FIFO. Set FIFO interrupt trigger level - * to 'empty'. */ - devpriv->daccon = (devpriv->daccon - & - ~PCI230P2_DAC_INT_FIFO_MASK) - | PCI230P2_DAC_INT_FIFO_EMPTY; - outw(devpriv->daccon, - dev->iobase + PCI230_DACCON); - } - } - /* Check if FIFO underrun occurred while writing to FIFO. */ - dacstat = inw(dev->iobase + PCI230_DACCON); - if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { - comedi_error(dev, "AO FIFO underrun"); - events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; - } - } - if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) - != 0) { - /* Stopping AO due to completion or error. */ - pci230_ao_stop(dev, s); - running = 0; - } else { - running = 1; - } - async->events |= events; - return running; -} - static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -2569,70 +2615,6 @@ static void pci230_handle_ai(struct comedi_device *dev, } } -static void pci230_ao_stop(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci230_private *devpriv = dev->private; - unsigned long irqflags; - unsigned char intsrc; - int started; - struct comedi_cmd *cmd; - - spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); - started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state); - spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); - if (!started) - return; - - - cmd = &s->async->cmd; - if (cmd->scan_begin_src == TRIG_TIMER) { - /* Stop scan rate generator. */ - pci230_cancel_ct(dev, 1); - } - - /* Determine interrupt source. */ - if (devpriv->hwver < 2) { - /* Not using DAC FIFO. Using CT1 interrupt. */ - intsrc = PCI230_INT_ZCLK_CT1; - } else { - /* Using DAC FIFO interrupt. */ - intsrc = PCI230P2_INT_DAC; - } - /* Disable interrupt and wait for interrupt routine to finish running - * unless we are called from the interrupt routine. */ - spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); - devpriv->int_en &= ~intsrc; - while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { - spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); - } - if (devpriv->ier != devpriv->int_en) { - devpriv->ier = devpriv->int_en; - outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); - } - spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - - if (devpriv->hwver >= 2) { - /* Using DAC FIFO. Reset FIFO, clear underrun error, - * disable FIFO. */ - devpriv->daccon &= PCI230_DAC_OR_MASK; - outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET - | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, - dev->iobase + PCI230_DACCON); - } - - /* Release resources. */ - put_all_resources(dev, OWNER_AOCMD); -} - -static int pci230_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - pci230_ao_stop(dev, s); - return 0; -} - static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s) { -- GitLab From 5d3b0d1859722a855b0310fcdc34c2e545cc1c7d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 1 Jun 2012 17:31:45 +0100 Subject: [PATCH 0257/5711] staging: comedi: amplc_pci230: Remove forward declarations 4 Move these functions and remove their forward declarations: pci230_ai_stop(), pci230_handle_ai(). Also move pci230_ai_cancel() for aesthetic reasons. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 310 +++++++++--------- 1 file changed, 146 insertions(+), 164 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 0e9c4ba6e6c0..30487be11650 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -579,11 +579,6 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static void pci230_ai_stop(struct comedi_device *dev, - struct comedi_subdevice *s); -static void pci230_handle_ai(struct comedi_device *dev, - struct comedi_subdevice *s); - static short pci230_ai_read(struct comedi_device *dev) { const struct pci230_board *thisboard = comedi_board(dev); @@ -2103,6 +2098,52 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, return 1; } +static void pci230_ai_stop(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci230_private *devpriv = dev->private; + unsigned long irqflags; + struct comedi_cmd *cmd; + int started; + + spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); + started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state); + spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); + if (!started) + return; + cmd = &s->async->cmd; + if (cmd->convert_src == TRIG_TIMER) { + /* Stop conversion rate generator. */ + pci230_cancel_ct(dev, 2); + } + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* Stop scan period monostable. */ + pci230_cancel_ct(dev, 0); + } + spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + /* Disable ADC interrupt and wait for interrupt routine to finish + * running unless we are called from the interrupt routine. */ + devpriv->int_en &= ~PCI230_INT_ADC; + while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { + spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + } + if (devpriv->ier != devpriv->int_en) { + devpriv->ier = devpriv->int_en; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + } + spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + /* Reset FIFO, disable FIFO and set start conversion source to none. + * Keep se/diff and bip/uni settings */ + devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK + | PCI230_ADC_IM_MASK)) | + PCI230_ADC_TRIG_NONE; + outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, + dev->iobase + PCI230_ADCCON); + /* Release resources. */ + put_all_resources(dev, OWNER_AICMD); +} + static void pci230_ai_start(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -2255,6 +2296,99 @@ static int pci230_ai_inttrig_start(struct comedi_device *dev, return 1; } +static void pci230_handle_ai(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci230_private *devpriv = dev->private; + unsigned int events = 0; + unsigned int status_fifo; + unsigned int i; + unsigned int todo; + unsigned int fifoamount; + struct comedi_async *async = s->async; + unsigned int scanlen = async->cmd.scan_end_arg; + + /* Determine number of samples to read. */ + if (devpriv->ai_continuous) { + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else if (devpriv->ai_scan_count == 0) { + todo = 0; + } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) + || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) { + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else { + todo = (devpriv->ai_scan_count * scanlen) + - devpriv->ai_scan_pos; + if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } + if (todo == 0) + return; + fifoamount = 0; + for (i = 0; i < todo; i++) { + if (fifoamount == 0) { + /* Read FIFO state. */ + status_fifo = inw(dev->iobase + PCI230_ADCCON); + if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) { + /* Report error otherwise FIFO overruns will go + * unnoticed by the caller. */ + comedi_error(dev, "AI FIFO overrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + break; + } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) { + /* FIFO empty. */ + break; + } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) { + /* FIFO half full. */ + fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else { + /* FIFO not empty. */ + if (devpriv->hwver > 0) { + /* Read PCI230+/260+ ADC FIFO level. */ + fifoamount = inw(dev->iobase + + PCI230P_ADCFFLEV); + if (fifoamount == 0) { + /* Shouldn't happen. */ + break; + } + } else { + fifoamount = 1; + } + } + } + /* Read sample and store in Comedi's circular buffer. */ + if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) { + events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; + comedi_error(dev, "AI buffer overflow"); + break; + } + fifoamount--; + devpriv->ai_scan_pos++; + if (devpriv->ai_scan_pos == scanlen) { + /* End of scan. */ + devpriv->ai_scan_pos = 0; + devpriv->ai_scan_count--; + async->events |= COMEDI_CB_EOS; + } + } + if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { + /* End of acquisition. */ + events |= COMEDI_CB_EOA; + } else { + /* More samples required, tell Comedi to block. */ + events |= COMEDI_CB_BLOCK; + } + async->events |= events; + if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | + COMEDI_CB_OVERFLOW)) != 0) { + /* disable hardware conversions */ + pci230_ai_stop(dev, s); + } else { + /* update FIFO interrupt trigger level */ + pci230_ai_update_fifo_trigger_level(dev, s); + } +} + static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci230_private *devpriv = dev->private; @@ -2449,6 +2583,13 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +static int pci230_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + pci230_ai_stop(dev, s); + return 0; +} + /* Interrupt handler */ static irqreturn_t pci230_interrupt(int irq, void *d) { @@ -2514,165 +2655,6 @@ static irqreturn_t pci230_interrupt(int irq, void *d) return IRQ_HANDLED; } -static void pci230_handle_ai(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci230_private *devpriv = dev->private; - unsigned int events = 0; - unsigned int status_fifo; - unsigned int i; - unsigned int todo; - unsigned int fifoamount; - struct comedi_async *async = s->async; - unsigned int scanlen = async->cmd.scan_end_arg; - - /* Determine number of samples to read. */ - if (devpriv->ai_continuous) { - todo = PCI230_ADC_FIFOLEVEL_HALFFULL; - } else if (devpriv->ai_scan_count == 0) { - todo = 0; - } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) - || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) { - todo = PCI230_ADC_FIFOLEVEL_HALFFULL; - } else { - todo = (devpriv->ai_scan_count * scanlen) - - devpriv->ai_scan_pos; - if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) - todo = PCI230_ADC_FIFOLEVEL_HALFFULL; - - } - - if (todo == 0) - return; - - - fifoamount = 0; - for (i = 0; i < todo; i++) { - if (fifoamount == 0) { - /* Read FIFO state. */ - status_fifo = inw(dev->iobase + PCI230_ADCCON); - - if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) { - /* Report error otherwise FIFO overruns will go - * unnoticed by the caller. */ - comedi_error(dev, "AI FIFO overrun"); - events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; - break; - } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) { - /* FIFO empty. */ - break; - } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) { - /* FIFO half full. */ - fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL; - } else { - /* FIFO not empty. */ - if (devpriv->hwver > 0) { - /* Read PCI230+/260+ ADC FIFO level. */ - fifoamount = inw(dev->iobase - + PCI230P_ADCFFLEV); - if (fifoamount == 0) { - /* Shouldn't happen. */ - break; - } - } else { - fifoamount = 1; - } - } - } - - /* Read sample and store in Comedi's circular buffer. */ - if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) { - events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; - comedi_error(dev, "AI buffer overflow"); - break; - } - fifoamount--; - devpriv->ai_scan_pos++; - if (devpriv->ai_scan_pos == scanlen) { - /* End of scan. */ - devpriv->ai_scan_pos = 0; - devpriv->ai_scan_count--; - async->events |= COMEDI_CB_EOS; - } - } - - if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { - /* End of acquisition. */ - events |= COMEDI_CB_EOA; - } else { - /* More samples required, tell Comedi to block. */ - events |= COMEDI_CB_BLOCK; - } - async->events |= events; - - if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | - COMEDI_CB_OVERFLOW)) != 0) { - /* disable hardware conversions */ - pci230_ai_stop(dev, s); - } else { - /* update FIFO interrupt trigger level */ - pci230_ai_update_fifo_trigger_level(dev, s); - } -} - -static void pci230_ai_stop(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci230_private *devpriv = dev->private; - unsigned long irqflags; - struct comedi_cmd *cmd; - int started; - - spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); - started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state); - spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); - if (!started) - return; - - - cmd = &s->async->cmd; - if (cmd->convert_src == TRIG_TIMER) { - /* Stop conversion rate generator. */ - pci230_cancel_ct(dev, 2); - } - if (cmd->scan_begin_src != TRIG_FOLLOW) { - /* Stop scan period monostable. */ - pci230_cancel_ct(dev, 0); - } - - spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); - /* Disable ADC interrupt and wait for interrupt routine to finish - * running unless we are called from the interrupt routine. */ - devpriv->int_en &= ~PCI230_INT_ADC; - while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { - spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); - } - if (devpriv->ier != devpriv->int_en) { - devpriv->ier = devpriv->int_en; - outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); - } - spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - - /* Reset FIFO, disable FIFO and set start conversion source to none. - * Keep se/diff and bip/uni settings */ - devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK - | PCI230_ADC_IM_MASK)) | - PCI230_ADC_TRIG_NONE; - outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, - dev->iobase + PCI230_ADCCON); - - /* Release resources. */ - put_all_resources(dev, OWNER_AICMD); -} - -static int pci230_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - pci230_ai_stop(dev, s); - return 0; -} - /* Check if PCI device matches a specific board. */ static bool pci230_match_pci_board(const struct pci230_board *board, struct pci_dev *pci_dev) -- GitLab From 8a7245ea2c48641257ff149569b56650d0cfc99c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 20 May 2012 14:06:36 -0700 Subject: [PATCH 0258/5711] Staging: android: alarm: Rename pr_alarm to alarm_dbg Rename a macro to make it explicit it's for debugging. Use %s: __func__ instead of embedding function names. Coalesce formats, align arguments. Signed-off-by: Joe Perches Acked-by: David Rientjes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 53ce6ecf390a..32614d611283 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -29,16 +29,14 @@ #define ANDROID_ALARM_PRINT_IO (1U << 1) #define ANDROID_ALARM_PRINT_INT (1U << 2) - static int debug_mask = ANDROID_ALARM_PRINT_INFO; module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); -#define pr_alarm(debug_level_mask, args...) \ - do { \ - if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ - pr_info(args); \ - } \ - } while (0) +#define alarm_dbg(debug_level_mask, fmt, ...) \ +do { \ + if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \ + pr_info(fmt, ##__VA_ARGS__); \ +} while (0) #define ANDROID_ALARM_WAKEUP_MASK ( \ ANDROID_ALARM_RTC_WAKEUP_MASK | \ @@ -138,7 +136,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_CLEAR(0): spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm %d clear\n", alarm_type); + alarm_dbg(IO, "alarm %d clear\n", alarm_type); devalarm_try_to_cancel(&alarms[alarm_type]); if (alarm_pending) { alarm_pending &= ~alarm_type_mask; @@ -167,8 +165,9 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } from_old_alarm_set: spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, - new_alarm_time.tv_sec, new_alarm_time.tv_nsec); + alarm_dbg(IO, "alarm %d set %ld.%09ld\n", + alarm_type, + new_alarm_time.tv_sec, new_alarm_time.tv_nsec); alarm_enabled |= alarm_type_mask; devalarm_start(&alarms[alarm_type], timespec_to_ktime(new_alarm_time)); @@ -179,7 +178,7 @@ from_old_alarm_set: /* fall though */ case ANDROID_ALARM_WAIT: spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm wait\n"); + alarm_dbg(IO, "alarm wait\n"); if (!alarm_pending && wait_pending) { __pm_relax(&alarm_wake_lock); wait_pending = 0; @@ -260,9 +259,10 @@ static int alarm_release(struct inode *inode, struct file *file) for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { uint32_t alarm_type_mask = 1U << i; if (alarm_enabled & alarm_type_mask) { - pr_alarm(INFO, "alarm_release: clear alarm, " - "pending %d\n", - !!(alarm_pending & alarm_type_mask)); + alarm_dbg(INFO, + "%s: clear alarm, pending %d\n", + __func__, + !!(alarm_pending & alarm_type_mask)); alarm_enabled &= ~alarm_type_mask; } spin_unlock_irqrestore(&alarm_slock, flags); @@ -271,8 +271,8 @@ static int alarm_release(struct inode *inode, struct file *file) } if (alarm_pending | wait_pending) { if (alarm_pending) - pr_alarm(INFO, "alarm_release: clear " - "pending alarms %x\n", alarm_pending); + alarm_dbg(INFO, "%s: clear pending alarms %x\n", + __func__, alarm_pending); __pm_relax(&alarm_wake_lock); wait_pending = 0; alarm_pending = 0; @@ -288,7 +288,7 @@ static void devalarm_triggered(struct devalarm *alarm) unsigned long flags; uint32_t alarm_type_mask = 1U << alarm->type; - pr_alarm(INT, "devalarm_triggered type %d\n", alarm->type); + alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); spin_lock_irqsave(&alarm_slock, flags); if (alarm_enabled & alarm_type_mask) { __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ -- GitLab From 3fe192d8e0c99ca3b96573cdc7cc03cfcf935f74 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 21 May 2012 07:56:57 -0700 Subject: [PATCH 0259/5711] staging "rts_pstor" fix some typos while reading through rts_pstor Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/ms.c | 2 +- drivers/staging/rts_pstor/sd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c index 0bf6d95b3fab..7cc2b53f20d0 100644 --- a/drivers/staging/rts_pstor/ms.c +++ b/drivers/staging/rts_pstor/ms.c @@ -2488,7 +2488,7 @@ int reset_ms_card(struct rtsx_chip *chip) if (!CHK_MSPRO(ms_card)) { /* Build table for the last segment, - * to check if L2P talbe block exist,erasing it + * to check if L2P table block exists, erasing it */ retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1); if (retval != STATUS_SUCCESS) { diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c index aab690932eae..b9474a8aefc0 100644 --- a/drivers/staging/rts_pstor/sd.c +++ b/drivers/staging/rts_pstor/sd.c @@ -1169,7 +1169,7 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]); } else { /* Maximum current consumption, check whether current is acceptable; - * bit[511:496] = 0x0000 means some error happaned. + * bit[511:496] = 0x0000 means some error happened. */ u16 cc = ((u16)buf[0] << 8) | buf[1]; RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc); -- GitLab From 76cc6f92039208e04291af751c5d46568aa24162 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:53 -0400 Subject: [PATCH 0260/5711] Staging: bcm: Remove typedef from "eInterface_setting" in Adapter.h This patch removes the typedef from eInterface_setting, and renames the enum to bcm_einterface_setting. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index aa51d17be5a1..a67022f23871 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -585,9 +585,9 @@ int InitAdapter(PMINI_ADAPTER psAdapter); #define EP5 4 #define EP6 5 -typedef enum eInterface_setting { +enum bcm_einterface_setting { DEFAULT_SETTING_0 = 0, ALTERNATE_SETTING_1 = 1, -} INTERFACE_SETTING; +}; #endif /* __ADAPTER_H__ */ -- GitLab From be3099957ca9d465a46b83d08c1cd9617a461078 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:54 -0400 Subject: [PATCH 0261/5711] Staging: bcm: Remove typedef for _DDR_SETTING and call directly. This patch removes the typedef for _DDR_SETTING, changes the name of the struct from _DDR_SETTING, to bcm_ddr_setting. In addition, any calls to the following typedefs "DDR_SET_NODE and *PDDR_SET_NODE" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 5 ++- drivers/staging/bcm/DDRInit.c | 62 +++++++++++++++++------------------ 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index a67022f23871..9b788563a014 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -549,11 +549,10 @@ typedef struct _cntl_pkt { } cntl_pkt; typedef LINK_REQUEST CONTROL_MESSAGE; -typedef struct _DDR_SETTING { +struct bcm_ddr_setting { UINT ulRegAddress; UINT ulRegValue; -} DDR_SETTING, *PDDR_SETTING; -typedef DDR_SETTING DDR_SET_NODE, *PDDR_SET_NODE; +}; int InitAdapter(PMINI_ADAPTER psAdapter); /* ===================================================================== diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c index 2b46f4d4ef0e..e7571da81216 100644 --- a/drivers/staging/bcm/DDRInit.c +++ b/drivers/staging/bcm/DDRInit.c @@ -7,7 +7,7 @@ //DDR INIT-133Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12 //index for 0x0F007000 -static DDR_SET_NODE asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting {0x0F000800,0x00007212}, {0x0f000820,0x07F13FFF}, {0x0f000810,0x00000F95}, @@ -65,7 +65,7 @@ static DDR_SET_NODE asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting }; //80Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10 //index for 0x0F007000 -static DDR_SET_NODE asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting {0x0f000810,0x00000F95}, {0x0f000820,0x07f1ffff}, {0x0f000860,0x00000000}, @@ -117,7 +117,7 @@ static DDR_SET_NODE asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting }; //100Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13 //index for 0x0F007000 -static DDR_SET_NODE asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting {0x0F000800,0x00007008}, {0x0f000810,0x00000F95}, {0x0f000820,0x07F13E3F}, @@ -177,7 +177,7 @@ static DDR_SET_NODE asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting //Net T3B DDR Settings //DDR INIT-133Mhz -static DDR_SET_NODE asDPLL_266MHZ[] = { +static struct bcm_ddr_setting asDPLL_266MHZ[] = { {0x0F000800,0x00007212}, {0x0f000820,0x07F13FFF}, {0x0f000810,0x00000F95}, @@ -189,7 +189,7 @@ static DDR_SET_NODE asDPLL_266MHZ[] = { }; #define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11 //index for 0x0F007000 -static DDR_SET_NODE asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting {0x0f000810,0x00000F95}, {0x0f000810,0x00000F95}, {0x0f000810,0x00000F95}, @@ -247,7 +247,7 @@ static DDR_SET_NODE asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting }; #define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 -static DDR_SET_NODE asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting {0x0f000810,0x00000F95}, {0x0f000820,0x07F13FFF}, {0x0f000840,0x0FFF1F00}, @@ -301,7 +301,7 @@ static DDR_SET_NODE asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting //100Mhz #define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9 //index for 0x0F007000 -static DDR_SET_NODE asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting {0x0f000810,0x00000F95}, {0x0f000820,0x07F1369B}, {0x0f000840,0x0FFF0800}, @@ -356,7 +356,7 @@ static DDR_SET_NODE asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9 //index for 0x0F007000 -static DDR_SET_NODE asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting {0x0f000820,0x03F1365B}, {0x0f000810,0x00002F95}, {0x0f000880,0x000003DD}, @@ -416,7 +416,7 @@ static DDR_SET_NODE asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting }; #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11 //index for 0x0F007000 -static DDR_SET_NODE asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting {0x0f000810,0x00002F95}, {0x0f000820,0x03F1369B}, {0x0f000840,0x0fff0000}, @@ -476,7 +476,7 @@ static DDR_SET_NODE asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting }; #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 -static DDR_SET_NODE asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting {0x0f000820,0x07F13FFF}, {0x0f000810,0x00002F95}, {0x0f000860,0x00000000}, @@ -536,7 +536,7 @@ static DDR_SET_NODE asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting ///T3 LP-B (UMA-B) #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7 //index for 0x0F007000 -static DDR_SET_NODE asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting {0x0f000820,0x03F137DB}, {0x0f000810,0x01842795}, @@ -594,7 +594,7 @@ static DDR_SET_NODE asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7 //index for 0x0F007000 -static DDR_SET_NODE asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting {0x0f000820,0x03F1365B}, {0x0f000810,0x00002F95}, {0x0f000880,0x000003DD}, @@ -655,7 +655,7 @@ static DDR_SET_NODE asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting }; #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8 //index for 0x0F007000 -static DDR_SET_NODE asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting {0x0f000810,0x00002F95}, {0x0f000820,0x03F1369B}, {0x0f000840,0x0fff0000}, @@ -716,7 +716,7 @@ static DDR_SET_NODE asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting }; #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7 //index for 0x0F007000 -static DDR_SET_NODE asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting +static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting {0x0f000820,0x07F13FFF}, {0x0f000810,0x00002F95}, {0x0f000860,0x00000000}, @@ -774,7 +774,7 @@ static DDR_SET_NODE asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting int ddr_init(MINI_ADAPTER *Adapter) { - PDDR_SETTING psDDRSetting=NULL; + struct bcm_ddr_setting *psDDRSetting=NULL; ULONG RegCount=0; UINT value = 0; UINT uiResetValue = 0; @@ -789,17 +789,17 @@ int ddr_init(MINI_ADAPTER *Adapter) case DDR_80_MHZ: psDDRSetting=asT3LP_DDRSetting80MHz; RegCount=(sizeof(asT3LP_DDRSetting80MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: psDDRSetting=asT3LP_DDRSetting100MHz; RegCount=(sizeof(asT3LP_DDRSetting100MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: psDDRSetting=asT3LP_DDRSetting133MHz; RegCount=(sizeof(asT3LP_DDRSetting133MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); if(Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x03F13652; @@ -846,17 +846,17 @@ int ddr_init(MINI_ADAPTER *Adapter) case DDR_80_MHZ: psDDRSetting = asT3LPB_DDRSetting80MHz; RegCount=(sizeof(asT3B_DDRSetting80MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: psDDRSetting=asT3LPB_DDRSetting100MHz; RegCount=(sizeof(asT3B_DDRSetting100MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: psDDRSetting = asT3LPB_DDRSetting133MHz; RegCount=(sizeof(asT3B_DDRSetting133MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); if(Adapter->bMipsConfig == MIPS_200_MHZ) { @@ -870,7 +870,7 @@ int ddr_init(MINI_ADAPTER *Adapter) case DDR_160_MHZ: psDDRSetting = asT3LPB_DDRSetting160MHz; - RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SETTING); + RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(struct bcm_ddr_setting); if(Adapter->bMipsConfig == MIPS_200_MHZ) { @@ -894,17 +894,17 @@ int ddr_init(MINI_ADAPTER *Adapter) case DDR_80_MHZ: psDDRSetting = asT3_DDRSetting80MHz; RegCount = (sizeof(asT3_DDRSetting80MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: psDDRSetting = asT3_DDRSetting100MHz; RegCount = (sizeof(asT3_DDRSetting100MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: psDDRSetting = asT3_DDRSetting133MHz; RegCount = (sizeof(asT3_DDRSetting133MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; default: return -EINVAL; @@ -916,12 +916,12 @@ int ddr_init(MINI_ADAPTER *Adapter) case DDR_80_MHZ: psDDRSetting = asT3B_DDRSetting80MHz; RegCount=(sizeof(asT3B_DDRSetting80MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: psDDRSetting=asT3B_DDRSetting100MHz; RegCount=(sizeof(asT3B_DDRSetting100MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: @@ -931,13 +931,13 @@ int ddr_init(MINI_ADAPTER *Adapter) sizeof(asDPLL_266MHZ)); psDDRSetting = asT3B_DDRSetting133MHz; RegCount=(sizeof(asT3B_DDRSetting133MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); } else { psDDRSetting = asT3B_DDRSetting133MHz; RegCount=(sizeof(asT3B_DDRSetting133MHz)/ - sizeof(DDR_SETTING)); + sizeof(struct bcm_ddr_setting)); if(Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x07F13652; @@ -1101,7 +1101,7 @@ int ddr_init(MINI_ADAPTER *Adapter) int download_ddr_settings(PMINI_ADAPTER Adapter) { - PDDR_SET_NODE psDDRSetting=NULL; + struct bcm_ddr_setting *psDDRSetting=NULL; ULONG RegCount=0; unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY; UINT value = 0; @@ -1250,7 +1250,7 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) } ul_ddr_setting_load_addr+=sizeof(ULONG); - RegCount*=(sizeof(DDR_SETTING)/sizeof(ULONG)); + RegCount*=(sizeof(struct bcm_ddr_setting)/sizeof(ULONG)); while(RegCount && !retval) { -- GitLab From 7905c78816783dff5d167cf922557e35e8c1a45f Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:55 -0400 Subject: [PATCH 0262/5711] Staging: bcm: Remove typedef for _cntl_pkt in Adapter.h This patch removes typedef for _cntl_pkt because it is not used. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 9b788563a014..45c2e8c35980 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -543,10 +543,7 @@ typedef struct FirmwareInfo { /* holds the value of net_device structure.. */ extern struct net_device *gblpnetdev; -typedef struct _cntl_pkt { - PMINI_ADAPTER Adapter; - PLEADER PLeader; -} cntl_pkt; + typedef LINK_REQUEST CONTROL_MESSAGE; struct bcm_ddr_setting { -- GitLab From 7a27a2ccf8a6368f6d7f77cb02f5c5c698015c2e Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:56 -0400 Subject: [PATCH 0263/5711] Staging: bcm: Remove typedef for FirmwareInfo and call directly. This patch removes typedef for FirmwareInfo, changes the name from Firmwareinfo to bcm_firmware_info. In addition, any calls to the following typedefs "PFIRMWARE_INFO, FIRMWARE_INFO" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 4 ++-- drivers/staging/bcm/Bcmchar.c | 4 ++-- drivers/staging/bcm/InterfaceDld.c | 4 ++-- drivers/staging/bcm/Prototypes.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 45c2e8c35980..12a43fb92c18 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -535,11 +535,11 @@ struct _ETH_HEADER_STRUC { } __packed; typedef struct _ETH_HEADER_STRUC ETH_HEADER_STRUC, *PETH_HEADER_STRUC; -typedef struct FirmwareInfo { +struct bcm_firmware_info { void __user *pvMappedFirmwareAddress; ULONG u32FirmwareLength; ULONG u32StartingAddress; -} __packed FIRMWARE_INFO, *PFIRMWARE_INFO; +} __packed; /* holds the value of net_device structure.. */ extern struct net_device *gblpnetdev; diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index cf3059216958..cd0348e5914d 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -787,7 +787,7 @@ cntrlEnd: } case IOCTL_BCM_BUFFER_DOWNLOAD: { - FIRMWARE_INFO *psFwInfo = NULL; + struct bcm_firmware_info *psFwInfo = NULL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); if (!down_trylock(&Adapter->fw_download_sema)) { @@ -807,7 +807,7 @@ cntrlEnd: BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", IoBuffer.InputLength); - if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) { + if (IoBuffer.InputLength > sizeof(struct bcm_firmware_info)) { up(&Adapter->fw_download_sema); return -EINVAL; } diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c index 65c352f35681..cb0e72ee0789 100644 --- a/drivers/staging/bcm/InterfaceDld.c +++ b/drivers/staging/bcm/InterfaceDld.c @@ -132,7 +132,7 @@ exit: return Status; } -static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) +static int bcm_download_config_file(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo) { int retval = STATUS_SUCCESS; B_UINT32 value = 0; @@ -229,7 +229,7 @@ static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char return retval; } -int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) +int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo) { int retval = STATUS_SUCCESS; PUCHAR buff = NULL; diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h index b80b806c90a3..a8676b9b0624 100644 --- a/drivers/staging/bcm/Prototypes.h +++ b/drivers/staging/bcm/Prototypes.h @@ -92,7 +92,7 @@ int ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *buf); void GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *ioBuffer, PPER_TARANG_DATA pTarang); void beceem_parse_target_struct(PMINI_ADAPTER Adapter); -int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo); +int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo); void CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex); -- GitLab From 406a50826fb728ff3105907a2bf3e3180667e122 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:57 -0400 Subject: [PATCH 0264/5711] Staging: bcm: Remove typedef for _ETH_HEADER_STRUC and call directly. This patch removes typedef for _ETH_HEADER_STRUC, changes the name of the struct from _ETH_HEADER_STRUC to bcm_eth_header. In addition, any calls to the following typedefs "ETH_HEADER_STRUC, *PETH_HEADER_STRUC" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 3 +-- drivers/staging/bcm/Protocol.h | 8 ++++---- drivers/staging/bcm/Qos.c | 12 ++++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 12a43fb92c18..338f1acfdd18 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -528,12 +528,11 @@ typedef struct _MINI_ADAPTER MINI_ADAPTER, *PMINI_ADAPTER; #define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev) -struct _ETH_HEADER_STRUC { +struct bcm_eth_header { UCHAR au8DestinationAddress[6]; UCHAR au8SourceAddress[6]; USHORT u16Etype; } __packed; -typedef struct _ETH_HEADER_STRUC ETH_HEADER_STRUC, *PETH_HEADER_STRUC; struct bcm_firmware_info { void __user *pvMappedFirmwareAddress; diff --git a/drivers/staging/bcm/Protocol.h b/drivers/staging/bcm/Protocol.h index b8a4009bdf0c..562d4dd81a7c 100644 --- a/drivers/staging/bcm/Protocol.h +++ b/drivers/staging/bcm/Protocol.h @@ -55,7 +55,7 @@ typedef struct _S_ETHCS_PKT_INFO typedef struct _ETH_CS_802_Q_FRAME { - ETH_HEADER_STRUC EThHdr; + struct bcm_eth_header EThHdr; USHORT UserPriority:3; USHORT CFI:1; USHORT VLANID:12; @@ -64,7 +64,7 @@ typedef struct _ETH_CS_802_Q_FRAME typedef struct _ETH_CS_802_LLC_FRAME { - ETH_HEADER_STRUC EThHdr; + struct bcm_eth_header EThHdr; unsigned char DSAP; unsigned char SSAP; unsigned char Control; @@ -72,7 +72,7 @@ typedef struct _ETH_CS_802_LLC_FRAME typedef struct _ETH_CS_802_LLC_SNAP_FRAME { - ETH_HEADER_STRUC EThHdr; + struct bcm_eth_header EThHdr; unsigned char DSAP; unsigned char SSAP; unsigned char Control; @@ -82,7 +82,7 @@ typedef struct _ETH_CS_802_LLC_SNAP_FRAME typedef struct _ETH_CS_ETH2_FRAME { - ETH_HEADER_STRUC EThHdr; + struct bcm_eth_header EThHdr; } __attribute__((packed)) ETH_CS_ETH2_FRAME; #define ETHERNET_FRAMETYPE_IPV4 ntohs(0x0800) diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c index c97020f0fb6a..9bf61ff6ac78 100644 --- a/drivers/staging/bcm/Qos.c +++ b/drivers/staging/bcm/Qos.c @@ -733,7 +733,7 @@ static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct s if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame) return FALSE; - uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xF000) >> 13; + uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13; if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1])) bClassificationSucceed = TRUE; @@ -751,7 +751,7 @@ static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct s if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame) return FALSE; - usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xFFF; + usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority); @@ -774,12 +774,12 @@ static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, B_UINT8 EthCSCupport) { BOOLEAN bClassificationSucceed = FALSE; - bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((ETH_HEADER_STRUC *)(skb->data))->au8SourceAddress); + bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8SourceAddress); if(!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n"); - bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((ETH_HEADER_STRUC*)(skb->data))->au8DestinationAddress); + bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8DestinationAddress); if(!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n"); @@ -804,7 +804,7 @@ static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload, PS_ETHCS_PKT_INFO pstEthCsPktInfo) { - USHORT u16Etype = ntohs(((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype); + USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype); if(u16Etype > 0x5dc) @@ -845,7 +845,7 @@ static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload, else pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket; - pstEthCsPktInfo->usEtherType = ((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype; + pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n",pstEthCsPktInfo->eNwpktIPFrameType); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n",pstEthCsPktInfo->eNwpktEthFrameType); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n",pstEthCsPktInfo->usEtherType); -- GitLab From 3753164384a99c52682ba6dc38a9c8a87ecf55ad Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:58 -0400 Subject: [PATCH 0265/5711] Staging: bcm: Remove typedef for _STTARGETDSXBUFFER and call directly. This patch removes typedef for _STTARGETDSXBUFFER, changes the name of the struct from _STTARGETDSXBUFFER to bcm_targetdsx_buffer. In addition, any calls to the following typedefs "STTARGETDSXBUFFER, *PSTTARGETDSXBUFFER" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 338f1acfdd18..1d18ef9dd35c 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -332,11 +332,11 @@ typedef struct _TARGET_PARAMS { } STARGETPARAMS, *PSTARGETPARAMS; #endif -typedef struct _STTARGETDSXBUFFER { +struct bcm_targetdsx_buffer { ULONG ulTargetDsxBuffer; B_UINT16 tid; BOOLEAN valid; -} STTARGETDSXBUFFER, *PSTTARGETDSXBUFFER; +}; typedef int (*FP_FLASH_WRITE)(struct _MINI_ADAPTER *, UINT, PVOID); @@ -404,7 +404,7 @@ struct _MINI_ADAPTER { UINT index_datpkt; struct semaphore rdmwrmsync; - STTARGETDSXBUFFER astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS]; + struct bcm_targetdsx_buffer astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS]; ULONG ulFreeTargetBufferCnt; ULONG ulCurrentTargetBuffer; ULONG ulTotalTargetBuffersAvailable; -- GitLab From d0830f6c44050b78fde2fca8597d04064854cd87 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:04:59 -0400 Subject: [PATCH 0266/5711] Staging: bcm: Remove condition check on macro REL_4_1 because it is not used. This patch removes the conditional check on macro REL_4_1, and the corresponding controlled text because it is not used. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 81 ----------------------------------- drivers/staging/bcm/Macros.h | 4 -- 2 files changed, 85 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 1d18ef9dd35c..ade2b0d67974 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -251,87 +251,6 @@ typedef struct _PER_TARANG_DATA { ULONG RxCntrlMsgBitMask; } PER_TARANG_DATA, *PPER_TARANG_DATA; -#ifdef REL_4_1 -typedef struct _TARGET_PARAMS { - B_UINT32 m_u32CfgVersion; - - /* Scanning Related Params */ - B_UINT32 m_u32CenterFrequency; - B_UINT32 m_u32BandAScan; - B_UINT32 m_u32BandBScan; - B_UINT32 m_u32BandCScan; - - /* QoS Params */ - B_UINT32 m_u32minGrantsize; /* size of minimum grant is 0 or 6 */ - B_UINT32 m_u32PHSEnable; - - /* HO Params */ - B_UINT32 m_u32HoEnable; - B_UINT32 m_u32HoReserved1; - B_UINT32 m_u32HoReserved2; - - /* Power Control Params */ - B_UINT32 m_u32MimoEnable; - B_UINT32 m_u32SecurityEnable; - /* - * bit 1: 1 Idlemode enable; - * bit 2: 1 Sleepmode Enable - */ - B_UINT32 m_u32PowerSavingModesEnable; - /* PowerSaving Mode Options: - * bit 0 = 1: CPE mode - to keep pcmcia if alive; - * bit 1 = 1: CINR reporing in Idlemode Msg - * bit 2 = 1: Default PSC Enable in sleepmode - */ - B_UINT32 m_u32PowerSavingModeOptions; - - B_UINT32 m_u32ArqEnable; - - /* From Version #3, the HARQ section renamed as general */ - B_UINT32 m_u32HarqEnable; - /* EEPROM Param Location */ - B_UINT32 m_u32EEPROMFlag; - /* BINARY TYPE - 4th MSByte: - * Interface Type - 3rd MSByte: - * Vendor Type - 2nd MSByte - */ - /* Unused - LSByte */ - B_UINT32 m_u32Customize; - B_UINT32 m_u32ConfigBW; /* In Hz */ - B_UINT32 m_u32ShutDownTimer; - B_UINT32 m_u32RadioParameter; - B_UINT32 m_u32PhyParameter1; - B_UINT32 m_u32PhyParameter2; - B_UINT32 m_u32PhyParameter3; - - /* in eval mode only; - * lower 16bits = basic cid for testing; - * then bit 16 is test cqich, - * bit 17 test init rang; - * bit 18 test periodic rang - * bit 19 is test harq ack/nack - */ - B_UINT32 m_u32TestOptions; - B_UINT32 m_u32MaxMACDataperDLFrame; - B_UINT32 m_u32MaxMACDataperULFrame; - B_UINT32 m_u32Corr2MacFlags; - - /* adding driver params. */ - B_UINT32 HostDrvrConfig1; - B_UINT32 HostDrvrConfig2; - B_UINT32 HostDrvrConfig3; - B_UINT32 HostDrvrConfig4; - B_UINT32 HostDrvrConfig5; - B_UINT32 HostDrvrConfig6; - B_UINT32 m_u32SegmentedPUSCenable; - - /* BAMC enable - but 4.x does not support this feature - * This is added just to sync 4.x and 5.x CFGs - */ - B_UINT32 m_u32BandAMCEnable; -} STARGETPARAMS, *PSTARGETPARAMS; -#endif - struct bcm_targetdsx_buffer { ULONG ulTargetDsxBuffer; B_UINT16 tid; diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h index 46ed99c53764..8238cdba7a0f 100644 --- a/drivers/staging/bcm/Macros.h +++ b/drivers/staging/bcm/Macros.h @@ -252,11 +252,7 @@ typedef enum _E_PHS_DSC_ACTION { #define IDLE_MODE_WAKEUP_NOTIFIER_ADDRESS 0x1FC02FA8 #define IDLE_MODE_MAX_RETRY_COUNT 1000 -#ifdef REL_4_1 -#define CONFIG_BEGIN_ADDR 0xBF60B004 -#else #define CONFIG_BEGIN_ADDR 0xBF60B000 -#endif #define FIRMWARE_BEGIN_ADDR 0xBFC00000 -- GitLab From 774bea8314c3fa59a977e64114286d6e3341b7cc Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:00 -0400 Subject: [PATCH 0267/5711] Staging: bcm: Remove typedef for _PER_TARANG_DATA and call directly. This patch removes typedef for _PER_TARANG_DATA, changes the name of the struct from _PER_TARANG_DATA to bcm_per_tarang_data. In addition, any calls to the following typedefs "PER_TARANG_DATA, *PPER_TARANG_DATA" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 8 ++++---- drivers/staging/bcm/Bcmchar.c | 12 ++++++------ drivers/staging/bcm/HandleControlPacket.c | 4 ++-- drivers/staging/bcm/Prototypes.h | 2 +- drivers/staging/bcm/hostmibs.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index ade2b0d67974..7f58322e68b4 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -239,8 +239,8 @@ struct _packet_info { }; typedef struct _packet_info PacketInfo; -typedef struct _PER_TARANG_DATA { - struct _PER_TARANG_DATA *next; +struct bcm_tarang_data { + struct bcm_tarang_data *next; struct _MINI_ADAPTER *Adapter; struct sk_buff *RxAppControlHead; struct sk_buff *RxAppControlTail; @@ -249,7 +249,7 @@ typedef struct _PER_TARANG_DATA { BOOLEAN bApplicationToExit; S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs; ULONG RxCntrlMsgBitMask; -} PER_TARANG_DATA, *PPER_TARANG_DATA; +}; struct bcm_targetdsx_buffer { ULONG ulTargetDsxBuffer; @@ -280,7 +280,7 @@ struct _MINI_ADAPTER { struct sk_buff *RxControlTail; struct semaphore RxAppControlQueuelock; struct semaphore fw_download_sema; - PPER_TARANG_DATA pTarangs; + struct bcm_tarang_data *pTarangs; spinlock_t control_queue_lock; wait_queue_head_t process_read_wait_queue; diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index cd0348e5914d..03dc2b010450 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -16,10 +16,10 @@ static int bcm_char_open(struct inode *inode, struct file * filp) { PMINI_ADAPTER Adapter = NULL; - PPER_TARANG_DATA pTarang = NULL; + struct bcm_tarang_data *pTarang = NULL; Adapter = GET_BCM_ADAPTER(gblpnetdev); - pTarang = kzalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL); + pTarang = kzalloc(sizeof(struct bcm_tarang_data), GFP_KERNEL); if (!pTarang) return -ENOMEM; @@ -43,11 +43,11 @@ static int bcm_char_open(struct inode *inode, struct file * filp) static int bcm_char_release(struct inode *inode, struct file *filp) { - PPER_TARANG_DATA pTarang, tmp, ptmp; + struct bcm_tarang_data *pTarang, *tmp, *ptmp; PMINI_ADAPTER Adapter = NULL; struct sk_buff *pkt, *npkt; - pTarang = (PPER_TARANG_DATA)filp->private_data; + pTarang = (struct bcm_tarang_data *)filp->private_data; if (pTarang == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, @@ -97,7 +97,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp) static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos) { - PPER_TARANG_DATA pTarang = filp->private_data; + struct bcm_tarang_data *pTarang = filp->private_data; PMINI_ADAPTER Adapter = pTarang->Adapter; struct sk_buff *Packet = NULL; ssize_t PktLen = 0; @@ -155,7 +155,7 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { - PPER_TARANG_DATA pTarang = filp->private_data; + struct bcm_tarang_data *pTarang = filp->private_data; void __user *argp = (void __user *)arg; PMINI_ADAPTER Adapter = pTarang->Adapter; INT Status = STATUS_FAILURE; diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c index b058e30b2ca6..691b366bfe4f 100644 --- a/drivers/staging/bcm/HandleControlPacket.c +++ b/drivers/staging/bcm/HandleControlPacket.c @@ -13,7 +13,7 @@ */ static VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, struct sk_buff *skb) { - PPER_TARANG_DATA pTarang = NULL; + struct bcm_tarang_data *pTarang = NULL; BOOLEAN HighPriorityMessage = FALSE; struct sk_buff *newPacket = NULL; CHAR cntrl_msg_mask_bit = 0; @@ -214,7 +214,7 @@ int control_packet_handler(PMINI_ADAPTER Adapter /* pointer to adapter object*/) INT flushAllAppQ(void) { PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); - PPER_TARANG_DATA pTarang = NULL; + struct bcm_tarang_data *pTarang = NULL; struct sk_buff *PacketToDrop = NULL; for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) { while (pTarang->RxAppControlHead != NULL) { diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h index a8676b9b0624..b22f61d96c49 100644 --- a/drivers/staging/bcm/Prototypes.h +++ b/drivers/staging/bcm/Prototypes.h @@ -89,7 +89,7 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter); int ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *buf); -void GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *ioBuffer, PPER_TARANG_DATA pTarang); +void GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *ioBuffer, struct bcm_tarang_data *pTarang); void beceem_parse_target_struct(PMINI_ADAPTER Adapter); int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo); diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c index 101c4e31249e..27ddcbfd5935 100644 --- a/drivers/staging/bcm/hostmibs.c +++ b/drivers/staging/bcm/hostmibs.c @@ -94,7 +94,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMib return STATUS_SUCCESS; } -VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, const PPER_TARANG_DATA pTarang) +VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, struct bcm_tarang_data *pTarang) { memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs), &(pTarang->stDroppedAppCntrlMsgs), -- GitLab From 0b3edf760a56cf5372d2dafa35b400561ddc0eb0 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:01 -0400 Subject: [PATCH 0268/5711] Staging: bcm: Remove typedef for _packet_info and call directly. This patch removes typedef for _packet_info, changes the name of the struct from _packet_info to bcm_packet_info. In addition, any calls to the following typedefs "PacketInfo, _packet_info" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 6 ++---- drivers/staging/bcm/Bcmchar.c | 2 +- drivers/staging/bcm/CmHost.c | 2 +- drivers/staging/bcm/LeakyBucket.c | 6 +++--- drivers/staging/bcm/sort.c | 6 +++--- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 7f58322e68b4..20ac2b3ecdd2 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -99,7 +99,6 @@ typedef union _U_IP_ADDRESS { UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES]; }; } U_IP_ADDRESS; -struct _packet_info; typedef struct _S_HDR_SUPRESSION_CONTEXTINFO { UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */ @@ -168,7 +167,7 @@ typedef struct _S_FRAGMENTED_PACKET_INFO { BOOLEAN bOutOfOrderFragment; } S_FRAGMENTED_PACKET_INFO, *PS_FRAGMENTED_PACKET_INFO; -struct _packet_info { +struct bcm_packet_info { /* classification extension Rule */ ULONG ulSFID; USHORT usVCID_Value; @@ -237,7 +236,6 @@ struct _packet_info { UCHAR bIPCSSupport; UCHAR bEthCSSupport; }; -typedef struct _packet_info PacketInfo; struct bcm_tarang_data { struct bcm_tarang_data *next; @@ -296,7 +294,7 @@ struct _MINI_ADAPTER { USHORT PrevNumRecvDescs; USHORT CurrNumRecvDescs; UINT u32TotalDSD; - PacketInfo PackInfo[NO_OF_QUEUES]; + struct bcm_packet_info PackInfo[NO_OF_QUEUES]; S_CLASSIFIER_RULE astClassifierTable[MAX_CLASSIFIERS]; BOOLEAN TransferMode; diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 03dc2b010450..8d4052a7deae 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -971,7 +971,7 @@ cntrlEnd: break; case IOCTL_GET_PACK_INFO: - if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) + if (copy_to_user(argp, &Adapter->PackInfo, sizeof(struct bcm_packet_info)*NO_OF_QUEUES)) return -EFAULT; Status = STATUS_SUCCESS; break; diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 7e38af5e1765..f584fdc6be44 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -1918,7 +1918,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* "); /* Validate the parameters */ @@ -113,7 +113,7 @@ This function despatches packet from the specified queue. @return Zero(success) or Negative value(failure) */ static INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**bValid || !pb->bValid) return 0; @@ -27,7 +27,7 @@ VOID SortPackInfo(PMINI_ADAPTER Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<======="); - sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(PacketInfo), + sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(struct bcm_packet_info), compare_packet_info, NULL); } -- GitLab From 7f22485def175b9378019b90a1a54cd8f5df0af0 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:02 -0400 Subject: [PATCH 0269/5711] Staging: bcm: Remove typedef for _S_FRAGMENTED_PACKET_INFO and call directly. This patch removes typedef for _S_FRAGMENTED_PACKET_INFO, changes the name of the struct from _S_FRAGMENTED_PACKET_INFO to bcm_fragmented_packet_info. In addition, any calls to the following typedefs "S_FRAGMENTED_PACKET_INFO, *PS_FRAGMENTED_PACKET_INFO" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 6 +++--- drivers/staging/bcm/Misc.c | 8 ++++---- drivers/staging/bcm/Prototypes.h | 2 +- drivers/staging/bcm/Qos.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 20ac2b3ecdd2..f604b1bfa45d 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -159,13 +159,13 @@ typedef struct _S_CLASSIFIER_RULE { } S_CLASSIFIER_RULE; /* typedef struct _S_CLASSIFIER_RULE S_CLASSIFIER_RULE; */ -typedef struct _S_FRAGMENTED_PACKET_INFO { +struct bcm_fragmented_packet_info { BOOLEAN bUsed; ULONG ulSrcIpAddress; USHORT usIpIdentification; S_CLASSIFIER_RULE *pstMatchedClassifierEntry; BOOLEAN bOutOfOrderFragment; -} S_FRAGMENTED_PACKET_INFO, *PS_FRAGMENTED_PACKET_INFO; +}; struct bcm_packet_info { /* classification extension Rule */ @@ -389,7 +389,7 @@ struct _MINI_ADAPTER { BOOLEAN bDPLLConfig; UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; - S_FRAGMENTED_PACKET_INFO astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES]; + struct bcm_fragmented_packet_info astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES]; atomic_t uiMBupdate; UINT32 PmuMode; NVM_TYPE eNVMType; diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index 8223a6913fc5..3ca962d6adee 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -1533,12 +1533,12 @@ S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentific return NULL; } -void AddFragIPClsEntry(PMINI_ADAPTER Adapter, PS_FRAGMENTED_PACKET_INFO psFragPktInfo) +void AddFragIPClsEntry(PMINI_ADAPTER Adapter, struct bcm_fragmented_packet_info *psFragPktInfo) { UINT uiIndex = 0; for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) { - memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(S_FRAGMENTED_PACKET_INFO)); + memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(struct bcm_fragmented_packet_info)); break; } } @@ -1552,7 +1552,7 @@ void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG S (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) && (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIp)) - memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(S_FRAGMENTED_PACKET_INFO)); + memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(struct bcm_fragmented_packet_info)); } } @@ -1652,7 +1652,7 @@ static void beceem_protocol_reset(PMINI_ADAPTER Adapter) if (Adapter->TimerActive == TRUE) Adapter->TimerActive = FALSE; - memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); + memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(struct bcm_fragmented_packet_info) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); for (i = 0; i < HiPriority; i++) { /* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */ diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h index b22f61d96c49..4bb3796c9c5a 100644 --- a/drivers/staging/bcm/Prototypes.h +++ b/drivers/staging/bcm/Prototypes.h @@ -103,7 +103,7 @@ int InitLedSettings(PMINI_ADAPTER Adapter); S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIP); -void AddFragIPClsEntry(PMINI_ADAPTER Adapter,PS_FRAGMENTED_PACKET_INFO psFragPktInfo); +void AddFragIPClsEntry(PMINI_ADAPTER Adapter, struct bcm_fragmented_packet_info *psFragPktInfo); void DelFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIp); diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c index 9bf61ff6ac78..c87801cdd866 100644 --- a/drivers/staging/bcm/Qos.c +++ b/drivers/staging/bcm/Qos.c @@ -631,7 +631,7 @@ USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) if(bFragmentedPkt && (usCurrFragment == 0)) { //First Fragment of Fragmented Packet. Create Frag CLS Entry - S_FRAGMENTED_PACKET_INFO stFragPktInfo; + struct bcm_fragmented_packet_info stFragPktInfo; stFragPktInfo.bUsed = TRUE; stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr; stFragPktInfo.usIpIdentification = pIpHeader->id; -- GitLab From 92562aeec46c965821c59f78e58f1cfe0a47bbaf Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:03 -0400 Subject: [PATCH 0270/5711] Staging: bcm: Remove typedef for _S_CLASSIFIER_RULE and call directly. This patch removes typedef for _S_CLASSIFIER_RULE, changes the name of the struct from _S_CLASSIFIER_RULE to bcm_classifier_rule. In addition, any calls to the following typedefs "S_CLASSIFIER_RULE" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 9 ++++---- drivers/staging/bcm/CmHost.c | 10 ++++----- drivers/staging/bcm/IPv6Protocol.c | 10 ++++----- drivers/staging/bcm/IPv6ProtocolHdr.h | 8 +++---- drivers/staging/bcm/Misc.c | 4 ++-- drivers/staging/bcm/Prototypes.h | 8 +++---- drivers/staging/bcm/Qos.c | 30 +++++++++++++-------------- drivers/staging/bcm/sort.c | 6 +++--- 8 files changed, 42 insertions(+), 43 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index f604b1bfa45d..d2260fe8c2a1 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -105,7 +105,7 @@ typedef struct _S_HDR_SUPRESSION_CONTEXTINFO { UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */ } S_HDR_SUPRESSION_CONTEXTINFO; -typedef struct _S_CLASSIFIER_RULE { +struct bcm_classifier_rule { ULONG ulSFID; UCHAR ucReserved[2]; B_UINT16 uiClassifierRuleIndex; @@ -156,14 +156,13 @@ typedef struct _S_CLASSIFIER_RULE { UCHAR usUserPriority[2]; USHORT usVLANID; USHORT usValidityBitMap; -} S_CLASSIFIER_RULE; -/* typedef struct _S_CLASSIFIER_RULE S_CLASSIFIER_RULE; */ +}; struct bcm_fragmented_packet_info { BOOLEAN bUsed; ULONG ulSrcIpAddress; USHORT usIpIdentification; - S_CLASSIFIER_RULE *pstMatchedClassifierEntry; + struct bcm_classifier_rule *pstMatchedClassifierEntry; BOOLEAN bOutOfOrderFragment; }; @@ -295,7 +294,7 @@ struct _MINI_ADAPTER { USHORT CurrNumRecvDescs; UINT u32TotalDSD; struct bcm_packet_info PackInfo[NO_OF_QUEUES]; - S_CLASSIFIER_RULE astClassifierTable[MAX_CLASSIFIERS]; + struct bcm_classifier_rule astClassifierTable[MAX_CLASSIFIERS]; BOOLEAN TransferMode; /*************** qos ******************/ diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index f584fdc6be44..a0b1720aae3e 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -112,7 +112,7 @@ static VOID deleteSFBySfid(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) } static inline VOID -CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, +CopyIpAddrToClassifier(struct bcm_classifier_rule *pstClassifierEntry, B_UINT8 u8IpAddressLen, B_UINT8 *pu8IpAddressMaskSrc, BOOLEAN bIpVersion6, E_IPADDR_CONTEXT eIpAddrContext) { @@ -238,7 +238,7 @@ void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter, B_UINT16 TID, BOOLEAN bFreeAll) */ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSLTypes *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) { - S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + struct bcm_classifier_rule *pstClassifierEntry = NULL; /* VOID *pvPhsContext = NULL; */ int i; /* UCHAR ucProtocolLength=0; */ @@ -367,7 +367,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL */ static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex, UINT nClassifierIndex) { - S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + struct bcm_classifier_rule *pstClassifierEntry = NULL; B_UINT16 u16PacketClassificationRuleIndex; USHORT usVCID; /* VOID *pvPhsContext = NULL; */ @@ -386,7 +386,7 @@ static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSear if (pstClassifierEntry) { pstClassifierEntry->bUsed = FALSE; pstClassifierEntry->uiClassifierRuleIndex = 0; - memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_RULE)); + memset(pstClassifierEntry, 0, sizeof(struct bcm_classifier_rule)); /* Delete the PHS Rule for this classifier */ PhsDeleteClassifierRule(&Adapter->stBCMPhsContext, usVCID, u16PacketClassificationRuleIndex); @@ -398,7 +398,7 @@ static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSear */ VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) { - S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + struct bcm_classifier_rule *pstClassifierEntry = NULL; int i; /* B_UINT16 u16PacketClassificationRuleIndex; */ USHORT ulVCID; diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c index 1da21642c18e..4adbf9dbf7b5 100644 --- a/drivers/staging/bcm/IPv6Protocol.c +++ b/drivers/staging/bcm/IPv6Protocol.c @@ -1,8 +1,8 @@ #include "headers.h" -static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule, +static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule, IPV6Header *pstIpv6Header); -static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule, +static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule, IPV6Header *pstIpv6Header); static VOID DumpIpv6Header(IPV6Header *pstIpv6Header); @@ -181,7 +181,7 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort, * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet */ USHORT IpVersion6(PMINI_ADAPTER Adapter, PVOID pcIpHeader, - S_CLASSIFIER_RULE *pstClassifierRule) + struct bcm_classifier_rule *pstClassifierRule) { USHORT ushDestPort = 0; USHORT ushSrcPort = 0; @@ -288,7 +288,7 @@ USHORT IpVersion6(PMINI_ADAPTER Adapter, PVOID pcIpHeader, } -static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule, +static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule, IPV6Header *pstIpv6Header) { UINT uiLoopIndex = 0; @@ -344,7 +344,7 @@ static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule, return FALSE; } -static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule, +static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule, IPV6Header *pstIpv6Header) { UINT uiLoopIndex = 0; diff --git a/drivers/staging/bcm/IPv6ProtocolHdr.h b/drivers/staging/bcm/IPv6ProtocolHdr.h index a0db5a1de763..369b55316c79 100644 --- a/drivers/staging/bcm/IPv6ProtocolHdr.h +++ b/drivers/staging/bcm/IPv6ProtocolHdr.h @@ -104,13 +104,13 @@ typedef enum _E_IPADDR_CONTEXT USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ PVOID pcIpHeader, /**bShutStatus = FALSE; } -S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP) +struct bcm_classifier_rule *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP) { UINT uiIndex = 0; for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h index 4bb3796c9c5a..42a04b95909d 100644 --- a/drivers/staging/bcm/Prototypes.h +++ b/drivers/staging/bcm/Prototypes.h @@ -33,9 +33,9 @@ INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid); USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb); -BOOLEAN MatchSrcPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushSrcPort); -BOOLEAN MatchDestPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushSrcPort); -BOOLEAN MatchProtocol(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucProtocol); +BOOLEAN MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort); +BOOLEAN MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort); +BOOLEAN MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol); INT SetupNextSend(PMINI_ADAPTER Adapter, /**ucEtherTypeLen==0)|| @@ -718,7 +718,7 @@ static BOOLEAN EthCSMatchEThTypeSAP(S_CLASSIFIER_RULE *pstClassifierRule,struct } -static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) +static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) { BOOLEAN bClassificationSucceed = FALSE; USHORT usVLANID; @@ -770,7 +770,7 @@ static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct s static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, PS_ETHCS_PKT_INFO pstEthCsPktInfo, - S_CLASSIFIER_RULE *pstClassifierRule, + struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport) { BOOLEAN bClassificationSucceed = FALSE; diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c index 79585e4affff..5f891fa90a62 100644 --- a/drivers/staging/bcm/sort.c +++ b/drivers/staging/bcm/sort.c @@ -33,8 +33,8 @@ VOID SortPackInfo(PMINI_ADAPTER Adapter) static int compare_classifiers(void const *a, void const *b) { - S_CLASSIFIER_RULE const *pa = a; - S_CLASSIFIER_RULE const *pb = b; + struct bcm_classifier_rule const *pa = a; + struct bcm_classifier_rule const *pb = b; if (!pa->bUsed || !pb->bUsed) return 0; @@ -48,5 +48,5 @@ VOID SortClassifiers(PMINI_ADAPTER Adapter) DBG_LVL_ALL, "<======="); sort(Adapter->astClassifierTable, MAX_CLASSIFIERS, - sizeof(S_CLASSIFIER_RULE), compare_classifiers, NULL); + sizeof(struct bcm_classifier_rule), compare_classifiers, NULL); } -- GitLab From f428450a5d675682def5403e6842f6c61872c3dd Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:04 -0400 Subject: [PATCH 0271/5711] Staging: bcm: Remove typedef for _S_HDR_SUPRESSION_CONTEXTINFO and call directly. This patch removes typedef for _S_HDR_SUPRESSION_CONTEXTINFO, changes the name of the struct from _S_HDR_SUPRESSION_CONTEXTINFO to bcm_hdr_supression_contextinfo. In addition, any calls to the following typedefs "S_HDR_SUPRESSION_CONTEXTINFO" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index d2260fe8c2a1..9b5a0aa805af 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -100,10 +100,10 @@ typedef union _U_IP_ADDRESS { }; } U_IP_ADDRESS; -typedef struct _S_HDR_SUPRESSION_CONTEXTINFO { +struct bcm_hdr_supression_contextinfo { UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */ UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */ -} S_HDR_SUPRESSION_CONTEXTINFO; +}; struct bcm_classifier_rule { ULONG ulSFID; @@ -380,7 +380,7 @@ struct _MINI_ADAPTER { BOOLEAN bLinkDownRequested; int downloadDDR; PHS_DEVICE_EXTENSION stBCMPhsContext; - S_HDR_SUPRESSION_CONTEXTINFO stPhsTxContextInfo; + struct bcm_hdr_supression_contextinfo stPhsTxContextInfo; uint8_t ucaPHSPktRestoreBuf[2048]; uint8_t bPHSEnabled; BOOLEAN AutoFirmDld; -- GitLab From 0e000c2ee331a3389ab8875cb036e9cfcbcebea5 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:05 -0400 Subject: [PATCH 0272/5711] Staging: bcm: Remove typedef for _CLASSIFICATION_ONLY. This patch removes typedef for _CLASSIFICATION_ONLY, because it is not being used. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 9b5a0aa805af..13c0d0af0928 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -66,16 +66,6 @@ typedef struct _CLASSIFICATION_RULE { USHORT usVcid; } CLASSIFICATION_RULE, *PCLASSIFICATION_RULE; -typedef struct _CLASSIFICATION_ONLY { - USHORT usVcid; - ULONG DestIpAddress; - ULONG DestIpMask; - USHORT usPortLo; - USHORT usPortHi; - BOOLEAN bIpVersion; - UCHAR ucDestinationAddress[16]; -} CLASSIFICATION_ONLY, *PCLASSIFICATION_ONLY; - #define MAX_IP_RANGE_LENGTH 4 #define MAX_PORT_RANGE 4 #define MAX_PROTOCOL_LENGTH 32 -- GitLab From fa64354ff32a06dc8f392c2b3e0ddd57e2eb0357 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:06 -0400 Subject: [PATCH 0273/5711] Staging: bcm: Remove typedef for _CLASSIFICATION_RULE. This patch removes typedef for _CLASSIFICATION_RULE, because it is not being used. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 13c0d0af0928..e6269236c567 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -54,18 +54,6 @@ typedef struct _ADD_CONNECTION { UCHAR SrcProtocol; } ADD_CONNECTION, *PADD_CONNECTION; -typedef struct _CLASSIFICATION_RULE { - UCHAR ucIPSrcAddrLen; - UCHAR ucIPSrcAddr[32]; - UCHAR ucIPDestAddrLen; - UCHAR ucIPDestAddr[32]; - UCHAR ucSrcPortRangeLen; - UCHAR ucSrcPortRange[4]; - UCHAR ucDestPortRangeLen; - UCHAR ucDestPortRange[4]; - USHORT usVcid; -} CLASSIFICATION_RULE, *PCLASSIFICATION_RULE; - #define MAX_IP_RANGE_LENGTH 4 #define MAX_PORT_RANGE 4 #define MAX_PROTOCOL_LENGTH 32 -- GitLab From 845bd532cda92afc3329dff753aefbe4164a8f83 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:07 -0400 Subject: [PATCH 0274/5711] Staging: bcm: Remove typedef for _ADD_CONNECTION. This patch removes typedef for _ADD_CONNECTION, because it is not being used. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index e6269236c567..5256e3f2bcc3 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -34,26 +34,6 @@ struct link_request { } __packed; typedef struct link_request LINK_REQUEST, *PLINK_REQUEST; -/* classification extension is added */ -typedef struct _ADD_CONNECTION { - ULONG SrcIpAddressCount; - ULONG SrcIpAddress[MAX_CONNECTIONS]; - ULONG SrcIpMask[MAX_CONNECTIONS]; - - ULONG DestIpAddressCount; - ULONG DestIpAddress[MAX_CONNECTIONS]; - ULONG DestIpMask[MAX_CONNECTIONS]; - - USHORT SrcPortBegin; - USHORT SrcPortEnd; - - USHORT DestPortBegin; - USHORT DestPortEnd; - - UCHAR SrcTOS; - UCHAR SrcProtocol; -} ADD_CONNECTION, *PADD_CONNECTION; - #define MAX_IP_RANGE_LENGTH 4 #define MAX_PORT_RANGE 4 #define MAX_PROTOCOL_LENGTH 32 -- GitLab From 2610c7a889103587ce9a5714291a53dbf5490c3c Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:08 -0400 Subject: [PATCH 0275/5711] Staging: bcm: Remove typedef for link_request and call directly. This patch removes typedef for link_request, changes the name of the struct from link_request to bcm_link_request. In addition, any calls to the following typedefs "LINK_REQUEST, *PLINK_REQUEST, *CONTROL_MESSAGE" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 5 +---- drivers/staging/bcm/Bcmchar.c | 2 +- drivers/staging/bcm/InterfaceTx.c | 2 +- drivers/staging/bcm/Misc.c | 18 +++++++++--------- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 5256e3f2bcc3..a36767d9c551 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -28,11 +28,10 @@ struct _CONTROL_PACKET { } __packed; typedef struct _CONTROL_PACKET CONTROL_PACKET, *PCONTROL_PACKET; -struct link_request { +struct bcm_link_request { LEADER Leader; UCHAR szData[4]; } __packed; -typedef struct link_request LINK_REQUEST, *PLINK_REQUEST; #define MAX_IP_RANGE_LENGTH 4 #define MAX_PORT_RANGE 4 @@ -417,8 +416,6 @@ struct bcm_firmware_info { /* holds the value of net_device structure.. */ extern struct net_device *gblpnetdev; -typedef LINK_REQUEST CONTROL_MESSAGE; - struct bcm_ddr_setting { UINT ulRegAddress; UINT ulRegValue; diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 8d4052a7deae..d1dc0c3852ab 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -722,7 +722,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - if (IoBuffer.InputLength < sizeof(struct link_request)) + if (IoBuffer.InputLength < sizeof(struct bcm_link_request)) return -EINVAL; if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE) diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c index a842de9de6b5..3012f29cf85c 100644 --- a/drivers/staging/bcm/InterfaceTx.c +++ b/drivers/staging/bcm/InterfaceTx.c @@ -5,7 +5,7 @@ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) { PUSB_TCB pTcb= (PUSB_TCB)urb->context; PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter; - CONTROL_MESSAGE *pControlMsg = (CONTROL_MESSAGE *)urb->transfer_buffer; + struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer; PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ; BOOLEAN bpowerDownMsg = FALSE ; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index b2d90d1e26af..954c3adf7944 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -237,7 +237,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) INT Status = 0; unsigned char *ctrl_buff = NULL; UINT pktlen = 0; - PLINK_REQUEST pLinkReq = NULL; + struct bcm_link_request *pLinkReq = NULL; PUCHAR pucAddIndication = NULL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>"); @@ -246,7 +246,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) return -EINVAL; } - pLinkReq = (PLINK_REQUEST)ioBuffer; + pLinkReq = (struct bcm_link_request *)ioBuffer; pLeader = (PLEADER)ioBuffer; /* ioBuffer Contains sw_Status and Payload */ if (Adapter->bShutStatus == TRUE && @@ -414,7 +414,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) * * Returns - None. *****************************************************************/ -static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, PLINK_REQUEST pstStatisticsPtrRequest) +static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, struct bcm_link_request *pstStatisticsPtrRequest) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; @@ -438,10 +438,10 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, PLINK_REQUEST ps *******************************************************************/ VOID LinkMessage(PMINI_ADAPTER Adapter) { - PLINK_REQUEST pstLinkRequest = NULL; + struct bcm_link_request *pstLinkRequest = NULL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) { - pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); + pstLinkRequest = kzalloc(sizeof(struct bcm_link_request), GFP_ATOMIC); if (!pstLinkRequest) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); return; @@ -456,7 +456,7 @@ VOID LinkMessage(PMINI_ADAPTER Adapter) Adapter->bSyncUpRequestSent = TRUE; } else if (Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) { - pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); + pstLinkRequest = kzalloc(sizeof(struct bcm_link_request), GFP_ATOMIC); if (!pstLinkRequest) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); return; @@ -584,7 +584,7 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter) { INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0; struct timeval tv; - CONTROL_MESSAGE stIdleResponse = {{0} }; + struct bcm_link_request stIdleResponse = {{0} }; memset(&tv, 0, sizeof(tv)); stIdleResponse.Leader.Status = IDLE_MESSAGE; stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH; @@ -1392,11 +1392,11 @@ static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) { - CONTROL_MESSAGE stShutdownResponse; + struct bcm_link_request stShutdownResponse; UINT NVMAccess = 0, lowPwrAbortMsg = 0; UINT Status = 0; - memset(&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE)); + memset(&stShutdownResponse, 0, sizeof(struct bcm_link_request)); stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ; stShutdownResponse.Leader.PLength = 8; /* 8 bytes; */ stShutdownResponse.szData[0] = LINK_UP_ACK; -- GitLab From c1975eda98d12c7b34cdc94c53cda32de263e4af Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:09 -0400 Subject: [PATCH 0276/5711] Staging: bcm: Remove typedef for _CONTROL_PACKET and call directly. This patch removes typedef for _CONTROL_PACKET, changes the name of the struct from _CONTROL_PACKET to bcm_control_packet. In addition, any calls to the following typedefs "CONTROL_PACKET, *PCONTROL_PACKET" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index a36767d9c551..ea83bc03b696 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -21,12 +21,11 @@ struct _PACKETTOSEND { } __packed; typedef struct _PACKETTOSEND PACKETTOSEND, *PPACKETTOSEND; -struct _CONTROL_PACKET { +struct bcm_control_packet { PVOID ControlBuff; UINT ControlBuffLen; - struct _CONTROL_PACKET *next; + struct bcm_control_packet *next; } __packed; -typedef struct _CONTROL_PACKET CONTROL_PACKET, *PCONTROL_PACKET; struct bcm_link_request { LEADER Leader; -- GitLab From a869993f8f763b9792990e7ef8e8a644b799d0d3 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:10 -0400 Subject: [PATCH 0277/5711] Staging: bcm: Remove typedef for _PACKETTOSEND and call directly. This patch removes typedef for _PACKETTOSEND, changes the name of the struct from _PACKETTOSEND to bcm_packettosend. In addition, any calls to the following typedefs "PACKETTOSEND, *PPACKETTOSEND" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 3 +-- drivers/staging/bcm/Macros.h | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index ea83bc03b696..fce61ed2ab06 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -15,11 +15,10 @@ struct _LEADER { } __packed; typedef struct _LEADER LEADER, *PLEADER; -struct _PACKETTOSEND { +struct bcm_packettosend { LEADER Leader; UCHAR ucPayload; } __packed; -typedef struct _PACKETTOSEND PACKETTOSEND, *PPACKETTOSEND; struct bcm_control_packet { PVOID ControlBuff; diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h index 8238cdba7a0f..7c03cce5eede 100644 --- a/drivers/staging/bcm/Macros.h +++ b/drivers/staging/bcm/Macros.h @@ -109,10 +109,10 @@ #define LEADER_STATUS 0x00 #define LEADER_STATUS_TCP_ACK 0x1 #define LEADER_SIZE sizeof(LEADER) -#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) -#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) +#define MAC_ADDR_REQ_SIZE sizeof(struct bcm_packettosend) +#define SS_INFO_REQ_SIZE sizeof(struct bcm_packettosend) #define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest)) -#define IDLE_REQ_SIZE sizeof(PACKETTOSEND) +#define IDLE_REQ_SIZE sizeof(struct bcm_packettosend) #define MAX_TRANSFER_CTRL_BYTE_USB (2*1024) -- GitLab From ff352042ebb8f3823fb3725bc2356f6a60ce20df Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:11 -0400 Subject: [PATCH 0278/5711] Staging: bcm: Remove typedef for _LEADER and call directly. This patch removes typedef for _LEADER, changes the name of the struct from _LEADER to bcm_leader. In addition, any calls to the following typedefs "LEADER, *PLEADER" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 7 +++---- drivers/staging/bcm/CmHost.c | 4 ++-- drivers/staging/bcm/InterfaceRx.c | 6 +++--- drivers/staging/bcm/LeakyBucket.c | 4 ++-- drivers/staging/bcm/Macros.h | 2 +- drivers/staging/bcm/Misc.c | 6 +++--- drivers/staging/bcm/Transmit.c | 6 +++--- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index fce61ed2ab06..f269daa2d52d 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -7,16 +7,15 @@ #define MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES 256 #include "Debug.h" -struct _LEADER { +struct bcm_leader { USHORT Vcid; USHORT PLength; UCHAR Status; UCHAR Unused[3]; } __packed; -typedef struct _LEADER LEADER, *PLEADER; struct bcm_packettosend { - LEADER Leader; + struct bcm_leader Leader; UCHAR ucPayload; } __packed; @@ -27,7 +26,7 @@ struct bcm_control_packet { } __packed; struct bcm_link_request { - LEADER Leader; + struct bcm_leader Leader; UCHAR szData[4]; } __packed; diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index a0b1720aae3e..7189df69d81f 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -1663,7 +1663,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* "); - pLeader = (PLEADER)Adapter->caDsxReqResp; + pLeader = (struct bcm_leader *)Adapter->caDsxReqResp; pLeader->Status = CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ; pLeader->Vcid = 0; diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c index d495828a731f..7940a2e7def2 100644 --- a/drivers/staging/bcm/InterfaceRx.c +++ b/drivers/staging/bcm/InterfaceRx.c @@ -46,7 +46,7 @@ static void read_bulk_callback(struct urb *urb) PUSB_RCB pRcb = (PUSB_RCB)urb->context; PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter; PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; - PLEADER pLeader = urb->transfer_buffer; + struct bcm_leader *pLeader = urb->transfer_buffer; if (unlikely(netif_msg_rx_status(Adapter))) pr_info(PFX "%s: rx urb status %d length %d\n", @@ -126,7 +126,7 @@ static void read_bulk_callback(struct urb *urb) BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt..."); *(PUSHORT)skb->data = pLeader->Status; memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + - (sizeof(LEADER)), pLeader->PLength); + (sizeof(struct bcm_leader)), pLeader->PLength); skb->len = pLeader->PLength + sizeof(USHORT); spin_lock(&Adapter->control_queue_lock); @@ -144,7 +144,7 @@ static void read_bulk_callback(struct urb *urb) */ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt..."); skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); - memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength); + memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_leader), pLeader->PLength); skb->dev = Adapter->dev; /* currently skb->len has extra ETH_HLEN bytes in the beginning */ diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index 89f1e577f7cd..a6584d7c28bd 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -243,10 +243,10 @@ static VOID CheckAndSendPacketFromIndex(PMINI_ADAPTER Adapter, struct bcm_packet { spin_lock_bh(&psSF->SFQueueLock); psSF->NumOfPacketsSent++; - psSF->uiSentBytes+=((PLEADER)pControlPacket)->PLength; + psSF->uiSentBytes+=((struct bcm_leader *)pControlPacket)->PLength; psSF->uiSentPackets++; atomic_dec(&Adapter->TotalPacketCount); - psSF->uiCurrentBytesOnHost -= ((PLEADER)pControlPacket)->PLength; + psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength; psSF->uiCurrentPacketsOnHost--; atomic_inc(&Adapter->index_rd_txcntrlpkt); spin_unlock_bh(&psSF->SFQueueLock); diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h index 7c03cce5eede..b5ca6f6a1cb2 100644 --- a/drivers/staging/bcm/Macros.h +++ b/drivers/staging/bcm/Macros.h @@ -108,7 +108,7 @@ /*Leader related terms */ #define LEADER_STATUS 0x00 #define LEADER_STATUS_TCP_ACK 0x1 -#define LEADER_SIZE sizeof(LEADER) +#define LEADER_SIZE sizeof(struct bcm_leader) #define MAC_ADDR_REQ_SIZE sizeof(struct bcm_packettosend) #define SS_INFO_REQ_SIZE sizeof(struct bcm_packettosend) #define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest)) diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index 954c3adf7944..2772e9259f42 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -233,7 +233,7 @@ exit_download: */ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) { - PLEADER pLeader = NULL; + struct bcm_leader *pLeader = NULL; INT Status = 0; unsigned char *ctrl_buff = NULL; UINT pktlen = 0; @@ -247,7 +247,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) } pLinkReq = (struct bcm_link_request *)ioBuffer; - pLeader = (PLEADER)ioBuffer; /* ioBuffer Contains sw_Status and Payload */ + pLeader = (struct bcm_leader *)ioBuffer; /* ioBuffer Contains sw_Status and Payload */ if (Adapter->bShutStatus == TRUE && pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD && @@ -373,7 +373,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) memset(ctrl_buff, 0, pktlen+LEADER_SIZE); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); - *(PLEADER)ctrl_buff = *pLeader; + *(struct bcm_leader *)ctrl_buff = *pLeader; memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c index d5e4a7404f71..63c6a74bb1ff 100644 --- a/drivers/staging/bcm/Transmit.c +++ b/drivers/staging/bcm/Transmit.c @@ -43,7 +43,7 @@ This function dispatches control packet to the h/w interface */ INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket) { - PLEADER PLeader = (PLEADER)pControlPacket; + struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); if(!pControlPacket || !Adapter) @@ -90,7 +90,7 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid) BOOLEAN bHeaderSupressionEnabled = FALSE; B_UINT16 uiClassifierRuleID; u16 QueueIndex = skb_get_queue_mapping(Packet); - LEADER Leader={0}; + struct bcm_leader Leader={0}; if(Packet->len > MAX_DEVICE_DESC_SIZE) { @@ -143,7 +143,7 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid) else { Leader.PLength = Packet->len - ETH_HLEN; - memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); + memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, -- GitLab From 2979460d7aba1dac3452edcacd7b8c4cfcf06067 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sat, 26 May 2012 12:05:12 -0400 Subject: [PATCH 0279/5711] Staging: bcm: Remove typedef for _MINI_ADAPTER and call directly. This patch removes typedef for _MINI_ADAPTER, changes the name of the struct from _MINI_ADAPTER to bcm_mini_adapter. In addition, any calls to the following typedefs "MINI_ADAPTER, *PMINI_ADAPTER" are changed to call the struct directly. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 13 +- drivers/staging/bcm/Bcmchar.c | 12 +- drivers/staging/bcm/Bcmnet.c | 18 +- drivers/staging/bcm/CmHost.c | 50 +++--- drivers/staging/bcm/CmHost.h | 10 +- drivers/staging/bcm/DDRInit.c | 4 +- drivers/staging/bcm/DDRInit.h | 4 +- drivers/staging/bcm/HandleControlPacket.c | 6 +- drivers/staging/bcm/IPv6Protocol.c | 16 +- drivers/staging/bcm/IPv6ProtocolHdr.h | 2 +- drivers/staging/bcm/InterfaceAdapter.h | 2 +- drivers/staging/bcm/InterfaceDld.c | 14 +- drivers/staging/bcm/InterfaceIdleMode.c | 12 +- drivers/staging/bcm/InterfaceIdleMode.h | 10 +- drivers/staging/bcm/InterfaceInit.c | 8 +- drivers/staging/bcm/InterfaceIsr.c | 2 +- drivers/staging/bcm/InterfaceIsr.h | 4 +- drivers/staging/bcm/InterfaceMisc.c | 2 +- drivers/staging/bcm/InterfaceMisc.h | 2 +- drivers/staging/bcm/InterfaceRx.c | 6 +- drivers/staging/bcm/InterfaceTx.c | 4 +- drivers/staging/bcm/LeakyBucket.c | 10 +- drivers/staging/bcm/Misc.c | 88 +++++----- drivers/staging/bcm/PHSModule.c | 38 ++-- drivers/staging/bcm/PHSModule.h | 6 +- drivers/staging/bcm/Prototypes.h | 160 ++++++++--------- drivers/staging/bcm/Qos.c | 42 ++--- drivers/staging/bcm/Transmit.c | 8 +- drivers/staging/bcm/hostmibs.c | 4 +- drivers/staging/bcm/led_control.c | 22 +-- drivers/staging/bcm/nvm.c | 204 +++++++++++----------- drivers/staging/bcm/sort.c | 4 +- drivers/staging/bcm/vendorspecificextn.c | 6 +- drivers/staging/bcm/vendorspecificextn.h | 6 +- 34 files changed, 399 insertions(+), 400 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index f269daa2d52d..11d2c5a84552 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -192,7 +192,7 @@ struct bcm_packet_info { struct bcm_tarang_data { struct bcm_tarang_data *next; - struct _MINI_ADAPTER *Adapter; + struct bcm_mini_adapter *Adapter; struct sk_buff *RxAppControlHead; struct sk_buff *RxAppControlTail; int AppCtrlQueueLen; @@ -208,15 +208,15 @@ struct bcm_targetdsx_buffer { BOOLEAN valid; }; -typedef int (*FP_FLASH_WRITE)(struct _MINI_ADAPTER *, UINT, PVOID); +typedef int (*FP_FLASH_WRITE)(struct bcm_mini_adapter *, UINT, PVOID); -typedef int (*FP_FLASH_WRITE_STATUS)(struct _MINI_ADAPTER *, UINT, PVOID); +typedef int (*FP_FLASH_WRITE_STATUS)(struct bcm_mini_adapter *, UINT, PVOID); /* * Driver adapter data structure */ -struct _MINI_ADAPTER { - struct _MINI_ADAPTER *next; +struct bcm_mini_adapter { + struct bcm_mini_adapter *next; struct net_device *dev; u32 msg_enable; CHAR *caDsxReqResp; @@ -394,7 +394,6 @@ struct _MINI_ADAPTER { UINT gpioBitMap; S_BCM_DEBUG_STATE stDebugState; }; -typedef struct _MINI_ADAPTER MINI_ADAPTER, *PMINI_ADAPTER; #define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev) @@ -417,7 +416,7 @@ struct bcm_ddr_setting { UINT ulRegAddress; UINT ulRegValue; }; -int InitAdapter(PMINI_ADAPTER psAdapter); +int InitAdapter(struct bcm_mini_adapter *psAdapter); /* ===================================================================== * Beceem vendor request codes for EP0 diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index d1dc0c3852ab..cf411d1706b1 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -15,7 +15,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp) { - PMINI_ADAPTER Adapter = NULL; + struct bcm_mini_adapter *Adapter = NULL; struct bcm_tarang_data *pTarang = NULL; Adapter = GET_BCM_ADAPTER(gblpnetdev); @@ -44,7 +44,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp) static int bcm_char_release(struct inode *inode, struct file *filp) { struct bcm_tarang_data *pTarang, *tmp, *ptmp; - PMINI_ADAPTER Adapter = NULL; + struct bcm_mini_adapter *Adapter = NULL; struct sk_buff *pkt, *npkt; pTarang = (struct bcm_tarang_data *)filp->private_data; @@ -98,7 +98,7 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos) { struct bcm_tarang_data *pTarang = filp->private_data; - PMINI_ADAPTER Adapter = pTarang->Adapter; + struct bcm_mini_adapter *Adapter = pTarang->Adapter; struct sk_buff *Packet = NULL; ssize_t PktLen = 0; int wait_ret_val = 0; @@ -157,7 +157,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { struct bcm_tarang_data *pTarang = filp->private_data; void __user *argp = (void __user *)arg; - PMINI_ADAPTER Adapter = pTarang->Adapter; + struct bcm_mini_adapter *Adapter = pTarang->Adapter; INT Status = STATUS_FAILURE; int timeout = 0; IOCTL_BUFFER IoBuffer; @@ -2014,7 +2014,7 @@ static const struct file_operations bcm_fops = { .llseek = no_llseek, }; -int register_control_device_interface(PMINI_ADAPTER Adapter) +int register_control_device_interface(struct bcm_mini_adapter *Adapter) { if (Adapter->major > 0) @@ -2039,7 +2039,7 @@ int register_control_device_interface(PMINI_ADAPTER Adapter) return 0; } -void unregister_control_device_interface(PMINI_ADAPTER Adapter) +void unregister_control_device_interface(struct bcm_mini_adapter *Adapter) { if (Adapter->major > 0) { device_destroy(bcm_class, MKDEV(Adapter->major, 0)); diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c index 133e146a3dd4..6e8c7f523214 100644 --- a/drivers/staging/bcm/Bcmnet.c +++ b/drivers/staging/bcm/Bcmnet.c @@ -4,7 +4,7 @@ struct net_device *gblpnetdev; static INT bcm_open(struct net_device *dev) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); if (Adapter->fw_download_done == FALSE) { pr_notice(PFX "%s: link up failed (download in progress)\n", @@ -28,7 +28,7 @@ static INT bcm_open(struct net_device *dev) static INT bcm_close(struct net_device *dev) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); if (netif_msg_ifdown(Adapter)) pr_info(PFX "%s: disabling interface\n", dev->name); @@ -59,7 +59,7 @@ static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb) static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); u16 qindex = skb_get_queue_mapping(skb); @@ -141,7 +141,7 @@ static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter; struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface); @@ -156,21 +156,21 @@ static void bcm_get_drvinfo(struct net_device *dev, static u32 bcm_get_link(struct net_device *dev) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); return Adapter->LinkUpStatus; } static u32 bcm_get_msglevel(struct net_device *dev) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); return Adapter->msg_enable; } static void bcm_set_msglevel(struct net_device *dev, u32 level) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); Adapter->msg_enable = level; } @@ -183,7 +183,7 @@ static const struct ethtool_ops bcm_ethtool_ops = { .set_msglevel = bcm_set_msglevel, }; -int register_networkdev(PMINI_ADAPTER Adapter) +int register_networkdev(struct bcm_mini_adapter *Adapter) { struct net_device *net = Adapter->dev; PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; @@ -224,7 +224,7 @@ int register_networkdev(PMINI_ADAPTER Adapter) return 0; } -void unregister_networkdev(PMINI_ADAPTER Adapter) +void unregister_networkdev(struct bcm_mini_adapter *Adapter) { struct net_device *net = Adapter->dev; PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 7189df69d81f..189d243878c9 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -14,7 +14,7 @@ enum E_CLASSIFIER_ACTION { eDeleteClassifier }; -static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); +static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter, B_UINT16 tid); /************************************************************ * Function - SearchSfid @@ -28,7 +28,7 @@ static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); * Returns - Queue index for this SFID(If matched) * Else Invalid Queue Index(If Not matched) ************************************************************/ -int SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) +int SearchSfid(struct bcm_mini_adapter *Adapter, UINT uiSfid) { int i; @@ -49,7 +49,7 @@ int SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) * Returns - Queue index for the free SFID * Else returns Invalid Index. ****************************************************************/ -static int SearchFreeSfid(PMINI_ADAPTER Adapter) +static int SearchFreeSfid(struct bcm_mini_adapter *Adapter) { int i; @@ -63,12 +63,12 @@ static int SearchFreeSfid(PMINI_ADAPTER Adapter) /* * Function: SearchClsid * Description: This routinue would search Classifier having specified ClassifierID as input parameter - * Input parameters: PMINI_ADAPTER Adapter - Adapter Context + * Input parameters: struct bcm_mini_adapter *Adapter - Adapter Context * unsigned int uiSfid - The SF in which the classifier is to searched * B_UINT16 uiClassifierID - The classifier ID to be searched * Return: int :Classifier table index of matching entry */ -static int SearchClsid(PMINI_ADAPTER Adapter, ULONG ulSFID, B_UINT16 uiClassifierID) +static int SearchClsid(struct bcm_mini_adapter *Adapter, ULONG ulSFID, B_UINT16 uiClassifierID) { int i; @@ -87,7 +87,7 @@ static int SearchClsid(PMINI_ADAPTER Adapter, ULONG ulSFID, B_UINT16 uiClassifi * This routinue would search Free available Classifier entry in classifier table. * @return free Classifier Entry index in classifier table for specified SF */ -static int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/) +static int SearchFreeClsid(struct bcm_mini_adapter *Adapter /**Adapter Context*/) { int i; @@ -99,7 +99,7 @@ static int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/) return MAX_CLASSIFIERS+1; } -static VOID deleteSFBySfid(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) +static VOID deleteSFBySfid(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIndex) { /* deleting all the packet held in the SF */ flush_queue(Adapter, uiSearchRuleIndex); @@ -120,7 +120,7 @@ CopyIpAddrToClassifier(struct bcm_classifier_rule *pstClassifierEntry, UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS; UCHAR *ptrClassifierIpAddress = NULL; UCHAR *ptrClassifierIpMask = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if (bIpVersion6) nSizeOfIPAddressInBytes = IPV6_ADDRESS_SIZEINBYTES; @@ -214,7 +214,7 @@ CopyIpAddrToClassifier(struct bcm_classifier_rule *pstClassifierEntry, } } -void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter, B_UINT16 TID, BOOLEAN bFreeAll) +void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, BOOLEAN bFreeAll) { int i; @@ -236,7 +236,7 @@ void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter, B_UINT16 TID, BOOLEAN bFreeAll) * @ingroup ctrl_pkt_functions * copy classifier rule into the specified SF index */ -static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSLTypes *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) +static inline VOID CopyClassifierRuleToSF(struct bcm_mini_adapter *Adapter, stConvergenceSLTypes *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) { struct bcm_classifier_rule *pstClassifierEntry = NULL; /* VOID *pvPhsContext = NULL; */ @@ -365,7 +365,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL /* * @ingroup ctrl_pkt_functions */ -static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex, UINT nClassifierIndex) +static inline VOID DeleteClassifierRuleFromSF(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIndex, UINT nClassifierIndex) { struct bcm_classifier_rule *pstClassifierEntry = NULL; B_UINT16 u16PacketClassificationRuleIndex; @@ -396,7 +396,7 @@ static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSear /* * @ingroup ctrl_pkt_functions */ -VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) +VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIndex) { struct bcm_classifier_rule *pstClassifierEntry = NULL; int i; @@ -428,7 +428,7 @@ VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) * related data into the Adapter structure. * @ingroup ctrl_pkt_functions */ -static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* "); @@ -1325,7 +1325,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " bValid: 0x%X", pstAddIndication->sfActiveSet.bValid); } -static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet, PUCHAR pucDestBuffer) +static inline ULONG RestoreSFParam(struct bcm_mini_adapter *Adapter, ULONG ulAddrSFParamSet, PUCHAR pucDestBuffer) { UINT nBytesToRead = sizeof(stServiceFlowParamSI); @@ -1342,7 +1342,7 @@ static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet return 1; } -static ULONG StoreSFParam(PMINI_ADAPTER Adapter, PUCHAR pucSrcBuffer, ULONG ulAddrSFParamSet) +static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer, ULONG ulAddrSFParamSet) { UINT nBytesToWrite = sizeof(stServiceFlowParamSI); int ret = 0; @@ -1358,7 +1358,7 @@ static ULONG StoreSFParam(PMINI_ADAPTER Adapter, PUCHAR pucSrcBuffer, ULONG ulAd return 1; } -ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter, PVOID pvBuffer, UINT *puBufferLength) +ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer, UINT *puBufferLength) { stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL; stLocalSFAddIndication *pstAddIndication = NULL; @@ -1473,7 +1473,7 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter, PVOID pvBuffer, UINT } static inline stLocalSFAddIndicationAlt -*RestoreCmControlResponseMessage(register PMINI_ADAPTER Adapter, register PVOID pvBuffer) +*RestoreCmControlResponseMessage(register struct bcm_mini_adapter *Adapter, register PVOID pvBuffer) { ULONG ulStatus = 0; stLocalSFAddIndication *pstAddIndication = NULL; @@ -1551,7 +1551,7 @@ failed_restore_sf_param: return NULL; } -ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) +ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter) { ULONG ulTargetDsxBuffersBase = 0; ULONG ulCntTargetBuffers; @@ -1598,7 +1598,7 @@ ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) return 1; } -static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid) +static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter, B_UINT16 tid) { ULONG ulTargetDSXBufferAddress; ULONG ulTargetDsxBufferIndexToUse, ulMaxTry; @@ -1632,7 +1632,7 @@ static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid) return ulTargetDSXBufferAddress; } -int AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) +int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter) { /* * Need to Allocate memory to contain the SUPER Large structures @@ -1645,7 +1645,7 @@ int AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) return 0; } -int FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) +int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter) { kfree(Adapter->caDsxReqResp); return 0; @@ -1657,7 +1657,7 @@ int FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) * for the Connection Management. * @return - Queue index for the free SFID else returns Invalid Index. */ -BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* pTarangs; pTarang; pTarang = pTarang->next) { diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c index 4adbf9dbf7b5..4745ddd62f5b 100644 --- a/drivers/staging/bcm/IPv6Protocol.c +++ b/drivers/staging/bcm/IPv6Protocol.c @@ -12,7 +12,7 @@ static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload, UCHAR *pucRetHeaderPtr = NULL; UCHAR *pucPayloadPtr = NULL; USHORT usNextHeaderOffset = 0 ; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if ((ppucPayload == NULL) || (*pusPayloadLength == 0) || (*bParseDone)) { @@ -147,7 +147,7 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort, BOOLEAN bDone = FALSE; UCHAR ucHeaderType = 0; UCHAR *pucNextHeader = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if (!pucPayload || (usPayloadLength == 0)) return 0; @@ -177,10 +177,10 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort, /* - * Arg 1 PMINI_ADAPTER Adapter is a pointer ot the driver contorl structure + * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver contorl structure * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet */ -USHORT IpVersion6(PMINI_ADAPTER Adapter, PVOID pcIpHeader, +USHORT IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader, struct bcm_classifier_rule *pstClassifierRule) { USHORT ushDestPort = 0; @@ -295,7 +295,7 @@ static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule UINT uiIpv6AddIndex = 0; UINT uiIpv6AddrNoLongWords = 4; ULONG aulSrcIP[4]; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); /* * This is the no. of Src Addresses ie Range of IP Addresses contained * in the classifier rule for which we need to match @@ -351,7 +351,7 @@ static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRul UINT uiIpv6AddIndex = 0; UINT uiIpv6AddrNoLongWords = 4; ULONG aulDestIP[4]; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); /* * This is the no. of Destination Addresses * ie Range of IP Addresses contained in the classifier rule @@ -406,7 +406,7 @@ VOID DumpIpv6Address(ULONG *puIpv6Address) { UINT uiIpv6AddrNoLongWords = 4; UINT uiIpv6AddIndex = 0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, ":%lx", puIpv6Address[uiIpv6AddIndex]); @@ -418,7 +418,7 @@ static VOID DumpIpv6Header(IPV6Header *pstIpv6Header) { UCHAR ucVersion; UCHAR ucPrio; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header---"); ucVersion = pstIpv6Header->ucVersionPrio & 0xf0; diff --git a/drivers/staging/bcm/IPv6ProtocolHdr.h b/drivers/staging/bcm/IPv6ProtocolHdr.h index 369b55316c79..8ba88a5b081c 100644 --- a/drivers/staging/bcm/IPv6ProtocolHdr.h +++ b/drivers/staging/bcm/IPv6ProtocolHdr.h @@ -102,7 +102,7 @@ typedef enum _E_IPADDR_CONTEXT //Function Prototypes -USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ +USHORT IpVersion6(struct bcm_mini_adapter *Adapter, /**< Pointer to the driver control structure */ PVOID pcIpHeader, /**psAdapter; */ + /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); if (!buff) @@ -132,7 +132,7 @@ exit: return Status; } -static int bcm_download_config_file(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo) +static int bcm_download_config_file(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo) { int retval = STATUS_SUCCESS; B_UINT32 value = 0; @@ -208,7 +208,7 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter, struct bcm_firmware_i static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len) { int retval = STATUS_SUCCESS; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if ((len-sizeof(unsigned int)) < 4) { if (memcmp(readbackbuff , buff, len)) retval = -EINVAL; @@ -229,7 +229,7 @@ static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char return retval; } -int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, struct bcm_firmware_info *psFwInfo) +int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo) { int retval = STATUS_SUCCESS; PUCHAR buff = NULL; @@ -278,7 +278,7 @@ error: return retval; } -static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) +static INT buffDnld(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) { unsigned int len = 0; int retval = STATUS_SUCCESS; @@ -299,7 +299,7 @@ static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Firmware return retval; } -static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) +static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) { UINT len = u32FirmwareLength; INT retval = STATUS_SUCCESS; @@ -334,7 +334,7 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi return retval; } -INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress) +INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress) { INT status = STATUS_SUCCESS; diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c index faeb03e62c06..4f2f490921e1 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.c +++ b/drivers/staging/bcm/InterfaceIdleMode.c @@ -7,7 +7,7 @@ Description: This is the hardware specific Function for waking up HW device fr A software abort pattern is written to the device to wake it and necessary power state transitions from host are performed here. -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context +Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful. @@ -22,7 +22,7 @@ Description: This is the hardware specific Function for responding to Idle mod Necessary power state transitions from host for idle mode or other device specific initializations are performed here. -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context +Input parameters: IN struct bcm_mini_adapter * Adapter - Miniport Adapter Context Return: BCM_STATUS_SUCCESS - If Idle mode response related HW configuration was successful. @@ -42,7 +42,7 @@ send to f/w with in 200 ms after the Idle/Shutdown req issued */ -int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) +int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int* puiBuffer) { int status = STATUS_SUCCESS; unsigned int uiRegRead = 0; @@ -147,7 +147,7 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) return status; } -static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) +static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int Pattern) { int status = STATUS_SUCCESS; unsigned int value; @@ -246,7 +246,7 @@ static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) } return status; } -int InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter) +int InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter) { ULONG Status = 0; if(Adapter->bTriedToWakeUpFromlowPowerMode) @@ -263,7 +263,7 @@ int InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter) return Status; } -void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter) +void InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter) { unsigned int uiRegVal = 0; INT Status = 0; diff --git a/drivers/staging/bcm/InterfaceIdleMode.h b/drivers/staging/bcm/InterfaceIdleMode.h index 859a2ffba6b7..c3338c8a1dc8 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.h +++ b/drivers/staging/bcm/InterfaceIdleMode.h @@ -1,14 +1,14 @@ #ifndef _INTERFACE_IDLEMODE_H #define _INTERFACE_IDLEMODE_H -INT InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter); +INT InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter); -INT InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int *puiBuffer); +INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int *puiBuffer); -VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter); +VOID InterfaceWriteIdleModeWakePattern(struct bcm_mini_adapter *Adapter); -INT InterfaceWakeUp(PMINI_ADAPTER Adapter); +INT InterfaceWakeUp(struct bcm_mini_adapter * Adapter); -VOID InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter); +VOID InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter); #endif diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c index 8e3c586a699c..8f85de6a57ba 100644 --- a/drivers/staging/bcm/InterfaceInit.c +++ b/drivers/staging/bcm/InterfaceInit.c @@ -65,7 +65,7 @@ static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) AdapterFree(psIntfAdapter->psAdapter); } -static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) +static void ConfigureEndPointTypesThroughEEPROM(struct bcm_mini_adapter *Adapter) { unsigned long ulReg = 0; int bytes; @@ -143,12 +143,12 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi { struct usb_device *udev = interface_to_usbdev(intf); int retval; - PMINI_ADAPTER psAdapter; + struct bcm_mini_adapter *psAdapter; PS_INTERFACE_ADAPTER psIntfAdapter; struct net_device *ndev; /* Reserve one extra queue for the bit-bucket */ - ndev = alloc_etherdev_mq(sizeof(MINI_ADAPTER), NO_OF_QUEUES+1); + ndev = alloc_etherdev_mq(sizeof(struct bcm_mini_adapter), NO_OF_QUEUES+1); if (ndev == NULL) { dev_err(&udev->dev, DRV_NAME ": no memory for device\n"); return -ENOMEM; @@ -257,7 +257,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi static void usbbcm_disconnect(struct usb_interface *intf) { PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); - PMINI_ADAPTER psAdapter; + struct bcm_mini_adapter *psAdapter; struct usb_device *udev = interface_to_usbdev(intf); if (psIntfAdapter == NULL) diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c index 67719d57256d..6ee3428daa55 100644 --- a/drivers/staging/bcm/InterfaceIsr.c +++ b/drivers/staging/bcm/InterfaceIsr.c @@ -5,7 +5,7 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) { int status = urb->status; PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context; - PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter ; + struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter ; if (netif_msg_intr(Adapter)) pr_info(PFX "%s: interrupt status %d\n", diff --git a/drivers/staging/bcm/InterfaceIsr.h b/drivers/staging/bcm/InterfaceIsr.h index 6065a7141bca..40399788c419 100644 --- a/drivers/staging/bcm/InterfaceIsr.h +++ b/drivers/staging/bcm/InterfaceIsr.h @@ -7,9 +7,9 @@ int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); -VOID InterfaceEnableInterrupt(PMINI_ADAPTER Adapter); +VOID InterfaceEnableInterrupt(struct bcm_mini_adapter *Adapter); -VOID InterfaceDisableInterrupt(PMINI_ADAPTER Adapter); +VOID InterfaceDisableInterrupt(struct bcm_mini_adapter *Adapter); #endif diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c index 2218faeaf8ac..bbe909946091 100644 --- a/drivers/staging/bcm/InterfaceMisc.c +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -133,7 +133,7 @@ INT BcmWRM(PVOID arg, return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); } -INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) +INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter) { PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); INT status = STATUS_SUCCESS; diff --git a/drivers/staging/bcm/InterfaceMisc.h b/drivers/staging/bcm/InterfaceMisc.h index 6c9e39bf9889..1dfabdc3aadd 100644 --- a/drivers/staging/bcm/InterfaceMisc.h +++ b/drivers/staging/bcm/InterfaceMisc.h @@ -33,7 +33,7 @@ int BcmWRM(PVOID arg, PVOID buff, INT len); -INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter); +INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter); VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter); diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c index 7940a2e7def2..8a9f90fbdf13 100644 --- a/drivers/staging/bcm/InterfaceRx.c +++ b/drivers/staging/bcm/InterfaceRx.c @@ -1,6 +1,6 @@ #include "headers.h" -static int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid) +static int SearchVcid(struct bcm_mini_adapter *Adapter,unsigned short usVcid) { int iIndex=0; @@ -45,7 +45,7 @@ static void read_bulk_callback(struct urb *urb) //int idleflag = 0 ; PUSB_RCB pRcb = (PUSB_RCB)urb->context; PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter; - PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; + struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; struct bcm_leader *pLeader = urb->transfer_buffer; if (unlikely(netif_msg_rx_status(Adapter))) @@ -232,7 +232,7 @@ Function: InterfaceRx Description: This is the hardware specific Function for Receiving data packet/control packets from the device. -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context +Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c index 3012f29cf85c..7e2b53be4d9e 100644 --- a/drivers/staging/bcm/InterfaceTx.c +++ b/drivers/staging/bcm/InterfaceTx.c @@ -6,9 +6,9 @@ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) PUSB_TCB pTcb= (PUSB_TCB)urb->context; PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter; struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer; - PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ; + struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter ; BOOLEAN bpowerDownMsg = FALSE ; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if (unlikely(netif_msg_tx_done(Adapter))) pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status); diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index a6584d7c28bd..6e8a3279698b 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -15,7 +15,7 @@ * Returns - None **********************************************************************/ -static VOID UpdateTokenCount(register PMINI_ADAPTER Adapter) +static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) { ULONG liCurrentTime; INT i = 0; @@ -75,7 +75,7 @@ static VOID UpdateTokenCount(register PMINI_ADAPTER Adapter) * Returns - The number of bytes allowed for transmission. * ***********************************************************************/ -static ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, struct bcm_packet_info *psSF) +static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); /* Validate the parameters */ @@ -112,7 +112,7 @@ static ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, struct bcm_packet_info *psSF This function despatches packet from the specified queue. @return Zero(success) or Negative value(failure) */ -static INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**dev); } -static int create_worker_threads(PMINI_ADAPTER psAdapter) +static int create_worker_threads(struct bcm_mini_adapter *psAdapter) { /* Rx Control Packets Processing */ psAdapter->control_packet_handler = kthread_run((int (*)(void *)) @@ -155,7 +155,7 @@ static int create_worker_threads(PMINI_ADAPTER psAdapter) return 0; } -static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path) +static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path) { struct file *flp = NULL; mm_segment_t oldfs; @@ -179,7 +179,7 @@ static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path) * Path to image file * Download Address on the chip */ -static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc) +static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc) { int errorno = 0; struct file *flp = NULL; @@ -231,7 +231,7 @@ exit_download: * Logical Adapter * Control Packet Buffer */ -INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) +INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) { struct bcm_leader *pLeader = NULL; INT Status = 0; @@ -414,7 +414,7 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) * * Returns - None. *****************************************************************/ -static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, struct bcm_link_request *pstStatisticsPtrRequest) +static VOID SendStatisticsPointerRequest(struct bcm_mini_adapter *Adapter, struct bcm_link_request *pstStatisticsPtrRequest) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; @@ -436,7 +436,7 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, struct bcm_link_ * * Returns - None. *******************************************************************/ -VOID LinkMessage(PMINI_ADAPTER Adapter) +VOID LinkMessage(struct bcm_mini_adapter *Adapter) { struct bcm_link_request *pstLinkRequest = NULL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); @@ -487,7 +487,7 @@ VOID LinkMessage(PMINI_ADAPTER Adapter) * * Returns - None. ************************************************************************/ -VOID StatisticsResponse(PMINI_ADAPTER Adapter, PVOID pvBuffer) +VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__); Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer); @@ -506,7 +506,7 @@ VOID StatisticsResponse(PMINI_ADAPTER Adapter, PVOID pvBuffer) * * Returns - None. ***********************************************************************/ -VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) +VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>"); @@ -580,7 +580,7 @@ VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) return; } -void SendIdleModeResponse(PMINI_ADAPTER Adapter) +void SendIdleModeResponse(struct bcm_mini_adapter *Adapter) { INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0; struct timeval tv; @@ -679,7 +679,7 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter) * * Returns - None. *******************************************************************/ -VOID DumpPackInfo(PMINI_ADAPTER Adapter) +VOID DumpPackInfo(struct bcm_mini_adapter *Adapter) { UINT uiLoopIndex = 0; UINT uiIndex = 0; @@ -808,10 +808,10 @@ VOID DumpPackInfo(PMINI_ADAPTER Adapter) return; } -int reset_card_proc(PMINI_ADAPTER ps_adapter) +int reset_card_proc(struct bcm_mini_adapter *ps_adapter) { int retval = STATUS_SUCCESS; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); PS_INTERFACE_ADAPTER psIntfAdapter = NULL; unsigned int value = 0, uiResetValue = 0; int bytes; @@ -926,7 +926,7 @@ err_exit: return retval; } -int run_card_proc(PMINI_ADAPTER ps_adapter) +int run_card_proc(struct bcm_mini_adapter *ps_adapter) { int status = STATUS_SUCCESS; int bytes; @@ -953,7 +953,7 @@ int run_card_proc(PMINI_ADAPTER ps_adapter) return status; } -int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) +int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter) { int status; UINT value = 0; @@ -1077,7 +1077,7 @@ OUT: return status; } -static int bcm_parse_target_params(PMINI_ADAPTER Adapter) +static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter) { struct file *flp = NULL; mm_segment_t oldfs = {0}; @@ -1128,7 +1128,7 @@ static int bcm_parse_target_params(PMINI_ADAPTER Adapter) return STATUS_SUCCESS; } -void beceem_parse_target_struct(PMINI_ADAPTER Adapter) +void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter) { UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0; @@ -1186,7 +1186,7 @@ void beceem_parse_target_struct(PMINI_ADAPTER Adapter) doPowerAutoCorrection(Adapter); } -static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) +static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter) { UINT reporting_mode; @@ -1218,7 +1218,7 @@ static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) } #if 0 -static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) +static unsigned char *ReadMacAddrEEPROM(struct bcm_mini_adapter *Adapter, ulong dwAddress) { int status = 0, i = 0; unsigned int temp = 0; @@ -1272,13 +1272,13 @@ static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) #define CACHE_ADDRESS_MASK 0x80000000 #define UNCACHE_ADDRESS_MASK 0xa0000000 -int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) +int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { return Adapter->interface_rdm(Adapter->pvInterfaceAdapter, uiAddress, pucBuff, sSize); } -int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) +int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { int iRetVal; @@ -1287,13 +1287,13 @@ int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) return iRetVal; } -int wrmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +int wrmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size) { convertEndian(RWM_WRITE, pucBuff, size); return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size); } -int rdmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +int rdmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size) { INT uiRetVal = 0; @@ -1303,7 +1303,7 @@ int rdmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) return uiRetVal; } -int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) +int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { INT status = STATUS_SUCCESS; down(&Adapter->rdmwrmsync); @@ -1322,7 +1322,7 @@ exit: return status; } -int wrmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +int wrmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size) { int iRetVal = STATUS_SUCCESS; @@ -1342,7 +1342,7 @@ exit: return iRetVal; } -int rdmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +int rdmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size) { INT uiRetVal = STATUS_SUCCESS; @@ -1361,7 +1361,7 @@ exit: return uiRetVal; } -static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) +static VOID HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter) { int clear_abort_pattern = 0, Status = 0; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); @@ -1390,7 +1390,7 @@ static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); } -static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) +static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter) { struct bcm_link_request stShutdownResponse; UINT NVMAccess = 0, lowPwrAbortMsg = 0; @@ -1474,7 +1474,7 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) } } -static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) +static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer) { B_UINT32 uiResetValue = 0; @@ -1503,7 +1503,7 @@ static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) return; } -VOID ResetCounters(PMINI_ADAPTER Adapter) +VOID ResetCounters(struct bcm_mini_adapter *Adapter) { beceem_protocol_reset(Adapter); Adapter->CurrNumRecvDescs = 0; @@ -1519,7 +1519,7 @@ VOID ResetCounters(PMINI_ADAPTER Adapter) Adapter->bShutStatus = FALSE; } -struct bcm_classifier_rule *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP) +struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP) { UINT uiIndex = 0; for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { @@ -1533,7 +1533,7 @@ struct bcm_classifier_rule *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIp return NULL; } -void AddFragIPClsEntry(PMINI_ADAPTER Adapter, struct bcm_fragmented_packet_info *psFragPktInfo) +void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo) { UINT uiIndex = 0; for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { @@ -1544,7 +1544,7 @@ void AddFragIPClsEntry(PMINI_ADAPTER Adapter, struct bcm_fragmented_packet_info } } -void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIp) +void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp) { UINT uiIndex = 0; for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { @@ -1556,7 +1556,7 @@ void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG S } } -void update_per_cid_rx(PMINI_ADAPTER Adapter) +void update_per_cid_rx(struct bcm_mini_adapter *Adapter) { UINT qindex = 0; @@ -1580,7 +1580,7 @@ void update_per_cid_rx(PMINI_ADAPTER Adapter) Adapter->liDrainCalculated = jiffies; } -void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter) +void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter) { INT iIndex = 0; u32 uibuff[MAX_TARGET_DSX_BUFFERS]; @@ -1606,7 +1606,7 @@ void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter) atomic_set(&Adapter->uiMBupdate, FALSE); } -void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) +void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex) { struct sk_buff *PacketToDrop = NULL; struct net_device_stats *netstats = &Adapter->dev->stats; @@ -1630,7 +1630,7 @@ void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); } -static void beceem_protocol_reset(PMINI_ADAPTER Adapter) +static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter) { int i; if (netif_msg_link(Adapter)) diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c index 4aa2b71a40eb..a6e61510d278 100644 --- a/drivers/staging/bcm/PHSModule.c +++ b/drivers/staging/bcm/PHSModule.c @@ -58,7 +58,7 @@ Description: This routine handle PHS(Payload Header Suppression for Tx path. The header data after supression is copied back to the NDIS_PACKET. -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context +Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context IN Packet - NDIS packet containing data to be transmitted IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to identify PHS rule to be applied. @@ -69,7 +69,7 @@ Return: STATUS_SUCCESS - If the send was successful. Other - If an error occured. */ -int PHSTransmit(PMINI_ADAPTER Adapter, +int PHSTransmit(struct bcm_mini_adapter *Adapter, struct sk_buff **pPacket, USHORT Vcid, B_UINT16 uiClassifierRuleID, @@ -209,7 +209,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter, return STATUS_SUCCESS; } -int PHSReceive(PMINI_ADAPTER Adapter, +int PHSReceive(struct bcm_mini_adapter *Adapter, USHORT usVcid, struct sk_buff *packet, UINT *punPacketLen, @@ -273,7 +273,7 @@ int PHSReceive(PMINI_ADAPTER Adapter, void DumpFullPacket(UCHAR *pBuf,UINT nPktLen) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet"); BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen); } @@ -291,7 +291,7 @@ void DumpFullPacket(UCHAR *pBuf,UINT nPktLen) // TRUE(1) -If allocation of memory was success full. // FALSE -If allocation of memory fails. //----------------------------------------------------------------------------- -int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) +int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension, struct bcm_mini_adapter *Adapter) { int i; S_SERVICEFLOW_TABLE *pstServiceFlowTable; @@ -398,7 +398,7 @@ ULONG PhsUpdateClassifierRule(IN void* pvContext, ULONG lStatus =0; UINT nSFIndex =0 ; S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); @@ -462,7 +462,7 @@ ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI) UINT nSFIndex =0, nClsidIndex =0 ; S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; @@ -528,7 +528,7 @@ ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 UINT nSFIndex =0, nClsidIndex =0 ; S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; if(pDeviceExtension) @@ -592,7 +592,7 @@ ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid) UINT nSFIndex =0, nClsidIndex =0 ; S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n"); @@ -684,7 +684,7 @@ ULONG PhsCompress(IN void* pvContext, S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; S_PHS_RULE *pstPhsRule = NULL; ULONG lStatus =0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); @@ -778,7 +778,7 @@ ULONG PhsDeCompress(IN void* pvContext, S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_PHS_RULE *pstPhsRule = NULL; UINT phsi; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; @@ -847,7 +847,7 @@ ULONG PhsDeCompress(IN void* pvContext, static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) { int i,j; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n"); if(psServiceFlowRulesTable) @@ -1057,7 +1057,7 @@ UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, UINT uiStatus =PHS_SUCCESS; UINT nClassifierIndex = 0; S_CLASSIFIER_TABLE *psaClassifiertable = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); psaClassifiertable = pstServiceFlowEntry->pstClassifierTable; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>"); @@ -1148,7 +1148,7 @@ static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, BOOLEAN bFreeEntryFound = FALSE; S_CLASSIFIER_ENTRY *psClassifierRules = NULL; UINT nStatus = PHS_SUCCESS; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule"); if(psaClassifiertable == NULL) { @@ -1259,7 +1259,7 @@ static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, S_PHS_RULE *pstAddPhsRule = NULL; UINT nPhsRuleIndex = 0; BOOLEAN bPHSRuleOrphaned = FALSE; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); psPhsRule->u8RefCnt =0; /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/ @@ -1334,7 +1334,7 @@ static BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifi void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension) { int i,j,k,l; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n"); for(i=0;i\n"); *header_size = 0; @@ -1495,7 +1495,7 @@ static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf { unsigned char *old_addr = out_buf; int supress = 0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(phs_rule == NULL) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!"); @@ -1557,7 +1557,7 @@ static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buff { unsigned int size=0; int bit,i=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm); diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h index c629585d0a8c..b5f21157ac47 100644 --- a/drivers/staging/bcm/PHSModule.h +++ b/drivers/staging/bcm/PHSModule.h @@ -1,7 +1,7 @@ #ifndef BCM_MINIPORT_PHSMODULE_H #define BCM_MINIPORT_PHSMODULE_H -int PHSTransmit(PMINI_ADAPTER Adapter, +int PHSTransmit(struct bcm_mini_adapter *Adapter, struct sk_buff **pPacket, USHORT Vcid, B_UINT16 uiClassifierRuleID, @@ -9,7 +9,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter, PUINT PacketLen, UCHAR bEthCSSupport); -int PHSReceive(PMINI_ADAPTER Adapter, +int PHSReceive(struct bcm_mini_adapter *Adapter, USHORT usVcid, struct sk_buff *packet, UINT *punPacketLen, @@ -25,7 +25,7 @@ void DumpFullPacket(UCHAR *pBuf,UINT nPktLen); void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension); -int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter); +int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,struct bcm_mini_adapter *Adapter); int PhsCleanup(PPHS_DEVICE_EXTENSION pPHSDeviceExt); diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h index 42a04b95909d..3c8cc5ba2e2e 100644 --- a/drivers/staging/bcm/Prototypes.h +++ b/drivers/staging/bcm/Prototypes.h @@ -1,172 +1,172 @@ #ifndef _PROTOTYPES_H_ #define _PROTOTYPES_H_ -VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer); +VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer); -VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer); +VOID StatisticsResponse(struct bcm_mini_adapter *Adapter,PVOID pvBuffer); -VOID IdleModeResponse(PMINI_ADAPTER Adapter,PUINT puiBuffer); +VOID IdleModeResponse(struct bcm_mini_adapter *Adapter,PUINT puiBuffer); -int control_packet_handler (PMINI_ADAPTER Adapter); +int control_packet_handler (struct bcm_mini_adapter *Adapter); -VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter,UINT uiSearchRuleIndex); +VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter,UINT uiSearchRuleIndex); -VOID flush_all_queues(PMINI_ADAPTER Adapter); +VOID flush_all_queues(struct bcm_mini_adapter *Adapter); -int register_control_device_interface(PMINI_ADAPTER ps_adapter); +int register_control_device_interface(struct bcm_mini_adapter *ps_adapter); -void unregister_control_device_interface(PMINI_ADAPTER Adapter); +void unregister_control_device_interface(struct bcm_mini_adapter *Adapter); -INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**ucIPSourceAddressLength) @@ -61,7 +61,7 @@ BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ul BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulDestIP) { UCHAR ucLoopIndex=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); ulDestIP=ntohl(ulDestIP); if(0 == pstClassifierRule->ucIPDestinationAddressLength) @@ -94,7 +94,7 @@ BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG u BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfService) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if( 3 != pstClassifierRule->ucIPTypeOfServiceLength ) return TRUE; @@ -120,7 +120,7 @@ BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfSer BOOLEAN MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol) { UCHAR ucLoopIndex=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(0 == pstClassifierRule->ucProtocolLength) return TRUE; for(ucLoopIndex=0;ucLoopIndexucProtocolLength;ucLoopIndex++) @@ -150,7 +150,7 @@ BOOLEAN MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrc { UCHAR ucLoopIndex=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(0 == pstClassifierRule->ucSrcPortRangeLength) @@ -181,7 +181,7 @@ BOOLEAN MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrc BOOLEAN MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDestPort) { UCHAR ucLoopIndex=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(0 == pstClassifierRule->ucDestPortRangeLength) return TRUE; @@ -204,7 +204,7 @@ BOOLEAN MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDe Compares IPV4 Ip address and port number @return Queue Index. */ -static USHORT IpVersion4(PMINI_ADAPTER Adapter, +static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd, struct bcm_classifier_rule *pstClassifierRule) { @@ -302,7 +302,7 @@ static USHORT IpVersion4(PMINI_ADAPTER Adapter, return bClassificationSucceed; } -VOID PruneQueueAllSF(PMINI_ADAPTER Adapter) +VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter) { UINT iIndex = 0; @@ -323,7 +323,7 @@ is less than number of bytes in the queue. If so - drops packets from the Head till the number of bytes is less than or equal to max queue size for the queue. */ -static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex) +static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) { struct sk_buff* PacketToDrop=NULL; struct net_device_stats *netstats; @@ -392,7 +392,7 @@ static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<====="); } -VOID flush_all_queues(PMINI_ADAPTER Adapter) +VOID flush_all_queues(struct bcm_mini_adapter *Adapter) { INT iQIndex; UINT uiTotalPacketLength; @@ -442,7 +442,7 @@ VOID flush_all_queues(PMINI_ADAPTER Adapter) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<====="); } -USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) +USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) { INT uiLoopIndex=0; struct bcm_classifier_rule *pstClassifierRule = NULL; @@ -652,7 +652,7 @@ USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac) { UINT i=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(pstClassifierRule->ucEthCSSrcMACLen==0) return TRUE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); @@ -669,7 +669,7 @@ static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifier static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac) { UINT i=0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(pstClassifierRule->ucEthCSDestMACLen==0) return TRUE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); @@ -685,7 +685,7 @@ static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifie static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if((pstClassifierRule->ucEtherTypeLen==0)|| (pstClassifierRule->au8EthCSEtherType[0] == 0)) return TRUE; @@ -723,7 +723,7 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule BOOLEAN bClassificationSucceed = FALSE; USHORT usVLANID; B_UINT8 uPriority = 0; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID); @@ -768,7 +768,7 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule } -static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, +static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb, PS_ETHCS_PKT_INFO pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport) @@ -801,7 +801,7 @@ static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, return bClassificationSucceed; } -static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload, +static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, PS_ETHCS_PKT_INFO pstEthCsPktInfo) { USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype); diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c index 63c6a74bb1ff..5e603ce76fea 100644 --- a/drivers/staging/bcm/Transmit.c +++ b/drivers/staging/bcm/Transmit.c @@ -41,7 +41,7 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53 This function dispatches control packet to the h/w interface @return zero(success) or -ve value(failure) */ -INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket) +INT SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket) { struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket; @@ -84,7 +84,7 @@ This function despatches the IP packets with the given vcid to the target via the host h/w interface. @return zero(success) or -ve value(failure) */ -INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid) +INT SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid) { int status=0; BOOLEAN bHeaderSupressionEnabled = FALSE; @@ -180,7 +180,7 @@ errExit: return status; } -static int tx_pending(PMINI_ADAPTER Adapter) +static int tx_pending(struct bcm_mini_adapter *Adapter) { return (atomic_read(&Adapter->TxPktAvail) && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc)) @@ -191,7 +191,7 @@ static int tx_pending(PMINI_ADAPTER Adapter) @ingroup tx_functions Transmit thread */ -int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ +int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/ ) { int status = 0; diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c index 27ddcbfd5935..08d13a4dfd70 100644 --- a/drivers/staging/bcm/hostmibs.c +++ b/drivers/staging/bcm/hostmibs.c @@ -9,7 +9,7 @@ #include "headers.h" -INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) +INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) { S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_PHS_RULE *pstPhsRule = NULL; @@ -101,7 +101,7 @@ VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, struct bcm_t sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); } -VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) +VOID CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) { S_MIBS_EXTSERVICEFLOW_PARAMETERS *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable; diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c index c7f488629722..252a1b31d618 100644 --- a/drivers/staging/bcm/led_control.c +++ b/drivers/staging/bcm/led_control.c @@ -13,7 +13,7 @@ static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size) return u16CheckSum; } -BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios) +BOOLEAN IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios) { INT Status; Status = (Adapter->gpioBitMap & gpios) ^ gpios; @@ -23,7 +23,7 @@ BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios) return TRUE; } -static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, +static INT LED_Blink(struct bcm_mini_adapter *Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate) { int Status = STATUS_SUCCESS; @@ -95,7 +95,7 @@ static INT ScaleRateofTransfer(ULONG rate) -static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx, +static INT LED_Proportional_Blink(struct bcm_mini_adapter *Adapter, UCHAR GPIO_Num_tx, UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate) { @@ -261,7 +261,7 @@ static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx, * * ----------------------------------------------------------------------------- */ -static INT ValidateDSDParamsChecksum(PMINI_ADAPTER Adapter, ULONG ulParamOffset, +static INT ValidateDSDParamsChecksum(struct bcm_mini_adapter *Adapter, ULONG ulParamOffset, USHORT usParamLen) { INT Status = STATUS_SUCCESS; @@ -347,7 +347,7 @@ exit: * * ----------------------------------------------------------------------------- */ -static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset) +static INT ValidateHWParmStructure(struct bcm_mini_adapter *Adapter, ULONG ulHwParamOffset) { INT Status = STATUS_SUCCESS; @@ -371,7 +371,7 @@ static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset) return Status; } /* ValidateHWParmStructure() */ -static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, +static int ReadLEDInformationFromEEPROM(struct bcm_mini_adapter *Adapter, UCHAR GPIO_Array[]) { int Status = STATUS_SUCCESS; @@ -477,7 +477,7 @@ static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, } -static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, +static int ReadConfigFileStructure(struct bcm_mini_adapter *Adapter, BOOLEAN *bEnableThread) { int Status = STATUS_SUCCESS; @@ -580,7 +580,7 @@ static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, * * ----------------------------------------------------------------------------- */ -static VOID LedGpioInit(PMINI_ADAPTER Adapter) +static VOID LedGpioInit(struct bcm_mini_adapter *Adapter) { UINT uiResetValue = 0; UINT uiIndex = 0; @@ -605,7 +605,7 @@ static VOID LedGpioInit(PMINI_ADAPTER Adapter) Adapter->LEDInfo.bIdle_led_off = FALSE; } -static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, +static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex, LedEventInfo_t currdriverstate) { @@ -645,7 +645,7 @@ static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, } return STATUS_SUCCESS; } -static VOID LEDControlThread(PMINI_ADAPTER Adapter) +static VOID LEDControlThread(struct bcm_mini_adapter *Adapter) { UINT uiIndex = 0; UCHAR GPIO_num = 0; @@ -857,7 +857,7 @@ static VOID LEDControlThread(PMINI_ADAPTER Adapter) Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED; } -int InitLedSettings(PMINI_ADAPTER Adapter) +int InitLedSettings(struct bcm_mini_adapter *Adapter) { int Status = STATUS_SUCCESS; BOOLEAN bEnableThread = TRUE; diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index 7d703cb3c5e0..f16d3bb54c3c 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -2,54 +2,54 @@ #define DWORD unsigned int -static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset); -static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter); -static INT BcmGetActiveISO(PMINI_ADAPTER Adapter); -static UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter); -static INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter); -static UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize); - -static VOID BcmValidateNvmType(PMINI_ADAPTER Adapter); -static INT BcmGetNvmSize(PMINI_ADAPTER Adapter); -static UINT BcmGetFlashSize(PMINI_ADAPTER Adapter); -static NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter); - -static INT BcmGetSectionValEndOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); - -static B_UINT8 IsOffsetWritable(PMINI_ADAPTER Adapter, UINT uiOffset); -static INT IsSectionWritable(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL Section); -static INT IsSectionExistInVendorInfo(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section); - -static INT ReadDSDPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd); -static INT ReadDSDSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd); -static INT ReadISOPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso); -static INT ReadISOSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso); - -static INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); -static INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); -static INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiSectAlignAddr); -static INT WriteToFlashWithoutSectorErase(PMINI_ADAPTER Adapter, PUINT pBuff, +static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset); +static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter); +static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter); +static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter); +static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter); +static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize); + +static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter); +static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter); +static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter); +static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter); + +static INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); + +static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset); +static INT IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section); +static INT IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section); + +static INT ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd); +static INT ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd); +static INT ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso); +static INT ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso); + +static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); +static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); +static INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiSectAlignAddr); +static INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff, FLASH2X_SECTION_VAL eFlash2xSectionVal, UINT uiOffset, UINT uiNumBytes); -static FLASH2X_SECTION_VAL getHighestPriDSD(PMINI_ADAPTER Adapter); -static FLASH2X_SECTION_VAL getHighestPriISO(PMINI_ADAPTER Adapter); +static FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter); +static FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter); static INT BeceemFlashBulkRead( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes); static INT BeceemFlashBulkWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes, BOOLEAN bVerify); -static INT GetFlashBaseAddr(PMINI_ADAPTER Adapter); +static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter); -static INT ReadBeceemEEPROMBulk(PMINI_ADAPTER Adapter,UINT dwAddress, UINT *pdwData, UINT dwNumData); +static INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter,UINT dwAddress, UINT *pdwData, UINT dwNumData); // Procedure: ReadEEPROMStatusRegister // @@ -62,7 +62,7 @@ static INT ReadBeceemEEPROMBulk(PMINI_ADAPTER Adapter,UINT dwAddress, UINT *pdwD // //----------------------------------------------------------------------------- -static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) +static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter ) { UCHAR uiData = 0; DWORD dwRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; @@ -128,7 +128,7 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) // OSAL_STATUS_CODE: //----------------------------------------------------------------------------- -INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, +INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, DWORD dwAddress, DWORD *pdwData, DWORD dwNumWords @@ -255,7 +255,7 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, // OSAL_STATUS_CODE: //----------------------------------------------------------------------------- -INT ReadBeceemEEPROM( PMINI_ADAPTER Adapter, +INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, DWORD uiOffset, DWORD *pBuffer ) @@ -285,7 +285,7 @@ INT ReadBeceemEEPROM( PMINI_ADAPTER Adapter, -INT ReadMacAddressFromNVM(PMINI_ADAPTER Adapter) +INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) { INT Status; unsigned char puMacAddr[6]; @@ -318,7 +318,7 @@ INT ReadMacAddressFromNVM(PMINI_ADAPTER Adapter) //----------------------------------------------------------------------------- INT BeceemEEPROMBulkRead( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes) @@ -436,7 +436,7 @@ INT BeceemEEPROMBulkRead( //----------------------------------------------------------------------------- static INT BeceemFlashBulkRead( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes) @@ -518,7 +518,7 @@ static INT BeceemFlashBulkRead( // //----------------------------------------------------------------------------- -static UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) +static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter) { if(IsFlash2x(Adapter)) return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); @@ -541,7 +541,7 @@ static UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -static UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) +static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) { UINT uiData = 0; UINT uiIndex = 0; @@ -607,7 +607,7 @@ static UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) //----------------------------------------------------------------------------- -static INT FlashSectorErase(PMINI_ADAPTER Adapter, +static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, UINT addr, UINT numOfSectors) { @@ -672,7 +672,7 @@ static INT FlashSectorErase(PMINI_ADAPTER Adapter, //----------------------------------------------------------------------------- static INT flashByteWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { @@ -762,7 +762,7 @@ static INT flashByteWrite( //----------------------------------------------------------------------------- static INT flashWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) @@ -848,7 +848,7 @@ static INT flashWrite( // //----------------------------------------------------------------------------- static INT flashByteWriteStatus( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { @@ -935,7 +935,7 @@ static INT flashByteWriteStatus( //----------------------------------------------------------------------------- static INT flashWriteStatus( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { @@ -1014,7 +1014,7 @@ static INT flashWriteStatus( // //----------------------------------------------------------------------------- -static VOID BcmRestoreBlockProtectStatus(PMINI_ADAPTER Adapter,ULONG ulWriteStatus) +static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter,ULONG ulWriteStatus) { UINT value; value = (FLASH_CMD_WRITE_ENABLE<< 24); @@ -1037,7 +1037,7 @@ static VOID BcmRestoreBlockProtectStatus(PMINI_ADAPTER Adapter,ULONG ulWriteStat // ULONG - Status value before UnProtect. // //----------------------------------------------------------------------------- -static ULONG BcmFlashUnProtectBlock(PMINI_ADAPTER Adapter,UINT uiOffset, UINT uiLength) +static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter,UINT uiOffset, UINT uiLength) { ULONG ulStatus = 0; ULONG ulWriteStatus = 0; @@ -1146,7 +1146,7 @@ static ULONG BcmFlashUnProtectBlock(PMINI_ADAPTER Adapter,UINT uiOffset, UINT ui //----------------------------------------------------------------------------- static INT BeceemFlashBulkWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes, @@ -1365,7 +1365,7 @@ BeceemFlashBulkWrite_EXIT: //----------------------------------------------------------------------------- static INT BeceemFlashBulkWriteStatus( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes, @@ -1545,7 +1545,7 @@ BeceemFlashBulkWriteStatus_EXIT: //----------------------------------------------------------------------------- -INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) +INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) { PCHAR pBuff = kmalloc(BUFFER_4K, GFP_KERNEL); UINT uiEepromSize = 0; @@ -1614,7 +1614,7 @@ INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter) +INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) { PCHAR pBuff, pPtr; UINT uiEepromSize = 0; @@ -1699,7 +1699,7 @@ INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter) //----------------------------------------------------------------------------- static INT BeceemEEPROMReadBackandVerify( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes) @@ -1798,7 +1798,7 @@ static VOID BcmSwapWord(UINT *ptr1) { // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -static INT BeceemEEPROMWritePage( PMINI_ADAPTER Adapter, UINT uiData[], UINT uiOffset ) +static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[], UINT uiOffset ) { UINT uiRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; UINT uiStatus = 0; @@ -1934,7 +1934,7 @@ static INT BeceemEEPROMWritePage( PMINI_ADAPTER Adapter, UINT uiData[], UINT uiO //----------------------------------------------------------------------------- INT BeceemEEPROMBulkWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUCHAR pBuffer, UINT uiOffset, UINT uiNumBytes, @@ -2036,7 +2036,7 @@ INT BeceemEEPROMBulkWrite( //----------------------------------------------------------------------------- INT BeceemNVMRead( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes) @@ -2099,7 +2099,7 @@ INT BeceemNVMRead( //----------------------------------------------------------------------------- INT BeceemNVMWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, UINT uiOffset, UINT uiNumBytes, @@ -2233,7 +2233,7 @@ INT BeceemNVMWrite( // - if failed. //----------------------------------------------------------------------------- -INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize) +INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize) { INT Status = -1; FLASH_CS_INFO sFlashCsInfo = {0}; @@ -2308,7 +2308,7 @@ INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize) // //----------------------------------------------------------------------------- -static UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) +static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) { UINT uiSectorSize = 0; UINT uiSectorSig = 0; @@ -2377,7 +2377,7 @@ static UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig // //----------------------------------------------------------------------------- -static INT BcmInitEEPROMQueues(PMINI_ADAPTER Adapter) +static INT BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter) { UINT value = 0; /* CHIP Bug : Clear the Avail bits on the Read queue. The default @@ -2413,7 +2413,7 @@ static INT BcmInitEEPROMQueues(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -INT BcmInitNVM(PMINI_ADAPTER ps_adapter) +INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) { BcmValidateNvmType(ps_adapter); BcmInitEEPROMQueues(ps_adapter); @@ -2445,7 +2445,7 @@ INT BcmInitNVM(PMINI_ADAPTER ps_adapter) */ /***************************************************************************/ -static INT BcmGetNvmSize(PMINI_ADAPTER Adapter) +static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) { if(Adapter->eNVMType == NVM_EEPROM) { @@ -2469,7 +2469,7 @@ static INT BcmGetNvmSize(PMINI_ADAPTER Adapter) // Returns: // //----------------------------------------------------------------------------- -static VOID BcmValidateNvmType(PMINI_ADAPTER Adapter) +static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) { // @@ -2495,7 +2495,7 @@ static VOID BcmValidateNvmType(PMINI_ADAPTER Adapter) // Returns: // Flash ID //----------------------------------------------------------------------------- -static ULONG BcmReadFlashRDID(PMINI_ADAPTER Adapter) +static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) { ULONG ulRDID = 0; UINT value; @@ -2518,7 +2518,7 @@ static ULONG BcmReadFlashRDID(PMINI_ADAPTER Adapter) } -INT BcmAllocFlashCSStructure(PMINI_ADAPTER psAdapter) +INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { if(psAdapter == NULL) { @@ -2552,7 +2552,7 @@ INT BcmAllocFlashCSStructure(PMINI_ADAPTER psAdapter) return STATUS_SUCCESS; } -INT BcmDeAllocFlashCSStructure(PMINI_ADAPTER psAdapter) +INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { if(psAdapter == NULL) { @@ -2565,7 +2565,7 @@ INT BcmDeAllocFlashCSStructure(PMINI_ADAPTER psAdapter) return STATUS_SUCCESS ; } -static INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo,PMINI_ADAPTER Adapter) +static INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo,struct bcm_mini_adapter *Adapter) { UINT Index = 0; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************"); @@ -2715,14 +2715,14 @@ static INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) return STATUS_SUCCESS; } -static INT IsSectionExistInVendorInfo(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) +static INT IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section) { return ( Adapter->uiVendorExtnFlag && (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS) ); } -static VOID UpdateVendorInfo(PMINI_ADAPTER Adapter) +static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) { B_UINT32 i = 0; UINT uiSizeSection = 0; @@ -2813,7 +2813,7 @@ static VOID UpdateVendorInfo(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -static INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) +static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) { //FLASH_CS_INFO sFlashCsInfo = {0}; @@ -2960,7 +2960,7 @@ static INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -static NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter) +static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) { UINT uiData = 0; @@ -3004,7 +3004,7 @@ static NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter) * On Failure -returns STATUS_FAILURE **/ -INT BcmGetSectionValStartOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) +INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { /* * Considering all the section for which end offset can be calculated or directly given @@ -3098,7 +3098,7 @@ INT BcmGetSectionValStartOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlas * On Failure -returns STATUS_FAILURE **/ -INT BcmGetSectionValEndOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { INT SectEndOffset = 0 ; SectEndOffset = INVALID_OFFSET; @@ -3188,7 +3188,7 @@ INT BcmGetSectionValEndOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2 */ INT BcmFlash2xBulkRead( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, FLASH2X_SECTION_VAL eFlash2xSectionVal, UINT uiOffsetWithinSectionVal, @@ -3257,7 +3257,7 @@ INT BcmFlash2xBulkRead( */ INT BcmFlash2xBulkWrite( - PMINI_ADAPTER Adapter, + struct bcm_mini_adapter *Adapter, PUINT pBuffer, FLASH2X_SECTION_VAL eFlash2xSectVal, UINT uiOffset, @@ -3322,7 +3322,7 @@ INT BcmFlash2xBulkWrite( * Return STATUS_SUCESS if get success in setting the right DSD else negaive error code * **/ -static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) +static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) { FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; @@ -3371,7 +3371,7 @@ static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) * **/ -static INT BcmGetActiveISO(PMINI_ADAPTER Adapter) +static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter) { INT HighestPriISO = 0 ; @@ -3399,7 +3399,7 @@ static INT BcmGetActiveISO(PMINI_ADAPTER Adapter) * Failure:-FALSE, offset is RO * **/ -B_UINT8 IsOffsetWritable(PMINI_ADAPTER Adapter, UINT uiOffset) +B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset) { UINT uiSectorNum = 0; UINT uiWordOfSectorPermission =0; @@ -3424,7 +3424,7 @@ B_UINT8 IsOffsetWritable(PMINI_ADAPTER Adapter, UINT uiOffset) static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) { - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************"); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2); @@ -3456,7 +3456,7 @@ static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) * Failure:- negative error code **/ -INT BcmGetFlash2xSectionalBitMap(PMINI_ADAPTER Adapter, PFLASH2X_BITMAP psFlash2xBitMap) +INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITMAP psFlash2xBitMap) { @@ -3752,7 +3752,7 @@ BcmSetActiveSection :- Set Active section is used to make priority field highest Return Value:- Make the priorit highest else return erorr code **/ -INT BcmSetActiveSection(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal) +INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal) { unsigned int SectImagePriority = 0; INT Status =STATUS_SUCCESS; @@ -3958,7 +3958,7 @@ BcmCopyISO - Used only for copying the ISO section Return value:- SUCCESS if copies successfully else negative error code **/ -INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) +INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut) { PCHAR Buff = NULL; @@ -4289,7 +4289,7 @@ Return Value :- **/ -INT BcmFlash2xCorruptSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { INT Status = STATUS_SUCCESS ; @@ -4321,7 +4321,7 @@ Return Value :- Failure :-Return negative error code **/ -INT BcmFlash2xWriteSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) +INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { UINT uiSignature = 0 ; @@ -4394,7 +4394,7 @@ Return values:-Return TRUE is request is valid else FALSE. **/ -INT validateFlash2xReadWrite(PMINI_ADAPTER Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) +INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) { UINT uiNumOfBytes = 0 ; UINT uiSectStartOffset = 0 ; @@ -4459,7 +4459,7 @@ Return value:- return TRUE if flah2.x of hgher version else return false. **/ -INT IsFlash2x(PMINI_ADAPTER Adapter) +INT IsFlash2x(struct bcm_mini_adapter *Adapter) { if(Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER) return TRUE ; @@ -4474,7 +4474,7 @@ Return Value:- Success :- Base Address of the Flash **/ -static INT GetFlashBaseAddr(PMINI_ADAPTER Adapter) +static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) { UINT uiBaseAddr = 0; @@ -4525,7 +4525,7 @@ Return Values- **/ -INT BcmCopySection(PMINI_ADAPTER Adapter, +INT BcmCopySection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL SrcSection, FLASH2X_SECTION_VAL DstSection, UINT offset, @@ -4642,7 +4642,7 @@ Return value :- **/ -INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) +INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiOffset) { UINT offsetToProtect = 0,HeaderSizeToProtect =0; BOOLEAN bHasHeader = FALSE ; @@ -4715,7 +4715,7 @@ BcmDoChipSelect : This will selcet the appropriate chip for writing. OutPut:- Select the Appropriate chip and retrn status Success **/ -static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) +static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) { UINT FlashConfig = 0; INT ChipNum = 0; @@ -4791,7 +4791,7 @@ static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) return STATUS_SUCCESS; } -INT ReadDSDSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd) +INT ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd) { UINT uiDSDsig = 0; //UINT sigoffsetInMap = 0; @@ -4816,7 +4816,7 @@ INT ReadDSDSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd) return uiDSDsig ; } -INT ReadDSDPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd) +INT ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd) { //UINT priOffsetInMap = 0 ; unsigned int uiDSDPri = STATUS_FAILURE; @@ -4839,7 +4839,7 @@ INT ReadDSDPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd) } return uiDSDPri; } -FLASH2X_SECTION_VAL getHighestPriDSD(PMINI_ADAPTER Adapter) +FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter) { INT DSDHighestPri = STATUS_FAILURE; INT DsdPri= 0 ; @@ -4873,7 +4873,7 @@ FLASH2X_SECTION_VAL getHighestPriDSD(PMINI_ADAPTER Adapter) return HighestPriDSD ; } -INT ReadISOSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) +INT ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) { UINT uiISOsig = 0; //UINT sigoffsetInMap = 0; @@ -4898,7 +4898,7 @@ INT ReadISOSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) return uiISOsig ; } -INT ReadISOPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) +INT ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) { unsigned int ISOPri = STATUS_FAILURE; @@ -4919,7 +4919,7 @@ INT ReadISOPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) } return ISOPri; } -FLASH2X_SECTION_VAL getHighestPriISO(PMINI_ADAPTER Adapter) +FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter) { INT ISOHighestPri = STATUS_FAILURE; INT ISOPri= 0 ; @@ -4943,7 +4943,7 @@ FLASH2X_SECTION_VAL getHighestPriISO(PMINI_ADAPTER Adapter) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Highest ISO :%x and its Pri :%x",HighestPriISO,ISOHighestPri); return HighestPriISO ; } -INT WriteToFlashWithoutSectorErase(PMINI_ADAPTER Adapter, +INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff, FLASH2X_SECTION_VAL eFlash2xSectionVal, UINT uiOffset, @@ -5006,7 +5006,7 @@ INT WriteToFlashWithoutSectorErase(PMINI_ADAPTER Adapter, return Status; } -BOOLEAN IsSectionExistInFlash(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) +BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section) { BOOLEAN SectionPresent = FALSE ; @@ -5062,7 +5062,7 @@ BOOLEAN IsSectionExistInFlash(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section } return SectionPresent ; } -INT IsSectionWritable(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL Section) +INT IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section) { INT offset = STATUS_FAILURE; INT Status = FALSE; @@ -5087,7 +5087,7 @@ INT IsSectionWritable(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL Section) return Status ; } -static INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { PUCHAR pBuff = NULL; @@ -5160,7 +5160,7 @@ static INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSect return STATUS_SUCCESS ; } -static INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { PUCHAR pBuff = NULL; @@ -5212,7 +5212,7 @@ static INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSect return STATUS_SUCCESS ; } -BOOLEAN IsNonCDLessDevice(PMINI_ADAPTER Adapter) +BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter) { if(Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG) return TRUE; diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c index 5f891fa90a62..d518c4217f13 100644 --- a/drivers/staging/bcm/sort.c +++ b/drivers/staging/bcm/sort.c @@ -22,7 +22,7 @@ static int compare_packet_info(void const *a, void const *b) return pa->u8TrafficPriority - pb->u8TrafficPriority; } -VOID SortPackInfo(PMINI_ADAPTER Adapter) +VOID SortPackInfo(struct bcm_mini_adapter *Adapter) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<======="); @@ -42,7 +42,7 @@ static int compare_classifiers(void const *a, void const *b) return pa->u8ClassifierRulePriority - pb->u8ClassifierRulePriority; } -VOID SortClassifiers(PMINI_ADAPTER Adapter) +VOID SortClassifiers(struct bcm_mini_adapter *Adapter) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<======="); diff --git a/drivers/staging/bcm/vendorspecificextn.c b/drivers/staging/bcm/vendorspecificextn.c index 4178cd161da3..833883c21a22 100644 --- a/drivers/staging/bcm/vendorspecificextn.c +++ b/drivers/staging/bcm/vendorspecificextn.c @@ -28,7 +28,7 @@ INT vendorextnGetSectionInfo(PVOID pContext,PFLASH2X_VENDORSPECIFIC_INFO pVendo // STATUS_SUCCESS/STATUS_FAILURE // //----------------------------------------------------------------------------- -INT vendorextnInit(PMINI_ADAPTER Adapter) +INT vendorextnInit(struct bcm_mini_adapter *Adapter) { return STATUS_SUCCESS; } @@ -45,7 +45,7 @@ INT vendorextnInit(PMINI_ADAPTER Adapter) // STATUS_SUCCESS/STATUS_FAILURE // //----------------------------------------------------------------------------- -INT vendorextnExit(PMINI_ADAPTER Adapter) +INT vendorextnExit(struct bcm_mini_adapter *Adapter) { return STATUS_SUCCESS; } @@ -65,7 +65,7 @@ INT vendorextnExit(PMINI_ADAPTER Adapter) // STATUS_SUCCESS/STATUS_FAILURE as per the IOCTL return value // //-------------------------------------------------------------------------- -INT vendorextnIoctl(PMINI_ADAPTER Adapter, UINT cmd, ULONG arg) +INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg) { return CONTINUE_COMMON_PATH; } diff --git a/drivers/staging/bcm/vendorspecificextn.h b/drivers/staging/bcm/vendorspecificextn.h index 7ff14951f0ca..f237891b9f29 100644 --- a/drivers/staging/bcm/vendorspecificextn.h +++ b/drivers/staging/bcm/vendorspecificextn.h @@ -5,9 +5,9 @@ #define CONTINUE_COMMON_PATH 0xFFFF INT vendorextnGetSectionInfo(PVOID pContext,PFLASH2X_VENDORSPECIFIC_INFO pVendorInfo); -INT vendorextnExit(PMINI_ADAPTER Adapter); -INT vendorextnInit(PMINI_ADAPTER Adapter); -INT vendorextnIoctl(PMINI_ADAPTER Adapter, UINT cmd, ULONG arg); +INT vendorextnExit(struct bcm_mini_adapter *Adapter); +INT vendorextnInit(struct bcm_mini_adapter *Adapter); +INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg); INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, UINT offset, UINT numOfBytes); INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, -- GitLab From 9c8ea1b29bc9c9bbd922a652d1b91ddceeb180c6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 21 May 2012 14:18:06 +0200 Subject: [PATCH 0280/5711] iio: add LM3533 ambient-light-sensor driver Add sub-driver for the ambient-light-sensor interface on National Semiconductor / TI LM3533 lighting power chips. The sensor interface can be used to control the LEDs and backlights of the chip through defining five light zones and three sets of corresponding output-current values. The driver provides raw and mean adc readings along with the current light zone through sysfs. A threshold event can be generated on zone changes. The ALS-control output values can be set per zone for the three current output channels. Signed-off-by: Johan Hovold Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../testing/sysfs-bus-iio-light-lm3533-als | 62 ++ drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/light/Kconfig | 22 + drivers/iio/light/Makefile | 5 + drivers/iio/light/lm3533-als.c | 932 ++++++++++++++++++ 6 files changed, 1023 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als create mode 100644 drivers/iio/light/Kconfig create mode 100644 drivers/iio/light/Makefile create mode 100644 drivers/iio/light/lm3533-als.c diff --git a/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als b/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als new file mode 100644 index 000000000000..694a52c8cf82 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als @@ -0,0 +1,62 @@ +What: /sys/.../events/in_illuminance0_thresh_either_en +Date: April 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Event generated when channel passes one of the four thresholds + in each direction (rising|falling) and a zone change occurs. + The corresponding light zone can be read from + in_illuminance0_zone. + +What: /sys/.../events/in_illuminance0_threshY_hysteresis +Date: May 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Get the hysteresis for thresholds Y, that is, + + threshY_hysteresis = threshY_raising - threshY_falling + +What: /sys/.../events/illuminance_threshY_falling_value +What: /sys/.../events/illuminance_threshY_raising_value +Date: April 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Specifies the value of threshold that the device is comparing + against for the events enabled by + in_illuminance0_thresh_either_en (0..255), where Y in 0..3. + + Note that threshY_falling must be less than or equal to + threshY_raising. + + These thresholds correspond to the eight zone-boundary + registers (boundaryY_{low,high}) and defines the five light + zones. + +What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_zone +Date: April 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Get the current light zone (0..4) as defined by the + in_illuminance0_threshY_{falling,rising} thresholds. + +What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw +Date: May 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Get output current for channel Y (0..255), that is, + out_currentY_currentZ_raw, where Z is the current zone. + +What: /sys/bus/iio/devices/iio:deviceX/out_currentY_currentZ_raw +Date: May 2012 +KernelVersion: 3.5 +Contact: Johan Hovold +Description: + Set the output current for channel out_currentY when in zone + Z (0..255), where Y in 0..2 and Z in 0..4. + + These values correspond to the ALS-mapper target registers for + ALS-mapper Y + 1. diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 56eecefcec75..cacc74d70241 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -50,5 +50,6 @@ config IIO_CONSUMERS_PER_TRIGGER source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" +source "drivers/iio/light/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index e425afd1480c..060b674d278c 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o obj-y += adc/ obj-y += amplifiers/ +obj-y += light/ diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig new file mode 100644 index 000000000000..db5618e7d90b --- /dev/null +++ b/drivers/iio/light/Kconfig @@ -0,0 +1,22 @@ +# +# Light sensors +# +menu "Light sensors" + +config SENSORS_LM3533 + tristate "LM3533 ambient light sensor" + depends on MFD_LM3533 + help + If you say yes here you get support for the ambient light sensor + interface on National Semiconductor / TI LM3533 Lighting Power + chips. + + The sensor interface can be used to control the LEDs and backlights + of the chip through defining five light zones and three sets of + corresponding output-current values. + + The driver provides raw and mean adc readings along with the current + light zone through sysfs. A threshold event can be generated on zone + changes. The ALS-control output values can be set per zone for the + three current output channels. +endmenu diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile new file mode 100644 index 000000000000..c1c23a024cd2 --- /dev/null +++ b/drivers/iio/light/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for IIO Light sensors +# + +obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c new file mode 100644 index 000000000000..c3e7bac13123 --- /dev/null +++ b/drivers/iio/light/lm3533-als.c @@ -0,0 +1,932 @@ +/* + * lm3533-als.c -- LM3533 Ambient Light Sensor driver + * + * Copyright (C) 2011-2012 Texas Instruments + * + * Author: Johan Hovold + * + * 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 + + +#define LM3533_ALS_RESISTOR_MIN 1 +#define LM3533_ALS_RESISTOR_MAX 127 +#define LM3533_ALS_CHANNEL_CURRENT_MAX 2 +#define LM3533_ALS_THRESH_MAX 3 +#define LM3533_ALS_ZONE_MAX 4 + +#define LM3533_REG_ALS_RESISTOR_SELECT 0x30 +#define LM3533_REG_ALS_CONF 0x31 +#define LM3533_REG_ALS_ZONE_INFO 0x34 +#define LM3533_REG_ALS_READ_ADC_RAW 0x37 +#define LM3533_REG_ALS_READ_ADC_AVERAGE 0x38 +#define LM3533_REG_ALS_BOUNDARY_BASE 0x50 +#define LM3533_REG_ALS_TARGET_BASE 0x60 + +#define LM3533_ALS_ENABLE_MASK 0x01 +#define LM3533_ALS_INPUT_MODE_MASK 0x02 +#define LM3533_ALS_INT_ENABLE_MASK 0x01 + +#define LM3533_ALS_ZONE_SHIFT 2 +#define LM3533_ALS_ZONE_MASK 0x1c + +#define LM3533_ALS_FLAG_INT_ENABLED 1 + + +struct lm3533_als { + struct lm3533 *lm3533; + struct platform_device *pdev; + + unsigned long flags; + int irq; + + atomic_t zone; + struct mutex thresh_mutex; +}; + + +static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average, + int *adc) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + u8 val; + int ret; + + if (average) + reg = LM3533_REG_ALS_READ_ADC_AVERAGE; + else + reg = LM3533_REG_ALS_READ_ADC_RAW; + + ret = lm3533_read(als->lm3533, reg, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to read adc\n"); + return ret; + } + + *adc = val; + + return 0; +} + +static int _lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 val; + int ret; + + ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to read zone\n"); + return ret; + } + + val = (val & LM3533_ALS_ZONE_MASK) >> LM3533_ALS_ZONE_SHIFT; + *zone = min_t(u8, val, LM3533_ALS_ZONE_MAX); + + return 0; +} + +static int lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone) +{ + struct lm3533_als *als = iio_priv(indio_dev); + int ret; + + if (test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags)) { + *zone = atomic_read(&als->zone); + } else { + ret = _lm3533_als_get_zone(indio_dev, zone); + if (ret) + return ret; + } + + return 0; +} + +/* + * channel output channel 0..2 + * zone zone 0..4 + */ +static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone) +{ + return LM3533_REG_ALS_TARGET_BASE + 5 * channel + zone; +} + +static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel, + unsigned zone, u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX) + return -EINVAL; + + if (zone > LM3533_ALS_ZONE_MAX) + return -EINVAL; + + reg = lm3533_als_get_target_reg(channel, zone); + ret = lm3533_read(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to get target current\n"); + + return ret; +} + +static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel, + unsigned zone, u8 val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX) + return -EINVAL; + + if (zone > LM3533_ALS_ZONE_MAX) + return -EINVAL; + + reg = lm3533_als_get_target_reg(channel, zone); + ret = lm3533_write(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to set target current\n"); + + return ret; +} + +static int lm3533_als_get_current(struct iio_dev *indio_dev, unsigned channel, + int *val) +{ + u8 zone; + u8 target; + int ret; + + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + ret = lm3533_als_get_target(indio_dev, channel, zone, &target); + if (ret) + return ret; + + *val = target; + + return 0; +} + +static int lm3533_als_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + + switch (mask) { + case 0: + switch (chan->type) { + case IIO_LIGHT: + ret = lm3533_als_get_adc(indio_dev, false, val); + break; + case IIO_CURRENT: + ret = lm3533_als_get_current(indio_dev, chan->channel, + val); + break; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_AVERAGE_RAW: + ret = lm3533_als_get_adc(indio_dev, true, val); + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return IIO_VAL_INT; +} + +#define CHANNEL_CURRENT(_channel) \ + { \ + .type = IIO_CURRENT, \ + .channel = _channel, \ + .indexed = true, \ + .output = true, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ + } + +static const struct iio_chan_spec lm3533_als_channels[] = { + { + .type = IIO_LIGHT, + .channel = 0, + .indexed = true, + .info_mask = (IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_RAW_SEPARATE_BIT), + }, + CHANNEL_CURRENT(0), + CHANNEL_CURRENT(1), + CHANNEL_CURRENT(2), +}; + +static irqreturn_t lm3533_als_isr(int irq, void *dev_id) +{ + + struct iio_dev *indio_dev = dev_id; + struct lm3533_als *als = iio_priv(indio_dev); + u8 zone; + int ret; + + /* Clear interrupt by reading the ALS zone register. */ + ret = _lm3533_als_get_zone(indio_dev, &zone); + if (ret) + goto out; + + atomic_set(&als->zone, zone); + + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns()); +out: + return IRQ_HANDLED; +} + +static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + u8 val; + int ret; + + if (enable) + val = mask; + else + val = 0; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask); + if (ret) { + dev_err(&indio_dev->dev, "failed to set int mode %d\n", + enable); + return ret; + } + + return 0; +} + +static int lm3533_als_get_int_mode(struct iio_dev *indio_dev, int *enable) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + u8 val; + int ret; + + ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to get int mode\n"); + return ret; + } + + *enable = !!(val & mask); + + return 0; +} + +static inline u8 lm3533_als_get_threshold_reg(unsigned nr, bool raising) +{ + u8 offset = !raising; + + return LM3533_REG_ALS_BOUNDARY_BASE + 2 * nr + offset; +} + +static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr, + bool raising, u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + reg = lm3533_als_get_threshold_reg(nr, raising); + ret = lm3533_read(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to get threshold\n"); + + return ret; +} + +static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr, + bool raising, u8 val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 val2; + u8 reg, reg2; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + reg = lm3533_als_get_threshold_reg(nr, raising); + reg2 = lm3533_als_get_threshold_reg(nr, !raising); + + mutex_lock(&als->thresh_mutex); + ret = lm3533_read(als->lm3533, reg2, &val2); + if (ret) { + dev_err(&indio_dev->dev, "failed to get threshold\n"); + goto out; + } + /* + * This device does not allow negative hysteresis (in fact, it uses + * whichever value is smaller as the lower bound) so we need to make + * sure that thresh_falling <= thresh_raising. + */ + if ((raising && (val < val2)) || (!raising && (val > val2))) { + ret = -EINVAL; + goto out; + } + + ret = lm3533_write(als->lm3533, reg, val); + if (ret) { + dev_err(&indio_dev->dev, "failed to set threshold\n"); + goto out; + } +out: + mutex_unlock(&als->thresh_mutex); + + return ret; +} + +static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr, + u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 falling; + u8 raising; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + mutex_lock(&als->thresh_mutex); + ret = lm3533_als_get_threshold(indio_dev, nr, false, &falling); + if (ret) + goto out; + ret = lm3533_als_get_threshold(indio_dev, nr, true, &raising); + if (ret) + goto out; + + *val = raising - falling; +out: + mutex_unlock(&als->thresh_mutex); + + return ret; +} + +static int show_thresh_either_en(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als *als = iio_priv(indio_dev); + int enable; + int ret; + + if (als->irq) { + ret = lm3533_als_get_int_mode(indio_dev, &enable); + if (ret) + return ret; + } else { + enable = 0; + } + + return scnprintf(buf, PAGE_SIZE, "%u\n", enable); +} + +static int store_thresh_either_en(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als *als = iio_priv(indio_dev); + unsigned long enable; + bool int_enabled; + u8 zone; + int ret; + + if (!als->irq) + return -EBUSY; + + if (kstrtoul(buf, 0, &enable)) + return -EINVAL; + + int_enabled = test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + if (enable && !int_enabled) { + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + atomic_set(&als->zone, zone); + + set_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + } + + ret = lm3533_als_set_int_mode(indio_dev, enable); + if (ret) { + if (!int_enabled) + clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + return ret; + } + + if (!enable) + clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + return len; +} + +static ssize_t show_zone(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + u8 zone; + int ret; + + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + return scnprintf(buf, PAGE_SIZE, "%u\n", zone); +} + +enum lm3533_als_attribute_type { + LM3533_ATTR_TYPE_HYSTERESIS, + LM3533_ATTR_TYPE_TARGET, + LM3533_ATTR_TYPE_THRESH_FALLING, + LM3533_ATTR_TYPE_THRESH_RAISING, +}; + +struct lm3533_als_attribute { + struct device_attribute dev_attr; + enum lm3533_als_attribute_type type; + u8 val1; + u8 val2; +}; + +static inline struct lm3533_als_attribute * +to_lm3533_als_attr(struct device_attribute *attr) +{ + return container_of(attr, struct lm3533_als_attribute, dev_attr); +} + +static ssize_t show_als_attr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr); + u8 val; + int ret; + + switch (als_attr->type) { + case LM3533_ATTR_TYPE_HYSTERESIS: + ret = lm3533_als_get_hysteresis(indio_dev, als_attr->val1, + &val); + break; + case LM3533_ATTR_TYPE_TARGET: + ret = lm3533_als_get_target(indio_dev, als_attr->val1, + als_attr->val2, &val); + break; + case LM3533_ATTR_TYPE_THRESH_FALLING: + ret = lm3533_als_get_threshold(indio_dev, als_attr->val1, + false, &val); + break; + case LM3533_ATTR_TYPE_THRESH_RAISING: + ret = lm3533_als_get_threshold(indio_dev, als_attr->val1, + true, &val); + break; + default: + ret = -ENXIO; + } + + if (ret) + return ret; + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t store_als_attr(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr); + u8 val; + int ret; + + if (kstrtou8(buf, 0, &val)) + return -EINVAL; + + switch (als_attr->type) { + case LM3533_ATTR_TYPE_TARGET: + ret = lm3533_als_set_target(indio_dev, als_attr->val1, + als_attr->val2, val); + break; + case LM3533_ATTR_TYPE_THRESH_FALLING: + ret = lm3533_als_set_threshold(indio_dev, als_attr->val1, + false, val); + break; + case LM3533_ATTR_TYPE_THRESH_RAISING: + ret = lm3533_als_set_threshold(indio_dev, als_attr->val1, + true, val); + break; + default: + ret = -ENXIO; + } + + if (ret) + return ret; + + return len; +} + +#define ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type, \ + .val1 = _val1, \ + .val2 = _val2 } + +#define LM3533_ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \ + struct lm3533_als_attribute lm3533_als_attr_##_name = \ + ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) + +#define ALS_TARGET_ATTR_RW(_channel, _zone) \ + LM3533_ALS_ATTR(out_current##_channel##_current##_zone##_raw, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_TARGET, _channel, _zone) +/* + * ALS output current values (ALS mapper targets) + * + * out_current[0-2]_current[0-4]_raw 0-255 + */ +static ALS_TARGET_ATTR_RW(0, 0); +static ALS_TARGET_ATTR_RW(0, 1); +static ALS_TARGET_ATTR_RW(0, 2); +static ALS_TARGET_ATTR_RW(0, 3); +static ALS_TARGET_ATTR_RW(0, 4); + +static ALS_TARGET_ATTR_RW(1, 0); +static ALS_TARGET_ATTR_RW(1, 1); +static ALS_TARGET_ATTR_RW(1, 2); +static ALS_TARGET_ATTR_RW(1, 3); +static ALS_TARGET_ATTR_RW(1, 4); + +static ALS_TARGET_ATTR_RW(2, 0); +static ALS_TARGET_ATTR_RW(2, 1); +static ALS_TARGET_ATTR_RW(2, 2); +static ALS_TARGET_ATTR_RW(2, 3); +static ALS_TARGET_ATTR_RW(2, 4); + +#define ALS_THRESH_FALLING_ATTR_RW(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_falling_value, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_THRESH_FALLING, _nr, 0) + +#define ALS_THRESH_RAISING_ATTR_RW(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_raising_value, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_THRESH_RAISING, _nr, 0) +/* + * ALS Zone thresholds (boundaries) + * + * in_illuminance0_thresh[0-3]_falling_value 0-255 + * in_illuminance0_thresh[0-3]_raising_value 0-255 + */ +static ALS_THRESH_FALLING_ATTR_RW(0); +static ALS_THRESH_FALLING_ATTR_RW(1); +static ALS_THRESH_FALLING_ATTR_RW(2); +static ALS_THRESH_FALLING_ATTR_RW(3); + +static ALS_THRESH_RAISING_ATTR_RW(0); +static ALS_THRESH_RAISING_ATTR_RW(1); +static ALS_THRESH_RAISING_ATTR_RW(2); +static ALS_THRESH_RAISING_ATTR_RW(3); + +#define ALS_HYSTERESIS_ATTR_RO(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_hysteresis, \ + S_IRUGO, show_als_attr, NULL, \ + LM3533_ATTR_TYPE_HYSTERESIS, _nr, 0) +/* + * ALS Zone threshold hysteresis + * + * threshY_hysteresis = threshY_raising - threshY_falling + * + * in_illuminance0_thresh[0-3]_hysteresis 0-255 + * in_illuminance0_thresh[0-3]_hysteresis 0-255 + */ +static ALS_HYSTERESIS_ATTR_RO(0); +static ALS_HYSTERESIS_ATTR_RO(1); +static ALS_HYSTERESIS_ATTR_RO(2); +static ALS_HYSTERESIS_ATTR_RO(3); + +#define ILLUMINANCE_ATTR_RO(_name) \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL) +#define ILLUMINANCE_ATTR_RW(_name) \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \ + show_##_name, store_##_name) +/* + * ALS Zone threshold-event enable + * + * in_illuminance0_thresh_either_en 0,1 + */ +static ILLUMINANCE_ATTR_RW(thresh_either_en); + +/* + * ALS Current Zone + * + * in_illuminance0_zone 0-4 + */ +static ILLUMINANCE_ATTR_RO(zone); + +static struct attribute *lm3533_als_event_attributes[] = { + &dev_attr_in_illuminance0_thresh_either_en.attr, + &lm3533_als_attr_in_illuminance0_thresh0_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh0_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh0_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_raising_value.dev_attr.attr, + NULL +}; + +static struct attribute_group lm3533_als_event_attribute_group = { + .attrs = lm3533_als_event_attributes +}; + +static struct attribute *lm3533_als_attributes[] = { + &dev_attr_in_illuminance0_zone.attr, + &lm3533_als_attr_out_current0_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current4_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current4_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current4_raw.dev_attr.attr, + NULL +}; + +static struct attribute_group lm3533_als_attribute_group = { + .attrs = lm3533_als_attributes +}; + +static int __devinit lm3533_als_set_input_mode(struct lm3533_als *als, + bool pwm_mode) +{ + u8 mask = LM3533_ALS_INPUT_MODE_MASK; + u8 val; + int ret; + + if (pwm_mode) + val = mask; /* pwm input */ + else + val = 0; /* analog input */ + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, val, mask); + if (ret) { + dev_err(&als->pdev->dev, "failed to set input mode %d\n", + pwm_mode); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_set_resistor(struct lm3533_als *als, u8 val) +{ + int ret; + + if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) + return -EINVAL; + + ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); + if (ret) { + dev_err(&als->pdev->dev, "failed to set resistor\n"); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_setup(struct lm3533_als *als, + struct lm3533_als_platform_data *pdata) +{ + int ret; + + ret = lm3533_als_set_input_mode(als, pdata->pwm_mode); + if (ret) + return ret; + + /* ALS input is always high impedance in PWM-mode. */ + if (!pdata->pwm_mode) { + ret = lm3533_als_set_resistor(als, pdata->r_select); + if (ret) + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_setup_irq(struct lm3533_als *als, void *dev) +{ + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + int ret; + + /* Make sure interrupts are disabled. */ + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask); + if (ret) { + dev_err(&als->pdev->dev, "failed to disable interrupts\n"); + return ret; + } + + ret = request_threaded_irq(als->irq, NULL, lm3533_als_isr, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + dev_name(&als->pdev->dev), dev); + if (ret) { + dev_err(&als->pdev->dev, "failed to request irq %d\n", + als->irq); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_enable(struct lm3533_als *als) +{ + u8 mask = LM3533_ALS_ENABLE_MASK; + int ret; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask); + if (ret) + dev_err(&als->pdev->dev, "failed to enable ALS\n"); + + return ret; +} + +static int lm3533_als_disable(struct lm3533_als *als) +{ + u8 mask = LM3533_ALS_ENABLE_MASK; + int ret; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask); + if (ret) + dev_err(&als->pdev->dev, "failed to disable ALS\n"); + + return ret; +} + +static const struct iio_info lm3533_als_info = { + .attrs = &lm3533_als_attribute_group, + .event_attrs = &lm3533_als_event_attribute_group, + .driver_module = THIS_MODULE, + .read_raw = &lm3533_als_read_raw, +}; + +static int __devinit lm3533_als_probe(struct platform_device *pdev) +{ + struct lm3533 *lm3533; + struct lm3533_als_platform_data *pdata; + struct lm3533_als *als; + struct iio_dev *indio_dev; + int ret; + + lm3533 = dev_get_drvdata(pdev->dev.parent); + if (!lm3533) + return -EINVAL; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data\n"); + return -EINVAL; + } + + indio_dev = iio_device_alloc(sizeof(*als)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &lm3533_als_info; + indio_dev->channels = lm3533_als_channels; + indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels); + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = pdev->dev.parent; + indio_dev->modes = INDIO_DIRECT_MODE; + + als = iio_priv(indio_dev); + als->lm3533 = lm3533; + als->pdev = pdev; + als->irq = lm3533->irq; + atomic_set(&als->zone, 0); + mutex_init(&als->thresh_mutex); + + platform_set_drvdata(pdev, indio_dev); + + if (als->irq) { + ret = lm3533_als_setup_irq(als, indio_dev); + if (ret) + goto err_free_dev; + } + + ret = lm3533_als_setup(als, pdata); + if (ret) + goto err_free_irq; + + ret = lm3533_als_enable(als); + if (ret) + goto err_free_irq; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "failed to register ALS\n"); + goto err_disable; + } + + return 0; + +err_disable: + lm3533_als_disable(als); +err_free_irq: + if (als->irq) + free_irq(als->irq, indio_dev); +err_free_dev: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit lm3533_als_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct lm3533_als *als = iio_priv(indio_dev); + + lm3533_als_set_int_mode(indio_dev, false); + iio_device_unregister(indio_dev); + lm3533_als_disable(als); + if (als->irq) + free_irq(als->irq, indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static struct platform_driver lm3533_als_driver = { + .driver = { + .name = "lm3533-als", + .owner = THIS_MODULE, + }, + .probe = lm3533_als_probe, + .remove = __devexit_p(lm3533_als_remove), +}; +module_platform_driver(lm3533_als_driver); + +MODULE_AUTHOR("Johan Hovold "); +MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lm3533-als"); -- GitLab From cd1678f963298a9e777f3edb72d28bc18a3a32c2 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 29 May 2012 12:41:19 +0200 Subject: [PATCH 0281/5711] iio: frequency: New driver for AD9523 SPI Low Jitter Clock Generator Changes since V1: Apply Jonathan's review feedback: Revise device status attribute names, and split documentation into two sections. Add additional comments, and fix indention issues. Remove pointless zero initializations. Revise return value handling. Simplify some code sections. Split store_eeprom and sync handling into separate functions. Use strtobool where applicable. Document platform data structures using kernel-doc style. Use dev_to_iio_dev write_raw IIO_CHAN_INFO_FREQUENCY: Reject values <= 0 Make patch target drivers/iio Changes since V2: Use for_each_clear_bit() and __set_bit() where applicable. Add descriptive comment. Avoid temporary for struct regulator. spi_device_id name use ad9523-1, ad9523 will be added later. Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../testing/sysfs-bus-iio-frequency-ad9523 | 37 + drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/frequency/Kconfig | 23 + drivers/iio/frequency/Makefile | 5 + drivers/iio/frequency/ad9523.c | 1057 +++++++++++++++++ include/linux/iio/frequency/ad9523.h | 195 +++ 7 files changed, 1319 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 create mode 100644 drivers/iio/frequency/Kconfig create mode 100644 drivers/iio/frequency/Makefile create mode 100644 drivers/iio/frequency/ad9523.c create mode 100644 include/linux/iio/frequency/ad9523.h diff --git a/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 b/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 new file mode 100644 index 000000000000..2ce9c3f68eee --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 @@ -0,0 +1,37 @@ +What: /sys/bus/iio/devices/iio:deviceX/pll2_feedback_clk_present +What: /sys/bus/iio/devices/iio:deviceX/pll2_reference_clk_present +What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_a_present +What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_b_present +What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_test_present +What: /sys/bus/iio/devices/iio:deviceX/vcxo_clk_present +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Reading returns either '1' or '0'. + '1' means that the clock in question is present. + '0' means that the clock is missing. + +What: /sys/bus/iio/devices/iio:deviceX/pllY_locked +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Reading returns either '1' or '0'. '1' means that the + pllY is locked. + +What: /sys/bus/iio/devices/iio:deviceX/store_eeprom +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Writing '1' stores the current device configuration into + on-chip EEPROM. After power-up or chip reset the device will + automatically load the saved configuration. + +What: /sys/bus/iio/devices/iio:deviceX/sync_dividers +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Writing '1' triggers the clock distribution synchronization + functionality. All dividers are reset and the channels start + with their predefined phase offsets (out_altvoltageY_phase). + Writing this file has the effect as driving the external + /SYNC pin low. diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index cacc74d70241..64c88e5cda4d 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -51,5 +51,6 @@ config IIO_CONSUMERS_PER_TRIGGER source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" source "drivers/iio/light/Kconfig" +source "drivers/iio/frequency/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 060b674d278c..bd801c0bbc2f 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o obj-y += adc/ obj-y += amplifiers/ obj-y += light/ +obj-y += frequency/ diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig new file mode 100644 index 000000000000..0458c92464a3 --- /dev/null +++ b/drivers/iio/frequency/Kconfig @@ -0,0 +1,23 @@ +# +# Frequency +# Direct Digital Synthesis drivers (DDS) +# Clock Distribution device drivers +# Phase-Locked Loop (PLL) frequency synthesizers +# + +menu "Frequency Synthesizers DDS/PLL" + +menu "Clock Generator/Distribution" + +config AD9523 + tristate "Analog Devices AD9523 Low Jitter Clock Generator" + depends on SPI + help + Say yes here to build support for Analog Devices AD9523 Low Jitter + Clock Generator. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad9523. + +endmenu +endmenu diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile new file mode 100644 index 000000000000..1b5b22417da1 --- /dev/null +++ b/drivers/iio/frequency/Makefile @@ -0,0 +1,5 @@ +# +# Makefile iio/frequency +# + +obj-$(CONFIG_AD9523) += ad9523.o diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c new file mode 100644 index 000000000000..7272924484c1 --- /dev/null +++ b/drivers/iio/frequency/ad9523.c @@ -0,0 +1,1057 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AD9523_READ (1 << 15) +#define AD9523_WRITE (0 << 15) +#define AD9523_CNT(x) (((x) - 1) << 13) +#define AD9523_ADDR(x) ((x) & 0xFFF) + +#define AD9523_R1B (1 << 16) +#define AD9523_R2B (2 << 16) +#define AD9523_R3B (3 << 16) +#define AD9523_TRANSF_LEN(x) ((x) >> 16) + +#define AD9523_SERIAL_PORT_CONFIG (AD9523_R1B | 0x0) +#define AD9523_VERSION_REGISTER (AD9523_R1B | 0x2) +#define AD9523_PART_REGISTER (AD9523_R1B | 0x3) +#define AD9523_READBACK_CTRL (AD9523_R1B | 0x4) + +#define AD9523_EEPROM_CUSTOMER_VERSION_ID (AD9523_R2B | 0x6) + +#define AD9523_PLL1_REF_A_DIVIDER (AD9523_R2B | 0x11) +#define AD9523_PLL1_REF_B_DIVIDER (AD9523_R2B | 0x13) +#define AD9523_PLL1_REF_TEST_DIVIDER (AD9523_R1B | 0x14) +#define AD9523_PLL1_FEEDBACK_DIVIDER (AD9523_R2B | 0x17) +#define AD9523_PLL1_CHARGE_PUMP_CTRL (AD9523_R2B | 0x19) +#define AD9523_PLL1_INPUT_RECEIVERS_CTRL (AD9523_R1B | 0x1A) +#define AD9523_PLL1_REF_CTRL (AD9523_R1B | 0x1B) +#define AD9523_PLL1_MISC_CTRL (AD9523_R1B | 0x1C) +#define AD9523_PLL1_LOOP_FILTER_CTRL (AD9523_R1B | 0x1D) + +#define AD9523_PLL2_CHARGE_PUMP (AD9523_R1B | 0xF0) +#define AD9523_PLL2_FEEDBACK_DIVIDER_AB (AD9523_R1B | 0xF1) +#define AD9523_PLL2_CTRL (AD9523_R1B | 0xF2) +#define AD9523_PLL2_VCO_CTRL (AD9523_R1B | 0xF3) +#define AD9523_PLL2_VCO_DIVIDER (AD9523_R1B | 0xF4) +#define AD9523_PLL2_LOOP_FILTER_CTRL (AD9523_R2B | 0xF6) +#define AD9523_PLL2_R2_DIVIDER (AD9523_R1B | 0xF7) + +#define AD9523_CHANNEL_CLOCK_DIST(ch) (AD9523_R3B | (0x192 + 3 * ch)) + +#define AD9523_PLL1_OUTPUT_CTRL (AD9523_R1B | 0x1BA) +#define AD9523_PLL1_OUTPUT_CHANNEL_CTRL (AD9523_R1B | 0x1BB) + +#define AD9523_READBACK_0 (AD9523_R1B | 0x22C) +#define AD9523_READBACK_1 (AD9523_R1B | 0x22D) + +#define AD9523_STATUS_SIGNALS (AD9523_R3B | 0x232) +#define AD9523_POWER_DOWN_CTRL (AD9523_R1B | 0x233) +#define AD9523_IO_UPDATE (AD9523_R1B | 0x234) + +#define AD9523_EEPROM_DATA_XFER_STATUS (AD9523_R1B | 0xB00) +#define AD9523_EEPROM_ERROR_READBACK (AD9523_R1B | 0xB01) +#define AD9523_EEPROM_CTRL1 (AD9523_R1B | 0xB02) +#define AD9523_EEPROM_CTRL2 (AD9523_R1B | 0xB03) + +/* AD9523_SERIAL_PORT_CONFIG */ + +#define AD9523_SER_CONF_SDO_ACTIVE (1 << 7) +#define AD9523_SER_CONF_SOFT_RESET (1 << 5) + +/* AD9523_READBACK_CTRL */ +#define AD9523_READBACK_CTRL_READ_BUFFERED (1 << 0) + +/* AD9523_PLL1_CHARGE_PUMP_CTRL */ +#define AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(x) (((x) / 500) & 0x7F) +#define AD9523_PLL1_CHARGE_PUMP_TRISTATE (1 << 7) +#define AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL (3 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_UP (1 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_TRISTATE (0 << 8) +#define AD9523_PLL1_BACKLASH_PW_MIN (0 << 10) +#define AD9523_PLL1_BACKLASH_PW_LOW (1 << 10) +#define AD9523_PLL1_BACKLASH_PW_HIGH (2 << 10) +#define AD9523_PLL1_BACKLASH_PW_MAX (3 << 10) + +/* AD9523_PLL1_INPUT_RECEIVERS_CTRL */ +#define AD9523_PLL1_REF_TEST_RCV_EN (1 << 7) +#define AD9523_PLL1_REFB_DIFF_RCV_EN (1 << 6) +#define AD9523_PLL1_REFA_DIFF_RCV_EN (1 << 5) +#define AD9523_PLL1_REFB_RCV_EN (1 << 4) +#define AD9523_PLL1_REFA_RCV_EN (1 << 3) +#define AD9523_PLL1_REFA_REFB_PWR_CTRL_EN (1 << 2) +#define AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_OSC_IN_DIFF_EN (1 << 0) + +/* AD9523_PLL1_REF_CTRL */ +#define AD9523_PLL1_BYPASS_REF_TEST_DIV_EN (1 << 7) +#define AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN (1 << 6) +#define AD9523_PLL1_ZERO_DELAY_MODE_INT (1 << 5) +#define AD9523_PLL1_ZERO_DELAY_MODE_EXT (0 << 5) +#define AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN (1 << 4) +#define AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN (1 << 3) +#define AD9523_PLL1_ZD_IN_DIFF_EN (1 << 2) +#define AD9523_PLL1_REFB_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_REFA_CMOS_NEG_INP_EN (1 << 0) + +/* AD9523_PLL1_MISC_CTRL */ +#define AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN (1 << 7) +#define AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN (1 << 6) +#define AD9523_PLL1_REF_MODE(x) ((x) << 2) +#define AD9523_PLL1_BYPASS_REFB_DIV (1 << 1) +#define AD9523_PLL1_BYPASS_REFA_DIV (1 << 0) + +/* AD9523_PLL1_LOOP_FILTER_CTRL */ +#define AD9523_PLL1_LOOP_FILTER_RZERO(x) ((x) & 0xF) + +/* AD9523_PLL2_CHARGE_PUMP */ +#define AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(x) ((x) / 3500) + +/* AD9523_PLL2_FEEDBACK_DIVIDER_AB */ +#define AD9523_PLL2_FB_NDIV_A_CNT(x) (((x) & 0x3) << 6) +#define AD9523_PLL2_FB_NDIV_B_CNT(x) (((x) & 0x3F) << 0) +#define AD9523_PLL2_FB_NDIV(a, b) (4 * (b) + (a)) + +/* AD9523_PLL2_CTRL */ +#define AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL (3 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_UP (1 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_TRISTATE (0 << 0) +#define AD9523_PLL2_BACKLASH_PW_MIN (0 << 2) +#define AD9523_PLL2_BACKLASH_PW_LOW (1 << 2) +#define AD9523_PLL2_BACKLASH_PW_HIGH (2 << 2) +#define AD9523_PLL2_BACKLASH_PW_MAX (3 << 1) +#define AD9523_PLL2_BACKLASH_CTRL_EN (1 << 4) +#define AD9523_PLL2_FREQ_DOUBLER_EN (1 << 5) +#define AD9523_PLL2_LOCK_DETECT_PWR_DOWN_EN (1 << 7) + +/* AD9523_PLL2_VCO_CTRL */ +#define AD9523_PLL2_VCO_CALIBRATE (1 << 1) +#define AD9523_PLL2_FORCE_VCO_MIDSCALE (1 << 2) +#define AD9523_PLL2_FORCE_REFERENCE_VALID (1 << 3) +#define AD9523_PLL2_FORCE_RELEASE_SYNC (1 << 4) + +/* AD9523_PLL2_VCO_DIVIDER */ +#define AD9523_PLL2_VCO_DIV_M1(x) ((((x) - 3) & 0x3) << 0) +#define AD9523_PLL2_VCO_DIV_M2(x) ((((x) - 3) & 0x3) << 4) +#define AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN (1 << 2) +#define AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN (1 << 6) + +/* AD9523_PLL2_LOOP_FILTER_CTRL */ +#define AD9523_PLL2_LOOP_FILTER_CPOLE1(x) (((x) & 0x7) << 0) +#define AD9523_PLL2_LOOP_FILTER_RZERO(x) (((x) & 0x7) << 3) +#define AD9523_PLL2_LOOP_FILTER_RPOLE2(x) (((x) & 0x7) << 6) +#define AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN (1 << 8) + +/* AD9523_PLL2_R2_DIVIDER */ +#define AD9523_PLL2_R2_DIVIDER_VAL(x) (((x) & 0x1F) << 0) + +/* AD9523_CHANNEL_CLOCK_DIST */ +#define AD9523_CLK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18) +#define AD9523_CLK_DIST_DIV_PHASE_REV(x) ((ret >> 18) & 0x3F) +#define AD9523_CLK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8) +#define AD9523_CLK_DIST_DIV_REV(x) (((ret >> 8) & 0x3FF) + 1) +#define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN (1 << 7) +#define AD9523_CLK_DIST_IGNORE_SYNC_EN (1 << 6) +#define AD9523_CLK_DIST_PWR_DOWN_EN (1 << 5) +#define AD9523_CLK_DIST_LOW_PWR_MODE_EN (1 << 4) +#define AD9523_CLK_DIST_DRIVER_MODE(x) (((x) & 0xF) << 0) + +/* AD9523_PLL1_OUTPUT_CTRL */ +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH6_M2 (1 << 7) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH5_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CTRL_CMOS_DRV_WEAK (1 << 4) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_1 (0 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_2 (1 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_4 (2 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_8 (4 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_16 (8 << 0) + +/* AD9523_PLL1_OUTPUT_CHANNEL_CTRL */ +#define AD9523_PLL1_OUTP_CH_CTRL_OUTPUT_PWR_DOWN_EN (1 << 7) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH9_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH8_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 (1 << 4) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH3 (1 << 3) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH2 (1 << 2) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH1 (1 << 1) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 (1 << 0) + +/* AD9523_READBACK_0 */ +#define AD9523_READBACK_0_STAT_PLL2_REF_CLK (1 << 7) +#define AD9523_READBACK_0_STAT_PLL2_FB_CLK (1 << 6) +#define AD9523_READBACK_0_STAT_VCXO (1 << 5) +#define AD9523_READBACK_0_STAT_REF_TEST (1 << 4) +#define AD9523_READBACK_0_STAT_REFB (1 << 3) +#define AD9523_READBACK_0_STAT_REFA (1 << 2) +#define AD9523_READBACK_0_STAT_PLL2_LD (1 << 1) +#define AD9523_READBACK_0_STAT_PLL1_LD (1 << 0) + +/* AD9523_READBACK_1 */ +#define AD9523_READBACK_1_HOLDOVER_ACTIVE (1 << 3) +#define AD9523_READBACK_1_AUTOMODE_SEL_REFB (1 << 2) +#define AD9523_READBACK_1_VCO_CALIB_IN_PROGRESS (1 << 0) + +/* AD9523_STATUS_SIGNALS */ +#define AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL (1 << 16) +#define AD9523_STATUS_MONITOR_01_PLL12_LOCKED (0x302) +/* AD9523_POWER_DOWN_CTRL */ +#define AD9523_POWER_DOWN_CTRL_PLL1_PWR_DOWN (1 << 2) +#define AD9523_POWER_DOWN_CTRL_PLL2_PWR_DOWN (1 << 1) +#define AD9523_POWER_DOWN_CTRL_DIST_PWR_DOWN (1 << 0) + +/* AD9523_IO_UPDATE */ +#define AD9523_IO_UPDATE_EN (1 << 0) + +/* AD9523_EEPROM_DATA_XFER_STATUS */ +#define AD9523_EEPROM_DATA_XFER_IN_PROGRESS (1 << 0) + +/* AD9523_EEPROM_ERROR_READBACK */ +#define AD9523_EEPROM_ERROR_READBACK_FAIL (1 << 0) + +/* AD9523_EEPROM_CTRL1 */ +#define AD9523_EEPROM_CTRL1_SOFT_EEPROM (1 << 1) +#define AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS (1 << 0) + +/* AD9523_EEPROM_CTRL2 */ +#define AD9523_EEPROM_CTRL2_REG2EEPROM (1 << 0) + +#define AD9523_NUM_CHAN 14 +#define AD9523_NUM_CHAN_ALT_CLK_SRC 10 + +/* Helpers to avoid excess line breaks */ +#define AD_IFE(_pde, _a, _b) ((pdata->_pde) ? _a : _b) +#define AD_IF(_pde, _a) AD_IFE(_pde, _a, 0) + +enum { + AD9523_STAT_PLL1_LD, + AD9523_STAT_PLL2_LD, + AD9523_STAT_REFA, + AD9523_STAT_REFB, + AD9523_STAT_REF_TEST, + AD9523_STAT_VCXO, + AD9523_STAT_PLL2_FB_CLK, + AD9523_STAT_PLL2_REF_CLK, + AD9523_SYNC, + AD9523_EEPROM, +}; + +enum { + AD9523_VCO1, + AD9523_VCO2, + AD9523_VCXO, + AD9523_NUM_CLK_SRC, +}; + +struct ad9523_state { + struct spi_device *spi; + struct regulator *reg; + struct ad9523_platform_data *pdata; + struct iio_chan_spec ad9523_channels[AD9523_NUM_CHAN]; + + unsigned long vcxo_freq; + unsigned long vco_freq; + unsigned long vco_out_freq[AD9523_NUM_CLK_SRC]; + unsigned char vco_out_map[AD9523_NUM_CHAN_ALT_CLK_SRC]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + + /* We encode the register size 1..3 bytes into the register address. + * On transfer we get the size from the register datum, and make sure + * the result is properly aligned. + */ + + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + }, { + .rx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)], + .len = AD9523_TRANSF_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_READ | + AD9523_CNT(AD9523_TRANSF_LEN(addr)) | + AD9523_ADDR(addr)); + + ret = spi_sync(st->spi, &m); + if (ret < 0) + dev_err(&indio_dev->dev, "read failed (%d)", ret); + else + ret = be32_to_cpu(st->data[1].d32) & (0xFFFFFF >> + (8 * (3 - AD9523_TRANSF_LEN(addr)))); + + return ret; +}; + +static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + }, { + .tx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)], + .len = AD9523_TRANSF_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_WRITE | + AD9523_CNT(AD9523_TRANSF_LEN(addr)) | + AD9523_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(val); + + ret = spi_sync(st->spi, &m); + + if (ret < 0) + dev_err(&indio_dev->dev, "write failed (%d)", ret); + + return ret; +} + +static int ad9523_io_update(struct iio_dev *indio_dev) +{ + return ad9523_write(indio_dev, AD9523_IO_UPDATE, AD9523_IO_UPDATE_EN); +} + +static int ad9523_vco_out_map(struct iio_dev *indio_dev, + unsigned ch, bool out) +{ + struct ad9523_state *st = iio_priv(indio_dev); + int ret; + unsigned mask; + + switch (ch) { + case 0 ... 3: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 << ch; + if (out) { + ret |= mask; + out = 2; + } else { + ret &= ~mask; + } + ret = ad9523_write(indio_dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + case 4 ... 6: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 << (ch - 4); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, AD9523_PLL1_OUTPUT_CTRL, ret); + break; + case 7 ... 9: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 << (ch - 7); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + default: + return 0; + } + + st->vco_out_map[ch] = out; + + return ret; +} + +static int ad9523_set_clock_provider(struct iio_dev *indio_dev, + unsigned ch, unsigned long freq) +{ + struct ad9523_state *st = iio_priv(indio_dev); + long tmp1, tmp2; + bool use_alt_clk_src; + + switch (ch) { + case 0 ... 3: + use_alt_clk_src = (freq == st->vco_out_freq[AD9523_VCXO]); + break; + case 4 ... 9: + tmp1 = st->vco_out_freq[AD9523_VCO1] / freq; + tmp2 = st->vco_out_freq[AD9523_VCO2] / freq; + tmp1 *= freq; + tmp2 *= freq; + use_alt_clk_src = (abs(tmp1 - freq) > abs(tmp2 - freq)); + break; + default: + /* Ch 10..14: No action required, return success */ + return 0; + } + + return ad9523_vco_out_map(indio_dev, ch, use_alt_clk_src); +} + +static int ad9523_store_eeprom(struct iio_dev *indio_dev) +{ + int ret, tmp; + + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, + AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS); + if (ret < 0) + return ret; + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL2, + AD9523_EEPROM_CTRL2_REG2EEPROM); + if (ret < 0) + return ret; + + tmp = 4; + do { + msleep(16); + ret = ad9523_read(indio_dev, + AD9523_EEPROM_DATA_XFER_STATUS); + if (ret < 0) + return ret; + } while ((ret & AD9523_EEPROM_DATA_XFER_IN_PROGRESS) && tmp--); + + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, 0); + if (ret < 0) + return ret; + + ret = ad9523_read(indio_dev, AD9523_EEPROM_ERROR_READBACK); + if (ret < 0) + return ret; + + if (ret & AD9523_EEPROM_ERROR_READBACK_FAIL) { + dev_err(&indio_dev->dev, "Verify EEPROM failed"); + ret = -EIO; + } + + return ret; +} + +static int ad9523_sync(struct iio_dev *indio_dev) +{ + int ret, tmp; + + ret = ad9523_read(indio_dev, AD9523_STATUS_SIGNALS); + if (ret < 0) + return ret; + + tmp = ret; + tmp |= AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + return ret; + + ad9523_io_update(indio_dev); + tmp &= ~AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + return ret; + + return ad9523_io_update(indio_dev); +} + +static ssize_t ad9523_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 iio_dev_attr *this_attr = to_iio_dev_attr(attr); + bool state; + int ret; + + ret = strtobool(buf, &state); + if (ret < 0) + return ret; + + if (!state) + return 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case AD9523_SYNC: + ret = ad9523_sync(indio_dev); + break; + case AD9523_EEPROM: + ret = ad9523_store_eeprom(indio_dev); + break; + default: + ret = -ENODEV; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ad9523_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_READBACK_0); + if (ret >= 0) { + ret = sprintf(buf, "%d\n", !!(ret & (1 << + (u32)this_attr->address))); + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_DEVICE_ATTR(pll1_locked, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL1_LD); + +static IIO_DEVICE_ATTR(pll2_locked, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_LD); + +static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REFA); + +static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REFB); + +static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REF_TEST); + +static IIO_DEVICE_ATTR(vcxo_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_VCXO); + +static IIO_DEVICE_ATTR(pll2_feedback_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_FB_CLK); + +static IIO_DEVICE_ATTR(pll2_reference_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_REF_CLK); + +static IIO_DEVICE_ATTR(sync_dividers, S_IWUSR, + NULL, + ad9523_store, + AD9523_SYNC); + +static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, + NULL, + ad9523_store, + AD9523_EEPROM); + +static struct attribute *ad9523_attributes[] = { + &iio_dev_attr_sync_dividers.dev_attr.attr, + &iio_dev_attr_store_eeprom.dev_attr.attr, + &iio_dev_attr_pll2_feedback_clk_present.dev_attr.attr, + &iio_dev_attr_pll2_reference_clk_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_a_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_b_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_test_present.dev_attr.attr, + &iio_dev_attr_vcxo_clk_present.dev_attr.attr, + &iio_dev_attr_pll1_locked.dev_attr.attr, + &iio_dev_attr_pll2_locked.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9523_attribute_group = { + .attrs = ad9523_attributes, +}; + +static int ad9523_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad9523_state *st = iio_priv(indio_dev); + unsigned code; + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + *val = !(ret & AD9523_CLK_DIST_PWR_DOWN_EN); + return IIO_VAL_INT; + case IIO_CHAN_INFO_FREQUENCY: + *val = st->vco_out_freq[st->vco_out_map[chan->channel]] / + AD9523_CLK_DIST_DIV_REV(ret); + return IIO_VAL_INT; + case IIO_CHAN_INFO_PHASE: + code = (AD9523_CLK_DIST_DIV_PHASE_REV(ret) * 3141592) / + AD9523_CLK_DIST_DIV_REV(ret); + *val = code / 1000000; + *val2 = (code % 1000000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +}; + +static int ad9523_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad9523_state *st = iio_priv(indio_dev); + unsigned reg; + int ret, tmp, code; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + if (ret < 0) + goto out; + + reg = ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val) + reg &= ~AD9523_CLK_DIST_PWR_DOWN_EN; + else + reg |= AD9523_CLK_DIST_PWR_DOWN_EN; + break; + case IIO_CHAN_INFO_FREQUENCY: + if (val <= 0) { + ret = -EINVAL; + goto out; + } + ret = ad9523_set_clock_provider(indio_dev, chan->channel, val); + if (ret < 0) + goto out; + tmp = st->vco_out_freq[st->vco_out_map[chan->channel]] / val; + tmp = clamp(tmp, 1, 1024); + reg &= ~(0x3FF << 8); + reg |= AD9523_CLK_DIST_DIV(tmp); + break; + case IIO_CHAN_INFO_PHASE: + code = val * 1000000 + val2 % 1000000; + tmp = (code * AD9523_CLK_DIST_DIV_REV(ret)) / 3141592; + tmp = clamp(tmp, 0, 63); + reg &= ~AD9523_CLK_DIST_DIV_PHASE(~0); + reg |= AD9523_CLK_DIST_DIV_PHASE(tmp); + break; + default: + ret = -EINVAL; + goto out; + } + + ret = ad9523_write(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel), + reg); + if (ret < 0) + goto out; + + ad9523_io_update(indio_dev); +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad9523_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval); + ad9523_io_update(indio_dev); + } else { + ret = ad9523_read(indio_dev, reg | AD9523_R1B); + if (ret < 0) + return ret; + *readval = ret; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_info ad9523_info = { + .read_raw = &ad9523_read_raw, + .write_raw = &ad9523_write_raw, + .debugfs_reg_access = &ad9523_reg_access, + .attrs = &ad9523_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int ad9523_setup(struct iio_dev *indio_dev) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct ad9523_platform_data *pdata = st->pdata; + struct ad9523_channel_spec *chan; + unsigned long active_mask = 0; + int ret, i; + + ret = ad9523_write(indio_dev, AD9523_SERIAL_PORT_CONFIG, + AD9523_SER_CONF_SOFT_RESET | + (st->spi->mode & SPI_3WIRE ? 0 : + AD9523_SER_CONF_SDO_ACTIVE)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_READBACK_CTRL, + AD9523_READBACK_CTRL_READ_BUFFERED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + /* + * PLL1 Setup + */ + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_A_DIVIDER, + pdata->refa_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_B_DIVIDER, + pdata->refb_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_FEEDBACK_DIVIDER, + pdata->pll1_feedback_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL, + AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata-> + pll1_charge_pump_current_nA) | + AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL1_BACKLASH_PW_MIN); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_INPUT_RECEIVERS_CTRL, + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) | + AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | + AD_IF(osc_in_cmos_neg_inp_en, + AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) | + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_CTRL, + AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) | + AD_IF(zd_in_cmos_neg_inp_en, + AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) | + AD_IF(zero_delay_mode_internal_en, + AD9523_PLL1_ZERO_DELAY_MODE_INT) | + AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) | + AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) | + AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_MISC_CTRL, + AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN | + AD9523_PLL1_REF_MODE(pdata->ref_mode)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_LOOP_FILTER_CTRL, + AD9523_PLL1_LOOP_FILTER_RZERO(pdata->pll1_loop_filter_rzero)); + if (ret < 0) + return ret; + /* + * PLL2 Setup + */ + + ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP, + AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata-> + pll2_charge_pump_current_nA)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_FEEDBACK_DIVIDER_AB, + AD9523_PLL2_FB_NDIV_A_CNT(pdata->pll2_ndiv_a_cnt) | + AD9523_PLL2_FB_NDIV_B_CNT(pdata->pll2_ndiv_b_cnt)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_CTRL, + AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL2_BACKLASH_CTRL_EN | + AD_IF(pll2_freq_doubler_en, AD9523_PLL2_FREQ_DOUBLER_EN)); + if (ret < 0) + return ret; + + st->vco_freq = (pdata->vcxo_freq * (pdata->pll2_freq_doubler_en ? 2 : 1) + / pdata->pll2_r2_div) * AD9523_PLL2_FB_NDIV(pdata-> + pll2_ndiv_a_cnt, pdata->pll2_ndiv_b_cnt); + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_CTRL, + AD9523_PLL2_VCO_CALIBRATE); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER, + AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_diff_m1) | + AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_diff_m2) | + AD_IFE(pll2_vco_diff_m1, 0, + AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) | + AD_IFE(pll2_vco_diff_m2, 0, + AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN)); + if (ret < 0) + return ret; + + if (pdata->pll2_vco_diff_m1) + st->vco_out_freq[AD9523_VCO1] = + st->vco_freq / pdata->pll2_vco_diff_m1; + + if (pdata->pll2_vco_diff_m2) + st->vco_out_freq[AD9523_VCO2] = + st->vco_freq / pdata->pll2_vco_diff_m2; + + st->vco_out_freq[AD9523_VCXO] = pdata->vcxo_freq; + + ret = ad9523_write(indio_dev, AD9523_PLL2_R2_DIVIDER, + AD9523_PLL2_R2_DIVIDER_VAL(pdata->pll2_r2_div)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_LOOP_FILTER_CTRL, + AD9523_PLL2_LOOP_FILTER_CPOLE1(pdata->cpole1) | + AD9523_PLL2_LOOP_FILTER_RZERO(pdata->rzero) | + AD9523_PLL2_LOOP_FILTER_RPOLE2(pdata->rpole2) | + AD_IF(rzero_bypass_en, + AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN)); + if (ret < 0) + return ret; + + for (i = 0; i < pdata->num_channels; i++) { + chan = &pdata->channels[i]; + if (chan->channel_num < AD9523_NUM_CHAN) { + __set_bit(chan->channel_num, &active_mask); + ret = ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(chan->channel_num), + AD9523_CLK_DIST_DRIVER_MODE(chan->driver_mode) | + AD9523_CLK_DIST_DIV(chan->channel_divider) | + AD9523_CLK_DIST_DIV_PHASE(chan->divider_phase) | + (chan->sync_ignore_en ? + AD9523_CLK_DIST_IGNORE_SYNC_EN : 0) | + (chan->divider_output_invert_en ? + AD9523_CLK_DIST_INV_DIV_OUTPUT_EN : 0) | + (chan->low_power_mode_en ? + AD9523_CLK_DIST_LOW_PWR_MODE_EN : 0) | + (chan->output_dis ? + AD9523_CLK_DIST_PWR_DOWN_EN : 0)); + if (ret < 0) + return ret; + + ret = ad9523_vco_out_map(indio_dev, chan->channel_num, + chan->use_alt_clock_src); + if (ret < 0) + return ret; + + st->ad9523_channels[i].type = IIO_ALTVOLTAGE; + st->ad9523_channels[i].output = 1; + st->ad9523_channels[i].indexed = 1; + st->ad9523_channels[i].channel = chan->channel_num; + st->ad9523_channels[i].extend_name = + chan->extended_name; + st->ad9523_channels[i].info_mask = + IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_PHASE_SEPARATE_BIT | + IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT; + } + } + + for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) + ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(i), + AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) | + AD9523_CLK_DIST_PWR_DOWN_EN); + + ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, + AD9523_STATUS_MONITOR_01_PLL12_LOCKED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + return 0; +} + +static int __devinit ad9523_probe(struct spi_device *spi) +{ + struct ad9523_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad9523_state *st; + int ret; + + if (!pdata) { + dev_err(&spi->dev, "no platform data?\n"); + return -EINVAL; + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : + spi_get_device_id(spi)->name; + indio_dev->info = &ad9523_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->ad9523_channels; + indio_dev->num_channels = pdata->num_channels; + + ret = ad9523_setup(indio_dev); + if (ret < 0) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + dev_info(&spi->dev, "probed %s\n", indio_dev->name); + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad9523_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad9523_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad9523_id[] = { + {"ad9523-1", 9523}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9523_id); + +static struct spi_driver ad9523_driver = { + .driver = { + .name = "ad9523", + .owner = THIS_MODULE, + }, + .probe = ad9523_probe, + .remove = __devexit_p(ad9523_remove), + .id_table = ad9523_id, +}; +module_spi_driver(ad9523_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9523 CLOCKDIST/PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/iio/frequency/ad9523.h b/include/linux/iio/frequency/ad9523.h new file mode 100644 index 000000000000..12ce3ee427fd --- /dev/null +++ b/include/linux/iio/frequency/ad9523.h @@ -0,0 +1,195 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_FREQUENCY_AD9523_H_ +#define IIO_FREQUENCY_AD9523_H_ + +enum outp_drv_mode { + TRISTATE, + LVPECL_8mA, + LVDS_4mA, + LVDS_7mA, + HSTL0_16mA, + HSTL1_8mA, + CMOS_CONF1, + CMOS_CONF2, + CMOS_CONF3, + CMOS_CONF4, + CMOS_CONF5, + CMOS_CONF6, + CMOS_CONF7, + CMOS_CONF8, + CMOS_CONF9 +}; + +enum ref_sel_mode { + NONEREVERTIVE_STAY_ON_REFB, + REVERT_TO_REFA, + SELECT_REFA, + SELECT_REFB, + EXT_REF_SEL +}; + +/** + * struct ad9523_channel_spec - Output channel configuration + * + * @channel_num: Output channel number. + * @divider_output_invert_en: Invert the polarity of the output clock. + * @sync_ignore_en: Ignore chip-level SYNC signal. + * @low_power_mode_en: Reduce power used in the differential output modes. + * @use_alt_clock_src: Channel divider uses alternative clk source. + * @output_dis: Disables, powers down the entire channel. + * @driver_mode: Output driver mode (logic level family). + * @divider_phase: Divider initial phase after a SYNC. Range 0..63 + LSB = 1/2 of a period of the divider input clock. + * @channel_divider: 10-bit channel divider. + * @extended_name: Optional descriptive channel name. + */ + +struct ad9523_channel_spec { + unsigned channel_num; + bool divider_output_invert_en; + bool sync_ignore_en; + bool low_power_mode_en; + /* CH0..CH3 VCXO, CH4..CH9 VCO2 */ + bool use_alt_clock_src; + bool output_dis; + enum outp_drv_mode driver_mode; + unsigned char divider_phase; + unsigned short channel_divider; + char extended_name[16]; +}; + +enum pll1_rzero_resistor { + RZERO_883_OHM, + RZERO_677_OHM, + RZERO_341_OHM, + RZERO_135_OHM, + RZERO_10_OHM, + RZERO_USE_EXT_RES = 8, +}; + +enum rpole2_resistor { + RPOLE2_900_OHM, + RPOLE2_450_OHM, + RPOLE2_300_OHM, + RPOLE2_225_OHM, +}; + +enum rzero_resistor { + RZERO_3250_OHM, + RZERO_2750_OHM, + RZERO_2250_OHM, + RZERO_2100_OHM, + RZERO_3000_OHM, + RZERO_2500_OHM, + RZERO_2000_OHM, + RZERO_1850_OHM, +}; + +enum cpole1_capacitor { + CPOLE1_0_PF, + CPOLE1_8_PF, + CPOLE1_16_PF, + CPOLE1_24_PF, + _CPOLE1_24_PF, /* place holder */ + CPOLE1_32_PF, + CPOLE1_40_PF, + CPOLE1_48_PF, +}; + +/** + * struct ad9523_platform_data - platform specific information + * + * @vcxo_freq: External VCXO frequency in Hz + * @refa_diff_rcv_en: REFA differential/single-ended input selection. + * @refb_diff_rcv_en: REFB differential/single-ended input selection. + * @zd_in_diff_en: Zero Delay differential/single-ended input selection. + * @osc_in_diff_en: OSC differential/ single-ended input selection. + * @refa_cmos_neg_inp_en: REFA single-ended neg./pos. input enable. + * @refb_cmos_neg_inp_en: REFB single-ended neg./pos. input enable. + * @zd_in_cmos_neg_inp_en: Zero Delay single-ended neg./pos. input enable. + * @osc_in_cmos_neg_inp_en: OSC single-ended neg./pos. input enable. + * @refa_r_div: PLL1 10-bit REFA R divider. + * @refb_r_div: PLL1 10-bit REFB R divider. + * @pll1_feedback_div: PLL1 10-bit Feedback N divider. + * @pll1_charge_pump_current_nA: Magnitude of PLL1 charge pump current (nA). + * @zero_delay_mode_internal_en: Internal, external Zero Delay mode selection. + * @osc_in_feedback_en: PLL1 feedback path, local feedback from + * the OSC_IN receiver or zero delay mode + * @pll1_loop_filter_rzero: PLL1 Loop Filter Zero Resistor selection. + * @ref_mode: Reference selection mode. + * @pll2_charge_pump_current_nA: Magnitude of PLL2 charge pump current (nA). + * @pll2_ndiv_a_cnt: PLL2 Feedback N-divider, A Counter, range 0..4. + * @pll2_ndiv_b_cnt: PLL2 Feedback N-divider, B Counter, range 0..63. + * @pll2_freq_doubler_en: PLL2 frequency doubler enable. + * @pll2_r2_div: PLL2 R2 divider, range 0..31. + * @pll2_vco_diff_m1: VCO1 divider, range 3..5. + * @pll2_vco_diff_m2: VCO2 divider, range 3..5. + * @rpole2: PLL2 loop filter Rpole resistor value. + * @rzero: PLL2 loop filter Rzero resistor value. + * @cpole1: PLL2 loop filter Cpole capacitor value. + * @rzero_bypass_en: PLL2 loop filter Rzero bypass enable. + * @num_channels: Array size of struct ad9523_channel_spec. + * @channels: Pointer to channel array. + * @name: Optional alternative iio device name. + */ + +struct ad9523_platform_data { + unsigned long vcxo_freq; + + /* Differential/ Single-Ended Input Configuration */ + bool refa_diff_rcv_en; + bool refb_diff_rcv_en; + bool zd_in_diff_en; + bool osc_in_diff_en; + + /* + * Valid if differential input disabled + * if false defaults to pos input + */ + bool refa_cmos_neg_inp_en; + bool refb_cmos_neg_inp_en; + bool zd_in_cmos_neg_inp_en; + bool osc_in_cmos_neg_inp_en; + + /* PLL1 Setting */ + unsigned short refa_r_div; + unsigned short refb_r_div; + unsigned short pll1_feedback_div; + unsigned short pll1_charge_pump_current_nA; + bool zero_delay_mode_internal_en; + bool osc_in_feedback_en; + enum pll1_rzero_resistor pll1_loop_filter_rzero; + + /* Reference */ + enum ref_sel_mode ref_mode; + + /* PLL2 Setting */ + unsigned int pll2_charge_pump_current_nA; + unsigned char pll2_ndiv_a_cnt; + unsigned char pll2_ndiv_b_cnt; + bool pll2_freq_doubler_en; + unsigned char pll2_r2_div; + unsigned char pll2_vco_diff_m1; /* 3..5 */ + unsigned char pll2_vco_diff_m2; /* 3..5 */ + + /* Loop Filter PLL2 */ + enum rpole2_resistor rpole2; + enum rzero_resistor rzero; + enum cpole1_capacitor cpole1; + bool rzero_bypass_en; + + /* Output Channel Configuration */ + int num_channels; + struct ad9523_channel_spec *channels; + + char name[SPI_NAME_SIZE]; +}; + +#endif /* IIO_FREQUENCY_AD9523_H_ */ -- GitLab From e31166f0fd48478866ee9661c36789126435ebe8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 29 May 2012 12:41:20 +0200 Subject: [PATCH 0282/5711] iio: frequency: New driver for Analog Devices ADF4350/ADF4351 Wideband Synthesizers Changes since V1: Apply Jonathan's review feedback: Introduce and use IIO_ALTVOLTAGE. Fix up comments and documentation. Remove dead code. Reorder some code fragments. Add missing iio_device_free. Convert to new API. Fix-up out of staging includes. Removed pll_locked attribute. Changes since V2: Use module_spi_driver. adf4350_remove: move gpio_free after regulator. target patch to drivers/iio Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../testing/sysfs-bus-iio-frequency-adf4350 | 21 + drivers/iio/frequency/Kconfig | 18 + drivers/iio/frequency/Makefile | 1 + drivers/iio/frequency/adf4350.c | 478 ++++++++++++++++++ include/linux/iio/frequency/adf4350.h | 126 +++++ 5 files changed, 644 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 create mode 100644 drivers/iio/frequency/adf4350.c create mode 100644 include/linux/iio/frequency/adf4350.h diff --git a/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 b/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 new file mode 100644 index 000000000000..d89aded01c5a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 @@ -0,0 +1,21 @@ +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_resolution +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Stores channel Y frequency resolution/channel spacing in Hz. + The value given directly influences the MODULUS used by + the fractional-N PLL. It is assumed that the algorithm + that is used to compute the various dividers, is able to + generate proper values for multiples of channel spacing. + +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_refin_frequency +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + Sets channel Y REFin frequency in Hz. In some clock chained + applications, the reference frequency used by the PLL may + change during runtime. This attribute allows the user to + adjust the reference frequency accordingly. + The value written has no effect until out_altvoltageY_frequency + is updated. Consider to use out_altvoltageY_powerdown to power + down the PLL and it's RFOut buffers during REFin changes. diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index 0458c92464a3..6aaa33ef4544 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -19,5 +19,23 @@ config AD9523 To compile this driver as a module, choose M here: the module will be called ad9523. +endmenu + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# + +menu "Phase-Locked Loop (PLL) frequency synthesizers" + +config ADF4350 + tristate "Analog Devices ADF4350/ADF4351 Wideband Synthesizers" + depends on SPI + help + Say yes here to build support for Analog Devices ADF4350/ADF4351 + Wideband Synthesizers. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called adf4350. + endmenu endmenu diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile index 1b5b22417da1..00d26e5d1dc2 100644 --- a/drivers/iio/frequency/Makefile +++ b/drivers/iio/frequency/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_AD9523) += ad9523.o +obj-$(CONFIG_ADF4350) += adf4350.o diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c new file mode 100644 index 000000000000..fd4c8501aba9 --- /dev/null +++ b/drivers/iio/frequency/adf4350.c @@ -0,0 +1,478 @@ +/* + * ADF4350/ADF4351 SPI Wideband Synthesizer driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +enum { + ADF4350_FREQ, + ADF4350_FREQ_REFIN, + ADF4350_FREQ_RESOLUTION, + ADF4350_PWRDOWN, +}; + +struct adf4350_state { + struct spi_device *spi; + struct regulator *reg; + struct adf4350_platform_data *pdata; + unsigned long clkin; + unsigned long chspc; /* Channel Spacing */ + unsigned long fpfd; /* Phase Frequency Detector */ + unsigned long min_out_freq; + unsigned r0_fract; + unsigned r0_int; + unsigned r1_mod; + unsigned r4_rf_div_sel; + unsigned long regs[6]; + unsigned long regs_hw[6]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be32 val ____cacheline_aligned; +}; + +static struct adf4350_platform_data default_pdata = { + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, +}; + +static int adf4350_sync_config(struct adf4350_state *st) +{ + int ret, i, doublebuf = 0; + + for (i = ADF4350_REG5; i >= ADF4350_REG0; i--) { + if ((st->regs_hw[i] != st->regs[i]) || + ((i == ADF4350_REG0) && doublebuf)) { + + switch (i) { + case ADF4350_REG1: + case ADF4350_REG4: + doublebuf = 1; + break; + } + + st->val = cpu_to_be32(st->regs[i] | i); + ret = spi_write(st->spi, &st->val, 4); + if (ret < 0) + return ret; + st->regs_hw[i] = st->regs[i]; + dev_dbg(&st->spi->dev, "[%d] 0x%X\n", + i, (u32)st->regs[i] | i); + } + } + return 0; +} + +static int adf4350_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct adf4350_state *st = iio_priv(indio_dev); + int ret; + + if (reg > ADF4350_REG5) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + st->regs[reg] = writeval & ~(BIT(0) | BIT(1) | BIT(2)); + ret = adf4350_sync_config(st); + } else { + *readval = st->regs_hw[reg]; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int adf4350_tune_r_cnt(struct adf4350_state *st, unsigned short r_cnt) +{ + struct adf4350_platform_data *pdata = st->pdata; + + do { + r_cnt++; + st->fpfd = (st->clkin * (pdata->ref_doubler_en ? 2 : 1)) / + (r_cnt * (pdata->ref_div2_en ? 2 : 1)); + } while (st->fpfd > ADF4350_MAX_FREQ_PFD); + + return r_cnt; +} + +static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) +{ + struct adf4350_platform_data *pdata = st->pdata; + u64 tmp; + u32 div_gcd, prescaler; + u16 mdiv, r_cnt = 0; + u8 band_sel_div; + + if (freq > ADF4350_MAX_OUT_FREQ || freq < st->min_out_freq) + return -EINVAL; + + if (freq > ADF4350_MAX_FREQ_45_PRESC) { + prescaler = ADF4350_REG1_PRESCALER; + mdiv = 75; + } else { + prescaler = 0; + mdiv = 23; + } + + st->r4_rf_div_sel = 0; + + while (freq < ADF4350_MIN_VCO_FREQ) { + freq <<= 1; + st->r4_rf_div_sel++; + } + + /* + * Allow a predefined reference division factor + * if not set, compute our own + */ + if (pdata->ref_div_factor) + r_cnt = pdata->ref_div_factor - 1; + + do { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + + st->r1_mod = st->fpfd / st->chspc; + while (st->r1_mod > ADF4350_MAX_MODULUS) { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / st->chspc; + } + + tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); + do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ + st->r0_fract = do_div(tmp, st->r1_mod); + st->r0_int = tmp; + } while (mdiv > st->r0_int); + + band_sel_div = DIV_ROUND_UP(st->fpfd, ADF4350_MAX_BANDSEL_CLK); + + if (st->r0_fract && st->r1_mod) { + div_gcd = gcd(st->r1_mod, st->r0_fract); + st->r1_mod /= div_gcd; + st->r0_fract /= div_gcd; + } else { + st->r0_fract = 0; + st->r1_mod = 1; + } + + dev_dbg(&st->spi->dev, "VCO: %llu Hz, PFD %lu Hz\n" + "REF_DIV %d, R0_INT %d, R0_FRACT %d\n" + "R1_MOD %d, RF_DIV %d\nPRESCALER %s, BAND_SEL_DIV %d\n", + freq, st->fpfd, r_cnt, st->r0_int, st->r0_fract, st->r1_mod, + 1 << st->r4_rf_div_sel, prescaler ? "8/9" : "4/5", + band_sel_div); + + st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | + ADF4350_REG0_FRACT(st->r0_fract); + + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | + ADF4350_REG1_MOD(st->r1_mod) | + prescaler; + + st->regs[ADF4350_REG2] = + ADF4350_REG2_10BIT_R_CNT(r_cnt) | + ADF4350_REG2_DOUBLE_BUFF_EN | + (pdata->ref_doubler_en ? ADF4350_REG2_RMULT2_EN : 0) | + (pdata->ref_div2_en ? ADF4350_REG2_RDIV2_EN : 0) | + (pdata->r2_user_settings & (ADF4350_REG2_PD_POLARITY_POS | + ADF4350_REG2_LDP_6ns | ADF4350_REG2_LDF_INT_N | + ADF4350_REG2_CHARGE_PUMP_CURR_uA(5000) | + ADF4350_REG2_MUXOUT(0x7) | ADF4350_REG2_NOISE_MODE(0x9))); + + st->regs[ADF4350_REG3] = pdata->r3_user_settings & + (ADF4350_REG3_12BIT_CLKDIV(0xFFF) | + ADF4350_REG3_12BIT_CLKDIV_MODE(0x3) | + ADF4350_REG3_12BIT_CSR_EN | + ADF4351_REG3_CHARGE_CANCELLATION_EN | + ADF4351_REG3_ANTI_BACKLASH_3ns_EN | + ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH); + + st->regs[ADF4350_REG4] = + ADF4350_REG4_FEEDBACK_FUND | + ADF4350_REG4_RF_DIV_SEL(st->r4_rf_div_sel) | + ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(band_sel_div) | + ADF4350_REG4_RF_OUT_EN | + (pdata->r4_user_settings & + (ADF4350_REG4_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_EN | + ADF4350_REG4_AUX_OUTPUT_FUND | + ADF4350_REG4_MUTE_TILL_LOCK_EN)); + + st->regs[ADF4350_REG5] = ADF4350_REG5_LD_PIN_MODE_DIGITAL; + + return adf4350_sync_config(st); +} + +static ssize_t adf4350_write(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct adf4350_state *st = iio_priv(indio_dev); + unsigned long long readin; + int ret; + + ret = kstrtoull(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + switch ((u32)private) { + case ADF4350_FREQ: + ret = adf4350_set_freq(st, readin); + break; + case ADF4350_FREQ_REFIN: + if (readin > ADF4350_MAX_FREQ_REFIN) + ret = -EINVAL; + else + st->clkin = readin; + break; + case ADF4350_FREQ_RESOLUTION: + if (readin == 0) + ret = -EINVAL; + else + st->chspc = readin; + break; + case ADF4350_PWRDOWN: + if (readin) + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + else + st->regs[ADF4350_REG2] &= ~ADF4350_REG2_POWER_DOWN_EN; + + adf4350_sync_config(st); + break; + default: + ret = -ENODEV; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t adf4350_read(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct adf4350_state *st = iio_priv(indio_dev); + unsigned long long val; + int ret = 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)private) { + case ADF4350_FREQ: + val = (u64)((st->r0_int * st->r1_mod) + st->r0_fract) * + (u64)st->fpfd; + do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel)); + /* PLL unlocked? return error */ + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + if (!gpio_get_value(st->pdata->gpio_lock_detect)) { + dev_dbg(&st->spi->dev, "PLL un-locked\n"); + ret = -EBUSY; + } + break; + case ADF4350_FREQ_REFIN: + val = st->clkin; + break; + case ADF4350_FREQ_RESOLUTION: + val = st->chspc; + break; + case ADF4350_PWRDOWN: + val = !!(st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); + break; + } + mutex_unlock(&indio_dev->mlock); + + return ret < 0 ? ret : sprintf(buf, "%llu\n", val); +} + +#define _ADF4350_EXT_INFO(_name, _ident) { \ + .name = _name, \ + .read = adf4350_read, \ + .write = adf4350_write, \ + .private = _ident, \ +} + +static const struct iio_chan_spec_ext_info adf4350_ext_info[] = { + /* Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are + * values > 2^32 in order to support the entire frequency range + * in Hz. Using scale is a bit ugly. + */ + _ADF4350_EXT_INFO("frequency", ADF4350_FREQ), + _ADF4350_EXT_INFO("frequency_resolution", ADF4350_FREQ_RESOLUTION), + _ADF4350_EXT_INFO("refin_frequency", ADF4350_FREQ_REFIN), + _ADF4350_EXT_INFO("powerdown", ADF4350_PWRDOWN), + { }, +}; + +static const struct iio_chan_spec adf4350_chan = { + .type = IIO_ALTVOLTAGE, + .indexed = 1, + .output = 1, + .ext_info = adf4350_ext_info, +}; + +static const struct iio_info adf4350_info = { + .debugfs_reg_access = &adf4350_reg_access, + .driver_module = THIS_MODULE, +}; + +static int __devinit adf4350_probe(struct spi_device *spi) +{ + struct adf4350_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct adf4350_state *st; + int ret; + + if (!pdata) { + dev_warn(&spi->dev, "no platform data? using default\n"); + + pdata = &default_pdata; + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : + spi_get_device_id(spi)->name; + + indio_dev->info = &adf4350_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &adf4350_chan; + indio_dev->num_channels = 1; + + st->chspc = pdata->channel_spacing; + st->clkin = pdata->clkin; + + st->min_out_freq = spi_get_device_id(spi)->driver_data == 4351 ? + ADF4351_MIN_OUT_FREQ : ADF4350_MIN_OUT_FREQ; + + memset(st->regs_hw, 0xFF, sizeof(st->regs_hw)); + + if (gpio_is_valid(pdata->gpio_lock_detect)) { + ret = gpio_request(pdata->gpio_lock_detect, indio_dev->name); + if (ret) { + dev_err(&spi->dev, "fail to request lock detect GPIO-%d", + pdata->gpio_lock_detect); + goto error_disable_reg; + } + gpio_direction_input(pdata->gpio_lock_detect); + } + + if (pdata->power_up_frequency) { + ret = adf4350_set_freq(st, pdata->power_up_frequency); + if (ret) + goto error_free_gpio; + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_gpio; + + return 0; + +error_free_gpio: + if (gpio_is_valid(pdata->gpio_lock_detect)) + gpio_free(pdata->gpio_lock_detect); + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit adf4350_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adf4350_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + adf4350_sync_config(st); + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + gpio_free(st->pdata->gpio_lock_detect); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id adf4350_id[] = { + {"adf4350", 4350}, + {"adf4351", 4351}, + {} +}; + +static struct spi_driver adf4350_driver = { + .driver = { + .name = "adf4350", + .owner = THIS_MODULE, + }, + .probe = adf4350_probe, + .remove = __devexit_p(adf4350_remove), + .id_table = adf4350_id, +}; +module_spi_driver(adf4350_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices ADF4350/ADF4351 PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h new file mode 100644 index 000000000000..b76b4a87065e --- /dev/null +++ b/include/linux/iio/frequency/adf4350.h @@ -0,0 +1,126 @@ +/* + * ADF4350/ADF4351 SPI PLL driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_PLL_ADF4350_H_ +#define IIO_PLL_ADF4350_H_ + +/* Registers */ +#define ADF4350_REG0 0 +#define ADF4350_REG1 1 +#define ADF4350_REG2 2 +#define ADF4350_REG3 3 +#define ADF4350_REG4 4 +#define ADF4350_REG5 5 + +/* REG0 Bit Definitions */ +#define ADF4350_REG0_FRACT(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG0_INT(x) (((x) & 0xFFFF) << 15) + +/* REG1 Bit Definitions */ +#define ADF4350_REG1_MOD(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG1_PHASE(x) (((x) & 0xFFF) << 15) +#define ADF4350_REG1_PRESCALER (1 << 27) + +/* REG2 Bit Definitions */ +#define ADF4350_REG2_COUNTER_RESET_EN (1 << 3) +#define ADF4350_REG2_CP_THREESTATE_EN (1 << 4) +#define ADF4350_REG2_POWER_DOWN_EN (1 << 5) +#define ADF4350_REG2_PD_POLARITY_POS (1 << 6) +#define ADF4350_REG2_LDP_6ns (1 << 7) +#define ADF4350_REG2_LDP_10ns (0 << 7) +#define ADF4350_REG2_LDF_FRACT_N (0 << 8) +#define ADF4350_REG2_LDF_INT_N (1 << 8) +#define ADF4350_REG2_CHARGE_PUMP_CURR_uA(x) (((((x)-312) / 312) & 0xF) << 9) +#define ADF4350_REG2_DOUBLE_BUFF_EN (1 << 13) +#define ADF4350_REG2_10BIT_R_CNT(x) ((x) << 14) +#define ADF4350_REG2_RDIV2_EN (1 << 24) +#define ADF4350_REG2_RMULT2_EN (1 << 25) +#define ADF4350_REG2_MUXOUT(x) ((x) << 26) +#define ADF4350_REG2_NOISE_MODE(x) ((x) << 29) +#define ADF4350_MUXOUT_THREESTATE 0 +#define ADF4350_MUXOUT_DVDD 1 +#define ADF4350_MUXOUT_GND 2 +#define ADF4350_MUXOUT_R_DIV_OUT 3 +#define ADF4350_MUXOUT_N_DIV_OUT 4 +#define ADF4350_MUXOUT_ANALOG_LOCK_DETECT 5 +#define ADF4350_MUXOUT_DIGITAL_LOCK_DETECT 6 + +/* REG3 Bit Definitions */ +#define ADF4350_REG3_12BIT_CLKDIV(x) ((x) << 3) +#define ADF4350_REG3_12BIT_CLKDIV_MODE(x) ((x) << 16) +#define ADF4350_REG3_12BIT_CSR_EN (1 << 18) +#define ADF4351_REG3_CHARGE_CANCELLATION_EN (1 << 21) +#define ADF4351_REG3_ANTI_BACKLASH_3ns_EN (1 << 22) +#define ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH (1 << 23) + +/* REG4 Bit Definitions */ +#define ADF4350_REG4_OUTPUT_PWR(x) ((x) << 3) +#define ADF4350_REG4_RF_OUT_EN (1 << 5) +#define ADF4350_REG4_AUX_OUTPUT_PWR(x) ((x) << 6) +#define ADF4350_REG4_AUX_OUTPUT_EN (1 << 8) +#define ADF4350_REG4_AUX_OUTPUT_FUND (1 << 9) +#define ADF4350_REG4_AUX_OUTPUT_DIV (0 << 9) +#define ADF4350_REG4_MUTE_TILL_LOCK_EN (1 << 10) +#define ADF4350_REG4_VCO_PWRDOWN_EN (1 << 11) +#define ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(x) ((x) << 12) +#define ADF4350_REG4_RF_DIV_SEL(x) ((x) << 20) +#define ADF4350_REG4_FEEDBACK_DIVIDED (0 << 23) +#define ADF4350_REG4_FEEDBACK_FUND (1 << 23) + +/* REG5 Bit Definitions */ +#define ADF4350_REG5_LD_PIN_MODE_LOW (0 << 22) +#define ADF4350_REG5_LD_PIN_MODE_DIGITAL (1 << 22) +#define ADF4350_REG5_LD_PIN_MODE_HIGH (3 << 22) + +/* Specifications */ +#define ADF4350_MAX_OUT_FREQ 4400000000ULL /* Hz */ +#define ADF4350_MIN_OUT_FREQ 137500000 /* Hz */ +#define ADF4351_MIN_OUT_FREQ 34375000 /* Hz */ +#define ADF4350_MIN_VCO_FREQ 2200000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_45_PRESC 3000000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_PFD 32000000 /* Hz */ +#define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ +#define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ +#define ADF4350_MAX_MODULUS 4095 + +/** + * struct adf4350_platform_data - platform specific information + * @name: Optional device name. + * @clkin: REFin frequency in Hz. + * @channel_spacing: Channel spacing in Hz (influences MODULUS). + * @power_up_frequency: Optional, If set in Hz the PLL tunes to the desired + * frequency on probe. + * @ref_div_factor: Optional, if set the driver skips dynamic calculation + * and uses this default value instead. + * @ref_doubler_en: Enables reference doubler. + * @ref_div2_en: Enables reference divider. + * @r2_user_settings: User defined settings for ADF4350/1 REGISTER_2. + * @r3_user_settings: User defined settings for ADF4350/1 REGISTER_3. + * @r4_user_settings: User defined settings for ADF4350/1 REGISTER_4. + * @gpio_lock_detect: Optional, if set with a valid GPIO number, + * pll lock state is tested upon read. + * If not used - set to -1. + */ + +struct adf4350_platform_data { + char name[32]; + unsigned long clkin; + unsigned long channel_spacing; + unsigned long long power_up_frequency; + + unsigned short ref_div_factor; /* 10-bit R counter */ + bool ref_doubler_en; + bool ref_div2_en; + + unsigned r2_user_settings; + unsigned r3_user_settings; + unsigned r4_user_settings; + int gpio_lock_detect; +}; + +#endif /* IIO_PLL_ADF4350_H_ */ -- GitLab From 44dd5b02530a5aaea16c1a0a9eea377407445b4a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Jun 2012 11:34:49 +0530 Subject: [PATCH 0283/5711] staging: iio: Remove version.h header file inclusion version.h header file is no longer required. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index c3b05a1b3ea8..040da4acc66e 100755 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include -- GitLab From e4e8b7765867e8f4705bcc18b8930edbe0e4ef3c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 10:50:02 +0200 Subject: [PATCH 0284/5711] iio: Add iio_device_get() This patch add the iio_device_get() function, which increases the reference count of a iio device. The matching function to decrease the reference count - iio_device_put() - already exists. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3a4f6a3ab80d..3238fa3374f7 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -438,6 +438,17 @@ static inline struct iio_dev *dev_to_iio_dev(struct device *dev) return container_of(dev, struct iio_dev, dev); } +/** + * iio_device_get() - increment reference count for the device + * @indio_dev: IIO device structure + * + * Returns: The passed IIO device + **/ +static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev) +{ + return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL; +} + /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** -- GitLab From 1875ffd218ddafd78f0f8e78198c137cef97fd8a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 10:50:03 +0200 Subject: [PATCH 0285/5711] iio:inkern: Use iio_device_{get,put} Use iio_device_get and iio_device_put instead of open-coding it. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/iio/inkern.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 922645893dc8..d4760bd1e9b1 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -125,7 +125,7 @@ struct iio_channel *iio_st_channel_get(const char *name, strcmp(channel_name, c_i->map->consumer_channel) != 0)) continue; c = c_i; - get_device(&c->indio_dev->dev); + iio_device_get(c->indio_dev); break; } mutex_unlock(&iio_map_list_lock); @@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(iio_st_channel_get); void iio_st_channel_release(struct iio_channel *channel) { - put_device(&channel->indio_dev->dev); + iio_device_put(channel->indio_dev); kfree(channel); } EXPORT_SYMBOL_GPL(iio_st_channel_release); @@ -195,10 +195,10 @@ struct iio_channel *iio_st_channel_get_all(const char *name) c->map->adc_channel_label); if (chans[mapind].channel == NULL) { ret = -EINVAL; - put_device(&chans[mapind].indio_dev->dev); + iio_device_put(chans[mapind].indio_dev); goto error_free_chans; } - get_device(&chans[mapind].indio_dev->dev); + iio_device_get(chans[mapind].indio_dev); mapind++; } mutex_unlock(&iio_map_list_lock); @@ -210,8 +210,7 @@ struct iio_channel *iio_st_channel_get_all(const char *name) error_free_chans: for (i = 0; i < nummaps; i++) - if (chans[i].indio_dev) - put_device(&chans[i].indio_dev->dev); + iio_device_put(chans[i].indio_dev); kfree(chans); error_ret: mutex_unlock(&iio_map_list_lock); @@ -225,7 +224,7 @@ void iio_st_channel_release_all(struct iio_channel *channels) struct iio_channel *chan = &channels[0]; while (chan->indio_dev) { - put_device(&chan->indio_dev->dev); + iio_device_put(chan->indio_dev); chan++; } kfree(channels); -- GitLab From 5212cc8a9d833791a7aec566db136e78951f203d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:11 +0200 Subject: [PATCH 0286/5711] iio: Add helper functions for enum style channel attributes We often have the case were we do have a enum style channel attribute. These attributes have in common that they are a list of string values which usually map in a 1-to-1 fashion to integer values. This patch implements some common helper code for implementing enum style channel attributes using extended channel attributes. The helper functions take care of converting between the string and integer values, as well providing a function for "_available" attributes which list all available enum items. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 63 ++++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 1ddd8861c71b..56a3c0bc996c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -289,6 +289,69 @@ static ssize_t iio_write_channel_ext_info(struct device *dev, this_attr->c, buf, len); } +ssize_t iio_enum_available_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + unsigned int i; + size_t len = 0; + + if (!e->num_items) + return 0; + + for (i = 0; i < e->num_items; ++i) + len += snprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); + + /* replace last space with a newline */ + buf[len - 1] = '\n'; + + return len; +} +EXPORT_SYMBOL_GPL(iio_enum_available_read); + +ssize_t iio_enum_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + int i; + + if (!e->get) + return -EINVAL; + + i = e->get(indio_dev, chan); + if (i < 0) + return i; + else if (i >= e->num_items) + return -EINVAL; + + return sprintf(buf, "%s\n", e->items[i]); +} +EXPORT_SYMBOL_GPL(iio_enum_read); + +ssize_t iio_enum_write(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + unsigned int i; + int ret; + + if (!e->set) + return -EINVAL; + + for (i = 0; i < e->num_items; i++) { + if (sysfs_streq(buf, e->items[i])) + break; + } + + if (i == e->num_items) + return -EINVAL; + + ret = e->set(indio_dev, chan, i); + return ret ? ret : len; +} +EXPORT_SYMBOL_GPL(iio_enum_write); + static ssize_t iio_read_channel_info(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3238fa3374f7..944c63511731 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -129,6 +129,70 @@ struct iio_chan_spec_ext_info { uintptr_t private; }; +/** + * struct iio_enum - Enum channel info attribute + * items: A array of strings. + * num_items: Length of the item array. + * set: Set callback function, may be NULL. + * get: Get callback function, may be NULL. + * + * The iio_enum struct can be used to implement enum style channel attributes. + * Enum style attributes are those which have a set of strings which map to + * unsigned integer values. The IIO enum helper code takes care of mapping + * between value and string as well as generating a "_available" file which + * contains a list of all available items. The set callback will be called when + * the attribute is updated. The last parameter is the index to the newly + * activated item. The get callback will be used to query the currently active + * item and is supposed to return the index for it. + */ +struct iio_enum { + const char * const *items; + unsigned int num_items; + int (*set)(struct iio_dev *, const struct iio_chan_spec *, unsigned int); + int (*get)(struct iio_dev *, const struct iio_chan_spec *); +}; + +ssize_t iio_enum_available_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf); +ssize_t iio_enum_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf); +ssize_t iio_enum_write(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, + size_t len); + +/** + * IIO_ENUM() - Initialize enum extended channel attribute + * @_name: Attribute name + * @_shared: Whether the attribute is shared between all channels + * @_e: Pointer to a iio_enum struct + * + * This should usually be used together with IIO_ENUM_AVAILABLE() + */ +#define IIO_ENUM(_name, _shared, _e) \ +{ \ + .name = (_name), \ + .shared = (_shared), \ + .read = iio_enum_read, \ + .write = iio_enum_write, \ + .private = (uintptr_t)(_e), \ +} + +/** + * IIO_ENUM_AVAILABLE() - Initialize enum available extended channel attribute + * @_name: Attribute name ("_available" will be appended to the name) + * @_e: Pointer to a iio_enum struct + * + * Creates a read only attribute which list all the available enum items in a + * space separated list. This should usually be used together with IIO_ENUM() + */ +#define IIO_ENUM_AVAILABLE(_name, _e) \ +{ \ + .name = (_name "_available"), \ + .shared = true, \ + .read = iio_enum_available_read, \ + .private = (uintptr_t)(_e), \ +} + /** * struct iio_chan_spec - specification of a single channel * @type: What type of measurement is the channel making. -- GitLab From 26628f6b53d1ae3610146607c0c7fcbaf403bee7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:12 +0200 Subject: [PATCH 0287/5711] staging:iio:dac:ad5064: Use iio_enum for powerdown modes This allows us to remove some boilerplate code for comparing and formatting the enum strings. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5064.c | 65 +++++++++++--------------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 047148aa66b2..2394f05182ca 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -136,57 +136,42 @@ static int ad5064_sync_powerdown_mode(struct ad5064_state *st, return ret; } -static const char ad5064_powerdown_modes[][15] = { - [AD5064_LDAC_PWRDN_NONE] = "", - [AD5064_LDAC_PWRDN_1K] = "1kohm_to_gnd", - [AD5064_LDAC_PWRDN_100K] = "100kohm_to_gnd", - [AD5064_LDAC_PWRDN_3STATE] = "three_state", +static const char * const ad5064_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state", }; -static ssize_t ad5064_read_powerdown_mode_available(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, char *buf) -{ - return sprintf(buf, "%s %s %s\n", ad5064_powerdown_modes[1], - ad5064_powerdown_modes[2], ad5064_powerdown_modes[3]); -} - -static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, char *buf) +static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { struct ad5064_state *st = iio_priv(indio_dev); - return sprintf(buf, "%s\n", - ad5064_powerdown_modes[st->pwr_down_mode[chan->channel]]); + return st->pwr_down_mode[chan->channel] - 1; } -static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, const char *buf, - size_t len) +static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { struct ad5064_state *st = iio_priv(indio_dev); - unsigned int mode, i; int ret; - mode = 0; - - for (i = 1; i < ARRAY_SIZE(ad5064_powerdown_modes); ++i) { - if (sysfs_streq(buf, ad5064_powerdown_modes[i])) { - mode = i; - break; - } - } - if (mode == 0) - return -EINVAL; - mutex_lock(&indio_dev->mlock); - st->pwr_down_mode[chan->channel] = mode; + st->pwr_down_mode[chan->channel] = mode + 1; ret = ad5064_sync_powerdown_mode(st, chan->channel); mutex_unlock(&indio_dev->mlock); - return ret ? ret : len; + return ret; } +static const struct iio_enum ad5064_powerdown_mode_enum = { + .items = ad5064_powerdown_modes, + .num_items = ARRAY_SIZE(ad5064_powerdown_modes), + .get = ad5064_get_powerdown_mode, + .set = ad5064_set_powerdown_mode, +}; + static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, char *buf) { @@ -286,22 +271,14 @@ static const struct iio_info ad5064_info = { .driver_module = THIS_MODULE, }; -static struct iio_chan_spec_ext_info ad5064_ext_info[] = { +static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { { .name = "powerdown", .read = ad5064_read_dac_powerdown, .write = ad5064_write_dac_powerdown, }, - { - .name = "powerdown_mode", - .read = ad5064_read_powerdown_mode, - .write = ad5064_write_powerdown_mode, - }, - { - .name = "powerdown_mode_available", - .shared = true, - .read = ad5064_read_powerdown_mode_available, - }, + IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), { }, }; -- GitLab From 09d48aa9f67e05770c48df6437a753b9c4d4469a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:13 +0200 Subject: [PATCH 0288/5711] staging:iio:dac:ad5446: Use iio_enum for powerdown modes This allows us to remove some boilerplate code for comparing and formatting the enum strings. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5446.c | 55 +++++++++++--------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index daa65b384c13..1774f7f15d36 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -42,47 +42,34 @@ static int ad5660_write(struct ad5446_state *st, unsigned val) } static const char * const ad5446_powerdown_modes[] = { - "", "1kohm_to_gnd", "100kohm_to_gnd", "three_state" + "1kohm_to_gnd", "100kohm_to_gnd", "three_state" }; -static ssize_t ad5446_read_powerdown_mode_available(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, char *buf) -{ - return sprintf(buf, "%s %s %s\n", ad5446_powerdown_modes[1], - ad5446_powerdown_modes[2], ad5446_powerdown_modes[3]); -} - -static ssize_t ad5446_write_powerdown_mode(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - const char *buf, size_t len) +static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { struct ad5446_state *st = iio_priv(indio_dev); - int i; - - for (i = 1; i < ARRAY_SIZE(ad5446_powerdown_modes); i++) { - if (sysfs_streq(buf, ad5446_powerdown_modes[i])) { - st->pwr_down_mode = i; - break; - } - } - if (i == ARRAY_SIZE(ad5446_powerdown_modes)) - return -EINVAL; + st->pwr_down_mode = mode + 1; - return len; + return 0; } -static ssize_t ad5446_read_powerdown_mode(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - char *buf) +static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { struct ad5446_state *st = iio_priv(indio_dev); - return sprintf(buf, "%s\n", ad5446_powerdown_modes[st->pwr_down_mode]); + return st->pwr_down_mode - 1; } +static const struct iio_enum ad5446_powerdown_mode_enum = { + .items = ad5446_powerdown_modes, + .num_items = ARRAY_SIZE(ad5446_powerdown_modes), + .get = ad5446_get_powerdown_mode, + .set = ad5446_set_powerdown_mode, +}; + static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, @@ -129,15 +116,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = { .name = "powerdown", .read = ad5446_read_dac_powerdown, .write = ad5446_write_dac_powerdown, - }, { - .name = "powerdown_mode", - .read = ad5446_read_powerdown_mode, - .write = ad5446_write_powerdown_mode, - }, { - .name = "powerdown_mode_available", - .shared = true, - .read = ad5446_read_powerdown_mode_available, }, + IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum), { }, }; @@ -321,6 +302,8 @@ static int __devinit ad5446_probe(struct spi_device *spi) indio_dev->channels = &st->chip_info->channel; indio_dev->num_channels = 1; + st->pwr_down_mode = MODE_PWRDWN_1k; + if (st->chip_info->int_vref_mv) st->vref_mv = st->chip_info->int_vref_mv; else if (voltage_uv) -- GitLab From 868e0862c9f6a8bd6bf42534b80e1e7bd230bf74 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:14 +0200 Subject: [PATCH 0289/5711] staging:iio:dac:ad5380: Convert to extended channel attributes Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5380.c | 250 ++++++++++++++----------------- 1 file changed, 116 insertions(+), 134 deletions(-) diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c index 370d2842190e..7a35cc6c4c67 100644 --- a/drivers/staging/iio/dac/ad5380.c +++ b/drivers/staging/iio/dac/ad5380.c @@ -81,103 +81,18 @@ enum ad5380_type { ID_AD5392_5, }; -#define AD5380_CHANNEL(_bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ - .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \ -} - -static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { - [ID_AD5380_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 40, - .int_vref = 1250000, - }, - [ID_AD5380_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 40, - .int_vref = 2500000, - }, - [ID_AD5381_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5381_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5382_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 32, - .int_vref = 1250000, - }, - [ID_AD5382_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 32, - .int_vref = 2500000, - }, - [ID_AD5383_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 32, - .int_vref = 1250000, - }, - [ID_AD5383_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 32, - .int_vref = 2500000, - }, - [ID_AD5390_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5390_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5391_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5391_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5392_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 8, - .int_vref = 1250000, - }, - [ID_AD5392_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 8, - .int_vref = 2500000, - }, -}; - -static ssize_t ad5380_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t ad5380_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5380_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", st->pwr_down); } -static ssize_t ad5380_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5380_state *st = iio_priv(indio_dev); bool pwr_down; int ret; @@ -200,20 +115,14 @@ static ssize_t ad5380_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_DEVICE_ATTR(out_voltage_powerdown, - S_IRUGO | S_IWUSR, - ad5380_read_dac_powerdown, - ad5380_write_dac_powerdown, 0); - -static const char ad5380_powerdown_modes[][15] = { - [0] = "100kohm_to_gnd", - [1] = "three_state", +static const char * const ad5380_powerdown_modes[] = { + "100kohm_to_gnd", + "three_state", }; -static ssize_t ad5380_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static int ad5380_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5380_state *st = iio_priv(indio_dev); unsigned int mode; int ret; @@ -224,49 +133,27 @@ static ssize_t ad5380_read_powerdown_mode(struct device *dev, mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1; - return sprintf(buf, "%s\n", ad5380_powerdown_modes[mode]); + return mode; } -static ssize_t ad5380_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static int ad5380_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5380_state *st = iio_priv(indio_dev); - unsigned int i; int ret; - for (i = 0; i < ARRAY_SIZE(ad5380_powerdown_modes); ++i) { - if (sysfs_streq(buf, ad5380_powerdown_modes[i])) - break; - } - - if (i == ARRAY_SIZE(ad5380_powerdown_modes)) - return -EINVAL; - ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL, 1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET, - i << AD5380_CTRL_PWR_DOWN_MODE_OFFSET); + mode << AD5380_CTRL_PWR_DOWN_MODE_OFFSET); - return ret ? ret : len; + return ret; } -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, - S_IRUGO | S_IWUSR, - ad5380_read_powerdown_mode, - ad5380_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "100kohm_to_gnd three_state"); - -static struct attribute *ad5380_attributes[] = { - &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5380_attribute_group = { - .attrs = ad5380_attributes, +static const struct iio_enum ad5380_powerdown_mode_enum = { + .items = ad5380_powerdown_modes, + .num_items = ARRAY_SIZE(ad5380_powerdown_modes), + .get = ad5380_get_powerdown_mode, + .set = ad5380_set_powerdown_mode, }; static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan, @@ -354,10 +241,105 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, static const struct iio_info ad5380_info = { .read_raw = ad5380_read_raw, .write_raw = ad5380_write_raw, - .attrs = &ad5380_attribute_group, .driver_module = THIS_MODULE, }; +static struct iio_chan_spec_ext_info ad5380_ext_info[] = { + { + .name = "powerdown", + .read = ad5380_read_dac_powerdown, + .write = ad5380_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum), + { }, +}; + +#define AD5380_CHANNEL(_bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)), \ + .ext_info = ad5380_ext_info, \ +} + +static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { + [ID_AD5380_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 40, + .int_vref = 1250000, + }, + [ID_AD5380_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 40, + .int_vref = 2500000, + }, + [ID_AD5381_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5381_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5382_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 32, + .int_vref = 1250000, + }, + [ID_AD5382_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 32, + .int_vref = 2500000, + }, + [ID_AD5383_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 32, + .int_vref = 1250000, + }, + [ID_AD5383_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 32, + .int_vref = 2500000, + }, + [ID_AD5390_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5390_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5391_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5391_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5392_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 8, + .int_vref = 1250000, + }, + [ID_AD5392_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 8, + .int_vref = 2500000, + }, +}; + static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) { struct ad5380_state *st = iio_priv(indio_dev); -- GitLab From 8d05d7773d644bbde98e27eeba0e8f6251b30d1e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:15 +0200 Subject: [PATCH 0290/5711] staging:iio:dac:ad5504: Convert to extended channel attributes Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5504.c | 163 +++++++++++-------------------- 1 file changed, 58 insertions(+), 105 deletions(-) diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 019cf15cd24a..acb1d59b2de4 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -22,24 +22,6 @@ #include "dac.h" #include "ad5504.h" -#define AD5504_CHANNEL(_chan) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (_chan), \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = AD5504_ADDR_DAC(_chan), \ - .scan_type = IIO_ST('u', 12, 16, 0), \ -} - -static const struct iio_chan_spec ad5504_channels[] = { - AD5504_CHANNEL(0), - AD5504_CHANNEL(1), - AD5504_CHANNEL(2), - AD5504_CHANNEL(3), -}; - static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) { u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | @@ -122,65 +104,61 @@ static int ad5504_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static ssize_t ad5504_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static const char * const ad5504_powerdown_modes[] = { + "20kohm_to_gnd", + "three_state", +}; + +static int ad5504_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5504_state *st = iio_priv(indio_dev); - const char mode[][14] = {"20kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); + return st->pwr_down_mode; } -static ssize_t ad5504_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ad5504_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5504_state *st = iio_priv(indio_dev); - int ret; - if (sysfs_streq(buf, "20kohm_to_gnd")) - st->pwr_down_mode = AD5504_DAC_PWRDN_20K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5504_DAC_PWRDN_3STATE; - else - ret = -EINVAL; + st->pwr_down_mode = mode; - return ret ? ret : len; + return 0; } -static ssize_t ad5504_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) +static const struct iio_enum ad5504_powerdown_mode_enum = { + .items = ad5504_powerdown_modes, + .num_items = ARRAY_SIZE(ad5504_powerdown_modes), + .get = ad5504_get_powerdown_mode, + .set = ad5504_set_powerdown_mode, +}; + +static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); return sprintf(buf, "%d\n", - !(st->pwr_down_mask & (1 << this_attr->address))); + !(st->pwr_down_mask & (1 << chan->channel))); } -static ssize_t ad5504_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { long readin; int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); ret = strict_strtol(buf, 10, &readin); if (ret) return ret; if (readin == 0) - st->pwr_down_mask |= (1 << this_attr->address); + st->pwr_down_mask |= (1 << chan->channel); else if (readin == 1) - st->pwr_down_mask &= ~(1 << this_attr->address); + st->pwr_down_mask &= ~(1 << chan->channel); else ret = -EINVAL; @@ -194,50 +172,6 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5504_read_powerdown_mode, - ad5504_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "20kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 3); - -static struct attribute *ad5504_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5504_attribute_group = { - .attrs = ad5504_attributes, -}; - -static struct attribute *ad5501_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5501_attribute_group = { - .attrs = ad5501_attributes, -}; - static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000"); static IIO_CONST_ATTR(temp0_thresh_rising_en, "1"); @@ -267,17 +201,38 @@ static irqreturn_t ad5504_event_handler(int irq, void *private) static const struct iio_info ad5504_info = { .write_raw = ad5504_write_raw, .read_raw = ad5504_read_raw, - .attrs = &ad5504_attribute_group, .event_attrs = &ad5504_ev_attribute_group, .driver_module = THIS_MODULE, }; -static const struct iio_info ad5501_info = { - .write_raw = ad5504_write_raw, - .read_raw = ad5504_read_raw, - .attrs = &ad5501_attribute_group, - .event_attrs = &ad5504_ev_attribute_group, - .driver_module = THIS_MODULE, +static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { + { + .name = "powerdown", + .read = ad5504_read_dac_powerdown, + .write = ad5504_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum), + { }, +}; + +#define AD5504_CHANNEL(_chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = AD5504_ADDR_DAC(_chan), \ + .scan_type = IIO_ST('u', 12, 16, 0), \ + .ext_info = ad5504_ext_info, \ +} + +static const struct iio_chan_spec ad5504_channels[] = { + AD5504_CHANNEL(0), + AD5504_CHANNEL(1), + AD5504_CHANNEL(2), + AD5504_CHANNEL(3), }; static int __devinit ad5504_probe(struct spi_device *spi) @@ -315,13 +270,11 @@ static int __devinit ad5504_probe(struct spi_device *spi) st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(st->spi)->name; - if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) { - indio_dev->info = &ad5501_info; + indio_dev->info = &ad5504_info; + if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) indio_dev->num_channels = 1; - } else { - indio_dev->info = &ad5504_info; + else indio_dev->num_channels = 4; - } indio_dev->channels = ad5504_channels; indio_dev->modes = INDIO_DIRECT_MODE; -- GitLab From 66eb90505eaf38f3e88491eb9090cd7be7c2da03 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:16 +0200 Subject: [PATCH 0291/5711] staging:iio:dac:ad5624r: Convert to extended channel attributes Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5624r_spi.c | 208 +++++++++++--------------- 1 file changed, 90 insertions(+), 118 deletions(-) diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 42ff644ac43e..4c95eae1f3ac 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -21,56 +21,6 @@ #include "dac.h" #include "ad5624r.h" -#define AD5624R_CHANNEL(_chan, _bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (_chan), \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = (_chan), \ - .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ -} - -#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ - const struct iio_chan_spec _name##_channels[] = { \ - AD5624R_CHANNEL(0, _bits), \ - AD5624R_CHANNEL(1, _bits), \ - AD5624R_CHANNEL(2, _bits), \ - AD5624R_CHANNEL(3, _bits), \ -} - -static DECLARE_AD5624R_CHANNELS(ad5624r, 12); -static DECLARE_AD5624R_CHANNELS(ad5644r, 14); -static DECLARE_AD5624R_CHANNELS(ad5664r, 16); - -static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { - [ID_AD5624R3] = { - .channels = ad5624r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5624R5] = { - .channels = ad5624r_channels, - .int_vref_mv = 2500, - }, - [ID_AD5644R3] = { - .channels = ad5644r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5644R5] = { - .channels = ad5644r_channels, - .int_vref_mv = 2500, - }, - [ID_AD5664R3] = { - .channels = ad5664r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5664R5] = { - .channels = ad5664r_channels, - .int_vref_mv = 2500, - }, -}; - static int ad5624r_spi_write(struct spi_device *spi, u8 cmd, u8 addr, u16 val, u8 len) { @@ -138,67 +88,62 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static ssize_t ad5624r_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static const char * const ad5624r_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state" +}; + +static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5624r_state *st = iio_priv(indio_dev); - char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); + return st->pwr_down_mode; } -static ssize_t ad5624r_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5624r_state *st = iio_priv(indio_dev); - int ret; - if (sysfs_streq(buf, "1kohm_to_gnd")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_1K; - else if (sysfs_streq(buf, "100kohm_to_gnd")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_100K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_3STATE; - else - ret = -EINVAL; + st->pwr_down_mode = mode; - return ret ? ret : len; + return 0; } -static ssize_t ad5624r_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) +static const struct iio_enum ad5624r_powerdown_mode_enum = { + .items = ad5624r_powerdown_modes, + .num_items = ARRAY_SIZE(ad5624r_powerdown_modes), + .get = ad5624r_get_powerdown_mode, + .set = ad5624r_set_powerdown_mode, +}; + +static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5624r_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); return sprintf(buf, "%d\n", - !!(st->pwr_down_mask & (1 << this_attr->address))); + !!(st->pwr_down_mask & (1 << chan->channel))); } -static ssize_t ad5624r_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { long readin; int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5624r_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); ret = strict_strtol(buf, 10, &readin); if (ret) return ret; if (readin == 1) - st->pwr_down_mask |= (1 << this_attr->address); + st->pwr_down_mask |= (1 << chan->channel); else if (!readin) - st->pwr_down_mask &= ~(1 << this_attr->address); + st->pwr_down_mask &= ~(1 << chan->channel); else ret = -EINVAL; @@ -209,47 +154,74 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5624r_read_powerdown_mode, - ad5624r_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 3); - -static struct attribute *ad5624r_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5624r_attribute_group = { - .attrs = ad5624r_attributes, -}; - static const struct iio_info ad5624r_info = { .write_raw = ad5624r_write_raw, .read_raw = ad5624r_read_raw, - .attrs = &ad5624r_attribute_group, .driver_module = THIS_MODULE, }; +static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { + { + .name = "powerdown", + .read = ad5624r_read_dac_powerdown, + .write = ad5624r_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum), + { }, +}; + +#define AD5624R_CHANNEL(_chan, _bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = (_chan), \ + .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ + .ext_info = ad5624r_ext_info, \ +} + +#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ + const struct iio_chan_spec _name##_channels[] = { \ + AD5624R_CHANNEL(0, _bits), \ + AD5624R_CHANNEL(1, _bits), \ + AD5624R_CHANNEL(2, _bits), \ + AD5624R_CHANNEL(3, _bits), \ +} + +static DECLARE_AD5624R_CHANNELS(ad5624r, 12); +static DECLARE_AD5624R_CHANNELS(ad5644r, 14); +static DECLARE_AD5624R_CHANNELS(ad5664r, 16); + +static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { + [ID_AD5624R3] = { + .channels = ad5624r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5624R5] = { + .channels = ad5624r_channels, + .int_vref_mv = 2500, + }, + [ID_AD5644R3] = { + .channels = ad5644r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5644R5] = { + .channels = ad5644r_channels, + .int_vref_mv = 2500, + }, + [ID_AD5664R3] = { + .channels = ad5664r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5664R5] = { + .channels = ad5664r_channels, + .int_vref_mv = 2500, + }, +}; + static int __devinit ad5624r_probe(struct spi_device *spi) { struct ad5624r_state *st; -- GitLab From fe4586a8753117a089acb54f75870d07c8e474d0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:17 +0200 Subject: [PATCH 0292/5711] staging:iio:dac:ad5686: Convert to extended channel attributes Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5686.c | 196 +++++++++++++------------------ 1 file changed, 80 insertions(+), 116 deletions(-) diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index c1e903ebc7b9..f07e19721c9a 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -93,40 +93,6 @@ enum ad5686_supported_device_ids { ID_AD5685, ID_AD5686, }; -#define AD5868_CHANNEL(chan, bits, shift) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = chan, \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = AD5686_ADDR_DAC(chan), \ - .scan_type = IIO_ST('u', bits, 16, shift) \ -} -static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { - [ID_AD5684] = { - .channel[0] = AD5868_CHANNEL(0, 12, 4), - .channel[1] = AD5868_CHANNEL(1, 12, 4), - .channel[2] = AD5868_CHANNEL(2, 12, 4), - .channel[3] = AD5868_CHANNEL(3, 12, 4), - .int_vref_mv = 2500, - }, - [ID_AD5685] = { - .channel[0] = AD5868_CHANNEL(0, 14, 2), - .channel[1] = AD5868_CHANNEL(1, 14, 2), - .channel[2] = AD5868_CHANNEL(2, 14, 2), - .channel[3] = AD5868_CHANNEL(3, 14, 2), - .int_vref_mv = 2500, - }, - [ID_AD5686] = { - .channel[0] = AD5868_CHANNEL(0, 16, 0), - .channel[1] = AD5868_CHANNEL(1, 16, 0), - .channel[2] = AD5868_CHANNEL(2, 16, 0), - .channel[3] = AD5868_CHANNEL(3, 16, 0), - .int_vref_mv = 2500, - }, -}; - static int ad5686_spi_write(struct ad5686_state *st, u8 cmd, u8 addr, u16 val, u8 shift) { @@ -170,73 +136,63 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr) return be32_to_cpu(st->data[2].d32); } -static ssize_t ad5686_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static const char * const ad5686_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state" +}; + +static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >> - (this_attr->address * 2)) & 0x3]); + return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1; } -static ssize_t ad5686_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned mode; - - if (sysfs_streq(buf, "1kohm_to_gnd")) - mode = AD5686_LDAC_PWRDN_1K; - else if (sysfs_streq(buf, "100kohm_to_gnd")) - mode = AD5686_LDAC_PWRDN_100K; - else if (sysfs_streq(buf, "three_state")) - mode = AD5686_LDAC_PWRDN_3STATE; - else - return -EINVAL; - st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2)); - st->pwr_down_mode |= (mode << (this_attr->address * 2)); + st->pwr_down_mode &= ~(0x3 << (chan->channel * 2)); + st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2)); - return len; + return 0; } -static ssize_t ad5686_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) +static const struct iio_enum ad5686_powerdown_mode_enum = { + .items = ad5686_powerdown_modes, + .num_items = ARRAY_SIZE(ad5686_powerdown_modes), + .get = ad5686_get_powerdown_mode, + .set = ad5686_set_powerdown_mode, +}; + +static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); return sprintf(buf, "%d\n", !!(st->pwr_down_mask & - (0x3 << (this_attr->address * 2)))); + (0x3 << (chan->channel * 2)))); } -static ssize_t ad5686_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { bool readin; int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); ret = strtobool(buf, &readin); if (ret) return ret; if (readin == true) - st->pwr_down_mask |= (0x3 << (this_attr->address * 2)); + st->pwr_down_mask |= (0x3 << (chan->channel * 2)); else - st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2)); + st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0, st->pwr_down_mask & st->pwr_down_mode, 0); @@ -244,48 +200,6 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown_mode, \ - S_IRUGO | S_IWUSR, \ - ad5686_read_powerdown_mode, \ - ad5686_write_powerdown_mode, _num) - -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, \ - ad5686_read_dac_powerdown, \ - ad5686_write_dac_powerdown, _num) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3); - -static struct attribute *ad5686_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5686_attribute_group = { - .attrs = ad5686_attributes, -}; - static int ad5686_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -349,10 +263,57 @@ static int ad5686_write_raw(struct iio_dev *indio_dev, static const struct iio_info ad5686_info = { .read_raw = ad5686_read_raw, .write_raw = ad5686_write_raw, - .attrs = &ad5686_attribute_group, .driver_module = THIS_MODULE, }; +static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { + { + .name = "powerdown", + .read = ad5686_read_dac_powerdown, + .write = ad5686_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum), + { }, +}; + +#define AD5868_CHANNEL(chan, bits, shift) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = AD5686_ADDR_DAC(chan), \ + .scan_type = IIO_ST('u', bits, 16, shift), \ + .ext_info = ad5686_ext_info, \ +} + +static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { + [ID_AD5684] = { + .channel[0] = AD5868_CHANNEL(0, 12, 4), + .channel[1] = AD5868_CHANNEL(1, 12, 4), + .channel[2] = AD5868_CHANNEL(2, 12, 4), + .channel[3] = AD5868_CHANNEL(3, 12, 4), + .int_vref_mv = 2500, + }, + [ID_AD5685] = { + .channel[0] = AD5868_CHANNEL(0, 14, 2), + .channel[1] = AD5868_CHANNEL(1, 14, 2), + .channel[2] = AD5868_CHANNEL(2, 14, 2), + .channel[3] = AD5868_CHANNEL(3, 14, 2), + .int_vref_mv = 2500, + }, + [ID_AD5686] = { + .channel[0] = AD5868_CHANNEL(0, 16, 0), + .channel[1] = AD5868_CHANNEL(1, 16, 0), + .channel[2] = AD5868_CHANNEL(2, 16, 0), + .channel[3] = AD5868_CHANNEL(3, 16, 0), + .int_vref_mv = 2500, + }, +}; + + static int __devinit ad5686_probe(struct spi_device *spi) { struct ad5686_state *st; @@ -385,6 +346,9 @@ static int __devinit ad5686_probe(struct spi_device *spi) st->spi = spi; + /* Set all the power down mode for all channels to 1K pulldown */ + st->pwr_down_mode = 0x55; + indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5686_info; -- GitLab From 4571b39b0b08ff855707011c6f7fa04ceb43e5ca Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:18 +0200 Subject: [PATCH 0293/5711] staging:iio:dac:ad5791: Convert to extended channel attributes Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5791.c | 122 ++++++++++++++----------------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index 13d8b5bb1cea..ad33725dd3a4 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -72,71 +72,50 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) return ret; } -#define AD5791_CHAN(bits, shift) { \ - .type = IIO_VOLTAGE, \ - .output = 1, \ - .indexed = 1, \ - .address = AD5791_ADDR_DAC0, \ - .channel = 0, \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ - .scan_type = IIO_ST('u', bits, 24, shift) \ -} - -static const struct iio_chan_spec ad5791_channels[] = { - [ID_AD5760] = AD5791_CHAN(16, 4), - [ID_AD5780] = AD5791_CHAN(18, 2), - [ID_AD5781] = AD5791_CHAN(18, 2), - [ID_AD5791] = AD5791_CHAN(20, 0) +static const char * const ad5791_powerdown_modes[] = { + "6kohm_to_gnd", + "three_state", }; -static ssize_t ad5791_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5791_state *st = iio_priv(indio_dev); - const char mode[][14] = {"6kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); + return st->pwr_down_mode; } -static ssize_t ad5791_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5791_state *st = iio_priv(indio_dev); - int ret; - if (sysfs_streq(buf, "6kohm_to_gnd")) - st->pwr_down_mode = AD5791_DAC_PWRDN_6K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE; - else - ret = -EINVAL; + st->pwr_down_mode = mode; - return ret ? ret : len; + return 0; } -static ssize_t ad5791_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) +static const struct iio_enum ad5791_powerdown_mode_enum = { + .items = ad5791_powerdown_modes, + .num_items = ARRAY_SIZE(ad5791_powerdown_modes), + .get = ad5791_get_powerdown_mode, + .set = ad5791_set_powerdown_mode, +}; + +static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5791_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", st->pwr_down); } -static ssize_t ad5791_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { long readin; int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5791_state *st = iio_priv(indio_dev); ret = strict_strtol(buf, 10, &readin); @@ -160,31 +139,6 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5791_read_powerdown_mode, - ad5791_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "6kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown, - ad5791_write_dac_powerdown, 0); - -static struct attribute *ad5791_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5791_attribute_group = { - .attrs = ad5791_attributes, -}; - static int ad5791_get_lin_comp(unsigned int span) { if (span <= 10000) @@ -254,6 +208,37 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, }; +static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { + { + .name = "powerdown", + .shared = true, + .read = ad5791_read_dac_powerdown, + .write = ad5791_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum), + { }, +}; + +#define AD5791_CHAN(bits, shift) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .address = AD5791_ADDR_DAC0, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ + .scan_type = IIO_ST('u', bits, 24, shift), \ + .ext_info = ad5791_ext_info, \ +} + +static const struct iio_chan_spec ad5791_channels[] = { + [ID_AD5760] = AD5791_CHAN(16, 4), + [ID_AD5780] = AD5791_CHAN(18, 2), + [ID_AD5781] = AD5791_CHAN(18, 2), + [ID_AD5791] = AD5791_CHAN(20, 0) +}; static int ad5791_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -278,7 +263,6 @@ static int ad5791_write_raw(struct iio_dev *indio_dev, static const struct iio_info ad5791_info = { .read_raw = &ad5791_read_raw, .write_raw = &ad5791_write_raw, - .attrs = &ad5791_attribute_group, .driver_module = THIS_MODULE, }; -- GitLab From cadb695113f6f30b0a19a0437dbcf000e1d3419a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:19 +0200 Subject: [PATCH 0294/5711] staging:iio:dac: Remove unused dac.h includes None of these drivers use anything from dac.h, so remove the include. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5064.c | 1 - drivers/staging/iio/dac/ad5360.c | 1 - drivers/staging/iio/dac/ad5380.c | 2 -- drivers/staging/iio/dac/ad5421.c | 1 - drivers/staging/iio/dac/ad5446.c | 1 - drivers/staging/iio/dac/ad5504.c | 2 +- drivers/staging/iio/dac/ad5624r_spi.c | 2 +- drivers/staging/iio/dac/ad5686.c | 1 - drivers/staging/iio/dac/ad5764.c | 1 - drivers/staging/iio/dac/ad5791.c | 2 +- 10 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 2394f05182ca..276af02520af 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -18,7 +18,6 @@ #include #include -#include "dac.h" #define AD5064_MAX_DAC_CHANNELS 8 #define AD5064_MAX_VREFS 4 diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index 38660efca78a..8fce84fe70b1 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -18,7 +18,6 @@ #include #include -#include "dac.h" #define AD5360_CMD(x) ((x) << 22) #define AD5360_ADDR(x) ((x) << 16) diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c index 7a35cc6c4c67..5dfb4451728f 100644 --- a/drivers/staging/iio/dac/ad5380.c +++ b/drivers/staging/iio/dac/ad5380.c @@ -20,8 +20,6 @@ #include #include -#include "dac.h" - #define AD5380_REG_DATA(x) (((x) << 2) | 3) #define AD5380_REG_OFFSET(x) (((x) << 2) | 2) diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c index ffbd4c234f57..ea2f83b4e357 100644 --- a/drivers/staging/iio/dac/ad5421.c +++ b/drivers/staging/iio/dac/ad5421.c @@ -19,7 +19,6 @@ #include #include #include -#include "dac.h" #include "ad5421.h" diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 1774f7f15d36..49f557fc673b 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -20,7 +20,6 @@ #include #include -#include "dac.h" #include "ad5446.h" diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index acb1d59b2de4..331b536ec8aa 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -19,7 +19,7 @@ #include #include #include -#include "dac.h" + #include "ad5504.h" static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 4c95eae1f3ac..7524f96b8e52 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -18,7 +18,7 @@ #include #include -#include "dac.h" + #include "ad5624r.h" static int ad5624r_spi_write(struct spi_device *spi, diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index f07e19721c9a..6948d75e1036 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -18,7 +18,6 @@ #include #include -#include "dac.h" #define AD5686_DAC_CHANNELS 4 diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c index 03dbd937b081..ffce30447445 100644 --- a/drivers/staging/iio/dac/ad5764.c +++ b/drivers/staging/iio/dac/ad5764.c @@ -18,7 +18,6 @@ #include #include -#include "dac.h" #define AD5764_REG_SF_NOP 0x0 #define AD5764_REG_SF_CONFIG 0x1 diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index ad33725dd3a4..4e955ed9451d 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -19,7 +19,7 @@ #include #include -#include "dac.h" + #include "ad5791.h" static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) -- GitLab From 4cd8d87446d521b7824aa1be84d767c8b5300601 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:20 +0200 Subject: [PATCH 0295/5711] staging:iio:dac:max517: Convert to channel spec Convert the max517 driver to channel spec. As part of the conversion the "out_voltage_1&2_raw" property, which updates both channel 1 and 2 simultaneously with the same value, is lost, since this is not really covered by the IIO spec and has only a limited use case in practice. Also the channel index for the sysfs files is now zero based instead of one based, which means all channel numbers will be lower by one. E.g. "out_voltage_1_scale" instead of "out_voltage_2_scale" Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Acked-by: Roland Stigge Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/max517.c | 172 +++++++++++-------------------- 1 file changed, 61 insertions(+), 111 deletions(-) diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c index 5287cad1f3a4..403e06fbc39e 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -27,7 +27,6 @@ #include #include -#include "dac.h" #include "max517.h" @@ -55,129 +54,67 @@ struct max517_data { * bit 1: channel 2 * (this way, it's possible to set both channels at once) */ -static ssize_t max517_set_value(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count, int channel) +static int max517_set_value(struct iio_dev *indio_dev, + long val, int channel) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct max517_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - u8 outbuf[4]; /* 1x or 2x command + value */ - int outbuf_size = 0; + u8 outbuf[2]; int res; - long val; - - res = strict_strtol(buf, 10, &val); - - if (res) - return res; if (val < 0 || val > 255) return -EINVAL; - if (channel & 1) { - outbuf[outbuf_size++] = COMMAND_CHANNEL0; - outbuf[outbuf_size++] = val; - } - if (channel & 2) { - outbuf[outbuf_size++] = COMMAND_CHANNEL1; - outbuf[outbuf_size++] = val; - } + outbuf[0] = channel; + outbuf[1] = val; - /* - * At this point, there are always 1 or 2 two-byte commands in - * outbuf. With 2 commands, the device can set two outputs - * simultaneously, latching the values upon the end of the I2C - * transfer. - */ - - res = i2c_master_send(client, outbuf, outbuf_size); + res = i2c_master_send(client, outbuf, 2); if (res < 0) return res; - - return count; -} - -static ssize_t max517_set_value_1(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 1); -} -static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0); - -static ssize_t max517_set_value_2(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 2); -} -static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1); - -static ssize_t max517_set_value_both(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 3); + else if (res != 2) + return -EIO; + else + return 0; } -static IIO_DEVICE_ATTR_NAMED(out_voltage1and2_raw, - out_voltage1&2_raw, S_IWUSR, NULL, - max517_set_value_both, -1); -static ssize_t max517_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf, int channel) +static int max517_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct max517_data *data = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); + unsigned int scale_uv; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + /* Corresponds to Vref / 2^(bits) */ + scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8; + *val = scale_uv / 1000000; + *val2 = scale_uv % 1000000; + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + return -EINVAL; } -static ssize_t max517_show_scale1(struct device *dev, - struct device_attribute *attr, - char *buf) +static int max517_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) { - return max517_show_scale(dev, attr, buf, 1); -} -static IIO_DEVICE_ATTR(out_voltage1_scale, S_IRUGO, - max517_show_scale1, NULL, 0); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = max517_set_value(indio_dev, val, chan->channel); + break; + default: + ret = -EINVAL; + break; + } -static ssize_t max517_show_scale2(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return max517_show_scale(dev, attr, buf, 2); + return ret; } -static IIO_DEVICE_ATTR(out_voltage2_scale, S_IRUGO, - max517_show_scale2, NULL, 0); - -/* On MAX517 variant, we have one output */ -static struct attribute *max517_attributes[] = { - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_scale.dev_attr.attr, - NULL -}; - -static struct attribute_group max517_attribute_group = { - .attrs = max517_attributes, -}; - -/* On MAX518 and MAX519 variant, we have two outputs */ -static struct attribute *max518_attributes[] = { - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_scale.dev_attr.attr, - &iio_dev_attr_out_voltage2_raw.dev_attr.attr, - &iio_dev_attr_out_voltage2_scale.dev_attr.attr, - &iio_dev_attr_out_voltage1and2_raw.dev_attr.attr, - NULL -}; - -static struct attribute_group max518_attribute_group = { - .attrs = max518_attributes, -}; #ifdef CONFIG_PM_SLEEP static int max517_suspend(struct device *dev) @@ -201,13 +138,24 @@ static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); #endif static const struct iio_info max517_info = { - .attrs = &max517_attribute_group, + .read_raw = max517_read_raw, + .write_raw = max517_write_raw, .driver_module = THIS_MODULE, }; -static const struct iio_info max518_info = { - .attrs = &max518_attribute_group, - .driver_module = THIS_MODULE, +#define MAX517_CHANNEL(chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', 8, 8, 0), \ +} + +static const struct iio_chan_spec max517_channels[] = { + MAX517_CHANNEL(0), + MAX517_CHANNEL(1) }; static int max517_probe(struct i2c_client *client, @@ -230,12 +178,14 @@ static int max517_probe(struct i2c_client *client, /* establish that the iio_dev is a child of the i2c device */ indio_dev->dev.parent = &client->dev; - /* reduced attribute set for MAX517 */ + /* reduced channel set for MAX517 */ if (id->driver_data == ID_MAX517) - indio_dev->info = &max517_info; + indio_dev->num_channels = 1; else - indio_dev->info = &max518_info; + indio_dev->num_channels = 2; + indio_dev->channels = max517_channels; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &max517_info; /* * Reference voltage on MAX518 and default is 5V, else take vref_mv -- GitLab From 159fe695ae2ad53b915465f30ddd0fbc7f014900 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:21 +0200 Subject: [PATCH 0296/5711] staging:iio:dac: Remove dac.h Now that all drivers have been converted to channel spec, we can finally remove the dac.h file since it is no longer used. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/dac.h | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 drivers/staging/iio/dac/dac.h diff --git a/drivers/staging/iio/dac/dac.h b/drivers/staging/iio/dac/dac.h deleted file mode 100644 index 0754d715cf9c..000000000000 --- a/drivers/staging/iio/dac/dac.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * dac.h - sysfs attributes associated with DACs - */ - -#define IIO_DEV_ATTR_OUT_RAW(_num, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_raw, S_IWUSR, NULL, _store, _addr) -- GitLab From 3bbbf150ffde2ca48249537d2d9e4b52bc0a5fc8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:22 +0200 Subject: [PATCH 0297/5711] staging:iio:dac:ad5504: Use strtobool for boolean values Use strtobool for parsing the powerdown value instead of strict_strtol, since the powerdown attribute is a boolean value. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5504.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 331b536ec8aa..220150d2a165 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -147,20 +147,18 @@ static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, const char *buf, size_t len) { - long readin; + bool pwr_down; int ret; struct ad5504_state *st = iio_priv(indio_dev); - ret = strict_strtol(buf, 10, &readin); + ret = strtobool(buf, &pwr_down); if (ret) return ret; - if (readin == 0) + if (pwr_down) st->pwr_down_mask |= (1 << chan->channel); - else if (readin == 1) - st->pwr_down_mask &= ~(1 << chan->channel); else - ret = -EINVAL; + st->pwr_down_mask &= ~(1 << chan->channel); ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL, AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | -- GitLab From 2490594e89c7286585daeaf05a06b6cd7b5c8876 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:23 +0200 Subject: [PATCH 0298/5711] staging:iio:dac:ad5624r: Use strtobool for boolean values Use strtobool for parsing the powerdown value instead of strict_strtol, since the powerdown attribute is a boolean value. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5624r_spi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 7524f96b8e52..6a7d6a48cc6d 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -132,20 +132,18 @@ static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, const char *buf, size_t len) { - long readin; + bool pwr_down; int ret; struct ad5624r_state *st = iio_priv(indio_dev); - ret = strict_strtol(buf, 10, &readin); + ret = strtobool(buf, &pwr_down); if (ret) return ret; - if (readin == 1) + if (pwr_down) st->pwr_down_mask |= (1 << chan->channel); - else if (!readin) - st->pwr_down_mask &= ~(1 << chan->channel); else - ret = -EINVAL; + st->pwr_down_mask &= ~(1 << chan->channel); ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, (st->pwr_down_mode << 4) | -- GitLab From 4468cb552536731fd85f22a367602e9242a55376 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:24 +0200 Subject: [PATCH 0299/5711] staging:iio:dac:ad5791: Use strtobool for boolean values Use strtobool for parsing the powerdown value instead of strict_strtol, since the powerdown attribute is a boolean value. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5791.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index 4e955ed9451d..82b51a7aa808 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -114,25 +114,23 @@ static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, const char *buf, size_t len) { - long readin; + bool pwr_down; int ret; struct ad5791_state *st = iio_priv(indio_dev); - ret = strict_strtol(buf, 10, &readin); + ret = strtobool(buf, &pwr_down); if (ret) return ret; - if (readin == 0) { - st->pwr_down = false; + if (!pwr_down) { st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); - } else if (readin == 1) { - st->pwr_down = true; + } else { if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) st->ctrl |= AD5791_CTRL_OPGND; else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) st->ctrl |= AD5791_CTRL_DACTRI; - } else - ret = -EINVAL; + } + st->pwr_down = pwr_down; ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl); -- GitLab From 4f0a788dc892d62fabcfd61b289b6212bdedadfd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:25 +0200 Subject: [PATCH 0300/5711] staging:iio:dac:ad5504: Check if IRQ was requested before freeing it IRQ support is optional, so we have to check whether it was actually requested before we attempt to free it. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5504.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 220150d2a165..f3d7b47cfe1d 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -294,7 +294,8 @@ static int __devinit ad5504_probe(struct spi_device *spi) return 0; error_free_irq: - free_irq(spi->irq, indio_dev); + if (spi->irq) + free_irq(spi->irq, indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); -- GitLab From a98348b74ec2c4c5cda0f14d38ff19e08fc4e4bf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:26 +0200 Subject: [PATCH 0301/5711] staging:iio:dac:ad5504: Move private structs and defines from header to C file The header for this driver contains some private structs and defines, which do not have to be shared between multiple source files, as well as the platform data struct for this driver, which has to be shared with other source files. Since there is no need to expose those private structs and defines move them to the source file. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5504.c | 45 ++++++++++++++++++++++++++++++++ drivers/staging/iio/dac/ad5504.h | 45 -------------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index f3d7b47cfe1d..1289e9bc1688 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -22,6 +22,51 @@ #include "ad5504.h" +#define AD5505_BITS 12 +#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) + +#define AD5504_CMD_READ (1 << 15) +#define AD5504_CMD_WRITE (0 << 15) +#define AD5504_ADDR(addr) ((addr) << 12) + +/* Registers */ +#define AD5504_ADDR_NOOP 0 +#define AD5504_ADDR_DAC(x) ((x) + 1) +#define AD5504_ADDR_ALL_DAC 5 +#define AD5504_ADDR_CTRL 7 + +/* Control Register */ +#define AD5504_DAC_PWR(ch) ((ch) << 2) +#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) +#define AD5504_DAC_PWRDN_20K 0 +#define AD5504_DAC_PWRDN_3STATE 1 + +/** + * struct ad5446_state - driver instance specific data + * @us: spi_device + * @reg: supply regulator + * @vref_mv: actual reference voltage used + * @pwr_down_mask power down mask + * @pwr_down_mode current power down mode + */ + +struct ad5504_state { + struct spi_device *spi; + struct regulator *reg; + unsigned short vref_mv; + unsigned pwr_down_mask; + unsigned pwr_down_mode; +}; + +/** + * ad5504_supported_device_ids: + */ + +enum ad5504_supported_device_ids { + ID_AD5504, + ID_AD5501, +}; + static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) { u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h index afe09522f53c..d4980bf688bf 100644 --- a/drivers/staging/iio/dac/ad5504.h +++ b/drivers/staging/iio/dac/ad5504.h @@ -9,25 +9,6 @@ #ifndef SPI_AD5504_H_ #define SPI_AD5504_H_ -#define AD5505_BITS 12 -#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) - -#define AD5504_CMD_READ (1 << 15) -#define AD5504_CMD_WRITE (0 << 15) -#define AD5504_ADDR(addr) ((addr) << 12) - -/* Registers */ -#define AD5504_ADDR_NOOP 0 -#define AD5504_ADDR_DAC(x) ((x) + 1) -#define AD5504_ADDR_ALL_DAC 5 -#define AD5504_ADDR_CTRL 7 - -/* Control Register */ -#define AD5504_DAC_PWR(ch) ((ch) << 2) -#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) -#define AD5504_DAC_PWRDN_20K 0 -#define AD5504_DAC_PWRDN_3STATE 1 - /* * TODO: struct ad5504_platform_data needs to go into include/linux/iio */ @@ -36,30 +17,4 @@ struct ad5504_platform_data { u16 vref_mv; }; -/** - * struct ad5446_state - driver instance specific data - * @us: spi_device - * @reg: supply regulator - * @vref_mv: actual reference voltage used - * @pwr_down_mask power down mask - * @pwr_down_mode current power down mode - */ - -struct ad5504_state { - struct spi_device *spi; - struct regulator *reg; - unsigned short vref_mv; - unsigned pwr_down_mask; - unsigned pwr_down_mode; -}; - -/** - * ad5504_supported_device_ids: - */ - -enum ad5504_supported_device_ids { - ID_AD5504, - ID_AD5501, -}; - #endif /* SPI_AD5504_H_ */ -- GitLab From 20374d1a36df3e20cd6742ba376684e5506254a8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:27 +0200 Subject: [PATCH 0302/5711] staging:iio:dac:ad5791: Move private structs and defines from header to C file The header for this driver contains some private structs and defines, which do not have to be shared between multiple source files, as well as the platform data struct for this driver, which has to be shared with other source files. Since there is no need to expose those private structs and defines move them to the source file. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5791.c | 83 ++++++++++++++++++++++++++++++++ drivers/staging/iio/dac/ad5791.h | 83 -------------------------------- 2 files changed, 83 insertions(+), 83 deletions(-) diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index 82b51a7aa808..5de28c2a57ef 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -22,6 +22,89 @@ #include "ad5791.h" +#define AD5791_RES_MASK(x) ((1 << (x)) - 1) +#define AD5791_DAC_MASK AD5791_RES_MASK(20) +#define AD5791_DAC_MSB (1 << 19) + +#define AD5791_CMD_READ (1 << 23) +#define AD5791_CMD_WRITE (0 << 23) +#define AD5791_ADDR(addr) ((addr) << 20) + +/* Registers */ +#define AD5791_ADDR_NOOP 0 +#define AD5791_ADDR_DAC0 1 +#define AD5791_ADDR_CTRL 2 +#define AD5791_ADDR_CLRCODE 3 +#define AD5791_ADDR_SW_CTRL 4 + +/* Control Register */ +#define AD5791_CTRL_RBUF (1 << 1) +#define AD5791_CTRL_OPGND (1 << 2) +#define AD5791_CTRL_DACTRI (1 << 3) +#define AD5791_CTRL_BIN2SC (1 << 4) +#define AD5791_CTRL_SDODIS (1 << 5) +#define AD5761_CTRL_LINCOMP(x) ((x) << 6) + +#define AD5791_LINCOMP_0_10 0 +#define AD5791_LINCOMP_10_12 1 +#define AD5791_LINCOMP_12_16 2 +#define AD5791_LINCOMP_16_19 3 +#define AD5791_LINCOMP_19_20 12 + +#define AD5780_LINCOMP_0_10 0 +#define AD5780_LINCOMP_10_20 12 + +/* Software Control Register */ +#define AD5791_SWCTRL_LDAC (1 << 0) +#define AD5791_SWCTRL_CLR (1 << 1) +#define AD5791_SWCTRL_RESET (1 << 2) + +#define AD5791_DAC_PWRDN_6K 0 +#define AD5791_DAC_PWRDN_3STATE 1 + +/** + * struct ad5791_chip_info - chip specific information + * @get_lin_comp: function pointer to the device specific function + */ + +struct ad5791_chip_info { + int (*get_lin_comp) (unsigned int span); +}; + +/** + * struct ad5791_state - driver instance specific data + * @us: spi_device + * @reg_vdd: positive supply regulator + * @reg_vss: negative supply regulator + * @chip_info: chip model specific constants + * @vref_mv: actual reference voltage used + * @vref_neg_mv: voltage of the negative supply + * @pwr_down_mode current power down mode + */ + +struct ad5791_state { + struct spi_device *spi; + struct regulator *reg_vdd; + struct regulator *reg_vss; + const struct ad5791_chip_info *chip_info; + unsigned short vref_mv; + unsigned int vref_neg_mv; + unsigned ctrl; + unsigned pwr_down_mode; + bool pwr_down; +}; + +/** + * ad5791_supported_device_ids: + */ + +enum ad5791_supported_device_ids { + ID_AD5760, + ID_AD5780, + ID_AD5781, + ID_AD5791, +}; + static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) { union { diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h index fd7edbdb4ec3..87a6c922f18e 100644 --- a/drivers/staging/iio/dac/ad5791.h +++ b/drivers/staging/iio/dac/ad5791.h @@ -9,46 +9,6 @@ #ifndef SPI_AD5791_H_ #define SPI_AD5791_H_ -#define AD5791_RES_MASK(x) ((1 << (x)) - 1) -#define AD5791_DAC_MASK AD5791_RES_MASK(20) -#define AD5791_DAC_MSB (1 << 19) - -#define AD5791_CMD_READ (1 << 23) -#define AD5791_CMD_WRITE (0 << 23) -#define AD5791_ADDR(addr) ((addr) << 20) - -/* Registers */ -#define AD5791_ADDR_NOOP 0 -#define AD5791_ADDR_DAC0 1 -#define AD5791_ADDR_CTRL 2 -#define AD5791_ADDR_CLRCODE 3 -#define AD5791_ADDR_SW_CTRL 4 - -/* Control Register */ -#define AD5791_CTRL_RBUF (1 << 1) -#define AD5791_CTRL_OPGND (1 << 2) -#define AD5791_CTRL_DACTRI (1 << 3) -#define AD5791_CTRL_BIN2SC (1 << 4) -#define AD5791_CTRL_SDODIS (1 << 5) -#define AD5761_CTRL_LINCOMP(x) ((x) << 6) - -#define AD5791_LINCOMP_0_10 0 -#define AD5791_LINCOMP_10_12 1 -#define AD5791_LINCOMP_12_16 2 -#define AD5791_LINCOMP_16_19 3 -#define AD5791_LINCOMP_19_20 12 - -#define AD5780_LINCOMP_0_10 0 -#define AD5780_LINCOMP_10_20 12 - -/* Software Control Register */ -#define AD5791_SWCTRL_LDAC (1 << 0) -#define AD5791_SWCTRL_CLR (1 << 1) -#define AD5791_SWCTRL_RESET (1 << 2) - -#define AD5791_DAC_PWRDN_6K 0 -#define AD5791_DAC_PWRDN_3STATE 1 - /* * TODO: struct ad5791_platform_data needs to go into include/linux/iio */ @@ -66,47 +26,4 @@ struct ad5791_platform_data { bool use_rbuf_gain2; }; -/** - * struct ad5791_chip_info - chip specific information - * @get_lin_comp: function pointer to the device specific function - */ - -struct ad5791_chip_info { - int (*get_lin_comp) (unsigned int span); -}; - -/** - * struct ad5791_state - driver instance specific data - * @us: spi_device - * @reg_vdd: positive supply regulator - * @reg_vss: negative supply regulator - * @chip_info: chip model specific constants - * @vref_mv: actual reference voltage used - * @vref_neg_mv: voltage of the negative supply - * @pwr_down_mode current power down mode - */ - -struct ad5791_state { - struct spi_device *spi; - struct regulator *reg_vdd; - struct regulator *reg_vss; - const struct ad5791_chip_info *chip_info; - unsigned short vref_mv; - unsigned int vref_neg_mv; - unsigned ctrl; - unsigned pwr_down_mode; - bool pwr_down; -}; - -/** - * ad5791_supported_device_ids: - */ - -enum ad5791_supported_device_ids { - ID_AD5760, - ID_AD5780, - ID_AD5781, - ID_AD5791, -}; - #endif /* SPI_AD5791_H_ */ -- GitLab From dbdc025bb239ce62c9b4d28c459a98f22ce9ec0a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 4 Jun 2012 11:36:28 +0200 Subject: [PATCH 0303/5711] staging:iio: Move DAC drivers out of staging The IIO DAC drivers are in a reasonably good shape. They all make use of channel spec and non of them provides non-documented sysfs attributes. Code style should be OK as well, both checkpatch and coccicheck only report trivial issues. So lets move the whole folder out of staging. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/{staging => }/iio/dac/Kconfig | 0 drivers/{staging => }/iio/dac/Makefile | 0 drivers/{staging => }/iio/dac/ad5064.c | 0 drivers/{staging => }/iio/dac/ad5360.c | 0 drivers/{staging => }/iio/dac/ad5380.c | 0 drivers/{staging => }/iio/dac/ad5421.c | 2 +- drivers/{staging => }/iio/dac/ad5446.c | 0 drivers/{staging => }/iio/dac/ad5446.h | 0 drivers/{staging => }/iio/dac/ad5504.c | 3 +-- drivers/{staging => }/iio/dac/ad5624r.h | 0 drivers/{staging => }/iio/dac/ad5624r_spi.c | 0 drivers/{staging => }/iio/dac/ad5686.c | 0 drivers/{staging => }/iio/dac/ad5764.c | 0 drivers/{staging => }/iio/dac/ad5791.c | 3 +-- drivers/{staging => }/iio/dac/max517.c | 3 +-- drivers/staging/iio/Kconfig | 1 - drivers/staging/iio/Makefile | 1 - {drivers/staging => include/linux}/iio/dac/ad5421.h | 4 ---- {drivers/staging => include/linux}/iio/dac/ad5504.h | 4 ---- {drivers/staging => include/linux}/iio/dac/ad5791.h | 4 ---- {drivers/staging => include/linux}/iio/dac/max517.h | 4 ---- 23 files changed, 6 insertions(+), 25 deletions(-) rename drivers/{staging => }/iio/dac/Kconfig (100%) rename drivers/{staging => }/iio/dac/Makefile (100%) rename drivers/{staging => }/iio/dac/ad5064.c (100%) rename drivers/{staging => }/iio/dac/ad5360.c (100%) rename drivers/{staging => }/iio/dac/ad5380.c (100%) rename drivers/{staging => }/iio/dac/ad5421.c (99%) rename drivers/{staging => }/iio/dac/ad5446.c (100%) rename drivers/{staging => }/iio/dac/ad5446.h (100%) rename drivers/{staging => }/iio/dac/ad5504.c (99%) rename drivers/{staging => }/iio/dac/ad5624r.h (100%) rename drivers/{staging => }/iio/dac/ad5624r_spi.c (100%) rename drivers/{staging => }/iio/dac/ad5686.c (100%) rename drivers/{staging => }/iio/dac/ad5764.c (100%) rename drivers/{staging => }/iio/dac/ad5791.c (99%) rename drivers/{staging => }/iio/dac/max517.c (99%) rename {drivers/staging => include/linux}/iio/dac/ad5421.h (92%) rename {drivers/staging => include/linux}/iio/dac/ad5504.h (74%) rename {drivers/staging => include/linux}/iio/dac/ad5791.h (87%) rename {drivers/staging => include/linux}/iio/dac/max517.h (76%) diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 64c88e5cda4d..103349f2b3b5 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -52,5 +52,6 @@ source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" source "drivers/iio/light/Kconfig" source "drivers/iio/frequency/Kconfig" +source "drivers/iio/dac/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index bd801c0bbc2f..c38fa2a40af2 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -13,3 +13,4 @@ obj-y += adc/ obj-y += amplifiers/ obj-y += light/ obj-y += frequency/ +obj-y += dac/ diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/iio/dac/Kconfig similarity index 100% rename from drivers/staging/iio/dac/Kconfig rename to drivers/iio/dac/Kconfig diff --git a/drivers/staging/iio/dac/Makefile b/drivers/iio/dac/Makefile similarity index 100% rename from drivers/staging/iio/dac/Makefile rename to drivers/iio/dac/Makefile diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c similarity index 100% rename from drivers/staging/iio/dac/ad5064.c rename to drivers/iio/dac/ad5064.c diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c similarity index 100% rename from drivers/staging/iio/dac/ad5360.c rename to drivers/iio/dac/ad5360.c diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c similarity index 100% rename from drivers/staging/iio/dac/ad5380.c rename to drivers/iio/dac/ad5380.c diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c similarity index 99% rename from drivers/staging/iio/dac/ad5421.c rename to drivers/iio/dac/ad5421.c index ea2f83b4e357..cdbc5bf25c31 100644 --- a/drivers/staging/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -19,7 +19,7 @@ #include #include #include -#include "ad5421.h" +#include #define AD5421_REG_DAC_DATA 0x1 diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c similarity index 100% rename from drivers/staging/iio/dac/ad5446.c rename to drivers/iio/dac/ad5446.c diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/iio/dac/ad5446.h similarity index 100% rename from drivers/staging/iio/dac/ad5446.h rename to drivers/iio/dac/ad5446.h diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c similarity index 99% rename from drivers/staging/iio/dac/ad5504.c rename to drivers/iio/dac/ad5504.c index 1289e9bc1688..242bdc7d0044 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -19,8 +19,7 @@ #include #include #include - -#include "ad5504.h" +#include #define AD5505_BITS 12 #define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/iio/dac/ad5624r.h similarity index 100% rename from drivers/staging/iio/dac/ad5624r.h rename to drivers/iio/dac/ad5624r.h diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c similarity index 100% rename from drivers/staging/iio/dac/ad5624r_spi.c rename to drivers/iio/dac/ad5624r_spi.c diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c similarity index 100% rename from drivers/staging/iio/dac/ad5686.c rename to drivers/iio/dac/ad5686.c diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c similarity index 100% rename from drivers/staging/iio/dac/ad5764.c rename to drivers/iio/dac/ad5764.c diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c similarity index 99% rename from drivers/staging/iio/dac/ad5791.c rename to drivers/iio/dac/ad5791.c index 5de28c2a57ef..2bd2e37280ff 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -19,8 +19,7 @@ #include #include - -#include "ad5791.h" +#include #define AD5791_RES_MASK(x) ((1 << (x)) - 1) #define AD5791_DAC_MASK AD5791_RES_MASK(20) diff --git a/drivers/staging/iio/dac/max517.c b/drivers/iio/dac/max517.c similarity index 99% rename from drivers/staging/iio/dac/max517.c rename to drivers/iio/dac/max517.c index 403e06fbc39e..92c77c82026c 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -27,8 +27,7 @@ #include #include - -#include "max517.h" +#include #define MAX517_DRV_NAME "max517" diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 3c8e5ec26ac1..04cd6ec1f70f 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -29,7 +29,6 @@ source "drivers/staging/iio/accel/Kconfig" source "drivers/staging/iio/adc/Kconfig" source "drivers/staging/iio/addac/Kconfig" source "drivers/staging/iio/cdc/Kconfig" -source "drivers/staging/iio/dac/Kconfig" source "drivers/staging/iio/frequency/Kconfig" source "drivers/staging/iio/gyro/Kconfig" source "drivers/staging/iio/impedance-analyzer/Kconfig" diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 6a46d5afb380..fa6937d92ee3 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -17,7 +17,6 @@ obj-y += accel/ obj-y += adc/ obj-y += addac/ obj-y += cdc/ -obj-y += dac/ obj-y += frequency/ obj-y += gyro/ obj-y += impedance-analyzer/ diff --git a/drivers/staging/iio/dac/ad5421.h b/include/linux/iio/dac/ad5421.h similarity index 92% rename from drivers/staging/iio/dac/ad5421.h rename to include/linux/iio/dac/ad5421.h index cd2bb84ff1b0..8fd8f057a890 100644 --- a/drivers/staging/iio/dac/ad5421.h +++ b/include/linux/iio/dac/ad5421.h @@ -1,10 +1,6 @@ #ifndef __IIO_DAC_AD5421_H__ #define __IIO_DAC_AD5421_H__ -/* - * TODO: This file needs to go into include/linux/iio - */ - /** * enum ad5421_current_range - Current range the AD5421 is configured for. * @AD5421_CURRENT_RANGE_4mA_20mA: 4 mA to 20 mA (RANGE1,0 pins = 00) diff --git a/drivers/staging/iio/dac/ad5504.h b/include/linux/iio/dac/ad5504.h similarity index 74% rename from drivers/staging/iio/dac/ad5504.h rename to include/linux/iio/dac/ad5504.h index d4980bf688bf..43895376a9ca 100644 --- a/drivers/staging/iio/dac/ad5504.h +++ b/include/linux/iio/dac/ad5504.h @@ -9,10 +9,6 @@ #ifndef SPI_AD5504_H_ #define SPI_AD5504_H_ -/* - * TODO: struct ad5504_platform_data needs to go into include/linux/iio - */ - struct ad5504_platform_data { u16 vref_mv; }; diff --git a/drivers/staging/iio/dac/ad5791.h b/include/linux/iio/dac/ad5791.h similarity index 87% rename from drivers/staging/iio/dac/ad5791.h rename to include/linux/iio/dac/ad5791.h index 87a6c922f18e..45ee281c6660 100644 --- a/drivers/staging/iio/dac/ad5791.h +++ b/include/linux/iio/dac/ad5791.h @@ -9,10 +9,6 @@ #ifndef SPI_AD5791_H_ #define SPI_AD5791_H_ -/* - * TODO: struct ad5791_platform_data needs to go into include/linux/iio - */ - /** * struct ad5791_platform_data - platform specific information * @vref_pos_mv: Vdd Positive Analog Supply Volatge (mV) diff --git a/drivers/staging/iio/dac/max517.h b/include/linux/iio/dac/max517.h similarity index 76% rename from drivers/staging/iio/dac/max517.h rename to include/linux/iio/dac/max517.h index 8106cf24642a..f6d1d252f08d 100644 --- a/drivers/staging/iio/dac/max517.h +++ b/include/linux/iio/dac/max517.h @@ -8,10 +8,6 @@ #ifndef IIO_DAC_MAX517_H_ #define IIO_DAC_MAX517_H_ -/* - * TODO: struct max517_platform_data needs to go into include/linux/iio - */ - struct max517_platform_data { u16 vref_mv[2]; }; -- GitLab From 1079def493b55e7a69e6eefc6e026224e1d90e2a Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Mon, 4 Jun 2012 15:11:04 +0530 Subject: [PATCH 0304/5711] staging: iio: hmc5843: Make it behave better as modules The memory regions of the probe and remove are move to __devinit and __devexit respectively. Acked-by: Jonathan Cameron Signed-off-by: Shubhrajyoti D Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/hmc5843.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index c1fa09f07625..6c3e50f7c0d8 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -665,7 +665,7 @@ static const struct iio_info hmc5843_info = { .driver_module = THIS_MODULE, }; -static int hmc5843_probe(struct i2c_client *client, +static int __devinit hmc5843_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct hmc5843_data *data; @@ -704,7 +704,7 @@ exit: return err; } -static int hmc5843_remove(struct i2c_client *client) +static int __devexit hmc5843_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); @@ -755,7 +755,7 @@ static struct i2c_driver hmc5843_driver = { }, .id_table = hmc5843_id, .probe = hmc5843_probe, - .remove = hmc5843_remove, + .remove = __devexit_p(hmc5843_remove), .detect = hmc5843_detect, .address_list = normal_i2c, }; -- GitLab From f61343b397975c6360c0f83edebbfdad19baf8f7 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Mon, 4 Jun 2012 15:11:05 +0530 Subject: [PATCH 0305/5711] staging: iio: ak8975: Make it behave better as modules The memory regions of the probe and remove are move to __devinit and __devexit respectively. Acked-by: Jonathan Cameron Signed-off-by: Shubhrajyoti D Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/ak8975.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 5834e4a70f8c..7562cafb26bb 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -471,7 +471,7 @@ static const struct iio_info ak8975_info = { .driver_module = THIS_MODULE, }; -static int ak8975_probe(struct i2c_client *client, +static int __devinit ak8975_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ak8975_data *data; @@ -545,7 +545,7 @@ exit: return err; } -static int ak8975_remove(struct i2c_client *client) +static int __devexit ak8975_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ak8975_data *data = iio_priv(indio_dev); -- GitLab From cc502bb741e1797290381da14dddb695ec1adbaf Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 3 Jun 2012 18:39:13 +0200 Subject: [PATCH 0306/5711] renesas_usbhs: cleanup quoted includes A few quoted includes start with a superfluous "./". Clean up those quoted includes. Signed-off-by: Paul Bolle Signed-off-by: Jiri Kosina --- drivers/usb/renesas_usbhs/common.c | 2 +- drivers/usb/renesas_usbhs/common.h | 4 ++-- drivers/usb/renesas_usbhs/fifo.c | 4 ++-- drivers/usb/renesas_usbhs/mod.c | 4 ++-- drivers/usb/renesas_usbhs/mod.h | 2 +- drivers/usb/renesas_usbhs/pipe.c | 4 ++-- drivers/usb/renesas_usbhs/pipe.h | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index a165490bae48..8c9bb1ad3069 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -19,7 +19,7 @@ #include #include #include -#include "./common.h" +#include "common.h" /* * image of renesas_usbhs diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index 3f3ccd358753..dddf40a59ded 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -22,8 +22,8 @@ struct usbhs_priv; -#include "./mod.h" -#include "./pipe.h" +#include "mod.h" +#include "pipe.h" /* * diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 6ec7f838d7fa..08313574aac8 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -17,8 +17,8 @@ #include #include #include -#include "./common.h" -#include "./pipe.h" +#include "common.h" +#include "pipe.h" #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 0871e816df45..82a628f96c03 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -16,8 +16,8 @@ */ #include -#include "./common.h" -#include "./mod.h" +#include "common.h" +#include "mod.h" #define usbhs_priv_to_modinfo(priv) (&priv->mod_info) #define usbhs_mod_info_call(priv, func, param...) \ diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h index 6c6875533f01..1ef5bf604070 100644 --- a/drivers/usb/renesas_usbhs/mod.h +++ b/drivers/usb/renesas_usbhs/mod.h @@ -19,7 +19,7 @@ #include #include -#include "./common.h" +#include "common.h" /* * struct diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index feb06d6d2814..122526cfd32b 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -16,8 +16,8 @@ */ #include #include -#include "./common.h" -#include "./pipe.h" +#include "common.h" +#include "pipe.h" /* * macros diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index fa18b7dc2b2a..08786c06dcf1 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -17,8 +17,8 @@ #ifndef RENESAS_USB_PIPE_H #define RENESAS_USB_PIPE_H -#include "./common.h" -#include "./fifo.h" +#include "common.h" +#include "fifo.h" /* * struct -- GitLab From c224071e28e2bbd213cce2e6e9dde26e78542ca8 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 3 Jun 2012 18:39:42 +0200 Subject: [PATCH 0307/5711] parisc: cleanup quoted include A quoted include starts with a superfluous "./". Clean up that quoted include. Signed-off-by: Paul Bolle Signed-off-by: Jiri Kosina --- drivers/parisc/iosapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1f9e9fefb8e7..69ff60832b09 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -146,7 +146,7 @@ #endif #include -#include "./iosapic_private.h" +#include "iosapic_private.h" #define MODULE_NAME "iosapic" -- GitLab From 2f989f7e9f5f9ba97535fa58f4240ec250d6b2df Mon Sep 17 00:00:00 2001 From: M R Swami Reddy Date: Fri, 1 Jun 2012 22:21:54 +0530 Subject: [PATCH 0308/5711] ASoC: Support TI Isabelle Audio driver ASoC: Support TI Isabelle Audio driver The Isabelle Audio IC is a complete low power high fidelity CODEC with integrated ADCs, DACs, decimation and interpolation filters, PLL, and power providers. This device supports 2 analog and 2 digital microphone channels, a mono earpiece driver, stereo class G headphone drivers with ultra low power and best SNR in the industry, stereo Class D speaker drivers, and 2 high performance Line drivers. The below patch is a basic driver code for TI Isabelle audio codec. The functionalities like headset detection, etc., will be included incrementally in the up-coming patches. Signed-off-by: Vishwas A Deshpande Signed-off-by: M R Swami Reddy Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/isabelle.c | 1179 +++++++++++++++++++++++++++++++++++ sound/soc/codecs/isabelle.h | 143 +++++ 4 files changed, 1328 insertions(+) create mode 100644 sound/soc/codecs/isabelle.c create mode 100644 sound/soc/codecs/isabelle.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1e1613a438dd..8b879c71c23c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -36,6 +36,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CX20442 select SND_SOC_DA7210 if I2C select SND_SOC_DFBMCS320 + select SND_SOC_ISABELLE if I2C select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C select SND_SOC_LM49453 if I2C @@ -225,6 +226,9 @@ config SND_SOC_DFBMCS320 config SND_SOC_DMIC tristate +config SND_SOC_ISABELLE + tristate + config SND_SOC_LM49453 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fc27fec39487..e50811b182a4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -23,6 +23,7 @@ snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o snd-soc-dfbmcs320-objs := dfbmcs320.o snd-soc-dmic-objs := dmic.o +snd-soc-isabelle-objs := isabelle.o snd-soc-jz4740-codec-objs := jz4740.o snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o @@ -134,6 +135,7 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o +obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c new file mode 100644 index 000000000000..b6921a82fbcc --- /dev/null +++ b/sound/soc/codecs/isabelle.c @@ -0,0 +1,1179 @@ +/* + * isabelle.c - Low power high fidelity audio codec driver + * + * Copyright (c) 2012 Texas Instruments, Inc + * + * 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. + * + * + * Initially based on sound/soc/codecs/twl6040.c + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "isabelle.h" + + +/* Register default values for ISABELLE driver. */ +static struct reg_default isabelle_reg_defs[] = { + { 0, 0x00 }, + { 1, 0x00 }, + { 2, 0x00 }, + { 3, 0x00 }, + { 4, 0x00 }, + { 5, 0x00 }, + { 6, 0x00 }, + { 7, 0x00 }, + { 8, 0x00 }, + { 9, 0x00 }, + { 10, 0x00 }, + { 11, 0x00 }, + { 12, 0x00 }, + { 13, 0x00 }, + { 14, 0x00 }, + { 15, 0x00 }, + { 16, 0x00 }, + { 17, 0x00 }, + { 18, 0x00 }, + { 19, 0x00 }, + { 20, 0x00 }, + { 21, 0x02 }, + { 22, 0x02 }, + { 23, 0x02 }, + { 24, 0x02 }, + { 25, 0x0F }, + { 26, 0x8F }, + { 27, 0x0F }, + { 28, 0x8F }, + { 29, 0x00 }, + { 30, 0x00 }, + { 31, 0x00 }, + { 32, 0x00 }, + { 33, 0x00 }, + { 34, 0x00 }, + { 35, 0x00 }, + { 36, 0x00 }, + { 37, 0x00 }, + { 38, 0x00 }, + { 39, 0x00 }, + { 40, 0x00 }, + { 41, 0x00 }, + { 42, 0x00 }, + { 43, 0x00 }, + { 44, 0x00 }, + { 45, 0x00 }, + { 46, 0x00 }, + { 47, 0x00 }, + { 48, 0x00 }, + { 49, 0x00 }, + { 50, 0x00 }, + { 51, 0x00 }, + { 52, 0x00 }, + { 53, 0x00 }, + { 54, 0x00 }, + { 55, 0x00 }, + { 56, 0x00 }, + { 57, 0x00 }, + { 58, 0x00 }, + { 59, 0x00 }, + { 60, 0x00 }, + { 61, 0x00 }, + { 62, 0x00 }, + { 63, 0x00 }, + { 64, 0x00 }, + { 65, 0x00 }, + { 66, 0x00 }, + { 67, 0x00 }, + { 68, 0x00 }, + { 69, 0x90 }, + { 70, 0x90 }, + { 71, 0x90 }, + { 72, 0x00 }, + { 73, 0x00 }, + { 74, 0x00 }, + { 75, 0x00 }, + { 76, 0x00 }, + { 77, 0x00 }, + { 78, 0x00 }, + { 79, 0x00 }, + { 80, 0x00 }, + { 81, 0x00 }, + { 82, 0x00 }, + { 83, 0x00 }, + { 84, 0x00 }, + { 85, 0x07 }, + { 86, 0x00 }, + { 87, 0x00 }, + { 88, 0x00 }, + { 89, 0x07 }, + { 90, 0x80 }, + { 91, 0x07 }, + { 92, 0x07 }, + { 93, 0x00 }, + { 94, 0x00 }, + { 95, 0x00 }, + { 96, 0x00 }, + { 97, 0x00 }, + { 98, 0x00 }, + { 99, 0x00 }, +}; + +static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"}; +static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; + +static const struct soc_enum isabelle_rx1_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts), + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts), +}; + +static const struct soc_enum isabelle_rx2_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts), + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts), +}; + +/* Headset DAC playback switches */ +static const struct snd_kcontrol_new rx1_mux_controls = + SOC_DAPM_ENUM("Route", isabelle_rx1_enum); + +static const struct snd_kcontrol_new rx2_mux_controls = + SOC_DAPM_ENUM("Route", isabelle_rx2_enum); + +/* TX input selection */ +static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"}; +static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; + +static const struct soc_enum isabelle_atx_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts), + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts), +}; + +static const struct soc_enum isabelle_vtx_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts), + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts), +}; + +static const struct snd_kcontrol_new atx_mux_controls = + SOC_DAPM_ENUM("Route", isabelle_atx_enum); + +static const struct snd_kcontrol_new vtx_mux_controls = + SOC_DAPM_ENUM("Route", isabelle_vtx_enum); + +/* Left analog microphone selection */ +static const char *isabelle_amic1_texts[] = { + "Main Mic", "Headset Mic", "Aux/FM Left"}; + +/* Left analog microphone selection */ +static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; + +static const struct soc_enum isabelle_amic1_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5, + ARRAY_SIZE(isabelle_amic1_texts), + isabelle_amic1_texts), +}; + +static const struct soc_enum isabelle_amic2_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4, + ARRAY_SIZE(isabelle_amic2_texts), + isabelle_amic2_texts), +}; + +static const struct snd_kcontrol_new amic1_control = + SOC_DAPM_ENUM("Route", isabelle_amic1_enum); + +static const struct snd_kcontrol_new amic2_control = + SOC_DAPM_ENUM("Route", isabelle_amic2_enum); + +static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"}; + +static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; + +static const struct soc_enum isabelle_st_audio_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1, + isabelle_st_audio_texts), + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1, + isabelle_st_audio_texts), +}; + +static const struct soc_enum isabelle_st_voice_enum[] = { + SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1, + isabelle_st_voice_texts), + SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1, + isabelle_st_voice_texts), +}; + +static const struct snd_kcontrol_new st_audio_control = + SOC_DAPM_ENUM("Route", isabelle_st_audio_enum); + +static const struct snd_kcontrol_new st_voice_control = + SOC_DAPM_ENUM("Route", isabelle_st_voice_enum); + +/* Mixer controls */ +static const struct snd_kcontrol_new isabelle_hs_left_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC1L Playback Switch", ISABELLE_HSDRV_CFG1_REG, 7, 1, 0), +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_hs_right_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC1R Playback Switch", ISABELLE_HSDRV_CFG1_REG, 5, 1, 0), +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 4, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_hf_left_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_HFLPGA_CFG_REG, 7, 1, 0), +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HFLPGA_CFG_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_hf_right_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC2R Playback Switch", ISABELLE_HFRPGA_CFG_REG, 7, 1, 0), +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HFRPGA_CFG_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_ep_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_EARDRV_CFG1_REG, 7, 1, 0), +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_EARDRV_CFG1_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_aux_left_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC3L Playback Switch", ISABELLE_LINEAMP_CFG_REG, 7, 1, 0), +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_aux_right_mixer_controls[] = { +SOC_DAPM_SINGLE("DAC3R Playback Switch", ISABELLE_LINEAMP_CFG_REG, 5, 1, 0), +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 4, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga1_left_mixer_controls[] = { +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 7, 1, 0), +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 6, 1, 0), +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 5, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga1_right_mixer_controls[] = { +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 3, 1, 0), +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 2, 1, 0), +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 1, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga2_left_mixer_controls[] = { +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 7, 1, 0), +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 6, 1, 0), +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 5, 1, 0), +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 4, 1, 0), +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 3, 1, 0), +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 2, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga2_right_mixer_controls[] = { +SOC_DAPM_SINGLE("USNC Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 7, 1, 0), +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 3, 1, 0), +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 2, 1, 0), +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 1, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga3_left_mixer_controls[] = { +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 7, 1, 0), +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 6, 1, 0), +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 5, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_dpga3_right_mixer_controls[] = { +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 3, 1, 0), +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 2, 1, 0), +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 1, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx1_mixer_controls[] = { +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 7, 1, 0), +SOC_DAPM_SINGLE("DL1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx2_mixer_controls[] = { +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 5, 1, 0), +SOC_DAPM_SINGLE("DL2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 4, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx3_mixer_controls[] = { +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 3, 1, 0), +SOC_DAPM_SINGLE("DL3 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 2, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx4_mixer_controls[] = { +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 1, 1, 0), +SOC_DAPM_SINGLE("DL4 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 0, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx5_mixer_controls[] = { +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 7, 1, 0), +SOC_DAPM_SINGLE("DL5 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 6, 1, 0), +}; + +static const struct snd_kcontrol_new isabelle_rx6_mixer_controls[] = { +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 5, 1, 0), +SOC_DAPM_SINGLE("DL6 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 4, 1, 0), +}; + +static const struct snd_kcontrol_new ep_path_enable_control = + SOC_DAPM_SINGLE("Switch", ISABELLE_EARDRV_CFG2_REG, 0, 1, 0); + +/* TLV Declarations */ +static const DECLARE_TLV_DB_SCALE(mic_amp_tlv, 0, 100, 0); +static const DECLARE_TLV_DB_SCALE(afm_amp_tlv, -3300, 300, 0); +static const DECLARE_TLV_DB_SCALE(dac_tlv, -1200, 200, 0); +static const DECLARE_TLV_DB_SCALE(hf_tlv, -5000, 200, 0); + +/* from -63 to 0 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(dpga_tlv, -6300, 100, 1); + +/* from -63 to 9 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(rx_tlv, -6300, 100, 1); + +static const DECLARE_TLV_DB_SCALE(st_tlv, -2700, 300, 1); +static const DECLARE_TLV_DB_SCALE(tx_tlv, -600, 100, 0); + +static const struct snd_kcontrol_new isabelle_snd_controls[] = { + SOC_DOUBLE_TLV("Headset Playback Volume", ISABELLE_HSDRV_GAIN_REG, + 4, 0, 0xF, 0, dac_tlv), + SOC_DOUBLE_R_TLV("Handsfree Playback Volume", + ISABELLE_HFLPGA_CFG_REG, ISABELLE_HFRPGA_CFG_REG, + 0, 0x1F, 0, hf_tlv), + SOC_DOUBLE_TLV("Aux Playback Volume", ISABELLE_LINEAMP_GAIN_REG, + 4, 0, 0xF, 0, dac_tlv), + SOC_SINGLE_TLV("Earpiece Playback Volume", ISABELLE_EARDRV_CFG1_REG, + 0, 0xF, 0, dac_tlv), + + SOC_DOUBLE_TLV("Aux FM Volume", ISABELLE_APGA_GAIN_REG, 4, 0, 0xF, 0, + afm_amp_tlv), + SOC_SINGLE_TLV("Mic1 Capture Volume", ISABELLE_MIC1_GAIN_REG, 3, 0x1F, + 0, mic_amp_tlv), + SOC_SINGLE_TLV("Mic2 Capture Volume", ISABELLE_MIC2_GAIN_REG, 3, 0x1F, + 0, mic_amp_tlv), + + SOC_DOUBLE_R_TLV("DPGA1 Volume", ISABELLE_DPGA1L_GAIN_REG, + ISABELLE_DPGA1R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), + SOC_DOUBLE_R_TLV("DPGA2 Volume", ISABELLE_DPGA2L_GAIN_REG, + ISABELLE_DPGA2R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), + SOC_DOUBLE_R_TLV("DPGA3 Volume", ISABELLE_DPGA3L_GAIN_REG, + ISABELLE_DPGA3R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), + + SOC_SINGLE_TLV("Sidetone Audio TX1 Volume", + ISABELLE_ATX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), + SOC_SINGLE_TLV("Sidetone Audio TX2 Volume", + ISABELLE_ATX_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), + SOC_SINGLE_TLV("Sidetone Voice TX1 Volume", + ISABELLE_VTX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), + SOC_SINGLE_TLV("Sidetone Voice TX2 Volume", + ISABELLE_VTX2_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), + + SOC_SINGLE_TLV("Audio TX1 Volume", ISABELLE_ATX1_DPGA_REG, 4, 0xF, 0, + tx_tlv), + SOC_SINGLE_TLV("Audio TX2 Volume", ISABELLE_ATX2_DPGA_REG, 4, 0xF, 0, + tx_tlv), + SOC_SINGLE_TLV("Voice TX1 Volume", ISABELLE_VTX1_DPGA_REG, 4, 0xF, 0, + tx_tlv), + SOC_SINGLE_TLV("Voice TX2 Volume", ISABELLE_VTX2_DPGA_REG, 4, 0xF, 0, + tx_tlv), + + SOC_SINGLE_TLV("RX1 DPGA Volume", ISABELLE_RX1_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + SOC_SINGLE_TLV("RX2 DPGA Volume", ISABELLE_RX2_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + SOC_SINGLE_TLV("RX3 DPGA Volume", ISABELLE_RX3_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + SOC_SINGLE_TLV("RX4 DPGA Volume", ISABELLE_RX4_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + SOC_SINGLE_TLV("RX5 DPGA Volume", ISABELLE_RX5_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + SOC_SINGLE_TLV("RX6 DPGA Volume", ISABELLE_RX6_DPGA_REG, 0, 0x3F, 0, + rx_tlv), + + SOC_SINGLE("Headset Noise Gate", ISABELLE_HS_NG_CFG1_REG, 7, 1, 0), + SOC_SINGLE("Handsfree Noise Gate", ISABELLE_HF_NG_CFG1_REG, 7, 1, 0), + + SOC_SINGLE("ATX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 7, 1, 0), + SOC_SINGLE("ATX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 6, 1, 0), + SOC_SINGLE("ARX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 5, 1, 0), + SOC_SINGLE("ARX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 4, 1, 0), + SOC_SINGLE("ARX3 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 3, 1, 0), + SOC_SINGLE("ARX4 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 2, 1, 0), + SOC_SINGLE("ARX5 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 1, 1, 0), + SOC_SINGLE("ARX6 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 0, 1, 0), + SOC_SINGLE("VRX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 3, 1, 0), + SOC_SINGLE("VRX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, + 2, 1, 0), + + SOC_SINGLE("ATX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, + 7, 1, 0), + SOC_SINGLE("ATX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, + 6, 1, 0), + SOC_SINGLE("VTX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, + 5, 1, 0), + SOC_SINGLE("VTX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, + 4, 1, 0), + SOC_SINGLE("RX1 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 5, 1, 0), + SOC_SINGLE("RX2 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 4, 1, 0), + SOC_SINGLE("RX3 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 3, 1, 0), + SOC_SINGLE("RX4 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 2, 1, 0), + SOC_SINGLE("RX5 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 1, 1, 0), + SOC_SINGLE("RX6 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, + 0, 1, 0), + + SOC_SINGLE("ULATX12 Capture Switch", ISABELLE_ULATX12_INTF_CFG_REG, + 7, 1, 0), + + SOC_SINGLE("DL12 Playback Switch", ISABELLE_DL12_INTF_CFG_REG, + 7, 1, 0), + SOC_SINGLE("DL34 Playback Switch", ISABELLE_DL34_INTF_CFG_REG, + 7, 1, 0), + SOC_SINGLE("DL56 Playback Switch", ISABELLE_DL56_INTF_CFG_REG, + 7, 1, 0), + + /* DMIC Switch */ + SOC_SINGLE("DMIC Switch", ISABELLE_DMIC_CFG_REG, 0, 1, 0), +}; + +static const struct snd_soc_dapm_widget isabelle_dapm_widgets[] = { + /* Inputs */ + SND_SOC_DAPM_INPUT("MAINMIC"), + SND_SOC_DAPM_INPUT("HSMIC"), + SND_SOC_DAPM_INPUT("SUBMIC"), + SND_SOC_DAPM_INPUT("LINEIN1"), + SND_SOC_DAPM_INPUT("LINEIN2"), + SND_SOC_DAPM_INPUT("DMICDAT"), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HSOL"), + SND_SOC_DAPM_OUTPUT("HSOR"), + SND_SOC_DAPM_OUTPUT("HFL"), + SND_SOC_DAPM_OUTPUT("HFR"), + SND_SOC_DAPM_OUTPUT("EP"), + SND_SOC_DAPM_OUTPUT("LINEOUT1"), + SND_SOC_DAPM_OUTPUT("LINEOUT2"), + + SND_SOC_DAPM_PGA("DL1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DL2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DL3", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DL4", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DL5", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DL6", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Analog input muxes for the capture amplifiers */ + SND_SOC_DAPM_MUX("Analog Left Capture Route", + SND_SOC_NOPM, 0, 0, &amic1_control), + SND_SOC_DAPM_MUX("Analog Right Capture Route", + SND_SOC_NOPM, 0, 0, &amic2_control), + + SND_SOC_DAPM_MUX("Sidetone Audio Playback", SND_SOC_NOPM, 0, 0, + &st_audio_control), + SND_SOC_DAPM_MUX("Sidetone Voice Playback", SND_SOC_NOPM, 0, 0, + &st_voice_control), + + /* AIF */ + SND_SOC_DAPM_AIF_IN("INTF1_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 7, 0), + SND_SOC_DAPM_AIF_IN("INTF2_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 6, 0), + + SND_SOC_DAPM_AIF_OUT("INTF1_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 5, 0), + SND_SOC_DAPM_AIF_OUT("INTF2_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 4, 0), + + SND_SOC_DAPM_OUT_DRV("ULATX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("ULATX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("ULVTX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("ULVTX2", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Analog Capture PGAs */ + SND_SOC_DAPM_PGA("MicAmp1", ISABELLE_AMIC_CFG_REG, 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("MicAmp2", ISABELLE_AMIC_CFG_REG, 4, 0, NULL, 0), + + /* Auxiliary FM PGAs */ + SND_SOC_DAPM_PGA("APGA1", ISABELLE_APGA_CFG_REG, 7, 0, NULL, 0), + SND_SOC_DAPM_PGA("APGA2", ISABELLE_APGA_CFG_REG, 6, 0, NULL, 0), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC1", "Left Front Capture", + ISABELLE_AMIC_CFG_REG, 7, 0), + SND_SOC_DAPM_ADC("ADC2", "Right Front Capture", + ISABELLE_AMIC_CFG_REG, 6, 0), + + /* Microphone Bias */ + SND_SOC_DAPM_SUPPLY("Headset Mic Bias", ISABELLE_ABIAS_CFG_REG, + 3, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Main Mic Bias", ISABELLE_ABIAS_CFG_REG, + 2, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias", + ISABELLE_DBIAS_CFG_REG, 3, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias", + ISABELLE_DBIAS_CFG_REG, 2, 0, NULL, 0), + + /* Mixers */ + SND_SOC_DAPM_MIXER("Headset Left Mixer", SND_SOC_NOPM, 0, 0, + isabelle_hs_left_mixer_controls, + ARRAY_SIZE(isabelle_hs_left_mixer_controls)), + SND_SOC_DAPM_MIXER("Headset Right Mixer", SND_SOC_NOPM, 0, 0, + isabelle_hs_right_mixer_controls, + ARRAY_SIZE(isabelle_hs_right_mixer_controls)), + SND_SOC_DAPM_MIXER("Handsfree Left Mixer", SND_SOC_NOPM, 0, 0, + isabelle_hf_left_mixer_controls, + ARRAY_SIZE(isabelle_hf_left_mixer_controls)), + SND_SOC_DAPM_MIXER("Handsfree Right Mixer", SND_SOC_NOPM, 0, 0, + isabelle_hf_right_mixer_controls, + ARRAY_SIZE(isabelle_hf_right_mixer_controls)), + SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_aux_left_mixer_controls, + ARRAY_SIZE(isabelle_aux_left_mixer_controls)), + SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_aux_right_mixer_controls, + ARRAY_SIZE(isabelle_aux_right_mixer_controls)), + SND_SOC_DAPM_MIXER("Earphone Mixer", SND_SOC_NOPM, 0, 0, + isabelle_ep_mixer_controls, + ARRAY_SIZE(isabelle_ep_mixer_controls)), + + SND_SOC_DAPM_MIXER("DPGA1L Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga1_left_mixer_controls, + ARRAY_SIZE(isabelle_dpga1_left_mixer_controls)), + SND_SOC_DAPM_MIXER("DPGA1R Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga1_right_mixer_controls, + ARRAY_SIZE(isabelle_dpga1_right_mixer_controls)), + SND_SOC_DAPM_MIXER("DPGA2L Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga2_left_mixer_controls, + ARRAY_SIZE(isabelle_dpga2_left_mixer_controls)), + SND_SOC_DAPM_MIXER("DPGA2R Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga2_right_mixer_controls, + ARRAY_SIZE(isabelle_dpga2_right_mixer_controls)), + SND_SOC_DAPM_MIXER("DPGA3L Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga3_left_mixer_controls, + ARRAY_SIZE(isabelle_dpga3_left_mixer_controls)), + SND_SOC_DAPM_MIXER("DPGA3R Mixer", SND_SOC_NOPM, 0, 0, + isabelle_dpga3_right_mixer_controls, + ARRAY_SIZE(isabelle_dpga3_right_mixer_controls)), + + SND_SOC_DAPM_MIXER("RX1 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx1_mixer_controls, + ARRAY_SIZE(isabelle_rx1_mixer_controls)), + SND_SOC_DAPM_MIXER("RX2 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx2_mixer_controls, + ARRAY_SIZE(isabelle_rx2_mixer_controls)), + SND_SOC_DAPM_MIXER("RX3 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx3_mixer_controls, + ARRAY_SIZE(isabelle_rx3_mixer_controls)), + SND_SOC_DAPM_MIXER("RX4 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx4_mixer_controls, + ARRAY_SIZE(isabelle_rx4_mixer_controls)), + SND_SOC_DAPM_MIXER("RX5 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx5_mixer_controls, + ARRAY_SIZE(isabelle_rx5_mixer_controls)), + SND_SOC_DAPM_MIXER("RX6 Mixer", SND_SOC_NOPM, 0, 0, + isabelle_rx6_mixer_controls, + ARRAY_SIZE(isabelle_rx6_mixer_controls)), + + /* DACs */ + SND_SOC_DAPM_DAC("DAC1L", "Headset Playback", ISABELLE_DAC_CFG_REG, + 5, 0), + SND_SOC_DAPM_DAC("DAC1R", "Headset Playback", ISABELLE_DAC_CFG_REG, + 4, 0), + SND_SOC_DAPM_DAC("DAC2L", "Handsfree Playback", ISABELLE_DAC_CFG_REG, + 3, 0), + SND_SOC_DAPM_DAC("DAC2R", "Handsfree Playback", ISABELLE_DAC_CFG_REG, + 2, 0), + SND_SOC_DAPM_DAC("DAC3L", "Lineout Playback", ISABELLE_DAC_CFG_REG, + 1, 0), + SND_SOC_DAPM_DAC("DAC3R", "Lineout Playback", ISABELLE_DAC_CFG_REG, + 0, 0), + + /* Analog Playback PGAs */ + SND_SOC_DAPM_PGA("Sidetone Audio PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Sidetone Voice PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("HF Left PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("HF Right PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA1L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA1R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA2L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA2R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA3L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DPGA3R", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Analog Playback Mux */ + SND_SOC_DAPM_MUX("RX1 Playback", ISABELLE_ALU_RX_EN_REG, 5, 0, + &rx1_mux_controls), + SND_SOC_DAPM_MUX("RX2 Playback", ISABELLE_ALU_RX_EN_REG, 4, 0, + &rx2_mux_controls), + + /* TX Select */ + SND_SOC_DAPM_MUX("ATX Select", ISABELLE_TX_INPUT_CFG_REG, + 7, 0, &atx_mux_controls), + SND_SOC_DAPM_MUX("VTX Select", ISABELLE_TX_INPUT_CFG_REG, + 6, 0, &vtx_mux_controls), + + SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, + &ep_path_enable_control), + + /* Output Drivers */ + SND_SOC_DAPM_OUT_DRV("HS Left Driver", ISABELLE_HSDRV_CFG2_REG, + 1, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HS Right Driver", ISABELLE_HSDRV_CFG2_REG, + 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("LINEOUT1 Left Driver", ISABELLE_LINEAMP_CFG_REG, + 1, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("LINEOUT2 Right Driver", ISABELLE_LINEAMP_CFG_REG, + 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Earphone Driver", ISABELLE_EARDRV_CFG2_REG, + 1, 0, NULL, 0), + + SND_SOC_DAPM_OUT_DRV("HF Left Driver", ISABELLE_HFDRV_CFG_REG, + 1, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HF Right Driver", ISABELLE_HFDRV_CFG_REG, + 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route isabelle_intercon[] = { + /* Interface mapping */ + { "DL1", "DL12 Playback Switch", "INTF1_SDI" }, + { "DL2", "DL12 Playback Switch", "INTF1_SDI" }, + { "DL3", "DL34 Playback Switch", "INTF1_SDI" }, + { "DL4", "DL34 Playback Switch", "INTF1_SDI" }, + { "DL5", "DL56 Playback Switch", "INTF1_SDI" }, + { "DL6", "DL56 Playback Switch", "INTF1_SDI" }, + + { "DL1", "DL12 Playback Switch", "INTF2_SDI" }, + { "DL2", "DL12 Playback Switch", "INTF2_SDI" }, + { "DL3", "DL34 Playback Switch", "INTF2_SDI" }, + { "DL4", "DL34 Playback Switch", "INTF2_SDI" }, + { "DL5", "DL56 Playback Switch", "INTF2_SDI" }, + { "DL6", "DL56 Playback Switch", "INTF2_SDI" }, + + /* Input side mapping */ + { "Sidetone Audio PGA", NULL, "Sidetone Audio Playback" }, + { "Sidetone Voice PGA", NULL, "Sidetone Voice Playback" }, + + { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Audio PGA" }, + + { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, + { "RX1 Mixer", "DL1 Playback Switch", "DL1" }, + + { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Audio PGA" }, + + { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, + { "RX2 Mixer", "DL2 Playback Switch", "DL2" }, + + { "RX3 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, + { "RX3 Mixer", "DL3 Playback Switch", "DL3" }, + + { "RX4 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, + { "RX4 Mixer", "DL4 Playback Switch", "DL4" }, + + { "RX5 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, + { "RX5 Mixer", "DL5 Playback Switch", "DL5" }, + + { "RX6 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, + { "RX6 Mixer", "DL6 Playback Switch", "DL6" }, + + /* Capture path */ + { "Analog Left Capture Route", "Headset Mic", "HSMIC" }, + { "Analog Left Capture Route", "Main Mic", "MAINMIC" }, + { "Analog Left Capture Route", "Aux/FM Left", "LINEIN1" }, + + { "Analog Right Capture Route", "Sub Mic", "SUBMIC" }, + { "Analog Right Capture Route", "Aux/FM Right", "LINEIN2" }, + + { "MicAmp1", NULL, "Analog Left Capture Route" }, + { "MicAmp2", NULL, "Analog Right Capture Route" }, + + { "ADC1", NULL, "MicAmp1" }, + { "ADC2", NULL, "MicAmp2" }, + + { "ATX Select", "AMIC1", "ADC1" }, + { "ATX Select", "DMIC", "DMICDAT" }, + { "ATX Select", "AMIC2", "ADC2" }, + + { "VTX Select", "AMIC1", "ADC1" }, + { "VTX Select", "DMIC", "DMICDAT" }, + { "VTX Select", "AMIC2", "ADC2" }, + + { "ULATX1", "ATX1 Filter Enable Switch", "ATX Select" }, + { "ULATX1", "ATX1 Filter Bypass Switch", "ATX Select" }, + { "ULATX2", "ATX2 Filter Enable Switch", "ATX Select" }, + { "ULATX2", "ATX2 Filter Bypass Switch", "ATX Select" }, + + { "ULVTX1", "VTX1 Filter Enable Switch", "VTX Select" }, + { "ULVTX1", "VTX1 Filter Bypass Switch", "VTX Select" }, + { "ULVTX2", "VTX2 Filter Enable Switch", "VTX Select" }, + { "ULVTX2", "VTX2 Filter Bypass Switch", "VTX Select" }, + + { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX1" }, + { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX2" }, + { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX1" }, + { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX2" }, + + { "INTF1_SDO", NULL, "ULVTX1" }, + { "INTF1_SDO", NULL, "ULVTX2" }, + { "INTF2_SDO", NULL, "ULVTX1" }, + { "INTF2_SDO", NULL, "ULVTX2" }, + + /* AFM Path */ + { "APGA1", NULL, "LINEIN1" }, + { "APGA2", NULL, "LINEIN2" }, + + { "RX1 Playback", "VRX1 Filter Bypass Switch", "RX1 Mixer" }, + { "RX1 Playback", "ARX1 Filter Bypass Switch", "RX1 Mixer" }, + { "RX1 Playback", "RX1 Filter Enable Switch", "RX1 Mixer" }, + + { "RX2 Playback", "VRX2 Filter Bypass Switch", "RX2 Mixer" }, + { "RX2 Playback", "ARX2 Filter Bypass Switch", "RX2 Mixer" }, + { "RX2 Playback", "RX2 Filter Enable Switch", "RX2 Mixer" }, + + { "RX3 Playback", "ARX3 Filter Bypass Switch", "RX3 Mixer" }, + { "RX3 Playback", "RX3 Filter Enable Switch", "RX3 Mixer" }, + + { "RX4 Playback", "ARX4 Filter Bypass Switch", "RX4 Mixer" }, + { "RX4 Playback", "RX4 Filter Enable Switch", "RX4 Mixer" }, + + { "RX5 Playback", "ARX5 Filter Bypass Switch", "RX5 Mixer" }, + { "RX5 Playback", "RX5 Filter Enable Switch", "RX5 Mixer" }, + + { "RX6 Playback", "ARX6 Filter Bypass Switch", "RX6 Mixer" }, + { "RX6 Playback", "RX6 Filter Enable Switch", "RX6 Mixer" }, + + { "DPGA1L Mixer", "RX1 Playback Switch", "RX1 Playback" }, + { "DPGA1L Mixer", "RX3 Playback Switch", "RX3 Playback" }, + { "DPGA1L Mixer", "RX5 Playback Switch", "RX5 Playback" }, + + { "DPGA1R Mixer", "RX2 Playback Switch", "RX2 Playback" }, + { "DPGA1R Mixer", "RX4 Playback Switch", "RX4 Playback" }, + { "DPGA1R Mixer", "RX6 Playback Switch", "RX6 Playback" }, + + { "DPGA1L", NULL, "DPGA1L Mixer" }, + { "DPGA1R", NULL, "DPGA1R Mixer" }, + + { "DAC1L", NULL, "DPGA1L" }, + { "DAC1R", NULL, "DPGA1R" }, + + { "DPGA2L Mixer", "RX1 Playback Switch", "RX1 Playback" }, + { "DPGA2L Mixer", "RX2 Playback Switch", "RX2 Playback" }, + { "DPGA2L Mixer", "RX3 Playback Switch", "RX3 Playback" }, + { "DPGA2L Mixer", "RX4 Playback Switch", "RX4 Playback" }, + { "DPGA2L Mixer", "RX5 Playback Switch", "RX5 Playback" }, + { "DPGA2L Mixer", "RX6 Playback Switch", "RX6 Playback" }, + + { "DPGA2R Mixer", "RX2 Playback Switch", "RX2 Playback" }, + { "DPGA2R Mixer", "RX4 Playback Switch", "RX4 Playback" }, + { "DPGA2R Mixer", "RX6 Playback Switch", "RX6 Playback" }, + + { "DPGA2L", NULL, "DPGA2L Mixer" }, + { "DPGA2R", NULL, "DPGA2R Mixer" }, + + { "DAC2L", NULL, "DPGA2L" }, + { "DAC2R", NULL, "DPGA2R" }, + + { "DPGA3L Mixer", "RX1 Playback Switch", "RX1 Playback" }, + { "DPGA3L Mixer", "RX3 Playback Switch", "RX3 Playback" }, + { "DPGA3L Mixer", "RX5 Playback Switch", "RX5 Playback" }, + + { "DPGA3R Mixer", "RX2 Playback Switch", "RX2 Playback" }, + { "DPGA3R Mixer", "RX4 Playback Switch", "RX4 Playback" }, + { "DPGA3R Mixer", "RX6 Playback Switch", "RX6 Playback" }, + + { "DPGA3L", NULL, "DPGA3L Mixer" }, + { "DPGA3R", NULL, "DPGA3R Mixer" }, + + { "DAC3L", NULL, "DPGA3L" }, + { "DAC3R", NULL, "DPGA3R" }, + + { "Headset Left Mixer", "DAC1L Playback Switch", "DAC1L" }, + { "Headset Left Mixer", "APGA1 Playback Switch", "APGA1" }, + + { "Headset Right Mixer", "DAC1R Playback Switch", "DAC1R" }, + { "Headset Right Mixer", "APGA2 Playback Switch", "APGA2" }, + + { "HS Left Driver", NULL, "Headset Left Mixer" }, + { "HS Right Driver", NULL, "Headset Right Mixer" }, + + { "HSOL", NULL, "HS Left Driver" }, + { "HSOR", NULL, "HS Right Driver" }, + + /* Earphone playback path */ + { "Earphone Mixer", "DAC2L Playback Switch", "DAC2L" }, + { "Earphone Mixer", "APGA1 Playback Switch", "APGA1" }, + + { "Earphone Playback", "Switch", "Earphone Mixer" }, + { "Earphone Driver", NULL, "Earphone Playback" }, + { "EP", NULL, "Earphone Driver" }, + + { "Handsfree Left Mixer", "DAC2L Playback Switch", "DAC2L" }, + { "Handsfree Left Mixer", "APGA1 Playback Switch", "APGA1" }, + + { "Handsfree Right Mixer", "DAC2R Playback Switch", "DAC2R" }, + { "Handsfree Right Mixer", "APGA2 Playback Switch", "APGA2" }, + + { "HF Left PGA", NULL, "Handsfree Left Mixer" }, + { "HF Right PGA", NULL, "Handsfree Right Mixer" }, + + { "HF Left Driver", NULL, "HF Left PGA" }, + { "HF Right Driver", NULL, "HF Right PGA" }, + + { "HFL", NULL, "HF Left Driver" }, + { "HFR", NULL, "HF Right Driver" }, + + { "LINEOUT1 Mixer", "DAC3L Playback Switch", "DAC3L" }, + { "LINEOUT1 Mixer", "APGA1 Playback Switch", "APGA1" }, + + { "LINEOUT2 Mixer", "DAC3R Playback Switch", "DAC3R" }, + { "LINEOUT2 Mixer", "APGA2 Playback Switch", "APGA2" }, + + { "LINEOUT1 Driver", NULL, "LINEOUT1 Mixer" }, + { "LINEOUT2 Driver", NULL, "LINEOUT2 Mixer" }, + + { "LINEOUT1", NULL, "LINEOUT1 Driver" }, + { "LINEOUT2", NULL, "LINEOUT2 Driver" }, +}; + +static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) +{ + snd_soc_update_bits(dai->codec, ISABELLE_DAC1_SOFTRAMP_REG, + BIT(4), (mute ? BIT(4) : 0)); + + return 0; +} + +static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) +{ + snd_soc_update_bits(dai->codec, ISABELLE_DAC2_SOFTRAMP_REG, + BIT(4), (mute ? BIT(4) : 0)); + + return 0; +} + +static int isabelle_line_mute(struct snd_soc_dai *dai, int mute) +{ + snd_soc_update_bits(dai->codec, ISABELLE_DAC3_SOFTRAMP_REG, + BIT(4), (mute ? BIT(4) : 0)); + + return 0; +} + +static int isabelle_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, + ISABELLE_CHIP_EN, BIT(0)); + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, + ISABELLE_CHIP_EN, 0); + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static int isabelle_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + u16 aif = 0; + unsigned int fs_val = 0; + + switch (params_rate(params)) { + case 8000: + fs_val = ISABELLE_FS_RATE_8; + break; + case 11025: + fs_val = ISABELLE_FS_RATE_11; + break; + case 12000: + fs_val = ISABELLE_FS_RATE_12; + break; + case 16000: + fs_val = ISABELLE_FS_RATE_16; + break; + case 22050: + fs_val = ISABELLE_FS_RATE_22; + break; + case 24000: + fs_val = ISABELLE_FS_RATE_24; + break; + case 32000: + fs_val = ISABELLE_FS_RATE_32; + break; + case 44100: + fs_val = ISABELLE_FS_RATE_44; + break; + case 48000: + fs_val = ISABELLE_FS_RATE_48; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, ISABELLE_FS_RATE_CFG_REG, + ISABELLE_FS_RATE_MASK, fs_val); + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S20_3LE: + aif |= ISABELLE_AIF_LENGTH_20; + break; + case SNDRV_PCM_FORMAT_S32_LE: + aif |= ISABELLE_AIF_LENGTH_32; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, + ISABELLE_AIF_LENGTH_MASK, aif); + + return 0; +} + +static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int aif_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + aif_val &= ~ISABELLE_AIF_MS; + break; + case SND_SOC_DAIFMT_CBM_CFM: + aif_val |= ISABELLE_AIF_MS; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + aif_val |= ISABELLE_I2S_MODE; + break; + case SND_SOC_DAIFMT_LEFT_J: + aif_val |= ISABELLE_LEFT_J_MODE; + break; + case SND_SOC_DAIFMT_PDM: + aif_val |= ISABELLE_PDM_MODE; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, + (ISABELLE_AIF_MS | ISABELLE_AIF_FMT_MASK), aif_val); + + return 0; +} + +/* Rates supported by Isabelle driver */ +#define ISABELLE_RATES SNDRV_PCM_RATE_8000_48000 + +/* Formates supported by Isabelle driver. */ +#define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops isabelle_hs_dai_ops = { + .hw_params = isabelle_hw_params, + .set_fmt = isabelle_set_dai_fmt, + .digital_mute = isabelle_hs_mute, +}; + +static struct snd_soc_dai_ops isabelle_hf_dai_ops = { + .hw_params = isabelle_hw_params, + .set_fmt = isabelle_set_dai_fmt, + .digital_mute = isabelle_hf_mute, +}; + +static struct snd_soc_dai_ops isabelle_line_dai_ops = { + .hw_params = isabelle_hw_params, + .set_fmt = isabelle_set_dai_fmt, + .digital_mute = isabelle_line_mute, +}; + +static struct snd_soc_dai_ops isabelle_ul_dai_ops = { + .hw_params = isabelle_hw_params, + .set_fmt = isabelle_set_dai_fmt, +}; + +/* ISABELLE dai structure */ +struct snd_soc_dai_driver isabelle_dai[] = { + { + .name = "isabelle-dl1", + .playback = { + .stream_name = "Headset Playback", + .channels_min = 1, + .channels_max = 2, + .rates = ISABELLE_RATES, + .formats = ISABELLE_FORMATS, + }, + .ops = &isabelle_hs_dai_ops, + }, + { + .name = "isabelle-dl2", + .playback = { + .stream_name = "Handsfree Playback", + .channels_min = 1, + .channels_max = 2, + .rates = ISABELLE_RATES, + .formats = ISABELLE_FORMATS, + }, + .ops = &isabelle_hf_dai_ops, + }, + { + .name = "isabelle-lineout", + .playback = { + .stream_name = "Lineout Playback", + .channels_min = 1, + .channels_max = 2, + .rates = ISABELLE_RATES, + .formats = ISABELLE_FORMATS, + }, + .ops = &isabelle_line_dai_ops, + }, + { + .name = "isabelle-ul", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = ISABELLE_RATES, + .formats = ISABELLE_FORMATS, + }, + .ops = &isabelle_ul_dai_ops, + }, +}; + +static int isabelle_probe(struct snd_soc_codec *codec) +{ + int ret = 0; + + codec->control_data = dev_get_regmap(codec->dev, NULL); + + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_isabelle = { + .probe = isabelle_probe, + .set_bias_level = isabelle_set_bias_level, + .controls = isabelle_snd_controls, + .num_controls = ARRAY_SIZE(isabelle_snd_controls), + .dapm_widgets = isabelle_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), + .dapm_routes = isabelle_intercon, + .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), + .idle_bias_off = true, +}; + +static const struct regmap_config isabelle_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = ISABELLE_MAX_REGISTER, + .reg_defaults = isabelle_reg_defs, + .num_reg_defaults = ARRAY_SIZE(isabelle_reg_defs), + .cache_type = REGCACHE_RBTREE, +}; + +static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *isabelle_regmap; + int ret = 0; + + i2c_set_clientdata(i2c, isabelle_regmap); + + isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config); + if (IS_ERR(isabelle_regmap)) { + ret = PTR_ERR(isabelle_regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_isabelle, isabelle_dai, + ARRAY_SIZE(isabelle_dai)); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); + regmap_exit(dev_get_regmap(&i2c->dev, NULL)); + return ret; + } + + return ret; +} + +static int __devexit isabelle_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + regmap_exit(dev_get_regmap(&client->dev, NULL)); + return 0; +} + +static const struct i2c_device_id isabelle_i2c_id[] = { + { "isabelle", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); + +static struct i2c_driver isabelle_i2c_driver = { + .driver = { + .name = "isabelle", + .owner = THIS_MODULE, + }, + .probe = isabelle_i2c_probe, + .remove = __devexit_p(isabelle_i2c_remove), + .id_table = isabelle_i2c_id, +}; + +module_i2c_driver(isabelle_i2c_driver); + +MODULE_DESCRIPTION("ASoC ISABELLE driver"); +MODULE_AUTHOR("Vishwas A Deshpande "); +MODULE_AUTHOR("M R Swami Reddy "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/isabelle.h b/sound/soc/codecs/isabelle.h new file mode 100644 index 000000000000..96d839a8c956 --- /dev/null +++ b/sound/soc/codecs/isabelle.h @@ -0,0 +1,143 @@ +/* + * isabelle.h - Low power high fidelity audio codec driver header file + * + * Copyright (c) 2012 Texas Instruments, Inc + * + * 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. + * + */ + +#ifndef _ISABELLE_H +#define _ISABELLE_H + +#include + +/* ISABELLE REGISTERS */ + +#define ISABELLE_PWR_CFG_REG 0x01 +#define ISABELLE_PWR_EN_REG 0x02 +#define ISABELLE_PS_EN1_REG 0x03 +#define ISABELLE_INT1_STATUS_REG 0x04 +#define ISABELLE_INT1_MASK_REG 0x05 +#define ISABELLE_INT2_STATUS_REG 0x06 +#define ISABELLE_INT2_MASK_REG 0x07 +#define ISABELLE_HKCTL1_REG 0x08 +#define ISABELLE_HKCTL2_REG 0x09 +#define ISABELLE_HKCTL3_REG 0x0A +#define ISABELLE_ACCDET_STATUS_REG 0x0B +#define ISABELLE_BUTTON_ID_REG 0x0C +#define ISABELLE_PLL_CFG_REG 0x10 +#define ISABELLE_PLL_EN_REG 0x11 +#define ISABELLE_FS_RATE_CFG_REG 0x12 +#define ISABELLE_INTF_CFG_REG 0x13 +#define ISABELLE_INTF_EN_REG 0x14 +#define ISABELLE_ULATX12_INTF_CFG_REG 0x15 +#define ISABELLE_DL12_INTF_CFG_REG 0x16 +#define ISABELLE_DL34_INTF_CFG_REG 0x17 +#define ISABELLE_DL56_INTF_CFG_REG 0x18 +#define ISABELLE_ATX_STPGA1_CFG_REG 0x19 +#define ISABELLE_ATX_STPGA2_CFG_REG 0x1A +#define ISABELLE_VTX_STPGA1_CFG_REG 0x1B +#define ISABELLE_VTX2_STPGA2_CFG_REG 0x1C +#define ISABELLE_ATX1_DPGA_REG 0x1D +#define ISABELLE_ATX2_DPGA_REG 0x1E +#define ISABELLE_VTX1_DPGA_REG 0x1F +#define ISABELLE_VTX2_DPGA_REG 0x20 +#define ISABELLE_TX_INPUT_CFG_REG 0x21 +#define ISABELLE_RX_INPUT_CFG_REG 0x22 +#define ISABELLE_RX_INPUT_CFG2_REG 0x23 +#define ISABELLE_VOICE_HPF_CFG_REG 0x24 +#define ISABELLE_AUDIO_HPF_CFG_REG 0x25 +#define ISABELLE_RX1_DPGA_REG 0x26 +#define ISABELLE_RX2_DPGA_REG 0x27 +#define ISABELLE_RX3_DPGA_REG 0x28 +#define ISABELLE_RX4_DPGA_REG 0x29 +#define ISABELLE_RX5_DPGA_REG 0x2A +#define ISABELLE_RX6_DPGA_REG 0x2B +#define ISABELLE_ALU_TX_EN_REG 0x2C +#define ISABELLE_ALU_RX_EN_REG 0x2D +#define ISABELLE_IIR_RESYNC_REG 0x2E +#define ISABELLE_ABIAS_CFG_REG 0x30 +#define ISABELLE_DBIAS_CFG_REG 0x31 +#define ISABELLE_MIC1_GAIN_REG 0x32 +#define ISABELLE_MIC2_GAIN_REG 0x33 +#define ISABELLE_AMIC_CFG_REG 0x34 +#define ISABELLE_DMIC_CFG_REG 0x35 +#define ISABELLE_APGA_GAIN_REG 0x36 +#define ISABELLE_APGA_CFG_REG 0x37 +#define ISABELLE_TX_GAIN_DLY_REG 0x38 +#define ISABELLE_RX_GAIN_DLY_REG 0x39 +#define ISABELLE_RX_PWR_CTRL_REG 0x3A +#define ISABELLE_DPGA1LR_IN_SEL_REG 0x3B +#define ISABELLE_DPGA1L_GAIN_REG 0x3C +#define ISABELLE_DPGA1R_GAIN_REG 0x3D +#define ISABELLE_DPGA2L_IN_SEL_REG 0x3E +#define ISABELLE_DPGA2R_IN_SEL_REG 0x3F +#define ISABELLE_DPGA2L_GAIN_REG 0x40 +#define ISABELLE_DPGA2R_GAIN_REG 0x41 +#define ISABELLE_DPGA3LR_IN_SEL_REG 0x42 +#define ISABELLE_DPGA3L_GAIN_REG 0x43 +#define ISABELLE_DPGA3R_GAIN_REG 0x44 +#define ISABELLE_DAC1_SOFTRAMP_REG 0x45 +#define ISABELLE_DAC2_SOFTRAMP_REG 0x46 +#define ISABELLE_DAC3_SOFTRAMP_REG 0x47 +#define ISABELLE_DAC_CFG_REG 0x48 +#define ISABELLE_EARDRV_CFG1_REG 0x49 +#define ISABELLE_EARDRV_CFG2_REG 0x4A +#define ISABELLE_HSDRV_GAIN_REG 0x4B +#define ISABELLE_HSDRV_CFG1_REG 0x4C +#define ISABELLE_HSDRV_CFG2_REG 0x4D +#define ISABELLE_HS_NG_CFG1_REG 0x4E +#define ISABELLE_HS_NG_CFG2_REG 0x4F +#define ISABELLE_LINEAMP_GAIN_REG 0x50 +#define ISABELLE_LINEAMP_CFG_REG 0x51 +#define ISABELLE_HFL_VOL_CTRL_REG 0x52 +#define ISABELLE_HFL_SFTVOL_CTRL_REG 0x53 +#define ISABELLE_HFL_LIM_CTRL_1_REG 0x54 +#define ISABELLE_HFL_LIM_CTRL_2_REG 0x55 +#define ISABELLE_HFR_VOL_CTRL_REG 0x56 +#define ISABELLE_HFR_SFTVOL_CTRL_REG 0x57 +#define ISABELLE_HFR_LIM_CTRL_1_REG 0x58 +#define ISABELLE_HFR_LIM_CTRL_2_REG 0x59 +#define ISABELLE_HF_MODE_REG 0x5A +#define ISABELLE_HFLPGA_CFG_REG 0x5B +#define ISABELLE_HFRPGA_CFG_REG 0x5C +#define ISABELLE_HFDRV_CFG_REG 0x5D +#define ISABELLE_PDMOUT_CFG1_REG 0x5E +#define ISABELLE_PDMOUT_CFG2_REG 0x5F +#define ISABELLE_PDMOUT_L_WM_REG 0x60 +#define ISABELLE_PDMOUT_R_WM_REG 0x61 +#define ISABELLE_HF_NG_CFG1_REG 0x62 +#define ISABELLE_HF_NG_CFG2_REG 0x63 + +/* ISABELLE_PWR_EN_REG (0x02h) */ +#define ISABELLE_CHIP_EN BIT(0) + +/* ISABELLE DAI FORMATS */ +#define ISABELLE_AIF_FMT_MASK 0x70 +#define ISABELLE_I2S_MODE 0x0 +#define ISABELLE_LEFT_J_MODE 0x1 +#define ISABELLE_PDM_MODE 0x2 + +#define ISABELLE_AIF_LENGTH_MASK 0x30 +#define ISABELLE_AIF_LENGTH_20 0x00 +#define ISABELLE_AIF_LENGTH_32 0x10 + +#define ISABELLE_AIF_MS 0x80 + +#define ISABELLE_FS_RATE_MASK 0xF +#define ISABELLE_FS_RATE_8 0x0 +#define ISABELLE_FS_RATE_11 0x1 +#define ISABELLE_FS_RATE_12 0x2 +#define ISABELLE_FS_RATE_16 0x4 +#define ISABELLE_FS_RATE_22 0x5 +#define ISABELLE_FS_RATE_24 0x6 +#define ISABELLE_FS_RATE_32 0x8 +#define ISABELLE_FS_RATE_44 0x9 +#define ISABELLE_FS_RATE_48 0xA + +#define ISABELLE_MAX_REGISTER 0xFF + +#endif -- GitLab From 5eba8ec37fe8cfed4cacff56f9025b756cc43faa Mon Sep 17 00:00:00 2001 From: MR Swami Reddy Date: Mon, 4 Jun 2012 17:44:54 +0530 Subject: [PATCH 0309/5711] ASoC: isabelle: Remove regmap_exit() With devm_ APIs regmap_exit() not needed, so remove regmap_exit(). Signed-off-by: Vishwas A Deshpande Signed-off-by: M R Swami Reddy Signed-off-by: Mark Brown --- sound/soc/codecs/isabelle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index b6921a82fbcc..bcc77ef0eda2 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1141,7 +1141,6 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, ARRAY_SIZE(isabelle_dai)); if (ret < 0) { dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - regmap_exit(dev_get_regmap(&i2c->dev, NULL)); return ret; } @@ -1151,7 +1150,6 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, static int __devexit isabelle_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - regmap_exit(dev_get_regmap(&client->dev, NULL)); return 0; } -- GitLab From 165961efc03159631eadc086877704c7778ac356 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 10:44:23 +0100 Subject: [PATCH 0310/5711] ASoC: dapm: The clock API is even less consistent than thought Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 39e8c2fdf50e..7365fed1ba74 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2904,7 +2904,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, } break; case snd_soc_dapm_clock_supply: -#ifdef CONFIG_HAVE_CLK +#ifdef CONFIG_CLKDEV_LOOKUP w->clk = devm_clk_get(dapm->dev, w->name); if (IS_ERR(w->clk)) { ret = PTR_ERR(w->clk); -- GitLab From 571f6a7f07e9dda6c9795398747278e52368c88a Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Mon, 4 Jun 2012 13:19:41 -0500 Subject: [PATCH 0311/5711] ASoC: cs42l73: Convert to devm_regmap_init_i2c() Signed-off-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index e0d45fdaa750..2c08c4cb465a 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1362,11 +1362,11 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, i2c_set_clientdata(i2c_client, cs42l73); - cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap); + cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); if (IS_ERR(cs42l73->regmap)) { ret = PTR_ERR(cs42l73->regmap); dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); - goto err; + return ret; } /* initialize codec */ ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); @@ -1384,13 +1384,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L73 Device ID (%X). Expected %X\n", devid, CS42L73_DEVID); - goto err_regmap; + return ret; } ret = regmap_read(cs42l73->regmap, CS42L73_REVID, ®); if (ret < 0) { dev_err(&i2c_client->dev, "Get Revision ID failed\n"); - goto err_regmap; + return ret;; } dev_info(&i2c_client->dev, @@ -1402,23 +1402,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, &soc_codec_dev_cs42l73, cs42l73_dai, ARRAY_SIZE(cs42l73_dai)); if (ret < 0) - goto err_regmap; + return ret; return 0; - -err_regmap: - regmap_exit(cs42l73->regmap); - -err: - return ret; } static __devexit int cs42l73_i2c_remove(struct i2c_client *client) { - struct cs42l73_private *cs42l73 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(cs42l73->regmap); - return 0; } -- GitLab From 134b2f576b9144223dd5b59a496218e3aadaf56b Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Mon, 4 Jun 2012 13:19:42 -0500 Subject: [PATCH 0312/5711] ASoC: cs42l52: Convert to devm_regmap_init_i2c() Signed-off-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index ec03abc79a9a..628daf6a1d97 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1216,11 +1216,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, return -ENOMEM; cs42l52->dev = &i2c_client->dev; - cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap); + cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap); if (IS_ERR(cs42l52->regmap)) { ret = PTR_ERR(cs42l52->regmap); dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); - goto err; + return ret; } i2c_set_clientdata(i2c_client, cs42l52); @@ -1242,7 +1242,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L52 Device ID (%X). Expected %X\n", devid, CS42L52_CHIP_ID); - goto err_regmap; + return ret; } regcache_cache_only(cs42l52->regmap, true); @@ -1250,23 +1250,13 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_dev_cs42l52, &cs42l52_dai, 1); if (ret < 0) - goto err_regmap; + return ret; return 0; - -err_regmap: - regmap_exit(cs42l52->regmap); - -err: - return ret; } static int cs42l52_i2c_remove(struct i2c_client *client) { - struct cs42l52_private *cs42l52 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(cs42l52->regmap); - return 0; } -- GitLab From 61dc479e99d4d74c6113656dc50babed90a384c5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 11:08:45 +0100 Subject: [PATCH 0313/5711] Revert "ASoC: fsl_ssi: convert to use devm_clk_get" This reverts commit 014e5b56702575c5cd8ffc4b1a7924cfdfe0f1ea since PowerPC doesn't use clkdev and hasn't implemented devm_clk_get() itself. Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index b10a427a8098..4ed2afd47782 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -725,7 +725,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) u32 dma_events[2]; ssi_private->ssi_on_imx = true; - ssi_private->clk = devm_clk_get(&pdev->dev, NULL); + ssi_private->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(ssi_private->clk)) { ret = PTR_ERR(ssi_private->clk); dev_err(&pdev->dev, "could not get clock: %d\n", ret); @@ -842,8 +842,10 @@ error_dev: device_remove_file(&pdev->dev, dev_attr); error_clk: - if (ssi_private->ssi_on_imx) + if (ssi_private->ssi_on_imx) { clk_disable_unprepare(ssi_private->clk); + clk_put(ssi_private->clk); + } error_irq: free_irq(ssi_private->irq, ssi_private); @@ -869,6 +871,7 @@ static int fsl_ssi_remove(struct platform_device *pdev) if (ssi_private->ssi_on_imx) { platform_device_unregister(ssi_private->imx_pcm_pdev); clk_disable_unprepare(ssi_private->clk); + clk_put(ssi_private->clk); } snd_soc_unregister_dai(&pdev->dev); device_remove_file(&pdev->dev, &ssi_private->dev_attr); -- GitLab From cd86e3ce304189fbdb144622245d0da9189551a1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jun 2012 18:20:21 +0100 Subject: [PATCH 0314/5711] ASoC: lm59453: Unconstify dai_driver The core fills in some blanks which makes it annoying to do the right thing and constify the calls in the core. Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index c1bc9458906b..99b0a9dcff34 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1357,7 +1357,7 @@ static struct snd_soc_dai_ops lm49453_lineout_dai_ops = { }; /* LM49453 dai structure. */ -static const struct snd_soc_dai_driver lm49453_dai[] = { +static struct snd_soc_dai_driver lm49453_dai[] = { { .name = "LM49453 Headset", .playback = { -- GitLab From 223f18e4482fd90b7cdabb222fad5ca502dc0028 Mon Sep 17 00:00:00 2001 From: Raymond Yau Date: Mon, 4 Jun 2012 14:59:55 +0800 Subject: [PATCH 0315/5711] ALSA: au88x0 - Remove unused "Master Mono" Playback Volume and Playback Switch of ac97 codec Remove "Master Mono Playback Volume" and "Master Mono Playback Switch" of ac97 mixer since au88x0 does no use "Master Mono Pin" of AC97 codec even au88x0 support mono playback Signed-off-by: Raymond Yau Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0_mixer.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c index 557c782ae4fc..fa13efbebdaf 100644 --- a/sound/pci/au88x0/au88x0_mixer.c +++ b/sound/pci/au88x0/au88x0_mixer.c @@ -10,6 +10,15 @@ #include #include "au88x0.h" +static int remove_ctl(struct snd_card *card, const char *name) +{ + struct snd_ctl_elem_id id; + memset(&id, 0, sizeof(id)); + strcpy(id.name, name); + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + return snd_ctl_remove_id(card, &id); +} + static int __devinit snd_vortex_mixer(vortex_t * vortex) { struct snd_ac97_bus *pbus; @@ -28,5 +37,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex) ac97.scaps = AC97_SCAP_NO_SPDIF; err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80)); + remove_ctl(vortex->card, "Master Mono Playback Volume"); + remove_ctl(vortex->card, "Master Mono Playback Switch"); return err; } -- GitLab From 6edab08c24f9141d69cfa4683a0a027d86ab303e Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 1 Jun 2012 19:45:32 -0400 Subject: [PATCH 0316/5711] intel_idle: initial IVB support From an OS point of view, IVB looks like SNB, but quicker. Signed-off-by: Len Brown --- drivers/idle/intel_idle.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index d0f59c3f87ef..a759a4c4bb0a 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -169,6 +169,38 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { .enter = &intel_idle }, }; +static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = { + { /* MWAIT C0 */ }, + { /* MWAIT C1 */ + .name = "C1-IVB", + .desc = "MWAIT 0x00", + .flags = CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 1, + .target_residency = 1, + .enter = &intel_idle }, + { /* MWAIT C2 */ + .name = "C3-IVB", + .desc = "MWAIT 0x10", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 59, + .target_residency = 156, + .enter = &intel_idle }, + { /* MWAIT C3 */ + .name = "C6-IVB", + .desc = "MWAIT 0x20", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 80, + .target_residency = 300, + .enter = &intel_idle }, + { /* MWAIT C4 */ + .name = "C7-IVB", + .desc = "MWAIT 0x30", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 87, + .target_residency = 300, + .enter = &intel_idle }, +}; + static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C0 */ }, { /* MWAIT C1 */ @@ -347,6 +379,10 @@ static const struct idle_cpu idle_cpu_snb = { .state_table = snb_cstates, }; +static const struct idle_cpu idle_cpu_ivb = { + .state_table = ivb_cstates, +}; + #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } @@ -362,6 +398,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x2f, idle_cpu_nehalem), ICPU(0x2a, idle_cpu_snb), ICPU(0x2d, idle_cpu_snb), + ICPU(0x3a, idle_cpu_ivb), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); -- GitLab From 7a87c289778c5ee7ef79be5fba27e081383a30f3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 11:03:39 +0200 Subject: [PATCH 0317/5711] drm/i915: implement IBX hdmi transcoder select workaround Bspec Vol 3, Part 3, Section 3.8.1.1, bit 30: "[DevIBX] Writing to this bit only takes effect when port is enabled. Due to hardware issue it is required that this bit be cleared when port is disabled. To clear this bit software must temporarily enable this port on transcoder A." Unfortunately the public Bspec misses totally out on the same language for HDMIB. Internal Bspec also mentions that one of the bad side-effects is that DPx can fail to light up on transcoder A if HDMIx is disabled but using transcoder B. I've found this while reviewing Bsepc. We already implement the same workaround for the DP ports. Also replace a magic 1 with PIPE_B I've found while looking through the code. v2: Implement suggestions from Chris Wilson: - add pipe variable to cut down on code noise - write the reg value twice to w/a hw issues (Bspec is unclear on which bit actually require the write twice stuff, but better be paranoid about it) - untangle the if logic Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 32 ++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index b507d38faa10..69637db9af1f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -569,7 +569,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, if (HAS_PCH_CPT(dev)) sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); - else if (intel_crtc->pipe == 1) + else if (intel_crtc->pipe == PIPE_B) sdvox |= SDVO_PIPE_B_SELECT; I915_WRITE(intel_hdmi->sdvox_reg, sdvox); @@ -591,6 +591,36 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) temp = I915_READ(intel_hdmi->sdvox_reg); + /* HW workaround for IBX, we need to move the port to transcoder A + * before disabling it. */ + if (HAS_PCH_IBX(dev)) { + struct drm_crtc *crtc = encoder->crtc; + int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; + + if (mode != DRM_MODE_DPMS_ON) { + if (temp & SDVO_PIPE_B_SELECT) { + temp &= ~SDVO_PIPE_B_SELECT; + I915_WRITE(intel_hdmi->sdvox_reg, temp); + POSTING_READ(intel_hdmi->sdvox_reg); + + /* Again we need to write this twice. */ + I915_WRITE(intel_hdmi->sdvox_reg, temp); + POSTING_READ(intel_hdmi->sdvox_reg); + + /* Transcoder selection bits only update + * effectively on vblank. */ + if (crtc) + intel_wait_for_vblank(dev, pipe); + else + msleep(50); + } + } else { + /* Restore the transcoder select bit. */ + if (pipe == PIPE_B) + enable_bits |= SDVO_PIPE_B_SELECT; + } + } + /* HW workaround, need to toggle enable bit off and on for 12bpc, but * we do this anyway which shows more stable in testing. */ -- GitLab From de9a35abb3b343a25065449234e47a76c4f3454a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 11:03:40 +0200 Subject: [PATCH 0318/5711] drm/i915: assert that the IBX port transcoder select w/a is implemented Let's be a bit more paranoid here. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0161d947ab81..5e760319c0f2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1232,6 +1232,9 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); + + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + "IBX PCH dp port still using transcoder B\n"); } static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, @@ -1241,6 +1244,9 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, WARN(hdmi_pipe_enabled(dev_priv, val, pipe), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); + + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + "IBX PCH hdmi port still using transcoder B\n"); } static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, -- GitLab From 6dbc10c61d5841f64945fd94977fa8fa1c0192da Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 17 Feb 2012 11:58:14 +0200 Subject: [PATCH 0319/5711] usb: dwc3: gadget: drop useless code We never set CMDIOC bit for Start Transfer command, so that code will never be used. Tested-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 854f3a3c8832..056ace8ab97d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1765,9 +1765,6 @@ static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, case DWC3_DEPCMD_ENDTRANSFER: dwc3_process_ep_cmd_complete(dep, event); break; - case DWC3_DEPCMD_STARTTRANSFER: - dep->res_trans_idx = param & 0x7f; - break; default: printk(KERN_ERR "%s() unknown /unexpected type: %d\n", __func__, cmd_type); -- GitLab From ea53b8828c50b7a5138a8931c41b2671682c86b5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 17 Feb 2012 12:10:04 +0200 Subject: [PATCH 0320/5711] usb: dwc3: gadget: don't wait for ep cmd IRQ That IRQ is causing way too much trouble. We have a different handling which was agreed with IP provider and has been tested with FPGA and OMAP5. Tested-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 66 ++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 056ace8ab97d..0f19978d4840 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -555,9 +555,34 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_request *req; - if (!list_empty(&dep->req_queued)) + if (!list_empty(&dep->req_queued)) { dwc3_stop_active_transfer(dwc, dep->number); + /* + * NOTICE: We are violating what the Databook says about the + * EndTransfer command. Ideally we would _always_ wait for the + * EndTransfer Command Completion IRQ, but that's causing too + * much trouble synchronizing between us and gadget driver. + * + * We have discussed this with the IP Provider and it was + * suggested to giveback all requests here, but give HW some + * extra time to synchronize with the interconnect. We're using + * an arbitraty 100us delay for that. + * + * Note also that a similar handling was tested by Synopsys + * (thanks a lot Paul) and nothing bad has come out of it. + * In short, what we're doing is: + * + * - Issue EndTransfer WITH CMDIOC bit set + * - Wait 100us + * - giveback all requests to gadget driver + */ + udelay(100); + + req = next_request(&dep->req_queued); + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); + } + while (!list_empty(&dep->request_list)) { req = next_request(&dep->request_list); @@ -1735,43 +1760,6 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, } } -static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, - const struct dwc3_event_depevt *event) -{ - struct dwc3 *dwc = dep->dwc; - struct dwc3_event_depevt mod_ev = *event; - - /* - * We were asked to remove one request. It is possible that this - * request and a few others were started together and have the same - * transfer index. Since we stopped the complete endpoint we don't - * know how many requests were already completed (and not yet) - * reported and how could be done (later). We purge them all until - * the end of the list. - */ - mod_ev.status = DEPEVT_STATUS_LST; - dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); - dep->flags &= ~DWC3_EP_BUSY; - /* pending requests are ignored and are queued on XferNotReady */ -} - -static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, - const struct dwc3_event_depevt *event) -{ - u32 param = event->parameters; - u32 cmd_type = (param >> 8) & ((1 << 5) - 1); - - switch (cmd_type) { - case DWC3_DEPCMD_ENDTRANSFER: - dwc3_process_ep_cmd_complete(dep, event); - break; - default: - printk(KERN_ERR "%s() unknown /unexpected type: %d\n", - __func__, cmd_type); - break; - }; -} - static void dwc3_endpoint_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { @@ -1853,7 +1841,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); break; case DWC3_DEPEVT_EPCMDCMPLT: - dwc3_ep_cmd_compl(dep, event); + dev_vdbg(dwc->dev, "Endpoint Command Complete\n"); break; } } -- GitLab From 1e2360eadaa33c09bb72afb14f74b6c6ab2aca66 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Jun 2012 09:18:12 +0300 Subject: [PATCH 0321/5711] usb: dwc3: gadget: don't call stop_active_transfers() on disconnect In case we get disconnected, we will call gadget driver's disconnect method, which should make sure to disable all endpoints. At that point we will call stop_active_transfers() to make sure we didn't leave any pending request on the controller. Tested-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0f19978d4840..52d0f67e33d5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1927,7 +1927,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) reg &= ~DWC3_DCTL_INITU2ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); - dwc3_stop_active_transfers(dwc); dwc3_disconnect_gadget(dwc); dwc->start_config_issued = false; -- GitLab From 3336abb5b608300550136ddab7a7101b30d45fa7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Jun 2012 09:19:35 +0300 Subject: [PATCH 0322/5711] usb: dwc3: gadget: ignore endpoint IRQs when endpoint is disabled By the time we're disabling the endpoint, HW could already have posted more events to our event buffer. In that case, we will receive endpoint events for a disabled endpoint. In order to protect ourselves from that situation, we simply ignore endpoint interrupts whenever the endpoint is disabled. Tested-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 52d0f67e33d5..8e00756ee522 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1768,6 +1768,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dep = dwc->eps[epnum]; + if (!(dep->flags & DWC3_EP_ENABLED)) + return; + dev_vdbg(dwc->dev, "%s: %s\n", dep->name, dwc3_ep_event_string(event->endpoint_event)); -- GitLab From bacef661acdb634170a8faddbc1cf28e8f8b9eee Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 25 May 2012 16:20:31 +0100 Subject: [PATCH 0323/5711] x86-64/efi: Use EFI to deal with platform wall clock Other than ix86, x86-64 on EFI so far didn't set the {g,s}et_wallclock accessors to the EFI routines, thus incorrectly using raw RTC accesses instead. Simply removing the #ifdef around the respective code isn't enough, however: While so far early get-time calls were done in physical mode, this doesn't work properly for x86-64, as virtual addresses would still need to be set up for all runtime regions (which wasn't the case on the system I have access to), so instead the patch moves the call to efi_enter_virtual_mode() ahead (which in turn allows to drop all code related to calling efi-get-time in physical mode). Additionally the earlier calling of efi_set_executable() requires the CPA code to cope, i.e. during early boot it must be avoided to call cpa_flush_array(), as the first thing this function does is a BUG_ON(irqs_disabled()). Also make the two EFI functions in question here static - they're not being referenced elsewhere. Signed-off-by: Jan Beulich Tested-by: Matt Fleming Acked-by: Matthew Garrett Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/4FBFBF5F020000780008637F@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 10 ++++++---- arch/x86/platform/efi/efi.c | 30 ++++-------------------------- include/linux/efi.h | 2 -- init/main.c | 8 ++++---- 4 files changed, 14 insertions(+), 36 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e1ebde315210..ee09aca63998 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -919,11 +919,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, /* * On success we use clflush, when the CPU supports it to - * avoid the wbindv. If the CPU does not support it and in the - * error case we fall back to cpa_flush_all (which uses - * wbindv): + * avoid the wbindv. If the CPU does not support it, in the + * error case, and during early boot (for EFI) we fall back + * to cpa_flush_all (which uses wbinvd): */ - if (!ret && cpu_has_clflush) { + if (early_boot_irqs_disabled) + __cpa_flush_all((void *)(long)cache); + else if (!ret && cpu_has_clflush) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e7..2dc29f51e75a 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -234,22 +234,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( return status; } -static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) -{ - unsigned long flags; - efi_status_t status; - - spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), - virt_to_phys(tc)); - efi_call_phys_epilog(); - spin_unlock_irqrestore(&rtc_lock, flags); - return status; -} - -int efi_set_rtc_mmss(unsigned long nowtime) +static int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -278,7 +263,7 @@ int efi_set_rtc_mmss(unsigned long nowtime) return 0; } -unsigned long efi_get_time(void) +static unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; @@ -621,18 +606,13 @@ static int __init efi_runtime_init(void) } /* * We will only need *early* access to the following - * two EFI runtime services before set_virtual_address_map + * EFI runtime service before set_virtual_address_map * is invoked. */ - efi_phys.get_time = (efi_get_time_t *)runtime->get_time; efi_phys.set_virtual_address_map = (efi_set_virtual_address_map_t *) runtime->set_virtual_address_map; - /* - * Make efi_get_time can be called before entering - * virtual mode. - */ - efi.get_time = phys_efi_get_time; + early_iounmap(runtime, sizeof(efi_runtime_services_t)); return 0; @@ -720,12 +700,10 @@ void __init efi_init(void) efi_enabled = 0; return; } -#ifdef CONFIG_X86_32 if (efi_native) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } -#endif #if EFI_DEBUG print_efi_memmap(); diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd8708a..103adc6d7e3a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -503,8 +503,6 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); -extern unsigned long efi_get_time(void); -extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; diff --git a/init/main.c b/init/main.c index 1ca6b32c4828..eef30128321a 100644 --- a/init/main.c +++ b/init/main.c @@ -460,6 +460,10 @@ static void __init mm_init(void) percpu_init_late(); pgtable_cache_init(); vmalloc_init(); +#ifdef CONFIG_X86 + if (efi_enabled) + efi_enter_virtual_mode(); +#endif } asmlinkage void __init start_kernel(void) @@ -601,10 +605,6 @@ asmlinkage void __init start_kernel(void) calibrate_delay(); pidmap_init(); anon_vma_init(); -#ifdef CONFIG_X86 - if (efi_enabled) - efi_enter_virtual_mode(); -#endif thread_info_cache_init(); cred_init(); fork_init(totalram_pages); -- GitLab From ce63f3ba256a48023b425a4a6792f8da03d00948 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 6 Jun 2012 13:49:44 +0800 Subject: [PATCH 0324/5711] ALSA: hda - add power states information in proc add more power states information: - reset status - clock stop ok - power states error Output like: Power: setting=D0, actual=D0, Error, Clock-stop-OK, Setting-reset Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 3 +++ sound/pci/hda/hda_proc.c | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 4fc3960c8591..71864cddcb9d 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -323,6 +323,9 @@ enum { #define AC_PWRST_D1 0x01 #define AC_PWRST_D2 0x02 #define AC_PWRST_D3 0x03 +#define AC_PWRST_ERROR (1<<8) +#define AC_PWRST_CLK_STOP_OK (1<<9) +#define AC_PWRST_SETTING_RESET (1<<10) /* Processing capabilies */ #define AC_PCAP_BENIGN (1<<0) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6e..fb9ef132f13b 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -455,10 +455,17 @@ static void print_power_state(struct snd_info_buffer *buffer, snd_iprintf(buffer, " Power states: %s\n", bits_names(sup, names, ARRAY_SIZE(names))); - snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", + snd_iprintf(buffer, " Power: setting=%s, actual=%s", get_pwr_state(pwr & AC_PWRST_SETTING), get_pwr_state((pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT)); + if (pwr & AC_PWRST_ERROR) + snd_iprintf(buffer, ", Error"); + if (pwr & AC_PWRST_CLK_STOP_OK) + snd_iprintf(buffer, ", Clock-stop-OK"); + if (pwr & AC_PWRST_SETTING_RESET) + snd_iprintf(buffer, ", Setting-reset"); + snd_iprintf(buffer, "\n"); } static void print_unsol_cap(struct snd_info_buffer *buffer, -- GitLab From 167d2d55bfb4628169a57e3adbb1e5b097dca0f5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 6 Jun 2012 12:17:20 +0200 Subject: [PATCH 0325/5711] ALSA: hda - Show D3cold state in proc files Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index fb9ef132f13b..1dd9dbeeef6e 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -426,10 +426,10 @@ static void print_digital_conv(struct snd_info_buffer *buffer, static const char *get_pwr_state(u32 state) { - static const char * const buf[4] = { - "D0", "D1", "D2", "D3" + static const char * const buf[] = { + "D0", "D1", "D2", "D3", "D3cold" }; - if (state < 4) + if (state < ARRAY_SIZE(buf)) return buf[state]; return "UNKNOWN"; } -- GitLab From 0a305e496059a113f93bdd3ad27a5aaa917fe34d Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 6 Jun 2012 11:17:59 +0100 Subject: [PATCH 0326/5711] GFS2: Extend the life of the reservations This patch lengthens the lifespan of the reservations structure for inodes. Before, they were allocated and deallocated for every write operation. With this patch, they are allocated when the first write occurs, and deallocated when the last process closes the file. It's more efficient to do it this way because it saves GFS2 a lot of unnecessary allocates and frees. It also gives us more flexibility for the future: (1) we can now fold the qadata structure back into the structure and save those alloc/frees, (2) we can use this for multi-block reservations. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/aops.c | 2 +- fs/gfs2/file.c | 23 ++++++++++++++--- fs/gfs2/inode.c | 23 ++++++++++++++++- fs/gfs2/quota.c | 13 ++++++++-- fs/gfs2/rgrp.c | 68 +++++++++++++++++++++++++++---------------------- fs/gfs2/rgrp.h | 10 ++++++++ fs/gfs2/super.c | 2 ++ fs/gfs2/trans.h | 2 +- 8 files changed, 104 insertions(+), 39 deletions(-) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index e80a464850c8..aba77b5720bc 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -878,7 +878,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, brelse(dibh); failed: gfs2_trans_end(sdp); - if (ip->i_res) + if (gfs2_mb_reserved(ip)) gfs2_inplace_release(ip); if (qa) { gfs2_quota_unlock(ip); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 31b199f6efc1..37906174d417 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -376,6 +376,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) */ vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + ret = gfs2_rs_alloc(ip); + if (ret) + return ret; + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret) @@ -569,10 +573,15 @@ static int gfs2_release(struct inode *inode, struct file *file) { struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; struct gfs2_file *fp; + struct gfs2_inode *ip = GFS2_I(inode); fp = file->private_data; file->private_data = NULL; + if ((file->f_mode & FMODE_WRITE) && ip->i_res && + (atomic_read(&inode->i_writecount) == 1)) + gfs2_rs_delete(ip); + if (gfs2_assert_warn(sdp, fp)) return -EIO; @@ -653,12 +662,16 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; + struct dentry *dentry = file->f_dentry; + struct gfs2_inode *ip = GFS2_I(dentry->d_inode); + int ret; + + ret = gfs2_rs_alloc(ip); + if (ret) + return ret; if (file->f_flags & O_APPEND) { - struct dentry *dentry = file->f_dentry; - struct gfs2_inode *ip = GFS2_I(dentry->d_inode); struct gfs2_holder gh; - int ret; ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); if (ret) @@ -774,6 +787,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, if (bytes == 0) bytes = sdp->sd_sb.sb_bsize; + error = gfs2_rs_alloc(ip); + if (error) + return error; + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); error = gfs2_glock_nq(&ip->i_gh); if (unlikely(error)) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index a9ba2444e077..2a1b4b5a648c 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -667,6 +667,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (!name->len || name->len > GFS2_FNAMESIZE) return -ENAMETOOLONG; + error = gfs2_rs_alloc(dip); + if (error) + return error; + error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); if (error) goto fail; @@ -704,6 +708,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (error) goto fail_gunlock2; + /* the new inode needs a reservation so it can allocate xattrs. */ + error = gfs2_rs_alloc(GFS2_I(inode)); + if (error) + goto fail_gunlock2; + error = gfs2_acl_create(dip, inode); if (error) goto fail_gunlock2; @@ -722,7 +731,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, gfs2_trans_end(sdp); /* Check if we reserved space in the rgrp. Function link_dinode may not, depending on whether alloc is required. */ - if (dip->i_res) + if (gfs2_mb_reserved(dip)) gfs2_inplace_release(dip); gfs2_quota_unlock(dip); gfs2_qadata_put(dip); @@ -819,6 +828,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, if (S_ISDIR(inode->i_mode)) return -EPERM; + error = gfs2_rs_alloc(dip); + if (error) + return error; + gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); @@ -1234,6 +1247,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (error) return error; + error = gfs2_rs_alloc(ndip); + if (error) + return error; + if (odip != ndip) { error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0, &r_gh); @@ -1644,6 +1661,10 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) struct gfs2_holder i_gh; int error; + error = gfs2_rs_alloc(ip); + if (error) + return error; + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) return error; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index b97178e7d397..197cc2dade7f 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -764,6 +764,10 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) unsigned int nalloc = 0, blocks; int error; + error = gfs2_rs_alloc(ip); + if (error) + return error; + gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), &data_blocks, &ind_blocks); @@ -1549,10 +1553,14 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, if (error) return error; + error = gfs2_rs_alloc(ip); + if (error) + goto out_put; + mutex_lock(&ip->i_inode.i_mutex); error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); if (error) - goto out_put; + goto out_unlockput; error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) goto out_q; @@ -1609,8 +1617,9 @@ out_i: gfs2_glock_dq_uninit(&i_gh); out_q: gfs2_glock_dq_uninit(&q_gh); -out_put: +out_unlockput: mutex_unlock(&ip->i_inode.i_mutex); +out_put: qd_put(qd); return error; } diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index f74fb9bd1973..e944fefbc9a8 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -417,6 +417,39 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd) } } +/** + * gfs2_rs_alloc - make sure we have a reservation assigned to the inode + * @ip: the inode for this reservation + */ +int gfs2_rs_alloc(struct gfs2_inode *ip) +{ + int error = 0; + + down_write(&ip->i_rw_mutex); + if (!ip->i_res) { + ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS); + if (!ip->i_res) + error = -ENOMEM; + } + up_write(&ip->i_rw_mutex); + return error; +} + +/** + * gfs2_rs_delete - delete a reservation + * @ip: The inode for this reservation + * + */ +void gfs2_rs_delete(struct gfs2_inode *ip) +{ + down_write(&ip->i_rw_mutex); + if (ip->i_res) { + kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); + ip->i_res = NULL; + } + up_write(&ip->i_rw_mutex); +} + void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) { struct rb_node *n; @@ -992,22 +1025,6 @@ struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip) return ip->i_qadata; } -/** - * gfs2_blkrsv_get - get the struct gfs2_blkreserv structure for an inode - * @ip: the incore GFS2 inode structure - * - * Returns: the struct gfs2_qadata - */ - -static int gfs2_blkrsv_get(struct gfs2_inode *ip) -{ - BUG_ON(ip->i_res != NULL); - ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS); - if (!ip->i_res) - return -ENOMEM; - return 0; -} - /** * try_rgrp_fit - See if a given reservation will fit in a given RG * @rgd: the RG data @@ -1162,13 +1179,6 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) return -ENOSPC; } -static void gfs2_blkrsv_put(struct gfs2_inode *ip) -{ - BUG_ON(ip->i_res == NULL); - kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); - ip->i_res = NULL; -} - /** * gfs2_inplace_reserve - Reserve space in the filesystem * @ip: the inode to reserve space for @@ -1181,14 +1191,10 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_blkreserv *rs; - int error; + int error = 0; u64 last_unlinked = NO_BLOCK; int tries = 0; - error = gfs2_blkrsv_get(ip); - if (error) - return error; - rs = ip->i_res; rs->rs_requested = requested; if (gfs2_assert_warn(sdp, requested)) { @@ -1213,7 +1219,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) out: if (error) - gfs2_blkrsv_put(ip); + rs->rs_requested = 0; return error; } @@ -1230,7 +1236,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) if (rs->rs_rgd_gh.gh_gl) gfs2_glock_dq_uninit(&rs->rs_rgd_gh); - gfs2_blkrsv_put(ip); + rs->rs_requested = 0; } /** @@ -1496,7 +1502,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, /* Only happens if there is a bug in gfs2, return something distinctive * to ensure that it is noticed. */ - if (ip->i_res == NULL) + if (ip->i_res->rs_requested == 0) return -ECANCELED; rgd = ip->i_rgd; diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index b4b10f4de25f..d9eda5f9ef2a 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h @@ -43,6 +43,8 @@ extern void gfs2_inplace_release(struct gfs2_inode *ip); extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n, bool dinode, u64 *generation); +extern int gfs2_rs_alloc(struct gfs2_inode *ip); +extern void gfs2_rs_delete(struct gfs2_inode *ip); extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta); extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip); @@ -68,4 +70,12 @@ extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed); extern int gfs2_fitrim(struct file *filp, void __user *argp); +/* This is how to tell if a reservation is "inplace" reserved: */ +static inline int gfs2_mb_reserved(struct gfs2_inode *ip) +{ + if (ip->i_res && ip->i_res->rs_requested) + return 1; + return 0; +} + #endif /* __RGRP_DOT_H__ */ diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 713e621c240b..65578df29446 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1554,6 +1554,7 @@ out_unlock: out: /* Case 3 starts here */ truncate_inode_pages(&inode->i_data, 0); + gfs2_rs_delete(ip); clear_inode(inode); gfs2_dir_hash_inval(ip); ip->i_gl->gl_object = NULL; @@ -1576,6 +1577,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb) ip->i_flags = 0; ip->i_gl = NULL; ip->i_rgd = NULL; + ip->i_res = NULL; } return &ip->i_inode; } diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h index 125d4572e1c0..41f42cdccbb8 100644 --- a/fs/gfs2/trans.h +++ b/fs/gfs2/trans.h @@ -31,7 +31,7 @@ struct gfs2_glock; static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip) { const struct gfs2_blkreserv *rs = ip->i_res; - if (rs->rs_requested < ip->i_rgd->rd_length) + if (rs && rs->rs_requested < ip->i_rgd->rd_length) return rs->rs_requested + 1; return ip->i_rgd->rd_length; } -- GitLab From 5407e24229408d7586ee451a384fc13e4a2332be Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Fri, 18 May 2012 09:28:23 -0400 Subject: [PATCH 0327/5711] GFS2: Fold quota data into the reservations struct This patch moves the ancillary quota data structures into the block reservations structure. This saves GFS2 some time and effort in allocating and deallocating the qadata structure. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/aops.c | 16 ++----------- fs/gfs2/bmap.c | 18 ++++----------- fs/gfs2/dir.c | 9 +------- fs/gfs2/file.c | 22 +++++------------- fs/gfs2/incore.h | 13 ++++------- fs/gfs2/inode.c | 44 ++++-------------------------------- fs/gfs2/main.c | 1 - fs/gfs2/quota.c | 59 ++++++++++++++++++++++++------------------------ fs/gfs2/rgrp.c | 19 ---------------- fs/gfs2/rgrp.h | 8 ------- fs/gfs2/super.c | 9 +------- fs/gfs2/xattr.c | 24 ++------------------ 12 files changed, 56 insertions(+), 186 deletions(-) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index aba77b5720bc..d6526347d386 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -614,7 +614,6 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, unsigned int data_blocks = 0, ind_blocks = 0, rblocks; int alloc_required; int error = 0; - struct gfs2_qadata *qa = NULL; pgoff_t index = pos >> PAGE_CACHE_SHIFT; unsigned from = pos & (PAGE_CACHE_SIZE - 1); struct page *page; @@ -638,15 +637,9 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); if (alloc_required) { - qa = gfs2_qadata_get(ip); - if (!qa) { - error = -ENOMEM; - goto out_unlock; - } - error = gfs2_quota_lock_check(ip); if (error) - goto out_alloc_put; + goto out_unlock; error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks); if (error) @@ -708,8 +701,6 @@ out_trans_fail: gfs2_inplace_release(ip); out_qunlock: gfs2_quota_unlock(ip); -out_alloc_put: - gfs2_qadata_put(ip); } out_unlock: if (&ip->i_inode == sdp->sd_rindex) { @@ -846,7 +837,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct buffer_head *dibh; - struct gfs2_qadata *qa = ip->i_qadata; unsigned int from = pos & (PAGE_CACHE_SIZE - 1); unsigned int to = from + len; int ret; @@ -880,10 +870,8 @@ failed: gfs2_trans_end(sdp); if (gfs2_mb_reserved(ip)) gfs2_inplace_release(ip); - if (qa) { + if (ip->i_res->rs_qa_qd_num) gfs2_quota_unlock(ip); - gfs2_qadata_put(ip); - } if (inode == sdp->sd_rindex) { gfs2_glock_dq(&m_ip->i_gh); gfs2_holder_uninit(&m_ip->i_gh); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index dab54099dd98..6d957a86482b 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1045,12 +1045,13 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift; find_metapath(sdp, lblock, &mp, ip->i_height); - if (!gfs2_qadata_get(ip)) - return -ENOMEM; + error = gfs2_rindex_update(sdp); + if (error) + return error; error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) - goto out; + return error; while (height--) { struct strip_mine sm; @@ -1064,8 +1065,6 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) gfs2_quota_unhold(ip); -out: - gfs2_qadata_put(ip); return error; } @@ -1167,19 +1166,14 @@ static int do_grow(struct inode *inode, u64 size) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh; - struct gfs2_qadata *qa = NULL; int error; int unstuff = 0; if (gfs2_is_stuffed(ip) && (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) { - qa = gfs2_qadata_get(ip); - if (qa == NULL) - return -ENOMEM; - error = gfs2_quota_lock_check(ip); if (error) - goto do_grow_alloc_put; + return error; error = gfs2_inplace_reserve(ip, 1); if (error) @@ -1214,8 +1208,6 @@ do_grow_release: gfs2_inplace_release(ip); do_grow_qunlock: gfs2_quota_unlock(ip); -do_grow_alloc_put: - gfs2_qadata_put(ip); } return error; } diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 8aaeb07a07b5..259b088cfc4c 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1854,14 +1854,9 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, if (!ht) return -ENOMEM; - if (!gfs2_qadata_get(dip)) { - error = -ENOMEM; - goto out; - } - error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) - goto out_put; + goto out; /* Count the number of leaves */ bh = leaf_bh; @@ -1942,8 +1937,6 @@ out_rg_gunlock: out_rlist: gfs2_rlist_free(&rlist); gfs2_quota_unhold(dip); -out_put: - gfs2_qadata_put(dip); out: kfree(ht); return error; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 37906174d417..26e2905070ed 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -366,7 +366,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) u64 pos = page->index << PAGE_CACHE_SHIFT; unsigned int data_blocks, ind_blocks, rblocks; struct gfs2_holder gh; - struct gfs2_qadata *qa; loff_t size; int ret; @@ -397,14 +396,13 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) goto out_unlock; } - ret = -ENOMEM; - qa = gfs2_qadata_get(ip); - if (qa == NULL) + ret = gfs2_rindex_update(sdp); + if (ret) goto out_unlock; ret = gfs2_quota_lock_check(ip); if (ret) - goto out_alloc_put; + goto out_unlock; gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks); ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks); if (ret) @@ -451,8 +449,6 @@ out_trans_fail: gfs2_inplace_release(ip); out_quota_unlock: gfs2_quota_unlock(ip); -out_alloc_put: - gfs2_qadata_put(ip); out_unlock: gfs2_glock_dq(&gh); out: @@ -764,7 +760,6 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, struct gfs2_inode *ip = GFS2_I(inode); unsigned int data_blocks = 0, ind_blocks = 0, rblocks; loff_t bytes, max_bytes; - struct gfs2_qadata *qa; int error; const loff_t pos = offset; const loff_t count = len; @@ -804,15 +799,13 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, offset += bytes; continue; } - qa = gfs2_qadata_get(ip); - if (!qa) { - error = -ENOMEM; + error = gfs2_rindex_update(sdp); + if (error) goto out_unlock; - } error = gfs2_quota_lock_check(ip); if (error) - goto out_alloc_put; + goto out_unlock; retry: gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks); @@ -852,7 +845,6 @@ retry: offset += max_bytes; gfs2_inplace_release(ip); gfs2_quota_unlock(ip); - gfs2_qadata_put(ip); } if (error == 0) @@ -863,8 +855,6 @@ out_trans_fail: gfs2_inplace_release(ip); out_qunlock: gfs2_quota_unlock(ip); -out_alloc_put: - gfs2_qadata_put(ip); out_unlock: gfs2_glock_dq(&ip->i_gh); out_uninit: diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 67fd6beffece..5cda51a3e3bd 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -289,16 +289,14 @@ struct gfs2_glock { #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ -struct gfs2_qadata { /* quota allocation data */ - /* Quota stuff */ - struct gfs2_quota_data *qa_qd[2*MAXQUOTAS]; - struct gfs2_holder qa_qd_ghs[2*MAXQUOTAS]; - unsigned int qa_qd_num; -}; - struct gfs2_blkreserv { u32 rs_requested; /* Filled in by caller of gfs2_inplace_reserve() */ struct gfs2_holder rs_rgd_gh; /* Filled in by gfs2_inplace_reserve() */ + + /* ancillary quota stuff */ + struct gfs2_quota_data *rs_qa_qd[2 * MAXQUOTAS]; + struct gfs2_holder rs_qa_qd_ghs[2 * MAXQUOTAS]; + unsigned int rs_qa_qd_num; }; enum { @@ -319,7 +317,6 @@ struct gfs2_inode { struct gfs2_glock *i_gl; /* Move into i_gh? */ struct gfs2_holder i_iopen_gh; struct gfs2_holder i_gh; /* for prepare/commit_write only */ - struct gfs2_qadata *i_qadata; /* quota allocation data */ struct gfs2_blkreserv *i_res; /* resource group block reservation */ struct gfs2_rgrpd *i_rgd; u64 i_goal; /* goal block for allocations */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 2a1b4b5a648c..2b035e0959b2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -521,12 +521,10 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, int error; munge_mode_uid_gid(dip, &mode, &uid, &gid); - if (!gfs2_qadata_get(dip)) - return -ENOMEM; error = gfs2_quota_lock(dip, uid, gid); if (error) - goto out; + return error; error = gfs2_quota_check(dip, uid, gid); if (error) @@ -542,8 +540,6 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, out_quota: gfs2_quota_unlock(dip); -out: - gfs2_qadata_put(dip); return error; } @@ -551,15 +547,10 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, struct gfs2_inode *ip) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); - struct gfs2_qadata *qa; int alloc_required; struct buffer_head *dibh; int error; - qa = gfs2_qadata_get(dip); - if (!qa) - return -ENOMEM; - error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) goto fail; @@ -611,7 +602,6 @@ fail_quota_locks: gfs2_quota_unlock(dip); fail: - gfs2_qadata_put(dip); return error; } @@ -734,7 +724,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (gfs2_mb_reserved(dip)) gfs2_inplace_release(dip); gfs2_quota_unlock(dip); - gfs2_qadata_put(dip); mark_inode_dirty(inode); gfs2_glock_dq_uninit_m(2, ghs); d_instantiate(dentry, inode); @@ -883,16 +872,9 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, error = 0; if (alloc_required) { - struct gfs2_qadata *qa = gfs2_qadata_get(dip); - - if (!qa) { - error = -ENOMEM; - goto out_gunlock; - } - error = gfs2_quota_lock_check(dip); if (error) - goto out_alloc; + goto out_gunlock; error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres); if (error) @@ -935,9 +917,6 @@ out_ipres: out_gunlock_q: if (alloc_required) gfs2_quota_unlock(dip); -out_alloc: - if (alloc_required) - gfs2_qadata_put(dip); out_gunlock: gfs2_glock_dq(ghs + 1); out_child: @@ -1374,16 +1353,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_gunlock; if (alloc_required) { - struct gfs2_qadata *qa = gfs2_qadata_get(ndip); - - if (!qa) { - error = -ENOMEM; - goto out_gunlock; - } - error = gfs2_quota_lock_check(ndip); if (error) - goto out_alloc; + goto out_gunlock; error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres); if (error) @@ -1444,9 +1416,6 @@ out_ipreserv: out_gunlock_q: if (alloc_required) gfs2_quota_unlock(ndip); -out_alloc: - if (alloc_required) - gfs2_qadata_put(ndip); out_gunlock: while (x--) { gfs2_glock_dq(ghs + x); @@ -1607,12 +1576,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) ogid = ngid = NO_QUOTA_CHANGE; - if (!gfs2_qadata_get(ip)) - return -ENOMEM; - error = gfs2_quota_lock(ip, nuid, ngid); if (error) - goto out_alloc; + return error; if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { error = gfs2_quota_check(ip, nuid, ngid); @@ -1638,8 +1604,6 @@ out_end_trans: gfs2_trans_end(sdp); out_gunlock_q: gfs2_quota_unlock(ip); -out_alloc: - gfs2_qadata_put(ip); return error; } diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 6cdb0f2a1b09..e04d0e09ee7b 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -43,7 +43,6 @@ static void gfs2_init_inode_once(void *foo) inode_init_once(&ip->i_inode); init_rwsem(&ip->i_rw_mutex); INIT_LIST_HEAD(&ip->i_trunc_list); - ip->i_qadata = NULL; ip->i_res = NULL; ip->i_hash_cache = NULL; } diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 197cc2dade7f..7d1ede7b66fc 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -494,11 +494,15 @@ static void qdsb_put(struct gfs2_quota_data *qd) int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_qadata *qa = ip->i_qadata; - struct gfs2_quota_data **qd = qa->qa_qd; + struct gfs2_quota_data **qd; int error; - if (gfs2_assert_warn(sdp, !qa->qa_qd_num) || + if (ip->i_res == NULL) + gfs2_rs_alloc(ip); + + qd = ip->i_res->rs_qa_qd; + + if (gfs2_assert_warn(sdp, !ip->i_res->rs_qa_qd_num) || gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags))) return -EIO; @@ -508,20 +512,20 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd); if (error) goto out; - qa->qa_qd_num++; + ip->i_res->rs_qa_qd_num++; qd++; error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd); if (error) goto out; - qa->qa_qd_num++; + ip->i_res->rs_qa_qd_num++; qd++; if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { error = qdsb_get(sdp, QUOTA_USER, uid, qd); if (error) goto out; - qa->qa_qd_num++; + ip->i_res->rs_qa_qd_num++; qd++; } @@ -529,7 +533,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) error = qdsb_get(sdp, QUOTA_GROUP, gid, qd); if (error) goto out; - qa->qa_qd_num++; + ip->i_res->rs_qa_qd_num++; qd++; } @@ -542,16 +546,17 @@ out: void gfs2_quota_unhold(struct gfs2_inode *ip) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_qadata *qa = ip->i_qadata; unsigned int x; + if (ip->i_res == NULL) + return; gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)); - for (x = 0; x < qa->qa_qd_num; x++) { - qdsb_put(qa->qa_qd[x]); - qa->qa_qd[x] = NULL; + for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { + qdsb_put(ip->i_res->rs_qa_qd[x]); + ip->i_res->rs_qa_qd[x] = NULL; } - qa->qa_qd_num = 0; + ip->i_res->rs_qa_qd_num = 0; } static int sort_qd(const void *a, const void *b) @@ -919,7 +924,6 @@ fail: int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_qadata *qa = ip->i_qadata; struct gfs2_quota_data *qd; unsigned int x; int error = 0; @@ -932,15 +936,15 @@ int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid) sdp->sd_args.ar_quota != GFS2_QUOTA_ON) return 0; - sort(qa->qa_qd, qa->qa_qd_num, sizeof(struct gfs2_quota_data *), - sort_qd, NULL); + sort(ip->i_res->rs_qa_qd, ip->i_res->rs_qa_qd_num, + sizeof(struct gfs2_quota_data *), sort_qd, NULL); - for (x = 0; x < qa->qa_qd_num; x++) { + for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { int force = NO_FORCE; - qd = qa->qa_qd[x]; + qd = ip->i_res->rs_qa_qd[x]; if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags)) force = FORCE; - error = do_glock(qd, force, &qa->qa_qd_ghs[x]); + error = do_glock(qd, force, &ip->i_res->rs_qa_qd_ghs[x]); if (error) break; } @@ -949,7 +953,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid) set_bit(GIF_QD_LOCKED, &ip->i_flags); else { while (x--) - gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]); + gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]); gfs2_quota_unhold(ip); } @@ -994,7 +998,6 @@ static int need_sync(struct gfs2_quota_data *qd) void gfs2_quota_unlock(struct gfs2_inode *ip) { - struct gfs2_qadata *qa = ip->i_qadata; struct gfs2_quota_data *qda[4]; unsigned int count = 0; unsigned int x; @@ -1002,14 +1005,14 @@ void gfs2_quota_unlock(struct gfs2_inode *ip) if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags)) goto out; - for (x = 0; x < qa->qa_qd_num; x++) { + for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { struct gfs2_quota_data *qd; int sync; - qd = qa->qa_qd[x]; + qd = ip->i_res->rs_qa_qd[x]; sync = need_sync(qd); - gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]); + gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]); if (sync && qd_trylock(qd)) qda[count++] = qd; @@ -1042,7 +1045,6 @@ static int print_message(struct gfs2_quota_data *qd, char *type) int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_qadata *qa = ip->i_qadata; struct gfs2_quota_data *qd; s64 value; unsigned int x; @@ -1054,8 +1056,8 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON) return 0; - for (x = 0; x < qa->qa_qd_num; x++) { - qd = qa->qa_qd[x]; + for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { + qd = ip->i_res->rs_qa_qd[x]; if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags)))) @@ -1093,7 +1095,6 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) void gfs2_quota_change(struct gfs2_inode *ip, s64 change, u32 uid, u32 gid) { - struct gfs2_qadata *qa = ip->i_qadata; struct gfs2_quota_data *qd; unsigned int x; @@ -1102,8 +1103,8 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, if (ip->i_diskflags & GFS2_DIF_SYSTEM) return; - for (x = 0; x < qa->qa_qd_num; x++) { - qd = qa->qa_qd[x]; + for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { + qd = ip->i_res->rs_qa_qd[x]; if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) { diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index e944fefbc9a8..9eca6a9cff8f 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1006,25 +1006,6 @@ out: return ret; } -/** - * gfs2_qadata_get - get the struct gfs2_qadata structure for an inode - * @ip: the incore GFS2 inode structure - * - * Returns: the struct gfs2_qadata - */ - -struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip) -{ - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - int error; - BUG_ON(ip->i_qadata != NULL); - ip->i_qadata = kzalloc(sizeof(struct gfs2_qadata), GFP_NOFS); - error = gfs2_rindex_update(sdp); - if (error) - fs_warn(sdp, "rindex update returns %d\n", error); - return ip->i_qadata; -} - /** * try_rgrp_fit - See if a given reservation will fit in a given RG * @rgd: the RG data diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index d9eda5f9ef2a..5d8314dbc899 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h @@ -29,14 +29,6 @@ extern void gfs2_free_clones(struct gfs2_rgrpd *rgd); extern int gfs2_rgrp_go_lock(struct gfs2_holder *gh); extern void gfs2_rgrp_go_unlock(struct gfs2_holder *gh); -extern struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip); -static inline void gfs2_qadata_put(struct gfs2_inode *ip) -{ - BUG_ON(ip->i_qadata == NULL); - kfree(ip->i_qadata); - ip->i_qadata = NULL; -} - extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested); extern void gfs2_inplace_release(struct gfs2_inode *ip); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 65578df29446..81fc76264ed4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1399,7 +1399,6 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip) static int gfs2_dinode_dealloc(struct gfs2_inode *ip) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_qadata *qa; struct gfs2_rgrpd *rgd; struct gfs2_holder gh; int error; @@ -1409,13 +1408,9 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip) return -EIO; } - qa = gfs2_qadata_get(ip); - if (!qa) - return -ENOMEM; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) - goto out; + return error; rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1); if (!rgd) { @@ -1443,8 +1438,6 @@ out_rg_gunlock: gfs2_glock_dq_uninit(&gh); out_qs: gfs2_quota_unhold(ip); -out: - gfs2_qadata_put(ip); return error; } diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 927f4df874ae..523c0de0d805 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -325,13 +325,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, struct gfs2_ea_header *ea, struct gfs2_ea_header *prev, int leave) { - struct gfs2_qadata *qa; int error; - qa = gfs2_qadata_get(ip); - if (!qa) - return -ENOMEM; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) goto out_alloc; @@ -340,7 +335,6 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, gfs2_quota_unhold(ip); out_alloc: - gfs2_qadata_put(ip); return error; } @@ -713,17 +707,12 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, unsigned int blks, ea_skeleton_call_t skeleton_call, void *private) { - struct gfs2_qadata *qa; struct buffer_head *dibh; int error; - qa = gfs2_qadata_get(ip); - if (!qa) - return -ENOMEM; - error = gfs2_quota_lock_check(ip); if (error) - goto out; + return error; error = gfs2_inplace_reserve(ip, blks); if (error) @@ -753,8 +742,6 @@ out_ipres: gfs2_inplace_release(ip); out_gunlock_q: gfs2_quota_unlock(ip); -out: - gfs2_qadata_put(ip); return error; } @@ -1494,16 +1481,11 @@ out_gunlock: int gfs2_ea_dealloc(struct gfs2_inode *ip) { - struct gfs2_qadata *qa; int error; - qa = gfs2_qadata_get(ip); - if (!qa) - return -ENOMEM; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); if (error) - goto out_alloc; + return error; error = ea_foreach(ip, ea_dealloc_unstuffed, NULL); if (error) @@ -1519,8 +1501,6 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip) out_quota: gfs2_quota_unhold(ip); -out_alloc: - gfs2_qadata_put(ip); return error; } -- GitLab From eac1f14fd1e7243aa782ef85f2a217e0c3a709ad Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 5 Jun 2012 15:24:24 -0700 Subject: [PATCH 0328/5711] drm/i915: Inifite timeout for wait ioctl Change the ns_timeout parameter of the wait ioctl to a signed value. Doing this allows the kernel to provide an infinite wait when a timeout of less than 0 is provided. This mimics select/poll. Initially the parameter was meant to match up with the GL spec 1:1, but after being made aware of how much 2^64 - 1 nanoseconds actually is, I do not think anyone will ever notice the loss of 1 bit. The infinite timeout on waiting is similar to the existing i915 userspace interface with the exception that struct_mutex is dropped while doing the wait in this ioctl. Cc: Chris Wilson Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 15 ++++++++++----- include/drm/i915_drm.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index af67803e635f..deaa0d4bb456 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2082,11 +2082,14 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct drm_i915_gem_wait *args = data; struct drm_i915_gem_object *obj; struct intel_ring_buffer *ring = NULL; - struct timespec timeout; + struct timespec timeout_stack, *timeout = NULL; u32 seqno = 0; int ret = 0; - timeout = ns_to_timespec(args->timeout_ns); + if (args->timeout_ns >= 0) { + timeout_stack = ns_to_timespec(args->timeout_ns); + timeout = &timeout_stack; + } ret = i915_mutex_lock_interruptible(dev); if (ret) @@ -2122,9 +2125,11 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); - ret = __wait_seqno(ring, seqno, true, &timeout); - WARN_ON(!timespec_valid(&timeout)); - args->timeout_ns = timespec_to_ns(&timeout); + ret = __wait_seqno(ring, seqno, true, timeout); + if (timeout) { + WARN_ON(!timespec_valid(timeout)); + args->timeout_ns = timespec_to_ns(timeout); + } return ret; out: diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index bab174334da5..aae346e7f635 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -893,7 +893,7 @@ struct drm_i915_gem_wait { __u32 bo_handle; __u32 flags; /** Number of nanoseconds to wait, Returns time remaining. */ - __u64 timeout_ns; + __s64 timeout_ns; }; #endif /* _I915_DRM_H_ */ -- GitLab From 23d0bb834e264f38335f19fe601564b8422431e7 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 28 May 2012 15:26:56 +0100 Subject: [PATCH 0329/5711] GFS2: Add "top dir" flag support This patch adds support for the "top dir" flag. Currently this is unused but a subsequent patch is planned which will add support for the Orlov allocation policy when allocating subdirectories in a parent with this flag set. In order to ensure backward compatible behaviour, mkfs.gfs2 does not currently tag the root directory with this flag, it must always be set manually. Signed-off-by: Steven Whitehouse --- fs/gfs2/file.c | 4 ++++ include/linux/gfs2_ondisk.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 26e2905070ed..6fbf3cbd974d 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -142,6 +142,7 @@ static const u32 fsflags_to_gfs2[32] = { [7] = GFS2_DIF_NOATIME, [12] = GFS2_DIF_EXHASH, [14] = GFS2_DIF_INHERIT_JDATA, + [17] = GFS2_DIF_TOPDIR, }; static const u32 gfs2_to_fsflags[32] = { @@ -150,6 +151,7 @@ static const u32 gfs2_to_fsflags[32] = { [gfs2fl_AppendOnly] = FS_APPEND_FL, [gfs2fl_NoAtime] = FS_NOATIME_FL, [gfs2fl_ExHash] = FS_INDEX_FL, + [gfs2fl_TopLevel] = FS_TOPDIR_FL, [gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL, }; @@ -203,6 +205,7 @@ void gfs2_set_inode_flags(struct inode *inode) GFS2_DIF_NOATIME| \ GFS2_DIF_SYNC| \ GFS2_DIF_SYSTEM| \ + GFS2_DIF_TOPDIR| \ GFS2_DIF_INHERIT_JDATA) /** @@ -298,6 +301,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr) gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags); if (!S_ISDIR(inode->i_mode)) { + gfsflags &= ~GFS2_DIF_TOPDIR; if (gfsflags & GFS2_DIF_INHERIT_JDATA) gfsflags ^= (GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA); return do_gfs2_set_flags(filp, gfsflags, ~0); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index fa98bdb073b9..e8ccf6ff3b4d 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -214,6 +214,7 @@ enum { gfs2fl_NoAtime = 7, gfs2fl_Sync = 8, gfs2fl_System = 9, + gfs2fl_TopLevel = 10, gfs2fl_TruncInProg = 29, gfs2fl_InheritDirectio = 30, gfs2fl_InheritJdata = 31, @@ -230,8 +231,9 @@ enum { #define GFS2_DIF_NOATIME 0x00000080 #define GFS2_DIF_SYNC 0x00000100 #define GFS2_DIF_SYSTEM 0x00000200 /* New in gfs2 */ +#define GFS2_DIF_TOPDIR 0x00000400 /* New in gfs2 */ #define GFS2_DIF_TRUNC_IN_PROG 0x20000000 /* New in gfs2 */ -#define GFS2_DIF_INHERIT_DIRECTIO 0x40000000 +#define GFS2_DIF_INHERIT_DIRECTIO 0x40000000 /* only in gfs1 */ #define GFS2_DIF_INHERIT_JDATA 0x80000000 struct gfs2_dinode { -- GitLab From 1b8ba31a88c5115687095ca2a01bfcaecb489b5a Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 29 May 2012 10:47:51 +0100 Subject: [PATCH 0330/5711] GFS2: Fix error handling when reading an invalid block from the journal When we read an invalid block from the journal, we should not call withdraw, but simply print a message and return an error. It is up to the caller to then handle that error. In the case of mount that means a failed mount, rather than a withdraw (requiring a reboot). In the case of recovering another nodes journal then we return an error via the uevent. Signed-off-by: Steven Whitehouse --- fs/gfs2/lops.c | 9 +++++++-- fs/gfs2/util.h | 18 +++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 852c1be1dd3b..8ff95a2d54ee 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -401,9 +401,14 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) goto out; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); - gfs2_meta_check(sdp, bd->bd_bh); - gfs2_pin(sdp, bd->bd_bh); mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; + if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { + printk(KERN_ERR + "Attempting to add uninitialised block to journal (inplace block=%lld)\n", + (unsigned long long)bd->bd_bh->b_blocknr); + BUG(); + } + gfs2_pin(sdp, bd->bd_bh); mh->__pad0 = cpu_to_be64(0); mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); sdp->sd_log_num_buf++; diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 3586b0dd6aa7..80535739ac7b 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h @@ -79,23 +79,19 @@ int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, const char *type, const char *function, char *file, unsigned int line); -static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp, - struct buffer_head *bh, - const char *function, - char *file, unsigned int line) +static inline int gfs2_meta_check(struct gfs2_sbd *sdp, + struct buffer_head *bh) { struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data; u32 magic = be32_to_cpu(mh->mh_magic); - if (unlikely(magic != GFS2_MAGIC)) - return gfs2_meta_check_ii(sdp, bh, "magic number", function, - file, line); + if (unlikely(magic != GFS2_MAGIC)) { + printk(KERN_ERR "GFS2: Magic number missing at %llu\n", + (unsigned long long)bh->b_blocknr); + return -EIO; + } return 0; } -#define gfs2_meta_check(sdp, bh) \ -gfs2_meta_check_i((sdp), (bh), __func__, __FILE__, __LINE__) - - int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, u16 type, u16 t, const char *function, -- GitLab From 172cf15d18889313bf2c3bfb81fcea08369274ef Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 5 Jun 2012 15:24:25 -0700 Subject: [PATCH 0331/5711] drm/i915: Add wait render timeout get param Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ include/drm/i915_drm.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 262a74d1f852..97a5a5857f5b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1006,6 +1006,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_ALIASING_PPGTT: value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; break; + case I915_PARAM_HAS_WAIT_TIMEOUT: + value = 1; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index aae346e7f635..5c28ee1d1911 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -300,6 +300,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_GEN7_SOL_RESET 16 #define I915_PARAM_HAS_LLC 17 #define I915_PARAM_HAS_ALIASING_PPGTT 18 +#define I915_PARAM_HAS_WAIT_TIMEOUT 19 typedef struct drm_i915_getparam { int param; -- GitLab From 7e39b817ee64a8b67282c76f52aaabddc8a5cd26 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Wed, 6 Jun 2012 19:18:29 +0530 Subject: [PATCH 0332/5711] usb: dwc3: Correct DWC3_DCTL_HIRD_THRES definition The definition of DWC3_DCTL_HIRD_THRES macro is completely wrong. It will only work for when we want to read the register's contents for that bitfield. Change the macro so that it can be used to writing to the register, and when we need to read, we can add extra right shift of 24 bits. Signed-off-by: Pratyush Anand [ balbi@ti.com: add a commit log ] Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index fcb8be2ec1c9..d3e56cfb29c3 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -223,7 +223,7 @@ #define DWC3_DCTL_LSFTRST (1 << 29) #define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) -#define DWC3_DCTL_HIRD_THRES(n) (((n) & DWC3_DCTL_HIRD_THRES_MASK) >> 24) +#define DWC3_DCTL_HIRD_THRES(n) ((n) << 24) #define DWC3_DCTL_APPL1RES (1 << 23) -- GitLab From f9f9a1904467816452fc70740165030e84c2c659 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Jun 2012 09:15:33 -0500 Subject: [PATCH 0333/5711] rbd: Fix ceph_snap_context size calculation ceph_snap_context->snaps is an u64 array Signed-off-by: Zheng Yan Reviewed-by: Alex Elder --- drivers/block/rbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 65665c9c42c6..8b9c1734d807 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -499,7 +499,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, / sizeof (*ondisk)) return -EINVAL; header->snapc = kmalloc(sizeof(struct ceph_snap_context) + - snap_count * sizeof (*ondisk), + snap_count * sizeof(u64), gfp_flags); if (!header->snapc) return -ENOMEM; -- GitLab From 895cfcc810e53d7d36639969c71efb9087221167 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Jun 2012 09:15:33 -0500 Subject: [PATCH 0334/5711] rbd: endian bug in rbd_req_cb() Sparse complains about this because: drivers/block/rbd.c:996:20: warning: cast to restricted __le32 drivers/block/rbd.c:996:20: warning: cast from restricted __le16 These are set in osd_req_encode_op() and they are le16. Signed-off-by: Dan Carpenter Reviewed-by: Alex Elder --- drivers/block/rbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 8b9c1734d807..8f428a8ab003 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -977,7 +977,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg) op = (void *)(replyhead + 1); rc = le32_to_cpu(replyhead->result); bytes = le64_to_cpu(op->extent.length); - read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ); + read_op = (le16_to_cpu(op->op) == CEPH_OSD_OP_READ); dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc); -- GitLab From ab8cb34a4b2f60281a4b18b1f1ad23bc2313d91b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:32 -0500 Subject: [PATCH 0335/5711] libceph: osd_client: don't drop reply reference too early In ceph_osdc_release_request(), a reference to the r_reply message is dropped. But just after that, that same message is revoked if it was in use to receive an incoming reply. Reorder these so we are sure we hold a reference until we're actually done with the message. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index e30efbcc6388..d8b6d319499a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -139,8 +139,6 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); - if (req->r_reply) - ceph_msg_put(req->r_reply); if (req->r_con_filling_msg) { dout("release_request revoking pages %p from con %p\n", req->r_pages, req->r_con_filling_msg); @@ -148,6 +146,8 @@ void ceph_osdc_release_request(struct kref *kref) req->r_reply); ceph_con_put(req->r_con_filling_msg); } + if (req->r_reply) + ceph_msg_put(req->r_reply); if (req->r_own_pages) ceph_release_page_vector(req->r_pages, req->r_num_pages); -- GitLab From 0d47766f14211a73eaf54cab234db134ece79f49 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 31 May 2012 20:22:18 -0700 Subject: [PATCH 0336/5711] libceph: use con get/put ops from osd_client There were a few direct calls to ceph_con_{get,put}() instead of the con ops from osd_client.c. This is a bug since those ops aren't defined to be ceph_con_get/put. This breaks refcounting on the ceph_osd structs that contain the ceph_connections, and could lead to all manner of strangeness. The purpose of the ->get and ->put methods in a ceph connection are to allow the connection to indicate it has a reference to something external to the messaging system, *not* to indicate something external has a reference to the connection. [elder@inktank.com: added that last sentence] Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/osd_client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index d8b6d319499a..5b41a6929cd9 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -144,7 +144,7 @@ void ceph_osdc_release_request(struct kref *kref) req->r_pages, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } if (req->r_reply) ceph_msg_put(req->r_reply); @@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, if (req->r_con_filling_msg == con && req->r_reply == msg) { dout(" dropping con_filling_msg ref %p\n", con); req->r_con_filling_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } if (!req->r_got_reply) { @@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, dout("get_reply revoking msg %p from old con %p\n", req->r_reply, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } @@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, #endif } *skip = 0; - req->r_con_filling_msg = ceph_con_get(con); + req->r_con_filling_msg = con->ops->get(con); dout("get_reply tid %lld %p\n", tid, m); out: -- GitLab From 67130934fb579fdf0f2f6d745960264378b57dc8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 0337/5711] libceph: embed ceph connection structure in mon_client A monitor client has a pointer to a ceph connection structure in it. This is the only one of the three ceph client types that do it this way; the OSD and MDS clients embed the connection into their main structures. There is always exactly one ceph connection for a monitor client, so there is no need to allocate it separate from the monitor client structure. So switch the ceph_mon_client structure to embed its ceph_connection structure. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/mon_client.h | 2 +- net/ceph/mon_client.c | 47 ++++++++++++++------------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h index 545f85917780..2113e3850a4e 100644 --- a/include/linux/ceph/mon_client.h +++ b/include/linux/ceph/mon_client.h @@ -70,7 +70,7 @@ struct ceph_mon_client { bool hunting; int cur_mon; /* last monitor i contacted */ unsigned long sub_sent, sub_renew_after; - struct ceph_connection *con; + struct ceph_connection con; bool have_fsid; /* pending generic requests */ diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 704dc95dc620..ac4d6b100730 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -106,9 +106,9 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) monc->pending_auth = 1; monc->m_auth->front.iov_len = len; monc->m_auth->hdr.front_len = cpu_to_le32(len); - ceph_con_revoke(monc->con, monc->m_auth); + ceph_con_revoke(&monc->con, monc->m_auth); ceph_msg_get(monc->m_auth); /* keep our ref */ - ceph_con_send(monc->con, monc->m_auth); + ceph_con_send(&monc->con, monc->m_auth); } /* @@ -117,8 +117,8 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); - ceph_con_revoke(monc->con, monc->m_auth); - ceph_con_close(monc->con); + ceph_con_revoke(&monc->con, monc->m_auth); + ceph_con_close(&monc->con); monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -142,9 +142,9 @@ static int __open_session(struct ceph_mon_client *monc) monc->want_next_osdmap = !!monc->want_next_osdmap; dout("open_session mon%d opening\n", monc->cur_mon); - monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON; - monc->con->peer_name.num = cpu_to_le64(monc->cur_mon); - ceph_con_open(monc->con, + monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; + monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + ceph_con_open(&monc->con, &monc->monmap->mon_inst[monc->cur_mon].addr); /* initiatiate authentication handshake */ @@ -226,8 +226,8 @@ static void __send_subscribe(struct ceph_mon_client *monc) msg->front.iov_len = p - msg->front.iov_base; msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); - ceph_con_revoke(monc->con, msg); - ceph_con_send(monc->con, ceph_msg_get(msg)); + ceph_con_revoke(&monc->con, msg); + ceph_con_send(&monc->con, ceph_msg_get(msg)); monc->sub_sent = jiffies | 1; /* never 0 */ } @@ -247,7 +247,7 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc, if (monc->hunting) { pr_info("mon%d %s session established\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); monc->hunting = false; } dout("handle_subscribe_ack after %d seconds\n", seconds); @@ -461,7 +461,7 @@ static int do_generic_request(struct ceph_mon_client *monc, req->request->hdr.tid = cpu_to_le64(req->tid); __insert_generic_request(monc, req); monc->num_generic_requests++; - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); mutex_unlock(&monc->mutex); err = wait_for_completion_interruptible(&req->completion); @@ -684,8 +684,8 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); - ceph_con_revoke(monc->con, req->request); - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_con_revoke(&monc->con, req->request); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } @@ -705,7 +705,7 @@ static void delayed_work(struct work_struct *work) __close_session(monc); __open_session(monc); /* continue hunting */ } else { - ceph_con_keepalive(monc->con); + ceph_con_keepalive(&monc->con); __validate_auth(monc); @@ -760,19 +760,16 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) goto out; /* connection */ - monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); - if (!monc->con) - goto out_monmap; - ceph_con_init(&monc->client->msgr, monc->con); - monc->con->private = monc; - monc->con->ops = &mon_con_ops; + ceph_con_init(&monc->client->msgr, &monc->con); + monc->con.private = monc; + monc->con.ops = &mon_con_ops; /* authentication */ monc->auth = ceph_auth_init(cl->options->name, cl->options->key); if (IS_ERR(monc->auth)) { err = PTR_ERR(monc->auth); - goto out_con; + goto out_monmap; } monc->auth->want_keys = CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | @@ -824,8 +821,6 @@ out_subscribe_ack: ceph_msg_put(monc->m_subscribe_ack); out_auth: ceph_auth_destroy(monc->auth); -out_con: - monc->con->ops->put(monc->con); out_monmap: kfree(monc->monmap); out: @@ -841,9 +836,7 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_lock(&monc->mutex); __close_session(monc); - monc->con->private = NULL; - monc->con->ops->put(monc->con); - monc->con = NULL; + monc->con.private = NULL; mutex_unlock(&monc->mutex); @@ -1021,7 +1014,7 @@ static void mon_fault(struct ceph_connection *con) if (!monc->hunting) pr_info("mon%d %s session lost, " "hunting for new mon\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); __close_session(monc); if (!monc->hunting) { -- GitLab From ec87ef4309d33bd9c87a53bb5152a86ae7a65f25 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 31 May 2012 20:27:50 -0700 Subject: [PATCH 0338/5711] libceph: drop connection refcounting for mon_client All references to the embedded ceph_connection come from the msgr workqueue, which is drained prior to mon_client destruction. That means we can ignore con refcounting entirely. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/mon_client.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index ac4d6b100730..062b72478077 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -1029,9 +1029,23 @@ out: mutex_unlock(&monc->mutex); } +/* + * We can ignore refcounting on the connection struct, as all references + * will come from the messenger workqueue, which is drained prior to + * mon_client destruction. + */ +static struct ceph_connection *con_get(struct ceph_connection *con) +{ + return con; +} + +static void con_put(struct ceph_connection *con) +{ +} + static const struct ceph_connection_operations mon_con_ops = { - .get = ceph_con_get, - .put = ceph_con_put, + .get = con_get, + .put = con_put, .dispatch = dispatch, .fault = mon_fault, .alloc_msg = mon_alloc_msg, -- GitLab From 20581c1faf7b15ae1f8b80c0ec757877b0b53151 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 0339/5711] libceph: init monitor connection when opening Hold off initializing a monitor client's connection until just before it gets opened for use. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/mon_client.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 062b72478077..6adbea78b168 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -119,6 +119,7 @@ static void __close_session(struct ceph_mon_client *monc) dout("__close_session closing mon%d\n", monc->cur_mon); ceph_con_revoke(&monc->con, monc->m_auth); ceph_con_close(&monc->con); + monc->con.private = NULL; monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -141,9 +142,13 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - dout("open_session mon%d opening\n", monc->cur_mon); + ceph_con_init(&monc->client->msgr, &monc->con); + monc->con.private = monc; + monc->con.ops = &mon_con_ops; monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + + dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, &monc->monmap->mon_inst[monc->cur_mon].addr); @@ -760,10 +765,6 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) goto out; /* connection */ - ceph_con_init(&monc->client->msgr, &monc->con); - monc->con.private = monc; - monc->con.ops = &mon_con_ops; - /* authentication */ monc->auth = ceph_auth_init(cl->options->name, cl->options->key); @@ -836,8 +837,6 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_lock(&monc->mutex); __close_session(monc); - monc->con.private = NULL; - mutex_unlock(&monc->mutex); ceph_auth_destroy(monc->auth); -- GitLab From 1bfd89f4e6e1adc6a782d94aa5d4c53be1e404d7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 0340/5711] libceph: fully initialize connection in con_init() Move the initialization of a ceph connection's private pointer, operations vector pointer, and peer name information into ceph_con_init(). Rearrange the arguments so the connection pointer is first. Hide the byte-swapping of the peer entity number inside ceph_con_init() Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- fs/ceph/mds_client.c | 7 ++----- include/linux/ceph/messenger.h | 6 ++++-- net/ceph/messenger.c | 9 ++++++++- net/ceph/mon_client.c | 8 +++----- net/ceph/osd_client.c | 7 ++----- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index ad30261cd4c0..ecd7f15741c1 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,11 +394,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con); - s->s_con.private = s; - s->s_con.ops = &mds_con_ops; - s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; - s->s_con.peer_name.num = cpu_to_le64(mds); + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr, + CEPH_ENTITY_TYPE_MDS, mds); spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 5e852f444f68..dd27837f79ac 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -227,8 +227,10 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, u32 required_features, bool nocrc); -extern void ceph_con_init(struct ceph_messenger *msgr, - struct ceph_connection *con); +extern void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr, __u8 entity_type, + __u64 entity_num); extern void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr); extern bool ceph_con_opened(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 36b440a00cc2..3b65f6e6911b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -521,15 +521,22 @@ void ceph_con_put(struct ceph_connection *con) /* * initialize a new connection. */ -void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) +void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num) { dout("con_init %p\n", con); memset(con, 0, sizeof(*con)); + con->private = private; + con->ops = ops; atomic_set(&con->nref, 1); con->msgr = msgr; con_sock_state_init(con); + con->peer_name.type = (__u8) entity_type; + con->peer_name.num = cpu_to_le64(entity_num); + mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 6adbea78b168..ab6b24a5169e 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -142,11 +142,9 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - ceph_con_init(&monc->client->msgr, &monc->con); - monc->con.private = monc; - monc->con.ops = &mon_con_ops; - monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; - monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + ceph_con_init(&monc->con, monc, &mon_con_ops, + &monc->client->msgr, + CEPH_ENTITY_TYPE_MON, monc->cur_mon); dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 5b41a6929cd9..448c9da8beff 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -640,11 +640,8 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(&osdc->client->msgr, &osd->o_con); - osd->o_con.private = osd; - osd->o_con.ops = &osd_con_ops; - osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; - osd->o_con.peer_name.num = cpu_to_le64(onum); + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr, + CEPH_ENTITY_TYPE_OSD, onum); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; -- GitLab From 1c20f2d26795803fc4f5155fe4fca5717a5944b6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:32 -0500 Subject: [PATCH 0341/5711] libceph: tweak ceph_alloc_msg() The function ceph_alloc_msg() is only used to allocate a message that will be assigned to a connection's in_msg pointer. Rename the function so this implied usage is more clear. In addition, make that assignment inside the function (again, since that's precisely what it's intended to be used for). This allows us to return what is now provided via the passed-in address of a "skip" variable. The return type is now Boolean to be explicit that there are only two possible outcomes. Make sure the result of an ->alloc_msg method call always sets the value of *skip properly. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 61 ++++++++++++++++++++++++------------------- net/ceph/mon_client.c | 3 +++ net/ceph/osd_client.c | 1 + 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3b65f6e6911b..98ca23726ea6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1655,9 +1655,8 @@ static int read_partial_message_section(struct ceph_connection *con, return 1; } -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip); +static bool ceph_con_in_msg_alloc(struct ceph_connection *con, + struct ceph_msg_header *hdr); static int read_partial_message_pages(struct ceph_connection *con, @@ -1740,7 +1739,6 @@ static int read_partial_message(struct ceph_connection *con) int ret; unsigned front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; - int skip; u64 seq; u32 crc; @@ -1793,9 +1791,7 @@ static int read_partial_message(struct ceph_connection *con) if (!con->in_msg) { dout("got hdr type %d front %d data %d\n", con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); - skip = 0; - con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); - if (skip) { + if (ceph_con_in_msg_alloc(con, &con->in_hdr)) { /* skip this message */ dout("alloc_msg said skip message\n"); BUG_ON(con->in_msg); @@ -2577,46 +2573,57 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) } /* - * Generic message allocator, for incoming messages. + * Allocate a message for receiving an incoming message on a + * connection, and save the result in con->in_msg. Uses the + * connection's private alloc_msg op if available. + * + * Returns true if the message should be skipped, false otherwise. + * If true is returned (skip message), con->in_msg will be NULL. + * If false is returned, con->in_msg will contain a pointer to the + * newly-allocated message, or NULL in case of memory exhaustion. */ -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip) +static bool ceph_con_in_msg_alloc(struct ceph_connection *con, + struct ceph_msg_header *hdr) { int type = le16_to_cpu(hdr->type); int front_len = le32_to_cpu(hdr->front_len); int middle_len = le32_to_cpu(hdr->middle_len); - struct ceph_msg *msg = NULL; int ret; + BUG_ON(con->in_msg != NULL); + if (con->ops->alloc_msg) { + int skip = 0; + mutex_unlock(&con->mutex); - msg = con->ops->alloc_msg(con, hdr, skip); + con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); - if (!msg || *skip) - return NULL; + if (skip) + con->in_msg = NULL; + + if (!con->in_msg) + return skip != 0; } - if (!msg) { - *skip = 0; - msg = ceph_msg_new(type, front_len, GFP_NOFS, false); - if (!msg) { + if (!con->in_msg) { + con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!con->in_msg) { pr_err("unable to allocate msg type %d len %d\n", type, front_len); - return NULL; + return false; } - msg->page_alignment = le16_to_cpu(hdr->data_off); + con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } - memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); + memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); - if (middle_len && !msg->middle) { - ret = ceph_alloc_middle(con, msg); + if (middle_len && !con->in_msg->middle) { + ret = ceph_alloc_middle(con, con->in_msg); if (ret < 0) { - ceph_msg_put(msg); - return NULL; + ceph_msg_put(con->in_msg); + con->in_msg = NULL; } } - return msg; + return false; } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index ab6b24a5169e..8462ccec6333 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -442,6 +442,7 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con, m = NULL; } else { dout("get_generic_reply %lld got %p\n", tid, req->reply); + *skip = 0; m = ceph_msg_get(req->reply); /* * we don't need to track the connection reading into @@ -982,6 +983,8 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, case CEPH_MSG_MDS_MAP: case CEPH_MSG_OSD_MAP: m = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!m) + return NULL; /* ENOMEM--return skip == 0 */ break; } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 448c9da8beff..24b427b1eca4 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2077,6 +2077,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, int type = le16_to_cpu(hdr->type); int front = le32_to_cpu(hdr->front_len); + *skip = 0; switch (type) { case CEPH_MSG_OSD_MAP: case CEPH_MSG_WATCH_NOTIFY: -- GitLab From 38941f8031bf042dba3ced6394ba3a3b16c244ea Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 0342/5711] libceph: have messages point to their connection When a ceph message is queued for sending it is placed on a list of pending messages (ceph_connection->out_queue). When they are actually sent over the wire, they are moved from that list to another (ceph_connection->out_sent). When acknowledgement for the message is received, it is removed from the sent messages list. During that entire time the message is "in the possession" of a single ceph connection. Keep track of that connection in the message. This will be used in the next patch (and is a helpful bit of information for debugging anyway). Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 3 +++ net/ceph/messenger.c | 27 +++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index dd27837f79ac..6df837f72761 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -77,7 +77,10 @@ struct ceph_msg { unsigned nr_pages; /* size of page array */ unsigned page_alignment; /* io offset in first page */ struct ceph_pagelist *pagelist; /* instead of pages */ + + struct ceph_connection *con; struct list_head list_head; + struct kref kref; struct bio *bio; /* instead of pages/pagelist */ struct bio *bio_iter; /* bio iterator */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 98ca23726ea6..68b49b5b8e86 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -414,6 +414,9 @@ static int con_close_socket(struct ceph_connection *con) static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); + BUG_ON(msg->con == NULL); + msg->con = NULL; + ceph_msg_put(msg); } static void ceph_msg_remove_list(struct list_head *head) @@ -433,6 +436,8 @@ static void reset_connection(struct ceph_connection *con) ceph_msg_remove_list(&con->out_sent); if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; } @@ -625,8 +630,10 @@ static void prepare_write_message(struct ceph_connection *con) &con->out_temp_ack); } + BUG_ON(list_empty(&con->out_queue)); m = list_first_entry(&con->out_queue, struct ceph_msg, list_head); con->out_msg = m; + BUG_ON(m->con != con); /* put message on sent list */ ceph_msg_get(m); @@ -1806,6 +1813,8 @@ static int read_partial_message(struct ceph_connection *con) "error allocating memory for incoming message"; return -ENOMEM; } + + BUG_ON(con->in_msg->con != con); m = con->in_msg; m->front.iov_len = 0; /* haven't read it yet */ if (m->middle) @@ -1901,6 +1910,8 @@ static void process_message(struct ceph_connection *con) { struct ceph_msg *msg; + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; @@ -2260,6 +2271,8 @@ static void ceph_fault(struct ceph_connection *con) con_close_socket(con); if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; } @@ -2378,6 +2391,8 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* queue */ mutex_lock(&con->mutex); + BUG_ON(msg->con != NULL); + msg->con = con; BUG_ON(!list_empty(&msg->list_head)); list_add_tail(&msg->list_head, &con->out_queue); dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, @@ -2403,13 +2418,16 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) { mutex_lock(&con->mutex); if (!list_empty(&msg->list_head)) { - dout("con_revoke %p msg %p - was on queue\n", con, msg); + dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); + BUG_ON(msg->con == NULL); + msg->con = NULL; + ceph_msg_put(msg); msg->hdr.seq = 0; } if (con->out_msg == msg) { - dout("con_revoke %p msg %p - was sending\n", con, msg); + dout("%s %p msg %p - was sending\n", __func__, con, msg); con->out_msg = NULL; if (con->out_kvec_is_msg) { con->out_skip = con->out_kvec_bytes; @@ -2478,6 +2496,8 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, if (m == NULL) goto out; kref_init(&m->kref); + + m->con = NULL; INIT_LIST_HEAD(&m->list_head); m->hdr.tid = 0; @@ -2598,6 +2618,8 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, mutex_unlock(&con->mutex); con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); + if (con->in_msg) + con->in_msg->con = con; if (skip) con->in_msg = NULL; @@ -2611,6 +2633,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, type, front_len); return false; } + con->in_msg->con = con; con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); -- GitLab From 92ce034b5a740046cc643a21ea21eaad589e0043 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:33 -0500 Subject: [PATCH 0343/5711] libceph: have messages take a connection reference There are essentially two types of ceph messages: incoming and outgoing. Outgoing messages are always allocated via ceph_msg_new(), and at the time of their allocation they are not associated with any particular connection. Incoming messages are always allocated via ceph_con_in_msg_alloc(), and they are initially associated with the connection from which incoming data will be placed into the message. When an outgoing message gets sent, it becomes associated with a connection and remains that way until the message is successfully sent. The association of an incoming message goes away at the point it is sent to an upper layer via a con->ops->dispatch method. This patch implements reference counting for all ceph messages, such that every message holds a reference (and a pointer) to a connection if and only if it is associated with that connection (as described above). For background, here is an explanation of the ceph message lifecycle, emphasizing when an association exists between a message and a connection. Outgoing Messages An outgoing message is "owned" by its allocator, from the time it is allocated in ceph_msg_new() up to the point it gets queued for sending in ceph_con_send(). Prior to that point the message's msg->con pointer is null; at the point it is queued for sending its message pointer is assigned to refer to the connection. At that time the message is inserted into a connection's out_queue list. When a message on the out_queue list has been sent to the socket layer to be put on the wire, it is transferred out of that list and into the connection's out_sent list. At that point it is still owned by the connection, and will remain so until an acknowledgement is received from the recipient that indicates the message was successfully transferred. When such an acknowledgement is received (in process_ack()), the message is removed from its list (in ceph_msg_remove()), at which point it is no longer associated with the connection. So basically, any time a message is on one of a connection's lists, it is associated with that connection. Reference counting outgoing messages can thus be done at the points a message is added to the out_queue (in ceph_con_send()) and the point it is removed from either its two lists (in ceph_msg_remove())--at which point its connection pointer becomes null. Incoming Messages When an incoming message on a connection is getting read (in read_partial_message()) and there is no message in con->in_msg, a new one is allocated using ceph_con_in_msg_alloc(). At that point the message is associated with the connection. Once that message has been completely and successfully read, it is passed to upper layer code using the connection's con->ops->dispatch method. At that point the association between the message and the connection no longer exists. Reference counting of connections for incoming messages can be done by taking a reference to the connection when the message gets allocated, and releasing that reference when it gets handed off using the dispatch method. We should never fail to get a connection reference for a message--the since the caller should already hold one. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 68b49b5b8e86..88ac083bb995 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -415,6 +415,7 @@ static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); + ceph_con_put(msg->con); msg->con = NULL; ceph_msg_put(msg); @@ -440,6 +441,7 @@ static void reset_connection(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + ceph_con_put(con->in_msg->con); } con->connect_seq = 0; @@ -1914,6 +1916,7 @@ static void process_message(struct ceph_connection *con) con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; + ceph_con_put(con); /* if first message, set peer_name */ if (con->peer_name.type == 0) @@ -2275,6 +2278,7 @@ static void ceph_fault(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + ceph_con_put(con); } /* Requeue anything that hasn't been acked */ @@ -2391,8 +2395,11 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* queue */ mutex_lock(&con->mutex); + BUG_ON(msg->con != NULL); - msg->con = con; + msg->con = ceph_con_get(con); + BUG_ON(msg->con == NULL); + BUG_ON(!list_empty(&msg->list_head)); list_add_tail(&msg->list_head, &con->out_queue); dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, @@ -2421,10 +2428,11 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); + ceph_con_put(msg->con); msg->con = NULL; + msg->hdr.seq = 0; ceph_msg_put(msg); - msg->hdr.seq = 0; } if (con->out_msg == msg) { dout("%s %p msg %p - was sending\n", __func__, con, msg); @@ -2433,8 +2441,9 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) con->out_skip = con->out_kvec_bytes; con->out_kvec_is_msg = false; } - ceph_msg_put(msg); msg->hdr.seq = 0; + + ceph_msg_put(msg); } mutex_unlock(&con->mutex); } @@ -2618,8 +2627,10 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, mutex_unlock(&con->mutex); con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); - if (con->in_msg) - con->in_msg->con = con; + if (con->in_msg) { + con->in_msg->con = ceph_con_get(con); + BUG_ON(con->in_msg->con == NULL); + } if (skip) con->in_msg = NULL; @@ -2633,7 +2644,8 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, type, front_len); return false; } - con->in_msg->con = con; + con->in_msg->con = ceph_con_get(con); + BUG_ON(con->in_msg->con == NULL); con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); -- GitLab From 6740a845b2543cc46e1902ba21bac743fbadd0dc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 0344/5711] libceph: make ceph_con_revoke() a msg operation ceph_con_revoke() is passed both a message and a ceph connection. Now that any message associated with a connection holds a pointer to that connection, there's no need to provide the connection when revoking a message. This has the added benefit of precluding the possibility of the providing the wrong connection pointer. If the message's connection pointer is null, it is not being tracked by any connection, so revoking it is a no-op. This is supported as a convenience for upper layers, so they can revoke a message that is not actually "in flight." Rename the function ceph_msg_revoke() to reflect that it is really an operation on a message, not a connection. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 3 ++- net/ceph/messenger.c | 7 ++++++- net/ceph/mon_client.c | 8 ++++---- net/ceph/osd_client.c | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 6df837f72761..9008f81c20cd 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -239,7 +239,8 @@ extern void ceph_con_open(struct ceph_connection *con, extern bool ceph_con_opened(struct ceph_connection *con); extern void ceph_con_close(struct ceph_connection *con); extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); -extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg); + +extern void ceph_msg_revoke(struct ceph_msg *msg); extern void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg); extern void ceph_con_keepalive(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 88ac083bb995..d636903ad4b2 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2421,8 +2421,13 @@ EXPORT_SYMBOL(ceph_con_send); /* * Revoke a message that was previously queued for send */ -void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke(struct ceph_msg *msg) { + struct ceph_connection *con = msg->con; + + if (!con) + return; /* Message not in our possession */ + mutex_lock(&con->mutex); if (!list_empty(&msg->list_head)) { dout("%s %p msg %p - was on queue\n", __func__, con, msg); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 8462ccec6333..7a16750d62a6 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -106,7 +106,7 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) monc->pending_auth = 1; monc->m_auth->front.iov_len = len; monc->m_auth->hdr.front_len = cpu_to_le32(len); - ceph_con_revoke(&monc->con, monc->m_auth); + ceph_msg_revoke(monc->m_auth); ceph_msg_get(monc->m_auth); /* keep our ref */ ceph_con_send(&monc->con, monc->m_auth); } @@ -117,7 +117,7 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); - ceph_con_revoke(&monc->con, monc->m_auth); + ceph_msg_revoke(monc->m_auth); ceph_con_close(&monc->con); monc->con.private = NULL; monc->cur_mon = -1; @@ -229,7 +229,7 @@ static void __send_subscribe(struct ceph_mon_client *monc) msg->front.iov_len = p - msg->front.iov_base; msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); - ceph_con_revoke(&monc->con, msg); + ceph_msg_revoke(msg); ceph_con_send(&monc->con, ceph_msg_get(msg)); monc->sub_sent = jiffies | 1; /* never 0 */ @@ -688,7 +688,7 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); - ceph_con_revoke(&monc->con, req->request); + ceph_msg_revoke(req->request); ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 24b427b1eca4..ad78705a4aff 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -852,7 +852,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, if (req->r_osd) { /* make sure the original request isn't in flight. */ - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); list_del_init(&req->r_osd_item); if (list_empty(&req->r_osd->o_requests) && @@ -879,7 +879,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, static void __cancel_request(struct ceph_osd_request *req) { if (req->r_sent && req->r_osd) { - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); req->r_sent = 0; } } -- GitLab From 8921d114f5574c6da2cdd00749d185633ecf88f3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 0345/5711] libceph: make ceph_con_revoke_message() a msg op ceph_con_revoke_message() is passed both a message and a ceph connection. A ceph_msg allocated for incoming messages on a connection always has a pointer to that connection, so there's no need to provide the connection when revoking such a message. Note that the existing logic does not preclude the message supplied being a null/bogus message pointer. The only user of this interface is the OSD client, and the only value an osd client passes is a request's r_reply field. That is always non-null (except briefly in an error path in ceph_osdc_alloc_request(), and that drops the only reference so the request won't ever have a reply to revoke). So we can safely assume the passed-in message is non-null, but add a BUG_ON() to make it very obvious we are imposing this restriction. Rename the function ceph_msg_revoke_incoming() to reflect that it is really an operation on an incoming message. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 4 ++-- net/ceph/messenger.c | 22 ++++++++++++++++------ net/ceph/osd_client.c | 9 ++++----- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 9008f81c20cd..a334dbd1b324 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -241,8 +241,8 @@ extern void ceph_con_close(struct ceph_connection *con); extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); extern void ceph_msg_revoke(struct ceph_msg *msg); -extern void ceph_con_revoke_message(struct ceph_connection *con, - struct ceph_msg *msg); +extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); + extern void ceph_con_keepalive(struct ceph_connection *con); extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); extern void ceph_con_put(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index d636903ad4b2..3857f815c035 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2456,17 +2456,27 @@ void ceph_msg_revoke(struct ceph_msg *msg) /* * Revoke a message that we may be reading data into */ -void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke_incoming(struct ceph_msg *msg) { + struct ceph_connection *con; + + BUG_ON(msg == NULL); + if (!msg->con) { + dout("%s msg %p null con\n", __func__, msg); + + return; /* Message not in our possession */ + } + + con = msg->con; mutex_lock(&con->mutex); - if (con->in_msg && con->in_msg == msg) { + if (con->in_msg == msg) { unsigned front_len = le32_to_cpu(con->in_hdr.front_len); unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len); unsigned data_len = le32_to_cpu(con->in_hdr.data_len); /* skip rest of message */ - dout("con_revoke_pages %p msg %p revoked\n", con, msg); - con->in_base_pos = con->in_base_pos - + dout("%s %p msg %p revoked\n", __func__, con, msg); + con->in_base_pos = con->in_base_pos - sizeof(struct ceph_msg_header) - front_len - middle_len - @@ -2477,8 +2487,8 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) con->in_tag = CEPH_MSGR_TAG_READY; con->in_seq++; } else { - dout("con_revoke_pages %p msg %p pages %p no-op\n", - con, con->in_msg, msg); + dout("%s %p in_msg %p msg %p no-op\n", + __func__, con, con->in_msg, msg); } mutex_unlock(&con->mutex); } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index ad78705a4aff..c178c770acb4 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -140,10 +140,9 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); if (req->r_con_filling_msg) { - dout("release_request revoking pages %p from con %p\n", + dout("%s revoking pages %p from con %p\n", __func__, req->r_pages, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, - req->r_reply); + ceph_msg_revoke_incoming(req->r_reply); req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } if (req->r_reply) @@ -2022,9 +2021,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, } if (req->r_con_filling_msg) { - dout("get_reply revoking msg %p from old con %p\n", + dout("%s revoking msg %p from old con %p\n", __func__, req->r_reply, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); + ceph_msg_revoke_incoming(req->r_reply); req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } -- GitLab From dcae3573b98b2205961bfa5821427f5664422cd8 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Wed, 6 Jun 2012 19:36:17 +0530 Subject: [PATCH 0346/5711] usb: dwc3: resume phy during gadget initialization on recent cores It is needed to enumerate recent cores like 2.10a. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8e00756ee522..38cd13ffae9d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2449,8 +2449,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); - dwc3_gadget_usb2_phy_suspend(dwc, true); - dwc3_gadget_usb3_phy_suspend(dwc, true); + dwc3_gadget_usb2_phy_suspend(dwc, false); + dwc3_gadget_usb3_phy_suspend(dwc, false); } ret = device_register(&dwc->gadget.dev); -- GitLab From 6be96a5c905178637ec06a5d456a76b2b304fca3 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 6 Jun 2012 19:12:30 -0700 Subject: [PATCH 0347/5711] cgroup: remove hierarchy_mutex It was introduced for memcg to iterate cgroup hierarchy without holding cgroup_mutex, but soon after that it was replaced with a lockless way in memcg. No one used hierarchy_mutex since that, so remove it. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- Documentation/cgroups/cgroups.txt | 2 +- include/linux/cgroup.h | 17 ++---------- kernel/cgroup.c | 45 ------------------------------- 3 files changed, 3 insertions(+), 61 deletions(-) diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 8e74980ab385..e86faaea7d66 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -656,7 +656,7 @@ example in cpusets, no task may attach before 'cpus' and 'mems' are set up. void bind(struct cgroup *root) -(cgroup_mutex and ss->hierarchy_mutex held by caller) +(cgroup_mutex held by caller) Called when a cgroup subsystem is rebound to a different hierarchy and root cgroup. Currently this will only involve movement between diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index d3f5fba2c159..c90eaa803440 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -499,22 +499,9 @@ struct cgroup_subsys { #define MAX_CGROUP_TYPE_NAMELEN 32 const char *name; - /* - * Protects sibling/children links of cgroups in this - * hierarchy, plus protects which hierarchy (or none) the - * subsystem is a part of (i.e. root/sibling). To avoid - * potential deadlocks, the following operations should not be - * undertaken while holding any hierarchy_mutex: - * - * - allocating memory - * - initiating hotplug events - */ - struct mutex hierarchy_mutex; - struct lock_class_key subsys_key; - /* * Link to parent, and list entry in parent's children. - * Protected by this->hierarchy_mutex and cgroup_lock() + * Protected by cgroup_lock() */ struct cgroupfs_root *root; struct list_head sibling; @@ -602,7 +589,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); * the lifetime of cgroup_subsys_state is subsys's matter. * * Looking up and scanning function should be called under rcu_read_lock(). - * Taking cgroup_mutex()/hierarchy_mutex() is not necessary for following calls. + * Taking cgroup_mutex is not necessary for following calls. * But the css returned by this routine can be "not populated yet" or "being * destroyed". The caller should check css and cgroup's status. */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index ceeafe874b3f..dec62f5936ef 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1073,28 +1073,24 @@ static int rebind_subsystems(struct cgroupfs_root *root, BUG_ON(cgrp->subsys[i]); BUG_ON(!dummytop->subsys[i]); BUG_ON(dummytop->subsys[i]->cgroup != dummytop); - mutex_lock(&ss->hierarchy_mutex); cgrp->subsys[i] = dummytop->subsys[i]; cgrp->subsys[i]->cgroup = cgrp; list_move(&ss->sibling, &root->subsys_list); ss->root = root; if (ss->bind) ss->bind(cgrp); - mutex_unlock(&ss->hierarchy_mutex); /* refcount was already taken, and we're keeping it */ } else if (bit & removed_bits) { /* We're removing this subsystem */ BUG_ON(ss == NULL); BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]); BUG_ON(cgrp->subsys[i]->cgroup != cgrp); - mutex_lock(&ss->hierarchy_mutex); if (ss->bind) ss->bind(dummytop); dummytop->subsys[i]->cgroup = dummytop; cgrp->subsys[i] = NULL; subsys[i]->root = &rootnode; list_move(&ss->sibling, &rootnode.subsys_list); - mutex_unlock(&ss->hierarchy_mutex); /* subsystem is now free - drop reference on module */ module_put(ss->module); } else if (bit & final_bits) { @@ -3917,37 +3913,6 @@ static void init_cgroup_css(struct cgroup_subsys_state *css, set_bit(CSS_CLEAR_CSS_REFS, &css->flags); } -static void cgroup_lock_hierarchy(struct cgroupfs_root *root) -{ - /* We need to take each hierarchy_mutex in a consistent order */ - int i; - - /* - * No worry about a race with rebind_subsystems that might mess up the - * locking order, since both parties are under cgroup_mutex. - */ - for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { - struct cgroup_subsys *ss = subsys[i]; - if (ss == NULL) - continue; - if (ss->root == root) - mutex_lock(&ss->hierarchy_mutex); - } -} - -static void cgroup_unlock_hierarchy(struct cgroupfs_root *root) -{ - int i; - - for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { - struct cgroup_subsys *ss = subsys[i]; - if (ss == NULL) - continue; - if (ss->root == root) - mutex_unlock(&ss->hierarchy_mutex); - } -} - /* * cgroup_create - create a cgroup * @parent: cgroup that will be parent of the new cgroup @@ -4008,9 +3973,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, ss->post_clone(cgrp); } - cgroup_lock_hierarchy(root); list_add(&cgrp->sibling, &cgrp->parent->children); - cgroup_unlock_hierarchy(root); root->number_of_cgroups++; err = cgroup_create_dir(cgrp, dentry, mode); @@ -4037,9 +4000,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, err_remove: - cgroup_lock_hierarchy(root); list_del(&cgrp->sibling); - cgroup_unlock_hierarchy(root); root->number_of_cgroups--; err_destroy: @@ -4247,10 +4208,8 @@ again: list_del_init(&cgrp->release_list); raw_spin_unlock(&release_list_lock); - cgroup_lock_hierarchy(cgrp->root); /* delete this cgroup from parent->children */ list_del_init(&cgrp->sibling); - cgroup_unlock_hierarchy(cgrp->root); list_del_init(&cgrp->allcg_node); @@ -4324,8 +4283,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) * need to invoke fork callbacks here. */ BUG_ON(!list_empty(&init_task.tasks)); - mutex_init(&ss->hierarchy_mutex); - lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); ss->active = 1; /* this function shouldn't be used with modular subsystems, since they @@ -4452,8 +4409,6 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) } write_unlock(&css_set_lock); - mutex_init(&ss->hierarchy_mutex); - lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); ss->active = 1; /* success! */ -- GitLab From 7721d652c716af3f4c78a84c380822fdbb148d54 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Jun 2012 11:44:27 +0530 Subject: [PATCH 0348/5711] Staging: ipack: Remove version.h header file inclusion version.h header file is no longer required. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h index 0b547eedddc2..eedb00756206 100644 --- a/drivers/staging/ipack/bridges/tpci200.h +++ b/drivers/staging/ipack/bridges/tpci200.h @@ -14,7 +14,6 @@ #ifndef _TPCI200_H_ #define _TPCI200_H_ -#include #include #include #include -- GitLab From 862fe87a8bace8b3eb463d117d455d56c5a24488 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:40 +0200 Subject: [PATCH 0349/5711] Staging: ipack/bridges/tpci200: delete sysfs files To perform the installation of a mezzanine it was needed to write on these files, now it is not needed at all as the device model is properly implemented. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 225 ++---------------------- 1 file changed, 12 insertions(+), 213 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index ad2870750235..75ed600ecc77 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -365,207 +365,9 @@ static irqreturn_t tpci200_interrupt(int irq, void *dev_id) return ret; } -#ifdef CONFIG_SYSFS - -static struct ipack_device *tpci200_slot_register(unsigned int tpci200_number, - unsigned int slot_position) -{ - int found = 0; - struct ipack_device *dev; - struct tpci200_board *tpci200; - - list_for_each_entry(tpci200, &tpci200_list, list) { - if (tpci200->number == tpci200_number) { - found = 1; - break; - } - } - - if (!found) { - pr_err("carrier board not found for the device\n"); - return NULL; - } - - if (slot_position >= TPCI200_NB_SLOT) { - pr_info("Slot [%d:%d] doesn't exist!\n", tpci200_number, - slot_position); - return NULL; - } - - if (mutex_lock_interruptible(&tpci200->mutex)) - return NULL; - - if (tpci200->slots[slot_position].dev != NULL) { - pr_err("Slot [%d:%d] already installed !\n", tpci200_number, - slot_position); - goto err_unlock; - } - - /* - * Give the same IRQ number as the slot number. - * The TPCI200 has assigned his own two IRQ by PCI bus driver - */ - dev = ipack_device_register(tpci200->info->ipack_bus, - slot_position, slot_position); - if (dev == NULL) { - pr_info("Slot [%d:%d] Unable to register an ipack device\n", - tpci200_number, slot_position); - goto err_unlock; - } - - tpci200->slots[slot_position].dev = dev; - mutex_unlock(&tpci200->mutex); - return dev; - -err_unlock: - mutex_unlock(&tpci200->mutex); - return NULL; -} - -static ssize_t tpci200_store_board(struct device *pdev, const char *buf, - size_t count, int slot) -{ - struct tpci200_board *card = dev_get_drvdata(pdev); - struct ipack_device *dev = card->slots[slot].dev; - - if (dev != NULL) - return -EBUSY; - - dev = tpci200_slot_register(card->number, slot); - if (dev == NULL) - return -ENODEV; - - return count; -} - -static ssize_t tpci200_show_board(struct device *pdev, char *buf, int slot) -{ - struct tpci200_board *card = dev_get_drvdata(pdev); - struct ipack_device *dev = card->slots[slot].dev; - - if (dev != NULL) - return snprintf(buf, PAGE_SIZE, "%s\n", dev_name(&dev->dev)); - else - return snprintf(buf, PAGE_SIZE, "none\n"); -} - -static ssize_t tpci200_show_description(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, - "TEWS tpci200 carrier PCI for Industry-pack mezzanines.\n"); -} - -static ssize_t tpci200_show_board_slot0(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 0); -} - -static ssize_t tpci200_store_board_slot0(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 0); -} - -static ssize_t tpci200_show_board_slot1(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 1); -} - -static ssize_t tpci200_store_board_slot1(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 1); -} - -static ssize_t tpci200_show_board_slot2(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 2); -} - -static ssize_t tpci200_store_board_slot2(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 2); -} - - -static ssize_t tpci200_show_board_slot3(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 3); -} - -static ssize_t tpci200_store_board_slot3(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 3); -} - -/* Declaration of the device attributes for the TPCI200 */ -static DEVICE_ATTR(description, S_IRUGO, - tpci200_show_description, NULL); -static DEVICE_ATTR(board_slot0, S_IRUGO | S_IWUSR, - tpci200_show_board_slot0, tpci200_store_board_slot0); -static DEVICE_ATTR(board_slot1, S_IRUGO | S_IWUSR, - tpci200_show_board_slot1, tpci200_store_board_slot1); -static DEVICE_ATTR(board_slot2, S_IRUGO | S_IWUSR, - tpci200_show_board_slot2, tpci200_store_board_slot2); -static DEVICE_ATTR(board_slot3, S_IRUGO | S_IWUSR, - tpci200_show_board_slot3, tpci200_store_board_slot3); - -static struct attribute *tpci200_attrs[] = { - &dev_attr_description.attr, - &dev_attr_board_slot0.attr, - &dev_attr_board_slot1.attr, - &dev_attr_board_slot2.attr, - &dev_attr_board_slot3.attr, - NULL, -}; - -static struct attribute_group tpci200_attr_group = { - .attrs = tpci200_attrs, -}; - -static int tpci200_create_sysfs_files(struct tpci200_board *card) -{ - return sysfs_create_group(&card->info->pdev->dev.kobj, - &tpci200_attr_group); -} - -static void tpci200_remove_sysfs_files(struct tpci200_board *card) -{ - sysfs_remove_group(&card->info->pdev->dev.kobj, &tpci200_attr_group); -} - -#else - -static int tpci200_create_sysfs_files(struct tpci200_board *card) -{ - return 0; -} - -static void tpci200_remove_sysfs_files(struct tpci200_board *card) -{ -} - -#endif /* CONFIG_SYSFS */ - static int tpci200_register(struct tpci200_board *tpci200) { - int i; + int i; int res; unsigned long ioidint_base; unsigned long mem_base; @@ -574,12 +376,6 @@ static int tpci200_register(struct tpci200_board *tpci200) if (pci_enable_device(tpci200->info->pdev) < 0) return -ENODEV; - if (tpci200_create_sysfs_files(tpci200) < 0) { - pr_err("failed creating sysfs files\n"); - res = -EFAULT; - goto out_disable_pci; - } - /* Request IP interface register (Bar 2) */ res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR, "Carrier IP interface registers"); @@ -587,7 +383,7 @@ static int tpci200_register(struct tpci200_board *tpci200) pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_remove_sysfs; + goto out_disable_pci; } /* Request IO ID INT space (Bar 3) */ @@ -668,8 +464,7 @@ static int tpci200_register(struct tpci200_board *tpci200) pr_err("(bn 0x%X, sn 0x%X) unable to register IRQ !", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - tpci200_unregister(tpci200); - goto out_err; + goto out_release_ioid_int_space; } return 0; @@ -678,11 +473,8 @@ out_release_ioid_int_space: pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); out_release_ip_space: pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); -out_remove_sysfs: - tpci200_remove_sysfs_files(tpci200); out_disable_pci: pci_disable_device(tpci200->info->pdev); -out_err: return res; } @@ -1038,7 +830,7 @@ out_err: static int tpci200_pciprobe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret; + int ret, i; struct tpci200_board *tpci200; tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL); @@ -1081,13 +873,20 @@ static int tpci200_pciprobe(struct pci_dev *pdev, dev_set_drvdata(&pdev->dev, tpci200); /* add the registered device in an internal linked list */ list_add_tail(&tpci200->list, &tpci200_list); + + /* + * Give the same IRQ number as the slot number. + * The TPCI200 has assigned his own two IRQ by PCI bus driver + */ + for (i = 0; i < TPCI200_NB_SLOT; i++) + tpci200->slots[i].dev = + ipack_device_register(tpci200->info->ipack_bus, i, i); return ret; } static void __tpci200_pci_remove(struct tpci200_board *tpci200) { tpci200_uninstall(tpci200); - tpci200_remove_sysfs_files(tpci200); list_del(&tpci200->list); ipack_bus_unregister(tpci200->info->ipack_bus); kfree(tpci200->info); -- GitLab From be98cc1daa0419f31472c21e45aec30d24fa5931 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:41 +0200 Subject: [PATCH 0350/5711] Staging: ipack: return proper value in match() function It should return the same value given by the match function of the ipack_driver that has been called. Returning 0 here, means that the match has failed and it could be succeed. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/ipack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c index 2b4fa51bf167..e6dc21a47a0a 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/staging/ipack/ipack.c @@ -48,7 +48,7 @@ static int ipack_bus_match(struct device *device, struct device_driver *driver) if (ret) dev->driver = drv; - return 0; + return ret; } static int ipack_bus_probe(struct device *device) -- GitLab From 38f1c53df288b56ad4b8421b13fbdb7232e92270 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:42 +0200 Subject: [PATCH 0351/5711] Staging: ipack/bridges/tpci200: tpci200_slot_unmap_space() should return 0 if succeed. tpci200_slot_unmap_space() should return 0 if the operation was properly done. If not, the caller will think that something wrong happened. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 75ed600ecc77..85560c729703 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -551,20 +551,15 @@ out: static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) { - int res; struct ipack_addr_space *virt_addr_space; struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; switch (space) { case IPACK_IO_SPACE: @@ -594,9 +589,8 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) default: pr_err("Slot [%d:%d] space number %d doesn't exist !\n", dev->bus_nr, dev->slot, space); - res = -EINVAL; - goto out_unlock; - break; + mutex_unlock(&tpci200->mutex); + return -EINVAL; } iounmap(virt_addr_space->address); @@ -605,8 +599,7 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) virt_addr_space->size = 0; out_unlock: mutex_unlock(&tpci200->mutex); -out: - return res; + return 0; } static int tpci200_slot_unregister(struct ipack_device *dev) -- GitLab From 6ad0c486a4e702fa059ea24c2585c416f01f4664 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:43 +0200 Subject: [PATCH 0352/5711] Staging: ipack/bridges/tpci200: tpci200_slot_map_space() should return 0 if succeed. tpci200_slot_map_space() should return 0 if the operation was properly done. If not, the caller will think that something wrong happened. This patch establish the returned value to 0. It is overwritten in case of error. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 85560c729703..0c2a50a1ec00 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -628,7 +628,7 @@ static int tpci200_slot_unregister(struct ipack_device *dev) static int tpci200_slot_map_space(struct ipack_device *dev, unsigned int memory_size, int space) { - int res; + int res = 0; unsigned int size_to_map; void __iomem *phys_address; struct ipack_addr_space *virt_addr_space; -- GitLab From 786d986ea25632e3d8e7ad5ac2780861ff2b654f Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:44 +0200 Subject: [PATCH 0353/5711] Staging: ipack/bridges/tpci200: check if the remove function is available To avoid a dereference of a NULL pointer, the availability of the function is checked before its use. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 0c2a50a1ec00..ee26d9a7e370 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -764,6 +764,8 @@ out: static void tpci200_slot_remove(struct tpci200_slot *slot) { if ((slot->dev == NULL) || + (slot->dev->driver == NULL) || + (slot->dev->driver->ops == NULL) || (slot->dev->driver->ops->remove == NULL)) return; -- GitLab From e149ef80b08d92a27a9a8333719fe392955af798 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:45 +0200 Subject: [PATCH 0354/5711] Staging: ipack/bridges/tpci200: fix indention. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index ee26d9a7e370..24070a3ff210 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -582,7 +582,7 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) if (dev->mem_space.address == NULL) { pr_info("Slot [%d:%d] MEM space not mapped !\n", dev->bus_nr, dev->slot); - goto out_unlock; + goto out_unlock; } virt_addr_space = &dev->mem_space; break; -- GitLab From 1fc75280f1e48d8f941dfea881d0f5b53fca27f6 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:46 +0200 Subject: [PATCH 0355/5711] Staging: ipack/bridges/tpci200: remove name field from slot_irq This field is not needed at all, as the IRQ is registered for the carrier not for the mezzanine. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 1 - drivers/staging/ipack/bridges/tpci200.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 24070a3ff210..96bfe5b3ca23 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -750,7 +750,6 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, slot_irq->vector = vector; slot_irq->handler = handler; slot_irq->arg = arg; - slot_irq->name = dev_name(&dev->dev); tpci200->slots[dev->slot].irq = slot_irq; res = __tpci200_request_irq(tpci200, dev); diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h index eedb00756206..97ff0d6636b6 100644 --- a/drivers/staging/ipack/bridges/tpci200.h +++ b/drivers/staging/ipack/bridges/tpci200.h @@ -105,14 +105,12 @@ * @vector Vector number * @handler Handler called when IRQ arrives * @arg Handler argument - * @name IRQ name * */ struct slot_irq { int vector; int (*handler)(void *); void *arg; - const char *name; }; /** -- GitLab From 65260291c13d148a7b7f86f3a99af14c43599fa9 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Wed, 23 May 2012 15:54:47 +0200 Subject: [PATCH 0356/5711] Staging: ipack/bridges/tpci200: removed check of tpci200->slots[dev->slot].dev When ipack_device_register() is called, the variable tpci200->slots[dev->slot].dev has not assigned a value and it gives an error when the mezzanine driver is reading a register from the board for the match() function, as all the I/O functions call check_slot(). Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 96bfe5b3ca23..67516255480b 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -59,13 +59,6 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) return NULL; } - BUG_ON(tpci200->slots == NULL); - if (tpci200->slots[dev->slot].dev == NULL) { - pr_info("Slot [%d:%d] is not registered !\n", dev->bus_nr, - dev->slot); - return NULL; - } - return tpci200; } -- GitLab From 3b86bb2e11d854d258c5e05d709865ca3d3c8951 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 10:03:01 +0200 Subject: [PATCH 0357/5711] Staging: ipack: use idr interface for numbering buses Use idr interface to give the bus number. That way, we remove the limitation of 64 buses. The mutex is removed because the ida interface uses spinlocks inside, so it is not needed an extra lock. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/ipack.c | 40 ++++++----------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c index e6dc21a47a0a..e97be9960098 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/staging/ipack/ipack.c @@ -12,22 +12,14 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include +#include #include "ipack.h" #define to_ipack_dev(device) container_of(device, struct ipack_device, dev) #define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver) -/* used when allocating bus numbers */ -#define IPACK_MAXBUS 64 - -static DEFINE_MUTEX(ipack_mutex); - -struct ipack_busmap { - unsigned long busmap[IPACK_MAXBUS / (8*sizeof(unsigned long))]; -}; -static struct ipack_busmap busmap; +static DEFINE_IDA(ipack_ida); static void ipack_device_release(struct device *dev) { @@ -79,26 +71,6 @@ static struct bus_type ipack_bus_type = { .remove = ipack_bus_remove, }; -static int ipack_assign_bus_number(void) -{ - int busnum; - - mutex_lock(&ipack_mutex); - busnum = find_next_zero_bit(busmap.busmap, IPACK_MAXBUS, 1); - - if (busnum >= IPACK_MAXBUS) { - pr_err("too many buses\n"); - busnum = -1; - goto error_find_busnum; - } - - set_bit(busnum, busmap.busmap); - -error_find_busnum: - mutex_unlock(&ipack_mutex); - return busnum; -} - struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, struct ipack_bus_ops *ops) { @@ -109,7 +81,7 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, if (!bus) return NULL; - bus_nr = ipack_assign_bus_number(); + bus_nr = ida_simple_get(&ipack_ida, 0, 0, GFP_KERNEL); if (bus_nr < 0) { kfree(bus); return NULL; @@ -125,9 +97,7 @@ EXPORT_SYMBOL_GPL(ipack_bus_register); int ipack_bus_unregister(struct ipack_bus_device *bus) { - mutex_lock(&ipack_mutex); - clear_bit(bus->bus_nr, busmap.busmap); - mutex_unlock(&ipack_mutex); + ida_simple_remove(&ipack_ida, bus->bus_nr); kfree(bus); return 0; } @@ -189,12 +159,14 @@ EXPORT_SYMBOL_GPL(ipack_device_unregister); static int __init ipack_init(void) { + ida_init(&ipack_ida); return bus_register(&ipack_bus_type); } static void __exit ipack_exit(void) { bus_unregister(&ipack_bus_type); + ida_destroy(&ipack_ida); } module_init(ipack_init); -- GitLab From b2bc13c5e07501a0a4427b6a9eff8162aef5560a Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 10:03:02 +0200 Subject: [PATCH 0358/5711] Staging: ipack: delete the call to remove() in ipack_driver_register When a bus driver calls ipack_driver_register(), it should manages the returning NULL value to undo all the operations it did before this call, and print the corresponding trace. It is not a task for the ipack driver to call the remove() function here. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/ipack.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c index e97be9960098..a1448e68fd7a 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/staging/ipack/ipack.c @@ -141,8 +141,6 @@ struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, ret = device_register(&dev->dev); if (ret < 0) { - pr_err("error registering the device.\n"); - dev->driver->ops->remove(dev); kfree(dev); return NULL; } -- GitLab From 597d473f163a1672262b845ede8a65afdf1b27c6 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 10:03:03 +0200 Subject: [PATCH 0359/5711] Staging: ipack/devices/ipoctal: avoid kernel oops when uninstalling When uninstalling a device, there is a loop of calls that produces, at the end, two calls to __ipoctal_remove() function with the same ipack_device argument. The first time works fine, but the second will fail in tty_unregister_driver() To avoid this situation, the call to __ipoctal_remove() it is done only from the ipack bus driver and not from the ipack device driver. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index 29f6fa841d23..a6f424e65e39 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -853,11 +853,6 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) tty_unregister_driver(ipoctal->tty_drv); put_tty_driver(ipoctal->tty_drv); - - /* Tell the carrier board to free all the resources for this device */ - if (ipoctal->dev->bus->ops->remove_device != NULL) - ipoctal->dev->bus->ops->remove_device(ipoctal->dev); - list_del(&ipoctal->list); kfree(ipoctal); } @@ -889,7 +884,7 @@ static void __exit ipoctal_exit(void) struct ipoctal *p, *next; list_for_each_entry_safe(p, next, &ipoctal_list, list) - __ipoctal_remove(p); + p->dev->bus->ops->remove_device(p->dev); ipack_driver_unregister(&driver); } -- GitLab From ca2d2bb6618396ec0a79b182fcd1591ef62b07cb Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 10:03:04 +0200 Subject: [PATCH 0360/5711] Staging: ipack/bridges/tpci200: avoid dereference of a freed tpci200->info tpci200->info is used later when uninstalling the module. As there is another kfree in the proper place, this patch removes the wrong one. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 67516255480b..e04cb8ade9e7 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -290,8 +290,6 @@ static void tpci200_unregister(struct tpci200_board *tpci200) pci_disable_device(tpci200->info->pdev); pci_dev_put(tpci200->info->pdev); - kfree(tpci200->info); - for (i = 0; i < TPCI200_NB_SLOT; i++) { tpci200->slots[i].io_phys.address = NULL; tpci200->slots[i].io_phys.size = 0; -- GitLab From 20cf70082440ffabbec5c275726f68fe53872c94 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 10:03:05 +0200 Subject: [PATCH 0361/5711] Staging: ipack/bridges/tpci200: fix kernel oops when uninstalling a device When uninstalling a device, the call to the ipack_bus_ops remove() frees resources in the ipack device driver but without unregistering the device. It generates a kernel oops when somebody wants to unregister the device. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index e04cb8ade9e7..46127bca1af2 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -751,23 +751,12 @@ out: return res; } -static void tpci200_slot_remove(struct tpci200_slot *slot) -{ - if ((slot->dev == NULL) || - (slot->dev->driver == NULL) || - (slot->dev->driver->ops == NULL) || - (slot->dev->driver->ops->remove == NULL)) - return; - - slot->dev->driver->ops->remove(slot->dev); -} - static void tpci200_uninstall(struct tpci200_board *tpci200) { int i; for (i = 0; i < TPCI200_NB_SLOT; i++) - tpci200_slot_remove(&tpci200->slots[i]); + tpci200_slot_unregister(tpci200->slots[i].dev); tpci200_unregister(tpci200); kfree(tpci200->slots); -- GitLab From a23d32037073bbc818263ac26077a9981218a0d0 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 13:08:12 +0200 Subject: [PATCH 0362/5711] Staging: ipack/bridges/tpci200: change pr_* usage for dev_* functions Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 126 +++++++++++++----------- 1 file changed, 70 insertions(+), 56 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 46127bca1af2..c39499a81f6c 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -11,8 +11,6 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include "tpci200.h" @@ -36,10 +34,8 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) struct tpci200_board *tpci200; int found = 0; - if (dev == NULL) { - pr_info("Slot doesn't exist.\n"); + if (dev == NULL) return NULL; - } list_for_each_entry(tpci200, &tpci200_list, list) { if (tpci200->number == dev->bus_nr) { @@ -49,13 +45,14 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) } if (!found) { - pr_err("Carrier not found\n"); + dev_err(&dev->dev, "Carrier not found\n"); return NULL; } if (dev->slot >= TPCI200_NB_SLOT) { - pr_info("Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n", - dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1); + dev_info(&dev->dev, + "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n", + dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1); return NULL; } @@ -116,14 +113,15 @@ static struct ipack_addr_space *get_slot_address_space(struct ipack_device *dev, addr = &dev->mem_space; break; default: - pr_err("Slot [%d:%d] space number %d doesn't exist !\n", - dev->bus_nr, dev->slot, space); + dev_err(&dev->dev, + "Slot [%d:%d] space number %d doesn't exist !\n", + dev->bus_nr, dev->slot, space); return NULL; break; } if ((addr->size == 0) || (addr->address == NULL)) { - pr_err("Error, slot space not mapped !\n"); + dev_err(&dev->dev, "Error, slot space not mapped !\n"); return NULL; } @@ -145,7 +143,7 @@ static int tpci200_read8(struct ipack_device *dev, int space, return -EINVAL; if (offset >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -169,7 +167,7 @@ static int tpci200_read16(struct ipack_device *dev, int space, return -EINVAL; if ((offset+2) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } *value = __tpci200_read16(addr->address, offset); @@ -192,7 +190,7 @@ static int tpci200_read32(struct ipack_device *dev, int space, return -EINVAL; if ((offset+4) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -216,7 +214,7 @@ static int tpci200_write8(struct ipack_device *dev, int space, return -EINVAL; if (offset >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -240,7 +238,7 @@ static int tpci200_write16(struct ipack_device *dev, int space, return -EINVAL; if ((offset+2) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -264,7 +262,7 @@ static int tpci200_write32(struct ipack_device *dev, int space, return -EINVAL; if ((offset+4) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -338,8 +336,9 @@ static irqreturn_t tpci200_interrupt(int irq, void *dev_id) if (unhandled_ints) { for (i = 0; i < TPCI200_NB_SLOT; i++) { if (unhandled_ints & ((TPCI200_INT0_EN | TPCI200_INT1_EN) << (2*i))) { - pr_info("No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", - tpci200->number, i); + dev_info(&tpci200->slots[i].dev->dev, + "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", + tpci200->number, i); reg_value = readw( tpci200->info->interface_regs + control_reg[i]); @@ -371,9 +370,10 @@ static int tpci200_register(struct tpci200_board *tpci200) res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR, "Carrier IP interface registers"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_disable_pci; } @@ -382,9 +382,10 @@ static int tpci200_register(struct tpci200_board *tpci200) TPCI200_IO_ID_INT_SPACES_BAR, "Carrier IO ID INT space"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_release_ip_space; } @@ -392,9 +393,10 @@ static int tpci200_register(struct tpci200_board *tpci200) res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR, "Carrier MEM space"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_release_ioid_int_space; } @@ -452,9 +454,10 @@ static int tpci200_register(struct tpci200_board *tpci200) tpci200_interrupt, IRQF_SHARED, KBUILD_MODNAME, (void *) tpci200); if (res) { - pr_err("(bn 0x%X, sn 0x%X) unable to register IRQ !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) unable to register IRQ !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_release_ioid_int_space; } @@ -555,31 +558,35 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) switch (space) { case IPACK_IO_SPACE: if (dev->io_space.address == NULL) { - pr_info("Slot [%d:%d] IO space not mapped !\n", - dev->bus_nr, dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] IO space not mapped !\n", + dev->bus_nr, dev->slot); goto out_unlock; } virt_addr_space = &dev->io_space; break; case IPACK_ID_SPACE: if (dev->id_space.address == NULL) { - pr_info("Slot [%d:%d] ID space not mapped !\n", - dev->bus_nr, dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] ID space not mapped !\n", + dev->bus_nr, dev->slot); goto out_unlock; } virt_addr_space = &dev->id_space; break; case IPACK_MEM_SPACE: if (dev->mem_space.address == NULL) { - pr_info("Slot [%d:%d] MEM space not mapped !\n", - dev->bus_nr, dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] MEM space not mapped !\n", + dev->bus_nr, dev->slot); goto out_unlock; } virt_addr_space = &dev->mem_space; break; default: - pr_err("Slot [%d:%d] space number %d doesn't exist !\n", - dev->bus_nr, dev->slot, space); + dev_err(&dev->dev, + "Slot [%d:%d] space number %d doesn't exist !\n", + dev->bus_nr, dev->slot, space); mutex_unlock(&tpci200->mutex); return -EINVAL; } @@ -639,8 +646,9 @@ static int tpci200_slot_map_space(struct ipack_device *dev, switch (space) { case IPACK_IO_SPACE: if (dev->io_space.address != NULL) { - pr_err("Slot [%d:%d] IO space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] IO space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } @@ -651,8 +659,9 @@ static int tpci200_slot_map_space(struct ipack_device *dev, break; case IPACK_ID_SPACE: if (dev->id_space.address != NULL) { - pr_err("Slot [%d:%d] ID space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] ID space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } @@ -663,17 +672,19 @@ static int tpci200_slot_map_space(struct ipack_device *dev, break; case IPACK_MEM_SPACE: if (dev->mem_space.address != NULL) { - pr_err("Slot [%d:%d] MEM space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] MEM space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } virt_addr_space = &dev->mem_space; if (memory_size > tpci200->slots[dev->slot].mem_phys.size) { - pr_err("Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n", - dev->bus_nr, dev->slot, memory_size, - tpci200->slots[dev->slot].mem_phys.size); + dev_err(&dev->dev, + "Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n", + dev->bus_nr, dev->slot, memory_size, + tpci200->slots[dev->slot].mem_phys.size); res = -EINVAL; goto out_unlock; } @@ -682,8 +693,8 @@ static int tpci200_slot_map_space(struct ipack_device *dev, size_to_map = memory_size; break; default: - pr_err("Slot [%d:%d] space %d doesn't exist !\n", - tpci200->number, dev->slot, space); + dev_err(&dev->dev, "Slot [%d:%d] space %d doesn't exist !\n", + tpci200->number, dev->slot, space); res = -EINVAL; goto out_unlock; break; @@ -718,16 +729,18 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, } if (tpci200->slots[dev->slot].irq != NULL) { - pr_err("Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, - dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, + dev->slot); res = -EINVAL; goto out_unlock; } slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL); if (slot_irq == NULL) { - pr_err("Slot [%d:%d] unable to allocate memory for IRQ !\n", - dev->bus_nr, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] unable to allocate memory for IRQ !\n", + dev->bus_nr, dev->slot); res = -ENOMEM; goto out_unlock; } @@ -824,7 +837,7 @@ static int tpci200_pciprobe(struct pci_dev *pdev, /* register the device and initialize it */ ret = tpci200_install(tpci200); if (ret) { - pr_err("Error during tpci200 install !\n"); + dev_err(&pdev->dev, "Error during tpci200 install !\n"); kfree(tpci200->info); kfree(tpci200); return -ENODEV; @@ -835,7 +848,8 @@ static int tpci200_pciprobe(struct pci_dev *pdev, TPCI200_NB_SLOT, &tpci200_bus_ops); if (!tpci200->info->ipack_bus) { - pr_err("error registering the carrier on ipack driver\n"); + dev_err(&pdev->dev, + "error registering the carrier on ipack driver\n"); tpci200_uninstall(tpci200); kfree(tpci200->info); kfree(tpci200); -- GitLab From 42b38207c36890ead05ab1c0002714c48b9b996a Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 25 May 2012 13:08:13 +0200 Subject: [PATCH 0363/5711] Staging: ipack/devices/ipoctal: change pr_* usage for dev_* functions Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index a6f424e65e39..17aa35a9de63 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -11,8 +11,6 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -116,7 +114,8 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) ipoctal = ipoctal_find_board(tty); if (ipoctal == NULL) { - pr_err("Device not found. Major %d\n", tty->driver->major); + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); return -ENODEV; } @@ -136,7 +135,8 @@ static int ipoctal_open(struct tty_struct *tty, struct file *file) ipoctal = ipoctal_find_board(tty); if (ipoctal == NULL) { - pr_err("Device not found. Major %d\n", tty->driver->major); + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); return -ENODEV; } @@ -381,7 +381,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, IPACK_ID_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] ID space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] ID space!\n", + bus_nr, slot); return res; } @@ -396,14 +398,18 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, IPACK_IO_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] IO space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] IO space!\n", + bus_nr, slot); goto out_unregister_id_space; } res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0x8000, IPACK_MEM_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] MEM space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] MEM space!\n", + bus_nr, slot); goto out_unregister_io_space; } @@ -472,7 +478,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, tty_set_operations(tty, &ipoctal_fops); res = tty_register_driver(tty); if (res) { - pr_err("Can't register tty driver.\n"); + dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); put_tty_driver(tty); goto out_unregister_slot_unmap; } -- GitLab From a21e6bfeb40eddf365d3e7841b37f3708fa6b13f Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 5 Jun 2012 11:52:18 +0200 Subject: [PATCH 0364/5711] iio: adf4350: fix compiler warning [-Wuninitialized] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/iio/frequency/adf4350.c:316:32: warning: ‘val’ may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Michael Hennerich Reported-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/iio/frequency/adf4350.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index fd4c8501aba9..2d09f82d9752 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -310,6 +310,8 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, case ADF4350_PWRDOWN: val = !!(st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); break; + default: + ret = -ENODEV; } mutex_unlock(&indio_dev->mlock); -- GitLab From 74dcd439bf8c16b01f9f5a9dffb2b171ed94e2e5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 5 Jun 2012 18:24:12 +0200 Subject: [PATCH 0365/5711] iio: iio_enum_available_read: Prevent possible buffer overflow Use scnprint instead of snprintf, because snprintf returns the number of bytes that would have been written to the buffer if there was enough space, and as a result writing to buf[len-1] might cause a access beyond the buffers limits. Reported-by: Dan Carpenter Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 56a3c0bc996c..cf9ecd0ae7c9 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -300,7 +300,7 @@ ssize_t iio_enum_available_read(struct iio_dev *indio_dev, return 0; for (i = 0; i < e->num_items; ++i) - len += snprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); + len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); /* replace last space with a newline */ buf[len - 1] = '\n'; -- GitLab From 040f3e5833b9426aaeead6da8957a9b87f3ca9e8 Mon Sep 17 00:00:00 2001 From: Leed Aguilar Date: Wed, 6 Jun 2012 16:14:56 -0400 Subject: [PATCH 0366/5711] staging:iio:magnetometer:ak8975: set power-down mode after reading fuse ROM data Fuse ROM data access mode is the only mode which does not transition to power-down mode automatically. As per the AK8975 data sheet, it is recomended to set the power-down mode first before attempting to change into another mode. Signed-off-by: Leed Aguilar Acked-by: Laxman Dewangan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/ak8975.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 7562cafb26bb..001b3bff4765 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -194,6 +194,17 @@ static int ak8975_setup(struct i2c_client *client) return ret; } + /* After reading fuse ROM data set power-down mode */ + ret = ak8975_write_data(client, + AK8975_REG_CNTL, + AK8975_REG_CNTL_MODE_POWER_DOWN, + AK8975_REG_CNTL_MODE_MASK, + AK8975_REG_CNTL_MODE_SHIFT); + if (ret < 0) { + dev_err(&client->dev, "Error in setting power-down mode\n"); + return ret; + } + /* * Precalculate scale factor (in Gauss units) for each axis and * store in the device data. -- GitLab From 82f2acdce16ad7f124b6bb38c10a1894aa534864 Mon Sep 17 00:00:00 2001 From: Leed Aguilar Date: Wed, 6 Jun 2012 16:15:40 -0400 Subject: [PATCH 0367/5711] staging:iio:magnetometer:ak8975: use gpio_request_one api Use gpio_request_one api, it looks cleaner. Signed-off-by: Leed Aguilar Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/Kconfig | 2 +- drivers/staging/iio/magnetometer/ak8975.c | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index b9d932595ba9..df5e0d4ea295 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -6,7 +6,7 @@ menu "Magnetometer sensors" config SENSORS_AK8975 tristate "Asahi Kasei AK8975 3-Axis Magnetometer" depends on I2C - depends on GENERIC_GPIO + depends on GPIOLIB help Say yes here to build support for Asahi Kasei AK8975 3-Axis Magnetometer. diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 001b3bff4765..11bde3fd93b5 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -499,21 +499,13 @@ static int __devinit ak8975_probe(struct i2c_client *client, /* We may not have a GPIO based IRQ to scan, that is fine, we will poll if so */ if (gpio_is_valid(eoc_gpio)) { - err = gpio_request(eoc_gpio, "ak_8975"); + err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975"); if (err < 0) { dev_err(&client->dev, "failed to request GPIO %d, error %d\n", eoc_gpio, err); goto exit; } - - err = gpio_direction_input(eoc_gpio); - if (err < 0) { - dev_err(&client->dev, - "Failed to configure input direction for GPIO %d, error %d\n", - eoc_gpio, err); - goto exit_gpio; - } } /* Register with IIO */ -- GitLab From 4bf8523df925869d4d27478105f23656a2411ce0 Mon Sep 17 00:00:00 2001 From: Leed Aguilar Date: Wed, 6 Jun 2012 16:16:02 -0400 Subject: [PATCH 0368/5711] staging:iio:magnetometer:ak8975: remove 'mode' attribute The raw data reading process (ak8975_read_axis) sets the single measurement mode to take a sample and once the conversion is completed the device enters into power-down mode automatically, therefore there is no need to enable a flag for this to happen. Signed-off-by: Leed Aguilar Acked-by: Jonathan Cameron Acked-by: Laxman Dewangan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/ak8975.c | 73 ----------------------- 1 file changed, 73 deletions(-) diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 11bde3fd93b5..01b4b07c227b 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -92,7 +92,6 @@ struct ak8975_data { struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - bool mode; u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; int eoc_irq; @@ -247,60 +246,6 @@ static int ak8975_setup(struct i2c_client *client) return 0; } -/* - * Shows the device's mode. 0 = off, 1 = on. - */ -static ssize_t show_mode(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ak8975_data *data = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", data->mode); -} - -/* - * Sets the device's mode. 0 = off, 1 = on. The device's mode must be on - * for the magn raw attributes to be available. - */ -static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ak8975_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - bool value; - int ret; - - /* Convert mode string and do some basic sanity checking on it. - only 0 or 1 are valid. */ - ret = strtobool(buf, &value); - if (ret < 0) - return ret; - - mutex_lock(&data->lock); - - /* Write the mode to the device. */ - if (data->mode != value) { - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - (u8)value, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); - - if (ret < 0) { - dev_err(&client->dev, "Error in setting mode\n"); - mutex_unlock(&data->lock); - return ret; - } - data->mode = value; - } - - mutex_unlock(&data->lock); - - return count; -} - static int wait_conversion_complete_gpio(struct ak8975_data *data) { struct i2c_client *client = data->client; @@ -368,12 +313,6 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_lock(&data->lock); - if (data->mode == 0) { - dev_err(&client->dev, "Operating mode is in power down mode\n"); - ret = -EBUSY; - goto exit; - } - /* Set up the device for taking a sample. */ ret = ak8975_write_data(client, AK8975_REG_CNTL, @@ -465,19 +404,7 @@ static const struct iio_chan_spec ak8975_channels[] = { AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2), }; -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0); - -static struct attribute *ak8975_attr[] = { - &iio_dev_attr_mode.dev_attr.attr, - NULL -}; - -static struct attribute_group ak8975_attr_group = { - .attrs = ak8975_attr, -}; - static const struct iio_info ak8975_info = { - .attrs = &ak8975_attr_group, .read_raw = &ak8975_read_raw, .driver_module = THIS_MODULE, }; -- GitLab From f5c55847f7ae31275c3305c997330e5fefa9fa0e Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 6 Jun 2012 21:22:59 -0400 Subject: [PATCH 0369/5711] dma: enable mxs-dma for imx6q enable the mxs-dma for imx6q. Also remove the unused header file. Signed-off-by: Huang Shijie Acked-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- drivers/dma/mxs-dma.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index aadeb5be9dba..c8416d54f917 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -237,7 +237,7 @@ config IMX_DMA config MXS_DMA bool "MXS DMA support" - depends on SOC_IMX23 || SOC_IMX28 + depends on SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q select STMP_DEVICE select DMA_ENGINE help diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index c96ab15319f2..90b980d014aa 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -29,7 +29,6 @@ #include #include -#include #include "dmaengine.h" -- GitLab From 0c7f46ad927cbd29965d4971730de713b478d270 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 6 Jun 2012 22:02:48 +0800 Subject: [PATCH 0370/5711] ALSA: hda - check supported power states Add function to check whether power states supported by specific codec node. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 41ca803a1fff..b89c8ecc819a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3504,6 +3504,22 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, } EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); +/* + * supported power states check + */ +static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, + unsigned int power_state) +{ + int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); + + if (sup < 0) + return false; + if (sup & power_state) + return true; + else + return false; +} + /* * set power state of the codec */ -- GitLab From 0f4ccbb02533276ab750961e150aeee06492ed7c Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Thu, 7 Jun 2012 16:51:33 +0800 Subject: [PATCH 0371/5711] ALSA: hda - reduce msleep time if EPSS power states supported if EPSS supported, transition from D3 state to D0 state in less than 10ms Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b89c8ecc819a..fedbfae978af 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3532,8 +3532,11 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, } /* this delay seems necessary to avoid click noise at power-down */ - if (power_state == AC_PWRST_D3) - msleep(100); + if (power_state == AC_PWRST_D3) { + /* transition time less than 10ms for power down */ + bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); + msleep(epss ? 10 : 100); + } snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); snd_hda_codec_set_power_to_all(codec, fg, power_state, true); -- GitLab From e076eb5c952c0f724980b44a77902a2ff93d098c Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Thu, 7 Jun 2012 16:52:07 +0800 Subject: [PATCH 0372/5711] ALSA: hda - check proper return value snd_hda_param_read() return value -1 means error, others are responses Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 1dd9dbeeef6e..7e46258fc700 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -451,7 +451,7 @@ static void print_power_state(struct snd_info_buffer *buffer, int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); int pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); - if (sup) + if (sup != -1) snd_iprintf(buffer, " Power states: %s\n", bits_names(sup, names, ARRAY_SIZE(names))); -- GitLab From df5d2f5560a9c33129391a136ed9f0ac26abe69b Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 7 Jun 2012 13:30:16 +0100 Subject: [PATCH 0373/5711] GFS2: Increase buffer size for glocks and glstats debugfs files As per Al Viro's suggestion, this increases the buffer size used for these two files. This provides a speed up of slightly less than 8x (i.e. proportional to the buffer size) for cases when we have large numbers of glocks. Cc: Al Viro Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index dab2526071cc..1c4cddf42a66 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1972,6 +1972,9 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) struct seq_file *seq = file->private_data; struct gfs2_glock_iter *gi = seq->private; gi->sdp = inode->i_private; + seq->buf = kmalloc(8*PAGE_SIZE, GFP_KERNEL | __GFP_NOWARN); + if (seq->buf) + seq->size = 8*PAGE_SIZE; } return ret; } @@ -1984,6 +1987,9 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) struct seq_file *seq = file->private_data; struct gfs2_glock_iter *gi = seq->private; gi->sdp = inode->i_private; + seq->buf = kmalloc(8*PAGE_SIZE, GFP_KERNEL | __GFP_NOWARN); + if (seq->buf) + seq->size = 8*PAGE_SIZE; } return ret; } -- GitLab From 43643528cce60ca184fe8197efa8e8da7c89a037 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 0374/5711] rbd: Clear ceph_msg->bio_iter for retransmitted message The bug can cause NULL pointer dereference in write_partial_msg_pages Signed-off-by: Zheng Yan Reviewed-by: Alex Elder --- net/ceph/messenger.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3857f815c035..769a2c9fe1af 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -649,6 +649,10 @@ static void prepare_write_message(struct ceph_connection *con) m->hdr.seq = cpu_to_le64(++con->out_seq); m->needs_out_seq = false; } +#ifdef CONFIG_BLOCK + else + m->bio_iter = NULL; +#endif dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), -- GitLab From ad3b904c07dfa88603689bf9a67bffbb9b99beb5 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 0375/5711] libceph: fix overflow in __decode_pool_names() `len' is read from network and thus needs validation. Otherwise a large `len' would cause out-of-bounds access via the memcpy() call. In addition, len = 0xffffffff would overflow the kmalloc() size, leading to out-of-bounds write. This patch adds a check of `len' via ceph_decode_need(). Also use kstrndup rather than kmalloc/memcpy. [elder@inktank.com: added -ENOMEM return for null kstrndup() result] Signed-off-by: Xi Wang Reviewed-by: Alex Elder --- net/ceph/osdmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 1892c523c43c..df47871b8389 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -488,15 +488,16 @@ static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) ceph_decode_32_safe(p, end, pool, bad); ceph_decode_32_safe(p, end, len, bad); dout(" pool %d len %d\n", pool, len); + ceph_decode_need(p, end, len, bad); pi = __lookup_pg_pool(&map->pg_pools, pool); if (pi) { + char *name = kstrndup(*p, len, GFP_NOFS); + + if (!name) + return -ENOMEM; kfree(pi->name); - pi->name = kmalloc(len + 1, GFP_NOFS); - if (pi->name) { - memcpy(pi->name, *p, len); - pi->name[len] = '\0'; - dout(" name is %s\n", pi->name); - } + pi->name = name; + dout(" name is %s\n", pi->name); } *p += len; } -- GitLab From e91a9b639a691e0982088b5954eaafb5a25c8f1c Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 0376/5711] libceph: fix overflow in osdmap_decode() On 32-bit systems, a large `n' would overflow `n * sizeof(u32)' and bypass the check ceph_decode_need(p, end, n * sizeof(u32), bad). It would also overflow the subsequent kmalloc() size, leading to out-of-bounds write. Signed-off-by: Xi Wang Reviewed-by: Alex Elder --- net/ceph/osdmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index df47871b8389..d70aaca4a45d 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -667,6 +667,9 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); ceph_decode_copy(p, &pgid, sizeof(pgid)); n = ceph_decode_32(p); + err = -EINVAL; + if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; ceph_decode_need(p, end, n * sizeof(u32), bad); err = -ENOMEM; pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); -- GitLab From a5506049500b30dbc5edb4d07a3577477c1f3643 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 0377/5711] libceph: fix overflow in osdmap_apply_incremental() On 32-bit systems, a large `pglen' would overflow `pglen*sizeof(u32)' and bypass the check ceph_decode_need(p, end, pglen*sizeof(u32), bad). It would also overflow the subsequent kmalloc() size, leading to out-of-bounds write. Signed-off-by: Xi Wang Reviewed-by: Alex Elder --- net/ceph/osdmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index d70aaca4a45d..d3de09f519b2 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -893,6 +893,10 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, (void) __remove_pg_mapping(&map->pg_temp, pgid); /* insert */ + if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { + err = -EINVAL; + goto bad; + } pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); if (!pg) { err = -ENOMEM; -- GitLab From a265367ccbe72010757a56e5776fcf9a49370181 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 31 May 2012 14:47:46 +0100 Subject: [PATCH 0378/5711] ASoC: max98095: Staticise non-exported functions and export jack detect Signed-off-by: Mark Brown --- sound/soc/codecs/max98095.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 35179e2c23c9..7cd508e16a5c 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2216,7 +2216,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data) return IRQ_HANDLED; } -int max98095_jack_detect_enable(struct snd_soc_codec *codec) +static int max98095_jack_detect_enable(struct snd_soc_codec *codec) { struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); int ret = 0; @@ -2245,7 +2245,7 @@ int max98095_jack_detect_enable(struct snd_soc_codec *codec) return ret; } -int max98095_jack_detect_disable(struct snd_soc_codec *codec) +static int max98095_jack_detect_disable(struct snd_soc_codec *codec) { int ret = 0; @@ -2286,6 +2286,7 @@ int max98095_jack_detect(struct snd_soc_codec *codec, max98095_report_jack(client->irq, codec); return 0; } +EXPORT_SYMBOL_GPL(max98095_jack_detect); #ifdef CONFIG_PM static int max98095_suspend(struct snd_soc_codec *codec) -- GitLab From 40820105d4caef1489edd56e9dc2b85871b65308 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Jun 2012 15:38:37 +0300 Subject: [PATCH 0379/5711] ASoC: isabelle: using an uninitialized variable We should set "isabelle_regmap" before using it. GCC complains. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/codecs/isabelle.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index bcc77ef0eda2..0d62f3b0f474 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1126,8 +1126,6 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, struct regmap *isabelle_regmap; int ret = 0; - i2c_set_clientdata(i2c, isabelle_regmap); - isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config); if (IS_ERR(isabelle_regmap)) { ret = PTR_ERR(isabelle_regmap); @@ -1135,6 +1133,7 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, ret); return ret; } + i2c_set_clientdata(i2c, isabelle_regmap); ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_isabelle, isabelle_dai, -- GitLab From d392dead724935ad45c42e1a802d0f1de478c0d2 Mon Sep 17 00:00:00 2001 From: M R Swami Reddy Date: Thu, 7 Jun 2012 18:37:54 +0530 Subject: [PATCH 0380/5711] ASoC: MAINTAINERS: Add maintainer for TI Isabelle Audio driver Vishwas and I support the TI Isabelle audio driver. Signed-off-by: Vishwas A Deshpande Signed-off-by: M R Swami Reddy Signed-off-by: Mark Brown --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 55f0fda602ec..d0526640f717 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6723,9 +6723,11 @@ F: include/linux/tifm.h TI LM49xxx FAMILY ASoC CODEC DRIVERS M: M R Swami Reddy +M: Vishwas A Deshpande L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/soc/codecs/lm49453* +F: sound/soc/codecs/isabelle* TI TWL4030 SERIES SOC CODEC DRIVER M: Peter Ujfalusi -- GitLab From 9515c1010c98347ec92d923bd3e23793fa6dc6fe Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:07 -0600 Subject: [PATCH 0381/5711] ASoC: tegra: add .stream_name to CPU DAIs This is certainly required if the I2S and SPDIF controllers are converted to be CODECs, and is probably good practice irrespective. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 ++ sound/soc/tegra/tegra20_spdif.c | 1 + sound/soc/tegra/tegra30_i2s.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 0c7af63d444b..9d5d4704da29 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -261,12 +261,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { .probe = tegra20_i2s_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { + .stream_name = "Capture", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index f9b57418bd08..ffbd99c4106e 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -181,6 +181,7 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = { .name = DRV_NAME, .probe = tegra20_spdif_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 8596032985dc..9c5c0e6819eb 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -320,12 +320,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = { static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { .probe = tegra30_i2s_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { + .stream_name = "Capture", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, -- GitLab From 408dafc4235e393036708126057e4d643f579486 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:48 -0600 Subject: [PATCH 0382/5711] ASoC: tegra: statically define DAI link format Define the DAI format statically in the dai_link, rather than executing code to set it each time the hw params are set. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 22 +++------------------- sound/soc/tegra/trimslice.c | 22 +++------------------- 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 1fd71e5a9eb9..087d3d8d6c06 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -58,7 +58,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); @@ -86,24 +85,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, return err; } - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "codec_dai fmt not set\n"); - return err; - } - - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "cpu_dai fmt not set\n"); - return err; - } - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { @@ -240,6 +221,9 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { .codec_dai_name = "wm8903-hifi", .init = tegra_wm8903_init, .ops = &tegra_wm8903_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, }; static struct snd_soc_card snd_soc_tegra_wm8903 = { diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 5815430e8521..62bb805022dd 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -52,7 +52,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); @@ -68,24 +67,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, return err; } - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "codec_dai fmt not set\n"); - return err; - } - - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "cpu_dai fmt not set\n"); - return err; - } - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { @@ -121,6 +102,9 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { .cpu_dai_name = "tegra20-i2s.0", .codec_dai_name = "tlv320aic23-hifi", .ops = &trimslice_asoc_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, }; static struct snd_soc_card snd_soc_trimslice = { -- GitLab From 40db77a0c4223d0b87c4b61ae38760d47593b7a5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:49 -0600 Subject: [PATCH 0383/5711] ASoC: tegra: remove usage of rtd->codec rtd->codec_dai->codec can be used instead. This is a slight step along the way to not needing the rtd->codec field any more. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 5 +++-- sound/soc/tegra/tegra_wm8753.c | 2 +- sound/soc/tegra/tegra_wm8903.c | 5 +++-- sound/soc/tegra/trimslice.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 417b09b83fdf..d684df294c0c 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -43,7 +43,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); int srate, mclk; @@ -105,7 +105,8 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = { static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 02bd5a8e8544..ea9166d5c4eb 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -57,7 +57,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); int srate, mclk; diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 087d3d8d6c06..08b5fef67b31 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -58,7 +58,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); int srate, mclk; @@ -181,7 +181,8 @@ static const struct snd_kcontrol_new tegra_wm8903_controls[] = { static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 62bb805022dd..e69a4f7000d6 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -52,7 +52,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); int srate, mclk; -- GitLab From c92a40e3a163b6708e0dd82ba4612f79df846912 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:05 -0600 Subject: [PATCH 0384/5711] ASoC: tegra: use DAI's not card's dev for dev_err This is the actual device of the I2S or SPDIF controller reporting the problem. If a future change converts these controllers to be CODECs, then there may be no pcm associated with the substream, so this change avoids a crash. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 +- sound/soc/tegra/tegra20_spdif.c | 2 +- sound/soc/tegra/tegra30_i2s.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 9d5d4704da29..647daf610e4a 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -138,7 +138,7 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); u32 reg; int ret, sample_size, srate, i2sclock, bitcnt; diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index ffbd99c4106e..f774a2d5e585 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -77,7 +77,7 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); int ret, spdifclock; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 9c5c0e6819eb..2327f62e8a8c 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -181,7 +181,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); u32 val; int ret, sample_size, srate, i2sclock, bitcnt; -- GitLab From 0f163546a772d62250f59bad6a9338a0e3a2605c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:06 -0600 Subject: [PATCH 0385/5711] ASoC: tegra: use regmap more directly Stop open-coding the caching of the ctrl registers; instead, use regmap_update_bits() to update parts of the register from different places. The removal of the open-coded cache will allow controls to be created which touch registers, which will be necessary if any of these modules are converted to CODECs. Get rid of tegra*_read/write; just call regmap_read/write directly. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 90 ++++++++++++++++----------------- sound/soc/tegra/tegra20_i2s.h | 1 - sound/soc/tegra/tegra20_spdif.c | 33 +++++------- sound/soc/tegra/tegra20_spdif.h | 1 - sound/soc/tegra/tegra30_i2s.c | 81 +++++++++++++++-------------- sound/soc/tegra/tegra30_i2s.h | 1 - 6 files changed, 95 insertions(+), 112 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 647daf610e4a..c5fc6b1404f6 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -46,18 +46,6 @@ #define DRV_NAME "tegra20-i2s" -static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val) -{ - regmap_write(i2s->regmap, reg, val); -} - -static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg) -{ - u32 val; - regmap_read(i2s->regmap, reg, &val); - return val; -} - static int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); @@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; + mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; + val = TEGRA20_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; @@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | - TEGRA20_I2S_CTRL_LRCK_MASK); + mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | + TEGRA20_I2S_CTRL_LRCK_MASK; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_DSP_B: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; + val |= TEGRA20_I2S_CTRL_LRCK_R_LOW; break; case SND_SOC_DAIFMT_I2S: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_RIGHT_J: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_LEFT_J: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; default: return -EINVAL; } + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); + return 0; } @@ -140,27 +131,32 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); - u32 reg; + unsigned int mask, val; int ret, sample_size, srate, i2sclock, bitcnt; - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; + mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; + val = TEGRA20_I2S_CTRL_BIT_SIZE_16; sample_size = 16; break; case SNDRV_PCM_FORMAT_S24_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; + val = TEGRA20_I2S_CTRL_BIT_SIZE_24; sample_size = 24; break; case SNDRV_PCM_FORMAT_S32_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; + val = TEGRA20_I2S_CTRL_BIT_SIZE_32; sample_size = 32; break; default: return -EINVAL; } + mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK; + val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; + + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); + srate = params_rate(params); /* Final "* 2" required by Tegra hardware */ @@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, bitcnt = (i2sclock / (2 * srate)) - 1; if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) return -EINVAL; - reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; + val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; if (i2sclock % (2 * srate)) - reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; + val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); + regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val); - tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, - TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | - TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); + regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR, + TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | + TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); return 0; } static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) { - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO1_ENABLE, + TEGRA20_I2S_CTRL_FIFO1_ENABLE); } static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) { - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0); } static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) { - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO2_ENABLE, + TEGRA20_I2S_CTRL_FIFO2_ENABLE); } static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) { - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0); } static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, @@ -414,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev) i2s->playback_dma_data.width = 32; i2s->playback_dma_data.req_sel = dma_ch; - i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; - pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = tegra20_i2s_runtime_resume(&pdev->dev); diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index a57efc6a597e..c27069d24d77 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h @@ -158,7 +158,6 @@ struct tegra20_i2s { struct tegra_pcm_dma_params capture_dma_data; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index f774a2d5e585..5c33c618929d 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -37,19 +37,6 @@ #define DRV_NAME "tegra20-spdif" -static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, - u32 val) -{ - regmap_write(spdif->regmap, reg, val); -} - -static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg) -{ - u32 val; - regmap_read(spdif->regmap, reg, &val); - return val; -} - static int tegra20_spdif_runtime_suspend(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); @@ -79,19 +66,22 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; int ret, spdifclock; - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK; - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; + mask = TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK; - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; + val = TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; break; default: return -EINVAL; } + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val); + switch (params_rate(params)) { case 32000: spdifclock = 4096000; @@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif) { - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN; - tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, + TEGRA20_SPDIF_CTRL_TX_EN, + TEGRA20_SPDIF_CTRL_TX_EN); } static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif) { - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN; - tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, + TEGRA20_SPDIF_CTRL_TX_EN, 0); } static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h index ed756527efea..b48d699fd583 100644 --- a/sound/soc/tegra/tegra20_spdif.h +++ b/sound/soc/tegra/tegra20_spdif.h @@ -465,7 +465,6 @@ struct tegra20_spdif { struct tegra_pcm_dma_params capture_dma_data; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 2327f62e8a8c..b68e27a14608 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -44,18 +44,6 @@ #define DRV_NAME "tegra30-i2s" -static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val) -{ - regmap_write(i2s->regmap, reg, val); -} - -static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg) -{ - u32 val; - regmap_read(i2s->regmap, reg, &val); - return val; -} - static int tegra30_i2s_runtime_suspend(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); @@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE; + mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE; + val = TEGRA30_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; @@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | - TEGRA30_I2S_CTRL_LRCK_MASK); + mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | + TEGRA30_I2S_CTRL_LRCK_MASK; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_DSP_B: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; + val |= TEGRA30_I2S_CTRL_LRCK_R_LOW; break; case SND_SOC_DAIFMT_I2S: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_RIGHT_J: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_LEFT_J: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; default: return -EINVAL; } + pm_runtime_get_sync(dai->dev); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); + pm_runtime_put(dai->dev); + return 0; } @@ -183,22 +176,24 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); - u32 val; + unsigned int mask, val, reg; int ret, sample_size, srate, i2sclock, bitcnt; if (params_channels(params) != 2) return -EINVAL; - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK; + mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16; + val = TEGRA30_I2S_CTRL_BIT_SIZE_16; sample_size = 16; break; default: return -EINVAL; } + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); + srate = params_rate(params); /* Final "* 2" required by Tegra hardware */ @@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, if (i2sclock % (2 * srate)) val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; - tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val); + regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | @@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val); + reg = TEGRA30_I2S_CIF_RX_CTRL; } else { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val); + reg = TEGRA30_I2S_CIF_RX_CTRL; } + regmap_write(i2s->regmap, reg, val); + val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); - tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val); + regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val); return 0; } @@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) { tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_TX, + TEGRA30_I2S_CTRL_XFER_EN_TX); } static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) { tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_TX, 0); } static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) { tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_RX, + TEGRA30_I2S_CTRL_XFER_EN_RX); } static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) { tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_RX, 0); } static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h index 91adf29c7a87..34dc47b9581c 100644 --- a/sound/soc/tegra/tegra30_i2s.h +++ b/sound/soc/tegra/tegra30_i2s.h @@ -236,7 +236,6 @@ struct tegra30_i2s { enum tegra30_ahub_txcif playback_fifo_cif; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif -- GitLab From 4fd1e324b7b5f80bd521b58593ada74ef89e80c4 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 6 Jun 2012 10:55:26 +0530 Subject: [PATCH 0386/5711] dma: dmaengine: add slave req id in slave_config The DMA controller like Nvidia's Tegra Dma controller supports the different slave requestor id from different slave. This need to be configure in dma controller to handle the request properly. Adding the slave-id in the slave configuration so that information can be passed from client when configuring for slave. Signed-off-by: Laxman Dewangan Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 56377df39124..ccec62f8e501 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -338,6 +338,9 @@ enum dma_slave_buswidth { * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill * with 'true' if peripheral should be flow controller. Direction will be * selected at Runtime. + * @slave_id: Slave requester id. Only valid for slave channels. The dma + * slave peripheral will have unique id as dma requester which need to be + * pass as slave config. * * This struct is passed in as configuration data to a DMA engine * in order to set up a certain channel for DMA transport at runtime. @@ -365,6 +368,7 @@ struct dma_slave_config { u32 src_maxburst; u32 dst_maxburst; bool device_fc; + unsigned int slave_id; }; static inline const char *dma_chan_name(struct dma_chan *chan) -- GitLab From ec8a1586780cbb437aeb2006957c5bbe113c7046 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 6 Jun 2012 10:55:27 +0530 Subject: [PATCH 0387/5711] dma: tegra: add dmaengine based dma driver Add dmaengine based NVIDIA's Tegra APB DMA driver. This driver support the slave mode of data transfer from peripheral to memory and vice versa. The driver supports for the cyclic and non-cyclic mode of data transfer. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 14 + drivers/dma/Makefile | 1 + drivers/dma/tegra20-apb-dma.c | 1410 +++++++++++++++++++++++++++++++++ 3 files changed, 1425 insertions(+) create mode 100644 drivers/dma/tegra20-apb-dma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index c8416d54f917..b3761153649d 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -148,6 +148,20 @@ config TXX9_DMAC Support the TXx9 SoC internal DMA controller. This can be integrated in chips such as the Toshiba TX4927/38/39. +config TEGRA20_APB_DMA + bool "NVIDIA Tegra20 APB DMA support" + depends on ARCH_TEGRA + select DMA_ENGINE + help + Support for the NVIDIA Tegra20 APB DMA controller driver. The + DMA controller is having multiple DMA channel which can be + configured for different peripherals like audio, UART, SPI, + I2C etc which is in APB bus. + This DMA controller transfers data from memory to peripheral fifo + or vice versa. It does not support memory to memory data transfer. + + + config SH_DMAE tristate "Renesas SuperH DMAC support" depends on (SUPERH && SH_DMA) || (ARM && ARCH_SHMOBILE) diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 86b795baba98..d679ea3f6ab0 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_MXS_DMA) += mxs-dma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o obj-$(CONFIG_SIRF_DMA) += sirf-dma.o obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o +obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o obj-$(CONFIG_PL330_DMA) += pl330.o obj-$(CONFIG_PCH_DMA) += pch_dma.o obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c new file mode 100644 index 000000000000..134ea7cfc795 --- /dev/null +++ b/drivers/dma/tegra20-apb-dma.c @@ -0,0 +1,1410 @@ +/* + * DMA driver for Nvidia's Tegra20 APB DMA controller. + * + * Copyright (c) 2012, NVIDIA CORPORATION. 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dmaengine.h" + +#define TEGRA_APBDMA_GENERAL 0x0 +#define TEGRA_APBDMA_GENERAL_ENABLE BIT(31) + +#define TEGRA_APBDMA_CONTROL 0x010 +#define TEGRA_APBDMA_IRQ_MASK 0x01c +#define TEGRA_APBDMA_IRQ_MASK_SET 0x020 + +/* CSR register */ +#define TEGRA_APBDMA_CHAN_CSR 0x00 +#define TEGRA_APBDMA_CSR_ENB BIT(31) +#define TEGRA_APBDMA_CSR_IE_EOC BIT(30) +#define TEGRA_APBDMA_CSR_HOLD BIT(29) +#define TEGRA_APBDMA_CSR_DIR BIT(28) +#define TEGRA_APBDMA_CSR_ONCE BIT(27) +#define TEGRA_APBDMA_CSR_FLOW BIT(21) +#define TEGRA_APBDMA_CSR_REQ_SEL_SHIFT 16 +#define TEGRA_APBDMA_CSR_WCOUNT_MASK 0xFFFC + +/* STATUS register */ +#define TEGRA_APBDMA_CHAN_STATUS 0x004 +#define TEGRA_APBDMA_STATUS_BUSY BIT(31) +#define TEGRA_APBDMA_STATUS_ISE_EOC BIT(30) +#define TEGRA_APBDMA_STATUS_HALT BIT(29) +#define TEGRA_APBDMA_STATUS_PING_PONG BIT(28) +#define TEGRA_APBDMA_STATUS_COUNT_SHIFT 2 +#define TEGRA_APBDMA_STATUS_COUNT_MASK 0xFFFC + +/* AHB memory address */ +#define TEGRA_APBDMA_CHAN_AHBPTR 0x010 + +/* AHB sequence register */ +#define TEGRA_APBDMA_CHAN_AHBSEQ 0x14 +#define TEGRA_APBDMA_AHBSEQ_INTR_ENB BIT(31) +#define TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_8 (0 << 28) +#define TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_16 (1 << 28) +#define TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32 (2 << 28) +#define TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_64 (3 << 28) +#define TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_128 (4 << 28) +#define TEGRA_APBDMA_AHBSEQ_DATA_SWAP BIT(27) +#define TEGRA_APBDMA_AHBSEQ_BURST_1 (4 << 24) +#define TEGRA_APBDMA_AHBSEQ_BURST_4 (5 << 24) +#define TEGRA_APBDMA_AHBSEQ_BURST_8 (6 << 24) +#define TEGRA_APBDMA_AHBSEQ_DBL_BUF BIT(19) +#define TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT 16 +#define TEGRA_APBDMA_AHBSEQ_WRAP_NONE 0 + +/* APB address */ +#define TEGRA_APBDMA_CHAN_APBPTR 0x018 + +/* APB sequence register */ +#define TEGRA_APBDMA_CHAN_APBSEQ 0x01c +#define TEGRA_APBDMA_APBSEQ_BUS_WIDTH_8 (0 << 28) +#define TEGRA_APBDMA_APBSEQ_BUS_WIDTH_16 (1 << 28) +#define TEGRA_APBDMA_APBSEQ_BUS_WIDTH_32 (2 << 28) +#define TEGRA_APBDMA_APBSEQ_BUS_WIDTH_64 (3 << 28) +#define TEGRA_APBDMA_APBSEQ_BUS_WIDTH_128 (4 << 28) +#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27) +#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16) + +/* + * If any burst is in flight and DMA paused then this is the time to complete + * on-flight burst and update DMA status register. + */ +#define TEGRA_APBDMA_BURST_COMPLETE_TIME 20 + +/* Channel base address offset from APBDMA base address */ +#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000 + +/* DMA channel register space size */ +#define TEGRA_APBDMA_CHANNEL_REGISTER_SIZE 0x20 + +struct tegra_dma; + +/* + * tegra_dma_chip_data Tegra chip specific DMA data + * @nr_channels: Number of channels available in the controller. + * @max_dma_count: Maximum DMA transfer count supported by DMA controller. + */ +struct tegra_dma_chip_data { + int nr_channels; + int max_dma_count; +}; + +/* DMA channel registers */ +struct tegra_dma_channel_regs { + unsigned long csr; + unsigned long ahb_ptr; + unsigned long apb_ptr; + unsigned long ahb_seq; + unsigned long apb_seq; +}; + +/* + * tegra_dma_sg_req: Dma request details to configure hardware. This + * contains the details for one transfer to configure DMA hw. + * The client's request for data transfer can be broken into multiple + * sub-transfer as per requester details and hw support. + * This sub transfer get added in the list of transfer and point to Tegra + * DMA descriptor which manages the transfer details. + */ +struct tegra_dma_sg_req { + struct tegra_dma_channel_regs ch_regs; + int req_len; + bool configured; + bool last_sg; + bool half_done; + struct list_head node; + struct tegra_dma_desc *dma_desc; +}; + +/* + * tegra_dma_desc: Tegra DMA descriptors which manages the client requests. + * This descriptor keep track of transfer status, callbacks and request + * counts etc. + */ +struct tegra_dma_desc { + struct dma_async_tx_descriptor txd; + int bytes_requested; + int bytes_transferred; + enum dma_status dma_status; + struct list_head node; + struct list_head tx_list; + struct list_head cb_node; + int cb_count; +}; + +struct tegra_dma_channel; + +typedef void (*dma_isr_handler)(struct tegra_dma_channel *tdc, + bool to_terminate); + +/* tegra_dma_channel: Channel specific information */ +struct tegra_dma_channel { + struct dma_chan dma_chan; + bool config_init; + int id; + int irq; + unsigned long chan_base_offset; + spinlock_t lock; + bool busy; + struct tegra_dma *tdma; + bool cyclic; + + /* Different lists for managing the requests */ + struct list_head free_sg_req; + struct list_head pending_sg_req; + struct list_head free_dma_desc; + struct list_head cb_desc; + + /* ISR handler and tasklet for bottom half of isr handling */ + dma_isr_handler isr_handler; + struct tasklet_struct tasklet; + dma_async_tx_callback callback; + void *callback_param; + + /* Channel-slave specific configuration */ + struct dma_slave_config dma_sconfig; +}; + +/* tegra_dma: Tegra DMA specific information */ +struct tegra_dma { + struct dma_device dma_dev; + struct device *dev; + struct clk *dma_clk; + spinlock_t global_lock; + void __iomem *base_addr; + struct tegra_dma_chip_data *chip_data; + + /* Some register need to be cache before suspend */ + u32 reg_gen; + + /* Last member of the structure */ + struct tegra_dma_channel channels[0]; +}; + +static inline void tdma_write(struct tegra_dma *tdma, u32 reg, u32 val) +{ + writel(val, tdma->base_addr + reg); +} + +static inline u32 tdma_read(struct tegra_dma *tdma, u32 reg) +{ + return readl(tdma->base_addr + reg); +} + +static inline void tdc_write(struct tegra_dma_channel *tdc, + u32 reg, u32 val) +{ + writel(val, tdc->tdma->base_addr + tdc->chan_base_offset + reg); +} + +static inline u32 tdc_read(struct tegra_dma_channel *tdc, u32 reg) +{ + return readl(tdc->tdma->base_addr + tdc->chan_base_offset + reg); +} + +static inline struct tegra_dma_channel *to_tegra_dma_chan(struct dma_chan *dc) +{ + return container_of(dc, struct tegra_dma_channel, dma_chan); +} + +static inline struct tegra_dma_desc *txd_to_tegra_dma_desc( + struct dma_async_tx_descriptor *td) +{ + return container_of(td, struct tegra_dma_desc, txd); +} + +static inline struct device *tdc2dev(struct tegra_dma_channel *tdc) +{ + return &tdc->dma_chan.dev->device; +} + +static dma_cookie_t tegra_dma_tx_submit(struct dma_async_tx_descriptor *tx); +static int tegra_dma_runtime_suspend(struct device *dev); +static int tegra_dma_runtime_resume(struct device *dev); + +/* Get DMA desc from free list, if not there then allocate it. */ +static struct tegra_dma_desc *tegra_dma_desc_get( + struct tegra_dma_channel *tdc) +{ + struct tegra_dma_desc *dma_desc; + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + + /* Do not allocate if desc are waiting for ack */ + list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) { + if (async_tx_test_ack(&dma_desc->txd)) { + list_del(&dma_desc->node); + spin_unlock_irqrestore(&tdc->lock, flags); + return dma_desc; + } + } + + spin_unlock_irqrestore(&tdc->lock, flags); + + /* Allocate DMA desc */ + dma_desc = kzalloc(sizeof(*dma_desc), GFP_ATOMIC); + if (!dma_desc) { + dev_err(tdc2dev(tdc), "dma_desc alloc failed\n"); + return NULL; + } + + dma_async_tx_descriptor_init(&dma_desc->txd, &tdc->dma_chan); + dma_desc->txd.tx_submit = tegra_dma_tx_submit; + dma_desc->txd.flags = 0; + return dma_desc; +} + +static void tegra_dma_desc_put(struct tegra_dma_channel *tdc, + struct tegra_dma_desc *dma_desc) +{ + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + if (!list_empty(&dma_desc->tx_list)) + list_splice_init(&dma_desc->tx_list, &tdc->free_sg_req); + list_add_tail(&dma_desc->node, &tdc->free_dma_desc); + spin_unlock_irqrestore(&tdc->lock, flags); +} + +static struct tegra_dma_sg_req *tegra_dma_sg_req_get( + struct tegra_dma_channel *tdc) +{ + struct tegra_dma_sg_req *sg_req = NULL; + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + if (!list_empty(&tdc->free_sg_req)) { + sg_req = list_first_entry(&tdc->free_sg_req, + typeof(*sg_req), node); + list_del(&sg_req->node); + spin_unlock_irqrestore(&tdc->lock, flags); + return sg_req; + } + spin_unlock_irqrestore(&tdc->lock, flags); + + sg_req = kzalloc(sizeof(struct tegra_dma_sg_req), GFP_ATOMIC); + if (!sg_req) + dev_err(tdc2dev(tdc), "sg_req alloc failed\n"); + return sg_req; +} + +static int tegra_dma_slave_config(struct dma_chan *dc, + struct dma_slave_config *sconfig) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + if (!list_empty(&tdc->pending_sg_req)) { + dev_err(tdc2dev(tdc), "Configuration not allowed\n"); + return -EBUSY; + } + + memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig)); + tdc->config_init = true; + return 0; +} + +static void tegra_dma_global_pause(struct tegra_dma_channel *tdc, + bool wait_for_burst_complete) +{ + struct tegra_dma *tdma = tdc->tdma; + + spin_lock(&tdma->global_lock); + tdma_write(tdma, TEGRA_APBDMA_GENERAL, 0); + if (wait_for_burst_complete) + udelay(TEGRA_APBDMA_BURST_COMPLETE_TIME); +} + +static void tegra_dma_global_resume(struct tegra_dma_channel *tdc) +{ + struct tegra_dma *tdma = tdc->tdma; + + tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); + spin_unlock(&tdma->global_lock); +} + +static void tegra_dma_stop(struct tegra_dma_channel *tdc) +{ + u32 csr; + u32 status; + + /* Disable interrupts */ + csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); + csr &= ~TEGRA_APBDMA_CSR_IE_EOC; + tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, csr); + + /* Disable DMA */ + csr &= ~TEGRA_APBDMA_CSR_ENB; + tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, csr); + + /* Clear interrupt status if it is there */ + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { + dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__); + tdc_write(tdc, TEGRA_APBDMA_CHAN_STATUS, status); + } + tdc->busy = false; +} + +static void tegra_dma_start(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *sg_req) +{ + struct tegra_dma_channel_regs *ch_regs = &sg_req->ch_regs; + + tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, ch_regs->csr); + tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_regs->apb_seq); + tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr); + tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq); + tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr); + + /* Start DMA */ + tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, + ch_regs->csr | TEGRA_APBDMA_CSR_ENB); +} + +static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *nsg_req) +{ + unsigned long status; + + /* + * The DMA controller reloads the new configuration for next transfer + * after last burst of current transfer completes. + * If there is no IEC status then this makes sure that last burst + * has not be completed. There may be case that last burst is on + * flight and so it can complete but because DMA is paused, it + * will not generates interrupt as well as not reload the new + * configuration. + * If there is already IEC status then interrupt handler need to + * load new configuration. + */ + tegra_dma_global_pause(tdc, false); + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + + /* + * If interrupt is pending then do nothing as the ISR will handle + * the programing for new request. + */ + if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { + dev_err(tdc2dev(tdc), + "Skipping new configuration as interrupt is pending\n"); + tegra_dma_global_resume(tdc); + return; + } + + /* Safe to program new configuration */ + tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr); + tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr); + tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, + nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); + nsg_req->configured = true; + + tegra_dma_global_resume(tdc); +} + +static void tdc_start_head_req(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_sg_req *sg_req; + + if (list_empty(&tdc->pending_sg_req)) + return; + + sg_req = list_first_entry(&tdc->pending_sg_req, + typeof(*sg_req), node); + tegra_dma_start(tdc, sg_req); + sg_req->configured = true; + tdc->busy = true; +} + +static void tdc_configure_next_head_desc(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_sg_req *hsgreq; + struct tegra_dma_sg_req *hnsgreq; + + if (list_empty(&tdc->pending_sg_req)) + return; + + hsgreq = list_first_entry(&tdc->pending_sg_req, typeof(*hsgreq), node); + if (!list_is_last(&hsgreq->node, &tdc->pending_sg_req)) { + hnsgreq = list_first_entry(&hsgreq->node, + typeof(*hnsgreq), node); + tegra_dma_configure_for_next(tdc, hnsgreq); + } +} + +static inline int get_current_xferred_count(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *sg_req, unsigned long status) +{ + return sg_req->req_len - (status & TEGRA_APBDMA_STATUS_COUNT_MASK) - 4; +} + +static void tegra_dma_abort_all(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_sg_req *sgreq; + struct tegra_dma_desc *dma_desc; + + while (!list_empty(&tdc->pending_sg_req)) { + sgreq = list_first_entry(&tdc->pending_sg_req, + typeof(*sgreq), node); + list_del(&sgreq->node); + list_add_tail(&sgreq->node, &tdc->free_sg_req); + if (sgreq->last_sg) { + dma_desc = sgreq->dma_desc; + dma_desc->dma_status = DMA_ERROR; + list_add_tail(&dma_desc->node, &tdc->free_dma_desc); + + /* Add in cb list if it is not there. */ + if (!dma_desc->cb_count) + list_add_tail(&dma_desc->cb_node, + &tdc->cb_desc); + dma_desc->cb_count++; + } + } + tdc->isr_handler = NULL; +} + +static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *last_sg_req, bool to_terminate) +{ + struct tegra_dma_sg_req *hsgreq = NULL; + + if (list_empty(&tdc->pending_sg_req)) { + dev_err(tdc2dev(tdc), "Dma is running without req\n"); + tegra_dma_stop(tdc); + return false; + } + + /* + * Check that head req on list should be in flight. + * If it is not in flight then abort transfer as + * looping of transfer can not continue. + */ + hsgreq = list_first_entry(&tdc->pending_sg_req, typeof(*hsgreq), node); + if (!hsgreq->configured) { + tegra_dma_stop(tdc); + dev_err(tdc2dev(tdc), "Error in dma transfer, aborting dma\n"); + tegra_dma_abort_all(tdc); + return false; + } + + /* Configure next request */ + if (!to_terminate) + tdc_configure_next_head_desc(tdc); + return true; +} + +static void handle_once_dma_done(struct tegra_dma_channel *tdc, + bool to_terminate) +{ + struct tegra_dma_sg_req *sgreq; + struct tegra_dma_desc *dma_desc; + + tdc->busy = false; + sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node); + dma_desc = sgreq->dma_desc; + dma_desc->bytes_transferred += sgreq->req_len; + + list_del(&sgreq->node); + if (sgreq->last_sg) { + dma_desc->dma_status = DMA_SUCCESS; + dma_cookie_complete(&dma_desc->txd); + if (!dma_desc->cb_count) + list_add_tail(&dma_desc->cb_node, &tdc->cb_desc); + dma_desc->cb_count++; + list_add_tail(&dma_desc->node, &tdc->free_dma_desc); + } + list_add_tail(&sgreq->node, &tdc->free_sg_req); + + /* Do not start DMA if it is going to be terminate */ + if (to_terminate || list_empty(&tdc->pending_sg_req)) + return; + + tdc_start_head_req(tdc); + return; +} + +static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, + bool to_terminate) +{ + struct tegra_dma_sg_req *sgreq; + struct tegra_dma_desc *dma_desc; + bool st; + + sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node); + dma_desc = sgreq->dma_desc; + dma_desc->bytes_transferred += sgreq->req_len; + + /* Callback need to be call */ + if (!dma_desc->cb_count) + list_add_tail(&dma_desc->cb_node, &tdc->cb_desc); + dma_desc->cb_count++; + + /* If not last req then put at end of pending list */ + if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) { + list_del(&sgreq->node); + list_add_tail(&sgreq->node, &tdc->pending_sg_req); + sgreq->configured = false; + st = handle_continuous_head_request(tdc, sgreq, to_terminate); + if (!st) + dma_desc->dma_status = DMA_ERROR; + } + return; +} + +static void tegra_dma_tasklet(unsigned long data) +{ + struct tegra_dma_channel *tdc = (struct tegra_dma_channel *)data; + dma_async_tx_callback callback = NULL; + void *callback_param = NULL; + struct tegra_dma_desc *dma_desc; + unsigned long flags; + int cb_count; + + spin_lock_irqsave(&tdc->lock, flags); + while (!list_empty(&tdc->cb_desc)) { + dma_desc = list_first_entry(&tdc->cb_desc, + typeof(*dma_desc), cb_node); + list_del(&dma_desc->cb_node); + callback = dma_desc->txd.callback; + callback_param = dma_desc->txd.callback_param; + cb_count = dma_desc->cb_count; + dma_desc->cb_count = 0; + spin_unlock_irqrestore(&tdc->lock, flags); + while (cb_count-- && callback) + callback(callback_param); + spin_lock_irqsave(&tdc->lock, flags); + } + spin_unlock_irqrestore(&tdc->lock, flags); +} + +static irqreturn_t tegra_dma_isr(int irq, void *dev_id) +{ + struct tegra_dma_channel *tdc = dev_id; + unsigned long status; + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { + tdc_write(tdc, TEGRA_APBDMA_CHAN_STATUS, status); + tdc->isr_handler(tdc, false); + tasklet_schedule(&tdc->tasklet); + spin_unlock_irqrestore(&tdc->lock, flags); + return IRQ_HANDLED; + } + + spin_unlock_irqrestore(&tdc->lock, flags); + dev_info(tdc2dev(tdc), + "Interrupt already served status 0x%08lx\n", status); + return IRQ_NONE; +} + +static dma_cookie_t tegra_dma_tx_submit(struct dma_async_tx_descriptor *txd) +{ + struct tegra_dma_desc *dma_desc = txd_to_tegra_dma_desc(txd); + struct tegra_dma_channel *tdc = to_tegra_dma_chan(txd->chan); + unsigned long flags; + dma_cookie_t cookie; + + spin_lock_irqsave(&tdc->lock, flags); + dma_desc->dma_status = DMA_IN_PROGRESS; + cookie = dma_cookie_assign(&dma_desc->txd); + list_splice_tail_init(&dma_desc->tx_list, &tdc->pending_sg_req); + spin_unlock_irqrestore(&tdc->lock, flags); + return cookie; +} + +static void tegra_dma_issue_pending(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + if (list_empty(&tdc->pending_sg_req)) { + dev_err(tdc2dev(tdc), "No DMA request\n"); + goto end; + } + if (!tdc->busy) { + tdc_start_head_req(tdc); + + /* Continuous single mode: Configure next req */ + if (tdc->cyclic) { + /* + * Wait for 1 burst time for configure DMA for + * next transfer. + */ + udelay(TEGRA_APBDMA_BURST_COMPLETE_TIME); + tdc_configure_next_head_desc(tdc); + } + } +end: + spin_unlock_irqrestore(&tdc->lock, flags); + return; +} + +static void tegra_dma_terminate_all(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_sg_req *sgreq; + struct tegra_dma_desc *dma_desc; + unsigned long flags; + unsigned long status; + bool was_busy; + + spin_lock_irqsave(&tdc->lock, flags); + if (list_empty(&tdc->pending_sg_req)) { + spin_unlock_irqrestore(&tdc->lock, flags); + return; + } + + if (!tdc->busy) + goto skip_dma_stop; + + /* Pause DMA before checking the queue status */ + tegra_dma_global_pause(tdc, true); + + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { + dev_dbg(tdc2dev(tdc), "%s():handling isr\n", __func__); + tdc->isr_handler(tdc, true); + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + } + + was_busy = tdc->busy; + tegra_dma_stop(tdc); + + if (!list_empty(&tdc->pending_sg_req) && was_busy) { + sgreq = list_first_entry(&tdc->pending_sg_req, + typeof(*sgreq), node); + sgreq->dma_desc->bytes_transferred += + get_current_xferred_count(tdc, sgreq, status); + } + tegra_dma_global_resume(tdc); + +skip_dma_stop: + tegra_dma_abort_all(tdc); + + while (!list_empty(&tdc->cb_desc)) { + dma_desc = list_first_entry(&tdc->cb_desc, + typeof(*dma_desc), cb_node); + list_del(&dma_desc->cb_node); + dma_desc->cb_count = 0; + } + spin_unlock_irqrestore(&tdc->lock, flags); +} + +static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sg_req; + enum dma_status ret; + unsigned long flags; + + spin_lock_irqsave(&tdc->lock, flags); + + ret = dma_cookie_status(dc, cookie, txstate); + if (ret == DMA_SUCCESS) { + dma_set_residue(txstate, 0); + spin_unlock_irqrestore(&tdc->lock, flags); + return ret; + } + + /* Check on wait_ack desc status */ + list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) { + if (dma_desc->txd.cookie == cookie) { + dma_set_residue(txstate, + dma_desc->bytes_requested - + dma_desc->bytes_transferred); + ret = dma_desc->dma_status; + spin_unlock_irqrestore(&tdc->lock, flags); + return ret; + } + } + + /* Check in pending list */ + list_for_each_entry(sg_req, &tdc->pending_sg_req, node) { + dma_desc = sg_req->dma_desc; + if (dma_desc->txd.cookie == cookie) { + dma_set_residue(txstate, + dma_desc->bytes_requested - + dma_desc->bytes_transferred); + ret = dma_desc->dma_status; + spin_unlock_irqrestore(&tdc->lock, flags); + return ret; + } + } + + dev_dbg(tdc2dev(tdc), "cookie %d does not found\n", cookie); + spin_unlock_irqrestore(&tdc->lock, flags); + return ret; +} + +static int tegra_dma_device_control(struct dma_chan *dc, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + switch (cmd) { + case DMA_SLAVE_CONFIG: + return tegra_dma_slave_config(dc, + (struct dma_slave_config *)arg); + + case DMA_TERMINATE_ALL: + tegra_dma_terminate_all(dc); + return 0; + + default: + break; + } + + return -ENXIO; +} + +static inline int get_bus_width(struct tegra_dma_channel *tdc, + enum dma_slave_buswidth slave_bw) +{ + switch (slave_bw) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_8; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_16; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_32; + case DMA_SLAVE_BUSWIDTH_8_BYTES: + return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_64; + default: + dev_warn(tdc2dev(tdc), + "slave bw is not supported, using 32bits\n"); + return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_32; + } +} + +static inline int get_burst_size(struct tegra_dma_channel *tdc, + u32 burst_size, enum dma_slave_buswidth slave_bw, int len) +{ + int burst_byte; + int burst_ahb_width; + + /* + * burst_size from client is in terms of the bus_width. + * convert them into AHB memory width which is 4 byte. + */ + burst_byte = burst_size * slave_bw; + burst_ahb_width = burst_byte / 4; + + /* If burst size is 0 then calculate the burst size based on length */ + if (!burst_ahb_width) { + if (len & 0xF) + return TEGRA_APBDMA_AHBSEQ_BURST_1; + else if ((len >> 4) & 0x1) + return TEGRA_APBDMA_AHBSEQ_BURST_4; + else + return TEGRA_APBDMA_AHBSEQ_BURST_8; + } + if (burst_ahb_width < 4) + return TEGRA_APBDMA_AHBSEQ_BURST_1; + else if (burst_ahb_width < 8) + return TEGRA_APBDMA_AHBSEQ_BURST_4; + else + return TEGRA_APBDMA_AHBSEQ_BURST_8; +} + +static int get_transfer_param(struct tegra_dma_channel *tdc, + enum dma_transfer_direction direction, unsigned long *apb_addr, + unsigned long *apb_seq, unsigned long *csr, unsigned int *burst_size, + enum dma_slave_buswidth *slave_bw) +{ + + switch (direction) { + case DMA_MEM_TO_DEV: + *apb_addr = tdc->dma_sconfig.dst_addr; + *apb_seq = get_bus_width(tdc, tdc->dma_sconfig.dst_addr_width); + *burst_size = tdc->dma_sconfig.dst_maxburst; + *slave_bw = tdc->dma_sconfig.dst_addr_width; + *csr = TEGRA_APBDMA_CSR_DIR; + return 0; + + case DMA_DEV_TO_MEM: + *apb_addr = tdc->dma_sconfig.src_addr; + *apb_seq = get_bus_width(tdc, tdc->dma_sconfig.src_addr_width); + *burst_size = tdc->dma_sconfig.src_maxburst; + *slave_bw = tdc->dma_sconfig.src_addr_width; + *csr = 0; + return 0; + + default: + dev_err(tdc2dev(tdc), "Dma direction is not supported\n"); + return -EINVAL; + } + return -EINVAL; +} + +static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( + struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction direction, unsigned long flags, + void *context) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_desc *dma_desc; + unsigned int i; + struct scatterlist *sg; + unsigned long csr, ahb_seq, apb_ptr, apb_seq; + struct list_head req_list; + struct tegra_dma_sg_req *sg_req = NULL; + u32 burst_size; + enum dma_slave_buswidth slave_bw; + int ret; + + if (!tdc->config_init) { + dev_err(tdc2dev(tdc), "dma channel is not configured\n"); + return NULL; + } + if (sg_len < 1) { + dev_err(tdc2dev(tdc), "Invalid segment length %d\n", sg_len); + return NULL; + } + + ret = get_transfer_param(tdc, direction, &apb_ptr, &apb_seq, &csr, + &burst_size, &slave_bw); + if (ret < 0) + return NULL; + + INIT_LIST_HEAD(&req_list); + + ahb_seq = TEGRA_APBDMA_AHBSEQ_INTR_ENB; + ahb_seq |= TEGRA_APBDMA_AHBSEQ_WRAP_NONE << + TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; + ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; + + csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW; + csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_APBDMA_CSR_IE_EOC; + + apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; + + dma_desc = tegra_dma_desc_get(tdc); + if (!dma_desc) { + dev_err(tdc2dev(tdc), "Dma descriptors not available\n"); + return NULL; + } + INIT_LIST_HEAD(&dma_desc->tx_list); + INIT_LIST_HEAD(&dma_desc->cb_node); + dma_desc->cb_count = 0; + dma_desc->bytes_requested = 0; + dma_desc->bytes_transferred = 0; + dma_desc->dma_status = DMA_IN_PROGRESS; + + /* Make transfer requests */ + for_each_sg(sgl, sg, sg_len, i) { + u32 len, mem; + + mem = sg_phys(sg); + len = sg_dma_len(sg); + + if ((len & 3) || (mem & 3) || + (len > tdc->tdma->chip_data->max_dma_count)) { + dev_err(tdc2dev(tdc), + "Dma length/memory address is not supported\n"); + tegra_dma_desc_put(tdc, dma_desc); + return NULL; + } + + sg_req = tegra_dma_sg_req_get(tdc); + if (!sg_req) { + dev_err(tdc2dev(tdc), "Dma sg-req not available\n"); + tegra_dma_desc_put(tdc, dma_desc); + return NULL; + } + + ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len); + dma_desc->bytes_requested += len; + + sg_req->ch_regs.apb_ptr = apb_ptr; + sg_req->ch_regs.ahb_ptr = mem; + sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); + sg_req->ch_regs.apb_seq = apb_seq; + sg_req->ch_regs.ahb_seq = ahb_seq; + sg_req->configured = false; + sg_req->last_sg = false; + sg_req->dma_desc = dma_desc; + sg_req->req_len = len; + + list_add_tail(&sg_req->node, &dma_desc->tx_list); + } + sg_req->last_sg = true; + if (flags & DMA_CTRL_ACK) + dma_desc->txd.flags = DMA_CTRL_ACK; + + /* + * Make sure that mode should not be conflicting with currently + * configured mode. + */ + if (!tdc->isr_handler) { + tdc->isr_handler = handle_once_dma_done; + tdc->cyclic = false; + } else { + if (tdc->cyclic) { + dev_err(tdc2dev(tdc), "DMA configured in cyclic mode\n"); + tegra_dma_desc_put(tdc, dma_desc); + return NULL; + } + } + + return &dma_desc->txd; +} + +struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( + struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + void *context) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_desc *dma_desc = NULL; + struct tegra_dma_sg_req *sg_req = NULL; + unsigned long csr, ahb_seq, apb_ptr, apb_seq; + int len; + size_t remain_len; + dma_addr_t mem = buf_addr; + u32 burst_size; + enum dma_slave_buswidth slave_bw; + int ret; + + if (!buf_len || !period_len) { + dev_err(tdc2dev(tdc), "Invalid buffer/period len\n"); + return NULL; + } + + if (!tdc->config_init) { + dev_err(tdc2dev(tdc), "DMA slave is not configured\n"); + return NULL; + } + + /* + * We allow to take more number of requests till DMA is + * not started. The driver will loop over all requests. + * Once DMA is started then new requests can be queued only after + * terminating the DMA. + */ + if (tdc->busy) { + dev_err(tdc2dev(tdc), "Request not allowed when dma running\n"); + return NULL; + } + + /* + * We only support cycle transfer when buf_len is multiple of + * period_len. + */ + if (buf_len % period_len) { + dev_err(tdc2dev(tdc), "buf_len is not multiple of period_len\n"); + return NULL; + } + + len = period_len; + if ((len & 3) || (buf_addr & 3) || + (len > tdc->tdma->chip_data->max_dma_count)) { + dev_err(tdc2dev(tdc), "Req len/mem address is not correct\n"); + return NULL; + } + + ret = get_transfer_param(tdc, direction, &apb_ptr, &apb_seq, &csr, + &burst_size, &slave_bw); + if (ret < 0) + return NULL; + + + ahb_seq = TEGRA_APBDMA_AHBSEQ_INTR_ENB; + ahb_seq |= TEGRA_APBDMA_AHBSEQ_WRAP_NONE << + TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; + ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; + + csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC; + csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; + + apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; + + dma_desc = tegra_dma_desc_get(tdc); + if (!dma_desc) { + dev_err(tdc2dev(tdc), "not enough descriptors available\n"); + return NULL; + } + + INIT_LIST_HEAD(&dma_desc->tx_list); + INIT_LIST_HEAD(&dma_desc->cb_node); + dma_desc->cb_count = 0; + + dma_desc->bytes_transferred = 0; + dma_desc->bytes_requested = buf_len; + remain_len = buf_len; + + /* Split transfer equal to period size */ + while (remain_len) { + sg_req = tegra_dma_sg_req_get(tdc); + if (!sg_req) { + dev_err(tdc2dev(tdc), "Dma sg-req not available\n"); + tegra_dma_desc_put(tdc, dma_desc); + return NULL; + } + + ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len); + sg_req->ch_regs.apb_ptr = apb_ptr; + sg_req->ch_regs.ahb_ptr = mem; + sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); + sg_req->ch_regs.apb_seq = apb_seq; + sg_req->ch_regs.ahb_seq = ahb_seq; + sg_req->configured = false; + sg_req->half_done = false; + sg_req->last_sg = false; + sg_req->dma_desc = dma_desc; + sg_req->req_len = len; + + list_add_tail(&sg_req->node, &dma_desc->tx_list); + remain_len -= len; + mem += len; + } + sg_req->last_sg = true; + dma_desc->txd.flags = DMA_CTRL_ACK; + + /* + * Make sure that mode should not be conflicting with currently + * configured mode. + */ + if (!tdc->isr_handler) { + tdc->isr_handler = handle_cont_sngl_cycle_dma_done; + tdc->cyclic = true; + } else { + if (!tdc->cyclic) { + dev_err(tdc2dev(tdc), "DMA configuration conflict\n"); + tegra_dma_desc_put(tdc, dma_desc); + return NULL; + } + } + + return &dma_desc->txd; +} + +static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + dma_cookie_init(&tdc->dma_chan); + tdc->config_init = false; + return 0; +} + +static void tegra_dma_free_chan_resources(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sg_req; + struct list_head dma_desc_list; + struct list_head sg_req_list; + unsigned long flags; + + INIT_LIST_HEAD(&dma_desc_list); + INIT_LIST_HEAD(&sg_req_list); + + dev_dbg(tdc2dev(tdc), "Freeing channel %d\n", tdc->id); + + if (tdc->busy) + tegra_dma_terminate_all(dc); + + spin_lock_irqsave(&tdc->lock, flags); + list_splice_init(&tdc->pending_sg_req, &sg_req_list); + list_splice_init(&tdc->free_sg_req, &sg_req_list); + list_splice_init(&tdc->free_dma_desc, &dma_desc_list); + INIT_LIST_HEAD(&tdc->cb_desc); + tdc->config_init = false; + spin_unlock_irqrestore(&tdc->lock, flags); + + while (!list_empty(&dma_desc_list)) { + dma_desc = list_first_entry(&dma_desc_list, + typeof(*dma_desc), node); + list_del(&dma_desc->node); + kfree(dma_desc); + } + + while (!list_empty(&sg_req_list)) { + sg_req = list_first_entry(&sg_req_list, typeof(*sg_req), node); + list_del(&sg_req->node); + kfree(sg_req); + } +} + +/* Tegra20 specific DMA controller information */ +static struct tegra_dma_chip_data tegra20_dma_chip_data = { + .nr_channels = 16, + .max_dma_count = 1024UL * 64, +}; + +#if defined(CONFIG_OF) +/* Tegra30 specific DMA controller information */ +static struct tegra_dma_chip_data tegra30_dma_chip_data = { + .nr_channels = 32, + .max_dma_count = 1024UL * 64, +}; + +static const struct of_device_id tegra_dma_of_match[] __devinitconst = { + { + .compatible = "nvidia,tegra30-apbdma-new", + .data = &tegra30_dma_chip_data, + }, { + .compatible = "nvidia,tegra20-apbdma-new", + .data = &tegra20_dma_chip_data, + }, { + }, +}; +MODULE_DEVICE_TABLE(of, tegra_dma_of_match); +#endif + +static int __devinit tegra_dma_probe(struct platform_device *pdev) +{ + struct resource *res; + struct tegra_dma *tdma; + int ret; + int i; + struct tegra_dma_chip_data *cdata = NULL; + + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_device(of_match_ptr(tegra_dma_of_match), + &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "Error: No device match found\n"); + return -ENODEV; + } + cdata = match->data; + } else { + /* If no device tree then fallback to tegra20 */ + cdata = &tegra20_dma_chip_data; + } + + tdma = devm_kzalloc(&pdev->dev, sizeof(*tdma) + cdata->nr_channels * + sizeof(struct tegra_dma_channel), GFP_KERNEL); + if (!tdma) { + dev_err(&pdev->dev, "Error: memory allocation failed\n"); + return -ENOMEM; + } + + tdma->dev = &pdev->dev; + tdma->chip_data = cdata; + platform_set_drvdata(pdev, tdma); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "No mem resource for DMA\n"); + return -EINVAL; + } + + tdma->base_addr = devm_request_and_ioremap(&pdev->dev, res); + if (!tdma->base_addr) { + dev_err(&pdev->dev, + "Cannot request memregion/iomap dma address\n"); + return -EADDRNOTAVAIL; + } + + tdma->dma_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tdma->dma_clk)) { + dev_err(&pdev->dev, "Error: Missing controller clock\n"); + return PTR_ERR(tdma->dma_clk); + } + + spin_lock_init(&tdma->global_lock); + + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = tegra_dma_runtime_resume(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "dma_runtime_resume failed %d\n", + ret); + goto err_pm_disable; + } + } + + /* Reset DMA controller */ + tegra_periph_reset_assert(tdma->dma_clk); + udelay(2); + tegra_periph_reset_deassert(tdma->dma_clk); + + /* Enable global DMA registers */ + tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); + tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); + tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); + + INIT_LIST_HEAD(&tdma->dma_dev.channels); + for (i = 0; i < cdata->nr_channels; i++) { + struct tegra_dma_channel *tdc = &tdma->channels[i]; + char irq_name[30]; + + tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET + + i * TEGRA_APBDMA_CHANNEL_REGISTER_SIZE; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!res) { + ret = -EINVAL; + dev_err(&pdev->dev, "No irq resource for chan %d\n", i); + goto err_irq; + } + tdc->irq = res->start; + snprintf(irq_name, sizeof(irq_name), "apbdma.%d", i); + ret = devm_request_irq(&pdev->dev, tdc->irq, + tegra_dma_isr, 0, irq_name, tdc); + if (ret) { + dev_err(&pdev->dev, + "request_irq failed with err %d channel %d\n", + i, ret); + goto err_irq; + } + + tdc->dma_chan.device = &tdma->dma_dev; + dma_cookie_init(&tdc->dma_chan); + list_add_tail(&tdc->dma_chan.device_node, + &tdma->dma_dev.channels); + tdc->tdma = tdma; + tdc->id = i; + + tasklet_init(&tdc->tasklet, tegra_dma_tasklet, + (unsigned long)tdc); + spin_lock_init(&tdc->lock); + + INIT_LIST_HEAD(&tdc->pending_sg_req); + INIT_LIST_HEAD(&tdc->free_sg_req); + INIT_LIST_HEAD(&tdc->free_dma_desc); + INIT_LIST_HEAD(&tdc->cb_desc); + } + + dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask); + dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask); + tdma->dma_dev.dev = &pdev->dev; + tdma->dma_dev.device_alloc_chan_resources = + tegra_dma_alloc_chan_resources; + tdma->dma_dev.device_free_chan_resources = + tegra_dma_free_chan_resources; + tdma->dma_dev.device_prep_slave_sg = tegra_dma_prep_slave_sg; + tdma->dma_dev.device_prep_dma_cyclic = tegra_dma_prep_dma_cyclic; + tdma->dma_dev.device_control = tegra_dma_device_control; + tdma->dma_dev.device_tx_status = tegra_dma_tx_status; + tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending; + + ret = dma_async_device_register(&tdma->dma_dev); + if (ret < 0) { + dev_err(&pdev->dev, + "Tegra20 APB DMA driver registration failed %d\n", ret); + goto err_irq; + } + + dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n", + cdata->nr_channels); + return 0; + +err_irq: + while (--i >= 0) { + struct tegra_dma_channel *tdc = &tdma->channels[i]; + tasklet_kill(&tdc->tasklet); + } + +err_pm_disable: + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_dma_runtime_suspend(&pdev->dev); + return ret; +} + +static int __devexit tegra_dma_remove(struct platform_device *pdev) +{ + struct tegra_dma *tdma = platform_get_drvdata(pdev); + int i; + struct tegra_dma_channel *tdc; + + dma_async_device_unregister(&tdma->dma_dev); + + for (i = 0; i < tdma->chip_data->nr_channels; ++i) { + tdc = &tdma->channels[i]; + tasklet_kill(&tdc->tasklet); + } + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_dma_runtime_suspend(&pdev->dev); + + return 0; +} + +static int tegra_dma_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_dma *tdma = platform_get_drvdata(pdev); + + clk_disable(tdma->dma_clk); + return 0; +} + +static int tegra_dma_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_dma *tdma = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(tdma->dma_clk); + if (ret < 0) { + dev_err(dev, "clk_enable failed: %d\n", ret); + return ret; + } + return 0; +} + +static const struct dev_pm_ops tegra_dma_dev_pm_ops __devinitconst = { +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = tegra_dma_runtime_suspend, + .runtime_resume = tegra_dma_runtime_resume, +#endif +}; + +static struct platform_driver tegra_dmac_driver = { + .driver = { + .name = "tegra20-apbdma", + .owner = THIS_MODULE, + .pm = &tegra_dma_dev_pm_ops, + .of_match_table = of_match_ptr(tegra_dma_of_match), + }, + .probe = tegra_dma_probe, + .remove = __devexit_p(tegra_dma_remove), +}; + +module_platform_driver(tegra_dmac_driver); + +MODULE_ALIAS("platform:tegra20-apbdma"); +MODULE_DESCRIPTION("NVIDIA Tegra APB DMA Controller driver"); +MODULE_AUTHOR("Laxman Dewangan "); +MODULE_LICENSE("GPL v2"); -- GitLab From 09617ce4774ebf30a55b8451f4b35031f626f763 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Fri, 8 Jun 2012 10:26:08 +0800 Subject: [PATCH 0388/5711] ALSA: hda - power setting error check codec may reject power state transition requests(reporting PS-ERROR set), in that case we re-issue a power state setting and check error bit again. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fedbfae978af..851e6ecfa011 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3526,6 +3526,9 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { + int count; + unsigned int state; + if (codec->patch_ops.set_power_state) { codec->patch_ops.set_power_state(codec, fg, power_state); return; @@ -3537,9 +3540,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); msleep(epss ? 10 : 100); } - snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, - power_state); - snd_hda_codec_set_power_to_all(codec, fg, power_state, true); + + /* repeat power states setting at most 10 times*/ + for (count = 0; count < 10; count++) { + snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, + power_state); + snd_hda_codec_set_power_to_all(codec, fg, power_state, true); + state = snd_hda_codec_read(codec, fg, 0, + AC_VERB_GET_POWER_STATE, 0); + if (!(state & AC_PWRST_ERROR)) + break; + } } #ifdef CONFIG_SND_HDA_HWDEP -- GitLab From ba1ddcb6ca0c46edd275790d1e4e2cfd6219ce19 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 8 Jun 2012 11:16:22 +0100 Subject: [PATCH 0389/5711] GFS2: Cache last hash bucket for glock seq_files For the glocks and glstats seq_files, which are exposed via debugfs we should cache the most recent hash bucket, along with the offset into that bucket. This allows us to restart from that point, rather than having to begin at the beginning each time. This is an idea from Eric Dumazet, however I've slightly extended it so that if the position from which we are due to start is at any point beyond the last cached point, we start from the last cached point, plus whatever is the appropriate offset. I don't really expect people to be lseeking around these files, but if they did so with only positive offsets, then we'd still get some of the benefit of using a cached offset. With my simple test of around 200k entries in the file, I'm seeing an approx 10x speed up. Cc: Eric Dumazet Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 1c4cddf42a66..3ad8cb3eeb88 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -46,10 +46,12 @@ #include "trace_gfs2.h" struct gfs2_glock_iter { - int hash; /* hash bucket index */ - struct gfs2_sbd *sdp; /* incore superblock */ - struct gfs2_glock *gl; /* current glock struct */ - char string[512]; /* scratch space */ + int hash; /* hash bucket index */ + unsigned nhash; /* Index within current bucket */ + struct gfs2_sbd *sdp; /* incore superblock */ + struct gfs2_glock *gl; /* current glock struct */ + loff_t last_pos; /* last position */ + char string[512]; /* scratch space */ }; typedef void (*glock_examiner) (struct gfs2_glock * gl); @@ -950,7 +952,7 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) if (seq) { struct gfs2_glock_iter *gi = seq->private; vsprintf(gi->string, fmt, args); - seq_printf(seq, gi->string); + seq_puts(seq, gi->string); } else { vaf.fmt = fmt; vaf.va = &args; @@ -1854,8 +1856,14 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) gl = gi->gl; if (gl) { gi->gl = glock_hash_next(gl); + gi->nhash++; } else { + if (gi->hash >= GFS2_GL_HASH_SIZE) { + rcu_read_unlock(); + return 1; + } gi->gl = glock_hash_chain(gi->hash); + gi->nhash = 0; } while (gi->gl == NULL) { gi->hash++; @@ -1864,6 +1872,7 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) return 1; } gi->gl = glock_hash_chain(gi->hash); + gi->nhash = 0; } /* Skip entries for other sb and dead entries */ } while (gi->sdp != gi->gl->gl_sbd || atomic_read(&gi->gl->gl_ref) == 0); @@ -1876,7 +1885,12 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) struct gfs2_glock_iter *gi = seq->private; loff_t n = *pos; - gi->hash = 0; + if (gi->last_pos <= *pos) + n = gi->nhash + (*pos - gi->last_pos); + else + gi->hash = 0; + + gi->nhash = 0; rcu_read_lock(); do { @@ -1884,6 +1898,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) return NULL; } while (n--); + gi->last_pos = *pos; return gi->gl; } @@ -1893,7 +1908,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, struct gfs2_glock_iter *gi = seq->private; (*pos)++; - + gi->last_pos = *pos; if (gfs2_glock_iter_next(gi)) return NULL; -- GitLab From 90306c41dc3d8e5f12ecd0193dae99e0e7f6e896 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 29 May 2012 23:01:09 -0500 Subject: [PATCH 0390/5711] GFS2: Use lvbs for storing rgrp information with mount option Instead of reading in the resource groups when gfs2 is checking for free space to allocate from, gfs2 can store the necessary infromation in the resource group's lvb. Also, instead of searching for unlinked inodes in every resource group that's checked for free space, gfs2 can store the number of unlinked but inodes in the lvb, and only check for unlinked inodes if it will find some. The first time a resource group is locked, the lvb must initialized. Since this involves counting the unlinked inodes in the resource group, this takes a little extra time. But after that, if the resource group is locked with GL_SKIP, the buffer head won't be read in unless it's actually needed. Enabling the resource groups lvbs is done via the rgrplvb mount option. If this option isn't set, the lvbs will still be set and updated, but they won't be verfied or used by the filesystem. To safely turn on this option, all of the nodes mounting the filesystem must be running code with this patch, and the filesystem must have been completely unmounted since they were updated. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 1 + fs/gfs2/incore.h | 2 + fs/gfs2/rgrp.c | 147 +++++++++++++++++++++++++++++++++--- fs/gfs2/super.c | 12 +++ include/linux/gfs2_ondisk.h | 10 +++ 5 files changed, 163 insertions(+), 9 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 3ad8cb3eeb88..10ae1645d9a5 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0; gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0; memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb)); + memset(gl->gl_lvb, 0, 32 * sizeof(char)); gl->gl_lksb.sb_lvbptr = gl->gl_lvb; gl->gl_tchange = jiffies; gl->gl_object = NULL; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 5cda51a3e3bd..dc730700b3b4 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -89,6 +89,7 @@ struct gfs2_rgrpd { u64 rd_igeneration; struct gfs2_bitmap *rd_bits; struct gfs2_sbd *rd_sbd; + struct gfs2_rgrp_lvb *rd_rgl; u32 rd_last_alloc; u32 rd_flags; #define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */ @@ -470,6 +471,7 @@ struct gfs2_args { unsigned int ar_discard:1; /* discard requests */ unsigned int ar_errors:2; /* errors=withdraw | panic */ unsigned int ar_nobarrier:1; /* do not send barriers */ + unsigned int ar_rgrplvb:1; /* use lvbs for rgrp info */ int ar_commit; /* Commit interval */ int ar_statfs_quantum; /* The fast statfs interval */ int ar_quota_quantum; /* The quota interval */ diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 9eca6a9cff8f..3c6f7ed16a3b 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -660,6 +660,7 @@ static int read_rindex_entry(struct gfs2_inode *ip) goto fail; rgd->rd_gl->gl_object = rgd; + rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lvb; rgd->rd_flags &= ~GFS2_RDF_UPTODATE; if (rgd->rd_data > sdp->sd_max_rg_data) sdp->sd_max_rg_data = rgd->rd_data; @@ -769,9 +770,65 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); } +static int gfs2_rgrp_lvb_valid(struct gfs2_rgrpd *rgd) +{ + struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl; + struct gfs2_rgrp *str = (struct gfs2_rgrp *)rgd->rd_bits[0].bi_bh->b_data; + + if (rgl->rl_flags != str->rg_flags || rgl->rl_free != str->rg_free || + rgl->rl_dinodes != str->rg_dinodes || + rgl->rl_igeneration != str->rg_igeneration) + return 0; + return 1; +} + +static void gfs2_rgrp_ondisk2lvb(struct gfs2_rgrp_lvb *rgl, const void *buf) +{ + const struct gfs2_rgrp *str = buf; + + rgl->rl_magic = cpu_to_be32(GFS2_MAGIC); + rgl->rl_flags = str->rg_flags; + rgl->rl_free = str->rg_free; + rgl->rl_dinodes = str->rg_dinodes; + rgl->rl_igeneration = str->rg_igeneration; + rgl->__pad = 0UL; +} + +static void update_rgrp_lvb_unlinked(struct gfs2_rgrpd *rgd, u32 change) +{ + struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl; + u32 unlinked = be32_to_cpu(rgl->rl_unlinked) + change; + rgl->rl_unlinked = cpu_to_be32(unlinked); +} + +static u32 count_unlinked(struct gfs2_rgrpd *rgd) +{ + struct gfs2_bitmap *bi; + const u32 length = rgd->rd_length; + const u8 *buffer = NULL; + u32 i, goal, count = 0; + + for (i = 0, bi = rgd->rd_bits; i < length; i++, bi++) { + goal = 0; + buffer = bi->bi_bh->b_data + bi->bi_offset; + WARN_ON(!buffer_uptodate(bi->bi_bh)); + while (goal < bi->bi_len * GFS2_NBBY) { + goal = gfs2_bitfit(buffer, bi->bi_len, goal, + GFS2_BLKST_UNLINKED); + if (goal == BFITNOENT) + break; + count++; + goal++; + } + } + + return count; +} + + /** - * gfs2_rgrp_go_lock - Read in a RG's header and bitmaps - * @gh: The glock holder for the resource group + * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps + * @rgd: the struct gfs2_rgrpd describing the RG to read in * * Read in all of a Resource Group's header and bitmap blocks. * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps. @@ -779,9 +836,8 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) * Returns: errno */ -int gfs2_rgrp_go_lock(struct gfs2_holder *gh) +int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) { - struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_glock *gl = rgd->rd_gl; unsigned int length = rgd->rd_length; @@ -789,6 +845,9 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh) unsigned int x, y; int error; + if (rgd->rd_bits[0].bi_bh != NULL) + return 0; + for (x = 0; x < length; x++) { bi = rgd->rd_bits + x; error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh); @@ -815,7 +874,20 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh) rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); rgd->rd_free_clone = rgd->rd_free; } - + if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) { + rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd)); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, + rgd->rd_bits[0].bi_bh->b_data); + } + else if (sdp->sd_args.ar_rgrplvb) { + if (!gfs2_rgrp_lvb_valid(rgd)){ + gfs2_consist_rgrpd(rgd); + error = -EIO; + goto fail; + } + if (rgd->rd_rgl->rl_unlinked == 0) + rgd->rd_flags &= ~GFS2_RDF_CHECK; + } return 0; fail: @@ -829,6 +901,39 @@ fail: return error; } +int update_rgrp_lvb(struct gfs2_rgrpd *rgd) +{ + u32 rl_flags; + + if (rgd->rd_flags & GFS2_RDF_UPTODATE) + return 0; + + if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) + return gfs2_rgrp_bh_get(rgd); + + rl_flags = be32_to_cpu(rgd->rd_rgl->rl_flags); + rl_flags &= ~GFS2_RDF_MASK; + rgd->rd_flags &= GFS2_RDF_MASK; + rgd->rd_flags |= (rl_flags | GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); + if (rgd->rd_rgl->rl_unlinked == 0) + rgd->rd_flags &= ~GFS2_RDF_CHECK; + rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free); + rgd->rd_free_clone = rgd->rd_free; + rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes); + rgd->rd_igeneration = be64_to_cpu(rgd->rd_rgl->rl_igeneration); + return 0; +} + +int gfs2_rgrp_go_lock(struct gfs2_holder *gh) +{ + struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; + struct gfs2_sbd *sdp = rgd->rd_sbd; + + if (gh->gh_flags & GL_SKIP && sdp->sd_args.ar_rgrplvb) + return 0; + return gfs2_rgrp_bh_get((struct gfs2_rgrpd *)gh->gh_gl->gl_object); +} + /** * gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get() * @gh: The glock holder for the resource group @@ -842,8 +947,10 @@ void gfs2_rgrp_go_unlock(struct gfs2_holder *gh) for (x = 0; x < length; x++) { struct gfs2_bitmap *bi = rgd->rd_bits + x; - brelse(bi->bi_bh); - bi->bi_bh = NULL; + if (bi->bi_bh) { + brelse(bi->bi_bh); + bi->bi_bh = NULL; + } } } @@ -987,6 +1094,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) rgd->rd_flags |= GFS2_RGF_TRIMMED; gfs2_trans_add_bh(rgd->rd_gl, bh, 1); gfs2_rgrp_out(rgd, bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, bh->b_data); gfs2_trans_end(sdp); } } @@ -1116,6 +1224,9 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) int error, rg_locked, flags = LM_FLAG_TRY; int loops = 0; + if (sdp->sd_args.ar_rgrplvb) + flags |= GL_SKIP; + if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) rgd = begin = ip->i_rgd; else @@ -1133,22 +1244,34 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) } else { error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, flags, &rs->rs_rgd_gh); + if (!error && sdp->sd_args.ar_rgrplvb) { + error = update_rgrp_lvb(rgd); + if (error) { + gfs2_glock_dq_uninit(&rs->rs_rgd_gh); + return error; + } + } } switch (error) { case 0: if (try_rgrp_fit(rgd, ip)) { + if (sdp->sd_args.ar_rgrplvb) + gfs2_rgrp_bh_get(rgd); ip->i_rgd = rgd; return 0; } - if (rgd->rd_flags & GFS2_RDF_CHECK) + if (rgd->rd_flags & GFS2_RDF_CHECK) { + if (sdp->sd_args.ar_rgrplvb) + gfs2_rgrp_bh_get(rgd); try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); + } if (!rg_locked) gfs2_glock_dq_uninit(&rs->rs_rgd_gh); /* fall through */ case GLR_TRYFAILED: rgd = gfs2_rgrpd_get_next(rgd); if (rgd == begin) { - flags = 0; + flags &= ~LM_FLAG_TRY; loops++; } break; @@ -1529,6 +1652,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data); gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); if (dinode) @@ -1575,6 +1699,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta) rgd->rd_flags &= ~GFS2_RGF_TRIMMED; gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data); /* Directories keep their data in the metadata address space */ if (meta || ip->i_depth) @@ -1611,6 +1736,8 @@ void gfs2_unlink_di(struct inode *inode) trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED); gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data); + update_rgrp_lvb_unlinked(rgd, 1); } static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) @@ -1630,6 +1757,8 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data); + update_rgrp_lvb_unlinked(rgd, -1); gfs2_statfs_change(sdp, 0, +1, -1); } diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 81fc76264ed4..788068758f3a 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -78,6 +78,8 @@ enum { Opt_quota_quantum, Opt_barrier, Opt_nobarrier, + Opt_rgrplvb, + Opt_norgrplvb, Opt_error, }; @@ -115,6 +117,8 @@ static const match_table_t tokens = { {Opt_quota_quantum, "quota_quantum=%d"}, {Opt_barrier, "barrier"}, {Opt_nobarrier, "nobarrier"}, + {Opt_rgrplvb, "rgrplvb"}, + {Opt_norgrplvb, "norgrplvb"}, {Opt_error, NULL} }; @@ -267,6 +271,12 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) case Opt_nobarrier: args->ar_nobarrier = 1; break; + case Opt_rgrplvb: + args->ar_rgrplvb = 1; + break; + case Opt_norgrplvb: + args->ar_rgrplvb = 0; + break; case Opt_error: default: printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); @@ -1379,6 +1389,8 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root) seq_printf(s, ",nobarrier"); if (test_bit(SDF_DEMOTE, &sdp->sd_flags)) seq_printf(s, ",demote_interface_used"); + if (args->ar_rgrplvb) + seq_printf(s, ",rgrplvb"); return 0; } diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index e8ccf6ff3b4d..b2de1f9a88d6 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -170,6 +170,16 @@ struct gfs2_rindex { #define GFS2_RGF_NOALLOC 0x00000008 #define GFS2_RGF_TRIMMED 0x00000010 +struct gfs2_rgrp_lvb { + __be32 rl_magic; + __be32 rl_flags; + __be32 rl_free; + __be32 rl_dinodes; + __be64 rl_igeneration; + __be32 rl_unlinked; + __be32 __pad; +}; + struct gfs2_rgrp { struct gfs2_meta_header rg_header; -- GitLab From f3109a51f8dc88e8a94f620240b7474b91bed37a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 24 May 2012 18:59:10 +0200 Subject: [PATCH 0391/5711] lib: Proportions with flexible period Implement code computing proportions of events of different type (like code in lib/proportions.c) but allowing periods to have different lengths. This allows us to have aging periods of fixed wallclock time which gives better proportion estimates given the hugely varying throughput of different devices - previous measuring of aging period by number of events has the problem that a reasonable period length for a system with low-end USB stick is not a reasonable period length for a system with high-end storage array resulting either in too slow proportion updates or too fluctuating proportion updates. Acked-by: Peter Zijlstra Signed-off-by: Jan Kara Signed-off-by: Fengguang Wu --- include/linux/flex_proportions.h | 101 ++++++++++++ lib/Makefile | 2 +- lib/flex_proportions.c | 266 +++++++++++++++++++++++++++++++ 3 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 include/linux/flex_proportions.h create mode 100644 lib/flex_proportions.c diff --git a/include/linux/flex_proportions.h b/include/linux/flex_proportions.h new file mode 100644 index 000000000000..4ebc49fae391 --- /dev/null +++ b/include/linux/flex_proportions.h @@ -0,0 +1,101 @@ +/* + * Floating proportions with flexible aging period + * + * Copyright (C) 2011, SUSE, Jan Kara + */ + +#ifndef _LINUX_FLEX_PROPORTIONS_H +#define _LINUX_FLEX_PROPORTIONS_H + +#include +#include +#include + +/* + * When maximum proportion of some event type is specified, this is the + * precision with which we allow limitting. Note that this creates an upper + * bound on the number of events per period like + * ULLONG_MAX >> FPROP_FRAC_SHIFT. + */ +#define FPROP_FRAC_SHIFT 10 +#define FPROP_FRAC_BASE (1UL << FPROP_FRAC_SHIFT) + +/* + * ---- Global proportion definitions ---- + */ +struct fprop_global { + /* Number of events in the current period */ + struct percpu_counter events; + /* Current period */ + unsigned int period; + /* Synchronization with period transitions */ + seqcount_t sequence; +}; + +int fprop_global_init(struct fprop_global *p); +void fprop_global_destroy(struct fprop_global *p); +bool fprop_new_period(struct fprop_global *p, int periods); + +/* + * ---- SINGLE ---- + */ +struct fprop_local_single { + /* the local events counter */ + unsigned long events; + /* Period in which we last updated events */ + unsigned int period; + raw_spinlock_t lock; /* Protect period and numerator */ +}; + +#define INIT_FPROP_LOCAL_SINGLE(name) \ +{ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ +} + +int fprop_local_init_single(struct fprop_local_single *pl); +void fprop_local_destroy_single(struct fprop_local_single *pl); +void __fprop_inc_single(struct fprop_global *p, struct fprop_local_single *pl); +void fprop_fraction_single(struct fprop_global *p, + struct fprop_local_single *pl, unsigned long *numerator, + unsigned long *denominator); + +static inline +void fprop_inc_single(struct fprop_global *p, struct fprop_local_single *pl) +{ + unsigned long flags; + + local_irq_save(flags); + __fprop_inc_single(p, pl); + local_irq_restore(flags); +} + +/* + * ---- PERCPU ---- + */ +struct fprop_local_percpu { + /* the local events counter */ + struct percpu_counter events; + /* Period in which we last updated events */ + unsigned int period; + raw_spinlock_t lock; /* Protect period and numerator */ +}; + +int fprop_local_init_percpu(struct fprop_local_percpu *pl); +void fprop_local_destroy_percpu(struct fprop_local_percpu *pl); +void __fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl); +void __fprop_inc_percpu_max(struct fprop_global *p, struct fprop_local_percpu *pl, + int max_frac); +void fprop_fraction_percpu(struct fprop_global *p, + struct fprop_local_percpu *pl, unsigned long *numerator, + unsigned long *denominator); + +static inline +void fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl) +{ + unsigned long flags; + + local_irq_save(flags); + __fprop_inc_percpu(p, pl); + local_irq_restore(flags); +} + +#endif diff --git a/lib/Makefile b/lib/Makefile index 8c31a0cb75e9..ee837378b107 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o \ + proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o lib-$(CONFIG_MMU) += ioremap.o diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c new file mode 100644 index 000000000000..e02a3883ae01 --- /dev/null +++ b/lib/flex_proportions.c @@ -0,0 +1,266 @@ +/* + * Floating proportions with flexible aging period + * + * Copyright (C) 2011, SUSE, Jan Kara + * + * The goal of this code is: Given different types of event, measure proportion + * of each type of event over time. The proportions are measured with + * exponentially decaying history to give smooth transitions. A formula + * expressing proportion of event of type 'j' is: + * + * p_{j} = (\Sum_{i>=0} x_{i,j}/2^{i+1})/(\Sum_{i>=0} x_i/2^{i+1}) + * + * Where x_{i,j} is j's number of events in i-th last time period and x_i is + * total number of events in i-th last time period. + * + * Note that p_{j}'s are normalised, i.e. + * + * \Sum_{j} p_{j} = 1, + * + * This formula can be straightforwardly computed by maintaing denominator + * (let's call it 'd') and for each event type its numerator (let's call it + * 'n_j'). When an event of type 'j' happens, we simply need to do: + * n_j++; d++; + * + * When a new period is declared, we could do: + * d /= 2 + * for each j + * n_j /= 2 + * + * To avoid iteration over all event types, we instead shift numerator of event + * j lazily when someone asks for a proportion of event j or when event j + * occurs. This can bit trivially implemented by remembering last period in + * which something happened with proportion of type j. + */ +#include + +int fprop_global_init(struct fprop_global *p) +{ + int err; + + p->period = 0; + /* Use 1 to avoid dealing with periods with 0 events... */ + err = percpu_counter_init(&p->events, 1); + if (err) + return err; + seqcount_init(&p->sequence); + return 0; +} + +void fprop_global_destroy(struct fprop_global *p) +{ + percpu_counter_destroy(&p->events); +} + +/* + * Declare @periods new periods. It is upto the caller to make sure period + * transitions cannot happen in parallel. + * + * The function returns true if the proportions are still defined and false + * if aging zeroed out all events. This can be used to detect whether declaring + * further periods has any effect. + */ +bool fprop_new_period(struct fprop_global *p, int periods) +{ + u64 events = percpu_counter_sum(&p->events); + + /* + * Don't do anything if there are no events. + */ + if (events <= 1) + return false; + write_seqcount_begin(&p->sequence); + if (periods < 64) + events -= events >> periods; + /* Use addition to avoid losing events happening between sum and set */ + percpu_counter_add(&p->events, -events); + p->period += periods; + write_seqcount_end(&p->sequence); + + return true; +} + +/* + * ---- SINGLE ---- + */ + +int fprop_local_init_single(struct fprop_local_single *pl) +{ + pl->events = 0; + pl->period = 0; + raw_spin_lock_init(&pl->lock); + return 0; +} + +void fprop_local_destroy_single(struct fprop_local_single *pl) +{ +} + +static void fprop_reflect_period_single(struct fprop_global *p, + struct fprop_local_single *pl) +{ + unsigned int period = p->period; + unsigned long flags; + + /* Fast path - period didn't change */ + if (pl->period == period) + return; + raw_spin_lock_irqsave(&pl->lock, flags); + /* Someone updated pl->period while we were spinning? */ + if (pl->period >= period) { + raw_spin_unlock_irqrestore(&pl->lock, flags); + return; + } + /* Aging zeroed our fraction? */ + if (period - pl->period < BITS_PER_LONG) + pl->events >>= period - pl->period; + else + pl->events = 0; + pl->period = period; + raw_spin_unlock_irqrestore(&pl->lock, flags); +} + +/* Event of type pl happened */ +void __fprop_inc_single(struct fprop_global *p, struct fprop_local_single *pl) +{ + fprop_reflect_period_single(p, pl); + pl->events++; + percpu_counter_add(&p->events, 1); +} + +/* Return fraction of events of type pl */ +void fprop_fraction_single(struct fprop_global *p, + struct fprop_local_single *pl, + unsigned long *numerator, unsigned long *denominator) +{ + unsigned int seq; + s64 num, den; + + do { + seq = read_seqcount_begin(&p->sequence); + fprop_reflect_period_single(p, pl); + num = pl->events; + den = percpu_counter_read_positive(&p->events); + } while (read_seqcount_retry(&p->sequence, seq)); + + /* + * Make fraction <= 1 and denominator > 0 even in presence of percpu + * counter errors + */ + if (den <= num) { + if (num) + den = num; + else + den = 1; + } + *denominator = den; + *numerator = num; +} + +/* + * ---- PERCPU ---- + */ +#define PROP_BATCH (8*(1+ilog2(nr_cpu_ids))) + +int fprop_local_init_percpu(struct fprop_local_percpu *pl) +{ + int err; + + err = percpu_counter_init(&pl->events, 0); + if (err) + return err; + pl->period = 0; + raw_spin_lock_init(&pl->lock); + return 0; +} + +void fprop_local_destroy_percpu(struct fprop_local_percpu *pl) +{ + percpu_counter_destroy(&pl->events); +} + +static void fprop_reflect_period_percpu(struct fprop_global *p, + struct fprop_local_percpu *pl) +{ + unsigned int period = p->period; + unsigned long flags; + + /* Fast path - period didn't change */ + if (pl->period == period) + return; + raw_spin_lock_irqsave(&pl->lock, flags); + /* Someone updated pl->period while we were spinning? */ + if (pl->period >= period) { + raw_spin_unlock_irqrestore(&pl->lock, flags); + return; + } + /* Aging zeroed our fraction? */ + if (period - pl->period < BITS_PER_LONG) { + s64 val = percpu_counter_read(&pl->events); + + if (val < (nr_cpu_ids * PROP_BATCH)) + val = percpu_counter_sum(&pl->events); + + __percpu_counter_add(&pl->events, + -val + (val >> (period-pl->period)), PROP_BATCH); + } else + percpu_counter_set(&pl->events, 0); + pl->period = period; + raw_spin_unlock_irqrestore(&pl->lock, flags); +} + +/* Event of type pl happened */ +void __fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl) +{ + fprop_reflect_period_percpu(p, pl); + __percpu_counter_add(&pl->events, 1, PROP_BATCH); + percpu_counter_add(&p->events, 1); +} + +void fprop_fraction_percpu(struct fprop_global *p, + struct fprop_local_percpu *pl, + unsigned long *numerator, unsigned long *denominator) +{ + unsigned int seq; + s64 num, den; + + do { + seq = read_seqcount_begin(&p->sequence); + fprop_reflect_period_percpu(p, pl); + num = percpu_counter_read_positive(&pl->events); + den = percpu_counter_read_positive(&p->events); + } while (read_seqcount_retry(&p->sequence, seq)); + + /* + * Make fraction <= 1 and denominator > 0 even in presence of percpu + * counter errors + */ + if (den <= num) { + if (num) + den = num; + else + den = 1; + } + *denominator = den; + *numerator = num; +} + +/* + * Like __fprop_inc_percpu() except that event is counted only if the given + * type has fraction smaller than @max_frac/FPROP_FRAC_BASE + */ +void __fprop_inc_percpu_max(struct fprop_global *p, + struct fprop_local_percpu *pl, int max_frac) +{ + if (unlikely(max_frac < FPROP_FRAC_BASE)) { + unsigned long numerator, denominator; + + fprop_fraction_percpu(p, pl, &numerator, &denominator); + if (numerator > + (((u64)denominator) * max_frac) >> FPROP_FRAC_SHIFT) + return; + } else + fprop_reflect_period_percpu(p, pl); + __percpu_counter_add(&pl->events, 1, PROP_BATCH); + percpu_counter_add(&p->events, 1); +} -- GitLab From e78d4833c03e28205b3d983f0c4e586ee34785fd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 1 Jun 2012 00:42:06 +0200 Subject: [PATCH 0392/5711] lib: Fix possible deadlock in flexible proportion code When percpu counter function in fprop_new_period() is interrupted by an interrupt while holding counter lock, it can cause deadlock when the interrupt wants to take the lock as well. Fix the problem by disabling interrupts when calling percpu counter functions. Signed-off-by: Jan Kara Signed-off-by: Fengguang Wu --- lib/flex_proportions.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c index e02a3883ae01..c785554f9523 100644 --- a/lib/flex_proportions.c +++ b/lib/flex_proportions.c @@ -62,13 +62,18 @@ void fprop_global_destroy(struct fprop_global *p) */ bool fprop_new_period(struct fprop_global *p, int periods) { - u64 events = percpu_counter_sum(&p->events); + u64 events; + unsigned long flags; + local_irq_save(flags); + events = percpu_counter_sum(&p->events); /* * Don't do anything if there are no events. */ - if (events <= 1) + if (events <= 1) { + local_irq_restore(flags); return false; + } write_seqcount_begin(&p->sequence); if (periods < 64) events -= events >> periods; @@ -76,6 +81,7 @@ bool fprop_new_period(struct fprop_global *p, int periods) percpu_counter_add(&p->events, -events); p->period += periods; write_seqcount_end(&p->sequence); + local_irq_restore(flags); return true; } -- GitLab From eb608e3a344b3af21300360fcf868f8b4e808a8e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 24 May 2012 18:59:11 +0200 Subject: [PATCH 0393/5711] block: Convert BDI proportion calculations to flexible proportions Convert calculations of proportion of writeback each bdi does to new flexible proportion code. That allows us to use aging period of fixed wallclock time which gives better proportion estimates given the hugely varying throughput of different devices. Acked-by: Peter Zijlstra Signed-off-by: Jan Kara Signed-off-by: Fengguang Wu --- include/linux/backing-dev.h | 4 +- mm/backing-dev.c | 6 +-- mm/page-writeback.c | 103 ++++++++++++++++++++++-------------- 3 files changed, 69 insertions(+), 44 deletions(-) diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index b1038bd686ac..489de625cd25 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ struct backing_dev_info { unsigned long dirty_ratelimit; unsigned long balanced_dirty_ratelimit; - struct prop_local_percpu completions; + struct fprop_local_percpu completions; int dirty_exceeded; unsigned int min_ratio; diff --git a/mm/backing-dev.c b/mm/backing-dev.c index dd8e2aafb07e..3387aea11209 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -677,7 +677,7 @@ int bdi_init(struct backing_dev_info *bdi) bdi->min_ratio = 0; bdi->max_ratio = 100; - bdi->max_prop_frac = PROP_FRAC_BASE; + bdi->max_prop_frac = FPROP_FRAC_BASE; spin_lock_init(&bdi->wb_lock); INIT_LIST_HEAD(&bdi->bdi_list); INIT_LIST_HEAD(&bdi->work_list); @@ -700,7 +700,7 @@ int bdi_init(struct backing_dev_info *bdi) bdi->write_bandwidth = INIT_BW; bdi->avg_write_bandwidth = INIT_BW; - err = prop_local_init_percpu(&bdi->completions); + err = fprop_local_init_percpu(&bdi->completions); if (err) { err: @@ -744,7 +744,7 @@ void bdi_destroy(struct backing_dev_info *bdi) for (i = 0; i < NR_BDI_STAT_ITEMS; i++) percpu_counter_destroy(&bdi->bdi_stat[i]); - prop_local_destroy_percpu(&bdi->completions); + fprop_local_destroy_percpu(&bdi->completions); } EXPORT_SYMBOL(bdi_destroy); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 93d8d2f7108c..ec14419e53b5 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -34,6 +34,7 @@ #include #include /* __set_page_dirty_buffers */ #include +#include #include /* @@ -135,7 +136,20 @@ unsigned long global_dirty_limit; * measured in page writeback completions. * */ -static struct prop_descriptor vm_completions; +static struct fprop_global writeout_completions; + +static void writeout_period(unsigned long t); +/* Timer for aging of writeout_completions */ +static struct timer_list writeout_period_timer = + TIMER_DEFERRED_INITIALIZER(writeout_period, 0, 0); +static unsigned long writeout_period_time = 0; + +/* + * Length of period for aging writeout fractions of bdis. This is an + * arbitrarily chosen number. The longer the period, the slower fractions will + * reflect changes in current writeout rate. + */ +#define VM_COMPLETIONS_PERIOD_LEN (3*HZ) /* * Work out the current dirty-memory clamping and background writeout @@ -322,34 +336,6 @@ bool zone_dirty_ok(struct zone *zone) zone_page_state(zone, NR_WRITEBACK) <= limit; } -/* - * couple the period to the dirty_ratio: - * - * period/2 ~ roundup_pow_of_two(dirty limit) - */ -static int calc_period_shift(void) -{ - unsigned long dirty_total; - - if (vm_dirty_bytes) - dirty_total = vm_dirty_bytes / PAGE_SIZE; - else - dirty_total = (vm_dirty_ratio * global_dirtyable_memory()) / - 100; - return 2 + ilog2(dirty_total - 1); -} - -/* - * update the period when the dirty threshold changes. - */ -static void update_completion_period(void) -{ - int shift = calc_period_shift(); - prop_change_shift(&vm_completions, shift); - - writeback_set_ratelimit(); -} - int dirty_background_ratio_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) @@ -383,7 +369,7 @@ int dirty_ratio_handler(struct ctl_table *table, int write, ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (ret == 0 && write && vm_dirty_ratio != old_ratio) { - update_completion_period(); + writeback_set_ratelimit(); vm_dirty_bytes = 0; } return ret; @@ -398,12 +384,21 @@ int dirty_bytes_handler(struct ctl_table *table, int write, ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); if (ret == 0 && write && vm_dirty_bytes != old_bytes) { - update_completion_period(); + writeback_set_ratelimit(); vm_dirty_ratio = 0; } return ret; } +static unsigned long wp_next_time(unsigned long cur_time) +{ + cur_time += VM_COMPLETIONS_PERIOD_LEN; + /* 0 has a special meaning... */ + if (!cur_time) + return 1; + return cur_time; +} + /* * Increment the BDI's writeout completion count and the global writeout * completion count. Called from test_clear_page_writeback(). @@ -411,8 +406,19 @@ int dirty_bytes_handler(struct ctl_table *table, int write, static inline void __bdi_writeout_inc(struct backing_dev_info *bdi) { __inc_bdi_stat(bdi, BDI_WRITTEN); - __prop_inc_percpu_max(&vm_completions, &bdi->completions, - bdi->max_prop_frac); + __fprop_inc_percpu_max(&writeout_completions, &bdi->completions, + bdi->max_prop_frac); + /* First event after period switching was turned off? */ + if (!unlikely(writeout_period_time)) { + /* + * We can race with other __bdi_writeout_inc calls here but + * it does not cause any harm since the resulting time when + * timer will fire and what is in writeout_period_time will be + * roughly the same. + */ + writeout_period_time = wp_next_time(jiffies); + mod_timer(&writeout_period_timer, writeout_period_time); + } } void bdi_writeout_inc(struct backing_dev_info *bdi) @@ -431,10 +437,32 @@ EXPORT_SYMBOL_GPL(bdi_writeout_inc); static void bdi_writeout_fraction(struct backing_dev_info *bdi, long *numerator, long *denominator) { - prop_fraction_percpu(&vm_completions, &bdi->completions, + fprop_fraction_percpu(&writeout_completions, &bdi->completions, numerator, denominator); } +/* + * On idle system, we can be called long after we scheduled because we use + * deferred timers so count with missed periods. + */ +static void writeout_period(unsigned long t) +{ + int miss_periods = (jiffies - writeout_period_time) / + VM_COMPLETIONS_PERIOD_LEN; + + if (fprop_new_period(&writeout_completions, miss_periods + 1)) { + writeout_period_time = wp_next_time(writeout_period_time + + miss_periods * VM_COMPLETIONS_PERIOD_LEN); + mod_timer(&writeout_period_timer, writeout_period_time); + } else { + /* + * Aging has zeroed all fractions. Stop wasting CPU on period + * updates. + */ + writeout_period_time = 0; + } +} + /* * bdi_min_ratio keeps the sum of the minimum dirty shares of all * registered backing devices, which, for obvious reasons, can not @@ -475,7 +503,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio) ret = -EINVAL; } else { bdi->max_ratio = max_ratio; - bdi->max_prop_frac = (PROP_FRAC_BASE * max_ratio) / 100; + bdi->max_prop_frac = (FPROP_FRAC_BASE * max_ratio) / 100; } spin_unlock_bh(&bdi_lock); @@ -1606,13 +1634,10 @@ static struct notifier_block __cpuinitdata ratelimit_nb = { */ void __init page_writeback_init(void) { - int shift; - writeback_set_ratelimit(); register_cpu_notifier(&ratelimit_nb); - shift = calc_period_shift(); - prop_descriptor_init(&vm_completions, shift); + fprop_global_init(&writeout_completions); } /** -- GitLab From 7d116684945459e98538c797dca37c54ddd89906 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 10:21:16 +0800 Subject: [PATCH 0394/5711] ASoC: wm8903: Convert to devm_regmap_init_i2c() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 304b5cff3482..3abd450842ee 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2124,7 +2124,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, return -ENOMEM; wm8903->dev = &i2c->dev; - wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); + wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); if (IS_ERR(wm8903->regmap)) { ret = PTR_ERR(wm8903->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", @@ -2191,7 +2191,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, return 0; err: - regmap_exit(wm8903->regmap); return ret; } @@ -2200,7 +2199,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) struct wm8903_priv *wm8903 = i2c_get_clientdata(client); wm8903_free_gpio(wm8903); - regmap_exit(wm8903->regmap); snd_soc_unregister_codec(&client->dev); return 0; -- GitLab From 8cb28fd6d1e98fe4cf232d7803093a3b7b46e969 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 11:57:50 +0800 Subject: [PATCH 0395/5711] ASoC: wm8904: Convert to module_i2c_driver() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index db94d10b5c1a..02bc2caac83a 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2313,23 +2313,7 @@ static struct i2c_driver wm8904_i2c_driver = { .id_table = wm8904_i2c_id, }; -static int __init wm8904_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8904_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8904_modinit); - -static void __exit wm8904_exit(void) -{ - i2c_del_driver(&wm8904_i2c_driver); -} -module_exit(wm8904_exit); +module_i2c_driver(wm8904_i2c_driver); MODULE_DESCRIPTION("ASoC WM8904 driver"); MODULE_AUTHOR("Mark Brown "); -- GitLab From d633edd95dc938f3f5f0d4e431932f4ca042bffb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 11:26:01 +0800 Subject: [PATCH 0396/5711] ASoC: wm8904: Convert to devm_regmap_init_i2c() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 02bc2caac83a..560a9a47596b 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2263,7 +2263,7 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, if (wm8904 == NULL) return -ENOMEM; - wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap); + wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap); if (IS_ERR(wm8904->regmap)) { ret = PTR_ERR(wm8904->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", @@ -2283,15 +2283,12 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, return 0; err: - regmap_exit(wm8904->regmap); return ret; } static __devexit int wm8904_i2c_remove(struct i2c_client *client) { - struct wm8904_priv *wm8904 = i2c_get_clientdata(client); snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8904->regmap); return 0; } -- GitLab From 331cbdeedeb2f4ef01ccb761513708af0fe77098 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Sat, 9 Jun 2012 11:10:55 +0800 Subject: [PATCH 0397/5711] writeback: Fix some comment errors Signed-off-by: Wanpeng Li Signed-off-by: Fengguang Wu --- fs/fs-writeback.c | 4 ++-- fs/super.c | 2 +- fs/sync.c | 2 +- mm/page-writeback.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 41a3ccff18d8..0b2c87e08e90 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -628,8 +628,8 @@ static long writeback_sb_inodes(struct super_block *sb, } /* - * Don't bother with new inodes or inodes beeing freed, first - * kind does not need peridic writeout yet, and for the latter + * Don't bother with new inodes or inodes being freed, first + * kind does not need periodic writeout yet, and for the latter * kind writeout is handled by the freer. */ spin_lock(&inode->i_lock); diff --git a/fs/super.c b/fs/super.c index cf001775617f..3d65443aea8c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -318,7 +318,7 @@ static int grab_super(struct super_block *s) __releases(sb_lock) /* * grab_super_passive - acquire a passive reference - * @s: reference we are trying to grab + * @sb: reference we are trying to grab * * Tries to acquire a passive reference. This is used in places where we * cannot take an active reference but we need to ensure that the diff --git a/fs/sync.c b/fs/sync.c index 11e3d1c44901..1830704df071 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -92,7 +92,7 @@ static void sync_filesystems(int wait) } /* - * sync everything. Start out by waking pdflush, because that writes back + * sync everything. Start out by waking flusher, because that writes back * all queues in parallel. */ SYSCALL_DEFINE0(sync) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index ec14419e53b5..e5363f34e025 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -946,7 +946,7 @@ static void bdi_update_dirty_ratelimit(struct backing_dev_info *bdi, * bdi->dirty_ratelimit = balanced_dirty_ratelimit; * * However to get a more stable dirty_ratelimit, the below elaborated - * code makes use of task_ratelimit to filter out sigular points and + * code makes use of task_ratelimit to filter out singular points and * limit the step size. * * The below code essentially only uses the relative value of @@ -969,7 +969,7 @@ static void bdi_update_dirty_ratelimit(struct backing_dev_info *bdi, * feel and care are stable dirty rate and small position error. * * |task_ratelimit - dirty_ratelimit| is used to limit the step size - * and filter out the sigular points of balanced_dirty_ratelimit. Which + * and filter out the singular points of balanced_dirty_ratelimit. Which * keeps jumping around randomly and can even leap far away at times * due to the small 200ms estimation period of dirty_rate (we want to * keep that period small to reduce time lags). -- GitLab From 7d3da090cdcf400178b81f851c3721e2bbb9fce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 11:10:17 +0200 Subject: [PATCH 0398/5711] Staging: ipack/bridges/tpci200: remove gotos in tpci200_free_irq(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle error conditions with simple returns instead of usig gotos. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index c39499a81f6c..68bcc557cb47 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -512,24 +512,19 @@ static void __tpci200_free_irq(struct tpci200_board *tpci200, static int tpci200_free_irq(struct ipack_device *dev) { - int res; struct slot_irq *slot_irq; struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; if (tpci200->slots[dev->slot].irq == NULL) { - res = -EINVAL; - goto out_unlock; + mutex_unlock(&tpci200->mutex); + return -EINVAL; } __tpci200_free_irq(tpci200, dev); @@ -537,10 +532,8 @@ static int tpci200_free_irq(struct ipack_device *dev) tpci200->slots[dev->slot].irq = NULL; kfree(slot_irq); -out_unlock: mutex_unlock(&tpci200->mutex); -out: - return res; + return 0; } static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) -- GitLab From 5e4be523981c7e63873b0321dee51bd94226fc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:51 +0200 Subject: [PATCH 0399/5711] Staging: ipack/bridges/tpci200: remove "out" label in tpci200_slot_map_space() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the "out" label from tpci200_slot_map_space(), as it can directly return the error code instead of jumping. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 68bcc557cb47..7baa28a0caad 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -626,15 +626,11 @@ static int tpci200_slot_map_space(struct ipack_device *dev, struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; switch (space) { case IPACK_IO_SPACE: @@ -699,7 +695,6 @@ static int tpci200_slot_map_space(struct ipack_device *dev, out_unlock: mutex_unlock(&tpci200->mutex); -out: return res; } -- GitLab From 14d9f9a3e1f9a962f5cc480dcf2ee72fb16031be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:52 +0200 Subject: [PATCH 0400/5711] Staging: ipack/bridges/tpci200: remove useless break in tpci200_slot_map_space() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 7baa28a0caad..f354b38b7fc6 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -686,7 +686,6 @@ static int tpci200_slot_map_space(struct ipack_device *dev, tpci200->number, dev->slot, space); res = -EINVAL; goto out_unlock; - break; } virt_addr_space->size = size_to_map; -- GitLab From f7986a9e7341e8f4c69cc36a60e1f778a01471ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:53 +0200 Subject: [PATCH 0401/5711] Staging: ipack/bridges/tpci200: remove "out" label in tpci200_request_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the "out" label from tpci200_request_irq(), as it can directly return the error code instead of jumping. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index f354b38b7fc6..7616c4928c96 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -705,15 +705,11 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; if (tpci200->slots[dev->slot].irq != NULL) { dev_err(&dev->dev, @@ -747,7 +743,6 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, out_unlock: mutex_unlock(&tpci200->mutex); -out: return res; } -- GitLab From ec0ceb9e42ca9d7c65c1cbea585d8f5d61db7b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:54 +0200 Subject: [PATCH 0402/5711] Staging: ipack/bridges/tpci200: remove gotos in tpci200_install() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the gotos when handling error conditions, as the code gets clearer and the gotos are not really avoiding code replication. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index 7616c4928c96..e692f1e13aa5 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -777,23 +777,18 @@ static int tpci200_install(struct tpci200_board *tpci200) tpci200->slots = kzalloc( TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL); - if (tpci200->slots == NULL) { - res = -ENOMEM; - goto out_err; - } + if (tpci200->slots == NULL) + return -ENOMEM; res = tpci200_register(tpci200); - if (res) - goto out_free; + if (res) { + kfree(tpci200->slots); + tpci200->slots = NULL; + return res; + } mutex_init(&tpci200->mutex); return 0; - -out_free: - kfree(tpci200->slots); - tpci200->slots = NULL; -out_err: - return res; } static int tpci200_pciprobe(struct pci_dev *pdev, -- GitLab From 8ae7012d3ed3314cc1bf52bd6c51eaa4cc1609a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:55 +0200 Subject: [PATCH 0403/5711] Staging: ipack/devices/ipoctal: remove ipoctal_config structure. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The configuration of the communication channel is handled by the tty abstraction, so the ipoctal_config structure has become useless and it's only used to store values that are never accesed. Remove it. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.c | 11 ----------- drivers/staging/ipack/devices/ipoctal.h | 17 ----------------- 2 files changed, 28 deletions(-) diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index 17aa35a9de63..ff88800ab05b 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -49,7 +49,6 @@ struct ipoctal { char *buffer[NR_CHANNELS]; unsigned int nb_bytes[NR_CHANNELS]; unsigned int count_wr[NR_CHANNELS]; - struct ipoctal_config chan_config[NR_CHANNELS]; wait_queue_head_t queue[NR_CHANNELS]; unsigned short error_flag[NR_CHANNELS]; spinlock_t lock[NR_CHANNELS]; @@ -671,22 +670,18 @@ static void ipoctal_set_termios(struct tty_struct *tty, if (cflag & CRTSCTS) { mr1 |= MR1_RxRTS_CONTROL_ON; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; - ipoctal->chan_config[channel].flow_control = 1; } else { mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; } break; case IP_OCTAL_422_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; break; case IP_OCTAL_485_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; break; default: return; @@ -750,12 +745,6 @@ static void ipoctal_set_termios(struct tty_struct *tty, ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr2); ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.csr, csr); - /* save the setup in the structure */ - ipoctal->chan_config[channel].baud = tty_get_baud_rate(tty); - ipoctal->chan_config[channel].bits_per_char = cflag & CSIZE; - ipoctal->chan_config[channel].parity = cflag & PARENB; - ipoctal->chan_config[channel].stop_bits = cflag & CSTOPB; - /* Enable again the RX */ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, CR_ENABLE_RX); diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h index 266f3617069d..b3c901cf6d14 100644 --- a/drivers/staging/ipack/devices/ipoctal.h +++ b/drivers/staging/ipack/devices/ipoctal.h @@ -41,23 +41,6 @@ enum uart_error { UART_BREAK = 1 << 4, /* Received break */ }; -/** - * struct ipoctal_config - Serial configuration - * - * @baud: Baud rate - * @stop_bits: Stop bits (1 or 2) - * @bits_per_char: data size in bits - * @parity - * @flow_control: Flow control management (RTS/CTS) (0 disabled, 1 enabled) - */ -struct ipoctal_config { - unsigned int baud; - unsigned int stop_bits; - unsigned int bits_per_char; - unsigned short parity; - unsigned int flow_control; -}; - /** * struct ipoctal_stats -- Stats since last reset * -- GitLab From c15768bb0c346767eb54e01a7e772041f36eb65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:56 +0200 Subject: [PATCH 0404/5711] Staging: ipack/devices/ipoctal: remove error_flag field from ipoctal struct. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the error_flag field from the ipoctal structure, as the error code is handled through the tty abstraction. Remove the values definition as well. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.c | 8 -------- drivers/staging/ipack/devices/ipoctal.h | 13 ------------- 2 files changed, 21 deletions(-) diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index ff88800ab05b..29214677ea0c 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -50,7 +50,6 @@ struct ipoctal { unsigned int nb_bytes[NR_CHANNELS]; unsigned int count_wr[NR_CHANNELS]; wait_queue_head_t queue[NR_CHANNELS]; - unsigned short error_flag[NR_CHANNELS]; spinlock_t lock[NR_CHANNELS]; unsigned int pointer_read[NR_CHANNELS]; unsigned int pointer_write[NR_CHANNELS]; @@ -275,23 +274,19 @@ static int ipoctal_irq_handler(void *arg) CR_CMD_RESET_ERR_STATUS); if (sr & SR_OVERRUN_ERROR) { - ipoctal->error_flag[channel] |= UART_OVERRUN; ipoctal->chan_stats[channel].overrun_err++; /* Overrun doesn't affect the current character*/ tty_insert_flip_char(tty, 0, TTY_OVERRUN); } if (sr & SR_PARITY_ERROR) { - ipoctal->error_flag[channel] |= UART_PARITY; ipoctal->chan_stats[channel].parity_err++; flag = TTY_PARITY; } if (sr & SR_FRAMING_ERROR) { - ipoctal->error_flag[channel] |= UART_FRAMING; ipoctal->chan_stats[channel].framing_err++; flag = TTY_FRAME; } if (sr & SR_RECEIVED_BREAK) { - ipoctal->error_flag[channel] |= UART_BREAK; ipoctal->chan_stats[channel].rcv_break++; flag = TTY_BREAK; } @@ -493,7 +488,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal_reset_stats(&ipoctal->chan_stats[i]); ipoctal->nb_bytes[i] = 0; init_waitqueue_head(&ipoctal->queue[i]); - ipoctal->error_flag[i] = UART_NOERROR; spin_lock_init(&ipoctal->lock[i]); ipoctal->pointer_read[i] = 0; @@ -552,8 +546,6 @@ static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel, ipoctal_copy_write_buffer(ipoctal, channel, buf, count); - ipoctal->error_flag[channel] = UART_NOERROR; - /* As the IP-OCTAL 485 only supports half duplex, do it manually */ if (ipoctal->board_id == IP_OCTAL_485_ID) { ipoctal_write_io_reg(ipoctal, diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h index b3c901cf6d14..2aae170de613 100644 --- a/drivers/staging/ipack/devices/ipoctal.h +++ b/drivers/staging/ipack/devices/ipoctal.h @@ -28,19 +28,6 @@ enum uart_parity_e { UART_EVEN = 2, }; -/** - * enum uart_error - UART error type - * - */ -enum uart_error { - UART_NOERROR = 0, /* No error during transmission */ - UART_TIMEOUT = 1 << 0, /* Timeout error */ - UART_OVERRUN = 1 << 1, /* Overrun error */ - UART_PARITY = 1 << 2, /* Parity error */ - UART_FRAMING = 1 << 3, /* Framing error */ - UART_BREAK = 1 << 4, /* Received break */ -}; - /** * struct ipoctal_stats -- Stats since last reset * -- GitLab From 1be9bbddde32a0c414dd65220ca86f808aaeec5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:57 +0200 Subject: [PATCH 0405/5711] Staging: ipack/devices/ipoctal: remove unused enum uart_parity_e. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h index 2aae170de613..c5b4ed46516f 100644 --- a/drivers/staging/ipack/devices/ipoctal.h +++ b/drivers/staging/ipack/devices/ipoctal.h @@ -19,15 +19,6 @@ #define MAX_DEVICES (NR_CHANNELS * IPOCTAL_MAX_BOARDS) #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) -/** - * enum uart_parity_e - UART supported parity. - */ -enum uart_parity_e { - UART_NONE = 0, - UART_ODD = 1, - UART_EVEN = 2, -}; - /** * struct ipoctal_stats -- Stats since last reset * -- GitLab From 395350370010ab9693085ede5a1c08fb2faeb5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Thu, 7 Jun 2012 10:24:58 +0200 Subject: [PATCH 0406/5711] Staging: ipack/bridges/tpci200: change device table definition and export it. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DEFINE_PCI_DEVICE_TABLE() to create the device table and add MODULE_DEVICE_TABLE() to export it. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index e692f1e13aa5..ae9f803db292 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -871,12 +871,14 @@ static void __devexit tpci200_pci_remove(struct pci_dev *dev) } } -static struct pci_device_id tpci200_idtable[2] = { +static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = { { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID, TPCI200_SUBDEVICE_ID }, { 0, }, }; +MODULE_DEVICE_TABLE(pci, tpci200_idtable); + static struct pci_driver tpci200_pci_drv = { .name = "tpci200", .id_table = tpci200_idtable, -- GitLab From 2bbc89a8e9c652ee71c6c3b2e0679b7ecedb1a09 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 30 May 2012 15:49:59 +0200 Subject: [PATCH 0407/5711] m68k: Use Kbuild logic to import asm-generic headers Replace all headers files that just include their asm-generic version by Kbuild logic Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/Kbuild | 23 +++++++++++++++++++++++ arch/m68k/include/asm/bitsperlong.h | 1 - arch/m68k/include/asm/cputime.h | 6 ------ arch/m68k/include/asm/device.h | 7 ------- arch/m68k/include/asm/emergency-restart.h | 6 ------ arch/m68k/include/asm/errno.h | 6 ------ arch/m68k/include/asm/futex.h | 6 ------ arch/m68k/include/asm/ioctl.h | 1 - arch/m68k/include/asm/ipcbuf.h | 1 - arch/m68k/include/asm/irq_regs.h | 1 - arch/m68k/include/asm/kdebug.h | 1 - arch/m68k/include/asm/kmap_types.h | 6 ------ arch/m68k/include/asm/kvm_para.h | 1 - arch/m68k/include/asm/local.h | 6 ------ arch/m68k/include/asm/local64.h | 1 - arch/m68k/include/asm/mman.h | 1 - arch/m68k/include/asm/mutex.h | 9 --------- arch/m68k/include/asm/percpu.h | 6 ------ arch/m68k/include/asm/resource.h | 6 ------ arch/m68k/include/asm/scatterlist.h | 6 ------ arch/m68k/include/asm/siginfo.h | 6 ------ arch/m68k/include/asm/statfs.h | 6 ------ arch/m68k/include/asm/topology.h | 6 ------ arch/m68k/include/asm/xor.h | 1 - 24 files changed, 23 insertions(+), 97 deletions(-) delete mode 100644 arch/m68k/include/asm/bitsperlong.h delete mode 100644 arch/m68k/include/asm/cputime.h delete mode 100644 arch/m68k/include/asm/device.h delete mode 100644 arch/m68k/include/asm/emergency-restart.h delete mode 100644 arch/m68k/include/asm/errno.h delete mode 100644 arch/m68k/include/asm/futex.h delete mode 100644 arch/m68k/include/asm/ioctl.h delete mode 100644 arch/m68k/include/asm/ipcbuf.h delete mode 100644 arch/m68k/include/asm/irq_regs.h delete mode 100644 arch/m68k/include/asm/kdebug.h delete mode 100644 arch/m68k/include/asm/kmap_types.h delete mode 100644 arch/m68k/include/asm/kvm_para.h delete mode 100644 arch/m68k/include/asm/local.h delete mode 100644 arch/m68k/include/asm/local64.h delete mode 100644 arch/m68k/include/asm/mman.h delete mode 100644 arch/m68k/include/asm/mutex.h delete mode 100644 arch/m68k/include/asm/percpu.h delete mode 100644 arch/m68k/include/asm/resource.h delete mode 100644 arch/m68k/include/asm/scatterlist.h delete mode 100644 arch/m68k/include/asm/siginfo.h delete mode 100644 arch/m68k/include/asm/statfs.h delete mode 100644 arch/m68k/include/asm/topology.h delete mode 100644 arch/m68k/include/asm/xor.h diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index eafa2539a8ee..4d1f8fa33091 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,4 +1,27 @@ include include/asm-generic/Kbuild.asm header-y += cachectl.h +generic-y += bitsperlong.h +generic-y += cputime.h +generic-y += device.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += futex.h +generic-y += ioctl.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += kvm_para.h +generic-y += local64.h +generic-y += local.h +generic-y += mman.h +generic-y += mutex.h +generic-y += percpu.h +generic-y += resource.h +generic-y += scatterlist.h +generic-y += siginfo.h +generic-y += statfs.h +generic-y += topology.h generic-y += word-at-a-time.h +generic-y += xor.h diff --git a/arch/m68k/include/asm/bitsperlong.h b/arch/m68k/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b2..000000000000 --- a/arch/m68k/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/cputime.h b/arch/m68k/include/asm/cputime.h deleted file mode 100644 index c79c5e892305..000000000000 --- a/arch/m68k/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __M68K_CPUTIME_H -#define __M68K_CPUTIME_H - -#include - -#endif /* __M68K_CPUTIME_H */ diff --git a/arch/m68k/include/asm/device.h b/arch/m68k/include/asm/device.h deleted file mode 100644 index d8f9872b0e2d..000000000000 --- a/arch/m68k/include/asm/device.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Arch specific extensions to struct device - * - * This file is released under the GPLv2 - */ -#include - diff --git a/arch/m68k/include/asm/emergency-restart.h b/arch/m68k/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42e..000000000000 --- a/arch/m68k/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/m68k/include/asm/errno.h b/arch/m68k/include/asm/errno.h deleted file mode 100644 index 0d4e188d6ef6..000000000000 --- a/arch/m68k/include/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_ERRNO_H -#define _M68K_ERRNO_H - -#include - -#endif /* _M68K_ERRNO_H */ diff --git a/arch/m68k/include/asm/futex.h b/arch/m68k/include/asm/futex.h deleted file mode 100644 index 6a332a9f099c..000000000000 --- a/arch/m68k/include/asm/futex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#include - -#endif diff --git a/arch/m68k/include/asm/ioctl.h b/arch/m68k/include/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5..000000000000 --- a/arch/m68k/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/ipcbuf.h b/arch/m68k/include/asm/ipcbuf.h deleted file mode 100644 index 84c7e51cb6d0..000000000000 --- a/arch/m68k/include/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/irq_regs.h b/arch/m68k/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b70270..000000000000 --- a/arch/m68k/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/kdebug.h b/arch/m68k/include/asm/kdebug.h deleted file mode 100644 index 6ece1b037665..000000000000 --- a/arch/m68k/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/kmap_types.h b/arch/m68k/include/asm/kmap_types.h deleted file mode 100644 index 3413cc1390ec..000000000000 --- a/arch/m68k/include/asm/kmap_types.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_M68K_KMAP_TYPES_H -#define __ASM_M68K_KMAP_TYPES_H - -#include - -#endif /* __ASM_M68K_KMAP_TYPES_H */ diff --git a/arch/m68k/include/asm/kvm_para.h b/arch/m68k/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b957..000000000000 --- a/arch/m68k/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/local.h b/arch/m68k/include/asm/local.h deleted file mode 100644 index 6c259263e1f0..000000000000 --- a/arch/m68k/include/asm/local.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_M68K_LOCAL_H -#define _ASM_M68K_LOCAL_H - -#include - -#endif /* _ASM_M68K_LOCAL_H */ diff --git a/arch/m68k/include/asm/local64.h b/arch/m68k/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239..000000000000 --- a/arch/m68k/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/mman.h b/arch/m68k/include/asm/mman.h deleted file mode 100644 index 8eebf89f5ab1..000000000000 --- a/arch/m68k/include/asm/mman.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68k/include/asm/mutex.h b/arch/m68k/include/asm/mutex.h deleted file mode 100644 index 458c1f7fbc18..000000000000 --- a/arch/m68k/include/asm/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include diff --git a/arch/m68k/include/asm/percpu.h b/arch/m68k/include/asm/percpu.h deleted file mode 100644 index 0859d048faf5..000000000000 --- a/arch/m68k/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_M68K_PERCPU_H -#define __ASM_M68K_PERCPU_H - -#include - -#endif /* __ASM_M68K_PERCPU_H */ diff --git a/arch/m68k/include/asm/resource.h b/arch/m68k/include/asm/resource.h deleted file mode 100644 index e7d35019f337..000000000000 --- a/arch/m68k/include/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_RESOURCE_H -#define _M68K_RESOURCE_H - -#include - -#endif /* _M68K_RESOURCE_H */ diff --git a/arch/m68k/include/asm/scatterlist.h b/arch/m68k/include/asm/scatterlist.h deleted file mode 100644 index 312505452a1e..000000000000 --- a/arch/m68k/include/asm/scatterlist.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_SCATTERLIST_H -#define _M68K_SCATTERLIST_H - -#include - -#endif /* !(_M68K_SCATTERLIST_H) */ diff --git a/arch/m68k/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo.h deleted file mode 100644 index 851d3d784b53..000000000000 --- a/arch/m68k/include/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_SIGINFO_H -#define _M68K_SIGINFO_H - -#include - -#endif diff --git a/arch/m68k/include/asm/statfs.h b/arch/m68k/include/asm/statfs.h deleted file mode 100644 index 08d93f14e061..000000000000 --- a/arch/m68k/include/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_STATFS_H -#define _M68K_STATFS_H - -#include - -#endif /* _M68K_STATFS_H */ diff --git a/arch/m68k/include/asm/topology.h b/arch/m68k/include/asm/topology.h deleted file mode 100644 index ca173e9f26ff..000000000000 --- a/arch/m68k/include/asm/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_M68K_TOPOLOGY_H -#define _ASM_M68K_TOPOLOGY_H - -#include - -#endif /* _ASM_M68K_TOPOLOGY_H */ diff --git a/arch/m68k/include/asm/xor.h b/arch/m68k/include/asm/xor.h deleted file mode 100644 index c82eb12a5b18..000000000000 --- a/arch/m68k/include/asm/xor.h +++ /dev/null @@ -1 +0,0 @@ -#include -- GitLab From 2ef0d3e64f0ba9aed72c2ddd410aea83cd3261ab Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 30 May 2012 19:50:04 +0200 Subject: [PATCH 0408/5711] m68k: Use asm-generic version of The extra definition for BITS_PER_LONG we had is also indirectly provided by , via and Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/Kbuild | 1 + arch/m68k/include/asm/types.h | 22 ---------------------- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 arch/m68k/include/asm/types.h diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 4d1f8fa33091..064f86743b34 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -23,5 +23,6 @@ generic-y += scatterlist.h generic-y += siginfo.h generic-y += statfs.h generic-y += topology.h +generic-y += types.h generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/m68k/include/asm/types.h b/arch/m68k/include/asm/types.h deleted file mode 100644 index 89705adcbd52..000000000000 --- a/arch/m68k/include/asm/types.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _M68K_TYPES_H -#define _M68K_TYPES_H - -/* - * This file is never included by application software unless - * explicitly requested (e.g., via linux/types.h) in which case the - * application is Linux specific so (user-) name space pollution is - * not a major issue. However, for interoperability, libraries still - * need to be careful to avoid a name clashes. - */ -#include - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - -#define BITS_PER_LONG 32 - -#endif /* __KERNEL__ */ - -#endif /* _M68K_TYPES_H */ -- GitLab From 54503b1da74afdb38c730ad6413dbe54ce119134 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 31 May 2012 21:39:13 +0200 Subject: [PATCH 0409/5711] m68knommu: Clean up printing of sections - Remove casts and unneeded address-of ('&') operators, - Use %p to format pointers, %lx to format unsigned longs. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/kernel/setup_no.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 7dc186b7a85f..8a624ecf86b8 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -218,13 +218,10 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n"); #endif - pr_debug("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " - "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, - (int) &_sdata, (int) &_edata, - (int) &_sbss, (int) &_ebss); - pr_debug("MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ", - (int) &_ebss, (int) memory_start, - (int) memory_start, (int) memory_end); + pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", + _stext, _etext, _sdata, _edata, _sbss, _ebss); + pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", + _ebss, memory_start, memory_start, memory_end); /* Keep a copy of command line */ *cmdline_p = &command_line[0]; -- GitLab From f2378ed90572aeeecded30fd3754575c2ff1e55f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Jun 2012 17:24:47 +0200 Subject: [PATCH 0410/5711] m68k: Remove duplicate FPU config option It's also defined in arch/m68k/Kconfig.cpu Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 147120128260..bc8cc504dee1 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -62,9 +62,6 @@ config CPU_HAS_NO_MULDIV64 config CPU_HAS_ADDRESS_SPACES bool -config FPU - bool - config HZ int default 1000 if CLEOPATRA -- GitLab From 022613e0b0753f1261454dea9b07c2e959363af7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Jun 2012 17:26:35 +0200 Subject: [PATCH 0411/5711] m68k: Move CPU_HAS_* config options They belong together with the CPU selection Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/Kconfig | 9 --------- arch/m68k/Kconfig.cpu | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index bc8cc504dee1..87b504cfe001 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -53,15 +53,6 @@ config ZONE_DMA bool default y -config CPU_HAS_NO_BITFIELDS - bool - -config CPU_HAS_NO_MULDIV64 - bool - -config CPU_HAS_ADDRESS_SPACES - bool - config HZ int default 1000 if CLEOPATRA diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 2b53254ad994..6cd8c1a32893 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -360,6 +360,15 @@ config NODES_SHIFT default "3" depends on !SINGLE_MEMORY_CHUNK +config CPU_HAS_NO_BITFIELDS + bool + +config CPU_HAS_NO_MULDIV64 + bool + +config CPU_HAS_ADDRESS_SPACES + bool + config FPU bool -- GitLab From 5df58f3aac58bb0f08fa205a006c6b7840cd7ac4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Jun 2012 18:35:13 +0200 Subject: [PATCH 0412/5711] m68k: delay, muldi3 - Use CONFIG_CPU_HAS_NO_MULDIV64 instead of open coding CONFIG_M68000 || CONFIG_COLDFIRE Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/include/asm/delay.h | 2 +- arch/m68k/lib/muldi3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h index 9c09becfd4c9..12d8fe4f1d30 100644 --- a/arch/m68k/include/asm/delay.h +++ b/arch/m68k/include/asm/delay.h @@ -43,7 +43,7 @@ static inline void __delay(unsigned long loops) extern void __bad_udelay(void); -#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +#ifdef CONFIG_CPU_HAS_NO_MULDIV64 /* * The simpler m68k and ColdFire processors do not have a 32*32->64 * multiply instruction. So we need to handle them a little differently. diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index 79e928a525d0..ee5f0b1b5c5d 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -19,7 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +#ifdef CONFIG_CPU_HAS_NO_MULDIV64 #define SI_TYPE_SIZE 32 #define __BITS4 (SI_TYPE_SIZE / 4) -- GitLab From 9f1f118035b2d28bb741844537b9ee87705b4c6e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Jun 2012 19:37:52 +0200 Subject: [PATCH 0413/5711] m68k: Introduce config option CPU_HAS_NO_UNALIGNED Use CONFIG_CPU_HAS_NO_UNALIGNED instead of open coding CONFIG_M68000 || CONFIG_COLDFIRE Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/Kconfig.cpu | 5 +++++ arch/m68k/include/asm/unaligned.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 6cd8c1a32893..c4ed65081475 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -27,6 +27,7 @@ config COLDFIRE select ARCH_HAVE_CUSTOM_GPIO_H select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 + select CPU_HAS_NO_UNALIGNED select GENERIC_CSUM endchoice @@ -37,6 +38,7 @@ config M68000 bool select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 + select CPU_HAS_NO_UNALIGNED select GENERIC_CSUM help The Freescale (was Motorola) 68000 CPU is the first generation of @@ -366,6 +368,9 @@ config CPU_HAS_NO_BITFIELDS config CPU_HAS_NO_MULDIV64 bool +config CPU_HAS_NO_UNALIGNED + bool + config CPU_HAS_ADDRESS_SPACES bool diff --git a/arch/m68k/include/asm/unaligned.h b/arch/m68k/include/asm/unaligned.h index f4043ae63db1..2b3ca0bf7a0d 100644 --- a/arch/m68k/include/asm/unaligned.h +++ b/arch/m68k/include/asm/unaligned.h @@ -2,7 +2,7 @@ #define _ASM_M68K_UNALIGNED_H -#if defined(CONFIG_COLDFIRE) || defined(CONFIG_M68000) +#ifdef CONFIG_CPU_HAS_NO_UNALIGNED #include #include #include @@ -12,7 +12,7 @@ #else /* - * The m68k can do unaligned accesses itself. + * The m68k can do unaligned accesses itself. */ #include #include -- GitLab From 7df0d27f3d78282e9ab97da060e85f53a5f556b5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Jun 2012 19:39:39 +0200 Subject: [PATCH 0414/5711] m68k: CPU32 does not support unaligned accesses Hence select CPU_HAS_NO_UNALIGNED Reported-by: Philippe De Muyter Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/Kconfig.cpu | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index c4ed65081475..d4f3a9839cff 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -50,6 +50,7 @@ config M68000 config MCPU32 bool select CPU_HAS_NO_BITFIELDS + select CPU_HAS_NO_UNALIGNED help The Freescale (was then Motorola) CPU32 is a CPU core that is based on the 68020 processor. For the most part it is used in -- GitLab From 679d7abdc7543e56abc41b8f4858f31a91259b29 Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 7 Jun 2012 14:00:21 +0200 Subject: [PATCH 0415/5711] ASoC: codecs: Add AB8500 codec-driver Add codec-driver for ST-Ericsson AB8500 mixed-signal ASIC. Signed-off-by: Ola Lilja Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ab8500-codec.c | 2521 +++++++++++++++++++++++++++++++ sound/soc/codecs/ab8500-codec.h | 590 ++++++++ 4 files changed, 3117 insertions(+) create mode 100644 sound/soc/codecs/ab8500-codec.c create mode 100644 sound/soc/codecs/ab8500-codec.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8b879c71c23c..f63776d422b3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" select SND_SOC_88PM860X if MFD_88PM860X select SND_SOC_L3 + select SND_SOC_AB8500_CODEC if ABX500_CORE select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI @@ -132,6 +133,9 @@ config SND_SOC_WM_HUBS default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m +config SND_SOC_AB8500_CODEC + tristate + config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e50811b182a4..fc93b4b0c2c5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,4 +1,5 @@ snd-soc-88pm860x-objs := 88pm860x-codec.o +snd-soc-ab8500-codec-objs := ab8500-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o @@ -109,6 +110,7 @@ snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o +obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c new file mode 100644 index 000000000000..95dc7d5bb076 --- /dev/null +++ b/sound/soc/codecs/ab8500-codec.c @@ -0,0 +1,2521 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja , + * Kristoffer Karlsson , + * Roger Nilsson , + * for ST-Ericsson. + * + * Based on the early work done by: + * Mikko J. Lehto , + * Mikko Sarmanne , + * Jarmo K. Kuronen , + * for ST-Ericsson. + * + * License terms: + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "ab8500-codec.h" + +/* Macrocell value definitions */ +#define CLK_32K_OUT2_DISABLE 0x01 +#define INACTIVE_RESET_AUDIO 0x02 +#define ENABLE_AUDIO_CLK_TO_AUDIO_BLK 0x10 +#define ENABLE_VINTCORE12_SUPPLY 0x04 +#define GPIO27_DIR_OUTPUT 0x04 +#define GPIO29_DIR_OUTPUT 0x10 +#define GPIO31_DIR_OUTPUT 0x40 + +/* Macrocell register definitions */ +#define AB8500_CTRL3_REG 0x0200 +#define AB8500_GPIO_DIR4_REG 0x1013 + +/* Nr of FIR/IIR-coeff banks in ANC-block */ +#define AB8500_NR_OF_ANC_COEFF_BANKS 2 + +/* Minimum duration to keep ANC IIR Init bit high or +low before proceeding with the configuration sequence */ +#define AB8500_ANC_SM_DELAY 2000 + +#define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = filter_control_info, \ + .get = filter_control_get, .put = filter_control_put, \ + .private_value = (unsigned long)&(struct filter_control) \ + {.count = xcount, .min = xmin, .max = xmax} } + +struct filter_control { + long min, max; + unsigned int count; + long value[128]; +}; + +/* Sidetone states */ +static const char * const enum_sid_state[] = { + "Unconfigured", + "Apply FIR", + "FIR is configured", +}; +enum sid_state { + SID_UNCONFIGURED = 0, + SID_APPLY_FIR = 1, + SID_FIR_CONFIGURED = 2, +}; + +static const char * const enum_anc_state[] = { + "Unconfigured", + "Apply FIR and IIR", + "FIR and IIR are configured", + "Apply FIR", + "FIR is configured", + "Apply IIR", + "IIR is configured" +}; +enum anc_state { + ANC_UNCONFIGURED = 0, + ANC_APPLY_FIR_IIR = 1, + ANC_FIR_IIR_CONFIGURED = 2, + ANC_APPLY_FIR = 3, + ANC_FIR_CONFIGURED = 4, + ANC_APPLY_IIR = 5, + ANC_IIR_CONFIGURED = 6 +}; + +/* Analog microphones */ +enum amic_idx { + AMIC_IDX_1A, + AMIC_IDX_1B, + AMIC_IDX_2 +}; + +struct ab8500_codec_drvdata_dbg { + struct regulator *vaud; + struct regulator *vamic1; + struct regulator *vamic2; + struct regulator *vdmic; +}; + +/* Private data for AB8500 device-driver */ +struct ab8500_codec_drvdata { + /* Sidetone */ + long *sid_fir_values; + enum sid_state sid_status; + + /* ANC */ + struct mutex anc_lock; + long *anc_fir_values; + long *anc_iir_values; + enum anc_state anc_status; +}; + +static inline const char *amic_micbias_str(enum amic_micbias micbias) +{ + switch (micbias) { + case AMIC_MICBIAS_VAMIC1: + return "VAMIC1"; + case AMIC_MICBIAS_VAMIC2: + return "VAMIC2"; + default: + return "Unknown"; + } +} + +static inline const char *amic_type_str(enum amic_type type) +{ + switch (type) { + case AMIC_TYPE_DIFFERENTIAL: + return "DIFFERENTIAL"; + case AMIC_TYPE_SINGLE_ENDED: + return "SINGLE ENDED"; + default: + return "Unknown"; + } +} + +/* + * Read'n'write functions + */ + +/* Read a register from the audio-bank of AB8500 */ +static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec, + unsigned int reg) +{ + int status; + unsigned int value = 0; + + u8 value8; + status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO, + reg, &value8); + if (status < 0) { + dev_err(codec->dev, + "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n", + __func__, (u8)AB8500_AUDIO, (u8)reg, status); + } else { + dev_dbg(codec->dev, + "%s: Read 0x%02x from register 0x%02x:0x%02x\n", + __func__, value8, (u8)AB8500_AUDIO, (u8)reg); + value = (unsigned int)value8; + } + + return value; +} + +/* Write to a register in the audio-bank of AB8500 */ +static int ab8500_codec_write_reg(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + int status; + + status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO, + reg, value); + if (status < 0) + dev_err(codec->dev, + "%s: ERROR: Register (%02x:%02x) write failed (%d).\n", + __func__, (u8)AB8500_AUDIO, (u8)reg, status); + else + dev_dbg(codec->dev, + "%s: Wrote 0x%02x into register %02x:%02x\n", + __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg); + + return status; +} + +/* + * Controls - DAPM + */ + +/* Earpiece */ + +/* Earpiece source selector */ +static const char * const enum_ear_lineout_source[] = {"Headset Left", + "Speaker Left"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ear_lineout_source, AB8500_DMICFILTCONF, + AB8500_DMICFILTCONF_DA3TOEAR, enum_ear_lineout_source); +static const struct snd_kcontrol_new dapm_ear_lineout_source = + SOC_DAPM_ENUM("Earpiece or LineOut Mono Source", + dapm_enum_ear_lineout_source); + +/* LineOut */ + +/* LineOut source selector */ +static const char * const enum_lineout_source[] = {"Mono Path", "Stereo Path"}; +static SOC_ENUM_DOUBLE_DECL(dapm_enum_lineout_source, AB8500_ANACONF5, + AB8500_ANACONF5_HSLDACTOLOL, + AB8500_ANACONF5_HSRDACTOLOR, enum_lineout_source); +static const struct snd_kcontrol_new dapm_lineout_source[] = { + SOC_DAPM_ENUM("LineOut Source", dapm_enum_lineout_source), +}; + +/* Handsfree */ + +/* Speaker Left - ANC selector */ +static const char * const enum_HFx_sel[] = {"Audio Path", "ANC"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_HFl_sel, AB8500_DIGMULTCONF2, + AB8500_DIGMULTCONF2_HFLSEL, enum_HFx_sel); +static const struct snd_kcontrol_new dapm_HFl_select[] = { + SOC_DAPM_ENUM("Speaker Left Source", dapm_enum_HFl_sel), +}; + +/* Speaker Right - ANC selector */ +static SOC_ENUM_SINGLE_DECL(dapm_enum_HFr_sel, AB8500_DIGMULTCONF2, + AB8500_DIGMULTCONF2_HFRSEL, enum_HFx_sel); +static const struct snd_kcontrol_new dapm_HFr_select[] = { + SOC_DAPM_ENUM("Speaker Right Source", dapm_enum_HFr_sel), +}; + +/* Mic 1 */ + +/* Mic 1 - Mic 1a or 1b selector */ +static const char * const enum_mic1ab_sel[] = {"Mic 1b", "Mic 1a"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_mic1ab_sel, AB8500_ANACONF3, + AB8500_ANACONF3_MIC1SEL, enum_mic1ab_sel); +static const struct snd_kcontrol_new dapm_mic1ab_mux[] = { + SOC_DAPM_ENUM("Mic 1a or 1b Select", dapm_enum_mic1ab_sel), +}; + +/* Mic 1 - AD3 - Mic 1 or DMic 3 selector */ +static const char * const enum_ad3_sel[] = {"Mic 1", "DMic 3"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad3_sel, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_AD3SEL, enum_ad3_sel); +static const struct snd_kcontrol_new dapm_ad3_select[] = { + SOC_DAPM_ENUM("AD3 Source Select", dapm_enum_ad3_sel), +}; + +/* Mic 1 - AD6 - Mic 1 or DMic 6 selector */ +static const char * const enum_ad6_sel[] = {"Mic 1", "DMic 6"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad6_sel, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_AD6SEL, enum_ad6_sel); +static const struct snd_kcontrol_new dapm_ad6_select[] = { + SOC_DAPM_ENUM("AD6 Source Select", dapm_enum_ad6_sel), +}; + +/* Mic 2 */ + +/* Mic 2 - AD5 - Mic 2 or DMic 5 selector */ +static const char * const enum_ad5_sel[] = {"Mic 2", "DMic 5"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad5_sel, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_AD5SEL, enum_ad5_sel); +static const struct snd_kcontrol_new dapm_ad5_select[] = { + SOC_DAPM_ENUM("AD5 Source Select", dapm_enum_ad5_sel), +}; + +/* LineIn */ + +/* LineIn left - AD1 - LineIn Left or DMic 1 selector */ +static const char * const enum_ad1_sel[] = {"LineIn Left", "DMic 1"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad1_sel, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_AD1SEL, enum_ad1_sel); +static const struct snd_kcontrol_new dapm_ad1_select[] = { + SOC_DAPM_ENUM("AD1 Source Select", dapm_enum_ad1_sel), +}; + +/* LineIn right - Mic 2 or LineIn Right selector */ +static const char * const enum_mic2lr_sel[] = {"Mic 2", "LineIn Right"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_mic2lr_sel, AB8500_ANACONF3, + AB8500_ANACONF3_LINRSEL, enum_mic2lr_sel); +static const struct snd_kcontrol_new dapm_mic2lr_select[] = { + SOC_DAPM_ENUM("Mic 2 or LINR Select", dapm_enum_mic2lr_sel), +}; + +/* LineIn right - AD2 - LineIn Right or DMic2 selector */ +static const char * const enum_ad2_sel[] = {"LineIn Right", "DMic 2"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad2_sel, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_AD2SEL, enum_ad2_sel); +static const struct snd_kcontrol_new dapm_ad2_select[] = { + SOC_DAPM_ENUM("AD2 Source Select", dapm_enum_ad2_sel), +}; + + +/* ANC */ + +static const char * const enum_anc_in_sel[] = {"Mic 1 / DMic 6", + "Mic 2 / DMic 5"}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_in_sel, AB8500_DMICFILTCONF, + AB8500_DMICFILTCONF_ANCINSEL, enum_anc_in_sel); +static const struct snd_kcontrol_new dapm_anc_in_select[] = { + SOC_DAPM_ENUM("ANC Source", dapm_enum_anc_in_sel), +}; + +/* ANC - Enable/Disable */ +static const struct snd_kcontrol_new dapm_anc_enable[] = { + SOC_DAPM_SINGLE("Switch", AB8500_ANCCONF1, + AB8500_ANCCONF1_ENANC, 0, 0), +}; + +/* ANC to Earpiece - Mute */ +static const struct snd_kcontrol_new dapm_anc_ear_mute[] = { + SOC_DAPM_SINGLE("Switch", AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_ANCSEL, 1, 0), +}; + + + +/* Sidetone left */ + +/* Sidetone left - Input selector */ +static const char * const enum_stfir1_in_sel[] = { + "LineIn Left", "LineIn Right", "Mic 1", "Headset Left" +}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir1_in_sel, AB8500_DIGMULTCONF2, + AB8500_DIGMULTCONF2_FIRSID1SEL, enum_stfir1_in_sel); +static const struct snd_kcontrol_new dapm_stfir1_in_select[] = { + SOC_DAPM_ENUM("Sidetone Left Source", dapm_enum_stfir1_in_sel), +}; + +/* Sidetone right path */ + +/* Sidetone right - Input selector */ +static const char * const enum_stfir2_in_sel[] = { + "LineIn Right", "Mic 1", "DMic 4", "Headset Right" +}; +static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir2_in_sel, AB8500_DIGMULTCONF2, + AB8500_DIGMULTCONF2_FIRSID2SEL, enum_stfir2_in_sel); +static const struct snd_kcontrol_new dapm_stfir2_in_select[] = { + SOC_DAPM_ENUM("Sidetone Right Source", dapm_enum_stfir2_in_sel), +}; + +/* Vibra */ + +static const char * const enum_pwm2vibx[] = {"Audio Path", "PWM Generator"}; + +static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib1, AB8500_PWMGENCONF1, + AB8500_PWMGENCONF1_PWMTOVIB1, enum_pwm2vibx); + +static const struct snd_kcontrol_new dapm_pwm2vib1[] = { + SOC_DAPM_ENUM("Vibra 1 Controller", dapm_enum_pwm2vib1), +}; + +static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib2, AB8500_PWMGENCONF1, + AB8500_PWMGENCONF1_PWMTOVIB2, enum_pwm2vibx); + +static const struct snd_kcontrol_new dapm_pwm2vib2[] = { + SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2), +}; + +/* + * DAPM-widgets + */ + +static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { + + /* Clocks */ + SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), + + /* Regulators */ + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), + + /* Power */ + SND_SOC_DAPM_SUPPLY("Audio Power", + AB8500_POWERUP, AB8500_POWERUP_POWERUP, 0, + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("Audio Analog Power", + AB8500_POWERUP, AB8500_POWERUP_ENANA, 0, + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* Main supply node */ + SND_SOC_DAPM_SUPPLY("Main Supply", SND_SOC_NOPM, 0, 0, + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* DA/AD */ + + SND_SOC_DAPM_INPUT("ADC Input"), + SND_SOC_DAPM_ADC("ADC", "ab8500_0c", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("DAC Output"), + + SND_SOC_DAPM_AIF_IN("DA_IN1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DA_IN2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DA_IN3", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DA_IN4", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DA_IN5", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DA_IN6", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT1", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT2", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT3", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT4", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT57", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AD_OUT68", NULL, 0, SND_SOC_NOPM, 0, 0), + + /* Headset path */ + + SND_SOC_DAPM_SUPPLY("Charge Pump", AB8500_ANACONF5, + AB8500_ANACONF5_ENCPHS, 0, NULL, 0), + + SND_SOC_DAPM_DAC("DA1 Enable", "ab8500_0p", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA1, 0), + SND_SOC_DAPM_DAC("DA2 Enable", "ab8500_0p", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA2, 0), + + SND_SOC_DAPM_PGA("HSL Digital Volume", SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_PGA("HSR Digital Volume", SND_SOC_NOPM, 0, 0, + NULL, 0), + + SND_SOC_DAPM_DAC("HSL DAC", "ab8500_0p", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSL, 0), + SND_SOC_DAPM_DAC("HSR DAC", "ab8500_0p", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSR, 0), + SND_SOC_DAPM_MIXER("HSL DAC Mute", AB8500_MUTECONF, + AB8500_MUTECONF_MUTDACHSL, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("HSR DAC Mute", AB8500_MUTECONF, + AB8500_MUTECONF_MUTDACHSR, 1, + NULL, 0), + SND_SOC_DAPM_DAC("HSL DAC Driver", "ab8500_0p", + AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSL, 0), + SND_SOC_DAPM_DAC("HSR DAC Driver", "ab8500_0p", + AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSR, 0), + + SND_SOC_DAPM_MIXER("HSL Mute", + AB8500_MUTECONF, AB8500_MUTECONF_MUTHSL, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("HSR Mute", + AB8500_MUTECONF, AB8500_MUTECONF_MUTHSR, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("HSL Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENHSL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("HSR Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENHSR, 0, + NULL, 0), + SND_SOC_DAPM_PGA("HSL Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_PGA("HSR Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("Headset Left"), + SND_SOC_DAPM_OUTPUT("Headset Right"), + + /* LineOut path */ + + SND_SOC_DAPM_MUX("LineOut Source", + SND_SOC_NOPM, 0, 0, dapm_lineout_source), + + SND_SOC_DAPM_MIXER("LOL Disable HFL", + AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("LOR Disable HFR", + AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 1, + NULL, 0), + + SND_SOC_DAPM_MIXER("LOL Enable", + AB8500_ANACONF5, AB8500_ANACONF5_ENLOL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("LOR Enable", + AB8500_ANACONF5, AB8500_ANACONF5_ENLOR, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("LineOut Left"), + SND_SOC_DAPM_OUTPUT("LineOut Right"), + + /* Earpiece path */ + + SND_SOC_DAPM_MUX("Earpiece or LineOut Mono Source", + SND_SOC_NOPM, 0, 0, &dapm_ear_lineout_source), + SND_SOC_DAPM_MIXER("EAR DAC", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACEAR, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("EAR Mute", + AB8500_MUTECONF, AB8500_MUTECONF_MUTEAR, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("EAR Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENEAR, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("Earpiece"), + + /* Handsfree path */ + + SND_SOC_DAPM_MIXER("DA3 Channel Volume", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA3, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DA4 Channel Volume", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA4, 0, + NULL, 0), + SND_SOC_DAPM_MUX("Speaker Left Source", + SND_SOC_NOPM, 0, 0, dapm_HFl_select), + SND_SOC_DAPM_MUX("Speaker Right Source", + SND_SOC_NOPM, 0, 0, dapm_HFr_select), + SND_SOC_DAPM_MIXER("HFL DAC", AB8500_DAPATHCONF, + AB8500_DAPATHCONF_ENDACHFL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("HFR DAC", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHFR, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DA4 or ANC path to HfR", + AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFREN, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DA3 or ANC path to HfL", + AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFLEN, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("HFL Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("HFR Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("Speaker Left"), + SND_SOC_DAPM_OUTPUT("Speaker Right"), + + /* Vibrator path */ + + SND_SOC_DAPM_INPUT("PWMGEN1"), + SND_SOC_DAPM_INPUT("PWMGEN2"), + + SND_SOC_DAPM_MIXER("DA5 Channel Volume", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA5, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DA6 Channel Volume", + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA6, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("VIB1 DAC", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB1, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("VIB2 DAC", + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB2, 0, + NULL, 0), + SND_SOC_DAPM_MUX("Vibra 1 Controller", + SND_SOC_NOPM, 0, 0, dapm_pwm2vib1), + SND_SOC_DAPM_MUX("Vibra 2 Controller", + SND_SOC_NOPM, 0, 0, dapm_pwm2vib2), + SND_SOC_DAPM_MIXER("VIB1 Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENVIB1, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("VIB2 Enable", + AB8500_ANACONF4, AB8500_ANACONF4_ENVIB2, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("Vibra 1"), + SND_SOC_DAPM_OUTPUT("Vibra 2"), + + /* Mic 1 */ + + SND_SOC_DAPM_INPUT("Mic 1"), + + SND_SOC_DAPM_MUX("Mic 1a or 1b Select", + SND_SOC_NOPM, 0, 0, dapm_mic1ab_mux), + SND_SOC_DAPM_MIXER("MIC1 Mute", + AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC1, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("MIC1A V-AMICx Enable", + AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("MIC1B V-AMICx Enable", + AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("MIC1 ADC", + AB8500_ANACONF3, AB8500_ANACONF3_ENADCMIC, 0, + NULL, 0), + SND_SOC_DAPM_MUX("AD3 Source Select", + SND_SOC_NOPM, 0, 0, dapm_ad3_select), + SND_SOC_DAPM_MIXER("AD3 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD3 Enable", + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, 0, + NULL, 0), + + /* Mic 2 */ + + SND_SOC_DAPM_INPUT("Mic 2"), + + SND_SOC_DAPM_MIXER("MIC2 Mute", + AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC2, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("MIC2 V-AMICx Enable", AB8500_ANACONF2, + AB8500_ANACONF2_ENMIC2, 0, + NULL, 0), + + /* LineIn */ + + SND_SOC_DAPM_INPUT("LineIn Left"), + SND_SOC_DAPM_INPUT("LineIn Right"), + + SND_SOC_DAPM_MIXER("LINL Mute", + AB8500_ANACONF2, AB8500_ANACONF2_MUTLINL, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("LINR Mute", + AB8500_ANACONF2, AB8500_ANACONF2_MUTLINR, 1, + NULL, 0), + SND_SOC_DAPM_MIXER("LINL Enable", AB8500_ANACONF2, + AB8500_ANACONF2_ENLINL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("LINR Enable", AB8500_ANACONF2, + AB8500_ANACONF2_ENLINR, 0, + NULL, 0), + + /* LineIn Bypass path */ + SND_SOC_DAPM_MIXER("LINL to HSL Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("LINR to HSR Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + + /* LineIn, Mic 2 */ + SND_SOC_DAPM_MUX("Mic 2 or LINR Select", + SND_SOC_NOPM, 0, 0, dapm_mic2lr_select), + SND_SOC_DAPM_MIXER("LINL ADC", AB8500_ANACONF3, + AB8500_ANACONF3_ENADCLINL, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("LINR ADC", AB8500_ANACONF3, + AB8500_ANACONF3_ENADCLINR, 0, + NULL, 0), + SND_SOC_DAPM_MUX("AD1 Source Select", + SND_SOC_NOPM, 0, 0, dapm_ad1_select), + SND_SOC_DAPM_MUX("AD2 Source Select", + SND_SOC_NOPM, 0, 0, dapm_ad2_select), + SND_SOC_DAPM_MIXER("AD1 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD2 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + + SND_SOC_DAPM_MIXER("AD12 Enable", + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD12, 0, + NULL, 0), + + /* HD Capture path */ + + SND_SOC_DAPM_MUX("AD5 Source Select", + SND_SOC_NOPM, 0, 0, dapm_ad5_select), + SND_SOC_DAPM_MUX("AD6 Source Select", + SND_SOC_NOPM, 0, 0, dapm_ad6_select), + SND_SOC_DAPM_MIXER("AD5 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD6 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD57 Enable", + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD68 Enable", + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, + NULL, 0), + + /* Digital Microphone path */ + + SND_SOC_DAPM_INPUT("DMic 1"), + SND_SOC_DAPM_INPUT("DMic 2"), + SND_SOC_DAPM_INPUT("DMic 3"), + SND_SOC_DAPM_INPUT("DMic 4"), + SND_SOC_DAPM_INPUT("DMic 5"), + SND_SOC_DAPM_INPUT("DMic 6"), + + SND_SOC_DAPM_MIXER("DMIC1", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC1, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DMIC2", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC2, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DMIC3", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC3, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DMIC4", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC4, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DMIC5", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC5, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("DMIC6", + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC6, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD4 Channel Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("AD4 Enable", + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, + 0, NULL, 0), + + /* Acoustical Noise Cancellation path */ + + SND_SOC_DAPM_INPUT("ANC Configure Input"), + SND_SOC_DAPM_OUTPUT("ANC Configure Output"), + + SND_SOC_DAPM_MUX("ANC Source", + SND_SOC_NOPM, 0, 0, + dapm_anc_in_select), + SND_SOC_DAPM_SWITCH("ANC", + SND_SOC_NOPM, 0, 0, + dapm_anc_enable), + SND_SOC_DAPM_SWITCH("ANC to Earpiece", + SND_SOC_NOPM, 0, 0, + dapm_anc_ear_mute), + + /* Sidetone Filter path */ + + SND_SOC_DAPM_MUX("Sidetone Left Source", + SND_SOC_NOPM, 0, 0, + dapm_stfir1_in_select), + SND_SOC_DAPM_MUX("Sidetone Right Source", + SND_SOC_NOPM, 0, 0, + dapm_stfir2_in_select), + SND_SOC_DAPM_MIXER("STFIR1 Control", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("STFIR2 Control", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("STFIR1 Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("STFIR2 Volume", + SND_SOC_NOPM, 0, 0, + NULL, 0), +}; + +/* + * DAPM-routes + */ +static const struct snd_soc_dapm_route ab8500_dapm_routes[] = { + /* Power AB8500 audio-block when AD/DA is active */ + {"Main Supply", NULL, "V-AUD"}, + {"Main Supply", NULL, "audioclk"}, + {"Main Supply", NULL, "Audio Power"}, + {"Main Supply", NULL, "Audio Analog Power"}, + + {"DAC", NULL, "ab8500_0p"}, + {"DAC", NULL, "Main Supply"}, + {"ADC", NULL, "ab8500_0c"}, + {"ADC", NULL, "Main Supply"}, + + /* ANC Configure */ + {"ANC Configure Input", NULL, "Main Supply"}, + {"ANC Configure Output", NULL, "ANC Configure Input"}, + + /* AD/DA */ + {"ADC", NULL, "ADC Input"}, + {"DAC Output", NULL, "DAC"}, + + /* Powerup charge pump if DA1/2 is in use */ + + {"DA_IN1", NULL, "ab8500_0p"}, + {"DA_IN1", NULL, "Charge Pump"}, + {"DA_IN2", NULL, "ab8500_0p"}, + {"DA_IN2", NULL, "Charge Pump"}, + + /* Headset path */ + + {"DA1 Enable", NULL, "DA_IN1"}, + {"DA2 Enable", NULL, "DA_IN2"}, + + {"HSL Digital Volume", NULL, "DA1 Enable"}, + {"HSR Digital Volume", NULL, "DA2 Enable"}, + + {"HSL DAC", NULL, "HSL Digital Volume"}, + {"HSR DAC", NULL, "HSR Digital Volume"}, + + {"HSL DAC Mute", NULL, "HSL DAC"}, + {"HSR DAC Mute", NULL, "HSR DAC"}, + + {"HSL DAC Driver", NULL, "HSL DAC Mute"}, + {"HSR DAC Driver", NULL, "HSR DAC Mute"}, + + {"HSL Mute", NULL, "HSL DAC Driver"}, + {"HSR Mute", NULL, "HSR DAC Driver"}, + + {"HSL Enable", NULL, "HSL Mute"}, + {"HSR Enable", NULL, "HSR Mute"}, + + {"HSL Volume", NULL, "HSL Enable"}, + {"HSR Volume", NULL, "HSR Enable"}, + + {"Headset Left", NULL, "HSL Volume"}, + {"Headset Right", NULL, "HSR Volume"}, + + /* HF or LineOut path */ + + {"DA_IN3", NULL, "ab8500_0p"}, + {"DA3 Channel Volume", NULL, "DA_IN3"}, + {"DA_IN4", NULL, "ab8500_0p"}, + {"DA4 Channel Volume", NULL, "DA_IN4"}, + + {"Speaker Left Source", "Audio Path", "DA3 Channel Volume"}, + {"Speaker Right Source", "Audio Path", "DA4 Channel Volume"}, + + {"DA3 or ANC path to HfL", NULL, "Speaker Left Source"}, + {"DA4 or ANC path to HfR", NULL, "Speaker Right Source"}, + + /* HF path */ + + {"HFL DAC", NULL, "DA3 or ANC path to HfL"}, + {"HFR DAC", NULL, "DA4 or ANC path to HfR"}, + + {"HFL Enable", NULL, "HFL DAC"}, + {"HFR Enable", NULL, "HFR DAC"}, + + {"Speaker Left", NULL, "HFL Enable"}, + {"Speaker Right", NULL, "HFR Enable"}, + + /* Earpiece path */ + + {"Earpiece or LineOut Mono Source", "Headset Left", + "HSL Digital Volume"}, + {"Earpiece or LineOut Mono Source", "Speaker Left", + "DA3 or ANC path to HfL"}, + + {"EAR DAC", NULL, "Earpiece or LineOut Mono Source"}, + + {"EAR Mute", NULL, "EAR DAC"}, + + {"EAR Enable", NULL, "EAR Mute"}, + + {"Earpiece", NULL, "EAR Enable"}, + + /* LineOut path stereo */ + + {"LineOut Source", "Stereo Path", "HSL DAC Driver"}, + {"LineOut Source", "Stereo Path", "HSR DAC Driver"}, + + /* LineOut path mono */ + + {"LineOut Source", "Mono Path", "EAR DAC"}, + + /* LineOut path */ + + {"LOL Disable HFL", NULL, "LineOut Source"}, + {"LOR Disable HFR", NULL, "LineOut Source"}, + + {"LOL Enable", NULL, "LOL Disable HFL"}, + {"LOR Enable", NULL, "LOR Disable HFR"}, + + {"LineOut Left", NULL, "LOL Enable"}, + {"LineOut Right", NULL, "LOR Enable"}, + + /* Vibrator path */ + + {"DA_IN5", NULL, "ab8500_0p"}, + {"DA5 Channel Volume", NULL, "DA_IN5"}, + {"DA_IN6", NULL, "ab8500_0p"}, + {"DA6 Channel Volume", NULL, "DA_IN6"}, + + {"VIB1 DAC", NULL, "DA5 Channel Volume"}, + {"VIB2 DAC", NULL, "DA6 Channel Volume"}, + + {"Vibra 1 Controller", "Audio Path", "VIB1 DAC"}, + {"Vibra 2 Controller", "Audio Path", "VIB2 DAC"}, + {"Vibra 1 Controller", "PWM Generator", "PWMGEN1"}, + {"Vibra 2 Controller", "PWM Generator", "PWMGEN2"}, + + {"VIB1 Enable", NULL, "Vibra 1 Controller"}, + {"VIB2 Enable", NULL, "Vibra 2 Controller"}, + + {"Vibra 1", NULL, "VIB1 Enable"}, + {"Vibra 2", NULL, "VIB2 Enable"}, + + + /* Mic 2 */ + + {"MIC2 V-AMICx Enable", NULL, "Mic 2"}, + + /* LineIn */ + {"LINL Mute", NULL, "LineIn Left"}, + {"LINR Mute", NULL, "LineIn Right"}, + + {"LINL Enable", NULL, "LINL Mute"}, + {"LINR Enable", NULL, "LINR Mute"}, + + /* LineIn, Mic 2 */ + {"Mic 2 or LINR Select", "LineIn Right", "LINR Enable"}, + {"Mic 2 or LINR Select", "Mic 2", "MIC2 V-AMICx Enable"}, + + {"LINL ADC", NULL, "LINL Enable"}, + {"LINR ADC", NULL, "Mic 2 or LINR Select"}, + + {"AD1 Source Select", "LineIn Left", "LINL ADC"}, + {"AD2 Source Select", "LineIn Right", "LINR ADC"}, + + {"AD1 Channel Volume", NULL, "AD1 Source Select"}, + {"AD2 Channel Volume", NULL, "AD2 Source Select"}, + + {"AD12 Enable", NULL, "AD1 Channel Volume"}, + {"AD12 Enable", NULL, "AD2 Channel Volume"}, + + {"AD_OUT1", NULL, "ab8500_0c"}, + {"AD_OUT1", NULL, "AD12 Enable"}, + {"AD_OUT2", NULL, "ab8500_0c"}, + {"AD_OUT2", NULL, "AD12 Enable"}, + + /* Mic 1 */ + + {"MIC1 Mute", NULL, "Mic 1"}, + + {"MIC1A V-AMICx Enable", NULL, "MIC1 Mute"}, + {"MIC1B V-AMICx Enable", NULL, "MIC1 Mute"}, + + {"Mic 1a or 1b Select", "Mic 1a", "MIC1A V-AMICx Enable"}, + {"Mic 1a or 1b Select", "Mic 1b", "MIC1B V-AMICx Enable"}, + + {"MIC1 ADC", NULL, "Mic 1a or 1b Select"}, + + {"AD3 Source Select", "Mic 1", "MIC1 ADC"}, + + {"AD3 Channel Volume", NULL, "AD3 Source Select"}, + + {"AD3 Enable", NULL, "AD3 Channel Volume"}, + + {"AD_OUT3", NULL, "ab8500_0c"}, + {"AD_OUT3", NULL, "AD3 Enable"}, + + /* HD Capture path */ + + {"AD5 Source Select", "Mic 2", "LINR ADC"}, + {"AD6 Source Select", "Mic 1", "MIC1 ADC"}, + + {"AD5 Channel Volume", NULL, "AD5 Source Select"}, + {"AD6 Channel Volume", NULL, "AD6 Source Select"}, + + {"AD57 Enable", NULL, "AD5 Channel Volume"}, + {"AD68 Enable", NULL, "AD6 Channel Volume"}, + + {"AD_OUT57", NULL, "ab8500_0c"}, + {"AD_OUT57", NULL, "AD57 Enable"}, + {"AD_OUT68", NULL, "ab8500_0c"}, + {"AD_OUT68", NULL, "AD68 Enable"}, + + /* Digital Microphone path */ + + {"DMic 1", NULL, "V-DMIC"}, + {"DMic 2", NULL, "V-DMIC"}, + {"DMic 3", NULL, "V-DMIC"}, + {"DMic 4", NULL, "V-DMIC"}, + {"DMic 5", NULL, "V-DMIC"}, + {"DMic 6", NULL, "V-DMIC"}, + + {"AD1 Source Select", NULL, "DMic 1"}, + {"AD2 Source Select", NULL, "DMic 2"}, + {"AD3 Source Select", NULL, "DMic 3"}, + {"AD5 Source Select", NULL, "DMic 5"}, + {"AD6 Source Select", NULL, "DMic 6"}, + + {"AD4 Channel Volume", NULL, "DMic 4"}, + {"AD4 Enable", NULL, "AD4 Channel Volume"}, + + {"AD_OUT4", NULL, "ab8500_0c"}, + {"AD_OUT4", NULL, "AD4 Enable"}, + + /* LineIn Bypass path */ + + {"LINL to HSL Volume", NULL, "LINL Enable"}, + {"LINR to HSR Volume", NULL, "LINR Enable"}, + + {"HSL DAC Driver", NULL, "LINL to HSL Volume"}, + {"HSR DAC Driver", NULL, "LINR to HSR Volume"}, + + /* ANC path (Acoustic Noise Cancellation) */ + + {"ANC Source", "Mic 2 / DMic 5", "AD5 Channel Volume"}, + {"ANC Source", "Mic 1 / DMic 6", "AD6 Channel Volume"}, + + {"ANC", "Switch", "ANC Source"}, + + {"Speaker Left Source", "ANC", "ANC"}, + {"Speaker Right Source", "ANC", "ANC"}, + {"ANC to Earpiece", "Switch", "ANC"}, + + {"HSL Digital Volume", NULL, "ANC to Earpiece"}, + + /* Sidetone Filter path */ + + {"Sidetone Left Source", "LineIn Left", "AD12 Enable"}, + {"Sidetone Left Source", "LineIn Right", "AD12 Enable"}, + {"Sidetone Left Source", "Mic 1", "AD3 Enable"}, + {"Sidetone Left Source", "Headset Left", "DA_IN1"}, + {"Sidetone Right Source", "LineIn Right", "AD12 Enable"}, + {"Sidetone Right Source", "Mic 1", "AD3 Enable"}, + {"Sidetone Right Source", "DMic 4", "AD4 Enable"}, + {"Sidetone Right Source", "Headset Right", "DA_IN2"}, + + {"STFIR1 Control", NULL, "Sidetone Left Source"}, + {"STFIR2 Control", NULL, "Sidetone Right Source"}, + + {"STFIR1 Volume", NULL, "STFIR1 Control"}, + {"STFIR2 Volume", NULL, "STFIR2 Control"}, + + {"DA1 Enable", NULL, "STFIR1 Volume"}, + {"DA2 Enable", NULL, "STFIR2 Volume"}, +}; + +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1a_vamicx[] = { + {"MIC1A V-AMICx Enable", NULL, "V-AMIC1"}, + {"MIC1A V-AMICx Enable", NULL, "V-AMIC2"}, +}; + +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1b_vamicx[] = { + {"MIC1B V-AMICx Enable", NULL, "V-AMIC1"}, + {"MIC1B V-AMICx Enable", NULL, "V-AMIC2"}, +}; + +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = { + {"MIC2 V-AMICx Enable", NULL, "V-AMIC1"}, + {"MIC2 V-AMICx Enable", NULL, "V-AMIC2"}, +}; + +/* ANC FIR-coefficients configuration sequence */ +static void anc_fir(struct snd_soc_codec *codec, + unsigned int bnk, unsigned int par, unsigned int val) +{ + if (par == 0 && bnk == 0) + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCFIRUPDATE), + BIT(AB8500_ANCCONF1_ANCFIRUPDATE)); + + snd_soc_write(codec, AB8500_ANCCONF5, val >> 8 & 0xff); + snd_soc_write(codec, AB8500_ANCCONF6, val & 0xff); + + if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1) + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0); +} + +/* ANC IIR-coefficients configuration sequence */ +static void anc_iir(struct snd_soc_codec *codec, unsigned int bnk, + unsigned int par, unsigned int val) +{ + if (par == 0) { + if (bnk == 0) { + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCIIRINIT), + BIT(AB8500_ANCCONF1_ANCIIRINIT)); + usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCIIRINIT), 0); + usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); + } else { + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCIIRUPDATE), + BIT(AB8500_ANCCONF1_ANCIIRUPDATE)); + } + } else if (par > 3) { + snd_soc_write(codec, AB8500_ANCCONF7, 0); + snd_soc_write(codec, AB8500_ANCCONF8, val >> 16 & 0xff); + } + + snd_soc_write(codec, AB8500_ANCCONF7, val >> 8 & 0xff); + snd_soc_write(codec, AB8500_ANCCONF8, val & 0xff); + + if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1) + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0); +} + +/* ANC IIR-/FIR-coefficients configuration sequence */ +static void anc_configure(struct snd_soc_codec *codec, + bool apply_fir, bool apply_iir) +{ + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); + unsigned int bnk, par, val; + + dev_dbg(codec->dev, "%s: Enter.\n", __func__); + + if (apply_fir) + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ENANC), 0); + + snd_soc_update_bits(codec, AB8500_ANCCONF1, + BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC)); + + if (apply_fir) + for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) + for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) { + val = snd_soc_read(codec, + drvdata->anc_fir_values[par]); + anc_fir(codec, bnk, par, val); + } + + if (apply_iir) + for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) + for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) { + val = snd_soc_read(codec, + drvdata->anc_iir_values[par]); + anc_iir(codec, bnk, par, val); + } + + dev_dbg(codec->dev, "%s: Exit.\n", __func__); +} + +/* + * Control-events + */ + +static int sid_status_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); + + mutex_lock(&codec->mutex); + ucontrol->value.integer.value[0] = drvdata->sid_status; + mutex_unlock(&codec->mutex); + + return 0; +} + +/* Write sidetone FIR-coefficients configuration sequence */ +static int sid_status_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); + unsigned int param, sidconf, val; + int status = 1; + + dev_dbg(codec->dev, "%s: Enter\n", __func__); + + if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) { + dev_err(codec->dev, + "%s: ERROR: This control supports '%s' only!\n", + __func__, enum_sid_state[SID_APPLY_FIR]); + return -EIO; + } + + mutex_lock(&codec->mutex); + + sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); + if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { + if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) { + dev_err(codec->dev, "%s: Sidetone busy while off!\n", + __func__); + status = -EPERM; + } else { + status = -EBUSY; + } + goto out; + } + + snd_soc_write(codec, AB8500_SIDFIRADR, 0); + + for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) { + val = snd_soc_read(codec, drvdata->sid_fir_values[param]); + snd_soc_write(codec, AB8500_SIDFIRCOEF1, val >> 8 & 0xff); + snd_soc_write(codec, AB8500_SIDFIRCOEF2, val & 0xff); + } + + snd_soc_update_bits(codec, AB8500_SIDFIRADR, + BIT(AB8500_SIDFIRADR_FIRSIDSET), + BIT(AB8500_SIDFIRADR_FIRSIDSET)); + snd_soc_update_bits(codec, AB8500_SIDFIRADR, + BIT(AB8500_SIDFIRADR_FIRSIDSET), 0); + + drvdata->sid_status = SID_FIR_CONFIGURED; + +out: + mutex_unlock(&codec->mutex); + + dev_dbg(codec->dev, "%s: Exit\n", __func__); + + return status; +} + +static int anc_status_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); + + mutex_lock(&codec->mutex); + ucontrol->value.integer.value[0] = drvdata->anc_status; + mutex_unlock(&codec->mutex); + + return 0; +} + +static int anc_status_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); + struct device *dev = codec->dev; + bool apply_fir, apply_iir; + int req, status; + + dev_dbg(dev, "%s: Enter.\n", __func__); + + mutex_lock(&drvdata->anc_lock); + + req = ucontrol->value.integer.value[0]; + if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR && + req != ANC_APPLY_IIR) { + dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", + __func__, enum_anc_state[req]); + return -EINVAL; + } + apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; + apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; + + status = snd_soc_dapm_force_enable_pin(&codec->dapm, + "ANC Configure Input"); + if (status < 0) { + dev_err(dev, + "%s: ERROR: Failed to enable power (status = %d)!\n", + __func__, status); + goto cleanup; + } + snd_soc_dapm_sync(&codec->dapm); + + mutex_lock(&codec->mutex); + anc_configure(codec, apply_fir, apply_iir); + mutex_unlock(&codec->mutex); + + if (apply_fir) { + if (drvdata->anc_status == ANC_IIR_CONFIGURED) + drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; + else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) + drvdata->anc_status = ANC_FIR_CONFIGURED; + } + if (apply_iir) { + if (drvdata->anc_status == ANC_FIR_CONFIGURED) + drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; + else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) + drvdata->anc_status = ANC_IIR_CONFIGURED; + } + + status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); + snd_soc_dapm_sync(&codec->dapm); + +cleanup: + mutex_unlock(&drvdata->anc_lock); + + if (status < 0) + dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", + __func__, status); + + dev_dbg(dev, "%s: Exit.\n", __func__); + + return (status < 0) ? status : 1; +} + +static int filter_control_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct filter_control *fc = + (struct filter_control *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = fc->count; + uinfo->value.integer.min = fc->min; + uinfo->value.integer.max = fc->max; + + return 0; +} + +static int filter_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct filter_control *fc = + (struct filter_control *)kcontrol->private_value; + unsigned int i; + + mutex_lock(&codec->mutex); + for (i = 0; i < fc->count; i++) + ucontrol->value.integer.value[i] = fc->value[i]; + mutex_unlock(&codec->mutex); + + return 0; +} + +static int filter_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct filter_control *fc = + (struct filter_control *)kcontrol->private_value; + unsigned int i; + + mutex_lock(&codec->mutex); + for (i = 0; i < fc->count; i++) + fc->value[i] = ucontrol->value.integer.value[i]; + mutex_unlock(&codec->mutex); + + return 0; +} + +/* + * Controls - Non-DAPM ASoC + */ + +static DECLARE_TLV_DB_SCALE(adx_dig_gain_tlv, -3200, 100, 1); +/* -32dB = Mute */ + +static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1); +/* -63dB = Mute */ + +static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1); +/* -1dB = Mute */ + +static const unsigned int hs_gain_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0), + 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0), +}; + +static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0); + +static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0); + +static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1); +/* -38dB = Mute */ + +static const char * const enum_hsfadspeed[] = {"2ms", "0.5ms", "10.6ms", + "5ms"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_hsfadspeed, + AB8500_DIGMICCONF, AB8500_DIGMICCONF_HSFADSPEED, enum_hsfadspeed); + +static const char * const enum_envdetthre[] = { + "250mV", "300mV", "350mV", "400mV", + "450mV", "500mV", "550mV", "600mV", + "650mV", "700mV", "750mV", "800mV", + "850mV", "900mV", "950mV", "1.00V" }; +static SOC_ENUM_SINGLE_DECL(soc_enum_envdeththre, + AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETHTHRE, enum_envdetthre); +static SOC_ENUM_SINGLE_DECL(soc_enum_envdetlthre, + AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETLTHRE, enum_envdetthre); +static const char * const enum_envdettime[] = { + "26.6us", "53.2us", "106us", "213us", + "426us", "851us", "1.70ms", "3.40ms", + "6.81ms", "13.6ms", "27.2ms", "54.5ms", + "109ms", "218ms", "436ms", "872ms" }; +static SOC_ENUM_SINGLE_DECL(soc_enum_envdettime, + AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETTIME, enum_envdettime); + +static const char * const enum_sinc31[] = {"Sinc 3", "Sinc 1"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_hsesinc, AB8500_HSLEARDIGGAIN, + AB8500_HSLEARDIGGAIN_HSSINC1, enum_sinc31); + +static const char * const enum_fadespeed[] = {"1ms", "4ms", "8ms", "16ms"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_fadespeed, AB8500_HSRDIGGAIN, + AB8500_HSRDIGGAIN_FADESPEED, enum_fadespeed); + +/* Earpiece */ + +static const char * const enum_lowpow[] = {"Normal", "Low Power"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_eardaclowpow, AB8500_ANACONF1, + AB8500_ANACONF1_EARDACLOWPOW, enum_lowpow); +static SOC_ENUM_SINGLE_DECL(soc_enum_eardrvlowpow, AB8500_ANACONF1, + AB8500_ANACONF1_EARDRVLOWPOW, enum_lowpow); + +static const char * const enum_av_mode[] = {"Audio", "Voice"}; +static SOC_ENUM_DOUBLE_DECL(soc_enum_ad12voice, AB8500_ADFILTCONF, + AB8500_ADFILTCONF_AD1VOICE, AB8500_ADFILTCONF_AD2VOICE, enum_av_mode); +static SOC_ENUM_DOUBLE_DECL(soc_enum_ad34voice, AB8500_ADFILTCONF, + AB8500_ADFILTCONF_AD3VOICE, AB8500_ADFILTCONF_AD4VOICE, enum_av_mode); + +/* DA */ + +static SOC_ENUM_SINGLE_DECL(soc_enum_da12voice, + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DA12VOICE, + enum_av_mode); +static SOC_ENUM_SINGLE_DECL(soc_enum_da34voice, + AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DA34VOICE, + enum_av_mode); +static SOC_ENUM_SINGLE_DECL(soc_enum_da56voice, + AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DA56VOICE, + enum_av_mode); + +static const char * const enum_da2hslr[] = {"Sidetone", "Audio Path"}; +static SOC_ENUM_DOUBLE_DECL(soc_enum_da2hslr, AB8500_DIGMULTCONF1, + AB8500_DIGMULTCONF1_DATOHSLEN, + AB8500_DIGMULTCONF1_DATOHSREN, enum_da2hslr); + +static const char * const enum_sinc53[] = {"Sinc 5", "Sinc 3"}; +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic12sinc, AB8500_DMICFILTCONF, + AB8500_DMICFILTCONF_DMIC1SINC3, + AB8500_DMICFILTCONF_DMIC2SINC3, enum_sinc53); +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic34sinc, AB8500_DMICFILTCONF, + AB8500_DMICFILTCONF_DMIC3SINC3, + AB8500_DMICFILTCONF_DMIC4SINC3, enum_sinc53); +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic56sinc, AB8500_DMICFILTCONF, + AB8500_DMICFILTCONF_DMIC5SINC3, + AB8500_DMICFILTCONF_DMIC6SINC3, enum_sinc53); + +/* Digital interface - DA from slot mapping */ +static const char * const enum_da_from_slot_map[] = {"SLOT0", + "SLOT1", + "SLOT2", + "SLOT3", + "SLOT4", + "SLOT5", + "SLOT6", + "SLOT7", + "SLOT8", + "SLOT9", + "SLOT10", + "SLOT11", + "SLOT12", + "SLOT13", + "SLOT14", + "SLOT15", + "SLOT16", + "SLOT17", + "SLOT18", + "SLOT19", + "SLOT20", + "SLOT21", + "SLOT22", + "SLOT23", + "SLOT24", + "SLOT25", + "SLOT26", + "SLOT27", + "SLOT28", + "SLOT29", + "SLOT30", + "SLOT31"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_da1slotmap, + AB8500_DASLOTCONF1, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da2slotmap, + AB8500_DASLOTCONF2, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da3slotmap, + AB8500_DASLOTCONF3, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da4slotmap, + AB8500_DASLOTCONF4, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da5slotmap, + AB8500_DASLOTCONF5, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da6slotmap, + AB8500_DASLOTCONF6, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da7slotmap, + AB8500_DASLOTCONF7, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_da8slotmap, + AB8500_DASLOTCONF8, AB8500_DASLOTCONFX_SLTODAX_SHIFT, + enum_da_from_slot_map); + +/* Digital interface - AD to slot mapping */ +static const char * const enum_ad_to_slot_map[] = {"AD_OUT1", + "AD_OUT2", + "AD_OUT3", + "AD_OUT4", + "AD_OUT5", + "AD_OUT6", + "AD_OUT7", + "AD_OUT8", + "zeroes", + "tristate"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, + AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot1map, + AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot2map, + AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot3map, + AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot4map, + AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot5map, + AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot6map, + AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot7map, + AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot8map, + AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot9map, + AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot10map, + AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot11map, + AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot12map, + AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot13map, + AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot14map, + AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot15map, + AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot16map, + AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot17map, + AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot18map, + AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot19map, + AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot20map, + AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot21map, + AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot22map, + AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot23map, + AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot24map, + AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot25map, + AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot26map, + AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot27map, + AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot28map, + AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot29map, + AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot30map, + AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_EVEN_SHIFT, + enum_ad_to_slot_map); +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot31map, + AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_ODD_SHIFT, + enum_ad_to_slot_map); + +/* Digital interface - Burst mode */ +static const char * const enum_mask[] = {"Unmasked", "Masked"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomask, + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOMASK, + enum_mask); +static const char * const enum_bitclk0[] = {"19_2_MHz", "38_4_MHz"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifo19m2, + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFO19M2, + enum_bitclk0); +static const char * const enum_slavemaster[] = {"Slave", "Master"}; +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast, + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOMAST_SHIFT, + enum_slavemaster); + +/* Sidetone */ +static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state); + +/* ANC */ +static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state); + +static struct snd_kcontrol_new ab8500_ctrls[] = { + /* Charge pump */ + SOC_ENUM("Charge Pump High Threshold For Low Voltage", + soc_enum_envdeththre), + SOC_ENUM("Charge Pump Low Threshold For Low Voltage", + soc_enum_envdetlthre), + SOC_SINGLE("Charge Pump Envelope Detection Switch", + AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETCPEN, + 1, 0), + SOC_ENUM("Charge Pump Envelope Detection Decay Time", + soc_enum_envdettime), + + /* Headset */ + SOC_ENUM("Headset Mode", soc_enum_da12voice), + SOC_SINGLE("Headset High Pass Switch", + AB8500_ANACONF1, AB8500_ANACONF1_HSHPEN, + 1, 0), + SOC_SINGLE("Headset Low Power Switch", + AB8500_ANACONF1, AB8500_ANACONF1_HSLOWPOW, + 1, 0), + SOC_SINGLE("Headset DAC Low Power Switch", + AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW1, + 1, 0), + SOC_SINGLE("Headset DAC Drv Low Power Switch", + AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW0, + 1, 0), + SOC_ENUM("Headset Fade Speed", soc_enum_hsfadspeed), + SOC_ENUM("Headset Source", soc_enum_da2hslr), + SOC_ENUM("Headset Filter", soc_enum_hsesinc), + SOC_DOUBLE_R_TLV("Headset Master Volume", + AB8500_DADIGGAIN1, AB8500_DADIGGAIN2, + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), + SOC_DOUBLE_R_TLV("Headset Digital Volume", + AB8500_HSLEARDIGGAIN, AB8500_HSRDIGGAIN, + 0, AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX, 1, hs_ear_dig_gain_tlv), + SOC_DOUBLE_TLV("Headset Volume", + AB8500_ANAGAIN3, + AB8500_ANAGAIN3_HSLGAIN, AB8500_ANAGAIN3_HSRGAIN, + AB8500_ANAGAIN3_HSXGAIN_MAX, 1, hs_gain_tlv), + + /* Earpiece */ + SOC_ENUM("Earpiece DAC Mode", + soc_enum_eardaclowpow), + SOC_ENUM("Earpiece DAC Drv Mode", + soc_enum_eardrvlowpow), + + /* HandsFree */ + SOC_ENUM("HF Mode", soc_enum_da34voice), + SOC_SINGLE("HF and Headset Swap Switch", + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_SWAPDA12_34, + 1, 0), + SOC_DOUBLE("HF Low EMI Mode Switch", + AB8500_CLASSDCONF1, + AB8500_CLASSDCONF1_HFLSWAPEN, AB8500_CLASSDCONF1_HFRSWAPEN, + 1, 0), + SOC_DOUBLE("HF FIR Bypass Switch", + AB8500_CLASSDCONF2, + AB8500_CLASSDCONF2_FIRBYP0, AB8500_CLASSDCONF2_FIRBYP1, + 1, 0), + SOC_DOUBLE("HF High Volume Switch", + AB8500_CLASSDCONF2, + AB8500_CLASSDCONF2_HIGHVOLEN0, AB8500_CLASSDCONF2_HIGHVOLEN1, + 1, 0), + SOC_SINGLE("HF L and R Bridge Switch", + AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLHF, + 1, 0), + SOC_DOUBLE_R_TLV("HF Master Volume", + AB8500_DADIGGAIN3, AB8500_DADIGGAIN4, + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), + + /* Vibra */ + SOC_DOUBLE("Vibra High Volume Switch", + AB8500_CLASSDCONF2, + AB8500_CLASSDCONF2_HIGHVOLEN2, AB8500_CLASSDCONF2_HIGHVOLEN3, + 1, 0), + SOC_DOUBLE("Vibra Low EMI Mode Switch", + AB8500_CLASSDCONF1, + AB8500_CLASSDCONF1_VIB1SWAPEN, AB8500_CLASSDCONF1_VIB2SWAPEN, + 1, 0), + SOC_DOUBLE("Vibra FIR Bypass Switch", + AB8500_CLASSDCONF2, + AB8500_CLASSDCONF2_FIRBYP2, AB8500_CLASSDCONF2_FIRBYP3, + 1, 0), + SOC_ENUM("Vibra Mode", soc_enum_da56voice), + SOC_DOUBLE_R("Vibra PWM Duty Cycle N", + AB8500_PWMGENCONF3, AB8500_PWMGENCONF5, + AB8500_PWMGENCONFX_PWMVIBXDUTCYC, + AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), + SOC_DOUBLE_R("Vibra PWM Duty Cycle P", + AB8500_PWMGENCONF2, AB8500_PWMGENCONF4, + AB8500_PWMGENCONFX_PWMVIBXDUTCYC, + AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), + SOC_SINGLE("Vibra 1 and 2 Bridge Switch", + AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLVIB, + 1, 0), + SOC_DOUBLE_R_TLV("Vibra Master Volume", + AB8500_DADIGGAIN5, AB8500_DADIGGAIN6, + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), + + /* HandsFree, Vibra */ + SOC_SINGLE("ClassD High Pass Volume", + AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHHPGAIN, + AB8500_CLASSDCONF3_DITHHPGAIN_MAX, 0), + SOC_SINGLE("ClassD White Volume", + AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHWGAIN, + AB8500_CLASSDCONF3_DITHWGAIN_MAX, 0), + + /* Mic 1, Mic 2, LineIn */ + SOC_DOUBLE_R_TLV("Mic Master Volume", + AB8500_ADDIGGAIN3, AB8500_ADDIGGAIN4, + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), + + /* Mic 1 */ + SOC_SINGLE_TLV("Mic 1", + AB8500_ANAGAIN1, + AB8500_ANAGAINX_MICXGAIN, + AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), + SOC_SINGLE("Mic 1 Low Power Switch", + AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX, + 1, 0), + + /* Mic 2 */ + SOC_DOUBLE("Mic High Pass Switch", + AB8500_ADFILTCONF, + AB8500_ADFILTCONF_AD3NH, AB8500_ADFILTCONF_AD4NH, + 1, 1), + SOC_ENUM("Mic Mode", soc_enum_ad34voice), + SOC_ENUM("Mic Filter", soc_enum_dmic34sinc), + SOC_SINGLE_TLV("Mic 2", + AB8500_ANAGAIN2, + AB8500_ANAGAINX_MICXGAIN, + AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), + SOC_SINGLE("Mic 2 Low Power Switch", + AB8500_ANAGAIN2, AB8500_ANAGAINX_LOWPOWMICX, + 1, 0), + + /* LineIn */ + SOC_DOUBLE("LineIn High Pass Switch", + AB8500_ADFILTCONF, + AB8500_ADFILTCONF_AD1NH, AB8500_ADFILTCONF_AD2NH, + 1, 1), + SOC_ENUM("LineIn Filter", soc_enum_dmic12sinc), + SOC_ENUM("LineIn Mode", soc_enum_ad12voice), + SOC_DOUBLE_R_TLV("LineIn Master Volume", + AB8500_ADDIGGAIN1, AB8500_ADDIGGAIN2, + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), + SOC_DOUBLE_TLV("LineIn", + AB8500_ANAGAIN4, + AB8500_ANAGAIN4_LINLGAIN, AB8500_ANAGAIN4_LINRGAIN, + AB8500_ANAGAIN4_LINXGAIN_MAX, 0, lin_gain_tlv), + SOC_DOUBLE_R_TLV("LineIn to Headset Volume", + AB8500_DIGLINHSLGAIN, AB8500_DIGLINHSRGAIN, + AB8500_DIGLINHSXGAIN_LINTOHSXGAIN, + AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX, + 1, lin2hs_gain_tlv), + + /* DMic */ + SOC_ENUM("DMic Filter", soc_enum_dmic56sinc), + SOC_DOUBLE_R_TLV("DMic Master Volume", + AB8500_ADDIGGAIN5, AB8500_ADDIGGAIN6, + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), + + /* Digital gains */ + SOC_ENUM("Digital Gain Fade Speed", soc_enum_fadespeed), + + /* Analog loopback */ + SOC_DOUBLE_R_TLV("Analog Loopback Volume", + AB8500_ADDIGLOOPGAIN1, AB8500_ADDIGLOOPGAIN2, + 0, AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX, 1, dax_dig_gain_tlv), + + /* Digital interface - DA from slot mapping */ + SOC_ENUM("Digital Interface DA 1 From Slot Map", soc_enum_da1slotmap), + SOC_ENUM("Digital Interface DA 2 From Slot Map", soc_enum_da2slotmap), + SOC_ENUM("Digital Interface DA 3 From Slot Map", soc_enum_da3slotmap), + SOC_ENUM("Digital Interface DA 4 From Slot Map", soc_enum_da4slotmap), + SOC_ENUM("Digital Interface DA 5 From Slot Map", soc_enum_da5slotmap), + SOC_ENUM("Digital Interface DA 6 From Slot Map", soc_enum_da6slotmap), + SOC_ENUM("Digital Interface DA 7 From Slot Map", soc_enum_da7slotmap), + SOC_ENUM("Digital Interface DA 8 From Slot Map", soc_enum_da8slotmap), + + /* Digital interface - AD to slot mapping */ + SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map), + SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map), + SOC_ENUM("Digital Interface AD To Slot 2 Map", soc_enum_adslot2map), + SOC_ENUM("Digital Interface AD To Slot 3 Map", soc_enum_adslot3map), + SOC_ENUM("Digital Interface AD To Slot 4 Map", soc_enum_adslot4map), + SOC_ENUM("Digital Interface AD To Slot 5 Map", soc_enum_adslot5map), + SOC_ENUM("Digital Interface AD To Slot 6 Map", soc_enum_adslot6map), + SOC_ENUM("Digital Interface AD To Slot 7 Map", soc_enum_adslot7map), + SOC_ENUM("Digital Interface AD To Slot 8 Map", soc_enum_adslot8map), + SOC_ENUM("Digital Interface AD To Slot 9 Map", soc_enum_adslot9map), + SOC_ENUM("Digital Interface AD To Slot 10 Map", soc_enum_adslot10map), + SOC_ENUM("Digital Interface AD To Slot 11 Map", soc_enum_adslot11map), + SOC_ENUM("Digital Interface AD To Slot 12 Map", soc_enum_adslot12map), + SOC_ENUM("Digital Interface AD To Slot 13 Map", soc_enum_adslot13map), + SOC_ENUM("Digital Interface AD To Slot 14 Map", soc_enum_adslot14map), + SOC_ENUM("Digital Interface AD To Slot 15 Map", soc_enum_adslot15map), + SOC_ENUM("Digital Interface AD To Slot 16 Map", soc_enum_adslot16map), + SOC_ENUM("Digital Interface AD To Slot 17 Map", soc_enum_adslot17map), + SOC_ENUM("Digital Interface AD To Slot 18 Map", soc_enum_adslot18map), + SOC_ENUM("Digital Interface AD To Slot 19 Map", soc_enum_adslot19map), + SOC_ENUM("Digital Interface AD To Slot 20 Map", soc_enum_adslot20map), + SOC_ENUM("Digital Interface AD To Slot 21 Map", soc_enum_adslot21map), + SOC_ENUM("Digital Interface AD To Slot 22 Map", soc_enum_adslot22map), + SOC_ENUM("Digital Interface AD To Slot 23 Map", soc_enum_adslot23map), + SOC_ENUM("Digital Interface AD To Slot 24 Map", soc_enum_adslot24map), + SOC_ENUM("Digital Interface AD To Slot 25 Map", soc_enum_adslot25map), + SOC_ENUM("Digital Interface AD To Slot 26 Map", soc_enum_adslot26map), + SOC_ENUM("Digital Interface AD To Slot 27 Map", soc_enum_adslot27map), + SOC_ENUM("Digital Interface AD To Slot 28 Map", soc_enum_adslot28map), + SOC_ENUM("Digital Interface AD To Slot 29 Map", soc_enum_adslot29map), + SOC_ENUM("Digital Interface AD To Slot 30 Map", soc_enum_adslot30map), + SOC_ENUM("Digital Interface AD To Slot 31 Map", soc_enum_adslot31map), + + /* Digital interface - Loopback */ + SOC_SINGLE("Digital Interface AD 1 Loopback Switch", + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DAI7TOADO1, + 1, 0), + SOC_SINGLE("Digital Interface AD 2 Loopback Switch", + AB8500_DASLOTCONF2, AB8500_DASLOTCONF2_DAI8TOADO2, + 1, 0), + SOC_SINGLE("Digital Interface AD 3 Loopback Switch", + AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DAI7TOADO3, + 1, 0), + SOC_SINGLE("Digital Interface AD 4 Loopback Switch", + AB8500_DASLOTCONF4, AB8500_DASLOTCONF4_DAI8TOADO4, + 1, 0), + SOC_SINGLE("Digital Interface AD 5 Loopback Switch", + AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DAI7TOADO5, + 1, 0), + SOC_SINGLE("Digital Interface AD 6 Loopback Switch", + AB8500_DASLOTCONF6, AB8500_DASLOTCONF6_DAI8TOADO6, + 1, 0), + SOC_SINGLE("Digital Interface AD 7 Loopback Switch", + AB8500_DASLOTCONF7, AB8500_DASLOTCONF7_DAI8TOADO7, + 1, 0), + SOC_SINGLE("Digital Interface AD 8 Loopback Switch", + AB8500_DASLOTCONF8, AB8500_DASLOTCONF8_DAI7TOADO8, + 1, 0), + + /* Digital interface - Burst FIFO */ + SOC_SINGLE("Digital Interface 0 FIFO Enable Switch", + AB8500_DIGIFCONF3, AB8500_DIGIFCONF3_IF0BFIFOEN, + 1, 0), + SOC_ENUM("Burst FIFO Mask", soc_enum_bfifomask), + SOC_ENUM("Burst FIFO Bit-clock Frequency", soc_enum_bfifo19m2), + SOC_SINGLE("Burst FIFO Threshold", + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOINT_SHIFT, + AB8500_FIFOCONF1_BFIFOINT_MAX, 0), + SOC_SINGLE("Burst FIFO Length", + AB8500_FIFOCONF2, AB8500_FIFOCONF2_BFIFOTX_SHIFT, + AB8500_FIFOCONF2_BFIFOTX_MAX, 0), + SOC_SINGLE("Burst FIFO EOS Extra Slots", + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOEXSL_SHIFT, + AB8500_FIFOCONF3_BFIFOEXSL_MAX, 0), + SOC_SINGLE("Burst FIFO FS Extra Bit-clocks", + AB8500_FIFOCONF3, AB8500_FIFOCONF3_PREBITCLK0_SHIFT, + AB8500_FIFOCONF3_PREBITCLK0_MAX, 0), + SOC_ENUM("Burst FIFO Interface Mode", soc_enum_bfifomast), + + SOC_SINGLE("Burst FIFO Interface Switch", + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFORUN_SHIFT, + 1, 0), + SOC_SINGLE("Burst FIFO Switch Frame Number", + AB8500_FIFOCONF4, AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT, + AB8500_FIFOCONF4_BFIFOFRAMSW_MAX, 0), + SOC_SINGLE("Burst FIFO Wake Up Delay", + AB8500_FIFOCONF5, AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT, + AB8500_FIFOCONF5_BFIFOWAKEUP_MAX, 0), + SOC_SINGLE("Burst FIFO Samples In FIFO", + AB8500_FIFOCONF6, AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT, + AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0), + + /* ANC */ + SOC_ENUM_EXT("ANC Status", soc_enum_ancstate, + anc_status_control_get, anc_status_control_put), + SOC_SINGLE_XR_SX("ANC Warp Delay Shift", + AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT, + AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0), + SOC_SINGLE_XR_SX("ANC FIR Output Shift", + AB8500_ANCCONF3, 1, AB8500_ANCCONF3_SHIFT, + AB8500_ANCCONF3_MIN, AB8500_ANCCONF3_MAX, 0), + SOC_SINGLE_XR_SX("ANC IIR Output Shift", + AB8500_ANCCONF4, 1, AB8500_ANCCONF4_SHIFT, + AB8500_ANCCONF4_MIN, AB8500_ANCCONF4_MAX, 0), + SOC_SINGLE_XR_SX("ANC Warp Delay", + AB8500_ANCCONF9, 2, AB8500_ANC_WARP_DELAY_SHIFT, + AB8500_ANC_WARP_DELAY_MIN, AB8500_ANC_WARP_DELAY_MAX, 0), + + /* Sidetone */ + SOC_ENUM_EXT("Sidetone Status", soc_enum_sidstate, + sid_status_control_get, sid_status_control_put), + SOC_SINGLE_STROBE("Sidetone Reset", + AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0), +}; + +static struct snd_kcontrol_new ab8500_filter_controls[] = { + AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS, + AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX), + AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS, + AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX), + AB8500_FILTER_CONTROL("Sidetone FIR Coefficients", + AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN, + AB8500_SID_FIR_COEFF_MAX) +}; +enum ab8500_filter { + AB8500_FILTER_ANC_FIR = 0, + AB8500_FILTER_ANC_IIR = 1, + AB8500_FILTER_SID_FIR = 2, +}; + +/* + * Extended interface for codec-driver + */ + +static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec) +{ + int status; + + dev_dbg(codec->dev, "%s: Enter.\n", __func__); + + /* Reset audio-registers and disable 32kHz-clock output 2 */ + status = ab8500_sysctrl_write(AB8500_STW4500CTRL3, + AB8500_STW4500CTRL3_CLK32KOUT2DIS | + AB8500_STW4500CTRL3_RESETAUDN, + AB8500_STW4500CTRL3_RESETAUDN); + if (status < 0) + return status; + + return 0; +} + +static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, + struct amic_settings *amics) +{ + u8 value8; + unsigned int value; + int status; + const struct snd_soc_dapm_route *route; + + dev_dbg(codec->dev, "%s: Enter.\n", __func__); + + /* Set DMic-clocks to outputs */ + status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC, + (u8)AB8500_GPIO_DIR4_REG, + &value8); + if (status < 0) + return status; + value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | + GPIO31_DIR_OUTPUT; + status = abx500_set_register_interruptible(codec->dev, + (u8)AB8500_MISC, + (u8)AB8500_GPIO_DIR4_REG, + value); + if (status < 0) + return status; + + /* Attach regulators to AMic DAPM-paths */ + dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__, + amic_micbias_str(amics->mic1a_micbias)); + route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias]; + status = snd_soc_dapm_add_routes(&codec->dapm, route, 1); + dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__, + amic_micbias_str(amics->mic1b_micbias)); + route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias]; + status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); + dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__, + amic_micbias_str(amics->mic2_micbias)); + route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias]; + status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); + if (status < 0) { + dev_err(codec->dev, + "%s: Failed to add AMic-regulator DAPM-routes (%d).\n", + __func__, status); + return status; + } + + /* Set AMic-configuration */ + dev_dbg(codec->dev, "%s: Mic 1 mic-type: %s\n", __func__, + amic_type_str(amics->mic1_type)); + snd_soc_update_bits(codec, AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX, + amics->mic1_type == AMIC_TYPE_DIFFERENTIAL ? + 0 : AB8500_ANAGAINX_ENSEMICX); + dev_dbg(codec->dev, "%s: Mic 2 mic-type: %s\n", __func__, + amic_type_str(amics->mic2_type)); + snd_soc_update_bits(codec, AB8500_ANAGAIN2, AB8500_ANAGAINX_ENSEMICX, + amics->mic2_type == AMIC_TYPE_DIFFERENTIAL ? + 0 : AB8500_ANAGAINX_ENSEMICX); + + return 0; +} +EXPORT_SYMBOL_GPL(ab8500_audio_setup_mics); + +static int ab8500_audio_set_ear_cmv(struct snd_soc_codec *codec, + enum ear_cm_voltage ear_cmv) +{ + char *cmv_str; + + switch (ear_cmv) { + case EAR_CMV_0_95V: + cmv_str = "0.95V"; + break; + case EAR_CMV_1_10V: + cmv_str = "1.10V"; + break; + case EAR_CMV_1_27V: + cmv_str = "1.27V"; + break; + case EAR_CMV_1_58V: + cmv_str = "1.58V"; + break; + default: + dev_err(codec->dev, + "%s: Unknown earpiece CM-voltage (%d)!\n", + __func__, (int)ear_cmv); + return -EINVAL; + } + dev_dbg(codec->dev, "%s: Earpiece CM-voltage: %s\n", __func__, + cmv_str); + snd_soc_update_bits(codec, AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM, + ear_cmv); + + return 0; +} +EXPORT_SYMBOL_GPL(ab8500_audio_set_ear_cmv); + +static int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai, + unsigned int delay) +{ + unsigned int mask, val; + struct snd_soc_codec *codec = dai->codec; + + mask = BIT(AB8500_DIGIFCONF2_IF0DEL); + val = 0; + + switch (delay) { + case 0: + break; + case 1: + val |= BIT(AB8500_DIGIFCONF2_IF0DEL); + break; + default: + dev_err(dai->codec->dev, + "%s: ERROR: Unsupported bit-delay (0x%x)!\n", + __func__, delay); + return -EINVAL; + } + + dev_dbg(dai->codec->dev, "%s: IF0 Bit-delay: %d bits.\n", + __func__, delay); + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); + + return 0; +} + +/* Gates clocking according format mask */ +static int ab8500_codec_set_dai_clock_gate(struct snd_soc_codec *codec, + unsigned int fmt) +{ + unsigned int mask; + unsigned int val; + + mask = BIT(AB8500_DIGIFCONF1_ENMASTGEN) | + BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); + + val = BIT(AB8500_DIGIFCONF1_ENMASTGEN); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { + case SND_SOC_DAIFMT_CONT: /* continuous clock */ + dev_dbg(codec->dev, "%s: IF0 Clock is continuous.\n", + __func__); + val |= BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); + break; + case SND_SOC_DAIFMT_GATED: /* clock is gated */ + dev_dbg(codec->dev, "%s: IF0 Clock is gated.\n", + __func__); + break; + default: + dev_err(codec->dev, + "%s: ERROR: Unsupported clock mask (0x%x)!\n", + __func__, fmt & SND_SOC_DAIFMT_CLOCK_MASK); + return -EINVAL; + } + + snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); + + return 0; +} + +static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + unsigned int mask; + unsigned int val; + struct snd_soc_codec *codec = dai->codec; + int status; + + dev_dbg(codec->dev, "%s: Enter (fmt = 0x%x)\n", __func__, fmt); + + mask = BIT(AB8500_DIGIFCONF3_IF1DATOIF0AD) | + BIT(AB8500_DIGIFCONF3_IF1CLKTOIF0CLK) | + BIT(AB8500_DIGIFCONF3_IF0BFIFOEN) | + BIT(AB8500_DIGIFCONF3_IF0MASTER); + val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & FRM master */ + dev_dbg(dai->codec->dev, + "%s: IF0 Master-mode: AB8500 master.\n", __func__); + val |= BIT(AB8500_DIGIFCONF3_IF0MASTER); + break; + case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & FRM slave */ + dev_dbg(dai->codec->dev, + "%s: IF0 Master-mode: AB8500 slave.\n", __func__); + break; + case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & FRM master */ + case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ + dev_err(dai->codec->dev, + "%s: ERROR: The device is either a master or a slave.\n", + __func__); + default: + dev_err(dai->codec->dev, + "%s: ERROR: Unsupporter master mask 0x%x\n", + __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); + return -EINVAL; + break; + } + + snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val); + + /* Set clock gating */ + status = ab8500_codec_set_dai_clock_gate(codec, fmt); + if (status) { + dev_err(dai->codec->dev, + "%s: ERRROR: Failed to set clock gate (%d).\n", + __func__, status); + return status; + } + + /* Setting data transfer format */ + + mask = BIT(AB8500_DIGIFCONF2_IF0FORMAT0) | + BIT(AB8500_DIGIFCONF2_IF0FORMAT1) | + BIT(AB8500_DIGIFCONF2_FSYNC0P) | + BIT(AB8500_DIGIFCONF2_BITCLK0P); + val = 0; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: /* I2S mode */ + dev_dbg(dai->codec->dev, "%s: IF0 Protocol: I2S\n", __func__); + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT1); + ab8500_audio_set_bit_delay(dai, 0); + break; + + case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */ + dev_dbg(dai->codec->dev, + "%s: IF0 Protocol: DSP A (TDM)\n", __func__); + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); + ab8500_audio_set_bit_delay(dai, 1); + break; + + case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */ + dev_dbg(dai->codec->dev, + "%s: IF0 Protocol: DSP B (TDM)\n", __func__); + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); + ab8500_audio_set_bit_delay(dai, 0); + break; + + default: + dev_err(dai->codec->dev, + "%s: ERROR: Unsupported format (0x%x)!\n", + __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ + dev_dbg(dai->codec->dev, + "%s: IF0: Normal bit clock, normal frame\n", + __func__); + break; + case SND_SOC_DAIFMT_NB_IF: /* normal BCLK + inv FRM */ + dev_dbg(dai->codec->dev, + "%s: IF0: Normal bit clock, inverted frame\n", + __func__); + val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); + break; + case SND_SOC_DAIFMT_IB_NF: /* invert BCLK + nor FRM */ + dev_dbg(dai->codec->dev, + "%s: IF0: Inverted bit clock, normal frame\n", + __func__); + val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); + break; + case SND_SOC_DAIFMT_IB_IF: /* invert BCLK + FRM */ + dev_dbg(dai->codec->dev, + "%s: IF0: Inverted bit clock, inverted frame\n", + __func__); + val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); + val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); + break; + default: + dev_err(dai->codec->dev, + "%s: ERROR: Unsupported INV mask 0x%x\n", + __func__, fmt & SND_SOC_DAIFMT_INV_MASK); + return -EINVAL; + } + + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); + + return 0; +} + +static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned int val, mask, slots_active; + + mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | + BIT(AB8500_DIGIFCONF2_IF0WL1); + val = 0; + + switch (slot_width) { + case 16: + break; + case 20: + val |= BIT(AB8500_DIGIFCONF2_IF0WL0); + break; + case 24: + val |= BIT(AB8500_DIGIFCONF2_IF0WL1); + break; + case 32: + val |= BIT(AB8500_DIGIFCONF2_IF0WL1) | + BIT(AB8500_DIGIFCONF2_IF0WL0); + break; + default: + dev_err(dai->codec->dev, "%s: Unsupported slot-width 0x%x\n", + __func__, slot_width); + return -EINVAL; + } + + dev_dbg(dai->codec->dev, "%s: IF0 slot-width: %d bits.\n", + __func__, slot_width); + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); + + /* Setup TDM clocking according to slot count */ + dev_dbg(dai->codec->dev, "%s: Slots, total: %d\n", __func__, slots); + mask = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | + BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); + switch (slots) { + case 2: + val = AB8500_MASK_NONE; + break; + case 4: + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0); + break; + case 8: + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); + break; + case 16: + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | + BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); + break; + default: + dev_err(dai->codec->dev, + "%s: ERROR: Unsupported number of slots (%d)!\n", + __func__, slots); + return -EINVAL; + } + snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); + + /* Setup TDM DA according to active tx slots */ + mask = AB8500_DASLOTCONFX_SLTODAX_MASK; + slots_active = hweight32(tx_mask); + dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, + slots_active); + switch (slots_active) { + case 0: + break; + case 1: + /* Slot 9 -> DA_IN1 & DA_IN3 */ + snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); + snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); + snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); + snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); + break; + case 2: + /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ + snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); + snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); + snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); + snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); + + break; + case 8: + dev_dbg(dai->codec->dev, + "%s: In 8-channel mode DA-from-slot mapping is set manually.", + __func__); + break; + default: + dev_err(dai->codec->dev, + "%s: Unsupported number of active TX-slots (%d)!\n", + __func__, slots_active); + return -EINVAL; + } + + /* Setup TDM AD according to active RX-slots */ + slots_active = hweight32(rx_mask); + dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, + slots_active); + switch (slots_active) { + case 0: + break; + case 1: + /* AD_OUT3 -> slot 0 & 1 */ + snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); + break; + case 2: + /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ + snd_soc_update_bits(codec, + AB8500_ADSLOTSEL1, + AB8500_MASK_ALL, + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | + AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD); + break; + case 8: + dev_dbg(dai->codec->dev, + "%s: In 8-channel mode AD-to-slot mapping is set manually.", + __func__); + break; + default: + dev_err(dai->codec->dev, + "%s: Unsupported number of active RX-slots (%d)!\n", + __func__, slots_active); + return -EINVAL; + } + + return 0; +} + +struct snd_soc_dai_driver ab8500_codec_dai[] = { + { + .name = "ab8500-codec-dai.0", + .id = 0, + .playback = { + .stream_name = "ab8500_0p", + .channels_min = 1, + .channels_max = 8, + .rates = AB8500_SUPPORTED_RATE, + .formats = AB8500_SUPPORTED_FMT, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, + .set_fmt = ab8500_codec_set_dai_fmt, + } + }, + .symmetric_rates = 1 + }, + { + .name = "ab8500-codec-dai.1", + .id = 1, + .capture = { + .stream_name = "ab8500_0c", + .channels_min = 1, + .channels_max = 8, + .rates = AB8500_SUPPORTED_RATE, + .formats = AB8500_SUPPORTED_FMT, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, + .set_fmt = ab8500_codec_set_dai_fmt, + } + }, + .symmetric_rates = 1 + } +}; + +static int ab8500_codec_probe(struct snd_soc_codec *codec) +{ + struct device *dev = codec->dev; + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); + struct ab8500_platform_data *pdata; + struct filter_control *fc; + int status; + + dev_dbg(dev, "%s: Enter.\n", __func__); + + /* Setup AB8500 according to board-settings */ + pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); + status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); + if (status < 0) { + pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); + return status; + } + status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv); + if (status < 0) { + pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n", + __func__, status); + return status; + } + + status = ab8500_audio_init_audioblock(codec); + if (status < 0) { + dev_err(dev, "%s: failed to init audio-block (%d)!\n", + __func__, status); + return status; + } + + /* Override HW-defaults */ + ab8500_codec_write_reg(codec, + AB8500_ANACONF5, + BIT(AB8500_ANACONF5_HSAUTOEN)); + ab8500_codec_write_reg(codec, + AB8500_SHORTCIRCONF, + BIT(AB8500_SHORTCIRCONF_HSZCDDIS)); + + /* Add filter controls */ + status = snd_soc_add_codec_controls(codec, ab8500_filter_controls, + ARRAY_SIZE(ab8500_filter_controls)); + if (status < 0) { + dev_err(dev, + "%s: failed to add ab8500 filter controls (%d).\n", + __func__, status); + return status; + } + fc = (struct filter_control *) + &ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value; + drvdata->anc_fir_values = (long *)fc->value; + fc = (struct filter_control *) + &ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value; + drvdata->anc_iir_values = (long *)fc->value; + fc = (struct filter_control *) + &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value; + drvdata->sid_fir_values = (long *)fc->value; + + (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); + + mutex_init(&drvdata->anc_lock); + + return status; +} + +static struct snd_soc_codec_driver ab8500_codec_driver = { + .probe = ab8500_codec_probe, + .read = ab8500_codec_read_reg, + .write = ab8500_codec_write_reg, + .reg_word_size = sizeof(u8), + .controls = ab8500_ctrls, + .num_controls = ARRAY_SIZE(ab8500_ctrls), + .dapm_widgets = ab8500_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), + .dapm_routes = ab8500_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), +}; + +static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev) +{ + int status; + struct ab8500_codec_drvdata *drvdata; + + dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); + + /* Create driver private-data struct */ + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata), + GFP_KERNEL); + drvdata->sid_status = SID_UNCONFIGURED; + drvdata->anc_status = ANC_UNCONFIGURED; + dev_set_drvdata(&pdev->dev, drvdata); + + dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); + status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, + ab8500_codec_dai, + ARRAY_SIZE(ab8500_codec_dai)); + if (status < 0) + dev_err(&pdev->dev, + "%s: Error: Failed to register codec (%d).\n", + __func__, status); + + return status; +} + +static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev) +{ + dev_info(&pdev->dev, "%s Enter.\n", __func__); + + snd_soc_unregister_codec(&pdev->dev); + + return 0; +} + +static struct platform_driver ab8500_codec_platform_driver = { + .driver = { + .name = "ab8500-codec", + .owner = THIS_MODULE, + }, + .probe = ab8500_codec_driver_probe, + .remove = __devexit_p(ab8500_codec_driver_remove), + .suspend = NULL, + .resume = NULL, +}; +module_platform_driver(ab8500_codec_platform_driver); + +MODULE_LICENSE("GPLv2"); diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h new file mode 100644 index 000000000000..114f69a0c629 --- /dev/null +++ b/sound/soc/codecs/ab8500-codec.h @@ -0,0 +1,590 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja , + * Kristoffer Karlsson , + * Roger Nilsson , + * for ST-Ericsson. + * + * Based on the early work done by: + * Mikko J. Lehto , + * Mikko Sarmanne , + * for ST-Ericsson. + * + * License terms: + * + * 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 AB8500_CODEC_REGISTERS_H +#define AB8500_CODEC_REGISTERS_H + +#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) +#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) + +/* AB8500 audio bank (0x0d) register definitions */ + +#define AB8500_POWERUP 0x00 +#define AB8500_AUDSWRESET 0x01 +#define AB8500_ADPATHENA 0x02 +#define AB8500_DAPATHENA 0x03 +#define AB8500_ANACONF1 0x04 +#define AB8500_ANACONF2 0x05 +#define AB8500_DIGMICCONF 0x06 +#define AB8500_ANACONF3 0x07 +#define AB8500_ANACONF4 0x08 +#define AB8500_DAPATHCONF 0x09 +#define AB8500_MUTECONF 0x0A +#define AB8500_SHORTCIRCONF 0x0B +#define AB8500_ANACONF5 0x0C +#define AB8500_ENVCPCONF 0x0D +#define AB8500_SIGENVCONF 0x0E +#define AB8500_PWMGENCONF1 0x0F +#define AB8500_PWMGENCONF2 0x10 +#define AB8500_PWMGENCONF3 0x11 +#define AB8500_PWMGENCONF4 0x12 +#define AB8500_PWMGENCONF5 0x13 +#define AB8500_ANAGAIN1 0x14 +#define AB8500_ANAGAIN2 0x15 +#define AB8500_ANAGAIN3 0x16 +#define AB8500_ANAGAIN4 0x17 +#define AB8500_DIGLINHSLGAIN 0x18 +#define AB8500_DIGLINHSRGAIN 0x19 +#define AB8500_ADFILTCONF 0x1A +#define AB8500_DIGIFCONF1 0x1B +#define AB8500_DIGIFCONF2 0x1C +#define AB8500_DIGIFCONF3 0x1D +#define AB8500_DIGIFCONF4 0x1E +#define AB8500_ADSLOTSEL1 0x1F +#define AB8500_ADSLOTSEL2 0x20 +#define AB8500_ADSLOTSEL3 0x21 +#define AB8500_ADSLOTSEL4 0x22 +#define AB8500_ADSLOTSEL5 0x23 +#define AB8500_ADSLOTSEL6 0x24 +#define AB8500_ADSLOTSEL7 0x25 +#define AB8500_ADSLOTSEL8 0x26 +#define AB8500_ADSLOTSEL9 0x27 +#define AB8500_ADSLOTSEL10 0x28 +#define AB8500_ADSLOTSEL11 0x29 +#define AB8500_ADSLOTSEL12 0x2A +#define AB8500_ADSLOTSEL13 0x2B +#define AB8500_ADSLOTSEL14 0x2C +#define AB8500_ADSLOTSEL15 0x2D +#define AB8500_ADSLOTSEL16 0x2E +#define AB8500_ADSLOTHIZCTRL1 0x2F +#define AB8500_ADSLOTHIZCTRL2 0x30 +#define AB8500_ADSLOTHIZCTRL3 0x31 +#define AB8500_ADSLOTHIZCTRL4 0x32 +#define AB8500_DASLOTCONF1 0x33 +#define AB8500_DASLOTCONF2 0x34 +#define AB8500_DASLOTCONF3 0x35 +#define AB8500_DASLOTCONF4 0x36 +#define AB8500_DASLOTCONF5 0x37 +#define AB8500_DASLOTCONF6 0x38 +#define AB8500_DASLOTCONF7 0x39 +#define AB8500_DASLOTCONF8 0x3A +#define AB8500_CLASSDCONF1 0x3B +#define AB8500_CLASSDCONF2 0x3C +#define AB8500_CLASSDCONF3 0x3D +#define AB8500_DMICFILTCONF 0x3E +#define AB8500_DIGMULTCONF1 0x3F +#define AB8500_DIGMULTCONF2 0x40 +#define AB8500_ADDIGGAIN1 0x41 +#define AB8500_ADDIGGAIN2 0x42 +#define AB8500_ADDIGGAIN3 0x43 +#define AB8500_ADDIGGAIN4 0x44 +#define AB8500_ADDIGGAIN5 0x45 +#define AB8500_ADDIGGAIN6 0x46 +#define AB8500_DADIGGAIN1 0x47 +#define AB8500_DADIGGAIN2 0x48 +#define AB8500_DADIGGAIN3 0x49 +#define AB8500_DADIGGAIN4 0x4A +#define AB8500_DADIGGAIN5 0x4B +#define AB8500_DADIGGAIN6 0x4C +#define AB8500_ADDIGLOOPGAIN1 0x4D +#define AB8500_ADDIGLOOPGAIN2 0x4E +#define AB8500_HSLEARDIGGAIN 0x4F +#define AB8500_HSRDIGGAIN 0x50 +#define AB8500_SIDFIRGAIN1 0x51 +#define AB8500_SIDFIRGAIN2 0x52 +#define AB8500_ANCCONF1 0x53 +#define AB8500_ANCCONF2 0x54 +#define AB8500_ANCCONF3 0x55 +#define AB8500_ANCCONF4 0x56 +#define AB8500_ANCCONF5 0x57 +#define AB8500_ANCCONF6 0x58 +#define AB8500_ANCCONF7 0x59 +#define AB8500_ANCCONF8 0x5A +#define AB8500_ANCCONF9 0x5B +#define AB8500_ANCCONF10 0x5C +#define AB8500_ANCCONF11 0x5D +#define AB8500_ANCCONF12 0x5E +#define AB8500_ANCCONF13 0x5F +#define AB8500_ANCCONF14 0x60 +#define AB8500_SIDFIRADR 0x61 +#define AB8500_SIDFIRCOEF1 0x62 +#define AB8500_SIDFIRCOEF2 0x63 +#define AB8500_SIDFIRCONF 0x64 +#define AB8500_AUDINTMASK1 0x65 +#define AB8500_AUDINTSOURCE1 0x66 +#define AB8500_AUDINTMASK2 0x67 +#define AB8500_AUDINTSOURCE2 0x68 +#define AB8500_FIFOCONF1 0x69 +#define AB8500_FIFOCONF2 0x6A +#define AB8500_FIFOCONF3 0x6B +#define AB8500_FIFOCONF4 0x6C +#define AB8500_FIFOCONF5 0x6D +#define AB8500_FIFOCONF6 0x6E +#define AB8500_AUDREV 0x6F + +#define AB8500_FIRST_REG AB8500_POWERUP +#define AB8500_LAST_REG AB8500_AUDREV +#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) + +#define AB8500_MASK_ALL 0xFF +#define AB8500_MASK_NONE 0x00 + +/* AB8500_POWERUP */ +#define AB8500_POWERUP_POWERUP 7 +#define AB8500_POWERUP_ENANA 3 + +/* AB8500_AUDSWRESET */ +#define AB8500_AUDSWRESET_SWRESET 7 + +/* AB8500_ADPATHENA */ +#define AB8500_ADPATHENA_ENAD12 7 +#define AB8500_ADPATHENA_ENAD34 5 +#define AB8500_ADPATHENA_ENAD5768 3 + +/* AB8500_DAPATHENA */ +#define AB8500_DAPATHENA_ENDA1 7 +#define AB8500_DAPATHENA_ENDA2 6 +#define AB8500_DAPATHENA_ENDA3 5 +#define AB8500_DAPATHENA_ENDA4 4 +#define AB8500_DAPATHENA_ENDA5 3 +#define AB8500_DAPATHENA_ENDA6 2 + +/* AB8500_ANACONF1 */ +#define AB8500_ANACONF1_HSLOWPOW 7 +#define AB8500_ANACONF1_DACLOWPOW1 6 +#define AB8500_ANACONF1_DACLOWPOW0 5 +#define AB8500_ANACONF1_EARDACLOWPOW 4 +#define AB8500_ANACONF1_EARSELCM 2 +#define AB8500_ANACONF1_HSHPEN 1 +#define AB8500_ANACONF1_EARDRVLOWPOW 0 + +/* AB8500_ANACONF2 */ +#define AB8500_ANACONF2_ENMIC1 7 +#define AB8500_ANACONF2_ENMIC2 6 +#define AB8500_ANACONF2_ENLINL 5 +#define AB8500_ANACONF2_ENLINR 4 +#define AB8500_ANACONF2_MUTMIC1 3 +#define AB8500_ANACONF2_MUTMIC2 2 +#define AB8500_ANACONF2_MUTLINL 1 +#define AB8500_ANACONF2_MUTLINR 0 + +/* AB8500_DIGMICCONF */ +#define AB8500_DIGMICCONF_ENDMIC1 7 +#define AB8500_DIGMICCONF_ENDMIC2 6 +#define AB8500_DIGMICCONF_ENDMIC3 5 +#define AB8500_DIGMICCONF_ENDMIC4 4 +#define AB8500_DIGMICCONF_ENDMIC5 3 +#define AB8500_DIGMICCONF_ENDMIC6 2 +#define AB8500_DIGMICCONF_HSFADSPEED 0 + +/* AB8500_ANACONF3 */ +#define AB8500_ANACONF3_MIC1SEL 7 +#define AB8500_ANACONF3_LINRSEL 6 +#define AB8500_ANACONF3_ENDRVHSL 5 +#define AB8500_ANACONF3_ENDRVHSR 4 +#define AB8500_ANACONF3_ENADCMIC 2 +#define AB8500_ANACONF3_ENADCLINL 1 +#define AB8500_ANACONF3_ENADCLINR 0 + +/* AB8500_ANACONF4 */ +#define AB8500_ANACONF4_DISPDVSS 7 +#define AB8500_ANACONF4_ENEAR 6 +#define AB8500_ANACONF4_ENHSL 5 +#define AB8500_ANACONF4_ENHSR 4 +#define AB8500_ANACONF4_ENHFL 3 +#define AB8500_ANACONF4_ENHFR 2 +#define AB8500_ANACONF4_ENVIB1 1 +#define AB8500_ANACONF4_ENVIB2 0 + +/* AB8500_DAPATHCONF */ +#define AB8500_DAPATHCONF_ENDACEAR 6 +#define AB8500_DAPATHCONF_ENDACHSL 5 +#define AB8500_DAPATHCONF_ENDACHSR 4 +#define AB8500_DAPATHCONF_ENDACHFL 3 +#define AB8500_DAPATHCONF_ENDACHFR 2 +#define AB8500_DAPATHCONF_ENDACVIB1 1 +#define AB8500_DAPATHCONF_ENDACVIB2 0 + +/* AB8500_MUTECONF */ +#define AB8500_MUTECONF_MUTEAR 6 +#define AB8500_MUTECONF_MUTHSL 5 +#define AB8500_MUTECONF_MUTHSR 4 +#define AB8500_MUTECONF_MUTDACEAR 2 +#define AB8500_MUTECONF_MUTDACHSL 1 +#define AB8500_MUTECONF_MUTDACHSR 0 + +/* AB8500_SHORTCIRCONF */ +#define AB8500_SHORTCIRCONF_ENSHORTPWD 7 +#define AB8500_SHORTCIRCONF_EARSHORTDIS 6 +#define AB8500_SHORTCIRCONF_HSSHORTDIS 5 +#define AB8500_SHORTCIRCONF_HSPULLDEN 4 +#define AB8500_SHORTCIRCONF_HSOSCEN 2 +#define AB8500_SHORTCIRCONF_HSFADDIS 1 +#define AB8500_SHORTCIRCONF_HSZCDDIS 0 +/* Zero cross should be disabled */ + +/* AB8500_ANACONF5 */ +#define AB8500_ANACONF5_ENCPHS 7 +#define AB8500_ANACONF5_HSLDACTOLOL 5 +#define AB8500_ANACONF5_HSRDACTOLOR 4 +#define AB8500_ANACONF5_ENLOL 3 +#define AB8500_ANACONF5_ENLOR 2 +#define AB8500_ANACONF5_HSAUTOEN 0 + +/* AB8500_ENVCPCONF */ +#define AB8500_ENVCPCONF_ENVDETHTHRE 4 +#define AB8500_ENVCPCONF_ENVDETLTHRE 0 +#define AB8500_ENVCPCONF_ENVDETHTHRE_MAX 0x0F +#define AB8500_ENVCPCONF_ENVDETLTHRE_MAX 0x0F + +/* AB8500_SIGENVCONF */ +#define AB8500_SIGENVCONF_CPLVEN 5 +#define AB8500_SIGENVCONF_ENVDETCPEN 4 +#define AB8500_SIGENVCONF_ENVDETTIME 0 +#define AB8500_SIGENVCONF_ENVDETTIME_MAX 0x0F + +/* AB8500_PWMGENCONF1 */ +#define AB8500_PWMGENCONF1_PWMTOVIB1 7 +#define AB8500_PWMGENCONF1_PWMTOVIB2 6 +#define AB8500_PWMGENCONF1_PWM1CTRL 5 +#define AB8500_PWMGENCONF1_PWM2CTRL 4 +#define AB8500_PWMGENCONF1_PWM1NCTRL 3 +#define AB8500_PWMGENCONF1_PWM1PCTRL 2 +#define AB8500_PWMGENCONF1_PWM2NCTRL 1 +#define AB8500_PWMGENCONF1_PWM2PCTRL 0 + +/* AB8500_PWMGENCONF2 */ +/* AB8500_PWMGENCONF3 */ +/* AB8500_PWMGENCONF4 */ +/* AB8500_PWMGENCONF5 */ +#define AB8500_PWMGENCONFX_PWMVIBXPOL 7 +#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC 0 +#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX 0x64 + +/* AB8500_ANAGAIN1 */ +/* AB8500_ANAGAIN2 */ +#define AB8500_ANAGAINX_ENSEMICX 7 +#define AB8500_ANAGAINX_LOWPOWMICX 6 +#define AB8500_ANAGAINX_MICXGAIN 0 +#define AB8500_ANAGAINX_MICXGAIN_MAX 0x1F + +/* AB8500_ANAGAIN3 */ +#define AB8500_ANAGAIN3_HSLGAIN 4 +#define AB8500_ANAGAIN3_HSRGAIN 0 +#define AB8500_ANAGAIN3_HSXGAIN_MAX 0x0F + +/* AB8500_ANAGAIN4 */ +#define AB8500_ANAGAIN4_LINLGAIN 4 +#define AB8500_ANAGAIN4_LINRGAIN 0 +#define AB8500_ANAGAIN4_LINXGAIN_MAX 0x0F + +/* AB8500_DIGLINHSLGAIN */ +/* AB8500_DIGLINHSRGAIN */ +#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN 0 +#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX 0x13 + +/* AB8500_ADFILTCONF */ +#define AB8500_ADFILTCONF_AD1NH 7 +#define AB8500_ADFILTCONF_AD2NH 6 +#define AB8500_ADFILTCONF_AD3NH 5 +#define AB8500_ADFILTCONF_AD4NH 4 +#define AB8500_ADFILTCONF_AD1VOICE 3 +#define AB8500_ADFILTCONF_AD2VOICE 2 +#define AB8500_ADFILTCONF_AD3VOICE 1 +#define AB8500_ADFILTCONF_AD4VOICE 0 + +/* AB8500_DIGIFCONF1 */ +#define AB8500_DIGIFCONF1_ENMASTGEN 7 +#define AB8500_DIGIFCONF1_IF1BITCLKOS1 6 +#define AB8500_DIGIFCONF1_IF1BITCLKOS0 5 +#define AB8500_DIGIFCONF1_ENFSBITCLK1 4 +#define AB8500_DIGIFCONF1_IF0BITCLKOS1 2 +#define AB8500_DIGIFCONF1_IF0BITCLKOS0 1 +#define AB8500_DIGIFCONF1_ENFSBITCLK0 0 + +/* AB8500_DIGIFCONF2 */ +#define AB8500_DIGIFCONF2_FSYNC0P 6 +#define AB8500_DIGIFCONF2_BITCLK0P 5 +#define AB8500_DIGIFCONF2_IF0DEL 4 +#define AB8500_DIGIFCONF2_IF0FORMAT1 3 +#define AB8500_DIGIFCONF2_IF0FORMAT0 2 +#define AB8500_DIGIFCONF2_IF0WL1 1 +#define AB8500_DIGIFCONF2_IF0WL0 0 + +/* AB8500_DIGIFCONF3 */ +#define AB8500_DIGIFCONF3_IF0DATOIF1AD 7 +#define AB8500_DIGIFCONF3_IF0CLKTOIF1CLK 6 +#define AB8500_DIGIFCONF3_IF1MASTER 5 +#define AB8500_DIGIFCONF3_IF1DATOIF0AD 3 +#define AB8500_DIGIFCONF3_IF1CLKTOIF0CLK 2 +#define AB8500_DIGIFCONF3_IF0MASTER 1 +#define AB8500_DIGIFCONF3_IF0BFIFOEN 0 + +/* AB8500_DIGIFCONF4 */ +#define AB8500_DIGIFCONF4_FSYNC1P 6 +#define AB8500_DIGIFCONF4_BITCLK1P 5 +#define AB8500_DIGIFCONF4_IF1DEL 4 +#define AB8500_DIGIFCONF4_IF1FORMAT1 3 +#define AB8500_DIGIFCONF4_IF1FORMAT0 2 +#define AB8500_DIGIFCONF4_IF1WL1 1 +#define AB8500_DIGIFCONF4_IF1WL0 0 + +/* AB8500_ADSLOTSELX */ +#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 +#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x01 +#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x02 +#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x03 +#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x04 +#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x05 +#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x06 +#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x07 +#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x08 +#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0x0F +#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00 +#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x10 +#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x20 +#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x30 +#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x40 +#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x50 +#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x60 +#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x70 +#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x80 +#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0xF0 +#define AB8500_ADSLOTSELX_EVEN_SHIFT 0 +#define AB8500_ADSLOTSELX_ODD_SHIFT 4 + +/* AB8500_ADSLOTHIZCTRL1 */ +/* AB8500_ADSLOTHIZCTRL2 */ +/* AB8500_ADSLOTHIZCTRL3 */ +/* AB8500_ADSLOTHIZCTRL4 */ +/* AB8500_DASLOTCONF1 */ +#define AB8500_DASLOTCONF1_DA12VOICE 7 +#define AB8500_DASLOTCONF1_SWAPDA12_34 6 +#define AB8500_DASLOTCONF1_DAI7TOADO1 5 + +/* AB8500_DASLOTCONF2 */ +#define AB8500_DASLOTCONF2_DAI8TOADO2 5 + +/* AB8500_DASLOTCONF3 */ +#define AB8500_DASLOTCONF3_DA34VOICE 7 +#define AB8500_DASLOTCONF3_DAI7TOADO3 5 + +/* AB8500_DASLOTCONF4 */ +#define AB8500_DASLOTCONF4_DAI8TOADO4 5 + +/* AB8500_DASLOTCONF5 */ +#define AB8500_DASLOTCONF5_DA56VOICE 7 +#define AB8500_DASLOTCONF5_DAI7TOADO5 5 + +/* AB8500_DASLOTCONF6 */ +#define AB8500_DASLOTCONF6_DAI8TOADO6 5 + +/* AB8500_DASLOTCONF7 */ +#define AB8500_DASLOTCONF7_DAI8TOADO7 5 + +/* AB8500_DASLOTCONF8 */ +#define AB8500_DASLOTCONF8_DAI7TOADO8 5 + +#define AB8500_DASLOTCONFX_SLTODAX_SHIFT 0 +#define AB8500_DASLOTCONFX_SLTODAX_MASK 0x1F + +/* AB8500_CLASSDCONF1 */ +#define AB8500_CLASSDCONF1_PARLHF 7 +#define AB8500_CLASSDCONF1_PARLVIB 6 +#define AB8500_CLASSDCONF1_VIB1SWAPEN 3 +#define AB8500_CLASSDCONF1_VIB2SWAPEN 2 +#define AB8500_CLASSDCONF1_HFLSWAPEN 1 +#define AB8500_CLASSDCONF1_HFRSWAPEN 0 + +/* AB8500_CLASSDCONF2 */ +#define AB8500_CLASSDCONF2_FIRBYP3 7 +#define AB8500_CLASSDCONF2_FIRBYP2 6 +#define AB8500_CLASSDCONF2_FIRBYP1 5 +#define AB8500_CLASSDCONF2_FIRBYP0 4 +#define AB8500_CLASSDCONF2_HIGHVOLEN3 3 +#define AB8500_CLASSDCONF2_HIGHVOLEN2 2 +#define AB8500_CLASSDCONF2_HIGHVOLEN1 1 +#define AB8500_CLASSDCONF2_HIGHVOLEN0 0 + +/* AB8500_CLASSDCONF3 */ +#define AB8500_CLASSDCONF3_DITHHPGAIN 4 +#define AB8500_CLASSDCONF3_DITHHPGAIN_MAX 0x0A +#define AB8500_CLASSDCONF3_DITHWGAIN 0 +#define AB8500_CLASSDCONF3_DITHWGAIN_MAX 0x0A + +/* AB8500_DMICFILTCONF */ +#define AB8500_DMICFILTCONF_ANCINSEL 7 +#define AB8500_DMICFILTCONF_DA3TOEAR 6 +#define AB8500_DMICFILTCONF_DMIC1SINC3 5 +#define AB8500_DMICFILTCONF_DMIC2SINC3 4 +#define AB8500_DMICFILTCONF_DMIC3SINC3 3 +#define AB8500_DMICFILTCONF_DMIC4SINC3 2 +#define AB8500_DMICFILTCONF_DMIC5SINC3 1 +#define AB8500_DMICFILTCONF_DMIC6SINC3 0 + +/* AB8500_DIGMULTCONF1 */ +#define AB8500_DIGMULTCONF1_DATOHSLEN 7 +#define AB8500_DIGMULTCONF1_DATOHSREN 6 +#define AB8500_DIGMULTCONF1_AD1SEL 5 +#define AB8500_DIGMULTCONF1_AD2SEL 4 +#define AB8500_DIGMULTCONF1_AD3SEL 3 +#define AB8500_DIGMULTCONF1_AD5SEL 2 +#define AB8500_DIGMULTCONF1_AD6SEL 1 +#define AB8500_DIGMULTCONF1_ANCSEL 0 + +/* AB8500_DIGMULTCONF2 */ +#define AB8500_DIGMULTCONF2_DATOHFREN 7 +#define AB8500_DIGMULTCONF2_DATOHFLEN 6 +#define AB8500_DIGMULTCONF2_HFRSEL 5 +#define AB8500_DIGMULTCONF2_HFLSEL 4 +#define AB8500_DIGMULTCONF2_FIRSID1SEL 2 +#define AB8500_DIGMULTCONF2_FIRSID2SEL 0 + +/* AB8500_ADDIGGAIN1 */ +/* AB8500_ADDIGGAIN2 */ +/* AB8500_ADDIGGAIN3 */ +/* AB8500_ADDIGGAIN4 */ +/* AB8500_ADDIGGAIN5 */ +/* AB8500_ADDIGGAIN6 */ +#define AB8500_ADDIGGAINX_FADEDISADX 6 +#define AB8500_ADDIGGAINX_ADXGAIN_MAX 0x3F + +/* AB8500_DADIGGAIN1 */ +/* AB8500_DADIGGAIN2 */ +/* AB8500_DADIGGAIN3 */ +/* AB8500_DADIGGAIN4 */ +/* AB8500_DADIGGAIN5 */ +/* AB8500_DADIGGAIN6 */ +#define AB8500_DADIGGAINX_FADEDISDAX 6 +#define AB8500_DADIGGAINX_DAXGAIN_MAX 0x3F + +/* AB8500_ADDIGLOOPGAIN1 */ +/* AB8500_ADDIGLOOPGAIN2 */ +#define AB8500_ADDIGLOOPGAINX_FADEDISADXL 6 +#define AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX 0x3F + +/* AB8500_HSLEARDIGGAIN */ +#define AB8500_HSLEARDIGGAIN_HSSINC1 7 +#define AB8500_HSLEARDIGGAIN_FADEDISHSL 4 +#define AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX 0x09 + +/* AB8500_HSRDIGGAIN */ +#define AB8500_HSRDIGGAIN_FADESPEED 6 +#define AB8500_HSRDIGGAIN_FADEDISHSR 4 +#define AB8500_HSRDIGGAIN_HSRDGAIN_MAX 0x09 + +/* AB8500_SIDFIRGAIN1 */ +/* AB8500_SIDFIRGAIN2 */ +#define AB8500_SIDFIRGAINX_FIRSIDXGAIN_MAX 0x1F + +/* AB8500_ANCCONF1 */ +#define AB8500_ANCCONF1_ANCIIRUPDATE 3 +#define AB8500_ANCCONF1_ENANC 2 +#define AB8500_ANCCONF1_ANCIIRINIT 1 +#define AB8500_ANCCONF1_ANCFIRUPDATE 0 + +/* AB8500_ANCCONF2 */ +#define AB8500_ANCCONF2_SHIFT 5 +#define AB8500_ANCCONF2_MIN -0x10 +#define AB8500_ANCCONF2_MAX 0xF + +/* AB8500_ANCCONF3 */ +#define AB8500_ANCCONF3_SHIFT 5 +#define AB8500_ANCCONF3_MIN -0x10 +#define AB8500_ANCCONF3_MAX 0xF + +/* AB8500_ANCCONF4 */ +#define AB8500_ANCCONF4_SHIFT 5 +#define AB8500_ANCCONF4_MIN -0x10 +#define AB8500_ANCCONF4_MAX 0xF + +/* AB8500_ANC_FIR_COEFFS */ +#define AB8500_ANC_FIR_COEFF_MIN -0x8000 +#define AB8500_ANC_FIR_COEFF_MAX 0x7FFF +#define AB8500_ANC_FIR_COEFFS 15 + +/* AB8500_ANC_IIR_COEFFS */ +#define AB8500_ANC_IIR_COEFF_MIN -0x800000 +#define AB8500_ANC_IIR_COEFF_MAX 0x7FFFFF +#define AB8500_ANC_IIR_COEFFS 24 +/* AB8500_ANC_WARP_DELAY */ +#define AB8500_ANC_WARP_DELAY_SHIFT 16 +#define AB8500_ANC_WARP_DELAY_MIN 0x0000 +#define AB8500_ANC_WARP_DELAY_MAX 0xFFFF + +/* AB8500_ANCCONF11 */ +/* AB8500_ANCCONF12 */ +/* AB8500_ANCCONF13 */ +/* AB8500_ANCCONF14 */ + +/* AB8500_SIDFIRADR */ +#define AB8500_SIDFIRADR_FIRSIDSET 7 +#define AB8500_SIDFIRADR_ADDRESS_SHIFT 0 +#define AB8500_SIDFIRADR_ADDRESS_MAX 0x7F + +/* AB8500_SIDFIRCOEF1 */ +/* AB8500_SIDFIRCOEF2 */ +#define AB8500_SID_FIR_COEFF_MIN 0 +#define AB8500_SID_FIR_COEFF_MAX 0xFFFF +#define AB8500_SID_FIR_COEFFS 128 + +/* AB8500_SIDFIRCONF */ +#define AB8500_SIDFIRCONF_ENFIRSIDS 2 +#define AB8500_SIDFIRCONF_FIRSIDSTOIF1 1 +#define AB8500_SIDFIRCONF_FIRSIDBUSY 0 + +/* AB8500_AUDINTMASK1 */ +/* AB8500_AUDINTSOURCE1 */ +/* AB8500_AUDINTMASK2 */ +/* AB8500_AUDINTSOURCE2 */ + +/* AB8500_FIFOCONF1 */ +#define AB8500_FIFOCONF1_BFIFOMASK 0x80 +#define AB8500_FIFOCONF1_BFIFO19M2 0x40 +#define AB8500_FIFOCONF1_BFIFOINT_SHIFT 0 +#define AB8500_FIFOCONF1_BFIFOINT_MAX 0x3F + +/* AB8500_FIFOCONF2 */ +#define AB8500_FIFOCONF2_BFIFOTX_SHIFT 0 +#define AB8500_FIFOCONF2_BFIFOTX_MAX 0xFF + +/* AB8500_FIFOCONF3 */ +#define AB8500_FIFOCONF3_BFIFOEXSL_SHIFT 5 +#define AB8500_FIFOCONF3_BFIFOEXSL_MAX 0x5 +#define AB8500_FIFOCONF3_PREBITCLK0_SHIFT 2 +#define AB8500_FIFOCONF3_PREBITCLK0_MAX 0x7 +#define AB8500_FIFOCONF3_BFIFOMAST_SHIFT 1 +#define AB8500_FIFOCONF3_BFIFORUN_SHIFT 0 + +/* AB8500_FIFOCONF4 */ +#define AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT 0 +#define AB8500_FIFOCONF4_BFIFOFRAMSW_MAX 0xFF + +/* AB8500_FIFOCONF5 */ +#define AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT 0 +#define AB8500_FIFOCONF5_BFIFOWAKEUP_MAX 0xFF + +/* AB8500_FIFOCONF6 */ +#define AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT 0 +#define AB8500_FIFOCONF6_BFIFOSAMPLE_MAX 0xFF + +/* AB8500_AUDREV */ + +#endif -- GitLab From 754fdff86f956a91834887ad56ea292f5d2fa114 Mon Sep 17 00:00:00 2001 From: Annie Liu Date: Fri, 8 Jun 2012 19:18:39 +0800 Subject: [PATCH 0416/5711] ALSA: hda - add support for HD-Audio of VIA HDMI GFX Cards This is patch supporting HD-Audio function of VIA GFX cards which support HDMI. Those are integrated graphics of chipsets VX900 and VX11 separately. Signed-off-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2b6392be451c..d49926e4d19f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3338,6 +3338,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, + /* VIA GFX VT7122/VX900 */ + { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, + /* VIA GFX VT6122/VX11 */ + { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, /* SIS966 */ { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, /* ULI M5461 */ -- GitLab From 3de5ff88773d9f106b668937da2f36c97801b332 Mon Sep 17 00:00:00 2001 From: Annie Liu Date: Fri, 8 Jun 2012 19:18:42 +0800 Subject: [PATCH 0417/5711] ALSA: hda - add support for HD-Audio CODECes of VIA HDMI GFX Cards This is patch supporting the CODECes of HD-Audio function of VIA GFX cards which support HDMI. For CODECes 0x9f80/0x9f81, which belong to VX900, since the hardware is not fully compliant to HD-Audio 1.3, simple_i*() is adopted temporarily. Signed-off-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ad319d4dc32f..696681826b01 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1863,6 +1863,62 @@ static int patch_atihdmi(struct hda_codec *codec) return 0; } +/* VIA HDMI Implementation */ +#define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ +#define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ + +static struct hda_verb viahdmi_basic_init[] = { + /* enable digital output on pin widget */ + { VIAHDMI_PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + {} /* terminator */ +}; + +static int via_hdmi_init(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, viahdmi_basic_init); + return 0; +} + +static const struct hda_codec_ops via_hdmi_patch_ops = { + .build_controls = simple_playback_build_controls, + .build_pcms = simple_playback_build_pcms, + .init = via_hdmi_init, + .free = simple_playback_free, +}; + +static struct hda_pcm_stream via_hdmi_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = VIAHDMI_CVT_NID, /* NID to query formats and rates*/ + .ops = { + .open = simple_playback_pcm_open, + .close = simple_playback_pcm_close, + .prepare = simple_playback_pcm_prepare + }, +}; + +static int patch_via_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ + spec->num_cvts = 1; + spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; + spec->pins[0].pin_nid = VIAHDMI_PIN_NID; + spec->pcm_playback = &via_hdmi_digital_playback; + + codec->spec = spec; + codec->patch_ops = via_hdmi_patch_ops; + + return 0; +} /* * patch entries @@ -1904,6 +1960,10 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, +{ .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, +{ .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, +{ .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, @@ -1950,6 +2010,10 @@ MODULE_ALIAS("snd-hda-codec-id:10de0043"); MODULE_ALIAS("snd-hda-codec-id:10de0044"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); +MODULE_ALIAS("snd-hda-codec-id:11069f80"); +MODULE_ALIAS("snd-hda-codec-id:11069f81"); +MODULE_ALIAS("snd-hda-codec-id:11069f84"); +MODULE_ALIAS("snd-hda-codec-id:11069f85"); MODULE_ALIAS("snd-hda-codec-id:17e80047"); MODULE_ALIAS("snd-hda-codec-id:80860054"); MODULE_ALIAS("snd-hda-codec-id:80862801"); -- GitLab From b71dad181a55d2ad90bd03cd3216a5a8a31d9468 Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 9 Jun 2012 13:16:38 +0100 Subject: [PATCH 0418/5711] ALSA: usb-audio: Use a table of mixer controls Allow mixer controls to be provided clearly in a table, to avoid quantity of error checking at each use. Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 105 ++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b6911920..ce7d96f91578 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,13 @@ extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; +struct std_mono_table { + unsigned int unitid, control, cmask; + int val_type; + const char *name; + snd_kcontrol_tlv_rw_t *tlv_callback; +}; + /* private_free callback */ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) { @@ -113,6 +120,25 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, return 0; } +/* + * Create a set of standard UAC controls from a table + */ +static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, + struct std_mono_table *t) +{ + int err; + + while (t->name != NULL) { + err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, + t->cmask, t->val_type, t->name, t->tlv_callback); + if (err < 0) + return err; + t++; + } + + return 0; +} + /* * Sound Blaster remote control configuration * @@ -916,61 +942,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; } - -/* - * Create mixer for Electrix Ebox-44 - * - * The mixer units from this device are corrupt, and even where they - * are valid they presents mono controls as L and R channels of - * stereo. So we create a good mixer in code. - */ - -static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) -{ - int err; - - err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Headphone Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, - "Headphone A Mix Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, - "Headphone B Mix Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Output Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, - "Output A Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, - "Output B Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Input Capture Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, - "Input A Capture Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, - "Input B Capture Volume", NULL); - if (err < 0) - return err; - - return 0; -} - void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -990,6 +961,27 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } } +/* + * The mixer units for Ebox-44 are corrupt, and even where they + * are valid they presents mono controls as L and R channels of + * stereo. So we provide a good mixer here. + */ +struct std_mono_table ebox44_table[] = { + { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL }, + { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL }, + { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL }, + + { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL }, + { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL }, + { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL }, + + { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL }, + { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL }, + { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL }, + + { } +}; + int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1035,7 +1027,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break; case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ - err = snd_ebox44_create_mixer(mixer); + /* detection is disabled in mixer_maps.c */ + err = snd_create_std_mono_table(mixer, ebox44_table); break; } -- GitLab From 989b01385fa3cc4eaa488068a0868ae4de5198a9 Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 9 Jun 2012 13:16:39 +0100 Subject: [PATCH 0419/5711] ALSA: usb-audio: Convert table to preferred C99 format Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 74 ++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ce7d96f91578..690000db0ec0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -967,19 +967,73 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, * stereo. So we provide a good mixer here. */ struct std_mono_table ebox44_table[] = { - { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL }, - { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL }, - { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL }, + { + .unitid = 4, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Headphone Playback Switch" + }, + { + .unitid = 4, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Headphone A Mix Playback Volume" + }, + { + .unitid = 4, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Headphone B Mix Playback Volume" + }, - { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL }, - { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL }, - { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL }, + { + .unitid = 7, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Output Playback Switch" + }, + { + .unitid = 7, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Output A Playback Volume" + }, + { + .unitid = 7, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Output B Playback Volume" + }, - { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL }, - { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL }, - { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL }, + { + .unitid = 10, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Input Capture Switch" + }, + { + .unitid = 10, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Input A Capture Volume" + }, + { + .unitid = 10, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Input B Capture Volume" + }, - { } + {} }; int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) -- GitLab From a4808147dcf1ecf2f76212a78fd9692b3c112f47 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 11 Jun 2012 13:16:35 +0100 Subject: [PATCH 0420/5711] seq_file: Add seq_vprintf function and export it The existing seq_printf function is rewritten in terms of the new seq_vprintf which is also exported to modules. This allows GFS2 (and potentially other seq_file users) to have a vprintf based interface and to avoid an extra copy into a temporary buffer in some cases. Signed-off-by: Steven Whitehouse Reported-by: Eric Dumazet Acked-by: Al Viro --- fs/seq_file.c | 18 ++++++++++++++---- include/linux/seq_file.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/seq_file.c b/fs/seq_file.c index 0cbd0494b79e..14cf9de1dbe1 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -385,15 +385,12 @@ int seq_escape(struct seq_file *m, const char *s, const char *esc) } EXPORT_SYMBOL(seq_escape); -int seq_printf(struct seq_file *m, const char *f, ...) +int seq_vprintf(struct seq_file *m, const char *f, va_list args) { - va_list args; int len; if (m->count < m->size) { - va_start(args, f); len = vsnprintf(m->buf + m->count, m->size - m->count, f, args); - va_end(args); if (m->count + len < m->size) { m->count += len; return 0; @@ -402,6 +399,19 @@ int seq_printf(struct seq_file *m, const char *f, ...) seq_set_overflow(m); return -1; } +EXPORT_SYMBOL(seq_vprintf); + +int seq_printf(struct seq_file *m, const char *f, ...) +{ + int ret; + va_list args; + + va_start(args, f); + ret = seq_vprintf(m, f, args); + va_end(args); + + return ret; +} EXPORT_SYMBOL(seq_printf); /** diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index fc61854f6224..83c44eefe698 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -86,6 +86,7 @@ int seq_puts(struct seq_file *m, const char *s); int seq_write(struct seq_file *seq, const void *data, size_t len); __printf(2, 3) int seq_printf(struct seq_file *, const char *, ...); +__printf(2, 0) int seq_vprintf(struct seq_file *, const char *, va_list args); int seq_path(struct seq_file *, const struct path *, const char *); int seq_dentry(struct seq_file *, struct dentry *, const char *); -- GitLab From 66c2b7377a7cf22c48ebba7fdff5340ab492b7bc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 11 Jun 2012 18:09:46 +0800 Subject: [PATCH 0421/5711] ASoC: wm8996: Remove write sequencer registers from the defaults table They aren't marked as readable and the feature is never used so they'll never get referenced. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 178 -------------------------------------- 1 file changed, 178 deletions(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index efc4e9d0903b..f24989f090ca 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = { { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, - { WM8996_WRITE_SEQUENCER_0, 0x1 }, - { WM8996_WRITE_SEQUENCER_1, 0x1 }, - { WM8996_WRITE_SEQUENCER_3, 0x6 }, - { WM8996_WRITE_SEQUENCER_4, 0x40 }, - { WM8996_WRITE_SEQUENCER_5, 0x1 }, - { WM8996_WRITE_SEQUENCER_6, 0xf }, - { WM8996_WRITE_SEQUENCER_7, 0x6 }, - { WM8996_WRITE_SEQUENCER_8, 0x1 }, - { WM8996_WRITE_SEQUENCER_9, 0x3 }, - { WM8996_WRITE_SEQUENCER_10, 0x104 }, - { WM8996_WRITE_SEQUENCER_12, 0x60 }, - { WM8996_WRITE_SEQUENCER_13, 0x11 }, - { WM8996_WRITE_SEQUENCER_14, 0x401 }, - { WM8996_WRITE_SEQUENCER_16, 0x50 }, - { WM8996_WRITE_SEQUENCER_17, 0x3 }, - { WM8996_WRITE_SEQUENCER_18, 0x100 }, - { WM8996_WRITE_SEQUENCER_20, 0x51 }, - { WM8996_WRITE_SEQUENCER_21, 0x3 }, - { WM8996_WRITE_SEQUENCER_22, 0x104 }, - { WM8996_WRITE_SEQUENCER_23, 0xa }, - { WM8996_WRITE_SEQUENCER_24, 0x60 }, - { WM8996_WRITE_SEQUENCER_25, 0x3b }, - { WM8996_WRITE_SEQUENCER_26, 0x502 }, - { WM8996_WRITE_SEQUENCER_27, 0x100 }, - { WM8996_WRITE_SEQUENCER_28, 0x2fff }, - { WM8996_WRITE_SEQUENCER_32, 0x2fff }, - { WM8996_WRITE_SEQUENCER_36, 0x2fff }, - { WM8996_WRITE_SEQUENCER_40, 0x2fff }, - { WM8996_WRITE_SEQUENCER_44, 0x2fff }, - { WM8996_WRITE_SEQUENCER_48, 0x2fff }, - { WM8996_WRITE_SEQUENCER_52, 0x2fff }, - { WM8996_WRITE_SEQUENCER_56, 0x2fff }, - { WM8996_WRITE_SEQUENCER_60, 0x2fff }, - { WM8996_WRITE_SEQUENCER_64, 0x1 }, - { WM8996_WRITE_SEQUENCER_65, 0x1 }, - { WM8996_WRITE_SEQUENCER_67, 0x6 }, - { WM8996_WRITE_SEQUENCER_68, 0x40 }, - { WM8996_WRITE_SEQUENCER_69, 0x1 }, - { WM8996_WRITE_SEQUENCER_70, 0xf }, - { WM8996_WRITE_SEQUENCER_71, 0x6 }, - { WM8996_WRITE_SEQUENCER_72, 0x1 }, - { WM8996_WRITE_SEQUENCER_73, 0x3 }, - { WM8996_WRITE_SEQUENCER_74, 0x104 }, - { WM8996_WRITE_SEQUENCER_76, 0x60 }, - { WM8996_WRITE_SEQUENCER_77, 0x11 }, - { WM8996_WRITE_SEQUENCER_78, 0x401 }, - { WM8996_WRITE_SEQUENCER_80, 0x50 }, - { WM8996_WRITE_SEQUENCER_81, 0x3 }, - { WM8996_WRITE_SEQUENCER_82, 0x100 }, - { WM8996_WRITE_SEQUENCER_84, 0x60 }, - { WM8996_WRITE_SEQUENCER_85, 0x3b }, - { WM8996_WRITE_SEQUENCER_86, 0x502 }, - { WM8996_WRITE_SEQUENCER_87, 0x100 }, - { WM8996_WRITE_SEQUENCER_88, 0x2fff }, - { WM8996_WRITE_SEQUENCER_92, 0x2fff }, - { WM8996_WRITE_SEQUENCER_96, 0x2fff }, - { WM8996_WRITE_SEQUENCER_100, 0x2fff }, - { WM8996_WRITE_SEQUENCER_104, 0x2fff }, - { WM8996_WRITE_SEQUENCER_108, 0x2fff }, - { WM8996_WRITE_SEQUENCER_112, 0x2fff }, - { WM8996_WRITE_SEQUENCER_116, 0x2fff }, - { WM8996_WRITE_SEQUENCER_120, 0x2fff }, - { WM8996_WRITE_SEQUENCER_124, 0x2fff }, - { WM8996_WRITE_SEQUENCER_128, 0x1 }, - { WM8996_WRITE_SEQUENCER_129, 0x1 }, - { WM8996_WRITE_SEQUENCER_131, 0x6 }, - { WM8996_WRITE_SEQUENCER_132, 0x40 }, - { WM8996_WRITE_SEQUENCER_133, 0x1 }, - { WM8996_WRITE_SEQUENCER_134, 0xf }, - { WM8996_WRITE_SEQUENCER_135, 0x6 }, - { WM8996_WRITE_SEQUENCER_136, 0x1 }, - { WM8996_WRITE_SEQUENCER_137, 0x3 }, - { WM8996_WRITE_SEQUENCER_138, 0x106 }, - { WM8996_WRITE_SEQUENCER_140, 0x61 }, - { WM8996_WRITE_SEQUENCER_141, 0x11 }, - { WM8996_WRITE_SEQUENCER_142, 0x401 }, - { WM8996_WRITE_SEQUENCER_144, 0x50 }, - { WM8996_WRITE_SEQUENCER_145, 0x3 }, - { WM8996_WRITE_SEQUENCER_146, 0x102 }, - { WM8996_WRITE_SEQUENCER_148, 0x51 }, - { WM8996_WRITE_SEQUENCER_149, 0x3 }, - { WM8996_WRITE_SEQUENCER_150, 0x106 }, - { WM8996_WRITE_SEQUENCER_151, 0xa }, - { WM8996_WRITE_SEQUENCER_152, 0x61 }, - { WM8996_WRITE_SEQUENCER_153, 0x3b }, - { WM8996_WRITE_SEQUENCER_154, 0x502 }, - { WM8996_WRITE_SEQUENCER_155, 0x100 }, - { WM8996_WRITE_SEQUENCER_156, 0x2fff }, - { WM8996_WRITE_SEQUENCER_160, 0x2fff }, - { WM8996_WRITE_SEQUENCER_164, 0x2fff }, - { WM8996_WRITE_SEQUENCER_168, 0x2fff }, - { WM8996_WRITE_SEQUENCER_172, 0x2fff }, - { WM8996_WRITE_SEQUENCER_176, 0x2fff }, - { WM8996_WRITE_SEQUENCER_180, 0x2fff }, - { WM8996_WRITE_SEQUENCER_184, 0x2fff }, - { WM8996_WRITE_SEQUENCER_188, 0x2fff }, - { WM8996_WRITE_SEQUENCER_192, 0x1 }, - { WM8996_WRITE_SEQUENCER_193, 0x1 }, - { WM8996_WRITE_SEQUENCER_195, 0x6 }, - { WM8996_WRITE_SEQUENCER_196, 0x40 }, - { WM8996_WRITE_SEQUENCER_197, 0x1 }, - { WM8996_WRITE_SEQUENCER_198, 0xf }, - { WM8996_WRITE_SEQUENCER_199, 0x6 }, - { WM8996_WRITE_SEQUENCER_200, 0x1 }, - { WM8996_WRITE_SEQUENCER_201, 0x3 }, - { WM8996_WRITE_SEQUENCER_202, 0x106 }, - { WM8996_WRITE_SEQUENCER_204, 0x61 }, - { WM8996_WRITE_SEQUENCER_205, 0x11 }, - { WM8996_WRITE_SEQUENCER_206, 0x401 }, - { WM8996_WRITE_SEQUENCER_208, 0x50 }, - { WM8996_WRITE_SEQUENCER_209, 0x3 }, - { WM8996_WRITE_SEQUENCER_210, 0x102 }, - { WM8996_WRITE_SEQUENCER_212, 0x61 }, - { WM8996_WRITE_SEQUENCER_213, 0x3b }, - { WM8996_WRITE_SEQUENCER_214, 0x502 }, - { WM8996_WRITE_SEQUENCER_215, 0x100 }, - { WM8996_WRITE_SEQUENCER_216, 0x2fff }, - { WM8996_WRITE_SEQUENCER_220, 0x2fff }, - { WM8996_WRITE_SEQUENCER_224, 0x2fff }, - { WM8996_WRITE_SEQUENCER_228, 0x2fff }, - { WM8996_WRITE_SEQUENCER_232, 0x2fff }, - { WM8996_WRITE_SEQUENCER_236, 0x2fff }, - { WM8996_WRITE_SEQUENCER_240, 0x2fff }, - { WM8996_WRITE_SEQUENCER_244, 0x2fff }, - { WM8996_WRITE_SEQUENCER_248, 0x2fff }, - { WM8996_WRITE_SEQUENCER_252, 0x2fff }, - { WM8996_WRITE_SEQUENCER_256, 0x60 }, - { WM8996_WRITE_SEQUENCER_258, 0x601 }, - { WM8996_WRITE_SEQUENCER_260, 0x50 }, - { WM8996_WRITE_SEQUENCER_262, 0x100 }, - { WM8996_WRITE_SEQUENCER_264, 0x1 }, - { WM8996_WRITE_SEQUENCER_266, 0x104 }, - { WM8996_WRITE_SEQUENCER_267, 0x100 }, - { WM8996_WRITE_SEQUENCER_268, 0x2fff }, - { WM8996_WRITE_SEQUENCER_272, 0x2fff }, - { WM8996_WRITE_SEQUENCER_276, 0x2fff }, - { WM8996_WRITE_SEQUENCER_280, 0x2fff }, - { WM8996_WRITE_SEQUENCER_284, 0x2fff }, - { WM8996_WRITE_SEQUENCER_288, 0x2fff }, - { WM8996_WRITE_SEQUENCER_292, 0x2fff }, - { WM8996_WRITE_SEQUENCER_296, 0x2fff }, - { WM8996_WRITE_SEQUENCER_300, 0x2fff }, - { WM8996_WRITE_SEQUENCER_304, 0x2fff }, - { WM8996_WRITE_SEQUENCER_308, 0x2fff }, - { WM8996_WRITE_SEQUENCER_312, 0x2fff }, - { WM8996_WRITE_SEQUENCER_316, 0x2fff }, - { WM8996_WRITE_SEQUENCER_320, 0x61 }, - { WM8996_WRITE_SEQUENCER_322, 0x601 }, - { WM8996_WRITE_SEQUENCER_324, 0x50 }, - { WM8996_WRITE_SEQUENCER_326, 0x102 }, - { WM8996_WRITE_SEQUENCER_328, 0x1 }, - { WM8996_WRITE_SEQUENCER_330, 0x106 }, - { WM8996_WRITE_SEQUENCER_331, 0x100 }, - { WM8996_WRITE_SEQUENCER_332, 0x2fff }, - { WM8996_WRITE_SEQUENCER_336, 0x2fff }, - { WM8996_WRITE_SEQUENCER_340, 0x2fff }, - { WM8996_WRITE_SEQUENCER_344, 0x2fff }, - { WM8996_WRITE_SEQUENCER_348, 0x2fff }, - { WM8996_WRITE_SEQUENCER_352, 0x2fff }, - { WM8996_WRITE_SEQUENCER_356, 0x2fff }, - { WM8996_WRITE_SEQUENCER_360, 0x2fff }, - { WM8996_WRITE_SEQUENCER_364, 0x2fff }, - { WM8996_WRITE_SEQUENCER_368, 0x2fff }, - { WM8996_WRITE_SEQUENCER_372, 0x2fff }, - { WM8996_WRITE_SEQUENCER_376, 0x2fff }, - { WM8996_WRITE_SEQUENCER_380, 0x2fff }, - { WM8996_WRITE_SEQUENCER_384, 0x60 }, - { WM8996_WRITE_SEQUENCER_386, 0x601 }, - { WM8996_WRITE_SEQUENCER_388, 0x61 }, - { WM8996_WRITE_SEQUENCER_390, 0x601 }, - { WM8996_WRITE_SEQUENCER_392, 0x50 }, - { WM8996_WRITE_SEQUENCER_394, 0x300 }, - { WM8996_WRITE_SEQUENCER_396, 0x1 }, - { WM8996_WRITE_SEQUENCER_398, 0x304 }, - { WM8996_WRITE_SEQUENCER_400, 0x40 }, - { WM8996_WRITE_SEQUENCER_402, 0xf }, - { WM8996_WRITE_SEQUENCER_404, 0x1 }, - { WM8996_WRITE_SEQUENCER_407, 0x100 }, }; static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); -- GitLab From af691fb62c626fe374955ab306092b09f672e27d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 11 Jun 2012 18:20:48 +0800 Subject: [PATCH 0422/5711] ASoC: wm8996: Convert to devm_regmap_init_i2c() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index f24989f090ca..a6b5cffa498a 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -3000,7 +3000,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, msleep(5); } - wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); + wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap); if (IS_ERR(wm8996->regmap)) { ret = PTR_ERR(wm8996->regmap); dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); @@ -3049,7 +3049,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, err_gpiolib: wm8996_free_gpio(wm8996); err_regmap: - regmap_exit(wm8996->regmap); err_enable: if (wm8996->pdata.ldo_ena > 0) gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); @@ -3068,7 +3067,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client) snd_soc_unregister_codec(&client->dev); wm8996_free_gpio(wm8996); - regmap_exit(wm8996->regmap); if (wm8996->pdata.ldo_ena > 0) { gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); gpio_free(wm8996->pdata.ldo_ena); -- GitLab From 48e278746070b5fc62ec3da2e65f7cd511f6bbf4 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 11 Jun 2012 13:15:27 +0100 Subject: [PATCH 0423/5711] ASoC: codecs: Add DA732x codec driver This patch adds support for Dialog DA732x audio codecs. Signed-off-by: Michal Hajduk Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/da732x.c | 1627 +++++++++++++++++++++++++++++++++ sound/soc/codecs/da732x.h | 133 +++ sound/soc/codecs/da732x_reg.h | 654 +++++++++++++ 5 files changed, 2420 insertions(+) create mode 100644 sound/soc/codecs/da732x.c create mode 100644 sound/soc/codecs/da732x.h create mode 100644 sound/soc/codecs/da732x_reg.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f63776d422b3..43f5240e6942 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -36,6 +36,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI select SND_SOC_CX20442 select SND_SOC_DA7210 if I2C + select SND_SOC_DA732X if I2C select SND_SOC_DFBMCS320 select SND_SOC_ISABELLE if I2C select SND_SOC_JZ4740_CODEC @@ -224,6 +225,9 @@ config SND_SOC_L3 config SND_SOC_DA7210 tristate +config SND_SOC_DA732X + tristate + config SND_SOC_DFBMCS320 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fc93b4b0c2c5..3d30654f6fcc 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -22,6 +22,7 @@ snd-soc-cs4270-objs := cs4270.o snd-soc-cs4271-objs := cs4271.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o +snd-soc-da732x-objs := da732x.o snd-soc-dfbmcs320-objs := dfbmcs320.o snd-soc-dmic-objs := dmic.o snd-soc-isabelle-objs := isabelle.o @@ -135,6 +136,7 @@ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o +obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c new file mode 100644 index 000000000000..04af369f228c --- /dev/null +++ b/sound/soc/codecs/da732x.c @@ -0,0 +1,1627 @@ +/* + * da732x.c --- Dialog DA732X ALSA SoC Audio Driver + * + * Copyright (C) 2012 Dialog Semiconductor GmbH + * + * Author: Michal Hajduk + * + * 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 +#include +#include + +#include "da732x.h" +#include "da732x_reg.h" + + +struct da732x_priv { + struct regmap *regmap; + struct snd_soc_codec *codec; + + unsigned int sysclk; + bool pll_en; +}; + +/* + * da732x register cache - default settings + */ +static struct reg_default da732x_reg_cache[] = { + { DA732X_REG_REF1 , 0x02 }, + { DA732X_REG_BIAS_EN , 0x80 }, + { DA732X_REG_BIAS1 , 0x00 }, + { DA732X_REG_BIAS2 , 0x00 }, + { DA732X_REG_BIAS3 , 0x00 }, + { DA732X_REG_BIAS4 , 0x00 }, + { DA732X_REG_MICBIAS2 , 0x00 }, + { DA732X_REG_MICBIAS1 , 0x00 }, + { DA732X_REG_MICDET , 0x00 }, + { DA732X_REG_MIC1_PRE , 0x01 }, + { DA732X_REG_MIC1 , 0x40 }, + { DA732X_REG_MIC2_PRE , 0x01 }, + { DA732X_REG_MIC2 , 0x40 }, + { DA732X_REG_AUX1L , 0x75 }, + { DA732X_REG_AUX1R , 0x75 }, + { DA732X_REG_MIC3_PRE , 0x01 }, + { DA732X_REG_MIC3 , 0x40 }, + { DA732X_REG_INP_PINBIAS , 0x00 }, + { DA732X_REG_INP_ZC_EN , 0x00 }, + { DA732X_REG_INP_MUX , 0x50 }, + { DA732X_REG_HP_DET , 0x00 }, + { DA732X_REG_HPL_DAC_OFFSET , 0x00 }, + { DA732X_REG_HPL_DAC_OFF_CNTL , 0x00 }, + { DA732X_REG_HPL_OUT_OFFSET , 0x00 }, + { DA732X_REG_HPL , 0x40 }, + { DA732X_REG_HPL_VOL , 0x0F }, + { DA732X_REG_HPR_DAC_OFFSET , 0x00 }, + { DA732X_REG_HPR_DAC_OFF_CNTL , 0x00 }, + { DA732X_REG_HPR_OUT_OFFSET , 0x00 }, + { DA732X_REG_HPR , 0x40 }, + { DA732X_REG_HPR_VOL , 0x0F }, + { DA732X_REG_LIN2 , 0x4F }, + { DA732X_REG_LIN3 , 0x4F }, + { DA732X_REG_LIN4 , 0x4F }, + { DA732X_REG_OUT_ZC_EN , 0x00 }, + { DA732X_REG_HP_LIN1_GNDSEL , 0x00 }, + { DA732X_REG_CP_HP1 , 0x0C }, + { DA732X_REG_CP_HP2 , 0x03 }, + { DA732X_REG_CP_CTRL1 , 0x00 }, + { DA732X_REG_CP_CTRL2 , 0x99 }, + { DA732X_REG_CP_CTRL3 , 0x25 }, + { DA732X_REG_CP_LEVEL_MASK , 0x3F }, + { DA732X_REG_CP_DET , 0x00 }, + { DA732X_REG_CP_STATUS , 0x00 }, + { DA732X_REG_CP_THRESH1 , 0x00 }, + { DA732X_REG_CP_THRESH2 , 0x00 }, + { DA732X_REG_CP_THRESH3 , 0x00 }, + { DA732X_REG_CP_THRESH4 , 0x00 }, + { DA732X_REG_CP_THRESH5 , 0x00 }, + { DA732X_REG_CP_THRESH6 , 0x00 }, + { DA732X_REG_CP_THRESH7 , 0x00 }, + { DA732X_REG_CP_THRESH8 , 0x00 }, + { DA732X_REG_PLL_DIV_LO , 0x00 }, + { DA732X_REG_PLL_DIV_MID , 0x00 }, + { DA732X_REG_PLL_DIV_HI , 0x00 }, + { DA732X_REG_PLL_CTRL , 0x02 }, + { DA732X_REG_CLK_CTRL , 0xaa }, + { DA732X_REG_CLK_DSP , 0x07 }, + { DA732X_REG_CLK_EN1 , 0x00 }, + { DA732X_REG_CLK_EN2 , 0x00 }, + { DA732X_REG_CLK_EN3 , 0x00 }, + { DA732X_REG_CLK_EN4 , 0x00 }, + { DA732X_REG_CLK_EN5 , 0x00 }, + { DA732X_REG_AIF_MCLK , 0x00 }, + { DA732X_REG_AIFA1 , 0x02 }, + { DA732X_REG_AIFA2 , 0x00 }, + { DA732X_REG_AIFA3 , 0x08 }, + { DA732X_REG_AIFB1 , 0x02 }, + { DA732X_REG_AIFB2 , 0x00 }, + { DA732X_REG_AIFB3 , 0x08 }, + { DA732X_REG_PC_CTRL , 0xC0 }, + { DA732X_REG_DATA_ROUTE , 0x00 }, + { DA732X_REG_DSP_CTRL , 0x00 }, + { DA732X_REG_CIF_CTRL2 , 0x00 }, + { DA732X_REG_HANDSHAKE , 0x00 }, + { DA732X_REG_SPARE1_OUT , 0x00 }, + { DA732X_REG_SPARE2_OUT , 0x00 }, + { DA732X_REG_SPARE1_IN , 0x00 }, + { DA732X_REG_ADC1_PD , 0x00 }, + { DA732X_REG_ADC1_HPF , 0x00 }, + { DA732X_REG_ADC1_SEL , 0x00 }, + { DA732X_REG_ADC1_EQ12 , 0x00 }, + { DA732X_REG_ADC1_EQ34 , 0x00 }, + { DA732X_REG_ADC1_EQ5 , 0x00 }, + { DA732X_REG_ADC2_PD , 0x00 }, + { DA732X_REG_ADC2_HPF , 0x00 }, + { DA732X_REG_ADC2_SEL , 0x00 }, + { DA732X_REG_ADC2_EQ12 , 0x00 }, + { DA732X_REG_ADC2_EQ34 , 0x00 }, + { DA732X_REG_ADC2_EQ5 , 0x00 }, + { DA732X_REG_DAC1_HPF , 0x00 }, + { DA732X_REG_DAC1_L_VOL , 0x00 }, + { DA732X_REG_DAC1_R_VOL , 0x00 }, + { DA732X_REG_DAC1_SEL , 0x00 }, + { DA732X_REG_DAC1_SOFTMUTE , 0x00 }, + { DA732X_REG_DAC1_EQ12 , 0x00 }, + { DA732X_REG_DAC1_EQ34 , 0x00 }, + { DA732X_REG_DAC1_EQ5 , 0x00 }, + { DA732X_REG_DAC2_HPF , 0x00 }, + { DA732X_REG_DAC2_L_VOL , 0x00 }, + { DA732X_REG_DAC2_R_VOL , 0x00 }, + { DA732X_REG_DAC2_SEL , 0x00 }, + { DA732X_REG_DAC2_SOFTMUTE , 0x00 }, + { DA732X_REG_DAC2_EQ12 , 0x00 }, + { DA732X_REG_DAC2_EQ34 , 0x00 }, + { DA732X_REG_DAC2_EQ5 , 0x00 }, + { DA732X_REG_DAC3_HPF , 0x00 }, + { DA732X_REG_DAC3_VOL , 0x00 }, + { DA732X_REG_DAC3_SEL , 0x00 }, + { DA732X_REG_DAC3_SOFTMUTE , 0x00 }, + { DA732X_REG_DAC3_EQ12 , 0x00 }, + { DA732X_REG_DAC3_EQ34 , 0x00 }, + { DA732X_REG_DAC3_EQ5 , 0x00 }, + { DA732X_REG_BIQ_BYP , 0x00 }, + { DA732X_REG_DMA_CMD , 0x00 }, + { DA732X_REG_DMA_ADDR0 , 0x00 }, + { DA732X_REG_DMA_ADDR1 , 0x00 }, + { DA732X_REG_DMA_DATA0 , 0x00 }, + { DA732X_REG_DMA_DATA1 , 0x00 }, + { DA732X_REG_DMA_DATA2 , 0x00 }, + { DA732X_REG_DMA_DATA3 , 0x00 }, + { DA732X_REG_UNLOCK , 0x00 }, +}; + +static inline int da732x_get_input_div(struct snd_soc_codec *codec, int sysclk) +{ + int val; + int ret; + + if (sysclk < DA732X_MCLK_10MHZ) { + val = DA732X_MCLK_RET_0_10MHZ; + ret = DA732X_MCLK_VAL_0_10MHZ; + } else if ((sysclk >= DA732X_MCLK_10MHZ) && + (sysclk < DA732X_MCLK_20MHZ)) { + val = DA732X_MCLK_RET_10_20MHZ; + ret = DA732X_MCLK_VAL_10_20MHZ; + } else if ((sysclk >= DA732X_MCLK_20MHZ) && + (sysclk < DA732X_MCLK_40MHZ)) { + val = DA732X_MCLK_RET_20_40MHZ; + ret = DA732X_MCLK_VAL_20_40MHZ; + } else if ((sysclk >= DA732X_MCLK_40MHZ) && + (sysclk <= DA732X_MCLK_54MHZ)) { + val = DA732X_MCLK_RET_40_54MHZ; + ret = DA732X_MCLK_VAL_40_54MHZ; + } else { + return -EINVAL; + } + + snd_soc_write(codec, DA732X_REG_PLL_CTRL, val); + + return ret; +} + +static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state) +{ + switch (state) { + case DA732X_ENABLE_CP: + snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_EN); + snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_EN | + DA732X_HP_CP_REG | DA732X_HP_CP_PULSESKIP); + snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA732X_CP_EN | + DA732X_CP_CTRL_CPVDD1); + snd_soc_write(codec, DA732X_REG_CP_CTRL2, + DA732X_CP_MANAGE_MAGNITUDE | DA732X_CP_BOOST); + snd_soc_write(codec, DA732X_REG_CP_CTRL3, DA732X_CP_1MHZ); + break; + case DA732X_DISABLE_CP: + snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_DIS); + snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_DIS); + snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS); + break; + default: + pr_err(KERN_ERR "Wrong charge pump state\n"); + break; + } +} + +static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, DA732X_MIC_PRE_VOL_DB_MIN, + DA732X_MIC_PRE_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, DA732X_MIC_VOL_DB_MIN, + DA732X_MIC_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(aux_pga_tlv, DA732X_AUX_VOL_DB_MIN, + DA732X_AUX_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(hp_pga_tlv, DA732X_HP_VOL_DB_MIN, + DA732X_AUX_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(lin2_pga_tlv, DA732X_LIN2_VOL_DB_MIN, + DA732X_LIN2_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(lin3_pga_tlv, DA732X_LIN3_VOL_DB_MIN, + DA732X_LIN3_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(lin4_pga_tlv, DA732X_LIN4_VOL_DB_MIN, + DA732X_LIN4_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(adc_pga_tlv, DA732X_ADC_VOL_DB_MIN, + DA732X_ADC_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(dac_pga_tlv, DA732X_DAC_VOL_DB_MIN, + DA732X_DAC_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(eq_band_pga_tlv, DA732X_EQ_BAND_VOL_DB_MIN, + DA732X_EQ_BAND_VOL_DB_INC, 0); + +static const DECLARE_TLV_DB_SCALE(eq_overall_tlv, DA732X_EQ_OVERALL_VOL_DB_MIN, + DA732X_EQ_OVERALL_VOL_DB_INC, 0); + +/* High Pass Filter */ +static const char *da732x_hpf_mode[] = { + "Disable", "Music", "Voice", +}; + +static const char *da732x_hpf_music[] = { + "1.8Hz", "3.75Hz", "7.5Hz", "15Hz", +}; + +static const char *da732x_hpf_voice[] = { + "2.5Hz", "25Hz", "50Hz", "100Hz", + "150Hz", "200Hz", "300Hz", "400Hz" +}; + +static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, + DA732X_HPF_MODE_MAX, da732x_hpf_mode) +}; + +static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, + DA732X_HPF_MODE_MAX, da732x_hpf_mode) +}; + +static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, + DA732X_HPF_MODE_MAX, da732x_hpf_mode) +}; + +static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, + DA732X_HPF_MODE_MAX, da732x_hpf_mode) +}; + +static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, + DA732X_HPF_MODE_MAX, da732x_hpf_mode) +}; + +static const struct soc_enum da732x_dac1_hp_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) +}; + +static const struct soc_enum da732x_dac2_hp_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) +}; + +static const struct soc_enum da732x_dac3_hp_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) +}; + +static const struct soc_enum da732x_adc1_hp_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) +}; + +static const struct soc_enum da732x_adc2_hp_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) +}; + +static const struct soc_enum da732x_dac1_voice_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) +}; + +static const struct soc_enum da732x_dac2_voice_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) +}; + +static const struct soc_enum da732x_dac3_voice_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) +}; + +static const struct soc_enum da732x_adc1_voice_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) +}; + +static const struct soc_enum da732x_adc2_voice_filter_enum[] = { + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) +}; + + +static int da732x_hpf_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; + unsigned int reg = enum_ctrl->reg; + unsigned int sel = ucontrol->value.integer.value[0]; + unsigned int bits; + + switch (sel) { + case DA732X_HPF_DISABLED: + bits = DA732X_HPF_DIS; + break; + case DA732X_HPF_VOICE: + bits = DA732X_HPF_VOICE_EN; + break; + case DA732X_HPF_MUSIC: + bits = DA732X_HPF_MUSIC_EN; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, reg, DA732X_HPF_MASK, bits); + + return 0; +} + +static int da732x_hpf_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; + unsigned int reg = enum_ctrl->reg; + int val; + + val = snd_soc_read(codec, reg) & DA732X_HPF_MASK; + + switch (val) { + case DA732X_HPF_VOICE_EN: + ucontrol->value.integer.value[0] = DA732X_HPF_VOICE; + break; + case DA732X_HPF_MUSIC_EN: + ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC; + break; + default: + ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED; + break; + } + + return 0; +} + +static const struct snd_kcontrol_new da732x_snd_controls[] = { + /* Input PGAs */ + SOC_SINGLE_RANGE_TLV("MIC1 Boost Volume", DA732X_REG_MIC1_PRE, + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), + SOC_SINGLE_RANGE_TLV("MIC2 Boost Volume", DA732X_REG_MIC2_PRE, + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), + SOC_SINGLE_RANGE_TLV("MIC3 Boost Volume", DA732X_REG_MIC3_PRE, + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), + + /* MICs */ + SOC_SINGLE("MIC1 Switch", DA732X_REG_MIC1, DA732X_MIC_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_RANGE_TLV("MIC1 Volume", DA732X_REG_MIC1, + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), + SOC_SINGLE("MIC2 Switch", DA732X_REG_MIC2, DA732X_MIC_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_RANGE_TLV("MIC2 Volume", DA732X_REG_MIC2, + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), + SOC_SINGLE("MIC3 Switch", DA732X_REG_MIC3, DA732X_MIC_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_RANGE_TLV("MIC3 Volume", DA732X_REG_MIC3, + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), + + /* AUXs */ + SOC_SINGLE("AUX1L Switch", DA732X_REG_AUX1L, DA732X_AUX_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("AUX1L Volume", DA732X_REG_AUX1L, + DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, + DA732X_NO_INVERT, aux_pga_tlv), + SOC_SINGLE("AUX1R Switch", DA732X_REG_AUX1R, DA732X_AUX_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("AUX1R Volume", DA732X_REG_AUX1R, + DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, + DA732X_NO_INVERT, aux_pga_tlv), + + /* ADCs */ + SOC_DOUBLE_TLV("ADC1 Volume", DA732X_REG_ADC1_SEL, + DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, + DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), + + SOC_DOUBLE_TLV("ADC2 Volume", DA732X_REG_ADC2_SEL, + DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, + DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), + + /* DACs */ + SOC_DOUBLE("Digital Playback DAC12 Switch", DA732X_REG_DAC1_SEL, + DA732X_DACL_MUTE_SHIFT, DA732X_DACR_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_DOUBLE_R_TLV("Digital Playback DAC12 Volume", DA732X_REG_DAC1_L_VOL, + DA732X_REG_DAC1_R_VOL, DA732X_DAC_VOL_SHIFT, + DA732X_DAC_VOL_VAL_MAX, DA732X_INVERT, dac_pga_tlv), + SOC_SINGLE("Digital Playback DAC3 Switch", DA732X_REG_DAC2_SEL, + DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Digital Playback DAC3 Volume", DA732X_REG_DAC2_L_VOL, + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, + DA732X_INVERT, dac_pga_tlv), + SOC_SINGLE("Digital Playback DAC4 Switch", DA732X_REG_DAC2_SEL, + DA732X_DACR_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Digital Playback DAC4 Volume", DA732X_REG_DAC2_R_VOL, + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, + DA732X_INVERT, dac_pga_tlv), + SOC_SINGLE("Digital Playback DAC5 Switch", DA732X_REG_DAC3_SEL, + DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Digital Playback DAC5 Volume", DA732X_REG_DAC3_VOL, + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, + DA732X_INVERT, dac_pga_tlv), + + /* High Pass Filters */ + SOC_ENUM_EXT("DAC1 High Pass Filter Mode", + da732x_dac1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), + SOC_ENUM("DAC1 High Pass Filter", da732x_dac1_hp_filter_enum), + SOC_ENUM("DAC1 Voice Filter", da732x_dac1_voice_filter_enum), + + SOC_ENUM_EXT("DAC2 High Pass Filter Mode", + da732x_dac2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), + SOC_ENUM("DAC2 High Pass Filter", da732x_dac2_hp_filter_enum), + SOC_ENUM("DAC2 Voice Filter", da732x_dac2_voice_filter_enum), + + SOC_ENUM_EXT("DAC3 High Pass Filter Mode", + da732x_dac3_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), + SOC_ENUM("DAC3 High Pass Filter", da732x_dac3_hp_filter_enum), + SOC_ENUM("DAC3 Filter Mode", da732x_dac3_voice_filter_enum), + + SOC_ENUM_EXT("ADC1 High Pass Filter Mode", + da732x_adc1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), + SOC_ENUM("ADC1 High Pass Filter", da732x_adc1_hp_filter_enum), + SOC_ENUM("ADC1 Voice Filter", da732x_adc1_voice_filter_enum), + + SOC_ENUM_EXT("ADC2 High Pass Filter Mode", + da732x_adc2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), + SOC_ENUM("ADC2 High Pass Filter", da732x_adc2_hp_filter_enum), + SOC_ENUM("ADC2 Voice Filter", da732x_adc2_voice_filter_enum), + + /* Equalizers */ + SOC_SINGLE("ADC1 EQ Switch", DA732X_REG_ADC1_EQ5, + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), + SOC_SINGLE_TLV("ADC1 EQ Band 1 Volume", DA732X_REG_ADC1_EQ12, + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC1 EQ Band 2 Volume", DA732X_REG_ADC1_EQ12, + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC1 EQ Band 3 Volume", DA732X_REG_ADC1_EQ34, + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC1 EQ Band 4 Volume", DA732X_REG_ADC1_EQ34, + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC1 EQ Band 5 Volume", DA732X_REG_ADC1_EQ5, + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC1 EQ Overall Volume", DA732X_REG_ADC1_EQ5, + DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, + DA732X_INVERT, eq_overall_tlv), + + SOC_SINGLE("ADC2 EQ Switch", DA732X_REG_ADC2_EQ5, + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), + SOC_SINGLE_TLV("ADC2 EQ Band 1 Volume", DA732X_REG_ADC2_EQ12, + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC2 EQ Band 2 Volume", DA732X_REG_ADC2_EQ12, + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC2 EQ Band 3 Volume", DA732X_REG_ADC2_EQ34, + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ACD2 EQ Band 4 Volume", DA732X_REG_ADC2_EQ34, + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ACD2 EQ Band 5 Volume", DA732X_REG_ADC2_EQ5, + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("ADC2 EQ Overall Volume", DA732X_REG_ADC1_EQ5, + DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, + DA732X_INVERT, eq_overall_tlv), + + SOC_SINGLE("DAC1 EQ Switch", DA732X_REG_DAC1_EQ5, + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), + SOC_SINGLE_TLV("DAC1 EQ Band 1 Volume", DA732X_REG_DAC1_EQ12, + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC1 EQ Band 2 Volume", DA732X_REG_DAC1_EQ12, + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC1 EQ Band 3 Volume", DA732X_REG_DAC1_EQ34, + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC1 EQ Band 4 Volume", DA732X_REG_DAC1_EQ34, + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC1 EQ Band 5 Volume", DA732X_REG_DAC1_EQ5, + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + + SOC_SINGLE("DAC2 EQ Switch", DA732X_REG_DAC2_EQ5, + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), + SOC_SINGLE_TLV("DAC2 EQ Band 1 Volume", DA732X_REG_DAC2_EQ12, + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC2 EQ Band 2 Volume", DA732X_REG_DAC2_EQ12, + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC2 EQ Band 3 Volume", DA732X_REG_DAC2_EQ34, + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC2 EQ Band 4 Volume", DA732X_REG_DAC2_EQ34, + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC2 EQ Band 5 Volume", DA732X_REG_DAC2_EQ5, + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + + SOC_SINGLE("DAC3 EQ Switch", DA732X_REG_DAC3_EQ5, + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), + SOC_SINGLE_TLV("DAC3 EQ Band 1 Volume", DA732X_REG_DAC3_EQ12, + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC3 EQ Band 2 Volume", DA732X_REG_DAC3_EQ12, + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC3 EQ Band 3 Volume", DA732X_REG_DAC3_EQ34, + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC3 EQ Band 4 Volume", DA732X_REG_DAC3_EQ34, + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + SOC_SINGLE_TLV("DAC3 EQ Band 5 Volume", DA732X_REG_DAC3_EQ5, + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, + DA732X_INVERT, eq_band_pga_tlv), + + /* Lineout 2 Reciever*/ + SOC_SINGLE("Lineout 2 Switch", DA732X_REG_LIN2, DA732X_LOUT_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Lineout 2 Volume", DA732X_REG_LIN2, + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, + DA732X_NO_INVERT, lin2_pga_tlv), + + /* Lineout 3 SPEAKER*/ + SOC_SINGLE("Lineout 3 Switch", DA732X_REG_LIN3, DA732X_LOUT_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Lineout 3 Volume", DA732X_REG_LIN3, + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, + DA732X_NO_INVERT, lin3_pga_tlv), + + /* Lineout 4 */ + SOC_SINGLE("Lineout 4 Switch", DA732X_REG_LIN4, DA732X_LOUT_MUTE_SHIFT, + DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_SINGLE_TLV("Lineout 4 Volume", DA732X_REG_LIN4, + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, + DA732X_NO_INVERT, lin4_pga_tlv), + + /* Headphones */ + SOC_DOUBLE_R("Headphone Switch", DA732X_REG_HPR, DA732X_REG_HPL, + DA732X_HP_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), + SOC_DOUBLE_R_TLV("Headphone Volume", DA732X_REG_HPL_VOL, + DA732X_REG_HPR_VOL, DA732X_HP_VOL_SHIFT, + DA732X_HP_VOL_VAL_MAX, DA732X_NO_INVERT, hp_pga_tlv), +}; + +static int da732x_adc_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + switch (w->reg) { + case DA732X_REG_ADC1_PD: + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, + DA732X_ADCA_BB_CLK_EN, + DA732X_ADCA_BB_CLK_EN); + break; + case DA732X_REG_ADC2_PD: + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, + DA732X_ADCC_BB_CLK_EN, + DA732X_ADCC_BB_CLK_EN); + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, + DA732X_ADC_SET_ACT); + snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, + DA732X_ADC_ON); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, + DA732X_ADC_OFF); + snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, + DA732X_ADC_SET_RST); + + switch (w->reg) { + case DA732X_REG_ADC1_PD: + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, + DA732X_ADCA_BB_CLK_EN, 0); + break; + case DA732X_REG_ADC2_PD: + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, + DA732X_ADCC_BB_CLK_EN, 0); + break; + default: + return -EINVAL; + } + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int da732x_out_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, w->reg, + (1 << w->shift) | DA732X_OUT_HIZ_EN, + (1 << w->shift) | DA732X_OUT_HIZ_EN); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, w->reg, + (1 << w->shift) | DA732X_OUT_HIZ_EN, + (1 << w->shift) | DA732X_OUT_HIZ_DIS); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const char *adcl_text[] = { + "AUX1L", "MIC1" +}; + +static const char *adcr_text[] = { + "AUX1R", "MIC2", "MIC3" +}; + +static const char *enable_text[] = { + "Disabled", + "Enabled" +}; + +/* ADC1LMUX */ +static const struct soc_enum adc1l_enum = + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, + DA732X_ADCL_MUX_MAX, adcl_text); +static const struct snd_kcontrol_new adc1l_mux = + SOC_DAPM_ENUM("ADC Route", adc1l_enum); + +/* ADC1RMUX */ +static const struct soc_enum adc1r_enum = + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, + DA732X_ADCR_MUX_MAX, adcr_text); +static const struct snd_kcontrol_new adc1r_mux = + SOC_DAPM_ENUM("ADC Route", adc1r_enum); + +/* ADC2LMUX */ +static const struct soc_enum adc2l_enum = + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, + DA732X_ADCL_MUX_MAX, adcl_text); +static const struct snd_kcontrol_new adc2l_mux = + SOC_DAPM_ENUM("ADC Route", adc2l_enum); + +/* ADC2RMUX */ +static const struct soc_enum adc2r_enum = + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, + DA732X_ADCR_MUX_MAX, adcr_text); + +static const struct snd_kcontrol_new adc2r_mux = + SOC_DAPM_ENUM("ADC Route", adc2r_enum); + +static const struct soc_enum da732x_hp_left_output = + SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, + DA732X_DAC_EN_MAX, enable_text); + +static const struct snd_kcontrol_new hpl_mux = + SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); + +static const struct soc_enum da732x_hp_right_output = + SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, + DA732X_DAC_EN_MAX, enable_text); + +static const struct snd_kcontrol_new hpr_mux = + SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); + +static const struct soc_enum da732x_speaker_output = + SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, + DA732X_DAC_EN_MAX, enable_text); + +static const struct snd_kcontrol_new spk_mux = + SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); + +static const struct soc_enum da732x_lout4_output = + SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, + DA732X_DAC_EN_MAX, enable_text); + +static const struct snd_kcontrol_new lout4_mux = + SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); + +static const struct soc_enum da732x_lout2_output = + SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, + DA732X_DAC_EN_MAX, enable_text); + +static const struct snd_kcontrol_new lout2_mux = + SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); + +static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = { + /* Supplies */ + SND_SOC_DAPM_SUPPLY("ADC1 Supply", DA732X_REG_ADC1_PD, 0, + DA732X_NO_INVERT, da732x_adc_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("ADC2 Supply", DA732X_REG_ADC2_PD, 0, + DA732X_NO_INVERT, da732x_adc_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("DAC1 CLK", DA732X_REG_CLK_EN4, + DA732X_DACA_BB_CLK_SHIFT, DA732X_NO_INVERT, + NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC2 CLK", DA732X_REG_CLK_EN4, + DA732X_DACC_BB_CLK_SHIFT, DA732X_NO_INVERT, + NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC3 CLK", DA732X_REG_CLK_EN5, + DA732X_DACE_BB_CLK_SHIFT, DA732X_NO_INVERT, + NULL, 0), + + /* Micbias */ + SND_SOC_DAPM_SUPPLY("MICBIAS1", DA732X_REG_MICBIAS1, + DA732X_MICBIAS_EN_SHIFT, + DA732X_NO_INVERT, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS2", DA732X_REG_MICBIAS2, + DA732X_MICBIAS_EN_SHIFT, + DA732X_NO_INVERT, NULL, 0), + + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("MIC3"), + SND_SOC_DAPM_INPUT("AUX1L"), + SND_SOC_DAPM_INPUT("AUX1R"), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + SND_SOC_DAPM_OUTPUT("LOUTL"), + SND_SOC_DAPM_OUTPUT("LOUTR"), + SND_SOC_DAPM_OUTPUT("ClassD"), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC1L", NULL, DA732X_REG_ADC1_SEL, + DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_ADC("ADC1R", NULL, DA732X_REG_ADC1_SEL, + DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_ADC("ADC2L", NULL, DA732X_REG_ADC2_SEL, + DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_ADC("ADC2R", NULL, DA732X_REG_ADC2_SEL, + DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), + + /* DACs */ + SND_SOC_DAPM_DAC("DAC1L", NULL, DA732X_REG_DAC1_SEL, + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_DAC("DAC1R", NULL, DA732X_REG_DAC1_SEL, + DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_DAC("DAC2L", NULL, DA732X_REG_DAC2_SEL, + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_DAC("DAC2R", NULL, DA732X_REG_DAC2_SEL, + DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), + SND_SOC_DAPM_DAC("DAC3", NULL, DA732X_REG_DAC3_SEL, + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), + + /* Input Pgas */ + SND_SOC_DAPM_PGA("MIC1 PGA", DA732X_REG_MIC1, DA732X_MIC_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC2 PGA", DA732X_REG_MIC2, DA732X_MIC_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC3 PGA", DA732X_REG_MIC3, DA732X_MIC_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("AUX1L PGA", DA732X_REG_AUX1L, DA732X_AUX_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("AUX1R PGA", DA732X_REG_AUX1R, DA732X_AUX_EN_SHIFT, + 0, NULL, 0), + + SND_SOC_DAPM_PGA_E("HP Left", DA732X_REG_HPL, DA732X_HP_OUT_EN_SHIFT, + 0, NULL, 0, da732x_out_pga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("HP Right", DA732X_REG_HPR, DA732X_HP_OUT_EN_SHIFT, + 0, NULL, 0, da732x_out_pga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("LIN2", DA732X_REG_LIN2, DA732X_LIN_OUT_EN_SHIFT, + 0, NULL, 0, da732x_out_pga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("LIN3", DA732X_REG_LIN3, DA732X_LIN_OUT_EN_SHIFT, + 0, NULL, 0, da732x_out_pga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("LIN4", DA732X_REG_LIN4, DA732X_LIN_OUT_EN_SHIFT, + 0, NULL, 0, da732x_out_pga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + /* MUXs */ + SND_SOC_DAPM_MUX("ADC1 Left MUX", SND_SOC_NOPM, 0, 0, &adc1l_mux), + SND_SOC_DAPM_MUX("ADC1 Right MUX", SND_SOC_NOPM, 0, 0, &adc1r_mux), + SND_SOC_DAPM_MUX("ADC2 Left MUX", SND_SOC_NOPM, 0, 0, &adc2l_mux), + SND_SOC_DAPM_MUX("ADC2 Right MUX", SND_SOC_NOPM, 0, 0, &adc2r_mux), + + SND_SOC_DAPM_MUX("HP Left MUX", SND_SOC_NOPM, 0, 0, &hpl_mux), + SND_SOC_DAPM_MUX("HP Right MUX", SND_SOC_NOPM, 0, 0, &hpr_mux), + SND_SOC_DAPM_MUX("Speaker MUX", SND_SOC_NOPM, 0, 0, &spk_mux), + SND_SOC_DAPM_MUX("LOUT2 MUX", SND_SOC_NOPM, 0, 0, &lout2_mux), + SND_SOC_DAPM_MUX("LOUT4 MUX", SND_SOC_NOPM, 0, 0, &lout4_mux), + + /* AIF interfaces */ + SND_SOC_DAPM_AIF_OUT("AIFA Output", "AIFA Capture", 0, DA732X_REG_AIFA3, + DA732X_AIF_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("AIFA Input", "AIFA Playback", 0, DA732X_REG_AIFA3, + DA732X_AIF_EN_SHIFT, 0), + + SND_SOC_DAPM_AIF_OUT("AIFB Output", "AIFB Capture", 0, DA732X_REG_AIFB3, + DA732X_AIF_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("AIFB Input", "AIFB Playback", 0, DA732X_REG_AIFB3, + DA732X_AIF_EN_SHIFT, 0), +}; + +static const struct snd_soc_dapm_route da732x_dapm_routes[] = { + /* Inputs */ + {"AUX1L PGA", "NULL", "AUX1L"}, + {"AUX1R PGA", "NULL", "AUX1R"}, + {"MIC1 PGA", NULL, "MIC1"}, + {"MIC2 PGA", "NULL", "MIC2"}, + {"MIC3 PGA", "NULL", "MIC3"}, + + /* Capture Path */ + {"ADC1 Left MUX", "MIC1", "MIC1 PGA"}, + {"ADC1 Left MUX", "AUX1L", "AUX1L PGA"}, + + {"ADC1 Right MUX", "AUX1R", "AUX1R PGA"}, + {"ADC1 Right MUX", "MIC2", "MIC2 PGA"}, + {"ADC1 Right MUX", "MIC3", "MIC3 PGA"}, + + {"ADC2 Left MUX", "AUX1L", "AUX1L PGA"}, + {"ADC2 Left MUX", "MIC1", "MIC1 PGA"}, + + {"ADC2 Right MUX", "AUX1R", "AUX1R PGA"}, + {"ADC2 Right MUX", "MIC2", "MIC2 PGA"}, + {"ADC2 Right MUX", "MIC3", "MIC3 PGA"}, + + {"ADC1L", NULL, "ADC1 Supply"}, + {"ADC1R", NULL, "ADC1 Supply"}, + {"ADC2L", NULL, "ADC2 Supply"}, + {"ADC2R", NULL, "ADC2 Supply"}, + + {"ADC1L", NULL, "ADC1 Left MUX"}, + {"ADC1R", NULL, "ADC1 Right MUX"}, + {"ADC2L", NULL, "ADC2 Left MUX"}, + {"ADC2R", NULL, "ADC2 Right MUX"}, + + {"AIFA Output", NULL, "ADC1L"}, + {"AIFA Output", NULL, "ADC1R"}, + {"AIFB Output", NULL, "ADC2L"}, + {"AIFB Output", NULL, "ADC2R"}, + + {"HP Left MUX", "Enabled", "AIFA Input"}, + {"HP Right MUX", "Enabled", "AIFA Input"}, + {"Speaker MUX", "Enabled", "AIFB Input"}, + {"LOUT2 MUX", "Enabled", "AIFB Input"}, + {"LOUT4 MUX", "Enabled", "AIFB Input"}, + + {"DAC1L", NULL, "DAC1 CLK"}, + {"DAC1R", NULL, "DAC1 CLK"}, + {"DAC2L", NULL, "DAC2 CLK"}, + {"DAC2R", NULL, "DAC2 CLK"}, + {"DAC3", NULL, "DAC3 CLK"}, + + {"DAC1L", NULL, "HP Left MUX"}, + {"DAC1R", NULL, "HP Right MUX"}, + {"DAC2L", NULL, "Speaker MUX"}, + {"DAC2R", NULL, "LOUT4 MUX"}, + {"DAC3", NULL, "LOUT2 MUX"}, + + /* Output Pgas */ + {"HP Left", NULL, "DAC1L"}, + {"HP Right", NULL, "DAC1R"}, + {"LIN3", NULL, "DAC2L"}, + {"LIN4", NULL, "DAC2R"}, + {"LIN2", NULL, "DAC3"}, + + /* Outputs */ + {"ClassD", NULL, "LIN3"}, + {"LOUTL", NULL, "LIN2"}, + {"LOUTR", NULL, "LIN4"}, + {"HPL", NULL, "HP Left"}, + {"HPR", NULL, "HP Right"}, +}; + +static int da732x_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + u32 aif = 0; + u32 reg_aif; + u32 fs; + + reg_aif = dai->driver->base; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + aif |= DA732X_AIF_WORD_16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + aif |= DA732X_AIF_WORD_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + aif |= DA732X_AIF_WORD_24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + aif |= DA732X_AIF_WORD_32; + break; + default: + return -EINVAL; + } + + switch (params_rate(params)) { + case 8000: + fs = DA732X_SR_8KHZ; + break; + case 11025: + fs = DA732X_SR_11_025KHZ; + break; + case 12000: + fs = DA732X_SR_12KHZ; + break; + case 16000: + fs = DA732X_SR_16KHZ; + break; + case 22050: + fs = DA732X_SR_22_05KHZ; + break; + case 24000: + fs = DA732X_SR_24KHZ; + break; + case 32000: + fs = DA732X_SR_32KHZ; + break; + case 44100: + fs = DA732X_SR_44_1KHZ; + break; + case 48000: + fs = DA732X_SR_48KHZ; + break; + case 88100: + fs = DA732X_SR_88_1KHZ; + break; + case 96000: + fs = DA732X_SR_96KHZ; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, reg_aif, DA732X_AIF_WORD_MASK, aif); + snd_soc_update_bits(codec, DA732X_REG_CLK_CTRL, DA732X_SR1_MASK, fs); + + return 0; +} + +static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt) +{ + struct snd_soc_codec *codec = dai->codec; + u32 aif_mclk, pc_count; + u32 reg_aif1, aif1; + u32 reg_aif3, aif3; + + switch (dai->id) { + case DA732X_DAI_ID1: + reg_aif1 = DA732X_REG_AIFA1; + reg_aif3 = DA732X_REG_AIFA3; + pc_count = DA732X_PC_PULSE_AIFA | DA732X_PC_RESYNC_NOT_AUT | + DA732X_PC_SAME; + break; + case DA732X_DAI_ID2: + reg_aif1 = DA732X_REG_AIFB1; + reg_aif3 = DA732X_REG_AIFB3; + pc_count = DA732X_PC_PULSE_AIFB | DA732X_PC_RESYNC_NOT_AUT | + DA732X_PC_SAME; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + aif1 = DA732X_AIF_SLAVE; + aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA; + break; + case SND_SOC_DAIFMT_CBM_CFM: + aif1 = DA732X_AIF_CLK_FROM_SRC; + aif_mclk = DA732X_CLK_GENERATION_AIF_A; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + aif3 = DA732X_AIF_I2S_MODE; + break; + case SND_SOC_DAIFMT_RIGHT_J: + aif3 = DA732X_AIF_RIGHT_J_MODE; + break; + case SND_SOC_DAIFMT_LEFT_J: + aif3 = DA732X_AIF_LEFT_J_MODE; + break; + case SND_SOC_DAIFMT_DSP_B: + aif3 = DA732X_AIF_DSP_MODE; + break; + default: + return -EINVAL; + } + + /* Clock inversion */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_B: + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + aif3 |= DA732X_AIF_BCLK_INV; + break; + default: + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + aif3 |= DA732X_AIF_BCLK_INV | DA732X_AIF_WCLK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + aif3 |= DA732X_AIF_BCLK_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + aif3 |= DA732X_AIF_WCLK_INV; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + snd_soc_write(codec, DA732X_REG_AIF_MCLK, aif_mclk); + snd_soc_update_bits(codec, reg_aif1, DA732X_AIF1_CLK_MASK, aif1); + snd_soc_update_bits(codec, reg_aif3, DA732X_AIF_BCLK_INV | + DA732X_AIF_WCLK_INV | DA732X_AIF_MODE_MASK, aif3); + snd_soc_write(codec, DA732X_REG_PC_CTRL, pc_count); + + return 0; +} + + + +static int da732x_set_dai_pll(struct snd_soc_codec *codec, int pll_id, + int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); + int fref, indiv; + u8 div_lo, div_mid, div_hi; + u64 frac_div; + + /* Disable PLL */ + if (freq_out == 0) { + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, + DA732X_PLL_EN, 0); + da732x->pll_en = false; + return 0; + } + + if (da732x->pll_en) + return -EBUSY; + + if (source == DA732X_SRCCLK_MCLK) { + /* Validate Sysclk rate */ + switch (da732x->sysclk) { + case 11290000: + case 12288000: + case 22580000: + case 24576000: + case 45160000: + case 49152000: + snd_soc_write(codec, DA732X_REG_PLL_CTRL, + DA732X_PLL_BYPASS); + return 0; + default: + dev_err(codec->dev, + "Cannot use PLL Bypass, invalid SYSCLK rate\n"); + return -EINVAL; + } + } + + indiv = da732x_get_input_div(codec, da732x->sysclk); + if (indiv < 0) + return indiv; + + fref = (da732x->sysclk / indiv); + div_hi = freq_out / fref; + frac_div = (u64)(freq_out % fref) * 8192ULL; + do_div(frac_div, fref); + div_mid = (frac_div >> DA732X_1BYTE_SHIFT) & DA732X_U8_MASK; + div_lo = (frac_div) & DA732X_U8_MASK; + + snd_soc_write(codec, DA732X_REG_PLL_DIV_LO, div_lo); + snd_soc_write(codec, DA732X_REG_PLL_DIV_MID, div_mid); + snd_soc_write(codec, DA732X_REG_PLL_DIV_HI, div_hi); + + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, DA732X_PLL_EN, + DA732X_PLL_EN); + + da732x->pll_en = true; + + return 0; +} + +static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); + + da732x->sysclk = freq; + + return 0; +} + +#define DA732X_RATES SNDRV_PCM_RATE_8000_96000 + +#define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops da732x_dai1_ops = { + .hw_params = da732x_hw_params, + .set_fmt = da732x_set_dai_fmt, + .set_sysclk = da732x_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops da732x_dai2_ops = { + .hw_params = da732x_hw_params, + .set_fmt = da732x_set_dai_fmt, + .set_sysclk = da732x_set_dai_sysclk, +}; + +static struct snd_soc_dai_driver da732x_dai[] = { + { + .name = "DA732X_AIFA", + .id = DA732X_DAI_ID1, + .base = DA732X_REG_AIFA1, + .playback = { + .stream_name = "AIFA Playback", + .channels_min = 1, + .channels_max = 2, + .rates = DA732X_RATES, + .formats = DA732X_FORMATS, + }, + .capture = { + .stream_name = "AIFA Capture", + .channels_min = 1, + .channels_max = 2, + .rates = DA732X_RATES, + .formats = DA732X_FORMATS, + }, + .ops = &da732x_dai1_ops, + }, + { + .name = "DA732X_AIFB", + .id = DA732X_DAI_ID2, + .base = DA732X_REG_AIFB1, + .playback = { + .stream_name = "AIFB Playback", + .channels_min = 1, + .channels_max = 2, + .rates = DA732X_RATES, + .formats = DA732X_FORMATS, + }, + .capture = { + .stream_name = "AIFB Capture", + .channels_min = 1, + .channels_max = 2, + .rates = DA732X_RATES, + .formats = DA732X_FORMATS, + }, + .ops = &da732x_dai2_ops, + }, +}; + +static const struct regmap_config da732x_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = DA732X_MAX_REG, + .reg_defaults = da732x_reg_cache, + .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), + .cache_type = REGCACHE_RBTREE, +}; + + +static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) +{ + u8 offset[DA732X_HP_DACS]; + u8 sign[DA732X_HP_DACS]; + u8 step = DA732X_DAC_OFFSET_STEP; + + /* Initialize DAC offset calibration circuits and registers */ + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, + DA732X_HP_DAC_OFFSET_TRIM_VAL); + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, + DA732X_HP_DAC_OFFSET_TRIM_VAL); + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, + DA732X_HP_DAC_OFF_CALIBRATION | + DA732X_HP_DAC_OFF_SCALE_STEPS); + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, + DA732X_HP_DAC_OFF_CALIBRATION | + DA732X_HP_DAC_OFF_SCALE_STEPS); + + /* Wait for voltage stabilization */ + msleep(DA732X_WAIT_FOR_STABILIZATION); + + /* Check DAC offset sign */ + sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + DA732X_HP_DAC_OFF_CNTL_COMPO); + sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + DA732X_HP_DAC_OFF_CNTL_COMPO); + + /* Binary search DAC offset values (both channels at once) */ + offset[DA732X_HPL_DAC] = sign[DA732X_HPL_DAC] << DA732X_HP_DAC_COMPO_SHIFT; + offset[DA732X_HPR_DAC] = sign[DA732X_HPR_DAC] << DA732X_HP_DAC_COMPO_SHIFT; + + do { + offset[DA732X_HPL_DAC] |= step; + offset[DA732X_HPR_DAC] |= step; + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, + ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, + ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); + + msleep(DA732X_WAIT_FOR_STABILIZATION); + + if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) + offset[DA732X_HPL_DAC] &= ~step; + if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) + offset[DA732X_HPR_DAC] &= ~step; + + step >>= 1; + } while (step); + + /* Write final DAC offsets to registers */ + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, + ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, + ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); + + /* End DAC calibration mode */ + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, + DA732X_HP_DAC_OFF_SCALE_STEPS); + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, + DA732X_HP_DAC_OFF_SCALE_STEPS); +} + +static void da732x_output_offset_adjust(struct snd_soc_codec *codec) +{ + u8 offset[DA732X_HP_AMPS]; + u8 sign[DA732X_HP_AMPS]; + u8 step = DA732X_OUTPUT_OFFSET_STEP; + + offset[DA732X_HPL_AMP] = DA732X_HP_OUT_TRIM_VAL; + offset[DA732X_HPR_AMP] = DA732X_HP_OUT_TRIM_VAL; + + /* Initialize output offset calibration circuits and registers */ + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); + snd_soc_write(codec, DA732X_REG_HPL, + DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); + snd_soc_write(codec, DA732X_REG_HPR, + DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); + + /* Wait for voltage stabilization */ + msleep(DA732X_WAIT_FOR_STABILIZATION); + + /* Check output offset sign */ + sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & + DA732X_HP_OUT_COMPO; + sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & + DA732X_HP_OUT_COMPO; + + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | + (sign[DA732X_HPL_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | + DA732X_HP_OUT_EN); + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_COMP | + (sign[DA732X_HPR_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | + DA732X_HP_OUT_EN); + + /* Binary search output offset values (both channels at once) */ + do { + offset[DA732X_HPL_AMP] |= step; + offset[DA732X_HPR_AMP] |= step; + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, + offset[DA732X_HPL_AMP]); + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, + offset[DA732X_HPR_AMP]); + + msleep(DA732X_WAIT_FOR_STABILIZATION); + + if ((codec->hw_read(codec, DA732X_REG_HPL) & + DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) + offset[DA732X_HPL_AMP] &= ~step; + if ((codec->hw_read(codec, DA732X_REG_HPR) & + DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) + offset[DA732X_HPR_AMP] &= ~step; + + step >>= 1; + } while (step); + + /* Write final DAC offsets to registers */ + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, offset[DA732X_HPL_AMP]); + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, offset[DA732X_HPR_AMP]); +} + +static void da732x_hp_dc_offset_cancellation(struct snd_soc_codec *codec) +{ + /* Make sure that we have Soft Mute enabled */ + snd_soc_write(codec, DA732X_REG_DAC1_SOFTMUTE, DA732X_SOFTMUTE_EN | + DA732X_GAIN_RAMPED | DA732X_16_SAMPLES); + snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACL_EN | + DA732X_DACR_EN | DA732X_DACL_SDM | DA732X_DACR_SDM | + DA732X_DACL_MUTE | DA732X_DACR_MUTE); + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN | + DA732X_HP_OUT_MUTE | DA732X_HP_OUT_EN); + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_EN | + DA732X_HP_OUT_MUTE | DA732X_HP_OUT_DAC_EN); + + da732x_dac_offset_adjust(codec); + da732x_output_offset_adjust(codec); + + snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACS_DIS); + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_DIS); + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_DIS); +} + +static int da732x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, + DA732X_BIAS_BOOST_MASK, + DA732X_BIAS_BOOST_100PC); + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + /* Init Codec */ + snd_soc_write(codec, DA732X_REG_REF1, + DA732X_VMID_FASTCHG); + snd_soc_write(codec, DA732X_REG_BIAS_EN, + DA732X_BIAS_EN); + + mdelay(DA732X_STARTUP_DELAY); + + /* Disable Fast Charge and enable DAC ref voltage */ + snd_soc_write(codec, DA732X_REG_REF1, + DA732X_REFBUFX2_EN); + + /* Enable bypass DSP routing */ + snd_soc_write(codec, DA732X_REG_DATA_ROUTE, + DA732X_BYPASS_DSP); + + /* Enable Digital subsystem */ + snd_soc_write(codec, DA732X_REG_DSP_CTRL, + DA732X_DIGITAL_EN); + + snd_soc_write(codec, DA732X_REG_SPARE1_OUT, + DA732X_HP_DRIVER_EN | + DA732X_HP_GATE_LOW | + DA732X_HP_LOOP_GAIN_CTRL); + snd_soc_write(codec, DA732X_REG_HP_LIN1_GNDSEL, + DA732X_HP_OUT_GNDSEL); + + da732x_set_charge_pump(codec, DA732X_ENABLE_CP); + + snd_soc_write(codec, DA732X_REG_CLK_EN1, + DA732X_SYS3_CLK_EN | DA732X_PC_CLK_EN); + + /* Enable Zero Crossing */ + snd_soc_write(codec, DA732X_REG_INP_ZC_EN, + DA732X_MIC1_PRE_ZC_EN | + DA732X_MIC1_ZC_EN | + DA732X_MIC2_PRE_ZC_EN | + DA732X_MIC2_ZC_EN | + DA732X_AUXL_ZC_EN | + DA732X_AUXR_ZC_EN | + DA732X_MIC3_PRE_ZC_EN | + DA732X_MIC3_ZC_EN); + snd_soc_write(codec, DA732X_REG_OUT_ZC_EN, + DA732X_HPL_ZC_EN | DA732X_HPR_ZC_EN | + DA732X_LIN2_ZC_EN | DA732X_LIN3_ZC_EN | + DA732X_LIN4_ZC_EN); + + da732x_hp_dc_offset_cancellation(codec); + + regcache_cache_only(codec->control_data, false); + regcache_sync(codec->control_data); + } else { + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, + DA732X_BIAS_BOOST_MASK, + DA732X_BIAS_BOOST_50PC); + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, + DA732X_PLL_EN, 0); + da732x->pll_en = false; + } + break; + case SND_SOC_BIAS_OFF: + regcache_cache_only(codec->control_data, true); + da732x_set_charge_pump(codec, DA732X_DISABLE_CP); + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, + DA732X_BIAS_DIS); + da732x->pll_en = false; + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static int da732x_probe(struct snd_soc_codec *codec) +{ + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + int ret = 0; + + da732x->codec = codec; + + dapm->idle_bias_off = false; + + codec->control_data = da732x->regmap; + + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); + if (ret != 0) { + dev_err(codec->dev, "Failed to register codec.\n"); + goto err; + } + + da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +err: + return ret; +} + +static int da732x_remove(struct snd_soc_codec *codec) +{ + + da732x_set_bias_level(codec, SND_SOC_BIAS_OFF); + + return 0; +} + +struct snd_soc_codec_driver soc_codec_dev_da732x = { + .probe = da732x_probe, + .remove = da732x_remove, + .set_bias_level = da732x_set_bias_level, + .controls = da732x_snd_controls, + .num_controls = ARRAY_SIZE(da732x_snd_controls), + .dapm_widgets = da732x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), + .dapm_routes = da732x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), + .set_pll = da732x_set_dai_pll, + .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), +}; + +static __devinit int da732x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct da732x_priv *da732x; + unsigned int reg; + int ret; + + da732x = devm_kzalloc(&i2c->dev, sizeof(struct da732x_priv), + GFP_KERNEL); + if (!da732x) + return -ENOMEM; + + i2c_set_clientdata(i2c, da732x); + + da732x->regmap = devm_regmap_init_i2c(i2c, &da732x_regmap); + if (IS_ERR(da732x->regmap)) { + ret = PTR_ERR(da732x->regmap); + dev_err(&i2c->dev, "Failed to initialize regmap\n"); + goto err; + } + + ret = regmap_read(da732x->regmap, DA732X_REG_ID, ®); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); + goto err; + } + + dev_info(&i2c->dev, "Revision: %d.%d\n", + (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK)); + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x, + da732x_dai, ARRAY_SIZE(da732x_dai)); + if (ret != 0) + dev_err(&i2c->dev, "Failed to register codec.\n"); + +err: + return ret; +} + +static __devexit int da732x_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id da732x_i2c_id[] = { + { "da7320", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); + +static struct i2c_driver da732x_i2c_driver = { + .driver = { + .name = "da7320", + .owner = THIS_MODULE, + }, + .probe = da732x_i2c_probe, + .remove = __devexit_p(da732x_i2c_remove), + .id_table = da732x_i2c_id, +}; + +module_i2c_driver(da732x_i2c_driver); + + +MODULE_DESCRIPTION("ASoC DA732X driver"); +MODULE_AUTHOR("Michal Hajduk "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h new file mode 100644 index 000000000000..c8ce5475de22 --- /dev/null +++ b/sound/soc/codecs/da732x.h @@ -0,0 +1,133 @@ +/* + * da732x.h -- Dialog DA732X ALSA SoC Audio Driver Header File + * + * Copyright (C) 2012 Dialog Semiconductor GmbH + * + * Author: Michal Hajduk + * + * 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 __DA732X_H_ +#define __DA732X_H + +#include + +/* General */ +#define DA732X_U8_MASK 0xFF +#define DA732X_4BYTES 4 +#define DA732X_3BYTES 3 +#define DA732X_2BYTES 2 +#define DA732X_1BYTE 1 +#define DA732X_1BYTE_SHIFT 8 +#define DA732X_2BYTES_SHIFT 16 +#define DA732X_3BYTES_SHIFT 24 +#define DA732X_4BYTES_SHIFT 32 + +#define DA732X_DACS_DIS 0x0 +#define DA732X_HP_DIS 0x0 +#define DA732X_CLEAR_REG 0x0 + +/* Calibration */ +#define DA732X_DAC_OFFSET_STEP 0x20 +#define DA732X_OUTPUT_OFFSET_STEP 0x80 +#define DA732X_HP_OUT_TRIM_VAL 0x0 +#define DA732X_WAIT_FOR_STABILIZATION 1 +#define DA732X_HPL_DAC 0 +#define DA732X_HPR_DAC 1 +#define DA732X_HP_DACS 2 +#define DA732X_HPL_AMP 0 +#define DA732X_HPR_AMP 1 +#define DA732X_HP_AMPS 2 + +/* Clock settings */ +#define DA732X_STARTUP_DELAY 100 +#define DA732X_PLL_OUT_196608 196608000 +#define DA732X_PLL_OUT_180634 180633600 +#define DA732X_PLL_OUT_SRM 188620800 +#define DA732X_MCLK_10MHZ 10000000 +#define DA732X_MCLK_20MHZ 20000000 +#define DA732X_MCLK_40MHZ 40000000 +#define DA732X_MCLK_54MHZ 54000000 +#define DA732X_MCLK_RET_0_10MHZ 0 +#define DA732X_MCLK_VAL_0_10MHZ 1 +#define DA732X_MCLK_RET_10_20MHZ 1 +#define DA732X_MCLK_VAL_10_20MHZ 2 +#define DA732X_MCLK_RET_20_40MHZ 2 +#define DA732X_MCLK_VAL_20_40MHZ 4 +#define DA732X_MCLK_RET_40_54MHZ 3 +#define DA732X_MCLK_VAL_40_54MHZ 8 +#define DA732X_DAI_ID1 0 +#define DA732X_DAI_ID2 1 +#define DA732X_SRCCLK_PLL 0 +#define DA732X_SRCCLK_MCLK 1 + +#define DA732X_LIN_LP_VOL 0x4F +#define DA732X_LP_VOL 0x40 + +/* Kcontrols */ +#define DA732X_DAC_EN_MAX 2 +#define DA732X_ADCL_MUX_MAX 2 +#define DA732X_ADCR_MUX_MAX 3 +#define DA732X_HPF_MODE_MAX 3 +#define DA732X_HPF_MODE_SHIFT 4 +#define DA732X_HPF_MUSIC_SHIFT 0 +#define DA732X_HPF_MUSIC_MAX 4 +#define DA732X_HPF_VOICE_SHIFT 4 +#define DA732X_HPF_VOICE_MAX 8 +#define DA732X_EQ_EN_MAX 1 +#define DA732X_HPF_VOICE 1 +#define DA732X_HPF_MUSIC 2 +#define DA732X_HPF_DISABLED 0 +#define DA732X_NO_INVERT 0 +#define DA732X_INVERT 1 +#define DA732X_SWITCH_MAX 1 +#define DA732X_ENABLE_CP 1 +#define DA732X_DISABLE_CP 0 +#define DA732X_DISABLE_ALL_CLKS 0 +#define DA732X_RESET_ADCS 0 + +/* dB values */ +#define DA732X_MIC_VOL_DB_MIN 0 +#define DA732X_MIC_VOL_DB_INC 50 +#define DA732X_MIC_PRE_VOL_DB_MIN 0 +#define DA732X_MIC_PRE_VOL_DB_INC 600 +#define DA732X_AUX_VOL_DB_MIN -6000 +#define DA732X_AUX_VOL_DB_INC 150 +#define DA732X_HP_VOL_DB_MIN -2250 +#define DA732X_HP_VOL_DB_INC 150 +#define DA732X_LIN2_VOL_DB_MIN -1650 +#define DA732X_LIN2_VOL_DB_INC 150 +#define DA732X_LIN3_VOL_DB_MIN -1650 +#define DA732X_LIN3_VOL_DB_INC 150 +#define DA732X_LIN4_VOL_DB_MIN -2250 +#define DA732X_LIN4_VOL_DB_INC 150 +#define DA732X_EQ_BAND_VOL_DB_MIN -1050 +#define DA732X_EQ_BAND_VOL_DB_INC 150 +#define DA732X_DAC_VOL_DB_MIN -7725 +#define DA732X_DAC_VOL_DB_INC 75 +#define DA732X_ADC_VOL_DB_MIN 0 +#define DA732X_ADC_VOL_DB_INC -1 +#define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 +#define DA732X_EQ_OVERALL_VOL_DB_INC 600 + +#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ + {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} + +enum da732x_sysctl { + DA732X_SR_8KHZ = 0x1, + DA732X_SR_11_025KHZ = 0x2, + DA732X_SR_12KHZ = 0x3, + DA732X_SR_16KHZ = 0x5, + DA732X_SR_22_05KHZ = 0x6, + DA732X_SR_24KHZ = 0x7, + DA732X_SR_32KHZ = 0x9, + DA732X_SR_44_1KHZ = 0xA, + DA732X_SR_48KHZ = 0xB, + DA732X_SR_88_1KHZ = 0xE, + DA732X_SR_96KHZ = 0xF, +}; + +#endif /* __DA732X_H_ */ diff --git a/sound/soc/codecs/da732x_reg.h b/sound/soc/codecs/da732x_reg.h new file mode 100644 index 000000000000..bdd03ca4b2de --- /dev/null +++ b/sound/soc/codecs/da732x_reg.h @@ -0,0 +1,654 @@ +/* + * da732x_reg.h --- Dialog DA732X ALSA SoC Audio Registers Header File + * + * Copyright (C) 2012 Dialog Semiconductor GmbH + * + * Author: Michal Hajduk + * + * 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 __DA732X_REG_H_ +#define __DA732X_REG_H_ + +/* DA732X registers */ +#define DA732X_REG_STATUS_EXT 0x00 +#define DA732X_REG_STATUS 0x01 +#define DA732X_REG_REF1 0x02 +#define DA732X_REG_BIAS_EN 0x03 +#define DA732X_REG_BIAS1 0x04 +#define DA732X_REG_BIAS2 0x05 +#define DA732X_REG_BIAS3 0x06 +#define DA732X_REG_BIAS4 0x07 +#define DA732X_REG_MICBIAS2 0x0F +#define DA732X_REG_MICBIAS1 0x10 +#define DA732X_REG_MICDET 0x11 +#define DA732X_REG_MIC1_PRE 0x12 +#define DA732X_REG_MIC1 0x13 +#define DA732X_REG_MIC2_PRE 0x14 +#define DA732X_REG_MIC2 0x15 +#define DA732X_REG_AUX1L 0x16 +#define DA732X_REG_AUX1R 0x17 +#define DA732X_REG_MIC3_PRE 0x18 +#define DA732X_REG_MIC3 0x19 +#define DA732X_REG_INP_PINBIAS 0x1A +#define DA732X_REG_INP_ZC_EN 0x1B +#define DA732X_REG_INP_MUX 0x1D +#define DA732X_REG_HP_DET 0x20 +#define DA732X_REG_HPL_DAC_OFFSET 0x21 +#define DA732X_REG_HPL_DAC_OFF_CNTL 0x22 +#define DA732X_REG_HPL_OUT_OFFSET 0x23 +#define DA732X_REG_HPL 0x24 +#define DA732X_REG_HPL_VOL 0x25 +#define DA732X_REG_HPR_DAC_OFFSET 0x26 +#define DA732X_REG_HPR_DAC_OFF_CNTL 0x27 +#define DA732X_REG_HPR_OUT_OFFSET 0x28 +#define DA732X_REG_HPR 0x29 +#define DA732X_REG_HPR_VOL 0x2A +#define DA732X_REG_LIN2 0x2B +#define DA732X_REG_LIN3 0x2C +#define DA732X_REG_LIN4 0x2D +#define DA732X_REG_OUT_ZC_EN 0x2E +#define DA732X_REG_HP_LIN1_GNDSEL 0x37 +#define DA732X_REG_CP_HP1 0x3A +#define DA732X_REG_CP_HP2 0x3B +#define DA732X_REG_CP_CTRL1 0x40 +#define DA732X_REG_CP_CTRL2 0x41 +#define DA732X_REG_CP_CTRL3 0x42 +#define DA732X_REG_CP_LEVEL_MASK 0x43 +#define DA732X_REG_CP_DET 0x44 +#define DA732X_REG_CP_STATUS 0x45 +#define DA732X_REG_CP_THRESH1 0x46 +#define DA732X_REG_CP_THRESH2 0x47 +#define DA732X_REG_CP_THRESH3 0x48 +#define DA732X_REG_CP_THRESH4 0x49 +#define DA732X_REG_CP_THRESH5 0x4A +#define DA732X_REG_CP_THRESH6 0x4B +#define DA732X_REG_CP_THRESH7 0x4C +#define DA732X_REG_CP_THRESH8 0x4D +#define DA732X_REG_PLL_DIV_LO 0x50 +#define DA732X_REG_PLL_DIV_MID 0x51 +#define DA732X_REG_PLL_DIV_HI 0x52 +#define DA732X_REG_PLL_CTRL 0x53 +#define DA732X_REG_CLK_CTRL 0x54 +#define DA732X_REG_CLK_DSP 0x5A +#define DA732X_REG_CLK_EN1 0x5B +#define DA732X_REG_CLK_EN2 0x5C +#define DA732X_REG_CLK_EN3 0x5D +#define DA732X_REG_CLK_EN4 0x5E +#define DA732X_REG_CLK_EN5 0x5F +#define DA732X_REG_AIF_MCLK 0x60 +#define DA732X_REG_AIFA1 0x61 +#define DA732X_REG_AIFA2 0x62 +#define DA732X_REG_AIFA3 0x63 +#define DA732X_REG_AIFB1 0x64 +#define DA732X_REG_AIFB2 0x65 +#define DA732X_REG_AIFB3 0x66 +#define DA732X_REG_PC_CTRL 0x6A +#define DA732X_REG_DATA_ROUTE 0x70 +#define DA732X_REG_DSP_CTRL 0x71 +#define DA732X_REG_CIF_CTRL2 0x74 +#define DA732X_REG_HANDSHAKE 0x75 +#define DA732X_REG_MBOX0 0x76 +#define DA732X_REG_MBOX1 0x77 +#define DA732X_REG_MBOX2 0x78 +#define DA732X_REG_MBOX_STATUS 0x79 +#define DA732X_REG_SPARE1_OUT 0x7D +#define DA732X_REG_SPARE2_OUT 0x7E +#define DA732X_REG_SPARE1_IN 0x7F +#define DA732X_REG_ID 0x81 +#define DA732X_REG_ADC1_PD 0x90 +#define DA732X_REG_ADC1_HPF 0x93 +#define DA732X_REG_ADC1_SEL 0x94 +#define DA732X_REG_ADC1_EQ12 0x95 +#define DA732X_REG_ADC1_EQ34 0x96 +#define DA732X_REG_ADC1_EQ5 0x97 +#define DA732X_REG_ADC2_PD 0x98 +#define DA732X_REG_ADC2_HPF 0x9B +#define DA732X_REG_ADC2_SEL 0x9C +#define DA732X_REG_ADC2_EQ12 0x9D +#define DA732X_REG_ADC2_EQ34 0x9E +#define DA732X_REG_ADC2_EQ5 0x9F +#define DA732X_REG_DAC1_HPF 0xA0 +#define DA732X_REG_DAC1_L_VOL 0xA1 +#define DA732X_REG_DAC1_R_VOL 0xA2 +#define DA732X_REG_DAC1_SEL 0xA3 +#define DA732X_REG_DAC1_SOFTMUTE 0xA4 +#define DA732X_REG_DAC1_EQ12 0xA5 +#define DA732X_REG_DAC1_EQ34 0xA6 +#define DA732X_REG_DAC1_EQ5 0xA7 +#define DA732X_REG_DAC2_HPF 0xB0 +#define DA732X_REG_DAC2_L_VOL 0xB1 +#define DA732X_REG_DAC2_R_VOL 0xB2 +#define DA732X_REG_DAC2_SEL 0xB3 +#define DA732X_REG_DAC2_SOFTMUTE 0xB4 +#define DA732X_REG_DAC2_EQ12 0xB5 +#define DA732X_REG_DAC2_EQ34 0xB6 +#define DA732X_REG_DAC2_EQ5 0xB7 +#define DA732X_REG_DAC3_HPF 0xC0 +#define DA732X_REG_DAC3_VOL 0xC1 +#define DA732X_REG_DAC3_SEL 0xC3 +#define DA732X_REG_DAC3_SOFTMUTE 0xC4 +#define DA732X_REG_DAC3_EQ12 0xC5 +#define DA732X_REG_DAC3_EQ34 0xC6 +#define DA732X_REG_DAC3_EQ5 0xC7 +#define DA732X_REG_BIQ_BYP 0xD2 +#define DA732X_REG_DMA_CMD 0xD3 +#define DA732X_REG_DMA_ADDR0 0xD4 +#define DA732X_REG_DMA_ADDR1 0xD5 +#define DA732X_REG_DMA_DATA0 0xD6 +#define DA732X_REG_DMA_DATA1 0xD7 +#define DA732X_REG_DMA_DATA2 0xD8 +#define DA732X_REG_DMA_DATA3 0xD9 +#define DA732X_REG_DMA_STATUS 0xDA +#define DA732X_REG_BROWNOUT 0xDF +#define DA732X_REG_UNLOCK 0xE0 + +#define DA732X_MAX_REG DA732X_REG_UNLOCK +/* + * Bits + */ + +/* DA732X_REG_STATUS_EXT (addr=0x00) */ +#define DA732X_STATUS_EXT_DSP (1 << 4) +#define DA732X_STATUS_EXT_CLEAR (0 << 0) + +/* DA732X_REG_STATUS (addr=0x01) */ +#define DA732X_STATUS_PLL_LOCK (1 << 0) +#define DA732X_STATUS_PLL_MCLK_DET (1 << 1) +#define DA732X_STATUS_HPDET_OUT (1 << 2) +#define DA732X_STATUS_INP_MIXDET_1 (1 << 3) +#define DA732X_STATUS_INP_MIXDET_2 (1 << 4) +#define DA732X_STATUS_BO_STATUS (1 << 5) + +/* DA732X_REG_REF1 (addr=0x02) */ +#define DA732X_VMID_FASTCHG (1 << 1) +#define DA732X_VMID_FASTDISCHG (1 << 2) +#define DA732X_REFBUFX2_EN (1 << 6) +#define DA732X_REFBUFX2_DIS (0 << 6) + +/* DA732X_REG_BIAS_EN (addr=0x03) */ +#define DA732X_BIAS_BOOST_MASK (3 << 0) +#define DA732X_BIAS_BOOST_100PC (0 << 0) +#define DA732X_BIAS_BOOST_133PC (1 << 0) +#define DA732X_BIAS_BOOST_88PC (2 << 0) +#define DA732X_BIAS_BOOST_50PC (3 << 0) +#define DA732X_BIAS_EN (1 << 7) +#define DA732X_BIAS_DIS (0 << 7) + +/* DA732X_REG_BIAS1 (addr=0x04) */ +#define DA732X_BIAS1_HP_DAC_BIAS_MASK (3 << 0) +#define DA732X_BIAS1_HP_DAC_BIAS_100PC (0 << 0) +#define DA732X_BIAS1_HP_DAC_BIAS_150PC (1 << 0) +#define DA732X_BIAS1_HP_DAC_BIAS_50PC (2 << 0) +#define DA732X_BIAS1_HP_DAC_BIAS_75PC (3 << 0) +#define DA732X_BIAS1_HP_OUT_BIAS_MASK (7 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_100PC (0 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_125PC (1 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_150PC (2 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_175PC (3 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_200PC (4 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_250PC (5 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_300PC (6 << 4) +#define DA732X_BIAS1_HP_OUT_BIAS_350PC (7 << 4) + +/* DA732X_REG_BIAS2 (addr=0x05) */ +#define DA732X_BIAS2_LINE2_DAC_BIAS_MASK (3 << 0) +#define DA732X_BIAS2_LINE2_DAC_BIAS_100PC (0 << 0) +#define DA732X_BIAS2_LINE2_DAC_BIAS_150PC (1 << 0) +#define DA732X_BIAS2_LINE2_DAC_BIAS_50PC (2 << 0) +#define DA732X_BIAS2_LINE2_DAC_BIAS_75PC (3 << 0) +#define DA732X_BIAS2_LINE2_OUT_BIAS_MASK (7 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_100PC (0 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_125PC (1 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_150PC (2 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_175PC (3 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_200PC (4 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_250PC (5 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_300PC (6 << 4) +#define DA732X_BIAS2_LINE2_OUT_BIAS_350PC (7 << 4) + +/* DA732X_REG_BIAS3 (addr=0x06) */ +#define DA732X_BIAS3_LINE3_DAC_BIAS_MASK (3 << 0) +#define DA732X_BIAS3_LINE3_DAC_BIAS_100PC (0 << 0) +#define DA732X_BIAS3_LINE3_DAC_BIAS_150PC (1 << 0) +#define DA732X_BIAS3_LINE3_DAC_BIAS_50PC (2 << 0) +#define DA732X_BIAS3_LINE3_DAC_BIAS_75PC (3 << 0) +#define DA732X_BIAS3_LINE3_OUT_BIAS_MASK (7 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_100PC (0 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_125PC (1 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_150PC (2 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_175PC (3 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_200PC (4 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_250PC (5 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_300PC (6 << 4) +#define DA732X_BIAS3_LINE3_OUT_BIAS_350PC (7 << 4) + +/* DA732X_REG_BIAS4 (addr=0x07) */ +#define DA732X_BIAS4_LINE4_DAC_BIAS_MASK (3 << 0) +#define DA732X_BIAS4_LINE4_DAC_BIAS_100PC (0 << 0) +#define DA732X_BIAS4_LINE4_DAC_BIAS_150PC (1 << 0) +#define DA732X_BIAS4_LINE4_DAC_BIAS_50PC (2 << 0) +#define DA732X_BIAS4_LINE4_DAC_BIAS_75PC (3 << 0) +#define DA732X_BIAS4_LINE4_OUT_BIAS_MASK (7 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_100PC (0 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_125PC (1 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_150PC (2 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_175PC (3 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_200PC (4 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_250PC (5 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_300PC (6 << 4) +#define DA732X_BIAS4_LINE4_OUT_BIAS_350PC (7 << 4) + +/* DA732X_REG_SIF_VDD_SEL (addr=0x08) */ +#define DA732X_SIF_VDD_SEL_AIFA_VDD2 (1 << 0) +#define DA732X_SIF_VDD_SEL_AIFB_VDD2 (1 << 1) +#define DA732X_SIF_VDD_SEL_CIFA_VDD2 (1 << 4) + +/* DA732X_REG_MICBIAS2/1 (addr=0x0F/0x10) */ +#define DA732X_MICBIAS_VOLTAGE_MASK (0x0F << 0) +#define DA732X_MICBIAS_VOLTAGE_2V (0x00 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V05 (0x01 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V1 (0x02 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V15 (0x03 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V2 (0x04 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V25 (0x05 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V3 (0x06 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V35 (0x07 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V4 (0x08 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V45 (0x09 << 0) +#define DA732X_MICBIAS_VOLTAGE_2V5 (0x0A << 0) +#define DA732X_MICBIAS_EN (1 << 7) +#define DA732X_MICBIAS_EN_SHIFT 7 +#define DA732X_MICBIAS_VOLTAGE_SHIFT 0 +#define DA732X_MICBIAS_VOLTAGE_MAX 0x0B + +/* DA732X_REG_MICDET (addr=0x11) */ +#define DA732X_MICDET_INP_MICRES (1 << 0) +#define DA732X_MICDET_INP_MICHOOK (1 << 1) +#define DA732X_MICDET_INP_DEBOUNCE_PRD_8MS (0 << 0) +#define DA732X_MICDET_INP_DEBOUNCE_PRD_16MS (1 << 0) +#define DA732X_MICDET_INP_DEBOUNCE_PRD_32MS (2 << 0) +#define DA732X_MICDET_INP_DEBOUNCE_PRD_64MS (3 << 0) +#define DA732X_MICDET_INP_MICDET_EN (1 << 7) + +/* DA732X_REG_MIC1/2/3_PRE (addr=0x11/0x14/0x18) */ +#define DA732X_MICBOOST_MASK 0x7 +#define DA732X_MICBOOST_SHIFT 0 +#define DA732X_MICBOOST_MIN 0x1 +#define DA732X_MICBOOST_MAX DA732X_MICBOOST_MASK + +/* DA732X_REG_MIC1/2/3 (addr=0x13/0x15/0x19) */ +#define DA732X_MIC_VOL_SHIFT 0 +#define DA732X_MIC_VOL_VAL_MASK 0x1F +#define DA732X_MIC_MUTE_SHIFT 6 +#define DA732X_MIC_EN_SHIFT 7 +#define DA732X_MIC_VOL_VAL_MIN 0x7 +#define DA732X_MIC_VOL_VAL_MAX DA732X_MIC_VOL_VAL_MASK + +/* DA732X_REG_AUX1L/R (addr=0x16/0x17) */ +#define DA732X_AUX_VOL_SHIFT 0 +#define DA732X_AUX_VOL_MASK 0x7 +#define DA732X_AUX_MUTE_SHIFT 6 +#define DA732X_AUX_EN_SHIFT 7 +#define DA732X_AUX_VOL_VAL_MAX DA732X_AUX_VOL_MASK + +/* DA732X_REG_INP_PINBIAS (addr=0x1A) */ +#define DA732X_INP_MICL_PINBIAS_EN (1 << 0) +#define DA732X_INP_MICR_PINBIAS_EN (1 << 1) +#define DA732X_INP_AUX1L_PINBIAS_EN (1 << 2) +#define DA732X_INP_AUX1R_PINBIAS_EN (1 << 3) +#define DA732X_INP_AUX2_PINBIAS_EN (1 << 4) + +/* DA732X_REG_INP_ZC_EN (addr=0x1B) */ +#define DA732X_MIC1_PRE_ZC_EN (1 << 0) +#define DA732X_MIC1_ZC_EN (1 << 1) +#define DA732X_MIC2_PRE_ZC_EN (1 << 2) +#define DA732X_MIC2_ZC_EN (1 << 3) +#define DA732X_AUXL_ZC_EN (1 << 4) +#define DA732X_AUXR_ZC_EN (1 << 5) +#define DA732X_MIC3_PRE_ZC_EN (1 << 6) +#define DA732X_MIC3_ZC_EN (1 << 7) + +/* DA732X_REG_INP_MUX (addr=0x1D) */ +#define DA732X_INP_ADC1L_MUX_SEL_AUX1L (0 << 0) +#define DA732X_INP_ADC1L_MUX_SEL_MIC1 (1 << 0) +#define DA732X_INP_ADC1R_MUX_SEL_MASK (3 << 2) +#define DA732X_INP_ADC1R_MUX_SEL_AUX1R (0 << 2) +#define DA732X_INP_ADC1R_MUX_SEL_MIC2 (1 << 2) +#define DA732X_INP_ADC1R_MUX_SEL_MIC3 (2 << 2) +#define DA732X_INP_ADC2L_MUX_SEL_AUX1L (0 << 4) +#define DA732X_INP_ADC2L_MUX_SEL_MICL (1 << 4) +#define DA732X_INP_ADC2R_MUX_SEL_MASK (3 << 6) +#define DA732X_INP_ADC2R_MUX_SEL_AUX1R (0 << 6) +#define DA732X_INP_ADC2R_MUX_SEL_MICR (1 << 6) +#define DA732X_INP_ADC2R_MUX_SEL_AUX2 (2 << 6) +#define DA732X_ADC1L_MUX_SEL_SHIFT 0 +#define DA732X_ADC1R_MUX_SEL_SHIFT 2 +#define DA732X_ADC2L_MUX_SEL_SHIFT 4 +#define DA732X_ADC2R_MUX_SEL_SHIFT 6 + +/* DA732X_REG_HP_DET (addr=0x20) */ +#define DA732X_HP_DET_AZ (1 << 0) +#define DA732X_HP_DET_SEL1 (1 << 1) +#define DA732X_HP_DET_IS_MASK (3 << 2) +#define DA732X_HP_DET_IS_0_5UA (0 << 2) +#define DA732X_HP_DET_IS_1UA (1 << 2) +#define DA732X_HP_DET_IS_2UA (2 << 2) +#define DA732X_HP_DET_IS_4UA (3 << 2) +#define DA732X_HP_DET_RS_MASK (3 << 4) +#define DA732X_HP_DET_RS_INFINITE (0 << 4) +#define DA732X_HP_DET_RS_100KOHM (1 << 4) +#define DA732X_HP_DET_RS_10KOHM (2 << 4) +#define DA732X_HP_DET_RS_1KOHM (3 << 4) +#define DA732X_HP_DET_EN (1 << 7) + +/* DA732X_REG_HPL_DAC_OFFSET (addr=0x21/0x26) */ +#define DA732X_HP_DAC_OFFSET_TRIM_MASK (0x3F << 0) +#define DA732X_HP_DAC_OFFSET_DAC_SIGN (1 << 6) + +/* DA732X_REG_HPL_DAC_OFF_CNTL (addr=0x22/0x27) */ +#define DA732X_HP_DAC_OFF_CNTL_CONT_MASK (7 << 0) +#define DA732X_HP_DAC_OFF_CNTL_COMPO (1 << 3) +#define DA732X_HP_DAC_OFF_CALIBRATION (1 << 0) +#define DA732X_HP_DAC_OFF_SCALE_STEPS (1 << 1) +#define DA732X_HP_DAC_OFF_MASK 0x7F +#define DA732X_HP_DAC_COMPO_SHIFT 3 + +/* DA732X_REG_HPL_OUT_OFFSET (addr=0x23/0x28) */ +#define DA732X_HP_OUT_OFFSET_MASK (0xFF << 0) +#define DA732X_HP_DAC_OFFSET_TRIM_VAL 0x7F + +/* DA732X_REG_HPL/R (addr=0x24/0x29) */ +#define DA732X_HP_OUT_SIGN (1 << 0) +#define DA732X_HP_OUT_COMP (1 << 1) +#define DA732X_HP_OUT_RESERVED (1 << 2) +#define DA732X_HP_OUT_COMPO (1 << 3) +#define DA732X_HP_OUT_DAC_EN (1 << 4) +#define DA732X_HP_OUT_HIZ_EN (1 << 5) +#define DA732X_HP_OUT_HIZ_DIS (0 << 5) +#define DA732X_HP_OUT_MUTE (1 << 6) +#define DA732X_HP_OUT_EN (1 << 7) +#define DA732X_HP_OUT_COMPO_SHIFT 3 +#define DA732X_HP_OUT_DAC_EN_SHIFT 4 +#define DA732X_HP_HIZ_SHIFT 5 +#define DA732X_HP_MUTE_SHIFT 6 +#define DA732X_HP_OUT_EN_SHIFT 7 + +#define DA732X_OUT_HIZ_EN (1 << 5) +#define DA732X_OUT_HIZ_DIS (0 << 5) + +/* DA732X_REG_HPL/R_VOL (addr=0x25/0x2A) */ +#define DA732X_HP_VOL_VAL_MASK 0xF +#define DA732X_HP_VOL_SHIFT 0 +#define DA732X_HP_VOL_VAL_MAX DA732X_HP_VOL_VAL_MASK + +/* DA732X_REG_LIN2/3/4 (addr=0x2B/0x2C/0x2D) */ +#define DA732X_LOUT_VOL_SHIFT 0 +#define DA732X_LOUT_VOL_MASK 0x0F +#define DA732X_LOUT_DAC_OFF (0 << 4) +#define DA732X_LOUT_DAC_EN (1 << 4) +#define DA732X_LOUT_HIZ_N_DIS (0 << 5) +#define DA732X_LOUT_HIZ_N_EN (1 << 5) +#define DA732X_LOUT_UNMUTED (0 << 6) +#define DA732X_LOUT_MUTED (1 << 6) +#define DA732X_LOUT_EN (0 << 7) +#define DA732X_LOUT_DIS (1 << 7) +#define DA732X_LOUT_DAC_EN_SHIFT 4 +#define DA732X_LOUT_MUTE_SHIFT 6 +#define DA732X_LIN_OUT_EN_SHIFT 7 +#define DA732X_LOUT_VOL_VAL_MAX DA732X_LOUT_VOL_MASK + +/* DA732X_REG_OUT_ZC_EN (addr=0x2E) */ +#define DA732X_HPL_ZC_EN_SHIFT 0 +#define DA732X_HPR_ZC_EN_SHIFT 1 +#define DA732X_HPL_ZC_EN (1 << 0) +#define DA732X_HPL_ZC_DIS (0 << 0) +#define DA732X_HPR_ZC_EN (1 << 1) +#define DA732X_HPR_ZC_DIS (0 << 1) +#define DA732X_LIN2_ZC_EN (1 << 2) +#define DA732X_LIN2_ZC_DIS (0 << 2) +#define DA732X_LIN3_ZC_EN (1 << 3) +#define DA732X_LIN3_ZC_DIS (0 << 3) +#define DA732X_LIN4_ZC_EN (1 << 4) +#define DA732X_LIN4_ZC_DIS (0 << 4) + +/* DA732X_REG_HP_LIN1_GNDSEL (addr=0x37) */ +#define DA732X_HP_OUT_GNDSEL (1 << 0) + +/* DA732X_REG_CP_HP2 (addr=0x3a) */ +#define DA732X_HP_CP_PULSESKIP (1 << 0) +#define DA732X_HP_CP_REG (1 << 1) +#define DA732X_HP_CP_EN (1 << 3) +#define DA732X_HP_CP_DIS (0 << 3) + +/* DA732X_REG_CP_CTRL1 (addr=0x40) */ +#define DA732X_CP_MODE_MASK (7 << 1) +#define DA732X_CP_CTRL_STANDBY (0 << 1) +#define DA732X_CP_CTRL_CPVDD6 (2 << 1) +#define DA732X_CP_CTRL_CPVDD5 (3 << 1) +#define DA732X_CP_CTRL_CPVDD4 (4 << 1) +#define DA732X_CP_CTRL_CPVDD3 (5 << 1) +#define DA732X_CP_CTRL_CPVDD2 (6 << 1) +#define DA732X_CP_CTRL_CPVDD1 (7 << 1) +#define DA723X_CP_DIS (0 << 7) +#define DA732X_CP_EN (1 << 7) + +/* DA732X_REG_CP_CTRL2 (addr=0x41) */ +#define DA732X_CP_BOOST (1 << 0) +#define DA732X_CP_MANAGE_MAGNITUDE (2 << 2) + +/* DA732X_REG_CP_CTRL3 (addr=0x42) */ +#define DA732X_CP_1MHZ (0 << 0) +#define DA732X_CP_500KHZ (1 << 0) +#define DA732X_CP_250KHZ (2 << 0) +#define DA732X_CP_125KHZ (3 << 0) +#define DA732X_CP_63KHZ (4 << 0) +#define DA732X_CP_0KHZ (5 << 0) + +/* DA732X_REG_PLL_CTRL (addr=0x53) */ +#define DA732X_PLL_INDIV_MASK (3 << 0) +#define DA732X_PLL_SRM_EN (1 << 2) +#define DA732X_PLL_EN (1 << 7) +#define DA732X_PLL_BYPASS (0 << 0) + +/* DA732X_REG_CLK_CTRL (addr=0x54) */ +#define DA732X_SR1_MASK (0xF) +#define DA732X_SR2_MASK (0xF0) + +/* DA732X_REG_CLK_DSP (addr=0x5A) */ +#define DA732X_DSP_FREQ_MASK (7 << 0) +#define DA732X_DSP_FREQ_12MHZ (0 << 0) +#define DA732X_DSP_FREQ_24MHZ (1 << 0) +#define DA732X_DSP_FREQ_36MHZ (2 << 0) +#define DA732X_DSP_FREQ_48MHZ (3 << 0) +#define DA732X_DSP_FREQ_60MHZ (4 << 0) +#define DA732X_DSP_FREQ_72MHZ (5 << 0) +#define DA732X_DSP_FREQ_84MHZ (6 << 0) +#define DA732X_DSP_FREQ_96MHZ (7 << 0) + +/* DA732X_REG_CLK_EN1 (addr=0x5B) */ +#define DA732X_DSP_CLK_EN (1 << 0) +#define DA732X_SYS3_CLK_EN (1 << 1) +#define DA732X_DSP12_CLK_EN (1 << 2) +#define DA732X_PC_CLK_EN (1 << 3) +#define DA732X_MCLK_SQR_EN (1 << 7) + +/* DA732X_REG_CLK_EN2 (addr=0x5C) */ +#define DA732X_UART_CLK_EN (1 << 1) +#define DA732X_CP_CLK_EN (1 << 2) +#define DA732X_CP_CLK_DIS (0 << 2) + +/* DA732X_REG_CLK_EN3 (addr=0x5D) */ +#define DA732X_ADCA_BB_CLK_EN (1 << 0) +#define DA732X_ADCC_BB_CLK_EN (1 << 4) + +/* DA732X_REG_CLK_EN4 (addr=0x5E) */ +#define DA732X_DACA_BB_CLK_EN (1 << 0) +#define DA732X_DACC_BB_CLK_EN (1 << 4) +#define DA732X_DACA_BB_CLK_SHIFT 0 +#define DA732X_DACC_BB_CLK_SHIFT 4 + +/* DA732X_REG_CLK_EN5 (addr=0x5F) */ +#define DA732X_DACE_BB_CLK_EN (1 << 0) +#define DA732X_DACE_BB_CLK_SHIFT 0 + +/* DA732X_REG_AIF_MCLK (addr=0x60) */ +#define DA732X_AIFM_FRAME_64 (1 << 2) +#define DA732X_AIFM_SRC_SEL_AIFA (1 << 6) +#define DA732X_CLK_GENERATION_AIF_A (1 << 4) +#define DA732X_NO_CLK_GENERATION 0x0 + +/* DA732X_REG_AIFA1 (addr=0x61) */ +#define DA732X_AIF_WORD_MASK (0x3 << 0) +#define DA732X_AIF_WORD_16 (0 << 0) +#define DA732X_AIF_WORD_20 (1 << 0) +#define DA732X_AIF_WORD_24 (2 << 0) +#define DA732X_AIF_WORD_32 (3 << 0) +#define DA732X_AIF_TDM_MONO_SHIFT (1 << 6) +#define DA732X_AIF1_CLK_MASK (1 << 7) +#define DA732X_AIF_SLAVE (0 << 7) +#define DA732X_AIF_CLK_FROM_SRC (1 << 7) + +/* DA732X_REG_AIFA3 (addr=0x63) */ +#define DA732X_AIF_MODE_SHIFT 0 +#define DA732X_AIF_MODE_MASK 0x3 +#define DA732X_AIF_I2S_MODE (0 << 0) +#define DA732X_AIF_LEFT_J_MODE (1 << 0) +#define DA732X_AIF_RIGHT_J_MODE (2 << 0) +#define DA732X_AIF_DSP_MODE (3 << 0) +#define DA732X_AIF_WCLK_INV (1 << 4) +#define DA732X_AIF_BCLK_INV (1 << 5) +#define DA732X_AIF_EN (1 << 7) +#define DA732X_AIF_EN_SHIFT 7 + +/* DA732X_REG_PC_CTRL (addr=0x6a) */ +#define DA732X_PC_PULSE_AIFA (0 << 0) +#define DA732X_PC_PULSE_AIFB (1 << 0) +#define DA732X_PC_RESYNC_AUT (1 << 6) +#define DA732X_PC_RESYNC_NOT_AUT (0 << 6) +#define DA732X_PC_SAME (1 << 7) + +/* DA732X_REG_DATA_ROUTE (addr=0x70) */ +#define DA732X_ADC1_TO_AIFA (0 << 0) +#define DA732X_DSP_TO_AIFA (1 << 0) +#define DA732X_ADC2_TO_AIFB (0 << 1) +#define DA732X_DSP_TO_AIFB (1 << 1) +#define DA732X_AIFA_TO_DAC1L (0 << 2) +#define DA732X_DSP_TO_DAC1L (1 << 2) +#define DA732X_AIFA_TO_DAC1R (0 << 3) +#define DA732X_DSP_TO_DAC1R (1 << 3) +#define DA732X_AIFB_TO_DAC2L (0 << 4) +#define DA732X_DSP_TO_DAC2L (1 << 4) +#define DA732X_AIFB_TO_DAC2R (0 << 5) +#define DA732X_DSP_TO_DAC2R (1 << 5) +#define DA732X_AIFB_TO_DAC3 (0 << 6) +#define DA732X_DSP_TO_DAC3 (1 << 6) +#define DA732X_BYPASS_DSP (0 << 0) +#define DA732X_ALL_TO_DSP (0x7F << 0) + +/* DA732X_REG_DSP_CTRL (addr=0x71) */ +#define DA732X_DIGITAL_EN (1 << 0) +#define DA732X_DIGITAL_RESET (0 << 0) +#define DA732X_DSP_CORE_EN (1 << 1) +#define DA732X_DSP_CORE_RESET (0 << 1) + +/* DA732X_REG_SPARE1_OUT (addr=0x7D)*/ +#define DA732X_HP_DRIVER_EN (1 << 0) +#define DA732X_HP_GATE_LOW (1 << 2) +#define DA732X_HP_LOOP_GAIN_CTRL (1 << 3) + +/* DA732X_REG_ID (addr=0x81)*/ +#define DA732X_ID_MINOR_MASK (0xF << 0) +#define DA732X_ID_MAJOR_MASK (0xF << 4) + +/* DA732X_REG_ADC1/2_PD (addr=0x90/0x98) */ +#define DA732X_ADC_RST_MASK (0x3 << 0) +#define DA732X_ADC_PD_MASK (0x3 << 2) +#define DA732X_ADC_SET_ACT (0x3 << 0) +#define DA732X_ADC_SET_RST (0x0 << 0) +#define DA732X_ADC_ON (0x3 << 2) +#define DA732X_ADC_OFF (0x0 << 2) + +/* DA732X_REG_ADC1/2_SEL (addr=0x94/0x9C) */ +#define DA732X_ADC_VOL_VAL_MASK 0x7 +#define DA732X_ADCL_VOL_SHIFT 0 +#define DA732X_ADCR_VOL_SHIFT 4 +#define DA732X_ADCL_EN_SHIFT 2 +#define DA732X_ADCR_EN_SHIFT 3 +#define DA732X_ADCL_EN (1 << 2) +#define DA732X_ADCR_EN (1 << 3) +#define DA732X_ADC_VOL_VAL_MAX DA732X_ADC_VOL_VAL_MASK + +/* + * DA732X_REG_ADC1/2_HPF (addr=0x93/0x9b) + * DA732x_REG_DAC1/2/3_HPG (addr=0xA5/0xB5/0xC5) + */ +#define DA732X_HPF_MUSIC_EN (1 << 3) +#define DA732X_HPF_VOICE_EN ((1 << 3) | (1 << 7)) +#define DA732X_HPF_MASK ((1 << 3) | (1 << 7)) +#define DA732X_HPF_DIS ((0 << 3) | (0 << 7)) + +/* DA732X_REG_DAC1/2/3_VOL */ +#define DA732X_DAC_VOL_VAL_MASK 0x7F +#define DA732X_DAC_VOL_SHIFT 0 +#define DA732X_DAC_VOL_VAL_MAX DA732X_DAC_VOL_VAL_MASK + +/* DA732X_REG_DAC1/2/3_SEL (addr=0xA3/0xB3/0xC3) */ +#define DA732X_DACL_EN_SHIFT 3 +#define DA732X_DACR_EN_SHIFT 7 +#define DA732X_DACL_MUTE_SHIFT 2 +#define DA732X_DACR_MUTE_SHIFT 6 +#define DA732X_DACL_EN (1 << 3) +#define DA732X_DACR_EN (1 << 7) +#define DA732X_DACL_SDM (1 << 0) +#define DA732X_DACR_SDM (1 << 4) +#define DA732X_DACL_MUTE (1 << 2) +#define DA732X_DACR_MUTE (1 << 6) + +/* DA732X_REG_DAC_SOFTMUTE (addr=0xA4/0xB4/0xC4) */ +#define DA732X_SOFTMUTE_EN (1 << 7) +#define DA732X_GAIN_RAMPED (1 << 6) +#define DA732X_16_SAMPLES (4 << 0) +#define DA732X_SOFTMUTE_MASK (1 << 7) +#define DA732X_SOFTMUTE_SHIFT 7 + +/* + * DA732x_REG_ADC1/2_EQ12 (addr=0x95/0x9D) + * DA732x_REG_ADC1/2_EQ34 (addr=0x96/0x9E) + * DA732x_REG_ADC1/2_EQ5 (addr=0x97/0x9F) + * DA732x_REG_DAC1/2/3_EQ12 (addr=0xA5/0xB5/0xC5) + * DA732x_REG_DAC1/2/3_EQ34 (addr=0xA6/0xB6/0xC6) + * DA732x_REG_DAC1/2/3_EQ5 (addr=0xA7/0xB7/0xB7) + */ +#define DA732X_EQ_VOL_VAL_MASK 0xF +#define DA732X_EQ_BAND1_SHIFT 0 +#define DA732X_EQ_BAND2_SHIFT 4 +#define DA732X_EQ_BAND3_SHIFT 0 +#define DA732X_EQ_BAND4_SHIFT 4 +#define DA732X_EQ_BAND5_SHIFT 0 +#define DA732X_EQ_OVERALL_SHIFT 4 +#define DA732X_EQ_OVERALL_VOL_VAL_MASK 0x3 +#define DA732X_EQ_DIS (0 << 7) +#define DA732X_EQ_EN (1 << 7) +#define DA732X_EQ_EN_SHIFT 7 +#define DA732X_EQ_VOL_VAL_MAX DA732X_EQ_VOL_VAL_MASK +#define DA732X_EQ_OVERALL_VOL_VAL_MAX DA732X_EQ_OVERALL_VOL_VAL_MASK + +/* DA732X_REG_DMA_CMD (addr=0xD3) */ +#define DA732X_SEL_DSP_DMA_MASK (3 << 0) +#define DA732X_SEL_DSP_DMA_DIS (0 << 0) +#define DA732X_SEL_DSP_DMA_PMEM (1 << 0) +#define DA732X_SEL_DSP_DMA_XMEM (2 << 0) +#define DA732X_SEL_DSP_DMA_YMEM (3 << 0) +#define DA732X_DSP_RW_MASK (1 << 4) +#define DA732X_DSP_DMA_WRITE (0 << 4) +#define DA732X_DSP_DMA_READ (1 << 4) + +/* DA732X_REG_DMA_STATUS (addr=0xDA) */ +#define DA732X_DSP_DMA_FREE (0 << 0) +#define DA732X_DSP_DMA_BUSY (1 << 0) + +#endif /* __DA732X_REG_H_ */ -- GitLab From 1bb49303b7a82eb9bce0595087523343683abdf0 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 11 Jun 2012 13:26:50 +0100 Subject: [PATCH 0424/5711] GFS2: Use seq_vprintf for glocks debugfs file Make use of the newly added seq_vprintf() function. Signed-off-by: Steven Whitehouse Reported-by: Eric Dumazet Acked-by: Al Viro --- fs/gfs2/glock.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 10ae1645d9a5..4d5d63d9d2c0 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -51,7 +51,6 @@ struct gfs2_glock_iter { struct gfs2_sbd *sdp; /* incore superblock */ struct gfs2_glock *gl; /* current glock struct */ loff_t last_pos; /* last position */ - char string[512]; /* scratch space */ }; typedef void (*glock_examiner) (struct gfs2_glock * gl); @@ -951,9 +950,7 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) va_start(args, fmt); if (seq) { - struct gfs2_glock_iter *gi = seq->private; - vsprintf(gi->string, fmt, args); - seq_puts(seq, gi->string); + seq_vprintf(seq, fmt, args); } else { vaf.fmt = fmt; vaf.va = &args; -- GitLab From 0fe2f1e929ecabf834f4af2ffd300fe70700f4b3 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 11 Jun 2012 13:49:47 +0100 Subject: [PATCH 0425/5711] GFS2: Size seq_file buffer more carefully This places a limit on the buffer size for archs with larger PAGE_SIZE. Signed-off-by: Steven Whitehouse Reported-by: Eric Dumazet --- fs/gfs2/glock.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 4d5d63d9d2c0..1ed81f40da0d 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1977,6 +1977,8 @@ static const struct seq_operations gfs2_sbstats_seq_ops = { .show = gfs2_sbstats_seq_show, }; +#define GFS2_SEQ_GOODSIZE min(PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER, 65536UL) + static int gfs2_glocks_open(struct inode *inode, struct file *file) { int ret = seq_open_private(file, &gfs2_glock_seq_ops, @@ -1985,9 +1987,9 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) struct seq_file *seq = file->private_data; struct gfs2_glock_iter *gi = seq->private; gi->sdp = inode->i_private; - seq->buf = kmalloc(8*PAGE_SIZE, GFP_KERNEL | __GFP_NOWARN); + seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); if (seq->buf) - seq->size = 8*PAGE_SIZE; + seq->size = GFS2_SEQ_GOODSIZE; } return ret; } @@ -2000,9 +2002,9 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) struct seq_file *seq = file->private_data; struct gfs2_glock_iter *gi = seq->private; gi->sdp = inode->i_private; - seq->buf = kmalloc(8*PAGE_SIZE, GFP_KERNEL | __GFP_NOWARN); + seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); if (seq->buf) - seq->size = 8*PAGE_SIZE; + seq->size = GFS2_SEQ_GOODSIZE; } return ret; } -- GitLab From 53f2d02898755d1b24bde1975e202815d29fdb81 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Feb 2012 08:10:34 -0300 Subject: [PATCH 0426/5711] RAS: Add a tracepoint for reporting memory controller events Add a new tracepoint-based hardware events report method for reporting Memory Controller events. Part of the description bellow is shamelessly copied from Tony Luck's notes about the Hardware Error BoF during LPC 2010 [1]. Tony, thanks for your notes and discussions to generate the h/w error reporting requirements. [1] http://lwn.net/Articles/416669/ We have several subsystems & methods for reporting hardware errors: 1) EDAC ("Error Detection and Correction"). In its original form this consisted of a platform specific driver that read topology information and error counts from chipset registers and reported the results via a sysfs interface. 2) mcelog - x86 specific decoding of machine check bank registers reporting in binary form via /dev/mcelog. Recent additions make use of the APEI extensions that were documented in version 4.0a of the ACPI specification to acquire more information about errors without having to rely reading chipset registers directly. A user level programs decodes into somewhat human readable format. 3) drivers/edac/mce_amd.c - this driver hooks into the mcelog path and decodes errors reported via machine check bank registers in AMD processors to the console log using printk(); Each of these mechanisms has a band of followers ... and none of them appear to meet all the needs of all users. As part of a RAS subsystem, let's encapsulate the memory error hardware events into a trace facility. The tracepoint printk will be displayed like: mc_event: [quant] (Corrected|Uncorrected|Fatal) error:[error msg] on [label] ([location] [edac_mc detail] [driver_detail] Where: [quant] is the quantity of errors [error msg] is the driver-specific error message (e. g. "memory read", "bus error", ...); [location] is the location in terms of memory controller and branch/channel/slot, channel/slot or csrow/channel; [label] is the memory stick label; [edac_mc detail] describes the address location of the error and the syndrome; [driver detail] is driver-specifig error message details, when needed/provided (e. g. "area:DMA", ...) For example: mc_event: 1 Corrected error:memory read on memory stick DIMM_1A (mc:0 location:0:0:0 page:0x586b6e offset:0xa66 grain:32 syndrome:0x0 area:DMA) Of course, any userspace tools meant to handle errors should not parse the above data. They should, instead, use the binary fields provided by the tracepoint, mapping them directly into their Management Information Base. NOTE: The original patch was providing an additional mechanism for MCA-based trace events that also contained MCA error register data. However, as no agreement was reached so far for the MCA-based trace events, for now, let's add events only for memory errors. A latter patch is planned to change the tracepoint, for those types of event. Cc: Aristeu Rozanski Cc: Doug Thompson Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_core.h | 8 +-- drivers/edac/edac_mc.c | 72 +++++++++++++++++++++------ include/ras/ras_event.h | 102 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 include/ras/ras_event.h diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index f06ce9ab692c..740c7e22c023 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -463,12 +463,12 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, - const int layer0, - const int layer1, - const int layer2, + const int top_layer, + const int mid_layer, + const int low_layer, const char *msg, const char *other_detail, - const void *mcelog); + const void *arch_log); /* * edac_device APIs diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 10f375032e96..ce25750a83f9 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -27,12 +27,17 @@ #include #include #include +#include #include #include #include #include "edac_core.h" #include "edac_module.h" +#define CREATE_TRACE_POINTS +#define TRACE_INCLUDE_PATH ../../include/ras +#include + /* lock to memory controller's control array */ static DEFINE_MUTEX(mem_ctls_mutex); static LIST_HEAD(mc_devices); @@ -384,6 +389,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, * which will perform kobj unregistration and the actual free * will occur during the kobject callback operation */ + return mci; } EXPORT_SYMBOL_GPL(edac_mc_alloc); @@ -902,19 +908,19 @@ static void edac_ce_error(struct mem_ctl_info *mci, const bool enable_per_layer_report, const unsigned long page_frame_number, const unsigned long offset_in_page, - u32 grain) + long grain) { unsigned long remapped_page; if (edac_mc_get_log_ce()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s%s - %s)\n", + "CE %s on %s (%s %s - %s)\n", msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s%s)\n", + "CE %s on %s (%s %s)\n", msg, label, location, detail); } @@ -953,12 +959,12 @@ static void edac_ue_error(struct mem_ctl_info *mci, if (edac_mc_get_log_ue()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s%s - %s)\n", + "UE %s on %s (%s %s - %s)\n", msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s%s)\n", + "UE %s on %s (%s %s)\n", msg, label, location, detail); } @@ -975,27 +981,50 @@ static void edac_ue_error(struct mem_ctl_info *mci, } #define OTHER_LABEL " or " + +/** + * edac_mc_handle_error - reports a memory event to userspace + * + * @type: severity of the error (CE/UE/Fatal) + * @mci: a struct mem_ctl_info pointer + * @page_frame_number: mem page where the error occurred + * @offset_in_page: offset of the error inside the page + * @syndrome: ECC syndrome + * @top_layer: Memory layer[0] position + * @mid_layer: Memory layer[1] position + * @low_layer: Memory layer[2] position + * @msg: Message meaningful to the end users that + * explains the event + * @other_detail: Technical details about the event that + * may help hardware manufacturers and + * EDAC developers to analyse the event + * @arch_log: Architecture-specific struct that can + * be used to add extended information to the + * tracepoint, like dumping MCE registers. + */ void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, - const int layer0, - const int layer1, - const int layer2, + const int top_layer, + const int mid_layer, + const int low_layer, const char *msg, const char *other_detail, - const void *mcelog) + const void *arch_log) { /* FIXME: too much for stack: move it to some pre-alocated area */ char detail[80], location[80]; char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * mci->tot_dimms]; char *p; int row = -1, chan = -1; - int pos[EDAC_MAX_LAYERS] = { layer0, layer1, layer2 }; + int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer }; int i; - u32 grain; + long grain; bool enable_per_layer_report = false; + u16 error_count; /* FIXME: make it a parameter */ + u8 grain_bits; debugf3("MC%d: %s()\n", mci->mc_idx, __func__); @@ -1045,11 +1074,11 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, for (i = 0; i < mci->tot_dimms; i++) { struct dimm_info *dimm = &mci->dimms[i]; - if (layer0 >= 0 && layer0 != dimm->location[0]) + if (top_layer >= 0 && top_layer != dimm->location[0]) continue; - if (layer1 >= 0 && layer1 != dimm->location[1]) + if (mid_layer >= 0 && mid_layer != dimm->location[1]) continue; - if (layer2 >= 0 && layer2 != dimm->location[2]) + if (low_layer >= 0 && low_layer != dimm->location[2]) continue; /* get the max grain, over the error match range */ @@ -1120,11 +1149,22 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, edac_layer_name[mci->layers[i].type], pos[i]); } + if (p > location) + *(p - 1) = '\0'; + + /* Report the error via the trace interface */ + + error_count = 1; /* FIXME: allow change it */ + grain_bits = fls_long(grain) + 1; + trace_mc_event(type, msg, label, error_count, + mci->mc_idx, top_layer, mid_layer, low_layer, + PAGES_TO_MiB(page_frame_number) | offset_in_page, + grain_bits, syndrome, other_detail); /* Memory type dependent details about the error */ if (type == HW_EVENT_ERR_CORRECTED) { snprintf(detail, sizeof(detail), - "page:0x%lx offset:0x%lx grain:%d syndrome:0x%lx", + "page:0x%lx offset:0x%lx grain:%ld syndrome:0x%lx", page_frame_number, offset_in_page, grain, syndrome); edac_ce_error(mci, pos, msg, location, label, detail, @@ -1132,7 +1172,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, page_frame_number, offset_in_page, grain); } else { snprintf(detail, sizeof(detail), - "page:0x%lx offset:0x%lx grain:%d", + "page:0x%lx offset:0x%lx grain:%ld", page_frame_number, offset_in_page, grain); edac_ue_error(mci, pos, msg, location, label, detail, diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h new file mode 100644 index 000000000000..260470e72483 --- /dev/null +++ b/include/ras/ras_event.h @@ -0,0 +1,102 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ras +#define TRACE_INCLUDE_FILE ras_event + +#if !defined(_TRACE_HW_EVENT_MC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HW_EVENT_MC_H + +#include +#include +#include + +/* + * Hardware Events Report + * + * Those events are generated when hardware detected a corrected or + * uncorrected event, and are meant to replace the current API to report + * errors defined on both EDAC and MCE subsystems. + * + * FIXME: Add events for handling memory errors originated from the + * MCE subsystem. + */ + +/* + * Hardware-independent Memory Controller specific events + */ + +/* + * Default error mechanisms for Memory Controller errors (CE and UE) + */ +TRACE_EVENT(mc_event, + + TP_PROTO(const unsigned int err_type, + const char *error_msg, + const char *label, + const int error_count, + const u8 mc_index, + const s8 top_layer, + const s8 mid_layer, + const s8 low_layer, + unsigned long address, + const u8 grain_bits, + unsigned long syndrome, + const char *driver_detail), + + TP_ARGS(err_type, error_msg, label, error_count, mc_index, + top_layer, mid_layer, low_layer, address, grain_bits, + syndrome, driver_detail), + + TP_STRUCT__entry( + __field( unsigned int, error_type ) + __string( msg, error_msg ) + __string( label, label ) + __field( u16, error_count ) + __field( u8, mc_index ) + __field( s8, top_layer ) + __field( s8, middle_layer ) + __field( s8, lower_layer ) + __field( long, address ) + __field( u8, grain_bits ) + __field( long, syndrome ) + __string( driver_detail, driver_detail ) + ), + + TP_fast_assign( + __entry->error_type = err_type; + __assign_str(msg, error_msg); + __assign_str(label, label); + __entry->error_count = error_count; + __entry->mc_index = mc_index; + __entry->top_layer = top_layer; + __entry->middle_layer = mid_layer; + __entry->lower_layer = low_layer; + __entry->address = address; + __entry->grain_bits = grain_bits; + __entry->syndrome = syndrome; + __assign_str(driver_detail, driver_detail); + ), + + TP_printk("%d %s error%s:%s%s on %s (mc:%d location:%d:%d:%d address:0x%08lx grain:%d syndrome:0x%08lx%s%s)", + __entry->error_count, + (__entry->error_type == HW_EVENT_ERR_CORRECTED) ? "Corrected" : + ((__entry->error_type == HW_EVENT_ERR_FATAL) ? + "Fatal" : "Uncorrected"), + __entry->error_count > 1 ? "s" : "", + ((char *)__get_str(msg))[0] ? " " : "", + __get_str(msg), + __get_str(label), + __entry->mc_index, + __entry->top_layer, + __entry->middle_layer, + __entry->lower_layer, + __entry->address, + 1 << __entry->grain_bits, + __entry->syndrome, + ((char *)__get_str(driver_detail))[0] ? " " : "", + __get_str(driver_detail)) +); + +#endif /* _TRACE_HW_EVENT_MC_H */ + +/* This part must be outside protection */ +#include -- GitLab From fd687502dc8037aa5a4b84c570ada971106574ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 16 Mar 2012 07:44:18 -0300 Subject: [PATCH 0427/5711] edac: Rename the parent dev to pdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As EDAC doesn't use struct device itself, it created a parent dev pointer called as "pdev". Now that we'll be converting it to use struct device, instead of struct devsys, this needs to be fixed. No functional changes. Reviewed-by: Aristeu Rozanski Acked-by: Chris Metcalf Cc: Doug Thompson Cc: Borislav Petkov Cc: Mark Gross Cc: Jason Uhlenkott Cc: Tim Small Cc: Ranganathan Desikan Cc: "Arvind R." Cc: Olof Johansson Cc: Egor Martovetsky Cc: Michal Marek Cc: Jiri Kosina Cc: Joe Perches Cc: Dmitry Eremin-Solenikov Cc: Benjamin Herrenschmidt Cc: Hitoshi Mitake Cc: Andrew Morton Cc: "Niklas Söderlund" Cc: Shaohui Xie Cc: Josh Boyer Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 2 +- drivers/edac/amd76x_edac.c | 4 ++-- drivers/edac/cell_edac.c | 12 ++++++------ drivers/edac/cpc925_edac.c | 2 +- drivers/edac/e752x_edac.c | 2 +- drivers/edac/e7xxx_edac.c | 2 +- drivers/edac/edac_mc.c | 8 ++++---- drivers/edac/edac_mc_sysfs.c | 2 +- drivers/edac/i3000_edac.c | 4 ++-- drivers/edac/i3200_edac.c | 6 +++--- drivers/edac/i5000_edac.c | 2 +- drivers/edac/i5100_edac.c | 2 +- drivers/edac/i5400_edac.c | 2 +- drivers/edac/i7300_edac.c | 2 +- drivers/edac/i7core_edac.c | 4 ++-- drivers/edac/i82443bxgx_edac.c | 4 ++-- drivers/edac/i82860_edac.c | 4 ++-- drivers/edac/i82875p_edac.c | 4 ++-- drivers/edac/i82975x_edac.c | 4 ++-- drivers/edac/mpc85xx_edac.c | 4 ++-- drivers/edac/mv64x60_edac.c | 2 +- drivers/edac/pasemi_edac.c | 6 +++--- drivers/edac/ppc4xx_edac.c | 8 ++++---- drivers/edac/r82600_edac.c | 4 ++-- drivers/edac/sb_edac.c | 4 ++-- drivers/edac/tile_edac.c | 4 ++-- drivers/edac/x38_edac.c | 6 +++--- include/linux/edac.h | 2 +- 28 files changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7be9b7288e90..821bc2cdd2de 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2601,7 +2601,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) goto err_siblings; mci->pvt_info = pvt; - mci->dev = &pvt->F2->dev; + mci->pdev = &pvt->F2->dev; setup_mci_misc_attrs(mci, fam_type); diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 9774d443fa57..7439786f3bef 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -105,7 +105,7 @@ static void amd76x_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &info->ecc_mode_status); @@ -257,7 +257,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) return -ENOMEM; debugf0("%s(): mci = %p\n", __func__, mci); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = ems_mode ? diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 69ee6aab5c71..2e5b95374dc6 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -36,7 +36,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) struct csrow_info *csrow = &mci->csrows[0]; unsigned long address, pfn, offset, syndrome; - dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", + dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", priv->node, chan, ar); /* Address decoding is likely a bit bogus, to dbl check */ @@ -59,7 +59,7 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) struct csrow_info *csrow = &mci->csrows[0]; unsigned long address, pfn, offset; - dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", + dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", priv->node, chan, ar); /* Address decoding is likely a bit bogus, to dbl check */ @@ -83,7 +83,7 @@ static void cell_edac_check(struct mem_ctl_info *mci) fir = in_be64(&priv->regs->mic_fir); #ifdef DEBUG if (fir != priv->prev_fir) { - dev_dbg(mci->dev, "fir change : 0x%016lx\n", fir); + dev_dbg(mci->pdev, "fir change : 0x%016lx\n", fir); priv->prev_fir = fir; } #endif @@ -119,7 +119,7 @@ static void cell_edac_check(struct mem_ctl_info *mci) mb(); /* sync up */ #ifdef DEBUG fir = in_be64(&priv->regs->mic_fir); - dev_dbg(mci->dev, "fir clear : 0x%016lx\n", fir); + dev_dbg(mci->pdev, "fir clear : 0x%016lx\n", fir); #endif } } @@ -155,7 +155,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) dimm->edac_mode = EDAC_SECDED; dimm->nr_pages = nr_pages / csrow->nr_channels; } - dev_dbg(mci->dev, + dev_dbg(mci->pdev, "Initialized on node %d, chanmask=0x%x," " first_page=0x%lx, nr_pages=0x%x\n", priv->node, priv->chanmask, @@ -212,7 +212,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) priv->regs = regs; priv->node = pdev->id; priv->chanmask = chanmask; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_XDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index e22030a9de66..9488723f8138 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -995,7 +995,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) pdata->edac_idx = edac_mc_idx++; pdata->name = pdev->name; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; platform_set_drvdata(pdev, mci); mci->dev_name = dev_name(&pdev->dev); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 3186512c9739..d75660634b43 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1308,7 +1308,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E752X_REVISION; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; debugf3("%s(): init pvt\n", __func__); pvt = (struct e752x_pvt *)mci->pvt_info; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 9a9c1a546797..b111266dadf3 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -458,7 +458,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E7XXX_REVISION; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; debugf3("%s(): init pvt\n", __func__); pvt = (struct e7xxx_pvt *)mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index ce25750a83f9..811f09a38f3a 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -93,7 +93,7 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) mci->nr_csrows, mci->csrows); debugf3("\tmci->nr_dimms = %d, dimms = %p\n", mci->tot_dimms, mci->dimms); - debugf3("\tdev = %p\n", mci->dev); + debugf3("\tdev = %p\n", mci->pdev); debugf3("\tmod_name:ctl_name = %s:%s\n", mci->mod_name, mci->ctl_name); debugf3("\tpvt_info = %p\n\n", mci->pvt_info); } @@ -428,7 +428,7 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev) list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); - if (mci->dev == dev) + if (mci->pdev == dev) return mci; } @@ -580,7 +580,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) insert_before = &mc_devices; - p = find_mci_by_dev(mci->dev); + p = find_mci_by_dev(mci->pdev); if (unlikely(p != NULL)) goto fail0; @@ -602,7 +602,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) fail0: edac_printk(KERN_WARNING, EDAC_MC, - "%s (%s) %s %s already assigned %d\n", dev_name(p->dev), + "%s (%s) %s %s already assigned %d\n", dev_name(p->pdev), edac_dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx); return 1; diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index f6a29b0eedc8..595371941ef9 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -916,7 +916,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) INIT_LIST_HEAD(&mci->grp_kobj_list); /* create a symlink for the device */ - err = sysfs_create_link(kobj_mci, &mci->dev->kobj, + err = sysfs_create_link(kobj_mci, &mci->pdev->kobj, EDAC_DEVICE_SYMLINK); if (err) { debugf1("%s() failure to create symlink\n", __func__); diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 8ad1744faacd..d1ebd9b9ad6f 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -194,7 +194,7 @@ static void i3000_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -368,7 +368,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) debugf3("MC: %s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index bbe43ef71823..600a05df3759 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -159,7 +159,7 @@ static void i3200_clear_error_info(struct mem_ctl_info *mci) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * Clear any error bits. @@ -176,7 +176,7 @@ static void i3200_get_and_clear_error_info(struct mem_ctl_info *mci, struct i3200_priv *priv = mci->pvt_info; void __iomem *window = priv->window; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -354,7 +354,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) debugf3("MC: %s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 11ea835f155a..a69245ad5f32 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1409,7 +1409,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) kobject_get(&mci->edac_mci_kobj); debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->system_address = pdev; /* Record this device in our private */ diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index e9e7c2a29dc3..19aa2843c46a 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -943,7 +943,7 @@ static int __devinit i5100_init_one(struct pci_dev *pdev, goto bail_disable_ch1; } - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; priv = mci->pvt_info; priv->ranksperchan = ranksperch; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 6640c29e1885..ba60694437bd 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1299,7 +1299,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->system_address = pdev; /* Record this device in our private */ diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 97c22fd650ee..db84456e65d9 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1057,7 +1057,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */ diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index c05e1ada7a3d..598d215f7bd5 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -2122,7 +2122,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) i7core_pci_ctl_release(pvt); /* Remove MC sysfs nodes */ - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); debugf1("%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); @@ -2188,7 +2188,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* Get dimm basic config */ get_dimm_config(mci); /* record ptr to the generic device */ - mci->dev = &i7core_dev->pdev[0]->dev; + mci->pdev = &i7core_dev->pdev[0]->dev; /* Set the function pointer to an actual operation function */ mci->edac_check = i7core_check_error; diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 52072c28a8a6..65fd2e1eceb8 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -124,7 +124,7 @@ static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci, *info) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, I82443BXGX_EAP, &info->eap); if (info->eap & I82443BXGX_EAP_OFFSET_SBE) /* Clear error to allow next error to be reported [p.61] */ @@ -260,7 +260,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) return -ENOMEM; debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc); diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 08045059d10b..8f3350000942 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -67,7 +67,7 @@ static void i82860_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -211,7 +211,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) return -ENOMEM; debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; /* I"m not sure about this but I think that all RDRAM is SECDED */ diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index b613e31c16e5..1cc682d0678d 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -189,7 +189,7 @@ static void i82875p_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -430,7 +430,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) kobject_get(&mci->edac_mci_kobj); debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_UNKNOWN; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 433332c7cdba..8b26401efa19 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -241,7 +241,7 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -559,7 +559,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 4c402353ba98..67fb3280f333 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -989,9 +989,9 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) pdata = mci->pvt_info; pdata->name = "mpc85xx_mc_err"; pdata->irq = NO_IRQ; - mci->dev = &op->dev; + mci->pdev = &op->dev; pdata->edac_idx = edac_mc_idx++; - dev_set_drvdata(mci->dev, mci); + dev_set_drvdata(mci->pdev, mci); mci->ctl_name = pdata->name; mci->dev_name = pdata->name; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index b0bb5a3d2527..ff6b8e248e89 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -724,7 +724,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) } pdata = mci->pvt_info; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; platform_set_drvdata(pdev, mci); pdata->name = "mv64x60_mc_err"; pdata->irq = NO_IRQ; diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index b095a906a994..92becaa8722a 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -74,7 +74,7 @@ static int system_mmc_id; static u32 pasemi_edac_get_error_info(struct mem_ctl_info *mci) { - struct pci_dev *pdev = to_pci_dev(mci->dev); + struct pci_dev *pdev = to_pci_dev(mci->pdev); u32 tmp; pci_read_config_dword(pdev, MCDEBUG_ERRSTA, @@ -95,7 +95,7 @@ static u32 pasemi_edac_get_error_info(struct mem_ctl_info *mci) static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) { - struct pci_dev *pdev = to_pci_dev(mci->dev); + struct pci_dev *pdev = to_pci_dev(mci->pdev); u32 errlog1a; u32 cs; @@ -225,7 +225,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev, MCCFG_ERRCOR_ECC_GEN_EN | MCCFG_ERRCOR_ECC_CRR_EN; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = (errcor & MCCFG_ERRCOR_ECC_GEN_EN) ? diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index f3f9fed06ad7..53519828cc36 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -1027,9 +1027,9 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, /* Initial driver pointers and private data */ - mci->dev = &op->dev; + mci->pdev = &op->dev; - dev_set_drvdata(mci->dev, mci); + dev_set_drvdata(mci->pdev, mci); pdata = mci->pvt_info; @@ -1334,7 +1334,7 @@ static int __devinit ppc4xx_edac_probe(struct platform_device *op) return 0; fail1: - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); fail: edac_mc_free(mci); @@ -1368,7 +1368,7 @@ ppc4xx_edac_remove(struct platform_device *op) dcr_unmap(pdata->dcr_host, SDRAM_DCR_RESOURCE_LEN); - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); edac_mc_free(mci); return 0; diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index e1cacd164f31..cf4ccbdba85d 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -140,7 +140,7 @@ static void r82600_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, R82600_EAP, &info->eapr); if (info->eapr & BIT(0)) @@ -296,7 +296,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) return -ENOMEM; debugf0("%s(): mci = %p\n", __func__, mci); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; /* FIXME try to work out if the chip leads have been used for COM2 diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index e834dfd034d6..efa488357ae6 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1607,7 +1607,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) mce_unregister_decode_chain(&sbridge_mce_dec); /* Remove MC sysfs nodes */ - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); debugf1("%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); @@ -1672,7 +1672,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) get_memory_layout(mci); /* record ptr to the generic device */ - mci->dev = &sbridge_dev->pdev[0]->dev; + mci->pdev = &sbridge_dev->pdev[0]->dev; /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 7bb4614730db..604bc4df653a 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -69,7 +69,7 @@ static void tile_edac_check(struct mem_ctl_info *mci) /* Check if the current error count is different from the saved one. */ if (mem_error.sbe_count != priv->ce_count) { - dev_dbg(mci->dev, "ECC CE err on node %d\n", priv->node); + dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node); priv->ce_count = mem_error.sbe_count; edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, @@ -149,7 +149,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev) priv->node = pdev->id; priv->hv_devhdl = hv_devhdl; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 1ac7962d63ea..f9506f26e2bf 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -151,7 +151,7 @@ static void x38_clear_error_info(struct mem_ctl_info *mci) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * Clear any error bits. @@ -172,7 +172,7 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, struct pci_dev *pdev; void __iomem *window = mci->pvt_info; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -354,7 +354,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) debugf3("MC: %s(): init mci\n", __func__); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; diff --git a/include/linux/edac.h b/include/linux/edac.h index 91ba3bae42ee..ec1b5278b4cc 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -567,7 +567,7 @@ struct mem_ctl_info { * unique. dev pointer should be sufficiently unique, but * BUS:SLOT.FUNC numbers may not be unique. */ - struct device *dev; + struct device *pdev; const char *mod_name; const char *mod_ver; const char *ctl_name; -- GitLab From b0610bb82abd1c4ac97c33f0312cd7fd72eaa325 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 16:21:07 -0300 Subject: [PATCH 0428/5711] edac: use Documentation-nano format for some data structs No functional changes. Just comment improvements. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- include/linux/edac.h | 82 +++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/include/linux/edac.h b/include/linux/edac.h index ec1b5278b4cc..4e32e8d31e0a 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -49,7 +49,19 @@ static inline void opstate_init(void) #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 -/* memory devices */ +/** + * enum dev_type - describe the type of memory DRAM chips used at the stick + * @DEV_UNKNOWN: Can't be determined, or MC doesn't support detect it + * @DEV_X1: 1 bit for data + * @DEV_X2: 2 bits for data + * @DEV_X4: 4 bits for data + * @DEV_X8: 8 bits for data + * @DEV_X16: 16 bits for data + * @DEV_X32: 32 bits for data + * @DEV_X64: 64 bits for data + * + * Typical values are x4 and x8. + */ enum dev_type { DEV_UNKNOWN = 0, DEV_X1, @@ -167,18 +179,30 @@ enum mem_type { #define MEM_FLAG_DDR3 BIT(MEM_DDR3) #define MEM_FLAG_RDDR3 BIT(MEM_RDDR3) -/* chipset Error Detection and Correction capabilities and mode */ +/** + * enum edac-type - Error Detection and Correction capabilities and mode + * @EDAC_UNKNOWN: Unknown if ECC is available + * @EDAC_NONE: Doesn't support ECC + * @EDAC_RESERVED: Reserved ECC type + * @EDAC_PARITY: Detects parity errors + * @EDAC_EC: Error Checking - no correction + * @EDAC_SECDED: Single bit error correction, Double detection + * @EDAC_S2ECD2ED: Chipkill x2 devices - do these exist? + * @EDAC_S4ECD4ED: Chipkill x4 devices + * @EDAC_S8ECD8ED: Chipkill x8 devices + * @EDAC_S16ECD16ED: Chipkill x16 devices + */ enum edac_type { - EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ - EDAC_NONE, /* Doesn't support ECC */ - EDAC_RESERVED, /* Reserved ECC type */ - EDAC_PARITY, /* Detects parity errors */ - EDAC_EC, /* Error Checking - no correction */ - EDAC_SECDED, /* Single bit error correction, Double detection */ - EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */ - EDAC_S4ECD4ED, /* Chipkill x4 devices */ - EDAC_S8ECD8ED, /* Chipkill x8 devices */ - EDAC_S16ECD16ED, /* Chipkill x16 devices */ + EDAC_UNKNOWN = 0, + EDAC_NONE, + EDAC_RESERVED, + EDAC_PARITY, + EDAC_EC, + EDAC_SECDED, + EDAC_S2ECD2ED, + EDAC_S4ECD4ED, + EDAC_S8ECD8ED, + EDAC_S16ECD16ED, }; #define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN) @@ -191,18 +215,30 @@ enum edac_type { #define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED) #define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED) -/* scrubbing capabilities */ +/** + * enum scrub_type - scrubbing capabilities + * @SCRUB_UNKNOWN Unknown if scrubber is available + * @SCRUB_NONE: No scrubber + * @SCRUB_SW_PROG: SW progressive (sequential) scrubbing + * @SCRUB_SW_SRC: Software scrub only errors + * @SCRUB_SW_PROG_SRC: Progressive software scrub from an error + * @SCRUB_SW_TUNABLE: Software scrub frequency is tunable + * @SCRUB_HW_PROG: HW progressive (sequential) scrubbing + * @SCRUB_HW_SRC: Hardware scrub only errors + * @SCRUB_HW_PROG_SRC: Progressive hardware scrub from an error + * SCRUB_HW_TUNABLE: Hardware scrub frequency is tunable + */ enum scrub_type { - SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */ - SCRUB_NONE, /* No scrubber */ - SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */ - SCRUB_SW_SRC, /* Software scrub only errors */ - SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */ - SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */ - SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */ - SCRUB_HW_SRC, /* Hardware scrub only errors */ - SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */ - SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */ + SCRUB_UNKNOWN = 0, + SCRUB_NONE, + SCRUB_SW_PROG, + SCRUB_SW_SRC, + SCRUB_SW_PROG_SRC, + SCRUB_SW_TUNABLE, + SCRUB_HW_PROG, + SCRUB_HW_SRC, + SCRUB_HW_PROG_SRC, + SCRUB_HW_TUNABLE }; #define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG) -- GitLab From ef4459341a600703e99a08584350809a96b62371 Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Thu, 24 May 2012 11:43:32 -0500 Subject: [PATCH 0429/5711] staging: omapdrm: Fix error paths during dmm init Failures during the dmm probe can cause the kernel to crash. Moved the spinlock to a global and moved list initializations immediately after the allocation of the dmm private structure. Signed-off-by: Andy Gross Reviewed-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_dmm_priv.h | 1 - drivers/staging/omapdrm/omap_dmm_tiler.c | 44 +++++++++++++----------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h index 2f529ab4b7c7..08b22e9f0ed7 100644 --- a/drivers/staging/omapdrm/omap_dmm_priv.h +++ b/drivers/staging/omapdrm/omap_dmm_priv.h @@ -181,7 +181,6 @@ struct dmm { /* allocation list and lock */ struct list_head alloc_head; - spinlock_t list_lock; }; #endif diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 9d83060e753a..86197831f63e 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -40,6 +40,9 @@ static struct tcm *containers[TILFMT_NFORMATS]; static struct dmm *omap_dmm; +/* global spinlock for protecting lists */ +static DEFINE_SPINLOCK(list_lock); + /* Geometry table */ #define GEOM(xshift, yshift, bytes_per_pixel) { \ .x_shft = (xshift), \ @@ -147,13 +150,13 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm) down(&dmm->engine_sem); /* grab an idle engine */ - spin_lock(&dmm->list_lock); + spin_lock(&list_lock); if (!list_empty(&dmm->idle_head)) { engine = list_entry(dmm->idle_head.next, struct refill_engine, idle_node); list_del(&engine->idle_node); } - spin_unlock(&dmm->list_lock); + spin_unlock(&list_lock); BUG_ON(!engine); @@ -256,9 +259,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) } cleanup: - spin_lock(&dmm->list_lock); + spin_lock(&list_lock); list_add(&engine->idle_node, &dmm->idle_head); - spin_unlock(&dmm->list_lock); + spin_unlock(&list_lock); up(&omap_dmm->engine_sem); return ret; @@ -351,9 +354,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w, } /* add to allocation list */ - spin_lock(&omap_dmm->list_lock); + spin_lock(&list_lock); list_add(&block->alloc_node, &omap_dmm->alloc_head); - spin_unlock(&omap_dmm->list_lock); + spin_unlock(&list_lock); return block; } @@ -374,9 +377,9 @@ struct tiler_block *tiler_reserve_1d(size_t size) return ERR_PTR(-ENOMEM); } - spin_lock(&omap_dmm->list_lock); + spin_lock(&list_lock); list_add(&block->alloc_node, &omap_dmm->alloc_head); - spin_unlock(&omap_dmm->list_lock); + spin_unlock(&list_lock); return block; } @@ -389,9 +392,9 @@ int tiler_release(struct tiler_block *block) if (block->area.tcm) dev_err(omap_dmm->dev, "failed to release block\n"); - spin_lock(&omap_dmm->list_lock); + spin_lock(&list_lock); list_del(&block->alloc_node); - spin_unlock(&omap_dmm->list_lock); + spin_unlock(&list_lock); kfree(block); return ret; @@ -479,13 +482,13 @@ static int omap_dmm_remove(struct platform_device *dev) if (omap_dmm) { /* free all area regions */ - spin_lock(&omap_dmm->list_lock); + spin_lock(&list_lock); list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head, alloc_node) { list_del(&block->alloc_node); kfree(block); } - spin_unlock(&omap_dmm->list_lock); + spin_unlock(&list_lock); for (i = 0; i < omap_dmm->num_lut; i++) if (omap_dmm->tcm && omap_dmm->tcm[i]) @@ -503,7 +506,7 @@ static int omap_dmm_remove(struct platform_device *dev) vfree(omap_dmm->lut); - if (omap_dmm->irq != -1) + if (omap_dmm->irq > 0) free_irq(omap_dmm->irq, omap_dmm); iounmap(omap_dmm->base); @@ -527,6 +530,10 @@ static int omap_dmm_probe(struct platform_device *dev) goto fail; } + /* initialize lists */ + INIT_LIST_HEAD(&omap_dmm->alloc_head); + INIT_LIST_HEAD(&omap_dmm->idle_head); + /* lookup hwmod data - base address and irq */ mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!mem) { @@ -629,7 +636,6 @@ static int omap_dmm_probe(struct platform_device *dev) } sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines); - INIT_LIST_HEAD(&omap_dmm->idle_head); for (i = 0; i < omap_dmm->num_engines; i++) { omap_dmm->engines[i].id = i; omap_dmm->engines[i].dmm = omap_dmm; @@ -672,9 +678,6 @@ static int omap_dmm_probe(struct platform_device *dev) containers[TILFMT_32BIT] = omap_dmm->tcm[0]; containers[TILFMT_PAGE] = omap_dmm->tcm[0]; - INIT_LIST_HEAD(&omap_dmm->alloc_head); - spin_lock_init(&omap_dmm->list_lock); - area = (struct tcm_area) { .is2d = true, .tcm = NULL, @@ -697,7 +700,8 @@ static int omap_dmm_probe(struct platform_device *dev) return 0; fail: - omap_dmm_remove(dev); + if (omap_dmm_remove(dev)) + dev_err(&dev->dev, "cleanup failed\n"); return ret; } @@ -810,7 +814,7 @@ int tiler_map_show(struct seq_file *s, void *arg) map[i] = global_map + i * (w_adj + 1); map[i][w_adj] = 0; } - spin_lock_irqsave(&omap_dmm->list_lock, flags); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) { if (block->fmt != TILFMT_PAGE) { @@ -836,7 +840,7 @@ int tiler_map_show(struct seq_file *s, void *arg) } } - spin_unlock_irqrestore(&omap_dmm->list_lock, flags); + spin_unlock_irqrestore(&list_lock, flags); if (s) { seq_printf(s, "BEGIN DMM TILER MAP\n"); -- GitLab From 397d3e6029cb816d7a9a78531528a62d08c70d3f Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Fri, 25 May 2012 18:56:40 +0100 Subject: [PATCH 0430/5711] Staging: et131x: fix coding style issues This commit fixes coding style issues including braces position and line wrapping. Signed-off-by: Adnan Ali Reviewed-by: Jannis Pohlmann Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 5b11c5e3622e..cf02336ffbdc 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -85,8 +85,7 @@ MODULE_AUTHOR("Victor Soriano "); MODULE_AUTHOR("Mark Einon "); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver " - "for the ET1310 by Agere Systems"); +MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere Systems"); /* EEPROM defines */ #define MAX_NUM_REGISTER_POLLS 1000 @@ -2967,11 +2966,10 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) (ring_index == 0 && buff_index > rx_local->fbr[1]->num_entries - 1) || (ring_index == 1 && - buff_index > rx_local->fbr[0]->num_entries - 1)) + buff_index > rx_local->fbr[0]->num_entries - 1)) { #else - if (ring_index != 1 || buff_index > rx_local->fbr[0]->num_entries - 1) + if (ring_index != 1 || buff_index > rx_local->fbr[0]->num_entries - 1) { #endif - { /* Illegal buffer or ring index cannot be used by S/W*/ dev_err(&adapter->pdev->dev, "NICRxPkts PSR Entry %d indicates " @@ -4326,8 +4324,7 @@ static int et131x_mii_probe(struct net_device *netdev) phydev->advertising = phydev->supported; adapter->phydev = phydev; - dev_info(&adapter->pdev->dev, "attached PHY driver [%s] " - "(mii_bus:phy_addr=%s)\n", + dev_info(&adapter->pdev->dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", phydev->drv->name, dev_name(&phydev->dev)); return 0; -- GitLab From b5b86a4d99f48e5ac28c19ae2a00415e26a7ac1a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jun 2012 12:17:01 +0300 Subject: [PATCH 0431/5711] Staging: et131x: fix | vs & typos These two places seem like they should be using bitwise OR instead of bitwise AND. The first one is a noop which is equivalent to: imr |= (0x0100 & 0x0004 & 0x0001); The second is sets lcr2 to zero instead of just clearing the high bits. lcr2 &= (0x00F0 & 0x000F); Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index cf02336ffbdc..8f3fc5f85ec9 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1766,8 +1766,8 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) /* Set the link status interrupt only. Bad behavior when link status * and auto neg are set, we run into a nested interrupt problem */ - imr |= (ET_PHY_INT_MASK_AUTONEGSTAT & - ET_PHY_INT_MASK_LINKSTAT & + imr |= (ET_PHY_INT_MASK_AUTONEGSTAT | + ET_PHY_INT_MASK_LINKSTAT | ET_PHY_INT_MASK_ENABLE); et131x_mii_write(adapter, PHY_INTERRUPT_MASK, imr); @@ -1783,7 +1783,7 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) if ((adapter->eeprom_data[1] & 0x4) == 0) { et131x_mii_read(adapter, PHY_LED_2, &lcr2); - lcr2 &= (ET_LED2_LED_100TX & ET_LED2_LED_1000T); + lcr2 &= (ET_LED2_LED_100TX | ET_LED2_LED_1000T); lcr2 |= (LED_VAL_LINKON_ACTIVE << LED_LINK_SHIFT); if ((adapter->eeprom_data[1] & 0x8) == 0) -- GitLab From c234434835b1f4bad9bdbae6710044cba387c9e5 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 8 Jun 2012 15:39:25 +0900 Subject: [PATCH 0432/5711] staging: zsmalloc: zsmalloc: use unsigned long instead of void * We should use unsigned long as handle instead of void * to avoid any confusion. Without this, users may just treat zs_malloc return value as a pointer and try to deference it. This patch passed compile test(zram, zcache and ramster) and zram is tested on qemu. changelog * from v2 - remove hval pointed out by Nitin - based on next-20120607 * from v1 - change zcache's zv_create return value - baesd on next-20120604 Cc: Dan Magenheimer Acked-by: Seth Jennings Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Minchan Kim Acked-by: Nitin Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 12 +++++----- drivers/staging/zram/zram_drv.c | 16 +++++++------- drivers/staging/zram/zram_drv.h | 2 +- drivers/staging/zsmalloc/zsmalloc-main.c | 28 +++++++++++------------- drivers/staging/zsmalloc/zsmalloc.h | 8 +++---- 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 2734dacacbaf..d0141fbc649e 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -693,14 +693,14 @@ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; static atomic_t zv_curr_dist_counts[NCHUNKS]; static atomic_t zv_cumul_dist_counts[NCHUNKS]; -static struct zv_hdr *zv_create(struct zs_pool *pool, uint32_t pool_id, +static unsigned long zv_create(struct zs_pool *pool, uint32_t pool_id, struct tmem_oid *oid, uint32_t index, void *cdata, unsigned clen) { struct zv_hdr *zv; u32 size = clen + sizeof(struct zv_hdr); int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; - void *handle = NULL; + unsigned long handle = 0; BUG_ON(!irqs_disabled()); BUG_ON(chunks >= NCHUNKS); @@ -721,7 +721,7 @@ out: return handle; } -static void zv_free(struct zs_pool *pool, void *handle) +static void zv_free(struct zs_pool *pool, unsigned long handle) { unsigned long flags; struct zv_hdr *zv; @@ -743,7 +743,7 @@ static void zv_free(struct zs_pool *pool, void *handle) local_irq_restore(flags); } -static void zv_decompress(struct page *page, void *handle) +static void zv_decompress(struct page *page, unsigned long handle) { unsigned int clen = PAGE_SIZE; char *to_va; @@ -1247,7 +1247,7 @@ static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, int ret = 0; BUG_ON(is_ephemeral(pool)); - zv_decompress((struct page *)(data), pampd); + zv_decompress((struct page *)(data), (unsigned long)pampd); return ret; } @@ -1282,7 +1282,7 @@ static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, atomic_dec(&zcache_curr_eph_pampd_count); BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); } else { - zv_free(cli->zspool, pampd); + zv_free(cli->zspool, (unsigned long)pampd); atomic_dec(&zcache_curr_pers_pampd_count); BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); } diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 685d612a627b..abd69d13d0a1 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -135,7 +135,7 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) static void zram_free_page(struct zram *zram, size_t index) { - void *handle = zram->table[index].handle; + unsigned long handle = zram->table[index].handle; if (unlikely(!handle)) { /* @@ -150,7 +150,7 @@ static void zram_free_page(struct zram *zram, size_t index) } if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - __free_page(handle); + __free_page((struct page *)handle); zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED); zram_stat_dec(&zram->stats.pages_expand); goto out; @@ -166,7 +166,7 @@ out: zram->table[index].size); zram_stat_dec(&zram->stats.pages_stored); - zram->table[index].handle = NULL; + zram->table[index].handle = 0; zram->table[index].size = 0; } @@ -189,7 +189,7 @@ static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec, unsigned char *user_mem, *cmem; user_mem = kmap_atomic(page); - cmem = kmap_atomic(zram->table[index].handle); + cmem = kmap_atomic((struct page *)zram->table[index].handle); memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len); kunmap_atomic(cmem); @@ -317,7 +317,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int ret; u32 store_offset; size_t clen; - void *handle; + unsigned long handle; struct zobj_header *zheader; struct page *page, *page_store; unsigned char *user_mem, *cmem, *src, *uncmem = NULL; @@ -399,7 +399,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, store_offset = 0; zram_set_flag(zram, index, ZRAM_UNCOMPRESSED); zram_stat_inc(&zram->stats.pages_expand); - handle = page_store; + handle = (unsigned long)page_store; src = kmap_atomic(page); cmem = kmap_atomic(page_store); goto memstore; @@ -592,12 +592,12 @@ void __zram_reset_device(struct zram *zram) /* Free all pages that are still in this zram device */ for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) { - void *handle = zram->table[index].handle; + unsigned long handle = zram->table[index].handle; if (!handle) continue; if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) - __free_page(handle); + __free_page((struct page *)handle); else zs_free(zram->mem_pool, handle); } diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index fbe8ac98704c..7a7e25664826 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h @@ -81,7 +81,7 @@ enum zram_pageflags { /* Allocated for each disk page */ struct table { - void *handle; + unsigned long handle; u16 size; /* object size (excluding header) */ u8 count; /* object ref count (not yet used) */ u8 flags; diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 449673773286..8e830eeca729 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -247,13 +247,11 @@ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) } /* Decode pair from the given object handle */ -static void obj_handle_to_location(void *handle, struct page **page, +static void obj_handle_to_location(unsigned long handle, struct page **page, unsigned long *obj_idx) { - unsigned long hval = (unsigned long)handle; - - *page = pfn_to_page(hval >> OBJ_INDEX_BITS); - *obj_idx = hval & OBJ_INDEX_MASK; + *page = pfn_to_page(handle >> OBJ_INDEX_BITS); + *obj_idx = handle & OBJ_INDEX_MASK; } static unsigned long obj_idx_to_offset(struct page *page, @@ -568,12 +566,12 @@ EXPORT_SYMBOL_GPL(zs_destroy_pool); * @size: size of block to allocate * * On success, handle to the allocated object is returned, - * otherwise NULL. + * otherwise 0. * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail. */ -void *zs_malloc(struct zs_pool *pool, size_t size) +unsigned long zs_malloc(struct zs_pool *pool, size_t size) { - void *obj; + unsigned long obj; struct link_free *link; int class_idx; struct size_class *class; @@ -582,7 +580,7 @@ void *zs_malloc(struct zs_pool *pool, size_t size) unsigned long m_objidx, m_offset; if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE)) - return NULL; + return 0; class_idx = get_size_class_index(size); class = &pool->size_class[class_idx]; @@ -595,14 +593,14 @@ void *zs_malloc(struct zs_pool *pool, size_t size) spin_unlock(&class->lock); first_page = alloc_zspage(class, pool->flags); if (unlikely(!first_page)) - return NULL; + return 0; set_zspage_mapping(first_page, class->index, ZS_EMPTY); spin_lock(&class->lock); class->pages_allocated += class->pages_per_zspage; } - obj = first_page->freelist; + obj = (unsigned long)first_page->freelist; obj_handle_to_location(obj, &m_page, &m_objidx); m_offset = obj_idx_to_offset(m_page, m_objidx, class->size); @@ -621,7 +619,7 @@ void *zs_malloc(struct zs_pool *pool, size_t size) } EXPORT_SYMBOL_GPL(zs_malloc); -void zs_free(struct zs_pool *pool, void *obj) +void zs_free(struct zs_pool *pool, unsigned long obj) { struct link_free *link; struct page *first_page, *f_page; @@ -648,7 +646,7 @@ void zs_free(struct zs_pool *pool, void *obj) + f_offset); link->next = first_page->freelist; kunmap_atomic(link); - first_page->freelist = obj; + first_page->freelist = (void *)obj; first_page->inuse--; fullness = fix_fullness_group(pool, first_page); @@ -672,7 +670,7 @@ EXPORT_SYMBOL_GPL(zs_free); * this function. When done with the object, it must be unmapped using * zs_unmap_object */ -void *zs_map_object(struct zs_pool *pool, void *handle) +void *zs_map_object(struct zs_pool *pool, unsigned long handle) { struct page *page; unsigned long obj_idx, off; @@ -712,7 +710,7 @@ void *zs_map_object(struct zs_pool *pool, void *handle) } EXPORT_SYMBOL_GPL(zs_map_object); -void zs_unmap_object(struct zs_pool *pool, void *handle) +void zs_unmap_object(struct zs_pool *pool, unsigned long handle) { struct page *page; unsigned long obj_idx, off; diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/drivers/staging/zsmalloc/zsmalloc.h index 949384ee7491..485cbb1a5ac8 100644 --- a/drivers/staging/zsmalloc/zsmalloc.h +++ b/drivers/staging/zsmalloc/zsmalloc.h @@ -20,11 +20,11 @@ struct zs_pool; struct zs_pool *zs_create_pool(const char *name, gfp_t flags); void zs_destroy_pool(struct zs_pool *pool); -void *zs_malloc(struct zs_pool *pool, size_t size); -void zs_free(struct zs_pool *pool, void *obj); +unsigned long zs_malloc(struct zs_pool *pool, size_t size); +void zs_free(struct zs_pool *pool, unsigned long obj); -void *zs_map_object(struct zs_pool *pool, void *handle); -void zs_unmap_object(struct zs_pool *pool, void *handle); +void *zs_map_object(struct zs_pool *pool, unsigned long handle); +void zs_unmap_object(struct zs_pool *pool, unsigned long handle); u64 zs_get_total_size_bytes(struct zs_pool *pool); -- GitLab From 374a69191d12a0525b7ffe1197abc30c4795a230 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 8 Jun 2012 15:39:26 +0900 Subject: [PATCH 0433/5711] staging: zram: fix random data read fd1a30de makes a bug that it uses (struct page *) as zsmalloc's handle although it's a uncompressed page so that it can access random page, return random data or even crashed by get_first_page in zs_map_object. Cc: Seth Jennings Cc: Jerome Marchand Signed-off-by: Minchan Kim Acked-by: Nitin Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index abd69d13d0a1..0cdc303ad565 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -280,26 +280,27 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) size_t clen = PAGE_SIZE; struct zobj_header *zheader; unsigned char *cmem; + unsigned long handle = zram->table[index].handle; - if (zram_test_flag(zram, index, ZRAM_ZERO) || - !zram->table[index].handle) { + if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) { memset(mem, 0, PAGE_SIZE); return 0; } - cmem = zs_map_object(zram->mem_pool, zram->table[index].handle); - /* Page is stored uncompressed since it's incompressible */ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - memcpy(mem, cmem, PAGE_SIZE); - kunmap_atomic(cmem); + char *src = kmap_atomic((struct page *)handle); + memcpy(mem, src, PAGE_SIZE); + kunmap_atomic(src); return 0; } + cmem = zs_map_object(zram->mem_pool, handle); + ret = lzo1x_decompress_safe(cmem + sizeof(*zheader), zram->table[index].size, mem, &clen); - zs_unmap_object(zram->mem_pool, zram->table[index].handle); + zs_unmap_object(zram->mem_pool, handle); /* Should NEVER happen. Return bio error if it does. */ if (unlikely(ret != LZO_E_OK)) { -- GitLab From 130f315a174d127cbb90d4d1a4a7088dbcf930b5 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 8 Jun 2012 15:39:27 +0900 Subject: [PATCH 0434/5711] staging: zram: remove special handle of uncompressed page xvmalloc can't handle PAGE_SIZE page so that zram have to handle it specially but zsmalloc can do it so let's remove unnecessary special handling code. Quote from Nitin "I think page vs handle distinction was added since xvmalloc could not handle full page allocation. Now that zsmalloc allows full page allocation, we can just use it for both cases. This would also allow removing the ZRAM_UNCOMPRESSED flag. The only downside will be slightly slower code path for full page allocation but this event is anyways supposed to be rare, so should be fine." 1. This patch reduces code very much. drivers/staging/zram/zram_drv.c | 104 +++++-------------------------------- drivers/staging/zram/zram_drv.h | 17 +----- drivers/staging/zram/zram_sysfs.c | 6 +-- 3 files changed, 15 insertions(+), 112 deletions(-) 2. change pages_expand with bad_compress so it can count bad compression(above 75%) ratio. 3. remove zobj_header which is for back-reference for defragmentation because firstly, it's not used at the moment and zsmalloc can't handle bigger size than PAGE_SIZE so zram can't do it any more without redesign. Cc: Seth Jennings Signed-off-by: Minchan Kim Acked-by: Nitin Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 104 ++++-------------------------- drivers/staging/zram/zram_drv.h | 17 +---- drivers/staging/zram/zram_sysfs.c | 6 +- 3 files changed, 15 insertions(+), 112 deletions(-) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 0cdc303ad565..2036a901628b 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -136,6 +136,7 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) static void zram_free_page(struct zram *zram, size_t index) { unsigned long handle = zram->table[index].handle; + u16 size = zram->table[index].size; if (unlikely(!handle)) { /* @@ -149,19 +150,14 @@ static void zram_free_page(struct zram *zram, size_t index) return; } - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - __free_page((struct page *)handle); - zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED); - zram_stat_dec(&zram->stats.pages_expand); - goto out; - } + if (unlikely(size > max_zpage_size)) + zram_stat_dec(&zram->stats.bad_compress); zs_free(zram->mem_pool, handle); - if (zram->table[index].size <= PAGE_SIZE / 2) + if (size <= PAGE_SIZE / 2) zram_stat_dec(&zram->stats.good_compress); -out: zram_stat64_sub(zram, &zram->stats.compr_size, zram->table[index].size); zram_stat_dec(&zram->stats.pages_stored); @@ -182,22 +178,6 @@ static void handle_zero_page(struct bio_vec *bvec) flush_dcache_page(page); } -static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec, - u32 index, int offset) -{ - struct page *page = bvec->bv_page; - unsigned char *user_mem, *cmem; - - user_mem = kmap_atomic(page); - cmem = kmap_atomic((struct page *)zram->table[index].handle); - - memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len); - kunmap_atomic(cmem); - kunmap_atomic(user_mem); - - flush_dcache_page(page); -} - static inline int is_partial_io(struct bio_vec *bvec) { return bvec->bv_len != PAGE_SIZE; @@ -209,7 +189,6 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, int ret; size_t clen; struct page *page; - struct zobj_header *zheader; unsigned char *user_mem, *cmem, *uncmem = NULL; page = bvec->bv_page; @@ -227,12 +206,6 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, return 0; } - /* Page is stored uncompressed since it's incompressible */ - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - handle_uncompressed_page(zram, bvec, index, offset); - return 0; - } - if (is_partial_io(bvec)) { /* Use a temporary buffer to decompress the page */ uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); @@ -249,8 +222,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, cmem = zs_map_object(zram->mem_pool, zram->table[index].handle); - ret = lzo1x_decompress_safe(cmem + sizeof(*zheader), - zram->table[index].size, + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, uncmem, &clen); if (is_partial_io(bvec)) { @@ -278,7 +250,6 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) { int ret; size_t clen = PAGE_SIZE; - struct zobj_header *zheader; unsigned char *cmem; unsigned long handle = zram->table[index].handle; @@ -287,18 +258,8 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) return 0; } - /* Page is stored uncompressed since it's incompressible */ - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - char *src = kmap_atomic((struct page *)handle); - memcpy(mem, src, PAGE_SIZE); - kunmap_atomic(src); - return 0; - } - cmem = zs_map_object(zram->mem_pool, handle); - - ret = lzo1x_decompress_safe(cmem + sizeof(*zheader), - zram->table[index].size, + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, mem, &clen); zs_unmap_object(zram->mem_pool, handle); @@ -316,11 +277,9 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int offset) { int ret; - u32 store_offset; size_t clen; unsigned long handle; - struct zobj_header *zheader; - struct page *page, *page_store; + struct page *page; unsigned char *user_mem, *cmem, *src, *uncmem = NULL; page = bvec->bv_page; @@ -382,31 +341,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - /* - * Page is incompressible. Store it as-is (uncompressed) - * since we do not want to return too many disk write - * errors which has side effect of hanging the system. - */ - if (unlikely(clen > max_zpage_size)) { - clen = PAGE_SIZE; - page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); - if (unlikely(!page_store)) { - pr_info("Error allocating memory for " - "incompressible page: %u\n", index); - ret = -ENOMEM; - goto out; - } + if (unlikely(clen > max_zpage_size)) + zram_stat_inc(&zram->stats.bad_compress); - store_offset = 0; - zram_set_flag(zram, index, ZRAM_UNCOMPRESSED); - zram_stat_inc(&zram->stats.pages_expand); - handle = (unsigned long)page_store; - src = kmap_atomic(page); - cmem = kmap_atomic(page_store); - goto memstore; - } - - handle = zs_malloc(zram->mem_pool, clen + sizeof(*zheader)); + handle = zs_malloc(zram->mem_pool, clen); if (!handle) { pr_info("Error allocating memory for compressed " "page: %u, size=%zu\n", index, clen); @@ -415,24 +353,9 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, } cmem = zs_map_object(zram->mem_pool, handle); -memstore: -#if 0 - /* Back-reference needed for memory defragmentation */ - if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) { - zheader = (struct zobj_header *)cmem; - zheader->table_idx = index; - cmem += sizeof(*zheader); - } -#endif - memcpy(cmem, src, clen); - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - kunmap_atomic(cmem); - kunmap_atomic(src); - } else { - zs_unmap_object(zram->mem_pool, handle); - } + zs_unmap_object(zram->mem_pool, handle); zram->table[index].handle = handle; zram->table[index].size = clen; @@ -597,10 +520,7 @@ void __zram_reset_device(struct zram *zram) if (!handle) continue; - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) - __free_page((struct page *)handle); - else - zs_free(zram->mem_pool, handle); + zs_free(zram->mem_pool, handle); } vfree(zram->table); diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index 7a7e25664826..9711d1e281f1 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h @@ -26,18 +26,6 @@ */ static const unsigned max_num_devices = 32; -/* - * Stored at beginning of each compressed object. - * - * It stores back-reference to table entry which points to this - * object. This is required to support memory defragmentation. - */ -struct zobj_header { -#if 0 - u32 table_idx; -#endif -}; - /*-- Configurable parameters */ /* Default zram disk size: 25% of total RAM */ @@ -68,9 +56,6 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3; /* Flags for zram pages (table[page_no].flags) */ enum zram_pageflags { - /* Page is stored uncompressed */ - ZRAM_UNCOMPRESSED, - /* Page consists entirely of zeros */ ZRAM_ZERO, @@ -98,7 +83,7 @@ struct zram_stats { u32 pages_zero; /* no. of zero filled pages */ u32 pages_stored; /* no. of pages currently stored */ u32 good_compress; /* % of pages with compression ratio<=50% */ - u32 pages_expand; /* % of incompressible pages */ + u32 bad_compress; /* % of pages with compression ratio>=75% */ }; struct zram { diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c index a7f377175525..edb0ed4125d5 100644 --- a/drivers/staging/zram/zram_sysfs.c +++ b/drivers/staging/zram/zram_sysfs.c @@ -186,10 +186,8 @@ static ssize_t mem_used_total_show(struct device *dev, u64 val = 0; struct zram *zram = dev_to_zram(dev); - if (zram->init_done) { - val = zs_get_total_size_bytes(zram->mem_pool) + - ((u64)(zram->stats.pages_expand) << PAGE_SHIFT); - } + if (zram->init_done) + val = zs_get_total_size_bytes(zram->mem_pool); return sprintf(buf, "%llu\n", val); } -- GitLab From 2db51dae56240b52fe08ddbb1a2eb47fe7cfd044 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Sat, 9 Jun 2012 17:41:14 -0700 Subject: [PATCH 0435/5711] staging: zsmalloc documentation Documentation of various struct page fields used by zsmalloc. Changes for v2: - Regroup descriptions as suggested by Konrad Signed-off-by: Nitin Gupta Acked-by: Konrad Rzeszutek Wilk Reviewed-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 8e830eeca729..fb54a9b94c33 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -10,6 +10,54 @@ * Released under the terms of GNU General Public License Version 2.0 */ + +/* + * This allocator is designed for use with zcache and zram. Thus, the + * allocator is supposed to work well under low memory conditions. In + * particular, it never attempts higher order page allocation which is + * very likely to fail under memory pressure. On the other hand, if we + * just use single (0-order) pages, it would suffer from very high + * fragmentation -- any object of size PAGE_SIZE/2 or larger would occupy + * an entire page. This was one of the major issues with its predecessor + * (xvmalloc). + * + * To overcome these issues, zsmalloc allocates a bunch of 0-order pages + * and links them together using various 'struct page' fields. These linked + * pages act as a single higher-order page i.e. an object can span 0-order + * page boundaries. The code refers to these linked pages as a single entity + * called zspage. + * + * Following is how we use various fields and flags of underlying + * struct page(s) to form a zspage. + * + * Usage of struct page fields: + * page->first_page: points to the first component (0-order) page + * page->index (union with page->freelist): offset of the first object + * starting in this page. For the first page, this is + * always 0, so we use this field (aka freelist) to point + * to the first free object in zspage. + * page->lru: links together all component pages (except the first page) + * of a zspage + * + * For _first_ page only: + * + * page->private (union with page->first_page): refers to the + * component page after the first page + * page->freelist: points to the first free object in zspage. + * Free objects are linked together using in-place + * metadata. + * page->objects: maximum number of objects we can store in this + * zspage (class->zspage_order * PAGE_SIZE / class->size) + * page->lru: links together first pages of various zspages. + * Basically forming list of zspages in a fullness group. + * page->mapping: class index and fullness group of the zspage + * + * Usage of struct page flags: + * PG_private: identifies the first component page + * PG_private2: identifies the last component page + * + */ + #ifdef CONFIG_ZSMALLOC_DEBUG #define DEBUG #endif -- GitLab From 94b8435ff4d46dde75173da45564b0d65889dc64 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Thu, 7 Jun 2012 16:03:47 -0700 Subject: [PATCH 0436/5711] staging: zram: conventions pr_warning -> pr_warn() Porting zram to use the pr_warn() function instead of the deprecated pr_warning(). Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 2036a901628b..706cb625aae9 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -645,7 +645,7 @@ static int create_device(struct zram *zram, int device_id) zram->disk = alloc_disk(1); if (!zram->disk) { blk_cleanup_queue(zram->queue); - pr_warning("Error allocating disk structure for device %d\n", + pr_warn("Error allocating disk structure for device %d\n", device_id); ret = -ENOMEM; goto out; @@ -676,7 +676,7 @@ static int create_device(struct zram *zram, int device_id) ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj, &zram_disk_attr_group); if (ret < 0) { - pr_warning("Error creating sysfs group"); + pr_warn("Error creating sysfs group"); goto out; } @@ -710,7 +710,7 @@ static int __init zram_init(void) int ret, dev_id; if (num_devices > max_num_devices) { - pr_warning("Invalid value for num_devices: %u\n", + pr_warn("Invalid value for num_devices: %u\n", num_devices); ret = -EINVAL; goto out; @@ -718,7 +718,7 @@ static int __init zram_init(void) zram_major = register_blkdev(0, "zram"); if (zram_major <= 0) { - pr_warning("Unable to get major number\n"); + pr_warn("Unable to get major number\n"); ret = -EBUSY; goto out; } -- GitLab From 80677c2538283678c7b2ef7ebbd653a3fa54d086 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Thu, 7 Jun 2012 16:03:48 -0700 Subject: [PATCH 0437/5711] staging: zram: conventions, __aligned() attribute Using the __aligned() attribute in favor of __attribute__((aligned(size))) Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index 9711d1e281f1..572c0b1551d4 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h @@ -70,7 +70,7 @@ struct table { u16 size; /* object size (excluding header) */ u8 count; /* object ref count (not yet used) */ u8 flags; -} __attribute__((aligned(4))); +} __aligned(4); struct zram_stats { u64 compr_size; /* compressed size of pages stored */ -- GitLab From e034410a3dace8ee56906095e737281899126f44 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 1 Jun 2012 10:14:02 +0200 Subject: [PATCH 0438/5711] staging: usbip: userspace: include headers in release tarballs The header files should be included in generated tarballs for archives. Signed-off-by: Natanael Copa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/userspace/src/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/usbip/userspace/src/Makefile.am b/drivers/staging/usbip/userspace/src/Makefile.am index 3f09f6ad39f7..c365a3fada90 100644 --- a/drivers/staging/usbip/userspace/src/Makefile.am +++ b/drivers/staging/usbip/userspace/src/Makefile.am @@ -4,8 +4,9 @@ LDADD = $(top_builddir)/libsrc/libusbip.la @PACKAGE_LIBS@ sbin_PROGRAMS := usbip usbipd -usbip_SOURCES := usbip.c utils.c usbip_network.c \ +usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \ usbip_attach.c usbip_detach.c usbip_list.c \ usbip_bind.c usbip_unbind.c -usbipd_SOURCES := usbipd.c usbip_network.c + +usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c -- GitLab From 7a623c039075e4ea21648d88133fafa6dcfd113d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 16 Apr 2012 16:41:11 -0300 Subject: [PATCH 0439/5711] edac: rewrite the sysfs code to use struct device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EDAC subsystem uses the old struct sysdev approach, creating all nodes using the raw sysfs API. This is bad, as the API is deprecated. As we'll be changing the EDAC API, let's first port the existing code to struct device. There's one drawback on this patch: driver-specific sysfs nodes, used by mpc85xx_edac, amd64_edac and i7core_edac won't be created anymore. While it would be possible to also port the device-specific code, that would mix kobj with struct device, with is not recommended. Also, it is easier and nicer to move the code to the drivers, instead, as the core can get rid of some complex logic that just emulates what the device_add() and device_create_file() already does. The next patches will convert the driver-specific code to use the device-specific calls. Then, the remaining bits of the old sysfs API will be removed. NOTE: a per-MC bus is required, otherwise devices with more than one memory controller will hit a bug like the one below: [ 819.094946] EDAC DEBUG: find_mci_by_dev: find_mci_by_dev() [ 819.094948] EDAC DEBUG: edac_create_sysfs_mci_device: edac_create_sysfs_mci_device() idx=1 [ 819.094952] EDAC DEBUG: edac_create_sysfs_mci_device: edac_create_sysfs_mci_device(): creating device mc1 [ 819.094967] EDAC DEBUG: edac_create_sysfs_mci_device: edac_create_sysfs_mci_device creating dimm0, located at channel 0 slot 0 [ 819.094984] ------------[ cut here ]------------ [ 819.100142] WARNING: at fs/sysfs/dir.c:481 sysfs_add_one+0xc1/0xf0() [ 819.107282] Hardware name: S2600CP [ 819.111078] sysfs: cannot create duplicate filename '/bus/edac/devices/dimm0' [ 819.119062] Modules linked in: sb_edac(+) edac_core ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle iptable_filter ip_tables bridge stp llc sunrpc binfmt_misc dm_mirror dm_region_hash dm_log vhost_net macvtap macvlan tun kvm microcode pcspkr iTCO_wdt iTCO_vendor_support igb i2c_i801 i2c_core sg ioatdma dca sr_mod cdrom sd_mod crc_t10dif ahci libahci isci libsas libata scsi_transport_sas scsi_mod wmi dm_mod [last unloaded: scsi_wait_scan] [ 819.175748] Pid: 10902, comm: modprobe Not tainted 3.3.0-0.11.el7.v12.2.x86_64 #1 [ 819.184113] Call Trace: [ 819.186868] [] warn_slowpath_common+0x7f/0xc0 [ 819.193573] [] warn_slowpath_fmt+0x46/0x50 [ 819.200000] [] sysfs_add_one+0xc1/0xf0 [ 819.206025] [] sysfs_do_create_link+0x135/0x220 [ 819.212944] [] ? sysfs_create_group+0x13/0x20 [ 819.219656] [] sysfs_create_link+0x13/0x20 [ 819.226109] [] bus_add_device+0xe6/0x1b0 [ 819.232350] [] device_add+0x2db/0x460 [ 819.238300] [] edac_create_dimm_object+0x84/0xf0 [edac_core] [ 819.246460] [] edac_create_sysfs_mci_device+0xe8/0x290 [edac_core] [ 819.255215] [] edac_mc_add_mc+0x5a/0x2c0 [edac_core] [ 819.262611] [] sbridge_register_mci+0x1bc/0x279 [sb_edac] [ 819.270493] [] sbridge_probe+0xef/0x175 [sb_edac] [ 819.277630] [] ? pm_runtime_enable+0x58/0x90 [ 819.284268] [] local_pci_probe+0x5c/0xd0 [ 819.290508] [] __pci_device_probe+0xf1/0x100 [ 819.297117] [] pci_device_probe+0x3a/0x60 [ 819.303457] [] really_probe+0x73/0x270 [ 819.309496] [] driver_probe_device+0x4e/0xb0 [ 819.316104] [] __driver_attach+0xab/0xb0 [ 819.322337] [] ? driver_probe_device+0xb0/0xb0 [ 819.329151] [] bus_for_each_dev+0x56/0x90 [ 819.335489] [] driver_attach+0x1e/0x20 [ 819.341534] [] bus_add_driver+0x1b0/0x2a0 [ 819.347884] [] ? 0xffffffffa0346fff [ 819.353641] [] driver_register+0x76/0x140 [ 819.359980] [] ? printk+0x51/0x53 [ 819.365524] [] ? 0xffffffffa0346fff [ 819.371291] [] __pci_register_driver+0x56/0xd0 [ 819.378096] [] sbridge_init+0x54/0x1000 [sb_edac] [ 819.385231] [] do_one_initcall+0x3f/0x170 [ 819.391577] [] sys_init_module+0xbe/0x230 [ 819.397926] [] system_call_fastpath+0x16/0x1b [ 819.404633] ---[ end trace 1654fdd39556689f ]--- This happens because the bus is not being properly initialized. Instead of putting the memory sub-devices inside the memory controller, it is putting everything under the same directory: $ tree /sys/bus/edac/ /sys/bus/edac/ ├── devices │ ├── all_channel_counts -> ../../../devices/system/edac/mc/mc0/all_channel_counts │ ├── csrow0 -> ../../../devices/system/edac/mc/mc0/csrow0 │ ├── csrow1 -> ../../../devices/system/edac/mc/mc0/csrow1 │ ├── csrow2 -> ../../../devices/system/edac/mc/mc0/csrow2 │ ├── dimm0 -> ../../../devices/system/edac/mc/mc0/dimm0 │ ├── dimm1 -> ../../../devices/system/edac/mc/mc0/dimm1 │ ├── dimm3 -> ../../../devices/system/edac/mc/mc0/dimm3 │ ├── dimm6 -> ../../../devices/system/edac/mc/mc0/dimm6 │ ├── inject_addrmatch -> ../../../devices/system/edac/mc/mc0/inject_addrmatch │ ├── mc -> ../../../devices/system/edac/mc │ └── mc0 -> ../../../devices/system/edac/mc/mc0 ├── drivers ├── drivers_autoprobe ├── drivers_probe └── uevent On a multi-memory controller system, the names "csrow%d" and "dimm%d" should be under "mc%d", and not at the main hierarchy level. So, we need to create a per-MC bus, in order to have its own namespace. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Cc: Greg K H Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc.c | 13 +- drivers/edac/edac_mc_sysfs.c | 1074 +++++++++++++--------------------- drivers/edac/edac_module.c | 13 +- drivers/edac/edac_module.h | 9 +- include/linux/edac.h | 47 +- 5 files changed, 450 insertions(+), 706 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 811f09a38f3a..61ae34643b49 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -218,7 +218,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, unsigned size, tot_dimms = 1, count = 1; unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0; void *pvt, *p, *ptr = NULL; - int i, j, err, row, chn, n, len; + int i, j, row, chn, n, len; bool per_rank = false; BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0); @@ -374,15 +374,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->op_state = OP_ALLOC; INIT_LIST_HEAD(&mci->grp_kobj_list); - /* - * Initialize the 'root' kobj for the edac_mc controller - */ - err = edac_mc_register_sysfs_main_kobj(mci); - if (err) { - kfree(mci); - return NULL; - } - /* at this point, the root kobj is valid, and in order to * 'free' the object, then the function: * edac_mc_unregister_sysfs_main_kobj() must be called @@ -403,7 +394,7 @@ void edac_mc_free(struct mem_ctl_info *mci) { debugf1("%s()\n", __func__); - edac_mc_unregister_sysfs_main_kobj(mci); + edac_unregister_sysfs(mci); /* free the mci instance memory here */ kfree(mci); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 595371941ef9..7002c9cab999 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -7,17 +7,20 @@ * * Written Doug Thompson www.softwarebitmaker.com * + * (c) 2012 - Mauro Carvalho Chehab + * The entire API were re-written, and ported to use struct device + * */ #include #include #include #include +#include #include "edac_core.h" #include "edac_module.h" - /* MC EDAC Controls, setable by module parameter, and sysfs */ static int edac_mc_log_ue = 1; static int edac_mc_log_ce = 1; @@ -78,6 +81,8 @@ module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int, &edac_mc_poll_msec, 0644); MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); +static struct device mci_pdev; + /* * various constants for Memory Controllers */ @@ -125,308 +130,336 @@ static const char *edac_caps[] = { [EDAC_S16ECD16ED] = "S16ECD16ED" }; -/* EDAC sysfs CSROW data structures and methods +/* + * EDAC sysfs CSROW data structures and methods + */ + +#define to_csrow(k) container_of(k, struct csrow_info, dev) + +/* + * We need it to avoid namespace conflicts between the legacy API + * and the per-dimm/per-rank one */ +#define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \ + struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store) + +struct dev_ch_attribute { + struct device_attribute attr; + int channel; +}; + +#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \ + struct dev_ch_attribute dev_attr_legacy_##_name = \ + { __ATTR(_name, _mode, _show, _store), (_var) } + +#define to_channel(k) (container_of(k, struct dev_ch_attribute, attr)->channel) /* Set of more default csrow attribute show/store functions */ -static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_ue_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%u\n", csrow->ue_count); } -static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_ce_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%u\n", csrow->ce_count); } -static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_size_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); int i; u32 nr_pages = 0; for (i = 0; i < csrow->nr_channels; i++) nr_pages += csrow->channels[i].dimm->nr_pages; - return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); } -static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_mem_type_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]); } -static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_dev_type_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]); } -static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_edac_mode_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]); } /* show/store functions for DIMM Label attributes */ -static ssize_t channel_dimm_label_show(struct csrow_info *csrow, - char *data, int channel) +static ssize_t channel_dimm_label_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = &csrow->channels[chan]; + /* if field has not been initialized, there is nothing to send */ - if (!csrow->channels[channel].dimm->label[0]) + if (!rank->dimm->label[0]) return 0; return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", - csrow->channels[channel].dimm->label); + rank->dimm->label); } -static ssize_t channel_dimm_label_store(struct csrow_info *csrow, - const char *data, - size_t count, int channel) +static ssize_t channel_dimm_label_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = &csrow->channels[chan]; + ssize_t max_size = 0; max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1); - strncpy(csrow->channels[channel].dimm->label, data, max_size); - csrow->channels[channel].dimm->label[max_size] = '\0'; + strncpy(rank->dimm->label, data, max_size); + rank->dimm->label[max_size] = '\0'; return max_size; } /* show function for dynamic chX_ce_count attribute */ -static ssize_t channel_ce_count_show(struct csrow_info *csrow, - char *data, int channel) +static ssize_t channel_ce_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { - return sprintf(data, "%u\n", csrow->channels[channel].ce_count); + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = &csrow->channels[chan]; + + return sprintf(data, "%u\n", rank->ce_count); } -/* csrow specific attribute structure */ -struct csrowdev_attribute { - struct attribute attr; - ssize_t(*show) (struct csrow_info *, char *, int); - ssize_t(*store) (struct csrow_info *, const char *, size_t, int); - int private; -}; +/* cwrow/attribute files */ +DEVICE_ATTR_LEGACY(size_mb, S_IRUGO, csrow_size_show, NULL); +DEVICE_ATTR_LEGACY(dev_type, S_IRUGO, csrow_dev_type_show, NULL); +DEVICE_ATTR_LEGACY(mem_type, S_IRUGO, csrow_mem_type_show, NULL); +DEVICE_ATTR_LEGACY(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL); +DEVICE_ATTR_LEGACY(ue_count, S_IRUGO, csrow_ue_count_show, NULL); +DEVICE_ATTR_LEGACY(ce_count, S_IRUGO, csrow_ce_count_show, NULL); -#define to_csrow(k) container_of(k, struct csrow_info, kobj) -#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr) +/* default attributes of the CSROW object */ +static struct attribute *csrow_attrs[] = { + &dev_attr_legacy_dev_type.attr, + &dev_attr_legacy_mem_type.attr, + &dev_attr_legacy_edac_mode.attr, + &dev_attr_legacy_size_mb.attr, + &dev_attr_legacy_ue_count.attr, + &dev_attr_legacy_ce_count.attr, + NULL, +}; -/* Set of show/store higher level functions for default csrow attributes */ -static ssize_t csrowdev_show(struct kobject *kobj, - struct attribute *attr, char *buffer) -{ - struct csrow_info *csrow = to_csrow(kobj); - struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); +static struct attribute_group csrow_attr_grp = { + .attrs = csrow_attrs, +}; - if (csrowdev_attr->show) - return csrowdev_attr->show(csrow, - buffer, csrowdev_attr->private); - return -EIO; -} +static const struct attribute_group *csrow_attr_groups[] = { + &csrow_attr_grp, + NULL +}; -static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static void csrow_attr_release(struct device *device) { - struct csrow_info *csrow = to_csrow(kobj); - struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); - - if (csrowdev_attr->store) - return csrowdev_attr->store(csrow, - buffer, - count, csrowdev_attr->private); - return -EIO; + debugf1("Releasing csrow device %s\n", dev_name(device)); } -static const struct sysfs_ops csrowfs_ops = { - .show = csrowdev_show, - .store = csrowdev_store +static struct device_type csrow_attr_type = { + .groups = csrow_attr_groups, + .release = csrow_attr_release, }; -#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private) \ -static struct csrowdev_attribute attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ - .private = _private, \ -}; - -/* default cwrow/attribute files */ -CSROWDEV_ATTR(size_mb, S_IRUGO, csrow_size_show, NULL, 0); -CSROWDEV_ATTR(dev_type, S_IRUGO, csrow_dev_type_show, NULL, 0); -CSROWDEV_ATTR(mem_type, S_IRUGO, csrow_mem_type_show, NULL, 0); -CSROWDEV_ATTR(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL, 0); -CSROWDEV_ATTR(ue_count, S_IRUGO, csrow_ue_count_show, NULL, 0); -CSROWDEV_ATTR(ce_count, S_IRUGO, csrow_ce_count_show, NULL, 0); +/* + * possible dynamic channel DIMM Label attribute files + * + */ -/* default attributes of the CSROW object */ -static struct csrowdev_attribute *default_csrow_attr[] = { - &attr_dev_type, - &attr_mem_type, - &attr_edac_mode, - &attr_size_mb, - &attr_ue_count, - &attr_ce_count, - NULL, -}; +#define EDAC_NR_CHANNELS 6 -/* possible dynamic channel DIMM Label attribute files */ -CSROWDEV_ATTR(ch0_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 0); -CSROWDEV_ATTR(ch1_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 1); -CSROWDEV_ATTR(ch2_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch2_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 2); -CSROWDEV_ATTR(ch3_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch3_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 3); -CSROWDEV_ATTR(ch4_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch4_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 4); -CSROWDEV_ATTR(ch5_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 5); /* Total possible dynamic DIMM Label attribute file table */ -static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = { - &attr_ch0_dimm_label, - &attr_ch1_dimm_label, - &attr_ch2_dimm_label, - &attr_ch3_dimm_label, - &attr_ch4_dimm_label, - &attr_ch5_dimm_label +static struct device_attribute *dynamic_csrow_dimm_attr[] = { + &dev_attr_legacy_ch0_dimm_label.attr, + &dev_attr_legacy_ch1_dimm_label.attr, + &dev_attr_legacy_ch2_dimm_label.attr, + &dev_attr_legacy_ch3_dimm_label.attr, + &dev_attr_legacy_ch4_dimm_label.attr, + &dev_attr_legacy_ch5_dimm_label.attr }; /* possible dynamic channel ce_count attribute files */ -CSROWDEV_ATTR(ch0_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 0); -CSROWDEV_ATTR(ch1_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 1); -CSROWDEV_ATTR(ch2_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 2); -CSROWDEV_ATTR(ch3_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 3); -CSROWDEV_ATTR(ch4_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 4); -CSROWDEV_ATTR(ch5_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 5); +DEVICE_CHANNEL(ch0_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 0); +DEVICE_CHANNEL(ch1_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 1); +DEVICE_CHANNEL(ch2_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 2); +DEVICE_CHANNEL(ch3_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 3); +DEVICE_CHANNEL(ch4_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 4); +DEVICE_CHANNEL(ch5_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 5); /* Total possible dynamic ce_count attribute file table */ -static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = { - &attr_ch0_ce_count, - &attr_ch1_ce_count, - &attr_ch2_ce_count, - &attr_ch3_ce_count, - &attr_ch4_ce_count, - &attr_ch5_ce_count +static struct device_attribute *dynamic_csrow_ce_count_attr[] = { + &dev_attr_legacy_ch0_ce_count.attr, + &dev_attr_legacy_ch1_ce_count.attr, + &dev_attr_legacy_ch2_ce_count.attr, + &dev_attr_legacy_ch3_ce_count.attr, + &dev_attr_legacy_ch4_ce_count.attr, + &dev_attr_legacy_ch5_ce_count.attr }; -#define EDAC_NR_CHANNELS 6 - -/* Create dynamic CHANNEL files, indexed by 'chan', under specifed CSROW */ -static int edac_create_channel_files(struct kobject *kobj, int chan) +/* Create a CSROW object under specifed edac_mc_device */ +static int edac_create_csrow_object(struct mem_ctl_info *mci, + struct csrow_info *csrow, int index) { - int err = -ENODEV; + int err, chan; - if (chan >= EDAC_NR_CHANNELS) - return err; + if (csrow->nr_channels >= EDAC_NR_CHANNELS) + return -ENODEV; - /* create the DIMM label attribute file */ - err = sysfs_create_file(kobj, - (struct attribute *) - dynamic_csrow_dimm_attr[chan]); - - if (!err) { - /* create the CE Count attribute file */ - err = sysfs_create_file(kobj, - (struct attribute *) - dynamic_csrow_ce_count_attr[chan]); - } else { - debugf1("%s() dimm labels and ce_count files created", - __func__); - } + csrow->dev.type = &csrow_attr_type; + csrow->dev.bus = &mci->bus; + device_initialize(&csrow->dev); + csrow->dev.parent = &mci->dev; + dev_set_name(&csrow->dev, "csrow%d", index); + dev_set_drvdata(&csrow->dev, csrow); - return err; -} + debugf0("%s(): creating (virtual) csrow node %s\n", __func__, + dev_name(&csrow->dev)); -/* No memory to release for this kobj */ -static void edac_csrow_instance_release(struct kobject *kobj) -{ - struct mem_ctl_info *mci; - struct csrow_info *cs; + err = device_add(&csrow->dev); + if (err < 0) + return err; - debugf1("%s()\n", __func__); + for (chan = 0; chan < csrow->nr_channels; chan++) { + err = device_create_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + if (err < 0) + goto error; + err = device_create_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + if (err < 0) { + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + goto error; + } + } - cs = container_of(kobj, struct csrow_info, kobj); - mci = cs->mci; + return 0; - kobject_put(&mci->edac_mci_kobj); -} +error: + for (--chan; chan >= 0; chan--) { + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + } + put_device(&csrow->dev); -/* the kobj_type instance for a CSROW */ -static struct kobj_type ktype_csrow = { - .release = edac_csrow_instance_release, - .sysfs_ops = &csrowfs_ops, - .default_attrs = (struct attribute **)default_csrow_attr, -}; + return err; +} /* Create a CSROW object under specifed edac_mc_device */ -static int edac_create_csrow_object(struct mem_ctl_info *mci, - struct csrow_info *csrow, int index) +static int edac_create_csrow_objects(struct mem_ctl_info *mci) { - struct kobject *kobj_mci = &mci->edac_mci_kobj; - struct kobject *kobj; - int chan; - int err; + int err, i, chan; + struct csrow_info *csrow; - /* generate ..../edac/mc/mc/csrow */ - memset(&csrow->kobj, 0, sizeof(csrow->kobj)); - csrow->mci = mci; /* include container up link */ + for (i = 0; i < mci->nr_csrows; i++) { + err = edac_create_csrow_object(mci, &mci->csrows[i], i); + if (err < 0) + goto error; + } + return 0; - /* bump the mci instance's kobject's ref count */ - kobj = kobject_get(&mci->edac_mci_kobj); - if (!kobj) { - err = -ENODEV; - goto err_out; +error: + for (--i; i >= 0; i--) { + csrow = &mci->csrows[i]; + for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + } + put_device(&mci->csrows[i].dev); } - /* Instanstiate the csrow object */ - err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci, - "csrow%d", index); - if (err) - goto err_release_top_kobj; + return err; +} - /* At this point, to release a csrow kobj, one must - * call the kobject_put and allow that tear down - * to work the releasing - */ +static void edac_delete_csrow_objects(struct mem_ctl_info *mci) +{ + int i, chan; + struct csrow_info *csrow; - /* Create the dyanmic attribute files on this csrow, - * namely, the DIMM labels and the channel ce_count - */ - for (chan = 0; chan < csrow->nr_channels; chan++) { - err = edac_create_channel_files(&csrow->kobj, chan); - if (err) { - /* special case the unregister here */ - kobject_put(&csrow->kobj); - goto err_out; + for (i = mci->nr_csrows - 1; i >= 0; i--) { + csrow = &mci->csrows[i]; + for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + debugf1("Removing csrow %d channel %d sysfs nodes\n", + i, chan); + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); } + put_device(&mci->csrows[i].dev); + device_del(&mci->csrows[i].dev); } - kobject_uevent(&csrow->kobj, KOBJ_ADD); - return 0; - - /* error unwind stack */ -err_release_top_kobj: - kobject_put(&mci->edac_mci_kobj); - -err_out: - return err; } -/* default sysfs methods and data structures for the main MCI kobject */ +/* + * Memory controller device + */ + +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) -static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, +static ssize_t mci_reset_counters_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { - int row, chan; - - mci->ue_noinfo_count = 0; - mci->ce_noinfo_count = 0; + struct mem_ctl_info *mci = to_mci(dev); + int cnt, row, chan, i; mci->ue_mc = 0; mci->ce_mc = 0; + mci->ue_noinfo_count = 0; + mci->ce_noinfo_count = 0; for (row = 0; row < mci->nr_csrows; row++) { struct csrow_info *ri = &mci->csrows[row]; @@ -438,6 +471,13 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, ri->channels[chan].ce_count = 0; } + cnt = 1; + for (i = 0; i < mci->n_layers; i++) { + cnt *= mci->layers[i].size; + memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32)); + memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32)); + } + mci->start_time = jiffies; return count; } @@ -451,9 +491,11 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, * Negative value still means that an error has occurred while setting * the scrub rate. */ -static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, +static ssize_t mci_sdram_scrub_rate_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); unsigned long bandwidth = 0; int new_bw = 0; @@ -476,8 +518,11 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, /* * ->get_sdram_scrub_rate() return value semantics same as above. */ -static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_sdram_scrub_rate_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); int bandwidth = 0; if (!mci->get_sdram_scrub_rate) @@ -493,38 +538,65 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) } /* default attribute files for the MCI object */ -static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ue_count_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ue_mc); } -static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ce_count_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ce_mc); } -static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ce_noinfo_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ce_noinfo_count); } -static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ue_noinfo_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ue_noinfo_count); } -static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_seconds_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ); } -static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ctl_name_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%s\n", mci->ctl_name); } -static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_size_mb_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); int total_pages = 0, csrow_idx, j; for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { @@ -540,360 +612,53 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); } -#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj) -#define to_mcidev_attr(a) container_of(a,struct mcidev_sysfs_attribute,attr) - -/* MCI show/store functions for top most object */ -static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) -{ - struct mem_ctl_info *mem_ctl_info = to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->show) - return mcidev_attr->show(mem_ctl_info, buffer); - - return -EIO; -} - -static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct mem_ctl_info *mem_ctl_info = to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->store) - return mcidev_attr->store(mem_ctl_info, buffer, count); - - return -EIO; -} - -/* Intermediate show/store table */ -static const struct sysfs_ops mci_ops = { - .show = mcidev_show, - .store = mcidev_store -}; - -#define MCIDEV_ATTR(_name,_mode,_show,_store) \ -static struct mcidev_sysfs_attribute mci_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -}; - /* default Control file */ -MCIDEV_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); +DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); /* default Attribute files */ -MCIDEV_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL); -MCIDEV_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL); -MCIDEV_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL); -MCIDEV_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); -MCIDEV_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); -MCIDEV_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); -MCIDEV_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); +DEVICE_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL); +DEVICE_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL); +DEVICE_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL); +DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); +DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); +DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); +DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); /* memory scrubber attribute file */ -MCIDEV_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, +DEVICE_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, mci_sdram_scrub_rate_store); -static struct mcidev_sysfs_attribute *mci_attr[] = { - &mci_attr_reset_counters, - &mci_attr_mc_name, - &mci_attr_size_mb, - &mci_attr_seconds_since_reset, - &mci_attr_ue_noinfo_count, - &mci_attr_ce_noinfo_count, - &mci_attr_ue_count, - &mci_attr_ce_count, - &mci_attr_sdram_scrub_rate, +static struct attribute *mci_attrs[] = { + &dev_attr_reset_counters.attr, + &dev_attr_mc_name.attr, + &dev_attr_size_mb.attr, + &dev_attr_seconds_since_reset.attr, + &dev_attr_ue_noinfo_count.attr, + &dev_attr_ce_noinfo_count.attr, + &dev_attr_ue_count.attr, + &dev_attr_ce_count.attr, + &dev_attr_sdram_scrub_rate.attr, NULL }; - -/* - * Release of a MC controlling instance - * - * each MC control instance has the following resources upon entry: - * a) a ref count on the top memctl kobj - * b) a ref count on this module - * - * this function must decrement those ref counts and then - * issue a free on the instance's memory - */ -static void edac_mci_control_release(struct kobject *kobj) -{ - struct mem_ctl_info *mci; - - mci = to_mci(kobj); - - debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx); - - /* decrement the module ref count */ - module_put(mci->owner); -} - -static struct kobj_type ktype_mci = { - .release = edac_mci_control_release, - .sysfs_ops = &mci_ops, - .default_attrs = (struct attribute **)mci_attr, -}; - -/* EDAC memory controller sysfs kset: - * /sys/devices/system/edac/mc - */ -static struct kset *mc_kset; - -/* - * edac_mc_register_sysfs_main_kobj - * - * setups and registers the main kobject for each mci - */ -int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci) -{ - struct kobject *kobj_mci; - int err; - - debugf1("%s()\n", __func__); - - kobj_mci = &mci->edac_mci_kobj; - - /* Init the mci's kobject */ - memset(kobj_mci, 0, sizeof(*kobj_mci)); - - /* Record which module 'owns' this control structure - * and bump the ref count of the module - */ - mci->owner = THIS_MODULE; - - /* bump ref count on this module */ - if (!try_module_get(mci->owner)) { - err = -ENODEV; - goto fail_out; - } - - /* this instance become part of the mc_kset */ - kobj_mci->kset = mc_kset; - - /* register the mc kobject to the mc_kset */ - err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL, - "mc%d", mci->mc_idx); - if (err) { - debugf1("%s()Failed to register '.../edac/mc%d'\n", - __func__, mci->mc_idx); - goto kobj_reg_fail; - } - kobject_uevent(kobj_mci, KOBJ_ADD); - - /* At this point, to 'free' the control struct, - * edac_mc_unregister_sysfs_main_kobj() must be used - */ - - debugf1("%s() Registered '.../edac/mc%d' kobject\n", - __func__, mci->mc_idx); - - return 0; - - /* Error exit stack */ - -kobj_reg_fail: - module_put(mci->owner); - -fail_out: - return err; -} - -/* - * edac_mc_register_sysfs_main_kobj - * - * tears down and the main mci kobject from the mc_kset - */ -void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci) -{ - debugf1("%s()\n", __func__); - - /* delete the kobj from the mc_kset */ - kobject_put(&mci->edac_mci_kobj); -} - -#define EDAC_DEVICE_SYMLINK "device" - -#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci) - -/* MCI show/store functions for top most object */ -static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, - char *buffer) -{ - struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->show) - return mcidev_attr->show(mem_ctl_info, buffer); - - return -EIO; -} - -static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->store) - return mcidev_attr->store(mem_ctl_info, buffer, count); - - return -EIO; -} - -/* No memory to release for this kobj */ -static void edac_inst_grp_release(struct kobject *kobj) -{ - struct mcidev_sysfs_group_kobj *grp; - struct mem_ctl_info *mci; - - debugf1("%s()\n", __func__); - - grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj); - mci = grp->mci; -} - -/* Intermediate show/store table */ -static struct sysfs_ops inst_grp_ops = { - .show = inst_grp_show, - .store = inst_grp_store +static struct attribute_group mci_attr_grp = { + .attrs = mci_attrs, }; -/* the kobj_type instance for a instance group */ -static struct kobj_type ktype_inst_grp = { - .release = edac_inst_grp_release, - .sysfs_ops = &inst_grp_ops, +static const struct attribute_group *mci_attr_groups[] = { + &mci_attr_grp, + NULL }; - -/* - * edac_create_mci_instance_attributes - * create MC driver specific attributes bellow an specified kobj - * This routine calls itself recursively, in order to create an entire - * object tree. - */ -static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, - const struct mcidev_sysfs_attribute *sysfs_attrib, - struct kobject *kobj) +static void mci_attr_release(struct device *device) { - int err; - - debugf4("%s()\n", __func__); - - while (sysfs_attrib) { - debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib); - if (sysfs_attrib->grp) { - struct mcidev_sysfs_group_kobj *grp_kobj; - - grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL); - if (!grp_kobj) - return -ENOMEM; - - grp_kobj->grp = sysfs_attrib->grp; - grp_kobj->mci = mci; - list_add_tail(&grp_kobj->list, &mci->grp_kobj_list); - - debugf0("%s() grp %s, mci %p\n", __func__, - sysfs_attrib->grp->name, mci); - - err = kobject_init_and_add(&grp_kobj->kobj, - &ktype_inst_grp, - &mci->edac_mci_kobj, - sysfs_attrib->grp->name); - if (err < 0) { - printk(KERN_ERR "kobject_init_and_add failed: %d\n", err); - return err; - } - err = edac_create_mci_instance_attributes(mci, - grp_kobj->grp->mcidev_attr, - &grp_kobj->kobj); - - if (err < 0) - return err; - } else if (sysfs_attrib->attr.name) { - debugf4("%s() file %s\n", __func__, - sysfs_attrib->attr.name); - - err = sysfs_create_file(kobj, &sysfs_attrib->attr); - if (err < 0) { - printk(KERN_ERR "sysfs_create_file failed: %d\n", err); - return err; - } - } else - break; - - sysfs_attrib++; - } - - return 0; + debugf1("Releasing mci device %s\n", dev_name(device)); } -/* - * edac_remove_mci_instance_attributes - * remove MC driver specific attributes at the topmost level - * directory of this mci instance. - */ -static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, - const struct mcidev_sysfs_attribute *sysfs_attrib, - struct kobject *kobj, int count) -{ - struct mcidev_sysfs_group_kobj *grp_kobj, *tmp; - - debugf1("%s()\n", __func__); - - /* - * loop if there are attributes and until we hit a NULL entry - * Remove first all the attributes - */ - while (sysfs_attrib) { - debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib); - if (sysfs_attrib->grp) { - debugf4("%s() seeking for group %s\n", - __func__, sysfs_attrib->grp->name); - list_for_each_entry(grp_kobj, - &mci->grp_kobj_list, list) { - debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp); - if (grp_kobj->grp == sysfs_attrib->grp) { - edac_remove_mci_instance_attributes(mci, - grp_kobj->grp->mcidev_attr, - &grp_kobj->kobj, count + 1); - debugf4("%s() group %s\n", __func__, - sysfs_attrib->grp->name); - kobject_put(&grp_kobj->kobj); - } - } - debugf4("%s() end of seeking for group %s\n", - __func__, sysfs_attrib->grp->name); - } else if (sysfs_attrib->attr.name) { - debugf4("%s() file %s\n", __func__, - sysfs_attrib->attr.name); - sysfs_remove_file(kobj, &sysfs_attrib->attr); - } else - break; - sysfs_attrib++; - } - - /* Remove the group objects */ - if (count) - return; - list_for_each_entry_safe(grp_kobj, tmp, - &mci->grp_kobj_list, list) { - list_del(&grp_kobj->list); - kfree(grp_kobj); - } -} +static struct device_type mci_attr_type = { + .groups = mci_attr_groups, + .release = mci_attr_release, +}; /* @@ -906,77 +671,80 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, */ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) { - int i, j; - int err; - struct csrow_info *csrow; - struct kobject *kobj_mci = &mci->edac_mci_kobj; + int i, err; debugf0("%s() idx=%d\n", __func__, mci->mc_idx); - INIT_LIST_HEAD(&mci->grp_kobj_list); + /* get the /sys/devices/system/edac subsys reference */ - /* create a symlink for the device */ - err = sysfs_create_link(kobj_mci, &mci->pdev->kobj, - EDAC_DEVICE_SYMLINK); - if (err) { - debugf1("%s() failure to create symlink\n", __func__); - goto fail0; - } + mci->dev.type = &mci_attr_type; + device_initialize(&mci->dev); - /* If the low level driver desires some attributes, - * then create them now for the driver. + mci->dev.parent = &mci_pdev; + mci->dev.bus = &mci->bus; + dev_set_name(&mci->dev, "mc%d", mci->mc_idx); + dev_set_drvdata(&mci->dev, mci); + pm_runtime_forbid(&mci->dev); + + /* + * The memory controller needs its own bus, in order to avoid + * namespace conflicts at /sys/bus/edac. */ - if (mci->mc_driver_sysfs_attributes) { - err = edac_create_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, - &mci->edac_mci_kobj); - if (err) { - debugf1("%s() failure to create mci attributes\n", - __func__); - goto fail0; - } + debugf0("creating bus %s\n",mci->bus.name); + mci->bus.name = kstrdup(dev_name(&mci->dev), GFP_KERNEL); + err = bus_register(&mci->bus); + if (err < 0) + return err; + + debugf0("%s(): creating device %s\n", __func__, + dev_name(&mci->dev)); + err = device_add(&mci->dev); + if (err < 0) { + bus_unregister(&mci->bus); + kfree(mci->bus.name); + return err; } - /* Make directories for each CSROW object under the mc kobject + /* + * Create the dimm/rank devices */ - for (i = 0; i < mci->nr_csrows; i++) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - - if (nr_pages > 0) { - err = edac_create_csrow_object(mci, csrow, i); - if (err) { - debugf1("%s() failure: create csrow %d obj\n", - __func__, i); - goto fail1; - } + for (i = 0; i < mci->tot_dimms; i++) { + struct dimm_info *dimm = &mci->dimms[i]; + /* Only expose populated DIMMs */ + if (dimm->nr_pages == 0) + continue; +#ifdef CONFIG_EDAC_DEBUG + debugf1("%s creating dimm%d, located at ", + __func__, i); + if (edac_debug_level >= 1) { + int lay; + for (lay = 0; lay < mci->n_layers; lay++) + printk(KERN_CONT "%s %d ", + edac_layer_name[mci->layers[lay].type], + dimm->location[lay]); + printk(KERN_CONT "\n"); } +#endif } + err = edac_create_csrow_objects(mci); + if (err < 0) + goto fail; + return 0; -fail1: +fail: for (i--; i >= 0; i--) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - if (nr_pages > 0) - kobject_put(&mci->csrows[i].kobj); + struct dimm_info *dimm = &mci->dimms[i]; + if (dimm->nr_pages == 0) + continue; + put_device(&dimm->dev); + device_del(&dimm->dev); } - - /* remove the mci instance's attributes, if any */ - edac_remove_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); - - /* remove the symlink */ - sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); - -fail0: + put_device(&mci->dev); + device_del(&mci->dev); + bus_unregister(&mci->bus); + kfree(mci->bus.name); return err; } @@ -985,98 +753,70 @@ fail0: */ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { - struct csrow_info *csrow; - int i, j; + int i; debugf0("%s()\n", __func__); - /* remove all csrow kobjects */ - debugf4("%s() unregister this mci kobj\n", __func__); - for (i = 0; i < mci->nr_csrows; i++) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - if (nr_pages > 0) { - debugf0("%s() unreg csrow-%d\n", __func__, i); - kobject_put(&mci->csrows[i].kobj); - } - } + edac_delete_csrow_objects(mci); - /* remove this mci instance's attribtes */ - if (mci->mc_driver_sysfs_attributes) { - debugf4("%s() unregister mci private attributes\n", __func__); - edac_remove_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, - &mci->edac_mci_kobj, 0); + for (i = 0; i < mci->tot_dimms; i++) { + struct dimm_info *dimm = &mci->dimms[i]; + if (dimm->nr_pages == 0) + continue; + debugf0("%s(): removing device %s\n", __func__, + dev_name(&dimm->dev)); + put_device(&dimm->dev); + device_del(&dimm->dev); } - - /* remove the symlink */ - debugf4("%s() remove_link\n", __func__); - sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); - - /* unregister this instance's kobject */ - debugf4("%s() remove_mci_instance\n", __func__); - kobject_put(&mci->edac_mci_kobj); } +void edac_unregister_sysfs(struct mem_ctl_info *mci) +{ + debugf1("Unregistering device %s\n", dev_name(&mci->dev)); + put_device(&mci->dev); + device_del(&mci->dev); + bus_unregister(&mci->bus); + kfree(mci->bus.name); +} +static void mc_attr_release(struct device *device) +{ + debugf1("Releasing device %s\n", dev_name(device)); +} - +static struct device_type mc_attr_type = { + .release = mc_attr_release, +}; /* - * edac_setup_sysfs_mc_kset(void) - * - * Initialize the mc_kset for the 'mc' entry - * This requires creating the top 'mc' directory with a kset - * and its controls/attributes. - * - * To this 'mc' kset, instance 'mci' will be grouped as children. - * - * Return: 0 SUCCESS - * !0 FAILURE error code + * Init/exit code for the module. Basically, creates/removes /sys/class/rc */ -int edac_sysfs_setup_mc_kset(void) +int __init edac_mc_sysfs_init(void) { - int err = -EINVAL; struct bus_type *edac_subsys; - - debugf1("%s()\n", __func__); + int err; /* get the /sys/devices/system/edac subsys reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys error=%d\n", __func__, err); - goto fail_out; + debugf1("%s() no edac_subsys\n", __func__); + return -EINVAL; } - /* Init the MC's kobject */ - mc_kset = kset_create_and_add("mc", NULL, &edac_subsys->dev_root->kobj); - if (!mc_kset) { - err = -ENOMEM; - debugf1("%s() Failed to register '.../edac/mc'\n", __func__); - goto fail_kset; - } + mci_pdev.bus = edac_subsys; + mci_pdev.type = &mc_attr_type; + device_initialize(&mci_pdev); + dev_set_name(&mci_pdev, "mc"); - debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); + err = device_add(&mci_pdev); + if (err < 0) + return err; return 0; - -fail_kset: - edac_put_sysfs_subsys(); - -fail_out: - return err; } -/* - * edac_sysfs_teardown_mc_kset - * - * deconstruct the mc_ket for memory controllers - */ -void edac_sysfs_teardown_mc_kset(void) +void __exit edac_mc_sysfs_exit(void) { - kset_unregister(mc_kset); + put_device(&mci_pdev); + device_del(&mci_pdev); edac_put_sysfs_subsys(); } - diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 5ddaa86d6a6e..8735a0d3ed0c 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -90,10 +90,7 @@ static int __init edac_init(void) */ edac_pci_clear_parity_errors(); - /* - * now set up the mc_kset under the edac class object - */ - err = edac_sysfs_setup_mc_kset(); + err = edac_mc_sysfs_init(); if (err) goto error; @@ -101,15 +98,11 @@ static int __init edac_init(void) err = edac_workqueue_setup(); if (err) { edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n"); - goto workq_fail; + goto error; } return 0; - /* Error teardown stack */ -workq_fail: - edac_sysfs_teardown_mc_kset(); - error: return err; } @@ -124,7 +117,7 @@ static void __exit edac_exit(void) /* tear down the various subsystems */ edac_workqueue_teardown(); - edac_sysfs_teardown_mc_kset(); + edac_mc_sysfs_exit(); } /* diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 0ea7d14cb930..1af13676e857 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -19,12 +19,12 @@ * * edac_mc objects */ -extern int edac_sysfs_setup_mc_kset(void); -extern void edac_sysfs_teardown_mc_kset(void); -extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci); -extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci); + /* on edac_mc_sysfs.c */ +int edac_mc_sysfs_init(void); +void edac_mc_sysfs_exit(void); extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci); extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci); +void edac_unregister_sysfs(struct mem_ctl_info *mci); extern int edac_get_log_ue(void); extern int edac_get_log_ce(void); extern int edac_get_panic_on_ue(void); @@ -34,6 +34,7 @@ extern int edac_mc_get_panic_on_ue(void); extern int edac_get_poll_msec(void); extern int edac_mc_get_poll_msec(void); + /* on edac_device.c */ extern int edac_device_register_sysfs_main_kobj( struct edac_device_ctl_info *edac_dev); extern void edac_device_unregister_sysfs_main_kobj( diff --git a/include/linux/edac.h b/include/linux/edac.h index 4e32e8d31e0a..a2b0b6fc002c 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -13,6 +13,7 @@ #define _LINUX_EDAC_H_ #include +#include #include #include #include @@ -448,14 +449,15 @@ struct edac_mc_layer { __p; \ }) - -/* FIXME: add the proper per-location error counts */ struct dimm_info { + struct device dev; + char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ /* Memory location data */ unsigned location[EDAC_MAX_LAYERS]; + struct kobject kobj; /* sysfs kobject for this csrow */ struct mem_ctl_info *mci; /* the parent */ u32 grain; /* granularity of reported error in bytes */ @@ -484,6 +486,8 @@ struct dimm_info { * patches in this series will fix this issue. */ struct rank_info { + struct device dev; + int chan_idx; struct csrow_info *csrow; struct dimm_info *dimm; @@ -492,6 +496,8 @@ struct rank_info { }; struct csrow_info { + struct device dev; + /* Used only by edac_mc_find_csrow_by_page() */ unsigned long first_page; /* first page number in csrow */ unsigned long last_page; /* last page number in csrow */ @@ -517,15 +523,6 @@ struct mcidev_sysfs_group { const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ }; -struct mcidev_sysfs_group_kobj { - struct list_head list; /* list for all instances within a mc */ - - struct kobject kobj; /* kobj for the group */ - - const struct mcidev_sysfs_group *grp; /* group description table */ - struct mem_ctl_info *mci; /* the parent */ -}; - /* mcidev_sysfs_attribute structure * used for driver sysfs attributes and in mem_ctl_info * sysfs top level entries @@ -536,13 +533,27 @@ struct mcidev_sysfs_attribute { const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ /* Ops for show/store values at the attribute - not used on group */ - ssize_t (*show)(struct mem_ctl_info *,char *); - ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); + ssize_t (*show)(struct mem_ctl_info *, char *); + ssize_t (*store)(struct mem_ctl_info *, const char *, size_t); + + void *priv; +}; + +/* + * struct errcount_attribute - used to store the several error counts + */ +struct errcount_attribute_data { + int n_layers; + int pos[EDAC_MAX_LAYERS]; + int layer0, layer1, layer2; }; /* MEMORY controller information structure */ struct mem_ctl_info { + struct device dev; + struct bus_type bus; + struct list_head link; /* for global list of mem_ctl_info structs */ struct module *owner; /* Module owner of this control struct */ @@ -587,7 +598,15 @@ struct mem_ctl_info { struct csrow_info *csrows; unsigned nr_csrows, num_cschannel; - /* Memory Controller hierarchy */ + /* + * Memory Controller hierarchy + * + * There are basically two types of memory controller: the ones that + * sees memory sticks ("dimms"), and the ones that sees memory ranks. + * All old memory controllers enumerate memories per rank, but most + * of the recent drivers enumerate memories per DIMM, instead. + * When the memory controller is per rank, mem_is_per_rank is true. + */ unsigned n_layers; struct edac_mc_layer *layers; bool mem_is_per_rank; -- GitLab From ba004239e008a442bc327a57e227600fc1bd5ee7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 15:16:20 -0300 Subject: [PATCH 0440/5711] mpc85xx_edac: convert sysfs logic to use struct device Now that the EDAC core supports struct device, there's no sense on having any logic at the EDAC core to simulate it. So, instead of adding such logic there, change the logic at mpc85xx_edac to use it compile-tested only. Reviewed-by: Aristeu Rozanski Cc: Andrew Morton Cc: Shaohui Xie Cc: Jiri Kosina Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/mpc85xx_edac.c | 93 ++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 67fb3280f333..d132dbbd9bd7 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -49,34 +49,45 @@ static u32 orig_hid1[2]; /************************ MC SYSFS parts ***********************************/ -static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci, +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + +static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI)); } -static ssize_t mpc85xx_mc_inject_data_lo_show(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO)); } -static ssize_t mpc85xx_mc_inject_ctrl_show(struct mem_ctl_info *mci, char *data) +static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT)); } -static ssize_t mpc85xx_mc_inject_data_hi_store(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI, @@ -86,9 +97,11 @@ static ssize_t mpc85xx_mc_inject_data_hi_store(struct mem_ctl_info *mci, return 0; } -static ssize_t mpc85xx_mc_inject_data_lo_store(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO, @@ -98,9 +111,11 @@ static ssize_t mpc85xx_mc_inject_data_lo_store(struct mem_ctl_info *mci, return 0; } -static ssize_t mpc85xx_mc_inject_ctrl_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT, @@ -110,38 +125,35 @@ static ssize_t mpc85xx_mc_inject_ctrl_store(struct mem_ctl_info *mci, return 0; } -static struct mcidev_sysfs_attribute mpc85xx_mc_sysfs_attributes[] = { - { - .attr = { - .name = "inject_data_hi", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_data_hi_show, - .store = mpc85xx_mc_inject_data_hi_store}, - { - .attr = { - .name = "inject_data_lo", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_data_lo_show, - .store = mpc85xx_mc_inject_data_lo_store}, - { - .attr = { - .name = "inject_ctrl", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_ctrl_show, - .store = mpc85xx_mc_inject_ctrl_store}, +DEVICE_ATTR(inject_data_hi, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_data_hi_show, mpc85xx_mc_inject_data_hi_store); +DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_data_lo_show, mpc85xx_mc_inject_data_lo_store); +DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store); - /* End of list */ - { - .attr = {.name = NULL} - } -}; +static int mpc85xx_create_sysfs_attributes(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_data_hi); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_data_lo); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_ctrl); + if (rc < 0) + return rc; -static void mpc85xx_set_mc_sysfs_attributes(struct mem_ctl_info *mci) + return 0; +} + +static void mpc85xx_remove_sysfs_attributes(struct mem_ctl_info *mci) { - mci->mc_driver_sysfs_attributes = mpc85xx_mc_sysfs_attributes; + device_remove_file(&mci->dev, &dev_attr_inject_data_hi); + device_remove_file(&mci->dev, &dev_attr_inject_data_lo); + device_remove_file(&mci->dev, &dev_attr_inject_ctrl); } /**************************** PCI Err device ***************************/ @@ -1040,8 +1052,6 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) mci->scrub_mode = SCRUB_SW_SRC; - mpc85xx_set_mc_sysfs_attributes(mci); - mpc85xx_init_csrows(mci); /* store the original error disable bits */ @@ -1057,6 +1067,12 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) goto err; } + if (mpc85xx_create_sysfs_attributes(mci)) { + edac_mc_del_mc(mci->pdev); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + goto err; + } + if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, DDR_EIE_MBEE | DDR_EIE_SBEE); @@ -1116,6 +1132,7 @@ static int mpc85xx_mc_err_remove(struct platform_device *op) orig_ddr_err_disable); out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe); + mpc85xx_remove_sysfs_attributes(mci); edac_mc_del_mc(&op->dev); edac_mc_free(mci); return 0; -- GitLab From c56087595fb6531f359925b581529f1b2aef10f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 14:00:44 -0300 Subject: [PATCH 0441/5711] amd64_edac: convert sysfs logic to use struct device Now that the EDAC core supports struct device, there's no sense on having any logic at the EDAC core to simulate it. So, instead of adding such logic there, change the logic at amd64_edac to use it. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Cc: Borislav Petkov Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 43 +++++++----- drivers/edac/amd64_edac.h | 29 ++++++-- drivers/edac/amd64_edac_dbg.c | 89 +++++++++++------------ drivers/edac/amd64_edac_inj.c | 128 ++++++++++++++++++++-------------- 4 files changed, 167 insertions(+), 122 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 821bc2cdd2de..9905834b560f 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2463,26 +2463,29 @@ static bool ecc_enabled(struct pci_dev *F3, u8 nid) return true; } -struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + - ARRAY_SIZE(amd64_inj_attrs) + - 1]; - -struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; - -static void set_mc_sysfs_attrs(struct mem_ctl_info *mci) +static int set_mc_sysfs_attrs(struct mem_ctl_info *mci) { - unsigned int i = 0, j = 0; + int rc; - for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) - sysfs_attrs[i] = amd64_dbg_attrs[i]; + rc = amd64_create_sysfs_dbg_files(mci); + if (rc < 0) + return rc; - if (boot_cpu_data.x86 >= 0x10) - for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) - sysfs_attrs[i] = amd64_inj_attrs[j]; + if (boot_cpu_data.x86 >= 0x10) { + rc = amd64_create_sysfs_inject_files(mci); + if (rc < 0) + return rc; + } + + return 0; +} - sysfs_attrs[i] = terminator; +static void del_mc_sysfs_attrs(struct mem_ctl_info *mci) +{ + amd64_remove_sysfs_dbg_files(mci); - mci->mc_driver_sysfs_attributes = sysfs_attrs; + if (boot_cpu_data.x86 >= 0x10) + amd64_remove_sysfs_inject_files(mci); } static void setup_mci_misc_attrs(struct mem_ctl_info *mci, @@ -2608,13 +2611,15 @@ static int amd64_init_one_instance(struct pci_dev *F2) if (init_csrows(mci)) mci->edac_cap = EDAC_FLAG_NONE; - set_mc_sysfs_attrs(mci); - ret = -ENODEV; if (edac_mc_add_mc(mci)) { debugf1("failed edac_mc_add_mc()\n"); goto err_add_mc; } + if (set_mc_sysfs_attrs(mci)) { + debugf1("failed edac_mc_add_mc()\n"); + goto err_add_sysfs; + } /* register stuff with EDAC MCE */ if (report_gart_errors) @@ -2628,6 +2633,8 @@ static int amd64_init_one_instance(struct pci_dev *F2) return 0; +err_add_sysfs: + edac_mc_del_mc(mci->pdev); err_add_mc: edac_mc_free(mci); @@ -2698,6 +2705,8 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) struct pci_dev *F3 = node_to_amd_nb(nid)->misc; struct ecc_settings *s = ecc_stngs[nid]; + mci = find_mci_by_dev(&pdev->dev); + del_mc_sysfs_attrs(mci); /* Remove from EDAC CORE tracking list */ mci = edac_mc_del_mc(&pdev->dev); if (!mci) diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 9a666cb985b2..8d4804732bac 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -413,20 +413,33 @@ struct ecc_settings { }; #ifdef CONFIG_EDAC_DEBUG -#define NUM_DBG_ATTRS 5 +int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci); +void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci); + #else -#define NUM_DBG_ATTRS 0 +static inline int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + return 0; +} +static void inline amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci) +{ +} #endif #ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION -#define NUM_INJ_ATTRS 5 +int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci); +void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci); + #else -#define NUM_INJ_ATTRS 0 +static inline int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci) +{ + return 0; +} +static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci) +{ +} #endif -extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS], - amd64_inj_attrs[NUM_INJ_ATTRS]; - /* * Each of the PCI Device IDs types have their own set of hardware accessor * functions and per device encoding/decoding logic. @@ -460,3 +473,5 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, u64 *hole_offset, u64 *hole_size); + +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c index e3562288f4ce..2c1bbf740605 100644 --- a/drivers/edac/amd64_edac_dbg.c +++ b/drivers/edac/amd64_edac_dbg.c @@ -1,8 +1,11 @@ #include "amd64_edac.h" #define EDAC_DCT_ATTR_SHOW(reg) \ -static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \ +static ssize_t amd64_##reg##_show(struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct amd64_pvt *pvt = mci->pvt_info; \ return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \ } @@ -12,8 +15,12 @@ EDAC_DCT_ATTR_SHOW(dbam0); EDAC_DCT_ATTR_SHOW(top_mem); EDAC_DCT_ATTR_SHOW(top_mem2); -static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) +static ssize_t amd64_hole_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + u64 hole_base = 0; u64 hole_offset = 0; u64 hole_size = 0; @@ -27,46 +34,40 @@ static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) /* * update NUM_DBG_ATTRS in case you add new members */ -struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { +static DEVICE_ATTR(dhar, S_IRUGO, amd64_dhar_show, NULL); +static DEVICE_ATTR(dbam, S_IRUGO, amd64_dbam0_show, NULL); +static DEVICE_ATTR(topmem, S_IRUGO, amd64_top_mem_show, NULL); +static DEVICE_ATTR(topmem2, S_IRUGO, amd64_top_mem2_show, NULL); +static DEVICE_ATTR(dram_hole, S_IRUGO, amd64_hole_show, NULL); + +int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_dhar); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_dbam); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_topmem); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_topmem2); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_dram_hole); + if (rc < 0) + return rc; - { - .attr = { - .name = "dhar", - .mode = (S_IRUGO) - }, - .show = amd64_dhar_show, - .store = NULL, - }, - { - .attr = { - .name = "dbam", - .mode = (S_IRUGO) - }, - .show = amd64_dbam0_show, - .store = NULL, - }, - { - .attr = { - .name = "topmem", - .mode = (S_IRUGO) - }, - .show = amd64_top_mem_show, - .store = NULL, - }, - { - .attr = { - .name = "topmem2", - .mode = (S_IRUGO) - }, - .show = amd64_top_mem2_show, - .store = NULL, - }, - { - .attr = { - .name = "dram_hole", - .mode = (S_IRUGO) - }, - .show = amd64_hole_show, - .store = NULL, - }, -}; + return 0; +} + +void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + device_remove_file(&mci->dev, &dev_attr_dhar); + device_remove_file(&mci->dev, &dev_attr_dbam); + device_remove_file(&mci->dev, &dev_attr_topmem); + device_remove_file(&mci->dev, &dev_attr_topmem2); + device_remove_file(&mci->dev, &dev_attr_dram_hole); +} diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index 303f10e03dda..ef1ff4ea9576 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c @@ -1,7 +1,10 @@ #include "amd64_edac.h" -static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_section_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.section); } @@ -12,9 +15,11 @@ static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) * * range: 0..3 */ -static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, +static ssize_t amd64_inject_section_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -33,8 +38,11 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, return ret; } -static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_word_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.word); } @@ -45,9 +53,11 @@ static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) * * range: 0..8 */ -static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_word_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -66,8 +76,11 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, return ret; } -static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_ecc_vector_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.bit_map); } @@ -77,9 +90,11 @@ static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) * corresponding bit within the error injection word above. When used during a * DRAM ECC read, it holds the contents of the of the DRAM ECC bits. */ -static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_ecc_vector_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -103,9 +118,11 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, * Do a DRAM ECC read. Assemble staged values in the pvt area, format into * fields needed by the injection registers and read the NB Array Data Port. */ -static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_read_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; u32 section, word_bits; @@ -136,9 +153,11 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, * Do a DRAM ECC write. Assemble staged values in the pvt area and format into * fields needed by the injection registers. */ -static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, +static ssize_t amd64_inject_write_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; u32 section, word_bits; @@ -168,46 +187,47 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, /* * update NUM_INJ_ATTRS in case you add new members */ -struct mcidev_sysfs_attribute amd64_inj_attrs[] = { - - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_section_show, - .store = amd64_inject_section_store, - }, - { - .attr = { - .name = "inject_word", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_word_show, - .store = amd64_inject_word_store, - }, - { - .attr = { - .name = "inject_ecc_vector", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_ecc_vector_show, - .store = amd64_inject_ecc_vector_store, - }, - { - .attr = { - .name = "inject_write", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = NULL, - .store = amd64_inject_write_store, - }, - { - .attr = { - .name = "inject_read", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = NULL, - .store = amd64_inject_read_store, - }, -}; + +static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, + amd64_inject_section_show, amd64_inject_section_store); +static DEVICE_ATTR(inject_word, S_IRUGO | S_IWUSR, + amd64_inject_word_show, amd64_inject_word_store); +static DEVICE_ATTR(inject_ecc_vector, S_IRUGO | S_IWUSR, + amd64_inject_ecc_vector_show, amd64_inject_ecc_vector_store); +static DEVICE_ATTR(inject_write, S_IRUGO | S_IWUSR, + NULL, amd64_inject_write_store); +static DEVICE_ATTR(inject_read, S_IRUGO | S_IWUSR, + NULL, amd64_inject_read_store); + + +int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_section); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_word); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_ecc_vector); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_write); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_read); + if (rc < 0) + return rc; + + return 0; +} + +void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci) +{ + device_remove_file(&mci->dev, &dev_attr_inject_section); + device_remove_file(&mci->dev, &dev_attr_inject_word); + device_remove_file(&mci->dev, &dev_attr_inject_ecc_vector); + device_remove_file(&mci->dev, &dev_attr_inject_write); + device_remove_file(&mci->dev, &dev_attr_inject_read); +} -- GitLab From 5c4cdb5ae72988ef93f72ad6f46be0e4eea5be8d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 11:08:06 -0300 Subject: [PATCH 0442/5711] i7core_edac: convert it to use struct device Instead of relying on a complex logic inside the edac core to create a "device tree-like" sysfs struct, just use device_add. Reviewed-by: Aristeu Rozanski Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 338 +++++++++++++++++++++++-------------- 1 file changed, 209 insertions(+), 129 deletions(-) diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 598d215f7bd5..ab3b84b906b9 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -248,6 +248,8 @@ struct i7core_dev { }; struct i7core_pvt { + struct device addrmatch_dev, chancounts_dev; + struct pci_dev *pci_noncore; struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; @@ -662,6 +664,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) Error insertion routines ****************************************************************************/ +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + /* The i7core has independent error injection features per channel. However, to have a simpler code, we don't allow enabling error injection on more than one channel. @@ -691,9 +695,11 @@ static int disable_inject(const struct mem_ctl_info *mci) * bit 0 - refers to the lower 32-byte half cacheline * bit 1 - refers to the upper 32-byte half cacheline */ -static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, +static ssize_t i7core_inject_section_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -709,9 +715,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_section_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; return sprintf(data, "0x%08x\n", pvt->inject.section); } @@ -724,10 +732,12 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, * bit 1 - inject ECC error * bit 2 - inject parity error */ -static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, +static ssize_t i7core_inject_type_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { - struct i7core_pvt *pvt = mci->pvt_info; + struct mem_ctl_info *mci = to_mci(dev); +struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -742,10 +752,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_type_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; + return sprintf(data, "0x%08x\n", pvt->inject.type); } @@ -759,9 +772,11 @@ static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an * uncorrectable error to be injected. */ -static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t i7core_inject_eccmask_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -777,10 +792,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_eccmask_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; + return sprintf(data, "0x%08x\n", pvt->inject.eccmask); } @@ -797,9 +815,11 @@ static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, #define DECLARE_ADDR_MATCH(param, limit) \ static ssize_t i7core_inject_store_##param( \ - struct mem_ctl_info *mci, \ - const char *data, size_t count) \ + struct device *dev, \ + struct device_attribute *mattr, \ + const char *data, size_t count) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ long value; \ int rc; \ @@ -824,9 +844,11 @@ static ssize_t i7core_inject_store_##param( \ } \ \ static ssize_t i7core_inject_show_##param( \ - struct mem_ctl_info *mci, \ - char *data) \ + struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ \ pvt = mci->pvt_info; \ @@ -838,14 +860,9 @@ static ssize_t i7core_inject_show_##param( \ } #define ATTR_ADDR_MATCH(param) \ - { \ - .attr = { \ - .name = #param, \ - .mode = (S_IRUGO | S_IWUSR) \ - }, \ - .show = i7core_inject_show_##param, \ - .store = i7core_inject_store_##param, \ - } + static DEVICE_ATTR(param, S_IRUGO | S_IWUSR, \ + i7core_inject_show_##param, \ + i7core_inject_store_##param) DECLARE_ADDR_MATCH(channel, 3); DECLARE_ADDR_MATCH(dimm, 3); @@ -854,6 +871,13 @@ DECLARE_ADDR_MATCH(bank, 32); DECLARE_ADDR_MATCH(page, 0x10000); DECLARE_ADDR_MATCH(col, 0x4000); +ATTR_ADDR_MATCH(channel); +ATTR_ADDR_MATCH(dimm); +ATTR_ADDR_MATCH(rank); +ATTR_ADDR_MATCH(bank); +ATTR_ADDR_MATCH(page); +ATTR_ADDR_MATCH(col); + static int write_and_test(struct pci_dev *dev, const int where, const u32 val) { u32 read; @@ -899,9 +923,11 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val) * is reliable enough to check if the MC is using the * three channels. However, this is not clear at the datasheet. */ -static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t i7core_inject_enable_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; u32 injectmask; u64 mask = 0; @@ -1002,9 +1028,11 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_enable_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; u32 injectmask; @@ -1024,12 +1052,14 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, #define DECLARE_COUNTER(param) \ static ssize_t i7core_show_counter_##param( \ - struct mem_ctl_info *mci, \ - char *data) \ + struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt = mci->pvt_info; \ \ - debugf1("%s() \n", __func__); \ + debugf1("%s()\n", __func__); \ if (!pvt->ce_count_available || (pvt->is_registered)) \ return sprintf(data, "data unavailable\n"); \ return sprintf(data, "%lu\n", \ @@ -1037,121 +1067,167 @@ static ssize_t i7core_show_counter_##param( \ } #define ATTR_COUNTER(param) \ - { \ - .attr = { \ - .name = __stringify(udimm##param), \ - .mode = (S_IRUGO | S_IWUSR) \ - }, \ - .show = i7core_show_counter_##param \ - } + static DEVICE_ATTR(udimm##param, S_IRUGO | S_IWUSR, \ + i7core_show_counter_##param, \ + NULL) DECLARE_COUNTER(0); DECLARE_COUNTER(1); DECLARE_COUNTER(2); +ATTR_COUNTER(0); +ATTR_COUNTER(1); +ATTR_COUNTER(2); + /* - * Sysfs struct + * inject_addrmatch device sysfs struct */ -static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = { - ATTR_ADDR_MATCH(channel), - ATTR_ADDR_MATCH(dimm), - ATTR_ADDR_MATCH(rank), - ATTR_ADDR_MATCH(bank), - ATTR_ADDR_MATCH(page), - ATTR_ADDR_MATCH(col), - { } /* End of list */ +static struct attribute *i7core_addrmatch_attrs[] = { + &dev_attr_channel.attr, + &dev_attr_dimm.attr, + &dev_attr_rank.attr, + &dev_attr_bank.attr, + &dev_attr_page.attr, + &dev_attr_col.attr, + NULL }; -static const struct mcidev_sysfs_group i7core_inject_addrmatch = { - .name = "inject_addrmatch", - .mcidev_attr = i7core_addrmatch_attrs, +static struct attribute_group addrmatch_grp = { + .attrs = i7core_addrmatch_attrs, }; -static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { - ATTR_COUNTER(0), - ATTR_COUNTER(1), - ATTR_COUNTER(2), - { .attr = { .name = NULL } } +static const struct attribute_group *addrmatch_groups[] = { + &addrmatch_grp, + NULL }; -static const struct mcidev_sysfs_group i7core_udimm_counters = { - .name = "all_channel_counts", - .mcidev_attr = i7core_udimm_counters_attrs, +static void addrmatch_release(struct device *device) +{ + debugf1("Releasing device %s\n", dev_name(device)); +} + +static struct device_type addrmatch_type = { + .groups = addrmatch_groups, + .release = addrmatch_release, }; -static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = { - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_section_show, - .store = i7core_inject_section_store, - }, { - .attr = { - .name = "inject_type", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_type_show, - .store = i7core_inject_type_store, - }, { - .attr = { - .name = "inject_eccmask", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_eccmask_show, - .store = i7core_inject_eccmask_store, - }, { - .grp = &i7core_inject_addrmatch, - }, { - .attr = { - .name = "inject_enable", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_enable_show, - .store = i7core_inject_enable_store, - }, - { } /* End of list */ +/* + * all_channel_counts sysfs struct + */ + +static struct attribute *i7core_udimm_counters_attrs[] = { + &dev_attr_udimm0.attr, + &dev_attr_udimm1.attr, + &dev_attr_udimm2.attr, + NULL +}; + +static struct attribute_group all_channel_counts_grp = { + .attrs = i7core_udimm_counters_attrs, }; -static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = { - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_section_show, - .store = i7core_inject_section_store, - }, { - .attr = { - .name = "inject_type", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_type_show, - .store = i7core_inject_type_store, - }, { - .attr = { - .name = "inject_eccmask", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_eccmask_show, - .store = i7core_inject_eccmask_store, - }, { - .grp = &i7core_inject_addrmatch, - }, { - .attr = { - .name = "inject_enable", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_enable_show, - .store = i7core_inject_enable_store, - }, { - .grp = &i7core_udimm_counters, - }, - { } /* End of list */ +static const struct attribute_group *all_channel_counts_groups[] = { + &all_channel_counts_grp, + NULL }; +static void all_channel_counts_release(struct device *device) +{ + debugf1("Releasing device %s\n", dev_name(device)); +} + +static struct device_type all_channel_counts_type = { + .groups = all_channel_counts_groups, + .release = all_channel_counts_release, +}; + +/* + * inject sysfs attributes + */ + +static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, + i7core_inject_section_show, i7core_inject_section_store); + +static DEVICE_ATTR(inject_type, S_IRUGO | S_IWUSR, + i7core_inject_type_show, i7core_inject_type_store); + + +static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR, + i7core_inject_eccmask_show, i7core_inject_eccmask_store); + +static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR, + i7core_inject_enable_show, i7core_inject_enable_store); + +static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) +{ + struct i7core_pvt *pvt = mci->pvt_info; + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_section); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_type); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_enable); + if (rc < 0) + return rc; + + pvt->addrmatch_dev.type = &addrmatch_type; + pvt->addrmatch_dev.bus = mci->dev.bus; + device_initialize(&pvt->addrmatch_dev); + pvt->addrmatch_dev.parent = &mci->dev; + dev_set_name(&pvt->addrmatch_dev, "inject_addrmatch"); + dev_set_drvdata(&pvt->addrmatch_dev, mci); + + debugf1("%s(): creating %s\n", __func__, + dev_name(&pvt->addrmatch_dev)); + + rc = device_add(&pvt->addrmatch_dev); + if (rc < 0) + return rc; + + if (!pvt->is_registered) { + pvt->chancounts_dev.type = &all_channel_counts_type; + pvt->chancounts_dev.bus = mci->dev.bus; + device_initialize(&pvt->chancounts_dev); + pvt->chancounts_dev.parent = &mci->dev; + dev_set_name(&pvt->chancounts_dev, "all_channel_counts"); + dev_set_drvdata(&pvt->chancounts_dev, mci); + + debugf1("%s(): creating %s\n", __func__, + dev_name(&pvt->chancounts_dev)); + + rc = device_add(&pvt->chancounts_dev); + if (rc < 0) + return rc; + } + return 0; +} + +static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) +{ + struct i7core_pvt *pvt = mci->pvt_info; + + debugf1("\n"); + + device_remove_file(&mci->dev, &dev_attr_inject_section); + device_remove_file(&mci->dev, &dev_attr_inject_type); + device_remove_file(&mci->dev, &dev_attr_inject_eccmask); + device_remove_file(&mci->dev, &dev_attr_inject_enable); + + if (!pvt->is_registered) { + put_device(&pvt->chancounts_dev); + device_del(&pvt->chancounts_dev); + } + put_device(&pvt->addrmatch_dev); + device_del(&pvt->addrmatch_dev); +} + /**************************************************************************** Device initialization routines: put/get, init/exit ****************************************************************************/ @@ -2122,6 +2198,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) i7core_pci_ctl_release(pvt); /* Remove MC sysfs nodes */ + i7core_delete_sysfs_devices(mci); edac_mc_del_mc(mci->pdev); debugf1("%s: free mci struct\n", mci->ctl_name); @@ -2180,10 +2257,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) if (unlikely(rc < 0)) goto fail0; - if (pvt->is_registered) - mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs; - else - mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs; /* Get dimm basic config */ get_dimm_config(mci); @@ -2207,6 +2280,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) rc = -EINVAL; goto fail0; } + if (i7core_create_sysfs_devices(mci)) { + debugf0("MC: " __FILE__ + ": %s(): failed to create sysfs nodes\n", __func__); + edac_mc_del_mc(mci->pdev); + rc = -EINVAL; + goto fail0; + } /* Default error mask is any memory */ pvt->inject.channel = 0; -- GitLab From d90c008963ef638cb7ab7d5eb76362b3c2d379bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 16:55:02 -0300 Subject: [PATCH 0443/5711] edac: Get rid of the old kobj's from the edac mc code Now that al users for the old kobj raw access are gone, we can get rid of the legacy kobj-based structures and data. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Cc: Michal Marek Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc.c | 1 - drivers/edac/i5000_edac.c | 3 --- drivers/edac/i82875p_edac.c | 4 ---- include/linux/edac.h | 30 ------------------------------ 4 files changed, 38 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 61ae34643b49..4a6fdc03740e 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -372,7 +372,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, } mci->op_state = OP_ALLOC; - INIT_LIST_HEAD(&mci->grp_kobj_list); /* at this point, the root kobj is valid, and in order to * 'free' the object, then the function: diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index a69245ad5f32..a7da4c7ad7fa 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1406,7 +1406,6 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - kobject_get(&mci->edac_mci_kobj); debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1479,7 +1478,6 @@ fail1: i5000_put_devices(mci); fail0: - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); return -ENODEV; } @@ -1525,7 +1523,6 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) /* retrieve references to resources, and free those resources */ i5000_put_devices(mci); - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); } diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 1cc682d0678d..a47c6b25db31 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -426,9 +426,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - /* Keeps mci available after edac_mc_del_mc() till edac_mc_free() */ - kobject_get(&mci->edac_mci_kobj); - debugf3("%s(): init mci\n", __func__); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; @@ -471,7 +468,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) return 0; fail1: - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); fail0: diff --git a/include/linux/edac.h b/include/linux/edac.h index a2b0b6fc002c..8a2da47daa47 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -457,7 +457,6 @@ struct dimm_info { /* Memory location data */ unsigned location[EDAC_MAX_LAYERS]; - struct kobject kobj; /* sysfs kobject for this csrow */ struct mem_ctl_info *mci; /* the parent */ u32 grain; /* granularity of reported error in bytes */ @@ -511,34 +510,11 @@ struct csrow_info { struct mem_ctl_info *mci; /* the parent */ - struct kobject kobj; /* sysfs kobject for this csrow */ - /* channel information for this csrow */ u32 nr_channels; struct rank_info *channels; }; -struct mcidev_sysfs_group { - const char *name; /* group name */ - const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ -}; - -/* mcidev_sysfs_attribute structure - * used for driver sysfs attributes and in mem_ctl_info - * sysfs top level entries - */ -struct mcidev_sysfs_attribute { - /* It should use either attr or grp */ - struct attribute attr; - const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ - - /* Ops for show/store values at the attribute - not used on group */ - ssize_t (*show)(struct mem_ctl_info *, char *); - ssize_t (*store)(struct mem_ctl_info *, const char *, size_t); - - void *priv; -}; - /* * struct errcount_attribute - used to store the several error counts */ @@ -641,12 +617,6 @@ struct mem_ctl_info { struct completion complete; - /* edac sysfs device control */ - struct kobject edac_mci_kobj; - - /* list for all grp instances within a mc */ - struct list_head grp_kobj_list; - /* Additional top controller level attributes, but specified * by the low level driver. * -- GitLab From 199747106934c4dc9cf90d37538f989e29420833 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 17:06:53 -0300 Subject: [PATCH 0444/5711] edac: add a new per-dimm API and make the old per-virtual-rank API obsolete The old EDAC API is broken. It only works fine for systems manufatured before 2005 and for AMD 64. The reason is that it forces all memory controller drivers to discover rank info. Also, it doesn't allow grouping the several ranks into a DIMM. So, what almost all modern drivers do is to create a fake virtual-rank information, and use it to cheat the EDAC core to accept the driver. While this works if the user has enough time to discover what DIMM slot corresponds to each "virtual-rank" information, it prevents EDAC usage for users with less available time. It also makes life hard for vendors that may want to provide a table with their motherboards to the userspace tool (edac-utils) as each driver has its own logic for the virtual mapping. So, the old API should be removed, in favor of a more flexible API that allows newer drivers to not lie to the EDAC core. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Cc: Borislav Petkov Cc: Randy Dunlap Cc: Josh Boyer Cc: Hui Wang Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/Kconfig | 8 ++ drivers/edac/edac_mc_sysfs.c | 165 ++++++++++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 1 deletion(-) diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index fdffa1beca17..3b3f84ff351f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -31,6 +31,14 @@ if EDAC comment "Reporting subsystems" +config EDAC_LEGACY_SYSFS + bool "EDAC legacy sysfs" + default y + help + Enable the compatibility sysfs nodes. + Use 'Y' if your edac utilities aren't ported to work with the newer + structures. + config EDAC_DEBUG bool "Debugging" help diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 7002c9cab999..86da1767f86e 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -130,6 +130,7 @@ static const char *edac_caps[] = { [EDAC_S16ECD16ED] = "S16ECD16ED" }; +#ifdef CONFIG_EDAC_LEGACY_SYSFS /* * EDAC sysfs CSROW data structures and methods */ @@ -443,6 +444,159 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) device_del(&mci->csrows[i].dev); } } +#endif + +/* + * Per-dimm (or per-rank) devices + */ + +#define to_dimm(k) container_of(k, struct dimm_info, dev) + +/* show/store functions for DIMM Label attributes */ +static ssize_t dimmdev_location_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + struct mem_ctl_info *mci = dimm->mci; + int i; + char *p = data; + + for (i = 0; i < mci->n_layers; i++) { + p += sprintf(p, "%s %d ", + edac_layer_name[mci->layers[i].type], + dimm->location[i]); + } + + return p - data; +} + +static ssize_t dimmdev_label_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + /* if field has not been initialized, there is nothing to send */ + if (!dimm->label[0]) + return 0; + + return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", dimm->label); +} + +static ssize_t dimmdev_label_store(struct device *dev, + struct device_attribute *mattr, + const char *data, + size_t count) +{ + struct dimm_info *dimm = to_dimm(dev); + + ssize_t max_size = 0; + + max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1); + strncpy(dimm->label, data, max_size); + dimm->label[max_size] = '\0'; + + return max_size; +} + +static ssize_t dimmdev_size_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%u\n", PAGES_TO_MiB(dimm->nr_pages)); +} + +static ssize_t dimmdev_mem_type_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", mem_types[dimm->mtype]); +} + +static ssize_t dimmdev_dev_type_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", dev_types[dimm->dtype]); +} + +static ssize_t dimmdev_edac_mode_show(struct device *dev, + struct device_attribute *mattr, + char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", edac_caps[dimm->edac_mode]); +} + +/* dimm/rank attribute files */ +static DEVICE_ATTR(dimm_label, S_IRUGO | S_IWUSR, + dimmdev_label_show, dimmdev_label_store); +static DEVICE_ATTR(dimm_location, S_IRUGO, dimmdev_location_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, dimmdev_size_show, NULL); +static DEVICE_ATTR(dimm_mem_type, S_IRUGO, dimmdev_mem_type_show, NULL); +static DEVICE_ATTR(dimm_dev_type, S_IRUGO, dimmdev_dev_type_show, NULL); +static DEVICE_ATTR(dimm_edac_mode, S_IRUGO, dimmdev_edac_mode_show, NULL); + +/* attributes of the dimm/rank object */ +static struct attribute *dimm_attrs[] = { + &dev_attr_dimm_label.attr, + &dev_attr_dimm_location.attr, + &dev_attr_size.attr, + &dev_attr_dimm_mem_type.attr, + &dev_attr_dimm_dev_type.attr, + &dev_attr_dimm_edac_mode.attr, + NULL, +}; + +static struct attribute_group dimm_attr_grp = { + .attrs = dimm_attrs, +}; + +static const struct attribute_group *dimm_attr_groups[] = { + &dimm_attr_grp, + NULL +}; + +static void dimm_attr_release(struct device *device) +{ + debugf1("Releasing dimm device %s\n", dev_name(device)); +} + +static struct device_type dimm_attr_type = { + .groups = dimm_attr_groups, + .release = dimm_attr_release, +}; + +/* Create a DIMM object under specifed memory controller device */ +static int edac_create_dimm_object(struct mem_ctl_info *mci, + struct dimm_info *dimm, + int index) +{ + int err; + dimm->mci = mci; + + dimm->dev.type = &dimm_attr_type; + dimm->dev.bus = &mci->bus; + device_initialize(&dimm->dev); + + dimm->dev.parent = &mci->dev; + if (mci->mem_is_per_rank) + dev_set_name(&dimm->dev, "rank%d", index); + else + dev_set_name(&dimm->dev, "dimm%d", index); + dev_set_drvdata(&dimm->dev, dimm); + pm_runtime_forbid(&mci->dev); + + err = device_add(&dimm->dev); + + debugf0("%s(): creating rank/dimm device %s\n", __func__, + dev_name(&dimm->dev)); + + return err; +} /* * Memory controller device @@ -660,7 +814,6 @@ static struct device_type mci_attr_type = { .release = mci_attr_release, }; - /* * Create a new Memory Controller kobject instance, * mc under the 'mc' directory @@ -725,11 +878,19 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) printk(KERN_CONT "\n"); } #endif + err = edac_create_dimm_object(mci, dimm, i); + if (err) { + debugf1("%s() failure: create dimm %d obj\n", + __func__, i); + goto fail; + } } +#ifdef CONFIG_EDAC_LEGACY_SYSFS err = edac_create_csrow_objects(mci); if (err < 0) goto fail; +#endif return 0; @@ -757,7 +918,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) debugf0("%s()\n", __func__); +#ifdef CONFIG_EDAC_LEGACY_SYSFS edac_delete_csrow_objects(mci); +#endif for (i = 0; i < mci->tot_dimms; i++) { struct dimm_info *dimm = &mci->dimms[i]; -- GitLab From 8ad6c78a69ac5c74e8f4e8c78cdb86772face433 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 21 Mar 2012 17:13:24 -0300 Subject: [PATCH 0445/5711] edac: add a sysfs node to report the maximum location for the system The userspace tools need to know what's the maximum location on each system, as it helps to create nice maps showing how the memory was filled at the system. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc_sysfs.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 86da1767f86e..87fb396bc550 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -766,6 +766,23 @@ static ssize_t mci_size_mb_show(struct device *dev, return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); } +static ssize_t mci_max_location_show(struct device *dev, + struct device_attribute *mattr, + char *data) +{ + struct mem_ctl_info *mci = to_mci(dev); + int i; + char *p = data; + + for (i = 0; i < mci->n_layers; i++) { + p += sprintf(p, "%s %d ", + edac_layer_name[mci->layers[i].type], + mci->layers[i].size - 1); + } + + return p - data; +} + /* default Control file */ DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); @@ -777,6 +794,7 @@ DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); +DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL); /* memory scrubber attribute file */ DEVICE_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, @@ -792,6 +810,7 @@ static struct attribute *mci_attrs[] = { &dev_attr_ue_count.attr, &dev_attr_ce_count.attr, &dev_attr_sdram_scrub_rate.attr, + &dev_attr_max_location.attr, NULL }; -- GitLab From 452a6bf955ee1842361742833e40e046287308f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 26 Mar 2012 09:35:11 -0300 Subject: [PATCH 0446/5711] edac: Add debufs nodes to allow doing fake error inject Sometimes, it is useful to have a mechanism that generates fake errors, in order to test the EDAC core code, and the userspace tools. Provide such mechanism by adding a few debugfs nodes. Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc_sysfs.c | 87 ++++++++++++++++++++++++++++++++++++ include/linux/edac.h | 7 +++ 2 files changed, 94 insertions(+) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 87fb396bc550..daa418b61525 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "edac_core.h" #include "edac_module.h" @@ -783,6 +784,47 @@ static ssize_t mci_max_location_show(struct device *dev, return p - data; } +#ifdef CONFIG_EDAC_DEBUG +static ssize_t edac_fake_inject_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct device *dev = file->private_data; + struct mem_ctl_info *mci = to_mci(dev); + static enum hw_event_mc_err_type type; + + type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED + : HW_EVENT_ERR_CORRECTED; + + printk(KERN_DEBUG + "Generating a %s fake error to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n", + (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE", + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2] + ); + edac_mc_handle_error(type, mci, 0, 0, 0, + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2], + "FAKE ERROR", "for EDAC testing only", NULL); + + return count; +} + +static int debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static const struct file_operations debug_fake_inject_fops = { + .open = debugfs_open, + .write = edac_fake_inject_write, + .llseek = generic_file_llseek, +}; +#endif + /* default Control file */ DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); @@ -833,6 +875,45 @@ static struct device_type mci_attr_type = { .release = mci_attr_release, }; +#ifdef CONFIG_EDAC_DEBUG +int edac_create_debug_nodes(struct mem_ctl_info *mci) +{ + struct dentry *d, *parent; + char name[80]; + int i; + + d = debugfs_create_dir(mci->dev.kobj.name, mci->debugfs); + if (!d) + return -ENOMEM; + parent = d; + + for (i = 0; i < mci->n_layers; i++) { + sprintf(name, "fake_inject_%s", + edac_layer_name[mci->layers[i].type]); + d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_layer[i]); + if (!d) + goto nomem; + } + + d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_ue); + if (!d) + goto nomem; + + d = debugfs_create_file("fake_inject", S_IWUSR, parent, + &mci->dev, + &debug_fake_inject_fops); + if (!d) + goto nomem; + + return 0; +nomem: + debugfs_remove(mci->debugfs); + return -ENOMEM; +} +#endif + /* * Create a new Memory Controller kobject instance, * mc under the 'mc' directory @@ -911,6 +992,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) goto fail; #endif +#ifdef CONFIG_EDAC_DEBUG + edac_create_debug_nodes(mci); +#endif return 0; fail: @@ -937,6 +1021,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) debugf0("%s()\n", __func__); +#ifdef CONFIG_EDAC_DEBUG + debugfs_remove(mci->debugfs); +#endif #ifdef CONFIG_EDAC_LEGACY_SYSFS edac_delete_csrow_objects(mci); #endif diff --git a/include/linux/edac.h b/include/linux/edac.h index 8a2da47daa47..64ae0c5cf62e 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -17,6 +17,7 @@ #include #include #include +#include struct device; @@ -634,6 +635,12 @@ struct mem_ctl_info { /* the internal state of this controller instance */ int op_state; + +#ifdef CONFIG_EDAC_DEBUG + struct dentry *debugfs; + u8 fake_inject_layer[EDAC_MAX_LAYERS]; + u32 fake_inject_ue; +#endif }; #endif -- GitLab From fd63312dfe70b8279618b4d77dc951b6e309ffa2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 28 Mar 2012 19:37:59 -0300 Subject: [PATCH 0447/5711] edac: Move grain/dtype/edac_type calculus to be out of channel loop The 3e7bddc changeset (edac: move dimm properties to struct memset_info) moved the calculus inside a loop. However, at those stuff are common to all channels, on several drivers, it is better to put the calculus outside the loop, to optimize the code. Reported-by: Aristeu Rozanski Filho Reviewed-by: Aristeu Rozanski Cc: Mark Gross Cc: Doug Thompson Cc: Dmitry Eremin-Solenikov Cc: Benjamin Herrenschmidt Cc: Michal Marek Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/cpc925_edac.c | 54 +++++++++++++++++++------------------- drivers/edac/e752x_edac.c | 31 +++++++++++----------- drivers/edac/e7xxx_edac.c | 32 +++++++++++----------- 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 9488723f8138..3510aa446297 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -330,8 +330,9 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) struct cpc925_mc_pdata *pdata = mci->pvt_info; struct csrow_info *csrow; struct dimm_info *dimm; + enum dev_type dtype; int index, j; - u32 mbmr, mbbar, bba; + u32 mbmr, mbbar, bba, grain; unsigned long row_size, nr_pages, last_nr_pages = 0; get_total_mem(pdata); @@ -355,37 +356,36 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) csrow->last_page = csrow->first_page + nr_pages - 1; last_nr_pages = csrow->last_page + 1; + switch (csrow->nr_channels) { + case 1: /* Single channel */ + grain = 32; /* four-beat burst of 32 bytes */ + break; + case 2: /* Dual channel */ + default: + grain = 64; /* four-beat burst of 64 bytes */ + break; + } + switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { + case 6: /* 0110, no way to differentiate X8 VS X16 */ + case 5: /* 0101 */ + case 8: /* 1000 */ + dtype = DEV_X16; + break; + case 7: /* 0111 */ + case 9: /* 1001 */ + dtype = DEV_X8; + break; + default: + dtype = DEV_UNKNOWN; + break; + } for (j = 0; j < csrow->nr_channels; j++) { dimm = csrow->channels[j].dimm; - dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->mtype = MEM_RDDR; dimm->edac_mode = EDAC_SECDED; - - switch (csrow->nr_channels) { - case 1: /* Single channel */ - dimm->grain = 32; /* four-beat burst of 32 bytes */ - break; - case 2: /* Dual channel */ - default: - dimm->grain = 64; /* four-beat burst of 64 bytes */ - break; - } - - switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { - case 6: /* 0110, no way to differentiate X8 VS X16 */ - case 5: /* 0101 */ - case 8: /* 1000 */ - dimm->dtype = DEV_X16; - break; - case 7: /* 0111 */ - case 9: /* 1001 */ - dimm->dtype = DEV_X8; - break; - default: - dimm->dtype = DEV_UNKNOWN; - break; - } + dimm->grain = grain; + dimm->dtype = dtype; } } } diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index d75660634b43..d1142ed8bd88 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1069,6 +1069,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, u16 ddrcsr) { struct csrow_info *csrow; + enum edac_type edac_mode; unsigned long last_cumul_size; int index, mem_dev, drc_chan; int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ @@ -1111,6 +1112,20 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + edac_mode = EDAC_NONE; for (i = 0; i < csrow->nr_channels; i++) { struct dimm_info *dimm = csrow->channels[i].dimm; @@ -1119,21 +1134,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; - - /* - * if single channel or x8 devices then SECDED - * if dual channel and x4 then S4ECD4ED - */ - if (drc_ddim) { - if (drc_chan && mem_dev) { - dimm->edac_mode = EDAC_S4ECD4ED; - mci->edac_cap |= EDAC_FLAG_S4ECD4ED; - } else { - dimm->edac_mode = EDAC_SECDED; - mci->edac_cap |= EDAC_FLAG_SECDED; - } - } else - dimm->edac_mode = EDAC_NONE; + dimm->edac_mode = edac_mode; } } } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index b111266dadf3..bab31aab983d 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -362,6 +362,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, int drc_chan, drc_drbg, drc_ddim, mem_dev; struct csrow_info *csrow; struct dimm_info *dimm; + enum edac_type edac_mode; pci_read_config_dword(pdev, E7XXX_DRA, &dra); drc_chan = dual_channel_active(drc, dev_idx); @@ -392,6 +393,21 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + edac_mode = EDAC_NONE; + for (j = 0; j < drc_chan + 1; j++) { dimm = csrow->channels[j].dimm; @@ -399,21 +415,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; - - /* - * if single channel or x8 devices then SECDED - * if dual channel and x4 then S4ECD4ED - */ - if (drc_ddim) { - if (drc_chan && mem_dev) { - dimm->edac_mode = EDAC_S4ECD4ED; - mci->edac_cap |= EDAC_FLAG_S4ECD4ED; - } else { - dimm->edac_mode = EDAC_SECDED; - mci->edac_cap |= EDAC_FLAG_SECDED; - } - } else - dimm->edac_mode = EDAC_NONE; + dimm->edac_mode = edac_mode; } } } -- GitLab From e39f4ea9b01f137f9e6fa631f3e9088fb9175e91 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Mar 2012 12:20:22 -0300 Subject: [PATCH 0448/5711] edac: Only expose csrows/channels on legacy API if they're populated This patch actually fixes a bug with the legacy API, where, at the same csrow, some channels may have different DIMMs. This can happen on FB-DIMM/RAMBUS and modern Intel controllers. This is the case, for example, of Nehalem machines: $ ./edac-ctl --layout +-----------------------------------+ | mc0 | | channel0 | channel1 | channel2 | -------+-----------------------------------+ slot2: | 0 MB | 0 MB | 0 MB | slot1: | 1024 MB | 0 MB | 0 MB | slot0: | 1024 MB | 1024 MB | 1024 MB | -------+-----------------------------------+ Before this patch, non-filled memories were shown. Now, only what's filled is there: grep . /sys/devices/system/edac/mc/mc0/csrow*/ch?* /sys/devices/system/edac/mc/mc0/csrow0/ch0_ce_count:0 /sys/devices/system/edac/mc/mc0/csrow0/ch0_dimm_label:CPU#0Channel#0_DIMM#0 /sys/devices/system/edac/mc/mc0/csrow0/ch1_ce_count:0 /sys/devices/system/edac/mc/mc0/csrow0/ch1_dimm_label:CPU#0Channel#0_DIMM#1 /sys/devices/system/edac/mc/mc0/csrow1/ch0_ce_count:0 /sys/devices/system/edac/mc/mc0/csrow1/ch0_dimm_label:CPU#0Channel#1_DIMM#0 /sys/devices/system/edac/mc/mc0/csrow2/ch0_ce_count:0 /sys/devices/system/edac/mc/mc0/csrow2/ch0_dimm_label:CPU#0Channel#2_DIMM#0 Thanks-to: Aristeu Rozanski Filho Reviewed-by: Aristeu Rozanski Cc: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc_sysfs.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index daa418b61525..0f671907c90b 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -347,6 +347,16 @@ static struct device_attribute *dynamic_csrow_ce_count_attr[] = { &dev_attr_legacy_ch5_ce_count.attr }; +static inline int nr_pages_per_csrow(struct csrow_info *csrow) +{ + int chan, nr_pages = 0; + + for (chan = 0; chan < csrow->nr_channels; chan++) + nr_pages += csrow->channels[chan].dimm->nr_pages; + + return nr_pages; +} + /* Create a CSROW object under specifed edac_mc_device */ static int edac_create_csrow_object(struct mem_ctl_info *mci, struct csrow_info *csrow, int index) @@ -371,6 +381,9 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, return err; for (chan = 0; chan < csrow->nr_channels; chan++) { + /* Only expose populated DIMMs */ + if (!csrow->channels[chan].dimm->nr_pages) + continue; err = device_create_file(&csrow->dev, dynamic_csrow_dimm_attr[chan]); if (err < 0) @@ -405,6 +418,9 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) struct csrow_info *csrow; for (i = 0; i < mci->nr_csrows; i++) { + csrow = &mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; err = edac_create_csrow_object(mci, &mci->csrows[i], i); if (err < 0) goto error; @@ -414,7 +430,11 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) error: for (--i; i >= 0; i--) { csrow = &mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + if (!csrow->channels[chan].dimm->nr_pages) + continue; device_remove_file(&csrow->dev, dynamic_csrow_dimm_attr[chan]); device_remove_file(&csrow->dev, @@ -433,7 +453,11 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) for (i = mci->nr_csrows - 1; i >= 0; i--) { csrow = &mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + if (!csrow->channels[chan].dimm->nr_pages) + continue; debugf1("Removing csrow %d channel %d sysfs nodes\n", i, chan); device_remove_file(&csrow->dev, -- GitLab From de3910eb79ac8c0f29a11224661c0ebaaf813039 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Apr 2012 15:05:43 -0300 Subject: [PATCH 0449/5711] edac: change the mem allocation scheme to make Documentation/kobject.txt happy Kernel kobjects have rigid rules: each container object should be dynamically allocated, and can't be allocated into a single kmalloc. EDAC never obeyed this rule: it has a single malloc function that allocates all needed data into a single kzalloc. As this is not accepted anymore, change the allocation schema of the EDAC *_info structs to enforce this Kernel standard. Acked-by: Chris Metcalf Cc: Aristeu Rozanski Cc: Doug Thompson Cc: Greg K H Cc: Borislav Petkov Cc: Mark Gross Cc: Tim Small Cc: Ranganathan Desikan Cc: "Arvind R." Cc: Olof Johansson Cc: Egor Martovetsky Cc: Michal Marek Cc: Jiri Kosina Cc: Dmitry Eremin-Solenikov Cc: Benjamin Herrenschmidt Cc: Hitoshi Mitake Cc: Andrew Morton Cc: Shaohui Xie Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 10 +-- drivers/edac/amd76x_edac.c | 8 +-- drivers/edac/cell_edac.c | 8 +-- drivers/edac/cpc925_edac.c | 8 +-- drivers/edac/e752x_edac.c | 4 +- drivers/edac/e7xxx_edac.c | 4 +- drivers/edac/edac_mc.c | 107 ++++++++++++++++++---------- drivers/edac/edac_mc_sysfs.c | 126 +++++++++++++++++++-------------- drivers/edac/i3000_edac.c | 6 +- drivers/edac/i3200_edac.c | 4 +- drivers/edac/i5400_edac.c | 6 +- drivers/edac/i82443bxgx_edac.c | 4 +- drivers/edac/i82860_edac.c | 6 +- drivers/edac/i82875p_edac.c | 6 +- drivers/edac/i82975x_edac.c | 10 +-- drivers/edac/mpc85xx_edac.c | 6 +- drivers/edac/mv64x60_edac.c | 4 +- drivers/edac/pasemi_edac.c | 8 +-- drivers/edac/r82600_edac.c | 4 +- drivers/edac/tile_edac.c | 4 +- drivers/edac/x38_edac.c | 4 +- include/linux/edac.h | 59 ++++++++++----- 22 files changed, 242 insertions(+), 164 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9905834b560f..9fbced7f65ee 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2205,6 +2205,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) static int init_csrows(struct mem_ctl_info *mci) { struct csrow_info *csrow; + struct dimm_info *dimm; struct amd64_pvt *pvt = mci->pvt_info; u64 base, mask; u32 val; @@ -2222,7 +2223,7 @@ static int init_csrows(struct mem_ctl_info *mci) !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); for_each_chip_select(i, 0, pvt) { - csrow = &mci->csrows[i]; + csrow = mci->csrows[i]; if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) { debugf1("----CSROW %d EMPTY for node %d\n", i, @@ -2257,9 +2258,10 @@ static int init_csrows(struct mem_ctl_info *mci) edac_mode = EDAC_NONE; for (j = 0; j < pvt->channel_count; j++) { - csrow->channels[j].dimm->mtype = mtype; - csrow->channels[j].dimm->edac_mode = edac_mode; - csrow->channels[j].dimm->nr_pages = nr_pages; + dimm = csrow->channels[j]->dimm; + dimm->mtype = mtype; + dimm->edac_mode = edac_mode; + dimm->nr_pages = nr_pages; } } diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 7439786f3bef..a0c9f82875cd 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -146,7 +146,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = (info->ecc_mode_status >> 4) & 0xf; edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - mci->csrows[row].first_page, 0, 0, + mci->csrows[row]->first_page, 0, 0, row, 0, -1, mci->ctl_name, "", NULL); } @@ -161,7 +161,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = info->ecc_mode_status & 0xf; edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - mci->csrows[row].first_page, 0, 0, + mci->csrows[row]->first_page, 0, 0, row, 0, -1, mci->ctl_name, "", NULL); } @@ -194,8 +194,8 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, int index; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; /* find the DRAM Chip Select Base address and mask */ pci_read_config_dword(pdev, diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 2e5b95374dc6..478d8ee434df 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -33,7 +33,7 @@ struct cell_edac_priv static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) { struct cell_edac_priv *priv = mci->pvt_info; - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; unsigned long address, pfn, offset, syndrome; dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", @@ -56,7 +56,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) { struct cell_edac_priv *priv = mci->pvt_info; - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; unsigned long address, pfn, offset; dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", @@ -126,7 +126,7 @@ static void cell_edac_check(struct mem_ctl_info *mci) static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) { - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; struct dimm_info *dimm; struct cell_edac_priv *priv = mci->pvt_info; struct device_node *np; @@ -150,7 +150,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) csrow->last_page = csrow->first_page + nr_pages - 1; for (j = 0; j < csrow->nr_channels; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->mtype = MEM_XDR; dimm->edac_mode = EDAC_SECDED; dimm->nr_pages = nr_pages / csrow->nr_channels; diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 3510aa446297..534491d67159 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -348,7 +348,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) if (bba == 0) continue; /* not populated */ - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; row_size = bba * (1UL << 28); /* 256M */ csrow->first_page = last_nr_pages; @@ -380,7 +380,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) break; } for (j = 0; j < csrow->nr_channels; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->mtype = MEM_RDDR; dimm->edac_mode = EDAC_SECDED; @@ -463,7 +463,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, *csrow = rank; #ifdef CONFIG_EDAC_DEBUG - if (mci->csrows[rank].first_page == 0) { + if (mci->csrows[rank]->first_page == 0) { cpc925_mc_printk(mci, KERN_ERR, "ECC occurs in a " "non-populated csrow, broken hardware?\n"); return; @@ -471,7 +471,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, #endif /* Revert csrow number */ - pa = mci->csrows[rank].first_page << PAGE_SHIFT; + pa = mci->csrows[rank]->first_page << PAGE_SHIFT; /* Revert column address */ col += bcnt; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index d1142ed8bd88..7cde7f1aafb7 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1096,7 +1096,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { /* mem_dev 0=x8, 1=x4 */ mem_dev = (dra >> (index * 4 + 2)) & 0x3; - csrow = &mci->csrows[remap_csrow_index(mci, index)]; + csrow = mci->csrows[remap_csrow_index(mci, index)]; mem_dev = (mem_dev == 2); pci_read_config_byte(pdev, E752X_DRB + index, &value); @@ -1127,7 +1127,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, } else edac_mode = EDAC_NONE; for (i = 0; i < csrow->nr_channels; i++) { - struct dimm_info *dimm = csrow->channels[i].dimm; + struct dimm_info *dimm = csrow->channels[i]->dimm; debugf3("Initializing rank at (%i,%i)\n", index, i); dimm->nr_pages = nr_pages / csrow->nr_channels; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index bab31aab983d..c6c0ebaca371 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -378,7 +378,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, for (index = 0; index < mci->nr_csrows; index++) { /* mem_dev 0=x8, 1=x4 */ mem_dev = (dra >> (index * 4 + 3)) & 0x1; - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; pci_read_config_byte(pdev, E7XXX_DRB + index, &value); /* convert a 64 or 32 MiB DRB to a page size. */ @@ -409,7 +409,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, edac_mode = EDAC_NONE; for (j = 0; j < drc_chan + 1; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / (drc_chan + 1); dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4a6fdc03740e..db2ba31ba2b1 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -210,15 +210,15 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, { struct mem_ctl_info *mci; struct edac_mc_layer *layer; - struct csrow_info *csi, *csr; - struct rank_info *chi, *chp, *chan; + struct csrow_info *csr; + struct rank_info *chan; struct dimm_info *dimm; u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS]; unsigned pos[EDAC_MAX_LAYERS]; unsigned size, tot_dimms = 1, count = 1; unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0; void *pvt, *p, *ptr = NULL; - int i, j, row, chn, n, len; + int i, j, row, chn, n, len, off; bool per_rank = false; BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0); @@ -244,9 +244,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, */ mci = edac_align_ptr(&ptr, sizeof(*mci), 1); layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers); - csi = edac_align_ptr(&ptr, sizeof(*csi), tot_csrows); - chi = edac_align_ptr(&ptr, sizeof(*chi), tot_csrows * tot_channels); - dimm = edac_align_ptr(&ptr, sizeof(*dimm), tot_dimms); for (i = 0; i < n_layers; i++) { count *= layers[i].size; debugf4("%s: errcount layer %d size %d\n", __func__, i, count); @@ -264,6 +261,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, tot_dimms, per_rank ? "ranks" : "dimms", tot_csrows * tot_channels); + mci = kzalloc(size, GFP_KERNEL); if (mci == NULL) return NULL; @@ -272,9 +270,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, * rather than an imaginary chunk of memory located at address 0. */ layer = (struct edac_mc_layer *)(((char *)mci) + ((unsigned long)layer)); - csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi)); - chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi)); - dimm = (struct dimm_info *)(((char *)mci) + ((unsigned long)dimm)); for (i = 0; i < n_layers; i++) { mci->ce_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ce_per_layer[i])); mci->ue_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ue_per_layer[i])); @@ -283,8 +278,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* setup index and various internal pointers */ mci->mc_idx = mc_num; - mci->csrows = csi; - mci->dimms = dimm; mci->tot_dimms = tot_dimms; mci->pvt_info = pvt; mci->n_layers = n_layers; @@ -295,39 +288,60 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->mem_is_per_rank = per_rank; /* - * Fill the csrow struct + * Alocate and fill the csrow/channels structs */ + mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); + if (!mci->csrows) + goto error; for (row = 0; row < tot_csrows; row++) { - csr = &csi[row]; + csr = kzalloc(sizeof(**mci->csrows), GFP_KERNEL); + if (!csr) + goto error; + mci->csrows[row] = csr; csr->csrow_idx = row; csr->mci = mci; csr->nr_channels = tot_channels; - chp = &chi[row * tot_channels]; - csr->channels = chp; + csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, + GFP_KERNEL); + if (!csr->channels) + goto error; for (chn = 0; chn < tot_channels; chn++) { - chan = &chp[chn]; + chan = kzalloc(sizeof(**csr->channels), GFP_KERNEL); + if (!chan) + goto error; + csr->channels[chn] = chan; chan->chan_idx = chn; chan->csrow = csr; } } /* - * Fill the dimm struct + * Allocate and fill the dimm structs */ + mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); + if (!mci->dimms) + goto error; + memset(&pos, 0, sizeof(pos)); row = 0; chn = 0; debugf4("%s: initializing %d %s\n", __func__, tot_dimms, per_rank ? "ranks" : "dimms"); for (i = 0; i < tot_dimms; i++) { - chan = &csi[row].channels[chn]; - dimm = EDAC_DIMM_PTR(layer, mci->dimms, n_layers, - pos[0], pos[1], pos[2]); + chan = mci->csrows[row]->channels[chn]; + off = EDAC_DIMM_OFF(layer, n_layers, pos[0], pos[1], pos[2]); + if (off < 0 || off >= tot_dimms) { + edac_mc_printk(mci, KERN_ERR, "EDAC core bug: EDAC_DIMM_OFF is trying to do an illegal data access\n"); + goto error; + } + + dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL); + mci->dimms[off] = dimm; dimm->mci = mci; - debugf2("%s: %d: %s%zd (%d:%d:%d): row %d, chan %d\n", __func__, - i, per_rank ? "rank" : "dimm", (dimm - mci->dimms), + debugf2("%s: %d: %s%i (%d:%d:%d): row %d, chan %d\n", __func__, + i, per_rank ? "rank" : "dimm", off, pos[0], pos[1], pos[2], row, chn); /* @@ -381,6 +395,28 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, */ return mci; + +error: + if (mci->dimms) { + for (i = 0; i < tot_dimms; i++) + kfree(mci->dimms[i]); + kfree(mci->dimms); + } + if (mci->csrows) { + for (chn = 0; chn < tot_channels; chn++) { + csr = mci->csrows[chn]; + if (csr) { + for (chn = 0; chn < tot_channels; chn++) + kfree(csr->channels[chn]); + kfree(csr); + } + kfree(mci->csrows[i]); + } + kfree(mci->csrows); + } + kfree(mci); + + return NULL; } EXPORT_SYMBOL_GPL(edac_mc_alloc); @@ -393,10 +429,8 @@ void edac_mc_free(struct mem_ctl_info *mci) { debugf1("%s()\n", __func__); + /* the mci instance is freed here, when the sysfs object is dropped */ edac_unregister_sysfs(mci); - - /* free the mci instance memory here */ - kfree(mci); } EXPORT_SYMBOL_GPL(edac_mc_free); @@ -668,13 +702,12 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) for (i = 0; i < mci->nr_csrows; i++) { int j; - edac_mc_dump_csrow(&mci->csrows[i]); - for (j = 0; j < mci->csrows[i].nr_channels; j++) - edac_mc_dump_channel(&mci->csrows[i]. - channels[j]); + edac_mc_dump_csrow(mci->csrows[i]); + for (j = 0; j < mci->csrows[i]->nr_channels; j++) + edac_mc_dump_channel(mci->csrows[i]->channels[j]); } for (i = 0; i < mci->tot_dimms; i++) - edac_mc_dump_dimm(&mci->dimms[i]); + edac_mc_dump_dimm(mci->dimms[i]); } #endif mutex_lock(&mem_ctls_mutex); @@ -793,17 +826,17 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, /* FIXME - should return -1 */ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { - struct csrow_info *csrows = mci->csrows; + struct csrow_info **csrows = mci->csrows; int row, i, j, n; debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { - struct csrow_info *csrow = &csrows[i]; + struct csrow_info *csrow = csrows[i]; n = 0; for (j = 0; j < csrow->nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; n += dimm->nr_pages; } if (n == 0) @@ -1062,7 +1095,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, p = label; *p = '\0'; for (i = 0; i < mci->tot_dimms; i++) { - struct dimm_info *dimm = &mci->dimms[i]; + struct dimm_info *dimm = mci->dimms[i]; if (top_layer >= 0 && top_layer != dimm->location[0]) continue; @@ -1120,13 +1153,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, strcpy(label, "unknown memory"); if (type == HW_EVENT_ERR_CORRECTED) { if (row >= 0) { - mci->csrows[row].ce_count++; + mci->csrows[row]->ce_count++; if (chan >= 0) - mci->csrows[row].channels[chan].ce_count++; + mci->csrows[row]->channels[chan]->ce_count++; } } else if (row >= 0) - mci->csrows[row].ue_count++; + mci->csrows[row]->ue_count++; } /* Fill the RAM location data */ diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 0f671907c90b..87b8d7d6385f 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -82,7 +82,7 @@ module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int, &edac_mc_poll_msec, 0644); MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); -static struct device mci_pdev; +static struct device *mci_pdev; /* * various constants for Memory Controllers @@ -181,7 +181,7 @@ static ssize_t csrow_size_show(struct device *dev, u32 nr_pages = 0; for (i = 0; i < csrow->nr_channels; i++) - nr_pages += csrow->channels[i].dimm->nr_pages; + nr_pages += csrow->channels[i]->dimm->nr_pages; return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); } @@ -190,7 +190,7 @@ static ssize_t csrow_mem_type_show(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); - return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]); + return sprintf(data, "%s\n", mem_types[csrow->channels[0]->dimm->mtype]); } static ssize_t csrow_dev_type_show(struct device *dev, @@ -198,7 +198,7 @@ static ssize_t csrow_dev_type_show(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); - return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]); + return sprintf(data, "%s\n", dev_types[csrow->channels[0]->dimm->dtype]); } static ssize_t csrow_edac_mode_show(struct device *dev, @@ -207,7 +207,7 @@ static ssize_t csrow_edac_mode_show(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); - return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]); + return sprintf(data, "%s\n", edac_caps[csrow->channels[0]->dimm->edac_mode]); } /* show/store functions for DIMM Label attributes */ @@ -217,7 +217,7 @@ static ssize_t channel_dimm_label_show(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); unsigned chan = to_channel(mattr); - struct rank_info *rank = &csrow->channels[chan]; + struct rank_info *rank = csrow->channels[chan]; /* if field has not been initialized, there is nothing to send */ if (!rank->dimm->label[0]) @@ -233,7 +233,7 @@ static ssize_t channel_dimm_label_store(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); unsigned chan = to_channel(mattr); - struct rank_info *rank = &csrow->channels[chan]; + struct rank_info *rank = csrow->channels[chan]; ssize_t max_size = 0; @@ -250,7 +250,7 @@ static ssize_t channel_ce_count_show(struct device *dev, { struct csrow_info *csrow = to_csrow(dev); unsigned chan = to_channel(mattr); - struct rank_info *rank = &csrow->channels[chan]; + struct rank_info *rank = csrow->channels[chan]; return sprintf(data, "%u\n", rank->ce_count); } @@ -283,9 +283,12 @@ static const struct attribute_group *csrow_attr_groups[] = { NULL }; -static void csrow_attr_release(struct device *device) +static void csrow_attr_release(struct device *dev) { - debugf1("Releasing csrow device %s\n", dev_name(device)); + struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); + + debugf1("Releasing csrow device %s\n", dev_name(dev)); + kfree(csrow); } static struct device_type csrow_attr_type = { @@ -352,7 +355,7 @@ static inline int nr_pages_per_csrow(struct csrow_info *csrow) int chan, nr_pages = 0; for (chan = 0; chan < csrow->nr_channels; chan++) - nr_pages += csrow->channels[chan].dimm->nr_pages; + nr_pages += csrow->channels[chan]->dimm->nr_pages; return nr_pages; } @@ -382,7 +385,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, for (chan = 0; chan < csrow->nr_channels; chan++) { /* Only expose populated DIMMs */ - if (!csrow->channels[chan].dimm->nr_pages) + if (!csrow->channels[chan]->dimm->nr_pages) continue; err = device_create_file(&csrow->dev, dynamic_csrow_dimm_attr[chan]); @@ -418,10 +421,10 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) struct csrow_info *csrow; for (i = 0; i < mci->nr_csrows; i++) { - csrow = &mci->csrows[i]; + csrow = mci->csrows[i]; if (!nr_pages_per_csrow(csrow)) continue; - err = edac_create_csrow_object(mci, &mci->csrows[i], i); + err = edac_create_csrow_object(mci, mci->csrows[i], i); if (err < 0) goto error; } @@ -429,18 +432,18 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) error: for (--i; i >= 0; i--) { - csrow = &mci->csrows[i]; + csrow = mci->csrows[i]; if (!nr_pages_per_csrow(csrow)) continue; for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { - if (!csrow->channels[chan].dimm->nr_pages) + if (!csrow->channels[chan]->dimm->nr_pages) continue; device_remove_file(&csrow->dev, dynamic_csrow_dimm_attr[chan]); device_remove_file(&csrow->dev, dynamic_csrow_ce_count_attr[chan]); } - put_device(&mci->csrows[i].dev); + put_device(&mci->csrows[i]->dev); } return err; @@ -452,11 +455,11 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) struct csrow_info *csrow; for (i = mci->nr_csrows - 1; i >= 0; i--) { - csrow = &mci->csrows[i]; + csrow = mci->csrows[i]; if (!nr_pages_per_csrow(csrow)) continue; for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { - if (!csrow->channels[chan].dimm->nr_pages) + if (!csrow->channels[chan]->dimm->nr_pages) continue; debugf1("Removing csrow %d channel %d sysfs nodes\n", i, chan); @@ -465,8 +468,8 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) device_remove_file(&csrow->dev, dynamic_csrow_ce_count_attr[chan]); } - put_device(&mci->csrows[i].dev); - device_del(&mci->csrows[i].dev); + put_device(&mci->csrows[i]->dev); + device_del(&mci->csrows[i]->dev); } } #endif @@ -585,9 +588,12 @@ static const struct attribute_group *dimm_attr_groups[] = { NULL }; -static void dimm_attr_release(struct device *device) +static void dimm_attr_release(struct device *dev) { - debugf1("Releasing dimm device %s\n", dev_name(device)); + struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); + + debugf1("Releasing dimm device %s\n", dev_name(dev)); + kfree(dimm); } static struct device_type dimm_attr_type = { @@ -641,13 +647,13 @@ static ssize_t mci_reset_counters_store(struct device *dev, mci->ce_noinfo_count = 0; for (row = 0; row < mci->nr_csrows; row++) { - struct csrow_info *ri = &mci->csrows[row]; + struct csrow_info *ri = mci->csrows[row]; ri->ue_count = 0; ri->ce_count = 0; for (chan = 0; chan < ri->nr_channels; chan++) - ri->channels[chan].ce_count = 0; + ri->channels[chan]->ce_count = 0; } cnt = 1; @@ -779,10 +785,10 @@ static ssize_t mci_size_mb_show(struct device *dev, int total_pages = 0, csrow_idx, j; for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { - struct csrow_info *csrow = &mci->csrows[csrow_idx]; + struct csrow_info *csrow = mci->csrows[csrow_idx]; for (j = 0; j < csrow->nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; total_pages += dimm->nr_pages; } @@ -889,9 +895,12 @@ static const struct attribute_group *mci_attr_groups[] = { NULL }; -static void mci_attr_release(struct device *device) +static void mci_attr_release(struct device *dev) { - debugf1("Releasing mci device %s\n", dev_name(device)); + struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); + + debugf1("Releasing csrow device %s\n", dev_name(dev)); + kfree(mci); } static struct device_type mci_attr_type = { @@ -950,29 +959,28 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) { int i, err; - debugf0("%s() idx=%d\n", __func__, mci->mc_idx); + /* + * The memory controller needs its own bus, in order to avoid + * namespace conflicts at /sys/bus/edac. + */ + mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); + if (!mci->bus.name) + return -ENOMEM; + debugf0("creating bus %s\n",mci->bus.name); + err = bus_register(&mci->bus); + if (err < 0) + return err; /* get the /sys/devices/system/edac subsys reference */ - mci->dev.type = &mci_attr_type; device_initialize(&mci->dev); - mci->dev.parent = &mci_pdev; + mci->dev.parent = mci_pdev; mci->dev.bus = &mci->bus; dev_set_name(&mci->dev, "mc%d", mci->mc_idx); dev_set_drvdata(&mci->dev, mci); pm_runtime_forbid(&mci->dev); - /* - * The memory controller needs its own bus, in order to avoid - * namespace conflicts at /sys/bus/edac. - */ - debugf0("creating bus %s\n",mci->bus.name); - mci->bus.name = kstrdup(dev_name(&mci->dev), GFP_KERNEL); - err = bus_register(&mci->bus); - if (err < 0) - return err; - debugf0("%s(): creating device %s\n", __func__, dev_name(&mci->dev)); err = device_add(&mci->dev); @@ -986,7 +994,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) * Create the dimm/rank devices */ for (i = 0; i < mci->tot_dimms; i++) { - struct dimm_info *dimm = &mci->dimms[i]; + struct dimm_info *dimm = mci->dimms[i]; /* Only expose populated DIMMs */ if (dimm->nr_pages == 0) continue; @@ -1023,7 +1031,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) fail: for (i--; i >= 0; i--) { - struct dimm_info *dimm = &mci->dimms[i]; + struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; put_device(&dimm->dev); @@ -1053,7 +1061,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) #endif for (i = 0; i < mci->tot_dimms; i++) { - struct dimm_info *dimm = &mci->dimms[i]; + struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; debugf0("%s(): removing device %s\n", __func__, @@ -1072,9 +1080,15 @@ void edac_unregister_sysfs(struct mem_ctl_info *mci) kfree(mci->bus.name); } -static void mc_attr_release(struct device *device) +static void mc_attr_release(struct device *dev) { - debugf1("Releasing device %s\n", dev_name(device)); + /* + * There's no container structure here, as this is just the mci + * parent device, used to create the /sys/devices/mc sysfs node. + * So, there are no attributes on it. + */ + debugf1("Releasing device %s\n", dev_name(dev)); + kfree(dev); } static struct device_type mc_attr_type = { @@ -1095,21 +1109,25 @@ int __init edac_mc_sysfs_init(void) return -EINVAL; } - mci_pdev.bus = edac_subsys; - mci_pdev.type = &mc_attr_type; - device_initialize(&mci_pdev); - dev_set_name(&mci_pdev, "mc"); + mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL); + + mci_pdev->bus = edac_subsys; + mci_pdev->type = &mc_attr_type; + device_initialize(mci_pdev); + dev_set_name(mci_pdev, "mc"); - err = device_add(&mci_pdev); + err = device_add(mci_pdev); if (err < 0) return err; + debugf0("device %s created\n", dev_name(mci_pdev)); + return 0; } void __exit edac_mc_sysfs_exit(void) { - put_device(&mci_pdev); - device_del(&mci_pdev); + put_device(mci_pdev); + device_del(mci_pdev); edac_put_sysfs_subsys(); } diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index d1ebd9b9ad6f..812213da7f91 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -236,7 +236,7 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, int row, multi_chan, channel; unsigned long pfn, offset; - multi_chan = mci->csrows[0].nr_channels - 1; + multi_chan = mci->csrows[0]->nr_channels - 1; if (!(info->errsts & I3000_ERRSTS_BITS)) return 0; @@ -393,7 +393,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) { u8 value; u32 cumul_size; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; value = drb[i]; cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); @@ -410,7 +410,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) last_cumul_size = cumul_size; for (j = 0; j < nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_channels; dimm->grain = I3000_DEAP_GRAIN; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 600a05df3759..c5f0fb31d5e0 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -379,7 +379,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) */ for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; nr_pages = drb_to_nr_pages(drbs, stacked, i / I3200_RANKS_PER_CHANNEL, @@ -389,7 +389,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) continue; for (j = 0; j < nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_channels; dimm->grain = nr_pages << PAGE_SHIFT; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index ba60694437bd..0570cf3d2563 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1203,8 +1203,8 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) size_mb = pvt->dimm_info[slot][channel].megabytes; - debugf2("%s: dimm%zd (branch %d channel %d slot %d): %d.%03d GB\n", - __func__, dimm - mci->dimms, + debugf2("%s: dimm (branch %d channel %d slot %d): %d.%03d GB\n", + __func__, channel / 2, channel % 2, slot, size_mb / 1000, size_mb % 1000); @@ -1227,7 +1227,7 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) * With such single-DIMM mode, the SDCC algorithm degrades to SECDEC+. */ if (ndimms == 1) - mci->dimms[0].edac_mode = EDAC_SECDED; + mci->dimms[0]->edac_mode = EDAC_SECDED; return (ndimms == 0); } diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 65fd2e1eceb8..0f2751bf3ffe 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -197,8 +197,8 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc); row_high_limit_last = 0; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 8f3350000942..06a3c8d26d19 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -116,7 +116,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, info->eap >>= PAGE_SHIFT; row = edac_mc_find_csrow_by_page(mci, info->eap); - dimm = mci->csrows[row].channels[0].dimm; + dimm = mci->csrows[row]->channels[0]->dimm; if (info->errsts & 0x0002) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, @@ -161,8 +161,8 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) * in all eight rows. */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_word(pdev, I82860_GBA + index * 2, &value); cumul_size = (value & I82860_GBA_MASK) << diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index a47c6b25db31..97fd6b769c84 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -227,7 +227,7 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, { int row, multi_chan; - multi_chan = mci->csrows[0].nr_channels - 1; + multi_chan = mci->csrows[0]->nr_channels - 1; if (!(info->errsts & 0x0081)) return 0; @@ -367,7 +367,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; value = readb(ovrfl_window + I82875P_DRB + index); cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); @@ -382,7 +382,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, last_cumul_size = cumul_size; for (j = 0; j < nr_chans; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_chans; dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 8b26401efa19..4d239ab31e34 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -308,10 +308,10 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); return 0; } - chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1; + chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; offst = info->eap & ((1 << PAGE_SHIFT) - - (1 << mci->csrows[row].channels[chan].dimm->grain)); + (1 << mci->csrows[row]->channels[chan]->dimm->grain)); if (info->errsts & 0x0002) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, @@ -394,7 +394,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; value = readb(mch_window + I82975X_DRB + index + ((index >= 4) ? 0x80 : 0)); @@ -421,10 +421,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ dtype = i82975x_dram_type(mch_window, index); for (chan = 0; chan < csrow->nr_channels; chan++) { - dimm = mci->csrows[index].channels[chan].dimm; + dimm = mci->csrows[index]->channels[chan]->dimm; dimm->nr_pages = nr_pages / csrow->nr_channels; - strncpy(csrow->channels[chan].dimm->label, + strncpy(csrow->channels[chan]->dimm->label, labels[(index >> 1) + (chan * 2)], EDAC_MC_LABEL_LEN); dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index d132dbbd9bd7..0db6f1e84656 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -825,7 +825,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) pfn = err_addr >> PAGE_SHIFT; for (row_index = 0; row_index < mci->nr_csrows; row_index++) { - csrow = &mci->csrows[row_index]; + csrow = mci->csrows[row_index]; if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page)) break; } @@ -945,8 +945,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) u32 start; u32 end; - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + (index * MPC85XX_MC_CS_BNDS_OFS)); diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index ff6b8e248e89..3a58ba9158db 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -670,8 +670,8 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); - csrow = &mci->csrows[0]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[0]; + dimm = csrow->channels[0]->dimm; dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT; dimm->grain = 8; diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 92becaa8722a..44f73b00df01 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -111,14 +111,14 @@ static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) if (errsta & (MCDEBUG_ERRSTA_MBE_STATUS | MCDEBUG_ERRSTA_RFL_STATUS)) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - mci->csrows[cs].first_page, 0, 0, + mci->csrows[cs]->first_page, 0, 0, cs, 0, -1, mci->ctl_name, "", NULL); } /* correctable/single-bit errors */ if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - mci->csrows[cs].first_page, 0, 0, + mci->csrows[cs]->first_page, 0, 0, cs, 0, -1, mci->ctl_name, "", NULL); } @@ -141,8 +141,8 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, int index; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_dword(pdev, MCDRAM_RANKCFG + (index * 12), diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index cf4ccbdba85d..445c9ff27b88 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -230,8 +230,8 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, row_high_limit_last = 0; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 604bc4df653a..fc77f77fa065 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -84,10 +84,10 @@ static void tile_edac_check(struct mem_ctl_info *mci) */ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) { - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; struct tile_edac_priv *priv = mci->pvt_info; struct mshim_mem_info mem_info; - struct dimm_info *dimm = csrow->channels[0].dimm; + struct dimm_info *dimm = csrow->channels[0]->dimm; if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info, sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) != diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index f9506f26e2bf..ae699be78b24 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -378,7 +378,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) */ for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; nr_pages = drb_to_nr_pages(drbs, stacked, i / X38_RANKS_PER_CHANNEL, @@ -388,7 +388,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) continue; for (j = 0; j < x38_channel_num; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / x38_channel_num; dimm->grain = nr_pages << PAGE_SHIFT; diff --git a/include/linux/edac.h b/include/linux/edac.h index 64ae0c5cf62e..6677af853e30 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -412,23 +412,21 @@ struct edac_mc_layer { #define EDAC_MAX_LAYERS 3 /** - * EDAC_DIMM_PTR - Macro responsible to find a pointer inside a pointer array + * EDAC_DIMM_OFF - Macro responsible to get a pointer offset inside a pointer array * for the element given by [layer0,layer1,layer2] position * * @layers: a struct edac_mc_layer array, describing how many elements * were allocated for each layer - * @var: name of the var where we want to get the pointer - * (like mci->dimms) * @n_layers: Number of layers at the @layers array * @layer0: layer0 position * @layer1: layer1 position. Unused if n_layers < 2 * @layer2: layer2 position. Unused if n_layers < 3 * - * For 1 layer, this macro returns &var[layer0] + * For 1 layer, this macro returns &var[layer0] - &var * For 2 layers, this macro is similar to allocate a bi-dimensional array - * and to return "&var[layer0][layer1]" + * and to return "&var[layer0][layer1] - &var" * For 3 layers, this macro is similar to allocate a tri-dimensional array - * and to return "&var[layer0][layer1][layer2]" + * and to return "&var[layer0][layer1][layer2] - &var" * * A loop could be used here to make it more generic, but, as we only have * 3 layers, this is a little faster. @@ -436,17 +434,46 @@ struct edac_mc_layer { * a NULL is returned, causing an OOPS during the memory allocation routine, * with would point to the developer that he's doing something wrong. */ -#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ - typeof(var) __p; \ +#define EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2) ({ \ + int __i; \ if ((nlayers) == 1) \ - __p = &var[layer0]; \ + __i = layer0; \ else if ((nlayers) == 2) \ - __p = &var[(layer1) + ((layers[1]).size * (layer0))]; \ + __i = (layer1) + ((layers[1]).size * (layer0)); \ else if ((nlayers) == 3) \ - __p = &var[(layer2) + ((layers[2]).size * ((layer1) + \ - ((layers[1]).size * (layer0))))]; \ + __i = (layer2) + ((layers[2]).size * ((layer1) + \ + ((layers[1]).size * (layer0)))); \ else \ + __i = -EINVAL; \ + __i; \ +}) + +/** + * EDAC_DIMM_PTR - Macro responsible to get a pointer inside a pointer array + * for the element given by [layer0,layer1,layer2] position + * + * @layers: a struct edac_mc_layer array, describing how many elements + * were allocated for each layer + * @var: name of the var where we want to get the pointer + * (like mci->dimms) + * @n_layers: Number of layers at the @layers array + * @layer0: layer0 position + * @layer1: layer1 position. Unused if n_layers < 2 + * @layer2: layer2 position. Unused if n_layers < 3 + * + * For 1 layer, this macro returns &var[layer0] + * For 2 layers, this macro is similar to allocate a bi-dimensional array + * and to return "&var[layer0][layer1]" + * For 3 layers, this macro is similar to allocate a tri-dimensional array + * and to return "&var[layer0][layer1][layer2]" + */ +#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ + typeof(*var) __p; \ + int ___i = EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2); \ + if (___i < 0) \ __p = NULL; \ + else \ + __p = (var)[___i]; \ __p; \ }) @@ -486,8 +513,6 @@ struct dimm_info { * patches in this series will fix this issue. */ struct rank_info { - struct device dev; - int chan_idx; struct csrow_info *csrow; struct dimm_info *dimm; @@ -513,7 +538,7 @@ struct csrow_info { /* channel information for this csrow */ u32 nr_channels; - struct rank_info *channels; + struct rank_info **channels; }; /* @@ -572,7 +597,7 @@ struct mem_ctl_info { unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, unsigned long page); int mc_idx; - struct csrow_info *csrows; + struct csrow_info **csrows; unsigned nr_csrows, num_cschannel; /* @@ -592,7 +617,7 @@ struct mem_ctl_info { * DIMM info. Will eventually remove the entire csrows_info some day */ unsigned tot_dimms; - struct dimm_info *dimms; + struct dimm_info **dimms; /* * FIXME - what about controllers on other busses? - IDs must be -- GitLab From 356f0a30860d44de7ac021708caa0c8bd5688dbe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Mar 2012 16:10:51 -0300 Subject: [PATCH 0450/5711] i7core_edac: change the mem allocation scheme to make Documentation/kobject.txt happy Kernel kobjects have rigid rules: each container object should be dynamically allocated, and can't be allocated into a single kmalloc. EDAC never obeyed this rule: it has a single malloc function that allocates all needed data into a single kzalloc. As this is not accepted anymore, change the allocation schema of the EDAC *_info structs to enforce this Kernel standard. Cc: Aristeu Rozanski Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 56 ++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index ab3b84b906b9..c29944fbb7d8 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -248,7 +248,7 @@ struct i7core_dev { }; struct i7core_pvt { - struct device addrmatch_dev, chancounts_dev; + struct device *addrmatch_dev, *chancounts_dev; struct pci_dev *pci_noncore; struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; @@ -1105,6 +1105,7 @@ static const struct attribute_group *addrmatch_groups[] = { static void addrmatch_release(struct device *device) { debugf1("Releasing device %s\n", dev_name(device)); + kfree(device); } static struct device_type addrmatch_type = { @@ -1135,6 +1136,7 @@ static const struct attribute_group *all_channel_counts_groups[] = { static void all_channel_counts_release(struct device *device) { debugf1("Releasing device %s\n", dev_name(device)); + kfree(device); } static struct device_type all_channel_counts_type = { @@ -1177,32 +1179,44 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) if (rc < 0) return rc; - pvt->addrmatch_dev.type = &addrmatch_type; - pvt->addrmatch_dev.bus = mci->dev.bus; - device_initialize(&pvt->addrmatch_dev); - pvt->addrmatch_dev.parent = &mci->dev; - dev_set_name(&pvt->addrmatch_dev, "inject_addrmatch"); - dev_set_drvdata(&pvt->addrmatch_dev, mci); + pvt->addrmatch_dev = kzalloc(sizeof(*pvt->addrmatch_dev), GFP_KERNEL); + if (!pvt->addrmatch_dev) + return rc; + + pvt->addrmatch_dev->type = &addrmatch_type; + pvt->addrmatch_dev->bus = mci->dev.bus; + device_initialize(pvt->addrmatch_dev); + pvt->addrmatch_dev->parent = &mci->dev; + dev_set_name(pvt->addrmatch_dev, "inject_addrmatch"); + dev_set_drvdata(pvt->addrmatch_dev, mci); debugf1("%s(): creating %s\n", __func__, - dev_name(&pvt->addrmatch_dev)); + dev_name(pvt->addrmatch_dev)); - rc = device_add(&pvt->addrmatch_dev); + rc = device_add(pvt->addrmatch_dev); if (rc < 0) return rc; if (!pvt->is_registered) { - pvt->chancounts_dev.type = &all_channel_counts_type; - pvt->chancounts_dev.bus = mci->dev.bus; - device_initialize(&pvt->chancounts_dev); - pvt->chancounts_dev.parent = &mci->dev; - dev_set_name(&pvt->chancounts_dev, "all_channel_counts"); - dev_set_drvdata(&pvt->chancounts_dev, mci); + pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), + GFP_KERNEL); + if (!pvt->chancounts_dev) { + put_device(pvt->addrmatch_dev); + device_del(pvt->addrmatch_dev); + return rc; + } + + pvt->chancounts_dev->type = &all_channel_counts_type; + pvt->chancounts_dev->bus = mci->dev.bus; + device_initialize(pvt->chancounts_dev); + pvt->chancounts_dev->parent = &mci->dev; + dev_set_name(pvt->chancounts_dev, "all_channel_counts"); + dev_set_drvdata(pvt->chancounts_dev, mci); debugf1("%s(): creating %s\n", __func__, - dev_name(&pvt->chancounts_dev)); + dev_name(pvt->chancounts_dev)); - rc = device_add(&pvt->chancounts_dev); + rc = device_add(pvt->chancounts_dev); if (rc < 0) return rc; } @@ -1221,11 +1235,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) device_remove_file(&mci->dev, &dev_attr_inject_enable); if (!pvt->is_registered) { - put_device(&pvt->chancounts_dev); - device_del(&pvt->chancounts_dev); + put_device(pvt->chancounts_dev); + device_del(pvt->chancounts_dev); } - put_device(&pvt->addrmatch_dev); - device_del(&pvt->addrmatch_dev); + put_device(pvt->addrmatch_dev); + device_del(pvt->addrmatch_dev); } /**************************************************************************** -- GitLab From 8b6f04ce6b9fb3aa8dd5dcd57d91be5d73e643a0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Apr 2012 08:53:34 -0300 Subject: [PATCH 0451/5711] edac: move documentation ABI to ABI/testing/sysfs-devices-edac The EDAC MC API is currently stored at the wrong place. Move the parts of the EDAC MC ABI that will be kept to ABI/testing/sysfs-devices-edac. The Date: field were added based on git timestamps for the git commit patches that added the functionality at edac.txt. Acked-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- Documentation/ABI/testing/sysfs-devices-edac | 76 +++++++++++++ Documentation/edac.txt | 112 ++----------------- 2 files changed, 84 insertions(+), 104 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-devices-edac diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac new file mode 100644 index 000000000000..40db633b00f6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-edac @@ -0,0 +1,76 @@ +What: /sys/devices/system/edac/mc/mc*/reset_counters +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This write-only control file will zero all the statistical + counters for UE and CE errors on the given memory controller. + Zeroing the counters will also reset the timer indicating how + long since the last counter were reset. This is useful for + computing errors/time. Since the counters are always reset + at driver initialization time, no module/kernel parameter + is available. + +What: /sys/devices/system/edac/mc/mc*/seconds_since_reset +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays how many seconds have elapsed + since the last counter reset. This can be used with the error + counters to measure error rates. + +What: /sys/devices/system/edac/mc/mc*/mc_name +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the type of memory controller + that is being utilized. + +What: /sys/devices/system/edac/mc/mc*/size_mb +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays, in count of megabytes, of memory + that this memory controller manages. + +What: /sys/devices/system/edac/mc/mc*/ue_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the total count of uncorrectable + errors that have occurred on this memory controller. If + panic_on_ue is set, this counter will not have a chance to + increment, since EDAC will panic the system + +What: /sys/devices/system/edac/mc/mc*/ue_noinfo_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the number of UEs that have + occurred on this memory controller with no information as to + which DIMM slot is having errors. + +What: /sys/devices/system/edac/mc/mc*/ce_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the total count of correctable + errors that have occurred on this memory controller. This + count is very important to examine. CEs provide early + indications that a DIMM is beginning to fail. This count + field should be monitored for non-zero values and report + such information to the system administrator. + +What: /sys/devices/system/edac/mc/mc*/ce_noinfo_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the number of CEs that + have occurred on this memory controller wherewith no + information as to which DIMM slot is having errors. Memory is + handicapped, but operational, yet no information is available + to indicate which slot the failing memory is in. This count + field should be also be monitored for non-zero values. + +What: /sys/devices/system/edac/mc/mc*/sdram_scrub_rate +Date: February 2007 +Contact: linux-edac@vger.kernel.org +Description: Read/Write attribute file that controls memory scrubbing. + The scrubbing rate used by the memory controller is set by + writing a minimum bandwidth in bytes/sec to the attribute file. + The rate will be translated to an internal value that gives at + least the specified rate. + Reading the file will return the actual scrubbing rate employed. + If configuration fails or memory scrubbing is not implemented, + the value of the attribute file will be -1. diff --git a/Documentation/edac.txt b/Documentation/edac.txt index fdcc49fad8e1..c25f086a6960 100644 --- a/Documentation/edac.txt +++ b/Documentation/edac.txt @@ -232,116 +232,20 @@ EDAC control and attribute files. In 'mcX' directories are EDAC control and attribute files for -this 'X' instance of the memory controllers: - - -Counter reset control file: - - 'reset_counters' - - This write-only control file will zero all the statistical counters - for UE and CE errors. Zeroing the counters will also reset the timer - indicating how long since the last counter zero. This is useful - for computing errors/time. Since the counters are always reset at - driver initialization time, no module/kernel parameter is available. - - RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset - - This resets the counters on memory controller 0 - - -Seconds since last counter reset control file: - - 'seconds_since_reset' - - This attribute file displays how many seconds have elapsed since the - last counter reset. This can be used with the error counters to - measure error rates. - - - -Memory Controller name attribute file: - - 'mc_name' - - This attribute file displays the type of memory controller - that is being utilized. - - -Total memory managed by this memory controller attribute file: - - 'size_mb' - - This attribute file displays, in count of megabytes, of memory - that this instance of memory controller manages. - - -Total Uncorrectable Errors count attribute file: - - 'ue_count' - - This attribute file displays the total count of uncorrectable - errors that have occurred on this memory controller. If panic_on_ue - is set this counter will not have a chance to increment, - since EDAC will panic the system. - - -Total UE count that had no information attribute fileY: - - 'ue_noinfo_count' - - This attribute file displays the number of UEs that have occurred - with no information as to which DIMM slot is having errors. - - -Total Correctable Errors count attribute file: - - 'ce_count' - - This attribute file displays the total count of correctable - errors that have occurred on this memory controller. This - count is very important to examine. CEs provide early - indications that a DIMM is beginning to fail. This count - field should be monitored for non-zero values and report - such information to the system administrator. - - -Total Correctable Errors count attribute file: - - 'ce_noinfo_count' - - This attribute file displays the number of CEs that - have occurred wherewith no information as to which DIMM slot - is having errors. Memory is handicapped, but operational, - yet no information is available to indicate which slot - the failing memory is in. This count field should be also - be monitored for non-zero values. - -Device Symlink: - - 'device' - - Symlink to the memory controller device. - -Sdram memory scrubbing rate: - - 'sdram_scrub_rate' - - Read/Write attribute file that controls memory scrubbing. The scrubbing - rate is set by writing a minimum bandwidth in bytes/sec to the attribute - file. The rate will be translated to an internal value that gives at - least the specified rate. - - Reading the file will return the actual scrubbing rate employed. - - If configuration fails or memory scrubbing is not implemented, accessing - that attribute will fail. +this 'X' instance of the memory controllers. +For a description of the sysfs API, please see: + Documentation/ABI/testing/sysfs/devices-edac ============================================================================ 'csrowX' DIRECTORIES +When CONFIG_EDAC_LEGACY_SYSFS is enabled, the sysfs will contain the +csrowX directories. As this API doesn't work properly for Rambus, FB-DIMMs +and modern Intel Memory Controllers, this is being deprecated in favor +of dimmX directories. + In the 'csrowX' directories are EDAC control and attribute files for this 'X' instance of csrow: -- GitLab From 2639c3ee298401881cc560c5e3987f8b222b9f7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Apr 2012 11:13:10 -0300 Subject: [PATCH 0452/5711] Edac: Add ABI Documentation for the new device nodes The EDAC ABI were extended to add support for per-DIMM or per-rank information and silkscreen labels. Properly document them. Most of the comments there came from edac.txt descriptions of the fields that are part of the legacy csrowX ABI (e. g. /sys/devices/system/edac/mc/mc*/csrow*/*). Acked-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- Documentation/ABI/testing/sysfs-devices-edac | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac index 40db633b00f6..30ee78aaed75 100644 --- a/Documentation/ABI/testing/sysfs-devices-edac +++ b/Documentation/ABI/testing/sysfs-devices-edac @@ -74,3 +74,67 @@ Description: Read/Write attribute file that controls memory scrubbing. Reading the file will return the actual scrubbing rate employed. If configuration fails or memory scrubbing is not implemented, the value of the attribute file will be -1. + +What: /sys/devices/system/edac/mc/mc*/max_location +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file displays the information about the last + available memory slot in this memory controller. It is used by + userspace tools in order to display the memory filling layout. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file will display the size of dimm or rank. + For dimm*/size, this is the size, in MB of the DIMM memory + stick. For rank*/size, this is the size, in MB for one rank + of the DIMM memory stick. On single rank memories (1R), this + is also the total size of the dimm. On dual rank (2R) memories, + this is half the size of the total DIMM memories. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file will display what type of DRAM device is + being utilized on this DIMM (x1, x2, x4, x8, ...). + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file will display what type of Error detection + and correction is being utilized. For example: S4ECD4ED would + mean a Chipkill with x4 DRAM. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This control file allows this DIMM to have a label assigned + to it. With this label in the module, when errors occur + the output can provide the DIMM label in the system log. + This becomes vital for panic events to isolate the + cause of the UE event. + DIMM Labels must be assigned after booting, with information + that correctly identifies the physical slot with its + silk screen label. This information is currently very + motherboard specific and determination of this information + must occur in userland at this time. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file will display the location (csrow/channel, + branch/channel/slot or channel/slot) of the dimm or rank. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type +Date: April 2012 +Contact: Mauro Carvalho Chehab + linux-edac@vger.kernel.org +Description: This attribute file will display what type of memory is + currently on this csrow. Normally, either buffered or + unbuffered memory (for example, Unbuffered-DDR3). -- GitLab From dd23cd6eb1f59ba722a6e6aa228adff7c01404de Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Apr 2012 11:59:14 -0300 Subject: [PATCH 0453/5711] edac: Don't add __func__ or __FILE__ for debugf[0-9] msgs The debug macro already adds that. Most of the work here was made by this small script: $f .=$_ while (<>); $f =~ s/(debugf[0-9]\s*\(\s*)__FILE__\s*": /\1"/g; $f =~ s/(debugf[0-9]\s*\(\s*)__FILE__\s*/\1/g; $f =~ s/(debugf[0-9]\s*\(\s*)__FILE__\s*"MC: /\1"/g; $f =~ s/(debugf[0-9]\s*\(\")\%s[\:\,\(\)]*\s*([^\"]*\s*[^\)]+)__func__\s*\,\s*/\1\2/g; $f =~ s/(debugf[0-9]\s*\(\")\%s[\:\,\(\)]*\s*([^\"]*\s*[^\)]+),\s*__func__\s*\)/\1\2)/g; $f =~ s/(debugf[0-9]\s*\(\"MC\:\s*)\%s[\:\,\(\)]*\s*([^\"]*\s*[^\)]+)__func__\s*\,\s*/\1\2/g; $f =~ s/(debugf[0-9]\s*\(\"MC\:\s*)\%s[\:\,\(\)]*\s*([^\"]*\s*[^\)]+),\s*__func__\s*\)/\1\2)/g; $f =~ s/\"MC\: \\n\"/"MC:\\n"/g; print $f; After running the script, manual cleanups were done to fix it the remaining places. While here, removed the __LINE__ on most places, as it doesn't actually give useful info on most places. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd76x_edac.c | 14 +++---- drivers/edac/cpc925_edac.c | 24 +++++------ drivers/edac/e752x_edac.c | 34 +++++++-------- drivers/edac/e7xxx_edac.c | 34 +++++++-------- drivers/edac/edac_device.c | 28 ++++++------- drivers/edac/edac_device_sysfs.c | 71 ++++++++++++++++---------------- drivers/edac/edac_mc.c | 44 ++++++++++---------- drivers/edac/edac_mc_sysfs.c | 24 +++++------ drivers/edac/edac_module.c | 2 +- drivers/edac/edac_pci.c | 26 ++++++------ drivers/edac/edac_pci_sysfs.c | 37 ++++++++--------- drivers/edac/i3000_edac.c | 22 +++++----- drivers/edac/i3200_edac.c | 18 ++++---- drivers/edac/i5000_edac.c | 25 ++++++----- drivers/edac/i5400_edac.c | 24 +++++------ drivers/edac/i7300_edac.c | 14 +++---- drivers/edac/i7core_edac.c | 37 +++++++---------- drivers/edac/i82443bxgx_edac.c | 26 ++++++------ drivers/edac/i82860_edac.c | 18 ++++---- drivers/edac/i82875p_edac.c | 22 +++++----- drivers/edac/i82975x_edac.c | 24 +++++------ drivers/edac/mpc85xx_edac.c | 22 +++++----- drivers/edac/mv64x60_edac.c | 26 ++++++------ drivers/edac/r82600_edac.c | 32 +++++++------- drivers/edac/sb_edac.c | 22 +++++----- drivers/edac/x38_edac.c | 18 ++++---- 26 files changed, 331 insertions(+), 357 deletions(-) diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index a0c9f82875cd..b6e94ae4bf6f 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -180,7 +180,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; - debugf3("%s()\n", __func__); + debugf3("\n"); amd76x_get_error_info(mci, &info); amd76x_process_error_info(mci, &info, 1); } @@ -241,7 +241,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) u32 ems_mode; struct amd76x_error_info discard; - debugf0("%s()\n", __func__); + debugf0("\n"); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; @@ -256,7 +256,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("%s(): mci = %p\n", __func__, mci); + debugf0("mci = %p\n", mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -276,7 +276,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail; } @@ -292,7 +292,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail: @@ -304,7 +304,7 @@ fail: static int __devinit amd76x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* don't need to call pci_enable_device() */ return amd76x_probe1(pdev, ent->driver_data); @@ -322,7 +322,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); if (amd76x_pci) edac_pci_release_generic_ctl(amd76x_pci); diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 534491d67159..fa39a7840e28 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -316,13 +316,12 @@ static void get_total_mem(struct cpc925_mc_pdata *pdata) reg += aw; size = of_read_number(reg, sw); reg += sw; - debugf1("%s: start 0x%lx, size 0x%lx\n", __func__, - start, size); + debugf1("start 0x%lx, size 0x%lx\n", start, size); pdata->total_mem += size; } while (reg < reg_end); of_node_put(np); - debugf0("%s: total_mem 0x%lx\n", __func__, pdata->total_mem); + debugf0("total_mem 0x%lx\n", pdata->total_mem); } static void cpc925_init_csrows(struct mem_ctl_info *mci) @@ -512,7 +511,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, *offset = pa & (PAGE_SIZE - 1); *pfn = pa >> PAGE_SHIFT; - debugf0("%s: ECC physical address 0x%lx\n", __func__, pa); + debugf0("ECC physical address 0x%lx\n", pa); } static int cpc925_mc_find_channel(struct mem_ctl_info *mci, u16 syndrome) @@ -852,8 +851,8 @@ static void cpc925_add_edac_devices(void __iomem *vbase) goto err2; } - debugf0("%s: Successfully added edac device for %s\n", - __func__, dev_info->ctl_name); + debugf0("Successfully added edac device for %s\n", + dev_info->ctl_name); continue; @@ -884,8 +883,8 @@ static void cpc925_del_edac_devices(void) if (dev_info->exit) dev_info->exit(dev_info); - debugf0("%s: Successfully deleted edac device for %s\n", - __func__, dev_info->ctl_name); + debugf0("Successfully deleted edac device for %s\n", + dev_info->ctl_name); } } @@ -900,7 +899,7 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) mscr = __raw_readl(pdata->vbase + REG_MSCR_OFFSET); si = (mscr & MSCR_SI_MASK) >> MSCR_SI_SHIFT; - debugf0("%s, Mem Scrub Ctrl Register 0x%x\n", __func__, mscr); + debugf0("Mem Scrub Ctrl Register 0x%x\n", mscr); if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || (si == 0)) { @@ -928,8 +927,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase) ((mbcr & MBCR_64BITBUS_MASK) == 0)) dual = 1; - debugf0("%s: %s channel\n", __func__, - (dual > 0) ? "Dual" : "Single"); + debugf0("%s channel\n", (dual > 0) ? "Dual" : "Single"); return dual; } @@ -944,7 +942,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) struct resource *r; int res = 0, nr_channels; - debugf0("%s: %s platform device found!\n", __func__, pdev->name); + debugf0("%s platform device found!\n", pdev->name); if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) { res = -ENOMEM; @@ -1026,7 +1024,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) cpc925_add_edac_devices(vbase); /* get this far and it's successful */ - debugf0("%s: success\n", __func__); + debugf0("success\n"); res = 0; goto out; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 7cde7f1aafb7..39c8997b2162 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -309,7 +309,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + debugf3("\n"); if (page < pvt->tolm) return page; @@ -335,7 +335,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, int i; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + debugf3("\n"); /* convert the addr to 4k page */ page = sec1_add >> (PAGE_SHIFT - 4); @@ -394,7 +394,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, int row; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + debugf3("\n"); if (error_one & 0x0202) { error_2b = ded_add; @@ -453,7 +453,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, if (!handle_error) return; - debugf3("%s()\n", __func__); + debugf3("\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e752x UE log memory write", "", NULL); @@ -982,7 +982,7 @@ static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; - debugf3("%s()\n", __func__); + debugf3("\n"); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); } @@ -1102,7 +1102,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, pci_read_config_byte(pdev, E752X_DRB + index, &value); /* convert a 128 or 64 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + debugf3("(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -1270,7 +1270,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; /* Number of channels 0=1chan,1=2chan */ struct e752x_error_info discard; - debugf0("%s(): mci\n", __func__); + debugf0("mci\n"); debugf0("Starting Probe1\n"); /* check to see if device 0 function 1 is enabled; if it isn't, we @@ -1301,7 +1301,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; /* 3100 IMCH supports SECDEC only */ mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED : @@ -1311,7 +1311,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_ver = E752X_REVISION; mci->pdev = &pdev->dev; - debugf3("%s(): init pvt\n", __func__); + debugf3("init pvt\n"); pvt = (struct e752x_pvt *)mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); @@ -1321,7 +1321,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) return -ENODEV; } - debugf3("%s(): more mci init\n", __func__); + debugf3("more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e752x_check; @@ -1343,7 +1343,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */ else mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + debugf3("tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E752X_TOLM, &pci_data); @@ -1360,7 +1360,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail; } @@ -1378,7 +1378,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail: @@ -1394,7 +1394,7 @@ fail: static int __devinit e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* wake up and enable device */ if (pci_enable_device(pdev) < 0) @@ -1408,7 +1408,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e752x_pvt *pvt; - debugf0("%s()\n", __func__); + debugf0("\n"); if (e752x_pci) edac_pci_release_generic_ctl(e752x_pci); @@ -1454,7 +1454,7 @@ static int __init e752x_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + debugf3("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1465,7 +1465,7 @@ static int __init e752x_init(void) static void __exit e752x_exit(void) { - debugf3("%s()\n", __func__); + debugf3("\n"); pci_unregister_driver(&e752x_driver); } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index c6c0ebaca371..691d7067a141 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -166,7 +166,7 @@ static const struct e7xxx_dev_info e7xxx_devs[] = { /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { - debugf3("%s()\n", __func__); + debugf3("\n"); if ((syndrome & 0xff00) == 0) return 0; @@ -186,7 +186,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + debugf3("\n"); if ((page < pvt->tolm) || ((page >= 0x100000) && (page < pvt->remapbase))) @@ -208,7 +208,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int row; int channel; - debugf3("%s()\n", __func__); + debugf3("\n"); /* read the error address */ error_1b = info->dram_celog_add; /* FIXME - should use PAGE_SHIFT */ @@ -225,7 +225,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ce_no_info(struct mem_ctl_info *mci) { - debugf3("%s()\n", __func__); + debugf3("\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e7xxx CE log register overflow", "", NULL); } @@ -235,7 +235,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) u32 error_2b, block_page; int row; - debugf3("%s()\n", __func__); + debugf3("\n"); /* read the error address */ error_2b = info->dram_uelog_add; /* FIXME - should use PAGE_SHIFT */ @@ -248,7 +248,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ue_no_info(struct mem_ctl_info *mci) { - debugf3("%s()\n", __func__); + debugf3("\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e7xxx UE log register overflow", "", NULL); @@ -334,7 +334,7 @@ static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; - debugf3("%s()\n", __func__); + debugf3("\n"); e7xxx_get_error_info(mci, &info); e7xxx_process_error_info(mci, &info, 1); } @@ -383,7 +383,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, pci_read_config_byte(pdev, E7XXX_DRB + index, &value); /* convert a 64 or 32 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + debugf3("(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -430,7 +430,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; struct e7xxx_error_info discard; - debugf0("%s(): mci\n", __func__); + debugf0("mci\n"); pci_read_config_dword(pdev, E7XXX_DRC, &drc); @@ -453,7 +453,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; @@ -461,7 +461,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E7XXX_REVISION; mci->pdev = &pdev->dev; - debugf3("%s(): init pvt\n", __func__); + debugf3("init pvt\n"); pvt = (struct e7xxx_pvt *)mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -474,14 +474,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - debugf3("%s(): more mci init\n", __func__); + debugf3("more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e7xxx_check; mci->ctl_page_to_phys = ctl_page_to_phys; e7xxx_init_csrows(mci, pdev, dev_idx, drc); mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + debugf3("tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E7XXX_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -500,7 +500,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail1; } @@ -516,7 +516,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail1: @@ -532,7 +532,7 @@ fail0: static int __devinit e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* wake up and enable device */ return pci_enable_device(pdev) ? @@ -544,7 +544,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e7xxx_pvt *pvt; - debugf0("%s()\n", __func__); + debugf0("\n"); if (e7xxx_pci) edac_pci_release_generic_ctl(e7xxx_pci); diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index cb397d9437d1..ed46949f25cf 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -82,8 +82,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( void *pvt, *p; int err; - debugf4("%s() instances=%d blocks=%d\n", - __func__, nr_instances, nr_blocks); + debugf4("instances=%d blocks=%d\n", + nr_instances, nr_blocks); /* Calculate the size of memory we need to allocate AND * determine the offsets of the various item arrays @@ -156,8 +156,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( /* Name of this edac device */ snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); - debugf4("%s() edac_dev=%p next after end=%p\n", - __func__, dev_ctl, pvt + sz_private ); + debugf4("edac_dev=%p next after end=%p\n", + dev_ctl, pvt + sz_private ); /* Initialize every Instance */ for (instance = 0; instance < nr_instances; instance++) { @@ -178,9 +178,9 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( snprintf(blk->name, sizeof(blk->name), "%s%d", edac_block_name, block+offset_value); - debugf4("%s() instance=%d inst_p=%p block=#%d " + debugf4("instance=%d inst_p=%p block=#%d " "block_p=%p name='%s'\n", - __func__, instance, inst, block, + instance, inst, block, blk, blk->name); /* if there are NO attributes OR no attribute pointer @@ -194,8 +194,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; blk->block_attributes = attrib_p; - debugf4("%s() THIS BLOCK_ATTRIB=%p\n", - __func__, blk->block_attributes); + debugf4("THIS BLOCK_ATTRIB=%p\n", + blk->block_attributes); /* Initialize every user specified attribute in this * block with the data the caller passed in @@ -214,9 +214,9 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib->block = blk; /* up link */ - debugf4("%s() alloc-attrib=%p attrib_name='%s' " + debugf4("alloc-attrib=%p attrib_name='%s' " "attrib-spec=%p spec-name=%s\n", - __func__, attrib, attrib->attr.name, + attrib, attrib->attr.name, &attrib_spec[attr], attrib_spec[attr].attr.name ); @@ -273,7 +273,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev) struct edac_device_ctl_info *edac_dev; struct list_head *item; - debugf0("%s()\n", __func__); + debugf0("\n"); list_for_each(item, &edac_device_list) { edac_dev = list_entry(item, struct edac_device_ctl_info, link); @@ -408,7 +408,7 @@ static void edac_device_workq_function(struct work_struct *work_req) void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, unsigned msec) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* take the arg 'msec' and set it into the control structure * to used in the time period calculation @@ -496,7 +496,7 @@ EXPORT_SYMBOL_GPL(edac_device_alloc_index); */ int edac_device_add_device(struct edac_device_ctl_info *edac_dev) { - debugf0("%s()\n", __func__); + debugf0("\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -570,7 +570,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev) { struct edac_device_ctl_info *edac_dev; - debugf0("%s()\n", __func__); + debugf0("\n"); mutex_lock(&device_ctls_mutex); diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index b4ea185ccebf..1cee83ec35fe 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -202,7 +202,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj) { struct edac_device_ctl_info *edac_dev = to_edacdev(kobj); - debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx); + debugf4("control index=%d\n", edac_dev->dev_idx); /* decrement the EDAC CORE module ref count */ module_put(edac_dev->owner); @@ -233,12 +233,12 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) struct bus_type *edac_subsys; int err; - debugf1("%s()\n", __func__); + debugf1("\n"); /* get the /sys/devices/system/edac reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys error\n", __func__); + debugf1("no edac_subsys error\n"); err = -ENODEV; goto err_out; } @@ -264,8 +264,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) &edac_subsys->dev_root->kobj, "%s", edac_dev->name); if (err) { - debugf1("%s()Failed to register '.../edac/%s'\n", - __func__, edac_dev->name); + debugf1("Failed to register '.../edac/%s'\n", + edac_dev->name); goto err_kobj_reg; } kobject_uevent(&edac_dev->kobj, KOBJ_ADD); @@ -274,8 +274,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) * edac_device_unregister_sysfs_main_kobj() must be used */ - debugf4("%s() Registered '.../edac/%s' kobject\n", - __func__, edac_dev->name); + debugf4("Registered '.../edac/%s' kobject\n", + edac_dev->name); return 0; @@ -296,9 +296,9 @@ err_out: */ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) { - debugf0("%s()\n", __func__); - debugf4("%s() name of kobject is: %s\n", - __func__, kobject_name(&dev->kobj)); + debugf0("\n"); + debugf4("name of kobject is: %s\n", + kobject_name(&dev->kobj)); /* * Unregister the edac device's kobject and @@ -336,7 +336,7 @@ static void edac_device_ctrl_instance_release(struct kobject *kobj) { struct edac_device_instance *instance; - debugf1("%s()\n", __func__); + debugf1("\n"); /* map from this kobj to the main control struct * and then dec the main kobj count @@ -442,7 +442,7 @@ static void edac_device_ctrl_block_release(struct kobject *kobj) { struct edac_device_block *block; - debugf1("%s()\n", __func__); + debugf1("\n"); /* get the container of the kobj */ block = to_block(kobj); @@ -524,10 +524,10 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; - debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n", - __func__, instance->name, instance, block->name, block); - debugf4("%s() block kobj=%p block kobj->parent=%p\n", - __func__, &block->kobj, &block->kobj.parent); + debugf4("Instance '%s' inst_p=%p block '%s' block_p=%p\n", + instance->name, instance, block->name, block); + debugf4("block kobj=%p block kobj->parent=%p\n", + &block->kobj, &block->kobj.parent); /* init this block's kobject */ memset(&block->kobj, 0, sizeof(struct kobject)); @@ -546,8 +546,8 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, &instance->kobj, "%s", block->name); if (err) { - debugf1("%s() Failed to register instance '%s'\n", - __func__, block->name); + debugf1("Failed to register instance '%s'\n", + block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; @@ -560,9 +560,8 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { - debugf4("%s() creating block attrib='%s' " + debugf4("creating block attrib='%s' " "attrib->%p to kobj=%p\n", - __func__, sysfs_attrib->attr.name, sysfs_attrib, &block->kobj); @@ -647,14 +646,14 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl, &edac_dev->kobj, "%s", instance->name); if (err != 0) { - debugf2("%s() Failed to register instance '%s'\n", - __func__, instance->name); + debugf2("Failed to register instance '%s'\n", + instance->name); kobject_put(main_kobj); goto err_out; } - debugf4("%s() now register '%d' blocks for instance %d\n", - __func__, instance->nr_blocks, idx); + debugf4("now register '%d' blocks for instance %d\n", + instance->nr_blocks, idx); /* register all blocks of this instance */ for (i = 0; i < instance->nr_blocks; i++) { @@ -670,8 +669,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, } kobject_uevent(&instance->kobj, KOBJ_ADD); - debugf4("%s() Registered instance %d '%s' kobject\n", - __func__, idx, instance->name); + debugf4("Registered instance %d '%s' kobject\n", + idx, instance->name); return 0; @@ -715,7 +714,7 @@ static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev) int i, j; int err; - debugf0("%s()\n", __func__); + debugf0("\n"); /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) { @@ -817,12 +816,12 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) int err; struct kobject *edac_kobj = &edac_dev->kobj; - debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx); + debugf0("idx=%d\n", edac_dev->dev_idx); /* go create any main attributes callers wants */ err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { - debugf0("%s() failed to add sysfs attribs\n", __func__); + debugf0("failed to add sysfs attribs\n"); goto err_out; } @@ -832,8 +831,8 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { - debugf0("%s() sysfs_create_link() returned err= %d\n", - __func__, err); + debugf0("sysfs_create_link() returned err= %d\n", + err); goto err_remove_main_attribs; } @@ -843,14 +842,14 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) */ err = edac_device_create_instances(edac_dev); if (err) { - debugf0("%s() edac_device_create_instances() " - "returned err= %d\n", __func__, err); + debugf0("edac_device_create_instances() " + "returned err= %d\n", err); goto err_remove_link; } - debugf4("%s() create-instances done, idx=%d\n", - __func__, edac_dev->dev_idx); + debugf4("create-instances done, idx=%d\n", + edac_dev->dev_idx); return 0; @@ -873,7 +872,7 @@ err_out: */ void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* remove any main attributes for this device */ edac_device_remove_main_sysfs_attributes(edac_dev); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index db2ba31ba2b1..4df9c4ac63c3 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -246,18 +246,18 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers); for (i = 0; i < n_layers; i++) { count *= layers[i].size; - debugf4("%s: errcount layer %d size %d\n", __func__, i, count); + debugf4("errcount layer %d size %d\n", i, count); ce_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); ue_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); tot_errcount += 2 * count; } - debugf4("%s: allocating %d error counters\n", __func__, tot_errcount); + debugf4("allocating %d error counters\n", tot_errcount); pvt = edac_align_ptr(&ptr, sz_pvt, 1); size = ((unsigned long)pvt) + sz_pvt; - debugf1("%s(): allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", - __func__, size, + debugf1("allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", + size, tot_dimms, per_rank ? "ranks" : "dimms", tot_csrows * tot_channels); @@ -326,7 +326,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, memset(&pos, 0, sizeof(pos)); row = 0; chn = 0; - debugf4("%s: initializing %d %s\n", __func__, tot_dimms, + debugf4("initializing %d %s\n", tot_dimms, per_rank ? "ranks" : "dimms"); for (i = 0; i < tot_dimms; i++) { chan = mci->csrows[row]->channels[chn]; @@ -340,8 +340,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->dimms[off] = dimm; dimm->mci = mci; - debugf2("%s: %d: %s%i (%d:%d:%d): row %d, chan %d\n", __func__, - i, per_rank ? "rank" : "dimm", off, + debugf2("%d: %s%i (%d:%d:%d): row %d, chan %d\n", i, + per_rank ? "rank" : "dimm", off, pos[0], pos[1], pos[2], row, chn); /* @@ -427,7 +427,7 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc); */ void edac_mc_free(struct mem_ctl_info *mci) { - debugf1("%s()\n", __func__); + debugf1("\n"); /* the mci instance is freed here, when the sysfs object is dropped */ edac_unregister_sysfs(mci); @@ -447,7 +447,7 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev) struct mem_ctl_info *mci; struct list_head *item; - debugf3("%s()\n", __func__); + debugf3("\n"); list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); @@ -515,7 +515,7 @@ static void edac_mc_workq_function(struct work_struct *work_req) */ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* if this instance is not in the POLL state, then simply return */ if (mci->op_state != OP_RUNNING_POLL) @@ -542,8 +542,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) status = cancel_delayed_work(&mci->work); if (status == 0) { - debugf0("%s() not canceled, flush the queue\n", - __func__); + debugf0("not canceled, flush the queue\n"); /* workq instance might be running, wait for it */ flush_workqueue(edac_workqueue); @@ -690,7 +689,7 @@ EXPORT_SYMBOL(edac_mc_find); /* FIXME - should a warning be printed if no error detection? correction? */ int edac_mc_add_mc(struct mem_ctl_info *mci) { - debugf0("%s()\n", __func__); + debugf0("\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -761,7 +760,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); mutex_lock(&mem_ctls_mutex); @@ -799,7 +798,7 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, void *virt_addr; unsigned long flags = 0; - debugf3("%s()\n", __func__); + debugf3("\n"); /* ECC error page was not in our memory. Ignore it. */ if (!pfn_valid(page)) @@ -829,7 +828,7 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) struct csrow_info **csrows = mci->csrows; int row, i, j, n; - debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); + debugf1("MC%d: 0x%lx\n", mci->mc_idx, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { @@ -842,8 +841,8 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) if (n == 0) continue; - debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) " - "mask(0x%lx)\n", mci->mc_idx, __func__, + debugf3("MC%d: first(0x%lx) page(0x%lx) last(0x%lx) " + "mask(0x%lx)\n", mci->mc_idx, csrow->first_page, page, csrow->last_page, csrow->page_mask); @@ -1049,7 +1048,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, u16 error_count; /* FIXME: make it a parameter */ u8 grain_bits; - debugf3("MC%d: %s()\n", mci->mc_idx, __func__); + debugf3("MC%d\n", mci->mc_idx); /* * Check if the event report is consistent and if the memory @@ -1127,8 +1126,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, * get csrow/channel of the DIMM, in order to allow * incrementing the compat API counters */ - debugf4("%s: %s csrows map: (%d,%d)\n", - __func__, + debugf4("%s csrows map: (%d,%d)\n", mci->mem_is_per_rank ? "rank" : "dimm", dimm->csrow, dimm->cschannel); @@ -1147,8 +1145,8 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, if (!enable_per_layer_report) { strcpy(label, "any memory"); } else { - debugf4("%s: csrow/channel to increment: (%d,%d)\n", - __func__, row, chan); + debugf4("csrow/channel to increment: (%d,%d)\n", + row, chan); if (p == label) strcpy(label, "unknown memory"); if (type == HW_EVENT_ERR_CORRECTED) { diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 87b8d7d6385f..f72de8ba6a3b 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -376,8 +376,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, dev_set_name(&csrow->dev, "csrow%d", index); dev_set_drvdata(&csrow->dev, csrow); - debugf0("%s(): creating (virtual) csrow node %s\n", __func__, - dev_name(&csrow->dev)); + debugf0("creating (virtual) csrow node %s\n", dev_name(&csrow->dev)); err = device_add(&csrow->dev); if (err < 0) @@ -623,8 +622,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, err = device_add(&dimm->dev); - debugf0("%s(): creating rank/dimm device %s\n", __func__, - dev_name(&dimm->dev)); + debugf0("creating rank/dimm device %s\n", dev_name(&dimm->dev)); return err; } @@ -981,8 +979,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) dev_set_drvdata(&mci->dev, mci); pm_runtime_forbid(&mci->dev); - debugf0("%s(): creating device %s\n", __func__, - dev_name(&mci->dev)); + debugf0("creating device %s\n", dev_name(&mci->dev)); err = device_add(&mci->dev); if (err < 0) { bus_unregister(&mci->bus); @@ -999,8 +996,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) if (dimm->nr_pages == 0) continue; #ifdef CONFIG_EDAC_DEBUG - debugf1("%s creating dimm%d, located at ", - __func__, i); + debugf1("creating dimm%d, located at ", + i); if (edac_debug_level >= 1) { int lay; for (lay = 0; lay < mci->n_layers; lay++) @@ -1012,8 +1009,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) #endif err = edac_create_dimm_object(mci, dimm, i); if (err) { - debugf1("%s() failure: create dimm %d obj\n", - __func__, i); + debugf1("failure: create dimm %d obj\n", + i); goto fail; } } @@ -1051,7 +1048,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { int i; - debugf0("%s()\n", __func__); + debugf0("\n"); #ifdef CONFIG_EDAC_DEBUG debugfs_remove(mci->debugfs); @@ -1064,8 +1061,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; - debugf0("%s(): removing device %s\n", __func__, - dev_name(&dimm->dev)); + debugf0("removing device %s\n", dev_name(&dimm->dev)); put_device(&dimm->dev); device_del(&dimm->dev); } @@ -1105,7 +1101,7 @@ int __init edac_mc_sysfs_init(void) /* get the /sys/devices/system/edac subsys reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys\n", __func__); + debugf1("no edac_subsys\n"); return -EINVAL; } diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 8735a0d3ed0c..9de248492908 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -113,7 +113,7 @@ error: */ static void __exit edac_exit(void) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* tear down the various subsystems */ edac_workqueue_teardown(); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index f1ac86649886..51dd4e05a76f 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -45,7 +45,7 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, void *p = NULL, *pvt; unsigned int size; - debugf1("%s()\n", __func__); + debugf1("\n"); pci = edac_align_ptr(&p, sizeof(*pci), 1); pvt = edac_align_ptr(&p, 1, sz_pvt); @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); */ void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) { - debugf1("%s()\n", __func__); + debugf1("\n"); edac_pci_remove_sysfs(pci); } @@ -97,7 +97,7 @@ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) struct edac_pci_ctl_info *pci; struct list_head *item; - debugf1("%s()\n", __func__); + debugf1("\n"); list_for_each(item, &edac_pci_list) { pci = list_entry(item, struct edac_pci_ctl_info, link); @@ -122,7 +122,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) struct list_head *item, *insert_before; struct edac_pci_ctl_info *rover; - debugf1("%s()\n", __func__); + debugf1("\n"); insert_before = &edac_pci_list; @@ -226,7 +226,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) int msec; unsigned long delay; - debugf3("%s() checking\n", __func__); + debugf3("checking\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -261,7 +261,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, unsigned int msec) { - debugf0("%s()\n", __func__); + debugf0("\n"); INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); queue_delayed_work(edac_workqueue, &pci->work, @@ -276,7 +276,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { int status; - debugf0("%s()\n", __func__); + debugf0("\n"); status = cancel_delayed_work(&pci->work); if (status == 0) @@ -293,7 +293,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value) { - debugf0("%s()\n", __func__); + debugf0("\n"); edac_pci_workq_teardown(pci); @@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_index); */ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) { - debugf0("%s()\n", __func__); + debugf0("\n"); pci->pci_idx = edac_idx; pci->start_time = jiffies; @@ -393,7 +393,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) { struct edac_pci_ctl_info *pci; - debugf0("%s()\n", __func__); + debugf0("\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -430,7 +430,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device); */ static void edac_pci_generic_check(struct edac_pci_ctl_info *pci) { - debugf4("%s()\n", __func__); + debugf4("\n"); edac_pci_do_parity_check(); } @@ -475,7 +475,7 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, pdata->edac_idx = edac_pci_idx++; if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + debugf3("failed edac_pci_add_device()\n"); edac_pci_free_ctl_info(pci); return NULL; } @@ -491,7 +491,7 @@ EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); */ void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) { - debugf0("%s() pci mod=%s\n", __func__, pci->mod_name); + debugf0("pci mod=%s\n", pci->mod_name); edac_pci_del_device(pci->dev); edac_pci_free_ctl_info(pci); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 97f5064e3992..6678216a7cbc 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -78,7 +78,7 @@ static void edac_pci_instance_release(struct kobject *kobj) { struct edac_pci_ctl_info *pci; - debugf0("%s()\n", __func__); + debugf0("\n"); /* Form pointer to containing struct, the pci control struct */ pci = to_instance(kobj); @@ -161,7 +161,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) struct kobject *main_kobj; int err; - debugf0("%s()\n", __func__); + debugf0("\n"); /* First bump the ref count on the top main kobj, which will * track the number of PCI instances we have, and thus nest @@ -177,14 +177,14 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance, edac_pci_top_main_kobj, "pci%d", idx); if (err != 0) { - debugf2("%s() failed to register instance pci%d\n", - __func__, idx); + debugf2("failed to register instance pci%d\n", + idx); kobject_put(edac_pci_top_main_kobj); goto error_out; } kobject_uevent(&pci->kobj, KOBJ_ADD); - debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); + debugf1("Register instance 'pci%d' kobject\n", idx); return 0; @@ -201,7 +201,7 @@ error_out: static void edac_pci_unregister_sysfs_instance_kobj( struct edac_pci_ctl_info *pci) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* Unregister the instance kobject and allow its release * function release the main reference count and then @@ -317,7 +317,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { */ static void edac_pci_release_main_kobj(struct kobject *kobj) { - debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); + debugf0("here to module_put(THIS_MODULE)\n"); kfree(kobj); @@ -345,7 +345,7 @@ static int edac_pci_main_kobj_setup(void) int err; struct bus_type *edac_subsys; - debugf0("%s()\n", __func__); + debugf0("\n"); /* check and count if we have already created the main kobject */ if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) @@ -356,7 +356,7 @@ static int edac_pci_main_kobj_setup(void) */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys\n", __func__); + debugf1("no edac_subsys\n"); err = -ENODEV; goto decrement_count_fail; } @@ -366,7 +366,7 @@ static int edac_pci_main_kobj_setup(void) * level main kobj for EDAC PCI */ if (!try_module_get(THIS_MODULE)) { - debugf1("%s() try_module_get() failed\n", __func__); + debugf1("try_module_get() failed\n"); err = -ENODEV; goto mod_get_fail; } @@ -421,15 +421,14 @@ decrement_count_fail: */ static void edac_pci_main_kobj_teardown(void) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* Decrement the count and only if no more controller instances * are connected perform the unregisteration of the top level * main kobj */ if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { - debugf0("%s() called kobject_put on main kobj\n", - __func__); + debugf0("called kobject_put on main kobj\n"); kobject_put(edac_pci_top_main_kobj); } edac_put_sysfs_subsys(); @@ -446,7 +445,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) int err; struct kobject *edac_kobj = &pci->kobj; - debugf0("%s() idx=%d\n", __func__, pci->pci_idx); + debugf0("idx=%d\n", pci->pci_idx); /* create the top main EDAC PCI kobject, IF needed */ err = edac_pci_main_kobj_setup(); @@ -460,8 +459,8 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) { - debugf0("%s() sysfs_create_link() returned err= %d\n", - __func__, err); + debugf0("sysfs_create_link() returned err= %d\n", + err); goto symlink_fail; } @@ -484,7 +483,7 @@ unregister_cleanup: */ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) { - debugf0("%s() index=%d\n", __func__, pci->pci_idx); + debugf0("index=%d\n", pci->pci_idx); /* Remove the symlink */ sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); @@ -496,7 +495,7 @@ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) * if this 'pci' is the last instance. * If it is, the main kobject will be unregistered as a result */ - debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__); + debugf0("calling edac_pci_main_kobj_teardown()\n"); edac_pci_main_kobj_teardown(); } @@ -671,7 +670,7 @@ void edac_pci_do_parity_check(void) { int before_count; - debugf3("%s()\n", __func__); + debugf3("\n"); /* if policy has PCI check off, leave now */ if (!check_pci_errors) diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 812213da7f91..67975ba252fa 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -275,7 +275,7 @@ static void i3000_check(struct mem_ctl_info *mci) { struct i3000_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); i3000_get_error_info(mci, &info); i3000_process_error_info(mci, &info, 1); } @@ -322,7 +322,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) unsigned long mchbar; void __iomem *window; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar); mchbar &= I3000_MCHBAR_MASK; @@ -366,7 +366,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + debugf3("MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -399,8 +399,8 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); if (interleaved) cumul_size <<= 1; - debugf3("MC: %s(): (%d) cumul_size 0x%x\n", - __func__, i, cumul_size); + debugf3("MC: (%d) cumul_size 0x%x\n", + i, cumul_size); if (cumul_size == last_cumul_size) continue; @@ -429,7 +429,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("MC: failed edac_mc_add_mc()\n"); goto fail; } @@ -445,7 +445,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + debugf3("MC: success\n"); return 0; fail: @@ -461,7 +461,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -477,7 +477,7 @@ static void __devexit i3000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); if (i3000_pci) edac_pci_release_generic_ctl(i3000_pci); @@ -511,7 +511,7 @@ static int __init i3000_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -552,7 +552,7 @@ fail0: static void __exit i3000_exit(void) { - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); pci_unregister_driver(&i3000_driver); if (!i3000_registered) { diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index c5f0fb31d5e0..9698ca39e38a 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -245,7 +245,7 @@ static void i3200_check(struct mem_ctl_info *mci) { struct i3200_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); i3200_get_and_clear_error_info(mci, &info); i3200_process_error_info(mci, &info); } @@ -332,7 +332,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) void __iomem *window; struct i3200_priv *priv; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); window = i3200_map_mchbar(pdev); if (!window) @@ -352,7 +352,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + debugf3("MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -403,12 +403,12 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + debugf3("MC: success\n"); return 0; fail: @@ -424,7 +424,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -441,7 +441,7 @@ static void __devexit i3200_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i3200_priv *priv; - debugf0("%s()\n", __func__); + debugf0("\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -475,7 +475,7 @@ static int __init i3200_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -516,7 +516,7 @@ fail0: static void __exit i3200_exit(void) { - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); pci_unregister_driver(&i3200_driver); if (!i3200_registered) { diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index a7da4c7ad7fa..4a5ca5229d5f 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -779,7 +779,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci) static void i5000_check_error(struct mem_ctl_info *mci) { struct i5000_error_info info; - debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + debugf4("MC%d\n", mci->mc_idx); i5000_get_error_info(mci, &info); i5000_process_error_info(mci, &info, 1); } @@ -1363,9 +1363,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) int num_channels; int num_dimms_per_channel; - debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, __func__, - pdev->bus->number, + debugf0("MC: %s(), pdev bus %u dev=0x%x fn=0x%x\n", + __FILE__, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ @@ -1388,8 +1387,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, &num_channels); - debugf0("MC: %s(): Number of Branches=2 Channels= %d DIMMS= %d\n", - __func__, num_channels, num_dimms_per_channel); + debugf0("MC: Number of Branches=2 Channels= %d DIMMS= %d\n", + num_channels, num_dimms_per_channel); /* allocate a new MC control structure */ @@ -1406,7 +1405,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); + debugf0("MC: %s(): mci = %p\n", __FILE__, mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1449,8 +1448,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", - __FILE__, __func__); + debugf0("MC: %s(): failed edac_mc_add_mc()\n", + __FILE__); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1494,7 +1493,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + debugf0("MC: %s()\n", __FILE__); /* wake up device */ rc = pci_enable_device(pdev); @@ -1513,7 +1512,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + debugf0("%s()\n", __FILE__); if (i5000_pci) edac_pci_release_generic_ctl(i5000_pci); @@ -1559,7 +1558,7 @@ static int __init i5000_init(void) { int pci_rc; - debugf2("MC: %s: %s()\n", __FILE__, __func__); + debugf2("MC: %s()\n", __FILE__); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1575,7 +1574,7 @@ static int __init i5000_init(void) */ static void __exit i5000_exit(void) { - debugf2("MC: %s: %s()\n", __FILE__, __func__); + debugf2("MC: %s()\n", __FILE__); pci_unregister_driver(&i5000_driver); } diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 0570cf3d2563..be1880de33a6 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -700,7 +700,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci) static void i5400_check_error(struct mem_ctl_info *mci) { struct i5400_error_info info; - debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + debugf4("MC%d\n", mci->mc_idx); i5400_get_error_info(mci, &info); i5400_process_error_info(mci, &info); } @@ -1203,8 +1203,7 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) size_mb = pvt->dimm_info[slot][channel].megabytes; - debugf2("%s: dimm (branch %d channel %d slot %d): %d.%03d GB\n", - __func__, + debugf2("dimm (branch %d channel %d slot %d): %d.%03d GB\n", channel / 2, channel % 2, slot, size_mb / 1000, size_mb % 1000); @@ -1270,9 +1269,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (dev_idx >= ARRAY_SIZE(i5400_devs)) return -EINVAL; - debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, __func__, - pdev->bus->number, + debugf0("MC: %s(), pdev bus %u dev=0x%x fn=0x%x\n", + __FILE__, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ @@ -1297,7 +1295,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); + debugf0("MC: %s(): mci = %p\n", __FILE__, mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1340,8 +1338,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", - __FILE__, __func__); + debugf0("MC: %s(): failed edac_mc_add_mc()\n", + __FILE__); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1385,7 +1383,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + debugf0("MC: %s()\n", __FILE__); /* wake up device */ rc = pci_enable_device(pdev); @@ -1404,7 +1402,7 @@ static void __devexit i5400_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + debugf0("%s()\n", __FILE__); if (i5400_pci) edac_pci_release_generic_ctl(i5400_pci); @@ -1450,7 +1448,7 @@ static int __init i5400_init(void) { int pci_rc; - debugf2("MC: %s: %s()\n", __FILE__, __func__); + debugf2("MC: %s()\n", __FILE__); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1466,7 +1464,7 @@ static int __init i5400_init(void) */ static void __exit i5400_exit(void) { - debugf2("MC: %s: %s()\n", __FILE__, __func__); + debugf2("MC: %s()\n", __FILE__); pci_unregister_driver(&i5400_driver); } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index db84456e65d9..20435ee47077 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1032,8 +1032,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (rc == -EIO) return rc; - debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __func__, + debugf0("MC: pdev bus %u dev=0x%x fn=0x%x\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); @@ -1055,7 +1054,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (mci == NULL) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + debugf0("MC: mci = %p\n", mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1099,8 +1098,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf0("MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1142,7 +1140,7 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; char *tmp; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("\n"); if (i7300_pci) edac_pci_release_generic_ctl(i7300_pci); @@ -1189,7 +1187,7 @@ static int __init i7300_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1204,7 +1202,7 @@ static int __init i7300_init(void) */ static void __exit i7300_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); pci_unregister_driver(&i7300_driver); } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index c29944fbb7d8..f851a433d620 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -824,7 +824,7 @@ static ssize_t i7core_inject_store_##param( \ long value; \ int rc; \ \ - debugf1("%s()\n", __func__); \ + debugf1("\n"); \ pvt = mci->pvt_info; \ \ if (pvt->inject.enable) \ @@ -852,7 +852,7 @@ static ssize_t i7core_inject_show_##param( \ struct i7core_pvt *pvt; \ \ pvt = mci->pvt_info; \ - debugf1("%s() pvt=%p\n", __func__, pvt); \ + debugf1("pvt=%p\n", pvt); \ if (pvt->inject.param < 0) \ return sprintf(data, "any\n"); \ else \ @@ -1059,7 +1059,7 @@ static ssize_t i7core_show_counter_##param( \ struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt = mci->pvt_info; \ \ - debugf1("%s()\n", __func__); \ + debugf1("\n"); \ if (!pvt->ce_count_available || (pvt->is_registered)) \ return sprintf(data, "data unavailable\n"); \ return sprintf(data, "%lu\n", \ @@ -1190,8 +1190,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) dev_set_name(pvt->addrmatch_dev, "inject_addrmatch"); dev_set_drvdata(pvt->addrmatch_dev, mci); - debugf1("%s(): creating %s\n", __func__, - dev_name(pvt->addrmatch_dev)); + debugf1("creating %s\n", dev_name(pvt->addrmatch_dev)); rc = device_add(pvt->addrmatch_dev); if (rc < 0) @@ -1213,8 +1212,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) dev_set_name(pvt->chancounts_dev, "all_channel_counts"); dev_set_drvdata(pvt->chancounts_dev, mci); - debugf1("%s(): creating %s\n", __func__, - dev_name(pvt->chancounts_dev)); + debugf1("creating %s\n", dev_name(pvt->chancounts_dev)); rc = device_add(pvt->chancounts_dev); if (rc < 0) @@ -1254,7 +1252,7 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev) { int i; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("\n"); for (i = 0; i < i7core_dev->n_devs; i++) { struct pci_dev *pdev = i7core_dev->pdev[i]; if (!pdev) @@ -1652,7 +1650,7 @@ static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci) int new0, new1, new2; if (!pvt->pci_mcr[4]) { - debugf0("%s MCR registers not found\n", __func__); + debugf0("MCR registers not found\n"); return; } @@ -2190,8 +2188,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) struct i7core_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: " __FILE__ ": %s(): dev = %p\n", - __func__, &i7core_dev->pdev[0]->dev); + debugf0("MC: dev = %p\n", &i7core_dev->pdev[0]->dev); i7core_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -2199,8 +2196,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) pvt = mci->pvt_info; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &i7core_dev->pdev[0]->dev); + debugf0("MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); /* Disable scrubrate setting */ if (pvt->enable_scrub) @@ -2241,8 +2237,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &i7core_dev->pdev[0]->dev); + debugf0("MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -2285,8 +2280,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf0("MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -2295,8 +2289,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) goto fail0; } if (i7core_create_sysfs_devices(mci)) { - debugf0("MC: " __FILE__ - ": %s(): failed to create sysfs nodes\n", __func__); + debugf0("MC: failed to create sysfs nodes\n"); edac_mc_del_mc(mci->pdev); rc = -EINVAL; goto fail0; @@ -2402,7 +2395,7 @@ static void __devexit i7core_remove(struct pci_dev *pdev) { struct i7core_dev *i7core_dev; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -2451,7 +2444,7 @@ static int __init i7core_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -2476,7 +2469,7 @@ static int __init i7core_init(void) */ static void __exit i7core_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); pci_unregister_driver(&i7core_driver); } diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 0f2751bf3ffe..c43214fdf2d8 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -178,7 +178,7 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci) { struct i82443bxgx_edacmc_error_info info; - debugf1("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + debugf1("MC%d\n", mci->mc_idx); i82443bxgx_edacmc_get_error_info(mci, &info); i82443bxgx_edacmc_process_error_info(mci, &info, 1); } @@ -201,13 +201,13 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, dimm = csrow->channels[0]->dimm; pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); - debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", - mci->mc_idx, __FILE__, __func__, index, drbar); + debugf1("MC%d: Row=%d DRB = %#0x\n", + mci->mc_idx,index, drbar); row_high_limit = ((u32) drbar << 23); /* find the DRAM Chip Select Base address and mask */ - debugf1("MC%d: %s: %s() Row=%d, " + debugf1("MC%d: Row=%d, " "Boundary Address=%#0x, Last = %#0x\n", - mci->mc_idx, __FILE__, __func__, index, row_high_limit, + mci->mc_idx, index, row_high_limit, row_high_limit_last); /* 440GX goes to 2GB, represented with a DRB of 0. */ @@ -241,7 +241,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) enum mem_type mtype; enum edac_type edac_mode; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + debugf0("MC: %s()\n", __FILE__); /* Something is really hosed if PCI config space reads from * the MC aren't working. @@ -259,7 +259,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); + debugf0("MC: %s(): mci = %p\n", __FILE__, mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -305,8 +305,8 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) edac_mode = EDAC_SECDED; break; default: - debugf0("%s(): Unknown/reserved ECC state " - "in NBXCFG register!\n", __func__); + debugf0("Unknown/reserved ECC state " + "in NBXCFG register!\n"); edac_mode = EDAC_UNKNOWN; break; } @@ -330,7 +330,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) mci->ctl_page_to_phys = NULL; if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail; } @@ -345,7 +345,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("MC: %s: %s(): success\n", __FILE__, __func__); + debugf3("MC: %s(): success\n", __FILE__); return 0; fail: @@ -361,7 +361,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + debugf0("MC: %s()\n", __FILE__); /* don't need to call pci_enable_device() */ rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); @@ -376,7 +376,7 @@ static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + debugf0("%s()\n", __FILE__); if (i82443bxgx_pci) edac_pci_release_generic_ctl(i82443bxgx_pci); diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 06a3c8d26d19..d4ec21db22ba 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -136,7 +136,7 @@ static void i82860_check(struct mem_ctl_info *mci) { struct i82860_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); i82860_get_error_info(mci, &info); i82860_process_error_info(mci, &info, 1); } @@ -167,7 +167,7 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) pci_read_config_word(pdev, I82860_GBA + index * 2, &value); cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + debugf3("(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) @@ -210,7 +210,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -229,7 +229,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail; } @@ -245,7 +245,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; @@ -260,7 +260,7 @@ static int __devinit i82860_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + debugf0("\n"); i82860_printk(KERN_INFO, "i82860 init one\n"); if (pci_enable_device(pdev) < 0) @@ -278,7 +278,7 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); if (i82860_pci) edac_pci_release_generic_ctl(i82860_pci); @@ -311,7 +311,7 @@ static int __init i82860_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + debugf3("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -352,7 +352,7 @@ fail0: static void __exit i82860_exit(void) { - debugf3("%s()\n", __func__); + debugf3("\n"); pci_unregister_driver(&i82860_driver); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 97fd6b769c84..4ded498047f7 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -263,7 +263,7 @@ static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); i82875p_get_error_info(mci, &info); i82875p_process_error_info(mci, &info, 1); } @@ -371,7 +371,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, value = readb(ovrfl_window + I82875P_DRB + index); cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + debugf3("(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -405,7 +405,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) u32 nr_chans; struct i82875p_error_info discard; - debugf0("%s()\n", __func__); + debugf0("\n"); ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); @@ -426,7 +426,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -437,7 +437,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); + debugf3("init pvt\n"); pvt = (struct i82875p_pvt *)mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; pvt->ovrfl_window = ovrfl_window; @@ -448,7 +448,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail1; } @@ -464,7 +464,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail1: @@ -485,7 +485,7 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + debugf0("\n"); i82875p_printk(KERN_INFO, "i82875p init one\n"); if (pci_enable_device(pdev) < 0) @@ -504,7 +504,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82875p_pvt *pvt = NULL; - debugf0("%s()\n", __func__); + debugf0("\n"); if (i82875p_pci) edac_pci_release_generic_ctl(i82875p_pci); @@ -550,7 +550,7 @@ static int __init i82875p_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + debugf3("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -593,7 +593,7 @@ fail0: static void __exit i82875p_exit(void) { - debugf3("%s()\n", __func__); + debugf3("\n"); i82875p_remove_one(mci_pdev); pci_dev_put(mci_pdev); diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 4d239ab31e34..91b9e33fff27 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -331,7 +331,7 @@ static void i82975x_check(struct mem_ctl_info *mci) { struct i82975x_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); i82975x_get_error_info(mci, &info); i82975x_process_error_info(mci, &info, 1); } @@ -406,7 +406,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ if (csrow->nr_channels > 1) cumul_size <<= 1; - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + debugf3("(%d) cumul_size 0x%x\n", index, cumul_size); nr_pages = cumul_size - last_cumul_size; @@ -489,11 +489,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) u8 c1drb[4]; #endif - debugf0("%s()\n", __func__); + debugf0("\n"); pci_read_config_dword(pdev, I82975X_MCHBAR, &mchbar); if (!(mchbar & 1)) { - debugf3("%s(): failed, MCHBAR disabled!\n", __func__); + debugf3("failed, MCHBAR disabled!\n"); goto fail0; } mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ @@ -558,7 +558,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) goto fail1; } - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -569,7 +569,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82975x_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); + debugf3("init pvt\n"); pvt = (struct i82975x_pvt *) mci->pvt_info; pvt->mch_window = mch_window; i82975x_init_csrows(mci, pdev, mch_window); @@ -578,12 +578,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) /* finalize this instance of memory controller with edac core */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail2; } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail2: @@ -601,7 +601,7 @@ static int __devinit i82975x_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + debugf0("\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -619,7 +619,7 @@ static void __devexit i82975x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82975x_pvt *pvt; - debugf0("%s()\n", __func__); + debugf0("\n"); mci = edac_mc_del_mc(&pdev->dev); if (mci == NULL) @@ -655,7 +655,7 @@ static int __init i82975x_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + debugf3("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -697,7 +697,7 @@ fail0: static void __exit i82975x_exit(void) { - debugf3("%s()\n", __func__); + debugf3("\n"); pci_unregister_driver(&i82975x_driver); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 0db6f1e84656..e01c678cb6a7 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -280,7 +280,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + debugf3("failed edac_pci_add_device()\n"); goto err; } @@ -303,7 +303,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_pci_err_probe); - debugf3("%s(): success\n", __func__); + debugf3("success\n"); printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); return 0; @@ -321,7 +321,7 @@ static int mpc85xx_pci_err_remove(struct platform_device *op) struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; - debugf0("%s()\n", __func__); + debugf0("\n"); out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, orig_pci_err_cap_dr); @@ -582,7 +582,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + debugf3("failed edac_device_add_device()\n"); goto err; } @@ -610,7 +610,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) devres_remove_group(&op->dev, mpc85xx_l2_err_probe); - debugf3("%s(): success\n", __func__); + debugf3("success\n"); printk(KERN_INFO EDAC_MOD_STR " L2 err registered\n"); return 0; @@ -628,7 +628,7 @@ static int mpc85xx_l2_err_remove(struct platform_device *op) struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; - debugf0("%s()\n", __func__); + debugf0("\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0); @@ -1037,7 +1037,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) goto err; } - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 | MEM_FLAG_DDR | MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -1063,13 +1063,13 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0); if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto err; } if (mpc85xx_create_sysfs_attributes(mci)) { edac_mc_del_mc(mci->pdev); - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto err; } @@ -1103,7 +1103,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_mc_err_probe); - debugf3("%s(): success\n", __func__); + debugf3("success\n"); printk(KERN_INFO EDAC_MOD_STR " MC err registered\n"); return 0; @@ -1121,7 +1121,7 @@ static int mpc85xx_mc_err_remove(struct platform_device *op) struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; - debugf0("%s()\n", __func__); + debugf0("\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0); diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 3a58ba9158db..25851ef56b5b 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -169,7 +169,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) MV64X60_PCIx_ERR_MASK_VAL); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + debugf3("failed edac_pci_add_device()\n"); goto err; } @@ -194,7 +194,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_pci_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; @@ -210,7 +210,7 @@ static int mv64x60_pci_err_remove(struct platform_device *pdev) { struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + debugf0("\n"); edac_pci_del_device(&pdev->dev); @@ -336,7 +336,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + debugf3("failed edac_device_add_device()\n"); goto err; } @@ -363,7 +363,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_sram_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; @@ -379,7 +379,7 @@ static int mv64x60_sram_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + debugf0("\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -531,7 +531,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + debugf3("failed edac_device_add_device()\n"); goto err; } @@ -558,7 +558,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; @@ -574,7 +574,7 @@ static int mv64x60_cpu_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + debugf0("\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -766,7 +766,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) goto err2; } - debugf3("%s(): init mci\n", __func__); + debugf3("init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; @@ -790,7 +790,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto err; } @@ -815,7 +815,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; @@ -831,7 +831,7 @@ static int mv64x60_mc_err_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + debugf0("\n"); edac_mc_del_mc(&pdev->dev); edac_mc_free(mci); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 445c9ff27b88..872c3b928035 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -205,7 +205,7 @@ static void r82600_check(struct mem_ctl_info *mci) { struct r82600_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); r82600_get_error_info(mci, &info); r82600_process_error_info(mci, &info, 1); } @@ -236,13 +236,13 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); - debugf1("%s() Row=%d DRBA = %#0x\n", __func__, index, drbar); + debugf1("Row=%d DRBA = %#0x\n", index, drbar); row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ - debugf1("%s() Row=%d, Boundary Address=%#0x, Last = %#0x\n", - __func__, index, row_high_limit, row_high_limit_last); + debugf1("Row=%d, Boundary Address=%#0x, Last = %#0x\n", + index, row_high_limit, row_high_limit_last); /* Empty row [p.57] */ if (row_high_limit == row_high_limit_last) @@ -277,14 +277,13 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) u32 sdram_refresh_rate; struct r82600_error_info discard; - debugf0("%s()\n", __func__); + debugf0("\n"); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("%s(): sdram refresh rate = %#0x\n", __func__, - sdram_refresh_rate); - debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); + debugf2("sdram refresh rate = %#0x\n", sdram_refresh_rate); + debugf2("DRAMC register = %#0x\n", dramcr); layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; layers[0].size = R82600_NR_CSROWS; layers[0].is_virt_csrow = true; @@ -295,7 +294,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("%s(): mci = %p\n", __func__, mci); + debugf0("mci = %p\n", mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -311,8 +310,8 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (ecc_enabled(dramcr)) { if (scrub_disabled) - debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " - "%#0x\n", __func__, mci, eapr); + debugf3("mci = %p - Scrubbing disabled! EAP: " + "%#0x\n", mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; @@ -329,15 +328,14 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + debugf3("failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ if (disable_hardware_scrub) { - debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", - __func__); + debugf3("Disabling Hardware Scrub (scrub on error)\n"); pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); } @@ -352,7 +350,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("%s(): success\n", __func__); + debugf3("success\n"); return 0; fail: @@ -364,7 +362,7 @@ fail: static int __devinit r82600_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + debugf0("\n"); /* don't need to call pci_enable_device() */ return r82600_probe1(pdev, ent->driver_data); @@ -374,7 +372,7 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); if (r82600_pci) edac_pci_release_generic_ctl(r82600_pci); diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index efa488357ae6..96efa496db5a 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1064,7 +1064,7 @@ static void sbridge_put_devices(struct sbridge_dev *sbridge_dev) { int i; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("\n"); for (i = 0; i < sbridge_dev->n_devs; i++) { struct pci_dev *pdev = sbridge_dev->pdev[i]; if (!pdev) @@ -1592,8 +1592,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) struct sbridge_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: " __FILE__ ": %s(): dev = %p\n", - __func__, &sbridge_dev->pdev[0]->dev); + debugf0("MC: dev = %p\n", &sbridge_dev->pdev[0]->dev); sbridge_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -1601,8 +1600,8 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) pvt = mci->pvt_info; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &sbridge_dev->pdev[0]->dev); + debugf0("MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); mce_unregister_decode_chain(&sbridge_mce_dec); @@ -1640,8 +1639,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &sbridge_dev->pdev[0]->dev); + debugf0("MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -1676,8 +1675,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf0("MC: failed edac_mc_add_mc()\n"); rc = -EINVAL; goto fail0; } @@ -1755,7 +1753,7 @@ static void __devexit sbridge_remove(struct pci_dev *pdev) { struct sbridge_dev *sbridge_dev; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -1804,7 +1802,7 @@ static int __init sbridge_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1826,7 +1824,7 @@ static int __init sbridge_init(void) */ static void __exit sbridge_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + debugf2("\n"); pci_unregister_driver(&sbridge_driver); } diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index ae699be78b24..70c745422fca 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -243,7 +243,7 @@ static void x38_check(struct mem_ctl_info *mci) { struct x38_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + debugf1("MC%d\n", mci->mc_idx); x38_get_and_clear_error_info(mci, &info); x38_process_error_info(mci, &info); } @@ -331,7 +331,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) bool stacked; void __iomem *window; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); window = x38_map_mchbar(pdev); if (!window) @@ -352,7 +352,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + debugf3("MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -402,12 +402,12 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + debugf3("MC: success\n"); return 0; fail: @@ -423,7 +423,7 @@ static int __devinit x38_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + debugf0("MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -439,7 +439,7 @@ static void __devexit x38_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + debugf0("\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -472,7 +472,7 @@ static int __init x38_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -513,7 +513,7 @@ fail0: static void __exit x38_exit(void) { - debugf3("MC: %s()\n", __func__); + debugf3("MC:\n"); pci_unregister_driver(&x38_driver); if (!x38_registered) { -- GitLab From 7e881856eee8b889b76cd1d8e04ce2fc79b72099 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 28 Apr 2012 16:41:46 -0300 Subject: [PATCH 0454/5711] edac: Use more normal debugging macro style Convert macros to a simpler style and enforce appropriate format checking when not CONFIG_EDAC_DEBUG. Use fmt and __VA_ARGS__, neaten macros. Move some string arrays to the debugfx uses and remove the now unnecessary CONFIG_EDAC_DEBUG variable block definitions. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_core.h | 35 ++++++++++++++++++----------------- drivers/edac/i5000_edac.c | 30 +++++++++++------------------- drivers/edac/i5400_edac.c | 30 ++++++++++-------------------- drivers/edac/i7300_edac.c | 30 ++++++++++-------------------- 4 files changed, 49 insertions(+), 76 deletions(-) diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 740c7e22c023..410738bf30fd 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -71,29 +71,30 @@ extern const char *edac_mem_types[]; #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; -#define edac_debug_printk(level, fmt, arg...) \ - do { \ - if (level <= edac_debug_level) \ - edac_printk(KERN_DEBUG, EDAC_DEBUG, \ - "%s: " fmt, __func__, ##arg); \ - } while (0) - -#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ ) -#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ ) -#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) -#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ ) -#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ ) +#define edac_debug_printk(level, fmt, ...) \ +do { \ + if (level <= edac_debug_level) \ + edac_printk(KERN_DEBUG, EDAC_DEBUG, \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) #else /* !CONFIG_EDAC_DEBUG */ -#define debugf0( ... ) -#define debugf1( ... ) -#define debugf2( ... ) -#define debugf3( ... ) -#define debugf4( ... ) +#define edac_debug_printk(level, fmt, ...) \ +do { \ + if (0) \ + edac_printk(KERN_DEBUG, EDAC_DEBUG, \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) #endif /* !CONFIG_EDAC_DEBUG */ +#define debugf0(fmt, ...) edac_debug_printk(0, fmt, ##__VA_ARGS__) +#define debugf1(fmt, ...) edac_debug_printk(1, fmt, ##__VA_ARGS__) +#define debugf2(fmt, ...) edac_debug_printk(2, fmt, ##__VA_ARGS__) +#define debugf3(fmt, ...) edac_debug_printk(3, fmt, ##__VA_ARGS__) +#define debugf4(fmt, ...) edac_debug_printk(4, fmt, ##__VA_ARGS__) + #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ PCI_DEVICE_ID_ ## vend ## _ ## dev diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 4a5ca5229d5f..0e16db620ad5 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -273,7 +273,7 @@ #define CHANNELS_PER_BRANCH 2 #define MAX_BRANCHES 2 -/* Defines to extract the vaious fields from the +/* Defines to extract the various fields from the * MTRx - Memory Technology Registers */ #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (0x1 << 8)) @@ -287,22 +287,6 @@ #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) -#ifdef CONFIG_EDAC_DEBUG -static char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "reserved" -}; - -static char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /* enables the report of miscellaneous messages as CE errors - default off */ static int misc_messages; @@ -989,8 +973,16 @@ static void decode_mtr(int slot_row, u16 mtr) debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + debugf2("\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "reserved"); + debugf2("\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5000_pvt *pvt, int slot, int channel, diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index be1880de33a6..3004b946c403 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -300,24 +300,6 @@ static inline int extract_fbdchan_indx(u32 x) return (x>>28) & 0x3; } -#ifdef CONFIG_EDAC_DEBUG -/* MTR NUMROW */ -static const char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "65,536 - 16 rows" -}; - -/* MTR NUMCOL */ -static const char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /* Device name and register DID (Device ID) */ struct i5400_dev_info { const char *ctl_name; /* name for this device */ @@ -915,8 +897,16 @@ static void decode_mtr(int slot_row, u16 mtr) debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + debugf2("\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + debugf2("\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5400_pvt *pvt, int dimm, int channel, diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 20435ee47077..7eca688f7885 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -182,24 +182,6 @@ static const u16 mtr_regs[MAX_SLOTS] = { #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) -#ifdef CONFIG_EDAC_DEBUG -/* MTR NUMROW */ -static const char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "65,536 - 16 rows" -}; - -/* MTR NUMCOL */ -static const char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /************************************************ * i7300 Register definitions for error detection ************************************************/ @@ -645,8 +627,16 @@ static int decode_mtr(struct i7300_pvt *pvt, debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANKS(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + debugf2("\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + debugf2("\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes); /* -- GitLab From 956b9ba156dbfdb9cede2b2927ddf8be2233b3a7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 29 Apr 2012 17:08:39 -0300 Subject: [PATCH 0455/5711] edac: Convert debugfX to edac_dbg(X, Use a more common debugging style. Remove __FILE__ uses, add missing newlines, coalesce formats and align arguments. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 270 +++++++++++++++---------------- drivers/edac/amd64_edac_inj.c | 6 +- drivers/edac/amd76x_edac.c | 14 +- drivers/edac/cpc925_edac.c | 22 +-- drivers/edac/e752x_edac.c | 39 +++-- drivers/edac/e7xxx_edac.c | 35 ++-- drivers/edac/edac_core.h | 10 +- drivers/edac/edac_device.c | 47 +++--- drivers/edac/edac_device_sysfs.c | 70 ++++---- drivers/edac/edac_mc.c | 121 +++++++------- drivers/edac/edac_mc_sysfs.c | 37 +++-- drivers/edac/edac_module.c | 2 +- drivers/edac/edac_pci.c | 26 +-- drivers/edac/edac_pci_sysfs.c | 48 +++--- drivers/edac/i3000_edac.c | 25 ++- drivers/edac/i3200_edac.c | 26 +-- drivers/edac/i5000_edac.c | 163 ++++++++++--------- drivers/edac/i5100_edac.c | 4 +- drivers/edac/i5400_edac.c | 165 ++++++++++--------- drivers/edac/i7300_edac.c | 151 +++++++++-------- drivers/edac/i7core_edac.c | 144 ++++++++--------- drivers/edac/i82443bxgx_edac.c | 35 ++-- drivers/edac/i82860_edac.c | 23 ++- drivers/edac/i82875p_edac.c | 27 ++-- drivers/edac/i82975x_edac.c | 29 ++-- drivers/edac/mpc85xx_edac.c | 22 +-- drivers/edac/mv64x60_edac.c | 26 +-- drivers/edac/r82600_edac.c | 30 ++-- drivers/edac/sb_edac.c | 240 ++++++++++++++------------- drivers/edac/x38_edac.c | 26 +-- 30 files changed, 921 insertions(+), 962 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9fbced7f65ee..b47529554734 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -321,8 +321,8 @@ found: return edac_mc_find((int)node_id); err_no_match: - debugf2("sys_addr 0x%lx doesn't match any node\n", - (unsigned long)sys_addr); + edac_dbg(2, "sys_addr 0x%lx doesn't match any node\n", + (unsigned long)sys_addr); return NULL; } @@ -393,15 +393,15 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) mask = ~mask; if ((input_addr & mask) == (base & mask)) { - debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n", - (unsigned long)input_addr, csrow, - pvt->mc_node_id); + edac_dbg(2, "InputAddr 0x%lx matches csrow %d (node %d)\n", + (unsigned long)input_addr, csrow, + pvt->mc_node_id); return csrow; } } - debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n", - (unsigned long)input_addr, pvt->mc_node_id); + edac_dbg(2, "no matching csrow for InputAddr 0x%lx (MC node %d)\n", + (unsigned long)input_addr, pvt->mc_node_id); return -1; } @@ -430,20 +430,20 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, /* only revE and later have the DRAM Hole Address Register */ if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) { - debugf1(" revision %d for node %d does not support DHAR\n", - pvt->ext_model, pvt->mc_node_id); + edac_dbg(1, " revision %d for node %d does not support DHAR\n", + pvt->ext_model, pvt->mc_node_id); return 1; } /* valid for Fam10h and above */ if (boot_cpu_data.x86 >= 0x10 && !dhar_mem_hoist_valid(pvt)) { - debugf1(" Dram Memory Hoisting is DISABLED on this system\n"); + edac_dbg(1, " Dram Memory Hoisting is DISABLED on this system\n"); return 1; } if (!dhar_valid(pvt)) { - debugf1(" Dram Memory Hoisting is DISABLED on this node %d\n", - pvt->mc_node_id); + edac_dbg(1, " Dram Memory Hoisting is DISABLED on this node %d\n", + pvt->mc_node_id); return 1; } @@ -475,9 +475,9 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, else *hole_offset = k8_dhar_offset(pvt); - debugf1(" DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n", - pvt->mc_node_id, (unsigned long)*hole_base, - (unsigned long)*hole_offset, (unsigned long)*hole_size); + edac_dbg(1, " DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n", + pvt->mc_node_id, (unsigned long)*hole_base, + (unsigned long)*hole_offset, (unsigned long)*hole_size); return 0; } @@ -528,10 +528,9 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) /* use DHAR to translate SysAddr to DramAddr */ dram_addr = sys_addr - hole_offset; - debugf2("using DHAR to translate SysAddr 0x%lx to " - "DramAddr 0x%lx\n", - (unsigned long)sys_addr, - (unsigned long)dram_addr); + edac_dbg(2, "using DHAR to translate SysAddr 0x%lx to DramAddr 0x%lx\n", + (unsigned long)sys_addr, + (unsigned long)dram_addr); return dram_addr; } @@ -548,9 +547,8 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) */ dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base; - debugf2("using DRAM Base register to translate SysAddr 0x%lx to " - "DramAddr 0x%lx\n", (unsigned long)sys_addr, - (unsigned long)dram_addr); + edac_dbg(2, "using DRAM Base register to translate SysAddr 0x%lx to DramAddr 0x%lx\n", + (unsigned long)sys_addr, (unsigned long)dram_addr); return dram_addr; } @@ -586,9 +584,9 @@ static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr) input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) + (dram_addr & 0xfff); - debugf2(" Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n", - intlv_shift, (unsigned long)dram_addr, - (unsigned long)input_addr); + edac_dbg(2, " Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n", + intlv_shift, (unsigned long)dram_addr, + (unsigned long)input_addr); return input_addr; } @@ -604,8 +602,8 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) input_addr = dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr)); - debugf2("SysAdddr 0x%lx translates to InputAddr 0x%lx\n", - (unsigned long)sys_addr, (unsigned long)input_addr); + edac_dbg(2, "SysAdddr 0x%lx translates to InputAddr 0x%lx\n", + (unsigned long)sys_addr, (unsigned long)input_addr); return input_addr; } @@ -637,8 +635,8 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0)); if (intlv_shift == 0) { - debugf1(" InputAddr 0x%lx translates to DramAddr of " - "same value\n", (unsigned long)input_addr); + edac_dbg(1, " InputAddr 0x%lx translates to DramAddr of same value\n", + (unsigned long)input_addr); return input_addr; } @@ -649,9 +647,9 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1); dram_addr = bits + (intlv_sel << 12); - debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " - "(%d node interleave bits)\n", (unsigned long)input_addr, - (unsigned long)dram_addr, intlv_shift); + edac_dbg(1, "InputAddr 0x%lx translates to DramAddr 0x%lx (%d node interleave bits)\n", + (unsigned long)input_addr, + (unsigned long)dram_addr, intlv_shift); return dram_addr; } @@ -673,9 +671,9 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) (dram_addr < (hole_base + hole_size))) { sys_addr = dram_addr + hole_offset; - debugf1("using DHAR to translate DramAddr 0x%lx to " - "SysAddr 0x%lx\n", (unsigned long)dram_addr, - (unsigned long)sys_addr); + edac_dbg(1, "using DHAR to translate DramAddr 0x%lx to SysAddr 0x%lx\n", + (unsigned long)dram_addr, + (unsigned long)sys_addr); return sys_addr; } @@ -697,9 +695,9 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) */ sys_addr |= ~((sys_addr & (1ull << 39)) - 1); - debugf1(" Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", - pvt->mc_node_id, (unsigned long)dram_addr, - (unsigned long)sys_addr); + edac_dbg(1, " Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", + pvt->mc_node_id, (unsigned long)dram_addr, + (unsigned long)sys_addr); return sys_addr; } @@ -768,49 +766,48 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8); static void amd64_dump_dramcfg_low(u32 dclr, int chan) { - debugf1("F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); + edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); - debugf1(" DIMM type: %sbuffered; all DIMMs support ECC: %s\n", - (dclr & BIT(16)) ? "un" : "", - (dclr & BIT(19)) ? "yes" : "no"); + edac_dbg(1, " DIMM type: %sbuffered; all DIMMs support ECC: %s\n", + (dclr & BIT(16)) ? "un" : "", + (dclr & BIT(19)) ? "yes" : "no"); - debugf1(" PAR/ERR parity: %s\n", - (dclr & BIT(8)) ? "enabled" : "disabled"); + edac_dbg(1, " PAR/ERR parity: %s\n", + (dclr & BIT(8)) ? "enabled" : "disabled"); if (boot_cpu_data.x86 == 0x10) - debugf1(" DCT 128bit mode width: %s\n", - (dclr & BIT(11)) ? "128b" : "64b"); + edac_dbg(1, " DCT 128bit mode width: %s\n", + (dclr & BIT(11)) ? "128b" : "64b"); - debugf1(" x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n", - (dclr & BIT(12)) ? "yes" : "no", - (dclr & BIT(13)) ? "yes" : "no", - (dclr & BIT(14)) ? "yes" : "no", - (dclr & BIT(15)) ? "yes" : "no"); + edac_dbg(1, " x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n", + (dclr & BIT(12)) ? "yes" : "no", + (dclr & BIT(13)) ? "yes" : "no", + (dclr & BIT(14)) ? "yes" : "no", + (dclr & BIT(15)) ? "yes" : "no"); } /* Display and decode various NB registers for debug purposes. */ static void dump_misc_regs(struct amd64_pvt *pvt) { - debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap); + edac_dbg(1, "F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap); - debugf1(" NB two channel DRAM capable: %s\n", - (pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no"); + edac_dbg(1, " NB two channel DRAM capable: %s\n", + (pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no"); - debugf1(" ECC capable: %s, ChipKill ECC capable: %s\n", - (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", - (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); + edac_dbg(1, " ECC capable: %s, ChipKill ECC capable: %s\n", + (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", + (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); amd64_dump_dramcfg_low(pvt->dclr0, 0); - debugf1("F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); + edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); - debugf1("F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, " - "offset: 0x%08x\n", - pvt->dhar, dhar_base(pvt), - (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) - : f10_dhar_offset(pvt)); + edac_dbg(1, "F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, offset: 0x%08x\n", + pvt->dhar, dhar_base(pvt), + (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) + : f10_dhar_offset(pvt)); - debugf1(" DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); + edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); amd64_debug_display_dimm_sizes(pvt, 0); @@ -857,15 +854,15 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *base1 = &pvt->csels[1].csbases[cs]; if (!amd64_read_dct_pci_cfg(pvt, reg0, base0)) - debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", - cs, *base0, reg0); + edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", + cs, *base0, reg0); if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt)) continue; if (!amd64_read_dct_pci_cfg(pvt, reg1, base1)) - debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", - cs, *base1, reg1); + edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", + cs, *base1, reg1); } for_each_chip_select_mask(cs, 0, pvt) { @@ -875,15 +872,15 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *mask1 = &pvt->csels[1].csmasks[cs]; if (!amd64_read_dct_pci_cfg(pvt, reg0, mask0)) - debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", - cs, *mask0, reg0); + edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", + cs, *mask0, reg0); if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt)) continue; if (!amd64_read_dct_pci_cfg(pvt, reg1, mask1)) - debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", - cs, *mask1, reg1); + edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", + cs, *mask1, reg1); } } @@ -1193,7 +1190,7 @@ static int f1x_early_channel_count(struct amd64_pvt *pvt) * Need to check DCT0[0] and DCT1[0] to see if only one of them has * their CSEnable bit on. If so, then SINGLE DIMM case. */ - debugf0("Data width is not 128 bits - need more decoding\n"); + edac_dbg(0, "Data width is not 128 bits - need more decoding\n"); /* * Check DRAM Bank Address Mapping values for each DIMM to see if there @@ -1272,25 +1269,24 @@ static void read_dram_ctl_register(struct amd64_pvt *pvt) return; if (!amd64_read_dct_pci_cfg(pvt, DCT_SEL_LO, &pvt->dct_sel_lo)) { - debugf0("F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n", - pvt->dct_sel_lo, dct_sel_baseaddr(pvt)); + edac_dbg(0, "F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n", + pvt->dct_sel_lo, dct_sel_baseaddr(pvt)); - debugf0(" DCTs operate in %s mode.\n", - (dct_ganging_enabled(pvt) ? "ganged" : "unganged")); + edac_dbg(0, " DCTs operate in %s mode\n", + (dct_ganging_enabled(pvt) ? "ganged" : "unganged")); if (!dct_ganging_enabled(pvt)) - debugf0(" Address range split per DCT: %s\n", - (dct_high_range_enabled(pvt) ? "yes" : "no")); + edac_dbg(0, " Address range split per DCT: %s\n", + (dct_high_range_enabled(pvt) ? "yes" : "no")); - debugf0(" data interleave for ECC: %s, " - "DRAM cleared since last warm reset: %s\n", - (dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"), - (dct_memory_cleared(pvt) ? "yes" : "no")); + edac_dbg(0, " data interleave for ECC: %s, DRAM cleared since last warm reset: %s\n", + (dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"), + (dct_memory_cleared(pvt) ? "yes" : "no")); - debugf0(" channel interleave: %s, " - "interleave bits selector: 0x%x\n", - (dct_interleave_enabled(pvt) ? "enabled" : "disabled"), - dct_sel_interleave_addr(pvt)); + edac_dbg(0, " channel interleave: %s, " + "interleave bits selector: 0x%x\n", + (dct_interleave_enabled(pvt) ? "enabled" : "disabled"), + dct_sel_interleave_addr(pvt)); } amd64_read_dct_pci_cfg(pvt, DCT_SEL_HI, &pvt->dct_sel_hi); @@ -1428,7 +1424,7 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) pvt = mci->pvt_info; - debugf1("input addr: 0x%llx, DCT: %d\n", in_addr, dct); + edac_dbg(1, "input addr: 0x%llx, DCT: %d\n", in_addr, dct); for_each_chip_select(csrow, dct, pvt) { if (!csrow_enabled(csrow, dct, pvt)) @@ -1436,19 +1432,18 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) get_cs_base_and_mask(pvt, csrow, dct, &cs_base, &cs_mask); - debugf1(" CSROW=%d CSBase=0x%llx CSMask=0x%llx\n", - csrow, cs_base, cs_mask); + edac_dbg(1, " CSROW=%d CSBase=0x%llx CSMask=0x%llx\n", + csrow, cs_base, cs_mask); cs_mask = ~cs_mask; - debugf1(" (InputAddr & ~CSMask)=0x%llx " - "(CSBase & ~CSMask)=0x%llx\n", - (in_addr & cs_mask), (cs_base & cs_mask)); + edac_dbg(1, " (InputAddr & ~CSMask)=0x%llx (CSBase & ~CSMask)=0x%llx\n", + (in_addr & cs_mask), (cs_base & cs_mask)); if ((in_addr & cs_mask) == (cs_base & cs_mask)) { cs_found = f10_process_possible_spare(pvt, dct, csrow); - debugf1(" MATCH csrow=%d\n", cs_found); + edac_dbg(1, " MATCH csrow=%d\n", cs_found); break; } } @@ -1505,8 +1500,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, u8 intlv_en = dram_intlv_en(pvt, range); u32 intlv_sel = dram_intlv_sel(pvt, range); - debugf1("(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", - range, sys_addr, get_dram_limit(pvt, range)); + edac_dbg(1, "(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", + range, sys_addr, get_dram_limit(pvt, range)); if (dhar_valid(pvt) && dhar_base(pvt) <= sys_addr && @@ -1562,7 +1557,7 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, (chan_addr & 0xfff); } - debugf1(" Normalized DCT addr: 0x%llx\n", chan_addr); + edac_dbg(1, " Normalized DCT addr: 0x%llx\n", chan_addr); cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel); @@ -1664,7 +1659,8 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->csels[1].csbases : pvt->csels[0].csbases; - debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam); + edac_dbg(1, "F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", + ctrl, dbam); edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl); @@ -1840,7 +1836,7 @@ static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs, } } - debugf0("syndrome(%x) not found\n", syndrome); + edac_dbg(0, "syndrome(%x) not found\n", syndrome); return -1; } @@ -2047,9 +2043,9 @@ static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id) return -ENODEV; } - debugf1("F1: %s\n", pci_name(pvt->F1)); - debugf1("F2: %s\n", pci_name(pvt->F2)); - debugf1("F3: %s\n", pci_name(pvt->F3)); + edac_dbg(1, "F1: %s\n", pci_name(pvt->F1)); + edac_dbg(1, "F2: %s\n", pci_name(pvt->F2)); + edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); return 0; } @@ -2076,15 +2072,15 @@ static void read_mc_regs(struct amd64_pvt *pvt) * those are Read-As-Zero */ rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem); - debugf0(" TOP_MEM: 0x%016llx\n", pvt->top_mem); + edac_dbg(0, " TOP_MEM: 0x%016llx\n", pvt->top_mem); /* check first whether TOP_MEM2 is enabled */ rdmsrl(MSR_K8_SYSCFG, msr_val); if (msr_val & (1U << 21)) { rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2); - debugf0(" TOP_MEM2: 0x%016llx\n", pvt->top_mem2); + edac_dbg(0, " TOP_MEM2: 0x%016llx\n", pvt->top_mem2); } else - debugf0(" TOP_MEM2 disabled.\n"); + edac_dbg(0, " TOP_MEM2 disabled\n"); amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap); @@ -2100,17 +2096,17 @@ static void read_mc_regs(struct amd64_pvt *pvt) if (!rw) continue; - debugf1(" DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n", - range, - get_dram_base(pvt, range), - get_dram_limit(pvt, range)); + edac_dbg(1, " DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n", + range, + get_dram_base(pvt, range), + get_dram_limit(pvt, range)); - debugf1(" IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n", - dram_intlv_en(pvt, range) ? "Enabled" : "Disabled", - (rw & 0x1) ? "R" : "-", - (rw & 0x2) ? "W" : "-", - dram_intlv_sel(pvt, range), - dram_dst_node(pvt, range)); + edac_dbg(1, " IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n", + dram_intlv_en(pvt, range) ? "Enabled" : "Disabled", + (rw & 0x1) ? "R" : "-", + (rw & 0x2) ? "W" : "-", + dram_intlv_sel(pvt, range), + dram_dst_node(pvt, range)); } read_dct_base_mask(pvt); @@ -2191,9 +2187,9 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT); - debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); - debugf0(" nr_pages/channel= %u channel-count = %d\n", - nr_pages, pvt->channel_count); + edac_dbg(0, " (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); + edac_dbg(0, " nr_pages/channel= %u channel-count = %d\n", + nr_pages, pvt->channel_count); return nr_pages; } @@ -2218,22 +2214,19 @@ static int init_csrows(struct mem_ctl_info *mci) pvt->nbcfg = val; - debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", - pvt->mc_node_id, val, - !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); + edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", + pvt->mc_node_id, val, + !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); for_each_chip_select(i, 0, pvt) { csrow = mci->csrows[i]; if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) { - debugf1("----CSROW %d EMPTY for node %d\n", i, - pvt->mc_node_id); + edac_dbg(1, "----CSROW %d VALID for MC node %d\n", + i, pvt->mc_node_id); continue; } - debugf1("----CSROW %d VALID for MC node %d\n", - i, pvt->mc_node_id); - empty = 0; if (csrow_enabled(i, 0, pvt)) nr_pages = amd64_csrow_nr_pages(pvt, 0, i); @@ -2245,8 +2238,9 @@ static int init_csrows(struct mem_ctl_info *mci) mtype = amd64_determine_memory_type(pvt, i); - debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); - debugf1(" nr_pages: %u\n", nr_pages * pvt->channel_count); + edac_dbg(1, " for MC node %d csrow %d:\n", pvt->mc_node_id, i); + edac_dbg(1, " nr_pages: %u\n", + nr_pages * pvt->channel_count); /* * determine whether CHIPKILL or JUST ECC or NO ECC is operating @@ -2298,9 +2292,9 @@ static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid) struct msr *reg = per_cpu_ptr(msrs, cpu); nbe = reg->l & MSR_MCGCTL_NBE; - debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", - cpu, reg->q, - (nbe ? "enabled" : "disabled")); + edac_dbg(0, "core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", + cpu, reg->q, + (nbe ? "enabled" : "disabled")); if (!nbe) goto out; @@ -2371,8 +2365,8 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, amd64_read_pci_cfg(F3, NBCFG, &value); - debugf0("1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", - nid, value, !!(value & NBCFG_ECC_ENABLE)); + edac_dbg(0, "1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", + nid, value, !!(value & NBCFG_ECC_ENABLE)); if (!(value & NBCFG_ECC_ENABLE)) { amd64_warn("DRAM ECC disabled on this node, enabling...\n"); @@ -2396,8 +2390,8 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, s->flags.nb_ecc_prev = 1; } - debugf0("2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", - nid, value, !!(value & NBCFG_ECC_ENABLE)); + edac_dbg(0, "2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", + nid, value, !!(value & NBCFG_ECC_ENABLE)); return ret; } @@ -2615,11 +2609,11 @@ static int amd64_init_one_instance(struct pci_dev *F2) ret = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf1("failed edac_mc_add_mc()\n"); + edac_dbg(1, "failed edac_mc_add_mc()\n"); goto err_add_mc; } if (set_mc_sysfs_attrs(mci)) { - debugf1("failed edac_mc_add_mc()\n"); + edac_dbg(1, "failed edac_mc_add_mc()\n"); goto err_add_sysfs; } @@ -2660,7 +2654,7 @@ static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret < 0) { - debugf0("ret=%d\n", ret); + edac_dbg(0, "ret=%d\n", ret); return -EIO; } diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index ef1ff4ea9576..53d972e00dfb 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c @@ -142,7 +142,8 @@ static ssize_t amd64_inject_read_store(struct device *dev, /* Issue 'word' and 'bit' along with the READ request */ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); - debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); + edac_dbg(0, "section=0x%x word_bits=0x%x\n", + section, word_bits); return count; } @@ -177,7 +178,8 @@ static ssize_t amd64_inject_write_store(struct device *dev, /* Issue 'word' and 'bit' along with the READ request */ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); - debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); + edac_dbg(0, "section=0x%x word_bits=0x%x\n", + section, word_bits); return count; } diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index b6e94ae4bf6f..a015fbaa9552 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -180,7 +180,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; - debugf3("\n"); + edac_dbg(3, "\n"); amd76x_get_error_info(mci, &info); amd76x_process_error_info(mci, &info, 1); } @@ -241,7 +241,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) u32 ems_mode; struct amd76x_error_info discard; - debugf0("\n"); + edac_dbg(0, "\n"); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; @@ -256,7 +256,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("mci = %p\n", mci); + edac_dbg(0, "mci = %p\n", mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -276,7 +276,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -292,7 +292,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail: @@ -304,7 +304,7 @@ fail: static int __devinit amd76x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("\n"); + edac_dbg(0, "\n"); /* don't need to call pci_enable_device() */ return amd76x_probe1(pdev, ent->driver_data); @@ -322,7 +322,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); if (amd76x_pci) edac_pci_release_generic_ctl(amd76x_pci); diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index fa39a7840e28..a7ea3986d423 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -316,12 +316,12 @@ static void get_total_mem(struct cpc925_mc_pdata *pdata) reg += aw; size = of_read_number(reg, sw); reg += sw; - debugf1("start 0x%lx, size 0x%lx\n", start, size); + edac_dbg(1, "start 0x%lx, size 0x%lx\n", start, size); pdata->total_mem += size; } while (reg < reg_end); of_node_put(np); - debugf0("total_mem 0x%lx\n", pdata->total_mem); + edac_dbg(0, "total_mem 0x%lx\n", pdata->total_mem); } static void cpc925_init_csrows(struct mem_ctl_info *mci) @@ -511,7 +511,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, *offset = pa & (PAGE_SIZE - 1); *pfn = pa >> PAGE_SHIFT; - debugf0("ECC physical address 0x%lx\n", pa); + edac_dbg(0, "ECC physical address 0x%lx\n", pa); } static int cpc925_mc_find_channel(struct mem_ctl_info *mci, u16 syndrome) @@ -851,8 +851,8 @@ static void cpc925_add_edac_devices(void __iomem *vbase) goto err2; } - debugf0("Successfully added edac device for %s\n", - dev_info->ctl_name); + edac_dbg(0, "Successfully added edac device for %s\n", + dev_info->ctl_name); continue; @@ -883,8 +883,8 @@ static void cpc925_del_edac_devices(void) if (dev_info->exit) dev_info->exit(dev_info); - debugf0("Successfully deleted edac device for %s\n", - dev_info->ctl_name); + edac_dbg(0, "Successfully deleted edac device for %s\n", + dev_info->ctl_name); } } @@ -899,7 +899,7 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) mscr = __raw_readl(pdata->vbase + REG_MSCR_OFFSET); si = (mscr & MSCR_SI_MASK) >> MSCR_SI_SHIFT; - debugf0("Mem Scrub Ctrl Register 0x%x\n", mscr); + edac_dbg(0, "Mem Scrub Ctrl Register 0x%x\n", mscr); if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || (si == 0)) { @@ -927,7 +927,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase) ((mbcr & MBCR_64BITBUS_MASK) == 0)) dual = 1; - debugf0("%s channel\n", (dual > 0) ? "Dual" : "Single"); + edac_dbg(0, "%s channel\n", (dual > 0) ? "Dual" : "Single"); return dual; } @@ -942,7 +942,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) struct resource *r; int res = 0, nr_channels; - debugf0("%s platform device found!\n", pdev->name); + edac_dbg(0, "%s platform device found!\n", pdev->name); if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) { res = -ENOMEM; @@ -1024,7 +1024,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) cpc925_add_edac_devices(vbase); /* get this far and it's successful */ - debugf0("success\n"); + edac_dbg(0, "success\n"); res = 0; goto out; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 39c8997b2162..675ba3c284eb 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -309,7 +309,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("\n"); + edac_dbg(3, "\n"); if (page < pvt->tolm) return page; @@ -335,7 +335,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, int i; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("\n"); + edac_dbg(3, "\n"); /* convert the addr to 4k page */ page = sec1_add >> (PAGE_SHIFT - 4); @@ -394,7 +394,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, int row; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("\n"); + edac_dbg(3, "\n"); if (error_one & 0x0202) { error_2b = ded_add; @@ -453,7 +453,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, if (!handle_error) return; - debugf3("\n"); + edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e752x UE log memory write", "", NULL); @@ -982,7 +982,7 @@ static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; - debugf3("\n"); + edac_dbg(3, "\n"); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); } @@ -1102,8 +1102,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, pci_read_config_byte(pdev, E752X_DRB + index, &value); /* convert a 128 or 64 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("(%d) cumul_size 0x%x\n", index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -1129,7 +1128,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, for (i = 0; i < csrow->nr_channels; i++) { struct dimm_info *dimm = csrow->channels[i]->dimm; - debugf3("Initializing rank at (%i,%i)\n", index, i); + edac_dbg(3, "Initializing rank at (%i,%i)\n", index, i); dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ @@ -1270,8 +1269,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; /* Number of channels 0=1chan,1=2chan */ struct e752x_error_info discard; - debugf0("mci\n"); - debugf0("Starting Probe1\n"); + edac_dbg(0, "mci\n"); + edac_dbg(0, "Starting Probe1\n"); /* check to see if device 0 function 1 is enabled; if it isn't, we * assume the BIOS has reserved it for a reason and is expecting @@ -1301,7 +1300,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; /* 3100 IMCH supports SECDEC only */ mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED : @@ -1311,7 +1310,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_ver = E752X_REVISION; mci->pdev = &pdev->dev; - debugf3("init pvt\n"); + edac_dbg(3, "init pvt\n"); pvt = (struct e752x_pvt *)mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); @@ -1321,7 +1320,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) return -ENODEV; } - debugf3("more mci init\n"); + edac_dbg(3, "more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e752x_check; @@ -1343,7 +1342,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */ else mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("tolm, remapbase, remaplimit\n"); + edac_dbg(3, "tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E752X_TOLM, &pci_data); @@ -1360,7 +1359,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -1378,7 +1377,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail: @@ -1394,7 +1393,7 @@ fail: static int __devinit e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("\n"); + edac_dbg(0, "\n"); /* wake up and enable device */ if (pci_enable_device(pdev) < 0) @@ -1408,7 +1407,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e752x_pvt *pvt; - debugf0("\n"); + edac_dbg(0, "\n"); if (e752x_pci) edac_pci_release_generic_ctl(e752x_pci); @@ -1454,7 +1453,7 @@ static int __init e752x_init(void) { int pci_rc; - debugf3("\n"); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1465,7 +1464,7 @@ static int __init e752x_init(void) static void __exit e752x_exit(void) { - debugf3("\n"); + edac_dbg(3, "\n"); pci_unregister_driver(&e752x_driver); } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 691d7067a141..3ce661e883f7 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -166,7 +166,7 @@ static const struct e7xxx_dev_info e7xxx_devs[] = { /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { - debugf3("\n"); + edac_dbg(3, "\n"); if ((syndrome & 0xff00) == 0) return 0; @@ -186,7 +186,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *)mci->pvt_info; - debugf3("\n"); + edac_dbg(3, "\n"); if ((page < pvt->tolm) || ((page >= 0x100000) && (page < pvt->remapbase))) @@ -208,7 +208,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int row; int channel; - debugf3("\n"); + edac_dbg(3, "\n"); /* read the error address */ error_1b = info->dram_celog_add; /* FIXME - should use PAGE_SHIFT */ @@ -225,7 +225,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ce_no_info(struct mem_ctl_info *mci) { - debugf3("\n"); + edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e7xxx CE log register overflow", "", NULL); } @@ -235,7 +235,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) u32 error_2b, block_page; int row; - debugf3("\n"); + edac_dbg(3, "\n"); /* read the error address */ error_2b = info->dram_uelog_add; /* FIXME - should use PAGE_SHIFT */ @@ -248,7 +248,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ue_no_info(struct mem_ctl_info *mci) { - debugf3("\n"); + edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, "e7xxx UE log register overflow", "", NULL); @@ -334,7 +334,7 @@ static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; - debugf3("\n"); + edac_dbg(3, "\n"); e7xxx_get_error_info(mci, &info); e7xxx_process_error_info(mci, &info, 1); } @@ -383,8 +383,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, pci_read_config_byte(pdev, E7XXX_DRB + index, &value); /* convert a 64 or 32 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("(%d) cumul_size 0x%x\n", index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -430,7 +429,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; struct e7xxx_error_info discard; - debugf0("mci\n"); + edac_dbg(0, "mci\n"); pci_read_config_dword(pdev, E7XXX_DRC, &drc); @@ -453,7 +452,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; @@ -461,7 +460,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E7XXX_REVISION; mci->pdev = &pdev->dev; - debugf3("init pvt\n"); + edac_dbg(3, "init pvt\n"); pvt = (struct e7xxx_pvt *)mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -474,14 +473,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - debugf3("more mci init\n"); + edac_dbg(3, "more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e7xxx_check; mci->ctl_page_to_phys = ctl_page_to_phys; e7xxx_init_csrows(mci, pdev, dev_idx, drc); mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("tolm, remapbase, remaplimit\n"); + edac_dbg(3, "tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E7XXX_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -500,7 +499,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail1; } @@ -516,7 +515,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail1: @@ -532,7 +531,7 @@ fail0: static int __devinit e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("\n"); + edac_dbg(0, "\n"); /* wake up and enable device */ return pci_enable_device(pdev) ? @@ -544,7 +543,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e7xxx_pvt *pvt; - debugf0("\n"); + edac_dbg(0, "\n"); if (e7xxx_pci) edac_pci_release_generic_ctl(e7xxx_pci); diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 410738bf30fd..ee25f5483f9b 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -71,7 +71,7 @@ extern const char *edac_mem_types[]; #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; -#define edac_debug_printk(level, fmt, ...) \ +#define edac_dbg(level, fmt, ...) \ do { \ if (level <= edac_debug_level) \ edac_printk(KERN_DEBUG, EDAC_DEBUG, \ @@ -80,7 +80,7 @@ do { \ #else /* !CONFIG_EDAC_DEBUG */ -#define edac_debug_printk(level, fmt, ...) \ +#define edac_dbg(level, fmt, ...) \ do { \ if (0) \ edac_printk(KERN_DEBUG, EDAC_DEBUG, \ @@ -89,12 +89,6 @@ do { \ #endif /* !CONFIG_EDAC_DEBUG */ -#define debugf0(fmt, ...) edac_debug_printk(0, fmt, ##__VA_ARGS__) -#define debugf1(fmt, ...) edac_debug_printk(1, fmt, ##__VA_ARGS__) -#define debugf2(fmt, ...) edac_debug_printk(2, fmt, ##__VA_ARGS__) -#define debugf3(fmt, ...) edac_debug_printk(3, fmt, ##__VA_ARGS__) -#define debugf4(fmt, ...) edac_debug_printk(4, fmt, ##__VA_ARGS__) - #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ PCI_DEVICE_ID_ ## vend ## _ ## dev diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index ed46949f25cf..9523e76191f2 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -40,12 +40,13 @@ static LIST_HEAD(edac_device_list); #ifdef CONFIG_EDAC_DEBUG static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) { - debugf3("\tedac_dev = %p dev_idx=%d \n", edac_dev, edac_dev->dev_idx); - debugf4("\tedac_dev->edac_check = %p\n", edac_dev->edac_check); - debugf3("\tdev = %p\n", edac_dev->dev); - debugf3("\tmod_name:ctl_name = %s:%s\n", - edac_dev->mod_name, edac_dev->ctl_name); - debugf3("\tpvt_info = %p\n\n", edac_dev->pvt_info); + edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n", + edac_dev, edac_dev->dev_idx); + edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check); + edac_dbg(3, "\tdev = %p\n", edac_dev->dev); + edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n", + edac_dev->mod_name, edac_dev->ctl_name); + edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info); } #endif /* CONFIG_EDAC_DEBUG */ @@ -82,8 +83,7 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( void *pvt, *p; int err; - debugf4("instances=%d blocks=%d\n", - nr_instances, nr_blocks); + edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks); /* Calculate the size of memory we need to allocate AND * determine the offsets of the various item arrays @@ -156,8 +156,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( /* Name of this edac device */ snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); - debugf4("edac_dev=%p next after end=%p\n", - dev_ctl, pvt + sz_private ); + edac_dbg(4, "edac_dev=%p next after end=%p\n", + dev_ctl, pvt + sz_private); /* Initialize every Instance */ for (instance = 0; instance < nr_instances; instance++) { @@ -178,10 +178,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( snprintf(blk->name, sizeof(blk->name), "%s%d", edac_block_name, block+offset_value); - debugf4("instance=%d inst_p=%p block=#%d " - "block_p=%p name='%s'\n", - instance, inst, block, - blk, blk->name); + edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n", + instance, inst, block, blk, blk->name); /* if there are NO attributes OR no attribute pointer * then continue on to next block iteration @@ -194,8 +192,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; blk->block_attributes = attrib_p; - debugf4("THIS BLOCK_ATTRIB=%p\n", - blk->block_attributes); + edac_dbg(4, "THIS BLOCK_ATTRIB=%p\n", + blk->block_attributes); /* Initialize every user specified attribute in this * block with the data the caller passed in @@ -214,11 +212,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib->block = blk; /* up link */ - debugf4("alloc-attrib=%p attrib_name='%s' " - "attrib-spec=%p spec-name=%s\n", - attrib, attrib->attr.name, - &attrib_spec[attr], - attrib_spec[attr].attr.name + edac_dbg(4, "alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n", + attrib, attrib->attr.name, + &attrib_spec[attr], + attrib_spec[attr].attr.name ); } } @@ -273,7 +270,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev) struct edac_device_ctl_info *edac_dev; struct list_head *item; - debugf0("\n"); + edac_dbg(0, "\n"); list_for_each(item, &edac_device_list) { edac_dev = list_entry(item, struct edac_device_ctl_info, link); @@ -408,7 +405,7 @@ static void edac_device_workq_function(struct work_struct *work_req) void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, unsigned msec) { - debugf0("\n"); + edac_dbg(0, "\n"); /* take the arg 'msec' and set it into the control structure * to used in the time period calculation @@ -496,7 +493,7 @@ EXPORT_SYMBOL_GPL(edac_device_alloc_index); */ int edac_device_add_device(struct edac_device_ctl_info *edac_dev) { - debugf0("\n"); + edac_dbg(0, "\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -570,7 +567,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev) { struct edac_device_ctl_info *edac_dev; - debugf0("\n"); + edac_dbg(0, "\n"); mutex_lock(&device_ctls_mutex); diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index 1cee83ec35fe..fb68a06ad683 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -202,7 +202,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj) { struct edac_device_ctl_info *edac_dev = to_edacdev(kobj); - debugf4("control index=%d\n", edac_dev->dev_idx); + edac_dbg(4, "control index=%d\n", edac_dev->dev_idx); /* decrement the EDAC CORE module ref count */ module_put(edac_dev->owner); @@ -233,12 +233,12 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) struct bus_type *edac_subsys; int err; - debugf1("\n"); + edac_dbg(1, "\n"); /* get the /sys/devices/system/edac reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("no edac_subsys error\n"); + edac_dbg(1, "no edac_subsys error\n"); err = -ENODEV; goto err_out; } @@ -264,8 +264,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) &edac_subsys->dev_root->kobj, "%s", edac_dev->name); if (err) { - debugf1("Failed to register '.../edac/%s'\n", - edac_dev->name); + edac_dbg(1, "Failed to register '.../edac/%s'\n", + edac_dev->name); goto err_kobj_reg; } kobject_uevent(&edac_dev->kobj, KOBJ_ADD); @@ -274,8 +274,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) * edac_device_unregister_sysfs_main_kobj() must be used */ - debugf4("Registered '.../edac/%s' kobject\n", - edac_dev->name); + edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name); return 0; @@ -296,9 +295,8 @@ err_out: */ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) { - debugf0("\n"); - debugf4("name of kobject is: %s\n", - kobject_name(&dev->kobj)); + edac_dbg(0, "\n"); + edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj)); /* * Unregister the edac device's kobject and @@ -336,7 +334,7 @@ static void edac_device_ctrl_instance_release(struct kobject *kobj) { struct edac_device_instance *instance; - debugf1("\n"); + edac_dbg(1, "\n"); /* map from this kobj to the main control struct * and then dec the main kobj count @@ -442,7 +440,7 @@ static void edac_device_ctrl_block_release(struct kobject *kobj) { struct edac_device_block *block; - debugf1("\n"); + edac_dbg(1, "\n"); /* get the container of the kobj */ block = to_block(kobj); @@ -524,10 +522,10 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; - debugf4("Instance '%s' inst_p=%p block '%s' block_p=%p\n", - instance->name, instance, block->name, block); - debugf4("block kobj=%p block kobj->parent=%p\n", - &block->kobj, &block->kobj.parent); + edac_dbg(4, "Instance '%s' inst_p=%p block '%s' block_p=%p\n", + instance->name, instance, block->name, block); + edac_dbg(4, "block kobj=%p block kobj->parent=%p\n", + &block->kobj, &block->kobj.parent); /* init this block's kobject */ memset(&block->kobj, 0, sizeof(struct kobject)); @@ -546,8 +544,7 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, &instance->kobj, "%s", block->name); if (err) { - debugf1("Failed to register instance '%s'\n", - block->name); + edac_dbg(1, "Failed to register instance '%s'\n", block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; @@ -560,10 +557,9 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { - debugf4("creating block attrib='%s' " - "attrib->%p to kobj=%p\n", - sysfs_attrib->attr.name, - sysfs_attrib, &block->kobj); + edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n", + sysfs_attrib->attr.name, + sysfs_attrib, &block->kobj); /* Create each block_attribute file */ err = sysfs_create_file(&block->kobj, @@ -646,14 +642,14 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl, &edac_dev->kobj, "%s", instance->name); if (err != 0) { - debugf2("Failed to register instance '%s'\n", - instance->name); + edac_dbg(2, "Failed to register instance '%s'\n", + instance->name); kobject_put(main_kobj); goto err_out; } - debugf4("now register '%d' blocks for instance %d\n", - instance->nr_blocks, idx); + edac_dbg(4, "now register '%d' blocks for instance %d\n", + instance->nr_blocks, idx); /* register all blocks of this instance */ for (i = 0; i < instance->nr_blocks; i++) { @@ -669,8 +665,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, } kobject_uevent(&instance->kobj, KOBJ_ADD); - debugf4("Registered instance %d '%s' kobject\n", - idx, instance->name); + edac_dbg(4, "Registered instance %d '%s' kobject\n", + idx, instance->name); return 0; @@ -714,7 +710,7 @@ static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev) int i, j; int err; - debugf0("\n"); + edac_dbg(0, "\n"); /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) { @@ -816,12 +812,12 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) int err; struct kobject *edac_kobj = &edac_dev->kobj; - debugf0("idx=%d\n", edac_dev->dev_idx); + edac_dbg(0, "idx=%d\n", edac_dev->dev_idx); /* go create any main attributes callers wants */ err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { - debugf0("failed to add sysfs attribs\n"); + edac_dbg(0, "failed to add sysfs attribs\n"); goto err_out; } @@ -831,8 +827,7 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { - debugf0("sysfs_create_link() returned err= %d\n", - err); + edac_dbg(0, "sysfs_create_link() returned err= %d\n", err); goto err_remove_main_attribs; } @@ -842,14 +837,13 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) */ err = edac_device_create_instances(edac_dev); if (err) { - debugf0("edac_device_create_instances() " - "returned err= %d\n", err); + edac_dbg(0, "edac_device_create_instances() returned err= %d\n", + err); goto err_remove_link; } - debugf4("create-instances done, idx=%d\n", - edac_dev->dev_idx); + edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx); return 0; @@ -872,7 +866,7 @@ err_out: */ void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev) { - debugf0("\n"); + edac_dbg(0, "\n"); /* remove any main attributes for this device */ edac_device_remove_main_sysfs_attributes(edac_dev); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4df9c4ac63c3..a39fe6f966e3 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -46,56 +46,57 @@ static LIST_HEAD(mc_devices); static void edac_mc_dump_channel(struct rank_info *chan) { - debugf4("\tchannel = %p\n", chan); - debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx); - debugf4("\tchannel->csrow = %p\n\n", chan->csrow); - debugf4("\tchannel->dimm = %p\n", chan->dimm); + edac_dbg(4, "\tchannel = %p\n", chan); + edac_dbg(4, "\tchannel->chan_idx = %d\n", chan->chan_idx); + edac_dbg(4, "\tchannel->csrow = %p\n", chan->csrow); + edac_dbg(4, "\tchannel->dimm = %p\n", chan->dimm); } static void edac_mc_dump_dimm(struct dimm_info *dimm) { int i; - debugf4("\tdimm = %p\n", dimm); - debugf4("\tdimm->label = '%s'\n", dimm->label); - debugf4("\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); - debugf4("\tdimm location "); + edac_dbg(4, "\tdimm = %p\n", dimm); + edac_dbg(4, "\tdimm->label = '%s'\n", dimm->label); + edac_dbg(4, "\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); + edac_dbg(4, "\tdimm location "); for (i = 0; i < dimm->mci->n_layers; i++) { printk(KERN_CONT "%d", dimm->location[i]); if (i < dimm->mci->n_layers - 1) printk(KERN_CONT "."); } printk(KERN_CONT "\n"); - debugf4("\tdimm->grain = %d\n", dimm->grain); - debugf4("\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); + edac_dbg(4, "\tdimm->grain = %d\n", dimm->grain); + edac_dbg(4, "\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); } static void edac_mc_dump_csrow(struct csrow_info *csrow) { - debugf4("\tcsrow = %p\n", csrow); - debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); - debugf4("\tcsrow->first_page = 0x%lx\n", csrow->first_page); - debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); - debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); - debugf4("\tcsrow->nr_channels = %d\n", csrow->nr_channels); - debugf4("\tcsrow->channels = %p\n", csrow->channels); - debugf4("\tcsrow->mci = %p\n\n", csrow->mci); + edac_dbg(4, "\tcsrow = %p\n", csrow); + edac_dbg(4, "\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); + edac_dbg(4, "\tcsrow->first_page = 0x%lx\n", csrow->first_page); + edac_dbg(4, "\tcsrow->last_page = 0x%lx\n", csrow->last_page); + edac_dbg(4, "\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); + edac_dbg(4, "\tcsrow->nr_channels = %d\n", csrow->nr_channels); + edac_dbg(4, "\tcsrow->channels = %p\n", csrow->channels); + edac_dbg(4, "\tcsrow->mci = %p\n", csrow->mci); } static void edac_mc_dump_mci(struct mem_ctl_info *mci) { - debugf3("\tmci = %p\n", mci); - debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap); - debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap); - debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap); - debugf4("\tmci->edac_check = %p\n", mci->edac_check); - debugf3("\tmci->nr_csrows = %d, csrows = %p\n", - mci->nr_csrows, mci->csrows); - debugf3("\tmci->nr_dimms = %d, dimms = %p\n", - mci->tot_dimms, mci->dimms); - debugf3("\tdev = %p\n", mci->pdev); - debugf3("\tmod_name:ctl_name = %s:%s\n", mci->mod_name, mci->ctl_name); - debugf3("\tpvt_info = %p\n\n", mci->pvt_info); + edac_dbg(3, "\tmci = %p\n", mci); + edac_dbg(3, "\tmci->mtype_cap = %lx\n", mci->mtype_cap); + edac_dbg(3, "\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap); + edac_dbg(3, "\tmci->edac_cap = %lx\n", mci->edac_cap); + edac_dbg(4, "\tmci->edac_check = %p\n", mci->edac_check); + edac_dbg(3, "\tmci->nr_csrows = %d, csrows = %p\n", + mci->nr_csrows, mci->csrows); + edac_dbg(3, "\tmci->nr_dimms = %d, dimms = %p\n", + mci->tot_dimms, mci->dimms); + edac_dbg(3, "\tdev = %p\n", mci->pdev); + edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n", + mci->mod_name, mci->ctl_name); + edac_dbg(3, "\tpvt_info = %p\n\n", mci->pvt_info); } #endif /* CONFIG_EDAC_DEBUG */ @@ -246,21 +247,21 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers); for (i = 0; i < n_layers; i++) { count *= layers[i].size; - debugf4("errcount layer %d size %d\n", i, count); + edac_dbg(4, "errcount layer %d size %d\n", i, count); ce_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); ue_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); tot_errcount += 2 * count; } - debugf4("allocating %d error counters\n", tot_errcount); + edac_dbg(4, "allocating %d error counters\n", tot_errcount); pvt = edac_align_ptr(&ptr, sz_pvt, 1); size = ((unsigned long)pvt) + sz_pvt; - debugf1("allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", - size, - tot_dimms, - per_rank ? "ranks" : "dimms", - tot_csrows * tot_channels); + edac_dbg(1, "allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", + size, + tot_dimms, + per_rank ? "ranks" : "dimms", + tot_csrows * tot_channels); mci = kzalloc(size, GFP_KERNEL); if (mci == NULL) @@ -326,8 +327,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, memset(&pos, 0, sizeof(pos)); row = 0; chn = 0; - debugf4("initializing %d %s\n", tot_dimms, - per_rank ? "ranks" : "dimms"); + edac_dbg(4, "initializing %d %s\n", + tot_dimms, per_rank ? "ranks" : "dimms"); for (i = 0; i < tot_dimms; i++) { chan = mci->csrows[row]->channels[chn]; off = EDAC_DIMM_OFF(layer, n_layers, pos[0], pos[1], pos[2]); @@ -340,9 +341,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->dimms[off] = dimm; dimm->mci = mci; - debugf2("%d: %s%i (%d:%d:%d): row %d, chan %d\n", i, - per_rank ? "rank" : "dimm", off, - pos[0], pos[1], pos[2], row, chn); + edac_dbg(2, "%d: %s%i (%d:%d:%d): row %d, chan %d\n", + i, per_rank ? "rank" : "dimm", off, + pos[0], pos[1], pos[2], row, chn); /* * Copy DIMM location and initialize it. @@ -427,7 +428,7 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc); */ void edac_mc_free(struct mem_ctl_info *mci) { - debugf1("\n"); + edac_dbg(1, "\n"); /* the mci instance is freed here, when the sysfs object is dropped */ edac_unregister_sysfs(mci); @@ -447,7 +448,7 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev) struct mem_ctl_info *mci; struct list_head *item; - debugf3("\n"); + edac_dbg(3, "\n"); list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); @@ -515,7 +516,7 @@ static void edac_mc_workq_function(struct work_struct *work_req) */ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) { - debugf0("\n"); + edac_dbg(0, "\n"); /* if this instance is not in the POLL state, then simply return */ if (mci->op_state != OP_RUNNING_POLL) @@ -542,7 +543,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) status = cancel_delayed_work(&mci->work); if (status == 0) { - debugf0("not canceled, flush the queue\n"); + edac_dbg(0, "not canceled, flush the queue\n"); /* workq instance might be running, wait for it */ flush_workqueue(edac_workqueue); @@ -689,7 +690,7 @@ EXPORT_SYMBOL(edac_mc_find); /* FIXME - should a warning be printed if no error detection? correction? */ int edac_mc_add_mc(struct mem_ctl_info *mci) { - debugf0("\n"); + edac_dbg(0, "\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -760,7 +761,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); mutex_lock(&mem_ctls_mutex); @@ -798,7 +799,7 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, void *virt_addr; unsigned long flags = 0; - debugf3("\n"); + edac_dbg(3, "\n"); /* ECC error page was not in our memory. Ignore it. */ if (!pfn_valid(page)) @@ -828,7 +829,7 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) struct csrow_info **csrows = mci->csrows; int row, i, j, n; - debugf1("MC%d: 0x%lx\n", mci->mc_idx, page); + edac_dbg(1, "MC%d: 0x%lx\n", mci->mc_idx, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { @@ -841,10 +842,10 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) if (n == 0) continue; - debugf3("MC%d: first(0x%lx) page(0x%lx) last(0x%lx) " - "mask(0x%lx)\n", mci->mc_idx, - csrow->first_page, page, csrow->last_page, - csrow->page_mask); + edac_dbg(3, "MC%d: first(0x%lx) page(0x%lx) last(0x%lx) mask(0x%lx)\n", + mci->mc_idx, + csrow->first_page, page, csrow->last_page, + csrow->page_mask); if ((page >= csrow->first_page) && (page <= csrow->last_page) && @@ -1048,7 +1049,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, u16 error_count; /* FIXME: make it a parameter */ u8 grain_bits; - debugf3("MC%d\n", mci->mc_idx); + edac_dbg(3, "MC%d\n", mci->mc_idx); /* * Check if the event report is consistent and if the memory @@ -1126,10 +1127,9 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, * get csrow/channel of the DIMM, in order to allow * incrementing the compat API counters */ - debugf4("%s csrows map: (%d,%d)\n", - mci->mem_is_per_rank ? "rank" : "dimm", - dimm->csrow, dimm->cschannel); - + edac_dbg(4, "%s csrows map: (%d,%d)\n", + mci->mem_is_per_rank ? "rank" : "dimm", + dimm->csrow, dimm->cschannel); if (row == -1) row = dimm->csrow; else if (row >= 0 && row != dimm->csrow) @@ -1145,8 +1145,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, if (!enable_per_layer_report) { strcpy(label, "any memory"); } else { - debugf4("csrow/channel to increment: (%d,%d)\n", - row, chan); + edac_dbg(4, "csrow/channel to increment: (%d,%d)\n", row, chan); if (p == label) strcpy(label, "unknown memory"); if (type == HW_EVENT_ERR_CORRECTED) { diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index f72de8ba6a3b..eace646b57f0 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -287,7 +287,7 @@ static void csrow_attr_release(struct device *dev) { struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); - debugf1("Releasing csrow device %s\n", dev_name(dev)); + edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); kfree(csrow); } @@ -376,7 +376,8 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, dev_set_name(&csrow->dev, "csrow%d", index); dev_set_drvdata(&csrow->dev, csrow); - debugf0("creating (virtual) csrow node %s\n", dev_name(&csrow->dev)); + edac_dbg(0, "creating (virtual) csrow node %s\n", + dev_name(&csrow->dev)); err = device_add(&csrow->dev); if (err < 0) @@ -460,8 +461,8 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { if (!csrow->channels[chan]->dimm->nr_pages) continue; - debugf1("Removing csrow %d channel %d sysfs nodes\n", - i, chan); + edac_dbg(1, "Removing csrow %d channel %d sysfs nodes\n", + i, chan); device_remove_file(&csrow->dev, dynamic_csrow_dimm_attr[chan]); device_remove_file(&csrow->dev, @@ -591,7 +592,7 @@ static void dimm_attr_release(struct device *dev) { struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); - debugf1("Releasing dimm device %s\n", dev_name(dev)); + edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev)); kfree(dimm); } @@ -622,7 +623,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, err = device_add(&dimm->dev); - debugf0("creating rank/dimm device %s\n", dev_name(&dimm->dev)); + edac_dbg(0, "creating rank/dimm device %s\n", dev_name(&dimm->dev)); return err; } @@ -897,7 +898,7 @@ static void mci_attr_release(struct device *dev) { struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); - debugf1("Releasing csrow device %s\n", dev_name(dev)); + edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); kfree(mci); } @@ -964,7 +965,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); if (!mci->bus.name) return -ENOMEM; - debugf0("creating bus %s\n",mci->bus.name); + edac_dbg(0, "creating bus %s\n", mci->bus.name); err = bus_register(&mci->bus); if (err < 0) return err; @@ -979,7 +980,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) dev_set_drvdata(&mci->dev, mci); pm_runtime_forbid(&mci->dev); - debugf0("creating device %s\n", dev_name(&mci->dev)); + edac_dbg(0, "creating device %s\n", dev_name(&mci->dev)); err = device_add(&mci->dev); if (err < 0) { bus_unregister(&mci->bus); @@ -996,8 +997,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) if (dimm->nr_pages == 0) continue; #ifdef CONFIG_EDAC_DEBUG - debugf1("creating dimm%d, located at ", - i); + edac_dbg(1, "creating dimm%d, located at ", i); if (edac_debug_level >= 1) { int lay; for (lay = 0; lay < mci->n_layers; lay++) @@ -1009,8 +1009,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) #endif err = edac_create_dimm_object(mci, dimm, i); if (err) { - debugf1("failure: create dimm %d obj\n", - i); + edac_dbg(1, "failure: create dimm %d obj\n", i); goto fail; } } @@ -1048,7 +1047,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { int i; - debugf0("\n"); + edac_dbg(0, "\n"); #ifdef CONFIG_EDAC_DEBUG debugfs_remove(mci->debugfs); @@ -1061,7 +1060,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; - debugf0("removing device %s\n", dev_name(&dimm->dev)); + edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev)); put_device(&dimm->dev); device_del(&dimm->dev); } @@ -1069,7 +1068,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) void edac_unregister_sysfs(struct mem_ctl_info *mci) { - debugf1("Unregistering device %s\n", dev_name(&mci->dev)); + edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); put_device(&mci->dev); device_del(&mci->dev); bus_unregister(&mci->bus); @@ -1083,7 +1082,7 @@ static void mc_attr_release(struct device *dev) * parent device, used to create the /sys/devices/mc sysfs node. * So, there are no attributes on it. */ - debugf1("Releasing device %s\n", dev_name(dev)); + edac_dbg(1, "Releasing device %s\n", dev_name(dev)); kfree(dev); } @@ -1101,7 +1100,7 @@ int __init edac_mc_sysfs_init(void) /* get the /sys/devices/system/edac subsys reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("no edac_subsys\n"); + edac_dbg(1, "no edac_subsys\n"); return -EINVAL; } @@ -1116,7 +1115,7 @@ int __init edac_mc_sysfs_init(void) if (err < 0) return err; - debugf0("device %s created\n", dev_name(mci_pdev)); + edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); return 0; } diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 9de248492908..cbba80d3423a 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -113,7 +113,7 @@ error: */ static void __exit edac_exit(void) { - debugf0("\n"); + edac_dbg(0, "\n"); /* tear down the various subsystems */ edac_workqueue_teardown(); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 51dd4e05a76f..ee87ef972ead 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -45,7 +45,7 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, void *p = NULL, *pvt; unsigned int size; - debugf1("\n"); + edac_dbg(1, "\n"); pci = edac_align_ptr(&p, sizeof(*pci), 1); pvt = edac_align_ptr(&p, 1, sz_pvt); @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); */ void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) { - debugf1("\n"); + edac_dbg(1, "\n"); edac_pci_remove_sysfs(pci); } @@ -97,7 +97,7 @@ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) struct edac_pci_ctl_info *pci; struct list_head *item; - debugf1("\n"); + edac_dbg(1, "\n"); list_for_each(item, &edac_pci_list) { pci = list_entry(item, struct edac_pci_ctl_info, link); @@ -122,7 +122,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) struct list_head *item, *insert_before; struct edac_pci_ctl_info *rover; - debugf1("\n"); + edac_dbg(1, "\n"); insert_before = &edac_pci_list; @@ -226,7 +226,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) int msec; unsigned long delay; - debugf3("checking\n"); + edac_dbg(3, "checking\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -261,7 +261,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, unsigned int msec) { - debugf0("\n"); + edac_dbg(0, "\n"); INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); queue_delayed_work(edac_workqueue, &pci->work, @@ -276,7 +276,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { int status; - debugf0("\n"); + edac_dbg(0, "\n"); status = cancel_delayed_work(&pci->work); if (status == 0) @@ -293,7 +293,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value) { - debugf0("\n"); + edac_dbg(0, "\n"); edac_pci_workq_teardown(pci); @@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_index); */ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) { - debugf0("\n"); + edac_dbg(0, "\n"); pci->pci_idx = edac_idx; pci->start_time = jiffies; @@ -393,7 +393,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) { struct edac_pci_ctl_info *pci; - debugf0("\n"); + edac_dbg(0, "\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -430,7 +430,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device); */ static void edac_pci_generic_check(struct edac_pci_ctl_info *pci) { - debugf4("\n"); + edac_dbg(4, "\n"); edac_pci_do_parity_check(); } @@ -475,7 +475,7 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, pdata->edac_idx = edac_pci_idx++; if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("failed edac_pci_add_device()\n"); + edac_dbg(3, "failed edac_pci_add_device()\n"); edac_pci_free_ctl_info(pci); return NULL; } @@ -491,7 +491,7 @@ EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); */ void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) { - debugf0("pci mod=%s\n", pci->mod_name); + edac_dbg(0, "pci mod=%s\n", pci->mod_name); edac_pci_del_device(pci->dev); edac_pci_free_ctl_info(pci); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 6678216a7cbc..e164c555a337 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -78,7 +78,7 @@ static void edac_pci_instance_release(struct kobject *kobj) { struct edac_pci_ctl_info *pci; - debugf0("\n"); + edac_dbg(0, "\n"); /* Form pointer to containing struct, the pci control struct */ pci = to_instance(kobj); @@ -161,7 +161,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) struct kobject *main_kobj; int err; - debugf0("\n"); + edac_dbg(0, "\n"); /* First bump the ref count on the top main kobj, which will * track the number of PCI instances we have, and thus nest @@ -177,14 +177,13 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance, edac_pci_top_main_kobj, "pci%d", idx); if (err != 0) { - debugf2("failed to register instance pci%d\n", - idx); + edac_dbg(2, "failed to register instance pci%d\n", idx); kobject_put(edac_pci_top_main_kobj); goto error_out; } kobject_uevent(&pci->kobj, KOBJ_ADD); - debugf1("Register instance 'pci%d' kobject\n", idx); + edac_dbg(1, "Register instance 'pci%d' kobject\n", idx); return 0; @@ -201,7 +200,7 @@ error_out: static void edac_pci_unregister_sysfs_instance_kobj( struct edac_pci_ctl_info *pci) { - debugf0("\n"); + edac_dbg(0, "\n"); /* Unregister the instance kobject and allow its release * function release the main reference count and then @@ -317,7 +316,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { */ static void edac_pci_release_main_kobj(struct kobject *kobj) { - debugf0("here to module_put(THIS_MODULE)\n"); + edac_dbg(0, "here to module_put(THIS_MODULE)\n"); kfree(kobj); @@ -345,7 +344,7 @@ static int edac_pci_main_kobj_setup(void) int err; struct bus_type *edac_subsys; - debugf0("\n"); + edac_dbg(0, "\n"); /* check and count if we have already created the main kobject */ if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) @@ -356,7 +355,7 @@ static int edac_pci_main_kobj_setup(void) */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("no edac_subsys\n"); + edac_dbg(1, "no edac_subsys\n"); err = -ENODEV; goto decrement_count_fail; } @@ -366,14 +365,14 @@ static int edac_pci_main_kobj_setup(void) * level main kobj for EDAC PCI */ if (!try_module_get(THIS_MODULE)) { - debugf1("try_module_get() failed\n"); + edac_dbg(1, "try_module_get() failed\n"); err = -ENODEV; goto mod_get_fail; } edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); if (!edac_pci_top_main_kobj) { - debugf1("Failed to allocate\n"); + edac_dbg(1, "Failed to allocate\n"); err = -ENOMEM; goto kzalloc_fail; } @@ -383,7 +382,7 @@ static int edac_pci_main_kobj_setup(void) &ktype_edac_pci_main_kobj, &edac_subsys->dev_root->kobj, "pci"); if (err) { - debugf1("Failed to register '.../edac/pci'\n"); + edac_dbg(1, "Failed to register '.../edac/pci'\n"); goto kobject_init_and_add_fail; } @@ -392,7 +391,7 @@ static int edac_pci_main_kobj_setup(void) * must be used, for resources to be cleaned up properly */ kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD); - debugf1("Registered '.../edac/pci' kobject\n"); + edac_dbg(1, "Registered '.../edac/pci' kobject\n"); return 0; @@ -421,14 +420,14 @@ decrement_count_fail: */ static void edac_pci_main_kobj_teardown(void) { - debugf0("\n"); + edac_dbg(0, "\n"); /* Decrement the count and only if no more controller instances * are connected perform the unregisteration of the top level * main kobj */ if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { - debugf0("called kobject_put on main kobj\n"); + edac_dbg(0, "called kobject_put on main kobj\n"); kobject_put(edac_pci_top_main_kobj); } edac_put_sysfs_subsys(); @@ -445,7 +444,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) int err; struct kobject *edac_kobj = &pci->kobj; - debugf0("idx=%d\n", pci->pci_idx); + edac_dbg(0, "idx=%d\n", pci->pci_idx); /* create the top main EDAC PCI kobject, IF needed */ err = edac_pci_main_kobj_setup(); @@ -459,8 +458,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) { - debugf0("sysfs_create_link() returned err= %d\n", - err); + edac_dbg(0, "sysfs_create_link() returned err= %d\n", err); goto symlink_fail; } @@ -483,7 +481,7 @@ unregister_cleanup: */ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) { - debugf0("index=%d\n", pci->pci_idx); + edac_dbg(0, "index=%d\n", pci->pci_idx); /* Remove the symlink */ sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); @@ -495,7 +493,7 @@ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) * if this 'pci' is the last instance. * If it is, the main kobject will be unregistered as a result */ - debugf0("calling edac_pci_main_kobj_teardown()\n"); + edac_dbg(0, "calling edac_pci_main_kobj_teardown()\n"); edac_pci_main_kobj_teardown(); } @@ -571,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) local_irq_restore(flags); - debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); + edac_dbg(4, "PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); /* check the status reg for errors on boards NOT marked as broken * if broken, we cannot trust any of the status bits @@ -602,13 +600,15 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) } - debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev)); + edac_dbg(4, "PCI HEADER TYPE= 0x%02x %s\n", + header_type, dev_name(&dev->dev)); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* On bridges, need to examine secondary status register */ status = get_pci_parity_status(dev, 1); - debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); + edac_dbg(4, "PCI SEC_STATUS= 0x%04x %s\n", + status, dev_name(&dev->dev)); /* check the secondary status reg for errors, * on NOT broken boards @@ -670,7 +670,7 @@ void edac_pci_do_parity_check(void) { int before_count; - debugf3("\n"); + edac_dbg(3, "\n"); /* if policy has PCI check off, leave now */ if (!check_pci_errors) diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 67975ba252fa..399aec351aa1 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -275,7 +275,7 @@ static void i3000_check(struct mem_ctl_info *mci) { struct i3000_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i3000_get_error_info(mci, &info); i3000_process_error_info(mci, &info, 1); } @@ -322,7 +322,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) unsigned long mchbar; void __iomem *window; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar); mchbar &= I3000_MCHBAR_MASK; @@ -366,7 +366,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: init mci\n"); + edac_dbg(3, "MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -399,8 +399,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); if (interleaved) cumul_size <<= 1; - debugf3("MC: (%d) cumul_size 0x%x\n", - i, cumul_size); + edac_dbg(3, "MC: (%d) cumul_size 0x%x\n", i, cumul_size); if (cumul_size == last_cumul_size) continue; @@ -429,7 +428,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: failed edac_mc_add_mc()\n"); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } @@ -445,7 +444,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("MC: success\n"); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -461,7 +460,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -477,7 +476,7 @@ static void __devexit i3000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); if (i3000_pci) edac_pci_release_generic_ctl(i3000_pci); @@ -511,7 +510,7 @@ static int __init i3000_init(void) { int pci_rc; - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -525,14 +524,14 @@ static int __init i3000_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_3000_HB, NULL); if (!mci_pdev) { - debugf0("i3000 pci_get_device fail\n"); + edac_dbg(0, "i3000 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = i3000_init_one(mci_pdev, i3000_pci_tbl); if (pci_rc < 0) { - debugf0("i3000 init fail\n"); + edac_dbg(0, "i3000 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -552,7 +551,7 @@ fail0: static void __exit i3000_exit(void) { - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&i3000_driver); if (!i3000_registered) { diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 9698ca39e38a..dfd843a0481b 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -110,10 +110,10 @@ static int how_many_channels(struct pci_dev *pdev) pci_read_config_byte(pdev, I3200_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ - debugf0("In single channel mode.\n"); + edac_dbg(0, "In single channel mode\n"); return 1; } else { - debugf0("In dual channel mode.\n"); + edac_dbg(0, "In dual channel mode\n"); return 2; } } @@ -245,7 +245,7 @@ static void i3200_check(struct mem_ctl_info *mci) { struct i3200_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i3200_get_and_clear_error_info(mci, &info); i3200_process_error_info(mci, &info); } @@ -332,7 +332,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) void __iomem *window; struct i3200_priv *priv; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); window = i3200_map_mchbar(pdev); if (!window) @@ -352,7 +352,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: init mci\n"); + edac_dbg(3, "MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -403,12 +403,12 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: failed edac_mc_add_mc()\n"); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: success\n"); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -424,7 +424,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -441,7 +441,7 @@ static void __devexit i3200_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i3200_priv *priv; - debugf0("\n"); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -475,7 +475,7 @@ static int __init i3200_init(void) { int pci_rc; - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -489,14 +489,14 @@ static int __init i3200_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_3200_HB, NULL); if (!mci_pdev) { - debugf0("i3200 pci_get_device fail\n"); + edac_dbg(0, "i3200 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = i3200_init_one(mci_pdev, i3200_pci_tbl); if (pci_rc < 0) { - debugf0("i3200 init fail\n"); + edac_dbg(0, "i3200 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -516,7 +516,7 @@ fail0: static void __exit i3200_exit(void) { - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&i3200_driver); if (!i3200_registered) { diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 0e16db620ad5..96431a547e46 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -478,10 +478,9 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, ras = NREC_RAS(info->nrecmemb); cas = NREC_CAS(info->nrecmemb); - debugf0("\t\tCSROW= %d Channel= %d " - "(DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channel= %d (DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, bank, + rdwr ? "Write" : "Read", ras, cas); /* Only 1 bit will be on */ switch (allErrors) { @@ -558,7 +557,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, /* ONLY ONE of the possible error bits will be set, as per the docs */ ue_errors = allErrors & FERR_NF_UNCORRECTABLE; if (ue_errors) { - debugf0("\tUncorrected bits= 0x%x\n", ue_errors); + edac_dbg(0, "\tUncorrected bits= 0x%x\n", ue_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); @@ -574,11 +573,9 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, ras = NREC_RAS(info->nrecmemb); cas = NREC_CAS(info->nrecmemb); - debugf0 - ("\t\tCSROW= %d Channels= %d,%d (Branch= %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, channel + 1, branch >> 1, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channels= %d,%d (Branch= %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, channel + 1, branch >> 1, bank, + rdwr ? "Write" : "Read", ras, cas); switch (ue_errors) { case FERR_NF_M12ERR: @@ -630,7 +627,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Check correctable errors */ ce_errors = allErrors & FERR_NF_CORRECTABLE; if (ce_errors) { - debugf0("\tCorrected bits= 0x%x\n", ce_errors); + edac_dbg(0, "\tCorrected bits= 0x%x\n", ce_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); @@ -648,10 +645,9 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, ras = REC_RAS(info->recmemb); cas = REC_CAS(info->recmemb); - debugf0("\t\tCSROW= %d Channel= %d (Branch %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, branch >> 1, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channel= %d (Branch %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, branch >> 1, bank, + rdwr ? "Write" : "Read", ras, cas); switch (ce_errors) { case FERR_NF_M17ERR: @@ -763,7 +759,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci) static void i5000_check_error(struct mem_ctl_info *mci) { struct i5000_error_info info; - debugf4("MC%d\n", mci->mc_idx); + edac_dbg(4, "MC%d\n", mci->mc_idx); i5000_get_error_info(mci, &info); i5000_process_error_info(mci, &info, 1); } @@ -834,15 +830,16 @@ static int i5000_get_devices(struct mem_ctl_info *mci, int dev_idx) pvt->fsb_error_regs = pdev; - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->system_address), - pvt->system_address->vendor, pvt->system_address->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->branchmap_werrors), - pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->fsb_error_regs), - pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->system_address), + pvt->system_address->vendor, pvt->system_address->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->branchmap_werrors), + pvt->branchmap_werrors->vendor, + pvt->branchmap_werrors->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->fsb_error_regs), + pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); pdev = NULL; pdev = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -965,24 +962,25 @@ static void decode_mtr(int slot_row, u16 mtr) ans = MTR_DIMMS_PRESENT(mtr); - debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d=0x%x: DIMMs are %sPresent\n", + slot_row, mtr, ans ? "" : "NOT "); if (!ans) return; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", - MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : - MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : - MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : - "reserved"); - debugf2("\t\tNUMCOL: %s\n", - MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : - MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : - MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : - "reserved"); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANK(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "reserved"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5000_pvt *pvt, int slot, int channel, @@ -1053,7 +1051,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) "--------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1074,7 +1072,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) } p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1084,7 +1082,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) "--------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1097,7 +1095,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1110,7 +1108,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) } /* output the last message and free buffer */ - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); kfree(mem_buffer); } @@ -1140,17 +1138,18 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) maxdimmperch = pvt->maxdimmperch; maxch = pvt->maxch; - debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", - (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); + edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", + (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); /* Get the Branch Map regs */ pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = pvt->tolm << 28; - debugf2("Actual TOLM byte addr=%u (0x%x)\n", actual_tolm, actual_tolm); + edac_dbg(2, "Actual TOLM byte addr=%u (0x%x)\n", + actual_tolm, actual_tolm); pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0); pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1); @@ -1160,15 +1159,18 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) limit = (pvt->mir0 >> 4) & 0x0FFF; way0 = pvt->mir0 & 0x1; way1 = pvt->mir0 & 0x2; - debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir1 >> 4) & 0x0FFF; way0 = pvt->mir1 & 0x1; way1 = pvt->mir1 & 0x2; - debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir2 >> 4) & 0x0FFF; way0 = pvt->mir2 & 0x1; way1 = pvt->mir2 & 0x2; - debugf2("MIR2: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR2: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); /* Get the MTR[0-3] regs */ for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { @@ -1177,31 +1179,31 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_word(pvt->branch_0, where, &pvt->b0_mtr[slot_row]); - debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where, - pvt->b0_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B0 value=0x%x\n", + slot_row, where, pvt->b0_mtr[slot_row]); if (pvt->maxch >= CHANNELS_PER_BRANCH) { pci_read_config_word(pvt->branch_1, where, &pvt->b1_mtr[slot_row]); - debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, - where, pvt->b1_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B1 value=0x%x\n", + slot_row, where, pvt->b1_mtr[slot_row]); } else { pvt->b1_mtr[slot_row] = 0; } } /* Read and dump branch 0's MTRs */ - debugf2("\nMemory Technology Registers:\n"); - debugf2(" Branch 0:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); + edac_dbg(2, " Branch 0:\n"); for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { decode_mtr(slot_row, pvt->b0_mtr[slot_row]); } pci_read_config_word(pvt->branch_0, AMB_PRESENT_0, &pvt->b0_ambpresent0); - debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); pci_read_config_word(pvt->branch_0, AMB_PRESENT_1, &pvt->b0_ambpresent1); - debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); /* Only if we have 2 branchs (4 channels) */ if (pvt->maxch < CHANNELS_PER_BRANCH) { @@ -1209,18 +1211,18 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pvt->b1_ambpresent1 = 0; } else { /* Read and dump branch 1's MTRs */ - debugf2(" Branch 1:\n"); + edac_dbg(2, " Branch 1:\n"); for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { decode_mtr(slot_row, pvt->b1_mtr[slot_row]); } pci_read_config_word(pvt->branch_1, AMB_PRESENT_0, &pvt->b1_ambpresent0); - debugf2("\t\tAMB-Branch 1-present0 0x%x:\n", - pvt->b1_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 1-present0 0x%x:\n", + pvt->b1_ambpresent0); pci_read_config_word(pvt->branch_1, AMB_PRESENT_1, &pvt->b1_ambpresent1); - debugf2("\t\tAMB-Branch 1-present1 0x%x:\n", - pvt->b1_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 1-present1 0x%x:\n", + pvt->b1_ambpresent1); } /* Go and determine the size of each DIMM and place in an @@ -1355,9 +1357,9 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) int num_channels; int num_dimms_per_channel; - debugf0("MC: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1379,8 +1381,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, &num_channels); - debugf0("MC: Number of Branches=2 Channels= %d DIMMS= %d\n", - num_channels, num_dimms_per_channel); + edac_dbg(0, "MC: Number of Branches=2 Channels= %d DIMMS= %d\n", + num_channels, num_dimms_per_channel); /* allocate a new MC control structure */ @@ -1397,7 +1399,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s(): mci = %p\n", __FILE__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1429,19 +1431,16 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) /* initialize the MC control structure 'csrows' table * with the mapping and control information */ if (i5000_init_csrows(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i5000_init_csrows() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i5000_init_csrows() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i5000_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s(): failed edac_mc_add_mc()\n", - __FILE__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1485,7 +1484,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __FILE__); + edac_dbg(0, "MC:\n"); /* wake up device */ rc = pci_enable_device(pdev); @@ -1504,7 +1503,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __FILE__); + edac_dbg(0, "\n"); if (i5000_pci) edac_pci_release_generic_ctl(i5000_pci); @@ -1550,7 +1549,7 @@ static int __init i5000_init(void) { int pci_rc; - debugf2("MC: %s()\n", __FILE__); + edac_dbg(2, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1566,7 +1565,7 @@ static int __init i5000_init(void) */ static void __exit i5000_exit(void) { - debugf2("MC: %s()\n", __FILE__); + edac_dbg(2, "MC:\n"); pci_unregister_driver(&i5000_driver); } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 19aa2843c46a..a9b996c8ef2d 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -859,8 +859,8 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) i5100_rank_to_slot(mci, chan, rank)); } - debugf2("dimm channel %d, rank %d, size %ld\n", - chan, rank, (long)PAGES_TO_MiB(npages)); + edac_dbg(2, "dimm channel %d, rank %d, size %ld\n", + chan, rank, (long)PAGES_TO_MiB(npages)); } } diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 3004b946c403..90fad3a9c3f7 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -542,10 +542,9 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, ras = nrec_ras(info); cas = nrec_cas(info); - debugf0("\t\tDIMM= %d Channels= %d,%d (Branch= %d " - "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, channel + 1, branch >> 1, bank, - buf_id, rdwr_str(rdwr), ras, cas); + edac_dbg(0, "\t\tDIMM= %d Channels= %d,%d (Branch= %d DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, channel + 1, branch >> 1, bank, + buf_id, rdwr_str(rdwr), ras, cas); /* Only 1 bit will be on */ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); @@ -595,7 +594,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Correctable errors */ if (allErrors & ERROR_NF_CORRECTABLE) { - debugf0("\tCorrected bits= 0x%lx\n", allErrors); + edac_dbg(0, "\tCorrected bits= 0x%lx\n", allErrors); branch = extract_fbdchan_indx(info->ferr_nf_fbd); @@ -616,10 +615,9 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Only 1 bit will be on */ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); - debugf0("\t\tDIMM= %d Channel= %d (Branch %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, branch >> 1, bank, - rdwr_str(rdwr), ras, cas); + edac_dbg(0, "\t\tDIMM= %d Channel= %d (Branch %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, branch >> 1, bank, + rdwr_str(rdwr), ras, cas); /* Form out message */ snprintf(msg, sizeof(msg), @@ -682,7 +680,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci) static void i5400_check_error(struct mem_ctl_info *mci) { struct i5400_error_info info; - debugf4("MC%d\n", mci->mc_idx); + edac_dbg(4, "MC%d\n", mci->mc_idx); i5400_get_error_info(mci, &info); i5400_process_error_info(mci, &info); } @@ -768,15 +766,16 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) } pvt->fsb_error_regs = pdev; - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->system_address), - pvt->system_address->vendor, pvt->system_address->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->branchmap_werrors), - pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->fsb_error_regs), - pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->system_address), + pvt->system_address->vendor, pvt->system_address->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->branchmap_werrors), + pvt->branchmap_werrors->vendor, + pvt->branchmap_werrors->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->fsb_error_regs), + pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); pvt->branch_0 = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0, NULL); @@ -864,8 +863,8 @@ static int determine_mtr(struct i5400_pvt *pvt, int dimm, int channel) n = dimm; if (n >= DIMMS_PER_CHANNEL) { - debugf0("ERROR: trying to access an invalid dimm: %d\n", - dimm); + edac_dbg(0, "ERROR: trying to access an invalid dimm: %d\n", + dimm); return 0; } @@ -885,28 +884,29 @@ static void decode_mtr(int slot_row, u16 mtr) ans = MTR_DIMMS_PRESENT(mtr); - debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d=0x%x: DIMMs are %sPresent\n", + slot_row, mtr, ans ? "" : "NOT "); if (!ans) return; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - - debugf2("\t\tELECTRICAL THROTTLING is %s\n", - MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); - - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", - MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : - MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : - MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : - "65,536 - 16 rows"); - debugf2("\t\tNUMCOL: %s\n", - MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : - MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : - MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : - "reserved"); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + + edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n", + MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); + + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANK(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5400_pvt *pvt, int dimm, int channel, @@ -979,7 +979,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) "-------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -994,7 +994,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1004,7 +1004,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) "-------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1019,7 +1019,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) } space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1032,7 +1032,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) } /* output the last message and free buffer */ - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); kfree(mem_buffer); } @@ -1062,18 +1062,18 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) maxdimmperch = pvt->maxdimmperch; maxch = pvt->maxch; - debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", - (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); + edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", + (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); /* Get the Branch Map regs */ pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "\nTOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); - debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", - actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n", + actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0); pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1); @@ -1082,11 +1082,13 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) limit = (pvt->mir0 >> 4) & 0x0fff; way0 = pvt->mir0 & 0x1; way1 = pvt->mir0 & 0x2; - debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir1 >> 4) & 0xfff; way0 = pvt->mir1 & 0x1; way1 = pvt->mir1 & 0x2; - debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); /* Get the set of MTR[0-3] regs by each branch */ for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) { @@ -1096,8 +1098,8 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_word(pvt->branch_0, where, &pvt->b0_mtr[slot_row]); - debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where, - pvt->b0_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B0 value=0x%x\n", + slot_row, where, pvt->b0_mtr[slot_row]); if (pvt->maxch < CHANNELS_PER_BRANCH) { pvt->b1_mtr[slot_row] = 0; @@ -1107,22 +1109,22 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) /* Branch 1 set of MTR registers */ pci_read_config_word(pvt->branch_1, where, &pvt->b1_mtr[slot_row]); - debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, where, - pvt->b1_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B1 value=0x%x\n", + slot_row, where, pvt->b1_mtr[slot_row]); } /* Read and dump branch 0's MTRs */ - debugf2("\nMemory Technology Registers:\n"); - debugf2(" Branch 0:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); + edac_dbg(2, " Branch 0:\n"); for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) decode_mtr(slot_row, pvt->b0_mtr[slot_row]); pci_read_config_word(pvt->branch_0, AMBPRESENT_0, &pvt->b0_ambpresent0); - debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); pci_read_config_word(pvt->branch_0, AMBPRESENT_1, &pvt->b0_ambpresent1); - debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); /* Only if we have 2 branchs (4 channels) */ if (pvt->maxch < CHANNELS_PER_BRANCH) { @@ -1130,18 +1132,18 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) pvt->b1_ambpresent1 = 0; } else { /* Read and dump branch 1's MTRs */ - debugf2(" Branch 1:\n"); + edac_dbg(2, " Branch 1:\n"); for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) decode_mtr(slot_row, pvt->b1_mtr[slot_row]); pci_read_config_word(pvt->branch_1, AMBPRESENT_0, &pvt->b1_ambpresent0); - debugf2("\t\tAMB-Branch 1-present0 0x%x:\n", - pvt->b1_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 1-present0 0x%x:\n", + pvt->b1_ambpresent0); pci_read_config_word(pvt->branch_1, AMBPRESENT_1, &pvt->b1_ambpresent1); - debugf2("\t\tAMB-Branch 1-present1 0x%x:\n", - pvt->b1_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 1-present1 0x%x:\n", + pvt->b1_ambpresent1); } /* Go and determine the size of each DIMM and place in an @@ -1193,9 +1195,9 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) size_mb = pvt->dimm_info[slot][channel].megabytes; - debugf2("dimm (branch %d channel %d slot %d): %d.%03d GB\n", - channel / 2, channel % 2, slot, - size_mb / 1000, size_mb % 1000); + edac_dbg(2, "dimm (branch %d channel %d slot %d): %d.%03d GB\n", + channel / 2, channel % 2, slot, + size_mb / 1000, size_mb % 1000); dimm->nr_pages = size_mb << 8; dimm->grain = 8; @@ -1259,9 +1261,9 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (dev_idx >= ARRAY_SIZE(i5400_devs)) return -EINVAL; - debugf0("MC: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1285,7 +1287,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s(): mci = %p\n", __FILE__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1317,19 +1319,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) /* initialize the MC control structure 'dimms' table * with the mapping and control information */ if (i5400_init_dimms(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i5400_init_dimms() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i5400_init_dimms() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no dimms found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i5400_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s(): failed edac_mc_add_mc()\n", - __FILE__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1373,7 +1372,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __FILE__); + edac_dbg(0, "MC:\n"); /* wake up device */ rc = pci_enable_device(pdev); @@ -1392,7 +1391,7 @@ static void __devexit i5400_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __FILE__); + edac_dbg(0, "\n"); if (i5400_pci) edac_pci_release_generic_ctl(i5400_pci); @@ -1438,7 +1437,7 @@ static int __init i5400_init(void) { int pci_rc; - debugf2("MC: %s()\n", __FILE__); + edac_dbg(2, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1454,7 +1453,7 @@ static int __init i5400_init(void) */ static void __exit i5400_exit(void) { - debugf2("MC: %s()\n", __FILE__); + edac_dbg(2, "MC:\n"); pci_unregister_driver(&i5400_driver); } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 7eca688f7885..738b8919194f 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -596,9 +596,8 @@ static int decode_mtr(struct i7300_pvt *pvt, mtr = pvt->mtr[slot][branch]; ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0; - debugf2("\tMTR%d CH%d: DIMMs are %s (mtr)\n", - slot, channel, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d CH%d: DIMMs are %sPresent (mtr)\n", + slot, channel, ans ? "" : "NOT "); /* Determine if there is a DIMM present in this DIMM slot */ if (!ans) @@ -620,24 +619,25 @@ static int decode_mtr(struct i7300_pvt *pvt, dinfo->megabytes = 1 << addrBits; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - - debugf2("\t\tELECTRICAL THROTTLING is %s\n", - MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); - - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANKS(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", - MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : - MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : - MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : - "65,536 - 16 rows"); - debugf2("\t\tNUMCOL: %s\n", - MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : - MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : - MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : - "reserved"); - debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + + edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n", + MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); + + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANKS(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); + edac_dbg(2, "\t\tSIZE: %d MB\n", dinfo->megabytes); /* * The type of error detection actually depends of the @@ -653,9 +653,9 @@ static int decode_mtr(struct i7300_pvt *pvt, dimm->mtype = MEM_FB_DDR2; if (IS_SINGLE_MODE(pvt->mc_settings_a)) { dimm->edac_mode = EDAC_SECDED; - debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); + edac_dbg(2, "\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); } else { - debugf2("\t\tECC code is on Lockstep mode\n"); + edac_dbg(2, "\t\tECC code is on Lockstep mode\n"); if (MTR_DRAM_WIDTH(mtr) == 8) dimm->edac_mode = EDAC_S8ECD8ED; else @@ -664,9 +664,9 @@ static int decode_mtr(struct i7300_pvt *pvt, /* ask what device type on this row */ if (MTR_DRAM_WIDTH(mtr) == 8) { - debugf2("\t\tScrub algorithm for x8 is on %s mode\n", - IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? - "enhanced" : "normal"); + edac_dbg(2, "\t\tScrub algorithm for x8 is on %s mode\n", + IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? + "enhanced" : "normal"); dimm->dtype = DEV_X8; } else @@ -700,14 +700,14 @@ static void print_dimm_size(struct i7300_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; n = snprintf(p, space, "-------------------------------" "------------------------------"); p += n; space -= n; - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; @@ -723,7 +723,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) space -= n; } - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; } @@ -732,7 +732,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) "------------------------------"); p += n; space -= n; - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; #endif @@ -755,7 +755,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) pvt = mci->pvt_info; - debugf2("Memory Technology Registers:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); /* Get the AMB present registers for the four channels */ for (branch = 0; branch < MAX_BRANCHES; branch++) { @@ -764,15 +764,15 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_0, &pvt->ambpresent[channel]); - debugf2("\t\tAMB-present CH%d = 0x%x:\n", - channel, pvt->ambpresent[channel]); + edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); channel = to_channel(1, branch); pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1, &pvt->ambpresent[channel]); - debugf2("\t\tAMB-present CH%d = 0x%x:\n", - channel, pvt->ambpresent[channel]); + edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); } /* Get the set of MTR[0-7] regs by each branch */ @@ -814,12 +814,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) static void decode_mir(int mir_no, u16 mir[MAX_MIR]) { if (mir[mir_no] & 3) - debugf2("MIR%d: limit= 0x%x Branch(es) that participate:" - " %s %s\n", - mir_no, - (mir[mir_no] >> 4) & 0xfff, - (mir[mir_no] & 1) ? "B0" : "", - (mir[mir_no] & 2) ? "B1" : ""); + edac_dbg(2, "MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n", + mir_no, + (mir[mir_no] >> 4) & 0xfff, + (mir[mir_no] & 1) ? "B0" : "", + (mir[mir_no] & 2) ? "B1" : ""); } /** @@ -839,17 +838,17 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE, (u32 *) &pvt->ambase); - debugf2("AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); + edac_dbg(2, "AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); /* Get the Branch Map regs */ pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("TOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); - debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", - actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n", + actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); /* Get memory controller settings */ pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, @@ -858,15 +857,15 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) &pvt->mc_settings_a); if (IS_SINGLE_MODE(pvt->mc_settings_a)) - debugf0("Memory controller operating on single mode\n"); + edac_dbg(0, "Memory controller operating on single mode\n"); else - debugf0("Memory controller operating on %s mode\n", - IS_MIRRORED(pvt->mc_settings) ? "mirrored" : "non-mirrored"); + edac_dbg(0, "Memory controller operating on %smirrored mode\n", + IS_MIRRORED(pvt->mc_settings) ? "" : "non-"); - debugf0("Error detection is %s\n", - IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); - debugf0("Retry is %s\n", - IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); + edac_dbg(0, "Error detection is %s\n", + IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); + edac_dbg(0, "Retry is %s\n", + IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); /* Get Memory Interleave Range registers */ pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, @@ -960,18 +959,18 @@ static int __devinit i7300_get_devices(struct mem_ctl_info *mci) } } - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_0_fsb_ctlr), - pvt->pci_dev_16_0_fsb_ctlr->vendor, - pvt->pci_dev_16_0_fsb_ctlr->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_1_fsb_addr_map), - pvt->pci_dev_16_1_fsb_addr_map->vendor, - pvt->pci_dev_16_1_fsb_addr_map->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_2_fsb_err_regs), - pvt->pci_dev_16_2_fsb_err_regs->vendor, - pvt->pci_dev_16_2_fsb_err_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_0_fsb_ctlr), + pvt->pci_dev_16_0_fsb_ctlr->vendor, + pvt->pci_dev_16_0_fsb_ctlr->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_1_fsb_addr_map), + pvt->pci_dev_16_1_fsb_addr_map->vendor, + pvt->pci_dev_16_1_fsb_addr_map->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_2_fsb_err_regs), + pvt->pci_dev_16_2_fsb_err_regs->vendor, + pvt->pci_dev_16_2_fsb_err_regs->device); pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, @@ -1022,9 +1021,9 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (rc == -EIO) return rc; - debugf0("MC: pdev bus %u dev=0x%x fn=0x%x\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1044,7 +1043,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (mci == NULL) return -ENOMEM; - debugf0("MC: mci = %p\n", mci); + edac_dbg(0, "MC: mci = %p\n", mci); mci->pdev = &pdev->dev; /* record ptr to the generic device */ @@ -1077,18 +1076,16 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, /* initialize the MC control structure 'csrows' table * with the mapping and control information */ if (i7300_get_mc_regs(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i7300_init_csrows() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i7300_init_csrows() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i7300_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: failed edac_mc_add_mc()\n"); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1130,7 +1127,7 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; char *tmp; - debugf0("\n"); + edac_dbg(0, "\n"); if (i7300_pci) edac_pci_release_generic_ctl(i7300_pci); @@ -1177,7 +1174,7 @@ static int __init i7300_init(void) { int pci_rc; - debugf2("\n"); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1192,7 +1189,7 @@ static int __init i7300_init(void) */ static void __exit i7300_exit(void) { - debugf2("\n"); + edac_dbg(2, "\n"); pci_unregister_driver(&i7300_driver); } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index f851a433d620..0899d7da7248 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -516,29 +516,28 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod); pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map); - debugf0("QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n", - pvt->i7core_dev->socket, pvt->info.mc_control, pvt->info.mc_status, - pvt->info.max_dod, pvt->info.ch_map); + edac_dbg(0, "QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n", + pvt->i7core_dev->socket, pvt->info.mc_control, + pvt->info.mc_status, pvt->info.max_dod, pvt->info.ch_map); if (ECC_ENABLED(pvt)) { - debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4); + edac_dbg(0, "ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4); if (ECCx8(pvt)) mode = EDAC_S8ECD8ED; else mode = EDAC_S4ECD4ED; } else { - debugf0("ECC disabled\n"); + edac_dbg(0, "ECC disabled\n"); mode = EDAC_NONE; } /* FIXME: need to handle the error codes */ - debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked " - "x%x x 0x%x\n", - numdimms(pvt->info.max_dod), - numrank(pvt->info.max_dod >> 2), - numbank(pvt->info.max_dod >> 4), - numrow(pvt->info.max_dod >> 6), - numcol(pvt->info.max_dod >> 9)); + edac_dbg(0, "DOD Max limits: DIMMS: %d, %d-ranked, %d-banked x%x x 0x%x\n", + numdimms(pvt->info.max_dod), + numrank(pvt->info.max_dod >> 2), + numbank(pvt->info.max_dod >> 4), + numrow(pvt->info.max_dod >> 6), + numcol(pvt->info.max_dod >> 9)); for (i = 0; i < NUM_CHANS; i++) { u32 data, dimm_dod[3], value[8]; @@ -547,11 +546,11 @@ static int get_dimm_config(struct mem_ctl_info *mci) continue; if (!CH_ACTIVE(pvt, i)) { - debugf0("Channel %i is not active\n", i); + edac_dbg(0, "Channel %i is not active\n", i); continue; } if (CH_DISABLED(pvt, i)) { - debugf0("Channel %i is disabled\n", i); + edac_dbg(0, "Channel %i is disabled\n", i); continue; } @@ -582,15 +581,14 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_ch[i][1], MC_DOD_CH_DIMM2, &dimm_dod[2]); - debugf0("Ch%d phy rd%d, wr%d (0x%08x): " - "%s%s%s%cDIMMs\n", - i, - RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), - data, - pvt->channel[i].is_3dimms_present ? "3DIMMS " : "", - pvt->channel[i].is_3dimms_present ? "SINGLE_4R " : "", - pvt->channel[i].has_4rank ? "HAS_4R " : "", - (data & REGISTERED_DIMM) ? 'R' : 'U'); + edac_dbg(0, "Ch%d phy rd%d, wr%d (0x%08x): %s%s%s%cDIMMs\n", + i, + RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), + data, + pvt->channel[i].is_3dimms_present ? "3DIMMS " : "", + pvt->channel[i].is_3dimms_present ? "SINGLE_4R " : "", + pvt->channel[i].has_4rank ? "HAS_4R " : "", + (data & REGISTERED_DIMM) ? 'R' : 'U'); for (j = 0; j < 3; j++) { u32 banks, ranks, rows, cols; @@ -609,11 +607,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) /* DDR3 has 8 I/O banks */ size = (rows * cols * banks * ranks) >> (20 - 3); - debugf0("\tdimm %d %d Mb offset: %x, " - "bank: %d, rank: %d, row: %#x, col: %#x\n", - j, size, - RANKOFFSET(dimm_dod[j]), - banks, ranks, rows, cols); + edac_dbg(0, "\tdimm %d %d Mb offset: %x, bank: %d, rank: %d, row: %#x, col: %#x\n", + j, size, + RANKOFFSET(dimm_dod[j]), + banks, ranks, rows, cols); npages = MiB_TO_PAGES(size); @@ -649,12 +646,12 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]); pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]); pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]); - debugf1("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i); + edac_dbg(1, "\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i); for (j = 0; j < 8; j++) - debugf1("\t\t%#x\t%#x\t%#x\n", - (value[j] >> 27) & 0x1, - (value[j] >> 24) & 0x7, - (value[j] & ((1 << 24) - 1))); + edac_dbg(1, "\t\t%#x\t%#x\t%#x\n", + (value[j] >> 27) & 0x1, + (value[j] >> 24) & 0x7, + (value[j] & ((1 << 24) - 1))); } return 0; @@ -824,7 +821,7 @@ static ssize_t i7core_inject_store_##param( \ long value; \ int rc; \ \ - debugf1("\n"); \ + edac_dbg(1, "\n"); \ pvt = mci->pvt_info; \ \ if (pvt->inject.enable) \ @@ -852,7 +849,7 @@ static ssize_t i7core_inject_show_##param( \ struct i7core_pvt *pvt; \ \ pvt = mci->pvt_info; \ - debugf1("pvt=%p\n", pvt); \ + edac_dbg(1, "pvt=%p\n", pvt); \ if (pvt->inject.param < 0) \ return sprintf(data, "any\n"); \ else \ @@ -883,9 +880,9 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val) u32 read; int count; - debugf0("setting pci %02x:%02x.%x reg=%02x value=%08x\n", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - where, val); + edac_dbg(0, "setting pci %02x:%02x.%x reg=%02x value=%08x\n", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), + where, val); for (count = 0; count < 10; count++) { if (count) @@ -1020,9 +1017,8 @@ static ssize_t i7core_inject_enable_store(struct device *dev, pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 8); - debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," - " inject 0x%08x\n", - mask, pvt->inject.eccmask, injectmask); + edac_dbg(0, "Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n", + mask, pvt->inject.eccmask, injectmask); return count; @@ -1042,7 +1038,7 @@ static ssize_t i7core_inject_enable_show(struct device *dev, pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], MC_CHANNEL_ERROR_INJECT, &injectmask); - debugf0("Inject error read: 0x%018x\n", injectmask); + edac_dbg(0, "Inject error read: 0x%018x\n", injectmask); if (injectmask & 0x0c) pvt->inject.enable = 1; @@ -1059,7 +1055,7 @@ static ssize_t i7core_show_counter_##param( \ struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt = mci->pvt_info; \ \ - debugf1("\n"); \ + edac_dbg(1, "\n"); \ if (!pvt->ce_count_available || (pvt->is_registered)) \ return sprintf(data, "data unavailable\n"); \ return sprintf(data, "%lu\n", \ @@ -1104,7 +1100,7 @@ static const struct attribute_group *addrmatch_groups[] = { static void addrmatch_release(struct device *device) { - debugf1("Releasing device %s\n", dev_name(device)); + edac_dbg(1, "Releasing device %s\n", dev_name(device)); kfree(device); } @@ -1135,7 +1131,7 @@ static const struct attribute_group *all_channel_counts_groups[] = { static void all_channel_counts_release(struct device *device) { - debugf1("Releasing device %s\n", dev_name(device)); + edac_dbg(1, "Releasing device %s\n", dev_name(device)); kfree(device); } @@ -1190,7 +1186,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) dev_set_name(pvt->addrmatch_dev, "inject_addrmatch"); dev_set_drvdata(pvt->addrmatch_dev, mci); - debugf1("creating %s\n", dev_name(pvt->addrmatch_dev)); + edac_dbg(1, "creating %s\n", dev_name(pvt->addrmatch_dev)); rc = device_add(pvt->addrmatch_dev); if (rc < 0) @@ -1212,7 +1208,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) dev_set_name(pvt->chancounts_dev, "all_channel_counts"); dev_set_drvdata(pvt->chancounts_dev, mci); - debugf1("creating %s\n", dev_name(pvt->chancounts_dev)); + edac_dbg(1, "creating %s\n", dev_name(pvt->chancounts_dev)); rc = device_add(pvt->chancounts_dev); if (rc < 0) @@ -1225,7 +1221,7 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) { struct i7core_pvt *pvt = mci->pvt_info; - debugf1("\n"); + edac_dbg(1, "\n"); device_remove_file(&mci->dev, &dev_attr_inject_section); device_remove_file(&mci->dev, &dev_attr_inject_type); @@ -1252,14 +1248,14 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev) { int i; - debugf0("\n"); + edac_dbg(0, "\n"); for (i = 0; i < i7core_dev->n_devs; i++) { struct pci_dev *pdev = i7core_dev->pdev[i]; if (!pdev) continue; - debugf0("Removing dev %02x:%02x.%d\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "Removing dev %02x:%02x.%d\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); pci_dev_put(pdev); } } @@ -1302,12 +1298,12 @@ static unsigned i7core_pci_lastbus(void) while ((b = pci_find_next_bus(b)) != NULL) { bus = b->number; - debugf0("Found bus %d\n", bus); + edac_dbg(0, "Found bus %d\n", bus); if (bus > last_bus) last_bus = bus; } - debugf0("Last bus %d\n", last_bus); + edac_dbg(0, "Last bus %d\n", last_bus); return last_bus; } @@ -1414,10 +1410,10 @@ static int i7core_get_onedevice(struct pci_dev **prev, return -ENODEV; } - debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", - socket, bus, dev_descr->dev, - dev_descr->func, - PCI_VENDOR_ID_INTEL, dev_descr->dev_id); + edac_dbg(0, "Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", + socket, bus, dev_descr->dev, + dev_descr->func, + PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* * As stated on drivers/pci/search.c, the reference count for @@ -1515,13 +1511,13 @@ static int mci_bind_devs(struct mem_ctl_info *mci, family = "unknown"; pvt->enable_scrub = false; } - debugf0("Detected a processor type %s\n", family); + edac_dbg(0, "Detected a processor type %s\n", family); } else goto error; - debugf0("Associated fn %d.%d, dev = %p, socket %d\n", - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pdev, i7core_dev->socket); + edac_dbg(0, "Associated fn %d.%d, dev = %p, socket %d\n", + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev, i7core_dev->socket); if (PCI_SLOT(pdev->devfn) == 3 && PCI_FUNC(pdev->devfn) == 2) @@ -1618,8 +1614,8 @@ static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5, &rcv[2][1]); for (i = 0 ; i < 3; i++) { - debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n", - (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]); + edac_dbg(3, "MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n", + (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]); /*if the channel has 3 dimms*/ if (pvt->channel[i].dimms > 2) { new0 = DIMM_BOT_COR_ERR(rcv[i][0]); @@ -1650,7 +1646,7 @@ static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci) int new0, new1, new2; if (!pvt->pci_mcr[4]) { - debugf0("MCR registers not found\n"); + edac_dbg(0, "MCR registers not found\n"); return; } @@ -2188,7 +2184,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) struct i7core_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: dev = %p\n", &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: dev = %p\n", &i7core_dev->pdev[0]->dev); i7core_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -2196,7 +2192,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) pvt = mci->pvt_info; - debugf0("MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); /* Disable scrubrate setting */ if (pvt->enable_scrub) @@ -2211,7 +2207,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) i7core_delete_sysfs_devices(mci); edac_mc_del_mc(mci->pdev); - debugf1("%s: free mci struct\n", mci->ctl_name); + edac_dbg(1, "%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); edac_mc_free(mci); i7core_dev->mci = NULL; @@ -2237,7 +2233,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -2280,7 +2276,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: failed edac_mc_add_mc()\n"); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -2289,7 +2285,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) goto fail0; } if (i7core_create_sysfs_devices(mci)) { - debugf0("MC: failed to create sysfs nodes\n"); + edac_dbg(0, "MC: failed to create sysfs nodes\n"); edac_mc_del_mc(mci->pdev); rc = -EINVAL; goto fail0; @@ -2395,7 +2391,7 @@ static void __devexit i7core_remove(struct pci_dev *pdev) { struct i7core_dev *i7core_dev; - debugf0("\n"); + edac_dbg(0, "\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -2444,7 +2440,7 @@ static int __init i7core_init(void) { int pci_rc; - debugf2("\n"); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -2469,7 +2465,7 @@ static int __init i7core_init(void) */ static void __exit i7core_exit(void) { - debugf2("\n"); + edac_dbg(2, "\n"); pci_unregister_driver(&i7core_driver); } diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index c43214fdf2d8..475bde1c4508 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -178,7 +178,7 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci) { struct i82443bxgx_edacmc_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82443bxgx_edacmc_get_error_info(mci, &info); i82443bxgx_edacmc_process_error_info(mci, &info, 1); } @@ -201,14 +201,13 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, dimm = csrow->channels[0]->dimm; pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); - debugf1("MC%d: Row=%d DRB = %#0x\n", - mci->mc_idx,index, drbar); + edac_dbg(1, "MC%d: Row=%d DRB = %#0x\n", + mci->mc_idx, index, drbar); row_high_limit = ((u32) drbar << 23); /* find the DRAM Chip Select Base address and mask */ - debugf1("MC%d: Row=%d, " - "Boundary Address=%#0x, Last = %#0x\n", - mci->mc_idx, index, row_high_limit, - row_high_limit_last); + edac_dbg(1, "MC%d: Row=%d, Boundary Address=%#0x, Last = %#0x\n", + mci->mc_idx, index, row_high_limit, + row_high_limit_last); /* 440GX goes to 2GB, represented with a DRB of 0. */ if (row_high_limit_last && !row_high_limit) @@ -241,7 +240,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) enum mem_type mtype; enum edac_type edac_mode; - debugf0("MC: %s()\n", __FILE__); + edac_dbg(0, "MC:\n"); /* Something is really hosed if PCI config space reads from * the MC aren't working. @@ -259,7 +258,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s(): mci = %p\n", __FILE__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -275,8 +274,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) mtype = MEM_RDR; break; default: - debugf0("Unknown/reserved DRAM type value " - "in DRAMC register!\n"); + edac_dbg(0, "Unknown/reserved DRAM type value in DRAMC register!\n"); mtype = -MEM_UNKNOWN; } @@ -305,8 +303,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) edac_mode = EDAC_SECDED; break; default: - debugf0("Unknown/reserved ECC state " - "in NBXCFG register!\n"); + edac_dbg(0, "Unknown/reserved ECC state in NBXCFG register!\n"); edac_mode = EDAC_UNKNOWN; break; } @@ -330,7 +327,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) mci->ctl_page_to_phys = NULL; if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -345,7 +342,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("MC: %s(): success\n", __FILE__); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -361,7 +358,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __FILE__); + edac_dbg(0, "MC:\n"); /* don't need to call pci_enable_device() */ rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); @@ -376,7 +373,7 @@ static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __FILE__); + edac_dbg(0, "\n"); if (i82443bxgx_pci) edac_pci_release_generic_ctl(i82443bxgx_pci); @@ -428,7 +425,7 @@ static int __init i82443bxgx_edacmc_init(void) id = &i82443bxgx_pci_tbl[i]; } if (!mci_pdev) { - debugf0("i82443bxgx pci_get_device fail\n"); + edac_dbg(0, "i82443bxgx pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -436,7 +433,7 @@ static int __init i82443bxgx_edacmc_init(void) pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl); if (pci_rc < 0) { - debugf0("i82443bxgx init fail\n"); + edac_dbg(0, "i82443bxgx init fail\n"); pci_rc = -ENODEV; goto fail1; } diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index d4ec21db22ba..832e7dd2c5fa 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -136,7 +136,7 @@ static void i82860_check(struct mem_ctl_info *mci) { struct i82860_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82860_get_error_info(mci, &info); i82860_process_error_info(mci, &info, 1); } @@ -167,8 +167,7 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) pci_read_config_word(pdev, I82860_GBA + index * 2, &value); cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); - debugf3("(%d) cumul_size 0x%x\n", index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -210,7 +209,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -229,7 +228,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -245,7 +244,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; @@ -260,7 +259,7 @@ static int __devinit i82860_init_one(struct pci_dev *pdev, { int rc; - debugf0("\n"); + edac_dbg(0, "\n"); i82860_printk(KERN_INFO, "i82860 init one\n"); if (pci_enable_device(pdev) < 0) @@ -278,7 +277,7 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); if (i82860_pci) edac_pci_release_generic_ctl(i82860_pci); @@ -311,7 +310,7 @@ static int __init i82860_init(void) { int pci_rc; - debugf3("\n"); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -324,7 +323,7 @@ static int __init i82860_init(void) PCI_DEVICE_ID_INTEL_82860_0, NULL); if (mci_pdev == NULL) { - debugf0("860 pci_get_device fail\n"); + edac_dbg(0, "860 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -332,7 +331,7 @@ static int __init i82860_init(void) pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); if (pci_rc < 0) { - debugf0("860 init fail\n"); + edac_dbg(0, "860 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -352,7 +351,7 @@ fail0: static void __exit i82860_exit(void) { - debugf3("\n"); + edac_dbg(3, "\n"); pci_unregister_driver(&i82860_driver); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 4ded498047f7..db64bd74bc54 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -263,7 +263,7 @@ static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82875p_get_error_info(mci, &info); i82875p_process_error_info(mci, &info, 1); } @@ -371,8 +371,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, value = readb(ovrfl_window + I82875P_DRB + index); cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); - debugf3("(%d) cumul_size 0x%x\n", index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -405,7 +404,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) u32 nr_chans; struct i82875p_error_info discard; - debugf0("\n"); + edac_dbg(0, "\n"); ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); @@ -426,7 +425,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -437,7 +436,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("init pvt\n"); + edac_dbg(3, "init pvt\n"); pvt = (struct i82875p_pvt *)mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; pvt->ovrfl_window = ovrfl_window; @@ -448,7 +447,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail1; } @@ -464,7 +463,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail1: @@ -485,7 +484,7 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev, { int rc; - debugf0("\n"); + edac_dbg(0, "\n"); i82875p_printk(KERN_INFO, "i82875p init one\n"); if (pci_enable_device(pdev) < 0) @@ -504,7 +503,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82875p_pvt *pvt = NULL; - debugf0("\n"); + edac_dbg(0, "\n"); if (i82875p_pci) edac_pci_release_generic_ctl(i82875p_pci); @@ -550,7 +549,7 @@ static int __init i82875p_init(void) { int pci_rc; - debugf3("\n"); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -565,7 +564,7 @@ static int __init i82875p_init(void) PCI_DEVICE_ID_INTEL_82875_0, NULL); if (!mci_pdev) { - debugf0("875p pci_get_device fail\n"); + edac_dbg(0, "875p pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -573,7 +572,7 @@ static int __init i82875p_init(void) pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); if (pci_rc < 0) { - debugf0("875p init fail\n"); + edac_dbg(0, "875p init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -593,7 +592,7 @@ fail0: static void __exit i82875p_exit(void) { - debugf3("\n"); + edac_dbg(3, "\n"); i82875p_remove_one(mci_pdev); pci_dev_put(mci_pdev); diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 91b9e33fff27..974d1a2be379 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -331,7 +331,7 @@ static void i82975x_check(struct mem_ctl_info *mci) { struct i82975x_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82975x_get_error_info(mci, &info); i82975x_process_error_info(mci, &info, 1); } @@ -406,8 +406,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ if (csrow->nr_channels > 1) cumul_size <<= 1; - debugf3("(%d) cumul_size 0x%x\n", index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); nr_pages = cumul_size - last_cumul_size; if (!nr_pages) @@ -489,11 +488,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) u8 c1drb[4]; #endif - debugf0("\n"); + edac_dbg(0, "\n"); pci_read_config_dword(pdev, I82975X_MCHBAR, &mchbar); if (!(mchbar & 1)) { - debugf3("failed, MCHBAR disabled!\n"); + edac_dbg(3, "failed, MCHBAR disabled!\n"); goto fail0; } mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ @@ -558,7 +557,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) goto fail1; } - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -569,7 +568,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82975x_check; mci->ctl_page_to_phys = NULL; - debugf3("init pvt\n"); + edac_dbg(3, "init pvt\n"); pvt = (struct i82975x_pvt *) mci->pvt_info; pvt->mch_window = mch_window; i82975x_init_csrows(mci, pdev, mch_window); @@ -578,12 +577,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) /* finalize this instance of memory controller with edac core */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail2; } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail2: @@ -601,7 +600,7 @@ static int __devinit i82975x_init_one(struct pci_dev *pdev, { int rc; - debugf0("\n"); + edac_dbg(0, "\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -619,7 +618,7 @@ static void __devexit i82975x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82975x_pvt *pvt; - debugf0("\n"); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (mci == NULL) @@ -655,7 +654,7 @@ static int __init i82975x_init(void) { int pci_rc; - debugf3("\n"); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -669,7 +668,7 @@ static int __init i82975x_init(void) PCI_DEVICE_ID_INTEL_82975_0, NULL); if (!mci_pdev) { - debugf0("i82975x pci_get_device fail\n"); + edac_dbg(0, "i82975x pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -677,7 +676,7 @@ static int __init i82975x_init(void) pci_rc = i82975x_init_one(mci_pdev, i82975x_pci_tbl); if (pci_rc < 0) { - debugf0("i82975x init fail\n"); + edac_dbg(0, "i82975x init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -697,7 +696,7 @@ fail0: static void __exit i82975x_exit(void) { - debugf3("\n"); + edac_dbg(3, "\n"); pci_unregister_driver(&i82975x_driver); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index e01c678cb6a7..64b476543248 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -280,7 +280,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("failed edac_pci_add_device()\n"); + edac_dbg(3, "failed edac_pci_add_device()\n"); goto err; } @@ -303,7 +303,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_pci_err_probe); - debugf3("success\n"); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); return 0; @@ -321,7 +321,7 @@ static int mpc85xx_pci_err_remove(struct platform_device *op) struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; - debugf0("\n"); + edac_dbg(0, "\n"); out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, orig_pci_err_cap_dr); @@ -582,7 +582,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("failed edac_device_add_device()\n"); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -610,7 +610,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) devres_remove_group(&op->dev, mpc85xx_l2_err_probe); - debugf3("success\n"); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " L2 err registered\n"); return 0; @@ -628,7 +628,7 @@ static int mpc85xx_l2_err_remove(struct platform_device *op) struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; - debugf0("\n"); + edac_dbg(0, "\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0); @@ -1037,7 +1037,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) goto err; } - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 | MEM_FLAG_DDR | MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -1063,13 +1063,13 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0); if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto err; } if (mpc85xx_create_sysfs_attributes(mci)) { edac_mc_del_mc(mci->pdev); - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto err; } @@ -1103,7 +1103,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_mc_err_probe); - debugf3("success\n"); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " MC err registered\n"); return 0; @@ -1121,7 +1121,7 @@ static int mpc85xx_mc_err_remove(struct platform_device *op) struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; - debugf0("\n"); + edac_dbg(0, "\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0); diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 25851ef56b5b..f54b3cb0a134 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -169,7 +169,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) MV64X60_PCIx_ERR_MASK_VAL); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("failed edac_pci_add_device()\n"); + edac_dbg(3, "failed edac_pci_add_device()\n"); goto err; } @@ -194,7 +194,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_pci_err_probe); /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; @@ -210,7 +210,7 @@ static int mv64x60_pci_err_remove(struct platform_device *pdev) { struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); - debugf0("\n"); + edac_dbg(0, "\n"); edac_pci_del_device(&pdev->dev); @@ -336,7 +336,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("failed edac_device_add_device()\n"); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -363,7 +363,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_sram_err_probe); /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; @@ -379,7 +379,7 @@ static int mv64x60_sram_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("\n"); + edac_dbg(0, "\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -531,7 +531,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("failed edac_device_add_device()\n"); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -558,7 +558,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe); /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; @@ -574,7 +574,7 @@ static int mv64x60_cpu_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("\n"); + edac_dbg(0, "\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -766,7 +766,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) goto err2; } - debugf3("init mci\n"); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; @@ -790,7 +790,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto err; } @@ -815,7 +815,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) } /* get this far and it's successful */ - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; @@ -831,7 +831,7 @@ static int mv64x60_mc_err_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); - debugf0("\n"); + edac_dbg(0, "\n"); edac_mc_del_mc(&pdev->dev); edac_mc_free(mci); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 872c3b928035..b68e734398ea 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -205,7 +205,7 @@ static void r82600_check(struct mem_ctl_info *mci) { struct r82600_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); r82600_get_error_info(mci, &info); r82600_process_error_info(mci, &info, 1); } @@ -236,13 +236,13 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); - debugf1("Row=%d DRBA = %#0x\n", index, drbar); + edac_dbg(1, "Row=%d DRBA = %#0x\n", index, drbar); row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ - debugf1("Row=%d, Boundary Address=%#0x, Last = %#0x\n", - index, row_high_limit, row_high_limit_last); + edac_dbg(1, "Row=%d, Boundary Address=%#0x, Last = %#0x\n", + index, row_high_limit, row_high_limit_last); /* Empty row [p.57] */ if (row_high_limit == row_high_limit_last) @@ -277,13 +277,13 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) u32 sdram_refresh_rate; struct r82600_error_info discard; - debugf0("\n"); + edac_dbg(0, "\n"); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("sdram refresh rate = %#0x\n", sdram_refresh_rate); - debugf2("DRAMC register = %#0x\n", dramcr); + edac_dbg(2, "sdram refresh rate = %#0x\n", sdram_refresh_rate); + edac_dbg(2, "DRAMC register = %#0x\n", dramcr); layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; layers[0].size = R82600_NR_CSROWS; layers[0].is_virt_csrow = true; @@ -294,7 +294,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("mci = %p\n", mci); + edac_dbg(0, "mci = %p\n", mci); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -310,8 +310,8 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (ecc_enabled(dramcr)) { if (scrub_disabled) - debugf3("mci = %p - Scrubbing disabled! EAP: " - "%#0x\n", mci, eapr); + edac_dbg(3, "mci = %p - Scrubbing disabled! EAP: %#0x\n", + mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; @@ -328,14 +328,14 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("failed edac_mc_add_mc()\n"); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ if (disable_hardware_scrub) { - debugf3("Disabling Hardware Scrub (scrub on error)\n"); + edac_dbg(3, "Disabling Hardware Scrub (scrub on error)\n"); pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); } @@ -350,7 +350,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("success\n"); + edac_dbg(3, "success\n"); return 0; fail: @@ -362,7 +362,7 @@ fail: static int __devinit r82600_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("\n"); + edac_dbg(0, "\n"); /* don't need to call pci_enable_device() */ return r82600_probe1(pdev, ent->driver_data); @@ -372,7 +372,7 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); if (r82600_pci) edac_pci_release_generic_ctl(r82600_pci); diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 96efa496db5a..05955bfda849 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -381,8 +381,8 @@ static inline int numrank(u32 mtr) int ranks = (1 << RANK_CNT_BITS(mtr)); if (ranks > 4) { - debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)", - ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n", + ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); return -EINVAL; } @@ -394,8 +394,8 @@ static inline int numrow(u32 mtr) int rows = (RANK_WIDTH_BITS(mtr) + 12); if (rows < 13 || rows > 18) { - debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)", - rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)\n", + rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr); return -EINVAL; } @@ -407,8 +407,8 @@ static inline int numcol(u32 mtr) int cols = (COL_WIDTH_BITS(mtr) + 10); if (cols > 12) { - debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)", - cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of cols: %d (max = 4) raw value = %x (%04x)\n", + cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr); return -EINVAL; } @@ -475,8 +475,8 @@ static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot && PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) { - debugf1("Associated %02x.%02x.%d with %p\n", - bus, slot, func, sbridge_dev->pdev[i]); + edac_dbg(1, "Associated %02x.%02x.%d with %p\n", + bus, slot, func, sbridge_dev->pdev[i]); return sbridge_dev->pdev[i]; } } @@ -523,45 +523,45 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_br, SAD_CONTROL, ®); pvt->sbridge_dev->node_id = NODE_ID(reg); - debugf0("mc#%d: Node ID: %d, source ID: %d\n", - pvt->sbridge_dev->mc, - pvt->sbridge_dev->node_id, - pvt->sbridge_dev->source_id); + edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", + pvt->sbridge_dev->mc, + pvt->sbridge_dev->node_id, + pvt->sbridge_dev->source_id); pci_read_config_dword(pvt->pci_ras, RASENABLES, ®); if (IS_MIRROR_ENABLED(reg)) { - debugf0("Memory mirror is enabled\n"); + edac_dbg(0, "Memory mirror is enabled\n"); pvt->is_mirrored = true; } else { - debugf0("Memory mirror is disabled\n"); + edac_dbg(0, "Memory mirror is disabled\n"); pvt->is_mirrored = false; } pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr); if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) { - debugf0("Lockstep is enabled\n"); + edac_dbg(0, "Lockstep is enabled\n"); mode = EDAC_S8ECD8ED; pvt->is_lockstep = true; } else { - debugf0("Lockstep is disabled\n"); + edac_dbg(0, "Lockstep is disabled\n"); mode = EDAC_S4ECD4ED; pvt->is_lockstep = false; } if (IS_CLOSE_PG(pvt->info.mcmtr)) { - debugf0("address map is on closed page mode\n"); + edac_dbg(0, "address map is on closed page mode\n"); pvt->is_close_pg = true; } else { - debugf0("address map is on open page mode\n"); + edac_dbg(0, "address map is on open page mode\n"); pvt->is_close_pg = false; } pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, ®); if (IS_RDIMM_ENABLED(reg)) { /* FIXME: Can also be LRDIMM */ - debugf0("Memory is registered\n"); + edac_dbg(0, "Memory is registered\n"); mtype = MEM_RDDR3; } else { - debugf0("Memory is unregistered\n"); + edac_dbg(0, "Memory is unregistered\n"); mtype = MEM_DDR3; } @@ -576,7 +576,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) i, j, 0); pci_read_config_dword(pvt->pci_tad[i], mtr_regs[j], &mtr); - debugf4("Channel #%d MTR%d = %x\n", i, j, mtr); + edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr); if (IS_DIMM_PRESENT(mtr)) { pvt->channel[i].dimms++; @@ -588,10 +588,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) size = (rows * cols * banks * ranks) >> (20 - 3); npages = MiB_TO_PAGES(size); - debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", - pvt->sbridge_dev->mc, i, j, - size, npages, - banks, ranks, rows, cols); + edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", + pvt->sbridge_dev->mc, i, j, + size, npages, + banks, ranks, rows, cols); dimm->nr_pages = npages; dimm->grain = 32; @@ -629,8 +629,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (1 + pvt->tolm) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TOLM: %u.%03u GB (0x%016Lx)\n", - mb, kb, (u64)pvt->tolm); + edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); /* Address range is already 45:25 */ pci_read_config_dword(pvt->pci_sad1, TOHM, @@ -639,8 +638,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (1 + pvt->tohm) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TOHM: %u.%03u GB (0x%016Lx)", - mb, kb, (u64)pvt->tohm); + edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)", mb, kb, (u64)pvt->tohm); /* * Step 2) Get SAD range and SAD Interleave list @@ -663,13 +661,13 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (limit + 1) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n", - n_sads, - get_dram_attr(reg), - mb, kb, - ((u64)tmp_mb) << 20L, - INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]", - reg); + edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n", + n_sads, + get_dram_attr(reg), + mb, kb, + ((u64)tmp_mb) << 20L, + INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]", + reg); prv = limit; pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads], @@ -679,8 +677,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci) if (j > 0 && sad_interl == sad_pkg(reg, j)) break; - debugf0("SAD#%d, interleave #%d: %d\n", - n_sads, j, sad_pkg(reg, j)); + edac_dbg(0, "SAD#%d, interleave #%d: %d\n", + n_sads, j, sad_pkg(reg, j)); } } @@ -697,16 +695,16 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (limit + 1) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", - n_tads, mb, kb, - ((u64)tmp_mb) << 20L, - (u32)TAD_SOCK(reg), - (u32)TAD_CH(reg), - (u32)TAD_TGT0(reg), - (u32)TAD_TGT1(reg), - (u32)TAD_TGT2(reg), - (u32)TAD_TGT3(reg), - reg); + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", + n_tads, mb, kb, + ((u64)tmp_mb) << 20L, + (u32)TAD_SOCK(reg), + (u32)TAD_CH(reg), + (u32)TAD_TGT0(reg), + (u32)TAD_TGT1(reg), + (u32)TAD_TGT2(reg), + (u32)TAD_TGT3(reg), + reg); prv = limit; } @@ -722,11 +720,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci) ®); tmp_mb = TAD_OFFSET(reg) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", - i, j, - mb, kb, - ((u64)tmp_mb) << 20L, - reg); + edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", + i, j, + mb, kb, + ((u64)tmp_mb) << 20L, + reg); } } @@ -747,12 +745,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = RIR_LIMIT(reg) >> 20; rir_way = 1 << RIR_WAY(reg); mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", - i, j, - mb, kb, - ((u64)tmp_mb) << 20L, - rir_way, - reg); + edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", + i, j, + mb, kb, + ((u64)tmp_mb) << 20L, + rir_way, + reg); for (k = 0; k < rir_way; k++) { pci_read_config_dword(pvt->pci_tad[i], @@ -761,12 +759,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = RIR_OFFSET(reg) << 6; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", - i, j, k, - mb, kb, - ((u64)tmp_mb) << 20L, - (u32)RIR_RNK_TGT(reg), - reg); + edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", + i, j, k, + mb, kb, + ((u64)tmp_mb) << 20L, + (u32)RIR_RNK_TGT(reg), + reg); } } } @@ -853,16 +851,16 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way)) break; sad_interleave[sad_way] = sad_pkg(reg, sad_way); - debugf0("SAD interleave #%d: %d\n", - sad_way, sad_interleave[sad_way]); + edac_dbg(0, "SAD interleave #%d: %d\n", + sad_way, sad_interleave[sad_way]); } - debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", - pvt->sbridge_dev->mc, - n_sads, - addr, - limit, - sad_way + 7, - interleave_mode ? "" : "XOR[18:16]"); + edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", + pvt->sbridge_dev->mc, + n_sads, + addr, + limit, + sad_way + 7, + interleave_mode ? "" : "XOR[18:16]"); if (interleave_mode) idx = ((addr >> 6) ^ (addr >> 16)) & 7; else @@ -884,8 +882,8 @@ static int get_memory_error_data(struct mem_ctl_info *mci, return -EINVAL; } *socket = sad_interleave[idx]; - debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n", - idx, sad_way, *socket); + edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", + idx, sad_way, *socket); /* * Move to the proper node structure, in order to access the @@ -972,16 +970,16 @@ static int get_memory_error_data(struct mem_ctl_info *mci, offset = TAD_OFFSET(tad_offset); - debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n", - n_tads, - addr, - limit, - (u32)TAD_SOCK(reg), - ch_way, - offset, - idx, - base_ch, - *channel_mask); + edac_dbg(0, "TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n", + n_tads, + addr, + limit, + (u32)TAD_SOCK(reg), + ch_way, + offset, + idx, + base_ch, + *channel_mask); /* Calculate channel address */ /* Remove the TAD offset */ @@ -1017,11 +1015,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci, limit = RIR_LIMIT(reg); mb = div_u64_rem(limit >> 20, 1000, &kb); - debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", - n_rir, - mb, kb, - limit, - 1 << RIR_WAY(reg)); + edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", + n_rir, + mb, kb, + limit, + 1 << RIR_WAY(reg)); if (ch_addr <= limit) break; } @@ -1042,12 +1040,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ®); *rank = RIR_RNK_TGT(reg); - debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", - n_rir, - ch_addr, - limit, - rir_way, - idx); + edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", + n_rir, + ch_addr, + limit, + rir_way, + idx); return 0; } @@ -1064,14 +1062,14 @@ static void sbridge_put_devices(struct sbridge_dev *sbridge_dev) { int i; - debugf0("\n"); + edac_dbg(0, "\n"); for (i = 0; i < sbridge_dev->n_devs; i++) { struct pci_dev *pdev = sbridge_dev->pdev[i]; if (!pdev) continue; - debugf0("Removing dev %02x:%02x.%d\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "Removing dev %02x:%02x.%d\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); pci_dev_put(pdev); } } @@ -1177,10 +1175,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev, return -ENODEV; } - debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n", - bus, dev_descr->dev, - dev_descr->func, - PCI_VENDOR_ID_INTEL, dev_descr->dev_id); + edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n", + bus, dev_descr->dev, dev_descr->func, + PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* * As stated on drivers/pci/search.c, the reference count for @@ -1297,10 +1294,10 @@ static int mci_bind_devs(struct mem_ctl_info *mci, goto error; } - debugf0("Associated PCI %02x.%02d.%d with dev = %p\n", - sbridge_dev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pdev); + edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", + sbridge_dev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev); } /* Check if everything were registered */ @@ -1445,7 +1442,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, channel_mask, rank); - debugf0("%s", msg); + edac_dbg(0, "%s\n", msg); /* FIXME: need support for channel mask */ @@ -1592,7 +1589,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) struct sbridge_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: dev = %p\n", &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: dev = %p\n", &sbridge_dev->pdev[0]->dev); sbridge_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -1600,15 +1597,15 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) pvt = mci->pvt_info; - debugf0("MC: mci = %p, dev = %p\n", - mci, &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); mce_unregister_decode_chain(&sbridge_mce_dec); /* Remove MC sysfs nodes */ edac_mc_del_mc(mci->pdev); - debugf1("%s: free mci struct\n", mci->ctl_name); + edac_dbg(1, "%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); edac_mc_free(mci); sbridge_dev->mci = NULL; @@ -1639,8 +1636,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: mci = %p, dev = %p\n", - mci, &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -1675,7 +1672,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: failed edac_mc_add_mc()\n"); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); rc = -EINVAL; goto fail0; } @@ -1723,7 +1720,8 @@ static int __devinit sbridge_probe(struct pci_dev *pdev, mc = 0; list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { - debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc); + edac_dbg(0, "Registering MC#%d (%d of %d)\n", + mc, mc + 1, num_mc); sbridge_dev->mc = mc++; rc = sbridge_register_mci(sbridge_dev); if (unlikely(rc < 0)) @@ -1753,7 +1751,7 @@ static void __devexit sbridge_remove(struct pci_dev *pdev) { struct sbridge_dev *sbridge_dev; - debugf0("\n"); + edac_dbg(0, "\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -1802,7 +1800,7 @@ static int __init sbridge_init(void) { int pci_rc; - debugf2("\n"); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1824,7 +1822,7 @@ static int __init sbridge_init(void) */ static void __exit sbridge_exit(void) { - debugf2("\n"); + edac_dbg(2, "\n"); pci_unregister_driver(&sbridge_driver); } diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 70c745422fca..0e1581afadaf 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -103,10 +103,10 @@ static int how_many_channel(struct pci_dev *pdev) pci_read_config_byte(pdev, X38_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ - debugf0("In single channel mode.\n"); + edac_dbg(0, "In single channel mode\n"); x38_channel_num = 1; } else { - debugf0("In dual channel mode.\n"); + edac_dbg(0, "In dual channel mode\n"); x38_channel_num = 2; } @@ -243,7 +243,7 @@ static void x38_check(struct mem_ctl_info *mci) { struct x38_error_info info; - debugf1("MC%d\n", mci->mc_idx); + edac_dbg(1, "MC%d\n", mci->mc_idx); x38_get_and_clear_error_info(mci, &info); x38_process_error_info(mci, &info); } @@ -331,7 +331,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) bool stacked; void __iomem *window; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); window = x38_map_mchbar(pdev); if (!window) @@ -352,7 +352,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: init mci\n"); + edac_dbg(3, "MC: init mci\n"); mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; @@ -402,12 +402,12 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: failed edac_mc_add_mc()\n"); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: success\n"); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -423,7 +423,7 @@ static int __devinit x38_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC:\n"); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -439,7 +439,7 @@ static void __devexit x38_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("\n"); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -472,7 +472,7 @@ static int __init x38_init(void) { int pci_rc; - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -486,14 +486,14 @@ static int __init x38_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X38_HB, NULL); if (!mci_pdev) { - debugf0("x38 pci_get_device fail\n"); + edac_dbg(0, "x38 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = x38_init_one(mci_pdev, x38_pci_tbl); if (pci_rc < 0) { - debugf0("x38 init fail\n"); + edac_dbg(0, "x38 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -513,7 +513,7 @@ fail0: static void __exit x38_exit(void) { - debugf3("MC:\n"); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&x38_driver); if (!x38_registered) { -- GitLab From 6e84d359b2bea5ce659b3c3e5d3003fb11bd91d5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Apr 2012 10:24:43 -0300 Subject: [PATCH 0456/5711] edac_mc: Cleanup per-dimm_info debug messages The edac_mc_alloc() routine allocates one dimm_info device for all possible memories, including the non-filled ones. The debug messages there are somewhat confusing. So, cleans them, by moving the code that prints the memory location to edac_mc, and using it on both edac_mc_sysfs and edac_mc. Also, only dumps information when DIMM/ranks are actually filled. After this patch, a dimm-based memory controller will print the debug info as: [ 1011.380027] EDAC DEBUG: edac_mc_dump_csrow: csrow->csrow_idx = 0 [ 1011.380029] EDAC DEBUG: edac_mc_dump_csrow: csrow = ffff8801169be000 [ 1011.380031] EDAC DEBUG: edac_mc_dump_csrow: csrow->first_page = 0x0 [ 1011.380032] EDAC DEBUG: edac_mc_dump_csrow: csrow->last_page = 0x0 [ 1011.380034] EDAC DEBUG: edac_mc_dump_csrow: csrow->page_mask = 0x0 [ 1011.380035] EDAC DEBUG: edac_mc_dump_csrow: csrow->nr_channels = 3 [ 1011.380037] EDAC DEBUG: edac_mc_dump_csrow: csrow->channels = ffff8801149c2840 [ 1011.380039] EDAC DEBUG: edac_mc_dump_csrow: csrow->mci = ffff880117426000 [ 1011.380041] EDAC DEBUG: edac_mc_dump_channel: channel->chan_idx = 0 [ 1011.380042] EDAC DEBUG: edac_mc_dump_channel: channel = ffff8801149c2860 [ 1011.380044] EDAC DEBUG: edac_mc_dump_channel: channel->csrow = ffff8801169be000 [ 1011.380046] EDAC DEBUG: edac_mc_dump_channel: channel->dimm = ffff88010fe90400 ... [ 1011.380095] EDAC DEBUG: edac_mc_dump_dimm: dimm0: channel 0 slot 0 mapped as virtual row 0, chan 0 [ 1011.380097] EDAC DEBUG: edac_mc_dump_dimm: dimm = ffff88010fe90400 [ 1011.380099] EDAC DEBUG: edac_mc_dump_dimm: dimm->label = 'CPU#0Channel#0_DIMM#0' [ 1011.380101] EDAC DEBUG: edac_mc_dump_dimm: dimm->nr_pages = 0x40000 [ 1011.380103] EDAC DEBUG: edac_mc_dump_dimm: dimm->grain = 8 [ 1011.380104] EDAC DEBUG: edac_mc_dump_dimm: dimm->nr_pages = 0x40000 ... (a rank-based memory controller would print, instead of "dimm?", "rank?" on the above debug info) Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc.c | 95 ++++++++++++++++++++++-------------- drivers/edac/edac_mc_sysfs.c | 11 +---- drivers/edac/edac_module.h | 3 ++ 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index a39fe6f966e3..98c759dc0d5d 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -42,44 +42,63 @@ static DEFINE_MUTEX(mem_ctls_mutex); static LIST_HEAD(mc_devices); +unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf, + unsigned len) +{ + struct mem_ctl_info *mci = dimm->mci; + int i, n, count = 0; + char *p = buf; + + for (i = 0; i < mci->n_layers; i++) { + n = snprintf(p, len, "%s %d ", + edac_layer_name[mci->layers[i].type], + dimm->location[i]); + p += n; + len -= n; + count += n; + if (!len) + break; + } + + return count; +} + #ifdef CONFIG_EDAC_DEBUG static void edac_mc_dump_channel(struct rank_info *chan) { - edac_dbg(4, "\tchannel = %p\n", chan); - edac_dbg(4, "\tchannel->chan_idx = %d\n", chan->chan_idx); - edac_dbg(4, "\tchannel->csrow = %p\n", chan->csrow); - edac_dbg(4, "\tchannel->dimm = %p\n", chan->dimm); + edac_dbg(4, " channel->chan_idx = %d\n", chan->chan_idx); + edac_dbg(4, " channel = %p\n", chan); + edac_dbg(4, " channel->csrow = %p\n", chan->csrow); + edac_dbg(4, " channel->dimm = %p\n", chan->dimm); } -static void edac_mc_dump_dimm(struct dimm_info *dimm) +static void edac_mc_dump_dimm(struct dimm_info *dimm, int number) { - int i; - - edac_dbg(4, "\tdimm = %p\n", dimm); - edac_dbg(4, "\tdimm->label = '%s'\n", dimm->label); - edac_dbg(4, "\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); - edac_dbg(4, "\tdimm location "); - for (i = 0; i < dimm->mci->n_layers; i++) { - printk(KERN_CONT "%d", dimm->location[i]); - if (i < dimm->mci->n_layers - 1) - printk(KERN_CONT "."); - } - printk(KERN_CONT "\n"); - edac_dbg(4, "\tdimm->grain = %d\n", dimm->grain); - edac_dbg(4, "\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); + char location[80]; + + edac_dimm_info_location(dimm, location, sizeof(location)); + + edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", + dimm->mci->mem_is_per_rank ? "rank" : "dimm", + number, location, dimm->csrow, dimm->cschannel); + edac_dbg(4, " dimm = %p\n", dimm); + edac_dbg(4, " dimm->label = '%s'\n", dimm->label); + edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages); + edac_dbg(4, " dimm->grain = %d\n", dimm->grain); + edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages); } static void edac_mc_dump_csrow(struct csrow_info *csrow) { - edac_dbg(4, "\tcsrow = %p\n", csrow); - edac_dbg(4, "\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); - edac_dbg(4, "\tcsrow->first_page = 0x%lx\n", csrow->first_page); - edac_dbg(4, "\tcsrow->last_page = 0x%lx\n", csrow->last_page); - edac_dbg(4, "\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); - edac_dbg(4, "\tcsrow->nr_channels = %d\n", csrow->nr_channels); - edac_dbg(4, "\tcsrow->channels = %p\n", csrow->channels); - edac_dbg(4, "\tcsrow->mci = %p\n", csrow->mci); + edac_dbg(4, "csrow->csrow_idx = %d\n", csrow->csrow_idx); + edac_dbg(4, " csrow = %p\n", csrow); + edac_dbg(4, " csrow->first_page = 0x%lx\n", csrow->first_page); + edac_dbg(4, " csrow->last_page = 0x%lx\n", csrow->last_page); + edac_dbg(4, " csrow->page_mask = 0x%lx\n", csrow->page_mask); + edac_dbg(4, " csrow->nr_channels = %d\n", csrow->nr_channels); + edac_dbg(4, " csrow->channels = %p\n", csrow->channels); + edac_dbg(4, " csrow->mci = %p\n", csrow->mci); } static void edac_mc_dump_mci(struct mem_ctl_info *mci) @@ -327,8 +346,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, memset(&pos, 0, sizeof(pos)); row = 0; chn = 0; - edac_dbg(4, "initializing %d %s\n", - tot_dimms, per_rank ? "ranks" : "dimms"); for (i = 0; i < tot_dimms; i++) { chan = mci->csrows[row]->channels[chn]; off = EDAC_DIMM_OFF(layer, n_layers, pos[0], pos[1], pos[2]); @@ -341,10 +358,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->dimms[off] = dimm; dimm->mci = mci; - edac_dbg(2, "%d: %s%i (%d:%d:%d): row %d, chan %d\n", - i, per_rank ? "rank" : "dimm", off, - pos[0], pos[1], pos[2], row, chn); - /* * Copy DIMM location and initialize it. */ @@ -700,14 +713,22 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) int i; for (i = 0; i < mci->nr_csrows; i++) { + struct csrow_info *csrow = mci->csrows[i]; + u32 nr_pages = 0; int j; - edac_mc_dump_csrow(mci->csrows[i]); - for (j = 0; j < mci->csrows[i]->nr_channels; j++) - edac_mc_dump_channel(mci->csrows[i]->channels[j]); + for (j = 0; j < csrow->nr_channels; j++) + nr_pages += csrow->channels[j]->dimm->nr_pages; + if (!nr_pages) + continue; + edac_mc_dump_csrow(csrow); + for (j = 0; j < csrow->nr_channels; j++) + if (csrow->channels[j]->dimm->nr_pages) + edac_mc_dump_channel(csrow->channels[j]); } for (i = 0; i < mci->tot_dimms; i++) - edac_mc_dump_dimm(mci->dimms[i]); + if (mci->dimms[i]->nr_pages) + edac_mc_dump_dimm(mci->dimms[i], i); } #endif mutex_lock(&mem_ctls_mutex); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index eace646b57f0..7079a428c8ea 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -485,17 +485,8 @@ static ssize_t dimmdev_location_show(struct device *dev, struct device_attribute *mattr, char *data) { struct dimm_info *dimm = to_dimm(dev); - struct mem_ctl_info *mci = dimm->mci; - int i; - char *p = data; - - for (i = 0; i < mci->n_layers; i++) { - p += sprintf(p, "%s %d ", - edac_layer_name[mci->layers[i].type], - dimm->location[i]); - } - return p - data; + return edac_dimm_info_location(dimm, data, PAGE_SIZE); } static ssize_t dimmdev_label_show(struct device *dev, diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 1af13676e857..62de640c8c8a 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -34,6 +34,9 @@ extern int edac_mc_get_panic_on_ue(void); extern int edac_get_poll_msec(void); extern int edac_mc_get_poll_msec(void); +unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf, + unsigned len); + /* on edac_device.c */ extern int edac_device_register_sysfs_main_kobj( struct edac_device_ctl_info *edac_dev); -- GitLab From 5156a5f4e058b906c1e8c0fe2ab16f30b60dee96 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 10 May 2012 12:43:01 -0300 Subject: [PATCH 0457/5711] edac: Increase version to 3.0.0 There were lots of changes introduced to justify renaming it to 3.0.0: - EDAC core were redesigned to represent all types of memory controllers; - EDAC API were redesigned to properly represent the memory controller hierarchy; - a tracepoint-based API were added to report memory errors. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index cbba80d3423a..3454798c270e 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -15,7 +15,7 @@ #include "edac_core.h" #include "edac_module.h" -#define EDAC_VERSION "Ver: 2.1.0" +#define EDAC_VERSION "Ver: 3.0.0" #ifdef CONFIG_EDAC_DEBUG /* Values of 0 to 4 will generate output */ -- GitLab From 08a4a136909602eae0e71e147153461df077a46f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 May 2012 15:51:02 +0300 Subject: [PATCH 0458/5711] edac_mc: check for allocation failure in edac_mc_alloc() Add a check here for if kzalloc() failed. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 98c759dc0d5d..91ca4101c789 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -355,6 +355,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, } dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL); + if (!dimm) + goto error; mci->dimms[off] = dimm; dimm->mci = mci; -- GitLab From 075f30901e32feefd3641e6c5537611fd7e27b59 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 May 2012 09:06:17 -0300 Subject: [PATCH 0459/5711] amd64_edac: Don't pass driver name as an error parameter The EDAC driver name doesn't help to handle EDAC errors. So, remove it from the EDAC error messages, preserving only the error_message. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index b47529554734..811d3e8e5025 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1049,8 +1049,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a node", + "", NULL); return; } @@ -1061,8 +1061,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a csrow", + "", NULL); return; } @@ -1082,8 +1082,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, csrow, -1, -1, - EDAC_MOD_STR, "unknown syndrome - possible error reporting race", + "", NULL); return; } @@ -1102,7 +1102,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, page, offset, syndrome, csrow, channel, -1, - EDAC_MOD_STR, "", NULL); + "", "", NULL); } static int ddr2_cs_size(unsigned i, bool dct_width) @@ -1614,8 +1614,8 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a csrow", + "", NULL); return; } @@ -1631,7 +1631,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, csrow, chan, -1, - EDAC_MOD_STR, "", NULL); + "", "", NULL); } /* @@ -1916,8 +1916,8 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, -1, -1, -1, - EDAC_MOD_STR, "HW has no ERROR_ADDRESS available", + "", NULL); return; } @@ -1945,8 +1945,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - EDAC_MOD_STR, "HW has no ERROR_ADDRESS available", + "", NULL); return; } @@ -1965,8 +1965,9 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offset, 0, -1, -1, -1, - EDAC_MOD_STR, - "ERROR ADDRESS NOT mapped to a MC", NULL); + "ERROR ADDRESS NOT mapped to a MC", + "", + NULL); return; } @@ -1979,14 +1980,14 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offset, 0, -1, -1, -1, - EDAC_MOD_STR, "ERROR ADDRESS NOT mapped to CS", + "", NULL); } else { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offset, 0, csrow, -1, -1, - EDAC_MOD_STR, "", NULL); + "", "", NULL); } } -- GitLab From 03f7eae80f4b913929be84e0c883ee98196fd6ff Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 4 Jun 2012 11:29:25 -0300 Subject: [PATCH 0460/5711] edac: remove arch-specific parameter for the error handler Remove the arch-dependent parameter, as it were not used, as the MCE tracepoint weren't implemented. It probably doesn't make sense to have an MCE-specific tracepoint, as this will cost more bytes at the tracepoint, and tracepoint is not free. The changes at the EDAC drivers were done by this small perl script: $file .=$_ while (<>); $file =~ s/(edac_mc_handle_error)\s*\(([^\;]+)\,([^\,\)]+)\s*\)/$1($2)/g; print $file; Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 30 +++++++++++------------------- drivers/edac/amd76x_edac.c | 4 ++-- drivers/edac/cell_edac.c | 4 ++-- drivers/edac/cpc925_edac.c | 4 ++-- drivers/edac/e752x_edac.c | 8 ++++---- drivers/edac/e7xxx_edac.c | 8 ++++---- drivers/edac/edac_core.h | 3 +-- drivers/edac/edac_mc.c | 6 +----- drivers/edac/edac_mc_sysfs.c | 2 +- drivers/edac/i3000_edac.c | 6 +++--- drivers/edac/i3200_edac.c | 6 +++--- drivers/edac/i5000_edac.c | 8 ++++---- drivers/edac/i5100_edac.c | 4 ++-- drivers/edac/i5400_edac.c | 4 ++-- drivers/edac/i7300_edac.c | 4 ++-- drivers/edac/i7core_edac.c | 4 ++-- drivers/edac/i82443bxgx_edac.c | 4 ++-- drivers/edac/i82860_edac.c | 6 +++--- drivers/edac/i82875p_edac.c | 6 +++--- drivers/edac/i82975x_edac.c | 6 +++--- drivers/edac/mpc85xx_edac.c | 4 ++-- drivers/edac/mv64x60_edac.c | 4 ++-- drivers/edac/pasemi_edac.c | 4 ++-- drivers/edac/ppc4xx_edac.c | 4 ++-- drivers/edac/r82600_edac.c | 4 ++-- drivers/edac/sb_edac.c | 4 ++-- drivers/edac/tile_edac.c | 2 +- drivers/edac/x38_edac.c | 6 +++--- 28 files changed, 73 insertions(+), 86 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 811d3e8e5025..6231cbe6e7c1 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1050,8 +1050,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a node", - "", - NULL); + ""); return; } @@ -1062,8 +1061,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a csrow", - "", - NULL); + ""); return; } @@ -1083,8 +1081,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, page, offset, syndrome, csrow, -1, -1, "unknown syndrome - possible error reporting race", - "", - NULL); + ""); return; } } else { @@ -1102,7 +1099,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, page, offset, syndrome, csrow, channel, -1, - "", "", NULL); + "", ""); } static int ddr2_cs_size(unsigned i, bool dct_width) @@ -1615,8 +1612,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a csrow", - "", - NULL); + ""); return; } @@ -1631,7 +1627,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset, syndrome, csrow, chan, -1, - "", "", NULL); + "", ""); } /* @@ -1917,8 +1913,7 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m) 0, 0, 0, -1, -1, -1, "HW has no ERROR_ADDRESS available", - "", - NULL); + ""); return; } @@ -1946,8 +1941,7 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) 0, 0, 0, -1, -1, -1, "HW has no ERROR_ADDRESS available", - "", - NULL); + ""); return; } @@ -1966,8 +1960,7 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) page, offset, 0, -1, -1, -1, "ERROR ADDRESS NOT mapped to a MC", - "", - NULL); + ""); return; } @@ -1981,13 +1974,12 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) page, offset, 0, -1, -1, -1, "ERROR ADDRESS NOT mapped to CS", - "", - NULL); + ""); } else { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offset, 0, csrow, -1, -1, - "", "", NULL); + "", ""); } } diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index a015fbaa9552..c7c208eae233 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -148,7 +148,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, mci->csrows[row]->first_page, 0, 0, row, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } @@ -163,7 +163,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, mci->csrows[row]->first_page, 0, 0, row, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 478d8ee434df..165d255e627d 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -50,7 +50,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) /* TODO: Decoding of the error address */ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, csrow->first_page + pfn, offset, syndrome, - 0, chan, -1, "", "", NULL); + 0, chan, -1, "", ""); } static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) @@ -72,7 +72,7 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) /* TODO: Decoding of the error address */ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, csrow->first_page + pfn, offset, 0, - 0, chan, -1, "", "", NULL); + 0, chan, -1, "", ""); } static void cell_edac_check(struct mem_ctl_info *mci) diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index a7ea3986d423..32e9c88dbde9 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -557,7 +557,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, pfn, offset, syndrome, csrow, channel, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } if (apiexcp & UECC_EXCP_DETECTED) { @@ -565,7 +565,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, pfn, offset, 0, csrow, -1, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n"); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 675ba3c284eb..b5a8bf1292ac 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -374,7 +374,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offset_in_page(sec1_add << 4), sec1_syndrome, row, channel, -1, - "e752x CE", "", NULL); + "e752x CE", ""); } static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, @@ -412,7 +412,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, - "e752x UE from Read", "", NULL); + "e752x UE from Read", ""); } if (error_one & 0x0404) { @@ -431,7 +431,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, - "e752x UE from Scruber", "", NULL); + "e752x UE from Scruber", ""); } } @@ -456,7 +456,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "e752x UE log memory write", "", NULL); + "e752x UE log memory write", ""); } static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 3ce661e883f7..c26b69e70039 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -220,14 +220,14 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) /* convert syndrome to channel */ channel = e7xxx_find_channel(syndrome); edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, 0, syndrome, - row, channel, -1, "e7xxx CE", "", NULL); + row, channel, -1, "e7xxx CE", ""); } static void process_ce_no_info(struct mem_ctl_info *mci) { edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "e7xxx CE log register overflow", "", NULL); + "e7xxx CE log register overflow", ""); } static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) @@ -243,7 +243,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) row = edac_mc_find_csrow_by_page(mci, block_page); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, block_page, 0, 0, - row, -1, -1, "e7xxx UE", "", NULL); + row, -1, -1, "e7xxx UE", ""); } static void process_ue_no_info(struct mem_ctl_info *mci) @@ -251,7 +251,7 @@ static void process_ue_no_info(struct mem_ctl_info *mci) edac_dbg(3, "\n"); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "e7xxx UE log register overflow", "", NULL); + "e7xxx UE log register overflow", ""); } static void e7xxx_get_error_info(struct mem_ctl_info *mci, diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index ee25f5483f9b..500ba6698986 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -462,8 +462,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, const int mid_layer, const int low_layer, const char *msg, - const char *other_detail, - const void *arch_log); + const char *other_detail); /* * edac_device APIs diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 91ca4101c789..fb41e38c6891 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1044,9 +1044,6 @@ static void edac_ue_error(struct mem_ctl_info *mci, * @other_detail: Technical details about the event that * may help hardware manufacturers and * EDAC developers to analyse the event - * @arch_log: Architecture-specific struct that can - * be used to add extended information to the - * tracepoint, like dumping MCE registers. */ void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, @@ -1057,8 +1054,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, const int mid_layer, const int low_layer, const char *msg, - const char *other_detail, - const void *arch_log) + const char *other_detail) { /* FIXME: too much for stack: move it to some pre-alocated area */ char detail[80], location[80]; diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 7079a428c8ea..107e7a71678e 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -827,7 +827,7 @@ static ssize_t edac_fake_inject_write(struct file *file, mci->fake_inject_layer[0], mci->fake_inject_layer[1], mci->fake_inject_layer[2], - "FAKE ERROR", "for EDAC testing only", NULL); + "FAKE ERROR", "for EDAC testing only"); return count; } diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 399aec351aa1..dd07bea34078 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -247,7 +247,7 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -261,12 +261,12 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, pfn, offset, 0, row, -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); else edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, pfn, offset, info->derrsyn, row, multi_chan ? channel : 0, -1, - "i3000 CE", "", NULL); + "i3000 CE", ""); return 1; } diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index dfd843a0481b..07ae4426b5df 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -219,7 +219,7 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & I3200_ERRSTS_BITS) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -230,13 +230,13 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); } else if (log & I3200_ECCERRLOG_CE) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); } } } diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 96431a547e46..0406f0d4dd2f 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -522,7 +522,7 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, channel >> 1, channel & 1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* @@ -621,7 +621,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, channel >> 1, -1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* Check correctable errors */ @@ -675,7 +675,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, channel >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } if (!misc_messages) @@ -720,7 +720,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Call the helper to output message */ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, branch >> 1, -1, -1, - "Misc error", msg, NULL); + "Misc error", msg); } } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index a9b996c8ef2d..1e5c8f668652 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -434,7 +434,7 @@ static void i5100_handle_ce(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, syndrome, chan, rank, -1, - msg, detail, NULL); + msg, detail); } static void i5100_handle_ue(struct mem_ctl_info *mci, @@ -456,7 +456,7 @@ static void i5100_handle_ue(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, syndrome, chan, rank, -1, - msg, detail, NULL); + msg, detail); } static void i5100_read_log(struct mem_ctl_info *mci, int chan, diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 90fad3a9c3f7..f2bfc2660158 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -557,7 +557,7 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, edac_mc_handle_error(tp_event, mci, 0, 0, 0, branch >> 1, -1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* @@ -629,7 +629,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, branch >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); return; } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 738b8919194f..4a8835fd12bd 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -452,7 +452,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, branch, -1, rank, is_wr ? "Write error" : "Read error", - pvt->tmp_prt_buffer, NULL); + pvt->tmp_prt_buffer); } @@ -499,7 +499,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) syndrome, branch >> 1, channel % 2, rank, is_wr ? "Write error" : "Read error", - pvt->tmp_prt_buffer, NULL); + pvt->tmp_prt_buffer); } return; } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 0899d7da7248..aba8d5190330 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1545,7 +1545,7 @@ static void i7core_rdimm_update_errcount(struct mem_ctl_info *mci, for (i = 0; i < add; i++) { edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, - chan, dimm, -1, "error", "", NULL); + chan, dimm, -1, "error", ""); } } @@ -1801,7 +1801,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, m->addr & ~PAGE_MASK, syndrome, channel, dimm, -1, - err, msg, m); + err, msg); } /* diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 475bde1c4508..1c414a87195e 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -159,7 +159,7 @@ static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), - 0, -1, mci->ctl_name, "", NULL); + 0, -1, mci->ctl_name, ""); } if (info->eap & I82443BXGX_EAP_OFFSET_MBE) { @@ -168,7 +168,7 @@ static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), - 0, -1, mci->ctl_name, "", NULL); + 0, -1, mci->ctl_name, ""); } return error_found; diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 832e7dd2c5fa..ff4f590e9b90 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -110,7 +110,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & 0x0003) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -122,12 +122,12 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, info->eap, 0, 0, dimm->location[0], dimm->location[1], -1, - "i82860 UE", "", NULL); + "i82860 UE", ""); else edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, info->eap, 0, info->derrsyn, dimm->location[0], dimm->location[1], -1, - "i82860 CE", "", NULL); + "i82860 CE", ""); return 1; } diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index db64bd74bc54..2e3f306c9c72 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -238,7 +238,7 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & 0x0081) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -249,12 +249,12 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, info->eap, 0, 0, row, -1, -1, - "i82875p UE", "", NULL); + "i82875p UE", ""); else edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, info->eap, 0, info->derrsyn, row, multi_chan ? (info->des & 0x1) : 0, - -1, "i82875p CE", "", NULL); + -1, "i82875p CE", ""); return 1; } diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 974d1a2be379..c95ebe5e4d60 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -289,7 +289,7 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & 0x0003) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -317,12 +317,12 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offst, 0, row, -1, -1, - "i82975x UE", "", NULL); + "i82975x UE", ""); else edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, offst, info->derrsyn, row, chan ? chan : 0, -1, - "i82975x CE", "", NULL); + "i82975x CE", ""); return 1; } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 64b476543248..56e79a053fe6 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -869,13 +869,13 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); if (err_detect & DDR_EDE_MBE) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect); } diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index f54b3cb0a134..e491a297f5ec 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -615,13 +615,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, syndrome, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); else /* 2 bit error, UE */ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, 0, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); /* clear the error */ out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 44f73b00df01..04851be51612 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -112,14 +112,14 @@ static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) MCDEBUG_ERRSTA_RFL_STATUS)) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, mci->csrows[cs]->first_page, 0, 0, - cs, 0, -1, mci->ctl_name, "", NULL); + cs, 0, -1, mci->ctl_name, ""); } /* correctable/single-bit errors */ if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, mci->csrows[cs]->first_page, 0, 0, - cs, 0, -1, mci->ctl_name, "", NULL); + cs, 0, -1, mci->ctl_name, ""); } static void pasemi_edac_check(struct mem_ctl_info *mci) diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index 53519828cc36..67a29201dae7 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -730,7 +730,7 @@ ppc4xx_edac_handle_ce(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, row, 0, -1, - message, "", NULL); + message, ""); } /** @@ -761,7 +761,7 @@ ppc4xx_edac_handle_ue(struct mem_ctl_info *mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, page, offset, 0, row, 0, -1, - message, "", NULL); + message, ""); } /** diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index b68e734398ea..aa10178397fe 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -183,7 +183,7 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, page, 0, syndrome, edac_mc_find_csrow_by_page(mci, page), 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } if (info->eapr & BIT(1)) { /* UE? */ @@ -195,7 +195,7 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, page, 0, 0, edac_mc_find_csrow_by_page(mci, page), 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } return error_found; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 05955bfda849..ae18d9849cc7 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1450,12 +1450,12 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, edac_mc_handle_error(tp_event, mci, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, channel, dimm, -1, - optype, msg, m); + optype, msg); return; err_parsing: edac_mc_handle_error(tp_event, mci, 0, 0, 0, -1, -1, -1, - msg, "", m); + msg, ""); } diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index fc77f77fa065..0589f56aa568 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -74,7 +74,7 @@ static void tile_edac_check(struct mem_ctl_info *mci) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 0e1581afadaf..3d46d40987af 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -217,7 +217,7 @@ static void x38_process_error_info(struct mem_ctl_info *mci, if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -228,13 +228,13 @@ static void x38_process_error_info(struct mem_ctl_info *mci, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, - "x38 UE", "", NULL); + "x38 UE", ""); } else if (log & X38_ECCERRLOG_CE) { edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, - "x38 CE", "", NULL); + "x38 CE", ""); } } } -- GitLab From 109cdbc223f6e2d6c80f8371f22415b50c18a366 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 18 May 2012 16:52:19 -0600 Subject: [PATCH 0461/5711] PCI: remove pci_bus_find_ext_capability() (unused) pci_bus_find_ext_capability() is unused, and this patch removes it. Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 43 ------------------------------------------- include/linux/pci.h | 2 -- 2 files changed, 45 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..de9386da2eb2 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -329,49 +329,6 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) } EXPORT_SYMBOL_GPL(pci_find_ext_capability); -/** - * pci_bus_find_ext_capability - find an extended capability - * @bus: the PCI bus to query - * @devfn: PCI device to query - * @cap: capability code - * - * Like pci_find_ext_capability() but works for pci devices that do not have a - * pci_dev structure set up yet. - * - * Returns the address of the requested capability structure within the - * device's PCI configuration space or 0 in case the device does not - * support it. - */ -int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn, - int cap) -{ - u32 header; - int ttl; - int pos = PCI_CFG_SPACE_SIZE; - - /* minimum 8 bytes per capability */ - ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; - - if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) - return 0; - if (header == 0xffffffff || header == 0) - return 0; - - while (ttl-- > 0) { - if (PCI_EXT_CAP_ID(header) == cap) - return pos; - - pos = PCI_EXT_CAP_NEXT(header); - if (pos < PCI_CFG_SPACE_SIZE) - break; - - if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) - break; - } - - return 0; -} - static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) { int rc, ttl = PCI_FIND_CAP_TTL; diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..2618ad996535 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -714,8 +714,6 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev); int pci_find_capability(struct pci_dev *dev, int cap); int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability(struct pci_dev *dev, int cap); -int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn, - int cap); int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); struct pci_bus *pci_find_next_bus(const struct pci_bus *from); -- GitLab From 533b6608b73669309becd90f11f939b60bb221be Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 18 May 2012 16:52:34 -0600 Subject: [PATCH 0462/5711] PCI: remove pci_max_busnr() (was already commented out) pci_max_busnr() has been commented out for years (since 54c762fe62), and this patch removes it completely. Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index de9386da2eb2..2cc53acad26a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -136,30 +136,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) EXPORT_SYMBOL_GPL(pci_ioremap_bar); #endif -#if 0 -/** - * pci_max_busnr - returns maximum PCI bus number - * - * Returns the highest PCI bus number present in the system global list of - * PCI buses. - */ -unsigned char __devinit -pci_max_busnr(void) -{ - struct pci_bus *bus = NULL; - unsigned char max, n; - - max = 0; - while ((bus = pci_find_next_bus(bus)) != NULL) { - n = pci_bus_max_busnr(bus); - if(n > max) - max = n; - } - return max; -} - -#endif /* 0 */ - #define PCI_FIND_CAP_TTL 48 static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn, -- GitLab From 505cf30b7f4ef64c6db36f34adbe4a7ad9081fd3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 18 May 2012 16:52:40 -0600 Subject: [PATCH 0463/5711] PCI/AER: use pci_is_pcie() instead of obsolete pci_dev.is_pcie Use pci_is_pcie() instead of looking at obsolete is_pcie field in struct pci_dev. CC: Huang Ying CC: Kenji Kaneshige Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aerdrv_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 275bf158ffa7..124f20ff11b2 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -59,7 +59,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) p = (struct acpi_hest_aer_common *)(hest_hdr + 1); if (p->flags & ACPI_HEST_GLOBAL) { - if ((info->pci_dev->is_pcie && + if ((pci_is_pcie(info->pci_dev) && info->pci_dev->pcie_type == pcie_type) || bridge) ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); } else -- GitLab From 442f24ace6c5991df2a9ab49fe0273b79b145d19 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Mon, 11 Jun 2012 17:47:41 -0400 Subject: [PATCH 0464/5711] ACPI: remove acpi_pad MAINTAINERS entry As Shaohua is no longer in this neck of the woods, and thus treat the acpi_pad driver as just another part of drivers/acpi/ Signed-off-by: Len Brown --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 14bc7071f9df..508a935afe04 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -242,13 +242,6 @@ W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/fan.c -ACPI PROCESSOR AGGREGATOR DRIVER -M: Shaohua Li -L: linux-acpi@vger.kernel.org -W: http://www.lesswatts.org/projects/acpi/ -S: Supported -F: drivers/acpi/acpi_pad.c - ACPI THERMAL DRIVER M: Zhang Rui L: linux-acpi@vger.kernel.org -- GitLab From bdd4034df8b37841eeaf7b05f86e732ab8e0b08a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 23 Apr 2012 09:16:36 +0200 Subject: [PATCH 0465/5711] driver core: always handle dpm_order If !dev->class, device_move() does not respect the dpm_order. Fix it to do so. Acked-by: Rafael J. Wysocki Signed-off-by: Rabin Vincent Reviewed-by: Srinidhi Kasagar [Fixed a small dangling label compile warning] Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 346be8b78b24..846d12b5d579 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1754,25 +1754,25 @@ int device_move(struct device *dev, struct device *new_parent, set_dev_node(dev, dev_to_node(new_parent)); } - if (!dev->class) - goto out_put; - error = device_move_class_links(dev, old_parent, new_parent); - if (error) { - /* We ignore errors on cleanup since we're hosed anyway... */ - device_move_class_links(dev, new_parent, old_parent); - if (!kobject_move(&dev->kobj, &old_parent->kobj)) { - if (new_parent) - klist_remove(&dev->p->knode_parent); - dev->parent = old_parent; - if (old_parent) { - klist_add_tail(&dev->p->knode_parent, - &old_parent->p->klist_children); - set_dev_node(dev, dev_to_node(old_parent)); + if (dev->class) { + error = device_move_class_links(dev, old_parent, new_parent); + if (error) { + /* We ignore errors on cleanup since we're hosed anyway... */ + device_move_class_links(dev, new_parent, old_parent); + if (!kobject_move(&dev->kobj, &old_parent->kobj)) { + if (new_parent) + klist_remove(&dev->p->knode_parent); + dev->parent = old_parent; + if (old_parent) { + klist_add_tail(&dev->p->knode_parent, + &old_parent->p->klist_children); + set_dev_node(dev, dev_to_node(old_parent)); + } } + cleanup_glue_dir(dev, new_parent_kobj); + put_device(new_parent); + goto out; } - cleanup_glue_dir(dev, new_parent_kobj); - put_device(new_parent); - goto out; } switch (dpm_order) { case DPM_ORDER_NONE: @@ -1787,7 +1787,7 @@ int device_move(struct device *dev, struct device *new_parent, device_pm_move_last(dev); break; } -out_put: + put_device(old_parent); out: device_pm_unlock(); -- GitLab From a6e51c1e3425fe61040e9e770f514cfdf576a1f0 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Fri, 8 Jun 2012 12:22:46 +0200 Subject: [PATCH 0466/5711] staging: Delete if_strip.h Commit f80a3f62383bf673c310926d55142d51f118926d ("Staging: strip: delete the driver") left if_strip.h unused: nothing in the tree includes it anymore. It is still exported, but since nothing in the kernel uses struct MetricomAddress, that seems pointless. Delete this header too. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman --- include/linux/Kbuild | 1 - include/linux/if_strip.h | 27 --------------------------- 2 files changed, 28 deletions(-) delete mode 100644 include/linux/if_strip.h diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 8760be30b375..9366142ec7e5 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -183,7 +183,6 @@ header-y += if_ppp.h header-y += if_pppol2tp.h header-y += if_pppox.h header-y += if_slip.h -header-y += if_strip.h header-y += if_team.h header-y += if_tun.h header-y += if_tunnel.h diff --git a/include/linux/if_strip.h b/include/linux/if_strip.h deleted file mode 100644 index 6526a6235832..000000000000 --- a/include/linux/if_strip.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * if_strip.h -- - * - * Definitions for the STRIP interface - * - * Copyright 1996 The Board of Trustees of The Leland Stanford - * Junior University. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies. Stanford University - * makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without - * express or implied warranty. - */ - -#ifndef __LINUX_STRIP_H -#define __LINUX_STRIP_H - -#include - -typedef struct { - __u8 c[6]; -} MetricomAddress; - -#endif -- GitLab From 4bfa9b2ee16e73087435ac64a35f32140a385438 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 6 Jun 2012 13:43:55 +0100 Subject: [PATCH 0467/5711] staging: comedi: das08: Reduce conditional compilation This code is used by some combination of the CONFIG_COMEDI_DAS08_CS, CONFIG_COMEDI_DAS08_ISA, and CONFIG_COMEDI_DAS08_PCI and contains a lot of conditional compilation. Remove most of the conditional compilation, relying on the compiler to optimize out unused static functions and data. Use the '__maybe_unused' tag for those functions that cause compiler warnings as a result of this. Also change the DO_COMEDI_DRIVER_REGISTER macro from a conditionally defined macro to a manifest constant macro to allow it to be tested outside the preprocessor (although this is not currently needed). Signed-off-by: Ian Abbott Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 74 +++++++++++--------------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index fa2784d65569..f99f72b9cdf3 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -60,9 +60,9 @@ #define DRV_NAME "das08" -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) || IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) -#define DO_COMEDI_DRIVER_REGISTER -#endif +#define DO_COMEDI_DRIVER_REGISTER \ + (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) || \ + IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) #define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307 #define PCI_DEVICE_ID_PCIDAS08 0x29 @@ -341,22 +341,19 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, return 2; } -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -static int das08jr_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[0] = 0; data[1] = inb(dev->iobase + DAS08JR_DIO); return 2; } -#endif -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -static int das08jr_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; @@ -370,12 +367,10 @@ static int das08jr_do_wbits(struct comedi_device *dev, return 2; } -#endif -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -static int das08jr_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; int lsb, msb; @@ -401,7 +396,6 @@ static int das08jr_ao_winsn(struct comedi_device *dev, return n; } -#endif /* * @@ -409,10 +403,9 @@ static int das08jr_ao_winsn(struct comedi_device *dev, * a different method to force an update. * */ -#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -static int das08ao_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; int lsb, msb; @@ -438,7 +431,6 @@ static int das08ao_ao_winsn(struct comedi_device *dev, return n; } -#endif static unsigned int i8254_read_channel_low(unsigned int base, int chan) { @@ -570,7 +562,7 @@ static int das08_counter_config(struct comedi_device *dev, return 2; } -#ifdef DO_COMEDI_DRIVER_REGISTER +#if DO_COMEDI_DRIVER_REGISTER static const struct das08_board_struct das08_boards[] = { #if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) { @@ -943,7 +935,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) } EXPORT_SYMBOL_GPL(das08_common_attach); -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static int das08_pci_attach_common(struct comedi_device *dev, struct pci_dev *pdev) { @@ -951,6 +942,9 @@ static int das08_pci_attach_common(struct comedi_device *dev, unsigned long pci_iobase; struct das08_private_struct *devpriv = dev->private; + if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) + return -EINVAL; + devpriv->pdev = pdev; /* enable PCI device and reserve I/O spaces */ if (comedi_pci_enable(pdev, dev->driver->driver_name)) { @@ -977,28 +971,28 @@ static int das08_pci_attach_common(struct comedi_device *dev, #endif return das08_common_attach(dev, iobase); } -#endif -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static const struct das08_board_struct * das08_find_pci_board(struct pci_dev *pdev) { +#if DO_COMEDI_DRIVER_REGISTER unsigned int i; for (i = 0; i < ARRAY_SIZE(das08_boards); i++) if (das08_boards[i].bustype == pci && pdev->device == das08_boards[i].id) return &das08_boards[i]; +#endif return NULL; } -#endif -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) /* only called in the PCI probe path, via comedi_pci_auto_config() */ -static int __devinit das08_attach_pci(struct comedi_device *dev, - struct pci_dev *pdev) +static int __devinit __maybe_unused +das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev) { int ret; + if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) + return -EINVAL; ret = alloc_private(dev, sizeof(struct das08_private_struct)); if (ret < 0) return ret; @@ -1010,9 +1004,7 @@ static int __devinit das08_attach_pci(struct comedi_device *dev, } return das08_pci_attach_common(dev, pdev); } -#endif -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static struct pci_dev *das08_find_pci(struct comedi_device *dev, int bus, int slot) { @@ -1063,10 +1055,9 @@ static struct pci_dev *das08_find_pci(struct comedi_device *dev, thisboard->name); return NULL; } -#endif -#ifdef DO_COMEDI_DRIVER_REGISTER -static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static int __maybe_unused +das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das08_board_struct *thisboard = comedi_board(dev); struct das08_private_struct *devpriv; @@ -1097,7 +1088,6 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) } else return -EIO; } -#endif /* DO_COMEDI_DRIVER_REGISTER */ void das08_common_detach(struct comedi_device *dev) { @@ -1106,8 +1096,7 @@ void das08_common_detach(struct comedi_device *dev) } EXPORT_SYMBOL_GPL(das08_common_detach); -#ifdef DO_COMEDI_DRIVER_REGISTER -static void das08_detach(struct comedi_device *dev) +static void __maybe_unused das08_detach(struct comedi_device *dev) { const struct das08_board_struct *thisboard = comedi_board(dev); struct das08_private_struct *devpriv = dev->private; @@ -1126,16 +1115,13 @@ static void das08_detach(struct comedi_device *dev) } } } -#endif /* DO_COMEDI_DRIVER_REGISTER */ -#ifdef DO_COMEDI_DRIVER_REGISTER +#if DO_COMEDI_DRIVER_REGISTER static struct comedi_driver das08_driver = { .driver_name = DRV_NAME, .module = THIS_MODULE, .attach = das08_attach, -#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) .attach_pci = das08_attach_pci, -#endif .detach = das08_detach, .board_name = &das08_boards[0].name, .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct), @@ -1170,7 +1156,7 @@ static struct pci_driver das08_pci_driver = { }; #endif /* CONFIG_COMEDI_DAS08_PCI */ -#ifdef DO_COMEDI_DRIVER_REGISTER +#if DO_COMEDI_DRIVER_REGISTER #if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) module_comedi_pci_driver(das08_driver, das08_pci_driver); #else -- GitLab From 4e2f002f7a9b316640eb06ef6df767f017e3e7b1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 6 Jun 2012 15:17:02 +0100 Subject: [PATCH 0468/5711] staging: comedi: describe comedi_recognize() Add a comment to comedi_recognize() to describe what it does as it's a bit confusing. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 9d2b206251ac..49e53eaa8e41 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -300,8 +300,32 @@ static int postconfig(struct comedi_device *dev) return 0; } -/* generic recognize function for drivers - * that register their supported board names */ +/* + * Generic recognize function for drivers that register their supported + * board names. + * + * 'driv->board_name' points to a 'const char *' member within the + * zeroth element of an array of some private board information + * structure, say 'struct foo_board' containing a member 'const char + * *board_name' that is initialized to point to a board name string that + * is one of the candidates matched against this function's 'name' + * parameter. + * + * 'driv->offset' is the size of the private board information + * structure, say 'sizeof(struct foo_board)', and 'driv->num_names' is + * the length of the array of private board information structures. + * + * If one of the board names in the array of private board information + * structures matches the name supplied to this function, the function + * returns a pointer to the pointer to the board name, otherwise it + * returns NULL. The return value ends up in the 'board_ptr' member of + * a 'struct comedi_device' that the low-level comedi driver's + * 'attach()' hook can convert to a point to a particular element of its + * array of private board information structures by subtracting the + * offset of the member that points to the board name. (No subtraction + * is required if the board name pointer is the first member of the + * private board information structure, which is generally the case.) + */ static void *comedi_recognize(struct comedi_driver *driv, const char *name) { char **name_ptr = (char **)driv->board_name; -- GitLab From 72fd9facfb697d5f7b61958bb10efaabbd8461eb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 5 Jun 2012 10:18:02 -0700 Subject: [PATCH 0469/5711] staging: comedi: cleanup sysfs functions Make the comedi sysfs functions a bit more concise by shortening some of the verbose variable names and reusing some of the variables that were used for intermediate calculations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 210 ++++++++++----------------- 1 file changed, 76 insertions(+), 134 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 76776571ed91..b3b86d48c771 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -172,28 +172,19 @@ static int resize_async_buffer(struct comedi_device *dev, /* sysfs attribute files */ -static const unsigned bytes_per_kibi = 1024; - static ssize_t show_max_read_buffer_kb(struct device *dev, struct device_attribute *attr, char *buf) { - ssize_t retval; struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned max_buffer_size_kb = 0; - struct comedi_subdevice *const read_subdevice = - comedi_get_read_subdevice(info); + struct comedi_subdevice *s = comedi_get_read_subdevice(info); + unsigned int size = 0; mutex_lock(&info->device->mutex); - if (read_subdevice && - (read_subdevice->subdev_flags & SDF_CMD_READ) && - read_subdevice->async) { - max_buffer_size_kb = read_subdevice->async->max_bufsize / - bytes_per_kibi; - } - retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb); + if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) + size = s->async->max_bufsize / 1024; mutex_unlock(&info->device->mutex); - return retval; + return snprintf(buf, PAGE_SIZE, "%i\n", size); } static ssize_t store_max_read_buffer_kb(struct device *dev, @@ -201,52 +192,40 @@ static ssize_t store_max_read_buffer_kb(struct device *dev, const char *buf, size_t count) { struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned int new_max_size_kb; - unsigned int new_max_size; - int ret; - struct comedi_subdevice *const read_subdevice = - comedi_get_read_subdevice(info); - - ret = kstrtouint(buf, 10, &new_max_size_kb); - if (ret) - return ret; - if (new_max_size_kb > (UINT_MAX / bytes_per_kibi)) + struct comedi_subdevice *s = comedi_get_read_subdevice(info); + unsigned int size; + int err; + + err = kstrtouint(buf, 10, &size); + if (err) + return err; + if (size > (UINT_MAX / 1024)) return -EINVAL; - new_max_size = new_max_size_kb * bytes_per_kibi; + size *= 1024; mutex_lock(&info->device->mutex); - if (read_subdevice == NULL || - (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 || - read_subdevice->async == NULL) { - mutex_unlock(&info->device->mutex); - return -EINVAL; - } - read_subdevice->async->max_bufsize = new_max_size; + if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) + s->async->max_bufsize = size; + else + err = -EINVAL; mutex_unlock(&info->device->mutex); - return count; + return err ? err : count; } static ssize_t show_read_buffer_kb(struct device *dev, struct device_attribute *attr, char *buf) { - ssize_t retval; struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned buffer_size_kb = 0; - struct comedi_subdevice *const read_subdevice = - comedi_get_read_subdevice(info); + struct comedi_subdevice *s = comedi_get_read_subdevice(info); + unsigned int size = 0; mutex_lock(&info->device->mutex); - if (read_subdevice && - (read_subdevice->subdev_flags & SDF_CMD_READ) && - read_subdevice->async) { - buffer_size_kb = read_subdevice->async->prealloc_bufsz / - bytes_per_kibi; - } - retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb); + if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) + size = s->async->prealloc_bufsz / 1024; mutex_unlock(&info->device->mutex); - return retval; + return snprintf(buf, PAGE_SIZE, "%i\n", size); } static ssize_t store_read_buffer_kb(struct device *dev, @@ -254,57 +233,41 @@ static ssize_t store_read_buffer_kb(struct device *dev, const char *buf, size_t count) { struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned int new_size_kb; - unsigned int new_size; - int retval; - int ret; - struct comedi_subdevice *const read_subdevice = - comedi_get_read_subdevice(info); - - ret = kstrtouint(buf, 10, &new_size_kb); - if (ret) - return ret; - if (new_size_kb > (UINT_MAX / bytes_per_kibi)) + struct comedi_subdevice *s = comedi_get_read_subdevice(info); + unsigned int size; + int err; + + err = kstrtouint(buf, 10, &size); + if (err) + return err; + if (size > (UINT_MAX / 1024)) return -EINVAL; - new_size = new_size_kb * bytes_per_kibi; + size *= 1024; mutex_lock(&info->device->mutex); - if (read_subdevice == NULL || - (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 || - read_subdevice->async == NULL) { - mutex_unlock(&info->device->mutex); - return -EINVAL; - } - retval = resize_async_buffer(info->device, read_subdevice, - read_subdevice->async, new_size); + if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) + err = resize_async_buffer(info->device, s, s->async, size); + else + err = -EINVAL; mutex_unlock(&info->device->mutex); - if (retval < 0) - return retval; - return count; + return err ? err : count; } static ssize_t show_max_write_buffer_kb(struct device *dev, struct device_attribute *attr, char *buf) { - ssize_t retval; struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned max_buffer_size_kb = 0; - struct comedi_subdevice *const write_subdevice = - comedi_get_write_subdevice(info); + struct comedi_subdevice *s = comedi_get_write_subdevice(info); + unsigned int size = 0; mutex_lock(&info->device->mutex); - if (write_subdevice && - (write_subdevice->subdev_flags & SDF_CMD_WRITE) && - write_subdevice->async) { - max_buffer_size_kb = write_subdevice->async->max_bufsize / - bytes_per_kibi; - } - retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb); + if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) + size = s->async->max_bufsize / 1024; mutex_unlock(&info->device->mutex); - return retval; + return snprintf(buf, PAGE_SIZE, "%i\n", size); } static ssize_t store_max_write_buffer_kb(struct device *dev, @@ -312,52 +275,40 @@ static ssize_t store_max_write_buffer_kb(struct device *dev, const char *buf, size_t count) { struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned int new_max_size_kb; - unsigned int new_max_size; - int ret; - struct comedi_subdevice *const write_subdevice = - comedi_get_write_subdevice(info); - - ret = kstrtouint(buf, 10, &new_max_size_kb); - if (ret) - return ret; - if (new_max_size_kb > (UINT_MAX / bytes_per_kibi)) + struct comedi_subdevice *s = comedi_get_write_subdevice(info); + unsigned int size; + int err; + + err = kstrtouint(buf, 10, &size); + if (err) + return err; + if (size > (UINT_MAX / 1024)) return -EINVAL; - new_max_size = new_max_size_kb * bytes_per_kibi; + size *= 1024; mutex_lock(&info->device->mutex); - if (write_subdevice == NULL || - (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 || - write_subdevice->async == NULL) { - mutex_unlock(&info->device->mutex); - return -EINVAL; - } - write_subdevice->async->max_bufsize = new_max_size; + if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) + s->async->max_bufsize = size; + else + err = -EINVAL; mutex_unlock(&info->device->mutex); - return count; + return err ? err : count; } static ssize_t show_write_buffer_kb(struct device *dev, struct device_attribute *attr, char *buf) { - ssize_t retval; struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned buffer_size_kb = 0; - struct comedi_subdevice *const write_subdevice = - comedi_get_write_subdevice(info); + struct comedi_subdevice *s = comedi_get_write_subdevice(info); + unsigned int size = 0; mutex_lock(&info->device->mutex); - if (write_subdevice && - (write_subdevice->subdev_flags & SDF_CMD_WRITE) && - write_subdevice->async) { - buffer_size_kb = write_subdevice->async->prealloc_bufsz / - bytes_per_kibi; - } - retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb); + if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) + size = s->async->prealloc_bufsz / 1024; mutex_unlock(&info->device->mutex); - return retval; + return snprintf(buf, PAGE_SIZE, "%i\n", size); } static ssize_t store_write_buffer_kb(struct device *dev, @@ -365,34 +316,25 @@ static ssize_t store_write_buffer_kb(struct device *dev, const char *buf, size_t count) { struct comedi_device_file_info *info = dev_get_drvdata(dev); - unsigned int new_size_kb; - unsigned int new_size; - int retval; - int ret; - struct comedi_subdevice *const write_subdevice = - comedi_get_write_subdevice(info); - - ret = kstrtouint(buf, 10, &new_size_kb); - if (ret) - return ret; - if (new_size_kb > (UINT_MAX / bytes_per_kibi)) + struct comedi_subdevice *s = comedi_get_write_subdevice(info); + unsigned int size; + int err; + + err = kstrtouint(buf, 10, &size); + if (err) + return err; + if (size > (UINT_MAX / 1024)) return -EINVAL; - new_size = ((uint64_t) new_size_kb) * bytes_per_kibi; + size *= 1024; mutex_lock(&info->device->mutex); - if (write_subdevice == NULL || - (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 || - write_subdevice->async == NULL) { - mutex_unlock(&info->device->mutex); - return -EINVAL; - } - retval = resize_async_buffer(info->device, write_subdevice, - write_subdevice->async, new_size); + if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) + err = resize_async_buffer(info->device, s, s->async, size); + else + err = -EINVAL; mutex_unlock(&info->device->mutex); - if (retval < 0) - return retval; - return count; + return err ? err : count; } static struct device_attribute comedi_dev_attrs[] = { -- GitLab From 513e48f90a9d092ffcf8301b6ed10a8d8a5ebe77 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 5 Jun 2012 11:12:18 -0700 Subject: [PATCH 0470/5711] staging: comedi: ni_labpc: unlock spinlock on command error When starting the acquisition the labpc_ai_cmd function was exiting without unlocking the spinlock. This results in a sparse warning: warning: context imbalance in 'labpc_ai_cmd' - different lock contexts for basic block Add the missing spin_unlock_irqrestore calls. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 53349777246b..1d739b26e678 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1386,6 +1386,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; default: comedi_error(dev, "bug with start_src"); + spin_unlock_irqrestore(&dev->spinlock, flags); return -1; break; } @@ -1398,6 +1399,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; default: comedi_error(dev, "bug with stop_src"); + spin_unlock_irqrestore(&dev->spinlock, flags); return -1; } devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); -- GitLab From 91211dd13bec5e87490770f5b530b39b50f5d2f8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 6 Jun 2012 23:41:36 +0200 Subject: [PATCH 0471/5711] drivers/staging/comedi/drivers/me4000.c: adjust suspicious bit operation TRIG_ROUND_NEAREST is 0, so a bit-and with it is always false. The value TRIG_ROUND_MASK covers the bits of the TRIG_ROUND constants, so first pick those bits and then make the test using ==. The same is done for TRIG_ROUND_UP for symmetry, even though bit-and would be sufficient in this case. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index cb6bf8c5fb45..09890b8c586c 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -948,10 +948,10 @@ static int ai_round_cmd_args(struct comedi_device *dev, *init_ticks = (cmd->start_arg * 33) / 1000; rest = (cmd->start_arg * 33) % 1000; - if (cmd->flags & TRIG_ROUND_NEAREST) { + if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) { if (rest > 33) (*init_ticks)++; - } else if (cmd->flags & TRIG_ROUND_UP) { + } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) { if (rest) (*init_ticks)++; } @@ -961,10 +961,10 @@ static int ai_round_cmd_args(struct comedi_device *dev, *scan_ticks = (cmd->scan_begin_arg * 33) / 1000; rest = (cmd->scan_begin_arg * 33) % 1000; - if (cmd->flags & TRIG_ROUND_NEAREST) { + if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) { if (rest > 33) (*scan_ticks)++; - } else if (cmd->flags & TRIG_ROUND_UP) { + } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) { if (rest) (*scan_ticks)++; } @@ -974,10 +974,10 @@ static int ai_round_cmd_args(struct comedi_device *dev, *chan_ticks = (cmd->convert_arg * 33) / 1000; rest = (cmd->convert_arg * 33) % 1000; - if (cmd->flags & TRIG_ROUND_NEAREST) { + if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) { if (rest > 33) (*chan_ticks)++; - } else if (cmd->flags & TRIG_ROUND_UP) { + } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) { if (rest) (*chan_ticks)++; } -- GitLab From 47db6d58099437ddcec4fd2e572c95eba8c37cdd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jun 2012 17:05:27 -0700 Subject: [PATCH 0472/5711] staging: comedi: refactor comedi_fops to remove most of the forward declarations Move the comedi_unlocked_ioctl function in order to remove most of the forward declarations in this file. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 214 ++++++++++++--------------- 1 file changed, 92 insertions(+), 122 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b3b86d48c771..ad8634734194 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -92,36 +92,6 @@ static DEFINE_SPINLOCK(comedi_file_info_table_lock); static struct comedi_device_file_info *comedi_file_info_table[COMEDI_NUM_MINORS]; -static int do_devconfig_ioctl(struct comedi_device *dev, - struct comedi_devconfig __user *arg); -static int do_bufconfig_ioctl(struct comedi_device *dev, - struct comedi_bufconfig __user *arg); -static int do_devinfo_ioctl(struct comedi_device *dev, - struct comedi_devinfo __user *arg, - struct file *file); -static int do_subdinfo_ioctl(struct comedi_device *dev, - struct comedi_subdinfo __user *arg, void *file); -static int do_chaninfo_ioctl(struct comedi_device *dev, - struct comedi_chaninfo __user *arg); -static int do_bufinfo_ioctl(struct comedi_device *dev, - struct comedi_bufinfo __user *arg, void *file); -static int do_cmd_ioctl(struct comedi_device *dev, - struct comedi_cmd __user *arg, void *file); -static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, - void *file); -static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, - void *file); -static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, - void *file); -static int do_cmdtest_ioctl(struct comedi_device *dev, - struct comedi_cmd __user *arg, void *file); -static int do_insnlist_ioctl(struct comedi_device *dev, - struct comedi_insnlist __user *arg, void *file); -static int do_insn_ioctl(struct comedi_device *dev, - struct comedi_insn __user *arg, void *file); -static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, - void *file); - static void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s); static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s); @@ -349,98 +319,6 @@ static struct device_attribute comedi_dev_attrs[] = { __ATTR_NULL }; -static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev; - int rc; - - if (dev_file_info == NULL || dev_file_info->device == NULL) - return -ENODEV; - dev = dev_file_info->device; - - mutex_lock(&dev->mutex); - - /* Device config is special, because it must work on - * an unconfigured device. */ - if (cmd == COMEDI_DEVCONFIG) { - rc = do_devconfig_ioctl(dev, - (struct comedi_devconfig __user *)arg); - goto done; - } - - if (!dev->attached) { - DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor); - rc = -ENODEV; - goto done; - } - - switch (cmd) { - case COMEDI_BUFCONFIG: - rc = do_bufconfig_ioctl(dev, - (struct comedi_bufconfig __user *)arg); - break; - case COMEDI_DEVINFO: - rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg, - file); - break; - case COMEDI_SUBDINFO: - rc = do_subdinfo_ioctl(dev, - (struct comedi_subdinfo __user *)arg, - file); - break; - case COMEDI_CHANINFO: - rc = do_chaninfo_ioctl(dev, (void __user *)arg); - break; - case COMEDI_RANGEINFO: - rc = do_rangeinfo_ioctl(dev, (void __user *)arg); - break; - case COMEDI_BUFINFO: - rc = do_bufinfo_ioctl(dev, - (struct comedi_bufinfo __user *)arg, - file); - break; - case COMEDI_LOCK: - rc = do_lock_ioctl(dev, arg, file); - break; - case COMEDI_UNLOCK: - rc = do_unlock_ioctl(dev, arg, file); - break; - case COMEDI_CANCEL: - rc = do_cancel_ioctl(dev, arg, file); - break; - case COMEDI_CMD: - rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file); - break; - case COMEDI_CMDTEST: - rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg, - file); - break; - case COMEDI_INSNLIST: - rc = do_insnlist_ioctl(dev, - (struct comedi_insnlist __user *)arg, - file); - break; - case COMEDI_INSN: - rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg, - file); - break; - case COMEDI_POLL: - rc = do_poll_ioctl(dev, arg, file); - break; - default: - rc = -ENOTTY; - break; - } - -done: - mutex_unlock(&dev->mutex); - return rc; -} - /* COMEDI_DEVCONFIG device config ioctl @@ -1651,6 +1529,98 @@ static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, return -EINVAL; } +static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + const unsigned minor = iminor(file->f_dentry->d_inode); + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev; + int rc; + + if (dev_file_info == NULL || dev_file_info->device == NULL) + return -ENODEV; + dev = dev_file_info->device; + + mutex_lock(&dev->mutex); + + /* Device config is special, because it must work on + * an unconfigured device. */ + if (cmd == COMEDI_DEVCONFIG) { + rc = do_devconfig_ioctl(dev, + (struct comedi_devconfig __user *)arg); + goto done; + } + + if (!dev->attached) { + DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor); + rc = -ENODEV; + goto done; + } + + switch (cmd) { + case COMEDI_BUFCONFIG: + rc = do_bufconfig_ioctl(dev, + (struct comedi_bufconfig __user *)arg); + break; + case COMEDI_DEVINFO: + rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg, + file); + break; + case COMEDI_SUBDINFO: + rc = do_subdinfo_ioctl(dev, + (struct comedi_subdinfo __user *)arg, + file); + break; + case COMEDI_CHANINFO: + rc = do_chaninfo_ioctl(dev, (void __user *)arg); + break; + case COMEDI_RANGEINFO: + rc = do_rangeinfo_ioctl(dev, (void __user *)arg); + break; + case COMEDI_BUFINFO: + rc = do_bufinfo_ioctl(dev, + (struct comedi_bufinfo __user *)arg, + file); + break; + case COMEDI_LOCK: + rc = do_lock_ioctl(dev, arg, file); + break; + case COMEDI_UNLOCK: + rc = do_unlock_ioctl(dev, arg, file); + break; + case COMEDI_CANCEL: + rc = do_cancel_ioctl(dev, arg, file); + break; + case COMEDI_CMD: + rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file); + break; + case COMEDI_CMDTEST: + rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg, + file); + break; + case COMEDI_INSNLIST: + rc = do_insnlist_ioctl(dev, + (struct comedi_insnlist __user *)arg, + file); + break; + case COMEDI_INSN: + rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg, + file); + break; + case COMEDI_POLL: + rc = do_poll_ioctl(dev, arg, file); + break; + default: + rc = -ENOTTY; + break; + } + +done: + mutex_unlock(&dev->mutex); + return rc; +} + static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { int ret = 0; -- GitLab From 0bdf8ec0a57e5c4f90f4d6e83938f24653360d84 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jun 2012 17:31:19 -0700 Subject: [PATCH 0473/5711] staging: comedi: adl_pci9118: if test should use logical AND not bitwise AND This quiets a couple sparse warnings about: warning: dubious: !x & y Also, remove the unnecessary parentheses around the variables. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 3670ebdbcd81..5a5c903f5e03 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1735,7 +1735,7 @@ static int check_channel_list(struct comedi_device *dev, "can't be mixtured!"); return 0; } - if ((!devpriv->usemux) & (differencial) & + if (!devpriv->usemux && differencial && (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) { comedi_error(dev, "If AREF_DIFF is used then is " -- GitLab From e26d925f42064a800c1226e15dbaa23da1721fb7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jun 2012 17:25:35 -0700 Subject: [PATCH 0474/5711] staging: comedi: pcl816: if test should use logical OR not bitwise OR This quiets a couple sparse warnings about: warning: dubious: !x | !y warning: dubious: x | !y Also, remove the unnecessary parentheses abound the variables. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 277a23ece6fa..845039cd6207 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -414,8 +414,8 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) } outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ - if ((!dev->irq) | (!devpriv->irq_free) | (!devpriv->irq_blocked) | - (!devpriv->int816_mode)) { + if (!dev->irq || !devpriv->irq_free || !devpriv->irq_blocked || + !devpriv->int816_mode) { if (devpriv->irq_was_now_closed) { devpriv->irq_was_now_closed = 0; /* comedi_error(dev,"last IRQ.."); */ -- GitLab From 27494c092a81847fef515549b76251d96b760619 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jun 2012 17:14:25 -0700 Subject: [PATCH 0475/5711] staging: comedi: serial2002: quiet NULL pointer sparse noise Quiet a number of sparse warnings in this file: warning: Using plain integer as NULL pointer Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 9200310dce5d..c25808c05251 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -643,7 +643,7 @@ err_alloc_configs: if (result) { if (devpriv->tty) { - filp_close(devpriv->tty, 0); + filp_close(devpriv->tty, NULL); devpriv->tty = NULL; } } @@ -653,8 +653,8 @@ err_alloc_configs: static void serial_2002_close(struct comedi_device *dev) { - if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) - filp_close(devpriv->tty, 0); + if (!IS_ERR(devpriv->tty) && devpriv->tty) + filp_close(devpriv->tty, NULL); } static int serial2002_di_rinsn(struct comedi_device *dev, @@ -819,7 +819,7 @@ static int serial2002_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 0; s->maxdata = 1; - s->range_table = 0; + s->range_table = NULL; s->insn_read = &serial2002_ai_rinsn; /* analog output subdevice */ @@ -828,7 +828,7 @@ static int serial2002_attach(struct comedi_device *dev, s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; s->maxdata = 1; - s->range_table = 0; + s->range_table = NULL; s->insn_write = &serial2002_ao_winsn; s->insn_read = &serial2002_ao_rinsn; @@ -838,7 +838,7 @@ static int serial2002_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_LSAMPL; s->n_chan = 0; s->maxdata = 1; - s->range_table = 0; + s->range_table = NULL; s->insn_read = &serial2002_ei_rinsn; return 1; -- GitLab From f59f231e3db835353d8d1ff91062d89140dc8be3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jun 2012 09:52:58 +0300 Subject: [PATCH 0476/5711] staging: comedi: amplc_pci230: add a missing unlock This side of the if else statement returned with the lock held and IRQs disabled. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 30487be11650..f2ad35c6527d 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -1387,6 +1387,8 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, /* Delay. Should driver be responsible for this? */ /* XXX TODO: See if DAC busy bit can be used. */ udelay(8); + } else { + spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); } return 1; -- GitLab From 83afda9d449c61b55881d50465833784d8fda786 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Jun 2012 10:40:05 +0100 Subject: [PATCH 0477/5711] staging: comedi: amplc_pci230: Replace NULLFUNC The source code defines a macro NULLFUNC #define NULLFUNC 0 and uses it as a generic null function pointer constant. This is superfluous. Just use NULL instead. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index f2ad35c6527d..2a43df5d966e 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -430,9 +430,6 @@ enum { /* Combine old and new bits. */ #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask))) -/* A generic null function pointer value. */ -#define NULLFUNC 0 - /* Current CPU. XXX should this be hard_smp_processor_id()? */ #define THISCPU smp_processor_id() @@ -1491,7 +1488,7 @@ static int pci230_ao_inttrig_start(struct comedi_device *dev, if (trig_num != 0) return -EINVAL; - s->async->inttrig = NULLFUNC; + s->async->inttrig = NULL; pci230_ao_start(dev, s); return 1; @@ -2292,7 +2289,7 @@ static int pci230_ai_inttrig_start(struct comedi_device *dev, if (trig_num != 0) return -EINVAL; - s->async->inttrig = NULLFUNC; + s->async->inttrig = NULL; pci230_ai_start(dev, s); return 1; -- GitLab From cbdfaffc461fd3df12f494655aca5cae68d6c7aa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Jun 2012 10:39:42 +0100 Subject: [PATCH 0478/5711] staging: comedi: amplc_pci224: Replace NULLFUNC The source code defines a macro NULLFUNC #define NULLFUNC 0 and uses it as a generic null function pointer constant. This is superfluous. Just use NULL instead. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 43f07f8f365e..a1e23bafabea 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -265,9 +265,6 @@ Caveats: /* Combine old and new bits. */ #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask))) -/* A generic null function pointer value. */ -#define NULLFUNC 0 - /* Current CPU. XXX should this be hard_smp_processor_id()? */ #define THISCPU smp_processor_id() @@ -703,7 +700,7 @@ pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s, if (trignum != 0) return -EINVAL; - s->async->inttrig = NULLFUNC; + s->async->inttrig = NULL; pci224_ao_start(dev, s); return 1; -- GitLab From f059077388b0c35cd47ee06ba5da3401a62dc657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Wed, 6 Jun 2012 16:22:04 +0200 Subject: [PATCH 0479/5711] Staging: xgifb: Remove #ifdef MODULE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check for MODULE is not needed. In a static compilation the parameters definition is valid and module_exit() does nothing. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 85dbf32b1f66..61dc7cb94ffb 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2325,8 +2325,6 @@ module_init(xgifb_init); /* MODULE */ /*****************************************************/ -#ifdef MODULE - MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("XGITECH , Others"); @@ -2359,5 +2357,3 @@ static void __exit xgifb_remove_module(void) } module_exit(xgifb_remove_module); - -#endif /* /MODULE */ -- GitLab From d049053ef052535c8986f104f904548dfcaa14aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Wed, 6 Jun 2012 16:22:05 +0200 Subject: [PATCH 0480/5711] Staging: xgifb: reorder the code a bit to be more module friendly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 51 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 61dc7cb94ffb..96abb23f6b42 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2306,49 +2306,44 @@ static struct pci_driver xgifb_driver = { .remove = __devexit_p(xgifb_remove) }; -static int __init xgifb_init(void) -{ - char *option = NULL; - - if (forcecrt2type != NULL) - XGIfb_search_crt2type(forcecrt2type); - if (fb_get_options("xgifb", &option)) - return -ENODEV; - XGIfb_setup(option); - - return pci_register_driver(&xgifb_driver); -} -module_init(xgifb_init); /*****************************************************/ /* MODULE */ /*****************************************************/ -MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("XGITECH , Others"); - module_param(mode, charp, 0); -module_param(vesa, int, 0); -module_param(filter, int, 0); -module_param(forcecrt2type, charp, 0); +MODULE_PARM_DESC(mode, + "\nSelects the desired default display mode in the format XxYxDepth,\n" + "eg. 1024x768x16.\n"); +module_param(forcecrt2type, charp, 0); MODULE_PARM_DESC(forcecrt2type, "\nForce the second display output type. Possible values are NONE,\n" "LCD, TV, VGA, SVIDEO or COMPOSITE.\n"); -MODULE_PARM_DESC(mode, - "\nSelects the desired default display mode in the format XxYxDepth,\n" - "eg. 1024x768x16.\n"); - +module_param(vesa, int, 0); MODULE_PARM_DESC(vesa, "\nSelects the desired default display mode by VESA mode number, eg.\n" "0x117.\n"); +module_param(filter, int, 0); MODULE_PARM_DESC(filter, - "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" - "(Possible values 0-7, default: [no filter])\n"); + "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" + "(Possible values 0-7, default: [no filter])\n"); + +static int __init xgifb_init(void) +{ + char *option = NULL; + + if (forcecrt2type != NULL) + XGIfb_search_crt2type(forcecrt2type); + if (fb_get_options("xgifb", &option)) + return -ENODEV; + XGIfb_setup(option); + + return pci_register_driver(&xgifb_driver); +} static void __exit xgifb_remove_module(void) { @@ -2356,4 +2351,8 @@ static void __exit xgifb_remove_module(void) pr_debug("Module unloaded\n"); } +MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("XGITECH , Others"); +module_init(xgifb_init); module_exit(xgifb_remove_module); -- GitLab From 05e06036ddffd3e285bddc23e4ce55f54cd27537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Wed, 6 Jun 2012 16:22:06 +0200 Subject: [PATCH 0481/5711] Staging: xgifb: disable pci device if there's an error after enabling it. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 96abb23f6b42..438781ff33a3 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1904,7 +1904,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (reg1 != 0xa1) { /*I/O error */ pr_err("I/O error!!!"); ret = -EIO; - goto error; + goto error_disable; } switch (xgifb_info->chip_id) { @@ -1927,7 +1927,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, break; default: ret = -ENODEV; - goto error; + goto error_disable; } pr_info("chipid = %x\n", xgifb_info->chip); @@ -1936,7 +1936,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (XGIfb_get_dram_size(xgifb_info)) { pr_err("Fatal error: Unable to determine RAM size.\n"); ret = -ENODEV; - goto error; + goto error_disable; } /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ @@ -1956,7 +1956,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, pr_err("Fatal error: Unable to reserve frame buffer memory\n"); pr_err("Is there another framebuffer driver active?\n"); ret = -ENODEV; - goto error; + goto error_disable; } if (!request_mem_region(xgifb_info->mmio_base, @@ -2271,6 +2271,8 @@ error_1: release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size); error_0: release_mem_region(xgifb_info->video_base, xgifb_info->video_size); +error_disable: + pci_disable_device(pdev); error: framebuffer_release(fb_info); return ret; -- GitLab From bf55b48371d1ca6ee64152753b359924e3cfcbcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Wed, 6 Jun 2012 16:22:07 +0200 Subject: [PATCH 0482/5711] Staging: xgifb: disable pci device on pci remove function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 438781ff33a3..033463d1966c 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2297,6 +2297,7 @@ static void __devexit xgifb_remove(struct pci_dev *pdev) iounmap(xgifb_info->video_vbase); release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size); release_mem_region(xgifb_info->video_base, xgifb_info->video_size); + pci_disable_device(pdev); framebuffer_release(fb_info); pci_set_drvdata(pdev, NULL); } -- GitLab From 1132b9aafa61bb589a2c09980d13c154659bdb07 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Mon, 11 Jun 2012 16:57:30 -0400 Subject: [PATCH 0483/5711] staging: usbip: Updated comment describing VHCI_NPORTS Updated out-of-date comment describing VHCI_NPORT Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 88b32981cf1f..c66b8b3f97b4 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -71,12 +71,7 @@ struct vhci_unlink { unsigned long unlink_seqnum; }; -/* - * The number of ports is less than 16 ? - * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value - * would be 31 because the event_bits[1] of struct usb_hub is defined as - * unsigned long in hub.h - */ +/* Number of supported ports. Value has an upperbound of USB_MAXCHILDREN */ #define VHCI_NPORTS 8 /* for usb_bus.hcpriv */ -- GitLab From 12ea6cad1c7d046e21decc18b0e2170c6794dc51 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 11 Jun 2012 05:26:55 +0000 Subject: [PATCH 0484/5711] PCI: add PCI DMA source ID quirk DMA transactions are tagged with the source ID of the device making the request. Occasionally hardware screws this up and uses the source ID of a different device (often the wrong function number of a multifunction device). A specific Ricoh multifunction device is a prime example of this problem and included in this patch. Given a pci_dev, this function returns the pci_dev to use as the source ID for DMA. When hardware works correctly, this returns the input device. For the components of the Ricoh multifunction device, it returns the pci_dev for function 0. This will be used by IOMMU drivers for determining the boundaries of IOMMU groups as multiple devices using the same source ID must be contained within the same group. This can also be used by existing streaming DMA paths for the same purpose. [bhelgaas: fold in pci_dev_get() for !CONFIG_PCI] Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 8 +++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a7521677541..acd3956b44bd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3179,3 +3179,54 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe) return -ENOTTY; } + +static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev) +{ + if (!PCI_FUNC(dev->devfn)) + return pci_dev_get(dev); + + return pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); +} + +static const struct pci_dev_dma_source { + u16 vendor; + u16 device; + struct pci_dev *(*dma_source)(struct pci_dev *dev); +} pci_dev_dma_source[] = { + /* + * https://bugzilla.redhat.com/show_bug.cgi?id=605888 + * + * Some Ricoh devices use the function 0 source ID for DMA on + * other functions of a multifunction device. The DMA devices + * is therefore function 0, which will have implications of the + * iommu grouping of these devices. + */ + { PCI_VENDOR_ID_RICOH, 0xe822, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe230, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe476, pci_func_0_dma_source }, + { 0 } +}; + +/* + * IOMMUs with isolation capabilities need to be programmed with the + * correct source ID of a device. In most cases, the source ID matches + * the device doing the DMA, but sometimes hardware is broken and will + * tag the DMA as being sourced from a different device. This function + * allows that translation. Note that the reference count of the + * returned device is incremented on all paths. + */ +struct pci_dev *pci_get_dma_source(struct pci_dev *dev) +{ + const struct pci_dev_dma_source *i; + + for (i = pci_dev_dma_source; i->dma_source; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) + return i->dma_source(dev); + } + + return pci_dev_get(dev); +} diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..39983be7b25b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1332,6 +1332,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, static inline int pci_domain_nr(struct pci_bus *bus) { return 0; } +static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) +{ return NULL; } + #define dev_is_pci(d) (false) #define dev_is_pf(d) (false) #define dev_num_vf(d) (0) @@ -1486,9 +1489,14 @@ enum pci_fixup_pass { #ifdef CONFIG_PCI_QUIRKS void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); +struct pci_dev *pci_get_dma_source(struct pci_dev *dev); #else static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} +static inline struct pci_dev *pci_get_dma_source(struct pci_dev *dev) +{ + return pci_dev_get(dev); +} #endif void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); -- GitLab From 20c5fd399482ef5b87a41ab064b3255f1faaaee4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 10:03:20 +0800 Subject: [PATCH 0485/5711] ASoC: wm8903: Move pin configuration into I2C probe() function Ensure that the device pins are configured as soon as possible by moving the pin configration (including MICBIAS) into the I2C probe() function. This had been done in the CODEC probe() function when we were relying on the ASoC register I/O code. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- sound/soc/codecs/wm8903.c | 92 ++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 3abd450842ee..64ca9042bad3 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1,7 +1,7 @@ /* * wm8903.c -- WM8903 ALSA SoC Audio driver * - * Copyright 2008-11 Wolfson Microelectronics + * Copyright 2008-12 Wolfson Microelectronics * Copyright 2011-2012 NVIDIA, Inc. * * Author: Mark Brown @@ -1880,10 +1880,9 @@ static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); struct wm8903_platform_data *pdata = wm8903->pdata; - int ret, i; + int ret; int trigger, irq_pol; u16 val; - bool mic_gpio = false; wm8903->codec = codec; codec->control_data = wm8903->regmap; @@ -1894,47 +1893,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) return ret; } - /* Set up GPIOs, detect if any are MIC detect outputs */ - for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { - if ((!pdata->gpio_cfg[i]) || - (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) - continue; - - snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, - pdata->gpio_cfg[i] & 0x7fff); - - val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) - >> WM8903_GP1_FN_SHIFT; - - switch (val) { - case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: - case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: - mic_gpio = true; - break; - default: - break; - } - } - - /* Set up microphone detection */ - snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, - pdata->micdet_cfg); - - /* Microphone detection needs the WSEQ clock */ - if (pdata->micdet_cfg) - snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, - WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); - - /* If microphone detection is enabled by pdata but - * detected via IRQ then interrupts can be lost before - * the machine driver has set up microphone detection - * IRQs as the IRQs are clear on read. The detection - * will be enabled when the machine driver configures. - */ - WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); - - wm8903->mic_delay = pdata->micdet_delay; - if (wm8903->irq) { if (pdata->irq_active_low) { trigger = IRQF_TRIGGER_LOW; @@ -2115,8 +2073,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, { struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); struct wm8903_priv *wm8903; + bool mic_gpio = false; unsigned int val; - int ret; + int ret, i; wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), GFP_KERNEL); @@ -2160,6 +2119,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, } } + pdata = wm8903->pdata; + ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); if (ret != 0) { dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); @@ -2184,6 +2145,47 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, wm8903_init_gpio(wm8903); + /* Set up GPIO pin state, detect if any are MIC detect outputs */ + for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { + if ((!pdata->gpio_cfg[i]) || + (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) + continue; + + regmap_write(wm8903->regmap, WM8903_GPIO_CONTROL_1 + i, + pdata->gpio_cfg[i] & 0x7fff); + + val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) + >> WM8903_GP1_FN_SHIFT; + + switch (val) { + case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: + case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: + mic_gpio = true; + break; + default: + break; + } + } + + /* Set up microphone detection */ + regmap_write(wm8903->regmap, WM8903_MIC_BIAS_CONTROL_0, + pdata->micdet_cfg); + + /* Microphone detection needs the WSEQ clock */ + if (pdata->micdet_cfg) + regmap_update_bits(wm8903->regmap, WM8903_WRITE_SEQUENCER_0, + WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); + + /* If microphone detection is enabled by pdata but + * detected via IRQ then interrupts can be lost before + * the machine driver has set up microphone detection + * IRQs as the IRQs are clear on read. The detection + * will be enabled when the machine driver configures. + */ + WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); + + wm8903->mic_delay = pdata->micdet_delay; + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8903, &wm8903_dai, 1); if (ret != 0) -- GitLab From e373cbfb2f7d194e48d528794b3b99274d4c1a97 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 10:06:11 +0800 Subject: [PATCH 0486/5711] ASoC: wm8903: Make interrupt handler use regmap directly There's no urgent need for the interrupt handler to use the ASoC I/O functions and it'll support a further move in where we request the interrupt so call the regmap APIs directly. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- sound/soc/codecs/wm8903.c | 48 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 64ca9042bad3..f5d47c8e5402 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1636,17 +1636,27 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); static irqreturn_t wm8903_irq(int irq, void *data) { - struct snd_soc_codec *codec = data; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int mic_report; - int int_pol; - int int_val = 0; - int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK); + struct wm8903_priv *wm8903 = data; + int mic_report, ret; + unsigned int int_val, mask, int_pol; + + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1_MASK, + &mask); + if (ret != 0) { + dev_err(wm8903->dev, "Failed to read IRQ mask: %d\n", ret); + return IRQ_NONE; + } + + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1, &int_val); + if (ret != 0) { + dev_err(wm8903->dev, "Failed to read IRQ status: %d\n", ret); + return IRQ_NONE; + } - int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; + int_val &= ~mask; if (int_val & WM8903_WSEQ_BUSY_EINT) { - dev_warn(codec->dev, "Write sequencer done\n"); + dev_warn(wm8903->dev, "Write sequencer done\n"); } /* @@ -1657,22 +1667,28 @@ static irqreturn_t wm8903_irq(int irq, void *data) * the polarity register. */ mic_report = wm8903->mic_last_report; - int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, + &int_pol); + if (ret != 0) { + dev_err(wm8903->dev, "Failed to read interrupt polarity: %d\n", + ret); + return IRQ_HANDLED; + } #ifndef CONFIG_SND_SOC_WM8903_MODULE if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) - trace_snd_soc_jack_irq(dev_name(codec->dev)); + trace_snd_soc_jack_irq(dev_name(wm8903->dev)); #endif if (int_val & WM8903_MICSHRT_EINT) { - dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); + dev_dbg(wm8903->dev, "Microphone short (pol=%x)\n", int_pol); mic_report ^= wm8903->mic_short; int_pol ^= WM8903_MICSHRT_INV; } if (int_val & WM8903_MICDET_EINT) { - dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); + dev_dbg(wm8903->dev, "Microphone detect (pol=%x)\n", int_pol); mic_report ^= wm8903->mic_det; int_pol ^= WM8903_MICDET_INV; @@ -1680,8 +1696,8 @@ static irqreturn_t wm8903_irq(int irq, void *data) msleep(wm8903->mic_delay); } - snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, - WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); + regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, + WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); snd_soc_jack_report(wm8903->mic_jack, mic_report, wm8903->mic_short | wm8903->mic_det); @@ -1907,7 +1923,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, trigger | IRQF_ONESHOT, - "wm8903", codec); + "wm8903", wm8903); if (ret != 0) { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); @@ -1963,7 +1979,7 @@ static int wm8903_remove(struct snd_soc_codec *codec) wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); if (wm8903->irq) - free_irq(wm8903->irq, codec); + free_irq(wm8903->irq, wm8903); return 0; } -- GitLab From b7c95d9146c8201740e2ce9dca7fb1eb8b7b0053 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 10:15:10 +0800 Subject: [PATCH 0487/5711] ASoC: wm8903: Move interrupt request to I2C probe There's no reason to defer requesting of the interrupt until the CODEC probe and doing so results in more work if we hit an error as we'll have registered the CODEC with the core. It's neater to acquire as many of the resources we'll need as we can in the bus probe function. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- sound/soc/codecs/wm8903.c | 65 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f5d47c8e5402..7261a68aac6f 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1895,9 +1895,7 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct wm8903_platform_data *pdata = wm8903->pdata; int ret; - int trigger, irq_pol; u16 val; wm8903->codec = codec; @@ -1909,32 +1907,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) return ret; } - if (wm8903->irq) { - if (pdata->irq_active_low) { - trigger = IRQF_TRIGGER_LOW; - irq_pol = WM8903_IRQ_POL; - } else { - trigger = IRQF_TRIGGER_HIGH; - irq_pol = 0; - } - - snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, - WM8903_IRQ_POL, irq_pol); - - ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, - trigger | IRQF_ONESHOT, - "wm8903", wm8903); - if (ret != 0) { - dev_err(codec->dev, "Failed to request IRQ: %d\n", - ret); - return ret; - } - - /* Enable write sequencer interrupts */ - snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, - WM8903_IM_WSEQ_BUSY_EINT, 0); - } - /* power on device */ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1975,11 +1947,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) /* power down chip */ static int wm8903_remove(struct snd_soc_codec *codec) { - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - if (wm8903->irq) - free_irq(wm8903->irq, wm8903); return 0; } @@ -2089,8 +2057,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, { struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); struct wm8903_priv *wm8903; + int trigger; bool mic_gpio = false; - unsigned int val; + unsigned int val, irq_pol; int ret, i; wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), @@ -2108,7 +2077,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, } i2c_set_clientdata(i2c, wm8903); - wm8903->irq = i2c->irq; /* If no platform data was supplied, create storage for defaults */ if (pdata) { @@ -2202,6 +2170,33 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, wm8903->mic_delay = pdata->micdet_delay; + if (i2c->irq) { + if (pdata->irq_active_low) { + trigger = IRQF_TRIGGER_LOW; + irq_pol = WM8903_IRQ_POL; + } else { + trigger = IRQF_TRIGGER_HIGH; + irq_pol = 0; + } + + regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_CONTROL, + WM8903_IRQ_POL, irq_pol); + + ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, + trigger | IRQF_ONESHOT, + "wm8903", wm8903); + if (ret != 0) { + dev_err(wm8903->dev, "Failed to request IRQ: %d\n", + ret); + return ret; + } + + /* Enable write sequencer interrupts */ + regmap_update_bits(wm8903->regmap, + WM8903_INTERRUPT_STATUS_1_MASK, + WM8903_IM_WSEQ_BUSY_EINT, 0); + } + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8903, &wm8903_dai, 1); if (ret != 0) @@ -2216,6 +2211,8 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) { struct wm8903_priv *wm8903 = i2c_get_clientdata(client); + if (client->irq) + free_irq(client->irq, wm8903); wm8903_free_gpio(wm8903); snd_soc_unregister_codec(&client->dev); -- GitLab From a89c3e956ae78cec8926b92f2d61b7a5b675e787 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 9 Jun 2012 10:30:34 +0800 Subject: [PATCH 0488/5711] ASoC: wm8903: Move register default changes to I2C probe Also convert to use update_bits() while we're at it. No great need to do this, it's just a bit neater to do as much as possible in the I2C probe. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- sound/soc/codecs/wm8903.c | 63 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 7261a68aac6f..73f1c8d7bafb 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1896,7 +1896,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); int ret; - u16 val; wm8903->codec = codec; codec->control_data = wm8903->regmap; @@ -1910,37 +1909,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) /* power on device */ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* Latch volume update bits */ - val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); - val |= WM8903_ADCVU; - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); - - val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); - val |= WM8903_DACVU; - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT); - val |= WM8903_HPOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT); - val |= WM8903_LINEOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT); - val |= WM8903_SPKVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); - - /* Enable DAC soft mute by default */ - snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, - WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, - WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); - return ret; } @@ -2197,6 +2165,37 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, WM8903_IM_WSEQ_BUSY_EINT, 0); } + /* Latch volume update bits */ + regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_LEFT, + WM8903_ADCVU, WM8903_ADCVU); + regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_RIGHT, + WM8903_ADCVU, WM8903_ADCVU); + + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_LEFT, + WM8903_DACVU, WM8903_DACVU); + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_RIGHT, + WM8903_DACVU, WM8903_DACVU); + + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_LEFT, + WM8903_HPOUTVU, WM8903_HPOUTVU); + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_RIGHT, + WM8903_HPOUTVU, WM8903_HPOUTVU); + + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_LEFT, + WM8903_LINEOUTVU, WM8903_LINEOUTVU); + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_RIGHT, + WM8903_LINEOUTVU, WM8903_LINEOUTVU); + + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_LEFT, + WM8903_SPKVU, WM8903_SPKVU); + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_RIGHT, + WM8903_SPKVU, WM8903_SPKVU); + + /* Enable DAC soft mute by default */ + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_1, + WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, + WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8903, &wm8903_dai, 1); if (ret != 0) -- GitLab From c32823f82b42abc1f08b365085862fd1d57c0b61 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Fri, 1 Jun 2012 15:16:25 -0600 Subject: [PATCH 0489/5711] PCI: make pci_ltr_supported() static The PCI Express Latency Tolerance Reporting (LTR) feature's pci_ltr_supported() routine is currently only used within drivers/pci/pci.c so make it static. Acked-by: Donald Dutile Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 3 +-- include/linux/pci.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..847e0c35cdb7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2169,7 +2169,7 @@ EXPORT_SYMBOL(pci_disable_obff); * RETURNS: * True if @dev supports latency tolerance reporting, false otherwise. */ -bool pci_ltr_supported(struct pci_dev *dev) +static bool pci_ltr_supported(struct pci_dev *dev) { int pos; u32 cap; @@ -2185,7 +2185,6 @@ bool pci_ltr_supported(struct pci_dev *dev) return cap & PCI_EXP_DEVCAP2_LTR; } -EXPORT_SYMBOL(pci_ltr_supported); /** * pci_enable_ltr - enable latency tolerance reporting diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..b2bec26b7f0a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -875,7 +875,6 @@ enum pci_obff_signal_type { int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type); void pci_disable_obff(struct pci_dev *dev); -bool pci_ltr_supported(struct pci_dev *dev); int pci_enable_ltr(struct pci_dev *dev); void pci_disable_ltr(struct pci_dev *dev); int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns); -- GitLab From cb97ae3485955401d637bd269b0d24d3cd3fd3ec Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Fri, 1 Jun 2012 15:16:31 -0600 Subject: [PATCH 0490/5711] PCI: remove redundant checking in PCI Express capability routines There are a number of redundant pci_is_pcie() checks in various PCI Express capabilities related routines like the following: if (!pci_is_pcie(dev)) return false; pos = pci_pcie_cap(dev); if (!pos) return false; The current pci_is_pcie() implementation is merely: static inline bool pci_is_pcie(struct pci_dev *dev) { return !!pci_pcie_cap(dev); } so we can just drop the pci_is_pcie() test in such cases. Acked-by: Donald Dutile Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 847e0c35cdb7..766bb13bb0a3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1994,7 +1994,7 @@ void pci_enable_ari(struct pci_dev *dev) return; bridge = dev->bus->self; - if (!bridge || !pci_is_pcie(bridge)) + if (!bridge) return; pos = pci_pcie_cap(bridge); @@ -2054,9 +2054,6 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type) int pos; u16 ctrl; - if (!pci_is_pcie(dev)) - return; - pos = pci_pcie_cap(dev); if (!pos) return; @@ -2096,9 +2093,6 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) u16 ctrl; int ret; - if (!pci_is_pcie(dev)) - return -ENOTSUPP; - pos = pci_pcie_cap(dev); if (!pos) return -ENOTSUPP; @@ -2149,9 +2143,6 @@ void pci_disable_obff(struct pci_dev *dev) int pos; u16 ctrl; - if (!pci_is_pcie(dev)) - return; - pos = pci_pcie_cap(dev); if (!pos) return; @@ -2174,9 +2165,6 @@ static bool pci_ltr_supported(struct pci_dev *dev) int pos; u32 cap; - if (!pci_is_pcie(dev)) - return false; - pos = pci_pcie_cap(dev); if (!pos) return false; -- GitLab From c463b8cb9350cf1230cefe467a1cf279140a5437 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Fri, 1 Jun 2012 15:16:37 -0600 Subject: [PATCH 0491/5711] PCI: add pci_pcie_cap2() check for PCIe feature capabilities >= v2 This patch resolves potential issues when accessing PCI Express Capability structures. The makeup of the capability varies substantially between v1 and v2: Version 1 of the PCI Express Capability (defined by PCI Express 1.0 and 1.1 base) neither requires the endpoint to implement the entire PCIe capability structure nor specifies default values of registers that are not implemented by the device. Version 2 of the PCI Express Capability (defined by PCIe 1.1 Capability Structure Expansion ECN, PCIe 2.0, 2.1, and 3.0) added additional registers to the structure and requires all registers to be either implemented or hardwired to 0. Due to the differences in the capability structures, code dealing with capability features must be careful not to access the additional registers introduced with v2 unless the device is specifically known to be a v2 capable device. Otherwise, attempts to access non-existant registers will occur. This is a subtle issue that is hard to track down when it occurs (and it has - see commit 864d296cf94). To try and help mitigate such occurrences, this patch introduces pci_pcie_cap2() which is similar to pci_pcie_cap() but also checks that the PCIe capability version is >= 2. pci_pcie_cap2() should be used for qualifying PCIe capability features introduced after v1. Suggested by Don Dutile. Acked-by: Donald Dutile Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 65 ++++++++++++++++++++++++++++++---------- include/linux/pci_regs.h | 6 ++++ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 766bb13bb0a3..985df63aa59f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -277,6 +277,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) return pos; } +/** + * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure + * @dev: PCI device to check + * + * Like pci_pcie_cap() but also checks that the PCIe capability version is + * >= 2. Note that v1 capability structures could be sparse in that not + * all register fields were required. v2 requires the entire structure to + * be present size wise, while still allowing for non-implemented registers + * to exist but they must be hardwired to 0. + * + * Due to the differences in the versions of capability structures, one + * must be careful not to try and access non-existant registers that may + * exist in early versions - v1 - of Express devices. + * + * Returns the offset of the PCIe capability structure as long as the + * capability version is >= 2; otherwise 0 is returned. + */ +static int pci_pcie_cap2(struct pci_dev *dev) +{ + u16 flags; + int pos; + + pos = pci_pcie_cap(dev); + if (pos) { + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); + if ((flags & PCI_EXP_FLAGS_VERS) < 2) + pos = 0; + } + + return pos; +} + /** * pci_find_ext_capability - Find an extended capability * @dev: PCI device to query @@ -1983,7 +2015,7 @@ void pci_enable_ari(struct pci_dev *dev) { int pos; u32 cap; - u16 flags, ctrl; + u16 ctrl; struct pci_dev *bridge; if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) @@ -1997,15 +2029,11 @@ void pci_enable_ari(struct pci_dev *dev) if (!bridge) return; - pos = pci_pcie_cap(bridge); + /* ARI is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(bridge); if (!pos) return; - /* ARI is a PCIe v2 feature */ - pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags); - if ((flags & PCI_EXP_FLAGS_VERS) < 2) - return; - pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; @@ -2018,7 +2046,7 @@ void pci_enable_ari(struct pci_dev *dev) } /** - * pci_enable_ido - enable ID-based ordering on a device + * pci_enable_ido - enable ID-based Ordering on a device * @dev: the PCI device * @type: which types of IDO to enable * @@ -2031,7 +2059,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type) int pos; u16 ctrl; - pos = pci_pcie_cap(dev); + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -2054,7 +2083,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type) int pos; u16 ctrl; - pos = pci_pcie_cap(dev); + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -2093,7 +2123,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) u16 ctrl; int ret; - pos = pci_pcie_cap(dev); + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return -ENOTSUPP; @@ -2143,7 +2174,8 @@ void pci_disable_obff(struct pci_dev *dev) int pos; u16 ctrl; - pos = pci_pcie_cap(dev); + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -2165,7 +2197,8 @@ static bool pci_ltr_supported(struct pci_dev *dev) int pos; u32 cap; - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return false; @@ -2193,7 +2226,8 @@ int pci_enable_ltr(struct pci_dev *dev) if (!pci_ltr_supported(dev)) return -ENOTSUPP; - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return -ENOTSUPP; @@ -2228,7 +2262,8 @@ void pci_disable_ltr(struct pci_dev *dev) if (!pci_ltr_supported(dev)) return; - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 4b608f543412..e7642f5bb12a 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -507,6 +507,12 @@ #define PCI_EXP_RTSTA 32 /* Root Status */ #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ +/* + * Note that the following PCI Express 'Capability Structure' registers + * were introduced with 'Capability Version' 0x2 (v2). These registers + * do not exist on devices with Capability Version 1. Use pci_pcie_cap2() + * to use these fields safely. + */ #define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ #define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ #define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */ -- GitLab From 9cb604ed45a31419bab3877472691a5da15a3c47 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Fri, 1 Jun 2012 15:16:43 -0600 Subject: [PATCH 0492/5711] PCI: remove redundant capabilities checking in pci_{save, restore}_pcie_state Unlike PCI Express v1's Capabilities Structure, v2's requires the entire structure to be implemented. In v2 structures, register fields that are not implemented are present but hardwired to 0x0. These may include: Link Capabilities, Status, and Control; Slot Capabilities, Status, and Control; Root Capabilities, Status, and Control; and all of the '2' (Device, Link, and Slot) Capabilities, Status, and Control registers. This patch removes the redundant capability checks corresponding to the Link 2's and Slot 2's, Capabilities, Status, and Control registers as they will be present if Device Capabilities 2's registers are (which explains why the macros for each of the three are identical). Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 985df63aa59f..fe26df7cf5cd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -854,12 +854,6 @@ EXPORT_SYMBOL(pci_choose_state); ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ (type == PCI_EXP_TYPE_ROOT_PORT || \ type == PCI_EXP_TYPE_RC_EC)) -#define pcie_cap_has_devctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) -#define pcie_cap_has_lnkctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) -#define pcie_cap_has_sltctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) static struct pci_cap_saved_state *pci_find_saved_cap( struct pci_dev *pci_dev, char cap) @@ -902,13 +896,14 @@ static int pci_save_pcie_state(struct pci_dev *dev) pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); if (pcie_cap_has_rtctl(dev->pcie_type, flags)) pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); - if (pcie_cap_has_devctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); - if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); - if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); + pos = pci_pcie_cap2(dev); + if (!pos) + return 0; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); return 0; } @@ -935,12 +930,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); if (pcie_cap_has_rtctl(dev->pcie_type, flags)) pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); - if (pcie_cap_has_devctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); - if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); - if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); + + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); + pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); } -- GitLab From f242e50eee1ec7692c4854d94e8cd543991cce71 Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 7 Jun 2012 14:00:46 +0200 Subject: [PATCH 0493/5711] mfd/ab8500: Move platform-data for ab8500-codec into mfd-driver The platform-data used by the Ux500 ASoC-driver is moved from the machine-driver context into the codec-driver context. This means adding the platform-data for 'ab8500-codec' into the main AB8500 platform-data. Signed-off-by: Ola Lilja Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500.c | 14 +++++++ include/linux/mfd/abx500/ab8500-codec.h | 52 +++++++++++++++++++++++++ include/linux/mfd/abx500/ab8500.h | 2 + 3 files changed, 68 insertions(+) create mode 100644 include/linux/mfd/abx500/ab8500-codec.h diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 9c74ac545849..c8a8fde777bb 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,18 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { 0x7A, 0x00, 0x00}, }; +/* ab8500-codec */ +static struct ab8500_codec_platform_data ab8500_codec_pdata = { + .amics = { + .mic1_type = AMIC_TYPE_DIFFERENTIAL, + .mic2_type = AMIC_TYPE_DIFFERENTIAL, + .mic1a_micbias = AMIC_MICBIAS_VAMIC1, + .mic1b_micbias = AMIC_MICBIAS_VAMIC1, + .mic2_micbias = AMIC_MICBIAS_VAMIC2 + }, + .ear_cmv = EAR_CMV_0_95V +}; + static struct gpio_keys_button snowball_key_array[] = { { .gpio = 32, @@ -195,6 +208,7 @@ static struct ab8500_platform_data ab8500_platdata = { .regulator = ab8500_regulators, .num_regulator = ARRAY_SIZE(ab8500_regulators), .gpio = &ab8500_gpio_pdata, + .codec = &ab8500_codec_pdata, }; static struct resource ab8500_resources[] = { diff --git a/include/linux/mfd/abx500/ab8500-codec.h b/include/linux/mfd/abx500/ab8500-codec.h new file mode 100644 index 000000000000..dc6529202cdd --- /dev/null +++ b/include/linux/mfd/abx500/ab8500-codec.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja + * for ST-Ericsson. + * + * License terms: + * + * 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 AB8500_CORE_CODEC_H +#define AB8500_CORE_CODEC_H + +/* Mic-types */ +enum amic_type { + AMIC_TYPE_SINGLE_ENDED, + AMIC_TYPE_DIFFERENTIAL +}; + +/* Mic-biases */ +enum amic_micbias { + AMIC_MICBIAS_VAMIC1, + AMIC_MICBIAS_VAMIC2 +}; + +/* Bias-voltage */ +enum ear_cm_voltage { + EAR_CMV_0_95V, + EAR_CMV_1_10V, + EAR_CMV_1_27V, + EAR_CMV_1_58V +}; + +/* Analog microphone settings */ +struct amic_settings { + enum amic_type mic1_type; + enum amic_type mic2_type; + enum amic_micbias mic1a_micbias; + enum amic_micbias mic1b_micbias; + enum amic_micbias mic2_micbias; +}; + +/* Platform data structure for the audio-parts of the AB8500 */ +struct ab8500_codec_platform_data { + struct amic_settings amics; + enum ear_cm_voltage ear_cmv; +}; + +#endif diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 91dd3ef63e99..bc9b84b60ec6 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -266,6 +266,7 @@ struct ab8500 { struct regulator_reg_init; struct regulator_init_data; struct ab8500_gpio_platform_data; +struct ab8500_codec_platform_data; /** * struct ab8500_platform_data - AB8500 platform data @@ -284,6 +285,7 @@ struct ab8500_platform_data { int num_regulator; struct regulator_init_data *regulator; struct ab8500_gpio_platform_data *gpio; + struct ab8500_codec_platform_data *codec; }; extern int __devinit ab8500_init(struct ab8500 *ab8500, -- GitLab From 4eceb14f669cb9e9d189019e8fcbf73577fe77a7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 11 Jun 2012 23:55:32 -0700 Subject: [PATCH 0494/5711] Input: gpio_keys - remove useless reinitialization of pdata->nbuttons pdata is zeroed using memset just a few lines before, so there is no need to set the nbuttons member to 0 again. Signed-off-by: Tobias Klauser Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 62bfce468f9f..cbb1add43d5e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -559,7 +559,6 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, pdata->rep = !!of_get_property(node, "autorepeat", NULL); /* First count the subnodes */ - pdata->nbuttons = 0; pp = NULL; while ((pp = of_get_next_child(node, pp))) pdata->nbuttons++; -- GitLab From 03ecd229a5d05a5c62e7262d66ec6cd57d5eca6c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jun 2012 00:21:47 -0700 Subject: [PATCH 0495/5711] Input: ab8500-ponkey - add device tree support Allow the ab8500-ponkey driver to be probed during boot when Device Tree is enabled. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ab8500-ponkey.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 350fd0c385d2..84ec691c05aa 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /** @@ -131,10 +132,18 @@ static int __devexit ab8500_ponkey_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id ab8500_ponkey_match[] = { + { .compatible = "stericsson,ab8500-ponkey", }, + {} +}; +#endif + static struct platform_driver ab8500_ponkey_driver = { .driver = { .name = "ab8500-poweron-key", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ab8500_ponkey_match), }, .probe = ab8500_ponkey_probe, .remove = __devexit_p(ab8500_ponkey_remove), -- GitLab From ea2e60244573a9204c8cee9b4fb181106784c617 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 12 Jun 2012 00:14:12 -0700 Subject: [PATCH 0496/5711] Input: wacom - rearrange type enum So we can simplify a few type related if statements Signed-off-by: Ping Cheng Acked-by: Chris Bagwell Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 10 +++------- drivers/input/tablet/wacom_wac.c | 6 ++---- drivers/input/tablet/wacom_wac.h | 6 +++--- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b3a8bd3514b2..79b5cfbc1bc4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -440,8 +440,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* ask to report Wacom data */ if (features->device_type == BTN_TOOL_FINGER) { /* if it is an MT Tablet PC touch */ - if (features->type == TABLETPC2FG || - features->type == MTSCREEN) { + if (features->type > TABLETPC) { do { rep_data[0] = 3; rep_data[1] = 4; @@ -460,7 +459,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); } - } else if (features->type != TABLETPC && + } else if (features->type <= BAMBOO_PT && features->type != WIRELESS && features->device_type == BTN_TOOL_PEN) { do { @@ -510,10 +509,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, } /* only devices that support touch need to retrieve the info */ - if (features->type != TABLETPC && - features->type != TABLETPC2FG && - features->type != BAMBOO_PT && - features->type != MTSCREEN) { + if (features->type < BAMBOO_PT) { goto out; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 004bc1bb1544..c40dcb7036b3 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1317,10 +1317,8 @@ void wacom_setup_device_quirks(struct wacom_features *features) } /* these device have multiple inputs */ - if (features->type == TABLETPC || features->type == TABLETPC2FG || - features->type == BAMBOO_PT || features->type == WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L) || - features->type == MTSCREEN) + if (features->type >= WIRELESS || + (features->type >= INTUOS5S && features->type <= INTUOS5L)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 78fbd3f42009..87080435116c 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -62,8 +62,6 @@ enum { PTU, PL, DTU, - BAMBOO_PT, - WIRELESS, INTUOS, INTUOS3S, INTUOS3, @@ -79,7 +77,9 @@ enum { CINTIQ, WACOM_BEE, WACOM_MO, - TABLETPC, + WIRELESS, + BAMBOO_PT, + TABLETPC, /* add new TPC below */ TABLETPC2FG, MTSCREEN, MAX_TYPE -- GitLab From ac173837cd4b268a538235a1699b91457551a9a9 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 12 Jun 2012 00:15:06 -0700 Subject: [PATCH 0497/5711] Input: wacom - add two new devices (0xed and 0xef) 0xed supports pen and one finger touch; 0xef is pen only. Signed-off-by: Ping Cheng Acked-by: Chris Bagwell Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 13 ++++++++++++- drivers/input/tablet/wacom_wac.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c40dcb7036b3..fd0cf4d328a3 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -888,7 +888,7 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) prox = data[0] & 0x01; x = get_unaligned_le16(&data[1]); y = get_unaligned_le16(&data[3]); - } else { /* with capacity */ + } else { prox = data[1] & 0x01; x = le16_to_cpup((__le16 *)&data[2]); y = le16_to_cpup((__le16 *)&data[4]); @@ -961,6 +961,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) case WACOM_REPORT_TPC1FG: case WACOM_REPORT_TPCHID: case WACOM_REPORT_TPCST: + case WACOM_REPORT_TPC1FGE: return wacom_tpc_single_touch(wacom, len); case WACOM_REPORT_TPCMT: @@ -1244,6 +1245,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case TABLETPC: + case TABLETPCE: case TABLETPC2FG: case MTSCREEN: sync = wacom_tpc_irq(wacom_wac, len); @@ -1569,6 +1571,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case TABLETPC: + case TABLETPCE: __clear_bit(ABS_MISC, input_dev->absbit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); @@ -1886,6 +1889,12 @@ static const struct wacom_features wacom_features_0xE6 = static const struct wacom_features wacom_features_0xEC = { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xED = + { "Wacom ISDv4 ED", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xEF = + { "Wacom ISDv4 EF", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x47 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2060,6 +2069,8 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xE5) }, { USB_DEVICE_WACOM(0xE6) }, { USB_DEVICE_WACOM(0xEC) }, + { USB_DEVICE_WACOM(0xED) }, + { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_LENOVO(0x6004) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 87080435116c..bd5d37b28714 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -48,6 +48,7 @@ #define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 +#define WACOM_REPORT_TPC1FGE 18 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -80,6 +81,7 @@ enum { WIRELESS, BAMBOO_PT, TABLETPC, /* add new TPC below */ + TABLETPCE, TABLETPC2FG, MTSCREEN, MAX_TYPE -- GitLab From b7af2bb84cea328c766c615aac45cdd498c50bc6 Mon Sep 17 00:00:00 2001 From: Chris Bagwell Date: Tue, 12 Jun 2012 00:25:23 -0700 Subject: [PATCH 0498/5711] Input: wacom - battery reporting improvements Do not register battery device until connected to a tablet. This prevents an empty battery icon from being shown when tablet is connected using USB cable. Also, call power_supply_powers() for apps that can make use of that info. And stop ignoring input registration failures. Signed-off-by: Chris Bagwell Reviewed-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 82 +++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 79b5cfbc1bc4..a48fcb76bb83 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -963,6 +963,10 @@ static int wacom_initialize_battery(struct wacom *wacom) error = power_supply_register(&wacom->usbdev->dev, &wacom->battery); + + if (!error) + power_supply_powers(&wacom->battery, + &wacom->usbdev->dev); } return error; @@ -970,8 +974,11 @@ static int wacom_initialize_battery(struct wacom *wacom) static void wacom_destroy_battery(struct wacom *wacom) { - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR && + wacom->battery.dev) { power_supply_unregister(&wacom->battery); + wacom->battery.dev = NULL; + } } static int wacom_register_input(struct wacom *wacom) @@ -1018,23 +1025,30 @@ static void wacom_wireless_work(struct work_struct *work) struct wacom *wacom = container_of(work, struct wacom, work); struct usb_device *usbdev = wacom->usbdev; struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom *wacom1, *wacom2; + struct wacom_wac *wacom_wac1, *wacom_wac2; + int error; /* * Regardless if this is a disconnect or a new tablet, - * remove any existing input devices. + * remove any existing input and battery devices. */ + wacom_destroy_battery(wacom); + /* Stylus interface */ - wacom = usb_get_intfdata(usbdev->config->interface[1]); - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - wacom->wacom_wac.input = NULL; + wacom1 = usb_get_intfdata(usbdev->config->interface[1]); + wacom_wac1 = &(wacom1->wacom_wac); + if (wacom_wac1->input) + input_unregister_device(wacom_wac1->input); + wacom_wac1->input = NULL; /* Touch interface */ - wacom = usb_get_intfdata(usbdev->config->interface[2]); - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - wacom->wacom_wac.input = NULL; + wacom2 = usb_get_intfdata(usbdev->config->interface[2]); + wacom_wac2 = &(wacom2->wacom_wac); + if (wacom_wac2->input) + input_unregister_device(wacom_wac2->input); + wacom_wac2->input = NULL; if (wacom_wac->pid == 0) { dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); @@ -1059,24 +1073,39 @@ static void wacom_wireless_work(struct work_struct *work) } /* Stylus interface */ - wacom = usb_get_intfdata(usbdev->config->interface[1]); - wacom_wac = &wacom->wacom_wac; - wacom_wac->features = + wacom_wac1->features = *((struct wacom_features *)id->driver_info); - wacom_wac->features.device_type = BTN_TOOL_PEN; - wacom_register_input(wacom); + wacom_wac1->features.device_type = BTN_TOOL_PEN; + error = wacom_register_input(wacom1); + if (error) + goto fail1; /* Touch interface */ - wacom = usb_get_intfdata(usbdev->config->interface[2]); - wacom_wac = &wacom->wacom_wac; - wacom_wac->features = + wacom_wac2->features = *((struct wacom_features *)id->driver_info); - wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac->features.device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(&wacom_wac->features); - wacom_wac->features.x_max = wacom_wac->features.y_max = 4096; - wacom_register_input(wacom); + wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; + wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_set_phy_from_res(&wacom_wac2->features); + wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; + error = wacom_register_input(wacom2); + if (error) + goto fail2; + + error = wacom_initialize_battery(wacom); + if (error) + goto fail3; } + + return; + +fail3: + input_unregister_device(wacom_wac2->input); + wacom_wac2->input = NULL; +fail2: + input_unregister_device(wacom_wac1->input); + wacom_wac1->input = NULL; +fail1: + return; } static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1179,14 +1208,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i if (error) goto fail4; - error = wacom_initialize_battery(wacom); - if (error) - goto fail5; - if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_register_input(wacom); if (error) - goto fail6; + goto fail5; } /* Note that if query fails it is not a hard failure */ @@ -1201,7 +1226,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; - fail6: wacom_destroy_battery(wacom); fail5: wacom_destroy_leds(wacom); fail4: wacom_remove_shared_data(wacom_wac); fail3: usb_free_urb(wacom->irq); -- GitLab From 6dc463511d4a690f01a9248df3b384db717e0b1c Mon Sep 17 00:00:00 2001 From: Chris Bagwell Date: Tue, 12 Jun 2012 00:25:48 -0700 Subject: [PATCH 0499/5711] Input: wacom - Bamboo One 1024 pressure fix Bamboo One's with ID of 0x6a and 0x6b were added with correct indication of 1024 pressure levels but the Graphire packet routine was only looking at 9 bits. Increased to 10 bits. This bug caused these devices to roll over to zero pressure at half way mark. The other devices using this routine only support 256 or 512 range and look to fix unused bits at zero. Signed-off-by: Chris Bagwell Reported-by: Tushant Mirchandani Reviewed-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index fd0cf4d328a3..4453864956b6 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -248,7 +248,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); + input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8)); input_report_key(input, BTN_TOUCH, data[1] & 0x01); input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x04); -- GitLab From a19fc98685ad0b5bccc38ca17acb50a92915ec51 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 12 Jun 2012 00:27:53 -0700 Subject: [PATCH 0500/5711] Input: wacom - initialize and destroy LEDs for Intuos4 S tablets This case appears to have been missed in the original commit. Signed-off-by: Jason Gerecke Reviewed-by: Chris Bagwell Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a48fcb76bb83..a5d1c60e77ee 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -851,6 +851,7 @@ static int wacom_initialize_leds(struct wacom *wacom) /* Initialize default values */ switch (wacom->wacom_wac.features.type) { + case INTUOS4S: case INTUOS4: case INTUOS4L: wacom->led.select[0] = 0; @@ -904,6 +905,7 @@ static int wacom_initialize_leds(struct wacom *wacom) static void wacom_destroy_leds(struct wacom *wacom) { switch (wacom->wacom_wac.features.type) { + case INTUOS4S: case INTUOS4: case INTUOS4L: sysfs_remove_group(&wacom->intf->dev.kobj, -- GitLab From 32edbf562cabc0fb927692c86274c3cd2ccde0d0 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 12 Jun 2012 00:28:37 -0700 Subject: [PATCH 0501/5711] Input: wacom - remove code duplication Replaces code to calculate Intuos5 physical dimensions with a call to an existing function that performs the same task. Signed-off-by: Jason Gerecke Reviewed-by: Chris Bagwell Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a5d1c60e77ee..9e8fdcf005a3 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1171,10 +1171,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; - features->x_phy = - (features->x_max * 100) / features->x_resolution; - features->y_phy = - (features->y_max * 100) / features->y_resolution; + wacom_set_phy_from_res(features); features->x_max = 4096; features->y_max = 4096; -- GitLab From e7ec014a47e4d68fc01561d0541a50650646317c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 12 Jun 2012 01:10:02 -0700 Subject: [PATCH 0502/5711] Input: twl6040-vibra - update for device tree support The twl6040 DT support implementation has been changed from the originally planned. None of the child devices going to have compatible_of property which means that the child devices of twl6040 will be created as traditional MFD devices. The mfd core driver will decide (based on the DT blob) to create a device for the twl6040-vibra or not. If the DT blob has 'vibra' section the device will be created without pdata. In this case the vibra driver will reach up to the parent node to get the needed properties. With DT booted kernel we no longer be able to link the regulators to the vibra driver, they can be only linked to the MFD device (probed via DT). From the vibra driver we ned to use pdev->dev.parent to get the regulators. Signed-off-by: Peter Ujfalusi Signed-off-by: Dmitry Torokhov --- .../bindings/input/twl6040-vibra.txt | 37 ---------------- drivers/input/misc/twl6040-vibra.c | 42 +++++++++++-------- 2 files changed, 24 insertions(+), 55 deletions(-) delete mode 100644 Documentation/devicetree/bindings/input/twl6040-vibra.txt diff --git a/Documentation/devicetree/bindings/input/twl6040-vibra.txt b/Documentation/devicetree/bindings/input/twl6040-vibra.txt deleted file mode 100644 index 5b1918b818fb..000000000000 --- a/Documentation/devicetree/bindings/input/twl6040-vibra.txt +++ /dev/null @@ -1,37 +0,0 @@ -Vibra driver for the twl6040 family - -The vibra driver is a child of the twl6040 MFD dirver. -Documentation/devicetree/bindings/mfd/twl6040.txt - -Required properties: -- compatible : Must be "ti,twl6040-vibra"; -- interrupts: 4, Vibra overcurrent interrupt -- vddvibl-supply: Regulator supplying the left vibra motor -- vddvibr-supply: Regulator supplying the right vibra motor -- vibldrv_res: Board specific left driver resistance -- vibrdrv_res: Board specific right driver resistance -- viblmotor_res: Board specific left motor resistance -- vibrmotor_res: Board specific right motor resistance - -Optional properties: -- vddvibl_uV: If the vddvibl default voltage need to be changed -- vddvibr_uV: If the vddvibr default voltage need to be changed - -Example: -/* - * 8-channel high quality low-power audio codec - * http://www.ti.com/lit/ds/symlink/twl6040.pdf - */ -twl6040: twl6040@4b { - ... - twl6040_vibra: twl6040@1 { - compatible = "ti,twl6040-vibra"; - interrupts = <4>; - vddvibl-supply = <&vbat>; - vddvibr-supply = <&vbat>; - vibldrv_res = <8>; - vibrdrv_res = <3>; - viblmotor_res = <10>; - vibrmotor_res = <10>; - }; -}; diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index c34f6c0371c4..c8a288ae1d5b 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -251,7 +251,6 @@ static int twl6040_vibra_suspend(struct device *dev) return 0; } - #endif static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); @@ -259,13 +258,19 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); static int __devinit twl6040_vibra_probe(struct platform_device *pdev) { struct twl6040_vibra_data *pdata = pdev->dev.platform_data; - struct device_node *node = pdev->dev.of_node; + struct device *twl6040_core_dev = pdev->dev.parent; + struct device_node *twl6040_core_node = NULL; struct vibra_info *info; int vddvibl_uV = 0; int vddvibr_uV = 0; int ret; - if (!pdata && !node) { +#ifdef CONFIG_OF + twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node, + "vibra"); +#endif + + if (!pdata && !twl6040_core_node) { dev_err(&pdev->dev, "platform_data not available\n"); return -EINVAL; } @@ -287,14 +292,18 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) vddvibl_uV = pdata->vddvibl_uV; vddvibr_uV = pdata->vddvibr_uV; } else { - of_property_read_u32(node, "vibldrv_res", &info->vibldrv_res); - of_property_read_u32(node, "vibrdrv_res", &info->vibrdrv_res); - of_property_read_u32(node, "viblmotor_res", + of_property_read_u32(twl6040_core_node, "ti,vibldrv-res", + &info->vibldrv_res); + of_property_read_u32(twl6040_core_node, "ti,vibrdrv-res", + &info->vibrdrv_res); + of_property_read_u32(twl6040_core_node, "ti,viblmotor-res", &info->viblmotor_res); - of_property_read_u32(node, "vibrmotor_res", + of_property_read_u32(twl6040_core_node, "ti,vibrmotor-res", &info->vibrmotor_res); - of_property_read_u32(node, "vddvibl_uV", &vddvibl_uV); - of_property_read_u32(node, "vddvibr_uV", &vddvibr_uV); + of_property_read_u32(twl6040_core_node, "ti,vddvibl-uV", + &vddvibl_uV); + of_property_read_u32(twl6040_core_node, "ti,vddvibr-uV", + &vddvibr_uV); } if ((!info->vibldrv_res && !info->viblmotor_res) || @@ -351,8 +360,12 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) info->supplies[0].supply = "vddvibl"; info->supplies[1].supply = "vddvibr"; - ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies), - info->supplies); + /* + * When booted with Device tree the regulators are attached to the + * parent device (twl6040 MFD core) + */ + ret = regulator_bulk_get(pdata ? info->dev : twl6040_core_dev, + ARRAY_SIZE(info->supplies), info->supplies); if (ret) { dev_err(info->dev, "couldn't get regulators %d\n", ret); goto err_regulator; @@ -418,12 +431,6 @@ static int __devexit twl6040_vibra_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id twl6040_vibra_of_match[] = { - {.compatible = "ti,twl6040-vibra", }, - { }, -}; -MODULE_DEVICE_TABLE(of, twl6040_vibra_of_match); - static struct platform_driver twl6040_vibra_driver = { .probe = twl6040_vibra_probe, .remove = __devexit_p(twl6040_vibra_remove), @@ -431,7 +438,6 @@ static struct platform_driver twl6040_vibra_driver = { .name = "twl6040-vibra", .owner = THIS_MODULE, .pm = &twl6040_vibra_pm_ops, - .of_match_table = twl6040_vibra_of_match, }, }; module_platform_driver(twl6040_vibra_driver); -- GitLab From 65df57743924c3d13e1fa1bcf5bf70fe874fcdfd Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 24 May 2012 11:13:42 +0200 Subject: [PATCH 0503/5711] crypto: sha1 - use Kbuild supplied flags for AVX test Commit ea4d26ae ("raid5: add AVX optimized RAID5 checksumming") introduced x86/ arch wide defines for AFLAGS and CFLAGS indicating AVX support in binutils based on the same test we have in x86/crypto/ right now. To minimize duplication drop our implementation in favour to the one in x86/. Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 7 ------- arch/x86/crypto/sha1_ssse3_asm.S | 2 +- arch/x86/crypto/sha1_ssse3_glue.c | 6 +++--- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index e191ac048b59..479f95a744f7 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -34,12 +34,5 @@ salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o - ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o - -# enable AVX support only when $(AS) can actually assemble the instructions -ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes) -AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT -CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT -endif sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S index b2c2f57d70e8..49d6987a73d9 100644 --- a/arch/x86/crypto/sha1_ssse3_asm.S +++ b/arch/x86/crypto/sha1_ssse3_asm.S @@ -468,7 +468,7 @@ W_PRECALC_SSSE3 */ SHA1_VECTOR_ASM sha1_transform_ssse3 -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX .macro W_PRECALC_AVX diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c index f916499d0abe..4a11a9d72451 100644 --- a/arch/x86/crypto/sha1_ssse3_glue.c +++ b/arch/x86/crypto/sha1_ssse3_glue.c @@ -35,7 +35,7 @@ asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data, unsigned int rounds); -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX asmlinkage void sha1_transform_avx(u32 *digest, const char *data, unsigned int rounds); #endif @@ -184,7 +184,7 @@ static struct shash_alg alg = { } }; -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX static bool __init avx_usable(void) { u64 xcr0; @@ -209,7 +209,7 @@ static int __init sha1_ssse3_mod_init(void) if (cpu_has_ssse3) sha1_transform_asm = sha1_transform_ssse3; -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX /* allow AVX to override SSSE3, it's a little faster */ if (avx_usable()) sha1_transform_asm = sha1_transform_avx; -- GitLab From a482b081a2d4d74d16bc9ea8779f9f6055f95852 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 25 May 2012 17:54:13 +0800 Subject: [PATCH 0504/5711] crypto: testmgr - Add new test cases for Blackfin CRC crypto driver Signed-off-by: Sonic Zhang Acked-by: Mike Frysinger Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 3 ++ crypto/testmgr.c | 9 +++++ crypto/testmgr.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 8f147bff0980..750cce44bad6 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1192,6 +1192,9 @@ static int do_test(int m) case 109: ret += tcrypt_test("vmac(aes)"); break; + case 110: + ret += tcrypt_test("hmac(crc32)"); + break; case 150: ret += tcrypt_test("ansi_cprng"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5674878ff6c1..eb6d20f8ec5d 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2219,6 +2219,15 @@ static const struct alg_test_desc alg_test_descs[] = { .count = GHASH_TEST_VECTORS } } + }, { + .alg = "hmac(crc32)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = bfin_crc_tv_template, + .count = BFIN_CRC_TEST_VECTORS + } + } }, { .alg = "hmac(md5)", .test = alg_test_hash, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 36e5a8ee0e1e..34a9d511deef 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -14858,4 +14858,94 @@ static struct hash_testvec crc32c_tv_template[] = { }, }; +/* + * Blakcifn CRC test vectors + */ +#define BFIN_CRC_TEST_VECTORS 6 + +static struct hash_testvec bfin_crc_tv_template[] = { + { + .psize = 0, + .digest = "\x00\x00\x00\x00", + }, + { + .key = "\x87\xa9\xcb\xed", + .ksize = 4, + .psize = 0, + .digest = "\x87\xa9\xcb\xed", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27\x28", + .psize = 40, + .digest = "\x84\x0c\x8d\xa2", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26", + .psize = 38, + .digest = "\x8c\x58\xec\xb7", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27", + .psize = 39, + .digest = "\xdc\x50\x28\x7b", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27\x28" + "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" + "\x31\x32\x33\x34\x35\x36\x37\x38" + "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" + "\x41\x42\x43\x44\x45\x46\x47\x48" + "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" + "\x51\x52\x53\x54\x55\x56\x57\x58" + "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" + "\x61\x62\x63\x64\x65\x66\x67\x68" + "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" + "\x71\x72\x73\x74\x75\x76\x77\x78" + "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" + "\x81\x82\x83\x84\x85\x86\x87\x88" + "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98" + "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" + "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" + "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" + "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" + "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8" + "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" + "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" + "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" + "\xe9\xea\xeb\xec\xed\xee\xef\xf0", + .psize = 240, + .digest = "\x10\x19\x4a\x5c", + .np = 2, + .tap = { 31, 209 } + }, + +}; + #endif /* _CRYPTO_TESTMGR_H */ -- GitLab From b8840098b70c11d70c29263e0765f103e6cbe55e Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 4 Jun 2012 12:24:47 +0800 Subject: [PATCH 0505/5711] crypto: bfin_crc - CRC hardware driver for BF60x family processors. The CRC peripheral is a hardware block used to compute the CRC of the block of data. This is based on a CRC32 engine which computes the CRC value of 32b data words presented to it. For data words of < 32b in size, this driver pack 0 automatically into 32b data units. This driver implements the async hash crypto framework API. Signed-off-by: Sonic Zhang Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 7 + drivers/crypto/Makefile | 3 +- drivers/crypto/bfin_crc.c | 780 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 789 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/bfin_crc.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 1092a770482e..dd4d5af6c31f 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -325,4 +325,11 @@ if CRYPTO_DEV_UX500 source "drivers/crypto/ux500/Kconfig" endif # if CRYPTO_DEV_UX500 +config CRYPTO_DEV_BFIN_CRC + tristate "Support for Blackfin CRC hardware" + depends on BF60x + help + Newer Blackfin processors have CRC hardware. Select this if you + want to use the Blackfin CRC module. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 01390325d72d..d5062bb7a1f2 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o -obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ \ No newline at end of file +obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ +obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c new file mode 100644 index 000000000000..5398580b4313 --- /dev/null +++ b/drivers/crypto/bfin_crc.c @@ -0,0 +1,780 @@ +/* + * Cryptographic API. + * + * Support Blackfin CRC HW acceleration. + * + * Copyright 2012 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 +#include +#include +#include + +#include +#include +#include +#include + +#define CRC_CCRYPTO_QUEUE_LENGTH 5 + +#define DRIVER_NAME "bfin-hmac-crc" +#define CHKSUM_DIGEST_SIZE 4 +#define CHKSUM_BLOCK_SIZE 1 + +#define CRC_MAX_DMA_DESC 100 + +#define CRC_CRYPTO_STATE_UPDATE 1 +#define CRC_CRYPTO_STATE_FINALUPDATE 2 +#define CRC_CRYPTO_STATE_FINISH 3 + +struct bfin_crypto_crc { + struct list_head list; + struct device *dev; + spinlock_t lock; + + int irq; + int dma_ch; + u32 poly; + volatile struct crc_register *regs; + + struct ahash_request *req; /* current request in operation */ + struct dma_desc_array *sg_cpu; /* virt addr of sg dma descriptors */ + dma_addr_t sg_dma; /* phy addr of sg dma descriptors */ + u8 *sg_mid_buf; + + struct tasklet_struct done_task; + struct crypto_queue queue; /* waiting requests */ + + u8 busy:1; /* crc device in operation flag */ +}; + +static struct bfin_crypto_crc_list { + struct list_head dev_list; + spinlock_t lock; +} crc_list; + +struct bfin_crypto_crc_reqctx { + struct bfin_crypto_crc *crc; + + unsigned int total; /* total request bytes */ + size_t sg_buflen; /* bytes for this update */ + unsigned int sg_nents; + struct scatterlist *sg; /* sg list head for this update*/ + struct scatterlist bufsl[2]; /* chained sg list */ + + size_t bufnext_len; + size_t buflast_len; + u8 bufnext[CHKSUM_DIGEST_SIZE]; /* extra bytes for next udpate */ + u8 buflast[CHKSUM_DIGEST_SIZE]; /* extra bytes from last udpate */ + + u8 flag; +}; + +struct bfin_crypto_crc_ctx { + struct bfin_crypto_crc *crc; + u32 key; +}; + + +/* + * derive number of elements in scatterlist + */ +static int sg_count(struct scatterlist *sg_list) +{ + struct scatterlist *sg = sg_list; + int sg_nents = 1; + + if (sg_list == NULL) + return 0; + + while (!sg_is_last(sg)) { + sg_nents++; + sg = scatterwalk_sg_next(sg); + } + + return sg_nents; +} + +/* + * get element in scatter list by given index + */ +static struct scatterlist *sg_get(struct scatterlist *sg_list, unsigned int nents, + unsigned int index) +{ + struct scatterlist *sg = NULL; + int i; + + for_each_sg(sg_list, sg, nents, i) + if (i == index) + break; + + return sg; +} + +static int bfin_crypto_crc_init_hw(struct bfin_crypto_crc *crc, u32 key) +{ + crc->regs->datacntrld = 0; + crc->regs->control = MODE_CALC_CRC << OPMODE_OFFSET; + crc->regs->curresult = key; + + /* setup CRC interrupts */ + crc->regs->status = CMPERRI | DCNTEXPI; + crc->regs->intrenset = CMPERRI | DCNTEXPI; + SSYNC(); + + return 0; +} + +static int bfin_crypto_crc_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm); + struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req); + struct bfin_crypto_crc *crc; + + dev_dbg(crc->dev, "crc_init\n"); + spin_lock_bh(&crc_list.lock); + list_for_each_entry(crc, &crc_list.dev_list, list) { + crc_ctx->crc = crc; + break; + } + spin_unlock_bh(&crc_list.lock); + + if (sg_count(req->src) > CRC_MAX_DMA_DESC) { + dev_dbg(crc->dev, "init: requested sg list is too big > %d\n", + CRC_MAX_DMA_DESC); + return -EINVAL; + } + + ctx->crc = crc; + ctx->bufnext_len = 0; + ctx->buflast_len = 0; + ctx->sg_buflen = 0; + ctx->total = 0; + ctx->flag = 0; + + /* init crc results */ + put_unaligned_le32(crc_ctx->key, req->result); + + dev_dbg(crc->dev, "init: digest size: %d\n", + crypto_ahash_digestsize(tfm)); + + return bfin_crypto_crc_init_hw(crc, crc_ctx->key); +} + +static void bfin_crypto_crc_config_dma(struct bfin_crypto_crc *crc) +{ + struct scatterlist *sg; + struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(crc->req); + int i = 0, j = 0; + unsigned long dma_config; + unsigned int dma_count; + unsigned int dma_addr; + unsigned int mid_dma_count = 0; + int dma_mod; + + dma_map_sg(crc->dev, ctx->sg, ctx->sg_nents, DMA_TO_DEVICE); + + for_each_sg(ctx->sg, sg, ctx->sg_nents, j) { + dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32; + dma_addr = sg_dma_address(sg); + /* deduce extra bytes in last sg */ + if (sg_is_last(sg)) + dma_count = sg_dma_len(sg) - ctx->bufnext_len; + else + dma_count = sg_dma_len(sg); + + if (mid_dma_count) { + /* Append last middle dma buffer to 4 bytes with first + bytes in current sg buffer. Move addr of current + sg and deduce the length of current sg. + */ + memcpy(crc->sg_mid_buf +((i-1) << 2) + mid_dma_count, + (void *)dma_addr, + CHKSUM_DIGEST_SIZE - mid_dma_count); + dma_addr += CHKSUM_DIGEST_SIZE - mid_dma_count; + dma_count -= CHKSUM_DIGEST_SIZE - mid_dma_count; + } + /* chop current sg dma len to multiple of 32 bits */ + mid_dma_count = dma_count % 4; + dma_count &= ~0x3; + + if (dma_addr % 4 == 0) { + dma_config |= WDSIZE_32; + dma_count >>= 2; + dma_mod = 4; + } else if (dma_addr % 2 == 0) { + dma_config |= WDSIZE_16; + dma_count >>= 1; + dma_mod = 2; + } else { + dma_config |= WDSIZE_8; + dma_mod = 1; + } + + crc->sg_cpu[i].start_addr = dma_addr; + crc->sg_cpu[i].cfg = dma_config; + crc->sg_cpu[i].x_count = dma_count; + crc->sg_cpu[i].x_modify = dma_mod; + dev_dbg(crc->dev, "%d: crc_dma: start_addr:0x%lx, " + "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", + i, crc->sg_cpu[i].start_addr, + crc->sg_cpu[i].cfg, crc->sg_cpu[i].x_count, + crc->sg_cpu[i].x_modify); + i++; + + if (mid_dma_count) { + /* copy extra bytes to next middle dma buffer */ + dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | + DMAEN | PSIZE_32 | WDSIZE_32; + memcpy(crc->sg_mid_buf + (i << 2), + (void *)(dma_addr + (dma_count << 2)), + mid_dma_count); + /* setup new dma descriptor for next middle dma */ + crc->sg_cpu[i].start_addr = dma_map_single(crc->dev, + crc->sg_mid_buf + (i << 2), + CHKSUM_DIGEST_SIZE, DMA_TO_DEVICE); + crc->sg_cpu[i].cfg = dma_config; + crc->sg_cpu[i].x_count = 1; + crc->sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE; + dev_dbg(crc->dev, "%d: crc_dma: start_addr:0x%lx, " + "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", + i, crc->sg_cpu[i].start_addr, + crc->sg_cpu[i].cfg, crc->sg_cpu[i].x_count, + crc->sg_cpu[i].x_modify); + i++; + } + } + + dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32 | WDSIZE_32; + /* For final update req, append the buffer for next update as well*/ + if (ctx->bufnext_len && (ctx->flag == CRC_CRYPTO_STATE_FINALUPDATE || + ctx->flag == CRC_CRYPTO_STATE_FINISH)) { + crc->sg_cpu[i].start_addr = dma_map_single(crc->dev, ctx->bufnext, + CHKSUM_DIGEST_SIZE, DMA_TO_DEVICE); + crc->sg_cpu[i].cfg = dma_config; + crc->sg_cpu[i].x_count = 1; + crc->sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE; + dev_dbg(crc->dev, "%d: crc_dma: start_addr:0x%lx, " + "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", + i, crc->sg_cpu[i].start_addr, + crc->sg_cpu[i].cfg, crc->sg_cpu[i].x_count, + crc->sg_cpu[i].x_modify); + i++; + } + + if (i == 0) + return; + + flush_dcache_range((unsigned int)crc->sg_cpu, + (unsigned int)crc->sg_cpu + + i * sizeof(struct dma_desc_array)); + + /* Set the last descriptor to stop mode */ + crc->sg_cpu[i - 1].cfg &= ~(DMAFLOW | NDSIZE); + crc->sg_cpu[i - 1].cfg |= DI_EN; + set_dma_curr_desc_addr(crc->dma_ch, (unsigned long *)crc->sg_dma); + set_dma_x_count(crc->dma_ch, 0); + set_dma_x_modify(crc->dma_ch, 0); + SSYNC(); + set_dma_config(crc->dma_ch, dma_config); +} + +static int bfin_crypto_crc_handle_queue(struct bfin_crypto_crc *crc, + struct ahash_request *req) +{ + struct crypto_async_request *async_req, *backlog; + struct bfin_crypto_crc_reqctx *ctx; + struct scatterlist *sg; + int ret = 0; + int nsg, i, j; + unsigned int nextlen; + unsigned long flags; + + spin_lock_irqsave(&crc->lock, flags); + if (req) + ret = ahash_enqueue_request(&crc->queue, req); + if (crc->busy) { + spin_unlock_irqrestore(&crc->lock, flags); + return ret; + } + backlog = crypto_get_backlog(&crc->queue); + async_req = crypto_dequeue_request(&crc->queue); + if (async_req) + crc->busy = 1; + spin_unlock_irqrestore(&crc->lock, flags); + + if (!async_req) + return ret; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + req = ahash_request_cast(async_req); + crc->req = req; + ctx = ahash_request_ctx(req); + ctx->sg = NULL; + ctx->sg_buflen = 0; + ctx->sg_nents = 0; + + dev_dbg(crc->dev, "handling new req, flag=%u, nbytes: %d\n", + ctx->flag, req->nbytes); + + if (ctx->flag == CRC_CRYPTO_STATE_FINISH) { + if (ctx->bufnext_len == 0) { + crc->busy = 0; + return 0; + } + + /* Pack last crc update buffer to 32bit */ + memset(ctx->bufnext + ctx->bufnext_len, 0, + CHKSUM_DIGEST_SIZE - ctx->bufnext_len); + } else { + /* Pack small data which is less than 32bit to buffer for next update. */ + if (ctx->bufnext_len + req->nbytes < CHKSUM_DIGEST_SIZE) { + memcpy(ctx->bufnext + ctx->bufnext_len, + sg_virt(req->src), req->nbytes); + ctx->bufnext_len += req->nbytes; + if (ctx->flag == CRC_CRYPTO_STATE_FINALUPDATE && + ctx->bufnext_len) { + goto finish_update; + } else { + crc->busy = 0; + return 0; + } + } + + if (ctx->bufnext_len) { + /* Chain in extra bytes of last update */ + ctx->buflast_len = ctx->bufnext_len; + memcpy(ctx->buflast, ctx->bufnext, ctx->buflast_len); + + nsg = ctx->sg_buflen ? 2 : 1; + sg_init_table(ctx->bufsl, nsg); + sg_set_buf(ctx->bufsl, ctx->buflast, ctx->buflast_len); + if (nsg > 1) + scatterwalk_sg_chain(ctx->bufsl, nsg, + req->src); + ctx->sg = ctx->bufsl; + } else + ctx->sg = req->src; + + /* Chop crc buffer size to multiple of 32 bit */ + nsg = ctx->sg_nents = sg_count(ctx->sg); + ctx->sg_buflen = ctx->buflast_len + req->nbytes; + ctx->bufnext_len = ctx->sg_buflen % 4; + ctx->sg_buflen &= ~0x3; + + if (ctx->bufnext_len) { + /* copy extra bytes to buffer for next update */ + memset(ctx->bufnext, 0, CHKSUM_DIGEST_SIZE); + nextlen = ctx->bufnext_len; + for (i = nsg - 1; i >= 0; i--) { + sg = sg_get(ctx->sg, nsg, i); + j = min(nextlen, sg_dma_len(sg)); + memcpy(ctx->bufnext + nextlen - j, + sg_virt(sg) + sg_dma_len(sg) - j, j); + if (j == sg_dma_len(sg)) + ctx->sg_nents--; + nextlen -= j; + if (nextlen == 0) + break; + } + } + } + +finish_update: + if (ctx->bufnext_len && (ctx->flag == CRC_CRYPTO_STATE_FINALUPDATE || + ctx->flag == CRC_CRYPTO_STATE_FINISH)) + ctx->sg_buflen += CHKSUM_DIGEST_SIZE; + + /* set CRC data count before start DMA */ + crc->regs->datacnt = ctx->sg_buflen >> 2; + + /* setup and enable CRC DMA */ + bfin_crypto_crc_config_dma(crc); + + /* finally kick off CRC operation */ + crc->regs->control |= BLKEN; + SSYNC(); + + return -EINPROGRESS; +} + +static int bfin_crypto_crc_update(struct ahash_request *req) +{ + struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req); + + if (!req->nbytes) + return 0; + + dev_dbg(ctx->crc->dev, "crc_update\n"); + ctx->total += req->nbytes; + ctx->flag = CRC_CRYPTO_STATE_UPDATE; + + return bfin_crypto_crc_handle_queue(ctx->crc, req); +} + +static int bfin_crypto_crc_final(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm); + struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req); + + dev_dbg(ctx->crc->dev, "crc_final\n"); + ctx->flag = CRC_CRYPTO_STATE_FINISH; + crc_ctx->key = 0; + + return bfin_crypto_crc_handle_queue(ctx->crc, req); +} + +static int bfin_crypto_crc_finup(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm); + struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req); + + dev_dbg(ctx->crc->dev, "crc_finishupdate\n"); + ctx->total += req->nbytes; + ctx->flag = CRC_CRYPTO_STATE_FINALUPDATE; + crc_ctx->key = 0; + + return bfin_crypto_crc_handle_queue(ctx->crc, req); +} + +static int bfin_crypto_crc_digest(struct ahash_request *req) +{ + int ret; + + ret = bfin_crypto_crc_init(req); + if (ret) + return ret; + + return bfin_crypto_crc_finup(req); +} + +static int bfin_crypto_crc_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) +{ + struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm); + + dev_dbg(crc_ctx->crc->dev, "crc_setkey\n"); + if (keylen != CHKSUM_DIGEST_SIZE) { + crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + crc_ctx->key = get_unaligned_le32(key); + + return 0; +} + +static int bfin_crypto_crc_cra_init(struct crypto_tfm *tfm) +{ + struct bfin_crypto_crc_ctx *crc_ctx = crypto_tfm_ctx(tfm); + + crc_ctx->key = 0; + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct bfin_crypto_crc_reqctx)); + + return 0; +} + +static void bfin_crypto_crc_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct ahash_alg algs = { + .init = bfin_crypto_crc_init, + .update = bfin_crypto_crc_update, + .final = bfin_crypto_crc_final, + .finup = bfin_crypto_crc_finup, + .digest = bfin_crypto_crc_digest, + .setkey = bfin_crypto_crc_setkey, + .halg.digestsize = CHKSUM_DIGEST_SIZE, + .halg.base = { + .cra_name = "hmac(crc32)", + .cra_driver_name = DRIVER_NAME, + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct bfin_crypto_crc_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + .cra_init = bfin_crypto_crc_cra_init, + .cra_exit = bfin_crypto_crc_cra_exit, + } +}; + +static void bfin_crypto_crc_done_task(unsigned long data) +{ + struct bfin_crypto_crc *crc = (struct bfin_crypto_crc *)data; + + bfin_crypto_crc_handle_queue(crc, NULL); +} + +static irqreturn_t bfin_crypto_crc_handler(int irq, void *dev_id) +{ + struct bfin_crypto_crc *crc = dev_id; + + if (crc->regs->status & DCNTEXP) { + crc->regs->status = DCNTEXP; + SSYNC(); + + /* prepare results */ + put_unaligned_le32(crc->regs->result, crc->req->result); + + crc->regs->control &= ~BLKEN; + crc->busy = 0; + + if (crc->req->base.complete) + crc->req->base.complete(&crc->req->base, 0); + + tasklet_schedule(&crc->done_task); + + return IRQ_HANDLED; + } else + return IRQ_NONE; +} + +#ifdef CONFIG_PM +/** + * bfin_crypto_crc_suspend - suspend crc device + * @pdev: device being suspended + * @state: requested suspend state + */ +static int bfin_crypto_crc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct bfin_crypto_crc *crc = platform_get_drvdata(pdev); + int i = 100000; + + while ((crc->regs->control & BLKEN) && --i) + cpu_relax(); + + if (i == 0) + return -EBUSY; + + return 0; +} +#else +# define bfin_crypto_crc_suspend NULL +#endif + +#define bfin_crypto_crc_resume NULL + +/** + * bfin_crypto_crc_probe - Initialize module + * + */ +static int __devinit bfin_crypto_crc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct bfin_crypto_crc *crc; + unsigned int timeout = 100000; + int ret; + + crc = kzalloc(sizeof(*crc), GFP_KERNEL); + if (!crc) { + dev_err(&pdev->dev, "fail to malloc bfin_crypto_crc\n"); + return -ENOMEM; + } + + crc->dev = dev; + + INIT_LIST_HEAD(&crc->list); + spin_lock_init(&crc->lock); + tasklet_init(&crc->done_task, bfin_crypto_crc_done_task, (unsigned long)crc); + crypto_init_queue(&crc->queue, CRC_CCRYPTO_QUEUE_LENGTH); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); + ret = -ENOENT; + goto out_error_free_mem; + } + + crc->regs = ioremap(res->start, resource_size(res)); + if (!crc->regs) { + dev_err(&pdev->dev, "Cannot map CRC IO\n"); + ret = -ENXIO; + goto out_error_free_mem; + } + + crc->irq = platform_get_irq(pdev, 0); + if (crc->irq < 0) { + dev_err(&pdev->dev, "No CRC DCNTEXP IRQ specified\n"); + ret = -ENOENT; + goto out_error_unmap; + } + + ret = request_irq(crc->irq, bfin_crypto_crc_handler, IRQF_SHARED, dev_name(dev), crc); + if (ret) { + dev_err(&pdev->dev, "Unable to request blackfin crc irq\n"); + goto out_error_unmap; + } + + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (res == NULL) { + dev_err(&pdev->dev, "No CRC DMA channel specified\n"); + ret = -ENOENT; + goto out_error_irq; + } + crc->dma_ch = res->start; + + ret = request_dma(crc->dma_ch, dev_name(dev)); + if (ret) { + dev_err(&pdev->dev, "Unable to attach Blackfin CRC DMA channel\n"); + goto out_error_irq; + } + + crc->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &crc->sg_dma, GFP_KERNEL); + if (crc->sg_cpu == NULL) { + ret = -ENOMEM; + goto out_error_dma; + } + /* + * need at most CRC_MAX_DMA_DESC sg + CRC_MAX_DMA_DESC middle + + * 1 last + 1 next dma descriptors + */ + crc->sg_mid_buf = (u8 *)(crc->sg_cpu + ((CRC_MAX_DMA_DESC + 1) << 1)); + + crc->regs->control = 0; + SSYNC(); + crc->regs->poly = crc->poly = (u32)pdev->dev.platform_data; + SSYNC(); + + while (!(crc->regs->status & LUTDONE) && (--timeout) > 0) + cpu_relax(); + + if (timeout == 0) + dev_info(&pdev->dev, "init crc poly timeout\n"); + + spin_lock(&crc_list.lock); + list_add(&crc->list, &crc_list.dev_list); + spin_unlock(&crc_list.lock); + + platform_set_drvdata(pdev, crc); + + ret = crypto_register_ahash(&algs); + if (ret) { + spin_lock(&crc_list.lock); + list_del(&crc->list); + spin_unlock(&crc_list.lock); + dev_err(&pdev->dev, "Cann't register crypto ahash device\n"); + goto out_error_dma; + } + + dev_info(&pdev->dev, "initialized\n"); + + return 0; + +out_error_dma: + if (crc->sg_cpu) + dma_free_coherent(&pdev->dev, PAGE_SIZE, crc->sg_cpu, crc->sg_dma); + free_dma(crc->dma_ch); +out_error_irq: + free_irq(crc->irq, crc->dev); +out_error_unmap: + iounmap((void *)crc->regs); +out_error_free_mem: + kfree(crc); + + return ret; +} + +/** + * bfin_crypto_crc_remove - Initialize module + * + */ +static int __devexit bfin_crypto_crc_remove(struct platform_device *pdev) +{ + struct bfin_crypto_crc *crc = platform_get_drvdata(pdev); + + if (!crc) + return -ENODEV; + + spin_lock(&crc_list.lock); + list_del(&crc->list); + spin_unlock(&crc_list.lock); + + crypto_unregister_ahash(&algs); + tasklet_kill(&crc->done_task); + iounmap((void *)crc->regs); + free_dma(crc->dma_ch); + if (crc->irq > 0) + free_irq(crc->irq, crc->dev); + kfree(crc); + + return 0; +} + +static struct platform_driver bfin_crypto_crc_driver = { + .probe = bfin_crypto_crc_probe, + .remove = __devexit_p(bfin_crypto_crc_remove), + .suspend = bfin_crypto_crc_suspend, + .resume = bfin_crypto_crc_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +/** + * bfin_crypto_crc_mod_init - Initialize module + * + * Checks the module params and registers the platform driver. + * Real work is in the platform probe function. + */ +static int __init bfin_crypto_crc_mod_init(void) +{ + int ret; + + pr_info("Blackfin hardware CRC crypto driver\n"); + + INIT_LIST_HEAD(&crc_list.dev_list); + spin_lock_init(&crc_list.lock); + + ret = platform_driver_register(&bfin_crypto_crc_driver); + if (ret) { + pr_info(KERN_ERR "unable to register driver\n"); + return ret; + } + + return 0; +} + +/** + * bfin_crypto_crc_mod_exit - Deinitialize module + */ +static void __exit bfin_crypto_crc_mod_exit(void) +{ + platform_driver_unregister(&bfin_crypto_crc_driver); +} + +module_init(bfin_crypto_crc_mod_init); +module_exit(bfin_crypto_crc_mod_exit); + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Blackfin CRC hardware crypto driver"); +MODULE_LICENSE("GPL"); -- GitLab From 170dd56dfc3b13e7dafd48e27f67fddb3f17ef2a Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 25 May 2012 15:54:46 +0200 Subject: [PATCH 0506/5711] crypto: mv_cesa - add an expiry timer in case anything goes wrong The timer triggers when 500ms have gone by after triggering the engine and no completion interrupt was received. The callback then tries to sanitise things as well as possible. Signed-off-by: Phil Sutter Signed-off-by: Herbert Xu --- drivers/crypto/mv_cesa.c | 41 ++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 1cc6b3f3e262..b0b2f02518f8 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -24,6 +24,7 @@ #define MV_CESA "MV-CESA:" #define MAX_HW_HASH_SIZE 0xFFFF +#define MV_CESA_EXPIRE 500 /* msec */ /* * STM: @@ -87,6 +88,7 @@ struct crypto_priv { spinlock_t lock; struct crypto_queue queue; enum engine_status eng_st; + struct timer_list completion_timer; struct crypto_async_request *cur_req; struct req_progress p; int max_req_size; @@ -138,6 +140,29 @@ struct mv_req_hash_ctx { int count_add; }; +static void mv_completion_timer_callback(unsigned long unused) +{ + int active = readl(cpg->reg + SEC_ACCEL_CMD) & SEC_CMD_EN_SEC_ACCL0; + + printk(KERN_ERR MV_CESA + "completion timer expired (CESA %sactive), cleaning up.\n", + active ? "" : "in"); + + del_timer(&cpg->completion_timer); + writel(SEC_CMD_DISABLE_SEC, cpg->reg + SEC_ACCEL_CMD); + while(readl(cpg->reg + SEC_ACCEL_CMD) & SEC_CMD_DISABLE_SEC) + printk(KERN_INFO MV_CESA "%s: waiting for engine finishing\n", __func__); + cpg->eng_st = ENGINE_W_DEQUEUE; + wake_up_process(cpg->queue_th); +} + +static void mv_setup_timer(void) +{ + setup_timer(&cpg->completion_timer, &mv_completion_timer_callback, 0); + mod_timer(&cpg->completion_timer, + jiffies + msecs_to_jiffies(MV_CESA_EXPIRE)); +} + static void compute_aes_dec_key(struct mv_ctx *ctx) { struct crypto_aes_ctx gen_aes_key; @@ -273,12 +298,8 @@ static void mv_process_current_q(int first_block) sizeof(struct sec_accel_config)); /* GO */ + mv_setup_timer(); writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD); - - /* - * XXX: add timer if the interrupt does not occur for some mystery - * reason - */ } static void mv_crypto_algo_completion(void) @@ -357,12 +378,8 @@ static void mv_process_hash_current(int first_block) memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config)); /* GO */ + mv_setup_timer(); writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD); - - /* - * XXX: add timer if the interrupt does not occur for some mystery - * reason - */ } static inline int mv_hash_import_sha1_ctx(const struct mv_req_hash_ctx *ctx, @@ -888,6 +905,10 @@ irqreturn_t crypto_int(int irq, void *priv) if (!(val & SEC_INT_ACCEL0_DONE)) return IRQ_NONE; + if (!del_timer(&cpg->completion_timer)) { + printk(KERN_WARNING MV_CESA + "got an interrupt but no pending timer?\n"); + } val &= ~SEC_INT_ACCEL0_DONE; writel(val, cpg->reg + FPGA_INT_STATUS); writel(val, cpg->reg + SEC_ACCEL_INT_STATUS); -- GitLab From 5741d2eeaee28b37a4711a1776f716b274f3d2e4 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 12 Jun 2012 16:41:21 +0800 Subject: [PATCH 0507/5711] crypto: mv_cesa - initialise the interrupt status field to zero Signed-off-by: Phil Sutter Signed-off-by: Herbert Xu --- drivers/crypto/mv_cesa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index b0b2f02518f8..904623d45c62 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -1082,6 +1082,7 @@ static int mv_probe(struct platform_device *pdev) if (!IS_ERR(cp->clk)) clk_prepare_enable(cp->clk); + writel(0, cpg->reg + SEC_ACCEL_INT_STATUS); writel(SEC_INT_ACCEL0_DONE, cpg->reg + SEC_ACCEL_INT_MASK); writel(SEC_CFG_STOP_DIG_ERR, cpg->reg + SEC_ACCEL_CFG); writel(SRAM_CONFIG, cpg->reg + SEC_ACCEL_DESC_P0); -- GitLab From 4d03c5047a07a62563e1a8fa798ea258f048bfde Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 25 May 2012 15:54:49 +0200 Subject: [PATCH 0508/5711] crypto: mv_cesa - fix for hash finalisation with data Since mv_hash_final_fallback() uses ctx->state, read out the digest state register before calling it. Signed-off-by: Phil Sutter Signed-off-by: Herbert Xu --- drivers/crypto/mv_cesa.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 904623d45c62..0d4071754352 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -423,6 +423,15 @@ out: return rc; } +static void mv_save_digest_state(struct mv_req_hash_ctx *ctx) +{ + ctx->state[0] = readl(cpg->reg + DIGEST_INITIAL_VAL_A); + ctx->state[1] = readl(cpg->reg + DIGEST_INITIAL_VAL_B); + ctx->state[2] = readl(cpg->reg + DIGEST_INITIAL_VAL_C); + ctx->state[3] = readl(cpg->reg + DIGEST_INITIAL_VAL_D); + ctx->state[4] = readl(cpg->reg + DIGEST_INITIAL_VAL_E); +} + static void mv_hash_algo_completion(void) { struct ahash_request *req = ahash_request_cast(cpg->cur_req); @@ -437,14 +446,12 @@ static void mv_hash_algo_completion(void) memcpy(req->result, cpg->sram + SRAM_DIGEST_BUF, crypto_ahash_digestsize(crypto_ahash_reqtfm (req))); - } else + } else { + mv_save_digest_state(ctx); mv_hash_final_fallback(req); + } } else { - ctx->state[0] = readl(cpg->reg + DIGEST_INITIAL_VAL_A); - ctx->state[1] = readl(cpg->reg + DIGEST_INITIAL_VAL_B); - ctx->state[2] = readl(cpg->reg + DIGEST_INITIAL_VAL_C); - ctx->state[3] = readl(cpg->reg + DIGEST_INITIAL_VAL_D); - ctx->state[4] = readl(cpg->reg + DIGEST_INITIAL_VAL_E); + mv_save_digest_state(ctx); } } -- GitLab From 107778b592576c0c8e8d2ca7a2aa5415a4908223 Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Mon, 28 May 2012 15:54:24 +0200 Subject: [PATCH 0509/5711] crypto: twofish - add x86_64/avx assembler implementation This patch adds a x86_64/avx assembler implementation of the Twofish block cipher. The implementation processes eight blocks in parallel (two 4 block chunk AVX operations). The table-lookups are done in general-purpose registers. For small blocksizes the 3way-parallel functions from the twofish-x86_64-3way module are called. A good performance increase is provided for blocksizes greater or equal to 128B. Patch has been tested with tcrypt and automated filesystem tests. Tcrypt benchmark results: Intel Core i5-2500 CPU (fam:6, model:42, step:7) twofish-avx-x86_64 vs. twofish-x86_64-3way 128bit key: (lrw:256bit) (xts:256bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 0.96x 0.97x 1.00x 0.95x 0.97x 0.97x 0.96x 0.95x 0.95x 0.98x 64B 0.99x 0.99x 1.00x 0.99x 0.98x 0.98x 0.99x 0.98x 0.99x 0.98x 256B 1.20x 1.21x 1.00x 1.19x 1.15x 1.14x 1.19x 1.20x 1.18x 1.19x 1024B 1.29x 1.30x 1.00x 1.28x 1.23x 1.24x 1.26x 1.28x 1.26x 1.27x 8192B 1.31x 1.32x 1.00x 1.31x 1.25x 1.25x 1.28x 1.29x 1.28x 1.30x 256bit key: (lrw:384bit) (xts:512bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 0.96x 0.96x 1.00x 0.96x 0.97x 0.98x 0.95x 0.95x 0.95x 0.96x 64B 1.00x 0.99x 1.00x 0.98x 0.98x 1.01x 0.98x 0.98x 0.98x 0.98x 256B 1.20x 1.21x 1.00x 1.21x 1.15x 1.15x 1.19x 1.20x 1.18x 1.19x 1024B 1.29x 1.30x 1.00x 1.28x 1.23x 1.23x 1.26x 1.27x 1.26x 1.27x 8192B 1.31x 1.33x 1.00x 1.31x 1.26x 1.26x 1.29x 1.29x 1.28x 1.30x twofish-avx-x86_64 vs aes-asm (8kB block): 128bit 256bit ecb-enc 1.19x 1.63x ecb-dec 1.18x 1.62x cbc-enc 0.75x 1.03x cbc-dec 1.23x 1.67x ctr-enc 1.24x 1.65x ctr-dec 1.24x 1.65x lrw-enc 1.15x 1.53x lrw-dec 1.14x 1.52x xts-enc 1.16x 1.56x xts-dec 1.16x 1.56x Signed-off-by: Johannes Goetzfried Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 301 +++++ arch/x86/crypto/twofish_avx_glue.c | 1086 +++++++++++++++++++ arch/x86/crypto/twofish_glue_3way.c | 2 + crypto/Kconfig | 24 + crypto/tcrypt.c | 23 + crypto/testmgr.c | 60 + 7 files changed, 1498 insertions(+) create mode 100644 arch/x86/crypto/twofish-avx-x86_64-asm_64.S create mode 100644 arch/x86/crypto/twofish_avx_glue.c diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 479f95a744f7..3420feef0c70 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o +obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o @@ -30,6 +31,7 @@ camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o +twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o twofish_avx_glue.o salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S new file mode 100644 index 000000000000..fc31b89ba4c3 --- /dev/null +++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S @@ -0,0 +1,301 @@ +/* + * Twofish Cipher 8-way parallel algorithm (AVX/x86_64) + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +.file "twofish-avx-x86_64-asm_64.S" +.text + +/* structure of crypto context */ +#define s0 0 +#define s1 1024 +#define s2 2048 +#define s3 3072 +#define w 4096 +#define k 4128 + +/********************************************************************** + 8-way AVX twofish + **********************************************************************/ +#define CTX %rdi + +#define RA1 %xmm0 +#define RB1 %xmm1 +#define RC1 %xmm2 +#define RD1 %xmm3 + +#define RA2 %xmm4 +#define RB2 %xmm5 +#define RC2 %xmm6 +#define RD2 %xmm7 + +#define RX %xmm8 +#define RY %xmm9 + +#define RK1 %xmm10 +#define RK2 %xmm11 + +#define RID1 %rax +#define RID1b %al +#define RID2 %rbx +#define RID2b %bl + +#define RGI1 %rdx +#define RGI1bl %dl +#define RGI1bh %dh +#define RGI2 %rcx +#define RGI2bl %cl +#define RGI2bh %ch + +#define RGS1 %r8 +#define RGS1d %r8d +#define RGS2 %r9 +#define RGS2d %r9d +#define RGS3 %r10 +#define RGS3d %r10d + + +#define lookup_32bit(t0, t1, t2, t3, src, dst) \ + movb src ## bl, RID1b; \ + movb src ## bh, RID2b; \ + movl t0(CTX, RID1, 4), dst ## d; \ + xorl t1(CTX, RID2, 4), dst ## d; \ + shrq $16, src; \ + movb src ## bl, RID1b; \ + movb src ## bh, RID2b; \ + xorl t2(CTX, RID1, 4), dst ## d; \ + xorl t3(CTX, RID2, 4), dst ## d; + +#define G(a, x, t0, t1, t2, t3) \ + vmovq a, RGI1; \ + vpsrldq $8, a, x; \ + vmovq x, RGI2; \ + \ + lookup_32bit(t0, t1, t2, t3, RGI1, RGS1); \ + shrq $16, RGI1; \ + lookup_32bit(t0, t1, t2, t3, RGI1, RGS2); \ + shlq $32, RGS2; \ + orq RGS1, RGS2; \ + \ + lookup_32bit(t0, t1, t2, t3, RGI2, RGS1); \ + shrq $16, RGI2; \ + lookup_32bit(t0, t1, t2, t3, RGI2, RGS3); \ + shlq $32, RGS3; \ + orq RGS1, RGS3; \ + \ + vmovq RGS2, x; \ + vpinsrq $1, RGS3, x, x; + +#define encround(a, b, c, d, x, y) \ + G(a, x, s0, s1, s2, s3); \ + G(b, y, s1, s2, s3, s0); \ + vpaddd x, y, x; \ + vpaddd y, x, y; \ + vpaddd x, RK1, x; \ + vpaddd y, RK2, y; \ + vpxor x, c, c; \ + vpsrld $1, c, x; \ + vpslld $(32 - 1), c, c; \ + vpor c, x, c; \ + vpslld $1, d, x; \ + vpsrld $(32 - 1), d, d; \ + vpor d, x, d; \ + vpxor d, y, d; + +#define decround(a, b, c, d, x, y) \ + G(a, x, s0, s1, s2, s3); \ + G(b, y, s1, s2, s3, s0); \ + vpaddd x, y, x; \ + vpaddd y, x, y; \ + vpaddd y, RK2, y; \ + vpxor d, y, d; \ + vpsrld $1, d, y; \ + vpslld $(32 - 1), d, d; \ + vpor d, y, d; \ + vpslld $1, c, y; \ + vpsrld $(32 - 1), c, c; \ + vpor c, y, c; \ + vpaddd x, RK1, x; \ + vpxor x, c, c; + +#define encrypt_round(n, a, b, c, d) \ + vbroadcastss (k+4*(2*(n)))(CTX), RK1; \ + vbroadcastss (k+4*(2*(n)+1))(CTX), RK2; \ + encround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \ + encround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY); + +#define decrypt_round(n, a, b, c, d) \ + vbroadcastss (k+4*(2*(n)))(CTX), RK1; \ + vbroadcastss (k+4*(2*(n)+1))(CTX), RK2; \ + decround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \ + decround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY); + +#define encrypt_cycle(n) \ + encrypt_round((2*n), RA, RB, RC, RD); \ + encrypt_round(((2*n) + 1), RC, RD, RA, RB); + +#define decrypt_cycle(n) \ + decrypt_round(((2*n) + 1), RC, RD, RA, RB); \ + decrypt_round((2*n), RA, RB, RC, RD); + + +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + vpunpckldq x1, x0, t0; \ + vpunpckhdq x1, x0, t2; \ + vpunpckldq x3, x2, t1; \ + vpunpckhdq x3, x2, x3; \ + \ + vpunpcklqdq t1, t0, x0; \ + vpunpckhqdq t1, t0, x1; \ + vpunpcklqdq x3, t2, x2; \ + vpunpckhqdq x3, t2, x3; + +#define inpack_blocks(in, x0, x1, x2, x3, wkey, t0, t1, t2) \ + vpxor (0*4*4)(in), wkey, x0; \ + vpxor (1*4*4)(in), wkey, x1; \ + vpxor (2*4*4)(in), wkey, x2; \ + vpxor (3*4*4)(in), wkey, x3; \ + \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) + +#define outunpack_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor x0, wkey, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor x1, wkey, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor x2, wkey, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor x3, wkey, x3; \ + vmovdqu x3, (3*4*4)(out); + +#define outunpack_xor_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor x0, wkey, x0; \ + vpxor (0*4*4)(out), x0, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor x1, wkey, x1; \ + vpxor (1*4*4)(out), x1, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor x2, wkey, x2; \ + vpxor (2*4*4)(out), x2, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor x3, wkey, x3; \ + vpxor (3*4*4)(out), x3, x3; \ + vmovdqu x3, (3*4*4)(out); + +.align 8 +.global __twofish_enc_blk_8way +.type __twofish_enc_blk_8way,@function; + +__twofish_enc_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + * %rcx: bool, if true: xor output + */ + + pushq %rbx; + pushq %rcx; + + vmovdqu w(CTX), RK1; + + leaq (4*4*4)(%rdx), %rax; + inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2); + inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2); + + xorq RID1, RID1; + xorq RID2, RID2; + + encrypt_cycle(0); + encrypt_cycle(1); + encrypt_cycle(2); + encrypt_cycle(3); + encrypt_cycle(4); + encrypt_cycle(5); + encrypt_cycle(6); + encrypt_cycle(7); + + vmovdqu (w+4*4)(CTX), RK1; + + popq %rcx; + popq %rbx; + + leaq (4*4*4)(%rsi), %rax; + leaq (4*4*4)(%rax), %rdx; + + testb %cl, %cl; + jnz __enc_xor8; + + outunpack_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + ret; + +__enc_xor8: + outunpack_xor_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + ret; + +.align 8 +.global twofish_dec_blk_8way +.type twofish_dec_blk_8way,@function; + +twofish_dec_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + */ + + pushq %rbx; + + vmovdqu (w+4*4)(CTX), RK1; + + leaq (4*4*4)(%rdx), %rax; + inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + xorq RID1, RID1; + xorq RID2, RID2; + + decrypt_cycle(7); + decrypt_cycle(6); + decrypt_cycle(5); + decrypt_cycle(4); + decrypt_cycle(3); + decrypt_cycle(2); + decrypt_cycle(1); + decrypt_cycle(0); + + vmovdqu (w)(CTX), RK1; + + popq %rbx; + + leaq (4*4*4)(%rsi), %rax; + outunpack_blocks(%rsi, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2); + outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2); + + ret; diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c new file mode 100644 index 000000000000..599f19e4bef6 --- /dev/null +++ b/arch/x86/crypto/twofish_avx_glue.c @@ -0,0 +1,1086 @@ +/* + * Glue Code for AVX assembler version of Twofish Cipher + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Glue code based on serpent_sse2_glue.c by: + * Copyright (C) 2011 Jussi Kivilinna + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define TWOFISH_PARALLEL_BLOCKS 8 + +/* regular block cipher functions from twofish_x86_64 module */ +asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); +asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +/* 3-way parallel cipher functions from twofish_x86_64-3way module */ +asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_3way(ctx, dst, src, false); +} + +static inline void twofish_enc_blk_3way_xor(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_3way(ctx, dst, src, true); +} + +/* 8-way parallel cipher functions */ +asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void twofish_dec_blk_8way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void twofish_enc_blk_xway(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_8way(ctx, dst, src, false); +} + +static inline void twofish_enc_blk_xway_xor(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_8way(ctx, dst, src, true); +} + +static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + twofish_dec_blk_8way(ctx, dst, src); +} + + + +struct async_twofish_ctx { + struct cryptd_ablkcipher *cryptd_tfm; +}; + +static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) +{ + if (fpu_enabled) + return true; + + /* AVX is only used when chunk to be processed is large enough, so + * do not enable FPU until it is necessary. + */ + if (nbytes < TF_BLOCK_SIZE * TWOFISH_PARALLEL_BLOCKS) + return false; + + kernel_fpu_begin(); + return true; +} + +static inline void twofish_fpu_end(bool fpu_enabled) +{ + if (fpu_enabled) + kernel_fpu_end(); +} + +static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, + bool enc) +{ + bool fpu_enabled = false; + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes; + int err; + + err = blkcipher_walk_virt(desc, walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk->nbytes)) { + u8 *wsrc = walk->src.virt.addr; + u8 *wdst = walk->dst.virt.addr; + + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + if (enc) + twofish_enc_blk_xway(ctx, wdst, wsrc); + else + twofish_dec_blk_xway(ctx, wdst, wsrc); + + wsrc += bsize * TWOFISH_PARALLEL_BLOCKS; + wdst += bsize * TWOFISH_PARALLEL_BLOCKS; + nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + if (enc) + twofish_enc_blk_3way(ctx, wdst, wsrc); + else + twofish_dec_blk_3way(ctx, wdst, wsrc); + + wsrc += bsize * 3; + wdst += bsize * 3; + nbytes -= bsize * 3; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (enc) + twofish_enc_blk(ctx, wdst, wsrc); + else + twofish_dec_blk(ctx, wdst, wsrc); + + wsrc += bsize; + wdst += bsize; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + err = blkcipher_walk_done(desc, walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + return err; +} + +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, true); +} + +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, false); +} + +static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 *iv = (u128 *)walk->iv; + + do { + u128_xor(dst, src, iv); + twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); + iv = dst; + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + + u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); + return nbytes; +} + +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + nbytes = __cbc_encrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1]; + u128 last_iv; + int i; + + /* Start of the last block. */ + src += nbytes / bsize - 1; + dst += nbytes / bsize - 1; + + last_iv = *src; + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + nbytes -= bsize * (TWOFISH_PARALLEL_BLOCKS - 1); + src -= TWOFISH_PARALLEL_BLOCKS - 1; + dst -= TWOFISH_PARALLEL_BLOCKS - 1; + + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) + ivs[i] = src[i]; + + twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) + u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + nbytes -= bsize * (3 - 1); + src -= 3 - 1; + dst -= 3 - 1; + + ivs[0] = src[0]; + ivs[1] = src[1]; + + twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); + + u128_xor(dst + 1, dst + 1, ivs + 0); + u128_xor(dst + 2, dst + 2, ivs + 1); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + for (;;) { + twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src); + + nbytes -= bsize; + if (nbytes < bsize) + break; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } + +done: + u128_xor(dst, dst, (u128 *)walk->iv); + *(u128 *)walk->iv = last_iv; + + return nbytes; +} + +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes)) { + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + nbytes = __cbc_decrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + return err; +} + +static inline void u128_to_be128(be128 *dst, const u128 *src) +{ + dst->a = cpu_to_be64(src->a); + dst->b = cpu_to_be64(src->b); +} + +static inline void be128_to_u128(u128 *dst, const be128 *src) +{ + dst->a = be64_to_cpu(src->a); + dst->b = be64_to_cpu(src->b); +} + +static inline void u128_inc(u128 *i) +{ + i->b++; + if (!i->b) + i->a++; +} + +static void ctr_crypt_final(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *ctrblk = walk->iv; + u8 keystream[TF_BLOCK_SIZE]; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + unsigned int nbytes = walk->nbytes; + + twofish_enc_blk(ctx, keystream, ctrblk); + crypto_xor(keystream, src, nbytes); + memcpy(dst, keystream, nbytes); + + crypto_inc(ctrblk, TF_BLOCK_SIZE); +} + +static unsigned int __ctr_crypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ctrblk; + be128 ctrblocks[TWOFISH_PARALLEL_BLOCKS]; + int i; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + /* create ctrblks for parallel encrypt */ + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; + + u128_to_be128(&ctrblocks[i], &ctrblk); + u128_inc(&ctrblk); + } + + twofish_enc_blk_xway_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += TWOFISH_PARALLEL_BLOCKS; + dst += TWOFISH_PARALLEL_BLOCKS; + nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + if (dst != src) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + } + + /* create ctrblks for parallel encrypt */ + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + u128_to_be128(&ctrblocks[1], &ctrblk); + u128_inc(&ctrblk); + u128_to_be128(&ctrblocks[2], &ctrblk); + u128_inc(&ctrblk); + + twofish_enc_blk_3way_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += 3; + dst += 3; + nbytes -= bsize * 3; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (dst != src) + *dst = *src; + + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + + twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); + u128_xor(dst, dst, (u128 *)ctrblocks); + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + u128_to_be128((be128 *)walk->iv, &ctrblk); + return nbytes; +} + +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) { + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + nbytes = __ctr_crypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + + if (walk.nbytes) { + ctr_crypt_final(desc, &walk); + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} + +struct crypt_priv { + struct twofish_ctx *ctx; + bool fpu_enabled; +}; + +static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = TF_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) { + twofish_enc_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / (bsize * 3); i++, srcdst += bsize * 3) + twofish_enc_blk_3way(ctx->ctx, srcdst, srcdst); + + nbytes %= bsize * 3; + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + twofish_enc_blk(ctx->ctx, srcdst, srcdst); +} + +static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = TF_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) { + twofish_dec_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / (bsize * 3); i++, srcdst += bsize * 3) + twofish_dec_blk_3way(ctx->ctx, srcdst, srcdst); + + nbytes %= bsize * 3; + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + twofish_dec_blk(ctx->ctx, srcdst, srcdst); +} + +struct twofish_lrw_ctx { + struct lrw_table_ctx lrw_table; + struct twofish_ctx twofish_ctx; +}; + +static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + int err; + + err = __twofish_setkey(&ctx->twofish_ctx, key, + keylen - TF_BLOCK_SIZE, &tfm->crt_flags); + if (err) + return err; + + return lrw_init_table(&ctx->lrw_table, key + keylen - + TF_BLOCK_SIZE); +} + +static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->twofish_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->twofish_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static void lrw_exit_tfm(struct crypto_tfm *tfm) +{ + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + + lrw_free_table(&ctx->lrw_table); +} + +struct twofish_xts_ctx { + struct twofish_ctx tweak_ctx; + struct twofish_ctx crypt_ctx; +}; + +static int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct twofish_xts_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + int err; + + /* key consists of keys of equal size concatenated, therefore + * the length must be even + */ + if (keylen % 2) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* first half of xts-key is for crypt */ + err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags); + if (err) + return err; + + /* second half of xts-key is for tweak */ + return __twofish_setkey(&ctx->tweak_ctx, + key + keylen / 2, keylen / 2, flags); +} + +static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk), + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk), + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(child, key, key_len); + crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) + & CRYPTO_TFM_RES_MASK); + return err; +} + +static int __ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->encrypt( + &desc, req->dst, req->src, req->nbytes); +} + +static int ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_encrypt(cryptd_req); + } else { + return __ablk_encrypt(req); + } +} + +static int ablk_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_decrypt(cryptd_req); + } else { + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->decrypt( + &desc, req->dst, req->src, req->nbytes); + } +} + +static void ablk_exit(struct crypto_tfm *tfm) +{ + struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ablkcipher(ctx->cryptd_tfm); +} + +static int ablk_init(struct crypto_tfm *tfm) +{ + struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_ablkcipher *cryptd_tfm; + char drv_name[CRYPTO_MAX_ALG_NAME]; + + snprintf(drv_name, sizeof(drv_name), "__driver-%s", + crypto_tfm_alg_driver_name(tfm)); + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + + ctx->cryptd_tfm = cryptd_tfm; + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(&cryptd_tfm->base); + + return 0; +} + +static struct crypto_alg twofish_algs[10] = { { + .cra_name = "__ecb-twofish-avx", + .cra_driver_name = "__driver-ecb-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[0].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = twofish_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, + }, + }, +}, { + .cra_name = "__cbc-twofish-avx", + .cra_driver_name = "__driver-cbc-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[1].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = twofish_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, + }, + }, +}, { + .cra_name = "__ctr-twofish-avx", + .cra_driver_name = "__driver-ctr-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[2].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = twofish_setkey, + .encrypt = ctr_crypt, + .decrypt = ctr_crypt, + }, + }, +}, { + .cra_name = "__lrw-twofish-avx", + .cra_driver_name = "__driver-lrw-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_lrw_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[3].cra_list), + .cra_exit = lrw_exit_tfm, + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE + + TF_BLOCK_SIZE, + .max_keysize = TF_MAX_KEY_SIZE + + TF_BLOCK_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = lrw_twofish_setkey, + .encrypt = lrw_encrypt, + .decrypt = lrw_decrypt, + }, + }, +}, { + .cra_name = "__xts-twofish-avx", + .cra_driver_name = "__driver-xts-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_xts_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[4].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE * 2, + .max_keysize = TF_MAX_KEY_SIZE * 2, + .ivsize = TF_BLOCK_SIZE, + .setkey = xts_twofish_setkey, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, + }, + }, +}, { + .cra_name = "ecb(twofish)", + .cra_driver_name = "ecb-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[5].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "cbc(twofish)", + .cra_driver_name = "cbc-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[6].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = __ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "ctr(twofish)", + .cra_driver_name = "ctr-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[7].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_encrypt, + .geniv = "chainiv", + }, + }, +}, { + .cra_name = "lrw(twofish)", + .cra_driver_name = "lrw-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[8].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE + + TF_BLOCK_SIZE, + .max_keysize = TF_MAX_KEY_SIZE + + TF_BLOCK_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "xts(twofish)", + .cra_driver_name = "xts-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[9].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE * 2, + .max_keysize = TF_MAX_KEY_SIZE * 2, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +} }; + +static int __init twofish_init(void) +{ + u64 xcr0; + + if (!cpu_has_avx || !cpu_has_osxsave) { + printk(KERN_INFO "AVX instructions are not detected.\n"); + return -ENODEV; + } + + xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { + printk(KERN_INFO "AVX detected but unusable.\n"); + return -ENODEV; + } + + return crypto_register_algs(twofish_algs, ARRAY_SIZE(twofish_algs)); +} + +static void __exit twofish_exit(void) +{ + crypto_unregister_algs(twofish_algs, ARRAY_SIZE(twofish_algs)); +} + +module_init(twofish_init); +module_exit(twofish_exit); + +MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("twofish"); diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 922ab24cce31..77e4e55a2660 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -45,8 +45,10 @@ asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, /* 3-way parallel cipher functions */ asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src, bool xor); +EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way); asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src); +EXPORT_SYMBOL_GPL(twofish_dec_blk_3way); static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src) diff --git a/crypto/Kconfig b/crypto/Kconfig index 8e84225c096b..e00a4e49e013 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -913,6 +913,30 @@ config CRYPTO_TWOFISH_X86_64_3WAY See also: +config CRYPTO_TWOFISH_AVX_X86_64 + tristate "Twofish cipher algorithm (x86_64/AVX)" + depends on X86 && 64BIT + select CRYPTO_ALGAPI + select CRYPTO_CRYPTD + select CRYPTO_TWOFISH_COMMON + select CRYPTO_TWOFISH_X86_64 + select CRYPTO_TWOFISH_X86_64_3WAY + select CRYPTO_LRW + select CRYPTO_XTS + help + Twofish cipher algorithm (x86_64/AVX). + + Twofish was submitted as an AES (Advanced Encryption Standard) + candidate cipher by researchers at CounterPane Systems. It is a + 16 round block cipher supporting key sizes of 128, 192, and 256 + bits. + + This module provides the Twofish cipher algorithm that processes + eight blocks parallel using the AVX Instruction Set. + + See also: + + comment "Compression" config CRYPTO_DEFLATE diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 750cce44bad6..2af879786e75 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1566,6 +1566,29 @@ static int do_test(int m) speed_template_32_64); break; + case 504: + test_acipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("lrw(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_32_40_48); + test_acipher_speed("lrw(twofish)", DECRYPT, sec, NULL, 0, + speed_template_32_40_48); + test_acipher_speed("xts(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_32_48_64); + test_acipher_speed("xts(twofish)", DECRYPT, sec, NULL, 0, + speed_template_32_48_64); + break; + case 1000: test_available(); break; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index eb6d20f8ec5d..73b3ec6fe1a2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1548,6 +1548,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__cbc-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-cbc-aes-aesni", .test = alg_test_null, @@ -1578,6 +1593,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-cbc-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-ecb-aes-aesni", .test = alg_test_null, @@ -1608,6 +1638,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-ecb-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__ghash-pclmulqdqni", .test = alg_test_null, @@ -1805,6 +1850,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "cryptd(__driver-ecb-twofish-avx)", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__ghash-pclmulqdqni)", .test = alg_test_null, -- GitLab From 4da7de4d8be7d18559c56bca446b1161a3b63acc Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Mon, 28 May 2012 15:55:38 +0200 Subject: [PATCH 0510/5711] crypto: testmgr - expand twofish test vectors The AVX implementation of the twofish cipher processes 8 blocks parallel, so we need to make test vectors larger to check parallel code paths. Test vectors are also large enough to deal with 16 block parallel implementations which may occur in the future. Signed-off-by: Johannes Goetzfried Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- crypto/testmgr.h | 928 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 896 insertions(+), 32 deletions(-) diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 34a9d511deef..4d84fe48df08 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -2765,8 +2765,62 @@ static struct cipher_testvec tf_enc_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .ilen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .ilen = 496, .result = "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF" "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC" "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D" @@ -2774,8 +2828,62 @@ static struct cipher_testvec tf_enc_tv_template[] = { "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5" "\xDF\xFA\xC7\xE8\x09\x50\x76\x08" "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05" - "\x89\xF6\x82\xF0\xD3\xDB\x06\x02", - .rlen = 64, + "\x89\xF6\x82\xF0\xD3\xDB\x06\x02" + "\xB5\x11\x5C\x5E\x79\x1A\xAC\x43" + "\x5C\xC0\x30\x4B\x6B\x16\xA1\x40" + "\x80\x27\x88\xBA\x2C\x74\x42\xE0" + "\x1B\xA5\x85\x08\xB9\xE6\x22\x7A" + "\x36\x3B\x0D\x9F\xA0\x22\x6C\x2A" + "\x91\x75\x47\xBC\x67\x21\x4E\xF9" + "\xEA\xFF\xD9\xD5\xC0\xFC\x9E\x2C" + "\x3E\xAD\xC6\x61\x0E\x93\x7A\x22" + "\x09\xC8\x8D\xC1\x8E\xB4\x8B\x5C" + "\xC6\x24\x42\xB8\x23\x66\x80\xA9" + "\x32\x0B\x7A\x29\xBF\xB3\x0B\x63" + "\x43\x27\x13\xA9\xBE\xEB\xBD\xF3" + "\x33\x62\x70\xE2\x1B\x86\x7A\xA1" + "\x51\x4A\x16\xFE\x29\x63\x7E\xD0" + "\x7A\xA4\x6E\x2C\xF8\xC1\xDB\xE8" + "\xCB\x4D\xD2\x8C\x04\x14\xB4\x66" + "\x41\xB7\x3A\x96\x16\x7C\x1D\x5B" + "\xB6\x41\x42\x64\x43\xEE\x6E\x7C" + "\x8B\xAF\x01\x9C\xA4\x6E\x75\x8F" + "\xDE\x10\x9F\xA6\xE7\xD6\x44\x97" + "\x66\xA3\x96\x0F\x1C\x25\x60\xF5" + "\x3C\x2E\x32\x69\x0E\x82\xFF\x27" + "\x0F\xB5\x06\xDA\xD8\x31\x15\x6C" + "\xDF\x18\x6C\x87\xF5\x3B\x11\x9A" + "\x1B\x42\x1F\x5B\x29\x19\x96\x13" + "\x68\x2E\x5E\x08\x1C\x8F\x32\x4B" + "\x81\x77\x6D\xF4\xA0\x01\x42\xEC" + "\xDD\x5B\xFD\x3A\x8E\x6A\x14\xFB" + "\x83\x54\xDF\x0F\x86\xB7\xEA\x40" + "\x46\x39\xF7\x2A\x89\x8D\x4E\x96" + "\x5F\x5F\x6D\x76\xC6\x13\x9D\x3D" + "\x1D\x5F\x0C\x7D\xE2\xBC\xC2\x16" + "\x16\xBE\x89\x3E\xB0\x61\xA2\x5D" + "\xAF\xD1\x40\x5F\x1A\xB8\x26\x41" + "\xC6\xBD\x36\xEF\xED\x29\x50\x6D" + "\x10\xEF\x26\xE8\xA8\x93\x11\x3F" + "\x2D\x1F\x88\x20\x77\x45\xF5\x66" + "\x08\xB9\xF1\xEF\xB1\x93\xA8\x81" + "\x65\xC5\xCD\x3E\x8C\x06\x60\x2C" + "\xB2\x10\x7A\xCA\x05\x25\x59\xDB" + "\xC7\x28\xF5\x20\x35\x52\x9E\x62" + "\xF8\x88\x24\x1C\x4D\x84\x12\x39" + "\x39\xE4\x2E\xF4\xD4\x9D\x2B\xBC" + "\x87\x66\xE6\xC0\x6B\x31\x9A\x66" + "\x03\xDC\x95\xD8\x6B\xD0\x30\x8F" + "\xDF\x8F\x8D\xFA\xEC\x1F\x08\xBD" + "\xA3\x63\xE2\x71\x4F\x03\x94\x87" + "\x50\xDF\x15\x1F\xED\x3A\xA3\x7F" + "\x1F\x2A\xB5\xA1\x69\xAC\x4B\x0D" + "\x84\x9B\x2A\xE9\x55\xDD\x46\x91" + "\x15\x33\xF3\x2B\x9B\x46\x97\x00" + "\xF0\x29\xD8\x59\x5D\x33\x37\xF9" + "\x58\x33\x9B\x78\xC7\x58\x48\x6B" + "\x2C\x75\x64\xC4\xCA\xC1\x7E\xD5", + .rlen = 496, }, }; @@ -2822,8 +2930,62 @@ static struct cipher_testvec tf_dec_tv_template[] = { "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5" "\xDF\xFA\xC7\xE8\x09\x50\x76\x08" "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05" - "\x89\xF6\x82\xF0\xD3\xDB\x06\x02", - .ilen = 64, + "\x89\xF6\x82\xF0\xD3\xDB\x06\x02" + "\xB5\x11\x5C\x5E\x79\x1A\xAC\x43" + "\x5C\xC0\x30\x4B\x6B\x16\xA1\x40" + "\x80\x27\x88\xBA\x2C\x74\x42\xE0" + "\x1B\xA5\x85\x08\xB9\xE6\x22\x7A" + "\x36\x3B\x0D\x9F\xA0\x22\x6C\x2A" + "\x91\x75\x47\xBC\x67\x21\x4E\xF9" + "\xEA\xFF\xD9\xD5\xC0\xFC\x9E\x2C" + "\x3E\xAD\xC6\x61\x0E\x93\x7A\x22" + "\x09\xC8\x8D\xC1\x8E\xB4\x8B\x5C" + "\xC6\x24\x42\xB8\x23\x66\x80\xA9" + "\x32\x0B\x7A\x29\xBF\xB3\x0B\x63" + "\x43\x27\x13\xA9\xBE\xEB\xBD\xF3" + "\x33\x62\x70\xE2\x1B\x86\x7A\xA1" + "\x51\x4A\x16\xFE\x29\x63\x7E\xD0" + "\x7A\xA4\x6E\x2C\xF8\xC1\xDB\xE8" + "\xCB\x4D\xD2\x8C\x04\x14\xB4\x66" + "\x41\xB7\x3A\x96\x16\x7C\x1D\x5B" + "\xB6\x41\x42\x64\x43\xEE\x6E\x7C" + "\x8B\xAF\x01\x9C\xA4\x6E\x75\x8F" + "\xDE\x10\x9F\xA6\xE7\xD6\x44\x97" + "\x66\xA3\x96\x0F\x1C\x25\x60\xF5" + "\x3C\x2E\x32\x69\x0E\x82\xFF\x27" + "\x0F\xB5\x06\xDA\xD8\x31\x15\x6C" + "\xDF\x18\x6C\x87\xF5\x3B\x11\x9A" + "\x1B\x42\x1F\x5B\x29\x19\x96\x13" + "\x68\x2E\x5E\x08\x1C\x8F\x32\x4B" + "\x81\x77\x6D\xF4\xA0\x01\x42\xEC" + "\xDD\x5B\xFD\x3A\x8E\x6A\x14\xFB" + "\x83\x54\xDF\x0F\x86\xB7\xEA\x40" + "\x46\x39\xF7\x2A\x89\x8D\x4E\x96" + "\x5F\x5F\x6D\x76\xC6\x13\x9D\x3D" + "\x1D\x5F\x0C\x7D\xE2\xBC\xC2\x16" + "\x16\xBE\x89\x3E\xB0\x61\xA2\x5D" + "\xAF\xD1\x40\x5F\x1A\xB8\x26\x41" + "\xC6\xBD\x36\xEF\xED\x29\x50\x6D" + "\x10\xEF\x26\xE8\xA8\x93\x11\x3F" + "\x2D\x1F\x88\x20\x77\x45\xF5\x66" + "\x08\xB9\xF1\xEF\xB1\x93\xA8\x81" + "\x65\xC5\xCD\x3E\x8C\x06\x60\x2C" + "\xB2\x10\x7A\xCA\x05\x25\x59\xDB" + "\xC7\x28\xF5\x20\x35\x52\x9E\x62" + "\xF8\x88\x24\x1C\x4D\x84\x12\x39" + "\x39\xE4\x2E\xF4\xD4\x9D\x2B\xBC" + "\x87\x66\xE6\xC0\x6B\x31\x9A\x66" + "\x03\xDC\x95\xD8\x6B\xD0\x30\x8F" + "\xDF\x8F\x8D\xFA\xEC\x1F\x08\xBD" + "\xA3\x63\xE2\x71\x4F\x03\x94\x87" + "\x50\xDF\x15\x1F\xED\x3A\xA3\x7F" + "\x1F\x2A\xB5\xA1\x69\xAC\x4B\x0D" + "\x84\x9B\x2A\xE9\x55\xDD\x46\x91" + "\x15\x33\xF3\x2B\x9B\x46\x97\x00" + "\xF0\x29\xD8\x59\x5D\x33\x37\xF9" + "\x58\x33\x9B\x78\xC7\x58\x48\x6B" + "\x2C\x75\x64\xC4\xCA\xC1\x7E\xD5", + .ilen = 496, .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31" "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3" "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15" @@ -2831,8 +2993,62 @@ static struct cipher_testvec tf_dec_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .rlen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .rlen = 496, }, }; @@ -2894,8 +3110,62 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .ilen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .ilen = 496, .result = "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1" "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5" "\x26\x1B\x05\x0C\x05\x12\x3F\xC0" @@ -2903,8 +3173,62 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = { "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE" "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC" "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3" - "\xB1\xD3\x44\x65\xDF\xE7\x63\x38", - .rlen = 64, + "\xB1\xD3\x44\x65\xDF\xE7\x63\x38" + "\x4A\xFC\xDC\xEC\x3F\x26\x8E\xB8" + "\x43\xFC\xFE\x18\xB5\x11\x6D\x31" + "\x81\x8B\x0D\x75\xF6\x80\xEC\x84" + "\x04\xB9\xE6\x09\x63\xED\x39\xDB" + "\xC3\xF6\x14\xD6\x6E\x5E\x8B\xBD" + "\x3E\xFA\xD7\x98\x50\x6F\xD9\x63" + "\x02\xCD\x0D\x39\x4B\x0D\xEC\x80" + "\xE3\x6A\x17\xF4\xCC\xAD\xFF\x68" + "\x45\xDD\xC8\x83\x1D\x41\x96\x0D" + "\x91\x2E\x05\xD3\x59\x82\xE0\x43" + "\x90\x4F\xB9\xF7\xAD\x6B\x2E\xAF" + "\xA7\x84\x00\x53\xCD\x6F\xD1\x0C" + "\x4E\xF9\x5A\x23\xFB\xCA\xC7\xD3" + "\xA9\xAA\x9D\xB2\x3F\x66\xF1\xAC" + "\x25\x21\x8F\xF7\xEF\xF2\x6A\xDF" + "\xE8\xDA\x75\x1A\x8A\xF1\xDD\x38" + "\x1F\xF9\x3D\x68\x4A\xBB\x9E\x34" + "\x1F\x66\x1F\x9C\x2B\x54\xFF\x60" + "\x7F\x29\x4B\x55\x80\x8F\x4E\xA7" + "\xA6\x9A\x0A\xD9\x0D\x19\x00\xF8" + "\x1F\xBC\x0C\x40\x6B\xEC\x99\x25" + "\x94\x70\x74\x0E\x1D\xC5\xBC\x12" + "\xF3\x42\xBE\x95\xBF\xFB\x4E\x55" + "\x9A\xB9\xCE\x14\x16\x5B\xDC\xD3" + "\x75\x42\x62\x04\x31\x1F\x95\x7C" + "\x66\x1A\x97\xDC\x2F\x40\x5C\x39" + "\x78\xE6\x02\xDB\x49\xE1\xC6\x47" + "\xC2\x78\x9A\xBB\xF3\xBE\xCB\x93" + "\xD8\xB8\xE8\xBB\x8C\xB3\x9B\xA7" + "\xC2\x89\xF3\x91\x88\x83\x3D\xF0" + "\x29\xA2\xCD\xB5\x79\x16\xC2\x40" + "\x11\x03\x8E\x9C\xFD\xC9\x43\xC4" + "\xC2\x19\xF0\x4A\x32\xEF\x0C\x2B" + "\xD3\x2B\xE9\xD4\x4C\xDE\x95\xCF" + "\x04\x03\xD3\x2C\x7F\x82\xC8\xFA" + "\x0F\xD8\x7A\x39\x7B\x01\x41\x9C" + "\x78\xB6\xC9\xBF\xF9\x78\x57\x88" + "\xB1\xA5\xE1\xE0\xD9\x16\xD4\xC8" + "\xEE\xC4\xBE\x7B\x55\x59\x00\x48" + "\x1B\xBC\x14\xFA\x2A\x9D\xC9\x1C" + "\xFB\x28\x3F\x95\xDD\xB7\xD6\xCE" + "\x3A\x7F\x09\x0C\x0E\x69\x30\x7D" + "\xBC\x68\x9C\x91\x2A\x59\x57\x04" + "\xED\x1A\x1E\x00\xB1\x85\x92\x04" + "\x28\x8C\x0C\x3C\xC1\xD5\x12\xF7" + "\x4C\x3E\xB0\xE7\x86\x62\x68\x91" + "\xFC\xC4\xE2\xCE\xA6\xDC\x5E\x93" + "\x5D\x8D\x8C\x68\xB3\xB2\xB9\x64" + "\x16\xB8\xC8\x6F\xD8\xEE\x21\xBD" + "\xAC\x18\x0C\x7D\x0D\x05\xAB\xF1" + "\xFA\xDD\xE2\x48\xDF\x4C\x02\x39" + "\x69\xA1\x62\xBD\x49\x3A\x9D\x91" + "\x30\x70\x56\xA4\x37\xDD\x7C\xC0" + "\x0A\xA3\x30\x10\x26\x25\x41\x2C", + .rlen = 496, }, }; @@ -2966,8 +3290,62 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = { "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE" "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC" "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3" - "\xB1\xD3\x44\x65\xDF\xE7\x63\x38", - .ilen = 64, + "\xB1\xD3\x44\x65\xDF\xE7\x63\x38" + "\x4A\xFC\xDC\xEC\x3F\x26\x8E\xB8" + "\x43\xFC\xFE\x18\xB5\x11\x6D\x31" + "\x81\x8B\x0D\x75\xF6\x80\xEC\x84" + "\x04\xB9\xE6\x09\x63\xED\x39\xDB" + "\xC3\xF6\x14\xD6\x6E\x5E\x8B\xBD" + "\x3E\xFA\xD7\x98\x50\x6F\xD9\x63" + "\x02\xCD\x0D\x39\x4B\x0D\xEC\x80" + "\xE3\x6A\x17\xF4\xCC\xAD\xFF\x68" + "\x45\xDD\xC8\x83\x1D\x41\x96\x0D" + "\x91\x2E\x05\xD3\x59\x82\xE0\x43" + "\x90\x4F\xB9\xF7\xAD\x6B\x2E\xAF" + "\xA7\x84\x00\x53\xCD\x6F\xD1\x0C" + "\x4E\xF9\x5A\x23\xFB\xCA\xC7\xD3" + "\xA9\xAA\x9D\xB2\x3F\x66\xF1\xAC" + "\x25\x21\x8F\xF7\xEF\xF2\x6A\xDF" + "\xE8\xDA\x75\x1A\x8A\xF1\xDD\x38" + "\x1F\xF9\x3D\x68\x4A\xBB\x9E\x34" + "\x1F\x66\x1F\x9C\x2B\x54\xFF\x60" + "\x7F\x29\x4B\x55\x80\x8F\x4E\xA7" + "\xA6\x9A\x0A\xD9\x0D\x19\x00\xF8" + "\x1F\xBC\x0C\x40\x6B\xEC\x99\x25" + "\x94\x70\x74\x0E\x1D\xC5\xBC\x12" + "\xF3\x42\xBE\x95\xBF\xFB\x4E\x55" + "\x9A\xB9\xCE\x14\x16\x5B\xDC\xD3" + "\x75\x42\x62\x04\x31\x1F\x95\x7C" + "\x66\x1A\x97\xDC\x2F\x40\x5C\x39" + "\x78\xE6\x02\xDB\x49\xE1\xC6\x47" + "\xC2\x78\x9A\xBB\xF3\xBE\xCB\x93" + "\xD8\xB8\xE8\xBB\x8C\xB3\x9B\xA7" + "\xC2\x89\xF3\x91\x88\x83\x3D\xF0" + "\x29\xA2\xCD\xB5\x79\x16\xC2\x40" + "\x11\x03\x8E\x9C\xFD\xC9\x43\xC4" + "\xC2\x19\xF0\x4A\x32\xEF\x0C\x2B" + "\xD3\x2B\xE9\xD4\x4C\xDE\x95\xCF" + "\x04\x03\xD3\x2C\x7F\x82\xC8\xFA" + "\x0F\xD8\x7A\x39\x7B\x01\x41\x9C" + "\x78\xB6\xC9\xBF\xF9\x78\x57\x88" + "\xB1\xA5\xE1\xE0\xD9\x16\xD4\xC8" + "\xEE\xC4\xBE\x7B\x55\x59\x00\x48" + "\x1B\xBC\x14\xFA\x2A\x9D\xC9\x1C" + "\xFB\x28\x3F\x95\xDD\xB7\xD6\xCE" + "\x3A\x7F\x09\x0C\x0E\x69\x30\x7D" + "\xBC\x68\x9C\x91\x2A\x59\x57\x04" + "\xED\x1A\x1E\x00\xB1\x85\x92\x04" + "\x28\x8C\x0C\x3C\xC1\xD5\x12\xF7" + "\x4C\x3E\xB0\xE7\x86\x62\x68\x91" + "\xFC\xC4\xE2\xCE\xA6\xDC\x5E\x93" + "\x5D\x8D\x8C\x68\xB3\xB2\xB9\x64" + "\x16\xB8\xC8\x6F\xD8\xEE\x21\xBD" + "\xAC\x18\x0C\x7D\x0D\x05\xAB\xF1" + "\xFA\xDD\xE2\x48\xDF\x4C\x02\x39" + "\x69\xA1\x62\xBD\x49\x3A\x9D\x91" + "\x30\x70\x56\xA4\x37\xDD\x7C\xC0" + "\x0A\xA3\x30\x10\x26\x25\x41\x2C", + .ilen = 496, .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31" "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3" "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15" @@ -2975,8 +3353,62 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .rlen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .rlen = 496, }, }; @@ -2996,8 +3428,62 @@ static struct cipher_testvec tf_ctr_enc_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .ilen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .ilen = 496, .result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE" "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30" "\x26\x9B\x89\xA1\xEE\x43\xE0\x52" @@ -3005,8 +3491,62 @@ static struct cipher_testvec tf_ctr_enc_tv_template[] = { "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0" "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA" "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60" - "\x01\x41\x21\x12\x38\xAB\x52\x4F", - .rlen = 64, + "\x01\x41\x21\x12\x38\xAB\x52\x4F" + "\xA8\x57\x20\xE0\x21\x6A\x17\x0D" + "\x0E\xF9\x8E\x49\x42\x00\x3C\x94" + "\x14\xC0\xD0\x8D\x8A\x98\xEB\x29" + "\xEC\xAE\x96\x44\xC0\x3C\x48\xDC" + "\x29\x35\x25\x2F\xE7\x11\x6C\x68" + "\xC8\x67\x0A\x2F\xF4\x07\xBE\xF9" + "\x2C\x31\x87\x40\xAB\xB2\xB6\xFA" + "\xD2\xC9\x6D\x5C\x50\xE9\xE6\x7E" + "\xE3\x0A\xD2\xD5\x6D\x8D\x64\x9E" + "\x70\xCE\x03\x76\xDD\xE0\xF0\x8C" + "\x84\x86\x8B\x6A\xFE\xC7\xF9\x69" + "\x2E\xFE\xFC\xC2\xC4\x1A\x55\x58" + "\xB3\xBE\xE2\x7E\xED\x39\x42\x6C" + "\xB4\x42\x97\x9A\xEC\xE1\x0A\x06" + "\x02\xC5\x03\x9D\xC4\x48\x15\x66" + "\x35\x6A\xC2\xC9\xA2\x26\x30\xBB" + "\xDB\x2D\xC8\x08\x2B\xA0\x29\x1A" + "\x23\x61\x48\xEA\x80\x04\x27\xAA" + "\x69\x49\xE8\xE8\x4A\x83\x6B\x5A" + "\xCA\x7C\xD3\xB1\xB5\x0B\xCC\x23" + "\x74\x1F\xA9\x87\xCD\xED\xC0\x2D" + "\xBF\xEB\xCF\x16\x2D\x2A\x2E\x1D" + "\x96\xBA\x36\x11\x45\x41\xDA\xCE" + "\xA4\x48\x80\x8B\x06\xF4\x98\x89" + "\x8B\x23\x08\x53\xF4\xD4\x5A\x24" + "\x8B\xF8\x43\x73\xD1\xEE\xC4\xB0" + "\xF8\xFE\x09\x0C\x75\x05\x38\x0B" + "\x7C\x81\xDE\x9D\xE4\x61\x37\x63" + "\x63\xAD\x12\xD2\x04\xB9\xCE\x45" + "\x5A\x1A\x6E\xB3\x78\x2A\xA4\x74" + "\x86\xD0\xE3\xFF\xDA\x38\x9C\xB5" + "\xB8\xB1\xDB\x38\x2F\xC5\x6A\xB4" + "\xEB\x6E\x96\xE8\x43\x80\xB5\x51" + "\x61\x2D\x48\xAA\x07\x65\x11\x8C" + "\x48\xE3\x90\x7E\x78\x3A\xEC\x97" + "\x05\x3D\x84\xE7\x90\x2B\xAA\xBD" + "\x83\x29\x0E\x1A\x81\x73\x7B\xE0" + "\x7A\x01\x4A\x37\x3B\x77\x7F\x8D" + "\x49\xA4\x2F\x6E\xBE\x68\x99\x08" + "\x99\xAA\x4C\x12\x04\xAE\x1F\x77" + "\x35\x88\xF1\x65\x06\x0A\x0B\x4D" + "\x47\xF9\x50\x38\x5D\x71\xF9\x6E" + "\xDE\xEC\x61\x35\x2C\x4C\x96\x50" + "\xE8\x28\x93\x9C\x7E\x01\xC6\x04" + "\xB2\xD6\xBC\x6C\x17\xEB\xC1\x7D" + "\x11\xE9\x43\x83\x76\xAA\x53\x37" + "\x0C\x1D\x39\x89\x53\x72\x09\x7E" + "\xD9\x85\x16\x04\xA5\x2C\x05\x6F" + "\x17\x0C\x6E\x66\xAA\x84\xA7\xD9" + "\xE2\xD9\xC4\xEB\x43\x3E\xB1\x8D" + "\x7C\x36\xC7\x71\x70\x9C\x10\xD8" + "\xE8\x47\x2A\x4D\xFD\xA1\xBC\xE3" + "\xB9\x32\xE2\xC1\x82\xAC\xFE\xCC" + "\xC5\xC9\x7F\x9E\xCF\x33\x7A\xDF", + .rlen = 496, }, { /* Generated with Crypto++ */ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9" "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A" @@ -3023,8 +3563,62 @@ static struct cipher_testvec tf_ctr_enc_tv_template[] = { "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" - "\xC3\x37\xCE", - .ilen = 67, + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7" + "\x2B\xC2\x59", + .ilen = 499, .result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE" "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30" "\x26\x9B\x89\xA1\xEE\x43\xE0\x52" @@ -3033,8 +3627,62 @@ static struct cipher_testvec tf_ctr_enc_tv_template[] = { "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA" "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60" "\x01\x41\x21\x12\x38\xAB\x52\x4F" - "\xA8\x57\x20", - .rlen = 67, + "\xA8\x57\x20\xE0\x21\x6A\x17\x0D" + "\x0E\xF9\x8E\x49\x42\x00\x3C\x94" + "\x14\xC0\xD0\x8D\x8A\x98\xEB\x29" + "\xEC\xAE\x96\x44\xC0\x3C\x48\xDC" + "\x29\x35\x25\x2F\xE7\x11\x6C\x68" + "\xC8\x67\x0A\x2F\xF4\x07\xBE\xF9" + "\x2C\x31\x87\x40\xAB\xB2\xB6\xFA" + "\xD2\xC9\x6D\x5C\x50\xE9\xE6\x7E" + "\xE3\x0A\xD2\xD5\x6D\x8D\x64\x9E" + "\x70\xCE\x03\x76\xDD\xE0\xF0\x8C" + "\x84\x86\x8B\x6A\xFE\xC7\xF9\x69" + "\x2E\xFE\xFC\xC2\xC4\x1A\x55\x58" + "\xB3\xBE\xE2\x7E\xED\x39\x42\x6C" + "\xB4\x42\x97\x9A\xEC\xE1\x0A\x06" + "\x02\xC5\x03\x9D\xC4\x48\x15\x66" + "\x35\x6A\xC2\xC9\xA2\x26\x30\xBB" + "\xDB\x2D\xC8\x08\x2B\xA0\x29\x1A" + "\x23\x61\x48\xEA\x80\x04\x27\xAA" + "\x69\x49\xE8\xE8\x4A\x83\x6B\x5A" + "\xCA\x7C\xD3\xB1\xB5\x0B\xCC\x23" + "\x74\x1F\xA9\x87\xCD\xED\xC0\x2D" + "\xBF\xEB\xCF\x16\x2D\x2A\x2E\x1D" + "\x96\xBA\x36\x11\x45\x41\xDA\xCE" + "\xA4\x48\x80\x8B\x06\xF4\x98\x89" + "\x8B\x23\x08\x53\xF4\xD4\x5A\x24" + "\x8B\xF8\x43\x73\xD1\xEE\xC4\xB0" + "\xF8\xFE\x09\x0C\x75\x05\x38\x0B" + "\x7C\x81\xDE\x9D\xE4\x61\x37\x63" + "\x63\xAD\x12\xD2\x04\xB9\xCE\x45" + "\x5A\x1A\x6E\xB3\x78\x2A\xA4\x74" + "\x86\xD0\xE3\xFF\xDA\x38\x9C\xB5" + "\xB8\xB1\xDB\x38\x2F\xC5\x6A\xB4" + "\xEB\x6E\x96\xE8\x43\x80\xB5\x51" + "\x61\x2D\x48\xAA\x07\x65\x11\x8C" + "\x48\xE3\x90\x7E\x78\x3A\xEC\x97" + "\x05\x3D\x84\xE7\x90\x2B\xAA\xBD" + "\x83\x29\x0E\x1A\x81\x73\x7B\xE0" + "\x7A\x01\x4A\x37\x3B\x77\x7F\x8D" + "\x49\xA4\x2F\x6E\xBE\x68\x99\x08" + "\x99\xAA\x4C\x12\x04\xAE\x1F\x77" + "\x35\x88\xF1\x65\x06\x0A\x0B\x4D" + "\x47\xF9\x50\x38\x5D\x71\xF9\x6E" + "\xDE\xEC\x61\x35\x2C\x4C\x96\x50" + "\xE8\x28\x93\x9C\x7E\x01\xC6\x04" + "\xB2\xD6\xBC\x6C\x17\xEB\xC1\x7D" + "\x11\xE9\x43\x83\x76\xAA\x53\x37" + "\x0C\x1D\x39\x89\x53\x72\x09\x7E" + "\xD9\x85\x16\x04\xA5\x2C\x05\x6F" + "\x17\x0C\x6E\x66\xAA\x84\xA7\xD9" + "\xE2\xD9\xC4\xEB\x43\x3E\xB1\x8D" + "\x7C\x36\xC7\x71\x70\x9C\x10\xD8" + "\xE8\x47\x2A\x4D\xFD\xA1\xBC\xE3" + "\xB9\x32\xE2\xC1\x82\xAC\xFE\xCC" + "\xC5\xC9\x7F\x9E\xCF\x33\x7A\xDF" + "\x6C\x82\x9D", + .rlen = 499, }, }; @@ -3054,8 +3702,62 @@ static struct cipher_testvec tf_ctr_dec_tv_template[] = { "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0" "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA" "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60" - "\x01\x41\x21\x12\x38\xAB\x52\x4F", - .ilen = 64, + "\x01\x41\x21\x12\x38\xAB\x52\x4F" + "\xA8\x57\x20\xE0\x21\x6A\x17\x0D" + "\x0E\xF9\x8E\x49\x42\x00\x3C\x94" + "\x14\xC0\xD0\x8D\x8A\x98\xEB\x29" + "\xEC\xAE\x96\x44\xC0\x3C\x48\xDC" + "\x29\x35\x25\x2F\xE7\x11\x6C\x68" + "\xC8\x67\x0A\x2F\xF4\x07\xBE\xF9" + "\x2C\x31\x87\x40\xAB\xB2\xB6\xFA" + "\xD2\xC9\x6D\x5C\x50\xE9\xE6\x7E" + "\xE3\x0A\xD2\xD5\x6D\x8D\x64\x9E" + "\x70\xCE\x03\x76\xDD\xE0\xF0\x8C" + "\x84\x86\x8B\x6A\xFE\xC7\xF9\x69" + "\x2E\xFE\xFC\xC2\xC4\x1A\x55\x58" + "\xB3\xBE\xE2\x7E\xED\x39\x42\x6C" + "\xB4\x42\x97\x9A\xEC\xE1\x0A\x06" + "\x02\xC5\x03\x9D\xC4\x48\x15\x66" + "\x35\x6A\xC2\xC9\xA2\x26\x30\xBB" + "\xDB\x2D\xC8\x08\x2B\xA0\x29\x1A" + "\x23\x61\x48\xEA\x80\x04\x27\xAA" + "\x69\x49\xE8\xE8\x4A\x83\x6B\x5A" + "\xCA\x7C\xD3\xB1\xB5\x0B\xCC\x23" + "\x74\x1F\xA9\x87\xCD\xED\xC0\x2D" + "\xBF\xEB\xCF\x16\x2D\x2A\x2E\x1D" + "\x96\xBA\x36\x11\x45\x41\xDA\xCE" + "\xA4\x48\x80\x8B\x06\xF4\x98\x89" + "\x8B\x23\x08\x53\xF4\xD4\x5A\x24" + "\x8B\xF8\x43\x73\xD1\xEE\xC4\xB0" + "\xF8\xFE\x09\x0C\x75\x05\x38\x0B" + "\x7C\x81\xDE\x9D\xE4\x61\x37\x63" + "\x63\xAD\x12\xD2\x04\xB9\xCE\x45" + "\x5A\x1A\x6E\xB3\x78\x2A\xA4\x74" + "\x86\xD0\xE3\xFF\xDA\x38\x9C\xB5" + "\xB8\xB1\xDB\x38\x2F\xC5\x6A\xB4" + "\xEB\x6E\x96\xE8\x43\x80\xB5\x51" + "\x61\x2D\x48\xAA\x07\x65\x11\x8C" + "\x48\xE3\x90\x7E\x78\x3A\xEC\x97" + "\x05\x3D\x84\xE7\x90\x2B\xAA\xBD" + "\x83\x29\x0E\x1A\x81\x73\x7B\xE0" + "\x7A\x01\x4A\x37\x3B\x77\x7F\x8D" + "\x49\xA4\x2F\x6E\xBE\x68\x99\x08" + "\x99\xAA\x4C\x12\x04\xAE\x1F\x77" + "\x35\x88\xF1\x65\x06\x0A\x0B\x4D" + "\x47\xF9\x50\x38\x5D\x71\xF9\x6E" + "\xDE\xEC\x61\x35\x2C\x4C\x96\x50" + "\xE8\x28\x93\x9C\x7E\x01\xC6\x04" + "\xB2\xD6\xBC\x6C\x17\xEB\xC1\x7D" + "\x11\xE9\x43\x83\x76\xAA\x53\x37" + "\x0C\x1D\x39\x89\x53\x72\x09\x7E" + "\xD9\x85\x16\x04\xA5\x2C\x05\x6F" + "\x17\x0C\x6E\x66\xAA\x84\xA7\xD9" + "\xE2\xD9\xC4\xEB\x43\x3E\xB1\x8D" + "\x7C\x36\xC7\x71\x70\x9C\x10\xD8" + "\xE8\x47\x2A\x4D\xFD\xA1\xBC\xE3" + "\xB9\x32\xE2\xC1\x82\xAC\xFE\xCC" + "\xC5\xC9\x7F\x9E\xCF\x33\x7A\xDF", + .ilen = 496, .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31" "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3" "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15" @@ -3063,8 +3765,62 @@ static struct cipher_testvec tf_ctr_dec_tv_template[] = { "\x1E\x92\x29\xC0\x34\xCB\x62\xF9" "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" - "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C", - .rlen = 64, + "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7", + .rlen = 496, }, { /* Generated with Crypto++ */ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9" "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A" @@ -3081,8 +3837,62 @@ static struct cipher_testvec tf_ctr_dec_tv_template[] = { "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA" "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60" "\x01\x41\x21\x12\x38\xAB\x52\x4F" - "\xA8\x57\x20", - .ilen = 67, + "\xA8\x57\x20\xE0\x21\x6A\x17\x0D" + "\x0E\xF9\x8E\x49\x42\x00\x3C\x94" + "\x14\xC0\xD0\x8D\x8A\x98\xEB\x29" + "\xEC\xAE\x96\x44\xC0\x3C\x48\xDC" + "\x29\x35\x25\x2F\xE7\x11\x6C\x68" + "\xC8\x67\x0A\x2F\xF4\x07\xBE\xF9" + "\x2C\x31\x87\x40\xAB\xB2\xB6\xFA" + "\xD2\xC9\x6D\x5C\x50\xE9\xE6\x7E" + "\xE3\x0A\xD2\xD5\x6D\x8D\x64\x9E" + "\x70\xCE\x03\x76\xDD\xE0\xF0\x8C" + "\x84\x86\x8B\x6A\xFE\xC7\xF9\x69" + "\x2E\xFE\xFC\xC2\xC4\x1A\x55\x58" + "\xB3\xBE\xE2\x7E\xED\x39\x42\x6C" + "\xB4\x42\x97\x9A\xEC\xE1\x0A\x06" + "\x02\xC5\x03\x9D\xC4\x48\x15\x66" + "\x35\x6A\xC2\xC9\xA2\x26\x30\xBB" + "\xDB\x2D\xC8\x08\x2B\xA0\x29\x1A" + "\x23\x61\x48\xEA\x80\x04\x27\xAA" + "\x69\x49\xE8\xE8\x4A\x83\x6B\x5A" + "\xCA\x7C\xD3\xB1\xB5\x0B\xCC\x23" + "\x74\x1F\xA9\x87\xCD\xED\xC0\x2D" + "\xBF\xEB\xCF\x16\x2D\x2A\x2E\x1D" + "\x96\xBA\x36\x11\x45\x41\xDA\xCE" + "\xA4\x48\x80\x8B\x06\xF4\x98\x89" + "\x8B\x23\x08\x53\xF4\xD4\x5A\x24" + "\x8B\xF8\x43\x73\xD1\xEE\xC4\xB0" + "\xF8\xFE\x09\x0C\x75\x05\x38\x0B" + "\x7C\x81\xDE\x9D\xE4\x61\x37\x63" + "\x63\xAD\x12\xD2\x04\xB9\xCE\x45" + "\x5A\x1A\x6E\xB3\x78\x2A\xA4\x74" + "\x86\xD0\xE3\xFF\xDA\x38\x9C\xB5" + "\xB8\xB1\xDB\x38\x2F\xC5\x6A\xB4" + "\xEB\x6E\x96\xE8\x43\x80\xB5\x51" + "\x61\x2D\x48\xAA\x07\x65\x11\x8C" + "\x48\xE3\x90\x7E\x78\x3A\xEC\x97" + "\x05\x3D\x84\xE7\x90\x2B\xAA\xBD" + "\x83\x29\x0E\x1A\x81\x73\x7B\xE0" + "\x7A\x01\x4A\x37\x3B\x77\x7F\x8D" + "\x49\xA4\x2F\x6E\xBE\x68\x99\x08" + "\x99\xAA\x4C\x12\x04\xAE\x1F\x77" + "\x35\x88\xF1\x65\x06\x0A\x0B\x4D" + "\x47\xF9\x50\x38\x5D\x71\xF9\x6E" + "\xDE\xEC\x61\x35\x2C\x4C\x96\x50" + "\xE8\x28\x93\x9C\x7E\x01\xC6\x04" + "\xB2\xD6\xBC\x6C\x17\xEB\xC1\x7D" + "\x11\xE9\x43\x83\x76\xAA\x53\x37" + "\x0C\x1D\x39\x89\x53\x72\x09\x7E" + "\xD9\x85\x16\x04\xA5\x2C\x05\x6F" + "\x17\x0C\x6E\x66\xAA\x84\xA7\xD9" + "\xE2\xD9\xC4\xEB\x43\x3E\xB1\x8D" + "\x7C\x36\xC7\x71\x70\x9C\x10\xD8" + "\xE8\x47\x2A\x4D\xFD\xA1\xBC\xE3" + "\xB9\x32\xE2\xC1\x82\xAC\xFE\xCC" + "\xC5\xC9\x7F\x9E\xCF\x33\x7A\xDF" + "\x6C\x82\x9D", + .ilen = 499, .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31" "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3" "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15" @@ -3091,8 +3901,62 @@ static struct cipher_testvec tf_ctr_dec_tv_template[] = { "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48" "\xDF\x76\x0D\x81\x18\xAF\x23\xBA" "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C" - "\xC3\x37\xCE", - .rlen = 67, + "\xC3\x37\xCE\x65\xFC\x70\x07\x9E" + "\x12\xA9\x40\xD7\x4B\xE2\x79\x10" + "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F" + "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1" + "\x68\xFF\x73\x0A\xA1\x15\xAC\x43" + "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5" + "\x29\xC0\x57\xEE\x62\xF9\x90\x04" + "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76" + "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8" + "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A" + "\xF1\x65\xFC\x93\x07\x9E\x35\xCC" + "\x40\xD7\x6E\x05\x79\x10\xA7\x1B" + "\xB2\x49\xE0\x54\xEB\x82\x19\x8D" + "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF" + "\x96\x0A\xA1\x38\xCF\x43\xDA\x71" + "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3" + "\x57\xEE\x85\x1C\x90\x27\xBE\x32" + "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4" + "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16" + "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88" + "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA" + "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49" + "\xE0\x77\x0E\x82\x19\xB0\x24\xBB" + "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D" + "\xC4\x38\xCF\x66\xFD\x71\x08\x9F" + "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11" + "\x85\x1C\xB3\x27\xBE\x55\xEC\x60" + "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2" + "\x69\x00\x74\x0B\xA2\x16\xAD\x44" + "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6" + "\x2A\xC1\x58\xEF\x63\xFA\x91\x05" + "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77" + "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9" + "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B" + "\xF2\x66\xFD\x94\x08\x9F\x36\xCD" + "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C" + "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E" + "\x25\xBC\x30\xC7\x5E\xF5\x69\x00" + "\x97\x0B\xA2\x39\xD0\x44\xDB\x72" + "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4" + "\x58\xEF\x86\x1D\x91\x28\xBF\x33" + "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5" + "\x3C\xD3\x47\xDE\x75\x0C\x80\x17" + "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89" + "\x20\x94\x2B\xC2\x36\xCD\x64\xFB" + "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A" + "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC" + "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E" + "\xC5\x39\xD0\x67\xFE\x72\x09\xA0" + "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12" + "\x86\x1D\xB4\x28\xBF\x56\xED\x61" + "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3" + "\x6A\x01\x75\x0C\xA3\x17\xAE\x45" + "\xDC\x50\xE7\x7E\x15\x89\x20\xB7" + "\x2B\xC2\x59", + .rlen = 499, }, }; -- GitLab From 7efe4076725aeb01722445b56613681aa492c8d6 Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Tue, 12 Jun 2012 16:47:43 +0800 Subject: [PATCH 0511/5711] crypto: serpent - add x86_64/avx assembler implementation This patch adds a x86_64/avx assembler implementation of the Serpent block cipher. The implementation is very similar to the sse2 implementation and processes eight blocks in parallel. Because of the new non-destructive three operand syntax all move-instructions can be removed and therefore a little performance increase is provided. Patch has been tested with tcrypt and automated filesystem tests. Tcrypt benchmark results: Intel Core i5-2500 CPU (fam:6, model:42, step:7) serpent-avx-x86_64 vs. serpent-sse2-x86_64 128bit key: (lrw:256bit) (xts:256bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 1.03x 1.01x 1.01x 1.01x 1.00x 1.00x 1.00x 1.00x 1.00x 1.01x 64B 1.00x 1.00x 1.00x 1.00x 1.00x 0.99x 1.00x 1.01x 1.00x 1.00x 256B 1.05x 1.03x 1.00x 1.02x 1.05x 1.06x 1.05x 1.02x 1.05x 1.02x 1024B 1.05x 1.02x 1.00x 1.02x 1.05x 1.06x 1.05x 1.03x 1.05x 1.02x 8192B 1.05x 1.02x 1.00x 1.02x 1.06x 1.06x 1.04x 1.03x 1.04x 1.02x 256bit key: (lrw:384bit) (xts:512bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 1.01x 1.00x 1.01x 1.01x 1.00x 1.00x 0.99x 1.03x 1.01x 1.01x 64B 1.00x 1.00x 1.00x 1.00x 1.00x 1.00x 1.00x 1.01x 1.00x 1.02x 256B 1.05x 1.02x 1.00x 1.02x 1.05x 1.02x 1.04x 1.05x 1.05x 1.02x 1024B 1.06x 1.02x 1.00x 1.02x 1.07x 1.06x 1.05x 1.04x 1.05x 1.02x 8192B 1.05x 1.02x 1.00x 1.02x 1.06x 1.06x 1.04x 1.05x 1.05x 1.02x serpent-avx-x86_64 vs aes-asm (8kB block): 128bit 256bit ecb-enc 1.26x 1.73x ecb-dec 1.20x 1.64x cbc-enc 0.33x 0.45x cbc-dec 1.24x 1.67x ctr-enc 1.32x 1.76x ctr-dec 1.32x 1.76x lrw-enc 1.20x 1.60x lrw-dec 1.15x 1.54x xts-enc 1.22x 1.64x xts-dec 1.17x 1.57x Signed-off-by: Johannes Goetzfried Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 704 +++++++++++++++ arch/x86/crypto/serpent_avx_glue.c | 949 ++++++++++++++++++++ crypto/Kconfig | 20 + crypto/testmgr.c | 60 ++ 5 files changed, 1735 insertions(+) create mode 100644 arch/x86/crypto/serpent-avx-x86_64-asm_64.S create mode 100644 arch/x86/crypto/serpent_avx_glue.c diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 3420feef0c70..83caa4b948c8 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o +obj-$(CONFIG_CRYPTO_SERPENT_AVX_X86_64) += serpent-avx-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o @@ -34,6 +35,7 @@ twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o twofish_avx_glue.o salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o +serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S new file mode 100644 index 000000000000..0ed47a124bac --- /dev/null +++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S @@ -0,0 +1,704 @@ +/* + * Serpent Cipher 8-way parallel algorithm (x86_64/AVX) + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Based on arch/x86/crypto/serpent-sse2-x86_64-asm_64.S by + * Copyright (C) 2011 Jussi Kivilinna + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +.file "serpent-avx-x86_64-asm_64.S" +.text + +#define CTX %rdi + +/********************************************************************** + 8-way AVX serpent + **********************************************************************/ +#define RA1 %xmm0 +#define RB1 %xmm1 +#define RC1 %xmm2 +#define RD1 %xmm3 +#define RE1 %xmm4 + +#define tp %xmm5 + +#define RA2 %xmm6 +#define RB2 %xmm7 +#define RC2 %xmm8 +#define RD2 %xmm9 +#define RE2 %xmm10 + +#define RNOT %xmm11 + +#define RK0 %xmm12 +#define RK1 %xmm13 +#define RK2 %xmm14 +#define RK3 %xmm15 + + +#define S0_1(x0, x1, x2, x3, x4) \ + vpor x0, x3, tp; \ + vpxor x3, x0, x0; \ + vpxor x2, x3, x4; \ + vpxor RNOT, x4, x4; \ + vpxor x1, tp, x3; \ + vpand x0, x1, x1; \ + vpxor x4, x1, x1; \ + vpxor x0, x2, x2; +#define S0_2(x0, x1, x2, x3, x4) \ + vpxor x3, x0, x0; \ + vpor x0, x4, x4; \ + vpxor x2, x0, x0; \ + vpand x1, x2, x2; \ + vpxor x2, x3, x3; \ + vpxor RNOT, x1, x1; \ + vpxor x4, x2, x2; \ + vpxor x2, x1, x1; + +#define S1_1(x0, x1, x2, x3, x4) \ + vpxor x0, x1, tp; \ + vpxor x3, x0, x0; \ + vpxor RNOT, x3, x3; \ + vpand tp, x1, x4; \ + vpor tp, x0, x0; \ + vpxor x2, x3, x3; \ + vpxor x3, x0, x0; \ + vpxor x3, tp, x1; +#define S1_2(x0, x1, x2, x3, x4) \ + vpxor x4, x3, x3; \ + vpor x4, x1, x1; \ + vpxor x2, x4, x4; \ + vpand x0, x2, x2; \ + vpxor x1, x2, x2; \ + vpor x0, x1, x1; \ + vpxor RNOT, x0, x0; \ + vpxor x2, x0, x0; \ + vpxor x1, x4, x4; + +#define S2_1(x0, x1, x2, x3, x4) \ + vpxor RNOT, x3, x3; \ + vpxor x0, x1, x1; \ + vpand x2, x0, tp; \ + vpxor x3, tp, tp; \ + vpor x0, x3, x3; \ + vpxor x1, x2, x2; \ + vpxor x1, x3, x3; \ + vpand tp, x1, x1; +#define S2_2(x0, x1, x2, x3, x4) \ + vpxor x2, tp, tp; \ + vpand x3, x2, x2; \ + vpor x1, x3, x3; \ + vpxor RNOT, tp, tp; \ + vpxor tp, x3, x3; \ + vpxor tp, x0, x4; \ + vpxor x2, tp, x0; \ + vpor x2, x1, x1; + +#define S3_1(x0, x1, x2, x3, x4) \ + vpxor x3, x1, tp; \ + vpor x0, x3, x3; \ + vpand x0, x1, x4; \ + vpxor x2, x0, x0; \ + vpxor tp, x2, x2; \ + vpand x3, tp, x1; \ + vpxor x3, x2, x2; \ + vpor x4, x0, x0; \ + vpxor x3, x4, x4; +#define S3_2(x0, x1, x2, x3, x4) \ + vpxor x0, x1, x1; \ + vpand x3, x0, x0; \ + vpand x4, x3, x3; \ + vpxor x2, x3, x3; \ + vpor x1, x4, x4; \ + vpand x1, x2, x2; \ + vpxor x3, x4, x4; \ + vpxor x3, x0, x0; \ + vpxor x2, x3, x3; + +#define S4_1(x0, x1, x2, x3, x4) \ + vpand x0, x3, tp; \ + vpxor x3, x0, x0; \ + vpxor x2, tp, tp; \ + vpor x3, x2, x2; \ + vpxor x1, x0, x0; \ + vpxor tp, x3, x4; \ + vpor x0, x2, x2; \ + vpxor x1, x2, x2; +#define S4_2(x0, x1, x2, x3, x4) \ + vpand x0, x1, x1; \ + vpxor x4, x1, x1; \ + vpand x2, x4, x4; \ + vpxor tp, x2, x2; \ + vpxor x0, x4, x4; \ + vpor x1, tp, x3; \ + vpxor RNOT, x1, x1; \ + vpxor x0, x3, x3; + +#define S5_1(x0, x1, x2, x3, x4) \ + vpor x0, x1, tp; \ + vpxor tp, x2, x2; \ + vpxor RNOT, x3, x3; \ + vpxor x0, x1, x4; \ + vpxor x2, x0, x0; \ + vpand x4, tp, x1; \ + vpor x3, x4, x4; \ + vpxor x0, x4, x4; +#define S5_2(x0, x1, x2, x3, x4) \ + vpand x3, x0, x0; \ + vpxor x3, x1, x1; \ + vpxor x2, x3, x3; \ + vpxor x1, x0, x0; \ + vpand x4, x2, x2; \ + vpxor x2, x1, x1; \ + vpand x0, x2, x2; \ + vpxor x2, x3, x3; + +#define S6_1(x0, x1, x2, x3, x4) \ + vpxor x0, x3, x3; \ + vpxor x2, x1, tp; \ + vpxor x0, x2, x2; \ + vpand x3, x0, x0; \ + vpor x3, tp, tp; \ + vpxor RNOT, x1, x4; \ + vpxor tp, x0, x0; \ + vpxor x2, tp, x1; +#define S6_2(x0, x1, x2, x3, x4) \ + vpxor x4, x3, x3; \ + vpxor x0, x4, x4; \ + vpand x0, x2, x2; \ + vpxor x1, x4, x4; \ + vpxor x3, x2, x2; \ + vpand x1, x3, x3; \ + vpxor x0, x3, x3; \ + vpxor x2, x1, x1; + +#define S7_1(x0, x1, x2, x3, x4) \ + vpxor RNOT, x1, tp; \ + vpxor RNOT, x0, x0; \ + vpand x2, tp, x1; \ + vpxor x3, x1, x1; \ + vpor tp, x3, x3; \ + vpxor x2, tp, x4; \ + vpxor x3, x2, x2; \ + vpxor x0, x3, x3; \ + vpor x1, x0, x0; +#define S7_2(x0, x1, x2, x3, x4) \ + vpand x0, x2, x2; \ + vpxor x4, x0, x0; \ + vpxor x3, x4, x4; \ + vpand x0, x3, x3; \ + vpxor x1, x4, x4; \ + vpxor x4, x2, x2; \ + vpxor x1, x3, x3; \ + vpor x0, x4, x4; \ + vpxor x1, x4, x4; + +#define SI0_1(x0, x1, x2, x3, x4) \ + vpxor x0, x1, x1; \ + vpor x1, x3, tp; \ + vpxor x1, x3, x4; \ + vpxor RNOT, x0, x0; \ + vpxor tp, x2, x2; \ + vpxor x0, tp, x3; \ + vpand x1, x0, x0; \ + vpxor x2, x0, x0; +#define SI0_2(x0, x1, x2, x3, x4) \ + vpand x3, x2, x2; \ + vpxor x4, x3, x3; \ + vpxor x3, x2, x2; \ + vpxor x3, x1, x1; \ + vpand x0, x3, x3; \ + vpxor x0, x1, x1; \ + vpxor x2, x0, x0; \ + vpxor x3, x4, x4; + +#define SI1_1(x0, x1, x2, x3, x4) \ + vpxor x3, x1, x1; \ + vpxor x2, x0, tp; \ + vpxor RNOT, x2, x2; \ + vpor x1, x0, x4; \ + vpxor x3, x4, x4; \ + vpand x1, x3, x3; \ + vpxor x2, x1, x1; \ + vpand x4, x2, x2; +#define SI1_2(x0, x1, x2, x3, x4) \ + vpxor x1, x4, x4; \ + vpor x3, x1, x1; \ + vpxor tp, x3, x3; \ + vpxor tp, x2, x2; \ + vpor x4, tp, x0; \ + vpxor x4, x2, x2; \ + vpxor x0, x1, x1; \ + vpxor x1, x4, x4; + +#define SI2_1(x0, x1, x2, x3, x4) \ + vpxor x1, x2, x2; \ + vpxor RNOT, x3, tp; \ + vpor x2, tp, tp; \ + vpxor x3, x2, x2; \ + vpxor x0, x3, x4; \ + vpxor x1, tp, x3; \ + vpor x2, x1, x1; \ + vpxor x0, x2, x2; +#define SI2_2(x0, x1, x2, x3, x4) \ + vpxor x4, x1, x1; \ + vpor x3, x4, x4; \ + vpxor x3, x2, x2; \ + vpxor x2, x4, x4; \ + vpand x1, x2, x2; \ + vpxor x3, x2, x2; \ + vpxor x4, x3, x3; \ + vpxor x0, x4, x4; + +#define SI3_1(x0, x1, x2, x3, x4) \ + vpxor x1, x2, x2; \ + vpand x2, x1, tp; \ + vpxor x0, tp, tp; \ + vpor x1, x0, x0; \ + vpxor x3, x1, x4; \ + vpxor x3, x0, x0; \ + vpor tp, x3, x3; \ + vpxor x2, tp, x1; +#define SI3_2(x0, x1, x2, x3, x4) \ + vpxor x3, x1, x1; \ + vpxor x2, x0, x0; \ + vpxor x3, x2, x2; \ + vpand x1, x3, x3; \ + vpxor x0, x1, x1; \ + vpand x2, x0, x0; \ + vpxor x3, x4, x4; \ + vpxor x0, x3, x3; \ + vpxor x1, x0, x0; + +#define SI4_1(x0, x1, x2, x3, x4) \ + vpxor x3, x2, x2; \ + vpand x1, x0, tp; \ + vpxor x2, tp, tp; \ + vpor x3, x2, x2; \ + vpxor RNOT, x0, x4; \ + vpxor tp, x1, x1; \ + vpxor x2, tp, x0; \ + vpand x4, x2, x2; +#define SI4_2(x0, x1, x2, x3, x4) \ + vpxor x0, x2, x2; \ + vpor x4, x0, x0; \ + vpxor x3, x0, x0; \ + vpand x2, x3, x3; \ + vpxor x3, x4, x4; \ + vpxor x1, x3, x3; \ + vpand x0, x1, x1; \ + vpxor x1, x4, x4; \ + vpxor x3, x0, x0; + +#define SI5_1(x0, x1, x2, x3, x4) \ + vpor x2, x1, tp; \ + vpxor x1, x2, x2; \ + vpxor x3, tp, tp; \ + vpand x1, x3, x3; \ + vpxor x3, x2, x2; \ + vpor x0, x3, x3; \ + vpxor RNOT, x0, x0; \ + vpxor x2, x3, x3; \ + vpor x0, x2, x2; +#define SI5_2(x0, x1, x2, x3, x4) \ + vpxor tp, x1, x4; \ + vpxor x4, x2, x2; \ + vpand x0, x4, x4; \ + vpxor tp, x0, x0; \ + vpxor x3, tp, x1; \ + vpand x2, x0, x0; \ + vpxor x3, x2, x2; \ + vpxor x2, x0, x0; \ + vpxor x4, x2, x2; \ + vpxor x3, x4, x4; + +#define SI6_1(x0, x1, x2, x3, x4) \ + vpxor x2, x0, x0; \ + vpand x3, x0, tp; \ + vpxor x3, x2, x2; \ + vpxor x2, tp, tp; \ + vpxor x1, x3, x3; \ + vpor x0, x2, x2; \ + vpxor x3, x2, x2; \ + vpand tp, x3, x3; +#define SI6_2(x0, x1, x2, x3, x4) \ + vpxor RNOT, tp, tp; \ + vpxor x1, x3, x3; \ + vpand x2, x1, x1; \ + vpxor tp, x0, x4; \ + vpxor x4, x3, x3; \ + vpxor x2, x4, x4; \ + vpxor x1, tp, x0; \ + vpxor x0, x2, x2; + +#define SI7_1(x0, x1, x2, x3, x4) \ + vpand x0, x3, tp; \ + vpxor x2, x0, x0; \ + vpor x3, x2, x2; \ + vpxor x1, x3, x4; \ + vpxor RNOT, x0, x0; \ + vpor tp, x1, x1; \ + vpxor x0, x4, x4; \ + vpand x2, x0, x0; \ + vpxor x1, x0, x0; +#define SI7_2(x0, x1, x2, x3, x4) \ + vpand x2, x1, x1; \ + vpxor x2, tp, x3; \ + vpxor x3, x4, x4; \ + vpand x3, x2, x2; \ + vpor x0, x3, x3; \ + vpxor x4, x1, x1; \ + vpxor x4, x3, x3; \ + vpand x0, x4, x4; \ + vpxor x2, x4, x4; + +#define get_key(i, j, t) \ + vbroadcastss (4*(i)+(j))*4(CTX), t; + +#define K2(x0, x1, x2, x3, x4, i) \ + get_key(i, 0, RK0); \ + get_key(i, 1, RK1); \ + get_key(i, 2, RK2); \ + get_key(i, 3, RK3); \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; + +#define LK2(x0, x1, x2, x3, x4, i) \ + vpslld $13, x0 ## 1, x4 ## 1; \ + vpsrld $(32 - 13), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x0 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x2 ## 1, x4 ## 1; \ + vpsrld $(32 - 3), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x2 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $13, x0 ## 2, x4 ## 2; \ + vpsrld $(32 - 13), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x0 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x2 ## 2, x4 ## 2; \ + vpsrld $(32 - 3), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x2 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $1, x1 ## 1, x4 ## 1; \ + vpsrld $(32 - 1), x1 ## 1, x1 ## 1; \ + vpor x4 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x0 ## 1, x4 ## 1; \ + vpxor x2 ## 1, x3 ## 1, x3 ## 1; \ + vpxor x4 ## 1, x3 ## 1, x3 ## 1; \ + get_key(i, 1, RK1); \ + vpslld $1, x1 ## 2, x4 ## 2; \ + vpsrld $(32 - 1), x1 ## 2, x1 ## 2; \ + vpor x4 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x0 ## 2, x4 ## 2; \ + vpxor x2 ## 2, x3 ## 2, x3 ## 2; \ + vpxor x4 ## 2, x3 ## 2, x3 ## 2; \ + get_key(i, 3, RK3); \ + vpslld $7, x3 ## 1, x4 ## 1; \ + vpsrld $(32 - 7), x3 ## 1, x3 ## 1; \ + vpor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpslld $7, x1 ## 1, x4 ## 1; \ + vpxor x1 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x3 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x3 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x4 ## 1, x2 ## 1, x2 ## 1; \ + get_key(i, 0, RK0); \ + vpslld $7, x3 ## 2, x4 ## 2; \ + vpsrld $(32 - 7), x3 ## 2, x3 ## 2; \ + vpor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpslld $7, x1 ## 2, x4 ## 2; \ + vpxor x1 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x3 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x3 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x4 ## 2, x2 ## 2, x2 ## 2; \ + get_key(i, 2, RK2); \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpslld $5, x0 ## 1, x4 ## 1; \ + vpsrld $(32 - 5), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpslld $22, x2 ## 1, x4 ## 1; \ + vpsrld $(32 - 22), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; \ + vpslld $5, x0 ## 2, x4 ## 2; \ + vpsrld $(32 - 5), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpslld $22, x2 ## 2, x4 ## 2; \ + vpsrld $(32 - 22), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; + +#define KL2(x0, x1, x2, x3, x4, i) \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpsrld $5, x0 ## 1, x4 ## 1; \ + vpslld $(32 - 5), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpsrld $22, x2 ## 1, x4 ## 1; \ + vpslld $(32 - 22), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x3 ## 1, x2 ## 1, x2 ## 1; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; \ + vpsrld $5, x0 ## 2, x4 ## 2; \ + vpslld $(32 - 5), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpsrld $22, x2 ## 2, x4 ## 2; \ + vpslld $(32 - 22), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x3 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x3 ## 1, x0 ## 1, x0 ## 1; \ + vpslld $7, x1 ## 1, x4 ## 1; \ + vpxor x1 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpsrld $1, x1 ## 1, x4 ## 1; \ + vpslld $(32 - 1), x1 ## 1, x1 ## 1; \ + vpor x4 ## 1, x1 ## 1, x1 ## 1; \ + vpxor x3 ## 2, x0 ## 2, x0 ## 2; \ + vpslld $7, x1 ## 2, x4 ## 2; \ + vpxor x1 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpsrld $1, x1 ## 2, x4 ## 2; \ + vpslld $(32 - 1), x1 ## 2, x1 ## 2; \ + vpor x4 ## 2, x1 ## 2, x1 ## 2; \ + vpsrld $7, x3 ## 1, x4 ## 1; \ + vpslld $(32 - 7), x3 ## 1, x3 ## 1; \ + vpor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpxor x0 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x0 ## 1, x4 ## 1; \ + vpxor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpsrld $7, x3 ## 2, x4 ## 2; \ + vpslld $(32 - 7), x3 ## 2, x3 ## 2; \ + vpor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpxor x0 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x0 ## 2, x4 ## 2; \ + vpxor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpsrld $13, x0 ## 1, x4 ## 1; \ + vpslld $(32 - 13), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x2 ## 1, x1 ## 1, x1 ## 1; \ + vpxor x2 ## 1, x3 ## 1, x3 ## 1; \ + vpsrld $3, x2 ## 1, x4 ## 1; \ + vpslld $(32 - 3), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpsrld $13, x0 ## 2, x4 ## 2; \ + vpslld $(32 - 13), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x2 ## 2, x1 ## 2, x1 ## 2; \ + vpxor x2 ## 2, x3 ## 2, x3 ## 2; \ + vpsrld $3, x2 ## 2, x4 ## 2; \ + vpslld $(32 - 3), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; + +#define S(SBOX, x0, x1, x2, x3, x4) \ + SBOX ## _1(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + SBOX ## _2(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + SBOX ## _1(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); + +#define SP(SBOX, x0, x1, x2, x3, x4, i) \ + get_key(i, 0, RK0); \ + SBOX ## _1(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + get_key(i, 2, RK2); \ + SBOX ## _2(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + get_key(i, 3, RK3); \ + SBOX ## _1(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + get_key(i, 1, RK1); \ + SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + vpunpckldq x1, x0, t0; \ + vpunpckhdq x1, x0, t2; \ + vpunpckldq x3, x2, t1; \ + vpunpckhdq x3, x2, x3; \ + \ + vpunpcklqdq t1, t0, x0; \ + vpunpckhqdq t1, t0, x1; \ + vpunpcklqdq x3, t2, x2; \ + vpunpckhqdq x3, t2, x3; + +#define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \ + vmovdqu (0*4*4)(in), x0; \ + vmovdqu (1*4*4)(in), x1; \ + vmovdqu (2*4*4)(in), x2; \ + vmovdqu (3*4*4)(in), x3; \ + \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) + +#define write_blocks(out, x0, x1, x2, x3, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vmovdqu x0, (0*4*4)(out); \ + vmovdqu x1, (1*4*4)(out); \ + vmovdqu x2, (2*4*4)(out); \ + vmovdqu x3, (3*4*4)(out); + +#define xor_blocks(out, x0, x1, x2, x3, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor (0*4*4)(out), x0, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor (1*4*4)(out), x1, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor (2*4*4)(out), x2, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor (3*4*4)(out), x3, x3; \ + vmovdqu x3, (3*4*4)(out); + +.align 8 +.global __serpent_enc_blk_8way +.type __serpent_enc_blk_8way,@function; + +__serpent_enc_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + * %rcx: bool, if true: xor output + */ + + vpcmpeqd RNOT, RNOT, RNOT; + + leaq (4*4*4)(%rdx), %rax; + read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + K2(RA, RB, RC, RD, RE, 0); + S(S0, RA, RB, RC, RD, RE); LK2(RC, RB, RD, RA, RE, 1); + S(S1, RC, RB, RD, RA, RE); LK2(RE, RD, RA, RC, RB, 2); + S(S2, RE, RD, RA, RC, RB); LK2(RB, RD, RE, RC, RA, 3); + S(S3, RB, RD, RE, RC, RA); LK2(RC, RA, RD, RB, RE, 4); + S(S4, RC, RA, RD, RB, RE); LK2(RA, RD, RB, RE, RC, 5); + S(S5, RA, RD, RB, RE, RC); LK2(RC, RA, RD, RE, RB, 6); + S(S6, RC, RA, RD, RE, RB); LK2(RD, RB, RA, RE, RC, 7); + S(S7, RD, RB, RA, RE, RC); LK2(RC, RA, RE, RD, RB, 8); + S(S0, RC, RA, RE, RD, RB); LK2(RE, RA, RD, RC, RB, 9); + S(S1, RE, RA, RD, RC, RB); LK2(RB, RD, RC, RE, RA, 10); + S(S2, RB, RD, RC, RE, RA); LK2(RA, RD, RB, RE, RC, 11); + S(S3, RA, RD, RB, RE, RC); LK2(RE, RC, RD, RA, RB, 12); + S(S4, RE, RC, RD, RA, RB); LK2(RC, RD, RA, RB, RE, 13); + S(S5, RC, RD, RA, RB, RE); LK2(RE, RC, RD, RB, RA, 14); + S(S6, RE, RC, RD, RB, RA); LK2(RD, RA, RC, RB, RE, 15); + S(S7, RD, RA, RC, RB, RE); LK2(RE, RC, RB, RD, RA, 16); + S(S0, RE, RC, RB, RD, RA); LK2(RB, RC, RD, RE, RA, 17); + S(S1, RB, RC, RD, RE, RA); LK2(RA, RD, RE, RB, RC, 18); + S(S2, RA, RD, RE, RB, RC); LK2(RC, RD, RA, RB, RE, 19); + S(S3, RC, RD, RA, RB, RE); LK2(RB, RE, RD, RC, RA, 20); + S(S4, RB, RE, RD, RC, RA); LK2(RE, RD, RC, RA, RB, 21); + S(S5, RE, RD, RC, RA, RB); LK2(RB, RE, RD, RA, RC, 22); + S(S6, RB, RE, RD, RA, RC); LK2(RD, RC, RE, RA, RB, 23); + S(S7, RD, RC, RE, RA, RB); LK2(RB, RE, RA, RD, RC, 24); + S(S0, RB, RE, RA, RD, RC); LK2(RA, RE, RD, RB, RC, 25); + S(S1, RA, RE, RD, RB, RC); LK2(RC, RD, RB, RA, RE, 26); + S(S2, RC, RD, RB, RA, RE); LK2(RE, RD, RC, RA, RB, 27); + S(S3, RE, RD, RC, RA, RB); LK2(RA, RB, RD, RE, RC, 28); + S(S4, RA, RB, RD, RE, RC); LK2(RB, RD, RE, RC, RA, 29); + S(S5, RB, RD, RE, RC, RA); LK2(RA, RB, RD, RC, RE, 30); + S(S6, RA, RB, RD, RC, RE); LK2(RD, RE, RB, RC, RA, 31); + S(S7, RD, RE, RB, RC, RA); K2(RA, RB, RC, RD, RE, 32); + + leaq (4*4*4)(%rsi), %rax; + + testb %cl, %cl; + jnz __enc_xor8; + + write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + ret; + +__enc_xor8: + xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + ret; + +.align 8 +.global serpent_dec_blk_8way +.type serpent_dec_blk_8way,@function; + +serpent_dec_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + */ + + vpcmpeqd RNOT, RNOT, RNOT; + + leaq (4*4*4)(%rdx), %rax; + read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + K2(RA, RB, RC, RD, RE, 32); + SP(SI7, RA, RB, RC, RD, RE, 31); KL2(RB, RD, RA, RE, RC, 31); + SP(SI6, RB, RD, RA, RE, RC, 30); KL2(RA, RC, RE, RB, RD, 30); + SP(SI5, RA, RC, RE, RB, RD, 29); KL2(RC, RD, RA, RE, RB, 29); + SP(SI4, RC, RD, RA, RE, RB, 28); KL2(RC, RA, RB, RE, RD, 28); + SP(SI3, RC, RA, RB, RE, RD, 27); KL2(RB, RC, RD, RE, RA, 27); + SP(SI2, RB, RC, RD, RE, RA, 26); KL2(RC, RA, RE, RD, RB, 26); + SP(SI1, RC, RA, RE, RD, RB, 25); KL2(RB, RA, RE, RD, RC, 25); + SP(SI0, RB, RA, RE, RD, RC, 24); KL2(RE, RC, RA, RB, RD, 24); + SP(SI7, RE, RC, RA, RB, RD, 23); KL2(RC, RB, RE, RD, RA, 23); + SP(SI6, RC, RB, RE, RD, RA, 22); KL2(RE, RA, RD, RC, RB, 22); + SP(SI5, RE, RA, RD, RC, RB, 21); KL2(RA, RB, RE, RD, RC, 21); + SP(SI4, RA, RB, RE, RD, RC, 20); KL2(RA, RE, RC, RD, RB, 20); + SP(SI3, RA, RE, RC, RD, RB, 19); KL2(RC, RA, RB, RD, RE, 19); + SP(SI2, RC, RA, RB, RD, RE, 18); KL2(RA, RE, RD, RB, RC, 18); + SP(SI1, RA, RE, RD, RB, RC, 17); KL2(RC, RE, RD, RB, RA, 17); + SP(SI0, RC, RE, RD, RB, RA, 16); KL2(RD, RA, RE, RC, RB, 16); + SP(SI7, RD, RA, RE, RC, RB, 15); KL2(RA, RC, RD, RB, RE, 15); + SP(SI6, RA, RC, RD, RB, RE, 14); KL2(RD, RE, RB, RA, RC, 14); + SP(SI5, RD, RE, RB, RA, RC, 13); KL2(RE, RC, RD, RB, RA, 13); + SP(SI4, RE, RC, RD, RB, RA, 12); KL2(RE, RD, RA, RB, RC, 12); + SP(SI3, RE, RD, RA, RB, RC, 11); KL2(RA, RE, RC, RB, RD, 11); + SP(SI2, RA, RE, RC, RB, RD, 10); KL2(RE, RD, RB, RC, RA, 10); + SP(SI1, RE, RD, RB, RC, RA, 9); KL2(RA, RD, RB, RC, RE, 9); + SP(SI0, RA, RD, RB, RC, RE, 8); KL2(RB, RE, RD, RA, RC, 8); + SP(SI7, RB, RE, RD, RA, RC, 7); KL2(RE, RA, RB, RC, RD, 7); + SP(SI6, RE, RA, RB, RC, RD, 6); KL2(RB, RD, RC, RE, RA, 6); + SP(SI5, RB, RD, RC, RE, RA, 5); KL2(RD, RA, RB, RC, RE, 5); + SP(SI4, RD, RA, RB, RC, RE, 4); KL2(RD, RB, RE, RC, RA, 4); + SP(SI3, RD, RB, RE, RC, RA, 3); KL2(RE, RD, RA, RC, RB, 3); + SP(SI2, RE, RD, RA, RC, RB, 2); KL2(RD, RB, RC, RA, RE, 2); + SP(SI1, RD, RB, RC, RA, RE, 1); KL2(RE, RB, RC, RA, RD, 1); + S(SI0, RE, RB, RC, RA, RD); K2(RC, RD, RB, RE, RA, 0); + + leaq (4*4*4)(%rsi), %rax; + write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2); + write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2); + + ret; diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c new file mode 100644 index 000000000000..0dc7a26535e5 --- /dev/null +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -0,0 +1,949 @@ +/* + * Glue Code for AVX assembler versions of Serpent Cipher + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Glue code based on serpent_sse2_glue.c by: + * Copyright (C) 2011 Jussi Kivilinna + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct async_serpent_ctx { + struct cryptd_ablkcipher *cryptd_tfm; +}; + +static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) +{ + if (fpu_enabled) + return true; + + /* AVX is only used when chunk to be processed is large enough, so + * do not enable FPU until it is necessary. + */ + if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS) + return false; + + kernel_fpu_begin(); + return true; +} + +static inline void serpent_fpu_end(bool fpu_enabled) +{ + if (fpu_enabled) + kernel_fpu_end(); +} + +static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, + bool enc) +{ + bool fpu_enabled = false; + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes; + int err; + + err = blkcipher_walk_virt(desc, walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk->nbytes)) { + u8 *wsrc = walk->src.virt.addr; + u8 *wdst = walk->dst.virt.addr; + + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + if (enc) + serpent_enc_blk_xway(ctx, wdst, wsrc); + else + serpent_dec_blk_xway(ctx, wdst, wsrc); + + wsrc += bsize * SERPENT_PARALLEL_BLOCKS; + wdst += bsize * SERPENT_PARALLEL_BLOCKS; + nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (enc) + __serpent_encrypt(ctx, wdst, wsrc); + else + __serpent_decrypt(ctx, wdst, wsrc); + + wsrc += bsize; + wdst += bsize; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + err = blkcipher_walk_done(desc, walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + return err; +} + +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, true); +} + +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, false); +} + +static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 *iv = (u128 *)walk->iv; + + do { + u128_xor(dst, src, iv); + __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst); + iv = dst; + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + + u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); + return nbytes; +} + +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + nbytes = __cbc_encrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; + u128 last_iv; + int i; + + /* Start of the last block. */ + src += nbytes / bsize - 1; + dst += nbytes / bsize - 1; + + last_iv = *src; + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1); + src -= SERPENT_PARALLEL_BLOCKS - 1; + dst -= SERPENT_PARALLEL_BLOCKS - 1; + + for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) + ivs[i] = src[i]; + + serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + + for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) + u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + for (;;) { + __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src); + + nbytes -= bsize; + if (nbytes < bsize) + break; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } + +done: + u128_xor(dst, dst, (u128 *)walk->iv); + *(u128 *)walk->iv = last_iv; + + return nbytes; +} + +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes)) { + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + nbytes = __cbc_decrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + return err; +} + +static inline void u128_to_be128(be128 *dst, const u128 *src) +{ + dst->a = cpu_to_be64(src->a); + dst->b = cpu_to_be64(src->b); +} + +static inline void be128_to_u128(u128 *dst, const be128 *src) +{ + dst->a = be64_to_cpu(src->a); + dst->b = be64_to_cpu(src->b); +} + +static inline void u128_inc(u128 *i) +{ + i->b++; + if (!i->b) + i->a++; +} + +static void ctr_crypt_final(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *ctrblk = walk->iv; + u8 keystream[SERPENT_BLOCK_SIZE]; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + unsigned int nbytes = walk->nbytes; + + __serpent_encrypt(ctx, keystream, ctrblk); + crypto_xor(keystream, src, nbytes); + memcpy(dst, keystream, nbytes); + + crypto_inc(ctrblk, SERPENT_BLOCK_SIZE); +} + +static unsigned int __ctr_crypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ctrblk; + be128 ctrblocks[SERPENT_PARALLEL_BLOCKS]; + int i; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + /* create ctrblks for parallel encrypt */ + for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; + + u128_to_be128(&ctrblocks[i], &ctrblk); + u128_inc(&ctrblk); + } + + serpent_enc_blk_xway_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += SERPENT_PARALLEL_BLOCKS; + dst += SERPENT_PARALLEL_BLOCKS; + nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (dst != src) + *dst = *src; + + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + + __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); + u128_xor(dst, dst, (u128 *)ctrblocks); + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + u128_to_be128((be128 *)walk->iv, &ctrblk); + return nbytes; +} + +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) { + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + nbytes = __ctr_crypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + + if (walk.nbytes) { + ctr_crypt_final(desc, &walk); + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} + +struct crypt_priv { + struct serpent_ctx *ctx; + bool fpu_enabled; +}; + +static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = SERPENT_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { + serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + __serpent_encrypt(ctx->ctx, srcdst, srcdst); +} + +static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = SERPENT_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { + serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + __serpent_decrypt(ctx->ctx, srcdst, srcdst); +} + +struct serpent_lrw_ctx { + struct lrw_table_ctx lrw_table; + struct serpent_ctx serpent_ctx; +}; + +static int lrw_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + int err; + + err = __serpent_setkey(&ctx->serpent_ctx, key, keylen - + SERPENT_BLOCK_SIZE); + if (err) + return err; + + return lrw_init_table(&ctx->lrw_table, key + keylen - + SERPENT_BLOCK_SIZE); +} + +static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->serpent_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->serpent_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static void lrw_exit_tfm(struct crypto_tfm *tfm) +{ + struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + + lrw_free_table(&ctx->lrw_table); +} + +struct serpent_xts_ctx { + struct serpent_ctx tweak_ctx; + struct serpent_ctx crypt_ctx; +}; + +static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + int err; + + /* key consists of keys of equal size concatenated, therefore + * the length must be even + */ + if (keylen % 2) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* first half of xts-key is for crypt */ + err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2); + if (err) + return err; + + /* second half of xts-key is for tweak */ + return __serpent_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2); +} + +static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(child, key, key_len); + crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) + & CRYPTO_TFM_RES_MASK); + return err; +} + +static int __ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->encrypt( + &desc, req->dst, req->src, req->nbytes); +} + +static int ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_encrypt(cryptd_req); + } else { + return __ablk_encrypt(req); + } +} + +static int ablk_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_decrypt(cryptd_req); + } else { + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->decrypt( + &desc, req->dst, req->src, req->nbytes); + } +} + +static void ablk_exit(struct crypto_tfm *tfm) +{ + struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ablkcipher(ctx->cryptd_tfm); +} + +static int ablk_init(struct crypto_tfm *tfm) +{ + struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_ablkcipher *cryptd_tfm; + char drv_name[CRYPTO_MAX_ALG_NAME]; + + snprintf(drv_name, sizeof(drv_name), "__driver-%s", + crypto_tfm_alg_driver_name(tfm)); + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + + ctx->cryptd_tfm = cryptd_tfm; + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(&cryptd_tfm->base); + + return 0; +} + +static struct crypto_alg serpent_algs[10] = { { + .cra_name = "__ecb-serpent-avx", + .cra_driver_name = "__driver-ecb-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[0].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = serpent_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, + }, + }, +}, { + .cra_name = "__cbc-serpent-avx", + .cra_driver_name = "__driver-cbc-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[1].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = serpent_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, + }, + }, +}, { + .cra_name = "__ctr-serpent-avx", + .cra_driver_name = "__driver-ctr-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[2].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = serpent_setkey, + .encrypt = ctr_crypt, + .decrypt = ctr_crypt, + }, + }, +}, { + .cra_name = "__lrw-serpent-avx", + .cra_driver_name = "__driver-lrw-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_lrw_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[3].cra_list), + .cra_exit = lrw_exit_tfm, + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = lrw_serpent_setkey, + .encrypt = lrw_encrypt, + .decrypt = lrw_decrypt, + }, + }, +}, { + .cra_name = "__xts-serpent-avx", + .cra_driver_name = "__driver-xts-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_xts_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[4].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE * 2, + .max_keysize = SERPENT_MAX_KEY_SIZE * 2, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = xts_serpent_setkey, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, + }, + }, +}, { + .cra_name = "ecb(serpent)", + .cra_driver_name = "ecb-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[5].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "cbc(serpent)", + .cra_driver_name = "cbc-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[6].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = __ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "ctr(serpent)", + .cra_driver_name = "ctr-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[7].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_encrypt, + .geniv = "chainiv", + }, + }, +}, { + .cra_name = "lrw(serpent)", + .cra_driver_name = "lrw-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[8].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "xts(serpent)", + .cra_driver_name = "xts-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[9].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE * 2, + .max_keysize = SERPENT_MAX_KEY_SIZE * 2, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +} }; + +static int __init serpent_init(void) +{ + u64 xcr0; + + if (!cpu_has_avx || !cpu_has_osxsave) { + printk(KERN_INFO "AVX instructions are not detected.\n"); + return -ENODEV; + } + + xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { + printk(KERN_INFO "AVX detected but unusable.\n"); + return -ENODEV; + } + + return crypto_register_algs(serpent_algs, ARRAY_SIZE(serpent_algs)); +} + +static void __exit serpent_exit(void) +{ + crypto_unregister_algs(serpent_algs, ARRAY_SIZE(serpent_algs)); +} + +module_init(serpent_init); +module_exit(serpent_exit); + +MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("serpent"); diff --git a/crypto/Kconfig b/crypto/Kconfig index e00a4e49e013..2c1c2dfcc02a 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -821,6 +821,26 @@ config CRYPTO_SERPENT_SSE2_586 See also: +config CRYPTO_SERPENT_AVX_X86_64 + tristate "Serpent cipher algorithm (x86_64/AVX)" + depends on X86 && 64BIT + select CRYPTO_ALGAPI + select CRYPTO_CRYPTD + select CRYPTO_SERPENT + select CRYPTO_LRW + select CRYPTO_XTS + help + Serpent cipher algorithm, by Anderson, Biham & Knudsen. + + Keys are allowed to be from 0 to 256 bits in length, in steps + of 8 bits. + + This module provides the Serpent cipher algorithm that processes + eight blocks parallel using the AVX instruction set. + + See also: + + config CRYPTO_TEA tristate "TEA, XTEA and XETA cipher algorithms" select CRYPTO_ALGAPI diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 73b3ec6fe1a2..36748a5996e2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1534,6 +1534,21 @@ static int alg_test_null(const struct alg_test_desc *desc, /* Please keep this list sorted by algorithm name. */ static const struct alg_test_desc alg_test_descs[] = { { + .alg = "__cbc-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } + }, { .alg = "__cbc-serpent-sse2", .test = alg_test_null, .suite = { @@ -1578,6 +1593,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-cbc-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-cbc-serpent-sse2", .test = alg_test_null, @@ -1623,6 +1653,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-ecb-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-ecb-serpent-sse2", .test = alg_test_null, @@ -1835,6 +1880,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "cryptd(__driver-ecb-serpent-avx)", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__driver-ecb-serpent-sse2)", .test = alg_test_null, -- GitLab From 9102d8715e5c10db37d81ab75285a2f6746360b2 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 12 Jun 2012 10:44:55 +0200 Subject: [PATCH 0512/5711] dmaengine: at_hdmac: trivial: fix comment in header Not all Atmel SoCs were pointed out in header comment which was bringing confusion. Remove the truncated list of supported devices, replace by the only one that is not supported. Reported-by: Elen Song Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7292aa87b2dd..bb1601305d25 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -9,10 +9,9 @@ * (at your option) any later version. * * - * This supports the Atmel AHB DMA Controller, - * - * The driver has currently been tested with the Atmel AT91SAM9RL - * and AT91SAM9G45 series. + * This supports the Atmel AHB DMA Controller found in several Atmel SoCs. + * The only Atmel DMA Controller that is not covered by this driver is the one + * found on AT91SAM9263. */ #include -- GitLab From b785ea7ce662c47f6208071320638a4813722803 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Jun 2012 10:20:23 +0300 Subject: [PATCH 0513/5711] usb: gadget: composite: fix ep->maxburst initialization bMaxBurst field on endpoint companion descriptor is supposed to contain the number of burst minus 1. When passing that to controller drivers, we should be passing the real number instead (by incrementing 1). While doing that, also fix the assumption on dwc3 that value comes decremented by one. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- drivers/usb/gadget/composite.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3df1a1973b05..cc978d65a808 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -414,7 +414,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) - | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst); + | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN | DWC3_DEPCFG_XFER_NOT_READY_EN; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 390749bbb0c3..3f72110da1b0 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -117,6 +117,7 @@ int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, struct usb_ep *_ep) { + struct usb_composite_dev *cdev = get_gadget_data(g); struct usb_endpoint_descriptor *chosen_desc = NULL; struct usb_descriptor_header **speed_desc = NULL; @@ -180,10 +181,12 @@ ep_found: _ep->mult = comp_desc->bmAttributes & 0x3; case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_INT: - _ep->maxburst = comp_desc->bMaxBurst; + _ep->maxburst = comp_desc->bMaxBurst + 1; break; default: - /* Do nothing for control endpoints */ + if (comp_desc->bMaxBurst != 0) + ERROR(cdev, "ep0 bMaxBurst must be 0\n"); + _ep->maxburst = 1; break; } } -- GitLab From 1c7f6cd3f97b038e875094a8433e239f03d10955 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 May 2012 20:14:53 -0300 Subject: [PATCH 0514/5711] usb: fsl_mxc_udc.c : Use clk_prepare_enable/clk_disable_unprepare Prepare the clock before enabling it. Cc: Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_mxc_udc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index dcbc0a2e48dd..f4b5109feb3d 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -40,7 +40,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) if (IS_ERR(mxc_ahb_clk)) return PTR_ERR(mxc_ahb_clk); - ret = clk_enable(mxc_ahb_clk); + ret = clk_prepare_enable(mxc_ahb_clk); if (ret < 0) { dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n"); goto eenahb; @@ -65,7 +65,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) } } - ret = clk_enable(mxc_usb_clk); + ret = clk_prepare_enable(mxc_usb_clk); if (ret < 0) { dev_err(&pdev->dev, "clk_enable(\"usb_clk\") failed\n"); goto eenusb; @@ -79,7 +79,7 @@ eclkrate: mxc_usb_clk = NULL; egusb: if (!cpu_is_mx35()) - clk_disable(mxc_ahb_clk); + clk_disable_unprepare(mxc_ahb_clk); eenahb: if (!cpu_is_mx35()) clk_put(mxc_ahb_clk); @@ -104,7 +104,7 @@ void fsl_udc_clk_finalize(struct platform_device *pdev) /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { - clk_disable(mxc_usb_clk); + clk_disable_unprepare(mxc_usb_clk); clk_put(mxc_usb_clk); mxc_usb_clk = NULL; } @@ -113,11 +113,11 @@ void fsl_udc_clk_finalize(struct platform_device *pdev) void fsl_udc_clk_release(void) { if (mxc_usb_clk) { - clk_disable(mxc_usb_clk); + clk_disable_unprepare(mxc_usb_clk); clk_put(mxc_usb_clk); } if (!cpu_is_mx35()) { - clk_disable(mxc_ahb_clk); + clk_disable_unprepare(mxc_ahb_clk); clk_put(mxc_ahb_clk); } } -- GitLab From 8194fea0fc308a7cdfc9333584d69cb5d428d47f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 May 2012 20:14:54 -0300 Subject: [PATCH 0515/5711] usb: imx_udc.c: Use clk_prepare_enable/clk_disable_unprepare Prepare the clock before enabling it. Cc: Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Felipe Balbi --- drivers/usb/gadget/imx_udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 54034f84f992..dc5334856afe 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1432,7 +1432,7 @@ static int __init imx_udc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get USB clock\n"); goto fail2; } - clk_enable(clk); + clk_prepare_enable(clk); if (clk_get_rate(clk) != 48000000) { D_INI(&pdev->dev, @@ -1496,7 +1496,7 @@ fail4: free_irq(imx_usb->usbd_int[i], imx_usb); fail3: clk_put(clk); - clk_disable(clk); + clk_disable_unprepare(clk); fail2: iounmap(base); fail1: @@ -1521,7 +1521,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) free_irq(imx_usb->usbd_int[i], imx_usb); clk_put(imx_usb->clk); - clk_disable(imx_usb->clk); + clk_disable_unprepare(imx_usb->clk); iounmap(imx_usb->base); release_mem_region(imx_usb->res->start, resource_size(imx_usb->res)); -- GitLab From 2b97fb5a605635684f757080cdc405d8173838d5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 May 2012 20:14:55 -0300 Subject: [PATCH 0516/5711] usb: imx21-hcd.c: Use clk_prepare_enable/clk_disable_unprepare Prepare the clock before enabling it. Cc: Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Felipe Balbi --- drivers/usb/host/imx21-hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index ff471c1c165e..f19e2690c232 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1811,7 +1811,7 @@ static int imx21_remove(struct platform_device *pdev) usb_remove_hcd(hcd); if (res != NULL) { - clk_disable(imx21->clk); + clk_disable_unprepare(imx21->clk); clk_put(imx21->clk); iounmap(imx21->regs); release_mem_region(res->start, resource_size(res)); @@ -1884,7 +1884,7 @@ static int imx21_probe(struct platform_device *pdev) ret = clk_set_rate(imx21->clk, clk_round_rate(imx21->clk, 48000000)); if (ret) goto failed_clock_set; - ret = clk_enable(imx21->clk); + ret = clk_prepare_enable(imx21->clk); if (ret) goto failed_clock_enable; @@ -1900,7 +1900,7 @@ static int imx21_probe(struct platform_device *pdev) return 0; failed_add_hcd: - clk_disable(imx21->clk); + clk_disable_unprepare(imx21->clk); failed_clock_enable: failed_clock_set: clk_put(imx21->clk); -- GitLab From 83452c6a43d06dfbc7f78b0eafe6664c95a3895c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:18 +0200 Subject: [PATCH 0517/5711] x86/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: x86@kernel.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/x86/kernel/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 03920a15a632..1b27de563561 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -512,7 +512,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) /* Set correct numa_node information for AMD NB functions */ -static void __init quirk_amd_nb_node(struct pci_dev *dev) +static void __devinit quirk_amd_nb_node(struct pci_dev *dev) { struct pci_dev *nb_ht; unsigned int devfn; -- GitLab From b99ea85a3acff53151322a1c882f217375b1300e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:19 +0200 Subject: [PATCH 0518/5711] PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a7521677541..993cec88c5b4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx) * workaround applied too * [Info kindly provided by ALi] */ -static void __init quirk_alimagik(struct pci_dev *dev) +static void __devinit quirk_alimagik(struct pci_dev *dev) { if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) { dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n"); @@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic); -static void __init quirk_ioapic_rmw(struct pci_dev *dev) +static void __devinit quirk_ioapic_rmw(struct pci_dev *dev) { if (dev->devfn == 0 && dev->bus->number == 0) sis_apic_bug = 1; @@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw); * Some settings of MMRBC can lead to data corruption so block changes. * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide */ -static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev) +static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev) { if (dev->subordinate && dev->revision <= 0x12) { dev_info(&dev->dev, "AMD8131 rev %x detected; " @@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB /* * Intel 82801CAM ICH3-M datasheet says IDE modes must be the same */ -static void __init quirk_ide_samemode(struct pci_dev *pdev) +static void __devinit quirk_ide_samemode(struct pci_dev *pdev) { u8 prog; @@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. */ -static void __init quirk_eisa_bridge(struct pci_dev *dev) +static void __devinit quirk_eisa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_EISA << 8; } @@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e */ static int asus_hides_smbus; -static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) +static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev) { if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB) @@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3 #endif #ifdef CONFIG_X86_IO_APIC -static void __init quirk_alder_ioapic(struct pci_dev *pdev) +static void __devinit quirk_alder_ioapic(struct pci_dev *pdev) { int i; @@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, qui * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. * Re-allocate the region if needed... */ -static void __init quirk_tc86c001_ide(struct pci_dev *dev) +static void __devinit quirk_tc86c001_ide(struct pci_dev *dev) { struct resource *r = &dev->resource[0]; @@ -2169,7 +2169,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); * aware of it. Instead of setting the flag on all busses in the * machine, simply disable MSI globally. */ -static void __init quirk_disable_all_msi(struct pci_dev *dev) +static void __devinit quirk_disable_all_msi(struct pci_dev *dev) { pci_no_msi(); dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n"); -- GitLab From 8ff255afb022b8e183c7aa1ecc4ba8d0563e1e17 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:20 +0200 Subject: [PATCH 0519/5711] alpha/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/alpha/kernel/pci.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc16..026d49f28de3 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -59,15 +59,13 @@ struct pci_controller *pci_isa_hose; * Quirks. */ -static void __init -quirk_isa_bridge(struct pci_dev *dev) +static void __devinit quirk_isa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_ISA << 8; } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge); -static void __init -quirk_cypress(struct pci_dev *dev) +static void __devinit quirk_cypress(struct pci_dev *dev) { /* The Notorious Cy82C693 chip. */ @@ -106,8 +104,7 @@ quirk_cypress(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress); /* Called for each device after PCI setup is done. */ -static void __init -pcibios_fixup_final(struct pci_dev *dev) +static void __devinit pcibios_fixup_final(struct pci_dev *dev) { unsigned int class = dev->class >> 8; -- GitLab From f39acb1f00059a7fada1971dcd6374fbff9b3238 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:21 +0200 Subject: [PATCH 0520/5711] arm/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Russell King Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/arm/kernel/bios32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 25552508c3fd..1c1a0e237a33 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -253,7 +253,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); -static void __init pci_fixup_it8152(struct pci_dev *dev) +static void __devinit pci_fixup_it8152(struct pci_dev *dev) { int i; /* fixup for ITE 8152 devices */ -- GitLab From a9149164280718ac244d5b5a246de5746f6aad4b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:22 +0200 Subject: [PATCH 0521/5711] frv/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: David Howells Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/frv/mb93090-mb00/pci-vdk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 6b0b82ff4419..d04ed14bbf0c 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -268,7 +268,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d) d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } -static void __init pci_fixup_ide_bases(struct pci_dev *d) +static void __devinit pci_fixup_ide_bases(struct pci_dev *d) { int i; @@ -287,7 +287,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } -static void __init pci_fixup_ide_trash(struct pci_dev *d) +static void __devinit pci_fixup_ide_trash(struct pci_dev *d) { int i; -- GitLab From 9eb07a7fb8a90ee39fa9d5489afc0330cfcfbea7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 4 Jun 2012 13:27:43 -0300 Subject: [PATCH 0522/5711] edac: edac_mc_handle_error(): add an error_count parameter In order to avoid loosing error events, it is desirable to group error events together and generate a single trace for several identical errors. The trace API already allows reporting multiple errors. Change the handle_error function to also allow that. The changes at the drivers were made by this small script: $file .=$_ while (<>); $file =~ s/(edac_mc_handle_error)\s*\(([^\,]+)\,([^\,]+)\,/$1($2,$3, 1,/g; print $file; Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 22 ++++++------- drivers/edac/amd76x_edac.c | 4 +-- drivers/edac/cell_edac.c | 4 +-- drivers/edac/cpc925_edac.c | 4 +-- drivers/edac/e752x_edac.c | 8 ++--- drivers/edac/e7xxx_edac.c | 8 ++--- drivers/edac/edac_core.h | 1 + drivers/edac/edac_mc.c | 56 +++++++++++++++++++--------------- drivers/edac/edac_mc_sysfs.c | 2 +- drivers/edac/i3000_edac.c | 6 ++-- drivers/edac/i3200_edac.c | 6 ++-- drivers/edac/i5000_edac.c | 8 ++--- drivers/edac/i5100_edac.c | 4 +-- drivers/edac/i5400_edac.c | 4 +-- drivers/edac/i7300_edac.c | 4 +-- drivers/edac/i7core_edac.c | 4 +-- drivers/edac/i82443bxgx_edac.c | 4 +-- drivers/edac/i82860_edac.c | 6 ++-- drivers/edac/i82875p_edac.c | 6 ++-- drivers/edac/i82975x_edac.c | 6 ++-- drivers/edac/mpc85xx_edac.c | 4 +-- drivers/edac/mv64x60_edac.c | 4 +-- drivers/edac/pasemi_edac.c | 4 +-- drivers/edac/ppc4xx_edac.c | 4 +-- drivers/edac/r82600_edac.c | 4 +-- drivers/edac/sb_edac.c | 4 +-- drivers/edac/tile_edac.c | 2 +- drivers/edac/x38_edac.c | 6 ++-- 28 files changed, 104 insertions(+), 95 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 6231cbe6e7c1..5a297a26211d 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1046,7 +1046,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, if (!src_mci) { amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a node", @@ -1057,7 +1057,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, /* Now map the sys_addr to a CSROW */ csrow = sys_addr_to_csrow(src_mci, sys_addr); if (csrow < 0) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a csrow", @@ -1077,7 +1077,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, amd64_mc_warn(src_mci, "unknown syndrome 0x%04x - " "possible error reporting race\n", syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, csrow, -1, -1, "unknown syndrome - possible error reporting race", @@ -1096,7 +1096,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, channel = ((sys_addr & BIT(3)) != 0); } - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, 1, page, offset, syndrome, csrow, channel, -1, "", ""); @@ -1608,7 +1608,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); if (csrow < 0) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, "failed to map error addr to a csrow", @@ -1624,7 +1624,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, if (dct_ganging_enabled(pvt)) chan = get_channel_from_ecc_syndrome(mci, syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, csrow, chan, -1, "", ""); @@ -1909,7 +1909,7 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m) /* Ensure that the Error Address is VALID */ if (!(m->status & MCI_STATUS_ADDRV)) { amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "HW has no ERROR_ADDRESS available", @@ -1937,7 +1937,7 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (!(m->status & MCI_STATUS_ADDRV)) { amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "HW has no ERROR_ADDRESS available", @@ -1956,7 +1956,7 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (!src_mci) { amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, -1, -1, -1, "ERROR ADDRESS NOT mapped to a MC", @@ -1970,13 +1970,13 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (csrow < 0) { amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, -1, -1, -1, "ERROR ADDRESS NOT mapped to CS", ""); } else { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, csrow, -1, -1, "", ""); diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index c7c208eae233..29eeb68a200c 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -145,7 +145,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = (info->ecc_mode_status >> 4) & 0xf; - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, mci->csrows[row]->first_page, 0, 0, row, 0, -1, mci->ctl_name, ""); @@ -160,7 +160,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = info->ecc_mode_status & 0xf; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, mci->csrows[row]->first_page, 0, 0, row, 0, -1, mci->ctl_name, ""); diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 165d255e627d..a1bbd8edd257 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -48,7 +48,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) syndrome = (ar & 0x000000001fe00000ul) >> 21; /* TODO: Decoding of the error address */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, csrow->first_page + pfn, offset, syndrome, 0, chan, -1, "", ""); } @@ -70,7 +70,7 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) offset = address & ~PAGE_MASK; /* TODO: Decoding of the error address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, csrow->first_page + pfn, offset, 0, 0, chan, -1, "", ""); } diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 32e9c88dbde9..c2ef13495873 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -554,7 +554,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) if (apiexcp & CECC_EXCP_DETECTED) { cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n"); channel = cpc925_mc_find_channel(mci, syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, syndrome, csrow, channel, -1, mci->ctl_name, ""); @@ -562,7 +562,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) if (apiexcp & UECC_EXCP_DETECTED) { cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n"); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, 0, csrow, -1, -1, mci->ctl_name, ""); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index b5a8bf1292ac..a5ed6b795fd4 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -371,7 +371,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, channel = !(error_one & 1); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset_in_page(sec1_add << 4), sec1_syndrome, row, channel, -1, "e752x CE", ""); @@ -408,7 +408,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, edac_mc_find_csrow_by_page(mci, block_page); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, @@ -427,7 +427,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, edac_mc_find_csrow_by_page(mci, block_page); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, @@ -454,7 +454,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, return; edac_dbg(3, "\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "e752x UE log memory write", ""); } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index c26b69e70039..9ff57f361a43 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -219,14 +219,14 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) row = edac_mc_find_csrow_by_page(mci, page); /* convert syndrome to channel */ channel = e7xxx_find_channel(syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, 0, syndrome, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, 0, syndrome, row, channel, -1, "e7xxx CE", ""); } static void process_ce_no_info(struct mem_ctl_info *mci) { edac_dbg(3, "\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "e7xxx CE log register overflow", ""); } @@ -242,7 +242,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) block_page = error_2b >> 6; /* convert to 4k address */ row = edac_mc_find_csrow_by_page(mci, block_page); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, block_page, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, 0, 0, row, -1, -1, "e7xxx UE", ""); } @@ -250,7 +250,7 @@ static void process_ue_no_info(struct mem_ctl_info *mci) { edac_dbg(3, "\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "e7xxx UE log register overflow", ""); } diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 500ba6698986..3843222e5b9f 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -455,6 +455,7 @@ extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page); void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, + const u16 error_count, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index fb41e38c6891..8d59378f839c 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -897,15 +897,16 @@ const char *edac_layer_name[] = { EXPORT_SYMBOL_GPL(edac_layer_name); static void edac_inc_ce_error(struct mem_ctl_info *mci, - bool enable_per_layer_report, - const int pos[EDAC_MAX_LAYERS]) + bool enable_per_layer_report, + const int pos[EDAC_MAX_LAYERS], + const u16 count) { int i, index = 0; - mci->ce_mc++; + mci->ce_mc += count; if (!enable_per_layer_report) { - mci->ce_noinfo_count++; + mci->ce_noinfo_count += count; return; } @@ -913,7 +914,7 @@ static void edac_inc_ce_error(struct mem_ctl_info *mci, if (pos[i] < 0) break; index += pos[i]; - mci->ce_per_layer[i][index]++; + mci->ce_per_layer[i][index] += count; if (i < mci->n_layers - 1) index *= mci->layers[i + 1].size; @@ -922,14 +923,15 @@ static void edac_inc_ce_error(struct mem_ctl_info *mci, static void edac_inc_ue_error(struct mem_ctl_info *mci, bool enable_per_layer_report, - const int pos[EDAC_MAX_LAYERS]) + const int pos[EDAC_MAX_LAYERS], + const u16 count) { int i, index = 0; - mci->ue_mc++; + mci->ue_mc += count; if (!enable_per_layer_report) { - mci->ce_noinfo_count++; + mci->ce_noinfo_count += count; return; } @@ -937,7 +939,7 @@ static void edac_inc_ue_error(struct mem_ctl_info *mci, if (pos[i] < 0) break; index += pos[i]; - mci->ue_per_layer[i][index]++; + mci->ue_per_layer[i][index] += count; if (i < mci->n_layers - 1) index *= mci->layers[i + 1].size; @@ -945,6 +947,7 @@ static void edac_inc_ue_error(struct mem_ctl_info *mci, } static void edac_ce_error(struct mem_ctl_info *mci, + const u16 error_count, const int pos[EDAC_MAX_LAYERS], const char *msg, const char *location, @@ -961,16 +964,18 @@ static void edac_ce_error(struct mem_ctl_info *mci, if (edac_mc_get_log_ce()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s %s - %s)\n", + "%d CE %s on %s (%s %s - %s)\n", + error_count, msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s %s)\n", + "%d CE %s on %s (%s %s)\n", + error_count, msg, label, location, detail); } - edac_inc_ce_error(mci, enable_per_layer_report, pos); + edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count); if (mci->scrub_mode & SCRUB_SW_SRC) { /* @@ -994,6 +999,7 @@ static void edac_ce_error(struct mem_ctl_info *mci, } static void edac_ue_error(struct mem_ctl_info *mci, + const u16 error_count, const int pos[EDAC_MAX_LAYERS], const char *msg, const char *location, @@ -1005,12 +1011,14 @@ static void edac_ue_error(struct mem_ctl_info *mci, if (edac_mc_get_log_ue()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s %s - %s)\n", + "%d UE %s on %s (%s %s - %s)\n", + error_count, msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s %s)\n", + "%d UE %s on %s (%s %s)\n", + error_count, msg, label, location, detail); } @@ -1023,7 +1031,7 @@ static void edac_ue_error(struct mem_ctl_info *mci, msg, label, location, detail); } - edac_inc_ue_error(mci, enable_per_layer_report, pos); + edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count); } #define OTHER_LABEL " or " @@ -1033,6 +1041,7 @@ static void edac_ue_error(struct mem_ctl_info *mci, * * @type: severity of the error (CE/UE/Fatal) * @mci: a struct mem_ctl_info pointer + * @error_count: Number of errors of the same type * @page_frame_number: mem page where the error occurred * @offset_in_page: offset of the error inside the page * @syndrome: ECC syndrome @@ -1047,6 +1056,7 @@ static void edac_ue_error(struct mem_ctl_info *mci, */ void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, + const u16 error_count, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, @@ -1065,7 +1075,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, int i; long grain; bool enable_per_layer_report = false; - u16 error_count; /* FIXME: make it a parameter */ u8 grain_bits; edac_dbg(3, "MC%d\n", mci->mc_idx); @@ -1169,13 +1178,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, strcpy(label, "unknown memory"); if (type == HW_EVENT_ERR_CORRECTED) { if (row >= 0) { - mci->csrows[row]->ce_count++; + mci->csrows[row]->ce_count += error_count; if (chan >= 0) - mci->csrows[row]->channels[chan]->ce_count++; + mci->csrows[row]->channels[chan]->ce_count += error_count; } } else if (row >= 0) - mci->csrows[row]->ue_count++; + mci->csrows[row]->ue_count += error_count; } /* Fill the RAM location data */ @@ -1193,7 +1202,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, /* Report the error via the trace interface */ - error_count = 1; /* FIXME: allow change it */ grain_bits = fls_long(grain) + 1; trace_mc_event(type, msg, label, error_count, mci->mc_idx, top_layer, mid_layer, low_layer, @@ -1206,16 +1214,16 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, "page:0x%lx offset:0x%lx grain:%ld syndrome:0x%lx", page_frame_number, offset_in_page, grain, syndrome); - edac_ce_error(mci, pos, msg, location, label, detail, - other_detail, enable_per_layer_report, + edac_ce_error(mci, error_count, pos, msg, location, label, + detail, other_detail, enable_per_layer_report, page_frame_number, offset_in_page, grain); } else { snprintf(detail, sizeof(detail), "page:0x%lx offset:0x%lx grain:%ld", page_frame_number, offset_in_page, grain); - edac_ue_error(mci, pos, msg, location, label, detail, - other_detail, enable_per_layer_report); + edac_ue_error(mci, error_count, pos, msg, location, label, + detail, other_detail, enable_per_layer_report); } } EXPORT_SYMBOL_GPL(edac_mc_handle_error); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 107e7a71678e..55b2f0a18d22 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -823,7 +823,7 @@ static ssize_t edac_fake_inject_write(struct file *file, mci->fake_inject_layer[1], mci->fake_inject_layer[2] ); - edac_mc_handle_error(type, mci, 0, 0, 0, + edac_mc_handle_error(type, mci, 1, 0, 0, 0, mci->fake_inject_layer[0], mci->fake_inject_layer[1], mci->fake_inject_layer[2], diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index dd07bea34078..d3d19cc4e9a1 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -245,7 +245,7 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; @@ -258,12 +258,12 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, row = edac_mc_find_csrow_by_page(mci, pfn); if (info->errsts & I3000_ERRSTS_UE) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, pfn, offset, 0, row, -1, -1, "i3000 UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, info->derrsyn, row, multi_chan ? channel : 0, -1, "i3000 CE", ""); diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 07ae4426b5df..47180a08edad 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -218,7 +218,7 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, return; if ((info->errsts ^ info->errsts2) & I3200_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -226,13 +226,13 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, for (channel = 0; channel < nr_channels; channel++) { log = info->eccerrlog[channel]; if (log & I3200_ECCERRLOG_UE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, "i3000 UE", ""); } else if (log & I3200_ECCERRLOG_CE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 0406f0d4dd2f..a5c33df520ac 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -519,7 +519,7 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, bank, ras, cas, allErrors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0, channel >> 1, channel & 1, rank, rdwr ? "Write error" : "Read error", msg); @@ -618,7 +618,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, rank, bank, ras, cas, ue_errors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, channel >> 1, -1, rank, rdwr ? "Write error" : "Read error", msg); @@ -672,7 +672,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, channel >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", msg); @@ -718,7 +718,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, "Err=%#x (%s)", misc_errors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, branch >> 1, -1, -1, "Misc error", msg); } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 1e5c8f668652..c4b5e5f868e8 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -431,7 +431,7 @@ static void i5100_handle_ce(struct mem_ctl_info *mci, "bank %u, cas %u, ras %u\n", bank, cas, ras); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, syndrome, chan, rank, -1, msg, detail); @@ -453,7 +453,7 @@ static void i5100_handle_ue(struct mem_ctl_info *mci, "bank %u, cas %u, ras %u\n", bank, cas, ras); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, syndrome, chan, rank, -1, msg, detail); diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index f2bfc2660158..50069c62c8d4 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -554,7 +554,7 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, "Bank=%d Buffer ID = %d RAS=%d CAS=%d Err=0x%lx (%s)", bank, buf_id, ras, cas, allErrors, error_name[errnum]); - edac_mc_handle_error(tp_event, mci, 0, 0, 0, + edac_mc_handle_error(tp_event, mci, 1, 0, 0, 0, branch >> 1, -1, rank, rdwr ? "Write error" : "Read error", msg); @@ -626,7 +626,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, branch >> 1, bank, rdwr_str(rdwr), ras, cas, allErrors, error_name[errnum]); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, branch >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", msg); diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 4a8835fd12bd..a09d0667f72a 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -449,7 +449,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) "Bank=%d RAS=%d CAS=%d Err=0x%lx (%s))", bank, ras, cas, errors, specific); - edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0, branch, -1, rank, is_wr ? "Write error" : "Read error", pvt->tmp_prt_buffer); @@ -495,7 +495,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) "DRAM-Bank=%d RAS=%d CAS=%d, Err=0x%lx (%s))", bank, ras, cas, errors, specific); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, syndrome, branch >> 1, channel % 2, rank, is_wr ? "Write error" : "Read error", diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index aba8d5190330..a95686e22416 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1544,7 +1544,7 @@ static void i7core_rdimm_update_errcount(struct mem_ctl_info *mci, int i; for (i = 0; i < add; i++) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, chan, dimm, -1, "error", ""); } } @@ -1796,7 +1796,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, * only one event */ if (uncorrected_error || !pvt->is_registered) - edac_mc_handle_error(tp_event, mci, + edac_mc_handle_error(tp_event, mci, 1, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, syndrome, diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 1c414a87195e..90f303db5d1d 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -156,7 +156,7 @@ static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci, if (info->eap & I82443BXGX_EAP_OFFSET_SBE) { error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), 0, -1, mci->ctl_name, ""); @@ -165,7 +165,7 @@ static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci, if (info->eap & I82443BXGX_EAP_OFFSET_MBE) { error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), 0, -1, mci->ctl_name, ""); diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index ff4f590e9b90..1faa74971513 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -109,7 +109,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0003) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -119,12 +119,12 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, dimm = mci->csrows[row]->channels[0]->dimm; if (info->errsts & 0x0002) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, 0, dimm->location[0], dimm->location[1], -1, "i82860 UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, info->derrsyn, dimm->location[0], dimm->location[1], -1, "i82860 CE", ""); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 2e3f306c9c72..3e416b1a6b53 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -236,7 +236,7 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0081) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; @@ -246,12 +246,12 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, row = edac_mc_find_csrow_by_page(mci, info->eap); if (info->errsts & 0x0080) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, 0, row, -1, -1, "i82875p UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, info->eap, 0, info->derrsyn, row, multi_chan ? (info->des & 0x1) : 0, -1, "i82875p CE", ""); diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index c95ebe5e4d60..069e26c11c4f 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -288,7 +288,7 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0003) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -314,12 +314,12 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, (1 << mci->csrows[row]->channels[chan]->dimm->grain)); if (info->errsts & 0x0002) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offst, 0, row, -1, -1, "i82975x UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offst, info->derrsyn, row, chan ? chan : 0, -1, "i82975x CE", ""); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 56e79a053fe6..117cf00bd743 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -866,13 +866,13 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n"); if (err_detect & DDR_EDE_SBE) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, mci->ctl_name, ""); if (err_detect & DDR_EDE_MBE) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, mci->ctl_name, ""); diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index e491a297f5ec..2b315c2edc3c 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -611,13 +611,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ if (!(reg & 0x1)) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, syndrome, 0, 0, -1, mci->ctl_name, ""); else /* 2 bit error, UE */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, 0, 0, 0, -1, diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 04851be51612..2d35b78ada3c 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -110,14 +110,14 @@ static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) /* uncorrectable/multi-bit errors */ if (errsta & (MCDEBUG_ERRSTA_MBE_STATUS | MCDEBUG_ERRSTA_RFL_STATUS)) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, mci->csrows[cs]->first_page, 0, 0, cs, 0, -1, mci->ctl_name, ""); } /* correctable/single-bit errors */ if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, mci->csrows[cs]->first_page, 0, 0, cs, 0, -1, mci->ctl_name, ""); } diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index 67a29201dae7..bf0957635991 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -727,7 +727,7 @@ ppc4xx_edac_handle_ce(struct mem_ctl_info *mci, for (row = 0; row < mci->nr_csrows; row++) if (ppc4xx_edac_check_bank_error(status, row)) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, row, 0, -1, message, ""); @@ -758,7 +758,7 @@ ppc4xx_edac_handle_ue(struct mem_ctl_info *mci, for (row = 0; row < mci->nr_csrows; row++) if (ppc4xx_edac_check_bank_error(status, row)) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, row, 0, -1, message, ""); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index aa10178397fe..f854debd5533 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -179,7 +179,7 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, 0, syndrome, edac_mc_find_csrow_by_page(mci, page), 0, -1, @@ -191,7 +191,7 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, if (handle_errors) /* 82600 doesn't give enough info */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, 0, 0, edac_mc_find_csrow_by_page(mci, page), 0, -1, diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index ae18d9849cc7..2809b07cbb01 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1447,13 +1447,13 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, /* FIXME: need support for channel mask */ /* Call the helper to output message */ - edac_mc_handle_error(tp_event, mci, + edac_mc_handle_error(tp_event, mci, 1, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, channel, dimm, -1, optype, msg); return; err_parsing: - edac_mc_handle_error(tp_event, mci, 0, 0, 0, + edac_mc_handle_error(tp_event, mci, 1, 0, 0, 0, -1, -1, -1, msg, ""); diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 0589f56aa568..1e904b7b79a0 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -71,7 +71,7 @@ static void tile_edac_check(struct mem_ctl_info *mci) if (mem_error.sbe_count != priv->ce_count) { dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node); priv->ce_count = mem_error.sbe_count; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, 0, 0, -1, mci->ctl_name, ""); diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 3d46d40987af..08a992693e62 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -215,7 +215,7 @@ static void x38_process_error_info(struct mem_ctl_info *mci, return; if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; @@ -224,13 +224,13 @@ static void x38_process_error_info(struct mem_ctl_info *mci, for (channel = 0; channel < x38_channel_num; channel++) { log = info->eccerrlog[channel]; if (log & X38_ECCERRLOG_UE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, "x38 UE", ""); } else if (log & X38_ECCERRLOG_CE) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, -- GitLab From 00d18339276d35bc6b7ae6ae1a64ebf2242b89f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 4 Jun 2012 13:38:52 -0300 Subject: [PATCH 0523/5711] i7core_edac: properly handle error count Instead of generating a burst of errors or reporting the error count via driver-specific details, use the new way provided by edac_mc_handle_error. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index a95686e22416..a3c9a37b4cc1 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1536,18 +1536,6 @@ error: /**************************************************************************** Error check routines ****************************************************************************/ -static void i7core_rdimm_update_errcount(struct mem_ctl_info *mci, - const int chan, - const int dimm, - const int add) -{ - int i; - - for (i = 0; i < add; i++) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, - chan, dimm, -1, "error", ""); - } -} static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci, const int chan, @@ -1586,12 +1574,17 @@ static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci, /*updated the edac core */ if (add0 != 0) - i7core_rdimm_update_errcount(mci, chan, 0, add0); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add0, + 0, 0, 0, + chan, 0, -1, "error", ""); if (add1 != 0) - i7core_rdimm_update_errcount(mci, chan, 1, add1); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add1, + 0, 0, 0, + chan, 1, -1, "error", ""); if (add2 != 0) - i7core_rdimm_update_errcount(mci, chan, 2, add2); - + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add2, + 0, 0, 0, + chan, 2, -1, "error", ""); } static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci) @@ -1710,7 +1703,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, const struct mce *m) { struct i7core_pvt *pvt = mci->pvt_info; - char *type, *optype, *err, msg[80]; + char *type, *optype, *err; enum hw_event_mc_err_type tp_event; unsigned long error = m->status & 0x1ff0000l; bool uncorrected_error = m->mcgstatus & 1ll << 61; @@ -1788,20 +1781,18 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, err = "unknown"; } - snprintf(msg, sizeof(msg), "count=%d %s", core_err_cnt, optype); - /* * Call the helper to output message * FIXME: what to do if core_err_cnt > 1? Currently, it generates * only one event */ if (uncorrected_error || !pvt->is_registered) - edac_mc_handle_error(tp_event, mci, 1, + edac_mc_handle_error(tp_event, mci, core_err_cnt, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, syndrome, channel, dimm, -1, - err, msg); + err, optype); } /* -- GitLab From c10538396bf3f0076630103ede49c863c27db720 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 4 Jun 2012 13:40:05 -0300 Subject: [PATCH 0524/5711] sb_edac: properly handle error count Instead of reporting the error count via driver-specific details, use the new way provided by edac_mc_handle_error. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/sb_edac.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 2809b07cbb01..6f8861369e7d 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1432,8 +1432,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, * to the group of dimm's where the error may be happening. */ snprintf(msg, sizeof(msg), - "count:%d%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", - core_err_cnt, + "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", overflow ? " OVERFLOW" : "", (uncorrected_error && recoverable) ? " recoverable" : "", area_type, @@ -1447,13 +1446,13 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, /* FIXME: need support for channel mask */ /* Call the helper to output message */ - edac_mc_handle_error(tp_event, mci, 1, + edac_mc_handle_error(tp_event, mci, core_err_cnt, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, channel, dimm, -1, optype, msg); return; err_parsing: - edac_mc_handle_error(tp_event, mci, 1, 0, 0, 0, + edac_mc_handle_error(tp_event, mci, core_err_cnt, 0, 0, 0, -1, -1, -1, msg, ""); -- GitLab From e7930ba49e469d9ce7374a788336caf955f8d7e2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 11 Jun 2012 21:32:12 -0500 Subject: [PATCH 0525/5711] edac: create top-level debugfs directory Create a single, top-level "edac" directory for debugfs. An "mc[0-N]" directory is then created for each memory controller. Individual drivers can create additional entries such as h/w error injection control. Signed-off-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/edac_mc_sysfs.c | 23 ++++++++++++++++++++++- drivers/edac/edac_module.c | 3 +++ drivers/edac/edac_module.h | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 55b2f0a18d22..a2bf7e9dd6de 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -899,13 +899,33 @@ static struct device_type mci_attr_type = { }; #ifdef CONFIG_EDAC_DEBUG +static struct dentry *edac_debugfs; + +int __init edac_debugfs_init(void) +{ + edac_debugfs = debugfs_create_dir("edac", NULL); + if (IS_ERR(edac_debugfs)) { + edac_debugfs = NULL; + return -ENOMEM; + } + return 0; +} + +void __exit edac_debugfs_exit(void) +{ + debugfs_remove(edac_debugfs); +} + int edac_create_debug_nodes(struct mem_ctl_info *mci) { struct dentry *d, *parent; char name[80]; int i; - d = debugfs_create_dir(mci->dev.kobj.name, mci->debugfs); + if (!edac_debugfs) + return -ENODEV; + + d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs); if (!d) return -ENOMEM; parent = d; @@ -930,6 +950,7 @@ int edac_create_debug_nodes(struct mem_ctl_info *mci) if (!d) goto nomem; + mci->debugfs = parent; return 0; nomem: debugfs_remove(mci->debugfs); diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 3454798c270e..58a28d838f37 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -94,6 +94,8 @@ static int __init edac_init(void) if (err) goto error; + edac_debugfs_init(); + /* Setup/Initialize the workq for this core */ err = edac_workqueue_setup(); if (err) { @@ -118,6 +120,7 @@ static void __exit edac_exit(void) /* tear down the various subsystems */ edac_workqueue_teardown(); edac_mc_sysfs_exit(); + edac_debugfs_exit(); } /* diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 62de640c8c8a..3d139c6e7fe3 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -56,6 +56,20 @@ extern void edac_mc_reset_delay_period(int value); extern void *edac_align_ptr(void **p, unsigned size, int n_elems); +/* + * EDAC debugfs functions + */ +#ifdef CONFIG_EDAC_DEBUG +int edac_debugfs_init(void); +void edac_debugfs_exit(void); +#else +static inline int edac_debugfs_init(void) +{ + return -ENODEV; +} +static inline void edac_debugfs_exit(void) {} +#endif + /* * EDAC PCI functions */ -- GitLab From ad805758c0eb25bce7b2e3b298d63dc62a1bc71c Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 11 Jun 2012 05:27:07 +0000 Subject: [PATCH 0526/5711] PCI: add ACS validation utility In a PCI environment, transactions aren't always required to reach the root bus before being re-routed. Intermediate switches between an endpoint and the root bus can redirect DMA back downstream before things like IOMMUs have a chance to intervene. Legacy PCI is always susceptible to this as it operates on a shared bus. PCIe added a new capability to describe and control this behavior, Access Control Services, or ACS. The utility function pci_acs_enabled() allows us to test the ACS capabilities of an individual devices against a set of flags while pci_acs_path_enabled() tests a complete path from a given downstream device up to the specified upstream device. We also include the ability to add device specific tests as it's likely we'll see devices that do not implement ACS, but want to indicate support for various capabilities in this space. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/quirks.c | 33 +++++++++++++++++++++ include/linux/pci.h | 10 ++++++- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..1ccf7d49f522 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2359,6 +2359,75 @@ void pci_enable_acs(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); } +/** + * pci_acs_enabled - test ACS against required flags for a given device + * @pdev: device to test + * @acs_flags: required PCI ACS flags + * + * Return true if the device supports the provided flags. Automatically + * filters out flags that are not implemented on multifunction devices. + */ +bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) +{ + int pos, ret; + u16 ctrl; + + ret = pci_dev_specific_acs_enabled(pdev, acs_flags); + if (ret >= 0) + return ret > 0; + + if (!pci_is_pcie(pdev)) + return false; + + /* Filter out flags not applicable to multifunction */ + if (pdev->multifunction) + acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | + PCI_ACS_EC | PCI_ACS_DT); + + if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM || + pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + pdev->multifunction) { + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return false; + + pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); + if ((ctrl & acs_flags) != acs_flags) + return false; + } + + return true; +} + +/** + * pci_acs_path_enable - test ACS flags from start to end in a hierarchy + * @start: starting downstream device + * @end: ending upstream device or NULL to search to the root bus + * @acs_flags: required flags + * + * Walk up a device tree from start to end testing PCI ACS support. If + * any step along the way does not support the required flags, return false. + */ +bool pci_acs_path_enabled(struct pci_dev *start, + struct pci_dev *end, u16 acs_flags) +{ + struct pci_dev *pdev, *parent = start; + + do { + pdev = parent; + + if (!pci_acs_enabled(pdev, acs_flags)) + return false; + + if (pci_is_root_bus(pdev->bus)) + return (end == NULL); + + parent = pdev->bus->self; + } while (pdev != end); + + return true; +} + /** * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge * @dev: the PCI device diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index acd3956b44bd..27e2c8f4ec73 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3230,3 +3230,36 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev) return pci_dev_get(dev); } + +static const struct pci_dev_acs_enabled { + u16 vendor; + u16 device; + int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags); +} pci_dev_acs_enabled[] = { + { 0 } +}; + +int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) +{ + const struct pci_dev_acs_enabled *i; + int ret; + + /* + * Allow devices that do not expose standard PCIe ACS capabilities + * or control to indicate their support here. Multi-function express + * devices which do not allow internal peer-to-peer between functions, + * but do not implement PCIe ACS may wish to return true here. + */ + for (i = pci_dev_acs_enabled; i->acs_enabled; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) { + ret = i->acs_enabled(dev, acs_flags); + if (ret >= 0) + return ret; + } + } + + return -ENOTTY; +} diff --git a/include/linux/pci.h b/include/linux/pci.h index 39983be7b25b..dd7af0f37b3a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1490,6 +1490,7 @@ enum pci_fixup_pass { #ifdef CONFIG_PCI_QUIRKS void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); struct pci_dev *pci_get_dma_source(struct pci_dev *dev); +int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); #else static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} @@ -1497,6 +1498,11 @@ static inline struct pci_dev *pci_get_dma_source(struct pci_dev *dev) { return pci_dev_get(dev); } +static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, + u16 acs_flags) +{ + return -ENOTTY; +} #endif void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); @@ -1599,7 +1605,9 @@ static inline bool pci_is_pcie(struct pci_dev *dev) } void pci_request_acs(void); - +bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags); +bool pci_acs_path_enabled(struct pci_dev *start, + struct pci_dev *end, u16 acs_flags); #define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */ #define PCI_VPD_LRDT_ID(x) (x | PCI_VPD_LRDT) -- GitLab From c63587d7f5b9db84e71daf5962dc0394eb657da2 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 11 Jun 2012 05:27:19 +0000 Subject: [PATCH 0527/5711] PCI: export pci_user functions for use by other drivers VFIO PCI support will make use of these for user-initiated PCI config accesses. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/access.c | 6 ++++-- drivers/pci/pci.h | 7 ------- include/linux/pci.h | 8 ++++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2a581642c237..ba91a7e17519 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -162,7 +162,8 @@ int pci_user_read_config_##size \ if (ret > 0) \ ret = -EINVAL; \ return ret; \ -} +} \ +EXPORT_SYMBOL_GPL(pci_user_read_config_##size); /* Returns 0 on success, negative values indicate error. */ #define PCI_USER_WRITE_CONFIG(size,type) \ @@ -181,7 +182,8 @@ int pci_user_write_config_##size \ if (ret > 0) \ ret = -EINVAL; \ return ret; \ -} +} \ +EXPORT_SYMBOL_GPL(pci_user_write_config_##size); PCI_USER_READ_CONFIG(byte, u8) PCI_USER_READ_CONFIG(word, u16) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e4943479b234..f2dcc46bdece 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -86,13 +86,6 @@ static inline bool pci_is_bridge(struct pci_dev *pci_dev) return !!(pci_dev->subordinate); } -extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); -extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); -extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val); -extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val); -extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val); -extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val); - struct pci_vpd_ops { ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf); ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); diff --git a/include/linux/pci.h b/include/linux/pci.h index dd7af0f37b3a..9d04599c6bd9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -777,6 +777,14 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where, return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); } +/* user-space driven config access */ +int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); +int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); +int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val); +int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val); +int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val); +int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val); + int __must_check pci_enable_device(struct pci_dev *dev); int __must_check pci_enable_device_io(struct pci_dev *dev); int __must_check pci_enable_device_mem(struct pci_dev *dev); -- GitLab From a6961651408afa9387d6df43c4a1dc4fd35dcb1b Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 11 Jun 2012 05:27:33 +0000 Subject: [PATCH 0528/5711] PCI: create common pcibios_err_to_errno For returning errors out to non-PCI code. Re-name xen's version. Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/xen/xen-pciback/conf_space.c | 6 +++--- include/linux/pci.h | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c index 30d7be026c18..46ae0f9f02ad 100644 --- a/drivers/xen/xen-pciback/conf_space.c +++ b/drivers/xen/xen-pciback/conf_space.c @@ -124,7 +124,7 @@ static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask, return val; } -static int pcibios_err_to_errno(int err) +static int xen_pcibios_err_to_errno(int err) { switch (err) { case PCIBIOS_SUCCESSFUL: @@ -202,7 +202,7 @@ out: pci_name(dev), size, offset, value); *ret_val = value; - return pcibios_err_to_errno(err); + return xen_pcibios_err_to_errno(err); } int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value) @@ -290,7 +290,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value) } } - return pcibios_err_to_errno(err); + return xen_pcibios_err_to_errno(err); } void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index 9d04599c6bd9..a691f62bcf89 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -474,6 +474,32 @@ static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) { return false; #define PCIBIOS_SET_FAILED 0x88 #define PCIBIOS_BUFFER_TOO_SMALL 0x89 +/* + * Translate above to generic errno for passing back through non-pci. + */ +static inline int pcibios_err_to_errno(int err) +{ + if (err <= PCIBIOS_SUCCESSFUL) + return err; /* Assume already errno */ + + switch (err) { + case PCIBIOS_FUNC_NOT_SUPPORTED: + return -ENOENT; + case PCIBIOS_BAD_VENDOR_ID: + return -EINVAL; + case PCIBIOS_DEVICE_NOT_FOUND: + return -ENODEV; + case PCIBIOS_BAD_REGISTER_NUMBER: + return -EFAULT; + case PCIBIOS_SET_FAILED: + return -EIO; + case PCIBIOS_BUFFER_TOO_SMALL: + return -ENOSPC; + } + + return -ENOTTY; +} + /* Low-level architecture-dependent routines */ struct pci_ops { -- GitLab From a0dee2ed0cdc666b5622f1fc74979355a6b36850 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 11 Jun 2012 05:27:45 +0000 Subject: [PATCH 0529/5711] PCI: misc pci_reg additions Fill in many missing definitions and add sizeof fields for many sections allowing for more extensive config parsing. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- include/linux/pci_regs.h | 113 ++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 4b608f543412..526d2c4bc3a6 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -26,6 +26,7 @@ * Under PCI, each device has 256 bytes of configuration address space, * of which the first 64 bytes are standardized as follows: */ +#define PCI_STD_HEADER_SIZEOF 64 #define PCI_VENDOR_ID 0x00 /* 16 bits */ #define PCI_DEVICE_ID 0x02 /* 16 bits */ #define PCI_COMMAND 0x04 /* 16 bits */ @@ -209,9 +210,12 @@ #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ #define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ #define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ +#define PCI_CAP_ID_SECDEV 0x0F /* Secure Device */ #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ +#define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */ #define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */ +#define PCI_CAP_ID_MAX PCI_CAP_ID_AF #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ #define PCI_CAP_SIZEOF 4 @@ -276,6 +280,7 @@ #define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ #define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ #define PCI_VPD_DATA 4 /* 32-bits of data returned here */ +#define PCI_CAP_VPD_SIZEOF 8 /* Slot Identification */ @@ -297,8 +302,10 @@ #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ #define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */ +#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */ #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ #define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */ +#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */ /* MSI-X registers */ #define PCI_MSIX_FLAGS 2 @@ -308,6 +315,7 @@ #define PCI_MSIX_TABLE 4 #define PCI_MSIX_PBA 8 #define PCI_MSIX_FLAGS_BIRMASK (7 << 0) +#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */ /* MSI-X entry's format */ #define PCI_MSIX_ENTRY_SIZE 16 @@ -338,6 +346,7 @@ #define PCI_AF_CTRL_FLR 0x01 #define PCI_AF_STATUS 5 #define PCI_AF_STATUS_TP 0x01 +#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */ /* PCI-X registers */ @@ -374,6 +383,10 @@ #define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */ #define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ #define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ +#define PCI_X_ECC_CSR 8 /* ECC control and status */ +#define PCI_CAP_PCIX_SIZEOF_V0 8 /* size of registers for Version 0 */ +#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */ +#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */ /* PCI Bridge Subsystem ID registers */ @@ -462,6 +475,7 @@ #define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */ #define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */ #define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */ +#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1 20 /* v1 endpoints end here */ #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ #define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */ #define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */ @@ -521,6 +535,7 @@ #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ +#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ @@ -529,23 +544,43 @@ #define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) #define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) -#define PCI_EXT_CAP_ID_ERR 1 -#define PCI_EXT_CAP_ID_VC 2 -#define PCI_EXT_CAP_ID_DSN 3 -#define PCI_EXT_CAP_ID_PWR 4 -#define PCI_EXT_CAP_ID_VNDR 11 -#define PCI_EXT_CAP_ID_ACS 13 -#define PCI_EXT_CAP_ID_ARI 14 -#define PCI_EXT_CAP_ID_ATS 15 -#define PCI_EXT_CAP_ID_SRIOV 16 -#define PCI_EXT_CAP_ID_PRI 19 -#define PCI_EXT_CAP_ID_LTR 24 -#define PCI_EXT_CAP_ID_PASID 27 +#define PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */ +#define PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel Capability */ +#define PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */ +#define PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */ +#define PCI_EXT_CAP_ID_RCLD 0x05 /* Root Complex Link Declaration */ +#define PCI_EXT_CAP_ID_RCILC 0x06 /* Root Complex Internal Link Control */ +#define PCI_EXT_CAP_ID_RCEC 0x07 /* Root Complex Event Collector */ +#define PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function VC Capability */ +#define PCI_EXT_CAP_ID_VC9 0x09 /* same as _VC */ +#define PCI_EXT_CAP_ID_RCRB 0x0A /* Root Complex RB? */ +#define PCI_EXT_CAP_ID_VNDR 0x0B /* Vendor Specific */ +#define PCI_EXT_CAP_ID_CAC 0x0C /* Config Access - obsolete */ +#define PCI_EXT_CAP_ID_ACS 0x0D /* Access Control Services */ +#define PCI_EXT_CAP_ID_ARI 0x0E /* Alternate Routing ID */ +#define PCI_EXT_CAP_ID_ATS 0x0F /* Address Translation Services */ +#define PCI_EXT_CAP_ID_SRIOV 0x10 /* Single Root I/O Virtualization */ +#define PCI_EXT_CAP_ID_MRIOV 0x11 /* Multi Root I/O Virtualization */ +#define PCI_EXT_CAP_ID_MCAST 0x12 /* Multicast */ +#define PCI_EXT_CAP_ID_PRI 0x13 /* Page Request Interface */ +#define PCI_EXT_CAP_ID_AMD_XXX 0x14 /* reserved for AMD */ +#define PCI_EXT_CAP_ID_REBAR 0x15 /* resizable BAR */ +#define PCI_EXT_CAP_ID_DPA 0x16 /* dynamic power alloc */ +#define PCI_EXT_CAP_ID_TPH 0x17 /* TPH request */ +#define PCI_EXT_CAP_ID_LTR 0x18 /* latency tolerance reporting */ +#define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe */ +#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ +#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID + +#define PCI_EXT_CAP_DSN_SIZEOF 12 +#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 /* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ #define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ #define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ +#define PCI_ERR_UNC_SURPDN 0x00000020 /* Surprise Down */ #define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ #define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ #define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ @@ -555,6 +590,11 @@ #define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ #define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ #define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ +#define PCI_ERR_UNC_ACSV 0x00200000 /* ACS Violation */ +#define PCI_ERR_UNC_INTN 0x00400000 /* internal error */ +#define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */ +#define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */ +#define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */ #define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ /* Same bits as above */ #define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ @@ -565,6 +605,9 @@ #define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ #define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ #define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ +#define PCI_ERR_COR_ADV_NFAT 0x00002000 /* Advisory Non-Fatal */ +#define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */ +#define PCI_ERR_COR_LOG_OVER 0x00008000 /* Header Log Overflow */ #define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ /* Same bits as above */ #define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ @@ -596,12 +639,18 @@ /* Virtual Channel */ #define PCI_VC_PORT_REG1 4 +#define PCI_VC_REG1_EVCC 0x7 /* extended vc count */ #define PCI_VC_PORT_REG2 8 +#define PCI_VC_REG2_32_PHASE 0x2 +#define PCI_VC_REG2_64_PHASE 0x4 +#define PCI_VC_REG2_128_PHASE 0x8 #define PCI_VC_PORT_CTRL 12 #define PCI_VC_PORT_STATUS 14 #define PCI_VC_RES_CAP 16 #define PCI_VC_RES_CTRL 20 #define PCI_VC_RES_STATUS 26 +#define PCI_CAP_VC_BASE_SIZEOF 0x10 +#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C /* Power Budgeting */ #define PCI_PWR_DSR 4 /* Data Select Register */ @@ -614,6 +663,7 @@ #define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ #define PCI_PWR_CAP 12 /* Capability */ #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ +#define PCI_EXT_CAP_PWR_SIZEOF 16 /* * Hypertransport sub capability types @@ -646,6 +696,8 @@ #define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ #define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ #define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ +#define HT_CAP_SIZEOF_LONG 28 /* slave & primary */ +#define HT_CAP_SIZEOF_SHORT 24 /* host & secondary */ /* Alternative Routing-ID Interpretation */ #define PCI_ARI_CAP 0x04 /* ARI Capability Register */ @@ -656,6 +708,7 @@ #define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ #define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ #define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ +#define PCI_EXT_CAP_ARI_SIZEOF 8 /* Address Translation Service */ #define PCI_ATS_CAP 0x04 /* ATS Capability Register */ @@ -665,6 +718,7 @@ #define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */ #define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */ #define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */ +#define PCI_EXT_CAP_ATS_SIZEOF 8 /* Page Request Interface */ #define PCI_PRI_CTRL 0x04 /* PRI control register */ @@ -676,6 +730,7 @@ #define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */ #define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */ #define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */ +#define PCI_EXT_CAP_PRI_SIZEOF 16 /* PASID capability */ #define PCI_PASID_CAP 0x04 /* PASID feature register */ @@ -685,6 +740,7 @@ #define PCI_PASID_CTRL_ENABLE 0x01 /* Enable bit */ #define PCI_PASID_CTRL_EXEC 0x02 /* Exec permissions Enable */ #define PCI_PASID_CTRL_PRIV 0x04 /* Priviledge Mode Enable */ +#define PCI_EXT_CAP_PASID_SIZEOF 8 /* Single Root I/O Virtualization */ #define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */ @@ -716,12 +772,14 @@ #define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */ #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ +#define PCI_EXT_CAP_SRIOV_SIZEOF 64 #define PCI_LTR_MAX_SNOOP_LAT 0x4 #define PCI_LTR_MAX_NOSNOOP_LAT 0x6 #define PCI_LTR_VALUE_MASK 0x000003ff #define PCI_LTR_SCALE_MASK 0x00001c00 #define PCI_LTR_SCALE_SHIFT 10 +#define PCI_EXT_CAP_LTR_SIZEOF 8 /* Access Control Service */ #define PCI_ACS_CAP 0x04 /* ACS Capability Register */ @@ -732,7 +790,38 @@ #define PCI_ACS_UF 0x10 /* Upstream Forwarding */ #define PCI_ACS_EC 0x20 /* P2P Egress Control */ #define PCI_ACS_DT 0x40 /* Direct Translated P2P */ +#define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */ #define PCI_ACS_CTRL 0x06 /* ACS Control Register */ #define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ +#define PCI_VSEC_HDR 4 /* extended cap - vendor specific */ +#define PCI_VSEC_HDR_LEN_SHIFT 20 /* shift for length field */ + +/* sata capability */ +#define PCI_SATA_REGS 4 /* SATA REGs specifier */ +#define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */ +#define PCI_SATA_REGS_INLINE 0xF /* REGS in config space */ +#define PCI_SATA_SIZEOF_SHORT 8 +#define PCI_SATA_SIZEOF_LONG 16 + +/* resizable BARs */ +#define PCI_REBAR_CTRL 8 /* control register */ +#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5) /* mask for # bars */ +#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # bars */ + +/* dynamic power allocation */ +#define PCI_DPA_CAP 4 /* capability register */ +#define PCI_DPA_CAP_SUBSTATE_MASK 0x1F /* # substates - 1 */ +#define PCI_DPA_BASE_SIZEOF 16 /* size with 0 substates */ + +/* TPH Requester */ +#define PCI_TPH_CAP 4 /* capability register */ +#define PCI_TPH_CAP_LOC_MASK 0x600 /* location mask */ +#define PCI_TPH_LOC_NONE 0x000 /* no location */ +#define PCI_TPH_LOC_CAP 0x200 /* in capability */ +#define PCI_TPH_LOC_MSIX 0x400 /* in MSI-X */ +#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* st table mask */ +#define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */ +#define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */ + #endif /* LINUX_PCI_REGS_H */ -- GitLab From afba018898ae54b498e82b3cd4d2b61c74032c90 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 12 Jun 2012 16:36:45 +0200 Subject: [PATCH 0530/5711] drm/i915: ensure HDMI port is disabled inside set_infoframes This function is supposed to be used at mode set time, so prevent against future mistakes by adding a WARN(). Based on a patch by Paulo Zanoni, with the check extracted into a little assert_hdmi_port_disabled helper added to make things self documenting and move the assert stuff out of line. [fixed up spelling goof-up while applying.] Cc: Paulo Zanoni Reviewed-by: Eugeni Dodonov Reviewed-by: Paulo Zanoni Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 69637db9af1f..5b2c88ca6edb 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -37,6 +37,19 @@ #include "i915_drm.h" #include "i915_drv.h" +static void +assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) +{ + struct drm_device *dev = intel_hdmi->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t enabled_bits; + + enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; + + WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, + "HDMI port enabled, expecting disabled\n"); +} + struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) { return container_of(encoder, struct intel_hdmi, base.base); @@ -334,6 +347,8 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, u32 val = I915_READ(reg); u32 port; + assert_hdmi_port_disabled(intel_hdmi); + /* If the registers were not initialized yet, they might be zeroes, * which means we're selecting the AVI DIP and we're setting its * frequency to once. This seems to really confuse the HW and make @@ -395,6 +410,8 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, u32 val = I915_READ(reg); u32 port; + assert_hdmi_port_disabled(intel_hdmi); + /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; @@ -451,6 +468,8 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + assert_hdmi_port_disabled(intel_hdmi); + /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; @@ -484,6 +503,8 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + assert_hdmi_port_disabled(intel_hdmi); + /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; @@ -516,6 +537,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + assert_hdmi_port_disabled(intel_hdmi); + if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); POSTING_READ(reg); -- GitLab From 534b5a5341cb7e16a98d44623d8fce9464ebf22c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 10:07:08 +0200 Subject: [PATCH 0531/5711] drm/i915: pnv has a backlight polarity control bit, too We already correctly ignore bit0 on gen < 4, now we also know why ;-) I've decided that losing that single bit of precision isn't worth the trouble to sprinkle IS_PINEVIEW checks all over the backlight control code - that code is way too fragile imo. Reviewed-by: Eugeni Dodonov Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7dcc04f2143e..20244b971fc6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1828,6 +1828,8 @@ */ #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) +#define BLM_POLARITY_PNV (1 << 0) /* pnv only */ #define BLC_HIST_CTL 0x61260 -- GitLab From 7cf4160148136deb31ee5f2802857dd935a38529 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 10:07:09 +0200 Subject: [PATCH 0532/5711] drm/i915: clear up backlight #define confusion on gen4+ - Regroup definitions for BLC_PWM_CTL so that they're all together and and ordered according to the bitfields. - Add all missing definitions for BLC_PWM_CTL2. - Use the BLM_ (for backlight modulation) prefix consistently. - Note that combination mode (i.e. also taking the legacy backlight control value from pci config space into account) is gen4 only. - Move the new registers for PCH-split machines up, they're an almost match for the gen4 defitions. Prefix the special PCH-only bits with BLM_PCH_. Also add the pipe C select bit for ivb. - Rip out the second pair of PCH polarity definitions - they're only valid on early (pre-production) ilk silicon. - Adapt the existing code to use the new definitions. This has the nice benefit of killing a magic (1 << 30) left behind be Jesse Barnes. No functional changes in this patch. Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 55 ++++++++++++++++++---------- drivers/gpu/drm/i915/intel_display.c | 4 +- drivers/gpu/drm/i915/intel_lvds.c | 12 +++--- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 20244b971fc6..c4b1a2b45bb4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1807,18 +1807,35 @@ #define PFIT_AUTO_RATIOS 0x61238 /* Backlight control */ -#define BLC_PWM_CTL 0x61254 -#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BLC_PWM_CTL2 0x61250 /* 965+ only */ -#define BLM_COMBINATION_MODE (1 << 30) +#define BLM_PWM_ENABLE (1 << 31) +#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ +#define BLM_PIPE_SELECT (1 << 29) +#define BLM_PIPE_SELECT_IVB (3 << 29) +#define BLM_PIPE_A (0 << 29) +#define BLM_PIPE_B (1 << 29) +#define BLM_PIPE_C (2 << 29) /* ivb + */ +#define BLM_PIPE(pipe) ((pipe) << 29) +#define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ +#define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) +#define BLM_PHASE_IN_ENABLE (1 << 25) +#define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) +#define BLM_PHASE_IN_TIME_BASE_SHIFT (16) +#define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) +#define BLM_PHASE_IN_COUNT_SHIFT (8) +#define BLM_PHASE_IN_COUNT_MASK (0xff << 8) +#define BLM_PHASE_IN_INCR_SHIFT (0) +#define BLM_PHASE_IN_INCR_MASK (0xff << 0) +#define BLC_PWM_CTL 0x61254 /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. * * The actual value is this field multiplied by two. */ -#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) -#define BLM_LEGACY_MODE (1 << 16) +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ /* * This is the number of cycles out of the backlight modulation cycle for which * the backlight is on. @@ -1833,6 +1850,19 @@ #define BLC_HIST_CTL 0x61260 +/* New registers for PCH-split platforms. Safe where new bits show up, the + * register layout machtes with gen4 BLC_PWM_CTL[12]. */ +#define BLC_PWM_CPU_CTL2 0x48250 +#define BLC_PWM_CPU_CTL 0x48254 + +/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is + * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ +#define BLC_PWM_PCH_CTL1 0xc8250 +#define BLM_PCH_PWM_ENABLE (1 << 30) +#define BLM_PCH_OVERRIDE_ENABLE (1 << 30) +#define BLM_PCH_POLARITY (1 << 29) +#define BLC_PWM_PCH_CTL2 0xc8254 + /* TV port control */ #define TV_CTL 0x68000 /** Enables the TV encoder */ @@ -3840,21 +3870,6 @@ #define PCH_LVDS 0xe1180 #define LVDS_DETECTED (1 << 1) -#define BLC_PWM_CPU_CTL2 0x48250 -#define PWM_ENABLE (1 << 31) -#define PWM_PIPE_A (0 << 29) -#define PWM_PIPE_B (1 << 29) -#define BLC_PWM_CPU_CTL 0x48254 - -#define BLC_PWM_PCH_CTL1 0xc8250 -#define PWM_PCH_ENABLE (1 << 31) -#define PWM_POLARITY_ACTIVE_LOW (1 << 29) -#define PWM_POLARITY_ACTIVE_HIGH (0 << 29) -#define PWM_POLARITY_ACTIVE_LOW2 (1 << 28) -#define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28) - -#define BLC_PWM_PCH_CTL2 0xc8254 - #define PCH_PP_STATUS 0xc7200 #define PCH_PP_CONTROL 0xc7204 #define PANEL_UNLOCK_REGS (0xabcd << 16) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e760319c0f2..bad36e0b8045 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6895,9 +6895,9 @@ static void ivb_pch_pwm_override(struct drm_device *dev) * IVB has CPU eDP backlight regs too, set things up to let the * PCH regs control the backlight */ - I915_WRITE(BLC_PWM_CPU_CTL2, PWM_ENABLE); + I915_WRITE(BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE); I915_WRITE(BLC_PWM_CPU_CTL, 0); - I915_WRITE(BLC_PWM_PCH_CTL1, PWM_ENABLE | (1<<30)); + I915_WRITE(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE | BLM_PCH_OVERRIDE_ENABLE); } void intel_modeset_init_hw(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 08eb04c787e8..a7269e6b4bf7 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -1081,16 +1081,16 @@ out: /* make sure PWM is enabled and locked to the LVDS pipe */ pwm = I915_READ(BLC_PWM_CPU_CTL2); - if (pipe == 0 && (pwm & PWM_PIPE_B)) - I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); + if (pipe == 0 && (pwm & BLM_PIPE_B)) + I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~BLM_PWM_ENABLE); if (pipe) - pwm |= PWM_PIPE_B; + pwm |= BLM_PIPE_B; else - pwm &= ~PWM_PIPE_B; - I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); + pwm &= ~BLM_PIPE_B; + I915_WRITE(BLC_PWM_CPU_CTL2, pwm | BLM_PWM_ENABLE); pwm = I915_READ(BLC_PWM_PCH_CTL1); - pwm |= PWM_PCH_ENABLE; + pwm |= BLM_PCH_PWM_ENABLE; I915_WRITE(BLC_PWM_PCH_CTL1, pwm); /* * Unlock registers and just -- GitLab From 24ded204429fa0f5501d37c63ee35c555c0b75ee Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 12:14:54 +0200 Subject: [PATCH 0533/5711] drm/i915: properly enable the blc controller on the right pipe On gen4+ we have a bitfield to specify from which pipe the backlight controller should take it's clock. For PCH split platforms we've already set these up, but only at initialization time. And without taking into account the 3rd pipe added with ivb. For gen4, we've completely ignored these. Although we do restrict lvds to the 2nd pipe, so this is only a problem on machines where we boot up with the lvds on the first pipe. So restructure the code to enable the backlight on the right pipe at modeset time. v2: For odd reasons panel_enable_backlight gets called twice in a modeset, so we can't WARN_ON in there if the backlight controller is switched on already. v3: backlight enable can also be called through dpms on, so the check in there is legit. Update the comment to reflect that. Tested-By: Kamal Mostafa Bugzilla: https://bugs.launchpad.net/bugs/954661 Cc: Carsten Emde Reviewed-by: Eugeni Dodonov Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 32 +++++-------------------- drivers/gpu/drm/i915/intel_panel.c | 38 +++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c35edd7ca84d..1a1fdb088dda 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -379,7 +379,8 @@ extern u32 intel_panel_get_max_backlight(struct drm_device *dev); extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); extern int intel_panel_setup_backlight(struct drm_device *dev); -extern void intel_panel_enable_backlight(struct drm_device *dev); +extern void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe); extern void intel_panel_disable_backlight(struct drm_device *dev); extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a7269e6b4bf7..492db7740de2 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -71,6 +71,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) static void intel_lvds_enable(struct intel_lvds *intel_lvds) { struct drm_device *dev = intel_lvds->base.base.dev; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc); struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, lvds_reg, stat_reg; @@ -107,7 +108,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) DRM_ERROR("timed out waiting for panel to power on\n"); - intel_panel_enable_backlight(dev); + intel_panel_enable_backlight(dev, intel_crtc->pipe); } static void intel_lvds_disable(struct intel_lvds *intel_lvds) @@ -1074,35 +1075,14 @@ bool intel_lvds_init(struct drm_device *dev) goto failed; out: + /* + * Unlock registers and just + * leave them unlocked + */ if (HAS_PCH_SPLIT(dev)) { - u32 pwm; - - pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; - - /* make sure PWM is enabled and locked to the LVDS pipe */ - pwm = I915_READ(BLC_PWM_CPU_CTL2); - if (pipe == 0 && (pwm & BLM_PIPE_B)) - I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~BLM_PWM_ENABLE); - if (pipe) - pwm |= BLM_PIPE_B; - else - pwm &= ~BLM_PIPE_B; - I915_WRITE(BLC_PWM_CPU_CTL2, pwm | BLM_PWM_ENABLE); - - pwm = I915_READ(BLC_PWM_PCH_CTL1); - pwm |= BLM_PCH_PWM_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, pwm); - /* - * Unlock registers and just - * leave them unlocked - */ I915_WRITE(PCH_PP_CONTROL, I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); } else { - /* - * Unlock registers and just - * leave them unlocked - */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 7180cc828f94..58c7ee7238b8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -287,9 +287,18 @@ void intel_panel_disable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = false; intel_panel_actually_set_backlight(dev, 0); + + if (INTEL_INFO(dev)->gen >= 4) { + uint32_t reg; + + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + + I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); + } } -void intel_panel_enable_backlight(struct drm_device *dev) +void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -298,6 +307,33 @@ void intel_panel_enable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = true; intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); + + if (INTEL_INFO(dev)->gen >= 4) { + uint32_t reg, tmp; + + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + + + tmp = I915_READ(reg); + + /* Note that this can also get called through dpms changes. And + * we don't track the backlight dpms state, hence check whether + * we have to do anything first. */ + if (tmp & BLM_PWM_ENABLE) + return; + + if (dev_priv->num_pipe == 3) + tmp &= ~BLM_PIPE_SELECT_IVB; + else + tmp &= ~BLM_PIPE_SELECT; + + tmp |= BLM_PIPE(pipe); + tmp &= ~BLM_PWM_ENABLE; + + I915_WRITE(reg, tmp); + POSTING_READ(reg); + I915_WRITE(reg, tmp | BLM_PWM_ENABLE); + } } static void intel_panel_init_backlight(struct drm_device *dev) -- GitLab From 0b9f43a0ee7e89013a3d913ce556715fd8acb674 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jun 2012 10:07:11 +0200 Subject: [PATCH 0534/5711] drm/i915: allow pipe A for lvds on gen4 Given the havoc the missing backlight pipe select code might have caused, let's try to re-enabled pipe A support for lvds on gen4 hw. Just to see what all blows up ... Note though that commit 4add75c43f39573edc884d46b7c2b7414f01171a Author: Chris Wilson Date: Sat Dec 4 17:49:46 2010 +0000 drm/i915: Allow LVDS to be on pipe A for Ironlake+ claims that this caused tons of spurious wakeups somehow. More details can be found in the old revert: commit 12e8ba25ef52f19e7a42e61aecb3c1fef83b2a82 Author: Chris Wilson Date: Tue Sep 7 23:39:28 2010 +0100 Revert "drm/i915: Allow LVDS on pipe A on gen4+" Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16307 Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lvds.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 492db7740de2..ab4d64792616 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -968,6 +968,8 @@ bool intel_lvds_init(struct drm_device *dev) intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); if (HAS_PCH_SPLIT(dev)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + else if (IS_GEN4(dev)) + intel_encoder->crtc_mask = (1 << 0) | (1 << 1); else intel_encoder->crtc_mask = (1 << 1); -- GitLab From 1caba565e13a867107ca78a316d6076c7b6a740c Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Mon, 28 May 2012 16:07:49 +0100 Subject: [PATCH 0535/5711] Staging: cptm1217: clearpad_tm1217: fix coding style issues This commit fixes coding style issues including quoted string across multiple lines. Signed-off-by: Adnan Ali Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cptm1217/clearpad_tm1217.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c index 5456f82c3066..0d924d3a2ab1 100644 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ b/drivers/staging/cptm1217/clearpad_tm1217.c @@ -396,8 +396,8 @@ static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts) retval = gpio_to_irq(ts->gpio); if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO to IRQ failedi," - " error %d\n", retval); + dev_err(ts->dev, + "cp_tm1217: GPIO to IRQ failed, error %d\n", retval); gpio_free(ts->gpio); } dev_dbg(ts->dev, -- GitLab From 2e0bec91399bab115d2a3a60288ce94a977f49c1 Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Mon, 28 May 2012 17:11:29 +0100 Subject: [PATCH 0536/5711] Staging: sep: fix coding style issues This commit fixes coding style issues related to string split across the lines and space before tab at start of line. Signed-off-by: Adnan Ali Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_crypto.c | 4 ++-- drivers/staging/sep/sep_main.c | 37 +++++++++++++++++--------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index 1cc790e9fa07..9fd9da84428e 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -1095,8 +1095,8 @@ static int sep_crypto_take_sep(struct this_task_ctx *ta_ctx) current->comm, sizeof(current->comm)); if (!ta_ctx->queue_elem) { - dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" - " status error\n", current->pid); + dev_dbg(&sep->pdev->dev, + "[PID%d] updating queue status error\n", current->pid); return -EINVAL; } diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index df1d13e96fcd..ab351289d893 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -1436,8 +1436,9 @@ static int sep_lli_table_secure_dma(struct sep_device *sep, start_page = app_virt_addr >> PAGE_SHIFT; num_pages = end_page - start_page + 1; - dev_dbg(&sep->pdev->dev, "[PID%d] lock user pages" - " app_virt_addr is %x\n", current->pid, app_virt_addr); + dev_dbg(&sep->pdev->dev, + "[PID%d] lock user pages app_virt_addr is %x\n", + current->pid, app_virt_addr); dev_dbg(&sep->pdev->dev, "[PID%d] data_size is (hex) %x\n", current->pid, data_size); @@ -1931,9 +1932,9 @@ static int sep_prepare_input_dma_table(struct sep_device *sep, void *dma_lli_table_alloc_addr = NULL; void *dma_in_lli_table_ptr = NULL; - dev_dbg(&sep->pdev->dev, "[PID%d] prepare intput dma " - "tbl data size: (hex) %x\n", - current->pid, data_size); + dev_dbg(&sep->pdev->dev, + "[PID%d] prepare intput dma tbl data size: (hex) %x\n", + current->pid, data_size); dev_dbg(&sep->pdev->dev, "[PID%d] block_size is (hex) %x\n", current->pid, block_size); @@ -2542,17 +2543,18 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep, } } - dev_dbg(&sep->pdev->dev, "[PID%d] After lock; prep input output dma " - "table sep_in_num_pages is (hex) %x\n", current->pid, + dev_dbg(&sep->pdev->dev, + "[PID%d] After lock; prep input output dma table sep_in_num_pages is (hex) %x\n", + current->pid, dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages); dev_dbg(&sep->pdev->dev, "[PID%d] sep_out_num_pages is (hex) %x\n", current->pid, dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages); - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP" - " is (hex) %x\n", current->pid, - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is (hex) %x\n", + current->pid, SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); /* Call the fucntion that creates table from the lli arrays */ dev_dbg(&sep->pdev->dev, "[PID%d] calling create table from lli\n", @@ -3844,8 +3846,9 @@ static ssize_t sep_write(struct file *filp, * buffers created. Only SEP_DOUBLEBUF_USERS_LIMIT number * of threads can progress further at a time */ - dev_dbg(&sep->pdev->dev, "[PID%d] waiting for double buffering " - "region access\n", current->pid); + dev_dbg(&sep->pdev->dev, + "[PID%d] waiting for double buffering region access\n", + current->pid); error = down_interruptible(&sep->sep_doublebuf); dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region start\n", current->pid); @@ -3889,8 +3892,8 @@ static ssize_t sep_write(struct file *filp, current->comm, sizeof(current->comm)); if (!my_queue_elem) { - dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" - "status error\n", current->pid); + dev_dbg(&sep->pdev->dev, + "[PID%d] updating queue status error\n", current->pid); error = -ENOMEM; goto end_function_error_doublebuf; } @@ -4155,8 +4158,8 @@ static int __devinit sep_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&sep->sep_queue_status); - dev_dbg(&sep->pdev->dev, "sep probe: PCI obtained, " - "device being prepared\n"); + dev_dbg(&sep->pdev->dev, + "sep probe: PCI obtained, device being prepared\n"); /* Set up our register area */ sep->reg_physical_addr = pci_resource_start(sep->pdev, 0); @@ -4318,7 +4321,7 @@ static void sep_remove(struct pci_dev *pdev) static DEFINE_PCI_DEVICE_TABLE(sep_pci_id_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0826)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08e9)}, - {0} + {0} }; /* Export our pci_device_id structure to user space */ -- GitLab From 6ee19aef7694e9533617573ebe8a0b379d5c75f4 Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Tue, 29 May 2012 11:33:03 +0100 Subject: [PATCH 0537/5711] Staging: ramster: r2net: fix coding style issues This commit fixes coding style issues related to string splite across multiple lines. Signed-off-by: Adnan Ali Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ramster/r2net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/ramster/r2net.c b/drivers/staging/ramster/r2net.c index 2ee02204c43d..fc830c3ac74b 100644 --- a/drivers/staging/ramster/r2net.c +++ b/drivers/staging/ramster/r2net.c @@ -266,8 +266,8 @@ int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size, static unsigned long cnt; cnt++; if (!(cnt&(cnt-1))) - pr_err("ramster_remote_put: message failed, " - "ret=%d, cnt=%lu\n", ret, cnt); + pr_err("ramster_remote_put: message failed, ret=%d, cnt=%lu\n", + ret, cnt); ret = -1; } #endif -- GitLab From ff5e4a1d2702582614996f6f6d005e9b5caadeb8 Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Thu, 31 May 2012 11:32:48 +0100 Subject: [PATCH 0538/5711] Staging: gdm72xx: gdm_usb: fix deprecated function kernel_thread This commit fixes deprecated function kernel_thread by replacing it with kthread_run. Signed-off-by: Adnan Ali Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/gdm_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index 1e9dc0d90362..19533c6e055b 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "gdm_usb.h" #include "gdm_wimax.h" @@ -775,7 +776,7 @@ static struct usb_driver gdm_usb_driver = { static int __init usb_gdm_wimax_init(void) { #ifdef CONFIG_WIMAX_GDM72XX_K_MODE - kernel_thread(k_mode_thread, NULL, CLONE_KERNEL); + kthread_run(k_mode_thread, NULL, "WiMax_thread"); #endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ return usb_register(&gdm_usb_driver); } -- GitLab From dee0dc0d0649b028e16473a8e2410efd455135c2 Mon Sep 17 00:00:00 2001 From: Adnan Ali Date: Tue, 29 May 2012 15:21:20 +0100 Subject: [PATCH 0539/5711] Staging: rts5139: sd_cprm: fix coding style and deprecation issues This commit fixes coding style and deprecation issues which includes long lines, braces with single statments in if condition and deprecated min() function. Signed-off-by: Adnan Ali Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5139/sd_cprm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rts5139/sd_cprm.c b/drivers/staging/rts5139/sd_cprm.c index f8c60711f710..0167f7f35c20 100644 --- a/drivers/staging/rts5139/sd_cprm.c +++ b/drivers/staging/rts5139/sd_cprm.c @@ -201,9 +201,8 @@ RTY_SEND_CMD: if (buf[1] & 0x80) TRACE_RET(chip, STATUS_FAIL); } - if (buf[1] & 0x7F) { + if (buf[1] & 0x7F) TRACE_RET(chip, STATUS_FAIL); - } if (buf[2] & 0xF8) TRACE_RET(chip, STATUS_FAIL); @@ -224,7 +223,8 @@ RTY_SEND_CMD: return STATUS_SUCCESS; } -static int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 *rsp, u8 rsp_type) +static int ext_sd_get_rsp(struct rts51x_chip *chip, int len, + u8 *rsp, u8 rsp_type) { int retval, rsp_len; u16 reg_addr; @@ -844,7 +844,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip) buf[15] = chip->max_lun; - len = min(18, (int)scsi_bufflen(srb)); + len = min_t(unsigned, 18, scsi_bufflen(srb)); rts51x_set_xfer_buf(buf, len, srb); return TRANSPORT_GOOD; -- GitLab From 02fd3b3670fb99017b17757d33a0a17e2405920c Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Mon, 28 May 2012 01:53:22 +0530 Subject: [PATCH 0540/5711] staging/gdm72xx: Remove version.h includes Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/gdm_qos.c | 1 - drivers/staging/gdm72xx/gdm_sdio.c | 1 - drivers/staging/gdm72xx/gdm_usb.c | 1 - drivers/staging/gdm72xx/gdm_wimax.c | 1 - drivers/staging/gdm72xx/gdm_wimax.h | 1 - drivers/staging/gdm72xx/netlink_k.c | 1 - drivers/staging/gdm72xx/sdio_boot.c | 1 - drivers/staging/gdm72xx/usb_boot.c | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c index 0217680ec545..e7134e28a06d 100644 --- a/drivers/staging/gdm72xx/gdm_qos.c +++ b/drivers/staging/gdm72xx/gdm_qos.c @@ -11,7 +11,6 @@ * GNU General Public License for more details. */ -#include #include #include diff --git a/drivers/staging/gdm72xx/gdm_sdio.c b/drivers/staging/gdm72xx/gdm_sdio.c index e1a3dd2fc4af..5e19b09e3bff 100644 --- a/drivers/staging/gdm72xx/gdm_sdio.c +++ b/drivers/staging/gdm72xx/gdm_sdio.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index 19533c6e055b..e201b341e52f 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c index f1936b92533b..110bdbc9c899 100644 --- a/drivers/staging/gdm72xx/gdm_wimax.c +++ b/drivers/staging/gdm72xx/gdm_wimax.c @@ -11,7 +11,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/drivers/staging/gdm72xx/gdm_wimax.h b/drivers/staging/gdm72xx/gdm_wimax.h index 023e6492e33d..6ec0ab43e9cc 100644 --- a/drivers/staging/gdm72xx/gdm_wimax.h +++ b/drivers/staging/gdm72xx/gdm_wimax.h @@ -15,7 +15,6 @@ #define __GDM_WIMAX_H__ #include -#include #include #include "wm_ioctl.h" #if defined(CONFIG_WIMAX_GDM72XX_QOS) diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c index 292af0f7f451..1c74b0875515 100644 --- a/drivers/staging/gdm72xx/netlink_k.c +++ b/drivers/staging/gdm72xx/netlink_k.c @@ -11,7 +11,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c index 6ff4dc372522..760efee23d4a 100644 --- a/drivers/staging/gdm72xx/sdio_boot.c +++ b/drivers/staging/gdm72xx/sdio_boot.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c index 5a0e030220dc..c163bcc437ed 100644 --- a/drivers/staging/gdm72xx/usb_boot.c +++ b/drivers/staging/gdm72xx/usb_boot.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include -- GitLab From ef73b7a45dfd3c4cdd447a6767422349e5fe7242 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 4 Jun 2012 07:46:52 -0700 Subject: [PATCH 0541/5711] staging: "sbe-2t3e3" Fix typos in sbe-2t3e3 Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sbe-2t3e3/dc.c | 2 +- drivers/staging/sbe-2t3e3/io.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/sbe-2t3e3/dc.c b/drivers/staging/sbe-2t3e3/dc.c index 9dc4ec2109eb..e897a4366620 100644 --- a/drivers/staging/sbe-2t3e3/dc.c +++ b/drivers/staging/sbe-2t3e3/dc.c @@ -81,7 +81,7 @@ void dc_init(struct channel *sc) SBE_2T3E3_21143_VAL_NUMBER_OF_RECEIVE_PACKETS; dc_write(sc->addr, SBE_2T3E3_21143_REG_GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL, val); - /* prepare descriptors and data for receive and transmit procecsses */ + /* prepare descriptors and data for receive and transmit processes */ if (dc_init_descriptor_list(sc) != 0) return; diff --git a/drivers/staging/sbe-2t3e3/io.c b/drivers/staging/sbe-2t3e3/io.c index 9a50bcc59594..d2391cb23e64 100644 --- a/drivers/staging/sbe-2t3e3/io.c +++ b/drivers/staging/sbe-2t3e3/io.c @@ -17,7 +17,7 @@ /* All access to registers done via the 21143 on port 0 must be * protected via the card->bootrom_lock. */ -/* priviate define to be used here only - must be protected by card->bootrom_lock */ +/* private define to be used here only - must be protected by card->bootrom_lock */ #define cpld_write_nolock(channel, reg, val) \ bootrom_write((channel), CPLD_MAP_REG(reg, channel), val) -- GitLab From 8aac4d443980a4b5833b6896169c30d22e4cce74 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Wed, 6 Jun 2012 01:10:50 +0530 Subject: [PATCH 0542/5711] staging/wlan-ng: cfg80211.c coding style cleanup there are warnings that are reported by checkpatch.pl fixed the following problems drivers/staging/wlan-ng/cfg80211.c:130: WARNING: line over 80 characters drivers/staging/wlan-ng/cfg80211.c:366: WARNING: line over 80 characters drivers/staging/wlan-ng/cfg80211.c:543: WARNING: line over 80 characters drivers/staging/wlan-ng/cfg80211.c:665: WARNING: line over 80 characters drivers/staging/wlan-ng/cfg80211.c:692: WARNING: line over 80 characters drivers/staging/wlan-ng/cfg80211.c:735: WARNING: line over 80 characters Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8bc562b8c4d9..fabff4d650ef 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -127,7 +127,9 @@ int prism2_change_virtual_intf(struct wiphy *wiphy, } /* Set Operation mode to the PORT TYPE RID */ - result = prism2_domibset_uint32(wlandev, DIDmib_p2_p2Static_p2CnfPortType, data); + result = prism2_domibset_uint32(wlandev, + DIDmib_p2_p2Static_p2CnfPortType, + data); if (result) err = -EFAULT; @@ -363,7 +365,8 @@ int prism2_scan(struct wiphy *wiphy, struct net_device *dev, if (request->n_ssids > 0) { msg1.scantype.data = P80211ENUM_scantype_active; msg1.ssid.data.len = request->ssids->ssid_len; - memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len); + memcpy(msg1.ssid.data.data, + request->ssids->ssid, request->ssids->ssid_len); } else { msg1.scantype.data = 0; } @@ -540,7 +543,9 @@ int prism2_connect(struct wiphy *wiphy, struct net_device *dev, goto exit; } - result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *) sme->key); + result = prism2_domibset_pstr32(wlandev, + did, sme->key_len, + (u8 *)sme->key); if (result) goto exit; @@ -662,10 +667,11 @@ int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; struct p80211msg_dot11req_mibget msg; - p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + p80211item_uint32_t *mibitem; int result; int err = 0; + mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; @@ -689,7 +695,8 @@ exit: /* Interface callback functions, passing data back up to the cfg80211 layer */ void prism2_connect_result(wlandevice_t *wlandev, u8 failed) { - u16 status = failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; + u16 status = failed ? + WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; cfg80211_connect_result(wlandev->netdev, wlandev->bssid, NULL, 0, NULL, 0, status, GFP_KERNEL); @@ -732,7 +739,8 @@ struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) { struct wiphy *wiphy; struct prism2_wiphy_private *priv; - wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(struct prism2_wiphy_private)); + + wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv)); if (!wiphy) return NULL; -- GitLab From cf66823dd224294f40ad6ddced70e80bae940741 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Wed, 6 Jun 2012 01:12:06 +0530 Subject: [PATCH 0543/5711] staging/wlan-ng: prsim2fw.c coding style cleanup this patch fixes the coding style problems found by using checkpatch.pl drivers/staging/wlan-ng/prism2fw.c:175: ERROR: "foo * bar" should be "foo *bar" drivers/staging/wlan-ng/prism2fw.c:210: WARNING: line over 80 characters drivers/staging/wlan-ng/prism2fw.c:596: WARNING: line over 80 characters drivers/staging/wlan-ng/prism2fw.c:658: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2fw.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 3c40096f0c05..f13cdc9ab412 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -172,7 +172,7 @@ static int read_cardpda(struct pda *pda, wlandevice_t *wlandev); static int mkpdrlist(struct pda *pda); static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, - struct s3plugrec *s3plug, unsigned int ns3plug, struct pda * pda); + struct s3plugrec *s3plug, unsigned int ns3plug, struct pda *pda); static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3crcrec *s3crc, unsigned int ns3crc); @@ -207,7 +207,8 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) printk(KERN_INFO "prism2_usb: Checking for firmware %s\n", PRISM2_USB_FWFILE); - if (request_ihex_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) { + if (request_ihex_firmware(&fw_entry, + PRISM2_USB_FWFILE, &udev->dev) != 0) { printk(KERN_INFO "prism2_usb: Firmware not available, but not essential\n"); printk(KERN_INFO @@ -593,7 +594,8 @@ int mkpdrlist(struct pda *pda) le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) { pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]); - if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) { + if (le16_to_cpu(pda->rec[pda->nrec]->code) == + HFA384x_PDR_NICID) { memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid, sizeof(nicid)); nicid.id = le16_to_cpu(nicid.id); @@ -655,7 +657,7 @@ int mkpdrlist(struct pda *pda) * ~0 failure ----------------------------------------------------------------*/ int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, - struct s3plugrec *s3plug, unsigned int ns3plug, struct pda * pda) + struct s3plugrec *s3plug, unsigned int ns3plug, struct pda *pda) { int result = 0; int i; /* plug index */ -- GitLab From 9b754b17f9ac5fbb9586ae6582de7ecbfc46b56d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Jun 2012 14:46:44 -0700 Subject: [PATCH 0544/5711] staging: wlags49_h2: remove direct declarations of KERN_ prefixes Use the standard KERN_ #defines instead of "<.>" Signed-off-by: Joe Perches Cc: Kay Sievers Cc: Henk de Groot Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlags49_h2/hcf.c | 8 ++++---- drivers/staging/wlags49_h2/wl_main.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wlags49_h2/hcf.c b/drivers/staging/wlags49_h2/hcf.c index 366e4a4b75c5..423544634ae5 100644 --- a/drivers/staging/wlags49_h2/hcf.c +++ b/drivers/staging/wlags49_h2/hcf.c @@ -705,7 +705,7 @@ hcf_action( IFBP ifbp, hcf_16 action ) // 800 us latency before FW switches to high power MSF_WAIT(800); // MSF-defined function to wait n microseconds. //OOR if ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_DS_OOR ) { // OutOfRange -// printk( "<5>ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day +// printk(KERN_NOTICE "ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day // hcf_cntl( ifbp, HCF_CNTL_ENABLE ); // } // ifbp->IFB_DSLinkStat &= ~( CFG_LINK_STAT_DS_IR | CFG_LINK_STAT_DS_OOR); //clear IR/OOR state @@ -2979,7 +2979,7 @@ hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len ) ltv.typ = CFG_DDS_TICK_TIME; ltv.tick_time = ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_TIMER ) + 0x10 ) *64; //78 is more right hcf_put_info( ifbp, (LTVP)<v ); - printk( "<5>Preparing for sleep, link_status: %04X, timer : %d\n", + printk(KERN_NOTICE "Preparing for sleep, link_status: %04X, timer : %d\n", ifbp->IFB_DSLinkStat, ltv.tick_time );//;?remove me 1 day ifbp->IFB_TickCnt++; //;?just to make sure we do not keep on printing above message if ( ltv.tick_time < 300 * 125 ) ifbp->IFB_DSLinkStat += 0x0010; @@ -4221,11 +4221,11 @@ isr_info( IFBP ifbp ) // /*4*/ if ( info[1] == CFG_LINK_STAT ) { // ifbp->IFB_DSLinkStat = IPW( HREG_DATA_1 ) | CFG_LINK_STAT_CHANGE; //corrupts BAP !! ;? // ifbp->IFB_LinkStat = ifbp->IFB_DSLinkStat & CFG_LINK_STAT_FW; //;? to be obsoleted -// printk( "<4>linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day +// printk(KERN_ERR "linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day // #if (HCF_SLEEP) & HCF_DDS // if ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { //even values are disconnected etc. // ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty) -// printk( "<5>isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day +// printk(KERN_NOTICE "isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day // } // #endif // HCF_DDS // } diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c index d5bf0a7012f2..204107829577 100644 --- a/drivers/staging/wlags49_h2/wl_main.c +++ b/drivers/staging/wlags49_h2/wl_main.c @@ -3822,7 +3822,7 @@ static int write_int(struct file *file, const char *buffer, unsigned long count, lp->timer_oor.data = (unsigned long)lp; lp->timer_oor.expires = RUN_AT( 3 * HZ ); add_timer( &lp->timer_oor ); - printk( "<5>wl_enable: %ld\n", jiffies ); //;?remove me 1 day + printk(KERN_NOTICE "wl_enable: %ld\n", jiffies ); //;?remove me 1 day #endif //DN554 #ifdef DN554 /******************************************************************************* @@ -3852,7 +3852,7 @@ void timer_oor( u_long arg ) DBG_ENTER( DbgInfo ); DBG_PARAM( DbgInfo, "arg", "0x%08lx", arg ); - printk( "<5>timer_oor: %ld 0x%04X\n", jiffies, lp->timer_oor_cnt ); //;?remove me 1 day + printk(KERN_NOTICE "timer_oor: %ld 0x%04X\n", jiffies, lp->timer_oor_cnt ); //;?remove me 1 day lp->timer_oor_cnt += 10; if ( (lp->timer_oor_cnt & ~DS_OOR) > 300 ) { lp->timer_oor_cnt = 300; -- GitLab From 093abf11d3c4ecb8d8c57adec926dced532878ba Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 6 Jun 2012 22:54:27 -0400 Subject: [PATCH 0545/5711] Staging: bcm: Fix all whitespace issues in nvm.c This patch resolves all whitespace issues as reported by checkpatch.pl. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 4067 ++++++++++++++++++------------------- 1 file changed, 1980 insertions(+), 2087 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index f16d3bb54c3c..2bb87c93b0e9 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -29,8 +29,8 @@ static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal); static INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiSectAlignAddr); static INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff, - FLASH2X_SECTION_VAL eFlash2xSectionVal, - UINT uiOffset, UINT uiNumBytes); + FLASH2X_SECTION_VAL eFlash2xSectionVal, + UINT uiOffset, UINT uiNumBytes); static FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter); static FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter); @@ -49,7 +49,7 @@ static INT BeceemFlashBulkWrite( static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter); -static INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter,UINT dwAddress, UINT *pdwData, UINT dwNumData); +static INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, UINT dwAddress, UINT *pdwData, UINT dwNumData); // Procedure: ReadEEPROMStatusRegister // @@ -62,52 +62,52 @@ static INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter,UINT dwAddress, // //----------------------------------------------------------------------------- -static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter ) +static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) { UCHAR uiData = 0; - DWORD dwRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; UINT uiStatus = 0; UINT value = 0; UINT value1 = 0; /* Read the EEPROM status register */ - value = EEPROM_READ_STATUS_REGISTER ; - wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); + value = EEPROM_READ_STATUS_REGISTER; + wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); - while ( dwRetries != 0 ) + while (dwRetries != 0) { - value=0; - uiStatus = 0 ; + value = 0; + uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if(Adapter->device_removed == TRUE) + if (Adapter->device_removed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got removed hence exiting...."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting...."); break; } /* Wait for Avail bit to be set. */ - if ( ( uiStatus & EEPROM_READ_DATA_AVAIL) != 0 ) + if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { /* Clear the Avail/Full bits - which ever is set. */ value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); - value =0; + value = 0; rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); uiData = (UCHAR)value; break; } - dwRetries-- ; - if ( dwRetries == 0 ) + dwRetries--; + if (dwRetries == 0) { - rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); - rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"0x3004 = %x 0x3008 = %x, retries = %d failed.\n",value,value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x3004 = %x 0x3008 = %x, retries = %d failed.\n", value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); return uiData; } - if( !(dwRetries%RETRIES_PER_DELAY) ) + if (!(dwRetries%RETRIES_PER_DELAY)) msleep(1); uiStatus = 0 ; } @@ -129,68 +129,65 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter ) //----------------------------------------------------------------------------- INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, - DWORD dwAddress, - DWORD *pdwData, - DWORD dwNumWords - ) + DWORD dwAddress, + DWORD *pdwData, + DWORD dwNumWords) { DWORD dwIndex = 0; - DWORD dwRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; UINT uiStatus = 0; - UINT value= 0; + UINT value = 0; UINT value1 = 0; UCHAR *pvalue; /* Flush the read and cmd queue. */ - value=( EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH ); - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); - value=0; - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + value = (EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH); + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + value = 0; + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); /* Clear the Avail/Full bits. */ - value=( EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL ); - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); - - value= dwAddress | ( (dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ ); - wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); + value = (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); - while ( dwRetries != 0 ) - { + value = dwAddress | ((dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ); + wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); + while (dwRetries != 0) + { uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if(Adapter->device_removed == TRUE) + if (Adapter->device_removed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got Removed.hence exiting from loop..."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got Removed.hence exiting from loop..."); return -ENODEV; } /* If we are reading 16 bytes we want to be sure that the queue * is full before we read. In the other cases we are ok if the * queue has data available */ - if ( dwNumWords == 4 ) + if (dwNumWords == 4) { - if ( ( uiStatus & EEPROM_READ_DATA_FULL ) != 0 ) + if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) { /* Clear the Avail/Full bits - which ever is set. */ - value = ( uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL) ) ; - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL)); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); break; } } - else if ( dwNumWords == 1 ) + else if (dwNumWords == 1) { - - if ( ( uiStatus & EEPROM_READ_DATA_AVAIL ) != 0 ) + if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { /* We just got Avail and we have to read 32bits so we * need this sleep for Cardbus kind of devices. */ - if (Adapter->chip_id == 0xBECE0210 ) - udelay(800); + if (Adapter->chip_id == 0xBECE0210) + udelay(800); /* Clear the Avail/Full bits - which ever is set. */ - value=( uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL) ); - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL)); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); break; } } @@ -198,25 +195,27 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, uiStatus = 0; dwRetries--; - if(dwRetries == 0) + if (dwRetries == 0) { - value=0; - value1=0; + value = 0; + value1 = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", dwNumWords, value, value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", + dwNumWords, value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); return STATUS_FAILURE; } - if( !(dwRetries%RETRIES_PER_DELAY) ) + + if (!(dwRetries%RETRIES_PER_DELAY)) msleep(1); } - for ( dwIndex = 0; dwIndex < dwNumWords ; dwIndex++ ) + for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) { /* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */ pvalue = (PUCHAR)(pdwData + dwIndex); - value =0; + value = 0; rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[0] = value; @@ -226,7 +225,7 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, pvalue[1] = value; - value =0; + value = 0; rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[2] = value; @@ -256,15 +255,14 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, //----------------------------------------------------------------------------- INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, - DWORD uiOffset, - DWORD *pBuffer - ) + DWORD uiOffset, + DWORD *pBuffer) { - UINT uiData[8] = {0}; + UINT uiData[8] = {0}; UINT uiByteOffset = 0; UINT uiTempOffset = 0; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," ====> "); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ====> "); uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); uiByteOffset = uiOffset - uiTempOffset; @@ -273,18 +271,16 @@ INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, /* A word can overlap at most over 2 pages. In that case we read the * next page too. */ - if ( uiByteOffset > 12 ) + if (uiByteOffset > 12) { ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4); } - memcpy( (PUCHAR) pBuffer, ( ((PUCHAR)&uiData[0]) + uiByteOffset ), 4); + memcpy((PUCHAR)pBuffer, (((PUCHAR)&uiData[0]) + uiByteOffset), 4); return STATUS_SUCCESS; } /* ReadBeceemEEPROM() */ - - INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) { INT Status; @@ -295,7 +291,7 @@ INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) INIT_PARAMS_1_MACADDRESS_ADDRESS, MAC_ADDRESS_SIZE); - if(Status == STATUS_SUCCESS) + if (Status == STATUS_SUCCESS) memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); return Status; @@ -317,62 +313,56 @@ INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) // - if failed. //----------------------------------------------------------------------------- -INT BeceemEEPROMBulkRead( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes) +INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) { - UINT uiData[4] = {0}; - //UINT uiAddress = 0; - UINT uiBytesRemaining = uiNumBytes; - UINT uiIndex = 0; - UINT uiTempOffset = 0; - UINT uiExtraBytes = 0; - UINT uiFailureRetries = 0; + UINT uiData[4] = {0}; + // UINT uiAddress = 0; + UINT uiBytesRemaining = uiNumBytes; + UINT uiIndex = 0; + UINT uiTempOffset = 0; + UINT uiExtraBytes = 0; + UINT uiFailureRetries = 0; PUCHAR pcBuff = (PUCHAR)pBuffer; - - if(uiOffset%MAX_RW_SIZE&& uiBytesRemaining) + if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) { - uiTempOffset = uiOffset - (uiOffset%MAX_RW_SIZE); - uiExtraBytes = uiOffset-uiTempOffset; - ReadBeceemEEPROMBulk(Adapter,uiTempOffset,(PUINT)&uiData[0],4); - if(uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) + uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); + uiExtraBytes = uiOffset - uiTempOffset; + ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); + if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) { - memcpy(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),MAX_RW_SIZE - uiExtraBytes); - + memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), MAX_RW_SIZE - uiExtraBytes); uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes); uiIndex += (MAX_RW_SIZE - uiExtraBytes); uiOffset += (MAX_RW_SIZE - uiExtraBytes); } else { - memcpy(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),uiBytesRemaining); + memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), uiBytesRemaining); uiIndex += uiBytesRemaining; uiOffset += uiBytesRemaining; uiBytesRemaining = 0; } - - } - - while(uiBytesRemaining && uiFailureRetries != 128) + while (uiBytesRemaining && uiFailureRetries != 128) { - if(Adapter->device_removed ) + if (Adapter->device_removed) { return -1; } - if(uiBytesRemaining >= MAX_RW_SIZE) + if (uiBytesRemaining >= MAX_RW_SIZE) { /* For the requests more than or equal to 16 bytes, use bulk * read function to make the access faster. * We read 4 Dwords of data */ - if(0 == ReadBeceemEEPROMBulk(Adapter,uiOffset,&uiData[0],4)) + if (0 == ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4)) { - memcpy(pcBuff+uiIndex,&uiData[0],MAX_RW_SIZE); + memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE); uiOffset += MAX_RW_SIZE; uiBytesRemaining -= MAX_RW_SIZE; uiIndex += MAX_RW_SIZE; @@ -380,40 +370,39 @@ INT BeceemEEPROMBulkRead( else { uiFailureRetries++; - mdelay(3);//sleep for a while before retry... + mdelay(3); //sleep for a while before retry... } } - else if(uiBytesRemaining >= 4) + else if (uiBytesRemaining >= 4) { - if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) + if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { - memcpy(pcBuff+uiIndex,&uiData[0],4); + memcpy(pcBuff + uiIndex, &uiData[0], 4); uiOffset += 4; uiBytesRemaining -= 4; - uiIndex +=4; + uiIndex += 4; } else { uiFailureRetries++; - mdelay(3);//sleep for a while before retry... + mdelay(3); //sleep for a while before retry... } } else - { // Handle the reads less than 4 bytes... + { // Handle the reads less than 4 bytes... PUCHAR pCharBuff = (PUCHAR)pBuffer; pCharBuff += uiIndex; - if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) + if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { - memcpy(pCharBuff,&uiData[0],uiBytesRemaining);//copy only bytes requested. + memcpy(pCharBuff, &uiData[0], uiBytesRemaining); //copy only bytes requested. uiBytesRemaining = 0; } else { uiFailureRetries++; - mdelay(3);//sleep for a while before retry... + mdelay(3); //sleep for a while before retry... } } - } return 0; @@ -435,11 +424,10 @@ INT BeceemEEPROMBulkRead( // - if failed. //----------------------------------------------------------------------------- -static INT BeceemFlashBulkRead( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes) +static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) { UINT uiIndex = 0; UINT uiBytesToRead = uiNumBytes; @@ -447,30 +435,30 @@ static INT BeceemFlashBulkRead( UINT uiPartOffset = 0; int bytes; - if(Adapter->device_removed ) + if (Adapter->device_removed) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device Got Removed "); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device Got Removed"); return -ENODEV; } - //Adding flash Base address -// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); -#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) - Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); - return Status; -#endif + // Adding flash Base address + // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); + return Status; + #endif Adapter->SelectedChip = RESET_CHIP_SELECT; - if(uiOffset % MAX_RW_SIZE) + if (uiOffset % MAX_RW_SIZE) { - BcmDoChipSelect(Adapter,uiOffset); + BcmDoChipSelect(Adapter, uiOffset); uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - uiBytesToRead = MAX_RW_SIZE - (uiOffset%MAX_RW_SIZE); - uiBytesToRead = MIN(uiNumBytes,uiBytesToRead); + uiBytesToRead = MAX_RW_SIZE - (uiOffset % MAX_RW_SIZE); + uiBytesToRead = MIN(uiNumBytes, uiBytesToRead); - bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead); + bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead); if (bytes < 0) { Status = bytes; Adapter->SelectedChip = RESET_CHIP_SELECT; @@ -482,24 +470,22 @@ static INT BeceemFlashBulkRead( uiNumBytes -= uiBytesToRead; } - while(uiNumBytes) + while (uiNumBytes) { - BcmDoChipSelect(Adapter,uiOffset); + BcmDoChipSelect(Adapter, uiOffset); uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - uiBytesToRead = MIN(uiNumBytes,MAX_RW_SIZE); + uiBytesToRead = MIN(uiNumBytes, MAX_RW_SIZE); - bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead); + bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead); if (bytes < 0) { Status = bytes; break; } - uiIndex += uiBytesToRead; uiOffset += uiBytesToRead; uiNumBytes -= uiBytesToRead; - } Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; @@ -520,12 +506,10 @@ static INT BeceemFlashBulkRead( static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter) { - if(IsFlash2x(Adapter)) - return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); + if (IsFlash2x(Adapter)) + return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); else - return 32*1024; - - + return 32 * 1024; } //----------------------------------------------------------------------------- @@ -546,51 +530,48 @@ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) UINT uiData = 0; UINT uiIndex = 0; -// -// if EEPROM is present and already Calibrated,it will have -// 'BECM' string at 0th offset. -// To find the EEPROM size read the possible boundaries of the -// EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will -// result in wrap around. So when we get the End of the EEPROM we will -// get 'BECM' string which is indeed at offset 0. -// - BeceemEEPROMBulkRead(Adapter,&uiData,0x0,4); - if(uiData == BECM) + // + // if EEPROM is present and already Calibrated,it will have + // 'BECM' string at 0th offset. + // To find the EEPROM size read the possible boundaries of the + // EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will + // result in wrap around. So when we get the End of the EEPROM we will + // get 'BECM' string which is indeed at offset 0. + // + BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); + if (uiData == BECM) { - for(uiIndex = 2;uiIndex <=256; uiIndex*=2) + for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { - BeceemEEPROMBulkRead(Adapter,&uiData,uiIndex*1024,4); - if(uiData == BECM) + BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); + if (uiData == BECM) { - return uiIndex*1024; + return uiIndex * 1024; } } } else { -// -// EEPROM may not be present or not programmed -// - - uiData = 0xBABEFACE; - if(0 == BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&uiData,0,4,TRUE)) + // + // EEPROM may not be present or not programmed + // + uiData = 0xBABEFACE; + if (0 == BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE)) { uiData = 0; - for(uiIndex = 2;uiIndex <=256; uiIndex*=2) + for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { - BeceemEEPROMBulkRead(Adapter,&uiData,uiIndex*1024,4); - if(uiData == 0xBABEFACE) + BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); + if (uiData == 0xBABEFACE) { - return uiIndex*1024; + return uiIndex * 1024; } } } - } return 0; } - //----------------------------------------------------------------------------- // Procedure: FlashSectorErase // @@ -606,17 +587,16 @@ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) // //----------------------------------------------------------------------------- - static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, - UINT addr, - UINT numOfSectors) + UINT addr, + UINT numOfSectors) { UINT iIndex = 0, iRetries = 0; UINT uiStatus = 0; UINT value; int bytes; - for(iIndex=0;iIndex\n")); + // DumpDebug(NVM_RW,("flashWrite ====>\n")); value = (FLASH_CMD_WRITE_ENABLE << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write enable in FLASH_SPI_CMDQ_REG register fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); return STATUS_FAILURE; } - if(wrm(Adapter,FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0 ) + + if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DATA Write on FLASH_SPI_WRITEQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); return STATUS_FAILURE; } value = (0x02000000 | (uiOffset & 0xFFFFFF)); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0 ) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programming of FLASH_SPI_CMDQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -718,35 +695,33 @@ static INT flashByteWrite( do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; - } - //__udelay(1); + } + //__udelay(1); bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); return uiStatus; } - iRetries--; - if( iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); + iRetries--; + if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); - }while((uiStatus & 0x1) && (iRetries >0) ); + } while ((uiStatus & 0x1) && (iRetries > 0)); - if(uiStatus & 0x1) + if (uiStatus & 0x1) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE; } return STATUS_SUCCESS; } - - //----------------------------------------------------------------------------- // Procedure: flashWrite // @@ -761,11 +736,9 @@ static INT flashByteWrite( // //----------------------------------------------------------------------------- -static INT flashWrite( - struct bcm_mini_adapter *Adapter, - UINT uiOffset, - PVOID pData) - +static INT flashWrite(struct bcm_mini_adapter *Adapter, + UINT uiOffset, + PVOID pData) { //UINT uiStatus = 0; //INT iRetries = 0; @@ -773,14 +746,13 @@ static INT flashWrite( UINT uiStatus = 0; INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 - UINT value; - UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + UINT uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; int bytes; -// -// need not write 0xFFFFFFFF because write requires an erase and erase will -// make whole sector 0xFFFFFFFF. -// + // + // need not write 0xFFFFFFFF because write requires an erase and erase will + // make whole sector 0xFFFFFFFF. + // if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) { return 0; @@ -788,14 +760,15 @@ static INT flashWrite( value = (FLASH_CMD_WRITE_ENABLE << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0 ) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write Enable of FLASH_SPI_CMDQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - if(wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) + + if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Data write fails..."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); return STATUS_FAILURE; } @@ -803,12 +776,12 @@ static INT flashWrite( do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; - } - //__udelay(1); + } + //__udelay(1); bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; @@ -821,14 +794,14 @@ static INT flashWrite( //currently one rdm/wrm takes 125 us. //Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay) //Hence current implementation cycle will intoduce no delay in current path - if(iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); - }while((uiStatus & 0x1) && (iRetries > 0)); + if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + } while ((uiStatus & 0x1) && (iRetries > 0)); - if(uiStatus & 0x1) + if (uiStatus & 0x1) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE; } return STATUS_SUCCESS; @@ -847,10 +820,9 @@ static INT flashWrite( // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -static INT flashByteWriteStatus( - struct bcm_mini_adapter *Adapter, - UINT uiOffset, - PVOID pData) +static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, + UINT uiOffset, + PVOID pData) { UINT uiStatus = 0; INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 @@ -858,12 +830,12 @@ static INT flashByteWriteStatus( UINT value; int bytes; -// -// need not write 0xFFFFFFFF because write requires an erase and erase will -// make whole sector 0xFFFFFFFF. -// + // + // need not write 0xFFFFFFFF because write requires an erase and erase will + // make whole sector 0xFFFFFFFF. + // - if(0xFF == ulData) + if (0xFF == ulData) { return STATUS_SUCCESS; } @@ -871,31 +843,31 @@ static INT flashByteWriteStatus( // DumpDebug(NVM_RW,("flashWrite ====>\n")); value = (FLASH_CMD_WRITE_ENABLE << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write enable in FLASH_SPI_CMDQ_REG register fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); return STATUS_SUCCESS; } - if(wrm(Adapter,FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) + if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DATA Write on FLASH_SPI_WRITEQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); return STATUS_FAILURE; } value = (0x02000000 | (uiOffset & 0xFFFFFF)); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programming of FLASH_SPI_CMDQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - //msleep(1); + //msleep(1); do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } //__udelay(1); @@ -907,18 +879,18 @@ static INT flashByteWriteStatus( } iRetries--; - if( iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); - }while((uiStatus & 0x1) && (iRetries > 0)); + if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + + } while ((uiStatus & 0x1) && (iRetries > 0)); - if(uiStatus & 0x1) + if (uiStatus & 0x1) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE; } return STATUS_SUCCESS; - } //----------------------------------------------------------------------------- // Procedure: flashWriteStatus @@ -934,68 +906,69 @@ static INT flashByteWriteStatus( // //----------------------------------------------------------------------------- -static INT flashWriteStatus( - struct bcm_mini_adapter *Adapter, - UINT uiOffset, - PVOID pData) +static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, + UINT uiOffset, + PVOID pData) { UINT uiStatus = 0; INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 //UINT uiReadBack = 0; UINT value; - UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + UINT uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; int bytes; -// -// need not write 0xFFFFFFFF because write requires an erase and erase will -// make whole sector 0xFFFFFFFF. -// - if (!memcmp(pData,uiErasePattern,MAX_RW_SIZE)) + // + // need not write 0xFFFFFFFF because write requires an erase and erase will + // make whole sector 0xFFFFFFFF. + // + if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) { return 0; } value = (FLASH_CMD_WRITE_ENABLE << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write Enable of FLASH_SPI_CMDQ_REG fails"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - if(wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) + + if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Data write fails..."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); return STATUS_FAILURE; } - // __udelay(1); + // __udelay(1); do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; - } - //__udelay(1); + } + //__udelay(1); bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); return uiStatus; } - iRetries--; - //this will ensure that in there will be no changes in the current path. - //currently one rdm/wrm takes 125 us. - //Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) - //Hence current implementation cycle will intoduce no delay in current path - if(iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); - }while((uiStatus & 0x1) && (iRetries >0)); + iRetries--; + // this will ensure that in there will be no changes in the current path. + // currently one rdm/wrm takes 125 us. + // Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) + // Hence current implementation cycle will intoduce no delay in current path + if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); - if(uiStatus & 0x1) + } while ((uiStatus & 0x1) && (iRetries > 0)); + + if (uiStatus & 0x1) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE; } return STATUS_SUCCESS; @@ -1014,17 +987,18 @@ static INT flashWriteStatus( // //----------------------------------------------------------------------------- -static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter,ULONG ulWriteStatus) +static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus) { UINT value; - value = (FLASH_CMD_WRITE_ENABLE<< 24); + value = (FLASH_CMD_WRITE_ENABLE << 24); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(20); - value = (FLASH_CMD_STATUS_REG_WRITE<<24)|(ulWriteStatus << 16); + value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(20); } + //----------------------------------------------------------------------------- // Procedure: BcmFlashUnProtectBlock // @@ -1037,98 +1011,96 @@ static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter,ULONG // ULONG - Status value before UnProtect. // //----------------------------------------------------------------------------- -static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter,UINT uiOffset, UINT uiLength) + +static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOffset, UINT uiLength) { - ULONG ulStatus = 0; - ULONG ulWriteStatus = 0; + ULONG ulStatus = 0; + ULONG ulWriteStatus = 0; UINT value; - uiOffset = uiOffset&0x000FFFFF; -// -// Implemented only for 1MB Flash parts. -// - if(FLASH_PART_SST25VF080B == Adapter->ulFlashID) - { + uiOffset = uiOffset&0x000FFFFF; // - // Get Current BP status. + // Implemented only for 1MB Flash parts. // + if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) + { + // + // Get Current BP status. + // value = (FLASH_CMD_STATUS_REG_READ << 24); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(10); - // - // Read status will be WWXXYYZZ. We have to take only WW. - // + // + // Read status will be WWXXYYZZ. We have to take only WW. + // rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus)); ulStatus >>= 24; ulWriteStatus = ulStatus; - - // - // Bits [5-2] give current block level protection status. - // Bit5: BP3 - DONT CARE - // BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 - // 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS - // - - if(ulStatus) + // + // Bits [5-2] give current block level protection status. + // Bit5: BP3 - DONT CARE + // BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 + // 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS + // + + if (ulStatus) { - if((uiOffset+uiLength) <= 0x80000) + if ((uiOffset+uiLength) <= 0x80000) { - // - // Offset comes in lower half of 1MB. Protect the upper half. - // Clear BP1 and BP0 and set BP2. - // + // + // Offset comes in lower half of 1MB. Protect the upper half. + // Clear BP1 and BP0 and set BP2. + // ulWriteStatus |= (0x4<<2); ulWriteStatus &= ~(0x3<<2); } - else if((uiOffset+uiLength) <= 0xC0000) + else if ((uiOffset + uiLength) <= 0xC0000) { - // - // Offset comes below Upper 1/4. Upper 1/4 can be protected. - // Clear BP2 and set BP1 and BP0. - // + // + // Offset comes below Upper 1/4. Upper 1/4 can be protected. + // Clear BP2 and set BP1 and BP0. + // ulWriteStatus |= (0x3<<2); ulWriteStatus &= ~(0x1<<4); } - else if((uiOffset+uiLength) <= 0xE0000) - { - // - // Offset comes below Upper 1/8. Upper 1/8 can be protected. - // Clear BP2 and BP0 and set BP1 - // - ulWriteStatus |= (0x1<<3); - ulWriteStatus &= ~(0x5<<2); - - } - else if((uiOffset+uiLength) <= 0xF0000) - { - // - // Offset comes below Upper 1/16. Only upper 1/16 can be protected. - // Set BP0 and Clear BP2,BP1. - // - ulWriteStatus |= (0x1<<2); - ulWriteStatus &= ~(0x3<<3); - } - else - { - // - // Unblock all. - // Clear BP2,BP1 and BP0. - // - ulWriteStatus &= ~(0x7<<2); - } - - value = (FLASH_CMD_WRITE_ENABLE<< 24); + else if ((uiOffset + uiLength) <= 0xE0000) + { + // + // Offset comes below Upper 1/8. Upper 1/8 can be protected. + // Clear BP2 and BP0 and set BP1 + // + ulWriteStatus |= (0x1<<3); + ulWriteStatus &= ~(0x5<<2); + } + else if ((uiOffset + uiLength) <= 0xF0000) + { + // + // Offset comes below Upper 1/16. Only upper 1/16 can be protected. + // Set BP0 and Clear BP2,BP1. + // + ulWriteStatus |= (0x1<<2); + ulWriteStatus &= ~(0x3<<3); + } + else + { + // + // Unblock all. + // Clear BP2,BP1 and BP0. + // + ulWriteStatus &= ~(0x7<<2); + } + + value = (FLASH_CMD_WRITE_ENABLE << 24); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(20); - value = (FLASH_CMD_STATUS_REG_WRITE<<24)|(ulWriteStatus << 16); + value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(20); - } - } return ulStatus; } + //----------------------------------------------------------------------------- // Procedure: BeceemFlashBulkWrite // @@ -1136,7 +1108,7 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter,UINT uiOffs // // Arguments: // Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. +// pBuffer - Data to be written. // uiOffset - Offset of the flash where data needs to be written to. // uiNumBytes - Number of bytes to be written. // bVerify - read verify flag. @@ -1145,91 +1117,90 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter,UINT uiOffs // //----------------------------------------------------------------------------- -static INT BeceemFlashBulkWrite( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify) +static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) { - PCHAR pTempBuff = NULL; - PUCHAR pcBuffer = (PUCHAR)pBuffer; - UINT uiIndex = 0; - UINT uiOffsetFromSectStart = 0; - UINT uiSectAlignAddr = 0; - UINT uiCurrSectOffsetAddr = 0; - UINT uiSectBoundary = 0; - UINT uiNumSectTobeRead = 0; - UCHAR ucReadBk[16] = {0}; - ULONG ulStatus = 0; - INT Status = STATUS_SUCCESS; - UINT uiTemp = 0; - UINT index = 0; - UINT uiPartOffset = 0; - -#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) - Status = bcmflash_raw_write((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); - return Status; -#endif - - uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); - - //Adding flash Base address -// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); - - uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); - uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); - uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; + PCHAR pTempBuff = NULL; + PUCHAR pcBuffer = (PUCHAR)pBuffer; + UINT uiIndex = 0; + UINT uiOffsetFromSectStart = 0; + UINT uiSectAlignAddr = 0; + UINT uiCurrSectOffsetAddr = 0; + UINT uiSectBoundary = 0; + UINT uiNumSectTobeRead = 0; + UCHAR ucReadBk[16] = {0}; + ULONG ulStatus = 0; + INT Status = STATUS_SUCCESS; + UINT uiTemp = 0; + UINT index = 0; + UINT uiPartOffset = 0; + + #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_write((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); + return Status; + #endif + + uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); + + // Adding flash Base address + // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); + uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); - if(NULL == pTempBuff) + if (NULL == pTempBuff) goto BeceemFlashBulkWrite_EXIT; -// -// check if the data to be written is overlapped across sectors -// - if(uiOffset+uiNumBytes < uiSectBoundary) + // + // check if the data to be written is overlapped across sectors + // + if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; } else { - // Number of sectors = Last sector start address/First sector start address - uiNumSectTobeRead = (uiCurrSectOffsetAddr+uiNumBytes)/Adapter->uiSectorSize; - if((uiCurrSectOffsetAddr+uiNumBytes)%Adapter->uiSectorSize) + // Number of sectors = Last sector start address/First sector start address + uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; + if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) { uiNumSectTobeRead++; } } - //Check whether Requested sector is writable or not in case of flash2x write. But if write call is + // Check whether Requested sector is writable or not in case of flash2x write. But if write call is // for DSD calibration, allow it without checking of sector permission - if(IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) + if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) { index = 0; - uiTemp = uiNumSectTobeRead ; - while(uiTemp) + uiTemp = uiNumSectTobeRead; + while (uiTemp) { - if(IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize ) == FALSE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Sector Starting at offset <0X%X> is not writable", - (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); + if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable", + (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); Status = SECTOR_IS_NOT_WRITABLE; goto BeceemFlashBulkWrite_EXIT; - } - uiTemp = uiTemp - 1; - index = index + 1 ; + } + uiTemp = uiTemp - 1; + index = index + 1 ; } } Adapter->SelectedChip = RESET_CHIP_SELECT; - while(uiNumSectTobeRead) + while (uiNumSectTobeRead) { - //do_gettimeofday(&tv1); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); + // do_gettimeofday(&tv1); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - BcmDoChipSelect(Adapter,uiSectAlignAddr); + BcmDoChipSelect(Adapter, uiSectAlignAddr); - if(0 != BeceemFlashBulkRead(Adapter, + if (0 != BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, uiOffsetFromSectStart, Adapter->uiSectorSize)) @@ -1238,61 +1209,60 @@ static INT BeceemFlashBulkWrite( goto BeceemFlashBulkWrite_EXIT; } - //do_gettimeofday(&tr); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); - - ulStatus = BcmFlashUnProtectBlock(Adapter,uiSectAlignAddr,Adapter->uiSectorSize); + // do_gettimeofday(&tr); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); + ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); - if(uiNumSectTobeRead > 1) + if (uiNumSectTobeRead > 1) { - - memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); - pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); - uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); + pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); + uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); } else { - memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); } - if(IsFlash2x(Adapter)) + if (IsFlash2x(Adapter)) { - SaveHeaderIfPresent(Adapter,(PUCHAR)pTempBuff,uiOffsetFromSectStart); + SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); } - FlashSectorErase(Adapter,uiPartOffset,1); - //do_gettimeofday(&te); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); + FlashSectorErase(Adapter, uiPartOffset, 1); + // do_gettimeofday(&te); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); - for(uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex +=Adapter->ulFlashWriteSize) + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { - if(Adapter->device_removed) + if (Adapter->device_removed) { Status = -1; goto BeceemFlashBulkWrite_EXIT; } - if(STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter,uiPartOffset+uiIndex,(&pTempBuff[uiIndex]))) + + if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) { Status = -1; goto BeceemFlashBulkWrite_EXIT; } } - //do_gettimeofday(&tw); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); - for(uiIndex = 0;uiIndex < Adapter->uiSectorSize;uiIndex += MAX_RW_SIZE) + // do_gettimeofday(&tw); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { - if(STATUS_SUCCESS == BeceemFlashBulkRead(Adapter,(PUINT)ucReadBk,uiOffsetFromSectStart+uiIndex,MAX_RW_SIZE)) + if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { - if(Adapter->ulFlashWriteSize == 1) + if (Adapter->ulFlashWriteSize == 1) { UINT uiReadIndex = 0; - for(uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) + for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) { - if(ucReadBk[uiReadIndex] != pTempBuff[uiIndex+uiReadIndex]) + if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) { - if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex+uiReadIndex,&pTempBuff[uiIndex+uiReadIndex])) + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) { Status = STATUS_FAILURE; goto BeceemFlashBulkWrite_EXIT; @@ -1302,9 +1272,9 @@ static INT BeceemFlashBulkWrite( } else { - if(memcmp(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) { - if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex,&pTempBuff[uiIndex])) + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) { Status = STATUS_FAILURE; goto BeceemFlashBulkWrite_EXIT; @@ -1313,13 +1283,11 @@ static INT BeceemFlashBulkWrite( } } } - //do_gettimeofday(&twv); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); - - - if(ulStatus) + // do_gettimeofday(&twv); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); + if (ulStatus) { - BcmRestoreBlockProtectStatus(Adapter,ulStatus); + BcmRestoreBlockProtectStatus(Adapter, ulStatus); ulStatus = 0; } @@ -1329,119 +1297,117 @@ static INT BeceemFlashBulkWrite( uiOffsetFromSectStart += Adapter->uiSectorSize; uiNumSectTobeRead--; } - //do_gettimeofday(&tv2); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); -// -// Cleanup. -// -BeceemFlashBulkWrite_EXIT: - if(ulStatus) + // do_gettimeofday(&tv2); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); + // + // Cleanup. + // +BeceemFlashBulkWrite_EXIT : + if (ulStatus) { - BcmRestoreBlockProtectStatus(Adapter,ulStatus); + BcmRestoreBlockProtectStatus(Adapter, ulStatus); } - + kfree(pTempBuff); Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; } - //----------------------------------------------------------------------------- // Procedure: BeceemFlashBulkWriteStatus // // Description: Writes to Flash. Checks the SPI status after each write. // // Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the flash where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// bVerify - read verify flag. +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the flash where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// bVerify - read verify flag. // Returns: // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -static INT BeceemFlashBulkWriteStatus( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify) +static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) { - PCHAR pTempBuff = NULL; - PUCHAR pcBuffer = (PUCHAR)pBuffer; - UINT uiIndex = 0; - UINT uiOffsetFromSectStart = 0; - UINT uiSectAlignAddr = 0; - UINT uiCurrSectOffsetAddr = 0; - UINT uiSectBoundary = 0; - UINT uiNumSectTobeRead = 0; - UCHAR ucReadBk[16] = {0}; - ULONG ulStatus = 0; - UINT Status = STATUS_SUCCESS; - UINT uiTemp = 0; - UINT index = 0; - UINT uiPartOffset = 0; - - uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); - - //uiOffset += Adapter->ulFlashCalStart; - //Adding flash Base address -// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); - - uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); - uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); - uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; + PCHAR pTempBuff = NULL; + PUCHAR pcBuffer = (PUCHAR)pBuffer; + UINT uiIndex = 0; + UINT uiOffsetFromSectStart = 0; + UINT uiSectAlignAddr = 0; + UINT uiCurrSectOffsetAddr = 0; + UINT uiSectBoundary = 0; + UINT uiNumSectTobeRead = 0; + UCHAR ucReadBk[16] = {0}; + ULONG ulStatus = 0; + UINT Status = STATUS_SUCCESS; + UINT uiTemp = 0; + UINT index = 0; + UINT uiPartOffset = 0; + + uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); + + // uiOffset += Adapter->ulFlashCalStart; + // Adding flash Base address + // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); + uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); - if(NULL == pTempBuff) + if (NULL == pTempBuff) goto BeceemFlashBulkWriteStatus_EXIT; -// -// check if the data to be written is overlapped across sectors -// - if(uiOffset+uiNumBytes < uiSectBoundary) + // + // check if the data to be written is overlapped across sectors + // + if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; } else { -// Number of sectors = Last sector start address/First sector start address - uiNumSectTobeRead = (uiCurrSectOffsetAddr+uiNumBytes)/Adapter->uiSectorSize; - if((uiCurrSectOffsetAddr+uiNumBytes)%Adapter->uiSectorSize) + // Number of sectors = Last sector start address/First sector start address + uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; + if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) { uiNumSectTobeRead++; } } - if(IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) + if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) { index = 0; - uiTemp = uiNumSectTobeRead ; - while(uiTemp) + uiTemp = uiNumSectTobeRead; + while (uiTemp) { - if(IsOffsetWritable(Adapter,uiOffsetFromSectStart + index * Adapter->uiSectorSize ) == FALSE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Sector Starting at offset <0X%x> is not writable", - (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); + if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable", + (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); Status = SECTOR_IS_NOT_WRITABLE; goto BeceemFlashBulkWriteStatus_EXIT; - } - uiTemp = uiTemp - 1; - index = index + 1 ; + } + uiTemp = uiTemp - 1; + index = index + 1 ; } } Adapter->SelectedChip = RESET_CHIP_SELECT; - while(uiNumSectTobeRead) + while (uiNumSectTobeRead) { uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - BcmDoChipSelect(Adapter,uiSectAlignAddr); - if(0 != BeceemFlashBulkRead(Adapter, + BcmDoChipSelect(Adapter, uiSectAlignAddr); + if (0 != BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, uiOffsetFromSectStart, Adapter->uiSectorSize)) @@ -1450,64 +1416,59 @@ static INT BeceemFlashBulkWriteStatus( goto BeceemFlashBulkWriteStatus_EXIT; } - ulStatus = BcmFlashUnProtectBlock(Adapter,uiOffsetFromSectStart,Adapter->uiSectorSize); + ulStatus = BcmFlashUnProtectBlock(Adapter, uiOffsetFromSectStart, Adapter->uiSectorSize); - if(uiNumSectTobeRead > 1) + if (uiNumSectTobeRead > 1) { - - memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); - pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); - uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); + pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); + uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); } else { - memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); } - if(IsFlash2x(Adapter)) + if (IsFlash2x(Adapter)) { - SaveHeaderIfPresent(Adapter,(PUCHAR)pTempBuff,uiOffsetFromSectStart); + SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); } - FlashSectorErase(Adapter,uiPartOffset,1); - - for(uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex +=Adapter->ulFlashWriteSize) + FlashSectorErase(Adapter, uiPartOffset, 1); + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { - if(Adapter->device_removed) + if (Adapter->device_removed) { Status = -1; goto BeceemFlashBulkWriteStatus_EXIT; } - if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex,&pTempBuff[uiIndex])) + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) { Status = -1; goto BeceemFlashBulkWriteStatus_EXIT; } } - if(bVerify) + if (bVerify) { - for(uiIndex = 0;uiIndex < Adapter->uiSectorSize;uiIndex += MAX_RW_SIZE) + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { - - if(STATUS_SUCCESS == BeceemFlashBulkRead(Adapter,(PUINT)ucReadBk,uiOffsetFromSectStart+uiIndex,MAX_RW_SIZE)) + if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { - if(memcmp(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) { Status = STATUS_FAILURE; goto BeceemFlashBulkWriteStatus_EXIT; } - } - } } - if(ulStatus) + if (ulStatus) { - BcmRestoreBlockProtectStatus(Adapter,ulStatus); + BcmRestoreBlockProtectStatus(Adapter, ulStatus); ulStatus = 0; } @@ -1520,16 +1481,15 @@ static INT BeceemFlashBulkWriteStatus( // // Cleanup. // -BeceemFlashBulkWriteStatus_EXIT: - if(ulStatus) +BeceemFlashBulkWriteStatus_EXIT : + if (ulStatus) { - BcmRestoreBlockProtectStatus(Adapter,ulStatus); + BcmRestoreBlockProtectStatus(Adapter, ulStatus); } kfree(pTempBuff); Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; - } //----------------------------------------------------------------------------- @@ -1544,7 +1504,6 @@ BeceemFlashBulkWriteStatus_EXIT: // //----------------------------------------------------------------------------- - INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) { PCHAR pBuff = kmalloc(BUFFER_4K, GFP_KERNEL); @@ -1555,51 +1514,49 @@ INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; UINT value; INT Status = 0; - if(pBuff == NULL) + + if (pBuff == NULL) { return -1; } - if(0 != BeceemEEPROMBulkRead(Adapter,&uiEepromSize,EEPROM_SIZE_OFFSET,4)) + if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) { - kfree(pBuff); return -1; } uiEepromSize >>= 16; - if(uiEepromSize > 1024*1024) + if (uiEepromSize > 1024 * 1024) { kfree(pBuff); return -1; } + uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); - uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); - - while(uiBytesToCopy) + while (uiBytesToCopy) { - if(0 != BeceemEEPROMBulkRead(Adapter,(PUINT)pBuff,uiCalStartAddr,uiBytesToCopy)) + if (0 != BeceemEEPROMBulkRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiBytesToCopy)) { Status = -1; break; } - wrm(Adapter,uiMemoryLoc,(PCHAR)(((PULONG)pBuff)+uiIndex),uiBytesToCopy); + wrm(Adapter, uiMemoryLoc, (PCHAR)(((PULONG)pBuff) + uiIndex), uiBytesToCopy); uiMemoryLoc += uiBytesToCopy; uiEepromSize -= uiBytesToCopy; uiCalStartAddr += uiBytesToCopy; - uiIndex += uiBytesToCopy/4; - uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + uiIndex += uiBytesToCopy / 4; + uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); } value = 0xbeadbead; - wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-4,&value, sizeof(value)); + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); value = 0xbeadbead; - wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-8,&value, sizeof(value)); + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); kfree(pBuff); return Status; - } //----------------------------------------------------------------------------- @@ -1624,36 +1581,37 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; UINT value; INT Status = 0; -// -// Write the signature first. This will ensure firmware does not access EEPROM. -// + + // + // Write the signature first. This will ensure firmware does not access EEPROM. + // value = 0xbeadbead; wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); value = 0xbeadbead; wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); - if(0 != BeceemNVMRead(Adapter,&uiEepromSize,EEPROM_SIZE_OFFSET, 4)) + if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) { return -1; } uiEepromSize = ntohl(uiEepromSize); uiEepromSize >>= 16; -// -// subtract the auto init section size -// + // + // subtract the auto init section size + // uiEepromSize -= EEPROM_CALPARAM_START; - if(uiEepromSize > 1024*1024) + if (uiEepromSize > 1024 * 1024) { return -1; } pBuff = kmalloc(uiEepromSize, GFP_KERNEL); - if ( pBuff == NULL ) + if (pBuff == NULL) return -1; - if(0 != BeceemNVMRead(Adapter,(PUINT)pBuff,uiCalStartAddr, uiEepromSize)) + if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) { kfree(pBuff); return -1; @@ -1661,26 +1619,25 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) pPtr = pBuff; - uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); - while(uiBytesToCopy) + while (uiBytesToCopy) { - Status = wrm(Adapter,uiMemoryLoc,(PCHAR)pPtr,uiBytesToCopy); - if(Status) + Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"wrm failed with status :%d",Status); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status); break; } pPtr += uiBytesToCopy; uiEepromSize -= uiBytesToCopy; uiMemoryLoc += uiBytesToCopy; - uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); } kfree(pBuff); return Status; - } //----------------------------------------------------------------------------- @@ -1689,45 +1646,44 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) // Description: Read back the data written and verifies. // // Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the flash where data needs to be written to. -// uiNumBytes - Number of bytes to be written. +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the flash where data needs to be written to. +// uiNumBytes - Number of bytes to be written. // Returns: // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -static INT BeceemEEPROMReadBackandVerify( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes) +static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) { - UINT uiRdbk = 0; - UINT uiIndex = 0; - UINT uiData = 0; - UINT auiData[4] = {0}; + UINT uiRdbk = 0; + UINT uiIndex = 0; + UINT uiData = 0; + UINT auiData[4] = {0}; - while(uiNumBytes) + while (uiNumBytes) { - if(Adapter->device_removed ) + if (Adapter->device_removed) { return -1; } - if(uiNumBytes >= MAX_RW_SIZE) - {// for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. - BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); + if (uiNumBytes >= MAX_RW_SIZE) + { // for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. + BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); - if(memcmp(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) { // re-write - BeceemEEPROMBulkWrite(Adapter,(PUCHAR)(pBuffer+uiIndex),uiOffset,MAX_RW_SIZE,FALSE); + BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE); mdelay(3); - BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); + BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); - if(memcmp(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) { return -1; } @@ -1735,18 +1691,17 @@ static INT BeceemEEPROMReadBackandVerify( uiOffset += MAX_RW_SIZE; uiNumBytes -= MAX_RW_SIZE; uiIndex += 4; - } - else if(uiNumBytes >= 4) + else if (uiNumBytes >= 4) { - BeceemEEPROMBulkRead(Adapter,&uiData,uiOffset,4); - if(uiData != pBuffer[uiIndex]) + BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); + if (uiData != pBuffer[uiIndex]) { - //re-write - BeceemEEPROMBulkWrite(Adapter,(PUCHAR)(pBuffer+uiIndex),uiOffset,4,FALSE); + // re-write + BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE); mdelay(3); - BeceemEEPROMBulkRead(Adapter,&uiData,uiOffset,4); - if(uiData != pBuffer[uiIndex]) + BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); + if (uiData != pBuffer[uiIndex]) { return -1; } @@ -1754,20 +1709,18 @@ static INT BeceemEEPROMReadBackandVerify( uiOffset += 4; uiNumBytes -= 4; uiIndex++; - } else { // Handle the reads less than 4 bytes... uiData = 0; - memcpy(&uiData,((PUCHAR)pBuffer)+(uiIndex*sizeof(UINT)),uiNumBytes); - BeceemEEPROMBulkRead(Adapter,&uiRdbk,uiOffset,4); + memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(UINT)), uiNumBytes); + BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4); - if(memcmp(&uiData, &uiRdbk, uiNumBytes)) + if (memcmp(&uiData, &uiRdbk, uiNumBytes)) return -1; uiNumBytes = 0; } - } return 0; @@ -1775,7 +1728,7 @@ static INT BeceemEEPROMReadBackandVerify( static VOID BcmSwapWord(UINT *ptr1) { - UINT tempval = (UINT)*ptr1; + UINT tempval = (UINT)*ptr1; char *ptr2 = (char *)&tempval; char *ptr = (char *)ptr1; @@ -1791,95 +1744,95 @@ static VOID BcmSwapWord(UINT *ptr1) { // Description: Performs page write (16bytes) to the EEPROM // // Arguments: -// Adapter - ptr to Adapter object instance -// uiData - Data to be written. -// uiOffset - Offset of the EEPROM where data needs to be written to. +// Adapter - ptr to Adapter object instance +// uiData - Data to be written. +// uiOffset - Offset of the EEPROM where data needs to be written to. // Returns: // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[], UINT uiOffset ) + +static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[], UINT uiOffset) { - UINT uiRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + UINT uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; UINT uiStatus = 0; UCHAR uiEpromStatus = 0; - UINT value =0 ; + UINT value = 0; /* Flush the Write/Read/Cmd queues. */ - value = ( EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH ); - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); - value = 0 ; - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); + value = (EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH); + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + value = 0; + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); /* Clear the Empty/Avail/Full bits. After this it has been confirmed * that the bit was cleared by reading back the register. See NOTE below. * We also clear the Read queues as we do a EEPROM status register read * later. */ - value = ( EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL ) ; - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + value = (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); /* Enable write */ - value = EEPROM_WRITE_ENABLE ; - wrmalt( Adapter, EEPROM_CMDQ_SPI_REG,&value, sizeof(value) ); + value = EEPROM_WRITE_ENABLE; + wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); /* We can write back to back 8bits * 16 into the queue and as we have * checked for the queue to be empty we can write in a burst. */ value = uiData[0]; BcmSwapWord(&value); - wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); value = uiData[1]; BcmSwapWord(&value); - wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); value = uiData[2]; BcmSwapWord(&value); - wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); value = uiData[3]; BcmSwapWord(&value); - wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG * shows that we see 7 for the EEPROM data write. Which means that * queue got full, also space is available as well as the queue is empty. * This may happen in sequence. */ - value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset ; - wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value) ); + value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset; + wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); /* Ideally we should loop here without tries and eventually succeed. * What we are checking if the previous write has completed, and this * may take time. We should wait till the Empty bit is set. */ uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - while ( ( uiStatus & EEPROM_WRITE_QUEUE_EMPTY ) == 0 ) + while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) { uiRetries--; - if ( uiRetries == 0 ) + if (uiRetries == 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES *RETRIES_PER_DELAY); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); + return STATUS_FAILURE; } - if( !(uiRetries%RETRIES_PER_DELAY) ) - msleep(1); + if (!(uiRetries%RETRIES_PER_DELAY)) + msleep(1); uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if(Adapter->device_removed == TRUE) + if (Adapter->device_removed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem got removed hence exiting from loop...."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop...."); return -ENODEV; } - } - if ( uiRetries != 0 ) + if (uiRetries != 0) { /* Clear the ones that are set - either, Empty/Full/Avail bits */ - value = ( uiStatus & ( EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL ) ); - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL)); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); } /* Here we should check if the EEPROM status register is correct before @@ -1887,82 +1840,79 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy * with the previous write. Note also that issuing this read finally * means the previous write to the EEPROM has completed. */ - uiRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; uiEpromStatus = 0; - while ( uiRetries != 0 ) + while (uiRetries != 0) { - uiEpromStatus = ReadEEPROMStatusRegister( Adapter) ; - if(Adapter->device_removed == TRUE) + uiEpromStatus = ReadEEPROMStatusRegister(Adapter); + if (Adapter->device_removed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop..."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop..."); return -ENODEV; } - if ( ( EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus ) == 0 ) + if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY- uiRetries) ); - return STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries)); + return STATUS_SUCCESS; } uiRetries--; - if ( uiRetries == 0 ) + if (uiRetries == 0) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES *RETRIES_PER_DELAY); - return STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); + return STATUS_FAILURE; } uiEpromStatus = 0; - if( !(uiRetries%RETRIES_PER_DELAY) ) - msleep(1); + if (!(uiRetries%RETRIES_PER_DELAY)) + msleep(1); } - return STATUS_SUCCESS ; + return STATUS_SUCCESS; } /* BeceemEEPROMWritePage */ - //----------------------------------------------------------------------------- // Procedure: BeceemEEPROMBulkWrite // // Description: Performs write to the EEPROM // // Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the EEPROM where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// bVerify - read verify flag. +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the EEPROM where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// bVerify - read verify flag. // Returns: // OSAL_STATUS_CODE // //----------------------------------------------------------------------------- -INT BeceemEEPROMBulkWrite( - struct bcm_mini_adapter *Adapter, - PUCHAR pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify) +INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, + PUCHAR pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) { - UINT uiBytesToCopy = uiNumBytes; - //UINT uiRdbk = 0; - UINT uiData[4] = {0}; - UINT uiIndex = 0; - UINT uiTempOffset = 0; - UINT uiExtraBytes = 0; - //PUINT puiBuffer = (PUINT)pBuffer; - //INT value; + UINT uiBytesToCopy = uiNumBytes; + // UINT uiRdbk = 0; + UINT uiData[4] = {0}; + UINT uiIndex = 0; + UINT uiTempOffset = 0; + UINT uiExtraBytes = 0; + // PUINT puiBuffer = (PUINT)pBuffer; + // INT value; - if(uiOffset%MAX_RW_SIZE && uiBytesToCopy) + if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) { - uiTempOffset = uiOffset - (uiOffset%MAX_RW_SIZE); - uiExtraBytes = uiOffset-uiTempOffset; - + uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); + uiExtraBytes = uiOffset - uiTempOffset; - BeceemEEPROMBulkRead(Adapter,&uiData[0],uiTempOffset,MAX_RW_SIZE); + BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE); - if(uiBytesToCopy >= (16 -uiExtraBytes)) + if (uiBytesToCopy >= (16 - uiExtraBytes)) { - memcpy((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,MAX_RW_SIZE- uiExtraBytes); + memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes); - if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) - return STATUS_FAILURE; + if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) + return STATUS_FAILURE; uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes); uiIndex += (MAX_RW_SIZE - uiExtraBytes); @@ -1970,50 +1920,46 @@ INT BeceemEEPROMBulkWrite( } else { - memcpy((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,uiBytesToCopy); + memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy); - if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) - return STATUS_FAILURE; + if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) + return STATUS_FAILURE; uiIndex += uiBytesToCopy; uiOffset += uiBytesToCopy; uiBytesToCopy = 0; } - - } - while(uiBytesToCopy) + while (uiBytesToCopy) { - if(Adapter->device_removed) + if (Adapter->device_removed) { return -1; } - if(uiBytesToCopy >= MAX_RW_SIZE) + if (uiBytesToCopy >= MAX_RW_SIZE) { - - if (STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, (PUINT) &pBuffer[uiIndex], uiOffset ) ) - return STATUS_FAILURE; + if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset)) + return STATUS_FAILURE; uiIndex += MAX_RW_SIZE; uiOffset += MAX_RW_SIZE; - uiBytesToCopy -= MAX_RW_SIZE; + uiBytesToCopy -= MAX_RW_SIZE; } else { - // - // To program non 16byte aligned data, read 16byte and then update. - // - BeceemEEPROMBulkRead(Adapter,&uiData[0],uiOffset,16); - memcpy(&uiData[0],pBuffer+uiIndex,uiBytesToCopy); + // + // To program non 16byte aligned data, read 16byte and then update. + // + BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16); + memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy); + if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiOffset)) + return STATUS_FAILURE; - if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiOffset ) ) - return STATUS_FAILURE; uiBytesToCopy = 0; } - } return 0; @@ -2035,40 +1981,41 @@ INT BeceemEEPROMBulkWrite( // - if failed. //----------------------------------------------------------------------------- -INT BeceemNVMRead( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes) +INT BeceemNVMRead(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) { INT Status = 0; -#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) - UINT uiTemp = 0, value; -#endif - if(Adapter->eNVMType == NVM_FLASH) + #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT uiTemp = 0, value; + #endif + + if (Adapter->eNVMType == NVM_FLASH) { - if(Adapter->bFlashRawRead == FALSE) + if (Adapter->bFlashRawRead == FALSE) { - if (IsSectionExistInVendorInfo(Adapter,Adapter->eActiveDSD)) - return vendorextnReadSection(Adapter,(PUCHAR)pBuffer,Adapter->eActiveDSD,uiOffset,uiNumBytes); - uiOffset = uiOffset+ Adapter->ulFlashCalStart ; + if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) + return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes); + + uiOffset = uiOffset + Adapter->ulFlashCalStart; } -#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) - Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); -#else - rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - value = 0; - wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); - Status = BeceemFlashBulkRead(Adapter, + #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_read((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); + #else + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); + Status = BeceemFlashBulkRead(Adapter, pBuffer, uiOffset, uiNumBytes); - wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); -#endif + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + #endif } - else if(Adapter->eNVMType == NVM_EEPROM) + else if (Adapter->eNVMType == NVM_EEPROM) { Status = BeceemEEPROMBulkRead(Adapter, pBuffer, @@ -2079,6 +2026,7 @@ INT BeceemNVMRead( { Status = -1; } + return Status; } @@ -2098,72 +2046,72 @@ INT BeceemNVMRead( // - if failed. //----------------------------------------------------------------------------- -INT BeceemNVMWrite( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify) +INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) { INT Status = 0; UINT uiTemp = 0; UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; UINT uiIndex = 0; -#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) - UINT value; -#endif + + #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT value; + #endif + UINT uiFlashOffset = 0; - if(Adapter->eNVMType == NVM_FLASH) + if (Adapter->eNVMType == NVM_FLASH) { - if (IsSectionExistInVendorInfo(Adapter,Adapter->eActiveDSD)) - Status = vendorextnWriteSection(Adapter,(PUCHAR)pBuffer,Adapter->eActiveDSD,uiOffset,uiNumBytes,bVerify); + if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) + Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify); else { uiFlashOffset = uiOffset + Adapter->ulFlashCalStart; -#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) - Status = bcmflash_raw_write((uiFlashOffset/FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer,uiNumBytes); -#else - rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - value = 0; - wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); + #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_write((uiFlashOffset / FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); + #else + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); - if(Adapter->bStatusWrite == TRUE) - { - Status = BeceemFlashBulkWriteStatus(Adapter, - pBuffer, - uiFlashOffset, - uiNumBytes , - bVerify); - } - else - { + if (Adapter->bStatusWrite == TRUE) + { + Status = BeceemFlashBulkWriteStatus(Adapter, + pBuffer, + uiFlashOffset, + uiNumBytes , + bVerify); + } + else + { - Status = BeceemFlashBulkWrite(Adapter, - pBuffer, - uiFlashOffset, - uiNumBytes, - bVerify); - } -#endif + Status = BeceemFlashBulkWrite(Adapter, + pBuffer, + uiFlashOffset, + uiNumBytes, + bVerify); + } + #endif } - - if(uiOffset >= EEPROM_CALPARAM_START) + if (uiOffset >= EEPROM_CALPARAM_START) { uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START); - while(uiNumBytes) + while (uiNumBytes) { - if(uiNumBytes > BUFFER_4K) + if (uiNumBytes > BUFFER_4K) { - wrm(Adapter,(uiMemoryLoc+uiIndex),(PCHAR)(pBuffer+(uiIndex/4)),BUFFER_4K); + wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K); uiNumBytes -= BUFFER_4K; uiIndex += BUFFER_4K; } else { - wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR)(pBuffer+(uiIndex/4)),uiNumBytes); + wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes); uiNumBytes = 0; break; } @@ -2171,45 +2119,43 @@ INT BeceemNVMWrite( } else { - if((uiOffset+uiNumBytes) > EEPROM_CALPARAM_START) + if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) { ULONG ulBytesTobeSkipped = 0; - PUCHAR pcBuffer = (PUCHAR)pBuffer;// char pointer to take care of odd byte cases. + PUCHAR pcBuffer = (PUCHAR)pBuffer; // char pointer to take care of odd byte cases. uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset); ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset); uiOffset += (EEPROM_CALPARAM_START - uiOffset); - while(uiNumBytes) + while (uiNumBytes) { - if(uiNumBytes > BUFFER_4K) + if (uiNumBytes > BUFFER_4K) { - wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR )&pcBuffer[ulBytesTobeSkipped+uiIndex],BUFFER_4K); + wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K); uiNumBytes -= BUFFER_4K; uiIndex += BUFFER_4K; } else { - wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR)&pcBuffer[ulBytesTobeSkipped+uiIndex],uiNumBytes); + wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes); uiNumBytes = 0; break; } } - } } - - // restore the values. - wrmalt(Adapter,0x0f000C80,&uiTemp, sizeof(uiTemp)); + // restore the values. + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); } - else if(Adapter->eNVMType == NVM_EEPROM) + else if (Adapter->eNVMType == NVM_EEPROM) { Status = BeceemEEPROMBulkWrite(Adapter, (PUCHAR)pBuffer, uiOffset, uiNumBytes, bVerify); - if(bVerify) + if (bVerify) { - Status = BeceemEEPROMReadBackandVerify(Adapter,(PUINT)pBuffer,uiOffset,uiNumBytes); + Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes); } } else @@ -2233,47 +2179,41 @@ INT BeceemNVMWrite( // - if failed. //----------------------------------------------------------------------------- -INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize) +INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) { INT Status = -1; FLASH_CS_INFO sFlashCsInfo = {0}; UINT uiTemp = 0; - UINT uiSectorSig = 0; UINT uiCurrentSectorSize = 0; - UINT value; - - rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); value = 0; - wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); -// -// Before updating the sector size in the reserved area, check if already present. -// - BeceemFlashBulkRead(Adapter,(PUINT)&sFlashCsInfo,Adapter->ulFlashControlSectionStart,sizeof(sFlashCsInfo)); + // + // Before updating the sector size in the reserved area, check if already present. + // + BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo)); uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig); uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize); - if(uiSectorSig == FLASH_SECTOR_SIZE_SIG) + if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { - - if((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) + if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) { - if(uiSectorSize == uiCurrentSectorSize) + if (uiSectorSize == uiCurrentSectorSize) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Provided sector size is same as programmed in Flash"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash"); Status = STATUS_SUCCESS; - goto Restore ; + goto Restore; } } } - if((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) + if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) { - sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize); sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG); @@ -2282,17 +2222,13 @@ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize) Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo), TRUE); - - } - Restore : +Restore: // restore the values. - wrmalt(Adapter, 0x0f000C80,&uiTemp, sizeof(uiTemp)); - + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); return Status; - } //----------------------------------------------------------------------------- @@ -2313,44 +2249,42 @@ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSe UINT uiSectorSize = 0; UINT uiSectorSig = 0; - if(Adapter->bSectorSizeOverride && + if (Adapter->bSectorSizeOverride && (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && - Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) { Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; } else { - uiSectorSig = FlashSectorSizeSig; - if(uiSectorSig == FLASH_SECTOR_SIZE_SIG) + if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { uiSectorSize = FlashSectorSize; - // - // If the sector size stored in the FLASH makes sense then use it. - // - if(uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) + // + // If the sector size stored in the FLASH makes sense then use it. + // + if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) { Adapter->uiSectorSize = uiSectorSize; } - //No valid size in FLASH, check if Config file has it. - else if(Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && - Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) + //No valid size in FLASH, check if Config file has it. + else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) { Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; } - // Init to Default, if none of the above works. + // Init to Default, if none of the above works. else { Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; } - } else { - if(Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && - Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) + if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) { Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; } @@ -2361,7 +2295,8 @@ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSe } } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x \n", Adapter->uiSectorSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x\n", Adapter->uiSectorSize); + return Adapter->uiSectorSize; } @@ -2383,20 +2318,20 @@ static INT BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter) /* CHIP Bug : Clear the Avail bits on the Read queue. The default * value on this register is supposed to be 0x00001102. * But we get 0x00001122. */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Fixing reset value on 0x0f003004 register\n" ); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n"); value = EEPROM_READ_DATA_AVAIL; - wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); /* Flush the all the EEPROM queues. */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n"); - value =EEPROM_ALL_QUEUE_FLUSH ; - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n"); + value = EEPROM_ALL_QUEUE_FLUSH; + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); value = 0; - wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); + wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); /* Read the EEPROM Status Register. Just to see, no real purpose. */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter) ); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter)); return STATUS_SUCCESS; } /* BcmInitEEPROMQueues() */ @@ -2418,15 +2353,15 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) BcmValidateNvmType(ps_adapter); BcmInitEEPROMQueues(ps_adapter); - if(ps_adapter->eNVMType == NVM_AUTODETECT) + if (ps_adapter->eNVMType == NVM_AUTODETECT) { ps_adapter->eNVMType = BcmGetNvmType(ps_adapter); - if(ps_adapter->eNVMType == NVM_UNKNOWN) + if (ps_adapter->eNVMType == NVM_UNKNOWN) { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n"); + BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n"); } } - else if(ps_adapter->eNVMType == NVM_FLASH) + else if (ps_adapter->eNVMType == NVM_FLASH) { BcmGetFlashCSInfo(ps_adapter); } @@ -2435,6 +2370,7 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) return STATUS_SUCCESS; } + /***************************************************************************/ /*BcmGetNvmSize : set the EEPROM or flash size in Adapter. * @@ -2447,11 +2383,11 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) { - if(Adapter->eNVMType == NVM_EEPROM) + if (Adapter->eNVMType == NVM_EEPROM) { Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter); } - else if(Adapter->eNVMType == NVM_FLASH) + else if (Adapter->eNVMType == NVM_FLASH) { Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter); } @@ -2469,21 +2405,22 @@ static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) // Returns: // //----------------------------------------------------------------------------- + static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) { - // // if forcing the FLASH through CFG file, we should ensure device really has a FLASH. // Accessing the FLASH address without the FLASH being present can cause hang/freeze etc. // So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice. // - if(Adapter->eNVMType == NVM_FLASH && + if (Adapter->eNVMType == NVM_FLASH && Adapter->chip_id < 0xBECE3300) { Adapter->eNVMType = NVM_AUTODETECT; } } + //----------------------------------------------------------------------------- // Procedure: BcmReadFlashRDID // @@ -2495,55 +2432,56 @@ static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) // Returns: // Flash ID //----------------------------------------------------------------------------- + static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) { ULONG ulRDID = 0; UINT value; -// -// Read ID Instruction. -// - value = (FLASH_CMD_READ_ID<<24); - wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)); -//Delay - udelay(10); -// -// Read SPI READQ REG. The output will be WWXXYYZZ. -// The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. -// - rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); + // + // Read ID Instruction. + // + value = (FLASH_CMD_READ_ID << 24); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); - return (ulRDID >>8); + //Delay + udelay(10); + // + // Read SPI READQ REG. The output will be WWXXYYZZ. + // The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. + // + rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); + return (ulRDID >> 8); } INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { - if(psAdapter == NULL) + if (psAdapter == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); + BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); return -EINVAL; } psAdapter->psFlashCSInfo = (PFLASH_CS_INFO)kzalloc(sizeof(FLASH_CS_INFO), GFP_KERNEL); - if(psAdapter->psFlashCSInfo == NULL) + if (psAdapter->psFlashCSInfo == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate memory for Flash 1.x"); + BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x"); return -ENOMEM; } psAdapter->psFlash2xCSInfo = (PFLASH2X_CS_INFO)kzalloc(sizeof(FLASH2X_CS_INFO), GFP_KERNEL); - if(psAdapter->psFlash2xCSInfo == NULL) + if (psAdapter->psFlash2xCSInfo == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate memory for Flash 2.x"); + BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x"); kfree(psAdapter->psFlashCSInfo); return -ENOMEM; } psAdapter->psFlash2xVendorInfo = (PFLASH2X_VENDORSPECIFIC_INFO)kzalloc(sizeof(FLASH2X_VENDORSPECIFIC_INFO), GFP_KERNEL); - if(psAdapter->psFlash2xVendorInfo == NULL) + if (psAdapter->psFlash2xVendorInfo == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate Vendor Info Memory for Flash 2.x"); + BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x"); kfree(psAdapter->psFlashCSInfo); kfree(psAdapter->psFlash2xCSInfo); return -ENOMEM; @@ -2554,89 +2492,91 @@ INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { - if(psAdapter == NULL) + if (psAdapter == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0," Adapter structure point is NULL"); + BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); return -EINVAL; } kfree(psAdapter->psFlashCSInfo); kfree(psAdapter->psFlash2xCSInfo); kfree(psAdapter->psFlash2xVendorInfo); - return STATUS_SUCCESS ; + return STATUS_SUCCESS; } -static INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo,struct bcm_mini_adapter *Adapter) +static INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo, struct bcm_mini_adapter *Adapter) { UINT Index = 0; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware )); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :"); - for(Index =0; Index <(FLASH2X_TOTAL_SIZE/(DEFAULT_SECTOR_SIZE *16)); Index++) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index, + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :"); + + for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index, (psFlash2xCSInfo->SectorAccessBitMap[Index])); } return STATUS_SUCCESS; } - -static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) +static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) { UINT Index = 0; + psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber); - psFlash2xCSInfo->FlashLayoutVersion= ntohl(psFlash2xCSInfo->FlashLayoutVersion); + psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion); //psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion); - psFlash2xCSInfo->SCSIFirmwareVersion =ntohl(psFlash2xCSInfo->SCSIFirmwareVersion); + psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion); psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage); psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); - psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware ); + psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware); psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage); psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart); psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd); @@ -2675,51 +2615,51 @@ static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End); psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start); psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End); - for(Index =0; Index <(FLASH2X_TOTAL_SIZE/(DEFAULT_SECTOR_SIZE *16)); Index++) + + for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) { - psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]); + psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]); } return STATUS_SUCCESS; } -static INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) +static INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) { //UINT Index = 0; - psFlashCSInfo->MagicNumber =ntohl(psFlashCSInfo->MagicNumber); - psFlashCSInfo->FlashLayoutVersion =ntohl(psFlashCSInfo->FlashLayoutVersion); - psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion); + psFlashCSInfo->MagicNumber = ntohl(psFlashCSInfo->MagicNumber); + psFlashCSInfo->FlashLayoutVersion = ntohl(psFlashCSInfo->FlashLayoutVersion); + psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion); //won't convert according to old assumption - psFlashCSInfo->SCSIFirmwareVersion =(psFlashCSInfo->SCSIFirmwareVersion); - - psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage); - psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware); - psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware ); - psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage); - psFlashCSInfo->OffsetFromZeroForCalibrationStart = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart); - psFlashCSInfo->OffsetFromZeroForCalibrationEnd = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd); - psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart); - psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd); - psFlashCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart); - psFlashCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData); - psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout); - psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature); - psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig); - psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize); - psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize); - psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize); - psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr); - psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize); - psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig); - psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout); + psFlashCSInfo->SCSIFirmwareVersion = (psFlashCSInfo->SCSIFirmwareVersion); + psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage); + psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware); + psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware); + psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage); + psFlashCSInfo->OffsetFromZeroForCalibrationStart = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart); + psFlashCSInfo->OffsetFromZeroForCalibrationEnd = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd); + psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart); + psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd); + psFlashCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart); + psFlashCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData); + psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout); + psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature); + psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig); + psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize); + psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize); + psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize); + psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr); + psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize); + psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig); + psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout); return STATUS_SUCCESS; } static INT IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section) { - return ( Adapter->uiVendorExtnFlag && - (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && - (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS) ); + return (Adapter->uiVendorExtnFlag && + (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && + (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS)); } static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) @@ -2729,16 +2669,16 @@ static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) Adapter->uiVendorExtnFlag = FALSE; - for(i = 0;i < TOTAL_SECTIONS;i++) + for (i = 0; i < TOTAL_SECTIONS; i++) Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS; - if(STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo)) + if (STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo)) return; i = 0; - while(i < TOTAL_SECTIONS) + while (i < TOTAL_SECTIONS) { - if(!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) + if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) { i++; continue; @@ -2746,59 +2686,58 @@ static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) Adapter->uiVendorExtnFlag = TRUE; uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd - - Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart); + Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart); - switch(i) + switch (i) { - case DSD0: - if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; - break; + case DSD0: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; + break; - case DSD1: - if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; - break; + case DSD1: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; + break; - case DSD2: - if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; - break; - case VSA0: - if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; - break; + case DSD2: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; + break; + case VSA0: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; + break; - case VSA1: - if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; - break; - case VSA2: - if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; - break; + case VSA1: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; + break; + case VSA2: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; + break; - default: - break; + default: + break; } i++; } - } //----------------------------------------------------------------------------- @@ -2817,21 +2756,21 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) { //FLASH_CS_INFO sFlashCsInfo = {0}; -#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) - UINT value; -#endif + #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT value; + #endif + UINT uiFlashLayoutMajorVersion; Adapter->uiFlashLayoutMinorVersion = 0; Adapter->uiFlashLayoutMajorVersion = 0; Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR; - Adapter->uiFlashBaseAdd = 0; Adapter->ulFlashCalStart = 0; - memset(Adapter->psFlashCSInfo, 0 ,sizeof(FLASH_CS_INFO)); - memset(Adapter->psFlash2xCSInfo, 0 ,sizeof(FLASH2X_CS_INFO)); + memset(Adapter->psFlashCSInfo, 0 , sizeof(FLASH_CS_INFO)); + memset(Adapter->psFlash2xCSInfo, 0 , sizeof(FLASH2X_CS_INFO)); - if(!Adapter->bDDRInitDone) + if (!Adapter->bDDRInitDone) { { value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; @@ -2839,17 +2778,16 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) } } - // Reading first 8 Bytes to get the Flash Layout // MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) - BeceemFlashBulkRead(Adapter,(PUINT)Adapter->psFlashCSInfo,Adapter->ulFlashControlSectionStart,8); + BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8); Adapter->psFlashCSInfo->FlashLayoutVersion = ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion)); //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); - if(FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) + if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) { uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); @@ -2860,71 +2798,68 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) uiFlashLayoutMajorVersion = 0; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion); - if(uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) + if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) { - BeceemFlashBulkRead(Adapter,(PUINT)Adapter->psFlashCSInfo,Adapter->ulFlashControlSectionStart,sizeof(FLASH_CS_INFO)); + BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(FLASH_CS_INFO)); ConvertEndianOfCSStructure(Adapter->psFlashCSInfo); Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart); - if(!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) + if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) { Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart; } - if((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) && - (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) && - (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) && - (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) + if ((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) && + (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) && + (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) && + (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) { Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize); - Adapter->fpFlashWrite = flashByteWrite; - Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; + Adapter->fpFlashWrite = flashByteWrite; + Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; } else { Adapter->ulFlashWriteSize = MAX_RW_SIZE; Adapter->fpFlashWrite = flashWrite; - Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; + Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; } BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig), - (Adapter->psFlashCSInfo->FlashSectorSize)); - - + (Adapter->psFlashCSInfo->FlashSectorSize)); Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF; - - } else { - if(BcmFlash2xBulkRead(Adapter,(PUINT)Adapter->psFlash2xCSInfo,NO_SECTION_VAL, - Adapter->ulFlashControlSectionStart,sizeof(FLASH2X_CS_INFO))) + if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL, + Adapter->ulFlashControlSectionStart, sizeof(FLASH2X_CS_INFO))) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n"); return STATUS_FAILURE; } + ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo); - BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo,Adapter); - if((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && - (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && - (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && - (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) + BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo, Adapter); + if ((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && + (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && + (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && + (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) { Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize; - Adapter->fpFlashWrite = flashByteWrite; - Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; + Adapter->fpFlashWrite = flashByteWrite; + Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; } else { Adapter->ulFlashWriteSize = MAX_RW_SIZE; Adapter->fpFlashWrite = flashWrite; - Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; + Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; } BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig, - Adapter->psFlash2xCSInfo->FlashSectorSize); + Adapter->psFlash2xCSInfo->FlashSectorSize); UpdateVendorInfo(Adapter); @@ -2932,21 +2867,17 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) BcmGetActiveISO(Adapter); Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF; Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart; - } /* - Concerns: what if CS sector size does not match with this sector size ??? - what is the indication of AccessBitMap in CS in flash 2.x ???? + Concerns: what if CS sector size does not match with this sector size ??? + what is the indication of AccessBitMap in CS in flash 2.x ???? */ Adapter->ulFlashID = BcmReadFlashRDID(Adapter); - Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion; - - return STATUS_SUCCESS ; + return STATUS_SUCCESS; } - //----------------------------------------------------------------------------- // Procedure: BcmGetNvmType // @@ -2964,33 +2895,33 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) { UINT uiData = 0; - BeceemEEPROMBulkRead(Adapter,&uiData,0x0,4); - if(uiData == BECM) + BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); + if (uiData == BECM) { return NVM_EEPROM; } + // // Read control struct and get cal addresses before accessing the flash // BcmGetFlashCSInfo(Adapter); - BeceemFlashBulkRead(Adapter,&uiData,0x0 + Adapter->ulFlashCalStart,4); - if(uiData == BECM) + BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4); + if (uiData == BECM) { return NVM_FLASH; } -// -// even if there is no valid signature on EEPROM/FLASH find out if they really exist. -// if exist select it. -// - if(BcmGetEEPROMSize(Adapter)) + + // + // even if there is no valid signature on EEPROM/FLASH find out if they really exist. + // if exist select it. + // + if (BcmGetEEPROMSize(Adapter)) { return NVM_EEPROM; } -//TBD for Flash. - - + //TBD for Flash. return NVM_UNKNOWN; } @@ -3007,84 +2938,85 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { /* - * Considering all the section for which end offset can be calculated or directly given - * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section - * endoffset can't be calculated or given in CS Structure. - */ + * Considering all the section for which end offset can be calculated or directly given + * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section + * endoffset can't be calculated or given in CS Structure. + */ - INT SectStartOffset = 0 ; + INT SectStartOffset = 0; - SectStartOffset = INVALID_OFFSET ; + SectStartOffset = INVALID_OFFSET; - if(IsSectionExistInVendorInfo(Adapter,eFlashSectionVal)) + if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal)) { return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart; } - switch(eFlashSectionVal) - { - case ISO_IMAGE1 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); - break; - case ISO_IMAGE2 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); - break; - case DSD0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); - break; - case DSD1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); - break; - case DSD2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); - break; - case VSA0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); - break; - case VSA1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); - break; - case VSA2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); - break; - case SCSI : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); - break; - case CONTROL_SECTION : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); - break; - case ISO_IMAGE1_PART2 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); - break; - case ISO_IMAGE1_PART3 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - break; - case ISO_IMAGE2_PART2 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); - break; - case ISO_IMAGE2_PART3 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - break; - default : - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section Does not exist in Flash 2.x"); - SectStartOffset = INVALID_OFFSET; + switch (eFlashSectionVal) + { + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); + break; + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); + break; + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); + break; + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); + break; + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); + break; + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); + break; + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); + break; + case CONTROL_SECTION: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); + break; + case ISO_IMAGE1_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); + break; + case ISO_IMAGE1_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + break; + case ISO_IMAGE2_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); + break; + case ISO_IMAGE2_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + break; + default: + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); + SectStartOffset = INVALID_OFFSET; } + return SectStartOffset; } @@ -3100,78 +3032,78 @@ INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTIO INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { - INT SectEndOffset = 0 ; - SectEndOffset = INVALID_OFFSET; + INT SectEndOffset = 0; - if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) + SectEndOffset = INVALID_OFFSET; + if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) { return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd; } - switch(eFlash2xSectionVal) + switch (eFlash2xSectionVal) { - case ISO_IMAGE1 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End!= UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); - break; - case ISO_IMAGE2 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End!= UNINIT_PTR_IN_CS) && + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) && (IsNonCDLessDevice(Adapter) == FALSE)) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); - break; - case DSD0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd); break; - case DSD1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End); break; - case DSD2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End); break; - case VSA0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd); break; - case VSA1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End); break; - case VSA2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End); break; - case SCSI : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) + - (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); + (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); + break; + case CONTROL_SECTION: + //Not Clear So Putting failure. confirm and fix it. + SectEndOffset = STATUS_FAILURE; + case ISO_IMAGE1_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); + break; + case ISO_IMAGE1_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); + break; + case ISO_IMAGE2_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); break; - case CONTROL_SECTION : - //Not Clear So Putting failure. confirm and fix it. - SectEndOffset = STATUS_FAILURE; - case ISO_IMAGE1_PART2 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End!= UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); - break; - case ISO_IMAGE1_PART3 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End!= UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); - break; - case ISO_IMAGE2_PART2 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); - break; - case ISO_IMAGE2_PART3 : - if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End!= UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); - break; - - default : + case ISO_IMAGE2_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); + break; + default: SectEndOffset = INVALID_OFFSET; } + return SectEndOffset ; } @@ -3187,57 +3119,54 @@ INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_ * return true on success and STATUS_FAILURE on fail. */ -INT BcmFlash2xBulkRead( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - FLASH2X_SECTION_VAL eFlash2xSectionVal, - UINT uiOffsetWithinSectionVal, - UINT uiNumBytes) +INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + FLASH2X_SECTION_VAL eFlash2xSectionVal, + UINT uiOffsetWithinSectionVal, + UINT uiNumBytes) { - INT Status = STATUS_SUCCESS; INT SectionStartOffset = 0; - UINT uiAbsoluteOffset = 0 ; - UINT uiTemp =0, value =0 ; - if(Adapter == NULL) + UINT uiAbsoluteOffset = 0; + UINT uiTemp = 0, value = 0; + + if (Adapter == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); return -EINVAL; } - if(Adapter->device_removed ) + if (Adapter->device_removed) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); return -ENODEV; } //NO_SECTION_VAL means absolute offset is given. - if(eFlash2xSectionVal == NO_SECTION_VAL) + if (eFlash2xSectionVal == NO_SECTION_VAL) SectionStartOffset = 0; else - SectionStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); - if(SectionStartOffset == STATUS_FAILURE ) + if (SectionStartOffset == STATUS_FAILURE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"This Section<%d> does not exixt in Flash 2.x Map ",eFlash2xSectionVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash 2.x Map ", eFlash2xSectionVal); return -EINVAL; } - if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) - return vendorextnReadSection(Adapter,(PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes); + if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) + return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes); //calculating the absolute offset from FLASH; uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset; rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); value = 0; - wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); - - Status= BeceemFlashBulkRead(Adapter, pBuffer,uiAbsoluteOffset,uiNumBytes) ; - + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); + Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes); wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - if(Status) + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status); - return Status ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status); + return Status; } return Status; @@ -3256,42 +3185,42 @@ INT BcmFlash2xBulkRead( * */ -INT BcmFlash2xBulkWrite( - struct bcm_mini_adapter *Adapter, - PUINT pBuffer, - FLASH2X_SECTION_VAL eFlash2xSectVal, - UINT uiOffset, - UINT uiNumBytes, - UINT bVerify) +INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, + PUINT pBuffer, + FLASH2X_SECTION_VAL eFlash2xSectVal, + UINT uiOffset, + UINT uiNumBytes, + UINT bVerify) { - - INT Status = STATUS_SUCCESS; + INT Status = STATUS_SUCCESS; UINT FlashSectValStartOffset = 0; UINT uiTemp = 0, value = 0; - if(Adapter == NULL) + + if (Adapter == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); return -EINVAL; } - if(Adapter->device_removed ) + + if (Adapter->device_removed) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); return -ENODEV; } //NO_SECTION_VAL means absolute offset is given. - if(eFlash2xSectVal == NO_SECTION_VAL) + if (eFlash2xSectVal == NO_SECTION_VAL) FlashSectValStartOffset = 0; else - FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectVal); + FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal); - if(FlashSectValStartOffset == STATUS_FAILURE ) + if (FlashSectValStartOffset == STATUS_FAILURE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"This Section<%d> does not exixt in Flash Map 2.x",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash Map 2.x", eFlash2xSectVal); return -EINVAL; } - if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectVal)) + if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal)) return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify); //calculating the absolute offset from FLASH; @@ -3299,19 +3228,18 @@ INT BcmFlash2xBulkWrite( rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); value = 0; - wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); - Status = BeceemFlashBulkWrite(Adapter, pBuffer,uiOffset,uiNumBytes,bVerify); + Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify); wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - if(Status) + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status); - return Status ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status); + return Status; } return Status; - } /** @@ -3322,35 +3250,36 @@ INT BcmFlash2xBulkWrite( * Return STATUS_SUCESS if get success in setting the right DSD else negaive error code * **/ + static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) { - FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; + FLASH2X_SECTION_VAL uiHighestPriDSD = 0; uiHighestPriDSD = getHighestPriDSD(Adapter); Adapter->eActiveDSD = uiHighestPriDSD; - if(DSD0 == uiHighestPriDSD) + if (DSD0 == uiHighestPriDSD) Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; - if(DSD1 == uiHighestPriDSD) + if (DSD1 == uiHighestPriDSD) Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; - if(DSD2 == uiHighestPriDSD) + if (DSD2 == uiHighestPriDSD) Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; - if(Adapter->eActiveDSD) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); - if(Adapter->eActiveDSD == 0) + if (Adapter->eActiveDSD) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); + if (Adapter->eActiveDSD == 0) { //if No DSD gets Active, Make Active the DSD with WR permission - if(IsSectionWritable(Adapter,DSD2)) + if (IsSectionWritable(Adapter, DSD2)) { Adapter->eActiveDSD = DSD2; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; } - else if(IsSectionWritable(Adapter,DSD1)) + else if (IsSectionWritable(Adapter, DSD1)) { Adapter->eActiveDSD = DSD1; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; } - else if(IsSectionWritable(Adapter,DSD0)) + else if (IsSectionWritable(Adapter, DSD0)) { Adapter->eActiveDSD = DSD0; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; @@ -3360,7 +3289,6 @@ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) return STATUS_SUCCESS; } - /** * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue * @Adapter : Driver private Data Structure @@ -3373,18 +3301,18 @@ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter) { + INT HighestPriISO = 0; - INT HighestPriISO = 0 ; HighestPriISO = getHighestPriISO(Adapter); - Adapter->eActiveISO = HighestPriISO ; - if(Adapter->eActiveISO == ISO_IMAGE2) + Adapter->eActiveISO = HighestPriISO; + if (Adapter->eActiveISO == ISO_IMAGE2) Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); - else if(Adapter->eActiveISO == ISO_IMAGE1) + else if (Adapter->eActiveISO == ISO_IMAGE1) Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); - if(Adapter->eActiveISO) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Active ISO :%x", Adapter->eActiveISO); + if (Adapter->eActiveISO) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active ISO :%x", Adapter->eActiveISO); return STATUS_SUCCESS; } @@ -3399,25 +3327,27 @@ static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter) * Failure:-FALSE, offset is RO * **/ + B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset) { UINT uiSectorNum = 0; - UINT uiWordOfSectorPermission =0; + UINT uiWordOfSectorPermission = 0; UINT uiBitofSectorePermission = 0; B_UINT32 permissionBits = 0; + uiSectorNum = uiOffset/Adapter->uiSectorSize; - //calculating the word having this Sector Access permission from SectorAccessBitMap Array - uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum /16]; + // calculating the word having this Sector Access permission from SectorAccessBitMap Array + uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16]; - //calculating the bit index inside the word for this sector - uiBitofSectorePermission = 2*(15 - uiSectorNum %16); + // calculating the bit index inside the word for this sector + uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16); - //Setting Access permission - permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission) ; + // Setting Access permission + permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission); permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3; - if(permissionBits == SECTOR_READWRITE_PERMISSION) - return TRUE; + if (permissionBits == SECTOR_READWRITE_PERMISSION) + return TRUE; else return FALSE; } @@ -3425,17 +3355,18 @@ B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset) static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) { struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD0 :0X%x", psFlash2xBitMap->DSD0); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD1 :0X%x", psFlash2xBitMap->DSD1); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD2 :0X%x", psFlash2xBitMap->DSD2); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA0 :0X%x", psFlash2xBitMap->VSA0); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA1 :0X%x", psFlash2xBitMap->VSA1); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA2 :0X%x", psFlash2xBitMap->VSA2); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"SCSI :0X%x", psFlash2xBitMap->SCSI); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD0 :0X%x", psFlash2xBitMap->DSD0); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD1 :0X%x", psFlash2xBitMap->DSD1); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD2 :0X%x", psFlash2xBitMap->DSD2); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA0 :0X%x", psFlash2xBitMap->VSA0); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA1 :0X%x", psFlash2xBitMap->VSA1); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA2 :0X%x", psFlash2xBitMap->VSA2); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSI :0X%x", psFlash2xBitMap->SCSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION); return STATUS_SUCCESS; } @@ -3458,33 +3389,31 @@ static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITMAP psFlash2xBitMap) { - - PFLASH2X_CS_INFO psFlash2xCSInfo = Adapter->psFlash2xCSInfo; - FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; - FLASH2X_SECTION_VAL uiHighestPriISO= 0 ; - BOOLEAN SetActiveDSDDone = FALSE ; - BOOLEAN SetActiveISODone = FALSE ; + FLASH2X_SECTION_VAL uiHighestPriDSD = 0; + FLASH2X_SECTION_VAL uiHighestPriISO = 0; + BOOLEAN SetActiveDSDDone = FALSE; + BOOLEAN SetActiveISODone = FALSE; - //For 1.x map all the section except DSD0 will be shown as not present - //This part will be used by calibration tool to detect the number of DSD present in Flash. - if(IsFlash2x(Adapter) == FALSE) + // For 1.x map all the section except DSD0 will be shown as not present + // This part will be used by calibration tool to detect the number of DSD present in Flash. + if (IsFlash2x(Adapter) == FALSE) { psFlash2xBitMap->ISO_IMAGE2 = 0; psFlash2xBitMap->ISO_IMAGE1 = 0; psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; //0xF; //0000(Reseved)1(Active)0(RW)1(valid)1(present) - psFlash2xBitMap->DSD1 = 0 ; - psFlash2xBitMap->DSD2 = 0 ; - psFlash2xBitMap->VSA0 = 0 ; - psFlash2xBitMap->VSA1 = 0 ; - psFlash2xBitMap->VSA2 = 0 ; - psFlash2xBitMap->CONTROL_SECTION = 0 ; - psFlash2xBitMap->SCSI= 0 ; - psFlash2xBitMap->Reserved0 = 0 ; - psFlash2xBitMap->Reserved1 = 0 ; - psFlash2xBitMap->Reserved2 = 0 ; - return STATUS_SUCCESS ; + psFlash2xBitMap->DSD1 = 0; + psFlash2xBitMap->DSD2 = 0; + psFlash2xBitMap->VSA0 = 0; + psFlash2xBitMap->VSA1 = 0; + psFlash2xBitMap->VSA2 = 0; + psFlash2xBitMap->CONTROL_SECTION = 0; + psFlash2xBitMap->SCSI = 0; + psFlash2xBitMap->Reserved0 = 0; + psFlash2xBitMap->Reserved1 = 0; + psFlash2xBitMap->Reserved2 = 0; + return STATUS_SUCCESS; } uiHighestPriDSD = getHighestPriDSD(Adapter); @@ -3493,76 +3422,70 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // IS0 IMAGE 2 /// - if((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->ISO_IMAGE2= psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; + psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; - - if(ReadISOSignature(Adapter,ISO_IMAGE2)== ISO_IMAGE_MAGIC_NUMBER) + if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID; - - //Calculation for extrating the Access permission - if(IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE) + // Calculation for extrating the Access permission + if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE) psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO; - if(SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) + if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) { - psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT ; + psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT; SetActiveISODone = TRUE; } - } /// // IS0 IMAGE 1 /// - if((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. + // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT; - if(ReadISOSignature(Adapter,ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER) + if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission - if(IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE) + // Calculation for extrating the Access permission + if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE) psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO; - if(SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) + if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) { - psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT ; + psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT; SetActiveISODone = TRUE; } } - - /// // DSD2 /// - if((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->DSD2= psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; + psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; - if(ReadDSDSignature(Adapter,DSD2)== DSD_IMAGE_MAGIC_NUMBER) + if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID; - //Calculation for extrating the Access permission - if(IsSectionWritable(Adapter, DSD2) == FALSE) + // Calculation for extrating the Access permission + if (IsSectionWritable(Adapter, DSD2) == FALSE) { psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO; - } else { //Means section is writable - if((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) { - psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT ; - SetActiveDSDDone =TRUE ; + psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT; + SetActiveDSDDone = TRUE; } } } @@ -3570,178 +3493,163 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // DSD 1 /// - if((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->DSD1= psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; - + // Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; - if(ReadDSDSignature(Adapter,DSD1)== DSD_IMAGE_MAGIC_NUMBER) + if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID; - //Calculation for extrating the Access permission - if(IsSectionWritable(Adapter, DSD1) == FALSE) + // Calculation for extrating the Access permission + if (IsSectionWritable(Adapter, DSD1) == FALSE) { psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO; } else { - //Means section is writable - if((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) + // Means section is writable + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) { - psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT ; - SetActiveDSDDone =TRUE ; + psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT; + SetActiveDSDDone = TRUE; } } - } /// //For DSD 0 // - if((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT; - if(ReadDSDSignature(Adapter,DSD0) == DSD_IMAGE_MAGIC_NUMBER) + if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID; - //Setting Access permission - if(IsSectionWritable(Adapter, DSD0) == FALSE) + // Setting Access permission + if (IsSectionWritable(Adapter, DSD0) == FALSE) { psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO; } else { - //Means section is writable - if((SetActiveDSDDone == FALSE) &&(uiHighestPriDSD == DSD0)) + // Means section is writable + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) { - psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT ; - SetActiveDSDDone =TRUE ; + psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT; + SetActiveDSDDone = TRUE; } } } /// - // VSA 0 + // VSA 0 /// - if((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->VSA0= psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; + // Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; - //Setting the Access Bit. Map is not defined hece setting it always valid + // Setting the Access Bit. Map is not defined hece setting it always valid psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID; - //Calculation for extrating the Access permission - if(IsSectionWritable(Adapter, VSA0) == FALSE) + // Calculation for extrating the Access permission + if (IsSectionWritable(Adapter, VSA0) == FALSE) psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO; - //By Default section is Active - psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT ; - + // By Default section is Active + psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT; } - /// - // VSA 1 + // VSA 1 /// - - if((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->VSA1= psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; + // Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; - //Setting the Access Bit. Map is not defined hece setting it always valid - psFlash2xBitMap->VSA1|= FLASH2X_SECTION_VALID; + // Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID; - //Checking For Access permission - if(IsSectionWritable(Adapter, VSA1) == FALSE) + // Checking For Access permission + if (IsSectionWritable(Adapter, VSA1) == FALSE) psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO; - //By Default section is Active - psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT ; - + // By Default section is Active + psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT; } - /// - // VSA 2 + // VSA 2 /// - - if((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->VSA2= psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; - + // Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; - //Setting the Access Bit. Map is not defined hece setting it always valid + // Setting the Access Bit. Map is not defined hece setting it always valid psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID; - //Checking For Access permission - if(IsSectionWritable(Adapter, VSA2) == FALSE) + // Checking For Access permission + if (IsSectionWritable(Adapter, VSA2) == FALSE) psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO; - //By Default section is Active - psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT ; + // By Default section is Active + psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT; } /// // SCSI Section /// - if((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. - psFlash2xBitMap->SCSI= psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; - + // Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; - //Setting the Access Bit. Map is not defined hece setting it always valid - psFlash2xBitMap->SCSI|= FLASH2X_SECTION_VALID; + // Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID; - //Checking For Access permission - if(IsSectionWritable(Adapter, SCSI) == FALSE) + // Checking For Access permission + if (IsSectionWritable(Adapter, SCSI) == FALSE) psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO; - //By Default section is Active - psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT ; - + // By Default section is Active + psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT; } - /// - // Control Section + // Control Section /// - if((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) + if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. + // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT); - - //Setting the Access Bit. Map is not defined hece setting it always valid + // Setting the Access Bit. Map is not defined hece setting it always valid psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID; - //Checking For Access permission - if(IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE) + // Checking For Access permission + if (IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE) psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO; - //By Default section is Active - psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT ; - + // By Default section is Active + psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT; } /// - // For Reserved Sections + // For Reserved Sections /// psFlash2xBitMap->Reserved0 = 0; psFlash2xBitMap->Reserved0 = 0; psFlash2xBitMap->Reserved0 = 0; - BcmDumpFlash2xSectionBitMap(psFlash2xBitMap); - return STATUS_SUCCESS ; - + return STATUS_SUCCESS; } + /** BcmSetActiveSection :- Set Active section is used to make priority field highest over other section of same type. @@ -3752,49 +3660,48 @@ BcmSetActiveSection :- Set Active section is used to make priority field highest Return Value:- Make the priorit highest else return erorr code **/ + INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal) { unsigned int SectImagePriority = 0; - INT Status =STATUS_SUCCESS; + INT Status = STATUS_SUCCESS; //DSD_HEADER sDSD = {0}; //ISO_HEADER sISO = {0}; INT HighestPriDSD = 0 ; INT HighestPriISO = 0; - - - Status = IsSectionWritable(Adapter,eFlash2xSectVal) ; - if(Status != TRUE ) + Status = IsSectionWritable(Adapter, eFlash2xSectVal); + if (Status != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section <%d> is not writable",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal); return STATUS_FAILURE; } - Adapter->bHeaderChangeAllowed = TRUE ; - switch(eFlash2xSectVal) + Adapter->bHeaderChangeAllowed = TRUE; + switch (eFlash2xSectVal) { - case ISO_IMAGE1 : - case ISO_IMAGE2 : - if(ReadISOSignature(Adapter,eFlash2xSectVal)== ISO_IMAGE_MAGIC_NUMBER ) + case ISO_IMAGE1: + case ISO_IMAGE2: + if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) { HighestPriISO = getHighestPriISO(Adapter); - if(HighestPriISO == eFlash2xSectVal ) + if (HighestPriISO == eFlash2xSectVal) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given ISO<%x> already has highest priority",eFlash2xSectVal ); - Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS; break; } SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; - if((SectImagePriority <= 0) && IsSectionWritable(Adapter,HighestPriISO)) + if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) { // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO // by user - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, &SectImagePriority, @@ -3802,152 +3709,144 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), SIGNATURE_SIZE, TRUE); - - if(Status) + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); Status = STATUS_FAILURE; - break ; + break; } HighestPriISO = getHighestPriISO(Adapter); - if(HighestPriISO == eFlash2xSectVal ) + if (HighestPriISO == eFlash2xSectVal) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given ISO<%x> already has highest priority",eFlash2xSectVal ); - Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS; break; } SectImagePriority = 2; - } - + } SectImagePriority = htonl(SectImagePriority); Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - eFlash2xSectVal, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), - SIGNATURE_SIZE, - TRUE); - if(Status) + &SectImagePriority, + eFlash2xSectVal, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); - break ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break; } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); - Status = STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + Status = STATUS_FAILURE; break; } break; - case DSD0 : - case DSD1 : - case DSD2 : - if(ReadDSDSignature(Adapter,eFlash2xSectVal)== DSD_IMAGE_MAGIC_NUMBER) + case DSD0: + case DSD1: + case DSD2: + if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) { HighestPriDSD = getHighestPriDSD(Adapter); - - if((HighestPriDSD == eFlash2xSectVal)) + if ((HighestPriDSD == eFlash2xSectVal)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given DSD<%x> already has highest priority", eFlash2xSectVal); - Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS; break; } - SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1 ; - if(SectImagePriority <= 0) + SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1; + if (SectImagePriority <= 0) { // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD // by user - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - HighestPriDSD, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - SIGNATURE_SIZE, - TRUE); - - if(Status) + &SectImagePriority, + HighestPriDSD, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - break ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break; } HighestPriDSD = getHighestPriDSD(Adapter); - if((HighestPriDSD == eFlash2xSectVal)) + if ((HighestPriDSD == eFlash2xSectVal)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); - Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); + Status = STATUS_SUCCESS; break; } SectImagePriority = htonl(0x2); Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - HighestPriDSD, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - SIGNATURE_SIZE, - TRUE); - - if(Status) + &SectImagePriority, + HighestPriDSD, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - break ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break; } HighestPriDSD = getHighestPriDSD(Adapter); - - if((HighestPriDSD == eFlash2xSectVal)) + if ((HighestPriDSD == eFlash2xSectVal)) { - Status = STATUS_SUCCESS ; + Status = STATUS_SUCCESS; break; } - SectImagePriority = 3 ; + SectImagePriority = 3; } SectImagePriority = htonl(SectImagePriority); Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - eFlash2xSectVal, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - SIGNATURE_SIZE , - TRUE); - if(Status) + &SectImagePriority, + eFlash2xSectVal, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); - Status = STATUS_FAILURE ; - break ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + Status = STATUS_FAILURE; + break; } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); - Status = STATUS_FAILURE ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + Status = STATUS_FAILURE; break; } break; - case VSA0 : - case VSA1 : - case VSA2 : - //Has to be decided - break ; - default : - Status = STATUS_FAILURE ; - break; - + case VSA0: + case VSA1: + case VSA2: + // Has to be decided + break; + default: + Status = STATUS_FAILURE; + break; } - Adapter->bHeaderChangeAllowed = FALSE ; + Adapter->bHeaderChangeAllowed = FALSE; return Status; - } /** @@ -3958,325 +3857,315 @@ BcmCopyISO - Used only for copying the ISO section Return value:- SUCCESS if copies successfully else negative error code **/ + INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut) { - PCHAR Buff = NULL; - FLASH2X_SECTION_VAL eISOReadPart = 0,eISOWritePart = 0; + FLASH2X_SECTION_VAL eISOReadPart = 0, eISOWritePart = 0; UINT uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0; UINT uiTotalDataToCopy = 0; - BOOLEAN IsThisHeaderSector = FALSE ; + BOOLEAN IsThisHeaderSector = FALSE; UINT sigOffset = 0; UINT ISOLength = 0; UINT Status = STATUS_SUCCESS; UINT SigBuff[MAX_RW_SIZE]; UINT i = 0; - if(ReadISOSignature(Adapter,sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) + if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); return STATUS_FAILURE; } Status = BcmFlash2xBulkRead(Adapter, - &ISOLength, - sCopySectStrut.SrcSection, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageSize), - 4); - - if(Status) + &ISOLength, + sCopySectStrut.SrcSection, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageSize), + 4); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n"); return Status; } ISOLength = htonl(ISOLength); - - if(ISOLength % Adapter->uiSectorSize) + if (ISOLength % Adapter->uiSectorSize) { - ISOLength = Adapter->uiSectorSize*(1 + ISOLength/Adapter->uiSectorSize); + ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize); } sigOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL); - if(Buff == NULL) + if (Buff == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for section size"); - return -ENOMEM; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size"); + return -ENOMEM; } - if(sCopySectStrut.SrcSection ==ISO_IMAGE1 && sCopySectStrut.DstSection ==ISO_IMAGE2) + if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) { - eISOReadPart = ISO_IMAGE1 ; - eISOWritePart = ISO_IMAGE2 ; + eISOReadPart = ISO_IMAGE1; + eISOWritePart = ISO_IMAGE2; uiReadOffsetWithinPart = 0; - uiWriteOffsetWithinPart = 0 ; + uiWriteOffsetWithinPart = 0; - uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - if(uiTotalDataToCopy < ISOLength) + if (uiTotalDataToCopy < ISOLength) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); Status = STATUS_FAILURE; goto out; } - uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - if(uiTotalDataToCopy < ISOLength) + if (uiTotalDataToCopy < ISOLength) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); Status = STATUS_FAILURE; goto out; } uiTotalDataToCopy = ISOLength; - CorruptISOSig(Adapter,ISO_IMAGE2); - - while(uiTotalDataToCopy) + CorruptISOSig(Adapter, ISO_IMAGE2); + while (uiTotalDataToCopy) { - if(uiTotalDataToCopy == Adapter->uiSectorSize) + if (uiTotalDataToCopy == Adapter->uiSectorSize) { - //Setting for write of first sector. First sector is assumed to be written in last - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Writing the signature sector"); - eISOReadPart = ISO_IMAGE1 ; + // Setting for write of first sector. First sector is assumed to be written in last + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); + eISOReadPart = ISO_IMAGE1; uiReadOffsetWithinPart = 0; eISOWritePart = ISO_IMAGE2; - uiWriteOffsetWithinPart = 0 ; - IsThisHeaderSector = TRUE ; - + uiWriteOffsetWithinPart = 0; + IsThisHeaderSector = TRUE; } else { - uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize ; - uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize ; + uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; + uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; - if((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) )) + if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { - eISOReadPart = ISO_IMAGE1_PART2 ; + eISOReadPart = ISO_IMAGE1_PART2; uiReadOffsetWithinPart = 0; } - if((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) + + if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { - eISOReadPart = ISO_IMAGE1_PART3 ; + eISOReadPart = ISO_IMAGE1_PART3; uiReadOffsetWithinPart = 0; } - if((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) + + if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { - eISOWritePart = ISO_IMAGE2_PART2 ; + eISOWritePart = ISO_IMAGE2_PART2; uiWriteOffsetWithinPart = 0; } - if((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) + + if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { - eISOWritePart = ISO_IMAGE2_PART3 ; + eISOWritePart = ISO_IMAGE2_PART3; uiWriteOffsetWithinPart = 0; } } Status = BcmFlash2xBulkRead(Adapter, - (PUINT)Buff, - eISOReadPart, - uiReadOffsetWithinPart, - Adapter->uiSectorSize - ); - - if(Status) + (PUINT)Buff, + eISOReadPart, + uiReadOffsetWithinPart, + Adapter->uiSectorSize); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); break; } - if(IsThisHeaderSector == TRUE) + if (IsThisHeaderSector == TRUE) { - //If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); - for(i = 0; i < MAX_RW_SIZE;i++) + for (i = 0; i < MAX_RW_SIZE; i++) *(Buff + sigOffset + i) = 0xFF; } - Adapter->bHeaderChangeAllowed = TRUE ; - + Adapter->bHeaderChangeAllowed = TRUE; Status = BcmFlash2xBulkWrite(Adapter, - (PUINT)Buff, - eISOWritePart, - uiWriteOffsetWithinPart, - Adapter->uiSectorSize, - TRUE); - if(Status) + (PUINT)Buff, + eISOWritePart, + uiWriteOffsetWithinPart, + Adapter->uiSectorSize, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); break; } Adapter->bHeaderChangeAllowed = FALSE; - - if(IsThisHeaderSector == TRUE) + if (IsThisHeaderSector == TRUE) { WriteToFlashWithoutSectorErase(Adapter, - SigBuff, - eISOWritePart, - sigOffset, - MAX_RW_SIZE); - IsThisHeaderSector = FALSE ; + SigBuff, + eISOWritePart, + sigOffset, + MAX_RW_SIZE); + IsThisHeaderSector = FALSE; } //subtracting the written Data - uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; + uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; } - - } - if(sCopySectStrut.SrcSection ==ISO_IMAGE2 && sCopySectStrut.DstSection ==ISO_IMAGE1) + if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) { - eISOReadPart = ISO_IMAGE2 ; - eISOWritePart = ISO_IMAGE1 ; - uiReadOffsetWithinPart = 0; - uiWriteOffsetWithinPart = 0 ; + eISOReadPart = ISO_IMAGE2; + eISOWritePart = ISO_IMAGE1; + uiReadOffsetWithinPart = 0; + uiWriteOffsetWithinPart = 0; - uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - if(uiTotalDataToCopy < ISOLength) + if (uiTotalDataToCopy < ISOLength) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); Status = STATUS_FAILURE; goto out; } - uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start)+ - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) + + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - if(uiTotalDataToCopy < ISOLength) + if (uiTotalDataToCopy < ISOLength) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); Status = STATUS_FAILURE; goto out; } uiTotalDataToCopy = ISOLength; - CorruptISOSig(Adapter,ISO_IMAGE1); + CorruptISOSig(Adapter, ISO_IMAGE1); - while(uiTotalDataToCopy) + while (uiTotalDataToCopy) { - if(uiTotalDataToCopy == Adapter->uiSectorSize) + if (uiTotalDataToCopy == Adapter->uiSectorSize) { //Setting for write of first sector. First sector is assumed to be written in last - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Writing the signature sector"); - eISOReadPart = ISO_IMAGE2 ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); + eISOReadPart = ISO_IMAGE2; uiReadOffsetWithinPart = 0; eISOWritePart = ISO_IMAGE1; - uiWriteOffsetWithinPart = 0 ; + uiWriteOffsetWithinPart = 0; IsThisHeaderSector = TRUE; - } else { - uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize ; - uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize ; + uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; + uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; - if((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) )) + if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { - eISOReadPart = ISO_IMAGE2_PART2 ; + eISOReadPart = ISO_IMAGE2_PART2; uiReadOffsetWithinPart = 0; } - if((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) + + if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { - eISOReadPart = ISO_IMAGE2_PART3 ; + eISOReadPart = ISO_IMAGE2_PART3; uiReadOffsetWithinPart = 0; } - if((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) + + if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { - eISOWritePart = ISO_IMAGE1_PART2 ; + eISOWritePart = ISO_IMAGE1_PART2; uiWriteOffsetWithinPart = 0; } - if((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) + + if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { - eISOWritePart = ISO_IMAGE1_PART3 ; + eISOWritePart = ISO_IMAGE1_PART3; uiWriteOffsetWithinPart = 0; } } Status = BcmFlash2xBulkRead(Adapter, - (PUINT)Buff, - eISOReadPart, - uiReadOffsetWithinPart, - Adapter->uiSectorSize - ); - if(Status) + (PUINT)Buff, + eISOReadPart, + uiReadOffsetWithinPart, + Adapter->uiSectorSize); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); break; } - if(IsThisHeaderSector == TRUE) + if (IsThisHeaderSector == TRUE) { - //If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); - for(i = 0; i < MAX_RW_SIZE;i++) + for (i = 0; i < MAX_RW_SIZE; i++) *(Buff + sigOffset + i) = 0xFF; - } - Adapter->bHeaderChangeAllowed = TRUE ; + Adapter->bHeaderChangeAllowed = TRUE; Status = BcmFlash2xBulkWrite(Adapter, - (PUINT)Buff, - eISOWritePart, - uiWriteOffsetWithinPart, - Adapter->uiSectorSize, - TRUE); - - if(Status) + (PUINT)Buff, + eISOWritePart, + uiWriteOffsetWithinPart, + Adapter->uiSectorSize, + TRUE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); break; } - Adapter->bHeaderChangeAllowed = FALSE ; - - if(IsThisHeaderSector == TRUE) + Adapter->bHeaderChangeAllowed = FALSE; + if (IsThisHeaderSector == TRUE) { WriteToFlashWithoutSectorErase(Adapter, - SigBuff, - eISOWritePart, - sigOffset, - MAX_RW_SIZE); - IsThisHeaderSector = FALSE ; + SigBuff, + eISOWritePart, + sigOffset, + MAX_RW_SIZE); + + IsThisHeaderSector = FALSE; } - //subtracting the written Data - uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; + // subtracting the written Data + uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; } - - } - out: kfree(Buff); return Status; } + /** BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section. It will corrupt the sig, if Section is writable, by making first bytes as zero. @@ -4289,27 +4178,29 @@ Return Value :- **/ + INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { + INT Status = STATUS_SUCCESS; - INT Status = STATUS_SUCCESS ; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Section Value :%x \n", eFlash2xSectionVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal); - if((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) + if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) { Status = CorruptDSDSig(Adapter, eFlash2xSectionVal); } - else if(eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) + else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) { Status = CorruptISOSig(Adapter, eFlash2xSectionVal); } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given Section <%d>does not have Header",eFlash2xSectionVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal); return STATUS_SUCCESS; } return Status; } + /** BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has header and Write Permission. @@ -4321,69 +4212,68 @@ Return Value :- Failure :-Return negative error code **/ + INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { - - UINT uiSignature = 0 ; + UINT uiSignature = 0; UINT uiOffset = 0; - //DSD_HEADER dsdHeader = {0}; - if(Adapter->bSigCorrupted == FALSE) + // DSD_HEADER dsdHeader = {0}; + if (Adapter->bSigCorrupted == FALSE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Signature is not corrupted by driver, hence not restoring\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n"); return STATUS_SUCCESS; } - if(Adapter->bAllDSDWriteAllow == FALSE) + + if (Adapter->bAllDSDWriteAllow == FALSE) { - if(IsSectionWritable(Adapter,eFlashSectionVal) == FALSE) + if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Write signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature"); return SECTOR_IS_NOT_WRITABLE; } } - if((eFlashSectionVal == DSD0) ||(eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) + + if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) { - uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER) ; - uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader ; + uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER); + uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader; - uiOffset += FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber); + uiOffset += FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber); - if((ReadDSDSignature(Adapter,eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) + if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Corrupted Pattern is not there. Hence won't write sig"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig"); return STATUS_FAILURE; } - } - else if((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) + else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) { uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER); - //uiOffset = 0; - uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageMagicNumber); - if((ReadISOSignature(Adapter,eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) + // uiOffset = 0; + uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); + if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Currupted Pattern is not there. Hence won't write sig"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig"); return STATUS_FAILURE; } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal); return STATUS_FAILURE; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Restoring the signature"); - + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature"); Adapter->bHeaderChangeAllowed = TRUE; Adapter->bSigCorrupted = FALSE; - BcmFlash2xBulkWrite(Adapter, &uiSignature,eFlashSectionVal,uiOffset,SIGNATURE_SIZE,TRUE); + BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE); Adapter->bHeaderChangeAllowed = FALSE; - - return STATUS_SUCCESS; } + /** validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write. if requested Bytes goes beyond the Requested section, it reports error. @@ -4394,61 +4284,62 @@ Return values:-Return TRUE is request is valid else FALSE. **/ -INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) + +INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) { - UINT uiNumOfBytes = 0 ; - UINT uiSectStartOffset = 0 ; + UINT uiNumOfBytes = 0; + UINT uiSectStartOffset = 0; UINT uiSectEndOffset = 0; + uiNumOfBytes = psFlash2xReadWrite->numOfBytes; - if(IsSectionExistInFlash(Adapter,psFlash2xReadWrite->Section) != TRUE) + if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section<%x> does not exixt in Flash",psFlash2xReadWrite->Section); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exixt in Flash", psFlash2xReadWrite->Section); return FALSE; } - uiSectStartOffset = BcmGetSectionValStartOffset(Adapter,psFlash2xReadWrite->Section); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n",uiSectStartOffset,psFlash2xReadWrite->Section); - if((psFlash2xReadWrite->Section == ISO_IMAGE1) ||(psFlash2xReadWrite->Section == ISO_IMAGE2)) + uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section); + if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) { - if(psFlash2xReadWrite->Section == ISO_IMAGE1) + if (psFlash2xReadWrite->Section == ISO_IMAGE1) { - uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1)+ - BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1_PART2) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1_PART2)+ - BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1_PART3) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1_PART3); + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) + + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART2) + + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART3); } - else if(psFlash2xReadWrite->Section == ISO_IMAGE2) + else if (psFlash2xReadWrite->Section == ISO_IMAGE2) { - uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2)+ - BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2_PART2) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2_PART2)+ - BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2_PART3) - - BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2_PART3); - + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2) + + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART2) + + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART3) - + BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3); } - //since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset - //it should be added in startoffset. so that check done in last of this function can be valued. - uiSectEndOffset = uiSectStartOffset + uiSectEndOffset ; + // since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset + // it should be added in startoffset. so that check done in last of this function can be valued. + uiSectEndOffset = uiSectStartOffset + uiSectEndOffset; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Total size of the ISO Image :%x",uiSectEndOffset); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset); } else - uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,psFlash2xReadWrite->Section); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x \n",uiSectEndOffset); + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset); - //Checking the boundary condition - if((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) + // Checking the boundary condition + if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) return TRUE; else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Invalid Request...."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request...."); return FALSE; } - } /** @@ -4461,11 +4352,12 @@ Return value:- INT IsFlash2x(struct bcm_mini_adapter *Adapter) { - if(Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER) - return TRUE ; + if (Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER) + return TRUE; else return FALSE; } + /** GetFlashBaseAddr :- Calculate the Flash Base address @Adapater :- Bcm Driver Private Data Structure @@ -4476,38 +4368,36 @@ Return Value:- static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) { - UINT uiBaseAddr = 0; - if(Adapter->bDDRInitDone) + if (Adapter->bDDRInitDone) { /* - For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr - In case of Raw Read... use the default value + For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + In case of Raw Read... use the default value */ - if(Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && - !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)) - ) - uiBaseAddr = Adapter->uiFlashBaseAdd ; + if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && + !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) + uiBaseAddr = Adapter->uiFlashBaseAdd; else uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT; } else { /* - For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr - In case of Raw Read... use the default value + For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + In case of Raw Read... use the default value */ - if(Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && - !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)) - ) + if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && + !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; else uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; } - return uiBaseAddr ; + return uiBaseAddr; } + /** BcmCopySection :- This API is used to copy the One section in another. Both section should be contiuous and of same size. Hence this Will not be applicabe to copy ISO. @@ -4525,108 +4415,108 @@ Return Values- **/ -INT BcmCopySection(struct bcm_mini_adapter *Adapter, - FLASH2X_SECTION_VAL SrcSection, - FLASH2X_SECTION_VAL DstSection, - UINT offset, - UINT numOfBytes) +INT BcmCopySection(struct bcm_mini_adapter *Adapter, + FLASH2X_SECTION_VAL SrcSection, + FLASH2X_SECTION_VAL DstSection, + UINT offset, + UINT numOfBytes) { - UINT BuffSize = 0 ; + UINT BuffSize = 0; UINT BytesToBeCopied = 0; - PUCHAR pBuff = NULL ; - INT Status = STATUS_SUCCESS ; - if(SrcSection == DstSection) + PUCHAR pBuff = NULL; + INT Status = STATUS_SUCCESS; + + if (SrcSection == DstSection) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source and Destination should be different ...try again"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again"); return -EINVAL; } - if((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) + + if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source should be DSD subsection"); - return -EINVAL; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection"); + return -EINVAL; } - if((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) + + if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destination should be DSD subsection"); - return -EINVAL; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection"); + return -EINVAL; } - //if offset zero means have to copy complete secton - - if(numOfBytes == 0) + // if offset zero means have to copy complete secton + if (numOfBytes == 0) { - numOfBytes = BcmGetSectionValEndOffset(Adapter,SrcSection) - - BcmGetSectionValStartOffset(Adapter,SrcSection); + numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection) + - BcmGetSectionValStartOffset(Adapter, SrcSection); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," Section Size :0x%x",numOfBytes); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Section Size :0x%x", numOfBytes); } - if((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter,SrcSection) - - BcmGetSectionValStartOffset(Adapter,SrcSection)) + if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection) + - BcmGetSectionValStartOffset(Adapter, SrcSection)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Input parameters going beyond the section offS: %x numB: %x of Source Section\n", - offset, numOfBytes); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n", + offset, numOfBytes); return -EINVAL; } - if((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter,DstSection) - - BcmGetSectionValStartOffset(Adapter,DstSection)) + if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection) + - BcmGetSectionValStartOffset(Adapter, DstSection)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Input parameters going beyond the section offS: %x numB: %x of Destination Section\n", - offset, numOfBytes); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n", + offset, numOfBytes); return -EINVAL; } - - if(numOfBytes > Adapter->uiSectorSize ) + if (numOfBytes > Adapter->uiSectorSize) BuffSize = Adapter->uiSectorSize; else - BuffSize = numOfBytes ; + BuffSize = numOfBytes; pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL); - if(pBuff == NULL) + if (pBuff == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed.. "); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. "); return -ENOMEM; } - - BytesToBeCopied = Adapter->uiSectorSize ; - if(offset % Adapter->uiSectorSize) + BytesToBeCopied = Adapter->uiSectorSize; + if (offset % Adapter->uiSectorSize) BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize); - if(BytesToBeCopied > numOfBytes) - BytesToBeCopied = numOfBytes ; - - + if (BytesToBeCopied > numOfBytes) + BytesToBeCopied = numOfBytes; Adapter->bHeaderChangeAllowed = TRUE; do { - Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset,BytesToBeCopied); - if(Status) + Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection,BytesToBeCopied); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied); break; } - Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pBuff,DstSection,offset,BytesToBeCopied,FALSE); - if(Status) + Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, FALSE); + if (Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection,BytesToBeCopied); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied); break; } offset = offset + BytesToBeCopied; - numOfBytes = numOfBytes - BytesToBeCopied ; - if(numOfBytes) + numOfBytes = numOfBytes - BytesToBeCopied; + if (numOfBytes) { - if(numOfBytes > Adapter->uiSectorSize ) + if (numOfBytes > Adapter->uiSectorSize) BytesToBeCopied = Adapter->uiSectorSize; else BytesToBeCopied = numOfBytes; } - }while(numOfBytes > 0) ; + } while (numOfBytes > 0); + kfree(pBuff); - Adapter->bHeaderChangeAllowed = FALSE ; + Adapter->bHeaderChangeAllowed = FALSE; + return Status; } @@ -4644,68 +4534,66 @@ Return value :- INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiOffset) { - UINT offsetToProtect = 0,HeaderSizeToProtect =0; - BOOLEAN bHasHeader = FALSE ; - PUCHAR pTempBuff =NULL; + UINT offsetToProtect = 0, HeaderSizeToProtect = 0; + BOOLEAN bHasHeader = FALSE; + PUCHAR pTempBuff = NULL; UINT uiSectAlignAddr = 0; UINT sig = 0; //making the offset sector aligned uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); - - if((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD2)- Adapter->uiSectorSize)|| - (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD1)- Adapter->uiSectorSize)|| - (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD0)- Adapter->uiSectorSize)) + if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) || + (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) || + (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) { - - //offset from the sector boundary having the header map + // offset from the sector boundary having the header map offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; HeaderSizeToProtect = sizeof(DSD_HEADER); - bHasHeader = TRUE ; + bHasHeader = TRUE; } - if(uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1) || - uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2)) + if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) || + uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) { offsetToProtect = 0; HeaderSizeToProtect = sizeof(ISO_HEADER); bHasHeader = TRUE; } - //If Header is present overwrite passed buffer with this - if(bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) + // If Header is present overwrite passed buffer with this + if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) { pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL); - if(pTempBuff == NULL) + if (pTempBuff == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed "); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed"); return -ENOMEM; } - //Read header - BeceemFlashBulkRead(Adapter,(PUINT)pTempBuff,(uiSectAlignAddr + offsetToProtect),HeaderSizeToProtect); - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pTempBuff ,HeaderSizeToProtect); + // Read header + BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect); + BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect); //Replace Buffer content with Header - memcpy(pBuff +offsetToProtect,pTempBuff,HeaderSizeToProtect); + memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect); kfree(pTempBuff); } - if(bHasHeader && Adapter->bSigCorrupted) + if (bHasHeader && Adapter->bSigCorrupted) { - sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber))); + sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber))); sig = ntohl(sig); - if((sig & 0xFF000000) != CORRUPTED_PATTERN) + if ((sig & 0xFF000000) != CORRUPTED_PATTERN) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Desired pattern is not at sig offset. Hence won't restore"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore"); Adapter->bSigCorrupted = FALSE; return STATUS_SUCCESS; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," Corrupted sig is :%X", sig); - *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber)))= htonl(DSD_IMAGE_MAGIC_NUMBER); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Restoring the signature in Header Write only"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig); + *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only"); Adapter->bSigCorrupted = FALSE; } - return STATUS_SUCCESS ; + return STATUS_SUCCESS; } /** @@ -4722,7 +4610,7 @@ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) UINT GPIOConfig = 0; UINT PartNum = 0; - ChipNum = offset / FLASH_PART_SIZE ; + ChipNum = offset / FLASH_PART_SIZE; // // Chip Select mapping to enable flash0. @@ -4733,363 +4621,369 @@ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) // /* - SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured - if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) - Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from - power down modes (Idle mode/shutdown mode), the values in the register will be different. + SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured + if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) + Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from + power down modes (Idle mode/shutdown mode), the values in the register will be different. */ - if(Adapter->SelectedChip == ChipNum) - return STATUS_SUCCESS; + if (Adapter->SelectedChip == ChipNum) + return STATUS_SUCCESS; - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); - Adapter->SelectedChip = ChipNum ; + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); + Adapter->SelectedChip = ChipNum; - //bit[13..12] will select the appropriate chip + // bit[13..12] will select the appropriate chip rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); - { - switch(ChipNum) + switch (ChipNum) { - case 0: - PartNum = 0; - break; - case 1: - PartNum = 3; - GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); - break; - case 2: - PartNum = 1; - GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); - break; - case 3: - PartNum = 2; - GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); - break; + case 0: + PartNum = 0; + break; + case 1: + PartNum = 3; + GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); + break; + case 2: + PartNum = 1; + GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); + break; + case 3: + PartNum = 2; + GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); + break; } } /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired, - nothing to do... can return immediately. - ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. - Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. - These values are not written by host other than during CHIP_SELECT. + nothing to do... can return immediately. + ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. + Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. + These values are not written by host other than during CHIP_SELECT. */ - if(PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3)) + if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3)) return STATUS_SUCCESS; - //clearing the bit[13..12] + // clearing the bit[13..12] FlashConfig &= 0xFFFFCFFF; - FlashConfig = (FlashConfig | (PartNum<psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber), - SIGNATURE_SIZE); + if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs"); + return STATUS_FAILURE; + } + BcmFlash2xBulkRead(Adapter, + &uiDSDsig, + dsd, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber), + SIGNATURE_SIZE); - uiDSDsig = ntohl(uiDSDsig); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD SIG :%x", uiDSDsig); + uiDSDsig = ntohl(uiDSDsig); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD SIG :%x", uiDSDsig); - return uiDSDsig ; + return uiDSDsig; } + INT ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd) { - //UINT priOffsetInMap = 0 ; + // UINT priOffsetInMap = 0 ; unsigned int uiDSDPri = STATUS_FAILURE; - //DSD_HEADER dsdHeader = {0}; - //priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader; - if(IsSectionWritable(Adapter,dsd)) + // DSD_HEADER dsdHeader = {0}; + // priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader; + if (IsSectionWritable(Adapter, dsd)) { - if(ReadDSDSignature(Adapter,dsd)== DSD_IMAGE_MAGIC_NUMBER) + if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) { BcmFlash2xBulkRead(Adapter, - &uiDSDPri, - dsd, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader +FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - 4); + &uiDSDPri, + dsd, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + 4); uiDSDPri = ntohl(uiDSDPri); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD<%x> Priority :%x", dsd, uiDSDPri); - + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD<%x> Priority :%x", dsd, uiDSDPri); } } + return uiDSDPri; } + FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter) { INT DSDHighestPri = STATUS_FAILURE; - INT DsdPri= 0 ; - FLASH2X_SECTION_VAL HighestPriDSD = 0 ; + INT DsdPri = 0; + FLASH2X_SECTION_VAL HighestPriDSD = 0; - if(IsSectionWritable(Adapter,DSD2)) + if (IsSectionWritable(Adapter, DSD2)) { - DSDHighestPri = ReadDSDPriority(Adapter,DSD2); - HighestPriDSD = DSD2 ; + DSDHighestPri = ReadDSDPriority(Adapter, DSD2); + HighestPriDSD = DSD2; } - if(IsSectionWritable(Adapter,DSD1)) + + if (IsSectionWritable(Adapter, DSD1)) { - DsdPri = ReadDSDPriority(Adapter,DSD1); - if(DSDHighestPri < DsdPri) - { - DSDHighestPri = DsdPri ; + DsdPri = ReadDSDPriority(Adapter, DSD1); + if (DSDHighestPri < DsdPri) + { + DSDHighestPri = DsdPri; HighestPriDSD = DSD1; - } + } } - if(IsSectionWritable(Adapter,DSD0)) + + if (IsSectionWritable(Adapter, DSD0)) { - DsdPri = ReadDSDPriority(Adapter,DSD0); - if(DSDHighestPri < DsdPri) - { - DSDHighestPri = DsdPri ; + DsdPri = ReadDSDPriority(Adapter, DSD0); + if (DSDHighestPri < DsdPri) + { + DSDHighestPri = DsdPri; HighestPriDSD = DSD0; - } + } } - if(HighestPriDSD) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri); - return HighestPriDSD ; + if (HighestPriDSD) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri); + + return HighestPriDSD; } INT ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) { - UINT uiISOsig = 0; - //UINT sigoffsetInMap = 0; - //ISO_HEADER ISOHeader = {0}; + UINT uiISOsig = 0; + //UINT sigoffsetInMap = 0; + //ISO_HEADER ISOHeader = {0}; + //sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader; + if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs"); + return STATUS_FAILURE; + } + BcmFlash2xBulkRead(Adapter, + &uiISOsig, + iso, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber), + SIGNATURE_SIZE); - //sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader; - - if(iso != ISO_IMAGE1 && iso != ISO_IMAGE2) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"passed section value is not for ISOs"); - return STATUS_FAILURE; - } - BcmFlash2xBulkRead(Adapter, - &uiISOsig, - iso, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageMagicNumber), - SIGNATURE_SIZE); - - uiISOsig = ntohl(uiISOsig); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO SIG :%x", uiISOsig); + uiISOsig = ntohl(uiISOsig); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO SIG :%x", uiISOsig); - return uiISOsig ; + return uiISOsig; } + INT ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) { - unsigned int ISOPri = STATUS_FAILURE; - if(IsSectionWritable(Adapter,iso)) + if (IsSectionWritable(Adapter, iso)) { - if(ReadISOSignature(Adapter,iso)== ISO_IMAGE_MAGIC_NUMBER) + if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) { BcmFlash2xBulkRead(Adapter, - &ISOPri, - iso, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), - 4); + &ISOPri, + iso, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + 4); ISOPri = ntohl(ISOPri); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO<%x> Priority :%x", iso, ISOPri); - + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO<%x> Priority :%x", iso, ISOPri); } } + return ISOPri; } + FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter) { INT ISOHighestPri = STATUS_FAILURE; - INT ISOPri= 0 ; - FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL ; + INT ISOPri = 0; + FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL; - if(IsSectionWritable(Adapter,ISO_IMAGE2)) + if (IsSectionWritable(Adapter, ISO_IMAGE2)) { - ISOHighestPri = ReadISOPriority(Adapter,ISO_IMAGE2); - HighestPriISO = ISO_IMAGE2 ; + ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2); + HighestPriISO = ISO_IMAGE2; } - if(IsSectionWritable(Adapter,ISO_IMAGE1)) + + if (IsSectionWritable(Adapter, ISO_IMAGE1)) { - ISOPri = ReadISOPriority(Adapter,ISO_IMAGE1); - if(ISOHighestPri < ISOPri) - { - ISOHighestPri = ISOPri ; + ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1); + if (ISOHighestPri < ISOPri) + { + ISOHighestPri = ISOPri; HighestPriISO = ISO_IMAGE1; - } + } } - if(HighestPriISO) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Highest ISO :%x and its Pri :%x",HighestPriISO,ISOHighestPri); - return HighestPriISO ; + if (HighestPriISO) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest ISO :%x and its Pri :%x", HighestPriISO, ISOHighestPri); + + return HighestPriISO; } + INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, - PUINT pBuff, - FLASH2X_SECTION_VAL eFlash2xSectionVal, - UINT uiOffset, - UINT uiNumBytes - ) + PUINT pBuff, + FLASH2X_SECTION_VAL eFlash2xSectionVal, + UINT uiOffset, + UINT uiNumBytes) { -#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) - UINT uiTemp = 0, value = 0 ; - UINT i = 0; - UINT uiPartOffset = 0; -#endif + #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT uiTemp = 0, value = 0; + UINT i = 0; + UINT uiPartOffset = 0; + #endif UINT uiStartOffset = 0; - //Adding section start address + // Adding section start address INT Status = STATUS_SUCCESS; PUCHAR pcBuff = (PUCHAR)pBuff; - if(uiNumBytes % Adapter->ulFlashWriteSize) + if (uiNumBytes % Adapter->ulFlashWriteSize) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes); return STATUS_FAILURE; } - uiStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); - if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) + if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) { return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes); } uiOffset = uiOffset + uiStartOffset; -#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) - Status = bcmflash_raw_writenoerase((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE), pcBuff,uiNumBytes); -#else - rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - value = 0; - wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_writenoerase((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), pcBuff, uiNumBytes); + #else + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); - Adapter->SelectedChip = RESET_CHIP_SELECT; - BcmDoChipSelect(Adapter,uiOffset); - uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + Adapter->SelectedChip = RESET_CHIP_SELECT; + BcmDoChipSelect(Adapter, uiOffset); + uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - for(i = 0 ; i< uiNumBytes; i += Adapter->ulFlashWriteSize) - { - if(Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) - Status = flashByteWrite(Adapter,uiPartOffset, pcBuff); - else - Status = flashWrite(Adapter,uiPartOffset, pcBuff); + for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) + { + if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) + Status = flashByteWrite(Adapter, uiPartOffset, pcBuff); + else + Status = flashWrite(Adapter, uiPartOffset, pcBuff); - if(Status != STATUS_SUCCESS) - break; + if (Status != STATUS_SUCCESS) + break; - pcBuff = pcBuff + Adapter->ulFlashWriteSize; - uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize; - } - wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - Adapter->SelectedChip = RESET_CHIP_SELECT; -#endif + pcBuff = pcBuff + Adapter->ulFlashWriteSize; + uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize; + } + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + Adapter->SelectedChip = RESET_CHIP_SELECT; + #endif return Status; } BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section) { + BOOLEAN SectionPresent = FALSE; - BOOLEAN SectionPresent = FALSE ; - - switch(section) + switch (section) { - - case ISO_IMAGE1 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectionPresent = TRUE ; - break; - case ISO_IMAGE2 : - if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectionPresent = TRUE ; - break; - case DSD0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case DSD1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case DSD2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case VSA0 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case VSA1 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case VSA2 : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case SCSI : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - case CONTROL_SECTION : - if(Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE ; - break; - default : - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section Does not exist in Flash 2.x"); + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE; + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE; + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case CONTROL_SECTION: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + default: + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); SectionPresent = FALSE; } - return SectionPresent ; + + return SectionPresent; } + INT IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section) { - INT offset = STATUS_FAILURE; - INT Status = FALSE; - if(IsSectionExistInFlash(Adapter,Section) == FALSE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section <%d> does not exixt", Section); - return FALSE; - } - offset = BcmGetSectionValStartOffset(Adapter,Section); - if(offset == INVALID_OFFSET) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section<%d> does not exixt", Section); - return FALSE; - } + INT offset = STATUS_FAILURE; + INT Status = FALSE; - if(IsSectionExistInVendorInfo(Adapter,Section)) - { - return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO); - } + if (IsSectionExistInFlash(Adapter, Section) == FALSE) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exixt", Section); + return FALSE; + } + + offset = BcmGetSectionValStartOffset(Adapter, Section); + if (offset == INVALID_OFFSET) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exixt", Section); + return FALSE; + } + + if (IsSectionExistInVendorInfo(Adapter, Section)) + { + return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO); + } - Status = IsOffsetWritable(Adapter,offset); - return Status ; + Status = IsOffsetWritable(Adapter, offset); + return Status; } static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { - PUCHAR pBuff = NULL; UINT sig = 0; UINT uiOffset = 0; @@ -5097,126 +4991,125 @@ static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e UINT uiSectAlignAddr = 0; Adapter->bSigCorrupted = FALSE; - - if(Adapter->bAllDSDWriteAllow == FALSE) + if (Adapter->bAllDSDWriteAllow == FALSE) { - if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) + if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } } pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); - if(pBuff == NULL) + if (pBuff == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); - return -ENOMEM ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); + return -ENOMEM; } uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER); - uiOffset -= MAX_RW_SIZE ; - - BcmFlash2xBulkRead(Adapter, (PUINT)pBuff,eFlash2xSectionVal,uiOffset,MAX_RW_SIZE); + uiOffset -= MAX_RW_SIZE; + BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE); - sig = *((PUINT)(pBuff +12)); - sig =ntohl(sig); - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pBuff,MAX_RW_SIZE); - //Now corrupting the sig by corrupting 4th last Byte. + sig = *((PUINT)(pBuff + 12)); + sig = ntohl(sig); + BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE); + // Now corrupting the sig by corrupting 4th last Byte. *(pBuff + 12) = 0; - if(sig == DSD_IMAGE_MAGIC_NUMBER) + if (sig == DSD_IMAGE_MAGIC_NUMBER) { Adapter->bSigCorrupted = TRUE; - if(Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) + if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) { - uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize -1); - BlockStatus = BcmFlashUnProtectBlock(Adapter,uiSectAlignAddr,Adapter->uiSectorSize); + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); - WriteToFlashWithoutSectorErase(Adapter,(PUINT)(pBuff + 12),eFlash2xSectionVal, - (uiOffset + 12),BYTE_WRITE_SUPPORT); - if(BlockStatus) + WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal, + (uiOffset + 12), BYTE_WRITE_SUPPORT); + if (BlockStatus) { - BcmRestoreBlockProtectStatus(Adapter,BlockStatus); + BcmRestoreBlockProtectStatus(Adapter, BlockStatus); BlockStatus = 0; } } else { - WriteToFlashWithoutSectorErase(Adapter,(PUINT)pBuff,eFlash2xSectionVal, - uiOffset ,MAX_RW_SIZE); + WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, + uiOffset, MAX_RW_SIZE); } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); kfree(pBuff); + return STATUS_FAILURE; } kfree(pBuff); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); - return STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature"); + + return STATUS_SUCCESS; } static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { - PUCHAR pBuff = NULL; UINT sig = 0; UINT uiOffset = 0; Adapter->bSigCorrupted = FALSE; - if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) + if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); - if(pBuff == NULL) + if (pBuff == NULL) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allocate memorey"); - return -ENOMEM ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); + return -ENOMEM; } uiOffset = 0; - BcmFlash2xBulkRead(Adapter, (PUINT)pBuff,eFlash2xSectionVal,uiOffset, MAX_RW_SIZE); + BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE); sig = *((PUINT)pBuff); - sig =ntohl(sig); + sig = ntohl(sig); - //corrupt signature + // corrupt signature *pBuff = 0; - if(sig == ISO_IMAGE_MAGIC_NUMBER) + if (sig == ISO_IMAGE_MAGIC_NUMBER) { Adapter->bSigCorrupted = TRUE; - WriteToFlashWithoutSectorErase(Adapter,(PUINT)pBuff,eFlash2xSectionVal, - uiOffset ,Adapter->ulFlashWriteSize); + WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, + uiOffset, Adapter->ulFlashWriteSize); } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); kfree(pBuff); + return STATUS_FAILURE; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pBuff,MAX_RW_SIZE); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature"); + BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE); kfree(pBuff); - return STATUS_SUCCESS ; + return STATUS_SUCCESS; } BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter) { - if(Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG) + if (Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG) return TRUE; else - return FALSE ; + return FALSE; } - -- GitLab From a2940b635bbe6bc4b7d6156eddc92fdbe1037bd9 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 6 Jun 2012 22:54:28 -0400 Subject: [PATCH 0546/5711] Staging: bcm: Properly format braces in nvm.c This patch cuddles braces as reported by checkpatch.pl. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 1784 ++++++++++++++----------------------- 1 file changed, 659 insertions(+), 1125 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index 2bb87c93b0e9..66001fcd4402 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -74,20 +74,17 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) value = EEPROM_READ_STATUS_REGISTER; wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); - while (dwRetries != 0) - { + while (dwRetries != 0) { value = 0; uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if (Adapter->device_removed == TRUE) - { + if (Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting...."); break; } /* Wait for Avail bit to be set. */ - if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) - { + if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { /* Clear the Avail/Full bits - which ever is set. */ value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); @@ -100,8 +97,7 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) } dwRetries--; - if (dwRetries == 0) - { + if (dwRetries == 0) { rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x3004 = %x 0x3008 = %x, retries = %d failed.\n", value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); @@ -153,12 +149,10 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, value = dwAddress | ((dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ); wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); - while (dwRetries != 0) - { + while (dwRetries != 0) { uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if (Adapter->device_removed == TRUE) - { + if (Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got Removed.hence exiting from loop..."); return -ENODEV; } @@ -166,20 +160,15 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, /* If we are reading 16 bytes we want to be sure that the queue * is full before we read. In the other cases we are ok if the * queue has data available */ - if (dwNumWords == 4) - { - if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) - { + if (dwNumWords == 4) { + if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) { /* Clear the Avail/Full bits - which ever is set. */ value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL)); wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); break; } - } - else if (dwNumWords == 1) - { - if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) - { + } else if (dwNumWords == 1) { + if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { /* We just got Avail and we have to read 32bits so we * need this sleep for Cardbus kind of devices. */ if (Adapter->chip_id == 0xBECE0210) @@ -195,8 +184,7 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, uiStatus = 0; dwRetries--; - if (dwRetries == 0) - { + if (dwRetries == 0) { value = 0; value1 = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); @@ -210,8 +198,7 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, msleep(1); } - for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) - { + for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) { /* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */ pvalue = (PUCHAR)(pdwData + dwIndex); @@ -272,9 +259,7 @@ INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, /* A word can overlap at most over 2 pages. In that case we read the * next page too. */ if (uiByteOffset > 12) - { ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4); - } memcpy((PUCHAR)pBuffer, (((PUCHAR)&uiData[0]) + uiByteOffset), 4); @@ -327,20 +312,16 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, UINT uiFailureRetries = 0; PUCHAR pcBuff = (PUCHAR)pBuffer; - if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) - { + if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) { uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); uiExtraBytes = uiOffset - uiTempOffset; ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); - if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) - { + if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) { memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), MAX_RW_SIZE - uiExtraBytes); uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes); uiIndex += (MAX_RW_SIZE - uiExtraBytes); uiOffset += (MAX_RW_SIZE - uiExtraBytes); - } - else - { + } else { memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), uiBytesRemaining); uiIndex += uiBytesRemaining; uiOffset += uiBytesRemaining; @@ -348,57 +329,41 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, } } - while (uiBytesRemaining && uiFailureRetries != 128) - { + while (uiBytesRemaining && uiFailureRetries != 128) { if (Adapter->device_removed) - { return -1; - } - if (uiBytesRemaining >= MAX_RW_SIZE) - { + if (uiBytesRemaining >= MAX_RW_SIZE) { /* For the requests more than or equal to 16 bytes, use bulk * read function to make the access faster. * We read 4 Dwords of data */ - if (0 == ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4)) - { + if (0 == ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4)) { memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE); uiOffset += MAX_RW_SIZE; uiBytesRemaining -= MAX_RW_SIZE; uiIndex += MAX_RW_SIZE; - } - else - { + } else { uiFailureRetries++; mdelay(3); //sleep for a while before retry... } - } - else if (uiBytesRemaining >= 4) - { - if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) - { + } else if (uiBytesRemaining >= 4) { + if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { memcpy(pcBuff + uiIndex, &uiData[0], 4); uiOffset += 4; uiBytesRemaining -= 4; uiIndex += 4; - } - else - { + } else { uiFailureRetries++; mdelay(3); //sleep for a while before retry... } - } - else - { // Handle the reads less than 4 bytes... + } else { + // Handle the reads less than 4 bytes... PUCHAR pCharBuff = (PUCHAR)pBuffer; pCharBuff += uiIndex; - if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) - { + if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { memcpy(pCharBuff, &uiData[0], uiBytesRemaining); //copy only bytes requested. uiBytesRemaining = 0; - } - else - { + } else { uiFailureRetries++; mdelay(3); //sleep for a while before retry... } @@ -435,8 +400,7 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, UINT uiPartOffset = 0; int bytes; - if (Adapter->device_removed) - { + if (Adapter->device_removed) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device Got Removed"); return -ENODEV; } @@ -450,8 +414,7 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, Adapter->SelectedChip = RESET_CHIP_SELECT; - if (uiOffset % MAX_RW_SIZE) - { + if (uiOffset % MAX_RW_SIZE) { BcmDoChipSelect(Adapter, uiOffset); uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); @@ -470,8 +433,7 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, uiNumBytes -= uiBytesToRead; } - while (uiNumBytes) - { + while (uiNumBytes) { BcmDoChipSelect(Adapter, uiOffset); uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); @@ -539,33 +501,23 @@ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) // get 'BECM' string which is indeed at offset 0. // BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); - if (uiData == BECM) - { - for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) - { + if (uiData == BECM) { + for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); if (uiData == BECM) - { return uiIndex * 1024; - } } - } - else - { + } else { // // EEPROM may not be present or not programmed // uiData = 0xBABEFACE; - if (0 == BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE)) - { + if (0 == BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE)) { uiData = 0; - for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) - { + for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); if (uiData == 0xBABEFACE) - { return uiIndex * 1024; - } } } } @@ -596,8 +548,7 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, UINT value; int bytes; - for (iIndex = 0; iIndex < numOfSectors; iIndex++) - { + for (iIndex = 0; iIndex < numOfSectors; iIndex++) { value = 0x06000000; wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); @@ -605,11 +556,9 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); iRetries = 0; - do - { + do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -627,8 +576,7 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, msleep(10); } while ((uiStatus & 0x1) && (iRetries < 400)); - if (uiStatus & 0x1) - { + if (uiStatus & 0x1) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "iRetries crossing the limit of 80000\n"); return STATUS_FAILURE; } @@ -666,37 +614,30 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, // if (0xFF == ulData) - { return STATUS_SUCCESS; - } // DumpDebug(NVM_RW,("flashWrite ====>\n")); value = (FLASH_CMD_WRITE_ENABLE << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); return STATUS_FAILURE; } - if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) - { + if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); return STATUS_FAILURE; } value = (0x02000000 | (uiOffset & 0xFFFFFF)); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } //__udelay(950); - do - { + do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -713,8 +654,7 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, } while ((uiStatus & 0x1) && (iRetries > 0)); - if (uiStatus & 0x1) - { + if (uiStatus & 0x1) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); return STATUS_FAILURE; } @@ -754,30 +694,24 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, // make whole sector 0xFFFFFFFF. // if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) - { return 0; - } value = (FLASH_CMD_WRITE_ENABLE << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) - { + if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); return STATUS_FAILURE; } //__udelay(950); - do - { + do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -798,8 +732,7 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, msleep(1); } while ((uiStatus & 0x1) && (iRetries > 0)); - if (uiStatus & 0x1) - { + if (uiStatus & 0x1) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); return STATUS_FAILURE; } @@ -836,37 +769,30 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, // if (0xFF == ulData) - { return STATUS_SUCCESS; - } // DumpDebug(NVM_RW,("flashWrite ====>\n")); value = (FLASH_CMD_WRITE_ENABLE << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); return STATUS_SUCCESS; } - if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) - { + if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); return STATUS_FAILURE; } value = (0x02000000 | (uiOffset & 0xFFFFFF)); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } //msleep(1); - do - { + do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -884,8 +810,7 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, } while ((uiStatus & 0x1) && (iRetries > 0)); - if (uiStatus & 0x1) - { + if (uiStatus & 0x1) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); return STATUS_FAILURE; } @@ -922,29 +847,23 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, // make whole sector 0xFFFFFFFF. // if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) - { return 0; - } value = (FLASH_CMD_WRITE_ENABLE << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) - { + if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); return STATUS_FAILURE; } // __udelay(1); - do - { + do { value = (FLASH_CMD_STATUS_REG_READ << 24); - if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) - { + if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } @@ -965,8 +884,7 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, } while ((uiStatus & 0x1) && (iRetries > 0)); - if (uiStatus & 0x1) - { + if (uiStatus & 0x1) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); return STATUS_FAILURE; } @@ -1022,8 +940,7 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOff // // Implemented only for 1MB Flash parts. // - if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) - { + if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) { // // Get Current BP status. // @@ -1043,46 +960,36 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOff // 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS // - if (ulStatus) - { - if ((uiOffset+uiLength) <= 0x80000) - { + if (ulStatus) { + if ((uiOffset+uiLength) <= 0x80000) { // // Offset comes in lower half of 1MB. Protect the upper half. // Clear BP1 and BP0 and set BP2. // ulWriteStatus |= (0x4<<2); ulWriteStatus &= ~(0x3<<2); - } - else if ((uiOffset + uiLength) <= 0xC0000) - { + } else if ((uiOffset + uiLength) <= 0xC0000) { // // Offset comes below Upper 1/4. Upper 1/4 can be protected. // Clear BP2 and set BP1 and BP0. // ulWriteStatus |= (0x3<<2); ulWriteStatus &= ~(0x1<<4); - } - else if ((uiOffset + uiLength) <= 0xE0000) - { + } else if ((uiOffset + uiLength) <= 0xE0000) { // // Offset comes below Upper 1/8. Upper 1/8 can be protected. // Clear BP2 and BP0 and set BP1 // ulWriteStatus |= (0x1<<3); ulWriteStatus &= ~(0x5<<2); - } - else if ((uiOffset + uiLength) <= 0xF0000) - { + } else if ((uiOffset + uiLength) <= 0xF0000) { // // Offset comes below Upper 1/16. Only upper 1/16 can be protected. // Set BP0 and Clear BP2,BP1. // ulWriteStatus |= (0x1<<2); ulWriteStatus &= ~(0x3<<3); - } - else - { + } else { // // Unblock all. // Clear BP2,BP1 and BP0. @@ -1158,30 +1065,22 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, // // check if the data to be written is overlapped across sectors // - if (uiOffset+uiNumBytes < uiSectBoundary) - { + if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; - } - else - { + } else { // Number of sectors = Last sector start address/First sector start address uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) - { uiNumSectTobeRead++; - } } // Check whether Requested sector is writable or not in case of flash2x write. But if write call is // for DSD calibration, allow it without checking of sector permission - if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) - { + if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) { index = 0; uiTemp = uiNumSectTobeRead; - while (uiTemp) - { - if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) - { + while (uiTemp) { + if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable", (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); Status = SECTOR_IS_NOT_WRITABLE; @@ -1192,8 +1091,7 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, } } Adapter->SelectedChip = RESET_CHIP_SELECT; - while (uiNumSectTobeRead) - { + while (uiNumSectTobeRead) { // do_gettimeofday(&tv1); // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); @@ -1203,8 +1101,7 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, if (0 != BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, uiOffsetFromSectStart, - Adapter->uiSectorSize)) - { + Adapter->uiSectorSize)) { Status = -1; goto BeceemFlashBulkWrite_EXIT; } @@ -1214,36 +1111,28 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); - if (uiNumSectTobeRead > 1) - { + if (uiNumSectTobeRead > 1) { memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); - } - else - { + } else { memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); } if (IsFlash2x(Adapter)) - { SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); - } FlashSectorErase(Adapter, uiPartOffset, 1); // do_gettimeofday(&te); // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); - for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) - { - if (Adapter->device_removed) - { + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { + if (Adapter->device_removed) { Status = -1; goto BeceemFlashBulkWrite_EXIT; } - if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) - { + if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) { Status = -1; goto BeceemFlashBulkWrite_EXIT; } @@ -1251,31 +1140,21 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, // do_gettimeofday(&tw); // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); - for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) - { - if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) - { - if (Adapter->ulFlashWriteSize == 1) - { + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { + if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { + if (Adapter->ulFlashWriteSize == 1) { UINT uiReadIndex = 0; - for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) - { - if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) - { - if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) - { + for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) { + if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) { + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) { Status = STATUS_FAILURE; goto BeceemFlashBulkWrite_EXIT; } } } - } - else - { - if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) - { - if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) - { + } else { + if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) { + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) { Status = STATUS_FAILURE; goto BeceemFlashBulkWrite_EXIT; } @@ -1285,8 +1164,7 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, } // do_gettimeofday(&twv); // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); - if (ulStatus) - { + if (ulStatus) { BcmRestoreBlockProtectStatus(Adapter, ulStatus); ulStatus = 0; } @@ -1305,9 +1183,7 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, // BeceemFlashBulkWrite_EXIT : if (ulStatus) - { BcmRestoreBlockProtectStatus(Adapter, ulStatus); - } kfree(pTempBuff); @@ -1369,28 +1245,20 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, // // check if the data to be written is overlapped across sectors // - if (uiOffset+uiNumBytes < uiSectBoundary) - { + if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; - } - else - { + } else { // Number of sectors = Last sector start address/First sector start address uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) - { uiNumSectTobeRead++; - } } - if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) - { + if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) { index = 0; uiTemp = uiNumSectTobeRead; - while (uiTemp) - { - if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) - { + while (uiTemp) { + if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable", (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); Status = SECTOR_IS_NOT_WRITABLE; @@ -1402,63 +1270,49 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, } Adapter->SelectedChip = RESET_CHIP_SELECT; - while (uiNumSectTobeRead) - { + while (uiNumSectTobeRead) { uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); BcmDoChipSelect(Adapter, uiSectAlignAddr); if (0 != BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, uiOffsetFromSectStart, - Adapter->uiSectorSize)) - { + Adapter->uiSectorSize)) { Status = -1; goto BeceemFlashBulkWriteStatus_EXIT; } ulStatus = BcmFlashUnProtectBlock(Adapter, uiOffsetFromSectStart, Adapter->uiSectorSize); - if (uiNumSectTobeRead > 1) - { + if (uiNumSectTobeRead > 1) { memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); - } - else - { + } else { memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); } if (IsFlash2x(Adapter)) - { SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); - } FlashSectorErase(Adapter, uiPartOffset, 1); - for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) - { - if (Adapter->device_removed) - { + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { + if (Adapter->device_removed) { Status = -1; goto BeceemFlashBulkWriteStatus_EXIT; } - if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) - { + if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) { Status = -1; goto BeceemFlashBulkWriteStatus_EXIT; } } - if (bVerify) - { - for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) - { - if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) - { - if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) - { + if (bVerify) { + for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { + if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { + if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) { Status = STATUS_FAILURE; goto BeceemFlashBulkWriteStatus_EXIT; } @@ -1466,8 +1320,7 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, } } - if (ulStatus) - { + if (ulStatus) { BcmRestoreBlockProtectStatus(Adapter, ulStatus); ulStatus = 0; } @@ -1483,9 +1336,7 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, // BeceemFlashBulkWriteStatus_EXIT : if (ulStatus) - { BcmRestoreBlockProtectStatus(Adapter, ulStatus); - } kfree(pTempBuff); Adapter->SelectedChip = RESET_CHIP_SELECT; @@ -1516,29 +1367,23 @@ INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) INT Status = 0; if (pBuff == NULL) - { return -1; - } - if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) - { + if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) { kfree(pBuff); return -1; } uiEepromSize >>= 16; - if (uiEepromSize > 1024 * 1024) - { + if (uiEepromSize > 1024 * 1024) { kfree(pBuff); return -1; } uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); - while (uiBytesToCopy) - { - if (0 != BeceemEEPROMBulkRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiBytesToCopy)) - { + while (uiBytesToCopy) { + if (0 != BeceemEEPROMBulkRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiBytesToCopy)) { Status = -1; break; } @@ -1591,9 +1436,8 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) - { return -1; - } + uiEepromSize = ntohl(uiEepromSize); uiEepromSize >>= 16; @@ -1603,16 +1447,13 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) uiEepromSize -= EEPROM_CALPARAM_START; if (uiEepromSize > 1024 * 1024) - { return -1; - } pBuff = kmalloc(uiEepromSize, GFP_KERNEL); if (pBuff == NULL) return -1; - if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) - { + if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) { kfree(pBuff); return -1; } @@ -1621,11 +1462,9 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); - while (uiBytesToCopy) - { + while (uiBytesToCopy) { Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status); break; } @@ -1665,53 +1504,41 @@ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, UINT uiData = 0; UINT auiData[4] = {0}; - while (uiNumBytes) - { + while (uiNumBytes) { if (Adapter->device_removed) - { return -1; - } - if (uiNumBytes >= MAX_RW_SIZE) - { // for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. + if (uiNumBytes >= MAX_RW_SIZE) { + // for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); - if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) - { + if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) { // re-write BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE); mdelay(3); BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) - { return -1; - } } uiOffset += MAX_RW_SIZE; uiNumBytes -= MAX_RW_SIZE; uiIndex += 4; - } - else if (uiNumBytes >= 4) - { + } else if (uiNumBytes >= 4) { BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); - if (uiData != pBuffer[uiIndex]) - { + if (uiData != pBuffer[uiIndex]) { // re-write BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE); mdelay(3); BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); if (uiData != pBuffer[uiIndex]) - { return -1; - } } uiOffset += 4; uiNumBytes -= 4; uiIndex++; - } - else - { // Handle the reads less than 4 bytes... + } else { + // Handle the reads less than 4 bytes... uiData = 0; memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(UINT)), uiNumBytes); BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4); @@ -1726,8 +1553,8 @@ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, return 0; } -static VOID BcmSwapWord(UINT *ptr1) { - +static VOID BcmSwapWord(UINT *ptr1) +{ UINT tempval = (UINT)*ptr1; char *ptr2 = (char *)&tempval; char *ptr = (char *)ptr1; @@ -1807,11 +1634,9 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] * may take time. We should wait till the Empty bit is set. */ uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) - { + while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) { uiRetries--; - if (uiRetries == 0) - { + if (uiRetries == 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); return STATUS_FAILURE; } @@ -1821,15 +1646,13 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); - if (Adapter->device_removed == TRUE) - { + if (Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop...."); return -ENODEV; } } - if (uiRetries != 0) - { + if (uiRetries != 0) { /* Clear the ones that are set - either, Empty/Full/Avail bits */ value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL)); wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); @@ -1842,22 +1665,18 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] * means the previous write to the EEPROM has completed. */ uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; uiEpromStatus = 0; - while (uiRetries != 0) - { + while (uiRetries != 0) { uiEpromStatus = ReadEEPROMStatusRegister(Adapter); - if (Adapter->device_removed == TRUE) - { + if (Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop..."); return -ENODEV; } - if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) - { + if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries)); return STATUS_SUCCESS; } uiRetries--; - if (uiRetries == 0) - { + if (uiRetries == 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); return STATUS_FAILURE; } @@ -1900,15 +1719,13 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, // PUINT puiBuffer = (PUINT)pBuffer; // INT value; - if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) - { + if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) { uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); uiExtraBytes = uiOffset - uiTempOffset; BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE); - if (uiBytesToCopy >= (16 - uiExtraBytes)) - { + if (uiBytesToCopy >= (16 - uiExtraBytes)) { memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes); if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) @@ -1917,9 +1734,7 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes); uiIndex += (MAX_RW_SIZE - uiExtraBytes); uiOffset += (MAX_RW_SIZE - uiExtraBytes); - } - else - { + } else { memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy); if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) @@ -1931,24 +1746,18 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, } } - while (uiBytesToCopy) - { + while (uiBytesToCopy) { if (Adapter->device_removed) - { return -1; - } - if (uiBytesToCopy >= MAX_RW_SIZE) - { + if (uiBytesToCopy >= MAX_RW_SIZE) { if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset)) return STATUS_FAILURE; uiIndex += MAX_RW_SIZE; uiOffset += MAX_RW_SIZE; uiBytesToCopy -= MAX_RW_SIZE; - } - else - { + } else { // // To program non 16byte aligned data, read 16byte and then update. // @@ -1992,10 +1801,8 @@ INT BeceemNVMRead(struct bcm_mini_adapter *Adapter, UINT uiTemp = 0, value; #endif - if (Adapter->eNVMType == NVM_FLASH) - { - if (Adapter->bFlashRawRead == FALSE) - { + if (Adapter->eNVMType == NVM_FLASH) { + if (Adapter->bFlashRawRead == FALSE) { if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes); @@ -2014,16 +1821,12 @@ INT BeceemNVMRead(struct bcm_mini_adapter *Adapter, uiNumBytes); wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); #endif - } - else if (Adapter->eNVMType == NVM_EEPROM) - { + } else if (Adapter->eNVMType == NVM_EEPROM) { Status = BeceemEEPROMBulkRead(Adapter, pBuffer, uiOffset, uiNumBytes); - } - else - { + } else { Status = -1; } @@ -2063,12 +1866,10 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, UINT uiFlashOffset = 0; - if (Adapter->eNVMType == NVM_FLASH) - { + if (Adapter->eNVMType == NVM_FLASH) { if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify); - else - { + else { uiFlashOffset = uiOffset + Adapter->ulFlashCalStart; #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) @@ -2079,63 +1880,47 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); if (Adapter->bStatusWrite == TRUE) - { Status = BeceemFlashBulkWriteStatus(Adapter, pBuffer, uiFlashOffset, uiNumBytes , bVerify); - } else - { Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiFlashOffset, uiNumBytes, bVerify); - } #endif } - if (uiOffset >= EEPROM_CALPARAM_START) - { + if (uiOffset >= EEPROM_CALPARAM_START) { uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START); - while (uiNumBytes) - { - if (uiNumBytes > BUFFER_4K) - { + while (uiNumBytes) { + if (uiNumBytes > BUFFER_4K) { wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K); uiNumBytes -= BUFFER_4K; uiIndex += BUFFER_4K; - } - else - { + } else { wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes); uiNumBytes = 0; break; } } - } - else - { - if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) - { + } else { + if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) { ULONG ulBytesTobeSkipped = 0; PUCHAR pcBuffer = (PUCHAR)pBuffer; // char pointer to take care of odd byte cases. uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset); ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset); uiOffset += (EEPROM_CALPARAM_START - uiOffset); - while (uiNumBytes) - { - if (uiNumBytes > BUFFER_4K) - { + while (uiNumBytes) { + if (uiNumBytes > BUFFER_4K) { wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K); uiNumBytes -= BUFFER_4K; uiIndex += BUFFER_4K; - } - else - { + } else { wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes); uiNumBytes = 0; break; @@ -2145,21 +1930,15 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, } // restore the values. wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - } - else if (Adapter->eNVMType == NVM_EEPROM) - { + } else if (Adapter->eNVMType == NVM_EEPROM) { Status = BeceemEEPROMBulkWrite(Adapter, (PUCHAR)pBuffer, uiOffset, uiNumBytes, bVerify); if (bVerify) - { Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes); - } - } - else - { + } else { Status = -1; } return Status; @@ -2199,12 +1978,9 @@ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig); uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize); - if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) - { - if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) - { - if (uiSectorSize == uiCurrentSectorSize) - { + if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { + if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) { + if (uiSectorSize == uiCurrentSectorSize) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash"); Status = STATUS_SUCCESS; goto Restore; @@ -2212,8 +1988,7 @@ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) } } - if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) - { + if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) { sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize); sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG); @@ -2251,47 +2026,32 @@ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSe if (Adapter->bSectorSizeOverride && (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && - Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) - { + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) { Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; - } - else - { + } else { uiSectorSig = FlashSectorSizeSig; - if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) - { + if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { uiSectorSize = FlashSectorSize; // // If the sector size stored in the FLASH makes sense then use it. // - if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) - { + if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) { Adapter->uiSectorSize = uiSectorSize; - } - //No valid size in FLASH, check if Config file has it. - else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && - Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) - { + } else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) { + //No valid size in FLASH, check if Config file has it. Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; - } - // Init to Default, if none of the above works. - else - { + } else { + // Init to Default, if none of the above works. Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; } - } - else - { + } else { if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) - { Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; - } else - { Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; - } } } @@ -2353,16 +2113,11 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) BcmValidateNvmType(ps_adapter); BcmInitEEPROMQueues(ps_adapter); - if (ps_adapter->eNVMType == NVM_AUTODETECT) - { + if (ps_adapter->eNVMType == NVM_AUTODETECT) { ps_adapter->eNVMType = BcmGetNvmType(ps_adapter); if (ps_adapter->eNVMType == NVM_UNKNOWN) - { BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n"); - } - } - else if (ps_adapter->eNVMType == NVM_FLASH) - { + } else if (ps_adapter->eNVMType == NVM_FLASH) { BcmGetFlashCSInfo(ps_adapter); } @@ -2384,13 +2139,10 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) { if (Adapter->eNVMType == NVM_EEPROM) - { Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter); - } else if (Adapter->eNVMType == NVM_FLASH) - { Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter); - } + return 0; } @@ -2416,9 +2168,7 @@ static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) if (Adapter->eNVMType == NVM_FLASH && Adapter->chip_id < 0xBECE3300) - { Adapter->eNVMType = NVM_AUTODETECT; - } } //----------------------------------------------------------------------------- @@ -2458,29 +2208,25 @@ static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { - if (psAdapter == NULL) - { + if (psAdapter == NULL) { BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); return -EINVAL; } psAdapter->psFlashCSInfo = (PFLASH_CS_INFO)kzalloc(sizeof(FLASH_CS_INFO), GFP_KERNEL); - if (psAdapter->psFlashCSInfo == NULL) - { + if (psAdapter->psFlashCSInfo == NULL) { BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x"); return -ENOMEM; } psAdapter->psFlash2xCSInfo = (PFLASH2X_CS_INFO)kzalloc(sizeof(FLASH2X_CS_INFO), GFP_KERNEL); - if (psAdapter->psFlash2xCSInfo == NULL) - { + if (psAdapter->psFlash2xCSInfo == NULL) { BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x"); kfree(psAdapter->psFlashCSInfo); return -ENOMEM; } psAdapter->psFlash2xVendorInfo = (PFLASH2X_VENDORSPECIFIC_INFO)kzalloc(sizeof(FLASH2X_VENDORSPECIFIC_INFO), GFP_KERNEL); - if (psAdapter->psFlash2xVendorInfo == NULL) - { + if (psAdapter->psFlash2xVendorInfo == NULL) { BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x"); kfree(psAdapter->psFlashCSInfo); kfree(psAdapter->psFlash2xCSInfo); @@ -2492,8 +2238,7 @@ INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) { - if (psAdapter == NULL) - { + if (psAdapter == NULL) { BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); return -EINVAL; } @@ -2557,10 +2302,8 @@ static INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo, struct bc BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :"); for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) - { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index, (psFlash2xCSInfo->SectorAccessBitMap[Index])); - } return STATUS_SUCCESS; } @@ -2617,9 +2360,8 @@ static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End); for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) - { psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]); - } + return STATUS_SUCCESS; } @@ -2676,10 +2418,8 @@ static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) return; i = 0; - while (i < TOTAL_SECTIONS) - { - if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) - { + while (i < TOTAL_SECTIONS) { + if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) { i++; continue; } @@ -2688,53 +2428,52 @@ static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd - Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart); - switch (i) - { - case DSD0: - if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; - break; + switch (i) { + case DSD0: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; + break; - case DSD1: - if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; - break; + case DSD1: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; + break; - case DSD2: - if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && - (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; - break; - case VSA0: - if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; - break; + case DSD2: + if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; + break; + case VSA0: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; + break; - case VSA1: - if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; - break; - case VSA2: - if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; - else - Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; - break; + case VSA1: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; + break; + case VSA2: + if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; + break; - default: - break; + default: + break; } i++; } @@ -2770,12 +2509,9 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) memset(Adapter->psFlashCSInfo, 0 , sizeof(FLASH_CS_INFO)); memset(Adapter->psFlash2xCSInfo, 0 , sizeof(FLASH2X_CS_INFO)); - if (!Adapter->bDDRInitDone) - { - { - value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; - wrmalt(Adapter, 0xAF00A080, &value, sizeof(value)); - } + if (!Adapter->bDDRInitDone) { + value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; + wrmalt(Adapter, 0xAF00A080, &value, sizeof(value)); } // Reading first 8 Bytes to get the Flash Layout @@ -2787,41 +2523,32 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); - if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) - { + if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) { uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); - } - else - { + } else { Adapter->uiFlashLayoutMinorVersion = 0; uiFlashLayoutMajorVersion = 0; } BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion); - if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) - { + if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) { BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(FLASH_CS_INFO)); ConvertEndianOfCSStructure(Adapter->psFlashCSInfo); Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart); if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) - { Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart; - } if ((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) && (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) && (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) && - (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) - { + (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) { Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize); Adapter->fpFlashWrite = flashByteWrite; Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; - } - else - { + } else { Adapter->ulFlashWriteSize = MAX_RW_SIZE; Adapter->fpFlashWrite = flashWrite; Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; @@ -2830,12 +2557,9 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig), (Adapter->psFlashCSInfo->FlashSectorSize)); Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF; - } - else - { + } else { if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL, - Adapter->ulFlashControlSectionStart, sizeof(FLASH2X_CS_INFO))) - { + Adapter->ulFlashControlSectionStart, sizeof(FLASH2X_CS_INFO))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n"); return STATUS_FAILURE; } @@ -2845,14 +2569,11 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) if ((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && - (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) - { + (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) { Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize; Adapter->fpFlashWrite = flashByteWrite; Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; - } - else - { + } else { Adapter->ulFlashWriteSize = MAX_RW_SIZE; Adapter->fpFlashWrite = flashWrite; Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; @@ -2897,9 +2618,7 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); if (uiData == BECM) - { return NVM_EEPROM; - } // // Read control struct and get cal addresses before accessing the flash @@ -2908,18 +2627,14 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4); if (uiData == BECM) - { return NVM_FLASH; - } // // even if there is no valid signature on EEPROM/FLASH find out if they really exist. // if exist select it. // if (BcmGetEEPROMSize(Adapter)) - { return NVM_EEPROM; - } //TBD for Flash. return NVM_UNKNOWN; @@ -2948,73 +2663,70 @@ INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTIO SectStartOffset = INVALID_OFFSET; if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal)) - { return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart; - } - switch (eFlashSectionVal) - { - case ISO_IMAGE1: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); - break; - case ISO_IMAGE2: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); - break; - case DSD0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); - break; - case DSD1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); - break; - case DSD2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); - break; - case VSA0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); - break; - case VSA1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); - break; - case VSA2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); - break; - case SCSI: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); - break; - case CONTROL_SECTION: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); - break; - case ISO_IMAGE1_PART2: - if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); - break; - case ISO_IMAGE1_PART3: - if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - break; - case ISO_IMAGE2_PART2: - if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); - break; - case ISO_IMAGE2_PART3: - if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) - SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - break; - default: - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); - SectStartOffset = INVALID_OFFSET; + switch (eFlashSectionVal) { + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); + break; + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); + break; + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); + break; + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); + break; + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); + break; + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); + break; + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); + break; + case CONTROL_SECTION: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); + break; + case ISO_IMAGE1_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); + break; + case ISO_IMAGE1_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + break; + case ISO_IMAGE2_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); + break; + case ISO_IMAGE2_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + break; + default: + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); + SectStartOffset = INVALID_OFFSET; } return SectStartOffset; @@ -3036,72 +2748,69 @@ INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_ SectEndOffset = INVALID_OFFSET; if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) - { return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd; - } - switch (eFlash2xSectionVal) - { - case ISO_IMAGE1: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); - break; - case ISO_IMAGE2: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); - break; - case DSD0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd); - break; - case DSD1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End); - break; - case DSD2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End); - break; - case VSA0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd); - break; - case VSA1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End); - break; - case VSA2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End); - break; - case SCSI: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) - SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) + - (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); - break; - case CONTROL_SECTION: - //Not Clear So Putting failure. confirm and fix it. - SectEndOffset = STATUS_FAILURE; - case ISO_IMAGE1_PART2: - if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); - break; - case ISO_IMAGE1_PART3: - if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); - break; - case ISO_IMAGE2_PART2: - if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); - break; - case ISO_IMAGE2_PART3: - if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS) - SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); - break; - default: - SectEndOffset = INVALID_OFFSET; + switch (eFlash2xSectionVal) { + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd); + break; + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End); + break; + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End); + break; + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd); + break; + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End); + break; + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End); + break; + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) + + (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); + break; + case CONTROL_SECTION: + //Not Clear So Putting failure. confirm and fix it. + SectEndOffset = STATUS_FAILURE; + case ISO_IMAGE1_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); + break; + case ISO_IMAGE1_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); + break; + case ISO_IMAGE2_PART2: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); + break; + case ISO_IMAGE2_PART3: + if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); + break; + default: + SectEndOffset = INVALID_OFFSET; } return SectEndOffset ; @@ -3130,13 +2839,11 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, UINT uiAbsoluteOffset = 0; UINT uiTemp = 0, value = 0; - if (Adapter == NULL) - { + if (Adapter == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); return -EINVAL; } - if (Adapter->device_removed) - { + if (Adapter->device_removed) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); return -ENODEV; } @@ -3147,8 +2854,7 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, else SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); - if (SectionStartOffset == STATUS_FAILURE) - { + if (SectionStartOffset == STATUS_FAILURE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash 2.x Map ", eFlash2xSectionVal); return -EINVAL; } @@ -3163,8 +2869,7 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes); wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status); return Status; } @@ -3196,14 +2901,12 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, UINT FlashSectValStartOffset = 0; UINT uiTemp = 0, value = 0; - if (Adapter == NULL) - { + if (Adapter == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); return -EINVAL; } - if (Adapter->device_removed) - { + if (Adapter->device_removed) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); return -ENODEV; } @@ -3214,8 +2917,7 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, else FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal); - if (FlashSectValStartOffset == STATUS_FAILURE) - { + if (FlashSectValStartOffset == STATUS_FAILURE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash Map 2.x", eFlash2xSectVal); return -EINVAL; } @@ -3233,8 +2935,7 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify); wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status); return Status; } @@ -3266,21 +2967,15 @@ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; if (Adapter->eActiveDSD) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); - if (Adapter->eActiveDSD == 0) - { + if (Adapter->eActiveDSD == 0) { //if No DSD gets Active, Make Active the DSD with WR permission - if (IsSectionWritable(Adapter, DSD2)) - { + if (IsSectionWritable(Adapter, DSD2)) { Adapter->eActiveDSD = DSD2; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; - } - else if (IsSectionWritable(Adapter, DSD1)) - { + } else if (IsSectionWritable(Adapter, DSD1)) { Adapter->eActiveDSD = DSD1; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; - } - else if (IsSectionWritable(Adapter, DSD0)) - { + } else if (IsSectionWritable(Adapter, DSD0)) { Adapter->eActiveDSD = DSD0; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; } @@ -3397,8 +3092,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM // For 1.x map all the section except DSD0 will be shown as not present // This part will be used by calibration tool to detect the number of DSD present in Flash. - if (IsFlash2x(Adapter) == FALSE) - { + if (IsFlash2x(Adapter) == FALSE) { psFlash2xBitMap->ISO_IMAGE2 = 0; psFlash2xBitMap->ISO_IMAGE1 = 0; psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; //0xF; //0000(Reseved)1(Active)0(RW)1(valid)1(present) @@ -3422,8 +3116,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // IS0 IMAGE 2 /// - if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; @@ -3434,8 +3127,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE) psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO; - if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) - { + if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) { psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT; SetActiveISODone = TRUE; } @@ -3444,8 +3136,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // IS0 IMAGE 1 /// - if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT; @@ -3456,8 +3147,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE) psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO; - if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) - { + if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) { psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT; SetActiveISODone = TRUE; } @@ -3466,8 +3156,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // DSD2 /// - if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; @@ -3475,15 +3164,11 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID; // Calculation for extrating the Access permission - if (IsSectionWritable(Adapter, DSD2) == FALSE) - { + if (IsSectionWritable(Adapter, DSD2) == FALSE) { psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO; - } - else - { + } else { //Means section is writable - if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) - { + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) { psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; } @@ -3493,8 +3178,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // DSD 1 /// - if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; @@ -3502,15 +3186,11 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID; // Calculation for extrating the Access permission - if (IsSectionWritable(Adapter, DSD1) == FALSE) - { + if (IsSectionWritable(Adapter, DSD1) == FALSE) { psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO; - } - else - { + } else { // Means section is writable - if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) - { + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) { psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; } @@ -3520,8 +3200,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// //For DSD 0 // - if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) { //Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT; @@ -3529,15 +3208,11 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID; // Setting Access permission - if (IsSectionWritable(Adapter, DSD0) == FALSE) - { + if (IsSectionWritable(Adapter, DSD0) == FALSE) { psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO; - } - else - { + } else { // Means section is writable - if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) - { + if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) { psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; } @@ -3547,8 +3222,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // VSA 0 /// - if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; @@ -3566,8 +3240,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // VSA 1 /// - if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; @@ -3585,8 +3258,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // VSA 2 /// - if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; @@ -3604,8 +3276,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // SCSI Section /// - if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; @@ -3623,8 +3294,7 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM /// // Control Section /// - if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) - { + if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) { // Setting the 0th Bit representing the Section is present or not. psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT); @@ -3672,177 +3342,157 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF INT HighestPriISO = 0; Status = IsSectionWritable(Adapter, eFlash2xSectVal); - if (Status != TRUE) - { + if (Status != TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal); return STATUS_FAILURE; } Adapter->bHeaderChangeAllowed = TRUE; - switch (eFlash2xSectVal) - { - case ISO_IMAGE1: - case ISO_IMAGE2: - if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) - { + switch (eFlash2xSectVal) { + case ISO_IMAGE1: + case ISO_IMAGE2: + if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) { + HighestPriISO = getHighestPriISO(Adapter); + + if (HighestPriISO == eFlash2xSectVal) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS; + break; + } + + SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; + + if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) { + // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. + // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO + // by user + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); + SectImagePriority = htonl(0x1); + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + HighestPriISO, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + Status = STATUS_FAILURE; + break; + } + HighestPriISO = getHighestPriISO(Adapter); - if (HighestPriISO == eFlash2xSectVal) - { + if (HighestPriISO == eFlash2xSectVal) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); Status = STATUS_SUCCESS; break; } - SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; - - if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) - { - // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. - // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO - // by user - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); - SectImagePriority = htonl(0x1); - Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - HighestPriISO, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), - SIGNATURE_SIZE, - TRUE); - if (Status) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - Status = STATUS_FAILURE; - break; - } - - HighestPriISO = getHighestPriISO(Adapter); + SectImagePriority = 2; + } - if (HighestPriISO == eFlash2xSectVal) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); - Status = STATUS_SUCCESS; - break; - } + SectImagePriority = htonl(SectImagePriority); - SectImagePriority = 2; - } + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + eFlash2xSectVal, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break; + } + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + Status = STATUS_FAILURE; + break; + } + break; + case DSD0: + case DSD1: + case DSD2: + if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) { + HighestPriDSD = getHighestPriDSD(Adapter); + if ((HighestPriDSD == eFlash2xSectVal)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS; + break; + } - SectImagePriority = htonl(SectImagePriority); + SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1; + if (SectImagePriority <= 0) { + // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. + // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD + // by user + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); + SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, &SectImagePriority, - eFlash2xSectVal, - 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + HighestPriDSD, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), SIGNATURE_SIZE, TRUE); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); break; } - } - else - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); - Status = STATUS_FAILURE; - break; - } - break; - case DSD0: - case DSD1: - case DSD2: - if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) - { + HighestPriDSD = getHighestPriDSD(Adapter); - if ((HighestPriDSD == eFlash2xSectVal)) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal); + + if ((HighestPriDSD == eFlash2xSectVal)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); Status = STATUS_SUCCESS; break; } - SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1; - if (SectImagePriority <= 0) - { - // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. - // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD - // by user - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); - SectImagePriority = htonl(0x1); - - Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - HighestPriDSD, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - SIGNATURE_SIZE, - TRUE); - if (Status) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - break; - } - - HighestPriDSD = getHighestPriDSD(Adapter); - - if ((HighestPriDSD == eFlash2xSectVal)) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); - Status = STATUS_SUCCESS; - break; - } - - SectImagePriority = htonl(0x2); - Status = BcmFlash2xBulkWrite(Adapter, - &SectImagePriority, - HighestPriDSD, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), - SIGNATURE_SIZE, - TRUE); - if (Status) - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - break; - } - - HighestPriDSD = getHighestPriDSD(Adapter); - if ((HighestPriDSD == eFlash2xSectVal)) - { - Status = STATUS_SUCCESS; - break; - } - - SectImagePriority = 3; - } - SectImagePriority = htonl(SectImagePriority); + SectImagePriority = htonl(0x2); Status = BcmFlash2xBulkWrite(Adapter, &SectImagePriority, - eFlash2xSectVal, + HighestPriDSD, Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), SIGNATURE_SIZE, TRUE); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); - Status = STATUS_FAILURE; break; } + + HighestPriDSD = getHighestPriDSD(Adapter); + if ((HighestPriDSD == eFlash2xSectVal)) { + Status = STATUS_SUCCESS; + break; + } + + SectImagePriority = 3; } - else - { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + SectImagePriority = htonl(SectImagePriority); + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + eFlash2xSectVal, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + if (Status) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); Status = STATUS_FAILURE; break; } - break; - case VSA0: - case VSA1: - case VSA2: - // Has to be decided - break; - default: + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); Status = STATUS_FAILURE; break; + } + break; + case VSA0: + case VSA1: + case VSA2: + // Has to be decided + break; + default: + Status = STATUS_FAILURE; + break; } Adapter->bHeaderChangeAllowed = FALSE; @@ -3871,8 +3521,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS UINT SigBuff[MAX_RW_SIZE]; UINT i = 0; - if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) - { + if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); return STATUS_FAILURE; } @@ -3882,30 +3531,25 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS sCopySectStrut.SrcSection, 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageSize), 4); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n"); return Status; } ISOLength = htonl(ISOLength); if (ISOLength % Adapter->uiSectorSize) - { ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize); - } sigOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL); - if (Buff == NULL) - { + if (Buff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size"); return -ENOMEM; } - if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) - { + if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) { eISOReadPart = ISO_IMAGE1; eISOWritePart = ISO_IMAGE2; uiReadOffsetWithinPart = 0; @@ -3918,8 +3562,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - if (uiTotalDataToCopy < ISOLength) - { + if (uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); Status = STATUS_FAILURE; goto out; @@ -3932,8 +3575,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - if (uiTotalDataToCopy < ISOLength) - { + if (uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); Status = STATUS_FAILURE; goto out; @@ -3942,10 +3584,8 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS uiTotalDataToCopy = ISOLength; CorruptISOSig(Adapter, ISO_IMAGE2); - while (uiTotalDataToCopy) - { - if (uiTotalDataToCopy == Adapter->uiSectorSize) - { + while (uiTotalDataToCopy) { + if (uiTotalDataToCopy == Adapter->uiSectorSize) { // Setting for write of first sector. First sector is assumed to be written in last BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); eISOReadPart = ISO_IMAGE1; @@ -3953,32 +3593,26 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS eISOWritePart = ISO_IMAGE2; uiWriteOffsetWithinPart = 0; IsThisHeaderSector = TRUE; - } - else - { + } else { uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; - if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) - { + if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { eISOReadPart = ISO_IMAGE1_PART2; uiReadOffsetWithinPart = 0; } - if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) - { + if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { eISOReadPart = ISO_IMAGE1_PART3; uiReadOffsetWithinPart = 0; } - if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) - { + if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { eISOWritePart = ISO_IMAGE2_PART2; uiWriteOffsetWithinPart = 0; } - if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) - { + if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { eISOWritePart = ISO_IMAGE2_PART3; uiWriteOffsetWithinPart = 0; } @@ -3989,14 +3623,12 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS eISOReadPart, uiReadOffsetWithinPart, Adapter->uiSectorSize); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); break; } - if (IsThisHeaderSector == TRUE) - { + if (IsThisHeaderSector == TRUE) { // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); @@ -4010,15 +3642,13 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS uiWriteOffsetWithinPart, Adapter->uiSectorSize, TRUE); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); break; } Adapter->bHeaderChangeAllowed = FALSE; - if (IsThisHeaderSector == TRUE) - { + if (IsThisHeaderSector == TRUE) { WriteToFlashWithoutSectorErase(Adapter, SigBuff, eISOWritePart, @@ -4031,8 +3661,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS } } - if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) - { + if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) { eISOReadPart = ISO_IMAGE2; eISOWritePart = ISO_IMAGE1; uiReadOffsetWithinPart = 0; @@ -4045,8 +3674,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); - if (uiTotalDataToCopy < ISOLength) - { + if (uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); Status = STATUS_FAILURE; goto out; @@ -4059,8 +3687,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); - if (uiTotalDataToCopy < ISOLength) - { + if (uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); Status = STATUS_FAILURE; goto out; @@ -4070,10 +3697,8 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS CorruptISOSig(Adapter, ISO_IMAGE1); - while (uiTotalDataToCopy) - { - if (uiTotalDataToCopy == Adapter->uiSectorSize) - { + while (uiTotalDataToCopy) { + if (uiTotalDataToCopy == Adapter->uiSectorSize) { //Setting for write of first sector. First sector is assumed to be written in last BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); eISOReadPart = ISO_IMAGE2; @@ -4081,32 +3706,26 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS eISOWritePart = ISO_IMAGE1; uiWriteOffsetWithinPart = 0; IsThisHeaderSector = TRUE; - } - else - { + } else { uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; - if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) - { + if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { eISOReadPart = ISO_IMAGE2_PART2; uiReadOffsetWithinPart = 0; } - if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) - { + if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { eISOReadPart = ISO_IMAGE2_PART3; uiReadOffsetWithinPart = 0; } - if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) - { + if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { eISOWritePart = ISO_IMAGE1_PART2; uiWriteOffsetWithinPart = 0; } - if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) - { + if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { eISOWritePart = ISO_IMAGE1_PART3; uiWriteOffsetWithinPart = 0; } @@ -4117,14 +3736,12 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS eISOReadPart, uiReadOffsetWithinPart, Adapter->uiSectorSize); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); break; } - if (IsThisHeaderSector == TRUE) - { + if (IsThisHeaderSector == TRUE) { // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); @@ -4138,15 +3755,13 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS uiWriteOffsetWithinPart, Adapter->uiSectorSize, TRUE); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); break; } Adapter->bHeaderChangeAllowed = FALSE; - if (IsThisHeaderSector == TRUE) - { + if (IsThisHeaderSector == TRUE) { WriteToFlashWithoutSectorErase(Adapter, SigBuff, eISOWritePart, @@ -4185,16 +3800,11 @@ INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal); - if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) - { + if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) { Status = CorruptDSDSig(Adapter, eFlash2xSectionVal); - } - else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) - { + } else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) { Status = CorruptISOSig(Adapter, eFlash2xSectionVal); - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal); return STATUS_SUCCESS; } @@ -4219,47 +3829,37 @@ INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFl UINT uiOffset = 0; // DSD_HEADER dsdHeader = {0}; - if (Adapter->bSigCorrupted == FALSE) - { + if (Adapter->bSigCorrupted == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n"); return STATUS_SUCCESS; } - if (Adapter->bAllDSDWriteAllow == FALSE) - { - if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) - { + if (Adapter->bAllDSDWriteAllow == FALSE) { + if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature"); return SECTOR_IS_NOT_WRITABLE; } } - if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) - { + if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) { uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER); uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader; uiOffset += FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber); - if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) - { + if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig"); return STATUS_FAILURE; } - } - else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) - { + } else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) { uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER); // uiOffset = 0; uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); - if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) - { + if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig"); return STATUS_FAILURE; } - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal); return STATUS_FAILURE; } @@ -4293,26 +3893,21 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT uiNumOfBytes = psFlash2xReadWrite->numOfBytes; - if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) - { + if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exixt in Flash", psFlash2xReadWrite->Section); return FALSE; } uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section); - if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) - { - if (psFlash2xReadWrite->Section == ISO_IMAGE1) - { + if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) { + if (psFlash2xReadWrite->Section == ISO_IMAGE1) { uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) - BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) - BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART2) + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) - BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART3); - } - else if (psFlash2xReadWrite->Section == ISO_IMAGE2) - { + } else if (psFlash2xReadWrite->Section == ISO_IMAGE2) { uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) - BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2) + BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) - @@ -4326,8 +3921,7 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT uiSectEndOffset = uiSectStartOffset + uiSectEndOffset; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset); - } - else + } else uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset); @@ -4335,8 +3929,7 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT // Checking the boundary condition if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) return TRUE; - else - { + else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request...."); return FALSE; } @@ -4370,8 +3963,7 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) { UINT uiBaseAddr = 0; - if (Adapter->bDDRInitDone) - { + if (Adapter->bDDRInitDone) { /* For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr In case of Raw Read... use the default value @@ -4381,9 +3973,7 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) uiBaseAddr = Adapter->uiFlashBaseAdd; else uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT; - } - else - { + } else { /* For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr In case of Raw Read... use the default value @@ -4426,27 +4016,23 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, PUCHAR pBuff = NULL; INT Status = STATUS_SUCCESS; - if (SrcSection == DstSection) - { + if (SrcSection == DstSection) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again"); return -EINVAL; } - if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) - { + if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection"); return -EINVAL; } - if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) - { + if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection"); return -EINVAL; } // if offset zero means have to copy complete secton - if (numOfBytes == 0) - { + if (numOfBytes == 0) { numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection) - BcmGetSectionValStartOffset(Adapter, SrcSection); @@ -4454,16 +4040,14 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, } if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection) - - BcmGetSectionValStartOffset(Adapter, SrcSection)) - { + - BcmGetSectionValStartOffset(Adapter, SrcSection)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n", offset, numOfBytes); return -EINVAL; } if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection) - - BcmGetSectionValStartOffset(Adapter, DstSection)) - { + - BcmGetSectionValStartOffset(Adapter, DstSection)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n", offset, numOfBytes); return -EINVAL; @@ -4475,8 +4059,7 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, BuffSize = numOfBytes; pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL); - if (pBuff == NULL) - { + if (pBuff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. "); return -ENOMEM; } @@ -4489,24 +4072,20 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, Adapter->bHeaderChangeAllowed = TRUE; - do - { + do { Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied); break; } Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, FALSE); - if (Status) - { + if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied); break; } offset = offset + BytesToBeCopied; numOfBytes = numOfBytes - BytesToBeCopied; - if (numOfBytes) - { + if (numOfBytes) { if (numOfBytes > Adapter->uiSectorSize) BytesToBeCopied = Adapter->uiSectorSize; else @@ -4545,8 +4124,7 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) || (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) || - (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) - { + (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) { // offset from the sector boundary having the header map offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; HeaderSizeToProtect = sizeof(DSD_HEADER); @@ -4554,18 +4132,15 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO } if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) || - uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) - { + uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) { offsetToProtect = 0; HeaderSizeToProtect = sizeof(ISO_HEADER); bHasHeader = TRUE; } // If Header is present overwrite passed buffer with this - if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) - { + if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) { pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL); - if (pTempBuff == NULL) - { + if (pTempBuff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed"); return -ENOMEM; } @@ -4577,12 +4152,10 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO kfree(pTempBuff); } - if (bHasHeader && Adapter->bSigCorrupted) - { + if (bHasHeader && Adapter->bSigCorrupted) { sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber))); sig = ntohl(sig); - if ((sig & 0xFF000000) != CORRUPTED_PATTERN) - { + if ((sig & 0xFF000000) != CORRUPTED_PATTERN) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore"); Adapter->bSigCorrupted = FALSE; return STATUS_SUCCESS; @@ -4637,23 +4210,22 @@ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); { - switch (ChipNum) - { - case 0: - PartNum = 0; - break; - case 1: - PartNum = 3; - GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); - break; - case 2: - PartNum = 1; - GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); - break; - case 3: - PartNum = 2; - GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); - break; + switch (ChipNum) { + case 0: + PartNum = 0; + break; + case 1: + PartNum = 3; + GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); + break; + case 2: + PartNum = 1; + GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); + break; + case 3: + PartNum = 2; + GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); + break; } } /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired, @@ -4687,8 +4259,7 @@ INT ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd) //sigoffsetInMap =(PUCHAR)&(dsdHeader.DSDImageMagicNumber) -(PUCHAR)&dsdHeader; - if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) - { + if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs"); return STATUS_FAILURE; } @@ -4710,10 +4281,8 @@ INT ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd) unsigned int uiDSDPri = STATUS_FAILURE; // DSD_HEADER dsdHeader = {0}; // priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader; - if (IsSectionWritable(Adapter, dsd)) - { - if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) - { + if (IsSectionWritable(Adapter, dsd)) { + if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) { BcmFlash2xBulkRead(Adapter, &uiDSDPri, dsd, @@ -4734,27 +4303,22 @@ FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter) INT DsdPri = 0; FLASH2X_SECTION_VAL HighestPriDSD = 0; - if (IsSectionWritable(Adapter, DSD2)) - { + if (IsSectionWritable(Adapter, DSD2)) { DSDHighestPri = ReadDSDPriority(Adapter, DSD2); HighestPriDSD = DSD2; } - if (IsSectionWritable(Adapter, DSD1)) - { + if (IsSectionWritable(Adapter, DSD1)) { DsdPri = ReadDSDPriority(Adapter, DSD1); - if (DSDHighestPri < DsdPri) - { + if (DSDHighestPri < DsdPri) { DSDHighestPri = DsdPri; HighestPriDSD = DSD1; } } - if (IsSectionWritable(Adapter, DSD0)) - { + if (IsSectionWritable(Adapter, DSD0)) { DsdPri = ReadDSDPriority(Adapter, DSD0); - if (DSDHighestPri < DsdPri) - { + if (DSDHighestPri < DsdPri) { DSDHighestPri = DsdPri; HighestPriDSD = DSD0; } @@ -4772,8 +4336,7 @@ INT ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) //ISO_HEADER ISOHeader = {0}; //sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader; - if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) - { + if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs"); return STATUS_FAILURE; } @@ -4792,10 +4355,8 @@ INT ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) INT ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso) { unsigned int ISOPri = STATUS_FAILURE; - if (IsSectionWritable(Adapter, iso)) - { - if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) - { + if (IsSectionWritable(Adapter, iso)) { + if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) { BcmFlash2xBulkRead(Adapter, &ISOPri, iso, @@ -4816,17 +4377,14 @@ FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter) INT ISOPri = 0; FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL; - if (IsSectionWritable(Adapter, ISO_IMAGE2)) - { + if (IsSectionWritable(Adapter, ISO_IMAGE2)) { ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2); HighestPriISO = ISO_IMAGE2; } - if (IsSectionWritable(Adapter, ISO_IMAGE1)) - { + if (IsSectionWritable(Adapter, ISO_IMAGE1)) { ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1); - if (ISOHighestPri < ISOPri) - { + if (ISOHighestPri < ISOPri) { ISOHighestPri = ISOPri; HighestPriISO = ISO_IMAGE1; } @@ -4853,8 +4411,7 @@ INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, INT Status = STATUS_SUCCESS; PUCHAR pcBuff = (PUCHAR)pBuff; - if (uiNumBytes % Adapter->ulFlashWriteSize) - { + if (uiNumBytes % Adapter->ulFlashWriteSize) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes); return STATUS_FAILURE; } @@ -4862,9 +4419,7 @@ INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) - { return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes); - } uiOffset = uiOffset + uiStartOffset; @@ -4879,8 +4434,7 @@ INT WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, BcmDoChipSelect(Adapter, uiOffset); uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); - for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) - { + for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) { if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) Status = flashByteWrite(Adapter, uiPartOffset, pcBuff); else @@ -4903,53 +4457,52 @@ BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_ { BOOLEAN SectionPresent = FALSE; - switch (section) - { - case ISO_IMAGE1: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectionPresent = TRUE; - break; - case ISO_IMAGE2: - if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && - (IsNonCDLessDevice(Adapter) == FALSE)) - SectionPresent = TRUE; - break; - case DSD0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case DSD1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case DSD2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case VSA0: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case VSA1: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case VSA2: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case SCSI: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - case CONTROL_SECTION: - if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) - SectionPresent = TRUE; - break; - default: - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); - SectionPresent = FALSE; + switch (section) { + case ISO_IMAGE1: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE; + break; + case ISO_IMAGE2: + if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE; + break; + case DSD0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case DSD1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case DSD2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA0: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA1: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case VSA2: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case SCSI: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + case CONTROL_SECTION: + if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE; + break; + default: + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); + SectionPresent = FALSE; } return SectionPresent; @@ -4960,23 +4513,19 @@ INT IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Sect INT offset = STATUS_FAILURE; INT Status = FALSE; - if (IsSectionExistInFlash(Adapter, Section) == FALSE) - { + if (IsSectionExistInFlash(Adapter, Section) == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exixt", Section); return FALSE; } offset = BcmGetSectionValStartOffset(Adapter, Section); - if (offset == INVALID_OFFSET) - { + if (offset == INVALID_OFFSET) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exixt", Section); return FALSE; } if (IsSectionExistInVendorInfo(Adapter, Section)) - { return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO); - } Status = IsOffsetWritable(Adapter, offset); return Status; @@ -4991,18 +4540,15 @@ static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e UINT uiSectAlignAddr = 0; Adapter->bSigCorrupted = FALSE; - if (Adapter->bAllDSDWriteAllow == FALSE) - { - if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) - { + if (Adapter->bAllDSDWriteAllow == FALSE) { + if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } } pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); - if (pBuff == NULL) - { + if (pBuff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); return -ENOMEM; } @@ -5018,30 +4564,23 @@ static INT CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e // Now corrupting the sig by corrupting 4th last Byte. *(pBuff + 12) = 0; - if (sig == DSD_IMAGE_MAGIC_NUMBER) - { + if (sig == DSD_IMAGE_MAGIC_NUMBER) { Adapter->bSigCorrupted = TRUE; - if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) - { + if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) { uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal, (uiOffset + 12), BYTE_WRITE_SUPPORT); - if (BlockStatus) - { + if (BlockStatus) { BcmRestoreBlockProtectStatus(Adapter, BlockStatus); BlockStatus = 0; } - } - else - { + } else { WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE); } - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); kfree(pBuff); @@ -5062,15 +4601,13 @@ static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e Adapter->bSigCorrupted = FALSE; - if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) - { + if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); - if (pBuff == NULL) - { + if (pBuff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); return -ENOMEM; } @@ -5085,14 +4622,11 @@ static INT CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e // corrupt signature *pBuff = 0; - if (sig == ISO_IMAGE_MAGIC_NUMBER) - { + if (sig == ISO_IMAGE_MAGIC_NUMBER) { Adapter->bSigCorrupted = TRUE; WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, Adapter->ulFlashWriteSize); - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); kfree(pBuff); -- GitLab From de443c96e5e62c5c32ae6fdfc44e12470bbf70b3 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 6 Jun 2012 22:54:29 -0400 Subject: [PATCH 0547/5711] Staging: bcm: Correctly format all comments in nvm.c This patch correctly formats all comments as reported by checkpatch.pl. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 1895 +++++++++++++++++++------------------ 1 file changed, 955 insertions(+), 940 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index 66001fcd4402..cfc0458b6e0a 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -51,17 +51,15 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter); static INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, UINT dwAddress, UINT *pdwData, UINT dwNumData); -// Procedure: ReadEEPROMStatusRegister -// -// Description: Reads the standard EEPROM Status Register. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- - +/* Procedure: ReadEEPROMStatusRegister + * + * Description: Reads the standard EEPROM Status Register. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * Returns: + * OSAL_STATUS_CODE + */ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) { UCHAR uiData = 0; @@ -110,19 +108,19 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) return uiData; } /* ReadEEPROMStatusRegister */ -//----------------------------------------------------------------------------- -// Procedure: ReadBeceemEEPROMBulk -// -// Description: This routine reads 16Byte data from EEPROM -// -// Arguments: -// Adapter - ptr to Adapter object instance -// dwAddress - EEPROM Offset to read the data from. -// pdwData - Pointer to double word where data needs to be stored in. // dwNumWords - Number of words. Valid values are 4 ONLY. -// -// Returns: -// OSAL_STATUS_CODE: -//----------------------------------------------------------------------------- +/* + * Procedure: ReadBeceemEEPROMBulk + * + * Description: This routine reads 16Byte data from EEPROM + * + * Arguments: + * Adapter - ptr to Adapter object instance + * dwAddress - EEPROM Offset to read the data from. + * pdwData - Pointer to double word where data needs to be stored in. // dwNumWords - Number of words. Valid values are 4 ONLY. + * + * Returns: + * OSAL_STATUS_CODE: + */ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, DWORD dwAddress, @@ -159,7 +157,8 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, /* If we are reading 16 bytes we want to be sure that the queue * is full before we read. In the other cases we are ok if the - * queue has data available */ + * queue has data available + */ if (dwNumWords == 4) { if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) { /* Clear the Avail/Full bits - which ever is set. */ @@ -170,7 +169,8 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, } else if (dwNumWords == 1) { if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { /* We just got Avail and we have to read 32bits so we - * need this sleep for Cardbus kind of devices. */ + * need this sleep for Cardbus kind of devices. + */ if (Adapter->chip_id == 0xBECE0210) udelay(800); @@ -226,20 +226,20 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, return STATUS_SUCCESS; } /* ReadBeceemEEPROMBulk() */ -//----------------------------------------------------------------------------- -// Procedure: ReadBeceemEEPROM -// -// Description: This routine reads 4 data from EEPROM. It uses 1 or 2 page -// reads to do this operation. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - EEPROM Offset to read the data from. -// pBuffer - Pointer to word where data needs to be stored in. -// -// Returns: -// OSAL_STATUS_CODE: -//----------------------------------------------------------------------------- +/* + * Procedure: ReadBeceemEEPROM + * + * Description: This routine reads 4 data from EEPROM. It uses 1 or 2 page + * reads to do this operation. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - EEPROM Offset to read the data from. + * pBuffer - Pointer to word where data needs to be stored in. + * + * Returns: + * OSAL_STATUS_CODE: + */ INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, DWORD uiOffset, @@ -257,7 +257,8 @@ INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); /* A word can overlap at most over 2 pages. In that case we read the - * next page too. */ + * next page too. + */ if (uiByteOffset > 12) ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4); @@ -282,21 +283,21 @@ INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) return Status; } -//----------------------------------------------------------------------------- -// Procedure: BeceemEEPROMBulkRead -// -// Description: Reads the EEPROM and returns the Data. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Buffer to store the data read from EEPROM -// uiOffset - Offset of EEPROM from where data should be read -// uiNumBytes - Number of bytes to be read from the EEPROM. -// -// Returns: -// OSAL_STATUS_SUCCESS - if EEPROM read is successful. -// - if failed. -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemEEPROMBulkRead + * + * Description: Reads the EEPROM and returns the Data. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Buffer to store the data read from EEPROM + * uiOffset - Offset of EEPROM from where data should be read + * uiNumBytes - Number of bytes to be read from the EEPROM. + * + * Returns: + * OSAL_STATUS_SUCCESS - if EEPROM read is successful. + * - if failed. + */ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -304,7 +305,7 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, UINT uiNumBytes) { UINT uiData[4] = {0}; - // UINT uiAddress = 0; + /* UINT uiAddress = 0; */ UINT uiBytesRemaining = uiNumBytes; UINT uiIndex = 0; UINT uiTempOffset = 0; @@ -336,7 +337,8 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, if (uiBytesRemaining >= MAX_RW_SIZE) { /* For the requests more than or equal to 16 bytes, use bulk * read function to make the access faster. - * We read 4 Dwords of data */ + * We read 4 Dwords of data + */ if (0 == ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4)) { memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE); uiOffset += MAX_RW_SIZE; @@ -344,7 +346,7 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, uiIndex += MAX_RW_SIZE; } else { uiFailureRetries++; - mdelay(3); //sleep for a while before retry... + mdelay(3); /* sleep for a while before retry... */ } } else if (uiBytesRemaining >= 4) { if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { @@ -354,18 +356,18 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, uiIndex += 4; } else { uiFailureRetries++; - mdelay(3); //sleep for a while before retry... + mdelay(3); /* sleep for a while before retry... */ } } else { - // Handle the reads less than 4 bytes... + /* Handle the reads less than 4 bytes... */ PUCHAR pCharBuff = (PUCHAR)pBuffer; pCharBuff += uiIndex; if (0 == ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0])) { - memcpy(pCharBuff, &uiData[0], uiBytesRemaining); //copy only bytes requested. + memcpy(pCharBuff, &uiData[0], uiBytesRemaining); /* copy only bytes requested. */ uiBytesRemaining = 0; } else { uiFailureRetries++; - mdelay(3); //sleep for a while before retry... + mdelay(3); /* sleep for a while before retry... */ } } } @@ -373,21 +375,21 @@ INT BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, return 0; } -//----------------------------------------------------------------------------- -// Procedure: BeceemFlashBulkRead -// -// Description: Reads the FLASH and returns the Data. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Buffer to store the data read from FLASH -// uiOffset - Offset of FLASH from where data should be read -// uiNumBytes - Number of bytes to be read from the FLASH. -// -// Returns: -// OSAL_STATUS_SUCCESS - if FLASH read is successful. -// - if failed. -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemFlashBulkRead + * + * Description: Reads the FLASH and returns the Data. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Buffer to store the data read from FLASH + * uiOffset - Offset of FLASH from where data should be read + * uiNumBytes - Number of bytes to be read from the FLASH. + * + * Returns: + * OSAL_STATUS_SUCCESS - if FLASH read is successful. + * - if failed. + */ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -405,8 +407,9 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, return -ENODEV; } - // Adding flash Base address - // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + /* Adding flash Base address + * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + */ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); return Status; @@ -453,18 +456,18 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, return Status; } -//----------------------------------------------------------------------------- -// Procedure: BcmGetFlashSize -// -// Description: Finds the size of FLASH. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// UINT - size of the FLASH Storage. -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmGetFlashSize + * + * Description: Finds the size of FLASH. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * UINT - size of the FLASH Storage. + * + */ static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter) { @@ -474,32 +477,32 @@ static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter) return 32 * 1024; } -//----------------------------------------------------------------------------- -// Procedure: BcmGetEEPROMSize -// -// Description: Finds the size of EEPROM. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// UINT - size of the EEPROM Storage. -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmGetEEPROMSize + * + * Description: Finds the size of EEPROM. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * UINT - size of the EEPROM Storage. + * + */ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) { UINT uiData = 0; UINT uiIndex = 0; - // - // if EEPROM is present and already Calibrated,it will have - // 'BECM' string at 0th offset. - // To find the EEPROM size read the possible boundaries of the - // EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will - // result in wrap around. So when we get the End of the EEPROM we will - // get 'BECM' string which is indeed at offset 0. - // + /* + * if EEPROM is present and already Calibrated,it will have + * 'BECM' string at 0th offset. + * To find the EEPROM size read the possible boundaries of the + * EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will + * result in wrap around. So when we get the End of the EEPROM we will + * get 'BECM' string which is indeed at offset 0. + */ BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); if (uiData == BECM) { for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { @@ -508,9 +511,9 @@ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) return uiIndex * 1024; } } else { - // - // EEPROM may not be present or not programmed - // + /* + * EEPROM may not be present or not programmed + */ uiData = 0xBABEFACE; if (0 == BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE)) { uiData = 0; @@ -524,20 +527,20 @@ static UINT BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) return 0; } -//----------------------------------------------------------------------------- -// Procedure: FlashSectorErase -// -// Description: Finds the sector size of the FLASH. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// addr - sector start address -// numOfSectors - number of sectors to be erased. -// -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: FlashSectorErase + * + * Description: Finds the sector size of the FLASH. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * addr - sector start address + * numOfSectors - number of sectors to be erased. + * + * Returns: + * OSAL_STATUS_CODE + * + */ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, UINT addr, @@ -570,9 +573,10 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, return uiStatus; } iRetries++; - // After every try lets make the CPU free for 10 ms. generally time taken by the - // the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms - // won't hamper performance in any case. + /* After every try lets make the CPU free for 10 ms. generally time taken by the + * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms + * won't hamper performance in any case. + */ msleep(10); } while ((uiStatus & 0x1) && (iRetries < 400)); @@ -585,38 +589,38 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, } return 0; } -//----------------------------------------------------------------------------- -// Procedure: flashByteWrite -// -// Description: Performs Byte by Byte write to flash -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - Offset of the flash where data needs to be written to. -// pData - Address of Data to be written. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: flashByteWrite + * + * Description: Performs Byte by Byte write to flash + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - Offset of the flash where data needs to be written to. + * pData - Address of Data to be written. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { UINT uiStatus = 0; - INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ UINT value; ULONG ulData = *(PUCHAR)pData; int bytes; - // - // need not write 0xFF because write requires an erase and erase will - // make whole sector 0xFF. - // + /* + * need not write 0xFF because write requires an erase and erase will + * make whole sector 0xFF. + */ if (0xFF == ulData) return STATUS_SUCCESS; - // DumpDebug(NVM_RW,("flashWrite ====>\n")); + /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */ value = (FLASH_CMD_WRITE_ENABLE << 24); if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); @@ -633,7 +637,7 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, return STATUS_FAILURE; } - //__udelay(950); + /* __udelay(950); */ do { value = (FLASH_CMD_STATUS_REG_READ << 24); @@ -641,7 +645,7 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - //__udelay(1); + /* __udelay(1); */ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; @@ -662,37 +666,37 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, return STATUS_SUCCESS; } -//----------------------------------------------------------------------------- -// Procedure: flashWrite -// -// Description: Performs write to flash -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - Offset of the flash where data needs to be written to. -// pData - Address of Data to be written. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: flashWrite + * + * Description: Performs write to flash + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - Offset of the flash where data needs to be written to. + * pData - Address of Data to be written. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT flashWrite(struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { - //UINT uiStatus = 0; - //INT iRetries = 0; - //UINT uiReadBack = 0; - + /* UINT uiStatus = 0; + * INT iRetries = 0; + * UINT uiReadBack = 0; + */ UINT uiStatus = 0; - INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ UINT value; UINT uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; int bytes; - // - // need not write 0xFFFFFFFF because write requires an erase and erase will - // make whole sector 0xFFFFFFFF. - // + /* + * need not write 0xFFFFFFFF because write requires an erase and erase will + * make whole sector 0xFFFFFFFF. + */ if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) return 0; @@ -708,14 +712,14 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, return STATUS_FAILURE; } - //__udelay(950); + /* __udelay(950); */ do { value = (FLASH_CMD_STATUS_REG_READ << 24); if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - //__udelay(1); + /* __udelay(1); */ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; @@ -724,10 +728,11 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, } iRetries--; - //this will ensure that in there will be no changes in the current path. - //currently one rdm/wrm takes 125 us. - //Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay) - //Hence current implementation cycle will intoduce no delay in current path + /* this will ensure that in there will be no changes in the current path. + * currently one rdm/wrm takes 125 us. + * Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay) + * Hence current implementation cycle will intoduce no delay in current path + */ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) msleep(1); } while ((uiStatus & 0x1) && (iRetries > 0)); @@ -740,38 +745,38 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, return STATUS_SUCCESS; } -//----------------------------------------------------------------------------- -// Procedure: flashByteWriteStatus -// -// Description: Performs byte by byte write to flash with write done status check -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - Offset of the flash where data needs to be written to. -// pData - Address of the Data to be written. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/*----------------------------------------------------------------------------- + * Procedure: flashByteWriteStatus + * + * Description: Performs byte by byte write to flash with write done status check + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - Offset of the flash where data needs to be written to. + * pData - Address of the Data to be written. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { UINT uiStatus = 0; - INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ ULONG ulData = *(PUCHAR)pData; UINT value; int bytes; - // - // need not write 0xFFFFFFFF because write requires an erase and erase will - // make whole sector 0xFFFFFFFF. - // + /* + * need not write 0xFFFFFFFF because write requires an erase and erase will + * make whole sector 0xFFFFFFFF. + */ if (0xFF == ulData) return STATUS_SUCCESS; - // DumpDebug(NVM_RW,("flashWrite ====>\n")); + /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */ value = (FLASH_CMD_WRITE_ENABLE << 24); if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { @@ -788,7 +793,7 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, return STATUS_FAILURE; } - //msleep(1); + /* msleep(1); */ do { value = (FLASH_CMD_STATUS_REG_READ << 24); @@ -796,7 +801,7 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - //__udelay(1); + /* __udelay(1); */ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; @@ -817,35 +822,35 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, return STATUS_SUCCESS; } -//----------------------------------------------------------------------------- -// Procedure: flashWriteStatus -// -// Description: Performs write to flash with write done status check -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - Offset of the flash where data needs to be written to. -// pData - Address of the Data to be written. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: flashWriteStatus + * + * Description: Performs write to flash with write done status check + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - Offset of the flash where data needs to be written to. + * pData - Address of the Data to be written. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, UINT uiOffset, PVOID pData) { UINT uiStatus = 0; - INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 - //UINT uiReadBack = 0; + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ + /* UINT uiReadBack = 0; */ UINT value; UINT uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; int bytes; - // - // need not write 0xFFFFFFFF because write requires an erase and erase will - // make whole sector 0xFFFFFFFF. - // + /* + * need not write 0xFFFFFFFF because write requires an erase and erase will + * make whole sector 0xFFFFFFFF. + */ if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) return 0; @@ -859,7 +864,7 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); return STATUS_FAILURE; } - // __udelay(1); + /* __udelay(1); */ do { value = (FLASH_CMD_STATUS_REG_READ << 24); @@ -867,7 +872,7 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); return STATUS_FAILURE; } - //__udelay(1); + /* __udelay(1); */ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); if (bytes < 0) { uiStatus = bytes; @@ -875,10 +880,11 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, return uiStatus; } iRetries--; - // this will ensure that in there will be no changes in the current path. - // currently one rdm/wrm takes 125 us. - // Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) - // Hence current implementation cycle will intoduce no delay in current path + /* this will ensure that in there will be no changes in the current path. + * currently one rdm/wrm takes 125 us. + * Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) + * Hence current implementation cycle will intoduce no delay in current path + */ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) msleep(1); @@ -892,18 +898,18 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, return STATUS_SUCCESS; } -//----------------------------------------------------------------------------- -// Procedure: BcmRestoreBlockProtectStatus -// -// Description: Restores the original block protection status. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// ulWriteStatus -Original status -// Returns: -// -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmRestoreBlockProtectStatus + * + * Description: Restores the original block protection status. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * ulWriteStatus -Original status + * Returns: + * + * + */ static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus) { @@ -917,18 +923,18 @@ static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG udelay(20); } -//----------------------------------------------------------------------------- -// Procedure: BcmFlashUnProtectBlock -// -// Description: UnProtects appropriate blocks for writing. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiOffset - Offset of the flash where data needs to be written to. This should be Sector aligned. -// Returns: -// ULONG - Status value before UnProtect. -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmFlashUnProtectBlock + * + * Description: UnProtects appropriate blocks for writing. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiOffset - Offset of the flash where data needs to be written to. This should be Sector aligned. + * Returns: + * ULONG - Status value before UnProtect. + * + */ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOffset, UINT uiLength) { @@ -937,63 +943,63 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOff UINT value; uiOffset = uiOffset&0x000FFFFF; - // - // Implemented only for 1MB Flash parts. - // + /* + * Implemented only for 1MB Flash parts. + */ if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) { - // - // Get Current BP status. - // + /* + * Get Current BP status. + */ value = (FLASH_CMD_STATUS_REG_READ << 24); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); udelay(10); - // - // Read status will be WWXXYYZZ. We have to take only WW. - // + /* + * Read status will be WWXXYYZZ. We have to take only WW. + */ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus)); ulStatus >>= 24; ulWriteStatus = ulStatus; - // - // Bits [5-2] give current block level protection status. - // Bit5: BP3 - DONT CARE - // BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 - // 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS - // + /* + * Bits [5-2] give current block level protection status. + * Bit5: BP3 - DONT CARE + * BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 + * 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS + */ if (ulStatus) { if ((uiOffset+uiLength) <= 0x80000) { - // - // Offset comes in lower half of 1MB. Protect the upper half. - // Clear BP1 and BP0 and set BP2. - // + /* + * Offset comes in lower half of 1MB. Protect the upper half. + * Clear BP1 and BP0 and set BP2. + */ ulWriteStatus |= (0x4<<2); ulWriteStatus &= ~(0x3<<2); } else if ((uiOffset + uiLength) <= 0xC0000) { - // - // Offset comes below Upper 1/4. Upper 1/4 can be protected. - // Clear BP2 and set BP1 and BP0. - // + /* + * Offset comes below Upper 1/4. Upper 1/4 can be protected. + * Clear BP2 and set BP1 and BP0. + */ ulWriteStatus |= (0x3<<2); ulWriteStatus &= ~(0x1<<4); } else if ((uiOffset + uiLength) <= 0xE0000) { - // - // Offset comes below Upper 1/8. Upper 1/8 can be protected. - // Clear BP2 and BP0 and set BP1 - // + /* + * Offset comes below Upper 1/8. Upper 1/8 can be protected. + * Clear BP2 and BP0 and set BP1 + */ ulWriteStatus |= (0x1<<3); ulWriteStatus &= ~(0x5<<2); } else if ((uiOffset + uiLength) <= 0xF0000) { - // - // Offset comes below Upper 1/16. Only upper 1/16 can be protected. - // Set BP0 and Clear BP2,BP1. - // + /* + * Offset comes below Upper 1/16. Only upper 1/16 can be protected. + * Set BP0 and Clear BP2,BP1. + */ ulWriteStatus |= (0x1<<2); ulWriteStatus &= ~(0x3<<3); } else { - // - // Unblock all. - // Clear BP2,BP1 and BP0. - // + /* + * Unblock all. + * Clear BP2,BP1 and BP0. + */ ulWriteStatus &= ~(0x7<<2); } @@ -1008,21 +1014,21 @@ static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, UINT uiOff return ulStatus; } -//----------------------------------------------------------------------------- -// Procedure: BeceemFlashBulkWrite -// -// Description: Performs write to the flash -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the flash where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// bVerify - read verify flag. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemFlashBulkWrite + * + * Description: Performs write to the flash + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Data to be written. + * uiOffset - Offset of the flash where data needs to be written to. + * uiNumBytes - Number of bytes to be written. + * bVerify - read verify flag. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -1052,8 +1058,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); - // Adding flash Base address - // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + /* Adding flash Base address + * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + */ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); @@ -1062,19 +1069,20 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); if (NULL == pTempBuff) goto BeceemFlashBulkWrite_EXIT; - // - // check if the data to be written is overlapped across sectors - // + /* + * check if the data to be written is overlapped across sectors + */ if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; } else { - // Number of sectors = Last sector start address/First sector start address + /* Number of sectors = Last sector start address/First sector start address */ uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) uiNumSectTobeRead++; } - // Check whether Requested sector is writable or not in case of flash2x write. But if write call is - // for DSD calibration, allow it without checking of sector permission + /* Check whether Requested sector is writable or not in case of flash2x write. But if write call is + * for DSD calibration, allow it without checking of sector permission + */ if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) { index = 0; @@ -1092,8 +1100,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, } Adapter->SelectedChip = RESET_CHIP_SELECT; while (uiNumSectTobeRead) { - // do_gettimeofday(&tv1); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); + /* do_gettimeofday(&tv1); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); + */ uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); BcmDoChipSelect(Adapter, uiSectAlignAddr); @@ -1106,9 +1115,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, goto BeceemFlashBulkWrite_EXIT; } - // do_gettimeofday(&tr); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); - + /* do_gettimeofday(&tr); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); + */ ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); if (uiNumSectTobeRead > 1) { @@ -1123,9 +1132,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); FlashSectorErase(Adapter, uiPartOffset, 1); - // do_gettimeofday(&te); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); - + /* do_gettimeofday(&te); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); + */ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { if (Adapter->device_removed) { Status = -1; @@ -1138,8 +1147,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, } } - // do_gettimeofday(&tw); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); + /* do_gettimeofday(&tw); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); + */ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { if (Adapter->ulFlashWriteSize == 1) { @@ -1162,8 +1172,9 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, } } } - // do_gettimeofday(&twv); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); + /* do_gettimeofday(&twv); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); + */ if (ulStatus) { BcmRestoreBlockProtectStatus(Adapter, ulStatus); ulStatus = 0; @@ -1175,13 +1186,13 @@ static INT BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, uiOffsetFromSectStart += Adapter->uiSectorSize; uiNumSectTobeRead--; } - // do_gettimeofday(&tv2); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); - // - // Cleanup. - // -BeceemFlashBulkWrite_EXIT : + /* do_gettimeofday(&tv2); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); + * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); + * + * Cleanup. + */ +BeceemFlashBulkWrite_EXIT: if (ulStatus) BcmRestoreBlockProtectStatus(Adapter, ulStatus); @@ -1191,21 +1202,21 @@ BeceemFlashBulkWrite_EXIT : return Status; } -//----------------------------------------------------------------------------- -// Procedure: BeceemFlashBulkWriteStatus -// -// Description: Writes to Flash. Checks the SPI status after each write. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the flash where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// bVerify - read verify flag. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemFlashBulkWriteStatus + * + * Description: Writes to Flash. Checks the SPI status after each write. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Data to be written. + * uiOffset - Offset of the flash where data needs to be written to. + * uiNumBytes - Number of bytes to be written. + * bVerify - read verify flag. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -1230,10 +1241,10 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); - // uiOffset += Adapter->ulFlashCalStart; - // Adding flash Base address - // uiOffset = uiOffset + GetFlashBaseAddr(Adapter); - + /* uiOffset += Adapter->ulFlashCalStart; + * Adding flash Base address + * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + */ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; @@ -1242,13 +1253,13 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, if (NULL == pTempBuff) goto BeceemFlashBulkWriteStatus_EXIT; - // - // check if the data to be written is overlapped across sectors - // + /* + * check if the data to be written is overlapped across sectors + */ if (uiOffset+uiNumBytes < uiSectBoundary) { uiNumSectTobeRead = 1; } else { - // Number of sectors = Last sector start address/First sector start address + /* Number of sectors = Last sector start address/First sector start address */ uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) uiNumSectTobeRead++; @@ -1331,10 +1342,10 @@ static INT BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, uiOffsetFromSectStart += Adapter->uiSectorSize; uiNumSectTobeRead--; } -// -// Cleanup. -// -BeceemFlashBulkWriteStatus_EXIT : +/* + * Cleanup. + */ +BeceemFlashBulkWriteStatus_EXIT: if (ulStatus) BcmRestoreBlockProtectStatus(Adapter, ulStatus); @@ -1343,17 +1354,17 @@ BeceemFlashBulkWriteStatus_EXIT : return Status; } -//----------------------------------------------------------------------------- -// Procedure: PropagateCalParamsFromEEPROMToMemory -// -// Description: Dumps the calibration section of EEPROM to DDR. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: PropagateCalParamsFromEEPROMToMemory + * + * Description: Dumps the calibration section of EEPROM to DDR. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * Returns: + * OSAL_STATUS_CODE + * + */ INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) { @@ -1404,32 +1415,32 @@ INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) return Status; } -//----------------------------------------------------------------------------- -// Procedure: PropagateCalParamsFromFlashToMemory -// -// Description: Dumps the calibration section of EEPROM to DDR. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: PropagateCalParamsFromFlashToMemory + * + * Description: Dumps the calibration section of EEPROM to DDR. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * Returns: + * OSAL_STATUS_CODE + * + */ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) { PCHAR pBuff, pPtr; UINT uiEepromSize = 0; UINT uiBytesToCopy = 0; - //UINT uiIndex = 0; + /* UINT uiIndex = 0; */ UINT uiCalStartAddr = EEPROM_CALPARAM_START; UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; UINT value; INT Status = 0; - // - // Write the signature first. This will ensure firmware does not access EEPROM. - // + /* + * Write the signature first. This will ensure firmware does not access EEPROM. + */ value = 0xbeadbead; wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); value = 0xbeadbead; @@ -1441,9 +1452,9 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) uiEepromSize = ntohl(uiEepromSize); uiEepromSize >>= 16; - // - // subtract the auto init section size - // + /* + * subtract the auto init section size + */ uiEepromSize -= EEPROM_CALPARAM_START; if (uiEepromSize > 1024 * 1024) @@ -1479,20 +1490,20 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) return Status; } -//----------------------------------------------------------------------------- -// Procedure: BeceemEEPROMReadBackandVerify -// -// Description: Read back the data written and verifies. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the flash where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemEEPROMReadBackandVerify + * + * Description: Read back the data written and verifies. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Data to be written. + * uiOffset - Offset of the flash where data needs to be written to. + * uiNumBytes - Number of bytes to be written. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -1509,11 +1520,11 @@ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, return -1; if (uiNumBytes >= MAX_RW_SIZE) { - // for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. + /* for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. */ BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) { - // re-write + /* re-write */ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE); mdelay(3); BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); @@ -1527,7 +1538,7 @@ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, } else if (uiNumBytes >= 4) { BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); if (uiData != pBuffer[uiIndex]) { - // re-write + /* re-write */ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE); mdelay(3); BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); @@ -1538,7 +1549,7 @@ static INT BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, uiNumBytes -= 4; uiIndex++; } else { - // Handle the reads less than 4 bytes... + /* Handle the reads less than 4 bytes... */ uiData = 0; memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(UINT)), uiNumBytes); BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4); @@ -1565,19 +1576,19 @@ static VOID BcmSwapWord(UINT *ptr1) ptr[3] = ptr2[0]; } -//----------------------------------------------------------------------------- -// Procedure: BeceemEEPROMWritePage -// -// Description: Performs page write (16bytes) to the EEPROM -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiData - Data to be written. -// uiOffset - Offset of the EEPROM where data needs to be written to. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemEEPROMWritePage + * + * Description: Performs page write (16bytes) to the EEPROM + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiData - Data to be written. + * uiOffset - Offset of the EEPROM where data needs to be written to. + * Returns: + * OSAL_STATUS_CODE + * + */ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[], UINT uiOffset) { @@ -1595,7 +1606,8 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] /* Clear the Empty/Avail/Full bits. After this it has been confirmed * that the bit was cleared by reading back the register. See NOTE below. * We also clear the Read queues as we do a EEPROM status register read - * later. */ + * later. + */ value = (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); @@ -1604,7 +1616,8 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); /* We can write back to back 8bits * 16 into the queue and as we have - * checked for the queue to be empty we can write in a burst. */ + * checked for the queue to be empty we can write in a burst. + */ value = uiData[0]; BcmSwapWord(&value); @@ -1625,13 +1638,15 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG * shows that we see 7 for the EEPROM data write. Which means that * queue got full, also space is available as well as the queue is empty. - * This may happen in sequence. */ + * This may happen in sequence. + */ value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset; wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); /* Ideally we should loop here without tries and eventually succeed. * What we are checking if the previous write has completed, and this - * may take time. We should wait till the Empty bit is set. */ + * may take time. We should wait till the Empty bit is set. + */ uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) { @@ -1662,7 +1677,8 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] * proceeding. Bit 0 in the EEPROM Status register should be 0 before * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy * with the previous write. Note also that issuing this read finally - * means the previous write to the EEPROM has completed. */ + * means the previous write to the EEPROM has completed. + */ uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; uiEpromStatus = 0; while (uiRetries != 0) { @@ -1688,21 +1704,21 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] return STATUS_SUCCESS; } /* BeceemEEPROMWritePage */ -//----------------------------------------------------------------------------- -// Procedure: BeceemEEPROMBulkWrite -// -// Description: Performs write to the EEPROM -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Data to be written. -// uiOffset - Offset of the EEPROM where data needs to be written to. -// uiNumBytes - Number of bytes to be written. -// bVerify - read verify flag. -// Returns: -// OSAL_STATUS_CODE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemEEPROMBulkWrite + * + * Description: Performs write to the EEPROM + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Data to be written. + * uiOffset - Offset of the EEPROM where data needs to be written to. + * uiNumBytes - Number of bytes to be written. + * bVerify - read verify flag. + * Returns: + * OSAL_STATUS_CODE + * + */ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, PUCHAR pBuffer, @@ -1711,13 +1727,14 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, BOOLEAN bVerify) { UINT uiBytesToCopy = uiNumBytes; - // UINT uiRdbk = 0; + /* UINT uiRdbk = 0; */ UINT uiData[4] = {0}; UINT uiIndex = 0; UINT uiTempOffset = 0; UINT uiExtraBytes = 0; - // PUINT puiBuffer = (PUINT)pBuffer; - // INT value; + /* PUINT puiBuffer = (PUINT)pBuffer; + * INT value; + */ if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) { uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); @@ -1758,9 +1775,9 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, uiOffset += MAX_RW_SIZE; uiBytesToCopy -= MAX_RW_SIZE; } else { - // - // To program non 16byte aligned data, read 16byte and then update. - // + /* + * To program non 16byte aligned data, read 16byte and then update. + */ BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16); memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy); @@ -1774,21 +1791,21 @@ INT BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, return 0; } -//----------------------------------------------------------------------------- -// Procedure: BeceemNVMRead -// -// Description: Reads n number of bytes from NVM. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Buffer to store the data read from NVM -// uiOffset - Offset of NVM from where data should be read -// uiNumBytes - Number of bytes to be read from the NVM. -// -// Returns: -// OSAL_STATUS_SUCCESS - if NVM read is successful. -// - if failed. -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemNVMRead + * + * Description: Reads n number of bytes from NVM. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Buffer to store the data read from NVM + * uiOffset - Offset of NVM from where data should be read + * uiNumBytes - Number of bytes to be read from the NVM. + * + * Returns: + * OSAL_STATUS_SUCCESS - if NVM read is successful. + * - if failed. + */ INT BeceemNVMRead(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -1833,21 +1850,21 @@ INT BeceemNVMRead(struct bcm_mini_adapter *Adapter, return Status; } -//----------------------------------------------------------------------------- -// Procedure: BeceemNVMWrite -// -// Description: Writes n number of bytes to NVM. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// pBuffer - Buffer contains the data to be written. -// uiOffset - Offset of NVM where data to be written to. -// uiNumBytes - Number of bytes to be written.. -// -// Returns: -// OSAL_STATUS_SUCCESS - if NVM write is successful. -// - if failed. -//----------------------------------------------------------------------------- +/* + * Procedure: BeceemNVMWrite + * + * Description: Writes n number of bytes to NVM. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * pBuffer - Buffer contains the data to be written. + * uiOffset - Offset of NVM where data to be written to. + * uiNumBytes - Number of bytes to be written.. + * + * Returns: + * OSAL_STATUS_SUCCESS - if NVM write is successful. + * - if failed. + */ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -1911,7 +1928,7 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, } else { if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) { ULONG ulBytesTobeSkipped = 0; - PUCHAR pcBuffer = (PUCHAR)pBuffer; // char pointer to take care of odd byte cases. + PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */ uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset); ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset); uiOffset += (EEPROM_CALPARAM_START - uiOffset); @@ -1928,7 +1945,7 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, } } } - // restore the values. + /* restore the values. */ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); } else if (Adapter->eNVMType == NVM_EEPROM) { Status = BeceemEEPROMBulkWrite(Adapter, @@ -1944,19 +1961,19 @@ INT BeceemNVMWrite(struct bcm_mini_adapter *Adapter, return Status; } -//----------------------------------------------------------------------------- -// Procedure: BcmUpdateSectorSize -// -// Description: Updates the sector size to FLASH. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// uiSectorSize - sector size -// -// Returns: -// OSAL_STATUS_SUCCESS - if NVM write is successful. -// - if failed. -//----------------------------------------------------------------------------- +/* + * Procedure: BcmUpdateSectorSize + * + * Description: Updates the sector size to FLASH. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * uiSectorSize - sector size + * + * Returns: + * OSAL_STATUS_SUCCESS - if NVM write is successful. + * - if failed. + */ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) { @@ -1971,9 +1988,9 @@ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) value = 0; wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); - // - // Before updating the sector size in the reserved area, check if already present. - // + /* + * Before updating the sector size in the reserved area, check if already present. + */ BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo)); uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig); uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize); @@ -2000,24 +2017,24 @@ INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize) } Restore: - // restore the values. + /* restore the values. */ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); return Status; } -//----------------------------------------------------------------------------- -// Procedure: BcmGetFlashSectorSize -// -// Description: Finds the sector size of the FLASH. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// UINT - sector size. -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmGetFlashSectorSize + * + * Description: Finds the sector size of the FLASH. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * UINT - sector size. + * + */ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) { @@ -2033,17 +2050,17 @@ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSe if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { uiSectorSize = FlashSectorSize; - // - // If the sector size stored in the FLASH makes sense then use it. - // + /* + * If the sector size stored in the FLASH makes sense then use it. + */ if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) { Adapter->uiSectorSize = uiSectorSize; } else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) { - //No valid size in FLASH, check if Config file has it. + /* No valid size in FLASH, check if Config file has it. */ Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; } else { - // Init to Default, if none of the above works. + /* Init to Default, if none of the above works. */ Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; } } else { @@ -2060,24 +2077,25 @@ static UINT BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, UINT FlashSe return Adapter->uiSectorSize; } -//----------------------------------------------------------------------------- -// Procedure: BcmInitEEPROMQueues -// -// Description: Initialization of EEPROM queues. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmInitEEPROMQueues + * + * Description: Initialization of EEPROM queues. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * + */ static INT BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter) { UINT value = 0; /* CHIP Bug : Clear the Avail bits on the Read queue. The default * value on this register is supposed to be 0x00001102. - * But we get 0x00001122. */ + * But we get 0x00001122. + */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n"); value = EEPROM_READ_DATA_AVAIL; wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); @@ -2096,17 +2114,17 @@ static INT BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter) return STATUS_SUCCESS; } /* BcmInitEEPROMQueues() */ -//----------------------------------------------------------------------------- -// Procedure: BcmInitNVM -// -// Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmInitNVM + * + * Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * + */ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) { @@ -2126,15 +2144,13 @@ INT BcmInitNVM(struct bcm_mini_adapter *ps_adapter) return STATUS_SUCCESS; } -/***************************************************************************/ -/*BcmGetNvmSize : set the EEPROM or flash size in Adapter. -* -*Input Parameter: -* Adapter data structure -*Return Value : -* 0. means success; -*/ -/***************************************************************************/ +/* BcmGetNvmSize : set the EEPROM or flash size in Adapter. + * + * Input Parameter: + * Adapter data structure + * Return Value : + * 0. means success; + */ static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) { @@ -2146,61 +2162,61 @@ static INT BcmGetNvmSize(struct bcm_mini_adapter *Adapter) return 0; } -//----------------------------------------------------------------------------- -// Procedure: BcmValidateNvm -// -// Description: Validates the NVM Type option selected against the device -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmValidateNvm + * + * Description: Validates the NVM Type option selected against the device + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * + */ static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) { - // - // if forcing the FLASH through CFG file, we should ensure device really has a FLASH. - // Accessing the FLASH address without the FLASH being present can cause hang/freeze etc. - // So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice. - // + /* + * if forcing the FLASH through CFG file, we should ensure device really has a FLASH. + * Accessing the FLASH address without the FLASH being present can cause hang/freeze etc. + * So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice. + */ if (Adapter->eNVMType == NVM_FLASH && Adapter->chip_id < 0xBECE3300) Adapter->eNVMType = NVM_AUTODETECT; } -//----------------------------------------------------------------------------- -// Procedure: BcmReadFlashRDID -// -// Description: Reads ID from Serial Flash -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// Flash ID -//----------------------------------------------------------------------------- +/* + * Procedure: BcmReadFlashRDID + * + * Description: Reads ID from Serial Flash + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * Flash ID + */ static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) { ULONG ulRDID = 0; UINT value; - // - // Read ID Instruction. - // + /* + * Read ID Instruction. + */ value = (FLASH_CMD_READ_ID << 24); wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); - //Delay + /* Delay */ udelay(10); - // - // Read SPI READQ REG. The output will be WWXXYYZZ. - // The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. - // + /* + * Read SPI READQ REG. The output will be WWXXYYZZ. + * The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. + */ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); return (ulRDID >> 8); @@ -2314,7 +2330,7 @@ static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber); psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion); - //psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); + /* psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); */ psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion); psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion); psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage); @@ -2367,11 +2383,11 @@ static INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) static INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) { - //UINT Index = 0; + /* UINT Index = 0; */ psFlashCSInfo->MagicNumber = ntohl(psFlashCSInfo->MagicNumber); psFlashCSInfo->FlashLayoutVersion = ntohl(psFlashCSInfo->FlashLayoutVersion); psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion); - //won't convert according to old assumption + /* won't convert according to old assumption */ psFlashCSInfo->SCSIFirmwareVersion = (psFlashCSInfo->SCSIFirmwareVersion); psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage); psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware); @@ -2479,21 +2495,21 @@ static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) } } -//----------------------------------------------------------------------------- -// Procedure: BcmGetFlashCSInfo -// -// Description: Reads control structure and gets Cal section addresses. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmGetFlashCSInfo + * + * Description: Reads control structure and gets Cal section addresses. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * + */ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) { - //FLASH_CS_INFO sFlashCsInfo = {0}; + /* FLASH_CS_INFO sFlashCsInfo = {0}; */ #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) UINT value; @@ -2514,13 +2530,14 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) wrmalt(Adapter, 0xAF00A080, &value, sizeof(value)); } - // Reading first 8 Bytes to get the Flash Layout - // MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) + /* Reading first 8 Bytes to get the Flash Layout + * MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) + */ BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8); Adapter->psFlashCSInfo->FlashLayoutVersion = ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion)); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); + /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) { @@ -2590,27 +2607,27 @@ static INT BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart; } /* - Concerns: what if CS sector size does not match with this sector size ??? - what is the indication of AccessBitMap in CS in flash 2.x ???? - */ + * Concerns: what if CS sector size does not match with this sector size ??? + * what is the indication of AccessBitMap in CS in flash 2.x ???? + */ Adapter->ulFlashID = BcmReadFlashRDID(Adapter); Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion; return STATUS_SUCCESS; } -//----------------------------------------------------------------------------- -// Procedure: BcmGetNvmType -// -// Description: Finds the type of NVM used. -// -// Arguments: -// Adapter - ptr to Adapter object instance -// -// Returns: -// NVM_TYPE -// -//----------------------------------------------------------------------------- +/* + * Procedure: BcmGetNvmType + * + * Description: Finds the type of NVM used. + * + * Arguments: + * Adapter - ptr to Adapter object instance + * + * Returns: + * NVM_TYPE + * + */ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) { @@ -2620,35 +2637,35 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter) if (uiData == BECM) return NVM_EEPROM; - // - // Read control struct and get cal addresses before accessing the flash - // + /* + * Read control struct and get cal addresses before accessing the flash + */ BcmGetFlashCSInfo(Adapter); BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4); if (uiData == BECM) return NVM_FLASH; - // - // even if there is no valid signature on EEPROM/FLASH find out if they really exist. - // if exist select it. - // + /* + * even if there is no valid signature on EEPROM/FLASH find out if they really exist. + * if exist select it. + */ if (BcmGetEEPROMSize(Adapter)) return NVM_EEPROM; - //TBD for Flash. + /* TBD for Flash. */ return NVM_UNKNOWN; } -/** -* BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given -* @Adapter : Drivers Private Data structure -* @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL -* -* Return value:- -* On success it return the start offset of the provided section val -* On Failure -returns STATUS_FAILURE -**/ +/* + * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given + * @Adapter : Drivers Private Data structure + * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL + * + * Return value:- + * On success it return the start offset of the provided section val + * On Failure -returns STATUS_FAILURE + */ INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { @@ -2732,15 +2749,15 @@ INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTIO return SectStartOffset; } -/** -* BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given -* @Adapter : Drivers Private Data structure -* @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL -* -* Return value:- -* On success it return the end offset of the provided section val -* On Failure -returns STATUS_FAILURE -**/ +/* + * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given + * @Adapter : Drivers Private Data structure + * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL + * + * Return value:- + * On success it return the end offset of the provided section val + * On Failure -returns STATUS_FAILURE + */ INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { @@ -2791,7 +2808,7 @@ INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_ (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); break; case CONTROL_SECTION: - //Not Clear So Putting failure. confirm and fix it. + /* Not Clear So Putting failure. confirm and fix it. */ SectEndOffset = STATUS_FAILURE; case ISO_IMAGE1_PART2: if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS) @@ -2817,16 +2834,16 @@ INT BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_ } /* -* BcmFlash2xBulkRead:- Read API for Flash Map 2.x . -* @Adapter :Driver Private Data Structure -* @pBuffer : Buffer where data has to be put after reading -* @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL -* @uiOffsetWithinSectionVal :- Offset with in provided section -* @uiNumBytes : Number of Bytes for Read -* -* Return value:- -* return true on success and STATUS_FAILURE on fail. -*/ + * BcmFlash2xBulkRead:- Read API for Flash Map 2.x . + * @Adapter :Driver Private Data Structure + * @pBuffer : Buffer where data has to be put after reading + * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL + * @uiOffsetWithinSectionVal :- Offset with in provided section + * @uiNumBytes : Number of Bytes for Read + * + * Return value:- + * return true on success and STATUS_FAILURE on fail. + */ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -2848,7 +2865,7 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, return -ENODEV; } - //NO_SECTION_VAL means absolute offset is given. + /* NO_SECTION_VAL means absolute offset is given. */ if (eFlash2xSectionVal == NO_SECTION_VAL) SectionStartOffset = 0; else @@ -2862,7 +2879,7 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes); - //calculating the absolute offset from FLASH; + /* calculating the absolute offset from FLASH; */ uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset; rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); value = 0; @@ -2878,17 +2895,17 @@ INT BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, } /* -* BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x. -* @Adapter :Driver Private Data Structure -* @pBuffer : Buffer From where data has to taken for writing -* @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL -* @uiOffsetWithinSectionVal :- Offset with in provided section -* @uiNumBytes : Number of Bytes for Write -* -* Return value:- -* return true on success and STATUS_FAILURE on fail. -* -*/ + * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x. + * @Adapter :Driver Private Data Structure + * @pBuffer : Buffer From where data has to taken for writing + * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL + * @uiOffsetWithinSectionVal :- Offset with in provided section + * @uiNumBytes : Number of Bytes for Write + * + * Return value:- + * return true on success and STATUS_FAILURE on fail. + * + */ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, PUINT pBuffer, @@ -2911,7 +2928,7 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, return -ENODEV; } - //NO_SECTION_VAL means absolute offset is given. + /* NO_SECTION_VAL means absolute offset is given. */ if (eFlash2xSectVal == NO_SECTION_VAL) FlashSectValStartOffset = 0; else @@ -2925,7 +2942,7 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal)) return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify); - //calculating the absolute offset from FLASH; + /* calculating the absolute offset from FLASH; */ uiOffset = uiOffset + FlashSectValStartOffset; rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); @@ -2943,14 +2960,14 @@ INT BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, return Status; } -/** -* BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR -* @Adapter :-Drivers private Data Structure -* -* Return Value:- -* Return STATUS_SUCESS if get success in setting the right DSD else negaive error code -* -**/ +/* + * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR + * @Adapter :-Drivers private Data Structure + * + * Return Value:- + * Return STATUS_SUCESS if get success in setting the right DSD else negaive error code + * + */ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) { @@ -2968,7 +2985,7 @@ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) if (Adapter->eActiveDSD) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); if (Adapter->eActiveDSD == 0) { - //if No DSD gets Active, Make Active the DSD with WR permission + /* if No DSD gets Active, Make Active the DSD with WR permission */ if (IsSectionWritable(Adapter, DSD2)) { Adapter->eActiveDSD = DSD2; Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; @@ -2984,15 +3001,15 @@ static INT BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) return STATUS_SUCCESS; } -/** -* BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue -* @Adapter : Driver private Data Structure -* -* Return Value:- -* Sucsess:- STATUS_SUCESS -* Failure- : negative erro code -* -**/ +/* + * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue + * @Adapter : Driver private Data Structure + * + * Return Value:- + * Sucsess:- STATUS_SUCESS + * Failure- : negative erro code + * + */ static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter) { @@ -3012,16 +3029,16 @@ static INT BcmGetActiveISO(struct bcm_mini_adapter *Adapter) return STATUS_SUCCESS; } -/** -* IsOffsetWritable :- it will tell the access permission of the sector having passed offset -* @Adapter : Drivers Private Data Structure -* @uiOffset : Offset provided in the Flash -* -* Return Value:- -* Success:-TRUE , offset is writable -* Failure:-FALSE, offset is RO -* -**/ +/* + * IsOffsetWritable :- it will tell the access permission of the sector having passed offset + * @Adapter : Drivers Private Data Structure + * @uiOffset : Offset provided in the Flash + * + * Return Value:- + * Success:-TRUE , offset is writable + * Failure:-FALSE, offset is RO + * + */ B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset) { @@ -3032,13 +3049,13 @@ B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, UINT uiOffset) uiSectorNum = uiOffset/Adapter->uiSectorSize; - // calculating the word having this Sector Access permission from SectorAccessBitMap Array + /* calculating the word having this Sector Access permission from SectorAccessBitMap Array */ uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16]; - // calculating the bit index inside the word for this sector + /* calculating the bit index inside the word for this sector */ uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16); - // Setting Access permission + /* Setting Access permission */ permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission); permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3; if (permissionBits == SECTOR_READWRITE_PERMISSION) @@ -3066,21 +3083,21 @@ static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) return STATUS_SUCCESS; } -/** -* BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash -* 8bit has been assigned to every section. - bit[0] :Section present or not - bit[1] :section is valid or not - bit[2] : Secton is read only or has write permission too. - bit[3] : Active Section - - bit[7...4] = Reserved . - - @Adapter:-Driver private Data Structure -* -* Return value:- -* Success:- STATUS_SUCESS -* Failure:- negative error code -**/ +/* + * BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash + * 8bit has been assigned to every section. + * bit[0] :Section present or not + * bit[1] :section is valid or not + * bit[2] : Secton is read only or has write permission too. + * bit[3] : Active Section - + * bit[7...4] = Reserved . + * + * @Adapter:-Driver private Data Structure + * + * Return value:- + * Success:- STATUS_SUCESS + * Failure:- negative error code + */ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITMAP psFlash2xBitMap) { @@ -3090,12 +3107,13 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM BOOLEAN SetActiveDSDDone = FALSE; BOOLEAN SetActiveISODone = FALSE; - // For 1.x map all the section except DSD0 will be shown as not present - // This part will be used by calibration tool to detect the number of DSD present in Flash. + /* For 1.x map all the section except DSD0 will be shown as not present + * This part will be used by calibration tool to detect the number of DSD present in Flash. + */ if (IsFlash2x(Adapter) == FALSE) { psFlash2xBitMap->ISO_IMAGE2 = 0; psFlash2xBitMap->ISO_IMAGE1 = 0; - psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; //0xF; //0000(Reseved)1(Active)0(RW)1(valid)1(present) + psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */ psFlash2xBitMap->DSD1 = 0; psFlash2xBitMap->DSD2 = 0; psFlash2xBitMap->VSA0 = 0; @@ -3113,17 +3131,17 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM uiHighestPriDSD = getHighestPriDSD(Adapter); uiHighestPriISO = getHighestPriISO(Adapter); - /// - // IS0 IMAGE 2 - /// + /* + * IS0 IMAGE 2 + */ if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission + /* Calculation for extrating the Access permission */ if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE) psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO; @@ -3133,17 +3151,17 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM } } - /// - // IS0 IMAGE 1 - /// + /* + * IS0 IMAGE 1 + */ if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT; if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission + /* Calculation for extrating the Access permission */ if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE) psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO; @@ -3153,21 +3171,21 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM } } - /// - // DSD2 - /// + /* + * DSD2 + */ if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission + /* Calculation for extrating the Access permission */ if (IsSectionWritable(Adapter, DSD2) == FALSE) { psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO; } else { - //Means section is writable + /* Means section is writable */ if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) { psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; @@ -3175,21 +3193,21 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM } } - /// - // DSD 1 - /// + /* + * DSD 1 + */ if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission + /* Calculation for extrating the Access permission */ if (IsSectionWritable(Adapter, DSD1) == FALSE) { psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO; } else { - // Means section is writable + /* Means section is writable */ if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) { psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; @@ -3197,21 +3215,21 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM } } - /// - //For DSD 0 - // + /* + * For DSD 0 + */ if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) { - //Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT; if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER) psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID; - // Setting Access permission + /* Setting Access permission */ if (IsSectionWritable(Adapter, DSD0) == FALSE) { psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO; } else { - // Means section is writable + /* Means section is writable */ if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) { psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT; SetActiveDSDDone = TRUE; @@ -3219,99 +3237,99 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM } } - /// - // VSA 0 - /// + /* + * VSA 0 + */ if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; - // Setting the Access Bit. Map is not defined hece setting it always valid + /* Setting the Access Bit. Map is not defined hece setting it always valid */ psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID; - // Calculation for extrating the Access permission + /* Calculation for extrating the Access permission */ if (IsSectionWritable(Adapter, VSA0) == FALSE) psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO; - // By Default section is Active + /* By Default section is Active */ psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT; } - /// - // VSA 1 - /// + /* + * VSA 1 + */ if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; - // Setting the Access Bit. Map is not defined hece setting it always valid + /* Setting the Access Bit. Map is not defined hece setting it always valid */ psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID; - // Checking For Access permission + /* Checking For Access permission */ if (IsSectionWritable(Adapter, VSA1) == FALSE) psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO; - // By Default section is Active + /* By Default section is Active */ psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT; } - /// - // VSA 2 - /// + /* + * VSA 2 + */ if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; - // Setting the Access Bit. Map is not defined hece setting it always valid + /* Setting the Access Bit. Map is not defined hece setting it always valid */ psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID; - // Checking For Access permission + /* Checking For Access permission */ if (IsSectionWritable(Adapter, VSA2) == FALSE) psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO; - // By Default section is Active + /* By Default section is Active */ psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT; } - /// - // SCSI Section - /// + /* + * SCSI Section + */ if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; - // Setting the Access Bit. Map is not defined hece setting it always valid + /* Setting the Access Bit. Map is not defined hece setting it always valid */ psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID; - // Checking For Access permission + /* Checking For Access permission */ if (IsSectionWritable(Adapter, SCSI) == FALSE) psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO; - // By Default section is Active + /* By Default section is Active */ psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT; } - /// - // Control Section - /// + /* + * Control Section + */ if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) { - // Setting the 0th Bit representing the Section is present or not. + /* Setting the 0th Bit representing the Section is present or not. */ psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT); - // Setting the Access Bit. Map is not defined hece setting it always valid + /* Setting the Access Bit. Map is not defined hece setting it always valid */ psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID; - // Checking For Access permission + /* Checking For Access permission */ if (IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE) psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO; - // By Default section is Active + /* By Default section is Active */ psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT; } - /// - // For Reserved Sections - /// + /* + * For Reserved Sections + */ psFlash2xBitMap->Reserved0 = 0; psFlash2xBitMap->Reserved0 = 0; psFlash2xBitMap->Reserved0 = 0; @@ -3320,24 +3338,25 @@ INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM return STATUS_SUCCESS; } -/** -BcmSetActiveSection :- Set Active section is used to make priority field highest over other - section of same type. - -@Adapater :- Bcm Driver Private Data Structure -@eFlash2xSectionVal :- Flash section val whose priority has to be made highest. - -Return Value:- Make the priorit highest else return erorr code - -**/ +/* + * BcmSetActiveSection :- Set Active section is used to make priority field highest over other + * section of same type. + * + * @Adapater :- Bcm Driver Private Data Structure + * @eFlash2xSectionVal :- Flash section val whose priority has to be made highest. + * + * Return Value:- Make the priorit highest else return erorr code + * + */ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal) { unsigned int SectImagePriority = 0; INT Status = STATUS_SUCCESS; - //DSD_HEADER sDSD = {0}; - //ISO_HEADER sISO = {0}; + /* DSD_HEADER sDSD = {0}; + * ISO_HEADER sISO = {0}; + */ INT HighestPriDSD = 0 ; INT HighestPriISO = 0; @@ -3363,9 +3382,10 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) { - // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. - // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO - // by user + /* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. + * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO + * by user + */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, @@ -3422,9 +3442,10 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1; if (SectImagePriority <= 0) { - // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. - // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD - // by user + /* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. + * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD + * by user + */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); SectImagePriority = htonl(0x1); @@ -3488,7 +3509,7 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF case VSA0: case VSA1: case VSA2: - // Has to be decided + /* Has to be decided */ break; default: Status = STATUS_FAILURE; @@ -3499,14 +3520,14 @@ INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF return Status; } -/** -BcmCopyISO - Used only for copying the ISO section -@Adapater :- Bcm Driver Private Data Structure -@sCopySectStrut :- Section copy structure - -Return value:- SUCCESS if copies successfully else negative error code - -**/ +/* + * BcmCopyISO - Used only for copying the ISO section + * @Adapater :- Bcm Driver Private Data Structure + * @sCopySectStrut :- Section copy structure + * + * Return value:- SUCCESS if copies successfully else negative error code + * + */ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut) { @@ -3586,7 +3607,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS CorruptISOSig(Adapter, ISO_IMAGE2); while (uiTotalDataToCopy) { if (uiTotalDataToCopy == Adapter->uiSectorSize) { - // Setting for write of first sector. First sector is assumed to be written in last + /* Setting for write of first sector. First sector is assumed to be written in last */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); eISOReadPart = ISO_IMAGE1; uiReadOffsetWithinPart = 0; @@ -3629,7 +3650,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS } if (IsThisHeaderSector == TRUE) { - // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */ memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); for (i = 0; i < MAX_RW_SIZE; i++) @@ -3656,7 +3677,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS MAX_RW_SIZE); IsThisHeaderSector = FALSE; } - //subtracting the written Data + /* subtracting the written Data */ uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; } } @@ -3699,7 +3720,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS while (uiTotalDataToCopy) { if (uiTotalDataToCopy == Adapter->uiSectorSize) { - //Setting for write of first sector. First sector is assumed to be written in last + /* Setting for write of first sector. First sector is assumed to be written in last */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); eISOReadPart = ISO_IMAGE2; uiReadOffsetWithinPart = 0; @@ -3742,7 +3763,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS } if (IsThisHeaderSector == TRUE) { - // If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */ memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); for (i = 0; i < MAX_RW_SIZE; i++) @@ -3771,7 +3792,7 @@ INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectS IsThisHeaderSector = FALSE; } - // subtracting the written Data + /* subtracting the written Data */ uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; } } @@ -3781,18 +3802,16 @@ out: return Status; } -/** -BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section. - It will corrupt the sig, if Section is writable, by making first bytes as zero. -@Adapater :- Bcm Driver Private Data Structure -@eFlash2xSectionVal :- Flash section val which has header - -Return Value :- - Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS - Failure :-Return negative error code - - -**/ +/* + * BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section. + * It will corrupt the sig, if Section is writable, by making first bytes as zero. + * @Adapater :- Bcm Driver Private Data Structure + * @eFlash2xSectionVal :- Flash section val which has header + * + * Return Value :- + * Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS + * Failure :-Return negative error code + */ INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { @@ -3811,24 +3830,23 @@ INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e return Status; } -/** -BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has - header and Write Permission. -@Adapater :- Bcm Driver Private Data Structure -@eFlashSectionVal :- Flash section val which has header - -Return Value :- - Success :- If Section is present and writable write the sig and return STATUS_SUCCESS - Failure :-Return negative error code - -**/ +/* + *BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has + * header and Write Permission. + * @Adapater :- Bcm Driver Private Data Structure + * @eFlashSectionVal :- Flash section val which has header + * + * Return Value :- + * Success :- If Section is present and writable write the sig and return STATUS_SUCCESS + * Failure :-Return negative error code + */ INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) { UINT uiSignature = 0; UINT uiOffset = 0; - // DSD_HEADER dsdHeader = {0}; + /* DSD_HEADER dsdHeader = {0}; */ if (Adapter->bSigCorrupted == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n"); return STATUS_SUCCESS; @@ -3853,7 +3871,7 @@ INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFl } } else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) { uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER); - // uiOffset = 0; + /* uiOffset = 0; */ uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig"); @@ -3874,16 +3892,14 @@ INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFl return STATUS_SUCCESS; } -/** -validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write. - if requested Bytes goes beyond the Requested section, it reports error. -@Adapater :- Bcm Driver Private Data Structure -@psFlash2xReadWrite :-Flash2x Read/write structure pointer - -Return values:-Return TRUE is request is valid else FALSE. - - -**/ +/* + * validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write. + * if requested Bytes goes beyond the Requested section, it reports error. + * @Adapater :- Bcm Driver Private Data Structure + * @psFlash2xReadWrite :-Flash2x Read/write structure pointer + * + * Return values:-Return TRUE is request is valid else FALSE. + */ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) { @@ -3916,8 +3932,9 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3); } - // since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset - // it should be added in startoffset. so that check done in last of this function can be valued. + /* since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset + * it should be added in startoffset. so that check done in last of this function can be valued. + */ uiSectEndOffset = uiSectStartOffset + uiSectEndOffset; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset); @@ -3926,7 +3943,7 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset); - // Checking the boundary condition + /* Checking the boundary condition */ if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) return TRUE; else { @@ -3935,13 +3952,13 @@ INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT } } -/** -IsFlash2x :- check for Flash 2.x -@Adapater :- Bcm Driver Private Data Structure - -Return value:- - return TRUE if flah2.x of hgher version else return false. -**/ +/* + * IsFlash2x :- check for Flash 2.x + * Adapater :- Bcm Driver Private Data Structure + * + * Return value:- + * return TRUE if flah2.x of hgher version else return false. + */ INT IsFlash2x(struct bcm_mini_adapter *Adapter) { @@ -3951,13 +3968,13 @@ INT IsFlash2x(struct bcm_mini_adapter *Adapter) return FALSE; } -/** -GetFlashBaseAddr :- Calculate the Flash Base address -@Adapater :- Bcm Driver Private Data Structure - -Return Value:- - Success :- Base Address of the Flash -**/ +/* + * GetFlashBaseAddr :- Calculate the Flash Base address + * @Adapater :- Bcm Driver Private Data Structure + * + * Return Value:- + * Success :- Base Address of the Flash + */ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) { @@ -3965,9 +3982,9 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) if (Adapter->bDDRInitDone) { /* - For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr - In case of Raw Read... use the default value - */ + * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + * In case of Raw Read... use the default value + */ if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) uiBaseAddr = Adapter->uiFlashBaseAdd; @@ -3975,9 +3992,9 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT; } else { /* - For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr - In case of Raw Read... use the default value - */ + * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + * In case of Raw Read... use the default value + */ if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; @@ -3988,22 +4005,20 @@ static INT GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) return uiBaseAddr; } -/** -BcmCopySection :- This API is used to copy the One section in another. Both section should - be contiuous and of same size. Hence this Will not be applicabe to copy ISO. - -@Adapater :- Bcm Driver Private Data Structure -@SrcSection :- Source section From where data has to be copied -@DstSection :- Destination section to which data has to be copied -@offset :- Offset from/to where data has to be copied from one section to another. -@numOfBytes :- number of byes that has to be copyed from one section to another at given offset. - in case of numofBytes equal zero complete section will be copied. - -Return Values- - Success : Return STATUS_SUCCESS - Faillure :- return negative error code - -**/ +/* + * BcmCopySection :- This API is used to copy the One section in another. Both section should + * be contiuous and of same size. Hence this Will not be applicabe to copy ISO. + * + * @Adapater :- Bcm Driver Private Data Structure + * @SrcSection :- Source section From where data has to be copied + * @DstSection :- Destination section to which data has to be copied + * @offset :- Offset from/to where data has to be copied from one section to another. + * @numOfBytes :- number of byes that has to be copyed from one section to another at given offset. + * in case of numofBytes equal zero complete section will be copied. + * Return Values- + * Success : Return STATUS_SUCCESS + * Faillure :- return negative error code + */ INT BcmCopySection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL SrcSection, @@ -4031,7 +4046,7 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, return -EINVAL; } - // if offset zero means have to copy complete secton + /* if offset zero means have to copy complete secton */ if (numOfBytes == 0) { numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection) - BcmGetSectionValStartOffset(Adapter, SrcSection); @@ -4099,17 +4114,16 @@ INT BcmCopySection(struct bcm_mini_adapter *Adapter, return Status; } -/** -SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write -@Adapater :- Bcm Driver Private Data Structure -@pBuff :- Data buffer that has to be written in sector having the header map. -@uiOffset :- Flash offset that has to be written. - -Return value :- - Success :- On success return STATUS_SUCCESS - Faillure :- Return negative error code - -**/ +/* + * SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write + * @Adapater :- Bcm Driver Private Data Structure + * @pBuff :- Data buffer that has to be written in sector having the header map. + * @uiOffset :- Flash offset that has to be written. + * + * Return value :- + * Success :- On success return STATUS_SUCCESS + * Faillure :- Return negative error code + */ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiOffset) { @@ -4119,13 +4133,13 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO UINT uiSectAlignAddr = 0; UINT sig = 0; - //making the offset sector aligned + /* making the offset sector aligned */ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) || (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) || (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) { - // offset from the sector boundary having the header map + /* offset from the sector boundary having the header map */ offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; HeaderSizeToProtect = sizeof(DSD_HEADER); bHasHeader = TRUE; @@ -4137,17 +4151,17 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO HeaderSizeToProtect = sizeof(ISO_HEADER); bHasHeader = TRUE; } - // If Header is present overwrite passed buffer with this + /* If Header is present overwrite passed buffer with this */ if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) { pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL); if (pTempBuff == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed"); return -ENOMEM; } - // Read header + /* Read header */ BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect); BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect); - //Replace Buffer content with Header + /* Replace Buffer content with Header */ memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect); kfree(pTempBuff); @@ -4169,13 +4183,13 @@ INT SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, UINT uiO return STATUS_SUCCESS; } -/** -BcmDoChipSelect : This will selcet the appropriate chip for writing. -@Adapater :- Bcm Driver Private Data Structure - -OutPut:- - Select the Appropriate chip and retrn status Success -**/ +/* + * BcmDoChipSelect : This will selcet the appropriate chip for writing. + * @Adapater :- Bcm Driver Private Data Structure + * + * OutPut:- + * Select the Appropriate chip and retrn status Success + */ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) { UINT FlashConfig = 0; @@ -4185,28 +4199,28 @@ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) ChipNum = offset / FLASH_PART_SIZE; - // - // Chip Select mapping to enable flash0. - // To select flash 0, we have to OR with (0<<12). - // ORing 0 will have no impact so not doing that part. - // In future if Chip select value changes from 0 to non zero, - // That needs be taken care with backward comaptibility. No worries for now. - // + /* + * Chip Select mapping to enable flash0. + * To select flash 0, we have to OR with (0<<12). + * ORing 0 will have no impact so not doing that part. + * In future if Chip select value changes from 0 to non zero, + * That needs be taken care with backward comaptibility. No worries for now. + */ /* - SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured - if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) - Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from - power down modes (Idle mode/shutdown mode), the values in the register will be different. - */ + * SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured + * if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) + * Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from + * power down modes (Idle mode/shutdown mode), the values in the register will be different. + */ if (Adapter->SelectedChip == ChipNum) return STATUS_SUCCESS; - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); + /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); */ Adapter->SelectedChip = ChipNum; - // bit[13..12] will select the appropriate chip + /* bit[13..12] will select the appropriate chip */ rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); { @@ -4229,17 +4243,17 @@ static INT BcmDoChipSelect(struct bcm_mini_adapter *Adapter, UINT offset) } } /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired, - nothing to do... can return immediately. - ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. - Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. - These values are not written by host other than during CHIP_SELECT. - */ + * nothing to do... can return immediately. + * ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. + * Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. + * These values are not written by host other than during CHIP_SELECT. + */ if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3)) return STATUS_SUCCESS; - // clearing the bit[13..12] + /* clearing the bit[13..12] */ FlashConfig &= 0xFFFFCFFF; - FlashConfig = (FlashConfig | (PartNum< Date: Wed, 6 Jun 2012 22:54:30 -0400 Subject: [PATCH 0548/5711] Staging: bcm: Fix ERROR: return is not a function, parentheses are not required. This patch fixes the following error reported by checkpatch.pl in nvm.c: "ERROR: return is not a function, parentheses are not required". Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index cfc0458b6e0a..02a090461c76 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -472,7 +472,7 @@ static INT BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, static UINT BcmGetFlashSize(struct bcm_mini_adapter *Adapter) { if (IsFlash2x(Adapter)) - return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); + return Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER); else return 32 * 1024; } @@ -2219,7 +2219,7 @@ static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) */ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); - return (ulRDID >> 8); + return ulRDID >> 8; } INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) -- GitLab From 6788d7dab6a5b126604ae0f40cfb13400fdf37f6 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 6 Jun 2012 22:54:31 -0400 Subject: [PATCH 0549/5711] Staging: bcm: Use udelay instead of msleep for delays in nvm.c This patch uses udelay instead of msleep for delays because msleep can sleep up to 20ms for any value less than 20. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index 02a090461c76..c8a0a9096a0e 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -102,7 +102,7 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) return uiData; } if (!(dwRetries%RETRIES_PER_DELAY)) - msleep(1); + udelay(1000); uiStatus = 0 ; } return uiData; @@ -195,7 +195,7 @@ INT ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, } if (!(dwRetries%RETRIES_PER_DELAY)) - msleep(1); + udelay(1000); } for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) { @@ -577,7 +577,7 @@ static INT FlashSectorErase(struct bcm_mini_adapter *Adapter, * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms * won't hamper performance in any case. */ - msleep(10); + udelay(10000); } while ((uiStatus & 0x1) && (iRetries < 400)); if (uiStatus & 0x1) { @@ -654,7 +654,7 @@ static INT flashByteWrite(struct bcm_mini_adapter *Adapter, } iRetries--; if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); + udelay(1000); } while ((uiStatus & 0x1) && (iRetries > 0)); @@ -734,7 +734,7 @@ static INT flashWrite(struct bcm_mini_adapter *Adapter, * Hence current implementation cycle will intoduce no delay in current path */ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); + udelay(1000); } while ((uiStatus & 0x1) && (iRetries > 0)); if (uiStatus & 0x1) { @@ -811,7 +811,7 @@ static INT flashByteWriteStatus(struct bcm_mini_adapter *Adapter, iRetries--; if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); + udelay(1000); } while ((uiStatus & 0x1) && (iRetries > 0)); @@ -886,7 +886,7 @@ static INT flashWriteStatus(struct bcm_mini_adapter *Adapter, * Hence current implementation cycle will intoduce no delay in current path */ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) - msleep(1); + udelay(1000); } while ((uiStatus & 0x1) && (iRetries > 0)); @@ -1657,7 +1657,7 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] } if (!(uiRetries%RETRIES_PER_DELAY)) - msleep(1); + udelay(1000); uiStatus = 0; rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); @@ -1698,7 +1698,7 @@ static INT BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, UINT uiData[] } uiEpromStatus = 0; if (!(uiRetries%RETRIES_PER_DELAY)) - msleep(1); + udelay(1000); } return STATUS_SUCCESS; -- GitLab From 7dd80eb925a5aac4ebe8b1abec20802e91f60c2e Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Thu, 7 Jun 2012 23:52:42 -0400 Subject: [PATCH 0550/5711] Staging: bcm: Return -ENOMEM instead of -1 when memory not acquired in nmv.c This patch changes the return statement on two conditions where memory could not be acquired. It returns -ENOMEM instead of -1. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/nvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index c8a0a9096a0e..ed2316570d30 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -1378,7 +1378,7 @@ INT PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter) INT Status = 0; if (pBuff == NULL) - return -1; + return -ENOMEM; if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) { kfree(pBuff); @@ -1462,7 +1462,7 @@ INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) pBuff = kmalloc(uiEepromSize, GFP_KERNEL); if (pBuff == NULL) - return -1; + return -ENOMEM; if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) { kfree(pBuff); -- GitLab From dd13c86b0dae86efdde98119ffd7348e80719ade Mon Sep 17 00:00:00 2001 From: Ben Chan Date: Wed, 6 Jun 2012 23:01:26 -0700 Subject: [PATCH 0551/5711] staging: gdm72xx: Fix spinlock recursion on gdm_usb_send_complete This patch fixes a spinlock recursion bug on several call sites of gdm_usb_send_complete by not calling spin_lock_irqsave on urb->context->tx_cxt->lock when the lock has already been acquired. Signed-off-by: Ben Chan Cc: Sage Ahn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/gdm_usb.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index e201b341e52f..646e0ace91ec 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -270,7 +270,7 @@ static void release_usb(struct usbwm_dev *udev) } } -static void gdm_usb_send_complete(struct urb *urb) +static void gdm_usb_send_complete_impl(struct urb *urb, bool need_lock) { struct usb_tx *t = urb->context; struct tx_cxt *tx = t->tx_cxt; @@ -282,7 +282,8 @@ static void gdm_usb_send_complete(struct urb *urb) if (urb->status == -ECONNRESET) return; - spin_lock_irqsave(&tx->lock, flags); + if (need_lock) + spin_lock_irqsave(&tx->lock, flags); if (t->callback) t->callback(t->cb_data); @@ -296,7 +297,18 @@ static void gdm_usb_send_complete(struct urb *urb) else free_tx_struct(t); - spin_unlock_irqrestore(&tx->lock, flags); + if (need_lock) + spin_unlock_irqrestore(&tx->lock, flags); +} + +static void gdm_usb_send_complete(struct urb *urb) +{ + gdm_usb_send_complete_impl(urb, true); +} + +static void gdm_usb_send_complete_no_lock(struct urb *urb) +{ + gdm_usb_send_complete_impl(urb, false); } static int gdm_usb_send(void *priv_dev, void *data, int len, @@ -411,7 +423,7 @@ out: send_fail: t->callback = NULL; - gdm_usb_send_complete(t->urb); + gdm_usb_send_complete_no_lock(t->urb); spin_unlock_irqrestore(&tx->lock, flags); return ret; } @@ -540,7 +552,7 @@ static void do_pm_control(struct work_struct *work) if (ret) { t->callback = NULL; - gdm_usb_send_complete(t->urb); + gdm_usb_send_complete_no_lock(t->urb); } } } @@ -742,7 +754,7 @@ static int k_mode_thread(void *arg) if (ret) { t->callback = NULL; - gdm_usb_send_complete(t->urb); + gdm_usb_send_complete_no_lock(t->urb); } } -- GitLab From 60ebf60b614cafd0c9f58e72cae151edf5e8bd94 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 9 Jun 2012 00:13:57 +0900 Subject: [PATCH 0552/5711] staging: Fix typo in winbond Correct spelling typo in winbond/mto.c and mds_s.h Signed-off-by: Masanari Iida Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/mds_s.h | 2 +- drivers/staging/winbond/mto.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h index 07d835b3b706..2972d66c9436 100644 --- a/drivers/staging/winbond/mds_s.h +++ b/drivers/staging/winbond/mds_s.h @@ -40,7 +40,7 @@ enum { /* * ================================================================ - * Configration default value + * Configuration default value * ================================================================ */ #define DEFAULT_MULTICASTLISTMAX 32 /* standard */ diff --git a/drivers/staging/winbond/mto.c b/drivers/staging/winbond/mto.c index 5250217156a7..1b52ebd4b011 100644 --- a/drivers/staging/winbond/mto.c +++ b/drivers/staging/winbond/mto.c @@ -33,7 +33,7 @@ u16 MTO_Frag_Th_Tbl[MTO_MAX_FRAG_TH_LEVELS] = { /* * Declare data rate table: - * The following table will be changed at anytime if the opration rate + * The following table will be changed at anytime if the operation rate * supported by AP don't match the table */ static u8 MTO_Data_Rate_Tbl[MTO_MAX_DATA_RATE_LEVELS] = { -- GitLab From 0cf5755f00f555d7cef4a7be0ae5aac5e4bdf07d Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 9 Jun 2012 00:19:17 +0900 Subject: [PATCH 0553/5711] staging: rts5139: Fix typo in rts5139 Correct spelling typo in rts5139/rts51x_chip.h, rts51x_scsi.h Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5139/rts51x_chip.h | 2 +- drivers/staging/rts5139/rts51x_scsi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts5139/rts51x_chip.h b/drivers/staging/rts5139/rts51x_chip.h index 6d395b6533a8..64257caf2f30 100644 --- a/drivers/staging/rts5139/rts51x_chip.h +++ b/drivers/staging/rts5139/rts51x_chip.h @@ -204,7 +204,7 @@ struct trace_msg_t { /*---- error code ----*/ #define CUR_ERR 0x70 /* current error */ -/*---- sense key Infomation ----*/ +/*---- sense key Information ----*/ #define SKSV 0x80 #define CDB_ILLEGAL 0x40 diff --git a/drivers/staging/rts5139/rts51x_scsi.h b/drivers/staging/rts5139/rts51x_scsi.h index 060d2c2e77ec..9042bc98a9a0 100644 --- a/drivers/staging/rts5139/rts51x_scsi.h +++ b/drivers/staging/rts5139/rts51x_scsi.h @@ -73,7 +73,7 @@ #define GET_BATCHRSP 0x44 #ifdef SUPPORT_CPRM -/* SD Pass Through Command Extention */ +/* SD Pass Through Command Extension */ #define SD_PASS_THRU_MODE 0xD0 #define SD_EXECUTE_NO_DATA 0xD1 #define SD_EXECUTE_READ 0xD2 -- GitLab From 6fe864409b54f60ed36804752acfd148da459e53 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jun 2012 20:05:16 +0300 Subject: [PATCH 0554/5711] Staging: rtl8187se, rtl8192e: fix '&' vs '|' bugs The original code is equivalent to: wrqu->retry.flags = 0x1000 & 0x0002; so it just sets .flags to zero. We should be ORing the values together like r8192_wx_get_retry() does in drivers/staging/rtl8192u/r8192U_wx.c. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/r8180_wx.c | 4 ++-- drivers/staging/rtl8192e/rtl8192e/rtl_wx.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 46ee6f47f525..52f63d75d248 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -615,10 +615,10 @@ static int r8180_wx_get_retry(struct net_device *dev, return -EINVAL; if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; wrqu->retry.value = priv->retry_rts; } else { - wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN; + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; wrqu->retry.value = priv->retry_data; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 778d7baf8e08..6202358c2984 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -919,10 +919,10 @@ static int r8192_wx_get_retry(struct net_device *dev, return -EINVAL; if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; wrqu->retry.value = priv->retry_rts; } else { - wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN; + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; wrqu->retry.value = priv->retry_data; } return 0; -- GitLab From 67c4e9f46b5241ff777ced09e29048363de8703f Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Sun, 10 Jun 2012 13:12:22 +0200 Subject: [PATCH 0555/5711] staging: sm7xx: code improvement This patch simplifies code. It erases redundant code under little endian compilations. Signed-off-by: Javier M. Mellid Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xx/smtcfb.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c index 746c4cd5d30e..2c172d6cd65f 100644 --- a/drivers/staging/sm7xx/smtcfb.c +++ b/drivers/staging/sm7xx/smtcfb.c @@ -724,16 +724,13 @@ static void smtc_unmap_mmio(struct smtcfb_info *sfb) static int smtc_map_smem(struct smtcfb_info *sfb, struct pci_dev *pdev, u_long smem_len) { - if (sfb->fb.var.bits_per_pixel == 32) { + + sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); + #ifdef __BIG_ENDIAN - sfb->fb.fix.smem_start = pci_resource_start(pdev, 0) - + 0x800000; -#else - sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); + if (sfb->fb.var.bits_per_pixel == 32) + sfb->fb.fix.smem_start += 0x800000; #endif - } else { - sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); - } sfb->fb.fix.smem_len = smem_len; -- GitLab From 0beb30d365b0fb36c9cac7b7dbe980e882378f23 Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Sun, 10 Jun 2012 13:12:23 +0200 Subject: [PATCH 0556/5711] staging: sm7xx: update comments and clarify supported chips This patch updates/adds comments in order to clarify devices and Lynx families supported for this driver. Signed-off-by: Javier M. Mellid Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xx/Kconfig | 9 +++++++-- drivers/staging/sm7xx/smtcfb.c | 10 +++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig index 315102c7fed1..323964f5b1a9 100644 --- a/drivers/staging/sm7xx/Kconfig +++ b/drivers/staging/sm7xx/Kconfig @@ -1,8 +1,13 @@ config FB_SM7XX - tristate "Silicon Motion SM7XX Frame Buffer Support" + tristate "Silicon Motion SM7XX framebuffer support" depends on FB select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT help - Frame Buffer driver for the Silicon Motion SM7XX serial graphic card. + Frame buffer driver for the Silicon Motion SM710, SM712, SM721 + and SM722 chips. + + This driver is also available as a module. The module will be + called sm7xx. If you want to compile it as a module, say M + here and read . diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c index 2c172d6cd65f..e7028a312ce1 100644 --- a/drivers/staging/sm7xx/smtcfb.c +++ b/drivers/staging/sm7xx/smtcfb.c @@ -15,6 +15,7 @@ * License. See the file COPYING in the main directory of this archive for * more details. * + * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips */ #include @@ -758,7 +759,7 @@ static void smtc_unmap_smem(struct smtcfb_info *sfb) } /* - * We need to wake up the LynxEM+, and make sure its in linear memory mode. + * We need to wake up the device and make sure its in linear memory mode. */ static inline void sm7xx_init_hw(void) { @@ -963,7 +964,11 @@ failed_free: return err; } - +/* + * 0x710 (LynxEM) + * 0x712 (LynxEM+) + * 0x720 (Lynx3DM, Lynx3DM+) + */ static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = { { PCI_DEVICE(0x126f, 0x710), }, { PCI_DEVICE(0x126f, 0x712), }, @@ -971,7 +976,6 @@ static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = { {0,} }; - static void __devexit smtcfb_pci_remove(struct pci_dev *pdev) { struct smtcfb_info *sfb; -- GitLab From 925aa6600cee015b694cb5fe2a9c667e0d9a68c6 Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Sun, 10 Jun 2012 13:12:24 +0200 Subject: [PATCH 0557/5711] staging: sm7xxfb: sm7xx becomes sm7xxfb Rename sm7xx driver to sm7xxfb. Fix Kconfig and Makefile to fit the new change. Changes are coherent with the rest of stable framebuffer drivers. TODO updated. Signed-off-by: Javier M. Mellid Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 +- drivers/staging/Makefile | 2 +- drivers/staging/sm7xx/Makefile | 3 --- drivers/staging/{sm7xx => sm7xxfb}/Kconfig | 2 +- drivers/staging/sm7xxfb/Makefile | 1 + drivers/staging/{sm7xx => sm7xxfb}/TODO | 2 +- drivers/staging/{sm7xx/smtcfb.h => sm7xxfb/sm7xx.h} | 0 drivers/staging/{sm7xx/smtcfb.c => sm7xxfb/sm7xxfb.c} | 2 +- 8 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 drivers/staging/sm7xx/Makefile rename drivers/staging/{sm7xx => sm7xxfb}/Kconfig (85%) create mode 100644 drivers/staging/sm7xxfb/Makefile rename drivers/staging/{sm7xx => sm7xxfb}/TODO (76%) rename drivers/staging/{sm7xx/smtcfb.h => sm7xxfb/sm7xx.h} (100%) rename drivers/staging/{sm7xx/smtcfb.c => sm7xxfb/sm7xxfb.c} (99%) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 05e33c700750..38f1fb08eaef 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -84,7 +84,7 @@ source "drivers/staging/wlags49_h2/Kconfig" source "drivers/staging/wlags49_h25/Kconfig" -source "drivers/staging/sm7xx/Kconfig" +source "drivers/staging/sm7xxfb/Kconfig" source "drivers/staging/crystalhd/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a987b3ad380b..e0c4c2444fed 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -37,7 +37,7 @@ obj-$(CONFIG_ZCACHE) += zcache/ obj-$(CONFIG_ZSMALLOC) += zsmalloc/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ -obj-$(CONFIG_FB_SM7XX) += sm7xx/ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ obj-$(CONFIG_CRYSTALHD) += crystalhd/ obj-$(CONFIG_CXT1E1) += cxt1e1/ obj-$(CONFIG_FB_XGI) += xgifb/ diff --git a/drivers/staging/sm7xx/Makefile b/drivers/staging/sm7xx/Makefile deleted file mode 100644 index f43cb9106305..000000000000 --- a/drivers/staging/sm7xx/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_FB_SM7XX) += sm7xx.o - -sm7xx-y := smtcfb.o diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xxfb/Kconfig similarity index 85% rename from drivers/staging/sm7xx/Kconfig rename to drivers/staging/sm7xxfb/Kconfig index 323964f5b1a9..d5013f8a865b 100644 --- a/drivers/staging/sm7xx/Kconfig +++ b/drivers/staging/sm7xxfb/Kconfig @@ -9,5 +9,5 @@ config FB_SM7XX and SM722 chips. This driver is also available as a module. The module will be - called sm7xx. If you want to compile it as a module, say M + called sm7xxfb. If you want to compile it as a module, say M here and read . diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile new file mode 100644 index 000000000000..48f471cf9f36 --- /dev/null +++ b/drivers/staging/sm7xxfb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xxfb/TODO similarity index 76% rename from drivers/staging/sm7xx/TODO rename to drivers/staging/sm7xxfb/TODO index 7304021368c3..1fcead591c16 100644 --- a/drivers/staging/sm7xx/TODO +++ b/drivers/staging/sm7xxfb/TODO @@ -3,7 +3,7 @@ TODO: - 2D acceleration support - use kernel coding style - refine the code and remove unused code -- move it to drivers/video/sm7xx/ or make it be drivers/video/sm7xxfb.c +- move it to drivers/video/sm7xxfb.c Please send any patches to Greg Kroah-Hartman and Teddy Wang . diff --git a/drivers/staging/sm7xx/smtcfb.h b/drivers/staging/sm7xxfb/sm7xx.h similarity index 100% rename from drivers/staging/sm7xx/smtcfb.h rename to drivers/staging/sm7xxfb/sm7xx.h diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c similarity index 99% rename from drivers/staging/sm7xx/smtcfb.c rename to drivers/staging/sm7xxfb/sm7xxfb.c index e7028a312ce1..21dab346253a 100644 --- a/drivers/staging/sm7xx/smtcfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -32,7 +32,7 @@ #include #endif -#include "smtcfb.h" +#include "sm7xx.h" struct screen_info smtc_screen_info; -- GitLab From 14e70bfdc6dd4d6b88f3477f3966df7405e78a69 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 11 Jun 2012 08:56:36 +0200 Subject: [PATCH 0558/5711] Staging: ipack: remove pr_fmt definition. As there is no pr_* function used here, pr_fmt is not needed. Signed-off-by: Samuel Iglesias Gonsalvez Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/ipack.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c index a1448e68fd7a..c1cd97a4d9ce 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/staging/ipack/ipack.c @@ -9,8 +9,6 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include -- GitLab From 4bce6b897ed6812e000c034968c8c250de40da9b Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 11 Jun 2012 11:11:59 +0200 Subject: [PATCH 0559/5711] staging: usb: gadget: Configurable Composite Gadget depends on BLOCK Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccg/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ccg/Kconfig b/drivers/staging/ccg/Kconfig index ff05e52392bf..1f00d701da25 100644 --- a/drivers/staging/ccg/Kconfig +++ b/drivers/staging/ccg/Kconfig @@ -2,7 +2,7 @@ if USB_GADGET config USB_G_CCG tristate "Configurable Composite Gadget (STAGING)" - depends on STAGING && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM + depends on STAGING && BLOCK && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM help The Configurable Composite Gadget supports multiple USB functions: acm, mass storage, rndis and FunctionFS. -- GitLab From 383b7fc2dca769d98ca373306e105987e8f143b3 Mon Sep 17 00:00:00 2001 From: William Blair Date: Sun, 10 Jun 2012 15:10:33 -0400 Subject: [PATCH 0560/5711] Staging: keucr: init: fixed a brace coding style issue Fixed a coding style issue. Signed-off-by: William Blair Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/keucr/init.c b/drivers/staging/keucr/init.c index 071bdc238786..231611dc0f74 100644 --- a/drivers/staging/keucr/init.c +++ b/drivers/staging/keucr/init.c @@ -30,9 +30,8 @@ int ENE_InitMedia(struct us_data *us) if (MiscReg03 & 0x02) { if (!us->SM_Status.Ready && !us->MS_Status.Ready) { result = ENE_SMInit(us); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - } } } -- GitLab From 7a2ea600fcda3cfa04033cf3077116cf2522aa9c Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Tue, 12 Jun 2012 11:37:46 +0200 Subject: [PATCH 0561/5711] Staging: ipack: delete sysfs from to-do list. As we have already got rid of sysfs files in the tpci200 driver, it is needed to delete that mention in the TODO file. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/TODO | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/ipack/TODO b/drivers/staging/ipack/TODO index 3a45a53afd88..0f8bf2044843 100644 --- a/drivers/staging/ipack/TODO +++ b/drivers/staging/ipack/TODO @@ -15,10 +15,6 @@ TODO TPCI-200 -------- -* It receives the name of the mezzanine plugged in each slot by SYSFS. - No autodetection supported yet, because the mezzanine driver could not be - loaded at the time that the tpci200 driver loads. - * It has a linked list with the tpci200 devices it is managing. Get rid of it and use driver_for_each_device() instead. -- GitLab From e34995148a2a305106c4f746fb76da23488c46c7 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 11 Jun 2012 07:48:46 -0700 Subject: [PATCH 0562/5711] staging "sep" Fix typos found while reading. Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_crypto.c | 18 ++++++------- drivers/staging/sep/sep_driver_api.h | 8 +++--- drivers/staging/sep/sep_driver_config.h | 4 +-- drivers/staging/sep/sep_main.c | 36 ++++++++++++------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index 9fd9da84428e..045493b61995 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -807,7 +807,7 @@ end_function: * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes * @msg_offset: pointer to current offset (is updated) - * @byte_array: flag ti indicate wheter endian must be changed + * @byte_array: flag ti indicate whether endian must be changed * Copies data into the message area from caller */ static void sep_write_msg(struct this_task_ctx *ta_ctx, void *in_addr, @@ -855,7 +855,7 @@ static void sep_make_header(struct this_task_ctx *ta_ctx, u32 *msg_offset, * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes * @msg_offset: pointer to current offset (is updated) - * @byte_array: flag ti indicate wheter endian must be changed + * @byte_array: flag ti indicate whether endian must be changed * Copies data out of the message area to caller */ static void sep_read_msg(struct this_task_ctx *ta_ctx, void *in_addr, @@ -990,7 +990,7 @@ static void sep_clear_out(struct this_task_ctx *ta_ctx) /** * The following unlocks the sep and makes it available * to any other application - * First, null out crypto entries in sep before relesing it + * First, null out crypto entries in sep before releasing it */ ta_ctx->sep_used->current_hash_req = NULL; ta_ctx->sep_used->current_cypher_req = NULL; @@ -1001,7 +1001,7 @@ static void sep_clear_out(struct this_task_ctx *ta_ctx) ta_ctx->call_status.status = 0; - /* Remove anything confidentail */ + /* Remove anything confidential */ memset(ta_ctx->sep_used->shared_addr, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); @@ -1207,7 +1207,7 @@ static int sep_crypto_block_data(struct ablkcipher_request *req) req->nbytes, ta_ctx->walk.blocksize, &new_sg, 1); if (int_error < 0) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page eerror\n"); + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page error\n"); return -ENOMEM; } else if (int_error == 1) { ta_ctx->src_sg = new_sg; @@ -1870,7 +1870,7 @@ static u32 hash_update_post_op(struct sep_device *sep) sizeof(struct sep_hash_private_context)); /** - * Following is only for finup; if we just completd the + * Following is only for finup; if we just completed the * data portion of finup, we now need to kick off the * finish portion of finup. */ @@ -2011,7 +2011,7 @@ static u32 hash_digest_post_op(struct sep_device *sep) } /** - * The sep_finish function is the function that is schedule (via tasket) + * The sep_finish function is the function that is scheduled (via tasklet) * by the interrupt service routine when the SEP sends and interrupt * This is only called by the interrupt handler as a tasklet. */ @@ -2249,7 +2249,7 @@ static void sep_hash_update(void *data) head_len = (block_size - int_ctx->prev_update_bytes) % block_size; tail_len = (req->nbytes - head_len) % block_size; - /* Make sure all pages are even block */ + /* Make sure all pages are an even block */ int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); @@ -2482,7 +2482,7 @@ static void sep_hash_digest(void *data) dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); - /* Make sure all pages are even block */ + /* Make sure all pages are an even block */ int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h index 8b797d5388bb..7ee1c3bf17d7 100644 --- a/drivers/staging/sep/sep_driver_api.h +++ b/drivers/staging/sep/sep_driver_api.h @@ -91,7 +91,7 @@ struct sep_dcblock { }; /* - command structure for building dcb block (currently for ext app only + command structure for building dcb block (currently for ext app only) */ struct build_dcb_struct { /* address value of the data in */ @@ -234,7 +234,7 @@ struct sep_dma_context { u32 dmatables_len; /* size of input data */ u32 input_data_len; - /* secure dma use (for imr memory restriced area in output */ + /* secure dma use (for imr memory restricted area in output) */ bool secure_dma; struct sep_dma_resource dma_res_arr[SEP_MAX_NUM_SYNC_DMA_OPS]; /* Scatter gather for kernel crypto */ @@ -347,10 +347,10 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, /** * sep_free_dma_table_data_handler - free DMA table - * @sep: pointere to struct sep_device + * @sep: pointer to struct sep_device * @dma_ctx: dma context * - * Handles the request to free DMA table for synchronic actions + * Handles the request to free DMA table for synchronic actions */ int sep_free_dma_table_data_handler(struct sep_device *sep, struct sep_dma_context **dma_ctx); diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h index 9d9fc7c94a6e..7d7c7ab610b7 100644 --- a/drivers/staging/sep/sep_driver_config.h +++ b/drivers/staging/sep/sep_driver_config.h @@ -43,7 +43,7 @@ #define SEP_DRIVER_POLLING_MODE 0 /* flag which defines if the shared area address should be - reconfiged (send to SEP anew) during init of the driver */ + reconfigured (send to SEP anew) during init of the driver */ #define SEP_DRIVER_RECONFIG_MESSAGE_AREA 0 /* the mode for running on the ARM1172 Evaluation platform (flag is 1) */ @@ -166,7 +166,7 @@ held by the process (struct file) */ (SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \ SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES) -/* synhronic dma tables area offset */ +/* synchronic dma tables area offset */ #define SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES \ (SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \ SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index ab351289d893..270fcb811b80 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -94,7 +94,7 @@ #endif /** - * Currenlty, there is only one SEP device per platform; + * Currently, there is only one SEP device per platform; * In event platforms in the future have more than one SEP * device, this will be a linked list */ @@ -106,7 +106,7 @@ struct sep_device *sep_dev; * @sep: SEP device * @sep_queue_info: pointer to status queue * - * This function will removes information about transaction from the queue. + * This function will remove information about transaction from the queue. */ void sep_queue_status_remove(struct sep_device *sep, struct sep_queue_info **queue_elem) @@ -294,7 +294,7 @@ int sep_wait_transaction(struct sep_device *sep) end_function_setpid: /* * The pid_doing_transaction indicates that this process - * now owns the facilities to performa a transaction with + * now owns the facilities to perform a transaction with * the SEP. While this process is performing a transaction, * no other process who has the SEP device open can perform * any transactions. This method allows more than one process @@ -447,10 +447,10 @@ static int sep_open(struct inode *inode, struct file *filp) /** * sep_free_dma_table_data_handler - free DMA table - * @sep: pointere to struct sep_device + * @sep: pointer to struct sep_device * @dma_ctx: dma context * - * Handles the request to free DMA table for synchronic actions + * Handles the request to free DMA table for synchronic actions */ int sep_free_dma_table_data_handler(struct sep_device *sep, struct sep_dma_context **dma_ctx) @@ -540,7 +540,7 @@ int sep_free_dma_table_data_handler(struct sep_device *sep, * don't have a page array; the page array is generated * only in the lock_user_pages, which is not called * for kernel crypto, which is what the sg (scatter gather - * is used for exclusively + * is used for exclusively) */ if (dma->src_sg) { dma_unmap_sg(&sep->pdev->dev, dma->src_sg, @@ -1227,7 +1227,7 @@ static int sep_lock_user_pages(struct sep_device *sep, /* Map array */ struct sep_dma_map *map_array; - /* Set start and end pages and num pages */ + /* Set start and end pages and num pages */ end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; start_page = app_virt_addr >> PAGE_SHIFT; num_pages = end_page - start_page + 1; @@ -1431,7 +1431,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep, /* Array of lli */ struct sep_lli_entry *lli_array; - /* Set start and end pages and num pages */ + /* Set start and end pages and num pages */ end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; start_page = app_virt_addr >> PAGE_SHIFT; num_pages = end_page - start_page + 1; @@ -1602,7 +1602,7 @@ end_function: * @num_table_entries_ptr: pointer to number of tables * @table_data_size: total data size * - * Builds ant lli table from the lli_array according to + * Builds an lli table from the lli_array according to * the given size of data */ static void sep_build_lli_table(struct sep_device *sep, @@ -1701,7 +1701,7 @@ static void sep_build_lli_table(struct sep_device *sep, * @virt_address: virtual address to convert * * This functions returns the physical address inside shared area according - * to the virtual address. It can be either on the externa RAM device + * to the virtual address. It can be either on the external RAM device * (ioremapped), or on the system RAM * This implementation is for the external RAM */ @@ -1725,7 +1725,7 @@ static dma_addr_t sep_shared_area_virt_to_bus(struct sep_device *sep, * * This functions returns the virtual address inside shared area * according to the physical address. It can be either on the - * externa RAM device (ioremapped), or on the system RAM + * external RAM device (ioremapped), or on the system RAM * This implementation is for the external RAM */ static void *sep_shared_area_bus_to_virt(struct sep_device *sep, @@ -1891,9 +1891,9 @@ static void sep_prepare_empty_lli_table(struct sep_device *sep, * @lli_table_ptr: * @num_entries_ptr: * @table_data_size_ptr: - * @is_kva: set for kernel data (kernel cryptio call) + * @is_kva: set for kernel data (kernel crypt io call) * - * This function prepares only input DMA table for synhronic symmetric + * This function prepares only input DMA table for synchronic symmetric * operations (HASH) * Note that all bus addresses that are passed to the SEP * are in 32 bit format; the SEP is a 32 bit device @@ -2174,9 +2174,9 @@ static int sep_construct_dma_tables_from_lli( u32 last_table_flag = 0; /* The data size that should be in table */ u32 table_data_size = 0; - /* Number of etnries in the input table */ + /* Number of entries in the input table */ u32 num_entries_in_table = 0; - /* Number of etnries in the output table */ + /* Number of entries in the output table */ u32 num_entries_out_table = 0; if (!dma_ctx) { @@ -2401,7 +2401,7 @@ static int sep_construct_dma_tables_from_lli( * @table_data_size_ptr: * @is_kva: set for kernel data; used only for kernel crypto module * - * This function builds input and output DMA tables for synhronic + * This function builds input and output DMA tables for synchronic * symmetric operations (AES, DES, HASH). It also checks that each table * is of the modular block size * Note that all bus addresses that are passed to the SEP @@ -2556,7 +2556,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep, "[PID%d] SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is (hex) %x\n", current->pid, SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - /* Call the fucntion that creates table from the lli arrays */ + /* Call the function that creates table from the lli arrays */ dev_dbg(&sep->pdev->dev, "[PID%d] calling create table from lli\n", current->pid); error = sep_construct_dma_tables_from_lli( @@ -3663,7 +3663,7 @@ static ssize_t sep_read(struct file *filp, goto end_function; } - /* Checks that user has called necessarry apis */ + /* Checks that user has called necessary apis */ if (0 == test_bit(SEP_FASTCALL_WRITE_DONE_OFFSET, &call_status->status)) { dev_warn(&sep->pdev->dev, -- GitLab From 2f0b9d082e5d0056a3aca4be038483a564849196 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 11 Jun 2012 17:45:15 -0700 Subject: [PATCH 0563/5711] staging: comedi: export alloc_subdevices as comedi_alloc_subdevices Move the inline alloc_subdevices() function from comedidev.h to drivers.c and rename it to comedi_alloc_subdevices(). The function is large enough to warrant being an exported symbol rather than being an inline in every driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 22 ++----------------- drivers/staging/comedi/drivers.c | 21 ++++++++++++++++++ drivers/staging/comedi/drivers/8255.c | 2 +- drivers/staging/comedi/drivers/acl7225b.c | 2 +- .../comedi/drivers/addi-data/addi_common.c | 2 +- .../comedi/drivers/addi-data/hwdrv_APCI1710.c | 2 +- drivers/staging/comedi/drivers/adl_pci6208.c | 2 +- drivers/staging/comedi/drivers/adl_pci7230.c | 2 +- drivers/staging/comedi/drivers/adl_pci7296.c | 2 +- drivers/staging/comedi/drivers/adl_pci7432.c | 2 +- drivers/staging/comedi/drivers/adl_pci8164.c | 2 +- drivers/staging/comedi/drivers/adl_pci9111.c | 2 +- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- drivers/staging/comedi/drivers/adq12b.c | 2 +- drivers/staging/comedi/drivers/adv_pci1710.c | 2 +- drivers/staging/comedi/drivers/adv_pci1723.c | 2 +- drivers/staging/comedi/drivers/adv_pci_dio.c | 2 +- drivers/staging/comedi/drivers/aio_aio12_8.c | 2 +- drivers/staging/comedi/drivers/aio_iiro_16.c | 2 +- drivers/staging/comedi/drivers/amplc_dio200.c | 2 +- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- drivers/staging/comedi/drivers/amplc_pc263.c | 2 +- drivers/staging/comedi/drivers/amplc_pci224.c | 2 +- drivers/staging/comedi/drivers/amplc_pci230.c | 2 +- drivers/staging/comedi/drivers/c6xdigio.c | 3 ++- drivers/staging/comedi/drivers/cb_das16_cs.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas64.c | 2 +- drivers/staging/comedi/drivers/cb_pcidda.c | 2 +- drivers/staging/comedi/drivers/cb_pcidio.c | 2 +- drivers/staging/comedi/drivers/cb_pcimdas.c | 2 +- drivers/staging/comedi/drivers/cb_pcimdda.c | 2 +- drivers/staging/comedi/drivers/comedi_bond.c | 2 +- .../staging/comedi/drivers/comedi_parport.c | 2 +- drivers/staging/comedi/drivers/comedi_test.c | 2 +- .../staging/comedi/drivers/contec_pci_dio.c | 2 +- drivers/staging/comedi/drivers/daqboard2000.c | 2 +- drivers/staging/comedi/drivers/das08.c | 2 +- drivers/staging/comedi/drivers/das16.c | 2 +- drivers/staging/comedi/drivers/das16m1.c | 2 +- drivers/staging/comedi/drivers/das1800.c | 2 +- drivers/staging/comedi/drivers/das6402.c | 2 +- drivers/staging/comedi/drivers/das800.c | 2 +- drivers/staging/comedi/drivers/dmm32at.c | 2 +- drivers/staging/comedi/drivers/dt2801.c | 2 +- drivers/staging/comedi/drivers/dt2811.c | 2 +- drivers/staging/comedi/drivers/dt2814.c | 2 +- drivers/staging/comedi/drivers/dt2815.c | 2 +- drivers/staging/comedi/drivers/dt2817.c | 2 +- drivers/staging/comedi/drivers/dt282x.c | 2 +- drivers/staging/comedi/drivers/dt3000.c | 2 +- drivers/staging/comedi/drivers/dt9812.c | 2 +- drivers/staging/comedi/drivers/dyna_pci10xx.c | 2 +- drivers/staging/comedi/drivers/fl512.c | 2 +- drivers/staging/comedi/drivers/gsc_hpdi.c | 2 +- drivers/staging/comedi/drivers/icp_multi.c | 2 +- drivers/staging/comedi/drivers/ii_pci20kc.c | 2 +- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- drivers/staging/comedi/drivers/ke_counter.c | 2 +- drivers/staging/comedi/drivers/me4000.c | 2 +- drivers/staging/comedi/drivers/me_daq.c | 2 +- drivers/staging/comedi/drivers/mpc624.c | 2 +- drivers/staging/comedi/drivers/mpc8260cpm.c | 2 +- drivers/staging/comedi/drivers/multiq3.c | 2 +- drivers/staging/comedi/drivers/ni_6527.c | 2 +- drivers/staging/comedi/drivers/ni_65xx.c | 2 +- drivers/staging/comedi/drivers/ni_660x.c | 2 +- drivers/staging/comedi/drivers/ni_670x.c | 2 +- drivers/staging/comedi/drivers/ni_at_a2150.c | 2 +- drivers/staging/comedi/drivers/ni_at_ao.c | 2 +- drivers/staging/comedi/drivers/ni_atmio16d.c | 2 +- drivers/staging/comedi/drivers/ni_daq_700.c | 2 +- drivers/staging/comedi/drivers/ni_daq_dio24.c | 2 +- drivers/staging/comedi/drivers/ni_labpc.c | 2 +- .../staging/comedi/drivers/ni_mio_common.c | 2 +- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/pcl711.c | 2 +- drivers/staging/comedi/drivers/pcl724.c | 2 +- drivers/staging/comedi/drivers/pcl725.c | 2 +- drivers/staging/comedi/drivers/pcl726.c | 2 +- drivers/staging/comedi/drivers/pcl730.c | 2 +- drivers/staging/comedi/drivers/pcl812.c | 2 +- drivers/staging/comedi/drivers/pcl816.c | 2 +- drivers/staging/comedi/drivers/pcl818.c | 2 +- drivers/staging/comedi/drivers/pcm3724.c | 2 +- drivers/staging/comedi/drivers/pcm3730.c | 2 +- drivers/staging/comedi/drivers/pcmad.c | 2 +- drivers/staging/comedi/drivers/pcmda12.c | 2 +- drivers/staging/comedi/drivers/pcmmio.c | 2 +- drivers/staging/comedi/drivers/pcmuio.c | 2 +- drivers/staging/comedi/drivers/poc.c | 2 +- .../staging/comedi/drivers/quatech_daqp_cs.c | 2 +- drivers/staging/comedi/drivers/rtd520.c | 2 +- drivers/staging/comedi/drivers/rti800.c | 2 +- drivers/staging/comedi/drivers/rti802.c | 2 +- drivers/staging/comedi/drivers/s526.c | 2 +- drivers/staging/comedi/drivers/s626.c | 2 +- drivers/staging/comedi/drivers/serial2002.c | 2 +- drivers/staging/comedi/drivers/skel.c | 2 +- drivers/staging/comedi/drivers/ssv_dnp.c | 2 +- drivers/staging/comedi/drivers/unioxx5.c | 2 +- drivers/staging/comedi/drivers/usbdux.c | 2 +- drivers/staging/comedi/drivers/usbduxfast.c | 2 +- drivers/staging/comedi/drivers/usbduxsigma.c | 2 +- drivers/staging/comedi/drivers/vmk80xx.c | 2 +- 105 files changed, 127 insertions(+), 123 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 9cd2b5117106..bb98f82141a1 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -292,6 +292,8 @@ static inline struct comedi_subdevice *comedi_get_write_subdevice( return info->device->write_subdev; } +int comedi_alloc_subdevices(struct comedi_device *, unsigned int); + void comedi_device_detach(struct comedi_device *dev); int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it); @@ -413,26 +415,6 @@ struct comedi_lrange { /* some silly little inline functions */ -static inline int alloc_subdevices(struct comedi_device *dev, - unsigned int num_subdevices) -{ - unsigned i; - - dev->n_subdevices = num_subdevices; - dev->subdevices = - kcalloc(num_subdevices, sizeof(struct comedi_subdevice), - GFP_KERNEL); - if (!dev->subdevices) - return -ENOMEM; - for (i = 0; i < num_subdevices; ++i) { - dev->subdevices[i].device = dev; - dev->subdevices[i].async_dma_dir = DMA_NONE; - spin_lock_init(&dev->subdevices[i].spin_lock); - dev->subdevices[i].minor = -1; - } - return 0; -} - static inline int alloc_private(struct comedi_device *dev, int size) { dev->private = kzalloc(size, GFP_KERNEL); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 49e53eaa8e41..541364782b5f 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -56,6 +56,27 @@ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_driver *comedi_drivers; +int comedi_alloc_subdevices(struct comedi_device *dev, + unsigned int num_subdevices) +{ + unsigned i; + + dev->n_subdevices = num_subdevices; + dev->subdevices = + kcalloc(num_subdevices, sizeof(struct comedi_subdevice), + GFP_KERNEL); + if (!dev->subdevices) + return -ENOMEM; + for (i = 0; i < num_subdevices; ++i) { + dev->subdevices[i].device = dev; + dev->subdevices[i].async_dma_dir = DMA_NONE; + spin_lock_init(&dev->subdevices[i].spin_lock); + dev->subdevices[i].minor = -1; + } + return 0; +} +EXPORT_SYMBOL_GPL(comedi_alloc_subdevices); + static void cleanup_device(struct comedi_device *dev) { int i; diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 27e39e4eb6b3..875b02021777 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -388,7 +388,7 @@ static int dev_8255_attach(struct comedi_device *dev, return -EINVAL; } - ret = alloc_subdevices(dev, i); + ret = comedi_alloc_subdevices(dev, i); if (ret < 0) { /* FIXME this printk call should give a proper message, the * below line just maintains previous functionality */ diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index c1963add660d..3c39148c64cb 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -82,7 +82,7 @@ static int acl7225b_attach(struct comedi_device *dev, dev->iobase = iobase; dev->irq = 0; - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 44aaf8351ba3..274990a7cd3f 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -1688,7 +1688,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } else { /* Update-0.7.57->0.7.68dev->n_subdevices = 7; */ n_subdevices = 7; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c index a76ed2553fb4..9632ca182d25 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -63,7 +63,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) int n_subdevices = 9; /* Update-0.7.57->0.7.68dev->n_subdevices = 9; */ - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return; diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 2f48dc72b20e..7d26d45d0753 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -301,7 +301,7 @@ static int pci6208_attach(struct comedi_device *dev, dev->iobase = io_base; dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index 2c8349273d7f..5a6e6c11e7fe 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -116,7 +116,7 @@ static int adl_pci7230_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7230_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; devpriv->pci_dev = adl_pci7230_find_pci(dev, it); diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index 0b8b27983122..fd9b33afd458 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -92,7 +92,7 @@ static int adl_pci7296_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7296_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; devpriv->pci_dev = adl_pci7296_find_pci(dev, it); diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index dd818f1b75ae..4976a70fb1e4 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -125,7 +125,7 @@ static int adl_pci7432_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; devpriv->pci_dev = adl_pci7432_find_pci(dev, it); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 344754877892..78169f7d06ac 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -261,7 +261,7 @@ static int adl_pci8164_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; devpriv->pci_dev = adl_pci8164_find_pci(dev, it); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 410bbf9f5a95..cc179466dce0 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1317,7 +1317,7 @@ static int pci9111_attach(struct comedi_device *dev, /* TODO: Add external multiplexer setup (according to option[2]). */ - error = alloc_subdevices(dev, 4); + error = comedi_alloc_subdevices(dev, 4); if (error < 0) return error; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 5a5c903f5e03..ebd8b8ec8c31 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2268,7 +2268,7 @@ static int pci9118_attach(struct comedi_device *dev, pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64); /* Enable parity check for parity error */ - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 1da298967413..ca8892e83db1 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -271,7 +271,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index db9f0a56f79f..be3fc4dd8859 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1433,7 +1433,7 @@ static int pci1710_attach(struct comedi_device *dev, if (this_board->n_counter) n_subdevices++; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index b8768b54e943..0aa0af4741a5 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -365,7 +365,7 @@ static int pci1723_attach(struct comedi_device *dev, if (this_board->n_diochan) n_subdevices++; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) { printk(" - Allocation failed!\n"); return ret; diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index df8236c952e7..0fc4f858acca 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1156,7 +1156,7 @@ static int pci_dio_attach(struct comedi_device *dev, n_subdevices++; } - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index d215ae16668b..60466c81e2a9 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -182,7 +182,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = &dev->subdevices[0]; diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 5c1548b385f4..7d161d6739ae 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -124,7 +124,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct aio_iiro_16_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 3afebb24b26b..d7d056e20c02 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1273,7 +1273,7 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase, devpriv->intr_sd = -1; dev->iobase = iobase; dev->board_name = thisboard->name; - ret = alloc_subdevices(dev, layout->n_subdevs); + ret = comedi_alloc_subdevices(dev, layout->n_subdevs); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 9cf514e54a58..522e1c0c385e 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -455,7 +455,7 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, dev->board_name = thisboard->name; dev->iobase = iobase; - ret = alloc_subdevices(dev, 2); + ret = comedi_alloc_subdevices(dev, 2); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 7020907f1af7..cfb69fa9c89d 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -227,7 +227,7 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) dev->board_name = thisboard->name; dev->iobase = iobase; - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index a1e23bafabea..8d33aeab53b1 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1380,7 +1380,7 @@ static int pci224_attach_common(struct comedi_device *dev, dev->iobase + PCI224_DACCON); /* Allocate subdevices. There is only one! */ - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 2a43df5d966e..e6598cafb39a 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2843,7 +2843,7 @@ static int pci230_attach_common(struct comedi_device *dev, * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index fb9951a746a6..72b000fad609 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -433,7 +433,8 @@ static int c6xdigio_attach(struct comedi_device *dev, dev->iobase = iobase; dev->board_name = "c6xdigio"; - result = alloc_subdevices(dev, 2); /* 3 with encoder_init write */ + /* 3 subdevices with encoder_init write */ + result = comedi_alloc_subdevices(dev, 2); if (result < 0) return result; diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 35159235a1b6..9aa11c15497f 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -195,7 +195,7 @@ static int das16cs_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct das16cs_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 074feeef829b..435f3aaedf88 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -617,7 +617,7 @@ found: /* * Allocate the subdevice structures. */ - if (alloc_subdevices(dev, 7) < 0) + if (comedi_alloc_subdevices(dev, 7) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 5bcadcb00c99..6b2f153980a9 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1345,7 +1345,7 @@ static int setup_subdevices(struct comedi_device *dev) void __iomem *dio_8255_iobase; int i; - if (alloc_subdevices(dev, 10) < 0) + if (comedi_alloc_subdevices(dev, 10) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index dc4cf0b030ef..4ab3584365e2 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -336,7 +336,7 @@ found: /* * Allocate the subdevice structures. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 58d5a3d257bd..56c1d09188aa 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -181,7 +181,7 @@ found: * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, thisboard->n_8255) < 0) + if (comedi_alloc_subdevices(dev, thisboard->n_8255) < 0) return -ENOMEM; for (i = 0; i < thisboard->n_8255; i++) { diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index a06b67a0b36d..6acb3199e6f3 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -273,7 +273,7 @@ found: * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index bec250bf15bb..abb6008da4df 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -240,7 +240,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 29412de06c31..d56eec48e4c8 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -362,7 +362,7 @@ static int bonding_attach(struct comedi_device *dev, * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index bff5dcd76107..c9a725fc61f2 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -315,7 +315,7 @@ static int parport_attach(struct comedi_device *dev, } dev->board_name = "parport"; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; ret = alloc_private(dev, sizeof(struct parport_private)); diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 9f3c3d5d02a4..cd43c0d7df38 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -448,7 +448,7 @@ static int waveform_attach(struct comedi_device *dev, devpriv->usec_period = period; dev->n_subdevices = 2; - if (alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 2cd7407adbea..a5bad1bd6dcd 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -115,7 +115,7 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct contec_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; for_each_pci_dev(pcidev) { diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index d84794ca4380..dbd0472bc7e2 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -772,7 +772,7 @@ static int daqboard2000_attach(struct comedi_device *dev, if (!devpriv->plx || !devpriv->daq) return -ENOMEM; - result = alloc_subdevices(dev, 3); + result = comedi_alloc_subdevices(dev, 3); if (result < 0) goto out; diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index f99f72b9cdf3..1dea21a33a27 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -834,7 +834,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) dev->board_name = thisboard->name; - ret = alloc_subdevices(dev, 6); + ret = comedi_alloc_subdevices(dev, 6); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 61705366dd40..6a8a7eb1ae9c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1264,7 +1264,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } devpriv->timer_mode = timer_mode ? 1 : 0; - ret = alloc_subdevices(dev, 5); + ret = comedi_alloc_subdevices(dev, 5); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index e468ff14aa52..eafd6b59a483 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -646,7 +646,7 @@ static int das16m1_attach(struct comedi_device *dev, return -EINVAL; } - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 079fb06de215..12d736a6e38d 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1644,7 +1644,7 @@ static int das1800_attach(struct comedi_device *dev, return -ENOMEM; } - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 881f392d1dba..2039b6c11590 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -307,7 +307,7 @@ static int das6402_attach(struct comedi_device *dev, if (ret < 0) return ret; - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 4e33b2a28d97..6263f532e5da 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -510,7 +510,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 5be99b5d22e4..40d7befec5ea 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -375,7 +375,7 @@ static int dmm32at_attach(struct comedi_device *dev, * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 625bd617a8e9..35ce076237a4 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -628,7 +628,7 @@ havetype: n_ai_chans = probe_number_of_ai_chans(dev); printk(" (ai channels = %d)", n_ai_chans); - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) goto out; diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 727da9e19206..6ff610d1b0f9 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -465,7 +465,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) } #endif - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index fa4ade61be5f..876d5cbdbe4a 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -338,7 +338,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif } - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index bbab712be4b9..33ad1fa90762 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -177,7 +177,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->board_name = "dt2815"; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; if (alloc_private(dev, sizeof(struct dt2815_private)) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 1ee10e7bf1d2..665db07aeb84 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -137,7 +137,7 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->board_name = "dt2817"; - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index eefda3c064d3..f11d1fdfcae2 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1268,7 +1268,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - ret = alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 3); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index af0202474127..10415b218b5c 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -882,7 +882,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->irq = devpriv->pci_dev->irq; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 22cda5c76ce4..56af2f28f98d 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -1036,7 +1036,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->serial = it->options[0]; /* Allocate subdevices */ - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; /* digital input subdevice */ diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 367a7c88a0fd..6f6fb527d543 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -329,7 +329,7 @@ found: devpriv->BADR4 = pci_resource_start(pcidev, 4); devpriv->BADR5 = pci_resource_start(pcidev, 5); - if (alloc_subdevices(dev, 4) < 0) { + if (comedi_alloc_subdevices(dev, 4) < 0) { printk(KERN_ERR "comedi: dyna_pci10xx: " "failed allocating subdevices\n"); mutex_unlock(&start_stop_sem); diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index d23814450b40..7218a9b2cda9 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -131,7 +131,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_DEBUG "malloc ok\n"); #endif - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; /* diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index fe1fd2f75f0d..b103cfbf3274 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -431,7 +431,7 @@ static int setup_subdevices(struct comedi_device *dev) { struct comedi_subdevice *s; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 1f254f480a66..06c66afc6aa1 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -903,7 +903,7 @@ static int icp_multi_attach(struct comedi_device *dev, if (this_board->n_ctrs) n_subdevices++; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 6f6947602398..9c1165791078 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -202,7 +202,7 @@ static int pci20xxx_attach(struct comedi_device *dev, struct comedi_subdevice *s; union pci20xxx_subdev_private *sdp; - ret = alloc_subdevices(dev, 1 + PCI20000_MODULES); + ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index e8dfc367aa8d..182643bed561 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -826,7 +826,7 @@ static int jr3_pci_attach(struct comedi_device *dev, if (!devpriv->iobase) return -ENOMEM; - result = alloc_subdevices(dev, devpriv->n_channels); + result = comedi_alloc_subdevices(dev, devpriv->n_channels); if (result < 0) goto out; diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 9f92420dd826..bcb1eb49a1f7 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -190,7 +190,7 @@ found: dev->iobase = io_base; /* allocate the subdevice structures */ - error = alloc_subdevices(dev, 1); + error = comedi_alloc_subdevices(dev, 1); if (error < 0) return error; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 09890b8c586c..39100ddddef8 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2195,7 +2195,7 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) * convenient macro defined in comedidev.h. It relies on * n_subdevices being set correctly. */ - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; /*========================================================================= diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index fcadb0fcd1d0..231b29413eaa 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -762,7 +762,7 @@ found: me_reset(dev); /* device driver capabilities */ - error = alloc_subdevices(dev, 3); + error = comedi_alloc_subdevices(dev, 3); if (error < 0) return error; diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 4304e864a4d4..48ba6b9f9430 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -349,7 +349,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Subdevices structures */ - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c index 364470e4458f..13110510d7fe 100644 --- a/drivers/staging/comedi/drivers/mpc8260cpm.c +++ b/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -131,7 +131,7 @@ static int mpc8260cpm_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; for (i = 0; i < 4; i++) { diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index e951e73d66f5..00d497c270ae 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -255,7 +255,7 @@ static int multiq3_attach(struct comedi_device *dev, else printk(KERN_WARNING "comedi%d: no irq\n", dev->minor); dev->board_name = "multiq3"; - result = alloc_subdevices(dev, 5); + result = comedi_alloc_subdevices(dev, 5); if (result < 0) return result; diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index b02aa0efcd86..89fee6fdcf61 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -397,7 +397,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "comedi board: %s, ID=0x%02x\n", dev->board_name, readb(devpriv->mite->daq_io_addr + ID_Register)); - ret = alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 3); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 0d27a9323bc0..a49dceac65bc 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -678,7 +678,7 @@ static int ni_65xx_attach(struct comedi_device *dev, printk(KERN_INFO " ID=0x%02x", readb(private(dev)->mite->daq_io_addr + ID_Register)); - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 8c40730e296a..5827debd3366 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1095,7 +1095,7 @@ static int ni_660x_attach(struct comedi_device *dev, dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS; - if (alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index a9cf94fd0c30..45a03e64549a 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -202,7 +202,7 @@ static int ni_670x_attach(struct comedi_device *dev, dev->irq = mite_irq(devpriv->mite); printk(KERN_INFO " %s", dev->board_name); - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index ae896a094150..9d1a0f745bf8 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -826,7 +826,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = a2150_boards + a2150_probe(dev); dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index bfe7fb79880d..03a4d736b454 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -356,7 +356,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct atao_private)) < 0) return -ENOMEM; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index a0890ee202f4..37ff6fc86157 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -709,7 +709,7 @@ static int atmio16d_attach(struct comedi_device *dev, dev->board_name = board->name; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 75764e8d27eb..8860207e88d7 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -409,7 +409,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; /* DAQCard-700 dio */ diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 493a22788637..36c0c62382ed 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -158,7 +158,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; /* 8255 dio */ diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 1d739b26e678..a92570f5a7c5 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -622,7 +622,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 5) < 0) + if (comedi_alloc_subdevices(dev, 5) < 0) return -ENOMEM; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index fd232bc5f873..4261e929869f 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4412,7 +4412,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it) return -EINVAL; } - if (alloc_subdevices(dev, NI_NUM_SUBDEVICES) < 0) + if (comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES) < 0) return -ENOMEM; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 37b700830e21..77ef312f657e 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1248,7 +1248,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) else n_subdevices = 1; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index e943b52d04a8..35b95105a749 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -518,7 +518,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->irq = irq; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 4136a03a5125..698c9004c74e 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -156,7 +156,7 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) || (it->options[1] == 96))) n_subdevices = 4; /* PCL-724 in 96 DIO configuration */ - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index 83a6fa53dddd..d7ba336ce031 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -63,7 +63,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->irq = 0; - if (alloc_subdevices(dev, 2) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index e9449bb2ba00..e756a3033767 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -292,7 +292,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk("\n"); - ret = alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 3); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 02a4386e1031..e258bcebf198 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -85,7 +85,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->irq = 0; - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 28780ede1ee5..128f5b644878 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1382,7 +1382,7 @@ no_dma: if (board->n_dochan > 0) n_subdevices++; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) { free_resources(dev); return ret; diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 845039cd6207..37cedbc47a43 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -1194,7 +1194,7 @@ no_dma: subdevs[3] = COMEDI_SUBD_DO; */ - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 6c84b29a8dad..a4c2870562fb 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1778,7 +1778,7 @@ no_rtc: no_dma: - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 9eee708e8442..d755b406a6f1 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -258,7 +258,7 @@ static int pcm3724_attach(struct comedi_device *dev, n_subdevices = board->numofports; - ret = alloc_subdevices(dev, n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index f8d1c644daf8..48a21bd679fd 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -71,7 +71,7 @@ static int pcm3730_attach(struct comedi_device *dev, dev->iobase = dev->iobase; dev->irq = 0; - if (alloc_subdevices(dev, 6) < 0) + if (comedi_alloc_subdevices(dev, 6) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 2ec0b2e63c35..00b0f2a6894c 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -117,7 +117,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_CONT "\n"); dev->iobase = iobase; - ret = alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index f49c66afe5fc..3645e9ee8807 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -197,7 +197,7 @@ static int pcmda12_attach(struct comedi_device *dev, * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the * 96-channel version of the board. */ - if (alloc_subdevices(dev, 1) < 0) { + if (comedi_alloc_subdevices(dev, 1) < 0) { printk(KERN_ERR "cannot allocate subdevice data structures\n"); return -ENOMEM; } diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index c4482ae9d08b..67fdac5b81d6 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1077,7 +1077,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO) */ - if (alloc_subdevices(dev, n_subdevs) < 0) { + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) { printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n", dev->minor); return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index b1a9bed38551..ce5068e3b46e 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -807,7 +807,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the * 96-channel version of the board. */ - if (alloc_subdevices(dev, n_subdevs) < 0) { + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) { dev_dbg(dev->hw_dev, "cannot allocate subdevice data structures\n"); return -ENOMEM; } diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 95e348fa89c8..1e954f9c4165 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -160,7 +160,7 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->iobase = iobase; - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 2f130b3095e9..38a13ba38e18 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -871,7 +871,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = local->link->resource[0]->start; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 84b28b6b99d6..7d248a7685b2 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -2003,7 +2003,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 4) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 04a23687ae3e..a80f6302375b 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -348,7 +348,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = board->name; - ret = alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 4); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 09da5c21858c..1aacf3f6e3f5 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -103,7 +103,7 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = "rti802"; - if (alloc_subdevices(dev, 1) < 0 + if (comedi_alloc_subdevices(dev, 1) < 0 || alloc_private(dev, sizeof(struct rti802_private))) { return -ENOMEM; } diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 3c8e9799824e..17d581b8ac6f 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -779,7 +779,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) * convenient macro defined in comedidev.h. */ dev->n_subdevices = 4; - if (alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index d6dc3381205a..f2eeca51ebfa 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -595,7 +595,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = s626_boards; dev->board_name = thisboard->name; - if (alloc_subdevices(dev, 6) < 0) + if (comedi_alloc_subdevices(dev, 6) < 0) return -ENOMEM; dev->iobase = (unsigned long)devpriv->base_addr; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index c25808c05251..dc41c04fae4f 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -792,7 +792,7 @@ static int serial2002_attach(struct comedi_device *dev, dev_dbg(dev->hw_dev, "/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed); - if (alloc_subdevices(dev, 5) < 0) + if (comedi_alloc_subdevices(dev, 5) < 0) return -ENOMEM; /* digital input subdevice */ diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 7d13ffa7f4f9..16947c8b8803 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -237,7 +237,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 3) < 0) + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index de580958e32a..5eaef8434e09 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -200,7 +200,7 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Allocate the subdevice structures. alloc_subdevice() is a */ /* convenient macro defined in comedidev.h. */ - if (alloc_subdevices(dev, 1) < 0) + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index d5f1f22aa708..170bc48cfd1c 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -468,7 +468,7 @@ static int unioxx5_attach(struct comedi_device *dev, return -1; } - if (alloc_subdevices(dev, n_subd) < 0) { + if (comedi_alloc_subdevices(dev, n_subd) < 0) { printk(KERN_ERR "out of memory\n"); return -ENOMEM; } diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 13d9fd3efcfd..ca8b3e121ff0 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2645,7 +2645,7 @@ static int usbdux_attach_common(struct comedi_device *dev, } /* allocate space for the subdevices */ - ret = alloc_subdevices(dev, dev->n_subdevices); + ret = comedi_alloc_subdevices(dev, dev->n_subdevices); if (ret < 0) { dev_err(&udev->interface->dev, "comedi%d: error alloc space for subdev\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 7b1d21a6fc53..b2f7350c429f 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1675,7 +1675,7 @@ static int usbduxfast_attach(struct comedi_device *dev, dev->n_subdevices = N_SUBDEVICES; /* allocate space for the subdevices */ - ret = alloc_subdevices(dev, N_SUBDEVICES); + ret = comedi_alloc_subdevices(dev, N_SUBDEVICES); if (ret < 0) { printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for " "subdev\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 441ccef4c110..00faf4ad6ffb 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2690,7 +2690,7 @@ static int usbduxsigma_attach(struct comedi_device *dev, } /* allocate space for the subdevices */ - ret = alloc_subdevices(dev, dev->n_subdevices); + ret = comedi_alloc_subdevices(dev, dev->n_subdevices); if (ret < 0) { dev_err(&udev->interface->dev, "comedi%d: no space for subdev\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index baee8d767636..5a3e33d83c84 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -1159,7 +1159,7 @@ static int vmk80xx_attach(struct comedi_device *cdev, else n_subd = 6; - if (alloc_subdevices(cdev, n_subd) < 0) { + if (comedi_alloc_subdevices(cdev, n_subd) < 0) { up(&dev->limit_sem); mutex_unlock(&glb_mutex); return -ENOMEM; -- GitLab From c810a399798022d545191e2daaca0368623c15d3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 5 Jun 2012 16:40:10 +0530 Subject: [PATCH 0564/5711] staging: Android: Fix some checkpatch warnings Warnings reported by checkpatch.pl have been fixed. Cc: Brian Swetland Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 14 ++++++++------ drivers/staging/android/logger.c | 10 ++++++---- drivers/staging/android/ram_console.c | 4 +++- drivers/staging/android/timed_output.c | 4 +++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index e84dbecd0991..69cf2db1d69c 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -16,6 +16,8 @@ ** GNU General Public License for more details. */ +#define pr_fmt(fmt) "ashmem: " fmt + #include #include #include @@ -707,7 +709,7 @@ static int __init ashmem_init(void) sizeof(struct ashmem_area), 0, 0, NULL); if (unlikely(!ashmem_area_cachep)) { - printk(KERN_ERR "ashmem: failed to create slab cache\n"); + pr_err("failed to create slab cache\n"); return -ENOMEM; } @@ -715,19 +717,19 @@ static int __init ashmem_init(void) sizeof(struct ashmem_range), 0, 0, NULL); if (unlikely(!ashmem_range_cachep)) { - printk(KERN_ERR "ashmem: failed to create slab cache\n"); + pr_err("failed to create slab cache\n"); return -ENOMEM; } ret = misc_register(&ashmem_misc); if (unlikely(ret)) { - printk(KERN_ERR "ashmem: failed to register misc device!\n"); + pr_err("failed to register misc device!\n"); return ret; } register_shrinker(&ashmem_shrinker); - printk(KERN_INFO "ashmem: initialized\n"); + pr_info("initialized\n"); return 0; } @@ -740,12 +742,12 @@ static void __exit ashmem_exit(void) ret = misc_deregister(&ashmem_misc); if (unlikely(ret)) - printk(KERN_ERR "ashmem: failed to unregister misc device!\n"); + pr_err("failed to unregister misc device!\n"); kmem_cache_destroy(ashmem_range_cachep); kmem_cache_destroy(ashmem_area_cachep); - printk(KERN_INFO "ashmem: unloaded\n"); + pr_info("unloaded\n"); } module_init(ashmem_init); diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index b2e71c6fd175..f7b8237d5be7 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -17,6 +17,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "logger: " fmt + #include #include #include @@ -621,13 +623,13 @@ static int __init create_log(char *log_name, int size) /* finally, initialize the misc device for this log */ ret = misc_register(&log->misc); if (unlikely(ret)) { - printk(KERN_ERR "logger: failed to register misc " - "device for log '%s'!\n", log->misc.name); + pr_err("failed to register misc device for log '%s'!\n", + log->misc.name); goto out_free_log; } - printk(KERN_INFO "logger: created %luK log '%s'\n", - (unsigned long) log->size >> 10, log->misc.name); + pr_info("created %luK log '%s'\n", + (unsigned long) log->size >> 10, log->misc.name); return 0; diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c index 82323bb1d1a3..7add022b1c22 100644 --- a/drivers/staging/android/ram_console.c +++ b/drivers/staging/android/ram_console.c @@ -13,6 +13,8 @@ * */ +#define pr_fmt(fmt) "ram_console: " fmt + #include #include #include @@ -162,7 +164,7 @@ static int __init ram_console_late_init(void) entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { - printk(KERN_ERR "ram_console: failed to create proc entry\n"); + pr_err("failed to create proc entry\n"); persistent_ram_free_old(prz); return 0; } diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c index 38d930cadad3..ec9e2ae2de0d 100644 --- a/drivers/staging/android/timed_output.c +++ b/drivers/staging/android/timed_output.c @@ -14,6 +14,8 @@ * */ +#define pr_fmt(fmt) "timed_output: " fmt + #include #include #include @@ -90,7 +92,7 @@ int timed_output_dev_register(struct timed_output_dev *tdev) err_create_file: device_destroy(timed_output_class, MKDEV(0, tdev->index)); - printk(KERN_ERR "timed_output: Failed to register driver %s\n", + pr_err("failed to register driver %s\n", tdev->name); return ret; -- GitLab From 592314e9e1c0057bdb75ff00cbd1c51aa06c65e7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 5 Jun 2012 15:05:13 +0530 Subject: [PATCH 0565/5711] staging: Android: Fix NULL pointer related warning in alarm-dev.c file Fixes the following sparse warning: drivers/staging/android/alarm-dev.c:259:35: warning: Using plain integer as NULL pointer Cc: Brian Swetland Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 32614d611283..c2d87c546e99 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -255,7 +255,7 @@ static int alarm_release(struct inode *inode, struct file *file) unsigned long flags; spin_lock_irqsave(&alarm_slock, flags); - if (file->private_data != 0) { + if (file->private_data) { for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { uint32_t alarm_type_mask = 1U << i; if (alarm_enabled & alarm_type_mask) { -- GitLab From 9b990de76ced807b2d92a601fb7f03863b632c58 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Jun 2012 15:55:56 +0200 Subject: [PATCH 0566/5711] agp/intel-gtt: remove dead code This is a leftover from the conversion of the i81x fake agp driver over to the new intel-gtt code layoute. Reviewed-by: Jani Nikula Signed-Off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 1237e7575c3f..53c4c7fca10b 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1556,9 +1556,6 @@ int intel_gmch_probe(struct pci_dev *pdev, pci_set_consistent_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)); - /*if (bridge->driver == &intel_810_driver) - return 1;*/ - if (intel_gtt_init() != 0) return 0; -- GitLab From dd2757f8b557ab2030154896eac9b2285557dda6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Jun 2012 15:55:57 +0200 Subject: [PATCH 0567/5711] drm/i915: stop using dev->agp->base For that to work we need to export the base address of the gtt mmio window from intel-gtt. Also replace all other uses of dev->agp by values we already have at hand. Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 5 ++--- drivers/gpu/drm/i915/i915_dma.c | 21 +++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_debug.c | 3 ++- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_fb.c | 4 +++- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++++-- include/drm/intel-gtt.h | 2 ++ 9 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 53c4c7fca10b..2aab0a03ee42 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -66,7 +66,6 @@ static struct _intel_private { struct pci_dev *bridge_dev; u8 __iomem *registers; phys_addr_t gtt_bus_addr; - phys_addr_t gma_bus_addr; u32 PGETBL_save; u32 __iomem *gtt; /* I915G */ bool clear_fake_agp; /* on first access via agp, fill with scratch */ @@ -779,7 +778,7 @@ static bool intel_enable_gtt(void) pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &gma_addr); - intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); + intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); if (INTEL_GTT_GEN >= 6) return true; @@ -860,7 +859,7 @@ static int intel_fake_agp_configure(void) return -EIO; intel_private.clear_fake_agp = true; - agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; + agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; return 0; } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 97a5a5857f5b..c639d431ad66 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1085,8 +1085,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); - dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr, - 4096); + dev_priv->dri1.gfx_hws_cpu_addr = + ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096); if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { i915_dma_cleanup(dev); ring->status_page.gfx_addr = 0; @@ -1482,15 +1482,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; dev_priv->mm.gtt_mapping = - io_mapping_create_wc(dev->agp->base, aperture_size); + io_mapping_create_wc(dev_priv->mm.gtt_base_addr, + aperture_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; goto out_rmmap; } - i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size); + i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, + aperture_size); /* The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -1602,8 +1605,9 @@ out_gem_unload: destroy_workqueue(dev_priv->wq); out_mtrrfree: if (dev_priv->mm.gtt_mtrr >= 0) { - mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, - dev->agp->agp_info.aper_size * 1024 * 1024); + mtrr_del(dev_priv->mm.gtt_mtrr, + dev_priv->mm.gtt_base_addr, + aperture_size); dev_priv->mm.gtt_mtrr = -1; } io_mapping_free(dev_priv->mm.gtt_mapping); @@ -1640,8 +1644,9 @@ int i915_driver_unload(struct drm_device *dev) io_mapping_free(dev_priv->mm.gtt_mapping); if (dev_priv->mm.gtt_mtrr >= 0) { - mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, - dev->agp->agp_info.aper_size * 1024 * 1024); + mtrr_del(dev_priv->mm.gtt_mtrr, + dev_priv->mm.gtt_base_addr, + dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE); dev_priv->mm.gtt_mtrr = -1; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccabadd2b6c3..ae4129b3cb3e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -651,6 +651,7 @@ typedef struct drm_i915_private { unsigned long gtt_end; struct io_mapping *gtt_mapping; + phys_addr_t gtt_base_addr; int gtt_mtrr; /** PPGTT used for aliasing the PPGTT with the GTT */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index deaa0d4bb456..108e4c2b5ffa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1122,7 +1122,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) obj->fault_mappable = true; - pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) + + pfn = ((dev_priv->mm.gtt_base_addr + obj->gtt_offset) >> PAGE_SHIFT) + page_offset; /* Finally, remap it using the new GTT offset */ diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index a4f6aaabca99..bddf7bed183f 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -132,7 +132,8 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) __func__, obj, obj->gtt_offset, handle, obj->size / 1024); - gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size); + gtt_mapping = ioremap(dev_priv->mm.gtt_base_addr + obj->gtt_offset, + obj->base.size); if (gtt_mapping == NULL) { DRM_ERROR("failed to map GTT space\n"); return; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bad36e0b8045..174549df5929 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6954,7 +6954,7 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; } - dev->mode_config.fb_base = dev->agp->base; + dev->mode_config.fb_base = dev_priv->mm.gtt_base_addr; DRM_DEBUG_KMS("%d display pipe%s available.\n", dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index bf8690720a0c..e9f8338bd802 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -140,7 +140,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; - info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); + info->screen_base = + ioremap_wc(dev_priv->mm.gtt_base_addr + obj->gtt_offset, + size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 89a5e7f89d7a..14025ab9d4ca 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -968,6 +968,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, struct intel_ring_buffer *ring) { struct drm_i915_gem_object *obj; + struct drm_i915_private *dev_priv = dev->dev_private; int ret; ring->dev = dev; @@ -997,8 +998,9 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto err_unref; - ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, - ring->size); + ring->virtual_start = + ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, + ring->size); if (ring->virtual_start == NULL) { DRM_ERROR("Failed to map ringbuffer.\n"); ret = -EINVAL; diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 923afb5dcf0c..8048c005c6f6 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -19,6 +19,8 @@ const struct intel_gtt { dma_addr_t scratch_page_dma; /* for ppgtt PDE access */ u32 __iomem *gtt; + /* needed for ioremap in drm/i915 */ + phys_addr_t gma_bus_addr; } *intel_gtt_get(void); void intel_gtt_chipset_flush(void); -- GitLab From 7e8f6306fe155d6fc3fe99d666be95b4ed24427d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Jun 2012 15:55:58 +0200 Subject: [PATCH 0568/5711] agp/intel-gtt: don't require the agp bridge on setup We only need it to fake the agp interface and don't actually use it in the driver anywhere. Hence conditionalize that. This is just a prep patch to eventually disable the fake agp driver on gen6+. Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 2aab0a03ee42..5e6c89e1d5eb 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1539,9 +1539,11 @@ int intel_gmch_probe(struct pci_dev *pdev, if (!intel_private.driver) return 0; - bridge->driver = &intel_fake_agp_driver; - bridge->dev_private_data = &intel_private; - bridge->dev = pdev; + if (bridge) { + bridge->driver = &intel_fake_agp_driver; + bridge->dev_private_data = &intel_private; + bridge->dev = pdev; + } intel_private.bridge_dev = pci_dev_get(pdev); -- GitLab From 14be93ddff61eb196382aeaa3ac86f4db844aeb0 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 8 Jun 2012 15:55:40 +0200 Subject: [PATCH 0569/5711] drm/i915 + agp/intel-gtt: prep work for direct setup To be able to directly set up the intel-gtt code from drm/i915 and avoid setting up the fake-agp driver we need to prepare a few things: - pass both the bridge and gpu pci_dev to the probe function and add code to handle the gpu pdev both being present (for drm/i915) and not present (fake agp). - add refcounting to the remove function so that unloading drm/i915 doesn't kill the fake agp driver v2: Fix up the cleanup and refcount, noticed by Jani Nikula. Reviewed-by: Jani Nikula Signed-Off-by: Daniel Vetter --- drivers/char/agp/intel-agp.c | 5 ++-- drivers/char/agp/intel-agp.h | 3 --- drivers/char/agp/intel-gtt.c | 46 ++++++++++++++++++++++++++------- drivers/gpu/drm/i915/i915_dma.c | 13 ++++++++-- include/drm/intel-gtt.h | 4 +++ 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 764f70c5e690..c98c5689bb0b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -12,6 +12,7 @@ #include #include "agp.h" #include "intel-agp.h" +#include int intel_agp_enabled; EXPORT_SYMBOL(intel_agp_enabled); @@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->capndx = cap_ptr; - if (intel_gmch_probe(pdev, bridge)) + if (intel_gmch_probe(pdev, NULL, bridge)) goto found_gmch; for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { @@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) agp_remove_bridge(bridge); - intel_gmch_remove(pdev); + intel_gmch_remove(); agp_put_bridge(bridge); } diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index c0091753a0d1..cf2e764b1760 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -250,7 +250,4 @@ #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 -int intel_gmch_probe(struct pci_dev *pdev, - struct agp_bridge_data *bridge); -void intel_gmch_remove(struct pci_dev *pdev); #endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 5e6c89e1d5eb..cea9f9905c7d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -75,6 +75,7 @@ static struct _intel_private { struct resource ifp_resource; int resource_valid; struct page *scratch_page; + int refcount; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -1522,14 +1523,32 @@ static int find_gmch(u16 device) return 1; } -int intel_gmch_probe(struct pci_dev *pdev, - struct agp_bridge_data *bridge) +int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, + struct agp_bridge_data *bridge) { int i, mask; - intel_private.driver = NULL; + + /* + * Can be called from the fake agp driver but also directly from + * drm/i915.ko. Hence we need to check whether everything is set up + * already. + */ + if (intel_private.driver) { + intel_private.refcount++; + return 1; + } for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { - if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { + if (gpu_pdev) { + if (gpu_pdev->device == + intel_gtt_chipsets[i].gmch_chip_id) { + intel_private.pcidev = pci_dev_get(gpu_pdev); + intel_private.driver = + intel_gtt_chipsets[i].gtt_driver; + + break; + } + } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { intel_private.driver = intel_gtt_chipsets[i].gtt_driver; break; @@ -1539,15 +1558,17 @@ int intel_gmch_probe(struct pci_dev *pdev, if (!intel_private.driver) return 0; + intel_private.refcount++; + if (bridge) { bridge->driver = &intel_fake_agp_driver; bridge->dev_private_data = &intel_private; - bridge->dev = pdev; + bridge->dev = bridge_pdev; } - intel_private.bridge_dev = pci_dev_get(pdev); + intel_private.bridge_dev = pci_dev_get(bridge_pdev); - dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); + dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); mask = intel_private.driver->dma_mask_size; if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) @@ -1557,8 +1578,11 @@ int intel_gmch_probe(struct pci_dev *pdev, pci_set_consistent_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)); - if (intel_gtt_init() != 0) + if (intel_gtt_init() != 0) { + intel_gmch_remove(); + return 0; + } return 1; } @@ -1577,12 +1601,16 @@ void intel_gtt_chipset_flush(void) } EXPORT_SYMBOL(intel_gtt_chipset_flush); -void intel_gmch_remove(struct pci_dev *pdev) +void intel_gmch_remove(void) { + if (--intel_private.refcount) + return; + if (intel_private.pcidev) pci_dev_put(intel_private.pcidev); if (intel_private.bridge_dev) pci_dev_put(intel_private.bridge_dev); + intel_private.driver = NULL; } EXPORT_SYMBOL(intel_gmch_remove); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c639d431ad66..cf512e7178b4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1474,11 +1474,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto put_bridge; } + ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); + if (!ret) { + DRM_ERROR("failed to set up gmch\n"); + ret = -EIO; + goto out_rmmap; + } + dev_priv->mm.gtt = intel_gtt_get(); if (!dev_priv->mm.gtt) { DRM_ERROR("Failed to initialize GTT\n"); ret = -ENODEV; - goto out_rmmap; + goto put_gmch; } aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; @@ -1489,7 +1496,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) aperture_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; - goto out_rmmap; + goto put_gmch; } i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, @@ -1611,6 +1618,8 @@ out_mtrrfree: dev_priv->mm.gtt_mtrr = -1; } io_mapping_free(dev_priv->mm.gtt_mapping); +put_gmch: + intel_gmch_remove(); out_rmmap: pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 8048c005c6f6..84ebd7188fc6 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -23,6 +23,10 @@ const struct intel_gtt { phys_addr_t gma_bus_addr; } *intel_gtt_get(void); +int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, + struct agp_bridge_data *bridge); +void intel_gmch_remove(void); + void intel_gtt_chipset_flush(void); void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); -- GitLab From 32e3cd6ecd7ae9b79605b5f2eb993186a509c239 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Jun 2012 15:56:02 +0200 Subject: [PATCH 0570/5711] agp/intel-gtt: move gart base addres setup We need this thing much earlier, and it doesn't make sense in the hw enabling function intel_enable_gtt - this does not change over a suspend/resume cycle ... Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index cea9f9905c7d..4387e69f8b11 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -648,6 +648,7 @@ static void intel_gtt_cleanup(void) static int intel_gtt_init(void) { + u32 gma_addr; u32 gtt_map_size; int ret; @@ -694,6 +695,15 @@ static int intel_gtt_init(void) return ret; } + if (INTEL_GTT_GEN <= 2) + pci_read_config_dword(intel_private.pcidev, I810_GMADDR, + &gma_addr); + else + pci_read_config_dword(intel_private.pcidev, I915_GMADDR, + &gma_addr); + + intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); + return 0; } @@ -769,18 +779,8 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, static bool intel_enable_gtt(void) { - u32 gma_addr; u8 __iomem *reg; - if (INTEL_GTT_GEN <= 2) - pci_read_config_dword(intel_private.pcidev, I810_GMADDR, - &gma_addr); - else - pci_read_config_dword(intel_private.pcidev, I915_GMADDR, - &gma_addr); - - intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); - if (INTEL_GTT_GEN >= 6) return true; -- GitLab From 8ecd1a6615f0d9de6759aafe229bc1cc4ee99c7b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Jun 2012 15:56:03 +0200 Subject: [PATCH 0571/5711] drm/i915: call intel_enable_gtt When drm/i915 is in control of the gtt, we need to call the enable function at all the relevant places ourselves. Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 3 +++ include/drm/intel-gtt.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 4387e69f8b11..419a25eeefd8 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -777,7 +777,7 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, writel(addr | pte_flags, intel_private.gtt + entry); } -static bool intel_enable_gtt(void) +bool intel_enable_gtt(void) { u8 __iomem *reg; @@ -823,6 +823,7 @@ static bool intel_enable_gtt(void) return true; } +EXPORT_SYMBOL(intel_enable_gtt); static int i830_setup(void) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 108e4c2b5ffa..2884b0865473 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3689,6 +3689,9 @@ i915_gem_init_hw(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; int ret; + if (!intel_enable_gtt()) + return -EIO; + i915_gem_l3_remap(dev); i915_gem_init_swizzling(dev); diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 84ebd7188fc6..8e29d551bb3c 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -27,6 +27,8 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, struct agp_bridge_data *bridge); void intel_gmch_remove(void); +bool intel_enable_gtt(void); + void intel_gtt_chipset_flush(void); void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); -- GitLab From 0c16ae762990660c4dfd7515e3d46b4249f535f0 Mon Sep 17 00:00:00 2001 From: Ben Chan Date: Tue, 12 Jun 2012 11:23:32 -0700 Subject: [PATCH 0572/5711] staging: gdm72xx: Simplify spinlock fix for gdm_usb_send_complete This patch simplifies the previous patch (commit dd13c86b0dae86efdde98119ffd7348e80719ade) for fixing the spinlock recursion issue on several call sites of gdm_usb_send_complete. Signed-off-by: Ben Chan Cc: Sage Ahn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/gdm_usb.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index 646e0ace91ec..89268c785b25 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -270,21 +270,17 @@ static void release_usb(struct usbwm_dev *udev) } } -static void gdm_usb_send_complete_impl(struct urb *urb, bool need_lock) +static void __gdm_usb_send_complete(struct urb *urb) { struct usb_tx *t = urb->context; struct tx_cxt *tx = t->tx_cxt; u8 *pkt = t->buf; u16 cmd_evt; - unsigned long flags; /* Completion by usb_unlink_urb */ if (urb->status == -ECONNRESET) return; - if (need_lock) - spin_lock_irqsave(&tx->lock, flags); - if (t->callback) t->callback(t->cb_data); @@ -296,19 +292,17 @@ static void gdm_usb_send_complete_impl(struct urb *urb, bool need_lock) put_tx_struct(tx, t); else free_tx_struct(t); - - if (need_lock) - spin_unlock_irqrestore(&tx->lock, flags); } static void gdm_usb_send_complete(struct urb *urb) { - gdm_usb_send_complete_impl(urb, true); -} + struct usb_tx *t = urb->context; + struct tx_cxt *tx = t->tx_cxt; + unsigned long flags; -static void gdm_usb_send_complete_no_lock(struct urb *urb) -{ - gdm_usb_send_complete_impl(urb, false); + spin_lock_irqsave(&tx->lock, flags); + __gdm_usb_send_complete(urb); + spin_unlock_irqrestore(&tx->lock, flags); } static int gdm_usb_send(void *priv_dev, void *data, int len, @@ -423,7 +417,7 @@ out: send_fail: t->callback = NULL; - gdm_usb_send_complete_no_lock(t->urb); + __gdm_usb_send_complete(t->urb); spin_unlock_irqrestore(&tx->lock, flags); return ret; } @@ -552,7 +546,7 @@ static void do_pm_control(struct work_struct *work) if (ret) { t->callback = NULL; - gdm_usb_send_complete_no_lock(t->urb); + __gdm_usb_send_complete(t->urb); } } } @@ -754,7 +748,7 @@ static int k_mode_thread(void *arg) if (ret) { t->callback = NULL; - gdm_usb_send_complete_no_lock(t->urb); + __gdm_usb_send_complete(t->urb); } } -- GitLab From 8b9ba6e5efc3213f384cda155861a4f7ae903365 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:57:27 -0700 Subject: [PATCH 0573/5711] staging: comedi: change type of num_subdevices parameter to comedi_alloc_subdevices The n_subdevices variable of struct comedi_device is an int type. Change the type of the comedi_alloc_subdevices 'num_subdevices' from an unsigned int to an int to match it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 2 +- drivers/staging/comedi/drivers.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index bb98f82141a1..e0f3915b0f63 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -292,7 +292,7 @@ static inline struct comedi_subdevice *comedi_get_write_subdevice( return info->device->write_subdev; } -int comedi_alloc_subdevices(struct comedi_device *, unsigned int); +int comedi_alloc_subdevices(struct comedi_device *, int); void comedi_device_detach(struct comedi_device *dev); int comedi_device_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 541364782b5f..979aa0e88997 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -56,10 +56,9 @@ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_driver *comedi_drivers; -int comedi_alloc_subdevices(struct comedi_device *dev, - unsigned int num_subdevices) +int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { - unsigned i; + int i; dev->n_subdevices = num_subdevices; dev->subdevices = -- GitLab From 7f801c41714729f7741a042de839918be2bb56f0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:57:45 -0700 Subject: [PATCH 0574/5711] staging: comedi: sanity check num_subdevices parameter in comedi_alloc_subdevices It's possible for a couple of the comedi drivers to incorrectly call comedi_alloc_subdevices with num_subdevices = 0. Add a sanity check before doing the kcalloc. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 979aa0e88997..61161ce8e93f 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -60,6 +60,8 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { int i; + if (num_subdevices < 1) + return -EINVAL; dev->n_subdevices = num_subdevices; dev->subdevices = kcalloc(num_subdevices, sizeof(struct comedi_subdevice), -- GitLab From fba1d0faf726b442ab8771d5e9fbaf5f5a4c624c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:58:27 -0700 Subject: [PATCH 0575/5711] staging: comedi: only set dev->n_subdevices when kcalloc succeedes It's possible for the kcalloc in comedi_alloc_subdevices to fail. Only set the dev->n_subdevices variable if the allocation is successful. Since the core sets dev->n_subdevices, remove all the places in the drivers where this variable was getting set. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 2 +- drivers/staging/comedi/drivers/comedi_test.c | 3 +-- drivers/staging/comedi/drivers/ni_660x.c | 4 +--- drivers/staging/comedi/drivers/s526.c | 3 +-- drivers/staging/comedi/drivers/usbdux.c | 7 ++++--- drivers/staging/comedi/drivers/usbduxfast.c | 10 +--------- drivers/staging/comedi/drivers/usbduxsigma.c | 7 ++++--- 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 61161ce8e93f..ecad2288c9fb 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -62,12 +62,12 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) if (num_subdevices < 1) return -EINVAL; - dev->n_subdevices = num_subdevices; dev->subdevices = kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL); if (!dev->subdevices) return -ENOMEM; + dev->n_subdevices = num_subdevices; for (i = 0; i < num_subdevices; ++i) { dev->subdevices[i].device = dev; dev->subdevices[i].async_dma_dir = DMA_NONE; diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index cd43c0d7df38..004da30d7d2b 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -447,8 +447,7 @@ static int waveform_attach(struct comedi_device *dev, devpriv->uvolt_amplitude = amplitude; devpriv->usec_period = period; - dev->n_subdevices = 2; - if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 5827debd3366..8c6a6ba9d4b9 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1093,9 +1093,7 @@ static int ni_660x_attach(struct comedi_device *dev, printk(KERN_INFO " %s ", dev->board_name); - dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS; - - if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 17d581b8ac6f..dbbff70dc0ca 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -778,8 +778,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ - dev->n_subdevices = 4; - if (comedi_alloc_subdevices(dev, dev->n_subdevices) < 0) + if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index ca8b3e121ff0..3819663b1cbe 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2624,6 +2624,7 @@ static int usbdux_attach_common(struct comedi_device *dev, { int ret; struct comedi_subdevice *s = NULL; + int n_subdevs; down(&udev->sem); /* pointer back to the corresponding comedi device */ @@ -2638,14 +2639,14 @@ static int usbdux_attach_common(struct comedi_device *dev, /* set number of subdevices */ if (udev->high_speed) { /* with pwm */ - dev->n_subdevices = 5; + n_subdevs = 5; } else { /* without pwm */ - dev->n_subdevices = 4; + n_subdevs = 4; } /* allocate space for the subdevices */ - ret = comedi_alloc_subdevices(dev, dev->n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { dev_err(&udev->interface->dev, "comedi%d: error alloc space for subdev\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index b2f7350c429f..262556ebc4db 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -126,11 +126,6 @@ */ #define NUMUSBDUXFAST 16 -/* - * number of subdevices - */ -#define N_SUBDEVICES 1 - /* * analogue in subdevice */ @@ -1671,11 +1666,8 @@ static int usbduxfast_attach(struct comedi_device *dev, dev->board_name = BOARDNAME; - /* set number of subdevices */ - dev->n_subdevices = N_SUBDEVICES; - /* allocate space for the subdevices */ - ret = comedi_alloc_subdevices(dev, N_SUBDEVICES); + ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) { printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for " "subdev\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 00faf4ad6ffb..87c613e88892 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2642,6 +2642,7 @@ static int usbduxsigma_attach(struct comedi_device *dev, int index; int i; struct usbduxsub *udev; + int n_subdevs; int offset; @@ -2683,14 +2684,14 @@ static int usbduxsigma_attach(struct comedi_device *dev, /* set number of subdevices */ if (udev->high_speed) { /* with pwm */ - dev->n_subdevices = 4; + n_subdevs = 4; } else { /* without pwm */ - dev->n_subdevices = 3; + n_subdevs = 3; } /* allocate space for the subdevices */ - ret = comedi_alloc_subdevices(dev, dev->n_subdevices); + ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { dev_err(&udev->interface->dev, "comedi%d: no space for subdev\n", dev->minor); -- GitLab From 0e4039f3112326d73f66b00fd18468a3804ed29e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:58:45 -0700 Subject: [PATCH 0576/5711] staging: comedi: remove the comed_alloc_subdevices "allocation failed" messages Remove all the "allocation failed" debug messages that are displayed when the comedi_alloc_subdevices call fails. Signed-off-by: H Hartley Sweeten Cc: Ian Abbot Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 6 +----- drivers/staging/comedi/drivers/adv_pci1723.c | 4 +--- drivers/staging/comedi/drivers/amplc_dio200.c | 4 +--- drivers/staging/comedi/drivers/amplc_pc236.c | 4 +--- drivers/staging/comedi/drivers/amplc_pc263.c | 4 +--- drivers/staging/comedi/drivers/amplc_pci224.c | 4 +--- drivers/staging/comedi/drivers/dyna_pci10xx.c | 2 -- drivers/staging/comedi/drivers/pcmda12.c | 4 +--- drivers/staging/comedi/drivers/pcmmio.c | 5 +---- drivers/staging/comedi/drivers/pcmuio.c | 4 +--- drivers/staging/comedi/drivers/unioxx5.c | 4 +--- drivers/staging/comedi/drivers/usbdux.c | 2 -- drivers/staging/comedi/drivers/usbduxfast.c | 2 -- drivers/staging/comedi/drivers/usbduxsigma.c | 2 -- 14 files changed, 10 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 875b02021777..64b00547228b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -389,12 +389,8 @@ static int dev_8255_attach(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, i); - if (ret < 0) { - /* FIXME this printk call should give a proper message, the - * below line just maintains previous functionality */ - printk("comedi%d: 8255:", dev->minor); + if (ret < 0) return ret; - } printk(KERN_INFO "comedi%d: 8255:", dev->minor); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 0aa0af4741a5..c14ad35cb835 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -366,10 +366,8 @@ static int pci1723_attach(struct comedi_device *dev, n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) { - printk(" - Allocation failed!\n"); + if (ret < 0) return ret; - } pci1723_reset(dev); subdev = 0; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index d7d056e20c02..17d3489b7f98 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1274,10 +1274,8 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase, dev->iobase = iobase; dev->board_name = thisboard->name; ret = comedi_alloc_subdevices(dev, layout->n_subdevs); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); + if (ret < 0) return ret; - } for (n = 0; n < dev->n_subdevices; n++) { s = &dev->subdevices[n]; switch (layout->sdtype[n]) { diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 522e1c0c385e..6205985806f5 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -456,10 +456,8 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, dev->iobase = iobase; ret = comedi_alloc_subdevices(dev, 2); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); + if (ret < 0) return ret; - } s = dev->subdevices + 0; /* digital i/o subdevice (8255) */ diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index cfb69fa9c89d..f1d68dff1ab0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -228,10 +228,8 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) dev->iobase = iobase; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); + if (ret < 0) return ret; - } s = dev->subdevices + 0; /* digital output subdevice */ diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 8d33aeab53b1..c64e32821c4d 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1381,10 +1381,8 @@ static int pci224_attach_common(struct comedi_device *dev, /* Allocate subdevices. There is only one! */ ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) { - dev_err(dev->class_dev, "error! out of memory!\n"); + if (ret < 0) return ret; - } s = dev->subdevices + 0; /* Analog output subdevice. */ diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 6f6fb527d543..bab2e37967ed 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -330,8 +330,6 @@ found: devpriv->BADR5 = pci_resource_start(pcidev, 5); if (comedi_alloc_subdevices(dev, 4) < 0) { - printk(KERN_ERR "comedi: dyna_pci10xx: " - "failed allocating subdevices\n"); mutex_unlock(&start_stop_sem); return -ENOMEM; } diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 3645e9ee8807..e1b30cc5d733 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -197,10 +197,8 @@ static int pcmda12_attach(struct comedi_device *dev, * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the * 96-channel version of the board. */ - if (comedi_alloc_subdevices(dev, 1) < 0) { - printk(KERN_ERR "cannot allocate subdevice data structures\n"); + if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; - } s = dev->subdevices; s->private = NULL; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 67fdac5b81d6..abaf6c758baf 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1077,11 +1077,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO) */ - if (comedi_alloc_subdevices(dev, n_subdevs) < 0) { - printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n", - dev->minor); + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) return -ENOMEM; - } /* First, AI */ sdev_no = 0; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index ce5068e3b46e..e4153bd27172 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -807,10 +807,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the * 96-channel version of the board. */ - if (comedi_alloc_subdevices(dev, n_subdevs) < 0) { - dev_dbg(dev->hw_dev, "cannot allocate subdevice data structures\n"); + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) return -ENOMEM; - } port = 0; asic = 0; diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 170bc48cfd1c..711dad77c598 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -468,10 +468,8 @@ static int unioxx5_attach(struct comedi_device *dev, return -1; } - if (comedi_alloc_subdevices(dev, n_subd) < 0) { - printk(KERN_ERR "out of memory\n"); + if (comedi_alloc_subdevices(dev, n_subd) < 0) return -ENOMEM; - } /* initializing each of for same subdevices */ for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) { diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 3819663b1cbe..79df200bb6ee 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2648,8 +2648,6 @@ static int usbdux_attach_common(struct comedi_device *dev, /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { - dev_err(&udev->interface->dev, - "comedi%d: error alloc space for subdev\n", dev->minor); up(&udev->sem); return ret; } diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 262556ebc4db..660dd4ee51e0 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1669,8 +1669,6 @@ static int usbduxfast_attach(struct comedi_device *dev, /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) { - printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for " - "subdev\n", dev->minor); up(&(usbduxfastsub[index].sem)); up(&start_stop_sem); return ret; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 87c613e88892..f37e96c80b91 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2693,8 +2693,6 @@ static int usbduxsigma_attach(struct comedi_device *dev, /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { - dev_err(&udev->interface->dev, - "comedi%d: no space for subdev\n", dev->minor); up(&udev->sem); up(&start_stop_sem); return ret; -- GitLab From eea6838b1206b0ac90110f1a6f58e101aa496e99 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:59:15 -0700 Subject: [PATCH 0577/5711] staging: comedi: remove the "Allocate the subdevice..." comments These comments are redundant. The function name 'comedi_alloc_subdevices' provides this information. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/addi_common.c | 1 - drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c | 1 - drivers/staging/comedi/drivers/adq12b.c | 4 ---- drivers/staging/comedi/drivers/amplc_pci224.c | 1 - drivers/staging/comedi/drivers/amplc_pci230.c | 5 +---- drivers/staging/comedi/drivers/c6xdigio.c | 1 - drivers/staging/comedi/drivers/cb_pcidas.c | 3 --- drivers/staging/comedi/drivers/cb_pcidda.c | 3 --- drivers/staging/comedi/drivers/cb_pcidio.c | 4 ---- drivers/staging/comedi/drivers/cb_pcimdas.c | 4 ---- drivers/staging/comedi/drivers/cb_pcimdda.c | 4 ---- drivers/staging/comedi/drivers/comedi_bond.c | 4 ---- drivers/staging/comedi/drivers/dmm32at.c | 4 ---- drivers/staging/comedi/drivers/dt9812.c | 1 - drivers/staging/comedi/drivers/ke_counter.c | 1 - drivers/staging/comedi/drivers/me4000.c | 5 ----- drivers/staging/comedi/drivers/mpc624.c | 1 - drivers/staging/comedi/drivers/pcmda12.c | 7 ------- drivers/staging/comedi/drivers/pcmmio.c | 7 +------ drivers/staging/comedi/drivers/pcmuio.c | 8 +------- drivers/staging/comedi/drivers/rtd520.c | 4 ---- drivers/staging/comedi/drivers/s526.c | 4 ---- drivers/staging/comedi/drivers/skel.c | 4 ---- drivers/staging/comedi/drivers/ssv_dnp.c | 3 --- drivers/staging/comedi/drivers/usbdux.c | 1 - drivers/staging/comedi/drivers/usbduxfast.c | 1 - drivers/staging/comedi/drivers/usbduxsigma.c | 1 - 27 files changed, 3 insertions(+), 84 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 274990a7cd3f..46c590b1ad96 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -1686,7 +1686,6 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->s_BoardInfos.ui_Address = io_addr[2]; #endif } else { - /* Update-0.7.57->0.7.68dev->n_subdevices = 7; */ n_subdevices = 7; ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c index 9632ca182d25..aa390b01475b 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -62,7 +62,6 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) int ret = 0; int n_subdevices = 9; - /* Update-0.7.57->0.7.68dev->n_subdevices = 9; */ ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret < 0) return; diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index ca8892e83db1..afc6815bcc36 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -267,10 +267,6 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->last_channel = -1; devpriv->last_range = -1; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index c64e32821c4d..1392406d99f0 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1379,7 +1379,6 @@ static int pci224_attach_common(struct comedi_device *dev, outw(devpriv->daccon | PCI224_DACCON_FIFORESET, dev->iobase + PCI224_DACCON); - /* Allocate subdevices. There is only one! */ ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index e6598cafb39a..52f3cb8fb2d1 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2839,10 +2839,7 @@ static int pci230_attach_common(struct comedi_device *dev, dev_dbg(dev->class_dev, "registered irq %u\n", devpriv->pci_dev->irq); } - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ + if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 72b000fad609..5fa344b269fd 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -433,7 +433,6 @@ static int c6xdigio_attach(struct comedi_device *dev, dev->iobase = iobase; dev->board_name = "c6xdigio"; - /* 3 subdevices with encoder_init write */ result = comedi_alloc_subdevices(dev, 2); if (result < 0) return result; diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 435f3aaedf88..e1bd99a950e4 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -614,9 +614,6 @@ found: /* Initialize dev->board_name */ dev->board_name = thisboard->name; -/* - * Allocate the subdevice structures. - */ if (comedi_alloc_subdevices(dev, 7) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 4ab3584365e2..fedaf55af03d 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -333,9 +333,6 @@ found: */ dev->board_name = thisboard->name; -/* - * Allocate the subdevice structures. - */ if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 56c1d09188aa..f2fff4f2080b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -177,10 +177,6 @@ found: pci_resource_start(devpriv->pci_dev, pcidio_boards[index].dioregs_badrindex); -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, thisboard->n_8255) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 6acb3199e6f3..0ada8b91b315 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -269,10 +269,6 @@ found: /* Initialize dev->board_name */ dev->board_name = thisboard->name; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index abb6008da4df..b401aec89348 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -236,10 +236,6 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) */ dev->board_name = thisboard->name; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 2) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index d56eec48e4c8..96e5b35f4d7c 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -358,10 +358,6 @@ static int bonding_attach(struct comedi_device *dev, */ dev->board_name = devpriv->name; - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 40d7befec5ea..6b637a2a48c7 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -371,10 +371,6 @@ static int dmm32at_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) return -ENOMEM; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 56af2f28f98d..678fa502a716 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -1035,7 +1035,6 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->serial = it->options[0]; - /* Allocate subdevices */ if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index bcb1eb49a1f7..7c256f4f32d1 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -189,7 +189,6 @@ found: io_base = pci_resource_start(pci_device, 0); dev->iobase = io_base; - /* allocate the subdevice structures */ error = comedi_alloc_subdevices(dev, 1); if (error < 0) return error; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 39100ddddef8..4adb206ebd93 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2190,11 +2190,6 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (result) return result; - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. It relies on - * n_subdevices being set correctly. - */ if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 48ba6b9f9430..975033653f0c 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -348,7 +348,6 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; } - /* Subdevices structures */ if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index e1b30cc5d733..87faa0381976 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -190,13 +190,6 @@ static int pcmda12_attach(struct comedi_device *dev, devpriv->simultaneous_xfer_mode = it->options[1]; - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - * - * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the - * 96-channel version of the board. - */ if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index abaf6c758baf..31053034b073 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1071,12 +1071,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->minor); return -ENOMEM; } - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - * - * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO) - */ + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index e4153bd27172..33ab4c63b3dc 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -800,13 +800,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_warn(dev->hw_dev, "cannot allocate subdevice private data structures\n"); return -ENOMEM; } - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - * - * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the - * 96-channel version of the board. - */ + if (comedi_alloc_subdevices(dev, n_subdevs) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 7d248a7685b2..445333b2413e 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1999,10 +1999,6 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Show board configuration */ printk(KERN_INFO "%s:", dev->board_name); - /* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index dbbff70dc0ca..6a30537987c6 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -774,10 +774,6 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct s526_private)) < 0) return -ENOMEM; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 4) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 16947c8b8803..ca10b1a98153 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -233,10 +233,6 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct skel_private)) < 0) return -ENOMEM; -/* - * Allocate the subdevice structures. alloc_subdevice() is a - * convenient macro defined in comedidev.h. - */ if (comedi_alloc_subdevices(dev, 3) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 5eaef8434e09..130e4bd5c640 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -197,9 +197,6 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0) return -ENOMEM; - /* Allocate the subdevice structures. alloc_subdevice() is a */ - /* convenient macro defined in comedidev.h. */ - if (comedi_alloc_subdevices(dev, 1) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 79df200bb6ee..a6cf13459c61 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2645,7 +2645,6 @@ static int usbdux_attach_common(struct comedi_device *dev, n_subdevs = 4; } - /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { up(&udev->sem); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 660dd4ee51e0..f7d4f56c1688 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1666,7 +1666,6 @@ static int usbduxfast_attach(struct comedi_device *dev, dev->board_name = BOARDNAME; - /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, 1); if (ret < 0) { up(&(usbduxfastsub[index].sem)); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index f37e96c80b91..f23fad957e5e 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2690,7 +2690,6 @@ static int usbduxsigma_attach(struct comedi_device *dev, n_subdevs = 3; } - /* allocate space for the subdevices */ ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret < 0) { up(&udev->sem); -- GitLab From 8b6c56949ffa83dbc2a6e8fa3f98b10a19372207 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:59:33 -0700 Subject: [PATCH 0578/5711] staging: comedi: propogate error code from comedi_alloc_subdevices comedi_alloc_subdevices can fail with -EINVAL or -ENOMEM. When it does fail make sure to pass the proper error code back. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 2 +- drivers/staging/comedi/drivers/acl7225b.c | 6 ++++-- drivers/staging/comedi/drivers/addi-data/addi_common.c | 2 +- .../staging/comedi/drivers/addi-data/hwdrv_APCI1710.c | 2 +- drivers/staging/comedi/drivers/adl_pci6208.c | 5 +++-- drivers/staging/comedi/drivers/adl_pci7230.c | 6 ++++-- drivers/staging/comedi/drivers/adl_pci7296.c | 5 +++-- drivers/staging/comedi/drivers/adl_pci7432.c | 6 ++++-- drivers/staging/comedi/drivers/adl_pci8164.c | 6 ++++-- drivers/staging/comedi/drivers/adl_pci9111.c | 2 +- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- drivers/staging/comedi/drivers/adq12b.c | 6 ++++-- drivers/staging/comedi/drivers/adv_pci1710.c | 2 +- drivers/staging/comedi/drivers/adv_pci1723.c | 2 +- drivers/staging/comedi/drivers/adv_pci_dio.c | 2 +- drivers/staging/comedi/drivers/aio_aio12_8.c | 6 ++++-- drivers/staging/comedi/drivers/aio_iiro_16.c | 6 ++++-- drivers/staging/comedi/drivers/amplc_dio200.c | 4 +++- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- drivers/staging/comedi/drivers/amplc_pc263.c | 2 +- drivers/staging/comedi/drivers/amplc_pci224.c | 2 +- drivers/staging/comedi/drivers/amplc_pci230.c | 6 ++++-- drivers/staging/comedi/drivers/c6xdigio.c | 2 +- drivers/staging/comedi/drivers/cb_das16_cs.c | 5 +++-- drivers/staging/comedi/drivers/cb_pcidas.c | 6 ++++-- drivers/staging/comedi/drivers/cb_pcidas64.c | 6 ++++-- drivers/staging/comedi/drivers/cb_pcidda.c | 7 ++++--- drivers/staging/comedi/drivers/cb_pcidio.c | 6 ++++-- drivers/staging/comedi/drivers/cb_pcimdas.c | 6 ++++-- drivers/staging/comedi/drivers/cb_pcimdda.c | 5 +++-- drivers/staging/comedi/drivers/comedi_bond.c | 6 ++++-- drivers/staging/comedi/drivers/comedi_parport.c | 3 ++- drivers/staging/comedi/drivers/comedi_test.c | 6 ++++-- drivers/staging/comedi/drivers/contec_pci_dio.c | 6 ++++-- drivers/staging/comedi/drivers/daqboard2000.c | 4 ++-- drivers/staging/comedi/drivers/das08.c | 2 +- drivers/staging/comedi/drivers/das16.c | 2 +- drivers/staging/comedi/drivers/das16m1.c | 2 +- drivers/staging/comedi/drivers/das1800.c | 5 +++-- drivers/staging/comedi/drivers/das6402.c | 2 +- drivers/staging/comedi/drivers/das800.c | 6 ++++-- drivers/staging/comedi/drivers/dmm32at.c | 5 +++-- drivers/staging/comedi/drivers/dt2801.c | 8 +++----- drivers/staging/comedi/drivers/dt2811.c | 2 +- drivers/staging/comedi/drivers/dt2814.c | 2 +- drivers/staging/comedi/drivers/dt2815.c | 7 +++++-- drivers/staging/comedi/drivers/dt2817.c | 2 +- drivers/staging/comedi/drivers/dt282x.c | 2 +- drivers/staging/comedi/drivers/dt3000.c | 2 +- drivers/staging/comedi/drivers/dt9812.c | 6 ++++-- drivers/staging/comedi/drivers/dyna_pci10xx.c | 6 ++++-- drivers/staging/comedi/drivers/fl512.c | 6 ++++-- drivers/staging/comedi/drivers/gsc_hpdi.c | 6 ++++-- drivers/staging/comedi/drivers/icp_multi.c | 2 +- drivers/staging/comedi/drivers/ii_pci20kc.c | 2 +- drivers/staging/comedi/drivers/jr3_pci.c | 4 ++-- drivers/staging/comedi/drivers/ke_counter.c | 2 +- drivers/staging/comedi/drivers/me4000.c | 5 +++-- drivers/staging/comedi/drivers/me_daq.c | 3 +-- drivers/staging/comedi/drivers/mpc624.c | 6 ++++-- drivers/staging/comedi/drivers/mpc8260cpm.c | 6 ++++-- drivers/staging/comedi/drivers/multiq3.c | 3 ++- drivers/staging/comedi/drivers/ni_6527.c | 2 +- drivers/staging/comedi/drivers/ni_65xx.c | 2 +- drivers/staging/comedi/drivers/ni_660x.c | 5 +++-- drivers/staging/comedi/drivers/ni_670x.c | 5 +++-- drivers/staging/comedi/drivers/ni_at_a2150.c | 6 ++++-- drivers/staging/comedi/drivers/ni_at_ao.c | 6 ++++-- drivers/staging/comedi/drivers/ni_atmio16d.c | 2 +- drivers/staging/comedi/drivers/ni_daq_700.c | 6 ++++-- drivers/staging/comedi/drivers/ni_daq_dio24.c | 6 ++++-- drivers/staging/comedi/drivers/ni_labpc.c | 6 ++++-- drivers/staging/comedi/drivers/ni_mio_common.c | 6 ++++-- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/pcl711.c | 2 +- drivers/staging/comedi/drivers/pcl724.c | 2 +- drivers/staging/comedi/drivers/pcl725.c | 6 ++++-- drivers/staging/comedi/drivers/pcl726.c | 2 +- drivers/staging/comedi/drivers/pcl730.c | 6 ++++-- drivers/staging/comedi/drivers/pcl812.c | 2 +- drivers/staging/comedi/drivers/pcl816.c | 2 +- drivers/staging/comedi/drivers/pcl818.c | 2 +- drivers/staging/comedi/drivers/pcm3724.c | 2 +- drivers/staging/comedi/drivers/pcm3730.c | 6 ++++-- drivers/staging/comedi/drivers/pcmad.c | 2 +- drivers/staging/comedi/drivers/pcmda12.c | 6 ++++-- drivers/staging/comedi/drivers/pcmmio.c | 6 ++++-- drivers/staging/comedi/drivers/pcmuio.c | 6 ++++-- drivers/staging/comedi/drivers/poc.c | 7 +++++-- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 2 +- drivers/staging/comedi/drivers/rtd520.c | 6 +++--- drivers/staging/comedi/drivers/rti800.c | 2 +- drivers/staging/comedi/drivers/rti802.c | 9 ++++++--- drivers/staging/comedi/drivers/s526.c | 6 ++++-- drivers/staging/comedi/drivers/s626.c | 5 +++-- drivers/staging/comedi/drivers/serial2002.c | 6 ++++-- drivers/staging/comedi/drivers/skel.c | 6 ++++-- drivers/staging/comedi/drivers/ssv_dnp.c | 6 ++++-- drivers/staging/comedi/drivers/unioxx5.c | 6 ++++-- drivers/staging/comedi/drivers/usbdux.c | 2 +- drivers/staging/comedi/drivers/usbduxfast.c | 2 +- drivers/staging/comedi/drivers/usbduxsigma.c | 2 +- drivers/staging/comedi/drivers/vmk80xx.c | 6 ++++-- 103 files changed, 269 insertions(+), 168 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 64b00547228b..502bde8c22c1 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -389,7 +389,7 @@ static int dev_8255_attach(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, i); - if (ret < 0) + if (ret) return ret; printk(KERN_INFO "comedi%d: 8255:", dev->minor); diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index 3c39148c64cb..0bf552581c5f 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -68,6 +68,7 @@ static int acl7225b_attach(struct comedi_device *dev, const struct boardtype *board = comedi_board(dev); struct comedi_subdevice *s; int iobase, iorange; + int ret; iobase = it->options[0]; iorange = board->io_range; @@ -82,8 +83,9 @@ static int acl7225b_attach(struct comedi_device *dev, dev->iobase = iobase; dev->irq = 0; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; /* Relays outputs */ diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 46c590b1ad96..a5aa673335ef 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -1688,7 +1688,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } else { n_subdevices = 7; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; /* Allocate and Initialise AI Subdevice Structures */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c index aa390b01475b..595238feaf42 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -63,7 +63,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) int n_subdevices = 9; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return; /* Allocate and Initialise Timer Subdevice Structures */ diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 7d26d45d0753..98b373063445 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -301,8 +301,9 @@ static int pci6208_attach(struct comedi_device *dev, dev->iobase = io_base; dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + retval = comedi_alloc_subdevices(dev, 2); + if (retval) + return retval; s = dev->subdevices + 0; /* analog output subdevice */ diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index 5a6e6c11e7fe..62fdf7f63703 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -108,6 +108,7 @@ static int adl_pci7230_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int ret; printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor); @@ -116,8 +117,9 @@ static int adl_pci7230_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7230_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; devpriv->pci_dev = adl_pci7230_find_pci(dev, it); if (!devpriv->pci_dev) diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index fd9b33afd458..58deb60f2b8c 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -92,8 +92,9 @@ static int adl_pci7296_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7296_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; devpriv->pci_dev = adl_pci7296_find_pci(dev, it); if (!devpriv->pci_dev) diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index 4976a70fb1e4..aabf4183aaf5 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -117,6 +117,7 @@ static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int ret; printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); @@ -125,8 +126,9 @@ static int adl_pci7432_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; devpriv->pci_dev = adl_pci7432_find_pci(dev, it); if (!devpriv->pci_dev) diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 78169f7d06ac..181137546133 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -252,6 +252,7 @@ static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int ret; printk(KERN_INFO "comedi: attempt to attach...\n"); printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor); @@ -261,8 +262,9 @@ static int adl_pci8164_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; devpriv->pci_dev = adl_pci8164_find_pci(dev, it); if (!devpriv->pci_dev) diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index cc179466dce0..4f2cea8e11f7 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1318,7 +1318,7 @@ static int pci9111_attach(struct comedi_device *dev, /* TODO: Add external multiplexer setup (according to option[2]). */ error = comedi_alloc_subdevices(dev, 4); - if (error < 0) + if (error) return error; subdevice = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index ebd8b8ec8c31..9a7b6a5797bb 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2269,7 +2269,7 @@ static int pci9118_attach(struct comedi_device *dev, /* Enable parity check for parity error */ ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index afc6815bcc36..f7bb14589c9b 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -224,6 +224,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase; int unipolar, differential; + int ret; iobase = it->options[0]; unipolar = it->options[1]; @@ -267,8 +268,9 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->last_channel = -1; devpriv->last_range = -1; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index be3fc4dd8859..60a50adcd715 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1434,7 +1434,7 @@ static int pci1710_attach(struct comedi_device *dev, n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; pci1710_reset(dev); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index c14ad35cb835..d37c14da5ec6 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -366,7 +366,7 @@ static int pci1723_attach(struct comedi_device *dev, n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; pci1723_reset(dev); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 0fc4f858acca..942dc777a0e6 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1157,7 +1157,7 @@ static int pci_dio_attach(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; subdev = 0; diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 60466c81e2a9..f7d453f8fe33 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -168,6 +168,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev, const struct aio12_8_boardtype *board = comedi_board(dev); int iobase; struct comedi_subdevice *s; + int ret; iobase = it->options[0]; if (!request_region(iobase, 24, "aio_aio12_8")) { @@ -182,8 +183,9 @@ static int aio_aio12_8_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 7d161d6739ae..8059cefe5b8c 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -107,6 +107,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, const struct aio_iiro_16_board *board = comedi_board(dev); int iobase; struct comedi_subdevice *s; + int ret; printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor); @@ -124,8 +125,9 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct aio_iiro_16_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 17d3489b7f98..c67b09ff37d7 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1273,9 +1273,11 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase, devpriv->intr_sd = -1; dev->iobase = iobase; dev->board_name = thisboard->name; + ret = comedi_alloc_subdevices(dev, layout->n_subdevs); - if (ret < 0) + if (ret) return ret; + for (n = 0; n < dev->n_subdevices; n++) { s = &dev->subdevices[n]; switch (layout->sdtype[n]) { diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 6205985806f5..e55321ec5ae8 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -456,7 +456,7 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, dev->iobase = iobase; ret = comedi_alloc_subdevices(dev, 2); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index f1d68dff1ab0..4f15bfd80719 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -228,7 +228,7 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) dev->iobase = iobase; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 1392406d99f0..b87e10ddf239 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1380,7 +1380,7 @@ static int pci224_attach_common(struct comedi_device *dev, dev->iobase + PCI224_DACCON); ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 52f3cb8fb2d1..3d7f2cda980a 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2840,8 +2840,10 @@ static int pci230_attach_common(struct comedi_device *dev, devpriv->pci_dev->irq); } - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + rc = comedi_alloc_subdevices(dev, 3); + if (rc) + return rc; + s = dev->subdevices + 0; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 5fa344b269fd..41ed8576f301 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -434,7 +434,7 @@ static int c6xdigio_attach(struct comedi_device *dev, dev->board_name = "c6xdigio"; result = comedi_alloc_subdevices(dev, 2); - if (result < 0) + if (result) return result; /* Make sure that PnP ports get activated */ diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 9aa11c15497f..031007791d29 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -195,8 +195,9 @@ static int das16cs_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct das16cs_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = dev->subdevices + 0; dev->read_subdev = s; diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index e1bd99a950e4..2ca3fa0fc776 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -533,6 +533,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, struct pci_dev *pcidev = NULL; int index; int i; + int ret; /* * Allocate the private structure area. @@ -614,8 +615,9 @@ found: /* Initialize dev->board_name */ dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 7) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 7); + if (ret) + return ret; s = dev->subdevices + 0; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 6b2f153980a9..3aab75b5217d 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1344,9 +1344,11 @@ static int setup_subdevices(struct comedi_device *dev) struct comedi_subdevice *s; void __iomem *dio_8255_iobase; int i; + int ret; - if (comedi_alloc_subdevices(dev, 10) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 10); + if (ret) + return ret; s = dev->subdevices + 0; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index fedaf55af03d..0572dc6fd5ca 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -265,7 +265,7 @@ static int cb_pcidda_attach(struct comedi_device *dev, struct comedi_subdevice *s; struct pci_dev *pcidev = NULL; int index; - + int ret; /* * Allocate the private structure area. @@ -333,8 +333,9 @@ found: */ dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; /* analog output subdevice */ diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index f2fff4f2080b..0186737c1ee1 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -116,6 +116,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pci_dev *pcidev = NULL; int index; int i; + int ret; /* * Allocate the private structure area. alloc_private() is a @@ -177,8 +178,9 @@ found: pci_resource_start(devpriv->pci_dev, pcidio_boards[index].dioregs_badrindex); - if (comedi_alloc_subdevices(dev, thisboard->n_8255) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, thisboard->n_8255); + if (ret) + return ret; for (i = 0; i < thisboard->n_8255; i++) { subdev_8255_init(dev, dev->subdevices + i, diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 0ada8b91b315..b99a451bab9e 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -187,6 +187,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev, struct comedi_subdevice *s; struct pci_dev *pcidev = NULL; int index; + int ret; /* int i; */ /* @@ -269,8 +270,9 @@ found: /* Initialize dev->board_name */ dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; /* dev->read_subdev=s; */ diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index b401aec89348..a80146133c04 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -236,8 +236,9 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) */ dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + err = comedi_alloc_subdevices(dev, 2); + if (err) + return err; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 96e5b35f4d7c..0260ddc05645 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -336,6 +336,7 @@ static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int ret; LOG_MSG("comedi%d\n", dev->minor); @@ -358,8 +359,9 @@ static int bonding_attach(struct comedi_device *dev, */ dev->board_name = devpriv->name; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index c9a725fc61f2..589d12f68067 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -316,8 +316,9 @@ static int parport_attach(struct comedi_device *dev, dev->board_name = "parport"; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; + ret = alloc_private(dev, sizeof(struct parport_private)); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 004da30d7d2b..523a809708b7 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -432,6 +432,7 @@ static int waveform_attach(struct comedi_device *dev, int amplitude = it->options[0]; int period = it->options[1]; int i; + int ret; dev->board_name = board->name; @@ -447,8 +448,9 @@ static int waveform_attach(struct comedi_device *dev, devpriv->uvolt_amplitude = amplitude; devpriv->usec_period = period; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; s = dev->subdevices + 0; dev->read_subdev = s; diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index a5bad1bd6dcd..79854b1ac243 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -107,6 +107,7 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pcidev = NULL; struct comedi_subdevice *s; + int ret; printk("comedi%d: contec: ", dev->minor); @@ -115,8 +116,9 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct contec_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; for_each_pci_dev(pcidev) { if (pcidev->vendor == PCI_VENDOR_ID_CONTEC && diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index dbd0472bc7e2..9ecf1a468567 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -773,8 +773,8 @@ static int daqboard2000_attach(struct comedi_device *dev, return -ENOMEM; result = comedi_alloc_subdevices(dev, 3); - if (result < 0) - goto out; + if (result) + return result; readl(devpriv->plx + 0x6c); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 1dea21a33a27..c4627a6b62be 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -835,7 +835,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) dev->board_name = thisboard->name; ret = comedi_alloc_subdevices(dev, 6); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 6a8a7eb1ae9c..0c6ad1067055 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1265,7 +1265,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->timer_mode = timer_mode ? 1 : 0; ret = comedi_alloc_subdevices(dev, 5); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index eafd6b59a483..f3fba13432bb 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -647,7 +647,7 @@ static int das16m1_attach(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 12d736a6e38d..af60e5d5b8a3 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1644,8 +1644,9 @@ static int das1800_attach(struct comedi_device *dev, return -ENOMEM; } - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + retval = comedi_alloc_subdevices(dev, 4); + if (retval) + return retval; /* analog input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 2039b6c11590..22a9b3448e3f 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -308,7 +308,7 @@ static int das6402_attach(struct comedi_device *dev, return ret; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; /* ai subdevice */ diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 6263f532e5da..81698b1fd0da 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -465,6 +465,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int irq = it->options[1]; unsigned long irq_flags; int board; + int ret; dev_info(dev->hw_dev, "comedi%d: das800: io 0x%lx\n", dev->minor, iobase); @@ -510,8 +511,9 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; /* analog input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 6b637a2a48c7..2b60cf816b6e 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -371,8 +371,9 @@ static int dmm32at_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; dev->read_subdev = s; diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 35ce076237a4..5afbf8a4b030 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -626,15 +626,15 @@ havetype: printk("dt2801: %s at port 0x%lx", boardtype.name, iobase); n_ai_chans = probe_number_of_ai_chans(dev); - printk(" (ai channels = %d)", n_ai_chans); + printk(" (ai channels = %d)\n", n_ai_chans); ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) goto out; ret = alloc_private(dev, sizeof(struct dt2801_private)); if (ret < 0) - goto out; + return ret; dev->board_name = boardtype.name; @@ -688,8 +688,6 @@ havetype: ret = 0; out: - printk("\n"); - return ret; } diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 6ff610d1b0f9..91fbf4a7a2af 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -466,7 +466,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct dt2811_private)); diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 876d5cbdbe4a..2e39ebe36fb5 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -339,7 +339,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) } ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct dt2814_private)); diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 33ad1fa90762..45b20bee4369 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -166,6 +166,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) int i; const struct comedi_lrange *current_range_type, *voltage_range_type; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: dt2815: 0x%04lx ", dev->minor, iobase); @@ -177,8 +178,10 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->board_name = "dt2815"; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; + if (alloc_private(dev, sizeof(struct dt2815_private)) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 665db07aeb84..9282ca55f637 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -138,7 +138,7 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = "dt2817"; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index f11d1fdfcae2..9c0a0df7dff2 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1269,7 +1269,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; ret = comedi_alloc_subdevices(dev, 3); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 10415b218b5c..9828fb1e3365 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -883,7 +883,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->irq = devpriv->pci_dev->irq; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; s = dev->subdevices; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 678fa502a716..40821c7303ea 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -1021,6 +1021,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int i; struct comedi_subdevice *s; + int ret; dev->board_name = "dt9812"; @@ -1035,8 +1036,9 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->serial = it->options[0]; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; /* digital input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index bab2e37967ed..9c855e25275c 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -246,6 +246,7 @@ static int dyna_pci10xx_attach(struct comedi_device *dev, struct pci_dev *pcidev; unsigned int opt_bus, opt_slot; int board_index, i; + int ret; mutex_lock(&start_stop_sem); @@ -329,9 +330,10 @@ found: devpriv->BADR4 = pci_resource_start(pcidev, 4); devpriv->BADR5 = pci_resource_start(pcidev, 5); - if (comedi_alloc_subdevices(dev, 4) < 0) { + ret = comedi_alloc_subdevices(dev, 4); + if (ret) { mutex_unlock(&start_stop_sem); - return -ENOMEM; + return ret; } /* analog input */ diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 7218a9b2cda9..d1da80976f84 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -111,6 +111,7 @@ static int fl512_ao_insn_readback(struct comedi_device *dev, static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) { unsigned long iobase; + int ret; /* pointer to the subdevice: Analog in, Analog out, (not made ->and Digital IO) */ @@ -131,8 +132,9 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_DEBUG "malloc ok\n"); #endif - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; /* * this if the definitions of the supdevices, 2 have been defined diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index b103cfbf3274..79f580841dee 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -430,9 +430,11 @@ static void init_plx9080(struct comedi_device *dev) static int setup_subdevices(struct comedi_device *dev) { struct comedi_subdevice *s; + int ret; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices + 0; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 06c66afc6aa1..544bed870470 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -904,7 +904,7 @@ static int icp_multi_attach(struct comedi_device *dev, n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; icp_multi_reset(dev); diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 9c1165791078..bea3d03bae2e 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -203,7 +203,7 @@ static int pci20xxx_attach(struct comedi_device *dev, union pci20xxx_subdev_private *sdp; ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct pci20xxx_private)); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 182643bed561..3c043e535506 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -827,8 +827,8 @@ static int jr3_pci_attach(struct comedi_device *dev, return -ENOMEM; result = comedi_alloc_subdevices(dev, devpriv->n_channels); - if (result < 0) - goto out; + if (result) + return result; dev->open = jr3_pci_open; for (i = 0; i < devpriv->n_channels; i++) { diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 7c256f4f32d1..019e91a9f143 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -190,7 +190,7 @@ found: dev->iobase = io_base; error = comedi_alloc_subdevices(dev, 1); - if (error < 0) + if (error) return error; subdevice = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 4adb206ebd93..aae01f10b1c3 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2190,8 +2190,9 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (result) return result; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + result = comedi_alloc_subdevices(dev, 4); + if (result) + return result; /*========================================================================= Analog input subdevice diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 231b29413eaa..ae3b0469541e 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -761,9 +761,8 @@ found: me_reset(dev); - /* device driver capabilities */ error = comedi_alloc_subdevices(dev, 3); - if (error < 0) + if (error) return error; subdevice = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 975033653f0c..b928b6763cd5 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -285,6 +285,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase); @@ -348,8 +349,9 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; } - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c index 13110510d7fe..a6311b11831b 100644 --- a/drivers/staging/comedi/drivers/mpc8260cpm.c +++ b/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -121,6 +121,7 @@ static int mpc8260cpm_attach(struct comedi_device *dev, { struct comedi_subdevice *s; int i; + int ret; printk("comedi%d: mpc8260cpm: ", dev->minor); @@ -131,8 +132,9 @@ static int mpc8260cpm_attach(struct comedi_device *dev, if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret =comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; for (i = 0; i < 4; i++) { s = dev->subdevices + i; diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 00d497c270ae..b1bbd0255fbc 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -255,8 +255,9 @@ static int multiq3_attach(struct comedi_device *dev, else printk(KERN_WARNING "comedi%d: no irq\n", dev->minor); dev->board_name = "multiq3"; + result = comedi_alloc_subdevices(dev, 5); - if (result < 0) + if (result) return result; result = alloc_private(dev, sizeof(struct multiq3_private)); diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 89fee6fdcf61..b60ab4848b64 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -398,7 +398,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) readb(devpriv->mite->daq_io_addr + ID_Register)); ret = comedi_alloc_subdevices(dev, 3); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index a49dceac65bc..ac7c74be08a2 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -679,7 +679,7 @@ static int ni_65xx_attach(struct comedi_device *dev, readb(private(dev)->mite->daq_io_addr + ID_Register)); ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 8c6a6ba9d4b9..5391a3949da1 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1093,8 +1093,9 @@ static int ni_660x_attach(struct comedi_device *dev, printk(KERN_INFO " %s ", dev->board_name); - if (comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS); + if (ret) + return ret; s = dev->subdevices + 0; /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */ diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 45a03e64549a..5dffe6ce4738 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -202,8 +202,9 @@ static int ni_670x_attach(struct comedi_device *dev, dev->irq = mite_irq(devpriv->mite); printk(KERN_INFO " %s", dev->board_name); - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; s = dev->subdevices + 0; /* analog output subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 9d1a0f745bf8..b53a4286f8cb 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -755,6 +755,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int dma = it->options[2]; static const int timeout = 2000; int i; + int ret; printk("comedi%d: %s: io 0x%lx", dev->minor, dev->driver->driver_name, iobase); @@ -826,8 +827,9 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = a2150_boards + a2150_probe(dev); dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; /* analog input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 03a4d736b454..1c3f3222d496 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -337,6 +337,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase; int ao_unipolar; + int ret; iobase = it->options[0]; if (iobase == 0) @@ -356,8 +357,9 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct atao_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = dev->subdevices + 0; /* analog output subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 37ff6fc86157..95bee84b78ae 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -710,7 +710,7 @@ static int atmio16d_attach(struct comedi_device *dev, dev->board_name = board->name; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct atmio16d_private)); diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 8860207e88d7..53b0173aa2b2 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -364,6 +364,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int irq = 0; #endif struct pcmcia_device *link; + int ret; /* allocate and initialize dev->private */ if (alloc_private(dev, sizeof(struct dio700_private)) < 0) @@ -409,8 +410,9 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; /* DAQCard-700 dio */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 36c0c62382ed..e27cae0eb8a2 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -116,6 +116,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int irq = 0; #endif struct pcmcia_device *link; + int ret; /* allocate and initialize dev->private */ if (alloc_private(dev, sizeof(struct dio24_private)) < 0) @@ -158,8 +159,9 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; /* 8255 dio */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index a92570f5a7c5..ab8b787c78bb 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -536,6 +536,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, unsigned long dma_flags; #endif short lsb, msb; + int ret; printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, thisboard->name, @@ -622,8 +623,9 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 5) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 5); + if (ret) + return ret; /* analog input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 4261e929869f..1f796b9361b2 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4406,14 +4406,16 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned j; enum ni_gpct_variant counter_variant; + int ret; if (boardtype.n_aochan > MAX_N_AO_CHAN) { printk("bug! boardtype.n_aochan > MAX_N_AO_CHAN\n"); return -EINVAL; } - if (comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES); + if (ret) + return ret; /* analog input subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 77ef312f657e..cba045965167 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1249,7 +1249,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) n_subdevices = 1; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; if (!this_board->is_diodaq) { diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 35b95105a749..d5fa6f28eb1f 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -519,7 +519,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->irq = irq; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct pcl711_private)); diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 698c9004c74e..c8fe23ca899d 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -157,7 +157,7 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) n_subdevices = 4; /* PCL-724 in 96 DIO configuration */ ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; for (i = 0; i < dev->n_subdevices; i++) { diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index d7ba336ce031..8edbefd7c43b 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -52,6 +52,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase); @@ -63,8 +64,9 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->irq = 0; - if (comedi_alloc_subdevices(dev, 2) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; s = dev->subdevices + 0; /* do */ diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index e756a3033767..b2e73cda2957 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -293,7 +293,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk("\n"); ret = comedi_alloc_subdevices(dev, 3); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index e258bcebf198..3cba79a219b8 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -72,6 +72,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase; unsigned int iorange; + int ret; iobase = it->options[0]; iorange = board->io_range; @@ -85,8 +86,9 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; dev->irq = 0; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = dev->subdevices + 0; /* Isolated do */ diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 128f5b644878..0a4074af8a60 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1383,7 +1383,7 @@ no_dma: n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) { + if (ret) { free_resources(dev); return ret; } diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 37cedbc47a43..c3ee6d69b9a6 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -1195,7 +1195,7 @@ no_dma: */ ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index a4c2870562fb..66b2570fb24e 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1779,7 +1779,7 @@ no_rtc: no_dma: ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index d755b406a6f1..62c22ccfb780 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -259,7 +259,7 @@ static int pcm3724_attach(struct comedi_device *dev, n_subdevices = board->numofports; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret < 0) + if (ret) return ret; for (i = 0; i < dev->n_subdevices; i++) { diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index 48a21bd679fd..b48f7aa7520b 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -59,6 +59,7 @@ static int pcm3730_attach(struct comedi_device *dev, { struct comedi_subdevice *s; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); @@ -71,8 +72,9 @@ static int pcm3730_attach(struct comedi_device *dev, dev->iobase = dev->iobase; dev->irq = 0; - if (comedi_alloc_subdevices(dev, 6) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 6); + if (ret) + return ret; s = dev->subdevices + 0; s->type = COMEDI_SUBD_DO; diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 00b0f2a6894c..54d19c943967 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -118,7 +118,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct pcmad_priv_struct)); diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 87faa0381976..291ce7c1bdb1 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -165,6 +165,7 @@ static int pcmda12_attach(struct comedi_device *dev, const struct pcmda12_board *board = comedi_board(dev); struct comedi_subdevice *s; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO @@ -190,8 +191,9 @@ static int pcmda12_attach(struct comedi_device *dev, devpriv->simultaneous_xfer_mode = it->options[1]; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices; s->private = NULL; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 31053034b073..0e64d848a2a8 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1020,6 +1020,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisasic_chanct = 0; unsigned long iobase; unsigned int irq[MAX_ASICS]; + int ret; iobase = it->options[0]; irq[0] = it->options[1]; @@ -1072,8 +1073,9 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; } - if (comedi_alloc_subdevices(dev, n_subdevs) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, n_subdevs); + if (ret) + return ret; /* First, AI */ sdev_no = 0; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 33ab4c63b3dc..48565fe9efcc 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -754,6 +754,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; unsigned long iobase; unsigned int irq[MAX_ASICS]; + int ret; iobase = it->options[0]; irq[0] = it->options[1]; @@ -801,8 +802,9 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; } - if (comedi_alloc_subdevices(dev, n_subdevs) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, n_subdevs); + if (ret) + return ret; port = 0; asic = 0; diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 1e954f9c4165..a129ccace93d 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -139,6 +139,7 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; unsigned long iobase; unsigned int iosize; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor, @@ -160,8 +161,10 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->iobase = iobase; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; + if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 38a13ba38e18..a029147c9b69 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -872,7 +872,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = local->link->resource[0]->start; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n", diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 445333b2413e..c3c8097acd02 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1999,9 +1999,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Show board configuration */ printk(KERN_INFO "%s:", dev->board_name); - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; - + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = dev->subdevices + 0; dev->read_subdev = s; diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index a80f6302375b..966ac2ccc877 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -349,7 +349,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = board->name; ret = comedi_alloc_subdevices(dev, 4); - if (ret < 0) + if (ret) return ret; ret = alloc_private(dev, sizeof(struct rti800_private)); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 1aacf3f6e3f5..fc16508181d4 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -92,6 +92,7 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int i; unsigned long iobase; + int ret; iobase = it->options[0]; printk(KERN_INFO "comedi%d: rti802: 0x%04lx ", dev->minor, iobase); @@ -103,10 +104,12 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = "rti802"; - if (comedi_alloc_subdevices(dev, 1) < 0 - || alloc_private(dev, sizeof(struct rti802_private))) { + if (alloc_private(dev, sizeof(struct rti802_private))) return -ENOMEM; - } + + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices; /* ao subdevice */ diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 6a30537987c6..141bc9e881c9 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -743,6 +743,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int iobase; int i, n; + int ret; /* short value; */ /* int subdev_channel = 0; */ union cmReg cmReg; @@ -774,8 +775,9 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct s526_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 4) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = dev->subdevices + 0; /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */ diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index f2eeca51ebfa..32e03bc247b3 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -595,8 +595,9 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = s626_boards; dev->board_name = thisboard->name; - if (comedi_alloc_subdevices(dev, 6) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 6); + if (ret) + return ret; dev->iobase = (unsigned long)devpriv->base_addr; dev->irq = devpriv->pdev->irq; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index dc41c04fae4f..e62297380786 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -780,6 +780,7 @@ static int serial2002_attach(struct comedi_device *dev, { const struct serial2002_board *board = comedi_board(dev); struct comedi_subdevice *s; + int ret; dev_dbg(dev->hw_dev, "comedi%d: attached\n", dev->minor); dev->board_name = board->name; @@ -792,8 +793,9 @@ static int serial2002_attach(struct comedi_device *dev, dev_dbg(dev->hw_dev, "/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed); - if (comedi_alloc_subdevices(dev, 5) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 5); + if (ret) + return ret; /* digital input subdevice */ s = dev->subdevices + 0; diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index ca10b1a98153..92d44c1d2587 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -210,6 +210,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round); static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int ret; pr_info("comedi%d: skel: ", dev->minor); @@ -233,8 +234,9 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct skel_private)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 3) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; s = dev->subdevices + 0; /* dev->read_subdev=s; */ diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 130e4bd5c640..b12bafe9baf6 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -187,6 +187,7 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct dnp_board *board = comedi_board(dev); struct comedi_subdevice *s; + int ret; printk(KERN_INFO "comedi%d: dnp: ", dev->minor); @@ -197,8 +198,9 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0) return -ENOMEM; - if (comedi_alloc_subdevices(dev, 1) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; s = dev->subdevices + 0; /* digital i/o subdevice */ diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 711dad77c598..9f1fdec62dcb 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -443,6 +443,7 @@ static int unioxx5_attach(struct comedi_device *dev, { int iobase, i, n_subd; int id, num, ba; + int ret; iobase = it->options[0]; @@ -468,8 +469,9 @@ static int unioxx5_attach(struct comedi_device *dev, return -1; } - if (comedi_alloc_subdevices(dev, n_subd) < 0) - return -ENOMEM; + ret = comedi_alloc_subdevices(dev, n_subd); + if (ret) + return ret; /* initializing each of for same subdevices */ for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) { diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index a6cf13459c61..0386fd4a80ba 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2646,7 +2646,7 @@ static int usbdux_attach_common(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, n_subdevs); - if (ret < 0) { + if (ret) { up(&udev->sem); return ret; } diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index f7d4f56c1688..2ee9ecd33539 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1667,7 +1667,7 @@ static int usbduxfast_attach(struct comedi_device *dev, dev->board_name = BOARDNAME; ret = comedi_alloc_subdevices(dev, 1); - if (ret < 0) { + if (ret) { up(&(usbduxfastsub[index].sem)); up(&start_stop_sem); return ret; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index f23fad957e5e..502a40948ebd 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2691,7 +2691,7 @@ static int usbduxsigma_attach(struct comedi_device *dev, } ret = comedi_alloc_subdevices(dev, n_subdevs); - if (ret < 0) { + if (ret) { up(&udev->sem); up(&start_stop_sem); return ret; diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 5a3e33d83c84..69402dade14b 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -1135,6 +1135,7 @@ static int vmk80xx_attach(struct comedi_device *cdev, int n_subd; struct comedi_subdevice *s; int minor; + int ret; mutex_lock(&glb_mutex); @@ -1159,10 +1160,11 @@ static int vmk80xx_attach(struct comedi_device *cdev, else n_subd = 6; - if (comedi_alloc_subdevices(cdev, n_subd) < 0) { + ret = comedi_alloc_subdevices(cdev, n_subd); + if (ret) { up(&dev->limit_sem); mutex_unlock(&glb_mutex); - return -ENOMEM; + return ret; } /* Analog input subdevice */ -- GitLab From 03afcf472785a63d720202d28d51852d965a95d9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 11:59:55 -0700 Subject: [PATCH 0579/5711] staging: comedi: cleanup comedi_alloc_subdevices Access the individual comedi_subdevices using a pointer instead of directly accessing as an array. This is how the rest of the comedi core accesses them. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index ecad2288c9fb..6af4a5b302df 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -58,21 +58,24 @@ struct comedi_driver *comedi_drivers; int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { + struct comedi_subdevice *s; int i; if (num_subdevices < 1) return -EINVAL; - dev->subdevices = - kcalloc(num_subdevices, sizeof(struct comedi_subdevice), - GFP_KERNEL); - if (!dev->subdevices) + + s = kcalloc(num_subdevices, sizeof(*s), GFP_KERNEL); + if (!s) return -ENOMEM; + dev->subdevices = s; dev->n_subdevices = num_subdevices; + for (i = 0; i < num_subdevices; ++i) { - dev->subdevices[i].device = dev; - dev->subdevices[i].async_dma_dir = DMA_NONE; - spin_lock_init(&dev->subdevices[i].spin_lock); - dev->subdevices[i].minor = -1; + s = dev->subdevices + i; + s->device = dev; + s->async_dma_dir = DMA_NONE; + spin_lock_init(&s->spin_lock); + s->minor = -1; } return 0; } -- GitLab From 17c88eb6a09bafb75644b8c37fd65c89c8f49bec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jun 2012 09:54:03 +0300 Subject: [PATCH 0580/5711] iio: frequency: ad9523: unlock on error in ad9523_reg_access() There was a return path which got missed accidentally. Signed-off-by: Dan Carpenter Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/iio/frequency/ad9523.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 7272924484c1..832e6ab26114 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -731,10 +731,12 @@ static int ad9523_reg_access(struct iio_dev *indio_dev, } else { ret = ad9523_read(indio_dev, reg | AD9523_R1B); if (ret < 0) - return ret; + goto out_unlock; *readval = ret; ret = 0; } + +out_unlock: mutex_unlock(&indio_dev->mlock); return ret; -- GitLab From 227d5e0040ff18b6258ef6680e3c54150bb6b8b1 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 8 Jun 2012 08:54:17 +0200 Subject: [PATCH 0581/5711] iio: remove indio_dev pointer from max517_data Signed-off-by: Peter Meerwald Acked-by: Roland Stigge Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/dac/max517.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index 92c77c82026c..352abe2004a4 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -43,7 +43,6 @@ enum max517_device_ids { }; struct max517_data { - struct iio_dev *indio_dev; struct i2c_client *client; unsigned short vref_mv[2]; }; -- GitLab From f9eb89e97dec966981494c75ef7dc41630b0cb43 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 8 Jun 2012 08:54:18 +0200 Subject: [PATCH 0582/5711] iio: max517: mark probe() and remove() with __devinit and __devexit Signed-off-by: Peter Meerwald Acked-by: Roland Stigge Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/dac/max517.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index 352abe2004a4..c3d748c25939 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -156,7 +156,7 @@ static const struct iio_chan_spec max517_channels[] = { MAX517_CHANNEL(1) }; -static int max517_probe(struct i2c_client *client, +static int __devinit max517_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max517_data *data; @@ -210,7 +210,7 @@ exit: return err; } -static int max517_remove(struct i2c_client *client) +static int __devexit max517_remove(struct i2c_client *client) { iio_device_unregister(i2c_get_clientdata(client)); iio_device_free(i2c_get_clientdata(client)); @@ -232,7 +232,7 @@ static struct i2c_driver max517_driver = { .pm = MAX517_PM_OPS, }, .probe = max517_probe, - .remove = max517_remove, + .remove = __devexit_p(max517_remove), .id_table = max517_id, }; module_i2c_driver(max517_driver); -- GitLab From e86ee142a223ec85efda7c66b3e99fe79aa8cc4f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jun 2012 09:55:37 +0300 Subject: [PATCH 0583/5711] iio: frequency: adf4350: fix an initialization Sparse complains about this: drivers/iio/frequency/adf4350.c:58:29: warning: Initializer entry defined twice drivers/iio/frequency/adf4350.c:59:10: also defined here It looks like '|' was intended here instead of ','. Signed-off-by: Dan Carpenter Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/iio/frequency/adf4350.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 2d09f82d9752..6ce45f5c0deb 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -54,7 +54,7 @@ struct adf4350_state { static struct adf4350_platform_data default_pdata = { .clkin = 122880000, .channel_spacing = 10000, - .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS | ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | -- GitLab From 1a135d1ab5e3122ab2a50cbbdb9cb1504c1f421f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jun 2012 09:54:32 +0300 Subject: [PATCH 0584/5711] iio: frequency: adf4350: using an uninitialized variable GCC complains that we use an uninitialized variable if the user passes an invalid parameter to adf4350_read(). I decided that we should return -EINVAL instead in that case. However, when I looked up at adf4350_write() it returned -ENODEV for that condition. In the end, I decided the -EINVAL was the right thing and I change adf4350_write() to match. Signed-off-by: Dan Carpenter Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/iio/frequency/adf4350.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 6ce45f5c0deb..59fbb3ae40e7 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -272,7 +272,7 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev, adf4350_sync_config(st); break; default: - ret = -ENODEV; + ret = -EINVAL; } mutex_unlock(&indio_dev->mlock); @@ -311,7 +311,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, val = !!(st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); break; default: - ret = -ENODEV; + ret = -EINVAL; } mutex_unlock(&indio_dev->mlock); -- GitLab From cf35ad61aca2c0c8983fa1e140c901f6588aba7e Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 8 Jun 2012 18:06:45 +0200 Subject: [PATCH 0585/5711] iio: add mcp4725 I2C DAC driver v5: * fix warnings (Jonathan Cameron) v4: * remove unused indio_dev pointer in mcp4725_data (Jonathan Cameron) * use u16 instead of unsigned short in mcp4725_data (Jonathan Cameron) * #include mcp4725.h from linux/iio/dac/ v3: * move from staging to drivers/iio * switch to chan_spec * dev_get_drvdata() -> dev_to_iio_dev() * annotate probe() and remove() with __devinit and __devexit v2 (based on comments from Jonathan Cameron and Lars-Peter Clausen): * did NOT switch to chan_spec yet * rebase to staging-next tree, update iio header locations * dropped dac.h #include, not needed * strict_strtol() -> kstrtol() * call iio_device_unregister() in remove() * everything in one patch Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/dac/Kconfig | 11 ++ drivers/iio/dac/Makefile | 1 + drivers/iio/dac/mcp4725.c | 227 ++++++++++++++++++++++++++++++++ include/linux/iio/dac/mcp4725.h | 16 +++ 4 files changed, 255 insertions(+) create mode 100644 drivers/iio/dac/mcp4725.c create mode 100644 include/linux/iio/dac/mcp4725.h diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index a626f03871ec..92fb3a003510 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -118,4 +118,15 @@ config MAX517 This driver can also be built as a module. If so, the module will be called max517. +config MCP4725 + tristate "MCP4725 DAC driver" + depends on I2C + ---help--- + Say Y here if you want to build a driver for the Microchip + MCP 4725 12-bit digital-to-analog converter (DAC) with I2C + interface. + + To compile this driver as a module, choose M here: the module + will be called mcp4725. + endmenu diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 8ab1d264aab7..9ea3ceeefc07 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_MAX517) += max517.o +obj-$(CONFIG_MCP4725) += mcp4725.o diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c new file mode 100644 index 000000000000..e0e168bd5b45 --- /dev/null +++ b/drivers/iio/dac/mcp4725.c @@ -0,0 +1,227 @@ +/* + * mcp4725.c - Support for Microchip MCP4725 + * + * Copyright (C) 2012 Peter Meerwald + * + * Based on max517 by Roland Stigge + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC) + * (7-bit I2C slave address 0x60, the three LSBs can be configured in + * hardware) + * + * writing the DAC value to EEPROM is not supported + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define MCP4725_DRV_NAME "mcp4725" + +struct mcp4725_data { + struct i2c_client *client; + u16 vref_mv; + u16 dac_value; +}; + +#ifdef CONFIG_PM_SLEEP +static int mcp4725_suspend(struct device *dev) +{ + u8 outbuf[2]; + + outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */ + outbuf[1] = 0; + + return i2c_master_send(to_i2c_client(dev), outbuf, 2); +} + +static int mcp4725_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct mcp4725_data *data = iio_priv(indio_dev); + u8 outbuf[2]; + + /* restore previous DAC value */ + outbuf[0] = (data->dac_value >> 8) & 0xf; + outbuf[1] = data->dac_value & 0xff; + + return i2c_master_send(to_i2c_client(dev), outbuf, 2); +} + +static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume); +#define MCP4725_PM_OPS (&mcp4725_pm_ops) +#else +#define MCP4725_PM_OPS NULL +#endif + +static const struct iio_chan_spec mcp4725_channel = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_type = IIO_ST('u', 12, 16, 0), +}; + +static int mcp4725_set_value(struct iio_dev *indio_dev, int val) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + u8 outbuf[2]; + int ret; + + if (val >= (1 << 12) || val < 0) + return -EINVAL; + + outbuf[0] = (val >> 8) & 0xf; + outbuf[1] = val & 0xff; + + ret = i2c_master_send(data->client, outbuf, 2); + if (ret < 0) + return ret; + else if (ret != 2) + 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) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + unsigned long scale_uv; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val = data->dac_value; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (data->vref_mv * 1000) >> 12; + *val = scale_uv / 1000000; + *val2 = scale_uv % 1000000; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int mcp4725_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = mcp4725_set_value(indio_dev, val); + data->dac_value = val; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct iio_info mcp4725_info = { + .read_raw = mcp4725_read_raw, + .write_raw = mcp4725_write_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit 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 *platform_data = client->dev.platform_data; + u8 inbuf[3]; + int err; + + if (!platform_data || !platform_data->vref_mv) { + dev_err(&client->dev, "invalid platform data"); + err = -EINVAL; + goto exit; + } + + indio_dev = iio_device_alloc(sizeof(*data)); + if (indio_dev == NULL) { + err = -ENOMEM; + goto exit; + } + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &mcp4725_info; + indio_dev->channels = &mcp4725_channel; + 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"); + goto exit_free_device; + } + data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); + + err = iio_device_register(indio_dev); + if (err) + goto exit_free_device; + + dev_info(&client->dev, "MCP4725 DAC registered\n"); + + return 0; + +exit_free_device: + iio_device_free(indio_dev); +exit: + return err; +} + +static int __devexit mcp4725_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static const struct i2c_device_id mcp4725_id[] = { + { "mcp4725", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mcp4725_id); + +static struct i2c_driver mcp4725_driver = { + .driver = { + .name = MCP4725_DRV_NAME, + .pm = MCP4725_PM_OPS, + }, + .probe = mcp4725_probe, + .remove = __devexit_p(mcp4725_remove), + .id_table = mcp4725_id, +}; +module_i2c_driver(mcp4725_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("MCP4725 12-bit DAC"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h new file mode 100644 index 000000000000..91530e6611e9 --- /dev/null +++ b/include/linux/iio/dac/mcp4725.h @@ -0,0 +1,16 @@ +/* + * MCP4725 DAC driver + * + * Copyright (C) 2012 Peter Meerwald + * + * Licensed under the GPL-2 or later. + */ + +#ifndef IIO_DAC_MCP4725_H_ +#define IIO_DAC_MCP4725_H_ + +struct mcp4725_platform_data { + u16 vref_mv; +}; + +#endif /* IIO_DAC_MCP4725_H_ */ -- GitLab From 011c10c351f3f081b496e2197db2948d120cc26c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 11 Jun 2012 09:51:04 +0200 Subject: [PATCH 0586/5711] iio: ad9523: Fix argument type mismatch drivers/iio/frequency/ad9523.c:378 ad9523_vco_out_map() warn: value 2 can't fit into 1 'out' Signed-off-by: Michael Hennerich Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/iio/frequency/ad9523.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 832e6ab26114..b737c64a402d 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -361,7 +361,7 @@ static int ad9523_io_update(struct iio_dev *indio_dev) } static int ad9523_vco_out_map(struct iio_dev *indio_dev, - unsigned ch, bool out) + unsigned ch, unsigned out) { struct ad9523_state *st = iio_priv(indio_dev); int ret; -- GitLab From 988bb033d703c8b2e0e71c63f3f55616a0220ced Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 14:39:37 +0200 Subject: [PATCH 0587/5711] iio: drop comment about 'real' channels Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 1b073b1cc7c2..d086736a9033 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -11,7 +11,6 @@ #define _IIO_TYPES_H_ enum iio_chan_type { - /* real channel types */ IIO_VOLTAGE, IIO_CURRENT, IIO_POWER, -- GitLab From 8b417d78ea486280bf8e908e76214c44c533ed3d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 15:31:27 +0200 Subject: [PATCH 0588/5711] iio: nitpicking on sysfs-bus-iio v2: address comments by Jonathan Cameron * add more output power down modes * spelling of etc. Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-iio | 50 +++++++++++++------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 5bc8a476c15e..e0f68f6a0e2a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -40,9 +40,9 @@ Contact: linux-iio@vger.kernel.org Description: Some devices have internal clocks. This parameter sets the resulting sampling frequency. In many devices this - parameter has an effect on input filters etc rather than + parameter has an effect on input filters etc. rather than simply controlling when the input is sampled. As this - effects datardy triggers, hardware buffers and the sysfs + effects data ready triggers, hardware buffers and the sysfs direct access interfaces, it may be found in any of the relevant directories. If it effects all of the above then it is to be found in the base device directory. @@ -74,7 +74,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Raw (unscaled no bias removal etc) voltage measurement from + Raw (unscaled no bias removal etc.) voltage measurement from channel Y. In special cases where the channel does not correspond to externally available input one of the named versions may be used. The number must always be specified and @@ -118,7 +118,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_temp_z_raw KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Raw (unscaled no bias removal etc) temperature measurement. + Raw (unscaled no bias removal etc.) temperature measurement. If an axis is specified it generally means that the temperature sensor is associated with one part of a compound device (e.g. a gyroscope axis). Units after application of scale and offset @@ -148,10 +148,9 @@ KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: Angular velocity about axis x, y or z (may be arbitrarily - assigned) Data converted by application of offset then scale to - radians per second. Has all the equivalent parameters as - per voltageY. Units after application of scale and offset are - radians per second. + assigned). Has all the equivalent parameters as per voltageY. + Units after application of scale and offset are radians per + second. What: /sys/bus/iio/devices/iio:deviceX/in_incli_x_raw What: /sys/bus/iio/devices/iio:deviceX/in_incli_y_raw @@ -161,7 +160,7 @@ Contact: linux-iio@vger.kernel.org Description: Inclination raw reading about axis x, y or z (may be arbitrarily assigned). Data converted by application of offset - and scale to Degrees. + and scale to degrees. What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_raw What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_raw @@ -203,7 +202,7 @@ Contact: linux-iio@vger.kernel.org Description: If known for a device, offset to be added to [Y]_raw prior to scaling by [Y]_scale in order to obtain value in the - units as specified in [y]_raw documentation. + units as specified in [Y]_raw documentation. Not present if the offset is always 0 or unknown. If Y or axis is not present, then the offset applies to all in channels of . @@ -248,7 +247,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Hardware applied calibration offset. (assumed to fix production + Hardware applied calibration offset (assumed to fix production inaccuracies). What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale @@ -265,7 +264,7 @@ what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Hardware applied calibration scale factor. (assumed to fix + Hardware applied calibration scale factor (assumed to fix production inaccuracies). If shared across all channels, _calibscale is used. @@ -277,7 +276,7 @@ What: /sys/.../iio:deviceX/in_capacitance_scale_available KernelVersion: 2.635 Contact: linux-iio@vger.kernel.org Description: - If a discrete set of scale values are available, they + If a discrete set of scale values is available, they are listed in this attribute. What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain @@ -321,9 +320,11 @@ Contact: linux-iio@vger.kernel.org Description: Specifies the output powerdown mode. DAC output stage is disconnected from the amplifier and - 1kohm_to_gnd: connected to ground via an 1kOhm resistor - 100kohm_to_gnd: connected to ground via an 100kOhm resistor - three_state: left floating + 1kohm_to_gnd: connected to ground via an 1kOhm resistor, + 6kohm_to_gnd: connected to ground via a 6kOhm resistor, + 20kohm_to_gnd: connected to ground via a 20kOhm resistor, + 100kohm_to_gnd: connected to ground via an 100kOhm resistor, + three_state: left floating. For a list of available output power down options read outX_powerdown_mode_available. If Y is not present the mode is shared across all outputs. @@ -342,9 +343,10 @@ KernelVersion: 2.6.38 Contact: linux-iio@vger.kernel.org Description: Writing 1 causes output Y to enter the power down mode specified - by the corresponding outY_powerdown_mode. Clearing returns to - normal operation. Y may be suppressed if all outputs are - controlled together. + by the corresponding outY_powerdown_mode. DAC output stage is + disconnected from the amplifier. Clearing returns to normal + operation. Y may be suppressed if all outputs are controlled + together. What: /sys/bus/iio/devices/iio:deviceX/events KernelVersion: 2.6.35 @@ -390,12 +392,12 @@ Description: different values, but the device can only enable both thresholds or neither. Note the driver will assume the last p events requested are - to be enabled where p is however many it supports (which may - vary depending on the exact set requested. So if you want to be + to be enabled where p is how many it supports (which may vary + depending on the exact set requested. So if you want to be sure you have set what you think you have, check the contents of these attributes after everything is configured. Drivers may have to buffer any parameters so that they are consistent when - a given event type is enabled a future point (and not those for + a given event type is enabled at a future point (and not those for whatever event was previously enabled). What: /sys/.../iio:deviceX/events/in_accel_x_roc_rising_en @@ -671,7 +673,7 @@ What: /sys/.../buffer/scan_elements/in_anglvel_type What: /sys/.../buffer/scan_elements/in_magn_type What: /sys/.../buffer/scan_elements/in_incli_type What: /sys/.../buffer/scan_elements/in_voltageY_type -What: /sys/.../buffer/scan_elements/in_voltage-in_type +What: /sys/.../buffer/scan_elements/in_voltage_type What: /sys/.../buffer/scan_elements/in_voltageY_supply_type What: /sys/.../buffer/scan_elements/in_timestamp_type KernelVersion: 2.6.37 @@ -692,7 +694,7 @@ Description: the buffer output value appropriately. The storagebits value also specifies the data alignment. So s48/64>>2 will be a signed 48 bit integer stored in a 64 bit location aligned to - a a64 bit boundary. To obtain the clean value, shift right 2 + a 64 bit boundary. To obtain the clean value, shift right 2 and apply a mask to zero the top 16 bits of the result. For other storage combinations this attribute will be extended appropriately. -- GitLab From 1787948873fd2ca730fb5891b6a2ade510367ace Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 15:38:45 +0200 Subject: [PATCH 0589/5711] iio: fix typos in iio.h v2: * "used in in-kernel" (Jonathan Cameron) Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 944c63511731..01afaa08ff21 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -131,7 +131,7 @@ struct iio_chan_spec_ext_info { /** * struct iio_enum - Enum channel info attribute - * items: A array of strings. + * items: An array of strings. * num_items: Length of the item array. * set: Set callback function, may be NULL. * get: Get callback function, may be NULL. @@ -218,7 +218,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * @extend_name: Allows labeling of channel attributes with an * informative name. Note this has no effect codes etc, * unlike modifiers. - * @datasheet_name: A name used in in kernel mapping of channels. It should + * @datasheet_name: A name used in in-kernel mapping of channels. It should * correspond to the first name that the channel is referred * to by in the datasheet (e.g. IND), or the nearest * possible compound name (e.g. IND-INC). @@ -393,7 +393,7 @@ struct iio_buffer_setup_ops { * @trig: [INTERN] current device trigger (buffer modes) * @pollfunc: [DRIVER] function run on trigger being received * @channels: [DRIVER] channel specification structure table - * @num_channels: [DRIVER] number of chanels specified in @channels. + * @num_channels: [DRIVER] number of channels specified in @channels. * @channel_attr_list: [INTERN] keep track of automatically created channel * attributes * @chan_attr_group: [INTERN] group for all attrs in base directory -- GitLab From a16561c6f713630270b905297f3eedf02db7fa98 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 15:38:46 +0200 Subject: [PATCH 0590/5711] iio: clarify channel and indexed in struct iio_chan_spec Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 01afaa08ff21..9a9e6d52a6de 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -196,7 +196,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, /** * struct iio_chan_spec - specification of a single channel * @type: What type of measurement is the channel making. - * @channel: What number or name do we wish to assign the channel. + * @channel: What number do we wish to assign the channel. * @channel2: If there is a second number for a differential * channel then this is it. If modified is set then the * value here specifies the modifier. @@ -227,9 +227,8 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * channel2. Examples are IIO_MOD_X for axial sensors about * the 'x' axis. * @indexed: Specify the channel has a numerical index. If not, - * the value in channel will be suppressed for attribute - * but not for event codes. Typically set it to 0 when - * the index is false. + * the channel index number will be suppressed for sysfs + * attributes but not for event codes. * @differential: Channel is differential. */ struct iio_chan_spec { -- GitLab From f4c349395e8ad4fe07f1222502568f0d9d5d1dfc Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 15:38:47 +0200 Subject: [PATCH 0591/5711] iio: mark struct iio_enum elements with @ in comment Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 9a9e6d52a6de..bd3e7217ceee 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -131,10 +131,10 @@ struct iio_chan_spec_ext_info { /** * struct iio_enum - Enum channel info attribute - * items: An array of strings. - * num_items: Length of the item array. - * set: Set callback function, may be NULL. - * get: Get callback function, may be NULL. + * @items: An array of strings. + * @num_items: Length of the item array. + * @set: Set callback function, may be NULL. + * @get: Get callback function, may be NULL. * * The iio_enum struct can be used to implement enum style channel attributes. * Enum style attributes are those which have a set of strings which map to -- GitLab From 7dcd7b60724cab551deba54f31752fa8959efab4 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Jun 2012 15:38:48 +0200 Subject: [PATCH 0592/5711] iio: cleanup iio/iio.h indentation of parameter description, fix parameter name (@dev -> @indio_dev) in comments, IIO device info structure -> IIO device structure Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index bd3e7217ceee..ae0cad908182 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -131,10 +131,10 @@ struct iio_chan_spec_ext_info { /** * struct iio_enum - Enum channel info attribute - * @items: An array of strings. - * @num_items: Length of the item array. - * @set: Set callback function, may be NULL. - * @get: Get callback function, may be NULL. + * @items: An array of strings. + * @num_items: Length of the item array. + * @set: Set callback function, may be NULL. + * @get: Get callback function, may be NULL. * * The iio_enum struct can be used to implement enum style channel attributes. * Enum style attributes are those which have a set of strings which map to @@ -162,9 +162,9 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, /** * IIO_ENUM() - Initialize enum extended channel attribute - * @_name: Attribute name - * @_shared: Whether the attribute is shared between all channels - * @_e: Pointer to a iio_enum struct + * @_name: Attribute name + * @_shared: Whether the attribute is shared between all channels + * @_e: Pointer to a iio_enum struct * * This should usually be used together with IIO_ENUM_AVAILABLE() */ @@ -179,8 +179,8 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, /** * IIO_ENUM_AVAILABLE() - Initialize enum available extended channel attribute - * @_name: Attribute name ("_available" will be appended to the name) - * @_e: Pointer to a iio_enum struct + * @_name: Attribute name ("_available" will be appended to the name) + * @_e: Pointer to a iio_enum struct * * Creates a read only attribute which list all the available enum items in a * space separated list. This should usually be used together with IIO_ENUM() @@ -201,7 +201,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * channel then this is it. If modified is set then the * value here specifies the modifier. * @address: Driver specific identifier. - * @scan_index: Monotonic index to give ordering in scans when read + * @scan_index: Monotonic index to give ordering in scans when read * from a buffer. * @scan_type: Sign: 's' or 'u' to specify signed or unsigned * realbits: Number of valid bits of data @@ -211,7 +211,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * endianness: little or big endian * @info_mask: What information is to be exported about this channel. * This includes calibbias, scale etc. - * @event_mask: What events can this channel produce. + * @event_mask: What events can this channel produce. * @ext_info: Array of extended info attributes for this channel. * The array is NULL terminated, the last element should * have it's name field set to NULL. @@ -482,7 +482,7 @@ extern struct bus_type iio_bus_type; /** * iio_device_put() - reference counted deallocation of struct device - * @dev: the iio_device containing the device + * @indio_dev: IIO device structure containing the device **/ static inline void iio_device_put(struct iio_dev *indio_dev) { @@ -492,7 +492,7 @@ static inline void iio_device_put(struct iio_dev *indio_dev) /** * dev_to_iio_dev() - Get IIO device struct from a device struct - * @dev: The device embedded in the IIO device + * @dev: The device embedded in the IIO device * * Note: The device must be a IIO device, otherwise the result is undefined. */ @@ -503,7 +503,7 @@ static inline struct iio_dev *dev_to_iio_dev(struct device *dev) /** * iio_device_get() - increment reference count for the device - * @indio_dev: IIO device structure + * @indio_dev: IIO device structure * * Returns: The passed IIO device **/ @@ -516,7 +516,7 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev) #define IIO_ALIGN L1_CACHE_BYTES /** * iio_device_alloc() - allocate an iio_dev from a driver - * @sizeof_priv: Space to allocate for private structure. + * @sizeof_priv: Space to allocate for private structure. **/ struct iio_dev *iio_device_alloc(int sizeof_priv); @@ -533,13 +533,13 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) /** * iio_device_free() - free an iio_dev from a driver - * @dev: the iio_dev associated with the device + * @indio_dev: the iio_dev associated with the device **/ void iio_device_free(struct iio_dev *indio_dev); /** * iio_buffer_enabled() - helper function to test if the buffer is enabled - * @indio_dev: IIO device info structure for device + * @indio_dev: IIO device structure for device **/ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) { @@ -549,7 +549,7 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) /** * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry - * @indio_dev: IIO device info structure for device + * @indio_dev: IIO device structure for device **/ #if defined(CONFIG_DEBUG_FS) static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) -- GitLab From 59d4467be405316916a4087d5b02d99196eeef04 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 1 May 2012 11:49:24 -0700 Subject: [PATCH 0593/5711] w1: introduce a slave mutex for serializing IO w1 devices need a mutex to serial IO. Most use master->mutex. However that is used for other purposes and they can conflict. In particular master->mutex is held while w1_attach_slave_device is called. For bq27000, this registers a 'powersupply' device which tries to read the current status. The attempt to read will cause a deadlock on master->mutex. So create a new per-slave mutex and use that for serializing IO for bq27000. Signed-off-by: NeilBrown Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/slaves/w1_bq27000.c | 4 ++-- drivers/w1/w1.c | 1 + drivers/w1/w1.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 52ad812fa1e7..87554788fa32 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c @@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg) u8 val; struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->mutex); w1_write_8(sl->master, HDQ_CMD_READ | reg); val = w1_read_8(sl->master); - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->mutex); return val; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 2f2e894ea0c8..69075c3dfc73 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -688,6 +688,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); atomic_set(&sl->refcnt, 0); init_completion(&sl->released); + mutex_init(&sl->mutex); spin_lock(&w1_flock); f = w1_family_registered(rn->family); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 4d012ca3f32c..8c8be380a98a 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -75,6 +75,7 @@ struct w1_slave void *family_data; struct device dev; struct completion released; + struct mutex mutex; }; typedef void (*w1_slave_found_callback)(struct w1_master *, u64); -- GitLab From 526be41625a8b2282d5720dcb19f927edbf193b4 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 19 May 2012 07:31:54 +0400 Subject: [PATCH 0594/5711] w1: cleanup w1_uevent There were some return statements around in the w1_uevent, used goto to cleanup those return statements with the help of err variable, and also removed a semi colon at the end of the w1_uevent's closing brace. Signed-off-by: Devendra Naga Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 69075c3dfc73..79e488db5104 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -557,7 +557,7 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) struct w1_master *md = NULL; struct w1_slave *sl = NULL; char *event_owner, *name; - int err; + int err = 0; if (dev->driver == &w1_master_driver) { md = container_of(dev, struct w1_master, dev); @@ -576,19 +576,17 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) event_owner, name, dev_name(dev)); if (dev->driver != &w1_slave_driver || !sl) - return 0; + goto end; err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); if (err) - return err; + goto end; err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", (unsigned long long)sl->reg_num.id); - if (err) - return err; - - return 0; -}; +end: + return err; +} #else static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) { -- GitLab From 95dc690eb7cc394a7b5749ecf0118e2f2e011e69 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 15:58:29 -0700 Subject: [PATCH 0595/5711] staging: comedi: remove check for PCI_SUPPORT_VER1 This symbol is not defined in the kernel. It appears to be left over from the 2.4 kernel. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h | 4 ---- drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h index d70ac8bb6228..95f7dc61cd00 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h @@ -22,10 +22,6 @@ #include "../../comedidev.h" -#ifdef PCI_SUPPORT_VER1 -#error No support for 2.1.55 and older -#endif - /* written on base0 */ #define FIFO_ADVANCE_ON_BYTE_2 0x20000000 diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h index 349e93c23e91..c26c28c31b97 100644 --- a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h +++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h @@ -23,10 +23,6 @@ #include #include "../../comedidev.h" -#ifdef PCI_SUPPORT_VER1 -#error Sorry, no support for 2.1.55 and older! :-(((( -#endif - /***********Added by sarath for compatibility with APCI3120 *************************/ -- GitLab From 85f243912b99b053ce0624c30609f5d8fd4445d2 Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Wed, 13 Jun 2012 10:09:51 +0200 Subject: [PATCH 0596/5711] ASoC: Ux500: Correct license strings GPLv2 -> GPL v2 Reported-by: Stephen Rothwell Signed-off-by: Ola Lilja Acked-by: Linus Walleij Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 2 +- sound/soc/ux500/ux500_msp_dai.c | 2 +- sound/soc/ux500/ux500_msp_i2s.c | 2 +- sound/soc/ux500/ux500_pcm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 95dc7d5bb076..389dd660b511 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2518,4 +2518,4 @@ static struct platform_driver ab8500_codec_platform_driver = { }; module_platform_driver(ab8500_codec_platform_driver); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 93c6c40e724c..62ac0285bfaf 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -840,4 +840,4 @@ static struct platform_driver msp_i2s_driver = { }; module_platform_driver(msp_i2s_driver); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 496dec10c96e..ee14d2dac2f5 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -739,4 +739,4 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, devm_kfree(&pdev->dev, msp); } -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 66b080e5de96..97d8e4de29c2 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -315,4 +315,4 @@ static struct platform_driver ux500_pcm_driver = { }; module_platform_driver(ux500_pcm_driver); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); -- GitLab From 8994a5e1d2443511e677d62e97d7de3718b71325 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jun 2012 14:36:07 +0800 Subject: [PATCH 0597/5711] ASoC: ml26124: Convert to devm_regmap_init_i2c This fixes a leak if snd_soc_register_codec fails. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/ml26124.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 22cb5bf59273..96aa5fa05160 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -638,7 +638,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, priv); - priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap); + priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap); if (IS_ERR(priv->regmap)) { ret = PTR_ERR(priv->regmap); dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); @@ -651,10 +651,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, static __devexit int ml26124_i2c_remove(struct i2c_client *client) { - struct ml26124_priv *priv = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(priv->regmap); return 0; } -- GitLab From e188719a2891f01b3100dca4ae3a055fb5a7ab52 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 12 Jun 2012 11:28:17 +0200 Subject: [PATCH 0598/5711] drm/i915: kick any firmware framebuffers before claiming the gtt Especially vesafb likes to map everything as uc- (yikes), and if that mapping hangs around still while we try to map the gtt as wc the kernel will downgrade our request to uc-, resulting in abyssal performance. Unfortunately we can't do this as early as readon does (i.e. as the first thing we do when initializing the hw) because our fb/mmio space region moves around on a per-gen basis. So I've had to move it below the gtt initialization, but that seems to work, too. The important thing is that we do this before we set up the gtt wc mapping. Now an altogether different question is why people compile their kernels with vesafb enabled, but I guess making things just work isn't bad per se ... v2: - s/radeondrmfb/inteldrmfb/ - fix up error handling v3: Kill #ifdef X86, this is Intel after all. Noticed by Ben Widawsky. v4: Jani Nikula complained about the pointless bool primary initialization. v5: Don't oops if we can't allocate, noticed by Chris Wilson. v6: Resolve conflicts with agp rework and fixup whitespace. Reported-and-tested-by: "Kilarski, Bernard R" Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 57 +++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index cf512e7178b4..fa8f2699344b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1404,6 +1404,27 @@ i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base, } } +static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) +{ + struct apertures_struct *ap; + struct pci_dev *pdev = dev_priv->dev->pdev; + bool primary; + + ap = alloc_apertures(1); + if (!ap) + return; + + ap->ranges[0].base = dev_priv->dev->agp->base; + ap->ranges[0].size = + dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + primary = + pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; + + remove_conflicting_framebuffers(ap, "inteldrmfb", primary); + + kfree(ap); +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -1449,6 +1470,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); + if (!ret) { + DRM_ERROR("failed to set up gmch\n"); + ret = -EIO; + goto put_bridge; + } + + dev_priv->mm.gtt = intel_gtt_get(); + if (!dev_priv->mm.gtt) { + DRM_ERROR("Failed to initialize GTT\n"); + ret = -ENODEV; + goto put_gmch; + } + + i915_kick_out_firmware_fb(dev_priv); + pci_set_master(dev->pdev); /* overlay on gen2 is broken and can't address above 1G */ @@ -1471,20 +1508,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); ret = -EIO; - goto put_bridge; - } - - ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); - if (!ret) { - DRM_ERROR("failed to set up gmch\n"); - ret = -EIO; - goto out_rmmap; - } - - dev_priv->mm.gtt = intel_gtt_get(); - if (!dev_priv->mm.gtt) { - DRM_ERROR("Failed to initialize GTT\n"); - ret = -ENODEV; goto put_gmch; } @@ -1496,7 +1519,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) aperture_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; - goto put_gmch; + goto out_rmmap; } i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, @@ -1618,10 +1641,10 @@ out_mtrrfree: dev_priv->mm.gtt_mtrr = -1; } io_mapping_free(dev_priv->mm.gtt_mapping); -put_gmch: - intel_gmch_remove(); out_rmmap: pci_iounmap(dev->pdev, dev_priv->regs); +put_gmch: + intel_gmch_remove(); put_bridge: pci_dev_put(dev_priv->bridge_dev); free_priv: -- GitLab From 7a824e214e25a49442fe868dac0af8a904b24f58 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Mon, 11 Jun 2012 18:04:38 +0800 Subject: [PATCH 0599/5711] ASoC: mmp: add audio dma support mmp-pcm handle audio dma based on soc-dmaengine Support mmp and pxa910 Signed-off-by: Zhangfei Gao Signed-off-by: Leo Yan Signed-off-by: Qiao Zhou Signed-off-by: Mark Brown --- include/linux/platform_data/mmp_audio.h | 22 ++ sound/soc/pxa/Kconfig | 9 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mmp-pcm.c | 297 ++++++++++++++++++++++++ 4 files changed, 330 insertions(+) create mode 100644 include/linux/platform_data/mmp_audio.h create mode 100644 sound/soc/pxa/mmp-pcm.c diff --git a/include/linux/platform_data/mmp_audio.h b/include/linux/platform_data/mmp_audio.h new file mode 100644 index 000000000000..0f25d165abd6 --- /dev/null +++ b/include/linux/platform_data/mmp_audio.h @@ -0,0 +1,22 @@ +/* + * MMP Platform AUDIO Management + * + * Copyright (c) 2011 Marvell Semiconductors 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 MMP_AUDIO_H +#define MMP_AUDIO_H + +struct mmp_audio_platdata { + u32 period_max_capture; + u32 buffer_max_capture; + u32 period_max_playback; + u32 buffer_max_playback; +}; + +#endif /* MMP_AUDIO_H */ diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index a0f7d3cfa470..5d76e2971fbe 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -8,6 +8,15 @@ config SND_PXA2XX_SOC the PXA2xx AC97, I2S or SSP interface. You will also need to select the audio interfaces to support below. +config SND_MMP_SOC + bool "Soc Audio for Marvell MMP chips" + depends on ARCH_MMP + select SND_SOC_DMAENGINE_PCM + select SND_ARM + help + Say Y if you want to add support for codecs attached to + the MMP SSPA interface. + config SND_PXA2XX_AC97 tristate select SND_AC97_CODEC diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index af357623be9d..f913e9bfce4f 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -3,11 +3,13 @@ snd-soc-pxa2xx-objs := pxa2xx-pcm.o snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o snd-soc-pxa-ssp-objs := pxa-ssp.o +snd-soc-mmp-objs := mmp-pcm.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o +obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o # PXA Machine Support snd-soc-corgi-objs := corgi.o diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c new file mode 100644 index 000000000000..73ac5463c9e4 --- /dev/null +++ b/sound/soc/pxa/mmp-pcm.c @@ -0,0 +1,297 @@ +/* + * linux/sound/soc/pxa/mmp-pcm.c + * + * Copyright (C) 2011 Marvell International Ltd. + * + * 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 + +struct mmp_dma_data { + int ssp_id; + struct resource *dma_res; +}; + +#define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ + SNDRV_PCM_INFO_MMAP_VALID | \ + SNDRV_PCM_INFO_INTERLEAVED | \ + SNDRV_PCM_INFO_PAUSE | \ + SNDRV_PCM_INFO_RESUME) + +#define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_pcm_hardware mmp_pcm_hardware[] = { + { + .info = MMP_PCM_INFO, + .formats = MMP_PCM_FORMATS, + .period_bytes_min = 1024, + .period_bytes_max = 2048, + .periods_min = 2, + .periods_max = 32, + .buffer_bytes_max = 4096, + .fifo_size = 32, + }, + { + .info = MMP_PCM_INFO, + .formats = MMP_PCM_FORMATS, + .period_bytes_min = 1024, + .period_bytes_max = 2048, + .periods_min = 2, + .periods_max = 32, + .buffer_bytes_max = 4096, + .fifo_size = 32, + }, +}; + +static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct pxa2xx_pcm_dma_params *dma_params; + struct dma_slave_config slave_config; + int ret; + + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + if (!dma_params) + return 0; + + ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); + if (ret) + return ret; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config.dst_addr = dma_params->dev_addr; + slave_config.dst_maxburst = 4; + } else { + slave_config.src_addr = dma_params->dev_addr; + slave_config.src_maxburst = 4; + } + + ret = dmaengine_slave_config(chan, &slave_config); + if (ret) + return ret; + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} + +static bool filter(struct dma_chan *chan, void *param) +{ + struct mmp_dma_data *dma_data = param; + bool found = false; + char *devname; + + devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name, + dma_data->ssp_id); + if ((strcmp(dev_name(chan->device->dev), devname) == 0) && + (chan->chan_id == dma_data->dma_res->start)) { + found = true; + } + + kfree(devname); + return found; +} + +static int mmp_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct platform_device *pdev = to_platform_device(rtd->platform->dev); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct mmp_dma_data *dma_data; + struct resource *r; + int ret; + + r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); + if (!r) + return -EBUSY; + + snd_soc_set_runtime_hwparams(substream, + &mmp_pcm_hardware[substream->stream]); + dma_data = devm_kzalloc(&pdev->dev, + sizeof(struct mmp_dma_data), GFP_KERNEL); + if (dma_data == NULL) + return -ENOMEM; + + dma_data->dma_res = r; + dma_data->ssp_id = cpu_dai->id; + + ret = snd_dmaengine_pcm_open(substream, filter, dma_data); + if (ret) { + devm_kfree(&pdev->dev, dma_data); + return ret; + } + + snd_dmaengine_pcm_set_data(substream, dma_data); + return 0; +} + +static int mmp_pcm_close(struct snd_pcm_substream *substream) +{ + struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct platform_device *pdev = to_platform_device(rtd->platform->dev); + + snd_dmaengine_pcm_close(substream); + devm_kfree(&pdev->dev, dma_data); + return 0; +} + +static int mmp_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long off = vma->vm_pgoff; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(runtime->dma_addr) + off, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +struct snd_pcm_ops mmp_pcm_ops = { + .open = mmp_pcm_open, + .close = mmp_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = mmp_pcm_hw_params, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = mmp_pcm_mmap, +}; + +static void mmp_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + struct gen_pool *gpool; + + gpool = sram_get_gpool("asram"); + if (!gpool) + return; + + for (stream = 0; stream < 2; stream++) { + size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; + + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + gen_pool_free(gpool, (unsigned long)buf->area, size); + buf->area = NULL; + } + + return; +} + +static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream, + int stream) +{ + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; + struct gen_pool *gpool; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = substream->pcm->card->dev; + buf->private_data = NULL; + + gpool = sram_get_gpool("asram"); + if (!gpool) + return -ENOMEM; + + buf->area = (unsigned char *)gen_pool_alloc(gpool, size); + if (!buf->area) + return -ENOMEM; + buf->addr = gen_pool_virt_to_phys(gpool, (unsigned long)buf->area); + buf->bytes = size; + return 0; +} + +int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm_substream *substream; + struct snd_pcm *pcm = rtd->pcm; + int ret = 0, stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + + ret = mmp_pcm_preallocate_dma_buffer(substream, stream); + if (ret) + goto err; + } + + return 0; + +err: + mmp_pcm_free_dma_buffers(pcm); + return ret; +} + +struct snd_soc_platform_driver mmp_soc_platform = { + .ops = &mmp_pcm_ops, + .pcm_new = mmp_pcm_new, + .pcm_free = mmp_pcm_free_dma_buffers, +}; + +static __devinit int mmp_pcm_probe(struct platform_device *pdev) +{ + struct mmp_audio_platdata *pdata = pdev->dev.platform_data; + + if (pdata) { + mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].buffer_bytes_max = + pdata->buffer_max_playback; + mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].period_bytes_max = + pdata->period_max_playback; + mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].buffer_bytes_max = + pdata->buffer_max_capture; + mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max = + pdata->period_max_capture; + } + return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform); +} + +static int __devexit mmp_pcm_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver mmp_pcm_driver = { + .driver = { + .name = "mmp-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = mmp_pcm_probe, + .remove = __devexit_p(mmp_pcm_remove), +}; + +module_platform_driver(mmp_pcm_driver); + +MODULE_AUTHOR("Leo Yan "); +MODULE_DESCRIPTION("MMP Soc Audio DMA module"); +MODULE_LICENSE("GPL"); -- GitLab From fa375d42f0e531b7ca4316ea9fd5444e01d585e8 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Mon, 11 Jun 2012 18:04:39 +0800 Subject: [PATCH 0600/5711] ASoC: mmp: add sspa support The SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified. Signed-off-by: Zhangfei Gao Signed-off-by: Leo Yan Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 3 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mmp-sspa.c | 480 +++++++++++++++++++++++++++++++++++++++ sound/soc/pxa/mmp-sspa.h | 92 ++++++++ 4 files changed, 577 insertions(+) create mode 100644 sound/soc/pxa/mmp-sspa.c create mode 100644 sound/soc/pxa/mmp-sspa.h diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 5d76e2971fbe..6c3d00b8ea0b 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -35,6 +35,9 @@ config SND_PXA_SOC_SSP tristate select PXA_SSP +config SND_MMP_SOC_SSPA + tristate + config SND_PXA2XX_SOC_CORGI tristate "SoC Audio support for Sharp Zaurus SL-C7x0" depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index f913e9bfce4f..07b841746fc3 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -4,12 +4,14 @@ snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o snd-soc-pxa-ssp-objs := pxa-ssp.o snd-soc-mmp-objs := mmp-pcm.o +snd-soc-mmp-sspa-objs := mmp-sspa.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o +obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o # PXA Machine Support snd-soc-corgi-objs := corgi.o diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c new file mode 100644 index 000000000000..4d6cb8a30fc8 --- /dev/null +++ b/sound/soc/pxa/mmp-sspa.c @@ -0,0 +1,480 @@ +/* + * linux/sound/soc/pxa/mmp-sspa.c + * Base on pxa2xx-ssp.c + * + * Copyright (C) 2011 Marvell International Ltd. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mmp-sspa.h" + +/* + * SSPA audio private data + */ +struct sspa_priv { + struct ssp_device *sspa; + struct pxa2xx_pcm_dma_params *dma_params; + struct clk *audio_clk; + struct clk *sysclk; + int dai_fmt; + int running_cnt; +}; + +static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val) +{ + __raw_writel(val, sspa->mmio_base + reg); +} + +static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg) +{ + return __raw_readl(sspa->mmio_base + reg); +} + +static void mmp_sspa_tx_enable(struct ssp_device *sspa) +{ + unsigned int sspa_sp; + + sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); + sspa_sp |= SSPA_SP_S_EN; + sspa_sp |= SSPA_SP_WEN; + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); +} + +static void mmp_sspa_tx_disable(struct ssp_device *sspa) +{ + unsigned int sspa_sp; + + sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); + sspa_sp &= ~SSPA_SP_S_EN; + sspa_sp |= SSPA_SP_WEN; + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); +} + +static void mmp_sspa_rx_enable(struct ssp_device *sspa) +{ + unsigned int sspa_sp; + + sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); + sspa_sp |= SSPA_SP_S_EN; + sspa_sp |= SSPA_SP_WEN; + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); +} + +static void mmp_sspa_rx_disable(struct ssp_device *sspa) +{ + unsigned int sspa_sp; + + sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); + sspa_sp &= ~SSPA_SP_S_EN; + sspa_sp |= SSPA_SP_WEN; + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); +} + +static int mmp_sspa_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); + + clk_enable(priv->sysclk); + clk_enable(priv->sspa->clk); + + return 0; +} + +static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); + + clk_disable(priv->sspa->clk); + clk_disable(priv->sysclk); + + return; +} + +/* + * Set the SSP ports SYSCLK. + */ +static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); + int ret = 0; + + switch (clk_id) { + case MMP_SSPA_CLK_AUDIO: + ret = clk_set_rate(priv->audio_clk, freq); + if (ret) + return ret; + break; + case MMP_SSPA_CLK_PLL: + case MMP_SSPA_CLK_VCXO: + /* not support yet */ + return -EINVAL; + default: + return -EINVAL; + } + + return 0; +} + +static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, + int source, unsigned int freq_in, + unsigned int freq_out) +{ + struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); + int ret = 0; + + switch (pll_id) { + case MMP_SYSCLK: + ret = clk_set_rate(priv->sysclk, freq_out); + if (ret) + return ret; + break; + case MMP_SSPA_CLK: + ret = clk_set_rate(priv->sspa->clk, freq_out); + if (ret) + return ret; + break; + default: + return -ENODEV; + } + + return 0; +} + +/* + * Set up the sspa dai format. The sspa port must be inactive + * before calling this function as the physical + * interface format is changed. + */ +static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai); + struct ssp_device *sspa = sspa_priv->sspa; + u32 sspa_sp, sspa_ctrl; + + /* check if we need to change anything at all */ + if (sspa_priv->dai_fmt == fmt) + return 0; + + /* we can only change the settings if the port is not in use */ + if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || + (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { + dev_err(&sspa->pdev->dev, + "can't change hardware dai format: stream is in use\n"); + return -EINVAL; + } + + /* reset port settings */ + sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; + sspa_ctrl = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + sspa_sp |= SSPA_SP_MSL; + break; + case SND_SOC_DAIFMT_CBM_CFM: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + sspa_sp |= SSPA_SP_FSP; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + sspa_sp |= SSPA_TXSP_FPER(63); + sspa_sp |= SSPA_SP_FWID(31); + sspa_ctrl |= SSPA_CTL_XDATDLY(1); + break; + default: + return -EINVAL; + } + + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); + + sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); + mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); + + /* + * FIXME: hw issue, for the tx serial port, + * can not config the master/slave mode; + * so must clean this bit. + * The master/slave mode has been set in the + * rx port. + */ + sspa_sp &= ~SSPA_SP_MSL; + mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); + + mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); + mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); + + /* Since we are configuring the timings for the format by hand + * we have to defer some things until hw_params() where we + * know parameters like the sample size. + */ + sspa_priv->dai_fmt = fmt; + return 0; +} + +/* + * Set the SSPA audio DMA parameters and sample size. + * Can be called multiple times by oss emulation. + */ +static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); + struct ssp_device *sspa = sspa_priv->sspa; + struct pxa2xx_pcm_dma_params *dma_params; + u32 sspa_ctrl; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL); + else + sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL); + + sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; + sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); + sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; + sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS); + sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS); + break; + case SNDRV_PCM_FORMAT_S16_LE: + sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); + break; + case SNDRV_PCM_FORMAT_S20_3LE: + sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS); + break; + case SNDRV_PCM_FORMAT_S24_3LE: + sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); + break; + case SNDRV_PCM_FORMAT_S32_LE: + sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS); + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); + mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); + } else { + mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); + mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0); + } + + dma_params = &sspa_priv->dma_params[substream->stream]; + dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + (sspa->phys_base + SSPA_TXD) : + (sspa->phys_base + SSPA_RXD); + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); + return 0; +} + +static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); + struct ssp_device *sspa = sspa_priv->sspa; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /* + * whatever playback or capture, must enable rx. + * this is a hw issue, so need check if rx has been + * enabled or not; if has been enabled by another + * stream, do not enable again. + */ + if (!sspa_priv->running_cnt) + mmp_sspa_rx_enable(sspa); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + mmp_sspa_tx_enable(sspa); + + sspa_priv->running_cnt++; + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sspa_priv->running_cnt--; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + mmp_sspa_tx_disable(sspa); + + /* have no capture stream, disable rx port */ + if (!sspa_priv->running_cnt) + mmp_sspa_rx_disable(sspa); + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int mmp_sspa_probe(struct snd_soc_dai *dai) +{ + struct sspa_priv *priv = dev_get_drvdata(dai->dev); + + snd_soc_dai_set_drvdata(dai, priv); + return 0; + +} + +#define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000 +#define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops mmp_sspa_dai_ops = { + .startup = mmp_sspa_startup, + .shutdown = mmp_sspa_shutdown, + .trigger = mmp_sspa_trigger, + .hw_params = mmp_sspa_hw_params, + .set_sysclk = mmp_sspa_set_dai_sysclk, + .set_pll = mmp_sspa_set_dai_pll, + .set_fmt = mmp_sspa_set_dai_fmt, +}; + +struct snd_soc_dai_driver mmp_sspa_dai = { + .probe = mmp_sspa_probe, + .playback = { + .channels_min = 1, + .channels_max = 128, + .rates = MMP_SSPA_RATES, + .formats = MMP_SSPA_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = MMP_SSPA_RATES, + .formats = MMP_SSPA_FORMATS, + }, + .ops = &mmp_sspa_dai_ops, +}; + +static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev) +{ + struct sspa_priv *priv; + struct resource *res; + + priv = devm_kzalloc(&pdev->dev, + sizeof(struct sspa_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->sspa = devm_kzalloc(&pdev->dev, + sizeof(struct ssp_device), GFP_KERNEL); + if (priv->sspa == NULL) + return -ENOMEM; + + priv->dma_params = devm_kzalloc(&pdev->dev, + 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL); + if (priv->dma_params == NULL) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) + return -ENOMEM; + + priv->sspa->mmio_base = devm_request_and_ioremap(&pdev->dev, res); + if (priv->sspa->mmio_base == NULL) + return -ENODEV; + + priv->sspa->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->sspa->clk)) + return PTR_ERR(priv->sspa->clk); + + priv->audio_clk = clk_get(NULL, "mmp-audio"); + if (IS_ERR(priv->audio_clk)) + return PTR_ERR(priv->audio_clk); + + priv->sysclk = clk_get(NULL, "mmp-sysclk"); + if (IS_ERR(priv->sysclk)) { + clk_put(priv->audio_clk); + return PTR_ERR(priv->sysclk); + } + clk_enable(priv->audio_clk); + priv->dai_fmt = (unsigned int) -1; + platform_set_drvdata(pdev, priv); + + return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai); +} + +static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev) +{ + struct sspa_priv *priv = platform_get_drvdata(pdev); + + clk_disable(priv->audio_clk); + clk_put(priv->audio_clk); + clk_put(priv->sysclk); + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver asoc_mmp_sspa_driver = { + .driver = { + .name = "mmp-sspa-dai", + .owner = THIS_MODULE, + }, + .probe = asoc_mmp_sspa_probe, + .remove = __devexit_p(asoc_mmp_sspa_remove), +}; + +module_platform_driver(asoc_mmp_sspa_driver); + +MODULE_AUTHOR("Leo Yan "); +MODULE_DESCRIPTION("MMP SSPA SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h new file mode 100644 index 000000000000..ea365cb9e784 --- /dev/null +++ b/sound/soc/pxa/mmp-sspa.h @@ -0,0 +1,92 @@ +/* + * linux/sound/soc/pxa/mmp-sspa.h + * + * Copyright (C) 2011 Marvell International Ltd. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _MMP_SSPA_H +#define _MMP_SSPA_H + +/* + * SSPA Registers + */ +#define SSPA_RXD (0x00) +#define SSPA_RXID (0x04) +#define SSPA_RXCTL (0x08) +#define SSPA_RXSP (0x0c) +#define SSPA_RXFIFO_UL (0x10) +#define SSPA_RXINT_MASK (0x14) +#define SSPA_RXC (0x18) +#define SSPA_RXFIFO_NOFS (0x1c) +#define SSPA_RXFIFO_SIZE (0x20) + +#define SSPA_TXD (0x80) +#define SSPA_TXID (0x84) +#define SSPA_TXCTL (0x88) +#define SSPA_TXSP (0x8c) +#define SSPA_TXFIFO_LL (0x90) +#define SSPA_TXINT_MASK (0x94) +#define SSPA_TXC (0x98) +#define SSPA_TXFIFO_NOFS (0x9c) +#define SSPA_TXFIFO_SIZE (0xa0) + +/* SSPA Control Register */ +#define SSPA_CTL_XPH (1 << 31) /* Read Phase */ +#define SSPA_CTL_XFIG (1 << 15) /* Transmit Zeros when FIFO Empty */ +#define SSPA_CTL_JST (1 << 3) /* Audio Sample Justification */ +#define SSPA_CTL_XFRLEN2_MASK (7 << 24) +#define SSPA_CTL_XFRLEN2(x) ((x) << 24) /* Transmit Frame Length in Phase 2 */ +#define SSPA_CTL_XWDLEN2_MASK (7 << 21) +#define SSPA_CTL_XWDLEN2(x) ((x) << 21) /* Transmit Word Length in Phase 2 */ +#define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Tansmit Data Delay */ +#define SSPA_CTL_XSSZ2_MASK (7 << 16) +#define SSPA_CTL_XSSZ2(x) ((x) << 16) /* Transmit Sample Audio Size */ +#define SSPA_CTL_XFRLEN1_MASK (7 << 8) +#define SSPA_CTL_XFRLEN1(x) ((x) << 8) /* Transmit Frame Length in Phase 1 */ +#define SSPA_CTL_XWDLEN1_MASK (7 << 5) +#define SSPA_CTL_XWDLEN1(x) ((x) << 5) /* Transmit Word Length in Phase 1 */ +#define SSPA_CTL_XSSZ1_MASK (7 << 0) +#define SSPA_CTL_XSSZ1(x) ((x) << 0) /* XSSZ1 */ + +#define SSPA_CTL_8_BITS (0x0) /* Sample Size */ +#define SSPA_CTL_12_BITS (0x1) +#define SSPA_CTL_16_BITS (0x2) +#define SSPA_CTL_20_BITS (0x3) +#define SSPA_CTL_24_BITS (0x4) +#define SSPA_CTL_32_BITS (0x5) + +/* SSPA Serial Port Register */ +#define SSPA_SP_WEN (1 << 31) /* Write Configuration Enable */ +#define SSPA_SP_MSL (1 << 18) /* Master Slave Configuration */ +#define SSPA_SP_CLKP (1 << 17) /* CLKP Polarity Clock Edge Select */ +#define SSPA_SP_FSP (1 << 16) /* FSP Polarity Clock Edge Select */ +#define SSPA_SP_FFLUSH (1 << 2) /* FIFO Flush */ +#define SSPA_SP_S_RST (1 << 1) /* Active High Reset Signal */ +#define SSPA_SP_S_EN (1 << 0) /* Serial Clock Domain Enable */ +#define SSPA_SP_FWID(x) ((x) << 20) /* Frame-Sync Width */ +#define SSPA_TXSP_FPER(x) ((x) << 4) /* Frame-Sync Active */ + +/* sspa clock sources */ +#define MMP_SSPA_CLK_PLL 0 +#define MMP_SSPA_CLK_VCXO 1 +#define MMP_SSPA_CLK_AUDIO 3 + +/* sspa pll id */ +#define MMP_SYSCLK 0 +#define MMP_SSPA_CLK 1 + +#endif /* _MMP_SSPA_H */ -- GitLab From 5ebf20ae286a7d2b02551757166247a901d705e5 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Mon, 11 Jun 2012 18:04:40 +0800 Subject: [PATCH 0601/5711] ASoC: add mmp brownstone support Adds Alsa audio platform driver for mmp brownstone machine Signed-off-by: Zhangfei Gao Signed-off-by: Leo Yan Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 10 +++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/brownstone.c | 174 +++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 sound/soc/pxa/brownstone.c diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 6c3d00b8ea0b..d389fd574efe 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -206,3 +206,13 @@ config SND_PXA2XX_SOC_IMOTE2 help Say Y if you want to add support for SoC audio on the IMote 2. + +config SND_MMP_SOC_BROWNSTONE + tristate "SoC Audio support for Marvell Brownstone" + depends on SND_MMP_SOC && MACH_BROWNSTONE + select SND_MMP_SOC_SSPA + select MFD_WM8994 + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on the + Marvell Brownstone reference platform. diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 07b841746fc3..c12aa2a9bf74 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -32,6 +32,7 @@ snd-soc-mioa701-objs := mioa701_wm9713.o snd-soc-z2-objs := z2.o snd-soc-imote2-objs := imote2.o snd-soc-raumfeld-objs := raumfeld.o +snd-soc-brownstone-objs := brownstone.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o @@ -51,3 +52,4 @@ obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o +obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c new file mode 100644 index 000000000000..5e666e03d333 --- /dev/null +++ b/sound/soc/pxa/brownstone.c @@ -0,0 +1,174 @@ +/* + * linux/sound/soc/pxa/brownstone.c + * + * Copyright (C) 2011 Marvell International Ltd. + * + * 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 "../codecs/wm8994.h" +#include "mmp-sspa.h" + +static const struct snd_kcontrol_new brownstone_dapm_control[] = { + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static const struct snd_soc_dapm_widget brownstone_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", NULL), +}; + +static const struct snd_soc_dapm_route brownstone_audio_map[] = { + {"Ext Spk", NULL, "SPKOUTLP"}, + {"Ext Spk", NULL, "SPKOUTLN"}, + {"Ext Spk", NULL, "SPKOUTRP"}, + {"Ext Spk", NULL, "SPKOUTRN"}, + + {"Headset Stereophone", NULL, "HPOUT1L"}, + {"Headset Stereophone", NULL, "HPOUT1R"}, + + {"IN1RN", NULL, "Headset Mic"}, + + {"DMIC1DAT", NULL, "MICBIAS1"}, + {"MICBIAS1", NULL, "Main Mic"}, +}; + +static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); + snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin(dapm, "Main Mic"); + + /* set endpoints to not connected */ + snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); + snd_soc_dapm_nc_pin(dapm, "HPOUT2N"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); + snd_soc_dapm_nc_pin(dapm, "IN1LN"); + snd_soc_dapm_nc_pin(dapm, "IN1LP"); + snd_soc_dapm_nc_pin(dapm, "IN1RP"); + snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); + snd_soc_dapm_nc_pin(dapm, "IN2RN"); + snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); + snd_soc_dapm_nc_pin(dapm, "IN2LN"); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int freq_out, sspa_mclk, sysclk; + int sspa_div; + + if (params_rate(params) > 11025) { + freq_out = params_rate(params) * 512; + sysclk = params_rate(params) * 256; + sspa_mclk = params_rate(params) * 64; + } else { + freq_out = params_rate(params) * 1024; + sysclk = params_rate(params) * 512; + sspa_mclk = params_rate(params) * 64; + } + sspa_div = freq_out; + do_div(sspa_div, sspa_mclk); + + snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0); + snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk); + snd_soc_dai_set_pll(cpu_dai, MMP_SSPA_CLK, 0, freq_out, sspa_mclk); + + /* set wm8994 sysclk */ + snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, sysclk, 0); + + return 0; +} + +/* machine stream operations */ +static struct snd_soc_ops brownstone_ops = { + .hw_params = brownstone_wm8994_hw_params, +}; + +static struct snd_soc_dai_link brownstone_wm8994_dai[] = { +{ + .name = "WM8994", + .stream_name = "WM8994 HiFi", + .cpu_dai_name = "mmp-sspa-dai.0", + .codec_dai_name = "wm8994-aif1", + .platform_name = "mmp-pcm-audio", + .codec_name = "wm8994-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &brownstone_ops, + .init = brownstone_wm8994_init, +}, +}; + +/* audio machine driver */ +static struct snd_soc_card brownstone = { + .name = "brownstone", + .dai_link = brownstone_wm8994_dai, + .num_links = ARRAY_SIZE(brownstone_wm8994_dai), + + .controls = brownstone_dapm_control, + .num_controls = ARRAY_SIZE(brownstone_dapm_control), + .dapm_widgets = brownstone_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), + .dapm_routes = brownstone_audio_map, + .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), +}; + +static int __devinit brownstone_probe(struct platform_device *pdev) +{ + int ret; + + brownstone.dev = &pdev->dev; + ret = snd_soc_register_card(&brownstone); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + return ret; +} + +static int __devexit brownstone_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&brownstone); + return 0; +} + +static struct platform_driver mmp_driver = { + .driver = { + .name = "brownstone-audio", + .owner = THIS_MODULE, + }, + .probe = brownstone_probe, + .remove = __devexit_p(brownstone_remove), +}; + +module_platform_driver(mmp_driver); + +MODULE_AUTHOR("Leo Yan "); +MODULE_DESCRIPTION("ALSA SoC Brownstone"); +MODULE_LICENSE("GPL"); -- GitLab From b883f363495f3d2e237170f6b8814869a3dd16fe Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Mon, 11 Jun 2012 18:04:41 +0800 Subject: [PATCH 0602/5711] ASoC: add ttc-dkb machine support add ttc-dkb machine support for pxa910. It uses 88pm8607 as codec dai, mmp-pcm as platform and pxa-ssp as cpu dai. Signed-off-by: Qiao Zhou Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 20 +++++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/ttc-dkb.c | 173 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 sound/soc/pxa/ttc-dkb.c diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index d389fd574efe..4d2e46fae77c 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -150,6 +150,26 @@ config SND_SOC_TAVOREVB3 Say Y if you want to add support for SoC audio on the Marvell Saarb reference platform. +config SND_PXA910_SOC + tristate "SoC Audio for Marvell PXA910 chip" + depends on ARCH_MMP && SND + select SND_PCM + help + Say Y if you want to add support for SoC audio on the + Marvell PXA910 reference platform. + +config SND_SOC_TTC_DKB + bool "SoC Audio support for TTC DKB" + depends on SND_PXA910_SOC && MACH_TTC_DKB + select PXA_SSP + select SND_PXA_SOC_SSP + select SND_MMP_SOC + select MFD_88PM860X + select SND_SOC_88PM860X + help + Say Y if you want to add support for SoC audio on TTC DKB + + config SND_SOC_ZYLONITE tristate "SoC Audio support for Marvell Zylonite" depends on SND_PXA2XX_SOC && MACH_ZYLONITE diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index c12aa2a9bf74..d8a265d2d5d7 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -33,6 +33,7 @@ snd-soc-z2-objs := z2.o snd-soc-imote2-objs := imote2.o snd-soc-raumfeld-objs := raumfeld.o snd-soc-brownstone-objs := brownstone.o +snd-soc-ttc-dkb-objs := ttc-dkb.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o @@ -53,3 +54,4 @@ obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o +obj-$(CONFIG_SND_SOC_TTC_DKB) += snd-soc-ttc-dkb.o diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c new file mode 100644 index 000000000000..935491a8a770 --- /dev/null +++ b/sound/soc/pxa/ttc-dkb.c @@ -0,0 +1,173 @@ +/* + * linux/sound/soc/pxa/ttc_dkb.c + * + * Copyright (C) 2012 Marvell International Ltd. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/88pm860x-codec.h" + +static struct snd_soc_jack hs_jack, mic_jack; + +static struct snd_soc_jack_pin hs_jack_pins[] = { + { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, +}; + +static struct snd_soc_jack_pin mic_jack_pins[] = { + { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, +}; + +/* ttc machine dapm widgets */ +static const struct snd_soc_dapm_widget ttc_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_LINE("Lineout Out 1", NULL), + SND_SOC_DAPM_LINE("Lineout Out 2", NULL), + SND_SOC_DAPM_SPK("Ext Speaker", NULL), + SND_SOC_DAPM_MIC("Ext Mic 1", NULL), + SND_SOC_DAPM_MIC("Headset Mic 2", NULL), + SND_SOC_DAPM_MIC("Ext Mic 3", NULL), +}; + +/* ttc machine audio map */ +static const struct snd_soc_dapm_route ttc_audio_map[] = { + {"Headset Stereophone", NULL, "HS1"}, + {"Headset Stereophone", NULL, "HS2"}, + + {"Ext Speaker", NULL, "LSP"}, + {"Ext Speaker", NULL, "LSN"}, + + {"Lineout Out 1", NULL, "LINEOUT1"}, + {"Lineout Out 2", NULL, "LINEOUT2"}, + + {"MIC1P", NULL, "Mic1 Bias"}, + {"MIC1N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Ext Mic 1"}, + + {"MIC2P", NULL, "Mic1 Bias"}, + {"MIC2N", NULL, "Mic1 Bias"}, + {"Mic1 Bias", NULL, "Headset Mic 2"}, + + {"MIC3P", NULL, "Mic3 Bias"}, + {"MIC3N", NULL, "Mic3 Bias"}, + {"Mic3 Bias", NULL, "Ext Mic 3"}, +}; + +static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + /* connected pins */ + snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); + snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); + snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); + snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); + snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); + + /* Headset jack detection */ + snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE + | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, + &hs_jack); + snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, + &mic_jack); + snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), + mic_jack_pins); + + /* headphone, microphone detection & headset short detection */ + pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, + SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); + pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); + + return 0; +} + +/* ttc/td-dkb digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = { +{ + .name = "88pm860x i2s", + .stream_name = "audio playback", + .codec_name = "88pm860x-codec", + .platform_name = "mmp-pcm-audio", + .cpu_dai_name = "pxa-ssp-dai.1", + .codec_dai_name = "88pm860x-i2s", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + .init = ttc_pm860x_init, +}, +}; + +/* ttc/td audio machine driver */ +static struct snd_soc_card ttc_dkb_card = { + .name = "ttc-dkb-hifi", + .dai_link = ttc_pm860x_hifi_dai, + .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), + + .dapm_widgets = ttc_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ttc_dapm_widgets), + .dapm_routes = ttc_audio_map, + .num_dapm_routes = ARRAY_SIZE(ttc_audio_map), +}; + +static int __devinit ttc_dkb_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &ttc_dkb_card; + int ret; + + card->dev = &pdev->dev; + + ret = snd_soc_register_card(card); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + + return ret; +} + +static int __devexit ttc_dkb_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static struct platform_driver ttc_dkb_driver = { + .driver = { + .name = "ttc-dkb-audio", + .owner = THIS_MODULE, + }, + .probe = ttc_dkb_probe, + .remove = __devexit_p(ttc_dkb_remove), +}; + +module_platform_driver(ttc_dkb_driver); + +/* Module information */ +MODULE_AUTHOR("Qiao Zhou, "); +MODULE_DESCRIPTION("ALSA SoC TTC DKB"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ttc-dkb-audio"); -- GitLab From a9db7dbee0436f0c741c6dfb39ab0241d4131539 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 8 Jun 2012 12:34:20 -0600 Subject: [PATCH 0603/5711] ASoC: when initializing CPU DAI, don't duplicate any CODEC init If the CPU-side of a DAI link is a CODEC rather than a standalone DAI, the codec initialization will call try_module_get() and create the DAI widgets. Ensure that this isn't duplicated when the CPU DAI itself is probed, if the CPU DAI is part of a CODEC. Note that this is not a complete fix on its own, since there's no guarantee that the CODEC itself will be initialized - currently that only happens if the CODEC is also used as the CODEC-side of a DAI link, and that initialization may happen before or after the DAIs within the CODEC are initialized. However, such a scenario doesn't necessarily currently work, and I don't think this change alone makes it any worse. This is fixed in a couple patches time. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3d803f3cd272..448d4a7c09dd 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -983,7 +983,9 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) } cpu_dai->probed = 0; list_del(&cpu_dai->card_list); - module_put(cpu_dai->dev->driver->owner); + + if (!cpu_dai->codec) + module_put(cpu_dai->dev->driver->owner); } } @@ -1257,11 +1259,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) /* probe the cpu_dai */ if (!cpu_dai->probed && cpu_dai->driver->probe_order == order) { - cpu_dai->dapm.card = card; - if (!try_module_get(cpu_dai->dev->driver->owner)) - return -ENODEV; + if (!cpu_dai->codec) { + cpu_dai->dapm.card = card; + if (!try_module_get(cpu_dai->dev->driver->owner)) + return -ENODEV; - snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); + snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); + } if (cpu_dai->driver->probe) { ret = cpu_dai->driver->probe(cpu_dai); -- GitLab From 18d756440e8ed292b772682c4440a9d33643225b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 8 Jun 2012 12:34:21 -0600 Subject: [PATCH 0604/5711] ASoC: when removing a CPU DAI, clean up its DAPM context When a standalone CPU DAI (one not part of a CODEC) is probed, widgets are created for it. Add a call to snd_soc_dapm_free() in order to clean these up when the CPU DAI is removed. In order for snd_soc_dapm_free() to work, the CPU DAI's DAPM context's list member must be initialized, since snd_soc_dapm_free() removes that from the list it's part of. Add it to the card's list of DAPM contexts. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 448d4a7c09dd..621c5bdea483 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -984,8 +984,10 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) cpu_dai->probed = 0; list_del(&cpu_dai->card_list); - if (!cpu_dai->codec) + if (!cpu_dai->codec) { + snd_soc_dapm_free(&cpu_dai->dapm); module_put(cpu_dai->dev->driver->owner); + } } } @@ -1264,6 +1266,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) if (!try_module_get(cpu_dai->dev->driver->owner)) return -ENODEV; + list_add(&cpu_dai->dapm.list, &card->dapm_list); snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); } -- GitLab From d12cd198cba7949c70f596296297b772063175c0 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 8 Jun 2012 12:34:22 -0600 Subject: [PATCH 0605/5711] ASoC: factor out soc_remove_platform() This change simply factors out part of soc_remove_dai_link() into a standalone function. This makes platform and CODEC removal much more similar at the call-sites. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 621c5bdea483..a539ade477af 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -898,6 +898,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) return 0; } +static int soc_remove_platform(struct snd_soc_platform *platform) +{ + int ret; + + if (platform->driver->remove) { + ret = platform->driver->remove(platform); + if (ret < 0) + pr_err("asoc: failed to remove %s: %d\n", + platform->name, ret); + } + + /* Make sure all DAPM widgets are freed */ + snd_soc_dapm_free(&platform->dapm); + + soc_cleanup_platform_debugfs(platform); + platform->probed = 0; + list_del(&platform->card_list); + module_put(platform->dev->driver->owner); + + return 0; +} + static void soc_remove_codec(struct snd_soc_codec *codec) { int err; @@ -950,22 +972,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) /* remove the platform */ if (platform && platform->probed && - platform->driver->remove_order == order) { - if (platform->driver->remove) { - err = platform->driver->remove(platform); - if (err < 0) - pr_err("asoc: failed to remove %s: %d\n", - platform->name, err); - } - - /* Make sure all DAPM widgets are freed */ - snd_soc_dapm_free(&platform->dapm); - - soc_cleanup_platform_debugfs(platform); - platform->probed = 0; - list_del(&platform->card_list); - module_put(platform->dev->driver->owner); - } + platform->driver->remove_order == order) + soc_remove_platform(platform); /* remove the CODEC */ if (codec && codec->probed && -- GitLab From 62ae68fa5d6d6f93d8ca8d00e21ad7ac410f9d58 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 8 Jun 2012 12:34:23 -0600 Subject: [PATCH 0606/5711] ASoC: probe CODECs and platforms before DAIs and links soc_probe_dai_link() currently inter-mixes the probing of CODECs, platforms, and DAIs. This can lead to problems such as a CODEC's DAI being probed before the CODEC, if that DAI is used as the CPU-side of a DAI link without any other of the CODEC's DAIs having been used as the CODEC-side of any DAI link that was probed earlier. To solve this, split soc_probe_dai_link() into soc_probe_link_components() and soc_probe_link_dais(). The former is used to probe all CODECs and platforms used by a card first, and then the latter is used to probe all the DAIs and links later. A similar change is made to soc_remove_dai_links(). Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 129 +++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 34 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a539ade477af..fe16135250f8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -941,11 +941,9 @@ static void soc_remove_codec(struct snd_soc_codec *codec) module_put(codec->dev->driver->owner); } -static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) +static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) { struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; int err; @@ -970,16 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) list_del(&codec_dai->card_list); } - /* remove the platform */ - if (platform && platform->probed && - platform->driver->remove_order == order) - soc_remove_platform(platform); - - /* remove the CODEC */ - if (codec && codec->probed && - codec->driver->remove_order == order) - soc_remove_codec(codec); - /* remove the cpu_dai */ if (cpu_dai && cpu_dai->probed && cpu_dai->driver->remove_order == order) { @@ -999,6 +987,38 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) } } +static void soc_remove_link_components(struct snd_soc_card *card, int num, + int order) +{ + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_codec *codec; + + /* remove the platform */ + if (platform && platform->probed && + platform->driver->remove_order == order) { + soc_remove_platform(platform); + } + + /* remove the CODEC-side CODEC */ + if (codec_dai) { + codec = codec_dai->codec; + if (codec && codec->probed && + codec->driver->remove_order == order) + soc_remove_codec(codec); + } + + /* remove any CPU-side CODEC */ + if (cpu_dai) { + codec = cpu_dai->codec; + if (codec && codec->probed && + codec->driver->remove_order == order) + soc_remove_codec(codec); + } +} + static void soc_remove_dai_links(struct snd_soc_card *card) { int dai, order; @@ -1006,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card) for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { for (dai = 0; dai < card->num_rtd; dai++) - soc_remove_dai_link(card, dai, order); + soc_remove_link_dais(card, dai, order); + } + + for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; + order++) { + for (dai = 0; dai < card->num_rtd; dai++) + soc_remove_link_components(card, dai, order); } + card->num_rtd = 0; } @@ -1244,7 +1271,44 @@ out: return 0; } -static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) +static int soc_probe_link_components(struct snd_soc_card *card, int num, + int order) +{ + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_platform *platform = rtd->platform; + int ret; + + /* probe the CPU-side component, if it is a CODEC */ + if (cpu_dai->codec && + !cpu_dai->codec->probed && + cpu_dai->codec->driver->probe_order == order) { + ret = soc_probe_codec(card, cpu_dai->codec); + if (ret < 0) + return ret; + } + + /* probe the CODEC-side component */ + if (!codec_dai->codec->probed && + codec_dai->codec->driver->probe_order == order) { + ret = soc_probe_codec(card, codec_dai->codec); + if (ret < 0) + return ret; + } + + /* probe the platform */ + if (!platform->probed && + platform->driver->probe_order == order) { + ret = soc_probe_platform(card, platform); + if (ret < 0) + return ret; + } + + return 0; +} + +static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; @@ -1292,22 +1356,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) list_add(&cpu_dai->card_list, &card->dai_dev_list); } - /* probe the CODEC */ - if (!codec->probed && - codec->driver->probe_order == order) { - ret = soc_probe_codec(card, codec); - if (ret < 0) - return ret; - } - - /* probe the platform */ - if (!platform->probed && - platform->driver->probe_order == order) { - ret = soc_probe_platform(card, platform); - if (ret < 0) - return ret; - } - /* probe the CODEC DAI */ if (!codec_dai->probed && codec_dai->driver->probe_order == order) { if (codec_dai->driver->probe) { @@ -1582,14 +1630,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) goto card_probe_error; } - /* early DAI link probe */ + /* probe all components used by DAI links on this card */ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { for (i = 0; i < card->num_links; i++) { - ret = soc_probe_dai_link(card, i, order); + ret = soc_probe_link_components(card, i, order); if (ret < 0) { pr_err("asoc: failed to instantiate card %s: %d\n", - card->name, ret); + card->name, ret); + goto probe_dai_err; + } + } + } + + /* probe all DAI links on this card */ + for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; + order++) { + for (i = 0; i < card->num_links; i++) { + ret = soc_probe_link_dais(card, i, order); + if (ret < 0) { + pr_err("asoc: failed to instantiate card %s: %d\n", + card->name, ret); goto probe_dai_err; } } -- GitLab From 0d515210b6969ecfc161f71a4515831d9a6e58f4 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 13 Jun 2012 10:27:41 -0400 Subject: [PATCH 0607/5711] GFS2: Add kobject release method This patch adds a kobject release function that properly maintains the kobject use count, so that accesses to the sysfs files do not cause an access to freed kernel memory after an unmount. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 36 ++++++++++++++++++++++++------------ fs/gfs2/sys.c | 21 ++++++++++++++++++--- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index b8c250fc4922..9b2389756acd 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1118,20 +1118,33 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent } error = init_names(sdp, silent); - if (error) - goto fail; + if (error) { + /* In this case, we haven't initialized sysfs, so we have to + manually free the sdp. */ + free_percpu(sdp->sd_lkstats); + kfree(sdp); + sb->s_fs_info = NULL; + return error; + } snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s", sdp->sd_table_name); - gfs2_create_debugfs_file(sdp); - error = gfs2_sys_fs_add(sdp); + /* + * If we hit an error here, gfs2_sys_fs_add will have called function + * kobject_put which causes the sysfs usage count to go to zero, which + * causes sysfs to call function gfs2_sbd_release, which frees sdp. + * Subsequent error paths here will call gfs2_sys_fs_del, which also + * kobject_put to free sdp. + */ if (error) - goto fail; + return error; + + gfs2_create_debugfs_file(sdp); error = gfs2_lm_mount(sdp, silent); if (error) - goto fail_sys; + goto fail_debug; error = init_locking(sdp, &mount_gh, DO); if (error) @@ -1215,12 +1228,12 @@ fail_locking: fail_lm: gfs2_gl_hash_clear(sdp); gfs2_lm_unmount(sdp); -fail_sys: - gfs2_sys_fs_del(sdp); -fail: +fail_debug: gfs2_delete_debugfs_file(sdp); free_percpu(sdp->sd_lkstats); - kfree(sdp); + /* gfs2_sys_fs_del must be the last thing we do, since it causes + * sysfs to call function gfs2_sbd_release, which frees sdp. */ + gfs2_sys_fs_del(sdp); sb->s_fs_info = NULL; return error; } @@ -1390,10 +1403,9 @@ static void gfs2_kill_sb(struct super_block *sb) sdp->sd_root_dir = NULL; sdp->sd_master_dir = NULL; shrink_dcache_sb(sb); - kill_block_super(sb); gfs2_delete_debugfs_file(sdp); free_percpu(sdp->sd_lkstats); - kfree(sdp); + kill_block_super(sb); } struct file_system_type gfs2_fs_type = { diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 9c2592b1d5ff..e4bee4bebbf6 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -276,7 +276,15 @@ static struct attribute *gfs2_attrs[] = { NULL, }; +static void gfs2_sbd_release(struct kobject *kobj) +{ + struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); + + kfree(sdp); +} + static struct kobj_type gfs2_ktype = { + .release = gfs2_sbd_release, .default_attrs = gfs2_attrs, .sysfs_ops = &gfs2_attr_ops, }; @@ -583,6 +591,7 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) char ro[20]; char spectator[20]; char *envp[] = { ro, spectator, NULL }; + int sysfs_frees_sdp = 0; sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0); sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0); @@ -591,8 +600,10 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL, "%s", sdp->sd_table_name); if (error) - goto fail; + goto fail_reg; + sysfs_frees_sdp = 1; /* Freeing sdp is now done by sysfs calling + function gfs2_sbd_release. */ error = sysfs_create_group(&sdp->sd_kobj, &tune_group); if (error) goto fail_reg; @@ -615,9 +626,13 @@ fail_lock_module: fail_tune: sysfs_remove_group(&sdp->sd_kobj, &tune_group); fail_reg: - kobject_put(&sdp->sd_kobj); -fail: + free_percpu(sdp->sd_lkstats); fs_err(sdp, "error %d adding sysfs files", error); + if (sysfs_frees_sdp) + kobject_put(&sdp->sd_kobj); + else + kfree(sdp); + sb->s_fs_info = NULL; return error; } -- GitLab From 93314b5b6f343f5a4c14c89d000007a754190c9a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Jun 2012 17:36:55 +0100 Subject: [PATCH 0608/5711] drm/i915: Switch off FBC when disabling the primary plane when obscured As we switch on/off the primary plane if it is completely obscured by an overlapping video sprite, we also nee to make sure that we update the FBC configuration at the same time. v2: Not all crtcs are intel_crtcs, as spotted by Daniel. v3: Boot testing rules. References: https://bugs.freedesktop.org/show_bug.cgi?id=50238 Signed-off-by: Chris Wilson Cc: Jesse Barnes Reviewed-by: Jesse Barnes Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 +++- drivers/gpu/drm/i915/intel_sprite.c | 25 +++++++++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1a1fdb088dda..5290e9df327b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -169,6 +169,7 @@ struct intel_crtc { u8 lut_r[256], lut_g[256], lut_b[256]; int dpms_mode; bool active; /* is the crtc on? independent of the dpms mode */ + bool primary_disabled; /* is the crtc obscured by a plane? */ bool busy; /* is scanout buffer being updated frequently? */ struct timer_list idle_timer; bool lowfreq_avail; @@ -191,7 +192,6 @@ struct intel_plane { struct drm_plane base; enum pipe pipe; struct drm_i915_gem_object *obj; - bool primary_disabled; int max_downscale; u32 lut_r[1024], lut_g[1024], lut_b[1024]; void (*update_plane)(struct drm_plane *plane, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d0ce2a5b1d3f..b7de5ea62aa4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -405,7 +405,9 @@ void intel_update_fbc(struct drm_device *dev) * - going to an unsupported config (interlace, pixel multiply, etc.) */ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { - if (tmp_crtc->enabled && tmp_crtc->fb) { + if (tmp_crtc->enabled && + !to_intel_crtc(tmp_crtc)->primary_disabled && + tmp_crtc->fb) { if (crtc) { DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 2a20fb0781d7..9d7777bc1545 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -326,6 +326,12 @@ intel_enable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); + if (!intel_crtc->primary_disabled) + return; + + intel_crtc->primary_disabled = false; + intel_update_fbc(dev); + I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); } @@ -337,7 +343,13 @@ intel_disable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); + if (intel_crtc->primary_disabled) + return; + I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); + + intel_crtc->primary_disabled = true; + intel_update_fbc(dev); } static int @@ -485,18 +497,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * Be sure to re-enable the primary before the sprite is no longer * covering it fully. */ - if (!disable_primary && intel_plane->primary_disabled) { + if (!disable_primary) intel_enable_primary(crtc); - intel_plane->primary_disabled = false; - } intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, crtc_w, crtc_h, x, y, src_w, src_h); - if (disable_primary) { + if (disable_primary) intel_disable_primary(crtc); - intel_plane->primary_disabled = true; - } /* Unpin old obj after new one is active to avoid ugliness */ if (old_obj) { @@ -527,11 +535,8 @@ intel_disable_plane(struct drm_plane *plane) struct intel_plane *intel_plane = to_intel_plane(plane); int ret = 0; - if (intel_plane->primary_disabled) { + if (plane->crtc) intel_enable_primary(plane->crtc); - intel_plane->primary_disabled = false; - } - intel_plane->disable_plane(plane); if (!intel_plane->obj) -- GitLab From 14d94a3d82ab3ef6b3a9f881e134d5b48323b202 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 13 Jun 2012 13:46:58 -0500 Subject: [PATCH 0609/5711] drm/i915: ignore pipe select bit when checking for LVDS register initialization The Lenovo Thinkpad T410 has the LVDS_PIPEB_SELECT bit set in the LVDS register when booted with the lid closed, even though the LVDS hasn't really been initialized. Ignore this bit so that the VBT value will be used instead. Signed-off-by: Seth Forshee Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 174549df5929..308e1a2967e7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -434,7 +434,7 @@ static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, * register is uninitialized. */ val = I915_READ(reg); - if (!(val & ~LVDS_DETECTED)) + if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) val = dev_priv->bios_lvds_val; dev_priv->lvds_val = val; } -- GitLab From f922ffc0b52f8ee9e7503e769fa6931cb51635ab Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 13 Jun 2012 20:44:34 +0200 Subject: [PATCH 0610/5711] staging bcm: spelling of suppress in comments Signed-off-by: Peter Meerwald Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/PHSModule.c | 10 +++++----- drivers/staging/bcm/cntrl_SignalingInterface.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c index a6e61510d278..c0862c6c21a0 100644 --- a/drivers/staging/bcm/PHSModule.c +++ b/drivers/staging/bcm/PHSModule.c @@ -54,8 +54,8 @@ Function: PHSTransmit Description: This routine handle PHS(Payload Header Suppression for Tx path. It extracts a fragment of the NDIS_PACKET containing the header - to be suppressed.It then supresses the header by invoking PHS exported compress routine. - The header data after supression is copied back to the NDIS_PACKET. + to be suppressed. It then suppresses the header by invoking PHS exported compress routine. + The header data after suppression is copied back to the NDIS_PACKET. Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context @@ -101,7 +101,7 @@ int PHSTransmit(struct bcm_mini_adapter *Adapter, if(!bEthCSSupport) BytesToRemove=ETH_HLEN; /* - Accumulate the header upto the size we support supression + Accumulate the header upto the size we support suppression from NDIS packet */ @@ -125,7 +125,7 @@ int PHSTransmit(struct bcm_mini_adapter *Adapter, { - // Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf. + // Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf. // Suppress only if IP Header and PHS Enabled For the Service Flow if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) || (usPacketType == ETHERNET_FRAMETYPE_IPV6)) && @@ -238,7 +238,7 @@ int PHSReceive(struct bcm_mini_adapter *Adapter, &nTotalsupressedPktHdrBytes, &nStandardPktHdrLen); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", nTotalsupressedPktHdrBytes,nStandardPktHdrLen); if(ulPhsStatus != STATUS_PHS_COMPRESSED) diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h index ab131806e2c9..7619e4b819bd 100644 --- a/drivers/staging/bcm/cntrl_SignalingInterface.h +++ b/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -117,7 +117,7 @@ typedef struct _stPhsRuleSI { B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; /** 8bit Total number of bytes to be suppressed for the Service Flow*/ B_UINT8 u8PHSS; - /** 8bit Indicates whether or not Packet Header contents need to be verified prior to supression */ + /** 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */ B_UINT8 u8PHSV; /** Vendor Specific PHS param Length Of The Service Flow*/ B_UINT8 u8VendorSpecificPHSParamsLength; -- GitLab From b38e274fdb6dfa2dd77598b8b6e2c32d7608f494 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 13 Jun 2012 20:44:35 +0200 Subject: [PATCH 0611/5711] staging bcm: spelling of suppress in code Signed-off-by: Peter Meerwald Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Adapter.h | 8 ++++---- drivers/staging/bcm/PHSModule.c | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 11d2c5a84552..4d490a99110c 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -54,9 +54,9 @@ typedef union _U_IP_ADDRESS { }; } U_IP_ADDRESS; -struct bcm_hdr_supression_contextinfo { - UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */ - UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */ +struct bcm_hdr_suppression_contextinfo { + UCHAR ucaHdrSuppressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */ + UCHAR ucaHdrSuppressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */ }; struct bcm_classifier_rule { @@ -334,7 +334,7 @@ struct bcm_mini_adapter { BOOLEAN bLinkDownRequested; int downloadDDR; PHS_DEVICE_EXTENSION stBCMPhsContext; - struct bcm_hdr_supression_contextinfo stPhsTxContextInfo; + struct bcm_hdr_suppression_contextinfo stPhsTxContextInfo; uint8_t ucaPHSPktRestoreBuf[2048]; uint8_t bPHSEnabled; BOOLEAN AutoFirmDld; diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c index c0862c6c21a0..479574234e4c 100644 --- a/drivers/staging/bcm/PHSModule.c +++ b/drivers/staging/bcm/PHSModule.c @@ -84,10 +84,10 @@ int PHSTransmit(struct bcm_mini_adapter *Adapter, UINT unPHSNewPktHeaderLen = 0; /* Pointer to PHS IN Hdr Buffer */ PUCHAR pucPHSPktHdrInBuf = - Adapter->stPhsTxContextInfo.ucaHdrSupressionInBuf; + Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf; /* Pointer to PHS OUT Hdr Buffer */ PUCHAR pucPHSPktHdrOutBuf = - Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf; + Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf; UINT usPacketType; UINT BytesToRemove=0; BOOLEAN bPHSI = 0; @@ -217,7 +217,7 @@ int PHSReceive(struct bcm_mini_adapter *Adapter, UINT bHeaderSuppressionEnabled) { u32 nStandardPktHdrLen = 0; - u32 nTotalsupressedPktHdrBytes = 0; + u32 nTotalsuppressedPktHdrBytes = 0; int ulPhsStatus = 0; PUCHAR pucInBuff = NULL ; UINT TotalBytesAdded = 0; @@ -235,11 +235,11 @@ int PHSReceive(struct bcm_mini_adapter *Adapter, usVcid, pucInBuff, Adapter->ucaPHSPktRestoreBuf, - &nTotalsupressedPktHdrBytes, + &nTotalsuppressedPktHdrBytes, &nStandardPktHdrLen); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", - nTotalsupressedPktHdrBytes,nStandardPktHdrLen); + nTotalsuppressedPktHdrBytes,nStandardPktHdrLen); if(ulPhsStatus != STATUS_PHS_COMPRESSED) { @@ -248,7 +248,7 @@ int PHSReceive(struct bcm_mini_adapter *Adapter, } else { - TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - PHSI_LEN; + TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN; if(TotalBytesAdded) { if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded)) @@ -1494,7 +1494,7 @@ static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size) { unsigned char *old_addr = out_buf; - int supress = 0; + int suppress = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); if(phs_rule == NULL) { @@ -1514,10 +1514,10 @@ static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf } //To copy PHSI out_buf++; - supress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF, + suppress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF, phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size); - if(supress == STATUS_PHS_COMPRESSED) + if(suppress == STATUS_PHS_COMPRESSED) { *old_addr = (unsigned char)phs_rule->u8PHSI; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI); @@ -1527,7 +1527,7 @@ static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf *old_addr = ZERO_PHSI; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed"); } - return supress; + return suppress; } -- GitLab From a2c49a9ac993fa2b4795890d5fa56f2fc002453e Mon Sep 17 00:00:00 2001 From: William Blair Date: Wed, 13 Jun 2012 01:16:49 -0400 Subject: [PATCH 0612/5711] Staging: keucr: scsiglue: fixed a do while coding style issue Added a do ... while (0) to a multi statement macro and reformatted a similar macro. Signed-off-by: William Blair Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/scsiglue.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/staging/keucr/scsiglue.c b/drivers/staging/keucr/scsiglue.c index e1f3931d41e0..083b20e6253e 100644 --- a/drivers/staging/keucr/scsiglue.c +++ b/drivers/staging/keucr/scsiglue.c @@ -230,7 +230,10 @@ void usb_stor_report_bus_reset(struct us_data *us) /* 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) /* * proc_info() @@ -279,8 +282,10 @@ static int proc_info(struct Scsi_Host *host, char *buffer, char **start, pos += sprintf(pos, " Quirks:"); #define US_FLAG(name, value) \ - if (us->fflags & value)\ - pos += sprintf(pos, " " #name); + do { \ + if (us->fflags & value) \ + pos += sprintf(pos, " " #name); \ + } while (0); US_DO_ALL_FLAGS #undef US_FLAG -- GitLab From e888fabd10cdd46a4b46bcc029c5c6d2364dab7f Mon Sep 17 00:00:00 2001 From: Chris Yungmann Date: Wed, 13 Jun 2012 12:39:55 -0400 Subject: [PATCH 0613/5711] staging: speakup: fixed checkpatch and sparse warnings in selection.c Signed-off-by: Chris Yungmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/selection.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index fe1f405d5d70..0612df06a4bf 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -68,7 +68,7 @@ int speakup_set_selection(struct tty_struct *tty) if (spk_sel_cons != vc_cons[fg_console].d) { speakup_clear_selection(); spk_sel_cons = vc_cons[fg_console].d; - printk(KERN_WARNING + dev_warn(tty->dev, "Selection: mark console not the same as cut\n"); return -EINVAL; } @@ -95,7 +95,7 @@ int speakup_set_selection(struct tty_struct *tty) /* Allocate a new buffer before freeing the old one ... */ bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC); if (!bp) { - printk(KERN_WARNING "selection: kmalloc() failed\n"); + dev_warn(tty->dev, "selection: kmalloc() failed\n"); speakup_clear_selection(); return -ENOMEM; } @@ -141,7 +141,7 @@ int speakup_paste_selection(struct tty_struct *tty) count = sel_buffer_lth - pasted; count = min_t(int, count, tty->receive_room); tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, - 0, count); + NULL, count); pasted += count; } remove_wait_queue(&vc->paste_wait, &wait); -- GitLab From 4829a9967dbe3a3ab192df0bfdde281960cc1319 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 12 Jun 2012 17:37:10 -0700 Subject: [PATCH 0614/5711] staging: comedi: Kconfig: cleanup depends on logic All of the config options for comedi depend on COMEDI being selected. Wrap everything in an 'if COMEDI/endif' block and remove all the individual 'depends on COMEDI' in the Kconfig. Also, remove the redundant && ISA/PCI/PCMCIA/USB for the if blocks with those driver types. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 54e32da55c7c..848cf7e3e8fd 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -6,9 +6,10 @@ config COMEDI Enable support a wide range of data acquisition devices for Linux. +if COMEDI + config COMEDI_DEBUG bool "Comedi debugging" - depends on COMEDI != n ---help--- This is an option for use by developers; most people should say N here. This enables comedi core and driver debugging. @@ -16,7 +17,6 @@ config COMEDI_DEBUG config COMEDI_DEFAULT_BUF_SIZE_KB int "Comedi default initial asynchronous buffer size in KiB" default "2048" - depends on COMEDI != n ---help--- This is the default asynchronous buffer size which is used for commands running in the background in kernel space. This @@ -26,7 +26,6 @@ config COMEDI_DEFAULT_BUF_SIZE_KB config COMEDI_DEFAULT_BUF_MAXSIZE_KB int "Comedi default maximum asynchronous buffer size in KiB" default "20480" - depends on COMEDI != n ---help--- This is the default maximum asynchronous buffer size which can be requested by a userspace program without root privileges. @@ -35,7 +34,6 @@ config COMEDI_DEFAULT_BUF_MAXSIZE_KB menuconfig COMEDI_MISC_DRIVERS tristate "Comedi misc drivers" - depends on COMEDI ---help--- Enable comedi misc drivers to be built @@ -103,7 +101,7 @@ endif # COMEDI_MISC_DRIVERS menuconfig COMEDI_ISA_DRIVERS tristate "Comedi ISA and PC/104 drivers" - depends on COMEDI && ISA + depends on ISA ---help--- Enable comedi ISA and PC/104 drivers to be built @@ -111,7 +109,7 @@ menuconfig COMEDI_ISA_DRIVERS kernel: saying N will just cause the configurator to skip all the questions about ISA and PC/104 comedi drivers. -if COMEDI_ISA_DRIVERS && ISA +if COMEDI_ISA_DRIVERS config COMEDI_ACL7225B tristate "ADlink NuDAQ ACL-7225b and compatibles support" @@ -543,7 +541,7 @@ endif # COMEDI_ISA_DRIVERS menuconfig COMEDI_PCI_DRIVERS tristate "Comedi PCI drivers" - depends on COMEDI && PCI + depends on PCI ---help--- Enable comedi PCI drivers to be built @@ -551,7 +549,7 @@ menuconfig COMEDI_PCI_DRIVERS kernel: saying N will just cause the configurator to skip all the questions about PCI comedi drivers. -if COMEDI_PCI_DRIVERS && PCI +if COMEDI_PCI_DRIVERS config COMEDI_ADDI_APCI_035 tristate "ADDI-DATA APCI_035 support" @@ -1099,7 +1097,7 @@ endif # COMEDI_PCI_DRIVERS menuconfig COMEDI_PCMCIA_DRIVERS tristate "Comedi PCMCIA drivers" - depends on COMEDI && (PCMCIA || PCCARD) + depends on (PCMCIA || PCCARD) ---help--- Enable comedi PCMCIA and PCCARD drivers to be built @@ -1107,7 +1105,7 @@ menuconfig COMEDI_PCMCIA_DRIVERS kernel: saying N will just cause the configurator to skip all the questions about PCMCIA comedi drivers. -if COMEDI_PCMCIA_DRIVERS && PCMCIA +if COMEDI_PCMCIA_DRIVERS config COMEDI_CB_DAS16_CS tristate "CB DAS16 series PCMCIA support" @@ -1182,7 +1180,7 @@ endif # COMEDI_PCMCIA_DRIVERS menuconfig COMEDI_USB_DRIVERS tristate "Comedi USB drivers" - depends on COMEDI && USB + depends on USB ---help--- Enable comedi USB drivers to be built @@ -1190,7 +1188,7 @@ menuconfig COMEDI_USB_DRIVERS kernel: saying N will just cause the configurator to skip all the questions about USB comedi drivers. -if COMEDI_USB_DRIVERS && USB +if COMEDI_USB_DRIVERS config COMEDI_DT9812 tristate "DataTranslation DT9812 USB module support" @@ -1290,7 +1288,6 @@ endif # COMEDI_NI_COMMON config COMEDI_8255 tristate "Generic 8255 support" - depends on COMEDI ---help--- Enable generic 8255 support. @@ -1306,23 +1303,20 @@ config COMEDI_8255 config COMEDI_FC tristate - depends on COMEDI config COMEDI_AMPLC_DIO200 tristate - depends on COMEDI select COMEDI_8255 config COMEDI_AMPLC_PC236 tristate - depends on COMEDI select COMEDI_8255 config COMEDI_AMPLC_PC263 tristate - depends on COMEDI config COMEDI_DAS08 tristate - depends on COMEDI select COMEDI_8255 + +endif # COMEDI -- GitLab From 4527715979a34601b783f5f12774586c679c2a89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 28 May 2012 23:31:39 -0700 Subject: [PATCH 0615/5711] usb: renesas_usbhs: add DMAEngine ID specification note renesas_usbhs DMAEngine uses D0FIFO/D1FIFO, but the data transfer direction should be fixed for keeping consistency. This patch explain about it on renesas_usbhs.h Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/renesas_usbhs.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 547e59cc00ea..c5d36c65c33b 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -132,6 +132,14 @@ struct renesas_usbhs_driver_param { * option: * * dma id for dmaengine + * The data transfer direction on D0FIFO/D1FIFO should be + * fixed for keeping consistency. + * So, the platform id settings will be.. + * .d0_tx_id = xx_TX, + * .d1_rx_id = xx_RX, + * or + * .d1_tx_id = xx_TX, + * .d0_rx_id = xx_RX, */ int d0_tx_id; int d0_rx_id; -- GitLab From c2e935a7db6e7354e9dd138b7f6f4c53affc09d9 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 13 Jun 2012 20:34:12 +0800 Subject: [PATCH 0616/5711] USB: move transceiver from ehci_hcd and ohci_hcd to hcd and rename it as phy - to decrease redundant since both ehci_hcd and ohci_hcd have the same variable - it helps access phy in usb core code - phy is more meaningful than transceiver Signed-off-by: Richard Zhao Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 21 ++++++++++----------- drivers/usb/host/ehci-hub.c | 2 +- drivers/usb/host/ehci.h | 4 ---- drivers/usb/host/ohci-omap.c | 27 ++++++++++++++------------- drivers/usb/host/ohci.h | 5 ----- include/linux/usb/hcd.h | 6 ++++++ 6 files changed, 31 insertions(+), 34 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 43362577b54a..3379945b095e 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -142,19 +142,19 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, if (pdata->operating_mode == FSL_USB2_DR_OTG) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - ehci->transceiver = usb_get_transceiver(); - dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n", - hcd, ehci, ehci->transceiver); + hcd->phy = usb_get_transceiver(); + dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n", + hcd, ehci, hcd->phy); - if (ehci->transceiver) { - retval = otg_set_host(ehci->transceiver->otg, + if (hcd->phy) { + retval = otg_set_host(hcd->phy->otg, &ehci_to_hcd(ehci)->self); if (retval) { - usb_put_transceiver(ehci->transceiver); + usb_put_transceiver(hcd->phy); goto err4; } } else { - dev_err(&pdev->dev, "can't find transceiver\n"); + dev_err(&pdev->dev, "can't find phy\n"); retval = -ENODEV; goto err4; } @@ -190,11 +190,10 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - if (ehci->transceiver) { - otg_set_host(ehci->transceiver->otg, NULL); - usb_put_transceiver(ehci->transceiver); + if (hcd->phy) { + otg_set_host(hcd->phy->otg, NULL); + usb_put_transceiver(hcd->phy); } usb_remove_hcd(hcd); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index fc9e7cc6ac9b..dd5eef6af6df 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -724,7 +724,7 @@ static int ehci_hub_control ( #ifdef CONFIG_USB_OTG if ((hcd->self.otg_port == (wIndex + 1)) && hcd->self.b_hnp_enable) { - otg_start_hnp(ehci->transceiver->otg); + otg_start_hnp(hcd->phy->otg); break; } #endif diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2694ed6558d2..85c3572155d1 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -175,10 +175,6 @@ struct ehci_hcd { /* one per controller */ #ifdef DEBUG struct dentry *debug_dir; #endif - /* - * OTG controllers and transceivers need software interaction - */ - struct usb_phy *transceiver; }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 9ce35d0d9d5d..eccddb461396 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -167,14 +167,15 @@ static int omap_1510_local_bus_init(void) static void start_hnp(struct ohci_hcd *ohci) { - const unsigned port = ohci_to_hcd(ohci)->self.otg_port - 1; + struct usb_hcd *hcd = ohci_to_hcd(ohci); + const unsigned port = hcd->self.otg_port - 1; unsigned long flags; u32 l; - otg_start_hnp(ohci->transceiver->otg); + otg_start_hnp(hcd->phy->otg); local_irq_save(flags); - ohci->transceiver->state = OTG_STATE_A_SUSPEND; + hcd->phy->state = OTG_STATE_A_SUSPEND; writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]); l = omap_readl(OTG_CTRL); l &= ~OTG_A_BUSREQ; @@ -211,18 +212,18 @@ static int ohci_omap_init(struct usb_hcd *hcd) #ifdef CONFIG_USB_OTG if (need_transceiver) { - ohci->transceiver = usb_get_transceiver(); - if (ohci->transceiver) { - int status = otg_set_host(ohci->transceiver->otg, + hcd->phy = usb_get_transceiver(); + if (hcd->phy) { + int status = otg_set_host(hcd->phy->otg, &ohci_to_hcd(ohci)->self); - dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n", - ohci->transceiver->label, status); + dev_dbg(hcd->self.controller, "init %s phy, status %d\n", + hcd->phy->label, status); if (status) { - usb_put_transceiver(ohci->transceiver); + usb_put_transceiver(hcd->phy); return status; } } else { - dev_err(hcd->self.controller, "can't find transceiver\n"); + dev_err(hcd->self.controller, "can't find phy\n"); return -ENODEV; } ohci->start_hnp = start_hnp; @@ -403,9 +404,9 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) struct ohci_hcd *ohci = hcd_to_ohci (hcd); usb_remove_hcd(hcd); - if (ohci->transceiver) { - (void) otg_set_host(ohci->transceiver->otg, 0); - usb_put_transceiver(ohci->transceiver); + if (hcd->phy) { + (void) otg_set_host(hcd->phy->otg, 0); + usb_put_transceiver(hcd->phy); } if (machine_is_omap_osk()) gpio_free(9); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 1b19aea25a2b..d3299143d9e2 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -372,11 +372,6 @@ struct ohci_hcd { struct ed *ed_controltail; /* last in ctrl list */ struct ed *periodic [NUM_INTS]; /* shadow int_table */ - /* - * OTG controllers and transceivers need software interaction; - * other external transceivers should be software-transparent - */ - struct usb_phy *transceiver; void (*start_hnp)(struct ohci_hcd *ohci); /* diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 7f855d50cdf5..c532cbeabfbc 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -93,6 +93,12 @@ struct usb_hcd { */ const struct hc_driver *driver; /* hw-specific hooks */ + /* + * OTG and some Host controllers need software interaction with phys; + * other external phys should be software-transparent + */ + struct usb_phy *phy; + /* Flags that need to be manipulated atomically because they can * change while the host controller is running. Always use * set_bit() or clear_bit() to change their values. -- GitLab From f6a4e494e059b7f0e361dba28f0e2d13144da1d1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 29 May 2012 16:39:09 +0300 Subject: [PATCH 0617/5711] mei: mei.txt: minor grammar fixes Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/mei/mei.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt index 2785697da59d..6ec702950719 100644 --- a/Documentation/misc-devices/mei/mei.txt +++ b/Documentation/misc-devices/mei/mei.txt @@ -50,25 +50,25 @@ Intel MEI Driver The driver exposes a misc device called /dev/mei. An application maintains communication with an Intel ME feature while -/dev/mei is open. The binding to a specific features is performed by calling +/dev/mei is open. The binding to a specific feature is performed by calling MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID. The number of instances of an Intel ME feature that can be opened at the same time depends on the Intel ME feature, but most of the features allow only a single instance. The Intel AMT Host Interface (Intel AMTHI) feature supports multiple -simultaneous user applications. Therefore, the Intel MEI driver handles -this internally by maintaining request queues for the applications. +simultaneous user connected applications. The Intel MEI driver +handles this internally by maintaining request queues for the applications. -The driver is oblivious to data that is passed between firmware feature +The driver is transparent to data that are passed between firmware feature and host application. Because some of the Intel ME features can change the system configuration, the driver by default allows only a privileged user to access it. -A code snippet for an application communicating with -Intel AMTHI client: +A code snippet for an application communicating with Intel AMTHI client: + struct mei_connect_client_data data; fd = open(MEI_DEVICE); @@ -185,7 +185,7 @@ The Intel AMT Watchdog is composed of two parts: 2) Intel MEI driver - connects to the watchdog feature, configures the watchdog and sends the heartbeats. -The Intel MEI driver uses the kernel watchdog to configure the Intel AMT +The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT Watchdog and to send heartbeats to it. The default timeout of the watchdog is 120 seconds. -- GitLab From 92f02430934ca1c1e991a1ab3541880575042697 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0618/5711] PCI: add busn_res in struct pci_bus This adds a busn_res resource in struct pci_bus. This will replace the secondary/subordinate members and will be used to build a bus number resource tree to help with bus number allocation. [bhelgaas: changelog] CC: Andrew Morton Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..ba7c5cd314b7 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -419,6 +419,7 @@ struct pci_bus { struct list_head slots; /* list of slots on this bus */ struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; struct list_head resources; /* address space routed to this bus */ + struct resource busn_res; /* bus numbers routed to this bus */ struct pci_ops *ops; /* configuration access functions */ void *sysdata; /* hook for sys-specific extension */ -- GitLab From b918c62e086b2130a7bae44110ca516ef10bfe5a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0619/5711] PCI: replace struct pci_bus secondary/subordinate with busn_res Replace the struct pci_bus secondary/subordinate members with the struct resource busn_res. Later we'll build a resource tree of these bus numbers. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/alpha/kernel/pci.c | 2 +- arch/arm/kernel/bios32.c | 2 +- arch/ia64/pci/pci.c | 2 +- arch/microblaze/pci/pci-common.c | 4 +- arch/mips/pci/pci.c | 2 +- arch/powerpc/kernel/pci-common.c | 6 +-- arch/powerpc/kernel/pci_64.c | 2 +- arch/powerpc/kernel/pci_of_scan.c | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 8 +-- arch/powerpc/platforms/pseries/pci_dlpar.c | 2 +- arch/sh/drivers/pci/pci.c | 2 +- arch/sparc/kernel/pci.c | 6 +-- arch/tile/kernel/pci.c | 4 +- arch/x86/pci/acpi.c | 2 +- arch/xtensa/kernel/pci.c | 2 +- drivers/iommu/intel-iommu.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 4 +- drivers/parisc/dino.c | 10 ++-- drivers/parisc/iosapic.c | 2 +- drivers/parisc/lba_pci.c | 22 ++++---- drivers/pci/hotplug/acpiphp_glue.c | 8 +-- drivers/pci/hotplug/cpci_hotplug_pci.c | 6 +-- drivers/pci/hotplug/pciehp_pci.c | 4 +- drivers/pci/hotplug/shpchp_pci.c | 6 +-- drivers/pci/hotplug/shpchp_sysfs.c | 6 +-- drivers/pci/iov.c | 4 +- drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 58 +++++++++++----------- drivers/pci/setup-bus.c | 24 ++++----- drivers/pcmcia/cardbus.c | 2 +- drivers/pcmcia/yenta_socket.c | 26 +++++----- 31 files changed, 117 insertions(+), 117 deletions(-) diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc16..53229a496311 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -359,7 +359,7 @@ common_init_pci(void) hose, &resources); hose->bus = bus; hose->need_domain_info = need_domain_info; - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 25552508c3fd..f07710849b58 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) if (!sys->bus) panic("PCI: unable to scan bus!"); - busnr = sys->bus->subordinate + 1; + busnr = sys->bus->busn_res.end + 1; list_add(&sys->node, head); } else { diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 524df4295c90..3ca9bed7dc50 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -384,7 +384,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } - pbus->subordinate = pci_scan_child_bus(pbus); + pbus->busn_res.end = pci_scan_child_bus(pbus); return pbus; out3: diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db14..9b32483cd0c0 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -1506,10 +1506,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->secondary = hose->first_busno; + bus->busn_res.start = hose->first_busno; hose->bus = bus; - hose->last_busno = bus->subordinate; + hose->last_busno = bus->busn_res.end; } static int __init pcibios_init(void) diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 271e8c4a54c7..0a9bf778edb5 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; if (bus) { - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c8185..3532b535698a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1646,7 +1646,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->secondary = hose->first_busno; + bus->busn_res.start = hose->first_busno; hose->bus = bus; /* Get probe mode and perform scan */ @@ -1655,12 +1655,12 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) mode = ppc_md.pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) { - bus->subordinate = hose->last_busno; + bus->busn_res.end = hose->last_busno; of_scan_bus(node, bus); } if (mode == PCI_PROBE_NORMAL) - hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); + hose->last_busno = bus->busn_res.end = pci_scan_child_bus(bus); /* Platform gets a chance to do some global fixups before * we proceed to resource allocation diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 94a54f61d341..4ff190ff24a0 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { bus = pci_bus_b(ln); - if (in_bus >= bus->number && in_bus <= bus->subordinate) + if (in_bus >= bus->number && in_bus <= bus->busn_res.end) break; bus = NULL; } diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 89dde171a6fa..a36281aa98f3 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev) } bus->primary = dev->bus->number; - bus->subordinate = busrange[1]; + bus->busn_res.end = busrange[1]; bus->bridge_ctl = 0; /* parse ranges property */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index fbdd74dac3ac..9cda6a1ad0cf 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb, dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER; fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER; parent = pe->pbus->self; - count = pe->pbus->subordinate - pe->pbus->secondary + 1; + count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1; switch(count) { case 1: bcomp = OpalPciBusAll; break; case 2: bcomp = OpalPciBus7Bits; break; @@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev, pe->pdev = NULL; pe->tce32_seg = -1; pe->mve_number = -1; - pe->rid = bus->secondary << 8; + pe->rid = bus->busn_res.start << 8; pe->dma_weight = 0; - pe_info(pe, "Secondary busses %d..%d associated with PE\n", - bus->secondary, bus->subordinate); + pe_info(pe, "Secondary busses %pR associated with PE\n", + &bus->busn_res); if (pnv_ioda_configure_pe(phb, pe)) { /* XXX What do we do here ? */ diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 8b7bafa489c2..3ccebc83dc02 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) if (!num) return; pcibios_setup_bus_devices(bus); - max = bus->secondary; + max = bus->busn_res.start; for (pass=0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 9d10a3cb8797..43068dcb451c 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose) need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; if (bus) { - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index fdaf21811670..c85bfd788f74 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, } bus->primary = dev->bus->number; - bus->subordinate = busrange[1]; + bus->busn_res.end = busrange[1]; bus->bridge_ctl = 0; /* parse ranges property, or cook one up by hand for Simba */ @@ -693,8 +693,8 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_free_resource_list(&resources); return NULL; } - bus->secondary = pbm->pci_first_busno; - bus->subordinate = pbm->pci_last_busno; + bus->busn_res.start = pbm->pci_first_busno; + bus->busn_res.end = pbm->pci_last_busno; pci_of_scan_bus(pbm, node, bus); pci_bus_add_devices(bus); diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index b56d12bf5900..54cc8d77c90c 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -329,7 +329,7 @@ int __init pcibios_init(void) */ bus = pci_scan_bus(0, controller->ops, controller); controller->root_bus = bus; - controller->last_busno = bus->subordinate; + controller->last_busno = bus->busn_res.end; } } @@ -366,7 +366,7 @@ int __init pcibios_init(void) */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && (PCI_SLOT(dev->devfn) == 0)) { - next_bus = dev->subordinate; + next_bus = dev->busn_res.end; controllers[i].mem_resources[0] = *next_bus->resource[0]; controllers[i].mem_resources[1] = diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index fc09c2754e08..350fe63c8a42 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -440,7 +440,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); if (bus) { - bus->subordinate = pci_scan_child_bus(bus); + bus->busn_res.end = pci_scan_child_bus(bus); pci_set_host_bridge_release( to_pci_host_bridge(bus->bridge), release_pci_root_info, info); diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index eb30e356f5be..9c57c1e6870c 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -187,7 +187,7 @@ static int __init pcibios_init(void) bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, pci_ctrl->ops, pci_ctrl, &resources); pci_ctrl->bus = bus; - pci_ctrl->last_busno = bus->subordinate; + pci_ctrl->last_busno = bus->busn_res.end; if (next_busno <= pci_ctrl->last_busno) next_busno = pci_ctrl->last_busno+1; } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b12af2ff8c54..2fb7d1598a68 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) if (drhd->devices[i] && drhd->devices[i]->subordinate && drhd->devices[i]->subordinate->number <= bus && - drhd->devices[i]->subordinate->subordinate >= bus) + drhd->devices[i]->subordinate->busn_res.end >= bus) return drhd->iommu; } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index edeeb516807a..09fa3c687a1f 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14168,7 +14168,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 5701_DMA_BUG); pci_dev_put(bridge); @@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge && bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 40BIT_DMA_BUG); pci_dev_put(bridge); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 432d4bbcc62a..70517b0f94e6 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; @@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; @@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus) struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n", - __func__, bus, bus->secondary, + __func__, bus, bus->busn_res.start, bus->bridge->platform_data); /* Firmware doesn't set up card-mode dino, so we have to */ @@ -998,12 +998,12 @@ static int __init dino_probe(struct parisc_device *dev) return 0; } - bus->subordinate = pci_scan_child_bus(bus); + bus->busn_res.end = pci_scan_child_bus(bus); /* This code *depends* on scanning being single threaded * if it isn't, this global bus number count will fail */ - dino_current_bus = bus->subordinate + 1; + dino_current_bus = bus->busn_res.end + 1; pci_bus_assign_resources(bus); pci_bus_add_devices(bus); return 0; diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1f9e9fefb8e7..83380c8fcb6b 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) intr_slot = PCI_SLOT(pcidev->devfn); } DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n", - pcidev->bus->secondary, intr_slot, intr_pin); + pcidev->bus->busn_res.start, intr_slot, intr_pin); return irt_find_irqline(isi, intr_slot, intr_pin); } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 052fa230bc77..cd8f9ce8720f 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d) static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d) { - u8 first_bus = d->hba.hba_bus->secondary; - u8 last_sub_bus = d->hba.hba_bus->subordinate; + u8 first_bus = d->hba.hba_bus->busn_res.start; + u8 last_sub_bus = d->hba.hba_bus->busn_res.end; if ((bus < first_bus) || (bus > last_sub_bus) || @@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int return 0; } - if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) { + if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) { DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); /* either don't want to look or know device isn't present. */ *data = ~0U; @@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) @@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int return 0; } - if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) { + if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) { DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); return 1; /* New Workaround */ } @@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = { static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) @@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus) struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n", - bus, bus->secondary, bus->bridge->platform_data); + bus, (int)bus->busn_res.start, bus->bridge->platform_data); /* ** Properly Setup MMIO resources for this bus. @@ -1511,7 +1511,7 @@ lba_driver_probe(struct parisc_device *dev) return 0; } - lba_bus->subordinate = pci_scan_child_bus(lba_bus); + lba_bus->busn_res.end = pci_scan_child_bus(lba_bus); /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { @@ -1541,7 +1541,7 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->flags |= LBA_FLAG_SKIP_PROBE; } - lba_next_bus = lba_bus->subordinate + 1; + lba_next_bus = lba_res->busn_res.end + 1; pci_bus_add_devices(lba_bus); /* Whew! Finally done! Tell services we got this one covered. */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645a..62d0ae4dfcad 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, PCI_PRIMARY_BUS, &buses); - if (((buses >> 8) & 0xff) != bus->secondary) { + if (((buses >> 8) & 0xff) != bus->busn_res.start) { buses = (buses & 0xff000000) | ((unsigned int)(bus->primary) << 0) - | ((unsigned int)(bus->secondary) << 8) - | ((unsigned int)(bus->subordinate) << 16); + | ((unsigned int)(bus->busn_res.start) << 8) + | ((unsigned int)(bus->busn_res.end) << 16); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); } return NOTIFY_OK; @@ -692,7 +692,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) * bus->subordinate value because it could have * padding in it. */ - max = bus->secondary; + max = bus->busn_res.start; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index ae853ccd0cd5..42f3a61db87c 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -292,8 +292,8 @@ int __ref cpci_configure_slot(struct slot *slot) (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { /* Find an unused bus number for the new bridge */ struct pci_bus *child; - unsigned char busnr, start = parent->secondary; - unsigned char end = parent->subordinate; + unsigned char busnr, start = parent->busn_res.start; + unsigned char end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), @@ -312,7 +312,7 @@ int __ref cpci_configure_slot(struct slot *slot) pci_dev_put(dev); continue; } - child->subordinate = pci_do_scan_bus(child); + child->busn_res.end = pci_do_scan_bus(child); pci_bus_size_bridges(child); } pci_dev_put(dev); diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 47d9dc06b109..b898f06b588d 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -37,8 +37,8 @@ static int __ref pciehp_add_bridge(struct pci_dev *dev) { struct pci_bus *parent = dev->bus; - int pass, busnr, start = parent->secondary; - int end = parent->subordinate; + int pass, busnr, start = parent->busn_res.start; + int end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), busnr)) diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index df7e4bfadae3..d021eb031b3c 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -64,8 +64,8 @@ int __ref shpchp_configure_device(struct slot *p_slot) (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { /* Find an unused bus number for the new bridge */ struct pci_bus *child; - unsigned char busnr, start = parent->secondary; - unsigned char end = parent->subordinate; + unsigned char busnr, start = parent->busn_res.start; + unsigned char end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), busnr)) @@ -84,7 +84,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) pci_dev_put(dev); continue; } - child->subordinate = pci_do_scan_bus(child); + child->busn_res.end = pci_do_scan_bus(child); pci_bus_size_bridges(child); } pci_configure_slot(dev); diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index efa30da1ae8f..eeb23ceae4a8 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha } } out += sprintf(out, "Free resources: bus numbers\n"); - for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) { + for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) { if (!pci_find_bus(pci_domain_nr(bus), busnr)) break; } - if (busnr < bus->subordinate) + if (busnr < bus->busn_res.end) out += sprintf(out, "start = %8.8x, length = %8.8x\n", - busnr, (bus->subordinate - busnr)); + busnr, (int)(bus->busn_res.end - busnr)); return out - buf; } diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 6554e1a0f634..e873060fb35b 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) if (!child) return NULL; - child->subordinate = busnr; + child->busn_res.end = busnr; child->dev.parent = bus->bridge; rc = pci_bus_add_child(child); if (rc) { @@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) iov->offset = offset; iov->stride = stride; - if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) { + if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) { dev_err(&dev->dev, "SR-IOV: bus number out of range\n"); return -ENOMEM; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..aeda6e9c245c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->subordinate; + max = bus->busn_res.end; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 658ac977cb56..651b096134dc 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -381,8 +381,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ return; - dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", - child->secondary, child->subordinate, + dev_info(&dev->dev, "PCI bridge to %pR%s\n", + &child->busn_res, dev->transparent ? " (subtractive decode)" : ""); pci_bus_remove_resources(child); @@ -599,9 +599,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, * Set up the primary, secondary and subordinate * bus numbers. */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; + child->number = child->busn_res.start = busnr; + child->primary = parent->busn_res.start; + child->busn_res.end = 0xff; if (!bridge) return child; @@ -643,8 +643,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) if (!pcibios_assign_all_busses()) return; - while (parent->parent && parent->subordinate < max) { - parent->subordinate = max; + while (parent->parent && parent->busn_res.end < max) { + parent->busn_res.end = max; pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max); parent = parent->parent; } @@ -718,15 +718,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, if (!child) goto out; child->primary = primary; - child->subordinate = subordinate; + child->busn_res.end = subordinate; child->bridge_ctl = bctl; } cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; - if (child->subordinate > max) - max = child->subordinate; + if (child->busn_res.end > max) + max = child->busn_res.end; } else { /* * We need to assign a number to this bus which we always @@ -759,8 +759,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, } buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) - | ((unsigned int)(child->secondary) << 8) - | ((unsigned int)(child->subordinate) << 16); + | ((unsigned int)(child->busn_res.start) << 8) + | ((unsigned int)(child->busn_res.end) << 16); /* * yenta.c forces a secondary latency timer of 176. @@ -805,8 +805,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, break; while (parent->parent) { if ((!pcibios_assign_all_busses()) && - (parent->subordinate > max) && - (parent->subordinate <= max+i)) { + (parent->busn_res.end > max) && + (parent->busn_res.end <= max+i)) { j = 1; } parent = parent->parent; @@ -827,7 +827,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* * Set the subordinate bus number to its real value. */ - child->subordinate = max; + child->busn_res.end = max; pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } @@ -837,19 +837,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Has only triggered on CardBus, fixup is in yenta_socket */ while (bus->parent) { - if ((child->subordinate > bus->subordinate) || - (child->number > bus->subordinate) || + if ((child->busn_res.end > bus->busn_res.end) || + (child->number > bus->busn_res.end) || (child->number < bus->number) || - (child->subordinate < bus->number)) { - dev_info(&child->dev, "[bus %02x-%02x] %s " - "hidden behind%s bridge %s [bus %02x-%02x]\n", - child->number, child->subordinate, - (bus->number > child->subordinate && - bus->subordinate < child->number) ? + (child->busn_res.end < bus->number)) { + dev_info(&child->dev, "%pR %s " + "hidden behind%s bridge %s %pR\n", + &child->busn_res, + (bus->number > child->busn_res.end && + bus->busn_res.end < child->number) ? "wholly" : "partially", bus->self->transparent ? " transparent" : "", dev_name(&bus->dev), - bus->number, bus->subordinate); + &bus->busn_res); } bus = bus->parent; } @@ -1548,7 +1548,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings); unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) { - unsigned int devfn, pass, max = bus->secondary; + unsigned int devfn, pass, max = bus->busn_res.start; struct pci_dev *dev; dev_dbg(&bus->dev, "scanning bus\n"); @@ -1642,7 +1642,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(b); - b->number = b->secondary = bus; + b->number = b->busn_res.start = bus; if (parent) dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); @@ -1693,7 +1693,7 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, if (!b) return NULL; - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); pci_bus_add_devices(b); return b; } @@ -1710,7 +1710,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, pci_add_resource(&resources, &iomem_resource); b = pci_create_root_bus(parent, bus, ops, sysdata, &resources); if (b) - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); else pci_free_resource_list(&resources); return b; @@ -1727,7 +1727,7 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, pci_add_resource(&resources, &iomem_resource); b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources); if (b) { - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); pci_bus_add_devices(b); } else { pci_free_resource_list(&resources); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8fa2d4be88de..192172c87b77 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus) struct resource *res; struct pci_bus_region region; - dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n", - bus->secondary, bus->subordinate); + dev_info(&bridge->dev, "CardBus bridge to %pR\n", + &bus->busn_res); res = bus->resource[0]; pcibios_resource_to_bus(bridge, ®ion, res); @@ -553,8 +553,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) { struct pci_dev *bridge = bus->self; - dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", - bus->secondary, bus->subordinate); + dev_info(&bridge->dev, "PCI bridge to %pR\n", + &bus->busn_res); if (type & IORESOURCE_IO) pci_setup_bridge_io(bus); @@ -745,8 +745,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window " - "%pR to [bus %02x-%02x] (unused)\n", b_res, - bus->secondary, bus->subordinate); + "%pR to %pR (unused)\n", b_res, + &bus->busn_res); b_res->flags = 0; return; } @@ -757,8 +757,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, if (size1 > size0 && realloc_head) { add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " - "%pR to [bus %02x-%02x] add_size %lx\n", b_res, - bus->secondary, bus->subordinate, size1-size0); + "%pR to %pR add_size %lx\n", b_res, + &bus->busn_res, size1-size0); } } @@ -863,8 +863,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window " - "%pR to [bus %02x-%02x] (unused)\n", b_res, - bus->secondary, bus->subordinate); + "%pR to %pR (unused)\n", b_res, + &bus->busn_res); b_res->flags = 0; return 1; } @@ -874,8 +874,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, if (size1 > size0 && realloc_head) { add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " - "%pR to [bus %02x-%02x] add_size %llx\n", b_res, - bus->secondary, bus->subordinate, (unsigned long long)size1-size0); + "%pR to %pR add_size %llx\n", b_res, + &bus->busn_res, (unsigned long long)size1-size0); } return 1; } diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 6e75153c5b4f..24caeaf50529 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); pci_fixup_cardbus(bus); - max = bus->secondary; + max = bus->busn_res.start; for (pass = 0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index d07f9ac8c41d..667678db1153 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket) config_writeb(socket, PCI_LATENCY_TIMER, 168); config_writel(socket, PCI_PRIMARY_BUS, (176 << 24) | /* sec. latency timer */ - (dev->subordinate->subordinate << 16) | /* subordinate bus */ - (dev->subordinate->secondary << 8) | /* secondary bus */ + ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */ + ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */ dev->subordinate->primary); /* primary bus */ /* @@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) struct pci_bus *bridge_to_fix = cardbus_bridge->parent; /* Check bus numbers are already set up correctly: */ - if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate) + if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end) return; /* The subordinate number is ok, nothing to do */ if (!bridge_to_fix->parent) return; /* Root bridges are ok */ /* stay within the limits of the bus range of the parent: */ - upper_limit = bridge_to_fix->parent->subordinate; + upper_limit = bridge_to_fix->parent->busn_res.end; /* check the bus ranges of all silbling bridges to prevent overlap */ list_for_each(tmp, &bridge_to_fix->parent->children) { @@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) * current upper limit, set the new upper limit to * the bus number below the silbling's range: */ - if (silbling->secondary > bridge_to_fix->subordinate - && silbling->secondary <= upper_limit) - upper_limit = silbling->secondary - 1; + if (silbling->busn_res.start > bridge_to_fix->busn_res.end + && silbling->busn_res.start <= upper_limit) + upper_limit = silbling->busn_res.start - 1; } /* Show that the wanted subordinate number is not possible: */ - if (cardbus_bridge->subordinate > upper_limit) + if (cardbus_bridge->busn_res.end > upper_limit) dev_printk(KERN_WARNING, &cardbus_bridge->dev, "Upper limit for fixing this " "bridge's parent bridge: #%02x\n", upper_limit); /* If we have room to increase the bridge's subordinate number, */ - if (bridge_to_fix->subordinate < upper_limit) { + if (bridge_to_fix->busn_res.end < upper_limit) { /* use the highest number of the hidden bus, within limits */ unsigned char subordinate_to_assign = - min(cardbus_bridge->subordinate, upper_limit); + min_t(int, cardbus_bridge->busn_res.end, upper_limit); dev_printk(KERN_INFO, &bridge_to_fix->dev, "Raising subordinate bus# of parent " "bus (#%02x) from #%02x to #%02x\n", bridge_to_fix->number, - bridge_to_fix->subordinate, subordinate_to_assign); + (int)bridge_to_fix->busn_res.end, subordinate_to_assign); /* Save the new subordinate in the bus struct of the bridge */ - bridge_to_fix->subordinate = subordinate_to_assign; + bridge_to_fix->busn_res.end = subordinate_to_assign; /* and update the PCI config space with the new subordinate */ pci_write_config_byte(bridge_to_fix->self, - PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate); + PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end); } } -- GitLab From 3527ed81ca01bbaf09df952e68528377a9cd092f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0620/5711] PCI: remove secondary/subordinate in struct pci_bus The pci_bus secondary/subordinate members are now unused, so remove them. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index ba7c5cd314b7..6b10966cd1b9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -427,8 +427,6 @@ struct pci_bus { unsigned char number; /* bus number */ unsigned char primary; /* number of primary bridge */ - unsigned char secondary; /* number of secondary bridge */ - unsigned char subordinate; /* max number of subordinate buses */ unsigned char max_bus_speed; /* enum pci_bus_speed */ unsigned char cur_bus_speed; /* enum pci_bus_speed */ -- GitLab From 5cc62c202211096ec26309722ec27455d52c8726 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0621/5711] PCI: build a bus number resource tree for every domain This adds get_pci_domain_busn_res(), which returns the root of the bus number resource tree for a domain, creating it if necessary. We will later populate the tree with the bus numbers used by host bridges and P2P bridges in the domain. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 651b096134dc..674a477a6486 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -20,6 +20,36 @@ LIST_HEAD(pci_root_buses); EXPORT_SYMBOL(pci_root_buses); +static LIST_HEAD(pci_domain_busn_res_list); + +struct pci_domain_busn_res { + struct list_head list; + struct resource res; + int domain_nr; +}; + +static struct resource *get_pci_domain_busn_res(int domain_nr) +{ + struct pci_domain_busn_res *r; + + list_for_each_entry(r, &pci_domain_busn_res_list, list) + if (r->domain_nr == domain_nr) + return &r->res; + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) + return NULL; + + r->domain_nr = domain_nr; + r->res.start = 0; + r->res.end = 0xff; + r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED; + + list_add_tail(&r->list, &pci_domain_busn_res_list); + + return &r->res; +} + static int find_anything(struct device *dev, void *data) { return 1; -- GitLab From 82ec90eac304e81b1389175b4dded7abecc678ef Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0622/5711] resources: allow adjust_resource() for resources with no parent If a resource has no parent, allow its start/end to be set arbitrarily as long as any children are still contained within the new range. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- kernel/resource.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index e1d2b8ee76d5..dc8b47764443 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -722,14 +722,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t write_lock(&resource_lock); + if (!parent) + goto skip; + if ((start < parent->start) || (end > parent->end)) goto out; - for (tmp = res->child; tmp; tmp = tmp->sibling) { - if ((tmp->start < start) || (tmp->end > end)) - goto out; - } - if (res->sibling && (res->sibling->start <= end)) goto out; @@ -741,6 +739,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t goto out; } +skip: + for (tmp = res->child; tmp; tmp = tmp->sibling) + if ((tmp->start < start) || (tmp->end > end)) + goto out; + res->start = start; res->end = end; result = 0; -- GitLab From 98a3583107ed587ed3cfe2a1d8e5347421de5a80 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 18 May 2012 11:35:50 -0600 Subject: [PATCH 0623/5711] PCI: add busn_res operation functions Will use them insert/update busn res in pci_bus struct. [bhelgaas: print conflicting entry if insertion fails] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 3 ++ 2 files changed, 71 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 674a477a6486..7662ab7b2640 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1714,6 +1714,74 @@ err_out: return NULL; } +int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max) +{ + struct resource *res = &b->busn_res; + struct resource *parent_res, *conflict; + + res->start = bus; + res->end = bus_max; + res->flags = IORESOURCE_BUS; + + if (!pci_is_root_bus(b)) + parent_res = &b->parent->busn_res; + else { + parent_res = get_pci_domain_busn_res(pci_domain_nr(b)); + res->flags |= IORESOURCE_PCI_FIXED; + } + + conflict = insert_resource_conflict(parent_res, res); + + if (conflict) + dev_printk(KERN_DEBUG, &b->dev, + "busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n", + res, pci_is_root_bus(b) ? "domain " : "", + parent_res, conflict->name, conflict); + else + dev_printk(KERN_DEBUG, &b->dev, + "busn_res: %pR is inserted under %s%pR\n", + res, pci_is_root_bus(b) ? "domain " : "", + parent_res); + + return conflict == NULL; +} + +int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max) +{ + struct resource *res = &b->busn_res; + struct resource old_res = *res; + resource_size_t size; + int ret; + + if (res->start > bus_max) + return -EINVAL; + + size = bus_max - res->start + 1; + ret = adjust_resource(res, res->start, size); + dev_printk(KERN_DEBUG, &b->dev, + "busn_res: %pR end %s updated to %02x\n", + &old_res, ret ? "can not be" : "is", bus_max); + + if (!ret && !res->parent) + pci_bus_insert_busn_res(b, res->start, res->end); + + return ret; +} + +void pci_bus_release_busn_res(struct pci_bus *b) +{ + struct resource *res = &b->busn_res; + int ret; + + if (!res->flags || !res->parent) + return; + + ret = release_resource(res); + dev_printk(KERN_DEBUG, &b->dev, + "busn_res: %pR %s released\n", + res, ret ? "can not be" : "is"); +} + struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 6b10966cd1b9..c4df570f3bbb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -667,6 +667,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata); struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources); +int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax); +int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax); +void pci_bus_release_busn_res(struct pci_bus *b); struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources); -- GitLab From f6dd68a77f9c07088eee71a1787cfc84dcf49198 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: [PATCH 0624/5711] PCI: release busn_res when removing bus Release bus number resource when removing a bus. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/remove.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index fd77e2bde2e8..04a4861b4749 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus) down_write(&pci_bus_sem); list_del(&pci_bus->node); + pci_bus_release_busn_res(pci_bus); up_write(&pci_bus_sem); if (!pci_bus->is_added) return; -- GitLab From f848ffb1043ed0d168064176fb452cc51ec8e0b7 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0625/5711] PCI: insert busn_res in pci_create_root_bus() That busn_res is from resources list. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7662ab7b2640..59011ce9840f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1684,7 +1684,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, list_move_tail(&window->list, &bridge->windows); res = window->res; offset = window->offset; - pci_bus_add_resource(b, res, 0); + if (res->flags & IORESOURCE_BUS) + pci_bus_insert_busn_res(b, bus, res->end); + else + pci_bus_add_resource(b, res, 0); if (offset) { if (resource_type(res) == IORESOURCE_IO) fmt = " (bus address [%#06llx-%#06llx])"; -- GitLab From 4d99f524234c2e772eea68ad019ec9c805991f23 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0626/5711] PCI: checking busn_res in pci_scan_root_bus() Some callers do not supply the bus number aperture, usually because they do not know the end. In this case, we assume the aperture extends from the root bus number to bus 255, scan the bus, and shrink the bus number resource so it ends at the largest bus number we found. This is obviously not correct because the actual end of the aperture may well be larger than the largest bus number we found. But I guess it's all we have for now. Also print out one info about that, so we could find out which path does not have busn_res in resources list. [bhelgaas: changelog, _safe iterator unnecessary, use %pR format for bus] Signed-off-by: Yinghai Lu --- drivers/pci/probe.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 59011ce9840f..6258f6f24983 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1788,13 +1788,33 @@ void pci_bus_release_busn_res(struct pci_bus *b) struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { + struct pci_host_bridge_window *window; + bool found = false; struct pci_bus *b; + int max; + + list_for_each_entry(window, resources, list) + if (window->res->flags & IORESOURCE_BUS) { + found = true; + break; + } b = pci_create_root_bus(parent, bus, ops, sysdata, resources); if (!b) return NULL; - b->busn_res.end = pci_scan_child_bus(b); + if (!found) { + dev_info(&b->dev, + "No busn resource found for root bus, will use [bus %02x-ff]\n", + bus); + pci_bus_insert_busn_res(b, bus, 255); + } + + max = pci_scan_child_bus(b); + + if (!found) + pci_bus_update_busn_res_end(b, max); + pci_bus_add_devices(b); return b; } -- GitLab From 67cdc827286366acb6c60c821013c1185ee00b36 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0627/5711] PCI: add default busn_resource We need to put into the resources list for legacy system. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 7 +++++++ include/linux/pci.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6258f6f24983..68e75cb0831b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -16,6 +16,13 @@ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_RESERVE_BUSNR 3 +struct resource busn_resource = { + .name = "PCI busn", + .start = 0, + .end = 255, + .flags = IORESOURCE_BUS, +}; + /* Ugh. Need to stop exporting this to modules. */ LIST_HEAD(pci_root_buses); EXPORT_SYMBOL(pci_root_buses); diff --git a/include/linux/pci.h b/include/linux/pci.h index c4df570f3bbb..8c8b44d62105 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -368,6 +368,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev) return (pdev->error_state != pci_channel_io_normal); } +extern struct resource busn_resource; + struct pci_host_bridge_window { struct list_head list; struct resource *res; /* host bridge aperture (CPU address) */ -- GitLab From 857c3b668ae35c48d9d7a4248b6c0bdb65797d0e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0628/5711] PCI: add default busn_res for pci_scan_bus() also do not need to shrink busn_res. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 68e75cb0831b..9f68b9d3597c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1836,9 +1836,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, pci_add_resource(&resources, &ioport_resource); pci_add_resource(&resources, &iomem_resource); + pci_add_resource(&resources, &busn_resource); b = pci_create_root_bus(parent, bus, ops, sysdata, &resources); if (b) - b->busn_res.end = pci_scan_child_bus(b); + pci_scan_child_bus(b); else pci_free_resource_list(&resources); return b; @@ -1853,9 +1854,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, pci_add_resource(&resources, &ioport_resource); pci_add_resource(&resources, &iomem_resource); + pci_add_resource(&resources, &busn_resource); b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources); if (b) { - b->busn_res.end = pci_scan_child_bus(b); + pci_scan_child_bus(b); pci_bus_add_devices(b); } else { pci_free_resource_list(&resources); -- GitLab From 5c1d81d160cc46e36fdd06702885c98c2643b4c5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0629/5711] x86/PCI: use _CRS bus number aperture for host bridges from ACPI Add the host bridge bus number aperture from _CRS to the resource list. Like the MMIO and I/O port apertures, this will be used when assigning resources to hot-added devices or in the case of conflicts. Note that we always use the _CRS bus number aperture, even if we're ignoring _CRS otherwise. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/acpi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 350fe63c8a42..2bb885afe103 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -12,7 +12,6 @@ struct pci_root_info { char name[16]; unsigned int res_num; struct resource *res; - int busnum; struct pci_sysdata sd; }; @@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, { size_t size; + sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); info->bridge = device; + info->res_num = 0; acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, info); @@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, if (!info->res) return; - sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); - acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, info); } @@ -426,6 +425,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) } else { probe_pci_root_info(info, device, busnum, domain); + /* insert busn res at first */ + pci_add_resource(&resources, &root->secondary); /* * _CRS with no apertures is normal, so only fall back to * defaults or native bridge info if we're ignoring _CRS. @@ -440,7 +441,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); if (bus) { - bus->busn_res.end = pci_scan_child_bus(bus); + pci_scan_child_bus(bus); pci_set_host_bridge_release( to_pci_host_bridge(bus->bridge), release_pci_root_info, info); -- GitLab From a10bb128b64fe03198c4930f4483dda55c5c84eb Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0630/5711] x86/PCI: put busn resource in pci_root_info for native host bridge drivers Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this will be used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog, tidy printk] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/amd_bus.c | 7 +++---- arch/x86/pci/bus_numa.c | 22 +++++++++++++++++++--- arch/x86/pci/bus_numa.h | 3 +-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 5aed49bff058..e9e6ed5cdf94 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void) link = (reg >> 8) & 0x03; info = alloc_pci_root_info(min_bus, max_bus, node, link); - sprintf(info->name, "PCI Bus #%02x", min_bus); } /* get the default node and link for left over res */ @@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void) int busnum; struct pci_root_res *root_res; - busnum = info->bus_min; - printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", - info->bus_min, info->bus_max, info->node, info->link); + busnum = info->busn.start; + printk(KERN_DEBUG "bus: %pR on node %x link %x\n", + &info->busn, info->node, info->link); list_for_each_entry(root_res, &info->resources, list) printk(KERN_DEBUG "bus: %02x %pR\n", busnum, &root_res->res); diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index 306579f7d0fd..d37e2fec97e5 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c @@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus) return NULL; list_for_each_entry(info, &pci_root_infos, list) - if (info->bus_min == bus) + if (info->busn.start == bus) return info; return NULL; @@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) { struct pci_root_info *info = x86_find_pci_root_info(bus); struct pci_root_res *root_res; + struct pci_host_bridge_window *window; + bool found = false; if (!info) goto default_resources; @@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", bus); + /* already added by acpi ? */ + list_for_each_entry(window, resources, list) + if (window->res->flags & IORESOURCE_BUS) { + found = true; + break; + } + + if (!found) + pci_add_resource(resources, &info->busn); + list_for_each_entry(root_res, &info->resources, list) { struct resource *res; struct resource *root; @@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max, if (!info) return info; + sprintf(info->name, "PCI Bus #%02x", bus_min); + INIT_LIST_HEAD(&info->resources); - info->bus_min = bus_min; - info->bus_max = bus_max; + info->busn.name = info->name; + info->busn.start = bus_min; + info->busn.end = bus_max; + info->busn.flags = IORESOURCE_BUS; info->node = node; info->link = link; diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index 226a466b2b2b..ff8f65b04574 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h @@ -13,8 +13,7 @@ struct pci_root_info { struct list_head list; char name[12]; struct list_head resources; - int bus_min; - int bus_max; + struct resource busn; int node; int link; }; -- GitLab From 2661b819a10d432aa6f508630ff72e31367d4f21 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0631/5711] ia64/PCI: register busn_res for root buses Add the host bridge bus number aperture from _CRS to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog] CC: Tony Luck CC: Fenghua Yu CC: linux-ia64@vger.kernel.org Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 3ca9bed7dc50..d173a88d744a 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root) #endif INIT_LIST_HEAD(&info.resources); + /* insert busn resource at first */ + pci_add_resource(&info.resources, &root->secondary); acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); if (windows) { @@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } - pbus->busn_res.end = pci_scan_child_bus(pbus); + pci_scan_child_bus(pbus); return pbus; out3: -- GitLab From 3f1b540d460589e20df882aa2c86808d113890a8 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0632/5711] sparc/PCI: register busn_res for root buses Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog, fix "pci_last_busn" typo] Acked-by: "David S. Miller" CC: sparclinux@vger.kernel.org Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pci.c | 8 +++++--- arch/sparc/kernel/pci_impl.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index c85bfd788f74..4f92a9aba358 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, } bus->primary = dev->bus->number; - bus->busn_res.end = busrange[1]; + pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; /* parse ranges property, or cook one up by hand for Simba */ @@ -685,6 +685,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pbm->io_space.start); pci_add_resource_offset(&resources, &pbm->mem_space, pbm->mem_space.start); + pbm->busn.start = pbm->pci_first_busno; + pbm->busn.end = pbm->pci_last_busno; + pbm->busn.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &pbm->busn); bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm, &resources); if (!bus) { @@ -693,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_free_resource_list(&resources); return NULL; } - bus->busn_res.start = pbm->pci_first_busno; - bus->busn_res.end = pbm->pci_last_busno; pci_of_scan_bus(pbm, node, bus); pci_bus_add_devices(bus); diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index 6beb60df31d0..918a2031c8bb 100644 --- a/arch/sparc/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h @@ -97,6 +97,7 @@ struct pci_pbm_info { /* PBM I/O and Memory space resources. */ struct resource io_space; struct resource mem_space; + struct resource busn; /* Base of PCI Config space, can be per-PBM or shared. */ unsigned long config_space; -- GitLab From be8e60d8bed118b19bd7038ac2f6ac6688d072d9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0633/5711] powerpc/PCI: register busn_res for root buses Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog] CC: Paul Mackerras CC: linuxppc-dev@lists.ozlabs.org CC: Benjamin Herrenschmidt Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/powerpc/include/asm/pci-bridge.h | 1 + arch/powerpc/kernel/pci-common.c | 17 +++++++++++------ arch/powerpc/kernel/pci_of_scan.c | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a3b25a..8cccbee61519 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -30,6 +30,7 @@ struct pci_controller { int first_busno; int last_busno; int self_busno; + struct resource busn; void __iomem *io_base_virt; #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 3532b535698a..7320f3685523 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1637,6 +1637,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) /* Wire up PHB bus resources */ pcibios_setup_phb_resources(hose, &resources); + hose->busn.start = hose->first_busno; + hose->busn.end = hose->last_busno; + hose->busn.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &hose->busn); + /* Create an empty bus for the toplevel */ bus = pci_create_root_bus(hose->parent, hose->first_busno, hose->ops, hose, &resources); @@ -1646,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->busn_res.start = hose->first_busno; hose->bus = bus; /* Get probe mode and perform scan */ @@ -1654,13 +1658,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) if (node && ppc_md.pci_probe_mode) mode = ppc_md.pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); - if (mode == PCI_PROBE_DEVTREE) { - bus->busn_res.end = hose->last_busno; + if (mode == PCI_PROBE_DEVTREE) of_scan_bus(node, bus); - } - if (mode == PCI_PROBE_NORMAL) - hose->last_busno = bus->busn_res.end = pci_scan_child_bus(bus); + if (mode == PCI_PROBE_NORMAL) { + pci_bus_update_busn_res_end(bus, 255); + hose->last_busno = pci_scan_child_bus(bus); + pci_bus_update_busn_res_end(bus, hose->last_busno); + } /* Platform gets a chance to do some global fixups before * we proceed to resource allocation diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index a36281aa98f3..ae5ea5e04d65 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev) } bus->primary = dev->bus->number; - bus->busn_res.end = busrange[1]; + pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; /* parse ranges property */ -- GitLab From 30aa80da43a5f23728eae1516e3a1aad40e808dd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: [PATCH 0634/5711] parisc/PCI: register busn_res for root buses Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog, set flags directly, at LBA bus_num init] CC: Kyle McMartin CC: Helge Deller CC: linux-parisc@vger.kernel.org Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/parisc/dino.c | 10 ++++++++-- drivers/parisc/lba_pci.c | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 70517b0f94e6..ffddc4f64268 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -898,6 +898,7 @@ static int __init dino_probe(struct parisc_device *dev) LIST_HEAD(resources); struct pci_bus *bus; unsigned long hpa = dev->hpa.start; + int max; name = "Dino"; if (is_card_dino(&dev->id)) { @@ -983,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev) if (dino_dev->hba.gmmio_space.flags) pci_add_resource(&resources, &dino_dev->hba.gmmio_space); + dino_dev->hba.bus_num.start = dino_current_bus; + dino_dev->hba.bus_num.end = 255; + dino_dev->hba.bus_num.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &dino_dev->hba.bus_num); /* ** It's not used to avoid chicken/egg problems ** with configuration accessor functions. @@ -998,12 +1003,13 @@ static int __init dino_probe(struct parisc_device *dev) return 0; } - bus->busn_res.end = pci_scan_child_bus(bus); + max = pci_scan_child_bus(bus); + pci_bus_update_busn_res_end(bus, max); /* This code *depends* on scanning being single threaded * if it isn't, this global bus number count will fail */ - dino_current_bus = bus->busn_res.end + 1; + dino_current_bus = max + 1; pci_bus_assign_resources(bus); pci_bus_add_devices(bus); return 0; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index cd8f9ce8720f..4f9cf2456f4e 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -989,6 +989,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_PBNUM: lba_dev->hba.bus_num.start = p->start; lba_dev->hba.bus_num.end = p->end; + lba_dev->hba.bus_num.flags = IORESOURCE_BUS; break; case PAT_LMMIO: @@ -1366,6 +1367,7 @@ lba_driver_probe(struct parisc_device *dev) void *tmp_obj; char *version; void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); + int max; /* Read HW Rev First */ func_class = READ_REG32(addr + LBA_FCLASS); @@ -1502,6 +1504,8 @@ lba_driver_probe(struct parisc_device *dev) if (lba_dev->hba.gmmio_space.flags) pci_add_resource(&resources, &lba_dev->hba.gmmio_space); + pci_add_resource(&resources, &lba_dev->hba.bus_num); + dev->dev.platform_data = lba_dev; lba_bus = lba_dev->hba.hba_bus = pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start, @@ -1511,7 +1515,7 @@ lba_driver_probe(struct parisc_device *dev) return 0; } - lba_bus->busn_res.end = pci_scan_child_bus(lba_bus); + max = pci_scan_child_bus(lba_bus); /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { @@ -1541,7 +1545,7 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->flags |= LBA_FLAG_SKIP_PROBE; } - lba_next_bus = lba_res->busn_res.end + 1; + lba_next_bus = max + 1; pci_bus_add_devices(lba_bus); /* Whew! Finally done! Tell services we got this one covered. */ -- GitLab From b17c0e6f665023ae729ca112516c7b6f3b71f9d3 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0635/5711] tile/PCI: use pci_scan_root_bus instead pci_scan_bus It will update busn_res accordingly, so we get that for last_busno. Acked-by: Chris Metcalf Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/tile/kernel/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 54cc8d77c90c..87422ed7b834 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -310,6 +310,7 @@ int __init pcibios_init(void) if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { struct pci_controller *controller = &controllers[i]; struct pci_bus *bus; + LIST_HEAD(resources); if (tile_init_irqs(i, controller)) { pr_err("PCI: Could not initialize IRQs\n"); @@ -327,7 +328,9 @@ int __init pcibios_init(void) * This is inlined in linux/pci.h and calls into * pci_scan_bus_parented() in probe.c. */ - bus = pci_scan_bus(0, controller->ops, controller); + pci_add_resource(&resources, &ioport_resource); + pci_add_resource(&resources, &iomem_resource); + bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources); controller->root_bus = bus; controller->last_busno = bus->busn_res.end; } -- GitLab From b7eac055c0a8f6026393a83cdf9699e9052eae25 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0636/5711] PCI: register busn_res for iov bus Insert that to tree. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index e873060fb35b..74bbaf82638d 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) if (!child) return NULL; - child->busn_res.end = busnr; + pci_bus_insert_busn_res(child, busnr, busnr); child->dev.parent = bus->bridge; rc = pci_bus_add_child(child); if (rc) { -- GitLab From bc76b7310a352be1c2ed24133e89c5df24eff05e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0637/5711] PCI: insert busn_res for child bus Now we can insert busn_res now, after all root bus's get inserted. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9f68b9d3597c..08404098080b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -755,7 +755,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, if (!child) goto out; child->primary = primary; - child->busn_res.end = subordinate; + pci_bus_insert_busn_res(child, secondary, subordinate); child->bridge_ctl = bctl; } @@ -793,6 +793,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, child = pci_add_new_bus(bus, dev, ++max); if (!child) goto out; + pci_bus_insert_busn_res(child, max, 0xff); } buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) @@ -864,7 +865,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* * Set the subordinate bus number to its real value. */ - child->busn_res.end = max; + pci_bus_update_busn_res_end(child, max); pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } -- GitLab From f406384628e97618955e17e8d61e59d5ecdc9ca0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0638/5711] PCI: cpci_hotplug: register busn_res Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/cpci_hotplug_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 42f3a61db87c..111b7d94c9a9 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -294,6 +294,7 @@ int __ref cpci_configure_slot(struct slot *slot) struct pci_bus *child; unsigned char busnr, start = parent->busn_res.start; unsigned char end = parent->busn_res.end; + int max; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), @@ -312,7 +313,8 @@ int __ref cpci_configure_slot(struct slot *slot) pci_dev_put(dev); continue; } - child->busn_res.end = pci_do_scan_bus(child); + max = pci_do_scan_bus(child); + pci_bus_update_busn_res_end(child, max); pci_bus_size_bridges(child); } pci_dev_put(dev); -- GitLab From 6cda0fcf26df18f0e5476fbff12845cc46e1f41b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0639/5711] PCI: shpchp: register busn_res Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/shpchp_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index d021eb031b3c..13069802b8c8 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -66,6 +66,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) struct pci_bus *child; unsigned char busnr, start = parent->busn_res.start; unsigned char end = parent->busn_res.end; + int max; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), busnr)) @@ -84,7 +85,8 @@ int __ref shpchp_configure_device(struct slot *p_slot) pci_dev_put(dev); continue; } - child->busn_res.end = pci_do_scan_bus(child); + max = pci_do_scan_bus(child); + pci_bus_update_busn_res_end(child, max); pci_bus_size_bridges(child); } pci_configure_slot(dev); -- GitLab From 450878759aa10c6d172a0cafd5922b23a3b4547a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0640/5711] PCI: cpqhp: register busn_res Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/cpqphp_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 1c8494021a42..24716725263f 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -106,9 +106,11 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) } if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + int max; pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); - pci_do_scan_bus(child); + max = pci_do_scan_bus(child); + pci_bus_update_busn_res_end(child, max); } pci_dev_put(func->pci_dev); -- GitLab From d0a350fe57c0a4014a8eccf8166d7dc2e599ce5c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0641/5711] PCI: ibmhp: register busn_res Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/ibmphp_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 4fda7e6a86a7..a62f296e8b0d 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -805,9 +805,11 @@ static int ibm_configure_device(struct pci_func *func) } } if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { + int max; pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus); child = pci_add_new_bus(func->dev->bus, func->dev, bus); - pci_do_scan_bus(child); + max = pci_do_scan_bus(child); + pci_bus_update_busn_res_end(child, max); } return 0; -- GitLab From 85019faf4a88477cc72f56b6e371955ea0bb7a2a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: [PATCH 0642/5711] PCI: sgihp: register busn_res Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/sgi_hotplug.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index de573113c102..b0bb3b537bb0 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -398,11 +398,13 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) sn_io_slot_fixup(dev); if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { unsigned char sec_bus; + int max; pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_bus); new_bus = pci_add_new_bus(dev->bus, dev, sec_bus); - pci_scan_child_bus(new_bus); + max = pci_scan_child_bus(new_bus); + pci_bus_update_busn_res_end(new_bus, max); new_ppb = 1; } pci_dev_put(dev); -- GitLab From a8e4b9c101ae58cc64cda0201229d3318701a7f0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 18 May 2012 13:46:34 -0600 Subject: [PATCH 0643/5711] PCI: add generic pci_hp_add_bridge() This creates a generic pci_hp_add_bridge() that can be used by several hotplug drivers. [bhelgaas: split out from pciehp patch] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug-pci.c | 23 +++++++++++++++++++++++ drivers/pci/pci.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c index d3509cdeb554..44088c4fe687 100644 --- a/drivers/pci/hotplug-pci.c +++ b/drivers/pci/hotplug-pci.c @@ -4,6 +4,29 @@ #include #include "pci.h" +int __ref pci_hp_add_bridge(struct pci_dev *dev) +{ + struct pci_bus *parent = dev->bus; + int pass, busnr, start = parent->busn_res.start; + int end = parent->busn_res.end; + + for (busnr = start; busnr <= end; busnr++) { + if (!pci_find_bus(pci_domain_nr(parent), busnr)) + break; + } + if (busnr-- > end) { + printk(KERN_ERR "No bus number available for hot-added bridge %s\n", + pci_name(dev)); + return -1; + } + for (pass = 0; pass < 2; pass++) + busnr = pci_scan_bridge(parent, dev, busnr, pass); + if (!dev->subordinate) + return -1; + + return 0; +} +EXPORT_SYMBOL_GPL(pci_hp_add_bridge); unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e4943479b234..f3e14ce8eab7 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -124,6 +124,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } #endif /* Functions for PCI Hotplug drivers to use */ +int pci_hp_add_bridge(struct pci_dev *dev); extern unsigned int pci_do_scan_bus(struct pci_bus *bus); #ifdef HAVE_PCI_LEGACY -- GitLab From c6da81a4d3cb8d461f77c5f61843fcc9c18b6c2c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0644/5711] PCI: pciehp: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: split "add generic pci_hp_add_bridge()" into a separate patch] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_pci.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index b898f06b588d..09cecaf450c5 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -34,29 +34,6 @@ #include "../pci.h" #include "pciehp.h" -static int __ref pciehp_add_bridge(struct pci_dev *dev) -{ - struct pci_bus *parent = dev->bus; - int pass, busnr, start = parent->busn_res.start; - int end = parent->busn_res.end; - - for (busnr = start; busnr <= end; busnr++) { - if (!pci_find_bus(pci_domain_nr(parent), busnr)) - break; - } - if (busnr-- > end) { - err("No bus number available for hot-added bridge %s\n", - pci_name(dev)); - return -1; - } - for (pass = 0; pass < 2; pass++) - busnr = pci_scan_bridge(parent, dev, busnr, pass); - if (!dev->subordinate) - return -1; - - return 0; -} - int pciehp_configure_device(struct slot *p_slot) { struct pci_dev *dev; @@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot) if (!dev) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || - (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { - pciehp_add_bridge(dev); - } + (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) + pci_hp_add_bridge(dev); pci_dev_put(dev); } -- GitLab From 073ae10c0f8284b6c6dd9708656802507349ef91 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0645/5711] PCI: cpci_hotplug: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/cpci_hotplug_pci.c | 37 +++++--------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 111b7d94c9a9..dcc75c785443 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -285,44 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot) for (fn = 0; fn < 8; fn++) { struct pci_dev *dev; - dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); + dev = pci_get_slot(parent, + PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); if (!dev) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || - (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { - /* Find an unused bus number for the new bridge */ - struct pci_bus *child; - unsigned char busnr, start = parent->busn_res.start; - unsigned char end = parent->busn_res.end; - int max; - - for (busnr = start; busnr <= end; busnr++) { - if (!pci_find_bus(pci_domain_nr(parent), - busnr)) - break; - } - if (busnr >= end) { - err("No free bus for hot-added bridge\n"); - pci_dev_put(dev); - continue; - } - child = pci_add_new_bus(parent, dev, busnr); - if (!child) { - err("Cannot add new bus for %s\n", - pci_name(dev)); - pci_dev_put(dev); - continue; - } - max = pci_do_scan_bus(child); - pci_bus_update_busn_res_end(child, max); - pci_bus_size_bridges(child); - } + (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) + pci_hp_add_bridge(dev); pci_dev_put(dev); } - pci_bus_assign_resources(parent); + pci_assign_unassigned_bridge_resources(parent->self); + pci_bus_add_devices(parent); - pci_enable_bridges(parent); dbg("%s - exit", __func__); return 0; -- GitLab From 7d01f70ac6f48733d595f1a54aa7c4d2ae3fef0d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0646/5711] PCI: shpchp: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/shpchp_pci.c | 47 ++++++++++---------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 13069802b8c8..c627ed9957d1 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -37,9 +37,10 @@ int __ref shpchp_configure_device(struct slot *p_slot) { struct pci_dev *dev; - struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; - int num, fn; struct controller *ctrl = p_slot->ctrl; + struct pci_dev *bridge = ctrl->pci_dev; + struct pci_bus *parent = bridge->subordinate; + int num, fn; dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { @@ -61,41 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot) if (!dev) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || - (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { - /* Find an unused bus number for the new bridge */ - struct pci_bus *child; - unsigned char busnr, start = parent->busn_res.start; - unsigned char end = parent->busn_res.end; - int max; - for (busnr = start; busnr <= end; busnr++) { - if (!pci_find_bus(pci_domain_nr(parent), - busnr)) - break; - } - if (busnr > end) { - ctrl_err(ctrl, - "No free bus for hot-added bridge\n"); - pci_dev_put(dev); - continue; - } - child = pci_add_new_bus(parent, dev, busnr); - if (!child) { - ctrl_err(ctrl, "Cannot add new bus for %s\n", - pci_name(dev)); - pci_dev_put(dev); - continue; - } - max = pci_do_scan_bus(child); - pci_bus_update_busn_res_end(child, max); - pci_bus_size_bridges(child); - } + (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) + pci_hp_add_bridge(dev); + pci_dev_put(dev); + } + + pci_assign_unassigned_bridge_resources(bridge); + + for (fn = 0; fn < 8; fn++) { + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); + if (!dev) + continue; pci_configure_slot(dev); pci_dev_put(dev); } - pci_bus_assign_resources(parent); pci_bus_add_devices(parent); - pci_enable_bridges(parent); + return 0; } -- GitLab From 04de975e7840e6d9da3ef44ab414f3ee1b98d611 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0647/5711] PCI: cpqhp: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/cpqphp_pci.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 24716725263f..09801c6945ce 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) { - unsigned char bus; struct pci_bus *child; int num; @@ -106,11 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) } if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - int max; - pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); - child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); - max = pci_do_scan_bus(child); - pci_bus_update_busn_res_end(child, max); + pci_hp_add_bridge(func->pci_dev); + child = func->pci_dev->subordinate; + if (child) + pci_bus_add_devices(child); } pci_dev_put(func->pci_dev); -- GitLab From 2d7abf32925f1a8aeeb37234c8ea7590ebbe62be Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0648/5711] PCI: ibmhp: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/ibmphp_core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index a62f296e8b0d..7dccad5fc891 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno) static int ibm_configure_device(struct pci_func *func) { - unsigned char bus; struct pci_bus *child; int num; int flag = 0; /* this is to make sure we don't double scan the bus, @@ -805,11 +804,10 @@ static int ibm_configure_device(struct pci_func *func) } } if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { - int max; - pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus); - child = pci_add_new_bus(func->dev->bus, func->dev, bus); - max = pci_do_scan_bus(child); - pci_bus_update_busn_res_end(child, max); + pci_hp_add_bridge(func->dev); + child = func->dev->subordinate; + if (child) + pci_bus_add_devices(child); } return 0; -- GitLab From 69ba29b9f91317b0cb8a4891c0cc6270a6f77ec9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0649/5711] PCI: sgihp: use generic pci_hp_add_bridge() Use the new generic pci_hp_add_bridge() interface. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/sgi_hotplug.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index b0bb3b537bb0..f64ca92253da 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -397,15 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) else sn_io_slot_fixup(dev); if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - unsigned char sec_bus; - int max; - pci_read_config_byte(dev, PCI_SECONDARY_BUS, - &sec_bus); - new_bus = pci_add_new_bus(dev->bus, dev, - sec_bus); - max = pci_scan_child_bus(new_bus); - pci_bus_update_busn_res_end(new_bus, max); - new_ppb = 1; + pci_hp_add_bridge(dev); + if (dev->subordinate) { + new_bus = dev->subordinate; + new_ppb = 1; + } } pci_dev_put(dev); } -- GitLab From 06aef8cec7563c40c7d7501d13ec1ed12f5e495b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:58:41 -0700 Subject: [PATCH 0650/5711] PCI: hotplug: remove pci_do_scan_bus() All callers of pci_do_scan_bus() are gone, so remove it. Note that pci_do_scan_bus() was exported, so out-of-tree modules could depend on it. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug-pci.c | 15 --------------- drivers/pci/pci.h | 1 - 2 files changed, 16 deletions(-) diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c index 44088c4fe687..6258dc260d9f 100644 --- a/drivers/pci/hotplug-pci.c +++ b/drivers/pci/hotplug-pci.c @@ -27,18 +27,3 @@ int __ref pci_hp_add_bridge(struct pci_dev *dev) return 0; } EXPORT_SYMBOL_GPL(pci_hp_add_bridge); - -unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) -{ - unsigned int max; - - max = pci_scan_child_bus(bus); - - /* - * Make the discovered devices available. - */ - pci_bus_add_devices(bus); - - return max; -} -EXPORT_SYMBOL(pci_do_scan_bus); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f3e14ce8eab7..1c56ea8110b1 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -125,7 +125,6 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } /* Functions for PCI Hotplug drivers to use */ int pci_hp_add_bridge(struct pci_dev *dev); -extern unsigned int pci_do_scan_bus(struct pci_bus *bus); #ifdef HAVE_PCI_LEGACY extern void pci_create_legacy_files(struct pci_bus *bus); -- GitLab From a276400d14bb5b98a5db1d87bbee7b1621abe4a1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 May 2012 12:24:59 +0200 Subject: [PATCH 0651/5711] USB: option: use usb_{get,set}_serial_data Use usb_{get,set}_serial_data to access usb-serial data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1aae9028cd0b..6cb40ec52532 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1347,12 +1347,15 @@ static int option_probe(struct usb_serial *serial, serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; - data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; data->send_setup = option_send_setup; spin_lock_init(&data->susp_lock); data->private = (void *)id->driver_info; + + usb_set_serial_data(serial, data); + return 0; } @@ -1419,8 +1422,7 @@ static void option_instat_callback(struct urb *urb) static int option_send_setup(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct usb_wwan_intf_private *intfdata = - (struct usb_wwan_intf_private *) serial->private; + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct option_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; -- GitLab From 378fac2a46decbcd16b42044303ba8a1a3f8001e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 May 2012 12:25:00 +0200 Subject: [PATCH 0652/5711] USB: option: clean up probe coding style Clean up option probe by introducing intermediate variables and fixing up comments. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 38 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6ff37e67adfa..ccf7f3c9a7c6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1306,33 +1306,41 @@ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { struct usb_wwan_intf_private *data; + struct usb_interface_descriptor *iface_desc = + &serial->interface->cur_altsetting->desc; + struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; - /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ - if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && - serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && - serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8) + /* + * D-Link DWM 652 still exposes CD-Rom emulation interface in modem + * mode. + */ + if (dev_desc->idVendor == DLINK_VENDOR_ID && + dev_desc->idProduct == DLINK_PRODUCT_DWM_652 && + iface_desc->bInterfaceClass == 0x08) return -ENODEV; /* Bandrich modem and AT command interface is 0xff */ - if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID || - serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) && - serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) + if ((dev_desc->idVendor == BANDRICH_VENDOR_ID || + dev_desc->idVendor == PIRELLI_VENDOR_ID) && + iface_desc->bInterfaceClass != 0xff) return -ENODEV; - - /* Don't bind reserved interfaces (like network ones) which often have + /* + * Don't bind reserved interfaces (like network ones) which often have * the same class/subclass/protocol as the serial interfaces. Look at * the Windows driver .INF files for reserved interface numbers. */ if (is_blacklisted( - serial->interface->cur_altsetting->desc.bInterfaceNumber, + iface_desc->bInterfaceNumber, OPTION_BLACKLIST_RESERVED_IF, (const struct option_blacklist_info *) id->driver_info)) return -ENODEV; - - /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */ - if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID && - serial->dev->descriptor.idProduct == SAMSUNG_PRODUCT_GT_B3730 && - serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) + /* + * Don't bind network interface on Samsung GT-B3730, it is handled by + * a separate module. + */ + if (dev_desc->idVendor == SAMSUNG_VENDOR_ID && + dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 && + iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); -- GitLab From e463c6dda8f5ee0baa6a5400e45d300287339536 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 May 2012 12:25:01 +0200 Subject: [PATCH 0653/5711] USB: option: handle send_setup blacklisting at probe Determine whether to use send_setup at probe time rather than at every call to send_setup. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 40 +++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ccf7f3c9a7c6..9520c4c54743 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1276,6 +1276,10 @@ static struct usb_serial_driver * const serial_drivers[] = { static bool debug; +struct option_private { + u8 bInterfaceNumber; +}; + module_usb_serial_driver(serial_drivers, option_ids); static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, @@ -1306,6 +1310,7 @@ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { struct usb_wwan_intf_private *data; + struct option_private *priv; struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1346,9 +1351,22 @@ static int option_probe(struct usb_serial *serial, data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; - data->send_setup = option_send_setup; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + kfree(data); + return -ENOMEM; + } + + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; + data->private = priv; + + if (!is_blacklisted(iface_desc->bInterfaceNumber, + OPTION_BLACKLIST_SENDSETUP, + (struct option_blacklist_info *)id->driver_info)) { + data->send_setup = option_send_setup; + } spin_lock_init(&data->susp_lock); - data->private = (void *)id->driver_info; usb_set_serial_data(serial, data); @@ -1357,11 +1375,13 @@ static int option_probe(struct usb_serial *serial, static void option_release(struct usb_serial *serial) { - struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); + struct option_private *priv = intfdata->private; usb_wwan_release(serial); kfree(priv); + kfree(intfdata); } static void option_instat_callback(struct urb *urb) @@ -1429,16 +1449,10 @@ static int option_send_setup(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); + struct option_private *priv = intfdata->private; struct usb_wwan_port_private *portdata; - int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; - if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, - (struct option_blacklist_info *) intfdata->private)) { - dbg("No send_setup on blacklisted interface #%d\n", ifNum); - return -EIO; - } - portdata = usb_get_serial_port_data(port); if (portdata->dtr_state) @@ -1446,9 +1460,9 @@ static int option_send_setup(struct usb_serial_port *port) if (portdata->rts_state) val |= 0x02; - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); + return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 0x22, 0x21, val, priv->bInterfaceNumber, NULL, + 0, USB_CTRL_SET_TIMEOUT); } MODULE_AUTHOR(DRIVER_AUTHOR); -- GitLab From fc8ef481df1bd6dac5d9c44b744f8050fcb6a5fe Mon Sep 17 00:00:00 2001 From: Jeffrin Jose Date: Wed, 30 May 2012 18:05:47 +0530 Subject: [PATCH 0654/5711] USB: storage: fixed space issues in coding style. Fixed space issues in coding style found by checkpatch.pl tool in drivers/usb/storage/protocol.c Signed-off-by: Jeffrin Jose Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/protocol.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 82dd834709c7..5dfb4c36a1b0 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -66,7 +66,7 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) * NOTE: This only works because a scsi_cmnd struct field contains * a unsigned char cmnd[16], so we know we have storage available */ - for (; srb->cmd_len<12; srb->cmd_len++) + for (; srb->cmd_len < 12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; /* send the command to the transport layer */ @@ -76,14 +76,14 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) { /* fix some commands -- this is a form of mode translation - * UFI devices only accept 12 byte long commands + * UFI devices only accept 12 byte long commands * * NOTE: This only works because a scsi_cmnd struct field contains * a unsigned char cmnd[16], so we know we have storage available */ /* Pad the ATAPI command with zeros */ - for (; srb->cmd_len<12; srb->cmd_len++) + for (; srb->cmd_len < 12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; /* set command length to 12 bytes (this affects the transport layer) */ -- GitLab From 7e97243c2080ecae7129e83635227fdebd4feef6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 25 Apr 2012 17:22:37 -0700 Subject: [PATCH 0655/5711] USB: rename the usb misc class from "usb" to "usbmisc" This class was not named properly years ago, and it turns out that tools like udev can't properly see the devices in this class after booting due to the fact that there is a bus with the same name in the system. Changing this to "usbmisc" fixes this problem, and it solves the problem for the future when we want to unify classes and busses. Reported-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index e673b26e598f..e5387a47ef6f 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -92,7 +92,7 @@ static int init_usb_class(void) } kref_init(&usb_class->kref); - usb_class->class = class_create(THIS_MODULE, "usb"); + usb_class->class = class_create(THIS_MODULE, "usbmisc"); if (IS_ERR(usb_class->class)) { result = IS_ERR(usb_class->class); printk(KERN_ERR "class_create failed for usb devices\n"); -- GitLab From 638f293307b5787b69bf0a0bc915aed491efbec9 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Tue, 22 May 2012 21:58:40 -0600 Subject: [PATCH 0656/5711] PCI: acpiphp: fix function 0 leak when disabling a slot Previously, we acquired two references to function 0, but only released one. [bhelgaas: split this out from "remove all functions" fix] Signed-off-by: Amos Kong Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp_glue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 62d0ae4dfcad..c8f999102765 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -893,6 +893,7 @@ static int disable_device(struct acpiphp_slot *slot) pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); if (!pdev) goto err_exit; + pci_dev_put(pdev); list_for_each_entry(func, &slot->funcs, sibling) { if (func->bridge) { -- GitLab From ce29ca3ea40744f24c2b5d88431e8ac566d257cc Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Wed, 23 May 2012 10:20:35 -0600 Subject: [PATCH 0657/5711] PCI: acpiphp: remove all functions in slot, even without ACPI _EJx When we add a device with acpiphp, we enumerate all functions in the slot with pci_scan_slot(), regardless of whether they have associated ACPI methods such as _EJ0. When removing the device, we previously removed only the functions with those ACPI methods. This patch makes the remove symmetric with the add: we remove all functions in the slot, whether they have associated ACPI methods or not. With qemu-kvm and SeaBIOS, we can build a multi-function device where only function 0 has _EJ0 and _ADR (see bugzilla below). Removing and re-adding that slot (including all functions of the device) works correctly with Windows guests. This patch makes it also work in Linux guests. [bhelgaas: restructure loop iteration, pull out of slot->funcs loop] Reference: https://bugzilla.kernel.org/show_bug.cgi?id=43219 Signed-off-by: Amos Kong Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp_glue.c | 42 +++++++++++++++++++++++------- drivers/pci/search.c | 2 ++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c8f999102765..73af3374e915 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -878,6 +878,24 @@ static void disable_bridges(struct pci_bus *bus) } } +/* return first device in slot, acquiring a reference on it */ +static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) +{ + struct pci_bus *bus = slot->bridge->pci_bus; + struct pci_dev *dev; + struct pci_dev *ret = NULL; + + down_read(&pci_bus_sem); + list_for_each_entry(dev, &bus->devices, bus_list) + if (PCI_SLOT(dev->devfn) == slot->device) { + ret = pci_dev_get(dev); + break; + } + up_read(&pci_bus_sem); + + return ret; +} + /** * disable_device - disable a slot * @slot: ACPI PHP slot @@ -902,18 +920,22 @@ static int disable_device(struct acpiphp_slot *slot) (u32)1, NULL, NULL); func->bridge = NULL; } + } - pdev = pci_get_slot(slot->bridge->pci_bus, - PCI_DEVFN(slot->device, func->function)); - if (pdev) { - pci_stop_bus_device(pdev); - if (pdev->subordinate) { - disable_bridges(pdev->subordinate); - pci_disable_device(pdev); - } - __pci_remove_bus_device(pdev); - pci_dev_put(pdev); + /* + * enable_device() enumerates all functions in this device via + * pci_scan_slot(), whether they have associated ACPI hotplug + * methods (_EJ0, etc.) or not. Therefore, we remove all functions + * here. + */ + while ((pdev = dev_in_slot(slot))) { + pci_stop_bus_device(pdev); + if (pdev->subordinate) { + disable_bridges(pdev->subordinate); + pci_disable_device(pdev); } + __pci_remove_bus_device(pdev); + pci_dev_put(pdev); } list_for_each_entry(func, &slot->funcs, sibling) { diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 9d75dc8ca602..993d4a0a2469 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -15,6 +15,8 @@ #include "pci.h" DECLARE_RWSEM(pci_bus_sem); +EXPORT_SYMBOL_GPL(pci_bus_sem); + /* * find the upstream PCIe-to-PCI bridge of a PCI device * if the device is PCIE, return NULL -- GitLab From 81df2d594340dcb6d1a02191976be88a1ca8120c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 18 May 2012 21:27:43 +0200 Subject: [PATCH 0658/5711] USB: allow match on bInterfaceNumber MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some composite USB devices provide multiple interfaces with different functions, all using "vendor-specific" for class/subclass/protocol. Another OS use interface numbers to match the driver and interface. It seems these devices are designed with that in mind - using static interface numbers for the different functions. This adds support for matching against the bInterfaceNumber, allowing such devices to be supported without having to resort to testing against interface number whitelists and/or blacklists in the probe. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 9 +++++++-- drivers/usb/core/message.c | 5 +++-- drivers/usb/core/sysfs.c | 5 +++-- include/linux/mod_devicetable.h | 7 +++++++ include/linux/usb.h | 16 ++++++++++++++++ scripts/mod/file2alias.c | 5 ++++- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f536aebc958e..23d7bbd199a5 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -622,14 +622,15 @@ int usb_match_one_id(struct usb_interface *interface, if (!usb_match_device(dev, id)) return 0; - /* The interface class, subclass, and protocol should never be + /* The interface class, subclass, protocol and number should never be * checked for a match if the device class is Vendor Specific, * unless the match record specifies the Vendor ID. */ if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | - USB_DEVICE_ID_MATCH_INT_PROTOCOL))) + USB_DEVICE_ID_MATCH_INT_PROTOCOL | + USB_DEVICE_ID_MATCH_INT_NUMBER))) return 0; if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && @@ -644,6 +645,10 @@ int usb_match_one_id(struct usb_interface *interface, (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) return 0; + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) && + (id->bInterfaceNumber != intf->desc.bInterfaceNumber)) + return 0; + return 1; } EXPORT_SYMBOL_GPL(usb_match_one_id); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b548cf1dbc62..ca7fc392fd9e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1559,7 +1559,7 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "MODALIAS=usb:" - "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", + "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02Xin%02X", le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.bcdDevice), @@ -1568,7 +1568,8 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) usb_dev->descriptor.bDeviceProtocol, alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) + alt->desc.bInterfaceProtocol, + alt->desc.bInterfaceNumber)) return -ENOMEM; return 0; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 9a56e3adf476..777f03c37725 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -840,7 +840,7 @@ static ssize_t show_modalias(struct device *dev, alt = intf->cur_altsetting; return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" - "ic%02Xisc%02Xip%02X\n", + "ic%02Xisc%02Xip%02Xin%02X\n", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct), le16_to_cpu(udev->descriptor.bcdDevice), @@ -849,7 +849,8 @@ static ssize_t show_modalias(struct device *dev, udev->descriptor.bDeviceProtocol, alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol); + alt->desc.bInterfaceProtocol, + alt->desc.bInterfaceNumber); } static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 5db93821f9c7..7771d453e5f3 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -78,6 +78,9 @@ struct ieee1394_device_id { * of a given interface; other interfaces may support other classes. * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass. * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass. + * @bInterfaceNumber: Number of interface; composite devices may use + * fixed interface numbers to differentiate between vendor-specific + * interfaces. * @driver_info: Holds information used by the driver. Usually it holds * a pointer to a descriptor understood by the driver, or perhaps * device flags. @@ -115,6 +118,9 @@ struct usb_device_id { __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; + /* Used for vendor-specific interface matches */ + __u8 bInterfaceNumber; + /* not matched against */ kernel_ulong_t driver_info; }; @@ -130,6 +136,7 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 #define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 +#define USB_DEVICE_ID_MATCH_INT_NUMBER 0x0400 #define HID_ANY_ID (~0) #define HID_BUS_ANY 0xffff diff --git a/include/linux/usb.h b/include/linux/usb.h index dea39dc551d4..f717fbdaee8e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -776,6 +776,22 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) .idProduct = (prod), \ .bInterfaceProtocol = (pr) +/** + * USB_DEVICE_INTERFACE_NUMBER - describe a usb device with a specific interface number + * @vend: the 16 bit USB Vendor ID + * @prod: the 16 bit USB Product ID + * @num: bInterfaceNumber value + * + * This macro is used to create a struct usb_device_id that matches a + * specific interface number of devices. + */ +#define USB_DEVICE_INTERFACE_NUMBER(vend, prod, num) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_NUMBER, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .bInterfaceNumber = (num) + /** * USB_DEVICE_INFO - macro used to describe a class of usb devices * @cl: bDeviceClass value diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5759751a1f61..7ed6864ef65b 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -156,7 +156,7 @@ static void device_id_check(const char *modname, const char *device_id, } /* USB is special because the bcdDevice can be matched against a numeric range */ -/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ +/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ static void do_usb_entry(struct usb_device_id *id, unsigned int bcdDevice_initial, int bcdDevice_initial_digits, unsigned char range_lo, unsigned char range_hi, @@ -210,6 +210,9 @@ static void do_usb_entry(struct usb_device_id *id, ADD(alias, "ip", id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, id->bInterfaceProtocol); + ADD(alias, "in", + id->match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, + id->bInterfaceNumber); add_wildcard(alias); buf_printf(&mod->dev_table_buf, -- GitLab From 4d4847b8502ec093864936a4669318675c0ced22 Mon Sep 17 00:00:00 2001 From: Jeffrin Jose Date: Sun, 20 May 2012 00:56:58 +0530 Subject: [PATCH 0659/5711] usb: early: fixed coding style issue related to : operator Fixed a space issue relating to ":" operator found by checkpatch.pl tool in drivers/usb/early/ehci-dbgp.c Signed-off-by: Jeffrin Jose Signed-off-by: Greg Kroah-Hartman --- drivers/usb/early/ehci-dbgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 1fc8f1249806..ee0ebacf8227 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -334,7 +334,7 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, int ret; read = (requesttype & USB_DIR_IN) != 0; - if (size > (read ? DBGP_MAX_PACKET:0)) + if (size > (read ? DBGP_MAX_PACKET : 0)) return -1; /* Compute the control message */ -- GitLab From e714fad054e219b52eee17591d95d725888a95c4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 May 2012 11:36:59 +0200 Subject: [PATCH 0660/5711] usb-core: Set intfdata to NULL if a driver's probe method failed Ensure that intfdata always is NULL if no driver is bound: 1) drvdata is for a driver to store a pointer to driver specific data 2) If no driver is bound, there is no driver specific data associated with the device 3) Thus logically drvdata should be NULL if no driver is bound. We already set intfdata to NULL when a driver is unbound, to ensure that intfdata will be NULL even if the drivers disconnect method does not properly clear it. This ensures that intfdata will also be NULL after a failed probe, even if the driver's probe method left a (likely dangling) pointer in there. Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 23d7bbd199a5..69781016a266 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -367,6 +367,7 @@ static int usb_probe_interface(struct device *dev) return error; err: + usb_set_intfdata(intf, NULL); intf->needs_remote_wakeup = 0; intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); -- GitLab From 7e54e97812ccf59e71e002f9bd6d12bf4ab448b8 Mon Sep 17 00:00:00 2001 From: "Du, ChangbinX" Date: Wed, 23 May 2012 02:43:05 +0000 Subject: [PATCH 0661/5711] testusb: expose looping forever option "l" to user The testusb.c tool has support for looping forever implemented, which may be useful for stress test, yet it is not exposed to the user, so even though the code is there, it cannot be used. This commit adds "l" to the set of options handled by the application which enables the feature. Also, I collate help information for each command line option to make it easier to use for novice. Signed-off-by: Du Changbin Acked-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- tools/usb/testusb.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c index 82d7c590c026..b0adb2710c02 100644 --- a/tools/usb/testusb.c +++ b/tools/usb/testusb.c @@ -425,7 +425,7 @@ int main (int argc, char **argv) /* for easy use when hotplugging */ device = getenv ("DEVICE"); - while ((c = getopt (argc, argv, "D:aA:c:g:hns:t:v:")) != EOF) + while ((c = getopt (argc, argv, "D:aA:c:g:hlns:t:v:")) != EOF) switch (c) { case 'D': /* device, if only one */ device = optarg; @@ -468,10 +468,21 @@ int main (int argc, char **argv) case 'h': default: usage: - fprintf (stderr, "usage: %s [-n] [-D dev | -a | -A usbfs-dir]\n" - "\t[-c iterations] [-t testnum]\n" - "\t[-s packetsize] [-g sglen] [-v vary]\n", - argv [0]); + fprintf (stderr, + "usage: %s [options]\n" + "Options:\n" + "\t-D dev only test specific device\n" + "\t-A usbfs-dir\n" + "\t-a test all recognized devices\n" + "\t-l loop forever(for stress test)\n" + "\t-t testnum only run specified case\n" + "\t-n no test running, show devices to be tested\n" + "Case arguments:\n" + "\t-c iterations default 1000\n" + "\t-s packetsize default 512\n" + "\t-g sglen default 32\n" + "\t-v vary default 512\n", + argv[0]); return 1; } if (optind != argc) -- GitLab From 71f882fe71823c54ae095ce29ce050f814eefdbc Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sun, 20 May 2012 00:23:26 +0530 Subject: [PATCH 0662/5711] staging: android: alarm: remove unnecessary goto statement Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index c2d87c546e99..5b7064005188 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -237,7 +237,6 @@ from_old_alarm_set: default: rv = -EINVAL; - goto err1; } err1: return rv; -- GitLab From dd0aa67cd7cf3f4a3ca52ecc1d6b82f3fad1352b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Jun 2012 16:33:54 -0700 Subject: [PATCH 0663/5711] Revert "w1: introduce a slave mutex for serializing IO" This reverts commit 59d4467be405316916a4087d5b02d99196eeef04. Turns out it was the wrong version, will apply the correct version after this. Reported-by: NeilBrown Cc: Evgeniy Polyakov Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/slaves/w1_bq27000.c | 4 ++-- drivers/w1/w1.c | 1 - drivers/w1/w1.h | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 87554788fa32..52ad812fa1e7 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c @@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg) u8 val; struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); - mutex_lock(&sl->mutex); + mutex_lock(&sl->master->mutex); w1_write_8(sl->master, HDQ_CMD_READ | reg); val = w1_read_8(sl->master); - mutex_unlock(&sl->mutex); + mutex_unlock(&sl->master->mutex); return val; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 79e488db5104..bfb898641029 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -686,7 +686,6 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); atomic_set(&sl->refcnt, 0); init_completion(&sl->released); - mutex_init(&sl->mutex); spin_lock(&w1_flock); f = w1_family_registered(rn->family); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 8c8be380a98a..4d012ca3f32c 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -75,7 +75,6 @@ struct w1_slave void *family_data; struct device dev; struct completion released; - struct mutex mutex; }; typedef void (*w1_slave_found_callback)(struct w1_master *, u64); -- GitLab From 7b5362a603a1ecc9a25b97dafd702b8098090f41 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 22 May 2012 09:43:02 +1000 Subject: [PATCH 0664/5711] w1: omap_hdq: Fix some error/debug handling. - some debug messages missed spaces - sometimes no error was returned when it should have been - sometimes a message is printed when there is no error, rather than when there is one. Acked-by: Evgeniy Polyakov Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/omap_hdq.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 5ef385bfed18..3036b6113ffd 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -180,6 +180,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); if (ret == 0) { dev_dbg(hdq_data->dev, "TX wait elapsed\n"); + ret = -ETIMEDOUT; goto out; } @@ -187,7 +188,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) /* check irqstatus */ if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { dev_dbg(hdq_data->dev, "timeout waiting for" - "TXCOMPLETE/RXCOMPLETE, %x", *status); + " TXCOMPLETE/RXCOMPLETE, %x", *status); ret = -ETIMEDOUT; goto out; } @@ -198,7 +199,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) OMAP_HDQ_FLAG_CLEAR, &tmp_status); if (ret) { dev_dbg(hdq_data->dev, "timeout waiting GO bit" - "return to zero, %x", tmp_status); + " return to zero, %x", tmp_status); } out: @@ -341,7 +342,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data) &tmp_status); if (ret) dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" - "return to zero, %x", tmp_status); + " return to zero, %x", tmp_status); out: mutex_unlock(&hdq_data->hdq_mutex); @@ -386,7 +387,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) /* check irqstatus */ if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { dev_dbg(hdq_data->dev, "timeout waiting for" - "RXCOMPLETE, %x", status); + " RXCOMPLETE, %x", status); ret = -ETIMEDOUT; goto out; } @@ -396,7 +397,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) out: mutex_unlock(&hdq_data->hdq_mutex); rtn: - return 0; + return ret; } @@ -470,7 +471,7 @@ static int omap_hdq_put(struct hdq_data *hdq_data) if (0 == hdq_data->hdq_usecount) { dev_dbg(hdq_data->dev, "attempt to decrement use count" - "when it is zero"); + " when it is zero"); ret = -EINVAL; } else { hdq_data->hdq_usecount--; @@ -540,7 +541,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) mutex_unlock(&hdq_data->hdq_mutex); ret = hdq_write_byte(hdq_data, byte, &status); - if (ret == 0) { + if (ret < 0) { dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); return; } -- GitLab From b7e938d06d0de43bdbee8844a8736c81480c1031 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 22 May 2012 09:43:02 +1000 Subject: [PATCH 0665/5711] w1: omap_hdq: use wait_event_timeout to wait for read to complete. There is no gain in having a loop - there is no risk of missing the interrupt with wait_event_timeout. Signed-off-by: NeilBrown Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/omap_hdq.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 3036b6113ffd..848399bfb9b4 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -354,7 +354,6 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) { int ret = 0; u8 status; - unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); if (ret < 0) { @@ -372,15 +371,13 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); /* - * The RX comes immediately after TX. It - * triggers another interrupt before we - * sleep. So we have to wait for RXCOMPLETE bit. + * The RX comes immediately after TX. */ - while (!(hdq_data->hdq_irqstatus - & OMAP_HDQ_INT_STATUS_RXCOMPLETE) - && time_before(jiffies, timeout)) { - schedule_timeout_uninterruptible(1); - } + wait_event_timeout(hdq_wait_queue, + (hdq_data->hdq_irqstatus + & OMAP_HDQ_INT_STATUS_RXCOMPLETE), + OMAP_HDQ_TIMEOUT); + hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, OMAP_HDQ_CTRL_STATUS_DIR); status = hdq_data->hdq_irqstatus; -- GitLab From b02f8bede217a4b145ecc16d3940c78d83941147 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 18 May 2012 15:59:52 +1000 Subject: [PATCH 0666/5711] W1: split master mutex to avoid deadlocks. The 'mutex' in struct w1_master is use for two very different purposes. Firstly it protects various data structures such as the list of all slaves. Secondly it protects the w1 buss against concurrent accesses. This can lead to deadlocks when the ->probe code called while adding a slave needs to talk on the bus, as is the case for power_supply devices. ds2780 and ds2781 drivers contain a work around to track which process hold the lock simply to avoid this deadlock. bq27000 doesn't have that work around and so deadlocks. There are other possible deadlocks involving sysfs. When removing a device the sysfs s_active lock is held, so the lock that protects the slave list must take precedence over s_active. However when access power_supply attributes via sysfs, the s_active lock must take precedence over the lock that protects accesses to the bus. So to avoid deadlocks between w1 slaves and sysfs, these must be two separate locks. Making them separate means that the work around in ds2780 and ds2781 can be removed. So this patch: - adds a new mutex: "bus_mutex" which serialises access to the bus. - takes in mutex in w1_search and ds1wm_search while they access the bus for searching. The mutex is dropped before calling the callback which adds the slave. - changes all slaves to use bus_mutex instead of mutex to protect access to the bus - removes w1_ds2790_io_nolock and w1_ds2781_io_nolock, and the related code from drivers/power/ds278[01]_battery.c which calls them. Signed-off-by: NeilBrown Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/power/ds2780_battery.c | 11 +---------- drivers/power/ds2781_battery.c | 12 +----------- drivers/w1/masters/ds1wm.c | 4 ++++ drivers/w1/slaves/w1_bq27000.c | 4 ++-- drivers/w1/slaves/w1_ds2408.c | 24 ++++++++++++------------ drivers/w1/slaves/w1_ds2423.c | 4 ++-- drivers/w1/slaves/w1_ds2431.c | 8 ++++---- drivers/w1/slaves/w1_ds2433.c | 8 ++++---- drivers/w1/slaves/w1_ds2760.c | 8 ++++---- drivers/w1/slaves/w1_ds2780.c | 22 ++++------------------ drivers/w1/slaves/w1_ds2780.h | 2 -- drivers/w1/slaves/w1_ds2781.c | 22 ++++------------------ drivers/w1/slaves/w1_ds2781.h | 2 -- drivers/w1/slaves/w1_therm.c | 10 +++++----- drivers/w1/w1.c | 9 ++++++++- drivers/w1/w1.h | 1 + drivers/w1/w1_int.c | 1 + 17 files changed, 57 insertions(+), 95 deletions(-) diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c index de31cae1ba53..74fad941c56c 100644 --- a/drivers/power/ds2780_battery.c +++ b/drivers/power/ds2780_battery.c @@ -39,7 +39,6 @@ struct ds2780_device_info { struct device *dev; struct power_supply bat; struct device *w1_dev; - struct task_struct *mutex_holder; }; enum current_types { @@ -64,10 +63,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, char *buf, int addr, size_t count, int io) { - if (dev_info->mutex_holder == current) - return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io); - else - return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); + return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); } static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, @@ -779,7 +775,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) dev_info->bat.properties = ds2780_battery_props; dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); dev_info->bat.get_property = ds2780_battery_get_property; - dev_info->mutex_holder = current; ret = power_supply_register(&pdev->dev, &dev_info->bat); if (ret) { @@ -809,8 +804,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) goto fail_remove_bin_file; } - dev_info->mutex_holder = NULL; - return 0; fail_remove_bin_file: @@ -830,8 +823,6 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev) { struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); - dev_info->mutex_holder = current; - /* remove attributes */ sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c index 975684a40f15..5f92a4bb33f9 100644 --- a/drivers/power/ds2781_battery.c +++ b/drivers/power/ds2781_battery.c @@ -37,7 +37,6 @@ struct ds2781_device_info { struct device *dev; struct power_supply bat; struct device *w1_dev; - struct task_struct *mutex_holder; }; enum current_types { @@ -62,11 +61,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, char *buf, int addr, size_t count, int io) { - if (dev_info->mutex_holder == current) - return w1_ds2781_io_nolock(dev_info->w1_dev, buf, addr, - count, io); - else - return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); + return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); } int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, @@ -775,7 +770,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) dev_info->bat.properties = ds2781_battery_props; dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); dev_info->bat.get_property = ds2781_battery_get_property; - dev_info->mutex_holder = current; ret = power_supply_register(&pdev->dev, &dev_info->bat); if (ret) { @@ -805,8 +799,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) goto fail_remove_bin_file; } - dev_info->mutex_holder = NULL; - return 0; fail_remove_bin_file: @@ -826,8 +818,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev) { struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); - dev_info->mutex_holder = current; - /* remove attributes */ sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index a0c8965c1a79..530a2d309063 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -334,7 +334,9 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, return; } + mutex_lock(&master_dev->bus_mutex); if (ds1wm_reset(ds1wm_data)) { + mutex_unlock(&master_dev->bus_mutex); dev_dbg(&ds1wm_data->pdev->dev, "pass: %d reset error (or no slaves)\n", pass); break; @@ -387,6 +389,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, } if (ds1wm_data->read_error) { + mutex_unlock(&master_dev->bus_mutex); dev_err(&ds1wm_data->pdev->dev, "pass: %d read error, retrying\n", pass); break; @@ -400,6 +403,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, dev_dbg(&ds1wm_data->pdev->dev, "pass: %d resetting bus\n", pass); ds1wm_reset(ds1wm_data); + mutex_unlock(&master_dev->bus_mutex); if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { dev_err(&ds1wm_data->pdev->dev, "pass: %d bus error, retrying\n", pass); diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 52ad812fa1e7..773dca5beafe 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c @@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg) u8 val; struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); w1_write_8(sl->master, HDQ_CMD_READ | reg); val = w1_read_8(sl->master); - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return val; } diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index 8e813eed0f0a..441ad3a3b586 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c @@ -52,11 +52,11 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) if (!buf) return -EINVAL; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex locked"); if (w1_reset_select_slave(sl)) { - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return -EIO; } @@ -66,7 +66,7 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) w1_write_block(sl->master, wrbuf, 3); *buf = w1_read_8(sl->master); - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked"); return 1; } @@ -165,7 +165,7 @@ static ssize_t w1_f29_write_output( return -EFAULT; dev_dbg(&sl->dev, "locking mutex for write_output"); - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex locked"); if (w1_reset_select_slave(sl)) @@ -200,14 +200,14 @@ static ssize_t w1_f29_write_output( /* read the result of the READ_PIO_REGS command */ if (w1_read_8(sl->master) == *buf) { /* success! */ - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries); return 1; } } error: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); return -EIO; @@ -228,7 +228,7 @@ static ssize_t w1_f29_write_activity( if (count != 1 || off != 0) return -EFAULT; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl)) goto error; @@ -236,7 +236,7 @@ static ssize_t w1_f29_write_activity( while (retries--) { w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return 1; } if (w1_reset_resume_command(sl->master)) @@ -244,7 +244,7 @@ static ssize_t w1_f29_write_activity( } error: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return -EIO; } @@ -263,7 +263,7 @@ static ssize_t w1_f29_write_status_control( if (count != 1 || off != 0) return -EFAULT; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl)) goto error; @@ -285,12 +285,12 @@ static ssize_t w1_f29_write_status_control( w1_write_block(sl->master, w1_buf, 3); if (w1_read_8(sl->master) == *buf) { /* success! */ - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return 1; } } error: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return -EIO; } diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c index 7a7dbe5026f1..40a10b5ed120 100644 --- a/drivers/w1/slaves/w1_ds2423.c +++ b/drivers/w1/slaves/w1_ds2423.c @@ -66,7 +66,7 @@ static ssize_t w1_counter_read(struct device *device, wrbuf[0] = 0xA5; wrbuf[1] = rom_addr & 0xFF; wrbuf[2] = rom_addr >> 8; - mutex_lock(&dev->mutex); + mutex_lock(&dev->bus_mutex); if (!w1_reset_select_slave(sl)) { w1_write_block(dev, wrbuf, 3); read_byte_count = 0; @@ -124,7 +124,7 @@ static ssize_t w1_counter_read(struct device *device, } else { c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error"); } - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->bus_mutex); return PAGE_SIZE - c; } diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 84e2410aec1d..984b30331a45 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c @@ -107,7 +107,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, if (count == 0) return 0; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */ while (todo > 0) { @@ -126,7 +126,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, off += W1_F2D_READ_MAXLEN; } - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return count; } @@ -214,7 +214,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, if (count == 0) return 0; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); /* Can only write data in blocks of the size of the scratchpad */ addr = off; @@ -259,7 +259,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, } out_up: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return count; } diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 0f7b8f9c509a..85f2cdb27fa2 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -107,7 +107,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) return 0; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); #ifdef CONFIG_W1_SLAVE_DS2433_CRC @@ -138,7 +138,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ out_up: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return count; } @@ -233,7 +233,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, } #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); /* Can only write data to one page at a time */ idx = 0; @@ -251,7 +251,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, } out_up: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return count; } diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index 5754c9a4f58b..aa7bd5fa2fa8 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c @@ -31,7 +31,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, if (!dev) return 0; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (addr > DS2760_DATA_SIZE || addr < 0) { count = 0; @@ -54,7 +54,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, } out: - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return count; } @@ -76,14 +76,14 @@ static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) if (!dev) return -EINVAL; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl) == 0) { w1_write_8(sl->master, cmd); w1_write_8(sl->master, addr); } - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return 0; } diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c index 39f78c0b143c..7b09307de0ef 100644 --- a/drivers/w1/slaves/w1_ds2780.c +++ b/drivers/w1/slaves/w1_ds2780.c @@ -60,30 +60,16 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, if (!dev) return -ENODEV; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); ret = w1_ds2780_do_io(dev, buf, addr, count, io); - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return ret; } EXPORT_SYMBOL(w1_ds2780_io); -int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count, - int io) -{ - int ret; - - if (!dev) - return -ENODEV; - - ret = w1_ds2780_do_io(dev, buf, addr, count, io); - - return ret; -} -EXPORT_SYMBOL(w1_ds2780_io_nolock); - int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) { struct w1_slave *sl = container_of(dev, struct w1_slave, dev); @@ -91,14 +77,14 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) if (!dev) return -EINVAL; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl) == 0) { w1_write_8(sl->master, cmd); w1_write_8(sl->master, addr); } - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return 0; } EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); diff --git a/drivers/w1/slaves/w1_ds2780.h b/drivers/w1/slaves/w1_ds2780.h index 737379365021..a1fba79eb1b5 100644 --- a/drivers/w1/slaves/w1_ds2780.h +++ b/drivers/w1/slaves/w1_ds2780.h @@ -124,8 +124,6 @@ extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, int io); -extern int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, - size_t count, int io); extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); #endif /* !_W1_DS2780_H */ diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c index 0d0c7985293f..877daf74159c 100644 --- a/drivers/w1/slaves/w1_ds2781.c +++ b/drivers/w1/slaves/w1_ds2781.c @@ -58,30 +58,16 @@ int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, if (!dev) return -ENODEV; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); ret = w1_ds2781_do_io(dev, buf, addr, count, io); - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return ret; } EXPORT_SYMBOL(w1_ds2781_io); -int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, size_t count, - int io) -{ - int ret; - - if (!dev) - return -ENODEV; - - ret = w1_ds2781_do_io(dev, buf, addr, count, io); - - return ret; -} -EXPORT_SYMBOL(w1_ds2781_io_nolock); - int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) { struct w1_slave *sl = container_of(dev, struct w1_slave, dev); @@ -89,14 +75,14 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) if (!dev) return -EINVAL; - mutex_lock(&sl->master->mutex); + mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl) == 0) { w1_write_8(sl->master, cmd); w1_write_8(sl->master, addr); } - mutex_unlock(&sl->master->mutex); + mutex_unlock(&sl->master->bus_mutex); return 0; } EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); diff --git a/drivers/w1/slaves/w1_ds2781.h b/drivers/w1/slaves/w1_ds2781.h index 82bc66497b43..557dfb0b4f64 100644 --- a/drivers/w1/slaves/w1_ds2781.h +++ b/drivers/w1/slaves/w1_ds2781.h @@ -129,8 +129,6 @@ extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, int io); -extern int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, - size_t count, int io); extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd); #endif /* !_W1_DS2781_H */ diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index ff29ae747ee8..d90062b211f8 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -179,7 +179,7 @@ static ssize_t w1_therm_read(struct device *device, int i, max_trying = 10; ssize_t c = PAGE_SIZE; - i = mutex_lock_interruptible(&dev->mutex); + i = mutex_lock_interruptible(&dev->bus_mutex); if (i != 0) return i; @@ -207,19 +207,19 @@ static ssize_t w1_therm_read(struct device *device, w1_write_8(dev, W1_CONVERT_TEMP); if (external_power) { - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->bus_mutex); sleep_rem = msleep_interruptible(tm); if (sleep_rem != 0) return -EINTR; - i = mutex_lock_interruptible(&dev->mutex); + i = mutex_lock_interruptible(&dev->bus_mutex); if (i != 0) return i; } else if (!w1_strong_pullup) { sleep_rem = msleep_interruptible(tm); if (sleep_rem != 0) { - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->bus_mutex); return -EINTR; } } @@ -258,7 +258,7 @@ static ssize_t w1_therm_read(struct device *device, c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", w1_convert_temp(rom, sl->family->fid)); - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->bus_mutex); return PAGE_SIZE - c; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index bfb898641029..1a574370d2cd 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -885,16 +885,21 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb * * Return 0 - device(s) present, 1 - no devices present. */ + mutex_lock(&dev->bus_mutex); if (w1_reset_bus(dev)) { + mutex_unlock(&dev->bus_mutex); dev_dbg(&dev->dev, "No devices present on the wire.\n"); break; } /* Do fast search on single slave bus */ if (dev->max_slave_count == 1) { + int rv; w1_write_8(dev, W1_READ_ROM); + rv = w1_read_block(dev, (u8 *)&rn, 8); + mutex_unlock(&dev->bus_mutex); - if (w1_read_block(dev, (u8 *)&rn, 8) == 8 && rn) + if (rv == 8 && rn) cb(dev, rn); break; @@ -927,10 +932,12 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb rn |= (tmp64 << i); if (kthread_should_stop()) { + mutex_unlock(&dev->bus_mutex); dev_dbg(&dev->dev, "Abort w1_search\n"); return; } } + mutex_unlock(&dev->bus_mutex); if ( (triplet_ret & 0x03) != 0x03 ) { if ( (desc_bit == last_zero) || (last_zero < 0)) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 4d012ca3f32c..45908e56c2f8 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -180,6 +180,7 @@ struct w1_master struct task_struct *thread; struct mutex mutex; + struct mutex bus_mutex; struct device_driver *driver; struct device dev; diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 68288355727a..531434180afd 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, INIT_LIST_HEAD(&dev->slist); mutex_init(&dev->mutex); + mutex_init(&dev->bus_mutex); memcpy(&dev->dev, device, sizeof(struct device)); dev_set_name(&dev->dev, "w1_bus_master%u", dev->id); -- GitLab From 0998d0631001288a5974afc0b2a5f568bcdecb4d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 23 May 2012 00:09:34 +0200 Subject: [PATCH 0667/5711] device-core: Ensure drvdata = NULL when no driver is bound 1) drvdata is for a driver to store a pointer to driver specific data 2) If no driver is bound, there is no driver specific data associated with the device 3) Thus logically drvdata should be NULL if no driver is bound. But many drivers don't clear drvdata on device_release, or set drvdata early on in probe and leave it set on probe error. Both of which results in a dangling pointer in drvdata. This patch enforce for drvdata to be NULL after device_release or on probe failure. Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1b1cbb571d38..9a1e9704d782 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -283,6 +283,7 @@ probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; + dev_set_drvdata(dev, NULL); if (ret == -EPROBE_DEFER) { /* Driver requested deferred probing */ @@ -487,6 +488,7 @@ static void __device_release_driver(struct device *dev) drv->remove(dev); devres_release_all(dev); dev->driver = NULL; + dev_set_drvdata(dev, NULL); klist_remove(&dev->p->knode_driver); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, -- GitLab From a59d6293e5372d7c35212932e083e2a541151eff Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 23 May 2012 15:13:07 +0200 Subject: [PATCH 0668/5711] debugfs: change parameter check in debugfs_remove() functions The dentry parameter in debugfs_remove() and debugfs_remove_recursive() is checked being a NULL pointer. To make cleanup by callers easier this check is extended using the IS_ERR_OR_NULL macro instead because the debugfs_create_... functions can return a ERR_PTR() value. Signed-off-by: Arend van Spriel Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b80bc846a15a..0de5e26870c3 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -498,7 +498,7 @@ void debugfs_remove(struct dentry *dentry) struct dentry *parent; int ret; - if (!dentry) + if (IS_ERR_OR_NULL(dentry)) return; parent = dentry->d_parent; @@ -530,7 +530,7 @@ void debugfs_remove_recursive(struct dentry *dentry) struct dentry *child; struct dentry *parent; - if (!dentry) + if (IS_ERR_OR_NULL(dentry)) return; parent = dentry->d_parent; -- GitLab From fbf7f7b4e2ae40f790828c86d31beff2d49e9ac8 Mon Sep 17 00:00:00 2001 From: Markus Franke Date: Sat, 26 May 2012 00:45:12 +0200 Subject: [PATCH 0669/5711] w1: Add 1-wire slave device driver for DS28E04-100 Signed-off-by: Markus Franke Signed-off-by: Greg Kroah-Hartman --- .../ABI/stable/sysfs-driver-w1_ds28e04 | 15 + Documentation/w1/slaves/w1_ds28e04 | 36 ++ drivers/w1/slaves/Kconfig | 13 + drivers/w1/slaves/Makefile | 1 + drivers/w1/slaves/w1_ds28e04.c | 469 ++++++++++++++++++ drivers/w1/w1_family.h | 1 + 6 files changed, 535 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-driver-w1_ds28e04 create mode 100644 Documentation/w1/slaves/w1_ds28e04 create mode 100644 drivers/w1/slaves/w1_ds28e04.c diff --git a/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 new file mode 100644 index 000000000000..26579ee868c9 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 @@ -0,0 +1,15 @@ +What: /sys/bus/w1/devices/.../pio +Date: May 2012 +Contact: Markus Franke +Description: read/write the contents of the two PIO's of the DS28E04-100 + see Documentation/w1/slaves/w1_ds28e04 for detailed information +Users: any user space application which wants to communicate with DS28E04-100 + + + +What: /sys/bus/w1/devices/.../eeprom +Date: May 2012 +Contact: Markus Franke +Description: read/write the contents of the EEPROM memory of the DS28E04-100 + see Documentation/w1/slaves/w1_ds28e04 for detailed information +Users: any user space application which wants to communicate with DS28E04-100 diff --git a/Documentation/w1/slaves/w1_ds28e04 b/Documentation/w1/slaves/w1_ds28e04 new file mode 100644 index 000000000000..85bc9a7e02fe --- /dev/null +++ b/Documentation/w1/slaves/w1_ds28e04 @@ -0,0 +1,36 @@ +Kernel driver w1_ds28e04 +======================== + +Supported chips: + * Maxim DS28E04-100 4096-Bit Addressable 1-Wire EEPROM with PIO + +supported family codes: + W1_FAMILY_DS28E04 0x1C + +Author: Markus Franke, + +Description +----------- + +Support is provided through the sysfs files "eeprom" and "pio". CRC checking +during memory accesses can optionally be enabled/disabled via the device +attribute "crccheck". The strong pull-up can optionally be enabled/disabled +via the module parameter "w1_strong_pullup". + +Memory Access + + A read operation on the "eeprom" file reads the given amount of bytes + from the EEPROM of the DS28E04. + + A write operation on the "eeprom" file writes the given byte sequence + to the EEPROM of the DS28E04. If CRC checking mode is enabled only + fully alligned blocks of 32 bytes with valid CRC16 values (in bytes 30 + and 31) are allowed to be written. + +PIO Access + + The 2 PIOs of the DS28E04-100 are accessible via the "pio" sysfs file. + + The current status of the PIO's is returned as an 8 bit value. Bit 0/1 + represent the state of PIO_0/PIO_1. Bits 2..7 do not care. The PIO's are + driven low-active, i.e. the driver delivers/expects low-active values. diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index eb9e376d6244..67526690acbc 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig @@ -94,6 +94,19 @@ config W1_SLAVE_DS2781 If you are unsure, say N. +config W1_SLAVE_DS28E04 + tristate "4096-Bit Addressable 1-Wire EEPROM with PIO (DS28E04-100)" + depends on W1 + select CRC16 + help + If you enable this you will have the DS28E04-100 + chip support. + + Say Y here if you want to use a 1-wire + 4kb EEPROM with PIO family device (DS28E04). + + If you are unsure, say N. + config W1_SLAVE_BQ27000 tristate "BQ27000 slave support" depends on W1 diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index c4f1859fb520..05188f6aab5a 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o +obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c new file mode 100644 index 000000000000..98117db595bb --- /dev/null +++ b/drivers/w1/slaves/w1_ds28e04.c @@ -0,0 +1,469 @@ +/* + * w1_ds28e04.c - w1 family 1C (DS28E04) driver + * + * Copyright (c) 2012 Markus Franke + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CRC16_INIT 0 +#define CRC16_VALID 0xb001 + +#include "../w1.h" +#include "../w1_int.h" +#include "../w1_family.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Markus Franke , "); +MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); + +/* Allow the strong pullup to be disabled, but default to enabled. + * If it was disabled a parasite powered device might not get the required + * current to copy the data from the scratchpad to EEPROM. If it is enabled + * parasite powered devices have a better chance of getting the current + * required. + */ +static int w1_strong_pullup = 1; +module_param_named(strong_pullup, w1_strong_pullup, int, 0); + +/* enable/disable CRC checking on DS28E04-100 memory accesses */ +static char w1_enable_crccheck = 1; + +#define W1_EEPROM_SIZE 512 +#define W1_PAGE_COUNT 16 +#define W1_PAGE_SIZE 32 +#define W1_PAGE_BITS 5 +#define W1_PAGE_MASK 0x1F + +#define W1_F1C_READ_EEPROM 0xF0 +#define W1_F1C_WRITE_SCRATCH 0x0F +#define W1_F1C_READ_SCRATCH 0xAA +#define W1_F1C_COPY_SCRATCH 0x55 +#define W1_F1C_ACCESS_WRITE 0x5A + +#define W1_1C_REG_LOGIC_STATE 0x220 + +struct w1_f1C_data { + u8 memory[W1_EEPROM_SIZE]; + u32 validcrc; +}; + +/** + * Check the file size bounds and adjusts count as needed. + * This would not be needed if the file size didn't reset to 0 after a write. + */ +static inline size_t w1_f1C_fix_count(loff_t off, size_t count, size_t size) +{ + if (off > size) + return 0; + + if ((off + count) > size) + return size - off; + + return count; +} + +static int w1_f1C_refresh_block(struct w1_slave *sl, struct w1_f1C_data *data, + int block) +{ + u8 wrbuf[3]; + int off = block * W1_PAGE_SIZE; + + if (data->validcrc & (1 << block)) + return 0; + + if (w1_reset_select_slave(sl)) { + data->validcrc = 0; + return -EIO; + } + + wrbuf[0] = W1_F1C_READ_EEPROM; + wrbuf[1] = off & 0xff; + wrbuf[2] = off >> 8; + w1_write_block(sl->master, wrbuf, 3); + w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE); + + /* cache the block if the CRC is valid */ + if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID) + data->validcrc |= (1 << block); + + return 0; +} + +static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data) +{ + u8 wrbuf[3]; + + /* read directly from the EEPROM */ + if (w1_reset_select_slave(sl)) + return -EIO; + + wrbuf[0] = W1_F1C_READ_EEPROM; + wrbuf[1] = addr & 0xff; + wrbuf[2] = addr >> 8; + + w1_write_block(sl->master, wrbuf, sizeof(wrbuf)); + return w1_read_block(sl->master, data, len); +} + +static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + struct w1_f1C_data *data = sl->family_data; + int i, min_page, max_page; + + count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE); + if (count == 0) + return 0; + + mutex_lock(&sl->master->mutex); + + if (w1_enable_crccheck) { + min_page = (off >> W1_PAGE_BITS); + max_page = (off + count - 1) >> W1_PAGE_BITS; + for (i = min_page; i <= max_page; i++) { + if (w1_f1C_refresh_block(sl, data, i)) { + count = -EIO; + goto out_up; + } + } + memcpy(buf, &data->memory[off], count); + } else { + count = w1_f1C_read(sl, off, count, buf); + } + +out_up: + mutex_unlock(&sl->master->mutex); + + return count; +} + +/** + * Writes to the scratchpad and reads it back for verification. + * Then copies the scratchpad to EEPROM. + * The data must be on one page. + * The master must be locked. + * + * @param sl The slave structure + * @param addr Address for the write + * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK)) + * @param data The data to write + * @return 0=Success -1=failure + */ +static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data) +{ + u8 wrbuf[4]; + u8 rdbuf[W1_PAGE_SIZE + 3]; + u8 es = (addr + len - 1) & 0x1f; + unsigned int tm = 10; + int i; + struct w1_f1C_data *f1C = sl->family_data; + + /* Write the data to the scratchpad */ + if (w1_reset_select_slave(sl)) + return -1; + + wrbuf[0] = W1_F1C_WRITE_SCRATCH; + wrbuf[1] = addr & 0xff; + wrbuf[2] = addr >> 8; + + w1_write_block(sl->master, wrbuf, 3); + w1_write_block(sl->master, data, len); + + /* Read the scratchpad and verify */ + if (w1_reset_select_slave(sl)) + return -1; + + w1_write_8(sl->master, W1_F1C_READ_SCRATCH); + w1_read_block(sl->master, rdbuf, len + 3); + + /* Compare what was read against the data written */ + if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) || + (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) + return -1; + + /* Copy the scratchpad to EEPROM */ + if (w1_reset_select_slave(sl)) + return -1; + + wrbuf[0] = W1_F1C_COPY_SCRATCH; + wrbuf[3] = es; + + for (i = 0; i < sizeof(wrbuf); ++i) { + /* issue 10ms strong pullup (or delay) on the last byte + for writing the data from the scratchpad to EEPROM */ + if (w1_strong_pullup && i == sizeof(wrbuf)-1) + w1_next_pullup(sl->master, tm); + + w1_write_8(sl->master, wrbuf[i]); + } + + if (!w1_strong_pullup) + msleep(tm); + + if (w1_enable_crccheck) { + /* invalidate cached data */ + f1C->validcrc &= ~(1 << (addr >> W1_PAGE_BITS)); + } + + /* Reset the bus to wake up the EEPROM (this may not be needed) */ + w1_reset_bus(sl->master); + + return 0; +} + +static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) + +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + int addr, len, idx; + + count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE); + if (count == 0) + return 0; + + if (w1_enable_crccheck) { + /* can only write full blocks in cached mode */ + if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) { + dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n", + (int)off, count); + return -EINVAL; + } + + /* make sure the block CRCs are valid */ + for (idx = 0; idx < count; idx += W1_PAGE_SIZE) { + if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) + != CRC16_VALID) { + dev_err(&sl->dev, "bad CRC at offset %d\n", + (int)off); + return -EINVAL; + } + } + } + + mutex_lock(&sl->master->mutex); + + /* Can only write data to one page at a time */ + idx = 0; + while (idx < count) { + addr = off + idx; + len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK); + if (len > (count - idx)) + len = count - idx; + + if (w1_f1C_write(sl, addr, len, &buf[idx]) < 0) { + count = -EIO; + goto out_up; + } + idx += len; + } + +out_up: + mutex_unlock(&sl->master->mutex); + + return count; +} + +static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) + +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + int ret; + + /* check arguments */ + if (off != 0 || count != 1 || buf == NULL) + return -EINVAL; + + mutex_lock(&sl->master->mutex); + ret = w1_f1C_read(sl, W1_1C_REG_LOGIC_STATE, count, buf); + mutex_unlock(&sl->master->mutex); + + return ret; +} + +static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) + +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + u8 wrbuf[3]; + u8 ack; + + /* check arguments */ + if (off != 0 || count != 1 || buf == NULL) + return -EINVAL; + + mutex_lock(&sl->master->mutex); + + /* Write the PIO data */ + if (w1_reset_select_slave(sl)) { + mutex_unlock(&sl->master->mutex); + return -1; + } + + /* set bit 7..2 to value '1' */ + *buf = *buf | 0xFC; + + wrbuf[0] = W1_F1C_ACCESS_WRITE; + wrbuf[1] = *buf; + wrbuf[2] = ~(*buf); + w1_write_block(sl->master, wrbuf, 3); + + w1_read_block(sl->master, &ack, sizeof(ack)); + + mutex_unlock(&sl->master->mutex); + + /* check for acknowledgement */ + if (ack != 0xAA) + return -EIO; + + return count; +} + +static ssize_t w1_f1C_show_crccheck(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (put_user(w1_enable_crccheck + 0x30, buf)) + return -EFAULT; + + return sizeof(w1_enable_crccheck); +} + +static ssize_t w1_f1C_store_crccheck(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char val; + + if (count != 1 || !buf) + return -EINVAL; + + if (get_user(val, buf)) + return -EFAULT; + + /* convert to decimal */ + val = val - 0x30; + if (val != 0 && val != 1) + return -EINVAL; + + /* set the new value */ + w1_enable_crccheck = val; + + return sizeof(w1_enable_crccheck); +} + +#define NB_SYSFS_BIN_FILES 2 +static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = { + { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = W1_EEPROM_SIZE, + .read = w1_f1C_read_bin, + .write = w1_f1C_write_bin, + }, + { + .attr = { + .name = "pio", + .mode = S_IRUGO | S_IWUSR, + }, + .size = 1, + .read = w1_f1C_read_pio, + .write = w1_f1C_write_pio, + } +}; + +static DEVICE_ATTR(crccheck, S_IWUSR | S_IRUGO, + w1_f1C_show_crccheck, w1_f1C_store_crccheck); + +static int w1_f1C_add_slave(struct w1_slave *sl) +{ + int err = 0; + int i; + struct w1_f1C_data *data = NULL; + + if (w1_enable_crccheck) { + data = kzalloc(sizeof(struct w1_f1C_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + sl->family_data = data; + } + + /* create binary sysfs attributes */ + for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) + err = sysfs_create_bin_file( + &sl->dev.kobj, &(w1_f1C_bin_attr[i])); + + if (!err) { + /* create device attributes */ + err = device_create_file(&sl->dev, &dev_attr_crccheck); + } + + if (err) { + /* remove binary sysfs attributes */ + for (i = 0; i < NB_SYSFS_BIN_FILES; ++i) + sysfs_remove_bin_file( + &sl->dev.kobj, &(w1_f1C_bin_attr[i])); + + kfree(data); + } + + return err; +} + +static void w1_f1C_remove_slave(struct w1_slave *sl) +{ + int i; + + kfree(sl->family_data); + sl->family_data = NULL; + + /* remove device attributes */ + device_remove_file(&sl->dev, &dev_attr_crccheck); + + /* remove binary sysfs attributes */ + for (i = 0; i < NB_SYSFS_BIN_FILES; ++i) + sysfs_remove_bin_file(&sl->dev.kobj, &(w1_f1C_bin_attr[i])); +} + +static struct w1_family_ops w1_f1C_fops = { + .add_slave = w1_f1C_add_slave, + .remove_slave = w1_f1C_remove_slave, +}; + +static struct w1_family w1_family_1C = { + .fid = W1_FAMILY_DS28E04, + .fops = &w1_f1C_fops, +}; + +static int __init w1_f1C_init(void) +{ + return w1_register_family(&w1_family_1C); +} + +static void __exit w1_f1C_fini(void) +{ + w1_unregister_family(&w1_family_1C); +} + +module_init(w1_f1C_init); +module_exit(w1_f1C_fini); diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 874aeb05011b..b00ada44a89b 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -30,6 +30,7 @@ #define W1_FAMILY_SMEM_01 0x01 #define W1_FAMILY_SMEM_81 0x81 #define W1_THERM_DS18S20 0x10 +#define W1_FAMILY_DS28E04 0x1C #define W1_COUNTER_DS2423 0x1D #define W1_THERM_DS1822 0x22 #define W1_EEPROM_DS2433 0x23 -- GitLab From f29e5956aebafe63f81e80f972c44c4a666e5c7f Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:19 -0700 Subject: [PATCH 0670/5711] pstore: Add console log messages support Pstore doesn't support logging kernel messages in run-time, it only dumps dmesg when kernel oopses/panics. This makes pstore useless for debugging hangs caused by HW issues or improper use of HW (e.g. weird device inserted -> driver tried to write a reserved bits -> SoC hanged. In that case we don't get any messages in the pstore. Therefore, let's add a runtime logging support: PSTORE_TYPE_CONSOLE. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Acked-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- fs/pstore/Kconfig | 7 +++++++ fs/pstore/inode.c | 3 +++ fs/pstore/platform.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/pstore.h | 1 + 4 files changed, 48 insertions(+) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 23ade2680a4a..d044de6ee308 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -12,6 +12,13 @@ config PSTORE If you don't have a platform persistent store driver, say N. +config PSTORE_CONSOLE + bool "Log kernel console messages" + depends on PSTORE + help + When the option is enabled, pstore will log all kernel + messages, even if no oops or panic happened. + config PSTORE_RAM tristate "Log panic/oops to a RAM buffer" depends on PSTORE diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 11a2aa2a56c4..45bff5441b04 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -212,6 +212,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, case PSTORE_TYPE_DMESG: sprintf(name, "dmesg-%s-%lld", psname, id); break; + case PSTORE_TYPE_CONSOLE: + sprintf(name, "console-%s", psname); + break; case PSTORE_TYPE_MCE: sprintf(name, "mce-%s-%lld", psname, id); break; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 82c585f715e3..61461ed9b6c8 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -1,6 +1,7 @@ /* * Persistent Storage - platform driver interface parts. * + * Copyright (C) 2007-2008 Google, Inc. * Copyright (C) 2010 Intel Corporation * * This program is free software; you can redistribute it and/or modify @@ -22,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +158,40 @@ static struct kmsg_dumper pstore_dumper = { .dump = pstore_dump, }; +#ifdef CONFIG_PSTORE_CONSOLE +static void pstore_console_write(struct console *con, const char *s, unsigned c) +{ + const char *e = s + c; + + while (s < e) { + unsigned long flags; + + if (c > psinfo->bufsize) + c = psinfo->bufsize; + spin_lock_irqsave(&psinfo->buf_lock, flags); + memcpy(psinfo->buf, s, c); + psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo); + spin_unlock_irqrestore(&psinfo->buf_lock, flags); + s += c; + c = e - s; + } +} + +static struct console pstore_console = { + .name = "pstore", + .write = pstore_console_write, + .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME, + .index = -1, +}; + +static void pstore_register_console(void) +{ + register_console(&pstore_console); +} +#else +static void pstore_register_console(void) {} +#endif + /* * platform specific persistent storage driver registers with * us here. If pstore is already mounted, call the platform @@ -193,6 +229,7 @@ int pstore_register(struct pstore_info *psi) pstore_get_records(0); kmsg_dump_register(&pstore_dumper); + pstore_register_console(); pstore_timer.expires = jiffies + PSTORE_INTERVAL; add_timer(&pstore_timer); diff --git a/include/linux/pstore.h b/include/linux/pstore.h index e1461e143be2..1bd014b8e432 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -29,6 +29,7 @@ enum pstore_type_id { PSTORE_TYPE_DMESG = 0, PSTORE_TYPE_MCE = 1, + PSTORE_TYPE_CONSOLE = 2, PSTORE_TYPE_UNKNOWN = 255 }; -- GitLab From cac2eb7b580c95e3871a71276c99e2bd751a1624 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:20 -0700 Subject: [PATCH 0671/5711] pstore/ram: Give proper names to dump-related variables We're about to add support for other message types, so let's rename some variables to not be confused later. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 453030f9c5bc..9b274b98bf3b 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -68,9 +68,9 @@ struct ramoops_context { size_t record_size; int dump_oops; bool ecc; - unsigned int count; - unsigned int max_count; - unsigned int read_count; + unsigned int max_dump_cnt; + unsigned int dump_write_cnt; + unsigned int dump_read_cnt; struct pstore_info pstore; }; @@ -81,7 +81,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; - cxt->read_count = 0; + cxt->dump_read_cnt = 0; return 0; } @@ -94,10 +94,10 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; - if (cxt->read_count >= cxt->max_count) + if (cxt->dump_read_cnt >= cxt->max_dump_cnt) return -EINVAL; - *id = cxt->read_count++; + *id = cxt->dump_read_cnt++; prz = cxt->przs[*id]; /* Only supports dmesg output so far. */ @@ -141,7 +141,7 @@ static int ramoops_pstore_write(enum pstore_type_id type, size_t size, struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; - struct persistent_ram_zone *prz = cxt->przs[cxt->count]; + struct persistent_ram_zone *prz = cxt->przs[cxt->dump_write_cnt]; size_t hlen; /* Currently ramoops is designed to only store dmesg dumps. */ @@ -172,7 +172,7 @@ static int ramoops_pstore_write(enum pstore_type_id type, size = prz->buffer_size - hlen; persistent_ram_write(prz, cxt->pstore.buf, size); - cxt->count = (cxt->count + 1) % cxt->max_count; + cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt; return 0; } @@ -182,7 +182,7 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, { struct ramoops_context *cxt = psi->data; - if (id >= cxt->max_count) + if (id >= cxt->max_dump_cnt) return -EINVAL; persistent_ram_free_old(cxt->przs[id]); @@ -213,7 +213,7 @@ static int __init ramoops_probe(struct platform_device *pdev) /* Only a single ramoops area allowed at a time, so fail extra * probes. */ - if (cxt->max_count) + if (cxt->max_dump_cnt) goto fail_out; if (!pdata->mem_size || !pdata->record_size) { @@ -239,22 +239,22 @@ static int __init ramoops_probe(struct platform_device *pdev) goto fail_out; } - cxt->max_count = pdata->mem_size / pdata->record_size; - cxt->count = 0; + cxt->max_dump_cnt = pdata->mem_size / pdata->record_size; + cxt->dump_read_cnt = 0; cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; cxt->record_size = pdata->record_size; cxt->dump_oops = pdata->dump_oops; cxt->ecc = pdata->ecc; - cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL); + cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt, GFP_KERNEL); if (!cxt->przs) { err = -ENOMEM; dev_err(dev, "failed to initialize a prz array\n"); goto fail_out; } - for (i = 0; i < cxt->max_count; i++) { + for (i = 0; i < cxt->max_dump_cnt; i++) { size_t sz = cxt->record_size; phys_addr_t start = cxt->phys_addr + sz * i; @@ -293,7 +293,7 @@ static int __init ramoops_probe(struct platform_device *pdev) pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n", cxt->size, (unsigned long long)cxt->phys_addr, - cxt->max_count, cxt->record_size, + cxt->max_dump_cnt, cxt->record_size, ramoops_ecc ? "on" : "off"); return 0; @@ -302,7 +302,7 @@ fail_buf: kfree(cxt->pstore.buf); fail_clear: cxt->pstore.bufsize = 0; - cxt->max_count = 0; + cxt->max_dump_cnt = 0; fail_przs: for (i = 0; cxt->przs[i]; i++) persistent_ram_free(cxt->przs[i]); @@ -321,7 +321,7 @@ static int __exit ramoops_remove(struct platform_device *pdev) iounmap(cxt->virt_addr); release_mem_region(cxt->phys_addr, cxt->size); - cxt->max_count = 0; + cxt->max_dump_cnt = 0; /* TODO(kees): When pstore supports unregistering, call it here. */ kfree(cxt->pstore.buf); -- GitLab From f4c5d2423c64266ba0daa9cc803d1d5ba469fe36 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:21 -0700 Subject: [PATCH 0672/5711] pstore/ram: Factor dmesg przs initialization out of probe() This will help make code clearer when we'll add support for other message types. This also makes probe() much shorter and understandable, plus makes mem/record size checking a bit easier. Implementation detail: we now use a paddr pointer, this will be used for allocating persistent ram zones for other message types. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram.c | 99 +++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 9b274b98bf3b..6b7676738493 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -202,13 +202,65 @@ static struct ramoops_context oops_cxt = { }, }; +static void ramoops_free_przs(struct ramoops_context *cxt) +{ + int i; + + if (!cxt->przs) + return; + + for (i = 0; cxt->przs[i]; i++) + persistent_ram_free(cxt->przs[i]); + kfree(cxt->przs); +} + +static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, + phys_addr_t *paddr, size_t dump_mem_sz) +{ + int err = -ENOMEM; + int i; + + if (!cxt->record_size) + return 0; + + cxt->max_dump_cnt = dump_mem_sz / cxt->record_size; + if (!cxt->max_dump_cnt) + return -ENOMEM; + + cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt, + GFP_KERNEL); + if (!cxt->przs) { + dev_err(dev, "failed to initialize a prz array for dumps\n"); + return -ENOMEM; + } + + for (i = 0; i < cxt->max_dump_cnt; i++) { + size_t sz = cxt->record_size; + + cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc); + if (IS_ERR(cxt->przs[i])) { + err = PTR_ERR(cxt->przs[i]); + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", + sz, (unsigned long long)*paddr, err); + goto fail_prz; + } + *paddr += sz; + } + + return 0; +fail_prz: + ramoops_free_przs(cxt); + return err; +} + static int __init ramoops_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ramoops_platform_data *pdata = pdev->dev.platform_data; struct ramoops_context *cxt = &oops_cxt; + size_t dump_mem_sz; + phys_addr_t paddr; int err = -EINVAL; - int i; /* Only a single ramoops area allowed at a time, so fail extra * probes. @@ -225,21 +277,6 @@ static int __init ramoops_probe(struct platform_device *pdev) pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); pdata->record_size = rounddown_pow_of_two(pdata->record_size); - /* Check for the minimum memory size */ - if (pdata->mem_size < MIN_MEM_SIZE && - pdata->record_size < MIN_MEM_SIZE) { - pr_err("memory size too small, minimum is %lu\n", - MIN_MEM_SIZE); - goto fail_out; - } - - if (pdata->mem_size < pdata->record_size) { - pr_err("The memory size must be larger than the " - "records size\n"); - goto fail_out; - } - - cxt->max_dump_cnt = pdata->mem_size / pdata->record_size; cxt->dump_read_cnt = 0; cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; @@ -247,24 +284,14 @@ static int __init ramoops_probe(struct platform_device *pdev) cxt->dump_oops = pdata->dump_oops; cxt->ecc = pdata->ecc; - cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt, GFP_KERNEL); - if (!cxt->przs) { - err = -ENOMEM; - dev_err(dev, "failed to initialize a prz array\n"); - goto fail_out; - } - - for (i = 0; i < cxt->max_dump_cnt; i++) { - size_t sz = cxt->record_size; - phys_addr_t start = cxt->phys_addr + sz * i; + paddr = cxt->phys_addr; - cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc); - if (IS_ERR(cxt->przs[i])) { - err = PTR_ERR(cxt->przs[i]); - dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", - sz, (unsigned long long)start, err); - goto fail_przs; - } + dump_mem_sz = cxt->size; + err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); + if (err) { + pr_err("memory size too small, minimum is %lu\n", + cxt->record_size); + goto fail_count; } cxt->pstore.data = cxt; @@ -303,10 +330,8 @@ fail_buf: fail_clear: cxt->pstore.bufsize = 0; cxt->max_dump_cnt = 0; -fail_przs: - for (i = 0; cxt->przs[i]; i++) - persistent_ram_free(cxt->przs[i]); - kfree(cxt->przs); +fail_count: + ramoops_free_przs(cxt); fail_out: return err; } -- GitLab From 755d66b48fe5a1f2a07802fcc8704e8b9e775e7d Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:22 -0700 Subject: [PATCH 0673/5711] pstore/ram: Factor ramoops_get_next_prz() out of ramoops_pstore_read() This will help make code clearer when we'll add support for other message types. The patch also changes return value from -EINVAL to 0 in case of end-of-records. The exact value doesn't matter for pstore (it should be just <= 0), but 0 feels more correct. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 6b7676738493..d770d7266e96 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -85,6 +85,33 @@ static int ramoops_pstore_open(struct pstore_info *psi) return 0; } +static struct persistent_ram_zone * +ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, + u64 *id, + enum pstore_type_id *typep, enum pstore_type_id type, + bool update) +{ + struct persistent_ram_zone *prz; + int i = (*c)++; + + if (i >= max) + return NULL; + + prz = przs[i]; + + if (update) { + /* Update old/shadowed buffer. */ + persistent_ram_save_old(prz); + if (!persistent_ram_old_size(prz)) + return NULL; + } + + *typep = type; + *id = i; + + return prz; +} + static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, struct timespec *time, char **buf, @@ -94,20 +121,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; - if (cxt->dump_read_cnt >= cxt->max_dump_cnt) - return -EINVAL; - - *id = cxt->dump_read_cnt++; - prz = cxt->przs[*id]; + prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, + cxt->max_dump_cnt, id, type, + PSTORE_TYPE_DMESG, 1); + if (!prz) + return 0; - /* Only supports dmesg output so far. */ - *type = PSTORE_TYPE_DMESG; /* TODO(kees): Bogus time for the moment. */ time->tv_sec = 0; time->tv_nsec = 0; - /* Update old/shadowed buffer. */ - persistent_ram_save_old(prz); size = persistent_ram_old_size(prz); *buf = kmalloc(size, GFP_KERNEL); if (*buf == NULL) -- GitLab From b5d38e9bf1b0c4db19e336b59b38dfb5d28bf1bf Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:23 -0700 Subject: [PATCH 0674/5711] pstore/ram: Add console messages handling The console log size is configurable via ramoops.console_size module option, and the log itself is available via /console-ramoops file. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram.c | 100 +++++++++++++++++++++++++++++++------ include/linux/pstore_ram.h | 1 + 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index d770d7266e96..c7acf94ff475 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -41,6 +41,10 @@ module_param(record_size, ulong, 0400); MODULE_PARM_DESC(record_size, "size of each dump done on oops/panic"); +static ulong ramoops_console_size = MIN_MEM_SIZE; +module_param_named(console_size, ramoops_console_size, ulong, 0400); +MODULE_PARM_DESC(console_size, "size of kernel console log"); + static ulong mem_address; module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, @@ -63,14 +67,17 @@ MODULE_PARM_DESC(ramoops_ecc, struct ramoops_context { struct persistent_ram_zone **przs; + struct persistent_ram_zone *cprz; phys_addr_t phys_addr; unsigned long size; size_t record_size; + size_t console_size; int dump_oops; bool ecc; unsigned int max_dump_cnt; unsigned int dump_write_cnt; unsigned int dump_read_cnt; + unsigned int console_read_cnt; struct pstore_info pstore; }; @@ -82,6 +89,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) struct ramoops_context *cxt = psi->data; cxt->dump_read_cnt = 0; + cxt->console_read_cnt = 0; return 0; } @@ -124,6 +132,9 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); + if (!prz) + prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, + 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz) return 0; @@ -167,7 +178,13 @@ static int ramoops_pstore_write(enum pstore_type_id type, struct persistent_ram_zone *prz = cxt->przs[cxt->dump_write_cnt]; size_t hlen; - /* Currently ramoops is designed to only store dmesg dumps. */ + if (type == PSTORE_TYPE_CONSOLE) { + if (!cxt->cprz) + return -ENOMEM; + persistent_ram_write(cxt->cprz, cxt->pstore.buf, size); + return 0; + } + if (type != PSTORE_TYPE_DMESG) return -EINVAL; @@ -204,12 +221,23 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; + struct persistent_ram_zone *prz; - if (id >= cxt->max_dump_cnt) + switch (type) { + case PSTORE_TYPE_DMESG: + if (id >= cxt->max_dump_cnt) + return -EINVAL; + prz = cxt->przs[id]; + break; + case PSTORE_TYPE_CONSOLE: + prz = cxt->cprz; + break; + default: return -EINVAL; + } - persistent_ram_free_old(cxt->przs[id]); - persistent_ram_zap(cxt->przs[id]); + persistent_ram_free_old(prz); + persistent_ram_zap(prz); return 0; } @@ -276,6 +304,32 @@ fail_prz: return err; } +static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, + struct persistent_ram_zone **prz, + phys_addr_t *paddr, size_t sz) +{ + if (!sz) + return 0; + + if (*paddr + sz > *paddr + cxt->size) + return -ENOMEM; + + *prz = persistent_ram_new(*paddr, sz, cxt->ecc); + if (IS_ERR(*prz)) { + int err = PTR_ERR(*prz); + + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", + sz, (unsigned long long)*paddr, err); + return err; + } + + persistent_ram_zap(*prz); + + *paddr += sz; + + return 0; +} + static int __init ramoops_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -291,34 +345,50 @@ static int __init ramoops_probe(struct platform_device *pdev) if (cxt->max_dump_cnt) goto fail_out; - if (!pdata->mem_size || !pdata->record_size) { - pr_err("The memory size and the record size must be " + if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size)) { + pr_err("The memory size and the record/console size must be " "non-zero\n"); goto fail_out; } pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); pdata->record_size = rounddown_pow_of_two(pdata->record_size); + pdata->console_size = rounddown_pow_of_two(pdata->console_size); cxt->dump_read_cnt = 0; cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; cxt->record_size = pdata->record_size; + cxt->console_size = pdata->console_size; cxt->dump_oops = pdata->dump_oops; cxt->ecc = pdata->ecc; paddr = cxt->phys_addr; - dump_mem_sz = cxt->size; + dump_mem_sz = cxt->size - cxt->console_size; err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); - if (err) { + if (err) + goto fail_out; + + err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr, cxt->console_size); + if (err) + goto fail_init_cprz; + + if (!cxt->przs && !cxt->cprz) { pr_err("memory size too small, minimum is %lu\n", - cxt->record_size); - goto fail_count; + cxt->console_size + cxt->record_size); + goto fail_cnt; } cxt->pstore.data = cxt; - cxt->pstore.bufsize = cxt->przs[0]->buffer_size; + /* + * Console can handle any buffer size, so prefer dumps buffer + * size since usually it is smaller. + */ + if (cxt->przs) + cxt->pstore.bufsize = cxt->przs[0]->buffer_size; + else + cxt->pstore.bufsize = cxt->cprz->buffer_size; cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); spin_lock_init(&cxt->pstore.buf_lock); if (!cxt->pstore.buf) { @@ -341,9 +411,8 @@ static int __init ramoops_probe(struct platform_device *pdev) record_size = pdata->record_size; dump_oops = pdata->dump_oops; - pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n", + pr_info("attached 0x%lx@0x%llx, ecc: %s\n", cxt->size, (unsigned long long)cxt->phys_addr, - cxt->max_dump_cnt, cxt->record_size, ramoops_ecc ? "on" : "off"); return 0; @@ -353,7 +422,9 @@ fail_buf: fail_clear: cxt->pstore.bufsize = 0; cxt->max_dump_cnt = 0; -fail_count: +fail_cnt: + kfree(cxt->cprz); +fail_init_cprz: ramoops_free_przs(cxt); fail_out: return err; @@ -405,6 +476,7 @@ static int __init ramoops_init(void) dummy_data->mem_size = mem_size; dummy_data->mem_address = mem_address; dummy_data->record_size = record_size; + dummy_data->console_size = ramoops_console_size; dummy_data->dump_oops = dump_oops; dummy_data->ecc = ramoops_ecc; dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 3b823d49a85a..9385d41cb1c3 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -93,6 +93,7 @@ struct ramoops_platform_data { unsigned long mem_size; unsigned long mem_address; unsigned long record_size; + unsigned long console_size; int dump_oops; bool ecc; }; -- GitLab From 602b5be4f14cabd5b751c340919958549475ab62 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:24 -0700 Subject: [PATCH 0675/5711] pstore/ram_core: Silence some printks Since we use multiple regions, the messages are somewhat annoying. We do print total mapped memory already, so no need to print the information for each region in the library routines. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Acked-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index c5fbdbbf81ac..78f6d4b2addb 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -409,14 +409,14 @@ static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool " size %zu, start %zu\n", buffer_size(prz), buffer_start(prz)); else { - pr_info("persistent_ram: found existing buffer," + pr_debug("persistent_ram: found existing buffer," " size %zu, start %zu\n", buffer_size(prz), buffer_start(prz)); persistent_ram_save_old(prz); return 0; } } else { - pr_info("persistent_ram: no valid data in buffer" + pr_debug("persistent_ram: no valid data in buffer" " (sig = 0x%08x)\n", prz->buffer->sig); } -- GitLab From 958502d836cf18c6f39bdb787b76d53839e4d8aa Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:25 -0700 Subject: [PATCH 0676/5711] pstore/ram: Add some more documentation and examples Suggested-by: Shuah Khan Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Acked-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- Documentation/ramoops.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt index 4ba7db231cb2..59a74a8ee2e5 100644 --- a/Documentation/ramoops.txt +++ b/Documentation/ramoops.txt @@ -40,6 +40,12 @@ corrupt, but usually it is restorable. Setting the ramoops parameters can be done in 2 different manners: 1. Use the module parameters (which have the names of the variables described as before). + For quick debugging, you can also reserve parts of memory during boot + and then use the reserved memory for ramoops. For example, assuming a machine + with > 128 MB of memory, the following kernel command line will tell the + kernel to use only the first 128 MB of memory, and place ECC-protected ramoops + region at 128 MB boundary: + "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1" 2. Use a platform device and set the platform data. The parameters can then be set through that platform data. An example of doing that is: @@ -70,6 +76,14 @@ if (ret) { return ret; } +You can specify either RAM memory or peripheral devices' memory. However, when +specifying RAM, be sure to reserve the memory by issuing memblock_reserve() +very early in the architecture code, e.g.: + +#include + +memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size); + 3. Dump format The data dump begins with a header, currently defined as "====" followed by a -- GitLab From b8587daa756141da776e3d4c3a5a315f5af78708 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:27 -0700 Subject: [PATCH 0677/5711] pstore/ram_core: Remove now unused code The code tried to maintain the global list of persistent ram zones, which isn't a great idea overall, plus since Android's ram_console is no longer there, we can remove some unused functions. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Acked-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram_core.c | 77 -------------------------------------- include/linux/pstore_ram.h | 19 ---------- 2 files changed, 96 deletions(-) diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 78f6d4b2addb..0fd81611525c 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -35,8 +35,6 @@ struct persistent_ram_buffer { #define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ -static __initdata LIST_HEAD(persistent_ram_list); - static inline size_t buffer_size(struct persistent_ram_zone *prz) { return atomic_read(&prz->buffer->size); @@ -462,78 +460,3 @@ err: kfree(prz); return ERR_PTR(ret); } - -#ifndef MODULE -static int __init persistent_ram_buffer_init(const char *name, - struct persistent_ram_zone *prz) -{ - int i; - struct persistent_ram *ram; - struct persistent_ram_descriptor *desc; - phys_addr_t start; - - list_for_each_entry(ram, &persistent_ram_list, node) { - start = ram->start; - for (i = 0; i < ram->num_descs; i++) { - desc = &ram->descs[i]; - if (!strcmp(desc->name, name)) - return persistent_ram_buffer_map(start, - desc->size, prz); - start += desc->size; - } - } - - return -EINVAL; -} - -static __init -struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) -{ - struct persistent_ram_zone *prz; - int ret = -ENOMEM; - - prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); - if (!prz) { - pr_err("persistent_ram: failed to allocate persistent ram zone\n"); - goto err; - } - - ret = persistent_ram_buffer_init(dev_name(dev), prz); - if (ret) { - pr_err("persistent_ram: failed to initialize buffer\n"); - goto err; - } - - persistent_ram_post_init(prz, ecc); - - return prz; -err: - kfree(prz); - return ERR_PTR(ret); -} - -struct persistent_ram_zone * __init -persistent_ram_init_ringbuffer(struct device *dev, bool ecc) -{ - return __persistent_ram_init(dev, ecc); -} - -int __init persistent_ram_early_init(struct persistent_ram *ram) -{ - int ret; - - ret = memblock_reserve(ram->start, ram->size); - if (ret) { - pr_err("Failed to reserve persistent memory from %08lx-%08lx\n", - (long)ram->start, (long)(ram->start + ram->size - 1)); - return ret; - } - - list_add_tail(&ram->node, &persistent_ram_list); - - pr_info("Initialized persistent memory from %08lx-%08lx\n", - (long)ram->start, (long)(ram->start + ram->size - 1)); - - return 0; -} -#endif diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 9385d41cb1c3..2470bb591434 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -25,21 +25,6 @@ struct persistent_ram_buffer; -struct persistent_ram_descriptor { - const char *name; - phys_addr_t size; -}; - -struct persistent_ram { - phys_addr_t start; - phys_addr_t size; - - int num_descs; - struct persistent_ram_descriptor *descs; - - struct list_head node; -}; - struct persistent_ram_zone { phys_addr_t paddr; size_t size; @@ -63,15 +48,11 @@ struct persistent_ram_zone { size_t old_log_size; }; -int persistent_ram_early_init(struct persistent_ram *ram); - struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, size_t size, bool ecc); void persistent_ram_free(struct persistent_ram_zone *prz); void persistent_ram_zap(struct persistent_ram_zone *prz); -struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev, - bool ecc); int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, unsigned int count); -- GitLab From a3f5f075c2e2c52c9c656c54ea77ceff5b2e1e25 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:28 -0700 Subject: [PATCH 0678/5711] pstore/platform: Make automatic updates interval configurable There is no behavioural change, the default value is still 60 seconds. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/platform.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 61461ed9b6c8..34ca3141eb0a 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "internal.h" @@ -40,7 +41,10 @@ * whether the system is actually still running well enough * to let someone see the entry */ -#define PSTORE_INTERVAL (60 * HZ) +static int pstore_update_ms = 60000; +module_param_named(update_ms, pstore_update_ms, int, 0600); +MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content " + "(default is 60000; -1 means runtime updates are disabled)"); static int pstore_new_entry; @@ -231,8 +235,11 @@ int pstore_register(struct pstore_info *psi) kmsg_dump_register(&pstore_dumper); pstore_register_console(); - pstore_timer.expires = jiffies + PSTORE_INTERVAL; - add_timer(&pstore_timer); + if (pstore_update_ms >= 0) { + pstore_timer.expires = jiffies + + msecs_to_jiffies(pstore_update_ms); + add_timer(&pstore_timer); + } return 0; } @@ -291,7 +298,7 @@ static void pstore_timefunc(unsigned long dummy) schedule_work(&pstore_work); } - mod_timer(&pstore_timer, jiffies + PSTORE_INTERVAL); + mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms)); } module_param(backend, charp, 0444); -- GitLab From 521f7288a8126a8ec28e3ab623aacf0590684b80 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:29 -0700 Subject: [PATCH 0679/5711] pstore/platform: Disable automatic updates by default Having automatic updates seems pointless for production system, and even dangerous and thus counter-productive: 1. If we can mount pstore, or read files, we can as well read /proc/kmsg. So, there's little point in duplicating the functionality and present the same information but via another userland ABI; 2. Expecting the kernel to behave sanely after oops/panic is naive. It might work, but you'd rather not try it. Screwed up kernel can do rather bad things, like recursive faults[1]; and pstore rather provoking bad things to happen. It uses: 1. Timers (assumes sane interrupts state); 2. Workqueues and mutexes (assumes scheduler in a sane state); 3. kzalloc (a working slab allocator); That's too much for a dead kernel, so the debugging facility itself might just make debugging harder, which is not what we want. Maybe for non-oops message types it would make sense to re-enable automatic updates, but so far I don't see any use case for this. Even for tracing, it has its own run-time/normal ABI, so we're only interested in pstore upon next boot, to retrieve what has gone wrong with HW or SW. So, let's disable the updates by default. [1] BUG: unable to handle kernel paging request at fffffffffffffff8 IP: [] kthread_data+0xb/0x20 [...] Process kworker/0:1 (pid: 14, threadinfo ffff8800072c0000, task ffff88000725b100) [... Call Trace: [] wq_worker_sleeping+0x10/0xa0 [] __schedule+0x568/0x7d0 [] ? trace_hardirqs_on+0xd/0x10 [] ? call_rcu_sched+0x12/0x20 [] ? release_task+0x156/0x2d0 [] ? release_task+0x1e/0x2d0 [] ? trace_hardirqs_on+0xd/0x10 [] schedule+0x24/0x70 [] do_exit+0x1f8/0x370 [] oops_end+0x77/0xb0 [] no_context+0x1a6/0x1b5 [] __bad_area_nosemaphore+0x1ce/0x1ed [] ? ttwu_queue+0xc6/0xe0 [] bad_area_nosemaphore+0xe/0x10 [] do_page_fault+0x2c7/0x450 [] ? __lock_release+0x6b/0xe0 [] ? mark_held_locks+0x61/0x140 [] ? __wake_up+0x4e/0x70 [] ? trace_hardirqs_off_thunk+0x3a/0x3c [] ? pstore_register+0x120/0x120 [] page_fault+0x1f/0x30 [] ? pstore_register+0x120/0x120 [] ? memcpy+0x68/0x110 [] ? pstore_get_records+0x3a/0x130 [] ? persistent_ram_copy_old+0x64/0x90 [] ramoops_pstore_read+0x84/0x130 [] pstore_get_records+0x79/0x130 [] ? process_one_work+0x116/0x450 [] ? pstore_register+0x120/0x120 [] pstore_dowork+0xe/0x10 [] process_one_work+0x174/0x450 [] ? process_one_work+0x116/0x450 [] worker_thread+0x123/0x2d0 [] ? manage_workers.isra.28+0x120/0x120 [] kthread+0x8e/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? retint_restore_args+0xe/0xe [] ? __init_kthread_worker+0x70/0x70 [] ? gs_change+0xb/0xb Code: be e2 00 00 00 48 c7 c7 d1 2a 4e 81 e8 bf fb fd ff 48 8b 5d f0 4c 8b 65 f8 c9 c3 0f 1f 44 00 00 48 8b 87 08 02 00 00 55 48 89 e5 <48> 8b 40 f8 5d c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 RIP [] kthread_data+0xb/0x20 RSP CR2: fffffffffffffff8 ---[ end trace 996a332dc399111d ]--- Fixing recursive fault but reboot is needed! Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- fs/pstore/platform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 34ca3141eb0a..be4614f24a2f 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -41,10 +41,12 @@ * whether the system is actually still running well enough * to let someone see the entry */ -static int pstore_update_ms = 60000; +static int pstore_update_ms = -1; module_param_named(update_ms, pstore_update_ms, int, 0600); MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content " - "(default is 60000; -1 means runtime updates are disabled)"); + "(default is -1, which means runtime updates are disabled; " + "enabling this option is not safe, it may lead to further " + "corruption on Oopses)"); static int pstore_new_entry; -- GitLab From 15d76446205710ddfcba6cc9156c7883074f84b1 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 26 May 2012 06:20:26 -0700 Subject: [PATCH 0680/5711] staging/android: Remove ram_console driver All the functionality is now supported by pstore and pstore_ram drivers. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Acked-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 5 - drivers/staging/android/Makefile | 1 - drivers/staging/android/ram_console.c | 181 -------------------------- 3 files changed, 187 deletions(-) delete mode 100644 drivers/staging/android/ram_console.c diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 0e16b594460f..0ce50d12c30f 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -25,11 +25,6 @@ config ANDROID_LOGGER tristate "Android log driver" default n -config ANDROID_RAM_CONSOLE - bool "Android RAM buffer console" - depends on !S390 && !UML && HAVE_MEMBLOCK && PSTORE_RAM=y - default n - config ANDROID_TIMED_OUTPUT bool "Timed output class driver" default y diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 98711e2b2afa..e16fcd51716e 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o -obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c deleted file mode 100644 index 7add022b1c22..000000000000 --- a/drivers/staging/android/ram_console.c +++ /dev/null @@ -1,181 +0,0 @@ -/* drivers/android/ram_console.c - * - * Copyright (C) 2007-2008 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. - * - */ - -#define pr_fmt(fmt) "ram_console: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ram_console.h" - -static struct persistent_ram_zone *ram_console_zone; -static const char *bootinfo; -static size_t bootinfo_size; - -static void -ram_console_write(struct console *console, const char *s, unsigned int count) -{ - struct persistent_ram_zone *prz = console->data; - persistent_ram_write(prz, s, count); -} - -static struct console ram_console = { - .name = "ram", - .write = ram_console_write, - .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME, - .index = -1, -}; - -void ram_console_enable_console(int enabled) -{ - if (enabled) - ram_console.flags |= CON_ENABLED; - else - ram_console.flags &= ~CON_ENABLED; -} - -static int __init ram_console_probe(struct platform_device *pdev) -{ - struct ram_console_platform_data *pdata = pdev->dev.platform_data; - struct persistent_ram_zone *prz; - - prz = persistent_ram_init_ringbuffer(&pdev->dev, true); - if (IS_ERR(prz)) - return PTR_ERR(prz); - - - if (pdata) { - bootinfo = kstrdup(pdata->bootinfo, GFP_KERNEL); - if (bootinfo) - bootinfo_size = strlen(bootinfo); - } - - ram_console_zone = prz; - ram_console.data = prz; - - register_console(&ram_console); - - return 0; -} - -static struct platform_driver ram_console_driver = { - .driver = { - .name = "ram_console", - }, -}; - -static int __init ram_console_module_init(void) -{ - return platform_driver_probe(&ram_console_driver, ram_console_probe); -} - -#ifndef CONFIG_PRINTK -#define dmesg_restrict 0 -#endif - -static ssize_t ram_console_read_old(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - loff_t pos = *offset; - ssize_t count; - struct persistent_ram_zone *prz = ram_console_zone; - size_t old_log_size = persistent_ram_old_size(prz); - const char *old_log = persistent_ram_old(prz); - char *str; - int ret; - - if (dmesg_restrict && !capable(CAP_SYSLOG)) - return -EPERM; - - /* Main last_kmsg log */ - if (pos < old_log_size) { - count = min(len, (size_t)(old_log_size - pos)); - if (copy_to_user(buf, old_log + pos, count)) - return -EFAULT; - goto out; - } - - /* ECC correction notice */ - pos -= old_log_size; - count = persistent_ram_ecc_string(prz, NULL, 0); - if (pos < count) { - str = kmalloc(count, GFP_KERNEL); - if (!str) - return -ENOMEM; - persistent_ram_ecc_string(prz, str, count + 1); - count = min(len, (size_t)(count - pos)); - ret = copy_to_user(buf, str + pos, count); - kfree(str); - if (ret) - return -EFAULT; - goto out; - } - - /* Boot info passed through pdata */ - pos -= count; - if (pos < bootinfo_size) { - count = min(len, (size_t)(bootinfo_size - pos)); - if (copy_to_user(buf, bootinfo + pos, count)) - return -EFAULT; - goto out; - } - - /* EOF */ - return 0; - -out: - *offset += count; - return count; -} - -static const struct file_operations ram_console_file_ops = { - .owner = THIS_MODULE, - .read = ram_console_read_old, -}; - -static int __init ram_console_late_init(void) -{ - struct proc_dir_entry *entry; - struct persistent_ram_zone *prz = ram_console_zone; - - if (!prz) - return 0; - - if (persistent_ram_old_size(prz) == 0) - return 0; - - entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); - if (!entry) { - pr_err("failed to create proc entry\n"); - persistent_ram_free_old(prz); - return 0; - } - - entry->proc_fops = &ram_console_file_ops; - entry->size = persistent_ram_old_size(prz) + - persistent_ram_ecc_string(prz, NULL, 0) + - bootinfo_size; - - return 0; -} - -late_initcall(ram_console_late_init); -postcore_initcall(ram_console_module_init); -- GitLab From 176f7842a8c0a19e0947f630d71bb53db312812f Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:39 +0200 Subject: [PATCH 0681/5711] staging/xgifb: Remove assignments without effect This patch removes assignments to the fb_fix_screeninfo struct which are overwritten by the memset in XGIfb_get_fix() a few lines later. Since the name/id might be useful this was moved to XGIfb_get_fix(). Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 033463d1966c..729d980f0104 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1348,6 +1348,8 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, DEBUGPRN("inside get_fix"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strncpy(fix->id, "XGI", sizeof(fix->id) - 1); + fix->smem_start = xgifb_info->video_base; fix->smem_len = xgifb_info->video_size; @@ -2230,11 +2232,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } - strncpy(fb_info->fix.id, "XGI", sizeof(fb_info->fix.id) - 1); - fb_info->fix.type = FB_TYPE_PACKED_PIXELS; - fb_info->fix.xpanstep = 1; - fb_info->fix.ypanstep = 1; - fb_info->flags = FBINFO_FLAG_DEFAULT; fb_info->screen_base = xgifb_info->video_vbase; fb_info->fbops = &XGIfb_ops; -- GitLab From 95649c425fa2805b76f183c27aeed93f159e47cc Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:40 +0200 Subject: [PATCH 0682/5711] staging/xgifb: Add mutext for fb_mmap locking This adds a mutex for fb_mmap around smem_start and smem_len so the mutex inside the fb_mmap() is actually used. Changing of these fields before calling the framebuffer_register() are not mutexed. We check whether framebuffer_register has been called by reading fbinfo->count. See 537a1bf0 - "fbdev: add mutex for fb_mmap locking" by Krzysztof Helt for details. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 729d980f0104..3a4328f28d07 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1350,10 +1350,17 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, strncpy(fix->id, "XGI", sizeof(fix->id) - 1); - fix->smem_start = xgifb_info->video_base; + /* if register_framebuffer has been called, we must lock */ + if (atomic_read(&info->count)) + mutex_lock(&info->mm_lock); + fix->smem_start = xgifb_info->video_base; fix->smem_len = xgifb_info->video_size; + /* if register_framebuffer has been called, we can unlock */ + if (atomic_read(&info->count)) + mutex_unlock(&info->mm_lock); + fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; if (xgifb_info->video_bpp == 8) -- GitLab From ac326fb96bdf720ceb4871a7219073c5fc257595 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:41 +0200 Subject: [PATCH 0683/5711] staging/xgifb: Add header #include guards to vb_table.h This patch adds a simple #include guard to vb_table.h Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_table.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index d22e599cb305..9a17113849ec 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1,3 +1,5 @@ +#ifndef _VB_TABLE_ +#define _VB_TABLE_ /* yilin modify for xgi20 */ static struct SiS_MCLKData XGI340New_MCLKData[] = { {0x16, 0x01, 0x01, 166}, @@ -2696,3 +2698,4 @@ static struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = { } } }; +#endif -- GitLab From f3ca589baf317d61b87c409e205bfaf740169710 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:42 +0200 Subject: [PATCH 0684/5711] staging/xgifb: Remove superfluous header includes This patch removes all unnecessary, redundant and superfluous header includes from xgifb. Tested on hp t5325 (XGI Z11) Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main.h | 6 ------ drivers/staging/xgifb/XGI_main_26.c | 26 +------------------------- drivers/staging/xgifb/XGIfb.h | 3 --- drivers/staging/xgifb/vb_init.c | 9 --------- drivers/staging/xgifb/vb_setmode.c | 8 -------- drivers/staging/xgifb/vb_util.c | 9 --------- drivers/staging/xgifb/vgatypes.h | 1 - 7 files changed, 1 insertion(+), 61 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index 9c62aeb9ede9..ce18f8c98b2d 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -1,13 +1,7 @@ #ifndef _XGIFB_MAIN #define _XGIFB_MAIN - - /* ------------------- Constant Definitions ------------------------- */ - - #include "XGIfb.h" -#include "vb_struct.h" -#include "../../video/sis/sis.h" #include "vb_def.h" #define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 3a4328f28d07..338227226260 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -6,36 +6,12 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -/* #include */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include + #ifdef CONFIG_MTRR #include #endif -#include "XGIfb.h" -#include "vgatypes.h" #include "XGI_main.h" #include "vb_init.h" #include "vb_util.h" diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h index 9068c5ad76ec..741bba351cff 100644 --- a/drivers/staging/xgifb/XGIfb.h +++ b/drivers/staging/xgifb/XGIfb.h @@ -1,8 +1,5 @@ #ifndef _LINUX_XGIFB #define _LINUX_XGIFB -#include -#include - #include "vgatypes.h" #include "vb_struct.h" diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index c222d611431d..dd6a51995ea6 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1,19 +1,10 @@ -#include #include /* udelay */ -#include #include #include "XGIfb.h" -#include "vgatypes.h" - #include "vb_def.h" -#include "vb_struct.h" #include "vb_util.h" #include "vb_setmode.h" -#include "vb_init.h" - - -#include static const unsigned short XGINew_DDRDRAM_TYPE340[4][5] = { { 2, 13, 9, 64, 0x45}, diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index b2f4338b1109..ad1e23d3c938 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1,17 +1,9 @@ - -#include #include -#include #include "XGIfb.h" - #include "vb_def.h" -#include "vgatypes.h" -#include "vb_struct.h" -#include "vb_init.h" #include "vb_util.h" #include "vb_table.h" -#include "vb_setmode.h" #define IndexMask 0xff diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c index b5c99891ead4..5c93a2202bd0 100644 --- a/drivers/staging/xgifb/vb_util.c +++ b/drivers/staging/xgifb/vb_util.c @@ -1,13 +1,4 @@ -#include -#include - -#include "vb_def.h" #include "vgatypes.h" -#include "vb_struct.h" - -#include "XGIfb.h" - -#include "vb_util.h" void xgifb_reg_set(unsigned long port, u8 index, u8 data) { diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h index 30cdd1af81f1..7fc07194eea2 100644 --- a/drivers/staging/xgifb/vgatypes.h +++ b/drivers/staging/xgifb/vgatypes.h @@ -1,7 +1,6 @@ #ifndef _VGATYPES_ #define _VGATYPES_ -#include #include /* for struct fb_var_screeninfo for sis.h */ #include "../../video/sis/vgatypes.h" #include "../../video/sis/sis.h" /* for LCD_TYPE */ -- GitLab From 391f695b90ba8b3905c818f03188440a5df9cfe7 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:43 +0200 Subject: [PATCH 0685/5711] staging/xgifb: Consolidate XGINew_SetDRAMSize{,20}Reg This patch consolidates the almost identical functions XGINew_SetDRAMSizeReg and XGINew_SetDRAMSize20Reg as they are implemented identically except one division factor. The changed factor is now reflected in the input data. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 54 +++------------------------------ 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index dd6a51995ea6..726c33561bd1 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -7,10 +7,10 @@ #include "vb_setmode.h" static const unsigned short XGINew_DDRDRAM_TYPE340[4][5] = { - { 2, 13, 9, 64, 0x45}, - { 2, 12, 9, 32, 0x35}, - { 2, 12, 8, 16, 0x31}, - { 2, 11, 8, 8, 0x21} }; + { 2, 13, 9, 16, 0x45}, + { 2, 12, 9, 8, 0x35}, + { 2, 12, 8, 4, 0x31}, + { 2, 11, 8, 2, 0x21} }; static const unsigned short XGINew_DDRDRAM_TYPE20[12][5] = { { 2, 14, 11, 128, 0x5D}, @@ -591,50 +591,6 @@ static void XGINew_SetDRAMSizingType(int index, /* should delay 50 ns */ } -static unsigned short XGINew_SetDRAMSizeReg(int index, - const unsigned short DRAMTYPE_TABLE[][5], - struct vb_device_info *pVBInfo) -{ - unsigned short data = 0, memsize = 0; - int RankSize; - unsigned char ChannelNo; - - RankSize = DRAMTYPE_TABLE[index][3] * pVBInfo->ram_bus / 32; - data = xgifb_reg_get(pVBInfo->P3c4, 0x13); - data &= 0x80; - - if (data == 0x80) - RankSize *= 2; - - data = 0; - - if (pVBInfo->ram_channel == 3) - ChannelNo = 4; - else - ChannelNo = pVBInfo->ram_channel; - - if (ChannelNo * RankSize <= 256) { - while ((RankSize >>= 1) > 0) - data += 0x10; - - memsize = data >> 4; - - /* [2004/03/25] Vicent, Fix DRAM Sizing Error */ - xgifb_reg_set(pVBInfo->P3c4, - 0x14, - (xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) | - (data & 0xF0)); - - /* data |= pVBInfo->ram_channel << 2; */ - /* data |= (pVBInfo->ram_bus / 64) << 1; */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */ - - /* should delay */ - /* XGINew_SetDRAMModeRegister340(pVBInfo); */ - } - return memsize; -} - static unsigned short XGINew_SetDRAMSize20Reg(int index, const unsigned short DRAMTYPE_TABLE[][5], struct vb_device_info *pVBInfo) @@ -968,7 +924,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, XGINew_SetDRAMSizingType(i, XGINew_DDRDRAM_TYPE340, pVBInfo); - memsize = XGINew_SetDRAMSizeReg(i, + memsize = XGINew_SetDRAMSize20Reg(i, XGINew_DDRDRAM_TYPE340, pVBInfo); -- GitLab From 672f5ee27e622c995bd0c19d2ba1bb5a55b6d902 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:44 +0200 Subject: [PATCH 0686/5711] staging/xgifb: Remove duplicated code from XGINew_DDRSizing340 Since XGINew_SetDRAMSize20Reg now handles both cases we can remove the code duplication in XGINew_DDRSizing340. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 64 +++++++++++++-------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 726c33561bd1..512284c3de91 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -893,52 +893,38 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { - int i; - unsigned short memsize, addr; + u8 i, size; + unsigned short memsize, start_addr; + const unsigned short (*dram_table)[5]; xgifb_reg_set(pVBInfo->P3c4, 0x15, 0x00); /* noninterleaving */ xgifb_reg_set(pVBInfo->P3c4, 0x1C, 0x00); /* nontiling */ XGINew_CheckChannel(HwDeviceExtension, pVBInfo); if (HwDeviceExtension->jChipType >= XG20) { - for (i = 0; i < 12; i++) { - XGINew_SetDRAMSizingType(i, - XGINew_DDRDRAM_TYPE20, - pVBInfo); - memsize = XGINew_SetDRAMSize20Reg(i, - XGINew_DDRDRAM_TYPE20, - pVBInfo); - if (memsize == 0) - continue; - - addr = memsize + (pVBInfo->ram_channel - 2) + 20; - if ((HwDeviceExtension->ulVideoMemorySize - 1) < - (unsigned long) (1 << addr)) - continue; - - if (XGINew_ReadWriteRest(addr, 5, pVBInfo) == 1) - return 1; - } + dram_table = XGINew_DDRDRAM_TYPE20; + size = ARRAY_SIZE(XGINew_DDRDRAM_TYPE20); + start_addr = 5; } else { - for (i = 0; i < 4; i++) { - XGINew_SetDRAMSizingType(i, - XGINew_DDRDRAM_TYPE340, - pVBInfo); - memsize = XGINew_SetDRAMSize20Reg(i, - XGINew_DDRDRAM_TYPE340, - pVBInfo); - - if (memsize == 0) - continue; - - addr = memsize + (pVBInfo->ram_channel - 2) + 20; - if ((HwDeviceExtension->ulVideoMemorySize - 1) < - (unsigned long) (1 << addr)) - continue; - - if (XGINew_ReadWriteRest(addr, 9, pVBInfo) == 1) - return 1; - } + dram_table = XGINew_DDRDRAM_TYPE340; + size = ARRAY_SIZE(XGINew_DDRDRAM_TYPE340); + start_addr = 9; + } + + for (i = 0; i < size; i++) { + XGINew_SetDRAMSizingType(i, dram_table, pVBInfo); + memsize = XGINew_SetDRAMSize20Reg(i, dram_table, pVBInfo); + + if (memsize == 0) + continue; + + memsize += (pVBInfo->ram_channel - 2) + 20; + if ((HwDeviceExtension->ulVideoMemorySize - 1) < + (unsigned long) (1 << memsize)) + continue; + + if (XGINew_ReadWriteRest(memsize, start_addr, pVBInfo) == 1) + return 1; } return 0; } -- GitLab From 4e55d0b3ee13bb21dc0f74217675e86486004b8b Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:45 +0200 Subject: [PATCH 0687/5711] staging/xgifb: Inline XGINew_SetDRAMSizingType Since the function XGINew_SetDRAMSizingType is only called from one location and consist only of 2 valuable lines we can simply inline it here. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 512284c3de91..63011af0d347 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -579,17 +579,6 @@ static void XGINew_SetDRAMDefaultRegister340( pVBInfo->SR15[3][pVBInfo->ram_type]); /* SR1B */ } -static void XGINew_SetDRAMSizingType(int index, - const unsigned short DRAMTYPE_TABLE[][5], - struct vb_device_info *pVBInfo) -{ - unsigned short data; - - data = DRAMTYPE_TABLE[index][4]; - xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, data); - udelay(15); - /* should delay 50 ns */ -} static unsigned short XGINew_SetDRAMSize20Reg(int index, const unsigned short DRAMTYPE_TABLE[][5], @@ -912,7 +901,10 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, } for (i = 0; i < size; i++) { - XGINew_SetDRAMSizingType(i, dram_table, pVBInfo); + /* SetDRAMSizingType */ + xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, dram_table[i][4]); + udelay(15); /* should delay 50 ns */ + memsize = XGINew_SetDRAMSize20Reg(i, dram_table, pVBInfo); if (memsize == 0) -- GitLab From d6461e49c09a1a7f203437c084ec169563bcbf68 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:46 +0200 Subject: [PATCH 0688/5711] staging/xgifb: Remove unnecessary fields of XGINew_DDRDRAM_TYPE{340, 20} Since the first three entries in XGINew_DDRDRAM_TYPE{340,20} are never used, we can simply remove them; and instead of passing XGINew_DDRDRAM_TYPE with an index we can simply pass the value directly to XGINew_SetDRAMSize20Reg. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 63011af0d347..944653dcf1ea 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -6,25 +6,25 @@ #include "vb_util.h" #include "vb_setmode.h" -static const unsigned short XGINew_DDRDRAM_TYPE340[4][5] = { - { 2, 13, 9, 16, 0x45}, - { 2, 12, 9, 8, 0x35}, - { 2, 12, 8, 4, 0x31}, - { 2, 11, 8, 2, 0x21} }; - -static const unsigned short XGINew_DDRDRAM_TYPE20[12][5] = { - { 2, 14, 11, 128, 0x5D}, - { 2, 14, 10, 64, 0x59}, - { 2, 13, 11, 64, 0x4D}, - { 2, 14, 9, 32, 0x55}, - { 2, 13, 10, 32, 0x49}, - { 2, 12, 11, 32, 0x3D}, - { 2, 14, 8, 16, 0x51}, - { 2, 13, 9, 16, 0x45}, - { 2, 12, 10, 16, 0x39}, - { 2, 13, 8, 8, 0x41}, - { 2, 12, 9, 8, 0x35}, - { 2, 12, 8, 4, 0x31} }; +static const unsigned short XGINew_DDRDRAM_TYPE340[4][2] = { + { 16, 0x45}, + { 8, 0x35}, + { 4, 0x31}, + { 2, 0x21} }; + +static const unsigned short XGINew_DDRDRAM_TYPE20[12][2] = { + { 128, 0x5D}, + { 64, 0x59}, + { 64, 0x4D}, + { 32, 0x55}, + { 32, 0x49}, + { 32, 0x3D}, + { 16, 0x51}, + { 16, 0x45}, + { 16, 0x39}, + { 8, 0x41}, + { 8, 0x35}, + { 4, 0x31} }; #define XGIFB_ROM_SIZE 65536 @@ -580,15 +580,15 @@ static void XGINew_SetDRAMDefaultRegister340( } -static unsigned short XGINew_SetDRAMSize20Reg(int index, - const unsigned short DRAMTYPE_TABLE[][5], +static unsigned short XGINew_SetDRAMSize20Reg( + unsigned short dram_size, struct vb_device_info *pVBInfo) { unsigned short data = 0, memsize = 0; int RankSize; unsigned char ChannelNo; - RankSize = DRAMTYPE_TABLE[index][3] * pVBInfo->ram_bus / 8; + RankSize = dram_size * pVBInfo->ram_bus / 8; data = xgifb_reg_get(pVBInfo->P3c4, 0x13); data &= 0x80; @@ -884,7 +884,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, { u8 i, size; unsigned short memsize, start_addr; - const unsigned short (*dram_table)[5]; + const unsigned short (*dram_table)[2]; xgifb_reg_set(pVBInfo->P3c4, 0x15, 0x00); /* noninterleaving */ xgifb_reg_set(pVBInfo->P3c4, 0x1C, 0x00); /* nontiling */ @@ -902,10 +902,10 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, for (i = 0; i < size; i++) { /* SetDRAMSizingType */ - xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, dram_table[i][4]); + xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, dram_table[i][1]); udelay(15); /* should delay 50 ns */ - memsize = XGINew_SetDRAMSize20Reg(i, dram_table, pVBInfo); + memsize = XGINew_SetDRAMSize20Reg(dram_table[i][0], pVBInfo); if (memsize == 0) continue; -- GitLab From f477d3e6bb1bef4f3e2286d762137ae7e8a53195 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:47 +0200 Subject: [PATCH 0689/5711] staging/xgifb: Replace constant arrays with constant values This patch removes the arrays in XGI_GetVCLK2Ptr which each contain only one value four times and replaces them with their constant value. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index ad1e23d3c938..47d60c8a848c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1010,24 +1010,6 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { - unsigned short LCDXlat1VCLK[4] = { VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2 }; - unsigned short LCDXlat2VCLK[4] = { VCLK108_2_315 + 5, - VCLK108_2_315 + 5, - VCLK108_2_315 + 5, - VCLK108_2_315 + 5 }; - unsigned short LVDSXlat1VCLK[4] = { VCLK40, VCLK40, VCLK40, VCLK40 }; - unsigned short LVDSXlat2VCLK[4] = { VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2 }; - unsigned short LVDSXlat3VCLK[4] = { VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2, - VCLK65_315 + 2 }; - unsigned short CRT2Index, VCLKIndex; unsigned short modeflag, resinfo; @@ -1040,9 +1022,9 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, CRT2Index = CRT2Index >> 6; /* for LCD */ if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /*301b*/ if (pVBInfo->LCDResInfo != Panel_1024x768) - VCLKIndex = LCDXlat2VCLK[CRT2Index]; + VCLKIndex = VCLK108_2_315 + 5; /* LCDXlat2VCLK */ else - VCLKIndex = LCDXlat1VCLK[CRT2Index]; + VCLKIndex = VCLK65_315 + 2; /* LCDXlat1VCLK */ } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->SetFlag & RPLLDIV2XO) { VCLKIndex = TVCLKBASE_315 + HiTVVCLKDIV2; @@ -1093,12 +1075,12 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = VCLKIndex >> 6; if ((pVBInfo->LCDResInfo == Panel_800x600) || (pVBInfo->LCDResInfo == Panel_320x480)) - VCLKIndex = LVDSXlat1VCLK[VCLKIndex]; + VCLKIndex = VCLK40; /* LVDSXlat1VCLK */ else if ((pVBInfo->LCDResInfo == Panel_1024x768) || (pVBInfo->LCDResInfo == Panel_1024x768x75)) - VCLKIndex = LVDSXlat2VCLK[VCLKIndex]; + VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK */ else - VCLKIndex = LVDSXlat3VCLK[VCLKIndex]; + VCLKIndex = VCLK65_315 + 2; /* LVDSXlat3VCLK */ } return VCLKIndex; -- GitLab From 950725920af27251b4c3b253017572c664f2300a Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:48 +0200 Subject: [PATCH 0690/5711] staging/xgifb: Simplyfy XGI_GetVCLK2Ptr a bit This patch simplyfies the XGI_GetVCLK2Ptr a bit by moving the +=25 to a define and removing statements without effect. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 47d60c8a848c..3b9a0f724f26 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -7,6 +7,7 @@ #define IndexMask 0xff +#define TVCLKBASE_315_25 (TVCLKBASE_315 + 25) static const unsigned short XGINew_VGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, @@ -1027,20 +1028,16 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = VCLK65_315 + 2; /* LCDXlat1VCLK */ } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->SetFlag & RPLLDIV2XO) { - VCLKIndex = TVCLKBASE_315 + HiTVVCLKDIV2; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + HiTVVCLKDIV2; } else { - VCLKIndex = TVCLKBASE_315 + HiTVVCLK; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + HiTVVCLK; } if (pVBInfo->SetFlag & TVSimuMode) { if (modeflag & Charx8Dot) { - VCLKIndex = TVCLKBASE_315 + HiTVSimuVCLK; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + HiTVSimuVCLK; } else { - VCLKIndex = TVCLKBASE_315 + HiTVTextVCLK; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + HiTVTextVCLK; } } @@ -1058,11 +1055,9 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, } } else if (pVBInfo->VBInfo & SetCRT2ToTV) { if (pVBInfo->SetFlag & RPLLDIV2XO) { - VCLKIndex = TVCLKBASE_315 + TVVCLKDIV2; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + TVVCLKDIV2; } else { - VCLKIndex = TVCLKBASE_315 + TVVCLK; - VCLKIndex += 25; + VCLKIndex = TVCLKBASE_315_25 + TVVCLK; } } else { /* for CRT2 */ /* di+Ext_CRTVCLK */ @@ -1071,16 +1066,11 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex &= IndexMask; } } else { /* LVDS */ - VCLKIndex = CRT2Index; - VCLKIndex = VCLKIndex >> 6; if ((pVBInfo->LCDResInfo == Panel_800x600) || (pVBInfo->LCDResInfo == Panel_320x480)) VCLKIndex = VCLK40; /* LVDSXlat1VCLK */ - else if ((pVBInfo->LCDResInfo == Panel_1024x768) || - (pVBInfo->LCDResInfo == Panel_1024x768x75)) - VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK */ else - VCLKIndex = VCLK65_315 + 2; /* LVDSXlat3VCLK */ + VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK, LVDSXlat3VCLK */ } return VCLKIndex; -- GitLab From 64e2498b6cd47eb64b1ced4ab173b6c5ecc4025e Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:49 +0200 Subject: [PATCH 0691/5711] staging/xgifb: Remove useless function XGI_CloseCRTC Since XGI_CloseCRTC does not perform anything useful we can simply remove it. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 3b9a0f724f26..2ffab4589531 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -6229,17 +6229,6 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, } } -static void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) -{ - unsigned short tempbx; - - tempbx = 0; - - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) - tempbx = 0x08A0; - -} void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) @@ -6831,7 +6820,6 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo); XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/ - XGI_CloseCRTC(HwDeviceExtension, pVBInfo); XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo); } /* !XG20 */ else { -- GitLab From 03f76fc617fdcf0f9cde4d56c5d7c6d9d33acbc1 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:50 +0200 Subject: [PATCH 0692/5711] staging/xgifb: Replace delay lookup tables with constant values For TV Devices: The values taken from XGI_TVDelayList are always overwritten with the values from XGI_TVDelayList2 since the if condition for using the values from XGI_TVDelayList2 is identical with the check to enter this scope and thus always true. The delay values in XGI_TVDelayList2 is always 0x22 so we can simply replace it with this constant value. For LCD Devices: The LCD_DelayCompensation field is always set to 0x12 so we can simply replace this field with a constant value. This saves about 500 bytes in compiled size. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 25 ++----------- drivers/staging/xgifb/vb_struct.h | 3 -- drivers/staging/xgifb/vb_table.h | 60 ++++++++---------------------- 3 files changed, 19 insertions(+), 69 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 2ffab4589531..c6c6843ef4de 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -105,9 +105,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) else pVBInfo->LCDCapList = XGI_LCDCapList; - pVBInfo->XGI_TVDelayList = XGI301TVDelayList; - pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2; - pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition; if (ChipType >= XG20) @@ -5712,32 +5709,19 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) { - unsigned short index; - unsigned char tempah, tempbl, tempbh; if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC)) { - tempbl = 0; tempbh = 0; - - index = XGI_GetTVPtrIndex(pVBInfo); /* Get TV Delay */ - tempbl = pVBInfo->XGI_TVDelayList[index]; - - if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B - | VB_SIS301LV | VB_SIS302LV - | VB_XGI301C)) - tempbl = pVBInfo->XGI_TVDelayList2[index]; + tempbl = XGI301TVDelay; if (pVBInfo->VBInfo & SetCRT2ToDualEdge) tempbl = tempbl >> 4; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - /* Get LCD Delay */ - index = XGI_GetLCDCapPtr(pVBInfo); - tempbh = pVBInfo->LCDCapList[index]. - LCD_DelayCompensation; + tempbh = XGI301LCDDelay; if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) tempbl = tempbh; @@ -5763,10 +5747,7 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) tempbl = 0; tempbh = 0; if (pVBInfo->VBInfo & SetCRT2ToLCD) { - /* / Get LCD Delay */ - tempah = pVBInfo->LCDCapList[ - XGI_GetLCDCapPtr(pVBInfo)]. - LCD_DelayCompensation; + tempah = XGI301LCDDelay; tempah &= 0x0f; tempah = tempah << 4; xgifb_reg_and_or(pVBInfo->Part1Port, 0x2D, 0x0f, diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index 38f47ffc69c4..b95497132b7b 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -126,7 +126,6 @@ struct XGI330_LCDCapStruct { unsigned char LCD_ID; unsigned short LCD_Capability; unsigned char LCD_SetFlag; - unsigned char LCD_DelayCompensation; unsigned char LCD_HSyncWidth; unsigned char LCD_VSyncWidth; unsigned char LCD_VCLK; @@ -262,8 +261,6 @@ struct vb_device_info { struct SiS_MCLKData *MCLKData; struct XGI_ECLKDataStruct *ECLKData; - unsigned char *XGI_TVDelayList; - unsigned char *XGI_TVDelayList2; unsigned char *NTSCTiming; unsigned char *PALTiming; unsigned char *HiTVExtTiming; diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 9a17113849ec..50ef885adf62 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1993,70 +1993,70 @@ static unsigned short LCDLenList[] = { /* Dual link only */ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { /* LCDCap1024x768 */ - {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, + {Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ {Panel_1280x1024, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2_315, + 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ {Panel_1400x1050, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2_315, + 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ {Panel_1600x1200, XGI_LCDDualLink+DefaultLCDCap, LCDToFull, - 0x012, 0xC0, 0x03, VCLK162, + 0xC0, 0x03, VCLK162, 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1024x768x75 */ - {Panel_1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + {Panel_1024x768x75, DefaultLCDCap, 0, 0x60, 0, VCLK78_75, 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024x75 */ {Panel_1280x1024x75, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, - 0x012, 0x90, 0x03, VCLK135_5, + 0x90, 0x03, VCLK135_5, 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCapDefault */ - {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, + {0xFF, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} }; static struct XGI330_LCDCapStruct XGI_LCDCapList[] = { /* LCDCap1024x768 */ - {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, + {Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ {Panel_1280x1024, DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2_315, + 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ {Panel_1400x1050, DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2_315, + 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ {Panel_1600x1200, DefaultLCDCap, LCDToFull, - 0x012, 0xC0, 0x03, VCLK162, + 0xC0, 0x03, VCLK162, 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1024x768x75 */ - {Panel_1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + {Panel_1024x768x75, DefaultLCDCap, 0, 0x60, 0, VCLK78_75, 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024x75 */ {Panel_1280x1024x75, DefaultLCDCap, StLCDBToA, - 0x012, 0x90, 0x03, VCLK135_5, + 0x90, 0x03, VCLK135_5, 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCapDefault */ - {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, + {0xFF, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} }; @@ -2482,36 +2482,8 @@ static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = { {0xFF, 0x00, 0} /* End mark */ }; -static unsigned char XGI301TVDelayList[] = { - 0x22, /* ; 0 ExtNTSCDelay */ - 0x22, /* ; 1 StNTSCDelay */ - 0x22, /* ; 2 ExtPALDelay */ - 0x22, /* ; 3 StPALDelay */ - 0x88, /* ; 4 ExtHiTVDelay(1080i) */ - 0xBB, /* ; 5 StHiTVDelay(1080i) */ - 0x22, /* ; 6 ExtYPbPrDelay(525i) */ - 0x22, /* ; 7 StYPbPrDealy(525i) */ - 0x22, /* ; 8 ExtYPbPrDelay(525p) */ - 0x22, /* ; 9 StYPbPrDealy(525p) */ - 0x22, /* ; A ExtYPbPrDelay(750p) */ - 0x22 /* B StYPbPrDealy(750p) */ -}; - -static unsigned char XGI301TVDelayList2[] = { - 0x22, /* ; 0 ExtNTSCDelay */ - 0x22, /* ; 1 StNTSCDelay */ - 0x22, /* ; 2 ExtPALDelay */ - 0x22, /* ; 3 StPALDelay */ - 0x22, /* ; 4 ExtHiTVDelay */ - 0x22, /* ; 5 StHiTVDelay */ - 0x22, /* ; 6 ExtYPbPrDelay(525i) */ - 0x22, /* ; 7 StYPbPrDealy(525i) */ - 0x22, /* ; 8 ExtYPbPrDelay(525p) */ - 0x22, /* ; 9 StYPbPrDealy(525p) */ - 0x22, /* ; A ExtYPbPrDelay(750p) */ - 0x22 /* ; B StYPbPrDealy(750p) */ -}; - +#define XGI301TVDelay 0x22 +#define XGI301LCDDelay 0x12 static unsigned char TVAntiFlickList[] = {/* NTSCAntiFlicker */ 0x04, /* ; 0 Adaptive */ -- GitLab From 51f984bc068c8704221a8eddd96b580eafcd2912 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:51 +0200 Subject: [PATCH 0693/5711] staging/xgifb: Use SiS structs This patch replaces some of the XGI internal structs by their counterparts in the SiS driver. XGI330_LVDSDataStruct -> SiS_LVDSData XGI330_LCDDataStruct -> SiS_LCDData XGI330_CHTVDataStruct -> SiS_LVDSData Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 4 +- drivers/staging/xgifb/vb_struct.h | 28 --------- drivers/staging/xgifb/vb_table.h | 96 +++++++++++++++--------------- 3 files changed, 50 insertions(+), 78 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index c6c6843ef4de..183afe4bc24c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1980,12 +1980,12 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short tempbx; - struct XGI330_LVDSDataStruct *LCDPtr = NULL; + struct SiS_LVDSData *LCDPtr = NULL; tempbx = 2; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = (struct XGI330_LVDSDataStruct *) XGI_GetLcdPtr(tempbx, + LCDPtr = (struct SiS_LVDSData *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); pVBInfo->VGAHT = LCDPtr->VGAHT; diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index b95497132b7b..b54488b621e6 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -51,13 +51,6 @@ struct XGI_LCDDataTablStruct { unsigned short DATAPTR; }; -struct XGI330_LVDSDataStruct { - unsigned short VGAHT; - unsigned short VGAVT; - unsigned short LCDHT; - unsigned short LCDVT; -}; - struct XGI330_LCDDataDesStruct2 { unsigned short LCDHDES; unsigned short LCDHRS; @@ -67,15 +60,6 @@ struct XGI330_LCDDataDesStruct2 { unsigned short LCDVSync; }; -struct XGI330_LCDDataStruct { - unsigned short RVBHCMAX; - unsigned short RVBHCFACT; - unsigned short VGAHT; - unsigned short VGAVT; - unsigned short LCDHT; - unsigned short LCDVT; -}; - struct XGI330_TVDataStruct { unsigned short RVBHCMAX; @@ -103,13 +87,6 @@ struct XGI330_TVDataTablStruct { }; -struct XGI330_CHTVDataStruct { - unsigned short VGAHT; - unsigned short VGAVT; - unsigned short LCDHT; - unsigned short LCDVT; -}; - struct XGI_TimingHStruct { unsigned char data[8]; }; @@ -173,11 +150,6 @@ struct XGI_CRT1TableStruct { }; -struct XGI330_VCLKDataStruct { - unsigned char SR2B, SR2C; - unsigned short CLOCK; -}; - struct XGI301C_Tap4TimingStruct { unsigned short DE; unsigned char Reg[64]; /* C0-FF */ diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 50ef885adf62..16bb831a711f 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -420,7 +420,7 @@ static unsigned char XGI_CH7017LV1400x1050[] = { 0xAD, 0xDB, 0xF6, 0xAC, 0xE0, 0x02}; /*add for new UNIVGABIOS*/ -static struct XGI330_LCDDataStruct XGI_StLCD1024x768Data[] = { +static struct SiS_LCDData XGI_StLCD1024x768Data[] = { {62, 25, 800, 546, 1344, 806}, {32, 15, 930, 546, 1344, 806}, {62, 25, 800, 546, 1344, 806}, /*chiawenfordot9->dot8*/ @@ -430,7 +430,7 @@ static struct XGI330_LCDDataStruct XGI_StLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806} }; -static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[] = { +static struct SiS_LCDData XGI_ExtLCD1024x768Data[] = { /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */ {42, 25, 1536, 419, 1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */ @@ -450,7 +450,7 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806} }; -static struct XGI330_LCDDataStruct XGI_CetLCD1024x768Data[] = { +static struct SiS_LCDData XGI_CetLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 1344, 806, 1344, 806}, /* 01 (320x350,640x350) */ @@ -461,7 +461,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806} /* 06 (1024x768x60Hz) */ }; -static struct XGI330_LCDDataStruct XGI_StLCD1280x1024Data[] = { +static struct SiS_LCDData XGI_StLCD1280x1024Data[] = { {22, 5, 800, 510, 1650, 1088}, {22, 5, 800, 510, 1650, 1088}, {176, 45, 900, 510, 1650, 1088}, @@ -472,7 +472,7 @@ static struct XGI330_LCDDataStruct XGI_StLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066} }; -static struct XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[] = { +static struct SiS_LCDData XGI_ExtLCD1280x1024Data[] = { {211, 60, 1024, 501, 1688, 1066}, {211, 60, 1024, 508, 1688, 1066}, {211, 60, 1024, 501, 1688, 1066}, @@ -483,7 +483,7 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066} }; -static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[] = { +static struct SiS_LCDData XGI_CetLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */ @@ -496,7 +496,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */ }; -static struct XGI330_LCDDataStruct xgifb_lcd_1400x1050[] = { +static struct SiS_LCDData xgifb_lcd_1400x1050[] = { {211, 100, 2100, 408, 1688, 1066}, /* 00 (320x200,320x400, 640x200,640x400) */ {211, 64, 1536, 358, 1688, 1066}, /* 01 (320x350,640x350) */ @@ -510,7 +510,7 @@ static struct XGI330_LCDDataStruct xgifb_lcd_1400x1050[] = { {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */ }; -static struct XGI330_LCDDataStruct XGI_ExtLCD1600x1200Data[] = { +static struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = { {4, 1, 1620, 420, 2160, 1250}, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400, // 640x200,640x400) @@ -528,7 +528,7 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1600x1200Data[] = { {1, 1, 2160, 1250, 2160, 1250} /* 09 (1600x1200x60Hz) ;302lv */ }; -static struct XGI330_LCDDataStruct XGI_StLCD1600x1200Data[] = { +static struct SiS_LCDData XGI_StLCD1600x1200Data[] = { {27, 4, 800, 500, 2160, 1250}, /* 00 (320x200,320x400, 640x200,640x400) */ {27, 4, 800, 500, 2160, 1250}, /* 01 (320x350,640x350) */ @@ -542,7 +542,7 @@ static struct XGI330_LCDDataStruct XGI_StLCD1600x1200Data[] = { {1, 1, 2160, 1250, 2160, 1250} /* 09 (1600x1200) */ }; -static struct XGI330_LCDDataStruct XGI_CetLCD1400x1050Data[] = { +static struct SiS_LCDData XGI_CetLCD1400x1050Data[] = { {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */ @@ -555,7 +555,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1400x1050Data[] = { {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */ }; -static struct XGI330_LCDDataStruct XGI_NoScalingData[] = { +static struct SiS_LCDData XGI_NoScalingData[] = { {1, 1, 800, 449, 800, 449}, {1, 1, 800, 449, 800, 449}, {1, 1, 900, 449, 900, 449}, @@ -566,7 +566,7 @@ static struct XGI330_LCDDataStruct XGI_NoScalingData[] = { {1, 1, 1688, 1066, 1688, 1066} }; -static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[] = { +static struct SiS_LCDData XGI_ExtLCD1024x768x75Data[] = { {42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400, 640x200,640x400) */ {48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */ @@ -577,7 +577,7 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */ }; -static struct XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[] = { +static struct SiS_LCDData XGI_CetLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */ @@ -588,7 +588,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */ }; -static struct XGI330_LCDDataStruct xgifb_lcd_1280x1024x75[] = { +static struct SiS_LCDData xgifb_lcd_1280x1024x75[] = { {211, 60, 1024, 501, 1688, 1066}, /* ; 00 (320x200,320x400, 640x200,640x400) */ {211, 60, 1024, 508, 1688, 1066}, /* ; 01 (320x350,640x350) */ @@ -600,7 +600,7 @@ static struct XGI330_LCDDataStruct xgifb_lcd_1280x1024x75[] = { {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */ }; -static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024x75Data[] = { +static struct SiS_LCDData XGI_CetLCD1280x1024x75Data[] = { {1, 1, 1688, 1066, 1688, 1066}, /* ; 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 1688, 1066, 1688, 1066}, /* ; 01 (320x350,640x350) */ @@ -612,7 +612,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024x75Data[] = { {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */ }; -static struct XGI330_LCDDataStruct XGI_NoScalingDatax75[] = { +static struct SiS_LCDData XGI_NoScalingDatax75[] = { {1, 1, 800, 449, 800, 449}, /* ; 00 (320x200, 320x400, 640x200, 640x400) */ {1, 1, 800, 449, 800, 449}, /* ; 01 (320x350, 640x350) */ @@ -1222,7 +1222,7 @@ static unsigned char XGI330_Ren750pGroup3[] = { 0x18, 0x1D, 0x23, 0x28, 0x4C, 0xAA, 0x01 }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Data_1[] = { { 960, 438, 1344, 806}, /* 00 (320x200,320x400,640x200,640x400) */ { 960, 388, 1344, 806}, /* 01 (320x350,640x350) */ {1040, 438, 1344, 806}, /* 02 (360x400,720x400) */ @@ -1233,7 +1233,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[] = { }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Data_2[] = { {1344, 806, 1344, 806}, {1344, 806, 1344, 806}, {1344, 806, 1344, 806}, @@ -1245,7 +1245,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2[] = { {800, 525, 1280, 813} }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Data_1[] = { {1048, 442, 1688, 1066}, {1048, 392, 1688, 1066}, {1048, 442, 1688, 1066}, @@ -1256,7 +1256,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1[] = { {1688, 1066, 1688, 1066} }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Data_2[] = { {1344, 806, 1344, 806}, {1344, 806, 1344, 806}, {1344, 806, 1344, 806}, @@ -1268,7 +1268,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[] = { {800, 525, 1280, 813} }; -static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[] = { +static struct SiS_LVDSData XGI_LVDS1400x1050Data_1[] = { {928, 416, 1688, 1066}, {928, 366, 1688, 1066}, {928, 416, 1688, 1066}, @@ -1280,7 +1280,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[] = { {1688, 1066, 1688, 1066} }; -static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_2[] = { +static struct SiS_LVDSData XGI_LVDS1400x1050Data_2[] = { {1688, 1066, 1688, 1066}, {1688, 1066, 1688, 1066}, {1688, 1066, 1688, 1066}, @@ -1293,7 +1293,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_2[] = { }; /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */ -static struct XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[] = { +static struct SiS_LVDSData XGI_LVDS1600x1200Data_1[] = { {1088, 520, 2048, 1320}, /* 00 (320x200,320x400,640x200,640x400) */ {1088, 470, 2048, 1320}, /* 01 (320x350,640x350) */ {1088, 520, 2048, 1320}, /* 02 (360x400,720x400) */ @@ -1306,7 +1306,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[] = { {2048, 1320, 2048, 1320} /* 09 (1600x1200) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDSNoScalingData[] = { +static struct SiS_LVDSData XGI_LVDSNoScalingData[] = { { 800, 449, 800, 449}, /* 00 (320x200,320x400,640x200,640x400) */ { 800, 449, 800, 449}, /* 01 (320x350,640x350) */ { 800, 449, 800, 449}, /* 02 (360x400,720x400) */ @@ -1320,7 +1320,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDSNoScalingData[] = { {1688, 806, 1688, 806} /* 0A (1280x768x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Data_1x75[] = { { 960, 438, 1312, 800}, /* 00 (320x200,320x400,640x200,640x400) */ { 960, 388, 1312, 800}, /* 01 (320x350,640x350) */ {1040, 438, 1312, 800}, /* 02 (360x400,720x400) */ @@ -1331,7 +1331,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[] = { }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Data_2x75[] = { {1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,640x200,640x400) */ {1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */ {1312, 800, 1312, 800}, /* ; 02 (360x400,720x400) */ @@ -1341,7 +1341,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[] = { {1312, 800, 1312, 800}, /* ; 06 (512x384,1024x768) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Data_1x75[] = { {1048, 442, 1688, 1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ {1048, 392, 1688, 1066 }, /* ; 01 (320x350,640x350) */ {1128, 442, 1688, 1066 }, /* ; 02 (360x400,720x400) */ @@ -1352,7 +1352,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[] = { {1688, 1066, 1688, 1066 }, /* ; 06; 07 (640x512,1280x1024) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Data_2x75[] = { {1688, 1066, 1688, 1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ {1688, 1066, 1688, 1066 }, /* ; 01 (320x350,640x350) */ {1688, 1066, 1688, 1066 }, /* ; 02 (360x400,720x400) */ @@ -1363,7 +1363,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[] = { {1688, 1066, 1688, 1066 }, /* ; 06; 07 (640x512,1280x1024) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[] = { +static struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = { { 800, 449, 800, 449}, /* ; 00 (320x200,320x400,640x200,640x400) */ { 800, 449, 800, 449}, /* ; 01 (320x350,640x350) */ { 900, 449, 900, 449}, /* ; 02 (360x400,720x400) */ @@ -1378,7 +1378,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[] = { {1688, 806, 1688, 806}, /* ; 0A (1280x768x75Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = { {0, 1048, 0, 771}, /* 00 (320x200,320x400,640x200,640x400) */ {0, 1048, 0, 771}, /* 01 (320x350,640x350) */ {0, 1048, 0, 771}, /* 02 (360x400,720x400) */ @@ -1388,7 +1388,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[] = { {0, 1048, 805, 770} /* 06 (1024x768x60Hz) */ } ; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = { {1142, 856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */ {1142, 856, 597, 562}, /* 01 (320x350,640x350) */ {1142, 856, 622, 587}, /* 02 (360x400,720x400) */ @@ -1398,7 +1398,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[] = { { 0, 1048, 805, 771} /* 06 (1024x768x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_3[] = { {320, 24, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */ {320, 24, 597, 562}, /* 01 (320x350,640x350) */ {320, 24, 622, 587}, /* 02 (360x400,720x400) */ @@ -1406,7 +1406,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[] = { {320, 24, 722, 687} /* 04 (640x480x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Des_1[] = { {0, 1328, 0, 1025}, /* 00 (320x200,320x400,640x200,640x400) */ {0, 1328, 0, 1025}, /* 01 (320x350,640x350) */ {0, 1328, 0, 1025}, /* 02 (360x400,720x400) */ @@ -1418,7 +1418,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[] = { }; /* The Display setting for DE Mode Panel */ -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Des_2[] = { {1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */ {1368, 1008, 729, 688}, /* 01 (320x350,640x350) */ {1408, 1048, 752, 711}, /* 02 (360x400,720x400) */ @@ -1429,7 +1429,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[] = { {0000, 1328, 0, 1025} /* 07 (1280x1024x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[] = { +static struct SiS_LVDSData XGI_LVDS1400x1050Des_1[] = { {0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */ {0, 1448, 0, 1051}, /* 01 (320x350,640x350) */ {0, 1448, 0, 1051}, /* 02 (360x400,720x400) */ @@ -1441,7 +1441,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[] = { {0, 1448, 0, 1051} /* 08 (1400x1050x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[] = { +static struct SiS_LVDSData XGI_LVDS1400x1050Des_2[] = { {1308, 1068, 781, 766}, /* 00 (320x200,320x400,640x200,640x400) */ {1308, 1068, 781, 766}, /* 01 (320x350,640x350) */ {1308, 1068, 781, 766}, /* 02 (360x400,720x400) */ @@ -1453,7 +1453,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[] = { { 0, 1448, 0, 1051} /* 08 (1400x1050x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[] = { +static struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = { {0, 1664, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */ {0, 1664, 0, 1201}, /* 01 (320x350,640x350) */ {0, 1664, 0, 1201}, /* 02 (360x400,720x400) */ @@ -1483,7 +1483,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[] = { }; /* ; 1024x768 Full-screen */ -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_1x75[] = { {0, 1040, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */ {0, 1040, 0, 769}, /* ; 01 (320x350,640x350) */ {0, 1040, 0, 769}, /* ; 02 (360x400,720x400) */ @@ -1494,7 +1494,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[] = { }; /* ; 1024x768 center-screen (Enh. Mode) */ -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_2x75[] = { {1142, 856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */ {1142, 856, 597, 562}, /* 01 (320x350,640x350) */ {1142, 856, 622, 587}, /* 02 (360x400,720x400) */ @@ -1505,7 +1505,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[] = { }; /* ; 1024x768 center-screen (St.Mode) */ -static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[] = { +static struct SiS_LVDSData XGI_LVDS1024x768Des_3x75[] = { {320, 24, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */ {320, 24, 597, 562}, /* ; 01 (320x350,640x350) */ {320, 24, 622, 587}, /* ; 02 (360x400,720x400) */ @@ -1513,7 +1513,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[] = { {320, 24, 722, 687} /* ; 04 (640x480x60Hz) */ }; -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = { {0, 1296, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */ {0, 1296, 0, 1025}, /* ; 01 (320x350,640x350) */ {0, 1296, 0, 1025}, /* ; 02 (360x400,720x400) */ @@ -1526,7 +1526,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[] = { /* The Display setting for DE Mode Panel */ /* [ycchen] 02/18/03 Set DE as default */ -static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[] = { +static struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = { {1368, 976, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */ {1368, 976, 729, 688}, /* ; 01 (320x350,640x350) */ {1408, 976, 752, 711}, /* ; 02 (360x400,720x400) */ @@ -1554,7 +1554,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = { {0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */ }; -static struct XGI330_CHTVDataStruct XGI_CHTVUNTSCData[] = { +static struct SiS_LVDSData XGI_CHTVUNTSCData[] = { { 840, 600, 840, 600}, { 840, 600, 840, 600}, { 840, 600, 840, 600}, @@ -1563,7 +1563,7 @@ static struct XGI330_CHTVDataStruct XGI_CHTVUNTSCData[] = { {1064, 750, 1064, 750} }; -static struct XGI330_CHTVDataStruct XGI_CHTVONTSCData[] = { +static struct SiS_LVDSData XGI_CHTVONTSCData[] = { { 840, 525, 840, 525}, { 840, 525, 840, 525}, { 840, 525, 840, 525}, @@ -1572,7 +1572,7 @@ static struct XGI330_CHTVDataStruct XGI_CHTVONTSCData[] = { {1040, 700, 1040, 700} }; -static struct XGI330_CHTVDataStruct XGI_CHTVUPALData[] = { +static struct SiS_LVDSData XGI_CHTVUPALData[] = { {1008, 625, 1008, 625}, {1008, 625, 1008, 625}, {1008, 625, 1008, 625}, @@ -1581,7 +1581,7 @@ static struct XGI330_CHTVDataStruct XGI_CHTVUPALData[] = { { 936, 836, 936, 836} }; -static struct XGI330_CHTVDataStruct XGI_CHTVOPALData[] = { +static struct SiS_LVDSData XGI_CHTVOPALData[] = { {1008, 625, 1008, 625}, {1008, 625, 1008, 625}, {1008, 625, 1008, 625}, @@ -2297,7 +2297,7 @@ static unsigned char XG27_SR41 = 0x00 ; static unsigned char Z11m_CR97 = 0x80 ; -static struct XGI330_VCLKDataStruct XGI_VCLKData[] = { +static struct SiS_VCLKData XGI_VCLKData[] = { /* SR2B,SR2C,SR2D */ {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */ {0x4E, 0xE4, 28}, /* 01 (28.322MHz) */ @@ -2390,7 +2390,7 @@ static struct XGI330_VCLKDataStruct XGI_VCLKData[] = { {0xFF, 0x00, 0} /* End mark */ }; -static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = { +static struct SiS_VCLKData XGI_VBVCLKData[] = { {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */ {0x4E, 0xE4, 28}, /* 01 (28.322MHz) */ {0x57, 0xE4, 31}, /* 02 (31.500MHz) */ -- GitLab From 6d12dae47e8c93da24d54a402a48dab0958083ca Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 14 Jun 2012 00:21:52 +0200 Subject: [PATCH 0694/5711] staging/xgifb: Cleanup vb_device_info struct This patch cleans up the vb_device_info struct and the related functions. The cleanup decreases the size of the compiled module by about 10kB. == Remove fields in vb_device_info that are never read: == pOutputSelect pRGBSenseData pRGBSenseData2 pVideoSenseData pVideoSenseData2 pYCSenseData pYCSenseData2 CR49 pXGINew_I2CDefinition pCR2E pCR2F pCR46 pCR47 pCRD0 pCRDE pSR40 pSR41 pCR47 === Remove the corresponding 'constants' === XGI330_RGBSenseData XGI330_RGBSenseData2 XGI330_VideoSenseData XGI330_VideoSenseData2 XGI330_YCSenseData XGI330_YCSenseData2 XGI330_CR49 XG40_I2CDefinition XG21_CR2E XG21_CR2F XG21_CR46 XG21_CR47 XG27_CRD0 XG27_CRDE XGI330_OutputSelect == Remove 'constant fields' and replace constant value with #define == pSR07 = XGI330_SR07 -> 0x18 pSR1F = XGI330_SR1F -> 0 pSR23 = XGI330_SR23 -> 0xf6 pSR24 = XGI330_SR24 -> 0x0d pSR33 = XGI330_SR33 ->0 pCRT2Data_1_2 = XGI330_CRT2Data_1_2 -> 0 pCRT2Data_4_D = XGI330_CRT2Data_4_D -> 0 pCRT2Data_4_E = XGI330_CRT2Data_4_E -> 0 pCRT2Data_4_10 = XGI330_CRT2Data_4_10 -> 0x80 pSR36 = XG27_SR36 -> 0x30 pCR8F = &XG27_CR8F -> 0x0C pSR40 = XG27_SR40 -> 0x04 pSR41 = XG27_SR41 ->0x00 pSR31 = XGI330_SR31 -> 0xc0 pSR32 = XGI330_SR32 -> 0xc0 SR25 = XGI330_sr25 -> 0 (we only use XGI330_sr25[0]) == Constant fields with 'dead' code: == pSoftSetting is set to XGI330_SoftSetting = 0x30 -> if (*pVBInfo->pSoftSetting & SoftDRAMType) is never true since SoftDRAMType = 0x80 -> if (*pVBInfo->pSoftSetting & ModeSoftSetting) is never true since ModeSoftSetting = 0x04 --> remove the code, remove pSoftSetting, remove XGI330_SoftSetting pDVOSetting is set to XG21_DVOSetting = 0 -> if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) is never true --> remove the code, remove pDVOSetting, remove XG21_DVOSetting pXGINew_DRAMTypeDefinition is set to &XG40_DRAMTypeDefinition 0xFF -> if (*pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C) is always true --> remove the if and remove pXGINew_DRAMTypeDefinition remove XG40_DRAMTypeDefinition == Replace pointer to unsigned char with unsigned char variable and assign value of referenced pointer: == pSR21 -> SR21, remove XGI330_SR21 pSR22 -> SR22, remove XGI330_SR22 pXGINew_CR97 -> XGINew_CR97, remove XG20_CR97, XG27_CR97 and Z11m_CR97 Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_def.h | 19 ++++++ drivers/staging/xgifb/vb_init.c | 96 ++++++++++++------------------ drivers/staging/xgifb/vb_setmode.c | 59 ++---------------- drivers/staging/xgifb/vb_struct.h | 43 ++----------- drivers/staging/xgifb/vb_table.h | 49 --------------- 5 files changed, 67 insertions(+), 199 deletions(-) diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index c7317931f671..5b987a68ee9f 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -264,4 +264,23 @@ #define RES1280x960x85 0x46 #define RES1280x960x120 0x47 + +#define XG27_CR8F 0x0C +#define XG27_SR36 0x30 +#define XG27_SR40 0x04 +#define XG27_SR41 0x00 +#define XG40_CRCF 0x13 +#define XGI330_CRT2Data_1_2 0 +#define XGI330_CRT2Data_4_D 0 +#define XGI330_CRT2Data_4_E 0 +#define XGI330_CRT2Data_4_10 0x80 +#define XGI330_SR07 0x18 +#define XGI330_SR1F 0 +#define XGI330_SR23 0xf6 +#define XGI330_SR24 0x0d +#define XGI330_SR25 0 +#define XGI330_SR31 0xc0 +#define XGI330_SR32 0x11 +#define XGI330_SR33 0 + #endif diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 944653dcf1ea..a3d54b7f23c6 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -5,7 +5,6 @@ #include "vb_def.h" #include "vb_util.h" #include "vb_setmode.h" - static const unsigned short XGINew_DDRDRAM_TYPE340[4][2] = { { 16, 0x45}, { 8, 0x35}, @@ -35,21 +34,12 @@ XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension, unsigned char data, temp; if (HwDeviceExtension->jChipType < XG20) { - if (*pVBInfo->pSoftSetting & SoftDRAMType) { - data = *pVBInfo->pSoftSetting & 0x07; - return data; - } else { - data = xgifb_reg_get(pVBInfo->P3c4, 0x39) & 0x02; - if (data == 0) - data = (xgifb_reg_get(pVBInfo->P3c4, 0x3A) & - 0x02) >> 1; - return data; - } + data = xgifb_reg_get(pVBInfo->P3c4, 0x39) & 0x02; + if (data == 0) + data = (xgifb_reg_get(pVBInfo->P3c4, 0x3A) & + 0x02) >> 1; + return data; } else if (HwDeviceExtension->jChipType == XG27) { - if (*pVBInfo->pSoftSetting & SoftDRAMType) { - data = *pVBInfo->pSoftSetting & 0x07; - return data; - } temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B); /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */ if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08)) @@ -92,13 +82,11 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4, xgifb_reg_set(P3c4, 0x16, 0x00); xgifb_reg_set(P3c4, 0x16, 0x80); - if (*pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C) { /* Samsung F Die */ - mdelay(3); - xgifb_reg_set(P3c4, 0x18, 0x00); - xgifb_reg_set(P3c4, 0x19, 0x20); - xgifb_reg_set(P3c4, 0x16, 0x00); - xgifb_reg_set(P3c4, 0x16, 0x80); - } + mdelay(3); + xgifb_reg_set(P3c4, 0x18, 0x00); + xgifb_reg_set(P3c4, 0x19, 0x20); + xgifb_reg_set(P3c4, 0x16, 0x00); + xgifb_reg_set(P3c4, 0x16, 0x80); udelay(60); xgifb_reg_set(P3c4, @@ -172,7 +160,7 @@ static void XGINew_DDRII_Bootup_XG27( /* Set Double Frequency */ /* xgifb_reg_set(P3d4, 0x97, 0x11); *//* CR97 */ - xgifb_reg_set(P3d4, 0x97, *pVBInfo->pXGINew_CR97); /* CR97 */ + xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */ udelay(200); @@ -532,7 +520,7 @@ static void XGINew_SetDRAMDefaultRegister340( pVBInfo->CR40[0][pVBInfo->ram_type]); /* CR41 */ if (HwDeviceExtension->jChipType == XG27) - xgifb_reg_set(P3d4, 0x8F, *pVBInfo->pCR8F); /* CR8F */ + xgifb_reg_set(P3d4, 0x8F, XG27_CR8F); /* CR8F */ for (j = 0; j <= 6; j++) /* CR90 - CR96 */ xgifb_reg_set(P3d4, (0x90 + j), @@ -555,7 +543,7 @@ static void XGINew_SetDRAMDefaultRegister340( xgifb_reg_set(P3d4, 0x83, 0x09); /* CR83 */ xgifb_reg_set(P3d4, 0x87, 0x00); /* CR87 */ - xgifb_reg_set(P3d4, 0xCF, *pVBInfo->pCRCF); /* CRCF */ + xgifb_reg_set(P3d4, 0xCF, XG40_CRCF); /* CRCF */ if (pVBInfo->ram_type) { /* xgifb_reg_set(P3c4, 0x17, 0xC0); */ /* SR17 DDRII */ xgifb_reg_set(P3c4, 0x17, 0x80); /* SR17 DDRII */ @@ -1075,13 +1063,9 @@ static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, CR3CData = xgifb_reg_get(pVBInfo->P3d4, 0x3c); if (!(CR3CData & DisplayDeviceFromCMOS)) { tempcx = 0x1FF0; - if (*pVBInfo->pSoftSetting & ModeSoftSetting) - tempbx = 0x1FF0; } } else { tempcx = 0x1FF0; - if (*pVBInfo->pSoftSetting & ModeSoftSetting) - tempbx = 0x1FF0; } tempbx &= tempcx; @@ -1425,7 +1409,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) printk("10"); if (HwDeviceExtension->jChipType >= XG20) - xgifb_reg_set(pVBInfo->P3d4, 0x97, *pVBInfo->pXGINew_CR97); + xgifb_reg_set(pVBInfo->P3d4, 0x97, pVBInfo->XGINew_CR97); /* 3.SetMemoryClock @@ -1435,20 +1419,20 @@ unsigned char XGIInitNew(struct pci_dev *pdev) printk("11"); /* 4.SetDefExt1Regs begin */ - xgifb_reg_set(pVBInfo->P3c4, 0x07, *pVBInfo->pSR07); + xgifb_reg_set(pVBInfo->P3c4, 0x07, XGI330_SR07); if (HwDeviceExtension->jChipType == XG27) { - xgifb_reg_set(pVBInfo->P3c4, 0x40, *pVBInfo->pSR40); - xgifb_reg_set(pVBInfo->P3c4, 0x41, *pVBInfo->pSR41); + xgifb_reg_set(pVBInfo->P3c4, 0x40, XG27_SR40); + xgifb_reg_set(pVBInfo->P3c4, 0x41, XG27_SR41); } xgifb_reg_set(pVBInfo->P3c4, 0x11, 0x0F); - xgifb_reg_set(pVBInfo->P3c4, 0x1F, *pVBInfo->pSR1F); + xgifb_reg_set(pVBInfo->P3c4, 0x1F, XGI330_SR1F); /* xgifb_reg_set(pVBInfo->P3c4, 0x20, 0x20); */ /* alan, 2001/6/26 Frame buffer can read/write SR20 */ xgifb_reg_set(pVBInfo->P3c4, 0x20, 0xA0); /* Hsuan, 2006/01/01 H/W request for slow corner chip */ xgifb_reg_set(pVBInfo->P3c4, 0x36, 0x70); if (HwDeviceExtension->jChipType == XG27) /* Alan 12/07/2006 */ - xgifb_reg_set(pVBInfo->P3c4, 0x36, *pVBInfo->pSR36); + xgifb_reg_set(pVBInfo->P3c4, 0x36, XG27_SR36); /* SR11 = 0x0F; */ /* xgifb_reg_set(pVBInfo->P3c4, 0x11, SR11); */ @@ -1534,9 +1518,9 @@ unsigned char XGIInitNew(struct pci_dev *pdev) } /* != XG20 */ /* Set PCI */ - xgifb_reg_set(pVBInfo->P3c4, 0x23, *pVBInfo->pSR23); - xgifb_reg_set(pVBInfo->P3c4, 0x24, *pVBInfo->pSR24); - xgifb_reg_set(pVBInfo->P3c4, 0x25, pVBInfo->SR25[0]); + xgifb_reg_set(pVBInfo->P3c4, 0x23, XGI330_SR23); + xgifb_reg_set(pVBInfo->P3c4, 0x24, XGI330_SR24); + xgifb_reg_set(pVBInfo->P3c4, 0x25, XGI330_SR25); printk("15"); if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ @@ -1550,8 +1534,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) temp = (unsigned char) ((temp1 >> 4) & 0x0F); xgifb_reg_set(pVBInfo->Part1Port, - 0x02, - (*pVBInfo->pCRT2Data_1_2)); + 0x02, XGI330_CRT2Data_1_2); printk("16"); @@ -1565,15 +1548,15 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* Not DDR */ xgifb_reg_set(pVBInfo->P3c4, 0x31, - (*pVBInfo->pSR31 & 0x3F) | 0x40); + (XGI330_SR31 & 0x3F) | 0x40); xgifb_reg_set(pVBInfo->P3c4, 0x32, - (*pVBInfo->pSR32 & 0xFC) | 0x01); + (XGI330_SR32 & 0xFC) | 0x01); } else { - xgifb_reg_set(pVBInfo->P3c4, 0x31, *pVBInfo->pSR31); - xgifb_reg_set(pVBInfo->P3c4, 0x32, *pVBInfo->pSR32); + xgifb_reg_set(pVBInfo->P3c4, 0x31, XGI330_SR31); + xgifb_reg_set(pVBInfo->P3c4, 0x32, XGI330_SR32); } - xgifb_reg_set(pVBInfo->P3c4, 0x33, *pVBInfo->pSR33); + xgifb_reg_set(pVBInfo->P3c4, 0x33, XGI330_SR33); printk("17"); /* @@ -1584,14 +1567,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) if (pVBInfo->IF_DEF_LVDS == 0) { xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C); xgifb_reg_set(pVBInfo->Part4Port, - 0x0D, - *pVBInfo->pCRT2Data_4_D); + 0x0D, XGI330_CRT2Data_4_D); xgifb_reg_set(pVBInfo->Part4Port, - 0x0E, - *pVBInfo->pCRT2Data_4_E); + 0x0E, XGI330_CRT2Data_4_E); xgifb_reg_set(pVBInfo->Part4Port, - 0x10, - *pVBInfo->pCRT2Data_4_10); + 0x10, XGI330_CRT2Data_4_10); xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F); } @@ -1651,12 +1631,12 @@ unsigned char XGIInitNew(struct pci_dev *pdev) AGP = 0; if (AGP == 0) - *pVBInfo->pSR21 &= 0xEF; + pVBInfo->SR21 &= 0xEF; - xgifb_reg_set(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21); + xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21); if (AGP == 1) - *pVBInfo->pSR22 &= 0x20; - xgifb_reg_set(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22); + pVBInfo->SR22 &= 0x20; + xgifb_reg_set(pVBInfo->P3c4, 0x22, pVBInfo->SR22); */ /* base = 0x80000000; */ /* OutPortLong(0xcf8, base); */ @@ -1664,12 +1644,12 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* if (Temp == 0x1039) { */ xgifb_reg_set(pVBInfo->P3c4, 0x22, - (unsigned char) ((*pVBInfo->pSR22) & 0xFE)); + (unsigned char) ((pVBInfo->SR22) & 0xFE)); /* } else { */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22); */ + /* xgifb_reg_set(pVBInfo->P3c4, 0x22, pVBInfo->SR22); */ /* } */ - xgifb_reg_set(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21); + xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21); printk("23"); diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 183afe4bc24c..b1713d389794 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -38,9 +38,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->ModeResInfo = (struct SiS_ModeResInfo_S *) XGI330_ModeResInfo; - pVBInfo->pOutputSelect = &XGI330_OutputSelect; - pVBInfo->pSoftSetting = &XGI330_SoftSetting; - pVBInfo->pSR07 = &XGI330_SR07; pVBInfo->LCDResInfo = 0; pVBInfo->LCDTypeInfo = 0; pVBInfo->LCDInfo = 0; @@ -49,36 +46,15 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->SR15 = XGI340_SR13; pVBInfo->CR40 = XGI340_cr41; - pVBInfo->SR25 = XGI330_sr25; - pVBInfo->pSR31 = &XGI330_sr31; - pVBInfo->pSR32 = &XGI330_sr32; pVBInfo->CR6B = XGI340_CR6B; pVBInfo->CR6E = XGI340_CR6E; pVBInfo->CR6F = XGI340_CR6F; pVBInfo->CR89 = XGI340_CR89; pVBInfo->AGPReg = XGI340_AGPReg; pVBInfo->SR16 = XGI340_SR16; - pVBInfo->pCRCF = &XG40_CRCF; - pVBInfo->pXGINew_DRAMTypeDefinition = &XG40_DRAMTypeDefinition; - - pVBInfo->CR49 = XGI330_CR49; - pVBInfo->pSR1F = &XGI330_SR1F; - pVBInfo->pSR21 = &XGI330_SR21; - pVBInfo->pSR22 = &XGI330_SR22; - pVBInfo->pSR23 = &XGI330_SR23; - pVBInfo->pSR24 = &XGI330_SR24; - pVBInfo->pSR33 = &XGI330_SR33; - - pVBInfo->pCRT2Data_1_2 = &XGI330_CRT2Data_1_2; - pVBInfo->pCRT2Data_4_D = &XGI330_CRT2Data_4_D; - pVBInfo->pCRT2Data_4_E = &XGI330_CRT2Data_4_E; - pVBInfo->pCRT2Data_4_10 = &XGI330_CRT2Data_4_10; - pVBInfo->pRGBSenseData = &XGI330_RGBSenseData; - pVBInfo->pVideoSenseData = &XGI330_VideoSenseData; - pVBInfo->pYCSenseData = &XGI330_YCSenseData; - pVBInfo->pRGBSenseData2 = &XGI330_RGBSenseData2; - pVBInfo->pVideoSenseData2 = &XGI330_VideoSenseData2; - pVBInfo->pYCSenseData2 = &XGI330_YCSenseData2; + + pVBInfo->SR21 = 0xa3; + pVBInfo->SR22 = 0xfb; pVBInfo->NTSCTiming = XGI330_NTSCTiming; pVBInfo->PALTiming = XGI330_PALTiming; @@ -105,38 +81,22 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) else pVBInfo->LCDCapList = XGI_LCDCapList; - pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition; - if (ChipType >= XG20) - pVBInfo->pXGINew_CR97 = &XG20_CR97; + pVBInfo->XGINew_CR97 = 0x10; if (ChipType == XG27) { unsigned char temp; pVBInfo->MCLKData = (struct SiS_MCLKData *) XGI27New_MCLKData; pVBInfo->CR40 = XGI27_cr41; - pVBInfo->pXGINew_CR97 = &XG27_CR97; - pVBInfo->pSR36 = &XG27_SR36; - pVBInfo->pCR8F = &XG27_CR8F; - pVBInfo->pCRD0 = XG27_CRD0; - pVBInfo->pCRDE = XG27_CRDE; - pVBInfo->pSR40 = &XG27_SR40; - pVBInfo->pSR41 = &XG27_SR41; + pVBInfo->XGINew_CR97 = 0xc1; pVBInfo->SR15 = XG27_SR13; /*Z11m DDR*/ temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B); /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */ if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08)) - pVBInfo->pXGINew_CR97 = &Z11m_CR97; - } - - if (ChipType >= XG20) { - pVBInfo->pDVOSetting = &XG21_DVOSetting; - pVBInfo->pCR2E = &XG21_CR2E; - pVBInfo->pCR2F = &XG21_CR2F; - pVBInfo->pCR46 = &XG21_CR46; - pVBInfo->pCR47 = &XG21_CR47; + pVBInfo->XGINew_CR97 = 0x80; } } @@ -783,13 +743,6 @@ static void xgifb_set_lcd(int chip_id, } } - if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) { - xgifb_reg_set(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E); - xgifb_reg_set(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F); - xgifb_reg_set(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46); - xgifb_reg_set(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47); - } - if (chip_id == XG27) { XGI_SetXG27FPBits(pVBInfo); } else { diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index b54488b621e6..aea760ad4ae2 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -191,45 +191,11 @@ struct vb_device_info { unsigned char (*SR15)[8]; unsigned char (*CR40)[8]; - unsigned char *pSoftSetting; - unsigned char *pOutputSelect; - - unsigned short *pRGBSenseData; - unsigned short *pRGBSenseData2; /*301b*/ - unsigned short *pVideoSenseData; - unsigned short *pVideoSenseData2; - unsigned short *pYCSenseData; - unsigned short *pYCSenseData2; - - unsigned char *pSR07; - unsigned char *CR49; - unsigned char *pSR1F; unsigned char *AGPReg; unsigned char *SR16; - unsigned char *pSR21; - unsigned char *pSR22; - unsigned char *pSR23; - unsigned char *pSR24; - unsigned char *SR25; - unsigned char *pSR31; - unsigned char *pSR32; - unsigned char *pSR33; - unsigned char *pSR36; /* alan 12/07/2006 */ - unsigned char *pCRCF; - unsigned char *pCRD0; /* alan 12/07/2006 */ - unsigned char *pCRDE; /* alan 12/07/2006 */ - unsigned char *pCR8F; /* alan 12/07/2006 */ - unsigned char *pSR40; /* alan 12/07/2006 */ - unsigned char *pSR41; /* alan 12/07/2006 */ - unsigned char *pDVOSetting; - unsigned char *pCR2E; - unsigned char *pCR2F; - unsigned char *pCR46; - unsigned char *pCR47; - unsigned char *pCRT2Data_1_2; - unsigned char *pCRT2Data_4_D; - unsigned char *pCRT2Data_4_E; - unsigned char *pCRT2Data_4_10; + unsigned char SR21; + unsigned char SR22; + unsigned char SR25; struct SiS_MCLKData *MCLKData; struct XGI_ECLKDataStruct *ECLKData; @@ -249,8 +215,7 @@ struct vb_device_info { unsigned char *Ren750pGroup3; unsigned char *ScreenOffset; unsigned char *pXGINew_DRAMTypeDefinition; - unsigned char *pXGINew_I2CDefinition ; - unsigned char *pXGINew_CR97 ; + unsigned char XGINew_CR97; struct XGI330_LCDCapStruct *LCDCapList; diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 16bb831a711f..75da7c3e1baf 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -130,13 +130,6 @@ static unsigned char XGI340_AGPReg[12] = { static unsigned char XGI340_SR16[4] = {0x03, 0x83, 0x03, 0x83}; -static unsigned char XGI330_sr25[2]; -static unsigned char XGI330_sr31 = 0xc0; -static unsigned char XGI330_sr32 = 0x11; -static unsigned char XGI330_SR33; -static unsigned char XG40_CRCF = 0x13; -static unsigned char XG40_DRAMTypeDefinition = 0xFF ; - static struct XGI_ExtStruct XGI330_EModeIDTable[] = { {0x2e, 0x0a1b, 0x0306, 0x06, 0x05, 0x06}, {0x2f, 0x0a1b, 0x0305, 0x05, 0x05, 0x05}, @@ -2255,48 +2248,6 @@ static struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = { {1152, 864, 8, 16} }; -static unsigned char XGI330_OutputSelect = 0x40; -static unsigned char XGI330_SoftSetting = 0x30; -static unsigned char XGI330_SR07 = 0x18; - -static unsigned char XGI330_CR49[] = {0xaa, 0x88}; -static unsigned char XGI330_SR1F; -static unsigned char XGI330_SR21 = 0xa3; -static unsigned char XGI330_SR22 = 0xfb; -static unsigned char XGI330_SR23 = 0xf6; -static unsigned char XGI330_SR24 = 0xd; - -static unsigned char XGI330_CRT2Data_1_2; -static unsigned char XGI330_CRT2Data_4_D; -static unsigned char XGI330_CRT2Data_4_E; -static unsigned char XGI330_CRT2Data_4_10 = 0x80; -static unsigned short XGI330_RGBSenseData = 0xd1; -static unsigned short XGI330_VideoSenseData = 0xb9; -static unsigned short XGI330_YCSenseData = 0xb3; -static unsigned short XGI330_RGBSenseData2 = 0x0190; /*301b*/ -static unsigned short XGI330_VideoSenseData2 = 0x0110; -static unsigned short XGI330_YCSenseData2 = 0x016B; -static unsigned char XG40_I2CDefinition; -static unsigned char XG20_CR97 = 0x10 ; - -static unsigned char XG21_DVOSetting; -static unsigned char XG21_CR2E; -static unsigned char XG21_CR2F; -static unsigned char XG21_CR46; -static unsigned char XG21_CR47; - -static unsigned char XG27_CR97 = 0xC1 ; -static unsigned char XG27_SR36 = 0x30 ; -static unsigned char XG27_CR8F = 0x0C ; -static unsigned char XG27_CRD0[] = { - 0, 0, 0, 0, 0, 0, 0, 0x82, 0x00, 0x66, 0x01, 0x00 -}; -static unsigned char XG27_CRDE[2]; -static unsigned char XG27_SR40 = 0x04 ; -static unsigned char XG27_SR41 = 0x00 ; - -static unsigned char Z11m_CR97 = 0x80 ; - static struct SiS_VCLKData XGI_VCLKData[] = { /* SR2B,SR2C,SR2D */ {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */ -- GitLab From 01bd3e3fc9f9fa62c6c86a32c9f60b4501b96b3d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:41:15 -0700 Subject: [PATCH 0695/5711] staging: comedi: 8255: replace printk calls Replace the printk calls with dev_info, dev_warn, etc. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 502bde8c22c1..b608a05bcd1b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -383,8 +383,7 @@ static int dev_8255_attach(struct comedi_device *dev, break; } if (i == 0) { - printk(KERN_WARNING - "comedi%d: 8255: no devices specified\n", dev->minor); + dev_warn(dev->class_dev, "no devices specified\n"); return -EINVAL; } @@ -392,24 +391,21 @@ static int dev_8255_attach(struct comedi_device *dev, if (ret) return ret; - printk(KERN_INFO "comedi%d: 8255:", dev->minor); - for (i = 0; i < dev->n_subdevices; i++) { iobase = it->options[i]; - printk(" 0x%04lx", iobase); if (!request_region(iobase, _8255_SIZE, "8255")) { - printk(" (I/O port conflict)"); + dev_warn(dev->class_dev, + "0x%04lx (I/O port conflict)\n", iobase); dev->subdevices[i].type = COMEDI_SUBD_UNUSED; } else { subdev_8255_init(dev, dev->subdevices + i, NULL, iobase); + dev_info(dev->class_dev, "0x%04lx\n", iobase); } } - printk("\n"); - return 0; } -- GitLab From e40e8375c0eb546b66c5e66f5e10b68ec46f7b95 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:41:27 -0700 Subject: [PATCH 0696/5711] staging: comedi: 8255: use pointer to dev->subdevices Instead of accessing the dev->subdevices directly as an array, use a pointer. This method is more common in the comedi subsystem. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index b608a05bcd1b..23b9accc34d3 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -371,6 +371,7 @@ EXPORT_SYMBOL(subdev_8255_cleanup); static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + struct comedi_subdevice *s; int ret; unsigned long iobase; int i; @@ -392,16 +393,16 @@ static int dev_8255_attach(struct comedi_device *dev, return ret; for (i = 0; i < dev->n_subdevices; i++) { + s = dev->subdevices + i; iobase = it->options[i]; if (!request_region(iobase, _8255_SIZE, "8255")) { dev_warn(dev->class_dev, "0x%04lx (I/O port conflict)\n", iobase); - dev->subdevices[i].type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } else { - subdev_8255_init(dev, dev->subdevices + i, NULL, - iobase); + subdev_8255_init(dev, s, NULL, iobase); dev_info(dev->class_dev, "0x%04lx\n", iobase); } } -- GitLab From a9044d91990d4ba611f95fc5c84e2531fa54a5f9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:41:36 -0700 Subject: [PATCH 0697/5711] staging: comedi: 8255: rename the private data structure Rename the 8255's private data structure from subdev_8255_struct to subdev_8255_private. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 23b9accc34d3..446dfc5c970a 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -97,15 +97,15 @@ I/O port base address can be found in the output of 'lspci -v'. #define CR_A_MODE(a) ((a)<<5) #define CR_CW 0x80 -struct subdev_8255_struct { +struct subdev_8255_private { unsigned long cb_arg; int (*cb_func) (int, int, int, unsigned long); int have_irq; }; -#define CALLBACK_ARG (((struct subdev_8255_struct *)s->private)->cb_arg) -#define CALLBACK_FUNC (((struct subdev_8255_struct *)s->private)->cb_func) -#define subdevpriv ((struct subdev_8255_struct *)s->private) +#define CALLBACK_ARG (((struct subdev_8255_private *)s->private)->cb_arg) +#define CALLBACK_FUNC (((struct subdev_8255_private *)s->private)->cb_func) +#define subdevpriv ((struct subdev_8255_private *)s->private) void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) @@ -316,7 +316,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, s->range_table = &range_digital; s->maxdata = 1; - s->private = kmalloc(sizeof(struct subdev_8255_struct), GFP_KERNEL); + s->private = kmalloc(sizeof(struct subdev_8255_private), GFP_KERNEL); if (!s->private) return -ENOMEM; -- GitLab From 7c61452afcf5cf2f781f8aabc42405af0edc4b06 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:41:45 -0700 Subject: [PATCH 0698/5711] staging: comedi: 8255: remove the s->private access macros The macros CALLBACK_ARG, CALLBACK_FUNC, and subdevpriv all rely on a a local variable having a specific name. Replace the macros with local variables wherever they occur. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 59 +++++++++++++++------------ 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 446dfc5c970a..5e0e8ff89366 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -103,17 +103,14 @@ struct subdev_8255_private { int have_irq; }; -#define CALLBACK_ARG (((struct subdev_8255_private *)s->private)->cb_arg) -#define CALLBACK_FUNC (((struct subdev_8255_private *)s->private)->cb_func) -#define subdevpriv ((struct subdev_8255_private *)s->private) - void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { + struct subdev_8255_private *spriv = s->private; short d; - d = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG); - d |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8); + d = spriv->cb_func(0, _8255_DATA, 0, spriv->cb_arg); + d |= (spriv->cb_func(0, _8255_DATA + 1, 0, spriv->cb_arg) << 8); comedi_buf_put(s->async, d); s->async->events |= COMEDI_CB_EOS; @@ -138,30 +135,33 @@ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct subdev_8255_private *spriv = s->private; + if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); if (data[0] & 0xff) - CALLBACK_FUNC(1, _8255_DATA, s->state & 0xff, - CALLBACK_ARG); + spriv->cb_func(1, _8255_DATA, s->state & 0xff, + spriv->cb_arg); if (data[0] & 0xff00) - CALLBACK_FUNC(1, _8255_DATA + 1, (s->state >> 8) & 0xff, - CALLBACK_ARG); + spriv->cb_func(1, _8255_DATA + 1, + (s->state >> 8) & 0xff, spriv->cb_arg); if (data[0] & 0xff0000) - CALLBACK_FUNC(1, _8255_DATA + 2, - (s->state >> 16) & 0xff, CALLBACK_ARG); + spriv->cb_func(1, _8255_DATA + 2, + (s->state >> 16) & 0xff, spriv->cb_arg); } - data[1] = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG); - data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8); - data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 2, 0, CALLBACK_ARG) << 16); + data[1] = spriv->cb_func(0, _8255_DATA, 0, spriv->cb_arg); + data[1] |= (spriv->cb_func(0, _8255_DATA + 1, 0, spriv->cb_arg) << 8); + data[1] |= (spriv->cb_func(0, _8255_DATA + 2, 0, spriv->cb_arg) << 16); return 2; } static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) { + struct subdev_8255_private *spriv = s->private; int config; config = CR_CW; @@ -174,7 +174,7 @@ static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) config |= CR_C_LO_IO; if (!(s->io_bits & 0xf00000)) config |= CR_C_HI_IO; - CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG); + spriv->cb_func(1, _8255_CR, config, spriv->cb_arg); } static int subdev_8255_insn_config(struct comedi_device *dev, @@ -310,21 +310,24 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*cb) (int, int, int, unsigned long), unsigned long arg) { + struct subdev_8255_private *spriv; + s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 24; s->range_table = &range_digital; s->maxdata = 1; - s->private = kmalloc(sizeof(struct subdev_8255_private), GFP_KERNEL); - if (!s->private) + spriv = kmalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) return -ENOMEM; + s->private = spriv; - CALLBACK_ARG = arg; + spriv->cb_arg = arg; if (cb == NULL) - CALLBACK_FUNC = subdev_8255_cb; + spriv->cb_func = subdev_8255_cb; else - CALLBACK_FUNC = cb; + spriv->cb_func = cb; s->insn_bits = subdev_8255_insn; s->insn_config = subdev_8255_insn_config; @@ -340,18 +343,20 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int (*cb) (int, int, int, unsigned long), unsigned long arg) { + struct subdev_8255_private *spriv; int ret; ret = subdev_8255_init(dev, s, cb, arg); if (ret < 0) return ret; + spriv = s->private; + + spriv->have_irq = 1; s->do_cmdtest = subdev_8255_cmdtest; s->do_cmd = subdev_8255_cmd; s->cancel = subdev_8255_cancel; - subdevpriv->have_irq = 1; - return 0; } EXPORT_SYMBOL(subdev_8255_init_irq); @@ -412,15 +417,15 @@ static int dev_8255_attach(struct comedi_device *dev, static void dev_8255_detach(struct comedi_device *dev) { - int i; - unsigned long iobase; struct comedi_subdevice *s; + struct subdev_8255_private *spriv; + int i; for (i = 0; i < dev->n_subdevices; i++) { s = dev->subdevices + i; if (s->type != COMEDI_SUBD_UNUSED) { - iobase = CALLBACK_ARG; - release_region(iobase, _8255_SIZE); + spriv = s->private; + release_region(spriv->cb_arg, _8255_SIZE); } subdev_8255_cleanup(dev, s); } -- GitLab From 7a583163e87c8dd5b1826199d2a189f0daaf3247 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:41:54 -0700 Subject: [PATCH 0699/5711] staging: comedi: 8255: rename cb_arg and cb_func The 8255's private data variables cb_arg and cb_func are actually the iobase for the 8255 device and the pointer to the io function to access the device. Rename them as such to improve the readability of the driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 5e0e8ff89366..7b7768b62484 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -98,8 +98,8 @@ I/O port base address can be found in the output of 'lspci -v'. #define CR_CW 0x80 struct subdev_8255_private { - unsigned long cb_arg; - int (*cb_func) (int, int, int, unsigned long); + unsigned long iobase; + int (*io) (int, int, int, unsigned long); int have_irq; }; @@ -109,8 +109,8 @@ void subdev_8255_interrupt(struct comedi_device *dev, struct subdev_8255_private *spriv = s->private; short d; - d = spriv->cb_func(0, _8255_DATA, 0, spriv->cb_arg); - d |= (spriv->cb_func(0, _8255_DATA + 1, 0, spriv->cb_arg) << 8); + d = spriv->io(0, _8255_DATA, 0, spriv->iobase); + d |= (spriv->io(0, _8255_DATA + 1, 0, spriv->iobase) << 8); comedi_buf_put(s->async, d); s->async->events |= COMEDI_CB_EOS; @@ -142,19 +142,19 @@ static int subdev_8255_insn(struct comedi_device *dev, s->state |= (data[0] & data[1]); if (data[0] & 0xff) - spriv->cb_func(1, _8255_DATA, s->state & 0xff, - spriv->cb_arg); + spriv->io(1, _8255_DATA, s->state & 0xff, + spriv->iobase); if (data[0] & 0xff00) - spriv->cb_func(1, _8255_DATA + 1, - (s->state >> 8) & 0xff, spriv->cb_arg); + spriv->io(1, _8255_DATA + 1, + (s->state >> 8) & 0xff, spriv->iobase); if (data[0] & 0xff0000) - spriv->cb_func(1, _8255_DATA + 2, - (s->state >> 16) & 0xff, spriv->cb_arg); + spriv->io(1, _8255_DATA + 2, + (s->state >> 16) & 0xff, spriv->iobase); } - data[1] = spriv->cb_func(0, _8255_DATA, 0, spriv->cb_arg); - data[1] |= (spriv->cb_func(0, _8255_DATA + 1, 0, spriv->cb_arg) << 8); - data[1] |= (spriv->cb_func(0, _8255_DATA + 2, 0, spriv->cb_arg) << 16); + data[1] = spriv->io(0, _8255_DATA, 0, spriv->iobase); + data[1] |= (spriv->io(0, _8255_DATA + 1, 0, spriv->iobase) << 8); + data[1] |= (spriv->io(0, _8255_DATA + 2, 0, spriv->iobase) << 16); return 2; } @@ -174,7 +174,7 @@ static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) config |= CR_C_LO_IO; if (!(s->io_bits & 0xf00000)) config |= CR_C_HI_IO; - spriv->cb_func(1, _8255_CR, config, spriv->cb_arg); + spriv->io(1, _8255_CR, config, spriv->iobase); } static int subdev_8255_insn_config(struct comedi_device *dev, @@ -323,11 +323,11 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, return -ENOMEM; s->private = spriv; - spriv->cb_arg = arg; + spriv->iobase = arg; if (cb == NULL) - spriv->cb_func = subdev_8255_cb; + spriv->io = subdev_8255_cb; else - spriv->cb_func = cb; + spriv->io = cb; s->insn_bits = subdev_8255_insn; s->insn_config = subdev_8255_insn_config; @@ -425,7 +425,7 @@ static void dev_8255_detach(struct comedi_device *dev) s = dev->subdevices + i; if (s->type != COMEDI_SUBD_UNUSED) { spriv = s->private; - release_region(spriv->cb_arg, _8255_SIZE); + release_region(spriv->iobase, _8255_SIZE); } subdev_8255_cleanup(dev, s); } -- GitLab From d29a18dcdbfbe250265abdf9c94d60df86f90316 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:02 -0700 Subject: [PATCH 0700/5711] staging: comedi: 8255: push out the 8255's private data variable rename Push out the rename of the private variables to improve the readability of the driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 32 +++++++++++++-------------- drivers/staging/comedi/drivers/8255.h | 8 +++---- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 7b7768b62484..80ef0315662b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -60,15 +60,15 @@ I/O port base address can be found in the output of 'lspci -v'. set up the subdevice in the attach function of the driver by calling: - subdev_8255_init(device, subdevice, callback_function, arg) + subdev_8255_init(device, subdevice, io_function, iobase) device and subdevice are pointers to the device and subdevice - structures. callback_function will be called to provide the + structures. io_function will be called to provide the low-level input/output to the device, i.e., actual register - access. callback_function will be called with the value of arg + access. io_function will be called with the value of iobase as the last parameter. If the 8255 device is mapped as 4 - consecutive I/O ports, you can use NULL for callback_function - and the I/O port base for arg, and an internal function will + consecutive I/O ports, you can use NULL for io_function + and the I/O port base for iobase, and an internal function will handle the register access. In addition, if the main driver handles interrupts, you can @@ -119,10 +119,8 @@ void subdev_8255_interrupt(struct comedi_device *dev, } EXPORT_SYMBOL(subdev_8255_interrupt); -static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) +static int subdev_8255_io(int dir, int port, int data, unsigned long iobase) { - unsigned long iobase = arg; - if (dir) { outb(data, iobase + port); return 0; @@ -307,8 +305,8 @@ static int subdev_8255_cancel(struct comedi_device *dev, } int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, - int (*cb) (int, int, int, unsigned long), - unsigned long arg) + int (*io) (int, int, int, unsigned long), + unsigned long iobase) { struct subdev_8255_private *spriv; @@ -323,11 +321,11 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, return -ENOMEM; s->private = spriv; - spriv->iobase = arg; - if (cb == NULL) - spriv->io = subdev_8255_cb; + spriv->iobase = iobase; + if (io == NULL) + spriv->io = subdev_8255_io; else - spriv->io = cb; + spriv->io = io; s->insn_bits = subdev_8255_insn; s->insn_config = subdev_8255_insn_config; @@ -340,13 +338,13 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, EXPORT_SYMBOL(subdev_8255_init); int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, - int (*cb) (int, int, int, unsigned long), - unsigned long arg) + int (*io) (int, int, int, unsigned long), + unsigned long iobase) { struct subdev_8255_private *spriv; int ret; - ret = subdev_8255_init(dev, s, cb, arg); + ret = subdev_8255_init(dev, s, io, iobase); if (ret < 0) return ret; spriv = s->private; diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index b6314c9b7eae..1e589b4b8b73 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -27,11 +27,11 @@ #include "../comedidev.h" int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, - int (*cb) (int, int, int, unsigned long), - unsigned long arg); + int (*io) (int, int, int, unsigned long), + unsigned long iobase); int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, - int (*cb) (int, int, int, unsigned long), - unsigned long arg); + int (*io) (int, int, int, unsigned long), + unsigned long iobase); void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s); void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s); -- GitLab From cc31b1be67bf4b878157e276056b6dbce76fdb45 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:12 -0700 Subject: [PATCH 0701/5711] staging: comedi: 8255: refactor subdev_8255_init Refactor the initialization of the 8255 so that the private data allocation is done before the subdevice is setup. This makes sure that the setup is complete. Also, add a bit of whitespace to improve the readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 80ef0315662b..52b98171a16e 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -310,27 +310,26 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, { struct subdev_8255_private *spriv; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->range_table = &range_digital; - s->maxdata = 1; - spriv = kmalloc(sizeof(*spriv), GFP_KERNEL); if (!spriv) return -ENOMEM; - s->private = spriv; - spriv->iobase = iobase; - if (io == NULL) - spriv->io = subdev_8255_io; - else - spriv->io = io; - s->insn_bits = subdev_8255_insn; - s->insn_config = subdev_8255_insn_config; + spriv->iobase = iobase; + spriv->io = io ? io : subdev_8255_io; + + s->private = spriv; + + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = subdev_8255_insn; + s->insn_config = subdev_8255_insn_config; + + s->state = 0; + s->io_bits = 0; - s->state = 0; - s->io_bits = 0; do_config(dev, s); return 0; -- GitLab From 34cfcf9acc6b0697e71294007c57eae91b80005c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:21 -0700 Subject: [PATCH 0702/5711] staging: comedi: 8255: remove have_irg and refactor subdev_8255_init_irq The have_irq variable in the 8255 private data is not used by the driver, remove it. This removes the need to access the private data in the subdev_8255_init_irq function. Also, add a bit of whitespace to improve the readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 52b98171a16e..da86a04b70f7 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -100,7 +100,6 @@ I/O port base address can be found in the output of 'lspci -v'. struct subdev_8255_private { unsigned long iobase; int (*io) (int, int, int, unsigned long); - int have_irq; }; void subdev_8255_interrupt(struct comedi_device *dev, @@ -340,19 +339,15 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int (*io) (int, int, int, unsigned long), unsigned long iobase) { - struct subdev_8255_private *spriv; int ret; ret = subdev_8255_init(dev, s, io, iobase); if (ret < 0) return ret; - spriv = s->private; - - spriv->have_irq = 1; - s->do_cmdtest = subdev_8255_cmdtest; - s->do_cmd = subdev_8255_cmd; - s->cancel = subdev_8255_cancel; + s->do_cmdtest = subdev_8255_cmdtest; + s->do_cmd = subdev_8255_cmd; + s->cancel = subdev_8255_cancel; return 0; } -- GitLab From 3e189f08ef81e27aeccd2c2fb55175451f9faa71 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:28 -0700 Subject: [PATCH 0703/5711] staging: comedi: 8255: check for failure of subdev_8255_init The initialization of the 8255 subdevice can fail. Make sure to check for it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index da86a04b70f7..4cdd00762e86 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -342,7 +342,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int ret; ret = subdev_8255_init(dev, s, io, iobase); - if (ret < 0) + if (ret) return ret; s->do_cmdtest = subdev_8255_cmdtest; @@ -399,7 +399,9 @@ static int dev_8255_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } else { - subdev_8255_init(dev, s, NULL, iobase); + ret = subdev_8255_init(dev, s, NULL, iobase); + if (ret) + return ret; dev_info(dev->class_dev, "0x%04lx\n", iobase); } } -- GitLab From e64fb55b1a519a7d0fda51f40ab668830d6475ac Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:34 -0700 Subject: [PATCH 0704/5711] staging: comedi: 8255: use kzalloc to allocate the private data Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 4cdd00762e86..f6ea49335bb4 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -309,7 +309,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, { struct subdev_8255_private *spriv; - spriv = kmalloc(sizeof(*spriv), GFP_KERNEL); + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); if (!spriv) return -ENOMEM; -- GitLab From f218d9f57b472848da34beac3e8097b054dcb2fe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:39 -0700 Subject: [PATCH 0705/5711] staging: comedi: 8255: use a local variable for the iobase To improve readability, use a locale variable to hold the 8255's private iobase value. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index f6ea49335bb4..1f4b24c9ed85 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -106,10 +106,11 @@ void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct subdev_8255_private *spriv = s->private; + unsigned long iobase = spriv->iobase; short d; - d = spriv->io(0, _8255_DATA, 0, spriv->iobase); - d |= (spriv->io(0, _8255_DATA + 1, 0, spriv->iobase) << 8); + d = spriv->io(0, _8255_DATA, 0, iobase); + d |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); comedi_buf_put(s->async, d); s->async->events |= COMEDI_CB_EOS; @@ -133,25 +134,25 @@ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct subdev_8255_private *spriv = s->private; + unsigned long iobase = spriv->iobase; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); if (data[0] & 0xff) - spriv->io(1, _8255_DATA, s->state & 0xff, - spriv->iobase); + spriv->io(1, _8255_DATA, s->state & 0xff, iobase); if (data[0] & 0xff00) spriv->io(1, _8255_DATA + 1, - (s->state >> 8) & 0xff, spriv->iobase); + (s->state >> 8) & 0xff, iobase); if (data[0] & 0xff0000) spriv->io(1, _8255_DATA + 2, - (s->state >> 16) & 0xff, spriv->iobase); + (s->state >> 16) & 0xff, iobase); } - data[1] = spriv->io(0, _8255_DATA, 0, spriv->iobase); - data[1] |= (spriv->io(0, _8255_DATA + 1, 0, spriv->iobase) << 8); - data[1] |= (spriv->io(0, _8255_DATA + 2, 0, spriv->iobase) << 16); + data[1] = spriv->io(0, _8255_DATA, 0, iobase); + data[1] |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); + data[1] |= (spriv->io(0, _8255_DATA + 2, 0, iobase) << 16); return 2; } @@ -159,6 +160,7 @@ static int subdev_8255_insn(struct comedi_device *dev, static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) { struct subdev_8255_private *spriv = s->private; + unsigned long iobase = spriv->iobase; int config; config = CR_CW; @@ -171,7 +173,8 @@ static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) config |= CR_C_LO_IO; if (!(s->io_bits & 0xf00000)) config |= CR_C_HI_IO; - spriv->io(1, _8255_CR, config, spriv->iobase); + + spriv->io(1, _8255_CR, config, iobase); } static int subdev_8255_insn_config(struct comedi_device *dev, -- GitLab From 459f299e5b1759644a6cde8328919b6e542fb9eb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:45 -0700 Subject: [PATCH 0706/5711] staging: comedi: 8255: refactor subdev_8255_insn function Refactor the subdev_8255_insn function to follow what the user space library is doing. 1) This function requires 'data' to contain 2 parameters. Add a sanity check for this (insn->n != 2). 2) The 'data' parameters are actually a 'mask' of the valid bits and the actual 'bits' to modify. Create local variables of these names to help with maintainability. 3) The value returned in data[1] reflects the actual state of the 8255 io pins after the update of the masked bits. Fetch this data in a local variable and then set data[1]. 4) The user space library only checks for a < 0 return to indicate an error. It appears that the 'return 2' in this function is supposed to indicate the number of data parameters used to perform the command. Return the insn->n value for this, the open coded '2' looks wrong. Signed-off-by: H Hartley Sweeten Cc: Iam Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 44 +++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 1f4b24c9ed85..da374dee9bc0 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -135,26 +135,38 @@ static int subdev_8255_insn(struct comedi_device *dev, { struct subdev_8255_private *spriv = s->private; unsigned long iobase = spriv->iobase; + unsigned int mask; + unsigned int bits; + unsigned int v; + + if (insn->n != 2) + return -EINVAL; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - - if (data[0] & 0xff) - spriv->io(1, _8255_DATA, s->state & 0xff, iobase); - if (data[0] & 0xff00) - spriv->io(1, _8255_DATA + 1, - (s->state >> 8) & 0xff, iobase); - if (data[0] & 0xff0000) - spriv->io(1, _8255_DATA + 2, - (s->state >> 16) & 0xff, iobase); + mask = data[0]; + bits = data[1]; + + if (mask) { + v = s->state; + v &= ~mask; + v |= (bits & mask); + + if (mask & 0xff) + spriv->io(1, _8255_DATA, v & 0xff, iobase); + if (mask & 0xff00) + spriv->io(1, _8255_DATA + 1, (v >> 8) & 0xff, iobase); + if (mask & 0xff0000) + spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase); + + s->state = v; } - data[1] = spriv->io(0, _8255_DATA, 0, iobase); - data[1] |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); - data[1] |= (spriv->io(0, _8255_DATA + 2, 0, iobase) << 16); + v = spriv->io(0, _8255_DATA, 0, iobase); + v |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); + v |= (spriv->io(0, _8255_DATA + 2, 0, iobase) << 16); + + data[1] = v; - return 2; + return insn->n; } static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) -- GitLab From f9af899b0c6c778083d1040349930a0f9fffb525 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:42:51 -0700 Subject: [PATCH 0707/5711] staging: comedi: 8255: move the subdev_8255_io function The subdev_8255_interrupt function indirectly calls subdev_8255_io. For aesthetic reasons, move the subdev_8255_io function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index da374dee9bc0..abbb6d4d10d1 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -102,6 +102,16 @@ struct subdev_8255_private { int (*io) (int, int, int, unsigned long); }; +static int subdev_8255_io(int dir, int port, int data, unsigned long iobase) +{ + if (dir) { + outb(data, iobase + port); + return 0; + } else { + return inb(iobase + port); + } +} + void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -119,16 +129,6 @@ void subdev_8255_interrupt(struct comedi_device *dev, } EXPORT_SYMBOL(subdev_8255_interrupt); -static int subdev_8255_io(int dir, int port, int data, unsigned long iobase) -{ - if (dir) { - outb(data, iobase + port); - return 0; - } else { - return inb(iobase + port); - } -} - static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) -- GitLab From cf8a6b3d86ec4d6ac8e2925a65335bd0d155c480 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:43:04 -0700 Subject: [PATCH 0708/5711] staging: comedi: 8255: add namespace to 'do_config' function The name 'do_config' is pretty generic, and this function is the only one in this driver without namespace. Add namespace to it just to avoid any issues. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index abbb6d4d10d1..8c97ac1e6970 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -169,7 +169,8 @@ static int subdev_8255_insn(struct comedi_device *dev, return insn->n; } -static void do_config(struct comedi_device *dev, struct comedi_subdevice *s) +static void subdev_8255_do_config(struct comedi_device *dev, + struct comedi_subdevice *s) { struct subdev_8255_private *spriv = s->private; unsigned long iobase = spriv->iobase; @@ -221,7 +222,7 @@ static int subdev_8255_insn_config(struct comedi_device *dev, return -EINVAL; } - do_config(dev, s); + subdev_8255_do_config(dev, s); return 1; } @@ -344,7 +345,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, s->state = 0; s->io_bits = 0; - do_config(dev, s); + subdev_8255_do_config(dev, s); return 0; } -- GitLab From 03ae8189ee6cab3d4af3e39136105f02d7c35883 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 15:43:11 -0700 Subject: [PATCH 0709/5711] staging: comedi: 8255: add some whitespace to the #define's Add whitespace to the _8255_* defines to improve readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 8c97ac1e6970..e0de149c3c29 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -84,10 +84,10 @@ I/O port base address can be found in the output of 'lspci -v'. #include #include "8255.h" -#define _8255_SIZE 4 +#define _8255_SIZE 4 -#define _8255_DATA 0 -#define _8255_CR 3 +#define _8255_DATA 0 +#define _8255_CR 3 #define CR_C_LO_IO 0x01 #define CR_B_IO 0x02 -- GitLab From b4b700c5a61c6e6db976f60d4eb6ad369e838aa9 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 13 Jun 2012 16:03:42 -0500 Subject: [PATCH 0710/5711] staging: zsmalloc: fix uninit'ed variable warning This patch fixes an uninitialized variable warning in alloc_zspage(). It also fixes the secondary issue of prev_page leaving scope on each loop iteration. The only reason this ever worked was because prev_page was occupying the same space on the stack on each iteration. Signed-off-by: Seth Jennings Reported-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index fb54a9b94c33..4af3dd6641c9 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -400,7 +400,7 @@ static void init_zspage(struct page *first_page, struct size_class *class) static struct page *alloc_zspage(struct size_class *class, gfp_t flags) { int i, error; - struct page *first_page = NULL; + struct page *first_page = NULL, *uninitialized_var(prev_page); /* * Allocate individual pages and link them together as: @@ -415,7 +415,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags) */ error = -ENOMEM; for (i = 0; i < class->pages_per_zspage; i++) { - struct page *page, *prev_page; + struct page *page; page = alloc_page(flags); if (!page) -- GitLab From 7489301a1590c2771d27a08d41fa2778791cdf9d Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Wed, 13 Jun 2012 15:37:18 -0400 Subject: [PATCH 0711/5711] staging: usbip: cleanup and fix of vhci_hub_status Changed setting the status bits to a byte-oriented approach. Number of written status bits is now based on VHCI_NPORT, instead of casting status buffer to a long. This fixes a stack corruption bug on 64-bit based architectures, and potential byte order / endianness related issues. In addition updated function comments, and log statements. Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 39 +++++++++----------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index f708cbaee16b..12a9a5fbc797 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -178,44 +178,32 @@ void rh_port_disconnect(int rhport) | USB_PORT_STAT_C_RESET) << 16) /* - * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without - * suspend/resume support. But, it is modified to provide multiple ports. + * Returns 0 if the status hasn't changed, or the number of bytes in buf. + * Ports are 0-indexed from the HCD point of view, + * and 1-indexed from the USB core pointer of view. * * @buf: a bitmap to show which port status has been changed. - * bit 0: reserved or used for another purpose? + * bit 0: reserved * bit 1: the status of port 0 has been changed. * bit 2: the status of port 1 has been changed. * ... - * bit 7: the status of port 6 has been changed. - * bit 8: the status of port 7 has been changed. - * ... - * bit 15: the status of port 14 has been changed. - * - * So, the maximum number of ports is 31 ( port 0 to port 30) ? - * - * The return value is the actual transferred length in byte. If nothing has - * been changed, return 0. In the case that the number of ports is less than or - * equal to 6 (VHCI_NPORTS==7), return 1. - * */ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) { struct vhci_hcd *vhci; unsigned long flags; - int retval = 0; - - /* the enough buffer is allocated according to USB_MAXCHILDREN */ - unsigned long *event_bits = (unsigned long *) buf; + int retval; int rhport; int changed = 0; - *event_bits = 0; + retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8); + memset(buf, 0, retval); vhci = hcd_to_vhci(hcd); spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { - usbip_dbg_vhci_rh("hw accessible flag in on?\n"); + usbip_dbg_vhci_rh("hw accessible flag not on?\n"); goto done; } @@ -223,9 +211,9 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) for (rhport = 0; rhport < VHCI_NPORTS; rhport++) { if ((vhci->port_status[rhport] & PORT_C_MASK)) { /* The status of a port has been changed, */ - usbip_dbg_vhci_rh("port %d is changed\n", rhport); + usbip_dbg_vhci_rh("port %d status changed\n", rhport); - *event_bits |= 1 << (rhport + 1); + buf[(rhport + 1) / 8] |= 1 << (rhport + 1) % 8; changed = 1; } } @@ -235,14 +223,9 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) if (hcd->state == HC_STATE_SUSPENDED) usb_hcd_resume_root_hub(hcd); - if (changed) - retval = 1 + (VHCI_NPORTS / 8); - else - retval = 0; - done: spin_unlock_irqrestore(&vhci->lock, flags); - return retval; + return changed ? retval : 0; } /* See hub_configure in hub.c */ -- GitLab From d691af000274ae9658695c2a63a76b30890a8983 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 12 Jun 2012 16:50:55 +0800 Subject: [PATCH 0712/5711] crypto: s390 - clean up DES code a bit more Commit 98971f8439b1bb9a61682fe24a865ddd25167a6b ("crypto: s390 - cleanup DES code") should have also removed crypto_des.h. That file is unused and unneeded since that commit. So let's clean up that file too. Signed-off-by: Paul Bolle Acked-by: Jan Glauber Signed-off-by: Herbert Xu --- arch/s390/crypto/crypto_des.h | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 arch/s390/crypto/crypto_des.h diff --git a/arch/s390/crypto/crypto_des.h b/arch/s390/crypto/crypto_des.h deleted file mode 100644 index 6210457ceebb..000000000000 --- a/arch/s390/crypto/crypto_des.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Cryptographic API. - * - * Function for checking keys for the DES and Tripple DES Encryption - * algorithms. - * - * 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 __CRYPTO_DES_H__ -#define __CRYPTO_DES_H__ - -extern int crypto_des_check_key(const u8*, unsigned int, u32*); - -#endif /*__CRYPTO_DES_H__*/ -- GitLab From 31b4cd2907322bd56e4090168e4ce8f8dcd17820 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 12 Jun 2012 16:52:04 +0800 Subject: [PATCH 0713/5711] crypto: testmgr - add ecb(arc4) speed tests Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 2af879786e75..58ad4fe5d208 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1342,6 +1342,11 @@ static int do_test(int m) speed_template_32_64); break; + case 208: + test_cipher_speed("ecb(arc4)", ENCRYPT, sec, NULL, 0, + speed_template_8); + break; + case 300: /* fall through */ @@ -1589,6 +1594,11 @@ static int do_test(int m) speed_template_32_48_64); break; + case 505: + test_acipher_speed("ecb(arc4)", ENCRYPT, sec, NULL, 0, + speed_template_8); + break; + case 1000: test_available(); break; -- GitLab From 150ed86fade791d82319b27e84a7a6d2de84d1fa Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 13 Jun 2012 22:07:20 -0400 Subject: [PATCH 0714/5711] ACPI: acpi_pad: rename "power_saving" thread to "acpi_pad" thread "acpi_pad/%d" is a better thread name than generic "power_saving/%d" because users who see these threads will know the name of the driver that caused them. Signed-off-by: Len Brown --- drivers/acpi/acpi_pad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index a43fa1a57d57..1c09e1b532b0 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -234,7 +234,7 @@ static int create_power_saving_task(void) ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, - "power_saving/%d", ps_tsk_num); + "acpi_pad/%d", ps_tsk_num); rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; if (!rc) ps_tsk_num++; -- GitLab From ce6dd368984068c8938e8d3fba8e292ef63cee97 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 9 Jun 2012 18:25:40 +0300 Subject: [PATCH 0715/5711] crypto: arc4 - improve performance by adding ecb(arc4) Currently arc4.c provides simple one-byte blocksize cipher which is wrapped by ecb() module, giving function call overhead on every encrypted byte. This patch adds ecb(arc4) directly into arc4.c for higher performance. tcrypt results (speed ratios: new/old): AMD Phenom II, x86-64 : x2.7 Intel Core 2, x86-64 : x1.9 Intel Atom N260, i386 : x1.4 Cc: Jon Oberheide Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- crypto/arc4.c | 109 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 22 deletions(-) diff --git a/crypto/arc4.c b/crypto/arc4.c index 0d12a96da1d8..07913fc52c4e 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -11,9 +11,11 @@ * (at your option) any later version. * */ + #include #include #include +#include #define ARC4_MIN_KEY_SIZE 1 #define ARC4_MAX_KEY_SIZE 256 @@ -48,51 +50,114 @@ static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, return 0; } -static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, + unsigned int len) { - struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); - u8 *const S = ctx->S; - u8 x = ctx->x; - u8 y = ctx->y; - u8 a, b; + u8 x, y, a, b; + u8 ty, ta, tb; + + if (len == 0) + return; + + x = ctx->x; + y = ctx->y; a = S[x]; y = (y + a) & 0xff; b = S[y]; - S[x] = b; - S[y] = a; - x = (x + 1) & 0xff; - *out++ = *in ^ S[(a + b) & 0xff]; + + do { + S[y] = a; + a = (a + b) & 0xff; + S[x] = b; + x = (x + 1) & 0xff; + ta = S[x]; + ty = (y + ta) & 0xff; + tb = S[ty]; + *out++ = *in++ ^ S[a]; + if (--len == 0) + break; + y = ty; + a = ta; + b = tb; + } while (true); ctx->x = x; ctx->y = y; } -static struct crypto_alg arc4_alg = { +static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1); +} + +static int ecb_arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + + err = blkcipher_walk_virt(desc, &walk); + + while (walk.nbytes > 0) { + u8 *wsrc = walk.src.virt.addr; + u8 *wdst = walk.dst.virt.addr; + + arc4_crypt(ctx, wdst, wsrc, walk.nbytes); + + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} + +static struct crypto_alg arc4_algs[2] = { { .cra_name = "arc4", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = ARC4_BLOCK_SIZE, .cra_ctxsize = sizeof(struct arc4_ctx), .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = ARC4_MIN_KEY_SIZE, - .cia_max_keysize = ARC4_MAX_KEY_SIZE, - .cia_setkey = arc4_set_key, - .cia_encrypt = arc4_crypt, - .cia_decrypt = arc4_crypt } } -}; + .cra_u = { + .cipher = { + .cia_min_keysize = ARC4_MIN_KEY_SIZE, + .cia_max_keysize = ARC4_MAX_KEY_SIZE, + .cia_setkey = arc4_set_key, + .cia_encrypt = arc4_crypt_one, + .cia_decrypt = arc4_crypt_one, + }, + }, +}, { + .cra_name = "ecb(arc4)", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = ARC4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct arc4_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_u = { + .blkcipher = { + .min_keysize = ARC4_MIN_KEY_SIZE, + .max_keysize = ARC4_MAX_KEY_SIZE, + .setkey = arc4_set_key, + .encrypt = ecb_arc4_crypt, + .decrypt = ecb_arc4_crypt, + }, + }, +} }; static int __init arc4_init(void) { - return crypto_register_alg(&arc4_alg); + return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs)); } - static void __exit arc4_exit(void) { - crypto_unregister_alg(&arc4_alg); + crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs)); } module_init(arc4_init); -- GitLab From d366db605c8c4a9878589bc4a87e55f6063184ac Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 9 Jun 2012 18:25:46 +0300 Subject: [PATCH 0716/5711] crypto: arc4 - improve performance by using u32 for ctx and variables This patch changes u8 in struct arc4_ctx and variables to u32 (as AMD seems to have problem with u8 array). Below are tcrypt results of old 1-byte block cipher versus ecb(arc4) with u8 and ecb(arc4) with u32. tcrypt results, x86-64 (speed ratios: new-u32/old, new-u8/old): u32 u8 AMD Phenom II : x3.6 x2.7 Intel Core 2 : x2.0 x1.9 tcrypt results, i386 (speed ratios: new-u32/old, new-u8/old): u32 u8 Intel Atom N260 : x1.5 x1.4 Cc: Jon Oberheide Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- crypto/arc4.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crypto/arc4.c b/crypto/arc4.c index 07913fc52c4e..5a772c3657d5 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -22,8 +22,8 @@ #define ARC4_BLOCK_SIZE 1 struct arc4_ctx { - u8 S[256]; - u8 x, y; + u32 S[256]; + u32 x, y; }; static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, @@ -39,7 +39,7 @@ static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, ctx->S[i] = i; for (i = 0; i < 256; i++) { - u8 a = ctx->S[i]; + u32 a = ctx->S[i]; j = (j + in_key[k] + a) & 0xff; ctx->S[i] = ctx->S[j]; ctx->S[j] = a; @@ -53,9 +53,9 @@ static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len) { - u8 *const S = ctx->S; - u8 x, y, a, b; - u8 ty, ta, tb; + u32 *const S = ctx->S; + u32 x, y, a, b; + u32 ty, ta, tb; if (len == 0) return; -- GitLab From 3387e7d69048f5ab02729825f9611754850d9a87 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 14 Jun 2012 10:09:03 +0800 Subject: [PATCH 0717/5711] crypto: serpent-sse2/avx - allow both to be built into kernel Rename serpent-avx assembler functions so that they do not collide with serpent-sse2 assembler functions when linking both versions in to same kernel image. Reported-by: Randy Dunlap Cc: Johannes Goetzfried Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 12 +++---- arch/x86/crypto/serpent_avx_glue.c | 2 +- arch/x86/crypto/serpent_sse2_glue.c | 2 +- arch/x86/include/asm/serpent-avx.h | 32 +++++++++++++++++++ .../include/asm/{serpent.h => serpent-sse2.h} | 4 +-- 5 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 arch/x86/include/asm/serpent-avx.h rename arch/x86/include/asm/{serpent.h => serpent-sse2.h} (95%) diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S index 0ed47a124bac..504106bf04a2 100644 --- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S @@ -579,10 +579,10 @@ vmovdqu x3, (3*4*4)(out); .align 8 -.global __serpent_enc_blk_8way -.type __serpent_enc_blk_8way,@function; +.global __serpent_enc_blk_8way_avx +.type __serpent_enc_blk_8way_avx,@function; -__serpent_enc_blk_8way: +__serpent_enc_blk_8way_avx: /* input: * %rdi: ctx, CTX * %rsi: dst @@ -647,10 +647,10 @@ __enc_xor8: ret; .align 8 -.global serpent_dec_blk_8way -.type serpent_dec_blk_8way,@function; +.global serpent_dec_blk_8way_avx +.type serpent_dec_blk_8way_avx,@function; -serpent_dec_blk_8way: +serpent_dec_blk_8way_avx: /* input: * %rdi: ctx, CTX * %rsi: dst diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index 0dc7a26535e5..dd81bab4f11a 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 4b21be85e0a1..deecd25c1299 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/include/asm/serpent-avx.h b/arch/x86/include/asm/serpent-avx.h new file mode 100644 index 000000000000..432deedd2945 --- /dev/null +++ b/arch/x86/include/asm/serpent-avx.h @@ -0,0 +1,32 @@ +#ifndef ASM_X86_SERPENT_AVX_H +#define ASM_X86_SERPENT_AVX_H + +#include +#include + +#define SERPENT_PARALLEL_BLOCKS 8 + +asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_8way_avx(ctx, dst, src); +} + +#endif diff --git a/arch/x86/include/asm/serpent.h b/arch/x86/include/asm/serpent-sse2.h similarity index 95% rename from arch/x86/include/asm/serpent.h rename to arch/x86/include/asm/serpent-sse2.h index d3ef63fe0c81..e6e77dffbdab 100644 --- a/arch/x86/include/asm/serpent.h +++ b/arch/x86/include/asm/serpent-sse2.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86_SERPENT_H -#define ASM_X86_SERPENT_H +#ifndef ASM_X86_SERPENT_SSE2_H +#define ASM_X86_SERPENT_SSE2_H #include #include -- GitLab From f7ceb362c4d2f4e613982148ddb143ad6a205485 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Jun 2012 20:19:24 +0200 Subject: [PATCH 0718/5711] dma: coh901318: use devm allocation Allocate memory, region, remap and irq for device state using devm_* helpers to simplify memory accounting. Signed-off-by: Linus Walleij Signed-off-by: Vinod Koul --- drivers/dma/coh901318.c | 72 ++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 48 deletions(-) diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index e67b4e06a918..aa384e53b7ac 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1438,34 +1438,32 @@ static int __init coh901318_probe(struct platform_device *pdev) io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) - goto err_get_resource; + return -ENODEV; /* Map DMA controller registers to virtual memory */ - if (request_mem_region(io->start, - resource_size(io), - pdev->dev.driver->name) == NULL) { - err = -EBUSY; - goto err_request_mem; - } + if (devm_request_mem_region(&pdev->dev, + io->start, + resource_size(io), + pdev->dev.driver->name) == NULL) + return -ENOMEM; pdata = pdev->dev.platform_data; if (!pdata) - goto err_no_platformdata; + return -ENODEV; - base = kmalloc(ALIGN(sizeof(struct coh901318_base), 4) + - pdata->max_channels * - sizeof(struct coh901318_chan), - GFP_KERNEL); + base = devm_kzalloc(&pdev->dev, + ALIGN(sizeof(struct coh901318_base), 4) + + pdata->max_channels * + sizeof(struct coh901318_chan), + GFP_KERNEL); if (!base) - goto err_alloc_coh_dma_channels; + return -ENOMEM; base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4); - base->virtbase = ioremap(io->start, resource_size(io)); - if (!base->virtbase) { - err = -ENOMEM; - goto err_no_ioremap; - } + base->virtbase = devm_ioremap(&pdev->dev, io->start, resource_size(io)); + if (!base->virtbase) + return -ENOMEM; base->dev = &pdev->dev; base->platform = pdata; @@ -1474,25 +1472,20 @@ static int __init coh901318_probe(struct platform_device *pdev) COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base); - platform_set_drvdata(pdev, base); - irq = platform_get_irq(pdev, 0); if (irq < 0) - goto err_no_irq; - - err = request_irq(irq, dma_irq_handler, IRQF_DISABLED, - "coh901318", base); - if (err) { - dev_crit(&pdev->dev, - "Cannot allocate IRQ for DMA controller!\n"); - goto err_request_irq; - } + return irq; + + err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED, + "coh901318", base); + if (err) + return err; err = coh901318_pool_create(&base->pool, &pdev->dev, sizeof(struct coh901318_lli), 32); if (err) - goto err_pool_create; + return err; /* init channels for device transfers */ coh901318_base_init(&base->dma_slave, base->platform->chans_slave, @@ -1538,6 +1531,7 @@ static int __init coh901318_probe(struct platform_device *pdev) if (err) goto err_register_memcpy; + platform_set_drvdata(pdev, base); dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n", (u32) base->virtbase); @@ -1547,19 +1541,6 @@ static int __init coh901318_probe(struct platform_device *pdev) dma_async_device_unregister(&base->dma_slave); err_register_slave: coh901318_pool_destroy(&base->pool); - err_pool_create: - free_irq(platform_get_irq(pdev, 0), base); - err_request_irq: - err_no_irq: - iounmap(base->virtbase); - err_no_ioremap: - kfree(base); - err_alloc_coh_dma_channels: - err_no_platformdata: - release_mem_region(pdev->resource->start, - resource_size(pdev->resource)); - err_request_mem: - err_get_resource: return err; } @@ -1570,11 +1551,6 @@ static int __exit coh901318_remove(struct platform_device *pdev) dma_async_device_unregister(&base->dma_memcpy); dma_async_device_unregister(&base->dma_slave); coh901318_pool_destroy(&base->pool); - free_irq(platform_get_irq(pdev, 0), base); - iounmap(base->virtbase); - kfree(base); - release_mem_region(pdev->resource->start, - resource_size(pdev->resource)); return 0; } -- GitLab From b8c24c4aef94b1f0daafb450363fef13a1163780 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:52 -0500 Subject: [PATCH 0719/5711] slob: Define page struct fields used in mm_types.h Define the fields used by slob in mm_types.h and use struct page instead of struct slob_page in slob. This cleans up numerous of typecasts in slob.c and makes readers aware of slob's use of page struct fields. [Also cleans up some bitrot in slob.c. The page struct field layout in slob.c is an old layout and does not match the one in mm_types.h] Reviewed-by: Glauber Costa Acked-by: David Rientjes Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/mm_types.h | 7 ++- mm/slob.c | 95 ++++++++++++++++------------------------ 2 files changed, 42 insertions(+), 60 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index dad95bdd06d7..5922c3452592 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -53,7 +53,7 @@ struct page { struct { union { pgoff_t index; /* Our offset within mapping. */ - void *freelist; /* slub first free object */ + void *freelist; /* slub/slob first free object */ }; union { @@ -81,11 +81,12 @@ struct page { */ atomic_t _mapcount; - struct { + struct { /* SLUB */ unsigned inuse:16; unsigned objects:15; unsigned frozen:1; }; + int units; /* SLOB */ }; atomic_t _count; /* Usage count, see below. */ }; @@ -107,6 +108,8 @@ struct page { short int pobjects; #endif }; + + struct list_head list; /* slobs list of pages */ }; /* Remainder is not double word aligned */ diff --git a/mm/slob.c b/mm/slob.c index 8105be42cad1..30862a2d56a9 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -91,34 +91,13 @@ struct slob_block { }; typedef struct slob_block slob_t; -/* - * We use struct page fields to manage some slob allocation aspects, - * however to avoid the horrible mess in include/linux/mm_types.h, we'll - * just define our own struct page type variant here. - */ -struct slob_page { - union { - struct { - unsigned long flags; /* mandatory */ - atomic_t _count; /* mandatory */ - slobidx_t units; /* free units left in page */ - unsigned long pad[2]; - slob_t *free; /* first free slob_t in page */ - struct list_head list; /* linked list of free pages */ - }; - struct page page; - }; -}; -static inline void struct_slob_page_wrong_size(void) -{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); } - /* * free_slob_page: call before a slob_page is returned to the page allocator. */ -static inline void free_slob_page(struct slob_page *sp) +static inline void free_slob_page(struct page *sp) { - reset_page_mapcount(&sp->page); - sp->page.mapping = NULL; + reset_page_mapcount(sp); + sp->mapping = NULL; } /* @@ -133,44 +112,44 @@ static LIST_HEAD(free_slob_large); /* * is_slob_page: True for all slob pages (false for bigblock pages) */ -static inline int is_slob_page(struct slob_page *sp) +static inline int is_slob_page(struct page *sp) { - return PageSlab((struct page *)sp); + return PageSlab(sp); } -static inline void set_slob_page(struct slob_page *sp) +static inline void set_slob_page(struct page *sp) { - __SetPageSlab((struct page *)sp); + __SetPageSlab(sp); } -static inline void clear_slob_page(struct slob_page *sp) +static inline void clear_slob_page(struct page *sp) { - __ClearPageSlab((struct page *)sp); + __ClearPageSlab(sp); } -static inline struct slob_page *slob_page(const void *addr) +static inline struct page *slob_page(const void *addr) { - return (struct slob_page *)virt_to_page(addr); + return virt_to_page(addr); } /* * slob_page_free: true for pages on free_slob_pages list. */ -static inline int slob_page_free(struct slob_page *sp) +static inline int slob_page_free(struct page *sp) { - return PageSlobFree((struct page *)sp); + return PageSlobFree(sp); } -static void set_slob_page_free(struct slob_page *sp, struct list_head *list) +static void set_slob_page_free(struct page *sp, struct list_head *list) { list_add(&sp->list, list); - __SetPageSlobFree((struct page *)sp); + __SetPageSlobFree(sp); } -static inline void clear_slob_page_free(struct slob_page *sp) +static inline void clear_slob_page_free(struct page *sp) { list_del(&sp->list); - __ClearPageSlobFree((struct page *)sp); + __ClearPageSlobFree(sp); } #define SLOB_UNIT sizeof(slob_t) @@ -267,12 +246,12 @@ static void slob_free_pages(void *b, int order) /* * Allocate a slob block within a given slob_page sp. */ -static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) +static void *slob_page_alloc(struct page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); - for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { + for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur); if (align) { @@ -296,12 +275,12 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) if (prev) set_slob(prev, slob_units(prev), next); else - sp->free = next; + sp->freelist = next; } else { /* fragment */ if (prev) set_slob(prev, slob_units(prev), cur + units); else - sp->free = cur + units; + sp->freelist = cur + units; set_slob(cur + units, avail - units, next); } @@ -320,7 +299,7 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { - struct slob_page *sp; + struct page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; @@ -341,7 +320,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ - if (node != -1 && page_to_nid(&sp->page) != node) + if (node != -1 && page_to_nid(sp) != node) continue; #endif /* Enough room on this page? */ @@ -374,7 +353,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); - sp->free = b; + sp->freelist = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); @@ -392,7 +371,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) */ static void slob_free(void *block, int size) { - struct slob_page *sp; + struct page *sp; slob_t *prev, *next, *b = (slob_t *)block; slobidx_t units; unsigned long flags; @@ -421,7 +400,7 @@ static void slob_free(void *block, int size) if (!slob_page_free(sp)) { /* This slob page is about to become partially free. Easy! */ sp->units = units; - sp->free = b; + sp->freelist = b; set_slob(b, units, (void *)((unsigned long)(b + SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); @@ -441,15 +420,15 @@ static void slob_free(void *block, int size) */ sp->units += units; - if (b < sp->free) { - if (b + units == sp->free) { - units += slob_units(sp->free); - sp->free = slob_next(sp->free); + if (b < (slob_t *)sp->freelist) { + if (b + units == sp->freelist) { + units += slob_units(sp->freelist); + sp->freelist = slob_next(sp->freelist); } - set_slob(b, units, sp->free); - sp->free = b; + set_slob(b, units, sp->freelist); + sp->freelist = b; } else { - prev = sp->free; + prev = sp->freelist; next = slob_next(prev); while (b > next) { prev = next; @@ -522,7 +501,7 @@ EXPORT_SYMBOL(__kmalloc_node); void kfree(const void *block) { - struct slob_page *sp; + struct page *sp; trace_kfree(_RET_IP_, block); @@ -536,14 +515,14 @@ void kfree(const void *block) unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); } else - put_page(&sp->page); + put_page(sp); } EXPORT_SYMBOL(kfree); /* can't use ksize for kmem_cache_alloc memory, only kmalloc */ size_t ksize(const void *block) { - struct slob_page *sp; + struct page *sp; BUG_ON(!block); if (unlikely(block == ZERO_SIZE_PTR)) @@ -555,7 +534,7 @@ size_t ksize(const void *block) unsigned int *m = (unsigned int *)(block - align); return SLOB_UNITS(*m) * SLOB_UNIT; } else - return sp->page.private; + return sp->private; } EXPORT_SYMBOL(ksize); -- GitLab From 690d5777392180fdc05a82c0c7979e50e8d93de8 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:53 -0500 Subject: [PATCH 0720/5711] slob: No need to zero mapping since it is no longer in use Reviewed-by: Joonsoo Kim Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slob.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/slob.c b/mm/slob.c index 30862a2d56a9..74c3bb25f640 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -97,7 +97,6 @@ typedef struct slob_block slob_t; static inline void free_slob_page(struct page *sp) { reset_page_mapcount(sp); - sp->mapping = NULL; } /* -- GitLab From b5568280c9b9162b384be9d447013b74d682d4b3 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:54 -0500 Subject: [PATCH 0721/5711] slob: Remove various small accessors Those have become so simple that they are no longer needed. Reviewed-by: Joonsoo Kim Acked-by: David Rientjes signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slob.c | 49 +++++++++---------------------------------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/mm/slob.c b/mm/slob.c index 74c3bb25f640..c85265d22e08 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -91,14 +91,6 @@ struct slob_block { }; typedef struct slob_block slob_t; -/* - * free_slob_page: call before a slob_page is returned to the page allocator. - */ -static inline void free_slob_page(struct page *sp) -{ - reset_page_mapcount(sp); -} - /* * All partially free slob pages go on these lists. */ @@ -108,29 +100,6 @@ static LIST_HEAD(free_slob_small); static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); -/* - * is_slob_page: True for all slob pages (false for bigblock pages) - */ -static inline int is_slob_page(struct page *sp) -{ - return PageSlab(sp); -} - -static inline void set_slob_page(struct page *sp) -{ - __SetPageSlab(sp); -} - -static inline void clear_slob_page(struct page *sp) -{ - __ClearPageSlab(sp); -} - -static inline struct page *slob_page(const void *addr) -{ - return virt_to_page(addr); -} - /* * slob_page_free: true for pages on free_slob_pages list. */ @@ -347,8 +316,8 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; - sp = slob_page(b); - set_slob_page(sp); + sp = virt_to_page(b); + __SetPageSlab(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); @@ -380,7 +349,7 @@ static void slob_free(void *block, int size) return; BUG_ON(!size); - sp = slob_page(block); + sp = virt_to_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); @@ -390,8 +359,8 @@ static void slob_free(void *block, int size) if (slob_page_free(sp)) clear_slob_page_free(sp); spin_unlock_irqrestore(&slob_lock, flags); - clear_slob_page(sp); - free_slob_page(sp); + __ClearPageSlab(sp); + reset_page_mapcount(sp); slob_free_pages(b, 0); return; } @@ -508,8 +477,8 @@ void kfree(const void *block) return; kmemleak_free(block); - sp = slob_page(block); - if (is_slob_page(sp)) { + sp = virt_to_page(block); + if (PageSlab(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); @@ -527,8 +496,8 @@ size_t ksize(const void *block) if (unlikely(block == ZERO_SIZE_PTR)) return 0; - sp = slob_page(block); - if (is_slob_page(sp)) { + sp = virt_to_page(block); + if (PageSlab(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); return SLOB_UNITS(*m) * SLOB_UNIT; -- GitLab From e571b0ad3495be5793e54e21cd244c4545c49d88 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:55 -0500 Subject: [PATCH 0722/5711] slab: Use page struct fields instead of casting Add fields to the page struct so that it is properly documented that slab overlays the lru fields. This cleans up some casts in slab. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/mm_types.h | 4 ++++ mm/slab.c | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 5922c3452592..680a5e4e8cd5 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -110,6 +110,10 @@ struct page { }; struct list_head list; /* slobs list of pages */ + struct { /* slab fields */ + struct kmem_cache *slab_cache; + struct slab *slab_page; + }; }; /* Remainder is not double word aligned */ diff --git a/mm/slab.c b/mm/slab.c index e901a36e2520..af05147d7abd 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -496,25 +496,25 @@ static bool slab_max_order_set __initdata; */ static inline void page_set_cache(struct page *page, struct kmem_cache *cache) { - page->lru.next = (struct list_head *)cache; + page->slab_cache = cache; } static inline struct kmem_cache *page_get_cache(struct page *page) { page = compound_head(page); BUG_ON(!PageSlab(page)); - return (struct kmem_cache *)page->lru.next; + return page->slab_cache; } static inline void page_set_slab(struct page *page, struct slab *slab) { - page->lru.prev = (struct list_head *)slab; + page->slab_page = slab; } static inline struct slab *page_get_slab(struct page *page) { BUG_ON(!PageSlab(page)); - return (struct slab *)page->lru.prev; + return page->slab_page; } static inline struct kmem_cache *virt_to_cache(const void *obj) -- GitLab From 350260889b251821e770573dfd65cd851b4ef781 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:56 -0500 Subject: [PATCH 0723/5711] slab: Remove some accessors Those are rather trivial now and its better to see inline what is really going on. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slab.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index af05147d7abd..28a8f7d29d4a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -489,16 +489,6 @@ EXPORT_SYMBOL(slab_buffer_size); static int slab_max_order = SLAB_MAX_ORDER_LO; static bool slab_max_order_set __initdata; -/* - * Functions for storing/retrieving the cachep and or slab from the page - * allocator. These are used to find the slab an obj belongs to. With kfree(), - * these are used to find the cache which an obj belongs to. - */ -static inline void page_set_cache(struct page *page, struct kmem_cache *cache) -{ - page->slab_cache = cache; -} - static inline struct kmem_cache *page_get_cache(struct page *page) { page = compound_head(page); @@ -506,27 +496,18 @@ static inline struct kmem_cache *page_get_cache(struct page *page) return page->slab_cache; } -static inline void page_set_slab(struct page *page, struct slab *slab) -{ - page->slab_page = slab; -} - -static inline struct slab *page_get_slab(struct page *page) -{ - BUG_ON(!PageSlab(page)); - return page->slab_page; -} - static inline struct kmem_cache *virt_to_cache(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_cache(page); + return page->slab_cache; } static inline struct slab *virt_to_slab(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_slab(page); + + VM_BUG_ON(!PageSlab(page)); + return page->slab_page; } static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab, @@ -2918,8 +2899,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab, nr_pages <<= cache->gfporder; do { - page_set_cache(page, cache); - page_set_slab(page, slab); + page->slab_cache = cache; + page->slab_page = slab; page++; } while (--nr_pages); } @@ -3057,7 +3038,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, kfree_debugcheck(objp); page = virt_to_head_page(objp); - slabp = page_get_slab(page); + slabp = page->slab_page; if (cachep->flags & SLAB_RED_ZONE) { verify_redzone_free(cachep, objp); @@ -3261,7 +3242,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, struct slab *slabp; unsigned objnr; - slabp = page_get_slab(virt_to_head_page(objp)); + slabp = virt_to_head_page(objp)->slab_page; objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE; } -- GitLab From 3b0efdfa1e719303536c04d9abca43abeb40f80a Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:57 -0500 Subject: [PATCH 0724/5711] mm, sl[aou]b: Extract common fields from struct kmem_cache Define a struct that describes common fields used in all slab allocators. A slab allocator either uses the common definition (like SLOB) or is required to provide members of kmem_cache with the definition given. After that it will be possible to share code that only operates on those fields of kmem_cache. The patch basically takes the slob definition of kmem cache and uses the field namees for the other allocators. It also standardizes the names used for basic object lengths in allocators: object_size Struct size specified at kmem_cache_create. Basically the payload expected to be used by the subsystem. size The size of memory allocator for each object. This size is larger than object_size and includes padding, alignment and extra metadata for each object (f.e. for debugging and rcu). Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slab.h | 24 ++++++++ include/linux/slab_def.h | 10 ++-- include/linux/slub_def.h | 2 +- mm/slab.c | 117 +++++++++++++++++++-------------------- mm/slob.c | 9 +-- mm/slub.c | 80 +++++++++++++------------- 6 files changed, 130 insertions(+), 112 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 67d5d94b783a..0dd2dfa7beca 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -92,6 +92,30 @@ #define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \ (unsigned long)ZERO_SIZE_PTR) +/* + * Common fields provided in kmem_cache by all slab allocators + * This struct is either used directly by the allocator (SLOB) + * or the allocator must include definitions for all fields + * provided in kmem_cache_common in their definition of kmem_cache. + * + * Once we can do anonymous structs (C11 standard) we could put a + * anonymous struct definition in these allocators so that the + * separate allocations in the kmem_cache structure of SLAB and + * SLUB is no longer needed. + */ +#ifdef CONFIG_SLOB +struct kmem_cache { + unsigned int object_size;/* The original size of the object */ + unsigned int size; /* The aligned/padded/added on size */ + unsigned int align; /* Alignment as calculated */ + unsigned long flags; /* Active flags on the slab */ + const char *name; /* Slab name for sysfs */ + int refcount; /* Use counter */ + void (*ctor)(void *); /* Called on object slot creation */ + struct list_head list; /* List of all slab caches on the system */ +}; +#endif + /* * struct kmem_cache related prototypes */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index fbd1117fdfde..1d93f27d81de 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -27,7 +27,7 @@ struct kmem_cache { unsigned int limit; unsigned int shared; - unsigned int buffer_size; + unsigned int size; u32 reciprocal_buffer_size; /* 2) touched by every alloc & free from the backend */ @@ -52,7 +52,10 @@ struct kmem_cache { /* 4) cache creation/removal */ const char *name; - struct list_head next; + struct list_head list; + int refcount; + int object_size; + int align; /* 5) statistics */ #ifdef CONFIG_DEBUG_SLAB @@ -73,12 +76,11 @@ struct kmem_cache { /* * If debugging is enabled, then the allocator can add additional - * fields and/or padding to every object. buffer_size contains the total + * fields and/or padding to every object. size contains the total * object size including these internal fields, the following two * variables contain the offset to the user object and its size. */ int obj_offset; - int obj_size; #endif /* CONFIG_DEBUG_SLAB */ /* 6) per-cpu/per-node data, touched during every alloc/free */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index ebdcf4ba42ee..df448adb7283 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -82,7 +82,7 @@ struct kmem_cache { unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ - int objsize; /* The size of an object without meta data */ + int object_size; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ int cpu_partial; /* Number of per cpu partial objects to keep around */ struct kmem_cache_order_objects oo; diff --git a/mm/slab.c b/mm/slab.c index 28a8f7d29d4a..e2b3907b7b0c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -424,8 +424,8 @@ static void kmem_list3_init(struct kmem_list3 *parent) * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1: * redzone word. * cachep->obj_offset: The real object. - * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] - * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address + * cachep->size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->size - 1* BYTES_PER_WORD: last caller address * [BYTES_PER_WORD long] */ static int obj_offset(struct kmem_cache *cachep) @@ -435,7 +435,7 @@ static int obj_offset(struct kmem_cache *cachep) static int obj_size(struct kmem_cache *cachep) { - return cachep->obj_size; + return cachep->object_size; } static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp) @@ -449,23 +449,23 @@ static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long long *)(objp + cachep->buffer_size - + return (unsigned long long *)(objp + cachep->size - sizeof(unsigned long long) - REDZONE_ALIGN); - return (unsigned long long *) (objp + cachep->buffer_size - + return (unsigned long long *) (objp + cachep->size - sizeof(unsigned long long)); } static void **dbg_userword(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD); + return (void **)(objp + cachep->size - BYTES_PER_WORD); } #else #define obj_offset(x) 0 -#define obj_size(cachep) (cachep->buffer_size) +#define obj_size(cachep) (cachep->size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) @@ -475,7 +475,7 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) #ifdef CONFIG_TRACING size_t slab_buffer_size(struct kmem_cache *cachep) { - return cachep->buffer_size; + return cachep->size; } EXPORT_SYMBOL(slab_buffer_size); #endif @@ -513,13 +513,13 @@ static inline struct slab *virt_to_slab(const void *obj) static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab, unsigned int idx) { - return slab->s_mem + cache->buffer_size * idx; + return slab->s_mem + cache->size * idx; } /* - * We want to avoid an expensive divide : (offset / cache->buffer_size) - * Using the fact that buffer_size is a constant for a particular cache, - * we can replace (offset / cache->buffer_size) by + * We want to avoid an expensive divide : (offset / cache->size) + * Using the fact that size is a constant for a particular cache, + * we can replace (offset / cache->size) by * reciprocal_divide(offset, cache->reciprocal_buffer_size) */ static inline unsigned int obj_to_index(const struct kmem_cache *cache, @@ -565,7 +565,7 @@ static struct kmem_cache cache_cache = { .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, - .buffer_size = sizeof(struct kmem_cache), + .size = sizeof(struct kmem_cache), .name = "kmem_cache", }; @@ -1134,7 +1134,7 @@ static int init_cache_nodelists_node(int node) struct kmem_list3 *l3; const int memsize = sizeof(struct kmem_list3); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { /* * Set up the size64 kmemlist for cpu before we can * begin anything. Make sure some other cpu on this @@ -1172,7 +1172,7 @@ static void __cpuinit cpuup_canceled(long cpu) int node = cpu_to_mem(cpu); const struct cpumask *mask = cpumask_of_node(node); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { struct array_cache *nc; struct array_cache *shared; struct array_cache **alien; @@ -1222,7 +1222,7 @@ free_array_cache: * the respective cache's slabs, now we can go ahead and * shrink each nodelist to its limit. */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { l3 = cachep->nodelists[node]; if (!l3) continue; @@ -1251,7 +1251,7 @@ static int __cpuinit cpuup_prepare(long cpu) * Now we can go ahead with allocating the shared arrays and * array caches */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { struct array_cache *nc; struct array_cache *shared = NULL; struct array_cache **alien = NULL; @@ -1383,7 +1383,7 @@ static int __meminit drain_cache_nodelists_node(int node) struct kmem_cache *cachep; int ret = 0; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { struct kmem_list3 *l3; l3 = cachep->nodelists[node]; @@ -1526,7 +1526,7 @@ void __init kmem_cache_init(void) /* 1) create the cache_cache */ INIT_LIST_HEAD(&cache_chain); - list_add(&cache_cache.next, &cache_chain); + list_add(&cache_cache.list, &cache_chain); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; @@ -1534,18 +1534,16 @@ void __init kmem_cache_init(void) /* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + + cache_cache.size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + nr_node_ids * sizeof(struct kmem_list3 *); -#if DEBUG - cache_cache.obj_size = cache_cache.buffer_size; -#endif - cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, + cache_cache.object_size = cache_cache.size; + cache_cache.size = ALIGN(cache_cache.size, cache_line_size()); cache_cache.reciprocal_buffer_size = - reciprocal_value(cache_cache.buffer_size); + reciprocal_value(cache_cache.size); for (order = 0; order < MAX_ORDER; order++) { - cache_estimate(order, cache_cache.buffer_size, + cache_estimate(order, cache_cache.size, cache_line_size(), 0, &left_over, &cache_cache.num); if (cache_cache.num) break; @@ -1671,7 +1669,7 @@ void __init kmem_cache_init_late(void) /* 6) resize the head arrays to their final sizes */ mutex_lock(&cache_chain_mutex); - list_for_each_entry(cachep, &cache_chain, next) + list_for_each_entry(cachep, &cache_chain, list) if (enable_cpucache(cachep, GFP_NOWAIT)) BUG(); mutex_unlock(&cache_chain_mutex); @@ -1724,7 +1722,7 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid) "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n", nodeid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, order: %d\n", - cachep->name, cachep->buffer_size, cachep->gfporder); + cachep->name, cachep->size, cachep->gfporder); for_each_online_node(node) { unsigned long active_objs = 0, num_objs = 0, free_objects = 0; @@ -2028,10 +2026,10 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slab if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if (cachep->buffer_size % PAGE_SIZE == 0 && + if (cachep->size % PAGE_SIZE == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -2281,7 +2279,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, mutex_lock(&cache_chain_mutex); } - list_for_each_entry(pc, &cache_chain, next) { + list_for_each_entry(pc, &cache_chain, list) { char tmp; int res; @@ -2294,7 +2292,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (res) { printk(KERN_ERR "SLAB: cache with size %d has lost its name\n", - pc->buffer_size); + pc->size); continue; } @@ -2399,8 +2397,9 @@ kmem_cache_create (const char *name, size_t size, size_t align, goto oops; cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; + cachep->object_size = size; + cachep->align = align; #if DEBUG - cachep->obj_size = size; /* * Both debugging options require word-alignment which is calculated @@ -2423,7 +2422,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { + && cachep->object_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { cachep->obj_offset += PAGE_SIZE - ALIGN(size, align); size = PAGE_SIZE; } @@ -2492,7 +2491,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, cachep->gfpflags = 0; if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA)) cachep->gfpflags |= GFP_DMA; - cachep->buffer_size = size; + cachep->size = size; cachep->reciprocal_buffer_size = reciprocal_value(size); if (flags & CFLGS_OFF_SLAB) { @@ -2526,7 +2525,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, } /* cache setup completed, link it into the list */ - list_add(&cachep->next, &cache_chain); + list_add(&cachep->list, &cache_chain); oops: if (!cachep && (flags & SLAB_PANIC)) panic("kmem_cache_create(): failed to create slab `%s'\n", @@ -2721,10 +2720,10 @@ void kmem_cache_destroy(struct kmem_cache *cachep) /* * the chain is never empty, cache_cache is never destroyed */ - list_del(&cachep->next); + list_del(&cachep->list); if (__cache_shrink(cachep)) { slab_error(cachep, "Can't free all objects"); - list_add(&cachep->next, &cache_chain); + list_add(&cachep->list, &cache_chain); mutex_unlock(&cache_chain_mutex); put_online_cpus(); return; @@ -2821,10 +2820,10 @@ static void cache_init_objs(struct kmem_cache *cachep, slab_error(cachep, "constructor overwrote the" " start of an object"); } - if ((cachep->buffer_size % PAGE_SIZE) == 0 && + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); #else if (cachep->ctor) cachep->ctor(objp); @@ -3058,10 +3057,10 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, #endif if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { + if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { store_stackinfo(cachep, objp, (unsigned long)caller); kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); } else { poison_obj(cachep, objp, POISON_FREE); } @@ -3211,9 +3210,9 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, return objp; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -3243,7 +3242,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, unsigned objnr; slabp = virt_to_head_page(objp)->slab_page; - objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; + objnr = (unsigned)(objp - slabp->s_mem) / cachep->size; slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE; } #endif @@ -3747,7 +3746,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); trace_kmem_cache_alloc(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, flags); + obj_size(cachep), cachep->size, flags); return ret; } @@ -3775,7 +3774,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) __builtin_return_address(0)); trace_kmem_cache_alloc_node(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, + obj_size(cachep), cachep->size, flags, nodeid); return ret; @@ -3857,7 +3856,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, ret = __cache_alloc(cachep, flags, caller); trace_kmalloc((unsigned long) caller, ret, - size, cachep->buffer_size, flags); + size, cachep->size, flags); return ret; } @@ -4011,7 +4010,7 @@ static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp) return 0; fail: - if (!cachep->next.next) { + if (!cachep->list.next) { /* Cache is not active yet. Roll back what we did */ node--; while (node >= 0) { @@ -4105,13 +4104,13 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * The numbers are guessed, we should auto-tune as described by * Bonwick. */ - if (cachep->buffer_size > 131072) + if (cachep->size > 131072) limit = 1; - else if (cachep->buffer_size > PAGE_SIZE) + else if (cachep->size > PAGE_SIZE) limit = 8; - else if (cachep->buffer_size > 1024) + else if (cachep->size > 1024) limit = 24; - else if (cachep->buffer_size > 256) + else if (cachep->size > 256) limit = 54; else limit = 120; @@ -4126,7 +4125,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * to a larger limit. Thus disabled by default. */ shared = 0; - if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1) + if (cachep->size <= PAGE_SIZE && num_possible_cpus() > 1) shared = 8; #if DEBUG @@ -4196,7 +4195,7 @@ static void cache_reap(struct work_struct *w) /* Give up. Setup the next iteration. */ goto out; - list_for_each_entry(searchp, &cache_chain, next) { + list_for_each_entry(searchp, &cache_chain, list) { check_irq_on(); /* @@ -4289,7 +4288,7 @@ static void s_stop(struct seq_file *m, void *p) static int s_show(struct seq_file *m, void *p) { - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; @@ -4345,7 +4344,7 @@ static int s_show(struct seq_file *m, void *p) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", - name, active_objs, num_objs, cachep->buffer_size, + name, active_objs, num_objs, cachep->size, cachep->num, (1 << cachep->gfporder)); seq_printf(m, " : tunables %4u %4u %4u", cachep->limit, cachep->batchcount, cachep->shared); @@ -4437,7 +4436,7 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, /* Find the cache in the chain of caches. */ mutex_lock(&cache_chain_mutex); res = -EINVAL; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &cache_chain, list) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4513,7 +4512,7 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s) int i; if (n[0] == n[1]) return; - for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) { + for (i = 0, p = s->s_mem; i < c->num; i++, p += c->size) { if (slab_bufctl(s)[i] != BUFCTL_ACTIVE) continue; if (!add_caller(n, (unsigned long)*dbg_userword(c, p))) diff --git a/mm/slob.c b/mm/slob.c index c85265d22e08..95d1c7dd88e0 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -506,13 +506,6 @@ size_t ksize(const void *block) } EXPORT_SYMBOL(ksize); -struct kmem_cache { - unsigned int size, align; - unsigned long flags; - const char *name; - void (*ctor)(void *); -}; - struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { @@ -523,7 +516,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, if (c) { c->name = name; - c->size = size; + c->size = c->object_size; if (flags & SLAB_DESTROY_BY_RCU) { /* leave room for rcu footer at the end of object */ c->size += sizeof(struct slob_rcu); diff --git a/mm/slub.c b/mm/slub.c index 2de3c996f327..797271f5afb8 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -311,7 +311,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s) * and whatever may come after it. */ if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->objsize; + return s->object_size; #endif /* @@ -609,11 +609,11 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) if (p > addr + 16) print_section("Bytes b4 ", p - 16, 16); - print_section("Object ", p, min_t(unsigned long, s->objsize, + print_section("Object ", p, min_t(unsigned long, s->object_size, PAGE_SIZE)); if (s->flags & SLAB_RED_ZONE) - print_section("Redzone ", p + s->objsize, - s->inuse - s->objsize); + print_section("Redzone ", p + s->object_size, + s->inuse - s->object_size); if (s->offset) off = s->offset + sizeof(void *); @@ -655,12 +655,12 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) u8 *p = object; if (s->flags & __OBJECT_POISON) { - memset(p, POISON_FREE, s->objsize - 1); - p[s->objsize - 1] = POISON_END; + memset(p, POISON_FREE, s->object_size - 1); + p[s->object_size - 1] = POISON_END; } if (s->flags & SLAB_RED_ZONE) - memset(p + s->objsize, val, s->inuse - s->objsize); + memset(p + s->object_size, val, s->inuse - s->object_size); } static void restore_bytes(struct kmem_cache *s, char *message, u8 data, @@ -705,10 +705,10 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * Poisoning uses 0x6b (POISON_FREE) and the last byte is * 0xa5 (POISON_END) * - * object + s->objsize + * object + s->object_size * Padding to reach word boundary. This is also used for Redzoning. * Padding is extended by another word if Redzoning is enabled and - * objsize == inuse. + * object_size == inuse. * * We fill with 0xbb (RED_INACTIVE) for inactive objects and with * 0xcc (RED_ACTIVE) for objects in use. @@ -727,7 +727,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * object + s->size * Nothing is used beyond s->size. * - * If slabcaches are merged then the objsize and inuse boundaries are mostly + * If slabcaches are merged then the object_size and inuse boundaries are mostly * ignored. And therefore no slab options that rely on these boundaries * may be used with merged slabcaches. */ @@ -787,25 +787,25 @@ static int check_object(struct kmem_cache *s, struct page *page, void *object, u8 val) { u8 *p = object; - u8 *endobject = object + s->objsize; + u8 *endobject = object + s->object_size; if (s->flags & SLAB_RED_ZONE) { if (!check_bytes_and_report(s, page, object, "Redzone", - endobject, val, s->inuse - s->objsize)) + endobject, val, s->inuse - s->object_size)) return 0; } else { - if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) { + if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) { check_bytes_and_report(s, page, p, "Alignment padding", - endobject, POISON_INUSE, s->inuse - s->objsize); + endobject, POISON_INUSE, s->inuse - s->object_size); } } if (s->flags & SLAB_POISON) { if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) && (!check_bytes_and_report(s, page, p, "Poison", p, - POISON_FREE, s->objsize - 1) || + POISON_FREE, s->object_size - 1) || !check_bytes_and_report(s, page, p, "Poison", - p + s->objsize - 1, POISON_END, 1))) + p + s->object_size - 1, POISON_END, 1))) return 0; /* * check_pad_bytes cleans up on its own. @@ -926,7 +926,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object, page->freelist); if (!alloc) - print_section("Object ", (void *)object, s->objsize); + print_section("Object ", (void *)object, s->object_size); dump_stack(); } @@ -942,14 +942,14 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) lockdep_trace_alloc(flags); might_sleep_if(flags & __GFP_WAIT); - return should_failslab(s->objsize, flags, s->flags); + return should_failslab(s->object_size, flags, s->flags); } static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; kmemcheck_slab_alloc(s, flags, object, slab_ksize(s)); - kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags); + kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags); } static inline void slab_free_hook(struct kmem_cache *s, void *x) @@ -966,13 +966,13 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) unsigned long flags; local_irq_save(flags); - kmemcheck_slab_free(s, x, s->objsize); - debug_check_no_locks_freed(x, s->objsize); + kmemcheck_slab_free(s, x, s->object_size); + debug_check_no_locks_freed(x, s->object_size); local_irq_restore(flags); } #endif if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(x, s->objsize); + debug_check_no_obj_freed(x, s->object_size); } /* @@ -1207,7 +1207,7 @@ out: __setup("slub_debug", setup_slub_debug); -static unsigned long kmem_cache_flags(unsigned long objsize, +static unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1237,7 +1237,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page, static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} static inline void remove_full(struct kmem_cache *s, struct page *page) {} -static inline unsigned long kmem_cache_flags(unsigned long objsize, +static inline unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -2098,10 +2098,10 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) "SLUB: Unable to allocate memory on node %d (gfp=0x%x)\n", nid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, buffer size: %d, " - "default order: %d, min order: %d\n", s->name, s->objsize, + "default order: %d, min order: %d\n", s->name, s->object_size, s->size, oo_order(s->oo), oo_order(s->min)); - if (oo_order(s->min) > get_order(s->objsize)) + if (oo_order(s->min) > get_order(s->object_size)) printk(KERN_WARNING " %s debugging increased min order, use " "slub_debug=O to disable.\n", s->name); @@ -2374,7 +2374,7 @@ redo: } if (unlikely(gfpflags & __GFP_ZERO) && object) - memset(object, 0, s->objsize); + memset(object, 0, s->object_size); slab_post_alloc_hook(s, gfpflags, object); @@ -2385,7 +2385,7 @@ void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) { void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); - trace_kmem_cache_alloc(_RET_IP_, ret, s->objsize, s->size, gfpflags); + trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags); return ret; } @@ -2415,7 +2415,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); trace_kmem_cache_alloc_node(_RET_IP_, ret, - s->objsize, s->size, gfpflags, node); + s->object_size, s->size, gfpflags, node); return ret; } @@ -2910,7 +2910,7 @@ static void set_min_partial(struct kmem_cache *s, unsigned long min) static int calculate_sizes(struct kmem_cache *s, int forced_order) { unsigned long flags = s->flags; - unsigned long size = s->objsize; + unsigned long size = s->object_size; unsigned long align = s->align; int order; @@ -2939,7 +2939,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * end of the object and the free pointer. If not then add an * additional word to have some bytes to store Redzone information. */ - if ((flags & SLAB_RED_ZONE) && size == s->objsize) + if ((flags & SLAB_RED_ZONE) && size == s->object_size) size += sizeof(void *); #endif @@ -2987,7 +2987,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * user specified and the dynamic determination of cache line size * on bootup. */ - align = calculate_alignment(flags, align, s->objsize); + align = calculate_alignment(flags, align, s->object_size); s->align = align; /* @@ -3035,7 +3035,7 @@ static int kmem_cache_open(struct kmem_cache *s, memset(s, 0, kmem_size); s->name = name; s->ctor = ctor; - s->objsize = size; + s->object_size = size; s->align = align; s->flags = kmem_cache_flags(size, flags, name, ctor); s->reserved = 0; @@ -3050,7 +3050,7 @@ static int kmem_cache_open(struct kmem_cache *s, * Disable debugging flags that store metadata if the min slab * order increased. */ - if (get_order(s->size) > get_order(s->objsize)) { + if (get_order(s->size) > get_order(s->object_size)) { s->flags &= ~DEBUG_METADATA_FLAGS; s->offset = 0; if (!calculate_sizes(s, -1)) @@ -3124,7 +3124,7 @@ error: */ unsigned int kmem_cache_size(struct kmem_cache *s) { - return s->objsize; + return s->object_size; } EXPORT_SYMBOL(kmem_cache_size); @@ -3853,11 +3853,11 @@ void __init kmem_cache_init(void) if (s && s->size) { char *name = kasprintf(GFP_NOWAIT, - "dma-kmalloc-%d", s->objsize); + "dma-kmalloc-%d", s->object_size); BUG_ON(!name); kmalloc_dma_caches[i] = create_kmalloc_cache(name, - s->objsize, SLAB_CACHE_DMA); + s->object_size, SLAB_CACHE_DMA); } } #endif @@ -3951,7 +3951,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, * Adjust the object sizes so that we clear * the complete object on kzalloc. */ - s->objsize = max(s->objsize, (int)size); + s->object_size = max(s->object_size, (int)size); s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); if (sysfs_slab_alias(s, name)) { @@ -4634,7 +4634,7 @@ SLAB_ATTR_RO(align); static ssize_t object_size_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->objsize); + return sprintf(buf, "%d\n", s->object_size); } SLAB_ATTR_RO(object_size); @@ -5438,7 +5438,7 @@ __initcall(slab_sysfs_init); static void print_slabinfo_header(struct seq_file *m) { seq_puts(m, "slabinfo - version: 2.1\n"); - seq_puts(m, "# name " + seq_puts(m, "# name " " "); seq_puts(m, " : tunables "); seq_puts(m, " : slabdata "); -- GitLab From 8c138bc00925521c4e764269db3a903bd2a51592 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 13 Jun 2012 10:24:58 -0500 Subject: [PATCH 0725/5711] slab: Get rid of obj_size macro The size of the slab object is frequently needed. Since we now have a size field directly in the kmem_cache structure there is no need anymore of the obj_size macro/function. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slab.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e2b3907b7b0c..fc4a77446700 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -433,11 +433,6 @@ static int obj_offset(struct kmem_cache *cachep) return cachep->obj_offset; } -static int obj_size(struct kmem_cache *cachep) -{ - return cachep->object_size; -} - static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); @@ -465,7 +460,6 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) #else #define obj_offset(x) 0 -#define obj_size(cachep) (cachep->size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) @@ -1853,7 +1847,7 @@ static void kmem_rcu_free(struct rcu_head *head) static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, unsigned long caller) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)]; @@ -1885,7 +1879,7 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = &((char *)addr)[obj_offset(cachep)]; memset(addr, val, size); @@ -1945,7 +1939,7 @@ static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines) printk("\n"); } realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size && lines; i += 16, lines--) { int limit; limit = 16; @@ -1962,7 +1956,7 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) int lines = 0; realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size; i++) { char exp = POISON_FREE; @@ -3265,7 +3259,7 @@ static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) if (cachep == &cache_cache) return false; - return should_failslab(obj_size(cachep), flags, cachep->flags); + return should_failslab(cachep->object_size, flags, cachep->flags); } static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) @@ -3525,14 +3519,14 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, out: local_irq_restore(save_flags); ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller); - kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags, flags); if (likely(ptr)) - kmemcheck_slab_alloc(cachep, flags, ptr, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && ptr)) - memset(ptr, 0, obj_size(cachep)); + memset(ptr, 0, cachep->object_size); return ptr; } @@ -3587,15 +3581,15 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) objp = __do_cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller); - kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags, flags); prefetchw(objp); if (likely(objp)) - kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && objp)) - memset(objp, 0, obj_size(cachep)); + memset(objp, 0, cachep->object_size); return objp; } @@ -3711,7 +3705,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, kmemleak_free_recursive(objp, cachep->flags); objp = cache_free_debugcheck(cachep, objp, caller); - kmemcheck_slab_free(cachep, objp, obj_size(cachep)); + kmemcheck_slab_free(cachep, objp, cachep->object_size); /* * Skip calling cache_free_alien() when the platform is not numa. @@ -3746,7 +3740,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); trace_kmem_cache_alloc(_RET_IP_, ret, - obj_size(cachep), cachep->size, flags); + cachep->object_size, cachep->size, flags); return ret; } @@ -3774,7 +3768,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) __builtin_return_address(0)); trace_kmem_cache_alloc_node(_RET_IP_, ret, - obj_size(cachep), cachep->size, + cachep->object_size, cachep->size, flags, nodeid); return ret; @@ -3896,9 +3890,9 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) unsigned long flags; local_irq_save(flags); - debug_check_no_locks_freed(objp, obj_size(cachep)); + debug_check_no_locks_freed(objp, cachep->size); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(objp, obj_size(cachep)); + debug_check_no_obj_freed(objp, cachep->object_size); __cache_free(cachep, objp, __builtin_return_address(0)); local_irq_restore(flags); @@ -3927,8 +3921,9 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); - debug_check_no_locks_freed(objp, obj_size(c)); - debug_check_no_obj_freed(objp, obj_size(c)); + debug_check_no_locks_freed(objp, c->object_size); + + debug_check_no_obj_freed(objp, c->object_size); __cache_free(c, (void *)objp, __builtin_return_address(0)); local_irq_restore(flags); } @@ -3936,7 +3931,7 @@ EXPORT_SYMBOL(kfree); unsigned int kmem_cache_size(struct kmem_cache *cachep) { - return obj_size(cachep); + return cachep->object_size; } EXPORT_SYMBOL(kmem_cache_size); @@ -4657,6 +4652,6 @@ size_t ksize(const void *objp) if (unlikely(objp == ZERO_SIZE_PTR)) return 0; - return obj_size(virt_to_cache(objp)); + return virt_to_cache(objp)->object_size; } EXPORT_SYMBOL(ksize); -- GitLab From 666d1d8ad201803862514317c17695925e61316b Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 13 Jun 2012 23:03:56 -0400 Subject: [PATCH 0726/5711] GFS2: Combine functions get_local_rgrp and gfs2_inplace_reserve This function combines rgrp functions get_local_rgrp and gfs2_inplace_reserve so that the double retry loop is gone. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 82 ++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3c6f7ed16a3b..e53d0a1c234f 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1207,25 +1207,30 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip } /** - * get_local_rgrp - Choose and lock a rgrp for allocation + * gfs2_inplace_reserve - Reserve space in the filesystem * @ip: the inode to reserve space for - * @last_unlinked: the last unlinked block - * - * Try to acquire rgrp in way which avoids contending with others. + * @requested: the number of blocks to be reserved * * Returns: errno */ -static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) +int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_rgrpd *rgd, *begin = NULL; struct gfs2_blkreserv *rs = ip->i_res; - int error, rg_locked, flags = LM_FLAG_TRY; + int error = 0, rg_locked, flags = LM_FLAG_TRY; + u64 last_unlinked = NO_BLOCK; int loops = 0; if (sdp->sd_args.ar_rgrplvb) flags |= GL_SKIP; + rs = ip->i_res; + rs->rs_requested = requested; + if (gfs2_assert_warn(sdp, requested)) { + error = -EINVAL; + goto out; + } if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) rgd = begin = ip->i_rgd; @@ -1263,63 +1268,34 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) if (rgd->rd_flags & GFS2_RDF_CHECK) { if (sdp->sd_args.ar_rgrplvb) gfs2_rgrp_bh_get(rgd); - try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); + try_rgrp_unlink(rgd, &last_unlinked, + ip->i_no_addr); } if (!rg_locked) gfs2_glock_dq_uninit(&rs->rs_rgd_gh); /* fall through */ case GLR_TRYFAILED: rgd = gfs2_rgrpd_get_next(rgd); - if (rgd == begin) { - flags &= ~LM_FLAG_TRY; - loops++; - } + if (rgd != begin) /* If we didn't wrap */ + break; + + flags &= ~LM_FLAG_TRY; + loops++; + /* Check that fs hasn't grown if writing to rindex */ + if (ip == GFS2_I(sdp->sd_rindex) && + !sdp->sd_rindex_uptodate) { + error = gfs2_ri_update(ip); + if (error) + goto out; + } else if (loops == 2) + /* Flushing the log may release space */ + gfs2_log_flush(sdp, NULL); break; default: - return error; + goto out; } } - - return -ENOSPC; -} - -/** - * gfs2_inplace_reserve - Reserve space in the filesystem - * @ip: the inode to reserve space for - * @requested: the number of blocks to be reserved - * - * Returns: errno - */ - -int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) -{ - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_blkreserv *rs; - int error = 0; - u64 last_unlinked = NO_BLOCK; - int tries = 0; - - rs = ip->i_res; - rs->rs_requested = requested; - if (gfs2_assert_warn(sdp, requested)) { - error = -EINVAL; - goto out; - } - - do { - error = get_local_rgrp(ip, &last_unlinked); - if (error != -ENOSPC) - break; - /* Check that fs hasn't grown if writing to rindex */ - if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) { - error = gfs2_ri_update(ip); - if (error) - break; - continue; - } - /* Flushing the log may release space */ - gfs2_log_flush(sdp, NULL); - } while (tries++ < 3); + error = -ENOSPC; out: if (error) -- GitLab From 6b03b13336ee5d8da7bda8799c9ed990e3daedcc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Jun 2012 13:24:42 +0300 Subject: [PATCH 0727/5711] usb: otg: twl: add missing IRQF_ONESHOT this patch fixes the following warning: [ 2.825378] genirq: Threaded irq requested \ with handler=NULL and !ONESHOT for irq 363 Signed-off-by: Felipe Balbi --- drivers/usb/otg/twl4030-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index c4a86da858e2..02979306bf83 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -651,8 +651,8 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) */ twl->irq_enabled = true; status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "twl4030_usb", twl); + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT, "twl4030_usb", twl); if (status < 0) { dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq, status); -- GitLab From c35f77417ebfc7c21c02aa9c8c30aa4cecf331d6 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 11 Jun 2012 12:56:45 +0300 Subject: [PATCH 0728/5711] x86: Define early read-mostly per-cpu macros Some read-mostly per-cpu data may need to be declared or defined early, so it can be initialized and accessed before per_cpu areas are allocated. Only the data that resides in the per_cpu areas should be read-mostly, as there is little benefit in optimizing cache lines on initialization. Signed-off-by: Ido Yariv [ Added the missing declarations in !SMP code. ] Signed-off-by: Vlad Zolotarov Acked-by: Shai Fultheim Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/46188571.ddB8aVQYWo@vlad Signed-off-by: Ingo Molnar --- arch/x86/include/asm/percpu.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index d9b8e3f7f42a..1104afaba52b 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -551,6 +551,12 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); { [0 ... NR_CPUS-1] = _initvalue }; \ __typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map +#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue) \ + DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue; \ + __typeof__(_type) _name##_early_map[NR_CPUS] __initdata = \ + { [0 ... NR_CPUS-1] = _initvalue }; \ + __typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map + #define EXPORT_EARLY_PER_CPU_SYMBOL(_name) \ EXPORT_PER_CPU_SYMBOL(_name) @@ -559,6 +565,11 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); extern __typeof__(_type) *_name##_early_ptr; \ extern __typeof__(_type) _name##_early_map[] +#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name) \ + DECLARE_PER_CPU_READ_MOSTLY(_type, _name); \ + extern __typeof__(_type) *_name##_early_ptr; \ + extern __typeof__(_type) _name##_early_map[] + #define early_per_cpu_ptr(_name) (_name##_early_ptr) #define early_per_cpu_map(_name, _idx) (_name##_early_map[_idx]) #define early_per_cpu(_name, _cpu) \ @@ -570,12 +581,18 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); #define DEFINE_EARLY_PER_CPU(_type, _name, _initvalue) \ DEFINE_PER_CPU(_type, _name) = _initvalue +#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue) \ + DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue + #define EXPORT_EARLY_PER_CPU_SYMBOL(_name) \ EXPORT_PER_CPU_SYMBOL(_name) #define DECLARE_EARLY_PER_CPU(_type, _name) \ DECLARE_PER_CPU(_type, _name) +#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name) \ + DECLARE_PER_CPU_READ_MOSTLY(_type, _name) + #define early_per_cpu(_name, _cpu) per_cpu(_name, _cpu) #define early_per_cpu_ptr(_name) NULL /* no early_per_cpu_map() */ -- GitLab From 0816b0f0365539c8f6280634d2c1778d0108d8f5 Mon Sep 17 00:00:00 2001 From: Vlad Zolotarov Date: Mon, 11 Jun 2012 12:56:52 +0300 Subject: [PATCH 0729/5711] x86: Add read_mostly declaration/definition to variables from smp.h Add "read-mostly" qualifier to the following variables in smp.h: - cpu_sibling_map - cpu_core_map - cpu_llc_shared_map - cpu_llc_id - cpu_number - x86_cpu_to_apicid - x86_bios_cpu_apicid - x86_cpu_to_logical_apicid As long as all the variables above are only written during the initialization, this change is meant to prevent the false sharing. More specifically, on vSMP Foundation platform x86_cpu_to_apicid shared the same internode_cache_line with frequently written lapic_events. From the analysis of the first 33 per_cpu variables out of 219 (memories they describe, to be more specific) the 8 have read_mostly nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.) and 25 are frequently written (irq_stack_union, gdt_page, exception_stacks, idt_desc, etc.). Assuming that the spread of the rest of the per_cpu variables is similar, identifying the read mostly memories will make more sense in terms of long-term code maintenance comparing to identifying frequently written memories. Signed-off-by: Vlad Zolotarov Acked-by: Shai Fultheim Cc: Shai Fultheim (Shai@ScaleMP.com) Cc: ido@wizery.com Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 2 +- arch/x86/include/asm/smp.h | 16 ++++++++-------- arch/x86/kernel/apic/apic.c | 6 +++--- arch/x86/kernel/setup_percpu.c | 2 +- arch/x86/kernel/smpboot.c | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index eaff4790ed96..a907d4d251a8 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -537,7 +537,7 @@ static inline const struct cpumask *default_target_cpus(void) #endif } -DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid); static inline unsigned int read_apic_id(void) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index f48394513c37..cc1df2b5cc65 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -31,12 +31,12 @@ static inline bool cpu_has_ht_siblings(void) return has_siblings; } -DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); -DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); /* cpus sharing the last level cache: */ -DECLARE_PER_CPU(cpumask_var_t, cpu_llc_shared_map); -DECLARE_PER_CPU(u16, cpu_llc_id); -DECLARE_PER_CPU(int, cpu_number); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); +DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id); +DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number); static inline struct cpumask *cpu_sibling_mask(int cpu) { @@ -53,10 +53,10 @@ static inline struct cpumask *cpu_llc_shared_mask(int cpu) return per_cpu(cpu_llc_shared_map, cpu); } -DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); -DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid); #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) -DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid); #endif /* Static state in head.S used to set up a CPU */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 39a222e094af..0443b6482214 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -75,8 +75,8 @@ physid_mask_t phys_cpu_present_map; /* * Map cpu index to physical APIC ID */ -DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); -DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid, BAD_APICID); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); @@ -88,7 +88,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); * used for the mapping. This is where the behaviors of x86_64 and 32 * actually diverge. Let's keep it ugly for now. */ -DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID); /* * Knob to control our willingness to enable the local APIC. diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 5a98aa272184..5cdff0357746 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -21,7 +21,7 @@ #include #include -DEFINE_PER_CPU(int, cpu_number); +DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 3fab55bea29b..e61110e29a8c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -104,17 +104,17 @@ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); /* Last level cache ID of each logical CPU */ -DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID; +DEFINE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id) = BAD_APICID; /* representing HT siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); EXPORT_PER_CPU_SYMBOL(cpu_core_map); -DEFINE_PER_CPU(cpumask_var_t, cpu_llc_shared_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); /* Per CPU bogomips and other parameters */ DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); -- GitLab From 80c8bfbe76869bfd6bdf3d260d316e7a32f318c3 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 4 Jun 2012 09:33:51 +0200 Subject: [PATCH 0730/5711] ALSA: HDA: Create phantom jacks for fixed inputs and outputs PulseAudio sometimes have difficulties knowing that there is a "Speaker" or "Internal Mic", if they have no individual volume controls or selectors. As a result, only e g "Headphone" might be created for a laptop, but no "Speaker". To help out, create phantom jacks (that are always present, at least for now) for "Speaker", "Internal Mic" etc, in case we detect them. The naming convention is e g "Speaker Phantom Jack". In order not to pollute the /dev/input namespace with even more devices, these are added to the kcontrols only, not the input devices. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 59 ++++++++++++++++++++++++++++------------ sound/pci/hda/hda_jack.h | 1 + 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 2dd1c113a4c1..60c976f06280 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -127,10 +127,15 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) static void jack_detect_update(struct hda_codec *codec, struct hda_jack_tbl *jack) { - if (jack->jack_dirty || !jack->jack_detect) { + if (!jack->jack_dirty) + return; + + if (jack->phantom_jack) + jack->pin_sense = AC_PINSENSE_PRESENCE; + else jack->pin_sense = read_pin_sense(codec, jack->nid); - jack->jack_dirty = 0; - } + + jack->jack_dirty = 0; } /** @@ -264,8 +269,8 @@ static void hda_free_jack_priv(struct snd_jack *jack) * This assigns a jack-detection kctl to the given pin. The kcontrol * will have the given name and index. */ -int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, int idx) +static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, + const char *name, int idx, bool phantom_jack) { struct hda_jack_tbl *jack; struct snd_kcontrol *kctl; @@ -283,19 +288,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, if (err < 0) return err; jack->kctl = kctl; + jack->phantom_jack = !!phantom_jack; + state = snd_hda_jack_detect(codec, nid); snd_kctl_jack_report(codec->bus->card, kctl, state); #ifdef CONFIG_SND_HDA_INPUT_JACK - jack->type = get_input_jack_type(codec, nid); - err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); - if (err < 0) - return err; - jack->jack->private_data = jack; - jack->jack->private_free = hda_free_jack_priv; - snd_jack_report(jack->jack, state ? jack->type : 0); + if (!phantom_jack) { + jack->type = get_input_jack_type(codec, nid); + err = snd_jack_new(codec->bus->card, name, jack->type, + &jack->jack); + if (err < 0) + return err; + jack->jack->private_data = jack; + jack->jack->private_free = hda_free_jack_priv; + snd_jack_report(jack->jack, state ? jack->type : 0); + } #endif return 0; } + +int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, + const char *name, int idx) +{ + return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); +} EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, @@ -305,25 +321,32 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, unsigned int def_conf, conn; char name[44]; int idx, err; + bool phantom_jack; if (!nid) return 0; - if (!is_jack_detectable(codec, nid)) - return 0; def_conf = snd_hda_codec_get_pincfg(codec, nid); conn = get_defcfg_connect(def_conf); - if (conn != AC_JACK_PORT_COMPLEX) + if (conn == AC_JACK_PORT_NONE) return 0; + phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || + !is_jack_detectable(codec, nid); snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); + if (phantom_jack) + /* Example final name: "Internal Mic Phantom Jack" */ + strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); if (!strcmp(name, lastname) && idx == *lastidx) idx++; - strncpy(lastname, name, 44); + strncpy(lastname, name, sizeof(name)); *lastidx = idx; - err = snd_hda_jack_add_kctl(codec, nid, name, idx); + err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); if (err < 0) return err; - return snd_hda_jack_detect_enable(codec, nid, 0); + + if (!phantom_jack) + return snd_hda_jack_detect_enable(codec, nid, 0); + return 0; } /** diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 8ae52465ec5d..a9803da633c0 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -23,6 +23,7 @@ struct hda_jack_tbl { unsigned int pin_sense; /* cached pin-sense value */ unsigned int jack_detect:1; /* capable of jack-detection? */ unsigned int jack_dirty:1; /* needs to update? */ + unsigned int phantom_jack:1; /* a fixed, always present port? */ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ #ifdef CONFIG_SND_HDA_INPUT_JACK int type; -- GitLab From fe1cc68fcb11ca14f420068d1806eb5e719ac772 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:41 -0700 Subject: [PATCH 0731/5711] drm/i915: CXT_SIZE register offsets added The GPUs can have different default context layouts, and the sizes could vary based on platform or BIOS. In order to back the context object with a properly sized BO, we must read this register in order to find out a sufficient size. Thankfully (sarcarm!), the register moves and changes meanings throughout generations. CTX and CXT differences are intentional as that is how it is in the documentation (prior to GEN6 it was CXT). Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_reg.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c4b1a2b45bb4..bee101208195 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1454,6 +1454,27 @@ */ #define CCID 0x2180 #define CCID_EN (1<<0) +#define CXT_SIZE 0x21a0 +#define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f) +#define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f) +#define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f) +#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f) +#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f) +#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_POWER_SIZE(cxt_reg) + \ + GEN6_CXT_RING_SIZE(cxt_reg) + \ + GEN6_CXT_RENDER_SIZE(cxt_reg) + \ + GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ + GEN6_CXT_PIPELINE_SIZE(cxt_reg)) +#define GEN7_CTX_SIZE 0x21a8 +#define GEN7_CTX_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f) +#define GEN7_CTX_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f) +#define GEN7_CTX_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7) +#define GEN7_CTX_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f) +#define GEN7_CTX_TOTAL_SIZE(ctx_reg) (GEN7_CTX_RENDER_SIZE(ctx_reg) + \ + GEN7_CTX_EXTENDED_SIZE(ctx_reg) + \ + GEN7_CTX_GT1_SIZE(ctx_reg) + \ + GEN7_CTX_VFSTATE_SIZE(ctx_reg)) + /* * Overlay regs */ -- GitLab From 254f965c39e3918544395f4ebac8c589d890bae6 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:42 -0700 Subject: [PATCH 0732/5711] drm/i915: preliminary context support Very basic code for context setup/destruction in the driver. Adds the file i915_gem_context.c This file implements HW context support. On gen5+ a HW context consists of an opaque GPU object which is referenced at times of context saves and restores. With RC6 enabled, the context is also referenced as the GPU enters and exists from RC6 (GPU has it's own internal power context, except on gen5). Though something like a context does exist for the media ring, the code only supports contexts for the render ring. In software, there is a distinction between contexts created by the user, and the default HW context. The default HW context is used by GPU clients that do not request setup of their own hardware context. The default context's state is never restored to help prevent programming errors. This would happen if a client ran and piggy-backed off another clients GPU state. The default context only exists to give the GPU some offset to load as the current to invoke a save of the context we actually care about. In fact, the code could likely be constructed, albeit in a more complicated fashion, to never use the default context, though that limits the driver's ability to swap out, and/or destroy other contexts. All other contexts are created as a request by the GPU client. These contexts store GPU state, and thus allow GPU clients to not re-emit state (and potentially query certain state) at any time. The kernel driver makes certain that the appropriate commands are inserted. There are 4 entry points into the contexts, init, fini, open, close. The names are self-explanatory except that init can be called during reset, and also during pm thaw/resume. As we expect our context to be preserved across these events, we do not reinitialize in this case. As Adam Jackson pointed out, The cutoff of 1MB where a HW context is considered too big is arbitrary. The reason for this is even though context sizes are increasing with every generation, they have yet to eclipse even 32k. If we somehow read back way more than that, it probably means BIOS has done something strange, or we're running on a platform that wasn't designed for this. v2: rename load/unload to init/fini (daniel) remove ILK support for get_size() (indirectly daniel) add HAS_HW_CONTEXTS macro to clarify supported platforms (daniel) added comments (Ben) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_dma.c | 4 + drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 8 ++ drivers/gpu/drm/i915/i915_gem.c | 5 + drivers/gpu/drm/i915/i915_gem_context.c | 175 ++++++++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_gem_context.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 2e9268da58d8..b0bacdba6d7e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -7,6 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915_debugfs.o \ i915_suspend.o \ i915_gem.o \ + i915_gem_context.o \ i915_gem_debug.o \ i915_gem_evict.o \ i915_gem_execbuffer.o \ diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index fa8f2699344b..3f3aca8c3767 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1669,6 +1669,7 @@ int i915_driver_unload(struct drm_device *dev) if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); i915_gem_retire_requests(dev); + i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); /* Cancel the retire work handler, which should be idle now. */ @@ -1758,6 +1759,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); + i915_gem_context_open(dev, file); + return 0; } @@ -1790,6 +1793,7 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { + i915_gem_context_close(dev, file_priv); i915_gem_release(dev, file_priv); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 238a52165833..5d9e07ece3c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -903,6 +903,7 @@ int i915_reset(struct drm_device *dev) for_each_ring(ring, dev_priv, i) ring->init(ring); + i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ae4129b3cb3e..8d02951b988b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -821,6 +821,8 @@ typedef struct drm_i915_private { struct drm_property *force_audio_property; struct work_struct parity_error_work; + bool hw_contexts_disabled; + uint32_t hw_context_size; } drm_i915_private_t; /* Iterate over initialised rings */ @@ -1075,6 +1077,7 @@ struct drm_i915_file_private { #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) +#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) @@ -1363,6 +1366,11 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags); +/* i915_gem_context.c */ +void i915_gem_context_init(struct drm_device *dev); +void i915_gem_context_fini(struct drm_device *dev); +void 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); /* i915_gem_gtt.c */ int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2884b0865473..c06f50d44a23 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3714,6 +3714,11 @@ i915_gem_init_hw(struct drm_device *dev) dev_priv->next_seqno = 1; + /* + * XXX: There was some w/a described somewhere suggesting loading + * contexts before PPGTT. + */ + i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c new file mode 100644 index 000000000000..e39808e349f1 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -0,0 +1,175 @@ +/* + * Copyright © 2011-2012 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: + * Ben Widawsky + * + */ + +/* + * This file implements HW context support. On gen5+ a HW context consists of an + * opaque GPU object which is referenced at times of context saves and restores. + * With RC6 enabled, the context is also referenced as the GPU enters and exists + * from RC6 (GPU has it's own internal power context, except on gen5). Though + * something like a context does exist for the media ring, the code only + * supports contexts for the render ring. + * + * In software, there is a distinction between contexts created by the user, + * and the default HW context. The default HW context is used by GPU clients + * that do not request setup of their own hardware context. The default + * context's state is never restored to help prevent programming errors. This + * would happen if a client ran and piggy-backed off another clients GPU state. + * The default context only exists to give the GPU some offset to load as the + * current to invoke a save of the context we actually care about. In fact, the + * code could likely be constructed, albeit in a more complicated fashion, to + * never use the default context, though that limits the driver's ability to + * swap out, and/or destroy other contexts. + * + * All other contexts are created as a request by the GPU client. These contexts + * store GPU state, and thus allow GPU clients to not re-emit state (and + * potentially query certain state) at any time. The kernel driver makes + * certain that the appropriate commands are inserted. + * + * The context life cycle is semi-complicated in that context BOs may live + * longer than the context itself because of the way the hardware, and object + * tracking works. Below is a very crude representation of the state machine + * describing the context life. + * refcount pincount active + * S0: initial state 0 0 0 + * S1: context created 1 0 0 + * S2: context is currently running 2 1 X + * S3: GPU referenced, but not current 2 0 1 + * S4: context is current, but destroyed 1 1 0 + * S5: like S3, but destroyed 1 0 1 + * + * The most common (but not all) transitions: + * S0->S1: client creates a context + * S1->S2: client submits execbuf with context + * S2->S3: other clients submits execbuf with context + * S3->S1: context object was retired + * S3->S2: clients submits another execbuf + * S2->S4: context destroy called with current context + * S3->S5->S0: destroy path + * S4->S5->S0: destroy path on current context + * + * There are two confusing terms used above: + * The "current context" means the context which is currently running on the + * GPU. The GPU has loaded it's state already and has stored away the gtt + * offset of the BO. The GPU is not actively referencing the data at this + * offset, but it will on the next context switch. The only way to avoid this + * is to do a GPU reset. + * + * An "active context' is one which was previously the "current context" and is + * on the active list waiting for the next context switch to occur. Until this + * happens, the object must remain at the same gtt offset. It is therefore + * possible to destroy a context, but it is still active. + * + */ + +#include "drmP.h" +#include "i915_drm.h" +#include "i915_drv.h" + +static int get_context_size(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + u32 reg; + + switch (INTEL_INFO(dev)->gen) { + case 6: + reg = I915_READ(CXT_SIZE); + ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; + break; + case 7: + reg = I915_READ(GEN7_CTX_SIZE); + ret = GEN7_CTX_TOTAL_SIZE(reg) * 64; + break; + default: + BUG(); + } + + return ret; +} + +/** + * The default context needs to exist per ring that uses contexts. It stores the + * context state of the GPU for applications that don't utilize HW contexts, as + * well as an idle case. + */ +static int create_default_context(struct drm_i915_private *dev_priv) +{ + return 0; +} + +void i915_gem_context_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t ctx_size; + + if (!HAS_HW_CONTEXTS(dev)) + return; + + /* If called from reset, or thaw... we've been here already */ + if (dev_priv->hw_contexts_disabled) + return; + + ctx_size = get_context_size(dev); + dev_priv->hw_context_size = get_context_size(dev); + dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096); + + if (ctx_size <= 0 || ctx_size > (1<<20)) { + dev_priv->hw_contexts_disabled = true; + return; + } + + if (create_default_context(dev_priv)) { + dev_priv->hw_contexts_disabled = true; + return; + } + + DRM_DEBUG_DRIVER("HW context support initialized\n"); +} + +void i915_gem_context_fini(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->hw_contexts_disabled) + return; +} + +void i915_gem_context_open(struct drm_device *dev, struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->hw_contexts_disabled) + return; +} + +void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->hw_contexts_disabled) + return; +} -- GitLab From 40521054fd46f94e0368cead312d56e9e442aaab Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:43 -0700 Subject: [PATCH 0733/5711] drm/i915: context basic create & destroy Invent an abstraction for a hw context which is passed around through the core functions. The main bit a hw context holds is the buffer object which backs the context. The rest of the members are just helper functions. Specifically the ring member, which could likely go away if we decide to never implement whatever other hw context support exists. Of note here is the introduction of the 64k alignment constraint for the BO. If contexts become heavily used, we should consider tweaking this down to 4k. Until the contexts are merged and tested a bit though, I think 64k is a nice start (based on docs). Since we don't yet switch contexts, there is really not much complexity here. Creation/destruction works pretty much as one would expect. An idr is used to generate the context id numbers which are unique per file descriptor. v2: add DRM_DEBUG_DRIVERS to distinguish ENOMEM failures (ben) convert a BUG_ON to WARN_ON, default destruction is still fatal (ben) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_drv.h | 11 ++ drivers/gpu/drm/i915/i915_gem_context.c | 142 +++++++++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 3 files changed, 153 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8d02951b988b..250eeae7c262 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -308,6 +308,16 @@ struct i915_hw_ppgtt { dma_addr_t scratch_page_dma_addr; }; + +/* This must match up with the value previously used for execbuf2.rsvd1. */ +#define DEFAULT_CONTEXT_ID 0 +struct i915_hw_context { + int id; + struct drm_i915_file_private *file_priv; + struct intel_ring_buffer *ring; + struct drm_i915_gem_object *obj; +}; + enum no_fbc_reason { FBC_NO_OUTPUT, /* no outputs enabled to compress */ FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ @@ -1032,6 +1042,7 @@ struct drm_i915_file_private { struct spinlock lock; struct list_head request_list; } mm; + struct idr context_idr; }; #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index e39808e349f1..2aca00235ce3 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -89,6 +89,15 @@ #include "i915_drm.h" #include "i915_drv.h" +/* This is a HW constraint. The value below is the largest known requirement + * I've seen in a spec to date, and that was a workaround for a non-shipping + * part. It should be safe to decrease this, but it's more future proof as is. + */ +#define CONTEXT_ALIGN (64<<10) + +static struct i915_hw_context * +i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); + static int get_context_size(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -111,6 +120,76 @@ static int get_context_size(struct drm_device *dev) return ret; } +static void do_destroy(struct i915_hw_context *ctx) +{ + struct drm_device *dev = ctx->obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (ctx->file_priv) + idr_remove(&ctx->file_priv->context_idr, ctx->id); + else + BUG_ON(ctx != dev_priv->ring[RCS].default_context); + + drm_gem_object_unreference(&ctx->obj->base); + kfree(ctx); +} + +static int +create_hw_context(struct drm_device *dev, + struct drm_i915_file_private *file_priv, + struct i915_hw_context **ctx_out) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int ret, id; + + *ctx_out = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL); + if (*ctx_out == NULL) + return -ENOMEM; + + (*ctx_out)->obj = i915_gem_alloc_object(dev, + dev_priv->hw_context_size); + if ((*ctx_out)->obj == NULL) { + kfree(*ctx_out); + DRM_DEBUG_DRIVER("Context object allocated failed\n"); + return -ENOMEM; + } + + /* The ring associated with the context object is handled by the normal + * object tracking code. We give an initial ring value simple to pass an + * assertion in the context switch code. + */ + (*ctx_out)->ring = &dev_priv->ring[RCS]; + + /* Default context will never have a file_priv */ + if (file_priv == NULL) + return 0; + + (*ctx_out)->file_priv = file_priv; + +again: + if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) { + ret = -ENOMEM; + DRM_DEBUG_DRIVER("idr allocation failed\n"); + goto err_out; + } + + ret = idr_get_new_above(&file_priv->context_idr, *ctx_out, + DEFAULT_CONTEXT_ID + 1, &id); + if (ret == 0) + (*ctx_out)->id = id; + + if (ret == -EAGAIN) + goto again; + else if (ret) + goto err_out; + + return 0; + +err_out: + do_destroy(*ctx_out); + return ret; +} + /** * The default context needs to exist per ring that uses contexts. It stores the * context state of the GPU for applications that don't utilize HW contexts, as @@ -118,7 +197,30 @@ static int get_context_size(struct drm_device *dev) */ static int create_default_context(struct drm_i915_private *dev_priv) { - return 0; + struct i915_hw_context *ctx; + int ret; + + BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + + ret = create_hw_context(dev_priv->dev, NULL, + &dev_priv->ring[RCS].default_context); + if (ret) + return ret; + + /* We may need to do things with the shrinker which require us to + * immediately switch back to the default context. This can cause a + * problem as pinning the default context also requires GTT space which + * may not be available. To avoid this we always pin the + * default context. + */ + ctx = dev_priv->ring[RCS].default_context; + ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); + if (ret) { + do_destroy(ctx); + return ret; + } + + return ret; } void i915_gem_context_init(struct drm_device *dev) @@ -130,7 +232,8 @@ void i915_gem_context_init(struct drm_device *dev) return; /* If called from reset, or thaw... we've been here already */ - if (dev_priv->hw_contexts_disabled) + if (dev_priv->hw_contexts_disabled || + dev_priv->ring[RCS].default_context) return; ctx_size = get_context_size(dev); @@ -156,20 +259,55 @@ void i915_gem_context_fini(struct drm_device *dev) if (dev_priv->hw_contexts_disabled) return; + + i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); + + do_destroy(dev_priv->ring[RCS].default_context); } void i915_gem_context_open(struct drm_device *dev, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_file_private *file_priv = file->driver_priv; if (dev_priv->hw_contexts_disabled) return; + + idr_init(&file_priv->context_idr); +} + +static int context_idr_cleanup(int id, void *p, void *data) +{ + struct drm_file *file = (struct drm_file *)data; + struct drm_i915_file_private *file_priv = file->driver_priv; + struct i915_hw_context *ctx; + + BUG_ON(id == DEFAULT_CONTEXT_ID); + ctx = i915_gem_context_get(file_priv, id); + if (WARN_ON(ctx == NULL)) + return -ENXIO; + + do_destroy(ctx); + + return 0; } void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_file_private *file_priv = file->driver_priv; if (dev_priv->hw_contexts_disabled) return; + + mutex_lock(&dev->struct_mutex); + idr_for_each(&file_priv->context_idr, context_idr_cleanup, file); + idr_destroy(&file_priv->context_idr); + mutex_unlock(&dev->struct_mutex); +} + +static __used struct i915_hw_context * +i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) +{ + return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 55d3da26bae7..bb19becb1163 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -116,6 +116,8 @@ struct intel_ring_buffer { wait_queue_head_t irq_queue; + struct i915_hw_context *default_context; + void *private; }; -- GitLab From e055684168af48ac7deb27d7267046a0fb9ef80e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:46 -0700 Subject: [PATCH 0734/5711] drm/i915: context switch implementation Implement the context switch code as well as the interfaces to do the context switch. This patch also doesn't match 1:1 with the RFC patches. The main difference is that from Daniel's responses the last context object is now stored instead of the last context. This aids in allows us to free the context data structure, and context object independently. There is room for optimization: this code will pin the context object until the next context is active. The optimal way to do it is to actually pin the object, move it to the active list, do the context switch, and then unpin it. This allows the eviction code to actually evict the context object if needed. The context switch code is missing workarounds, they will be implemented in future patches. v2: actually do obj->dirty=1 in switch (daniel) Modified comment around above Remove flags to context switch (daniel) Move mi_set_context code to i915_gem_context.c (daniel) Remove seqno , use lazy request instead (daniel) v3: use i915_gem_request_next_seqno instead of outstanding_lazy_request (Daniel) remove id's from trace events (Daniel) Put the context BO in the instruction domain (Daniel) Don't unref the BO is context switch fails (Chris) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_gem_context.c | 146 +++++++++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 250eeae7c262..7fb0364d5d61 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -313,6 +313,7 @@ struct i915_hw_ppgtt { #define DEFAULT_CONTEXT_ID 0 struct i915_hw_context { int id; + bool is_initialized; struct drm_i915_file_private *file_priv; struct intel_ring_buffer *ring; struct drm_i915_gem_object *obj; @@ -1382,6 +1383,8 @@ void i915_gem_context_init(struct drm_device *dev); void i915_gem_context_fini(struct drm_device *dev); void 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 intel_ring_buffer *ring, + struct drm_file *file, int to_id); /* i915_gem_gtt.c */ int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2aca00235ce3..5248c00707f6 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -190,6 +190,11 @@ err_out: return ret; } +static inline bool is_default_context(struct i915_hw_context *ctx) +{ + return (ctx == ctx->ring->default_context); +} + /** * The default context needs to exist per ring that uses contexts. It stores the * context state of the GPU for applications that don't utilize HW contexts, as @@ -306,8 +311,147 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) mutex_unlock(&dev->struct_mutex); } -static __used struct i915_hw_context * +static struct i915_hw_context * i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) { return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); } + +static inline int +mi_set_context(struct intel_ring_buffer *ring, + struct i915_hw_context *new_context, + u32 hw_flags) +{ + int ret; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_SET_CONTEXT); + intel_ring_emit(ring, new_context->obj->gtt_offset | + MI_MM_SPACE_GTT | + MI_SAVE_EXT_STATE_EN | + MI_RESTORE_EXT_STATE_EN | + hw_flags); + /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); + + return ret; +} + +static int do_switch(struct drm_i915_gem_object *from_obj, + struct i915_hw_context *to, + u32 seqno) +{ + struct intel_ring_buffer *ring = NULL; + u32 hw_flags = 0; + int ret; + + BUG_ON(to == NULL); + BUG_ON(from_obj != NULL && from_obj->pin_count == 0); + + ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); + if (ret) + return ret; + + if (!to->is_initialized || is_default_context(to)) + hw_flags |= MI_RESTORE_INHIBIT; + else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ + hw_flags |= MI_FORCE_RESTORE; + + ring = to->ring; + ret = mi_set_context(ring, to, hw_flags); + if (ret) { + i915_gem_object_unpin(to->obj); + return ret; + } + + /* The backing object for the context is done after switching to the + * *next* context. Therefore we cannot retire the previous context until + * the next context has already started running. In fact, the below code + * is a bit suboptimal because the retiring can occur simply after the + * MI_SET_CONTEXT instead of when the next seqno has completed. + */ + if (from_obj != NULL) { + from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; + i915_gem_object_move_to_active(from_obj, ring, seqno); + /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the + * whole damn pipeline, we don't need to explicitly mark the + * object dirty. The only exception is that the context must be + * correct in case the object gets swapped out. Ideally we'd be + * able to defer doing this until we know the object would be + * swapped, but there is no way to do that yet. + */ + from_obj->dirty = 1; + BUG_ON(from_obj->ring != to->ring); + i915_gem_object_unpin(from_obj); + } + + ring->last_context_obj = to->obj; + to->is_initialized = true; + + return 0; +} + +/** + * i915_switch_context() - perform a GPU context switch. + * @ring: ring for which we'll execute the context switch + * @file_priv: file_priv associated with the context, may be NULL + * @id: context id number + * @seqno: sequence number by which the new context will be switched to + * @flags: + * + * The context life cycle is simple. The context refcount is incremented and + * decremented by 1 and create and destroy. If the context is in use by the GPU, + * it will have a refoucnt > 1. This allows us to destroy the context abstract + * object while letting the normal object tracking destroy the backing BO. + */ +int i915_switch_context(struct intel_ring_buffer *ring, + struct drm_file *file, + int to_id) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_file_private *file_priv = NULL; + struct i915_hw_context *to; + struct drm_i915_gem_object *from_obj = ring->last_context_obj; + int ret; + + if (dev_priv->hw_contexts_disabled) + return 0; + + if (ring != &dev_priv->ring[RCS]) + return 0; + + if (file) + file_priv = file->driver_priv; + + if (to_id == DEFAULT_CONTEXT_ID) { + to = ring->default_context; + } else { + to = i915_gem_context_get(file_priv, to_id); + if (to == NULL) + return -EINVAL; + } + + if (from_obj == to->obj) + return 0; + + ret = do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring)); + if (ret) + return ret; + + /* Just to make the code a little cleaner we take the object reference + * after the switch was successful. It would be more intuitive to ref + * the 'to' object before the switch but we know the refcount must be >0 + * if context_get() succeeded, and we hold struct mutex. So it's safe to + * do this here/now + */ + drm_gem_object_reference(&to->obj->base); + if (from_obj != NULL) + drm_gem_object_unreference(&from_obj->base); + return ret; +} diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index bb19becb1163..b7884b90474a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -117,6 +117,7 @@ struct intel_ring_buffer { wait_queue_head_t irq_queue; struct i915_hw_context *default_context; + struct drm_i915_gem_object *last_context_obj; void *private; }; -- GitLab From 3af7b8572f5e375421ba6128585972d4a42a0762 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 14 Jun 2012 00:08:32 +0200 Subject: [PATCH 0735/5711] drm/i915: ensure context objects are bound to the global gtt This way round we don't introduce and ugly layering violations and use the interface as I planned to use it. Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5248c00707f6..fb6aa5e10991 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -358,6 +358,9 @@ static int do_switch(struct drm_i915_gem_object *from_obj, if (ret) return ret; + if (!to->obj->has_global_gtt_mapping) + i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); + if (!to->is_initialized || is_default_context(to)) hw_flags |= MI_RESTORE_INHIBIT; else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ -- GitLab From e37ec39b180c53dea3106ceb8f247bcba47dfb82 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:48 -0700 Subject: [PATCH 0736/5711] drm/i915: Ivybridge MI_ARB_ON_OFF context w/a The workaround itself applies to gen7 only (according to the docs) and as Eric Anholt points out shouldn't be required since we don't use HW scheduling features, and therefore arbitration. Though since it is a small, and simple addition, and we don't really understand the issue, just do it. FWIW, I eventually want to play with some of the arbitration stuff, and I'd hate to forget about this. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem_context.c | 12 +++++++++++- drivers/gpu/drm/i915/i915_reg.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index fb6aa5e10991..d49d5fc0a592 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -324,10 +324,15 @@ mi_set_context(struct intel_ring_buffer *ring, { int ret; - ret = intel_ring_begin(ring, 4); + ret = intel_ring_begin(ring, 6); if (ret) return ret; + if (IS_GEN7(ring->dev)) + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); + else + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); intel_ring_emit(ring, MI_SET_CONTEXT); intel_ring_emit(ring, new_context->obj->gtt_offset | @@ -338,6 +343,11 @@ mi_set_context(struct intel_ring_buffer *ring, /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ intel_ring_emit(ring, MI_NOOP); + if (IS_GEN7(ring->dev)) + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); + else + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); return ret; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bee101208195..14cb714df352 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -210,6 +210,9 @@ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) +#define MI_ARB_ON_OFF MI_INSTR(0x08, 0) +#define MI_ARB_ENABLE (1<<0) +#define MI_ARB_DISABLE (0<<0) #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) -- GitLab From cc0f6398225ffd2b890ff83eafe212b1ae863cad Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:49 -0700 Subject: [PATCH 0737/5711] drm/i915: PIPE_CONTROL_TLB_INVALIDATE This has showed up in several other patches. It's required for the next context workaround. I tested this one on its own and saw no differences in basic tests (performance or otherwise). This patch is relatively likely to cause regressions, hence why it's split out. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 14cb714df352..60562f0c7018 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -294,6 +294,7 @@ #define DISPLAY_PLANE_B (1<<20) #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) #define PIPE_CONTROL_CS_STALL (1<<20) +#define PIPE_CONTROL_TLB_INVALIDATE (1<<18) #define PIPE_CONTROL_QW_WRITE (1<<14) #define PIPE_CONTROL_DEPTH_STALL (1<<13) #define PIPE_CONTROL_WRITE_FLUSH (1<<12) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 14025ab9d4ca..a041492fdd46 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -226,6 +226,7 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, * impact. */ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; + flags |= PIPE_CONTROL_TLB_INVALIDATE; flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; -- GitLab From 12b0286f49947a6cdc9285032d918466a8c3f5f9 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:50 -0700 Subject: [PATCH 0738/5711] drm/i915: possibly invalidate TLB before context switch From http://intellinuxgraphics.org/documentation/SNB/IHD_OS_Vol1_Part3.pdf [DevSNB] If Flush TLB invalidation Mode is enabled it's the driver's responsibility to invalidate the TLBs at least once after the previous context switch after any GTT mappings changed (including new GTT entries). This can be done by a pipelined PIPE_CONTROL with TLB inv bit set immediately before MI_SET_CONTEXT. On GEN7 the invalidation mode is explicitly set, but this appears to be lacking for GEN6. Since I don't know the history on this, I've decided to dynamically read the value at ring init time, and use that value throughout. v2: better comment (daniel) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem_context.c | 11 +++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d49d5fc0a592..fb1e1d22572c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -324,6 +324,17 @@ mi_set_context(struct intel_ring_buffer *ring, { int ret; + /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB + * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value + * explicitly, so we rely on the value at ring init, stored in + * itlb_before_ctx_switch. + */ + if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { + ret = ring->flush(ring, 0, 0); + if (ret) + return ret; + } + ret = intel_ring_begin(ring, 6); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a041492fdd46..7a16f16371e6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -423,6 +423,13 @@ static int init_render_ring(struct intel_ring_buffer *ring) */ I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); + + /* This is not explicitly set for GEN6, so read the register. + * see intel_ring_mi_set_context() for why we care. + * TODO: consider explicitly setting the bit for GEN5 + */ + ring->itlb_before_ctx_switch = + !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); } if (INTEL_INFO(dev)->gen >= 6) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index b7884b90474a..594c9c4ad396 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -116,6 +116,10 @@ struct intel_ring_buffer { wait_queue_head_t irq_queue; + /** + * Do an explicit TLB flush before MI_SET_CONTEXT + */ + bool itlb_before_ctx_switch; struct i915_hw_context *default_context; struct drm_i915_gem_object *last_context_obj; -- GitLab From dfabbcb4f6a277992037fe199bcc1bf6bd44a996 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:51 -0700 Subject: [PATCH 0739/5711] drm/i915: use the default context With the code to do HW context switches in place have the driver load the default context for the render ring when the driver loads. The default context will be an ever present context that is available to switch to at any time for the given ring. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem_context.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index fb1e1d22572c..6a7b67d9f43f 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -97,6 +97,8 @@ static struct i915_hw_context * i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); +static int do_switch(struct drm_i915_gem_object *from_obj, + struct i915_hw_context *to, u32 seqno); static int get_context_size(struct drm_device *dev) { @@ -225,6 +227,14 @@ static int create_default_context(struct drm_i915_private *dev_priv) return ret; } + ret = do_switch(NULL, ctx, 0); + if (ret) { + i915_gem_object_unpin(ctx->obj); + do_destroy(ctx); + } else { + DRM_DEBUG_DRIVER("Default HW context loaded\n"); + } + return ret; } -- GitLab From b9a3906b609c4b546f00483089516c65fb2ff014 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:52 -0700 Subject: [PATCH 0740/5711] drm/i915: add ccid to error state Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4fa00fcfbc96..2909b123baf5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -713,6 +713,7 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); + seq_printf(m, "CCID: 0x%08x\n", error->ccid); for (i = 0; i < dev_priv->num_fence_regs; i++) seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7fb0364d5d61..6edc02b6dda4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -176,6 +176,7 @@ struct drm_i915_error_state { u32 eir; u32 pgtbl_er; u32 ier; + u32 ccid; bool waiting[I915_NUM_RINGS]; u32 pipestat[I915_MAX_PIPES]; u32 tail[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0e876646d769..add0aaeadecd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1156,6 +1156,7 @@ static void i915_capture_error_state(struct drm_device *dev) kref_init(&error->ref); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); + error->ccid = I915_READ(CCID); if (HAS_PCH_SPLIT(dev)) error->ier = I915_READ(DEIER) | I915_READ(GTIER); -- GitLab From f2ef6eb1453a95ce8ab388493793c54a6bedc405 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:53 -0700 Subject: [PATCH 0741/5711] drm/i915: switch to default context on idle To keep things as sane as possible, switch to the default context before idling. This should help free context objects, as well as put things in a more well defined state before suspending. v2: remove seqno from context switch call (daniel) return error on failed context switch instead of WARN+continue (daniel) v3: move idling to i915_gpu idle (from i915_gem_idle) (Chris) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c06f50d44a23..3596f3415624 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2332,6 +2332,10 @@ int i915_gpu_idle(struct drm_device *dev) /* Is the device fubar? */ if (WARN_ON(!list_empty(&ring->gpu_write_list))) return -EBUSY; + + ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); + if (ret) + return ret; } return 0; -- GitLab From 846248136dd3a6723135b8515ed7dc4c52a7b2ae Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:54 -0700 Subject: [PATCH 0742/5711] drm/i915/context: create & destroy ioctls Add the interfaces to allow user space to create and destroy contexts. Contexts are destroyed automatically if the file descriptor for the dri device is closed. Following convention as usual here causes checkpatch warnings. v2: with is_initialized, no longer need to init at create drop the context switch on create (daniel) v3: Use interruptible lock (Chris) return -ENODEV in !GEM case (Chris) Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_dma.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 4 ++ drivers/gpu/drm/i915/i915_gem_context.c | 55 +++++++++++++++++++++++++ include/drm/i915_drm.h | 15 +++++++ 4 files changed, 76 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3f3aca8c3767..ba75af12f1fd 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1848,6 +1848,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6edc02b6dda4..03e7f9e683e3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1386,6 +1386,10 @@ void 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 intel_ring_buffer *ring, struct drm_file *file, int to_id); +int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); +int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); /* i915_gem_gtt.c */ int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6a7b67d9f43f..5642c4019b53 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -489,3 +489,58 @@ int i915_switch_context(struct intel_ring_buffer *ring, drm_gem_object_unreference(&from_obj->base); return ret; } + +int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_context_create *args = data; + struct drm_i915_file_private *file_priv = file->driver_priv; + struct i915_hw_context *ctx; + int ret; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + return ret; + + ret = create_hw_context(dev, file_priv, &ctx); + mutex_unlock(&dev->struct_mutex); + + args->ctx_id = ctx->id; + DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); + + return ret; +} + +int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_context_destroy *args = data; + struct drm_i915_file_private *file_priv = file->driver_priv; + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_hw_context *ctx; + int ret; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + return ret; + + ctx = i915_gem_context_get(file_priv, args->ctx_id); + if (!ctx) { + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + do_destroy(ctx); + + mutex_unlock(&dev->struct_mutex); + + DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); + return 0; +} diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 5c28ee1d1911..5da73244486a 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -201,6 +201,8 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GET_SPRITE_COLORKEY 0x2a #define DRM_I915_SET_SPRITE_COLORKEY 0x2b #define DRM_I915_GEM_WAIT 0x2c +#define DRM_I915_GEM_CONTEXT_CREATE 0x2d +#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -245,6 +247,8 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) +#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -897,4 +901,15 @@ struct drm_i915_gem_wait { __s64 timeout_ns; }; +struct drm_i915_gem_context_create { + /* output: id of new context*/ + __u32 ctx_id; + __u32 pad; +}; + +struct drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + #endif /* _I915_DRM_H_ */ -- GitLab From 6e0a69dbc81b88f5a42e08344203021571f6fb2f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:55 -0700 Subject: [PATCH 0743/5711] drm/i915/context: switch contexts with execbuf2 Use the rsvd1 field in execbuf2 to specify the context ID associated with the workload. This will allow the driver to do the proper context switch when/if needed. v2: Add checks for context switches on rings not supporting contexts. Before the code would silently ignore such requests. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 16 ++++++++++++++++ include/drm/i915_drm.h | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 974a9f1068a3..f32d02464bce 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1044,6 +1044,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_object *batch_obj; struct drm_clip_rect *cliprects = NULL; struct intel_ring_buffer *ring; + u32 ctx_id = i915_execbuffer2_get_context_id(*args); u32 exec_start, exec_len; u32 seqno; u32 mask; @@ -1065,9 +1066,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, break; case I915_EXEC_BSD: ring = &dev_priv->ring[VCS]; + if (ctx_id != 0) { + DRM_DEBUG("Ring %s doesn't support contexts\n", + ring->name); + return -EPERM; + } break; case I915_EXEC_BLT: ring = &dev_priv->ring[BCS]; + if (ctx_id != 0) { + DRM_DEBUG("Ring %s doesn't support contexts\n", + ring->name); + return -EPERM; + } break; default: DRM_DEBUG("execbuf with unknown ring: %d\n", @@ -1261,6 +1272,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto err; } + ret = i915_switch_context(ring, file, ctx_id); + if (ret) + goto err; + trace_i915_gem_ring_dispatch(ring, seqno); exec_start = batch_obj->gtt_offset + args->batch_start_offset; @@ -1367,6 +1382,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, exec2.num_cliprects = args->num_cliprects; exec2.cliprects_ptr = args->cliprects_ptr; exec2.flags = I915_EXEC_RENDER; + i915_execbuffer2_set_context_id(exec2, 0); ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); if (!ret) { diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 5da73244486a..8cc70837f929 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -663,13 +663,19 @@ struct drm_i915_gem_execbuffer2 { #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ __u64 flags; - __u64 rsvd1; + __u64 rsvd1; /* now used for context info */ __u64 rsvd2; }; /** Resets the SO write offset registers for transform feedback on gen7. */ #define I915_EXEC_GEN7_SOL_RESET (1<<8) +#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) +#define i915_execbuffer2_set_context_id(eb2, context) \ + (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK +#define i915_execbuffer2_get_context_id(eb2) \ + ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) + struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ __u32 handle; -- GitLab From 8e96d9c4d9843f00ebeb4a9b33596d96602ea101 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Jun 2012 14:42:56 -0700 Subject: [PATCH 0744/5711] drm/i915: reset the GPU on context fini It's the only way we know how to make the GPU actually forget about the default context. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem_context.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5d9e07ece3c2..f0bd30ab1551 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -799,7 +799,7 @@ static int gen6_do_reset(struct drm_device *dev) return ret; } -static int intel_gpu_reset(struct drm_device *dev) +int intel_gpu_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret = -ENODEV; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 03e7f9e683e3..6f29fd141ab0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1184,6 +1184,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, extern int i915_emit_box(struct drm_device *dev, struct drm_clip_rect *box, int DR1, int DR4); +extern int intel_gpu_reset(struct drm_device *dev); extern int i915_reset(struct drm_device *dev); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); extern unsigned long i915_mch_val(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 5642c4019b53..6dc426a48b2d 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -278,6 +278,8 @@ void i915_gem_context_fini(struct drm_device *dev) i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); do_destroy(dev_priv->ring[RCS].default_context); + + intel_gpu_reset(dev); } void i915_gem_context_open(struct drm_device *dev, struct drm_file *file) -- GitLab From 7d0fa3ecba2f12ceef93fffe615e5dd9b50bb794 Mon Sep 17 00:00:00 2001 From: Alain Renaud Date: Fri, 8 Jun 2012 15:34:46 -0400 Subject: [PATCH 0745/5711] xfs: xfs_vm_writepage clear iomap_valid when !buffer_uptodate (REV2) On filesytems with a block size smaller than PAGE_SIZE we currently have a problem with unwritten extents. If a we have multi-block page for which an unwritten extent has been allocated, and only some of the buffers have been written to, and they are not contiguous, we can expose stale data from disk in the blocks between the writes after extent conversion. Example of a page with unwritten and real data. buffer content 0 empty b_state = 0 1 DATA b_state = 0x1023 Uptodate,Dirty,Mapped,Unwritten 2 DATA b_state = 0x1023 Uptodate,Dirty,Mapped,Unwritten 3 empty b_state = 0 4 empty b_state = 0 5 DATA b_state = 0x1023 Uptodate,Dirty,Mapped,Unwritten 6 DATA b_state = 0x1023 Uptodate,Dirty,Mapped,Unwritten 7 empty b_state = 0 Buffers 1, 2, 5, and 6 have been written to, leaving 0, 3, 4, and 7 empty. Currently buffers 1, 2, 5, and 6 are added to a single ioend, and when IO has completed, extent conversion creates a real extent from block 1 through block 6, leaving 0 and 7 unwritten. However buffers 3 and 4 were not written to disk, so stale data is exposed from those blocks on a subsequent read. Fix this by setting iomap_valid = 0 when we find a buffer that is not Uptodate. This ensures that buffers 5 and 6 are not added to the same ioend as buffers 1 and 2. Later these blocks will be converted into two separate real extents, leaving the blocks in between unwritten. Signed-off-by: Alain Renaud Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_aops.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index ae31c313a79e..8dad722c0041 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -981,10 +981,15 @@ xfs_vm_writepage( imap_valid = 0; } } else { - if (PageUptodate(page)) { + if (PageUptodate(page)) ASSERT(buffer_mapped(bh)); - imap_valid = 0; - } + /* + * This buffer is not uptodate and will not be + * written to disk. Ensure that we will put any + * subsequent writeable buffers into a new + * ioend. + */ + imap_valid = 0; continue; } -- GitLab From 0f2cf9d3d917b269645902506adaa4ff92b5e506 Mon Sep 17 00:00:00 2001 From: Jeff Liu Date: Thu, 7 Jun 2012 15:44:32 +0800 Subject: [PATCH 0746/5711] xfs: fix debug_object WARN at xfs_alloc_vextent() Fengguang reports: [ 780.529603] XFS (vdd): Ending clean mount [ 781.454590] ODEBUG: object is on stack, but not annotated [ 781.455433] ------------[ cut here ]------------ [ 781.455433] WARNING: at /c/kernel-tests/sound/lib/debugobjects.c:301 __debug_object_init+0x173/0x1f1() [ 781.455433] Hardware name: Bochs [ 781.455433] Modules linked in: [ 781.455433] Pid: 26910, comm: kworker/0:2 Not tainted 3.4.0+ #51 [ 781.455433] Call Trace: [ 781.455433] [] warn_slowpath_common+0x83/0x9b [ 781.455433] [] warn_slowpath_null+0x1a/0x1c [ 781.455433] [] __debug_object_init+0x173/0x1f1 [ 781.455433] [] debug_object_init+0x14/0x16 [ 781.455433] [] __init_work+0x20/0x22 [ 781.455433] [] xfs_alloc_vextent+0x6c/0xd5 Use INIT_WORK_ONSTACK in xfs_alloc_vextent instead of INIT_WORK. Reported-by: Wu Fengguang Signed-off-by: Jie Liu Signed-off-by: Ben Myers --- fs/xfs/xfs_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 229641fb8e67..a996e398692b 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -2441,7 +2441,7 @@ xfs_alloc_vextent( DECLARE_COMPLETION_ONSTACK(done); args->done = &done; - INIT_WORK(&args->work, xfs_alloc_vextent_worker); + INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker); queue_work(xfs_alloc_wq, &args->work); wait_for_completion(&done); return args->result; -- GitLab From d2c2819117176e139dc761873c664aaa770c79c9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 8 Jun 2012 15:44:53 +1000 Subject: [PATCH 0747/5711] xfs: m_maxioffset is redundant The m_maxioffset field in the struct xfs_mount contains the same value as the superblock s_maxbytes field. There is no need to carry two copies of this limit around, so use the VFS superblock version. Signed-off-by: Dave Chinner Reviewed-by: Eric Sandeen Signed-off-by: Ben Myers --- fs/xfs/xfs_aops.c | 12 ++++++------ fs/xfs/xfs_iomap.c | 4 ++-- fs/xfs/xfs_mount.c | 2 -- fs/xfs/xfs_mount.h | 3 +-- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8dad722c0041..84e372596d56 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -323,10 +323,10 @@ xfs_map_blocks( ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || (ip->i_df.if_flags & XFS_IFEXTENTS)); - ASSERT(offset <= mp->m_maxioffset); + ASSERT(offset <= mp->m_super->s_maxbytes); - if (offset + count > mp->m_maxioffset) - count = mp->m_maxioffset - offset; + if (offset + count > mp->m_super->s_maxbytes) + count = mp->m_super->s_maxbytes - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); offset_fsb = XFS_B_TO_FSBT(mp, offset); error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, @@ -1162,9 +1162,9 @@ __xfs_get_blocks( lockmode = xfs_ilock_map_shared(ip); } - ASSERT(offset <= mp->m_maxioffset); - if (offset + size > mp->m_maxioffset) - size = mp->m_maxioffset - offset; + ASSERT(offset <= mp->m_super->s_maxbytes); + if (offset + size > mp->m_super->s_maxbytes) + size = mp->m_super->s_maxbytes - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); offset_fsb = XFS_B_TO_FSBT(mp, offset); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index aadfce6681ee..4590cd1da432 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -416,8 +416,8 @@ retry: * Make sure preallocation does not create extents beyond the range we * actually support in this filesystem. */ - if (last_fsb > XFS_B_TO_FSB(mp, mp->m_maxioffset)) - last_fsb = XFS_B_TO_FSB(mp, mp->m_maxioffset); + if (last_fsb > XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes)) + last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); ASSERT(last_fsb > offset_fsb); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 536021fb3d4e..9536fd190191 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1200,8 +1200,6 @@ xfs_mountfs( xfs_set_maxicount(mp); - mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); - error = xfs_uuid_mount(mp); if (error) goto out; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 8b89c5ac72d9..47c6b3b3eb9c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -176,7 +176,6 @@ typedef struct xfs_mount { uint m_qflags; /* quota status flags */ xfs_trans_reservations_t m_reservations;/* precomputed res values */ __uint64_t m_maxicount; /* maximum inode count */ - __uint64_t m_maxioffset; /* maximum inode offset */ __uint64_t m_resblks; /* total reserved blocks */ __uint64_t m_resblks_avail;/* available reserved blocks */ __uint64_t m_resblks_save; /* reserved blks @ remount,ro */ @@ -297,7 +296,7 @@ xfs_preferred_iosize(xfs_mount_t *mp) PAGE_CACHE_SIZE)); } -#define XFS_MAXIOFFSET(mp) ((mp)->m_maxioffset) +#define XFS_MAXIOFFSET(mp) ((mp)->m_super->s_maxbytes) #define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \ ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN) -- GitLab From 32972383ca46223aa2b129826b3789721ec147aa Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 8 Jun 2012 15:44:54 +1000 Subject: [PATCH 0748/5711] xfs: make largest supported offset less shouty XFS_MAXIOFFSET() is just a simple macro that resolves to mp->m_maxioffset. It doesn't need to exist, and it just makes the code unnecessarily loud and shouty. Make it quiet and easy to read. Signed-off-by: Dave Chinner Reviewed-by: Eric Sandeen Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_file.c | 2 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_iomap.c | 2 +- fs/xfs/xfs_mount.h | 2 -- fs/xfs/xfs_qm.c | 2 +- fs/xfs/xfs_vnodeops.c | 10 +++++----- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 58b815ec8c91..848ffa77707b 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5517,7 +5517,7 @@ xfs_getbmap( if (xfs_get_extsz_hint(ip) || ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){ prealloced = 1; - fixlen = XFS_MAXIOFFSET(mp); + fixlen = mp->m_super->s_maxbytes; } else { prealloced = 0; fixlen = XFS_ISIZE(ip); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 9f7ec15a6522..59e22c989cd4 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -273,7 +273,7 @@ xfs_file_aio_read( } } - n = XFS_MAXIOFFSET(mp) - iocb->ki_pos; + n = mp->m_super->s_maxbytes - iocb->ki_pos; if (n <= 0 || size == 0) return 0; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index a59eea09930a..257f3c463e0e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1226,7 +1226,7 @@ xfs_itruncate_extents( * then there is nothing to do. */ first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); - last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + last_block = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); if (first_unmap_block == last_block) return 0; diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 4590cd1da432..915edf6639f0 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -285,7 +285,7 @@ xfs_iomap_eof_want_preallocate( * do any speculative allocation. */ start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1))); - count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + count_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); while (count_fsb > 0) { imaps = nimaps; firstblock = NULLFSBLOCK; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 47c6b3b3eb9c..90a45305407d 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -296,8 +296,6 @@ xfs_preferred_iosize(xfs_mount_t *mp) PAGE_CACHE_SIZE)); } -#define XFS_MAXIOFFSET(mp) ((mp)->m_super->s_maxbytes) - #define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \ ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN) #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 249db1987764..2e86fa0cfc0d 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -940,7 +940,7 @@ xfs_qm_dqiterate( map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP); lblkno = 0; - maxlblkcnt = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + maxlblkcnt = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); do { nmaps = XFS_DQITER_MAP_SIZE; /* diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b6a82d817a82..c22f4e0ecac1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -174,7 +174,7 @@ xfs_free_eofblocks( * of the file. If not, then there is nothing to do. */ end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); - last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); if (last_fsb <= end_fsb) return 0; map_len = last_fsb - end_fsb; @@ -2262,10 +2262,10 @@ xfs_change_file_space( llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len; - if ( (bf->l_start < 0) - || (bf->l_start > XFS_MAXIOFFSET(mp)) - || (bf->l_start + llen < 0) - || (bf->l_start + llen > XFS_MAXIOFFSET(mp))) + if (bf->l_start < 0 || + bf->l_start > mp->m_super->s_maxbytes || + bf->l_start + llen < 0 || + bf->l_start + llen > mp->m_super->s_maxbytes) return XFS_ERROR(EINVAL); bf->l_whence = 0; -- GitLab From 5276432997feb2366ac1e77949e94fe86a394813 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 8 Jun 2012 15:45:44 +1000 Subject: [PATCH 0749/5711] xfs: kill copy and paste segment checks in xfs_file_aio_read The generic segment check code now returns a count of the number of bytes in the iovec, so we don't need to roll our own anymore. Signed-off-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_file.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 59e22c989cd4..c4559c6e6f2c 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -236,7 +236,6 @@ xfs_file_aio_read( ssize_t ret = 0; int ioflags = 0; xfs_fsize_t n; - unsigned long seg; XFS_STATS_INC(xs_read_calls); @@ -247,19 +246,9 @@ xfs_file_aio_read( if (file->f_mode & FMODE_NOCMTIME) ioflags |= IO_INVIS; - /* START copy & waste from filemap.c */ - for (seg = 0; seg < nr_segs; seg++) { - const struct iovec *iv = &iovp[seg]; - - /* - * If any segment has a negative length, or the cumulative - * length ever wraps negative then return -EINVAL. - */ - size += iv->iov_len; - if (unlikely((ssize_t)(size|iv->iov_len) < 0)) - return XFS_ERROR(-EINVAL); - } - /* END copy & waste from filemap.c */ + ret = generic_segment_checks(iovp, &nr_segs, &size, VERIFY_WRITE); + if (ret < 0) + return ret; if (unlikely(ioflags & IO_ISDIRECT)) { xfs_buftarg_t *target = -- GitLab From 51c84223af604ce2d00d0416c30a38c50aed00bd Mon Sep 17 00:00:00 2001 From: Chen Baozi Date: Sat, 26 May 2012 00:48:47 +0800 Subject: [PATCH 0750/5711] xfs: fix typo in comment of xfs_dinode_t. There should be "XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR" instead of "XFS_DFORK_PTR, XFS_DFORK_DPTR, and XFS_DFORK_PTR". Signed-off-by: Chen Baozi Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_dinode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index a3721633abc8..1d9643b3dce6 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -33,7 +33,7 @@ typedef struct xfs_timestamp { * variable size the leftover area split into a data and an attribute fork. * The format of the data and attribute fork depends on the format of the * inode as indicated by di_format and di_aformat. To access the data and - * attribute use the XFS_DFORK_PTR, XFS_DFORK_DPTR, and XFS_DFORK_PTR macros + * attribute use the XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR macros * below. * * There is a very similar struct icdinode in xfs_inode which matches the -- GitLab From aeda3e7c6524956c616040f4265f16343b3edd83 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 31 May 2012 19:51:05 -0300 Subject: [PATCH 0751/5711] [media] v4l: Correct create_bufs documentation Patch id 6016af82eafcb6e086a8f2a2197b46029a843d68 ("[media] v4l2: use __u32 rather than enums in ioctl() structs") unintentionally changes the type of the format field in struct v4l2_create_buffers from struct v4l2_format to __u32. Revert that change. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-create-bufs.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index 765549ff8a71..7cf3116c2cc5 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml @@ -108,10 +108,9 @@ information. /> - __u32 + &v4l2-format; format - Filled in by the application, preserved by the driver. - See . + Filled in by the application, preserved by the driver. __u32 -- GitLab From 2584f5212d97b664be250ad5700a2d0fee31a10d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 5 Jun 2012 11:15:50 -0400 Subject: [PATCH 0752/5711] stable: update references to older 2.6 versions for 3.x Also add information on where the respective trees are. Signed-off-by: Paul Gortmaker Acked-by: Rob Landley Signed-off-by: Greg Kroah-Hartman --- Documentation/stable_kernel_rules.txt | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index f0ab5cf28fca..2edf833e8cb5 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -1,4 +1,4 @@ -Everything you ever wanted to know about Linux 2.6 -stable releases. +Everything you ever wanted to know about Linux -stable releases. Rules on what kind of patches are accepted, and which ones are not, into the "-stable" tree: @@ -36,10 +36,10 @@ Procedure for submitting patches to the -stable tree: cherry-picked than this can be specified in the following format in the sign-off area: - Cc: # .32.x: a1f84a3: sched: Check for idle - Cc: # .32.x: 1b9508f: sched: Rate-limit newidle - Cc: # .32.x: fd21073: sched: Fix affinity logic - Cc: # .32.x + Cc: # 3.3.x: a1f84a3: sched: Check for idle + Cc: # 3.3.x: 1b9508f: sched: Rate-limit newidle + Cc: # 3.3.x: fd21073: sched: Fix affinity logic + Cc: # 3.3.x Signed-off-by: Ingo Molnar The tag sequence has the meaning of: @@ -73,6 +73,15 @@ Review cycle: security kernel team, and not go through the normal review cycle. Contact the kernel security team for more details on this procedure. +Trees: + + - The queues of patches, for both completed versions and in progress + versions can be found at: + http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git + - The finalized and tagged releases of all stable kernels can be found + in separate branches per version at: + http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git + Review committee: -- GitLab From be3a07f71ca3ae300d652a653279321e85b9f3d0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 16:14:38 +0100 Subject: [PATCH 0753/5711] Extcon: Staticise extcon_class It's not referenced outside the core file. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon_class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c index f598a700ec15..99f7227834e3 100644 --- a/drivers/extcon/extcon_class.c +++ b/drivers/extcon/extcon_class.c @@ -65,7 +65,7 @@ const char *extcon_cable_name[] = { NULL, }; -struct class *extcon_class; +static struct class *extcon_class; #if defined(CONFIG_ANDROID) static struct class_compat *switch_class; #endif /* CONFIG_ANDROID */ -- GitLab From 6e7b4a59b3d7bb2dcd11c019354bf0c91037dadd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 9 Jun 2012 15:02:59 -0700 Subject: [PATCH 0754/5711] driver core: fix some kernel-doc warnings in dma*.c Fix kernel-doc warnings in drivers/base/dma*.c: Warning(drivers/base/dma-buf.c:498): No description found for parameter 'vaddr' Warning(drivers/base/dma-coherent.c:199): No description found for parameter 'ret' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-buf.c | 1 + drivers/base/dma-coherent.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 24e88fe29ec1..c30f3e1d0efc 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -493,6 +493,7 @@ EXPORT_SYMBOL_GPL(dma_buf_vmap); /** * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap. * @dmabuf: [in] buffer to vunmap + * @vaddr: [in] vmap to vunmap */ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) { diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 1b85949e3d2f..560a7173f810 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -186,6 +186,7 @@ EXPORT_SYMBOL(dma_release_from_coherent); * @vma: vm_area for the userspace memory * @vaddr: cpu address returned by dma_alloc_from_coherent * @size: size of the memory buffer allocated by dma_alloc_from_coherent + * @ret: result from remap_pfn_range() * * This checks whether the memory was allocated from the per-device * coherent memory pool and if so, maps that memory to the provided vma. -- GitLab From 98dcd59dd063dd8099d8dbccd84a40e927dc7138 Mon Sep 17 00:00:00 2001 From: "Camuso, Tony" Date: Sun, 10 Jun 2012 14:39:20 +0100 Subject: [PATCH 0755/5711] misc: hpilo: increase number of max supported channels Increase number of supported channels from 8 to 24. Make the number of channels configurable via module parameter max_ccb. Signed-off-by: Mark Rusk Signed-off-by: Tony Camuso Signed-off-by: Greg Kroah-Hartman --- drivers/misc/hpilo.c | 33 +++++++++++++++++++++------------ drivers/misc/hpilo.h | 4 +++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index fffc227181b0..6df0da4085e3 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -30,6 +30,7 @@ static struct class *ilo_class; static unsigned int ilo_major; +static unsigned int max_ccb = MIN_CCB; static char ilo_hwdev[MAX_ILO_DEV]; static inline int get_entry_id(int entry) @@ -424,7 +425,7 @@ static void ilo_set_reset(struct ilo_hwinfo *hw) * Mapped memory is zeroed on ilo reset, so set a per ccb flag * to indicate that this ccb needs to be closed and reopened. */ - for (slot = 0; slot < MAX_CCB; slot++) { + for (slot = 0; slot < max_ccb; slot++) { if (!hw->ccb_alloc[slot]) continue; set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb); @@ -535,7 +536,7 @@ static int ilo_close(struct inode *ip, struct file *fp) struct ilo_hwinfo *hw; unsigned long flags; - slot = iminor(ip) % MAX_CCB; + slot = iminor(ip) % max_ccb; hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); spin_lock(&hw->open_lock); @@ -566,7 +567,7 @@ static int ilo_open(struct inode *ip, struct file *fp) struct ilo_hwinfo *hw; unsigned long flags; - slot = iminor(ip) % MAX_CCB; + slot = iminor(ip) % max_ccb; hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); /* new ccb allocation */ @@ -663,7 +664,7 @@ static irqreturn_t ilo_isr(int irq, void *data) ilo_set_reset(hw); } - for (i = 0; i < MAX_CCB; i++) { + for (i = 0; i < max_ccb; i++) { if (!hw->ccb_alloc[i]) continue; if (pending & (1 << i)) @@ -697,14 +698,14 @@ static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) } /* map the adapter shared memory region */ - hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ); + hw->ram_vaddr = pci_iomap(pdev, 2, max_ccb * ILOHW_CCB_SZ); if (hw->ram_vaddr == NULL) { dev_err(&pdev->dev, "Error mapping shared mem\n"); goto mmio_free; } /* map the doorbell aperture */ - hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE); + hw->db_vaddr = pci_iomap(pdev, 3, max_ccb * ONE_DB_SIZE); if (hw->db_vaddr == NULL) { dev_err(&pdev->dev, "Error mapping doorbell\n"); goto ram_free; @@ -727,7 +728,7 @@ static void ilo_remove(struct pci_dev *pdev) clear_device(ilo_hw); minor = MINOR(ilo_hw->cdev.dev); - for (i = minor; i < minor + MAX_CCB; i++) + for (i = minor; i < minor + max_ccb; i++) device_destroy(ilo_class, MKDEV(ilo_major, i)); cdev_del(&ilo_hw->cdev); @@ -737,7 +738,7 @@ static void ilo_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); kfree(ilo_hw); - ilo_hwdev[(minor / MAX_CCB)] = 0; + ilo_hwdev[(minor / max_ccb)] = 0; } static int __devinit ilo_probe(struct pci_dev *pdev, @@ -746,6 +747,11 @@ static int __devinit ilo_probe(struct pci_dev *pdev, int devnum, minor, start, error; struct ilo_hwinfo *ilo_hw; + if (max_ccb > MAX_CCB) + max_ccb = MAX_CCB; + else if (max_ccb < MIN_CCB) + max_ccb = MIN_CCB; + /* find a free range for device files */ for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) { if (ilo_hwdev[devnum] == 0) { @@ -795,14 +801,14 @@ static int __devinit ilo_probe(struct pci_dev *pdev, cdev_init(&ilo_hw->cdev, &ilo_fops); ilo_hw->cdev.owner = THIS_MODULE; - start = devnum * MAX_CCB; - error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB); + start = devnum * max_ccb; + error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), max_ccb); if (error) { dev_err(&pdev->dev, "Could not add cdev\n"); goto remove_isr; } - for (minor = 0 ; minor < MAX_CCB; minor++) { + for (minor = 0 ; minor < max_ccb; minor++) { struct device *dev; dev = device_create(ilo_class, &pdev->dev, MKDEV(ilo_major, minor), NULL, @@ -879,11 +885,14 @@ static void __exit ilo_exit(void) class_destroy(ilo_class); } -MODULE_VERSION("1.2"); +MODULE_VERSION("1.3"); MODULE_ALIAS(ILO_NAME); MODULE_DESCRIPTION(ILO_NAME); MODULE_AUTHOR("David Altobelli "); MODULE_LICENSE("GPL v2"); +module_param(max_ccb, uint, 0444); +MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)"); + module_init(ilo_init); module_exit(ilo_exit); diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index 54e43adbdea1..b97672e0cf90 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h @@ -14,7 +14,9 @@ #define ILO_NAME "hpilo" /* max number of open channel control blocks per device, hw limited to 32 */ -#define MAX_CCB 8 +#define MAX_CCB 24 +/* min number of open channel control blocks per device, hw limited to 32 */ +#define MIN_CCB 8 /* max number of supported devices */ #define MAX_ILO_DEV 1 /* max number of files */ -- GitLab From 002176db8113c92d0bda02a47e3d2a4b8f9f55ea Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Thu, 14 Jun 2012 09:59:23 -0300 Subject: [PATCH 0756/5711] misc: at25: Parse dt settings This adds dt support to the at25 eeprom driver. Signed-off-by: Alexandre Pereira da Silva Tested-by: Roland Stigge Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/misc/at25.txt | 21 +++++++ drivers/misc/eeprom/at25.c | 61 ++++++++++++++----- 2 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/misc/at25.txt diff --git a/Documentation/devicetree/bindings/misc/at25.txt b/Documentation/devicetree/bindings/misc/at25.txt new file mode 100644 index 000000000000..ab3c327929dd --- /dev/null +++ b/Documentation/devicetree/bindings/misc/at25.txt @@ -0,0 +1,21 @@ +Atmel AT25 eeprom + +Required properties: +- compatible : "atmel,at25". +- reg : chip select number +- spi-max-frequency : max spi frequency to use + +- at25,byte-len : total eeprom size in bytes +- at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h +- at25,page-size : size of the eeprom page + +Examples: +at25@0 { + compatible = "atmel,at25"; + reg = <0> + spi-max-frequency = <5000000>; + + at25,byte-len = <0x8000>; + at25,addr-mode = <2>; + at25,page-size = <64>; +}; diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 0842c2994ee2..25003d6ceb56 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -19,7 +19,7 @@ #include #include - +#include /* * NOTE: this is an *EEPROM* driver. The vagaries of product naming @@ -305,25 +305,54 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf, static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; - const struct spi_eeprom *chip; + struct spi_eeprom chip; + struct device_node *np = spi->dev.of_node; int err; int sr; int addrlen; /* Chip description */ - chip = spi->dev.platform_data; - if (!chip) { - dev_dbg(&spi->dev, "no chip description\n"); - err = -ENODEV; - goto fail; - } + if (!spi->dev.platform_data) { + if (np) { + u32 val; + + memset(&chip, 0, sizeof(chip)); + strncpy(chip.name, np->name, 10); + + err = of_property_read_u32(np, "at25,byte-len", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); + goto fail; + } + chip.byte_len = val; + + err = of_property_read_u32(np, "at25,addr-mode", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); + goto fail; + } + chip.flags = (u16)val; + + err = of_property_read_u32(np, "at25,page-size", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); + goto fail; + } + chip.page_size = (u16)val; + } else { + dev_dbg(&spi->dev, "no chip description\n"); + err = -ENODEV; + goto fail; + } + } else + chip = *(struct spi_eeprom *)spi->dev.platform_data; /* For now we only support 8/16/24 bit addressing */ - if (chip->flags & EE_ADDR1) + if (chip.flags & EE_ADDR1) addrlen = 1; - else if (chip->flags & EE_ADDR2) + else if (chip.flags & EE_ADDR2) addrlen = 2; - else if (chip->flags & EE_ADDR3) + else if (chip.flags & EE_ADDR3) addrlen = 3; else { dev_dbg(&spi->dev, "unsupported address type\n"); @@ -348,7 +377,7 @@ static int at25_probe(struct spi_device *spi) } mutex_init(&at25->lock); - at25->chip = *chip; + at25->chip = chip; at25->spi = spi_dev_get(spi); dev_set_drvdata(&spi->dev, at25); at25->addrlen = addrlen; @@ -369,7 +398,7 @@ static int at25_probe(struct spi_device *spi) at25->mem.read = at25_mem_read; at25->bin.size = at25->chip.byte_len; - if (!(chip->flags & EE_READONLY)) { + if (!(chip.flags & EE_READONLY)) { at25->bin.write = at25_bin_write; at25->bin.attr.mode |= S_IWUSR; at25->mem.write = at25_mem_write; @@ -379,8 +408,8 @@ static int at25_probe(struct spi_device *spi) if (err) goto fail; - if (chip->setup) - chip->setup(&at25->mem, chip->context); + if (chip.setup) + chip.setup(&at25->mem, chip.context); dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n", (at25->bin.size < 1024) @@ -388,7 +417,7 @@ static int at25_probe(struct spi_device *spi) : (at25->bin.size / 1024), (at25->bin.size < 1024) ? "Byte" : "KByte", at25->chip.name, - (chip->flags & EE_READONLY) ? " (readonly)" : "", + (chip.flags & EE_READONLY) ? " (readonly)" : "", at25->chip.page_size); return 0; fail: -- GitLab From d7be394f7c2869e22d2258a1bba257661ca3fc52 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 6 Jun 2012 21:05:48 +0200 Subject: [PATCH 0757/5711] staging: zcache: don't limit number of pools per client Currently the amount of pools each client can use is limited to 16, this is and arbitrary limit which isn't really required by current implementation. This places and arbitrary limit on the number of mounted filesystems that can use cleancache. This patch removes that limit and uses IDR to do sparse mapping of pools in each client. Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 38 +++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index d0141fbc649e..174861f93b42 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "tmem.h" #include "../zsmalloc/zsmalloc.h" @@ -53,15 +54,13 @@ (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) #endif -#define MAX_POOLS_PER_CLIENT 16 - #define MAX_CLIENTS 16 #define LOCAL_CLIENT ((uint16_t)-1) MODULE_LICENSE("GPL"); struct zcache_client { - struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; + struct idr tmem_pools; struct zs_pool *zspool; bool allocated; atomic_t refcount; @@ -949,11 +948,9 @@ static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) goto out; atomic_inc(&cli->refcount); } - if (poolid < MAX_POOLS_PER_CLIENT) { - pool = cli->tmem_pools[poolid]; - if (pool != NULL) - atomic_inc(&pool->refcount); - } + pool = idr_find(&cli->tmem_pools, poolid); + if (pool != NULL) + atomic_inc(&pool->refcount); out: return pool; } @@ -987,6 +984,7 @@ int zcache_new_client(uint16_t cli_id) cli->zspool = zs_create_pool("zcache", ZCACHE_GFP_MASK); if (cli->zspool == NULL) goto out; + idr_init(&cli->tmem_pools); #endif ret = 0; out: @@ -1673,10 +1671,10 @@ static int zcache_destroy_pool(int cli_id, int pool_id) if (cli == NULL) goto out; atomic_inc(&cli->refcount); - pool = cli->tmem_pools[pool_id]; + pool = idr_find(&cli->tmem_pools, pool_id); if (pool == NULL) goto out; - cli->tmem_pools[pool_id] = NULL; + idr_remove(&cli->tmem_pools, pool_id); /* wait for pool activity on other cpus to quiesce */ while (atomic_read(&pool->refcount) != 0) ; @@ -1696,6 +1694,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) int poolid = -1; struct tmem_pool *pool; struct zcache_client *cli = NULL; + int r; if (cli_id == LOCAL_CLIENT) cli = &zcache_host; @@ -1710,20 +1709,25 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) goto out; } - for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) - if (cli->tmem_pools[poolid] == NULL) - break; - if (poolid >= MAX_POOLS_PER_CLIENT) { - pr_info("zcache: pool creation failed: max exceeded\n"); + do { + r = idr_pre_get(&cli->tmem_pools, GFP_ATOMIC); + if (r != 1) { + kfree(pool); + pr_info("zcache: pool creation failed: out of memory\n"); + goto out; + } + r = idr_get_new(&cli->tmem_pools, pool, &poolid); + } while (r == -EAGAIN); + if (r) { + pr_info("zcache: pool creation failed: error %d\n", r); kfree(pool); - poolid = -1; goto out; } + atomic_set(&pool->refcount, 0); pool->client = cli; pool->pool_id = poolid; tmem_new_pool(pool, flags); - cli->tmem_pools[poolid] = pool; pr_info("zcache: created %s tmem pool, id=%d, client=%d\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", poolid, cli_id); -- GitLab From 985eb50d553f4e2609778f999ecc5ec9837152f0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 18:09:51 -0700 Subject: [PATCH 0758/5711] staging: comedi: ni_atmio16d: remove the function tracing debug These printk's are #ifdef'ed out with an undefined symbol anyway. Just remove them. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 24 ++------------------ 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 95bee84b78ae..87992c99d413 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -236,10 +236,6 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices + 0; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_interrupt!\n"); -#endif - comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); comedi_event(dev, s); @@ -251,9 +247,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0, tmp; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_ai_cmdtest\n"); -#endif + /* make sure triggers are valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_NOW; @@ -355,9 +349,7 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, unsigned int timer, base_clock; unsigned int sample_count, tmp, chan, gain; int i; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_ai_cmd\n"); -#endif + /* This is slowly becoming a working command interface. * * It is still uber-experimental */ @@ -517,9 +509,6 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, int gain; int status; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_ai_insn_read\n"); -#endif chan = CR_CHAN(insn->chanspec); gain = CR_RANGE(insn->chanspec); @@ -538,9 +527,6 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, for (t = 0; t < ATMIO16D_TIMEOUT; t++) { /* check conversion status */ status = inw(dev->iobase + STAT_REG); -#ifdef DEBUG1 - printk(KERN_DEBUG "status=%x\n", status); -#endif if (status & STAT_AD_CONVAVAIL) { /* read the data now */ data[i] = inw(dev->iobase + AD_FIFO_REG); @@ -572,9 +558,6 @@ static int atmio16d_ao_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int i; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_ao_insn_read\n"); -#endif for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; @@ -588,9 +571,6 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev, int i; int chan; int d; -#ifdef DEBUG1 - printk(KERN_DEBUG "atmio16d_ao_insn_write\n"); -#endif chan = CR_CHAN(insn->chanspec); -- GitLab From 2b8557a734ab17d2cbb96a79bc267b30055e0ef3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 17:50:53 -0700 Subject: [PATCH 0759/5711] staging: comedi: pcl816: remove unneeded tests in pcl816_ai_cmdtest The step 2 tests of the start_src, scan_begin_src, and scan_end_src triggers to make sure they are unique are not needed. These triggers all only have one source and it was trivially validated in step 1. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index c3ee6d69b9a6..ba6911f063cb 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -493,26 +493,11 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, * are unique and mutually compatible */ - if (cmd->start_src != TRIG_NOW) { - cmd->start_src = TRIG_NOW; - err++; - } - - if (cmd->scan_begin_src != TRIG_FOLLOW) { - cmd->scan_begin_src = TRIG_FOLLOW; - err++; - } - if (cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_TIMER) { cmd->convert_src = TRIG_TIMER; err++; } - if (cmd->scan_end_src != TRIG_COUNT) { - cmd->scan_end_src = TRIG_COUNT; - err++; - } - if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) err++; -- GitLab From f7f111c214f218483a23d40a1f8e2d798b6e130a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 17:41:35 -0700 Subject: [PATCH 0760/5711] staging: comedi: pcl818: remove unneeded tests in ai_cmdtest The step 2 tests of the start_src, scan_begin_src, and scan_end_src triggers to make sure they are unique are not needed. These triggers all only have one source and it was trivially validated in step 1. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 66b2570fb24e..786c3b6442a6 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1299,22 +1299,9 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* step 2: make sure trigger sources are unique and mutually compatible */ - if (cmd->start_src != TRIG_NOW) { - cmd->start_src = TRIG_NOW; - err++; - } - if (cmd->scan_begin_src != TRIG_FOLLOW) { - cmd->scan_begin_src = TRIG_FOLLOW; - err++; - } if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) err++; - if (cmd->scan_end_src != TRIG_COUNT) { - cmd->scan_end_src = TRIG_COUNT; - err++; - } - if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) err++; -- GitLab From 31a4590ee31f2b46d28a4b85f84b04e90fa7ae00 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 17:58:07 -0700 Subject: [PATCH 0761/5711] staging: comedi: pcl812: remove unneeded tests in pcl812_ai_cmdtest The step 2 tests to make sure that the triggers are unique is not needed for single source triggers. These were already trivially validated in step 1. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 27 ------------------------- 1 file changed, 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 0a4074af8a60..511c90136439 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -612,33 +612,6 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, * unique and mutually compatible */ - if (cmd->start_src != TRIG_NOW) { - cmd->start_src = TRIG_NOW; - err++; - } - - if (cmd->scan_begin_src != TRIG_FOLLOW) { - cmd->scan_begin_src = TRIG_FOLLOW; - err++; - } - - if (devpriv->use_ext_trg) { - if (cmd->convert_src != TRIG_EXT) { - cmd->convert_src = TRIG_EXT; - err++; - } - } else { - if (cmd->convert_src != TRIG_TIMER) { - cmd->convert_src = TRIG_TIMER; - err++; - } - } - - if (cmd->scan_end_src != TRIG_COUNT) { - cmd->scan_end_src = TRIG_COUNT; - err++; - } - if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) err++; -- GitLab From 23bcbb6495d04df086450e0751fc9b9fd5e98936 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 18:22:07 -0700 Subject: [PATCH 0762/5711] staging: comedi: pcl812: remove PCL812_EXTDEBUG define and related code The PCL812_EXTDEBUG define enables a bunch of function tracing debug messages as well as a dump of the comedi_cmd info during the cmdtest. There are better ways to do the function tracing and the cmdtest dump shouldn't be in the driver. Just remove all of it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 100 +----------------------- 1 file changed, 4 insertions(+), 96 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 511c90136439..b0eb2ab89fd8 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -119,9 +119,6 @@ #include "8253.h" -/* if this is defined then a lot of messages is printed */ -#undef PCL812_EXTDEBUG - /* hardware types of the cards */ #define boardPCL812PG 0 /* and ACL-8112PG */ #define boardPCL813B 1 @@ -534,24 +531,6 @@ static int pcl812_do_insn_bits(struct comedi_device *dev, return 2; } -#ifdef PCL812_EXTDEBUG -/* -============================================================================== -*/ -static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd) -{ - printk(KERN_INFO "pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, - cmd->start_src, cmd->scan_begin_src, cmd->convert_src); - printk(KERN_INFO "pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e, - cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); - printk(KERN_INFO "pcl812 e=%d stopsrc=%x scanend=%x\n", e, - cmd->stop_src, cmd->scan_end_src); - printk(KERN_INFO "pcl812 e=%d stoparg=%d scanendarg=%d " - "chanlistlen=%d\n", e, cmd->stop_arg, cmd->scan_end_arg, - cmd->chanlist_len); -} -#endif - /* ============================================================================== */ @@ -562,10 +541,6 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp, divisor1, divisor2; -#ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n"); - pcl812_cmdtest_out(-1, cmd); -#endif /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; @@ -597,15 +572,8 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, if (!cmd->stop_src || tmp != cmd->stop_src) err++; - if (err) { -#ifdef PCL812_EXTDEBUG - pcl812_cmdtest_out(1, cmd); - printk - ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n", - err); -#endif + if (err) return 1; - } /* * step 2: make sure trigger sources are @@ -615,15 +583,8 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) err++; - if (err) { -#ifdef PCL812_EXTDEBUG - pcl812_cmdtest_out(2, cmd); - printk - ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n", - err); -#endif + if (err) return 2; - } /* step 3: make sure arguments are trivially compatible */ @@ -673,15 +634,8 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, } } - if (err) { -#ifdef PCL812_EXTDEBUG - pcl812_cmdtest_out(3, cmd); - printk - ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n", - err); -#endif + if (err) return 3; - } /* step 4: fix up any arguments */ @@ -696,14 +650,8 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, err++; } - if (err) { -#ifdef PCL812_EXTDEBUG - printk - ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n", - err); -#endif + if (err) return 4; - } return 0; } @@ -717,10 +665,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes; struct comedi_cmd *cmd = &s->async->cmd; -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n"); -#endif - if (cmd->start_src != TRIG_NOW) return -EINVAL; if (cmd->scan_begin_src != TRIG_FOLLOW) @@ -844,13 +788,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); release_dma_lock(dma_flags); enable_dma(devpriv->dma); -#ifdef PCL812_EXTDEBUG - printk - ("pcl812 EDBG: DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n", - devpriv->dma, devpriv->hwdmaptr[0], - devpriv->hwdmaptr[1], devpriv->dmabytestomove[0], - devpriv->dmabytestomove[1], devpriv->ai_eos); -#endif } switch (cmd->convert_src) { @@ -864,10 +801,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else /* let's go! */ outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE); -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cmd(...)\n"); -#endif - return 0; } @@ -987,9 +920,6 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) int len, bufptr; short *ptr; -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n"); -#endif ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf]; len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - devpriv->ai_poll_ptr; @@ -1022,9 +952,6 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) transfer_from_dma_buf(dev, s, ptr, bufptr, len); -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n"); -#endif return IRQ_HANDLED; } @@ -1141,10 +1068,6 @@ static void setup_range_channel(struct comedi_device *dev, static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, unsigned int divisor2) { -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, - divisor1, divisor2); -#endif outb(0xb4, dev->iobase + PCL812_CTRCTL); outb(0x74, dev->iobase + PCL812_CTRCTL); udelay(1); @@ -1155,9 +1078,6 @@ static void start_pacer(struct comedi_device *dev, int mode, outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1); outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1); } -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: END: start_pacer(...)\n"); -#endif } /* @@ -1187,9 +1107,6 @@ static void free_resources(struct comedi_device *dev) static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n"); -#endif if (devpriv->ai_dma) disable_dma(devpriv->dma); outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ @@ -1197,9 +1114,6 @@ static int pcl812_ai_cancel(struct comedi_device *dev, outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); start_pacer(dev, -1, 0, 0); /* stop 8254 */ outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cancel(...)\n"); -#endif return 0; } @@ -1210,9 +1124,6 @@ static void pcl812_reset(struct comedi_device *dev) { const struct pcl812_board *board = comedi_board(dev); -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_reset(...)\n"); -#endif outb(0, dev->iobase + PCL812_MUX); outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN); devpriv->old_chan_reg = -1; /* invalidate chain/gain memory */ @@ -1242,9 +1153,6 @@ static void pcl812_reset(struct comedi_device *dev) break; } udelay(5); -#ifdef PCL812_EXTDEBUG - printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_reset(...)\n"); -#endif } static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) -- GitLab From 1d489bab6651cfda44ddcb2ae0543ccf3cbd5400 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 19:12:18 -0700 Subject: [PATCH 0763/5711] staging: comedi: me4000: remove CALL_PDEBUG macro The CALL_PDEBUG macro is used to do function tracing in the driver. There are better ways to do this. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 61 ------------------------- drivers/staging/comedi/drivers/me4000.h | 8 ---- 2 files changed, 69 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index aae01f10b1c3..f5a0bcf65cf5 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -163,8 +163,6 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it) int result, i; struct me4000_board *board; - CALL_PDEBUG("In me4000_probe()\n"); - /* Allocate private memory */ if (alloc_private(dev, sizeof(struct me4000_info)) < 0) return -ENOMEM; @@ -308,9 +306,6 @@ found: static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p) { - - CALL_PDEBUG("In get_registers()\n"); - /*--------------------------- plx regbase -------------------------------*/ info->plx_regbase = pci_resource_start(pci_dev_p, 1); @@ -362,8 +357,6 @@ static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p) { int result; - CALL_PDEBUG("In init_board_info()\n"); - /* Init spin locks */ /* spin_lock_init(&info->preload_lock); */ /* spin_lock_init(&info->ai_ctrl_lock); */ @@ -394,8 +387,6 @@ static int init_ao_context(struct comedi_device *dev) { int i; - CALL_PDEBUG("In init_ao_context()\n"); - for (i = 0; i < thisboard->ao.count; i++) { /* spin_lock_init(&info->ao_context[i].use_lock); */ info->ao_context[i].irq = info->irq; @@ -475,9 +466,6 @@ static int init_ao_context(struct comedi_device *dev) static int init_ai_context(struct comedi_device *dev) { - - CALL_PDEBUG("In init_ai_context()\n"); - info->ai_context.irq = info->irq; info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG; @@ -509,9 +497,6 @@ static int init_ai_context(struct comedi_device *dev) static int init_dio_context(struct comedi_device *dev) { - - CALL_PDEBUG("In init_dio_context()\n"); - info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG; info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG; info->dio_context.port_0_reg = @@ -528,9 +513,6 @@ static int init_dio_context(struct comedi_device *dev) static int init_cnt_context(struct comedi_device *dev) { - - CALL_PDEBUG("In init_cnt_context()\n"); - info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG; info->cnt_context.counter_0_reg = info->timer_regbase + ME4000_CNT_COUNTER_0_REG; @@ -554,8 +536,6 @@ static int xilinx_download(struct comedi_device *dev) int idx = 0; int size = 0; - CALL_PDEBUG("In xilinx_download()\n"); - init_waitqueue_head(&queue); /* @@ -634,8 +614,6 @@ static int reset_board(struct comedi_device *dev) { unsigned long icr; - CALL_PDEBUG("In reset_board()\n"); - /* Make a hardware reset */ icr = me4000_inl(dev, info->plx_regbase + PLX_ICR); icr |= 0x40000000; @@ -708,8 +686,6 @@ static int me4000_ai_insn_read(struct comedi_device *dev, unsigned long tmp; long lval; - CALL_PDEBUG("In me4000_ai_insn_read()\n"); - if (insn->n == 0) { return 0; } else if (insn->n > 1) { @@ -827,8 +803,6 @@ static int me4000_ai_cancel(struct comedi_device *dev, { unsigned long tmp; - CALL_PDEBUG("In me4000_ai_cancel()\n"); - /* Stop any running conversion */ tmp = me4000_inl(dev, info->ai_context.ctrl_reg); tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); @@ -846,8 +820,6 @@ static int ai_check_chanlist(struct comedi_device *dev, int aref; int i; - CALL_PDEBUG("In ai_check_chanlist()\n"); - /* Check whether a channel list is available */ if (!cmd->chanlist_len) { printk(KERN_ERR @@ -933,8 +905,6 @@ static int ai_round_cmd_args(struct comedi_device *dev, int rest; - CALL_PDEBUG("In ai_round_cmd_args()\n"); - *init_ticks = 0; *scan_ticks = 0; *chan_ticks = 0; @@ -994,9 +964,6 @@ static void ai_write_timer(struct comedi_device *dev, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks) { - - CALL_PDEBUG("In ai_write_timer()\n"); - me4000_outl(dev, init_ticks - 1, info->ai_context.scan_pre_timer_low_reg); me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg); @@ -1020,8 +987,6 @@ static int ai_prepare(struct comedi_device *dev, unsigned long tmp = 0; - CALL_PDEBUG("In ai_prepare()\n"); - /* Write timer arguments */ ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); @@ -1089,8 +1054,6 @@ static int ai_write_chanlist(struct comedi_device *dev, unsigned int aref; int i; - CALL_PDEBUG("In ai_write_chanlist()\n"); - for (i = 0; i < cmd->chanlist_len; i++) { chan = CR_CHAN(cmd->chanlist[i]); rang = CR_RANGE(cmd->chanlist[i]); @@ -1127,8 +1090,6 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, unsigned int chan_ticks = 0; struct comedi_cmd *cmd = &s->async->cmd; - CALL_PDEBUG("In me4000_ai_do_cmd()\n"); - /* Reset the analog input */ err = me4000_ai_cancel(dev, s); if (err) @@ -1173,8 +1134,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, unsigned int scan_ticks; int err = 0; - CALL_PDEBUG("In me4000_ai_do_cmd_test()\n"); - PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd->subdev); PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd->flags); PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n", @@ -1717,8 +1676,6 @@ static int me4000_ao_insn_write(struct comedi_device *dev, int aref = CR_AREF(insn->chanspec); unsigned long tmp; - CALL_PDEBUG("In me4000_ao_insn_write()\n"); - if (insn->n == 0) { return 0; } else if (insn->n > 1) { @@ -1794,9 +1751,6 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - - CALL_PDEBUG("In me4000_dio_insn_bits()\n"); - /* Length of data must be 2 (mask and new data, see below) */ if (insn->n == 0) return 0; @@ -1851,8 +1805,6 @@ static int me4000_dio_insn_config(struct comedi_device *dev, unsigned long tmp; int chan = CR_CHAN(insn->chanspec); - CALL_PDEBUG("In me4000_dio_insn_config()\n"); - switch (data[0]) { default: return -EINVAL; @@ -1948,9 +1900,6 @@ static int me4000_dio_insn_config(struct comedi_device *dev, static int cnt_reset(struct comedi_device *dev, unsigned int channel) { - - CALL_PDEBUG("In cnt_reset()\n"); - switch (channel) { case 0: me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg); @@ -1982,8 +1931,6 @@ static int cnt_config(struct comedi_device *dev, unsigned int channel, { int tmp = 0; - CALL_PDEBUG("In cnt_config()\n"); - switch (channel) { case 0: tmp |= ME4000_CNT_COUNTER_0; @@ -2041,8 +1988,6 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, int err; - CALL_PDEBUG("In me4000_cnt_insn_config()\n"); - switch (data[0]) { case GPCT_RESET: if (insn->n != 1) { @@ -2087,8 +2032,6 @@ static int me4000_cnt_insn_read(struct comedi_device *dev, unsigned short tmp; - CALL_PDEBUG("In me4000_cnt_insn_read()\n"); - if (insn->n == 0) return 0; @@ -2137,8 +2080,6 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, unsigned short tmp; - CALL_PDEBUG("In me4000_cnt_insn_write()\n"); - if (insn->n == 0) { return 0; } else if (insn->n > 1) { @@ -2184,8 +2125,6 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int result; - CALL_PDEBUG("In me4000_attach()\n"); - result = me4000_probe(dev, it); if (result) return result; diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h index 733b19243c75..7087da27b716 100644 --- a/drivers/staging/comedi/drivers/me4000.h +++ b/drivers/staging/comedi/drivers/me4000.h @@ -28,18 +28,10 @@ Debug section ===========================================================================*/ -#undef ME4000_CALL_DEBUG /* Debug function entry and exit */ #undef ME4000_PORT_DEBUG /* Debug port access */ #undef ME4000_ISR_DEBUG /* Debug the interrupt service routine */ #undef ME4000_DEBUG /* General purpose debug masseges */ -#ifdef ME4000_CALL_DEBUG -#undef CALL_PDEBUG -#define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -#else -# define CALL_PDEBUG(fmt, args...) /* no debugging, do nothing */ -#endif - #ifdef ME4000_PORT_DEBUG #undef PORT_PDEBUG #define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -- GitLab From 3934954b4c76b049c79b28ed245425dee71c2472 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 19:12:35 -0700 Subject: [PATCH 0764/5711] staging: comedi: me4000: remove PORT_PDEBUG macro The PORT_PDEBUG macro is used to output the result of every port io operation. This shouldn't be in a mainline driver. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 4 ---- drivers/staging/comedi/drivers/me4000.h | 8 -------- 2 files changed, 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index f5a0bcf65cf5..ddb93844bb56 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -111,14 +111,12 @@ static int ai_write_chanlist(struct comedi_device *dev, static inline void me4000_outb(struct comedi_device *dev, unsigned char value, unsigned long port) { - PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port); outb(value, port); } static inline void me4000_outl(struct comedi_device *dev, unsigned long value, unsigned long port) { - PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port); outl(value, port); } @@ -127,7 +125,6 @@ static inline unsigned long me4000_inl(struct comedi_device *dev, { unsigned long value; value = inl(port); - PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port); return value; } @@ -136,7 +133,6 @@ static inline unsigned char me4000_inb(struct comedi_device *dev, { unsigned char value; value = inb(port); - PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port); return value; } diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h index 7087da27b716..d9ee3fbb1212 100644 --- a/drivers/staging/comedi/drivers/me4000.h +++ b/drivers/staging/comedi/drivers/me4000.h @@ -28,17 +28,9 @@ Debug section ===========================================================================*/ -#undef ME4000_PORT_DEBUG /* Debug port access */ #undef ME4000_ISR_DEBUG /* Debug the interrupt service routine */ #undef ME4000_DEBUG /* General purpose debug masseges */ -#ifdef ME4000_PORT_DEBUG -#undef PORT_PDEBUG -#define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -#else -#define PORT_PDEBUG(fmt, args...) /* no debugging, do nothing */ -#endif - #ifdef ME4000_ISR_DEBUG #undef ISR_PDEBUG #define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -- GitLab From d6cbe537c6f0cb99bc76a48d138ac21f7ec59548 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 19:12:55 -0700 Subject: [PATCH 0765/5711] staging: comedi: me4000: remove inline port io wrappers With the PORT_PDEBUG macro remove we can now remove the inline port io wrappers. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 247 ++++++++++-------------- 1 file changed, 98 insertions(+), 149 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index ddb93844bb56..5b4514621d00 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -104,38 +104,6 @@ static int ai_write_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); -/*----------------------------------------------------------------------------- - Meilhaus inline functions - ---------------------------------------------------------------------------*/ - -static inline void me4000_outb(struct comedi_device *dev, unsigned char value, - unsigned long port) -{ - outb(value, port); -} - -static inline void me4000_outl(struct comedi_device *dev, unsigned long value, - unsigned long port) -{ - outl(value, port); -} - -static inline unsigned long me4000_inl(struct comedi_device *dev, - unsigned long port) -{ - unsigned long value; - value = inl(port); - return value; -} - -static inline unsigned char me4000_inb(struct comedi_device *dev, - unsigned long port) -{ - unsigned char value; - value = inb(port); - return value; -} - static const struct comedi_lrange me4000_ai_range = { 4, { @@ -611,56 +579,45 @@ static int reset_board(struct comedi_device *dev) unsigned long icr; /* Make a hardware reset */ - icr = me4000_inl(dev, info->plx_regbase + PLX_ICR); + icr = inl(info->plx_regbase + PLX_ICR); icr |= 0x40000000; - me4000_outl(dev, icr, info->plx_regbase + PLX_ICR); + outl(icr, info->plx_regbase + PLX_ICR); icr &= ~0x40000000; - me4000_outl(dev, icr, info->plx_regbase + PLX_ICR); + outl(icr, info->plx_regbase + PLX_ICR); /* 0x8000 to the DACs means an output voltage of 0V */ - me4000_outl(dev, 0x8000, - info->me4000_regbase + ME4000_AO_00_SINGLE_REG); - me4000_outl(dev, 0x8000, - info->me4000_regbase + ME4000_AO_01_SINGLE_REG); - me4000_outl(dev, 0x8000, - info->me4000_regbase + ME4000_AO_02_SINGLE_REG); - me4000_outl(dev, 0x8000, - info->me4000_regbase + ME4000_AO_03_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG); /* Set both stop bits in the analog input control register */ - me4000_outl(dev, - ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, - info->me4000_regbase + ME4000_AI_CTRL_REG); + outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AI_CTRL_REG); /* Set both stop bits in the analog output control register */ - me4000_outl(dev, - ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, - info->me4000_regbase + ME4000_AO_00_CTRL_REG); - me4000_outl(dev, - ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, - info->me4000_regbase + ME4000_AO_01_CTRL_REG); - me4000_outl(dev, - ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, - info->me4000_regbase + ME4000_AO_02_CTRL_REG); - me4000_outl(dev, - ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, - info->me4000_regbase + ME4000_AO_03_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_00_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_01_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_02_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_03_CTRL_REG); /* Enable interrupts on the PLX */ - me4000_outl(dev, 0x43, info->plx_regbase + PLX_INTCSR); + outl(0x43, info->plx_regbase + PLX_INTCSR); /* Set the adustment register for AO demux */ - me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE, + outl(ME4000_AO_DEMUX_ADJUST_VALUE, info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG); /* * Set digital I/O direction for port 0 * to output on isolated versions */ - if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) { - me4000_outl(dev, 0x1, - info->me4000_regbase + ME4000_DIO_CTRL_REG); - } + if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) + outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG); return 0; } @@ -750,36 +707,34 @@ static int me4000_ai_insn_read(struct comedi_device *dev, entry |= ME4000_AI_LIST_LAST_ENTRY; /* Clear channel list, data fifo and both stop bits */ - tmp = me4000_inl(dev, info->ai_context.ctrl_reg); + tmp = inl(info->ai_context.ctrl_reg); tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO | ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Set the acquisition mode to single */ tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 | ME4000_AI_CTRL_BIT_MODE_2); - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Enable channel list and data fifo */ tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO; - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Generate channel list entry */ - me4000_outl(dev, entry, info->ai_context.channel_list_reg); + outl(entry, info->ai_context.channel_list_reg); /* Set the timer to maximum sample rate */ - me4000_outl(dev, ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg); - me4000_outl(dev, ME4000_AI_MIN_TICKS, - info->ai_context.chan_pre_timer_reg); + outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg); + outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg); /* Start conversion by dummy read */ - me4000_inl(dev, info->ai_context.start_reg); + inl(info->ai_context.start_reg); /* Wait until ready */ udelay(10); - if (! - (me4000_inl(dev, info->ai_context.status_reg) & + if (!(inl(info->ai_context.status_reg) & ME4000_AI_STATUS_BIT_EF_DATA)) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_insn_read(): " @@ -788,7 +743,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, } /* Read value from data fifo */ - lval = me4000_inl(dev, info->ai_context.data_reg) & 0xFFFF; + lval = inl(info->ai_context.data_reg) & 0xFFFF; data[0] = lval ^ 0x8000; return 1; @@ -800,12 +755,12 @@ static int me4000_ai_cancel(struct comedi_device *dev, unsigned long tmp; /* Stop any running conversion */ - tmp = me4000_inl(dev, info->ai_context.ctrl_reg); + tmp = inl(info->ai_context.ctrl_reg); tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Clear the control register */ - me4000_outl(dev, 0x0, info->ai_context.ctrl_reg); + outl(0x0, info->ai_context.ctrl_reg); return 0; } @@ -960,18 +915,16 @@ static void ai_write_timer(struct comedi_device *dev, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks) { - me4000_outl(dev, init_ticks - 1, - info->ai_context.scan_pre_timer_low_reg); - me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg); + outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg); + outl(0x0, info->ai_context.scan_pre_timer_high_reg); if (scan_ticks) { - me4000_outl(dev, scan_ticks - 1, - info->ai_context.scan_timer_low_reg); - me4000_outl(dev, 0x0, info->ai_context.scan_timer_high_reg); + outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg); + outl(0x0, info->ai_context.scan_timer_high_reg); } - me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_pre_timer_reg); - me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg); + outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg); + outl(chan_ticks - 1, info->ai_context.chan_timer_reg); } static int ai_prepare(struct comedi_device *dev, @@ -987,7 +940,7 @@ static int ai_prepare(struct comedi_device *dev, ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); /* Reset control register */ - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Start sources */ if ((cmd->start_src == TRIG_EXT && @@ -1020,12 +973,12 @@ static int ai_prepare(struct comedi_device *dev, /* Stop triggers */ if (cmd->stop_src == TRIG_COUNT) { - me4000_outl(dev, cmd->chanlist_len * cmd->stop_arg, + outl(cmd->chanlist_len * cmd->stop_arg, info->ai_context.sample_counter_reg); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; } else if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_COUNT) { - me4000_outl(dev, cmd->scan_end_arg, + outl(cmd->scan_end_arg, info->ai_context.sample_counter_reg); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; } else { @@ -1033,7 +986,7 @@ static int ai_prepare(struct comedi_device *dev, } /* Write the setup to the control register */ - me4000_outl(dev, tmp, info->ai_context.ctrl_reg); + outl(tmp, info->ai_context.ctrl_reg); /* Write the channel list */ ai_write_chanlist(dev, s, cmd); @@ -1071,7 +1024,7 @@ static int ai_write_chanlist(struct comedi_device *dev, else entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; - me4000_outl(dev, entry, info->ai_context.channel_list_reg); + outl(entry, info->ai_context.channel_list_reg); } return 0; @@ -1103,7 +1056,7 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, return err; /* Start acquistion by dummy read */ - me4000_inl(dev, info->ai_context.start_reg); + inl(info->ai_context.start_reg); return 0; } @@ -1516,14 +1469,13 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) return IRQ_HANDLED; } - if (me4000_inl(dev, - ai_context->irq_status_reg) & + if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_AI_HF) { ISR_PDEBUG ("me4000_ai_isr(): Fifo half full interrupt occurred\n"); /* Read status register to find out what happened */ - tmp = me4000_inl(dev, ai_context->ctrl_reg); + tmp = inl(ai_context->ctrl_reg); if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && @@ -1538,7 +1490,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; @@ -1566,7 +1518,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; @@ -1590,7 +1542,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_OVERFLOW; @@ -1605,13 +1557,12 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) /* Work is done, so reset the interrupt */ ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n"); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); } - if (me4000_inl(dev, - ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { + if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { ISR_PDEBUG ("me4000_ai_isr(): Sample counter interrupt occurred\n"); @@ -1621,10 +1572,10 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) * Acquisition is complete, so stop * conversion and disable all interrupts */ - tmp = me4000_inl(dev, ai_context->ctrl_reg); + tmp = inl(ai_context->ctrl_reg); tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); /* Poll data until fifo empty */ while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) { @@ -1645,9 +1596,9 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ISR_PDEBUG ("me4000_ai_isr(): Reset interrupt from sample counter\n"); tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; - me4000_outl(dev, tmp, ai_context->ctrl_reg); + outl(tmp, ai_context->ctrl_reg); } ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events); @@ -1703,15 +1654,15 @@ static int me4000_ao_insn_write(struct comedi_device *dev, } /* Stop any running conversion */ - tmp = me4000_inl(dev, info->ao_context[chan].ctrl_reg); + tmp = inl(info->ao_context[chan].ctrl_reg); tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; - me4000_outl(dev, tmp, info->ao_context[chan].ctrl_reg); + outl(tmp, info->ao_context[chan].ctrl_reg); /* Clear control register and set to single mode */ - me4000_outl(dev, 0x0, info->ao_context[chan].ctrl_reg); + outl(0x0, info->ao_context[chan].ctrl_reg); /* Write data value */ - me4000_outl(dev, data[0], info->ao_context[chan].single_reg); + outl(data[0], info->ao_context[chan].single_reg); /* Store in the mirror */ info->ao_context[chan].mirror = data[0]; @@ -1773,23 +1724,22 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, s->state |= data[0] & data[1]; /* Write out the new digital output lines */ - me4000_outl(dev, (s->state >> 0) & 0xFF, + outl((s->state >> 0) & 0xFF, info->dio_context.port_0_reg); - me4000_outl(dev, (s->state >> 8) & 0xFF, + outl((s->state >> 8) & 0xFF, info->dio_context.port_1_reg); - me4000_outl(dev, (s->state >> 16) & 0xFF, + outl((s->state >> 16) & 0xFF, info->dio_context.port_2_reg); - me4000_outl(dev, (s->state >> 24) & 0xFF, + outl((s->state >> 24) & 0xFF, info->dio_context.port_3_reg); } /* On return, data[1] contains the value of the digital input and output lines. */ - data[1] = - ((me4000_inl(dev, info->dio_context.port_0_reg) & 0xFF) << 0) | - ((me4000_inl(dev, info->dio_context.port_1_reg) & 0xFF) << 8) | - ((me4000_inl(dev, info->dio_context.port_2_reg) & 0xFF) << 16) | - ((me4000_inl(dev, info->dio_context.port_3_reg) & 0xFF) << 24); + data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) | + ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) | + ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) | + ((inl(info->dio_context.port_3_reg) & 0xFF) << 24); return 2; } @@ -1821,7 +1771,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * On the ME-4000 it is only possible to switch port wise (8 bit) */ - tmp = me4000_inl(dev, info->dio_context.ctrl_reg); + tmp = inl(info->dio_context.ctrl_reg); if (data[0] == INSN_CONFIG_DIO_OUTPUT) { if (chan < 8) { @@ -1835,7 +1785,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * If one the first port is a fixed output * port and the second is a fixed input port. */ - if (!me4000_inl(dev, info->dio_context.dir_reg)) + if (!inl(info->dio_context.dir_reg)) return -ENODEV; s->io_bits |= 0xFF00; @@ -1862,7 +1812,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * If one the first port is a fixed output * port and the second is a fixed input port. */ - if (!me4000_inl(dev, info->dio_context.dir_reg)) + if (!inl(info->dio_context.dir_reg)) return -ENODEV; s->io_bits &= ~0xFF; @@ -1885,7 +1835,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, } } - me4000_outl(dev, tmp, info->dio_context.ctrl_reg); + outl(tmp, info->dio_context.ctrl_reg); return 1; } @@ -1898,19 +1848,19 @@ static int cnt_reset(struct comedi_device *dev, unsigned int channel) { switch (channel) { case 0: - me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg); + outb(0x30, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_0_reg); + outb(0x00, info->cnt_context.counter_0_reg); break; case 1: - me4000_outb(dev, 0x70, info->cnt_context.ctrl_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg); + outb(0x70, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_1_reg); + outb(0x00, info->cnt_context.counter_1_reg); break; case 2: - me4000_outb(dev, 0xB0, info->cnt_context.ctrl_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg); - me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg); + outb(0xB0, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_2_reg); + outb(0x00, info->cnt_context.counter_2_reg); break; default: printk(KERN_ERR @@ -1972,7 +1922,7 @@ static int cnt_config(struct comedi_device *dev, unsigned int channel, /* Write the control word */ tmp |= 0x30; - me4000_outb(dev, tmp, info->cnt_context.ctrl_reg); + outb(tmp, info->cnt_context.ctrl_reg); return 0; } @@ -2041,21 +1991,21 @@ static int me4000_cnt_insn_read(struct comedi_device *dev, switch (insn->chanspec) { case 0: - tmp = me4000_inb(dev, info->cnt_context.counter_0_reg); + tmp = inb(info->cnt_context.counter_0_reg); data[0] = tmp; - tmp = me4000_inb(dev, info->cnt_context.counter_0_reg); + tmp = inb(info->cnt_context.counter_0_reg); data[0] |= tmp << 8; break; case 1: - tmp = me4000_inb(dev, info->cnt_context.counter_1_reg); + tmp = inb(info->cnt_context.counter_1_reg); data[0] = tmp; - tmp = me4000_inb(dev, info->cnt_context.counter_1_reg); + tmp = inb(info->cnt_context.counter_1_reg); data[0] |= tmp << 8; break; case 2: - tmp = me4000_inb(dev, info->cnt_context.counter_2_reg); + tmp = inb(info->cnt_context.counter_2_reg); data[0] = tmp; - tmp = me4000_inb(dev, info->cnt_context.counter_2_reg); + tmp = inb(info->cnt_context.counter_2_reg); data[0] |= tmp << 8; break; default: @@ -2089,21 +2039,21 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, switch (insn->chanspec) { case 0: tmp = data[0] & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_0_reg); + outb(tmp, info->cnt_context.counter_0_reg); tmp = (data[0] >> 8) & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_0_reg); + outb(tmp, info->cnt_context.counter_0_reg); break; case 1: tmp = data[0] & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_1_reg); + outb(tmp, info->cnt_context.counter_1_reg); tmp = (data[0] >> 8) & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_1_reg); + outb(tmp, info->cnt_context.counter_1_reg); break; case 2: tmp = data[0] & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_2_reg); + outb(tmp, info->cnt_context.counter_2_reg); tmp = (data[0] >> 8) & 0xFF; - me4000_outb(dev, tmp, info->cnt_context.counter_2_reg); + outb(tmp, info->cnt_context.counter_2_reg); break; default: printk(KERN_ERR @@ -2207,10 +2157,9 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) * Check for optoisolated ME-4000 version. If one the first * port is a fixed output port and the second is a fixed input port. */ - if (!me4000_inl(dev, info->dio_context.dir_reg)) { + if (!inl(info->dio_context.dir_reg)) { s->io_bits |= 0xFF; - me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0, - info->dio_context.dir_reg); + outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg); } /*========================================================================= -- GitLab From ef5bbfcb29db95c944bbfd4487454cd237d38b29 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 19:13:15 -0700 Subject: [PATCH 0766/5711] staging: comedi: me4000: remove ISR_PDEBUG macro The ISR_PDEBUG macro is used to output trace messages in the isr routine. This shouldn't be in a mainline driver. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 22 +--------------------- drivers/staging/comedi/drivers/me4000.h | 8 -------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 5b4514621d00..657d2fa8bd89 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1451,12 +1451,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) int c = 0; long lval; - ISR_PDEBUG("me4000_ai_isr() is executed\n"); - - if (!dev->attached) { - ISR_PDEBUG("me4000_ai_isr() premature interrupt\n"); + if (!dev->attached) return IRQ_NONE; - } /* Reset all events */ s->async->events = 0; @@ -1471,16 +1467,12 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_AI_HF) { - ISR_PDEBUG - ("me4000_ai_isr(): Fifo half full interrupt occurred\n"); - /* Read status register to find out what happened */ tmp = inl(ai_context->ctrl_reg); if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { - ISR_PDEBUG("me4000_ai_isr(): Fifo full\n"); c = ME4000_AI_FIFO_COUNT; /* @@ -1500,8 +1492,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { - ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n"); - s->async->events |= COMEDI_CB_BLOCK; c = ME4000_AI_FIFO_COUNT / 2; @@ -1527,8 +1517,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) "Undefined FIFO state\n", dev->minor); } - ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c); - for (i = 0; i < c; i++) { /* Read value from data fifo */ lval = inl(ai_context->data_reg) & 0xFFFF; @@ -1555,7 +1543,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) } /* Work is done, so reset the interrupt */ - ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n"); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; @@ -1563,9 +1550,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) } if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { - ISR_PDEBUG - ("me4000_ai_isr(): Sample counter interrupt occurred\n"); - s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA; /* @@ -1593,16 +1577,12 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) } /* Work is done, so reset the interrupt */ - ISR_PDEBUG - ("me4000_ai_isr(): Reset interrupt from sample counter\n"); tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; outl(tmp, ai_context->ctrl_reg); } - ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events); - if (s->async->events) comedi_event(dev, s); diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h index d9ee3fbb1212..f87dd197a96a 100644 --- a/drivers/staging/comedi/drivers/me4000.h +++ b/drivers/staging/comedi/drivers/me4000.h @@ -28,16 +28,8 @@ Debug section ===========================================================================*/ -#undef ME4000_ISR_DEBUG /* Debug the interrupt service routine */ #undef ME4000_DEBUG /* General purpose debug masseges */ -#ifdef ME4000_ISR_DEBUG -#undef ISR_PDEBUG -#define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -#else -#define ISR_PDEBUG(fmt, args...) /* no debugging, do nothing */ -#endif - #ifdef ME4000_DEBUG #undef PDEBUG #define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -- GitLab From 871784a5f86323ce654ba56e1f5e85f717a53a5e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jun 2012 19:13:42 -0700 Subject: [PATCH 0767/5711] staging: comedi: me4000: remove PDEBUG macro The PDEBUG macro is used to output a bunch of debug messages in the driver. These messages might be useful when first creating the driver but they shouldn't be in mainline. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 35 ------------------------- drivers/staging/comedi/drivers/me4000.h | 13 --------- 2 files changed, 48 deletions(-) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 657d2fa8bd89..72466bfa3b1d 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -860,11 +860,6 @@ static int ai_round_cmd_args(struct comedi_device *dev, *scan_ticks = 0; *chan_ticks = 0; - PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd->start_arg); - PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n", - cmd->scan_begin_arg); - PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd->convert_arg); - if (cmd->start_arg) { *init_ticks = (cmd->start_arg * 33) / 1000; rest = (cmd->start_arg * 33) % 1000; @@ -904,10 +899,6 @@ static int ai_round_cmd_args(struct comedi_device *dev, } } - PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks); - PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks); - PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks); - return 0; } @@ -1083,32 +1074,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, unsigned int scan_ticks; int err = 0; - PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd->subdev); - PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd->flags); - PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n", - cmd->start_src); - PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n", - cmd->start_arg); - PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n", - cmd->scan_begin_src); - PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n", - cmd->scan_begin_arg); - PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n", - cmd->convert_src); - PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n", - cmd->convert_arg); - PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n", - cmd->scan_end_src); - PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n", - cmd->scan_end_arg); - PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n", - cmd->stop_src); - PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd->stop_arg); - PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n", - (unsigned int)cmd->chanlist); - PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n", - cmd->chanlist_len); - /* Only rounding flags are implemented */ cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN; diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h index f87dd197a96a..5a4df4e4b236 100644 --- a/drivers/staging/comedi/drivers/me4000.h +++ b/drivers/staging/comedi/drivers/me4000.h @@ -24,19 +24,6 @@ #ifndef _ME4000_H_ #define _ME4000_H_ -/*============================================================================= - Debug section - ===========================================================================*/ - -#undef ME4000_DEBUG /* General purpose debug masseges */ - -#ifdef ME4000_DEBUG -#undef PDEBUG -#define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) -#else -#define PDEBUG(fmt, args...) /* no debugging, do nothing */ -#endif - /*============================================================================= PCI vendor and device IDs ===========================================================================*/ -- GitLab From 4d9505af7743828464d066795c6e1311c7884db4 Mon Sep 17 00:00:00 2001 From: Leed Aguilar Date: Thu, 14 Jun 2012 11:05:31 -0400 Subject: [PATCH 0768/5711] staging:iio:gyro:adis16080: remove sparse warnings Removed the following sparse warning: In function 'adis16080_read_raw': warning: 'ut' may be used uninitialized in this function Signed-off-by: Leed Aguilar Acked-by: Lars-Peter Clausen Cc: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/gyro/adis16080_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 11f1dccd7a0d..345e4fa778ba 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -82,7 +82,7 @@ static int adis16080_read_raw(struct iio_dev *indio_dev, long mask) { int ret = -EINVAL; - u16 ut; + u16 ut = 0; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); -- GitLab From c20c5a841cbe47f5b7812b57bd25397497e5fbc0 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 14 Jun 2012 14:23:53 -0700 Subject: [PATCH 0769/5711] ALSA: hda_intel: activate COMBO mode for Intel client chipsets This patch activates the COMBO position_fix for recent Intel client chipsets. COMBO mode is the recommended setting for Intel chipsets and eliminates HD audio warnings in dmesg. This patch has been tested on Lynx Point, Panther Point, and Cougar Pont. Signed-off-by: Seth Heasley Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d49926e4d19f..1a07d2188dd7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -535,6 +535,7 @@ enum { #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ +#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -2728,6 +2729,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) snd_printd(SFX "Using LPIB position fix\n"); return POS_FIX_LPIB; } + if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { + snd_printd(SFX "Using COMBO position fix\n"); + return POS_FIX_COMBO; + } return POS_FIX_AUTO; } @@ -3240,7 +3245,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | @@ -3248,11 +3253,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | -- GitLab From 4b6ace9e7176d93f819cec9df47faadaaceead4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 11:53:32 +0200 Subject: [PATCH 0770/5711] ALSA: hda - Add the support for VIA HDMI pin detection This patch adds the hotplug unsol event handling to simple_hdmi*(). It works on VIA VX900. If AMD or Nvidia chips support the pin-detection similarly, it can be added easily, too. Reported-by: Annie Liu Tested-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 696681826b01..8e7333b07b58 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1377,6 +1377,19 @@ static int simple_playback_build_pcms(struct hda_codec *codec) return 0; } +/* unsolicited event for jack sensing */ +static void simple_hdmi_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + snd_hda_jack_get_action(codec, res >> AC_UNSOL_RES_TAG_SHIFT); + snd_hda_jack_report_sync(codec); +} + +/* generic_hdmi_build_jack can be used for simple_hdmi, too, + * as long as spec->pins[] is set correctly + */ +#define simple_hdmi_build_jack generic_hdmi_build_jack + static int simple_playback_build_controls(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -1389,6 +1402,11 @@ static int simple_playback_build_controls(struct hda_codec *codec) spec->cvts[i].cvt_nid); if (err < 0) return err; + if (codec->patch_ops.unsol_event) { + err = simple_hdmi_build_jack(codec, i); + if (err < 0) + return err; + } } return 0; @@ -1876,6 +1894,7 @@ static struct hda_verb viahdmi_basic_init[] = { static int via_hdmi_init(struct hda_codec *codec) { snd_hda_sequence_write(codec, viahdmi_basic_init); + snd_hda_jack_report_sync(codec); return 0; } @@ -1884,6 +1903,7 @@ static const struct hda_codec_ops via_hdmi_patch_ops = { .build_pcms = simple_playback_build_pcms, .init = via_hdmi_init, .free = simple_playback_free, + .unsol_event = simple_hdmi_unsol_event, }; static struct hda_pcm_stream via_hdmi_digital_playback = { -- GitLab From 4f0110ced1b5d61e6df4871f6f800a9d3678bf26 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 12:45:43 +0200 Subject: [PATCH 0771/5711] ALSA: hda - Merge ATI/VIA HDMI simple init functions Just a minor code cleanup to use the same function for both AMD and VIA simple_hdmi*(). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 56 +++++++++++++++----------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8e7333b07b58..c9d0c98bbe86 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1412,6 +1412,24 @@ static int simple_playback_build_controls(struct hda_codec *codec) return 0; } +static int simple_playback_init(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int i; + + for (i = 0; i < spec->num_pins; i++) { + snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + /* some codecs require to unmute the pin */ + if (get_wcaps(codec, spec->pins[i].pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); + } + snd_hda_jack_report_sync(codec); + return 0; +} + static void simple_playback_free(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -1831,29 +1849,10 @@ static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { }, }; -static const struct hda_verb atihdmi_basic_init[] = { - /* enable digital output on pin widget */ - { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {} /* terminator */ -}; - -static int atihdmi_init(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - - snd_hda_sequence_write(codec, atihdmi_basic_init); - /* SI codec requires to unmute the pin */ - if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - return 0; -} - static const struct hda_codec_ops atihdmi_patch_ops = { .build_controls = simple_playback_build_controls, .build_pcms = simple_playback_build_pcms, - .init = atihdmi_init, + .init = simple_playback_init, .free = simple_playback_free, }; @@ -1872,6 +1871,7 @@ static int patch_atihdmi(struct hda_codec *codec) spec->multiout.max_channels = 2; spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; spec->num_cvts = 1; + spec->num_pins = 1; spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; spec->pins[0].pin_nid = ATIHDMI_PIN_NID; spec->pcm_playback = &atihdmi_pcm_digital_playback; @@ -1885,23 +1885,10 @@ static int patch_atihdmi(struct hda_codec *codec) #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ -static struct hda_verb viahdmi_basic_init[] = { - /* enable digital output on pin widget */ - { VIAHDMI_PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {} /* terminator */ -}; - -static int via_hdmi_init(struct hda_codec *codec) -{ - snd_hda_sequence_write(codec, viahdmi_basic_init); - snd_hda_jack_report_sync(codec); - return 0; -} - static const struct hda_codec_ops via_hdmi_patch_ops = { .build_controls = simple_playback_build_controls, .build_pcms = simple_playback_build_pcms, - .init = via_hdmi_init, + .init = simple_playback_init, .free = simple_playback_free, .unsol_event = simple_hdmi_unsol_event, }; @@ -1930,6 +1917,7 @@ static int patch_via_hdmi(struct hda_codec *codec) spec->multiout.max_channels = 2; spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ spec->num_cvts = 1; + spec->num_pins = 1; spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; spec->pins[0].pin_nid = VIAHDMI_PIN_NID; spec->pcm_playback = &via_hdmi_digital_playback; -- GitLab From 0c2498f1660878339350bea8d18550b1b87ca055 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 28 Jan 2011 09:40:40 +0100 Subject: [PATCH 0772/5711] pwm: Add PWM framework support This patch adds framework support for PWM (pulse width modulation) devices. The is a barebone PWM API already in the kernel under include/linux/pwm.h, but it does not allow for multiple drivers as each of them implements the pwm_*() functions. There are other PWM framework patches around from Bill Gatliff. Unlike his framework this one does not change the existing API for PWMs so that this framework can act as a drop in replacement for the existing API. Why another framework? Several people argue that there should not be another framework for PWMs but they should be integrated into one of the existing frameworks like led or hwmon. Unlike these frameworks the PWM framework is agnostic to the purpose of the PWM. In fact, a PWM can drive a LED, but this makes the LED framework a user of a PWM, like already done in leds-pwm.c. The gpio framework also is not suitable for PWMs. Every gpio could be turned into a PWM using timer based toggling, but on the other hand not every PWM hardware device can be turned into a gpio due to the lack of hardware capabilities. This patch does not try to improve the PWM API yet, this could be done in subsequent patches. Signed-off-by: Sascha Hauer Acked-by: Kurt Van Dijck Reviewed-by: Arnd Bergmann Reviewed-by: Matthias Kaehlcke Reviewed-by: Mark Brown Reviewed-by: Shawn Guo [thierry.reding@avionic-design.de: fixup typos, kerneldoc comments] Signed-off-by: Thierry Reding --- Documentation/pwm.txt | 54 ++++++++++ MAINTAINERS | 6 ++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/pwm/Kconfig | 12 +++ drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 227 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pwm.h | 38 +++++++ 8 files changed, 341 insertions(+) create mode 100644 Documentation/pwm.txt create mode 100644 drivers/pwm/Kconfig create mode 100644 drivers/pwm/Makefile create mode 100644 drivers/pwm/core.c diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt new file mode 100644 index 000000000000..03e39d145911 --- /dev/null +++ b/Documentation/pwm.txt @@ -0,0 +1,54 @@ +Pulse Width Modulation (PWM) interface + +This provides an overview about the Linux PWM interface + +PWMs are commonly used for controlling LEDs, fans or vibrators in +cell phones. PWMs with a fixed purpose have no need implementing +the Linux PWM API (although they could). However, PWMs are often +found as discrete devices on SoCs which have no fixed purpose. It's +up to the board designer to connect them to LEDs or fans. To provide +this kind of flexibility the generic PWM API exists. + +Identifying PWMs +---------------- + +Users of the legacy PWM API use unique IDs to refer to PWM devices. One +goal of the new PWM framework is to get rid of this global namespace. + +Using PWMs +---------- + +A PWM can be requested using pwm_request() and freed after usage with +pwm_free(). After being requested a PWM has to be configured using + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); + +To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). + +Implementing a PWM driver +------------------------- + +Currently there are two ways to implement pwm drivers. Traditionally +there only has been the barebone API meaning that each driver has +to implement the pwm_*() functions itself. This means that it's impossible +to have multiple PWM drivers in the system. For this reason it's mandatory +for new drivers to use the generic PWM framework. +A new PWM device can be added using pwmchip_add() and removed again with +pwmchip_remove(). pwmchip_add() takes a filled in struct pwm_chip as +argument which provides the ops and the pwm id to the framework. + +Locking +------- + +The PWM core list manipulations are protected by a mutex, so pwm_request() +and pwm_free() may not be called from an atomic context. Currently the +PWM core does not enforce any locking to pwm_enable(), pwm_disable() and +pwm_config(), so the calling context is currently driver specific. This +is an issue derived from the former barebone API and should be fixed soon. + +Helpers +------- + +Currently a PWM can only be configured with period_ns and duty_ns. For several +use cases freq_hz and duty_percent might be better. Instead of calculating +this in your driver please consider adding appropriate helpers to the framework. diff --git a/MAINTAINERS b/MAINTAINERS index 14bc7071f9df..67d6cb70cb7e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5487,6 +5487,12 @@ S: Maintained F: Documentation/video4linux/README.pvrusb2 F: drivers/media/video/pvrusb2/ +PWM core +M: Sascha Hauer +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/pwm/ + PXA2xx/PXA3xx SUPPORT M: Eric Miao M: Russell King diff --git a/drivers/Kconfig b/drivers/Kconfig index bfc918633fd9..805c432c9439 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -148,4 +148,6 @@ source "drivers/iio/Kconfig" source "drivers/vme/Kconfig" +source "drivers/pwm/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 2ba29ffef2cb..bd36f09f2246 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -8,6 +8,7 @@ # GPIO must come after pinctrl as gpios may need to mux pins etc obj-y += pinctrl/ obj-y += gpio/ +obj-y += pwm/ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig new file mode 100644 index 000000000000..93c1052291a3 --- /dev/null +++ b/drivers/pwm/Kconfig @@ -0,0 +1,12 @@ +menuconfig PWM + bool "PWM Support" + help + This enables PWM support through the generic PWM framework. + You only need to enable this, if you also want to enable + one or more of the PWM drivers below. + + If unsure, say N. + +if PWM + +endif diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile new file mode 100644 index 000000000000..3469c3d28b7a --- /dev/null +++ b/drivers/pwm/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PWM) += core.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c new file mode 100644 index 000000000000..0b8a38eca23c --- /dev/null +++ b/drivers/pwm/core.c @@ -0,0 +1,227 @@ +/* + * Generic pwmlib implementation + * + * Copyright (C) 2011 Sascha Hauer + * + * 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, 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. + * + * 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 + +struct pwm_device { + struct pwm_chip *chip; + const char *label; + unsigned long flags; +#define FLAG_REQUESTED 0 +#define FLAG_ENABLED 1 + struct list_head node; +}; + +static LIST_HEAD(pwm_list); + +static DEFINE_MUTEX(pwm_lock); + +static struct pwm_device *_find_pwm(int pwm_id) +{ + struct pwm_device *pwm; + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->chip->pwm_id == pwm_id) + return pwm; + } + + return NULL; +} + +/** + * pwmchip_add() - register a new PWM chip + * @chip: the PWM chip to add + */ +int pwmchip_add(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + int ret = 0; + + pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; + + pwm->chip = chip; + + mutex_lock(&pwm_lock); + + if (chip->pwm_id >= 0 && _find_pwm(chip->pwm_id)) { + ret = -EBUSY; + goto out; + } + + list_add_tail(&pwm->node, &pwm_list); +out: + mutex_unlock(&pwm_lock); + + if (ret) + kfree(pwm); + + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_add); + +/** + * pwmchip_remove() - remove a PWM chip + * @chip: the PWM chip to remove + * + * Removes a PWM chip. This function may return busy if the PWM chip provides + * a PWM device that is still requested. + */ +int pwmchip_remove(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + int ret = 0; + + mutex_lock(&pwm_lock); + + pwm = _find_pwm(chip->pwm_id); + if (!pwm) { + ret = -ENOENT; + goto out; + } + + if (test_bit(FLAG_REQUESTED, &pwm->flags)) { + ret = -EBUSY; + goto out; + } + + list_del(&pwm->node); + + kfree(pwm); +out: + mutex_unlock(&pwm_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_remove); + +/** + * pwm_request() - request a PWM device + * @pwm_id: global PWM device index + * @label: PWM device label + */ +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int ret; + + mutex_lock(&pwm_lock); + + pwm = _find_pwm(pwm_id); + if (!pwm) { + pwm = ERR_PTR(-ENOENT); + goto out; + } + + if (test_bit(FLAG_REQUESTED, &pwm->flags)) { + pwm = ERR_PTR(-EBUSY); + goto out; + } + + if (!try_module_get(pwm->chip->ops->owner)) { + pwm = ERR_PTR(-ENODEV); + goto out; + } + + if (pwm->chip->ops->request) { + ret = pwm->chip->ops->request(pwm->chip); + if (ret) { + pwm = ERR_PTR(ret); + goto out_put; + } + } + + pwm->label = label; + set_bit(FLAG_REQUESTED, &pwm->flags); + + goto out; + +out_put: + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); + + return pwm; +} +EXPORT_SYMBOL_GPL(pwm_request); + +/** + * pwm_free() - free a PWM device + * @pwm: PWM device + */ +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (!test_and_clear_bit(FLAG_REQUESTED, &pwm->flags)) { + pr_warning("PWM device already freed\n"); + goto out; + } + + pwm->label = NULL; + + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL_GPL(pwm_free); + +/** + * pwm_config() - change a PWM device configuration + * @pwm: PWM device + * @duty_ns: "on" time (in nanoseconds) + * @period_ns: duration (in nanoseconds) of one cycle + */ +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + return pwm->chip->ops->config(pwm->chip, duty_ns, period_ns); +} +EXPORT_SYMBOL_GPL(pwm_config); + +/** + * pwm_enable() - start a PWM output toggling + * @pwm: PWM device + */ +int pwm_enable(struct pwm_device *pwm) +{ + if (!test_and_set_bit(FLAG_ENABLED, &pwm->flags)) + return pwm->chip->ops->enable(pwm->chip); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_enable); + +/** + * pwm_disable() - stop a PWM output toggling + * @pwm: PWM device + */ +void pwm_disable(struct pwm_device *pwm) +{ + if (test_and_clear_bit(FLAG_ENABLED, &pwm->flags)) + pwm->chip->ops->disable(pwm->chip); +} +EXPORT_SYMBOL_GPL(pwm_disable); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7c775751392c..1f308a13105f 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -28,4 +28,42 @@ int pwm_enable(struct pwm_device *pwm); */ void pwm_disable(struct pwm_device *pwm); +#ifdef CONFIG_PWM +struct pwm_chip; + +/** + * struct pwm_ops - PWM controller operations + * @request: optional hook for requesting a PWM + * @free: optional hook for freeing a PWM + * @config: configure duty cycles and period length for this PWM + * @enable: enable PWM output toggling + * @disable: disable PWM output toggling + * @owner: helps prevent removal of modules exporting active PWMs + */ +struct pwm_ops { + int (*request)(struct pwm_chip *chip); + void (*free)(struct pwm_chip *chip); + int (*config)(struct pwm_chip *chip, int duty_ns, + int period_ns); + int (*enable)(struct pwm_chip *chip); + void (*disable)(struct pwm_chip *chip); + struct module *owner; +}; + +/** + * struct pwm_chip - abstract a PWM + * @pwm_id: global PWM device index + * @label: PWM device label + * @ops: controller operations + */ +struct pwm_chip { + int pwm_id; + const char *label; + struct pwm_ops *ops; +}; + +int pwmchip_add(struct pwm_chip *chip); +int pwmchip_remove(struct pwm_chip *chip); +#endif + #endif /* __LINUX_PWM_H */ -- GitLab From f051c466cf690ac661d713d3ceb56b4efcecc853 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 14 Dec 2011 11:12:23 +0100 Subject: [PATCH 0773/5711] pwm: Allow chips to support multiple PWMs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many PWM controllers provide access to more than a single PWM output and may even share some resource among them. Allowing a PWM chip to provide multiple PWM devices enables better sharing of those resources. As a side-effect this change allows easy integration with the device tree where a given PWM can be looked up based on the PWM chip's phandle and a corresponding index. This commit modifies the PWM core to support multiple PWMs per struct pwm_chip. It achieves this in a similar way to how gpiolib works, by allowing PWM ranges to be requested dynamically (pwm_chip.base == -1) or starting at a given offset (pwm_chip.base >= 0). A chip specifies how many PWMs it controls using the npwm member. Each of the functions in the pwm_ops structure gets an additional argument that specified the PWM number (it can be converted to a per-chip index by subtracting the chip's base). The total maximum number of PWM devices is currently fixed to 1024 while the data is actually stored in a radix tree, thus saving resources if not all of them are used. Reviewed-by: Mark Brown Reviewed-by: Shawn Guo [eric@eukrea.com: fix error handling in pwmchip_add] Signed-off-by: Eric Bénard Signed-off-by: Thierry Reding --- Documentation/pwm.txt | 9 +- drivers/pwm/core.c | 267 ++++++++++++++++++++++++++++++------------ include/linux/pwm.h | 71 +++++++++-- 3 files changed, 254 insertions(+), 93 deletions(-) diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 03e39d145911..48f598acdd16 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -33,9 +33,12 @@ there only has been the barebone API meaning that each driver has to implement the pwm_*() functions itself. This means that it's impossible to have multiple PWM drivers in the system. For this reason it's mandatory for new drivers to use the generic PWM framework. -A new PWM device can be added using pwmchip_add() and removed again with -pwmchip_remove(). pwmchip_add() takes a filled in struct pwm_chip as -argument which provides the ops and the pwm id to the framework. + +A new PWM controller/chip can be added using pwmchip_add() and removed +again with pwmchip_remove(). pwmchip_add() takes a filled in struct +pwm_chip as argument which provides a description of the PWM chip, the +number of PWM devices provider by the chip and the chip-specific +implementation of the supported PWM operations to the framework. Locking ------- diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 0b8a38eca23c..a447be128328 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -2,6 +2,7 @@ * Generic pwmlib implementation * * Copyright (C) 2011 Sascha Hauer + * Copyright (C) 2011-2012 Avionic Design GmbH * * 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 @@ -20,66 +21,161 @@ #include #include +#include #include #include #include #include #include -struct pwm_device { - struct pwm_chip *chip; - const char *label; - unsigned long flags; -#define FLAG_REQUESTED 0 -#define FLAG_ENABLED 1 - struct list_head node; -}; - -static LIST_HEAD(pwm_list); +#define MAX_PWMS 1024 static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_chips); +static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); +static RADIX_TREE(pwm_tree, GFP_KERNEL); -static struct pwm_device *_find_pwm(int pwm_id) +static struct pwm_device *pwm_to_device(unsigned int pwm) { - struct pwm_device *pwm; + return radix_tree_lookup(&pwm_tree, pwm); +} + +static int alloc_pwms(int pwm, unsigned int count) +{ + unsigned int from = 0; + unsigned int start; + + if (pwm >= MAX_PWMS) + return -EINVAL; + + if (pwm >= 0) + from = pwm; - list_for_each_entry(pwm, &pwm_list, node) { - if (pwm->chip->pwm_id == pwm_id) - return pwm; + start = bitmap_find_next_zero_area(allocated_pwms, MAX_PWMS, from, + count, 0); + + if (pwm >= 0 && start != pwm) + return -EEXIST; + + if (start + count > MAX_PWMS) + return -ENOSPC; + + return start; +} + +static void free_pwms(struct pwm_chip *chip) +{ + unsigned int i; + + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; + radix_tree_delete(&pwm_tree, pwm->pwm); } - return NULL; + bitmap_clear(allocated_pwms, chip->base, chip->npwm); + + kfree(chip->pwms); + chip->pwms = NULL; +} + +static int pwm_device_request(struct pwm_device *pwm, const char *label) +{ + int err; + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + return -EBUSY; + + if (!try_module_get(pwm->chip->ops->owner)) + return -ENODEV; + + if (pwm->chip->ops->request) { + err = pwm->chip->ops->request(pwm->chip, pwm); + if (err) { + module_put(pwm->chip->ops->owner); + return err; + } + } + + set_bit(PWMF_REQUESTED, &pwm->flags); + pwm->label = label; + + return 0; +} + +/** + * pwm_set_chip_data() - set private chip data for a PWM + * @pwm: PWM device + * @data: pointer to chip-specific data + */ +int pwm_set_chip_data(struct pwm_device *pwm, void *data) +{ + if (!pwm) + return -EINVAL; + + pwm->chip_data = data; + + return 0; +} + +/** + * pwm_get_chip_data() - get private chip data for a PWM + * @pwm: PWM device + */ +void *pwm_get_chip_data(struct pwm_device *pwm) +{ + return pwm ? pwm->chip_data : NULL; } /** * pwmchip_add() - register a new PWM chip * @chip: the PWM chip to add + * + * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base + * will be used. */ int pwmchip_add(struct pwm_chip *chip) { struct pwm_device *pwm; - int ret = 0; - - pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); - if (!pwm) - return -ENOMEM; + unsigned int i; + int ret; - pwm->chip = chip; + if (!chip || !chip->dev || !chip->ops || !chip->ops->config || + !chip->ops->enable || !chip->ops->disable) + return -EINVAL; mutex_lock(&pwm_lock); - if (chip->pwm_id >= 0 && _find_pwm(chip->pwm_id)) { - ret = -EBUSY; + ret = alloc_pwms(chip->base, chip->npwm); + if (ret < 0) + goto out; + + chip->pwms = kzalloc(chip->npwm * sizeof(*pwm), GFP_KERNEL); + if (!chip->pwms) { + ret = -ENOMEM; goto out; } - list_add_tail(&pwm->node, &pwm_list); -out: - mutex_unlock(&pwm_lock); + chip->base = ret; + + for (i = 0; i < chip->npwm; i++) { + pwm = &chip->pwms[i]; + + pwm->chip = chip; + pwm->pwm = chip->base + i; + pwm->hwpwm = i; - if (ret) - kfree(pwm); + radix_tree_insert(&pwm_tree, pwm->pwm, pwm); + } + + bitmap_set(allocated_pwms, chip->base, chip->npwm); + + INIT_LIST_HEAD(&chip->list); + list_add(&chip->list, &pwm_chips); + ret = 0; + +out: + mutex_unlock(&pwm_lock); return ret; } EXPORT_SYMBOL_GPL(pwmchip_add); @@ -93,28 +189,25 @@ EXPORT_SYMBOL_GPL(pwmchip_add); */ int pwmchip_remove(struct pwm_chip *chip) { - struct pwm_device *pwm; + unsigned int i; int ret = 0; mutex_lock(&pwm_lock); - pwm = _find_pwm(chip->pwm_id); - if (!pwm) { - ret = -ENOENT; - goto out; - } + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; - if (test_bit(FLAG_REQUESTED, &pwm->flags)) { - ret = -EBUSY; - goto out; + if (test_bit(PWMF_REQUESTED, &pwm->flags)) { + ret = -EBUSY; + goto out; + } } - list_del(&pwm->node); + list_del_init(&chip->list); + free_pwms(chip); - kfree(pwm); out: mutex_unlock(&pwm_lock); - return ret; } EXPORT_SYMBOL_GPL(pwmchip_remove); @@ -124,50 +217,64 @@ EXPORT_SYMBOL_GPL(pwmchip_remove); * @pwm_id: global PWM device index * @label: PWM device label */ -struct pwm_device *pwm_request(int pwm_id, const char *label) +struct pwm_device *pwm_request(int pwm, const char *label) { - struct pwm_device *pwm; - int ret; + struct pwm_device *dev; + int err; + + if (pwm < 0 || pwm >= MAX_PWMS) + return ERR_PTR(-EINVAL); mutex_lock(&pwm_lock); - pwm = _find_pwm(pwm_id); - if (!pwm) { - pwm = ERR_PTR(-ENOENT); + dev = pwm_to_device(pwm); + if (!dev) { + dev = ERR_PTR(-EPROBE_DEFER); goto out; } - if (test_bit(FLAG_REQUESTED, &pwm->flags)) { - pwm = ERR_PTR(-EBUSY); - goto out; - } + err = pwm_device_request(dev, label); + if (err < 0) + dev = ERR_PTR(err); - if (!try_module_get(pwm->chip->ops->owner)) { - pwm = ERR_PTR(-ENODEV); - goto out; - } +out: + mutex_unlock(&pwm_lock); - if (pwm->chip->ops->request) { - ret = pwm->chip->ops->request(pwm->chip); - if (ret) { - pwm = ERR_PTR(ret); - goto out_put; - } - } + return dev; +} +EXPORT_SYMBOL_GPL(pwm_request); - pwm->label = label; - set_bit(FLAG_REQUESTED, &pwm->flags); +/** + * pwm_request_from_chip() - request a PWM device relative to a PWM chip + * @chip: PWM chip + * @index: per-chip index of the PWM to request + * @label: a literal description string of this PWM + * + * Returns the PWM at the given index of the given PWM chip. A negative error + * code is returned if the index is not valid for the specified PWM chip or + * if the PWM device cannot be requested. + */ +struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, + unsigned int index, + const char *label) +{ + struct pwm_device *pwm; + int err; - goto out; + if (!chip || index >= chip->npwm) + return ERR_PTR(-EINVAL); -out_put: - module_put(pwm->chip->ops->owner); -out: - mutex_unlock(&pwm_lock); + mutex_lock(&pwm_lock); + pwm = &chip->pwms[index]; + err = pwm_device_request(pwm, label); + if (err < 0) + pwm = ERR_PTR(err); + + mutex_unlock(&pwm_lock); return pwm; } -EXPORT_SYMBOL_GPL(pwm_request); +EXPORT_SYMBOL_GPL(pwm_request_from_chip); /** * pwm_free() - free a PWM device @@ -177,11 +284,14 @@ void pwm_free(struct pwm_device *pwm) { mutex_lock(&pwm_lock); - if (!test_and_clear_bit(FLAG_REQUESTED, &pwm->flags)) { + if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { pr_warning("PWM device already freed\n"); goto out; } + if (pwm->chip->ops->free) + pwm->chip->ops->free(pwm->chip, pwm); + pwm->label = NULL; module_put(pwm->chip->ops->owner); @@ -198,7 +308,10 @@ EXPORT_SYMBOL_GPL(pwm_free); */ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { - return pwm->chip->ops->config(pwm->chip, duty_ns, period_ns); + if (!pwm || period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); } EXPORT_SYMBOL_GPL(pwm_config); @@ -208,10 +321,10 @@ EXPORT_SYMBOL_GPL(pwm_config); */ int pwm_enable(struct pwm_device *pwm) { - if (!test_and_set_bit(FLAG_ENABLED, &pwm->flags)) - return pwm->chip->ops->enable(pwm->chip); + if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags)) + return pwm->chip->ops->enable(pwm->chip, pwm); - return 0; + return pwm ? 0 : -EINVAL; } EXPORT_SYMBOL_GPL(pwm_enable); @@ -221,7 +334,7 @@ EXPORT_SYMBOL_GPL(pwm_enable); */ void pwm_disable(struct pwm_device *pwm) { - if (test_and_clear_bit(FLAG_ENABLED, &pwm->flags)) - pwm->chip->ops->disable(pwm->chip); + if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags)) + pwm->chip->ops->disable(pwm->chip, pwm); } EXPORT_SYMBOL_GPL(pwm_disable); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 1f308a13105f..57103911f4c7 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -31,6 +31,33 @@ void pwm_disable(struct pwm_device *pwm); #ifdef CONFIG_PWM struct pwm_chip; +enum { + PWMF_REQUESTED = 1 << 0, + PWMF_ENABLED = 1 << 1, +}; + +struct pwm_device { + const char *label; + unsigned long flags; + unsigned int hwpwm; + unsigned int pwm; + struct pwm_chip *chip; + void *chip_data; + + unsigned int period; /* in nanoseconds */ +}; + +static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) +{ + if (pwm) + pwm->period = period; +} + +static inline unsigned int pwm_get_period(struct pwm_device *pwm) +{ + return pwm ? pwm->period : 0; +} + /** * struct pwm_ops - PWM controller operations * @request: optional hook for requesting a PWM @@ -41,29 +68,47 @@ struct pwm_chip; * @owner: helps prevent removal of modules exporting active PWMs */ struct pwm_ops { - int (*request)(struct pwm_chip *chip); - void (*free)(struct pwm_chip *chip); - int (*config)(struct pwm_chip *chip, int duty_ns, - int period_ns); - int (*enable)(struct pwm_chip *chip); - void (*disable)(struct pwm_chip *chip); + int (*request)(struct pwm_chip *chip, + struct pwm_device *pwm); + void (*free)(struct pwm_chip *chip, + struct pwm_device *pwm); + int (*config)(struct pwm_chip *chip, + struct pwm_device *pwm, + int duty_ns, int period_ns); + int (*enable)(struct pwm_chip *chip, + struct pwm_device *pwm); + void (*disable)(struct pwm_chip *chip, + struct pwm_device *pwm); struct module *owner; }; /** - * struct pwm_chip - abstract a PWM - * @pwm_id: global PWM device index - * @label: PWM device label - * @ops: controller operations + * struct pwm_chip - abstract a PWM controller + * @dev: device providing the PWMs + * @list: list node for internal use + * @ops: callbacks for this PWM controller + * @base: number of first PWM controlled by this chip + * @npwm: number of PWMs controlled by this chip + * @pwms: array of PWM devices allocated by the framework */ struct pwm_chip { - int pwm_id; - const char *label; - struct pwm_ops *ops; + struct device *dev; + struct list_head list; + const struct pwm_ops *ops; + int base; + unsigned int npwm; + + struct pwm_device *pwms; }; +int pwm_set_chip_data(struct pwm_device *pwm, void *data); +void *pwm_get_chip_data(struct pwm_device *pwm); + int pwmchip_add(struct pwm_chip *chip); int pwmchip_remove(struct pwm_chip *chip); +struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, + unsigned int index, + const char *label); #endif #endif /* __LINUX_PWM_H */ -- GitLab From 62099abf67a20cfb98d4c031fb1925e10a78ee1b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 26 Mar 2012 09:31:48 +0200 Subject: [PATCH 0774/5711] pwm: Add debugfs interface This commit adds a debugfs interface that can be used to list the current internal state of the PWM devices registered with the PWM framework. Reviewed-by: Mark Brown Reviewed-by: Shawn Guo Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pwm.h | 6 +++ 2 files changed, 96 insertions(+) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index a447be128328..aadc1d797449 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define MAX_PWMS 1024 @@ -338,3 +340,91 @@ void pwm_disable(struct pwm_device *pwm) pwm->chip->ops->disable(pwm->chip, pwm); } EXPORT_SYMBOL_GPL(pwm_disable); + +#ifdef CONFIG_DEBUG_FS +static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) +{ + unsigned int i; + + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; + + seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + seq_printf(s, " requested"); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) + seq_printf(s, " enabled"); + + seq_printf(s, "\n"); + } +} + +static void *pwm_seq_start(struct seq_file *s, loff_t *pos) +{ + mutex_lock(&pwm_lock); + s->private = ""; + + return seq_list_start(&pwm_chips, *pos); +} + +static void *pwm_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + s->private = "\n"; + + return seq_list_next(v, &pwm_chips, pos); +} + +static void pwm_seq_stop(struct seq_file *s, void *v) +{ + mutex_unlock(&pwm_lock); +} + +static int pwm_seq_show(struct seq_file *s, void *v) +{ + struct pwm_chip *chip = list_entry(v, struct pwm_chip, list); + + seq_printf(s, "%s%s/%s, %d PWM device%s\n", (char *)s->private, + chip->dev->bus ? chip->dev->bus->name : "no-bus", + dev_name(chip->dev), chip->npwm, + (chip->npwm != 1) ? "s" : ""); + + if (chip->ops->dbg_show) + chip->ops->dbg_show(chip, s); + else + pwm_dbg_show(chip, s); + + return 0; +} + +static const struct seq_operations pwm_seq_ops = { + .start = pwm_seq_start, + .next = pwm_seq_next, + .stop = pwm_seq_stop, + .show = pwm_seq_show, +}; + +static int pwm_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &pwm_seq_ops); +} + +static const struct file_operations pwm_debugfs_ops = { + .owner = THIS_MODULE, + .open = pwm_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init pwm_debugfs_init(void) +{ + debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, + &pwm_debugfs_ops); + + return 0; +} + +subsys_initcall(pwm_debugfs_init); +#endif /* CONFIG_DEBUG_FS */ diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 57103911f4c7..047cd5351a3b 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -2,6 +2,7 @@ #define __LINUX_PWM_H struct pwm_device; +struct seq_file; /* * pwm_request - request a PWM device @@ -65,6 +66,7 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm) * @config: configure duty cycles and period length for this PWM * @enable: enable PWM output toggling * @disable: disable PWM output toggling + * @dbg_show: optional routine to show contents in debugfs * @owner: helps prevent removal of modules exporting active PWMs */ struct pwm_ops { @@ -79,6 +81,10 @@ struct pwm_ops { struct pwm_device *pwm); void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm); +#ifdef CONFIG_DEBUG_FS + void (*dbg_show)(struct pwm_chip *chip, + struct seq_file *s); +#endif struct module *owner; }; -- GitLab From 8138d2ddbcca2a100482dac390133f83c5a60f94 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 26 Mar 2012 08:42:48 +0200 Subject: [PATCH 0775/5711] pwm: Add table-based lookup for static mappings In order to get rid of the global namespace for PWM devices, this commit provides an alternative method, similar to that of the regulator or clock frameworks, for registering a static mapping for PWM devices. This works by providing a table with a provider/consumer map in the board setup code. With the new pwm_get() and pwm_put() functions available, usage of pwm_request() and pwm_free() becomes deprecated. Reviewed-by: Shawn Guo Reviewed-by: Mark Brown Signed-off-by: Thierry Reding --- Documentation/pwm.txt | 27 ++++++- drivers/pwm/core.c | 169 ++++++++++++++++++++++++++++++++++++++---- include/linux/pwm.h | 22 ++++++ 3 files changed, 199 insertions(+), 19 deletions(-) diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 48f598acdd16..554290ebab94 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -12,14 +12,33 @@ this kind of flexibility the generic PWM API exists. Identifying PWMs ---------------- -Users of the legacy PWM API use unique IDs to refer to PWM devices. One -goal of the new PWM framework is to get rid of this global namespace. +Users of the legacy PWM API use unique IDs to refer to PWM devices. + +Instead of referring to a PWM device via its unique ID, board setup code +should instead register a static mapping that can be used to match PWM +consumers to providers, as given in the following example: + + static struct pwm_lookup board_pwm_lookup[] = { + PWM_LOOKUP("tegra-pwm", 0, "pwm-backlight", NULL), + }; + + static void __init board_init(void) + { + ... + pwm_add_table(board_pwm_lookup, ARRAY_SIZE(board_pwm_lookup)); + ... + } Using PWMs ---------- -A PWM can be requested using pwm_request() and freed after usage with -pwm_free(). After being requested a PWM has to be configured using +Legacy users can request a PWM device using pwm_request() and free it +after usage with pwm_free(). + +New users should use the pwm_get() function and pass to it the consumer +device or a consumer name. pwm_put() is used to free the PWM device. + +After being requested a PWM has to be configured using: int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index aadc1d797449..a2af599e61ae 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -32,6 +32,8 @@ #define MAX_PWMS 1024 +static DEFINE_MUTEX(pwm_lookup_lock); +static LIST_HEAD(pwm_lookup_list); static DEFINE_MUTEX(pwm_lock); static LIST_HEAD(pwm_chips); static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); @@ -80,6 +82,29 @@ static void free_pwms(struct pwm_chip *chip) chip->pwms = NULL; } +static struct pwm_chip *pwmchip_find_by_name(const char *name) +{ + struct pwm_chip *chip; + + if (!name) + return NULL; + + mutex_lock(&pwm_lock); + + list_for_each_entry(chip, &pwm_chips, list) { + const char *chip_name = dev_name(chip->dev); + + if (chip_name && strcmp(chip_name, name) == 0) { + mutex_unlock(&pwm_lock); + return chip; + } + } + + mutex_unlock(&pwm_lock); + + return NULL; +} + static int pwm_device_request(struct pwm_device *pwm, const char *label) { int err; @@ -218,6 +243,8 @@ EXPORT_SYMBOL_GPL(pwmchip_remove); * pwm_request() - request a PWM device * @pwm_id: global PWM device index * @label: PWM device label + * + * This function is deprecated, use pwm_get() instead. */ struct pwm_device *pwm_request(int pwm, const char *label) { @@ -281,24 +308,12 @@ EXPORT_SYMBOL_GPL(pwm_request_from_chip); /** * pwm_free() - free a PWM device * @pwm: PWM device + * + * This function is deprecated, use pwm_put() instead. */ void pwm_free(struct pwm_device *pwm) { - mutex_lock(&pwm_lock); - - if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { - pr_warning("PWM device already freed\n"); - goto out; - } - - if (pwm->chip->ops->free) - pwm->chip->ops->free(pwm->chip, pwm); - - pwm->label = NULL; - - module_put(pwm->chip->ops->owner); -out: - mutex_unlock(&pwm_lock); + pwm_put(pwm); } EXPORT_SYMBOL_GPL(pwm_free); @@ -341,6 +356,130 @@ void pwm_disable(struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(pwm_disable); +/** + * pwm_add_table() - register PWM device consumers + * @table: array of consumers to register + * @num: number of consumers in table + */ +void __init pwm_add_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(&pwm_lookup_lock); + + while (num--) { + list_add_tail(&table->list, &pwm_lookup_list); + table++; + } + + mutex_unlock(&pwm_lookup_lock); +} + +/** + * pwm_get() - look up and request a PWM device + * @dev: device for PWM consumer + * @con_id: consumer name + * + * Look up a PWM chip and a relative index via a table supplied by board setup + * code (see pwm_add_table()). + * + * Once a PWM chip has been found the specified PWM device will be requested + * and is ready to be used. + */ +struct pwm_device *pwm_get(struct device *dev, const char *con_id) +{ + struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); + const char *dev_id = dev ? dev_name(dev): NULL; + struct pwm_chip *chip = NULL; + unsigned int best = 0; + struct pwm_lookup *p; + unsigned int index; + unsigned int match; + + /* + * We look up the provider in the static table typically provided by + * board setup code. We first try to lookup the consumer device by + * name. If the consumer device was passed in as NULL or if no match + * was found, we try to find the consumer by directly looking it up + * by name. + * + * If a match is found, the provider PWM chip is looked up by name + * and a PWM device is requested using the PWM device per-chip index. + * + * The lookup algorithm was shamelessly taken from the clock + * framework: + * + * We do slightly fuzzy matching here: + * An entry with a NULL ID is assumed to be a wildcard. + * If an entry has a device ID, it must match + * If an entry has a connection ID, it must match + * Then we take the most specific entry - with the following order + * of precedence: dev+con > dev only > con only. + */ + mutex_lock(&pwm_lookup_lock); + + list_for_each_entry(p, &pwm_lookup_list, list) { + match = 0; + + if (p->dev_id) { + if (!dev_id || strcmp(p->dev_id, dev_id)) + continue; + + match += 2; + } + + if (p->con_id) { + if (!con_id || strcmp(p->con_id, con_id)) + continue; + + match += 1; + } + + if (match > best) { + chip = pwmchip_find_by_name(p->provider); + index = p->index; + + if (match != 3) + best = match; + else + break; + } + } + + if (chip) + pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id); + + mutex_unlock(&pwm_lookup_lock); + + return pwm; +} +EXPORT_SYMBOL_GPL(pwm_get); + +/** + * pwm_put() - release a PWM device + * @pwm: PWM device + */ +void pwm_put(struct pwm_device *pwm) +{ + if (!pwm) + return; + + mutex_lock(&pwm_lock); + + if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { + pr_warning("PWM device already freed\n"); + goto out; + } + + if (pwm->chip->ops->free) + pwm->chip->ops->free(pwm->chip, pwm); + + pwm->label = NULL; + + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL_GPL(pwm_put); + #ifdef CONFIG_DEBUG_FS static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) { diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 047cd5351a3b..2947a4fea6ad 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -115,6 +115,28 @@ int pwmchip_remove(struct pwm_chip *chip); struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, unsigned int index, const char *label); + +struct pwm_device *pwm_get(struct device *dev, const char *consumer); +void pwm_put(struct pwm_device *pwm); + +struct pwm_lookup { + struct list_head list; + const char *provider; + unsigned int index; + const char *dev_id; + const char *con_id; +}; + +#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id) \ + { \ + .provider = _provider, \ + .index = _index, \ + .dev_id = _dev_id, \ + .con_id = _con_id, \ + } + +void pwm_add_table(struct pwm_lookup *table, size_t num); + #endif #endif /* __LINUX_PWM_H */ -- GitLab From bd3d5500f0c41a30149cb184362716096a17bc75 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 13 Apr 2012 16:18:34 +0200 Subject: [PATCH 0776/5711] dt: Add empty of_property_match_string() function This commit adds an empty of_property_match_string() function for !CONFIG_OF builds. Acked-by: Rob Herring Signed-off-by: Thierry Reding --- include/linux/of.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 2ec1083af7ff..597e571110a2 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -377,6 +377,13 @@ static inline int of_property_read_u64(const struct device_node *np, return -ENOSYS; } +static inline int of_property_match_string(struct device_node *np, + const char *propname, + const char *string) +{ + return -ENOSYS; +} + static inline struct device_node *of_parse_phandle(struct device_node *np, const char *phandle_name, int index) -- GitLab From e05e5070f0ec2557d2d2ff3655ba03f29e297151 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 13 Apr 2012 16:19:21 +0200 Subject: [PATCH 0777/5711] dt: Add empty of_parse_phandle_with_args() function This commit adds an empty of_parse_phandle_with_args() function for !CONFIG_OF builds. Acked-by: Rob Herring Signed-off-by: Thierry Reding --- include/linux/of.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 597e571110a2..d5dd5c06efd3 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -391,6 +391,15 @@ static inline struct device_node *of_parse_phandle(struct device_node *np, return NULL; } +static inline int of_parse_phandle_with_args(struct device_node *np, + const char *list_name, + const char *cells_name, + int index, + struct of_phandle_args *out_args) +{ + return -ENOSYS; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; -- GitLab From 7299ab70e68e20e70cb45fe4ab4b6029fe964acd Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 14 Dec 2011 11:10:32 +0100 Subject: [PATCH 0778/5711] pwm: Add device tree support This patch adds helpers to support device tree bindings for the generic PWM API. Device tree binding documentation for PWM controllers is also provided. Acked-by: Arnd Bergmann Reviewed-by: Shawn Guo Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/pwm.txt | 57 +++++++ drivers/pwm/core.c | 148 +++++++++++++++++- include/linux/pwm.h | 6 + 3 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/pwm/pwm.txt diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt new file mode 100644 index 000000000000..73ec962bfe8c --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm.txt @@ -0,0 +1,57 @@ +Specifying PWM information for devices +====================================== + +1) PWM user nodes +----------------- + +PWM users should specify a list of PWM devices that they want to use +with a property containing a 'pwm-list': + + pwm-list ::= [pwm-list] + single-pwm ::= + pwm-phandle : phandle to PWM controller node + pwm-specifier : array of #pwm-cells specifying the given PWM + (controller specific) + +PWM properties should be named "pwms". The exact meaning of each pwms +property must be documented in the device tree binding for each device. +An optional property "pwm-names" may contain a list of strings to label +each of the PWM devices listed in the "pwms" property. If no "pwm-names" +property is given, the name of the user node will be used as fallback. + +Drivers for devices that use more than a single PWM device can use the +"pwm-names" property to map the name of the PWM device requested by the +pwm_get() call to an index into the list given by the "pwms" property. + +The following example could be used to describe a PWM-based backlight +device: + + pwm: pwm { + #pwm-cells = <2>; + }; + + [...] + + bl: backlight { + pwms = <&pwm 0 5000000>; + pwm-names = "backlight"; + }; + +pwm-specifier typically encodes the chip-relative PWM number and the PWM +period in nanoseconds. Note that in the example above, specifying the +"pwm-names" is redundant because the name "backlight" would be used as +fallback anyway. + +2) PWM controller nodes +----------------------- + +PWM controller nodes must specify the number of cells used for the +specifier using the '#pwm-cells' property. + +An example PWM controller might look like this: + + pwm: pwm@7000a000 { + compatible = "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + }; diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index a2af599e61ae..dbab53005da8 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -129,6 +129,45 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) return 0; } +static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, + const struct of_phandle_args *args) +{ + struct pwm_device *pwm; + + if (pc->of_pwm_n_cells < 2) + return ERR_PTR(-EINVAL); + + if (args->args[0] >= pc->npwm) + return ERR_PTR(-EINVAL); + + pwm = pwm_request_from_chip(pc, args->args[0], NULL); + if (IS_ERR(pwm)) + return pwm; + + pwm_set_period(pwm, args->args[1]); + + return pwm; +} + +void of_pwmchip_add(struct pwm_chip *chip) +{ + if (!chip->dev || !chip->dev->of_node) + return; + + if (!chip->of_xlate) { + chip->of_xlate = of_pwm_simple_xlate; + chip->of_pwm_n_cells = 2; + } + + of_node_get(chip->dev->of_node); +} + +void of_pwmchip_remove(struct pwm_chip *chip) +{ + if (chip->dev && chip->dev->of_node) + of_node_put(chip->dev->of_node); +} + /** * pwm_set_chip_data() - set private chip data for a PWM * @pwm: PWM device @@ -201,6 +240,9 @@ int pwmchip_add(struct pwm_chip *chip) ret = 0; + if (IS_ENABLED(CONFIG_OF)) + of_pwmchip_add(chip); + out: mutex_unlock(&pwm_lock); return ret; @@ -231,6 +273,10 @@ int pwmchip_remove(struct pwm_chip *chip) } list_del_init(&chip->list); + + if (IS_ENABLED(CONFIG_OF)) + of_pwmchip_remove(chip); + free_pwms(chip); out: @@ -356,6 +402,99 @@ void pwm_disable(struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(pwm_disable); +static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) +{ + struct pwm_chip *chip; + + mutex_lock(&pwm_lock); + + list_for_each_entry(chip, &pwm_chips, list) + if (chip->dev && chip->dev->of_node == np) { + mutex_unlock(&pwm_lock); + return chip; + } + + mutex_unlock(&pwm_lock); + + return ERR_PTR(-EPROBE_DEFER); +} + +/** + * of_pwm_request() - request a PWM via the PWM framework + * @np: device node to get the PWM from + * @con_id: consumer name + * + * Returns the PWM device parsed from the phandle and index specified in the + * "pwms" property of a device tree node or a negative error-code on failure. + * Values parsed from the device tree are stored in the returned PWM device + * object. + * + * If con_id is NULL, the first PWM device listed in the "pwms" property will + * be requested. Otherwise the "pwm-names" property is used to do a reverse + * lookup of the PWM index. This also means that the "pwm-names" property + * becomes mandatory for devices that look up the PWM device via the con_id + * parameter. + */ +static struct pwm_device *of_pwm_request(struct device_node *np, + const char *con_id) +{ + struct pwm_device *pwm = NULL; + struct of_phandle_args args; + struct pwm_chip *pc; + int index = 0; + int err; + + if (con_id) { + index = of_property_match_string(np, "pwm-names", con_id); + if (index < 0) + return ERR_PTR(index); + } + + err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index, + &args); + if (err) { + pr_debug("%s(): can't parse \"pwms\" property\n", __func__); + return ERR_PTR(err); + } + + pc = of_node_to_pwmchip(args.np); + if (IS_ERR(pc)) { + pr_debug("%s(): PWM chip not found\n", __func__); + pwm = ERR_CAST(pc); + goto put; + } + + if (args.args_count != pc->of_pwm_n_cells) { + pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name, + args.np->full_name); + pwm = ERR_PTR(-EINVAL); + goto put; + } + + pwm = pc->of_xlate(pc, &args); + if (IS_ERR(pwm)) + goto put; + + /* + * If a consumer name was not given, try to look it up from the + * "pwm-names" property if it exists. Otherwise use the name of + * the user device node. + */ + if (!con_id) { + err = of_property_read_string_index(np, "pwm-names", index, + &con_id); + if (err < 0) + con_id = np->name; + } + + pwm->label = con_id; + +put: + of_node_put(args.np); + + return pwm; +} + /** * pwm_add_table() - register PWM device consumers * @table: array of consumers to register @@ -378,8 +517,9 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num) * @dev: device for PWM consumer * @con_id: consumer name * - * Look up a PWM chip and a relative index via a table supplied by board setup - * code (see pwm_add_table()). + * Lookup is first attempted using DT. If the device was not instantiated from + * a device tree, a PWM chip and a relative index is looked up via a table + * supplied by board setup code (see pwm_add_table()). * * Once a PWM chip has been found the specified PWM device will be requested * and is ready to be used. @@ -394,6 +534,10 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) unsigned int index; unsigned int match; + /* look up via DT first */ + if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) + return of_pwm_request(dev->of_node, con_id); + /* * We look up the provider in the static table typically provided by * board setup code. We first try to lookup the consumer device by diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 2947a4fea6ad..21d076c5089e 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -1,6 +1,8 @@ #ifndef __LINUX_PWM_H #define __LINUX_PWM_H +#include + struct pwm_device; struct seq_file; @@ -105,6 +107,10 @@ struct pwm_chip { unsigned int npwm; struct pwm_device *pwms; + + struct pwm_device * (*of_xlate)(struct pwm_chip *pc, + const struct of_phandle_args *args); + unsigned int of_pwm_n_cells; }; int pwm_set_chip_data(struct pwm_device *pwm, void *data); -- GitLab From 1a12af1a751311e129ff8e8ca18f83613b78a83c Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 12 Jun 2012 12:42:17 +0200 Subject: [PATCH 0779/5711] usb: gadget: mass_storage: remove unused options This commit removes thread_name and lun_name_format fields from the fsg_config structure. Those fields are not used by any in-tree code and their usefulness is rather theoretical. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_mass_storage.c | 50 ++++++----------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 72116fa49ffb..9b29e8eab18f 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -75,25 +75,6 @@ * ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12) * commands for this LUN shall be ignored. * - * lun_name_format A printf-like format for names of the LUN - * devices. This determines how the - * directory in sysfs will be named. - * Unless you are using several MSFs in - * a single gadget (as opposed to single - * MSF in many configurations) you may - * leave it as NULL (in which case - * "lun%d" will be used). In the format - * you can use "%d" to index LUNs for - * MSF's with more than one LUN. (Beware - * that there is only one integer given - * as an argument for the format and - * specifying invalid format may cause - * unspecified behaviour.) - * thread_name Name of the kernel thread process used by the - * MSF. You can safely set it to NULL - * (in which case default "file-storage" - * will be used). - * * vendor_name * product_name * release Information used as a reply to INQUIRY @@ -155,15 +136,14 @@ * a buffer from being used by more than one endpoint. * * - * The pathnames of the backing files and the ro settings are - * available in the attribute files "file" and "ro" in the lun (or - * to be more precise in a directory which name comes from - * "lun_name_format" option!) subdirectory of the gadget's sysfs - * directory. If the "removable" option is set, writing to these - * files will simulate ejecting/loading the medium (writing an empty - * line means eject) and adjusting a write-enable tab. Changes to the - * ro setting are not allowed when the medium is loaded or if CD-ROM - * emulation is being used. + * The pathnames of the backing files, the ro settings and nofua + * settings are available in the attribute files "file", "ro" and + * "nofua" in the lun subdirectory of the gadget's sysfs directory. + * If the "removable" option is set, writing to these files will + * simulate ejecting/loading the medium (writing an empty line means + * eject) and adjusting a write-enable tab. Changes to the ro setting + * are not allowed when the medium is loaded or if CD-ROM emulation is + * being used. * * When a LUN receive an "eject" SCSI request (Start/Stop Unit), * if the LUN is removable, the backing file is released to simulate @@ -417,9 +397,6 @@ struct fsg_config { char nofua; } luns[FSG_MAX_LUNS]; - const char *lun_name_format; - const char *thread_name; - /* Callback functions. */ const struct fsg_operations *ops; /* Gadget's private data. */ @@ -2792,11 +2769,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, curlun->dev.parent = &gadget->dev; /* curlun->dev.driver = &fsg_driver.driver; XXX */ dev_set_drvdata(&curlun->dev, &common->filesem); - dev_set_name(&curlun->dev, - cfg->lun_name_format - ? cfg->lun_name_format - : "lun%d", - i); + dev_set_name(&curlun->dev, "lun%d", i); rc = device_register(&curlun->dev); if (rc) { @@ -2878,8 +2851,7 @@ buffhds_first_it: /* Tell the thread to start working */ common->thread_task = - kthread_create(fsg_main_thread, common, - cfg->thread_name ?: "file-storage"); + kthread_create(fsg_main_thread, common, "file-storage"); if (IS_ERR(common->thread_task)) { rc = PTR_ERR(common->thread_task); goto error_release; @@ -3175,8 +3147,6 @@ fsg_config_from_params(struct fsg_config *cfg, } /* Let MSF use defaults */ - cfg->lun_name_format = 0; - cfg->thread_name = 0; cfg->vendor_name = 0; cfg->product_name = 0; cfg->release = 0xffff; -- GitLab From a8287a4ed543494c121050dc453972902637e6de Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 12 Jun 2012 12:42:18 +0200 Subject: [PATCH 0780/5711] usb: gadget: mass_storage: add documentation This commit adds Documentation/usb/mass-storage.txt file. It contains description of how to use the mass storage gadget from user space. It elaborates on madule parameters and sysfs interface more then it was written in the comments in the source code. Signed-off-by: Michal Nazarewicz Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- Documentation/usb/mass-storage.txt | 226 ++++++++++++++++++++++++++++ drivers/usb/gadget/f_mass_storage.c | 69 +-------- 2 files changed, 233 insertions(+), 62 deletions(-) create mode 100644 Documentation/usb/mass-storage.txt diff --git a/Documentation/usb/mass-storage.txt b/Documentation/usb/mass-storage.txt new file mode 100644 index 000000000000..e9b9334627bf --- /dev/null +++ b/Documentation/usb/mass-storage.txt @@ -0,0 +1,226 @@ +* Overview + + Mass Storage Gadget (or MSG) acts as a USB Mass Storage device, + appearing to the host as a disk or a CD-ROM drive. It supports + multiple logical units (LUNs). Backing storage for each LUN is + provided by a regular file or a block device, access can be limited + to read-only, and gadget can indicate that it is removable and/or + CD-ROM (the latter implies read-only access). + + Its requirements are modest; only a bulk-in and a bulk-out endpoint + are needed. The memory requirement amounts to two 16K buffers. + Support is included for full-speed, high-speed and SuperSpeed + operation. + + Note that the driver is slightly non-portable in that it assumes + a single memory/DMA buffer will be useable for bulk-in and bulk-out + endpoints. With most device controllers this is not an issue, but + there may be some with hardware restrictions that prevent a buffer + from being used by more than one endpoint. + + This document describes how to use the gadget from user space, its + relation to mass storage function (or MSF) and different gadgets + using it, and how it differs from File Storage Gadget (or FSG). It + will talk only briefly about how to use MSF within composite + gadgets. + +* Module parameters + + The mass storage gadget accepts the following mass storage specific + module parameters: + + - file=filename[,filename...] + + This parameter lists paths to files or block devices used for + backing storage for each logical unit. There may be at most + FSG_MAX_LUNS (8) LUNs set. If more files are specified, they will + be silently ignored. See also “luns” parameter. + + *BEWARE* that if a file is used as a backing storage, it may not + be modified by any other process. This is because the host + assumes the data does not change without its knowledge. It may be + read, but (if the logical unit is writable) due to buffering on + the host side, the contents are not well defined. + + The size of the logical unit will be rounded down to a full + logical block. The logical block size is 2048 bytes for LUNs + simulating CD-ROM, block size of the device if the backing file is + a block device, or 512 bytes otherwise. + + - removable=b[,b...] + + This parameter specifies whether each logical unit should be + removable. “b” here is either “y”, “Y” or “1” for true or “n”, + “N” or “0” for false. + + If this option is set for a logical unit, gadget will accept an + “eject” SCSI request (Start/Stop Unit). When it is sent, the + backing file will be closed to simulate ejection and the logical + unit will not be mountable by the host until a new backing file is + specified by userspace on the device (see “sysfs entries” + section). + + If a logical unit is not removable (the default), a backing file + must be specified for it with the “file” parameter as the module + is loaded. The same applies if the module is built in, no + exceptions. + + The default value of the flag is false, *HOWEVER* it used to be + true. This has been changed to better match File Storage Gadget + and because it seems like a saner default after all. Thus to + maintain compatibility with older kernels, it's best to specify + the default values. Also, if one relied on old default, explicit + “n” needs to be specified now. + + Note that “removable” means the logical unit's media can be + ejected or removed (as is true for a CD-ROM drive or a card + reader). It does *not* mean that the entire gadget can be + unplugged from the host; the proper term for that is + “hot-unpluggable”. + + - cdrom=b[,b...] + + This parameter specifies whether each logical unit should simulate + CD-ROM. The default is false. + + - ro=b[,b...] + + This parameter specifies whether each logical unit should be + reported as read only. This will prevent host from modifying the + backing files. + + Note that if this flag for given logical unit is false but the + backing file could not be opened in read/write mode, the gadget + will fall back to read only mode anyway. + + The default value for non-CD-ROM logical units is false; for + logical units simulating CD-ROM it is forced to true. + + - nofua=b[,b...] + + This parameter specifies whether FUA flag should be ignored in SCSI + Write10 and Write12 commands sent to given logical units. + + MS Windows mounts removable storage in “Removal optimised mode” by + default. All the writes to the media are synchronous, which is + achieved by setting the FUA (Force Unit Access) bit in SCSI + Write(10,12) commands. This forces each write to wait until the + data has actually been written out and prevents I/O requests + aggregation in block layer dramatically decreasing performance. + + Note that this may mean that if the device is powered from USB and + the user unplugs the device without unmounting it first (which at + least some Windows users do), the data may be lost. + + The default value is false. + + - luns=N + + This parameter specifies number of logical units the gadget will + have. It is limited by FSG_MAX_LUNS (8) and higher value will be + capped. + + If this parameter is provided, and the number of files specified + in “file” argument is greater then the value of “luns”, all excess + files will be ignored. + + If this parameter is not present, the number of logical units will + be deduced from the number of files specified in the “file” + parameter. If the file parameter is missing as well, one is + assumed. + + - stall=b + + Specifies whether the gadget is allowed to halt bulk endpoints. + The default is determined according to the type of USB device + controller, but usually true. + + In addition to the above, the gadget also accepts the following + parameters defined by the composite framework (they are common to + all composite gadgets so just a quick listing): + + - idVendor -- USB Vendor ID (16 bit integer) + - idProduct -- USB Product ID (16 bit integer) + - bcdDevice -- USB Device version (BCD) (16 bit integer) + - iManufacturer -- USB Manufacturer string (string) + - iProduct -- USB Product string (string) + - iSerialNumber -- SerialNumber string (sting) + +* sysfs entries + + For each logical unit, the gadget creates a directory in the sysfs + hierarchy. Inside of it the following three files are created: + + - file + + When read it returns the path to the backing file for the given + logical unit. If there is no backing file (possible only if the + logical unit is removable), the content is empty. + + When written into, it changes the backing file for given logical + unit. This change can be performed even if given logical unit is + not specified as removable (but that may look strange to the + host). It may fail, however, if host disallowed medium removal + with the Prevent-Allow Medium Removal SCSI command. + + - ro + + Reflects the state of ro flag for the given logical unit. It can + be read any time, and written to when there is no backing file + open for given logical unit. + + - nofua + + Reflects the state of nofua flag for given logical unit. It can + be read and written. + + Other then those, as usual, the values of module parameters can be + read from /sys/module/g_mass_storage/parameters/* files. + +* Other gadgets using mass storage function + + The Mass Storage Gadget uses the Mass Storage Function to handle + mass storage protocol. As a composite function, MSF may be used by + other gadgets as well (eg. g_multi and acm_ms). + + All of the information in previous sections are valid for other + gadgets using MSF, except that support for mass storage related + module parameters may be missing, or the parameters may have + a prefix. To figure out whether any of this is true one needs to + consult the gadget's documentation or its source code. + + For examples of how to include mass storage function in gadgets, one + may take a look at mass_storage.c, acm_ms.c and multi.c (sorted by + complexity). + +* Relation to file storage gadget + + The Mass Storage Function and thus the Mass Storage Gadget has been + based on the File Storage Gadget. The difference between the two is + that MSG is a composite gadget (ie. uses the composite framework) + while file storage gadget is a traditional gadget. From userspace + point of view this distinction does not really matter, but from + kernel hacker's point of view, this means that (i) MSG does not + duplicate code needed for handling basic USB protocol commands and + (ii) MSF can be used in any other composite gadget. + + Because of that, File Storage Gadget has been deprecated and + scheduled to be removed in Linux 3.8. All users need to transition + to the Mass Storage Gadget by that time. The two gadgets behave + mostly the same from the outside except: + + 1. In FSG the “removable” and “cdrom” module parameters set the flag + for all logical units whereas in MSG they accept a list of y/n + values for each logical unit. If one uses only a single logical + unit this does not matter, but if there are more, the y/n value + needs to be repeated for each logical unit. + + 2. FSG's “serial”, “vendor”, “product” and “release” module + parameters are handled in MSG by the composite layer's parameters + named respectively: “iSerialnumber”, “idVendor”, “idProduct” and + “bcdDevice”. + + 3. MSG does not support FSG's test mode, thus “transport”, + “protocol” and “buflen” FSG's module parameters are not + supported. MSG always uses SCSI protocol with bulk only + transport mode and 16 KiB buffers. diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 9b29e8eab18f..7ad4f819752d 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -44,12 +44,12 @@ * function for a USB device, it also illustrates a technique of * double-buffering for increased throughput. * - * Function supports multiple logical units (LUNs). Backing storage - * for each LUN is provided by a regular file or a block device. - * Access for each LUN can be limited to read-only. Moreover, the - * function can indicate that LUN is removable and/or CD-ROM. (The - * later implies read-only access.) - * + * For more information about MSF and in particular its module + * parameters and sysfs interface read the + * file. + */ + +/* * MSF is configured by specifying a fsg_config structure. It has the * following fields: * @@ -95,61 +95,6 @@ * data track and no audio tracks; hence there need be only one * backing file per LUN. * - * - * MSF includes support for module parameters. If gadget using it - * decides to use it, the following module parameters will be - * available: - * - * file=filename[,filename...] - * Names of the files or block devices used for - * backing storage. - * ro=b[,b...] Default false, boolean for read-only access. - * removable=b[,b...] - * Default false, boolean for removable media. - * cdrom=b[,b...] Default false, boolean for whether to emulate - * a CD-ROM drive. - * nofua=b[,b...] Default false, booleans for ignore FUA flag - * in SCSI WRITE(10,12) commands - * luns=N Default N = number of filenames, number of - * LUNs to support. - * stall Default determined according to the type of - * USB device controller (usually true), - * boolean to permit the driver to halt - * bulk endpoints. - * - * The module parameters may be prefixed with some string. You need - * to consult gadget's documentation or source to verify whether it is - * using those module parameters and if it does what are the prefixes - * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is - * the prefix). - * - * - * Requirements are modest; only a bulk-in and a bulk-out endpoint are - * needed. The memory requirement amounts to two 16K buffers, size - * configurable by a parameter. Support is included for both - * full-speed and high-speed operation. - * - * Note that the driver is slightly non-portable in that it assumes a - * single memory/DMA buffer will be useable for bulk-in, bulk-out, and - * interrupt-in endpoints. With most device controllers this isn't an - * issue, but there may be some with hardware restrictions that prevent - * a buffer from being used by more than one endpoint. - * - * - * The pathnames of the backing files, the ro settings and nofua - * settings are available in the attribute files "file", "ro" and - * "nofua" in the lun subdirectory of the gadget's sysfs directory. - * If the "removable" option is set, writing to these files will - * simulate ejecting/loading the medium (writing an empty line means - * eject) and adjusting a write-enable tab. Changes to the ro setting - * are not allowed when the medium is loaded or if CD-ROM emulation is - * being used. - * - * When a LUN receive an "eject" SCSI request (Start/Stop Unit), - * if the LUN is removable, the backing file is released to simulate - * ejection. - * - * * This function is heavily based on "File-backed Storage Gadget" by * Alan Stern which in turn is heavily based on "Gadget Zero" by David * Brownell. The driver's SCSI command interface was based on the @@ -191,7 +136,7 @@ * In normal operation the main thread is started during the gadget's * fsg_bind() callback and stopped during fsg_unbind(). But it can * also exit when it receives a signal, and there's no point leaving - * the gadget running when the thread is dead. At of this moment, MSF + * the gadget running when the thread is dead. As of this moment, MSF * provides no way to deregister the gadget when thread dies -- maybe * a callback functions is needed. * -- GitLab From 99c515005857ff7d6cd5c2ba272ccab5dc0ea648 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 13 Jun 2012 12:54:45 +0200 Subject: [PATCH 0781/5711] usb: gadget: hidg: register OUT INT endpoint for SET_REPORT The hidg function driver currently handles its SET_REPORT calls via EP0. This is the implicit behaviour when no OUT interrupt endpoint is configured and generally works fine. The problem is that due to EP0's role in the gadget framework, we cannot hold back packets and control traffic flow to sync it to the char device, and hence there's a high risk of loosing packets with this implementation. This patch adds an OUT interrupt endpoint to the interface and queues a fix number of request to catch SET_REPORT events. According to the specs, host drivers should always use the dedicated OUT endpoint when present. The char device's read implementation was rewritten to retrieve data from the list of completed output requests. Signed-off-by: Daniel Mack Cc: Felipe Balbi Cc: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_hid.c | 208 +++++++++++++++++++++++++++++-------- 1 file changed, 165 insertions(+), 43 deletions(-) diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 3b3932c55361..16a8b1c15c62 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -26,6 +26,12 @@ static struct class *hidg_class; /*-------------------------------------------------------------------------*/ /* HID gadget struct */ +struct f_hidg_req_list { + struct usb_request *req; + unsigned int pos; + struct list_head list; +}; + struct f_hidg { /* configuration */ unsigned char bInterfaceSubClass; @@ -35,10 +41,10 @@ struct f_hidg { unsigned short report_length; /* recv report */ - char *set_report_buff; - unsigned short set_report_length; + struct list_head completed_out_req; spinlock_t spinlock; wait_queue_head_t read_queue; + unsigned int qlen; /* send report */ struct mutex lock; @@ -49,7 +55,9 @@ struct f_hidg { int minor; struct cdev cdev; struct usb_function func; + struct usb_ep *in_ep; + struct usb_ep *out_ep; }; static inline struct f_hidg *func_to_hidg(struct usb_function *f) @@ -65,7 +73,7 @@ static struct usb_interface_descriptor hidg_interface_desc = { .bDescriptorType = USB_DT_INTERFACE, /* .bInterfaceNumber = DYNAMIC */ .bAlternateSetting = 0, - .bNumEndpoints = 1, + .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_HID, /* .bInterfaceSubClass = DYNAMIC */ /* .bInterfaceProtocol = DYNAMIC */ @@ -96,10 +104,23 @@ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { */ }; +static struct usb_endpoint_descriptor hidg_hs_out_ep_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_INT, + /*.wMaxPacketSize = DYNAMIC */ + .bInterval = 4, /* FIXME: Add this field in the + * HID gadget configuration? + * (struct hidg_func_descriptor) + */ +}; + static struct usb_descriptor_header *hidg_hs_descriptors[] = { (struct usb_descriptor_header *)&hidg_interface_desc, (struct usb_descriptor_header *)&hidg_desc, (struct usb_descriptor_header *)&hidg_hs_in_ep_desc, + (struct usb_descriptor_header *)&hidg_hs_out_ep_desc, NULL, }; @@ -117,10 +138,23 @@ static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = { */ }; +static struct usb_endpoint_descriptor hidg_fs_out_ep_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_INT, + /*.wMaxPacketSize = DYNAMIC */ + .bInterval = 10, /* FIXME: Add this field in the + * HID gadget configuration? + * (struct hidg_func_descriptor) + */ +}; + static struct usb_descriptor_header *hidg_fs_descriptors[] = { (struct usb_descriptor_header *)&hidg_interface_desc, (struct usb_descriptor_header *)&hidg_desc, (struct usb_descriptor_header *)&hidg_fs_in_ep_desc, + (struct usb_descriptor_header *)&hidg_fs_out_ep_desc, NULL, }; @@ -130,9 +164,11 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = { static ssize_t f_hidg_read(struct file *file, char __user *buffer, size_t count, loff_t *ptr) { - struct f_hidg *hidg = file->private_data; - char *tmp_buff = NULL; - unsigned long flags; + struct f_hidg *hidg = file->private_data; + struct f_hidg_req_list *list; + struct usb_request *req; + unsigned long flags; + int ret; if (!count) return 0; @@ -142,8 +178,9 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, spin_lock_irqsave(&hidg->spinlock, flags); -#define READ_COND (hidg->set_report_buff != NULL) +#define READ_COND (!list_empty(&hidg->completed_out_req)) + /* wait for at least one buffer to complete */ while (!READ_COND) { spin_unlock_irqrestore(&hidg->spinlock, flags); if (file->f_flags & O_NONBLOCK) @@ -155,19 +192,34 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, spin_lock_irqsave(&hidg->spinlock, flags); } - - count = min_t(unsigned, count, hidg->set_report_length); - tmp_buff = hidg->set_report_buff; - hidg->set_report_buff = NULL; - + /* pick the first one */ + list = list_first_entry(&hidg->completed_out_req, + struct f_hidg_req_list, list); + req = list->req; + count = min_t(unsigned int, count, req->actual - list->pos); spin_unlock_irqrestore(&hidg->spinlock, flags); - if (tmp_buff != NULL) { - /* copy to user outside spinlock */ - count -= copy_to_user(buffer, tmp_buff, count); - kfree(tmp_buff); - } else - count = -ENOMEM; + /* copy to user outside spinlock */ + count -= copy_to_user(buffer, req->buf + list->pos, count); + list->pos += count; + + /* + * if this request is completely handled and transfered to + * userspace, remove its entry from the list and requeue it + * again. Otherwise, we will revisit it again upon the next + * call, taking into account its current read position. + */ + if (list->pos == req->actual) { + spin_lock_irqsave(&hidg->spinlock, flags); + list_del(&list->list); + kfree(list); + spin_unlock_irqrestore(&hidg->spinlock, flags); + + req->length = hidg->report_length; + ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); + if (ret < 0) + return ret; + } return count; } @@ -282,28 +334,37 @@ static int f_hidg_open(struct inode *inode, struct file *fd) /*-------------------------------------------------------------------------*/ /* usb_function */ -static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) +static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length) { - struct f_hidg *hidg = (struct f_hidg *)req->context; - - if (req->status != 0 || req->buf == NULL || req->actual == 0) { - ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__); - return; + struct usb_request *req; + + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (req) { + req->length = length; + req->buf = kmalloc(length, GFP_ATOMIC); + if (!req->buf) { + usb_ep_free_request(ep, req); + req = NULL; + } } + return req; +} - spin_lock(&hidg->spinlock); - - hidg->set_report_buff = krealloc(hidg->set_report_buff, - req->actual, GFP_ATOMIC); +static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_hidg *hidg = (struct f_hidg *) req->context; + struct f_hidg_req_list *req_list; + unsigned long flags; - if (hidg->set_report_buff == NULL) { - spin_unlock(&hidg->spinlock); + req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); + if (!req_list) return; - } - hidg->set_report_length = req->actual; - memcpy(hidg->set_report_buff, req->buf, req->actual); - spin_unlock(&hidg->spinlock); + req_list->req = req; + + spin_lock_irqsave(&hidg->spinlock, flags); + list_add_tail(&req_list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->spinlock, flags); wake_up(&hidg->read_queue); } @@ -344,9 +405,7 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_SET_REPORT): VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength); - req->context = hidg; - req->complete = hidg_set_report_complete; - goto respond; + goto stall; break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 @@ -403,16 +462,25 @@ respond: static void hidg_disable(struct usb_function *f) { struct f_hidg *hidg = func_to_hidg(f); + struct f_hidg_req_list *list, *next; usb_ep_disable(hidg->in_ep); hidg->in_ep->driver_data = NULL; + + usb_ep_disable(hidg->out_ep); + hidg->out_ep->driver_data = NULL; + + list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { + list_del(&list->list); + kfree(list); + } } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = f->config->cdev; struct f_hidg *hidg = func_to_hidg(f); - int status = 0; + int i, status = 0; VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); @@ -429,11 +497,55 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } status = usb_ep_enable(hidg->in_ep); if (status < 0) { - ERROR(cdev, "Enable endpoint FAILED!\n"); + ERROR(cdev, "Enable IN endpoint FAILED!\n"); goto fail; } hidg->in_ep->driver_data = hidg; } + + + if (hidg->out_ep != NULL) { + /* restart endpoint */ + if (hidg->out_ep->driver_data != NULL) + usb_ep_disable(hidg->out_ep); + + status = config_ep_by_speed(f->config->cdev->gadget, f, + hidg->out_ep); + if (status) { + ERROR(cdev, "config_ep_by_speed FAILED!\n"); + goto fail; + } + status = usb_ep_enable(hidg->out_ep); + if (status < 0) { + ERROR(cdev, "Enable IN endpoint FAILED!\n"); + goto fail; + } + hidg->out_ep->driver_data = hidg; + + /* + * allocate a bunch of read buffers and queue them all at once. + */ + for (i = 0; i < hidg->qlen && status == 0; i++) { + struct usb_request *req = + hidg_alloc_ep_req(hidg->out_ep, + hidg->report_length); + if (req) { + req->complete = hidg_set_report_complete; + req->context = hidg; + status = usb_ep_queue(hidg->out_ep, req, + GFP_ATOMIC); + if (status) + ERROR(cdev, "%s queue req --> %d\n", + hidg->out_ep->name, status); + } else { + usb_ep_disable(hidg->out_ep); + hidg->out_ep->driver_data = NULL; + status = -ENOMEM; + goto fail; + } + } + } + fail: return status; } @@ -470,13 +582,18 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ep->driver_data = c->cdev; /* claim */ hidg->in_ep = ep; + ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc); + if (!ep) + goto fail; + ep->driver_data = c->cdev; /* claim */ + hidg->out_ep = ep; + /* preallocate request and buffer */ status = -ENOMEM; hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL); if (!hidg->req) goto fail; - hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL); if (!hidg->req->buf) goto fail; @@ -486,12 +603,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); + hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); + hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; hidg_desc.desc[0].wDescriptorLength = cpu_to_le16(hidg->report_desc_length); - hidg->set_report_buff = NULL; - /* copy descriptors */ f->descriptors = usb_copy_descriptors(hidg_fs_descriptors); if (!f->descriptors) @@ -500,6 +617,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) if (gadget_is_dualspeed(c->cdev->gadget)) { hidg_hs_in_ep_desc.bEndpointAddress = hidg_fs_in_ep_desc.bEndpointAddress; + hidg_hs_out_ep_desc.bEndpointAddress = + hidg_fs_out_ep_desc.bEndpointAddress; f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors); if (!f->hs_descriptors) goto fail; @@ -509,6 +628,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) spin_lock_init(&hidg->spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); + INIT_LIST_HEAD(&hidg->completed_out_req); /* create char device */ cdev_init(&hidg->cdev, &f_hidg_fops); @@ -553,7 +673,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) usb_free_descriptors(f->descriptors); kfree(hidg->report_desc); - kfree(hidg->set_report_buff); kfree(hidg); } @@ -624,6 +743,9 @@ int __init hidg_bind_config(struct usb_configuration *c, hidg->func.disable = hidg_disable; hidg->func.setup = hidg_setup; + /* this could me made configurable at some point */ + hidg->qlen = 4; + status = usb_add_function(c, &hidg->func); if (status) kfree(hidg); -- GitLab From 22258f4906aa87e0c0debcad22cb292453e2ebfb Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:24 +0200 Subject: [PATCH 0782/5711] usb: hsotg: samsung: Replace endpoint specific locks with a global lock The endpoint specific locks are replaced with a global lock. This is crucial for running s3c-hsotg driver on a SMP SoC. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 54 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index d37585105bb4..b10791282f15 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -112,7 +112,6 @@ struct s3c_hsotg_ep { struct s3c_hsotg_req *req; struct dentry *debugfs; - spinlock_t lock; unsigned long total_data; unsigned int size_loaded; @@ -156,6 +155,8 @@ struct s3c_hsotg { struct usb_gadget_driver *driver; struct s3c_hsotg_plat *plat; + spinlock_t lock; + void __iomem *regs; int irq; struct clk *clk; @@ -901,6 +902,8 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, ep->name, req, req->length, req->buf, req->no_interrupt, req->zero, req->short_not_ok); + spin_lock_irqsave(&hs->lock, irqflags); + /* initialise status of the request */ INIT_LIST_HEAD(&hs_req->queue); req->actual = 0; @@ -913,15 +916,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, return ret; } - spin_lock_irqsave(&hs_ep->lock, irqflags); - first = list_empty(&hs_ep->queue); list_add_tail(&hs_req->queue, &hs_ep->queue); if (first) s3c_hsotg_start_req(hs, hs_ep, hs_req, false); - spin_unlock_irqrestore(&hs_ep->lock, irqflags); + spin_unlock_irqrestore(&hs->lock, irqflags); return 0; } @@ -1381,9 +1382,9 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, */ if (hs_req->req.complete) { - spin_unlock(&hs_ep->lock); + spin_unlock(&hsotg->lock); hs_req->req.complete(&hs_ep->ep, &hs_req->req); - spin_lock(&hs_ep->lock); + spin_lock(&hsotg->lock); } /* @@ -1418,9 +1419,9 @@ static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, { unsigned long flags; - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); } /** @@ -1442,6 +1443,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) int max_req; int read_ptr; + spin_lock(&hsotg->lock); + if (!hs_req) { u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; @@ -1454,11 +1457,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) for (ptr = 0; ptr < size; ptr += 4) (void)readl(fifo); + spin_unlock(&hsotg->lock); return; } - spin_lock(&hs_ep->lock); - to_read = size; read_ptr = hs_req->req.actual; max_req = hs_req->req.length - read_ptr; @@ -1486,7 +1488,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); - spin_unlock(&hs_ep->lock); + spin_unlock(&hsotg->lock); } /** @@ -2123,7 +2125,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, struct s3c_hsotg_req *req, *treq; unsigned long flags; - spin_lock_irqsave(&ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { /* @@ -2138,7 +2140,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, result); } - spin_unlock_irqrestore(&ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); } #define call_gadget(_hs, _entry) \ @@ -2602,7 +2604,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", __func__, epctrl, epctrl_reg); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK); epctrl |= DxEPCTL_MPS(mps); @@ -2681,7 +2683,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); out: - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return ret; } @@ -2711,7 +2713,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); ctrl &= ~DxEPCTL_EPEna; @@ -2724,7 +2726,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) /* disable endpoint interrupts */ s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return 0; } @@ -2759,15 +2761,15 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hs->lock, flags); if (!on_list(hs_ep, hs_req)) { - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hs->lock, flags); return -EINVAL; } s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hs->lock, flags); return 0; } @@ -2789,7 +2791,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); - spin_lock_irqsave(&hs_ep->lock, irqflags); + spin_lock_irqsave(&hs->lock, irqflags); /* write both IN and OUT control registers */ @@ -2825,7 +2827,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) writel(epctl, hs->regs + epreg); - spin_unlock_irqrestore(&hs_ep->lock, irqflags); + spin_unlock_irqrestore(&hs->lock, irqflags); return 0; } @@ -3061,8 +3063,6 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, INIT_LIST_HEAD(&hs_ep->queue); INIT_LIST_HEAD(&hs_ep->ep.ep_list); - spin_lock_init(&hs_ep->lock); - /* add to the list of endpoints known by the gadget driver */ if (epnum) list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); @@ -3340,7 +3340,7 @@ static int ep_show(struct seq_file *seq, void *v) seq_printf(seq, "request list (%p,%p):\n", ep->queue.next, ep->queue.prev); - spin_lock_irqsave(&ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry(req, &ep->queue, queue) { if (--show_limit < 0) { @@ -3355,7 +3355,7 @@ static int ep_show(struct seq_file *seq, void *v) req->req.actual, req->req.status); } - spin_unlock_irqrestore(&ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return 0; } @@ -3507,6 +3507,8 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) goto err_clk; } + spin_lock_init(&hsotg->lock); + hsotg->irq = ret; ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, -- GitLab From 2b19a52cc8a31ede990323d46a7faeeeba76bb8f Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:25 +0200 Subject: [PATCH 0783/5711] usb: hsotg: samsung: Protect the udc_stop routine with spinlock Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b10791282f15..ee1fe2b8b07f 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2988,6 +2988,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct s3c_hsotg *hsotg = to_hsotg(gadget); + unsigned long flags = 0; int ep; if (!hsotg) @@ -3000,6 +3001,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); + spin_lock_irqsave(&hsotg->lock, flags); + s3c_hsotg_phy_disable(hsotg); regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); @@ -3007,6 +3010,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->gadget.dev.driver = NULL; + spin_unlock_irqrestore(&hsotg->lock, flags); + dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", driver->driver.name); -- GitLab From 5ad1d3160973c588db806072968d7a2a93cb2a80 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:26 +0200 Subject: [PATCH 0784/5711] usb: hsotg: samsung: smp Provide *_lock functions abstraction layer for SMP SoCs For SMP processors the spin_lock_irqsave is _only_ able to disable interrupt on a core on which it is executed. Therefore there may be a situation when other cores raise s3c-hsotg IRQ. Then there are several places where critical sections can be overwritten. To protect the above thread, a spin_lock in the interrupt handler has been added. Due to coherent memory view (especially L1 cache) the spin lock variable control access to IRQ handler only for one CPU core. In this way serialization to access this driver is provided and hence several spin_lock_* routines could be removed from IRQ handler's related functions. The complete_request_lock function has been removed since all its calls are performed from interrupt (spin lock protected) context. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 97 +++++++++++++++++----------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index ee1fe2b8b07f..d208c46341d7 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -895,15 +895,12 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, struct s3c_hsotg_req *hs_req = our_req(req); struct s3c_hsotg_ep *hs_ep = our_ep(ep); struct s3c_hsotg *hs = hs_ep->parent; - unsigned long irqflags; bool first; dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", ep->name, req, req->length, req->buf, req->no_interrupt, req->zero, req->short_not_ok); - spin_lock_irqsave(&hs->lock, irqflags); - /* initialise status of the request */ INIT_LIST_HEAD(&hs_req->queue); req->actual = 0; @@ -922,11 +919,24 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, if (first) s3c_hsotg_start_req(hs, hs_ep, hs_req, false); - spin_unlock_irqrestore(&hs->lock, irqflags); - return 0; } +static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, + gfp_t gfp_flags) +{ + struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct s3c_hsotg *hs = hs_ep->parent; + unsigned long flags = 0; + int ret = 0; + + spin_lock_irqsave(&hs->lock, flags); + ret = s3c_hsotg_ep_queue(ep, req, gfp_flags); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + static void s3c_hsotg_ep_free_request(struct usb_ep *ep, struct usb_request *req) { @@ -1402,28 +1412,6 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, } } -/** - * s3c_hsotg_complete_request_lock - complete a request given to us (locked) - * @hsotg: The device state. - * @hs_ep: The endpoint the request was on. - * @hs_req: The request to complete. - * @result: The result code (0 => Ok, otherwise errno) - * - * See s3c_hsotg_complete_request(), but called with the endpoint's - * lock held. - */ -static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req, - int result) -{ - unsigned long flags; - - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); - spin_unlock_irqrestore(&hsotg->lock, flags); -} - /** * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint * @hsotg: The device state. @@ -1443,7 +1431,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) int max_req; int read_ptr; - spin_lock(&hsotg->lock); if (!hs_req) { u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); @@ -1457,7 +1444,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) for (ptr = 0; ptr < size; ptr += 4) (void)readl(fifo); - spin_unlock(&hsotg->lock); return; } @@ -1487,8 +1473,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) * alignment of the data. */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); - - spin_unlock(&hsotg->lock); } /** @@ -1609,7 +1593,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, s3c_hsotg_send_zlp(hsotg, hs_req); } - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); } /** @@ -1864,7 +1848,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, /* Finish ZLP handling for IN EP0 transactions */ if (hsotg->eps[0].sent_zlp) { dev_dbg(hsotg->dev, "zlp packet received\n"); - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); return; } @@ -1915,7 +1899,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); } else - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); } /** @@ -2123,9 +2107,6 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, int result, bool force) { struct s3c_hsotg_req *req, *treq; - unsigned long flags; - - spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { /* @@ -2139,14 +2120,15 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, s3c_hsotg_complete_request(hsotg, ep, req, result); } - - spin_unlock_irqrestore(&hsotg->lock, flags); } #define call_gadget(_hs, _entry) \ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ - (_hs)->driver && (_hs)->driver->_entry) \ - (_hs)->driver->_entry(&(_hs)->gadget); + (_hs)->driver && (_hs)->driver->_entry) { \ + spin_unlock(&_hs->lock); \ + (_hs)->driver->_entry(&(_hs)->gadget); \ + spin_lock(&_hs->lock); \ + } /** * s3c_hsotg_disconnect - disconnect service @@ -2388,6 +2370,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) u32 gintsts; u32 gintmsk; + spin_lock(&hsotg->lock); irq_retry: gintsts = readl(hsotg->regs + GINTSTS); gintmsk = readl(hsotg->regs + GINTMSK); @@ -2557,6 +2540,8 @@ irq_retry: if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) goto irq_retry; + spin_unlock(&hsotg->lock); + return IRQ_HANDLED; } @@ -2710,10 +2695,10 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); + spin_lock_irqsave(&hsotg->lock, flags); /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); - spin_lock_irqsave(&hsotg->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); ctrl &= ~DxEPCTL_EPEna; @@ -2784,15 +2769,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) struct s3c_hsotg_ep *hs_ep = our_ep(ep); struct s3c_hsotg *hs = hs_ep->parent; int index = hs_ep->index; - unsigned long irqflags; u32 epreg; u32 epctl; u32 xfertype; dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); - spin_lock_irqsave(&hs->lock, irqflags); - /* write both IN and OUT control registers */ epreg = DIEPCTL(index); @@ -2827,19 +2809,36 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) writel(epctl, hs->regs + epreg); - spin_unlock_irqrestore(&hs->lock, irqflags); - return 0; } +/** + * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held + * @ep: The endpoint to set halt. + * @value: Set or unset the halt. + */ +static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) +{ + struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct s3c_hsotg *hs = hs_ep->parent; + unsigned long flags = 0; + int ret = 0; + + spin_lock_irqsave(&hs->lock, flags); + ret = s3c_hsotg_ep_sethalt(ep, value); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + static struct usb_ep_ops s3c_hsotg_ep_ops = { .enable = s3c_hsotg_ep_enable, .disable = s3c_hsotg_ep_disable, .alloc_request = s3c_hsotg_ep_alloc_request, .free_request = s3c_hsotg_ep_free_request, - .queue = s3c_hsotg_ep_queue, + .queue = s3c_hsotg_ep_queue_lock, .dequeue = s3c_hsotg_ep_dequeue, - .set_halt = s3c_hsotg_ep_sethalt, + .set_halt = s3c_hsotg_ep_sethalt_lock, /* note, don't believe we have any call for the fifo routines */ }; -- GitLab From 1591633ed6c4c3994944f31ddb59bc072a2ed0ca Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 15 Jun 2012 11:54:36 +0530 Subject: [PATCH 0785/5711] usb: dwc3: giveback all queued request when ep disabled or reset received In case of ep_disable and reset interrupt is received and, still there was at least one request queued for dma transfer, then endpoint is stopped first. Once endpoint is stopped, callback for all queued request must be called. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 38cd13ffae9d..f6fb42da2e64 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -579,8 +579,11 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) */ udelay(100); - req = next_request(&dep->req_queued); - dwc3_gadget_giveback(dep, req, -ESHUTDOWN); + while (!list_empty(&dep->req_queued)) { + req = next_request(&dep->req_queued); + + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); + } } while (!list_empty(&dep->request_list)) { -- GitLab From d0b1252dd11549103a97a13aca25737b084c5618 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:34:42 +0200 Subject: [PATCH 0786/5711] ALSA: hda - Use common codes for ATI, Nvidia and VIA simple codecs The code refactoring using the same helper functions for sharing the codes among ATI, Nvidia and VIA simple_hdmi* stuff. Except for that spec->pcm_playback is no longer pointer, the functionality doesn't change. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 191 +++++++++++++------------------------ 1 file changed, 65 insertions(+), 126 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c9d0c98bbe86..6bf784fc8d6d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -85,7 +85,7 @@ struct hdmi_spec { * Non-generic ATI/NVIDIA specific */ struct hda_multi_out multiout; - const struct hda_pcm_stream *pcm_playback; + struct hda_pcm_stream pcm_playback; }; @@ -1367,8 +1367,7 @@ static int simple_playback_build_pcms(struct hda_codec *codec) info->name = get_hdmi_pcm_name(i); info->pcm_type = HDA_PCM_TYPE_HDMI; pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; - snd_BUG_ON(!spec->pcm_playback); - *pstr = *spec->pcm_playback; + *pstr = spec->pcm_playback; pstr->nid = spec->cvts[i].cvt_nid; if (pstr->channels_max <= 2 && chans && chans <= 16) pstr->channels_max = chans; @@ -1560,6 +1559,49 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, stream_tag, format, substream); } +static const struct hda_pcm_stream simple_pcm_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .ops = { + .open = simple_playback_pcm_open, + .close = simple_playback_pcm_close, + .prepare = simple_playback_pcm_prepare + }, +}; + +static const struct hda_codec_ops simple_hdmi_patch_ops = { + .build_controls = simple_playback_build_controls, + .build_pcms = simple_playback_build_pcms, + .init = simple_playback_init, + .free = simple_playback_free, +}; + +static int patch_simple_hdmi(struct hda_codec *codec, + hda_nid_t cvt_nid, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + codec->spec = spec; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = cvt_nid; + spec->num_cvts = 1; + spec->num_pins = 1; + spec->cvts[0].cvt_nid = cvt_nid; + spec->cvts[0].cvt_nid = pin_nid; + spec->pcm_playback = simple_pcm_playback; + + codec->patch_ops = simple_hdmi_patch_ops; + + return 0; +} + static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, int channels) { @@ -1732,54 +1774,20 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { }, }; -static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = nvhdmi_master_con_nid_7x, - .rates = SUPPORTED_RATES, - .maxbps = SUPPORTED_MAXBPS, - .formats = SUPPORTED_FORMATS, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = simple_playback_pcm_prepare - }, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - static int patch_nvhdmi_2ch(struct hda_codec *codec) { struct hdmi_spec *spec; + int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, + nvhdmi_master_pin_nid_7x); + if (err < 0) + return err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; - spec->num_cvts = 1; - spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; - spec->pcm_playback = &nvhdmi_pcm_playback_2ch; - - codec->patch_ops = nvhdmi_patch_ops_2ch; - + codec->patch_ops.init = nvhdmi_7x_init; + /* override the PCM rates, etc, as the codec doesn't give full list */ + spec = codec->spec; + spec->pcm_playback.rates = SUPPORTED_RATES; + spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; + spec->pcm_playback.formats = SUPPORTED_FORMATS; return 0; } @@ -1787,13 +1795,11 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) { struct hdmi_spec *spec; int err = patch_nvhdmi_2ch(codec); - if (err < 0) return err; spec = codec->spec; spec->multiout.max_channels = 8; - spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; - codec->patch_ops = nvhdmi_patch_ops_8ch_7x; + spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; /* Initialize the audio infoframe channel mask and checksum to something * valid */ @@ -1837,47 +1843,14 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, return 0; } -static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = ATIHDMI_CVT_NID, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = atihdmi_playback_pcm_prepare - }, -}; - -static const struct hda_codec_ops atihdmi_patch_ops = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = simple_playback_init, - .free = simple_playback_free, -}; - - static int patch_atihdmi(struct hda_codec *codec) { struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; - spec->num_cvts = 1; - spec->num_pins = 1; - spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; - spec->pins[0].pin_nid = ATIHDMI_PIN_NID; - spec->pcm_playback = &atihdmi_pcm_digital_playback; - - codec->patch_ops = atihdmi_patch_ops; - + int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); + if (err < 0) + return err; + spec = codec->spec; + spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; return 0; } @@ -1885,46 +1858,12 @@ static int patch_atihdmi(struct hda_codec *codec) #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ -static const struct hda_codec_ops via_hdmi_patch_ops = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = simple_playback_init, - .free = simple_playback_free, - .unsol_event = simple_hdmi_unsol_event, -}; - -static struct hda_pcm_stream via_hdmi_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = VIAHDMI_CVT_NID, /* NID to query formats and rates*/ - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = simple_playback_pcm_prepare - }, -}; - static int patch_via_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ - spec->num_cvts = 1; - spec->num_pins = 1; - spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; - spec->pins[0].pin_nid = VIAHDMI_PIN_NID; - spec->pcm_playback = &via_hdmi_digital_playback; - - codec->spec = spec; - codec->patch_ops = via_hdmi_patch_ops; - + int err = patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); + if (err < 0) + return err; + codec->patch_ops.unsol_event = simple_hdmi_unsol_event; return 0; } -- GitLab From ceaa86ba2ed90780617be76526de975521374595 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:38:31 +0200 Subject: [PATCH 0787/5711] ALSA: hda - Remove invalid init verbs for Nvidia 2ch codecs Nvidia 2ch codecs have no NIDs greather than 0x05. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6bf784fc8d6d..f51a0b5bfcb2 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1453,7 +1453,15 @@ static const hda_nid_t nvhdmi_con_nids_7x[4] = { 0x6, 0x8, 0xa, 0xc, }; -static const struct hda_verb nvhdmi_basic_init_7x[] = { +static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { + /* set audio protect on */ + { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, + /* enable digital output on pin widget */ + { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, + {} /* terminator */ +}; + +static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { /* set audio protect on */ { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, /* enable digital output on pin widget */ @@ -1481,9 +1489,15 @@ static const struct hda_verb nvhdmi_basic_init_7x[] = { (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) #endif -static int nvhdmi_7x_init(struct hda_codec *codec) +static int nvhdmi_7x_init_2ch(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); + return 0; +} + +static int nvhdmi_7x_init_8ch(struct hda_codec *codec) { - snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); return 0; } @@ -1782,7 +1796,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) if (err < 0) return err; - codec->patch_ops.init = nvhdmi_7x_init; + codec->patch_ops.init = nvhdmi_7x_init_2ch; /* override the PCM rates, etc, as the codec doesn't give full list */ spec = codec->spec; spec->pcm_playback.rates = SUPPORTED_RATES; @@ -1800,6 +1814,7 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) spec = codec->spec; spec->multiout.max_channels = 8; spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; + codec->patch_ops.init = nvhdmi_7x_init_8ch; /* Initialize the audio infoframe channel mask and checksum to something * valid */ -- GitLab From 250e41ac9f31216db1b592bfd77c6a097f10503d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:40:21 +0200 Subject: [PATCH 0788/5711] ALSA: hda - Enable unsol event for ATI and Nvidia HDMI codecs too ATI and Nvidia HDMI codecs have also the pin-detection capability, so let's enable the jack-detecion for them, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f51a0b5bfcb2..8891fa658382 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1401,11 +1401,9 @@ static int simple_playback_build_controls(struct hda_codec *codec) spec->cvts[i].cvt_nid); if (err < 0) return err; - if (codec->patch_ops.unsol_event) { - err = simple_hdmi_build_jack(codec, i); - if (err < 0) - return err; - } + err = simple_hdmi_build_jack(codec, i); + if (err < 0) + return err; } return 0; @@ -1589,6 +1587,7 @@ static const struct hda_codec_ops simple_hdmi_patch_ops = { .build_pcms = simple_playback_build_pcms, .init = simple_playback_init, .free = simple_playback_free, + .unsol_event = simple_hdmi_unsol_event, }; static int patch_simple_hdmi(struct hda_codec *codec, @@ -1875,11 +1874,7 @@ static int patch_atihdmi(struct hda_codec *codec) static int patch_via_hdmi(struct hda_codec *codec) { - int err = patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); - if (err < 0) - return err; - codec->patch_ops.unsol_event = simple_hdmi_unsol_event; - return 0; + return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); } /* -- GitLab From efd68e7254503f3207805f674a1ea1d743f5dfe2 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:33 -0700 Subject: [PATCH 0789/5711] devicetree: add helper inline for retrieving a node's full name The pattern (np ? np->full_name : "") is rather common in the kernel, but can also make for quite long lines. This patch adds a new inline function, of_node_full_name() so that the test for a valid node pointer doesn't need to be open coded at all call sites. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner --- arch/microblaze/pci/pci-common.c | 6 ++---- arch/powerpc/kernel/pci-common.c | 6 ++---- arch/powerpc/kernel/vio.c | 5 ++--- arch/powerpc/platforms/cell/iommu.c | 3 +-- arch/powerpc/platforms/pseries/iommu.c | 2 +- arch/sparc/kernel/of_device_64.c | 2 +- drivers/of/base.c | 2 +- drivers/of/irq.c | 2 +- include/linux/of.h | 10 ++++++++++ kernel/irq/irqdomain.c | 8 ++++---- 10 files changed, 25 insertions(+), 21 deletions(-) diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db14..ca8f6e769960 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev) } else { pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller ? oirq.controller->full_name : - ""); + of_node_full_name(oirq.controller)); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -1493,8 +1492,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) struct pci_bus *bus; struct device_node *node = hose->dn; - pr_debug("PCI: Scanning PHB %s\n", - node ? node->full_name : ""); + pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); pcibios_setup_phb_resources(hose, &resources); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c8185..886c254fd565 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) } else { pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller ? oirq.controller->full_name : - ""); + of_node_full_name(oirq.controller)); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) struct device_node *node = hose->dn; int mode; - pr_debug("PCI: Scanning PHB %s\n", - node ? node->full_name : ""); + pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); /* Get some IO space for the new PHB */ pcibios_setup_phb_io_space(hose); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb87301ccd55..63f72ede4341 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1296,8 +1296,7 @@ static void __devinit vio_dev_release(struct device *dev) struct iommu_table *tbl = get_iommu_table_base(dev); if (tbl) - iommu_free_table(tbl, dev->of_node ? - dev->of_node->full_name : dev_name(dev)); + iommu_free_table(tbl, of_node_full_name(dev->of_node)); of_node_put(dev->of_node); kfree(to_vio_dev(dev)); } @@ -1509,7 +1508,7 @@ static ssize_t devspec_show(struct device *dev, { struct device_node *of_node = dev->of_node; - return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); + return sprintf(buf, "%s\n", of_node_full_name(of_node)); } static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index b9f509a34c01..b6732004c882 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) iommu = cell_iommu_for_node(dev_to_node(dev)); if (iommu == NULL || list_empty(&iommu->windows)) { printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", - dev->of_node ? dev->of_node->full_name : "?", - dev_to_node(dev)); + of_node_full_name(dev->of_node), dev_to_node(dev)); return NULL; } window = list_entry(iommu->windows.next, struct iommu_window, list); diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 0915b1ad66ce..aab5fbc924e6 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) if (!pdn || !PCI_DN(pdn)) { printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " "no DMA window found for pci dev=%s dn=%s\n", - pci_name(dev), dn? dn->full_name : ""); + pci_name(dev), of_node_full_name(dn)); return; } pr_debug(" parent is %s\n", pdn->full_name); diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 7a3be6f6737a..7bbdc26d9512 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -580,7 +580,7 @@ static unsigned int __init build_one_device_irq(struct platform_device *op, printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", op->dev.of_node->full_name, pp->full_name, this_orig_irq, - (iret ? iret->full_name : "NULL"), irq); + of_node_full_name(iret), irq); if (!iret) break; diff --git a/drivers/of/base.c b/drivers/of/base.c index d9bfd49b1935..9282d4cc1091 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1173,7 +1173,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, ap->stem[stem_len] = 0; list_add_tail(&ap->link, &aliases_lookup); pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", - ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); + ap->alias, ap->stem, ap->id, of_node_full_name(np)); } /** diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9cf00602f566..ff8ab7b27373 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, skiplevel: /* Iterate again with new parent */ - pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); + pr_debug(" -> new parent: %s\n", of_node_full_name(newpar)); of_node_put(ipar); ipar = newpar; newpar = NULL; diff --git a/include/linux/of.h b/include/linux/of.h index 2ec1083af7ff..1012377cae92 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -163,6 +163,11 @@ static inline int of_node_to_nid(struct device_node *np) { return -1; } #define of_node_to_nid of_node_to_nid #endif +static inline const char* of_node_full_name(struct device_node *np) +{ + return np ? np->full_name : ""; +} + extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); #define for_each_node_by_name(dn, name) \ @@ -303,6 +308,11 @@ const char *of_prop_next_string(struct property *prop, const char *cur); #else /* CONFIG_OF */ +static inline const char* of_node_full_name(struct device_node *np) +{ + return ""; +} + static inline bool of_have_populated_dt(void) { return false; diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 41c1564103f1..38c5eb839c92 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, } pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", - hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); + hwirq, of_node_full_name(domain->of_node), virq); return virq; } @@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, return intspec[0]; #endif pr_warning("no irq domain found for %s !\n", - controller->full_name); + of_node_full_name(controller)); return 0; } @@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_file *m, void *private) data = irq_desc_get_chip_data(desc); seq_printf(m, data ? "0x%p " : " %p ", data); - if (desc->irq_data.domain && desc->irq_data.domain->of_node) - p = desc->irq_data.domain->of_node->full_name; + if (desc->irq_data.domain) + p = of_node_full_name(desc->irq_data.domain->of_node); else p = none; seq_printf(m, "%s\n", p); -- GitLab From 5ca4db61e859526b2dbee3bcea3626d3de49a0b2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sun, 3 Jun 2012 22:04:34 -0700 Subject: [PATCH 0790/5711] irqdomain: Simple NUMA awareness. While common irqdesc allocation is node aware, the irqdomain code is not. Presently we observe a number of regressions/inconsistencies on NUMA-capable platforms: - Platforms using irqdomains with legacy mappings, where the irq_descs are allocated node-local and the irqdomain data structure is not. - Drivers implementing irqdomains will lose node locality regardless of the underlying struct device's node id. This plugs in NUMA node id proliferation across the various allocation callsites by way of_node_to_nid() node lookup. While of_node_to_nid() does the right thing for OF-capable platforms it doesn't presently handle the non-DT case. This is trivially dealt with by simply wraping in to numa_node_id() unconditionally. Signed-off-by: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring Signed-off-by: Grant Likely --- include/linux/of.h | 15 ++++++++++----- kernel/irq/irqdomain.c | 13 ++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/linux/of.h b/include/linux/of.h index 1012377cae92..76930ee78db5 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -158,11 +159,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) #define OF_BAD_ADDR ((u64)-1) -#ifndef of_node_to_nid -static inline int of_node_to_nid(struct device_node *np) { return -1; } -#define of_node_to_nid of_node_to_nid -#endif - static inline const char* of_node_full_name(struct device_node *np) { return np ? np->full_name : ""; @@ -412,6 +408,15 @@ static inline int of_machine_is_compatible(const char *compat) while (0) #endif /* CONFIG_OF */ +#ifndef of_node_to_nid +static inline int of_node_to_nid(struct device_node *np) +{ + return numa_node_id(); +} + +#define of_node_to_nid of_node_to_nid +#endif + /** * of_property_read_bool - Findfrom a property * @np: device node from which the property value is to be read. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 38c5eb839c92..79ae0ebb90ba 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node, { struct irq_domain *domain; - domain = kzalloc(sizeof(*domain), GFP_KERNEL); + domain = kzalloc_node(sizeof(*domain), GFP_KERNEL, + of_node_to_nid(of_node)); if (WARN_ON(!domain)) return NULL; @@ -229,7 +231,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, struct irq_domain *domain; unsigned int *revmap; - revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL); + revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL, + of_node_to_nid(of_node)); if (WARN_ON(!revmap)) return NULL; @@ -367,7 +370,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) BUG_ON(domain == NULL); WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); - virq = irq_alloc_desc_from(1, 0); + virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); if (!virq) { pr_debug("create_direct virq allocation failed\n"); return 0; @@ -433,9 +436,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain, hint = hwirq % nr_irqs; if (hint == 0) hint++; - virq = irq_alloc_desc_from(hint, 0); + virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node)); if (virq <= 0) - virq = irq_alloc_desc_from(1, 0); + virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); if (virq <= 0) { pr_debug("-> virq allocation failed\n"); return 0; -- GitLab From 732557047128e5c200c3590efba39f10ac46bcb2 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:35 -0700 Subject: [PATCH 0791/5711] irqdomain: Remove unnecessary test for IRQ_DOMAIN_MAP_LEGACY Where irq_domain_associate() is called in irq_create_mapping, there is no need to test for IRQ_DOMAIN_MAP_LEGACY because it is already tested for earlier in the routine. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring --- kernel/irq/irqdomain.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 79ae0ebb90ba..b1f774cfd089 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -445,8 +445,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, } if (irq_setup_virq(domain, virq, hwirq)) { - if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY) - irq_free_desc(virq); + irq_free_desc(virq); return 0; } -- GitLab From 89a86be0ce20022f6ede8bccec078dbb3d63caaa Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sat, 9 Jun 2012 14:19:21 -0700 Subject: [PATCH 0792/5711] libceph: transition socket state prior to actual connect Once we call ->connect(), we are racing against the actual connection, and a subsequent transition from CONNECTING -> CONNECTED. Set the state to CONNECTING before that, under the protection of the mutex, to avoid the race. This was introduced in 928443cd9644e7cfd46f687dbeffda2d1a357ff9, with the original socket state code. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 769a2c9fe1af..bdbecac2d69d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -321,6 +321,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); + con_sock_state_connecting(con); ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), O_NONBLOCK); if (ret == -EINPROGRESS) { @@ -336,8 +337,6 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } con->sock = sock; - con_sock_state_connecting(con); - return 0; } -- GitLab From f3dea7edd3d449fe7a6d402c1ce56a294b985261 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 10 Jun 2012 20:43:56 -0700 Subject: [PATCH 0793/5711] libceph: flush msgr queue during mon_client shutdown We need to flush the msgr workqueue during mon_client shutdown to ensure that any work affecting our embedded ceph_connection is finished so that we can be safely destroyed. Previously, we were flushing the work queue after osd_client shutdown and before mon_client shutdown to ensure that any osd connection refs to authorizers are flushed. Remove the redundant flush, and document in the comment that the mon_client flush is needed to cover that case as well. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/ceph_common.c | 7 ------- net/ceph/mon_client.c | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 2de3ea1bbd64..c815f31a1a3f 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -498,13 +498,6 @@ void ceph_destroy_client(struct ceph_client *client) /* unmount */ ceph_osdc_stop(&client->osdc); - /* - * make sure osd connections close out before destroying the - * auth module, which is needed to free those connections' - * ceph_authorizers. - */ - ceph_msgr_flush(); - ceph_monc_stop(&client->monc); ceph_debugfs_client_cleanup(client); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 7a16750d62a6..dc16595d6885 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -838,6 +838,14 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_unlock(&monc->mutex); + /* + * flush msgr queue before we destroy ourselves to ensure that: + * - any work that references our embedded con is finished. + * - any osd_client or other work that may reference an authorizer + * finishes before we shut down the auth subsystem. + */ + ceph_msgr_flush(); + ceph_auth_destroy(monc->auth); ceph_msg_put(monc->m_auth); -- GitLab From d03fcfe626b89832b36dbfa5fb32a805478b097a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 15 Jun 2012 16:40:21 +0800 Subject: [PATCH 0794/5711] iio: dac: Convert ad5380 to devm_regmap_* APIs Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/iio/dac/ad5380.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 5dfb4451728f..14991ac55f26 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -373,7 +373,7 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, if (indio_dev == NULL) { dev_err(dev, "Failed to allocate iio device\n"); ret = -ENOMEM; - goto error_regmap_exit; + goto error_out; } st = iio_priv(indio_dev); @@ -436,8 +436,7 @@ error_free_reg: kfree(indio_dev->channels); error_free: iio_device_free(indio_dev); -error_regmap_exit: - regmap_exit(regmap); +error_out: return ret; } @@ -456,7 +455,6 @@ static int __devexit ad5380_remove(struct device *dev) regulator_put(st->vref_reg); } - regmap_exit(st->regmap); iio_device_free(indio_dev); return 0; @@ -485,7 +483,7 @@ static int __devinit ad5380_spi_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct regmap *regmap; - regmap = regmap_init_spi(spi, &ad5380_regmap_config); + regmap = devm_regmap_init_spi(spi, &ad5380_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -559,7 +557,7 @@ static int __devinit ad5380_i2c_probe(struct i2c_client *i2c, { struct regmap *regmap; - regmap = regmap_init_i2c(i2c, &ad5380_regmap_config); + regmap = devm_regmap_init_i2c(i2c, &ad5380_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); -- GitLab From 791de6771ee96e208ee30bfed48e8f6b25422843 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:11:49 +0200 Subject: [PATCH 0795/5711] staging:iio:adis16400: Fix ADIS16300 ROLL_OUT register address In the current driver ROLL_OUT register address is the same as the PITCH_OUT register address. This patch fixes it to use the correct address. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index 83d133efaac6..1f4e98783ef5 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -42,7 +42,7 @@ #define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ #define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ -#define ADIS16300_ROLL_OUT 0x12 /* Y axis inclinometer output measurement */ +#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */ /* Calibration parameters */ #define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ -- GitLab From 6f30592e8cf0c9eb2e403fe2a44c1d7c1d58b4f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:11:50 +0200 Subject: [PATCH 0796/5711] staging:iio:adis16400: Fix ADIS16300 temperature address The ADIS16300 uses the same address for the temperature register as the ADIS16350 and not the same as the ADIS16400. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 1f6bd854e950..1c9931ed4057 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -946,7 +946,7 @@ static struct iio_chan_spec adis16300_channels[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = temp, + .address = temp0, .scan_index = ADIS16400_SCAN_TEMP, .scan_type = IIO_ST('s', 12, 16, 0), }, { -- GitLab From bb7cf8bc52ff388c89f5984e428e966e326315ad Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:11:51 +0200 Subject: [PATCH 0797/5711] staging:iio:adis16400: Fix ADIS16334 temperature address The channel spec for ADUS16334's temperature channel uses the address and scan index for the Z-axis acceleration channel. This patch fixes it to use the temperature channel address and scan index instead. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 1c9931ed4057..7aa3a9aa55e4 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -1054,8 +1054,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, + .address = temp0, + .scan_index = ADIS16400_SCAN_TEMP, .scan_type = IIO_ST('s', 14, 16, 0), }, IIO_CHAN_SOFT_TIMESTAMP(12) -- GitLab From 07a8329c48b699a85086756eaa1a658540d02ac4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:11:52 +0200 Subject: [PATCH 0798/5711] staging:iio:adis16400: Fix ADIS163xx AUX_ADC address The ADIS163xx variants use a different register address for the auxiliary ADC channel than the ADIS16400. This patch fixes them to use the correct address. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400.h | 1 + drivers/staging/iio/imu/adis16400_core.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index 1f4e98783ef5..9dd9f1459a4d 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -43,6 +43,7 @@ #define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ #define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */ +#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */ /* Calibration parameters */ #define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 7aa3a9aa55e4..387301437cf5 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -472,11 +472,12 @@ enum adis16400_chan { temp, temp0, temp1, temp2, in1, + in2, incli_x, incli_y, }; -static u8 adis16400_addresses[17][2] = { +static u8 adis16400_addresses[18][2] = { [in_supply] = { ADIS16400_SUPPLY_OUT }, [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF }, [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF }, @@ -491,7 +492,8 @@ static u8 adis16400_addresses[17][2] = { [temp0] = { ADIS16350_XTEMP_OUT }, [temp1] = { ADIS16350_YTEMP_OUT }, [temp2] = { ADIS16350_ZTEMP_OUT }, - [in1] = { ADIS16400_AUX_ADC }, + [in1] = { ADIS16300_AUX_ADC }, + [in2] = { ADIS16400_AUX_ADC }, [incli_x] = { ADIS16300_PITCH_OUT }, [incli_y] = { ADIS16300_ROLL_OUT } }; @@ -752,7 +754,7 @@ static struct iio_chan_spec adis16400_channels[] = { .channel = 1, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in1, + .address = in2, .scan_index = ADIS16400_SCAN_ADC_0, .scan_type = IIO_ST('s', 12, 16, 0), }, -- GitLab From 25c38aa3d17d6ccfca225fafce68401908a1ccb4 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:27:10 +0200 Subject: [PATCH 0799/5711] staging: iio: fix typos in simple dummy driver Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_simple_dummy.c | 10 +++++----- drivers/staging/iio/iio_simple_dummy_buffer.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 310411911ed7..155a49a9da7e 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -27,7 +27,7 @@ /* * A few elements needed to fake a bus for this driver - * Note instances parmeter controls how many of these + * Note instances parameter controls how many of these * dummy devices are registered. */ static unsigned instances = 1; @@ -178,7 +178,7 @@ static struct iio_chan_spec iio_dummy_channels[] = { .scan_index = accelx, .scan_type = { /* Description of storage in buffer */ .sign = 's', /* signed */ - .realbits = 16, /* 12 bits */ + .realbits = 16, /* 16 bits */ .storagebits = 16, /* 16 bits used for storage */ .shift = 0, /* zero shift */ }, @@ -285,9 +285,9 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, * iio_dummy_write_raw() - data write function. * @indio_dev: the struct iio_dev associated with this device instance * @chan: the channel whose data is to be read - * @val: first element of returned value (typically INT) - * @val2: second element of returned value (typically MICRO) - * @mask: what we actually want to read. 0 is the channel, everything else + * @val: first element of value to set (typically INT) + * @val2: second element of value to set (typically MICRO) + * @mask: what we actually want to write. 0 is the channel, everything else * is as per the info_mask in iio_chan_spec. * * Note that all raw writes are assumed IIO_VAL_INT and info mask elements diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index fdfc8739095a..3e43025f887d 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -67,8 +67,8 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) * software culled hardware scans: * occasionally a driver may process the nearest hardware * scan to avoid storing elements that are not desired. This - * is the fidliest option by far. - * Here lets pretend we have random access. And the values are + * is the fiddliest option by far. + * Here let's pretend we have random access. And the values are * in the constant table fakedata. */ int i, j; -- GitLab From eaedfa54db0584ddf7308bb99c473cc6cf28fb65 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:14:36 +0200 Subject: [PATCH 0800/5711] staging: iio: Remove superfluous flush_scheduled_work None of these drivers ever schedule any work, so there is no need to flush any scheduled work when the driver is removed. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16209_core.c | 2 -- drivers/staging/iio/accel/adis16220_core.c | 2 -- drivers/staging/iio/accel/adis16240_core.c | 2 -- drivers/staging/iio/gyro/adis16260_core.c | 2 -- 4 files changed, 8 deletions(-) diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index f6fd0d31d4f0..6fc426e27e4e 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -606,8 +606,6 @@ static int adis16209_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - flush_scheduled_work(); - iio_device_unregister(indio_dev); adis16209_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 6a9ac898cb01..af5c57637166 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -694,8 +694,6 @@ static int adis16220_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - flush_scheduled_work(); - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 8b15eaea3381..2f59f83d002d 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -641,8 +641,6 @@ static int adis16240_remove(struct spi_device *spi) struct iio_dev *indio_dev = spi_get_drvdata(spi); - flush_scheduled_work(); - iio_device_unregister(indio_dev); adis16240_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index ec765f955f8d..fdb84cc3d7c9 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -728,8 +728,6 @@ static int adis16260_remove(struct spi_device *spi) if (ret) goto err_ret; - flush_scheduled_work(); - adis16260_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16260_unconfigure_ring(indio_dev); -- GitLab From cf655d2d6fb38de1a292e87075b39b1741f406c0 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:23 +0200 Subject: [PATCH 0801/5711] iio: sysfs-bus-iio typo Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-iio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 05449c68952c..a3774a71ec26 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -122,7 +122,7 @@ Description: If an axis is specified it generally means that the temperature sensor is associated with one part of a compound device (e.g. a gyroscope axis). Units after application of scale and offset - are milli degrees Celsuis. + are milli degrees Celsius. What: /sys/bus/iio/devices/iio:deviceX/in_tempX_input KernelVersion: 2.6.38 -- GitLab From 79e9b4e6f2d3fb904233f62cea1b6a42a58416a4 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:24 +0200 Subject: [PATCH 0802/5711] iio: cleanup sysfs-bus-iio-light-lm3533-als Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als b/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als index 694a52c8cf82..22c5ea670971 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als +++ b/Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als @@ -14,7 +14,6 @@ KernelVersion: 3.5 Contact: Johan Hovold Description: Get the hysteresis for thresholds Y, that is, - threshY_hysteresis = threshY_raising - threshY_falling What: /sys/.../events/illuminance_threshY_falling_value @@ -31,7 +30,7 @@ Description: threshY_raising. These thresholds correspond to the eight zone-boundary - registers (boundaryY_{low,high}) and defines the five light + registers (boundaryY_{low,high}) and define the five light zones. What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_zone -- GitLab From 33e0c249801c6913b2bd102683ab65ab61e12952 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:25 +0200 Subject: [PATCH 0803/5711] iio: iio/machine.h typo Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h index 0b1f19bfdc44..400a453ff67b 100644 --- a/include/linux/iio/machine.h +++ b/include/linux/iio/machine.h @@ -14,7 +14,7 @@ * This is matched against the datasheet_name element * of struct iio_chan_spec. * @consumer_dev_name: Name to uniquely identify the consumer device. - * @consumer_channel: Unique name used to idenitify the channel on the + * @consumer_channel: Unique name used to identify the channel on the * consumer side. */ struct iio_map { -- GitLab From a21601463d0e542d20635b835b6c97294571b0a5 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:26 +0200 Subject: [PATCH 0804/5711] staging: iio: add IIO_ALTVOLTAGE to iio_event_monitor example IIO_ALTVOLTAGE is used by frequency/adf4350 and frequency/ad9523 Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Documentation/iio_event_monitor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 22275845fb12..4326e9e764c9 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -45,6 +45,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ANGL] = "angl", [IIO_TIMESTAMP] = "timestamp", [IIO_CAPACITANCE] = "capacitance", + [IIO_ALTVOLTAGE] = "altvoltage", }; static const char * const iio_ev_type_text[] = { @@ -92,6 +93,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_ANGL: case IIO_TIMESTAMP: case IIO_CAPACITANCE: + case IIO_ALTVOLTAGE: break; default: return false; -- GitLab From 60ba16e35b887008eececcb935c835026504cef5 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:27 +0200 Subject: [PATCH 0805/5711] staging: iio:: fix some typos typos in comments, fix ring_sw module description Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Documentation/device.txt | 10 +++++----- drivers/staging/iio/Documentation/overview.txt | 2 +- drivers/staging/iio/Documentation/ring.txt | 4 ++-- drivers/staging/iio/ring_sw.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt index f03fbd3bb454..ea08d6213373 100644 --- a/drivers/staging/iio/Documentation/device.txt +++ b/drivers/staging/iio/Documentation/device.txt @@ -12,7 +12,7 @@ struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state)); where chip_state is a structure of local state data for this instance of the chip. -That data can be accessed using iio_priv(struct iio_dev *) +That data can be accessed using iio_priv(struct iio_dev *). Then fill in the following: @@ -39,7 +39,7 @@ Then fill in the following: and for associate parameters such as offsets and scales. * info->write_raw: Raw value writing function. Used for writable device values such - as DAC values and caliboffset. + as DAC values and calibbias. * info->read_event_config: Typically only set if there are some interrupt lines. This is used to read if an on sensor event detector is enabled. @@ -62,8 +62,8 @@ Then fill in the following: Poll function related elements. This controls what occurs when a trigger to which this device is attached sends an event. - indio_dev->channels: - Specification of device channels. Most attributes etc are built - form this spec. + Specification of device channels. Most attributes etc. are built + from this spec. - indio_dev->num_channels: How many channels are there? @@ -76,4 +76,4 @@ be registered afterwards (otherwise the whole parentage of devices gets confused) On remove, iio_device_unregister(indio_dev) will remove the device from -the core, and iio_device_free will clean up. +the core, and iio_device_free(indio_dev) will clean up. diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt index afc39ecde9ca..43f92b06bc3e 100644 --- a/drivers/staging/iio/Documentation/overview.txt +++ b/drivers/staging/iio/Documentation/overview.txt @@ -8,7 +8,7 @@ actual devices combine some ADCs with digital to analog converters The aim is to fill the gap between the somewhat similar hwmon and input subsystems. Hwmon is very much directed at low sample rate sensors used in applications such as fan speed control and temperature -measurement. Input is, as it's name suggests focused on input +measurement. Input is, as its name suggests focused on input devices. In some cases there is considerable overlap between these and IIO. diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e33807761cd7..e1da43381d0e 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -15,8 +15,8 @@ struct iio_ring_buffer contains a struct iio_ring_setup_ops *setup_ops which in turn contains the 4 function pointers (preenable, postenable, predisable and postdisable). These are used to perform device specific steps on either side -of the core changing it's current mode to indicate that the buffer -is enabled or disabled (along with enabling triggering etc as appropriate). +of the core changing its current mode to indicate that the buffer +is enabled or disabled (along with enabling triggering etc. as appropriate). Also in struct iio_ring_buffer is a struct iio_ring_access_funcs. The function pointers within here are used to allow the core to handle diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 9358c6cb1c72..f61c8fdaab06 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -24,7 +24,7 @@ * @read_p: read pointer (oldest available) * @write_p: write pointer * @half_p: half buffer length behind write_p (event generation) - * @update_needed: flag to indicated change in size requested + * @update_needed: flag to indicate change in size requested * * Note that the first element of all ring buffers must be a * struct iio_buffer. @@ -363,5 +363,5 @@ void iio_sw_rb_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_sw_rb_free); -MODULE_DESCRIPTION("Industrialio I/O software ring buffer"); +MODULE_DESCRIPTION("Industrial I/O software ring buffer"); MODULE_LICENSE("GPL"); -- GitLab From fb1c4bcd721fcc30d6e43f60a244483dc0d07056 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Fri, 15 Jun 2012 19:25:28 +0200 Subject: [PATCH 0806/5711] iio: iio/events.h typos Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/events.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h index b5acbf93c5da..13ce220c7003 100644 --- a/include/linux/iio/events.h +++ b/include/linux/iio/events.h @@ -46,7 +46,7 @@ enum iio_event_direction { * @diff: Whether the event is for an differential channel or not. * @modifier: Modifier for the channel. Should be one of enum iio_modifier. * @direction: Direction of the event. One of enum iio_event_direction. - * @type: Type of the event. Should be one enum iio_event_type. + * @type: Type of the event. Should be one of enum iio_event_type. * @chan: Channel number for non-differential channels. * @chan1: First channel number for differential channels. * @chan2: Second channel number for differential channels. @@ -69,7 +69,7 @@ enum iio_event_direction { * @chan_type: Type of the channel. Should be one of enum iio_chan_type. * @number: Channel number. * @modifier: Modifier for the channel. Should be one of enum iio_modifier. - * @type: Type of the event. Should be one enum iio_event_type. + * @type: Type of the event. Should be one of enum iio_event_type. * @direction: Direction of the event. One of enum iio_event_direction. */ @@ -81,7 +81,7 @@ enum iio_event_direction { * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels * @chan_type: Type of the channel. Should be one of enum iio_chan_type. * @number: Channel number. - * @type: Type of the event. Should be one enum iio_event_type. + * @type: Type of the event. Should be one of enum iio_event_type. * @direction: Direction of the event. One of enum iio_event_direction. */ -- GitLab From aff1eb4e3dd13ee419c6cd76baf1bcc2edeaaa86 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Jun 2012 18:08:59 +0200 Subject: [PATCH 0807/5711] iio: buffer: Fix NULL pointer deref caused by empty scan mask iio_scan_mask_match() returns NULL if the passed in scan mask is empty. This will happen if no channel has been selected and buffer is enabled. iio_sw_buffer_preenable() will assign NULL to indio_dev->active_scan_mask in this case. As a result iio_update_demux() will cause a NULL pointer deref, because it expects active_scan_mask to be non-NULL. Since it does not make much sense to start data capture if there is no data to capture this patch updates the code to fail gracefully in iio_scan_mask_match() instead of crashing the kernel. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-buffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index ac185b8694bd..2f35db93cdb6 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -553,6 +553,10 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev) buffer->scan_mask); else indio_dev->active_scan_mask = buffer->scan_mask; + + if (indio_dev->active_scan_mask == NULL) + return -EINVAL; + iio_update_demux(indio_dev); if (indio_dev->info->update_scan_mode) -- GitLab From dc348147a9e1ba84395d1e585d26af44f0ca4e29 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 15 Jun 2012 09:18:55 -0700 Subject: [PATCH 0808/5711] staging: comedi: fix Kconfig for COMEDI_PCMCIA_DRIVERS The depends on PCCARD is redundant. All of the comedi PCMCIA drivers depend on PCMCIA which can only be enabled if PCCARD is enabled. Remove the extra depends check. Signed-off-by: H Hartley Sweeten Cc: Frank Mori Hess Tested-by: Ian Abbott Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 848cf7e3e8fd..2ca7f08bc5b9 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -1097,7 +1097,7 @@ endif # COMEDI_PCI_DRIVERS menuconfig COMEDI_PCMCIA_DRIVERS tristate "Comedi PCMCIA drivers" - depends on (PCMCIA || PCCARD) + depends on PCMCIA ---help--- Enable comedi PCMCIA and PCCARD drivers to be built -- GitLab From 71c421dbd9d87ffe6229816a04b759ec5613014d Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 15 Jun 2012 12:01:33 +0200 Subject: [PATCH 0809/5711] usb: correct trivial typo in drivers/usb/host/Kconfig Correct "Enbale" -> "Enable", in the desc for USB_HCD_BCMA and USB_HCD_SSB. Signed-off-by: Jesper Dangaard Brouer Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 83e58df29fe3..18ba33da34ec 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -652,7 +652,7 @@ config USB_HCD_BCMA select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help - Enbale support for the EHCI and OCHI host controller on an bcma bus. + Enable support for the EHCI and OCHI host controller on an bcma bus. It converts the bcma driver into two platform device drivers for ehci and ohci. @@ -664,7 +664,7 @@ config USB_HCD_SSB select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help - Enbale support for the EHCI and OCHI host controller on an bcma bus. + Enable support for the EHCI and OCHI host controller on an bcma bus. It converts the bcma driver into two platform device drivers for ehci and ohci. -- GitLab From 60cd4dba9b75da175c79d0dc6d7beb8701307ff8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 15 Jun 2012 16:38:23 -0600 Subject: [PATCH 0810/5711] sparc/PCI: remove unused pcibios_assign_resource() definition pcibios_assign_resource() isn't used anywhere; remove it. Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pcic.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index ded3f6090c3f..46ba84998f16 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -884,11 +884,6 @@ void __init sun4m_pci_init_IRQ(void) sparc_config.load_profile_irq = pcic_load_profile_irq; } -int pcibios_assign_resource(struct pci_dev *pdev, int resource) -{ - return -ENXIO; -} - /* * This probably belongs here rather than ioport.c because * we do not want this crud linked into SBus kernels. -- GitLab From aaa377302b2994fcc2c66741b47da33feb489dca Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 16 Jun 2012 15:30:32 +0200 Subject: [PATCH 0811/5711] drm/i915/crt: Do not rely upon the HPD presence pin VGA hotplug detection "works" by measuring the resistance across certain pins. A lot of kvm switches fumble this and wire up cheap resistors with the wrong resistance or don't bother at all. To accomodate these, also try to detect a connected monitor by trying to grab the edid. Contrary to !HAS_HOTPLUG platforms we don't bother with an actual load-detection cycle when the output is life - that would be actual work to implement because things moved around. This is the big difference to Chris Wilson's original approach: commit 9e612a008fa7fe493a473454def56aa321479495 Author: Chris Wilson Date: Thu May 31 13:08:53 2012 +0100 drm/i915/crt: Do not rely upon the HPD presence pin This blew up on Linus' machine because it errornously detected a vga screen (without and edid and hence only the default modes), leading to it's prompt removal: commit 8f53369b753f5f4c7684c2eb0b592152abb1dd00 Author: Linus Torvalds Date: Fri Jun 8 14:53:06 2012 -0700 Revert "drm/i915/crt: Do not rely upon the HPD presence pin" Some digging around in Bspec shows the reason why load detect doesn't work on newer chips - the legacy VGA load detect bit isn't wired up any longer: Public Snb Bspec, Vol3 Part1, 1.1.1 ST00 Input Status 0, bit4: "RGB Comparator / Sense. This bit is here for compatibility and will always return one. Monitor detection must be done be done through the programming of registers in the MMIO space. 0 = Below threshold 1 = Above threshold" v2: Add a comment in the code that load detect on hotplug capable machines is broken and pimp the commit message with a quote of Bspec to show why. Reported-and-tested-by: Matthieu LAVIE Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50501 Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 75a70c46ef1b..5978490dac92 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -453,18 +453,27 @@ intel_crt_detect(struct drm_connector *connector, bool force) struct intel_load_detect_pipe tmp; if (I915_HAS_HOTPLUG(dev)) { + /* We can not rely on the HPD pin always being correctly wired + * up, for example many KVM do not pass it through, and so + * only trust an assertion that the monitor is connected. + */ if (intel_crt_detect_hotplug(connector)) { DRM_DEBUG_KMS("CRT detected via hotplug\n"); return connector_status_connected; - } else { + } else DRM_DEBUG_KMS("CRT not detected via hotplug\n"); - return connector_status_disconnected; - } } if (intel_crt_detect_ddc(connector)) return connector_status_connected; + /* Load detection is broken on HPD capable machines. Whoever wants a + * broken monitor (without edid) to work behind a broken kvm (that fails + * to have the right resistors for HP detection) needs to fix this up. + * For now just bail out. */ + if (I915_HAS_HOTPLUG(dev)) + return connector_status_disconnected; + if (!force) return connector->status; -- GitLab From 492bf4f25a1c8e87a6abb0e2edaa532b7fd43b29 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:24 +0200 Subject: [PATCH 0812/5711] powerpc/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Kumar Gala Cc: Paul Mackerras Acked-by: Benjamin Herrenschmidt Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/powerpc/platforms/85xx/tqm85xx.c | 2 +- arch/powerpc/platforms/86xx/gef_ppc9a.c | 2 +- arch/powerpc/platforms/86xx/gef_sbc310.c | 2 +- arch/powerpc/platforms/86xx/gef_sbc610.c | 2 +- arch/powerpc/sysdev/fsl_pci.c | 2 +- arch/powerpc/sysdev/mv64x60_pci.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 4d786c25d3e5..3e70a2035e53 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -102,7 +102,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m) seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); } -static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev) +static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 1fca663f1b25..563aafa8629c 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -164,7 +164,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m) gef_ppc9a_get_vme_is_syscon() ? "yes" : "no"); } -static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_ppc9a_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 14e0e576bcbd..cc6a91ae0889 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -152,7 +152,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m) } -static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc310_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 1638f43599f0..aead6b337f4a 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -141,7 +141,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m) seq_printf(m, "SVR\t\t: 0x%x\n", svid); } -static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc610_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 6073288fed29..edbf79465d50 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -36,7 +36,7 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci; -static void __init quirk_fsl_pcie_header(struct pci_dev *dev) +static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) { u8 progif; diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index b0037cefaada..364b14d4754b 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -104,7 +104,7 @@ subsys_initcall(mv64x60_sysfs_init); #endif /* CONFIG_SYSFS */ -static void __init mv64x60_pci_fixup_early(struct pci_dev *dev) +static void __devinit mv64x60_pci_fixup_early(struct pci_dev *dev) { /* * Set the host bridge hdr_type to an invalid value so that -- GitLab From 1359bac229637cd9e317f6069e5fb3544d64b7ca Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:25 +0200 Subject: [PATCH 0813/5711] sh/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Paul Mundt Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/sh/drivers/pci/fixups-dreamcast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index edeea8960c30..a5fe1b54c952 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -28,7 +28,7 @@ #include #include -static void __init gapspci_fixup_resources(struct pci_dev *dev) +static void __devinit gapspci_fixup_resources(struct pci_dev *dev) { struct pci_channel *p = dev->sysdata; -- GitLab From bb15d8db7cce766b62cab624120916d25e94ac7a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:17 +0200 Subject: [PATCH 0814/5711] scripts/modpost: check for bad references in .pci.fixups area Functions used for PCI fixups (like DECLARE_PCI_FIXUP_HEADER) are often marked __init. This is okay as long as nobody is using PCI hotplug. However if one does execute | echo 1 > /sys/bus/pci/rescan and we hit a module which is marked __init istead of __devinit then we go boom because the code is removed after the kernel booted. This patch help to see those section mismatches. Cc: Michal Marek Cc: linux-kbuild@vger.kernel.org Cc: Rusty Russell Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- scripts/mod/modpost.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0f84bb38eb0d..68e9f5ed0a6f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -865,6 +865,11 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_EXIT_TEXT_SECTIONS \ ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$" +#define ALL_PCI_INIT_SECTIONS \ + ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ + ".pci_fixup_enable$", ".pci_fixup_resume$", \ + ".pci_fixup_resume_early$", ".pci_fixup_suspend$" + #define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \ MEM_INIT_SECTIONS #define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \ @@ -1027,6 +1032,12 @@ const struct sectioncheck sectioncheck[] = { .mismatch = ANY_EXIT_TO_ANY_INIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, +{ + .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, + .tosec = { INIT_SECTIONS, NULL }, + .mismatch = ANY_INIT_TO_ANY_EXIT, + .symbol_white_list = { NULL }, +}, /* Do not export init/exit functions or data */ { .fromsec = { "__ksymtab*", NULL }, -- GitLab From fbebb9fd22581b6422d60669c4ff86ce99d6cdba Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 16 Jun 2012 14:40:22 -0600 Subject: [PATCH 0815/5711] PCI: add infrastructure for devices with broken INTx masking pci_intx_mask_supported() assumes INTx masking is supported if the PCI_COMMAND_INTX_DISABLE bit is writable. But when that bit is set, some devices don't actually mask INTx or update PCI_STATUS_INTERRUPT as we expect. This patch adds a way for quirks to identify these broken devices. [bhelgaas: split out from Chelsio quirk addition] Signed-off-by: Jan Kiszka Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 3 +++ drivers/pci/quirks.c | 10 ++++++++++ include/linux/pci.h | 1 + 3 files changed, 14 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..9ae517a68360 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2876,6 +2876,9 @@ bool pci_intx_mask_supported(struct pci_dev *dev) bool mask_supported = false; u16 orig, new; + if (dev->broken_intx_masking) + return false; + pci_cfg_access_lock(dev); pci_read_config_word(dev, PCI_COMMAND, &orig); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a7521677541..cc13415416d7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2929,6 +2929,16 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); +/* + * Some devices may pass our check in pci_intx_mask_supported if + * PCI_COMMAND_INTX_DISABLE works though they actually do not properly + * support this feature. + */ +static void __devinit quirk_broken_intx_masking(struct pci_dev *dev) +{ + dev->broken_intx_masking = 1; +} + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..40a039f1dffb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -324,6 +324,7 @@ struct pci_dev { unsigned int is_hotplug_bridge:1; unsigned int __aer_firmware_first_valid:1; unsigned int __aer_firmware_first:1; + unsigned int broken_intx_masking:1; pci_dev_flags_t dev_flags; atomic_t enable_cnt; /* pci_enable_device has been called */ -- GitLab From 9d23f9e946ad757344792a20ba5152f3a921688b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 13 Jun 2012 22:28:24 +0200 Subject: [PATCH 0816/5711] firewire: core: fix multichannel IR with buffers larger than 2 GB With a 32-bit i, computing i< Signed-off-by: Stefan Richter --- drivers/firewire/core-iso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 8382e27e9a27..38c0aa60b2cb 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -146,7 +146,7 @@ EXPORT_SYMBOL(fw_iso_buffer_destroy); /* Convert DMA address to offset into virtually contiguous buffer. */ size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed) { - int i; + size_t i; dma_addr_t address; ssize_t offset; -- GitLab From e18907cc8a3cd6e09510632b753b8b6fefa1752a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 13 Jun 2012 22:29:20 +0200 Subject: [PATCH 0817/5711] firewire: ohci: initialize multiChanMode bits after reset OHCI 1.1 says: | Since the value of this bit is undefined after reset in all IR | contexts, software shall initialize this bit to zero in all contexts | whether or not active to maintain the exclusive nature of this bit. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 922cd26b25e3..c788dbdaf3bc 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2279,6 +2279,11 @@ static int ohci_enable(struct fw_card *card, ohci->bus_time_running = false; + for (i = 0; i < 32; i++) + if (ohci->ir_context_support & (1 << i)) + reg_write(ohci, OHCI1394_IsoRcvContextControlClear(i), + IR_CONTEXT_MULTI_CHANNEL_MODE); + version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; if (version >= OHCI_VERSION_1_1) { reg_write(ohci, OHCI1394_InitialChannelsAvailableHi, -- GitLab From e0690385a86cac5403a62d91dc146f2508416ded Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Tue, 12 Jun 2012 08:50:08 +0200 Subject: [PATCH 0818/5711] ASoC: Ux500: Add machine-driver Add machine-driver for ST-Ericsson U8500 platform, including support for the AB8500-codec. Signed-off-by: Ola Lilja Acked-by: Linus Walleij Signed-off-by: Mark Brown --- sound/soc/ux500/Kconfig | 11 + sound/soc/ux500/Makefile | 3 + sound/soc/ux500/mop500.c | 113 +++++++++ sound/soc/ux500/mop500_ab8500.c | 431 ++++++++++++++++++++++++++++++++ sound/soc/ux500/mop500_ab8500.h | 22 ++ 5 files changed, 580 insertions(+) create mode 100644 sound/soc/ux500/mop500.c create mode 100644 sound/soc/ux500/mop500_ab8500.c create mode 100644 sound/soc/ux500/mop500_ab8500.h diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig index 1d385150064f..069330d82be5 100644 --- a/sound/soc/ux500/Kconfig +++ b/sound/soc/ux500/Kconfig @@ -19,3 +19,14 @@ config SND_SOC_UX500_PLAT_DMA select SND_SOC_DMAENGINE_PCM help Say Y if you want to enable the Ux500 platform-driver. + ++config SND_SOC_UX500_MACH_MOP500 ++ tristate "Machine - MOP500 (Ux500 + AB8500)" + depends on AB8500_CORE && AB8500_GPADC && SND_SOC_UX500 + select SND_SOC_AB8500_CODEC + select SND_SOC_UX500_PLAT_MSP_I2S + select SND_SOC_UX500_PLAT_DMA + help + Select this to enable the MOP500 machine-driver. + This will enable platform-drivers for: Ux500 + This will enable codec-drivers for: AB8500 diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile index 4634bf015f62..cce0c11a4d86 100644 --- a/sound/soc/ux500/Makefile +++ b/sound/soc/ux500/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o snd-soc-ux500-plat-dma-objs := ux500_pcm.o obj-$(CONFIG_SND_SOC_UX500_PLAT_DMA) += snd-soc-ux500-plat-dma.o + +snd-soc-ux500-mach-mop500-objs := mop500.o mop500_ab8500.o +obj-$(CONFIG_SND_SOC_UX500_MACH_MOP500) += snd-soc-ux500-mach-mop500.o diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c new file mode 100644 index 000000000000..31c4d26d0359 --- /dev/null +++ b/sound/soc/ux500/mop500.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja (ola.o.lilja@stericsson.com) + * for ST-Ericsson. + * + * License terms: + * + * 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 "ux500_pcm.h" +#include "ux500_msp_dai.h" + +#include + +/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ +struct snd_soc_dai_link mop500_dai_links[] = { + { + .name = "ab8500_0", + .stream_name = "ab8500_0", + .cpu_dai_name = "ux500-msp-i2s.1", + .codec_dai_name = "ab8500-codec-dai.0", + .platform_name = "ux500-pcm.0", + .codec_name = "ab8500-codec.0", + .init = mop500_ab8500_machine_init, + .ops = mop500_ab8500_ops, + }, + { + .name = "ab8500_1", + .stream_name = "ab8500_1", + .cpu_dai_name = "ux500-msp-i2s.3", + .codec_dai_name = "ab8500-codec-dai.1", + .platform_name = "ux500-pcm.0", + .codec_name = "ab8500-codec.0", + .init = NULL, + .ops = mop500_ab8500_ops, + }, +}; + +static struct snd_soc_card mop500_card = { + .name = "MOP500-card", + .probe = NULL, + .dai_link = mop500_dai_links, + .num_links = ARRAY_SIZE(mop500_dai_links), +}; + +static int __devinit mop500_probe(struct platform_device *pdev) +{ + int ret; + + pr_debug("%s: Enter.\n", __func__); + + dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); + + mop500_card.dev = &pdev->dev; + + dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", + __func__, mop500_card.name); + platform_set_drvdata(pdev, &mop500_card); + + snd_soc_card_set_drvdata(&mop500_card, NULL); + + dev_dbg(&pdev->dev, "%s: Card %s: num_links = %d\n", + __func__, mop500_card.name, mop500_card.num_links); + dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: name = %s\n", + __func__, mop500_card.name, mop500_card.dai_link[0].name); + dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: stream_name = %s\n", + __func__, mop500_card.name, + mop500_card.dai_link[0].stream_name); + + ret = snd_soc_register_card(&mop500_card); + if (ret) + dev_err(&pdev->dev, + "Error: snd_soc_register_card failed (%d)!\n", + ret); + + return ret; +} + +static int __devexit mop500_remove(struct platform_device *pdev) +{ + struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); + + pr_debug("%s: Enter.\n", __func__); + + snd_soc_unregister_card(mop500_card); + mop500_ab8500_remove(mop500_card); + + return 0; +} + +static struct platform_driver snd_soc_mop500_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "snd-soc-mop500", + }, + .probe = mop500_probe, + .remove = __devexit_p(mop500_remove), +}; + +module_platform_driver(snd_soc_mop500_driver); diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c new file mode 100644 index 000000000000..78cce236693e --- /dev/null +++ b/sound/soc/ux500/mop500_ab8500.c @@ -0,0 +1,431 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja , + * Kristoffer Karlsson + * for ST-Ericsson. + * + * License terms: + * + * 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 "ux500_pcm.h" +#include "ux500_msp_dai.h" +#include "../codecs/ab8500-codec.h" + +#define TX_SLOT_MONO 0x0008 +#define TX_SLOT_STEREO 0x000a +#define RX_SLOT_MONO 0x0001 +#define RX_SLOT_STEREO 0x0003 +#define TX_SLOT_8CH 0x00FF +#define RX_SLOT_8CH 0x00FF + +#define DEF_TX_SLOTS TX_SLOT_STEREO +#define DEF_RX_SLOTS RX_SLOT_MONO + +#define DRIVERMODE_NORMAL 0 +#define DRIVERMODE_CODEC_ONLY 1 + +/* Slot configuration */ +static unsigned int tx_slots = DEF_TX_SLOTS; +static unsigned int rx_slots = DEF_RX_SLOTS; + +/* Clocks */ +static const char * const enum_mclk[] = { + "SYSCLK", + "ULPCLK" +}; +enum mclk { + MCLK_SYSCLK, + MCLK_ULPCLK, +}; + +static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk); + +/* Private data for machine-part MOP500<->AB8500 */ +struct mop500_ab8500_drvdata { + /* Clocks */ + enum mclk mclk_sel; + struct clk *clk_ptr_intclk; + struct clk *clk_ptr_sysclk; + struct clk *clk_ptr_ulpclk; +}; + +static inline const char *get_mclk_str(enum mclk mclk_sel) +{ + switch (mclk_sel) { + case MCLK_SYSCLK: + return "SYSCLK"; + case MCLK_ULPCLK: + return "ULPCLK"; + default: + return "Unknown"; + } +} + +static int mop500_ab8500_set_mclk(struct device *dev, + struct mop500_ab8500_drvdata *drvdata) +{ + int status; + struct clk *clk_ptr; + + if (IS_ERR(drvdata->clk_ptr_intclk)) { + dev_err(dev, + "%s: ERROR: intclk not initialized!\n", __func__); + return -EIO; + } + + switch (drvdata->mclk_sel) { + case MCLK_SYSCLK: + clk_ptr = drvdata->clk_ptr_sysclk; + break; + case MCLK_ULPCLK: + clk_ptr = drvdata->clk_ptr_ulpclk; + break; + default: + return -EINVAL; + } + + if (IS_ERR(clk_ptr)) { + dev_err(dev, "%s: ERROR: %s not initialized!\n", __func__, + get_mclk_str(drvdata->mclk_sel)); + return -EIO; + } + + status = clk_set_parent(drvdata->clk_ptr_intclk, clk_ptr); + if (status) + dev_err(dev, + "%s: ERROR: Setting intclk parent to %s failed (ret = %d)!", + __func__, get_mclk_str(drvdata->mclk_sel), status); + else + dev_dbg(dev, + "%s: intclk parent changed to %s.\n", + __func__, get_mclk_str(drvdata->mclk_sel)); + + return status; +} + +/* + * Control-events + */ + +static int mclk_input_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mop500_ab8500_drvdata *drvdata = + snd_soc_card_get_drvdata(codec->card); + + ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; + + return 0; +} + +static int mclk_input_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mop500_ab8500_drvdata *drvdata = + snd_soc_card_get_drvdata(codec->card); + unsigned int val = ucontrol->value.enumerated.item[0]; + + if (val > (unsigned int)MCLK_ULPCLK) + return -EINVAL; + if (drvdata->mclk_sel == val) + return 0; + + drvdata->mclk_sel = val; + + return 1; +} + +/* + * Controls + */ + +static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { + SOC_ENUM_EXT("Master Clock Select", + soc_enum_mclk, + mclk_input_control_get, mclk_input_control_put), + /* Digital interface - Clocks */ + SOC_SINGLE("Digital Interface Master Generator Switch", + AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN, + 1, 0), + SOC_SINGLE("Digital Interface 0 Bit-clock Switch", + AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0, + 1, 0), + SOC_SINGLE("Digital Interface 1 Bit-clock Switch", + AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1, + 1, 0), + SOC_DAPM_PIN_SWITCH("Headset Left"), + SOC_DAPM_PIN_SWITCH("Headset Right"), + SOC_DAPM_PIN_SWITCH("Earpiece"), + SOC_DAPM_PIN_SWITCH("Speaker Left"), + SOC_DAPM_PIN_SWITCH("Speaker Right"), + SOC_DAPM_PIN_SWITCH("LineOut Left"), + SOC_DAPM_PIN_SWITCH("LineOut Right"), + SOC_DAPM_PIN_SWITCH("Vibra 1"), + SOC_DAPM_PIN_SWITCH("Vibra 2"), + SOC_DAPM_PIN_SWITCH("Mic 1"), + SOC_DAPM_PIN_SWITCH("Mic 2"), + SOC_DAPM_PIN_SWITCH("LineIn Left"), + SOC_DAPM_PIN_SWITCH("LineIn Right"), + SOC_DAPM_PIN_SWITCH("DMic 1"), + SOC_DAPM_PIN_SWITCH("DMic 2"), + SOC_DAPM_PIN_SWITCH("DMic 3"), + SOC_DAPM_PIN_SWITCH("DMic 4"), + SOC_DAPM_PIN_SWITCH("DMic 5"), + SOC_DAPM_PIN_SWITCH("DMic 6"), +}; + +/* ASoC */ + +int mop500_ab8500_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + /* Set audio-clock source */ + return mop500_ab8500_set_mclk(rtd->card->dev, + snd_soc_card_get_drvdata(rtd->card)); +} + +void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->card->dev; + + dev_dbg(dev, "%s: Enter\n", __func__); + + /* Reset slots configuration to default(s) */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + tx_slots = DEF_TX_SLOTS; + else + rx_slots = DEF_RX_SLOTS; +} + +int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct device *dev = rtd->card->dev; + unsigned int fmt; + int channels, ret = 0, driver_mode, slots; + unsigned int sw_codec, sw_cpu; + bool is_playback; + + dev_dbg(dev, "%s: Enter\n", __func__); + + dev_dbg(dev, "%s: substream->pcm->name = %s\n" + "substream->pcm->id = %s.\n" + "substream->name = %s.\n" + "substream->number = %d.\n", + __func__, + substream->pcm->name, + substream->pcm->id, + substream->name, + substream->number); + + channels = params_channels(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S32_LE: + sw_cpu = 32; + break; + + case SNDRV_PCM_FORMAT_S16_LE: + sw_cpu = 16; + break; + + default: + return -EINVAL; + } + + /* Setup codec depending on driver-mode */ + if (channels == 8) + driver_mode = DRIVERMODE_CODEC_ONLY; + else + driver_mode = DRIVERMODE_NORMAL; + dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__, + (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); + + /* Setup format */ + + if (driver_mode == DRIVERMODE_NORMAL) { + fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_CBM_CFM | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CONT; + } else { + fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_CBM_CFM | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_GATED; + } + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(dev, + "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", + __func__, ret); + return ret; + } + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + dev_err(dev, + "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", + __func__, ret); + return ret; + } + + /* Setup TDM-slots */ + + is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + switch (channels) { + case 1: + slots = 16; + tx_slots = (is_playback) ? TX_SLOT_MONO : 0; + rx_slots = (is_playback) ? 0 : RX_SLOT_MONO; + break; + case 2: + slots = 16; + tx_slots = (is_playback) ? TX_SLOT_STEREO : 0; + rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO; + break; + case 8: + slots = 16; + tx_slots = (is_playback) ? TX_SLOT_8CH : 0; + rx_slots = (is_playback) ? 0 : RX_SLOT_8CH; + break; + default: + return -EINVAL; + } + + if (driver_mode == DRIVERMODE_NORMAL) + sw_codec = sw_cpu; + else + sw_codec = 20; + + dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, + tx_slots, rx_slots); + ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, + sw_cpu); + if (ret) + return ret; + + dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, + tx_slots, rx_slots); + ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, + sw_codec); + if (ret) + return ret; + + return 0; +} + +struct snd_soc_ops mop500_ab8500_ops[] = { + { + .hw_params = mop500_ab8500_hw_params, + .startup = mop500_ab8500_startup, + .shutdown = mop500_ab8500_shutdown, + } +}; + +int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct device *dev = rtd->card->dev; + struct mop500_ab8500_drvdata *drvdata; + int ret; + + dev_dbg(dev, "%s Enter.\n", __func__); + + /* Create driver private-data struct */ + drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), + GFP_KERNEL); + snd_soc_card_set_drvdata(rtd->card, drvdata); + + /* Setup clocks */ + + drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk"); + if (IS_ERR(drvdata->clk_ptr_sysclk)) + dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n", + __func__); + drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk"); + if (IS_ERR(drvdata->clk_ptr_ulpclk)) + dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n", + __func__); + drvdata->clk_ptr_intclk = clk_get(dev, "intclk"); + if (IS_ERR(drvdata->clk_ptr_intclk)) + dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n", + __func__); + + /* Set intclk default parent to ulpclk */ + drvdata->mclk_sel = MCLK_ULPCLK; + ret = mop500_ab8500_set_mclk(dev, drvdata); + if (ret < 0) + dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n", + __func__); + + drvdata->mclk_sel = MCLK_ULPCLK; + + /* Add controls */ + ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, + ARRAY_SIZE(mop500_ab8500_ctrls)); + if (ret < 0) { + pr_err("%s: Failed to add machine-controls (%d)!\n", + __func__, ret); + return ret; + } + + ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5"); + ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6"); + + return ret; +} + +void mop500_ab8500_remove(struct snd_soc_card *card) +{ + struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card); + + if (drvdata->clk_ptr_sysclk != NULL) + clk_put(drvdata->clk_ptr_sysclk); + if (drvdata->clk_ptr_ulpclk != NULL) + clk_put(drvdata->clk_ptr_ulpclk); + if (drvdata->clk_ptr_intclk != NULL) + clk_put(drvdata->clk_ptr_intclk); + + snd_soc_card_set_drvdata(card, drvdata); +} diff --git a/sound/soc/ux500/mop500_ab8500.h b/sound/soc/ux500/mop500_ab8500.h new file mode 100644 index 000000000000..cca5b33964b6 --- /dev/null +++ b/sound/soc/ux500/mop500_ab8500.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja + * for ST-Ericsson. + * + * License terms: + * + * 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 MOP500_AB8500_H +#define MOP500_AB8500_H + +extern struct snd_soc_ops mop500_ab8500_ops[]; + +int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *runtime); +void mop500_ab8500_remove(struct snd_soc_card *card); + +#endif -- GitLab From 9f0ed7a7c547efbce2c15b5017744809e9bba23a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 16 Jun 2012 16:19:27 +0300 Subject: [PATCH 0819/5711] ASoC: Ux500: unlock on an error path There is a missing mutex_unlock() here. The cleanup path also has more debug output. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 389dd660b511..3c795921c5f6 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -1235,7 +1235,8 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, req != ANC_APPLY_IIR) { dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", __func__, enum_anc_state[req]); - return -EINVAL; + status = -EINVAL; + goto cleanup; } apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; -- GitLab From aed98048bd1c83469d96932c1901e867d9ba519a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:39 -0700 Subject: [PATCH 0820/5711] irqdomain: Make ops->map hook optional There isn't a really compelling reason to force ->map to be populated, so allow it to be left unset. Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Cc: Paul Mundt Cc: Thomas Gleixner Cc: Rob Herring --- kernel/irq/irqdomain.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index b1f774cfd089..d3968e91bfd2 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -205,7 +205,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, * one can then use irq_create_mapping() to * explicitly change them */ - ops->map(domain, irq, hwirq); + if (ops->map) + ops->map(domain, irq, hwirq); /* Clear norequest flags */ irq_clear_status_flags(irq, IRQ_NOREQUEST); @@ -340,8 +341,8 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, irq_data->hwirq = hwirq; irq_data->domain = domain; - if (domain->ops->map(domain, virq, hwirq)) { - pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); + if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { + pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); irq_data->domain = NULL; irq_data->hwirq = 0; return -1; @@ -763,12 +764,6 @@ static int __init irq_debugfs_init(void) __initcall(irq_debugfs_init); #endif /* CONFIG_IRQ_DOMAIN_DEBUG */ -static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - return 0; -} - /** * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings * @@ -831,7 +826,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell); const struct irq_domain_ops irq_domain_simple_ops = { - .map = irq_domain_simple_map, .xlate = irq_domain_xlate_onetwocell, }; EXPORT_SYMBOL_GPL(irq_domain_simple_ops); -- GitLab From 92311c3c70f9b7f1b7860c2fc2ada09b4d43bfea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 12 Jun 2012 09:46:26 +0800 Subject: [PATCH 0821/5711] pda_power: Complain if regulator operations fail Rather than silently ignoring errors from the regulator enable and disable add a WARN_ON() - it's probably pretty important if we're not getting power, though it should be vanishingly unlikely in production. Signed-off-by: Mark Brown Signed-off-by: Anton Vorontsov --- drivers/power/pda_power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 214468f4444a..ed54a3551148 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -134,13 +134,13 @@ static void update_charger(void) regulator_set_current_limit(ac_draw, max_uA, max_uA); if (!regulator_enabled) { dev_dbg(dev, "charger on (AC)\n"); - regulator_enable(ac_draw); + WARN_ON(regulator_enable(ac_draw)); regulator_enabled = 1; } } else { if (regulator_enabled) { dev_dbg(dev, "charger off\n"); - regulator_disable(ac_draw); + WARN_ON(regulator_disable(ac_draw)); regulator_enabled = 0; } } -- GitLab From 7dbae5562e86f2731d13bd2b8b3ea3f974f4b87d Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 17 Jun 2012 21:20:05 -0700 Subject: [PATCH 0822/5711] ds2781_battery: w1_ds2781_read() should be static This patch fixes the following sparse warning: CHECK drivers/power/ds2781_battery.c drivers/power/ds2781_battery.c:72:5: warning: symbol 'w1_ds2781_read' was not declared. Should it be static? Signed-off-by: Anton Vorontsov --- drivers/power/ds2781_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c index 975684a40f15..0e87e54b4ab1 100644 --- a/drivers/power/ds2781_battery.c +++ b/drivers/power/ds2781_battery.c @@ -69,7 +69,7 @@ static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); } -int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, +static int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, int addr, size_t count) { return ds2781_battery_io(dev_info, buf, addr, count, 0); -- GitLab From 3be330bf8860dc6079da5acc81295787a04cf4c9 Mon Sep 17 00:00:00 2001 From: Jenny TC Date: Wed, 9 May 2012 20:36:47 +0530 Subject: [PATCH 0823/5711] power_supply: Register battery as a thermal zone Battery and charger contribute to Thermals in most of the embedded devices. So, it makes sense to identify them as Thermal zones in a particular platform. This patch registers a thermal zone if the power supply is reporting a temperature property. The thermal zone will be used by platform's thermal management solution. Signed-off-by: Jenny TC Signed-off-by: Anton Vorontsov --- drivers/power/power_supply_core.c | 65 +++++++++++++++++++++++++++++++ include/linux/power_supply.h | 3 ++ 2 files changed, 68 insertions(+) diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 6ad612726785..ff990d26a0c0 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "power_supply.h" /* exported for the APM Power driver, APM emulation */ @@ -169,6 +170,63 @@ static void power_supply_dev_release(struct device *dev) kfree(dev); } +#ifdef CONFIG_THERMAL +static int power_supply_read_temp(struct thermal_zone_device *tzd, + unsigned long *temp) +{ + struct power_supply *psy; + union power_supply_propval val; + int ret; + + WARN_ON(tzd == NULL); + psy = tzd->devdata; + ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); + + /* Convert tenths of degree Celsius to milli degree Celsius. */ + if (!ret) + *temp = val.intval * 100; + + return ret; +} + +static struct thermal_zone_device_ops psy_tzd_ops = { + .get_temp = power_supply_read_temp, +}; + +static int psy_register_thermal(struct power_supply *psy) +{ + int i; + + /* Register battery zone device psy reports temperature */ + for (i = 0; i < psy->num_properties; i++) { + if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { + psy->tzd = thermal_zone_device_register(psy->name, 0, + psy, &psy_tzd_ops, 0, 0, 0, 0); + if (IS_ERR(psy->tzd)) + return PTR_ERR(psy->tzd); + break; + } + } + return 0; +} + +static void psy_unregister_thermal(struct power_supply *psy) +{ + if (IS_ERR_OR_NULL(psy->tzd)) + return; + thermal_zone_device_unregister(psy->tzd); +} +#else +static int psy_register_thermal(struct power_supply *psy) +{ + return 0; +} + +static void psy_unregister_thermal(struct power_supply *psy) +{ +} +#endif + int power_supply_register(struct device *parent, struct power_supply *psy) { struct device *dev; @@ -197,6 +255,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy) if (rc) goto device_add_failed; + rc = psy_register_thermal(psy); + if (rc) + goto register_thermal_failed; + rc = power_supply_create_triggers(psy); if (rc) goto create_triggers_failed; @@ -206,6 +268,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) goto success; create_triggers_failed: + psy_unregister_thermal(psy); +register_thermal_failed: device_del(dev); kobject_set_name_failed: device_add_failed: @@ -220,6 +284,7 @@ void power_supply_unregister(struct power_supply *psy) cancel_work_sync(&psy->changed_work); sysfs_remove_link(&psy->dev->kobj, "powers"); power_supply_remove_triggers(psy); + psy_unregister_thermal(psy); device_unregister(psy->dev); } EXPORT_SYMBOL_GPL(power_supply_unregister); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 3b912bee28d1..59ed2dd9dba9 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -173,6 +173,9 @@ struct power_supply { /* private */ struct device *dev; struct work_struct changed_work; +#ifdef CONFIG_THERMAL + struct thermal_zone_device *tzd; +#endif #ifdef CONFIG_LEDS_TRIGGERS struct led_trigger *charging_full_trig; -- GitLab From 4be77a530be1ea62574f31c20dd9848e7e2ab0f6 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Fri, 15 Jun 2012 16:35:28 +0100 Subject: [PATCH 0824/5711] ALSA: pcm: Add snd_pcm_rate_bit_to_rate() This is essentially the reverse of snd_pcm_rate_to_rate_bit(). This is generally useful as the Compress API uses the rate bit directly and it helps to be able to map back to the actual sample rate. Signed-off-by: Dimitris Papastamos Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 1 + sound/core/pcm_misc.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 0d1112815be3..68372bc1e11b 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -893,6 +893,7 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); +unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, struct snd_dma_buffer *bufp) diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 9c9eff9afbac..d4fc1bfbe457 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -488,3 +488,21 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) return SNDRV_PCM_RATE_KNOT; } EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); + +/** + * snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate + * @rate_bit: the rate bit to convert + * + * Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag + * or 0 for an unknown rate bit + */ +unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit) +{ + unsigned int i; + + for (i = 0; i < snd_pcm_known_rates.count; i++) + if ((1u << i) == rate_bit) + return snd_pcm_known_rates.list[i]; + return 0; +} +EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate); -- GitLab From 10a3061accd897c9e4e3821cbd501660ac482497 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 15 Jun 2012 20:55:54 +0200 Subject: [PATCH 0825/5711] ALSA: snd-opti9xx: fixes for MED3931 card (opti931) MED3931 card did not work (failed with "OPTI chip not found") because snd-opti9xx gets mc_indir_index from pnp by adding 2 to the pnp-reported port. It probably works for some cards but not for this one. Datasheet says that the port is always at 0xe?e so just force the lowest nibble to be 0xe. Also this card powers up with (ugly) 3D sound enabled. As there's no mixer control for this, just disable it. Signed-off-by: Ondrej Zary Signed-off-by: Takashi Iwai --- sound/isa/opti9xx/opti92x-ad1848.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index d7ccf28bd66a..ecc68dfe7b54 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -135,7 +135,6 @@ struct snd_opti9xx { unsigned long mc_base_size; #ifdef OPTi93X unsigned long mc_indir_index; - unsigned long mc_indir_size; struct resource *res_mc_indir; struct snd_wss *codec; #endif /* OPTi93X */ @@ -245,10 +244,8 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, case OPTi9XX_HW_82C931: case OPTi9XX_HW_82C933: chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; - if (!chip->mc_indir_index) { + if (!chip->mc_indir_index) chip->mc_indir_index = 0xe0e; - chip->mc_indir_size = 2; - } chip->password = 0xe4; chip->pwd_reg = 0; break; @@ -403,7 +400,9 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, #else /* OPTi93X */ case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: + /* disable 3D sound (set GPIO1 as output, low) */ + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); + case OPTi9XX_HW_82C933: /* FALL THROUGH */ /* * The BTC 1817DW has QS1000 wavetable which is connected * to the serial digital input of the OPTI931. @@ -696,8 +695,7 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) return 0; #else /* OPTi93X */ - chip->res_mc_indir = request_region(chip->mc_indir_index, - chip->mc_indir_size, + chip->res_mc_indir = request_region(chip->mc_indir_index, 2, "OPTi93x MC"); if (chip->res_mc_indir == NULL) return -EBUSY; @@ -770,8 +768,9 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, #ifdef OPTi93X port = pnp_port_start(pdev, 0) - 4; fm_port = pnp_port_start(pdev, 1) + 8; - chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; - chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; + /* adjust mc_indir_index - some cards report it at 0xe?d, + other at 0xe?c but it really is always at 0xe?e */ + chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe; #else devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); if (devmc == NULL) -- GitLab From 39fb50f6178d7dbd70142b25193d722ebf3f8193 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Fri, 8 Jun 2012 16:43:19 -0300 Subject: [PATCH 0826/5711] drm/i915: properly wait for SBI status Somehow this went unnoticed in the past reviews, but the condition would never timeout properly. This was initially introduced in the v2 of original SBI enabling patch. Highly embarrassing. Note that we now actually time out for the read, which resulted in gcc complaining that we can now return unitialized garbage if that happens. There's not much we can do here because there's not much point in thread -EIO all the way down through these functions. Hence simply shut up the compiler. Reported-by: Dan Carpenter Signed-off-by: Eugeni Dodonov [danvet: Added note and squashed uninitialized value shut-up into this patch.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 308e1a2967e7..97301621f48a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1350,7 +1350,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) unsigned long flags; spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to become ready\n"); goto out_unlock; @@ -1364,7 +1364,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) SBI_BUSY | SBI_CTL_OP_CRWR); - if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); goto out_unlock; @@ -1378,10 +1378,10 @@ static u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) { unsigned long flags; - u32 value; + u32 value = 0; spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to become ready\n"); goto out_unlock; @@ -1393,7 +1393,7 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) SBI_BUSY | SBI_CTL_OP_CRRD); - if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); goto out_unlock; -- GitLab From e158c5aa1776372cd751e2c395300a3a6ff0bc9c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sun, 17 Jun 2012 09:37:24 -0700 Subject: [PATCH 0827/5711] drm/i915: disable contexts on old HW This got dropped as a result of the last round of comments. I didn't test it on unsupported HW (which this is likely the case). Note that this prevents hw context from blowing up on any pre-gen6 hw. Signed-off-by: Ben Widawsky Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51142 [danvet: Added note and buglink.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6dc426a48b2d..8fb8cd8f6320 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -243,8 +243,10 @@ void i915_gem_context_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; uint32_t ctx_size; - if (!HAS_HW_CONTEXTS(dev)) + if (!HAS_HW_CONTEXTS(dev)) { + dev_priv->hw_contexts_disabled = true; return; + } /* If called from reset, or thaw... we've been here already */ if (dev_priv->hw_contexts_disabled || -- GitLab From 208482232de3590cee4757dfabe5d8cee8c6e626 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 4 May 2012 18:58:59 -0700 Subject: [PATCH 0828/5711] drm/i915: set IDICOS to medium uncore resources I'm seeing about a 5% FPS improvement across various benchmarks on my IVB i3. Rumor has it that the higher end parts show even more benefit. This derives from a patch originally given to me by Bernard. The docs are confusing about the definition names (ie. medium really seems like max), but it would seem it gives more cache to the GT at the expense of uncore. This configuration makes the split most in favor of the GT. I've not tried the other IDICOS values. Cc: "Kilarski, Bernard R" Acked-by: Eric Anholt Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b7de5ea62aa4..404b474eaea3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3384,6 +3384,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + uint32_t snpcr; I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); @@ -3429,6 +3430,11 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) /* WaDisable4x2SubspanOptimization */ I915_WRITE(CACHE_MODE_1, _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); + + snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); + snpcr &= ~GEN6_MBC_SNPCR_MASK; + snpcr |= GEN6_MBC_SNPCR_MED; + I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); } static void valleyview_init_clock_gating(struct drm_device *dev) -- GitLab From e080b915ecea3fff3e0d8d380a221677add419a5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 16 Jun 2012 18:29:44 +0200 Subject: [PATCH 0829/5711] drm/i915: fixup hangman rebase goof-up I've added a bit of logic such that running the hangman test on chips without any hw reset support at all doesn't wedge the gpu because the reset failed. This relied on checking for non-null stop_rings. Unfortunately I've botched a rebase somewhere and stop_rings is still cleared at the old place before the reset code. Fix this up so that running the i-g-t tests on gen2/3 doesn't result in a wedged gpu. v2: Actually remove the lines instead of adding them twice ... my git license should be revoked immediately. Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f0bd30ab1551..e41aadef9937 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -860,8 +860,6 @@ int i915_reset(struct drm_device *dev) if (!mutex_trylock(&dev->struct_mutex)) return -EBUSY; - dev_priv->stop_rings = 0; - i915_gem_reset(dev); ret = -ENODEV; -- GitLab From fc3f906bce236bcf414285dca46550a73e2eaec8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 24 May 2012 07:29:41 -0300 Subject: [PATCH 0830/5711] [media] gspca: Maintainer change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hans de Goede accepted to be the new gspca maintainer. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f175f444cb55..aaa63da72ab6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3061,8 +3061,7 @@ S: Maintained F: drivers/media/video/gspca/t613.c GSPCA USB WEBCAM DRIVER -M: Jean-Francois Moine -W: http://moinejf.free.fr +M: Hans de Goede L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git S: Maintained -- GitLab From 50fbe32cf41a8309ed8016eb6f81232acfa23ae7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 May 2012 11:56:41 -0300 Subject: [PATCH 0831/5711] [media] videobuf-dma-contig: use gfp_t for GFP flags Sparse complains if about using unsigned long. videobuf-dma-contig.c:47:67: warning: restricted gfp_t degrades to integer videobuf-dma-contig.c:47:65: warning: incorrect type in argument 2 (different base types) videobuf-dma-contig.c:47:65: expected restricted gfp_t [usertype] gfp_mask videobuf-dma-contig.c:47:65: got unsigned long Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-contig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index b6b5cc1a43cb..9b9a06fdd0f0 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -40,7 +40,7 @@ struct videobuf_dma_contig_memory { static int __videobuf_dc_alloc(struct device *dev, struct videobuf_dma_contig_memory *mem, - unsigned long size, unsigned long flags) + unsigned long size, gfp_t flags) { mem->size = size; if (mem->cached) { -- GitLab From e0815f35ccd276a903298ad4c3d8d10b65933b86 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 11 Jun 2012 16:58:49 -0300 Subject: [PATCH 0832/5711] ALSA: maestro3: Remove unused AC97 register definitions Signed-off-by: Ezequiel Garcia Signed-off-by: Takashi Iwai --- sound/pci/maestro3.c | 68 -------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index deef21399586..adb3b4c7917e 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -361,74 +361,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); #define DSP2HOST_REQ_I2SRATE 0x02 #define DSP2HOST_REQ_TIMER 0x04 -/* AC97 registers */ -/* XXX fix this crap up */ -/*#define AC97_RESET 0x00*/ - -#define AC97_VOL_MUTE_B 0x8000 -#define AC97_VOL_M 0x1F -#define AC97_LEFT_VOL_S 8 - -#define AC97_MASTER_VOL 0x02 -#define AC97_LINE_LEVEL_VOL 0x04 -#define AC97_MASTER_MONO_VOL 0x06 -#define AC97_PC_BEEP_VOL 0x0A -#define AC97_PC_BEEP_VOL_M 0x0F -#define AC97_SROUND_MASTER_VOL 0x38 -#define AC97_PC_BEEP_VOL_S 1 - -/*#define AC97_PHONE_VOL 0x0C -#define AC97_MIC_VOL 0x0E*/ -#define AC97_MIC_20DB_ENABLE 0x40 - -/*#define AC97_LINEIN_VOL 0x10 -#define AC97_CD_VOL 0x12 -#define AC97_VIDEO_VOL 0x14 -#define AC97_AUX_VOL 0x16*/ -#define AC97_PCM_OUT_VOL 0x18 -/*#define AC97_RECORD_SELECT 0x1A*/ -#define AC97_RECORD_MIC 0x00 -#define AC97_RECORD_CD 0x01 -#define AC97_RECORD_VIDEO 0x02 -#define AC97_RECORD_AUX 0x03 -#define AC97_RECORD_MONO_MUX 0x02 -#define AC97_RECORD_DIGITAL 0x03 -#define AC97_RECORD_LINE 0x04 -#define AC97_RECORD_STEREO 0x05 -#define AC97_RECORD_MONO 0x06 -#define AC97_RECORD_PHONE 0x07 - -/*#define AC97_RECORD_GAIN 0x1C*/ -#define AC97_RECORD_VOL_M 0x0F - -/*#define AC97_GENERAL_PURPOSE 0x20*/ -#define AC97_POWER_DOWN_CTRL 0x26 -#define AC97_ADC_READY 0x0001 -#define AC97_DAC_READY 0x0002 -#define AC97_ANALOG_READY 0x0004 -#define AC97_VREF_ON 0x0008 -#define AC97_PR0 0x0100 -#define AC97_PR1 0x0200 -#define AC97_PR2 0x0400 -#define AC97_PR3 0x0800 -#define AC97_PR4 0x1000 - -#define AC97_RESERVED1 0x28 - -#define AC97_VENDOR_TEST 0x5A - -#define AC97_CLOCK_DELAY 0x5C -#define AC97_LINEOUT_MUX_SEL 0x0001 -#define AC97_MONO_MUX_SEL 0x0002 -#define AC97_CLOCK_DELAY_SEL 0x1F -#define AC97_DAC_CDS_SHIFT 6 -#define AC97_ADC_CDS_SHIFT 11 - -#define AC97_MULTI_CHANNEL_SEL 0x74 - -/*#define AC97_VENDOR_ID1 0x7C -#define AC97_VENDOR_ID2 0x7E*/ - /* * ASSP control regs */ -- GitLab From 7e566be25895e55aaea4dd0c453f2a3b6919cfb6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 26 May 2012 11:11:54 -0300 Subject: [PATCH 0833/5711] [media] s5p-fimc: Add missing static storage class specifiers Fixes the following sparse warnings: drivers/media/video/s5p-fimc/fimc-lite-reg.c:218:6: warning: symbol 'flite_hw_set_out_order' was not declared. Should it be static? drivers/media/video/s5p-fimc/fimc-mdevice.c:183:5: warning: symbol '__fimc_pipeline_shutdown' was not declared. Should it be static? drivers/media/video/s5p-fimc/fimc-mdevice.c:1013:12: warning: symbol 'fimc_md_init' was not declared. Should it be static? drivers/media/video/s5p-fimc/fimc-mdevice.c:1024:13: warning: symbol 'fimc_md_exit' was not declared. Should it be static? drivers/media/video/s5p-fimc/fimc-core.c:466:5: warning: symbol 'fimc_set_color_effect' was not declared. Should it be static? drivers/media/video/s5p-fimc/fimc-capture.c:1163:5: warning: symbol 'enclosed_rectangle' was not declared. Should it be static? Signed-off-by: Sachin Kamat Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 2 +- drivers/media/video/s5p-fimc/fimc-core.c | 2 +- drivers/media/video/s5p-fimc/fimc-lite-reg.c | 2 +- drivers/media/video/s5p-fimc/fimc-mdevice.c | 7 ++++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 354574591908..62ce5399c4cf 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -1161,7 +1161,7 @@ static int fimc_cap_g_selection(struct file *file, void *fh, } /* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ -int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) +static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) { if (a->left < b->left || a->top < b->top) return 0; diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index fedcd561ba27..1628c0dbb163 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -463,7 +463,7 @@ void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v); } -int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx) +static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx) { struct fimc_effect *effect = &ctx->effect; diff --git a/drivers/media/video/s5p-fimc/fimc-lite-reg.c b/drivers/media/video/s5p-fimc/fimc-lite-reg.c index 419adfb7cdf9..f996e94873f6 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-lite-reg.c @@ -215,7 +215,7 @@ void flite_hw_set_camera_bus(struct fimc_lite *dev, flite_hw_set_camera_port(dev, s_info->mux_id); } -void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) +static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) { static const u32 pixcode[4][2] = { { V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR }, diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 6753c45631b8..7c5c739dd2f1 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -180,7 +180,7 @@ EXPORT_SYMBOL_GPL(fimc_pipeline_initialize); * sensor clock. * Called with the graph mutex held. */ -int __fimc_pipeline_shutdown(struct fimc_pipeline *p) +static int __fimc_pipeline_shutdown(struct fimc_pipeline *p) { int ret = 0; @@ -1010,7 +1010,7 @@ static struct platform_driver fimc_md_driver = { } }; -int __init fimc_md_init(void) +static int __init fimc_md_init(void) { int ret; @@ -1021,7 +1021,8 @@ int __init fimc_md_init(void) return platform_driver_register(&fimc_md_driver); } -void __exit fimc_md_exit(void) + +static void __exit fimc_md_exit(void) { platform_driver_unregister(&fimc_md_driver); fimc_unregister_driver(); -- GitLab From 0f846f81a154cc1818416918d22939bda73da194 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jun 2012 11:04:47 -0700 Subject: [PATCH 0834/5711] drm/i915: disable RCBP and VDS unit clock gating on SNB and VLV The RCBP workaround still applies on these chips, and we need VDS as well. v2: remove MB boot fetch that snuck in (Daniel) add workaround tags to comments for easier internal tracking (Daniel) v3: only apply RCPB and VDS on SNB and VLV, IVB doesn't need them (Eugeni) References: https://bugs.freedesktop.org/show_bug.cgi?id=50251 Signed-off-by: Jesse Barnes Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 54 +++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 60562f0c7018..e748f665a0d9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4037,6 +4037,7 @@ # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) #define GEN6_UCGCTL2 0x9404 +# define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 404b474eaea3..54c5e53dd415 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3330,8 +3330,12 @@ static void gen6_init_clock_gating(struct drm_device *dev) * * According to the spec, bit 11 (RCCUNIT) must also be set, * but we didn't debug actual testcases to find it out. + * + * Also apply WaDisableVDSUnitClockGating and + * WaDisableRCPBUnitClockGating. */ I915_WRITE(GEN6_UCGCTL2, + GEN7_VDSUNIT_CLOCK_GATE_DISABLE | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); @@ -3392,11 +3396,6 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); - /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. - * This implements the WaDisableRCZUnitClockGating workaround. - */ - I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); I915_WRITE(IVB_CHICKEN3, @@ -3413,6 +3412,23 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after + * some amount of runtime in the Mesa "fire" demo, and Unigine + * Sanctuary and Tropics, and apparently anything else with + * alpha test or pixel discard. + * + * According to the spec, bit 11 (RCCUNIT) must also be set, + * but we didn't debug actual testcases to find it out. + * + * According to the spec, bit 13 (RCZUNIT) must be set on IVB. + * This implements the WaDisableRCZUnitClockGating workaround. + */ + I915_WRITE(GEN6_UCGCTL2, + GEN6_RCZUNIT_CLOCK_GATE_DISABLE | + GEN6_RCCUNIT_CLOCK_GATE_DISABLE); + /* This is required by WaCatErrorRejectionIssue */ I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | @@ -3449,11 +3465,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); - /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. - * This implements the WaDisableRCZUnitClockGating workaround. - */ - I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); I915_WRITE(IVB_CHICKEN3, @@ -3473,6 +3484,29 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after + * some amount of runtime in the Mesa "fire" demo, and Unigine + * Sanctuary and Tropics, and apparently anything else with + * alpha test or pixel discard. + * + * According to the spec, bit 11 (RCCUNIT) must also be set, + * but we didn't debug actual testcases to find it out. + * + * According to the spec, bit 13 (RCZUNIT) must be set on IVB. + * This implements the WaDisableRCZUnitClockGating workaround. + * + * Also apply WaDisableVDSUnitClockGating and + * WaDisableRCPBUnitClockGating. + */ + I915_WRITE(GEN6_UCGCTL2, + GEN7_VDSUNIT_CLOCK_GATE_DISABLE | + GEN6_RCZUNIT_CLOCK_GATE_DISABLE | + GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | + GEN6_RCCUNIT_CLOCK_GATE_DISABLE); + for_each_pipe(pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | -- GitLab From b4ae3f22d238617ca11610b29fde16cf8c0bc6e0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jun 2012 11:04:48 -0700 Subject: [PATCH 0835/5711] drm/i915: load boot context at driver init time According to the bspec for MBCTL: Driver must set bit in the following scenarios: - to realod teh h/w boot context every time it gets loaded through OS - after an FLR clears the register (BIOS won't run afterwards) References: https://bugs.freedesktop.org/show_bug.cgi?id=50237 Signed-off-by: Jesse Barnes Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 54c5e53dd415..83c0e226f50c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3363,6 +3363,9 @@ static void gen6_init_clock_gating(struct drm_device *dev) ILK_DPARB_CLK_GATE | ILK_DPFD_CLK_GATE); + I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | + GEN6_MBCTL_ENABLE_BOOT_FETCH); + for_each_pipe(pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | @@ -3441,6 +3444,9 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) intel_flush_display_plane(dev_priv, pipe); } + I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | + GEN6_MBCTL_ENABLE_BOOT_FETCH); + gen7_setup_fixed_func_scheduler(dev_priv); /* WaDisable4x2SubspanOptimization */ @@ -3484,6 +3490,9 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | + GEN6_MBCTL_ENABLE_BOOT_FETCH); + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock * gating disable must be set. Failure to set it results in -- GitLab From 6edaa7fcf287b92fb231a9e23cd6b5b0fc3dddb2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jun 2012 11:04:49 -0700 Subject: [PATCH 0836/5711] drm/i915: add TDL unit clock gating disable for VLV Another required workaround for a potential hang: WaDisableTDLUnitClockGating. v2: only apply this to VLV, IVB doesn't need it anymore (Eugeni) References: https://bugs.freedesktop.org/show_bug.cgi?id=50245 Signed-off-by: Jesse Barnes Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e748f665a0d9..5d7cf5f7e750 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4038,6 +4038,7 @@ #define GEN6_UCGCTL2 0x9404 # define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) +# define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 83c0e226f50c..47c1a3e9b4af 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3512,6 +3512,7 @@ static void valleyview_init_clock_gating(struct drm_device *dev) */ I915_WRITE(GEN6_UCGCTL2, GEN7_VDSUNIT_CLOCK_GATE_DISABLE | + GEN7_TDLUNIT_CLOCK_GATE_DISABLE | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); -- GitLab From e3f33d46fd917747e966f8e6d25f2940223ad1ee Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jun 2012 11:04:50 -0700 Subject: [PATCH 0837/5711] drm/i915: add L3 bank clock gating disable on VLV Prevents a possible hang: WaDisableL3Bank2xClockGate. v2: only apply to VLV, IVB doesn't need this anymore References: https://bugs.freedesktop.org/show_bug.cgi?id=50245 Signed-off-by: Jesse Barnes Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_pm.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5d7cf5f7e750..782e5d1dc218 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4043,6 +4043,9 @@ # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) +#define GEN7_UCGCTL4 0x940c +#define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) + #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) #define GEN6_FREQUENCY(x) ((x)<<25) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 47c1a3e9b4af..17c16f026244 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3517,6 +3517,8 @@ static void valleyview_init_clock_gating(struct drm_device *dev) GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); + for_each_pipe(pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | -- GitLab From de509f9f08726077ffd2f2d5e4b63e17cb516938 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 7 Jun 2012 10:30:59 +0200 Subject: [PATCH 0838/5711] PCI: add Chelsio T310 10GbE NIC broken INTx masking quirk According to http://thread.gmane.org/gmane.comp.emulators.kvm.devel/91388 the T310 does not properly support INTx masking as it fails to keep the PCI_STATUS_INTERRUPT bit updated once the interrupt is masked. Mark this adapter as broken so that pci_intx_mask_supported won't report it as compatible. [bhelgaas: use HEADER, not FINAL, which is currently broken for hotplug] Tested-by: Alexey Kardashevskiy Signed-off-by: Jan Kiszka Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index cc13415416d7..b2b66d21105f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2938,6 +2938,8 @@ static void __devinit quirk_broken_intx_masking(struct pci_dev *dev) { dev->broken_intx_masking = 1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030, + quirk_broken_intx_masking); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) -- GitLab From 0bdb3b213ac64f9a16e59d57660174543eaa01f0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 7 Jun 2012 11:01:59 -0600 Subject: [PATCH 0839/5711] PCI: add Ralink RT2800 broken INTx masking quirk Passes pci_intx_mask_supported test but continues to send interrupts as discovered through VFIO-based device assignment. http://www.spinics.net/lists/kvm/msg73738.html [bhelgaas: use HEADER, not FINAL, which is currently broken for hotplug] Tested-by: Andreas Hartmann Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b2b66d21105f..2bbea6428d2e 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2940,6 +2940,8 @@ static void __devinit quirk_broken_intx_masking(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030, quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */ + quirk_broken_intx_masking); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) -- GitLab From 4a62817095696b9831721485bb5c607eba86633f Mon Sep 17 00:00:00 2001 From: volokh Date: Thu, 31 May 2012 03:08:51 -0300 Subject: [PATCH 0840/5711] [media] media: video: bt8xx: Remove duplicated pixel format entry Signed-off-by: Volokh Konstantin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a9cfb0f4be48..4e2f96f0e463 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -557,12 +557,6 @@ static const struct bttv_format formats[] = { .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .btformat = BT848_COLOR_FMT_YUY2, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, -- GitLab From fdaaee6c4a63e364b7f9c8bfdb218e6aaa65f1cf Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 2 Jun 2012 11:04:17 -0300 Subject: [PATCH 0841/5711] [media] DVB: stb0899: speed up getting BER values stb0899_read_ber() takes 500ms (half a second!) to deliver the current BER value. Apparently it takes 5 subsequent readings, with a 100ms pause between them (and even before the first one). This is a real performance brake if an application freqeuently reads the BER of several devices. The attached patch reduces this to a single reading, with no more pausing. I didn't observe any negative side effects of this change. Signed-off-by: Klaus Schmidinger Cc: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 8b0dc74a3298..5d7f8a9b451b 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -1129,7 +1129,6 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber) struct stb0899_internal *internal = &state->internal; u8 lsb, msb; - u32 i; *ber = 0; @@ -1137,14 +1136,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber) case SYS_DVBS: case SYS_DSS: if (internal->lock) { - /* average 5 BER values */ - for (i = 0; i < 5; i++) { - msleep(100); - lsb = stb0899_read_reg(state, STB0899_ECNT1L); - msb = stb0899_read_reg(state, STB0899_ECNT1M); - *ber += MAKEWORD16(msb, lsb); - } - *ber /= 5; + lsb = stb0899_read_reg(state, STB0899_ECNT1L); + msb = stb0899_read_reg(state, STB0899_ECNT1M); + *ber = MAKEWORD16(msb, lsb); /* Viterbi Check */ if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) { /* Error Rate */ @@ -1157,13 +1151,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber) break; case SYS_DVBS2: if (internal->lock) { - /* Average 5 PER values */ - for (i = 0; i < 5; i++) { - msleep(100); - lsb = stb0899_read_reg(state, STB0899_ECNT1L); - msb = stb0899_read_reg(state, STB0899_ECNT1M); - *ber += MAKEWORD16(msb, lsb); - } + lsb = stb0899_read_reg(state, STB0899_ECNT1L); + msb = stb0899_read_reg(state, STB0899_ECNT1M); + *ber = MAKEWORD16(msb, lsb); /* ber = ber * 10 ^ 7 */ *ber *= 10000000; *ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl)))); -- GitLab From 4b71ca6bce8fab3d08c61bf330e781f957934ae1 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 4 Jun 2012 13:05:24 -0300 Subject: [PATCH 0842/5711] [media] lirc_sir: make device registration work For one, the driver device pointer needs to be filled in, or the lirc core will refuse to load the driver. And we really need to wire up all the platform_device bits. This has been tested via the lirc sourceforge tree and verified to work, been sitting there for months, finally getting around to sending it. :\ CC: Josh Boyer Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_sir.c | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c index 945d9623550b..4afc3b419738 100644 --- a/drivers/staging/media/lirc/lirc_sir.c +++ b/drivers/staging/media/lirc/lirc_sir.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef LIRC_ON_SA1100 #include #ifdef CONFIG_SA1100_COLLIE @@ -487,9 +488,11 @@ static struct lirc_driver driver = { .owner = THIS_MODULE, }; +static struct platform_device *lirc_sir_dev; static int init_chrdev(void) { + driver.dev = &lirc_sir_dev->dev; driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); @@ -1215,20 +1218,71 @@ static int init_lirc_sir(void) return 0; } +static int __devinit lirc_sir_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_sir_remove(struct platform_device *dev) +{ + return 0; +} + +static struct platform_driver lirc_sir_driver = { + .probe = lirc_sir_probe, + .remove = __devexit_p(lirc_sir_remove), + .driver = { + .name = "lirc_sir", + .owner = THIS_MODULE, + }, +}; static int __init lirc_sir_init(void) { int retval; + retval = platform_driver_register(&lirc_sir_driver); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register " + "failed!\n"); + return -ENODEV; + } + + lirc_sir_dev = platform_device_alloc("lirc_dev", 0); + if (!lirc_sir_dev) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc " + "failed!\n"); + retval = -ENOMEM; + goto pdev_alloc_fail; + } + + retval = platform_device_add(lirc_sir_dev); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add " + "failed!\n"); + retval = -ENODEV; + goto pdev_add_fail; + } + retval = init_chrdev(); if (retval < 0) - return retval; + goto fail; + retval = init_lirc_sir(); if (retval) { drop_chrdev(); - return retval; + goto fail; } + return 0; + +fail: + platform_device_del(lirc_sir_dev); +pdev_add_fail: + platform_device_put(lirc_sir_dev); +pdev_alloc_fail: + platform_driver_unregister(&lirc_sir_driver); + return retval; } static void __exit lirc_sir_exit(void) @@ -1236,6 +1290,8 @@ static void __exit lirc_sir_exit(void) drop_hardware(); drop_chrdev(); drop_port(); + platform_device_unregister(lirc_sir_dev); + platform_driver_unregister(&lirc_sir_driver); printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); } -- GitLab From fec1868e23099023bc545e199b78d99840b1abc9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 18 Jun 2012 15:38:22 -0700 Subject: [PATCH 0843/5711] USB: properly pad out usb_device_id.driver_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some systems, struct usb_device_id doesn't align properly due to the recent changes in it. So pad out the driver_info field to align on a boundry that systems can handle it. Reported-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Cc: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- include/linux/mod_devicetable.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 7771d453e5f3..6955045199b0 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -122,7 +122,8 @@ struct usb_device_id { __u8 bInterfaceNumber; /* not matched against */ - kernel_ulong_t driver_info; + kernel_ulong_t driver_info + __attribute__((aligned(sizeof(kernel_ulong_t)))); }; /* Some useful macros to use to create struct usb_device_id */ -- GitLab From 86b0905516460b87542686248690337e1d703544 Mon Sep 17 00:00:00 2001 From: Albert Wang Date: Thu, 7 Jun 2012 05:42:24 -0300 Subject: [PATCH 0844/5711] [media] videobuf2: correct the #ifndef text mistake in videobuf2-dma-contig.h It should be a mistake due to copy & paste in header file Correct it in videobuf2-dma-config.h for avoiding duplicate include it Change-Id: I1f71fcec2889c033c7db380c58d9a1369c5afb35 Signed-off-by: Albert Wang Signed-off-by: Mauro Carvalho Chehab --- include/media/videobuf2-dma-contig.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h index 19ae1e350567..8197f87d6c61 100644 --- a/include/media/videobuf2-dma-contig.h +++ b/include/media/videobuf2-dma-contig.h @@ -1,5 +1,5 @@ /* - * videobuf2-dma-coherent.h - DMA coherent memory allocator for videobuf2 + * videobuf2-dma-contig.h - DMA contig memory allocator for videobuf2 * * Copyright (C) 2010 Samsung Electronics * @@ -10,8 +10,8 @@ * the Free Software Foundation. */ -#ifndef _MEDIA_VIDEOBUF2_DMA_COHERENT_H -#define _MEDIA_VIDEOBUF2_DMA_COHERENT_H +#ifndef _MEDIA_VIDEOBUF2_DMA_CONTIG_H +#define _MEDIA_VIDEOBUF2_DMA_CONTIG_H #include #include -- GitLab From 19f5a0c78573ed920a7f68de4a92603fdefa2ab6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jun 2012 03:47:32 -0300 Subject: [PATCH 0845/5711] [media] staging: solo6x10: fix | vs & The test here is never true because '&' was used instead of '|'. It was the same as: if (status & ((1<<16) & (1<<17)) ... Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/solo6x10/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/solo6x10/i2c.c b/drivers/staging/media/solo6x10/i2c.c index ef95a500b4da..398070a3d293 100644 --- a/drivers/staging/media/solo6x10/i2c.c +++ b/drivers/staging/media/solo6x10/i2c.c @@ -175,7 +175,7 @@ int solo_i2c_isr(struct solo_dev *solo_dev) solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_IIC); - if (status & (SOLO_IIC_STATE_TRNS & SOLO_IIC_STATE_SIG_ERR) || + if (status & (SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR) || solo_dev->i2c_id < 0) { solo_i2c_stop(solo_dev); return -ENXIO; -- GitLab From 87edb566ae883f09007e44969e9d4c9c9652a918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Sat, 9 Jun 2012 04:24:42 -0300 Subject: [PATCH 0846/5711] [media] em28xx: Make em28xx_ir_change_protocol a static function Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index fce5f7680c99..d2932f23638f 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc) cancel_delayed_work_sync(&ir->work); } -int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) +static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) { int rc = 0; struct em28xx_IR *ir = rc_dev->priv; -- GitLab From cb4f6818f8534280954f6e2f2e0d59f337610ed1 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sat, 9 Jun 2012 10:13:58 -0300 Subject: [PATCH 0847/5711] [media] saa7146: Variable set but not used In function fops_open variable type was set but not used. Tested by compilation only. Signed-off-by: Peter Senna Tschudin Acked-by: Michael Hunold Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_fops.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 7d42c11c8684..0cdbd742974a 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -198,7 +198,6 @@ static int fops_open(struct file *file) struct saa7146_dev *dev = video_drvdata(file); struct saa7146_fh *fh = NULL; int result = 0; - enum v4l2_buf_type type; DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev)); @@ -207,10 +206,6 @@ static int fops_open(struct file *file) DEB_D("using: %p\n", dev); - type = vdev->vfl_type == VFL_TYPE_GRABBER - ? V4L2_BUF_TYPE_VIDEO_CAPTURE - : V4L2_BUF_TYPE_VBI_CAPTURE; - /* check if an extension is registered */ if( NULL == dev->ext ) { DEB_S("no extension registered for this device\n"); -- GitLab From b945f3fa829a7315488f4d39a866dfbb29e8a49a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 16 Jun 2012 11:55:18 +0800 Subject: [PATCH 0848/5711] extcon: Set platform drvdata in gpio_extcon_probe() and fix irq leak Add missing platform_set_drvdata() in gpio_extcon_probe(), otherwise calling platform_get_drvdata in gpio_extcon_remove() returns NULL. Also add missing free_irq call in gpio_extcon_remove(). Signed-off-by: Axel Lin Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon_gpio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c index fe7a07b47336..8a0dcc11c7c7 100644 --- a/drivers/extcon/extcon_gpio.c +++ b/drivers/extcon/extcon_gpio.c @@ -125,6 +125,7 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) if (ret < 0) goto err_request_irq; + platform_set_drvdata(pdev, extcon_data); /* Perform initial detection */ gpio_extcon_work(&extcon_data->work.work); @@ -146,6 +147,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev) struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev); cancel_delayed_work_sync(&extcon_data->work); + free_irq(extcon_data->irq, extcon_data); gpio_free(extcon_data->gpio); extcon_dev_unregister(&extcon_data->edev); devm_kfree(&pdev->dev, extcon_data); -- GitLab From 01eaf2458773b276e219a48df69351d230c63d0b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 16 Jun 2012 11:56:24 +0800 Subject: [PATCH 0849/5711] extcon: Convert extcon_gpio to devm_gpio_request_one Also remove unneeded devm_kfree calls. Signed-off-by: Axel Lin Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon_gpio.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c index 8a0dcc11c7c7..fe3db45fa83c 100644 --- a/drivers/extcon/extcon_gpio.c +++ b/drivers/extcon/extcon_gpio.c @@ -105,25 +105,25 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); if (ret < 0) - goto err_extcon_dev_register; + return ret; ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); if (ret < 0) - goto err_request_gpio; + goto err; INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); extcon_data->irq = gpio_to_irq(extcon_data->gpio); if (extcon_data->irq < 0) { ret = extcon_data->irq; - goto err_detect_irq_num_failed; + goto err; } ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, pdata->irq_flags, pdev->name, extcon_data); if (ret < 0) - goto err_request_irq; + goto err; platform_set_drvdata(pdev, extcon_data); /* Perform initial detection */ @@ -131,13 +131,8 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) return 0; -err_request_irq: -err_detect_irq_num_failed: - gpio_free(extcon_data->gpio); -err_request_gpio: +err: extcon_dev_unregister(&extcon_data->edev); -err_extcon_dev_register: - devm_kfree(&pdev->dev, extcon_data); return ret; } @@ -148,9 +143,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev) cancel_delayed_work_sync(&extcon_data->work); free_irq(extcon_data->irq, extcon_data); - gpio_free(extcon_data->gpio); extcon_dev_unregister(&extcon_data->edev); - devm_kfree(&pdev->dev, extcon_data); return 0; } -- GitLab From 679012655acecfa807038ccf9237bba246f9fad8 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sun, 17 Jun 2012 12:17:31 -0300 Subject: [PATCH 0850/5711] w1: Fix a typo in 'hardware' word Signed-off-by: Otavio Salvador Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 531434180afd..5a98649f6abc 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -118,7 +118,7 @@ int w1_add_master_device(struct w1_bus_master *master) return(-EINVAL); } /* While it would be electrically possible to make a device that - * generated a strong pullup in bit bang mode, only hardare that + * generated a strong pullup in bit bang mode, only hardware that * controls 1-wire time frames are even expected to support a strong * pullup. w1_io.c would need to support calling set_pullup before * the last write_bit operation of a w1_write_8 which it currently -- GitLab From d59a14e2f9642573c02654cb814c96a2e9854a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:50 -0300 Subject: [PATCH 0851/5711] [media] tvaudio: fix TDA9873 constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These constants were unused so far but need | instead of &. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index c5b1a7365e4f..9b85e2a44762 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -583,7 +583,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_TR_MASK (7 << 2) #define TDA9873_TR_MONO 4 #define TDA9873_TR_STEREO 1 << 4 -#define TDA9873_TR_REVERSE (1 << 3) & (1 << 2) +#define TDA9873_TR_REVERSE ((1 << 3) | (1 << 2)) #define TDA9873_TR_DUALA 1 << 2 #define TDA9873_TR_DUALB 1 << 3 @@ -653,11 +653,11 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_MOUT_DUALA 0 #define TDA9873_MOUT_DUALB 1 << 3 #define TDA9873_MOUT_ST 1 << 4 -#define TDA9873_MOUT_EXTM (1 << 4 ) & (1 << 3) +#define TDA9873_MOUT_EXTM ((1 << 4) | (1 << 3)) #define TDA9873_MOUT_EXTL 1 << 5 -#define TDA9873_MOUT_EXTR (1 << 5 ) & (1 << 3) -#define TDA9873_MOUT_EXTLR (1 << 5 ) & (1 << 4) -#define TDA9873_MOUT_MUTE (1 << 5 ) & (1 << 4) & (1 << 3) +#define TDA9873_MOUT_EXTR ((1 << 5) | (1 << 3)) +#define TDA9873_MOUT_EXTLR ((1 << 5) | (1 << 4)) +#define TDA9873_MOUT_MUTE ((1 << 5) | (1 << 4) | (1 << 3)) /* Status bits: (chip read) */ #define TDA9873_PONR 0 /* Power-on reset detected if = 1 */ -- GitLab From f952848ddd441003ebd312533edf800f4c77a9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:51 -0300 Subject: [PATCH 0852/5711] [media] tvaudio: fix tda8425_setmode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The passed audio mode is not a bitfield. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 9b85e2a44762..76a8cbe2085d 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1230,21 +1230,25 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) { int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1; - if (mode & V4L2_TUNER_MODE_LANG1) { + switch (mode) { + case V4L2_TUNER_MODE_LANG1: s1 |= TDA8425_S1_ML_SOUND_A; s1 |= TDA8425_S1_STEREO_PSEUDO; - - } else if (mode & V4L2_TUNER_MODE_LANG2) { + break; + case V4L2_TUNER_MODE_LANG2: s1 |= TDA8425_S1_ML_SOUND_B; s1 |= TDA8425_S1_STEREO_PSEUDO; - - } else { + break; + case V4L2_TUNER_MODE_MONO: s1 |= TDA8425_S1_ML_STEREO; - - if (mode & V4L2_TUNER_MODE_MONO) - s1 |= TDA8425_S1_STEREO_MONO; - if (mode & V4L2_TUNER_MODE_STEREO) - s1 |= TDA8425_S1_STEREO_SPATIAL; + s1 |= TDA8425_S1_STEREO_MONO; + break; + case V4L2_TUNER_MODE_STEREO: + s1 |= TDA8425_S1_ML_STEREO; + s1 |= TDA8425_S1_STEREO_SPATIAL; + break; + default: + return; } chip_write(chip,TDA8425_S1,s1); } -- GitLab From 00fb18503fee608beee5fb11cb8a6db8533e7e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:52 -0300 Subject: [PATCH 0853/5711] [media] tvaudio: use V4L2_TUNER_MODE_SAP for TDA985x SAP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As V4L2_TUNER_MODE_SAP == V4L2_TUNER_MODE_LANG2, we make V4L2_TUNER_MODE_LANG1 equal to V4L2_TUNER_MODE_STEREO. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 76a8cbe2085d..3fbaaa0494c2 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -534,9 +534,10 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) c6 |= TDA985x_MONO; break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1: c6 |= TDA985x_STEREO; break; - case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_SAP: c6 |= TDA985x_SAP; break; default: -- GitLab From c799cfc57c98e603f62f1d79d48ff4418c99f6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:53 -0300 Subject: [PATCH 0854/5711] [media] tvaudio: remove watch_stereo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is never read and only assigned 0. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 3fbaaa0494c2..fc37587d0ce4 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -126,7 +126,6 @@ struct CHIPSTATE { /* thread */ struct task_struct *thread; struct timer_list wt; - int watch_stereo; int audmode; }; @@ -1741,7 +1740,6 @@ static int tvaudio_s_radio(struct v4l2_subdev *sd) struct CHIPSTATE *chip = to_state(sd); chip->radio = 1; - chip->watch_stereo = 0; /* del_timer(&chip->wt); */ return 0; } @@ -1821,7 +1819,6 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) chip->audmode = vt->audmode; if (mode) { - chip->watch_stereo = 0; /* del_timer(&chip->wt); */ chip->mode = mode; desc->setmode(chip, mode); -- GitLab From f3647b14ffa2e8d42860bacda3a9b52366726c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:54 -0300 Subject: [PATCH 0855/5711] [media] tvaudio: don't use thread for TA8874Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Judging from the data sheet it will automatically switch to the next best audio mode in accordance with the V4L2 tuner audio matrix. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index fc37587d0ce4..0e77d4936a73 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1597,7 +1597,6 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA9840 >> 1, .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 2, - .flags = CHIP_NEED_CHECKMODE, /* callbacks */ .getmode = ta8874z_getmode, -- GitLab From 3322a59e095d648883fe68909df1b8f13ab096a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:55 -0300 Subject: [PATCH 0856/5711] [media] tvaudio: use V4L2_TUNER_SUB_* for bitfields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The V4L2_TUNER_MODE_* constants are not suited for use in bitfields. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 63 +++++++++++++++-------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 0e77d4936a73..58a0e9c2fd4b 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -315,13 +315,13 @@ static int chip_thread(void *data) chip->prevmode = mode; - if (mode & V4L2_TUNER_MODE_STEREO) + if (mode & V4L2_TUNER_SUB_STEREO) desc->setmode(chip, V4L2_TUNER_MODE_STEREO); - if (mode & V4L2_TUNER_MODE_LANG1_LANG2) + if (mode & V4L2_TUNER_SUB_LANG1_LANG2) desc->setmode(chip, V4L2_TUNER_MODE_STEREO); - else if (mode & V4L2_TUNER_MODE_LANG1) + else if (mode & V4L2_SUB_MODE_LANG1) desc->setmode(chip, V4L2_TUNER_MODE_LANG1); - else if (mode & V4L2_TUNER_MODE_LANG2) + else if (mode & V4L2_SUB_MODE_LANG2) desc->setmode(chip, V4L2_TUNER_MODE_LANG2); else desc->setmode(chip, V4L2_TUNER_MODE_MONO); @@ -363,11 +363,11 @@ static int tda9840_getmode(struct CHIPSTATE *chip) int val, mode; val = chip_read(chip); - mode = V4L2_TUNER_MODE_MONO; + mode = V4L2_TUNER_SUB_MONO; if (val & TDA9840_DS_DUAL) - mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; if (val & TDA9840_ST_STEREO) - mode |= V4L2_TUNER_MODE_STEREO; + mode |= V4L2_TUNER_SUB_STEREO; v4l2_dbg(1, debug, sd, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); @@ -514,13 +514,17 @@ static int tda9855_treble(int val) { return (val/0x1c71+0x3)<<1; } static int tda985x_getmode(struct CHIPSTATE *chip) { - int mode; + int mode, val; - mode = ((TDA985x_STP | TDA985x_SAPP) & - chip_read(chip)) >> 4; /* Add mono mode regardless of SAP and stereo */ /* Allows forced mono */ - return mode | V4L2_TUNER_MODE_MONO; + mode = V4L2_TUNER_SUB_MONO; + val = chip_read(chip); + if (val & TDA985x_STP) + mode |= V4L2_TUNER_SUB_STEREO; + if (val & TDA985x_SAPP) + mode |= V4L2_TUNER_SUB_SAP; + return mode; } static void tda985x_setmode(struct CHIPSTATE *chip, int mode) @@ -670,11 +674,11 @@ static int tda9873_getmode(struct CHIPSTATE *chip) int val,mode; val = chip_read(chip); - mode = V4L2_TUNER_MODE_MONO; + mode = V4L2_TUNER_SUB_MONO; if (val & TDA9873_STEREO) - mode |= V4L2_TUNER_MODE_STEREO; + mode |= V4L2_TUNER_SUB_STEREO; if (val & TDA9873_DUAL) - mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; v4l2_dbg(1, debug, sd, "tda9873_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; @@ -865,7 +869,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) int dsr,nsr,mode; int necr; /* just for debugging */ - mode = V4L2_TUNER_MODE_MONO; + mode = V4L2_TUNER_SUB_MONO; if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR))) return mode; @@ -888,14 +892,14 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) * external 4052 multiplexer in audio_hook(). */ if(nsr & 0x02) /* NSR.S/MB=1 */ - mode |= V4L2_TUNER_MODE_STEREO; + mode |= V4L2_TUNER_SUB_STEREO; if(nsr & 0x01) /* NSR.D/SB=1 */ - mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { if(dsr & 0x02) /* DSR.IDSTE=1 */ - mode |= V4L2_TUNER_MODE_STEREO; + mode |= V4L2_TUNER_SUB_STEREO; if(dsr & 0x04) /* DSR.IDDUA=1 */ - mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } v4l2_dbg(1, debug, sd, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", @@ -1306,11 +1310,11 @@ static int ta8874z_getmode(struct CHIPSTATE *chip) int val, mode; val = chip_read(chip); - mode = V4L2_TUNER_MODE_MONO; + mode = V4L2_TUNER_SUB_MONO; if (val & TA8874Z_B1){ - mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; }else if (!(val & TA8874Z_B0)){ - mode |= V4L2_TUNER_MODE_STEREO; + mode |= V4L2_TUNER_SUB_STEREO; } /* v4l_dbg(1, debug, chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ return mode; @@ -1829,7 +1833,6 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) { struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; - int mode = V4L2_TUNER_MODE_MONO; if (!desc->getmode) return 0; @@ -1837,22 +1840,10 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; vt->audmode = chip->audmode; - vt->rxsubchans = 0; + vt->rxsubchans = desc->getmode(chip); vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - mode = desc->getmode(chip); - - if (mode & V4L2_TUNER_MODE_MONO) - vt->rxsubchans |= V4L2_TUNER_SUB_MONO; - if (mode & V4L2_TUNER_MODE_STEREO) - vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; - /* Note: for SAP it should be mono/lang2 or stereo/lang2. - When this module is converted fully to v4l2, then this - should change for those chips that can detect SAP. */ - if (mode & V4L2_TUNER_MODE_LANG1) - vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | - V4L2_TUNER_SUB_LANG2; return 0; } -- GitLab From e21adca897ee3744d15b805321012f9c40d3659c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:56 -0300 Subject: [PATCH 0857/5711] [media] tvaudio: obey V4L2 tuner audio matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V4L2 specifies the audio mode to use for combinations of possible (rxsubchans) and requested (audmode) audio modes. Up to now tvaudio has made these decisions automatically based on the possible audio modes from setting of the frequency until VIDIOC_S_TUNER was called. It then forced the hardware to use the mode requested by the user. With this patch it continues to adjust the audio mode while taking the requested mode into account. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 61 ++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 58a0e9c2fd4b..04ebdfe30205 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -118,7 +118,7 @@ struct CHIPSTATE { audiocmd shadow; /* current settings */ - __u16 left,right,treble,bass,muted,mode; + __u16 left, right, treble, bass, muted; int prevmode; int radio; int input; @@ -287,7 +287,7 @@ static int chip_thread(void *data) struct CHIPSTATE *chip = data; struct CHIPDESC *desc = chip->desc; struct v4l2_subdev *sd = &chip->sd; - int mode; + int mode, selected; v4l2_dbg(1, debug, sd, "thread started\n"); set_freezable(); @@ -301,8 +301,8 @@ static int chip_thread(void *data) break; v4l2_dbg(1, debug, sd, "thread wakeup\n"); - /* don't do anything for radio or if mode != auto */ - if (chip->radio || chip->mode != 0) + /* don't do anything for radio */ + if (chip->radio) continue; /* have a look what's going on */ @@ -315,16 +315,27 @@ static int chip_thread(void *data) chip->prevmode = mode; - if (mode & V4L2_TUNER_SUB_STEREO) - desc->setmode(chip, V4L2_TUNER_MODE_STEREO); - if (mode & V4L2_TUNER_SUB_LANG1_LANG2) - desc->setmode(chip, V4L2_TUNER_MODE_STEREO); - else if (mode & V4L2_SUB_MODE_LANG1) - desc->setmode(chip, V4L2_TUNER_MODE_LANG1); - else if (mode & V4L2_SUB_MODE_LANG2) - desc->setmode(chip, V4L2_TUNER_MODE_LANG2); - else - desc->setmode(chip, V4L2_TUNER_MODE_MONO); + selected = V4L2_TUNER_MODE_MONO; + switch (chip->audmode) { + case V4L2_TUNER_MODE_MONO: + if (mode & V4L2_TUNER_SUB_LANG1) + selected = V4L2_TUNER_MODE_LANG1; + break; + case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1: + if (mode & V4L2_TUNER_SUB_LANG1) + selected = V4L2_TUNER_MODE_LANG1; + else if (mode & V4L2_TUNER_SUB_STEREO) + selected = V4L2_TUNER_MODE_STEREO; + break; + case V4L2_TUNER_MODE_LANG2: + if (mode & V4L2_TUNER_SUB_LANG2) + selected = V4L2_TUNER_MODE_LANG2; + else if (mode & V4L2_TUNER_SUB_STEREO) + selected = V4L2_TUNER_MODE_STEREO; + break; + } + desc->setmode(chip, selected); /* schedule next check */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); @@ -712,7 +723,6 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) sw_data |= TDA9873_TR_DUALB; break; default: - chip->mode = 0; return; } @@ -944,7 +954,6 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) mdacosr = (tda9874a_mode) ? 0x83:0x81; break; default: - chip->mode = 0; return; } chip_write(chip, TDA9874A_AOSR, aosr); @@ -979,7 +988,6 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) aosr = 0x20; /* dual B/B */ break; default: - chip->mode = 0; return; } chip_write(chip, TDA9874A_FMMR, fmmr); @@ -1799,7 +1807,6 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) { struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; - int mode = 0; if (!desc->setmode) return 0; @@ -1811,21 +1818,20 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG2: - mode = vt->audmode; break; case V4L2_TUNER_MODE_LANG1_LANG2: - mode = V4L2_TUNER_MODE_STEREO; + vt->audmode = V4L2_TUNER_MODE_STEREO; break; default: return -EINVAL; } chip->audmode = vt->audmode; - if (mode) { - /* del_timer(&chip->wt); */ - chip->mode = mode; - desc->setmode(chip, mode); - } + if (chip->thread) + wake_up_process(chip->thread); + else + desc->setmode(chip, vt->audmode); + return 0; } @@ -1860,8 +1866,6 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; - chip->mode = 0; /* automatic */ - /* For chips that provide getmode and setmode, and doesn't automatically follows the stereo carrier, a kthread is created to set the audio standard. In this case, when then @@ -1872,8 +1876,7 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr */ if (chip->thread) { desc->setmode(chip, V4L2_TUNER_MODE_MONO); - if (chip->prevmode != V4L2_TUNER_MODE_MONO) - chip->prevmode = -1; /* reset previous mode */ + chip->prevmode = -1; /* reset previous mode */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); } return 0; -- GitLab From 9e019e075e03814d27c353e5e92a704d10238c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:57 -0300 Subject: [PATCH 0858/5711] [media] tvaudio: support V4L2_TUNER_MODE_LANG1_LANG2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many of the audio decoders handled by the driver support this mode, so the driver should support it as well. Coding style errors are done to blend into the surrounding code. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 04ebdfe30205..f3ce93a7cf79 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -334,6 +334,11 @@ static int chip_thread(void *data) else if (mode & V4L2_TUNER_SUB_STEREO) selected = V4L2_TUNER_MODE_STEREO; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + if (mode & V4L2_TUNER_SUB_LANG2) + selected = V4L2_TUNER_MODE_LANG1_LANG2; + else if (mode & V4L2_TUNER_SUB_STEREO) + selected = V4L2_TUNER_MODE_STEREO; } desc->setmode(chip, selected); @@ -403,6 +408,9 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) case V4L2_TUNER_MODE_LANG2: t |= TDA9840_DUALB; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + t |= TDA9840_DUALAB; + break; default: update = 0; } @@ -487,6 +495,7 @@ static int tda9840_checkit(struct CHIPSTATE *chip) /* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */ /* Common to TDA9855 and TDA9850: */ #define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */ +#define TDA985x_MONOSAP 2<<6 /* Selects Mono on left, SAP on right */ #define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ #define TDA985x_MONO 0 /* Forces Mono output */ #define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */ @@ -554,6 +563,9 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) case V4L2_TUNER_MODE_SAP: c6 |= TDA985x_SAP; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + c6 |= TDA985x_MONOSAP; + break; default: update = 0; } @@ -601,6 +613,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_TR_REVERSE ((1 << 3) | (1 << 2)) #define TDA9873_TR_DUALA 1 << 2 #define TDA9873_TR_DUALB 1 << 3 +#define TDA9873_TR_DUALAB 0 /* output level controls * B5: output level switch (0 = reduced gain, 1 = normal gain) @@ -722,6 +735,9 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) case V4L2_TUNER_MODE_LANG2: sw_data |= TDA9873_TR_DUALB; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + sw_data |= TDA9873_TR_DUALAB; + break; default: return; } @@ -953,6 +969,10 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) aosr = 0xa0; /* auto-select, dual B/B */ mdacosr = (tda9874a_mode) ? 0x83:0x81; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + aosr = 0x00; /* always route L to L and R to R */ + mdacosr = (tda9874a_mode) ? 0x82:0x80; + break; default: return; } @@ -987,6 +1007,10 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) fmmr = 0x02; /* dual */ aosr = 0x20; /* dual B/B */ break; + case V4L2_TUNER_MODE_LANG1_LANG2: + fmmr = 0x02; /* dual */ + aosr = 0x00; /* dual A/B */ + break; default: return; } @@ -1251,6 +1275,10 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) s1 |= TDA8425_S1_ML_SOUND_B; s1 |= TDA8425_S1_STEREO_PSEUDO; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + s1 |= TDA8425_S1_ML_STEREO; + s1 |= TDA8425_S1_STEREO_LINEAR; + break; case V4L2_TUNER_MODE_MONO: s1 |= TDA8425_S1_ML_STEREO; s1 |= TDA8425_S1_STEREO_MONO; @@ -1332,6 +1360,7 @@ static audiocmd ta8874z_stereo = { 2, {0, TA8874Z_SEPARATION_DEFAULT}}; static audiocmd ta8874z_mono = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}; static audiocmd ta8874z_main = {2, { 0, TA8874Z_SEPARATION_DEFAULT}}; static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}}; +static audiocmd ta8874z_both = {2, { TA8874Z_MODE_MAIN | TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}}; static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) { @@ -1354,6 +1383,9 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) case V4L2_TUNER_MODE_LANG2: t = &ta8874z_sub; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + t = &ta8874z_both; + break; default: update = 0; } @@ -1818,9 +1850,7 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG2: - break; case V4L2_TUNER_MODE_LANG1_LANG2: - vt->audmode = V4L2_TUNER_MODE_STEREO; break; default: return -EINVAL; -- GitLab From 1884e298c1790a24991c518a8cb8f18ab41f4376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Sat, 9 Jun 2012 21:43:58 -0300 Subject: [PATCH 0859/5711] [media] tvaudio: don't report mono when stereo is received MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The V4L2 spec says reporting mono and stereo at the same time means the hardware can not distinguish between the two. So when we can, we should report only one of them. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index f3ce93a7cf79..1e61cbf1c85e 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -383,7 +383,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip) if (val & TDA9840_DS_DUAL) mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; if (val & TDA9840_ST_STEREO) - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; v4l2_dbg(1, debug, sd, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); @@ -541,7 +541,7 @@ static int tda985x_getmode(struct CHIPSTATE *chip) mode = V4L2_TUNER_SUB_MONO; val = chip_read(chip); if (val & TDA985x_STP) - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; if (val & TDA985x_SAPP) mode |= V4L2_TUNER_SUB_SAP; return mode; @@ -700,7 +700,7 @@ static int tda9873_getmode(struct CHIPSTATE *chip) val = chip_read(chip); mode = V4L2_TUNER_SUB_MONO; if (val & TDA9873_STEREO) - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; if (val & TDA9873_DUAL) mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; v4l2_dbg(1, debug, sd, "tda9873_getmode(): raw chip read: %d, return: %d\n", @@ -918,12 +918,12 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) * external 4052 multiplexer in audio_hook(). */ if(nsr & 0x02) /* NSR.S/MB=1 */ - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; if(nsr & 0x01) /* NSR.D/SB=1 */ mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { if(dsr & 0x02) /* DSR.IDSTE=1 */ - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; if(dsr & 0x04) /* DSR.IDDUA=1 */ mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } @@ -1350,7 +1350,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip) if (val & TA8874Z_B1){ mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; }else if (!(val & TA8874Z_B0)){ - mode |= V4L2_TUNER_SUB_STEREO; + mode = V4L2_TUNER_SUB_STEREO; } /* v4l_dbg(1, debug, chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ return mode; -- GitLab From 6aeec0eacd3c6ac259e38d95a9398ac258470b4c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 27 May 2012 06:54:29 -0300 Subject: [PATCH 0860/5711] [media] videodev2.h: add new hwseek capability bits Tell the application whether the hardware seek is bounded and/or wraps around. Signed-off-by: Hans Verkuil Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 370d11106c11..2339678de092 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -2039,6 +2039,8 @@ struct v4l2_modulator { /* Flags for the 'capability' field */ #define V4L2_TUNER_CAP_LOW 0x0001 #define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_HWSEEK_BOUNDED 0x0004 +#define V4L2_TUNER_CAP_HWSEEK_WRAP 0x0008 #define V4L2_TUNER_CAP_STEREO 0x0010 #define V4L2_TUNER_CAP_LANG2 0x0020 #define V4L2_TUNER_CAP_SAP 0x0020 -- GitLab From e4cca4edbce693238ba4d75269db082f34da48bb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 28 May 2012 07:30:28 -0300 Subject: [PATCH 0861/5711] [media] v4l2 spec: document the new v4l2_tuner capabilities Update the spec with the new capabilities and specify new error codes for S_HW_FREQ_SEEK. Signed-off-by: Hans Verkuil Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-g-frequency.xml | 6 ++++++ .../DocBook/media/v4l/vidioc-g-tuner.xml | 12 ++++++++++++ .../media/v4l/vidioc-s-hw-freq-seek.xml | 18 +++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml index 69c178a4d205..40e58a42eb26 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml @@ -135,6 +135,12 @@ bounds or the value in the type field is wrong. + + EBUSY + + A hardware seek is in progress. + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index 62a1aa200a36..95d5371c1709 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -275,6 +275,18 @@ can or must be switched. (B/G PAL tuners for example are typically not see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only V4L2_TUNER_ANALOG_TV tuners can have this capability. + + V4L2_TUNER_CAP_HWSEEK_BOUNDED + 0x0004 + If set, then this tuner supports the hardware seek functionality + where the seek stops when it reaches the end of the frequency range. + + + V4L2_TUNER_CAP_HWSEEK_WRAP + 0x0008 + If set, then this tuner supports the hardware seek functionality + where the seek wraps around when it reaches the end of the frequency range. + V4L2_TUNER_CAP_STEREO 0x0010 diff --git a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml index 407dfceb71f0..f4db44d0d95a 100644 --- a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml +++ b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml @@ -58,6 +58,9 @@ To do this applications initialize the tuner, call the VIDIOC_S_HW_FREQ_SEEK ioctl with a pointer to this structure. + If an error is returned, then the original frequency will + be restored. + This ioctl is supported if the V4L2_CAP_HW_FREQ_SEEK capability is set. @@ -87,7 +90,10 @@ field and the &v4l2-tuner; index field. __u32 wrap_around - If non-zero, wrap around when at the end of the frequency range, else stop seeking. + If non-zero, wrap around when at the end of the frequency range, else stop seeking. + The &v4l2-tuner; capability field will tell you what the + hardware supports. + __u32 @@ -118,9 +124,15 @@ wrong. - EAGAIN + ENODATA + + The hardware seek found no channels. + + + + EBUSY - The ioctl timed-out. Try again. + Another hardware seek is already in progress. -- GitLab From 54f6019b5860ec062d1149b3a97a5a63ad3e4da9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 27 May 2012 07:25:06 -0300 Subject: [PATCH 0862/5711] [media] S_HW_FREQ_SEEK: set capability flags and return ENODATA instead of EAGAIN Set the new capability flags in G_TUNER and return ENODATA if no channels were found. Signed-off-by: Hans Verkuil Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 5 +++-- drivers/media/radio/radio-wl1273.c | 3 ++- drivers/media/radio/si470x/radio-si470x-common.c | 6 ++++-- drivers/media/radio/wl128x/fmdrv_rx.c | 2 +- drivers/media/radio/wl128x/fmdrv_v4l2.c | 4 +++- sound/i2c/other/tea575x-tuner.c | 4 +++- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 94cb6bc690f5..3182b26d6efa 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -295,7 +295,8 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; - v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_HWSEEK_WRAP; v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; v->audmode = radio->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; @@ -372,7 +373,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv, timeout = jiffies + msecs_to_jiffies(30000); for (;;) { if (time_after(jiffies, timeout)) { - retval = -EAGAIN; + retval = -ENODATA; break; } if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index f1b607099b6c..e8428f573ccd 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1514,7 +1514,8 @@ static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv, tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO; + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP; if (radio->stereo) tuner->audmode = V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 969cf494d85b..d485b79222fd 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -363,7 +363,7 @@ stop: /* try again, if timed out */ if (retval == 0 && timed_out) - return -EAGAIN; + return -ENODATA; return retval; } @@ -596,7 +596,9 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, strcpy(tuner->name, "FM"); tuner->type = V4L2_TUNER_RADIO; tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO; + V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_WRAP; /* range limits */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c index 43fb72291bea..3dd9fc097c47 100644 --- a/drivers/media/radio/wl128x/fmdrv_rx.c +++ b/drivers/media/radio/wl128x/fmdrv_rx.c @@ -251,7 +251,7 @@ again: if (!timeleft) { fmerr("Timeout(%d sec),didn't get tune ended int\n", jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000); - return -ETIMEDOUT; + return -ENODATA; } int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT); diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 080b96a61f1a..49a11ec1f449 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -285,7 +285,9 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv, tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO | ((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0); tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_LOW; + V4L2_TUNER_CAP_LOW | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_WRAP; tuner->audmode = (stereo_mono_mode ? V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO); diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 582aace20ea3..ba2bc511d777 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -191,6 +191,8 @@ static int vidioc_g_tuner(struct file *file, void *priv, strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + if (!tea->cannot_read_data) + v->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; @@ -299,7 +301,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh, } tea->val &= ~TEA575X_BIT_SEARCH; snd_tea575x_set_freq(tea); - return -EAGAIN; + return -ENODATA; } static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) -- GitLab From 4ea418b8b2fa8a70d0fcc8231b65e67b3a72984b Mon Sep 17 00:00:00 2001 From: Christopher Brannon Date: Sat, 16 Jun 2012 16:55:20 -0500 Subject: [PATCH 0863/5711] Staging: speakup: fix an improperly-declared variable. A local static variable was declared as a pointer to a string constant. We're assigning to the underlying memory, so it needs to be an array instead. Signed-off-by: Christopher Brannon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 92b34e29ad06..40e2488b9679 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1854,7 +1854,7 @@ static void speakup_bits(struct vc_data *vc) static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) { - static u_char *goto_buf = "\0\0\0\0\0\0"; + static u_char goto_buf[8]; static int num; int maxlen, go_pos; char *cp; -- GitLab From f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 18 Jun 2012 14:05:34 +0100 Subject: [PATCH 0864/5711] staging: comedi: change device used in dev_...() calls A previous set of patches by Ravishankar Karkala Mallikarjunayya replaced a load of printk() calls with dev_info(), dev_err(), etc. Unfortunately, these used the 'struct device *hw_dev' member of 'struct comedi_device') as the first parameter of these dev_...() calls, but that pointer is usually NULL, so the kernel log messages come out a bit wrong (they contain the phrase "(NULL device *)"). Use the 'struct device *class_dev' member of 'struct comedi_device' instead for these dev_...() calls. It will be non-NULL and somewhat meaningful to users. It's also consistent with those comedi drivers that already use the class_dev member in their dev_...() calls. Some of the messages included the format "comedi%d" with the minor device number used for the "%d". This is now redundant as it will be the same as the dev_name() part of the kernel log message produced by the dev_...() calls. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1710.c | 17 ++++---- drivers/staging/comedi/drivers/adv_pci_dio.c | 8 ++-- drivers/staging/comedi/drivers/cb_das16_cs.c | 14 +++---- drivers/staging/comedi/drivers/cb_pcidas.c | 26 +++++++------ drivers/staging/comedi/drivers/cb_pcidas64.c | 20 +++++----- drivers/staging/comedi/drivers/cb_pcidda.c | 12 +++--- drivers/staging/comedi/drivers/cb_pcidio.c | 9 +++-- drivers/staging/comedi/drivers/cb_pcimdas.c | 21 +++++----- .../staging/comedi/drivers/contec_pci_dio.c | 10 ++--- drivers/staging/comedi/drivers/daqboard2000.c | 29 +++++++------- drivers/staging/comedi/drivers/das08_cs.c | 7 ++-- drivers/staging/comedi/drivers/das1800.c | 36 +++++++++-------- drivers/staging/comedi/drivers/das6402.c | 10 ++--- drivers/staging/comedi/drivers/das800.c | 39 ++++++++++--------- drivers/staging/comedi/drivers/dt3000.c | 28 ++++++------- drivers/staging/comedi/drivers/jr3_pci.c | 18 +++++---- drivers/staging/comedi/drivers/ni_pcimio.c | 4 +- drivers/staging/comedi/drivers/pcl818.c | 12 +++--- drivers/staging/comedi/drivers/pcmuio.c | 23 ++++++----- drivers/staging/comedi/drivers/serial2002.c | 4 +- 20 files changed, 187 insertions(+), 160 deletions(-) diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 60a50adcd715..94d69e421c29 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1347,7 +1347,7 @@ static int pci1710_attach(struct comedi_device *dev, int i; int board_index; - dev_info(dev->hw_dev, "comedi%d: adv_pci1710:\n", dev->minor); + dev_info(dev->class_dev, DRV_NAME ": attach\n"); opt_bus = it->options[0]; opt_slot = it->options[1]; @@ -1399,10 +1399,10 @@ static int pci1710_attach(struct comedi_device *dev, if (!pcidev) { if (opt_bus || opt_slot) { - dev_err(dev->hw_dev, "- Card at b:s %d:%d %s\n", + dev_err(dev->class_dev, "- Card at b:s %d:%d %s\n", opt_bus, opt_slot, errstr); } else { - dev_err(dev->hw_dev, "- Card %s\n", errstr); + dev_err(dev->class_dev, "- Card %s\n", errstr); } return -EIO; } @@ -1413,8 +1413,8 @@ static int pci1710_attach(struct comedi_device *dev, irq = pcidev->irq; iobase = pci_resource_start(pcidev, 2); - dev_dbg(dev->hw_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", pci_bus, pci_slot, - pci_func, iobase); + dev_dbg(dev->class_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", + pci_bus, pci_slot, pci_func, iobase); dev->iobase = iobase; @@ -1444,14 +1444,15 @@ static int pci1710_attach(struct comedi_device *dev, if (request_irq(irq, interrupt_service_pci1710, IRQF_SHARED, "Advantech PCI-1710", dev)) { - dev_dbg(dev->hw_dev, "unable to allocate IRQ %d, DISABLING IT", + dev_dbg(dev->class_dev, + "unable to allocate IRQ %d, DISABLING IT", irq); irq = 0; /* Can't use IRQ */ } else { - dev_dbg(dev->hw_dev, "irq=%u", irq); + dev_dbg(dev->class_dev, "irq=%u", irq); } } else { - dev_dbg(dev->hw_dev, "IRQ disabled"); + dev_dbg(dev->class_dev, "IRQ disabled"); } } else { irq = 0; diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 942dc777a0e6..176a8016432d 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1121,16 +1121,18 @@ static int pci_dio_attach(struct comedi_device *dev, } if (!dev->board_ptr) { - dev_err(dev->hw_dev, "Error: Requested type of the card was not found!\n"); + dev_err(dev->class_dev, + "Error: Requested type of the card was not found!\n"); return -EIO; } if (comedi_pci_enable(pcidev, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "Error: Can't enable PCI device and request regions!\n"); + dev_err(dev->class_dev, + "Error: Can't enable PCI device and request regions!\n"); return -EIO; } iobase = pci_resource_start(pcidev, this_board->main_pci_region); - dev_dbg(dev->hw_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", + dev_dbg(dev->class_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", pcidev->bus->number, PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn), iobase); diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 031007791d29..77dc880ca786 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -150,7 +150,7 @@ static const struct das16cs_board *das16cs_probe(struct comedi_device *dev, return das16cs_boards + i; } - dev_dbg(dev->hw_dev, "unknown board!\n"); + dev_dbg(dev->class_dev, "unknown board!\n"); return NULL; } @@ -163,18 +163,18 @@ static int das16cs_attach(struct comedi_device *dev, int ret; int i; - dev_dbg(dev->hw_dev, "comedi%d: cb_das16_cs: attached\n", dev->minor); + dev_dbg(dev->class_dev, "cb_das16_cs: attach\n"); link = cur_dev; /* XXX hack */ if (!link) return -EIO; dev->iobase = link->resource[0]->start; - dev_dbg(dev->hw_dev, "I/O base=0x%04lx\n", dev->iobase); + dev_dbg(dev->class_dev, "I/O base=0x%04lx\n", dev->iobase); - dev_dbg(dev->hw_dev, "fingerprint:\n"); + dev_dbg(dev->class_dev, "fingerprint:\n"); for (i = 0; i < 48; i += 2) - dev_dbg(dev->hw_dev, "%04x\n", inw(dev->iobase + i)); + dev_dbg(dev->class_dev, "%04x\n", inw(dev->iobase + i)); ret = request_irq(link->irq, das16cs_interrupt, @@ -184,7 +184,7 @@ static int das16cs_attach(struct comedi_device *dev, dev->irq = link->irq; - dev_dbg(dev->hw_dev, "irq=%u\n", dev->irq); + dev_dbg(dev->class_dev, "irq=%u\n", dev->irq); dev->board_ptr = das16cs_probe(dev, link); if (!dev->board_ptr) @@ -306,7 +306,7 @@ static int das16cs_ai_rinsn(struct comedi_device *dev, break; } if (to == TIMEOUT) { - dev_dbg(dev->hw_dev, "cb_das16_cs: ai timeout\n"); + dev_dbg(dev->class_dev, "cb_das16_cs: ai timeout\n"); return -ETIME; } data[i] = (unsigned short)inw(dev->iobase + 0); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 2ca3fa0fc776..e2bf22270561 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -567,12 +567,13 @@ static int cb_pcidas_attach(struct comedi_device *dev, } } - dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); + dev_err(dev->class_dev, + "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); return -EIO; found: - dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", + dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name, pcidev->bus->number, PCI_SLOT(pcidev->devfn)); @@ -580,7 +581,8 @@ found: * Enable PCI device and reserve I/O ports. */ if (comedi_pci_enable(pcidev, "cb_pcidas")) { - dev_err(dev->hw_dev, "Failed to enable PCI device and request regions\n"); + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); return -EIO; } /* @@ -606,7 +608,7 @@ found: /* get irq */ if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, IRQF_SHARED, "cb_pcidas", dev)) { - dev_dbg(dev->hw_dev, "unable to allocate irq %d\n", + dev_dbg(dev->class_dev, "unable to allocate irq %d\n", devpriv->pci_dev->irq); return -EINVAL; } @@ -807,7 +809,7 @@ static int ai_config_calibration_source(struct comedi_device *dev, unsigned int source = data[1]; if (source >= num_calibration_sources) { - dev_err(dev->hw_dev, "invalid calibration source: %i\n", + dev_err(dev->class_dev, "invalid calibration source: %i\n", source); return -EINVAL; } @@ -1229,7 +1231,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, outw(bits, devpriv->control_status + ADCMUX_CONT); #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "comedi: sent 0x%x to adcmux control\n", bits); + dev_dbg(dev->class_dev, "sent 0x%x to adcmux control\n", bits); #endif /* load counters */ @@ -1256,7 +1258,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */ } #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "comedi: adc_fifo_bits are 0x%x\n", + dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); #endif /* enable (and clear) interrupts */ @@ -1283,7 +1285,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, bits |= BURSTE; outw(bits, devpriv->control_status + TRIG_CONTSTAT); #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "comedi: sent 0x%x to trig control\n", bits); + dev_dbg(dev->class_dev, "sent 0x%x to trig control\n", bits); #endif return 0; @@ -1500,7 +1502,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, spin_lock_irqsave(&dev->spinlock, flags); devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "comedi: adc_fifo_bits are 0x%x\n", + dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); #endif /* enable and clear interrupts */ @@ -1511,7 +1513,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "comedi: sent 0x%x to dac control\n", + dev_dbg(dev->class_dev, "sent 0x%x to dac control\n", devpriv->ao_control_bits); #endif spin_unlock_irqrestore(&dev->spinlock, flags); @@ -1540,8 +1542,8 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); #ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->hw_dev, "intcsr 0x%x\n", s5933_status); - dev_dbg(dev->hw_dev, "mbef 0x%x\n", + dev_dbg(dev->class_dev, "intcsr 0x%x\n", s5933_status); + dev_dbg(dev->class_dev, "mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF)); #endif diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 3aab75b5217d..7aacff3292c2 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1701,11 +1701,12 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EIO; } - dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", board(dev)->name, - pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", + board(dev)->name, pcidev->bus->number, PCI_SLOT(pcidev->devfn)); if (comedi_pci_enable(pcidev, dev->driver->driver_name)) { - dev_warn(dev->hw_dev, "failed to enable PCI device and request regions\n"); + dev_warn(dev->class_dev, + "failed to enable PCI device and request regions\n"); return -EIO; } pci_set_master(pcidev); @@ -1733,7 +1734,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!priv(dev)->plx9080_iobase || !priv(dev)->main_iobase || !priv(dev)->dio_counter_iobase) { - dev_warn(dev->hw_dev, "failed to remap io memory\n"); + dev_warn(dev->class_dev, "failed to remap io memory\n"); return -ENOMEM; } @@ -1769,19 +1770,19 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it) priv(dev)->hw_revision = hw_revision(dev, readw(priv(dev)->main_iobase + HW_STATUS_REG)); - dev_dbg(dev->hw_dev, "stc hardware revision %i\n", + dev_dbg(dev->class_dev, "stc hardware revision %i\n", priv(dev)->hw_revision); init_plx9080(dev); init_stc_registers(dev); /* get irq */ if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, "cb_pcidas64", dev)) { - dev_dbg(dev->hw_dev, "unable to allocate irq %u\n", + dev_dbg(dev->class_dev, "unable to allocate irq %u\n", pcidev->irq); return -EINVAL; } dev->irq = pcidev->irq; - dev_dbg(dev->hw_dev, "irq %u\n", dev->irq); + dev_dbg(dev->class_dev, "irq %u\n", dev->irq); retval = setup_subdevices(dev); if (retval < 0) @@ -2002,7 +2003,7 @@ static int ai_config_calibration_source(struct comedi_device *dev, else num_calibration_sources = 8; if (source >= num_calibration_sources) { - dev_dbg(dev->hw_dev, "invalid calibration source: %i\n", + dev_dbg(dev->class_dev, "invalid calibration source: %i\n", source); return -EINVAL; } @@ -2834,7 +2835,8 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) } if (num_samples < 0) { - dev_err(dev->hw_dev, "cb_pcidas64: bug! num_samples < 0\n"); + dev_err(dev->class_dev, + "cb_pcidas64: bug! num_samples < 0\n"); break; } diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 0572dc6fd5ca..f5a7957639df 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -294,21 +294,23 @@ static int cb_pcidda_attach(struct comedi_device *dev, } } if (!pcidev) { - dev_err(dev->hw_dev, "Not a ComputerBoards/MeasurementComputing card on requested position\n"); + dev_err(dev->class_dev, + "Not a ComputerBoards/MeasurementComputing card on requested position\n"); return -EIO; } found: devpriv->pci_dev = pcidev; dev->board_ptr = cb_pcidda_boards + index; /* "thisboard" macro can be used from here. */ - dev_dbg(dev->hw_dev, "Found %s at requested position\n", + dev_dbg(dev->class_dev, "Found %s at requested position\n", thisboard->name); /* * Enable PCI device and request regions. */ if (comedi_pci_enable(pcidev, thisboard->name)) { - dev_err(dev->hw_dev, "cb_pcidda: failed to enable PCI device and request regions\n"); + dev_err(dev->class_dev, + "cb_pcidda: failed to enable PCI device and request regions\n"); return -EIO; } @@ -356,10 +358,10 @@ found: s = dev->subdevices + 2; subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A); - dev_dbg(dev->hw_dev, "eeprom:\n"); + dev_dbg(dev->class_dev, "eeprom:\n"); for (index = 0; index < EEPROM_SIZE; index++) { devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index); - dev_dbg(dev->hw_dev, "%i:0x%x\n", index, + dev_dbg(dev->class_dev, "%i:0x%x\n", index, devpriv->eeprom_data[index]); } diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 0186737c1ee1..9160859deee3 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -155,7 +155,8 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); + dev_err(dev->class_dev, + "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); return -EIO; found: @@ -167,8 +168,8 @@ found: dev->board_name = thisboard->name; devpriv->pci_dev = pcidev; - dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", thisboard->name, - devpriv->pci_dev->bus->number, + dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", + thisboard->name, devpriv->pci_dev->bus->number, PCI_SLOT(devpriv->pci_dev->devfn)); if (comedi_pci_enable(pcidev, thisboard->name)) return -EIO; @@ -185,7 +186,7 @@ found: for (i = 0; i < thisboard->n_8255; i++) { subdev_8255_init(dev, dev->subdevices + i, NULL, devpriv->dio_reg_base + i * 4); - dev_dbg(dev->hw_dev, "subdev %d: base = 0x%lx\n", i, + dev_dbg(dev->class_dev, "subdev %d: base = 0x%lx\n", i, devpriv->dio_reg_base + i * 4); } diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index b99a451bab9e..2977f2d309cb 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -223,12 +223,13 @@ static int cb_pcimdas_attach(struct comedi_device *dev, } } - dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); + dev_err(dev->class_dev, + "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); return -EIO; found: - dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", + dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name, pcidev->bus->number, PCI_SLOT(pcidev->devfn)); @@ -237,12 +238,14 @@ found: case 0x56: break; default: - dev_dbg(dev->hw_dev, "THIS CARD IS UNSUPPORTED.\n" + dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n"); + dev_dbg(dev->class_dev, "PLEASE REPORT USAGE TO \n"); } if (comedi_pci_enable(pcidev, "cb_pcimdas")) { - dev_err(dev->hw_dev, "Failed to enable PCI device and request regions\n"); + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); return -EIO; } @@ -252,11 +255,11 @@ found: devpriv->BADR3 = pci_resource_start(devpriv->pci_dev, 3); devpriv->BADR4 = pci_resource_start(devpriv->pci_dev, 4); - dev_dbg(dev->hw_dev, "devpriv->BADR0 = 0x%lx\n", devpriv->BADR0); - dev_dbg(dev->hw_dev, "devpriv->BADR1 = 0x%lx\n", devpriv->BADR1); - dev_dbg(dev->hw_dev, "devpriv->BADR2 = 0x%lx\n", devpriv->BADR2); - dev_dbg(dev->hw_dev, "devpriv->BADR3 = 0x%lx\n", devpriv->BADR3); - dev_dbg(dev->hw_dev, "devpriv->BADR4 = 0x%lx\n", devpriv->BADR4); + dev_dbg(dev->class_dev, "devpriv->BADR0 = 0x%lx\n", devpriv->BADR0); + dev_dbg(dev->class_dev, "devpriv->BADR1 = 0x%lx\n", devpriv->BADR1); + dev_dbg(dev->class_dev, "devpriv->BADR2 = 0x%lx\n", devpriv->BADR2); + dev_dbg(dev->class_dev, "devpriv->BADR3 = 0x%lx\n", devpriv->BADR3); + dev_dbg(dev->class_dev, "devpriv->BADR4 = 0x%lx\n", devpriv->BADR4); /* Dont support IRQ yet */ /* get irq */ diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 79854b1ac243..d49561ff35ba 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -71,8 +71,8 @@ static int contec_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - dev_dbg(dev->hw_dev, "contec_do_insn_bits called\n"); - dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]); + dev_dbg(dev->class_dev, "contec_do_insn_bits called\n"); + dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); if (insn->n != 2) return -EINVAL; @@ -80,7 +80,7 @@ static int contec_do_insn_bits(struct comedi_device *dev, if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; - dev_dbg(dev->hw_dev, "out: %d on %lx\n", s->state, + dev_dbg(dev->class_dev, "out: %d on %lx\n", s->state, dev->iobase + thisboard->out_offs); outw(s->state, dev->iobase + thisboard->out_offs); } @@ -92,8 +92,8 @@ static int contec_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - dev_dbg(dev->hw_dev, "contec_di_insn_bits called\n"); - dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]); + dev_dbg(dev->class_dev, "contec_di_insn_bits called\n"); + dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); if (insn->n != 2) return -EINVAL; diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 9ecf1a468567..8455cb9f8d1c 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -485,7 +485,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, static void daqboard2000_resetLocalBus(struct comedi_device *dev) { - dev_dbg(dev->hw_dev, "daqboard2000_resetLocalBus\n"); + dev_dbg(dev->class_dev, "daqboard2000_resetLocalBus\n"); writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); @@ -494,7 +494,7 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev) static void daqboard2000_reloadPLX(struct comedi_device *dev) { - dev_dbg(dev->hw_dev, "daqboard2000_reloadPLX\n"); + dev_dbg(dev->class_dev, "daqboard2000_reloadPLX\n"); writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); @@ -505,7 +505,7 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev) static void daqboard2000_pulseProgPin(struct comedi_device *dev) { - dev_dbg(dev->hw_dev, "daqboard2000_pulseProgPin 1\n"); + dev_dbg(dev->class_dev, "daqboard2000_pulseProgPin 1\n"); writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); @@ -557,14 +557,14 @@ static int initialize_daqboard2000(struct comedi_device *dev, secr = readl(devpriv->plx + 0x6c); if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) { #ifdef DEBUG_EEPROM - dev_dbg(dev->hw_dev, "no serial eeprom\n"); + dev_dbg(dev->class_dev, "no serial eeprom\n"); #endif return -EIO; } for (retry = 0; retry < 3; retry++) { #ifdef DEBUG_EEPROM - dev_dbg(dev->hw_dev, "Programming EEPROM try %x\n", retry); + dev_dbg(dev->class_dev, "Programming EEPROM try %x\n", retry); #endif daqboard2000_resetLocalBus(dev); @@ -575,8 +575,8 @@ static int initialize_daqboard2000(struct comedi_device *dev, if (cpld_array[i] == 0xff && cpld_array[i + 1] == 0x20) { #ifdef DEBUG_EEPROM - dev_dbg(dev->hw_dev, "Preamble found at %d\n", - i); + dev_dbg(dev->class_dev, + "Preamble found at %d\n", i); #endif break; } @@ -589,7 +589,7 @@ static int initialize_daqboard2000(struct comedi_device *dev, } if (i >= len) { #ifdef DEBUG_EEPROM - dev_dbg(dev->hw_dev, "Programmed\n"); + dev_dbg(dev->class_dev, "Programmed\n"); #endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); @@ -733,10 +733,11 @@ static int daqboard2000_attach(struct comedi_device *dev, } if (!card) { if (bus || slot) - dev_err(dev->hw_dev, "no daqboard2000 found at bus/slot: %d/%d\n", + dev_err(dev->class_dev, + "no daqboard2000 found at bus/slot: %d/%d\n", bus, slot); else - dev_err(dev->hw_dev, "no daqboard2000 found\n"); + dev_err(dev->class_dev, "no daqboard2000 found\n"); return -EIO; } else { u32 id; @@ -746,7 +747,7 @@ static int daqboard2000_attach(struct comedi_device *dev, subsystem_device << 16) | card->subsystem_vendor; for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { if (boardtypes[i].id == id) { - dev_dbg(dev->hw_dev, "%s\n", + dev_dbg(dev->class_dev, "%s\n", boardtypes[i].name); dev->board_ptr = boardtypes + i; } @@ -761,7 +762,8 @@ static int daqboard2000_attach(struct comedi_device *dev, result = comedi_pci_enable(card, "daqboard2000"); if (result < 0) { - dev_err(dev->hw_dev, "failed to enable PCI device and request regions\n"); + dev_err(dev->class_dev, + "failed to enable PCI device and request regions\n"); return -EIO; } devpriv->got_regions = 1; @@ -791,7 +793,8 @@ static int daqboard2000_attach(struct comedi_device *dev, if (aux_data && aux_len) { result = initialize_daqboard2000(dev, aux_data, aux_len); } else { - dev_dbg(dev->hw_dev, "no FPGA initialization code, aborting\n"); + dev_dbg(dev->class_dev, + "no FPGA initialization code, aborting\n"); result = -EIO; } if (result < 0) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 4ad398aad72c..8bf6ec2dddba 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -79,17 +79,18 @@ static int das08_cs_attach(struct comedi_device *dev, if (ret < 0) return ret; - dev_info(dev->hw_dev, "comedi%d: das08_cs:\n", dev->minor); + dev_info(dev->class_dev, "das08_cs: attach\n"); /* deal with a pci board */ if (thisboard->bustype == pcmcia) { if (link == NULL) { - dev_err(dev->hw_dev, "no pcmcia cards found\n"); + dev_err(dev->class_dev, "no pcmcia cards found\n"); return -EIO; } iobase = link->resource[0]->start; } else { - dev_err(dev->hw_dev, "bug! board does not have PCMCIA bustype\n"); + dev_err(dev->class_dev, + "bug! board does not have PCMCIA bustype\n"); return -EINVAL; } diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index af60e5d5b8a3..365028772b00 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1405,22 +1405,26 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, devpriv->dma_bits |= DMA_CH7_CH5; break; default: - dev_err(dev->hw_dev, " only supports dma channels 5 through 7\n" - " Dual dma only allows the following combinations:\n" - " dma 5,6 / 6,7 / or 7,5\n"); + dev_err(dev->class_dev, + "only supports dma channels 5 through 7\n"); + dev_err(dev->class_dev, + "Dual dma only allows the following combinations:\n"); + dev_err(dev->class_dev, + "dma 5,6 / 6,7 / or 7,5\n"); return -EINVAL; break; } if (request_dma(dma0, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", - dma0); + dev_err(dev->class_dev, + "failed to allocate dma channel %i\n", dma0); return -EINVAL; } devpriv->dma0 = dma0; devpriv->dma_current = dma0; if (dma1) { if (request_dma(dma1, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "failed to allocate dma channel %i\n", + dev_err(dev->class_dev, + "failed to allocate dma channel %i\n", dma1); return -EINVAL; } @@ -1460,7 +1464,7 @@ static int das1800_probe(struct comedi_device *dev) case 0x3: if (board == das1801st_da || board == das1802st_da || board == das1701st_da || board == das1702st_da) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1470,7 +1474,7 @@ static int das1800_probe(struct comedi_device *dev) break; case 0x4: if (board == das1802hr_da || board == das1702hr_da) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1481,7 +1485,7 @@ static int das1800_probe(struct comedi_device *dev) case 0x5: if (board == das1801ao || board == das1802ao || board == das1701ao || board == das1702ao) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1491,7 +1495,7 @@ static int das1800_probe(struct comedi_device *dev) break; case 0x6: if (board == das1802hr || board == das1702hr) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1502,7 +1506,7 @@ static int das1800_probe(struct comedi_device *dev) case 0x7: if (board == das1801st || board == das1802st || board == das1701st || board == das1702st) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1512,7 +1516,7 @@ static int das1800_probe(struct comedi_device *dev) break; case 0x8: if (board == das1801hc || board == das1802hc) { - dev_dbg(dev->hw_dev, "Board model: %s\n", + dev_dbg(dev->class_dev, "Board model: %s\n", das1800_boards[board].name); return board; } @@ -1559,7 +1563,7 @@ static int das1800_attach(struct comedi_device *dev, printk(KERN_CONT "\n"); if (iobase == 0) { - dev_err(dev->hw_dev, "io base address required\n"); + dev_err(dev->class_dev, "io base address required\n"); return -EINVAL; } @@ -1574,7 +1578,7 @@ static int das1800_attach(struct comedi_device *dev, board = das1800_probe(dev); if (board < 0) { - dev_err(dev->hw_dev, "unable to determine board type\n"); + dev_err(dev->class_dev, "unable to determine board type\n"); return -ENODEV; } @@ -1598,7 +1602,7 @@ static int das1800_attach(struct comedi_device *dev, if (irq) { if (request_irq(irq, das1800_interrupt, 0, dev->driver->driver_name, dev)) { - dev_dbg(dev->hw_dev, "unable to allocate irq %u\n", + dev_dbg(dev->class_dev, "unable to allocate irq %u\n", irq); return -EINVAL; } @@ -1628,7 +1632,7 @@ static int das1800_attach(struct comedi_device *dev, devpriv->irq_dma_bits |= 0x38; break; default: - dev_err(dev->hw_dev, "irq out of range\n"); + dev_err(dev->class_dev, "irq out of range\n"); return -EINVAL; break; } diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 22a9b3448e3f..e3afcfa9efc8 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -155,7 +155,7 @@ static irqreturn_t intr_handler(int irq, void *d) struct comedi_subdevice *s = dev->subdevices; if (!dev->attached || devpriv->das6402_ignoreirq) { - dev_warn(dev->hw_dev, "BUG: spurious interrupt\n"); + dev_warn(dev->class_dev, "BUG: spurious interrupt\n"); return IRQ_HANDLED; } #ifdef DEBUG @@ -202,7 +202,7 @@ static int das6402_ai_cancel(struct comedi_device *dev, */ devpriv->das6402_ignoreirq = 1; - dev_dbg(dev->hw_dev, "Stopping acquisition\n"); + dev_dbg(dev->class_dev, "Stopping acquisition\n"); devpriv->das6402_ignoreirq = 1; outb_p(0x02, dev->iobase + 10); /* disable external trigging */ outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */ @@ -218,7 +218,7 @@ static int das6402_ai_mode2(struct comedi_device *dev, struct comedi_subdevice *s, comedi_trig * it) { devpriv->das6402_ignoreirq = 1; - dev_dbg(dev->hw_dev, "Starting acquisition\n"); + dev_dbg(dev->class_dev, "Starting acquisition\n"); outb_p(0x03, dev->iobase + 10); /* enable external trigging */ outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */ outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9); @@ -289,7 +289,7 @@ static int das6402_attach(struct comedi_device *dev, iobase = 0x300; if (!request_region(iobase, DAS6402_SIZE, "das6402")) { - dev_err(dev->hw_dev, "I/O port conflict\n"); + dev_err(dev->class_dev, "I/O port conflict\n"); return -EIO; } dev->iobase = iobase; @@ -297,7 +297,7 @@ static int das6402_attach(struct comedi_device *dev, /* should do a probe here */ irq = it->options[0]; - dev_dbg(dev->hw_dev, "( irq = %u )\n", irq); + dev_dbg(dev->class_dev, "( irq = %u )\n", irq); ret = request_irq(irq, intr_handler, 0, "das6402", dev); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 81698b1fd0da..917b31812b6c 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -296,46 +296,47 @@ static int das800_probe(struct comedi_device *dev) switch (id_bits) { case 0x0: if (board == das800) { - dev_dbg(dev->hw_dev, "Board model: DAS-800\n"); + dev_dbg(dev->class_dev, "Board model: DAS-800\n"); return board; } if (board == ciodas800) { - dev_dbg(dev->hw_dev, "Board model: CIO-DAS800\n"); + dev_dbg(dev->class_dev, "Board model: CIO-DAS800\n"); return board; } - dev_dbg(dev->hw_dev, "Board model (probed): DAS-800\n"); + dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); return das800; break; case 0x2: if (board == das801) { - dev_dbg(dev->hw_dev, "Board model: DAS-801\n"); + dev_dbg(dev->class_dev, "Board model: DAS-801\n"); return board; } if (board == ciodas801) { - dev_dbg(dev->hw_dev, "Board model: CIO-DAS801\n"); + dev_dbg(dev->class_dev, "Board model: CIO-DAS801\n"); return board; } - dev_dbg(dev->hw_dev, "Board model (probed): DAS-801\n"); + dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); return das801; break; case 0x3: if (board == das802) { - dev_dbg(dev->hw_dev, "Board model: DAS-802\n"); + dev_dbg(dev->class_dev, "Board model: DAS-802\n"); return board; } if (board == ciodas802) { - dev_dbg(dev->hw_dev, "Board model: CIO-DAS802\n"); + dev_dbg(dev->class_dev, "Board model: CIO-DAS802\n"); return board; } if (board == ciodas80216) { - dev_dbg(dev->hw_dev, "Board model: CIO-DAS802/16\n"); + dev_dbg(dev->class_dev, "Board model: CIO-DAS802/16\n"); return board; } - dev_dbg(dev->hw_dev, "Board model (probed): DAS-802\n"); + dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); return das802; break; default: - dev_dbg(dev->hw_dev, "Board model: probe returned 0x%x (unknown)\n", + dev_dbg(dev->class_dev, + "Board model: probe returned 0x%x (unknown)\n", id_bits); return board; break; @@ -467,42 +468,42 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) int board; int ret; - dev_info(dev->hw_dev, "comedi%d: das800: io 0x%lx\n", dev->minor, - iobase); + dev_info(dev->class_dev, "das800: io 0x%lx\n", iobase); if (irq) - dev_dbg(dev->hw_dev, "irq %u\n", irq); + dev_dbg(dev->class_dev, "irq %u\n", irq); /* allocate and initialize dev->private */ if (alloc_private(dev, sizeof(struct das800_private)) < 0) return -ENOMEM; if (iobase == 0) { - dev_err(dev->hw_dev, "io base address required for das800\n"); + dev_err(dev->class_dev, + "io base address required for das800\n"); return -EINVAL; } /* check if io addresses are available */ if (!request_region(iobase, DAS800_SIZE, "das800")) { - dev_err(dev->hw_dev, "I/O port conflict\n"); + dev_err(dev->class_dev, "I/O port conflict\n"); return -EIO; } dev->iobase = iobase; board = das800_probe(dev); if (board < 0) { - dev_dbg(dev->hw_dev, "unable to determine board type\n"); + dev_dbg(dev->class_dev, "unable to determine board type\n"); return -ENODEV; } dev->board_ptr = das800_boards + board; /* grab our IRQ */ if (irq == 1 || irq > 7) { - dev_err(dev->hw_dev, "irq out of range\n"); + dev_err(dev->class_dev, "irq out of range\n"); return -EINVAL; } if (irq) { if (request_irq(irq, das800_interrupt, 0, "das800", dev)) { - dev_err(dev->hw_dev, "unable to allocate irq %u\n", + dev_err(dev->class_dev, "unable to allocate irq %u\n", irq); return -EINVAL; } diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 9828fb1e3365..31a16edc0a27 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -289,7 +289,7 @@ static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) return 0; - dev_dbg(dev->hw_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n", + dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n", status); return -ETIME; @@ -390,7 +390,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, if (count < 0) count += AI_FIFO_DEPTH; - dev_dbg(dev->hw_dev, "reading %d samples\n", count); + dev_dbg(dev->class_dev, "reading %d samples\n", count); rear = devpriv->ai_rear; @@ -578,7 +578,7 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int ret; unsigned int mode; - dev_dbg(dev->hw_dev, "dt3k_ai_cmd:\n"); + dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n"); for (i = 0; i < cmd->chanlist_len; i++) { chan = CR_CHAN(cmd->chanlist[i]); range = CR_RANGE(cmd->chanlist[i]); @@ -589,15 +589,15 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) aref = CR_AREF(cmd->chanlist[0]); writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0)); - dev_dbg(dev->hw_dev, "param[0]=0x%04x\n", cmd->scan_end_arg); + dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg); if (cmd->convert_src == TRIG_TIMER) { divider = dt3k_ns_to_timer(50, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); writew((divider >> 16), devpriv->io_addr + DPR_Params(1)); - dev_dbg(dev->hw_dev, "param[1]=0x%04x\n", divider >> 16); + dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16); writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2)); - dev_dbg(dev->hw_dev, "param[2]=0x%04x\n", divider & 0xffff); + dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff); } else { /* not supported */ } @@ -606,21 +606,21 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3)); - dev_dbg(dev->hw_dev, "param[3]=0x%04x\n", tscandiv >> 16); + dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16); writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4)); - dev_dbg(dev->hw_dev, "param[4]=0x%04x\n", tscandiv & 0xffff); + dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff); } else { /* not supported */ } mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; writew(mode, devpriv->io_addr + DPR_Params(5)); - dev_dbg(dev->hw_dev, "param[5]=0x%04x\n", mode); + dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode); writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6)); - dev_dbg(dev->hw_dev, "param[6]=0x%04x\n", aref == AREF_DIFF); + dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF); writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7)); - dev_dbg(dev->hw_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2); + dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2); writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); ret = dt3k_send_cmd(dev, CMD_CONFIG); @@ -856,7 +856,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) int bus, slot; int ret = 0; - dev_dbg(dev->hw_dev, "dt3000:\n"); + dev_dbg(dev->class_dev, "dt3000:\n"); bus = it->options[0]; slot = it->options[1]; @@ -868,7 +868,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; if (ret == 0) { - dev_warn(dev->hw_dev, "no DT board found\n"); + dev_warn(dev->class_dev, "no DT board found\n"); return -ENODEV; } @@ -876,7 +876,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED, "dt3000", dev)) { - dev_err(dev->hw_dev, "unable to allocate IRQ %u\n", + dev_err(dev->class_dev, "unable to allocate IRQ %u\n", devpriv->pci_dev->irq); return -EINVAL; } diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 3c043e535506..93f94cd7bae2 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -349,13 +349,13 @@ static int jr3_pci_open(struct comedi_device *dev) int i; struct jr3_pci_dev_private *devpriv = dev->private; - dev_dbg(dev->hw_dev, "jr3_pci_open\n"); + dev_dbg(dev->class_dev, "jr3_pci_open\n"); for (i = 0; i < devpriv->n_channels; i++) { struct jr3_pci_subdev_private *p; p = dev->subdevices[i].private; if (p) { - dev_dbg(dev->hw_dev, "serial: %p %d (%d)\n", p, + dev_dbg(dev->class_dev, "serial: %p %d (%d)\n", p, p->serial_no, p->channel_no); } } @@ -434,7 +434,8 @@ static int jr3_download_firmware(struct comedi_device *dev, const u8 * data, break; more = more && read_idm_word(data, size, &pos, &addr); - dev_dbg(dev->hw_dev, "Loading#%d %4.4x bytes at %4.4x\n", + dev_dbg(dev->class_dev, + "Loading#%d %4.4x bytes at %4.4x\n", i, count, addr); while (more && count > 0) { if (addr & 0x4000) { @@ -754,7 +755,8 @@ static int jr3_pci_attach(struct comedi_device *dev, opt_slot = it->options[1]; if (sizeof(struct jr3_channel) != 0xc00) { - dev_err(dev->hw_dev, "sizeof(struct jr3_channel) = %x [expected %x]\n", + dev_err(dev->class_dev, + "sizeof(struct jr3_channel) = %x [expected %x]\n", (unsigned)sizeof(struct jr3_channel), 0xc00); return -EINVAL; } @@ -809,7 +811,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } } if (!card) { - dev_err(dev->hw_dev, "no jr3_pci found\n"); + dev_err(dev->class_dev, "no jr3_pci found\n"); return -EIO; } else { devpriv->pci_dev = card; @@ -844,7 +846,7 @@ static int jr3_pci_attach(struct comedi_device *dev, p = dev->subdevices[i].private; p->channel = &devpriv->iobase->channel[i].data; - dev_dbg(dev->hw_dev, "p->channel %p %p (%tx)\n", + dev_dbg(dev->class_dev, "p->channel %p %p (%tx)\n", p->channel, devpriv->iobase, ((char *)(p->channel) - (char *)(devpriv->iobase))); @@ -885,7 +887,7 @@ static int jr3_pci_attach(struct comedi_device *dev, devpriv->iobase->channel[0].reset = 0; result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); - dev_dbg(dev->hw_dev, "Firmare load %d\n", result); + dev_dbg(dev->class_dev, "Firmare load %d\n", result); if (result < 0) goto out; @@ -903,7 +905,7 @@ static int jr3_pci_attach(struct comedi_device *dev, */ msleep_interruptible(25); for (i = 0; i < 0x18; i++) { - dev_dbg(dev->hw_dev, "%c\n", + dev_dbg(dev->class_dev, "%c\n", get_u16(&devpriv->iobase->channel[0]. data.copyright[i]) >> 8); } diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 3974c0d98d2a..89f4d43c6d08 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1593,7 +1593,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; - dev_info(dev->hw_dev, "comedi%d: ni_pcimio:\n", dev->minor); + dev_info(dev->class_dev, "ni_pcimio: attach\n"); ret = ni_alloc_private(dev); if (ret < 0) @@ -1603,7 +1603,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - dev_dbg(dev->hw_dev, "%s\n", boardtype.name); + dev_dbg(dev->class_dev, "%s\n", boardtype.name); dev->board_name = boardtype.name; if (boardtype.reg_type & ni_reg_m_series_mask) { diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 786c3b6442a6..23b61d8aa404 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -952,7 +952,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, int divisor1 = 0, divisor2 = 0; unsigned int seglen; - dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode()\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode()\n"); if ((!dev->irq) && (!devpriv->dma_rtc)) { comedi_error(dev, "IRQ not defined!"); return -EINVAL; @@ -1055,7 +1055,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, break; } #endif - dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode() end\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode() end\n"); return 0; } @@ -1386,7 +1386,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; int retval; - dev_dbg(dev->hw_dev, "pcl818_ai_cmd()\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cmd()\n"); devpriv->ai_n_chan = cmd->chanlist_len; devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; @@ -1404,7 +1404,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */ devpriv->ai_timer1 = cmd->convert_arg; retval = pcl818_ai_cmd_mode(1, dev, s); - dev_dbg(dev->hw_dev, "pcl818_ai_cmd() end\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cmd() end\n"); return retval; } if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ @@ -1423,7 +1423,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { if (devpriv->irq_blocked > 0) { - dev_dbg(dev->hw_dev, "pcl818_ai_cancel()\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n"); devpriv->irq_was_now_closed = 1; switch (devpriv->ai_mode) { @@ -1473,7 +1473,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev, } end: - dev_dbg(dev->hw_dev, "pcl818_ai_cancel() end\n"); + dev_dbg(dev->class_dev, "pcl818_ai_cancel() end\n"); return 0; } diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 48565fe9efcc..4426e1798ed5 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -227,7 +227,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, #ifdef DAMMIT_ITS_BROKEN /* DEBUG */ - dev_dbg(dev->hw_dev, "write mask: %08x data: %08x\n", data[0], + dev_dbg(dev->class_dev, "write mask: %08x data: %08x\n", data[0], data[1]); #endif @@ -264,7 +264,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, } #ifdef DAMMIT_ITS_BROKEN /* DEBUG */ - dev_dbg(dev->hw_dev, "data_out_byte %02x\n", (unsigned)byte); + dev_dbg(dev->class_dev, "data_out_byte %02x\n", (unsigned)byte); #endif /* save the digital input lines for this byte.. */ s->state |= ((unsigned int)byte) << offset; @@ -275,7 +275,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, #ifdef DAMMIT_ITS_BROKEN /* DEBUG */ - dev_dbg(dev->hw_dev, "s->state %08x data_out %08x\n", s->state, + dev_dbg(dev->class_dev, "s->state %08x data_out %08x\n", s->state, data[1]); #endif @@ -760,7 +760,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq[0] = it->options[1]; irq[1] = it->options[2]; - dev_dbg(dev->hw_dev, "comedi%d: %s: io: %lx attached\n", dev->minor, + dev_dbg(dev->class_dev, "%s: io: %lx attach\n", dev->driver->driver_name, iobase); dev->iobase = iobase; @@ -768,7 +768,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!iobase || !request_region(iobase, board->num_asics * ASIC_IOSIZE, dev->driver->driver_name)) { - dev_err(dev->hw_dev, "I/O port conflict\n"); + dev_err(dev->class_dev, "I/O port conflict\n"); return -EIO; } @@ -779,7 +779,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * convenient macro defined in comedidev.h. */ if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) { - dev_warn(dev->hw_dev, "cannot allocate private data structure\n"); + dev_warn(dev->class_dev, + "cannot allocate private data structure\n"); return -ENOMEM; } @@ -798,7 +799,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private), GFP_KERNEL); if (!devpriv->sprivs) { - dev_warn(dev->hw_dev, "cannot allocate subdevice private data structures\n"); + dev_warn(dev->class_dev, + "cannot allocate subdevice private data structures\n"); return -ENOMEM; } @@ -890,11 +892,12 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) irqs.. */ if (irq[0]) { - dev_dbg(dev->hw_dev, "irq: %u\n", irq[0]); + dev_dbg(dev->class_dev, "irq: %u\n", irq[0]); if (irq[1] && board->num_asics == 2) - dev_dbg(dev->hw_dev, "second ASIC irq: %u\n", irq[1]); + dev_dbg(dev->class_dev, "second ASIC irq: %u\n", + irq[1]); } else { - dev_dbg(dev->hw_dev, "(IRQ mode disabled)\n"); + dev_dbg(dev->class_dev, "(IRQ mode disabled)\n"); } diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index e62297380786..c18314be8c82 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -782,7 +782,7 @@ static int serial2002_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev_dbg(dev->hw_dev, "comedi%d: attached\n", dev->minor); + dev_dbg(dev->class_dev, "serial2002: attach\n"); dev->board_name = board->name; if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) return -ENOMEM; @@ -790,7 +790,7 @@ static int serial2002_attach(struct comedi_device *dev, dev->close = serial_2002_close; devpriv->port = it->options[0]; devpriv->speed = it->options[1]; - dev_dbg(dev->hw_dev, "/dev/ttyS%d @ %d\n", devpriv->port, + dev_dbg(dev->class_dev, "/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed); ret = comedi_alloc_subdevices(dev, 5); -- GitLab From 185f9aa7df9b75609f6828ecc0d0120fbe94da08 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 18 Jun 2012 15:16:44 +0100 Subject: [PATCH 0865/5711] staging: comedi: usbduxfast: use attach_usb() hook Change the usbduxfast driver to use the new attach_usb() hook in struct comedi_driver to auto-configure probed USB devices after the firmware is loaded. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxfast.c | 133 ++++++++++++-------- 1 file changed, 79 insertions(+), 54 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 2ee9ecd33539..c71362086cdf 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1619,64 +1619,28 @@ static void usbduxfastsub_disconnect(struct usb_interface *intf) #endif } -/* - * is called when comedi-config is called - */ -static int usbduxfast_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +/* common part of attach and attach_usb */ +static int usbduxfast_attach_common(struct comedi_device *dev, + struct usbduxfastsub_s *udfs, + void *aux_data, int aux_len) { int ret; - int index; - int i; - struct comedi_subdevice *s = NULL; - dev->private = NULL; - - down(&start_stop_sem); - /* - * find a valid device which has been detected by the - * probe function of the usb - */ - index = -1; - for (i = 0; i < NUMUSBDUXFAST; i++) { - if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { - index = i; - break; - } - } - - if (index < 0) { - printk(KERN_ERR "comedi%d: usbduxfast: error: attach failed, " - "no usbduxfast devs connected to the usb bus.\n", - dev->minor); - up(&start_stop_sem); - return -ENODEV; - } + struct comedi_subdevice *s; - down(&(usbduxfastsub[index].sem)); + down(&udfs->sem); /* pointer back to the corresponding comedi device */ - usbduxfastsub[index].comedidev = dev; - + udfs->comedidev = dev; /* trying to upload the firmware into the chip */ - if (comedi_aux_data(it->options, 0) && - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { - firmwareUpload(&usbduxfastsub[index], - comedi_aux_data(it->options, 0), - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); - } - + if (aux_data) + firmwareUpload(udfs, aux_data, aux_len); dev->board_name = BOARDNAME; - ret = comedi_alloc_subdevices(dev, 1); if (ret) { - up(&(usbduxfastsub[index].sem)); - up(&start_stop_sem); + up(&udfs->sem); return ret; } - - printk(KERN_INFO "comedi%d: usbduxfast: usb-device %d is attached to " - "comedi.\n", dev->minor, index); /* private structure is also simply the usb-structure */ - dev->private = usbduxfastsub + index; + dev->private = udfs; /* the first subdevice is the A/D converter */ s = dev->subdevices + SUBDEV_AD; /* @@ -1703,16 +1667,76 @@ static int usbduxfast_attach(struct comedi_device *dev, s->maxdata = 0x1000; /* range table to convert to physical units */ s->range_table = &range_usbduxfast_ai_range; - /* finally decide that it's attached */ - usbduxfastsub[index].attached = 1; + udfs->attached = 1; + up(&udfs->sem); + dev_info(dev->class_dev, "successfully attached to usbduxfast.\n"); + return 0; +} + +/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ +static int usbduxfast_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + int ret; + int index; + int i; + void *aux_data; + int aux_len; - up(&(usbduxfastsub[index].sem)); + dev->private = NULL; + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data == NULL) + aux_len = 0; + else if (aux_len == 0) + aux_data = NULL; + down(&start_stop_sem); + /* + * find a valid device which has been detected by the + * probe function of the usb + */ + index = -1; + for (i = 0; i < NUMUSBDUXFAST; i++) { + if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { + index = i; + break; + } + } + if (index < 0) { + dev_err(dev->class_dev, + "usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n"); + ret = -ENODEV; + } else + ret = usbduxfast_attach_common(dev, &usbduxfastsub[index], + aux_data, aux_len); up(&start_stop_sem); - printk(KERN_INFO "comedi%d: successfully attached to usbduxfast.\n", - dev->minor); + return ret; +} - return 0; +/* is called from comedi_usb_auto_config() */ +static int usbduxfast_attach_usb(struct comedi_device *dev, + struct usb_interface *uinterf) +{ + int ret; + struct usbduxfastsub_s *udfs; + + dev->private = NULL; + down(&start_stop_sem); + udfs = usb_get_intfdata(uinterf); + if (!udfs || !udfs->probed) { + dev_err(dev->class_dev, + "usbduxfast: error: attach_usb failed, not connected\n"); + ret = -ENODEV; + } else if (udfs->attached) { + dev_err(dev->class_dev, + "usbduxfast: error: attach_usb failed, already attached\n"); + ret = -ENODEV; + } else + ret = usbduxfast_attach_common(dev, udfs, NULL, 0); + up(&start_stop_sem); + return ret; } static void usbduxfast_detach(struct comedi_device *dev) @@ -1737,7 +1761,8 @@ static struct comedi_driver driver_usbduxfast = { .driver_name = "usbduxfast", .module = THIS_MODULE, .attach = usbduxfast_attach, - .detach = usbduxfast_detach + .detach = usbduxfast_detach, + .attach_usb = usbduxfast_attach_usb, }; /* -- GitLab From f7d4d3bc0c5e30ac58e9e41c695852bfdcb8cb95 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 18 Jun 2012 17:36:58 +0100 Subject: [PATCH 0866/5711] staging: comedi: vmk80xx: use attach_usb() hook Change the vmv80xx driver to use the new attach_usb() hook in struct comedi_driver to auto-configure probed USB devices after the firmware is loaded. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/vmk80xx.c | 84 +++++++++++++----------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 69402dade14b..7d3cb3a035e6 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -1127,46 +1127,25 @@ static int vmk80xx_pwm_winsn(struct comedi_device *cdev, return n; } -static int vmk80xx_attach(struct comedi_device *cdev, - struct comedi_devconfig *it) +static int vmk80xx_attach_common(struct comedi_device *cdev, + struct vmk80xx_usb *dev) { - int i; - struct vmk80xx_usb *dev; int n_subd; struct comedi_subdevice *s; - int minor; int ret; - mutex_lock(&glb_mutex); - - for (i = 0; i < VMK80XX_MAX_BOARDS; i++) - if (vmb[i].probed && !vmb[i].attached) - break; - - if (i == VMK80XX_MAX_BOARDS) { - mutex_unlock(&glb_mutex); - return -ENODEV; - } - - dev = &vmb[i]; - down(&dev->limit_sem); - cdev->board_name = dev->board.name; cdev->private = dev; - if (dev->board.model == VMK8055_MODEL) n_subd = 5; else n_subd = 6; - ret = comedi_alloc_subdevices(cdev, n_subd); if (ret) { up(&dev->limit_sem); - mutex_unlock(&glb_mutex); return ret; } - /* Analog input subdevice */ s = cdev->subdevices + VMK80XX_SUBD_AI; s->type = COMEDI_SUBD_AI; @@ -1175,7 +1154,6 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = (1 << dev->board.ai_bits) - 1; s->range_table = dev->board.range; s->insn_read = vmk80xx_ai_rinsn; - /* Analog output subdevice */ s = cdev->subdevices + VMK80XX_SUBD_AO; s->type = COMEDI_SUBD_AO; @@ -1184,12 +1162,10 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = (1 << dev->board.ao_bits) - 1; s->range_table = dev->board.range; s->insn_write = vmk80xx_ao_winsn; - if (dev->board.model == VMK8061_MODEL) { s->subdev_flags |= SDF_READABLE; s->insn_read = vmk80xx_ao_rinsn; } - /* Digital input subdevice */ s = cdev->subdevices + VMK80XX_SUBD_DI; s->type = COMEDI_SUBD_DI; @@ -1198,7 +1174,6 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = 1; s->insn_read = vmk80xx_di_rinsn; s->insn_bits = vmk80xx_di_bits; - /* Digital output subdevice */ s = cdev->subdevices + VMK80XX_SUBD_DO; s->type = COMEDI_SUBD_DO; @@ -1207,12 +1182,10 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = 1; s->insn_write = vmk80xx_do_winsn; s->insn_bits = vmk80xx_do_bits; - if (dev->board.model == VMK8061_MODEL) { s->subdev_flags |= SDF_READABLE; s->insn_read = vmk80xx_do_rinsn; } - /* Counter subdevice */ s = cdev->subdevices + VMK80XX_SUBD_CNT; s->type = COMEDI_SUBD_COUNTER; @@ -1220,13 +1193,11 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->n_chan = dev->board.cnt_chans; s->insn_read = vmk80xx_cnt_rinsn; s->insn_config = vmk80xx_cnt_cinsn; - if (dev->board.model == VMK8055_MODEL) { s->subdev_flags |= SDF_WRITEABLE; s->maxdata = (1 << dev->board.cnt_bits) - 1; s->insn_write = vmk80xx_cnt_winsn; } - /* PWM subdevice */ if (dev->board.model == VMK8061_MODEL) { s = cdev->subdevices + VMK80XX_SUBD_PWM; @@ -1237,19 +1208,51 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->insn_read = vmk80xx_pwm_rinsn; s->insn_write = vmk80xx_pwm_winsn; } - dev->attached = 1; + dev_info(cdev->class_dev, "vmk80xx: board #%d [%s] attached\n", + dev->count, dev->board.name); + up(&dev->limit_sem); + return 0; +} - minor = cdev->minor; - - printk(KERN_INFO - "comedi%d: vmk80xx: board #%d [%s] attached to comedi\n", - minor, dev->count, dev->board.name); +/* called for COMEDI_DEVCONFIG ioctl for board_name "vmk80xx" */ +static int vmk80xx_attach(struct comedi_device *cdev, + struct comedi_devconfig *it) +{ + int i; + int ret; - up(&dev->limit_sem); + mutex_lock(&glb_mutex); + for (i = 0; i < VMK80XX_MAX_BOARDS; i++) + if (vmb[i].probed && !vmb[i].attached) + break; + if (i == VMK80XX_MAX_BOARDS) + ret = -ENODEV; + else + ret = vmk80xx_attach_common(cdev, &vmb[i]); mutex_unlock(&glb_mutex); + return ret; +} - return 0; +/* called via comedi_usb_auto_config() */ +static int vmk80xx_attach_usb(struct comedi_device *cdev, + struct usb_interface *intf) +{ + int i; + int ret; + + mutex_lock(&glb_mutex); + for (i = 0; i < VMK80XX_MAX_BOARDS; i++) + if (vmb[i].probed && vmb[i].intf == intf) + break; + if (i == VMK80XX_MAX_BOARDS) + ret = -ENODEV; + else if (vmb[i].attached) + ret = -EBUSY; + else + ret = vmk80xx_attach_common(cdev, &vmb[i]); + mutex_unlock(&glb_mutex); + return ret; } static void vmk80xx_detach(struct comedi_device *dev) @@ -1457,7 +1460,8 @@ static struct comedi_driver driver_vmk80xx = { .module = THIS_MODULE, .driver_name = "vmk80xx", .attach = vmk80xx_attach, - .detach = vmk80xx_detach + .detach = vmk80xx_detach, + .attach_usb = vmk80xx_attach_usb, }; static int __init vmk80xx_init(void) -- GitLab From 60ff46106744220506841c45f82576b9b56cf22e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 18 Jun 2012 16:35:54 +0100 Subject: [PATCH 0867/5711] staging: comedi: usbduxsigma: use attach_usb() hook Change the usbduxsigma driver to use the new attach_usb() hook in struct comedi_driver to auto-configure probed USB devices after the firmware is loaded. Move the release of the driver's static 'start_stop_sem' semaphore in usbduxsigma_attach() to occur a bit later for convenience, otherwise the new usbduxsigma_attach_common() would need to be split in two. I don't think the slight delay in releasing the semaphore matters too much; it's only used in the USB probe and disconnect functions and when attaching and detaching comedi devices. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 161 +++++++++++-------- 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 502a40948ebd..699deb16fa38 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2634,72 +2634,35 @@ static void usbduxsigma_disconnect(struct usb_interface *intf) dev_info(&intf->dev, "comedi_: disconnected from the usb\n"); } -/* is called when comedi-config is called */ -static int usbduxsigma_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +/* common part of attach and attach_usb */ +static int usbduxsigma_attach_common(struct comedi_device *dev, + struct usbduxsub *uds, + void *aux_data, int aux_len) { int ret; - int index; - int i; - struct usbduxsub *udev; + struct comedi_subdevice *s; int n_subdevs; - int offset; - struct comedi_subdevice *s = NULL; - dev->private = NULL; - - down(&start_stop_sem); - /* find a valid device which has been detected by the probe function of - * the usb */ - index = -1; - for (i = 0; i < NUMUSBDUX; i++) { - if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { - index = i; - break; - } - } - - if (index < 0) { - printk(KERN_ERR "comedi%d: usbduxsigma: error: attach failed," - "dev not connected to the usb bus.\n", dev->minor); - up(&start_stop_sem); - return -ENODEV; - } - - udev = &usbduxsub[index]; - down(&udev->sem); + down(&uds->sem); /* pointer back to the corresponding comedi device */ - udev->comedidev = dev; - + uds->comedidev = dev; /* trying to upload the firmware into the FX2 */ - if (comedi_aux_data(it->options, 0) && - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { - firmwareUpload(udev, comedi_aux_data(it->options, 0), - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); - } - + if (aux_data) + firmwareUpload(uds, aux_data, aux_len); dev->board_name = BOARDNAME; - /* set number of subdevices */ - if (udev->high_speed) { - /* with pwm */ - n_subdevs = 4; - } else { - /* without pwm */ - n_subdevs = 3; - } - + if (uds->high_speed) + n_subdevs = 4; /* with pwm */ + else + n_subdevs = 3; /* without pwm */ ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret) { - up(&udev->sem); - up(&start_stop_sem); + up(&uds->sem); return ret; } - /* private structure is also simply the usb-structure */ - dev->private = udev; - + dev->private = uds; /* the first subdevice is the A/D converter */ s = dev->subdevices + SUBDEV_AD; /* the URBs get the comedi subdevice */ @@ -2727,8 +2690,7 @@ static int usbduxsigma_attach(struct comedi_device *dev, s->maxdata = 0x00FFFFFF; /* range table to convert to physical units */ s->range_table = (&range_usbdux_ai_range); - - /* analog out */ + /* analog output subdevice */ s = dev->subdevices + SUBDEV_DA; /* analog out */ s->type = COMEDI_SUBD_AO; @@ -2753,8 +2715,7 @@ static int usbduxsigma_attach(struct comedi_device *dev, s->cancel = usbdux_ao_cancel; s->insn_read = usbdux_ao_insn_read; s->insn_write = usbdux_ao_insn_write; - - /* digital I/O */ + /* digital I/O subdevice */ s = dev->subdevices + SUBDEV_DIO; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -2766,37 +2727,94 @@ static int usbduxsigma_attach(struct comedi_device *dev, s->insn_config = usbdux_dio_insn_config; /* we don't use it */ s->private = NULL; - - if (udev->high_speed) { - /* timer / pwm */ + if (uds->high_speed) { + /* timer / pwm subdevice */ s = dev->subdevices + SUBDEV_PWM; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; /* this defines the max duty cycle resolution */ - s->maxdata = udev->sizePwmBuf; + s->maxdata = uds->sizePwmBuf; s->insn_write = usbdux_pwm_write; s->insn_read = usbdux_pwm_read; s->insn_config = usbdux_pwm_config; usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); } /* finally decide that it's attached */ - udev->attached = 1; + uds->attached = 1; + up(&uds->sem); + offset = usbdux_getstatusinfo(dev, 0); + if (offset < 0) + dev_err(&uds->interface->dev, + "Communication to USBDUXSIGMA failed! Check firmware and cabling."); + dev_info(&uds->interface->dev, + "comedi%d: attached, ADC_zero = %x\n", dev->minor, offset); + return 0; +} - up(&udev->sem); +/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ +static int usbduxsigma_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + int ret; + int index; + int i; + void *aux_data; + int aux_len; - up(&start_stop_sem); + dev->private = NULL; - offset = usbdux_getstatusinfo(dev, 0); - if (offset < 0) - dev_err(&udev->interface->dev, - "Communication to USBDUXSIGMA failed!" - "Check firmware and cabling."); + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data == NULL) + aux_len = 0; + else if (aux_len == 0) + aux_data = NULL; - dev_info(&udev->interface->dev, - "comedi%d: attached, ADC_zero = %x", dev->minor, offset); + down(&start_stop_sem); + /* find a valid device which has been detected by the probe function of + * the usb */ + index = -1; + for (i = 0; i < NUMUSBDUX; i++) { + if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { + index = i; + break; + } + } + if (index < 0) { + dev_err(dev->class_dev, + "usbduxsigma: error: attach failed, dev not connected to the usb bus.\n"); + up(&start_stop_sem); + ret = -ENODEV; + } else + ret = usbduxsigma_attach_common(dev, &usbduxsub[index], + aux_data, aux_len); + up(&start_stop_sem); + return ret; +} - return 0; +/* is called from comedi_usb_auto_config() */ +static int usbduxsigma_attach_usb(struct comedi_device *dev, + struct usb_interface *uinterf) +{ + int ret; + struct usbduxsub *uds; + + dev->private = NULL; + down(&start_stop_sem); + uds = usb_get_intfdata(uinterf); + if (!uds || !uds->probed) { + dev_err(dev->class_dev, + "usbduxsigma: error: attach_usb failed, not connected\n"); + ret = -ENODEV; + } else if (uds->attached) { + dev_err(dev->class_dev, + "usbduxsigma: error: attach_usb failed, already attached\n"); + ret = -ENODEV; + } else + ret = usbduxsigma_attach_common(dev, uds, NULL, 0); + up(&start_stop_sem); + return ret; } static void usbduxsigma_detach(struct comedi_device *dev) @@ -2818,6 +2836,7 @@ static struct comedi_driver driver_usbduxsigma = { .module = THIS_MODULE, .attach = usbduxsigma_attach, .detach = usbduxsigma_detach, + .attach_usb = usbduxsigma_attach_usb, }; /* Table with the USB-devices */ -- GitLab From 520706607befd1f5c20ec14db35d6be45791bc41 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 18 Jun 2012 11:18:25 -0700 Subject: [PATCH 0868/5711] staging: comedi: remove unneeded sanity check in insn_bits functions The comedi core does the sanity check to make sure that the data length the INSN_BITS instruction is 2. There is no need for the drivers to do this check. Remove all the sanity checks in the drivers. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 3 --- drivers/staging/comedi/drivers/acl7225b.c | 6 ------ drivers/staging/comedi/drivers/adl_pci6208.c | 2 -- drivers/staging/comedi/drivers/adl_pci7230.c | 6 ------ drivers/staging/comedi/drivers/adl_pci7432.c | 6 ------ drivers/staging/comedi/drivers/aio_iiro_16.c | 6 ------ drivers/staging/comedi/drivers/amplc_pc263.c | 3 --- drivers/staging/comedi/drivers/cb_das16_cs.c | 3 --- drivers/staging/comedi/drivers/comedi_bond.c | 2 -- drivers/staging/comedi/drivers/comedi_parport.c | 3 --- drivers/staging/comedi/drivers/contec_pci_dio.c | 6 ------ drivers/staging/comedi/drivers/dmm32at.c | 3 --- drivers/staging/comedi/drivers/dt2801.c | 2 -- drivers/staging/comedi/drivers/dt2811.c | 6 ------ drivers/staging/comedi/drivers/dt3000.c | 3 --- drivers/staging/comedi/drivers/dyna_pci10xx.c | 6 ------ drivers/staging/comedi/drivers/me4000.c | 11 ----------- drivers/staging/comedi/drivers/multiq3.c | 6 ------ drivers/staging/comedi/drivers/ni_6527.c | 8 -------- drivers/staging/comedi/drivers/ni_65xx.c | 6 +----- drivers/staging/comedi/drivers/ni_670x.c | 3 --- drivers/staging/comedi/drivers/ni_at_ao.c | 3 --- drivers/staging/comedi/drivers/ni_atmio16d.c | 3 --- drivers/staging/comedi/drivers/ni_mio_common.c | 9 ++------- drivers/staging/comedi/drivers/ni_pcidio.c | 2 -- drivers/staging/comedi/drivers/pcl711.c | 6 ------ drivers/staging/comedi/drivers/pcl725.c | 6 ------ drivers/staging/comedi/drivers/pcl726.c | 6 ------ drivers/staging/comedi/drivers/pcl730.c | 6 ------ drivers/staging/comedi/drivers/pcl812.c | 6 ------ drivers/staging/comedi/drivers/pcl818.c | 6 ------ drivers/staging/comedi/drivers/pcm3730.c | 4 ---- drivers/staging/comedi/drivers/pcmmio.c | 2 -- drivers/staging/comedi/drivers/pcmuio.c | 2 -- drivers/staging/comedi/drivers/poc.c | 5 ----- drivers/staging/comedi/drivers/rtd520.c | 3 --- drivers/staging/comedi/drivers/rti800.c | 5 ----- drivers/staging/comedi/drivers/s526.c | 3 --- drivers/staging/comedi/drivers/s626.c | 12 ------------ drivers/staging/comedi/drivers/skel.c | 3 --- drivers/staging/comedi/drivers/ssv_dnp.c | 4 ---- drivers/staging/comedi/drivers/usbdux.c | 3 --- drivers/staging/comedi/drivers/usbduxsigma.c | 3 --- 43 files changed, 3 insertions(+), 199 deletions(-) diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index e0de149c3c29..4c9977b8a5ae 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -139,9 +139,6 @@ static int subdev_8255_insn(struct comedi_device *dev, unsigned int bits; unsigned int v; - if (insn->n != 2) - return -EINVAL; - mask = data[0]; bits = data[1]; diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index 0bf552581c5f..ab765d3233e2 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -31,9 +31,6 @@ static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -53,9 +50,6 @@ static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + (unsigned long)s->private) | (inb(dev->iobase + (unsigned long)s->private + 1) << 8); diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 98b373063445..f0a5958d77b6 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -141,8 +141,6 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, * struct comedi_subdevice *s, */ /* struct comedi_insn *insn,unsigned int *data) */ /* { */ -/* if(insn->n!=2)return -EINVAL; */ - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ /* if(data[0]){ */ diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index 62fdf7f63703..d75734a03fb4 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -54,9 +54,6 @@ static int adl_pci7230_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -72,9 +69,6 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff; return 2; diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index aabf4183aaf5..b071a08b6159 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -57,9 +57,6 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev, printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n"); printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -79,9 +76,6 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n"); printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); - if (insn->n != 2) - return -EINVAL; - data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff; printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]); diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 8059cefe5b8c..34341078f654 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -70,9 +70,6 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; @@ -91,9 +88,6 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = 0; data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 4f15bfd80719..a018d8176aef 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -185,9 +185,6 @@ static int pc263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 77dc880ca786..515dda033e9a 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -549,9 +549,6 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 0260ddc05645..5ed324c4f620 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -133,8 +133,6 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, { #define LSAMPL_BITS (sizeof(unsigned int)*8) unsigned nchans = LSAMPL_BITS, num_done = 0, i; - if (insn->n != 2) - return -EINVAL; if (devpriv->nchans < nchans) nchans = devpriv->nchans; diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 589d12f68067..10c3c353f967 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -162,9 +162,6 @@ static int parport_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n < 1) - return -EINVAL; - data[1] = 0; return 2; } diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index d49561ff35ba..6aec9a6451b6 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -74,9 +74,6 @@ static int contec_do_insn_bits(struct comedi_device *dev, dev_dbg(dev->class_dev, "contec_do_insn_bits called\n"); dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; @@ -95,9 +92,6 @@ static int contec_di_insn_bits(struct comedi_device *dev, dev_dbg(dev->class_dev, "contec_di_insn_bits called\n"); dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); - if (insn->n != 2) - return -EINVAL; - data[1] = inw(dev->iobase + thisboard->in_offs); return 2; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 2b60cf816b6e..7cc9d20f3482 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -914,9 +914,6 @@ static int dmm32at_dio_insn_bits(struct comedi_device *dev, { unsigned char diobits; - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 5afbf8a4b030..d0bbbbb8816a 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -535,8 +535,6 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev, if (s == dev->subdevices + 4) which = 1; - if (insn->n != 2) - return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 91fbf4a7a2af..b239f381ad50 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -352,9 +352,6 @@ static int dt2811_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + DT2811_DIO); return 2; @@ -364,9 +361,6 @@ static int dt2811_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - s->state &= ~data[0]; s->state |= data[0] & data[1]; outb(s->state, dev->iobase + DT2811_DIO); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 31a16edc0a27..6acfe05ac569 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -745,9 +745,6 @@ static int dt3k_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[1] & data[0]; diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 9c855e25275c..78f3c8b4a0dc 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -189,9 +189,6 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev, { u16 d = 0; - if (insn->n != 2) - return -EINVAL; - mutex_lock(&devpriv->mutex); smp_mb(); d = inw_p(devpriv->BADR3); @@ -209,9 +206,6 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. * s->state contains the previous write data diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 72466bfa3b1d..631b4229201a 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1643,17 +1643,6 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - /* Length of data must be 2 (mask and new data, see below) */ - if (insn->n == 0) - return 0; - - if (insn->n != 2) { - printk - ("comedi%d: me4000: me4000_dio_insn_bits(): " - "Invalid instruction length\n", dev->minor); - return -EINVAL; - } - /* * The insn data consists of a mask in data[0] and the new data * in data[1]. The mask defines which bits we are concerning about. diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index b1bbd0255fbc..d1a8e9129b0f 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -161,9 +161,6 @@ static int multiq3_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inw(dev->iobase + MULTIQ3_DIGIN_PORT); return 2; @@ -173,9 +170,6 @@ static int multiq3_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - s->state &= ~data[0]; s->state |= (data[0] & data[1]); outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT); diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index b60ab4848b64..eec44a05af65 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -174,9 +174,6 @@ static int ni6527_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0)); data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8; data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16; @@ -188,8 +185,6 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -339,9 +334,6 @@ static int ni6527_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n < 1) - return -EINVAL; - data[1] = 0; return 2; } diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index ac7c74be08a2..f92f8ab30687 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -415,8 +415,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, const unsigned max_ports_per_bitfield = 5; unsigned read_bits = 0; unsigned j; - if (insn->n != 2) - return -EINVAL; + base_bitfield_channel = CR_CHAN(insn->chanspec); for (j = 0; j < max_ports_per_bitfield; ++j) { const unsigned port_offset = @@ -602,9 +601,6 @@ static int ni_65xx_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n < 1) - return -EINVAL; - data[1] = 0; return 2; } diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 5dffe6ce4738..b62b4271191e 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -306,9 +306,6 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 1c3f3222d496..28848bcc9375 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -239,9 +239,6 @@ static int atao_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 87992c99d413..54c039437b04 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -599,9 +599,6 @@ static int atmio16d_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] | data[1]); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1f796b9361b2..42df64ec921a 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3567,8 +3567,7 @@ static int ni_dio_insn_bits(struct comedi_device *dev, #ifdef DEBUG_DIO printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]); #endif - if (insn->n != 2) - return -EINVAL; + if (data[0]) { /* Perform check to make sure we're not using the serial part of the dio */ @@ -3629,8 +3628,7 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]); #endif - if (insn->n != 2) - return -EINVAL; + if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -5485,9 +5483,6 @@ static int ni_rtsi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = 0; return 2; diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index cba045965167..133ab2fd0377 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -745,8 +745,6 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index d5fa6f28eb1f..0df086a1a18d 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -449,9 +449,6 @@ static int pcl711_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + PCL711_DI_LO) | (inb(dev->iobase + PCL711_DI_HI) << 8); @@ -463,9 +460,6 @@ static int pcl711_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index 8edbefd7c43b..433ea05c3e91 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -23,9 +23,6 @@ Devices: [Advantech] PCL-725 (pcl725) static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -40,9 +37,6 @@ static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + PCL725_DI); return 2; diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index b2e73cda2957..dfff9af1951b 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -197,9 +197,6 @@ static int pcl726_di_insn_bits(struct comedi_device *dev, { const struct pcl726_board *board = comedi_board(dev); - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + board->di_lo) | (inb(dev->iobase + board->di_hi) << 8); @@ -212,9 +209,6 @@ static int pcl726_do_insn_bits(struct comedi_device *dev, { const struct pcl726_board *board = comedi_board(dev); - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 3cba79a219b8..d40caca42862 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -35,9 +35,6 @@ struct pcl730_board { static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -57,9 +54,6 @@ static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + ((unsigned long)s->private)) | (inb(dev->iobase + ((unsigned long)s->private) + 1) << 8); diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index b0eb2ab89fd8..1c146c879be9 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -501,9 +501,6 @@ static int pcl812_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + PCL812_DI_LO); data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8; @@ -517,9 +514,6 @@ static int pcl812_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 23b61d8aa404..13eaadfbaaab 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -442,9 +442,6 @@ static int pcl818_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + PCL818_DI_LO) | (inb(dev->iobase + PCL818_DI_HI) << 8); @@ -461,9 +458,6 @@ static int pcl818_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - s->state &= ~data[0]; s->state |= (data[0] & data[1]); diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index b48f7aa7520b..311fe2dc5386 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -32,8 +32,6 @@ static int pcm3730_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); @@ -48,8 +46,6 @@ static int pcm3730_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; data[1] = inb(dev->iobase + (unsigned long)(s->private)); return 2; } diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 0e64d848a2a8..a918cc087708 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -275,8 +275,6 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int byte_no; - if (insn->n != 2) - return -EINVAL; /* NOTE: reading a 0 means this channel was high diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 4426e1798ed5..33f740ee3524 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -211,8 +211,6 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int byte_no; - if (insn->n != 2) - return -EINVAL; /* NOTE: reading a 0 means this channel was high diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index a129ccace93d..a655b906164a 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -99,9 +99,6 @@ static int pcl733_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - data[1] = inb(dev->iobase + 0); data[1] |= (inb(dev->iobase + 1) << 8); data[1] |= (inb(dev->iobase + 2) << 16); @@ -114,8 +111,6 @@ static int pcl734_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index c3c8097acd02..6ff1fa0fd5de 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1811,9 +1811,6 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 966ac2ccc877..b6f219922a01 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -263,8 +263,6 @@ static int rti800_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; data[1] = inb(dev->iobase + RTI800_DI); return 2; } @@ -273,9 +271,6 @@ static int rti800_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 141bc9e881c9..b1dd22423704 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -678,9 +678,6 @@ static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 32e03bc247b3..182074c5f78b 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2140,18 +2140,6 @@ static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - - /* Length of data must be 2 (mask and new data, see below) */ - if (insn->n == 0) - return 0; - - if (insn->n != 2) { - printk - ("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", - dev->minor); - return -EINVAL; - } - /* * The insn data consists of a mask in data[0] and the new data in * data[1]. The mask defines which bits we are concerning about. diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 92d44c1d2587..67207de33906 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -561,9 +561,6 @@ static int skel_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - if (insn->n != 2) - return -EINVAL; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index b12bafe9baf6..f7bf3a2b9f31 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -77,10 +77,6 @@ static int dnp_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - - if (insn->n != 2) - return -EINVAL; /* insn uses data[0] and data[1] */ - /* The insn data is a mask in data[0] and the new data in data[1], */ /* each channel cooresponding to a bit. */ diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0386fd4a80ba..3185e1cdfb29 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1780,9 +1780,6 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, if (!this_usbduxsub) return -EFAULT; - if (insn->n != 2) - return -EINVAL; - down(&this_usbduxsub->sem); if (!(this_usbduxsub->probed)) { diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 699deb16fa38..a93cc5df2093 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1845,9 +1845,6 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, if (!this_usbduxsub) return -EFAULT; - if (insn->n != 2) - return -EINVAL; - down(&this_usbduxsub->sem); if (!(this_usbduxsub->probed)) { -- GitLab From a2714e3e42e746d6c8525c35fdcc58fb60c2830d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 18 Jun 2012 13:16:35 -0700 Subject: [PATCH 0869/5711] staging: comedi: fix return value for insn_bits functions The comedi_subdevice 'insn_bits' functions return the number of data elements used to perform the command. Most of the insn_bits functions return an open coded '2' to indicate this. The same value is available as 'insn->n'. Return that instead to better indicate what the return means. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/acl7225b.c | 4 ++-- drivers/staging/comedi/drivers/adl_pci6208.c | 2 +- drivers/staging/comedi/drivers/adl_pci7230.c | 4 ++-- drivers/staging/comedi/drivers/adl_pci7432.c | 4 ++-- drivers/staging/comedi/drivers/adl_pci9111.c | 4 ++-- drivers/staging/comedi/drivers/adl_pci9118.c | 4 ++-- drivers/staging/comedi/drivers/adq12b.c | 4 ++-- drivers/staging/comedi/drivers/adv_pci1710.c | 4 ++-- drivers/staging/comedi/drivers/adv_pci1723.c | 2 +- drivers/staging/comedi/drivers/adv_pci_dio.c | 12 ++++++------ drivers/staging/comedi/drivers/aio_iiro_16.c | 4 ++-- drivers/staging/comedi/drivers/amplc_dio200.c | 2 +- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- drivers/staging/comedi/drivers/amplc_pc263.c | 2 +- drivers/staging/comedi/drivers/cb_das16_cs.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas64.c | 6 +++--- drivers/staging/comedi/drivers/comedi_parport.c | 8 ++++---- drivers/staging/comedi/drivers/contec_pci_dio.c | 4 ++-- drivers/staging/comedi/drivers/das08.c | 8 ++++---- drivers/staging/comedi/drivers/das16.c | 4 ++-- drivers/staging/comedi/drivers/das16m1.c | 4 ++-- drivers/staging/comedi/drivers/das1800.c | 4 ++-- drivers/staging/comedi/drivers/das800.c | 4 ++-- drivers/staging/comedi/drivers/dmm32at.c | 2 +- drivers/staging/comedi/drivers/dt2801.c | 2 +- drivers/staging/comedi/drivers/dt2811.c | 4 ++-- drivers/staging/comedi/drivers/dt2817.c | 2 +- drivers/staging/comedi/drivers/dt282x.c | 2 +- drivers/staging/comedi/drivers/dt3000.c | 2 +- drivers/staging/comedi/drivers/dyna_pci10xx.c | 4 ++-- drivers/staging/comedi/drivers/icp_multi.c | 4 ++-- drivers/staging/comedi/drivers/ii_pci20kc.c | 2 +- drivers/staging/comedi/drivers/me4000.c | 2 +- drivers/staging/comedi/drivers/me_daq.c | 2 +- drivers/staging/comedi/drivers/mpc8260cpm.c | 2 +- drivers/staging/comedi/drivers/multiq3.c | 4 ++-- drivers/staging/comedi/drivers/ni_6527.c | 6 +++--- drivers/staging/comedi/drivers/ni_65xx.c | 2 +- drivers/staging/comedi/drivers/ni_660x.c | 2 +- drivers/staging/comedi/drivers/ni_670x.c | 2 +- drivers/staging/comedi/drivers/ni_at_ao.c | 2 +- drivers/staging/comedi/drivers/ni_atmio16d.c | 2 +- drivers/staging/comedi/drivers/ni_daq_700.c | 2 +- drivers/staging/comedi/drivers/ni_mio_common.c | 8 ++++---- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/pcl711.c | 4 ++-- drivers/staging/comedi/drivers/pcl725.c | 4 ++-- drivers/staging/comedi/drivers/pcl726.c | 4 ++-- drivers/staging/comedi/drivers/pcl730.c | 4 ++-- drivers/staging/comedi/drivers/pcl812.c | 4 ++-- drivers/staging/comedi/drivers/pcl818.c | 4 ++-- drivers/staging/comedi/drivers/pcm3730.c | 4 ++-- drivers/staging/comedi/drivers/pcmmio.c | 2 +- drivers/staging/comedi/drivers/pcmuio.c | 2 +- drivers/staging/comedi/drivers/poc.c | 4 ++-- drivers/staging/comedi/drivers/rtd520.c | 2 +- drivers/staging/comedi/drivers/rti800.c | 4 ++-- drivers/staging/comedi/drivers/s526.c | 2 +- drivers/staging/comedi/drivers/s626.c | 2 +- drivers/staging/comedi/drivers/skel.c | 2 +- drivers/staging/comedi/drivers/ssv_dnp.c | 2 +- drivers/staging/comedi/drivers/usbdux.c | 2 +- drivers/staging/comedi/drivers/usbduxsigma.c | 2 +- 63 files changed, 107 insertions(+), 107 deletions(-) diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index ab765d3233e2..ddba5db1e2e1 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -43,7 +43,7 @@ static int acl7225b_do_insn(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } static int acl7225b_di_insn(struct comedi_device *dev, @@ -53,7 +53,7 @@ static int acl7225b_di_insn(struct comedi_device *dev, data[1] = inb(dev->iobase + (unsigned long)s->private) | (inb(dev->iobase + (unsigned long)s->private + 1) << 8); - return 2; + return insn->n; } static int acl7225b_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index f0a5958d77b6..79f6765c46c1 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -157,7 +157,7 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, * it was a purely digital output subdevice */ /* data[1]=s->state; */ -/* return 2; */ +/* return insn->n; */ /* } */ /* static int pci6208_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index d75734a03fb4..cfb8bb055a02 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -61,7 +61,7 @@ static int adl_pci7230_do_insn_bits(struct comedi_device *dev, outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO); } - return 2; + return insn->n; } static int adl_pci7230_di_insn_bits(struct comedi_device *dev, @@ -71,7 +71,7 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev, { data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff; - return 2; + return insn->n; } static struct pci_dev *adl_pci7230_find_pci(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index b071a08b6159..10683c29276c 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -65,7 +65,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev, dev->iobase + PCI7432_DO); outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO); } - return 2; + return insn->n; } static int adl_pci7432_di_insn_bits(struct comedi_device *dev, @@ -79,7 +79,7 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff; printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]); - return 2; + return insn->n; } static struct pci_dev *adl_pci7432_find_pci(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 4f2cea8e11f7..c41cfc5c97ff 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1153,7 +1153,7 @@ static int pci9111_di_insn_bits(struct comedi_device *dev, bits = pci9111_di_get_bits(); data[1] = bits; - return 2; + return insn->n; } /* Digital outputs */ @@ -1179,7 +1179,7 @@ static int pci9111_do_insn_bits(struct comedi_device *dev, data[1] = bits; - return 2; + return insn->n; } /* ------------------------------------------------------------------ */ diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 9a7b6a5797bb..4482aabb3dcc 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -492,7 +492,7 @@ static int pci9118_insn_bits_di(struct comedi_device *dev, { data[1] = inl(dev->iobase + PCI9118_DI) & 0xf; - return 2; + return insn->n; } /* @@ -509,7 +509,7 @@ static int pci9118_insn_bits_do(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index f7bb14589c9b..6df51c8a602a 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -193,7 +193,7 @@ static int adq12b_di_insn_bits(struct comedi_device *dev, /* only bits 0-4 have information about digital inputs */ data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f)); - return 2; + return insn->n; } static int adq12b_do_insn_bits(struct comedi_device *dev, @@ -215,7 +215,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, data[1] = devpriv->digital_state; - return 2; + return insn->n; } static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 94d69e421c29..0ed1ff9217d5 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -435,7 +435,7 @@ static int pci171x_insn_bits_di(struct comedi_device *dev, { data[1] = inw(dev->iobase + PCI171x_DI); - return 2; + return insn->n; } /* @@ -452,7 +452,7 @@ static int pci171x_insn_bits_do(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index d37c14da5ec6..5c99c746d228 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -284,7 +284,7 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev, outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD); } data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); - return 2; + return insn->n; } static int pci1723_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 176a8016432d..ad653a5b8e2c 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -424,7 +424,7 @@ static int pci_dio_insn_bits_di_b(struct comedi_device *dev, data[1] |= inb(dev->iobase + d->addr + i) << (8 * i); - return 2; + return insn->n; } /* @@ -441,7 +441,7 @@ static int pci_dio_insn_bits_di_w(struct comedi_device *dev, for (i = 0; i < d->regs; i++) data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i); - return 2; + return insn->n; } /* @@ -463,7 +463,7 @@ static int pci_dio_insn_bits_do_b(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* @@ -485,7 +485,7 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* @@ -634,7 +634,7 @@ static int pci1760_insn_bits_di(struct comedi_device *dev, { data[1] = inb(dev->iobase + IMB3); - return 2; + return insn->n; } /* @@ -663,7 +663,7 @@ static int pci1760_insn_bits_do(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 34341078f654..16f28f65d292 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -80,7 +80,7 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, @@ -92,7 +92,7 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; - return 2; + return insn->n; } static int aio_iiro_16_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index c67b09ff37d7..55f30507e9e8 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -551,7 +551,7 @@ dio200_subdev_intr_insn_bits(struct comedi_device *dev, data[0] = 0; } - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index e55321ec5ae8..77dae8e956ca 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -293,7 +293,7 @@ static int pc236_intr_insn(struct comedi_device *dev, unsigned int *data) { data[1] = 0; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index a018d8176aef..e90178d29611 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -194,7 +194,7 @@ static int pc263_do_insn_bits(struct comedi_device *dev, outb(s->state & 0xFF, dev->iobase); outb(s->state >> 8, dev->iobase + 1); } - return 2; + return insn->n; } static void pc263_report_attach(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 515dda033e9a..6866e25543d1 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -560,7 +560,7 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev, * input and output lines. */ data[1] = inw(dev->iobase + 16); - return 2; + return insn->n; } static int das16cs_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 7aacff3292c2..11ce3fdff195 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -3617,7 +3617,7 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = bits; data[0] = 0; - return 2; + return insn->n; } static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, @@ -3633,7 +3633,7 @@ static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = s->state; - return 2; + return insn->n; } static int dio_60xx_config_insn(struct comedi_device *dev, @@ -3676,7 +3676,7 @@ static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = readb(priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG); - return 2; + return insn->n; } static void caldac_write(struct comedi_device *dev, unsigned int channel, diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 10c3c353f967..9a63cac2434a 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -110,7 +110,7 @@ static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = inb(dev->iobase + PARPORT_A); - return 2; + return insn->n; } static int parport_insn_config_a(struct comedi_device *dev, @@ -139,7 +139,7 @@ static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = (inb(dev->iobase + PARPORT_B) >> 3); - return 2; + return insn->n; } static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s, @@ -155,7 +155,7 @@ static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = devpriv->c_data & 0xf; - return 2; + return insn->n; } static int parport_intr_insn(struct comedi_device *dev, @@ -163,7 +163,7 @@ static int parport_intr_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { data[1] = 0; - return 2; + return insn->n; } static int parport_intr_cmdtest(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 6aec9a6451b6..ee769e00dc20 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -81,7 +81,7 @@ static int contec_do_insn_bits(struct comedi_device *dev, dev->iobase + thisboard->out_offs); outw(s->state, dev->iobase + thisboard->out_offs); } - return 2; + return insn->n; } static int contec_di_insn_bits(struct comedi_device *dev, @@ -94,7 +94,7 @@ static int contec_di_insn_bits(struct comedi_device *dev, data[1] = inw(dev->iobase + thisboard->in_offs); - return 2; + return insn->n; } static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c4627a6b62be..d0128e0e15cc 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -313,7 +313,7 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, data[0] = 0; data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS)); - return 2; + return insn->n; } static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, @@ -338,7 +338,7 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = wbits; - return 2; + return insn->n; } static int __maybe_unused @@ -348,7 +348,7 @@ das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, data[0] = 0; data[1] = inb(dev->iobase + DAS08JR_DIO); - return 2; + return insn->n; } static int __maybe_unused @@ -365,7 +365,7 @@ das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = devpriv->do_bits; - return 2; + return insn->n; } static int __maybe_unused diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 0c6ad1067055..895cc7783c9c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -812,7 +812,7 @@ static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = bits; data[0] = 0; - return 2; + return insn->n; } static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, @@ -832,7 +832,7 @@ static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, outb(s->state, dev->iobase + DAS16_DIO); - return 2; + return insn->n; } static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index f3fba13432bb..200926347861 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -428,7 +428,7 @@ static int das16m1_di_rbits(struct comedi_device *dev, data[1] = bits; data[0] = 0; - return 2; + return insn->n; } static int das16m1_do_wbits(struct comedi_device *dev, @@ -449,7 +449,7 @@ static int das16m1_do_wbits(struct comedi_device *dev, outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); - return 2; + return insn->n; } static void das16m1_handler(struct comedi_device *dev, unsigned int status) diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 365028772b00..25e7e56a376f 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1353,7 +1353,7 @@ static int das1800_di_rbits(struct comedi_device *dev, data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf; data[0] = 0; - return 2; + return insn->n; } /* writes to digital output channels */ @@ -1374,7 +1374,7 @@ static int das1800_do_wbits(struct comedi_device *dev, data[1] = devpriv->do_bits; - return 2; + return insn->n; } static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 917b31812b6c..a0959a5e8747 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -875,7 +875,7 @@ static int das800_di_rbits(struct comedi_device *dev, data[1] = bits; data[0] = 0; - return 2; + return insn->n; } static int das800_do_wbits(struct comedi_device *dev, @@ -899,7 +899,7 @@ static int das800_do_wbits(struct comedi_device *dev, data[1] = wbits; - return 2; + return insn->n; } /* loads counters with divisor1, divisor2 from private structure */ diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 7cc9d20f3482..af3531676e81 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -956,7 +956,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device *dev, * it was a purely digital output subdevice */ /* data[1]=s->state; */ - return 2; + return insn->n; } static int dmm32at_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index d0bbbbb8816a..d332269375ab 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -546,7 +546,7 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev, dt2801_writedata(dev, which); dt2801_readdata(dev, data + 1); - return 2; + return insn->n; } static int dt2801_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index b239f381ad50..290b933c5f96 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -354,7 +354,7 @@ static int dt2811_di_insn_bits(struct comedi_device *dev, { data[1] = inb(dev->iobase + DT2811_DIO); - return 2; + return insn->n; } static int dt2811_do_insn_bits(struct comedi_device *dev, @@ -367,7 +367,7 @@ static int dt2811_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 9282ca55f637..beba0447b3ee 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -119,7 +119,7 @@ static int dt2817_dio_insn_bits(struct comedi_device *dev, data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); - return 2; + return insn->n; } static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 9c0a0df7dff2..4af33431c380 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1038,7 +1038,7 @@ static int dt282x_dio_insn_bits(struct comedi_device *dev, } data[1] = inw(dev->iobase + DT2821_DIODAT); - return 2; + return insn->n; } static int dt282x_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 6acfe05ac569..d1d99a3e7491 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -752,7 +752,7 @@ static int dt3k_dio_insn_bits(struct comedi_device *dev, } data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); - return 2; + return insn->n; } static int dt3k_mem_insn_read(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 78f3c8b4a0dc..d0e3679ba2ad 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -198,7 +198,7 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev, data[1] = d; data[0] = s->state; mutex_unlock(&devpriv->mutex); - return 2; + return insn->n; } /* digital output bit interface */ @@ -226,7 +226,7 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev, */ data[1] = s->state; mutex_unlock(&devpriv->mutex); - return 2; + return insn->n; } /******************************************************************************/ diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 544bed870470..b10ebdbc1f7e 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -542,7 +542,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, { data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); - return 2; + return insn->n; } /* @@ -585,7 +585,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, #ifdef ICP_MULTI_EXTDEBUG printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_insn_bits_do(...)\n"); #endif - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index bea3d03bae2e..0f9cfe662b9a 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -565,7 +565,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev, data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; - return 2; + return insn->n; } static void pci20xxx_dio_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 631b4229201a..9a8258e6fa45 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1675,7 +1675,7 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) | ((inl(info->dio_context.port_3_reg) & 0xFF) << 24); - return 2; + return insn->n; } static int me4000_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index ae3b0469541e..1803d66cbf7d 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -331,7 +331,7 @@ static int me_dio_insn_bits(struct comedi_device *dev, data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16; } - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c index a6311b11831b..a7fda8f01e8c 100644 --- a/drivers/staging/comedi/drivers/mpc8260cpm.c +++ b/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -113,7 +113,7 @@ static int mpc8260cpm_dio_bits(struct comedi_device *dev, p = cpm_pdat((int)s->private); - return 2; + return insn->n; } static int mpc8260cpm_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index d1a8e9129b0f..eccbe1fb4f2c 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -163,7 +163,7 @@ static int multiq3_di_insn_bits(struct comedi_device *dev, { data[1] = inw(dev->iobase + MULTIQ3_DIGIN_PORT); - return 2; + return insn->n; } static int multiq3_do_insn_bits(struct comedi_device *dev, @@ -176,7 +176,7 @@ static int multiq3_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } static int multiq3_encoder_insn_read(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index eec44a05af65..a80c52fb2731 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -178,7 +178,7 @@ static int ni6527_di_insn_bits(struct comedi_device *dev, data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8; data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16; - return 2; + return insn->n; } static int ni6527_do_insn_bits(struct comedi_device *dev, @@ -206,7 +206,7 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } static irqreturn_t ni6527_interrupt(int irq, void *d) @@ -335,7 +335,7 @@ static int ni6527_intr_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { data[1] = 0; - return 2; + return insn->n; } static int ni6527_intr_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index f92f8ab30687..bce39f1ea36d 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -602,7 +602,7 @@ static int ni_65xx_intr_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { data[1] = 0; - return 2; + return insn->n; } static int ni_65xx_intr_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 5391a3949da1..5e863ff343dd 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1285,7 +1285,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device *dev, data[1] = (ni_660x_read_register(dev, 0, DIO32Input) >> base_bitfield_channel); - return 2; + return insn->n; } static void ni_660x_select_pfi_output(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index b62b4271191e..9032baccf3aa 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -319,7 +319,7 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev, * input lines. */ data[1] = readl(devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET); - return 2; + return insn->n; } static int ni_670x_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 28848bcc9375..62c8c44a8d28 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -247,7 +247,7 @@ static int atao_dio_insn_bits(struct comedi_device *dev, data[1] = inw(dev->iobase + ATAO_DIN); - return 2; + return insn->n; } static int atao_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 54c039437b04..2c78d3dd242a 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -606,7 +606,7 @@ static int atmio16d_dio_insn_bits(struct comedi_device *dev, } data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG); - return 2; + return insn->n; } static int atmio16d_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 53b0173aa2b2..4b42809d87a7 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -174,7 +174,7 @@ static int subdev_700_insn(struct comedi_device *dev, data[1] = s->state & 0xff; data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8; - return 2; + return insn->n; } static int subdev_700_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 42df64ec921a..cf0e0d147f8c 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3584,7 +3584,7 @@ static int ni_dio_insn_bits(struct comedi_device *dev, } data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register); - return 2; + return insn->n; } static int ni_m_series_dio_insn_config(struct comedi_device *dev, @@ -3636,7 +3636,7 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, } data[1] = ni_readl(M_Offset_Static_Digital_Input); - return 2; + return insn->n; } static int ni_cdio_cmdtest(struct comedi_device *dev, @@ -5394,7 +5394,7 @@ static int ni_pfi_insn_bits(struct comedi_device *dev, ni_writew(s->state, M_Offset_PFI_DO); } data[1] = ni_readw(M_Offset_PFI_DI); - return 2; + return insn->n; } static int ni_pfi_insn_config(struct comedi_device *dev, @@ -5485,7 +5485,7 @@ static int ni_rtsi_insn_bits(struct comedi_device *dev, { data[1] = 0; - return 2; + return insn->n; } /* Find best multiplier/divider to try and get the PLL running at 80 MHz diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 133ab2fd0377..0a55de968039 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -752,7 +752,7 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev, } data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0)); - return 2; + return insn->n; } static int ni_pcidio_cmdtest(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 0df086a1a18d..bb72d0bc2975 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -452,7 +452,7 @@ static int pcl711_di_insn_bits(struct comedi_device *dev, data[1] = inb(dev->iobase + PCL711_DI_LO) | (inb(dev->iobase + PCL711_DI_HI) << 8); - return 2; + return insn->n; } /* Digital port write - Untested on 8112 */ @@ -471,7 +471,7 @@ static int pcl711_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index 433ea05c3e91..d5b60cf7c93f 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -31,7 +31,7 @@ static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = s->state; - return 2; + return insn->n; } static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, @@ -39,7 +39,7 @@ static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, { data[1] = inb(dev->iobase + PCL725_DI); - return 2; + return insn->n; } static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index dfff9af1951b..2b10f1d83085 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -200,7 +200,7 @@ static int pcl726_di_insn_bits(struct comedi_device *dev, data[1] = inb(dev->iobase + board->di_lo) | (inb(dev->iobase + board->di_hi) << 8); - return 2; + return insn->n; } static int pcl726_do_insn_bits(struct comedi_device *dev, @@ -220,7 +220,7 @@ static int pcl726_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index d40caca42862..4675ec57082e 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -48,7 +48,7 @@ static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = s->state; - return 2; + return insn->n; } static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, @@ -57,7 +57,7 @@ static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, data[1] = inb(dev->iobase + ((unsigned long)s->private)) | (inb(dev->iobase + ((unsigned long)s->private) + 1) << 8); - return 2; + return insn->n; } static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 1c146c879be9..578fd8920be1 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -504,7 +504,7 @@ static int pcl812_di_insn_bits(struct comedi_device *dev, data[1] = inb(dev->iobase + PCL812_DI_LO); data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8; - return 2; + return insn->n; } /* @@ -522,7 +522,7 @@ static int pcl812_do_insn_bits(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 13eaadfbaaab..34169c16fb92 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -445,7 +445,7 @@ static int pcl818_di_insn_bits(struct comedi_device *dev, data[1] = inb(dev->iobase + PCL818_DI_LO) | (inb(dev->iobase + PCL818_DI_HI) << 8); - return 2; + return insn->n; } /* @@ -466,7 +466,7 @@ static int pcl818_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index 311fe2dc5386..d65e0bda2c44 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -39,7 +39,7 @@ static int pcm3730_do_insn_bits(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } static int pcm3730_di_insn_bits(struct comedi_device *dev, @@ -47,7 +47,7 @@ static int pcm3730_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { data[1] = inb(dev->iobase + (unsigned long)(s->private)); - return 2; + return insn->n; } static int pcm3730_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index a918cc087708..82a60d681eb4 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -344,7 +344,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, printk(KERN_DEBUG "s->state %08x data_out %08x\n", s->state, data[1]); #endif - return 2; + return insn->n; } /* The input or output configuration of each digital line is diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 33f740ee3524..feef3d02f35a 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -277,7 +277,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, data[1]); #endif - return 2; + return insn->n; } /* The input or output configuration of each digital line is diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index a655b906164a..c253bb9ef335 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -104,7 +104,7 @@ static int pcl733_insn_bits(struct comedi_device *dev, data[1] |= (inb(dev->iobase + 2) << 16); data[1] |= (inb(dev->iobase + 3) << 24); - return 2; + return insn->n; } static int pcl734_insn_bits(struct comedi_device *dev, @@ -125,7 +125,7 @@ static int pcl734_insn_bits(struct comedi_device *dev, } data[1] = s->state; - return 2; + return insn->n; } static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 6ff1fa0fd5de..cc1371daacd2 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1826,7 +1826,7 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */ - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index b6f219922a01..f7fa940d9783 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -264,7 +264,7 @@ static int rti800_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { data[1] = inb(dev->iobase + RTI800_DI); - return 2; + return insn->n; } static int rti800_do_insn_bits(struct comedi_device *dev, @@ -280,7 +280,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev, data[1] = s->state; - return 2; + return insn->n; } /* diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index b1dd22423704..358380f3eac5 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -694,7 +694,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev, * it was a purely digital output subdevice */ /* data[1]=s->state & 0xFF; */ - return 2; + return insn->n; } static int s526_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 182074c5f78b..d5edd9c091e6 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2160,7 +2160,7 @@ static int s626_dio_insn_bits(struct comedi_device *dev, } data[1] = DEBIread(dev, diopriv->RDDIn); - return 2; + return insn->n; } static int s626_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 67207de33906..6baac525f434 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -577,7 +577,7 @@ static int skel_dio_insn_bits(struct comedi_device *dev, * it was a purely digital output subdevice */ /* data[1]=s->state; */ - return 2; + return insn->n; } static int skel_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index f7bf3a2b9f31..72dbccc4427e 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -110,7 +110,7 @@ static int dnp_dio_insn_bits(struct comedi_device *dev, outb(PCDR, CSCIR); data[0] += ((inb(CSCDR) & 0xF0) << 12); - return 2; + return insn->n; } diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 3185e1cdfb29..83ee66965427 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1809,7 +1809,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]); up(&this_usbduxsub->sem); - return 2; + return insn->n; } /* reads the 4 counters, only two are used just now */ diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index a93cc5df2093..28f41e9cf682 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1884,7 +1884,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, s->state = data[1]; up(&this_usbduxsub->sem); - return 2; + return insn->n; } /***********************************/ -- GitLab From d4a7dc85289306d019378bac18fd88f35dc81b51 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 18 Jun 2012 14:45:42 -0700 Subject: [PATCH 0870/5711] staging: comedi: comedi_subdevice 'io_bits' should be an unsigned int The 'io_bits' variable in the comedi_subdevice struct is a bitmask of the input/output configuration of the the subdevice. It should be an unsigned int to correctly represent this. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess: Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index e0f3915b0f63..7363fd81cc7f 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -78,7 +78,7 @@ struct comedi_subdevice { unsigned runflags; spinlock_t spin_lock; - int io_bits; + unsigned int io_bits; unsigned int maxdata; /* if maxdata==0, use list */ const unsigned int *maxdata_list; /* list is channel specific */ -- GitLab From 560e8788eb659d9d301137eac1704ae1520d2fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:11:59 +0200 Subject: [PATCH 0871/5711] Staging: xgifb: reformat module parameter descriptions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 338227226260..8e0786d0ccf0 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2297,23 +2297,23 @@ static struct pci_driver xgifb_driver = { module_param(mode, charp, 0); MODULE_PARM_DESC(mode, - "\nSelects the desired default display mode in the format XxYxDepth,\n" - "eg. 1024x768x16.\n"); + "Selects the desired default display mode in the format XxYxDepth " + "(eg. 1024x768x16)."); module_param(forcecrt2type, charp, 0); MODULE_PARM_DESC(forcecrt2type, - "\nForce the second display output type. Possible values are NONE,\n" - "LCD, TV, VGA, SVIDEO or COMPOSITE.\n"); + "Force the second display output type. Possible values are NONE, " + "LCD, TV, VGA, SVIDEO or COMPOSITE."); module_param(vesa, int, 0); MODULE_PARM_DESC(vesa, - "\nSelects the desired default display mode by VESA mode number, eg.\n" - "0x117.\n"); + "Selects the desired default display mode by VESA mode number " + "(eg. 0x117)."); module_param(filter, int, 0); MODULE_PARM_DESC(filter, - "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" - "(Possible values 0-7, default: [no filter])\n"); + "Selects TV flicker filter type (only for systems with a SiS301 video bridge). " + "Possible values 0-7. Default: [no filter])."); static int __init xgifb_init(void) { -- GitLab From 67c0bf7ac72ebe7453ce822ca0d40e54fbbee52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:00 +0200 Subject: [PATCH 0872/5711] Staging: xgifb: remove DEBUGPRN() macro and its uses. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove DEBUGPRN() macro which is defined as empty. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 8e0786d0ccf0..143dd31298ba 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -117,12 +117,6 @@ static inline void dumpVGAReg(void) } #endif -#if 1 -#define DEBUGPRN(x) -#else -#define DEBUGPRN(x) pr_info(x "\n"); -#endif - /* --------------- Hardware Access Routines -------------------------- */ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, @@ -1054,7 +1048,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, int old_mode; /* unsigned char reg, reg1; */ - DEBUGPRN("Inside do_set_var"); /* printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres, var->upper_margin, var->lower_margin, var->vsync_len); */ info->var.xres_virtual = var->xres_virtual; @@ -1199,7 +1192,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } } XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/ - DEBUGPRN("End of do_set_var"); dumpVGAReg(); return 0; @@ -1321,7 +1313,6 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, { struct xgifb_video_info *xgifb_info = info->par; - DEBUGPRN("inside get_fix"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strncpy(fix->id, "XGI", sizeof(fix->id) - 1); @@ -1352,7 +1343,6 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, fix->mmio_len = xgifb_info->mmio_size; fix->accel = FB_ACCEL_SIS_XABRE; - DEBUGPRN("end of get_fix"); return 0; } @@ -1379,8 +1369,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) int found_mode = 0; int refresh_rate, search_idx; - DEBUGPRN("Inside check_var"); - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; @@ -1511,7 +1499,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->blue.msb_right = var->transp.offset = var->transp.length = var->transp.msb_right = 0; - DEBUGPRN("end of check_var"); return 0; } -- GitLab From d56b4c3dff9d1761bbd87746a0d92424960d2df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:01 +0200 Subject: [PATCH 0873/5711] Staging: xgifb: remove DPRINTK() macro and replace it with pr_debug. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 42 +++++++++++++---------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 143dd31298ba..9ffc85377c60 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -32,12 +32,6 @@ static unsigned int refresh_rate; #undef XGIFBDEBUG -#ifdef XGIFBDEBUG -#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - #ifdef XGIFBDEBUG static void dumpVGAReg(void) { @@ -662,8 +656,8 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, break; } else if (XGIfb_vrate[i].refresh > rate) { if ((XGIfb_vrate[i].refresh - rate) <= 3) { - DPRINTK("XGIfb: Adjusting rate from %d up to %d\n", - rate, XGIfb_vrate[i].refresh); + pr_debug("XGIfb: Adjusting rate from %d up to %d\n", + rate, XGIfb_vrate[i].refresh); xgifb_info->rate_idx = XGIfb_vrate[i].idx; xgifb_info->refresh_rate = @@ -671,8 +665,8 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, } else if (((rate - XGIfb_vrate[i - 1].refresh) <= 2) && (XGIfb_vrate[i].idx != 1)) { - DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", - rate, XGIfb_vrate[i-1].refresh); + pr_debug("XGIfb: Adjusting rate from %d down to %d\n", + rate, XGIfb_vrate[i-1].refresh); xgifb_info->rate_idx = XGIfb_vrate[i - 1].idx; xgifb_info->refresh_rate = @@ -680,8 +674,8 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, } break; } else if ((rate - XGIfb_vrate[i].refresh) <= 2) { - DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", - rate, XGIfb_vrate[i].refresh); + pr_debug("XGIfb: Adjusting rate from %d down to %d\n", + rate, XGIfb_vrate[i].refresh); xgifb_info->rate_idx = XGIfb_vrate[i].idx; break; } @@ -995,15 +989,15 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) } if ((filter >= 0) && (filter <= 7)) { - DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", - filter_tb, filter, - XGI_TV_filter[filter_tb]. + pr_debug("FilterTable[%d]-%d: %02x %02x %02x %02x\n", + filter_tb, filter, + XGI_TV_filter[filter_tb]. filter[filter][0], - XGI_TV_filter[filter_tb]. + XGI_TV_filter[filter_tb]. filter[filter][1], - XGI_TV_filter[filter_tb]. + XGI_TV_filter[filter_tb]. filter[filter][2], - XGI_TV_filter[filter_tb]. + XGI_TV_filter[filter_tb]. filter[filter][3] ); xgifb_reg_set( @@ -1064,7 +1058,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } if (!htotal || !vtotal) { - DPRINTK("XGIfb: Invalid 'var' information\n"); + pr_debug("XGIfb: Invalid 'var' information\n"); return -EINVAL; } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n", var->pixclock, htotal, vtotal); @@ -1140,11 +1134,11 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, XGIfb_post_setmode(xgifb_info); - DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n", - XGIbios_mode[xgifb_info->mode_idx].xres, - XGIbios_mode[xgifb_info->mode_idx].yres, - XGIbios_mode[xgifb_info->mode_idx].bpp, - xgifb_info->refresh_rate); + pr_debug("XGIfb: Set new mode: %dx%dx%d-%d\n", + XGIbios_mode[xgifb_info->mode_idx].xres, + XGIbios_mode[xgifb_info->mode_idx].yres, + XGIbios_mode[xgifb_info->mode_idx].bpp, + xgifb_info->refresh_rate); xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp; xgifb_info->video_vwidth = info->var.xres_virtual; -- GitLab From 96cd1f8b41c36c2520cc8b524734784a9e995ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:02 +0200 Subject: [PATCH 0874/5711] Staging: xgifb: define real dumpVGAReg() content only in DEBUG mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define real content of dumpVGAReg() only in debug mode. Remove old condition. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 9ffc85377c60..a45a497115ed 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -30,9 +30,7 @@ static unsigned int refresh_rate; /* -------------------- Macro definitions ---------------------------- */ -#undef XGIFBDEBUG - -#ifdef XGIFBDEBUG +#ifdef DEBUG static void dumpVGAReg(void) { u8 i, reg; -- GitLab From 47cee13d1dfe9867758c82a5ef93fd96629ceefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:03 +0200 Subject: [PATCH 0875/5711] Staging: xgifb: Remove XGIFAIL() macro and its calls. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XGIFAIL() prints a message and returns a value, but it's used only in one place. Better remove it and replace the call with the macro content. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main.h | 2 -- drivers/staging/xgifb/XGI_main_26.c | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index ce18f8c98b2d..be6bb7d0971e 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -4,8 +4,6 @@ #include "XGIfb.h" #include "vb_def.h" -#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) - #ifndef PCI_DEVICE_ID_XGI_42 #define PCI_DEVICE_ID_XGI_42 0x042 #endif diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index a45a497115ed..58cddb40f314 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1376,8 +1376,10 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; - if (!(htotal) || !(vtotal)) - XGIFAIL("XGIfb: no valid timing data"); + if (!(htotal) || !(vtotal)) { + pr_debug("XGIfb: no valid timing data\n"); + return -EINVAL; + } if (var->pixclock && htotal && vtotal) { drate = 1000000000 / var->pixclock; -- GitLab From 448810662ac3ba1c93c23a352a46d1f523f0b0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:04 +0200 Subject: [PATCH 0876/5711] Staging: xgifb: Remove printk usage. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace meaninful printks with pr_debug and remove useless ones. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 36 ++++++++-------------- drivers/staging/xgifb/vb_init.c | 47 ++--------------------------- 2 files changed, 15 insertions(+), 68 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 58cddb40f314..df6ef4686bbe 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -69,37 +69,37 @@ static void dumpVGAReg(void) for (i = 0; i < 0x4f; i++) { reg = xgifb_reg_get(XGISR, i); - printk("\no 3c4 %x", i); - printk("\ni 3c5 => %x", reg); + pr_debug("\no 3c4 %x", i); + pr_debug("\ni 3c5 => %x", reg); } for (i = 0; i < 0xF0; i++) { reg = xgifb_reg_get(XGICR, i); - printk("\no 3d4 %x", i); - printk("\ni 3d5 => %x", reg); + pr_debug("\no 3d4 %x", i); + pr_debug("\ni 3d5 => %x", reg); } /* xgifb_reg_set(XGIPART1,0x2F,1); for (i=1; i < 0x50; i++) { reg = xgifb_reg_get(XGIPART1, i); - printk("\no d004 %x", i); - printk("\ni d005 => %x", reg); + pr_debug("\no d004 %x", i); + pr_debug("\ni d005 => %x", reg); } for (i=0; i < 0x50; i++) { reg = xgifb_reg_get(XGIPART2, i); - printk("\no d010 %x", i); - printk("\ni d011 => %x", reg); + pr_debug("\no d010 %x", i); + pr_debug("\ni d011 => %x", reg); } for (i=0; i < 0x50; i++) { reg = xgifb_reg_get(XGIPART3, i); - printk("\no d012 %x",i); - printk("\ni d013 => %x",reg); + pr_debug("\no d012 %x",i); + pr_debug("\ni d013 => %x",reg); } for (i=0; i < 0x50; i++) { reg = xgifb_reg_get(XGIPART4, i); - printk("\no d014 %x",i); - printk("\ni d015 => %x",reg); + pr_debug("\no d014 %x",i); + pr_debug("\ni d015 => %x",reg); } */ } @@ -1040,8 +1040,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, int old_mode; /* unsigned char reg, reg1; */ - /* printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres, var->upper_margin, var->lower_margin, var->vsync_len); */ - info->var.xres_virtual = var->xres_virtual; info->var.yres_virtual = var->yres_virtual; info->var.bits_per_pixel = var->bits_per_pixel; @@ -1194,8 +1192,6 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) struct xgifb_video_info *xgifb_info = info->par; unsigned int base; - /* printk("Inside pan_var"); */ - base = var->yoffset * info->var.xres_virtual + var->xoffset; /* calculate base bpp dep. */ @@ -1229,7 +1225,6 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) 0x7F, ((base >> 24) & 0x01) << 7); } - /* printk("End of pan_var"); */ return 0; } @@ -1342,12 +1337,10 @@ static int XGIfb_set_par(struct fb_info *info) { int err; - /* printk("XGIfb: inside set_par\n"); */ err = XGIfb_do_set_var(&info->var, 1, info); if (err) return err; XGIfb_get_fix(&info->fix, -1, info); - /* printk("XGIfb: end of set_par\n"); */ return 0; } @@ -1501,8 +1494,6 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, { int err; - /* printk("\nInside pan_display:\n"); */ - if (var->xoffset > (info->var.xres_virtual - info->var.xres)) return -EINVAL; if (var->yoffset > (info->var.yres_virtual - info->var.yres)) @@ -1529,7 +1520,6 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, else info->var.vmode &= ~FB_VMODE_YWRAP; - /* printk("End of pan_display\n"); */ return 0; } @@ -1986,7 +1976,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, /* else if (reg >= 0xB0) { hw_info->ujVBChipID = VB_CHIP_301B; reg1 = xgifb_reg_get(XGIPART4, 0x23); - printk("XGIfb: XGI301B bridge detected\n"); + pr_debug("XGIfb: XGI301B bridge detected\n"); } */ else { hw_info->ujVBChipID = VB_CHIP_301; diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index a3d54b7f23c6..64d13117485a 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1318,22 +1318,17 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* Newdebugcode(0x99); */ if (pVBInfo->FBAddr == NULL) { - printk("\n pVBInfo->FBAddr == 0 "); + pr_debug("pVBInfo->FBAddr == 0\n"); return 0; } - printk("1"); if (pVBInfo->BaseAddr == 0) { - printk("\npVBInfo->BaseAddr == 0 "); + pr_debug("pVBInfo->BaseAddr == 0\n"); return 0; } - printk("2"); outb(0x67, (pVBInfo->BaseAddr + 0x12)); /* 3c2 <- 67 ,ynlai */ pVBInfo->ISXPDOS = 0; - printk("3"); - - printk("4"); /* VBIOSVersion[4] = 0x0; */ @@ -1356,7 +1351,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->Part3Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_12; pVBInfo->Part4Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14; pVBInfo->Part5Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14 + 2; - printk("5"); if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */ /* Run XGI_GetVBType before InitTo330Pointer */ @@ -1368,7 +1362,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* 1.Openkey */ xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86); - printk("6"); /* GetXG21Sense (GPIO) */ if (HwDeviceExtension->jChipType == XG21) @@ -1377,8 +1370,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) if (HwDeviceExtension->jChipType == XG27) XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo); - printk("7"); - /* 2.Reset Extended register */ for (i = 0x06; i < 0x20; i++) @@ -1390,11 +1381,8 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* for(i = 0x06; i <= 0x27; i++) */ /* xgifb_reg_set(pVBInfo->P3c4, i, 0); */ - printk("8"); - for (i = 0x31; i <= 0x3B; i++) xgifb_reg_set(pVBInfo->P3c4, i, 0); - printk("9"); /* [Hsuan] 2004/08/20 Auto over driver for XG42 */ if (HwDeviceExtension->jChipType == XG42) @@ -1406,8 +1394,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) for (i = 0x79; i <= 0x7C; i++) xgifb_reg_set(pVBInfo->P3d4, i, 0); /* shampoo 0208 */ - printk("10"); - if (HwDeviceExtension->jChipType >= XG20) xgifb_reg_set(pVBInfo->P3d4, 0x97, pVBInfo->XGINew_CR97); @@ -1416,8 +1402,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo); */ - printk("11"); - /* 4.SetDefExt1Regs begin */ xgifb_reg_set(pVBInfo->P3c4, 0x07, XGI330_SR07); if (HwDeviceExtension->jChipType == XG27) { @@ -1437,8 +1421,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* SR11 = 0x0F; */ /* xgifb_reg_set(pVBInfo->P3c4, 0x11, SR11); */ - printk("12"); - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ u32 Temp; @@ -1484,8 +1466,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) } */ - printk("13"); - /* Set AGP customize registers (in SetDefAGPRegs) Start */ for (i = 0x47; i <= 0x4C; i++) xgifb_reg_set(pVBInfo->P3d4, @@ -1514,14 +1494,12 @@ unsigned char XGIInitNew(struct pci_dev *pdev) if (Temp == 1) xgifb_reg_set(pVBInfo->P3d4, 0x48, 0x20); /* CR48 */ - printk("14"); } /* != XG20 */ /* Set PCI */ xgifb_reg_set(pVBInfo->P3c4, 0x23, XGI330_SR23); xgifb_reg_set(pVBInfo->P3c4, 0x24, XGI330_SR24); xgifb_reg_set(pVBInfo->P3c4, 0x25, XGI330_SR25); - printk("15"); if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ /* Set VB */ @@ -1536,8 +1514,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->Part1Port, 0x02, XGI330_CRT2Data_1_2); - printk("16"); - xgifb_reg_set(pVBInfo->Part1Port, 0x2E, 0x08); /* use VB */ } /* != XG20 */ @@ -1557,7 +1533,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->P3c4, 0x32, XGI330_SR32); } xgifb_reg_set(pVBInfo->P3c4, 0x33, XGI330_SR33); - printk("17"); /* SetPowerConsume (HwDeviceExtension, pVBInfo->P3c4); */ @@ -1578,18 +1553,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) XGI_LockCRT2(HwDeviceExtension, pVBInfo); } } /* != XG20 */ - printk("18"); - - printk("181"); - - printk("182"); XGI_SenseCRT1(pVBInfo); - printk("183"); /* XGINew_DetectMonitor(HwDeviceExtension); */ if (HwDeviceExtension->jChipType == XG21) { - printk("186"); xgifb_reg_and_or(pVBInfo->P3d4, 0x32, @@ -1597,7 +1565,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) Monitor1Sense); /* Z9 default has CRT */ temp = GetXG21FPBits(pVBInfo); xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x01, temp); - printk("187"); } if (HwDeviceExtension->jChipType == XG27) { @@ -1608,7 +1575,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) temp = GetXG27FPBits(pVBInfo); xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x03, temp); } - printk("19"); pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo); @@ -1616,11 +1582,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->P3d4, pVBInfo); - printk("20"); XGINew_SetDRAMSize_340(xgifb_info, HwDeviceExtension, pVBInfo); - printk("21"); - - printk("22"); /* SetDefExt2Regs begin */ /* @@ -1651,16 +1613,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21); - printk("23"); - XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo); XGINew_SetModeScratch(HwDeviceExtension, pVBInfo); - printk("24"); - xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87); xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x31); - printk("25"); return 1; } /* end of init */ -- GitLab From e054102b9fee7ef8cd1a10a8a6474f566e1c5631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:05 +0200 Subject: [PATCH 0877/5711] Staging: xgifb: Fix sparse warnings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add include files with function definitions to avoid sparse warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 1 + drivers/staging/xgifb/vb_setmode.c | 2 +- drivers/staging/xgifb/vb_util.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 64d13117485a..143957f82d6a 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -5,6 +5,7 @@ #include "vb_def.h" #include "vb_util.h" #include "vb_setmode.h" +#include "vb_init.h" static const unsigned short XGINew_DDRDRAM_TYPE340[4][2] = { { 16, 0x45}, { 8, 0x35}, diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index b1713d389794..479362eacb4f 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -4,7 +4,7 @@ #include "vb_def.h" #include "vb_util.h" #include "vb_table.h" - +#include "vb_setmode.h" #define IndexMask 0xff #define TVCLKBASE_315_25 (TVCLKBASE_315 + 25) diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c index 5c93a2202bd0..1b452f8b6274 100644 --- a/drivers/staging/xgifb/vb_util.c +++ b/drivers/staging/xgifb/vb_util.c @@ -1,4 +1,5 @@ #include "vgatypes.h" +#include "vb_util.h" void xgifb_reg_set(unsigned long port, u8 index, u8 data) { -- GitLab From 1918570388066fb15d591d9b9bf915dfc793aff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Mon, 18 Jun 2012 13:12:06 +0200 Subject: [PATCH 0878/5711] Staging: xgifb: Replace pr_* with dev_* when possible. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace pr_* calls with dev_* ones when the device structure is available. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 72 +++++++++++++++++------------ drivers/staging/xgifb/vb_init.c | 4 +- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index df6ef4686bbe..fe9061d37ce8 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1838,9 +1838,9 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->mmio_base = pci_resource_start(pdev, 1); xgifb_info->mmio_size = pci_resource_len(pdev, 1); xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30; - pr_info("Relocate IO address: %Lx [%08lx]\n", - (u64) pci_resource_start(pdev, 2), - xgifb_info->vga_base); + dev_info(&pdev->dev, "Relocate IO address: %Lx [%08lx]\n", + (u64) pci_resource_start(pdev, 2), + xgifb_info->vga_base); if (pci_enable_device(pdev)) { ret = -EIO; @@ -1858,7 +1858,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD); if (reg1 != 0xa1) { /*I/O error */ - pr_err("I/O error!!!"); + dev_err(&pdev->dev, "I/O error!!!"); ret = -EIO; goto error_disable; } @@ -1886,11 +1886,12 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, goto error_disable; } - pr_info("chipid = %x\n", xgifb_info->chip); + dev_info(&pdev->dev, "chipid = %x\n", xgifb_info->chip); hw_info->jChipType = xgifb_info->chip; if (XGIfb_get_dram_size(xgifb_info)) { - pr_err("Fatal error: Unable to determine RAM size.\n"); + dev_err(&pdev->dev, + "Fatal error: Unable to determine RAM size.\n"); ret = -ENODEV; goto error_disable; } @@ -1907,10 +1908,11 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (!request_mem_region(xgifb_info->video_base, xgifb_info->video_size, "XGIfb FB")) { - pr_err("unable request memory size %x\n", + dev_err(&pdev->dev, "unable request memory size %x\n", xgifb_info->video_size); - pr_err("Fatal error: Unable to reserve frame buffer memory\n"); - pr_err("Is there another framebuffer driver active?\n"); + dev_err(&pdev->dev, + "Fatal error: Unable to reserve frame buffer memory. " + "Is there another framebuffer driver active?\n"); ret = -ENODEV; goto error_disable; } @@ -1918,7 +1920,8 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (!request_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size, "XGIfb MMIO")) { - pr_err("Fatal error: Unable to reserve MMIO region\n"); + dev_err(&pdev->dev, + "Fatal error: Unable to reserve MMIO region\n"); ret = -ENODEV; goto error_0; } @@ -1928,18 +1931,20 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base, xgifb_info->mmio_size); - pr_info("Framebuffer at 0x%Lx, mapped to 0x%p, size %dk\n", - (u64) xgifb_info->video_base, - xgifb_info->video_vbase, - xgifb_info->video_size / 1024); + dev_info(&pdev->dev, + "Framebuffer at 0x%Lx, mapped to 0x%p, size %dk\n", + (u64) xgifb_info->video_base, + xgifb_info->video_vbase, + xgifb_info->video_size / 1024); - pr_info("MMIO at 0x%Lx, mapped to 0x%p, size %ldk\n", - (u64) xgifb_info->mmio_base, xgifb_info->mmio_vbase, - xgifb_info->mmio_size / 1024); + dev_info(&pdev->dev, + "MMIO at 0x%Lx, mapped to 0x%p, size %ldk\n", + (u64) xgifb_info->mmio_base, xgifb_info->mmio_vbase, + xgifb_info->mmio_size / 1024); pci_set_drvdata(pdev, xgifb_info); if (!XGIInitNew(pdev)) - pr_err("XGIInitNew() failed!\n"); + dev_err(&pdev->dev, "XGIInitNew() failed!\n"); xgifb_info->mtrr = (unsigned int) 0; @@ -1968,10 +1973,14 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg = xgifb_reg_get(XGIPART4, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; - pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); + dev_info(&pdev->dev, + "XGI302LV bridge detected (revision 0x%02x)\n", + reg); } else if (reg >= 0xD0) { hw_info->ujVBChipID = VB_CHIP_301LV; - pr_info("XGI301LV bridge detected (revision 0x%02x)\n", reg); + dev_info(&pdev->dev, + "XGI301LV bridge detected (revision 0x%02x)\n", + reg); } /* else if (reg >= 0xB0) { hw_info->ujVBChipID = VB_CHIP_301B; @@ -1980,17 +1989,21 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } */ else { hw_info->ujVBChipID = VB_CHIP_301; - pr_info("XGI301 bridge detected\n"); + dev_info(&pdev->dev, "XGI301 bridge detected\n"); } break; case HASVB_302: reg = xgifb_reg_get(XGIPART4, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; - pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); + dev_info(&pdev->dev, + "XGI302LV bridge detected (revision 0x%02x)\n", + reg); } else if (reg >= 0xD0) { hw_info->ujVBChipID = VB_CHIP_301LV; - pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); + dev_info(&pdev->dev, + "XGI302LV bridge detected (revision 0x%02x)\n", + reg); } else if (reg >= 0xB0) { reg1 = xgifb_reg_get(XGIPART4, 0x23); @@ -1998,27 +2011,28 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } else { hw_info->ujVBChipID = VB_CHIP_302; - pr_info("XGI302 bridge detected\n"); + dev_info(&pdev->dev, "XGI302 bridge detected\n"); } break; case HASVB_LVDS: hw_info->ulExternalChip = 0x1; - pr_info("LVDS transmitter detected\n"); + dev_info(&pdev->dev, "LVDS transmitter detected\n"); break; case HASVB_TRUMPION: hw_info->ulExternalChip = 0x2; - pr_info("Trumpion Zurac LVDS scaler detected\n"); + dev_info(&pdev->dev, "Trumpion Zurac LVDS scaler detected\n"); break; case HASVB_CHRONTEL: hw_info->ulExternalChip = 0x4; - pr_info("Chrontel TV encoder detected\n"); + dev_info(&pdev->dev, "Chrontel TV encoder detected\n"); break; case HASVB_LVDS_CHRONTEL: hw_info->ulExternalChip = 0x5; - pr_info("LVDS transmitter and Chrontel TV encoder detected\n"); + dev_info(&pdev->dev, + "LVDS transmitter and Chrontel TV encoder detected\n"); break; default: - pr_info("No or unknown bridge type detected\n"); + dev_info(&pdev->dev, "No or unknown bridge type detected\n"); break; } diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 143957f82d6a..7c555a7725fe 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1319,11 +1319,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) /* Newdebugcode(0x99); */ if (pVBInfo->FBAddr == NULL) { - pr_debug("pVBInfo->FBAddr == 0\n"); + dev_dbg(&pdev->dev, "pVBInfo->FBAddr == 0\n"); return 0; } if (pVBInfo->BaseAddr == 0) { - pr_debug("pVBInfo->BaseAddr == 0\n"); + dev_dbg(&pdev->dev, "pVBInfo->BaseAddr == 0\n"); return 0; } -- GitLab From 1351acce4fd25c6b7f007a92cc706e3fbd56479c Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 18 Jun 2012 07:42:23 -0700 Subject: [PATCH 0879/5711] staging: serqt_usb2: Fix some typos. Fixes some typos that was found while reading through staging/serqt_usb2 Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serqt_usb2/serqt_usb2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 43045db982d4..8a362f7af379 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -609,7 +609,7 @@ static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, /* * qt_setuart - * issuse a SET_UART vendor-spcific request on the default control pipe + * issues a SET_UART vendor-specific request on the default control pipe * If successful sets baud rate divisor and LCR value */ static int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number, @@ -1388,7 +1388,7 @@ static inline int qt_real_tiocmset(struct tty_struct *tty, return -ESPIPE; /* - * Turn off the RTS and DTR and loopbcck and then only turn on what was + * Turn off the RTS and DTR and loopback and then only turn on what was * asked for */ mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP); -- GitLab From 493b67b73c7f575058acec61903a2cb128207106 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 18 Jun 2012 07:42:24 -0700 Subject: [PATCH 0880/5711] staging: slicoss: Fix a typo. The below patch fixes a typo found while reading through staging/slicoss Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 77a0751a31ad..d2b82a78d2af 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -47,7 +47,7 @@ * Oasis cards (single and dual port PCI-x Gigabit) copper and fiber * Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber * - * The driver was acutally tested on Oasis and Kalahari cards. + * The driver was actually tested on Oasis and Kalahari cards. * * * NOTE: This is the standard, non-accelerated version of Alacritech's -- GitLab From f5b81ddd12da71bd00b2963203c23ff929e0c182 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:47 +0200 Subject: [PATCH 0881/5711] iio: iio_buffer_register: Skip channels with negative scan index It is not always the case that all channels can be used in buffered mode. This patch allows channels, which can not be used in buffered mode, to set their scan index to a negative number, which will cause iio_buffer_register to ignore the channel. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-buffer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 2f35db93cdb6..3d8d187eef2a 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -285,6 +285,9 @@ int iio_buffer_register(struct iio_dev *indio_dev, if (channels) { /* new magic */ for (i = 0; i < num_channels; i++) { + if (channels[i].scan_index < 0) + continue; + /* Establish necessary mask length */ if (channels[i].scan_index > (int)indio_dev->masklength - 1) -- GitLab From 23f2d735a932c7833d2d00da5e3ecdf4a6836210 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:48 +0200 Subject: [PATCH 0882/5711] iio: Add helper function for initializing triggered buffers Add a helper function for executing the common tasks which are usually involved in setting up a simple software ringbuffer. It will allocate the buffer, allocate the pollfunc and register the buffer. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/Kconfig | 7 ++ drivers/iio/Makefile | 1 + drivers/iio/industrialio-triggered-buffer.c | 110 ++++++++++++++++++++ include/linux/iio/triggered_buffer.h | 15 +++ 4 files changed, 133 insertions(+) create mode 100644 drivers/iio/industrialio-triggered-buffer.c create mode 100644 include/linux/iio/triggered_buffer.h diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 103349f2b3b5..612073f6c540 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -30,6 +30,13 @@ config IIO_KFIFO_BUF no buffer events so it is up to userspace to work out how often to read from the buffer. +config IIO_TRIGGERED_BUFFER + tristate + select IIO_TRIGGER + select IIO_KFIFO_BUF + help + Provides helper functions for setting up triggered buffers. + endif # IIO_BUFFER config IIO_TRIGGER diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index c38fa2a40af2..34309abb7979 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -7,6 +7,7 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o +obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o obj-y += adc/ diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c new file mode 100644 index 000000000000..46c619b0d8c5 --- /dev/null +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -0,0 +1,110 @@ + /* + * Copyright (c) 2012 Analog Devices, Inc. + * Author: Lars-Peter Clausen + * + * 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 + +static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { + .preenable = &iio_sw_buffer_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, +}; + +/** + * iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc + * @indio_dev: IIO device structure + * @pollfunc_bh: Function which will be used as pollfunc bottom half + * @pollfunc_th: Function which will be used as pollfunc top half + * @setup_ops: Buffer setup functions to use for this device. + * If NULL the default setup functions for triggered + * buffers will be used. + * + * This function combines some common tasks which will normally be performed + * when setting up a triggered buffer. It will allocate the buffer and the + * pollfunc, as well as register the buffer with the IIO core. + * + * Before calling this function the indio_dev structure should already be + * completely initialized, but not yet registered. In practice this means that + * this function should be called right before iio_device_register(). + * + * To free the resources allocated by this function call + * iio_triggered_buffer_cleanup(). + */ +int iio_triggered_buffer_setup(struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + const struct iio_buffer_setup_ops *setup_ops) +{ + int ret; + + indio_dev->buffer = iio_kfifo_allocate(indio_dev); + if (!indio_dev->buffer) { + ret = -ENOMEM; + goto error_ret; + } + + indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh, + pollfunc_th, + IRQF_ONESHOT, + indio_dev, + "%s_consumer%d", + indio_dev->name, + indio_dev->id); + if (indio_dev->pollfunc == NULL) { + ret = -ENOMEM; + goto error_kfifo_free; + } + + /* Ring buffer functions - here trigger setup related */ + if (setup_ops) + indio_dev->setup_ops = setup_ops; + else + indio_dev->setup_ops = &iio_triggered_buffer_setup_ops; + + /* Flag that polled ring buffering is possible */ + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); + if (ret) + goto error_dealloc_pollfunc; + + return 0; + +error_dealloc_pollfunc: + iio_dealloc_pollfunc(indio_dev->pollfunc); +error_kfifo_free: + iio_kfifo_free(indio_dev->buffer); +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_triggered_buffer_setup); + +/** + * iio_triggered_buffer_cleanup() - Free resources allocated by iio_triggered_buffer_setup() + * @indio_dev: IIO device structure + */ +void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) +{ + iio_buffer_unregister(indio_dev); + iio_dealloc_pollfunc(indio_dev->pollfunc); + iio_kfifo_free(indio_dev->buffer); +} +EXPORT_SYMBOL(iio_triggered_buffer_cleanup); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h new file mode 100644 index 000000000000..c378ebec605e --- /dev/null +++ b/include/linux/iio/triggered_buffer.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_IIO_TRIGGERED_BUFFER_H_ +#define _LINUX_IIO_TRIGGERED_BUFFER_H_ + +#include + +struct iio_dev; +struct iio_buffer_setup_ops; + +int iio_triggered_buffer_setup(struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + const struct iio_buffer_setup_ops *setup_ops); +void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev); + +#endif -- GitLab From 90032e4e9cc40e2933259190b670d70ddd149e68 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:49 +0200 Subject: [PATCH 0883/5711] iio:adc:at91: Use new triggered buffer setup helper Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Acked-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman --- drivers/iio/adc/Kconfig | 3 +-- drivers/iio/adc/at91_adc.c | 51 +++----------------------------------- 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 9a0df8123cc4..4f7f584cfd61 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -7,8 +7,7 @@ config AT91_ADC tristate "Atmel AT91 ADC" depends on ARCH_AT91 select IIO_BUFFER - select IIO_KFIFO_BUF - select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER select SYSFS help Say yes here to build support for Atmel AT91 ADC. diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f18a95d80255..6a084695b77e 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -26,9 +26,9 @@ #include #include -#include #include #include +#include #include @@ -318,58 +318,15 @@ static void at91_adc_trigger_remove(struct iio_dev *idev) } } -static const struct iio_buffer_setup_ops at91_adc_buffer_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - static int at91_adc_buffer_init(struct iio_dev *idev) { - int ret; - - idev->buffer = iio_kfifo_allocate(idev); - if (!idev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - - idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &at91_adc_trigger_handler, - IRQF_ONESHOT, - idev, - "%s-consumer%d", - idev->name, - idev->id); - if (idev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_pollfunc; - } - - idev->setup_ops = &at91_adc_buffer_ops; - idev->modes |= INDIO_BUFFER_TRIGGERED; - - ret = iio_buffer_register(idev, - idev->channels, - idev->num_channels); - if (ret) - goto error_register; - - return 0; - -error_register: - iio_dealloc_pollfunc(idev->pollfunc); -error_pollfunc: - iio_kfifo_free(idev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(idev, &iio_pollfunc_store_time, + &at91_adc_trigger_handler, NULL); } static void at91_adc_buffer_remove(struct iio_dev *idev) { - iio_buffer_unregister(idev); - iio_dealloc_pollfunc(idev->pollfunc); - iio_kfifo_free(idev->buffer); + iio_triggered_buffer_cleanup(idev); } static int at91_adc_read_raw(struct iio_dev *idev, -- GitLab From a648232dc5ed840c6dab0a949450ee4cdf5830bd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:50 +0200 Subject: [PATCH 0884/5711] staging:iio:adc:ad7192: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 3 +- drivers/staging/iio/adc/ad7192.c | 49 ++++---------------------------- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 8f1b3af02f29..7cdf421e76ee 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -136,8 +136,7 @@ config AD7192 tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver" depends on SPI select IIO_BUFFER - select IIO_KFIFO_BUF - select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices AD7190, AD7192 or AD7195 SPI analog to digital converters (ADC). diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 5eaeaf1f0ae8..839f17c4e33d 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include "ad7192.h" @@ -542,41 +542,13 @@ static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = { static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - int ret; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7192_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7192_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7192_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7192_trigger_handler, &ad7192_ring_setup_ops); } static void ad7192_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } /** @@ -1077,23 +1049,15 @@ static int __devinit ad7192_probe(struct spi_device *spi) if (ret) goto error_ring_cleanup; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_remove_trigger; - ret = ad7192_setup(st); if (ret) - goto error_unreg_ring; + goto error_remove_trigger; ret = iio_device_register(indio_dev); if (ret < 0) - goto error_unreg_ring; + goto error_remove_trigger; return 0; -error_unreg_ring: - iio_buffer_unregister(indio_dev); error_remove_trigger: ad7192_remove_trigger(indio_dev); error_ring_cleanup: @@ -1116,7 +1080,6 @@ static int ad7192_remove(struct spi_device *spi) struct ad7192_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7192_remove_trigger(indio_dev); ad7192_ring_cleanup(indio_dev); -- GitLab From d045b9d21b9591a4605590e7fe433f92d4b54762 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:51 +0200 Subject: [PATCH 0885/5711] staging:iio:adc:ad7298: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. The previous code was not passing the temperature channel to iio_buffer_register since the temperature channel can not be used in buffered mode. With the new helper functions it is not possible to do this, instead the scan index for the temperature channel is set to -1 which will cause iio_buffer_register to ignore the channel. (Also While we are at it also assign the symbolic constant instead of the raw value to the channel address for the temperature channel). Also as part of the conversion drop scan_timestamp being enabled by default, since it is a left over of an earlier cleanup. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 2 +- drivers/staging/iio/adc/ad7298.h | 5 +++ drivers/staging/iio/adc/ad7298_core.c | 15 ++----- drivers/staging/iio/adc/ad7298_ring.c | 64 +++++---------------------- 4 files changed, 20 insertions(+), 66 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 7cdf421e76ee..bb6fffd0d373 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -13,7 +13,7 @@ config AD7291 config AD7298 tristate "Analog Devices AD7298 ADC driver" depends on SPI - select IIO_KFIFO_BUF if IIO_BUFFER + select IIO_TRIGGERED_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices AD7298 8 Channel ADC with temperature sensor. diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h index 5051a7e4d4fd..18f278723002 100644 --- a/drivers/staging/iio/adc/ad7298.h +++ b/drivers/staging/iio/adc/ad7298.h @@ -55,6 +55,8 @@ struct ad7298_state { #ifdef CONFIG_IIO_BUFFER int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad7298_ring_cleanup(struct iio_dev *indio_dev); +int ad7298_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *active_scan_mask); #else /* CONFIG_IIO_BUFFER */ static inline int @@ -66,5 +68,8 @@ ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev) { } + +#define ad7298_update_scan_mode NULL + #endif /* CONFIG_IIO_BUFFER */ #endif /* IIO_ADC_AD7298_H_ */ diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index c90f2b3e661f..6141f4a70cfa 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -45,8 +45,8 @@ static struct iio_chan_spec ad7298_channels[] = { .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = 9, - .scan_index = AD7298_CH_TEMP, + .address = AD7298_CH_TEMP, + .scan_index = -1, .scan_type = { .sign = 's', .realbits = 32, @@ -171,6 +171,7 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, static const struct iio_info ad7298_info = { .read_raw = &ad7298_read_raw, + .update_scan_mode = ad7298_update_scan_mode, .driver_module = THIS_MODULE, }; @@ -231,19 +232,12 @@ static int __devinit ad7298_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, - &ad7298_channels[1], /* skip temp0 */ - ARRAY_SIZE(ad7298_channels) - 1); - if (ret) - goto error_cleanup_ring; ret = iio_device_register(indio_dev); if (ret) - goto error_unregister_ring; + goto error_cleanup_ring; return 0; -error_unregister_ring: - iio_buffer_unregister(indio_dev); error_cleanup_ring: ad7298_ring_cleanup(indio_dev); error_disable_reg: @@ -263,7 +257,6 @@ static int __devexit ad7298_remove(struct spi_device *spi) struct ad7298_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7298_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index 908a3e5609df..cd3e9cb47a64 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -13,37 +13,29 @@ #include #include -#include #include +#include #include "ad7298.h" /** - * ad7298_ring_preenable() setup the parameters of the ring before enabling - * - * The complex nature of the setting of the number of bytes per datum is due - * to this driver currently ensuring that the timestamp is stored at an 8 - * byte boundary. + * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask **/ -static int ad7298_ring_preenable(struct iio_dev *indio_dev) +int ad7298_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *active_scan_mask) { struct ad7298_state *st = iio_priv(indio_dev); int i, m; unsigned short command; - int scan_count, ret; - - ret = iio_sw_buffer_preenable(indio_dev); - if (ret < 0) - return ret; + int scan_count; /* Now compute overall size */ - scan_count = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); + scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength); command = AD7298_WRITE | st->ext_ref; for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1) - if (test_bit(i, indio_dev->active_scan_mask)) + if (test_bit(i, active_scan_mask)) command |= m; st->tx_buf[0] = cpu_to_be16(command); @@ -108,49 +100,13 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) return IRQ_HANDLED; } -static const struct iio_buffer_setup_ops ad7298_ring_setup_ops = { - .preenable = &ad7298_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - int ret; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &ad7298_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7298_consumer%d", - indio_dev->id); - - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7298_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, NULL, + &ad7298_trigger_handler, NULL); } void ad7298_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } -- GitLab From 397b85dd860db633e73fd5c1daf995431d5f6f7e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:52 +0200 Subject: [PATCH 0886/5711] staging:iio:adc:ad7476: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Also as part of the conversion drop scan_timestamp being enabled by default, since it is a left over of an earlier cleanup. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 3 +- drivers/staging/iio/adc/ad7476_core.c | 9 ------ drivers/staging/iio/adc/ad7476_ring.c | 46 +++------------------------ 3 files changed, 5 insertions(+), 53 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index bb6fffd0d373..c5f56511743c 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -73,8 +73,7 @@ config AD7476 tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver" depends on SPI select IIO_BUFFER - select IIO_KFIFO_BUF - select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495 diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index be1c260cf165..4d30a798ba0d 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -177,20 +177,12 @@ static int __devinit ad7476_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, - st->chip_info->channel, - ARRAY_SIZE(st->chip_info->channel)); - if (ret) - goto error_cleanup_ring; - ret = iio_device_register(indio_dev); if (ret) goto error_ring_unregister; return 0; error_ring_unregister: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: ad7476_ring_cleanup(indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) @@ -210,7 +202,6 @@ static int ad7476_remove(struct spi_device *spi) struct ad7476_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7476_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 383611b05764..10f8b8dd1fa4 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -15,8 +15,8 @@ #include #include -#include #include +#include #include "ad7476.h" @@ -52,51 +52,13 @@ done: return IRQ_HANDLED; } -static const struct iio_buffer_setup_ops ad7476_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - struct ad7476_state *st = iio_priv(indio_dev); - int ret = 0; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc - = iio_alloc_pollfunc(NULL, - &ad7476_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - spi_get_device_id(st->spi)->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7476_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, NULL, + &ad7476_trigger_handler, NULL); } void ad7476_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } -- GitLab From 74ed964931b1be634bce199ac854dc4ed76679b5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:53 +0200 Subject: [PATCH 0887/5711] staging:iio:adc:ad7606: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Also as part of the conversion drop scan_timestamp being enabled by default, since it is a left over of an earlier cleanup. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 3 +- drivers/staging/iio/adc/ad7606_core.c | 9 ------ drivers/staging/iio/adc/ad7606_ring.c | 46 +++------------------------ 3 files changed, 6 insertions(+), 52 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index c5f56511743c..ca4662750249 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -25,8 +25,7 @@ config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB select IIO_BUFFER - select IIO_TRIGGER - select IIO_KFIFO_BUF + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices: ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index a13afff2dfe6..ccb97fecdea7 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -533,20 +533,12 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) goto error_free_irq; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; ret = iio_device_register(indio_dev); if (ret) goto error_unregister_ring; return indio_dev; error_unregister_ring: - iio_buffer_unregister(indio_dev); - -error_cleanup_ring: ad7606_ring_cleanup(indio_dev); error_free_irq: @@ -571,7 +563,6 @@ int ad7606_remove(struct iio_dev *indio_dev, int irq) struct ad7606_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7606_ring_cleanup(indio_dev); free_irq(irq, indio_dev); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 24ce8fc71646..f15afe47c20d 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -13,8 +13,8 @@ #include #include -#include #include +#include #include "ad7606.h" @@ -91,54 +91,18 @@ done: kfree(buf); } -static const struct iio_buffer_setup_ops ad7606_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - int ret; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - - indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, - &ad7606_trigger_handler_th_bh, - 0, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - - indio_dev->setup_ops = &ad7606_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true; INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, + &ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, + NULL); } void ad7606_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } -- GitLab From 82796edca9ba014aa09cc158240c23b5b3f9326d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:54 +0200 Subject: [PATCH 0888/5711] staging:iio:adc:ad7793: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 3 +- drivers/staging/iio/adc/ad7793.c | 49 ++++---------------------------- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index ca4662750249..4fcc4be044ea 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -112,8 +112,7 @@ config AD7793 tristate "Analog Devices AD7792 AD7793 ADC driver" depends on SPI select IIO_BUFFER - select IIO_KFIFO_BUF - select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices AD7792 and AD7793 SPI analog to digital converters (ADC). diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index b36556fa2957..2bb9f68d66a4 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -21,9 +21,9 @@ #include #include #include -#include #include #include +#include #include "ad7793.h" @@ -407,41 +407,13 @@ static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = { static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - int ret; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7793_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7793_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7793_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7793_trigger_handler, &ad7793_ring_setup_ops); } static void ad7793_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } /** @@ -959,24 +931,16 @@ static int __devinit ad7793_probe(struct spi_device *spi) if (ret) goto error_unreg_ring; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_remove_trigger; - ret = ad7793_setup(st); if (ret) - goto error_uninitialize_ring; + goto error_remove_trigger; ret = iio_device_register(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_remove_trigger; return 0; -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); error_remove_trigger: ad7793_remove_trigger(indio_dev); error_unreg_ring: @@ -999,7 +963,6 @@ static int ad7793_remove(struct spi_device *spi) struct ad7793_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7793_remove_trigger(indio_dev); ad7793_ring_cleanup(indio_dev); -- GitLab From cc4dd03a6a9535cb2f731c5069e6a02781e3267a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:55 +0200 Subject: [PATCH 0889/5711] staging:iio:adc:ad7887: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 3 +-- drivers/staging/iio/adc/ad7887_core.c | 9 ------- drivers/staging/iio/adc/ad7887_ring.c | 35 +++------------------------ 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 4fcc4be044ea..e3fdb847de2c 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -86,8 +86,7 @@ config AD7887 tristate "Analog Devices AD7887 ADC driver" depends on SPI select IIO_BUFFER - select IIO_KFIFO_BUF - select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices AD7887 SPI analog to digital converter (ADC). diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 7186074deeb3..397b84947155 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -201,20 +201,12 @@ static int __devinit ad7887_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; - ret = iio_device_register(indio_dev); if (ret) goto error_unregister_ring; return 0; error_unregister_ring: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: ad7887_ring_cleanup(indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) @@ -233,7 +225,6 @@ static int ad7887_remove(struct spi_device *spi) struct ad7887_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7887_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index fd91384db894..1c406dad0e67 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -14,8 +14,8 @@ #include #include -#include #include +#include #include "ad7887.h" @@ -112,38 +112,11 @@ static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - int ret; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7887_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7887_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7887_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7887_trigger_handler, &ad7887_ring_setup_ops); } void ad7887_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } -- GitLab From ae3805c3aece38ee40ebc902a598b44a393902e1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 18 Jun 2012 18:33:56 +0200 Subject: [PATCH 0890/5711] staging:iio:adc:ad799x: Use new triggered buffer setup helper function Use the new triggered buffer setup helper function to allocate and register buffer and pollfunc. Also as part of the conversion drop scan_timestamp being enabled by default, since it is a left over of an earlier cleanup. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 2 +- drivers/staging/iio/adc/ad799x.h | 2 - drivers/staging/iio/adc/ad799x_core.c | 25 ++++++----- drivers/staging/iio/adc/ad799x_ring.c | 65 ++------------------------- 4 files changed, 20 insertions(+), 74 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index e3fdb847de2c..67711b7d718a 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -63,7 +63,7 @@ config AD799X_RING_BUFFER bool "Analog Devices AD799x: use ring buffer" depends on AD799X select IIO_BUFFER - select IIO_KFIFO_BUF + select IIO_TRIGGERED_BUFFER help Say yes here to include ring buffer support in the AD799X ADC driver. diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h index 99f8abe9731b..3e363c4ba211 100644 --- a/drivers/staging/iio/adc/ad799x.h +++ b/drivers/staging/iio/adc/ad799x.h @@ -120,8 +120,6 @@ struct ad799x_platform_data { u16 vref_mv; }; -int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask); - #ifdef CONFIG_AD799X_RING_BUFFER int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad799x_ring_cleanup(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 80e0c6e25a9b..2d4bda99eff7 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -99,10 +99,21 @@ static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data) return ret; } -int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask) +static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) { - return ad799x_i2c_write16(st, AD7998_CONF_REG, - st->config | (mask << AD799X_CHANNEL_SHIFT)); + struct ad799x_state *st = iio_priv(indio_dev); + + switch (st->id) { + case ad7997: + case ad7998: + return ad799x_i2c_write16(st, AD7998_CONF_REG, + st->config | (*scan_mask << AD799X_CHANNEL_SHIFT)); + default: + break; + } + + return 0; } static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) @@ -442,6 +453,7 @@ static const struct iio_info ad7993_4_7_8_info = { .read_event_value = &ad799x_read_event_value, .write_event_value = &ad799x_write_event_value, .driver_module = THIS_MODULE, + .update_scan_mode = ad7997_8_update_scan_mode, }; #define AD799X_EV_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \ @@ -887,12 +899,6 @@ static int __devinit ad799x_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; - if (client->irq > 0) { ret = request_threaded_irq(client->irq, NULL, @@ -934,7 +940,6 @@ static __devexit int ad799x_remove(struct i2c_client *client) if (client->irq > 0) free_irq(client->irq, indio_dev); - iio_buffer_unregister(indio_dev); ad799x_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 1c7ff4423db4..0882c9ef6572 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -18,32 +18,11 @@ #include #include -#include #include +#include #include "ad799x.h" -/** - * ad799x_ring_preenable() setup the parameters of the ring before enabling - * - * The complex nature of the setting of the number of bytes per datum is due - * to this driver currently ensuring that the timestamp is stored at an 8 - * byte boundary. - **/ -static int ad799x_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad799x_state *st = iio_priv(indio_dev); - /* - * Need to figure out the current mode based upon the requested - * scan mask in iio_dev - */ - - if (st->id == ad7997 || st->id == ad7998) - ad7997_8_set_scan_mode(st, *indio_dev->active_scan_mask); - - return iio_sw_buffer_preenable(indio_dev); -} - /** * ad799x_trigger_handler() bh of trigger launched polling to ring buffer * @@ -110,49 +89,13 @@ out: return IRQ_HANDLED; } -static const struct iio_buffer_setup_ops ad799x_buf_setup_ops = { - .preenable = &ad799x_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - int ret = 0; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &ad799x_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_kfifo; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad799x_buf_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_kfifo: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, NULL, + &ad799x_trigger_handler, NULL); } void ad799x_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } -- GitLab From 0941b9307e461570afe0378a410fb339936fad31 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:06 +0200 Subject: [PATCH 0891/5711] iio staging: fix typos in tsl*: register Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2583.c | 2 +- drivers/staging/iio/light/tsl2x7x_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 5e23ad5a30d5..6d2f4c659e56 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -410,7 +410,7 @@ static int taos_chip_on(struct iio_dev *indio_dev) return -EINVAL; } - /* determine als integration regster */ + /* determine als integration register */ als_count = (chip->taos_settings.als_time * 100 + 135) / 270; if (als_count == 0) als_count = 1; /* ensure at least one cycle */ diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 040da4acc66e..fdf75e45428c 100755 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -736,7 +736,7 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) return -EINVAL; } - /* determine als integration regster */ + /* determine als integration register */ als_count = (chip->tsl2x7x_settings.als_time * 100 + 135) / 270; if (als_count == 0) als_count = 1; /* ensure at least one cycle */ -- GitLab From 7695afdeb4dc6ae1ac7118c6ef9df7246f575923 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:05 +0200 Subject: [PATCH 0892/5711] iio staging: fix tsl2x7x file mode just drop execute permission Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 | 0 .../staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x | 0 drivers/staging/iio/light/tsl2x7x.h | 0 drivers/staging/iio/light/tsl2x7x_core.c | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 mode change 100755 => 100644 drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x mode change 100755 => 100644 drivers/staging/iio/light/tsl2x7x.h mode change 100755 => 100644 drivers/staging/iio/light/tsl2x7x_core.c diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 old mode 100755 new mode 100644 diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x old mode 100755 new mode 100644 diff --git a/drivers/staging/iio/light/tsl2x7x.h b/drivers/staging/iio/light/tsl2x7x.h old mode 100755 new mode 100644 diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c old mode 100755 new mode 100644 -- GitLab From 2a1d45ecc8cac79afe7f769f4241e4ad919c45bf Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:07 +0200 Subject: [PATCH 0893/5711] iio staging: fix spelling of suppression in isl29018 beware, does change the ABI as proximity_on_chip_ambient_infrared_supression is changed to proximity_on_chip_ambient_infrared_suppression Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Acked-by: Laxman Dewangan Signed-off-by: Greg Kroah-Hartman --- .../iio/Documentation/sysfs-bus-iio-light | 2 +- drivers/staging/iio/light/isl29018.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index 715c74dcb53a..d52be0385dc4 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -34,7 +34,7 @@ Description: it comes back in SI units, it should also include _input else it should include _raw to signify it is not in SI units. -What: /sys/.../device[n]/proximity_on_chip_ambient_infrared_supression +What: /sys/.../device[n]/proximity_on_chip_ambient_infrared_suppression KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 0abbf18d6103..31d22f5591ca 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -292,18 +292,18 @@ static ssize_t store_resolution(struct device *dev, } /* proximity scheme */ -static ssize_t show_prox_infrared_supression(struct device *dev, +static ssize_t show_prox_infrared_suppression(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 supression (1 means perform on chip supression) */ + infrared suppression (1 means perform on chip suppression) */ return sprintf(buf, "%d\n", chip->prox_scheme); } -static ssize_t store_prox_infrared_supression(struct device *dev, +static ssize_t store_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -318,7 +318,7 @@ static ssize_t store_prox_infrared_supression(struct device *dev, } /* get the "proximity scheme" i.e. if the chip does on chip - infrared supression (1 means perform on chip supression) */ + infrared suppression (1 means perform on chip suppression) */ mutex_lock(&chip->lock); chip->prox_scheme = (int)lval; mutex_unlock(&chip->lock); @@ -413,10 +413,10 @@ static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000"); static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16"); static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR, show_resolution, store_resolution, 0); -static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression, +static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, - show_prox_infrared_supression, - store_prox_infrared_supression, 0); + show_prox_infrared_suppression, + store_prox_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) @@ -425,7 +425,7 @@ static struct attribute *isl29018_attributes[] = { ISL29018_CONST_ATTR(range_available), ISL29018_DEV_ATTR(adc_resolution), ISL29018_CONST_ATTR(adc_resolution_available), - ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression), + ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), NULL }; -- GitLab From 9cc113bc84e683435c110268712d25aea05b8198 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:01 +0200 Subject: [PATCH 0894/5711] iio: typo in iio_chan_spec.ext_info comment Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index ae0cad908182..2afbb6f01afc 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -214,7 +214,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * @event_mask: What events can this channel produce. * @ext_info: Array of extended info attributes for this channel. * The array is NULL terminated, the last element should - * have it's name field set to NULL. + * have its name field set to NULL. * @extend_name: Allows labeling of channel attributes with an * informative name. Note this has no effect codes etc, * unlike modifiers. -- GitLab From b90406f1e5f4cb673e331ce6d435f4bdbf2136a2 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:02 +0200 Subject: [PATCH 0895/5711] iio: correct documentation for IIO_CONST_ATTR_SAMP_FREQ_AVAIL, match name of #define Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/sysfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h index bfedb73b850e..b7a934b9431b 100644 --- a/include/linux/iio/sysfs.h +++ b/include/linux/iio/sysfs.h @@ -97,7 +97,7 @@ struct iio_const_attr { #define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) /** - * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies + * IIO_CONST_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies * @_string: frequency string for the attribute * * Constant version -- GitLab From 19ea4752fc1f45c778ae66443c1023aced14ba05 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:03 +0200 Subject: [PATCH 0896/5711] iio: remove extra ; after function definition Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index fb0fe46fd659..ad4fb1af0f7d 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -184,7 +184,7 @@ static inline int iio_buffer_register(struct iio_dev *indio_dev, } static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{}; +{} #endif /* CONFIG_IIO_BUFFER */ -- GitLab From d163a19d915e9bb3dfa01abc251bc4d5395dc118 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 18 Jun 2012 20:33:04 +0200 Subject: [PATCH 0897/5711] iio staging: another typo in iio_simple_dummy_buffer Signed-off-by: Peter Meerwald Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_simple_dummy_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 3e43025f887d..fa4939caee6a 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -78,7 +78,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) i++) { j = find_next_bit(buffer->scan_mask, indio_dev->masklength, j + 1); - /* random access read form the 'device' */ + /* random access read from the 'device' */ data[i] = fakedata[j]; len += 2; } -- GitLab From 76728a93a70f23c6376c728e337fb26473737e7f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 18 Jun 2012 17:03:17 -0700 Subject: [PATCH 0898/5711] staging: comedi: pcmmio: quiet NULL pointer sparse noise The comedi_async 'inttrig' member is a pointer to a callback function. NULL should be used to clear it not 0. This quiets a number of sparse warnings about: Warning: Using plain integer as NULL pointer Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 82a60d681eb4..3d2e6f01c4b7 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -512,7 +512,7 @@ static void pcmmio_stop_intr(struct comedi_device *dev, subpriv->dio.intr.enabled_mask = 0; subpriv->dio.intr.active = 0; - s->async->inttrig = 0; + s->async->inttrig = NULL; nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT; firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT; switch_page(dev, asic, PAGE_ENAB); @@ -778,7 +778,7 @@ pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, return -EINVAL; spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); - s->async->inttrig = 0; + s->async->inttrig = NULL; if (subpriv->dio.intr.active) event = pcmmio_start_intr(dev, s); spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); -- GitLab From 55232eca66c540cbef9b950e71b358137651955b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 18 Jun 2012 16:53:17 -0700 Subject: [PATCH 0899/5711] staging: comedi: comedi_compat_ioctl should be NULL not 0 When CONFIG_COMPAT is not defined, comedi_compat_ioctl should be NULL not 0 in order to set the file_operations compat_ioctl variable correctly. This quiets a sparse warning about: warning: Using plain integer as NULL pointer Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Cc: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_compat32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 0340a8949c6b..c99573be046a 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -37,7 +37,7 @@ extern long comedi_compat_ioctl(struct file *file, unsigned int cmd, #else /* CONFIG_COMPAT */ -#define comedi_compat_ioctl 0 /* NULL */ +#define comedi_compat_ioctl NULL #endif /* CONFIG_COMPAT */ -- GitLab From efcf5bdac839f0dc9dc39ed1ad9fe2dbab49d00a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 28 May 2012 07:42:54 -0300 Subject: [PATCH 0900/5711] [media] V4L2 spec: clarify a few modulator issues Signed-off-by: Hans Verkuil Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/common.xml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml index 4101aeb56540..b91d25313b63 100644 --- a/Documentation/DocBook/media/v4l/common.xml +++ b/Documentation/DocBook/media/v4l/common.xml @@ -464,14 +464,14 @@ The type field of the respective tuner field contains the index number of the tuner. - Radio devices have exactly one tuner with index zero, no + Radio input devices have exactly one tuner with index zero, no video inputs. To query and change tuner properties applications use the &VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The &v4l2-tuner; returned by VIDIOC_G_TUNER also contains signal status information applicable when the tuner of the -current video input, or a radio tuner is queried. Note that +current video or radio input is queried. Note that VIDIOC_S_TUNER does not switch the current tuner, when there is more than one at all. The tuner is solely determined by the current video input. Drivers must support both ioctls and set the @@ -491,8 +491,17 @@ the modulator. The type field of the respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is set to V4L2_OUTPUT_TYPE_MODULATOR and its modulator field contains the index number -of the modulator. This specification does not define radio output -devices. +of the modulator. + + Radio output devices have exactly one modulator with index +zero, no video outputs. + + A video or radio device cannot support both a tuner and a +modulator. Two separate device nodes will have to be used for such +hardware, one that supports the tuner functionality and one that supports +the modulator functionality. The reason is a limitation with the +&VIDIOC-S-FREQUENCY; ioctl where you cannot specify whether the frequency +is for a tuner or a modulator. To query and change modulator properties applications use the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that -- GitLab From f7dd6c247f4318c47677a659dbb4622cc5da0690 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 31 May 2012 05:09:08 -0300 Subject: [PATCH 0901/5711] [media] V4L2 Spec: fix typo: NTSC -> NRSC Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/biblio.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/biblio.xml b/Documentation/DocBook/media/v4l/biblio.xml index 7c49facecd25..1078e45f189f 100644 --- a/Documentation/DocBook/media/v4l/biblio.xml +++ b/Documentation/DocBook/media/v4l/biblio.xml @@ -194,7 +194,7 @@ in the frequency range from 87,5 to 108,0 MHz National Radio Systems Committee (http://www.nrscstandards.org) - NTSC-4: United States RBDS Standard + NRSC-4: United States RBDS Standard -- GitLab From 629b15b95d5b12a47791147b7559eacbad04d507 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 18 Jun 2012 21:09:04 +0100 Subject: [PATCH 0902/5711] ASoC: wm5100: Remove stubs of ASoC-level register map code Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 3823af362912..f4817292ef45 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2378,13 +2378,6 @@ static int wm5100_remove(struct snd_soc_codec *codec) return 0; } -static int wm5100_soc_volatile(struct snd_soc_codec *codec, - unsigned int reg) -{ - return true; -} - - static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .probe = wm5100_probe, .remove = wm5100_remove, @@ -2392,8 +2385,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .set_sysclk = wm5100_set_sysclk, .set_pll = wm5100_set_fll, .idle_bias_off = 1, - .reg_cache_size = WM5100_MAX_REGISTER, - .volatile_register = wm5100_soc_volatile, .seq_notifier = wm5100_seq_notifier, .controls = wm5100_snd_controls, -- GitLab From 26ce171915f348abd1f41da1ed139d93750d987f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Jun 2012 08:52:33 -0500 Subject: [PATCH 0903/5711] libceph: fix NULL dereference in reset_connection() We dereference "con->in_msg" on the line after it was set to NULL. Signed-off-by: Dan Carpenter Reviewed-by: Alex Elder --- net/ceph/messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5e9f61d6d234..23073cff6481 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -440,7 +440,7 @@ static void reset_connection(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; - ceph_con_put(con->in_msg->con); + ceph_con_put(con); } con->connect_seq = 0; -- GitLab From 0b58a99eb27aa522a3cd16ece09c8045b322b9ce Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 18 Jun 2012 14:09:22 -0400 Subject: [PATCH 0904/5711] localmodconfig: Comments and cleanup for streamline_config.pl Added some more comments and cleaned up part of the the code to use a named variable instead of one of the special $1 perl variables. No functional changes. Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index bccf07ddd0b6..5c1ce8761205 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -186,6 +186,7 @@ sub read_kconfig { $state = "NEW"; $config = $2; + # Add depends for 'if' nesting for (my $i = 0; $i < $iflevel; $i++) { if ($i) { $depends{$config} .= " " . $ifdeps[$i]; @@ -204,10 +205,11 @@ sub read_kconfig { # Get the configs that select this config } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { - if (defined($selects{$1})) { - $selects{$1} .= " " . $config; + my $conf = $1; + if (defined($selects{$conf})) { + $selects{$conf} .= " " . $config; } else { - $selects{$1} = $config; + $selects{$conf} = $config; } # configs without prompts must be selected @@ -250,6 +252,7 @@ if ($kconfig) { read_kconfig($kconfig); } +# Makefiles can use variables to define their dependencies sub convert_vars { my ($line, %vars) = @_; @@ -293,6 +296,7 @@ foreach my $makefile (@makefiles) { my $objs; + # Convert variables in a line (could define configs) $_ = convert_vars($_, %make_vars); # collect objects after obj-$(CONFIG_FOO_BAR) @@ -373,7 +377,8 @@ while () { close (LIN); # add to the configs hash all configs that are needed to enable -# a loaded module. +# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o +# where we know we need bar.o so we add FOO to the list. my %configs; foreach my $module (keys(%modules)) { if (defined($objects{$module})) { -- GitLab From 4f4c51c9405a509e9073ff242746e9049c723aae Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 18 Jun 2012 21:43:53 -0400 Subject: [PATCH 0905/5711] localmodconfig: Read in orig config file to avoid extra processing Read in the entire config file. If there's a config that we depend on that happens to be in the core set (not a module) then we do not need to process it as a module. Currently, we follow the entire depend and selects even if they are enabled as core and not modules. By checking to make sure that we only look at modules we can drop the count a little. From one of my tests, localmodconfig went from taking 3095 set modules down to 356 before this patch, and down to 290 modules after the change. Tested-by: John David Yost # AlleyTrotter Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 5c1ce8761205..ab4985f7af79 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -113,6 +113,10 @@ sub find_config { find_config; +# Read in the entire config file into config_file +my @config_file = ; +close CIN; + # Parse options my $localmodconfig = 0; my $localyesconfig = 0; @@ -392,7 +396,20 @@ foreach my $module (keys(%modules)) { } } +# Read the current config, and see what is enabled. We want to +# ignore configs that we would not enable anyway. + +my %orig_configs; my $valid = "A-Za-z_0-9"; + +foreach my $line (@config_file) { + $_ = $line; + + if (/(CONFIG_[$valid]*)=(m|y)/) { + $orig_configs{$1} = $2; + } +} + my $repeat = 1; # @@ -414,6 +431,11 @@ sub parse_config_dep_select $p =~ s/^[^$valid]*[$valid]+//; + # We only need to process if the depend config is a module + if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + next; + } + if (!defined($configs{$conf})) { # We must make sure that this config has its # dependencies met. @@ -450,7 +472,8 @@ my %setconfigs; # Finally, read the .config file and turn off any module enabled that # we could not find a reason to keep enabled. -while() { +foreach my $line (@config_file) { + $_ = $line; if (/CONFIG_IKCONFIG/) { if (/# CONFIG_IKCONFIG is not set/) { @@ -478,7 +501,6 @@ while() { } print; } -close(CIN); # Integrity check, make sure all modules that we want enabled do # indeed have their configs set. -- GitLab From d4bb58b5cb3b6fbf89d0012c199be3954cba9fb3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 18 Jun 2012 22:22:33 -0400 Subject: [PATCH 0906/5711] localmodconfig: Check if configs are already set for selects There are some cases that a required module does not have a prompt and needs to have another module enabled that selects it to be set. As localmodconfig is conservative and tries to make the minimum config without breaking the user's kernel, or keeping the user from using devices that were loaded when the lsmod was done, all modules that select this module will also be enabled. If you needed module A, but module A did not have a prompt but needed module B to be selected, localmodconfig would make sure B was still enabled. If not only B selected A, but C, D, E, F, and G also selected A, then all of those would also be included, as well as the modules they depend on. This ballooned the number of configs that localmodconfig would keep. The fix here is to process the depends first, and then record those configs that did not have a prompt and needed to be selected. After the depends are done, check what configs are needed to select the configs in the list, and if a config that selects it is already set, then we don't need to do anything else. If no config that selects the config is set, then just pick one and try again. This change brought down the number of selected modules from 290 to 67! Both before and after were run against a config that had 3095 modules enabled. Tested-by: John David Yost # AlleyTrotter Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 115 ++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 11 deletions(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index ab4985f7af79..fcfcb302b0d7 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -420,7 +420,7 @@ my $repeat = 1; # to keep on. If A was on in the original config, B would not have been # and B would not be turned on by this script. # -sub parse_config_dep_select +sub parse_config_depends { my ($p) = @_; @@ -448,26 +448,119 @@ sub parse_config_dep_select } } -while ($repeat) { - $repeat = 0; +# Select is treated a bit differently than depends. We call this +# when a config has no prompt and requires another config to be +# selected. We use to just select all configs that selected this +# config, but found that that can balloon into enabling hundreds +# of configs that we do not care about. +# +# The idea is we look at all the configs that select it. If one +# is already in our list of configs to enable, then there's nothing +# else to do. If there isn't, we pick the first config that was +# enabled in the orignal config and use that. +sub parse_config_selects +{ + my ($config, $p) = @_; - foreach my $config (keys %configs) { - $config =~ s/^CONFIG_//; + my $next_config; + + while ($p =~ /[$valid]/) { + + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; - if (defined($depends{$config})) { - # This config has dependencies. Make sure they are also included - parse_config_dep_select $depends{$config}; + # Make sure that this config exists in the current .config file + if (!defined($orig_configs{$conf})) { + next; + } + + # Check if something other than a module selects this config + if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + # we are good with this + return; + } + if (defined($configs{$conf})) { + # A set config selects this config, we are good + return; + } + # Set this config to be selected + if (!defined($next_config)) { + $next_config = $conf; + } + } else { + die "this should never happen"; } + } - if (defined($prompts{$config}) || !defined($selects{$config})) { - next; + # If no possible config selected this, then something happened. + if (!defined($next_config)) { + print STDERR "WARNING: $config is required, but nothing in the\n"; + print STDERR " current config selects it.\n"; + return; + } + + # If we are here, then we found no config that is set and + # selects this config. Repeat. + $repeat = 1; + # Make this config need to be selected + $configs{$next_config} = 1; +} + +my %process_selects; + +# loop through all configs, select their dependencies. +sub loop_depend { + $repeat = 1; + + while ($repeat) { + $repeat = 0; + + forloop: + foreach my $config (keys %configs) { + + # If this config is not a module, we do not need to process it + if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { + next forloop; + } + + $config =~ s/^CONFIG_//; + + if (defined($depends{$config})) { + # This config has dependencies. Make sure they are also included + parse_config_depends $depends{$config}; + } + + # If the config has no prompt, then we need to check if a config + # that is enabled selected it. Or if we need to enable one. + if (!defined($prompts{$config}) && defined($selects{$config})) { + $process_selects{$config} = 1; + } } + } +} + +sub loop_select { + + foreach my $config (keys %process_selects) { + $config =~ s/^CONFIG_//; # config has no prompt and must be selected. - parse_config_dep_select $selects{$config}; + parse_config_selects $config, $selects{$config}; } } +while ($repeat) { + # Get the first set of configs and their dependencies. + loop_depend; + + $repeat = 0; + + # Now we need to see if we have to check selects; + loop_select; +} + my %setconfigs; # Finally, read the .config file and turn off any module enabled that -- GitLab From 4503379cb811809470ebefb58c943fe605bc3e29 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 18 Jun 2012 22:41:15 -0400 Subject: [PATCH 0907/5711] localmodconfig: Add debug environment variable LOCALMODCONFIG_DEBUG If the environment variable LOCALMODCONFIG_DEBUG is set, then debug output will appear in the make localmodconfig. This will simplify debugging what people get with their output, as I can just tell people to do: LOCALMODCONFIG_DEBUG=1 make localmodconfig 2>out.txt and have them send me the out.txt. I'll be able to see why things are not working as they think it should be. Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index fcfcb302b0d7..2fbbbc1ddea0 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -45,6 +45,16 @@ use strict; use Getopt::Long; +# set the environment variable LOCALMODCONFIG_DEBUG to get +# debug output. +my $debugprint = 0; +$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); + +sub dprint { + return if (!$debugprint); + print STDERR @_; +} + my $config = ".config"; my $uname = `uname -r`; @@ -389,6 +399,7 @@ foreach my $module (keys(%modules)) { my @arr = @{$objects{$module}}; foreach my $conf (@arr) { $configs{$conf} = $module; + dprint "$conf added by direct ($module)\n"; } } else { # Most likely, someone has a custom (binary?) module loaded. @@ -412,6 +423,8 @@ foreach my $line (@config_file) { my $repeat = 1; +my $depconfig; + # # Note, we do not care about operands (like: &&, ||, !) we want to add any # config that is in the depend list of another config. This script does @@ -440,6 +453,7 @@ sub parse_config_depends # We must make sure that this config has its # dependencies met. $repeat = 1; # do again + dprint "$conf selected by depend $depconfig\n"; $configs{$conf} = 1; } } else { @@ -473,15 +487,18 @@ sub parse_config_selects # Make sure that this config exists in the current .config file if (!defined($orig_configs{$conf})) { + dprint "$conf not set for $config select\n"; next; } # Check if something other than a module selects this config if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + dprint "$conf (non module) selects config, we are good\n"; # we are good with this return; } if (defined($configs{$conf})) { + dprint "$conf selects $config so we are good\n"; # A set config selects this config, we are good return; } @@ -506,6 +523,7 @@ sub parse_config_selects $repeat = 1; # Make this config need to be selected $configs{$next_config} = 1; + dprint "$next_config selected by select $config\n"; } my %process_selects; @@ -526,6 +544,7 @@ sub loop_depend { } $config =~ s/^CONFIG_//; + $depconfig = $config; if (defined($depends{$config})) { # This config has dependencies. Make sure they are also included @@ -546,6 +565,8 @@ sub loop_select { foreach my $config (keys %process_selects) { $config =~ s/^CONFIG_//; + dprint "Process select $config\n"; + # config has no prompt and must be selected. parse_config_selects $config, $selects{$config}; } -- GitLab From 15a4bc17b7f4e85cb019e683f14e834078ec2208 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 24 May 2012 09:47:38 -0700 Subject: [PATCH 0908/5711] Staging: add CSR Wifi "os helper" module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This module is used by the CSR wifi driver to "abstract" away the OS-specific parts of core functions. It will be eventually deleted, but for now is needed as the CSR driver relies on it. Cc: Mikko Virkkilä Cc: Lauri Hintsala Cc: Riku Mettälä Cc: Veli-Pekka Peltola Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/csr/Kconfig | 7 + drivers/staging/csr/Makefile | 1 + drivers/staging/csr/oska/Makefile | 12 ++ drivers/staging/csr/oska/all.h | 61 +++++++ drivers/staging/csr/oska/alloc.h | 41 +++++ drivers/staging/csr/oska/compat.c | 54 ++++++ drivers/staging/csr/oska/event.c | 82 ++++++++++ drivers/staging/csr/oska/event.h | 33 ++++ drivers/staging/csr/oska/io.h | 63 +++++++ drivers/staging/csr/oska/kernel-compat.h | 199 +++++++++++++++++++++++ drivers/staging/csr/oska/list.c | 103 ++++++++++++ drivers/staging/csr/oska/list.h | 115 +++++++++++++ drivers/staging/csr/oska/mutex.h | 42 +++++ drivers/staging/csr/oska/oska_module.c | 21 +++ drivers/staging/csr/oska/print.c | 44 +++++ drivers/staging/csr/oska/print.h | 32 ++++ drivers/staging/csr/oska/refcount.c | 47 ++++++ drivers/staging/csr/oska/refcount.h | 86 ++++++++++ drivers/staging/csr/oska/semaphore.h | 70 ++++++++ drivers/staging/csr/oska/spinlock.h | 43 +++++ drivers/staging/csr/oska/thread.c | 66 ++++++++ drivers/staging/csr/oska/thread.h | 39 +++++ drivers/staging/csr/oska/time.h | 34 ++++ drivers/staging/csr/oska/timer.c | 28 ++++ drivers/staging/csr/oska/timer.h | 40 +++++ drivers/staging/csr/oska/trace.h | 23 +++ drivers/staging/csr/oska/types.h | 14 ++ drivers/staging/csr/oska/util.h | 48 ++++++ 30 files changed, 1451 insertions(+) create mode 100644 drivers/staging/csr/Kconfig create mode 100644 drivers/staging/csr/Makefile create mode 100644 drivers/staging/csr/oska/Makefile create mode 100644 drivers/staging/csr/oska/all.h create mode 100644 drivers/staging/csr/oska/alloc.h create mode 100644 drivers/staging/csr/oska/compat.c create mode 100644 drivers/staging/csr/oska/event.c create mode 100644 drivers/staging/csr/oska/event.h create mode 100644 drivers/staging/csr/oska/io.h create mode 100644 drivers/staging/csr/oska/kernel-compat.h create mode 100644 drivers/staging/csr/oska/list.c create mode 100644 drivers/staging/csr/oska/list.h create mode 100644 drivers/staging/csr/oska/mutex.h create mode 100644 drivers/staging/csr/oska/oska_module.c create mode 100644 drivers/staging/csr/oska/print.c create mode 100644 drivers/staging/csr/oska/print.h create mode 100644 drivers/staging/csr/oska/refcount.c create mode 100644 drivers/staging/csr/oska/refcount.h create mode 100644 drivers/staging/csr/oska/semaphore.h create mode 100644 drivers/staging/csr/oska/spinlock.h create mode 100644 drivers/staging/csr/oska/thread.c create mode 100644 drivers/staging/csr/oska/thread.h create mode 100644 drivers/staging/csr/oska/time.h create mode 100644 drivers/staging/csr/oska/timer.c create mode 100644 drivers/staging/csr/oska/timer.h create mode 100644 drivers/staging/csr/oska/trace.h create mode 100644 drivers/staging/csr/oska/types.h create mode 100644 drivers/staging/csr/oska/util.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 38f1fb08eaef..d3934d79524a 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -132,4 +132,6 @@ source "drivers/staging/ipack/Kconfig" source "drivers/staging/gdm72xx/Kconfig" +source "drivers/staging/csr/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index e0c4c2444fed..5b2219ac5207 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_USB_G_CCG) += ccg/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ +obj-$(CONFIG_CSR_WIFI) += csr/ diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig new file mode 100644 index 000000000000..5d7b800058a3 --- /dev/null +++ b/drivers/staging/csr/Kconfig @@ -0,0 +1,7 @@ +config CSR_WIFI + tristate "CSR wireless driver" + depends on PCI + help + Driver for the CSR wireless SDIO device. + + If unsure, select N. diff --git a/drivers/staging/csr/Makefile b/drivers/staging/csr/Makefile new file mode 100644 index 000000000000..b9ba3b378e65 --- /dev/null +++ b/drivers/staging/csr/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CSR_WIFI) += oska/ diff --git a/drivers/staging/csr/oska/Makefile b/drivers/staging/csr/oska/Makefile new file mode 100644 index 000000000000..3a0b648ddebc --- /dev/null +++ b/drivers/staging/csr/oska/Makefile @@ -0,0 +1,12 @@ +obj-$(CONFIG_CSR_WIFI) := csr_oska.o + +csr_oska-y := \ + list.o \ + refcount.o \ + compat.o \ + event.o \ + oska_module.o \ + print.o \ + thread.o \ + timer.o + diff --git a/drivers/staging/csr/oska/all.h b/drivers/staging/csr/oska/all.h new file mode 100644 index 000000000000..5fe85834894b --- /dev/null +++ b/drivers/staging/csr/oska/all.h @@ -0,0 +1,61 @@ +/* + * Operating system kernel abstraction -- all functions + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_ALL_H +#define __OSKA_ALL_H + +/** + * @mainpage Operating System Kernel Abstraction + * + * @section intro Introduction + * + * The Operating System Kernel Abstraction (oska) is a software + * package providing an abstraction for various operating system + * kernel facilities for use by device drivers and other OS kernel + * software (e.g., SDIO stacks). Oska is modularized and intended to + * be a lightweight wrapper around an OSes interfaces. + * + * @section modules Modules + * + * Oska is organized into the modules, each of which has it's own + * header file providing the interface. + * + * - \ref alloc "Memory allocation" + * - \ref event "Events" + * - \ref mutex "Mutexes" + * - \ref print "Console output" + * - \ref spinlock "Spinlocks" + * - \ref thread "Threading" + * - \ref time "Timing and delays" + * - \ref timer "Timers" + * - \ref types "Standard Types" + * - \ref util "Miscellaneous utilities" + * + * An header is provided which includes all the above + * modules. + * + * There are additional modules that are not included in . + * + * - \ref io "Memory mapped I/O" + * - \ref refcount "Reference Counting" + * - \ref list "Linked lists" + * - \ref trace "Tracing messages" + */ + +#include "alloc.h" +#include "event.h" +#include "mutex.h" +#include "print.h" +#include "spinlock.h" +#include "thread.h" +#include "time.h" +#include "timer.h" +#include "types.h" +#include "util.h" + +#endif /* __OSKA_ALL_H */ diff --git a/drivers/staging/csr/oska/alloc.h b/drivers/staging/csr/oska/alloc.h new file mode 100644 index 000000000000..0f106016e1f7 --- /dev/null +++ b/drivers/staging/csr/oska/alloc.h @@ -0,0 +1,41 @@ +/* + * OSKA Linux implementation -- memory allocation + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_ALLOC_H +#define __OSKA_LINUX_ALLOC_H + +#include +#include +#include + +static inline void *os_alloc(size_t size) +{ + return kzalloc(size, GFP_ATOMIC); +} + +static inline void *os_alloc_nonzeroed(size_t size) +{ + return kmalloc(size, GFP_KERNEL); +} + +static inline void os_free(void *ptr) +{ + kfree(ptr); +} + +static inline void *os_alloc_big(size_t size) +{ + return vmalloc(size); +} + +static inline void os_free_big(void *ptr) +{ + vfree(ptr); +} + +#endif /* #ifndef __OSKA_LINUX_ALLOC_H */ diff --git a/drivers/staging/csr/oska/compat.c b/drivers/staging/csr/oska/compat.c new file mode 100644 index 000000000000..790b97a7d5f9 --- /dev/null +++ b/drivers/staging/csr/oska/compat.c @@ -0,0 +1,54 @@ +/* + * Linux version compatibility functions. + * + * Copyright (C) 2008 Cambridge Silicon Radio 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. + * + * 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, see . + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include "kernel-compat.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + +int dev_set_name(struct device *dev, const char *fmt, ...) +{ + va_list vargs; + + va_start(vargs, fmt); + vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); + va_end(vargs); + return 0; +} +EXPORT_SYMBOL_GPL(dev_set_name); + +#endif /* Linux kernel < 2.6.26 */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +struct device *class_find_device(struct class *class, struct device *start, + void *data, int (*match)(struct device *, void *)) +{ + struct device *dev; + + list_for_each_entry(dev, &class->devices, node) { + if (match(dev, data)) { + get_device(dev); + return dev; + } + } + return NULL; +} +EXPORT_SYMBOL_GPL(class_find_device); + +#endif /* Linux kernel < 2.6.25 */ diff --git a/drivers/staging/csr/oska/event.c b/drivers/staging/csr/oska/event.c new file mode 100644 index 000000000000..4aedaaa0d9e4 --- /dev/null +++ b/drivers/staging/csr/oska/event.c @@ -0,0 +1,82 @@ +/* + * Linux event functions. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include +#include + +#include "event.h" + +void os_event_init(os_event_t *evt) +{ + init_waitqueue_head(&evt->wq); + spin_lock_init(&evt->lock); + evt->events = 0; +} +EXPORT_SYMBOL(os_event_init); + +uint16_t os_event_wait(os_event_t *evt) +{ + uint16_t e; + unsigned long flags; + + wait_event(evt->wq, evt->events != 0); + + spin_lock_irqsave(&evt->lock, flags); + e = evt->events; + evt->events &= ~e; + spin_unlock_irqrestore(&evt->lock, flags); + + return e; +} +EXPORT_SYMBOL(os_event_wait); + +uint16_t os_event_wait_interruptible(os_event_t *evt) +{ + uint16_t e; + unsigned long flags; + + wait_event_interruptible(evt->wq, evt->events != 0); + + spin_lock_irqsave(&evt->lock, flags); + e = evt->events; + evt->events &= ~e; + spin_unlock_irqrestore(&evt->lock, flags); + + return e; +} +EXPORT_SYMBOL(os_event_wait_interruptible); + +uint16_t os_event_wait_timed(os_event_t *evt, unsigned timeout_ms) +{ + uint16_t e; + unsigned long flags; + + wait_event_interruptible_timeout(evt->wq, + evt->events != 0, + msecs_to_jiffies(timeout_ms)); + + spin_lock_irqsave(&evt->lock, flags); + e = evt->events; + evt->events &= ~e; + spin_unlock_irqrestore(&evt->lock, flags); + + return e; +} +EXPORT_SYMBOL(os_event_wait_timed); + +void os_event_raise(os_event_t *evt, uint16_t events) +{ + unsigned long flags; + + spin_lock_irqsave(&evt->lock, flags); + evt->events |= events; + spin_unlock_irqrestore(&evt->lock, flags); + + wake_up(&evt->wq); +} +EXPORT_SYMBOL(os_event_raise); diff --git a/drivers/staging/csr/oska/event.h b/drivers/staging/csr/oska/event.h new file mode 100644 index 000000000000..be52e42c37dc --- /dev/null +++ b/drivers/staging/csr/oska/event.h @@ -0,0 +1,33 @@ +/* + * OSKA Linux implementation -- events + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_EVENT_H +#define __OSKA_LINUX_EVENT_H + +#include +#include +#include + +typedef struct { + wait_queue_head_t wq; + spinlock_t lock; + uint16_t events; +} os_event_t; + +void os_event_init(os_event_t *evt); + +static inline void os_event_destroy(os_event_t *evt) +{ +} + +uint16_t os_event_wait(os_event_t *evt); +uint16_t os_event_wait_interruptible(os_event_t *evt); +uint16_t os_event_wait_timed(os_event_t *evt, unsigned timeout_ms); +void os_event_raise(os_event_t *evt, uint16_t events); + +#endif /* #ifndef __OSKA_LINUX_EVENT_H */ diff --git a/drivers/staging/csr/oska/io.h b/drivers/staging/csr/oska/io.h new file mode 100644 index 000000000000..c6c406c364b9 --- /dev/null +++ b/drivers/staging/csr/oska/io.h @@ -0,0 +1,63 @@ +/* + * OSKA Linux implementation -- memory mapped I/O. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_IO_H +#define __OSKA_LINUX_IO_H + +#include +#include +#include + +typedef void __iomem *os_io_mem_t; + +static inline uint8_t os_io_read8(os_io_mem_t base, unsigned offset) +{ + return readb(base + offset); +} + +static inline uint16_t os_io_read16(os_io_mem_t base, unsigned offset) +{ + return readw(base + offset); +} + +static inline uint32_t os_io_read32(os_io_mem_t base, unsigned offset) +{ + return readl(base + offset); +} + +static inline uint64_t os_io_read64(os_io_mem_t base, unsigned offset) +{ + return readq(base + offset); +} + +static inline void os_io_write8(os_io_mem_t base, unsigned offset, uint8_t val) +{ + writeb(val, base + offset); +} + +static inline void os_io_write16(os_io_mem_t base, unsigned offset, uint16_t val) +{ + writew(val, base + offset); +} + +static inline void os_io_write32(os_io_mem_t base, unsigned offset, uint32_t val) +{ + writel(val, base + offset); +} + +static inline void os_io_write64(os_io_mem_t base, unsigned offset, uint64_t val) +{ + writeq(val, base + offset); +} + +static inline void os_io_memory_barrier(void) +{ + mb(); +} + +#endif /* #ifndef __OSKA_LINUX_IO_H */ diff --git a/drivers/staging/csr/oska/kernel-compat.h b/drivers/staging/csr/oska/kernel-compat.h new file mode 100644 index 000000000000..b6d27d39c33b --- /dev/null +++ b/drivers/staging/csr/oska/kernel-compat.h @@ -0,0 +1,199 @@ +/* + * Kernel version compatibility. + * + * Copyright (C) 2007-2008 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * Wherever possible compatible implementations of newer APIs are + * provided for older kernel versions. + */ +#ifndef __LINUX_KERNEL_COMPAT_H +#define __LINUX_KERNEL_COMPAT_H + +#include +#include +#include + +#include + +/* + * linux/semaphore.h replaces asm/semaphore.h in 2.6.27. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +# include +#else +# include +#endif + +/* + * Workqueue API changes in 2.6.20 + * + * See http://lwn.net/Articles/211279/ for details. + * + * We deliberately don't provide the non-automatic release (NAR) + * variants as a simple compatible implementation is not possible. + * This shouldn't be a problem as all usage so far is to embed the + * struct work_struct into another struct and the NAR variants aren't + * useful in this case (see http://lwn.net/Articles/213149/). + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + +#include + +#undef INIT_WORK +#define INIT_WORK(_work, _func) \ + do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + PREPARE_WORK((_work), (_func), (_work)); \ + init_timer(&(_work)->timer); \ + } while(0) + +#undef DECLARE_WORK +#define DECLARE_WORK(n, f) \ + struct work_struct n = __WORK_INITIALIZER((n), (f), &(n)) + +struct delayed_work { + struct work_struct work; +}; + +#define INIT_DELAYED_WORK(dw, fn) \ + INIT_WORK(&(dw)->work, (fn)) + +#define queue_delayed_work(wq, dw, delay) \ + queue_delayed_work((wq), &(dw)->work, (delay)) + +#define schedule_delayed_work(dw, delay) \ + schedule_delayed_work(&(dw)->work, (delay)) + +#define cancel_delayed_work(dw) \ + cancel_delayed_work(&(dw)->work) + +#endif /* Linux kernel < 2.6.20 */ + +/* + * device_create()/class_device_create() + * + * device_create() gains a drvdata parameter in 2.6.27. Since all + * users of device_create() in CSR code don't use drvdata just ignore + * it. + * + * device_create() replaces class_device_create() in 2.6.21. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) + +#define device_create(class, parent, devt, drvdata, fmt, args...) \ + class_device_create((class), (parent), (devt), NULL, (fmt), ## args) +#define device_destroy(class, devt) \ + class_device_destroy(class, devt) + +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + +#define device_create(class, parent, devt, drvdata, fmt, args...) \ + device_create((class), (parent), (devt), (fmt), ## args) + +#endif /* Linux kernel < 2.6.26 */ + +/* + * dev_name() and dev_set_name() added in 2.6.26. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + +static inline char *dev_name(struct device *dev) +{ + return dev->bus_id; +} + +int dev_set_name(struct device *dev, const char *fmt, ...); + +#endif /* Linux kernel < 2.6.26 */ + +/* + * class_find_device() in 2.6.25 + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +struct device *class_find_device(struct class *class, struct device *start, + void *data, int (*match)(struct device *, void *)); + +#endif /* Linux kernel < 2.6.25 */ + +/* + * list_first_entry in 2.6.22. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#endif /* Linux kernel < 2.6.22 */ + +/* + * 2.6.19 adds a bool type. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + +typedef _Bool bool; +enum { + false = 0, + true = 1 +}; + +#endif /* Linux kernel < 2.6.19 */ + +/* + * Provide readq() and writeq() if unavailable. + */ +#ifndef readq +static inline __u64 readq(const volatile void __iomem *addr) +{ + const volatile u32 __iomem *p = addr; + u32 low, high; + + low = readl(p); + high = readl(p + 1); + + return low + ((u64)high << 32); +} +#endif + +#ifndef writeq +static inline void writeq(__u64 val, volatile void __iomem *addr) +{ + writel(val, addr); + writel(val >> 32, addr+4); +} +#endif + +/* + * get_unaligned_le16() and friends added in 2.6.26. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#include + +static inline __u16 get_unaligned_le16(const void *p) +{ + return le16_to_cpu(get_unaligned((__le16 *)p)); +} + +static inline void put_unaligned_le16(__u16 val, const void *p) +{ + put_unaligned(cpu_to_le16(val), (__le16 *)p); +} +#endif /* Linux kernel < 2.6.26 */ + +/* + * Various device or vendor IDs may not exist. + */ +#ifndef PCI_VENDOR_ID_CSR +# define PCI_VENDOR_ID_CSR 0x18e5 +#endif + +#ifndef PCI_DEVICE_ID_JMICRON_JMB38X_SD +# define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 +#endif + +#endif /* #ifndef __LINUX_KERNEL_COMPAT_H */ diff --git a/drivers/staging/csr/oska/list.c b/drivers/staging/csr/oska/list.c new file mode 100644 index 000000000000..b5e884e1f201 --- /dev/null +++ b/drivers/staging/csr/oska/list.c @@ -0,0 +1,103 @@ +/* + * Operating system kernel abstraction -- linked lists. + * + * Copyright (C) 2009-2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ + +#include + +#include "list.h" +#include "util.h" + +/** + * Initialize an empty list. + * + * @ingroup list + */ +void os_list_init(struct os_list *list) +{ + list->head.next = list->head.prev = &list->head; +} + +/** + * Is the list empty? + * + * @return true iff the list contains no nodes. + * + * @ingroup list + */ +int os_list_empty(struct os_list *list) +{ + return list->head.next == &list->head; +} + +static void os_list_add(struct os_list_node *prev, struct os_list_node *new, + struct os_list_node *next) +{ + OS_ASSERT(new->next == NULL && new->prev == NULL); + + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * Add a node to the tail of the list. + * + * @param list the list. + * @param node the list node to add. + * + * @ingroup list + */ +void os_list_add_tail(struct os_list *list, struct os_list_node *node) +{ + os_list_add(list->head.prev, node, &list->head); +} + +/** + * Remove a node from a list. + * + * @param node the node to remove. + * + * @ingroup list + */ +void os_list_del(struct os_list_node *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; + + node->prev = node->next = NULL; +} + +/** + * The node at the head of the list. + * + * @param list the list. + * + * @return the node at the head of the list; or os_list_end() if the + * list is empty. + * + * @ingroup list + */ +struct os_list_node *os_list_head(struct os_list *list) +{ + return list->head.next; +} + +/** + * The node marking the end of a list. + * + * @param list the list. + * + * @return the node that marks the end of the list. + * + * @ingroup list + */ +struct os_list_node *os_list_end(struct os_list *list) +{ + return &list->head; +} diff --git a/drivers/staging/csr/oska/list.h b/drivers/staging/csr/oska/list.h new file mode 100644 index 000000000000..a69b3b7d96b4 --- /dev/null +++ b/drivers/staging/csr/oska/list.h @@ -0,0 +1,115 @@ +/* + * Operating system kernel abstraction -- linked lists. + * + * Copyright (C) 2009-2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LIST_H +#define __OSKA_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup list Linked Lists + * + * Generic linked list implementations suitable for all platforms. + * + * - Circular, doubly-linked list (struct os_list). + */ + +/** + * A list node. + * + * This list node structure should be the first field within any + * structure that is to be stored in a list. + * + * @see struct os_list + * @ingroup list + */ +struct os_list_node { + /** + * The pointer to the previous node in the list, or os_list_end() + * if the end of the list has been reached. + */ + struct os_list_node *prev; + /** + * The pointer to the next node in the list, or os_list_end() if + * the end of the list has been reached. + */ + struct os_list_node *next; +}; + +/** + * A circular, doubly-linked list of nodes. + * + * Structures to be stored in a list should contains a struct + * os_list_node as the \e first field. + * \code + * struct foo { + * struct os_list_node node; + * int bar; + * ... + * }; + * \endcode + * Going to/from a struct foo to a list node is then simple. + * \code + * struct os_list_node *node; + * struct foo *foo; + * [...] + * node = &foo->node; + * foo = (struct foo *)node + * \endcode + * Lists must be initialized with os_list_init() before adding nodes + * with os_list_add_tail(). The node at the head of the list is + * obtained with os_list_head(). Nodes are removed from the list with + * os_list_del(). + * + * A list can be interated from the head to the tail using: + * \code + * struct os_list_node *node; + * for (node = os_list_head(list); node != os_list_end(list); node = node->next) { + * struct foo *foo = (struct foo *)node; + * ... + * } + * \endcode + * + * In the above loop, the current list node cannot be removed (with + * os_list_del()). If this is required use this form of loop: + * \code + * struct os_list_node *node, *next; + * for (node = os_list_head(list), next = node->next; + * node != os_list_end(list); + * node = next, next = node->next) { + * struct foo *foo = (struct foo *)node; + * ... + * os_list_del(node); + * ... + * } + * \endcode + * + * @ingroup list + */ +struct os_list { + /** + * @internal + * The dummy node marking the end of the list. + */ + struct os_list_node head; +}; + +void os_list_init(struct os_list *list); +int os_list_empty(struct os_list *list); +void os_list_add_tail(struct os_list *list, struct os_list_node *node); +void os_list_del(struct os_list_node *node); +struct os_list_node *os_list_head(struct os_list *list); +struct os_list_node *os_list_end(struct os_list *list); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef __OSKA_LIST_H */ diff --git a/drivers/staging/csr/oska/mutex.h b/drivers/staging/csr/oska/mutex.h new file mode 100644 index 000000000000..9138b2881832 --- /dev/null +++ b/drivers/staging/csr/oska/mutex.h @@ -0,0 +1,42 @@ +/* + * OSKA Linux implementation -- mutexes + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_MUTEX_H +#define __OSKA_LINUX_MUTEX_H + +#include +#include + +#include "kernel-compat.h" + +/* Real mutexes were only added to 2.6.16 so use semaphores + instead. */ +typedef struct semaphore os_mutex_t; + +static inline void os_mutex_init(os_mutex_t *mutex) +{ + //init_MUTEX(mutex); + sema_init(mutex, 1); +} + +static inline void os_mutex_destroy(os_mutex_t *mutex) +{ + /* no op */ +} + +static inline void os_mutex_lock(os_mutex_t *mutex) +{ + down(mutex); +} + +static inline void os_mutex_unlock(os_mutex_t *mutex) +{ + up(mutex); +} + +#endif /* __OSKA_LINUX_MUTEX_H */ diff --git a/drivers/staging/csr/oska/oska_module.c b/drivers/staging/csr/oska/oska_module.c new file mode 100644 index 000000000000..da125643d2d6 --- /dev/null +++ b/drivers/staging/csr/oska/oska_module.c @@ -0,0 +1,21 @@ +/* + * Linux kernel module support. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include + +#include "all.h" +#include "refcount.h" + +EXPORT_SYMBOL(os_refcount_init); +EXPORT_SYMBOL(os_refcount_destroy); +EXPORT_SYMBOL(os_refcount_get); +EXPORT_SYMBOL(os_refcount_put); + +MODULE_DESCRIPTION("Operating System Kernel Abstraction"); +MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/staging/csr/oska/print.c b/drivers/staging/csr/oska/print.c new file mode 100644 index 000000000000..5f5b26310663 --- /dev/null +++ b/drivers/staging/csr/oska/print.c @@ -0,0 +1,44 @@ +/* + * Linux console printing functions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include + +#include "print.h" + +void os_print(enum os_print_level level, const char *prefix, const char *name, + const char *format, ...) +{ + va_list va_args; + + va_start(va_args, format); + os_vprint(level, prefix, name, format, va_args); + va_end(va_args); +} +EXPORT_SYMBOL(os_print); + +void os_vprint(enum os_print_level level, const char *prefix, const char *name, + const char *format, va_list args) +{ + const char *level_str[] = { + [OS_PRINT_ERROR] = KERN_ERR, + [OS_PRINT_WARNING] = KERN_WARNING, + [OS_PRINT_INFO] = KERN_INFO, + [OS_PRINT_DEBUG] = KERN_DEBUG, + }; + char buf[80]; + int w = 0; + + if (name) { + w += snprintf(buf + w, sizeof(buf) - w, "%s%s%s: ", level_str[level], prefix, name); + } else { + w += snprintf(buf + w, sizeof(buf) - w, "%s%s", level_str[level], prefix); + } + w += vsnprintf(buf + w, sizeof(buf) - w, format, args); + printk("%s\n", buf); +} +EXPORT_SYMBOL(os_vprint); diff --git a/drivers/staging/csr/oska/print.h b/drivers/staging/csr/oska/print.h new file mode 100644 index 000000000000..f48bb836a587 --- /dev/null +++ b/drivers/staging/csr/oska/print.h @@ -0,0 +1,32 @@ +/* + * OSKA Linux implementation -- console printing + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_PRINT_H +#define __OSKA_LINUX_PRINT_H + +#include + +/** + * Severity of a console or log message. + * + * @ingroup print + */ +enum os_print_level { + OS_PRINT_ERROR, + OS_PRINT_WARNING, + OS_PRINT_INFO, + OS_PRINT_DEBUG, +}; + +void os_print(enum os_print_level level, const char *prefix, const char *name, + const char *format, ...); +void os_vprint(enum os_print_level level, const char *prefix, const char *name, + const char *format, va_list args); + + +#endif /* #ifndef __OSKA_LINUX_PRINT_H */ diff --git a/drivers/staging/csr/oska/refcount.c b/drivers/staging/csr/oska/refcount.c new file mode 100644 index 000000000000..28abb64a9d20 --- /dev/null +++ b/drivers/staging/csr/oska/refcount.c @@ -0,0 +1,47 @@ +/* + * OSKA generic implementation -- reference counting. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include "refcount.h" +#include "types.h" + +void os_refcount_init(os_refcount_t *refcount, os_refcount_callback_f func, void *arg) +{ + os_spinlock_init(&refcount->lock); + refcount->count = 1; + refcount->func = func; + refcount->arg = arg; +} + +void os_refcount_destroy(os_refcount_t *refcount) +{ + os_spinlock_destroy(&refcount->lock); +} + +void os_refcount_get(os_refcount_t *refcount) +{ + os_int_status_t istate; + + os_spinlock_lock_intsave(&refcount->lock, &istate); + refcount->count++; + os_spinlock_unlock_intrestore(&refcount->lock, &istate); +} + +void os_refcount_put(os_refcount_t *refcount) +{ + bool is_zero; + os_int_status_t istate; + + os_spinlock_lock_intsave(&refcount->lock, &istate); + refcount->count--; + is_zero = refcount->count == 0; + os_spinlock_unlock_intrestore(&refcount->lock, &istate); + + if (is_zero) { + refcount->func(refcount->arg); + } +} diff --git a/drivers/staging/csr/oska/refcount.h b/drivers/staging/csr/oska/refcount.h new file mode 100644 index 000000000000..741b00afcdf0 --- /dev/null +++ b/drivers/staging/csr/oska/refcount.h @@ -0,0 +1,86 @@ +/* + * Operating system kernel abstraction -- reference counting. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_REFCOUNT_H +#define __OSKA_REFCOUNT_H + +#include "spinlock.h" + +/** + * @defgroup refcount Reference Counting + * + * A reference count is an atomic counter. A callback function is + * called whenever the count reaches zero. + * + * A generic implementation is provided that is suitable for all + * platforms that support the spinlock API in (see + * \ref spinlock). + */ + +typedef void (*os_refcount_callback_f)(void *arg); + +struct __os_refcount_impl { + unsigned count; + os_spinlock_t lock; + os_refcount_callback_f func; + void *arg; +}; + +/** + * A reference count object. + * + * @ingroup refcount + */ +typedef struct __os_refcount_impl os_refcount_t; + +/** + * Initialize a reference count to 1. + * + * Initialized reference counts must be destroyed by calling + * os_refcount_destroy(). + * + * @param refcount the reference count. + * @param func the function which will be called when the + * reference count reaches 0. + * @param arg an argument to pass to func. + * + * @ingroup refcount + */ +void os_refcount_init(os_refcount_t *refcount, os_refcount_callback_f func, void *arg); + +/** + * Destroy a reference count object. + * + * @param refcount the reference count. + * + * @ingroup refcount + */ +void os_refcount_destroy(os_refcount_t *refcount); + +/** + * Atomically increase the reference count by 1. + * + * @param refcount the reference count. + * + * @ingroup refcount + */ +void os_refcount_get(os_refcount_t *refcount); + +/** + * Atomically decrease the reference count by 1. + * + * The callback function passed to the call to os_refcount_init() is + * called if the count was decreased to zero. + * + * @param refcount the reference count. + * + * @ingroup refcount + */ +void os_refcount_put(os_refcount_t *refcount); + +#endif /* #ifndef __OSKA_REFCOUNT_H */ diff --git a/drivers/staging/csr/oska/semaphore.h b/drivers/staging/csr/oska/semaphore.h new file mode 100644 index 000000000000..965bfe8f52cf --- /dev/null +++ b/drivers/staging/csr/oska/semaphore.h @@ -0,0 +1,70 @@ +/* + * OSKA Linux implementation -- semaphores + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_SEMAPHORE_H +#define __OSKA_LINUX_SEMAPHORE_H + +#include + +#include + +typedef struct semaphore os_semaphore_t; + +static inline void os_semaphore_init(os_semaphore_t *sem) +{ + sema_init(sem, 0); +} + +static inline void os_semaphore_destroy(os_semaphore_t *sem) +{ +} + +static inline void os_semaphore_wait(os_semaphore_t *sem) +{ + down(sem); +} + +/* + * down_timeout() was added in 2.6.26 with the generic semaphore + * implementation. For now, only support it on recent kernels as + * semaphores may be replaced by an event API that would be + * implemented with wait_event(), and wait_event_timeout(). + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + +static inline int os_semaphore_wait_timed(os_semaphore_t *sem, + int time_ms) +{ + if (down_timeout(sem, msecs_to_jiffies(time_ms)) < 0) { + return -ETIMEDOUT; + } + return 0; +} + +#else + +static inline int os_semaphore_wait_timed(os_semaphore_t *sem, int time_ms) +{ + unsigned long now = jiffies; + do{ + if(!down_trylock(sem)) + return 0; + msleep(1); + } while(time_before(jiffies, now + msecs_to_jiffies(time_ms))); + + return -ETIMEDOUT; +} + +#endif + +static inline void os_semaphore_post(os_semaphore_t *sem) +{ + up(sem); +} + +#endif /* __OSKA_LINUX_SEMAPHORE_H */ diff --git a/drivers/staging/csr/oska/spinlock.h b/drivers/staging/csr/oska/spinlock.h new file mode 100644 index 000000000000..157b350107ae --- /dev/null +++ b/drivers/staging/csr/oska/spinlock.h @@ -0,0 +1,43 @@ +/* + * OSKA Linux implementation -- spinlocks + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_SPINLOCK_H +#define __OSKA_LINUX_SPINLOCK_H + +#include +#include + +typedef spinlock_t os_spinlock_t; +typedef unsigned long os_int_status_t; + +static inline void os_spinlock_init(os_spinlock_t *lock) +{ + spinlock_t *l = (spinlock_t *)lock; + spin_lock_init(l); +} + +static inline void os_spinlock_destroy(os_spinlock_t *lock) +{ + /* no op */ +} + +static inline void os_spinlock_lock_intsave(os_spinlock_t *lock, + os_int_status_t *int_state) +{ + spinlock_t *l = (spinlock_t *)lock; + spin_lock_irqsave(l, *int_state); +} + +static inline void os_spinlock_unlock_intrestore(os_spinlock_t *lock, + os_int_status_t *int_state) +{ + spinlock_t *l = (spinlock_t *)lock; + spin_unlock_irqrestore(l, *int_state); +} + +#endif /* #ifndef __OSKA_LINUX_SPINLOCK_H */ diff --git a/drivers/staging/csr/oska/thread.c b/drivers/staging/csr/oska/thread.c new file mode 100644 index 000000000000..f680cef709e7 --- /dev/null +++ b/drivers/staging/csr/oska/thread.c @@ -0,0 +1,66 @@ +/* + * Linux thread functions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include + +#include "thread.h" + +static int thread_func(void *data) +{ + os_thread_t *thread = data; + + thread->func(thread->arg); + + /* + * kthread_stop() cannot handle the thread exiting while + * kthread_should_stop() is false, so sleep until kthread_stop() + * wakes us up. + */ + set_current_state(TASK_INTERRUPTIBLE); + if (!kthread_should_stop()) + schedule(); + + return 0; +} + +int os_thread_create(os_thread_t *thread, const char *name, void (*func)(void *), void *arg) +{ + thread->func = func; + thread->arg = arg; + + thread->stop = 0; + + thread->task = kthread_run(thread_func, thread, name); + if (IS_ERR(thread->task)) { + return PTR_ERR(thread->task); + } + return 0; +} +EXPORT_SYMBOL(os_thread_create); + +void os_thread_stop(os_thread_t *thread, os_event_t *evt) +{ + /* + * Stop flag must be set before the event is raised so + * kthread_should_stop() cannot be used. + */ + thread->stop = 1; + + if (evt) { + os_event_raise(evt, ~0); + } + + kthread_stop(thread->task); +} +EXPORT_SYMBOL(os_thread_stop); + +int os_thread_should_stop(os_thread_t *thread) +{ + return thread->stop; +} +EXPORT_SYMBOL(os_thread_should_stop); diff --git a/drivers/staging/csr/oska/thread.h b/drivers/staging/csr/oska/thread.h new file mode 100644 index 000000000000..8816dc853e26 --- /dev/null +++ b/drivers/staging/csr/oska/thread.h @@ -0,0 +1,39 @@ +/* + * OSKA Linux implementation -- threading + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_THREAD_H +#define __OSKA_LINUX_THREAD_H + +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19) +#include +#endif +#include "event.h" + +struct os_thread_lx { + void (*func)(void *); + void *arg; + struct task_struct *task; + int stop; +}; + +typedef struct os_thread_lx os_thread_t; + +int os_thread_create(os_thread_t *thread, const char *name, + void (*func)(void *), void *arg); +void os_thread_stop(os_thread_t *thread, os_event_t *evt); +int os_thread_should_stop(os_thread_t *thread); + +static inline void os_try_suspend_thread(os_thread_t *thread) +{ + try_to_freeze(); +} + +#endif /* __OSKA_LINUX_THREAD_H */ diff --git a/drivers/staging/csr/oska/time.h b/drivers/staging/csr/oska/time.h new file mode 100644 index 000000000000..d246ce937309 --- /dev/null +++ b/drivers/staging/csr/oska/time.h @@ -0,0 +1,34 @@ +/* + * OSKA Linux implementation -- timing + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_TIME_H +#define __OSKA_LINUX_TIME_H + +#include +#include +#include +#include + +static inline unsigned long os_current_time_ms(void) +{ + return jiffies_to_msecs(jiffies); +} + +static inline void os_sleep_ms(unsigned ms) +{ + msleep_interruptible(ms); +} + +static inline void os_delay_us(unsigned us) +{ + udelay(us); +} + +#define os_time_after(a, b) time_after((a), (b)) + +#endif /* __OSKA_LINUX_TIME_H */ diff --git a/drivers/staging/csr/oska/timer.c b/drivers/staging/csr/oska/timer.c new file mode 100644 index 000000000000..67d3423315f5 --- /dev/null +++ b/drivers/staging/csr/oska/timer.c @@ -0,0 +1,28 @@ +/* + * OSKA Linux implementation -- timers. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#include + +#include "timer.h" + +static void timer_func(unsigned long data) +{ + os_timer_t *timer = (os_timer_t *)data; + + timer->func(timer->arg); +} + +void os_timer_init(os_timer_t *timer, os_timer_func_t func, void *arg) +{ + timer->func = func; + timer->arg = arg; + timer->timer.function = timer_func; + timer->timer.data = (unsigned long)timer; + init_timer(&timer->timer); +} +EXPORT_SYMBOL(os_timer_init); diff --git a/drivers/staging/csr/oska/timer.h b/drivers/staging/csr/oska/timer.h new file mode 100644 index 000000000000..3045fc3b98b7 --- /dev/null +++ b/drivers/staging/csr/oska/timer.h @@ -0,0 +1,40 @@ +/* + * OSKA Linux implementation -- timers. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_TIMER_H +#define __OSKA_LINUX_TIMER_H + +#include +#include + +typedef void (*os_timer_func_t)(void *arg); + +typedef struct { + os_timer_func_t func; + void *arg; + struct timer_list timer; +} os_timer_t; + +void os_timer_init(os_timer_t *timer, os_timer_func_t func, void *arg); + +static inline void os_timer_destroy(os_timer_t *timer) +{ + del_timer_sync(&timer->timer); +} + +static inline void os_timer_set(os_timer_t *timer, unsigned long expires_ms) +{ + mod_timer(&timer->timer, jiffies + msecs_to_jiffies(expires_ms)); +} + +static inline void os_timer_cancel(os_timer_t *timer) +{ + del_timer(&timer->timer); +} + +#endif /* #ifndef __OSKA_LINUX_TIMER_H */ diff --git a/drivers/staging/csr/oska/trace.h b/drivers/staging/csr/oska/trace.h new file mode 100644 index 000000000000..b28f37da4fbb --- /dev/null +++ b/drivers/staging/csr/oska/trace.h @@ -0,0 +1,23 @@ +/* + * OSKA Linux implementation -- tracing messages. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_TRACE_H +#define __OSKA_LINUX_TRACE_H + +#include + +#ifndef OS_TRACE_PREFIX +# define OS_TRACE_PREFIX "" +#endif + +#define os_trace_err(format, ...) printk(KERN_ERR OS_TRACE_PREFIX format "\n", ## __VA_ARGS__) +#define os_trace_warn(format, ...) printk(KERN_WARNING OS_TRACE_PREFIX format "\n", ## __VA_ARGS__) +#define os_trace_info(format, ...) printk(KERN_INFO OS_TRACE_PREFIX format "\n", ## __VA_ARGS__) +#define os_trace_dbg(format, ...) printk(KERN_DEBUG OS_TRACE_PREFIX format "\n", ## __VA_ARGS__) + +#endif /* #ifndef __OSKA_LINUX_TRACE_H */ diff --git a/drivers/staging/csr/oska/types.h b/drivers/staging/csr/oska/types.h new file mode 100644 index 000000000000..18d7c111e74a --- /dev/null +++ b/drivers/staging/csr/oska/types.h @@ -0,0 +1,14 @@ +/* + * OSKA Linux implementation -- types + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_TYPES_H +#define __OSKA_LINUX_TYPES_H + +#include + +#endif /* #ifndef __OSKA_LINUX_TYPES_H */ diff --git a/drivers/staging/csr/oska/util.h b/drivers/staging/csr/oska/util.h new file mode 100644 index 000000000000..bf29e2d906ed --- /dev/null +++ b/drivers/staging/csr/oska/util.h @@ -0,0 +1,48 @@ +/* + * OSKA Linux implementation -- misc. utility functions + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef __OSKA_LINUX_UTILS_H +#define __OSKA_LINUX_UTILS_H + +#include +#include +#include + +#define OS_ASSERT(expr) BUG_ON(!(expr)) + +static inline uint16_t os_le16_to_cpu(uint16_t x) +{ + return le16_to_cpu(x); +} + +static inline uint16_t os_cpu_to_le16(uint16_t x) +{ + return cpu_to_le16(x); +} + +static inline uint32_t os_le32_to_cpu(uint32_t x) +{ + return le32_to_cpu(x); +} + +static inline uint32_t os_cpu_to_le32(uint32_t x) +{ + return cpu_to_le32(x); +} + +static inline uint64_t os_le64_to_cpu(uint64_t x) +{ + return le64_to_cpu(x); +} + +static inline uint64_t os_cpu_to_le64(uint64_t x) +{ + return cpu_to_le64(x); +} + +#endif /* __OSKA_LINUX_UTILS_H */ -- GitLab From 635d2b00e5070378e7bf812acf47fb135c6ab928 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jun 2012 16:15:42 -0700 Subject: [PATCH 0909/5711] Staging: add CSR wifi module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This consists of two modules, the driver, and a "helper" module that is just a wrapper around common kernel functions. The wrapper module will be removed soon, but for now it's needed. These files were based on the csr-linux-wifi-5.0.3-oss.tar.gz package provided by CSR and Blue Giga, and is covered under the license specified in the LICENSE.txt file (basically dual BSD and GPLv2). The files were flattened out of the deep directory mess they were originally in, and a few EXPORT_SYMBOL_GPL() were added in order for everything to link properly with the helper module setup. Cc: Mikko Virkkilä Cc: Lauri Hintsala Cc: Riku Mettälä Cc: Veli-Pekka Peltola Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/Kconfig | 2 +- drivers/staging/csr/LICENSE.txt | 39 + drivers/staging/csr/Makefile | 70 + drivers/staging/csr/bh.c | 391 + drivers/staging/csr/csr_formatted_io.c | 29 + drivers/staging/csr/csr_formatted_io.h | 25 + drivers/staging/csr/csr_framework_ext.c | 213 + drivers/staging/csr/csr_framework_ext.h | 354 + drivers/staging/csr/csr_framework_ext_types.h | 65 + drivers/staging/csr/csr_lib.h | 189 + drivers/staging/csr/csr_log.h | 250 + drivers/staging/csr/csr_log_configure.h | 135 + drivers/staging/csr/csr_log_text.h | 133 + drivers/staging/csr/csr_macro.h | 111 + drivers/staging/csr/csr_msg_transport.h | 25 + drivers/staging/csr/csr_msgconv.c | 324 + drivers/staging/csr/csr_msgconv.h | 145 + drivers/staging/csr/csr_panic.c | 22 + drivers/staging/csr/csr_panic.h | 55 + drivers/staging/csr/csr_pmem.c | 51 + drivers/staging/csr/csr_pmem.h | 143 + drivers/staging/csr/csr_prim_defs.h | 64 + drivers/staging/csr/csr_result.h | 27 + drivers/staging/csr/csr_sched.h | 292 + drivers/staging/csr/csr_sdio.h | 732 ++ .../csr/csr_serialize_primitive_types.c | 472 ++ drivers/staging/csr/csr_time.c | 71 + drivers/staging/csr/csr_time.h | 205 + drivers/staging/csr/csr_types.h | 93 + drivers/staging/csr/csr_unicode.h | 190 + drivers/staging/csr/csr_utf16.c | 1136 +++ drivers/staging/csr/csr_util.c | 435 ++ drivers/staging/csr/csr_util.h | 75 + drivers/staging/csr/csr_wifi_common.h | 109 + drivers/staging/csr/csr_wifi_fsm.h | 250 + drivers/staging/csr/csr_wifi_fsm_event.h | 51 + drivers/staging/csr/csr_wifi_fsm_types.h | 441 ++ drivers/staging/csr/csr_wifi_hip_card.h | 114 + drivers/staging/csr/csr_wifi_hip_card_sdio.c | 4128 +++++++++++ drivers/staging/csr/csr_wifi_hip_card_sdio.h | 702 ++ .../staging/csr/csr_wifi_hip_card_sdio_intr.c | 2561 +++++++ .../staging/csr/csr_wifi_hip_card_sdio_mem.c | 1713 +++++ drivers/staging/csr/csr_wifi_hip_chiphelper.c | 793 ++ drivers/staging/csr/csr_wifi_hip_chiphelper.h | 471 ++ .../csr/csr_wifi_hip_chiphelper_private.h | 208 + .../staging/csr/csr_wifi_hip_conversions.h | 81 + drivers/staging/csr/csr_wifi_hip_download.c | 834 +++ drivers/staging/csr/csr_wifi_hip_dump.c | 872 +++ drivers/staging/csr/csr_wifi_hip_packing.c | 4804 ++++++++++++ drivers/staging/csr/csr_wifi_hip_send.c | 422 ++ drivers/staging/csr/csr_wifi_hip_signals.c | 1313 ++++ drivers/staging/csr/csr_wifi_hip_signals.h | 137 + drivers/staging/csr/csr_wifi_hip_sigs.h | 1425 ++++ .../staging/csr/csr_wifi_hip_ta_sampling.c | 535 ++ .../staging/csr/csr_wifi_hip_ta_sampling.h | 75 + drivers/staging/csr/csr_wifi_hip_udi.c | 268 + drivers/staging/csr/csr_wifi_hip_unifi.h | 852 +++ .../csr/csr_wifi_hip_unifi_signal_names.c | 46 + drivers/staging/csr/csr_wifi_hip_unifi_udi.h | 76 + drivers/staging/csr/csr_wifi_hip_unifihw.h | 67 + .../staging/csr/csr_wifi_hip_unifiversion.h | 38 + drivers/staging/csr/csr_wifi_hip_xbv.c | 1075 +++ drivers/staging/csr/csr_wifi_hip_xbv.h | 127 + drivers/staging/csr/csr_wifi_hostio_prim.h | 27 + drivers/staging/csr/csr_wifi_lib.h | 113 + drivers/staging/csr/csr_wifi_msgconv.h | 60 + .../csr/csr_wifi_nme_ap_converter_init.h | 49 + drivers/staging/csr/csr_wifi_nme_ap_lib.h | 526 ++ drivers/staging/csr/csr_wifi_nme_ap_prim.h | 504 ++ drivers/staging/csr/csr_wifi_nme_ap_sef.c | 30 + drivers/staging/csr/csr_wifi_nme_ap_sef.h | 31 + .../staging/csr/csr_wifi_nme_ap_serialize.h | 105 + .../staging/csr/csr_wifi_nme_converter_init.h | 46 + drivers/staging/csr/csr_wifi_nme_lib.h | 1056 +++ drivers/staging/csr/csr_wifi_nme_prim.h | 1666 +++++ drivers/staging/csr/csr_wifi_nme_serialize.h | 177 + drivers/staging/csr/csr_wifi_nme_task.h | 38 + drivers/staging/csr/csr_wifi_private_common.h | 91 + drivers/staging/csr/csr_wifi_result.h | 36 + .../csr/csr_wifi_router_converter_init.c | 83 + .../csr/csr_wifi_router_converter_init.h | 42 + .../csr/csr_wifi_router_ctrl_converter_init.c | 132 + .../csr/csr_wifi_router_ctrl_converter_init.h | 42 + ...ifi_router_ctrl_free_downstream_contents.c | 95 + ..._wifi_router_ctrl_free_upstream_contents.c | 81 + .../staging/csr/csr_wifi_router_ctrl_lib.h | 1958 +++++ .../staging/csr/csr_wifi_router_ctrl_prim.h | 2018 +++++ .../staging/csr/csr_wifi_router_ctrl_sef.c | 43 + .../staging/csr/csr_wifi_router_ctrl_sef.h | 56 + .../csr/csr_wifi_router_ctrl_serialize.c | 2369 ++++++ .../csr/csr_wifi_router_ctrl_serialize.h | 323 + ...csr_wifi_router_free_downstream_contents.c | 54 + .../csr_wifi_router_free_upstream_contents.c | 54 + drivers/staging/csr/csr_wifi_router_lib.h | 429 ++ drivers/staging/csr/csr_wifi_router_prim.h | 430 ++ drivers/staging/csr/csr_wifi_router_sef.c | 19 + drivers/staging/csr/csr_wifi_router_sef.h | 33 + .../staging/csr/csr_wifi_router_serialize.c | 422 ++ .../staging/csr/csr_wifi_router_serialize.h | 78 + drivers/staging/csr/csr_wifi_router_task.h | 34 + .../staging/csr/csr_wifi_router_transport.c | 210 + .../csr/csr_wifi_serialize_primitive_types.c | 257 + drivers/staging/csr/csr_wifi_sme_ap_lib.h | 656 ++ drivers/staging/csr/csr_wifi_sme_ap_prim.h | 904 +++ .../staging/csr/csr_wifi_sme_converter_init.c | 201 + .../staging/csr/csr_wifi_sme_converter_init.h | 42 + .../csr_wifi_sme_free_downstream_contents.c | 181 + .../csr/csr_wifi_sme_free_upstream_contents.c | 276 + drivers/staging/csr/csr_wifi_sme_lib.h | 4282 +++++++++++ drivers/staging/csr/csr_wifi_sme_prim.h | 6494 +++++++++++++++++ drivers/staging/csr/csr_wifi_sme_sef.c | 85 + drivers/staging/csr/csr_wifi_sme_sef.h | 101 + drivers/staging/csr/csr_wifi_sme_serialize.c | 5756 +++++++++++++++ drivers/staging/csr/csr_wifi_sme_serialize.h | 668 ++ drivers/staging/csr/csr_wifi_sme_task.h | 34 + drivers/staging/csr/csr_wifi_vif_utils.h | 108 + drivers/staging/csr/data_tx.c | 57 + drivers/staging/csr/drv.c | 2150 ++++++ drivers/staging/csr/firmware.c | 398 + drivers/staging/csr/indications.c | 18 + drivers/staging/csr/inet.c | 106 + drivers/staging/csr/init_hw.c | 108 + drivers/staging/csr/io.c | 1146 +++ drivers/staging/csr/mlme.c | 441 ++ drivers/staging/csr/monitor.c | 458 ++ drivers/staging/csr/netdev.c | 3902 ++++++++++ drivers/staging/csr/os.c | 479 ++ drivers/staging/csr/putest.c | 664 ++ drivers/staging/csr/sdio_emb.c | 732 ++ drivers/staging/csr/sdio_events.c | 87 + drivers/staging/csr/sdio_mmc.c | 1165 +++ drivers/staging/csr/sdio_stubs.c | 82 + drivers/staging/csr/sdioemb/cspi.h | 62 + drivers/staging/csr/sdioemb/csr_result.h | 16 + drivers/staging/csr/sdioemb/csr_sdio.h | 711 ++ drivers/staging/csr/sdioemb/csr_sdio_lib.h | 30 + drivers/staging/csr/sdioemb/csr_sdio_wdf.h | 22 + drivers/staging/csr/sdioemb/csr_types.h | 53 + drivers/staging/csr/sdioemb/libsdio.h | 404 + drivers/staging/csr/sdioemb/linux.h | 16 + drivers/staging/csr/sdioemb/sdio.h | 117 + drivers/staging/csr/sdioemb/sdio_api.h | 408 ++ drivers/staging/csr/sdioemb/sdio_bt_a.h | 143 + drivers/staging/csr/sdioemb/sdio_cis.h | 27 + drivers/staging/csr/sdioemb/sdio_csr.h | 134 + drivers/staging/csr/sdioemb/slot_api.h | 313 + drivers/staging/csr/sdioemb/slot_imx27.h | 86 + drivers/staging/csr/sdioemb/slot_imx31.h | 86 + drivers/staging/csr/sdioemb/slot_pxa27x.h | 70 + drivers/staging/csr/sdioemb/slot_shc.h | 223 + drivers/staging/csr/sdioemb/slot_ushc.h | 133 + drivers/staging/csr/sdioemb/trace.h | 19 + drivers/staging/csr/sdioemb/uif.h | 41 + drivers/staging/csr/sdioemb/version.h | 11 + drivers/staging/csr/sme_blocking.c | 1468 ++++ drivers/staging/csr/sme_mgt.c | 1018 +++ drivers/staging/csr/sme_native.c | 591 ++ drivers/staging/csr/sme_sys.c | 2950 ++++++++ drivers/staging/csr/sme_userspace.c | 316 + drivers/staging/csr/sme_userspace.h | 38 + drivers/staging/csr/sme_wext.c | 3394 +++++++++ drivers/staging/csr/ul_int.c | 552 ++ drivers/staging/csr/unifi_clients.h | 129 + drivers/staging/csr/unifi_config.h | 34 + drivers/staging/csr/unifi_dbg.c | 110 + drivers/staging/csr/unifi_event.c | 794 ++ drivers/staging/csr/unifi_native.h | 276 + drivers/staging/csr/unifi_os.h | 137 + drivers/staging/csr/unifi_pdu_processing.c | 3728 ++++++++++ drivers/staging/csr/unifi_priv.h | 1148 +++ drivers/staging/csr/unifi_sme.c | 1164 +++ drivers/staging/csr/unifi_sme.h | 236 + drivers/staging/csr/unifi_wext.h | 124 + drivers/staging/csr/unifiio.h | 400 + drivers/staging/csr/wext_events.c | 285 + 175 files changed, 98765 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/csr/LICENSE.txt create mode 100644 drivers/staging/csr/bh.c create mode 100644 drivers/staging/csr/csr_formatted_io.c create mode 100644 drivers/staging/csr/csr_formatted_io.h create mode 100644 drivers/staging/csr/csr_framework_ext.c create mode 100644 drivers/staging/csr/csr_framework_ext.h create mode 100644 drivers/staging/csr/csr_framework_ext_types.h create mode 100644 drivers/staging/csr/csr_lib.h create mode 100644 drivers/staging/csr/csr_log.h create mode 100644 drivers/staging/csr/csr_log_configure.h create mode 100644 drivers/staging/csr/csr_log_text.h create mode 100644 drivers/staging/csr/csr_macro.h create mode 100644 drivers/staging/csr/csr_msg_transport.h create mode 100644 drivers/staging/csr/csr_msgconv.c create mode 100644 drivers/staging/csr/csr_msgconv.h create mode 100644 drivers/staging/csr/csr_panic.c create mode 100644 drivers/staging/csr/csr_panic.h create mode 100644 drivers/staging/csr/csr_pmem.c create mode 100644 drivers/staging/csr/csr_pmem.h create mode 100644 drivers/staging/csr/csr_prim_defs.h create mode 100644 drivers/staging/csr/csr_result.h create mode 100644 drivers/staging/csr/csr_sched.h create mode 100644 drivers/staging/csr/csr_sdio.h create mode 100644 drivers/staging/csr/csr_serialize_primitive_types.c create mode 100644 drivers/staging/csr/csr_time.c create mode 100644 drivers/staging/csr/csr_time.h create mode 100644 drivers/staging/csr/csr_types.h create mode 100644 drivers/staging/csr/csr_unicode.h create mode 100644 drivers/staging/csr/csr_utf16.c create mode 100644 drivers/staging/csr/csr_util.c create mode 100644 drivers/staging/csr/csr_util.h create mode 100644 drivers/staging/csr/csr_wifi_common.h create mode 100644 drivers/staging/csr/csr_wifi_fsm.h create mode 100644 drivers/staging/csr/csr_wifi_fsm_event.h create mode 100644 drivers/staging/csr/csr_wifi_fsm_types.h create mode 100644 drivers/staging/csr/csr_wifi_hip_card.h create mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio.c create mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio.h create mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c create mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c create mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper.c create mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper.h create mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper_private.h create mode 100644 drivers/staging/csr/csr_wifi_hip_conversions.h create mode 100644 drivers/staging/csr/csr_wifi_hip_download.c create mode 100644 drivers/staging/csr/csr_wifi_hip_dump.c create mode 100644 drivers/staging/csr/csr_wifi_hip_packing.c create mode 100644 drivers/staging/csr/csr_wifi_hip_send.c create mode 100644 drivers/staging/csr/csr_wifi_hip_signals.c create mode 100644 drivers/staging/csr/csr_wifi_hip_signals.h create mode 100644 drivers/staging/csr/csr_wifi_hip_sigs.h create mode 100644 drivers/staging/csr/csr_wifi_hip_ta_sampling.c create mode 100644 drivers/staging/csr/csr_wifi_hip_ta_sampling.h create mode 100644 drivers/staging/csr/csr_wifi_hip_udi.c create mode 100644 drivers/staging/csr/csr_wifi_hip_unifi.h create mode 100644 drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c create mode 100644 drivers/staging/csr/csr_wifi_hip_unifi_udi.h create mode 100644 drivers/staging/csr/csr_wifi_hip_unifihw.h create mode 100644 drivers/staging/csr/csr_wifi_hip_unifiversion.h create mode 100644 drivers/staging/csr/csr_wifi_hip_xbv.c create mode 100644 drivers/staging/csr/csr_wifi_hip_xbv.h create mode 100644 drivers/staging/csr/csr_wifi_hostio_prim.h create mode 100644 drivers/staging/csr/csr_wifi_lib.h create mode 100644 drivers/staging/csr/csr_wifi_msgconv.h create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_converter_init.h create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_lib.h create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_prim.h create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_sef.c create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_sef.h create mode 100644 drivers/staging/csr/csr_wifi_nme_ap_serialize.h create mode 100644 drivers/staging/csr/csr_wifi_nme_converter_init.h create mode 100644 drivers/staging/csr/csr_wifi_nme_lib.h create mode 100644 drivers/staging/csr/csr_wifi_nme_prim.h create mode 100644 drivers/staging/csr/csr_wifi_nme_serialize.h create mode 100644 drivers/staging/csr/csr_wifi_nme_task.h create mode 100644 drivers/staging/csr/csr_wifi_private_common.h create mode 100644 drivers/staging/csr/csr_wifi_result.h create mode 100644 drivers/staging/csr/csr_wifi_router_converter_init.c create mode 100644 drivers/staging/csr/csr_wifi_router_converter_init.h create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_lib.h create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_prim.h create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_sef.c create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_sef.h create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_serialize.c create mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_serialize.h create mode 100644 drivers/staging/csr/csr_wifi_router_free_downstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_router_free_upstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_router_lib.h create mode 100644 drivers/staging/csr/csr_wifi_router_prim.h create mode 100644 drivers/staging/csr/csr_wifi_router_sef.c create mode 100644 drivers/staging/csr/csr_wifi_router_sef.h create mode 100644 drivers/staging/csr/csr_wifi_router_serialize.c create mode 100644 drivers/staging/csr/csr_wifi_router_serialize.h create mode 100644 drivers/staging/csr/csr_wifi_router_task.h create mode 100644 drivers/staging/csr/csr_wifi_router_transport.c create mode 100644 drivers/staging/csr/csr_wifi_serialize_primitive_types.c create mode 100644 drivers/staging/csr/csr_wifi_sme_ap_lib.h create mode 100644 drivers/staging/csr/csr_wifi_sme_ap_prim.h create mode 100644 drivers/staging/csr/csr_wifi_sme_converter_init.c create mode 100644 drivers/staging/csr/csr_wifi_sme_converter_init.h create mode 100644 drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c create mode 100644 drivers/staging/csr/csr_wifi_sme_lib.h create mode 100644 drivers/staging/csr/csr_wifi_sme_prim.h create mode 100644 drivers/staging/csr/csr_wifi_sme_sef.c create mode 100644 drivers/staging/csr/csr_wifi_sme_sef.h create mode 100644 drivers/staging/csr/csr_wifi_sme_serialize.c create mode 100644 drivers/staging/csr/csr_wifi_sme_serialize.h create mode 100644 drivers/staging/csr/csr_wifi_sme_task.h create mode 100644 drivers/staging/csr/csr_wifi_vif_utils.h create mode 100644 drivers/staging/csr/data_tx.c create mode 100644 drivers/staging/csr/drv.c create mode 100644 drivers/staging/csr/firmware.c create mode 100644 drivers/staging/csr/indications.c create mode 100644 drivers/staging/csr/inet.c create mode 100644 drivers/staging/csr/init_hw.c create mode 100644 drivers/staging/csr/io.c create mode 100644 drivers/staging/csr/mlme.c create mode 100644 drivers/staging/csr/monitor.c create mode 100644 drivers/staging/csr/netdev.c create mode 100644 drivers/staging/csr/os.c create mode 100644 drivers/staging/csr/putest.c create mode 100644 drivers/staging/csr/sdio_emb.c create mode 100644 drivers/staging/csr/sdio_events.c create mode 100644 drivers/staging/csr/sdio_mmc.c create mode 100644 drivers/staging/csr/sdio_stubs.c create mode 100644 drivers/staging/csr/sdioemb/cspi.h create mode 100644 drivers/staging/csr/sdioemb/csr_result.h create mode 100644 drivers/staging/csr/sdioemb/csr_sdio.h create mode 100644 drivers/staging/csr/sdioemb/csr_sdio_lib.h create mode 100644 drivers/staging/csr/sdioemb/csr_sdio_wdf.h create mode 100644 drivers/staging/csr/sdioemb/csr_types.h create mode 100644 drivers/staging/csr/sdioemb/libsdio.h create mode 100644 drivers/staging/csr/sdioemb/linux.h create mode 100644 drivers/staging/csr/sdioemb/sdio.h create mode 100644 drivers/staging/csr/sdioemb/sdio_api.h create mode 100644 drivers/staging/csr/sdioemb/sdio_bt_a.h create mode 100644 drivers/staging/csr/sdioemb/sdio_cis.h create mode 100644 drivers/staging/csr/sdioemb/sdio_csr.h create mode 100644 drivers/staging/csr/sdioemb/slot_api.h create mode 100644 drivers/staging/csr/sdioemb/slot_imx27.h create mode 100644 drivers/staging/csr/sdioemb/slot_imx31.h create mode 100644 drivers/staging/csr/sdioemb/slot_pxa27x.h create mode 100644 drivers/staging/csr/sdioemb/slot_shc.h create mode 100644 drivers/staging/csr/sdioemb/slot_ushc.h create mode 100644 drivers/staging/csr/sdioemb/trace.h create mode 100644 drivers/staging/csr/sdioemb/uif.h create mode 100644 drivers/staging/csr/sdioemb/version.h create mode 100644 drivers/staging/csr/sme_blocking.c create mode 100644 drivers/staging/csr/sme_mgt.c create mode 100644 drivers/staging/csr/sme_native.c create mode 100644 drivers/staging/csr/sme_sys.c create mode 100644 drivers/staging/csr/sme_userspace.c create mode 100644 drivers/staging/csr/sme_userspace.h create mode 100644 drivers/staging/csr/sme_wext.c create mode 100644 drivers/staging/csr/ul_int.c create mode 100644 drivers/staging/csr/unifi_clients.h create mode 100644 drivers/staging/csr/unifi_config.h create mode 100644 drivers/staging/csr/unifi_dbg.c create mode 100644 drivers/staging/csr/unifi_event.c create mode 100644 drivers/staging/csr/unifi_native.h create mode 100644 drivers/staging/csr/unifi_os.h create mode 100644 drivers/staging/csr/unifi_pdu_processing.c create mode 100644 drivers/staging/csr/unifi_priv.h create mode 100644 drivers/staging/csr/unifi_sme.c create mode 100644 drivers/staging/csr/unifi_sme.h create mode 100644 drivers/staging/csr/unifi_wext.h create mode 100644 drivers/staging/csr/unifiio.h create mode 100644 drivers/staging/csr/wext_events.c diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig index 5d7b800058a3..e3a923ac6e75 100644 --- a/drivers/staging/csr/Kconfig +++ b/drivers/staging/csr/Kconfig @@ -1,6 +1,6 @@ config CSR_WIFI tristate "CSR wireless driver" - depends on PCI + depends on PCI && MMC help Driver for the CSR wireless SDIO device. diff --git a/drivers/staging/csr/LICENSE.txt b/drivers/staging/csr/LICENSE.txt new file mode 100644 index 000000000000..364853e5fedc --- /dev/null +++ b/drivers/staging/csr/LICENSE.txt @@ -0,0 +1,39 @@ +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. + +Except as contained in this notice, the names of above-listed +copyright holders and the names of any contributors shall not be used +in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization. + +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 HOLDERS OR +CONTRIBUTORS 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. + +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. + +As a special exception, if other files instantiate templates or use +macros or inline functions from this file, or you compile this file +and link it with other works to produce a work based on this file, +this file does not by itself cause the resulting work to be covered by +the GNU General Public License. However the source code for this file +must still be made available in accordance with section (3) of the GNU +General Public License. + +This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. diff --git a/drivers/staging/csr/Makefile b/drivers/staging/csr/Makefile index b9ba3b378e65..27eb4a77bc7f 100644 --- a/drivers/staging/csr/Makefile +++ b/drivers/staging/csr/Makefile @@ -1 +1,71 @@ obj-$(CONFIG_CSR_WIFI) += oska/ + +ccflags-y := -DCSR_SME_USERSPACE -DCSR_SUPPORT_SME -DREMOTE_SYS_SAP -DCSR_WIFI_SECURITY_WAPI_ENABLE -DENABLE_SHUTDOWN + +obj-$(CONFIG_CSR_WIFI) += csr_wifi.o +obj-$(CONFIG_CSR_WIFI) += csr_helper.o + +csr_wifi-y := bh.o \ + data_tx.o \ + drv.o \ + firmware.o \ + indications.o \ + inet.o \ + init_hw.o \ + io.o \ + monitor.o \ + netdev.o \ + os.o \ + putest.o \ + sdio_events.o \ + sdio_mmc.o \ + sdio_stubs.o \ + sme_blocking.o \ + ul_int.o \ + unifi_dbg.o \ + unifi_event.o \ + unifi_pdu_processing.o \ + unifi_sme.o \ + csr_formatted_io.o \ + csr_wifi_hip_card_sdio.o \ + csr_wifi_hip_card_sdio_intr.o \ + csr_wifi_hip_card_sdio_mem.o \ + csr_wifi_hip_chiphelper.o \ + csr_wifi_hip_download.o \ + csr_wifi_hip_dump.o \ + csr_wifi_hip_packing.o \ + csr_wifi_hip_send.o \ + csr_wifi_hip_signals.o \ + csr_wifi_hip_ta_sampling.o \ + csr_wifi_hip_udi.o \ + csr_wifi_hip_unifi_signal_names.o \ + csr_wifi_hip_xbv.o \ + csr_wifi_router_ctrl_sef.o \ + csr_wifi_router_sef.o \ + csr_wifi_router_transport.o \ + csr_wifi_sme_sef.o \ + csr_wifi_sme_converter_init.o \ + csr_wifi_sme_free_downstream_contents.o \ + csr_wifi_sme_free_upstream_contents.o \ + csr_wifi_sme_serialize.o \ + csr_wifi_router_ctrl_converter_init.o \ + csr_wifi_router_ctrl_free_downstream_contents.o \ + csr_wifi_router_ctrl_free_upstream_contents.o \ + csr_wifi_router_ctrl_serialize.o \ + csr_wifi_router_converter_init.o \ + csr_wifi_router_free_downstream_contents.o \ + csr_wifi_router_free_upstream_contents.o \ + csr_wifi_router_serialize.o \ + sme_mgt.o \ + sme_sys.o \ + sme_userspace.o + +csr_helper-y := csr_time.o \ + csr_util.o \ + csr_framework_ext.o \ + csr_pmem.o \ + csr_wifi_serialize_primitive_types.o \ + csr_serialize_primitive_types.o \ + csr_utf16.o \ + csr_msgconv.o \ + csr_panic.o diff --git a/drivers/staging/csr/bh.c b/drivers/staging/csr/bh.c new file mode 100644 index 000000000000..6af9d2953eae --- /dev/null +++ b/drivers/staging/csr/bh.c @@ -0,0 +1,391 @@ +/* + * --------------------------------------------------------------------------- + * FILE: bh.c + * + * PURPOSE: + * Provides an implementation for the driver bottom-half. + * It is part of the porting exercise in Linux. + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + +/* + * --------------------------------------------------------------------------- + * uf_start_thread + * + * Helper function to start a new thread. + * + * Arguments: + * priv Pointer to OS driver structure for the device. + * thread Pointer to the thread object + * func The thread function + * + * Returns: + * 0 on success or else a Linux error code. + * --------------------------------------------------------------------------- + */ +int +uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *)) +{ + if (thread->thread_task != NULL) { + unifi_error(priv, "%s thread already started\n", thread->name); + return 0; + } + + /* Start the kernel thread that handles all h/w accesses. */ + thread->thread_task = kthread_run(func, priv, "%s", thread->name); + if (IS_ERR(thread->thread_task)) { + return PTR_ERR(thread->thread_task); + } + + /* Module parameter overides the thread priority */ + if (bh_priority != -1) { + if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) { + struct sched_param param; + priv->bh_thread.prio = bh_priority; + unifi_trace(priv, UDBG1, "%s thread (RT) priority = %d\n", + thread->name, bh_priority); + param.sched_priority = bh_priority; + sched_setscheduler(thread->thread_task, SCHED_FIFO, ¶m); + } else if (bh_priority > MAX_RT_PRIO && bh_priority <= MAX_PRIO) { + priv->bh_thread.prio = bh_priority; + unifi_trace(priv, UDBG1, "%s thread priority = %d\n", + thread->name, PRIO_TO_NICE(bh_priority)); + set_user_nice(thread->thread_task, PRIO_TO_NICE(bh_priority)); + } else { + priv->bh_thread.prio = DEFAULT_PRIO; + unifi_warning(priv, "%s thread unsupported (%d) priority\n", + thread->name, bh_priority); + } + } else { + priv->bh_thread.prio = DEFAULT_PRIO; + } + unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name); + + return 0; +} /* uf_start_thread() */ + + +/* + * --------------------------------------------------------------------------- + * uf_stop_thread + * + * Helper function to stop a thread. + * + * Arguments: + * priv Pointer to OS driver structure for the device. + * thread Pointer to the thread object + * + * Returns: + * + * --------------------------------------------------------------------------- + */ + void +uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread) +{ + if (!thread->thread_task) { + unifi_notice(priv, "%s thread is already stopped\n", thread->name); + return; + } + + unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name); + + kthread_stop(thread->thread_task); + thread->thread_task = NULL; + +} /* uf_stop_thread() */ + + + +/* + * --------------------------------------------------------------------------- + * uf_wait_for_thread_to_stop + * + * Helper function to wait until a thread is stopped. + * + * Arguments: + * priv Pointer to OS driver structure for the device. + * + * Returns: + * + * --------------------------------------------------------------------------- + */ + void +uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread) +{ + /* + * kthread_stop() cannot handle the thread exiting while + * kthread_should_stop() is false, so sleep until kthread_stop() + * wakes us up. + */ + unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", thread->name); + set_current_state(TASK_INTERRUPTIBLE); + if (!kthread_should_stop()) { + unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name); + schedule(); + } + + thread->thread_task = NULL; + unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name); +} /* uf_wait_for_thread_to_stop() */ + + +/* + * --------------------------------------------------------------------------- + * handle_bh_error + * + * This function reports an error returned from the HIP core bottom-half. + * Normally, implemented during the porting exercise, passing the error + * to the SME using unifi_sys_wifi_off_ind(). + * The SME will try to reset the device and go through + * the initialisation of the UniFi. + * + * Arguments: + * priv Pointer to OS driver structure for the device. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ + static void +handle_bh_error(unifi_priv_t *priv) +{ + u8 conf_param = CONFIG_IND_ERROR; + CsrUint8 interfaceTag = 0; /* used as a loop counter */ + + + /* Block unifi_run_bh() until the error has been handled. */ + priv->bh_thread.block_thread = 1; + + /* Consider UniFi to be uninitialised */ + priv->init_progress = UNIFI_INIT_NONE; + + /* Stop the network traffic */ + for( interfaceTag =0; interfaceTag interfacePriv[interfaceTag]; + if (interfacePriv->netdev_registered == 1) { + netif_carrier_off(priv->netdev[interfaceTag]); + } + } + +#ifdef CSR_NATIVE_LINUX + /* Force any client waiting on an mlme_wait_for_reply() to abort. */ + uf_abort_mlme(priv); + + /* Cancel any pending workqueue tasks */ + flush_workqueue(priv->unifi_workqueue); + +#endif /* CSR_NATIVE_LINUX */ + + unifi_error(priv, "handle_bh_error: fatal error is reported to the SME.\n"); + /* Notify the clients (SME or unifi_manager) for the error. */ + ul_log_config_ind(priv, &conf_param, sizeof(u8)); + +} /* handle_bh_error() */ + + + +/* + * --------------------------------------------------------------------------- + * bh_thread_function + * + * All hardware access happens in this thread. + * This means there is no need for locks on the hardware and we don't need + * to worry about reentrancy with the SDIO library. + * Provides and example implementation on how to call unifi_bh(), which + * is part of the HIP core API. + * + * It processes the events generated by unifi_run_bh() to serialise calls + * to unifi_bh(). It also demonstrates how the timeout parameter passed in + * and returned from unifi_bh() needs to be handled. + * + * Arguments: + * arg Pointer to OS driver structure for the device. + * + * Returns: + * None. + * + * Notes: + * When the bottom half of the driver needs to process signals, events, + * or simply the host status (i.e sleep mode), it invokes unifi_run_bh(). + * Since we need all SDIO transaction to be in a single thread, the + * unifi_run_bh() will wake up this thread to process it. + * + * --------------------------------------------------------------------------- + */ +static int +bh_thread_function(void *arg) +{ + unifi_priv_t *priv = (unifi_priv_t*)arg; + CsrResult csrResult; + long ret; + CsrUint32 timeout, t; + struct uf_thread *this_thread; + + unifi_trace(priv, UDBG2, "bh_thread_function starting\n"); + + this_thread = &priv->bh_thread; + + t = timeout = 0; + while (!kthread_should_stop()) { + /* wait until an error occurs, or we need to process something. */ + unifi_trace(priv, UDBG3, "bh_thread goes to sleep.\n"); + + if (timeout > 0) { + /* Convert t in ms to jiffies */ + t = msecs_to_jiffies(timeout); + ret = wait_event_interruptible_timeout(this_thread->wakeup_q, + (this_thread->wakeup_flag && !this_thread->block_thread) || + kthread_should_stop(), + t); + timeout = (ret > 0) ? jiffies_to_msecs(ret) : 0; + } else { + ret = wait_event_interruptible(this_thread->wakeup_q, + (this_thread->wakeup_flag && !this_thread->block_thread) || + kthread_should_stop()); + } + + if (kthread_should_stop()) { + unifi_trace(priv, UDBG2, "bh_thread: signalled to exit\n"); + break; + } + + if (ret < 0) { + unifi_notice(priv, + "bh_thread: wait_event returned %d, thread will exit\n", + ret); + uf_wait_for_thread_to_stop(priv, this_thread); + break; + } + + this_thread->wakeup_flag = 0; + + unifi_trace(priv, UDBG3, "bh_thread calls unifi_bh().\n"); + + CsrSdioClaim(priv->sdio); + csrResult = unifi_bh(priv->card, &timeout); + if(csrResult != CSR_RESULT_SUCCESS) { + if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) { + CsrSdioRelease(priv->sdio); + uf_wait_for_thread_to_stop(priv, this_thread); + break; + } + /* Errors must be delivered to the error task */ + handle_bh_error(priv); + } + CsrSdioRelease(priv->sdio); + } + + /* + * I would normally try to call csr_sdio_remove_irq() here to make sure + * that we do not get any interrupts while this thread is not running. + * However, the MMC/SDIO driver tries to kill its' interrupt thread. + * The kernel threads implementation does not allow to kill threads + * from a signalled to stop thread. + * So, instead call csr_sdio_linux_remove_irq() always after calling + * uf_stop_thread() to kill this thread. + */ + + unifi_trace(priv, UDBG2, "bh_thread exiting....\n"); + return 0; +} /* bh_thread_function() */ + + +/* + * --------------------------------------------------------------------------- + * uf_init_bh + * + * Helper function to start the bottom half of the driver. + * All we need to do here is start the I/O bh thread. + * + * Arguments: + * priv Pointer to OS driver structure for the device. + * + * Returns: + * 0 on success or else a Linux error code. + * --------------------------------------------------------------------------- + */ + int +uf_init_bh(unifi_priv_t *priv) +{ + int r; + + /* Enable mlme interface. */ + priv->io_aborted = 0; + + + /* Start the BH thread */ + r = uf_start_thread(priv, &priv->bh_thread, bh_thread_function); + if (r) { + unifi_error(priv, + "uf_init_bh: failed to start the BH thread.\n"); + return r; + } + + /* Allow interrupts */ + r = csr_sdio_linux_install_irq(priv->sdio); + if (r) { + unifi_error(priv, + "uf_init_bh: failed to install the IRQ.\n"); + + uf_stop_thread(priv, &priv->bh_thread); + } + + return r; +} /* uf_init_bh() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_run_bh + * + * Part of the HIP core lib API, implemented in the porting exercise. + * The bottom half of the driver calls this function when + * it wants to process anything that requires access to unifi. + * We need to call unifi_bh() which in this implementation is done + * by waking up the I/O thread. + * + * Arguments: + * ospriv Pointer to OS driver structure for the device. + * + * Returns: + * 0 on success or else a Linux error code. + * + * Notes: + * --------------------------------------------------------------------------- + */ +CsrResult unifi_run_bh(void *ospriv) +{ + unifi_priv_t *priv = ospriv; + + /* + * If an error has occured, we discard silently all messages from the bh + * until the error has been processed and the unifi has been reinitialised. + */ + if (priv->bh_thread.block_thread == 1) { + unifi_trace(priv, UDBG3, "unifi_run_bh: discard message.\n"); + /* + * Do not try to acknowledge a pending interrupt here. + * This function is called by unifi_send_signal() which in turn can be + * running in an atomic or 'disabled irq' level if a signal is sent + * from a workqueue task (i.e multicass addresses set). + * We can not hold the SDIO lock because it might sleep. + */ + return CSR_RESULT_FAILURE; + } + + priv->bh_thread.wakeup_flag = 1; + /* wake up I/O thread */ + wake_up_interruptible(&priv->bh_thread.wakeup_q); + + return CSR_RESULT_SUCCESS; +} /* unifi_run_bh() */ + diff --git a/drivers/staging/csr/csr_formatted_io.c b/drivers/staging/csr/csr_formatted_io.c new file mode 100644 index 000000000000..bd6456bcf866 --- /dev/null +++ b/drivers/staging/csr/csr_formatted_io.c @@ -0,0 +1,29 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_formatted_io.h" +#include "csr_util.h" + +CsrInt32 CsrSnprintf(CsrCharString *dest, CsrSize n, const CsrCharString *fmt, ...) +{ + CsrInt32 r; + va_list args; + va_start(args, fmt); + r = CsrVsnprintf(dest, n, fmt, args); + va_end(args); + + if (dest && (n > 0)) + { + dest[n - 1] = '\0'; + } + + return r; +} diff --git a/drivers/staging/csr/csr_formatted_io.h b/drivers/staging/csr/csr_formatted_io.h new file mode 100644 index 000000000000..b458eb5ce9cd --- /dev/null +++ b/drivers/staging/csr/csr_formatted_io.h @@ -0,0 +1,25 @@ +#ifndef CSR_FORMATTED_IO_H__ +#define CSR_FORMATTED_IO_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_types.h" + +CsrInt32 CsrSnprintf(CsrCharString *dest, CsrSize n, const CsrCharString *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_framework_ext.c b/drivers/staging/csr/csr_framework_ext.c new file mode 100644 index 000000000000..0406a4b0f786 --- /dev/null +++ b/drivers/staging/csr/csr_framework_ext.c @@ -0,0 +1,213 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) +#include +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) +#include +#else +#include +#endif + +#include + +#include "csr_types.h" +#include "csr_framework_ext.h" +#include "csr_panic.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexCreate + * + * DESCRIPTION + * Create a mutex and return a handle to the created mutex. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_NO_MORE_MUTEXES in case of out of mutex resources + * CSR_FE_RESULT_INVALID_POINTER in case the mutexHandle pointer is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexCreate(CsrMutexHandle *mutexHandle) +{ + if (mutexHandle == NULL) + { + return CSR_FE_RESULT_INVALID_POINTER; + } + + sema_init(mutexHandle, 1); + + return CSR_RESULT_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexDestroy + * + * DESCRIPTION + * Destroy the previously created mutex. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMutexDestroy(CsrMutexHandle *mutexHandle) +{ +} + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexLock + * + * DESCRIPTION + * Lock the mutex refered to by the provided handle. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_HANDLE in case the mutexHandle is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexLock(CsrMutexHandle *mutexHandle) +{ + if (mutexHandle == NULL) + { + return CSR_FE_RESULT_INVALID_POINTER; + } + + if (down_interruptible(mutexHandle)) + { + CsrPanic(CSR_TECH_FW, CSR_PANIC_FW_UNEXPECTED_VALUE, "CsrMutexLock Failed"); + return CSR_FE_RESULT_INVALID_POINTER; + } + + return CSR_RESULT_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexUnlock + * + * DESCRIPTION + * Unlock the mutex refered to by the provided handle. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_HANDLE in case the mutexHandle is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexUnlock(CsrMutexHandle *mutexHandle) +{ + if (mutexHandle == NULL) + { + return CSR_FE_RESULT_INVALID_POINTER; + } + + up(mutexHandle); + + return CSR_RESULT_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * NAME + * CsrThreadSleep + * + * DESCRIPTION + * Sleep for a given period. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrThreadSleep(CsrUint16 sleepTimeInMs) +{ + unsigned long t; + + /* Convert t in ms to jiffies and round up */ + t = ((sleepTimeInMs * HZ) + 999) / 1000; + schedule_timeout_uninterruptible(t); +} +EXPORT_SYMBOL_GPL(CsrThreadSleep); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemCalloc + * + * DESCRIPTION + * Allocate dynamic memory of a given size calculated as the + * numberOfElements times the elementSize. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is zero initialised. + * + *----------------------------------------------------------------------------*/ +void *CsrMemCalloc(CsrSize numberOfElements, CsrSize elementSize) +{ + void *buf; + size_t size; + + size = numberOfElements * elementSize; + + buf = kmalloc(size, GFP_KERNEL); + if (buf != NULL) + { + memset(buf, 0, size); + } + + return buf; +} + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemAlloc + * + * DESCRIPTION + * Allocate dynamic memory of a given size. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is not initialised. + * + *----------------------------------------------------------------------------*/ +void *CsrMemAlloc(CsrSize size) +{ + return kmalloc(size, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(CsrMemAlloc); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemFree + * + * DESCRIPTION + * Free dynamic allocated memory. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMemFree(void *pointer) +{ + kfree(pointer); +} +EXPORT_SYMBOL_GPL(CsrMemFree); diff --git a/drivers/staging/csr/csr_framework_ext.h b/drivers/staging/csr/csr_framework_ext.h new file mode 100644 index 000000000000..401bf2d547a3 --- /dev/null +++ b/drivers/staging/csr/csr_framework_ext.h @@ -0,0 +1,354 @@ +#ifndef CSR_FRAMEWORK_EXT_H__ +#define CSR_FRAMEWORK_EXT_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_result.h" +#include "csr_framework_ext_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Result codes */ +#define CSR_FE_RESULT_NO_MORE_EVENTS ((CsrResult) 0x0001) +#define CSR_FE_RESULT_INVALID_POINTER ((CsrResult) 0x0002) +#define CSR_FE_RESULT_INVALID_HANDLE ((CsrResult) 0x0003) +#define CSR_FE_RESULT_NO_MORE_MUTEXES ((CsrResult) 0x0004) +#define CSR_FE_RESULT_TIMEOUT ((CsrResult) 0x0005) +#define CSR_FE_RESULT_NO_MORE_THREADS ((CsrResult) 0x0006) + +/* Thread priorities */ +#define CSR_THREAD_PRIORITY_HIGHEST ((CsrUint16) 0) +#define CSR_THREAD_PRIORITY_HIGH ((CsrUint16) 1) +#define CSR_THREAD_PRIORITY_NORMAL ((CsrUint16) 2) +#define CSR_THREAD_PRIORITY_LOW ((CsrUint16) 3) +#define CSR_THREAD_PRIORITY_LOWEST ((CsrUint16) 4) + +#define CSR_EVENT_WAIT_INFINITE ((CsrUint16) 0xFFFF) + +/*----------------------------------------------------------------------------* + * NAME + * CsrEventCreate + * + * DESCRIPTION + * Creates an event and returns a handle to the created event. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_NO_MORE_EVENTS in case of out of event resources + * CSR_FE_RESULT_INVALID_POINTER in case the eventHandle pointer is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrEventCreate(CsrEventHandle *eventHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrEventWait + * + * DESCRIPTION + * Wait fore one or more of the event bits to be set. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_TIMEOUT in case of timeout + * CSR_FE_RESULT_INVALID_HANDLE in case the eventHandle is invalid + * CSR_FE_RESULT_INVALID_POINTER in case the eventBits pointer is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrEventWait(CsrEventHandle *eventHandle, CsrUint16 timeoutInMs, CsrUint32 *eventBits); + +/*----------------------------------------------------------------------------* + * NAME + * CsrEventSet + * + * DESCRIPTION + * Set an event. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_HANDLE in case the eventHandle is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrEventSet(CsrEventHandle *eventHandle, CsrUint32 eventBits); + +/*----------------------------------------------------------------------------* + * NAME + * CsrEventDestroy + * + * DESCRIPTION + * Destroy the event associated. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrEventDestroy(CsrEventHandle *eventHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexCreate + * + * DESCRIPTION + * Create a mutex and return a handle to the created mutex. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_NO_MORE_MUTEXES in case of out of mutex resources + * CSR_FE_RESULT_INVALID_POINTER in case the mutexHandle pointer is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexCreate(CsrMutexHandle *mutexHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexLock + * + * DESCRIPTION + * Lock the mutex refered to by the provided handle. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_HANDLE in case the mutexHandle is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexLock(CsrMutexHandle *mutexHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexUnlock + * + * DESCRIPTION + * Unlock the mutex refered to by the provided handle. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_HANDLE in case the mutexHandle is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrMutexUnlock(CsrMutexHandle *mutexHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMutexDestroy + * + * DESCRIPTION + * Destroy the previously created mutex. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMutexDestroy(CsrMutexHandle *mutexHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrGlobalMutexLock + * + * DESCRIPTION + * Lock the global mutex. The global mutex is a single pre-initialised + * shared mutex, spinlock or similar that does not need to be created prior + * to use. The limitation is that there is only one single lock shared + * between all code. Consequently, it must only be used very briefly to + * either protect simple one-time initialisation or to protect the creation + * of a dedicated mutex by calling CsrMutexCreate. + * + *----------------------------------------------------------------------------*/ +void CsrGlobalMutexLock(void); + +/*----------------------------------------------------------------------------* + * NAME + * CsrGlobalMutexUnlock + * + * DESCRIPTION + * Unlock the global mutex. + * + *----------------------------------------------------------------------------*/ +void CsrGlobalMutexUnlock(void); + +/*----------------------------------------------------------------------------* + * NAME + * CsrThreadCreate + * + * DESCRIPTION + * Create thread function and return a handle to the created thread. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_NO_MORE_THREADS in case of out of thread resources + * CSR_FE_RESULT_INVALID_POINTER in case one of the supplied pointers is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrThreadCreate(void (*threadFunction)(void *pointer), void *pointer, + CsrUint32 stackSize, CsrUint16 priority, + const CsrCharString *threadName, CsrThreadHandle *threadHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrThreadGetHandle + * + * DESCRIPTION + * Return thread handle of calling thread. + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case of success + * CSR_FE_RESULT_INVALID_POINTER in case the threadHandle pointer is invalid + * + *----------------------------------------------------------------------------*/ +CsrResult CsrThreadGetHandle(CsrThreadHandle *threadHandle); + +/*----------------------------------------------------------------------------* + * NAME + * CsrThreadEqual + * + * DESCRIPTION + * Compare thread handles + * + * RETURNS + * Possible values: + * CSR_RESULT_SUCCESS in case thread handles are identical + * CSR_FE_RESULT_INVALID_POINTER in case either threadHandle pointer is invalid + * CSR_RESULT_FAILURE otherwise + * + *----------------------------------------------------------------------------*/ +CsrResult CsrThreadEqual(CsrThreadHandle *threadHandle1, CsrThreadHandle *threadHandle2); + +/*----------------------------------------------------------------------------* + * NAME + * CsrThreadSleep + * + * DESCRIPTION + * Sleep for a given period. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrThreadSleep(CsrUint16 sleepTimeInMs); + +#ifndef CSR_PMEM_DEBUG_ENABLE +/*----------------------------------------------------------------------------* + * NAME + * CsrMemAlloc + * + * DESCRIPTION + * Allocate dynamic memory of a given size. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is not initialised. + * + *----------------------------------------------------------------------------*/ +#ifdef CSR_MEM_DEBUG +void *CsrMemAllocDebug(CsrSize size, + const CsrCharString *file, CsrUint32 line); +#define CsrMemAlloc(sz) CsrMemAllocDebug((sz), __FILE__, __LINE__) +#else +void *CsrMemAlloc(CsrSize size); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemCalloc + * + * DESCRIPTION + * Allocate dynamic memory of a given size calculated as the + * numberOfElements times the elementSize. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is zero initialised. + * + *----------------------------------------------------------------------------*/ +#ifdef CSR_MEM_DEBUG +void *CsrMemCallocDebug(CsrSize numberOfElements, CsrSize elementSize, + const CsrCharString *file, CsrUint32 line); +#define CsrMemCalloc(cnt, sz) CsrMemAllocDebug((cnt), (sz), __FILE__, __LINE__) +#else +void *CsrMemCalloc(CsrSize numberOfElements, CsrSize elementSize); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemFree + * + * DESCRIPTION + * Free dynamic allocated memory. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMemFree(void *pointer); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemAllocDma + * + * DESCRIPTION + * Allocate dynamic memory suitable for DMA transfers. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is not initialised. + * + *----------------------------------------------------------------------------*/ +#ifdef CSR_MEM_DEBUG +void *CsrMemAllocDmaDebug(CsrSize size, + const CsrCharString *file, CsrUint32 line); +#define CsrMemAllocDma(sz) CsrMemAllocDmaDebug((sz), __FILE__, __LINE__) +#else +void *CsrMemAllocDma(CsrSize size); +#endif + + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemFreeDma + * + * DESCRIPTION + * Free dynamic memory allocated by CsrMemAllocDma. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMemFreeDma(void *pointer); +#else + +#include "csr_pmem.h" + +#define CsrMemAlloc(size) CsrPmemDebugAlloc(size, CSR_PMEM_DEBUG_TYPE_MEM_ALLOC, __FILE__, __LINE__) + +#define CsrMemCalloc(numberOfElements, elementSize) CsrPmemDebugAlloc((numberOfElements * elementSize), CSR_PMEM_DEBUG_TYPE_MEM_CALLOC, __FILE__, __LINE__) + +#define CsrMemFree(ptr) CsrPmemDebugFree(ptr,CSR_PMEM_DEBUG_TYPE_MEM_ALLOC, __FILE__, __LINE__) + +#define CsrMemAllocDma(size) CsrPmemDebugAlloc(size, CSR_PMEM_DEBUG_TYPE_MEM_ALLOC_DMA, __FILE__, __LINE__) + +#define CsrMemFreeDma(ptr) CsrPmemDebugFree(ptr, CSR_PMEM_DEBUG_TYPE_MEM_ALLOC_DMA, __FILE__, __LINE__) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_framework_ext_types.h b/drivers/staging/csr/csr_framework_ext_types.h new file mode 100644 index 000000000000..d155a2b8eee6 --- /dev/null +++ b/drivers/staging/csr/csr_framework_ext_types.h @@ -0,0 +1,65 @@ +#ifndef CSR_FRAMEWORK_EXT_TYPES_H__ +#define CSR_FRAMEWORK_EXT_TYPES_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" + +#ifdef __KERNEL__ +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __KERNEL__ + +struct CsrThread +{ + struct task_struct *thread_task; + char name[16]; +}; + +struct CsrEvent +{ + /* wait_queue for waking the kernel thread */ + wait_queue_head_t wakeup_q; + unsigned int wakeup_flag; +}; + +typedef struct CsrEvent CsrEventHandle; +typedef struct semaphore CsrMutexHandle; +typedef struct CsrThread CsrThreadHandle; + +#else /* __KERNEL __ */ + +struct CsrEvent +{ + pthread_cond_t event; + pthread_mutex_t mutex; + CsrUint32 eventBits; +}; + +typedef struct CsrEvent CsrEventHandle; +typedef pthread_mutex_t CsrMutexHandle; +typedef pthread_t CsrThreadHandle; + +#endif /* __KERNEL__ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_lib.h b/drivers/staging/csr/csr_lib.h new file mode 100644 index 000000000000..171f5feeea94 --- /dev/null +++ b/drivers/staging/csr/csr_lib.h @@ -0,0 +1,189 @@ +#ifndef CSR_LIB_H__ +#define CSR_LIB_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_prim_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + CsrPrim type; +} CsrEvent; + +/*----------------------------------------------------------------------------* + * CsrEvent_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEvent + * + *----------------------------------------------------------------------------*/ +CsrEvent *CsrEvent_struct(CsrUint16 primtype, CsrUint16 msgtype); + +typedef struct +{ + CsrPrim type; + CsrUint8 value; +} CsrEventCsrUint8; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint8_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint8 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint8 *CsrEventCsrUint8_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint8 value); + +typedef struct +{ + CsrPrim type; + CsrUint16 value; +} CsrEventCsrUint16; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint16_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint16 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint16 *CsrEventCsrUint16_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint16 value); + +typedef struct +{ + CsrPrim type; + CsrUint16 value1; + CsrUint8 value2; +} CsrEventCsrUint16CsrUint8; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint16CsrUint8_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint16CsrUint8 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint16CsrUint8 *CsrEventCsrUint16CsrUint8_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint16 value1, CsrUint8 value2); + +typedef struct +{ + CsrPrim type; + CsrUint16 value1; + CsrUint16 value2; +} CsrEventCsrUint16CsrUint16; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint16CsrUint16_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint16CsrUint16 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint16CsrUint16 *CsrEventCsrUint16CsrUint16_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint16 value1, CsrUint16 value2); + +typedef struct +{ + CsrPrim type; + CsrUint16 value1; + CsrUint32 value2; +} CsrEventCsrUint16CsrUint32; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint16_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint16 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint16CsrUint32 *CsrEventCsrUint16CsrUint32_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint16 value1, CsrUint32 value2); + +typedef struct +{ + CsrPrim type; + CsrUint16 value1; + CsrCharString *value2; +} CsrEventCsrUint16CsrCharString; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint16CsrCharString_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint16CsrCharString + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint16CsrCharString *CsrEventCsrUint16CsrCharString_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint16 value1, CsrCharString *value2); + +typedef struct +{ + CsrPrim type; + CsrUint32 value; +} CsrEventCsrUint32; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint32_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint32 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint32 *CsrEventCsrUint32_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint32 value); + +typedef struct +{ + CsrPrim type; + CsrUint32 value1; + CsrUint16 value2; +} CsrEventCsrUint32CsrUint16; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint32CsrUint16_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint32CsrUint16 + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint32CsrUint16 *CsrEventCsrUint32CsrUint16_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint32 value1, CsrUint32 value2); + +typedef struct +{ + CsrPrim type; + CsrUint32 value1; + CsrCharString *value2; +} CsrEventCsrUint32CsrCharString; + +/*----------------------------------------------------------------------------* + * CsrEventCsrUint32CsrCharString_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrEventCsrUint32CsrCharString + * + *----------------------------------------------------------------------------*/ +CsrEventCsrUint32CsrCharString *CsrEventCsrUint32CsrCharString_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrUint32 value1, CsrCharString *value2); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_LIB_H__ */ diff --git a/drivers/staging/csr/csr_log.h b/drivers/staging/csr/csr_log.h new file mode 100644 index 000000000000..db2653c30ea6 --- /dev/null +++ b/drivers/staging/csr/csr_log.h @@ -0,0 +1,250 @@ +#ifndef CSR_LOG_H__ +#define CSR_LOG_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_sched.h" +#include "csr_panic.h" +#include "csr_prim_defs.h" +#include "csr_msgconv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Log filtering + */ + +/*----------------------------------------------------*/ +/* Filtering on environment specific log levels */ +/*----------------------------------------------------*/ +typedef CsrUint32 CsrLogLevelEnvironment; +#define CSR_LOG_LEVEL_ENVIRONMENT_OFF ((CsrLogLevelEnvironment) 0x00000000) /* No environment data/events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_ACL ((CsrLogLevelEnvironment) 0x00000001) /* BlueCore Channel Interface HCI Acl data are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_HCI ((CsrLogLevelEnvironment) 0x00000002) /* BlueCore Channel Interface HCI Cmd/Evt data are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_SCO ((CsrLogLevelEnvironment) 0x00000004) /* BlueCore Channel Interface HCI Sco data are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_VENDOR ((CsrLogLevelEnvironment) 0x00000008) /* BlueCore Channel Interface HCI Vendor specific data are logged (This includes BCCMD, HQ, VM etc) */ +#define CSR_LOG_LEVEL_ENVIRONMENT_TRANSPORTS ((CsrLogLevelEnvironment) 0x00000010) /* Transport protocol data is logged (This includes transport protocols like BCSP, H4 etc.) */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_REG ((CsrLogLevelEnvironment) 0x00000020) /* Background Interrupt registration events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_UNREG ((CsrLogLevelEnvironment) 0x00000040) /* Background Interrupt unregistration events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_SET ((CsrLogLevelEnvironment) 0x00000080) /* Background Interrupt set events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_START ((CsrLogLevelEnvironment) 0x00000100) /* Background Interrupt start events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_DONE ((CsrLogLevelEnvironment) 0x00000200) /* Background Interrupt done events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_PROTO ((CsrLogLevelEnvironment) 0x00000400) /* Transport protocol events are logged */ +#define CSR_LOG_LEVEL_ENVIRONMENT_PROTO_LOC ((CsrLogLevelEnvironment) 0x00000800) /* The Location where the transport protocol event occured are logged NB: This is a supplement to CSR_LOG_LEVEL_ENVIRONMENT_PROTO, it has no effect without it */ +/* The bit masks between here are reserved for future usage */ +#define CSR_LOG_LEVEL_ENVIRONMENT_ALL ((CsrLogLevelEnvironment) 0xFFFFFFFF) /* All possible environment data/events are logged WARNING: By using this define the application also accepts future possible environment data/events in the logs */ + +/*----------------------------------------------------*/ +/* Filtering on task specific log levels */ +/*----------------------------------------------------*/ +typedef CsrUint32 CsrLogLevelTask; +#define CSR_LOG_LEVEL_TASK_OFF ((CsrLogLevelTask) 0x00000000) /* No events are logged for this task */ +#define CSR_LOG_LEVEL_TASK_TEXT ((CsrLogLevelTask) 0x00000001) /* Text strings printed by a task are logged NB: This bit does not affect the CSR_LOG_TEXT_LEVEL interface. This has to be configured separately */ +#define CSR_LOG_LEVEL_TASK_TEXT_LOC ((CsrLogLevelTask) 0x00000002) /* The locaction where the text string call occured are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TEXT, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_STATE ((CsrLogLevelTask) 0x00000004) /* FSM state transitions in a task are logged */ +#define CSR_LOG_LEVEL_TASK_STATE_NAME ((CsrLogLevelTask) 0x00000008) /* The name of each state in a FSM state transition are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_STATE, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_STATE_LOC ((CsrLogLevelTask) 0x00000010) /* The location where the FSM state transition occured are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_STATE, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_TASK_SWITCH ((CsrLogLevelTask) 0x00000020) /* Activation and deactiation of a task are logged */ +#define CSR_LOG_LEVEL_TASK_MESSAGE_PUT ((CsrLogLevelTask) 0x00000080) /* Message put operations are logged */ +#define CSR_LOG_LEVEL_TASK_MESSAGE_PUT_LOC ((CsrLogLevelTask) 0x00000100) /* The location where a message was sent are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_MESSAGE_PUT, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_MESSAGE_GET ((CsrLogLevelTask) 0x00000200) /* Message get operations are logged */ +#define CSR_LOG_LEVEL_TASK_MESSAGE_QUEUE_PUSH ((CsrLogLevelTask) 0x00000400) /* Message push operations are logged */ +#define CSR_LOG_LEVEL_TASK_MESSAGE_QUEUE_POP ((CsrLogLevelTask) 0x00000800) /* Message pop operations are logged */ +#define CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE ((CsrLogLevelTask) 0x00001000) /* Only the type of primitives in messages are logged. By default the entire primitive is serialized and logged */ +#define CSR_LOG_LEVEL_TASK_PRIM_APPLY_LIMIT ((CsrLogLevelTask) 0x00002000) /* An upper limit (defined by CSR_LOG_PRIM_SIZE_UPPER_LIMIT) is applied to how much of a primitive in a message are logged. NB: This limit is only applied if CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE is _not_ defined */ +#define CSR_LOG_LEVEL_TASK_TIMER_IN ((CsrLogLevelTask) 0x00004000) /* TimedEventIn events are logged */ +#define CSR_LOG_LEVEL_TASK_TIMER_IN_LOC ((CsrLogLevelTask) 0x00008000) /* The location where a timer was started are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TIMER_IN, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_TIMER_CANCEL ((CsrLogLevelTask) 0x00010000) /* TimedEventCancel events are logged */ +#define CSR_LOG_LEVEL_TASK_TIMER_CANCEL_LOC ((CsrLogLevelTask) 0x00020000) /* The location where a timer was cancelled are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TIMER_CANCEL, it has no effect without it */ +#define CSR_LOG_LEVEL_TASK_TIMER_FIRE ((CsrLogLevelTask) 0x00040000) /* TimedEventFire events are logged */ +#define CSR_LOG_LEVEL_TASK_TIMER_DONE ((CsrLogLevelTask) 0x00080000) /* TimedEventDone events are logged */ +/* The bit masks between here are reserved for future usage */ +#define CSR_LOG_LEVEL_TASK_ALL ((CsrLogLevelTask) 0xFFFFFFFF & ~(CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE | CSR_LOG_LEVEL_TASK_PRIM_APPLY_LIMIT)) /* All info possible to log for a task are logged. WARNING: By using this define the application also accepts future possible task data/events in the logs */ + +CsrBool CsrLogEnvironmentIsFiltered(CsrLogLevelEnvironment level); +CsrLogLevelTask CsrLogTaskFilterGet(CsrSchedQid taskId); +CsrBool CsrLogTaskIsFiltered(CsrSchedQid taskId, CsrLogLevelTask level); + +/* + * Logging stuff + */ +#define CSR_LOG_STRINGIFY_REAL(a) #a +#define CSR_LOG_STRINGIFY(a) CSR_LOG_STRINGIFY_REAL(a) + +#ifdef CSR_LOG_ASSERT_ENABLE +#define CSR_LOG_ASSERT(cond) \ + do { \ + if (!(cond)) \ + { \ + CsrCharString *panic_arg = "[" __FILE__ ":" CSR_LOG_STRINGIFY(__LINE__) "] - " CSR_LOG_STRINGIFY(cond); \ + CsrPanic(CSR_TECH_FW, CSR_PANIC_FW_ASSERTION_FAIL, panic_arg); \ + } \ + } while (0) +#else +#define CSR_LOG_ASSERT(cond) +#endif + +typedef struct +{ + CsrUint16 primitiveType; + const CsrCharString *primitiveName; + CsrMsgConvMsgEntry *messageConv; /* Private - do not use */ +} CsrLogPrimitiveInformation; + +typedef struct +{ + const CsrCharString *techVer; + CsrUint32 primitiveInfoCount; + CsrLogPrimitiveInformation *primitiveInfo; +} CsrLogTechInformation; + +/*---------------------------------*/ +/* Tech logging */ +/*---------------------------------*/ +typedef CsrUint8 bitmask8_t; +typedef CsrUint16 bitmask16_t; +typedef CsrUint32 bitmask32_t; + +#ifdef CSR_LOG_ENABLE +#ifdef CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER +/* DEPRECATED - replaced by csr_log_text.h */ +#define CSR_LOG_TEXT(text) \ + do { \ + if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) \ + { \ + CsrLogTaskText(text, __LINE__, __FILE__); \ + } \ + } while (0) +#else +/* DEPRECATED - replaced by csr_log_text.h */ +#define CSR_LOG_TEXT(text) \ + do { \ + if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) \ + { \ + CsrLogTaskText(text, 0, NULL); \ + } \ + } while (0) +#endif +#else +#define CSR_LOG_TEXT(text) +#endif + +/* DEPRECATED - replaced by csr_log_text.h */ +void CsrLogTaskText(const CsrCharString *text, + CsrUint32 line, + const CsrCharString *file); + +#define CSR_LOG_STATE_TRANSITION_MASK_FSM_NAME (0x001) +#define CSR_LOG_STATE_TRANSITION_MASK_NEXT_STATE (0x002) +#define CSR_LOG_STATE_TRANSITION_MASK_NEXT_STATE_STR (0x004) +#define CSR_LOG_STATE_TRANSITION_MASK_PREV_STATE (0x008) +#define CSR_LOG_STATE_TRANSITION_MASK_PREV_STATE_STR (0x010) +#define CSR_LOG_STATE_TRANSITION_MASK_EVENT (0x020) +#define CSR_LOG_STATE_TRANSITION_MASK_EVENT_STR (0x040) + +/* DEPRECATED - replaced by csr_log_text.h */ +void CsrLogStateTransition(bitmask16_t mask, + CsrUint32 identifier, + const CsrCharString *fsm_name, + CsrUint32 prev_state, + const CsrCharString *prev_state_str, + CsrUint32 in_event, + const CsrCharString *in_event_str, + CsrUint32 next_state, + const CsrCharString *next_state_str, + CsrUint32 line, + const CsrCharString *file); + +/*---------------------------------*/ +/* BSP logging */ +/*---------------------------------*/ +void CsrLogSchedInit(CsrUint8 thread_id); +void CsrLogSchedDeinit(CsrUint8 thread_id); + +void CsrLogSchedStart(CsrUint8 thread_id); +void CsrLogSchedStop(CsrUint8 thread_id); + +void CsrLogInitTask(CsrUint8 thread_id, CsrSchedQid tskid, const CsrCharString *tskName); +void CsrLogDeinitTask(CsrUint16 task_id); + +void CsrLogActivate(CsrSchedQid tskid); +void CsrLogDeactivate(CsrSchedQid tskid); + +#define SYNERGY_SERIALIZER_TYPE_DUMP (0x000) +#define SYNERGY_SERIALIZER_TYPE_SER (0x001) + +void CsrLogMessagePut(CsrUint32 line, + const CsrCharString *file, + CsrSchedQid src_task_id, + CsrSchedQid dst_taskid, + CsrSchedMsgId msg_id, + CsrUint16 prim_type, + const void *msg); + +void CsrLogMessageGet(CsrSchedQid src_task_id, + CsrSchedQid dst_taskid, + CsrBool get_res, + CsrSchedMsgId msg_id, + CsrUint16 prim_type, + const void *msg); + +void CsrLogTimedEventIn(CsrUint32 line, + const CsrCharString *file, + CsrSchedQid task_id, + CsrSchedTid tid, + CsrTime requested_delay, + CsrUint16 fniarg, + const void *fnvarg); + +void CsrLogTimedEventFire(CsrSchedQid task_id, + CsrSchedTid tid); + +void CsrLogTimedEventDone(CsrSchedQid task_id, + CsrSchedTid tid); + +void CsrLogTimedEventCancel(CsrUint32 line, + const CsrCharString *file, + CsrSchedQid task_id, + CsrSchedTid tid, + CsrBool cancel_res); + +void CsrLogBgintRegister(CsrUint8 thread_id, + CsrSchedBgint irq, + const CsrCharString *callback, + const void *ptr); +void CsrLogBgintUnregister(CsrSchedBgint irq); +void CsrLogBgintSet(CsrSchedBgint irq); +void CsrLogBgintServiceStart(CsrSchedBgint irq); +void CsrLogBgintServiceDone(CsrSchedBgint irq); + +void CsrLogExceptionStateEvent(CsrUint16 prim_type, + CsrPrim msg_type, + CsrUint16 state, + CsrUint32 line, + const CsrCharString *file); +void CsrLogExceptionGeneral(CsrUint16 prim_type, + CsrUint16 state, + const CsrCharString *text, + CsrUint32 line, + const CsrCharString *file); +void CsrLogExceptionWarning(CsrUint16 prim_type, + CsrUint16 state, + const CsrCharString *text, + CsrUint32 line, + const CsrCharString *file); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_log_configure.h b/drivers/staging/csr/csr_log_configure.h new file mode 100644 index 000000000000..3d48bf9762ea --- /dev/null +++ b/drivers/staging/csr/csr_log_configure.h @@ -0,0 +1,135 @@ +#ifndef CSR_LOG_CONFIGURE_H__ +#define CSR_LOG_CONFIGURE_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_log.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------*/ +/* Log init/deinit */ +/*---------------------------------*/ +void CsrLogInit(CsrUint8 size); +void CsrLogDeinit(void); + +/*---------------------------------*/ +/* Log Framework Tech info */ +/*---------------------------------*/ +void CsrLogTechInfoRegister(void); + +/* Set the logging level for the environment outside the scheduler context */ +void CsrLogLevelEnvironmentSet(CsrLogLevelEnvironment environmentLogLevel); + + +/* Set the logging level for all scheduler tasks */ +/* This function call takes precedence over all previous calls to CsrLogLevelTaskSetSpecific() */ +void CsrLogLevelTaskSetAll(CsrLogLevelTask tasksLogLevelMask); + +/* Set the logging level for a given Task */ +/* This function can be used as a complement to CsrLogLevelTaskSetAll() to add more _or_ less log from a given task than what is set +generally with CsrLogLevelTaskSetAll(). */ +void CsrLogLevelTaskSetSpecific(CsrSchedQid taskId, CsrLogLevelTask taskLogLevelMask); + + +/*--------------------------------------------*/ +/* Filtering on log text warning levels */ +/*--------------------------------------------*/ +typedef CsrUint32 CsrLogLevelText; +#define CSR_LOG_LEVEL_TEXT_OFF ((CsrLogLevelText) 0x0000) + +#define CSR_LOG_LEVEL_TEXT_CRITICAL ((CsrLogLevelText) 0x0001) +#define CSR_LOG_LEVEL_TEXT_ERROR ((CsrLogLevelText) 0x0002) +#define CSR_LOG_LEVEL_TEXT_WARNING ((CsrLogLevelText) 0x0004) +#define CSR_LOG_LEVEL_TEXT_INFO ((CsrLogLevelText) 0x0008) +#define CSR_LOG_LEVEL_TEXT_DEBUG ((CsrLogLevelText) 0x0010) + +#define CSR_LOG_LEVEL_TEXT_ALL ((CsrLogLevelText) 0xFFFF) + +/* The log text interface is used by both scheduler tasks and components outside the scheduler context. + * Therefore a CsrLogTextTaskId is introduced. It is effectively considered as two CsrUint16's. The lower + * 16 bits corresponds one2one with the scheduler queueId's (CsrSchedQid) and as such these bits can not be used + * by components outside scheduler tasks. The upper 16 bits are allocated for use of components outside the + * scheduler like drivers etc. Components in this range is defined independently by each technology. To avoid + * clashes the technologies are only allowed to assign values within the same restrictive range as allies to + * primitive identifiers. eg. for the framework components outside the scheduler is only allowed to assign + * taskId's in the range 0x0600xxxx to 0x06FFxxxx. And so on for other technologies. */ +typedef CsrUint32 CsrLogTextTaskId; + +/* Set the text logging level for all Tasks */ +/* This function call takes precedence over all previous calls to CsrLogLevelTextSetTask() and CsrLogLevelTextSetTaskSubOrigin() */ +void CsrLogLevelTextSetAll(CsrLogLevelText warningLevelMask); + +/* Set the text logging level for a given Task */ +/* This function call takes precedence over all previous calls to CsrLogLevelTextSetTaskSubOrigin(), but it can be used as a complement to + * CsrLogLevelTextSetAll() to add more _or_ less log from a given task than what is set generally with CsrLogLevelTextSetAll(). */ +void CsrLogLevelTextSetTask(CsrLogTextTaskId taskId, CsrLogLevelText warningLevelMask); + +/* Set the text logging level for a given tasks subOrigin */ +/* This function can be used as a complement to CsrLogLevelTextSetAll() and CsrLogLevelTextSetTask() to add more _or_ less log from a given + * subOrigin within a task than what is set generally with CsrLogLevelTextSetAll() _or_ CsrLogLevelTextSetTask(). */ +void CsrLogLevelTextSetTaskSubOrigin(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrLogLevelText warningLevelMask); + +/******************************************************************************* + + NAME + CsrLogLevelTextSet + + DESCRIPTION + Set the text logging level for a given origin and optionally sub origin + by name. If either string is NULL or zero length, it is interpreted as + all origins and/or all sub origins respectively. If originName is NULL + or zero length, subOriginName is ignored. + + Passing NULL or zero length strings in both originName and subOriginName + is equivalent to calling CsrLogLevelTextSetAll, and overrides all + previous filter configurations for all origins and sub origins. + + Passing NULL or a zero length string in subOriginName overrides all + previous filter configurations for all sub origins of the specified + origin. + + Note: the supplied strings may be accessed after the function returns + and must remain valid and constant until CsrLogDeinit is called. + + Note: when specifying an origin (originName is not NULL and not zero + length), this function can only be used for origins that use the + csr_log_text_2.h interface for registration and logging. Filtering for + origins that use the legacy csr_log_text.h interface must be be + configured using the legacy filter configuration functions that accept + a CsrLogTextTaskId as origin specifier. However, when not specifying an + origin this function also affects origins that have been registered with + the legacy csr_log_text.h interface. Furthermore, using this function + and the legacy filter configuration functions on the same origin is not + allowed. + + PARAMETERS + originName - a string containing the name of the origin. Can be NULL or + zero length to set the log level for all origins. In this case, the + subOriginName parameter will be ignored. + subOriginName - a string containing the name of the sub origin. Can be + NULL or zero length to set the log level for all sub origins of the + specified origin. + warningLevelMask - The desired log level for the specified origin(s) and + sub origin(s). + +*******************************************************************************/ +void CsrLogLevelTextSet(const CsrCharString *originName, + const CsrCharString *subOriginName, + CsrLogLevelText warningLevelMask); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_log_text.h b/drivers/staging/csr/csr_log_text.h new file mode 100644 index 000000000000..6e0df43c008e --- /dev/null +++ b/drivers/staging/csr/csr_log_text.h @@ -0,0 +1,133 @@ +#ifndef CSR_LOG_TEXT_H__ +#define CSR_LOG_TEXT_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_log_configure.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CsrLogSubOrigin +{ + CsrUint16 subOriginNumber; /* Id of the given SubOrigin */ + const CsrCharString *subOriginName; /* Prefix Text for this SubOrigin */ +} CsrLogSubOrigin; + +/* Register a task which is going to use the CSR_LOG_TEXT_XXX interface */ +#ifdef CSR_LOG_ENABLE +void CsrLogTextRegister(CsrLogTextTaskId taskId, const CsrCharString *taskName, CsrUint16 subOriginsLength, const CsrLogSubOrigin *subOrigins); +#else +#define CsrLogTextRegister(taskId, taskName, subOriginsLength, subOrigins) +#endif + +/* CRITICAL: Conditions that are threatening to the integrity/stability of the + system as a whole. */ +#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_CRITICAL_DISABLE) +void CsrLogTextCritical(CsrLogTextTaskId taskId, CsrUint16 subOrigin, const CsrCharString *formatString, ...); +void CsrLogTextBufferCritical(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrSize bufferLength, const void *buffer, const CsrCharString *formatString, ...); +#define CSR_LOG_TEXT_CRITICAL(taskId_subOrigin_formatString_varargs) CsrLogTextCritical taskId_subOrigin_formatString_varargs +#define CSR_LOG_TEXT_CONDITIONAL_CRITICAL(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_CRITICAL(logtextargs);}} +#define CSR_LOG_TEXT_BUFFER_CRITICAL(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferCritical taskId_subOrigin_length_buffer_formatString_varargs +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_CRITICAL(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_CRITICAL(logtextbufferargs);}} +#else +#define CSR_LOG_TEXT_CRITICAL(taskId_subOrigin_formatString_varargs) +#define CSR_LOG_TEXT_CONDITIONAL_CRITICAL(condition, logtextargs) +#define CSR_LOG_TEXT_BUFFER_CRITICAL(taskId_subOrigin_length_buffer_formatString_varargs) +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_CRITICAL(condition, logtextbufferargs) +#endif + +/* ERROR: Malfunction of a component rendering it unable to operate correctly, + causing lack of functionality but not loss of system integrity/stability. */ +#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_ERROR_DISABLE) +void CsrLogTextError(CsrLogTextTaskId taskId, CsrUint16 subOrigin, const CsrCharString *formatString, ...); +void CsrLogTextBufferError(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrSize bufferLength, const void *buffer, const CsrCharString *formatString, ...); +#define CSR_LOG_TEXT_ERROR(taskId_subOrigin_formatString_varargs) CsrLogTextError taskId_subOrigin_formatString_varargs +#define CSR_LOG_TEXT_CONDITIONAL_ERROR(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_ERROR(logtextargs);}} +#define CSR_LOG_TEXT_BUFFER_ERROR(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferError taskId_subOrigin_length_buffer_formatString_varargs +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_ERROR(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_ERROR(logtextbufferargs);}} +#else +#define CSR_LOG_TEXT_ERROR(taskId_subOrigin_formatString_varargs) +#define CSR_LOG_TEXT_CONDITIONAL_ERROR(condition, logtextargs) +#define CSR_LOG_TEXT_BUFFER_ERROR(taskId_subOrigin_length_buffer_formatString_varargs) +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_ERROR(condition, logtextbufferargs) +#endif + +/* WARNING: Conditions that are unexpected and indicative of possible problems + or violations of specifications, where the result of such deviations does not + lead to malfunction of the component. */ +#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_WARNING_DISABLE) +void CsrLogTextWarning(CsrLogTextTaskId taskId, CsrUint16 subOrigin, const CsrCharString *formatString, ...); +void CsrLogTextBufferWarning(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrSize bufferLength, const void *buffer, const CsrCharString *formatString, ...); +#define CSR_LOG_TEXT_WARNING(taskId_subOrigin_formatString_varargs) CsrLogTextWarning taskId_subOrigin_formatString_varargs +#define CSR_LOG_TEXT_CONDITIONAL_WARNING(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_WARNING(logtextargs);}} +#define CSR_LOG_TEXT_BUFFER_WARNING(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferWarning taskId_subOrigin_length_buffer_formatString_varargs +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_WARNING(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_WARNING(logtextbufferargs);}} +#else +#define CSR_LOG_TEXT_WARNING(taskId_subOrigin_formatString_varargs) +#define CSR_LOG_TEXT_CONDITIONAL_WARNING(condition, logtextargs) +#define CSR_LOG_TEXT_BUFFER_WARNING(taskId_subOrigin_length_buffer_formatString_varargs) +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_WARNING(condition, logtextbufferargs) +#endif + +/* INFO: Important events that may aid in determining the conditions under which + the more severe conditions are encountered. */ +#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_INFO_DISABLE) +void CsrLogTextInfo(CsrLogTextTaskId taskId, CsrUint16 subOrigin, const CsrCharString *formatString, ...); +void CsrLogTextBufferInfo(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrSize bufferLength, const void *buffer, const CsrCharString *formatString, ...); +#define CSR_LOG_TEXT_INFO(taskId_subOrigin_formatString_varargs) CsrLogTextInfo taskId_subOrigin_formatString_varargs +#define CSR_LOG_TEXT_CONDITIONAL_INFO(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_INFO(logtextargs);}} +#define CSR_LOG_TEXT_BUFFER_INFO(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferInfo taskId_subOrigin_length_buffer_formatString_varargs +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_INFO(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_INFO(logtextbufferargs);}} +#else +#define CSR_LOG_TEXT_INFO(taskId_subOrigin_formatString_varargs) +#define CSR_LOG_TEXT_CONDITIONAL_INFO(condition, logtextargs) +#define CSR_LOG_TEXT_BUFFER_INFO(taskId_subOrigin_length_buffer_formatString_varargs) +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_INFO(condition, logtextbufferargs) +#endif + +/* DEBUG: Similar to INFO, but dedicated to events that occur more frequently. */ +#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_DEBUG_DISABLE) +void CsrLogTextDebug(CsrLogTextTaskId taskId, CsrUint16 subOrigin, const CsrCharString *formatString, ...); +void CsrLogTextBufferDebug(CsrLogTextTaskId taskId, CsrUint16 subOrigin, CsrSize bufferLength, const void *buffer, const CsrCharString *formatString, ...); +#define CSR_LOG_TEXT_DEBUG(taskId_subOrigin_formatString_varargs) CsrLogTextDebug taskId_subOrigin_formatString_varargs +#define CSR_LOG_TEXT_CONDITIONAL_DEBUG(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_DEBUG(logtextargs);}} +#define CSR_LOG_TEXT_BUFFER_DEBUG(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferDebug taskId_subOrigin_length_buffer_formatString_varargs +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_DEBUG(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_DEBUG(logtextbufferargs);}} +#else +#define CSR_LOG_TEXT_DEBUG(taskId_subOrigin_formatString_varargs) +#define CSR_LOG_TEXT_CONDITIONAL_DEBUG(condition, logtextargs) +#define CSR_LOG_TEXT_BUFFER_DEBUG(taskId_subOrigin_length_buffer_formatString_varargs) +#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_DEBUG(condition, logtextbufferargs) +#endif + +/* CSR_LOG_TEXT_ASSERT (CRITICAL) */ +#ifdef CSR_LOG_ENABLE +#define CSR_LOG_TEXT_ASSERT(origin, suborigin, condition) \ + {if (!(condition)) {CSR_LOG_TEXT_CRITICAL((origin, suborigin, "Assertion \"%s\" failed at %s:%u", #condition, __FILE__, __LINE__));}} +#else +#define CSR_LOG_TEXT_ASSERT(origin, suborigin, condition) +#endif + +/* CSR_LOG_TEXT_UNHANDLED_PRIM (CRITICAL) */ +#ifdef CSR_LOG_ENABLE +#define CSR_LOG_TEXT_UNHANDLED_PRIMITIVE(origin, suborigin, primClass, primType) \ + CSR_LOG_TEXT_CRITICAL((origin, suborigin, "Unhandled primitive 0x%04X:0x%04X at %s:%u", primClass, primType, __FILE__, __LINE__)) +#else +#define CSR_LOG_TEXT_UNHANDLED_PRIMITIVE(origin, suborigin, primClass, primType) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_macro.h b/drivers/staging/csr/csr_macro.h new file mode 100644 index 000000000000..2e3dcac4f331 --- /dev/null +++ b/drivers/staging/csr/csr_macro.h @@ -0,0 +1,111 @@ +#ifndef CSR_MACRO_H__ +#define CSR_MACRO_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------------*/ +/* Bits - intended to operate on CsrUint32 values */ +/*------------------------------------------------------------------*/ +#define CSR_MASK_IS_SET(val, mask) (((val) & (mask)) == (mask)) +#define CSR_MASK_IS_UNSET(val, mask) ((((val) & (mask)) ^ mask) == (mask)) +#define CSR_MASK_SET(val, mask) ((val) |= (mask)) +#define CSR_MASK_UNSET(val, mask) ((val) = ((val) ^ (mask)) & (val)) /* Unsets the bits in val that are set in mask */ +#define CSR_BIT_IS_SET(val, bit) ((CsrBool) ((((val) & (1UL << (bit))) != 0))) +#define CSR_BIT_SET(val, bit) ((val) |= (1UL << (bit))) +#define CSR_BIT_UNSET(val, bit) ((val) &= ~(1UL << (bit))) +#define CSR_BIT_TOGGLE(val, bit) ((val) ^= (1UL << (bit))) + +/*------------------------------------------------------------------*/ +/* Endian conversion */ +/*------------------------------------------------------------------*/ +#define CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr) (((CsrUint16) ((CsrUint8 *) (ptr))[0]) | ((CsrUint16) ((CsrUint8 *) (ptr))[1]) << 8) +#define CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr) (((CsrUint32) ((CsrUint8 *) (ptr))[0]) | ((CsrUint32) ((CsrUint8 *) (ptr))[1]) << 8 | \ + ((CsrUint32) ((CsrUint8 *) (ptr))[2]) << 16 | ((CsrUint32) ((CsrUint8 *) (ptr))[3]) << 24) +#define CSR_COPY_UINT16_TO_LITTLE_ENDIAN(uint, ptr) ((CsrUint8 *) (ptr))[0] = ((CsrUint8) ((uint) & 0x00FF)); \ + ((CsrUint8 *) (ptr))[1] = ((CsrUint8) ((uint) >> 8)) +#define CSR_COPY_UINT32_TO_LITTLE_ENDIAN(uint, ptr) ((CsrUint8 *) (ptr))[0] = ((CsrUint8) ((uint) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[1] = ((CsrUint8) (((uint) >> 8) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[2] = ((CsrUint8) (((uint) >> 16) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[3] = ((CsrUint8) (((uint) >> 24) & 0x000000FF)) +#define CSR_GET_UINT16_FROM_BIG_ENDIAN(ptr) (((CsrUint16) ((CsrUint8 *) (ptr))[1]) | ((CsrUint16) ((CsrUint8 *) (ptr))[0]) << 8) +#define CSR_GET_UINT24_FROM_BIG_ENDIAN(ptr) (((CsrUint24) ((CsrUint8 *) (ptr))[2]) | \ + ((CsrUint24) ((CsrUint8 *) (ptr))[1]) << 8 | ((CsrUint24) ((CsrUint8 *) (ptr))[0]) << 16) +#define CSR_GET_UINT32_FROM_BIG_ENDIAN(ptr) (((CsrUint32) ((CsrUint8 *) (ptr))[3]) | ((CsrUint32) ((CsrUint8 *) (ptr))[2]) << 8 | \ + ((CsrUint32) ((CsrUint8 *) (ptr))[1]) << 16 | ((CsrUint32) ((CsrUint8 *) (ptr))[0]) << 24) +#define CSR_COPY_UINT16_TO_BIG_ENDIAN(uint, ptr) ((CsrUint8 *) (ptr))[1] = ((CsrUint8) ((uint) & 0x00FF)); \ + ((CsrUint8 *) (ptr))[0] = ((CsrUint8) ((uint) >> 8)) +#define CSR_COPY_UINT24_TO_BIG_ENDIAN(uint, ptr) ((CsrUint8 *) (ptr))[2] = ((CsrUint8) ((uint) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[1] = ((CsrUint8) (((uint) >> 8) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[0] = ((CsrUint8) (((uint) >> 16) & 0x000000FF)) +#define CSR_COPY_UINT32_TO_BIG_ENDIAN(uint, ptr) ((CsrUint8 *) (ptr))[3] = ((CsrUint8) ((uint) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[2] = ((CsrUint8) (((uint) >> 8) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[1] = ((CsrUint8) (((uint) >> 16) & 0x000000FF)); \ + ((CsrUint8 *) (ptr))[0] = ((CsrUint8) (((uint) >> 24) & 0x000000FF)) + +/*------------------------------------------------------------------*/ +/* XAP conversion macros */ +/*------------------------------------------------------------------*/ + +#define CSR_LSB16(a) ((CsrUint8) ((a) & 0x00ff)) +#define CSR_MSB16(b) ((CsrUint8) ((b) >> 8)) + +#define CSR_CONVERT_8_FROM_XAP(output, input) \ + (output) = ((CsrUint8) (input));(input) += 2 + +#define CSR_CONVERT_16_FROM_XAP(output, input) \ + (output) = (CsrUint16) ((((CsrUint16) (input)[1]) << 8) | \ + ((CsrUint16) (input)[0]));(input) += 2 + +#define CSR_CONVERT_32_FROM_XAP(output, input) \ + (output) = (((CsrUint32) (input)[1]) << 24) | \ + (((CsrUint32) (input)[0]) << 16) | \ + (((CsrUint32) (input)[3]) << 8) | \ + ((CsrUint32) (input)[2]);input += 4 + +#define CSR_ADD_UINT8_TO_XAP(output, input) \ + (output)[0] = (input); \ + (output)[1] = 0;(output) += 2 + +#define CSR_ADD_UINT16_TO_XAP(output, input) \ + (output)[0] = ((CsrUint8) ((input) & 0x00FF)); \ + (output)[1] = ((CsrUint8) ((input) >> 8));(output) += 2 + +#define CSR_ADD_UINT32_TO_XAP(output, input) \ + (output)[0] = ((CsrUint8) (((input) >> 16) & 0x00FF)); \ + (output)[1] = ((CsrUint8) ((input) >> 24)); \ + (output)[2] = ((CsrUint8) ((input) & 0x00FF)); \ + (output)[3] = ((CsrUint8) (((input) >> 8) & 0x00FF));(output) += 4 + +/*------------------------------------------------------------------*/ +/* Misc */ +/*------------------------------------------------------------------*/ +#define CSRMAX(a, b) (((a) > (b)) ? (a) : (b)) +#define CSRMIN(a, b) (((a) < (b)) ? (a) : (b)) + +/* Use this macro on unused local variables that cannot be removed (such as + unused function parameters). This will quell warnings from certain compilers + and static code analysis tools like Lint and Valgrind. */ +#define CSR_UNUSED(x) ((void) (x)) + +#define CSR_TOUPPER(character) (((character) >= 'a') && ((character) <= 'z') ? ((character) - 0x20) : (character)) +#define CSR_TOLOWER(character) (((character) >= 'A') && ((character) <= 'Z') ? ((character) + 0x20) : (character)) +#define CSR_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_msg_transport.h b/drivers/staging/csr/csr_msg_transport.h new file mode 100644 index 000000000000..b0095b023817 --- /dev/null +++ b/drivers/staging/csr/csr_msg_transport.h @@ -0,0 +1,25 @@ +#ifndef CSR_MSG_TRANSPORT_H__ +#define CSR_MSG_TRANSPORT_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CsrMsgTransport +#define CsrMsgTransport CsrSchedMessagePut +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_MSG_TRANSPORT */ diff --git a/drivers/staging/csr/csr_msgconv.c b/drivers/staging/csr/csr_msgconv.c new file mode 100644 index 000000000000..9f1c946c66f9 --- /dev/null +++ b/drivers/staging/csr/csr_msgconv.c @@ -0,0 +1,324 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_panic.h" +#include "csr_sched.h" +#include "csr_msgconv.h" +#include "csr_util.h" + +static CsrMsgConvEntry *converter; + +CsrMsgConvPrimEntry *CsrMsgConvFind(CsrUint16 primType) +{ + CsrMsgConvPrimEntry *ptr = NULL; + + if (converter) + { + ptr = converter->profile_converters; + while (ptr) + { + if (ptr->primType == primType) + { + break; + } + else + { + ptr = ptr->next; + } + } + } + + return ptr; +} + +static const CsrMsgConvMsgEntry *find_msg_converter(CsrMsgConvPrimEntry *ptr, CsrUint16 msgType) +{ + const CsrMsgConvMsgEntry *cv = ptr->conv; + if (ptr->lookupFunc) + { + return (const CsrMsgConvMsgEntry *) ptr->lookupFunc((CsrMsgConvMsgEntry *) cv, msgType); + } + + while (cv) + { + if (cv->serFunc == NULL) + { + /* We've reached the end of the chain */ + cv = NULL; + break; + } + + if (cv->msgType == msgType) + { + break; + } + else + { + cv++; + } + } + + return cv; +} + +static void *deserialize_data(CsrUint16 primType, + CsrSize length, + CsrUint8 *data) +{ + CsrMsgConvPrimEntry *ptr; + CsrUint8 *ret; + + ptr = CsrMsgConvFind(primType); + + if (ptr) + { + const CsrMsgConvMsgEntry *cv; + CsrUint16 msgId = 0; + CsrSize offset = 0; + CsrUint16Des(&msgId, data, &offset); + + cv = find_msg_converter(ptr, msgId); + if (cv) + { + ret = cv->deserFunc(data, length); + } + else + { + ret = NULL; + } + } + else + { + ret = NULL; + } + + return ret; +} + +static CsrSize sizeof_message(CsrUint16 primType, void *msg) +{ + CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); + CsrSize ret; + + if (ptr) + { + const CsrMsgConvMsgEntry *cv; + CsrUint16 msgId = *(CsrUint16 *) msg; + + cv = find_msg_converter(ptr, msgId); + if (cv) + { + ret = cv->sizeofFunc(msg); + } + else + { + ret = 0; + } + } + else + { + ret = 0; + } + + return ret; +} + +static CsrBool free_message(CsrUint16 primType, CsrUint8 *data) +{ + CsrMsgConvPrimEntry *ptr; + CsrBool ret; + + ptr = CsrMsgConvFind(primType); + + if (ptr) + { + const CsrMsgConvMsgEntry *cv; + CsrUint16 msgId = *(CsrUint16 *) data; + + cv = find_msg_converter(ptr, msgId); + if (cv) + { + cv->freeFunc(data); + ret = TRUE; + } + else + { + ret = FALSE; + } + } + else + { + ret = FALSE; + } + + return ret; +} + +static CsrUint8 *serialize_message(CsrUint16 primType, + void *msg, + CsrSize *length, + CsrUint8 *buffer) +{ + CsrMsgConvPrimEntry *ptr; + CsrUint8 *ret; + + ptr = CsrMsgConvFind(primType); + + *length = 0; + + if (ptr) + { + const CsrMsgConvMsgEntry *cv; + + cv = find_msg_converter(ptr, *(CsrUint16 *) msg); + if (cv) + { + ret = cv->serFunc(buffer, length, msg); + } + else + { + ret = NULL; + } + } + else + { + ret = NULL; + } + + return ret; +} + +CsrSize CsrMsgConvSizeof(CsrUint16 primType, void *msg) +{ + return sizeof_message(primType, msg); +} + +CsrUint8 *CsrMsgConvSerialize(CsrUint8 *buffer, CsrSize maxBufferOffset, CsrSize *offset, CsrUint16 primType, void *msg) +{ + if (converter) + { + CsrSize serializedLength; + CsrUint8 *bufSerialized; + CsrUint8 *bufOffset = &buffer[*offset]; + bufSerialized = converter->serialize_message(primType, msg, &serializedLength, bufOffset); + *offset += serializedLength; + return bufSerialized; + } + else + { + return NULL; + } +} + +/* Insert profile converter at head of converter list. */ +void CsrMsgConvInsert(CsrUint16 primType, const CsrMsgConvMsgEntry *ce) +{ + CsrMsgConvPrimEntry *pc; + pc = CsrMsgConvFind(primType); + + if (pc) + { + /* Already registered. Do nothing */ + } + else + { + pc = CsrPmemAlloc(sizeof(*pc)); + pc->primType = primType; + pc->conv = ce; + pc->lookupFunc = NULL; + pc->next = converter->profile_converters; + converter->profile_converters = pc; + } +} +EXPORT_SYMBOL_GPL(CsrMsgConvInsert); + +CsrMsgConvMsgEntry *CsrMsgConvFindEntry(CsrUint16 primType, CsrUint16 msgType) +{ + CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); + if (ptr) + { + return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType); + } + return NULL; +} +EXPORT_SYMBOL_GPL(CsrMsgConvFindEntry); + +CsrMsgConvMsgEntry *CsrMsgConvFindEntryByMsg(CsrUint16 primType, const void *msg) +{ + CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); + if (ptr && msg) + { + CsrUint16 msgType = *((CsrUint16 *) msg); + return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType); + } + return NULL; +} + +void CsrMsgConvCustomLookupRegister(CsrUint16 primType, CsrMsgCustomLookupFunc *lookupFunc) +{ + CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); + if (ptr) + { + ptr->lookupFunc = lookupFunc; + } +} +EXPORT_SYMBOL_GPL(CsrMsgConvCustomLookupRegister); + +CsrMsgConvEntry *CsrMsgConvInit(void) +{ + if (!converter) + { + converter = (CsrMsgConvEntry *) CsrPmemAlloc(sizeof(CsrMsgConvEntry)); + + converter->profile_converters = NULL; + converter->free_message = free_message; + converter->sizeof_message = sizeof_message; + converter->serialize_message = serialize_message; + converter->deserialize_data = deserialize_data; + } + + return converter; +} +EXPORT_SYMBOL_GPL(CsrMsgConvInit); + +CsrMsgConvEntry *CsrMsgConvGet(void) +{ + return converter; +} + +#ifdef ENABLE_SHUTDOWN +void CsrMsgConvDeinit(void) +{ + CsrMsgConvPrimEntry *s; + + if (converter == NULL) + { + return; + } + + /* Walk converter list and free elements. */ + s = converter->profile_converters; + while (s) + { + CsrMsgConvPrimEntry *s_next; + s_next = s->next; + CsrPmemFree(s); + s = s_next; + } + + CsrPmemFree(converter); + converter = NULL; +} +EXPORT_SYMBOL_GPL(CsrMsgConvDeinit); + +#endif /* ENABLE_SHUTDOWN */ diff --git a/drivers/staging/csr/csr_msgconv.h b/drivers/staging/csr/csr_msgconv.h new file mode 100644 index 000000000000..2875c8c69418 --- /dev/null +++ b/drivers/staging/csr/csr_msgconv.h @@ -0,0 +1,145 @@ +#ifndef CSR_MSGCONV_H__ +#define CSR_MSGCONV_H__ + +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_unicode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef CsrSize (CsrMsgSizeofFunc)(void *msg); +typedef CsrUint8 *(CsrMsgSerializeFunc)(CsrUint8 *buffer, CsrSize *length, void *msg); +typedef void (CsrMsgFreeFunc)(void *msg); +typedef void *(CsrMsgDeserializeFunc)(CsrUint8 *buffer, CsrSize length); + +/* Converter entry for one message type */ +typedef struct CsrMsgConvMsgEntry +{ + CsrUint16 msgType; + CsrMsgSizeofFunc *sizeofFunc; + CsrMsgSerializeFunc *serFunc; + CsrMsgDeserializeFunc *deserFunc; + CsrMsgFreeFunc *freeFunc; +} CsrMsgConvMsgEntry; + +/* Optional lookup function */ +typedef CsrMsgConvMsgEntry *(CsrMsgCustomLookupFunc)(CsrMsgConvMsgEntry *ce, CsrUint16 msgType); + +/* All converter entries for one specific primitive */ +typedef struct CsrMsgConvPrimEntry +{ + CsrUint16 primType; + const CsrMsgConvMsgEntry *conv; + CsrMsgCustomLookupFunc *lookupFunc; + struct CsrMsgConvPrimEntry *next; +} CsrMsgConvPrimEntry; + +typedef struct +{ + CsrMsgConvPrimEntry *profile_converters; + void *(*deserialize_data)(CsrUint16 primType, CsrSize length, CsrUint8 * data); + CsrBool (*free_message)(CsrUint16 primType, CsrUint8 *data); + CsrSize (*sizeof_message)(CsrUint16 primType, void *msg); + CsrUint8 *(*serialize_message)(CsrUint16 primType, void *msg, + CsrSize * length, + CsrUint8 * buffer); +} CsrMsgConvEntry; + +CsrSize CsrMsgConvSizeof(CsrUint16 primType, void *msg); +CsrUint8 *CsrMsgConvSerialize(CsrUint8 *buffer, CsrSize maxBufferOffset, CsrSize *offset, CsrUint16 primType, void *msg); +void CsrMsgConvCustomLookupRegister(CsrUint16 primType, CsrMsgCustomLookupFunc *lookupFunc); +void CsrMsgConvInsert(CsrUint16 primType, const CsrMsgConvMsgEntry *ce); +CsrMsgConvPrimEntry *CsrMsgConvFind(CsrUint16 primType); +CsrMsgConvMsgEntry *CsrMsgConvFindEntry(CsrUint16 primType, CsrUint16 msgType); +CsrMsgConvMsgEntry *CsrMsgConvFindEntryByMsg(CsrUint16 primType, const void *msg); +CsrMsgConvEntry *CsrMsgConvGet(void); +CsrMsgConvEntry *CsrMsgConvInit(void); +#ifdef ENABLE_SHUTDOWN +void CsrMsgConvDeinit(void); +#endif /* ENABLE_SHUTDOWN */ + +/* SHOULD BE INTERNAL TO FRAMEWORK AKA DEPRECATED */ + +CsrUint32 CsrCharStringSerLen(const CsrCharString *str); +CsrUint32 CsrUtf8StringSerLen(const CsrUtf8String *str); +CsrUint32 CsrUtf16StringSerLen(const CsrUtf16String *str); + +/* Prototypes for primitive type serializers */ +void CsrUint8Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint8 value); +void CsrUint16Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint16 value); +void CsrUint32Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint32 value); +void CsrMemCpySer(CsrUint8 *buffer, CsrSize *offset, const void *value, CsrSize length); +void CsrCharStringSer(CsrUint8 *buffer, CsrSize *offset, const CsrCharString *value); +void CsrUtf8StringSer(CsrUint8 *buffer, CsrSize *offset, const CsrUtf8String *value); +void CsrUtf16StringSer(CsrUint8 *buffer, CsrSize *offset, const CsrUtf16String *value); +void CsrVoidPtrSer(CsrUint8 *buffer, CsrSize *offset, void *ptr); +void CsrSizeSer(CsrUint8 *buffer, CsrSize *offset, CsrSize value); + +void CsrUint8Des(CsrUint8 *value, CsrUint8 *buffer, CsrSize *offset); +void CsrUint16Des(CsrUint16 *value, CsrUint8 *buffer, CsrSize *offset); +void CsrUint32Des(CsrUint32 *value, CsrUint8 *buffer, CsrSize *offset); +void CsrMemCpyDes(void *value, CsrUint8 *buffer, CsrSize *offset, CsrSize length); +void CsrCharStringDes(CsrCharString **value, CsrUint8 *buffer, CsrSize *offset); +void CsrUtf8StringDes(CsrUtf8String **value, CsrUint8 *buffer, CsrSize *offset); +void CsrUtf16StringDes(CsrUtf16String **value, CsrUint8 *buffer, CsrSize *offset); +void CsrVoidPtrDes(void **value, CsrUint8 *buffer, CsrSize *offset); +void CsrSizeDes(CsrSize *value, CsrUint8 *buffer, CsrSize *offset); + +CsrSize CsrEventSizeof(void *msg); +CsrUint8 *CsrEventSer(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventDes(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint8Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint8Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint16Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint16Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint32Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint32Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint16CsrUint8Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint16CsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint16CsrUint8Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint16CsrUint16Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint16CsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint16CsrUint16Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint16CsrUint32Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint16CsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint16CsrUint32Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint16CsrCharStringSizeof(void *msg); +CsrUint8 *CsrEventCsrUint16CsrCharStringSer(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint16CsrCharStringDes(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint32CsrUint16Sizeof(void *msg); +CsrUint8 *CsrEventCsrUint32CsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint32CsrUint16Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrEventCsrUint32CsrCharStringSizeof(void *msg); +CsrUint8 *CsrEventCsrUint32CsrCharStringSer(CsrUint8 *ptr, CsrSize *len, void *msg); +void *CsrEventCsrUint32CsrCharStringDes(CsrUint8 *buffer, CsrSize length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_panic.c b/drivers/staging/csr/csr_panic.c new file mode 100644 index 000000000000..2564e80297e2 --- /dev/null +++ b/drivers/staging/csr/csr_panic.c @@ -0,0 +1,22 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include +#include + +#include "csr_types.h" +#include "csr_panic.h" + +void CsrPanic(CsrUint8 tech, CsrUint16 reason, const char *p) +{ + BUG_ON(1); +} +EXPORT_SYMBOL_GPL(CsrPanic); diff --git a/drivers/staging/csr/csr_panic.h b/drivers/staging/csr/csr_panic.h new file mode 100644 index 000000000000..6e33f9337b21 --- /dev/null +++ b/drivers/staging/csr/csr_panic.h @@ -0,0 +1,55 @@ +#ifndef CSR_PANIC_H__ +#define CSR_PANIC_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Synergy techonology ID definitions */ +#define CSR_TECH_FW 0 +#define CSR_TECH_BT 1 +#define CSR_TECH_WIFI 2 +#define CSR_TECH_GPS 3 +#define CSR_TECH_NFC 4 + +/* Panic type ID definitions for technology type CSR_TECH_FW */ +#define CSR_PANIC_FW_UNEXPECTED_VALUE 0 +#define CSR_PANIC_FW_HEAP_EXHAUSTION 1 +#define CSR_PANIC_FW_INVALID_PFREE_POINTER 2 +#define CSR_PANIC_FW_EXCEPTION 3 +#define CSR_PANIC_FW_ASSERTION_FAIL 4 +#define CSR_PANIC_FW_NULL_TASK_HANDLER 5 +#define CSR_PANIC_FW_UNKNOWN_TASK 6 +#define CSR_PANIC_FW_QUEUE_ACCESS_VIOLATION 7 +#define CSR_PANIC_FW_TOO_MANY_MESSAGES 8 +#define CSR_PANIC_FW_TOO_MANY_TIMED_EVENTS 9 +#define CSR_PANIC_FW_ABCSP_SYNC_LOST 10 +#define CSR_PANIC_FW_OVERSIZE_ABCSP_PRIM 11 +#define CSR_PANIC_FW_H4_CORRUPTION 12 +#define CSR_PANIC_FW_H4_SYNC_LOST 13 +#define CSR_PANIC_FW_H4_RX_OVERRUN 14 +#define CSR_PANIC_FW_H4_TX_OVERRUN 15 +#define CSR_PANIC_FW_TM_BC_RESTART_FAIL 16 +#define CSR_PANIC_FW_TM_BC_START_FAIL 17 +#define CSR_PANIC_FW_TM_BC_BAD_STATE 18 +#define CSR_PANIC_FW_TM_BC_TRANSPORT_LOST 19 + +/* Panic interface used by technologies */ +/* DEPRECATED - replaced by csr_log_text.h */ +void CsrPanic(CsrUint8 tech, CsrUint16 reason, const char *p); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_PANIC_H__ */ diff --git a/drivers/staging/csr/csr_pmem.c b/drivers/staging/csr/csr_pmem.c new file mode 100644 index 000000000000..a07c44999168 --- /dev/null +++ b/drivers/staging/csr/csr_pmem.c @@ -0,0 +1,51 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include +#include + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) +#include +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) +#include +#endif + +#include + +#include "csr_panic.h" +#include "csr_pmem.h" + +void *CsrPmemAlloc(CsrSize size) +{ + void *ret; + + ret = kmalloc(size, GFP_KERNEL); + if (!ret) + { + CsrPanic(CSR_TECH_FW, CSR_PANIC_FW_HEAP_EXHAUSTION, + "out of memory"); + } + + return ret; +} +EXPORT_SYMBOL_GPL(CsrPmemAlloc); + +void CsrPmemFree(void *ptr) +{ + if (ptr == NULL) + { + return; + } + + kfree(ptr); +} +EXPORT_SYMBOL_GPL(CsrPmemFree); diff --git a/drivers/staging/csr/csr_pmem.h b/drivers/staging/csr/csr_pmem.h new file mode 100644 index 000000000000..f1e59ef83c65 --- /dev/null +++ b/drivers/staging/csr/csr_pmem.h @@ -0,0 +1,143 @@ +#ifndef CSR_PMEM_H__ +#define CSR_PMEM_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_PMEM_DEBUG_ENABLE +/***************************************************************************** + + NAME + CsrPmemAlloc + + DESCRIPTION + This function will allocate a contiguous block of memory of at least + the specified size in bytes and return a pointer to the allocated + memory. This function is not allowed to return NULL. A size of 0 is a + valid request, and a unique and valid (not NULL) pointer must be + returned in this case. + + PARAMETERS + size - Size of memory requested. Note that a size of 0 is valid. + + RETURNS + Pointer to allocated memory. + +*****************************************************************************/ +#ifdef CSR_PMEM_DEBUG +void *CsrPmemAllocDebug(CsrSize size, + const CsrCharString *file, CsrUint32 line); +#define CsrPmemAlloc(sz) CsrPmemAllocDebug((sz), __FILE__, __LINE__) +#else +void *CsrPmemAlloc(CsrSize size); +#endif + + +/***************************************************************************** + + NAME + CsrPmemFree + + DESCRIPTION + This function will deallocate a previously allocated block of memory. + + PARAMETERS + ptr - Pointer to allocated memory. + +*****************************************************************************/ +void CsrPmemFree(void *ptr); +#endif + +/***************************************************************************** + + NAME + CsrPmemZalloc + + DESCRIPTION + This function is equivalent to CsrPmemAlloc, but the allocated memory + is initialised to zero. + + PARAMETERS + size - Size of memory requested. Note that a size of 0 is valid. + + RETURNS + Pointer to allocated memory. + +*****************************************************************************/ +#define CsrPmemZalloc(s) (CsrMemSet(CsrPmemAlloc(s), 0x00, (s))) + + +/***************************************************************************** + + NAME + pnew and zpnew + + DESCRIPTIOM + Type-safe wrappers for CsrPmemAlloc and CsrPmemZalloc, for allocating + single instances of a specified and named type. + + PARAMETERS + t - type to allocate. + +*****************************************************************************/ +#define pnew(t) ((t *) (CsrPmemAlloc(sizeof(t)))) +#define zpnew(t) ((t *) (CsrPmemZalloc(sizeof(t)))) + + +/*----------------------------------------------------------------------------* + * Csr Pmem Debug code. Allows custom callbacks on CsrPmemAlloc and CsrPmemFree + *----------------------------------------------------------------------------*/ +#ifdef CSR_PMEM_DEBUG_ENABLE + +typedef CsrUint8 CsrPmemDebugAllocType; +#define CSR_PMEM_DEBUG_TYPE_PMEM_ALLOC 1 +#define CSR_PMEM_DEBUG_TYPE_MEM_ALLOC 2 +#define CSR_PMEM_DEBUG_TYPE_MEM_CALLOC 3 +#define CSR_PMEM_DEBUG_TYPE_MEM_ALLOC_DMA 4 + +typedef void (CsrPmemDebugOnAlloc)(void *ptr, void *userptr, CsrSize size, CsrPmemDebugAllocType type, const CsrCharString* file, CsrUint32 line); +typedef void (CsrPmemDebugOnFree)(void *ptr, void *userptr, CsrPmemDebugAllocType type, const CsrCharString* file, CsrUint32 line); + +/*----------------------------------------------------------------------------* + * NAME + * CsrPmemInstallHooks + * + * DESCRIPTION + * Install debug hooks for memory allocation + * Use NULL values to uninstall the hooks + * headSize = The number of extra bytes to allocate in the head of the Allocated buffer + * footSize = The number of extra bytes to allocate in the end of the Allocated buffer + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrPmemDebugInstallHooks(CsrUint8 headSize, CsrUint8 endSize, CsrPmemDebugOnAlloc *onAllocCallback, CsrPmemDebugOnFree *onFreeCallback); + +void *CsrPmemDebugAlloc(CsrSize size, CsrPmemDebugAllocType type, const CsrCharString* file, CsrUint32 line); +#define CsrPmemAlloc(size) CsrPmemDebugAlloc(size, CSR_PMEM_DEBUG_TYPE_PMEM_ALLOC, __FILE__, __LINE__) + +void CsrPmemDebugFree(void *ptr, CsrPmemDebugAllocType type, const CsrCharString* file, CsrUint32 line); +#define CsrPmemFree(ptr) CsrPmemDebugFree(ptr, CSR_PMEM_DEBUG_TYPE_PMEM_ALLOC, __FILE__, __LINE__) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_prim_defs.h b/drivers/staging/csr/csr_prim_defs.h new file mode 100644 index 000000000000..02ab91391949 --- /dev/null +++ b/drivers/staging/csr/csr_prim_defs.h @@ -0,0 +1,64 @@ +#ifndef CSR_PRIM_DEFS_H__ +#define CSR_PRIM_DEFS_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************ + * Segmentation of primitives in upstream and downstream segment + ************************************************************************************/ +typedef CsrUint16 CsrPrim; +#define CSR_PRIM_UPSTREAM ((CsrPrim) (0x8000)) + +/************************************************************************************ + * Primitive definitions for Synergy framework + ************************************************************************************/ +#define CSR_SYNERGY_EVENT_CLASS_BASE ((CsrUint16) (0x0600)) + +#define CSR_HCI_PRIM ((CsrUint16) (0x0000 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_BCCMD_PRIM ((CsrUint16) (0x0001 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_HQ_PRIM ((CsrUint16) (0x0002 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_VM_PRIM ((CsrUint16) (0x0003 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_TM_BLUECORE_PRIM ((CsrUint16) (0x0004 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_FP_PRIM ((CsrUint16) (0x0005 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_IP_SOCKET_PRIM ((CsrUint16) (0x0006 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_IP_ETHER_PRIM ((CsrUint16) (0x0007 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_IP_IFCONFIG_PRIM ((CsrUint16) (0x0008 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_IP_INTERNAL_PRIM ((CsrUint16) (0x0009 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_FSAL_PRIM ((CsrUint16) (0x000A | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_DATA_STORE_PRIM ((CsrUint16) (0x000B | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_AM_PRIM ((CsrUint16) (0x000C | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_TLS_PRIM ((CsrUint16) (0x000D | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_DHCP_SERVER_PRIM ((CsrUint16) (0x000E | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_TFTP_PRIM ((CsrUint16) (0x000F | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_DSPM_PRIM ((CsrUint16) (0x0010 | CSR_SYNERGY_EVENT_CLASS_BASE)) +#define CSR_TLS_INTERNAL_PRIM ((CsrUint16) (0x0011 | CSR_SYNERGY_EVENT_CLASS_BASE)) + +#define NUMBER_OF_CSR_FW_EVENTS (CSR_DSPM_PRIM - CSR_SYNERGY_EVENT_CLASS_BASE + 1) + +#define CSR_SYNERGY_EVENT_CLASS_MISC_BASE ((CsrUint16) (0x06A0)) + +#define CSR_UI_PRIM ((CsrUint16) (0x0000 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) +#define CSR_APP_PRIM ((CsrUint16) (0x0001 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) +#define CSR_SDIO_PROBE_PRIM ((CsrUint16) (0x0002 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) + +#define NUMBER_OF_CSR_FW_MISC_EVENTS (CSR_SDIO_PROBE_PRIM - CSR_SYNERGY_EVENT_CLASS_MISC_BASE + 1) + +#define CSR_ENV_PRIM ((CsrUint16) (0x00FF | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_PRIM_DEFS_H__ */ diff --git a/drivers/staging/csr/csr_result.h b/drivers/staging/csr/csr_result.h new file mode 100644 index 000000000000..249b4990c478 --- /dev/null +++ b/drivers/staging/csr/csr_result.h @@ -0,0 +1,27 @@ +#ifndef CSR_RESULT_H__ +#define CSR_RESULT_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef CsrUint16 CsrResult; +#define CSR_RESULT_SUCCESS ((CsrResult) 0x0000) +#define CSR_RESULT_FAILURE ((CsrResult) 0xFFFF) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_sched.h b/drivers/staging/csr/csr_sched.h new file mode 100644 index 000000000000..2f982bbfb723 --- /dev/null +++ b/drivers/staging/csr/csr_sched.h @@ -0,0 +1,292 @@ +#ifndef CSR_SCHED_H__ +#define CSR_SCHED_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#include "csr_types.h" +#include "csr_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* An identifier issued by the scheduler. */ +typedef CsrUint32 CsrSchedIdentifier; + +/* A task identifier */ +typedef CsrUint16 CsrSchedTaskId; + +/* A queue identifier */ +typedef CsrUint16 CsrSchedQid; +#define CSR_SCHED_QID_INVALID ((CsrSchedQid) 0xFFFF) + +/* A message identifier */ +typedef CsrSchedIdentifier CsrSchedMsgId; + +/* A timer event identifier */ +typedef CsrSchedIdentifier CsrSchedTid; +#define CSR_SCHED_TID_INVALID ((CsrSchedTid) 0) + +/* Scheduler entry functions share this structure */ +typedef void (*schedEntryFunction_t)(void **inst); + +/* Time constants. */ +#define CSR_SCHED_TIME_MAX ((CsrTime) 0xFFFFFFFF) +#define CSR_SCHED_MILLISECOND ((CsrTime) (1000)) +#define CSR_SCHED_SECOND ((CsrTime) (1000 * CSR_SCHED_MILLISECOND)) +#define CSR_SCHED_MINUTE ((CsrTime) (60 * CSR_SCHED_SECOND)) + +/* Queue and primitive that identifies the environment */ +#define CSR_SCHED_TASK_ID 0xFFFF +#define CSR_SCHED_PRIM (CSR_SCHED_TASK_ID) +#define CSR_SCHED_EXCLUDED_MODULE_QUEUE 0xFFFF + +/* + * Background interrupt definitions + */ +typedef CsrUint16 CsrSchedBgint; +#define CSR_SCHED_BGINT_INVALID ((CsrSchedBgint) 0xFFFF) + +typedef void (*CsrSchedBgintHandler)(void *); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedBgintReg + * + * DESCRIPTION + * Register a background interrupt handler function with the scheduler. + * When CsrSchedBgint() is called from the foreground (e.g. an interrupt + * routine) the registered function is called. + * + * If "cb" is null then the interrupt is effectively disabled. If a + * no bgints are available, CSR_SCHED_BGINT_INVALID is returned, otherwise + * a CsrSchedBgint value is returned to be used in subsequent calls to + * CsrSchedBgint(). id is a possibly NULL identifier used for logging + * purposes only. + * + * RETURNS + * CsrSchedBgint -- CSR_SCHED_BGINT_INVALID denotes failure to obtain a CsrSchedBgintSet. + * + *----------------------------------------------------------------------------*/ +CsrSchedBgint CsrSchedBgintReg(CsrSchedBgintHandler cb, + void *context, + const CsrCharString *id); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedBgintUnreg + * + * DESCRIPTION + * Unregister a background interrupt handler function. + * + * ``irq'' is a background interrupt handle previously obtained + * from a call to CsrSchedBgintReg(). + * + * RETURNS + * void. + * + *----------------------------------------------------------------------------*/ +void CsrSchedBgintUnreg(CsrSchedBgint bgint); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedBgintSet + * + * DESCRIPTION + * Set background interrupt. + * + * RETURNS + * void. + * + *----------------------------------------------------------------------------*/ +void CsrSchedBgintSet(CsrSchedBgint bgint); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedMessagePut + * + * DESCRIPTION + * Sends a message consisting of the integer "mi" and the void * pointer + * "mv" to the message queue "q". + * + * "mi" and "mv" are neither inspected nor changed by the scheduler - the + * task that owns "q" is expected to make sense of the values. "mv" may + * be null. + * + * NOTE + * If "mv" is not null then it will typically be a chunk of CsrPmemAlloc()ed + * memory, though there is no need for it to be so. Tasks should normally + * obey the convention that when a message built with CsrPmemAlloc()ed memory + * is given to CsrSchedMessagePut() then ownership of the memory is ceded to the + * scheduler - and eventually to the recipient task. I.e., the receiver of + * the message will be expected to CsrPmemFree() the message storage. + * + * RETURNS + * void. + * + *----------------------------------------------------------------------------*/ +#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) +void CsrSchedMessagePutStringLog(CsrSchedQid q, + CsrUint16 mi, + void *mv, + CsrUint32 line, + const CsrCharString *file); +#define CsrSchedMessagePut(q, mi, mv) CsrSchedMessagePutStringLog((q), (mi), (mv), __LINE__, __FILE__) +#else +void CsrSchedMessagePut(CsrSchedQid q, + CsrUint16 mi, + void *mv); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedMessageBroadcast + * + * DESCRIPTION + * Sends a message to all tasks. + * + * The user must supply a "factory function" that is called once + * for every task that exists. The "factory function", msg_build_func, + * must allocate and initialise the message and set the msg_build_ptr + * to point to the message when done. + * + * NOTE + * N/A + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) +void CsrSchedMessageBroadcastStringLog(CsrUint16 mi, + void *(*msg_build_func)(void *), + void *msg_build_ptr, + CsrUint32 line, + const CsrCharString *file); +#define CsrSchedMessageBroadcast(mi, fn, ptr) CsrSchedMessageBroadcastStringLog((mi), (fn), (ptr), __LINE__, __FILE__) +#else +void CsrSchedMessageBroadcast(CsrUint16 mi, + void *(*msg_build_func)(void *), + void *msg_build_ptr); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedMessageGet + * + * DESCRIPTION + * Obtains a message from the message queue belonging to the calling task. + * The message consists of one or both of a CsrUint16 and a void *. + * + * RETURNS + * CsrBool - TRUE if a message has been obtained from the queue, else FALSE. + * If a message is taken from the queue, then "*pmi" and "*pmv" are set to + * the "mi" and "mv" passed to CsrSchedMessagePut() respectively. + * + * "pmi" and "pmv" can be null, in which case the corresponding value from + * them message is discarded. + * + *----------------------------------------------------------------------------*/ +CsrBool CsrSchedMessageGet(CsrUint16 *pmi, void **pmv); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedTimerSet + * + * DESCRIPTION + * Causes the void function "fn" to be called with the arguments + * "fniarg" and "fnvarg" after "delay" has elapsed. + * + * "delay" must be less than half the range of a CsrTime. + * + * CsrSchedTimerSet() does nothing with "fniarg" and "fnvarg" except + * deliver them via a call to "fn()". (Unless CsrSchedTimerCancel() + * is used to prevent delivery.) + * + * NOTE + * The function will be called at or after "delay"; the actual delay will + * depend on the timing behaviour of the scheduler's tasks. + * + * RETURNS + * CsrSchedTid - A timed event identifier, can be used in CsrSchedTimerCancel(). + * + *----------------------------------------------------------------------------*/ +#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) +CsrSchedTid CsrSchedTimerSetStringLog(CsrTime delay, + void (*fn)(CsrUint16 mi, void *mv), + CsrUint16 fniarg, + void *fnvarg, + CsrUint32 line, + const CsrCharString *file); +#define CsrSchedTimerSet(d, fn, fni, fnv) CsrSchedTimerSetStringLog((d), (fn), (fni), (fnv), __LINE__, __FILE__) +#else +CsrSchedTid CsrSchedTimerSet(CsrTime delay, + void (*fn)(CsrUint16 mi, void *mv), + CsrUint16 fniarg, + void *fnvarg); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedTimerCancel + * + * DESCRIPTION + * Attempts to prevent the timed event with identifier "eventid" from + * occurring. + * + * RETURNS + * CsrBool - TRUE if cancelled, FALSE if the event has already occurred. + * + *----------------------------------------------------------------------------*/ +#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) +CsrBool CsrSchedTimerCancelStringLog(CsrSchedTid eventid, + CsrUint16 *pmi, + void **pmv, + CsrUint32 line, + const CsrCharString *file); +#define CsrSchedTimerCancel(e, pmi, pmv) CsrSchedTimerCancelStringLog((e), (pmi), (pmv), __LINE__, __FILE__) +#else +CsrBool CsrSchedTimerCancel(CsrSchedTid eventid, + CsrUint16 *pmi, + void **pmv); +#endif + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedTaskQueueGet + * + * DESCRIPTION + * Return the queue identifier for the currently running queue + * + * RETURNS + * CsrSchedQid - The current task queue identifier, or 0xFFFF if not available. + * + *----------------------------------------------------------------------------*/ +CsrSchedQid CsrSchedTaskQueueGet(void); + + +/*----------------------------------------------------------------------------* + * NAME + * CsrSchedTaskQueueGet + * + * DESCRIPTION + * Return the queue identifier for the currently running queue + * + * RETURNS + * CsrCharString - The current task queue identifier, or 0xFFFF if not available. + * + *----------------------------------------------------------------------------*/ +CsrCharString* CsrSchedTaskNameGet(CsrSchedQid ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_sdio.h b/drivers/staging/csr/csr_sdio.h new file mode 100644 index 000000000000..d60ef45a9ab0 --- /dev/null +++ b/drivers/staging/csr/csr_sdio.h @@ -0,0 +1,732 @@ +#ifndef CSR_SDIO_H__ +#define CSR_SDIO_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" +#include "csr_result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Result Codes */ +#define CSR_SDIO_RESULT_INVALID_VALUE ((CsrResult) 1) /* Invalid argument value */ +#define CSR_SDIO_RESULT_NO_DEVICE ((CsrResult) 2) /* The specified device is no longer present */ +#define CSR_SDIO_RESULT_CRC_ERROR ((CsrResult) 3) /* The transmitted/received data or command response contained a CRC error */ +#define CSR_SDIO_RESULT_TIMEOUT ((CsrResult) 4) /* No command response or data received from device, or function enable/disable did not succeed within timeout period */ +#define CSR_SDIO_RESULT_NOT_RESET ((CsrResult) 5) /* The device was not reset */ + +/* Features (for use in features member of CsrSdioFunction) */ +#define CSR_SDIO_FEATURE_BYTE_MODE 0x00000001 /* Transfer sizes do not have to be a multiple of block size */ +#define CSR_SDIO_FEATURE_DMA_CAPABLE_MEM_REQUIRED 0x00000002 /* Bulk operations require DMA friendly memory */ + +/* CsrSdioFunctionId wildcards (for use in CsrSdioFunctionId members) */ +#define CSR_SDIO_ANY_MANF_ID 0xFFFF +#define CSR_SDIO_ANY_CARD_ID 0xFFFF +#define CSR_SDIO_ANY_SDIO_FUNCTION 0xFF +#define CSR_SDIO_ANY_SDIO_INTERFACE 0xFF + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionId + * + * DESCRIPTION + * This structure describes one or more functions of a device, based on + * four qualitative measures. The CsrSdioFunctionId wildcard defines can be + * used for making the CsrSdioFunctionId match more than one function. + * + * MEMBERS + * manfId - Vendor ID (or CSR_SDIO_ANY_MANF_ID). + * cardId - Device ID (or CSR_SDIO_ANY_CARD_ID). + * sdioFunction - SDIO Function number (or CSR_SDIO_ANY_SDIO_FUNCTION). + * sdioInterface - SDIO Standard Interface Code (or CSR_SDIO_ANY_SDIO_INTERFACE) + * + *----------------------------------------------------------------------------*/ +typedef struct +{ + CsrUint16 manfId; /* Vendor ID to match or CSR_SDIO_ANY_MANF_ID */ + CsrUint16 cardId; /* Device ID to match or CSR_SDIO_ANY_CARD_ID */ + CsrUint8 sdioFunction; /* SDIO Function number to match or CSR_SDIO_ANY_SDIO_FUNCTION */ + CsrUint8 sdioInterface; /* SDIO Standard Interface Code to match or CSR_SDIO_ANY_SDIO_INTERFACE */ +} CsrSdioFunctionId; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunction + * + * DESCRIPTION + * This structure represents a single function on a device. + * + * MEMBERS + * sdioId - A CsrSdioFunctionId describing this particular function. The + * subfield shall not contain any CsrSdioFunctionId wildcards. The + * subfields shall describe the specific single function + * represented by this structure. + * blockSize - Actual configured block size, or 0 if unconfigured. + * features - Bit mask with any of CSR_SDIO_FEATURE_* set. + * device - Handle of device containing the function. If two functions have + * the same device handle, they reside on the same device. + * driverData - For use by the Function Driver. The SDIO Driver shall not + * attempt to dereference the pointer. + * priv - For use by the SDIO Driver. The Function Driver shall not attempt + * to dereference the pointer. + * + * + *----------------------------------------------------------------------------*/ +typedef struct +{ + CsrSdioFunctionId sdioId; + CsrUint16 blockSize; /* Actual configured block size, or 0 if unconfigured */ + CsrUint32 features; /* Bit mask with any of CSR_SDIO_FEATURE_* set */ + void *device; /* Handle of device containing the function */ + void *driverData; /* For use by the Function Driver */ + void *priv; /* For use by the SDIO Driver */ +} CsrSdioFunction; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInsertedCallback, CsrSdioRemovedCallback + * + * DESCRIPTION + * CsrSdioInsertedCallback is called when a function becomes available to + * a registered Function Driver that supports the function. + * CsrSdioRemovedCallback is called when a function is no longer available + * to a Function Driver, either because the device has been removed, or the + * Function Driver has been unregistered. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioInsertedCallback)(CsrSdioFunction *function); +typedef void (*CsrSdioRemovedCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptDsrCallback, CsrSdioInterruptCallback + * + * DESCRIPTION + * CsrSdioInterruptCallback is called when an interrupt occurs on the + * the device associated with the specified function. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS (only CsrSdioInterruptCallback) + * A pointer to a CsrSdioInterruptDsrCallback function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioInterruptDsrCallback)(CsrSdioFunction *function); +typedef CsrSdioInterruptDsrCallback (*CsrSdioInterruptCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioSuspendCallback, CsrSdioResumeCallback + * + * DESCRIPTION + * CsrSdioSuspendCallback is called when the system is preparing to go + * into a suspended state. CsrSdioResumeCallback is called when the system + * has entered an active state again. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioSuspendCallback)(CsrSdioFunction *function); +typedef void (*CsrSdioResumeCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioAsyncCallback, CsrSdioAsyncDsrCallback + * + * DESCRIPTION + * CsrSdioAsyncCallback is called when an asynchronous operation completes. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the function calls that initiate + * the operation. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * result - The result of the operation that completed. See the description + * of the initiating function for possible result values. + * + * RETURNS (only CsrSdioAsyncCallback) + * A pointer to a CsrSdioAsyncDsrCallback function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioAsyncDsrCallback)(CsrSdioFunction *function, CsrResult result); +typedef CsrSdioAsyncDsrCallback (*CsrSdioAsyncCallback)(CsrSdioFunction *function, CsrResult result); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionDriver + * + * DESCRIPTION + * Structure representing a Function Driver. + * + * MEMBERS + * inserted - Callback, see description of CsrSdioInsertedCallback. + * removed - Callback, see description of CsrSdioRemovedCallback. + * intr - Callback, see description of CsrSdioInterruptCallback. + * suspend - Callback, see description of CsrSdioSuspendCallback. + * resume - Callback, see description of CsrSdioResumeCallback. + * ids - Array of CsrSdioFunctionId describing one or more functions that + * are supported by the Function Driver. + * idsCount - Length of the ids array. + * priv - For use by the SDIO Driver. The Function Driver may initialise + * it to NULL, but shall otherwise not access the pointer or attempt + * to dereference it. + * + *----------------------------------------------------------------------------*/ +typedef struct +{ + CsrSdioInsertedCallback inserted; + CsrSdioRemovedCallback removed; + CsrSdioInterruptCallback intr; + CsrSdioSuspendCallback suspend; + CsrSdioResumeCallback resume; + CsrSdioFunctionId *ids; + CsrUint8 idsCount; + void *priv; /* For use by the SDIO Driver */ +} CsrSdioFunctionDriver; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionDriverRegister + * + * DESCRIPTION + * Register a Function Driver. + * + * PARAMETERS + * functionDriver - Pointer to struct describing the Function Driver. + * + * RETURNS + * CSR_RESULT_SUCCESS - The Function Driver was successfully + * registered. + * CSR_RESULT_FAILURE - Unable to register the function driver, + * because of an unspecified/unknown error. The + * Function Driver has not been registered. + * CSR_SDIO_RESULT_INVALID_VALUE - The specified Function Driver pointer + * does not point at a valid Function + * Driver structure, or some of the members + * contain invalid entries. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *functionDriver); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionDriverUnregister + * + * DESCRIPTION + * Unregister a previously registered Function Driver. + * + * PARAMETERS + * functionDriver - pointer to struct describing the Function Driver. + * + *----------------------------------------------------------------------------*/ +void CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *functionDriver); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionEnable, CsrSdioFunctionDisable + * + * DESCRIPTION + * Enable/disable the specified function by setting/clearing the + * corresponding bit in the I/O Enable register in function 0, and then + * periodically reading the related bit in the I/O Ready register until it + * is set/clear, limited by an implementation defined timeout. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS + * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The state of the + * related bit in the I/O Enable register is + * undefined. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device, or the related + * bit in the I/O ready register was not + * set/cleared within the timeout period. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioFunctionEnable(CsrSdioFunction *function); +CsrResult CsrSdioFunctionDisable(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptEnable, CsrSdioInterruptDisable + * + * DESCRIPTION + * Enable/disable the interrupt for the specified function by + * setting/clearing the corresponding bit in the INT Enable register in + * function 0. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS + * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The state of the + * related bit in the INT Enable register is + * unchanged. + * CSR_SDIO_RESULT_INVALID_VALUE - The specified function cannot be + * enabled/disabled, because it either + * does not exist or it is not possible to + * individually enable/disable functions. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioInterruptEnable(CsrSdioFunction *function); +CsrResult CsrSdioInterruptDisable(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled interrupt has been handled. Shall only + * be called once, and exactly once for each signalled interrupt to the + * corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * event was signalled. + * + *----------------------------------------------------------------------------*/ +void CsrSdioInterruptAcknowledge(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInsertedAcknowledge, CsrSdioRemovedAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled inserted/removed event has been handled. + * Shall only be called once, and exactly once for each signalled event to + * the corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * inserted was signalled. + * result (CsrSdioInsertedAcknowledge only) + * CSR_RESULT_SUCCESS - The Function Driver has accepted the + * function, and the function is attached to + * the Function Driver until the + * CsrSdioRemovedCallback is called and + * acknowledged. + * CSR_RESULT_FAILURE - Unable to accept the function. The + * function is not attached to the Function + * Driver, and it may be passed to another + * Function Driver which supports the + * function. + * + *----------------------------------------------------------------------------*/ +void CsrSdioInsertedAcknowledge(CsrSdioFunction *function, CsrResult result); +void CsrSdioRemovedAcknowledge(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioSuspendAcknowledge, CsrSdioResumeAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled suspend event has been handled. Shall only + * be called once, and exactly once for each signalled event to the + * corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * event was signalled. + * result + * CSR_RESULT_SUCCESS - Successfully suspended/resumed. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * + *----------------------------------------------------------------------------*/ +void CsrSdioSuspendAcknowledge(CsrSdioFunction *function, CsrResult result); +void CsrSdioResumeAcknowledge(CsrSdioFunction *function, CsrResult result); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioBlockSizeSet + * + * DESCRIPTION + * Set the block size to use for the function. The actual configured block + * size shall be the minimum of: + * 1) Maximum block size supported by the function. + * 2) Maximum block size supported by the host controller. + * 3) The block size specified by the blockSize argument. + * + * When this function returns, the actual configured block size is + * available in the blockSize member of the function struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * blockSize - Block size to use for the function. Valid range is 1 to + * 2048. + * + * RETURNS + * CSR_RESULT_SUCCESS - The block size register on the chip + * was updated. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The configured block + * size is undefined. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER + * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. + * If the ERROR bit is set (but not FUNCTION_NUMBER), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: Setting the block size requires two individual operations. The + * implementation shall ignore the OUT_OF_RANGE bit of the SDIO R5 + * response for the first operation, as the partially configured + * block size may be out of range, even if the final block size + * (after the second operation) is in the valid range. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioBlockSizeSet(CsrSdioFunction *function, CsrUint16 blockSize); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioMaxBusClockFrequencySet + * + * DESCRIPTION + * Set the maximum clock frequency to use for the device associated with + * the specified function. The actual configured clock frequency for the + * device shall be the minimum of: + * 1) Maximum clock frequency supported by the device. + * 2) Maximum clock frequency supported by the host controller. + * 3) Maximum clock frequency specified for any function on the same + * device. + * + * If the clock frequency exceeds 25MHz, it is the responsibility of the + * SDIO driver to enable high speed mode on the device, using the standard + * defined procedure, before increasing the frequency beyond the limit. + * + * Note that the clock frequency configured affects all functions on the + * same device. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * maxFrequency - The maximum clock frequency for the function in Hertz. + * + * RETURNS + * CSR_RESULT_SUCCESS - The maximum clock frequency was succesfully + * set for the function. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * + * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER + * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. + * If the ERROR bit is set (but not FUNCTION_NUMBER), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, CsrUint32 maxFrequency); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead8, CsrSdioWrite8, CsrSdioRead8Async, CsrSdioWrite8Async + * + * DESCRIPTION + * Read/write an 8bit value from/to the specified register address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. No data read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioRead8Async and CsrSdioWrite8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data); +CsrResult CsrSdioWrite8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data); +void CsrSdioRead8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data, CsrSdioAsyncCallback callback); +void CsrSdioWrite8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead16, CsrSdioWrite16, CsrSdioRead16Async, CsrSdioWrite16Async + * + * DESCRIPTION + * Read/write a 16bit value from/to the specified register address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. Data may have been + * partially read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioRead16Async and CsrSdioWrite16Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data); +CsrResult CsrSdioWrite16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data); +void CsrSdioRead16Async(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data, CsrSdioAsyncCallback callback); +void CsrSdioWrite16Async(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioF0Read8, CsrSdioF0Write8, CsrSdioF0Read8Async, + * CsrSdioF0Write8Async + * + * DESCRIPTION + * Read/write an 8bit value from/to the specified register address in + * function 0. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. No data read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioF0Read8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data); +CsrResult CsrSdioF0Write8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data); +void CsrSdioF0Read8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data, CsrSdioAsyncCallback callback); +void CsrSdioF0Write8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead, CsrSdioWrite, CsrSdioReadAsync, CsrSdioWriteAsync + * + * DESCRIPTION + * Read/write a specified number of bytes from/to the specified register + * address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * length - Number of byte to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. Data may have been + * partially read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length); +CsrResult CsrSdioWrite(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length); +void CsrSdioReadAsync(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length, CsrSdioAsyncCallback callback); +void CsrSdioWriteAsync(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioPowerOn, CsrSdioPowerOff + * + * DESCRIPTION + * Power on/off the device. + * + * PARAMETERS + * function - Pointer to struct representing the function that resides on + * the device to power on/off. + * + * RETURNS (only CsrSdioPowerOn) + * CSR_RESULT_SUCCESS - Power was succesfully reapplied and the device + * has been reinitialised. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured during reinitialisation. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device during + * reinitialisation. + * CSR_SDIO_RESULT_NOT_RESET - The power was not removed by the + * CsrSdioPowerOff call. The state of the + * device is unchanged. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioPowerOn(CsrSdioFunction *function); +void CsrSdioPowerOff(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioHardReset + * + * DESCRIPTION + * Perform a hardware reset of the device. + * + * PARAMETERS + * function - Pointer to struct representing the function that resides on + * the device to hard reset. + * + * RETURNS + * CSR_RESULT_SUCCESS - Reset was succesfully performed and the device + * has been reinitialised. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured during reinitialisation. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device during + * reinitialisation. + * CSR_SDIO_RESULT_NOT_RESET - The reset was not applied because it is not + * supported. The state of the device is + * unchanged. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioHardReset(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionActive, CsrSdioFunctionIdle + * + * DESCRIPTION + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +void CsrSdioFunctionActive(CsrSdioFunction *function); +void CsrSdioFunctionIdle(CsrSdioFunction *function); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_serialize_primitive_types.c b/drivers/staging/csr/csr_serialize_primitive_types.c new file mode 100644 index 000000000000..5ea06fc964d1 --- /dev/null +++ b/drivers/staging/csr/csr_serialize_primitive_types.c @@ -0,0 +1,472 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_msgconv.h" +#include "csr_util.h" +#include "csr_pmem.h" +#include "csr_lib.h" + +void CsrUint8Des(CsrUint8 *value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = buffer[*offset]; + *offset += sizeof(*value); +} +EXPORT_SYMBOL_GPL(CsrUint8Des); + +void CsrUint16Des(CsrUint16 *value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = (buffer[*offset + 0] << 0) | + (buffer[*offset + 1] << 8); + *offset += sizeof(*value); +} +EXPORT_SYMBOL_GPL(CsrUint16Des); + +void CsrUint32Des(CsrUint32 *value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = (buffer[*offset + 0] << 0) | + (buffer[*offset + 1] << 8) | + (buffer[*offset + 2] << 16) | + (buffer[*offset + 3] << 24); + *offset += sizeof(*value); +} +EXPORT_SYMBOL_GPL(CsrUint32Des); + +void CsrMemCpyDes(void *value, CsrUint8 *buffer, CsrSize *offset, CsrSize length) +{ + CsrMemCpy(value, &buffer[*offset], length); + *offset += length; +} +EXPORT_SYMBOL_GPL(CsrMemCpyDes); + +void CsrCharStringDes(CsrCharString **value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = CsrStrDup((CsrCharString *) &buffer[*offset]); + *offset += CsrStrLen(*value) + 1; +} +EXPORT_SYMBOL_GPL(CsrCharStringDes); + +void CsrUtf8StringDes(CsrUtf8String **value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = (CsrUtf8String *) CsrStrDup((CsrCharString *) &buffer[*offset]); + *offset += CsrStrLen((CsrCharString *) *value) + 1; +} + +void CsrUtf16StringDes(CsrUtf16String **value, CsrUint8 *buffer, CsrSize *offset) +{ + CsrUint32 length, i; + + CsrUint32Des(&length, buffer, offset); + + *value = CsrPmemAlloc(length * sizeof(**value)); + for (i = 0; i < length; i++) + { + CsrUint16Des(&(*value)[i], buffer, offset); + } +} + +void CsrSizeDes(CsrSize *value, CsrUint8 *buffer, CsrSize *offset) +{ + *value = (buffer[*offset + 0] << 0) | + (buffer[*offset + 1] << 8) | + (buffer[*offset + 2] << 16) | + (buffer[*offset + 3] << 24); + *offset += sizeof(*value); +} + +void CsrVoidPtrDes(void **value, CsrUint8 *buffer, CsrSize *offset) +{ + CsrSizeDes((CsrSize *) value, buffer, offset); +} + +void CsrUint8Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint8 value) +{ + buffer[*offset] = value; + *offset += sizeof(value); +} +EXPORT_SYMBOL_GPL(CsrUint8Ser); + +void CsrUint16Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint16 value) +{ + buffer[*offset + 0] = (CsrUint8) ((value >> 0) & 0xFF); + buffer[*offset + 1] = (CsrUint8) ((value >> 8) & 0xFF); + *offset += sizeof(value); +} +EXPORT_SYMBOL_GPL(CsrUint16Ser); + +void CsrUint32Ser(CsrUint8 *buffer, CsrSize *offset, CsrUint32 value) +{ + buffer[*offset + 0] = (CsrUint8) ((value >> 0) & 0xFF); + buffer[*offset + 1] = (CsrUint8) ((value >> 8) & 0xFF); + buffer[*offset + 2] = (CsrUint8) ((value >> 16) & 0xFF); + buffer[*offset + 3] = (CsrUint8) ((value >> 24) & 0xFF); + *offset += sizeof(value); +} +EXPORT_SYMBOL_GPL(CsrUint32Ser); + +void CsrMemCpySer(CsrUint8 *buffer, CsrSize *offset, const void *value, CsrSize length) +{ + CsrMemCpy(&buffer[*offset], value, length); + *offset += length; +} +EXPORT_SYMBOL_GPL(CsrMemCpySer); + +void CsrCharStringSer(CsrUint8 *buffer, CsrSize *offset, const CsrCharString *value) +{ + if (value) + { + CsrStrCpy(((CsrCharString *) &buffer[*offset]), value); + *offset += CsrStrLen(value) + 1; + } + else + { + CsrUint8Ser(buffer, offset, 0); + } +} +EXPORT_SYMBOL_GPL(CsrCharStringSer); + +void CsrUtf8StringSer(CsrUint8 *buffer, CsrSize *offset, const CsrUtf8String *value) +{ + CsrCharStringSer(buffer, offset, (CsrCharString *) value); +} + +void CsrUtf16StringSer(CsrUint8 *buffer, CsrSize *offset, const CsrUtf16String *value) +{ + if (value) + { + CsrUint32 length = CsrUtf16StrLen(value) + 1; + CsrUint32 i; + + CsrUint32Ser(buffer, offset, length); + + for (i = 0; i < length; i++) + { + CsrUint16Ser(buffer, offset, (CsrUint16) value[i]); + } + } + else + { + CsrUint32Ser(buffer, offset, 0); + } +} + +void CsrSizeSer(CsrUint8 *buffer, CsrSize *offset, CsrSize value) +{ + buffer[*offset + 0] = (CsrUint8) ((value >> 0) & 0xFF); + buffer[*offset + 1] = (CsrUint8) ((value >> 8) & 0xFF); + buffer[*offset + 2] = (CsrUint8) ((value >> 16) & 0xFF); + buffer[*offset + 3] = (CsrUint8) ((value >> 24) & 0xFF); + *offset += sizeof(value); +} + +void CsrVoidPtrSer(CsrUint8 *buffer, CsrSize *offset, void *ptr) +{ + CsrSizeSer(buffer, offset, (CsrSize) ptr); +} + +CsrUint32 CsrCharStringSerLen(const CsrCharString *str) +{ + if (str) + { + return (CsrUint32) (CsrStrLen(str) + sizeof(*str)); + } + else + { + return sizeof(*str); + } +} + +CsrUint32 CsrUtf8StringSerLen(const CsrUtf8String *str) +{ + if (str) + { + return (CsrUint32) (CsrStrLen((CsrCharString *) str) + sizeof(*str)); + } + else + { + return sizeof(*str); + } +} + +CsrUint32 CsrUtf16StringSerLen(const CsrUtf16String *str) +{ + if (str) + { + /* We always write down the length of the string */ + return sizeof(CsrUint32) + (CsrUtf16StrLen(str) + 1) * sizeof(*str); + } + else + { + return sizeof(CsrUint32); + } +} + +CsrSize CsrEventSizeof(void *msg) +{ + return 2; +} + +CsrUint8 *CsrEventSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEvent *primitive = (CsrEvent *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + return ptr; +} + +void *CsrEventDes(CsrUint8 *buffer, CsrSize length) +{ + CsrEvent *primitive = (CsrEvent *) CsrPmemAlloc(sizeof(CsrEvent)); + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint8Sizeof(void *msg) +{ + return 3; +} + +CsrUint8 *CsrEventCsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint8 *primitive = (CsrEventCsrUint8 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint8Ser(ptr, len, primitive->value); + return ptr; +} + +void *CsrEventCsrUint8Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint8 *primitive = (CsrEventCsrUint8 *) CsrPmemAlloc(sizeof(CsrEventCsrUint8)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint8Des(&primitive->value, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint16Sizeof(void *msg) +{ + return 4; +} + +CsrUint8 *CsrEventCsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint16 *primitive = (CsrEventCsrUint16 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint16Ser(ptr, len, primitive->value); + return ptr; +} + +void *CsrEventCsrUint16Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint16 *primitive = (CsrEventCsrUint16 *) CsrPmemAlloc(sizeof(CsrEventCsrUint16)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint16Des(&primitive->value, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint32Sizeof(void *msg) +{ + return 6; +} + +CsrUint8 *CsrEventCsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint32 *primitive = (CsrEventCsrUint32 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint32Ser(ptr, len, primitive->value); + return ptr; +} + +void *CsrEventCsrUint32Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint32 *primitive = (CsrEventCsrUint32 *) CsrPmemAlloc(sizeof(CsrEventCsrUint32)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint32Des(&primitive->value, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint16CsrUint8Sizeof(void *msg) +{ + return 5; +} + +CsrUint8 *CsrEventCsrUint16CsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint16CsrUint8 *primitive = (CsrEventCsrUint16CsrUint8 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint16Ser(ptr, len, primitive->value1); + CsrUint8Ser(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint16CsrUint8Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint16CsrUint8 *primitive = (CsrEventCsrUint16CsrUint8 *) CsrPmemAlloc(sizeof(CsrEventCsrUint16CsrUint8)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint16Des(&primitive->value1, buffer, &offset); + CsrUint8Des(&primitive->value2, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint16CsrUint16Sizeof(void *msg) +{ + return 6; +} + +CsrUint8 *CsrEventCsrUint16CsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint16CsrUint16 *primitive = (CsrEventCsrUint16CsrUint16 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint16Ser(ptr, len, primitive->value1); + CsrUint16Ser(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint16CsrUint16Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint16CsrUint16 *primitive = (CsrEventCsrUint16CsrUint16 *) CsrPmemAlloc(sizeof(CsrEventCsrUint16CsrUint16)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint16Des(&primitive->value1, buffer, &offset); + CsrUint16Des(&primitive->value2, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint16CsrUint32Sizeof(void *msg) +{ + return 8; +} + +CsrUint8 *CsrEventCsrUint16CsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint16CsrUint32 *primitive = (CsrEventCsrUint16CsrUint32 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint16Ser(ptr, len, primitive->value1); + CsrUint32Ser(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint16CsrUint32Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint16CsrUint32 *primitive = (CsrEventCsrUint16CsrUint32 *) CsrPmemAlloc(sizeof(CsrEventCsrUint16CsrUint32)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint16Des(&primitive->value1, buffer, &offset); + CsrUint32Des(&primitive->value2, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint16CsrCharStringSizeof(void *msg) +{ + CsrEventCsrUint16CsrCharString *primitive = (CsrEventCsrUint16CsrCharString *) msg; + return 4 + CsrStrLen(primitive->value2) + 1; +} + +CsrUint8 *CsrEventCsrUint16CsrCharStringSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint16CsrCharString *primitive = (CsrEventCsrUint16CsrCharString *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint16Ser(ptr, len, primitive->value1); + CsrCharStringSer(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint16CsrCharStringDes(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint16CsrCharString *primitive = (CsrEventCsrUint16CsrCharString *) CsrPmemAlloc(sizeof(CsrEventCsrUint16CsrCharString)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint16Des(&primitive->value1, buffer, &offset); + CsrCharStringDes(&primitive->value2, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint32CsrUint16Sizeof(void *msg) +{ + return 8; +} + +CsrUint8 *CsrEventCsrUint32CsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint32CsrUint16 *primitive = (CsrEventCsrUint32CsrUint16 *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint32Ser(ptr, len, primitive->value1); + CsrUint16Ser(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint32CsrUint16Des(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint32CsrUint16 *primitive = (CsrEventCsrUint32CsrUint16 *) CsrPmemAlloc(sizeof(CsrEventCsrUint32CsrUint16)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint32Des(&primitive->value1, buffer, &offset); + CsrUint16Des(&primitive->value2, buffer, &offset); + + return primitive; +} + +CsrSize CsrEventCsrUint32CsrCharStringSizeof(void *msg) +{ + CsrEventCsrUint32CsrCharString *primitive = (CsrEventCsrUint32CsrCharString *) msg; + return 6 + CsrStrLen(primitive->value2) + 1; +} + +CsrUint8 *CsrEventCsrUint32CsrCharStringSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrEventCsrUint32CsrCharString *primitive = (CsrEventCsrUint32CsrCharString *) msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + CsrUint32Ser(ptr, len, primitive->value1); + CsrCharStringSer(ptr, len, primitive->value2); + return ptr; +} + +void *CsrEventCsrUint32CsrCharStringDes(CsrUint8 *buffer, CsrSize length) +{ + CsrEventCsrUint32CsrCharString *primitive = (CsrEventCsrUint32CsrCharString *) CsrPmemAlloc(sizeof(CsrEventCsrUint32CsrCharString)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + CsrUint32Des(&primitive->value1, buffer, &offset); + CsrCharStringDes(&primitive->value2, buffer, &offset); + + return primitive; +} diff --git a/drivers/staging/csr/csr_time.c b/drivers/staging/csr/csr_time.c new file mode 100644 index 000000000000..1ef61e3efac6 --- /dev/null +++ b/drivers/staging/csr/csr_time.c @@ -0,0 +1,71 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) +#include +#include +#endif + +#include +#include + +#include "csr_types.h" +#include "csr_time.h" + +CsrTime CsrTimeGet(CsrTime *high) +{ + struct timespec ts; + CsrUint64 time; + CsrTime low; + + ts = current_kernel_time(); + time = (CsrUint64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + + if (high != NULL) + { + *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF); + } + + low = (CsrTime) (time & 0xFFFFFFFF); + + return low; +} +EXPORT_SYMBOL_GPL(CsrTimeGet); + +void CsrTimeUtcGet(CsrTimeUtc *tod, CsrTime *low, CsrTime *high) +{ + struct timespec ts; + CsrUint64 time; + + ts = current_kernel_time(); + time = (CsrUint64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + + if (high != NULL) + { + *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF); + } + + if (low != NULL) + { + *low = (CsrTime) (time & 0xFFFFFFFF); + } + + if (tod != NULL) + { + struct timeval tv; + do_gettimeofday(&tv); + tod->sec = tv.tv_sec; + tod->msec = tv.tv_usec / 1000; + } +} diff --git a/drivers/staging/csr/csr_time.h b/drivers/staging/csr/csr_time.h new file mode 100644 index 000000000000..0ede47e911f1 --- /dev/null +++ b/drivers/staging/csr/csr_time.h @@ -0,0 +1,205 @@ +#ifndef CSR_TIME_H__ +#define CSR_TIME_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + + NAME + CsrTime + + DESCRIPTION + Type to hold a value describing the current system time, which is a + measure of time elapsed since some arbitrarily defined fixed time + reference, usually associated with system startup. + +*******************************************************************************/ +typedef CsrUint32 CsrTime; + + +/******************************************************************************* + + NAME + CsrTimeUtc + + DESCRIPTION + Type to hold a value describing a UTC wallclock time expressed in + seconds and milliseconds elapsed since midnight January 1st 1970. + +*******************************************************************************/ +typedef struct +{ + CsrUint32 sec; + CsrUint16 msec; +} CsrTimeUtc; + + +/******************************************************************************* + + NAME + CsrTimeGet + + DESCRIPTION + Returns the current system time in a low and a high part. The low part + is expressed in microseconds. The high part is incremented when the low + part wraps to provide an extended range. + + The caller may provide a NULL pointer as the high parameter. In this case + the function just returns the low part and ignores the high parameter. + + Although the time is expressed in microseconds the actual resolution is + platform dependent and can be less. It is recommended that the + resolution is at least 10 milliseconds. + + PARAMETERS + high - Pointer to variable that will receive the high part of the + current system time. Passing NULL is valid. + + RETURNS + Low part of current system time in microseconds. + +*******************************************************************************/ +CsrTime CsrTimeGet(CsrTime *high); + + +/******************************************************************************* + + NAME + CsrTimeUtcGet + + DESCRIPTION + Get the current system wallclock time, and optionally the current system + time in a low and a high part as would have been returned by + CsrTimeGet. + + Although CsrTimeUtc is expressed in seconds and milliseconds, the actual + resolution is platform dependent, and can be less. It is recommended + that the resolution is at least 1 second. + + PARAMETERS + tod - Pointer to variable that will receive the current system + wallclock time. + low - The low part of the current system time in microseconds. Passing + NULL is valid. + high - The high part of the current system time in microseconds. Passing + NULL is valid. + +*******************************************************************************/ +void CsrTimeUtcGet(CsrTimeUtc *tod, CsrTime *low, CsrTime *high); + + +/*------------------------------------------------------------------*/ +/* CsrTime Macros */ +/*------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeAdd + * + * DESCRIPTION + * Add two time values. Adding the numbers can overflow the range of a + * CsrTime, so the user must be cautious. + * + * RETURNS + * CsrTime - the sum of "t1" and "t2". + * + *----------------------------------------------------------------------------*/ +#define CsrTimeAdd(t1, t2) ((t1) + (t2)) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeSub + * + * DESCRIPTION + * Subtract two time values. Subtracting the numbers can provoke an + * underflow, so the user must be cautious. + * + * RETURNS + * CsrTime - "t1" - "t2". + * + *----------------------------------------------------------------------------*/ +#define CsrTimeSub(t1, t2) ((CsrInt32) (t1) - (CsrInt32) (t2)) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeEq + * + * DESCRIPTION + * Compare two time values. + * + * RETURNS + * !0 if "t1" equal "t2", else 0. + * + *----------------------------------------------------------------------------*/ +#define CsrTimeEq(t1, t2) ((t1) == (t2)) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeGt + * + * DESCRIPTION + * Compare two time values. + * + * RETURNS + * !0 if "t1" is greater than "t2", else 0. + * + *----------------------------------------------------------------------------*/ +#define CsrTimeGt(t1, t2) (CsrTimeSub((t1), (t2)) > 0) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeGe + * + * DESCRIPTION + * Compare two time values. + * + * RETURNS + * !0 if "t1" is greater than, or equal to "t2", else 0. + * + *----------------------------------------------------------------------------*/ +#define CsrTimeGe(t1, t2) (CsrTimeSub((t1), (t2)) >= 0) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeLt + * + * DESCRIPTION + * Compare two time values. + * + * RETURNS + * !0 if "t1" is less than "t2", else 0. + * + *----------------------------------------------------------------------------*/ +#define CsrTimeLt(t1, t2) (CsrTimeSub((t1), (t2)) < 0) + +/*----------------------------------------------------------------------------* + * NAME + * CsrTimeLe + * + * DESCRIPTION + * Compare two time values. + * + * RETURNS + * !0 if "t1" is less than, or equal to "t2", else 0. + * + *----------------------------------------------------------------------------*/ +#define CsrTimeLe(t1, t2) (CsrTimeSub((t1), (t2)) <= 0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_types.h b/drivers/staging/csr/csr_types.h new file mode 100644 index 000000000000..d7d2c5d061fe --- /dev/null +++ b/drivers/staging/csr/csr_types.h @@ -0,0 +1,93 @@ +#ifndef CSR_TYPES_H__ +#define CSR_TYPES_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#undef FALSE +#define FALSE (0) + +#undef TRUE +#define TRUE (1) + +/* Basic types */ +typedef size_t CsrSize; /* Return type of sizeof (ISO/IEC 9899:1990 7.1.6) */ +typedef ptrdiff_t CsrPtrdiff; /* Type of the result of subtracting two pointers (ISO/IEC 9899:1990 7.1.6) */ +typedef uintptr_t CsrUintptr; /* Unsigned integer large enough to hold any pointer (ISO/IEC 9899:1999 7.18.1.4) */ +#ifdef __KERNEL__ +typedef ptrdiff_t CsrIntptr; /* intptr_t is not defined in kernel. Use the equivalent ptrdiff_t. */ +#else +typedef intptr_t CsrIntptr; /* Signed integer large enough to hold any pointer (ISO/IEC 9899:1999 7.18.1.4) */ +#endif + +/* Unsigned fixed width types */ +typedef uint8_t CsrUint8; +typedef uint16_t CsrUint16; +typedef uint32_t CsrUint32; + +/* Signed fixed width types */ +typedef int8_t CsrInt8; +typedef int16_t CsrInt16; +typedef int32_t CsrInt32; + +/* Boolean */ +typedef CsrUint8 CsrBool; + +/* String types */ +typedef char CsrCharString; +typedef CsrUint8 CsrUtf8String; +typedef CsrUint16 CsrUtf16String; /* 16-bit UTF16 strings */ +typedef CsrUint32 CsrUint24; + +/* + * 64-bit integers + * + * Note: If a given compiler does not support 64-bit types, it is + * OK to omit these definitions; 32-bit versions of the code using + * these types may be available. Consult the relevant documentation + * or the customer support group for information on this. + */ +#define CSR_HAVE_64_BIT_INTEGERS +typedef uint64_t CsrUint64; +typedef int64_t CsrInt64; + +/* + * Floating point + * + * Note: If a given compiler does not support floating point, it is + * OK to omit these definitions; alternative versions of the code using + * these types may be available. Consult the relevant documentation + * or the customer support group for information on this. + */ +#define CSR_HAVE_FLOATING_POINT +typedef float CsrFloat; +typedef double CsrDouble; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_unicode.h b/drivers/staging/csr/csr_unicode.h new file mode 100644 index 000000000000..9faf8567a5a1 --- /dev/null +++ b/drivers/staging/csr/csr_unicode.h @@ -0,0 +1,190 @@ +#ifndef CSR_UNICODE_H__ +#define CSR_UNICODE_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CsrUtf16String *CsrUint32ToUtf16String(CsrUint32 number); + +CsrUint32 CsrUtf16StringToUint32(const CsrUtf16String *unicodeString); +CsrUint32 CsrUtf16StrLen(const CsrUtf16String *unicodeString); + +CsrUtf8String *CsrUtf16String2Utf8(const CsrUtf16String *source); + +CsrUtf16String *CsrUtf82Utf16String(const CsrUtf8String *utf8String); + +CsrUtf16String *CsrUtf16StrCpy(CsrUtf16String *target, const CsrUtf16String *source); +CsrUtf16String *CsrUtf16StringDuplicate(const CsrUtf16String *source); + +CsrUint16 CsrUtf16StrICmp(const CsrUtf16String *string1, const CsrUtf16String *string2); +CsrUint16 CsrUtf16StrNICmp(const CsrUtf16String *string1, const CsrUtf16String *string2, CsrUint32 count); + +CsrUtf16String *CsrUtf16MemCpy(CsrUtf16String *dest, const CsrUtf16String *src, CsrUint32 count); +CsrUtf16String *CsrUtf16ConcatenateTexts(const CsrUtf16String *inputText1, const CsrUtf16String *inputText2, + const CsrUtf16String *inputText3, const CsrUtf16String *inputText4); + +CsrUtf16String *CsrUtf16String2XML(CsrUtf16String *str); +CsrUtf16String *CsrXML2Utf16String(CsrUtf16String *str); + +CsrInt32 CsrUtf8StrCmp(const CsrUtf8String *string1, const CsrUtf8String *string2); +CsrInt32 CsrUtf8StrNCmp(const CsrUtf8String *string1, const CsrUtf8String *string2, CsrSize count); +CsrUint32 CsrUtf8StringLengthInBytes(const CsrUtf8String *string); + +/******************************************************************************* + + NAME + CsrUtf8StrTruncate + + DESCRIPTION + In-place truncate a string on a UTF-8 character boundary by writing a + null character somewhere in the range target[count - 3]:target[count]. + + Please note that memory passed must be at least of length count + 1, to + ensure space for a full length string that is terminated at + target[count], in the event that target[count - 1] is the final byte of + a UTF-8 character. + + PARAMETERS + target - Target string to truncate. + count - The desired length, in bytes, of the resulting string. Depending + on the contents, the resulting string length will be between + count - 3 and count. + + RETURNS + Returns target + +*******************************************************************************/ +CsrUtf8String *CsrUtf8StrTruncate(CsrUtf8String *target, CsrSize count); + +/******************************************************************************* + + NAME + CsrUtf8StrCpy + + DESCRIPTION + Copies the null terminated UTF-8 string pointed at by source into the + memory pointed at by target, including the terminating null character. + + To avoid overflows, the size of the memory pointed at by target shall be + long enough to contain the same UTF-8 string as source (including the + terminating null character), and should not overlap in memory with + source. + + PARAMETERS + target - Pointer to the target memory where the content is to be copied. + source - UTF-8 string to be copied. + + RETURNS + Returns target + +*******************************************************************************/ +CsrUtf8String *CsrUtf8StrCpy(CsrUtf8String *target, const CsrUtf8String *source); + +/******************************************************************************* + + NAME + CsrUtf8StrNCpy + + DESCRIPTION + Copies the first count bytes of source to target. If the end of the + source UTF-8 string (which is signaled by a null-character) is found + before count bytes have been copied, target is padded with null + characters until a total of count bytes have been written to it. + + No null-character is implicitly appended to the end of target, so target + will only be null-terminated if the length of the UTF-8 string in source + is less than count. + + PARAMETERS + target - Pointer to the target memory where the content is to be copied. + source - UTF-8 string to be copied. + count - Maximum number of bytes to be written to target. + + RETURNS + Returns target + +*******************************************************************************/ +CsrUtf8String *CsrUtf8StrNCpy(CsrUtf8String *target, const CsrUtf8String *source, CsrSize count); + +/******************************************************************************* + + NAME + CsrUtf8StrNCpyZero + + DESCRIPTION + Equivalent to CsrUtf8StrNCpy, but if the length of source is equal to or + greater than count the target string is truncated on a UTF-8 character + boundary by writing a null character somewhere in the range + target[count - 4]:target[count - 1], leaving the target string + unconditionally null terminated in all cases. + + Please note that if the length of source is shorter than count, no + truncation will be applied, and the target string will be a one to one + copy of source. + + PARAMETERS + target - Pointer to the target memory where the content is to be copied. + source - UTF-8 string to be copied. + count - Maximum number of bytes to be written to target. + + RETURNS + Returns target + +*******************************************************************************/ +CsrUtf8String *CsrUtf8StrNCpyZero(CsrUtf8String *target, const CsrUtf8String *source, CsrSize count); + +/******************************************************************************* + + NAME + CsrUtf8StrDup + + DESCRIPTION + This function will allocate memory and copy the source string into the + allocated memory, which is then returned as a duplicate of the original + string. The memory returned must be freed by calling CsrPmemFree when + the duplicate is no longer needed. + + PARAMETERS + source - UTF-8 string to be duplicated. + + RETURNS + Returns a duplicate of source. + +*******************************************************************************/ +CsrUtf8String *CsrUtf8StrDup(const CsrUtf8String *source); + +CsrUtf8String *CsrUtf8StringConcatenateTexts(const CsrUtf8String *inputText1, const CsrUtf8String *inputText2, const CsrUtf8String *inputText3, const CsrUtf8String *inputText4); + +/* + * UCS2 + * + * D-13157 + */ +typedef CsrUint8 CsrUcs2String; + +CsrSize CsrUcs2ByteStrLen(const CsrUcs2String *ucs2String); +CsrSize CsrConverterUcs2ByteStrLen(const CsrUcs2String *str); + +CsrUint8 *CsrUcs2ByteString2Utf8(const CsrUcs2String *ucs2String); +CsrUcs2String *CsrUtf82Ucs2ByteString(const CsrUint8 *utf8String); + +CsrUint8 *CsrUtf16String2Ucs2ByteString(const CsrUtf16String *source); +CsrUtf16String *CsrUcs2ByteString2Utf16String(const CsrUint8 *source); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_utf16.c b/drivers/staging/csr/csr_utf16.c new file mode 100644 index 000000000000..9259635851f7 --- /dev/null +++ b/drivers/staging/csr/csr_utf16.c @@ -0,0 +1,1136 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#include +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_unicode.h" +#include "csr_util.h" + +#define UNI_SUR_HIGH_START ((CsrUint32) 0xD800) +#define UNI_SUR_HIGH_END ((CsrUint32) 0xDBFF) +#define UNI_SUR_LOW_START ((CsrUint32) 0xDC00) +#define UNI_SUR_LOW_END ((CsrUint32) 0xDFFF) +#define UNI_REPLACEMENT_CHAR ((CsrUint32) 0xFFFD) +#define UNI_HALF_SHIFT ((CsrUint8) 10) /* used for shifting by 10 bits */ +#define UNI_HALF_BASE ((CsrUint32) 0x00010000) +#define UNI_BYTEMASK ((CsrUint32) 0xBF) +#define UNI_BYTEMARK ((CsrUint32) 0x80) + +#define CAPITAL(x) ((x >= 'a') && (x <= 'z') ? ((x) & 0x00DF) : (x)) + +/* +* Index into the table with the first byte to get the number of trailing bytes in a utf-8 character. +* -1 if the byte has an invalid value. +* +* Legal sequences are: +* +* byte 1st 2nd 3rd 4th +* +* 00-7F +* C2-DF 80-BF +* E0 A0-BF 80-BF +* E1-EC 80-BF 80-BF +* ED 80-9F 80-BF +* EE-EF 80-BF 80-BF +* F0 90-BF 80-BF 80-BF +* F1-F3 80-BF 80-BF 80-BF +* F4 80-8F 80-BF 80-BF +*/ +static const CsrInt8 trailingBytesForUtf8[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x3F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x7F */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80 - 0x9F */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xA0 - 0xBF */ + -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xC0 - 0xDF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xE0 - 0xFF */ +}; + +/* Values to be substracted from a CsrUint32 when converting from UTF8 to UTF16 */ +static const CsrUint32 offsetsFromUtf8[4] = +{ + 0x00000000, 0x00003080, 0x000E2080, 0x03C82080 +}; + +/******************************************************************************** +* +* Name: CsrUint32ToUtf16String +* +* Description: The function converts an 32 bit number to an UTF-16 string +* that is allocated and 0-terminated. +* +* Input: 32 bit number. +* +* Output: A string of UTF-16 characters. +* +*********************************************************************************/ +CsrUtf16String *CsrUint32ToUtf16String(CsrUint32 number) +{ + CsrUint16 count, noOfDigits; + CsrUtf16String *output; + CsrUint32 tempNumber; + + /* calculate the number of digits in the output */ + tempNumber = number; + noOfDigits = 1; + while (tempNumber >= 10) + { + tempNumber = tempNumber / 10; + noOfDigits++; + } + + output = (CsrUtf16String *) CsrPmemAlloc(sizeof(CsrUtf16String) * (noOfDigits + 1)); /*add space for 0-termination*/ + + tempNumber = number; + for (count = noOfDigits; count > 0; count--) + { + output[count - 1] = (CsrUtf16String) ((tempNumber % 10) + '0'); + tempNumber = tempNumber / 10; + } + output[noOfDigits] = '\0'; + + return output; +} + +/******************************************************************************** +* +* Name: CsrUtf16StringToUint32 +* +* Description: The function converts an UTF-16 string that is +* 0-terminated into a 32 bit number. +* +* Input: A string of UTF-16 characters containig a number. +* +* Output: 32 bit number. +* +*********************************************************************************/ +CsrUint32 CsrUtf16StringToUint32(const CsrUtf16String *unicodeString) +{ + CsrUint16 numLen, count; + CsrUint32 newNumber = 0; + + numLen = (CsrUint16) CsrUtf16StrLen(unicodeString); + + if ((numLen > 10) || (numLen == 0) || (unicodeString == NULL)) /*CSRMAX number is 4.294.967.295 */ + { + return 0; + } + + for (count = 0; count < numLen; count++) + { + CsrUtf16String input = unicodeString[count]; + if ((input < 0x30) || (input > 0x39) || ((newNumber == 0x19999999) && (input > 0x35)) || (newNumber > 0x19999999)) /* chars are present or number is too large now causing number to get to large when *10 */ + { + return 0; + } + + newNumber = (newNumber * 10) + (input - 0x30); + } + return newNumber; +} + +/******************************************************************************** +* +* Name: CsrUtf16MemCpy +* +* Description: The function copies count number of 16 bit data elements +* from srv to dest. +* +* Input: A pointer to an unicoded string. +* +* Output: A pointer to an unicoded string. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf16MemCpy(CsrUtf16String *dest, const CsrUtf16String *src, CsrUint32 count) +{ + return CsrMemCpy((CsrUint8 *) dest, (CsrUint8 *) src, count * sizeof(CsrUtf16String)); +} + +/******************************************************************************** +* +* Name: CsrUtf16ConcatenateTexts +* +* Description: The function merge the contents of 4 unicoded input pointers +* into a new string. +* +* Input: 4 unicoded input strings (UTF-16). +* +* Output: A new unicoded string (UTF-16) containing the combined strings. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf16ConcatenateTexts(const CsrUtf16String *inputText1, const CsrUtf16String *inputText2, + const CsrUtf16String *inputText3, const CsrUtf16String *inputText4) +{ + CsrUtf16String *outputText; + CsrUint32 textLen, textLen1, textLen2, textLen3, textLen4; + + textLen1 = CsrUtf16StrLen(inputText1); + textLen2 = CsrUtf16StrLen(inputText2); + textLen3 = CsrUtf16StrLen(inputText3); + textLen4 = CsrUtf16StrLen(inputText4); + + textLen = textLen1 + textLen2 + textLen3 + textLen4; + + if (textLen == 0) /*stop here is all lengths are 0*/ + { + return NULL; + } + + outputText = (CsrUtf16String *) CsrPmemAlloc((textLen + 1) * sizeof(CsrUtf16String)); /* add space for 0-termination*/ + + + if (inputText1 != NULL) + { + CsrUtf16MemCpy(outputText, inputText1, textLen1); + } + + if (inputText2 != NULL) + { + CsrUtf16MemCpy(&(outputText[textLen1]), inputText2, textLen2); + } + + if (inputText3 != NULL) + { + CsrUtf16MemCpy(&(outputText[textLen1 + textLen2]), inputText3, textLen3); + } + + if (inputText4 != NULL) + { + CsrUtf16MemCpy(&(outputText[textLen1 + textLen2 + textLen3]), inputText4, textLen4); + } + + outputText[textLen] = '\0'; + + return outputText; +} + +/******************************************************************************** +* +* Name: CsrUtf16StrLen +* +* Description: The function returns the number of 16 bit elements present +* in the 0-terminated string. +* +* Input: 0-terminated string of 16 bit unicoded characters. +* +* Output: The number of 16 bit elements in the string. +* +*********************************************************************************/ +CsrUint32 CsrUtf16StrLen(const CsrUtf16String *unicodeString) +{ + CsrUint32 length; + + length = 0; + if (unicodeString != NULL) + { + while (*unicodeString) + { + length++; + unicodeString++; + } + } + return length; +} + +/******************************************************************************** +* +* Name: CsrUtf16String2Utf8 +* +* Description: The function decodes an UTF-16 string into an UTF8 byte +* oriented string. +* +* Input: 0-terminated UTF-16 string characters. +* +* Output: 0-terminated string of byte oriented UTF8 coded characters. +* +*********************************************************************************/ +CsrUtf8String *CsrUtf16String2Utf8(const CsrUtf16String *source) +{ + CsrUtf8String *dest, *destStart = NULL; + CsrUint32 i; + CsrUint32 ch; + CsrUint32 length; + CsrUint32 sourceLength; + CsrUint8 bytes; + CsrBool appendNull = FALSE; + + CsrUint8 firstByteMark[5] = {0x00, 0x00, 0xC0, 0xE0, 0xF0}; + + if (!source) + { + return NULL; + } + + length = 0; + sourceLength = CsrUtf16StrLen(source) + 1; + + for (i = 0; i < sourceLength; i++) + { + ch = source[i]; + if ((ch >= UNI_SUR_HIGH_START) && (ch <= UNI_SUR_HIGH_END)) /* This is a high surrogate */ + { + if (i + 1 < sourceLength) /* The low surrogate is in the source */ + { + CsrUint32 ch2 = source[++i]; + if ((ch2 >= UNI_SUR_LOW_START) && (ch2 <= UNI_SUR_LOW_END)) /* And it is a legal low surrogate */ + { + length += 4; + } + else /* It is not a low surrogate, instead put a Unicode + 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + length += 3; + i--; /* Substract 1 again as the conversion must continue after the ill-formed code unit */ + } + } + else /* The low surrogate does not exist, instead put a Unicode + 'REPLACEMENT CHARACTER' (U+FFFD), and the null terminated character */ + { + length += 4; + } + } + else if ((ch >= UNI_SUR_LOW_START) && (ch <= UNI_SUR_LOW_END)) /* The value of UTF-16 is not allowed to be in this range, instead put + a Unicode 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + length += 3; + } + else /* Figure out how many bytes that are required */ + { + if (ch < 0x0080) + { + length++; + } + else if (ch < 0x0800) + { + length += 2; + } + else + { + length += 3; + } + } + } + + dest = CsrPmemAlloc(length); + destStart = dest; + + for (i = 0; i < sourceLength; i++) + { + ch = source[i]; + if ((ch >= UNI_SUR_HIGH_START) && (ch <= UNI_SUR_HIGH_END)) /* This is a high surrogate */ + { + if (i + 1 < sourceLength) /* The low surrogate is in the source */ + { + CsrUint32 ch2 = source[++i]; + if ((ch2 >= UNI_SUR_LOW_START) && (ch2 <= UNI_SUR_LOW_END)) /* And it is a legal low surrogate, convert to UTF-32 */ + { + ch = ((ch - UNI_SUR_HIGH_START) << UNI_HALF_SHIFT) + (ch2 - UNI_SUR_LOW_START) + UNI_HALF_BASE; + } + else /* It is not a low surrogate, instead put a Unicode + 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + ch = UNI_REPLACEMENT_CHAR; + i--; /* Substract 1 again as the conversion must continue after the ill-formed code unit */ + } + } + else /* The low surrogate does not exist, instead put a Unicode + 'REPLACEMENT CHARACTER' (U+FFFD), and the null terminated character */ + { + ch = UNI_REPLACEMENT_CHAR; + appendNull = TRUE; + } + } + else if ((ch >= UNI_SUR_LOW_START) && (ch <= UNI_SUR_LOW_END)) /* The value of UTF-16 is not allowed to be in this range, instead put + a Unicode 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + ch = UNI_REPLACEMENT_CHAR; + } + + /* Figure out how many bytes that are required */ + if (ch < (CsrUint32) 0x80) + { + bytes = 1; + } + else if (ch < (CsrUint32) 0x800) + { + bytes = 2; + } + else if (ch < (CsrUint32) 0x10000) + { + bytes = 3; + } + else if (ch < (CsrUint32) 0x110000) + { + bytes = 4; + } + else + { + bytes = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + dest += bytes; + + switch (bytes) /* Convert character to UTF-8. Note: everything falls through. */ + { + case 4: + { + *--dest = (CsrUint8) ((ch | UNI_BYTEMARK) & UNI_BYTEMASK); + ch >>= 6; + } + /* FALLTHROUGH */ + case 3: + { + *--dest = (CsrUint8) ((ch | UNI_BYTEMARK) & UNI_BYTEMASK); + ch >>= 6; + } + /* FALLTHROUGH */ + case 2: + { + *--dest = (CsrUint8) ((ch | UNI_BYTEMARK) & UNI_BYTEMASK); + ch >>= 6; + } + /* FALLTHROUGH */ + case 1: + { + *--dest = (CsrUint8) (ch | firstByteMark[bytes]); + } + /* FALLTHROUGH */ + default: + { + break; + } + } + + dest += bytes; + } + + if (appendNull) /* Append the \0 character */ + { + *dest = '\0'; + } + + return destStart; +} + +/***************************************************************************** + + NAME + isLegalUtf8 + + DESCRIPTION + Returns TRUE if the given UFT-8 code unit is legal as defined by the + Unicode standard (see Chapter 3: Conformance, Section 3.9: Unicode + Encoding Forms, UTF-8). + + This function assumes that the length parameter is unconditionally + correct and that the first byte is already validated by looking it up + in the trailingBytesForUtf8 array, which also reveals the number of + trailing bytes. + + Legal code units are composed of one of the following byte sequences: + + 1st 2nd 3rd 4th + -------------------------------- + 00-7F + C2-DF 80-BF + E0 A0-BF 80-BF + E1-EC 80-BF 80-BF + ED 80-9F 80-BF + EE-EF 80-BF 80-BF + F0 90-BF 80-BF 80-BF + F1-F3 80-BF 80-BF 80-BF + F4 80-8F 80-BF 80-BF + + Please note that this function only checks whether the 2nd, 3rd and + 4th bytes fall into the valid ranges. + + PARAMETERS + codeUnit - pointer to the first byte of the byte sequence composing + the code unit to test. + length - the number of bytes in the code unit. Valid range is 1 to 4. + + RETURNS + TRUE if the given code unit is legal. + +*****************************************************************************/ +static CsrBool isLegalUtf8(const CsrUtf8String *codeUnit, CsrUint32 length) +{ + const CsrUtf8String *srcPtr = codeUnit + length; + CsrUint8 byte; + + switch (length) /* Everything falls through except case 1 */ + { + case 4: + { + byte = *--srcPtr; + if ((byte < 0x80) || (byte > 0xBF)) + { + return FALSE; + } + } + /* Fallthrough */ + case 3: + { + byte = *--srcPtr; + if ((byte < 0x80) || (byte > 0xBF)) + { + return FALSE; + } + } + /* Fallthrough */ + case 2: + { + byte = *--srcPtr; + if (byte > 0xBF) + { + return FALSE; + } + + switch (*codeUnit) /* No fallthrough */ + { + case 0xE0: + { + if (byte < 0xA0) + { + return FALSE; + } + break; + } + case 0xED: + { + if ((byte < 0x80) || (byte > 0x9F)) + { + return FALSE; + } + break; + } + case 0xF0: + { + if (byte < 0x90) + { + return FALSE; + } + break; + } + case 0xF4: + { + if ((byte < 0x80) || (byte > 0x8F)) + { + return FALSE; + } + break; + } + default: + { + if (byte < 0x80) + { + return FALSE; + } + break; + } + } + } + /* Fallthrough */ + case 1: + default: + /* The 1st byte and length are assumed correct */ + break; + } + + return TRUE; +} + +/******************************************************************************** +* +* Name: CsrUtf82Utf16String +* +* Description: The function decodes an UTF8 byte oriented string into a +* UTF-16string. +* +* Input: 0-terminated string of byte oriented UTF8 coded characters. +* +* Output: 0-terminated string of UTF-16 characters. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf82Utf16String(const CsrUtf8String *utf8String) +{ + CsrSize i, length = 0; + CsrSize sourceLength; + CsrUtf16String *dest = NULL; + CsrUtf16String *destStart = NULL; + CsrInt8 extraBytes2Read; + + if (!utf8String) + { + return NULL; + } + sourceLength = CsrStrLen((CsrCharString *) utf8String); + + for (i = 0; i < sourceLength; i++) + { + extraBytes2Read = trailingBytesForUtf8[utf8String[i]]; + + if (extraBytes2Read == -1) /* Illegal byte value, instead put a Unicode 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + length += 1; + } + else if (i + extraBytes2Read > sourceLength) /* The extra bytes does not exist, instead put a Unicode 'REPLACEMENT + CHARACTER' (U+FFFD), and the null terminated character */ + { + length += 2; + break; + } + else if (isLegalUtf8(&utf8String[i], extraBytes2Read + 1) == FALSE) /* It is not a legal utf-8 character, instead put a Unicode 'REPLACEMENT + CHARACTER' (U+FFFD) */ + { + length += 1; + } + else + { + if (utf8String[i] > 0xEF) /* Needs a high and a low surrogate */ + { + length += 2; + } + else + { + length += 1; + } + i += extraBytes2Read; + } + } + + /* Create space for the null terminated character */ + dest = (CsrUtf16String *) CsrPmemAlloc((1 + length) * sizeof(CsrUtf16String)); + destStart = dest; + + for (i = 0; i < sourceLength; i++) + { + extraBytes2Read = trailingBytesForUtf8[utf8String[i]]; + + if (extraBytes2Read == -1) /* Illegal byte value, instead put a Unicode 'REPLACEMENT CHARACTER' (U+FFFD) */ + { + *dest++ = UNI_REPLACEMENT_CHAR; + } + else if (i + extraBytes2Read > sourceLength) /* The extra bytes does not exist, instead put a Unicode 'REPLACEMENT + CHARACTER' (U+FFFD), and the null terminated character */ + { + *dest++ = UNI_REPLACEMENT_CHAR; + *dest++ = '\0'; + break; + } + else if (isLegalUtf8(&utf8String[i], extraBytes2Read + 1) == FALSE) /* It is not a legal utf-8 character, instead put a Unicode 'REPLACEMENT + CHARACTER' (U+FFFD) */ + { + *dest++ = UNI_REPLACEMENT_CHAR; + } + else /* It is legal, convert the character to an CsrUint32 */ + { + CsrUint32 ch = 0; + + switch (extraBytes2Read) /* Everything falls through */ + { + case 3: + { + ch += utf8String[i]; + ch <<= 6; + i++; + } + /* FALLTHROUGH */ + case 2: + { + ch += utf8String[i]; + ch <<= 6; + i++; + } + /* FALLTHROUGH */ + case 1: + { + ch += utf8String[i]; + ch <<= 6; + i++; + } + /* FALLTHROUGH */ + case 0: + { + ch += utf8String[i]; + } + /* FALLTHROUGH */ + default: + { + break; + } + } + + ch -= offsetsFromUtf8[extraBytes2Read]; + + if (ch <= 0xFFFF) /* Character can be encoded in one CsrUint16 */ + { + *dest++ = (CsrUint16) ch; + } + else /* The character needs two CsrUint16 */ + { + ch -= UNI_HALF_BASE; + *dest++ = (CsrUint16) ((ch >> UNI_HALF_SHIFT) | UNI_SUR_HIGH_START); + *dest++ = (CsrUint16) ((ch & 0x03FF) | UNI_SUR_LOW_START); + } + } + } + + destStart[length] = 0x00; + + return destStart; +} + +/******************************************************************************** +* +* Name: CsrUtf16StrCpy +* +* Description: The function copies the contents from one UTF-16 string +* to another UTF-16 string. +* +* Input: 0-terminated UTF-16 string. +* +* Output: 0-terminated UTF-16 string. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf16StrCpy(CsrUtf16String *target, const CsrUtf16String *source) +{ + if (source) /* if source is not NULL*/ + { + CsrMemCpy(target, source, (CsrUtf16StrLen(source) + 1) * sizeof(CsrUtf16String)); + return target; + } + else + { + return NULL; + } +} + +/******************************************************************************** +* +* Name: CsrUtf16StringDuplicate +* +* Description: The function allocates a new pointer and copies the input to +* the new pointer. +* +* Input: 0-terminated UTF-16 string. +* +* Output: Allocated variable0-terminated UTF-16 string. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf16StringDuplicate(const CsrUtf16String *source) +{ + CsrUtf16String *target = NULL; + CsrUint32 length; + + if (source) /* if source is not NULL*/ + { + length = (CsrUtf16StrLen(source) + 1) * sizeof(CsrUtf16String); + target = (CsrUtf16String *) CsrPmemAlloc(length); + CsrMemCpy(target, source, length); + } + return target; +} + +/******************************************************************************** +* +* Name: CsrUtf16StrICmp +* +* Description: The function compares two UTF-16 strings. +* +* Input: Two 0-terminated UTF-16 string. +* +* Output: 0: if the strings are identical. +* +*********************************************************************************/ +CsrUint16 CsrUtf16StrICmp(const CsrUtf16String *string1, const CsrUtf16String *string2) +{ + while (*string1 || *string2) + { + if (CAPITAL(*string1) != CAPITAL(*string2)) + { + return *string1 - *string2; + } + string1++; + string2++; + } + + return 0; +} + +/******************************************************************************** +* +* Name: CsrUtf16StrNICmp +* +* Description: The function compares upto count number of elements in the +* two UTF-16 string. +* +* Input: Two 0-terminated UTF-16 string and a maximum +* number of elements to check. +* +* Output: 0: if the strings are identical. +* +*********************************************************************************/ +CsrUint16 CsrUtf16StrNICmp(const CsrUtf16String *string1, const CsrUtf16String *string2, CsrUint32 count) +{ + while ((*string1 || *string2) && count--) + { + if (CAPITAL(*string1) != CAPITAL(*string2)) + { + return *string1 - *string2; + } + string1++; + string2++; + } + + return 0; +} + +/******************************************************************************** +* +* Name: CsrUtf16String2XML +* +* Description: The function converts an unicoded string (UTF-16) into an unicoded XML +* string where some special characters are encoded according to +* the XML spec. +* +* Input: A unicoded string (UTF-16) which is freed. +* +* Output: A new unicoded string (UTF-16) containing the converted output. +* +*********************************************************************************/ +CsrUtf16String *CsrUtf16String2XML(CsrUtf16String *str) +{ + CsrUtf16String *scanString; + CsrUtf16String *outputString = NULL; + CsrUtf16String *resultString = str; + CsrUint32 stringLength = 0; + CsrBool encodeChars = FALSE; + + scanString = str; + if (scanString) + { + while (*scanString) + { + if (*scanString == L'&') + { + stringLength += 5; + encodeChars = TRUE; + } + else if ((*scanString == L'<') || (*scanString == L'>')) + { + stringLength += 4; + encodeChars = TRUE; + } + else + { + stringLength++; + } + + scanString++; + } + + stringLength++; + + if (encodeChars) + { + resultString = outputString = CsrPmemAlloc(stringLength * sizeof(CsrUtf16String)); + + scanString = str; + + while (*scanString) + { + if (*scanString == L'&') + { + *outputString++ = '&'; + *outputString++ = 'a'; + *outputString++ = 'm'; + *outputString++ = 'p'; + *outputString++ = ';'; + } + else if (*scanString == L'<') + { + *outputString++ = '&'; + *outputString++ = 'l'; + *outputString++ = 't'; + *outputString++ = ';'; + } + else if (*scanString == L'>') + { + *outputString++ = '&'; + *outputString++ = 'g'; + *outputString++ = 't'; + *outputString++ = ';'; + } + else + { + *outputString++ = *scanString; + } + + scanString++; + } + + *outputString++ = 0; + + CsrPmemFree(str); + } + } + + return resultString; +} + +/******************************************************************************** +* +* Name: CsrXML2Utf16String +* +* Description: The function converts an unicoded XML string into an unicoded +* string (UTF-16) where some special XML characters are decoded according to +* the XML spec. +* +* Input: A unicoded XML string which is freed. +* +* Output: A new unicoded pointer containing the decoded output. +* +*********************************************************************************/ +CsrUtf16String *CsrXML2Utf16String(CsrUtf16String *str) +{ + CsrUtf16String *scanString; + CsrUtf16String *outputString = NULL; + CsrUtf16String *resultString = str; + CsrUint32 stringLength = 0; + CsrBool encodeChars = FALSE; + + scanString = str; + if (scanString) + { + while (*scanString) + { + if (*scanString == (CsrUtf16String) L'&') + { + scanString++; + + if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"AMP;", 4)) + { + scanString += 3; + encodeChars = TRUE; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"LT;", 3)) + { + scanString += 2; + encodeChars = TRUE; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"GT;", 3)) + { + scanString += 2; + encodeChars = TRUE; + } + if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"APOS;", 5)) + { + scanString += 4; + encodeChars = TRUE; + } + if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"QUOT;", 5)) + { + scanString += 4; + encodeChars = TRUE; + } + else + { + scanString--; + } + } + + stringLength++; + scanString++; + } + + stringLength++; + + if (encodeChars) + { + resultString = outputString = CsrPmemAlloc(stringLength * sizeof(CsrUtf16String)); + + scanString = str; + + while (*scanString) + { + if (*scanString == L'&') + { + scanString++; + + if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"AMP;", 4)) + { + *outputString++ = L'&'; + scanString += 3; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"LT;", 3)) + { + *outputString++ = L'<'; + scanString += 2; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"GT;", 3)) + { + *outputString++ = L'>'; + scanString += 2; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"APOS;", 5)) + { + *outputString++ = L'\''; + scanString += 4; + } + else if (!CsrUtf16StrNICmp(scanString, (CsrUtf16String *) L"QUOT;", 5)) + { + *outputString++ = L'\"'; + scanString += 4; + } + else + { + *outputString++ = L'&'; + scanString--; + } + } + else + { + *outputString++ = *scanString; + } + + scanString++; + } + + *outputString++ = 0; + + CsrPmemFree(str); + } + } + + return resultString; +} + +CsrInt32 CsrUtf8StrCmp(const CsrUtf8String *string1, const CsrUtf8String *string2) +{ + return CsrStrCmp((const CsrCharString *) string1, (const CsrCharString *) string2); +} + +CsrInt32 CsrUtf8StrNCmp(const CsrUtf8String *string1, const CsrUtf8String *string2, CsrSize count) +{ + return CsrStrNCmp((const CsrCharString *) string1, (const CsrCharString *) string2, count); +} + +CsrUint32 CsrUtf8StringLengthInBytes(const CsrUtf8String *string) +{ + CsrSize length = 0; + if (string) + { + length = CsrStrLen((const CsrCharString *) string); + } + return (CsrUint32) length; +} + +CsrUtf8String *CsrUtf8StrCpy(CsrUtf8String *target, const CsrUtf8String *source) +{ + return (CsrUtf8String *) CsrStrCpy((CsrCharString *) target, (const CsrCharString *) source); +} + +CsrUtf8String *CsrUtf8StrTruncate(CsrUtf8String *target, CsrSize count) +{ + CsrSize lastByte = count - 1; + + target[count] = '\0'; + + if (count && (target[lastByte] & 0x80)) + { + /* the last byte contains non-ascii char */ + if (target[lastByte] & 0x40) + { + /* multi-byte char starting just before truncation */ + target[lastByte] = '\0'; + } + else if ((target[lastByte - 1] & 0xE0) == 0xE0) + { + /* 3-byte char starting 2 bytes before truncation */ + target[lastByte - 1] = '\0'; + } + else if ((target[lastByte - 2] & 0xF0) == 0xF0) + { + /* 4-byte char starting 3 bytes before truncation */ + target[lastByte - 2] = '\0'; + } + } + + return target; +} + +CsrUtf8String *CsrUtf8StrNCpy(CsrUtf8String *target, const CsrUtf8String *source, CsrSize count) +{ + return (CsrUtf8String *) CsrStrNCpy((CsrCharString *) target, (const CsrCharString *) source, count); +} + +CsrUtf8String *CsrUtf8StrNCpyZero(CsrUtf8String *target, const CsrUtf8String *source, CsrSize count) +{ + CsrStrNCpy((CsrCharString *) target, (const CsrCharString *) source, count); + if (target[count - 1] != '\0') + { + CsrUtf8StrTruncate(target, count - 1); + } + return target; +} + +CsrUtf8String *CsrUtf8StrDup(const CsrUtf8String *source) +{ + return (CsrUtf8String *) CsrStrDup((const CsrCharString *) source); +} + +CsrUtf8String *CsrUtf8StringConcatenateTexts(const CsrUtf8String *inputText1, const CsrUtf8String *inputText2, const CsrUtf8String *inputText3, const CsrUtf8String *inputText4) +{ + CsrUtf8String *outputText; + CsrUint32 textLen, textLen1, textLen2, textLen3, textLen4; + + textLen1 = CsrUtf8StringLengthInBytes(inputText1); + textLen2 = CsrUtf8StringLengthInBytes(inputText2); + textLen3 = CsrUtf8StringLengthInBytes(inputText3); + textLen4 = CsrUtf8StringLengthInBytes(inputText4); + + textLen = textLen1 + textLen2 + textLen3 + textLen4; + + if (textLen == 0) /*stop here is all lengths are 0*/ + { + return NULL; + } + + outputText = (CsrUtf8String *) CsrPmemAlloc((textLen + 1) * sizeof(CsrUtf8String)); /* add space for 0-termination*/ + + + if (inputText1 != NULL) + { + CsrUtf8StrNCpy(outputText, inputText1, textLen1); + } + + if (inputText2 != NULL) + { + CsrUtf8StrNCpy(&(outputText[textLen1]), inputText2, textLen2); + } + + if (inputText3 != NULL) + { + CsrUtf8StrNCpy(&(outputText[textLen1 + textLen2]), inputText3, textLen3); + } + + if (inputText4 != NULL) + { + CsrUtf8StrNCpy(&(outputText[textLen1 + textLen2 + textLen3]), inputText4, textLen4); + } + + outputText[textLen] = '\0'; + + return outputText; +} diff --git a/drivers/staging/csr/csr_util.c b/drivers/staging/csr/csr_util.c new file mode 100644 index 000000000000..0ae11531e26d --- /dev/null +++ b/drivers/staging/csr/csr_util.c @@ -0,0 +1,435 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include +#include + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_util.h" + +/*------------------------------------------------------------------*/ +/* Bits */ +/*------------------------------------------------------------------*/ + +/* Time proportional with the number of 1's */ +CsrUint8 CsrBitCountSparse(CsrUint32 n) +{ + CsrUint8 count = 0; + + while (n) + { + count++; + n &= (n - 1); + } + + return count; +} + +/* Time proportional with the number of 0's */ +CsrUint8 CsrBitCountDense(CsrUint32 n) +{ + CsrUint8 count = 8 * sizeof(CsrUint32); + + n ^= (CsrUint32) (-1); + + while (n) + { + count--; + n &= (n - 1); + } + + return count; +} + +/*------------------------------------------------------------------*/ +/* Base conversion */ +/*------------------------------------------------------------------*/ +CsrBool CsrHexStrToUint8(const CsrCharString *string, CsrUint8 *returnValue) +{ + CsrUint16 currentIndex = 0; + *returnValue = 0; + if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) + { + string += 2; + } + if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + *returnValue = (CsrUint8) (*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10)); + currentIndex++; + if (currentIndex >= 2) + { + break; + } + } + return TRUE; + } + return FALSE; +} + +CsrBool CsrHexStrToUint16(const CsrCharString *string, CsrUint16 *returnValue) +{ + CsrUint16 currentIndex = 0; + *returnValue = 0; + if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) + { + string += 2; + } + if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + *returnValue = (CsrUint16) (*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10)); + currentIndex++; + if (currentIndex >= 4) + { + break; + } + } + return TRUE; + } + return FALSE; +} + +CsrBool CsrHexStrToUint32(const CsrCharString *string, CsrUint32 *returnValue) +{ + CsrUint16 currentIndex = 0; + *returnValue = 0; + if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) + { + string += 2; + } + if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) + { + *returnValue = *returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10); + currentIndex++; + if (currentIndex >= 8) + { + break; + } + } + return TRUE; + } + return FALSE; +} + +CsrUint32 CsrPow(CsrUint32 base, CsrUint32 exponent) +{ + if (exponent == 0) + { + return 1; + } + else + { + CsrUint32 i, t = base; + + for (i = 1; i < exponent; i++) + { + t = t * base; + } + return t; + } +} + +/* Convert signed 32 bit (or less) integer to string */ +#define I2B10_MAX 12 +void CsrIntToBase10(CsrInt32 number, CsrCharString *str) +{ + CsrInt32 digit; + CsrUint8 index; + CsrCharString res[I2B10_MAX]; + CsrBool foundDigit = FALSE; + + for (digit = 0; digit < I2B10_MAX; digit++) + { + res[digit] = '\0'; + } + + /* Catch sign - and deal with positive numbers only afterwards */ + index = 0; + if (number < 0) + { + res[index++] = '-'; + number = -1 * number; + } + + digit = 1000000000; + if (number > 0) + { + while ((index < I2B10_MAX - 1) && (digit > 0)) + { + /* If the foundDigit flag is TRUE, this routine should be proceeded. + Otherwise the number which has '0' digit cannot be converted correctly */ + if (((number / digit) > 0) || foundDigit) + { + foundDigit = TRUE; /* set foundDigit flag to TRUE*/ + res[index++] = (char) ('0' + (number / digit)); + number = number % digit; + } + + digit = digit / 10; + } + } + else + { + res[index] = (char) '0'; + } + + CsrStrCpy(str, res); +} + +void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str) +{ + CsrUint16 index; + CsrUint16 currentValue; + + for (index = 0; index < 4; index++) + { + currentValue = (CsrUint16) (number & 0x000F); + number >>= 4; + str[3 - index] = (char) (currentValue > 9 ? currentValue + 55 : currentValue + '0'); + } + str[4] = '\0'; +} + +void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str) +{ + CsrUint16 index; + CsrUint32 currentValue; + + for (index = 0; index < 8; index++) + { + currentValue = (CsrUint32) (number & 0x0000000F); + number >>= 4; + str[7 - index] = (char) (currentValue > 9 ? currentValue + 55 : currentValue + '0'); + } + str[8] = '\0'; +} + +/*------------------------------------------------------------------*/ +/* String */ +/*------------------------------------------------------------------*/ +void *CsrMemCpy(void *dest, const void *src, CsrSize count) +{ + return memcpy(dest, src, count); +} +EXPORT_SYMBOL_GPL(CsrMemCpy); + +void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count) +{ + return memset(dest, c, count); +} +EXPORT_SYMBOL_GPL(CsrMemSet); + +void *CsrMemMove(void *dest, const void *src, CsrSize count) +{ + return memmove(dest, src, count); +} +EXPORT_SYMBOL_GPL(CsrMemMove); + +CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count) +{ + return memcmp(buf1, buf2, count); +} +EXPORT_SYMBOL_GPL(CsrMemCmp); + +void *CsrMemDup(const void *buf1, CsrSize count) +{ + void *buf2 = NULL; + + if (buf1) + { + buf2 = CsrPmemAlloc(count); + CsrMemCpy(buf2, buf1, count); + } + + return buf2; +} + +CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src) +{ + return strcpy(dest, src); +} + +CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count) +{ + return strncpy(dest, src, count); +} + +CsrCharString *CsrStrCat(CsrCharString *dest, const CsrCharString *src) +{ + return strcat(dest, src); +} + +CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count) +{ + return strncat(dest, src, count); +} + +CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2) +{ + return strstr(string1, string2); +} + +CsrSize CsrStrLen(const CsrCharString *string) +{ + return strlen(string); +} +EXPORT_SYMBOL_GPL(CsrStrLen); + +CsrInt32 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2) +{ + return strcmp(string1, string2); +} + +CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count) +{ + return strncmp(string1, string2, count); +} + +CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c) +{ + return strchr(string, c); +} + +CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args) +{ + return vsnprintf(string, count, format, args); +} +EXPORT_SYMBOL_GPL(CsrVsnprintf); + +CsrCharString *CsrStrNCpyZero(CsrCharString *dest, + const CsrCharString *src, + CsrSize count) +{ + CsrStrNCpy(dest, src, count - 1); + dest[count - 1] = '\0'; + return dest; +} + +/* Convert string with base 10 to integer */ +CsrUint32 CsrStrToInt(const CsrCharString *str) +{ + CsrInt16 i; + CsrUint32 res; + CsrUint32 digit; + + res = 0; + digit = 1; + + /* Start from the string end */ + for (i = (CsrUint16) (CsrStrLen(str) - 1); i >= 0; i--) + { + /* Only convert numbers */ + if ((str[i] >= '0') && (str[i] <= '9')) + { + res += digit * (str[i] - '0'); + digit = digit * 10; + } + } + + return res; +} + +CsrCharString *CsrStrDup(const CsrCharString *string) +{ + CsrCharString *copy; + CsrUint32 len; + + copy = NULL; + if (string != NULL) + { + len = CsrStrLen(string) + 1; + copy = CsrPmemAlloc(len); + CsrMemCpy(copy, string, len); + } + return copy; +} + +int CsrStrNICmp(const CsrCharString *string1, + const CsrCharString *string2, + CsrSize count) +{ + CsrUint32 index; + int returnValue = 0; + + for (index = 0; index < count; index++) + { + if (CSR_TOUPPER(string1[index]) != CSR_TOUPPER(string2[index])) + { + if (CSR_TOUPPER(string1[index]) > CSR_TOUPPER(string2[index])) + { + returnValue = 1; + } + else + { + returnValue = -1; + } + break; + } + if (string1[index] == '\0') + { + break; + } + } + return returnValue; +} + +const CsrCharString *CsrGetBaseName(const CsrCharString *file) +{ + const CsrCharString *pch; + static const CsrCharString dotDir[] = "."; + + if (!file) + { + return NULL; + } + + if (file[0] == '\0') + { + return dotDir; + } + + pch = file + CsrStrLen(file) - 1; + + while (*pch != '\\' && *pch != '/' && *pch != ':') + { + if (pch == file) + { + return pch; + } + --pch; + } + + return ++pch; +} + +/*------------------------------------------------------------------*/ +/* Misc */ +/*------------------------------------------------------------------*/ +CsrBool CsrIsSpace(CsrUint8 c) +{ + switch (c) + { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': + return TRUE; + default: + return FALSE; + } +} diff --git a/drivers/staging/csr/csr_util.h b/drivers/staging/csr/csr_util.h new file mode 100644 index 000000000000..a19baddc0213 --- /dev/null +++ b/drivers/staging/csr/csr_util.h @@ -0,0 +1,75 @@ +#ifndef CSR_UTIL_H__ +#define CSR_UTIL_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_types.h" +#include "csr_macro.h" + +/*------------------------------------------------------------------*/ +/* Bits - intended to operate on CsrUint32 values */ +/*------------------------------------------------------------------*/ +CsrUint8 CsrBitCountSparse(CsrUint32 n); +CsrUint8 CsrBitCountDense(CsrUint32 n); + +/*------------------------------------------------------------------*/ +/* Base conversion */ +/*------------------------------------------------------------------*/ +CsrBool CsrHexStrToUint8(const CsrCharString *string, CsrUint8 *returnValue); +CsrBool CsrHexStrToUint16(const CsrCharString *string, CsrUint16 *returnValue); +CsrBool CsrHexStrToUint32(const CsrCharString *string, CsrUint32 *returnValue); +CsrUint32 CsrPow(CsrUint32 base, CsrUint32 exponent); +void CsrIntToBase10(CsrInt32 number, CsrCharString *str); +void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str); +void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str); + +/*------------------------------------------------------------------*/ +/* String */ +/*------------------------------------------------------------------*/ +void *CsrMemCpy(void *dest, const void *src, CsrSize count); +void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count); +void *CsrMemMove(void *dest, const void *src, CsrSize count); +CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count); +void *CsrMemDup(const void *buf1, CsrSize count); +CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src); +CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count); +int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count); +CsrCharString *CsrStrCat(CsrCharString *dest, const CsrCharString *src); +CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count); +CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2); +CsrSize CsrStrLen(const CsrCharString *string); +CsrInt32 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2); +CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count); +CsrCharString *CsrStrDup(const CsrCharString *string); +CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c); +CsrUint32 CsrStrToInt(const CsrCharString *string); +CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args); +CsrCharString *CsrStrNCpyZero(CsrCharString *dest, const CsrCharString *src, CsrSize count); + +/*------------------------------------------------------------------*/ +/* Filename */ +/*------------------------------------------------------------------*/ +const CsrCharString *CsrGetBaseName(const CsrCharString *file); + +/*------------------------------------------------------------------*/ +/* Misc */ +/*------------------------------------------------------------------*/ +CsrBool CsrIsSpace(CsrUint8 c); +#define CsrOffsetOf(st, m) ((CsrSize) & ((st *) 0)->m) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_wifi_common.h b/drivers/staging/csr/csr_wifi_common.h new file mode 100644 index 000000000000..1cdde5c7bd8d --- /dev/null +++ b/drivers/staging/csr/csr_wifi_common.h @@ -0,0 +1,109 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_COMMON_H__ +#define CSR_WIFI_COMMON_H__ + +#include "csr_types.h" +#include "csr_result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MAC address */ +typedef struct +{ + CsrUint8 a[6]; +} CsrWifiMacAddress; + +/* IPv4 address */ +typedef struct +{ + CsrUint8 a[4]; +} CsrWifiIp4Address; + +/* IPv6 address */ +typedef struct +{ + CsrUint8 a[16]; +} CsrWifiIp6Address; + +typedef struct +{ + CsrUint8 ssid[32]; + CsrUint8 length; +} CsrWifiSsid; + +/******************************************************************************* + + DESCRIPTION + Result values used on the Wifi Interfaces + + VALUES + CSR_RESULT_SUCCESS + - The request/procedure succeeded + CSR_RESULT_FAILURE + - The request/procedure did not succeed because of an error + CSR_WIFI_RESULT_NOT_FOUND + - The request did not succeed because some resource was not + found. + CSR_WIFI_RESULT_TIMED_OUT + - The request/procedure did not succeed because of a time out + CSR_WIFI_RESULT_CANCELLED + - The request was canceled due to another conflicting + request that was issued before this one was completed + CSR_WIFI_RESULT_INVALID_PARAMETER + - The request/procedure did not succeed because it had an + invalid parameter + CSR_WIFI_RESULT_NO_ROOM + - The request did not succeed due to a lack of resources, + e.g. out of memory problem. + CSR_WIFI_RESULT_UNSUPPORTED + - The request/procedure did not succeed because the feature + is not supported yet + CSR_WIFI_RESULT_UNAVAILABLE + - The request cannot be processed at this time + CSR_WIFI_RESULT_WIFI_OFF + - The requested action is not available because Wi-Fi is + currently off + CSR_WIFI_RESULT_SECURITY_ERROR + - The request/procedure did not succeed because of a security + error + CSR_WIFI_RESULT_MIB_SET_FAILURE + - MIB Set Failure: either the MIB OID to be written to does + not exist or the MIB Value is invalid. + CSR_WIFI_RESULT_INVALID_INTERFACE_TAG + - The supplied Interface Tag is not valid. + CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT + - The new NOA configuration conflicts with the existing NOA configuration + hence not accepted" +*******************************************************************************/ +#define CSR_WIFI_RESULT_NOT_FOUND ((CsrResult) 0x0001) +#define CSR_WIFI_RESULT_TIMED_OUT ((CsrResult) 0x0002) +#define CSR_WIFI_RESULT_CANCELLED ((CsrResult) 0x0003) +#define CSR_WIFI_RESULT_INVALID_PARAMETER ((CsrResult) 0x0004) +#define CSR_WIFI_RESULT_NO_ROOM ((CsrResult) 0x0005) +#define CSR_WIFI_RESULT_UNSUPPORTED ((CsrResult) 0x0006) +#define CSR_WIFI_RESULT_UNAVAILABLE ((CsrResult) 0x0007) +#define CSR_WIFI_RESULT_WIFI_OFF ((CsrResult) 0x0008) +#define CSR_WIFI_RESULT_SECURITY_ERROR ((CsrResult) 0x0009) +#define CSR_WIFI_RESULT_MIB_SET_FAILURE ((CsrResult) 0x000A) +#define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG ((CsrResult) 0x000B) +#define CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT ((CsrResult) 0x000C) + +#define CSR_WIFI_VERSION "5.0.3.0" + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/drivers/staging/csr/csr_wifi_fsm.h b/drivers/staging/csr/csr_wifi_fsm.h new file mode 100644 index 000000000000..cfdf082349ee --- /dev/null +++ b/drivers/staging/csr/csr_wifi_fsm.h @@ -0,0 +1,250 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_FSM_H +#define CSR_WIFI_FSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_prim_defs.h" +#include "csr_log_text.h" +#include "csr_wifi_fsm_event.h" + +/* including this file for CsrWifiInterfaceMode*/ +#include "csr_wifi_common.h" + +#define CSR_WIFI_FSM_ENV (0xFFFF) + +/** + * @brief + * Toplevel FSM context data + * + * @par Description + * Holds ALL FSM static and dynamic data for a FSM + */ +typedef struct CsrWifiFsmContext CsrWifiFsmContext; + +/** + * @brief + * FSM External Wakeup CallbackFunction Pointer + * + * @par Description + * Defines the external wakeup function for the FSM + * to call when an external event is injected into the systen + * + * @param[in] context : External context + * + * @return + * void + */ +typedef void (*CsrWifiFsmExternalWakupCallbackPtr)(void *context); + +/** + * @brief + * Initialises a top level FSM context + * + * @par Description + * Initialises the FSM Context to an initial state and allocates + * space for "maxProcesses" number of instances + * + * @param[in] osaContext : OSA context + * @param[in] applicationContext : Internal fsm application context + * @param[in] externalContext : External context + * @param[in] maxProcesses : Max processes to allocate room for + * + * @return + * CsrWifiFsmContext* fsm context + */ +extern CsrWifiFsmContext* CsrWifiFsmInit(void *applicationContext, void *externalContext, CsrUint16 maxProcesses, CsrLogTextTaskId loggingTaskId); + +/** + * @brief + * Resets the FSM's back to first conditions + * + * @par Description + * This function is used to free any dynamic resources allocated for the + * given context by CsrWifiFsmInit(). + * The FSM's reset function is called to cleanup any fsm specific memory + * The reset funtion does NOT need to free the fsm data pointer as + * CsrWifiFsmShutdown() will do it. + * the FSM's init function is call again to reinitialise the FSM context. + * CsrWifiFsmReset() should NEVER be called when CsrWifiFsmExecute() is running. + * + * @param[in] context : FSM context + * + * @return + * void + */ +extern void CsrWifiFsmReset(CsrWifiFsmContext *context); + +/** + * @brief + * Frees resources allocated by CsrWifiFsmInit + * + * @par Description + * This function is used to free any dynamic resources allocated for the + * given context by CsrWifiFsmInit(), prior to complete termination of + * the program. + * The FSM's reset function is called to cleanup any fsm specific memory. + * The reset funtion does NOT need to free the fsm data pointer as + * CsrWifiFsmShutdown() will do it. + * CsrWifiFsmShutdown() should NEVER be called when CsrWifiFsmExecute() is running. + * + * @param[in] context : FSM context + * + * @return + * void + */ +extern void CsrWifiFsmShutdown(CsrWifiFsmContext *context); + +/** + * @brief + * Executes the fsm context + * + * @par Description + * Executes the FSM context and runs until ALL events in the context are processed. + * When no more events are left to process then CsrWifiFsmExecute() returns to a time + * specifying when to next call the CsrWifiFsmExecute() + * Scheduling, threading, blocking and external event notification are outside + * the scope of the FSM and CsrWifiFsmExecute(). + * + * @param[in] context : FSM context + * + * @return + * CsrUint32 Time in ms until next timeout or 0xFFFFFFFF for no timer set + */ +extern CsrUint32 CsrWifiFsmExecute(CsrWifiFsmContext *context); + +/** + * @brief + * Adds an event to the FSM context's external event queue for processing + * + * @par Description + * Adds an event to the contexts external queue + * This is thread safe and adds an event to the fsm's external event queue. + * + * @param[in] context : FSM context + * @param[in] event : event to add to the event queue + * @param[in] source : source of the event (this can be a synergy task queue or an fsm instance id) + * @param[in] destination : destination of the event (This can be a fsm instance id or CSR_WIFI_FSM_ENV) + * @param[in] id : event id + * + * @return + * void + */ +extern void CsrWifiFsmSendEventExternal(CsrWifiFsmContext *context, CsrWifiFsmEvent *event, CsrUint16 source, CsrUint16 destination, CsrPrim primtype, CsrUint16 id); + +/** + * @brief + * Adds an Alien event to the FSM context's external event queue for processing + * + * @par Description + * Adds an event to the contexts external queue + * This is thread safe and adds an event to the fsm's external event queue. + * + * @param[in] context : FSM context + * @param[in] event : event to add to the event queue + * @param[in] source : source of the event (this can be a synergy task queue or an fsm instance id) + * @param[in] destination : destination of the event (This can be a fsm instance id or CSR_WIFI_FSM_ENV) + * @param[in] id : event id + */ +#define CsrWifiFsmSendAlienEventExternal(_context, _alienEvent, _source, _destination, _primtype, _id) \ + { \ + CsrWifiFsmAlienEvent *_evt = (CsrWifiFsmAlienEvent *)CsrPmemAlloc(sizeof(CsrWifiFsmAlienEvent)); \ + _evt->alienEvent = _alienEvent; \ + CsrWifiFsmSendEventExternal(_context, (CsrWifiFsmEvent *)_evt, _source, _destination, _primtype, _id); \ + } + + +/** + * @brief + * Current time of day in ms + * + * @param[in] context : FSM context + * + * @return + * CsrUint32 32 bit ms tick + */ +extern CsrUint32 CsrWifiFsmGetTimeOfDayMs(CsrWifiFsmContext *context); + +/** + * @brief + * Gets the time until the next FSM timer expiry + * + * @par Description + * Returns the next timeout time or 0 if no timers are set. + * + * @param[in] context : FSM context + * + * @return + * CsrUint32 Time in ms until next timeout or 0xFFFFFFFF for no timer set + */ +extern CsrUint32 CsrWifiFsmGetNextTimeout(CsrWifiFsmContext *context); + +/** + * @brief + * Fast forwards the fsm timers by ms Milliseconds + * + * @param[in] context : FSM context + * @param[in] ms : Milliseconds to fast forward by + * + * @return + * void + */ +extern void CsrWifiFsmFastForward(CsrWifiFsmContext *context, CsrUint16 ms); + +/** + * @brief + * shift the current time of day by ms amount + * + * @par Description + * usefull to speed up tests where time needs to pass + * + * @param[in] context : FSM context + * @param[in] ms : ms to adjust time by + * + * @return + * void + */ +extern void CsrWifiFsmTestAdvanceTime(CsrWifiFsmContext *context, CsrUint32 ms); + +/** + * @brief + * Check if the fsm has events to process + * + * @param[in] context : FSM context + * + * @return + * CsrBool returns TRUE if there are events for the FSM to process + */ +extern CsrBool CsrWifiFsmHasEvents(CsrWifiFsmContext *context); + +/** + * @brief + * function that installs the contexts wakeup function + * + * @param[in] context : FSM context + * @param[in] callback : Callback function pointer + * + * @return + * void + */ +extern void CsrWifiFsmInstallWakeupCallback(CsrWifiFsmContext *context, CsrWifiFsmExternalWakupCallbackPtr callback); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_FSM_H */ + diff --git a/drivers/staging/csr/csr_wifi_fsm_event.h b/drivers/staging/csr/csr_wifi_fsm_event.h new file mode 100644 index 000000000000..ef07d8a5cfb2 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_fsm_event.h @@ -0,0 +1,51 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_FSM_EVENT_H +#define CSR_WIFI_FSM_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" + +/** + * @brief + * FSM event header. + * + * @par Description + * All events MUST have this struct as the FIRST member. + * The next member is used internally for linked lists + */ +typedef struct CsrWifiFsmEvent +{ + CsrPrim type; + CsrUint16 primtype; + CsrSchedQid destination; + CsrSchedQid source; + + /* Private pointer to allow an optimal Event list */ + /* NOTE: Ignore this pointer. + * Do not waste code initializing OR freeing it. + * The pointer is used internally in the CsrWifiFsm code + * to avoid a second malloc when queuing events. + */ + struct CsrWifiFsmEvent *next; +} CsrWifiFsmEvent; + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_FSM_EVENT_H */ + diff --git a/drivers/staging/csr/csr_wifi_fsm_types.h b/drivers/staging/csr/csr_wifi_fsm_types.h new file mode 100644 index 000000000000..7c611e342938 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_fsm_types.h @@ -0,0 +1,441 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_FSM_TYPES_H +#define CSR_WIFI_FSM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_types.h" +#include "csr_util.h" +#include "csr_pmem.h" +#include "csr_panic.h" +#include "csr_sched.h" + +#ifdef CSR_WIFI_FSM_MUTEX_ENABLE +#include "csr_framework_ext.h" +#endif + +#include "csr_wifi_fsm.h" + +#define CSR_WIFI_FSM_MAX_TRANSITION_HISTORY 10 + +/** + * @brief + * FSM event list header. + * + * @par Description + * Singly linked list of events. + */ +typedef struct CsrWifiFsmEventList +{ + CsrWifiFsmEvent *first; + CsrWifiFsmEvent *last; +} CsrWifiFsmEventList; + + +/** + * @brief + * FSM timer id. + * + * @par Description + * Composite Id made up of the type, dest and a unique id so + * CsrWifiFsmRemoveTimer knows where to look when removing the timer + */ +typedef struct CsrWifiFsmTimerId +{ + CsrPrim type; + CsrUint16 primtype; + CsrSchedQid destination; + CsrUint16 uniqueid; +} CsrWifiFsmTimerId; + +/** + * @brief + * FSM timer header. + * + * @par Description + * All timer MUST have this struct as the FIRST member. + * The first members of the structure MUST remain compatable + * with the CsrWifiFsmEvent so that timers are just specialised events + */ +typedef struct CsrWifiFsmTimer +{ + CsrPrim type; + CsrUint16 primtype; + CsrSchedQid destination; + CsrSchedQid source; + + /* Private pointer to allow an optimal Event list */ + struct CsrWifiFsmTimer *next; + + CsrWifiFsmTimerId timerid; + CsrUint32 timeoutTimeMs; +} CsrWifiFsmTimer; + + +/** + * @brief + * Fsm Alien Event + * + * @par Description + * Allows the wrapping of alien events that do not use CsrWifiFsmEvent + * as the first member of the Event struct + */ +typedef struct +{ + CsrWifiFsmEvent event; + void *alienEvent; +} CsrWifiFsmAlienEvent; + + +/** + * @brief + * FSM timer list header. + * + * @par Description + * Singly linked list of timers. + */ +typedef struct CsrWifiFsmTimerList +{ + CsrWifiFsmTimer *first; + CsrWifiFsmTimer *last; + CsrUint16 nexttimerid; +} CsrWifiFsmTimerList; + +/** + * @brief + * Process Entry Function Pointer + * + * @par Description + * Defines the entry function for a processes. + * Called at process initialisation. + * + * @param[in] context : FSM context + * + * @return + * void + */ +typedef void (*CsrWifiFsmProcEntryFnPtr)(CsrWifiFsmContext *context); + +/** + * @brief + * Process Transition Function Pointer + * + * @par Description + * Defines a transition function for a processes. + * Called when an event causes a transition on a process + * + * @param[in] CsrWifiFsmContext* : FSM context + * @param[in] void* : FSM data (can be NULL) + * @param[in] const CsrWifiFsmEvent* : event to process + * + * @return + * void + */ +typedef void (*CsrWifiFsmTransitionFnPtr)(CsrWifiFsmContext *context, void *fsmData, const CsrWifiFsmEvent *event); + +/** + * @brief + * Process reset/shutdown Function Pointer + * + * @par Description + * Defines the reset/shutdown function for a processes. + * Called to reset or shutdown an fsm. + * + * @param[in] context : FSM context + * + * @return + * void + */ +typedef void (*CsrWifiFsmProcResetFnPtr)(CsrWifiFsmContext *context); + +/** + * @brief + * FSM Default Destination CallbackFunction Pointer + * + * @par Description + * Defines the default destination function for the FSM + * to call when an event does not have a valid destination. + * This + * + * @param[in] context : External context + * + * @return + * CsrUint16 a valid destination OR CSR_WIFI_FSM_ENV + */ +typedef CsrUint16 (*CsrWifiFsmDestLookupCallbackPtr)(void *context, const CsrWifiFsmEvent *event); + + +#ifdef CSR_WIFI_FSM_DUMP_ENABLE +/** + * @brief + * Trace Dump Function Pointer + * + * @par Description + * Called when we want to trace the FSM + * + * @param[in] context : FSM context + * @param[in] id : fsm id + * + * @return + * void + */ +typedef void (*CsrWifiFsmDumpFnPtr)(CsrWifiFsmContext *context, void *fsmData); +#endif + +/** + * @brief + * Event ID to transition function entry + * + * @par Description + * Event ID to Transition Entry in a state table. + */ +typedef struct +{ + CsrUint32 eventid; + CsrWifiFsmTransitionFnPtr transition; +#ifdef CSR_LOG_ENABLE + const CsrCharString *transitionName; +#endif +} CsrWifiFsmEventEntry; + +/** + * @brief + * Single State's Transition Table + * + * @par Description + * Stores Data for a single State's event to + * transition functions mapping + */ +typedef struct +{ + const CsrUint8 numEntries; + const CsrBool saveAll; + const CsrWifiFsmEventEntry *eventEntryArray; /* array of transition function pointers for state */ +#ifdef CSR_LOG_ENABLE + CsrUint16 stateNumber; + const CsrCharString *stateName; +#endif +} CsrWifiFsmTableEntry; + +/** + * @brief + * Process State Transtion table + * + * @par Description + * Stores Data for a processes State to transition table + */ +typedef struct +{ + CsrUint16 numStates; /* number of states */ + const CsrWifiFsmTableEntry *aStateEventMatrix; /* state event matrix */ +} CsrWifiFsmTransitionFunctionTable; + +/** + * @brief + * Const Process definition + * + * @par Description + * Constant process specification. + * This is ALL the non dynamic data that defines + * a process. + */ +typedef struct +{ + const CsrCharString *processName; + const CsrUint32 processId; + const CsrWifiFsmTransitionFunctionTable transitionTable; + const CsrWifiFsmTableEntry unhandledTransitions; + const CsrWifiFsmTableEntry ignoreFunctions; + const CsrWifiFsmProcEntryFnPtr entryFn; + const CsrWifiFsmProcResetFnPtr resetFn; +#ifdef CSR_WIFI_FSM_DUMP_ENABLE + const CsrWifiFsmDumpFnPtr dumpFn; /* Called to dump fsm specific trace if not NULL */ +#endif +} CsrWifiFsmProcessStateMachine; + +#ifdef CSR_WIFI_FSM_DUMP_ENABLE +/** + * @brief + * Storage for state transition info + */ +typedef struct +{ + CsrUint16 transitionNumber; + CsrWifiFsmEvent event; + CsrUint16 fromState; + CsrUint16 toState; + CsrWifiFsmTransitionFnPtr transitionFn; + CsrUint16 transitionCount; /* number consecutive of times this transition was seen */ +#ifdef CSR_LOG_ENABLE + const CsrCharString *transitionName; +#endif +} CsrWifiFsmTransitionRecord; + +/** + * @brief + * Storage for the last state X transitions + */ +typedef struct +{ + CsrUint16 numTransitions; + CsrWifiFsmTransitionRecord records[CSR_WIFI_FSM_MAX_TRANSITION_HISTORY]; +} CsrWifiFsmTransitionRecords; +#endif + +/** + * @brief + * Dynamic Process data + * + * @par Description + * Dynamic process data that is used to keep track of the + * state and data for a process instance + */ +typedef struct +{ + const CsrWifiFsmProcessStateMachine *fsmInfo; /* state machine info that is constant regardless of context */ + CsrUint16 instanceId; /* Runtime process id */ + CsrUint16 state; /* Current state */ + void *params; /* Instance user data */ + CsrWifiFsmEventList savedEventQueue; /* The saved event queue */ + struct CsrWifiFsmInstanceEntry *subFsm; /* Sub Fsm instance data */ + struct CsrWifiFsmInstanceEntry *subFsmCaller; /* The Fsm instance that created the SubFsm and should be used for callbacks*/ +#ifdef CSR_WIFI_FSM_DUMP_ENABLE + CsrWifiFsmTransitionRecords transitionRecords; /* Last X transitions in the FSM */ +#endif +} CsrWifiFsmInstanceEntry; + +/** + * @brief + * OnCreate Callback Function Pointer + * + * @par Description + * Called when an fsm is created. + * + * @param[in] extContext : External context + * @param[in] instance : FSM instance + * + * @return + * void + */ +typedef void (*CsrWifiFsmOnCreateFnPtr)(void *extContext, const CsrWifiFsmInstanceEntry *instance); + +/** + * @brief + * OnTransition Callback Function Pointer + * + * @par Description + * Called when an event is processed by a fsm + * + * @param[in] extContext : External context + * @param[in] eventEntryArray : Entry data + * @param[in] event : Event + * + * @return + * void + */ +typedef void (*CsrWifiFsmOnTransitionFnPtr)(void *extContext, const CsrWifiFsmEventEntry *eventEntryArray, const CsrWifiFsmEvent *event); + +/** + * @brief + * OnStateChange Callback Function Pointer + * + * @par Description + * Called when CsrWifiFsmNextState is called + * + * @param[in] extContext : External context + * + * @return + * void + */ +typedef void (*CsrWifiFsmOnStateChangeFnPtr)(void *extContext, CsrUint16 nextstate); + +/** + * @brief + * OnIgnore,OnError or OnInvalid Callback Function Pointer + * + * @par Description + * Called when an event is processed by a fsm + * + * @param[in] extContext : External context + * @param[in] event : Event + * + * @return + * void + */ +typedef void (*CsrWifiFsmOnEventFnPtr)(void *extContext, const CsrWifiFsmEvent *event); + +/** + * @brief + * Toplevel FSM context data + * + * @par Description + * Holds ALL FSM static and dynamic data for a FSM + */ +struct CsrWifiFsmContext +{ + CsrWifiFsmEventList eventQueue; /* The internal event queue */ + CsrWifiFsmEventList externalEventQueue; /* The external event queue */ +#ifdef CSR_WIFI_FSM_MUTEX_ENABLE + CsrMutexHandle externalEventQueueLock; /* The external event queue mutex */ +#endif + CsrUint32 timeOffset; /* Amount to adjust the TimeOfDayMs by */ + CsrWifiFsmTimerList timerQueue; /* The internal timer queue */ + CsrBool useTempSaveList; /* Should the temp save list be used */ + CsrWifiFsmEventList tempSaveList; /* The temp save event queue */ + CsrWifiFsmEvent *eventForwardedOrSaved; /* The event that was forwarded or Saved */ + CsrUint16 maxProcesses; /* Size of instanceArray */ + CsrUint16 numProcesses; /* Current number allocated in instanceArray */ + CsrWifiFsmInstanceEntry *instanceArray; /* Array of processes for this component */ + CsrWifiFsmInstanceEntry *ownerInstance; /* The Process that owns currentInstance (SubFsm support) */ + CsrWifiFsmInstanceEntry *currentInstance; /* Current Process that is executing */ + CsrWifiFsmExternalWakupCallbackPtr externalEventFn; /* External event Callback */ + CsrWifiFsmOnEventFnPtr appIgnoreCallback; /* Application Ignore event Callback */ + CsrWifiFsmDestLookupCallbackPtr appEvtDstCallback; /* Application Lookup event Destination Function*/ + + void *applicationContext; /* Internal fsm application context */ + void *externalContext; /* External context (set by the user of the fsm)*/ + CsrLogTextTaskId loggingTaskId; /* Task Id to use in any logging output */ + +#ifndef CSR_WIFI_FSM_SCHEDULER_DISABLED + CsrSchedTid schedTimerId; /* Scheduler TimerId for use in Scheduler Tasks */ + CsrUint32 schedTimerNexttimeoutMs; /* Next timeout time for the current timer */ +#endif + +#ifdef CSR_WIFI_FSM_MUTEX_ENABLE +#ifdef CSR_WIFI_FSM_TRANSITION_LOCK + CsrMutexHandle transitionLock; /* Lock when calling transition functions */ +#endif +#endif + +#ifdef CSR_LOG_ENABLE + CsrWifiFsmOnCreateFnPtr onCreate; /* Debug Transition Callback */ + CsrWifiFsmOnTransitionFnPtr onTransition; /* Debug Transition Callback */ + CsrWifiFsmOnTransitionFnPtr onUnhandedCallback; /* Unhanded event Callback */ + CsrWifiFsmOnStateChangeFnPtr onStateChange; /* Debug State Change Callback */ + CsrWifiFsmOnEventFnPtr onIgnoreCallback; /* Ignore event Callback */ + CsrWifiFsmOnEventFnPtr onSaveCallback; /* Save event Callback */ + CsrWifiFsmOnEventFnPtr onErrorCallback; /* Error event Callback */ + CsrWifiFsmOnEventFnPtr onInvalidCallback; /* Invalid event Callback */ +#endif +#ifdef CSR_WIFI_FSM_DUMP_ENABLE + CsrUint16 masterTransitionNumber; /* Increments on every transition */ +#endif +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_FSM_TYPES_H */ diff --git a/drivers/staging/csr/csr_wifi_hip_card.h b/drivers/staging/csr/csr_wifi_hip_card.h new file mode 100644 index 000000000000..8904211d3317 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_card.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + ****************************************************************************** + * FILE : csr_wifi_hip_card.h + * + * PURPOSE : Defines abstract interface for hardware specific functions. + * Note, this is a different file from one of the same name in the + * Windows driver. + * + ***************************************************************************** + */ +#ifndef __CARD_H__ +#define __CARD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_wifi_hip_card_sdio.h" +#include "csr_wifi_hip_signals.h" +#include "csr_wifi_hip_unifi_udi.h" + + +/***************************************************************************** + * CardEnableInt - + */ +CsrResult CardEnableInt(card_t *card); + +/***************************************************************************** + * CardGenInt - + */ +CsrResult CardGenInt(card_t *card); + +/***************************************************************************** + * CardPendingInt - + */ +CsrResult CardPendingInt(card_t *card, CsrBool *pintr); + +/***************************************************************************** + * CardDisableInt - + */ +CsrResult CardDisableInt(card_t *card); + +/***************************************************************************** + * CardClearInt - + */ +CsrResult CardClearInt(card_t *card); + +/***************************************************************************** + * CardDisable - + */ +void CardDisable(card_t *card); + +/***************************************************************************** + * CardIntEnabled - + */ +CsrResult CardIntEnabled(card_t *card, CsrBool *enabled); + +/***************************************************************************** + * CardGetDataSlotSize + */ +CsrUint16 CardGetDataSlotSize(card_t *card); + +/***************************************************************************** + * CardWriteBulkData - + */ +CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQueue queue); + + +/***************************************************************************** + * CardClearFromHostDataSlot - + */ +void CardClearFromHostDataSlot(card_t *card, const CsrInt16 aSlotNum); + +/***************************************************************************** + * CardGetFreeFromHostDataSlots - + */ +CsrUint16 CardGetFreeFromHostDataSlots(card_t *card); + +CsrUint16 CardAreAllFromHostDataSlotsEmpty(card_t *card); + +CsrResult card_start_processor(card_t *card, enum unifi_dbg_processors_select which); + +CsrResult card_wait_for_firmware_to_start(card_t *card, CsrUint32 *paddr); + +CsrResult unifi_dl_firmware(card_t *card, void *arg); +CsrResult unifi_dl_patch(card_t *card, void *arg, CsrUint32 boot_ctrl); +CsrResult unifi_do_loader_op(card_t *card, CsrUint32 op_addr, CsrUint8 opcode); +void* unifi_dl_fw_read_start(card_t *card, CsrInt8 is_fw); + +CsrResult unifi_coredump_handle_request(card_t *card); + +CsrResult ConvertCsrSdioToCsrHipResult(card_t *card, CsrResult csrResult); +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +void unifi_debug_log_to_buf(const CsrCharString *fmt, ...); +void unifi_debug_string_to_buf(const CsrCharString *str); +void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* __CARD_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c new file mode 100644 index 000000000000..719c608d18b4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c @@ -0,0 +1,4128 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_card_sdio.c + * + * PURPOSE: Implementation of the Card API for SDIO. + * + * NOTES: + * CardInit() is called from the SDIO probe callback when a card is + * inserted. This performs the basic SDIO initialisation, enabling i/o + * etc. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "csr_wifi_hip_unifiversion.h" +#include "csr_wifi_hip_card.h" +#include "csr_wifi_hip_card_sdio.h" +#include "csr_wifi_hip_chiphelper.h" + + +/* Time to wait between attempts to read MAILBOX0 */ +#define MAILBOX1_TIMEOUT 10 /* in millisecs */ +#define MAILBOX1_ATTEMPTS 200 /* 2 seconds */ + +#define MAILBOX2_TIMEOUT 5 /* in millisecs */ +#define MAILBOX2_ATTEMPTS 10 /* 50ms */ + +#define MAILBOX2_RESET_ATTEMPTS 10 +#define MAILBOX2_RESET_TIMEOUT 5 /* in millisecs */ + +#define RESET_SETTLE_DELAY 25 /* in millisecs */ + +static CsrResult card_init_slots(card_t *card); +static CsrResult card_hw_init(card_t *card); +static CsrResult firmware_present_in_flash(card_t *card); +static void bootstrap_chip_hw(card_t *card); +static CsrResult unifi_reset_hardware(card_t *card); +static CsrResult unifi_hip_init(card_t *card); +static CsrResult card_access_panic(card_t *card); +static CsrResult unifi_read_chip_version(card_t *card); + +/* + * --------------------------------------------------------------------------- + * unifi_alloc_card + * + * Allocate and initialise the card context structure. + * + * Arguments: + * sdio Pointer to SDIO context pointer to pass to low + * level i/o functions. + * ospriv Pointer to O/S private struct to pass when calling + * callbacks to the higher level system. + * + * Returns: + * Pointer to card struct, which represents the driver context or + * NULL if the allocation failed. + * --------------------------------------------------------------------------- + */ +card_t* unifi_alloc_card(CsrSdioFunction *sdio, void *ospriv) +{ + card_t *card; + CsrUint32 i; + + func_enter(); + + + card = (card_t *)CsrMemAlloc(sizeof(card_t)); + if (card == NULL) + { + return NULL; + } + CsrMemSet(card, 0, sizeof(card_t)); + + + card->sdio_if = sdio; + card->ospriv = ospriv; + + card->unifi_interrupt_seq = 1; + + /* Make these invalid. */ + card->proc_select = (CsrUint32)(-1); + card->dmem_page = (CsrUint32)(-1); + card->pmem_page = (CsrUint32)(-1); + + card->bh_reason_host = 0; + card->bh_reason_unifi = 0; + + for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++) + { + card->tx_q_paused_flag[i] = 0; + } + card->memory_resources_allocated = 0; + + card->low_power_mode = UNIFI_LOW_POWER_DISABLED; + card->periodic_wake_mode = UNIFI_PERIODIC_WAKE_HOST_DISABLED; + + card->host_state = UNIFI_HOST_STATE_AWAKE; + card->intmode = CSR_WIFI_INTMODE_DEFAULT; + + /* + * Memory resources for buffers are allocated when the chip is initialised + * because we need configuration information from the firmware. + */ + + /* + * Initialise wait queues and lists + */ + card->fh_command_queue.q_body = card->fh_command_q_body; + card->fh_command_queue.q_length = UNIFI_SOFT_COMMAND_Q_LENGTH; + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->fh_traffic_queue[i].q_body = card->fh_traffic_q_body[i]; + card->fh_traffic_queue[i].q_length = UNIFI_SOFT_TRAFFIC_Q_LENGTH; + } + + + /* Initialise mini-coredump pointers in case no coredump buffers + * are requested by the OS layer. + */ + card->request_coredump_on_reset = 0; + card->dump_next_write = NULL; + card->dump_cur_read = NULL; + card->dump_buf = NULL; + +#ifdef UNIFI_DEBUG + /* Determine offset of LSB in pointer for later alignment sanity check. + * Synergy integer types have specific widths, which cause compiler + * warnings when casting pointer types, e.g. on 64-bit systems. + */ + { + CsrUint32 val = 0x01234567; + + if (*((CsrUint8 *)&val) == 0x01) + { + card->lsb = sizeof(void *) - 1; /* BE */ + } + else + { + card->lsb = 0; /* LE */ + } + } +#endif + func_exit(); + return card; +} /* unifi_alloc_card() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_init_card + * + * Reset the hardware and perform HIP initialization + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CsrResult code + * CSR_RESULT_SUCCESS if successful + * --------------------------------------------------------------------------- + */ +CsrResult unifi_init_card(card_t *card, CsrInt32 led_mask) +{ + CsrResult r; + + func_enter(); + + if (card == NULL) + { + func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + r = unifi_init(card); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + + r = unifi_hip_init(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + func_exit_r(r); + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to start host protocol.\n"); + func_exit_r(r); + return r; + } + + func_exit(); + return CSR_RESULT_SUCCESS; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_init + * + * Init the hardware. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CsrResult code + * CSR_RESULT_SUCCESS if successful + * --------------------------------------------------------------------------- + */ +CsrResult unifi_init(card_t *card) +{ + CsrResult r; + CsrResult csrResult; + + func_enter(); + + if (card == NULL) + { + func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* + * Disable the SDIO interrupts while initialising UniFi. + * Re-enable them when f/w is running. + */ + csrResult = CsrSdioInterruptDisable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + + /* + * UniFi's PLL may start with a slow clock (~ 1 MHz) so initially + * set the SDIO bus clock to a similar value or SDIO accesses may + * fail. + */ + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + func_exit_r(r); + return r; + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; + + /* + * Reset UniFi. Note, this only resets the WLAN function part of the chip, + * the SDIO interface is not reset. + */ + unifi_trace(card->ospriv, UDBG1, "Resetting UniFi\n"); + r = unifi_reset_hardware(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to reset UniFi\n"); + func_exit_r(r); + return r; + } + + /* Reset the power save mode, to be active until the MLME-reset is complete */ + r = unifi_configure_low_power_mode(card, + UNIFI_LOW_POWER_DISABLED, UNIFI_PERIODIC_WAKE_HOST_DISABLED); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to set power save mode\n"); + func_exit_r(r); + return r; + } + + /* + * Set initial value of page registers. + * The page registers will be maintained by unifi_read...() and + * unifi_write...(). + */ + card->proc_select = (CsrUint32)(-1); + card->dmem_page = (CsrUint32)(-1); + card->pmem_page = (CsrUint32)(-1); + r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW3_PAGE(card->helper) * 2, 0); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n"); + func_exit_r(r); + return r; + } + r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, 0); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write PROG_MEM2_PAGE\n"); + func_exit_r(r); + return r; + } + + /* + * If the driver has reset UniFi due to previous SDIO failure, this may + * have been due to a chip watchdog reset. In this case, the driver may + * have requested a mini-coredump which needs to be captured now the + * SDIO interface is alive. + */ + unifi_coredump_handle_request(card); + + /* + * Probe to see if the UniFi has ROM/flash to boot from. CSR6xxx should do. + */ + r = firmware_present_in_flash(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r == CSR_WIFI_HIP_RESULT_NOT_FOUND) + { + unifi_error(card->ospriv, "No firmware found\n"); + } + else if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Probe for Flash failed\n"); + } + + func_exit_r(r); + return r; +} /* unifi_init() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_download + * + * Load the firmware. + * + * Arguments: + * card Pointer to card struct + * led_mask Loader LED mask + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CsrResult error code on failure. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_download(card_t *card, CsrInt32 led_mask) +{ + CsrResult r; + void *dlpriv; + + func_enter(); + + if (card == NULL) + { + func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* Set the loader led mask */ + card->loader_led_mask = led_mask; + + /* Get the firmware file information */ + unifi_trace(card->ospriv, UDBG1, "downloading firmware...\n"); + + dlpriv = unifi_dl_fw_read_start(card, UNIFI_FW_STA); + if (dlpriv == NULL) + { + func_exit_r(CSR_WIFI_HIP_RESULT_NOT_FOUND); + return CSR_WIFI_HIP_RESULT_NOT_FOUND; + } + + /* Download the firmware. */ + r = unifi_dl_firmware(card, dlpriv); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to download firmware\n"); + func_exit_r(r); + return r; + } + + /* Free the firmware file information. */ + unifi_fw_read_stop(card->ospriv, dlpriv); + + func_exit(); + + return CSR_RESULT_SUCCESS; +} /* unifi_download() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_hip_init + * + * This function performs the f/w initialisation sequence as described + * in the Unifi Host Interface Protocol Specification. + * It allocates memory for host-side slot data and signal queues. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS on success or else a CSR error code + * + * Notes: + * The firmware must have been downloaded. + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_hip_init(card_t *card) +{ + CsrResult r; + CsrResult csrResult; + + func_enter(); + + r = card_hw_init(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to establish communication with UniFi\n"); + func_exit_r(r); + return r; + } +#ifdef CSR_PRE_ALLOC_NET_DATA + /* if there is any preallocated netdata left from the prev session free it now */ + prealloc_netdata_free(card); +#endif + /* + * Allocate memory for host-side slot data and signal queues. + * We need the config info read from the firmware to know how much + * memory to allocate. + */ + r = card_init_slots(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Init slots failed: %d\n", r); + func_exit_r(r); + return r; + } + + unifi_trace(card->ospriv, UDBG2, "Sending first UniFi interrupt\n"); + + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + + /* Enable the SDIO interrupts now that the f/w is running. */ + csrResult = CsrSdioInterruptEnable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + + /* Signal the UniFi to start handling messages */ + r = CardGenInt(card); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + + func_exit(); + + return CSR_RESULT_SUCCESS; +} /* unifi_hip_init() */ + + +/* + * --------------------------------------------------------------------------- + * _build_sdio_config_data + * + * Unpack the SDIO configuration information from a buffer read from + * UniFi into a host structure. + * The data is byte-swapped for a big-endian host if necessary by the + * UNPACK... macros. + * + * Arguments: + * card Pointer to card struct + * cfg_data Destination structure to unpack into. + * cfg_data_buf Source buffer to read from. This should be the raw + * data read from UniFi. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void _build_sdio_config_data(sdio_config_data_t *cfg_data, + const CsrUint8 *cfg_data_buf) +{ + CsrInt16 offset = 0; + + cfg_data->version = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->sdio_ctrl_offset = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->fromhost_sigbuf_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->tohost_sigbuf_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->num_fromhost_sig_frags = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->num_tohost_sig_frags = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->num_fromhost_data_slots = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->num_tohost_data_slots = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->data_slot_size = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->initialised = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->overlay_size = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT32; + + cfg_data->data_slot_round = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->sig_frag_size = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); + offset += SIZEOF_UINT16; + + cfg_data->tohost_signal_padding = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); +} /* _build_sdio_config_data() */ + + +/* + * - Function ---------------------------------------------------------------- + * card_hw_init() + * + * Perform the initialisation procedure described in the UniFi Host + * Interface Protocol document (section 3.3.8) and read the run-time + * configuration information from the UniFi. This is stuff like number + * of bulk data slots etc. + * + * The card enumeration and SD initialisation has already been done by + * the SDIO library, see card_sdio_init(). + * + * The initialisation is done when firmware is ready, i.e. this may need + * to be called after a f/w download operation. + * + * The initialisation procedure goes like this: + * - Wait for UniFi to start-up by polling SHARED_MAILBOX1 + * - Find the symbol table and look up SLT_SDIO_SLOT_CONFIG + * - Read the config structure + * - Check the "SDIO initialised" flag, if not zero do a h/w reset and + * start again + * - Decide the number of bulk data slots to allocate, allocate them and + * set "SDIO initialised" flag (and generate an interrupt) to say so. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCEESS on success, + * a CSR error code on failure + * + * Notes: + * All data in the f/w is stored in a little endian format, without any + * padding bytes. Every read from this memory has to be transformed in + * host (cpu specific) format, before it is stored in driver's parameters + * or/and structures. Athough unifi_card_read16() and unifi_read32() do perform + * the convertion internally, unifi_readn() does not. + * --------------------------------------------------------------------------- + */ +static CsrResult card_hw_init(card_t *card) +{ + CsrUint32 slut_address; + CsrUint16 initialised; + CsrUint16 finger_print; + symbol_t slut; + sdio_config_data_t *cfg_data; + CsrUint8 cfg_data_buf[SDIO_CONFIG_DATA_SIZE]; + CsrResult r; + void *dlpriv; + CsrInt16 major, minor; + CsrInt16 search_4slut_again; + CsrResult csrResult; + + func_enter(); + + /* + * The device revision from the TPLMID_MANF and TPLMID_CARD fields + * of the CIS are available as + * card->sdio_if->pDevice->ManfID + * card->sdio_if->pDevice->AppID + */ + + /* + * Run in a loop so we can patch. + */ + do + { + /* Reset these each time around the loop. */ + search_4slut_again = 0; + cfg_data = NULL; + + r = card_wait_for_firmware_to_start(card, &slut_address); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Firmware hasn't started\n"); + func_exit_r(r); + return r; + } + unifi_trace(card->ospriv, UDBG4, "SLUT addr 0x%lX\n", slut_address); + + /* + * Firmware has started, but doesn't know full clock configuration yet + * as some of the information may be in the MIB. Therefore we set an + * initial SDIO clock speed, faster than UNIFI_SDIO_CLOCK_SAFE_HZ, for + * the patch download and subsequent firmware initialisation, and + * full speed UNIFI_SDIO_CLOCK_MAX_HZ will be set once the f/w tells us + * that it is ready. + */ + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + func_exit_r(r); + return r; + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; + + /* + * Check the SLUT fingerprint. + * The slut_address is a generic pointer so we must use unifi_card_read16(). + */ + unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n"); + finger_print = 0; + r = unifi_card_read16(card, slut_address, &finger_print); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read SLUT finger print\n"); + func_exit_r(r); + return r; + } + + if (finger_print != SLUT_FINGERPRINT) + { + unifi_error(card->ospriv, "Failed to find Symbol lookup table fingerprint\n"); + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + /* Symbol table starts imedately after the fingerprint */ + slut_address += 2; + + /* Search the table until either the end marker is found, or the + * loading of patch firmware invalidates the current table. + */ + while (!search_4slut_again) + { + CsrUint16 s; + CsrUint32 l; + + r = unifi_card_read16(card, slut_address, &s); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + slut_address += 2; + + if (s == CSR_SLT_END) + { + unifi_trace(card->ospriv, UDBG3, " found CSR_SLT_END\n"); + break; + } + + r = unifi_read32(card, slut_address, &l); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + slut_address += 4; + + slut.id = s; + slut.obj = l; + + unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", slut.id, slut.obj); + switch (slut.id) + { + case CSR_SLT_SDIO_SLOT_CONFIG: + cfg_data = &card->config_data; + /* + * unifi_card_readn reads n bytes from the card, where data is stored + * in a little endian format, without any padding bytes. So, we + * can not just pass the cfg_data pointer or use the + * sizeof(sdio_config_data_t) since the structure in the host can + * be big endian formatted or have padding bytes for alignment. + * We use a char buffer to read the data from the card. + */ + r = unifi_card_readn(card, slut.obj, cfg_data_buf, SDIO_CONFIG_DATA_SIZE); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read config data\n"); + func_exit_r(r); + return r; + } + /* .. and then we copy the data to the host structure */ + _build_sdio_config_data(cfg_data, cfg_data_buf); + + /* Make sure the from host data slots are what we expect + we reserve 2 for commands and there should be at least + 1 left for each access category */ + if ((cfg_data->num_fromhost_data_slots < UNIFI_RESERVED_COMMAND_SLOTS) + || (cfg_data->num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS) / UNIFI_NO_OF_TX_QS == 0) + { + unifi_error(card->ospriv, "From host data slots %d\n", cfg_data->num_fromhost_data_slots); + unifi_error(card->ospriv, "need to be (queues * x + 2) (UNIFI_RESERVED_COMMAND_SLOTS for commands)\n"); + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + /* Configure SDIO to-block-size padding */ + if (card->sdio_io_block_pad) + { + /* + * Firmware limits the maximum padding size via data_slot_round. + * Therefore when padding to whole block sizes, the block size + * must be configured correctly by adjusting CSR_WIFI_HIP_SDIO_BLOCK_SIZE. + */ + if (cfg_data->data_slot_round < card->sdio_io_block_size) + { + unifi_error(card->ospriv, + "Configuration error: Block size of %d exceeds f/w data_slot_round of %d\n", + card->sdio_io_block_size, cfg_data->data_slot_round); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* + * To force the To-Host signals to be rounded up to the SDIO block + * size, we need to write the To-Host Signal Padding Fragments + * field of the SDIO configuration in UniFi. + */ + if ((card->sdio_io_block_size % cfg_data->sig_frag_size) != 0) + { + unifi_error(card->ospriv, "Configuration error: Can not pad to-host signals.\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + cfg_data->tohost_signal_padding = (CsrUint16) (card->sdio_io_block_size / cfg_data->sig_frag_size); + unifi_info(card->ospriv, "SDIO block size %d requires %d padding chunks\n", + card->sdio_io_block_size, cfg_data->tohost_signal_padding); + r = unifi_card_write16(card, slut.obj + SDIO_TO_HOST_SIG_PADDING_OFFSET, cfg_data->tohost_signal_padding); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write To-Host Signal Padding Fragments\n"); + func_exit_r(r); + return r; + } + } + + /* Reconstruct the Generic Pointer address of the + * SDIO Control Data Struct. + */ + card->sdio_ctrl_addr = cfg_data->sdio_ctrl_offset | (UNIFI_SH_DMEM << 24); + card->init_flag_addr = slut.obj + SDIO_INIT_FLAG_OFFSET; + break; + + case CSR_SLT_BUILD_ID_NUMBER: + { + CsrUint32 n; + r = unifi_read32(card, slut.obj, &n); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read build id\n"); + func_exit_r(r); + return r; + } + card->build_id = n; + } + break; + + case CSR_SLT_BUILD_ID_STRING: + r = unifi_readnz(card, slut.obj, card->build_id_string, + sizeof(card->build_id_string)); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read build string\n"); + func_exit_r(r); + return r; + } + break; + + case CSR_SLT_PERSISTENT_STORE_DB: + break; + + case CSR_SLT_BOOT_LOADER_CONTROL: + + /* This command copies most of the station firmware + * image from ROM into program RAM. It also clears + * out the zerod data and sets up the initialised + * data. */ + r = unifi_do_loader_op(card, slut.obj + 6, UNIFI_BOOT_LOADER_LOAD_STA); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write loader load image command\n"); + func_exit_r(r); + return r; + } + + dlpriv = unifi_dl_fw_read_start(card, UNIFI_FW_STA); + + /* dlpriv might be NULL, we still need to do the do_loader_op step. */ + if (dlpriv != NULL) + { + /* Download the firmware. */ + r = unifi_dl_patch(card, dlpriv, slut.obj); + + /* Free the firmware file information. */ + unifi_fw_read_stop(card->ospriv, dlpriv); + + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to patch firmware\n"); + func_exit_r(r); + return r; + } + } + + /* This command starts the firmware image that we want (the + * station by default) with any patches required applied. */ + r = unifi_do_loader_op(card, slut.obj + 6, UNIFI_BOOT_LOADER_RESTART); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write loader restart command\n"); + func_exit_r(r); + return r; + } + + /* The now running patch f/w defines a new SLUT data structure - + * the current one is no longer valid. We must drop out of the + * processing loop and enumerate the new SLUT (which may appear + * at a different offset). + */ + search_4slut_again = 1; + break; + + case CSR_SLT_PANIC_DATA_PHY: + card->panic_data_phy_addr = slut.obj; + break; + + case CSR_SLT_PANIC_DATA_MAC: + card->panic_data_mac_addr = slut.obj; + break; + + default: + /* do nothing */ + break; + } + } /* while */ + } while (search_4slut_again); + + /* Did we find the Config Data ? */ + if (cfg_data == NULL) + { + unifi_error(card->ospriv, "Failed to find SDIO_SLOT_CONFIG Symbol\n"); + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + /* + * Has ths card already been initialised? + * If so, return an error so we do a h/w reset and start again. + */ + r = unifi_card_read16(card, card->init_flag_addr, &initialised); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read init flag at %08lx\n", + card->init_flag_addr); + func_exit_r(r); + return r; + } + if (initialised != 0) + { + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + + /* + * Now check the UniFi firmware version + */ + major = (cfg_data->version >> 8) & 0xFF; + minor = cfg_data->version & 0xFF; + unifi_info(card->ospriv, "UniFi f/w protocol version %d.%d (driver %d.%d)\n", + major, minor, + UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); + + unifi_info(card->ospriv, "Firmware build %u: %s\n", + card->build_id, card->build_id_string); + + if (major != UNIFI_HIP_MAJOR_VERSION) + { + unifi_error(card->ospriv, "UniFi f/w protocol major version (%d) is different from driver (v%d.%d)\n", + major, UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); +#ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; +#endif + } + if (minor < UNIFI_HIP_MINOR_VERSION) + { + unifi_error(card->ospriv, "UniFi f/w protocol version (v%d.%d) is older than minimum required by driver (v%d.%d).\n", + major, minor, + UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); +#ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; +#endif + } + + /* Read panic codes from a previous firmware panic. If the firmware has + * not panicked since power was applied (e.g. power-off hard reset) + * the stored panic codes will not be updated. + */ + unifi_read_panic(card); + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* card_hw_init() */ + + +/* + * --------------------------------------------------------------------------- + * card_wait_for_unifi_to_reset + * + * Waits for a reset to complete by polling the WLAN function enable + * bit (which is cleared on reset). + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure. + * --------------------------------------------------------------------------- + */ +static CsrResult card_wait_for_unifi_to_reset(card_t *card) +{ + CsrInt16 i; + CsrResult r; + CsrUint8 io_enable; + CsrResult csrResult; + + func_enter(); + + r = CSR_RESULT_SUCCESS; + for (i = 0; i < MAILBOX2_ATTEMPTS; i++) + { + unifi_trace(card->ospriv, UDBG1, "waiting for reset to complete, attempt %d\n", i); + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + /* It's quite likely that this read will timeout for the + * first few tries - especially if we have reset via + * DBG_RESET. + */ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("m0@%02X=", SDIO_IO_READY); +#endif + csrResult = CsrSdioF0Read8(card->sdio_if, SDIO_IO_READY, &io_enable); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf("error=%X\n", csrResult); + } + else + { + unifi_debug_log_to_buf("%X\n", io_enable); + } +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + r = CSR_RESULT_SUCCESS; + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + } + } + else + { + r = sdio_read_f0(card, SDIO_IO_ENABLE, &io_enable); + } + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r == CSR_RESULT_SUCCESS) + { + CsrUint16 mbox2; + CsrInt16 enabled = io_enable & (1 << card->function); + + if (!enabled) + { + unifi_trace(card->ospriv, UDBG1, + "Reset complete (function %d is disabled) in ~ %u msecs\n", + card->function, i * MAILBOX2_TIMEOUT); + + /* Enable WLAN function and verify MAILBOX2 is zero'd */ + csrResult = CsrSdioFunctionEnable(card->sdio_if); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + unifi_error(card->ospriv, "CsrSdioFunctionEnable failed %d\n", r); + break; + } + } + + r = unifi_read_direct16(card, ChipHelper_SDIO_HIP_HANDSHAKE(card->helper) * 2, &mbox2); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "read HIP_HANDSHAKE failed %d\n", r); + break; + } + if (mbox2 != 0) + { + unifi_error(card->ospriv, "MAILBOX2 non-zero after reset (mbox2 = %04x)\n", mbox2); + r = CSR_RESULT_FAILURE; + } + break; + } + else + { + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + /* We ignore read failures for the first few reads, + * they are probably benign. */ + if (i > MAILBOX2_ATTEMPTS / 4) + { + unifi_trace(card->ospriv, UDBG1, "Failed to read CCCR IO Ready register while polling for reset\n"); + } + } + else + { + unifi_trace(card->ospriv, UDBG1, "Failed to read CCCR IO Enable register while polling for reset\n"); + } + } + CsrThreadSleep(MAILBOX2_TIMEOUT); + } + + if (r == CSR_RESULT_SUCCESS && i == MAILBOX2_ATTEMPTS) + { + unifi_trace(card->ospriv, UDBG1, "Timeout waiting for UniFi to complete reset\n"); + r = CSR_RESULT_FAILURE; + } + + func_exit(); + return r; +} /* card_wait_for_unifi_to_reset() */ + + +/* + * --------------------------------------------------------------------------- + * card_wait_for_unifi_to_disable + * + * Waits for the function to become disabled by polling the + * IO_READY bit. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure. + * + * Notes: This function can only be used with + * card->chip_id > SDIO_CARD_ID_UNIFI_2 + * --------------------------------------------------------------------------- + */ +static CsrResult card_wait_for_unifi_to_disable(card_t *card) +{ + CsrInt16 i; + CsrResult r; + CsrUint8 io_enable; + CsrResult csrResult; + + func_enter(); + + if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) + { + unifi_error(card->ospriv, + "Function reset method not supported for chip_id=%d\n", + card->chip_id); + func_exit(); + return CSR_RESULT_FAILURE; + } + + r = CSR_RESULT_SUCCESS; + for (i = 0; i < MAILBOX2_ATTEMPTS; i++) + { + unifi_trace(card->ospriv, UDBG1, "waiting for disable to complete, attempt %d\n", i); + + /* + * It's quite likely that this read will timeout for the + * first few tries - especially if we have reset via + * DBG_RESET. + */ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("r0@%02X=", SDIO_IO_READY); +#endif + csrResult = CsrSdioF0Read8(card->sdio_if, SDIO_IO_READY, &io_enable); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf("error=%X\n", csrResult); + } + else + { + unifi_debug_log_to_buf("%X\n", io_enable); + } +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + if (csrResult == CSR_RESULT_SUCCESS) + { + CsrInt16 enabled = io_enable & (1 << card->function); + r = CSR_RESULT_SUCCESS; + if (!enabled) + { + unifi_trace(card->ospriv, UDBG1, + "Disable complete (function %d is disabled) in ~ %u msecs\n", + card->function, i * MAILBOX2_TIMEOUT); + + break; + } + } + else + { + /* + * We ignore read failures for the first few reads, + * they are probably benign. + */ + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + if (i > (MAILBOX2_ATTEMPTS / 4)) + { + unifi_trace(card->ospriv, UDBG1, + "Failed to read CCCR IO Ready register while polling for disable\n"); + } + } + CsrThreadSleep(MAILBOX2_TIMEOUT); + } + + if ((r == CSR_RESULT_SUCCESS) && (i == MAILBOX2_ATTEMPTS)) + { + unifi_trace(card->ospriv, UDBG1, "Timeout waiting for UniFi to complete disable\n"); + r = CSR_RESULT_FAILURE; + } + + func_exit(); + return r; +} /* card_wait_for_unifi_to_reset() */ + + +/* + * --------------------------------------------------------------------------- + * card_wait_for_firmware_to_start + * + * Polls the MAILBOX1 register for a non-zero value. + * Then reads MAILBOX0 and forms the two values into a 32-bit address + * which is returned to the caller. + * + * Arguments: + * card Pointer to card struct + * paddr Pointer to receive the UniFi address formed + * by concatenating MAILBOX1 and MAILBOX0. + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure. + * --------------------------------------------------------------------------- + */ +CsrResult card_wait_for_firmware_to_start(card_t *card, CsrUint32 *paddr) +{ + CsrInt32 i; + CsrUint16 mbox0, mbox1; + CsrResult r; + + func_enter(); + + /* + * Wait for UniFi to initialise its data structures by polling + * the SHARED_MAILBOX1 register. + * Experience shows this is typically 120ms. + */ + CsrThreadSleep(MAILBOX1_TIMEOUT); + + mbox1 = 0; + unifi_trace(card->ospriv, UDBG1, "waiting for MAILBOX1 to be non-zero...\n"); + for (i = 0; i < MAILBOX1_ATTEMPTS; i++) + { + r = unifi_read_direct16(card, ChipHelper_MAILBOX1(card->helper) * 2, &mbox1); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + /* These reads can fail if UniFi isn't up yet, so try again */ + unifi_warning(card->ospriv, "Failed to read UniFi Mailbox1 register\n"); + } + + if ((r == CSR_RESULT_SUCCESS) && (mbox1 != 0)) + { + unifi_trace(card->ospriv, UDBG1, "MAILBOX1 ready (0x%04X) in %u millisecs\n", + mbox1, i * MAILBOX1_TIMEOUT); + + /* Read the MAILBOX1 again in case we caught the value as it + * changed. */ + r = unifi_read_direct16(card, ChipHelper_MAILBOX1(card->helper) * 2, &mbox1); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read UniFi Mailbox1 register for second time\n"); + func_exit_r(r); + return r; + } + unifi_trace(card->ospriv, UDBG1, "MAILBOX1 value=0x%04X\n", mbox1); + + break; + } + + CsrThreadSleep(MAILBOX1_TIMEOUT); + if ((i % 100) == 99) + { + unifi_trace(card->ospriv, UDBG2, "MAILBOX1 not ready (0x%X), still trying...\n", mbox1); + } + } + + if ((r == CSR_RESULT_SUCCESS) && (mbox1 == 0)) + { + unifi_trace(card->ospriv, UDBG1, "Timeout waiting for firmware to start, Mailbox1 still 0 after %d ms\n", + MAILBOX1_ATTEMPTS * MAILBOX1_TIMEOUT); + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + + /* + * Complete the reset handshake by setting MAILBOX2 to 0xFFFF + */ + r = unifi_write_direct16(card, ChipHelper_SDIO_HIP_HANDSHAKE(card->helper) * 2, 0xFFFF); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write f/w startup handshake to MAILBOX2\n"); + func_exit_r(r); + return r; + } + + + /* + * Read the Symbol Look Up Table (SLUT) offset. + * Top 16 bits are in mbox1, read the lower 16 bits from mbox0. + */ + mbox0 = 0; + r = unifi_read_direct16(card, ChipHelper_MAILBOX0(card->helper) * 2, &mbox0); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read UniFi Mailbox0 register\n"); + func_exit_r(r); + return r; + } + + *paddr = (((CsrUint32)mbox1 << 16) | mbox0); + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* card_wait_for_firmware_to_start() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_capture_panic + * + * Attempt to capture panic codes from the firmware. This may involve + * warm reset of the chip to regain access following a watchdog reset. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS if panic codes were captured, or none available + * CSR_RESULT_FAILURE if the driver could not access function 1 + * --------------------------------------------------------------------------- + */ +CsrResult unifi_capture_panic(card_t *card) +{ + func_enter(); + + /* The firmware must have previously initialised to read the panic addresses + * from the SLUT + */ + if (!card->panic_data_phy_addr || !card->panic_data_mac_addr) + { + func_exit(); + return CSR_RESULT_SUCCESS; + } + + /* Ensure we can access function 1 following a panic/watchdog reset */ + if (card_access_panic(card) == CSR_RESULT_SUCCESS) + { + /* Read the panic codes */ + unifi_read_panic(card); + } + else + { + unifi_info(card->ospriv, "Unable to read panic codes"); + } + + func_exit(); + return CSR_RESULT_SUCCESS; +} + + +/* + * --------------------------------------------------------------------------- + * card_access_panic + * Attempt to read the WLAN SDIO function in order to read panic codes + * and perform various reset steps to regain access if the read fails. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS if panic codes can be read + * CSR error code if panic codes can not be read + * --------------------------------------------------------------------------- + */ +static CsrResult card_access_panic(card_t *card) +{ + CsrUint16 data_u16 = 0; + CsrInt32 i; + CsrResult r, sr; + + func_enter(); + + /* A chip version of zero means that the version never got succesfully read + * during reset. In this case give up because it will not be possible to + * verify the chip version. + */ + if (!card->chip_version) + { + unifi_info(card->ospriv, "Unknown chip version\n"); + return CSR_RESULT_FAILURE; + } + + /* Ensure chip is awake or access to function 1 will fail */ + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_set_host_state() failed %d\n", r); + return CSR_RESULT_FAILURE; /* Card is probably unpowered */ + } + CsrThreadSleep(20); + + for (i = 0; i < 3; i++) + { + sr = CsrSdioRead16(card->sdio_if, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION * 2, &data_u16); + if (sr != CSR_RESULT_SUCCESS || data_u16 != card->chip_version) + { + unifi_info(card->ospriv, "Failed to read valid chip version sr=%d (0x%04x want 0x%04x) try %d\n", + sr, data_u16, card->chip_version, i); + + /* Set clock speed low */ + sr = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); + if (sr != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "CsrSdioMaxBusClockFrequencySet() failed1 %d\n", sr); + r = ConvertCsrSdioToCsrHipResult(card, sr); + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; + + /* First try re-enabling function in case a f/w watchdog reset disabled it */ + if (i == 0) + { + unifi_info(card->ospriv, "Try function enable\n"); + sr = CsrSdioFunctionEnable(card->sdio_if); + if (sr != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, sr); + unifi_error(card->ospriv, "CsrSdioFunctionEnable failed %d (HIP %d)\n", sr, r); + } + continue; + } + + /* Second try, set awake */ + unifi_info(card->ospriv, "Try set awake\n"); + + /* Ensure chip is awake */ + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_set_host_state() failed2 %d\n", r); + } + + /* Set clock speed low in case setting the host state raised it, which + * would only happen if host state was previously TORPID + */ + sr = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); + if (sr != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "CsrSdioMaxBusClockFrequencySet() failed2 %d\n", sr); + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; + + if (i == 1) + { + continue; + } + + /* Perform a s/w reset to preserve as much as the card state as possible, + * (mainly the preserve RAM). The context will be lost for coredump - but as we + * were unable to access the WLAN function for panic, the coredump would have + * also failed without a reset. + */ + unifi_info(card->ospriv, "Try s/w reset\n"); + + r = unifi_card_hard_reset(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_card_hard_reset() failed %d\n", r); + } + } + else + { + if (i > 0) + { + unifi_info(card->ospriv, "Read chip version 0x%x after %d retries\n", data_u16, i); + } + break; + } + } + + r = ConvertCsrSdioToCsrHipResult(card, sr); + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_read_panic + * Reads, saves and prints panic codes stored by the firmware in UniFi's + * preserve RAM by the last panic that occurred since chip was powered. + * Nothing is saved if the panic codes are read as zero. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * --------------------------------------------------------------------------- + */ +void unifi_read_panic(card_t *card) +{ + CsrResult r; + CsrUint16 p_code, p_arg; + + func_enter(); + + /* The firmware must have previously initialised to read the panic addresses + * from the SLUT + */ + if (!card->panic_data_phy_addr || !card->panic_data_mac_addr) + { + return; + } + + /* Get the panic data from PHY */ + r = unifi_card_read16(card, card->panic_data_phy_addr, &p_code); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_phy_addr, r); + p_code = 0; + } + if (p_code) + { + r = unifi_card_read16(card, card->panic_data_phy_addr + 2, &p_arg); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_phy_addr + 2, r); + } + unifi_error(card->ospriv, "Last UniFi PHY PANIC %04x arg %04x\n", p_code, p_arg); + card->last_phy_panic_code = p_code; + card->last_phy_panic_arg = p_arg; + } + + /* Get the panic data from MAC */ + r = unifi_card_read16(card, card->panic_data_mac_addr, &p_code); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_mac_addr, r); + p_code = 0; + } + if (p_code) + { + r = unifi_card_read16(card, card->panic_data_mac_addr + 2, &p_arg); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_mac_addr + 2, r); + } + unifi_error(card->ospriv, "Last UniFi MAC PANIC %04x arg %04x\n", p_code, p_arg); + card->last_mac_panic_code = p_code; + card->last_mac_panic_arg = p_arg; + } + + func_exit(); +} + + +/* + * --------------------------------------------------------------------------- + * card_allocate_memory_resources + * + * Allocates memory for the from-host, to-host bulk data slots, + * soft queue buffers and bulk data buffers. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure. + * --------------------------------------------------------------------------- + */ +static CsrResult card_allocate_memory_resources(card_t *card) +{ + CsrInt16 n, i, k, r; + sdio_config_data_t *cfg_data; + + func_enter(); + + /* Reset any state carried forward from a previous life */ + card->fh_command_queue.q_rd_ptr = 0; + card->fh_command_queue.q_wr_ptr = 0; + CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + "fh_cmd_q"); + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->fh_traffic_queue[i].q_rd_ptr = 0; + card->fh_traffic_queue[i].q_wr_ptr = 0; + CsrSnprintf(card->fh_traffic_queue[i].name, + UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); + } +#ifndef CSR_WIFI_HIP_TA_DISABLE + unifi_ta_sampling_init(card); +#endif + /* Convenience short-cut */ + cfg_data = &card->config_data; + + /* + * Allocate memory for the from-host and to-host signal buffers. + */ + card->fh_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE); + if (card->fh_buffer.buf == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + card->fh_buffer.bufsize = UNIFI_FH_BUF_SIZE; + card->fh_buffer.ptr = card->fh_buffer.buf; + card->fh_buffer.count = 0; + + card->th_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE); + if (card->th_buffer.buf == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + card->th_buffer.bufsize = UNIFI_FH_BUF_SIZE; + card->th_buffer.ptr = card->th_buffer.buf; + card->th_buffer.count = 0; + + + /* + * Allocate memory for the from-host and to-host bulk data slots. + * This is done as separate CsrPmemAllocs because lots of smaller + * allocations are more likely to succeed than one huge one. + */ + + /* Allocate memory for the array of pointers */ + n = cfg_data->num_fromhost_data_slots; + + unifi_trace(card->ospriv, UDBG3, "Alloc from-host resources, %d slots.\n", n); + card->from_host_data = + (slot_desc_t *)CsrMemAlloc(n * sizeof(slot_desc_t)); + if (card->from_host_data == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for F-H bulk data array\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + /* Initialise from-host bulk data slots */ + for (i = 0; i < n; i++) + { + UNIFI_INIT_BULK_DATA(&card->from_host_data[i].bd); + } + + /* Allocate memory for the array used for slot host tag mapping */ + card->fh_slot_host_tag_record = + (CsrUint32 *)CsrMemAlloc(n * sizeof(CsrUint32)); + + if (card->fh_slot_host_tag_record == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for F-H slot host tag mapping array\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + + /* Allocate memory for the array of pointers */ + n = cfg_data->num_tohost_data_slots; + + unifi_trace(card->ospriv, UDBG3, "Alloc to-host resources, %d slots.\n", n); + card->to_host_data = + (bulk_data_desc_t *)CsrMemAlloc(n * sizeof(bulk_data_desc_t)); + if (card->to_host_data == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for T-H bulk data array\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + /* Initialise to-host bulk data slots */ + for (i = 0; i < n; i++) + { + UNIFI_INIT_BULK_DATA(&card->to_host_data[i]); + } + + /* + * Initialise buffers for soft Q + */ + for (i = 0; i < UNIFI_SOFT_COMMAND_Q_LENGTH; i++) + { + for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) + { + UNIFI_INIT_BULK_DATA(&card->fh_command_q_body[i].bulkdata[r]); + } + } + + for (k = 0; k < UNIFI_NO_OF_TX_QS; k++) + { + for (i = 0; i < UNIFI_SOFT_TRAFFIC_Q_LENGTH; i++) + { + for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) + { + UNIFI_INIT_BULK_DATA(&card->fh_traffic_q_body[k][i].bulkdata[r]); + } + } + } + + card->memory_resources_allocated = 1; + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* card_allocate_memory_resources() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_free_bulk_data + * + * Free the data associated to a bulk data structure. + * + * Arguments: + * card Pointer to card struct + * bulk_data_slot Pointer to bulk data structure + * + * Returns: + * None. + * + * --------------------------------------------------------------------------- + */ +static void unifi_free_bulk_data(card_t *card, bulk_data_desc_t *bulk_data_slot) +{ + if (bulk_data_slot->data_length != 0) + { + unifi_net_data_free(card->ospriv, bulk_data_slot); + } +} /* unifi_free_bulk_data() */ + + +/* + * --------------------------------------------------------------------------- + * card_free_memory_resources + * + * Frees memory allocated for the from-host, to-host bulk data slots, + * soft queue buffers and bulk data buffers. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void card_free_memory_resources(card_t *card) +{ + func_enter(); + + unifi_trace(card->ospriv, UDBG1, "Freeing card memory resources.\n"); + + /* Clear our internal queues */ + unifi_cancel_pending_signals(card); + + + if (card->to_host_data) + { + CsrMemFree(card->to_host_data); + card->to_host_data = NULL; + } + + if (card->from_host_data) + { + CsrMemFree(card->from_host_data); + card->from_host_data = NULL; + } + + /* free the memory for slot host tag mapping array */ + if (card->fh_slot_host_tag_record) + { + CsrMemFree(card->fh_slot_host_tag_record); + card->fh_slot_host_tag_record = NULL; + } + + if (card->fh_buffer.buf) + { + CsrMemFree(card->fh_buffer.buf); + } + card->fh_buffer.ptr = card->fh_buffer.buf = NULL; + card->fh_buffer.bufsize = 0; + card->fh_buffer.count = 0; + + if (card->th_buffer.buf) + { + CsrMemFree(card->th_buffer.buf); + } + card->th_buffer.ptr = card->th_buffer.buf = NULL; + card->th_buffer.bufsize = 0; + card->th_buffer.count = 0; + + + card->memory_resources_allocated = 0; + + func_exit(); +} /* card_free_memory_resources() */ + + +static void card_init_soft_queues(card_t *card) +{ + CsrInt16 i; + + func_enter(); + + unifi_trace(card->ospriv, UDBG1, "Initialising internal signal queues.\n"); + /* Reset any state carried forward from a previous life */ + card->fh_command_queue.q_rd_ptr = 0; + card->fh_command_queue.q_wr_ptr = 0; + CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + "fh_cmd_q"); + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->fh_traffic_queue[i].q_rd_ptr = 0; + card->fh_traffic_queue[i].q_wr_ptr = 0; + CsrSnprintf(card->fh_traffic_queue[i].name, + UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); + } +#ifndef CSR_WIFI_HIP_TA_DISABLE + unifi_ta_sampling_init(card); +#endif + func_exit(); +} + + +/* + * --------------------------------------------------------------------------- + * unifi_cancel_pending_signals + * + * Free the signals and associated bulk data, pending in the core. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void unifi_cancel_pending_signals(card_t *card) +{ + CsrInt16 i, n, r; + func_enter(); + + unifi_trace(card->ospriv, UDBG1, "Canceling pending signals.\n"); + + if (card->to_host_data) + { + /* + * Free any bulk data buffers allocated for the t-h slots + * This will clear all buffers that did not make it to + * unifi_receive_event() before cancel was request. + */ + n = card->config_data.num_tohost_data_slots; + unifi_trace(card->ospriv, UDBG3, "Freeing to-host resources, %d slots.\n", n); + for (i = 0; i < n; i++) + { + unifi_free_bulk_data(card, &card->to_host_data[i]); + } + } + + /* + * If any of the from-host bulk data has reached the card->from_host_data + * but not UniFi, we need to free the buffers here. + */ + if (card->from_host_data) + { + /* Free any bulk data buffers allocated for the f-h slots */ + n = card->config_data.num_fromhost_data_slots; + unifi_trace(card->ospriv, UDBG3, "Freeing from-host resources, %d slots.\n", n); + for (i = 0; i < n; i++) + { + unifi_free_bulk_data(card, &card->from_host_data[i].bd); + } + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->dynamic_slot_data.from_host_used_slots[i] = 0; + card->dynamic_slot_data.from_host_max_slots[i] = 0; + card->dynamic_slot_data.from_host_reserved_slots[i] = 0; + } + } + + /* + * Free any bulk data buffers allocated in the soft queues. + * This covers the case where a bulk data pointer has reached the soft queue + * but not the card->from_host_data. + */ + unifi_trace(card->ospriv, UDBG3, "Freeing cmd q resources.\n"); + for (i = 0; i < UNIFI_SOFT_COMMAND_Q_LENGTH; i++) + { + for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) + { + unifi_free_bulk_data(card, &card->fh_command_q_body[i].bulkdata[r]); + } + } + + unifi_trace(card->ospriv, UDBG3, "Freeing traffic q resources.\n"); + for (n = 0; n < UNIFI_NO_OF_TX_QS; n++) + { + for (i = 0; i < UNIFI_SOFT_TRAFFIC_Q_LENGTH; i++) + { + for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) + { + unifi_free_bulk_data(card, &card->fh_traffic_q_body[n][i].bulkdata[r]); + } + } + } + + card_init_soft_queues(card); + + func_exit(); +} /* unifi_cancel_pending_signals() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_free_card + * + * Free the memory allocated for the card structure and buffers. + * + * Notes: + * The porting layer is responsible for freeing any mini-coredump buffers + * allocated when it called unifi_coredump_init(), by calling + * unifi_coredump_free() before calling this function. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void unifi_free_card(card_t *card) +{ + func_enter(); +#ifdef CSR_PRE_ALLOC_NET_DATA + prealloc_netdata_free(card); +#endif + /* Free any memory allocated. */ + card_free_memory_resources(card); + + /* Warn if caller didn't free coredump buffers */ + if (card->dump_buf) + { + unifi_error(card->ospriv, "Caller should call unifi_coredump_free()\n"); + unifi_coredump_free(card); /* free anyway to prevent memory leak */ + } + + CsrMemFree(card); + + func_exit(); +} /* unifi_free_card() */ + + +/* + * --------------------------------------------------------------------------- + * card_init_slots + * + * Allocate memory for host-side slot data and signal queues. + * + * Arguments: + * card Pointer to card object + * + * Returns: + * CSR error code. + * --------------------------------------------------------------------------- + */ +static CsrResult card_init_slots(card_t *card) +{ + CsrResult r; + CsrUint8 i; + + func_enter(); + + /* Allocate the buffers we need, only once. */ + if (card->memory_resources_allocated == 1) + { + card_free_memory_resources(card); + } + else + { + /* Initialise our internal command and traffic queues */ + card_init_soft_queues(card); + } + + r = card_allocate_memory_resources(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to allocate card memory resources.\n"); + card_free_memory_resources(card); + func_exit_r(r); + return r; + } + + if (card->sdio_ctrl_addr == 0) + { + unifi_error(card->ospriv, "Failed to find config struct!\n"); + func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* + * Set initial counts. + */ + + card->from_host_data_head = 0; + + /* Get initial signal counts from UniFi, in case it has not been reset. */ + { + CsrUint16 s; + + /* Get the from-host-signals-written count */ + r = unifi_card_read16(card, card->sdio_ctrl_addr + 0, &s); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read from-host sig written count\n"); + func_exit_r(r); + return r; + } + card->from_host_signals_w = (CsrInt16)s; + + /* Get the to-host-signals-written count */ + r = unifi_card_read16(card, card->sdio_ctrl_addr + 6, &s); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read to-host sig read count\n"); + func_exit_r(r); + return r; + } + card->to_host_signals_r = (CsrInt16)s; + } + + /* Set Initialised flag. */ + r = unifi_card_write16(card, card->init_flag_addr, 0x0001); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write initialised flag\n"); + func_exit_r(r); + return r; + } + + /* Dynamic queue reservation */ + CsrMemSet(&card->dynamic_slot_data, 0, sizeof(card_dynamic_slot_t)); + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->dynamic_slot_data.from_host_max_slots[i] = card->config_data.num_fromhost_data_slots - + UNIFI_RESERVED_COMMAND_SLOTS; + card->dynamic_slot_data.queue_stable[i] = FALSE; + } + + card->dynamic_slot_data.packets_interval = UNIFI_PACKETS_INTERVAL; + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* card_init_slots() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_set_udi_hook + * + * Registers the udi hook that reports the sent signals to the core. + * + * Arguments: + * card Pointer to the card context struct + * udi_fn Pointer to the callback function. + * + * Returns: + * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the card pointer is invalid, + * CSR_RESULT_SUCCESS on success. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_set_udi_hook(card_t *card, udi_func_t udi_fn) +{ + if (card == NULL) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + if (card->udi_hook == NULL) + { + card->udi_hook = udi_fn; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_set_udi_hook() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_remove_udi_hook + * + * Removes the udi hook that reports the sent signals from the core. + * + * Arguments: + * card Pointer to the card context struct + * udi_fn Pointer to the callback function. + * + * Returns: + * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the card pointer is invalid, + * CSR_RESULT_SUCCESS on success. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_remove_udi_hook(card_t *card, udi_func_t udi_fn) +{ + if (card == NULL) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + if (card->udi_hook == udi_fn) + { + card->udi_hook = NULL; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_remove_udi_hook() */ + + +static void CardReassignDynamicReservation(card_t *card) +{ + CsrUint8 i; + + func_enter(); + + unifi_trace(card->ospriv, UDBG5, "Packets Txed %d %d %d %d\n", + card->dynamic_slot_data.packets_txed[0], + card->dynamic_slot_data.packets_txed[1], + card->dynamic_slot_data.packets_txed[2], + card->dynamic_slot_data.packets_txed[3]); + + /* Clear reservation and recalculate max slots */ + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + card->dynamic_slot_data.queue_stable[i] = FALSE; + card->dynamic_slot_data.from_host_reserved_slots[i] = 0; + card->dynamic_slot_data.from_host_max_slots[i] = card->config_data.num_fromhost_data_slots - + UNIFI_RESERVED_COMMAND_SLOTS; + card->dynamic_slot_data.packets_txed[i] = 0; + + unifi_trace(card->ospriv, UDBG5, "CardReassignDynamicReservation: queue %d reserved %d Max %d\n", i, + card->dynamic_slot_data.from_host_reserved_slots[i], + card->dynamic_slot_data.from_host_max_slots[i]); + } + + card->dynamic_slot_data.total_packets_txed = 0; + func_exit(); +} + + +/* Algorithm to dynamically reserve slots. The logic is based mainly on the outstanding queue + * length. Slots are reserved for particular queues during an interval and cleared after the interval. + * Each queue has three associated variables.. a) used slots - the number of slots currently occupied + * by the queue b) reserved slots - number of slots reserved specifically for the queue c) max slots - total + * slots that this queue can actually use (may be higher than reserved slots and is dependent on reserved slots + * for other queues). + * This function is called when there are no slots available for a queue. It checks to see if there are enough + * unreserved slots sufficient for this request. If available these slots are reserved for the queue. + * If there are not enough unreserved slots, a fair share for each queue is calculated based on the total slots + * and the number of active queues (any queue with existing reservation is considered active). Queues needing + * less than their fair share are allowed to have the previously reserved slots. The remaining slots are + * distributed evenly among queues that need more than the fair share + * + * A better scheme would take current bandwidth per AC into consideration when reserving slots. An + * implementation scheme could consider the relative time/service period for slots in an AC. If the firmware + * services other ACs faster than a particular AC (packets wait in the slots longer) then it is fair to reserve + * less slots for the AC + */ +static void CardCheckDynamicReservation(card_t *card, unifi_TrafficQueue queue) +{ + CsrUint16 q_len, active_queues = 0, excess_queue_slots, div_extra_slots, + queue_fair_share, reserved_slots = 0, q, excess_need_queues = 0, unmovable_slots = 0; + CsrInt32 i; + q_t *sigq; + CsrUint16 num_data_slots = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; + + func_enter(); + + /* Calculate the pending queue length */ + sigq = &card->fh_traffic_queue[queue]; + q_len = CSR_WIFI_HIP_Q_SLOTS_USED(sigq); + + if (q_len <= card->dynamic_slot_data.from_host_reserved_slots[queue]) + { + unifi_trace(card->ospriv, UDBG5, "queue %d q_len %d already has that many reserved slots, exiting\n", queue, q_len); + func_exit(); + return; + } + + /* Upper limit */ + if (q_len > num_data_slots) + { + q_len = num_data_slots; + } + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + if (i != (CsrInt32)queue) + { + reserved_slots += card->dynamic_slot_data.from_host_reserved_slots[i]; + } + if ((i == (CsrInt32)queue) || (card->dynamic_slot_data.from_host_reserved_slots[i] > 0)) + { + active_queues++; + } + } + + unifi_trace(card->ospriv, UDBG5, "CardCheckDynamicReservation: queue %d q_len %d\n", queue, q_len); + unifi_trace(card->ospriv, UDBG5, "Active queues %d reserved slots on other queues %d\n", + active_queues, reserved_slots); + + if (reserved_slots + q_len <= num_data_slots) + { + card->dynamic_slot_data.from_host_reserved_slots[queue] = q_len; + if (q_len == num_data_slots) + { + /* This is the common case when just 1 stream is going */ + card->dynamic_slot_data.queue_stable[queue] = TRUE; + } + } + else + { + queue_fair_share = num_data_slots / active_queues; + unifi_trace(card->ospriv, UDBG5, "queue fair share %d\n", queue_fair_share); + + /* Evenly distribute slots among active queues */ + /* Find out the queues that need excess of fair share. Also find slots allocated + * to queues less than their fair share, these slots cannot be reallocated (unmovable slots) */ + + card->dynamic_slot_data.from_host_reserved_slots[queue] = q_len; + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + if (card->dynamic_slot_data.from_host_reserved_slots[i] > queue_fair_share) + { + excess_need_queues++; + } + else + { + unmovable_slots += card->dynamic_slot_data.from_host_reserved_slots[i]; + } + } + + unifi_trace(card->ospriv, UDBG5, "Excess need queues %d\n", excess_need_queues); + + /* Now find the slots per excess demand queue */ + excess_queue_slots = (num_data_slots - unmovable_slots) / excess_need_queues; + div_extra_slots = (num_data_slots - unmovable_slots) - excess_queue_slots * excess_need_queues; + for (i = UNIFI_NO_OF_TX_QS - 1; i >= 0; i--) + { + if (card->dynamic_slot_data.from_host_reserved_slots[i] > excess_queue_slots) + { + card->dynamic_slot_data.from_host_reserved_slots[i] = excess_queue_slots; + if (div_extra_slots > 0) + { + card->dynamic_slot_data.from_host_reserved_slots[i]++; + div_extra_slots--; + } + /* No more slots will be allocated to this queue during the current interval */ + card->dynamic_slot_data.queue_stable[i] = TRUE; + unifi_trace(card->ospriv, UDBG5, "queue stable %d\n", i); + } + } + } + + /* Redistribute max slots */ + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + reserved_slots = 0; + for (q = 0; q < UNIFI_NO_OF_TX_QS; q++) + { + if (i != q) + { + reserved_slots += card->dynamic_slot_data.from_host_reserved_slots[q]; + } + } + + card->dynamic_slot_data.from_host_max_slots[i] = num_data_slots - reserved_slots; + unifi_trace(card->ospriv, UDBG5, "queue %d reserved %d Max %d\n", i, + card->dynamic_slot_data.from_host_reserved_slots[i], + card->dynamic_slot_data.from_host_max_slots[i]); + } + + func_exit(); +} + + +/* + * --------------------------------------------------------------------------- + * CardClearFromHostDataSlot + * + * Clear a the given data slot, making it available again. + * + * Arguments: + * card Pointer to Card object + * slot Index of the signal slot to clear. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void CardClearFromHostDataSlot(card_t *card, const CsrInt16 slot) +{ + CsrUint8 queue = card->from_host_data[slot].queue; + const void *os_data_ptr = card->from_host_data[slot].bd.os_data_ptr; + + func_enter(); + + if (card->from_host_data[slot].bd.data_length == 0) + { + unifi_warning(card->ospriv, + "Surprise: request to clear an already free FH data slot: %d\n", + slot); + func_exit(); + return; + } + + if (os_data_ptr == NULL) + { + unifi_warning(card->ospriv, + "Clearing FH data slot %d: has null payload, len=%d\n", + slot, card->from_host_data[slot].bd.data_length); + } + + /* Free card->from_host_data[slot].bd.os_net_ptr here. */ + /* Mark slot as free by setting length to 0. */ + unifi_free_bulk_data(card, &card->from_host_data[slot].bd); + if (queue < UNIFI_NO_OF_TX_QS) + { + if (card->dynamic_slot_data.from_host_used_slots[queue] == 0) + { + unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n", + queue, + card->dynamic_slot_data.from_host_used_slots[queue]); + } + else + { + card->dynamic_slot_data.from_host_used_slots[queue]--; + } + card->dynamic_slot_data.packets_txed[queue]++; + card->dynamic_slot_data.total_packets_txed++; + if (card->dynamic_slot_data.total_packets_txed >= card->dynamic_slot_data.packets_interval) + { + CardReassignDynamicReservation(card); + } + } + + unifi_trace(card->ospriv, UDBG4, "CardClearFromHostDataSlot: slot %d recycled %p\n", slot, os_data_ptr); + + func_exit(); +} /* CardClearFromHostDataSlot() */ + + +CsrUint16 CardGetDataSlotSize(card_t *card) +{ + return card->config_data.data_slot_size; +} /* CardGetDataSlotSize() */ + + +/* + * --------------------------------------------------------------------------- + * CardGetFreeFromHostDataSlots + * + * Retrieve the number of from-host bulk data slots available. + * + * Arguments: + * card Pointer to the card context struct + * + * Returns: + * Number of free from-host bulk data slots. + * --------------------------------------------------------------------------- + */ +CsrUint16 CardGetFreeFromHostDataSlots(card_t *card) +{ + CsrUint16 i, n = 0; + + func_enter(); + + /* First two slots reserved for MLME */ + for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) + { + if (card->from_host_data[i].bd.data_length == 0) + { + /* Free slot */ + n++; + } + } + + func_exit(); + return n; +} /* CardGetFreeFromHostDataSlots() */ + + +/* + * --------------------------------------------------------------------------- + * CardAreAllFromHostDataSlotsEmpty + * + * Returns the state of from-host bulk data slots. + * + * Arguments: + * card Pointer to the card context struct + * + * Returns: + * 1 The from-host bulk data slots are all empty (available). + * 0 Some or all the from-host bulk data slots are in use. + * --------------------------------------------------------------------------- + */ +CsrUint16 CardAreAllFromHostDataSlotsEmpty(card_t *card) +{ + CsrUint16 i; + + for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) + { + if (card->from_host_data[i].bd.data_length != 0) + { + return 0; + } + } + + return 1; +} /* CardGetFreeFromHostDataSlots() */ + + +static CsrResult unifi_identify_hw(card_t *card) +{ + func_enter(); + + card->chip_id = card->sdio_if->sdioId.cardId; + card->function = card->sdio_if->sdioId.sdioFunction; + card->sdio_io_block_size = card->sdio_if->blockSize; + + /* If SDIO controller doesn't support byte mode CMD53, pad transfers to block sizes */ + card->sdio_io_block_pad = (card->sdio_if->features & CSR_SDIO_FEATURE_BYTE_MODE)?FALSE : TRUE; + + /* + * Setup the chip helper so that we can access the registers (and + * also tell what sub-type of HIP we should use). + */ + card->helper = ChipHelper_GetVersionSdio((CsrUint8)card->chip_id); + if (!card->helper) + { + unifi_error(card->ospriv, "Null ChipHelper\n"); + } + + unifi_info(card->ospriv, "Chip ID 0x%02X Function %u Block Size %u Name %s(%s)\n", + card->chip_id, card->function, card->sdio_io_block_size, + ChipHelper_MarketingName(card->helper), + ChipHelper_FriendlyName(card->helper)); + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* unifi_identify_hw() */ + + +static CsrResult unifi_prepare_hw(card_t *card) +{ + CsrResult r; + CsrResult csrResult; + enum unifi_host_state old_state = card->host_state; + + func_enter(); + + r = unifi_identify_hw(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to identify hw\n"); + func_exit_r(r); + return r; + } + + unifi_trace(card->ospriv, UDBG1, + "%s mode SDIO\n", card->sdio_io_block_pad?"Block" : "Byte"); + /* + * Chip must be a awake or blocks that are asleep may not get + * reset. We can only do this after we have read the chip_id. + */ + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + + if (old_state == UNIFI_HOST_STATE_TORPID) + { + /* Ensure the initial clock rate is set; if a reset occured when the chip was + * TORPID, unifi_set_host_state() may have raised it to MAX. + */ + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + func_exit_r(r); + return r; + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; + } + + /* + * The WLAN function must be enabled to access MAILBOX2 and DEBUG_RST + * registers. + */ + csrResult = CsrSdioFunctionEnable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + /* Can't enable WLAN function. Try resetting the SDIO block. */ + unifi_error(card->ospriv, "Failed to re-enable function %d.\n", card->function); + func_exit_r(r); + return r; + } + + /* + * Poke some registers to make sure the PLL has started, + * otherwise memory accesses are likely to fail. + */ + bootstrap_chip_hw(card); + + /* Try to read the chip version from register. */ + r = unifi_read_chip_version(card); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* unifi_prepare_hw() */ + + +static CsrResult unifi_read_chip_version(card_t *card) +{ + CsrUint32 gbl_chip_version; + CsrResult r; + CsrUint16 ver; + + func_enter(); + + gbl_chip_version = ChipHelper_GBL_CHIP_VERSION(card->helper); + + /* Try to read the chip version from register. */ + if (gbl_chip_version != 0) + { + r = unifi_read_direct16(card, gbl_chip_version * 2, &ver); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read GBL_CHIP_VERSION\n"); + func_exit_r(r); + return r; + } + card->chip_version = ver; + } + else + { + unifi_info(card->ospriv, "Unknown Chip ID, cannot locate GBL_CHIP_VERSION\n"); + r = CSR_RESULT_FAILURE; + } + + unifi_info(card->ospriv, "Chip Version 0x%04X\n", card->chip_version); + + func_exit_r(r); + return r; +} /* unifi_read_chip_version() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_reset_hardware + * + * Execute the UniFi reset sequence. + * + * Note: This may fail if the chip is going TORPID so retry at + * least once. + * + * Arguments: + * card - pointer to card context structure + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error otherwise. + * + * Notes: + * Some platforms (e.g. Windows Vista) do not allow access to registers + * that are necessary for a software soft reset. + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_reset_hardware(card_t *card) +{ + CsrResult r; + CsrUint16 new_block_size = UNIFI_IO_BLOCK_SIZE; + CsrResult csrResult; + + func_enter(); + + /* Errors returned by unifi_prepare_hw() are not critical at this point */ + r = unifi_prepare_hw(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + + /* First try SDIO controller reset, which may power cycle the UniFi, assert + * its reset line, or not be implemented depending on the platform. + */ + unifi_info(card->ospriv, "Calling CsrSdioHardReset\n"); + csrResult = CsrSdioHardReset(card->sdio_if); + if (csrResult == CSR_RESULT_SUCCESS) + { + unifi_info(card->ospriv, "CsrSdioHardReset succeeded on reseting UniFi\n"); + r = unifi_prepare_hw(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_prepare_hw failed after hard reset\n"); + func_exit_r(r); + return r; + } + } + else if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + else + { + /* Falling back to software hard reset methods */ + unifi_info(card->ospriv, "Falling back to software hard reset\n"); + r = unifi_card_hard_reset(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "software hard reset failed\n"); + func_exit_r(r); + return r; + } + + /* If we fell back to unifi_card_hard_reset() methods, chip version may + * not have been read. (Note in the unlikely event that it is zero, + * it will be harmlessly read again) + */ + if (card->chip_version == 0) + { + r = unifi_read_chip_version(card); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + } + } + +#ifdef CSR_WIFI_HIP_SDIO_BLOCK_SIZE + new_block_size = CSR_WIFI_HIP_SDIO_BLOCK_SIZE; +#endif + + /* After hard reset, we need to restore the SDIO block size */ + csrResult = CsrSdioBlockSizeSet(card->sdio_if, new_block_size); + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + + /* Warn if a different block size was achieved by the transport */ + if (card->sdio_if->blockSize != new_block_size) + { + unifi_info(card->ospriv, + "Actually got block size %d\n", card->sdio_if->blockSize); + } + + /* sdio_io_block_size always needs be updated from the achieved block size, + * as it is used by the OS layer to allocate memory in unifi_net_malloc(). + * Controllers which don't support block mode (e.g. CSPI) will report a + * block size of zero. + */ + if (card->sdio_if->blockSize == 0) + { + unifi_info(card->ospriv, "Block size 0, block mode not available\n"); + + /* Set sdio_io_block_size to 1 so that unifi_net_data_malloc() has a + * sensible rounding value. Elsewhere padding will already be + * disabled because the controller supports byte mode. + */ + card->sdio_io_block_size = 1; + + /* Controller features must declare support for byte mode */ + if (!(card->sdio_if->features & CSR_SDIO_FEATURE_BYTE_MODE)) + { + unifi_error(card->ospriv, "Requires byte mode\n"); + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + } + else + { + /* Padding will be enabled if CSR_SDIO_FEATURE_BYTE_MODE isn't set */ + card->sdio_io_block_size = card->sdio_if->blockSize; + } + + + func_exit_r(r); + return r; +} /* unifi_reset_hardware() */ + + +/* + * --------------------------------------------------------------------------- + * card_reset_method_io_enable + * + * Issue a hard reset to the hw writing the IO_ENABLE. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * 0 on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred or if a response + * was not seen in the expected time + * --------------------------------------------------------------------------- + */ +static CsrResult card_reset_method_io_enable(card_t *card) +{ + CsrResult r; + CsrResult csrResult; + + func_enter(); + + /* + * This resets only function 1, so should be used in + * preference to the method below (CSR_FUNC_EN) + */ + unifi_trace(card->ospriv, UDBG1, "Hard reset (IO_ENABLE)\n"); + + csrResult = CsrSdioFunctionDisable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + unifi_warning(card->ospriv, "SDIO error writing IO_ENABLE: %d\n", r); + } + else + { + /* Delay here to let the reset take affect. */ + CsrThreadSleep(RESET_SETTLE_DELAY); + + r = card_wait_for_unifi_to_disable(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + + if (r == CSR_RESULT_SUCCESS) + { + r = card_wait_for_unifi_to_reset(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + } + } + + if (r != CSR_RESULT_SUCCESS) + { + unifi_trace(card->ospriv, UDBG1, "Hard reset (CSR_FUNC_EN)\n"); + + r = sdio_write_f0(card, SDIO_CSR_FUNC_EN, 0); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_warning(card->ospriv, "SDIO error writing SDIO_CSR_FUNC_EN: %d\n", r); + func_exit_r(r); + return r; + } + else + { + /* Delay here to let the reset take affect. */ + CsrThreadSleep(RESET_SETTLE_DELAY); + + r = card_wait_for_unifi_to_reset(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + } + } + + if (r != CSR_RESULT_SUCCESS) + { + unifi_warning(card->ospriv, "card_reset_method_io_enable failed to reset UniFi\n"); + } + + func_exit(); + return r; +} /* card_reset_method_io_enable() */ + + +/* + * --------------------------------------------------------------------------- + * card_reset_method_dbg_reset + * + * Issue a hard reset to the hw writing the DBG_RESET. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred or if a response + * was not seen in the expected time + * --------------------------------------------------------------------------- + */ +static CsrResult card_reset_method_dbg_reset(card_t *card) +{ + CsrResult r; + + func_enter(); + + /* + * Prepare UniFi for h/w reset + */ + if (card->host_state == UNIFI_HOST_STATE_TORPID) + { + r = unifi_set_host_state(card, UNIFI_HOST_STATE_DROWSY); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to set UNIFI_HOST_STATE_DROWSY\n"); + func_exit_r(r); + return r; + } + CsrThreadSleep(5); + } + + r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Can't stop processors\n"); + func_exit(); + return r; + } + + unifi_trace(card->ospriv, UDBG1, "Hard reset (DBG_RESET)\n"); + + /* + * This register write may fail. The debug reset resets + * parts of the Function 0 sections of the chip, and + * therefore the response cannot be sent back to the host. + */ + r = unifi_write_direct_8_or_16(card, ChipHelper_DBG_RESET(card->helper) * 2, 1); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_warning(card->ospriv, "SDIO error writing DBG_RESET: %d\n", r); + func_exit_r(r); + return r; + } + + /* Delay here to let the reset take affect. */ + CsrThreadSleep(RESET_SETTLE_DELAY); + + r = card_wait_for_unifi_to_reset(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_warning(card->ospriv, "card_reset_method_dbg_reset failed to reset UniFi\n"); + } + + func_exit(); + return r; +} /* card_reset_method_dbg_reset() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_hard_reset + * + * Issue reset to hardware, by writing to registers on the card. + * Power to the card is preserved. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred or if a response + * was not seen in the expected time + * --------------------------------------------------------------------------- + */ +CsrResult unifi_card_hard_reset(card_t *card) +{ + CsrResult r; + const struct chip_helper_reset_values *init_data; + CsrUint32 chunks; + + func_enter(); + + /* Clear cache of page registers */ + card->proc_select = (CsrUint32)(-1); + card->dmem_page = (CsrUint32)(-1); + card->pmem_page = (CsrUint32)(-1); + + /* + * We need to have a valid card->helper before we use software hard reset. + * If unifi_identify_hw() fails to get the card ID, it probably means + * that there is no way to talk to the h/w. + */ + r = unifi_identify_hw(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_card_hard_reset failed to identify h/w\n"); + func_exit(); + return r; + } + + /* Search for some reset code. */ + chunks = ChipHelper_HostResetSequence(card->helper, &init_data); + if (chunks != 0) + { + unifi_error(card->ospriv, + "Hard reset (Code download) is unsupported\n"); + + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + /* The HIP spec considers this a bus-specific reset. + * This resets only function 1, so should be used in + * preference to the method below (CSR_FUNC_EN) + * If this method fails, it means that the f/w is probably + * not running. In this case, try the DBG_RESET method. + */ + r = card_reset_method_io_enable(card); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r == CSR_RESULT_SUCCESS) + { + func_exit(); + return r; + } + } + + /* Software hard reset */ + r = card_reset_method_dbg_reset(card); + + func_exit_r(r); + return r; +} /* unifi_card_hard_reset() */ + + +/* + * --------------------------------------------------------------------------- + * + * CardGenInt + * + * Prod the card. + * This function causes an internal interrupt to be raised in the + * UniFi chip. It is used to signal the firmware that some action has + * been completed. + * The UniFi Host Interface asks that the value used increments for + * debugging purposes. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred or if a response + * was not seen in the expected time + * --------------------------------------------------------------------------- + */ +CsrResult CardGenInt(card_t *card) +{ + CsrResult r; + + func_enter(); + + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + r = sdio_write_f0(card, SDIO_CSR_FROM_HOST_SCRATCH0, + (CsrUint8)card->unifi_interrupt_seq); + } + else + { + r = unifi_write_direct_8_or_16(card, + ChipHelper_SHARED_IO_INTERRUPT(card->helper) * 2, + (CsrUint8)card->unifi_interrupt_seq); + } + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error writing UNIFI_SHARED_IO_INTERRUPT: %d\n", r); + func_exit_r(r); + return r; + } + + card->unifi_interrupt_seq++; + + func_exit(); + return CSR_RESULT_SUCCESS; +} /* CardGenInt() */ + + +/* + * --------------------------------------------------------------------------- + * CardEnableInt + * + * Enable the outgoing SDIO interrupt from UniFi to the host. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred, + * --------------------------------------------------------------------------- + */ +CsrResult CardEnableInt(card_t *card) +{ + CsrResult r; + CsrUint8 int_enable; + + r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); + return r; + } + + int_enable |= (1 << card->function) | UNIFI_SD_INT_ENABLE_IENM; + + r = sdio_write_f0(card, SDIO_INT_ENABLE, int_enable); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error writing SDIO_INT_ENABLE\n"); + return r; + } + + return CSR_RESULT_SUCCESS; +} /* CardEnableInt() */ + + +/* + * --------------------------------------------------------------------------- + * CardDisableInt + * + * Disable the outgoing SDIO interrupt from UniFi to the host. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred, + * --------------------------------------------------------------------------- + */ +CsrResult CardDisableInt(card_t *card) +{ + CsrResult r; + CsrUint8 int_enable; + + r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); + return r; + } + + int_enable &= ~(1 << card->function); + + r = sdio_write_f0(card, SDIO_INT_ENABLE, int_enable); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error writing SDIO_INT_ENABLE\n"); + return r; + } + + return CSR_RESULT_SUCCESS; +} /* CardDisableInt() */ + + +/* + * --------------------------------------------------------------------------- + * CardPendingInt + * + * Determine whether UniFi is currently asserting the SDIO interrupt + * request. + * + * Arguments: + * card Pointer to Card object + * pintr Pointer to location to write interrupt status, + * TRUE if interrupt pending, + * FALSE if no interrupt pending. + * Returns: + * CSR_RESULT_SUCCESS interrupt status read successfully + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred, + * --------------------------------------------------------------------------- + */ +CsrResult CardPendingInt(card_t *card, CsrBool *pintr) +{ + CsrResult r; + CsrUint8 pending; + + *pintr = FALSE; + + r = sdio_read_f0(card, SDIO_INT_PENDING, &pending); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error reading SDIO_INT_PENDING\n"); + return r; + } + + *pintr = (pending & (1 << card->function))?TRUE : FALSE; + + return CSR_RESULT_SUCCESS; +} /* CardPendingInt() */ + + +/* + * --------------------------------------------------------------------------- + * CardClearInt + * + * Clear the UniFi SDIO interrupt request. + * + * Arguments: + * card Pointer to Card object + * + * Returns: + * CSR_RESULT_SUCCESS if pending interrupt was cleared, or no pending interrupt. + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred, + * --------------------------------------------------------------------------- + */ +CsrResult CardClearInt(card_t *card) +{ + CsrResult r; + CsrBool intr; + + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + /* CardPendingInt() sets intr, if there is a pending interrupt */ + r = CardPendingInt(card, &intr); + if (intr == FALSE) + { + return r; + } + + r = sdio_write_f0(card, SDIO_CSR_HOST_INT_CLEAR, 1); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error writing SDIO_CSR_HOST_INT_CLEAR\n"); + } + } + else + { + r = unifi_write_direct_8_or_16(card, + ChipHelper_SDIO_HOST_INT(card->helper) * 2, + 0); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error writing UNIFI_SDIO_HOST_INT\n"); + } + } + + return r; +} /* CardClearInt() */ + + +/* + * --------------------------------------------------------------------------- + * CardIntEnabled + * + * Determine whether UniFi is currently asserting the SDIO interrupt + * request. + * + * Arguments: + * card Pointer to Card object + * enabled Pointer to location to write interrupt enable status, + * TRUE if interrupts enabled, + * FALSE if interupts disabled. + * + * Returns: + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred, + * --------------------------------------------------------------------------- + */ +CsrResult CardIntEnabled(card_t *card, CsrBool *enabled) +{ + CsrResult r; + CsrUint8 int_enable; + + r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); + return r; + } + + *enabled = (int_enable & (1 << card->function))?TRUE : FALSE; + + return CSR_RESULT_SUCCESS; +} /* CardIntEnabled() */ + + +/* + * --------------------------------------------------------------------------- + * CardWriteBulkData + * Allocate slot in the pending bulkdata arrays and assign it to a signal's + * bulkdata reference. The slot is then ready for UniFi's bulkdata commands + * to transfer the data to/from the host. + * + * Arguments: + * card Pointer to Card object + * csptr Pending signal pointer, including bulkdata ref + * queue Traffic queue that this signal is using + * + * Returns: + * CSR_RESULT_SUCCESS if a free slot was assigned + * CSR_RESULT_FAILURE if no slot was available + * --------------------------------------------------------------------------- + */ +CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQueue queue) +{ + CsrUint16 i, slots[UNIFI_MAX_DATA_REFERENCES], j = 0; + CsrUint8 *packed_sigptr, num_slots_required = 0; + bulk_data_desc_t *bulkdata = csptr->bulkdata; + CsrInt16 h, nslots; + + func_enter(); + + /* Count the number of slots required */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + if (bulkdata[i].data_length != 0) + { + num_slots_required++; + } + } + + /* Get the slot numbers */ + if (num_slots_required != 0) + { + /* Last 2 slots for MLME */ + if (queue == UNIFI_TRAFFIC_Q_MLME) + { + h = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; + for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) + { + if (card->from_host_data[h].bd.data_length == 0) + { + /* Free data slot, claim it */ + slots[j++] = h; + if (j == num_slots_required) + { + break; + } + } + + if (++h >= card->config_data.num_fromhost_data_slots) + { + h = 0; + } + } + } + else + { + if (card->dynamic_slot_data.from_host_used_slots[queue] + < card->dynamic_slot_data.from_host_max_slots[queue]) + { + /* Data commands get a free slot only after a few checks */ + nslots = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; + + h = card->from_host_data_head; + + for (i = 0; i < nslots; i++) + { + if (card->from_host_data[h].bd.data_length == 0) + { + /* Free data slot, claim it */ + slots[j++] = h; + if (j == num_slots_required) + { + break; + } + } + + if (++h >= nslots) + { + h = 0; + } + } + card->from_host_data_head = h; + } + } + + /* Required number of slots are not available, bail out */ + if (j != num_slots_required) + { + unifi_trace(card->ospriv, UDBG5, "CardWriteBulkData: didn't find free slot/s\n"); + + /* If we haven't already reached the stable state we can ask for reservation */ + if ((queue != UNIFI_TRAFFIC_Q_MLME) && (card->dynamic_slot_data.queue_stable[queue] == FALSE)) + { + CardCheckDynamicReservation(card, queue); + } + + for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) + { + unifi_trace(card->ospriv, UDBG5, "fh data slot %d: %d\n", i, card->from_host_data[i].bd.data_length); + } + func_exit(); + return CSR_RESULT_FAILURE; + } + } + + packed_sigptr = csptr->sigbuf; + + /* Fill in the slots with data */ + j = 0; + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + if (bulkdata[i].data_length == 0) + { + /* Zero-out the DATAREF in the signal */ + SET_PACKED_DATAREF_SLOT(packed_sigptr, i, 0); + SET_PACKED_DATAREF_LEN(packed_sigptr, i, 0); + } + else + { + /* + * Fill in the slot number in the SIGNAL structure but + * preserve the offset already in there + */ + SET_PACKED_DATAREF_SLOT(packed_sigptr, i, slots[j] | (((CsrUint16)packed_sigptr[SIZEOF_SIGNAL_HEADER + (i * SIZEOF_DATAREF) + 1]) << 8)); + SET_PACKED_DATAREF_LEN(packed_sigptr, i, bulkdata[i].data_length); + + /* Do not copy the data, just store the information to them */ + card->from_host_data[slots[j]].bd.os_data_ptr = bulkdata[i].os_data_ptr; + card->from_host_data[slots[j]].bd.os_net_buf_ptr = bulkdata[i].os_net_buf_ptr; + card->from_host_data[slots[j]].bd.data_length = bulkdata[i].data_length; + card->from_host_data[slots[j]].bd.net_buf_length = bulkdata[i].net_buf_length; + card->from_host_data[slots[j]].queue = queue; + + unifi_trace(card->ospriv, UDBG4, "CardWriteBulkData sig=0x%x, fh slot %d = %p\n", + GET_SIGNAL_ID(packed_sigptr), i, bulkdata[i].os_data_ptr); + + /* Sanity-check that the bulk data desc being assigned to the slot + * actually has a payload. + */ + if (!bulkdata[i].os_data_ptr) + { + unifi_error(card->ospriv, "Assign null os_data_ptr (len=%d) fh slot %d, i=%d, q=%d, sig=0x%x", + bulkdata[i].data_length, slots[j], i, queue, GET_SIGNAL_ID(packed_sigptr)); + } + + j++; + if (queue < UNIFI_NO_OF_TX_QS) + { + card->dynamic_slot_data.from_host_used_slots[queue]++; + } + } + } + + func_exit(); + + return CSR_RESULT_SUCCESS; +} /* CardWriteBulkData() */ + + +/* + * --------------------------------------------------------------------------- + * card_find_data_slot + * + * Dereference references to bulk data slots into pointers to real data. + * + * Arguments: + * card Pointer to the card struct. + * slot Slot number from a signal structure + * + * Returns: + * Pointer to entry in bulk_data_slot array. + * --------------------------------------------------------------------------- + */ +bulk_data_desc_t* card_find_data_slot(card_t *card, CsrInt16 slot) +{ + CsrInt16 sn; + bulk_data_desc_t *bd; + + sn = slot & 0x7FFF; + + /* ?? check sanity of slot number ?? */ + + if (slot & SLOT_DIR_TO_HOST) + { + bd = &card->to_host_data[sn]; + } + else + { + bd = &card->from_host_data[sn].bd; + } + + return bd; +} /* card_find_data_slot() */ + + +/* + * --------------------------------------------------------------------------- + * firmware_present_in_flash + * + * Probe for external Flash that looks like it might contain firmware. + * + * If Flash is not present, reads always return 0x0008. + * If Flash is present, but empty, reads return 0xFFFF. + * Anything else is considered to be firmware. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS firmware is present in ROM or flash + * CSR_WIFI_HIP_RESULT_NOT_FOUND firmware is not present in ROM or flash + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred + * --------------------------------------------------------------------------- + */ +static CsrResult firmware_present_in_flash(card_t *card) +{ + CsrResult r; + CsrUint16 m1, m5; + + if (ChipHelper_HasRom(card->helper)) + { + return CSR_RESULT_SUCCESS; + } + if (!ChipHelper_HasFlash(card->helper)) + { + return CSR_WIFI_HIP_RESULT_NOT_FOUND; + } + + /* + * Examine the Flash locations that are the power-on default reset + * vectors of the XAP processors. + * These are words 1 and 5 in Flash. + */ + r = unifi_card_read16(card, UNIFI_MAKE_GP(EXT_FLASH, 2), &m1); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + r = unifi_card_read16(card, UNIFI_MAKE_GP(EXT_FLASH, 10), &m5); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + /* Check for uninitialised/missing flash */ + if ((m1 == 0x0008) || (m1 == 0xFFFF) || + (m1 == 0x0004) || (m5 == 0x0004) || + (m5 == 0x0008) || (m5 == 0xFFFF)) + { + return CSR_WIFI_HIP_RESULT_NOT_FOUND; + } + + return CSR_RESULT_SUCCESS; +} /* firmware_present_in_flash() */ + + +/* + * --------------------------------------------------------------------------- + * bootstrap_chip_hw + * + * Perform chip specific magic to "Get It Working" TM. This will + * increase speed of PLLs in analogue and maybe enable some + * on-chip regulators. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void bootstrap_chip_hw(card_t *card) +{ + const struct chip_helper_init_values *vals; + CsrUint32 i, len; + void *sdio = card->sdio_if; + CsrResult csrResult; + + len = ChipHelper_ClockStartupSequence(card->helper, &vals); + if (len != 0) + { + for (i = 0; i < len; i++) + { + csrResult = CsrSdioWrite16(sdio, vals[i].addr * 2, vals[i].value); + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_warning(card->ospriv, "Failed to write bootstrap value %d\n", i); + /* Might not be fatal */ + } + + CsrThreadSleep(1); + } + } +} /* bootstrap_chip_hw() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_stop_processor + * + * Stop the UniFi XAP processors. + * + * Arguments: + * card Pointer to card struct + * which One of UNIFI_PROC_MAC, UNIFI_PROC_PHY, UNIFI_PROC_BOTH + * + * Returns: + * CSR_RESULT_SUCCESS if successful, or CSR error code + * --------------------------------------------------------------------------- + */ +CsrResult unifi_card_stop_processor(card_t *card, enum unifi_dbg_processors_select which) +{ + CsrResult r = CSR_RESULT_SUCCESS; + CsrUint8 status; + CsrInt16 retry = 100; + + while (retry--) + { + /* Select both XAPs */ + r = unifi_set_proc_select(card, which); + if (r != CSR_RESULT_SUCCESS) + { + break; + } + + /* Stop processors */ + r = unifi_write_direct16(card, ChipHelper_DBG_EMU_CMD(card->helper) * 2, 2); + if (r != CSR_RESULT_SUCCESS) + { + break; + } + + /* Read status */ + r = unifi_read_direct_8_or_16(card, + ChipHelper_DBG_HOST_STOP_STATUS(card->helper) * 2, + &status); + if (r != CSR_RESULT_SUCCESS) + { + break; + } + + if ((status & 1) == 1) + { + /* Success! */ + return CSR_RESULT_SUCCESS; + } + + /* Processors didn't stop, try again */ + } + + if (r != CSR_RESULT_SUCCESS) + { + /* An SDIO error occurred */ + unifi_error(card->ospriv, "Failed to stop processors: SDIO error\n"); + } + else + { + /* If we reach here, we didn't the status in time. */ + unifi_error(card->ospriv, "Failed to stop processors: timeout waiting for stopped status\n"); + r = CSR_RESULT_FAILURE; + } + + return r; +} /* unifi_card_stop_processor() */ + + +/* + * --------------------------------------------------------------------------- + * card_start_processor + * + * Start the UniFi XAP processors. + * + * Arguments: + * card Pointer to card struct + * which One of UNIFI_PROC_MAC, UNIFI_PROC_PHY, UNIFI_PROC_BOTH + * + * Returns: + * CSR_RESULT_SUCCESS or CSR error code + * --------------------------------------------------------------------------- + */ +CsrResult card_start_processor(card_t *card, enum unifi_dbg_processors_select which) +{ + CsrResult r; + + /* Select both XAPs */ + r = unifi_set_proc_select(card, which); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "unifi_set_proc_select failed: %d.\n", r); + return r; + } + + + r = unifi_write_direct_8_or_16(card, + ChipHelper_DBG_EMU_CMD(card->helper) * 2, 8); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + r = unifi_write_direct_8_or_16(card, + ChipHelper_DBG_EMU_CMD(card->helper) * 2, 0); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + return CSR_RESULT_SUCCESS; +} /* card_start_processor() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_set_interrupt_mode + * + * Configure the interrupt processing mode used by the HIP + * + * Arguments: + * card Pointer to card struct + * mode Interrupt mode to apply + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +void unifi_set_interrupt_mode(card_t *card, CsrUint32 mode) +{ + if (mode == CSR_WIFI_INTMODE_RUN_BH_ONCE) + { + unifi_info(card->ospriv, "Scheduled interrupt mode"); + } + card->intmode = mode; +} /* unifi_set_interrupt_mode() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_start_processors + * + * Start all UniFi XAP processors. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on error + * --------------------------------------------------------------------------- + */ +CsrResult unifi_start_processors(card_t *card) +{ + return card_start_processor(card, UNIFI_PROC_BOTH); +} /* unifi_start_processors() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_request_max_sdio_clock + * + * Requests that the maximum SDIO clock rate is set at the next suitable + * opportunity (e.g. when the BH next runs, so as not to interfere with + * any current operation). + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +void unifi_request_max_sdio_clock(card_t *card) +{ + card->request_max_clock = 1; +} /* unifi_request_max_sdio_clock() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_set_host_state + * + * Set the host deep-sleep state. + * + * If transitioning to TORPID, the SDIO driver will be notified + * that the SD bus will be unused (idle) and conversely, when + * transitioning from TORPID that the bus will be used (active). + * + * Arguments: + * card Pointer to card struct + * state New deep-sleep state. + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected + * CSR_RESULT_FAILURE if an SDIO error occurred + * + * Notes: + * We need to reduce the SDIO clock speed before trying to wake up the + * chip. Actually, in the implementation below we reduce the clock speed + * not just before we try to wake up the chip, but when we put the chip to + * deep sleep. This means that if the f/w wakes up on its' own, we waste + * a reduce/increace cycle. However, trying to eliminate this overhead is + * proved difficult, as the current state machine in the HIP lib does at + * least a CMD52 to disable the interrupts before we configure the host + * state. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_set_host_state(card_t *card, enum unifi_host_state state) +{ + CsrResult r = CSR_RESULT_SUCCESS; + CsrResult csrResult; + static const CsrCharString *const states[] = { + "AWAKE", "DROWSY", "TORPID" + }; + static const CsrUint8 state_csr_host_wakeup[] = { + 1, 3, 0 + }; + static const CsrUint8 state_io_abort[] = { + 0, 2, 3 + }; + + unifi_trace(card->ospriv, UDBG4, "State %s to %s\n", + states[card->host_state], states[state]); + + if (card->host_state == UNIFI_HOST_STATE_TORPID) + { + CsrSdioFunctionActive(card->sdio_if); + } + + /* Write the new state to UniFi. */ + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + r = sdio_write_f0(card, SDIO_CSR_HOST_WAKEUP, + (CsrUint8)((card->function << 4) | state_csr_host_wakeup[state])); + } + else + { + r = sdio_write_f0(card, SDIO_IO_ABORT, state_io_abort[state]); + } + + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write UniFi deep sleep state\n"); + } + else + { + /* + * If the chip was in state TORPID then we can now increase + * the maximum bus clock speed. + */ + if (card->host_state == UNIFI_HOST_STATE_TORPID) + { + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, + UNIFI_SDIO_CLOCK_MAX_HZ); + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + /* Non-fatal error */ + if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + unifi_warning(card->ospriv, + "Failed to increase the SDIO clock speed\n"); + } + else + { + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_MAX_HZ; + } + } + + /* + * Cache the current state in the card structure to avoid + * unnecessary SDIO reads. + */ + card->host_state = state; + + if (state == UNIFI_HOST_STATE_TORPID) + { + /* + * If the chip is now in state TORPID then we must now decrease + * the maximum bus clock speed. + */ + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, + UNIFI_SDIO_CLOCK_SAFE_HZ); + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + unifi_warning(card->ospriv, + "Failed to decrease the SDIO clock speed\n"); + } + else + { + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; + } + CsrSdioFunctionIdle(card->sdio_if); + } + } + + return r; +} /* unifi_set_host_state() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_info + * + * Update the card information data structure + * + * Arguments: + * card Pointer to card struct + * card_info Pointer to info structure to update + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +void unifi_card_info(card_t *card, card_info_t *card_info) +{ + card_info->chip_id = card->chip_id; + card_info->chip_version = card->chip_version; + card_info->fw_build = card->build_id; + card_info->fw_hip_version = card->config_data.version; + card_info->sdio_block_size = card->sdio_io_block_size; +} /* unifi_card_info() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_check_io_status + * + * Check UniFi for spontaneous reset and pending interrupt. + * + * Arguments: + * card Pointer to card struct + * status Pointer to location to write chip status: + * 0 if UniFi is running, and no interrupt pending + * 1 if UniFi has spontaneously reset + * 2 if there is a pending interrupt + * Returns: + * CSR_RESULT_SUCCESS if OK, or CSR error + * --------------------------------------------------------------------------- + */ +CsrResult unifi_check_io_status(card_t *card, CsrInt32 *status) +{ + CsrUint8 io_en; + CsrResult r; + CsrBool pending; + + *status = 0; + + r = sdio_read_f0(card, SDIO_IO_ENABLE, &io_en); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read SDIO_IO_ENABLE to check for spontaneous reset\n"); + return r; + } + + if ((io_en & (1 << card->function)) == 0) + { + CsrInt32 fw_count; + *status = 1; + unifi_error(card->ospriv, "UniFi has spontaneously reset.\n"); + + /* + * These reads are very likely to fail. We want to know if the function is really + * disabled or the SDIO driver just returns rubbish. + */ + fw_count = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); + if (fw_count < 0) + { + unifi_error(card->ospriv, "Failed to read to-host sig written count\n"); + } + else + { + unifi_error(card->ospriv, "thsw: %u (driver thinks is %u)\n", + fw_count, card->to_host_signals_w); + } + fw_count = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); + if (fw_count < 0) + { + unifi_error(card->ospriv, "Failed to read from-host sig read count\n"); + } + else + { + unifi_error(card->ospriv, "fhsr: %u (driver thinks is %u)\n", + fw_count, card->from_host_signals_r); + } + + return r; + } + + unifi_info(card->ospriv, "UniFi function %d is enabled.\n", card->function); + + /* See if we missed an SDIO interrupt */ + r = CardPendingInt(card, &pending); + if (pending) + { + unifi_error(card->ospriv, "There is an unhandled pending interrupt.\n"); + *status = 2; + return r; + } + + return r; +} /* unifi_check_io_status() */ + + +void unifi_get_hip_qos_info(card_t *card, unifi_HipQosInfo *hipqosinfo) +{ + CsrInt32 count_fhr; + CsrInt16 t; + CsrUint32 occupied_fh; + + q_t *sigq; + CsrUint16 nslots, i; + + CsrMemSet(hipqosinfo, 0, sizeof(unifi_HipQosInfo)); + + nslots = card->config_data.num_fromhost_data_slots; + + for (i = 0; i < nslots; i++) + { + if (card->from_host_data[i].bd.data_length == 0) + { + hipqosinfo->free_fh_bulkdata_slots++; + } + } + + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + sigq = &card->fh_traffic_queue[i]; + t = sigq->q_wr_ptr - sigq->q_rd_ptr; + if (t < 0) + { + t += sigq->q_length; + } + hipqosinfo->free_fh_sig_queue_slots[i] = (sigq->q_length - t) - 1; + } + + count_fhr = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); + if (count_fhr < 0) + { + unifi_error(card->ospriv, "Failed to read from-host sig read count - %d\n", count_fhr); + hipqosinfo->free_fh_fw_slots = 0xfa; + return; + } + + occupied_fh = (card->from_host_signals_w - count_fhr) % 128; + + hipqosinfo->free_fh_fw_slots = (CsrUint16)(card->config_data.num_fromhost_sig_frags - occupied_fh); +} + + + +CsrResult ConvertCsrSdioToCsrHipResult(card_t *card, CsrResult csrResult) +{ + CsrResult r = CSR_RESULT_FAILURE; + + switch (csrResult) + { + case CSR_RESULT_SUCCESS: + r = CSR_RESULT_SUCCESS; + break; + /* Timeout errors */ + case CSR_SDIO_RESULT_TIMEOUT: + /* Integrity errors */ + case CSR_SDIO_RESULT_CRC_ERROR: + r = CSR_RESULT_FAILURE; + break; + case CSR_SDIO_RESULT_NO_DEVICE: + r = CSR_WIFI_HIP_RESULT_NO_DEVICE; + break; + case CSR_SDIO_RESULT_INVALID_VALUE: + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + break; + case CSR_RESULT_FAILURE: + r = CSR_RESULT_FAILURE; + break; + default: + unifi_warning(card->ospriv, "Unrecognised csrResult error code: %d\n", csrResult); + break; + } + + return r; +} /* ConvertCsrSdioToCsrHipResult() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.h b/drivers/staging/csr/csr_wifi_hip_card_sdio.h new file mode 100644 index 000000000000..4481d81eee48 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.h @@ -0,0 +1,702 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * + * FILE: csr_wifi_hip_card_sdio.h + * + * PURPOSE: + * Internal header for Card API for SDIO. + * --------------------------------------------------------------------------- + */ +#ifndef __CARD_SDIO_H__ +#define __CARD_SDIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifi_udi.h" +#include "csr_wifi_hip_unifihw.h" +#include "csr_wifi_hip_unifiversion.h" +#ifndef CSR_WIFI_HIP_TA_DISABLE +#include "csr_wifi_hip_ta_sampling.h" +#endif +#include "csr_wifi_hip_xbv.h" +#include "csr_wifi_hip_chiphelper.h" + + +/* + * + * Configuration items. + * Which of these should go in a platform unifi_config.h file? + * + */ + +/* + * When the traffic queues contain more signals than there is space for on + * UniFi, a limiting algorithm comes into play. + * If a traffic queue has enough slots free to buffer more traffic from the + * network stack, then the following check is applied. The number of free + * slots is RESUME_XMIT_THRESHOLD. + */ +#define RESUME_XMIT_THRESHOLD 4 + + +/* + * When reading signals from UniFi, the host processes pending all signals + * and then acknowledges them together in a single write to update the + * to-host-chunks-read location. + * When there is more than one bulk data transfer (e.g. one received data + * packet and a request for the payload data of a transmitted packet), the + * update can be delayed significantly. This ties up resources on chip. + * + * To remedy this problem, to-host-chunks-read is updated after processing + * a signal if TO_HOST_FLUSH_THRESHOLD bytes of bulk data have been + * transferred since the last update. + */ +#define TO_HOST_FLUSH_THRESHOLD (500 * 5) + + +/* SDIO Card Common Control Registers */ +#define SDIO_CCCR_SDIO_REVISION (0x00) +#define SDIO_SD_SPEC_REVISION (0x01) +#define SDIO_IO_ENABLE (0x02) +#define SDIO_IO_READY (0x03) +#define SDIO_INT_ENABLE (0x04) +#define SDIO_INT_PENDING (0x05) +#define SDIO_IO_ABORT (0x06) +#define SDIO_BUS_IFACE_CONTROL (0x07) +#define SDIO_CARD_CAPABILOTY (0x08) +#define SDIO_COMMON_CIS_POINTER (0x09) +#define SDIO_BUS_SUSPEND (0x0C) +#define SDIO_FUNCTION_SELECT (0x0D) +#define SDIO_EXEC_FLAGS (0x0E) +#define SDIO_READY_FLAGS (0x0F) +#define SDIO_FN0_BLOCK_SIZE (0x10) +#define SDIO_POWER_CONTROL (0x12) +#define SDIO_VENDOR_START (0xF0) + +#define SDIO_CSR_HOST_WAKEUP (0xf0) +#define SDIO_CSR_HOST_INT_CLEAR (0xf1) +#define SDIO_CSR_FROM_HOST_SCRATCH0 (0xf2) +#define SDIO_CSR_FROM_HOST_SCRATCH1 (0xf3) +#define SDIO_CSR_TO_HOST_SCRATCH0 (0xf4) +#define SDIO_CSR_TO_HOST_SCRATCH1 (0xf5) +#define SDIO_CSR_FUNC_EN (0xf6) +#define SDIO_CSR_CSPI_MODE (0xf7) +#define SDIO_CSR_CSPI_STATUS (0xf8) +#define SDIO_CSR_CSPI_PADDING (0xf9) + + +#define UNIFI_SD_INT_ENABLE_IENM 0x0001 /* Master INT Enable */ + +#ifdef CSR_PRE_ALLOC_NET_DATA +#define BULK_DATA_PRE_ALLOC_NUM 16 +#endif + +/* + * Structure to hold configuration information read from UniFi. + */ +typedef struct +{ + /* + * The version of the SDIO signal queues and bulk data pools + * configuration structure. The MSB is the major version number, used to + * indicate incompatible changes. The LSB gives the minor revision number, + * used to indicate changes that maintain backwards compatibility. + */ + CsrUint16 version; + + /* + * offset from the start of the shared data memory to the SD IO + * control structure. + */ + CsrUint16 sdio_ctrl_offset; + + /* Buffer handle of the from-host signal queue */ + CsrUint16 fromhost_sigbuf_handle; + + /* Buffer handle of the to-host signal queue */ + CsrUint16 tohost_sigbuf_handle; + + /* + * Maximum number of signal primitive or bulk data command fragments that may be + * pending in the to-hw signal queue. + */ + CsrUint16 num_fromhost_sig_frags; + + /* + * Number of signal primitive or bulk data command fragments that must be pending + * in the to-host signal queue before the host will generate an interrupt + * to indicate that it has read a signal. This will usually be the total + * capacity of the to-host signal buffer less the size of the largest signal + * primitive divided by the signal primitive fragment size, but may be set + * to 1 to request interrupts every time that the host read a signal. + * Note that the hw may place more signals in the to-host signal queue + * than indicated by this field. + */ + CsrUint16 num_tohost_sig_frags; + + /* + * Number of to-hw bulk data slots. Slots are numbered from 0 (zero) to + * one less than the value in this field + */ + CsrUint16 num_fromhost_data_slots; + + /* + * Number of frm-hw bulk data slots. Slots are numbered from 0 (zero) to + * one less than the value in this field + */ + CsrUint16 num_tohost_data_slots; + + /* + * Size of the bulk data slots (2 octets) + * The size of the bulk data slots in octets. This will usually be + * the size of the largest MSDU. The value should always be even. + */ + CsrUint16 data_slot_size; + + /* + * Indicates that the host has finished the initialisation sequence. + * Initialised to 0x0000 by the firmware, and set to 0x0001 by us. + */ + CsrUint16 initialised; + + /* Added by protocol version 0x0001 */ + CsrUint32 overlay_size; + + /* Added by protocol version 0x0300 */ + CsrUint16 data_slot_round; + CsrUint16 sig_frag_size; + + /* Added by protocol version 0x0500 */ + CsrUint16 tohost_signal_padding; +} sdio_config_data_t; + +/* + * These values may change with versions of the Host Interface Protocol. + */ +/* + * Size of config info block pointed to by the CSR_SLT_SDIO_SLOT_CONFIG + * entry in the f/w symbol table + */ +#define SDIO_CONFIG_DATA_SIZE 30 + +/* Offset of the INIT flag in the config info block. */ +#define SDIO_INIT_FLAG_OFFSET 0x12 +#define SDIO_TO_HOST_SIG_PADDING_OFFSET 0x1C + + +/* Structure for a bulk data transfer command */ +typedef struct +{ + CsrUint16 cmd_and_len; /* bits 12-15 cmd, bits 0-11 len */ + CsrUint16 data_slot; /* slot number, perhaps OR'd with SLOT_DIR_TO_HOST */ + CsrUint16 offset; + CsrUint16 buffer_handle; +} bulk_data_cmd_t; + + +/* Bulk Data signal command values */ +#define SDIO_CMD_SIGNAL 0x00 +#define SDIO_CMD_TO_HOST_TRANSFER 0x01 +#define SDIO_CMD_TO_HOST_TRANSFER_ACK 0x02 /*deprecated*/ +#define SDIO_CMD_FROM_HOST_TRANSFER 0x03 +#define SDIO_CMD_FROM_HOST_TRANSFER_ACK 0x04 /*deprecated*/ +#define SDIO_CMD_CLEAR_SLOT 0x05 +#define SDIO_CMD_OVERLAY_TRANSFER 0x06 +#define SDIO_CMD_OVERLAY_TRANSFER_ACK 0x07 /*deprecated*/ +#define SDIO_CMD_FROM_HOST_AND_CLEAR 0x08 +#define SDIO_CMD_PADDING 0x0f + +#define SLOT_DIR_TO_HOST 0x8000 + + +/* Initialise bulkdata slot + * params: + * bulk_data_desc_t *bulk_data_slot + */ +#define UNIFI_INIT_BULK_DATA(bulk_data_slot) \ + { \ + (bulk_data_slot)->os_data_ptr = NULL; \ + (bulk_data_slot)->data_length = 0; \ + (bulk_data_slot)->os_net_buf_ptr = NULL; \ + (bulk_data_slot)->net_buf_length = 0; \ + } + +/* + * Structure to contain a SIGNAL datagram. + * This is used to build signal queues between the main driver and the + * i/o thread. + * The fields are: + * sigbuf Contains the HIP signal is wire-format (i.e. packed, + * little-endian) + * bulkdata Contains a copy of any associated bulk data + * signal_length The size of the signal in the sigbuf + */ +typedef struct card_signal +{ + CsrUint8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; + + /* Length of the SIGNAL inside sigbuf */ + CsrUint16 signal_length; + + bulk_data_desc_t bulkdata[UNIFI_MAX_DATA_REFERENCES]; +} card_signal_t; + + +/* + * Control structure for a generic ring buffer. + */ +#define UNIFI_QUEUE_NAME_MAX_LENGTH 16 +typedef struct +{ + card_signal_t *q_body; + + /* Num elements in queue (capacity is one less than this!) */ + CsrUint16 q_length; + + CsrUint16 q_wr_ptr; + CsrUint16 q_rd_ptr; + + CsrCharString name[UNIFI_QUEUE_NAME_MAX_LENGTH]; +} q_t; + + +#define UNIFI_RESERVED_COMMAND_SLOTS 2 + +/* Considering approx 500 us per packet giving 0.5 secs */ +#define UNIFI_PACKETS_INTERVAL 1000 + +/* + * Dynamic slot reservation for QoS + */ +typedef struct +{ + CsrUint16 from_host_used_slots[UNIFI_NO_OF_TX_QS]; + CsrUint16 from_host_max_slots[UNIFI_NO_OF_TX_QS]; + CsrUint16 from_host_reserved_slots[UNIFI_NO_OF_TX_QS]; + + /* Parameters to determine if a queue was active. + If number of packets sent is greater than the threshold + for the queue, the queue is considered active and no + re reservation is done, it is important not to keep this + value too low */ + /* Packets sent during this interval */ + CsrUint16 packets_txed[UNIFI_NO_OF_TX_QS]; + CsrUint16 total_packets_txed; + + /* Number of packets to see if slots need to be reassigned */ + CsrUint16 packets_interval; + + /* Once a queue reaches a stable state, avoid processing */ + CsrBool queue_stable[UNIFI_NO_OF_TX_QS]; +} card_dynamic_slot_t; + + +/* These are type-safe and don't write incorrect values to the + * structure. */ + +/* Return queue slots used count + * params: + * const q_t *q + * returns: + * CsrUint16 + */ +#define CSR_WIFI_HIP_Q_SLOTS_USED(q) \ + (((q)->q_wr_ptr - (q)->q_rd_ptr < 0)? \ + ((q)->q_wr_ptr - (q)->q_rd_ptr + (q)->q_length) : ((q)->q_wr_ptr - (q)->q_rd_ptr)) + +/* Return queue slots free count + * params: + * const q_t *q + * returns: + * CsrUint16 + */ +#define CSR_WIFI_HIP_Q_SLOTS_FREE(q) \ + ((q)->q_length - CSR_WIFI_HIP_Q_SLOTS_USED((q)) - 1) + +/* Return slot signal data pointer + * params: + * const q_t *q + * CsrUint16 slot + * returns: + * card_signal_t * + */ +#define CSR_WIFI_HIP_Q_SLOT_DATA(q, slot) \ + ((q)->q_body + slot) + +/* Return queue next read slot + * params: + * const q_t *q + * returns: + * CsrUint16 slot offset + */ +#define CSR_WIFI_HIP_Q_NEXT_R_SLOT(q) \ + ((q)->q_rd_ptr) + +/* Return queue next write slot + * params: + * const q_t *q + * returns: + * CsrUint16 slot offset + */ +#define CSR_WIFI_HIP_Q_NEXT_W_SLOT(q) \ + ((q)->q_wr_ptr) + +/* Return updated queue pointer wrapped around its length + * params: + * const q_t *q + * CsrUint16 x amount to add to queue pointer + * returns: + * CsrUint16 wrapped queue pointer + */ +#define CSR_WIFI_HIP_Q_WRAP(q, x) \ + ((((x) >= (q)->q_length)?((x) % (q)->q_length) : (x))) + +/* Advance queue read pointer + * params: + * const q_t *q + */ +#define CSR_WIFI_HIP_Q_INC_R(q) \ + ((q)->q_rd_ptr = CSR_WIFI_HIP_Q_WRAP((q), (q)->q_rd_ptr + 1)) + +/* Advance queue write pointer + * params: + * const q_t *q + */ +#define CSR_WIFI_HIP_Q_INC_W(q) \ + ((q)->q_wr_ptr = CSR_WIFI_HIP_Q_WRAP((q), (q)->q_wr_ptr + 1)) + +enum unifi_host_state +{ + UNIFI_HOST_STATE_AWAKE = 0, + UNIFI_HOST_STATE_DROWSY = 1, + UNIFI_HOST_STATE_TORPID = 2 +}; + +typedef struct +{ + bulk_data_desc_t bd; + unifi_TrafficQueue queue; /* Used for dynamic slot reservation */ +} slot_desc_t; + +/* + * Structure describing a UniFi SDIO card. + */ +struct card +{ + /* + * Back pointer for the higher level OS code. This is passed as + * an argument to callbacks (e.g. for received data and indications). + */ + void *ospriv; + + /* + * mapping of HIP slot to MA-PACKET.req host tag, the + * array is indexed by slot numbers and each index stores + * information of the last host tag it was used for + */ + CsrUint32 *fh_slot_host_tag_record; + + + /* Info read from Symbol Table during probe */ + CsrUint32 build_id; + CsrCharString build_id_string[128]; + + /* Retrieve from SDIO driver. */ + CsrUint16 chip_id; + + /* Read from GBL_CHIP_VERSION. */ + CsrUint16 chip_version; + + /* From the SDIO driver (probably 1) */ + CsrUint8 function; + + /* This is sused to get the register addresses and things. */ + ChipDescript *helper; + + /* + * Bit mask of PIOs for the loader to waggle during download. + * We assume these are connected to LEDs. The main firmware gets + * the mask from a MIB entry. + */ + CsrInt32 loader_led_mask; + + /* + * Support for flow control. When the from-host queue of signals + * is full, we ask the host upper layer to stop sending packets. When + * the queue drains we tell it that it can send packets again. + * We use this flag to remember the current state. + */ +#define card_is_tx_q_paused(card, q) (card->tx_q_paused_flag[q]) +#define card_tx_q_unpause(card, q) (card->tx_q_paused_flag[q] = 0) +#define card_tx_q_pause(card, q) (card->tx_q_paused_flag[q] = 1) + + CsrUint16 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX + 1 + UNIFI_NO_OF_TX_QS]; /* defensive more than big enough */ + + /* UDI callback for logging UniFi interactions */ + udi_func_t udi_hook; + + CsrUint8 bh_reason_host; + CsrUint8 bh_reason_unifi; + + /* SDIO clock speed request from OS layer */ + CsrUint8 request_max_clock; + + /* Last SDIO clock frequency set */ + CsrUint32 sdio_clock_speed; + + /* + * Current host state (copy of value in IOABORT register and + * spinlock to protect it. + */ + enum unifi_host_state host_state; + + enum unifi_low_power_mode low_power_mode; + enum unifi_periodic_wake_mode periodic_wake_mode; + + /* + * Ring buffer of signal structs for a queue of data packets from + * the host. + * The queue is empty when fh_data_q_num_rd == fh_data_q_num_wr. + * To add a packet to the queue, copy it to index given by + * (fh_data_q_num_wr%UNIFI_SOFT_Q_LENGTH) and advance fh_data_q_num_wr. + * To take a packet from the queue, copy data from index given by + * (fh_data_q_num_rd%UNIFI_SOFT_Q_LENGTH) and advance fh_data_q_num_rd. + * fh_data_q_num_rd and fh_data_q_num_rd are both modulo 256. + */ + card_signal_t fh_command_q_body[UNIFI_SOFT_COMMAND_Q_LENGTH]; + q_t fh_command_queue; + + card_signal_t fh_traffic_q_body[UNIFI_NO_OF_TX_QS][UNIFI_SOFT_TRAFFIC_Q_LENGTH]; + q_t fh_traffic_queue[UNIFI_NO_OF_TX_QS]; + + /* + * Signal counts from UniFi SDIO Control Data Structure. + * These are cached and synchronised with the UniFi before and after + * a batch of operations. + * + * These are the modulo-256 count of signals written to or read from UniFi + * The value is incremented for every signal. + */ + CsrInt32 from_host_signals_w; + CsrInt32 from_host_signals_r; + CsrInt32 to_host_signals_r; + CsrInt32 to_host_signals_w; + + + /* Should specify buffer size as a number of signals */ + /* + * Enough for 10 th and 10 fh data slots: + * 1 * 10 * 8 = 80 + * 2 * 10 * 8 = 160 + */ +#define UNIFI_FH_BUF_SIZE 1024 + struct sigbuf + { + CsrUint8 *buf; /* buffer area */ + CsrUint8 *ptr; /* current pos */ + CsrUint16 count; /* signal count */ + CsrUint16 bufsize; + } fh_buffer; + struct sigbuf th_buffer; + + + /* + * Field to use for the incrementing value to write to the UniFi + * SHARED_IO_INTERRUPT register. + * Flag to say we need to generate an interrupt at end of processing. + */ + CsrUint32 unifi_interrupt_seq; + CsrUint8 generate_interrupt; + + + /* Pointers to the bulk data slots */ + slot_desc_t *from_host_data; + bulk_data_desc_t *to_host_data; + + + /* + * Index of the next (hopefully) free data slot. + * This is an optimisation that starts searching at a more likely point + * than the beginning. + */ + CsrInt16 from_host_data_head; + + /* Dynamic slot allocation for queues */ + card_dynamic_slot_t dynamic_slot_data; + + /* + * SDIO specific fields + */ + + /* Interface pointer for the SDIO library */ + CsrSdioFunction *sdio_if; + + /* Copy of config_data struct from the card */ + sdio_config_data_t config_data; + + /* SDIO address of the Initialised flag and Control Data struct */ + CsrUint32 init_flag_addr; + CsrUint32 sdio_ctrl_addr; + + /* The last value written to the Shared Data Memory Page register */ + CsrUint32 proc_select; + CsrUint32 dmem_page; + CsrUint32 pmem_page; + + /* SDIO traffic counters limited to 32 bits for Synergy compatibility */ + CsrUint32 sdio_bytes_read; + CsrUint32 sdio_bytes_written; + + CsrUint8 memory_resources_allocated; + + /* UniFi SDIO I/O Block size. */ + CsrUint16 sdio_io_block_size; + + /* Pad transfer sizes to SDIO block boundaries */ + CsrBool sdio_io_block_pad; + + /* Read from the XBV */ + struct FWOV fwov; + +#ifndef CSR_WIFI_HIP_TA_DISABLE + /* TA sampling */ + ta_data_t ta_sampling; +#endif + + /* Auto-coredump */ + CsrInt16 request_coredump_on_reset; /* request coredump on next reset */ + struct coredump_buf *dump_buf; /* root node */ + struct coredump_buf *dump_next_write; /* node to fill at next dump */ + struct coredump_buf *dump_cur_read; /* valid node to read, or NULL */ + +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + struct cmd_profile + { + CsrUint32 cmd52_count; + CsrUint32 cmd53_count; + CsrUint32 tx_count; + CsrUint32 tx_cfm_count; + CsrUint32 rx_count; + CsrUint32 bh_count; + CsrUint32 process_count; + CsrUint32 protocol_count; + + CsrUint32 cmd52_f0_r_count; + CsrUint32 cmd52_f0_w_count; + CsrUint32 cmd52_r8or16_count; + CsrUint32 cmd52_w8or16_count; + CsrUint32 cmd52_r16_count; + CsrUint32 cmd52_w16_count; + CsrUint32 cmd52_r32_count; + + CsrUint32 sdio_cmd_signal; + CsrUint32 sdio_cmd_clear_slot; + CsrUint32 sdio_cmd_to_host; + CsrUint32 sdio_cmd_from_host; + CsrUint32 sdio_cmd_from_host_and_clear; + } hip_prof; + struct cmd_profile cmd_prof; +#endif + + /* Interrupt processing mode flags */ + CsrUint32 intmode; + +#ifdef UNIFI_DEBUG + CsrUint8 lsb; +#endif + + /* Historic firmware panic codes */ + CsrUint32 panic_data_phy_addr; + CsrUint32 panic_data_mac_addr; + CsrUint16 last_phy_panic_code; + CsrUint16 last_phy_panic_arg; + CsrUint16 last_mac_panic_code; + CsrUint16 last_mac_panic_arg; +#ifdef CSR_PRE_ALLOC_NET_DATA + bulk_data_desc_t bulk_data_desc_list[BULK_DATA_PRE_ALLOC_NUM]; + CsrUint16 prealloc_netdata_r; + CsrUint16 prealloc_netdata_w; +#endif +}; /* struct card */ + + +/* Reset types */ +enum unifi_reset_type +{ + UNIFI_COLD_RESET = 1, + UNIFI_WARM_RESET = 2 +}; + +/* + * unifi_set_host_state() implements signalling for waking UniFi from + * deep sleep. The host indicates to UniFi that it is in one of three states: + * Torpid - host has nothing to send, UniFi can go to sleep. + * Drowsy - host has data to send to UniFi. UniFi will respond with an + * SDIO interrupt. When hosts responds it moves to Awake. + * Awake - host has data to transfer, UniFi must stay awake. + * When host has finished, it moves to Torpid. + */ +CsrResult unifi_set_host_state(card_t *card, enum unifi_host_state state); + + +CsrResult unifi_set_proc_select(card_t *card, enum unifi_dbg_processors_select select); +CsrInt32 card_read_signal_counts(card_t *card); +bulk_data_desc_t* card_find_data_slot(card_t *card, CsrInt16 slot); + + +CsrResult unifi_read32(card_t *card, CsrUint32 unifi_addr, CsrUint32 *pdata); +CsrResult unifi_readnz(card_t *card, CsrUint32 unifi_addr, + void *pdata, CsrUint16 len); +CsrInt32 unifi_read_shared_count(card_t *card, CsrUint32 addr); + +CsrResult unifi_writen(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len); + +CsrResult unifi_bulk_rw(card_t *card, CsrUint32 handle, + void *pdata, CsrUint32 len, CsrInt16 direction); +CsrResult unifi_bulk_rw_noretry(card_t *card, CsrUint32 handle, + void *pdata, CsrUint32 len, CsrInt16 direction); +#define UNIFI_SDIO_READ 0 +#define UNIFI_SDIO_WRITE 1 + +CsrResult unifi_read_8_or_16(card_t *card, CsrUint32 unifi_addr, CsrUint8 *pdata); +CsrResult unifi_write_8_or_16(card_t *card, CsrUint32 unifi_addr, CsrUint8 data); +CsrResult unifi_read_direct_8_or_16(card_t *card, CsrUint32 addr, CsrUint8 *pdata); +CsrResult unifi_write_direct_8_or_16(card_t *card, CsrUint32 addr, CsrUint8 data); + +CsrResult unifi_read_direct16(card_t *card, CsrUint32 addr, CsrUint16 *pdata); +CsrResult unifi_read_direct32(card_t *card, CsrUint32 addr, CsrUint32 *pdata); +CsrResult unifi_read_directn(card_t *card, CsrUint32 addr, void *pdata, CsrUint16 len); + +CsrResult unifi_write_direct16(card_t *card, CsrUint32 addr, CsrUint16 data); +CsrResult unifi_write_directn(card_t *card, CsrUint32 addr, void *pdata, CsrUint16 len); + +CsrResult sdio_read_f0(card_t *card, CsrUint32 addr, CsrUint8 *pdata); +CsrResult sdio_write_f0(card_t *card, CsrUint32 addr, CsrUint8 data); + +void unifi_read_panic(card_t *card); +#ifdef CSR_PRE_ALLOC_NET_DATA +void prealloc_netdata_free(card_t *card); +CsrResult prealloc_netdata_alloc(card_t *card); +#endif +/* For diagnostic use */ +void dump(void *mem, CsrUint16 len); +void dump16(void *mem, CsrUint16 len); + +#ifdef __cplusplus +} +#endif + +#endif /* __CARD_SDIO_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c new file mode 100644 index 000000000000..3d563c13ff5a --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c @@ -0,0 +1,2561 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_card_sdio_intr.c + * + * PURPOSE: + * Interrupt processing for the UniFi SDIO driver. + * + * We may need another signal queue of responses to UniFi to hold + * bulk data commands generated by read_to_host_signals(). + * + * --------------------------------------------------------------------------- + */ +#undef CSR_WIFI_HIP_NOISY + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "csr_wifi_hip_card.h" +#include "csr_wifi_hip_xbv.h" + + +/* + * If the SDIO link is idle for this time (in milliseconds), + * signal UniFi to go into Deep Sleep. + * Valid return value of unifi_bh(). + */ +#define UNIFI_DEFAULT_HOST_IDLE_TIMEOUT 5 +/* + * If the UniFi has not woken up for this time (in milliseconds), + * signal the bottom half to take action. + * Valid return value of unifi_bh(). + */ +#define UNIFI_DEFAULT_WAKE_TIMEOUT 1000 + + +static CsrResult process_bh(card_t *card); +static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something); + +static CsrResult flush_fh_buffer(card_t *card); + +static CsrResult check_fh_sig_slots(card_t *card, CsrUint16 needed, CsrInt32 *space); + +static CsrResult read_to_host_signals(card_t *card, CsrInt32 *processed); +static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed); + +static CsrResult process_bulk_data_command(card_t *card, + const CsrUint8 *cmdptr, + CsrInt16 cmd, CsrUint16 len); +static CsrResult process_clear_slot_command(card_t *card, + const CsrUint8 *cmdptr); +static CsrResult process_fh_cmd_queue(card_t *card, CsrInt32 *processed); +static CsrResult process_fh_traffic_queue(card_t *card, CsrInt32 *processed); +static void restart_packet_flow(card_t *card); +static CsrResult process_clock_request(card_t *card); + +#ifdef CSR_WIFI_HIP_NOISY +CsrInt16 dump_fh_buf = 0; +#endif /* CSR_WIFI_HIP_NOISY */ + +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + +/* + * The unifi_debug_output buffer can be used to debug the HIP behaviour offline + * i.e. without using the tracing functions that change the timing. + * + * Call unifi_debug_log_to_buf() with printf arguments to store a string into + * unifi_debug_output. When unifi_debug_buf_dump() is called, the contents of the + * buffer are dumped with dump_str() which has to be implemented in the + * OS layer, during the porting exercise. The offset printed, holds the + * offset where the last character is (always a zero). + * + */ + +#define UNIFI_DEBUG_GBUFFER_SIZE 8192 +static CsrCharString unifi_debug_output[UNIFI_DEBUG_GBUFFER_SIZE]; +static CsrCharString *unifi_dbgbuf_ptr = unifi_debug_output; +static CsrCharString *unifi_dbgbuf_start = unifi_debug_output; + +static void append_char(CsrCharString c) +{ + /* write char and advance pointer */ + *unifi_dbgbuf_ptr++ = c; + /* wrap pointer at end of buffer */ + if ((unifi_dbgbuf_ptr - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE) + { + unifi_dbgbuf_ptr = unifi_debug_output; + } +} /* append_char() */ + + +void unifi_debug_string_to_buf(const CsrCharString *str) +{ + const CsrCharString *p = str; + while (*p) + { + append_char(*p); + p++; + } + /* Update start-of-buffer pointer */ + unifi_dbgbuf_start = unifi_dbgbuf_ptr + 1; + if ((unifi_dbgbuf_start - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE) + { + unifi_dbgbuf_start = unifi_debug_output; + } +} + + +void unifi_debug_log_to_buf(const CsrCharString *fmt, ...) +{ +#define DEBUG_BUFFER_SIZE 80 + static CsrCharString s[DEBUG_BUFFER_SIZE]; + va_list args; + + va_start(args, fmt); + CsrVsnprintf(s, DEBUG_BUFFER_SIZE, fmt, args); + va_end(args); + + unifi_debug_string_to_buf(s); +} /* unifi_debug_log_to_buf() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_debug_hex_to_buf + * + * puts the contents of the passed buffer into the debug buffer as a hex string + * + * Arguments: + * buff buffer to print as hex + * length number of chars to print + * + * Returns: + * None. + * + * --------------------------------------------------------------------------- + */ +void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length) +{ + CsrCharString s[5]; + CsrUint16 i; + + for (i = 0; i < length; i++) + { + CsrUInt16ToHex(0xff & buff[i], s); + unifi_debug_string_to_buf(s); + } +} + + +void unifi_debug_buf_dump(void) +{ + CsrInt32 offset = unifi_dbgbuf_ptr - unifi_debug_output; + + unifi_error(NULL, "HIP debug buffer offset=%d\n", offset); + dump_str(unifi_debug_output + offset, UNIFI_DEBUG_GBUFFER_SIZE - offset); + dump_str(unifi_debug_output, offset); +} /* unifi_debug_buf_dump() */ + + +#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ + +#ifdef CSR_PRE_ALLOC_NET_DATA +#define NETDATA_PRE_ALLOC_BUF_SIZE 8000 + +void prealloc_netdata_free(card_t *card) +{ + unifi_warning(card->ospriv, "prealloc_netdata_free: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); + + while (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length != 0) + { + unifi_warning(card->ospriv, "prealloc_netdata_free: r=%d\n", card->prealloc_netdata_r); + + unifi_net_data_free(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_r]); + card->prealloc_netdata_r++; + card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM; + } + card->prealloc_netdata_r = card->prealloc_netdata_w = 0; + + unifi_warning(card->ospriv, "prealloc_netdata_free: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); +} + + +CsrResult prealloc_netdata_alloc(card_t *card) +{ + CsrResult r; + + unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); + + while (card->bulk_data_desc_list[card->prealloc_netdata_w].data_length == 0) + { + r = unifi_net_data_malloc(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_w], NETDATA_PRE_ALLOC_BUF_SIZE); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "prealloc_netdata_alloc: Failed to allocate t-h bulk data\n"); + return CSR_RESULT_FAILURE; + } + card->prealloc_netdata_w++; + card->prealloc_netdata_w %= BULK_DATA_PRE_ALLOC_NUM; + } + unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); + + return CSR_RESULT_SUCCESS; +} + + +static CsrResult prealloc_netdata_get(card_t *card, bulk_data_desc_t *bulk_data_slot, CsrUint32 size) +{ + CsrResult r; + + unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); + + if (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0) + { + unifi_error(card->ospriv, "prealloc_netdata_get: data_length = 0\n"); + } + + if ((size > NETDATA_PRE_ALLOC_BUF_SIZE) || (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0)) + { + unifi_warning(card->ospriv, "prealloc_netdata_get: Calling net_data_malloc\n"); + + r = unifi_net_data_malloc(card->ospriv, bulk_data_slot, size); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "prealloc_netdata_get: Failed to allocate t-h bulk data\n"); + return CSR_RESULT_FAILURE; + } + return CSR_RESULT_SUCCESS; + } + + *bulk_data_slot = card->bulk_data_desc_list[card->prealloc_netdata_r]; + card->bulk_data_desc_list[card->prealloc_netdata_r].os_data_ptr = NULL; + card->bulk_data_desc_list[card->prealloc_netdata_r].os_net_buf_ptr = NULL; + card->bulk_data_desc_list[card->prealloc_netdata_r].net_buf_length = 0; + card->bulk_data_desc_list[card->prealloc_netdata_r].data_length = 0; + + card->prealloc_netdata_r++; + card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM; + + unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); + + return CSR_RESULT_SUCCESS; +} + + +#endif + +/* + * --------------------------------------------------------------------------- + * unifi_sdio_interrupt_handler + * + * This function should be called by the OS-dependent code to handle + * an SDIO interrupt from the UniFi. + * + * Arguments: + * card Pointer to card context structure. + * + * Returns: + * None. + * + * Notes: This function may be called in DRS context. In this case, + * tracing with the unifi_trace(), etc, is not allowed. + * --------------------------------------------------------------------------- + */ +void unifi_sdio_interrupt_handler(card_t *card) +{ + /* + * Set the flag to say reason for waking was SDIO interrupt. + * Then ask the OS layer to run the unifi_bh to give attention to the UniFi. + */ + card->bh_reason_unifi = 1; + unifi_run_bh(card->ospriv); +} /* sdio_interrupt_handler() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_configure_low_power_mode + * + * This function should be called by the OS-dependent when + * the deep sleep signaling needs to be enabled or disabled. + * + * Arguments: + * card Pointer to card context structure. + * low_power_mode Disable/Enable the deep sleep signaling + * periodic_wake_mode UniFi wakes host periodically. + * + * Returns: + * CSR_RESULT_SUCCESS on success or a CSR error code. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_configure_low_power_mode(card_t *card, + enum unifi_low_power_mode low_power_mode, + enum unifi_periodic_wake_mode periodic_wake_mode) +{ + card->low_power_mode = low_power_mode; + card->periodic_wake_mode = periodic_wake_mode; + + unifi_trace(card->ospriv, UDBG1, + "unifi_configure_low_power_mode: new mode = %s, wake_host = %s\n", + (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled", + (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE"); + + unifi_run_bh(card->ospriv); + return CSR_RESULT_SUCCESS; +} /* unifi_configure_low_power_mode() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_force_low_power_mode + * + * This function should be called by the OS-dependent when + * UniFi needs to be set to the low power mode (e.g. on suspend) + * + * Arguments: + * card Pointer to card context structure. + * + * Returns: + * CSR_RESULT_SUCCESS on success or a CSR error code. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_force_low_power_mode(card_t *card) +{ + if (card->low_power_mode == UNIFI_LOW_POWER_DISABLED) + { + unifi_error(card->ospriv, "Attempt to set mode to TORPID when lower power mode is disabled\n"); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + return unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); +} /* unifi_force_low_power_mode() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_bh + * + * This function should be called by the OS-dependent code when + * host and/or UniFi has requested an exchange of messages. + * + * Arguments: + * card Pointer to card context structure. + * + * Returns: + * CSR_RESULT_SUCCESS on success or a CSR error code. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_bh(card_t *card, CsrUint32 *remaining) +{ + CsrResult r; + CsrResult csrResult; + CsrBool pending; + CsrInt32 iostate, j; + const enum unifi_low_power_mode low_power_mode = card->low_power_mode; + CsrUint16 data_slots_used = 0; + + + /* Process request to raise the maximum SDIO clock */ + r = process_clock_request(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Error setting maximum SDIO clock\n"); + goto exit; + } + + /* + * Why was the BH thread woken? + * If it was an SDIO interrupt, UniFi is awake and we need to process it. + * If it was a host process queueing data, then we need to awaken UniFi. + * + * Priority of flags is top down. + * + * ----------------------------------------------------------+ + * \state| AWAKE | DROWSY | TORPID | + * flag\ | | | | + * ---------+--------------+----------------+----------------| + * | do the host | go to AWAKE and| go to AWAKE and| + * unifi | protocol | do the host | do the host | + * | | protocol | protocol | + * ---------+--------------+----------------+----------------| + * | do the host | | | + * host | protocol | do nothing | go to DROWSY | + * | | | | + * ---------+--------------+----------------+----------------| + * | | | should not | + * timeout | go to TORPID | error, unifi | occur | + * | | didn't wake up | do nothing | + * ----------------------------------------------------------+ + * + * Note that if we end up in the AWAKE state we always do the host protocol. + */ + + do + { + /* + * When the host state is set to DROWSY, then we can not disable the + * interrupts as UniFi can generate an interrupt even when the INT_ENABLE + * register has the interrupts disabled. This interrupt will be lost. + */ + if (card->host_state == UNIFI_HOST_STATE_DROWSY || card->host_state == UNIFI_HOST_STATE_TORPID) + { + CsrUint8 reason_unifi; + + /* + * An interrupt may occur while or after we cache the reason. + * This interrupt will cause the unifi_bh() to be scheduled again. + * Any interrupt that has happened before the register is read + * and is considered spurious has to acknowledged. + */ + reason_unifi = card->bh_reason_unifi; + + /* + * If an interrupt is received, check if it was a real one, + * set the host state to AWAKE and run the BH. + */ + r = CardPendingInt(card, &pending); + if (r != CSR_RESULT_SUCCESS) + { + goto exit; + } + + if (pending) + { + unifi_trace(card->ospriv, UDBG5, + "UNIFI_HOST_STATE_%s: Set state to AWAKE.\n", + (card->host_state == UNIFI_HOST_STATE_TORPID)?"TORPID" : "DROWSY"); + + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r == CSR_RESULT_SUCCESS) + { + (*remaining) = 0; + break; + } + } + else if (reason_unifi) + { + CsrSdioInterruptAcknowledge(card->sdio_if); + } + + /* + * If an chip is in TORPID, and the host wants to wake it up, + * set the host state to DROWSY and wait for the wake-up interrupt. + */ + if ((card->host_state == UNIFI_HOST_STATE_TORPID) && card->bh_reason_host) + { + r = unifi_set_host_state(card, UNIFI_HOST_STATE_DROWSY); + if (r == CSR_RESULT_SUCCESS) + { + /* + * set the timeout value to UNIFI_DEFAULT_WAKE_TIMEOUT + * to capture a wake error. + */ + card->bh_reason_host = 0; + (*remaining) = UNIFI_DEFAULT_WAKE_TIMEOUT; + return CSR_RESULT_SUCCESS; + } + + goto exit; + } + + /* + * If the chip is in DROWSY, and the timeout expires, + * we need to reset the chip. This should never occur. + * (If it does, check that the calling thread set "remaining" + * according to the time remaining when unifi_bh() was called). + */ + if ((card->host_state == UNIFI_HOST_STATE_DROWSY) && ((*remaining) == 0)) + { + unifi_error(card->ospriv, "UniFi did not wake up on time...\n"); + + /* + * Check if Function1 has gone away or + * if we missed an SDIO interrupt. + */ + r = unifi_check_io_status(card, &iostate); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + goto exit; + } + /* Need to reset and reboot */ + return CSR_RESULT_FAILURE; + } + } + else + { + if (card->bh_reason_unifi || card->bh_reason_host) + { + break; + } + + if (((*remaining) == 0) && (low_power_mode == UNIFI_LOW_POWER_ENABLED)) + { + r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); + if (r == CSR_RESULT_SUCCESS) + { + (*remaining) = 0; + return CSR_RESULT_SUCCESS; + } + + goto exit; + } + } + + /* No need to run the host protocol */ + return CSR_RESULT_SUCCESS; + } while (0); + + + /* Disable the SDIO interrupts while doing SDIO ops */ + csrResult = CsrSdioInterruptDisable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + r = CSR_WIFI_HIP_RESULT_NO_DEVICE; + goto exit; + } + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + unifi_error(card->ospriv, "Failed to disable SDIO interrupts. unifi_bh queues error.\n"); + goto exit; + } + + /* Now that the interrupts are disabled, ack the interrupt */ + CsrSdioInterruptAcknowledge(card->sdio_if); + + /* Run the HIP */ + r = process_bh(card); + if (r != CSR_RESULT_SUCCESS) + { + goto exit; + } + + /* + * If host is now idle, schedule a timer for the delay before we + * let UniFi go into deep sleep. + * If the timer goes off, we will move to TORPID state. + * If UniFi raises an interrupt in the meantime, we will cancel + * the timer and start a new one when we become idle. + */ + for (j = 0; j < UNIFI_NO_OF_TX_QS; j++) + { + data_slots_used += CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[j]); + } + + if ((low_power_mode == UNIFI_LOW_POWER_ENABLED) && (data_slots_used == 0)) + { +#ifndef CSR_WIFI_HIP_TA_DISABLE + if (card->ta_sampling.traffic_type != CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC) + { +#endif + /* return the UNIFI_DEFAULT_HOST_IDLE_TIMEOUT, so we can go to sleep. */ + unifi_trace(card->ospriv, UDBG5, + "Traffic is not periodic, set timer for TORPID.\n"); + (*remaining) = UNIFI_DEFAULT_HOST_IDLE_TIMEOUT; +#ifndef CSR_WIFI_HIP_TA_DISABLE + } + else + { + unifi_trace(card->ospriv, UDBG5, + "Traffic is periodic, set unifi to TORPID immediately.\n"); + if (CardAreAllFromHostDataSlotsEmpty(card) == 1) + { + r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); + if (r != CSR_RESULT_SUCCESS) + { + goto exit; + } + } + } +#endif + } + + csrResult = CsrSdioInterruptEnable(card->sdio_if); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + r = CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + unifi_error(card->ospriv, "Failed to enable SDIO interrupt\n"); + } + +exit: + + unifi_trace(card->ospriv, UDBG4, "New state=%d\n", card->host_state); + + if (r != CSR_RESULT_SUCCESS) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_buf_dump(); +#endif + /* If an interrupt has been raised, ack it here */ + if (card->bh_reason_unifi) + { + CsrSdioInterruptAcknowledge(card->sdio_if); + } + + unifi_error(card->ospriv, + "unifi_bh: state=%d %c, clock=%dkHz, interrupt=%d host=%d, power_save=%s\n", + card->host_state, + (card->host_state == UNIFI_HOST_STATE_AWAKE)?'A' : (card->host_state == UNIFI_HOST_STATE_DROWSY)?'D' : 'T', + card->sdio_clock_speed / 1000, + card->bh_reason_unifi, card->bh_reason_host, + (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled"); + + /* Try to capture firmware panic codes */ + unifi_capture_panic(card); + + /* Ask for a mini-coredump when the driver has reset UniFi */ + unifi_coredump_request_at_next_reset(card, 1); + } + + return r; +} /* unifi_bh() */ + + +/* + * --------------------------------------------------------------------------- + * process_clock_request + * + * Handle request from the OS layer to increase the SDIO clock speed. + * The fast clock is limited until the firmware has indicated that it has + * completed initialisation to the OS layer. + * + * Arguments: + * card Pointer to card context structure. + * + * Returns: + * CSR_RESULT_SUCCESS on success or CSR error code. + * --------------------------------------------------------------------------- + */ +static CsrResult process_clock_request(card_t *card) +{ + CsrResult r = CSR_RESULT_SUCCESS; + CsrResult csrResult; + + if (!card->request_max_clock) + { + return CSR_RESULT_SUCCESS; /* No pending request */ + } + + /* + * The SDIO clock speed request from the OS layer is only acted upon if + * the UniFi is awake. If it was in any other state, the clock speed will + * transition through SAFE to MAX while the host wakes it up, and the + * final speed reached will be UNIFI_SDIO_CLOCK_MAX_HZ. + * This assumes that the SME never requests low power mode while the f/w + * initialisation takes place. + */ + if (card->host_state == UNIFI_HOST_STATE_AWAKE) + { + unifi_trace(card->ospriv, UDBG1, "Set SDIO max clock\n"); + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_MAX_HZ); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + } + else + { + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_MAX_HZ; /* log the new freq */ + } + } + else + { + unifi_trace(card->ospriv, UDBG1, "Will set SDIO max clock after wakeup\n"); + } + + /* Cancel the request now that it has been acted upon, or is about to be + * by the wakeup mechanism + */ + card->request_max_clock = 0; + + return r; +} + + +/* + * --------------------------------------------------------------------------- + * process_bh + * + * Exchange messages with UniFi + * + * Arguments: + * card Pointer to card context structure. + * + * Returns: + * CSR_RESULT_SUCCESS on success or CSR error code. + * --------------------------------------------------------------------------- + */ +static CsrResult process_bh(card_t *card) +{ + CsrResult r; + CsrBool more; + more = FALSE; + + /* Process the reasons (interrupt, signals) */ + do + { + /* + * Run in a while loop, to save clearing the interrupts + * every time around the outside loop. + */ + do + { + /* If configured to run the HIP just once, skip first loop */ + if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) + { + break; + } + + r = handle_host_protocol(card, &more); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n", + card->cmd_prof.cmd52_count, + card->cmd_prof.cmd53_count, + card->cmd_prof.tx_count, + card->cmd_prof.tx_cfm_count, + card->cmd_prof.rx_count, + card->cmd_prof.sdio_cmd_signal, + card->cmd_prof.sdio_cmd_to_host, + card->cmd_prof.sdio_cmd_from_host_and_clear + ); + + card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0; + card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0; + + card->cmd_prof.cmd52_f0_r_count = 0; + card->cmd_prof.cmd52_f0_w_count = 0; + card->cmd_prof.cmd52_r8or16_count = 0; + card->cmd_prof.cmd52_w8or16_count = 0; + card->cmd_prof.cmd52_r16_count = 0; + card->cmd_prof.cmd52_w16_count = 0; + card->cmd_prof.cmd52_r32_count = 0; + + card->cmd_prof.sdio_cmd_signal = 0; + card->cmd_prof.sdio_cmd_clear_slot = 0; + card->cmd_prof.sdio_cmd_to_host = 0; + card->cmd_prof.sdio_cmd_from_host = 0; + card->cmd_prof.sdio_cmd_from_host_and_clear = 0; +#endif + + + } while (more || card->bh_reason_unifi || card->bh_reason_host); + + /* Acknowledge the h/w interrupt */ + r = CardClearInt(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to acknowledge interrupt.\n"); + return r; + } + + /* + * UniFi may have tried to generate an interrupt during the + * CardClearInt() was running. So, we need to run the host + * protocol again, to check if there are any pending requests. + */ + r = handle_host_protocol(card, &more); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n", + card->cmd_prof.cmd52_count, + card->cmd_prof.cmd53_count, + card->cmd_prof.tx_count, + card->cmd_prof.tx_cfm_count, + card->cmd_prof.rx_count, + card->cmd_prof.sdio_cmd_signal, + card->cmd_prof.sdio_cmd_to_host, + card->cmd_prof.sdio_cmd_from_host_and_clear + ); + + card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0; + card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0; + + card->cmd_prof.cmd52_f0_r_count = 0; + card->cmd_prof.cmd52_f0_w_count = 0; + card->cmd_prof.cmd52_r8or16_count = 0; + card->cmd_prof.cmd52_w8or16_count = 0; + card->cmd_prof.cmd52_r16_count = 0; + card->cmd_prof.cmd52_w16_count = 0; + card->cmd_prof.cmd52_r32_count = 0; + + card->cmd_prof.sdio_cmd_signal = 0; + card->cmd_prof.sdio_cmd_clear_slot = 0; + card->cmd_prof.sdio_cmd_to_host = 0; + card->cmd_prof.sdio_cmd_from_host = 0; + card->cmd_prof.sdio_cmd_from_host_and_clear = 0; +#endif + /* If configured to run the HIP just once, work is now done */ + if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) + { + break; + } + + } while (more || card->bh_reason_unifi || card->bh_reason_host); + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + if ((card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) == 0) + { + unifi_debug_log_to_buf("proc=%d\n", + card->cmd_prof.process_count); + } +#endif + + return CSR_RESULT_SUCCESS; +} /* process_bh() */ + + +/* + * --------------------------------------------------------------------------- + * handle_host_protocol + * + * This function implements the Host Interface Protocol (HIP) as + * described in the Host Interface Protocol Specification. + * + * Arguments: + * card Pointer to card context structure. + * processed_something Pointer to location to update processing status: + * TRUE when data was transferred + * FALSE when no data was transferred (queues empty) + * + * Returns: + * CSR_RESULT_SUCCESS on success or CSR error code. + * --------------------------------------------------------------------------- + */ +static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something) +{ + CsrResult r; + CsrInt32 done; + + *processed_something = FALSE; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, " ======================== \n"); +#endif /* CSR_WIFI_HIP_NOISY */ + +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.process_count++; +#endif + + card->bh_reason_unifi = card->bh_reason_host = 0; + card->generate_interrupt = 0; + + + /* + * (Re)fill the T-H signal buffer + */ + r = read_to_host_signals(card, &done); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Error occured reading to-host signals\n"); + return r; + } + if (done > 0) + { + *processed_something = TRUE; + } + + /* + * Process any to-host signals. + * Perform any requested CMD53 transfers here, but just queue any + * bulk data command responses. + */ + r = process_to_host_signals(card, &done); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Error occured processing to-host signals\n"); + return r; + } + + /* Now send any signals in the F-H queues */ + /* Give precedence to the command queue */ + r = process_fh_cmd_queue(card, &done); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Error occured processing from-host signals\n"); + return r; + } + if (done > 0) + { + *processed_something = TRUE; + } + + r = process_fh_traffic_queue(card, &done); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Error occured processing from-host data signals\n"); + return r; + } + if (done > 0) + { + *processed_something = TRUE; + } + + /* Flush out the batch of signals to the UniFi. */ + r = flush_fh_buffer(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to copy from-host signals to UniFi\n"); + return r; + } + + + /* + * Send the host interrupt to say the queues have been modified. + */ + if (card->generate_interrupt) + { + r = CardGenInt(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to notify UniFi that queues have been modified.\n"); + return r; + } + } +#ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ + unifi_rx_queue_flush(card->ospriv); +#endif + /* See if we can re-enable transmission now */ + restart_packet_flow(card); + +#ifdef CSR_PRE_ALLOC_NET_DATA + r = prealloc_netdata_alloc(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "prealloc_netdata failed\n"); + return r; + } +#endif + + /* + * Don't put the thread sleep if we just interacted with the chip, + * there might be more to do if we look again. + */ + return r; +} /* handle_host_protocol() */ + + +/* + * Rounds the given signal length in bytes to a whole number + * of sig_frag_size. + */ +#define GET_CHUNKS_FOR(SIG_FRAG_SIZE, LENGTH) (((LENGTH) + ((SIG_FRAG_SIZE)-1)) / (SIG_FRAG_SIZE)) + + +/* + * --------------------------------------------------------------------------- + * read_to_host_signals + * + * Read everything pending in the UniFi TH signal buffer. + * Only do it if the local buffer is empty. + * + * Arguments: + * card Pointer to card context struct + * processed Number of signals read: + * 0 if there were no signals pending, + * 1 if we read at least one signal + * Returns: + * CSR error code if an error occurred. + * --------------------------------------------------------------------------- + */ +static CsrResult read_to_host_signals(card_t *card, CsrInt32 *processed) +{ + CsrInt32 count_thw, count_thr; + CsrInt32 unread_chunks, unread_bytes; + CsrResult r; + + *processed = 0; + + /* Read any pending signals or bulk data commands */ + count_thw = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); + if (count_thw < 0) + { + unifi_error(card->ospriv, "Failed to read to-host sig written count\n"); + return CSR_RESULT_FAILURE; + } + card->to_host_signals_w = count_thw; /* diag */ + + count_thr = card->to_host_signals_r; + + if (count_thw == count_thr) + { + return CSR_RESULT_SUCCESS; + } + + unread_chunks = + (((count_thw - count_thr) + 128) % 128) - card->th_buffer.count; + + if (unread_chunks == 0) + { + return CSR_RESULT_SUCCESS; + } + + unread_bytes = card->config_data.sig_frag_size * unread_chunks; + + + r = unifi_bulk_rw(card, + card->config_data.tohost_sigbuf_handle, + card->th_buffer.ptr, + unread_bytes, + UNIFI_SDIO_READ); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read ToHost signal\n"); + return r; + } + + card->th_buffer.ptr += unread_bytes; + card->th_buffer.count += (CsrUint16)unread_chunks; + + *processed = 1; + + return CSR_RESULT_SUCCESS; +} /* read_to_host_signals() */ + + +/* + * --------------------------------------------------------------------------- + * update_to_host_signals_r + * + * Advance the shared-memory count of chunks read from the to-host + * signal buffer. + * Raise a UniFi internal interrupt to tell the firmware that the + * count has changed. + * + * Arguments: + * card Pointer to card context struct + * pending Number of chunks remaining + * + * Returns: + * CSR_RESULT_SUCCESS on success or CSR error code + * --------------------------------------------------------------------------- + */ +static CsrResult update_to_host_signals_r(card_t *card, CsrInt16 pending) +{ + CsrResult r; + + card->to_host_signals_r = + (card->to_host_signals_r + (card->th_buffer.count - pending)) % 128; + card->th_buffer.count = pending; + + /* Update the count of signals read */ + r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 6, + (CsrUint8)card->to_host_signals_r); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to update to-host signals read\n"); + return r; + } + + r = CardGenInt(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to notify UniFi that we processed to-host signals.\n"); + return r; + } + + card->generate_interrupt = 0; + + return CSR_RESULT_SUCCESS; +} /* update_to_host_signals_r() */ + + +/* + * --------------------------------------------------------------------------- + * read_unpack_cmd + * + * Converts a wire-formatted command to the host bulk_data_cmd_t structure. + * + * Arguments: + * ptr Pointer to the command + * bulk_data_cmd Pointer to the host structure + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void read_unpack_cmd(const CsrUint8 *ptr, bulk_data_cmd_t *bulk_data_cmd) +{ + CsrInt16 index = 0; + bulk_data_cmd->cmd_and_len = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + bulk_data_cmd->data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + bulk_data_cmd->offset = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + bulk_data_cmd->buffer_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; +} /* read_unpack_cmd */ + + +/* + * --------------------------------------------------------------------------- + * process_to_host_signals + * + * Read and dispatch signals from the UniFi + * + * Arguments: + * card Pointer to card context struct + * processed Pointer to location to write processing result: + * 0 if there were no signals pending, + * 1 if we read at least one signal + * + * Returns: + * CSR error code if there was an error + * + * Notes: + * Since bulk data transfers can take a long time, if we wait until + * all are done before we acknowledge the signals, the UniFi runs out + * of buffer space. Therefore we keep a count of the bytes transferred + * in bulk data commands, and update the to-host-signals-read count + * if we've done a large transfer. + * + * All data in the f/w is stored in a little endian format, without any + * padding bytes. Every read from the memory has to be transformed in + * host (cpu specific) format, before we can process it. Therefore we + * use read_unpack_cmd() and read_unpack_signal() to convert the raw data + * contained in the card->th_buffer.buf to host structures. + * Important: UDI clients use wire-formatted structures, so we need to + * indicate all data, as we have read it from the device. + * --------------------------------------------------------------------------- + */ +static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed) +{ + CsrInt16 pending; + CsrInt16 remaining; + CsrUint8 *bufptr; + bulk_data_param_t data_ptrs; + CsrInt16 cmd; + CsrUint16 sig_len; + CsrInt16 i; + CsrUint16 chunks_in_buf; + CsrUint16 bytes_transferred = 0; + CsrResult r = CSR_RESULT_SUCCESS; + + *processed = 0; + + pending = card->th_buffer.count; + + /* Are there new to-host signals? */ + unifi_trace(card->ospriv, UDBG4, "handling %d to-host chunks\n", pending); + + if (!pending) + { + return CSR_RESULT_SUCCESS; + } + + /* + * This is a pointer to the raw data we have read from the f/w. + * Can be a signal or a command. Note that we need to convert + * it to a host structure before we process it. + */ + bufptr = card->th_buffer.buf; + + while (pending > 0) + { + CsrInt16 f_flush_count = 0; + + /* + * Command and length are common to signal and bulk data msgs. + * If command == 0 (i.e. a signal), len is number of bytes + * *following* the 2-byte header. + */ + cmd = bufptr[1] >> 4; + sig_len = bufptr[0] + ((bufptr[1] & 0x0F) << 8); + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Received UniFi msg cmd=%d, len=%d\n", + cmd, sig_len); +#endif /* CSR_WIFI_HIP_NOISY */ + + if ((sig_len == 0) && + ((cmd != SDIO_CMD_CLEAR_SLOT) && (cmd != SDIO_CMD_PADDING))) + { + unifi_error(card->ospriv, "incomplete signal or command: has size zero\n"); + return CSR_RESULT_FAILURE; + } + /* + * Make sure the buffer contains a complete message. + * Signals may occupy multiple chunks, bulk-data commands occupy + * one chunk. + */ + if (cmd == SDIO_CMD_SIGNAL) + { + chunks_in_buf = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (CsrUint16)(sig_len + 2)); + } + else + { + chunks_in_buf = 1; + } + + if (chunks_in_buf > (CsrUint16)pending) + { + unifi_error(card->ospriv, "incomplete signal (0x%x?): need %d chunks, got %d\n", + GET_SIGNAL_ID(bufptr + 2), + chunks_in_buf, pending); + unifi_error(card->ospriv, " thsw=%d, thsr=%d\n", + card->to_host_signals_w, + card->to_host_signals_r); + return CSR_RESULT_FAILURE; + } + + + switch (cmd) + { + case SDIO_CMD_SIGNAL: + /* This is a signal. Read the rest of it and then handle it. */ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.sdio_cmd_signal++; +#endif + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + /* Retrieve dataRefs[i].DataLength */ + CsrUint16 data_len = GET_PACKED_DATAREF_LEN(bufptr + 2, i); + + /* + * The bulk data length in the signal can not be greater than + * the maximun length allowed by the SDIO config structure. + */ + if (data_len > card->config_data.data_slot_size) + { + unifi_error(card->ospriv, + "Bulk Data length (%d) exceeds Maximum Bulk Data length (%d)\n", + data_len, card->config_data.data_slot_size); + return CSR_RESULT_FAILURE; + } + + /* + * Len here might not be the same as the length in the + * bulk data slot. The slot length will always be even, + * but len could be odd. + */ + if (data_len != 0) + { + /* Retrieve dataRefs[i].SlotNumber */ + CsrInt16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i); + + if (slot >= card->config_data.num_tohost_data_slots) + { + unifi_error(card->ospriv, "!!!bad slot number in to-host signal: %d, sig 0x%X\n", + slot, cmd); + return CSR_RESULT_FAILURE; + } + + data_ptrs.d[i].os_data_ptr = card->to_host_data[slot].os_data_ptr; + data_ptrs.d[i].os_net_buf_ptr = card->to_host_data[slot].os_net_buf_ptr; + data_ptrs.d[i].net_buf_length = card->to_host_data[slot].net_buf_length; + data_ptrs.d[i].data_length = data_len; + } + else + { + UNIFI_INIT_BULK_DATA(&data_ptrs.d[i]); + } + } + + /* + * Log the signal to the UDI, before call unifi_receive_event() as + * it can modify the bulk data. + */ + if (card->udi_hook) + { + (*card->udi_hook)(card->ospriv, bufptr + 2, sig_len, + &data_ptrs, UDI_LOG_TO_HOST); + } + +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID) + { + card->cmd_prof.tx_cfm_count++; + } + else if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_INDICATION_ID) + { + if (data_ptrs.d[0].os_data_ptr) + { + if ((*data_ptrs.d[0].os_data_ptr) & 0x08) + { + card->cmd_prof.rx_count++; + } + } + } +#endif + /* + * Check if the signal is MA-PACKET.cfm and if so check the status. + * If the status is failure, search through the slot records to find + * if any slots are occupied for this host tag. This can happen if + * f/w has not downloaded the bulkdata and before that itself it has + * signalled the confirm with failure. If it finds a slot with that + * host tag then, it clears the corresponding slot + */ + + if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID) + { + /* Get host tag and transmission status */ + CsrUint32 host_tag = GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(bufptr + 2); + CsrUint16 status = GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(bufptr + 2); + + unifi_trace(card->ospriv, UDBG4, "process_to_host_signals signal ID=%x host Tag=%x status=%x\n", + GET_SIGNAL_ID(bufptr + 2), host_tag, status); + + /* If transmission status is failure then search through the slot records + * and if for any slot records the clear slot is not done then do it now + */ + + if (status && (card->fh_slot_host_tag_record)) + { + CsrUint16 num_fh_slots = card->config_data.num_fromhost_data_slots; + CsrUint16 i = 0; + + /* search through the list of slot records and match with host tag + * If a slot is not yet cleared then clear the slot from here + */ + for (i = 0; i < num_fh_slots; i++) + { + if (card->fh_slot_host_tag_record[i] == host_tag) + { + unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag); + card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; + + /* Set length field in from_host_data array to 0 */ + CardClearFromHostDataSlot(card, i); + + break; + } + } + } + } + + /* Pass event to OS layer */ + unifi_receive_event(card->ospriv, bufptr + 2, sig_len, &data_ptrs); + + /* Initialise the to_host data, so it can be re-used. */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + /* The slot is only valid if the length is non-zero. */ + if (GET_PACKED_DATAREF_LEN(bufptr + 2, i) != 0) + { + CsrInt16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i); + if (slot < card->config_data.num_tohost_data_slots) + { + UNIFI_INIT_BULK_DATA(&card->to_host_data[slot]); + } + } + } + +#ifndef CSR_WIFI_DEFER_TH_FLUSH + /* + * If we have previously transferred a lot of data, ack + * the signals read so far, so f/w can reclaim the buffer + * memory sooner. + */ + if (bytes_transferred >= TO_HOST_FLUSH_THRESHOLD) + { + f_flush_count = 1; + } +#endif + break; + + + case SDIO_CMD_CLEAR_SLOT: +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.sdio_cmd_clear_slot++; +#endif + /* This is a clear slot command. */ + if (sig_len != 0) + { + unifi_error(card->ospriv, "process_to_host_signals: clear slot, bad data len: 0x%X at offset %d\n", + sig_len, bufptr - card->th_buffer.buf); + return CSR_RESULT_FAILURE; + } + + r = process_clear_slot_command(card, bufptr); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to process clear slot\n"); + return r; + } + break; + + case SDIO_CMD_TO_HOST_TRANSFER: + case SDIO_CMD_FROM_HOST_TRANSFER: + case SDIO_CMD_FROM_HOST_AND_CLEAR: + case SDIO_CMD_OVERLAY_TRANSFER: + /* This is a bulk data command. */ + if (sig_len & 1) + { + unifi_error(card->ospriv, "process_to_host_signals: bulk data, bad data len: 0x%X at offset %d\n", + sig_len, bufptr - card->th_buffer.buf); + return CSR_RESULT_FAILURE; + } + + r = process_bulk_data_command(card, bufptr, cmd, sig_len); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to process bulk cmd\n"); + return r; + } + /* Count the bytes transferred */ + bytes_transferred += sig_len; + + if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.sdio_cmd_from_host_and_clear++; +#endif +#ifndef CSR_WIFI_DEFER_TH_FLUSH + f_flush_count = 1; +#endif + } +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + else if (cmd == SDIO_CMD_FROM_HOST_TRANSFER) + { + card->cmd_prof.sdio_cmd_from_host++; + } + else if (cmd == SDIO_CMD_TO_HOST_TRANSFER) + { + card->cmd_prof.sdio_cmd_to_host++; + } +#endif + break; + + case SDIO_CMD_PADDING: + break; + + default: + unifi_error(card->ospriv, "Unrecognised to-host command: %d\n", cmd); + break; + } + + bufptr += chunks_in_buf * card->config_data.sig_frag_size; + pending -= chunks_in_buf; + + /* + * Write out the host signal count when a significant + * number of bytes of bulk data have been transferred or + * when we have performed a CopyFromHostAndClear. + */ + if (f_flush_count) + { + r = update_to_host_signals_r(card, pending); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + bytes_transferred = 0; + } + } + + if (pending) + { + unifi_warning(card->ospriv, "proc_th_sigs: %d unprocessed\n", pending); + } + + /* If we processed any signals, write the updated count to UniFi */ + if (card->th_buffer.count != pending) + { + r = update_to_host_signals_r(card, pending); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + } + + /* + * Reset the buffer pointer, copying down any un-processed signals. + * This can happen if we enable the optimisation in read_to_host_signals() + * that limits the length to whole blocks. + */ + remaining = card->th_buffer.ptr - bufptr; + if (remaining < 0) + { + unifi_error(card->ospriv, "Processing TH signals overran the buffer\n"); + return CSR_RESULT_FAILURE; + } + if (remaining > 0) + { + /* Use a safe copy because source and destination may overlap */ + CsrUint8 *d = card->th_buffer.buf; + CsrUint8 *s = bufptr; + CsrInt32 n = remaining; + while (n--) + { + *d++ = *s++; + } + } + card->th_buffer.ptr = card->th_buffer.buf + remaining; + + + /* If we reach here then we processed something */ + *processed = 1; + return CSR_RESULT_SUCCESS; +} /* process_to_host_signals() */ + + +/* + * --------------------------------------------------------------------------- + * process_clear_slot_command + * + * Process a clear slot command fom the UniFi. + * + * Arguments: + * card Pointer to card context struct + * bdcmd Pointer to bulk-data command msg from UniFi + * + * Returns: + * 0 on success, CSR error code on error + * --------------------------------------------------------------------------- + */ +static CsrResult process_clear_slot_command(card_t *card, const CsrUint8 *cmdptr) +{ + CsrUint16 data_slot; + CsrInt16 slot; + + data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cmdptr + SIZEOF_UINT16); + + unifi_trace(card->ospriv, UDBG4, "Processing clear slot cmd, slot=0x%X\n", + data_slot); + + slot = data_slot & 0x7FFF; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "CMD clear data slot 0x%04x\n", data_slot); +#endif /* CSR_WIFI_HIP_NOISY */ + + if (data_slot & SLOT_DIR_TO_HOST) + { + if (slot >= card->config_data.num_tohost_data_slots) + { + unifi_error(card->ospriv, + "Invalid to-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n", + slot); + return CSR_RESULT_FAILURE; + } + /* clear to-host data slot */ + unifi_warning(card->ospriv, "Unexpected clear to-host data slot cmd: 0x%04x\n", + data_slot); + } + else + { + if (slot >= card->config_data.num_fromhost_data_slots) + { + unifi_error(card->ospriv, + "Invalid from-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n", + slot); + return CSR_RESULT_FAILURE; + } + + /* + * The driver is the owner to clear all slots now + * Ref - comment in process_fh_traffic_queue + * so it will just ignore the clear slot command from firmware + * and return success + */ + return CSR_RESULT_SUCCESS; + + /* Set length field in from_host_data array to 0 */ + /* CardClearFromHostDataSlot(card, slot); */ + } + + return CSR_RESULT_SUCCESS; +} /* process_clear_slot_command() */ + + +/* + * --------------------------------------------------------------------------- + * process_bulk_data_command + * + * Process a bulk data request from the UniFi. + * + * Arguments: + * card Pointer to card context struct + * bdcmd Pointer to bulk-data command msg from UniFi + * cmd, len Decoded values of command and length from the msg header + * Cmd will only be one of: + * SDIO_CMD_TO_HOST_TRANSFER + * SDIO_CMD_FROM_HOST_TRANSFER + * SDIO_CMD_FROM_HOST_AND_CLEAR + * SDIO_CMD_OVERLAY_TRANSFER + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on error + * --------------------------------------------------------------------------- + */ +static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr, + CsrInt16 cmd, CsrUint16 len) +{ + bulk_data_desc_t *bdslot; +#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND + CsrUint8 *host_bulk_data_slot; +#endif + bulk_data_cmd_t bdcmd; + CsrInt16 offset; + CsrInt16 slot; + CsrInt16 dir; + CsrResult r; + + read_unpack_cmd(cmdptr, &bdcmd); + + unifi_trace(card->ospriv, UDBG4, "Processing bulk data cmd %d %s, len=%d, slot=0x%X\n", + cmd, lookup_bulkcmd_name(cmd), len, bdcmd.data_slot); + + /* + * Round up the transfer length if required. + * This is useful to force all transfers to be a multiple of the SDIO block + * size, so the SDIO driver won't try to use a byte-mode CMD53. These are + * broken on some hardware platforms. + */ + if (card->sdio_io_block_pad) + { + len = (len + card->sdio_io_block_size - 1) & ~(card->sdio_io_block_size - 1); + unifi_trace(card->ospriv, UDBG4, "Rounded bulk data length up to %d\n", len); + } + + slot = bdcmd.data_slot & 0x7FFF; + + if (cmd == SDIO_CMD_OVERLAY_TRANSFER) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; /* Not used on CSR6xxx */ + } + else + { + if (bdcmd.data_slot & SLOT_DIR_TO_HOST) + { + /* Request is for to-host bulk data */ + + /* Check sanity of slot number */ + if (slot >= card->config_data.num_tohost_data_slots) + { + unifi_error(card->ospriv, + "Invalid to-host data slot in SDIO bulk xfr req: %d\n", + slot); + return CSR_RESULT_FAILURE; + } + + /* Allocate memory for card->to_host_data[slot] bulk data here. */ +#ifdef CSR_PRE_ALLOC_NET_DATA + r = prealloc_netdata_get(card, &card->to_host_data[slot], len); +#else + r = unifi_net_data_malloc(card->ospriv, &card->to_host_data[slot], len); +#endif + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to allocate t-h bulk data\n"); + return CSR_RESULT_FAILURE; + } + + bdslot = &card->to_host_data[slot]; + + /* Make sure that the buffer is 4-bytes aligned */ + r = unifi_net_dma_align(card->ospriv, bdslot); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to align t-h bulk data buffer for DMA\n"); + return CSR_RESULT_FAILURE; + } + } + else + { + /* Request is for from-host bulk data */ + + if (slot >= card->config_data.num_fromhost_data_slots) + { + unifi_error(card->ospriv, + "Invalid from-host data slot in SDIO bulk xfr req: %d\n", + slot); + return CSR_RESULT_FAILURE; + } + bdslot = &card->from_host_data[slot].bd; + } + offset = bdcmd.offset; + } + /* Do the transfer */ + dir = (cmd == SDIO_CMD_TO_HOST_TRANSFER)? + UNIFI_SDIO_READ : UNIFI_SDIO_WRITE; + + unifi_trace(card->ospriv, UDBG4, + "Bulk %c %s len=%d, handle %d - slot=%d %p+(%d)\n", + (dir == UNIFI_SDIO_READ)?'R' : 'W', + lookup_bulkcmd_name(cmd), + len, + bdcmd.buffer_handle, + slot, bdslot->os_data_ptr, offset); +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Bulk %s len=%d, handle %d - slot=%d %p+(%d)\n", + lookup_bulkcmd_name(cmd), + len, + bdcmd.buffer_handle, + slot, bdslot->os_data_ptr, offset); +#endif /* CSR_WIFI_HIP_NOISY */ + + + if (bdslot->os_data_ptr == NULL) + { + unifi_error(card->ospriv, "Null os_data_ptr - Bulk %s handle %d - slot=%d o=(%d)\n", + lookup_bulkcmd_name(cmd), + bdcmd.buffer_handle, + slot, + offset); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + +#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND + /* if os_data_ptr is not 4-byte aligned, then allocate a new buffer and copy data + to new buffer to ensure the address passed to unifi_bulk_rw is 4-byte aligned */ + + if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3)) + { + host_bulk_data_slot = CsrMemAlloc(len); + + if (!host_bulk_data_slot) + { + unifi_error(card->ospriv, " failed to allocate request_data before unifi_bulk_rw\n"); + return -1; + } + + CsrMemCpy((void *)host_bulk_data_slot, + (void *)(bdslot->os_data_ptr + offset), len); + + r = unifi_bulk_rw(card, + bdcmd.buffer_handle, + (void *)host_bulk_data_slot, + len, + dir); + } + else +#endif + { + r = unifi_bulk_rw(card, + bdcmd.buffer_handle, + (void *)(bdslot->os_data_ptr + offset), + len, + dir); + } + + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, + "Failed: %s hlen=%d, slen=%d, handle %d - slot=%d %p+0x%X\n", + lookup_bulkcmd_name(cmd), + len, /* Header length */ + bdslot->data_length, /* Length stored in slot */ + bdcmd.buffer_handle, + slot, bdslot->os_data_ptr, offset); + return r; + } + + bdslot->data_length = len; + + if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR) + { + if (slot >= card->config_data.num_fromhost_data_slots) + { + unifi_error(card->ospriv, + "Invalid from-host data slot in SDIO_CMD_FROM_HOST_AND_CLEAR: %d\n", + slot); + return CSR_RESULT_FAILURE; + } + +#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND + /* moving this check before we clear host data slot */ + if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3)) + { + CsrMemFree(host_bulk_data_slot); + } +#endif + + if (card->fh_slot_host_tag_record) + { + unifi_trace(card->ospriv, UDBG5, "CopyFromHostAndClearSlot Reset entry for slot=%d\n", slot); + + /* reset the host tag entry for the corresponding slot */ + card->fh_slot_host_tag_record[slot] = CSR_WIFI_HIP_RESERVED_HOST_TAG; + } + + + /* Set length field in from_host_data array to 0 */ + CardClearFromHostDataSlot(card, slot); + } + + return CSR_RESULT_SUCCESS; +} /* process_bulk_data_command() */ + + +/* + * --------------------------------------------------------------------------- + * check_fh_sig_slots + * + * Check whether there are free signal slots available on UniFi. + * This takes into account the signals already batched since the + * from_host_signal counts were last read. + * If the from_host_signal counts indicate not enough space, we read + * the latest count from UniFi to see if some more have been freed. + * + * Arguments: + * None. + * + * Returns: + * CSR_RESULT_SUCCESS, otherwise CSR error code on error. + * --------------------------------------------------------------------------- + */ +static CsrResult check_fh_sig_slots(card_t *card, CsrUint16 needed, CsrInt32 *space_fh) +{ + CsrUint32 count_fhw; + CsrUint32 occupied_fh, slots_fh; + CsrInt32 count_fhr; + + count_fhw = card->from_host_signals_w; + count_fhr = card->from_host_signals_r; + slots_fh = card->config_data.num_fromhost_sig_frags; + + /* Only read the space in from-host queue if necessary */ + occupied_fh = (count_fhw - count_fhr) % 128; + + if (slots_fh < occupied_fh) + { + *space_fh = 0; + } + else + { + *space_fh = slots_fh - occupied_fh; + } + + if ((occupied_fh != 0) && (*space_fh < needed)) + { + count_fhr = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); + if (count_fhr < 0) + { + unifi_error(card->ospriv, "Failed to read from-host sig read count\n"); + return CSR_RESULT_FAILURE; + } + card->from_host_signals_r = count_fhr; /* diag */ + + occupied_fh = (count_fhw - count_fhr) % 128; + *space_fh = slots_fh - occupied_fh; + } + + return CSR_RESULT_SUCCESS; +} /* check_fh_sig_slots() */ + + +/* +* If we are padding the From-Host signals to the SDIO block size, +* we need to round up the needed_chunks to the SDIO block size. +*/ +#define ROUND_UP_NEEDED_CHUNKS(_card, _needed_chunks) \ + { \ + CsrUint16 _chunks_per_block; \ + CsrUint16 _chunks_in_last_block; \ + \ + if (_card->sdio_io_block_pad) \ + { \ + _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \ + _chunks_in_last_block = _needed_chunks % _chunks_per_block; \ + if (_chunks_in_last_block != 0) \ + { \ + _needed_chunks = _needed_chunks + (_chunks_per_block - _chunks_in_last_block); \ + } \ + } \ + } + + +#define ROUND_UP_SPACE_CHUNKS(_card, _space_chunks) \ + { \ + CsrUint16 _chunks_per_block; \ + \ + if (_card->sdio_io_block_pad) \ + { \ + _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \ + _space_chunks = ((_space_chunks / _chunks_per_block) * _chunks_per_block); \ + } \ + } + + + + + +/* + * --------------------------------------------------------------------------- + * process_fh_cmd_queue + * + * Take one signal off the from-host queue and copy it to the UniFi. + * Does nothing if the UniFi has no slots free. + * + * Arguments: + * card Pointer to card context struct + * processed Location to write: + * 0 if there is nothing on the queue to process + * 1 if a signal was successfully processed + * + * Returns: + * CSR error code if an error occurred. + * + * Notes: + * The from-host queue contains signal requests from the network driver + * and any UDI clients interspersed. UDI clients' requests have been stored + * in the from-host queue using the wire-format structures, as they arrive. + * All other requests are stored in the from-host queue using the host + * (cpu specific) structures. We use the is_packed member of the card_signal_t + * structure that describes the queue to make the distiction. + * --------------------------------------------------------------------------- + */ +static CsrResult process_fh_cmd_queue(card_t *card, CsrInt32 *processed) +{ + q_t *sigq = &card->fh_command_queue; + + CsrResult r; + CsrUint16 pending_sigs; + CsrUint16 pending_chunks; + CsrUint16 needed_chunks; + CsrInt32 space_chunks; + CsrUint16 q_index; + + *processed = 0; + + /* Get the number of pending signals. */ + pending_sigs = CSR_WIFI_HIP_Q_SLOTS_USED(sigq); + unifi_trace(card->ospriv, UDBG5, "proc_fh: %d pending\n", pending_sigs); + if (pending_sigs == 0) + { + /* Nothing to do */ + return CSR_RESULT_SUCCESS; + } + + /* Work out how many chunks we have waiting to send */ + for (pending_chunks = 0, q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq); + q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq); + q_index = CSR_WIFI_HIP_Q_WRAP(sigq, q_index + 1)) + { + card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index); + + /* + * Note that GET_CHUNKS_FOR() needs the size of the packed + * (wire-formatted) structure + */ + pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (CsrUint16)(csptr->signal_length + 2)); + } + + /* + * Check whether UniFi has space for all the buffered bulk-data + * commands and signals as well. + */ + needed_chunks = pending_chunks + card->fh_buffer.count; + + /* Round up to the block size if necessary */ + ROUND_UP_NEEDED_CHUNKS(card, needed_chunks); + + r = check_fh_sig_slots(card, needed_chunks, &space_chunks); + if (r != CSR_RESULT_SUCCESS) + { + /* Error */ + unifi_error(card->ospriv, "Failed to read fh sig count\n"); + return r; + } + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "proc_fh: %d chunks free, need %d\n", + space_chunks, needed_chunks); +#endif /* CSR_WIFI_HIP_NOISY */ + + + /* + * Coalesce as many from-host signals as possible + * into a single block and write using a single CMD53 + */ + if (needed_chunks > (CsrUint16)space_chunks) + { + /* Round up to the block size if necessary */ + ROUND_UP_SPACE_CHUNKS(card, space_chunks); + + /* + * If the f/w has less free chunks than those already pending + * return immediately. + */ + if ((CsrUint16)space_chunks <= card->fh_buffer.count) + { + /* + * No room in UniFi for any signals after the buffered bulk + * data commands have been sent. + */ + unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n", + card->fh_buffer.count, space_chunks); + card->generate_interrupt = 1; + return CSR_RESULT_SUCCESS; + } + pending_chunks = (CsrUint16)(space_chunks - card->fh_buffer.count); + } + + while (pending_sigs-- && pending_chunks > 0) + { + card_signal_t *csptr; + CsrInt16 i; + CsrUint16 sig_chunks, total_length, free_chunks_in_fh_buffer; + bulk_data_param_t bulkdata; + CsrUint8 *packed_sigptr; + CsrUint16 signal_length = 0; + + /* Retrieve the entry at the head of the queue */ + q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq); + + /* Get a pointer to the containing card_signal_t struct */ + csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index); + + /* Get the new length of the packed signal */ + signal_length = csptr->signal_length; + + if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE)) + { + unifi_error(card->ospriv, "process_fh_queue: Bad len: %d\n", signal_length); + return CSR_RESULT_FAILURE; + } + + /* Need space for 2-byte SDIO protocol header + signal */ + sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (CsrUint16)(signal_length + 2)); + + free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size, + (CsrUint16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr)); + if (free_chunks_in_fh_buffer < sig_chunks) + { + /* No more room */ + unifi_notice(card->ospriv, "proc_fh_cmd_q: no room in fh buffer for 0x%.4X, deferring\n", + (CsrUint16)(GET_SIGNAL_ID(csptr->sigbuf))); + break; + } + + packed_sigptr = csptr->sigbuf; + + /* Claim and set up a from-host data slot */ + if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, UNIFI_TRAFFIC_Q_MLME)) + { + unifi_notice(card->ospriv, "proc_fh_cmd_q: no fh data slots for 0x%.4X, deferring\n", + (CsrUint16)(GET_SIGNAL_ID(csptr->sigbuf))); + break; + } + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + if (csptr->bulkdata[i].data_length == 0) + { + UNIFI_INIT_BULK_DATA(&bulkdata.d[i]); + } + else + { + bulkdata.d[i].os_data_ptr = csptr->bulkdata[i].os_data_ptr; + bulkdata.d[i].data_length = csptr->bulkdata[i].data_length; + } + + /* Pass the free responsibility to the lower layer. */ + UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]); + } + + unifi_trace(card->ospriv, UDBG2, "Sending signal 0x%.4X\n", + GET_SIGNAL_ID(packed_sigptr)); +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Sending signal 0x%.4X\n", + GET_SIGNAL_ID(packed_sigptr)); +#endif /* CSR_WIFI_HIP_NOISY */ + + + /* Append packed signal to F-H buffer */ + total_length = sig_chunks * card->config_data.sig_frag_size; + + card->fh_buffer.ptr[0] = (CsrUint8)(signal_length & 0xff); + card->fh_buffer.ptr[1] = + (CsrUint8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4)); + + CsrMemCpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length); + CsrMemSet(card->fh_buffer.ptr + 2 + signal_length, 0, + total_length - (2 + signal_length)); + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n", + signal_length + 2); + dump(card->fh_buffer.ptr, signal_length + 2); + unifi_trace(card->ospriv, UDBG1, " \n"); +#endif /* CSR_WIFI_HIP_NOISY */ + + card->fh_buffer.ptr += total_length; + card->fh_buffer.count += sig_chunks; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n", + signal_length, + card->fh_buffer.ptr - card->fh_buffer.buf, + card->fh_buffer.count); +#endif /* CSR_WIFI_HIP_NOISY */ + + (*processed)++; + pending_chunks -= sig_chunks; + + /* Log the signal to the UDI. */ + /* UDI will get the packed structure */ + /* Can not log the unpacked signal, unless we reconstruct it! */ + if (card->udi_hook) + { + (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length, + &bulkdata, UDI_LOG_FROM_HOST); + } + + /* Remove entry from q */ + csptr->signal_length = 0; + CSR_WIFI_HIP_Q_INC_R(sigq); + } + + return CSR_RESULT_SUCCESS; +} /* process_fh_cmd_queue() */ + + +/* + * --------------------------------------------------------------------------- + * process_fh_traffic_queue + * + * Take signals off the from-host queue and copy them to the UniFi. + * Does nothing if the UniFi has no slots free. + * + * Arguments: + * card Pointer to card context struct + * sigq Pointer to the traffic queue + * processed Pointer to location to write: + * 0 if there is nothing on the queue to process + * 1 if a signal was successfully processed + * + * Returns: + * CSR error code if an error occurred. + * + * Notes: + * The from-host queue contains signal requests from the network driver + * and any UDI clients interspersed. + * --------------------------------------------------------------------------- + */ +static CsrResult process_fh_traffic_queue(card_t *card, CsrInt32 *processed) +{ + q_t *sigq = card->fh_traffic_queue; + + CsrResult r; + CsrInt16 n = 0; + CsrInt32 q_no; + CsrUint16 pending_sigs = 0; + CsrUint16 pending_chunks = 0; + CsrUint16 needed_chunks; + CsrInt32 space_chunks; + CsrUint16 q_index; + CsrUint32 host_tag = 0; + CsrUint16 slot_num = 0; + + *processed = 0; + + /* calculate how many signals are in queues and how many chunks are needed. */ + for (n = UNIFI_NO_OF_TX_QS - 1; n >= 0; n--) + { + /* Get the number of pending signals. */ + pending_sigs += CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[n]); + unifi_trace(card->ospriv, UDBG5, "proc_fh%d: %d pending\n", n, pending_sigs); + + /* Work out how many chunks we have waiting to send */ + for (q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[n]); + q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(&sigq[n]); + q_index = CSR_WIFI_HIP_Q_WRAP(&sigq[n], q_index + 1)) + { + card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[n], q_index); + + /* + * Note that GET_CHUNKS_FOR() needs the size of the packed + * (wire-formatted) structure + */ + pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (CsrUint16)(csptr->signal_length + 2)); + } + } + + /* If there are no pending signals, just return */ + if (pending_sigs == 0) + { + /* Nothing to do */ + return CSR_RESULT_SUCCESS; + } + + /* + * Check whether UniFi has space for all the buffered bulk-data + * commands and signals as well. + */ + needed_chunks = pending_chunks + card->fh_buffer.count; + + /* Round up to the block size if necessary */ + ROUND_UP_NEEDED_CHUNKS(card, needed_chunks); + + r = check_fh_sig_slots(card, needed_chunks, &space_chunks); + if (r != CSR_RESULT_SUCCESS) + { + /* Error */ + unifi_error(card->ospriv, "Failed to read fh sig count\n"); + return r; + } + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, + "process_fh_traffic_queue: %d chunks free, need %d\n", + space_chunks, needed_chunks); + read_fhsr(card); /* debugging only */ +#endif /* CSR_WIFI_HIP_NOISY */ + + /* Coalesce as many from-host signals as possible + into a single block and write using a single CMD53 */ + if (needed_chunks > (CsrUint16)space_chunks) + { + /* Round up to the block size if necessary */ + ROUND_UP_SPACE_CHUNKS(card, space_chunks); + + if ((CsrUint16)space_chunks <= card->fh_buffer.count) + { + /* + * No room in UniFi for any signals after the buffered bulk + * data commands have been sent. + */ + unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n", + card->fh_buffer.count, space_chunks); + card->generate_interrupt = 1; + return 0; + } + + pending_chunks = (CsrUint16)space_chunks - card->fh_buffer.count; + } + + q_no = UNIFI_NO_OF_TX_QS - 1; + + /* + * pending_sigs will be exhausted if there are is no restriction to the pending + * signals per queue. pending_chunks may be exhausted if there is a restriction. + * q_no check will be exhausted if there is a restriction and our round-robin + * algorith fails to fill all chunks. + */ + do + { + card_signal_t *csptr; + CsrUint16 sig_chunks, total_length, free_chunks_in_fh_buffer; + bulk_data_param_t bulkdata; + CsrUint8 *packed_sigptr; + CsrUint16 signal_length = 0; + + /* if this queue is empty go to next one. */ + if (CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[q_no]) == 0) + { + q_no--; + continue; + } + + /* Retrieve the entry at the head of the queue */ + q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[q_no]); + + /* Get a pointer to the containing card_signal_t struct */ + csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[q_no], q_index); + + /* Get the new length of the packed signal */ + signal_length = csptr->signal_length; + + if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE)) + { + unifi_error(card->ospriv, "process_fh_traffic_queue: Bad len: %d\n", signal_length); + return CSR_RESULT_FAILURE; + } + + /* Need space for 2-byte SDIO protocol header + signal */ + sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (CsrUint16)(signal_length + 2)); + free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size, + (CsrUint16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr)); + if (free_chunks_in_fh_buffer < sig_chunks) + { + /* No more room */ + unifi_notice(card->ospriv, "process_fh_traffic_queue: no more chunks.\n"); + break; + } + + packed_sigptr = csptr->sigbuf; + /* Claim and set up a from-host data slot */ + if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, (unifi_TrafficQueue)q_no)) + { + q_no--; + continue; + } + + /* Sanity check: MA-PACKET.req must have a valid bulk data */ + if ((csptr->bulkdata[0].data_length == 0) || (csptr->bulkdata[0].os_data_ptr == NULL)) + { + unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n", + csptr->bulkdata[0].data_length, csptr->bulkdata[0].os_data_ptr); + dump(packed_sigptr, signal_length); + return CSR_RESULT_FAILURE; + } + + bulkdata.d[0].os_data_ptr = csptr->bulkdata[0].os_data_ptr; + bulkdata.d[0].data_length = csptr->bulkdata[0].data_length; + bulkdata.d[0].os_net_buf_ptr = csptr->bulkdata[0].os_net_buf_ptr; + bulkdata.d[0].net_buf_length = csptr->bulkdata[0].net_buf_length; + + /* The driver owns clearing of HIP slots for following scenario + * - driver has requested a MA-PACKET.req signal + * - The f/w after receiving the signal decides it can't send it out due to various reasons + * - So the f/w without downloading the bulk data decides to just send a confirmation with fail + * - and then sends a clear slot signal to HIP + * + * But in some cases the clear slot signal never comes and the slot remains --NOT-- freed for ever + * + * To handle this, HIP will keep the record of host tag for each occupied slot + * and then based on status of that Host tag and slot the driver will decide if the slot is + * cleared by f/w signal or the slot has to be freed by driver + */ + + if (card->fh_slot_host_tag_record) + { + /* Update the f-h slot record for the corresponding host tag */ + host_tag = GET_PACKED_MA_PACKET_REQUEST_HOST_TAG(packed_sigptr); + slot_num = GET_PACKED_DATAREF_SLOT(packed_sigptr, 0) & 0x00FF; + + unifi_trace(card->ospriv, UDBG5, + "process_fh_traffic_queue signal ID =%x fh slot=%x Host tag =%x\n", + GET_SIGNAL_ID(packed_sigptr), slot_num, host_tag); + card->fh_slot_host_tag_record[slot_num] = host_tag; + } + UNIFI_INIT_BULK_DATA(&bulkdata.d[1]); + UNIFI_INIT_BULK_DATA(&csptr->bulkdata[0]); + UNIFI_INIT_BULK_DATA(&csptr->bulkdata[1]); + +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + if (bulkdata.d[0].os_data_ptr) + { + if ((*bulkdata.d[0].os_data_ptr) & 0x08) + { + card->cmd_prof.tx_count++; + } + } +#endif + unifi_trace(card->ospriv, UDBG3, "Sending signal 0x%.4X\n", + GET_SIGNAL_ID(packed_sigptr)); +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Sending signal 0x%.4X\n", + GET_SIGNAL_ID(packed_sigptr)); +#endif /* CSR_WIFI_HIP_NOISY */ + + /* Append packed signal to F-H buffer */ + total_length = sig_chunks * card->config_data.sig_frag_size; + + card->fh_buffer.ptr[0] = (CsrUint8)(signal_length & 0xff); + card->fh_buffer.ptr[1] = + (CsrUint8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4)); + + CsrMemCpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length); + CsrMemSet(card->fh_buffer.ptr + 2 + signal_length, 0, + total_length - (2 + signal_length)); + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n", + signal_length + 2); + dump(card->fh_buffer.ptr, signal_length + 2); + unifi_trace(card->ospriv, UDBG1, " \n"); +#endif /* CSR_WIFI_HIP_NOISY */ + + card->fh_buffer.ptr += total_length; + card->fh_buffer.count += sig_chunks; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n", + signal_length, + card->fh_buffer.ptr - card->fh_buffer.buf, + card->fh_buffer.count); +#endif /* CSR_WIFI_HIP_NOISY */ + + (*processed)++; + pending_sigs--; + pending_chunks -= sig_chunks; + + /* Log the signal to the UDI. */ + /* UDI will get the packed structure */ + /* Can not log the unpacked signal, unless we reconstruct it! */ + if (card->udi_hook) + { + (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length, + &bulkdata, UDI_LOG_FROM_HOST); + } + + /* Remove entry from q */ + csptr->signal_length = 0; + /* Note that the traffic queue has only one valid bulk data buffer. */ + csptr->bulkdata[0].data_length = 0; + + CSR_WIFI_HIP_Q_INC_R(&sigq[q_no]); + } while ((pending_sigs > 0) && (pending_chunks > 0) && (q_no >= 0)); + + return CSR_RESULT_SUCCESS; +} /* process_fh_traffic_queue() */ + + +/* + * --------------------------------------------------------------------------- + * flush_fh_buffer + * + * Write out the cache from-hosts signals to the UniFi. + * + * Arguments: + * card Pointer to card context struct + * + * Returns: + * CSR error code if an SDIO error occurred. + * --------------------------------------------------------------------------- + */ +static CsrResult flush_fh_buffer(card_t *card) +{ + CsrResult r; + CsrUint16 len; + CsrUint16 sig_units; + CsrUint16 data_round; + CsrUint16 chunks_in_last_block; + CsrUint16 padding_chunks; + CsrUint16 i; + + len = card->fh_buffer.ptr - card->fh_buffer.buf; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "fh_buffer is at %p, ptr= %p\n", + card->fh_buffer.buf, card->fh_buffer.ptr); +#endif /* CSR_WIFI_HIP_NOISY */ + + if (len == 0) + { + return CSR_RESULT_SUCCESS; + } + +#ifdef CSR_WIFI_HIP_NOISY + if (dump_fh_buf) + { + dump(card->fh_buffer.buf, len); + dump_fh_buf = 0; + } +#endif /* CSR_WIFI_HIP_NOISY */ + + if (card->sdio_io_block_pad) + { + /* Both of these are powers of 2 */ + sig_units = card->config_data.sig_frag_size; + data_round = card->sdio_io_block_size; + + if (data_round > sig_units) + { + chunks_in_last_block = (len % data_round) / sig_units; + + if (chunks_in_last_block != 0) + { + padding_chunks = (data_round / sig_units) - chunks_in_last_block; + + CsrMemSet(card->fh_buffer.ptr, 0, padding_chunks * sig_units); + for (i = 0; i < padding_chunks; i++) + { + card->fh_buffer.ptr[1] = SDIO_CMD_PADDING << 4; + card->fh_buffer.ptr += sig_units; + } + + card->fh_buffer.count += padding_chunks; + len += padding_chunks * sig_units; + } + } + } + + r = unifi_bulk_rw(card, + card->config_data.fromhost_sigbuf_handle, + card->fh_buffer.buf, + len, UNIFI_SDIO_WRITE); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write fh signals: %u bytes, error %d\n", len, r); + return r; + } + + /* Update from-host-signals-written signal count */ + card->from_host_signals_w = + (card->from_host_signals_w + card->fh_buffer.count) % 128u; + r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 0, + (CsrUint8)card->from_host_signals_w); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write fh signal count %u with error %d\n", + card->from_host_signals_w, r); + return r; + } + card->generate_interrupt = 1; + + /* Reset the fh buffer pointer */ + card->fh_buffer.ptr = card->fh_buffer.buf; + card->fh_buffer.count = 0; + +#ifdef CSR_WIFI_HIP_NOISY + unifi_error(card->ospriv, "END flush: fh len %d, count %d\n", + card->fh_buffer.ptr - card->fh_buffer.buf, + card->fh_buffer.count); +#endif /* CSR_WIFI_HIP_NOISY */ + + return CSR_RESULT_SUCCESS; +} /* flush_fh_buffer() */ + + +/* + * --------------------------------------------------------------------------- + * restart_packet_flow + * + * This function is called before the bottom-half thread sleeps. + * It checks whether both data and signal resources are available and + * then calls the OS-layer function to re-enable packet transmission. + * + * Arguments: + * card Pointer to card context struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void restart_packet_flow(card_t *card) +{ + CsrUint8 q; + + /* + * We only look at the fh_traffic_queue, because that is where packets from + * the network stack are placed. + */ + for (q = 0; q <= UNIFI_TRAFFIC_Q_VO; q++) + { + if (card_is_tx_q_paused(card, q) && + CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[q]) >= RESUME_XMIT_THRESHOLD) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("U"); +#endif + card_tx_q_unpause(card, q); + unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue)q); + } + } +} /* restart_packet_flow() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c new file mode 100644 index 000000000000..403641d4df02 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c @@ -0,0 +1,1713 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_card_sdio_mem.c + * + * PURPOSE: Implementation of the Card API for SDIO. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_card.h" + +#define SDIO_RETRIES 3 +#define CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH 16 + + +#define retryable_sdio_error(_csrResult) (((_csrResult) == CSR_SDIO_RESULT_CRC_ERROR) || ((_csrResult) == CSR_SDIO_RESULT_TIMEOUT)) + + +/* + * --------------------------------------------------------------------------- + * retrying_read8 + * retrying_write8 + * + * These functions provide the first level of retry for SDIO operations. + * If an SDIO command fails for reason of a response timeout or CRC + * error, it is retried immediately. If three attempts fail we report a + * failure. + * If the command failed for any other reason, the failure is reported + * immediately. + * + * Arguments: + * card Pointer to card structure. + * funcnum The SDIO function to access. + * Function 0 is the Card Configuration Register space, + * function 1/2 is the UniFi register space. + * addr Address to access + * pdata Pointer in which to return the value read. + * data Value to write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +static CsrResult retrying_read8(card_t *card, CsrInt16 funcnum, CsrUint32 addr, CsrUint8 *pdata) +{ + CsrSdioFunction *sdio = card->sdio_if; + CsrResult r = CSR_RESULT_SUCCESS; + CsrInt16 retries; + CsrResult csrResult = CSR_RESULT_SUCCESS; + + retries = 0; + while (retries++ < SDIO_RETRIES) + { + if (funcnum == 0) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("r0@%02X", addr); +#endif + csrResult = CsrSdioF0Read8(sdio, addr, pdata); + } + else + { +#ifdef CSR_WIFI_TRANSPORT_CSPI + unifi_error(card->ospriv, + "retrying_read_f0_8: F1 8-bit reads are not allowed.\n"); + return CSR_RESULT_FAILURE; +#else +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("r@%02X", addr); +#endif + csrResult = CsrSdioRead8(sdio, addr, pdata); +#endif + } +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf("error=%X\n", csrResult); + } + else + { + unifi_debug_log_to_buf("=%X\n", *pdata); + } +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + /* + * Try again for retryable (CRC or TIMEOUT) errors, + * break on success or fatal error + */ + if (!retryable_sdio_error(csrResult)) + { +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.cmd52_count++; +#endif + break; + } + unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); + } + + if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) + { + unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); + } + + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", + addr, retries - 1); + /* Report any SDIO error as a general i/o error */ + r = CSR_RESULT_FAILURE; + } + + return r; +} /* retrying_read8() */ + + +static CsrResult retrying_write8(card_t *card, CsrInt16 funcnum, CsrUint32 addr, CsrUint8 data) +{ + CsrSdioFunction *sdio = card->sdio_if; + CsrResult r = CSR_RESULT_SUCCESS; + CsrInt16 retries; + CsrResult csrResult = CSR_RESULT_SUCCESS; + + retries = 0; + while (retries++ < SDIO_RETRIES) + { + if (funcnum == 0) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("w0@%02X=%X", addr, data); +#endif + csrResult = CsrSdioF0Write8(sdio, addr, data); + } + else + { +#ifdef CSR_WIFI_TRANSPORT_CSPI + unifi_error(card->ospriv, + "retrying_write_f0_8: F1 8-bit writes are not allowed.\n"); + return CSR_RESULT_FAILURE; +#else +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("w@%02X=%X", addr, data); +#endif + csrResult = CsrSdioWrite8(sdio, addr, data); +#endif + } +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf(",error=%X", csrResult); + } + unifi_debug_string_to_buf("\n"); +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + /* + * Try again for retryable (CRC or TIMEOUT) errors, + * break on success or fatal error + */ + if (!retryable_sdio_error(csrResult)) + { +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.cmd52_count++; +#endif + break; + } + unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", + data, funcnum, addr); + } + + if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) + { + unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); + } + + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", + addr, retries - 1); + /* Report any SDIO error as a general i/o error */ + r = CSR_RESULT_FAILURE; + } + + return r; +} /* retrying_write8() */ + + +static CsrResult retrying_read16(card_t *card, CsrInt16 funcnum, + CsrUint32 addr, CsrUint16 *pdata) +{ + CsrSdioFunction *sdio = card->sdio_if; + CsrResult r = CSR_RESULT_SUCCESS; + CsrInt16 retries; + CsrResult csrResult = CSR_RESULT_SUCCESS; + + retries = 0; + while (retries++ < SDIO_RETRIES) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("r@%02X", addr); +#endif + csrResult = CsrSdioRead16(sdio, addr, pdata); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf("error=%X\n", csrResult); + } + else + { + unifi_debug_log_to_buf("=%X\n", *pdata); + } +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + + /* + * Try again for retryable (CRC or TIMEOUT) errors, + * break on success or fatal error + */ + if (!retryable_sdio_error(csrResult)) + { +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.cmd52_count++; +#endif + break; + } + unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); + } + + if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) + { + unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); + } + + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", + addr, retries - 1); + /* Report any SDIO error as a general i/o error */ + r = CSR_RESULT_FAILURE; + } + + return r; +} /* retrying_read16() */ + + +static CsrResult retrying_write16(card_t *card, CsrInt16 funcnum, + CsrUint32 addr, CsrUint16 data) +{ + CsrSdioFunction *sdio = card->sdio_if; + CsrResult r = CSR_RESULT_SUCCESS; + CsrInt16 retries; + CsrResult csrResult = CSR_RESULT_SUCCESS; + + retries = 0; + while (retries++ < SDIO_RETRIES) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("w@%02X=%X", addr, data); +#endif + csrResult = CsrSdioWrite16(sdio, addr, data); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf(",error=%X", csrResult); + } + unifi_debug_string_to_buf("\n"); +#endif + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } + + /* + * Try again for retryable (CRC or TIMEOUT) errors, + * break on success or fatal error + */ + if (!retryable_sdio_error(csrResult)) + { +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.cmd52_count++; +#endif + break; + } + unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", + data, funcnum, addr); + } + + if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) + { + unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); + } + + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", + addr, retries - 1); + /* Report any SDIO error as a general i/o error */ + r = CSR_RESULT_FAILURE; + } + + return r; +} /* retrying_write16() */ + + +/* + * --------------------------------------------------------------------------- + * sdio_read_f0 + * + * Reads a byte value from the CCCR (func 0) area of UniFi. + * + * Arguments: + * card Pointer to card structure. + * addr Address to read from + * pdata Pointer in which to store the read value. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +CsrResult sdio_read_f0(card_t *card, CsrUint32 addr, CsrUint8 *pdata) +{ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_f0_r_count++; +#endif + return retrying_read8(card, 0, addr, pdata); +} /* sdio_read_f0() */ + + +/* + * --------------------------------------------------------------------------- + * sdio_write_f0 + * + * Writes a byte value to the CCCR (func 0) area of UniFi. + * + * Arguments: + * card Pointer to card structure. + * addr Address to read from + * data Data value to write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +CsrResult sdio_write_f0(card_t *card, CsrUint32 addr, CsrUint8 data) +{ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_f0_w_count++; +#endif + return retrying_write8(card, 0, addr, data); +} /* sdio_write_f0() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read_direct_8_or_16 + * + * Read a 8-bit value from the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Address to read from + * pdata Pointer in which to return data. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read_direct_8_or_16(card_t *card, CsrUint32 addr, CsrUint8 *pdata) +{ +#ifdef CSR_WIFI_TRANSPORT_CSPI + CsrUint16 w; + CsrResult r; + + r = retrying_read16(card, card->function, addr, &w); + *pdata = (CsrUint8)(w & 0xFF); + return r; +#else + return retrying_read8(card, card->function, addr, pdata); +#endif +} /* unifi_read_direct_8_or_16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_write_direct_8_or_16 + * + * Write a byte value to the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Address to write to + * data Value to write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error + * + * Notes: + * If 8-bit write is used, the even address *must* be written second. + * This is because writes to odd bytes are cached and not committed + * to memory until the preceding even address is written. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_write_direct_8_or_16(card_t *card, CsrUint32 addr, CsrUint8 data) +{ + if (addr & 1) + { + unifi_warning(card->ospriv, + "Warning: Byte write to an odd address (0x%lX) is dangerous\n", + addr); + } + +#ifdef CSR_WIFI_TRANSPORT_CSPI + return retrying_write16(card, card->function, addr, (CsrUint16)data); +#else + return retrying_write8(card, card->function, addr, data); +#endif +} /* unifi_write_direct_8_or_16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read_direct16 + * + * Read a 16-bit value from the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Address to read from + * pdata Pointer in which to return data. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * The even address *must* be read first. This is because reads from + * odd bytes are cached and read from memory when the preceding + * even address is read. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read_direct16(card_t *card, CsrUint32 addr, CsrUint16 *pdata) +{ + return retrying_read16(card, card->function, addr, pdata); +} /* unifi_read_direct16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_write_direct16 + * + * Write a 16-bit value to the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Address to write to + * data Value to write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * The even address *must* be written second. This is because writes to + * odd bytes are cached and not committed to memory until the preceding + * even address is written. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_write_direct16(card_t *card, CsrUint32 addr, CsrUint16 data) +{ + return retrying_write16(card, card->function, addr, data); +} /* unifi_write_direct16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read_direct32 + * + * Read a 32-bit value from the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Address to read from + * pdata Pointer in which to return data. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read_direct32(card_t *card, CsrUint32 addr, CsrUint32 *pdata) +{ + CsrResult r; + CsrUint16 w0, w1; + + r = retrying_read16(card, card->function, addr, &w0); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + r = retrying_read16(card, card->function, addr + 2, &w1); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + *pdata = ((CsrUint32)w1 << 16) | (CsrUint32)w0; + + return CSR_RESULT_SUCCESS; +} /* unifi_read_direct32() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read_directn_match + * + * Read multiple 8-bit values from the UniFi SDIO interface, + * stopping when either we have read 'len' bytes or we have read + * a octet equal to 'match'. If 'match' is not a valid octet + * then this function is the same as 'unifi_read_directn'. + * + * Arguments: + * card Pointer to card structure. + * addr Start address to read from. + * pdata Pointer to which to write data. + * len Maximum umber of bytes to read + * match The value to stop reading at. + * num Pointer to buffer to write number of bytes read + * + * Returns: + * number of octets read on success, negative error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * The even address *must* be read first. This is because reads from + * odd bytes are cached and read from memory when the preceding + * even address is read. + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_read_directn_match(card_t *card, CsrUint32 addr, void *pdata, CsrUint16 len, CsrInt8 m, CsrUint32 *num) +{ + CsrResult r; + CsrUint32 i; + CsrUint8 *cptr; + CsrUint16 w; + + *num = 0; + + cptr = (CsrUint8 *)pdata; + for (i = 0; i < len; i += 2) + { + r = retrying_read16(card, card->function, addr, &w); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + *cptr++ = ((CsrUint8)w & 0xFF); + if ((m >= 0) && (((CsrInt8)w & 0xFF) == m)) + { + break; + } + + if (i + 1 == len) + { + /* The len is odd. Ignore the last high byte */ + break; + } + + *cptr++ = ((CsrUint8)(w >> 8) & 0xFF); + if ((m >= 0) && (((CsrInt8)(w >> 8) & 0xFF) == m)) + { + break; + } + + addr += 2; + } + + *num = (CsrInt32)(cptr - (CsrUint8 *)pdata); + return CSR_RESULT_SUCCESS; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_read_directn + * + * Read multiple 8-bit values from the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Start address to read from. + * pdata Pointer to which to write data. + * len Number of bytes to read + * + * Returns: + * 0 on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * The even address *must* be read first. This is because reads from + * odd bytes are cached and read from memory when the preceding + * even address is read. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read_directn(card_t *card, CsrUint32 addr, void *pdata, CsrUint16 len) +{ + CsrUint32 num; + + return unifi_read_directn_match(card, addr, pdata, len, -1, &num); +} /* unifi_read_directn() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_write_directn + * + * Write multiple 8-bit values to the UniFi SDIO interface. + * + * Arguments: + * card Pointer to card structure. + * addr Start address to write to. + * pdata Source data pointer. + * len Number of bytes to write, must be even. + * + * Returns: + * 0 on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * The UniFi has a peculiar 16-bit bus architecture. Writes are only + * committed to memory when an even address is accessed. Writes to + * odd addresses are cached and only committed if the next write is + * to the preceding address. + * This means we must write data as pairs of bytes in reverse order. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_write_directn(card_t *card, CsrUint32 addr, void *pdata, CsrUint16 len) +{ + CsrResult r; + CsrUint8 *cptr; + CsrInt16 signed_len; + + cptr = (CsrUint8 *)pdata; + signed_len = (CsrInt16)len; + while (signed_len > 0) + { + /* This is UniFi-1 specific code. CSPI not supported so 8-bit write allowed */ + r = retrying_write16(card, card->function, addr, *cptr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + cptr += 2; + addr += 2; + signed_len -= 2; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_write_directn() */ + + +/* + * --------------------------------------------------------------------------- + * set_dmem_page + * set_pmem_page + * + * Set up the page register for the shared data memory window or program + * memory window. + * + * Arguments: + * card Pointer to card structure. + * dmem_addr UniFi shared-data-memory address to access. + * pmem_addr UniFi program memory address to access. This includes + * External FLASH memory at 0x000000 + * Processor program memory at 0x200000 + * External SRAM at memory 0x400000 + * paddr Location to write an SDIO address (24-bit) for + * use in a unifi_read_direct or unifi_write_direct call. + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +static CsrResult set_dmem_page(card_t *card, CsrUint32 dmem_addr, CsrUint32 *paddr) +{ + CsrUint16 page, addr; + CsrUint32 len; + CsrResult r; + + *paddr = 0; + + if (!ChipHelper_DecodeWindow(card->helper, + CHIP_HELPER_WINDOW_3, + CHIP_HELPER_WT_SHARED, + dmem_addr / 2, + &page, &addr, &len)) + { + unifi_error(card->ospriv, "Failed to decode SHARED_DMEM_PAGE %08lx\n", dmem_addr); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + if (page != card->dmem_page) + { + unifi_trace(card->ospriv, UDBG6, "setting dmem page=0x%X, addr=0x%lX\n", page, addr); + + /* change page register */ + r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW3_PAGE(card->helper) * 2, page); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n"); + return r; + } + + card->dmem_page = page; + } + + *paddr = ((CsrInt32)addr * 2) + (dmem_addr & 1); + + return CSR_RESULT_SUCCESS; +} /* set_dmem_page() */ + + +static CsrResult set_pmem_page(card_t *card, CsrUint32 pmem_addr, + enum chip_helper_window_type mem_type, CsrUint32 *paddr) +{ + CsrUint16 page, addr; + CsrUint32 len; + CsrResult r; + + *paddr = 0; + + if (!ChipHelper_DecodeWindow(card->helper, + CHIP_HELPER_WINDOW_2, + mem_type, + pmem_addr / 2, + &page, &addr, &len)) + { + unifi_error(card->ospriv, "Failed to decode PROG MEM PAGE %08lx %d\n", pmem_addr, mem_type); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + if (page != card->pmem_page) + { + unifi_trace(card->ospriv, UDBG6, "setting pmem page=0x%X, addr=0x%lX\n", page, addr); + + /* change page register */ + r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, page); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write PROG MEM PAGE\n"); + return r; + } + + card->pmem_page = page; + } + + *paddr = ((CsrInt32)addr * 2) + (pmem_addr & 1); + + return CSR_RESULT_SUCCESS; +} /* set_pmem_page() */ + + +/* + * --------------------------------------------------------------------------- + * set_page + * + * Sets up the appropriate page register to access the given address. + * Returns the sdio address at which the unifi address can be accessed. + * + * Arguments: + * card Pointer to card structure. + * generic_addr UniFi internal address to access, in Generic Pointer + * format, i.e. top byte is space indicator. + * paddr Location to write page address + * SDIO address (24-bit) for use in a unifi_read_direct or + * unifi_write_direct call + * + * Returns: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE the address is invalid + * --------------------------------------------------------------------------- + */ +static CsrResult set_page(card_t *card, CsrUint32 generic_addr, CsrUint32 *paddr) +{ + CsrInt32 space; + CsrUint32 addr; + CsrResult r = CSR_RESULT_SUCCESS; + + if (!paddr) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + *paddr = 0; + space = UNIFI_GP_SPACE(generic_addr); + addr = UNIFI_GP_OFFSET(generic_addr); + switch (space) + { + case UNIFI_SH_DMEM: + /* Shared Data Memory is accessed via the Shared Data Memory window */ + r = set_dmem_page(card, addr, paddr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + break; + + case UNIFI_EXT_FLASH: + if (!ChipHelper_HasFlash(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + /* External FLASH is accessed via the Program Memory window */ + r = set_pmem_page(card, addr, CHIP_HELPER_WT_FLASH, paddr); + break; + + case UNIFI_EXT_SRAM: + if (!ChipHelper_HasExtSram(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08l (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + /* External SRAM is accessed via the Program Memory window */ + r = set_pmem_page(card, addr, CHIP_HELPER_WT_EXT_SRAM, paddr); + break; + + case UNIFI_REGISTERS: + /* Registers are accessed directly */ + *paddr = addr; + break; + + case UNIFI_PHY_DMEM: + r = unifi_set_proc_select(card, UNIFI_PROC_PHY); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; + break; + + case UNIFI_MAC_DMEM: + r = unifi_set_proc_select(card, UNIFI_PROC_MAC); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; + break; + + case UNIFI_BT_DMEM: + if (!ChipHelper_HasBt(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + r = unifi_set_proc_select(card, UNIFI_PROC_BT); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; + break; + + case UNIFI_PHY_PMEM: + r = unifi_set_proc_select(card, UNIFI_PROC_PHY); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); + break; + + case UNIFI_MAC_PMEM: + r = unifi_set_proc_select(card, UNIFI_PROC_MAC); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); + break; + + case UNIFI_BT_PMEM: + if (!ChipHelper_HasBt(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + r = unifi_set_proc_select(card, UNIFI_PROC_BT); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); + break; + + case UNIFI_PHY_ROM: + if (!ChipHelper_HasRom(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + r = unifi_set_proc_select(card, UNIFI_PROC_PHY); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); + break; + + case UNIFI_MAC_ROM: + if (!ChipHelper_HasRom(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + r = unifi_set_proc_select(card, UNIFI_PROC_MAC); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); + break; + + case UNIFI_BT_ROM: + if (!ChipHelper_HasRom(card->helper) || !ChipHelper_HasBt(card->helper)) + { + unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", + generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + r = unifi_set_proc_select(card, UNIFI_PROC_BT); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); + break; + + default: + unifi_error(card->ospriv, "Bad address space %d in generic pointer 0x%08lX (helper=0x%x)\n", + space, generic_addr, card->helper); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + return r; +} /* set_page() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_set_proc_select + * + * + * Arguments: + * card Pointer to card structure. + * select Which XAP core to select + * + * Returns: + * 0 on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * --------------------------------------------------------------------------- + */ +CsrResult unifi_set_proc_select(card_t *card, enum unifi_dbg_processors_select select) +{ + CsrResult r; + + /* Verify the the select value is allowed. */ + switch (select) + { + case UNIFI_PROC_MAC: + case UNIFI_PROC_PHY: + case UNIFI_PROC_BOTH: + break; + + + default: + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + if (card->proc_select != (CsrUint32)select) + { + r = unifi_write_direct16(card, + ChipHelper_DBG_HOST_PROC_SELECT(card->helper) * 2, + (CsrUint8)select); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write to Proc Select register\n"); + return r; + } + + card->proc_select = (CsrUint32)select; + } + + return CSR_RESULT_SUCCESS; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_read_8_or_16 + * + * Performs a byte read of the given address in shared data memory. + * Set up the shared data memory page register as required. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to a byte variable for the value read. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read_8_or_16(card_t *card, CsrUint32 unifi_addr, CsrUint8 *pdata) +{ + CsrUint32 sdio_addr; + CsrResult r; +#ifdef CSR_WIFI_TRANSPORT_CSPI + CsrUint16 w; +#endif + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_r8or16_count++; +#endif +#ifdef CSR_WIFI_TRANSPORT_CSPI + r = retrying_read16(card, card->function, sdio_addr, &w); + *pdata = (CsrUint8)(w & 0xFF); + return r; +#else + return retrying_read8(card, card->function, sdio_addr, pdata); +#endif +} /* unifi_read_8_or_16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_write_8_or_16 + * + * Performs a byte write of the given address in shared data memory. + * Set up the shared data memory page register as required. + * + * Arguments: + * card Pointer to card context struct. + * unifi_addr UniFi shared-data-memory address to access. + * data Value to write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * + * Notes: + * Beware using unifi_write8() because byte writes are not safe on UniFi. + * Writes to odd bytes are cached, writes to even bytes perform a 16-bit + * write with the previously cached odd byte. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_write_8_or_16(card_t *card, CsrUint32 unifi_addr, CsrUint8 data) +{ + CsrUint32 sdio_addr; + CsrResult r; +#ifdef CSR_WIFI_TRANSPORT_CSPI + CsrUint16 w; +#endif + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + if (sdio_addr & 1) + { + unifi_warning(card->ospriv, + "Warning: Byte write to an odd address (0x%lX) is dangerous\n", + sdio_addr); + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_w8or16_count++; +#endif +#ifdef CSR_WIFI_TRANSPORT_CSPI + w = data; + return retrying_write16(card, card->function, sdio_addr, w); +#else + return retrying_write8(card, card->function, sdio_addr, data); +#endif +} /* unifi_write_8_or_16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_read16 + * + * Performs a 16-bit read of the given address in shared data memory. + * Set up the shared data memory page register as required. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to a 16-bit int variable for the value read. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * --------------------------------------------------------------------------- + */ +CsrResult unifi_card_read16(card_t *card, CsrUint32 unifi_addr, CsrUint16 *pdata) +{ + CsrUint32 sdio_addr; + CsrResult r; + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_r16_count++; +#endif + return unifi_read_direct16(card, sdio_addr, pdata); +} /* unifi_card_read16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_write16 + * + * Performs a 16-bit write of the given address in shared data memory. + * Set up the shared data memory page register as required. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to a byte variable for the value write. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * --------------------------------------------------------------------------- + */ +CsrResult unifi_card_write16(card_t *card, CsrUint32 unifi_addr, CsrUint16 data) +{ + CsrUint32 sdio_addr; + CsrResult r; + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_w16_count++; +#endif + return unifi_write_direct16(card, sdio_addr, data); +} /* unifi_card_write16() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read32 + * + * Performs a 32-bit read of the given address in shared data memory. + * Set up the shared data memory page register as required. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to a int variable for the value read. + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * --------------------------------------------------------------------------- + */ +CsrResult unifi_read32(card_t *card, CsrUint32 unifi_addr, CsrUint32 *pdata) +{ + CsrUint32 sdio_addr; + CsrResult r; + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + card->cmd_prof.cmd52_r32_count++; +#endif + return unifi_read_direct32(card, sdio_addr, pdata); +} /* unifi_read32() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_card_readn + * unifi_readnz + * + * Read multiple 8-bit values from the UniFi SDIO interface. + * This function interprets the address as a GenericPointer as + * defined in the UniFi Host Interface Protocol Specification. + * The readnz version of this function will stop when it reads a + * zero octet. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to which to write data. + * len Number of bytes to read + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified + * --------------------------------------------------------------------------- + */ +CsrResult unifi_readn_match(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len, CsrInt8 match) +{ + CsrUint32 sdio_addr; + CsrResult r; + CsrUint32 num; + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + r = unifi_read_directn_match(card, sdio_addr, pdata, len, match, &num); + return r; +} /* unifi_readn_match() */ + + +CsrResult unifi_card_readn(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len) +{ + return unifi_readn_match(card, unifi_addr, pdata, len, -1); +} /* unifi_card_readn() */ + + +CsrResult unifi_readnz(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len) +{ + return unifi_readn_match(card, unifi_addr, pdata, len, 0); +} /* unifi_readnz() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_read_shared_count + * + * Read signal count locations, checking for an SDIO error. The + * signal count locations only contain a valid number if the + * highest bit isn't set. + * + * Arguments: + * card Pointer to card context structure. + * addr Shared-memory address to read. + * + * Returns: + * Value read from memory (0-127) or -1 on error + * --------------------------------------------------------------------------- + */ +CsrInt32 unifi_read_shared_count(card_t *card, CsrUint32 addr) +{ + CsrUint8 b; + /* I've increased this count, because I have seen cases where + * there were three reads in a row with the top bit set. I'm not + * sure why this might have happened, but I can't see a problem + * with increasing this limit. It's better to take a while to + * recover than to fail. */ +#define SHARED_READ_RETRY_LIMIT 10 + CsrInt32 i; + + /* + * Get the to-host-signals-written count. + * The top-bit will be set if the firmware was in the process of + * changing the value, in which case we read again. + */ + /* Limit the number of repeats so we don't freeze */ + for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) + { + CsrResult r; + r = unifi_read_8_or_16(card, addr, &b); + if (r != CSR_RESULT_SUCCESS) + { + return -1; + } + if (!(b & 0x80)) + { + /* There is a chance that the MSB may have contained invalid data + * (overflow) at the time it was read. Therefore mask off the MSB. + * This avoids a race between driver read and firmware write of the + * word, the value we need is in the lower 8 bits anway. + */ + return (CsrInt32)(b & 0xff); + } + } + + return -1; /* this function has changed in WMM mods */ +} /* unifi_read_shared_count() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_writen + * + * Write multiple 8-bit values to the UniFi SDIO interface using CMD52 + * This function interprets the address as a GenericPointer as + * defined in the UniFi Host Interface Protocol Specification. + * + * Arguments: + * card Pointer to card structure. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to which to write data. + * len Number of bytes to write + * + * Returns: + * 0 on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * CSR_WIFI_HIP_RESULT_INVALID_VALUE an odd length or length too big. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_writen(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len) +{ + CsrUint32 sdio_addr; + CsrResult r; + + r = set_page(card, unifi_addr, &sdio_addr); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + return unifi_write_directn(card, sdio_addr, pdata, len); +} /* unifi_writen() */ + + +static CsrResult csr_sdio_block_rw(card_t *card, CsrInt16 funcnum, + CsrUint32 addr, CsrUint8 *pdata, + CsrUint16 count, CsrInt16 dir_is_write) +{ + CsrResult csrResult; + + if (dir_is_write == UNIFI_SDIO_READ) + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("r@%02X#%X=", addr, count); +#endif +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("R"); +#endif + csrResult = CsrSdioRead(card->sdio_if, addr, pdata, count); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("<"); +#endif + } + else + { +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + unifi_debug_log_to_buf("w@%02X#%X=", addr, count); + unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); +#endif +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("W"); +#endif + csrResult = CsrSdioWrite(card->sdio_if, addr, pdata, count); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf(">"); +#endif + } +#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE + card->cmd_prof.cmd53_count++; +#endif +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_debug_log_to_buf("error=%X", csrResult); + } + else if (dir_is_write == UNIFI_SDIO_READ) + { + unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); + } + unifi_debug_string_to_buf("\n"); +#endif + return csrResult; /* CSR SDIO (not HIP) error code */ +} + + +/* + * --------------------------------------------------------------------------- + * unifi_bulk_rw + * + * Transfer bulk data to or from the UniFi SDIO interface. + * This function is used to read or write signals and bulk data. + * + * Arguments: + * card Pointer to card structure. + * handle Value to put in the Register Address field of the CMD53 req. + * data Pointer to data to write. + * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE + * + * Returns: + * CSR_RESULT_SUCCESS on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * This function uses SDIO CMD53, which is the block transfer mode. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_bulk_rw(card_t *card, CsrUint32 handle, void *pdata, + CsrUint32 len, CsrInt16 direction) +{ +#define CMD53_RETRIES 3 + /* + * Ideally instead of sleeping, we want to busy wait. + * Currently there is no framework API to do this. When it becomes available, + * we can use it to busy wait using usecs + */ +#define REWIND_RETRIES 15 /* when REWIND_DELAY==1msec, or 250 when REWIND_DELAY==50usecs */ +#define REWIND_POLLING_RETRIES 5 +#define REWIND_DELAY 1 /* msec or 50usecs */ + CsrResult csrResult; /* SDIO error code */ + CsrResult r = CSR_RESULT_SUCCESS; /* HIP error code */ + CsrInt16 retries = CMD53_RETRIES; + CsrInt16 stat_retries; + CsrUint8 stat; + CsrInt16 dump_read; +#ifdef UNIFI_DEBUG + CsrUint8 *pdata_lsb = ((CsrUint8 *)&pdata) + card->lsb; +#endif +#ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS + static CsrInt16 fake_error; +#endif + + dump_read = 0; +#ifdef UNIFI_DEBUG + if (*pdata_lsb & 1) + { + unifi_notice(card->ospriv, "CD53 request on a unaligned buffer (addr: 0x%X) dir %s-Host\n", + pdata, (direction == UNIFI_SDIO_READ)?"To" : "From"); + if (direction == UNIFI_SDIO_WRITE) + { + dump(pdata, (CsrUint16)len); + } + else + { + dump_read = 1; + } + } +#endif + + /* Defensive checks */ + if (!pdata) + { + unifi_error(card->ospriv, "Null pdata for unifi_bulk_rw() len: %d\n", len); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + if ((len & 1) || (len > 0xffff)) + { + unifi_error(card->ospriv, "Impossible CMD53 length requested: %d\n", len); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + while (1) + { + csrResult = csr_sdio_block_rw(card, card->function, handle, + (CsrUint8 *)pdata, (CsrUint16)len, + direction); + if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) + { + return CSR_WIFI_HIP_RESULT_NO_DEVICE; + } +#ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS + if (++fake_error > 100) + { + fake_error = 90; + unifi_warning(card->ospriv, "Faking a CMD53 error,\n"); + if (csrResult == CSR_RESULT_SUCCESS) + { + csrResult = CSR_RESULT_FAILURE; + } + } +#endif + if (csrResult == CSR_RESULT_SUCCESS) + { + if (dump_read) + { + dump(pdata, (CsrUint16)len); + } + break; + } + + /* + * At this point the SDIO driver should have written the I/O Abort + * register to notify UniFi that the command has failed. + * UniFi-1 and UniFi-2 (not UF6xxx) use the same register to store the + * Deep Sleep State. This means we have to restore the Deep Sleep + * State (AWAKE in any case since we can not perform a CD53 in any other + * state) by rewriting the I/O Abort register to its previous value. + */ + if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) + { + unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + } + + /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted + * then stop retrying + */ + if (!retryable_sdio_error(csrResult)) + { + unifi_error(card->ospriv, "Fatal error in a CMD53 transfer\n"); + break; + } + + /* + * These happen from time to time, try again + */ + if (--retries == 0) + { + break; + } + + unifi_trace(card->ospriv, UDBG4, + "Error in a CMD53 transfer, retrying (h:%d,l:%u)...\n", + (CsrInt16)handle & 0xff, len); + + /* The transfer failed, rewind and try again */ + r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 8, + (CsrUint8)(handle & 0xff)); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + /* + * If we can't even do CMD52 (register read/write) then + * stop here. + */ + unifi_error(card->ospriv, "Failed to write REWIND cmd\n"); + return r; + } + + /* Signal the UniFi to look for the rewind request. */ + r = CardGenInt(card); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + /* Wait for UniFi to acknowledge the rewind */ + stat_retries = REWIND_RETRIES; + while (1) + { + r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 8, &stat); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read REWIND status\n"); + return CSR_RESULT_FAILURE; + } + + if (stat == 0) + { + break; + } + if (--stat_retries == 0) + { + unifi_error(card->ospriv, "Timeout waiting for REWIND ready\n"); + return CSR_RESULT_FAILURE; + } + + /* Poll for the ack a few times */ + if (stat_retries < REWIND_RETRIES - REWIND_POLLING_RETRIES) + { + CsrThreadSleep(REWIND_DELAY); + } + } + } + + /* The call to csr_sdio_block_rw() still failed after retrying */ + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Block %s failed after %d retries\n", + (direction == UNIFI_SDIO_READ)?"read" : "write", + CMD53_RETRIES - retries); + /* Report any SDIO error as a general i/o error */ + return CSR_RESULT_FAILURE; + } + + /* Collect some stats */ + if (direction == UNIFI_SDIO_READ) + { + card->sdio_bytes_read += len; + } + else + { + card->sdio_bytes_written += len; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_bulk_rw() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_bulk_rw_noretry + * + * Transfer bulk data to or from the UniFi SDIO interface. + * This function is used to read or write signals and bulk data. + * + * Arguments: + * card Pointer to card structure. + * handle Value to put in the Register Address field of + * the CMD53 req. + * data Pointer to data to write. + * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE + * + * Returns: + * 0 on success, non-zero error code on error: + * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected + * CSR_RESULT_FAILURE an SDIO error occurred + * + * Notes: + * This function uses SDIO CMD53, which is the block transfer mode. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_bulk_rw_noretry(card_t *card, CsrUint32 handle, void *pdata, + CsrUint32 len, CsrInt16 direction) +{ + CsrResult csrResult; + + csrResult = csr_sdio_block_rw(card, card->function, handle, + (CsrUint8 *)pdata, (CsrUint16)len, direction); + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Block %s failed\n", + (direction == UNIFI_SDIO_READ)?"read" : "write"); + return csrResult; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_bulk_rw_noretry() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.c b/drivers/staging/csr/csr_wifi_hip_chiphelper.c new file mode 100644 index 000000000000..0e2477ff4dd0 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_chiphelper.c @@ -0,0 +1,793 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + + +#include "csr_wifi_hip_chiphelper_private.h" + +#ifndef nelem +#define nelem(a) (sizeof(a) / sizeof(a[0])) +#endif + +#define counted(foo) { nelem(foo), foo } +#define null_counted() { 0, NULL } + +/* The init values are a set of register writes that we must + perform when we first connect to the chip to get it working. + They swicth on the correct clocks and possibly set the host + interface as a wkaeup source. They should not be used if + proper HIP opperation is required, but are useful before we + do a code download. */ +static const struct chip_helper_init_values init_vals_v1[] = { + { 0xFDBB, 0xFFFF }, + { 0xFDB6, 0x03FF }, + { 0xFDB1, 0x01E3 }, + { 0xFDB3, 0x0FFF }, + { 0xFEE3, 0x08F0 }, + { 0xFEE7, 0x3C3F }, + { 0xFEE6, 0x0050 }, + { 0xFDBA, 0x0000 } +}; + +static const struct chip_helper_init_values init_vals_v2[] = { + { 0xFDB6, 0x0FFF }, + { 0xF023, 0x3F3F }, + { 0xFDB1, 0x01E3 }, + { 0xFDB3, 0x0FFF }, + { 0xF003, 0x08F0 }, + { 0xF007, 0x3C3F }, + { 0xF006, 0x0050 } +}; + + +static const struct chip_helper_init_values init_vals_v22_v23[] = { + { 0xF81C, 0x00FF }, + /*{ 0x????, 0x???? }, */ + { 0xF80C, 0x1FFF }, + { 0xFA25, 0x001F }, + { 0xF804, 0x00FF }, + { 0xF802, 0x0FFF }, + /*{ 0x????, 0x???? }, + { 0x????, 0x???? }, + { 0x????, 0x???? }*/ +}; + +static const CsrUint16 reset_program_a_v1_or_v2[] = { + 0x0000 +}; +static const CsrUint16 reset_program_b_v1_or_v2[] = { + 0x0010, 0xFE00, 0xA021, 0xFF00, 0x8111, 0x0009, 0x0CA4, 0x0114, + 0x0280, 0x04F8, 0xFE00, 0x6F25, 0x06E0, 0x0010, 0xFC00, 0x0121, + 0xFC00, 0x0225, 0xFE00, 0x7125, 0xFE00, 0x6D11, 0x03F0, 0xFE00, + 0x6E25, 0x0008, 0x00E0 +}; + +static const struct chip_helper_reset_values reset_program_v1_or_v2[] = +{ + { + MAKE_GP(REGISTERS, 0x000C), + nelem(reset_program_a_v1_or_v2), + reset_program_a_v1_or_v2 + }, + { + MAKE_GP(MAC_PMEM, 0x000000), + nelem(reset_program_b_v1_or_v2), + reset_program_b_v1_or_v2 + } +}; + +static const struct chip_map_address_t unifi_map_address_v1_v2[] = +{ + { 0xFE9F, 0xFE7B }, /* PM1_BANK_SELECT */ + { 0xFE9E, 0xFE78 }, /* PM2_BANK_SELECT */ + { 0xFE9D, 0xFE7E }, /* SHARED_DMEM_PAGE */ + { 0xFE91, 0xFE90 }, /* PROC_SELECT */ + { 0xFE8D, 0xFE8C }, /* STOP_STATUS */ +}; + +static const struct chip_map_address_t unifi_map_address_v22_v23[] = +{ + { 0xF8F9, 0xF8AC }, /* GW1_CONFIG */ + { 0xF8FA, 0xF8AD }, /* GW2_CONFIG */ + { 0xF8FB, 0xF8AE }, /* GW3_CONFIG */ + { 0xF830, 0xF81E }, /* PROC_SELECT */ + { 0xF831, 0xF81F }, /* STOP_STATUS */ + { 0xF8FC, 0xF8AF }, /* IO_LOG_ADDRESS */ +}; + +static const struct chip_device_regs_t unifi_device_regs_null = +{ + 0xFE81, /* GBL_CHIP_VERSION */ + 0x0000, /* GBL_MISC_ENABLES */ + 0x0000, /* DBG_EMU_CMD */ + { + 0x0000, /* HOST.DBG_PROC_SELECT */ + 0x0000, /* HOST.DBG_STOP_STATUS */ + 0x0000, /* HOST.WINDOW1_PAGE */ + 0x0000, /* HOST.WINDOW2_PAGE */ + 0x0000, /* HOST.WINDOW3_PAGE */ + 0x0000 /* HOST.IO_LOG_ADDR */ + }, + { + 0x0000, /* SPI.DBG_PROC_SELECT */ + 0x0000, /* SPI.DBG_STOP_STATUS */ + 0x0000, /* SPI.WINDOW1_PAGE */ + 0x0000, /* SPI.WINDOW2_PAGE */ + 0x0000, /* SPI.WINDOW3_PAGE */ + 0x0000 /* SPI.IO_LOG_ADDR */ + }, + 0x0000, /* DBG_RESET */ + 0x0000, /* > DBG_RESET_VALUE */ + 0x0000, /* DBG_RESET_WARN */ + 0x0000, /* DBG_RESET_WARN_VALUE */ + 0x0000, /* DBG_RESET_RESULT */ + 0xFFE9, /* XAP_PCH */ + 0xFFEA, /* XAP_PCL */ + 0x0000, /* PROC_PC_SNOOP */ + 0x0000, /* WATCHDOG_DISABLE */ + 0x0000, /* MAILBOX0 */ + 0x0000, /* MAILBOX1 */ + 0x0000, /* MAILBOX2 */ + 0x0000, /* MAILBOX3 */ + 0x0000, /* SDIO_HOST_INT */ + 0x0000, /* SHARED_IO_INTERRUPT */ + 0x0000, /* SDIO HIP HANDSHAKE */ + 0x0000 /* COEX_STATUS */ +}; + +/* UF105x */ +static const struct chip_device_regs_t unifi_device_regs_v1 = +{ + 0xFE81, /* GBL_CHIP_VERSION */ + 0xFE87, /* GBL_MISC_ENABLES */ + 0xFE9C, /* DBG_EMU_CMD */ + { + 0xFE90, /* HOST.DBG_PROC_SELECT */ + 0xFE8C, /* HOST.DBG_STOP_STATUS */ + 0xFE7B, /* HOST.WINDOW1_PAGE */ + 0xFE78, /* HOST.WINDOW2_PAGE */ + 0xFE7E, /* HOST.WINDOW3_PAGE */ + 0x0000 /* HOST.IO_LOG_ADDR */ + }, + { + 0xFE91, /* SPI.DBG_PROC_SELECT */ + 0xFE8D, /* SPI.DBG_STOP_STATUS */ + 0xFE9F, /* SPI.WINDOW1_PAGE */ + 0xFE9E, /* SPI.WINDOW2_PAGE */ + 0xFE9D, /* SPI.WINDOW3_PAGE */ + 0x0000 /* SPI.IO_LOG_ADDR */ + }, + 0xFE92, /* DBG_RESET */ + 0x0001, /* > DBG_RESET_VALUE */ + 0xFDA0, /* DBG_RESET_WARN (HOST_SELECT) */ + 0x0000, /* DBG_RESET_WARN_VALUE */ + 0xFE92, /* DBG_RESET_RESULT */ + 0xFFE9, /* XAP_PCH */ + 0xFFEA, /* XAP_PCL */ + 0x0051, /* PROC_PC_SNOOP */ + 0xFE70, /* WATCHDOG_DISABLE */ + 0xFE6B, /* MAILBOX0 */ + 0xFE6A, /* MAILBOX1 */ + 0xFE69, /* MAILBOX2 */ + 0xFE68, /* MAILBOX3 */ + 0xFE67, /* SDIO_HOST_INT */ + 0xFE65, /* SHARED_IO_INTERRUPT */ + 0xFDE9, /* SDIO HIP HANDSHAKE */ + 0x0000 /* COEX_STATUS */ +}; + +/* UF2... */ +static const struct chip_device_regs_t unifi_device_regs_v2 = +{ + 0xFE81, /* GBL_CHIP_VERSION */ + 0xFE87, /* GBL_MISC_ENABLES */ + 0xFE9C, /* DBG_EMU_CMD */ + { + 0xFE90, /* HOST.DBG_PROC_SELECT */ + 0xFE8C, /* HOST.DBG_STOP_STATUS */ + 0xFE7B, /* HOST.WINDOW1_PAGE */ + 0xFE78, /* HOST.WINDOW2_PAGE */ + 0xFE7E, /* HOST.WINDOW3_PAGE */ + 0x0000 /* HOST.IO_LOG_ADDR */ + }, + { + 0xFE91, /* SPI.DBG_PROC_SELECT */ + 0xFE8D, /* SPI.DBG_STOP_STATUS */ + 0xFE9F, /* SPI.WINDOW1_PAGE */ + 0xFE9E, /* SPI.WINDOW2_PAGE */ + 0xFE9D, /* SPI.WINDOW3_PAGE */ + 0x0000 /* SPI.IO_LOG_ADDR */ + }, + 0xFE92, /* DBG_RESET */ + 0x0000, /* > DBG_RESET_VALUE */ + 0xFDE9, /* DBG_RESET_WARN (TEST_FLASH_DATA - SHARED_MAILBOX2B) */ + 0xFFFF, /* DBG_RESET_WARN_VALUE */ + 0xFDE9, /* DBG_RESET_RESULT (TEST_FLASH_DATA) */ + 0xFFE9, /* XAP_PCH */ + 0xFFEA, /* XAP_PCL */ + 0x0051, /* PROC_PC_SNOOP */ + 0xFE70, /* WATCHDOG_DISABLE */ + 0xFE6B, /* MAILBOX0 */ + 0xFE6A, /* MAILBOX1 */ + 0xFE69, /* MAILBOX2 */ + 0xFE68, /* MAILBOX3 */ + 0xFE67, /* SDIO_HOST_INT */ + 0xFE65, /* SHARED_IO_INTERRUPT */ + 0xFE69, /* SDIO HIP HANDSHAKE */ + 0x0000 /* COEX_STATUS */ +}; + +/* UF60xx */ +static const struct chip_device_regs_t unifi_device_regs_v22_v23 = +{ + 0xFE81, /* GBL_CHIP_VERSION */ + 0xF84F, /* GBL_MISC_ENABLES */ + 0xF81D, /* DBG_EMU_CMD */ + { + 0xF81E, /* HOST.DBG_PROC_SELECT */ + 0xF81F, /* HOST.DBG_STOP_STATUS */ + 0xF8AC, /* HOST.WINDOW1_PAGE */ + 0xF8AD, /* HOST.WINDOW2_PAGE */ + 0xF8AE, /* HOST.WINDOW3_PAGE */ + 0xF8AF /* HOST.IO_LOG_ADDR */ + }, + { + 0xF830, /* SPI.DBG_PROC_SELECT */ + 0xF831, /* SPI.DBG_STOP_STATUS */ + 0xF8F9, /* SPI.WINDOW1_PAGE */ + 0xF8FA, /* SPI.WINDOW2_PAGE */ + 0xF8FB, /* SPI.WINDOW3_PAGE */ + 0xF8FC /* SPI.IO_LOG_ADDR */ + }, + 0xF82F, /* DBG_RESET */ + 0x0001, /* > DBG_RESET_VALUE */ + 0x0000, /* DBG_RESET_WARN */ + 0x0000, /* DBG_RESET_WARN_VALUE */ + 0xF82F, /* DBG_RESET_RESULT */ + 0xFFE9, /* XAP_PCH */ + 0xFFEA, /* XAP_PCL */ + 0x001B, /* PROC_PC_SNOOP */ + 0x0055, /* WATCHDOG_DISABLE */ + 0xF84B, /* MAILBOX0 */ + 0xF84C, /* MAILBOX1 */ + 0xF84D, /* MAILBOX2 */ + 0xF84E, /* MAILBOX3 */ + 0xF92F, /* SDIO_HOST_INT */ + 0xF92B, /* SDIO_FROMHOST_SCRTACH0 / SHARED_IO_INTERRUPT */ + 0xF84D, /* SDIO HIP HANDSHAKE (MAILBOX2) */ + 0xF9FB /* COEX_STATUS */ +}; + +/* Program memory window on UF105x. */ +static const struct window_shift_info_t prog_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] = +{ + { TRUE, 11, 0x0200 }, /* CODE RAM */ + { TRUE, 11, 0x0000 }, /* FLASH */ + { TRUE, 11, 0x0400 }, /* External SRAM */ + { FALSE, 0, 0 }, /* ROM */ + { FALSE, 0, 0 } /* SHARED */ +}; + +/* Shared memory window on UF105x. */ +static const struct window_shift_info_t shared_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] = +{ + { FALSE, 0, 0 }, /* CODE RAM */ + { FALSE, 0, 0 }, /* FLASH */ + { FALSE, 0, 0 }, /* External SRAM */ + { FALSE, 0, 0 }, /* ROM */ + { TRUE, 11, 0x0000 } /* SHARED */ +}; + +/* One of the Generic Windows on UF60xx and later. */ +static const struct window_shift_info_t generic_window_array_unifi_v22_v23[CHIP_HELPER_WT_COUNT] = +{ + { TRUE, 11, 0x3800 }, /* CODE RAM */ + { FALSE, 0, 0 }, /* FLASH */ + { FALSE, 0, 0 }, /* External SRAM */ + { TRUE, 11, 0x2000 }, /* ROM */ + { TRUE, 11, 0x0000 } /* SHARED */ +}; + +/* The three windows on UF105x. */ +static const struct window_info_t prog1_window_unifi_v1_v2 = { 0x0000, 0x2000, 0x0080, prog_window_array_unifi_v1_v2 }; +static const struct window_info_t prog2_window_unifi_v1_v2 = { 0x2000, 0x2000, 0x0000, prog_window_array_unifi_v1_v2 }; +static const struct window_info_t shared_window_unifi_v1_v2 = { 0x4000, 0x2000, 0x0000, shared_window_array_unifi_v1_v2 }; + +/* The three windows on UF60xx and later. */ +static const struct window_info_t generic1_window_unifi_v22_v23 = { 0x0000, 0x2000, 0x0080, generic_window_array_unifi_v22_v23 }; +static const struct window_info_t generic2_window_unifi_v22_v23 = { 0x2000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 }; +static const struct window_info_t generic3_window_unifi_v22_v23 = { 0x4000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 }; + +static const struct chip_device_desc_t chip_device_desc_null = +{ + { FALSE, 0x0000, 0x0000, 0x00 }, + "", + "", + null_counted(), /* init */ + null_counted(), /* reset_prog */ + &unifi_device_regs_null, /* regs */ + { + FALSE, /* has_flash */ + FALSE, /* has_ext_sram */ + FALSE, /* has_rom */ + FALSE, /* has_bt */ + FALSE, /* has_wlan */ + }, + null_counted(), + /* prog_offset */ + { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 + }, + /* data_offset */ + { + 0x0000 /* ram */ + }, + /* windows */ + { + NULL, + NULL, + NULL + } +}; + +static const struct chip_device_desc_t unifi_device_desc_v1 = +{ + { FALSE, 0xf0ff, 0x1001, 0x01 }, /* UF105x R01 */ + "UF105x", + "UniFi-1", + counted(init_vals_v1), /* init */ + counted(reset_program_v1_or_v2), /* reset_prog */ + &unifi_device_regs_v1, /* regs */ + { + TRUE, /* has_flash */ + TRUE, /* has_ext_sram */ + FALSE, /* has_rom */ + FALSE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v1_v2), /* map */ + /* prog_offset */ + { + 0x00100000, /* ram */ + 0x00000000, /* rom (invalid) */ + 0x00000000, /* flash */ + 0x00200000, /* ext_ram */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &prog1_window_unifi_v1_v2, + &prog2_window_unifi_v1_v2, + &shared_window_unifi_v1_v2 + } +}; + +static const struct chip_device_desc_t unifi_device_desc_v2 = +{ + { FALSE, 0xf0ff, 0x2001, 0x02 }, /* UF2... R02 */ + "UF2...", + "UniFi-2", + counted(init_vals_v2), /* init */ + counted(reset_program_v1_or_v2), /* reset_prog */ + &unifi_device_regs_v2, /* regs */ + { + TRUE, /* has_flash */ + TRUE, /* has_ext_sram */ + FALSE, /* has_rom */ + FALSE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v1_v2), /* map */ + /* prog_offset */ + { + 0x00100000, /* ram */ + 0x00000000, /* rom (invalid) */ + 0x00000000, /* flash */ + 0x00200000, /* ext_ram */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &prog1_window_unifi_v1_v2, + &prog2_window_unifi_v1_v2, + &shared_window_unifi_v1_v2 + } +}; + +static const struct chip_device_desc_t unifi_device_desc_v3 = +{ + { FALSE, 0xf0ff, 0x3001, 0x02 }, /* UF2... R03 */ + "UF2...", + "UniFi-3", + counted(init_vals_v2), /* init */ + counted(reset_program_v1_or_v2), /* reset_prog */ + &unifi_device_regs_v2, /* regs */ + { + TRUE, /* has_flash */ + TRUE, /* has_ext_sram */ + FALSE, /* has_rom */ + FALSE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v1_v2), /* map */ + /* prog_offset */ + { + 0x00100000, /* ram */ + 0x00000000, /* rom (invalid) */ + 0x00000000, /* flash */ + 0x00200000, /* ext_ram */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &prog1_window_unifi_v1_v2, + &prog2_window_unifi_v1_v2, + &shared_window_unifi_v1_v2 + } +}; + +static const struct chip_device_desc_t unifi_device_desc_v22 = +{ + { FALSE, 0x00ff, 0x0022, 0x07 }, /* UF60xx */ + "UF60xx", + "UniFi-4", + counted(init_vals_v22_v23), /* init */ + null_counted(), /* reset_prog */ + &unifi_device_regs_v22_v23, /* regs */ + { + FALSE, /* has_flash */ + FALSE, /* has_ext_sram */ + TRUE, /* has_rom */ + FALSE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v22_v23), /* map */ + /* prog_offset */ + { + 0x00C00000, /* ram */ + 0x00000000, /* rom */ + 0x00000000, /* flash (invalid) */ + 0x00000000, /* ext_ram (invalid) */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &generic1_window_unifi_v22_v23, + &generic2_window_unifi_v22_v23, + &generic3_window_unifi_v22_v23 + } +}; + +static const struct chip_device_desc_t unifi_device_desc_v23 = +{ + { FALSE, 0x00ff, 0x0023, 0x08 }, /* UF.... */ + "UF....", + "UF.... (5)", + counted(init_vals_v22_v23), /* init */ + null_counted(), /* reset_prog */ + &unifi_device_regs_v22_v23, /* regs */ + { + FALSE, /* has_flash */ + FALSE, /* has_ext_sram */ + TRUE, /* has_rom */ + TRUE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v22_v23), + /* prog_offset */ + { + 0x00C00000, /* ram */ + 0x00000000, /* rom */ + 0x00000000, /* flash (invalid) */ + 0x00000000, /* ext_sram (invalid) */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &generic1_window_unifi_v22_v23, + &generic2_window_unifi_v22_v23, + &generic3_window_unifi_v22_v23 + } +}; + +static const struct chip_device_desc_t hyd_wlan_subsys_desc_v1 = +{ + { FALSE, 0x00ff, 0x0044, 0x00 }, /* UF.... */ + "HYD...", + "HYD... ", + counted(init_vals_v22_v23), /* init */ + null_counted(), /* reset_prog */ + &unifi_device_regs_v22_v23, /* regs */ + { + FALSE, /* has_flash */ + FALSE, /* has_ext_sram */ + TRUE, /* has_rom */ + FALSE, /* has_bt */ + TRUE, /* has_wlan */ + }, + counted(unifi_map_address_v22_v23), + /* prog_offset */ + { + 0x00C00000, /* ram */ + 0x00000000, /* rom */ + 0x00000000, /* flash (invalid) */ + 0x00000000, /* ext_sram (invalid) */ + }, + /* data_offset */ + { + 0x8000 /* ram */ + }, + /* windows */ + { + &generic1_window_unifi_v22_v23, + &generic2_window_unifi_v22_v23, + &generic3_window_unifi_v22_v23 + } +}; + + +/* This is the list of all chips that we know about. I'm + assuming that the order here will be important - we + might have multiple entries witrh the same SDIO id for + instance. The first one in this list will be the one + that is returned if a search is done on only that id. + The client will then have to call GetVersionXXX again + but with more detailed info. + + I don't know if we need to signal this up to the client + in some way? + + (We get the SDIO id before we know anything else about + the chip. We might not be able to read any of the other + registers at first, but we still need to know about the + chip). */ +static const struct chip_device_desc_t *chip_ver_to_desc[] = +{ + &unifi_device_desc_v1, /* UF105x R01 */ + &unifi_device_desc_v2, /* UF2... R02 */ + &unifi_device_desc_v3, /* UF2... R03 */ + &unifi_device_desc_v22, /* UF60xx */ + &unifi_device_desc_v23, /* UF.... */ + &hyd_wlan_subsys_desc_v1 +}; + +ChipDescript* ChipHelper_GetVersionSdio(CsrUint8 sdio_ver) +{ + CsrUint32 i; + + for (i = 0; i < nelem(chip_ver_to_desc); i++) + { + if (chip_ver_to_desc[i]->chip_version.sdio == sdio_ver) + { + return chip_ver_to_desc[i]; + } + } + + return &chip_device_desc_null; +} + + +ChipDescript* ChipHelper_GetVersionAny(CsrUint16 from_FF9A, CsrUint16 from_FE81) +{ + CsrUint32 i; + + if ((from_FF9A & 0xFF00) != 0) + { + for (i = 0; i < nelem(chip_ver_to_desc); i++) + { + if (chip_ver_to_desc[i]->chip_version.pre_bc7 && + ((from_FF9A & chip_ver_to_desc[i]->chip_version.mask) == + chip_ver_to_desc[i]->chip_version.result)) + { + return chip_ver_to_desc[i]; + } + } + } + else + { + for (i = 0; i < nelem(chip_ver_to_desc); i++) + { + if (!chip_ver_to_desc[i]->chip_version.pre_bc7 && + ((from_FE81 & chip_ver_to_desc[i]->chip_version.mask) == + chip_ver_to_desc[i]->chip_version.result)) + { + return chip_ver_to_desc[i]; + } + } + } + + return &chip_device_desc_null; +} + + +ChipDescript* ChipHelper_GetVersionUniFi(CsrUint16 ver) +{ + return ChipHelper_GetVersionAny(0x0000, ver); +} + + +ChipDescript* ChipHelper_Null() +{ + return &chip_device_desc_null; +} + + +ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age bc_age, CsrUint16 version) +{ + if (bc_age == chip_helper_bluecore_pre_bc7) + { + return ChipHelper_GetVersionAny(version, 0x0000); + } + else + { + return ChipHelper_GetVersionAny(0x0000, version); + } +} + + +/* Expand the DEF0 functions into simple code to return the + correct thing. The DEF1 functions expand to nothing in + this X macro expansion. */ +#define CHIP_HELPER_DEF0_C_DEF(ret_type, name, info) \ + ret_type ChipHelper_ ## name(ChipDescript * chip_help) \ + { \ + return chip_help->info; \ + } +#define CHIP_HELPER_DEF1_C_DEF(ret_type, name, type1, name1) + +CHIP_HELPER_LIST(C_DEF) + +/* + * Map register addresses between HOST and SPI access. + */ +CsrUint16 ChipHelper_MapAddress_SPI2HOST(ChipDescript *chip_help, CsrUint16 addr) +{ + CsrUint32 i; + for (i = 0; i < chip_help->map.len; i++) + { + if (chip_help->map.vals[i].spi == addr) + { + return chip_help->map.vals[i].host; + } + } + return addr; +} + + +CsrUint16 ChipHelper_MapAddress_HOST2SPI(ChipDescript *chip_help, CsrUint16 addr) +{ + CsrUint32 i; + for (i = 0; i < chip_help->map.len; i++) + { + if (chip_help->map.vals[i].host == addr) + { + return chip_help->map.vals[i].spi; + } + } + return addr; +} + + +/* The address returned by this function is the start of the + window in the address space, that is where we can start + accessing data from. If a section of the window at the + start is unusable because something else is cluttering up + the address map then that is taken into account and this + function returns that address justt past that. */ +CsrUint16 ChipHelper_WINDOW_ADDRESS(ChipDescript *chip_help, + enum chip_helper_window_index window) +{ + if (window < CHIP_HELPER_WINDOW_COUNT && + chip_help->windows[window] != NULL) + { + return chip_help->windows[window]->address + chip_help->windows[window]->blocked; + } + return 0; +} + + +/* This returns the size of the window minus any blocked section */ +CsrUint16 ChipHelper_WINDOW_SIZE(ChipDescript *chip_help, + enum chip_helper_window_index window) +{ + if (window < CHIP_HELPER_WINDOW_COUNT && + chip_help->windows[window] != NULL) + { + return chip_help->windows[window]->size - chip_help->windows[window]->blocked; + } + return 0; +} + + +/* Get the register writes we should do to make sure that + the chip is running with most clocks on. */ +CsrUint32 ChipHelper_ClockStartupSequence(ChipDescript *chip_help, + const struct chip_helper_init_values **val) +{ + *val = chip_help->init.vals; + return chip_help->init.len; +} + + +/* Get the set of values tat we should write to the chip to perform a reset. */ +CsrUint32 ChipHelper_HostResetSequence(ChipDescript *chip_help, + const struct chip_helper_reset_values **val) +{ + *val = chip_help->reset_prog.vals; + return chip_help->reset_prog.len; +} + + +/* Decode a windowed access to the chip. */ +CsrInt32 ChipHelper_DecodeWindow(ChipDescript *chip_help, + enum chip_helper_window_index window, + enum chip_helper_window_type type, + CsrUint32 offset, + CsrUint16 *page, CsrUint16 *addr, CsrUint32 *len) +{ + const struct window_info_t *win; + const struct window_shift_info_t *mode; + CsrUint16 of, pg; + + if (window >= CHIP_HELPER_WINDOW_COUNT) + { + return FALSE; + } + if ((win = chip_help->windows[window]) == NULL) + { + return FALSE; + } + if (type >= CHIP_HELPER_WT_COUNT) + { + return FALSE; + } + if ((mode = &win->mode[type]) == NULL) + { + return FALSE; + } + if (!mode->allowed) + { + return FALSE; + } + + pg = (CsrUint16)(offset >> mode->page_shift) + mode->page_offset; + of = (CsrUint16)(offset & ((1 << mode->page_shift) - 1)); + /* If 'blocked' is zero this does nothing, else decrease + the page register and increase the offset until we aren't + in the blocked region of the window. */ + while (of < win->blocked) + { + of += 1 << mode->page_shift; + pg--; + } + *page = pg; + *addr = win->address + of; + *len = win->size - of; + return TRUE; +} + + diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.h b/drivers/staging/csr/csr_wifi_hip_chiphelper.h new file mode 100644 index 000000000000..6166d5587571 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_chiphelper.h @@ -0,0 +1,471 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_HIP_CHIPHELPER_H__ +#define CSR_WIFI_HIP_CHIPHELPER_H__ + + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* The age of the BlueCore chip. This is probably not useful, if + you know the age then you can probably work out the version directly. */ +enum chip_helper_bluecore_age +{ + chip_helper_bluecore_pre_bc7, + chip_helper_bluecore_bc7_or_later +}; + +/* We support up to three windowed regions at the moment. + Don't reorder these - they're used to index into an array. */ +enum chip_helper_window_index +{ + CHIP_HELPER_WINDOW_1 = 0, + CHIP_HELPER_WINDOW_2 = 1, + CHIP_HELPER_WINDOW_3 = 2, + CHIP_HELPER_WINDOW_COUNT = 3 +}; + +/* These are the things that we can access through a window. + Don't reorder these - they're used to index into an array. */ +enum chip_helper_window_type +{ + CHIP_HELPER_WT_CODE_RAM = 0, + CHIP_HELPER_WT_FLASH = 1, + CHIP_HELPER_WT_EXT_SRAM = 2, + CHIP_HELPER_WT_ROM = 3, + CHIP_HELPER_WT_SHARED = 4, + CHIP_HELPER_WT_COUNT = 5 +}; + +/* Commands to stop and start the XAP */ +enum chip_helper_dbg_emu_cmd_enum +{ + CHIP_HELPER_DBG_EMU_CMD_XAP_STEP_MASK = 0x0001, + CHIP_HELPER_DBG_EMU_CMD_XAP_RUN_B_MASK = 0x0002, + CHIP_HELPER_DBG_EMU_CMD_XAP_BRK_MASK = 0x0004, + CHIP_HELPER_DBG_EMU_CMD_XAP_WAKEUP_MASK = 0x0008 +}; + +/* Bitmasks for Stop and sleep status: DBG_SPI_STOP_STATUS & DBG_HOST_STOP_STATUS */ +enum chip_helper_dbg_stop_status_enum +{ + CHIP_HELPER_DBG_STOP_STATUS_NONE_MASK = 0x0000, + CHIP_HELPER_DBG_STOP_STATUS_P0_MASK = 0x0001, + CHIP_HELPER_DBG_STOP_STATUS_P1_MASK = 0x0002, + CHIP_HELPER_DBG_STOP_STATUS_P2_MASK = 0x0004, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P0_MASK = 0x0008, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P1_MASK = 0x0010, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P2_MASK = 0x0020, + /* Legacy names/alias */ + CHIP_HELPER_DBG_STOP_STATUS_MAC_MASK = 0x0001, + CHIP_HELPER_DBG_STOP_STATUS_PHY_MASK = 0x0002, + CHIP_HELPER_DBG_STOP_STATUS_BT_MASK = 0x0004, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_MAC_MASK = 0x0008, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_PHY_MASK = 0x0010, + CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_BT_MASK = 0x0020 +}; + +/* Codes to disable the watchdog */ +enum chip_helper_watchdog_disable_enum +{ + CHIP_HELPER_WATCHDOG_DISABLE_CODE1 = 0x6734, + CHIP_HELPER_WATCHDOG_DISABLE_CODE2 = 0xD6BF, + CHIP_HELPER_WATCHDOG_DISABLE_CODE3 = 0xC31E +}; + +/* Other bits have changed between versions */ +enum chip_helper_gbl_misc_enum +{ + CHIP_HELPER_GBL_MISC_SPI_STOP_OUT_EN_MASK = 0x0001, + CHIP_HELPER_GBL_MISC_MMU_INIT_DONE_MASK = 0x0004 +}; + +/* Coex status register, contains interrupt status and reset pullup status. + * CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK can be used to check + * for WAPI on R03 chips and later. */ +enum chip_helper_coex_status_mask_enum +{ + CHIP_HELPER_COEX_STATUS_RST_PULLS_LSB_MASK = 0x0001, + CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK = 0x0008, + CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_LSB_MASK = 0x0010, + CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_MSB_MASK = 0x0080, + CHIP_HELPER_COEX_STATUS_INT_UART_MASK = 0x0100, + CHIP_HELPER_COEX_STATUS_INT_BT_LEG_MASK = 0x0200 +}; + +/* How to select the different CPUs */ +enum chip_helper_dbg_proc_sel_enum +{ + CHIP_HELPER_DBG_PROC_SEL_MAC = 0, + CHIP_HELPER_DBG_PROC_SEL_PHY = 1, + CHIP_HELPER_DBG_PROC_SEL_BT = 2, + CHIP_HELPER_DBG_PROC_SEL_NONE = 2, + CHIP_HELPER_DBG_PROC_SEL_BOTH = 3 +}; + +/* These are the only registers that we have to know the + address of before we know the chip version. */ +enum chip_helper_fixed_registers +{ + /* This is the address of GBL_CHIP_VERISON on BC7, + UF105x, UF60xx and + anything later than that. */ + CHIP_HELPER_UNIFI_GBL_CHIP_VERSION = 0xFE81, + + CHIP_HELPER_OLD_BLUECORE_GBL_CHIP_VERSION = 0xFF9A + + /* This isn't used at the moment (but might be needed + to distinguish the BlueCore sub version?) */ + /* CHIP_HELPER_OLD_BLUECORE_ANA_VERSION_ID = 0xFF7D */ +}; + +/* Address-value pairs for defining initialisation values */ +struct chip_helper_init_values +{ + CsrUint16 addr; + CsrUint16 value; +}; + +/* A block of data that should be written to the device */ +struct chip_helper_reset_values +{ + CsrUint32 gp_address; + CsrUint32 len; + const CsrUint16 *data; +}; + +/* + * This is the C API. + */ + +/* opaque type */ +typedef const struct chip_device_desc_t ChipDescript; + +/* Return a NULL descriptor */ +ChipDescript* ChipHelper_Null(void); + +/* This should get the correct version for any CSR chip. + The two parameters are what is read from addresses + 0xFF9A and 0xFE81 (OLD_BLUECORE_GBL_CHIP_VERSION and + UNIFI_GBL_CHIP_VERSION). These should give a unique identity + for most (all?) chips. + + FF9A is the old GBL_CHIP_VERSION register. If the high + eight bits are zero then the chip is a new (BC7 +) one + and FE81 is the _new_ GBL_CHIP_VERSION register. */ +ChipDescript* ChipHelper_GetVersionAny(CsrUint16 from_FF9A, CsrUint16 from_FE81); + +/* The chip is a UniFi, but we don't know which type + The parameter is the value of UNIFI_GBL_CHIP_VERSION (0xFE81) */ +ChipDescript* ChipHelper_GetVersionUniFi(CsrUint16 version); + +/* This gets the version from the SDIO device id. This only + gives quite a coarse grained version, so we should update once + we hav access to the function N registers. */ +ChipDescript* ChipHelper_GetVersionSdio(CsrUint8 sdio_version); + +/* The chip is some sort of BlueCore. If "age" is "pre_bc7" then + "version" is what was read from FF9A. If "age" is bc7_or_later + then "version" is read from FE81. If we don't know if we're pre + or post BC7 then we should use "GetVersionAny". */ +ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age age, + CsrUint16 version); + +/* The main functions of this class are built with an X macro. This + means we can generate the C and C++ versions from the same source + without the two diverging. + + The DEF0 functions are simple and take no parameters. The first + parameter to the macro is the return type. The second parameter + is the function name and the third parameter is where to get the + info from (this is hidden from the user). + + The DEF1 functions take one parameter. This time the third macro + parameter is the type of this parameter, and the fourth macro + parameter is the name of the parameter. The bodies of these + functions are hand written. */ +#define CHIP_HELPER_LIST(m) \ + CHIP_HELPER_DEF0(m, (const CsrCharString *, FriendlyName, friendly_name)) \ + CHIP_HELPER_DEF0(m, (const CsrCharString *, MarketingName, marketing_name)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_EMU_CMD, regs->dbg_emu_cmd)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_HOST_PROC_SELECT, regs->host.dbg_proc_select)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_HOST_STOP_STATUS, regs->host.dbg_stop_status)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, HOST_WINDOW1_PAGE, regs->host.window1_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, HOST_WINDOW2_PAGE, regs->host.window2_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, HOST_WINDOW3_PAGE, regs->host.window3_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, HOST_IO_LOG_ADDR, regs->host.io_log_addr)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_SPI_PROC_SELECT, regs->spi.dbg_proc_select)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_SPI_STOP_STATUS, regs->spi.dbg_stop_status)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SPI_WINDOW1_PAGE, regs->spi.window1_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SPI_WINDOW2_PAGE, regs->spi.window2_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SPI_WINDOW3_PAGE, regs->spi.window3_page)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SPI_IO_LOG_ADDR, regs->spi.io_log_addr)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_RESET, regs->dbg_reset)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_RESET_VALUE, regs->dbg_reset_value)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_RESET_WARN, regs->dbg_reset_warn)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_RESET_WARN_VALUE, regs->dbg_reset_warn_value)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DBG_RESET_RESULT, regs->dbg_reset_result)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, WATCHDOG_DISABLE, regs->watchdog_disable)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, PROC_PC_SNOOP, regs->proc_pc_snoop)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, GBL_CHIP_VERSION, regs->gbl_chip_version)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, GBL_MISC_ENABLES, regs->gbl_misc_enables)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, XAP_PCH, regs->xap_pch)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, XAP_PCL, regs->xap_pcl)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, MAILBOX0, regs->mailbox0)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, MAILBOX1, regs->mailbox1)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, MAILBOX2, regs->mailbox2)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, MAILBOX3, regs->mailbox3)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SDIO_HIP_HANDSHAKE, regs->sdio_hip_handshake)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SDIO_HOST_INT, regs->sdio_host_int)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, COEX_STATUS, regs->coex_status)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, SHARED_IO_INTERRUPT, regs->shared_io_interrupt)) \ + CHIP_HELPER_DEF0(m, (CsrUint32, PROGRAM_MEMORY_RAM_OFFSET, prog_offset.ram)) \ + CHIP_HELPER_DEF0(m, (CsrUint32, PROGRAM_MEMORY_ROM_OFFSET, prog_offset.rom)) \ + CHIP_HELPER_DEF0(m, (CsrUint32, PROGRAM_MEMORY_FLASH_OFFSET, prog_offset.flash)) \ + CHIP_HELPER_DEF0(m, (CsrUint32, PROGRAM_MEMORY_EXT_SRAM_OFFSET, prog_offset.ext_sram)) \ + CHIP_HELPER_DEF0(m, (CsrUint16, DATA_MEMORY_RAM_OFFSET, data_offset.ram)) \ + CHIP_HELPER_DEF0(m, (CsrInt32, HasFlash, bools.has_flash)) \ + CHIP_HELPER_DEF0(m, (CsrInt32, HasExtSram, bools.has_ext_sram)) \ + CHIP_HELPER_DEF0(m, (CsrInt32, HasRom, bools.has_rom)) \ + CHIP_HELPER_DEF0(m, (CsrInt32, HasBt, bools.has_bt)) \ + CHIP_HELPER_DEF0(m, (CsrInt32, HasWLan, bools.has_wlan)) \ + CHIP_HELPER_DEF1(m, (CsrUint16, WINDOW_ADDRESS, enum chip_helper_window_index, window)) \ + CHIP_HELPER_DEF1(m, (CsrUint16, WINDOW_SIZE, enum chip_helper_window_index, window)) \ + CHIP_HELPER_DEF1(m, (CsrUint16, MapAddress_SPI2HOST, CsrUint16, addr)) \ + CHIP_HELPER_DEF1(m, (CsrUint16, MapAddress_HOST2SPI, CsrUint16, addr)) \ + CHIP_HELPER_DEF1(m, (CsrUint32, ClockStartupSequence, const struct chip_helper_init_values **, val)) \ + CHIP_HELPER_DEF1(m, (CsrUint32, HostResetSequence, const struct chip_helper_reset_values **, val)) + +/* Some magic to help the expansion */ +#define CHIP_HELPER_DEF0(a, b) \ + CHIP_HELPER_DEF0_ ## a b +#define CHIP_HELPER_DEF1(a, b) \ + CHIP_HELPER_DEF1_ ## a b + +/* Macros so that when we expand the list we get "C" function prototypes. */ +#define CHIP_HELPER_DEF0_C_DEC(ret_type, name, info) \ + ret_type ChipHelper_ ## name(ChipDescript * chip_help); +#define CHIP_HELPER_DEF1_C_DEC(ret_type, name, type1, name1) \ + ret_type ChipHelper_ ## name(ChipDescript * chip_help, type1 name1); + +CHIP_HELPER_LIST(C_DEC) + +/* FriendlyName + MarketingName + + These two functions return human readable strings that describe + the chip. FriendlyName returns something that a software engineer + at CSR might understand. MarketingName returns something more like + an external name for a CSR chip. +*/ +/* DBG_EMU_CMD + WATCHDOG_DISABLE + PROC_PC_SNOOP + GBL_CHIP_VERSION + XAP_PCH + XAP_PCL + + These registers are used to control the XAPs. +*/ +/* DBG_HOST_PROC_SELECT DBG_HOST_STOP_STATUS + HOST_WINDOW1_PAGE HOST_WINDOW2_PAGE HOST_WINDOW3_PAGE + HOST_IO_LOG_ADDR + DBG_SPI_PROC_SELECT DBG_SPI_STOP_STATUS + SPI_WINDOW1_PAGE SPI_WINDOW2_PAGE SPI_WINDOW3_PAGE + SPI_IO_LOG_ADDR + + These register are used to control the XAPs and the memory + windows, normally while debugging the code on chip. There + are two versons of these registers, one for access via SPI + and another for access via the host interface. +*/ +/* DBG_RESET + DBG_RESET_VALUE + DBG_RESET_WARN + DBG_RESET_WARN_VALUE + DBG_RESET_RESULT + + These registers are used to reset the XAP. This can be + quite complex for some chips. If DBG_RESET_WARN is non + zero the DBG_RESET_WARN_VALUE should be written to address + DBG_RESET_WARN before the reset is perfeormed. DBG_RESET_VALUE + should then be written to DBG_RESET to make the reset happen. + The DBG_RESET_RESULT register should contain 0 if the reset + was successful. +*/ +/* GBL_MISC_ENABLES + + This register controls some special chip features. It + should be used with care is it changes quite a lot between + chip versions. +*/ +/* MAILBOX0 + MAILBOX1 + MAILBOX2 + MAILBOX3 + + The mailbox registers are for communication between the host + and the firmware. There use is described in part by the host + interface protcol specifcation. +*/ +/* SDIO_HIP_HANDSHAKE + + This is one of the more important SDIO HIP registers. On some + chips it has the same value as one of the mailbox registers + and on other chips it is different. +*/ +/* SDIO_HOST_INT + SHARED_IO_INTERRUPT + + These registers are used by some versions of the host interface + protocol specification. Their names should probably be changed + to hide the registers and to expose the functions more. +*/ +/* COEX_STATUS + + Coex status register, contains interrupt status and reset + pullup status. The latter is used to detect WAPI. +*/ +/* PROGRAM_MEMORY_RAM_OFFSET + PROGRAM_MEMORY_ROM_OFFSET + PROGRAM_MEMORY_FLASH_OFFSET + PROGRAM_MEMORY_EXT_SRAM_OFFSET + DATA_MEMORY_RAM_OFFSET + + These are constants that describe the offset of the different + memory types in the two different address spaces. +*/ +/* HasFlash HasExtSram HasRom + HasBt HasWLan + + These are a set of bools describing the chip. +*/ +/* WINDOW_ADDRESS WINDOW_SIZE + + These two functions return the size and address of the windows. + The address is the address of the lowest value in the address + map that is part of the window and the size is the number of + visible words. + + Some of the windows have thier lowest portion covered by + registers. For these windows address is the first address + after the registers and size is the siave excluding the part + covered by registers. +*/ +/* MapAddress_SPI2HOST + MapAddress_HOST2SPI + + The debugging interface is duplicated on UniFi and later chips + so that there are two versions - one over the SPI interaface and + the other over the SDIO interface. These functions map the + registers between these two interfaces. +*/ +/* ClockStartupSequence + + This function returns the list of register value pairs that + should be forced into UniFi to enable SPI communication. This + set of registers is not needed if the firmware is running, but + will be needed if the device is being booted from cold. These + register writes enable the clocks and setup the PLL to a basic + working state. SPI access might be unreliable until these writes + have occured (And they may take mulitple goes). +*/ +/* HostResetSequence + + This returns a number of chunks of data and generic pointers. + All of the XAPs should be stopped. The data should be written + to the generic pointers. The instruction pointer for the MAC + should then be set to the start of program memory and then the + MAC should be "go"d. This will reset the chip in a reliable + and orderly manner without resetting the SDIO interface. It + is therefore not needed if the chip is being accessed by the + SPI interface (the DBG_RESET_ mechanism can be used instead). +*/ + +/* The Decode Window function is more complex. For the window + 'window' it tries to return the address and page register + value needed to see offset 'offset' of memory type 'type'. + + It return 1 on success and 0 on failure. 'page' is what + should be written to the page register. 'addr' is the + address in the XAPs 16 address map to read from. 'len' + is the length that we can read without having to change + the page registers. */ +CsrInt32 ChipHelper_DecodeWindow(ChipDescript *chip_help, + enum chip_helper_window_index window, + enum chip_helper_window_type type, + CsrUint32 offset, + CsrUint16 *page, CsrUint16 *addr, CsrUint32 *len); + +#ifdef __cplusplus +/* Close the extern "C" */ +} + +/* + * This is the C++ API. + */ + +class ChipHelper +{ +public: + /* If this constructor is used then a GetVersionXXX function + should be called next. */ + ChipHelper(); + + /* copy constructor */ + ChipHelper(ChipDescript * desc); + + /* The default constructor assume a BC7 / UF105x series chip + and that the number given is the value of UNIFI_GBL_CHIP_VERSION + (0xFE81) */ + ChipHelper(CsrUint16 version); + + /* This returns the C interface magic token from a C++ instance. */ + ChipDescript* GetDescript() const + { + return m_desc; + } + + + /* Clear out theis class (set it to the null token). */ + void ClearVersion(); + + /* Load this class with data for a specific chip. */ + void GetVersionAny(CsrUint16 from_FF9A, CsrUint16 from_FE81); + void GetVersionUniFi(CsrUint16 version); + void GetVersionBlueCore(chip_helper_bluecore_age age, CsrUint16 version); + void GetVersionSdio(CsrUint8 sdio_version); + + /* Helpers to build the definitions of the member functions. */ +#define CHIP_HELPER_DEF0_CPP_DEC(ret_type, name, info) \ + ret_type name() const; +#define CHIP_HELPER_DEF1_CPP_DEC(ret_type, name, type1, name1) \ + ret_type name(type1 name1) const; + + CHIP_HELPER_LIST(CPP_DEC) + + + /* The DecodeWindow function, see the description of the C version. */ + CsrInt32 DecodeWindow(chip_helper_window_index window, + chip_helper_window_type type, + CsrUint32 offset, + CsrUint16 &page, CsrUint16 &addr, CsrUint32 &len) const; + +private: + ChipDescript *m_desc; +}; + +#endif /* __cplusplus */ + +#endif diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h b/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h new file mode 100644 index 000000000000..7ab8173328c4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h @@ -0,0 +1,208 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ +#define CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ + + +#include "csr_wifi_hip_chiphelper.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* This GP stuff should be somewhere else? */ + +/* Memory spaces encoded in top byte of Generic Pointer type */ +#define UNIFI_SH_DMEM 0x01 /* Shared Data Memory */ +#define UNIFI_EXT_FLASH 0x02 /* External FLASH */ +#define UNIFI_EXT_SRAM 0x03 /* External SRAM */ +#define UNIFI_REGISTERS 0x04 /* Registers */ +#define UNIFI_PHY_DMEM 0x10 /* PHY Data Memory */ +#define UNIFI_PHY_PMEM 0x11 /* PHY Program Memory */ +#define UNIFI_PHY_ROM 0x12 /* PHY ROM */ +#define UNIFI_MAC_DMEM 0x20 /* MAC Data Memory */ +#define UNIFI_MAC_PMEM 0x21 /* MAC Program Memory */ +#define UNIFI_MAC_ROM 0x22 /* MAC ROM */ +#define UNIFI_BT_DMEM 0x30 /* BT Data Memory */ +#define UNIFI_BT_PMEM 0x31 /* BT Program Memory */ +#define UNIFI_BT_ROM 0x32 /* BT ROM */ + +#define MAKE_GP(R, O) (((UNIFI_ ## R) << 24) | (O)) +#define GP_OFFSET(GP) ((GP) & 0xFFFFFF) +#define GP_SPACE(GP) (((GP) >> 24) & 0xFF) + + +/* Address value pairs */ +struct val_array_t +{ + CsrUint32 len; + const struct chip_helper_init_values *vals; +}; + +/* Just a (counted) CsrUint16 array */ +struct data_array_t +{ + CsrUint32 len; + const CsrUint16 *vals; +}; + +struct reset_prog_t +{ + CsrUint32 len; + const struct chip_helper_reset_values *vals; +}; + +/* The addresses of registers that are equivalent but on + different host transports. */ +struct chip_map_address_t +{ + CsrUint16 spi, host; +}; + +struct map_array_t +{ + CsrUint32 len; + const struct chip_map_address_t *vals; +}; + +struct chip_device_regs_per_transport_t +{ + CsrUint16 dbg_proc_select; + CsrUint16 dbg_stop_status; + CsrUint16 window1_page; /* PROG_PMEM1 or GW1 */ + CsrUint16 window2_page; /* PROG_PMEM2 or GW2 */ + CsrUint16 window3_page; /* SHARED or GW3 */ + CsrUint16 io_log_addr; +}; + +struct chip_device_regs_t +{ + CsrUint16 gbl_chip_version; + CsrUint16 gbl_misc_enables; + CsrUint16 dbg_emu_cmd; + struct chip_device_regs_per_transport_t host; + struct chip_device_regs_per_transport_t spi; + CsrUint16 dbg_reset; + CsrUint16 dbg_reset_value; + CsrUint16 dbg_reset_warn; + CsrUint16 dbg_reset_warn_value; + CsrUint16 dbg_reset_result; + CsrUint16 xap_pch; + CsrUint16 xap_pcl; + CsrUint16 proc_pc_snoop; + CsrUint16 watchdog_disable; + CsrUint16 mailbox0; + CsrUint16 mailbox1; + CsrUint16 mailbox2; + CsrUint16 mailbox3; + CsrUint16 sdio_host_int; + CsrUint16 shared_io_interrupt; + CsrUint16 sdio_hip_handshake; + CsrUint16 coex_status; /* Allows WAPI detection */ +}; + +/* If allowed is false then this window does not provide this + type of access. + This describes how addresses should be shifted to make the + "page" address. The address is shifted left by 'page_shift' + and then has 'page_offset' added. This value should then be + written to the page register. */ +struct window_shift_info_t +{ + CsrInt32 allowed; + CsrUint32 page_shift; + CsrUint16 page_offset; +}; + +/* Each window has an address and size. These are obvious. It then + has a description for each type of memory that might be accessed + through it. There might also be a start to the offset of the window. + This means that that number of addresses at the start of the window + are unusable. */ +struct window_info_t +{ + CsrUint16 address; + CsrUint16 size; + CsrUint16 blocked; + const struct window_shift_info_t *mode; +}; + +/* If GBL_CHIP_VERSION and'ed with 'mask' and is equal to 'result' + then this is the correct set of info. If pre_bc7 is true then the + address of GBL_CHIP_VERSION is FF9A, else its FE81. */ +struct chip_version_t +{ + CsrInt32 pre_bc7; + CsrUint16 mask; + CsrUint16 result; + CsrUint8 sdio; +}; + +struct chip_device_desc_t +{ + struct chip_version_t chip_version; + + /* This is a text string that a human might find useful (BC02, UF105x) */ + const CsrCharString *friendly_name; + /* This is what we show to customers */ + const CsrCharString *marketing_name; + + /* Initialisation values to write following a reset */ + struct val_array_t init; + + /* Binary sequence for hard reset */ + struct reset_prog_t reset_prog; + + /* The register map */ + const struct chip_device_regs_t *regs; + + /* Some misc. info on the chip */ + struct + { + CsrUint32 has_flash : 1; + CsrUint32 has_ext_sram : 1; + CsrUint32 has_rom : 1; + CsrUint32 has_bt : 1; + CsrUint32 has_wlan : 1; + } bools; + + /* This table is used to remap register addresses depending on what + host interface is used. On the BC7 and later chips there are + multiple sets of memory window registers, on for each host + interafce (SDIO / SPI). The correct one is needed. */ + struct map_array_t map; + + /* The offsets into the program address space of the different types of memory. + The RAM offset is probably the most useful. */ + struct + { + CsrUint32 ram; + CsrUint32 rom; + CsrUint32 flash; + CsrUint32 ext_sram; + } prog_offset; + + /* The offsets into the data address space of interesting things. */ + struct + { + CsrUint16 ram; + /* maybe add shared / page tables? */ + } data_offset; + + /* Information on the different windows */ + const struct window_info_t *windows[CHIP_HELPER_WINDOW_COUNT]; +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_conversions.h b/drivers/staging/csr/csr_wifi_hip_conversions.h new file mode 100644 index 000000000000..6a4647d5f910 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_conversions.h @@ -0,0 +1,81 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * + * FILE: csr_wifi_hip_conversions.h + * + * PURPOSE: + * This header file provides the macros for converting to and from + * wire format. + * These macros *MUST* work for little-endian AND big-endian hosts. + * + * --------------------------------------------------------------------------- + */ +#ifndef __CSR_WIFI_HIP_CONVERSIONS_H__ +#define __CSR_WIFI_HIP_CONVERSIONS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SIZEOF_UINT16 2 +#define SIZEOF_UINT32 4 +#define SIZEOF_UINT64 8 + +#define SIZEOF_SIGNAL_HEADER 6 +#define SIZEOF_DATAREF 4 + + +/* + * Macro to retrieve the signal ID from a wire-format signal. + */ +#define GET_SIGNAL_ID(_buf) CSR_GET_UINT16_FROM_LITTLE_ENDIAN((_buf)) + +/* + * Macros to retrieve and set the DATAREF fields in a packed (i.e. wire-format) + * HIP signal. + */ +#define GET_PACKED_DATAREF_SLOT(_buf, _ref) \ + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 0)) + +#define GET_PACKED_DATAREF_LEN(_buf, _ref) \ + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 2)) + +#define SET_PACKED_DATAREF_SLOT(_buf, _ref, _slot) \ + CSR_COPY_UINT16_TO_LITTLE_ENDIAN((_slot), ((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 0)) + +#define SET_PACKED_DATAREF_LEN(_buf, _ref, _len) \ + CSR_COPY_UINT16_TO_LITTLE_ENDIAN((_len), ((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 2)) + +#define GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(_buf) \ + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 8)) + +#define GET_PACKED_MA_PACKET_REQUEST_HOST_TAG(_buf) \ + CSR_GET_UINT32_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 4)) + +#define GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(_buf) \ + CSR_GET_UINT32_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 8)) + +#define GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(_buf) \ + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 2)) + + +CsrInt32 get_packed_struct_size(const CsrUint8 *buf); +CsrResult read_unpack_signal(const CsrUint8 *ptr, CSR_SIGNAL *sig); +CsrResult write_pack(const CSR_SIGNAL *sig, CsrUint8 *ptr, CsrUint16 *sig_len); + +#ifdef __cplusplus +} +#endif + +#endif /* __CSR_WIFI_HIP_CONVERSIONS_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_hip_download.c b/drivers/staging/csr/csr_wifi_hip_download.c new file mode 100644 index 000000000000..fb6f04e1bbf4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_download.c @@ -0,0 +1,834 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_download.c + * + * PURPOSE: + * Routines for downloading firmware to UniFi. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifiversion.h" +#include "csr_wifi_hip_card.h" +#include "csr_wifi_hip_xbv.h" + +#undef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH + +static CsrResult do_patch_download(card_t *card, void *dlpriv, + xbv1_t *pfwinfo, CsrUint32 boot_ctrl_addr); + +static CsrResult do_patch_convert_download(card_t *card, + void *dlpriv, xbv1_t *pfwinfo); + +/* + * --------------------------------------------------------------------------- + * _find_in_slut + * + * Find the offset of the appropriate object in the SLUT of a card + * + * Arguments: + * card Pointer to card struct + * psym Pointer to symbol object. + * id set up by caller + * obj will be set up by this function + * pslut Pointer to SLUT address, if 0xffffffff then it must be + * read from the chip. + * Returns: + * CSR_RESULT_SUCCESS on success + * Non-zero on error, + * CSR_WIFI_HIP_RESULT_NOT_FOUND if not found + * --------------------------------------------------------------------------- + */ +static CsrResult _find_in_slut(card_t *card, symbol_t *psym, CsrUint32 *pslut) +{ + CsrUint32 slut_address; + CsrUint16 finger_print; + CsrResult r; + CsrResult csrResult; + + /* Get SLUT address */ + if (*pslut == 0xffffffff) + { + r = card_wait_for_firmware_to_start(card, &slut_address); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Firmware hasn't started\n"); + func_exit_r(r); + return r; + } + *pslut = slut_address; + + /* + * Firmware has started so set the SDIO bus clock to the initial speed, + * faster than UNIFI_SDIO_CLOCK_SAFE_HZ, to speed up the f/w download. + */ + csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); + if (csrResult != CSR_RESULT_SUCCESS) + { + r = ConvertCsrSdioToCsrHipResult(card, csrResult); + func_exit_r(r); + return r; + } + card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; + } + else + { + slut_address = *pslut; /* Use previously discovered address */ + } + unifi_trace(card->ospriv, UDBG4, "SLUT addr: 0x%lX\n", slut_address); + + /* + * Check the SLUT fingerprint. + * The slut_address is a generic pointer so we must use unifi_card_read16(). + */ + unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n"); + finger_print = 0; + r = unifi_card_read16(card, slut_address, &finger_print); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read SLUT finger print\n"); + func_exit_r(r); + return r; + } + + if (finger_print != SLUT_FINGERPRINT) + { + unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n"); + func_exit_r(CSR_RESULT_FAILURE); + return CSR_RESULT_FAILURE; + } + + /* Symbol table starts imedately after the fingerprint */ + slut_address += 2; + + while (1) + { + CsrUint16 id; + CsrUint32 obj; + + r = unifi_card_read16(card, slut_address, &id); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + slut_address += 2; + + if (id == CSR_SLT_END) + { + /* End of table reached: not found */ + r = CSR_WIFI_HIP_RESULT_RANGE; + break; + } + + r = unifi_read32(card, slut_address, &obj); + if (r != CSR_RESULT_SUCCESS) + { + func_exit_r(r); + return r; + } + slut_address += 4; + + unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", id, obj); + + r = CSR_WIFI_HIP_RESULT_NOT_FOUND; + /* Found search term? */ + if (id == psym->id) + { + unifi_trace(card->ospriv, UDBG1, " matched SLUT id %02d.%08lx\n", id, obj); + psym->obj = obj; + r = CSR_RESULT_SUCCESS; + break; + } + } + + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * do_patch_convert_download + * + * Download the given firmware image to the UniFi, converting from FWDL + * to PTDL XBV format. + * + * Arguments: + * card Pointer to card struct + * dlpriv Pointer to source firmware image + * fwinfo Pointer to source firmware info struct + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on error + * + * Notes: + * --------------------------------------------------------------------------- + */ +static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo) +{ + CsrResult r; + CsrUint32 slut_base = 0xffffffff; + void *pfw; + CsrUint32 psize; + symbol_t sym; + + /* Reset the chip to guarantee that the ROM loader is running */ + r = unifi_init(card); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, + "do_patch_convert_download: failed to re-init UniFi\n"); + return r; + } + + /* If no unifi_helper is running, the firmware version must be read */ + if (card->build_id == 0) + { + CsrUint32 ver = 0; + sym.id = CSR_SLT_BUILD_ID_NUMBER; + sym.obj = 0; /* To be updated by _find_in_slut() */ + + unifi_trace(card->ospriv, UDBG1, "Need f/w version\n"); + + /* Find chip build id entry in SLUT */ + r = _find_in_slut(card, &sym, &slut_base); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to find CSR_SLT_BUILD_ID_NUMBER\n"); + return CSR_RESULT_FAILURE; + } + + /* Read running f/w version */ + r = unifi_read32(card, sym.obj, &ver); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read f/w id\n"); + return CSR_RESULT_FAILURE; + } + card->build_id = ver; + } + + /* Convert the ptest firmware to a patch against the running firmware */ + pfw = xbv_to_patch(card, unifi_fw_read, dlpriv, pfwinfo, &psize); + if (!pfw) + { + unifi_error(card->ospriv, "Failed to convert f/w to patch"); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + else + { + void *desc; + sym.id = CSR_SLT_BOOT_LOADER_CONTROL; + sym.obj = 0; /* To be updated by _find_in_slut() */ + + /* Find boot loader control entry in SLUT */ + r = _find_in_slut(card, &sym, &slut_base); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n"); + return CSR_RESULT_FAILURE; + } + + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to wake UniFi\n"); + } + + /* Get a dlpriv for the patch buffer so that unifi_fw_read() can + * access it. + */ + desc = unifi_fw_open_buffer(card->ospriv, pfw, psize); + if (!desc) + { + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + /* Download the patch */ + unifi_info(card->ospriv, "Downloading converted f/w as patch\n"); + r = unifi_dl_patch(card, desc, sym.obj); + CsrMemFree(pfw); + unifi_fw_close_buffer(card->ospriv, desc); + + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Converted patch download failed\n"); + func_exit_r(r); + return r; + } + else + { + unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n"); + } + + /* This command starts the firmware */ + r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write loader restart cmd\n"); + } + + func_exit_r(r); + return r; + } +} + + +/* + * --------------------------------------------------------------------------- + * unifi_dl_firmware + * + * Download the given firmware image to the UniFi. + * + * Arguments: + * card Pointer to card struct + * dlpriv A context pointer from the calling function to be + * passed when calling unifi_fw_read(). + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed + * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file + * CSR_RESULT_FAILURE SDIO error + * + * Notes: + * Stops and resets the chip, does the download and runs the new + * firmware. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_dl_firmware(card_t *card, void *dlpriv) +{ + xbv1_t *fwinfo; + CsrResult r; + + func_enter(); + + fwinfo = CsrMemAlloc(sizeof(xbv1_t)); + if (fwinfo == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for firmware\n"); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + /* + * Scan the firmware file to find the TLVs we are interested in. + * These are: + * - check we support the file format version in VERF + * - SLTP Symbol Lookup Table Pointer + * - FWDL firmware download segments + * - FWOV firmware overlay segment + * - VMEQ Register probe tests to verify matching h/w + */ + r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo); + if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware) + { + unifi_error(card->ospriv, "File type is %s, expected firmware.\n", + fwinfo->mode == xbv_patch?"patch" : "unknown"); + CsrMemFree(fwinfo); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* UF6xxx doesn't accept firmware, only patches. Therefore we convert + * the file to patch format with version numbers matching the current + * running firmware, and then download via the patch mechanism. + * The sole purpose of this is to support production test firmware across + * different ROM releases, the test firmware being provided in non-patch + * format. + */ + if (card->chip_id > SDIO_CARD_ID_UNIFI_2) + { + unifi_info(card->ospriv, "Must convert f/w to patch format\n"); + r = do_patch_convert_download(card, dlpriv, fwinfo); + } + else + { + /* Older UniFi chips allowed firmware to be directly loaded onto the + * chip, which is no longer supported. + */ + unifi_error(card->ospriv, "Only patch downloading supported\n"); + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + CsrMemFree(fwinfo); + func_exit_r(r); + return r; +} /* unifi_dl_firmware() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_dl_patch + * + * Load the given patch set into UniFi. + * + * Arguments: + * card Pointer to card struct + * dlpriv The os specific handle to the firmware file. + * boot_ctrl The address of the boot loader control structure. + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed + * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file + * CSR_RESULT_FAILURE SDIO error + * + * Notes: + * This ends up telling UniFi to restart. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_dl_patch(card_t *card, void *dlpriv, CsrUint32 boot_ctrl) +{ + xbv1_t *fwinfo; + CsrResult r; + + func_enter(); + + unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl); + + fwinfo = CsrMemAlloc(sizeof(xbv1_t)); + if (fwinfo == NULL) + { + unifi_error(card->ospriv, "Failed to allocate memory for patches\n"); + func_exit(); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + /* + * Scan the firmware file to find the TLVs we are interested in. + * These are: + * - check we support the file format version in VERF + * - FWID The build ID of the ROM that we can patch + * - PTDL patch download segments + */ + r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo); + if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch) + { + CsrMemFree(fwinfo); + unifi_error(card->ospriv, "Failed to read in patch file\n"); + func_exit(); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* + * We have to check the build id read from the SLUT against that + * for the patch file. They have to match exactly. + * "card->build_id" == XBV1.PTCH.FWID + */ + if (card->build_id != fwinfo->build_id) + { + unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n", + card->build_id, fwinfo->build_id); + CsrMemFree(fwinfo); +#ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH + func_exit(); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; +#else + fwinfo = NULL; + dlpriv = NULL; + return CSR_RESULT_SUCCESS; +#endif + } + + r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to patch image\n"); + } + + CsrMemFree(fwinfo); + + func_exit_r(r); + return r; +} /* unifi_dl_patch() */ + + +void* unifi_dl_fw_read_start(card_t *card, CsrInt8 is_fw) +{ + card_info_t card_info; + + unifi_card_info(card, &card_info); + unifi_trace(card->ospriv, UDBG5, + "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n", + card_info.chip_id, card_info.chip_version, + card_info.fw_build, card_info.fw_hip_version, + card_info.sdio_block_size); + + return unifi_fw_read_start(card->ospriv, is_fw, &card_info); +} + + +/* + * --------------------------------------------------------------------------- + * safe_read_shared_location + * + * Read a shared memory location repeatedly until we get two readings + * the same. + * + * Arguments: + * card Pointer to card context struct. + * unifi_addr UniFi shared-data-memory address to access. + * pdata Pointer to a byte variable for the value read. + * + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure + * --------------------------------------------------------------------------- + */ +static CsrResult safe_read_shared_location(card_t *card, CsrUint32 address, CsrUint8 *pdata) +{ + CsrResult r; + CsrUint16 limit = 1000; + CsrUint8 b, b2; + + *pdata = 0; + + r = unifi_read_8_or_16(card, address, &b); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + while (limit--) + { + r = unifi_read_8_or_16(card, address, &b2); + if (r != CSR_RESULT_SUCCESS) + { + return r; + } + + /* When we have a stable value, return it */ + if (b == b2) + { + *pdata = b; + return CSR_RESULT_SUCCESS; + } + + b = b2; + } + + return CSR_RESULT_FAILURE; +} /* safe_read_shared_location() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_do_loader_op + * + * Send a loader / boot_loader command to the UniFi and wait for + * it to complete. + * + * Arguments: + * card Pointer to card context struct. + * op_addr The address of the loader operation control word. + * opcode The operation to perform. + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CSR_RESULT_FAILURE SDIO error or SDIO/XAP timeout + * --------------------------------------------------------------------------- + */ + +/* + * Ideally instead of sleeping, we want to busy wait. + * Currently there is no framework API to do this. When it becomes available, + * we can use it to busy wait using usecs + */ +#define OPERATION_TIMEOUT_LOOPS (100) /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */ +#define OPERATION_TIMEOUT_DELAY 1 /* msec, or 200usecs */ + +CsrResult unifi_do_loader_op(card_t *card, CsrUint32 op_addr, CsrUint8 opcode) +{ + CsrResult r; + CsrInt16 op_retries; + + unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr); + + /* Set the Operation command byte to the opcode */ + r = unifi_write_8_or_16(card, op_addr, opcode); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to write loader copy command\n"); + return r; + } + + /* Wait for Operation command byte to be Idle */ + /* Typically takes ~100us */ + op_retries = 0; + r = CSR_RESULT_SUCCESS; + while (1) + { + CsrUint8 op; + + /* + * Read the memory location until two successive reads give + * the same value. + * Then handle it. + */ + r = safe_read_shared_location(card, op_addr, &op); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to read loader status\n"); + break; + } + + if (op == UNIFI_LOADER_IDLE) + { + /* Success */ + break; + } + + if (op != opcode) + { + unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op); + r = CSR_RESULT_FAILURE; + break; + } + + /* Allow 500us timeout */ + if (++op_retries >= OPERATION_TIMEOUT_LOOPS) + { + unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n"); + /* Stop XAPs to aid post-mortem */ + r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to stop UniFi processors\n"); + } + else + { + r = CSR_RESULT_FAILURE; + } + break; + } + CsrThreadSleep(OPERATION_TIMEOUT_DELAY); + } /* Loop exits with r != CSR_RESULT_SUCCESS on error */ + + return r; +} /* unifi_do_loader_op() */ + + +/* + * --------------------------------------------------------------------------- + * send_ptdl_to_unifi + * + * Copy a patch block from userland to the UniFi. + * This function reads data, 2K at a time, from userland and writes + * it to the UniFi. + * + * Arguments: + * card A pointer to the card structure + * dlpriv The os specific handle for the firmware file + * ptdl A pointer ot the PTDL block + * handle The buffer handle to use for the xfer + * op_addr The address of the loader operation control word + * + * Returns: + * Number of bytes sent (Positive) or negative value indicating + * error code: + * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed + * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file + * CSR_RESULT_FAILURE SDIO error + * --------------------------------------------------------------------------- + */ +static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv, + const struct PTDL *ptdl, CsrUint32 handle, + CsrUint32 op_addr) +{ + CsrUint32 offset; + CsrUint8 *buf; + CsrInt32 data_len; + CsrUint32 write_len; + CsrResult r; + const CsrUint16 buf_size = 2 * 1024; + + offset = ptdl->dl_offset; + data_len = ptdl->dl_size; + + if (data_len > buf_size) + { + unifi_error(card->ospriv, "PTDL block is too large (%u)\n", + ptdl->dl_size); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + buf = CsrMemAlloc(buf_size); + if (buf == NULL) + { + unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n"); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; + } + + r = CSR_RESULT_SUCCESS; + + if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len) + { + unifi_error(card->ospriv, "Failed to read from file\n"); + } + else + { + /* We can always round these if the host wants to */ + if (card->sdio_io_block_pad) + { + write_len = (data_len + (card->sdio_io_block_size - 1)) & + ~(card->sdio_io_block_size - 1); + + /* Zero out the rest of the buffer (This isn't needed, but it + * makes debugging things later much easier). */ + CsrMemSet(buf + data_len, 0, write_len - data_len); + } + else + { + write_len = data_len; + } + + r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n", + data_len, handle); + } + else + { + /* + * Can change the order of things to overlap read from file + * with copy to unifi + */ + r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH); + } + } + + CsrMemFree(buf); + + if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n", + ptdl->dl_size); + } + + return r; +} /* send_ptdl_to_unifi() */ + + +/* + * --------------------------------------------------------------------------- + * do_patch_download + * + * This function downloads a set of patches to UniFi and then + * causes it to restart. + * + * Arguments: + * card Pointer to card struct. + * dlpriv A context pointer from the calling function to be + * used when reading the XBV file. This can be NULL + * in which case not patches are applied. + * pfwinfo Pointer to a fwinfo struct describing the f/w + * XBV file. + * boot_ctrl_addr The address of the boot loader control structure. + * + * Returns: + * 0 on success, or an error code + * CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number + * --------------------------------------------------------------------------- + */ +static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, CsrUint32 boot_ctrl_addr) +{ + CsrResult r; + CsrInt32 i; + CsrUint16 loader_version; + CsrUint16 handle; + CsrUint32 total_bytes; + + /* + * Read info from the SDIO Loader Control Data Structure + */ + /* Check the loader version */ + r = unifi_card_read16(card, boot_ctrl_addr, &loader_version); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Patch download: Failed to read loader version\n"); + return r; + } + unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version); + switch (loader_version) + { + case 0x0000: + break; + + default: + unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n", + loader_version); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* Retrieve the handle to use with CMD53 */ + r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n"); + return r; + } + + /* Set the mask of LEDs to flash */ + if (card->loader_led_mask) + { + r = unifi_card_write16(card, boot_ctrl_addr + 2, + (CsrUint16)card->loader_led_mask); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n"); + return r; + } + } + + total_bytes = 0; + + /* Copy download data to UniFi memory */ + for (i = 0; i < pfwinfo->num_ptdl; i++) + { + unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n", + i, + pfwinfo->ptdl[i].dl_size, + pfwinfo->ptdl[i].dl_offset); + + r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i], + handle, boot_ctrl_addr + 6); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + return r; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Patch failed after %u bytes\n", + total_bytes); + return r; + } + total_bytes += pfwinfo->ptdl[i].dl_size; + } + + return CSR_RESULT_SUCCESS; +} /* do_patch_download() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_dump.c b/drivers/staging/csr/csr_wifi_hip_dump.c new file mode 100644 index 000000000000..c191ea135040 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_dump.c @@ -0,0 +1,872 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_dump.c + * + * PURPOSE: + * Routines for retrieving and buffering core status from the UniFi + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifiversion.h" +#include "csr_wifi_hip_card.h" + +/* Locations to capture in dump (XAP words) */ +#define HIP_CDUMP_FIRST_CPUREG (0xFFE0) /* First CPU register */ +#define HIP_CDUMP_FIRST_LO (0) /* Start of low address range */ +#define HIP_CDUMP_FIRST_HI_MAC (0x3C00) /* Start of MAC high area */ +#define HIP_CDUMP_FIRST_HI_PHY (0x1C00) /* Start of PHY high area */ +#define HIP_CDUMP_FIRST_SH (0) /* Start of shared memory area */ + +#define HIP_CDUMP_NCPUREGS (10) /* No. of 16-bit XAP registers */ +#define HIP_CDUMP_NWORDS_LO (0x0100) /* Low area size in 16-bit words */ +#define HIP_CDUMP_NWORDS_HI (0x0400) /* High area size in 16-bit words */ +#define HIP_CDUMP_NWORDS_SH (0x0500) /* Shared memory area size, 16-bit words */ + +#define HIP_CDUMP_NUM_ZONES 7 /* Number of UniFi memory areas to capture */ + +/* Mini-coredump state */ +typedef struct coredump_buf +{ + CsrUint16 count; /* serial number of dump */ + CsrTime timestamp; /* host's system time at capture */ + CsrInt16 requestor; /* request: 0=auto dump, 1=manual */ + CsrUint16 chip_ver; + CsrUint32 fw_ver; + CsrUint16 *zone[HIP_CDUMP_NUM_ZONES]; + + struct coredump_buf *next; /* circular list */ + struct coredump_buf *prev; /* circular list */ +} coredump_buffer; + +/* Structure used to describe a zone of chip memory captured by mini-coredump */ +struct coredump_zone +{ + unifi_coredump_space_t space; /* XAP memory space this zone covers */ + enum unifi_dbg_processors_select cpu; /* XAP CPU core selector */ + CsrUint32 gp; /* Generic Pointer to memory zone on XAP */ + CsrUint16 offset; /* 16-bit XAP word offset of zone in memory space */ + CsrUint16 length; /* Length of zone in XAP words */ +}; + +static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_buf); +static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_buf); +static CsrResult unifi_coredump_read_zone(card_t *card, CsrUint16 *zone, + const struct coredump_zone *def); +static CsrInt32 get_value_from_coredump(const coredump_buffer *dump, + const unifi_coredump_space_t space, const CsrUint16 offset); + +/* Table of chip memory zones we capture on mini-coredump */ +static const struct coredump_zone zonedef_table[HIP_CDUMP_NUM_ZONES] = { + { UNIFI_COREDUMP_MAC_REG, UNIFI_PROC_MAC, UNIFI_MAKE_GP(REGISTERS, HIP_CDUMP_FIRST_CPUREG * 2), HIP_CDUMP_FIRST_CPUREG, HIP_CDUMP_NCPUREGS }, + { UNIFI_COREDUMP_PHY_REG, UNIFI_PROC_PHY, UNIFI_MAKE_GP(REGISTERS, HIP_CDUMP_FIRST_CPUREG * 2), HIP_CDUMP_FIRST_CPUREG, HIP_CDUMP_NCPUREGS }, + { UNIFI_COREDUMP_SH_DMEM, UNIFI_PROC_INVALID, UNIFI_MAKE_GP(SH_DMEM, HIP_CDUMP_FIRST_SH * 2), HIP_CDUMP_FIRST_SH, HIP_CDUMP_NWORDS_SH }, + { UNIFI_COREDUMP_MAC_DMEM, UNIFI_PROC_MAC, UNIFI_MAKE_GP(MAC_DMEM, HIP_CDUMP_FIRST_LO * 2), HIP_CDUMP_FIRST_LO, HIP_CDUMP_NWORDS_LO }, + { UNIFI_COREDUMP_MAC_DMEM, UNIFI_PROC_MAC, UNIFI_MAKE_GP(MAC_DMEM, HIP_CDUMP_FIRST_HI_MAC * 2), HIP_CDUMP_FIRST_HI_MAC, HIP_CDUMP_NWORDS_HI }, + { UNIFI_COREDUMP_PHY_DMEM, UNIFI_PROC_PHY, UNIFI_MAKE_GP(PHY_DMEM, HIP_CDUMP_FIRST_LO * 2), HIP_CDUMP_FIRST_LO, HIP_CDUMP_NWORDS_LO }, + { UNIFI_COREDUMP_PHY_DMEM, UNIFI_PROC_PHY, UNIFI_MAKE_GP(PHY_DMEM, HIP_CDUMP_FIRST_HI_PHY * 2), HIP_CDUMP_FIRST_HI_PHY, HIP_CDUMP_NWORDS_HI }, +}; + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_request_at_next_reset + * + * Request that a mini-coredump is performed when the driver has + * completed resetting the UniFi device. + * + * Arguments: + * card Pointer to card struct + * enable If non-zero, sets the request. + * If zero, cancels any pending request. + * + * Returns: + * CSR_RESULT_SUCCESS or CSR HIP error code + * + * Notes: + * This function is typically called once the driver has detected that + * the UniFi device has become unresponsive due to crash, or internal + * watchdog reset. The driver must reset it to regain communication and, + * immediately after that, the mini-coredump can be captured. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_coredump_request_at_next_reset(card_t *card, CsrInt8 enable) +{ + CsrResult r; + + func_enter(); + + if (enable) + { + unifi_trace(card->ospriv, UDBG2, "Mini-coredump requested after reset\n"); + } + + if (card == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + else + { + card->request_coredump_on_reset = enable?1 : 0; + r = CSR_RESULT_SUCCESS; + } + + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_handle_request + * + * Performs a coredump now, if one was requested, and clears the request. + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * CSR_RESULT_SUCCESS or CSR HIP error code + * + * Notes: + * --------------------------------------------------------------------------- + */ +CsrResult unifi_coredump_handle_request(card_t *card) +{ + CsrResult r = CSR_RESULT_SUCCESS; + + func_enter(); + + if (card == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + else + { + if (card->request_coredump_on_reset == 1) + { + card->request_coredump_on_reset = 0; + r = unifi_coredump_capture(card, NULL); + } + } + + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_capture + * + * Capture the current status of the UniFi device. + * Various registers are buffered for future offline inspection. + * + * Arguments: + * card Pointer to card struct + * req Pointer to request struct, or NULL: + * A coredump requested manually by the user app + * will have a request struct pointer, an automatic + * coredump will have a NULL pointer. + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_RESULT_FAILURE SDIO error + * CSR_WIFI_HIP_RESULT_INVALID_VALUE Initialisation not complete + * + * Notes: + * The result is a filled entry in the circular buffer of core dumps, + * values from which can be extracted to userland via an ioctl. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req) +{ + CsrResult r = CSR_RESULT_SUCCESS; + static CsrUint16 dump_seq_no = 1; + CsrTime time_of_capture; + + func_enter(); + + if (card->dump_next_write == NULL) + { + r = CSR_RESULT_SUCCESS; + goto done; + } + + /* Reject forced capture before initialisation has happened */ + if (card->helper == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + goto done; + } + + + /* + * Force a mini-coredump capture right now + */ + time_of_capture = CsrTimeGet(NULL); + unifi_info(card->ospriv, "Mini-coredump capture at t=%u\n", time_of_capture); + + /* Wake up the processors so we can talk to them */ + r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to wake UniFi\n"); + goto done; + } + CsrThreadSleep(20); + + /* Stop both XAPs */ + unifi_trace(card->ospriv, UDBG4, "Stopping XAPs for coredump capture\n"); + r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to stop UniFi XAPs\n"); + goto done; + } + + /* Dump core into the next available slot in the circular list */ + r = unifi_coredump_from_sdio(card, card->dump_next_write); + if (r == CSR_RESULT_SUCCESS) + { + /* Record whether the dump was manual or automatic */ + card->dump_next_write->requestor = (req?1 : 0); + card->dump_next_write->timestamp = time_of_capture; + /* Advance to the next buffer */ + card->dump_next_write->count = dump_seq_no++; + card->dump_cur_read = card->dump_next_write; + card->dump_next_write = card->dump_next_write->next; + + /* Sequence no. of zero indicates slot not in use, so handle wrap */ + if (dump_seq_no == 0) + { + dump_seq_no = 1; + } + + unifi_trace(card->ospriv, UDBG3, + "Coredump (%p), SeqNo=%d, cur_read=%p, next_write=%p\n", + req, + card->dump_cur_read->count, + card->dump_cur_read, card->dump_next_write); + } + + /* Start both XAPs */ + unifi_trace(card->ospriv, UDBG4, "Restart XAPs after coredump\n"); + r = card_start_processor(card, UNIFI_PROC_BOTH); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Failed to start UniFi XAPs\n"); + goto done; + } + +done: + func_exit_r(r); + return r; +} /* unifi_coredump_capture() */ + + +/* + * --------------------------------------------------------------------------- + * get_value_from_coredump + * + * + * + * Arguments: + * dump Pointer to buffered coredump data + * offset_in_space XAP memory space to retrieve from the buffer (there + * may be more than one zone covering the same memory + * space, but starting from different offsets). + * offset Offset within the XAP memory space to be retrieved + * + * Returns: + * >=0 Register value on success + * <0 Register out of range of any captured zones + * + * Notes: + * --------------------------------------------------------------------------- + */ +static CsrInt32 get_value_from_coredump(const coredump_buffer *dump, + const unifi_coredump_space_t space, + const CsrUint16 offset_in_space) +{ + CsrInt32 r = -1; + CsrUint16 offset_in_zone; + CsrUint32 zone_end_offset; + CsrInt32 i; + const struct coredump_zone *def = &zonedef_table[0]; + + /* Search zone def table for a match with the requested memory space */ + for (i = 0; i < HIP_CDUMP_NUM_ZONES; i++, def++) + { + if (space == def->space) + { + zone_end_offset = def->offset + def->length; + + /* Is the space offset contained in this zone? */ + if (offset_in_space < zone_end_offset && + offset_in_space >= def->offset) + { + /* Calculate the offset of data within the zone buffer */ + offset_in_zone = offset_in_space - def->offset; + r = (CsrInt32) * (dump->zone[i] + offset_in_zone); + + unifi_trace(NULL, UDBG6, + "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n", + space, offset_in_space, r, + i, def->offset, zone_end_offset - 1); + break; + } + } + } + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_get_value + * + * Retrieve the value of a register buffered from a previous core dump, + * so that it may be reported back to application code. + * + * Arguments: + * card Pointer to card struct + * req_reg Pointer to request parameter partially filled. This + * function puts in the values retrieved from the dump. + * + * Returns: + * CSR_RESULT_SUCCESS on success, or: + * CSR_WIFI_HIP_RESULT_INVALID_VALUE Null parameter error + * CSR_WIFI_HIP_RESULT_RANGE Register out of range + * CSR_WIFI_HIP_RESULT_NOT_FOUND Dump index not (yet) captured + * + * Notes: + * --------------------------------------------------------------------------- + */ +CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req) +{ + CsrResult r; + CsrInt32 i = 0; + coredump_buffer *find_dump = NULL; + + func_enter(); + + if (req == NULL || card == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + goto done; + } + req->value = -1; + if (card->dump_buf == NULL) + { + unifi_trace(card->ospriv, UDBG2, "No coredump buffers\n"); + r = CSR_WIFI_HIP_RESULT_NOT_FOUND; /* Coredumping disabled */ + goto done; + } + if (card->dump_cur_read == NULL) + { + unifi_trace(card->ospriv, UDBG4, "No coredumps captured\n"); + r = CSR_WIFI_HIP_RESULT_NOT_FOUND; /* No coredump yet captured */ + goto done; + } + + /* Find the requested dump buffer */ + switch (req->index) + { + case 0: /* Newest */ + find_dump = card->dump_cur_read; + break; + case -1: /* Oldest: The next used slot forward */ + for (find_dump = card->dump_cur_read->next; + (find_dump->count == 0) && (find_dump != card->dump_cur_read); + find_dump = card->dump_cur_read->next) + { + } + break; + default: /* Number of steps back from current read position */ + for (i = 0, find_dump = card->dump_cur_read; + i < req->index; + i++, find_dump = find_dump->prev) + { + /* Walk the list for the index'th entry, but + * stop when about to wrap. */ + unifi_trace(card->ospriv, UDBG6, + "%d: %d, @%p, p=%p, n=%p, cr=%p, h=%p\n", + i, find_dump->count, find_dump, find_dump->prev, + find_dump->next, card->dump_cur_read, card->dump_buf); + if (find_dump->prev == card->dump_cur_read) + { + /* Wrapped but still not found, index out of range */ + if (i != req->index) + { + unifi_trace(card->ospriv, UDBG6, + "Dump index %d not found %d\n", req->index, i); + r = CSR_WIFI_HIP_RESULT_NOT_FOUND; + goto done; + } + break; + } + } + break; + } + + /* Check if the slot is actually filled with a core dump */ + if (find_dump->count == 0) + { + unifi_trace(card->ospriv, UDBG4, "Not captured %d\n", req->index); + r = CSR_WIFI_HIP_RESULT_NOT_FOUND; + goto done; + } + + unifi_trace(card->ospriv, UDBG6, "Req index %d, found seq %d at step %d\n", + req->index, find_dump->count, i); + + /* Find the appropriate entry in the buffer */ + req->value = get_value_from_coredump(find_dump, req->space, (CsrUint16)req->offset); + if (req->value < 0) + { + r = CSR_WIFI_HIP_RESULT_RANGE; /* Un-captured register */ + unifi_trace(card->ospriv, UDBG4, + "Can't read space %d, reg 0x%x from coredump buffer %d\n", + req->space, req->offset, req->index); + } + else + { + r = CSR_RESULT_SUCCESS; + } + + /* Update the private request structure with the found values */ + req->chip_ver = find_dump->chip_ver; + req->fw_ver = find_dump->fw_ver; + req->timestamp = find_dump->timestamp; + req->requestor = find_dump->requestor; + req->serial = find_dump->count; + +done: + func_exit_r(r); + return r; +} /* unifi_coredump_get_value() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_read_zone + * + * Captures a UniFi memory zone into a buffer on the host + * + * Arguments: + * card Pointer to card struct + * zonebuf Pointer to on-host buffer to dump the memory zone into + * def Pointer to description of the memory zone to read from UniFi. + * + * Returns: + * CSR_RESULT_SUCCESS on success, or: + * CSR_RESULT_FAILURE SDIO error + * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error + * + * Notes: + * It is assumed that the caller has already stopped the XAPs + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_coredump_read_zone(card_t *card, CsrUint16 *zonebuf, const struct coredump_zone *def) +{ + CsrResult r; + + func_enter(); + + if (zonebuf == NULL || def == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + goto done; + } + + /* Select XAP CPU if necessary */ + if (def->cpu != UNIFI_PROC_INVALID) + { + if (def->cpu != UNIFI_PROC_MAC && def->cpu != UNIFI_PROC_PHY) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + goto done; + } + r = unifi_set_proc_select(card, def->cpu); + if (r != CSR_RESULT_SUCCESS) + { + goto done; + } + } + + unifi_trace(card->ospriv, UDBG4, + "Dump sp %d, offs 0x%04x, 0x%04x words @GP=%08x CPU %d\n", + def->space, def->offset, def->length, def->gp, def->cpu); + + /* Read on-chip RAM (byte-wise) */ + r = unifi_card_readn(card, def->gp, zonebuf, (CsrUint16)(def->length * 2)); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + goto done; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Can't read UniFi shared data area\n"); + goto done; + } + +done: + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_read_zones + * + * Walks through the table of on-chip memory zones defined in zonedef_table, + * and reads each of them from the UniFi chip + * + * Arguments: + * card Pointer to card struct + * dump_buf Buffer into which register values will be dumped + * + * Returns: + * CSR_RESULT_SUCCESS on success, or: + * CSR_RESULT_FAILURE SDIO error + * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error + * + * Notes: + * It is assumed that the caller has already stopped the XAPs + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_buf) +{ + CsrResult r = CSR_RESULT_SUCCESS; + CsrInt32 i; + + func_enter(); + + /* Walk the table of coredump zone definitions and read them from the chip */ + for (i = 0; + (i < HIP_CDUMP_NUM_ZONES) && (r == 0); + i++) + { + r = unifi_coredump_read_zone(card, dump_buf->zone[i], &zonedef_table[i]); + } + + func_exit_r(r); + return r; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_from_sdio + * + * Capture the status of the UniFi processors, over SDIO + * + * Arguments: + * card Pointer to card struct + * reg_buffer Buffer into which register values will be dumped + * + * Returns: + * CSR_RESULT_SUCCESS on success, or: + * CSR_RESULT_FAILURE SDIO error + * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error + * + * Notes: + * --------------------------------------------------------------------------- + */ +static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_buf) +{ + CsrUint16 val; + CsrResult r; + CsrUint32 sdio_addr; + + func_enter(); + + if (dump_buf == NULL) + { + r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; + goto done; + } + + + /* Chip and firmware version */ + unifi_trace(card->ospriv, UDBG4, "Get chip version\n"); + sdio_addr = 2 * ChipHelper_GBL_CHIP_VERSION(card->helper); + if (sdio_addr != 0) + { + r = unifi_read_direct16(card, sdio_addr, &val); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + goto done; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Can't read GBL_CHIP_VERSION\n"); + goto done; + } + } + dump_buf->chip_ver = val; + dump_buf->fw_ver = card->build_id; + + unifi_trace(card->ospriv, UDBG4, "chip_ver 0x%04x, fw_ver %u\n", + dump_buf->chip_ver, dump_buf->fw_ver); + + /* Capture the memory zones required from UniFi */ + r = unifi_coredump_read_zones(card, dump_buf); + if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) + { + goto done; + } + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "Can't read UniFi memory areas\n"); + goto done; + } + +done: + func_exit_r(r); + return r; +} /* unifi_coredump_from_sdio() */ + + +#ifndef UNIFI_DISABLE_COREDUMP +/* + * --------------------------------------------------------------------------- + * new_coredump_node + * + * Allocates a coredump linked-list node, and links it to the previous. + * + * Arguments: + * ospriv OS context + * prevnode Previous node to link into + * + * Returns: + * Pointer to valid coredump_buffer on success + * NULL on memory allocation failure + * + * Notes: + * Allocates "all or nothing" + * --------------------------------------------------------------------------- + */ +static +coredump_buffer* new_coredump_node(void *ospriv, coredump_buffer *prevnode) +{ + coredump_buffer *newnode = NULL; + CsrUint16 *newzone = NULL; + CsrInt32 i; + CsrUint32 zone_size; + + /* Allocate node header */ + newnode = (coredump_buffer *)CsrMemAlloc(sizeof(coredump_buffer)); + if (newnode == NULL) + { + return NULL; + } + CsrMemSet(newnode, 0, sizeof(coredump_buffer)); + + /* Allocate chip memory zone capture buffers */ + for (i = 0; i < HIP_CDUMP_NUM_ZONES; i++) + { + zone_size = sizeof(CsrUint16) * zonedef_table[i].length; + newzone = (CsrUint16 *)CsrMemAlloc(zone_size); + newnode->zone[i] = newzone; + if (newzone != NULL) + { + CsrMemSet(newzone, 0, zone_size); + } + else + { + unifi_error(ospriv, "Out of memory on coredump zone %d (%d words)\n", + i, zonedef_table[i].length); + break; + } + } + + /* Clean up if any zone alloc failed */ + if (newzone == NULL) + { + for (i = 0; newnode->zone[i] != NULL; i++) + { + CsrMemFree(newnode->zone[i]); + newnode->zone[i] = NULL; + } + } + + /* Link to previous node */ + newnode->prev = prevnode; + if (prevnode) + { + prevnode->next = newnode; + } + newnode->next = NULL; + + return newnode; +} + + +#endif /* UNIFI_DISABLE_COREDUMP */ + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_init + * + * Allocates buffers for the automatic SDIO core dump + * + * Arguments: + * card Pointer to card struct + * num_dump_buffers Number of buffers to reserve for coredumps + * + * Returns: + * CSR_RESULT_SUCCESS on success, or: + * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed + * + * Notes: + * Allocates space in advance, to be used for the last n coredump buffers + * the intention being that the size is sufficient for at least one dump, + * probably several. + * It's probably advisable to have at least 2 coredump buffers to allow + * one to be enquired with the unifi_coredump tool, while leaving another + * free for capturing. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_coredump_init(card_t *card, CsrUint16 num_dump_buffers) +{ +#ifndef UNIFI_DISABLE_COREDUMP + void *ospriv = card->ospriv; + coredump_buffer *prev = NULL; + coredump_buffer *newnode = NULL; + CsrUint32 i = 0; +#endif + + func_enter(); + + card->request_coredump_on_reset = 0; + card->dump_next_write = NULL; + card->dump_cur_read = NULL; + card->dump_buf = NULL; + +#ifndef UNIFI_DISABLE_COREDUMP + unifi_trace(ospriv, UDBG1, + "Allocate buffers for %d core dumps\n", num_dump_buffers); + if (num_dump_buffers == 0) + { + goto done; + } + + /* Root node */ + card->dump_buf = new_coredump_node(ospriv, NULL); + if (card->dump_buf == NULL) + { + goto fail; + } + prev = card->dump_buf; + newnode = card->dump_buf; + + /* Add each subsequent node at tail */ + for (i = 1; i < num_dump_buffers; i++) + { + newnode = new_coredump_node(ospriv, prev); + if (newnode == NULL) + { + goto fail; + } + prev = newnode; + } + + /* Link the first and last nodes to make the list circular */ + card->dump_buf->prev = newnode; + newnode->next = card->dump_buf; + + /* Set initial r/w access pointers */ + card->dump_next_write = card->dump_buf; + card->dump_cur_read = NULL; + + unifi_trace(ospriv, UDBG2, "Core dump configured (%d dumps max)\n", i); + +done: +#endif + func_exit(); + return CSR_RESULT_SUCCESS; + +#ifndef UNIFI_DISABLE_COREDUMP +fail: + /* Unwind what we allocated so far */ + unifi_error(ospriv, "Out of memory allocating core dump node %d\n", i); + unifi_coredump_free(card); + func_exit(); + return CSR_WIFI_HIP_RESULT_NO_MEMORY; +#endif +} /* unifi_coreump_init() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_coredump_free + * + * Free all memory dynamically allocated for core dump + * + * Arguments: + * card Pointer to card struct + * + * Returns: + * None + * + * Notes: + * --------------------------------------------------------------------------- + */ +void unifi_coredump_free(card_t *card) +{ + void *ospriv = card->ospriv; + coredump_buffer *node, *del_node; + CsrInt16 i = 0; + CsrInt16 j; + + func_enter(); + unifi_trace(ospriv, UDBG2, "Core dump de-configured\n"); + + if (card->dump_buf == NULL) + { + return; + } + + node = card->dump_buf; + do + { + /* Free payload zones */ + for (j = 0; j < HIP_CDUMP_NUM_ZONES; j++) + { + if (node->zone[j] != NULL) + { + CsrMemFree(node->zone[j]); + node->zone[j] = NULL; + } + } + + /* Detach */ + del_node = node; + node = node->next; + + /* Free header */ + CsrMemFree(del_node); + i++; + } while ((node != NULL) && (node != card->dump_buf)); + + unifi_trace(ospriv, UDBG3, "Freed %d coredump buffers\n", i); + + card->dump_buf = NULL; + card->dump_next_write = NULL; + card->dump_cur_read = NULL; + + func_exit(); +} /* unifi_coredump_free() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_packing.c b/drivers/staging/csr/csr_wifi_hip_packing.c new file mode 100644 index 000000000000..4e98da976668 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_packing.c @@ -0,0 +1,4804 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_wifi_hip_signals.h" +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" + + +/* + * --------------------------------------------------------------------------- + * get_packed_struct_size + * + * Examine a buffer containing a UniFi signal in wire-format. + * The first two bytes contain the signal ID, decode the signal ID and + * return the size, in bytes, of the signal, not including any bulk + * data. + * + * WARNING: This function is auto-generated, DO NOT EDIT! + * + * Arguments: + * buf Pointer to buffer to decode. + * + * Returns: + * 0 if the signal ID is not recognised (i.e. zero length), + * otherwise the number of bytes occupied by the signal in the buffer. + * This is useful for stepping past the signal to the object in the buffer. + * --------------------------------------------------------------------------- + */ +CsrInt32 get_packed_struct_size(const CsrUint8 *buf) +{ + CsrInt32 size = 0; + CsrUint16 sig_id; + + sig_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(buf); + + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + switch (sig_id) + { +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_WORD16_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; + case CSR_DEBUG_GENERIC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT64; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; + case CSR_MLME_SET_TIM_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif + case CSR_DEBUG_GENERIC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_MLME_SET_TIM_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_GENERIC_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT32; + size += SIZEOF_UINT32; + size += 48 / 8; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 32 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_ERROR_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + size += SIZEOF_UINT32; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += 48 / 8; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + size += SIZEOF_UINT16; + break; +#endif + default: + size = 0; + } + return size; +} /* get_packed_struct_size() */ + + +/* + * --------------------------------------------------------------------------- + * read_unpack_signal + * + * Unpack a wire-format signal into a host-native structure. + * This function handles any necessary conversions for endianness and + * places no restrictions on packing or alignment for the structure + * definition. + * + * WARNING: This function is auto-generated, DO NOT EDIT! + * + * Arguments: + * ptr Signal buffer to unpack. + * sig Pointer to destination structure to populate. + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the ID of signal was not recognised. + * --------------------------------------------------------------------------- + */ +CsrResult read_unpack_signal(const CsrUint8 *ptr, CSR_SIGNAL *sig) +{ + CsrInt32 index = 0; + + sig->SignalPrimitiveHeader.SignalId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + + sig->SignalPrimitiveHeader.ReceiverProcessId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + + sig->SignalPrimitiveHeader.SenderProcessId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + + switch (sig->SignalPrimitiveHeader.SignalId) + { +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + sig->u.MlmeSetkeysConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + sig->u.MlmeConfigQueueConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + sig->u.MlmeAddBlackoutConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + sig->u.MlmeDelBlackoutRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutRequest.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + sig->u.MlmeSmStartConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + sig->u.MlmeStopAggregationConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeStopAggregationConfirm.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeStopAggregationConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + sig->u.MlmeDelTspecRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_WORD16_INDICATION_ID: + sig->u.DebugWord16Indication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[8] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[9] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[10] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[11] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[12] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[13] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[14] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugWord16Indication.DebugWords[15] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_DEBUG_GENERIC_CONFIRM_ID: + sig->u.DebugGenericConfirm.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericConfirm.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_INDICATION_ID: + sig->u.MaPacketIndication.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MaPacketIndication.LocalTime.x, &ptr[index], 64 / 8); + index += 64 / 8; + sig->u.MaPacketIndication.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.ReceptionStatus = (CSR_RECEPTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Rssi = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.Snr = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketIndication.ReceivedRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MLME_SET_TIM_REQUEST_ID: + sig->u.MlmeSetTimRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.AssociationId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimRequest.TimValue = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + sig->u.MlmeConnectedIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectedIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectedIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectedIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectedIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectedIndication.ConnectionStatus = (CSR_CONNECTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeConnectedIndication.PeerMacAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + sig->u.MlmeDelRxTriggerRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerRequest.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + sig->u.MlmeTriggeredGetIndication.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeTriggeredGetIndication.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + sig->u.MlmeScanRequest.ChannelList.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.ChannelList.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.ScanType = (CSR_SCAN_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.ProbeDelay = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeScanRequest.MinChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanRequest.MaxChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + sig->u.MlmeDeletekeysConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + sig->u.MlmeGetNextRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + sig->u.MlmeSetChannelConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + sig->u.MlmeStartAggregationRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeStartAggregationRequest.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeStartAggregationRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.StartingSequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.BufferSize = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationRequest.BlockAckTimeout = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + sig->u.MlmeHlSyncRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeHlSyncRequest.GroupAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif + case CSR_DEBUG_GENERIC_REQUEST_ID: + sig->u.DebugGenericRequest.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericRequest.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + sig->u.MlmeLeaveConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetRequest.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + sig->u.MlmeAddMulticastAddressRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressRequest.NumberOfMulticastGroupAddresses = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + sig->u.MlmeResetRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeResetRequest.StaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeResetRequest.SetDefaultMib = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + sig->u.MlmeScanCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanCancelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetConfirm.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + sig->u.MlmeSetPacketFilterRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.PacketFilterMode = (CSR_PACKET_FILTER_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetPacketFilterRequest.ArpFilterAddress = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelRxTriggerConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + sig->u.MlmeConnectStatusRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.ConnectionStatus = (CSR_CONNECTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeConnectStatusRequest.StaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeConnectStatusRequest.AssociationId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusRequest.AssociationCapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + sig->u.MlmeLeaveRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeLeaveRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + sig->u.MlmeConfigQueueRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.QueueIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Aifs = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Cwmin = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.Cwmax = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConfigQueueRequest.TxopLimit = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + sig->u.MlmeDelTspecConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTspecConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MLME_SET_TIM_CONFIRM_ID: + sig->u.MlmeSetTimConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetTimConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + sig->u.MlmeMeasureIndication.MeasurementReportSet.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureIndication.MeasurementReportSet.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureIndication.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + sig->u.MlmeDelBlackoutConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelBlackoutConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelTriggeredGetConfirm.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_GENERIC_INDICATION_ID: + sig->u.DebugGenericIndication.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugGenericIndication.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + sig->u.MaPacketCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketCancelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketCancelRequest.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_REQUEST_ID: + sig->u.MaPacketRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.TransmitRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketRequest.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MaPacketRequest.Priority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MaPacketRequest.Ra.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MaPacketRequest.TransmissionControl = (CSR_TRANSMISSION_CONTROL) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + sig->u.MlmeModifyBssParameterRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.BeaconPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.DtimPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeModifyBssParameterRequest.CapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeModifyBssParameterRequest.Bssid.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeModifyBssParameterRequest.RtsThreshold = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + sig->u.MlmeAddRxTriggerRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerRequest.Priority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + sig->u.MaVifAvailabilityIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityIndication.Multicast = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + sig->u.MlmeHlSyncCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeHlSyncCancelRequest.GroupAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + sig->u.MlmeBlackoutEndedIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlackoutEndedIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlackoutEndedIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlackoutEndedIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlackoutEndedIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlackoutEndedIndication.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanDoneIndication.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + sig->u.MlmeGetKeySequenceRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetKeySequenceRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeGetKeySequenceRequest.Address.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + sig->u.MlmeSetChannelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeSetChannelRequest.Address.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeSetChannelRequest.AvailabilityDuration = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetChannelRequest.AvailabilityInterval = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + sig->u.MlmeMeasureConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureConfirm.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + sig->u.MlmeAddTriggeredGetRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTriggeredGetRequest.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAutonomousScanLossIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeAutonomousScanLossIndication.Bssid.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + sig->u.MaVifAvailabilityResponse.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityResponse.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityResponse.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityResponse.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityResponse.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaVifAvailabilityResponse.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + sig->u.MlmeAddTemplateRequest.Data1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.Data1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.Data2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.Data2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.FrameType = (CSR_FRAME_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateRequest.MinTransmitRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + sig->u.MlmePowermgtConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + sig->u.MlmeAddPeriodicConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + sig->u.MlmeGetConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + sig->u.MlmeGetNextConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetNextConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + sig->u.MlmeStopAggregationRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeStopAggregationRequest.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeStopAggregationRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopAggregationRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddRxTriggerConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + sig->u.MlmeAddBlackoutRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.BlackoutType = (CSR_BLACKOUT_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.BlackoutSource = (CSR_BLACKOUT_SOURCE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddBlackoutRequest.BlackoutStartReference = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddBlackoutRequest.BlackoutPeriod = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddBlackoutRequest.BlackoutDuration = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + CsrMemCpy(sig->u.MlmeAddBlackoutRequest.PeerStaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeAddBlackoutRequest.BlackoutCount = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + sig->u.MlmeDeletekeysRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDeletekeysRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeDeletekeysRequest.Address.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + sig->u.MlmeResetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeResetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + sig->u.MlmeHlSyncConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeHlSyncConfirm.GroupAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeHlSyncConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + sig->u.MlmeAddAutonomousScanRequest.ChannelList.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.ChannelList.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.ChannelStartingFactor = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.ScanType = (CSR_SCAN_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.ProbeDelay = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddAutonomousScanRequest.MinChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddAutonomousScanRequest.MaxChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + sig->u.MlmeSetRequest.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetRequest.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + sig->u.MlmeSmStartRequest.Beacon.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.Beacon.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.BssParameters.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.BssParameters.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeSmStartRequest.InterfaceAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + CsrMemCpy(sig->u.MlmeSmStartRequest.Bssid.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeSmStartRequest.BeaconPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.DtimPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSmStartRequest.CapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + sig->u.MlmeConnectStatusConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeConnectStatusConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + sig->u.MlmeDelPeriodicRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicRequest.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + sig->u.MlmeSetkeysRequest.Key.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.Key.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.Length = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeSetkeysRequest.Address.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeSetkeysRequest.SequenceNumber[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetkeysRequest.SequenceNumber[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(&sig->u.MlmeSetkeysRequest.CipherSuiteSelector, &ptr[index], 32 / 8); + index += 32 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePauseAutonomousScanRequest.Pause = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + sig->u.MlmeGetRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + sig->u.MlmePowermgtRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.PowerManagementMode = (CSR_POWER_MANAGEMENT_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.ReceiveDtims = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.ListenInterval = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmePowermgtRequest.TrafficWindow = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_ERROR_INDICATION_ID: + sig->u.MaPacketErrorIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketErrorIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketErrorIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketErrorIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketErrorIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MaPacketErrorIndication.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MaPacketErrorIndication.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketErrorIndication.SequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + sig->u.MlmeAddPeriodicRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.MaximumLatency = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddPeriodicRequest.PeriodicSchedulingMode = (CSR_PERIODIC_SCHEDULING_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.WakeHost = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddPeriodicRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + sig->u.MlmeAddTspecRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.PsScheme = (CSR_PS_SCHEME) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.MediumTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecRequest.ServiceStartTime = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddTspecRequest.ServiceInterval = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + sig->u.MlmeAddTspecRequest.MinimumDataRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddMulticastAddressConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + sig->u.MlmeAddTspecConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTspecConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeHlSyncCancelConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + sig->u.MlmeScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + sig->u.DebugStringIndication.DebugMessage.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugStringIndication.DebugMessage.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugStringIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.DebugStringIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + sig->u.MlmeAddTemplateConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.FrameType = (CSR_FRAME_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeAddTemplateConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + sig->u.MlmeBlockackErrorIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlockackErrorIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlockackErrorIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlockackErrorIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlockackErrorIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeBlockackErrorIndication.ResultCode = (CSR_REASON_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeBlockackErrorIndication.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + sig->u.MlmeSetConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeSetConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + sig->u.MlmeMeasureRequest.MeasurementRequestSet.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureRequest.MeasurementRequestSet.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeMeasureRequest.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + sig->u.MlmeStartAggregationConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(sig->u.MlmeStartAggregationConfirm.PeerQstaAddress.x, &ptr[index], 48 / 8); + index += 48 / 8; + sig->u.MlmeStartAggregationConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStartAggregationConfirm.SequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + sig->u.MlmeStopMeasureConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureConfirm.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_CONFIRM_ID: + sig->u.MaPacketConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.TransmissionStatus = (CSR_TRANSMISSION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.RetryCount = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.Rate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MaPacketConfirm.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + sig->u.MlmeDelPeriodicConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeDelPeriodicConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + sig->u.MlmeStopMeasureRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + sig->u.MlmeStopMeasureRequest.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); + index += SIZEOF_UINT16; + break; +#endif + + default: + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + return CSR_RESULT_SUCCESS; +} /* read_unpack_signal() */ + + +/* + * --------------------------------------------------------------------------- + * write_pack + * + * Convert a signal structure, in host-native format, to the + * little-endian wire format specified in the UniFi Host Interface + * Protocol Specification. + * + * WARNING: This function is auto-generated, DO NOT EDIT! + * + * Arguments: + * sig Pointer to signal structure to pack. + * ptr Destination buffer to pack into. + * sig_len Returns the length of the packed signal, i.e. the + * number of bytes written to ptr. + * + * Returns: + * CSR_RESULT_SUCCESS on success, + * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the ID of signal was not recognised. + * --------------------------------------------------------------------------- + */ +CsrResult write_pack(const CSR_SIGNAL *sig, CsrUint8 *ptr, CsrUint16 *sig_len) +{ + CsrInt16 index = 0; + + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.SignalId, ptr + index); + index += SIZEOF_UINT16; + + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.ReceiverProcessId, ptr + index); + index += SIZEOF_UINT16; + + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.SenderProcessId, ptr + index); + index += SIZEOF_UINT16; + + switch (sig->SignalPrimitiveHeader.SignalId) + { +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.BlackoutId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.BlackoutId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[7], ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeStopAggregationConfirm.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Direction, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Direction, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_WORD16_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[7], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[8], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[9], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[10], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[11], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[12], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[13], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[14], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[15], ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_DEBUG_GENERIC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugVariable.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugVariable.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[7], ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Data.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Data.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MaPacketIndication.LocalTime.x, 64 / 8); + index += 64 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Ifindex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Channel, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.ReceptionStatus, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Rssi, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Snr, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.ReceivedRate, ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MLME_SET_TIM_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.AssociationId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.TimValue, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.ConnectionStatus, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeConnectedIndication.PeerMacAddress.x, 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.TriggerId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.MibAttributeValue.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.MibAttributeValue.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Status, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.ErrorIndex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.TriggeredId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ChannelList.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ChannelList.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.InformationElements.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.InformationElements.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.Ifindex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ScanType, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ProbeDelay, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.MinChannelTime, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.MaxChannelTime, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.MibAttribute.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.MibAttribute.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeStartAggregationRequest.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Direction, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.StartingSequenceNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.BufferSize, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.BlockAckTimeout, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeHlSyncRequest.GroupAddress.x, 48 / 8); + index += 48 / 8; + break; +#endif + case CSR_DEBUG_GENERIC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugVariable.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugVariable.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[7], ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.TriggeredId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Data.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Data.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.NumberOfMulticastGroupAddresses, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeResetRequest.StaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.SetDefaultMib, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.TriggeredId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.InformationElements.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.InformationElements.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.PacketFilterMode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.ArpFilterAddress, ptr + index); + index += SIZEOF_UINT32; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.TriggerId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.InformationElements.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.InformationElements.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.ConnectionStatus, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeConnectStatusRequest.StaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.AssociationId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.AssociationCapabilityInformation, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.QueueIndex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Aifs, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Cwmin, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Cwmax, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.TxopLimit, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MLME_SET_TIM_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.MeasurementReportSet.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.MeasurementReportSet.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.DialogToken, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.BlackoutId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.TriggeredId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_GENERIC_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugVariable.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugVariable.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[7], ptr + index); + index += SIZEOF_UINT16; + break; + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.HostTag, ptr + index); + index += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Data.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Data.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.TransmitRate, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.HostTag, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Priority, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MaPacketRequest.Ra.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.TransmissionControl, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Data.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Data.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.BeaconPeriod, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.DtimPeriod, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.CapabilityInformation, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeModifyBssParameterRequest.Bssid.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.RtsThreshold, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.InformationElements.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.InformationElements.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.TriggerId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Priority, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Multicast, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeHlSyncCancelRequest.GroupAddress.x, 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.BlackoutId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.KeyId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.KeyType, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeGetKeySequenceRequest.Address.x, 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Ifindex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Channel, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeSetChannelRequest.Address.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.AvailabilityDuration, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.AvailabilityInterval, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.DialogToken, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.MibAttribute.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.MibAttribute.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.TriggeredId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeAutonomousScanLossIndication.Bssid.x, 48 / 8); + index += 48 / 8; + break; +#endif + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.FrameType, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.MinTransmitRate, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.PeriodicId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.MibAttributeValue.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.MibAttributeValue.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Status, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.ErrorIndex, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.MibAttributeValue.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.MibAttributeValue.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Status, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.ErrorIndex, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeStopAggregationRequest.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Direction, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.TriggerId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutType, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutSource, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutStartReference, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutPeriod, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutDuration, ptr + index); + index += SIZEOF_UINT32; + CsrMemCpy(ptr + index, sig->u.MlmeAddBlackoutRequest.PeerStaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutCount, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.KeyId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.KeyType, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeDeletekeysRequest.Address.x, 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeHlSyncConfirm.GroupAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelList.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelList.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.InformationElements.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.InformationElements.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.Ifindex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelStartingFactor, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ScanType, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ProbeDelay, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.MinChannelTime, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.MaxChannelTime, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.MibAttributeValue.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.MibAttributeValue.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Beacon.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Beacon.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BssParameters.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BssParameters.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Ifindex, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Channel, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeSmStartRequest.InterfaceAddress.x, 48 / 8); + index += 48 / 8; + CsrMemCpy(ptr + index, sig->u.MlmeSmStartRequest.Bssid.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BeaconPeriod, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.DtimPeriod, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.CapabilityInformation, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.PeriodicId, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Key.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Key.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Length, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.KeyId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.KeyType, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeSetkeysRequest.Address.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[0], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[1], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[2], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[3], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[4], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[5], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[6], ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[7], ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, &sig->u.MlmeSetkeysRequest.CipherSuiteSelector, 32 / 8); + index += 32 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.AutonomousScanId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Pause, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.MibAttribute.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.MibAttribute.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.PowerManagementMode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.ReceiveDtims, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.ListenInterval, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.TrafficWindow, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_ERROR_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MaPacketErrorIndication.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.SequenceNumber, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.PeriodicId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.MaximumLatency, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.PeriodicSchedulingMode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.WakeHost, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.UserPriority, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Direction, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.PsScheme, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.MediumTime, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.ServiceStartTime, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.ServiceInterval, ptr + index); + index += SIZEOF_UINT32; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.MinimumDataRate, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.DebugMessage.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.DebugMessage.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.FrameType, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeBlockackErrorIndication.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.MibAttributeValue.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.MibAttributeValue.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Status, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.ErrorIndex, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.MeasurementRequestSet.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.MeasurementRequestSet.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.DialogToken, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CsrMemCpy(ptr + index, sig->u.MlmeStartAggregationConfirm.PeerQstaAddress.x, 48 / 8); + index += 48 / 8; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.UserPriority, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Direction, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.SequenceNumber, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.DialogToken, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + case CSR_MA_PACKET_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.TransmissionStatus, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.RetryCount, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Rate, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.HostTag, ptr + index); + index += SIZEOF_UINT32; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.VirtualInterfaceIdentifier, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.PeriodicId, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.ResultCode, ptr + index); + index += SIZEOF_UINT16; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref1.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref1.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref2.SlotNumber, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref2.DataLength, ptr + index); + index += SIZEOF_UINT16; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.DialogToken, ptr + index); + index += SIZEOF_UINT16; + break; +#endif + + default: + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + *sig_len = index; + + return CSR_RESULT_SUCCESS; +} /* write_pack() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_send.c b/drivers/staging/csr/csr_wifi_hip_send.c new file mode 100644 index 000000000000..624f3bb37129 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_send.c @@ -0,0 +1,422 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * *************************************************************************** + * + * FILE: csr_wifi_hip_send.c + * + * PURPOSE: + * Code for adding a signal request to the from-host queue. + * When the driver bottom-half is run, it will take requests from the + * queue and pass them to the UniFi. + * + * *************************************************************************** + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "csr_wifi_hip_sigs.h" +#include "csr_wifi_hip_card.h" + +unifi_TrafficQueue unifi_frame_priority_to_queue(CSR_PRIORITY priority) +{ + switch (priority) + { + case CSR_QOS_UP0: + case CSR_QOS_UP3: + return UNIFI_TRAFFIC_Q_BE; + case CSR_QOS_UP1: + case CSR_QOS_UP2: + return UNIFI_TRAFFIC_Q_BK; + case CSR_QOS_UP4: + case CSR_QOS_UP5: + return UNIFI_TRAFFIC_Q_VI; + case CSR_QOS_UP6: + case CSR_QOS_UP7: + case CSR_MANAGEMENT: + return UNIFI_TRAFFIC_Q_VO; + default: + return UNIFI_TRAFFIC_Q_BE; + } +} + + +CSR_PRIORITY unifi_get_default_downgrade_priority(unifi_TrafficQueue queue) +{ + switch (queue) + { + case UNIFI_TRAFFIC_Q_BE: + return CSR_QOS_UP0; + case UNIFI_TRAFFIC_Q_BK: + return CSR_QOS_UP1; + case UNIFI_TRAFFIC_Q_VI: + return CSR_QOS_UP5; + case UNIFI_TRAFFIC_Q_VO: + return CSR_QOS_UP6; + default: + return CSR_QOS_UP0; + } +} + + +/* + * --------------------------------------------------------------------------- + * send_signal + * + * This function queues a signal for sending to UniFi. It first checks + * that there is space on the fh_signal_queue for another entry, then + * claims any bulk data slots required and copies data into them. Then + * increments the fh_signal_queue write count. + * + * The fh_signal_queue is later processed by the driver bottom half + * (in unifi_bh()). + * + * This function call unifi_pause_xmit() to pause the flow of data plane + * packets when: + * - the fh_signal_queue ring buffer is full + * - there are less than UNIFI_MAX_DATA_REFERENCES (2) bulk data + * slots available. + * + * Arguments: + * card Pointer to card context structure + * sigptr Pointer to the signal to write to UniFi. + * siglen Number of bytes pointer to by sigptr. + * bulkdata Array of pointers to an associated bulk data. + * sigq To which from-host queue to add the signal. + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or + * no free signal queue entry + * + * Notes: + * Calls unifi_pause_xmit() when the last slots are used. + * --------------------------------------------------------------------------- + */ +static CsrResult send_signal(card_t *card, const CsrUint8 *sigptr, CsrUint32 siglen, + const bulk_data_param_t *bulkdata, + q_t *sigq, CsrUint32 priority_q, CsrUint32 run_bh) +{ + CsrUint16 i, data_slot_size; + card_signal_t *csptr; + CsrInt16 qe; + CsrResult r; + CsrInt16 debug_print = 0; + + data_slot_size = CardGetDataSlotSize(card); + + /* Check that the fh_data_queue has a free slot */ + if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sigq)) + { + unifi_trace(card->ospriv, UDBG3, "send_signal: %s full\n", sigq->name); + + return CSR_WIFI_HIP_RESULT_NO_SPACE; + } + + /* + * Now add the signal to the From Host signal queue + */ + /* Get next slot on queue */ + qe = CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq); + csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, qe); + + /* Make up the card_signal struct */ + csptr->signal_length = (CsrUint16)siglen; + CsrMemCpy((void *)csptr->sigbuf, (void *)sigptr, siglen); + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) + { + if ((bulkdata != NULL) && (bulkdata->d[i].data_length != 0)) + { + CsrUint32 datalen = bulkdata->d[i].data_length; + + /* Make sure data will fit in a bulk data slot */ + if (bulkdata->d[i].os_data_ptr == NULL) + { + unifi_error(card->ospriv, "send_signal - NULL bulkdata[%d]\n", i); + debug_print++; + csptr->bulkdata[i].data_length = 0; + } + else + { + if (datalen > data_slot_size) + { + unifi_error(card->ospriv, + "send_signal - Invalid data length %u (@%p), " + "truncating\n", + datalen, bulkdata->d[i].os_data_ptr); + datalen = data_slot_size; + debug_print++; + } + /* Store the bulk data info in the soft queue. */ + csptr->bulkdata[i].os_data_ptr = (CsrUint8 *)bulkdata->d[i].os_data_ptr; + csptr->bulkdata[i].os_net_buf_ptr = (CsrUint8 *)bulkdata->d[i].os_net_buf_ptr; + csptr->bulkdata[i].net_buf_length = bulkdata->d[i].net_buf_length; + csptr->bulkdata[i].data_length = datalen; + } + } + else + { + UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]); + } + } + + if (debug_print) + { + const CsrUint8 *sig = sigptr; + + unifi_error(card->ospriv, "Signal(%d): %02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + siglen, + sig[0], sig[1], sig[2], sig[3], + sig[4], sig[5], sig[6], sig[7], + sig[8], sig[9], sig[10], sig[11], + sig[12], sig[13], sig[14], sig[15]); + unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n", + bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL, + bulkdata != NULL?bulkdata->d[0].data_length : 0, + bulkdata != NULL?bulkdata->d[1].os_data_ptr : NULL, + bulkdata != NULL?bulkdata->d[1].data_length : 0); + } + + /* Advance the written count to say there is a new entry */ + CSR_WIFI_HIP_Q_INC_W(sigq); + + /* + * Set the flag to say reason for waking was a host request. + * Then ask the OS layer to run the unifi_bh. + */ + if (run_bh == 1) + { + card->bh_reason_host = 1; + r = unifi_run_bh(card->ospriv); + if (r != CSR_RESULT_SUCCESS) + { + unifi_error(card->ospriv, "failed to run bh.\n"); + card->bh_reason_host = 0; + + /* + * The bulk data buffer will be freed by the caller. + * We need to invalidate the description of the bulk data in our + * soft queue, to prevent the core freeing the bulk data again later. + */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) + { + if (csptr->bulkdata[i].data_length != 0) + { + csptr->bulkdata[i].os_data_ptr = csptr->bulkdata[i].os_net_buf_ptr = NULL; + csptr->bulkdata[i].net_buf_length = csptr->bulkdata[i].data_length = 0; + } + } + return r; + } + } + else + { + unifi_error(card->ospriv, "run_bh=%d, bh not called.\n", run_bh); + } + + /* + * Have we used up all the fh signal list entries? + */ + if (CSR_WIFI_HIP_Q_SLOTS_FREE(sigq) == 0) + { + /* We have filled the queue, so stop the upper layer. The command queue + * is an exception, as suspending due to that being full could delay + * resume/retry until new commands or data are received. + */ + if (sigq != &card->fh_command_queue) + { + /* + * Must call unifi_pause_xmit() *before* setting the paused flag. + * (the unifi_pause_xmit call should not be after setting the flag because of the possibility of being interrupted + * by the bh thread between our setting the flag and the call to unifi_pause_xmit() + * If bh thread then cleared the flag, we would end up paused, but without the flag set) + * Instead, setting it afterwards means that if this thread is interrupted by the bh thread + * the pause flag is still guaranteed to end up set + * However the potential deadlock now is that if bh thread emptied the queue and cleared the flag before this thread's + * call to unifi_pause_xmit(), then bh thread may not run again because it will be waiting for + * a packet to appear in the queue but nothing ever will because xmit is paused. + * So we will end up with the queue paused, and the flag set to say it is paused, but bh never runs to unpause it. + * (Note even this bad situation would not persist long in practice, because something else (eg rx, or tx in different queue) + * is likely to wake bh thread quite soon) + * But to avoid this deadlock completely, after setting the flag we check that there is something left in the queue. + * If there is, we know that bh thread has not emptied the queue yet. + * Since bh thread checks to unpause the queue *after* taking packets from the queue, we know that it is still going to make at + * least one more check to see whether it needs to unpause the queue. So all is well. + * If there are no packets in the queue, then the deadlock described above might happen. To make sure it does not, we + * unpause the queue here. A possible side effect is that unifi_restart_xmit() may (rarely) be called for second time + * unnecessarily, which is harmless + */ + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("P"); +#endif + unifi_pause_xmit(card->ospriv, (unifi_TrafficQueue)priority_q); + card_tx_q_pause(card, priority_q); + if (CSR_WIFI_HIP_Q_SLOTS_USED(sigq) == 0) + { + card_tx_q_unpause(card, priority_q); + unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue) priority_q); + } + } + else + { + unifi_warning(card->ospriv, + "send_signal: fh_cmd_q full, not pausing (run_bh=%d)\n", + run_bh); + } + } + + func_exit(); + + return CSR_RESULT_SUCCESS; +} /* send_signal() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_send_signal + * + * Invokes send_signal() to queue a signal in the command or traffic queue + * If sigptr pointer is NULL, it pokes the bh to check if UniFi is responsive. + * + * Arguments: + * card Pointer to card context struct + * sigptr Pointer to signal from card. + * siglen Size of the signal + * bulkdata Pointer to the bulk data of the signal + * + * Returns: + * CSR_RESULT_SUCCESS on success + * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or no free signal queue entry + * + * Notes: + * unifi_send_signal() is used to queue signals, created by the driver, + * to the device. Signals are constructed using the UniFi packed structures. + * --------------------------------------------------------------------------- + */ +CsrResult unifi_send_signal(card_t *card, const CsrUint8 *sigptr, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) +{ + q_t *sig_soft_q; + CsrUint16 signal_id; + CsrResult r; + CsrUint32 run_bh; + CsrUint32 priority_q; + + /* A NULL signal pointer is a request to check if UniFi is responsive */ + if (sigptr == NULL) + { + card->bh_reason_host = 1; + return unifi_run_bh(card->ospriv); + } + + priority_q = 0; + run_bh = 1; + signal_id = GET_SIGNAL_ID(sigptr); + /* + * If the signal is a CSR_MA_PACKET_REQUEST , + * we send it using the traffic soft queue. Else we use the command soft queue. + */ + if (signal_id == CSR_MA_PACKET_REQUEST_ID) + { + CsrUint16 frame_priority; + + if (card->periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_ENABLED) + { + run_bh = 0; + } + +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) + unifi_debug_log_to_buf("D"); +#endif + /* Sanity check: MA-PACKET.req must have a valid bulk data */ + if ((bulkdata->d[0].data_length == 0) || (bulkdata->d[0].os_data_ptr == NULL)) + { + unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n", + bulkdata->d[0].data_length, bulkdata->d[0].os_data_ptr); + dump((void *)sigptr, siglen); + return CSR_RESULT_FAILURE; + } + + /* Map the frame priority to a traffic queue index. */ + frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr); + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority); + + sig_soft_q = &card->fh_traffic_queue[priority_q]; + } + else + { + sig_soft_q = &card->fh_command_queue; + } + + r = send_signal(card, sigptr, siglen, bulkdata, sig_soft_q, priority_q, run_bh); + /* On error, the caller must free or requeue bulkdata buffers */ + + return r; +} /* unifi_send_signal() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_send_resources_available + * + * Examines whether there is available space to queue + * a signal in the command or traffic queue + * + * Arguments: + * card Pointer to card context struct + * sigptr Pointer to signal. + * + * Returns: + * CSR_RESULT_SUCCESS if resources available + * CSR_WIFI_HIP_RESULT_NO_SPACE if there was no free signal queue entry + * + * Notes: + * --------------------------------------------------------------------------- + */ +CsrResult unifi_send_resources_available(card_t *card, const CsrUint8 *sigptr) +{ + q_t *sig_soft_q; + CsrUint16 signal_id = GET_SIGNAL_ID(sigptr); + + /* + * If the signal is a CSR_MA_PACKET_REQUEST , + * we send it using the traffic soft queue. Else we use the command soft queue. + */ + if (signal_id == CSR_MA_PACKET_REQUEST_ID) + { + CsrUint16 frame_priority; + CsrUint32 priority_q; + + /* Map the frame priority to a traffic queue index. */ + frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr); + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority); + + sig_soft_q = &card->fh_traffic_queue[priority_q]; + } + else + { + sig_soft_q = &card->fh_command_queue; + } + + /* Check that the fh_data_queue has a free slot */ + if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sig_soft_q)) + { + unifi_notice(card->ospriv, "unifi_send_resources_available: %s full\n", + sig_soft_q->name); + return CSR_WIFI_HIP_RESULT_NO_SPACE; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_send_resources_available() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_signals.c b/drivers/staging/csr/csr_wifi_hip_signals.c new file mode 100644 index 000000000000..5d0be5397a4f --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_signals.c @@ -0,0 +1,1313 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + + +/* Generated by hip_dd_l_c_gen.pl */ + +#include "csr_wifi_hip_signals.h" + +#include "csr_wifi_hip_unifi.h" + +CsrInt32 SigGetSize(const CSR_SIGNAL *aSignal) +{ + switch (aSignal->SignalPrimitiveHeader.SignalId) + { + case CSR_MA_PACKET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_REQUEST); + case CSR_MA_PACKET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_CONFIRM); + case CSR_MA_PACKET_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_INDICATION); + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_CANCEL_REQUEST); + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_VIF_AVAILABILITY_RESPONSE); + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_VIF_AVAILABILITY_INDICATION); + case CSR_MA_PACKET_ERROR_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_ERROR_INDICATION); +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_RESET_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_RESET_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_NEXT_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_NEXT_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_POWERMGT_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_POWERMGT_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SETKEYS_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SETKEYS_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DELETEKEYS_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DELETEKEYS_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECTED_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_CANCEL_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CANCEL_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CANCEL_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_PERIODIC_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_PERIODIC_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_PERIODIC_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_PERIODIC_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_PACKET_FILTER_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_PACKET_FILTER_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_MEASURE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_MEASURE_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TRIGGERED_GET_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TRIGGERED_GET_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TRIGGERED_GET_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TRIGGERED_GET_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_TRIGGERED_GET_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_BLACKOUT_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_BLACKOUT_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_BLACKOUT_ENDED_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_BLACKOUT_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_BLACKOUT_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_RX_TRIGGER_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_RX_TRIGGER_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_RX_TRIGGER_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_RX_TRIGGER_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECT_STATUS_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECT_STATUS_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TEMPLATE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TEMPLATE_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONFIG_QUEUE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONFIG_QUEUE_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TSPEC_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TSPEC_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TSPEC_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TSPEC_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_START_AGGREGATION_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_START_AGGREGATION_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_BLOCKACK_ERROR_INDICATION); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_AGGREGATION_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_AGGREGATION_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SM_START_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SM_START_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_LEAVE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_LEAVE_CONFIRM); +#endif + case CSR_MLME_SET_TIM_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_TIM_REQUEST); + case CSR_MLME_SET_TIM_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_TIM_CONFIRM); +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_KEY_SEQUENCE_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_KEY_SEQUENCE_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CHANNEL_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CHANNEL_CONFIRM); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST); +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM); +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_STRING_INDICATION); + case CSR_DEBUG_WORD16_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_WORD16_INDICATION); + case CSR_DEBUG_GENERIC_REQUEST_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_REQUEST); + case CSR_DEBUG_GENERIC_CONFIRM_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_CONFIRM); + case CSR_DEBUG_GENERIC_INDICATION_ID: + return CsrOffsetOf(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_INDICATION); + default: + return 0; + } +} + + +CsrInt32 SigGetDataRefs(CSR_SIGNAL *aSignal, CSR_DATAREF **aDataRef) +{ + CsrInt32 numRefs = 0; + + switch (aSignal->SignalPrimitiveHeader.SignalId) + { + case CSR_MA_PACKET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MaPacketRequest.Data; + aDataRef[numRefs++] = &aSignal->u.MaPacketRequest.Dummydataref2; + break; + case CSR_MA_PACKET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MaPacketConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MaPacketConfirm.Dummydataref2; + break; + case CSR_MA_PACKET_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MaPacketIndication.Data; + aDataRef[numRefs++] = &aSignal->u.MaPacketIndication.Dummydataref2; + break; + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MaPacketCancelRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MaPacketCancelRequest.Dummydataref2; + break; + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityResponse.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityResponse.Dummydataref2; + break; + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityIndication.Dummydataref2; + break; + case CSR_MA_PACKET_ERROR_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MaPacketErrorIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MaPacketErrorIndication.Dummydataref2; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeResetRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeResetRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeResetConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeResetConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetRequest.MibAttribute; + aDataRef[numRefs++] = &aSignal->u.MlmeGetRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetConfirm.MibAttributeValue; + aDataRef[numRefs++] = &aSignal->u.MlmeGetConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetRequest.MibAttributeValue; + aDataRef[numRefs++] = &aSignal->u.MlmeSetRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetConfirm.MibAttributeValue; + aDataRef[numRefs++] = &aSignal->u.MlmeSetConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetNextRequest.MibAttribute; + aDataRef[numRefs++] = &aSignal->u.MlmeGetNextRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetNextConfirm.MibAttributeValue; + aDataRef[numRefs++] = &aSignal->u.MlmeGetNextConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmePowermgtRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmePowermgtRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmePowermgtConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmePowermgtConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeScanRequest.ChannelList; + aDataRef[numRefs++] = &aSignal->u.MlmeScanRequest.InformationElements; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeScanConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeScanConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureRequest.MeasurementRequestSet; + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureIndication.MeasurementReportSet; + aDataRef[numRefs++] = &aSignal->u.MlmeMeasureIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysRequest.Key; + aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanLossIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanLossIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeConnectedIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeConnectedIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeScanCancelRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeScanCancelRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanRequest.ChannelList; + aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanRequest.InformationElements; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterRequest.InformationElements; + aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanDoneIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanDoneIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetRequest.MibAttribute; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeTriggeredGetIndication.MibAttributeValue; + aDataRef[numRefs++] = &aSignal->u.MlmeTriggeredGetIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeBlackoutEndedIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeBlackoutEndedIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerRequest.InformationElements; + aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusRequest.InformationElements; + aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterRequest.Data; + aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateRequest.Data1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateRequest.Data2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeBlockackErrorIndication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeBlockackErrorIndication.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSmStartRequest.Beacon; + aDataRef[numRefs++] = &aSignal->u.MlmeSmStartRequest.BssParameters; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSmStartConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSmStartConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeLeaveRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeLeaveRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeLeaveConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeLeaveConfirm.Dummydataref2; + break; +#endif + case CSR_MLME_SET_TIM_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetTimRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetTimRequest.Dummydataref2; + break; + case CSR_MLME_SET_TIM_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetTimConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetTimConfirm.Dummydataref2; + break; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelRequest.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelConfirm.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressRequest.Data; + aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressRequest.Dummydataref2; + break; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressConfirm.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressConfirm.Dummydataref2; + break; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.DebugStringIndication.DebugMessage; + aDataRef[numRefs++] = &aSignal->u.DebugStringIndication.Dummydataref2; + break; + case CSR_DEBUG_WORD16_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.DebugWord16Indication.Dummydataref1; + aDataRef[numRefs++] = &aSignal->u.DebugWord16Indication.Dummydataref2; + break; + case CSR_DEBUG_GENERIC_REQUEST_ID: + aDataRef[numRefs++] = &aSignal->u.DebugGenericRequest.DebugVariable; + aDataRef[numRefs++] = &aSignal->u.DebugGenericRequest.Dummydataref2; + break; + case CSR_DEBUG_GENERIC_CONFIRM_ID: + aDataRef[numRefs++] = &aSignal->u.DebugGenericConfirm.DebugVariable; + aDataRef[numRefs++] = &aSignal->u.DebugGenericConfirm.Dummydataref2; + break; + case CSR_DEBUG_GENERIC_INDICATION_ID: + aDataRef[numRefs++] = &aSignal->u.DebugGenericIndication.DebugVariable; + aDataRef[numRefs++] = &aSignal->u.DebugGenericIndication.Dummydataref2; + break; + default: + return 0; + } + return numRefs; +} + + +CsrUint32 SigGetFilterPos(CsrUint16 aSigID) +{ + switch (aSigID) + { + case CSR_MA_PACKET_REQUEST_ID: + return 0x00000001; + case CSR_MA_PACKET_CONFIRM_ID: + return 0x00000002; + case CSR_MA_PACKET_INDICATION_ID: + return 0x00000004; + case CSR_MA_PACKET_CANCEL_REQUEST_ID: + return 0x00000008; + case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: + return 0x00000010; + case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: + return 0x00000020; + case CSR_MA_PACKET_ERROR_INDICATION_ID: + return 0x00000040; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_REQUEST_ID: + return 0x00000080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_RESET_CONFIRM_ID: + return 0x00000100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_REQUEST_ID: + return 0x00000200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_CONFIRM_ID: + return 0x00000400; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_REQUEST_ID: + return 0x00000800; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CONFIRM_ID: + return 0x00001000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_REQUEST_ID: + return 0x00002000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_NEXT_CONFIRM_ID: + return 0x00004000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_REQUEST_ID: + return 0x00008000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_POWERMGT_CONFIRM_ID: + return 0x00010001; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_REQUEST_ID: + return 0x00010002; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CONFIRM_ID: + return 0x00010004; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_REQUEST_ID: + return 0x00010008; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CONFIRM_ID: + return 0x00010010; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_REQUEST_ID: + return 0x00010020; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_CONFIRM_ID: + return 0x00010040; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MEASURE_INDICATION_ID: + return 0x00010080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_REQUEST_ID: + return 0x00010100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SETKEYS_CONFIRM_ID: + return 0x00010200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_REQUEST_ID: + return 0x00010400; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + return 0x00010800; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: + return 0x00011000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECTED_INDICATION_ID: + return 0x00012000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SCAN_CANCEL_REQUEST_ID: + return 0x00014000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: + return 0x00018000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + return 0x00020001; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_REQUEST_ID: + return 0x00020002; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + return 0x00020004; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_REQUEST_ID: + return 0x00020008; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + return 0x00020010; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: + return 0x00020020; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + return 0x00020040; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: + return 0x00020080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + return 0x00020100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: + return 0x00020200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + return 0x00020400; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_REQUEST_ID: + return 0x00020800; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + return 0x00021000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: + return 0x00022000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + return 0x00024000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: + return 0x00028000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: + return 0x00030001; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + return 0x00030002; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: + return 0x00030004; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + return 0x00030008; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_TRIGGERED_GET_INDICATION_ID: + return 0x00030010; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: + return 0x00030020; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + return 0x00030040; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: + return 0x00030080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: + return 0x00030100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + return 0x00030200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: + return 0x00030400; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + return 0x00030800; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: + return 0x00031000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + return 0x00032000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_REQUEST_ID: + return 0x00034000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + return 0x00038000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: + return 0x00040001; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + return 0x00040002; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: + return 0x00040004; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + return 0x00040008; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: + return 0x00040010; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + return 0x00040020; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_REQUEST_ID: + return 0x00040040; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + return 0x00040080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_REQUEST_ID: + return 0x00040100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + return 0x00040200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_REQUEST_ID: + return 0x00040400; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + return 0x00040800; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: + return 0x00041000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: + return 0x00042000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + return 0x00044000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_REQUEST_ID: + return 0x00048000; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SM_START_CONFIRM_ID: + return 0x00050001; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_REQUEST_ID: + return 0x00050002; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_LEAVE_CONFIRM_ID: + return 0x00050004; +#endif + case CSR_MLME_SET_TIM_REQUEST_ID: + return 0x00050008; + case CSR_MLME_SET_TIM_CONFIRM_ID: + return 0x00050010; +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: + return 0x00050020; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + return 0x00050040; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_REQUEST_ID: + return 0x00050080; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + return 0x00050100; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: + return 0x00050200; +#endif +#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + return 0x00050400; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + return 0x00050800; + case CSR_DEBUG_WORD16_INDICATION_ID: + return 0x00051000; + case CSR_DEBUG_GENERIC_REQUEST_ID: + return 0x00052000; + case CSR_DEBUG_GENERIC_CONFIRM_ID: + return 0x00054000; + case CSR_DEBUG_GENERIC_INDICATION_ID: + return 0x00058000; + default: + break; + } + return 0xffffffff; +} + + diff --git a/drivers/staging/csr/csr_wifi_hip_signals.h b/drivers/staging/csr/csr_wifi_hip_signals.h new file mode 100644 index 000000000000..c48fddd5fa34 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_signals.h @@ -0,0 +1,137 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + ***************************************************************************** + * + * FILE: csr_wifi_hip_signals.h + * + * PURPOSE: + * Header file wrapping the auto-generated code in csr_wifi_hip_sigs.h + * and csr_wifi_hip_signals.c - + * csr_wifi_hip_sigs.h provides structures defining UniFi signals and + * csr_wifi_hip_signals.c provides SigGetSize() and SigGetDataRefs(). + * + ***************************************************************************** + */ +#ifndef __CSR_WIFI_HIP_SIGNALS_H__ +#define __CSR_WIFI_HIP_SIGNALS_H__ + +#include "csr_types.h" +#include "csr_wifi_hip_sigs.h" + + +/****************************************************************************/ +/* INFORMATION ELEMENTS */ +/****************************************************************************/ + +/* Information Element ID's - shouldn't be in here, but nowhere better yet */ +#define IE_SSID_ID 0 +#define IE_SUPPORTED_RATES_ID 1 +#define IE_FH_PARAM_SET_ID 2 +#define IE_DS_PARAM_SET_ID 3 +#define IE_CF_PARAM_SET_ID 4 +#define IE_TIM_ID 5 +#define IE_IBSS_PARAM_SET_ID 6 +#define IE_COUNTRY_ID 7 +#define IE_HOPPING_PATTERN_PARAMS_ID 8 +#define IE_HOPPING_PATTERN_TABLE_ID 9 +#define IE_REQUEST_ID 10 +#define IE_QBSS_LOAD_ID 11 +#define IE_EDCA_PARAM_SET_ID 12 +#define IE_TRAFFIC_SPEC_ID 13 +#define IE_TRAFFIC_CLASS_ID 14 +#define IE_SCHEDULE_ID 15 +#define IE_CHALLENGE_TEXT_ID 16 +#define IE_POWER_CONSTRAINT_ID 32 +#define IE_POWER_CAPABILITY_ID 33 +#define IE_TPC_REQUEST_ID 34 +#define IE_TPC_REPORT_ID 35 +#define IE_SUPPORTED_CHANNELS_ID 36 +#define IE_CHANNEL_SWITCH_ANNOUNCE_ID 37 +#define IE_MEASUREMENT_REQUEST_ID 38 +#define IE_MEASUREMENT_REPORT_ID 39 +#define IE_QUIET_ID 40 +#define IE_IBSS_DFS_ID 41 +#define IE_ERP_INFO_ID 42 +#define IE_TS_DELAY_ID 43 +#define IE_TCLAS_PROCESSING_ID 44 +#define IE_QOS_CAPABILITY_ID 46 +#define IE_RSN_ID 48 +#define IE_EXTENDED_SUPPORTED_RATES_ID 50 +#define IE_AP_CHANNEL_REPORT_ID 52 +#define IE_RCPI_ID 53 +#define IE_WPA_ID 221 + + +/* The maximum number of data references in a signal structure */ +#define UNIFI_MAX_DATA_REFERENCES 2 + +/* The space to allow for a wire-format signal structure */ +#define UNIFI_PACKED_SIGBUF_SIZE 64 + + +/******************************************************************************/ +/* SIGNAL PARAMETER VALUES */ +/******************************************************************************/ + +/* ifIndex */ +#define UNIFI_IF_2G4 1 +#define UNIFI_IF_5G 2 + +/* SendProcessId */ +#define HOST_PROC_ID 0xc000 + +#define SIG_CAP_ESS 0x0001 +#define SIG_CAP_IBSS 0x0002 +#define SIG_CAP_CF_POLLABLE 0x0004 +#define SIG_CAP_CF_POLL_REQUEST 0x0008 +#define SIG_CAP_PRIVACY 0x0010 +#define SIG_CAP_SHORT_PREAMBLE 0x0020 +#define SIG_CAP_DSSSOFDM 0x2000 + +/******************************************************************************/ +/* FUNCTION DECLARATIONS */ +/******************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/****************************************************************************** + * SigGetNumDataRefs - Retrieve pointers to data-refs from a signal. + * + * PARAMETERS: + * aSignal - Pointer to signal to retrieve the data refs of. + * aDataRef - Address of a pointer to the structure that the data refs + * pointers will be stored. + * + * RETURNS: + * The number of data-refs in the signal. + */ +CsrInt32 SigGetDataRefs(CSR_SIGNAL *aSignal, CSR_DATAREF **aDataRef); + +/****************************************************************************** + * SigGetSize - Retrieve the size (in bytes) of a given signal. + * + * PARAMETERS: + * aSignal - Pointer to signal to retrieve size of. + * + * RETURNS: + * The size (in bytes) of the given signal. + */ +CsrInt32 SigGetSize(const CSR_SIGNAL *aSignal); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __CSR_WIFI_HIP_SIGNALS_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_sigs.h b/drivers/staging/csr/csr_wifi_hip_sigs.h new file mode 100644 index 000000000000..c94e2a483975 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_sigs.h @@ -0,0 +1,1425 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + + +/* Generated by hip_dd_l_h_gen.pl */ + +#ifndef CSR_WIFI_HIP_SIGS_H +#define CSR_WIFI_HIP_SIGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef CsrInt16 csr_place_holding_type; + +typedef CsrUint16 CSR_ASSOCIATION_ID; + +typedef CsrUint16 CSR_AUTONOMOUS_SCAN_ID; + +typedef CsrUint16 CSR_BEACON_PERIODS; + +typedef CsrUint16 CSR_BLACKOUT_ID; + +typedef enum CSR_BLACKOUT_SOURCE +{ + CSR_DOT11_LOCAL = 0x0000, + CSR_DOT11_REMOTE = 0x0001, + CSR_OTHER_RADIO = 0x0002, + CSR_NOT_LINKED = 0x0004 +} CSR_BLACKOUT_SOURCE; + +typedef enum CSR_BLACKOUT_TYPE +{ + CSR_LOCAL_DEVICE_ONLY = 0x0001, + CSR_SPECIFIED_PEER = 0x0002, + CSR_CURRENT_CHANNEL = 0x0004, + CSR_P2P = 0x0008 +} CSR_BLACKOUT_TYPE; + +typedef enum CSR_BOOT_LOADER_OPERATION +{ + CSR_BOOT_LOADER_IDLE = 0x00, + CSR_BOOT_LOADER_RESTART = 0x01, + CSR_BOOT_LOADER_PATCH = 0x02, + CSR_BOOT_LOADER_IMAGE_0 = 0x10, + CSR_BOOT_LOADER_IMAGE_1 = 0x11, + CSR_BOOT_LOADER_IMAGE_2 = 0x12, + CSR_BOOT_LOADER_IMAGE_3 = 0x13 +} CSR_BOOT_LOADER_OPERATION; + +typedef CsrUint16 CSR_CAPABILITY_INFORMATION; + +typedef CsrUint16 CSR_CHANNEL_STARTING_FACTOR; + +typedef CsrUint32 CSR_CIPHER_SUITE_SELECTOR; + +typedef CsrUint32 CSR_CLIENT_TAG; + +typedef enum CSR_CONNECTION_STATUS +{ + CSR_DISCONNECTED = 0x0000, + CSR_CONNECTED_AWAKE = 0x0001 +} CSR_CONNECTION_STATUS; + +typedef CsrInt16 CSR_DECIBELS; + +typedef enum CSR_DIRECTION +{ + CSR_TRANSMIT = 0x0000, + CSR_RECEIVE = 0x0001, + CSR_BIDIRECTIONAL = 0x0003 +} CSR_DIRECTION; + +typedef enum CSR_FRAME_TYPE +{ + CSR_RESERVED = 0x0000, + CSR_BEACON = 0x0001, + CSR_PROBE_RESPONSE = 0x0002, + CSR_BEACON_AND_PROBE_RESPONSE = 0x0003, + CSR_PROBE_REQUEST = 0x0004 +} CSR_FRAME_TYPE; + +typedef CsrUint32 CSR_IPV4_ADDRESS; + +typedef enum CSR_IFINTERFACE +{ + CSR_INDEX_2G4 = 0x0001, + CSR_INDEX_5G = 0x0002 +} CSR_IFINTERFACE; + +typedef enum CSR_KEY_TYPE +{ + CSR_GROUP = 0x0000, + CSR_PAIRWISE = 0x0001, + CSR_PEER_KEY = 0x0002, + CSR_IGTK = 0x0003 +} CSR_KEY_TYPE; + +typedef enum CSR_LOADER_OPERATION +{ + CSR_LOADER_IDLE = 0x0000, + CSR_LOADER_COPY = 0x0001 +} CSR_LOADER_OPERATION; + +typedef struct CSR_MAC_ADDRESS +{ + CsrUint8 x[6]; +} CSR_MACADDRESS; + +typedef enum CSR_MIB_STATUS +{ + CSR_MIB_SUCCESSFUL = 0x0000, + CSR_MIB_INVALID_PARAMETERS = 0x0001, + CSR_MIB_WRITE_ONLY = 0x0002, + CSR_MIB_READ_ONLY = 0x0003 +} CSR_MIB_STATUS; + +typedef enum CSR_MEMORY_SPACE +{ + CSR_NONE = 0x00, + CSR_SHARED_DATA_MEMORY = 0x01, + CSR_EXTERNAL_FLASH_MEMORY = 0x02, + CSR_EXTERNAL_SRAM = 0x03, + CSR_REGISTERS = 0x04, + CSR_PHY_PROCESSOR_DATA_MEMORY = 0x10, + CSR_PHY_PROCESSOR_PROGRAM_MEMORY = 0x11, + CSR_PHY_PROCESSOR_ROM = 0x12, + CSR_MAC_PROCESSOR_DATA_MEMORY = 0x20, + CSR_MAC_PROCESSOR_PROGRAM_MEMORY = 0x21, + CSR_MAC_PROCESSOR_ROM = 0x22, + CSR_BT_PROCESSOR_DATA_MEMORY = 0x30, + CSR_BT_PROCESSOR_PROGRAM_MEMORY = 0x31, + CSR_BT_PROCESSOR_ROM = 0x32 +} CSR_MEMORY_SPACE; + +typedef CsrUint16 CSR_MICROSECONDS16; + +typedef CsrUint32 CSR_MICROSECONDS32; + +typedef CsrUint16 CSR_NATURAL16; + +typedef enum CSR_PS_SCHEME +{ + CSR_LEGACY_PS = 0x0001, + CSR_U_APSD = 0x0002, + CSR_S_APSD = 0x0004 +} CSR_PS_SCHEME; + +typedef enum CSR_PACKET_FILTER_MODE +{ + CSR_PFM_OPT_OUT = 0x0000, + CSR_PFM_OPT_IN = 0x0003 +} CSR_PACKET_FILTER_MODE; + +typedef CsrUint16 CSR_PERIODIC_ID; + +typedef enum CSR_PERIODIC_SCHEDULING_MODE +{ + CSR_PSM_PERIODIC_SCHEDULE_PS_POLL = 0x0001, + CSR_PSM_PERIODIC_SCHEDULE_PM_BIT = 0x0002, + CSR_PSM_PERIODIC_SCHEDULE_UAPSD = 0x0004, + CSR_PSM_PERIODIC_SCHEDULE_SAPSD = 0x0008 +} CSR_PERIODIC_SCHEDULING_MODE; + +typedef enum CSR_POWER_MANAGEMENT_MODE +{ + CSR_PMM_ACTIVE_MODE = 0x0000, + CSR_PMM_POWER_SAVE = 0x0001, + CSR_PMM_FAST_POWER_SAVE = 0x0002 +} CSR_POWER_MANAGEMENT_MODE; + +typedef enum CSR_PRIORITY +{ + CSR_QOS_UP0 = 0x0000, + CSR_QOS_UP1 = 0x0001, + CSR_QOS_UP2 = 0x0002, + CSR_QOS_UP3 = 0x0003, + CSR_QOS_UP4 = 0x0004, + CSR_QOS_UP5 = 0x0005, + CSR_QOS_UP6 = 0x0006, + CSR_QOS_UP7 = 0x0007, + CSR_CONTENTION = 0x8000, + CSR_MANAGEMENT = 0x8010 +} CSR_PRIORITY; + +typedef enum CSR_REASON_CODE +{ + CSR_UNSPECIFIED_REASON = 0x0001, + CSR_INVALID_INFORMATION_ELEMENT = 0x000d, + CSR_QOS_UNSPECIFIED_REASON = 0x0020, + CSR_QOS_EXCESSIVE_NOT_ACK = 0x0022, + CSR_QOS_TXOP_LIMIT_EXCEEDED = 0x0023, + CSR_QSTA_LEAVING = 0x0024, + CSR_UNKNOWN_BA = 0x0026, + CSR_UNKNOWN_TS = 0x0026, + CSR_TIMEOUT = 0x0027 +} CSR_REASON_CODE; + +typedef enum CSR_RECEPTION_STATUS +{ + CSR_RX_SUCCESS = 0x0000, + CSR_RX_FAILURE_UNSPECIFIED = 0x0001, + CSR_MICHAEL_MIC_ERROR = 0x0002, + CSR_DECRYPTION_ERROR = 0x0003, + CSR_NO_TEMPORAL_KEY_AVAILABLE = 0x0004, + CSR_UNSUPPORTED_MODULATION = 0x0011, + CSR_BAD_FCS = 0x0012, + CSR_BAD_SIGNAL = 0x0013 +} CSR_RECEPTION_STATUS; + +typedef enum CSR_RESULT_CODE +{ + CSR_RC_SUCCESS = 0x0000, + CSR_RC_UNSPECIFIED_FAILURE = 0x0001, + CSR_RC_REFUSED = 0x0003, + CSR_RC_INVALID_PARAMETERS = 0x0026, + CSR_RC_REJECTED_INVALID_IE = 0x0028, + CSR_RC_REJECTED_INVALID_GROUP_CIPHER = 0x0029, + CSR_RC_REJECTED_INVALID_PAIRWISE_CIPHER = 0x002a, + CSR_RC_TIMEOUT = 0x8000, + CSR_RC_TOO_MANY_SIMULTANEOUS_REQUESTS = 0x8001, + CSR_RC_BSS_ALREADY_STARTED_OR_JOINED = 0x8002, + CSR_RC_NOT_SUPPORTED = 0x8003, + CSR_RC_TRANSMISSION_FAILURE = 0x8004, + CSR_RC_RESET_REQUIRED_BEFORE_START = 0x8006, + CSR_RC_INSUFFICIENT_RESOURCE = 0x8007, + CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES = 0x8008, + CSR_RC_INVALID_UNICAST_CIPHER = 0xf02f, + CSR_RC_INVALID_MULTICAST_CIPHER = 0xf030 +} CSR_RESULT_CODE; + +typedef enum CSR_SCAN_TYPE +{ + CSR_SC_ACTIVE_SCAN = 0x0000, + CSR_SC_PASSIVE_SCAN = 0x0001 +} CSR_SCAN_TYPE; + +typedef enum CSR_SIGNAL_ID +{ + CSR_MA_PACKET_REQUEST_ID = 0x0110, + CSR_MA_PACKET_CONFIRM_ID = 0x0111, + CSR_MA_PACKET_INDICATION_ID = 0x0113, + CSR_MA_PACKET_CANCEL_REQUEST_ID = 0x0114, + CSR_MA_VIF_AVAILABILITY_RESPONSE_ID = 0x0116, + CSR_MA_VIF_AVAILABILITY_INDICATION_ID = 0x0117, + CSR_MA_PACKET_ERROR_INDICATION_ID = 0x011b, + CSR_MLME_RESET_REQUEST_ID = 0x0200, + CSR_MLME_RESET_CONFIRM_ID = 0x0201, + CSR_MLME_GET_REQUEST_ID = 0x0204, + CSR_MLME_GET_CONFIRM_ID = 0x0205, + CSR_MLME_SET_REQUEST_ID = 0x0208, + CSR_MLME_SET_CONFIRM_ID = 0x0209, + CSR_MLME_GET_NEXT_REQUEST_ID = 0x020c, + CSR_MLME_GET_NEXT_CONFIRM_ID = 0x020d, + CSR_MLME_POWERMGT_REQUEST_ID = 0x0210, + CSR_MLME_POWERMGT_CONFIRM_ID = 0x0211, + CSR_MLME_SCAN_REQUEST_ID = 0x0214, + CSR_MLME_SCAN_CONFIRM_ID = 0x0215, + CSR_MLME_HL_SYNC_REQUEST_ID = 0x0244, + CSR_MLME_HL_SYNC_CONFIRM_ID = 0x0245, + CSR_MLME_MEASURE_REQUEST_ID = 0x0258, + CSR_MLME_MEASURE_CONFIRM_ID = 0x0259, + CSR_MLME_MEASURE_INDICATION_ID = 0x025b, + CSR_MLME_SETKEYS_REQUEST_ID = 0x0268, + CSR_MLME_SETKEYS_CONFIRM_ID = 0x0269, + CSR_MLME_DELETEKEYS_REQUEST_ID = 0x026c, + CSR_MLME_DELETEKEYS_CONFIRM_ID = 0x026d, + CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID = 0x0287, + CSR_MLME_CONNECTED_INDICATION_ID = 0x028b, + CSR_MLME_SCAN_CANCEL_REQUEST_ID = 0x028c, + CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID = 0x0298, + CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID = 0x0299, + CSR_MLME_ADD_PERIODIC_REQUEST_ID = 0x02a0, + CSR_MLME_ADD_PERIODIC_CONFIRM_ID = 0x02a1, + CSR_MLME_DEL_PERIODIC_REQUEST_ID = 0x02a4, + CSR_MLME_DEL_PERIODIC_CONFIRM_ID = 0x02a5, + CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID = 0x02a8, + CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02a9, + CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID = 0x02ac, + CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02ad, + CSR_MLME_SET_PACKET_FILTER_REQUEST_ID = 0x02b8, + CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID = 0x02b9, + CSR_MLME_STOP_MEASURE_REQUEST_ID = 0x02bc, + CSR_MLME_STOP_MEASURE_CONFIRM_ID = 0x02bd, + CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID = 0x02cc, + CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02cd, + CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID = 0x02db, + CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID = 0x02dc, + CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID = 0x02dd, + CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID = 0x02e0, + CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID = 0x02e1, + CSR_MLME_TRIGGERED_GET_INDICATION_ID = 0x02e7, + CSR_MLME_ADD_BLACKOUT_REQUEST_ID = 0x02f8, + CSR_MLME_ADD_BLACKOUT_CONFIRM_ID = 0x02f9, + CSR_MLME_BLACKOUT_ENDED_INDICATION_ID = 0x02fb, + CSR_MLME_DEL_BLACKOUT_REQUEST_ID = 0x02fc, + CSR_MLME_DEL_BLACKOUT_CONFIRM_ID = 0x02fd, + CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID = 0x0304, + CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID = 0x0305, + CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID = 0x0308, + CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID = 0x0309, + CSR_MLME_CONNECT_STATUS_REQUEST_ID = 0x0310, + CSR_MLME_CONNECT_STATUS_CONFIRM_ID = 0x0311, + CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID = 0x0314, + CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID = 0x0315, + CSR_MLME_ADD_TEMPLATE_REQUEST_ID = 0x0318, + CSR_MLME_ADD_TEMPLATE_CONFIRM_ID = 0x0319, + CSR_MLME_CONFIG_QUEUE_REQUEST_ID = 0x031c, + CSR_MLME_CONFIG_QUEUE_CONFIRM_ID = 0x031d, + CSR_MLME_ADD_TSPEC_REQUEST_ID = 0x0320, + CSR_MLME_ADD_TSPEC_CONFIRM_ID = 0x0321, + CSR_MLME_DEL_TSPEC_REQUEST_ID = 0x0324, + CSR_MLME_DEL_TSPEC_CONFIRM_ID = 0x0325, + CSR_MLME_START_AGGREGATION_REQUEST_ID = 0x0328, + CSR_MLME_START_AGGREGATION_CONFIRM_ID = 0x0329, + CSR_MLME_BLOCKACK_ERROR_INDICATION_ID = 0x032b, + CSR_MLME_STOP_AGGREGATION_REQUEST_ID = 0x032c, + CSR_MLME_STOP_AGGREGATION_CONFIRM_ID = 0x032d, + CSR_MLME_SM_START_REQUEST_ID = 0x0334, + CSR_MLME_SM_START_CONFIRM_ID = 0x0335, + CSR_MLME_LEAVE_REQUEST_ID = 0x0338, + CSR_MLME_LEAVE_CONFIRM_ID = 0x0339, + CSR_MLME_SET_TIM_REQUEST_ID = 0x033c, + CSR_MLME_SET_TIM_CONFIRM_ID = 0x033d, + CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID = 0x0340, + CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID = 0x0341, + CSR_MLME_SET_CHANNEL_REQUEST_ID = 0x034c, + CSR_MLME_SET_CHANNEL_CONFIRM_ID = 0x034d, + CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID = 0x040c, + CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID = 0x040d, + CSR_DEBUG_STRING_INDICATION_ID = 0x0803, + CSR_DEBUG_WORD16_INDICATION_ID = 0x0807, + CSR_DEBUG_GENERIC_REQUEST_ID = 0x0808, + CSR_DEBUG_GENERIC_CONFIRM_ID = 0x0809, + CSR_DEBUG_GENERIC_INDICATION_ID = 0x080b +} CSR_SIGNAL_ID; + +typedef CsrUint16 CSR_SIMPLE_POINTER; + +typedef CsrUint16 CSR_STARTING_SEQUENCE_NUMBER; + +typedef enum CSR_SYMBOL_ID +{ + CSR_SLT_END = 0x0000, + CSR_SLT_PCI_SLOT_CONFIG = 0x0001, + CSR_SLT_SDIO_SLOT_CONFIG = 0x0002, + CSR_SLT_BUILD_ID_NUMBER = 0x0003, + CSR_SLT_BUILD_ID_STRING = 0x0004, + CSR_SLT_PERSISTENT_STORE_DB = 0x0005, + CSR_SLT_RESET_VECTOR_PHY = 0x0006, + CSR_SLT_RESET_VECTOR_MAC = 0x0007, + CSR_SLT_SDIO_LOADER_CONTROL = 0x0008, + CSR_SLT_TEST_CMD = 0x0009, + CSR_SLT_TEST_ALIVE_COUNTER = 0x000a, + CSR_SLT_TEST_PARAMETERS = 0x000b, + CSR_SLT_TEST_RESULTS = 0x000c, + CSR_SLT_TEST_VERSION = 0x000d, + CSR_SLT_MIB_PSID_RANGES = 0x000e, + CSR_SLT_KIP_TABLE = 0x000f, + CSR_SLT_PANIC_DATA_PHY = 0x0010, + CSR_SLT_PANIC_DATA_MAC = 0x0011, + CSR_SLT_BOOT_LOADER_CONTROL = 0x0012, + CSR_SLT_SOFT_MAC = 0x0013 +} CSR_SYMBOL_ID; + +typedef struct CSR_TSF_TIME +{ + CsrUint8 x[8]; +} CSR_TSF_TIME; + +typedef CsrUint16 CSR_TIME_UNITS; + +typedef enum CSR_TRANSMISSION_CONTROL +{ + CSR_TRIGGERED = 0x0001, + CSR_END_OF_SERVICE = 0x0002, + CSR_NO_CONFIRM_REQUIRED = 0x0004, + CSR_ALLOW_BA = 0x0008 +} CSR_TRANSMISSION_CONTROL; + +typedef enum CSR_TRANSMISSION_STATUS +{ + CSR_TX_SUCCESSFUL = 0x0000, + CSR_TX_RETRY_LIMIT = 0x0001, + CSR_TX_LIFETIME = 0x0002, + CSR_TX_NO_BSS = 0x0003, + CSR_TX_EXCESSIVE_DATA_LENGTH = 0x0004, + CSR_TX_UNSUPPORTED_PRIORITY = 0x0006, + CSR_TX_UNAVAILABLE_PRIORITY = 0x0007, + CSR_TX_UNAVAILABLE_KEY_MAPPING = 0x000a, + CSR_TX_EDCA_TIMEOUT = 0x000b, + CSR_TX_BLOCK_ACK_TIMEOUT = 0x000c, + CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED = 0x000d, + CSR_TX_REJECTED_PEER_STATION_SLEEPING = 0x000e, + CSR_TX_REJECTED_DTIM_ENDED = 0x000f, + CSR_TX_REJECTED_DTIM_STARTED = 0x0010 +} CSR_TRANSMISSION_STATUS; + +typedef CsrUint16 CSR_TRIGGER_ID; + +typedef CsrUint16 CSR_TRIGGERED_ID; + +typedef enum CSR_HIP_VERSIONS +{ + CSR_HIP_ENG_VERSION = 0x0001, + CSR_HIP_VERSION = 0x0900 +} CSR_HIP_VERSIONS; + +typedef CsrUint16 CSR_BUFFER_HANDLE; + +typedef CsrUint16 CSR_CHANNEL_NUMBER; + +typedef struct CSR_DATA_REFERENCE +{ + CsrUint16 SlotNumber; + CsrUint16 DataLength; +} CSR_DATAREF; + +typedef CsrUint16 CSR_DIALOG_TOKEN; + +typedef struct CSR_GENERIC_POINTER +{ + CsrUint24 MemoryOffset; + CSR_MEMORY_SPACE MemorySpace; +} CSR_GENERIC_POINTER; + +typedef struct CSR_MLME_CONFIG_QUEUE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_CONFIG_QUEUE_CONFIRM; + +typedef struct CSR_MLME_CONFIG_QUEUE_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_NATURAL16 QueueIndex; + CSR_NATURAL16 Aifs; + CSR_NATURAL16 Cwmin; + CSR_NATURAL16 Cwmax; + CSR_NATURAL16 TxopLimit; +} CSR_MLME_CONFIG_QUEUE_REQUEST; + +typedef struct CSR_MLME_GET_CONFIRM +{ + CSR_DATAREF MibAttributeValue; + CSR_DATAREF Dummydataref2; + CSR_MIB_STATUS Status; + CSR_NATURAL16 ErrorIndex; +} CSR_MLME_GET_CONFIRM; + +typedef struct CSR_MLME_GET_REQUEST +{ + CSR_DATAREF MibAttribute; + CSR_DATAREF Dummydataref2; +} CSR_MLME_GET_REQUEST; + +typedef struct CSR_MLME_GET_NEXT_CONFIRM +{ + CSR_DATAREF MibAttributeValue; + CSR_DATAREF Dummydataref2; + CSR_MIB_STATUS Status; + CSR_NATURAL16 ErrorIndex; +} CSR_MLME_GET_NEXT_CONFIRM; + +typedef struct CSR_MLME_GET_NEXT_REQUEST +{ + CSR_DATAREF MibAttribute; + CSR_DATAREF Dummydataref2; +} CSR_MLME_GET_NEXT_REQUEST; + +typedef struct CSR_MLME_HL_SYNC_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_MACADDRESS GroupAddress; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_HL_SYNC_CONFIRM; + +typedef struct CSR_MLME_HL_SYNC_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_MACADDRESS GroupAddress; +} CSR_MLME_HL_SYNC_REQUEST; + +typedef struct CSR_MLME_HL_SYNC_CANCEL_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_HL_SYNC_CANCEL_CONFIRM; + +typedef struct CSR_MLME_HL_SYNC_CANCEL_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_MACADDRESS GroupAddress; +} CSR_MLME_HL_SYNC_CANCEL_REQUEST; + +typedef struct CSR_MLME_MEASURE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_RESULT_CODE ResultCode; + CSR_DIALOG_TOKEN DialogToken; +} CSR_MLME_MEASURE_CONFIRM; + +typedef struct CSR_MLME_MEASURE_INDICATION +{ + CSR_DATAREF MeasurementReportSet; + CSR_DATAREF Dummydataref2; + CSR_DIALOG_TOKEN DialogToken; +} CSR_MLME_MEASURE_INDICATION; + +typedef struct CSR_MLME_MEASURE_REQUEST +{ + CSR_DATAREF MeasurementRequestSet; + CSR_DATAREF Dummydataref2; + CSR_DIALOG_TOKEN DialogToken; +} CSR_MLME_MEASURE_REQUEST; + +typedef struct CSR_MLME_RESET_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_RESET_CONFIRM; + +typedef struct CSR_MLME_RESET_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_MACADDRESS StaAddress; + CsrInt16 SetDefaultMib; +} CSR_MLME_RESET_REQUEST; + +typedef struct CSR_MLME_SET_CONFIRM +{ + CSR_DATAREF MibAttributeValue; + CSR_DATAREF Dummydataref2; + CSR_MIB_STATUS Status; + CSR_NATURAL16 ErrorIndex; +} CSR_MLME_SET_CONFIRM; + +typedef struct CSR_MLME_SET_REQUEST +{ + CSR_DATAREF MibAttributeValue; + CSR_DATAREF Dummydataref2; +} CSR_MLME_SET_REQUEST; + +typedef struct CSR_MLME_STOP_MEASURE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_RESULT_CODE ResultCode; + CSR_DIALOG_TOKEN DialogToken; +} CSR_MLME_STOP_MEASURE_CONFIRM; + +typedef struct CSR_MLME_STOP_MEASURE_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_DIALOG_TOKEN DialogToken; +} CSR_MLME_STOP_MEASURE_REQUEST; + +typedef CsrUint16 CSR_PROCESS_ID; + +typedef CsrUint16 CSR_RATE; + +typedef CsrUint16 CSR_SEQUENCE_NUMBER; + +typedef struct CSR_SIGNAL_PRIMITIVE_HEADER +{ + CsrInt16 SignalId; + CSR_PROCESS_ID ReceiverProcessId; + CSR_PROCESS_ID SenderProcessId; +} CSR_SIGNAL_PRIMITIVE_HEADER; + +typedef CsrUint16 CSR_TRAFFIC_WINDOW; + +typedef CsrUint16 CSR_VIF_IDENTIFIER; + +typedef struct CSR_DEBUG_GENERIC_CONFIRM +{ + CSR_DATAREF DebugVariable; + CSR_DATAREF Dummydataref2; + CSR_NATURAL16 DebugWords[8]; +} CSR_DEBUG_GENERIC_CONFIRM; + +typedef struct CSR_DEBUG_GENERIC_INDICATION +{ + CSR_DATAREF DebugVariable; + CSR_DATAREF Dummydataref2; + CSR_NATURAL16 DebugWords[8]; +} CSR_DEBUG_GENERIC_INDICATION; + +typedef struct CSR_DEBUG_GENERIC_REQUEST +{ + CSR_DATAREF DebugVariable; + CSR_DATAREF Dummydataref2; + CSR_NATURAL16 DebugWords[8]; +} CSR_DEBUG_GENERIC_REQUEST; + +typedef struct CSR_DEBUG_STRING_INDICATION +{ + CSR_DATAREF DebugMessage; + CSR_DATAREF Dummydataref2; +} CSR_DEBUG_STRING_INDICATION; + +typedef struct CSR_DEBUG_WORD16_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_NATURAL16 DebugWords[16]; +} CSR_DEBUG_WORD16_INDICATION; + +typedef struct CSR_MA_PACKET_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRANSMISSION_STATUS TransmissionStatus; + CSR_NATURAL16 RetryCount; + CSR_RATE Rate; + CSR_CLIENT_TAG HostTag; +} CSR_MA_PACKET_CONFIRM; + +typedef struct CSR_MA_PACKET_INDICATION +{ + CSR_DATAREF Data; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TSF_TIME LocalTime; + CSR_IFINTERFACE Ifindex; + CSR_CHANNEL_NUMBER Channel; + CSR_RECEPTION_STATUS ReceptionStatus; + CSR_DECIBELS Rssi; + CSR_DECIBELS Snr; + CSR_RATE ReceivedRate; +} CSR_MA_PACKET_INDICATION; + +typedef struct CSR_MA_PACKET_REQUEST +{ + CSR_DATAREF Data; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RATE TransmitRate; + CSR_CLIENT_TAG HostTag; + CSR_PRIORITY Priority; + CSR_MACADDRESS Ra; + CSR_TRANSMISSION_CONTROL TransmissionControl; +} CSR_MA_PACKET_REQUEST; + +typedef struct CSR_MA_PACKET_CANCEL_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_CLIENT_TAG HostTag; +} CSR_MA_PACKET_CANCEL_REQUEST; + +typedef struct CSR_MA_PACKET_ERROR_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS PeerQstaAddress; + CSR_PRIORITY UserPriority; + CSR_SEQUENCE_NUMBER SequenceNumber; +} CSR_MA_PACKET_ERROR_INDICATION; + +typedef struct CSR_MA_VIF_AVAILABILITY_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CsrInt16 Multicast; +} CSR_MA_VIF_AVAILABILITY_INDICATION; + +typedef struct CSR_MA_VIF_AVAILABILITY_RESPONSE +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MA_VIF_AVAILABILITY_RESPONSE; + +typedef struct CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; +} CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM; + +typedef struct CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST +{ + CSR_DATAREF ChannelList; + CSR_DATAREF InformationElements; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; + CSR_IFINTERFACE Ifindex; + CSR_CHANNEL_STARTING_FACTOR ChannelStartingFactor; + CSR_SCAN_TYPE ScanType; + CSR_MICROSECONDS32 ProbeDelay; + CSR_TIME_UNITS MinChannelTime; + CSR_TIME_UNITS MaxChannelTime; +} CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST; + +typedef struct CSR_MLME_ADD_BLACKOUT_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_BLACKOUT_ID BlackoutId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_BLACKOUT_CONFIRM; + +typedef struct CSR_MLME_ADD_BLACKOUT_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_BLACKOUT_ID BlackoutId; + CSR_BLACKOUT_TYPE BlackoutType; + CSR_BLACKOUT_SOURCE BlackoutSource; + CSR_MICROSECONDS32 BlackoutStartReference; + CSR_MICROSECONDS32 BlackoutPeriod; + CSR_MICROSECONDS32 BlackoutDuration; + CSR_MACADDRESS PeerStaAddress; + CSR_NATURAL16 BlackoutCount; +} CSR_MLME_ADD_BLACKOUT_REQUEST; + +typedef struct CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM; + +typedef struct CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST +{ + CSR_DATAREF Data; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_NATURAL16 NumberOfMulticastGroupAddresses; +} CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST; + +typedef struct CSR_MLME_ADD_PERIODIC_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PERIODIC_ID PeriodicId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_PERIODIC_CONFIRM; + +typedef struct CSR_MLME_ADD_PERIODIC_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PERIODIC_ID PeriodicId; + CSR_MICROSECONDS32 MaximumLatency; + CSR_PERIODIC_SCHEDULING_MODE PeriodicSchedulingMode; + CsrInt16 WakeHost; + CSR_PRIORITY UserPriority; +} CSR_MLME_ADD_PERIODIC_REQUEST; + +typedef struct CSR_MLME_ADD_RX_TRIGGER_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGER_ID TriggerId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_RX_TRIGGER_CONFIRM; + +typedef struct CSR_MLME_ADD_RX_TRIGGER_REQUEST +{ + CSR_DATAREF InformationElements; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGER_ID TriggerId; + CSR_PRIORITY Priority; +} CSR_MLME_ADD_RX_TRIGGER_REQUEST; + +typedef struct CSR_MLME_ADD_TEMPLATE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_FRAME_TYPE FrameType; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_TEMPLATE_CONFIRM; + +typedef struct CSR_MLME_ADD_TEMPLATE_REQUEST +{ + CSR_DATAREF Data1; + CSR_DATAREF Data2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_FRAME_TYPE FrameType; + CSR_RATE MinTransmitRate; +} CSR_MLME_ADD_TEMPLATE_REQUEST; + +typedef struct CSR_MLME_ADD_TRIGGERED_GET_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_TRIGGERED_ID TriggeredId; +} CSR_MLME_ADD_TRIGGERED_GET_CONFIRM; + +typedef struct CSR_MLME_ADD_TRIGGERED_GET_REQUEST +{ + CSR_DATAREF MibAttribute; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGERED_ID TriggeredId; +} CSR_MLME_ADD_TRIGGERED_GET_REQUEST; + +typedef struct CSR_MLME_ADD_TSPEC_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PRIORITY UserPriority; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_ADD_TSPEC_CONFIRM; + +typedef struct CSR_MLME_ADD_TSPEC_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; + CSR_PS_SCHEME PsScheme; + CSR_NATURAL16 MediumTime; + CSR_MICROSECONDS32 ServiceStartTime; + CSR_MICROSECONDS32 ServiceInterval; + CSR_RATE MinimumDataRate; +} CSR_MLME_ADD_TSPEC_REQUEST; + +typedef struct CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; +} CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION; + +typedef struct CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS Bssid; +} CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION; + +typedef struct CSR_MLME_BLACKOUT_ENDED_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_BLACKOUT_ID BlackoutId; +} CSR_MLME_BLACKOUT_ENDED_INDICATION; + +typedef struct CSR_MLME_BLOCKACK_ERROR_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_REASON_CODE ResultCode; + CSR_MACADDRESS PeerQstaAddress; +} CSR_MLME_BLOCKACK_ERROR_INDICATION; + +typedef struct CSR_MLME_CONNECTED_INDICATION +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_CONNECTION_STATUS ConnectionStatus; + CSR_MACADDRESS PeerMacAddress; +} CSR_MLME_CONNECTED_INDICATION; + +typedef struct CSR_MLME_CONNECT_STATUS_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_CONNECT_STATUS_CONFIRM; + +typedef struct CSR_MLME_CONNECT_STATUS_REQUEST +{ + CSR_DATAREF InformationElements; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_CONNECTION_STATUS ConnectionStatus; + CSR_MACADDRESS StaAddress; + CSR_ASSOCIATION_ID AssociationId; + CSR_CAPABILITY_INFORMATION AssociationCapabilityInformation; +} CSR_MLME_CONNECT_STATUS_REQUEST; + +typedef struct CSR_MLME_DELETEKEYS_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_DELETEKEYS_CONFIRM; + +typedef struct CSR_MLME_DELETEKEYS_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_NATURAL16 KeyId; + CSR_KEY_TYPE KeyType; + CSR_MACADDRESS Address; +} CSR_MLME_DELETEKEYS_REQUEST; + +typedef struct CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; +} CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM; + +typedef struct CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; +} CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST; + +typedef struct CSR_MLME_DEL_BLACKOUT_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_BLACKOUT_ID BlackoutId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_DEL_BLACKOUT_CONFIRM; + +typedef struct CSR_MLME_DEL_BLACKOUT_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_BLACKOUT_ID BlackoutId; +} CSR_MLME_DEL_BLACKOUT_REQUEST; + +typedef struct CSR_MLME_DEL_PERIODIC_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PERIODIC_ID PeriodicId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_DEL_PERIODIC_CONFIRM; + +typedef struct CSR_MLME_DEL_PERIODIC_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PERIODIC_ID PeriodicId; +} CSR_MLME_DEL_PERIODIC_REQUEST; + +typedef struct CSR_MLME_DEL_RX_TRIGGER_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGER_ID TriggerId; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_DEL_RX_TRIGGER_CONFIRM; + +typedef struct CSR_MLME_DEL_RX_TRIGGER_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGER_ID TriggerId; +} CSR_MLME_DEL_RX_TRIGGER_REQUEST; + +typedef struct CSR_MLME_DEL_TRIGGERED_GET_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_TRIGGERED_ID TriggeredId; +} CSR_MLME_DEL_TRIGGERED_GET_CONFIRM; + +typedef struct CSR_MLME_DEL_TRIGGERED_GET_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TRIGGERED_ID TriggeredId; +} CSR_MLME_DEL_TRIGGERED_GET_REQUEST; + +typedef struct CSR_MLME_DEL_TSPEC_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PRIORITY UserPriority; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_DEL_TSPEC_CONFIRM; + +typedef struct CSR_MLME_DEL_TSPEC_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; +} CSR_MLME_DEL_TSPEC_REQUEST; + +typedef struct CSR_MLME_GET_KEY_SEQUENCE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_NATURAL16 SequenceNumber[8]; +} CSR_MLME_GET_KEY_SEQUENCE_CONFIRM; + +typedef struct CSR_MLME_GET_KEY_SEQUENCE_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_NATURAL16 KeyId; + CSR_KEY_TYPE KeyType; + CSR_MACADDRESS Address; +} CSR_MLME_GET_KEY_SEQUENCE_REQUEST; + +typedef struct CSR_MLME_LEAVE_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_LEAVE_CONFIRM; + +typedef struct CSR_MLME_LEAVE_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; +} CSR_MLME_LEAVE_REQUEST; + +typedef struct CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM; + +typedef struct CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST +{ + CSR_DATAREF Data; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_TIME_UNITS BeaconPeriod; + CSR_BEACON_PERIODS DtimPeriod; + CSR_CAPABILITY_INFORMATION CapabilityInformation; + CSR_MACADDRESS Bssid; + CSR_NATURAL16 RtsThreshold; +} CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST; + +typedef struct CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; +} CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM; + +typedef struct CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; + CsrInt16 Pause; +} CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST; + +typedef struct CSR_MLME_POWERMGT_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_POWERMGT_CONFIRM; + +typedef struct CSR_MLME_POWERMGT_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_POWER_MANAGEMENT_MODE PowerManagementMode; + CsrInt16 ReceiveDtims; + CSR_BEACON_PERIODS ListenInterval; + CSR_TRAFFIC_WINDOW TrafficWindow; +} CSR_MLME_POWERMGT_REQUEST; + +typedef struct CSR_MLME_SCAN_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SCAN_CONFIRM; + +typedef struct CSR_MLME_SCAN_REQUEST +{ + CSR_DATAREF ChannelList; + CSR_DATAREF InformationElements; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_IFINTERFACE Ifindex; + CSR_SCAN_TYPE ScanType; + CSR_MICROSECONDS32 ProbeDelay; + CSR_TIME_UNITS MinChannelTime; + CSR_TIME_UNITS MaxChannelTime; +} CSR_MLME_SCAN_REQUEST; + +typedef struct CSR_MLME_SCAN_CANCEL_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; +} CSR_MLME_SCAN_CANCEL_REQUEST; + +typedef struct CSR_MLME_SETKEYS_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SETKEYS_CONFIRM; + +typedef struct CSR_MLME_SETKEYS_REQUEST +{ + CSR_DATAREF Key; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_NATURAL16 Length; + CSR_NATURAL16 KeyId; + CSR_KEY_TYPE KeyType; + CSR_MACADDRESS Address; + CSR_NATURAL16 SequenceNumber[8]; + CSR_CIPHER_SUITE_SELECTOR CipherSuiteSelector; +} CSR_MLME_SETKEYS_REQUEST; + +typedef struct CSR_MLME_SET_CHANNEL_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SET_CHANNEL_CONFIRM; + +typedef struct CSR_MLME_SET_CHANNEL_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_IFINTERFACE Ifindex; + CSR_CHANNEL_NUMBER Channel; + CSR_MACADDRESS Address; + CSR_TIME_UNITS AvailabilityDuration; + CSR_TIME_UNITS AvailabilityInterval; +} CSR_MLME_SET_CHANNEL_REQUEST; + +typedef struct CSR_MLME_SET_PACKET_FILTER_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SET_PACKET_FILTER_CONFIRM; + +typedef struct CSR_MLME_SET_PACKET_FILTER_REQUEST +{ + CSR_DATAREF InformationElements; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_PACKET_FILTER_MODE PacketFilterMode; + CSR_IPV4_ADDRESS ArpFilterAddress; +} CSR_MLME_SET_PACKET_FILTER_REQUEST; + +typedef struct CSR_MLME_SET_TIM_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SET_TIM_CONFIRM; + +typedef struct CSR_MLME_SET_TIM_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_ASSOCIATION_ID AssociationId; + CsrInt16 TimValue; +} CSR_MLME_SET_TIM_REQUEST; + +typedef struct CSR_MLME_SM_START_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_SM_START_CONFIRM; + +typedef struct CSR_MLME_SM_START_REQUEST +{ + CSR_DATAREF Beacon; + CSR_DATAREF BssParameters; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_IFINTERFACE Ifindex; + CSR_CHANNEL_NUMBER Channel; + CSR_MACADDRESS InterfaceAddress; + CSR_MACADDRESS Bssid; + CSR_TIME_UNITS BeaconPeriod; + CSR_BEACON_PERIODS DtimPeriod; + CSR_CAPABILITY_INFORMATION CapabilityInformation; +} CSR_MLME_SM_START_REQUEST; + +typedef struct CSR_MLME_START_AGGREGATION_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS PeerQstaAddress; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; + CSR_RESULT_CODE ResultCode; + CSR_SEQUENCE_NUMBER SequenceNumber; +} CSR_MLME_START_AGGREGATION_CONFIRM; + +typedef struct CSR_MLME_START_AGGREGATION_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS PeerQstaAddress; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; + CSR_STARTING_SEQUENCE_NUMBER StartingSequenceNumber; + CSR_NATURAL16 BufferSize; + CSR_TIME_UNITS BlockAckTimeout; +} CSR_MLME_START_AGGREGATION_REQUEST; + +typedef struct CSR_MLME_STOP_AGGREGATION_CONFIRM +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS PeerQstaAddress; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; + CSR_RESULT_CODE ResultCode; +} CSR_MLME_STOP_AGGREGATION_CONFIRM; + +typedef struct CSR_MLME_STOP_AGGREGATION_REQUEST +{ + CSR_DATAREF Dummydataref1; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MACADDRESS PeerQstaAddress; + CSR_PRIORITY UserPriority; + CSR_DIRECTION Direction; +} CSR_MLME_STOP_AGGREGATION_REQUEST; + +typedef struct CSR_MLME_TRIGGERED_GET_INDICATION +{ + CSR_DATAREF MibAttributeValue; + CSR_DATAREF Dummydataref2; + CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; + CSR_MIB_STATUS Status; + CSR_NATURAL16 ErrorIndex; + CSR_TRIGGERED_ID TriggeredId; +} CSR_MLME_TRIGGERED_GET_INDICATION; + +typedef struct CSR_SIGNAL_PRIMITIVE +{ + CSR_SIGNAL_PRIMITIVE_HEADER SignalPrimitiveHeader; + union + { + CSR_MA_PACKET_REQUEST MaPacketRequest; + CSR_MA_PACKET_CONFIRM MaPacketConfirm; + CSR_MA_PACKET_INDICATION MaPacketIndication; + CSR_MA_PACKET_CANCEL_REQUEST MaPacketCancelRequest; + CSR_MA_VIF_AVAILABILITY_RESPONSE MaVifAvailabilityResponse; + CSR_MA_VIF_AVAILABILITY_INDICATION MaVifAvailabilityIndication; + CSR_MA_PACKET_ERROR_INDICATION MaPacketErrorIndication; + CSR_MLME_RESET_REQUEST MlmeResetRequest; + CSR_MLME_RESET_CONFIRM MlmeResetConfirm; + CSR_MLME_GET_REQUEST MlmeGetRequest; + CSR_MLME_GET_CONFIRM MlmeGetConfirm; + CSR_MLME_SET_REQUEST MlmeSetRequest; + CSR_MLME_SET_CONFIRM MlmeSetConfirm; + CSR_MLME_GET_NEXT_REQUEST MlmeGetNextRequest; + CSR_MLME_GET_NEXT_CONFIRM MlmeGetNextConfirm; + CSR_MLME_POWERMGT_REQUEST MlmePowermgtRequest; + CSR_MLME_POWERMGT_CONFIRM MlmePowermgtConfirm; + CSR_MLME_SCAN_REQUEST MlmeScanRequest; + CSR_MLME_SCAN_CONFIRM MlmeScanConfirm; + CSR_MLME_HL_SYNC_REQUEST MlmeHlSyncRequest; + CSR_MLME_HL_SYNC_CONFIRM MlmeHlSyncConfirm; + CSR_MLME_MEASURE_REQUEST MlmeMeasureRequest; + CSR_MLME_MEASURE_CONFIRM MlmeMeasureConfirm; + CSR_MLME_MEASURE_INDICATION MlmeMeasureIndication; + CSR_MLME_SETKEYS_REQUEST MlmeSetkeysRequest; + CSR_MLME_SETKEYS_CONFIRM MlmeSetkeysConfirm; + CSR_MLME_DELETEKEYS_REQUEST MlmeDeletekeysRequest; + CSR_MLME_DELETEKEYS_CONFIRM MlmeDeletekeysConfirm; + CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION MlmeAutonomousScanLossIndication; + CSR_MLME_CONNECTED_INDICATION MlmeConnectedIndication; + CSR_MLME_SCAN_CANCEL_REQUEST MlmeScanCancelRequest; + CSR_MLME_HL_SYNC_CANCEL_REQUEST MlmeHlSyncCancelRequest; + CSR_MLME_HL_SYNC_CANCEL_CONFIRM MlmeHlSyncCancelConfirm; + CSR_MLME_ADD_PERIODIC_REQUEST MlmeAddPeriodicRequest; + CSR_MLME_ADD_PERIODIC_CONFIRM MlmeAddPeriodicConfirm; + CSR_MLME_DEL_PERIODIC_REQUEST MlmeDelPeriodicRequest; + CSR_MLME_DEL_PERIODIC_CONFIRM MlmeDelPeriodicConfirm; + CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST MlmeAddAutonomousScanRequest; + CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM MlmeAddAutonomousScanConfirm; + CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST MlmeDelAutonomousScanRequest; + CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM MlmeDelAutonomousScanConfirm; + CSR_MLME_SET_PACKET_FILTER_REQUEST MlmeSetPacketFilterRequest; + CSR_MLME_SET_PACKET_FILTER_CONFIRM MlmeSetPacketFilterConfirm; + CSR_MLME_STOP_MEASURE_REQUEST MlmeStopMeasureRequest; + CSR_MLME_STOP_MEASURE_CONFIRM MlmeStopMeasureConfirm; + CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST MlmePauseAutonomousScanRequest; + CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM MlmePauseAutonomousScanConfirm; + CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION MlmeAutonomousScanDoneIndication; + CSR_MLME_ADD_TRIGGERED_GET_REQUEST MlmeAddTriggeredGetRequest; + CSR_MLME_ADD_TRIGGERED_GET_CONFIRM MlmeAddTriggeredGetConfirm; + CSR_MLME_DEL_TRIGGERED_GET_REQUEST MlmeDelTriggeredGetRequest; + CSR_MLME_DEL_TRIGGERED_GET_CONFIRM MlmeDelTriggeredGetConfirm; + CSR_MLME_TRIGGERED_GET_INDICATION MlmeTriggeredGetIndication; + CSR_MLME_ADD_BLACKOUT_REQUEST MlmeAddBlackoutRequest; + CSR_MLME_ADD_BLACKOUT_CONFIRM MlmeAddBlackoutConfirm; + CSR_MLME_BLACKOUT_ENDED_INDICATION MlmeBlackoutEndedIndication; + CSR_MLME_DEL_BLACKOUT_REQUEST MlmeDelBlackoutRequest; + CSR_MLME_DEL_BLACKOUT_CONFIRM MlmeDelBlackoutConfirm; + CSR_MLME_ADD_RX_TRIGGER_REQUEST MlmeAddRxTriggerRequest; + CSR_MLME_ADD_RX_TRIGGER_CONFIRM MlmeAddRxTriggerConfirm; + CSR_MLME_DEL_RX_TRIGGER_REQUEST MlmeDelRxTriggerRequest; + CSR_MLME_DEL_RX_TRIGGER_CONFIRM MlmeDelRxTriggerConfirm; + CSR_MLME_CONNECT_STATUS_REQUEST MlmeConnectStatusRequest; + CSR_MLME_CONNECT_STATUS_CONFIRM MlmeConnectStatusConfirm; + CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST MlmeModifyBssParameterRequest; + CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM MlmeModifyBssParameterConfirm; + CSR_MLME_ADD_TEMPLATE_REQUEST MlmeAddTemplateRequest; + CSR_MLME_ADD_TEMPLATE_CONFIRM MlmeAddTemplateConfirm; + CSR_MLME_CONFIG_QUEUE_REQUEST MlmeConfigQueueRequest; + CSR_MLME_CONFIG_QUEUE_CONFIRM MlmeConfigQueueConfirm; + CSR_MLME_ADD_TSPEC_REQUEST MlmeAddTspecRequest; + CSR_MLME_ADD_TSPEC_CONFIRM MlmeAddTspecConfirm; + CSR_MLME_DEL_TSPEC_REQUEST MlmeDelTspecRequest; + CSR_MLME_DEL_TSPEC_CONFIRM MlmeDelTspecConfirm; + CSR_MLME_START_AGGREGATION_REQUEST MlmeStartAggregationRequest; + CSR_MLME_START_AGGREGATION_CONFIRM MlmeStartAggregationConfirm; + CSR_MLME_BLOCKACK_ERROR_INDICATION MlmeBlockackErrorIndication; + CSR_MLME_STOP_AGGREGATION_REQUEST MlmeStopAggregationRequest; + CSR_MLME_STOP_AGGREGATION_CONFIRM MlmeStopAggregationConfirm; + CSR_MLME_SM_START_REQUEST MlmeSmStartRequest; + CSR_MLME_SM_START_CONFIRM MlmeSmStartConfirm; + CSR_MLME_LEAVE_REQUEST MlmeLeaveRequest; + CSR_MLME_LEAVE_CONFIRM MlmeLeaveConfirm; + CSR_MLME_SET_TIM_REQUEST MlmeSetTimRequest; + CSR_MLME_SET_TIM_CONFIRM MlmeSetTimConfirm; + CSR_MLME_GET_KEY_SEQUENCE_REQUEST MlmeGetKeySequenceRequest; + CSR_MLME_GET_KEY_SEQUENCE_CONFIRM MlmeGetKeySequenceConfirm; + CSR_MLME_SET_CHANNEL_REQUEST MlmeSetChannelRequest; + CSR_MLME_SET_CHANNEL_CONFIRM MlmeSetChannelConfirm; + CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST MlmeAddMulticastAddressRequest; + CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM MlmeAddMulticastAddressConfirm; + CSR_DEBUG_STRING_INDICATION DebugStringIndication; + CSR_DEBUG_WORD16_INDICATION DebugWord16Indication; + CSR_DEBUG_GENERIC_REQUEST DebugGenericRequest; + CSR_DEBUG_GENERIC_CONFIRM DebugGenericConfirm; + CSR_DEBUG_GENERIC_INDICATION DebugGenericIndication; + } u; +} CSR_SIGNAL; + +#define SIG_FILTER_SIZE 6 + +CsrUint32 SigGetFilterPos(CsrUint16 aSigID); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.c b/drivers/staging/csr/csr_wifi_hip_ta_sampling.c new file mode 100644 index 000000000000..4fa8f607f15c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_ta_sampling.c @@ -0,0 +1,535 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_ta_sampling.c + * + * PURPOSE: + * The traffic analysis sampling module. + * This gathers data which is sent to the SME and used to analyse + * the traffic behaviour. + * + * Provides: + * unifi_ta_sampling_init - Initialise the internal state + * unifi_ta_sample - Sampling function, call this for every data packet + * + * Calls these external functions which must be provided: + * unifi_ta_indicate_sampling - Pass sample data to the SME. + * unifi_ta_indicate_protocol - Report certain data packet types to the SME. + * --------------------------------------------------------------------------- + */ + +#include "csr_wifi_hip_card_sdio.h" + +/* Maximum number of Tx frames we store each CYCLE_1, for detecting period */ +#define TA_MAX_INTERVALS_IN_C1 100 + +/* Number of intervals in CYCLE_1 (one second), for detecting periodic */ +/* Must match size of unifi_TrafficStats.intervals - 1 */ +#define TA_INTERVALS_NUM 10 + +/* Step (in msecs) between intervals, for detecting periodic */ +/* We are only interested in periods up to 100ms, i.e. between beacons */ +/* This is correct for TA_INTERVALS_NUM=10 */ +#define TA_INTERVALS_STEP 10 + + +enum ta_frame_identity +{ + TA_FRAME_UNKNOWN, + TA_FRAME_ETHERNET_UNINTERESTING, + TA_FRAME_ETHERNET_INTERESTING +}; + + +#define TA_ETHERNET_TYPE_OFFSET 6 +#define TA_LLC_HEADER_SIZE 8 +#define TA_IP_TYPE_OFFSET 17 +#define TA_UDP_SOURCE_PORT_OFFSET 28 +#define TA_UDP_DEST_PORT_OFFSET (TA_UDP_SOURCE_PORT_OFFSET + 2) +#define TA_BOOTP_CLIENT_MAC_ADDR_OFFSET 64 +#define TA_DHCP_MESSAGE_TYPE_OFFSET 278 +#define TA_DHCP_MESSAGE_TYPE_ACK 0x05 +#define TA_PROTO_TYPE_IP 0x0800 +#define TA_PROTO_TYPE_EAP 0x888E +#define TA_PROTO_TYPE_WAI 0x8864 +#define TA_PROTO_TYPE_ARP 0x0806 +#define TA_IP_TYPE_TCP 0x06 +#define TA_IP_TYPE_UDP 0x11 +#define TA_UDP_PORT_BOOTPC 0x0044 +#define TA_UDP_PORT_BOOTPS 0x0043 +#define TA_EAPOL_TYPE_OFFSET 9 +#define TA_EAPOL_TYPE_START 0x01 + +static const CsrUint8 snap_802_2[3] = { 0xAA, 0xAA, 0x03 }; +static const CsrUint8 oui_rfc1042[3] = { 0x00, 0x00, 0x00 }; +static const CsrUint8 oui_8021h[3] = { 0x00, 0x00, 0xf8 }; +static const CsrUint8 aironet_snap[5] = { 0x00, 0x40, 0x96, 0x00, 0x00 }; + + +/* + * --------------------------------------------------------------------------- + * ta_detect_protocol + * + * Internal only. + * Detects a specific protocol in a frame and indicates a TA event. + * + * Arguments: + * ta The pointer to the TA module. + * direction The direction of the frame (tx or rx). + * data Pointer to the structure that contains the data. + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrlProtocolDirection direction, + const bulk_data_desc_t *data, + const CsrUint8 *saddr, + const CsrUint8 *sta_macaddr) +{ + ta_data_t *tad = &card->ta_sampling; + CsrUint16 proto; + CsrUint16 source_port, dest_port; + CsrWifiMacAddress srcAddress; + + if (data->data_length < TA_LLC_HEADER_SIZE) + { + return TA_FRAME_UNKNOWN; + } + + if (CsrMemCmp(data->os_data_ptr, snap_802_2, 3)) + { + return TA_FRAME_UNKNOWN; + } + + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) + { + /* + * Here we would use the custom filter to detect interesting frames. + */ + } + + if (!CsrMemCmp(data->os_data_ptr + 3, oui_rfc1042, 3) || + !CsrMemCmp(data->os_data_ptr + 3, oui_8021h, 3)) + { + proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) + + data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1]; + + /* The only interesting IP frames are the DHCP */ + if (proto == TA_PROTO_TYPE_IP) + { + if (data->data_length > TA_IP_TYPE_OFFSET) + { + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) + { + ta_l4stats_t *ta_l4stats = &tad->ta_l4stats; + CsrUint8 l4proto = data->os_data_ptr[TA_IP_TYPE_OFFSET]; + + if (l4proto == TA_IP_TYPE_TCP) + { + if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) + { + ta_l4stats->txTcpBytesCount += data->data_length; + } + else + { + ta_l4stats->rxTcpBytesCount += data->data_length; + } + } + else if (l4proto == TA_IP_TYPE_UDP) + { + if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) + { + ta_l4stats->txUdpBytesCount += data->data_length; + } + else + { + ta_l4stats->rxUdpBytesCount += data->data_length; + } + } + } + + /* detect DHCP frames */ + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP) + { + /* DHCP frames are UDP frames with BOOTP ports */ + if (data->os_data_ptr[TA_IP_TYPE_OFFSET] == TA_IP_TYPE_UDP) + { + if (data->data_length > TA_UDP_DEST_PORT_OFFSET) + { + source_port = (data->os_data_ptr[TA_UDP_SOURCE_PORT_OFFSET] * 256) + + data->os_data_ptr[TA_UDP_SOURCE_PORT_OFFSET + 1]; + dest_port = (data->os_data_ptr[TA_UDP_DEST_PORT_OFFSET] * 256) + + data->os_data_ptr[TA_UDP_DEST_PORT_OFFSET + 1]; + + if (((source_port == TA_UDP_PORT_BOOTPC) && (dest_port == TA_UDP_PORT_BOOTPS)) || + ((source_port == TA_UDP_PORT_BOOTPS) && (dest_port == TA_UDP_PORT_BOOTPC))) + { + /* The DHCP should have at least a message type (request, ack, nack, etc) */ + if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6) + { + CsrMemCpy(srcAddress.a, saddr, 6); + + if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) + { + unifi_ta_indicate_protocol(card->ospriv, + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP, + direction, + &srcAddress); + return TA_FRAME_ETHERNET_UNINTERESTING; + } + + /* DHCPACK is a special indication */ + if (!CsrMemCmp(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr, 6)) + { + if (data->os_data_ptr[TA_DHCP_MESSAGE_TYPE_OFFSET] == TA_DHCP_MESSAGE_TYPE_ACK) + { + unifi_ta_indicate_protocol(card->ospriv, + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK, + direction, + &srcAddress); + } + else + { + unifi_ta_indicate_protocol(card->ospriv, + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP, + direction, + &srcAddress); + } + } + } + } + } + } + } + } + + return TA_FRAME_ETHERNET_INTERESTING; + } + + /* detect protocol type EAPOL or WAI (treated as equivalent here) */ + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL) + { + if (TA_PROTO_TYPE_EAP == proto || TA_PROTO_TYPE_WAI == proto) + { + if ((TA_PROTO_TYPE_WAI == proto) || (direction != CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) || + (data->os_data_ptr[TA_EAPOL_TYPE_OFFSET] == TA_EAPOL_TYPE_START)) + { + CsrMemCpy(srcAddress.a, saddr, 6); + unifi_ta_indicate_protocol(card->ospriv, + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL, + direction, &srcAddress); + } + return TA_FRAME_ETHERNET_UNINTERESTING; + } + } + + /* detect protocol type 0x0806 (ARP) */ + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP) + { + if (proto == TA_PROTO_TYPE_ARP) + { + CsrMemCpy(srcAddress.a, saddr, 6); + unifi_ta_indicate_protocol(card->ospriv, + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP, + direction, &srcAddress); + return TA_FRAME_ETHERNET_UNINTERESTING; + } + } + + return TA_FRAME_ETHERNET_INTERESTING; + } + else if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET) + { + /* detect Aironet frames */ + if (!CsrMemCmp(data->os_data_ptr + 3, aironet_snap, 5)) + { + CsrMemCpy(srcAddress.a, saddr, 6); + unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET, + direction, &srcAddress); + } + } + + return TA_FRAME_ETHERNET_UNINTERESTING; +} /* ta_detect_protocol() */ + + +static void tas_reset_data(ta_data_t *tad) +{ + CsrInt16 i; + + for (i = 0; i < (TA_INTERVALS_NUM + 1); i++) + { + tad->stats.intervals[i] = 0; + } + + tad->stats.rxFramesNum = 0; + tad->stats.txFramesNum = 0; + tad->stats.rxBytesCount = 0; + tad->stats.txBytesCount = 0; + tad->stats.rxMeanRate = 0; + + tad->rx_sum_rate = 0; + + tad->ta_l4stats.rxTcpBytesCount = 0; + tad->ta_l4stats.txTcpBytesCount = 0; + tad->ta_l4stats.rxUdpBytesCount = 0; + tad->ta_l4stats.txUdpBytesCount = 0; +} /* tas_reset_data() */ + + +/* + * --------------------------------------------------------------------------- + * API. + * unifi_ta_sampling_init + * + * (Re)Initialise the Traffic Analysis sampling module. + * Resets the counters and timestamps. + * + * Arguments: + * tad Pointer to a ta_data_t structure containing the + * context for this device instance. + * drv_priv An opaque pointer that the TA sampling module will + * pass in call-outs. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void unifi_ta_sampling_init(card_t *card) +{ + (void)unifi_ta_configure(card, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET, NULL); + + card->ta_sampling.packet_filter = CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE; + card->ta_sampling.traffic_type = CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL; +} /* unifi_ta_sampling_init() */ + + +/* + * --------------------------------------------------------------------------- + * API. + * unifi_ta_sample + * + * Sample a data frame for the TA module. + * This function stores all the useful information it can extract from + * the frame and detects any specific protocols. + * + * Arguments: + * tad The pointer to the TA sampling context struct. + * direction The direction of the frame (rx, tx) + * data Pointer to the frame data + * saddr Source MAC address of frame. + * timestamp Time (in msecs) that the frame was received. + * rate Reported data rate for the rx frame (0 for tx frames) + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +void unifi_ta_sample(card_t *card, + CsrWifiRouterCtrlProtocolDirection direction, + const bulk_data_desc_t *data, + const CsrUint8 *saddr, + const CsrUint8 *sta_macaddr, + CsrUint32 timestamp, + CsrUint16 rate) +{ + ta_data_t *tad = &card->ta_sampling; + enum ta_frame_identity identity; + CsrUint32 time_delta; + + + + /* Step1: Check for specific frames */ + if (tad->packet_filter != CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE) + { + identity = ta_detect_protocol(card, direction, data, saddr, sta_macaddr); + } + else + { + identity = TA_FRAME_ETHERNET_INTERESTING; + } + + + /* Step2: Update the information in the current record */ + if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX) + { + /* Update the Rx packet count and the throughput count */ + tad->stats.rxFramesNum++; + tad->stats.rxBytesCount += data->data_length; + + /* Accumulate packet Rx rates for later averaging */ + tad->rx_sum_rate += rate; + } + else + { + if (identity == TA_FRAME_ETHERNET_INTERESTING) + { + /* + * Store the period between the last and the current frame. + * There is not point storing more than TA_MAX_INTERVALS_IN_C1 periods, + * the traffic will be bursty or continuous. + */ + if (tad->stats.txFramesNum < TA_MAX_INTERVALS_IN_C1) + { + CsrUint32 interval; + CsrUint32 index_in_intervals; + + interval = timestamp - tad->tx_last_ts; + tad->tx_last_ts = timestamp; + index_in_intervals = (interval + TA_INTERVALS_STEP / 2 - 1) / TA_INTERVALS_STEP; + + /* If the interval is interesting, update the t1_intervals count */ + if (index_in_intervals <= TA_INTERVALS_NUM) + { + unifi_trace(card->ospriv, UDBG5, + "unifi_ta_sample: TX interval=%d index=%d\n", + interval, index_in_intervals); + tad->stats.intervals[index_in_intervals]++; + } + } + } + + /* Update the Tx packet count... */ + tad->stats.txFramesNum++; + /* ... and the number of bytes for throughput. */ + tad->stats.txBytesCount += data->data_length; + } + + /* + * If more than one second has elapsed since the last report, send + * another one. + */ + /* Unsigned subtraction handles wrap-around from 0xFFFFFFFF to 0 */ + time_delta = timestamp - tad->last_indication_time; + if (time_delta >= 1000) + { + /* + * rxFramesNum can be flashed in tas_reset_data() by another thread. + * Use a temp to avoid division by zero. + */ + CsrUint32 temp_rxFramesNum; + temp_rxFramesNum = tad->stats.rxFramesNum; + + /* Calculate this interval's mean frame Rx rate from the sum */ + if (temp_rxFramesNum) + { + tad->stats.rxMeanRate = tad->rx_sum_rate / temp_rxFramesNum; + } + unifi_trace(card->ospriv, UDBG5, + "unifi_ta_sample: RX fr=%lu, r=%u, sum=%lu, av=%lu\n", + tad->stats.rxFramesNum, rate, + tad->rx_sum_rate, tad->stats.rxMeanRate); + + /* + * Send the information collected in the stats struct + * to the SME and reset the counters. + */ + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) + { + CsrUint32 rxTcpThroughput = tad->ta_l4stats.rxTcpBytesCount / time_delta; + CsrUint32 txTcpThroughput = tad->ta_l4stats.txTcpBytesCount / time_delta; + CsrUint32 rxUdpThroughput = tad->ta_l4stats.rxUdpBytesCount / time_delta; + CsrUint32 txUdpThroughput = tad->ta_l4stats.txUdpBytesCount / time_delta; + + unifi_ta_indicate_l4stats(card->ospriv, + rxTcpThroughput, + txTcpThroughput, + rxUdpThroughput, + txUdpThroughput + ); + } + unifi_ta_indicate_sampling(card->ospriv, &tad->stats); + tas_reset_data(tad); + tad->last_indication_time = timestamp; + } +} /* unifi_ta_sample() */ + + +/* + * --------------------------------------------------------------------------- + * External API. + * unifi_ta_configure + * + * Configures the TA module parameters. + * + * Arguments: + * ta The pointer to the TA module. + * config_type The type of the configuration request + * config Pointer to the configuration parameters. + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code otherwise + * --------------------------------------------------------------------------- + */ +CsrResult unifi_ta_configure(card_t *card, + CsrWifiRouterCtrlTrafficConfigType config_type, + const CsrWifiRouterCtrlTrafficConfig *config) +{ + ta_data_t *tad = &card->ta_sampling; + + /* Reinitialise our data when we are reset */ + if (config_type == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET) + { + /* Reset the stats to zero */ + tas_reset_data(tad); + + /* Reset the timer variables */ + tad->tx_last_ts = 0; + tad->last_indication_time = 0; + + return CSR_RESULT_SUCCESS; + } + + if (config_type == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER) + { + tad->packet_filter = config->packetFilter; + + if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) + { + tad->custom_filter = config->customFilter; + } + + return CSR_RESULT_SUCCESS; + } + + return CSR_RESULT_SUCCESS; +} /* unifi_ta_configure() */ + + +/* + * --------------------------------------------------------------------------- + * External API. + * unifi_ta_classification + * + * Configures the current TA classification. + * + * Arguments: + * ta The pointer to the TA module. + * traffic_type The classification type + * period The traffic period if the type is periodic + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +void unifi_ta_classification(card_t *card, + CsrWifiRouterCtrlTrafficType traffic_type, + CsrUint16 period) +{ + unifi_trace(card->ospriv, UDBG3, + "Changed current ta classification to: %d\n", traffic_type); + + card->ta_sampling.traffic_type = traffic_type; +} + + diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.h b/drivers/staging/csr/csr_wifi_hip_ta_sampling.h new file mode 100644 index 000000000000..602943ecc1b6 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_ta_sampling.h @@ -0,0 +1,75 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_ta_sampling.h + * + * PURPOSE: + * This file contains Traffic Analysis definitions common to the + * sampling and analysis modules. + * + * --------------------------------------------------------------------------- + */ +#ifndef __TA_SAMPLING_H__ +#define __TA_SAMPLING_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_wifi_hip_unifi.h" + +typedef struct ta_l4stats +{ + CsrUint32 rxTcpBytesCount; + CsrUint32 txTcpBytesCount; + CsrUint32 rxUdpBytesCount; + CsrUint32 txUdpBytesCount; +} ta_l4stats_t; + +/* + * Context structure to preserve state between calls. + */ + +typedef struct ta_data +{ + /* Current packet filter configuration */ + CsrUint16 packet_filter; + + /* Current packet custom filter configuration */ + CsrWifiRouterCtrlTrafficFilter custom_filter; + + /* The timestamp of the last tx packet processed. */ + CsrUint32 tx_last_ts; + + /* The timestamp of the last packet processed. */ + CsrUint32 last_indication_time; + + /* Statistics */ + CsrWifiRouterCtrlTrafficStats stats; + + /* Current traffic classification */ + CsrWifiRouterCtrlTrafficType traffic_type; + + /* Sum of packet rx rates for this interval used to calculate mean */ + CsrUint32 rx_sum_rate; + ta_l4stats_t ta_l4stats; +} ta_data_t; + + +void unifi_ta_sampling_init(card_t *card); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TA_SAMPLING_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_udi.c b/drivers/staging/csr/csr_wifi_hip_udi.c new file mode 100644 index 000000000000..2cf028108b10 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_udi.c @@ -0,0 +1,268 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_card_udi.c + * + * PURPOSE: + * Maintain a list of callbacks to log UniFi exchanges to one or more + * debug/monitoring client applications. + * + * NOTES: + * Just call the UDI driver log fn directly for now. + * When done properly, each open() on the UDI device will install + * a log function. We will call all log fns whenever a signal is written + * to or read form the UniFi. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_card.h" + + +/* + * --------------------------------------------------------------------------- + * unifi_print_status + * + * Print status info to given character buffer. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +CsrInt32 unifi_print_status(card_t *card, CsrCharString *str, CsrInt32 *remain) +{ + CsrCharString *p = str; + sdio_config_data_t *cfg; + CsrUint16 i, n; + CsrInt32 remaining = *remain; + CsrInt32 written; +#ifdef CSR_UNSAFE_SDIO_ACCESS + CsrInt32 iostate; + CsrResult r; + static const CsrCharString *const states[] = { + "AWAKE", "DROWSY", "TORPID" + }; + #define SHARED_READ_RETRY_LIMIT 10 + CsrUint8 b; +#endif + + if (remaining <= 0) + { + return 0; + } + + i = n = 0; + written = CsrSnprintf(p, remaining, "Chip ID %u\n", + (CsrUint16)card->chip_id); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "Chip Version %04X\n", + card->chip_version); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "HIP v%u.%u\n", + (card->config_data.version >> 8) & 0xFF, + card->config_data.version & 0xFF); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "Build %lu: %s\n", + card->build_id, card->build_id_string); + UNIFI_SNPRINTF_RET(p, remaining, written); + + cfg = &card->config_data; + + written = CsrSnprintf(p, remaining, "sdio ctrl offset %u\n", + cfg->sdio_ctrl_offset); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "fromhost sigbuf handle %u\n", + cfg->fromhost_sigbuf_handle); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "tohost_sigbuf_handle %u\n", + cfg->tohost_sigbuf_handle); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "num_fromhost_sig_frags %u\n", + cfg->num_fromhost_sig_frags); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "num_tohost_sig_frags %u\n", + cfg->num_tohost_sig_frags); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "num_fromhost_data_slots %u\n", + cfg->num_fromhost_data_slots); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "num_tohost_data_slots %u\n", + cfg->num_tohost_data_slots); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "data_slot_size %u\n", + cfg->data_slot_size); + UNIFI_SNPRINTF_RET(p, remaining, written); + + /* Added by protocol version 0x0001 */ + written = CsrSnprintf(p, remaining, "overlay_size %u\n", + (CsrUint16)cfg->overlay_size); + UNIFI_SNPRINTF_RET(p, remaining, written); + + /* Added by protocol version 0x0300 */ + written = CsrSnprintf(p, remaining, "data_slot_round %u\n", + cfg->data_slot_round); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "sig_frag_size %u\n", + cfg->sig_frag_size); + UNIFI_SNPRINTF_RET(p, remaining, written); + + /* Added by protocol version 0x0300 */ + written = CsrSnprintf(p, remaining, "tohost_sig_pad %u\n", + cfg->tohost_signal_padding); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, "\nInternal state:\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n", + card->last_phy_panic_code, card->last_phy_panic_arg); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n", + card->last_mac_panic_code, card->last_mac_panic_arg); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, "fhsr: %u\n", + (CsrUint16)card->from_host_signals_r); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "fhsw: %u\n", + (CsrUint16)card->from_host_signals_w); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "thsr: %u\n", + (CsrUint16)card->to_host_signals_r); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "thsw: %u\n", + (CsrUint16)card->to_host_signals_w); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, + "fh buffer contains: %u signals, %u bytes\n", + card->fh_buffer.count, + card->fh_buffer.ptr - card->fh_buffer.buf); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, "paused: "); + UNIFI_SNPRINTF_RET(p, remaining, written); + for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++) + { + written = CsrSnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0"); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + written = CsrSnprintf(p, remaining, "\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, + "fh command q: %u waiting, %u free of %u:\n", + CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue), + CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue), + UNIFI_SOFT_COMMAND_Q_LENGTH); + UNIFI_SNPRINTF_RET(p, remaining, written); + for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) + { + written = CsrSnprintf(p, remaining, + "fh traffic q[%u]: %u waiting, %u free of %u:\n", + i, + CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]), + CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[i]), + UNIFI_SOFT_TRAFFIC_Q_LENGTH); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + + written = CsrSnprintf(p, remaining, "fh data slots free: %u\n", + card->from_host_data?CardGetFreeFromHostDataSlots(card) : 0); + UNIFI_SNPRINTF_RET(p, remaining, written); + + + written = CsrSnprintf(p, remaining, "From host data slots:"); + UNIFI_SNPRINTF_RET(p, remaining, written); + n = card->config_data.num_fromhost_data_slots; + for (i = 0; i < n && card->from_host_data; i++) + { + written = CsrSnprintf(p, remaining, " %u", + (CsrUint16)card->from_host_data[i].bd.data_length); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + written = CsrSnprintf(p, remaining, "\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + + written = CsrSnprintf(p, remaining, "To host data slots:"); + UNIFI_SNPRINTF_RET(p, remaining, written); + n = card->config_data.num_tohost_data_slots; + for (i = 0; i < n && card->to_host_data; i++) + { + written = CsrSnprintf(p, remaining, " %u", + (CsrUint16)card->to_host_data[i].data_length); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + + written = CsrSnprintf(p, remaining, "\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + +#ifdef CSR_UNSAFE_SDIO_ACCESS + written = CsrSnprintf(p, remaining, "Host State: %s\n", states[card->host_state]); + UNIFI_SNPRINTF_RET(p, remaining, written); + + r = unifi_check_io_status(card, &iostate); + if (iostate == 1) + { + written = CsrSnprintf(p, remaining, "I/O Check: F1 disabled\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + else + { + if (iostate == 1) + { + written = CsrSnprintf(p, remaining, "I/O Check: pending interrupt\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + } + + written = CsrSnprintf(p, remaining, "BH reason interrupt = %d\n", + card->bh_reason_unifi); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "BH reason host = %d\n", + card->bh_reason_host); + UNIFI_SNPRINTF_RET(p, remaining, written); + + for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) + { + r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b); + if ((r == CSR_RESULT_SUCCESS) && (!(b & 0x80))) + { + written = CsrSnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n", + b, card->from_host_signals_r); + UNIFI_SNPRINTF_RET(p, remaining, written); + break; + } + } + iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); + written = CsrSnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n", + iostate, card->to_host_signals_w); + UNIFI_SNPRINTF_RET(p, remaining, written); + } +#endif + + written = CsrSnprintf(p, remaining, "\nStats:\n"); + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "Total SDIO bytes: R=%lu W=%lu\n", + card->sdio_bytes_read, card->sdio_bytes_written); + + UNIFI_SNPRINTF_RET(p, remaining, written); + written = CsrSnprintf(p, remaining, "Interrupts generated on card: %lu\n", + card->unifi_interrupt_seq); + UNIFI_SNPRINTF_RET(p, remaining, written); + + *remain = remaining; + return (p - str); +} /* unifi_print_status() */ + + diff --git a/drivers/staging/csr/csr_wifi_hip_unifi.h b/drivers/staging/csr/csr_wifi_hip_unifi.h new file mode 100644 index 000000000000..feda2e051c21 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_unifi.h @@ -0,0 +1,852 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * + * FILE : csr_wifi_hip_unifi.h + * + * PURPOSE : Public API for the UniFi HIP core library. + * + * --------------------------------------------------------------------------- + */ +#ifndef __CSR_WIFI_HIP_UNIFI_H__ +#define __CSR_WIFI_HIP_UNIFI_H__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_HIP_TA_DISABLE +#include "csr_wifi_router_ctrl_prim.h" +#include "csr_wifi_router_prim.h" +#else +#include "csr_time.h" +#endif + +/* SDIO chip ID numbers */ + +/* Manufacturer id */ +#define SDIO_MANF_ID_CSR 0x032a + +/* Device id */ +#define SDIO_CARD_ID_UNIFI_1 0x0001 +#define SDIO_CARD_ID_UNIFI_2 0x0002 +#define SDIO_CARD_ID_UNIFI_3 0x0007 +#define SDIO_CARD_ID_UNIFI_4 0x0008 + +/* Function number for WLAN */ +#define SDIO_WLAN_FUNC_ID_UNIFI_1 0x0001 +#define SDIO_WLAN_FUNC_ID_UNIFI_2 0x0001 +#define SDIO_WLAN_FUNC_ID_UNIFI_3 0x0001 +#define SDIO_WLAN_FUNC_ID_UNIFI_4 0x0002 + +/* Maximum SDIO bus clock supported. */ +#define UNIFI_SDIO_CLOCK_MAX_HZ 50000000 /* Hz */ + +/* + * Initialisation SDIO bus clock. + * + * The initialisation clock speed should be used from when the chip has been + * reset until the first MLME-reset has been received (i.e. during firmware + * initialisation), unless UNIFI_SDIO_CLOCK_SAFE_HZ applies. + */ +#define UNIFI_SDIO_CLOCK_INIT_HZ 12500000 /* Hz */ + +/* + * Safe SDIO bus clock. + * + * The safe speed should be used when the chip is in deep sleep or + * it's state is unknown (just after reset / power on). + */ +#define UNIFI_SDIO_CLOCK_SAFE_HZ 1000000 /* Hz */ + +/* I/O default block size to use for UniFi. */ +#define UNIFI_IO_BLOCK_SIZE 64 + +#define UNIFI_WOL_OFF 0 +#define UNIFI_WOL_SDIO 1 +#define UNIFI_WOL_PIO 2 + +/* The number of Tx traffic queues */ +#define UNIFI_NO_OF_TX_QS 4 + +#define CSR_WIFI_HIP_RESERVED_HOST_TAG 0xFFFFFFFF + +/* + * The number of slots in the from-host queues. + * + * UNIFI_SOFT_TRAFFIC_Q_LENGTH is the number of slots in the traffic queues + * and there will be UNIFI_NO_OF_TX_QS of them. + * Traffic queues are used for data packets. + * + * UNIFI_SOFT_COMMAND_Q_LENGTH is the number of slots in the command queue. + * The command queue is used for MLME management requests. + * + * Queues are ring buffers and so must always have 1 unused slot. + */ +#define UNIFI_SOFT_TRAFFIC_Q_LENGTH (20 + 1) +#define UNIFI_SOFT_COMMAND_Q_LENGTH (16 + 1) + +#include "csr_types.h" /* from the synergy porting folder */ +#include "csr_framework_ext.h" /* from the synergy porting folder */ +#include "csr_sdio.h" /* from the synergy porting folder */ +#include "csr_pmem.h" /* from the synergy porting folder */ +#include "csr_util.h" /* from the synergy porting folder */ +#include "csr_formatted_io.h" /* from the synergy gsp folder */ +#include "csr_wifi_result.h" + + +/* Traffic queue ordered according to priority + * EAPOL/Uncontrolled port Queue should be the last + */ +typedef enum +{ + UNIFI_TRAFFIC_Q_BK = 0, + UNIFI_TRAFFIC_Q_BE, + UNIFI_TRAFFIC_Q_VI, + UNIFI_TRAFFIC_Q_VO, + UNIFI_TRAFFIC_Q_EAPOL, /* Non existant in HIP */ + UNIFI_TRAFFIC_Q_MAX, /* Non existant */ + UNIFI_TRAFFIC_Q_MLME /* Non existant */ +} unifi_TrafficQueue; + +/* + * Structure describing a bulk data slot. + * This structure is shared between the HIP core library and the OS + * layer. See the definition of unifi_net_data_malloc() for more details. + * + * The data_length field is used to indicate empty/occupied state. + * Needs to be defined before #include "unifi_os.h". + */ +typedef struct _bulk_data_desc +{ + const CsrUint8 *os_data_ptr; + CsrUint32 data_length; + const void *os_net_buf_ptr; + CsrUint32 net_buf_length; +} bulk_data_desc_t; + +/* Structure of an entry in the Symbol Look Up Table (SLUT). */ +typedef struct _symbol +{ + CsrUint16 id; + CsrUint32 obj; +} symbol_t; + +/* + * Header files need to be included from the current directory, + * the SME library, the synergy framework and the OS layer. + * A thin OS layer needs to be implemented in the porting exercise. + * + * Note that unifi_os.h should be included only in unifi.h + */ + +#include "unifi_os.h" + +/* + * Contains the HIP core definitions selected in the porting exercise, such as + * UNIFI_PAD_BULK_DATA_TO_BLOCK_SIZE and UNIFI_PAD_SIGNALS_TO_BLOCK_SIZE. + * Implemented in the OS layer, as part of the porting exersice. + */ +#include "unifi_config.h" + +#include "csr_wifi_hip_signals.h" /* from this dir */ + +/* + * The card structure is an opaque pointer that is used to pass context + * to the upper-edge API functions. + */ +typedef struct card card_t; + + +/* + * This structure describes all of the bulk data that 'might' be + * associated with a signal. + */ +typedef struct _bulk_data_param +{ + bulk_data_desc_t d[UNIFI_MAX_DATA_REFERENCES]; +} bulk_data_param_t; + + +/* + * This structure describes the chip and HIP core lib + * information that exposed to the OS layer. + */ +typedef struct _card_info +{ + CsrUint16 chip_id; + CsrUint16 chip_version; + CsrUint32 fw_build; + CsrUint16 fw_hip_version; + CsrUint32 sdio_block_size; +} card_info_t; + + +/* + * Mini-coredump definitions + */ +/* Definition of XAP memory ranges used by the mini-coredump system. + * Note that, these values are NOT the same as UNIFI_REGISTERS, etc + * in unifihw.h which don't allow selection of register areas for each XAP. + */ +typedef enum unifi_coredump_space +{ + UNIFI_COREDUMP_MAC_REG, + UNIFI_COREDUMP_PHY_REG, + UNIFI_COREDUMP_SH_DMEM, + UNIFI_COREDUMP_MAC_DMEM, + UNIFI_COREDUMP_PHY_DMEM, + UNIFI_COREDUMP_TRIGGER_MAGIC = 0xFEED +} unifi_coredump_space_t; + +/* Structure used to request a register value from a mini-coredump buffer */ +typedef struct unifi_coredump_req +{ + /* From user */ + CsrInt32 index; /* 0=newest, -1=oldest */ + unifi_coredump_space_t space; /* memory space */ + CsrUint32 offset; /* register offset in space */ + /* From driver */ + CsrUint32 drv_build; /* Driver build id */ + CsrUint32 chip_ver; /* Chip version */ + CsrUint32 fw_ver; /* Firmware version */ + CsrInt32 requestor; /* Requestor: 0=auto dump, 1=manual */ + CsrTime timestamp; /* time of capture by driver */ + CsrUint32 serial; /* capture serial number */ + CsrInt32 value; /* register value */ +} unifi_coredump_req_t; /* mini-coredumped reg value request */ + + +/** + * @defgroup upperedge Upper edge API + * + * The following functions are implemented in the HIP core lib. + */ + +/** + * + * Initialise the HIP core lib. + * Note that the OS layer must initialise the SDIO glue layer and obtain + * an SDIO function context, prior to this call. + * + * @param sdiopriv the SDIO function context. + * + * @param ospriv the OS layer context. + * + * @return \p card_t the HIP core lib API context. + * + * @ingroup upperedge + */ +card_t* unifi_alloc_card(CsrSdioFunction *sdiopriv, void *ospriv); + + +/** + * + * Initialise the UniFi chip. + * + * @param card the HIP core lib API context. + * + * @param led_mask the led mask to apply to UniFi. + * + * @return \b 0 if UniFi is initialized. + * + * @return \b -CSR_EIO if an I/O error occured while initializing UniFi + * + * @return \b -CSR_ENODEV if the card is no longer present. + * + * @ingroup upperedge + */ +CsrResult unifi_init_card(card_t *card, CsrInt32 led_mask); + +/** + * + * De-Initialise the HIP core lib. + * + * @param card the HIP core lib API context. + * + * @ingroup upperedge + */ +void unifi_free_card(card_t *card); + +/** + * + * Cancel all the signals pending in the HIP core lib. + * Normally used during a system suspend when the power is retained on UniFi. + * + * @param card the HIP core lib API context. + * + * @ingroup upperedge + */ +void unifi_cancel_pending_signals(card_t *card); + +/** + * + * Send a signal to UniFi. + * Normally it is called from unifi_sys_hip_req() and the OS layer + * Tx data plane. + * + * Note that the bulkdata buffers ownership is passed to the HIP core lib. + * These buffers must be allocated using unifi_net_data_malloc(). + * + * @param card the HIP core lib API context. + * + * @param sigptr pointer to the signal. + * + * @param siglen size of the signal. + * + * @param bulkdata pointer to the bulk data associated with the signal. + * + * @return \b 0 signal is sent. + * + * @return \b -CSR_EIO if an error occured while sending the signal + * + * @return \b -CSR_ENODEV if the card is no longer present. + * + * @ingroup upperedge + */ +CsrResult unifi_send_signal(card_t *card, const CsrUint8 *sigptr, + CsrUint32 siglen, + const bulk_data_param_t *bulkdata); + +/** + * + * Check if the HIP core lib has resources to send a signal. + * Normally there no need to use this function. + * + * @param card the HIP core lib API context. + * + * @param sigptr pointer to the signal. + * + * @return \b 0 if there are resources for the signal. + * + * @return \b -CSR_ENOSPC if there are not enough resources + * + * @ingroup upperedge + */ +CsrResult unifi_send_resources_available(card_t *card, const CsrUint8 *sigptr); + +/** + * + * Read the UniFi chip and the HIP core lib information. + * + * @param card the HIP core lib API context. + * + * @param card_info pointer to save the information. + * + * @ingroup upperedge + */ +void unifi_card_info(card_t *card, card_info_t *card_info); + +/** + * + * Print the UniFi I/O and Interrupt status. + * Normally it is used for debug purposes only. + * + * @param card the HIP core lib API context. + + * @param status buffer for the chip status + * + * @return \b 0 if the check was performed. + * + * @return \b -CSR_EIO if an error occured while checking the status. + * + * @return \b -CSR_ENODEV if the card is no longer present. + * + * @ingroup upperedge + */ +CsrResult unifi_check_io_status(card_t *card, CsrInt32 *status); + + +/** + * + * Run the HIP core lib Botton-Half. + * Whenever the HIP core lib want this function to be called + * by the OS layer, it calls unifi_run_bh(). + * + * @param card the HIP core lib API context. + * + * @param remaining pointer to return the time (in msecs) that this function + * should be re-scheduled. A return value of 0 means that no re-scheduling + * is required. If unifi_bh() is called before the timeout expires, + * the caller must pass in the remaining time. + * + * @return \b 0 if no error occured. + * + * @return \b -CSR_ENODEV if the card is no longer present. + * + * @return \b -CSR_E* if an error occured while running the bottom half. + * + * @ingroup upperedge + */ +CsrResult unifi_bh(card_t *card, CsrUint32 *remaining); + + +/** + * UniFi Low Power Mode (Deep Sleep Signaling) + * + * unifi_low_power_mode defines the UniFi Deep Sleep Signaling status. + * Use with unifi_configure_low_power_mode() to enable/disable + * the Deep Sleep Signaling. + */ +enum unifi_low_power_mode +{ + UNIFI_LOW_POWER_DISABLED, + UNIFI_LOW_POWER_ENABLED +}; + +/** + * Periodic Wake Host Mode + * + * unifi_periodic_wake_mode defines the Periodic Wake Host Mode. + * It can only be set to UNIFI_PERIODIC_WAKE_HOST_ENABLED if + * low_power_mode == UNIFI_LOW_POWER_ENABLED. + */ +enum unifi_periodic_wake_mode +{ + UNIFI_PERIODIC_WAKE_HOST_DISABLED, + UNIFI_PERIODIC_WAKE_HOST_ENABLED +}; + +/** + * + * Run the HIP core lib Botton-Half. + * Whenever the HIP core lib want this function to be called + * by the OS layer, it calls unifi_run_bh(). + * + * Typically, the SME is responsible for configuring these parameters, + * so unifi_sys_configure_power_mode_req() is usually implemented + * as a direct call to unifi_configure_low_power_mode(). + * + * Note: When polling mode is used instead of interrupts, + * low_power_mode must never be set to UNIFI_LOW_POWER_ENABLED. + * + * @param card the HIP core lib API context. + * + * @param low_power_mode the Low Power Mode. + * + * @param periodic_wake_mode the Periodic Wake Mode. + * + * @return \b 0 if no error occured. + * + * @return \b -CSR_E* if the request failed. + * + * @ingroup upperedge + */ +CsrResult unifi_configure_low_power_mode(card_t *card, + enum unifi_low_power_mode low_power_mode, + enum unifi_periodic_wake_mode periodic_wake_mode); + +/** + * + * Forces the UniFi chip to enter a Deep Sleep state. + * This is normally called by the OS layer when the platform suspends. + * + * Note that if the UniFi Low Power Mode is disabled this call fails. + * + * @param card the HIP core lib API context. + * + * @return \b 0 if no error occured. + * + * @return \b -CSR_ENODEV if the card is no longer present. + * + * @return \b -CSR_E* if the request failed. + * + * @ingroup upperedge + */ +CsrResult unifi_force_low_power_mode(card_t *card); + +#ifndef CSR_WIFI_HIP_TA_DISABLE +/** + * Configure the Traffic Analysis sampling + * + * Enable or disable statistics gathering. + * Enable or disable particular packet detection. + * + * @param card the HIP core context + * @param config_type the item to configure + * @param config pointer to struct containing config info + * + * @return \b 0 if configuration was successful + * + * @return \b -CSR_EINVAL if a parameter had an invalid value + * + * @ingroup upperedge + */ +CsrResult unifi_ta_configure(card_t *card, + CsrWifiRouterCtrlTrafficConfigType config_type, + const CsrWifiRouterCtrlTrafficConfig *config); + +/** + * Pass a packet for Traffic Analysis sampling + * + * @param card the HIP core context + * @param direction the direction (Rx or Tx) of the frame. + * @param data pointer to bulkdata struct containing the packet + * @param saddr the source address of the packet + * @param sta_macaddr the MAC address of the UniFi chip + * @param timestamp the current time in msecs + * + * @ingroup upperedge + */ +void unifi_ta_sample(card_t *card, + CsrWifiRouterCtrlProtocolDirection direction, + const bulk_data_desc_t *data, + const CsrUint8 *saddr, + const CsrUint8 *sta_macaddr, + CsrUint32 timestamp, + CsrUint16 rate); + +/** + * Notify the HIP core lib for a detected Traffic Classification. + * Typically, the SME is responsible for configuring these parameters, + * so unifi_sys_traffic_classification_req() is usually implemented + * as a direct call to unifi_ta_classification(). + * + * @param card the HIP core context. + * @param traffic_type the detected traffic type. + * @param period The detected period of the traffic. + * + * @ingroup upperedge + */ +void unifi_ta_classification(card_t *card, + CsrWifiRouterCtrlTrafficType traffic_type, + CsrUint16 period); + +#endif +/** + * Use software to hard reset the chip. + * This is a subset of the unifi_init_card() functionality and should + * only be used only to reset a paniced chip before a coredump is taken. + * + * @param card the HIP core context. + * + * @ingroup upperedge + */ +CsrResult unifi_card_hard_reset(card_t *card); + + +CsrResult unifi_card_readn(card_t *card, CsrUint32 unifi_addr, void *pdata, CsrUint16 len); +CsrResult unifi_card_read16(card_t *card, CsrUint32 unifi_addr, CsrUint16 *pdata); +CsrResult unifi_card_write16(card_t *card, CsrUint32 unifi_addr, CsrUint16 data); + + +enum unifi_dbg_processors_select +{ + UNIFI_PROC_MAC, + UNIFI_PROC_PHY, + UNIFI_PROC_BT, + UNIFI_PROC_BOTH, + UNIFI_PROC_INVALID +}; + +CsrResult unifi_card_stop_processor(card_t *card, enum unifi_dbg_processors_select which); + +/** + * Call-outs from the HIP core lib to the OS layer. + * The following functions need to be implemented during the porting exercise. + */ + +/** + * Selects appropriate queue according to priority + * Helps maintain uniformity in queue selection between the HIP + * and the OS layers. + * + * @param priority priority of the packet + * + * @return \b Traffic queue to which a packet of this priority belongs + * + * @ingroup upperedge + */ +unifi_TrafficQueue +unifi_frame_priority_to_queue(CSR_PRIORITY priority); + +/** + * Returns the priority corresponding to a particular Queue when that is used + * when downgrading a packet to a lower AC. + * Helps maintain uniformity in queue - priority mapping between the HIP + * and the OS layers. + * + * @param queue + * + * @return \b Highest priority corresponding to this queue + * + * @ingroup upperedge + */ +CSR_PRIORITY unifi_get_default_downgrade_priority(unifi_TrafficQueue queue); + +/** + * + * Flow control callbacks. + * unifi_pause_xmit() is called when the HIP core lib does not have any + * resources to store data packets. The OS layer needs to pause + * the Tx data plane until unifi_restart_xmit() is called. + * + * @param ospriv the OS layer context. + * + * @ingroup upperedge + */ +void unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue); +void unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue); + +/** + * + * Request to run the Bottom-Half. + * The HIP core lib calls this function to request that unifi_bh() + * needs to be run by the OS layer. It can be called anytime, i.e. + * when the unifi_bh() is running. + * Since unifi_bh() is not re-entrant, usually unifi_run_bh() sets + * an event to a thread that schedules a call to unifi_bh(). + * + * @param ospriv the OS layer context. + * + * @ingroup upperedge + */ +CsrResult unifi_run_bh(void *ospriv); + +/** + * + * Delivers a signal received from UniFi to the OS layer. + * Normally, the data signals should be delivered to the data plane + * and all the rest to the SME (unifi_sys_hip_ind()). + * + * Note that the OS layer is responsible for freeing the bulkdata + * buffers, using unifi_net_data_free(). + * + * @param ospriv the OS layer context. + * + * @param sigptr pointer to the signal. + * + * @param siglen size of the signal. + * + * @param bulkdata pointer to the bulk data associated with the signal. + * + * @ingroup upperedge + */ +void unifi_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata); + + +typedef struct +{ + CsrUint16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS]; + CsrUint16 free_fh_bulkdata_slots; + CsrUint16 free_fh_fw_slots; +} unifi_HipQosInfo; + +void unifi_get_hip_qos_info(card_t *card, unifi_HipQosInfo *hipqosinfo); + + +/** + * Functions that read a portion of a firmware file. + * + * Note: If the UniFi chip runs the f/w from ROM, the HIP core may never + * call these functions. Also, the HIP core may call these functions even if + * a f/w file is not available. In this case, it is safe to fail the request. + */ +#define UNIFI_FW_STA 1 /* Identify STA firmware file */ + +/** + * + * Ask the OS layer to initialise a read from a f/w file. + * + * @param ospriv the OS layer context. + * + * @param is_fw if 0 the request if for the loader file, if 1 the request + * is for a f/w file. + * + * @param info a card_info_t structure containing versions information. + * Note that some members of the structure may not be initialised. + * + * @return \p NULL if the file is not available, or a pointer which contains + * OS specific information for the file (typically the contents of the file) + * that the HIP core uses when calling unifi_fw_read() and unifi_fw_read_stop() + * + * @ingroup upperedge + */ +void* unifi_fw_read_start(void *ospriv, CsrInt8 is_fw, const card_info_t *info); + +/** + * + * Ask the OS layer to return a portion from a f/w file. + * + * @param ospriv the OS layer context. + * + * @param arg the OS pointer returned by unifi_fw_read_start(). + * + * @param offset the offset in the f/w file to read the read from. + * + * @param buf the buffer to store the returned data. + * + * @param len the size in bytes of the requested read. + * + * @ingroup upperedge + */ +CsrInt32 unifi_fw_read(void *ospriv, void *arg, CsrUint32 offset, void *buf, CsrUint32 len); + +/** + * + * Ask the OS layer to finish reading from a f/w file. + * + * @param ospriv the OS layer context. + * + * @param dlpriv the OS pointer returned by unifi_fw_read_start(). + * + * @ingroup upperedge + */ +void unifi_fw_read_stop(void *ospriv, void *dlpriv); + +/** + * + * Ask OS layer for a handle to a dynamically allocated firmware buffer + * (primarily intended for production test images which may need conversion) + * + * @param ospriv the OS layer context. + * + * @param fwbuf pointer to dynamically allocated buffer + * + * @param len length of provided buffer in bytes + * + * @ingroup upperedge + */ +void* unifi_fw_open_buffer(void *ospriv, void *fwbuf, CsrUint32 len); + +/** + * + * Release a handle to a dynamically allocated firmware buffer + * (primarily intended for production test images which may need conversion) + * + * @param ospriv the OS layer context. + * + * @param fwbuf pointer to dynamically allocated buffer + * + * @ingroup upperedge + */ +void unifi_fw_close_buffer(void *ospriv, void *fwbuf); + +#ifndef CSR_WIFI_HIP_TA_DISABLE +/* + * Driver must provide these. + * + * A simple implementation will just call + * unifi_sys_traffic_protocol_ind() or unifi_sys_traffic_classification_ind() + * respectively. See sme_csr_userspace/sme_userspace.c. + */ +/** + * + * Indicates a detected packet of type packet_type. + * Typically, this information is processed by the SME so + * unifi_ta_indicate_protocol() needs to schedule a call to + * unifi_sys_traffic_protocol_ind(). + * + * @param ospriv the OS layer context. + * + * @param packet_type the detected packet type. + * + * @param direction the direction of the packet (Rx, Tx). + * + * @param src_addr the source address of the packet. + * + * @ingroup upperedge + */ +void unifi_ta_indicate_protocol(void *ospriv, + CsrWifiRouterCtrlTrafficPacketType packet_type, + CsrWifiRouterCtrlProtocolDirection direction, + const CsrWifiMacAddress *src_addr); + +/** + * + * Indicates statistics for the sample data over a period. + * Typically, this information is processed by the SME so + * unifi_ta_indicate_sampling() needs to schedule a call to + * unifi_sys_traffic_sample_ind(). + * + * @param ospriv the OS layer context. + * + * @param stats the pointer to the structure that contains the statistics. + * + * @ingroup upperedge + */ +void unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats); +void unifi_ta_indicate_l4stats(void *ospriv, + CsrUint32 rxTcpThroughput, + CsrUint32 txTcpThroughput, + CsrUint32 rxUdpThroughput, + CsrUint32 txUdpThroughput); +#endif + +void unifi_rx_queue_flush(void *ospriv); + +/** + * Call-out from the SDIO glue layer. + * + * The glue layer needs to call unifi_sdio_interrupt_handler() every time + * an interrupts occurs. + * + * @param card the HIP core context. + * + * @ingroup bottomedge + */ +void unifi_sdio_interrupt_handler(card_t *card); + + +/* HELPER FUNCTIONS */ + +/* + * unifi_init() and unifi_download() implement a subset of unifi_init_card functionality + * that excludes HIP initialization. + */ +CsrResult unifi_init(card_t *card); +CsrResult unifi_download(card_t *card, CsrInt32 led_mask); + +/* + * unifi_start_processors() ensures both on-chip processors are running + */ +CsrResult unifi_start_processors(card_t *card); + +CsrResult unifi_capture_panic(card_t *card); + +/* + * Configure HIP interrupt processing mode + */ +#define CSR_WIFI_INTMODE_DEFAULT 0 +#define CSR_WIFI_INTMODE_RUN_BH_ONCE 1 /* Run BH once per interrupt */ + +void unifi_set_interrupt_mode(card_t *card, CsrUint32 mode); + +/* + * unifi_request_max_clock() requests that max SDIO clock speed is set at the + * next suitable opportunity. + */ +void unifi_request_max_sdio_clock(card_t *card); + + +/* Functions to lookup bulk data command names. */ +const CsrCharString* lookup_bulkcmd_name(CsrUint16 id); + +/* Function to log HIP's global debug buffer */ +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +void unifi_debug_buf_dump(void); +#endif + +/* Mini-coredump utility functions */ +CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req); +CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req); +CsrResult unifi_coredump_request_at_next_reset(card_t *card, CsrInt8 enable); +CsrResult unifi_coredump_init(card_t *card, CsrUint16 num_dump_buffers); +void unifi_coredump_free(card_t *card); + +#ifdef __cplusplus +} +#endif + +#endif /* __CSR_WIFI_HIP_UNIFI_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c b/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c new file mode 100644 index 000000000000..ee1970dae91c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c @@ -0,0 +1,46 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include "csr_wifi_hip_unifi.h" + +struct sig_name +{ + CsrInt16 id; + const CsrCharString *name; +}; + +static const struct sig_name Unifi_bulkcmd_names[] = { + { 0, "SignalCmd" }, + { 1, "CopyToHost" }, + { 2, "CopyToHostAck" }, + { 3, "CopyFromHost" }, + { 4, "CopyFromHostAck" }, + { 5, "ClearSlot" }, + { 6, "CopyOverlay" }, + { 7, "CopyOverlayAck" }, + { 8, "CopyFromHostAndClearSlot" }, + { 15, "Padding" } +}; + +const CsrCharString* lookup_bulkcmd_name(CsrUint16 id) +{ + if (id < 9) + { + return Unifi_bulkcmd_names[id].name; + } + if (id == 15) + { + return "Padding"; + } + + return "UNKNOWN"; +} + + diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h new file mode 100644 index 000000000000..0873b7b998e2 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h @@ -0,0 +1,76 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_unifi_udi.h + * + * PURPOSE: + * Declarations and definitions for the UniFi Debug Interface. + * + * --------------------------------------------------------------------------- + */ +#ifndef __CSR_WIFI_HIP_UNIFI_UDI_H__ +#define __CSR_WIFI_HIP_UNIFI_UDI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_signals.h" + + +/* + * Support for tracing the wire protocol. + */ +enum udi_log_direction +{ + UDI_LOG_FROM_HOST = 0x0000, + UDI_LOG_TO_HOST = 0x0001 +}; + +typedef void (*udi_func_t)(void *ospriv, CsrUint8 *sigdata, + CsrUint32 signal_len, + const bulk_data_param_t *bulkdata, + enum udi_log_direction dir); + +CsrResult unifi_set_udi_hook(card_t *card, udi_func_t udi_fn); +CsrResult unifi_remove_udi_hook(card_t *card, udi_func_t udi_fn); + + +/* + * Function to print current status info to a string. + * This is used in the linux /proc interface and might be useful + * in other systems. + */ +CsrInt32 unifi_print_status(card_t *card, CsrCharString *str, CsrInt32 *remain); + +#define UNIFI_SNPRINTF_RET(buf_p, remain, written) \ + do { \ + if (written >= remain) { \ + if (remain >= 2) { \ + buf_p[remain - 2] = '\n'; \ + buf_p[remain - 1] = 0; \ + } \ + buf_p += remain; \ + remain = 0; \ + } else if (written > 0) { \ + buf_p += written; \ + remain -= written; \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif /* __CSR_WIFI_HIP_UNIFI_UDI_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifihw.h b/drivers/staging/csr/csr_wifi_hip_unifihw.h new file mode 100644 index 000000000000..5ffd6ba38d3b --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_unifihw.h @@ -0,0 +1,67 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * + * File: csr_wifi_hip_unifihw.h + * + * Definitions of various chip registers, addresses, values etc. + * + * --------------------------------------------------------------------------- + */ +#ifndef __UNIFIHW_H__ +#define __UNIFIHW_H__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Symbol Look Up Table fingerprint. IDs are in sigs.h */ +#define SLUT_FINGERPRINT 0xD397 + + +/* Values of LoaderOperation */ +#define UNIFI_LOADER_IDLE 0x00 +#define UNIFI_LOADER_COPY 0x01 +#define UNIFI_LOADER_ERROR_MASK 0xF0 + +/* Values of BootLoaderOperation */ +#define UNIFI_BOOT_LOADER_IDLE 0x00 +#define UNIFI_BOOT_LOADER_RESTART 0x01 +#define UNIFI_BOOT_LOADER_PATCH 0x02 +#define UNIFI_BOOT_LOADER_LOAD_STA 0x10 +#define UNIFI_BOOT_LOADER_LOAD_PTEST 0x11 + + +/* Memory spaces encoded in top byte of Generic Pointer type */ +#define UNIFI_SH_DMEM 0x01 /* Shared Data Memory */ +#define UNIFI_EXT_FLASH 0x02 /* External FLASH */ +#define UNIFI_EXT_SRAM 0x03 /* External SRAM */ +#define UNIFI_REGISTERS 0x04 /* Registers */ +#define UNIFI_PHY_DMEM 0x10 /* PHY Data Memory */ +#define UNIFI_PHY_PMEM 0x11 /* PHY Program Memory */ +#define UNIFI_PHY_ROM 0x12 /* PHY ROM */ +#define UNIFI_MAC_DMEM 0x20 /* MAC Data Memory */ +#define UNIFI_MAC_PMEM 0x21 /* MAC Program Memory */ +#define UNIFI_MAC_ROM 0x22 /* MAC ROM */ +#define UNIFI_BT_DMEM 0x30 /* BT Data Memory */ +#define UNIFI_BT_PMEM 0x31 /* BT Program Memory */ +#define UNIFI_BT_ROM 0x32 /* BT ROM */ + +#define UNIFI_MAKE_GP(R, O) (((UNIFI_ ## R) << 24) | (O)) +#define UNIFI_GP_OFFSET(GP) ((GP) & 0xFFFFFF) +#define UNIFI_GP_SPACE(GP) (((GP) >> 24) & 0xFF) + +#ifdef __cplusplus +} +#endif + +#endif /* __UNIFIHW_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifiversion.h b/drivers/staging/csr/csr_wifi_hip_unifiversion.h new file mode 100644 index 000000000000..e1fdbb27a463 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_unifiversion.h @@ -0,0 +1,38 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: unifiversion.h + * + * PURPOSE: + * Version information for the portable UniFi driver. + * + * --------------------------------------------------------------------------- + */ + +#ifndef __UNIFIVERSION_H__ +#define __UNIFIVERSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The minimum version of Host Interface Protocol required by the driver. + */ +#define UNIFI_HIP_MAJOR_VERSION 9 +#define UNIFI_HIP_MINOR_VERSION 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __UNIFIVERSION_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.c b/drivers/staging/csr/csr_wifi_hip_xbv.c new file mode 100644 index 000000000000..5d0fdcce1a97 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_xbv.c @@ -0,0 +1,1075 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_xbv.c + * + * PURPOSE: + * Routines for downloading firmware to UniFi. + * + * UniFi firmware files use a nested TLV (Tag-Length-Value) format. + * + * --------------------------------------------------------------------------- + */ + +#ifdef CSR_WIFI_XBV_TEST +/* Standalone test harness */ +#include "unifi_xbv.h" +#include "csr_wifi_hip_unifihw.h" +#else +/* Normal driver build */ +#include "csr_wifi_hip_unifiversion.h" +#include "csr_wifi_hip_card.h" +#define DBG_TAG(t) +#endif + +#include "csr_wifi_hip_xbv.h" + +#define STREAM_CHECKSUM 0x6d34 /* Sum of uint16s in each patch stream */ + +/* XBV sizes used in patch conversion + */ +#define PTDL_MAX_SIZE 2048 /* Max bytes allowed per PTDL */ +#define PTDL_HDR_SIZE (4 + 2 + 6 + 2) /* sizeof(fw_id, sec_len, patch_cmd, csum) */ + +/* Struct to represent a buffer for reading firmware file */ + +typedef struct +{ + void *dlpriv; + CsrInt32 ioffset; + fwreadfn_t iread; +} ct_t; + +/* Struct to represent a TLV field */ +typedef struct +{ + CsrCharString t_name[4]; + CsrUint32 t_len; +} tag_t; + + +#define TAG_EQ(i, v) (((i)[0] == (v)[0]) && \ + ((i)[1] == (v)[1]) && \ + ((i)[2] == (v)[2]) && \ + ((i)[3] == (v)[3])) + +/* We create a small stack on the stack that contains an enum + * indicating the containing list segments, and the offset at which + * those lists end. This enables a lot more error checking. */ +typedef enum +{ + xbv_xbv1, + /*xbv_info,*/ + xbv_fw, + xbv_vers, + xbv_vand, + xbv_ptch, + xbv_other +} xbv_container; + +#define XBV_STACK_SIZE 6 +#define XBV_MAX_OFFS 0x7fffffff + +typedef struct +{ + struct + { + xbv_container container; + CsrInt32 ioffset_end; + } s[XBV_STACK_SIZE]; + CsrUint32 ptr; +} xbv_stack_t; + +static CsrInt32 read_tag(card_t *card, ct_t *ct, tag_t *tag); +static CsrInt32 read_bytes(card_t *card, ct_t *ct, void *buf, CsrUint32 len); +static CsrInt32 read_uint(card_t *card, ct_t *ct, CsrUint32 *u, CsrUint32 len); +static CsrInt32 xbv_check(xbv1_t *fwinfo, const xbv_stack_t *stack, + xbv_mode new_mode, xbv_container old_cont); +static CsrInt32 xbv_push(xbv1_t *fwinfo, xbv_stack_t *stack, + xbv_mode new_mode, xbv_container old_cont, + xbv_container new_cont, CsrUint32 ioff); + +static CsrUint32 write_uint16(void *buf, const CsrUint32 offset, + const CsrUint16 val); +static CsrUint32 write_uint32(void *buf, const CsrUint32 offset, + const CsrUint32 val); +static CsrUint32 write_bytes(void *buf, const CsrUint32 offset, + const CsrUint8 *data, const CsrUint32 len); +static CsrUint32 write_tag(void *buf, const CsrUint32 offset, + const CsrCharString *tag_str); +static CsrUint32 write_chunk(void *buf, const CsrUint32 offset, + const CsrCharString *tag_str, + const CsrUint32 payload_len); +static CsrUint16 calc_checksum(void *buf, const CsrUint32 offset, + const CsrUint32 bytes_len); +static CsrUint32 calc_patch_size(const xbv1_t *fwinfo); + +static CsrUint32 write_xbv_header(void *buf, const CsrUint32 offset, + const CsrUint32 file_payload_length); +static CsrUint32 write_ptch_header(void *buf, const CsrUint32 offset, + const CsrUint32 fw_id); +static CsrUint32 write_patchcmd(void *buf, const CsrUint32 offset, + const CsrUint32 dst_genaddr, const CsrUint16 len); +static CsrUint32 write_reset_ptdl(void *buf, const CsrUint32 offset, + const xbv1_t *fwinfo, CsrUint32 fw_id); +static CsrUint32 write_fwdl_to_ptdl(void *buf, const CsrUint32 offset, + fwreadfn_t readfn, const struct FWDL *fwdl, + const void *fw_buf, const CsrUint32 fw_id, + void *rdbuf); + +/* + * --------------------------------------------------------------------------- + * parse_xbv1 + * + * Scan the firmware file to find the TLVs we are interested in. + * Actions performed: + * - check we support the file format version in VERF + * Store these TLVs if we have a firmware image: + * - SLTP Symbol Lookup Table Pointer + * - FWDL firmware download segments + * - FWOL firmware overlay segment + * - VMEQ Register probe tests to verify matching h/w + * Store these TLVs if we have a patch file: + * - FWID the firmware build ID that this file patches + * - PTDL The actual patches + * + * The structure pointed to by fwinfo is cleared and + * 'fwinfo->mode' is set to 'unknown'. The 'fwinfo->mode' + * variable is set to 'firmware' or 'patch' once we know which + * sort of XBV file we have. + * + * Arguments: + * readfn Pointer to function to call to read from the file. + * dlpriv Opaque pointer arg to pass to readfn. + * fwinfo Pointer to fwinfo struct to fill in. + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR error code on failure + * --------------------------------------------------------------------------- + */ +CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo) +{ + ct_t ct; + tag_t tag; + xbv_stack_t stack; + + ct.dlpriv = dlpriv; + ct.ioffset = 0; + ct.iread = readfn; + + CsrMemSet(fwinfo, 0, sizeof(xbv1_t)); + fwinfo->mode = xbv_unknown; + + /* File must start with XBV1 triplet */ + if (read_tag(card, &ct, &tag) <= 0) + { + unifi_error(NULL, "File is not UniFi firmware\n"); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + DBG_TAG(tag.t_name); + + if (!TAG_EQ(tag.t_name, "XBV1")) + { + unifi_error(NULL, "File is not UniFi firmware (%s)\n", tag.t_name); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + stack.ptr = 0; + stack.s[stack.ptr].container = xbv_xbv1; + stack.s[stack.ptr].ioffset_end = XBV_MAX_OFFS; + + /* Now scan the file */ + while (1) + { + CsrInt32 n; + + n = read_tag(card, &ct, &tag); + if (n < 0) + { + unifi_error(NULL, "No tag\n"); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + if (n == 0) + { + /* End of file */ + break; + } + + DBG_TAG(tag.t_name); + + /* File format version */ + if (TAG_EQ(tag.t_name, "VERF")) + { + CsrUint32 version; + + if (xbv_check(fwinfo, &stack, xbv_unknown, xbv_xbv1) || + (tag.t_len != 2) || + read_uint(card, &ct, &version, 2)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + if (version != 0) + { + unifi_error(NULL, "Unsupported firmware file version: %d.%d\n", + version >> 8, version & 0xFF); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + } + else if (TAG_EQ(tag.t_name, "LIST")) + { + CsrCharString name[4]; + CsrUint32 list_end; + + list_end = ct.ioffset + tag.t_len; + + if (read_bytes(card, &ct, name, 4)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + DBG_TAG(name); + if (TAG_EQ(name, "FW ")) + { + if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_xbv1, xbv_fw, list_end)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + } + else if (TAG_EQ(name, "VERS")) + { + if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_fw, xbv_vers, list_end) || + (fwinfo->vers.num_vand != 0)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + } + else if (TAG_EQ(name, "VAND")) + { + struct VAND *vand; + + if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_vers, xbv_vand, list_end) || + (fwinfo->vers.num_vand >= MAX_VAND)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* Get a new VAND */ + vand = fwinfo->vand + fwinfo->vers.num_vand++; + + /* Fill it in */ + vand->first = fwinfo->num_vmeq; + vand->count = 0; + } + else if (TAG_EQ(name, "PTCH")) + { + if (xbv_push(fwinfo, &stack, xbv_patch, xbv_xbv1, xbv_ptch, list_end)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + } + else + { + /* Skip over any other lists. We dont bother to push + * the new list type now as we would only pop it at + * the end of the outer loop. */ + ct.ioffset += tag.t_len - 4; + } + } + else if (TAG_EQ(tag.t_name, "SLTP")) + { + CsrUint32 addr; + + if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || + (tag.t_len != 4) || + (fwinfo->slut_addr != 0) || + read_uint(card, &ct, &addr, 4)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + fwinfo->slut_addr = addr; + } + else if (TAG_EQ(tag.t_name, "FWDL")) + { + CsrUint32 addr; + struct FWDL *fwdl; + + if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || + (fwinfo->num_fwdl >= MAX_FWDL) || + (read_uint(card, &ct, &addr, 4))) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + fwdl = fwinfo->fwdl + fwinfo->num_fwdl++; + + fwdl->dl_size = tag.t_len - 4; + fwdl->dl_addr = addr; + fwdl->dl_offset = ct.ioffset; + + ct.ioffset += tag.t_len - 4; + } + else if (TAG_EQ(tag.t_name, "FWOV")) + { + if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || + (fwinfo->fwov.dl_size != 0) || + (fwinfo->fwov.dl_offset != 0)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + fwinfo->fwov.dl_size = tag.t_len; + fwinfo->fwov.dl_offset = ct.ioffset; + + ct.ioffset += tag.t_len; + } + else if (TAG_EQ(tag.t_name, "VMEQ")) + { + CsrUint32 temp[3]; + struct VAND *vand; + struct VMEQ *vmeq; + + if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_vand) || + (fwinfo->num_vmeq >= MAX_VMEQ) || + (fwinfo->vers.num_vand == 0) || + (tag.t_len != 8) || + read_uint(card, &ct, &temp[0], 4) || + read_uint(card, &ct, &temp[1], 2) || + read_uint(card, &ct, &temp[2], 2)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* Get the last VAND */ + vand = fwinfo->vand + (fwinfo->vers.num_vand - 1); + + /* Get a new VMEQ */ + vmeq = fwinfo->vmeq + fwinfo->num_vmeq++; + + /* Note that this VAND contains another VMEQ */ + vand->count++; + + /* Fill in the VMEQ */ + vmeq->addr = temp[0]; + vmeq->mask = (CsrUint16)temp[1]; + vmeq->value = (CsrUint16)temp[2]; + } + else if (TAG_EQ(tag.t_name, "FWID")) + { + CsrUint32 build_id; + + if (xbv_check(fwinfo, &stack, xbv_patch, xbv_ptch) || + (tag.t_len != 4) || + (fwinfo->build_id != 0) || + read_uint(card, &ct, &build_id, 4)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + fwinfo->build_id = build_id; + } + else if (TAG_EQ(tag.t_name, "PTDL")) + { + struct PTDL *ptdl; + + if (xbv_check(fwinfo, &stack, xbv_patch, xbv_ptch) || + (fwinfo->num_ptdl >= MAX_PTDL)) + { + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + /* Allocate a new PTDL */ + ptdl = fwinfo->ptdl + fwinfo->num_ptdl++; + + ptdl->dl_size = tag.t_len; + ptdl->dl_offset = ct.ioffset; + + ct.ioffset += tag.t_len; + } + else + { + /* + * If we get here it is a tag we are not interested in, + * just skip over it. + */ + ct.ioffset += tag.t_len; + } + + /* Check to see if we are at the end of the currently stacked + * segment. We could finish more than one list at a time. */ + while (ct.ioffset >= stack.s[stack.ptr].ioffset_end) + { + if (ct.ioffset > stack.s[stack.ptr].ioffset_end) + { + unifi_error(NULL, + "XBV file has overrun stack'd segment %d (%d > %d)\n", + stack.ptr, ct.ioffset, stack.s[stack.ptr].ioffset_end); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + if (stack.ptr <= 0) + { + unifi_error(NULL, "XBV file has underrun stack pointer\n"); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + stack.ptr--; + } + } + + if (stack.ptr != 0) + { + unifi_error(NULL, "Last list of XBV is not complete.\n"); + return CSR_WIFI_HIP_RESULT_INVALID_VALUE; + } + + return CSR_RESULT_SUCCESS; +} /* xbv1_parse() */ + + +/* Check the the XBV file is of a consistant sort (either firmware or + * patch) and that we are in the correct containing list type. */ +static CsrInt32 xbv_check(xbv1_t *fwinfo, const xbv_stack_t *stack, + xbv_mode new_mode, xbv_container old_cont) +{ + /* If the new file mode is unknown the current packet could be in + * either (any) type of XBV file, and we cant make a decission at + * this time. */ + if (new_mode != xbv_unknown) + { + if (fwinfo->mode == xbv_unknown) + { + fwinfo->mode = new_mode; + } + else if (fwinfo->mode != new_mode) + { + return -1; + } + } + /* If the current stack top doesn't match what we expect then the + * file is corrupt. */ + if (stack->s[stack->ptr].container != old_cont) + { + return -1; + } + return 0; +} + + +/* Make checks as above and then enter a new list */ +static CsrInt32 xbv_push(xbv1_t *fwinfo, xbv_stack_t *stack, + xbv_mode new_mode, xbv_container old_cont, + xbv_container new_cont, CsrUint32 new_ioff) +{ + if (xbv_check(fwinfo, stack, new_mode, old_cont)) + { + return -1; + } + + /* Check that our stack won't overflow. */ + if (stack->ptr >= (XBV_STACK_SIZE - 1)) + { + return -1; + } + + /* Add the new list element to the top of the stack. */ + stack->ptr++; + stack->s[stack->ptr].container = new_cont; + stack->s[stack->ptr].ioffset_end = new_ioff; + + return 0; +} + + +static CsrUint32 xbv2uint(CsrUint8 *ptr, CsrInt32 len) +{ + CsrUint32 u = 0; + CsrInt16 i; + + for (i = 0; i < len; i++) + { + CsrUint32 b; + b = ptr[i]; + u += b << (i * 8); + } + return u; +} + + +static CsrInt32 read_tag(card_t *card, ct_t *ct, tag_t *tag) +{ + CsrUint8 buf[8]; + CsrInt32 n; + + n = (*ct->iread)(card->ospriv, ct->dlpriv, ct->ioffset, buf, 8); + if (n <= 0) + { + return n; + } + + /* read the tag and length */ + if (n != 8) + { + return -1; + } + + /* get section tag */ + CsrMemCpy(tag->t_name, buf, 4); + + /* get section length */ + tag->t_len = xbv2uint(buf + 4, 4); + + ct->ioffset += 8; + + return 8; +} /* read_tag() */ + + +static CsrInt32 read_bytes(card_t *card, ct_t *ct, void *buf, CsrUint32 len) +{ + /* read the tag value */ + if ((*ct->iread)(card->ospriv, ct->dlpriv, ct->ioffset, buf, len) != (CsrInt32)len) + { + return -1; + } + + ct->ioffset += len; + + return 0; +} /* read_bytes() */ + + +static CsrInt32 read_uint(card_t *card, ct_t *ct, CsrUint32 *u, CsrUint32 len) +{ + CsrUint8 buf[4]; + + /* Integer cannot be more than 4 bytes */ + if (len > 4) + { + return -1; + } + + if (read_bytes(card, ct, buf, len)) + { + return -1; + } + + *u = xbv2uint(buf, len); + + return 0; +} /* read_uint() */ + + +static CsrUint32 write_uint16(void *buf, const CsrUint32 offset, const CsrUint16 val) +{ + CsrUint8 *dst = (CsrUint8 *)buf + offset; + *dst++ = (CsrUint8)(val & 0xff); /* LSB first */ + *dst = (CsrUint8)(val >> 8); + return sizeof(CsrUint16); +} + + +static CsrUint32 write_uint32(void *buf, const CsrUint32 offset, const CsrUint32 val) +{ + write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff)); + write_uint16(buf, offset + 2, (CsrUint16)(val >> 16)); + return sizeof(CsrUint32); +} + + +static CsrUint32 write_bytes(void *buf, const CsrUint32 offset, const CsrUint8 *data, const CsrUint32 len) +{ + CsrUint32 i; + CsrUint8 *dst = (CsrUint8 *)buf + offset; + + for (i = 0; i < len; i++) + { + *dst++ = *((CsrUint8 *)data + i); + } + return len; +} + + +static CsrUint32 write_tag(void *buf, const CsrUint32 offset, const CsrCharString *tag_str) +{ + CsrUint8 *dst = (CsrUint8 *)buf + offset; + CsrMemCpy(dst, tag_str, 4); + return 4; +} + + +static CsrUint32 write_chunk(void *buf, const CsrUint32 offset, const CsrCharString *tag_str, const CsrUint32 payload_len) +{ + CsrUint32 written = 0; + written += write_tag(buf, offset, tag_str); + written += write_uint32(buf, written + offset, (CsrUint32)payload_len); + + return written; +} + + +static CsrUint16 calc_checksum(void *buf, const CsrUint32 offset, const CsrUint32 bytes_len) +{ + CsrUint32 i; + CsrUint8 *src = (CsrUint8 *)buf + offset; + CsrUint16 sum = 0; + CsrUint16 val; + + for (i = 0; i < bytes_len / 2; i++) + { + /* Contents copied to file is LE, host might not be */ + val = (CsrUint16) * src++; /* LSB */ + val += (CsrUint16)(*src++) << 8; /* MSB */ + sum += val; + } + + /* Total of uint16s in the stream plus the stored check value + * should equal STREAM_CHECKSUM when decoded. + */ + return (STREAM_CHECKSUM - sum); +} + + +#define PTDL_RESET_DATA_SIZE 20 /* Size of reset vectors PTDL */ + +static CsrUint32 calc_patch_size(const xbv1_t *fwinfo) +{ + CsrInt16 i; + CsrUint32 size = 0; + + /* + * Work out how big an equivalent patch format file must be for this image. + * This only needs to be approximate, so long as it's large enough. + */ + if (fwinfo->mode != xbv_firmware) + { + return 0; + } + + /* Payload (which will get put into a series of PTDLs) */ + for (i = 0; i < fwinfo->num_fwdl; i++) + { + size += fwinfo->fwdl[i].dl_size; + } + + /* Another PTDL at the end containing reset vectors */ + size += PTDL_RESET_DATA_SIZE; + + /* PTDL headers. Add one for remainder, one for reset vectors */ + size += ((fwinfo->num_fwdl / PTDL_MAX_SIZE) + 2) * PTDL_HDR_SIZE; + + /* Another 1K sufficient to cover miscellaneous headers */ + size += 1024; + + return size; +} + + +static CsrUint32 write_xbv_header(void *buf, const CsrUint32 offset, const CsrUint32 file_payload_length) +{ + CsrUint32 written = 0; + + /* The length value given to the XBV chunk is the length of all subsequent + * contents of the file, excluding the 8 byte size of the XBV1 header itself + * (The added 6 bytes thus accounts for the size of the VERF) + */ + written += write_chunk(buf, offset + written, (CsrCharString *)"XBV1", file_payload_length + 6); + + written += write_chunk(buf, offset + written, (CsrCharString *)"VERF", 2); + written += write_uint16(buf, offset + written, 0); /* File version */ + + return written; +} + + +static CsrUint32 write_ptch_header(void *buf, const CsrUint32 offset, const CsrUint32 fw_id) +{ + CsrUint32 written = 0; + + /* LIST is written with a zero length, to be updated later */ + written += write_chunk(buf, offset + written, (CsrCharString *)"LIST", 0); + written += write_tag(buf, offset + written, (CsrCharString *)"PTCH"); /* List type */ + + written += write_chunk(buf, offset + written, (CsrCharString *)"FWID", 4); + written += write_uint32(buf, offset + written, fw_id); + + + return written; +} + + +#define UF_REGION_PHY 1 +#define UF_REGION_MAC 2 +#define UF_MEMPUT_MAC 0x0000 +#define UF_MEMPUT_PHY 0x1000 + +static CsrUint32 write_patchcmd(void *buf, const CsrUint32 offset, const CsrUint32 dst_genaddr, const CsrUint16 len) +{ + CsrUint32 written = 0; + CsrUint32 region = (dst_genaddr >> 28); + CsrUint16 cmd_and_len = UF_MEMPUT_MAC; + + if (region == UF_REGION_PHY) + { + cmd_and_len = UF_MEMPUT_PHY; + } + else if (region != UF_REGION_MAC) + { + return 0; /* invalid */ + } + + /* Write the command and data length */ + cmd_and_len |= len; + written += write_uint16(buf, offset + written, cmd_and_len); + + /* Write the destination generic address */ + written += write_uint16(buf, offset + written, (CsrUint16)(dst_genaddr >> 16)); + written += write_uint16(buf, offset + written, (CsrUint16)(dst_genaddr & 0xffff)); + + /* The data payload should be appended to the command */ + return written; +} + + +static CsrUint32 write_fwdl_to_ptdl(void *buf, const CsrUint32 offset, fwreadfn_t readfn, + const struct FWDL *fwdl, const void *dlpriv, + const CsrUint32 fw_id, void *fw_buf) +{ + CsrUint32 written = 0; + CsrInt16 chunks = 0; + CsrUint32 left = fwdl->dl_size; /* Bytes left in this fwdl */ + CsrUint32 dl_addr = fwdl->dl_addr; /* Target address of fwdl image on XAP */ + CsrUint32 dl_offs = fwdl->dl_offset; /* Offset of fwdl image data in source */ + CsrUint16 csum; + CsrUint32 csum_start_offs; /* first offset to include in checksum */ + CsrUint32 sec_data_len; /* section data byte count */ + CsrUint32 sec_len; /* section data + header byte count */ + + /* FWDL maps to one or more PTDLs, as max size for a PTDL is 1K words */ + while (left) + { + /* Calculate amount to be transferred */ + sec_data_len = CSRMIN(left, PTDL_MAX_SIZE - PTDL_HDR_SIZE); + sec_len = sec_data_len + PTDL_HDR_SIZE; + + /* Write PTDL header + entire PTDL size */ + written += write_chunk(buf, offset + written, (CsrCharString *)"PTDL", sec_len); + /* bug digest implies 4 bytes of padding here, but that seems wrong */ + + /* Checksum starts here */ + csum_start_offs = offset + written; + + /* Patch-chunk header: fw_id. Note that this is in XAP word order */ + written += write_uint16(buf, offset + written, (CsrUint16)(fw_id >> 16)); + written += write_uint16(buf, offset + written, (CsrUint16)(fw_id & 0xffff)); + + /* Patch-chunk header: section length in uint16s */ + written += write_uint16(buf, offset + written, (CsrUint16)(sec_len / 2)); + + + /* Write the appropriate patch command for the data's destination ptr */ + written += write_patchcmd(buf, offset + written, dl_addr, (CsrUint16)(sec_data_len / 2)); + + /* Write the data itself (limited to the max chunk length) */ + if (readfn(NULL, (void *)dlpriv, dl_offs, fw_buf, sec_data_len) < 0) + { + return 0; + } + + written += write_bytes(buf, + offset + written, + fw_buf, + sec_data_len); + + /* CsrUint16 checksum calculated over data written */ + csum = calc_checksum(buf, csum_start_offs, written - (csum_start_offs - offset)); + written += write_uint16(buf, offset + written, csum); + + left -= sec_data_len; + dl_addr += sec_data_len; + dl_offs += sec_data_len; + chunks++; + } + + return written; +} + + +#define SEC_CMD_LEN ((4 + 2) * 2) /* sizeof(cmd, vector) per XAP */ +#define PTDL_VEC_HDR_SIZE (4 + 2 + 2) /* sizeof(fw_id, sec_len, csum) */ +#define UF_MAC_START_VEC 0x00c00000 /* Start address of image on MAC */ +#define UF_PHY_START_VEC 0x00c00000 /* Start address of image on PHY */ +#define UF_MAC_START_CMD 0x6000 /* MAC "Set start address" command */ +#define UF_PHY_START_CMD 0x7000 /* PHY "Set start address" command */ + +static CsrUint32 write_reset_ptdl(void *buf, const CsrUint32 offset, const xbv1_t *fwinfo, CsrUint32 fw_id) +{ + CsrUint32 written = 0; + CsrUint16 csum; + CsrUint32 csum_start_offs; /* first offset to include in checksum */ + CsrUint32 sec_len; /* section data + header byte count */ + + sec_len = SEC_CMD_LEN + PTDL_VEC_HDR_SIZE; /* Total section byte length */ + + /* Write PTDL header + entire PTDL size */ + written += write_chunk(buf, offset + written, (CsrCharString *)"PTDL", sec_len); + + /* Checksum starts here */ + csum_start_offs = offset + written; + + /* Patch-chunk header: fw_id. Note that this is in XAP word order */ + written += write_uint16(buf, offset + written, (CsrUint16)(fw_id >> 16)); + written += write_uint16(buf, offset + written, (CsrUint16)(fw_id & 0xffff)); + + /* Patch-chunk header: section length in uint16s */ + written += write_uint16(buf, offset + written, (CsrUint16)(sec_len / 2)); + + /* + * Restart addresses to be executed on subsequent loader restart command. + */ + + /* Setup the MAC start address, note word ordering */ + written += write_uint16(buf, offset + written, UF_MAC_START_CMD); + written += write_uint16(buf, offset + written, (UF_MAC_START_VEC >> 16)); + written += write_uint16(buf, offset + written, (UF_MAC_START_VEC & 0xffff)); + + /* Setup the PHY start address, note word ordering */ + written += write_uint16(buf, offset + written, UF_PHY_START_CMD); + written += write_uint16(buf, offset + written, (UF_PHY_START_VEC >> 16)); + written += write_uint16(buf, offset + written, (UF_PHY_START_VEC & 0xffff)); + + /* CsrUint16 checksum calculated over data written */ + csum = calc_checksum(buf, csum_start_offs, written - (csum_start_offs - offset)); + written += write_uint16(buf, offset + written, csum); + + return written; +} + + +/* + * --------------------------------------------------------------------------- + * read_slut + * + * desc + * + * Arguments: + * readfn Pointer to function to call to read from the file. + * dlpriv Opaque pointer arg to pass to readfn. + * addr Offset into firmware image of SLUT. + * fwinfo Pointer to fwinfo struct to fill in. + * + * Returns: + * Number of SLUT entries in the f/w, or -1 if the image was corrupt. + * --------------------------------------------------------------------------- + */ +CsrInt32 xbv1_read_slut(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo, + symbol_t *slut, CsrUint32 slut_len) +{ + CsrInt16 i; + CsrInt32 offset; + CsrUint32 magic; + CsrUint32 count = 0; + ct_t ct; + + if (fwinfo->mode != xbv_firmware) + { + return -1; + } + + /* Find the d/l segment containing the SLUT */ + /* This relies on the SLUT being entirely contained in one segment */ + offset = -1; + for (i = 0; i < fwinfo->num_fwdl; i++) + { + if ((fwinfo->slut_addr >= fwinfo->fwdl[i].dl_addr) && + (fwinfo->slut_addr < (fwinfo->fwdl[i].dl_addr + fwinfo->fwdl[i].dl_size))) + { + offset = fwinfo->fwdl[i].dl_offset + + (fwinfo->slut_addr - fwinfo->fwdl[i].dl_addr); + } + } + if (offset < 0) + { + return -1; + } + + ct.dlpriv = dlpriv; + ct.ioffset = offset; + ct.iread = readfn; + + if (read_uint(card, &ct, &magic, 2)) + { + return -1; + } + if (magic != SLUT_FINGERPRINT) + { + return -1; + } + + while (count < slut_len) + { + CsrUint32 id, obj; + + /* Read Symbol Id */ + if (read_uint(card, &ct, &id, 2)) + { + return -1; + } + + /* Check for end of table marker */ + if (id == CSR_SLT_END) + { + break; + } + + /* Read Symbol Value */ + if (read_uint(card, &ct, &obj, 4)) + { + return -1; + } + + slut[count].id = (CsrUint16)id; + slut[count].obj = obj; + count++; + } + + return count; +} /* read_slut() */ + + +/* + * --------------------------------------------------------------------------- + * xbv_to_patch + * + * Convert (the relevant parts of) a firmware xbv file into a patch xbv + * + * Arguments: + * card + * fw_buf - pointer to xbv firmware image + * fwinfo - structure describing the firmware image + * size - pointer to location into which size of f/w is written. + * + * Returns: + * Pointer to firmware image, or NULL on error. Caller must free this + * buffer via CsrMemFree() once it's finished with. + * + * Notes: + * The input fw_buf should have been checked via xbv1_parse prior to + * calling this function, so the input image is assumed valid. + * --------------------------------------------------------------------------- + */ +#define PTCH_LIST_SIZE 16 /* sizeof PTCH+FWID chunk in LIST header */ + +void* xbv_to_patch(card_t *card, fwreadfn_t readfn, + const void *fw_buf, const xbv1_t *fwinfo, CsrUint32 *size) +{ + void *patch_buf = NULL; + CsrUint32 patch_buf_size; + CsrUint32 payload_offs = 0; /* Start of XBV payload */ + CsrInt16 i; + CsrUint32 patch_offs = 0; + CsrUint32 list_len_offs = 0; /* Offset of PTDL LIST length parameter */ + CsrUint32 ptdl_start_offs = 0; /* Offset of first PTDL chunk */ + CsrUint32 fw_id; + void *rdbuf; + + if (!fw_buf || !fwinfo || !card) + { + return NULL; + } + + if (fwinfo->mode != xbv_firmware) + { + unifi_error(NULL, "Not a firmware file\n"); + return NULL; + } + + /* Pre-allocate read buffer for chunk conversion */ + rdbuf = CsrMemAlloc(PTDL_MAX_SIZE); + if (!rdbuf) + { + unifi_error(card, "Couldn't alloc conversion buffer\n"); + return NULL; + } + + /* Loader requires patch file's build ID to match the running firmware's */ + fw_id = card->build_id; + + /* Firmware XBV1 contains VERF, optional INFO, SLUT(s), FWDL(s) */ + /* Other chunks should get skipped. */ + /* VERF should be sanity-checked against chip version */ + + /* Patch XBV1 contains VERF, optional INFO, PTCH */ + /* PTCH contains FWID, optional INFO, PTDL(s), PTDL(start_vec) */ + /* Each FWDL is split into PTDLs (each is 1024 XAP words max) */ + /* Each PTDL contains running ROM f/w version, and checksum */ + /* MAC/PHY reset addresses (known) are added into a final PTDL */ + + /* The input image has already been parsed, and loaded into fwinfo, so we + * can use that to build the output image + */ + patch_buf_size = calc_patch_size(fwinfo); + + patch_buf = (void *)CsrMemAlloc(patch_buf_size); + if (!patch_buf) + { + CsrMemFree(rdbuf); + unifi_error(NULL, "Can't malloc buffer for patch conversion\n"); + return NULL; + } + + CsrMemSet(patch_buf, 0xdd, patch_buf_size); + + /* Write XBV + VERF headers */ + patch_offs += write_xbv_header(patch_buf, patch_offs, 0); + payload_offs = patch_offs; + + /* Write patch (LIST) header */ + list_len_offs = patch_offs + 4; /* Save LIST.length offset for later update */ + patch_offs += write_ptch_header(patch_buf, patch_offs, fw_id); + + /* Save start offset of the PTDL chunks */ + ptdl_start_offs = patch_offs; + + /* Write LIST of firmware PTDL blocks */ + for (i = 0; i < fwinfo->num_fwdl; i++) + { + patch_offs += write_fwdl_to_ptdl(patch_buf, + patch_offs, + readfn, + &fwinfo->fwdl[i], + fw_buf, + fw_id, + rdbuf); + } + + /* Write restart-vector PTDL last */ + patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id); + + /* Now the length is known, update the LIST.length */ + write_uint32(patch_buf, list_len_offs, + (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE); + + /* Re write XBV headers just to fill in the correct file size */ + write_xbv_header(patch_buf, 0, (patch_offs - payload_offs)); + + unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n", + patch_offs, fw_id); + if (size) + { + *size = patch_offs; + } + CsrMemFree(rdbuf); + + return patch_buf; +} + + diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.h b/drivers/staging/csr/csr_wifi_hip_xbv.h new file mode 100644 index 000000000000..fdc4560676b8 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hip_xbv.h @@ -0,0 +1,127 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* + * --------------------------------------------------------------------------- + * FILE: csr_wifi_hip_xbv.h + * + * PURPOSE: + * Definitions and declarations for code to read XBV files - the UniFi + * firmware download file format. + * + * --------------------------------------------------------------------------- + */ +#ifndef __XBV_H__ +#define __XBV_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_XBV_TEST +/* Driver includes */ +#include "csr_wifi_hip_unifi.h" +#endif + + +struct VMEQ +{ + CsrUint32 addr; + CsrUint16 mask; + CsrUint16 value; +}; + +struct VAND +{ + CsrUint32 first; + CsrUint32 count; +}; + +struct VERS +{ + CsrUint32 num_vand; +}; + +struct FWDL +{ + CsrUint32 dl_addr; + CsrUint32 dl_size; + CsrUint32 dl_offset; +}; + +struct FWOV +{ + CsrUint32 dl_size; + CsrUint32 dl_offset; +}; + +struct PTDL +{ + CsrUint32 dl_size; + CsrUint32 dl_offset; +}; + +#define MAX_VMEQ 64 +#define MAX_VAND 64 +#define MAX_FWDL 256 +#define MAX_PTDL 256 + +/* An XBV1 file can either contain firmware or patches (at the + * moment). The 'mode' member of the xbv1_t structure tells us which + * one is the case. */ +typedef enum +{ + xbv_unknown, + xbv_firmware, + xbv_patch +} xbv_mode; + +typedef struct +{ + xbv_mode mode; + + /* Parts of a Firmware XBV1 */ + + struct VMEQ vmeq[MAX_VMEQ]; + CsrUint32 num_vmeq; + struct VAND vand[MAX_VAND]; + struct VERS vers; + + CsrUint32 slut_addr; + + /* F/W download image, possibly more than one part */ + struct FWDL fwdl[MAX_FWDL]; + CsrInt16 num_fwdl; + + /* F/W overlay image, add r not used */ + struct FWOV fwov; + + /* Parts of a Patch XBV1 */ + + CsrUint32 build_id; + + struct PTDL ptdl[MAX_PTDL]; + CsrInt16 num_ptdl; +} xbv1_t; + + +typedef CsrInt32 (*fwreadfn_t)(void *ospriv, void *dlpriv, CsrUint32 offset, void *buf, CsrUint32 len); + +CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo); +CsrInt32 xbv1_read_slut(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo, + symbol_t *slut, CsrUint32 slut_len); +void* xbv_to_patch(card_t *card, fwreadfn_t readfn, const void *fw_buf, const xbv1_t *fwinfo, + CsrUint32 *size); + +#ifdef __cplusplus +} +#endif + +#endif /* __XBV_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hostio_prim.h b/drivers/staging/csr/csr_wifi_hostio_prim.h new file mode 100644 index 000000000000..bf7c55c6e84b --- /dev/null +++ b/drivers/staging/csr/csr_wifi_hostio_prim.h @@ -0,0 +1,27 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + + +#ifndef CSR_WIFI_HOSTIO_H +#define CSR_WIFI_HOSTIO_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CSR_WIFI_HOSTIO_PRIM 0x0453 + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_HOSTIO_H */ + diff --git a/drivers/staging/csr/csr_wifi_lib.h b/drivers/staging/csr/csr_wifi_lib.h new file mode 100644 index 000000000000..4c691fc8fdfa --- /dev/null +++ b/drivers/staging/csr/csr_wifi_lib.h @@ -0,0 +1,113 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#ifndef CSR_WIFI_LIB_H__ +#define CSR_WIFI_LIB_H__ + +#include "csr_types.h" +#include "csr_wifi_fsm_event.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiFsmEventInit + * + * DESCRIPTION + * Macro to initialise the members of a CsrWifiFsmEvent. + *----------------------------------------------------------------------------*/ +#define CsrWifiFsmEventInit(evt, p_primtype, p_msgtype, p_dst, p_src) \ + (evt)->primtype = p_primtype; \ + (evt)->type = p_msgtype; \ + (evt)->destination = p_dst; \ + (evt)->source = p_src + + +/*----------------------------------------------------------------------------* + * CsrWifiEvent_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrWifiEvent + * + *----------------------------------------------------------------------------*/ +CsrWifiFsmEvent* CsrWifiEvent_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrSchedQid dst, CsrSchedQid src); + +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 value; +} CsrWifiEventCsrUint8; + +/*----------------------------------------------------------------------------* + * CsrWifiEventCsrUint8_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrWifiEventCsrUint8 + * + *----------------------------------------------------------------------------*/ +CsrWifiEventCsrUint8* CsrWifiEventCsrUint8_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrSchedQid dst, CsrSchedQid src, CsrUint8 value); + +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 value; +} CsrWifiEventCsrUint16; + +/*----------------------------------------------------------------------------* + * CsrWifiEventCsrUint16_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrWifiEventCsrUint16 + * + *----------------------------------------------------------------------------*/ +CsrWifiEventCsrUint16* CsrWifiEventCsrUint16_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrSchedQid dst, CsrSchedQid src, CsrUint16 value); + +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint32 value; +} CsrWifiEventCsrUint32; + +/*----------------------------------------------------------------------------* + * CsrWifiEventCsrUint32_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrWifiEventCsrUint32 + * + *----------------------------------------------------------------------------*/ +CsrWifiEventCsrUint32* CsrWifiEventCsrUint32_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrSchedQid dst, CsrSchedQid src, CsrUint32 value); + +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 value16; + CsrUint8 value8; +} CsrWifiEventCsrUint16CsrUint8; + +/*----------------------------------------------------------------------------* + * CsrWifiEventCsrUint16CsrUint8_struct + * + * DESCRIPTION + * Generic message creator. + * Allocates and fills in a message with the signature CsrWifiEventCsrUint16CsrUint8 + * + *----------------------------------------------------------------------------*/ +CsrWifiEventCsrUint16CsrUint8* CsrWifiEventCsrUint16CsrUint8_struct(CsrUint16 primtype, CsrUint16 msgtype, CsrSchedQid dst, CsrSchedQid src, CsrUint16 value16, CsrUint8 value8); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_msgconv.h b/drivers/staging/csr/csr_wifi_msgconv.h new file mode 100644 index 000000000000..d74e5953ad1c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_msgconv.h @@ -0,0 +1,60 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_MSGCONV_H__ +#define CSR_WIFI_MSGCONV_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_unicode.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +void CsrUint16SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint16 v); +void CsrUint24SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint32 v); +void CsrUint32SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint32 v); + +void CsrUint16DesBigEndian(CsrUint16 *v, CsrUint8 *buffer, CsrSize *offset); +void CsrUint24DesBigEndian(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset); +void CsrUint32DesBigEndian(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset); + +void CsrUint24Ser(CsrUint8 *ptr, CsrSize *len, CsrUint32 v); +void CsrUint24Des(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset); + + +CsrSize CsrWifiEventSizeof(void *msg); +CsrUint8* CsrWifiEventSer(CsrUint8 *ptr, CsrSize *len, void *msg); +void* CsrWifiEventDes(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrWifiEventCsrUint8Sizeof(void *msg); +CsrUint8* CsrWifiEventCsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void* CsrWifiEventCsrUint8Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrWifiEventCsrUint16Sizeof(void *msg); +CsrUint8* CsrWifiEventCsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void* CsrWifiEventCsrUint16Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrWifiEventCsrUint32Sizeof(void *msg); +CsrUint8* CsrWifiEventCsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void* CsrWifiEventCsrUint32Des(CsrUint8 *buffer, CsrSize length); + +CsrSize CsrWifiEventCsrUint16CsrUint8Sizeof(void *msg); +CsrUint8* CsrWifiEventCsrUint16CsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg); +void* CsrWifiEventCsrUint16CsrUint8Des(CsrUint8 *buffer, CsrSize length); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_MSGCONV_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h new file mode 100644 index 000000000000..4072c06a152d --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h @@ -0,0 +1,49 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_AP_CONVERTER_INIT_H__ +#define CSR_WIFI_NME_AP_CONVERTER_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_converter_init.h +#endif +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_converter_init.h +#endif + +#ifndef EXCLUDE_CSR_WIFI_NME_AP_MODULE + +#include "csr_msgconv.h" + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" + +extern const CsrLogPrimitiveInformation* CsrWifiNmeApTechInfoGet(void); +#endif /* CSR_LOG_ENABLE */ + +extern void CsrWifiNmeApConverterInit(void); + +#else /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */ + +#define CsrWifiNmeApConverterInit() + +#endif /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_AP_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_lib.h b/drivers/staging/csr/csr_wifi_nme_ap_lib.h new file mode 100644 index 000000000000..fc5692476ddc --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_lib.h @@ -0,0 +1,526 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_AP_LIB_H__ +#define CSR_WIFI_NME_AP_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_nme_ap_prim.h" +#include "csr_wifi_nme_task.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_lib.h +#endif +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_lib.h +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiNmeApFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_NME_AP upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_NME_AP upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiNmeApFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiNmeApFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_NME_AP downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_NME_AP downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiNmeApFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiNmeApPersCredentialTypeToString(CsrWifiNmeApPersCredentialType value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiNmeApPrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiNmeApUpstreamPrimNames[CSR_WIFI_NME_AP_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiNmeApConfigSetReqSend + + DESCRIPTION + This primitive passes AP configuration info for NME. This can be sent at + any time but will be acted upon when the AP is started again. This + information is common to both P2P GO and AP + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + apConfig - AP configuration for the NME. + apMacConfig - MAC configuration to be acted on when + CSR_WIFI_NME_AP_START.request is sent. + +*******************************************************************************/ +#define CsrWifiNmeApConfigSetReqCreate(msg__, dst__, src__, apConfig__, apMacConfig__) \ + msg__ = (CsrWifiNmeApConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_CONFIG_SET_REQ, dst__, src__); \ + msg__->apConfig = (apConfig__); \ + msg__->apMacConfig = (apMacConfig__); + +#define CsrWifiNmeApConfigSetReqSendTo(dst__, src__, apConfig__, apMacConfig__) \ + { \ + CsrWifiNmeApConfigSetReq *msg__; \ + CsrWifiNmeApConfigSetReqCreate(msg__, dst__, src__, apConfig__, apMacConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApConfigSetReqSend(src__, apConfig__, apMacConfig__) \ + CsrWifiNmeApConfigSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, apConfig__, apMacConfig__) + +/******************************************************************************* + + NAME + CsrWifiNmeApConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiNmeApConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeApConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeApConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeApConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeApConfigSetCfm *msg__; \ + CsrWifiNmeApConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApConfigSetCfmSend(dst__, status__) \ + CsrWifiNmeApConfigSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStaRemoveReqSend + + DESCRIPTION + This primitive disconnects a connected station. If keepBlocking is set to + TRUE, the station with the specified MAC address is not allowed to + connect. If the requested station is not already connected,it may be + blocked based on keepBlocking parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + staMacAddress - Mac Address of the station to be disconnected or blocked + keepBlocking - If TRUE, the station is blocked. If FALSE and the station is + connected, disconnect the station. If FALSE and the station + is not connected, no action is taken. + +*******************************************************************************/ +#define CsrWifiNmeApStaRemoveReqCreate(msg__, dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__) \ + msg__ = (CsrWifiNmeApStaRemoveReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApStaRemoveReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STA_REMOVE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->staMacAddress = (staMacAddress__); \ + msg__->keepBlocking = (keepBlocking__); + +#define CsrWifiNmeApStaRemoveReqSendTo(dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__) \ + { \ + CsrWifiNmeApStaRemoveReq *msg__; \ + CsrWifiNmeApStaRemoveReqCreate(msg__, dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStaRemoveReqSend(src__, interfaceTag__, staMacAddress__, keepBlocking__) \ + CsrWifiNmeApStaRemoveReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, staMacAddress__, keepBlocking__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStartReqSend + + DESCRIPTION + This primitive requests NME to started the AP operation. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface identifier; unique identifier of an interface + apType - AP Type specifies the Legacy AP or P2P GO operation + cloakSsid - Indicates whether the SSID should be cloaked (hidden and + not broadcast in beacon) or not + ssid - Service Set Identifier + ifIndex - Radio interface + channel - Channel number of the channel to use + apCredentials - Security credential configuration. + maxConnections - Maximum number of stations/P2P clients allowed + p2pGoParam - P2P specific GO parameters. + NOT USED FOR CURRENT RELEASE + wpsEnabled - Indicates whether WPS should be enabled or not + +*******************************************************************************/ +#define CsrWifiNmeApStartReqCreate(msg__, dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ + msg__ = (CsrWifiNmeApStartReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApStartReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_START_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->apType = (apType__); \ + msg__->cloakSsid = (cloakSsid__); \ + msg__->ssid = (ssid__); \ + msg__->ifIndex = (ifIndex__); \ + msg__->channel = (channel__); \ + msg__->apCredentials = (apCredentials__); \ + msg__->maxConnections = (maxConnections__); \ + msg__->p2pGoParam = (p2pGoParam__); \ + msg__->wpsEnabled = (wpsEnabled__); + +#define CsrWifiNmeApStartReqSendTo(dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ + { \ + CsrWifiNmeApStartReq *msg__; \ + CsrWifiNmeApStartReqCreate(msg__, dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStartReqSend(src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ + CsrWifiNmeApStartReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStartCfmSend + + DESCRIPTION + This primitive reports the result of CSR_WIFI_NME_AP_START.request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + ssid - Service Set Identifier + +*******************************************************************************/ +#define CsrWifiNmeApStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ssid__) \ + msg__ = (CsrWifiNmeApStartCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeApStartCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_START_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->ssid = (ssid__); + +#define CsrWifiNmeApStartCfmSendTo(dst__, src__, interfaceTag__, status__, ssid__) \ + { \ + CsrWifiNmeApStartCfm *msg__; \ + CsrWifiNmeApStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ssid__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStartCfmSend(dst__, interfaceTag__, status__, ssid__) \ + CsrWifiNmeApStartCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, ssid__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStationIndSend + + DESCRIPTION + This primitive indicates that a station has joined or a previously joined + station has left the BSS/group + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + mediaStatus - Indicates whether the station is connected or + disconnected + peerMacAddress - MAC address of the station + peerDeviceAddress - P2P Device Address + +*******************************************************************************/ +#define CsrWifiNmeApStationIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ + msg__ = (CsrWifiNmeApStationInd *) CsrPmemAlloc(sizeof(CsrWifiNmeApStationInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STATION_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->mediaStatus = (mediaStatus__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->peerDeviceAddress = (peerDeviceAddress__); + +#define CsrWifiNmeApStationIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ + { \ + CsrWifiNmeApStationInd *msg__; \ + CsrWifiNmeApStationIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStationIndSend(dst__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ + CsrWifiNmeApStationIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStopReqSend + + DESCRIPTION + This primitive requests NME to stop the AP operation. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiNmeApStopReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiNmeApStopReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApStopReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiNmeApStopReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiNmeApStopReq *msg__; \ + CsrWifiNmeApStopReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStopReqSend(src__, interfaceTag__) \ + CsrWifiNmeApStopReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStopIndSend + + DESCRIPTION + Indicates that AP operation had stopped because of some unrecoverable + error after AP operation was started successfully. NME sends this signal + after failing to restart the AP operation internally following an error + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + apType - Reports AP Type (P2PGO or AP) + status - Error Status + +*******************************************************************************/ +#define CsrWifiNmeApStopIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__) \ + msg__ = (CsrWifiNmeApStopInd *) CsrPmemAlloc(sizeof(CsrWifiNmeApStopInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->apType = (apType__); \ + msg__->status = (status__); + +#define CsrWifiNmeApStopIndSendTo(dst__, src__, interfaceTag__, apType__, status__) \ + { \ + CsrWifiNmeApStopInd *msg__; \ + CsrWifiNmeApStopIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStopIndSend(dst__, interfaceTag__, apType__, status__) \ + CsrWifiNmeApStopIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, apType__, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeApStopCfmSend + + DESCRIPTION + This primitive confirms that the AP operation is stopped. NME shall send + this primitive in response to the request even if AP operation has + already been stopped + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiNmeApStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiNmeApStopCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeApStopCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiNmeApStopCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiNmeApStopCfm *msg__; \ + CsrWifiNmeApStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApStopCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiNmeApStopCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeApWmmParamUpdateReqSend + + DESCRIPTION + Application uses this primitive to update the WMM parameters + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + wmmApParams - WMM Access point parameters per access category. The array + index corresponds to the ACI + wmmApBcParams - WMM station parameters per access category to be advertised + in the beacons and probe response The array index + corresponds to the ACI + +*******************************************************************************/ +#define CsrWifiNmeApWmmParamUpdateReqCreate(msg__, dst__, src__, wmmApParams__, wmmApBcParams__) \ + msg__ = (CsrWifiNmeApWmmParamUpdateReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApWmmParamUpdateReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_REQ, dst__, src__); \ + CsrMemCpy(msg__->wmmApParams, (wmmApParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); \ + CsrMemCpy(msg__->wmmApBcParams, (wmmApBcParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); + +#define CsrWifiNmeApWmmParamUpdateReqSendTo(dst__, src__, wmmApParams__, wmmApBcParams__) \ + { \ + CsrWifiNmeApWmmParamUpdateReq *msg__; \ + CsrWifiNmeApWmmParamUpdateReqCreate(msg__, dst__, src__, wmmApParams__, wmmApBcParams__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApWmmParamUpdateReqSend(src__, wmmApParams__, wmmApBcParams__) \ + CsrWifiNmeApWmmParamUpdateReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, wmmApParams__, wmmApBcParams__) + +/******************************************************************************* + + NAME + CsrWifiNmeApWmmParamUpdateCfmSend + + DESCRIPTION + A confirm for for the WMM parameters update + + PARAMETERS + queue - Destination Task Queue + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiNmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeApWmmParamUpdateCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeApWmmParamUpdateCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeApWmmParamUpdateCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeApWmmParamUpdateCfm *msg__; \ + CsrWifiNmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApWmmParamUpdateCfmSend(dst__, status__) \ + CsrWifiNmeApWmmParamUpdateCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeApWpsRegisterReqSend + + DESCRIPTION + This primitive allows the NME to accept the WPS registration from an + enrollee. Such registration procedure can be cancelled by sending + CSR_WIFI_NME_WPS_CANCEL.request. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an + interface + selectedDevicePasswordId - Selected password type + selectedConfigMethod - Selected WPS configuration method type + pin - PIN value. + Relevant if selected device password ID is PIN.4 + digit pin is passed by sending the pin digits in + pin[0]..pin[3] and rest of the contents filled + with '-'. + +*******************************************************************************/ +#define CsrWifiNmeApWpsRegisterReqCreate(msg__, dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ + msg__ = (CsrWifiNmeApWpsRegisterReq *) CsrPmemAlloc(sizeof(CsrWifiNmeApWpsRegisterReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WPS_REGISTER_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->selectedDevicePasswordId = (selectedDevicePasswordId__); \ + msg__->selectedConfigMethod = (selectedConfigMethod__); \ + CsrMemCpy(msg__->pin, (pin__), sizeof(CsrUint8) * 8); + +#define CsrWifiNmeApWpsRegisterReqSendTo(dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ + { \ + CsrWifiNmeApWpsRegisterReq *msg__; \ + CsrWifiNmeApWpsRegisterReqCreate(msg__, dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApWpsRegisterReqSend(src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ + CsrWifiNmeApWpsRegisterReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) + +/******************************************************************************* + + NAME + CsrWifiNmeApWpsRegisterCfmSend + + DESCRIPTION + This primitive reports the result of WPS procedure. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiNmeApWpsRegisterCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiNmeApWpsRegisterCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeApWpsRegisterCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WPS_REGISTER_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiNmeApWpsRegisterCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiNmeApWpsRegisterCfm *msg__; \ + CsrWifiNmeApWpsRegisterCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ + } + +#define CsrWifiNmeApWpsRegisterCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiNmeApWpsRegisterCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_AP_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_prim.h b/drivers/staging/csr/csr_wifi_nme_ap_prim.h new file mode 100644 index 000000000000..e3b56b4b44e3 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_prim.h @@ -0,0 +1,504 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_AP_PRIM_H__ +#define CSR_WIFI_NME_AP_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" +#include "csr_wifi_sme_ap_prim.h" +#include "csr_wifi_nme_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_prim.h +#endif +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_prim.h +#endif + +#define CSR_WIFI_NME_AP_PRIM (0x0426) + +typedef CsrPrim CsrWifiNmeApPrim; + + +/******************************************************************************* + + NAME + CsrWifiNmeApPersCredentialType + + DESCRIPTION + NME Credential Types + + VALUES + CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK + - Use PSK as credential. + CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE + - Use the specified passphrase as credential + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeApPersCredentialType; +#define CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK ((CsrWifiNmeApPersCredentialType) 0x00) +#define CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE ((CsrWifiNmeApPersCredentialType) 0x01) + + +/******************************************************************************* + + NAME + CsrWifiNmeApConfig + + DESCRIPTION + Structure holding AP config data. + + MEMBERS + apGroupkeyTimeout - Access point group key timeout. + apStrictGtkRekey - Access point strict GTK rekey flag. If set TRUE, the AP + shall rekey GTK every time a connected STA leaves BSS. + apGmkTimeout - Access point GMK timeout + apResponseTimeout - Response timeout + apRetransLimit - Max allowed retransmissions + +*******************************************************************************/ +typedef struct +{ + CsrUint16 apGroupkeyTimeout; + CsrBool apStrictGtkRekey; + CsrUint16 apGmkTimeout; + CsrUint16 apResponseTimeout; + CsrUint8 apRetransLimit; +} CsrWifiNmeApConfig; + +/******************************************************************************* + + NAME + CsrWifiNmeApAuthPers + + DESCRIPTION + + MEMBERS + authSupport - Credential type value (as defined in the + enumeration type). + rsnCapabilities - RSN capabilities mask + wapiCapabilities - WAPI capabilities mask + pskOrPassphrase - Credential type value (as defined in the + enumeration type). + authPers_credentials - Union containing credentials which depends + on credentialType parameter. + authPers_credentialspsk - + authPers_credentialspassphrase - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApAuthSupportMask authSupport; + CsrWifiSmeApRsnCapabilitiesMask rsnCapabilities; + CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities; + CsrWifiNmeApPersCredentialType pskOrPassphrase; + union { + CsrWifiNmePsk psk; + CsrWifiNmePassphrase passphrase; + } authPers_credentials; +} CsrWifiNmeApAuthPers; + +/******************************************************************************* + + NAME + CsrWifiNmeApCredentials + + DESCRIPTION + Structure containing the Credentials data. + + MEMBERS + authType - Authentication type + nmeAuthType - Authentication parameters + nmeAuthTypeopenSystemEmpty - + nmeAuthTypeauthwep - + nmeAuthTypeauthTypePersonal - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApAuthType authType; + union { + CsrWifiSmeEmpty openSystemEmpty; + CsrWifiSmeWepAuth authwep; + CsrWifiNmeApAuthPers authTypePersonal; + } nmeAuthType; +} CsrWifiNmeApCredentials; + + +/* Downstream */ +#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_NME_AP_CONFIG_SET_REQ ((CsrWifiNmeApPrim) (0x0000 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_WPS_REGISTER_REQ ((CsrWifiNmeApPrim) (0x0001 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_START_REQ ((CsrWifiNmeApPrim) (0x0002 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_STOP_REQ ((CsrWifiNmeApPrim) (0x0003 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_REQ ((CsrWifiNmeApPrim) (0x0004 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_STA_REMOVE_REQ ((CsrWifiNmeApPrim) (0x0005 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0005 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_NME_AP_CONFIG_SET_CFM ((CsrWifiNmeApPrim)(0x0000 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_WPS_REGISTER_CFM ((CsrWifiNmeApPrim)(0x0001 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_START_CFM ((CsrWifiNmeApPrim)(0x0002 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_STOP_CFM ((CsrWifiNmeApPrim)(0x0003 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_STOP_IND ((CsrWifiNmeApPrim)(0x0004 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_CFM ((CsrWifiNmeApPrim)(0x0005 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_AP_STATION_IND ((CsrWifiNmeApPrim)(0x0006 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_HIGHEST (0x0006 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_COUNT (CSR_WIFI_NME_AP_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiNmeApConfigSetReq + + DESCRIPTION + This primitive passes AP configuration info for NME. This can be sent at + any time but will be acted upon when the AP is started again. This + information is common to both P2P GO and AP + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + apConfig - AP configuration for the NME. + apMacConfig - MAC configuration to be acted on when + CSR_WIFI_NME_AP_START.request is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiNmeApConfig apConfig; + CsrWifiSmeApMacConfig apMacConfig; +} CsrWifiNmeApConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApWpsRegisterReq + + DESCRIPTION + This primitive allows the NME to accept the WPS registration from an + enrollee. Such registration procedure can be cancelled by sending + CSR_WIFI_NME_WPS_CANCEL.request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an + interface + selectedDevicePasswordId - Selected password type + selectedConfigMethod - Selected WPS configuration method type + pin - PIN value. + Relevant if selected device password ID is PIN.4 + digit pin is passed by sending the pin digits in + pin[0]..pin[3] and rest of the contents filled + with '-'. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeWpsDpid selectedDevicePasswordId; + CsrWifiSmeWpsConfigType selectedConfigMethod; + CsrUint8 pin[8]; +} CsrWifiNmeApWpsRegisterReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApStartReq + + DESCRIPTION + This primitive requests NME to started the AP operation. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface identifier; unique identifier of an interface + apType - AP Type specifies the Legacy AP or P2P GO operation + cloakSsid - Indicates whether the SSID should be cloaked (hidden and + not broadcast in beacon) or not + ssid - Service Set Identifier + ifIndex - Radio interface + channel - Channel number of the channel to use + apCredentials - Security credential configuration. + maxConnections - Maximum number of stations/P2P clients allowed + p2pGoParam - P2P specific GO parameters. + NOT USED FOR CURRENT RELEASE + wpsEnabled - Indicates whether WPS should be enabled or not + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeApType apType; + CsrBool cloakSsid; + CsrWifiSsid ssid; + CsrWifiSmeRadioIF ifIndex; + CsrUint8 channel; + CsrWifiNmeApCredentials apCredentials; + CsrUint8 maxConnections; + CsrWifiSmeApP2pGoConfig p2pGoParam; + CsrBool wpsEnabled; +} CsrWifiNmeApStartReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApStopReq + + DESCRIPTION + This primitive requests NME to stop the AP operation. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiNmeApStopReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApWmmParamUpdateReq + + DESCRIPTION + Application uses this primitive to update the WMM parameters + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + wmmApParams - WMM Access point parameters per access category. The array + index corresponds to the ACI + wmmApBcParams - WMM station parameters per access category to be advertised + in the beacons and probe response The array index + corresponds to the ACI + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeWmmAcParams wmmApParams[4]; + CsrWifiSmeWmmAcParams wmmApBcParams[4]; +} CsrWifiNmeApWmmParamUpdateReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApStaRemoveReq + + DESCRIPTION + This primitive disconnects a connected station. If keepBlocking is set to + TRUE, the station with the specified MAC address is not allowed to + connect. If the requested station is not already connected,it may be + blocked based on keepBlocking parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + staMacAddress - Mac Address of the station to be disconnected or blocked + keepBlocking - If TRUE, the station is blocked. If FALSE and the station is + connected, disconnect the station. If FALSE and the station + is not connected, no action is taken. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiMacAddress staMacAddress; + CsrBool keepBlocking; +} CsrWifiNmeApStaRemoveReq; + +/******************************************************************************* + + NAME + CsrWifiNmeApConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeApConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeApWpsRegisterCfm + + DESCRIPTION + This primitive reports the result of WPS procedure. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiNmeApWpsRegisterCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeApStartCfm + + DESCRIPTION + This primitive reports the result of CSR_WIFI_NME_AP_START.request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + ssid - Service Set Identifier + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSsid ssid; +} CsrWifiNmeApStartCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeApStopCfm + + DESCRIPTION + This primitive confirms that the AP operation is stopped. NME shall send + this primitive in response to the request even if AP operation has + already been stopped + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface identifier; unique identifier of an interface + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiNmeApStopCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeApStopInd + + DESCRIPTION + Indicates that AP operation had stopped because of some unrecoverable + error after AP operation was started successfully. NME sends this signal + after failing to restart the AP operation internally following an error + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + apType - Reports AP Type (P2PGO or AP) + status - Error Status + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeApType apType; + CsrResult status; +} CsrWifiNmeApStopInd; + +/******************************************************************************* + + NAME + CsrWifiNmeApWmmParamUpdateCfm + + DESCRIPTION + A confirm for for the WMM parameters update + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeApWmmParamUpdateCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeApStationInd + + DESCRIPTION + This primitive indicates that a station has joined or a previously joined + station has left the BSS/group + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + mediaStatus - Indicates whether the station is connected or + disconnected + peerMacAddress - MAC address of the station + peerDeviceAddress - P2P Device Address + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeMediaStatus mediaStatus; + CsrWifiMacAddress peerMacAddress; + CsrWifiMacAddress peerDeviceAddress; +} CsrWifiNmeApStationInd; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_AP_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_nme_ap_sef.c b/drivers/staging/csr/csr_wifi_nme_ap_sef.c new file mode 100644 index 000000000000..e048848883d5 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_sef.c @@ -0,0 +1,30 @@ +/***************************************************************************** + + FILE: csr_wifi_nme_sef.c + + (c) Cambridge Silicon Radio Limited 2010 + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#include "csr_wifi_nme_ap_sef.h" +#include "unifi_priv.h" + +void CsrWifiNmeApUpstreamStateHandlers(void* drvpriv, CsrWifiFsmEvent* msg) +{ + switch(msg->type) { + case CSR_WIFI_NME_AP_START_CFM: + CsrWifiNmeApStartCfmHandler(drvpriv, msg); + break; + case CSR_WIFI_NME_AP_STOP_CFM: + CsrWifiNmeApStopCfmHandler(drvpriv, msg); + break; + case CSR_WIFI_NME_AP_CONFIG_SET_CFM: + CsrWifiNmeApConfigSetCfmHandler(drvpriv,msg); + break; + default: + unifi_error(drvpriv, "CsrWifiNmeApUpstreamStateHandlers: unhandled NME_AP message type 0x%.4X\n",msg->type); + break; + } +} diff --git a/drivers/staging/csr/csr_wifi_nme_ap_sef.h b/drivers/staging/csr/csr_wifi_nme_ap_sef.h new file mode 100644 index 000000000000..3f353633fa5e --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_sef.h @@ -0,0 +1,31 @@ +/***************************************************************************** + FILE: csr_wifi_nme_sef.h + (c) Cambridge Silicon Radio Limited 2010 + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ +#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ + +#include "csr_wifi_nme_prim.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +void CsrWifiNmeApUpstreamStateHandlers(void* drvpriv, CsrWifiFsmEvent* msg); + + +extern void CsrWifiNmeApConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiNmeApStartCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiNmeApStopCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_serialize.h b/drivers/staging/csr/csr_wifi_nme_ap_serialize.h new file mode 100644 index 000000000000..d59abf981cde --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_ap_serialize.h @@ -0,0 +1,105 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_AP_SERIALIZE_H__ +#define CSR_WIFI_NME_AP_SERIALIZE_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_wifi_msgconv.h" + +#include "csr_wifi_nme_ap_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_serialize.h +#endif +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_serialize.h +#endif + +extern void CsrWifiNmeApPfree(void *ptr); + +extern CsrUint8* CsrWifiNmeApConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApConfigSetReqSizeof(void *msg); +extern void CsrWifiNmeApConfigSetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeApWpsRegisterReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApWpsRegisterReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApWpsRegisterReqSizeof(void *msg); +#define CsrWifiNmeApWpsRegisterReqSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStartReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStartReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStartReqSizeof(void *msg); +extern void CsrWifiNmeApStartReqSerFree(void *msg); + +#define CsrWifiNmeApStopReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeApStopReqDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeApStopReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeApStopReqSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApWmmParamUpdateReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApWmmParamUpdateReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApWmmParamUpdateReqSizeof(void *msg); +#define CsrWifiNmeApWmmParamUpdateReqSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStaRemoveReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStaRemoveReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStaRemoveReqSizeof(void *msg); +#define CsrWifiNmeApStaRemoveReqSerFree CsrWifiNmeApPfree + +#define CsrWifiNmeApConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeApConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeApConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeApConfigSetCfmSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApWpsRegisterCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApWpsRegisterCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApWpsRegisterCfmSizeof(void *msg); +#define CsrWifiNmeApWpsRegisterCfmSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStartCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStartCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStartCfmSizeof(void *msg); +#define CsrWifiNmeApStartCfmSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStopCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStopCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStopCfmSizeof(void *msg); +#define CsrWifiNmeApStopCfmSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStopIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStopIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStopIndSizeof(void *msg); +#define CsrWifiNmeApStopIndSerFree CsrWifiNmeApPfree + +#define CsrWifiNmeApWmmParamUpdateCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeApWmmParamUpdateCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeApWmmParamUpdateCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeApWmmParamUpdateCfmSerFree CsrWifiNmeApPfree + +extern CsrUint8* CsrWifiNmeApStationIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeApStationIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeApStationIndSizeof(void *msg); +#define CsrWifiNmeApStationIndSerFree CsrWifiNmeApPfree + + +#ifdef __cplusplus +} +#endif +#endif /* CSR_WIFI_NME_AP_SERIALIZE_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_nme_converter_init.h b/drivers/staging/csr/csr_wifi_nme_converter_init.h new file mode 100644 index 000000000000..6661914fb403 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_converter_init.h @@ -0,0 +1,46 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_CONVERTER_INIT_H__ +#define CSR_WIFI_NME_CONVERTER_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_converter_init.h +#endif + +#ifndef EXCLUDE_CSR_WIFI_NME_MODULE + +#include "csr_msgconv.h" + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" + +extern const CsrLogPrimitiveInformation* CsrWifiNmeTechInfoGet(void); +#endif /* CSR_LOG_ENABLE */ + +extern void CsrWifiNmeConverterInit(void); + +#else /* EXCLUDE_CSR_WIFI_NME_MODULE */ + +#define CsrWifiNmeConverterInit() + +#endif /* EXCLUDE_CSR_WIFI_NME_MODULE */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_lib.h b/drivers/staging/csr/csr_wifi_nme_lib.h new file mode 100644 index 000000000000..897afbf14666 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_lib.h @@ -0,0 +1,1056 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_LIB_H__ +#define CSR_WIFI_NME_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_nme_prim.h" +#include "csr_wifi_nme_task.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_lib.h +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiNmeFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_NME upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_NME upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiNmeFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiNmeFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_NME downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_NME downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiNmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiNmeAuthModeToString(CsrWifiNmeAuthMode value); +const CsrCharString* CsrWifiNmeBssTypeToString(CsrWifiNmeBssType value); +const CsrCharString* CsrWifiNmeCcxOptionsMaskToString(CsrWifiNmeCcxOptionsMask value); +const CsrCharString* CsrWifiNmeConfigActionToString(CsrWifiNmeConfigAction value); +const CsrCharString* CsrWifiNmeConnectionStatusToString(CsrWifiNmeConnectionStatus value); +const CsrCharString* CsrWifiNmeCredentialTypeToString(CsrWifiNmeCredentialType value); +const CsrCharString* CsrWifiNmeEapMethodToString(CsrWifiNmeEapMethod value); +const CsrCharString* CsrWifiNmeEncryptionToString(CsrWifiNmeEncryption value); +const CsrCharString* CsrWifiNmeIndicationsToString(CsrWifiNmeIndications value); +const CsrCharString* CsrWifiNmeSecErrorToString(CsrWifiNmeSecError value); +const CsrCharString* CsrWifiNmeSimCardTypeToString(CsrWifiNmeSimCardType value); +const CsrCharString* CsrWifiNmeUmtsAuthResultToString(CsrWifiNmeUmtsAuthResult value); +const CsrCharString* CsrWifiNmeWmmQosInfoToString(CsrWifiNmeWmmQosInfo value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiNmePrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiNmeUpstreamPrimNames[CSR_WIFI_NME_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiNmeDownstreamPrimNames[CSR_WIFI_NME_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiNmeConnectionStatusGetReqSend + + DESCRIPTION + Requests the current connection status of the NME. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiNmeConnectionStatusGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiNmeConnectionStatusGetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeConnectionStatusGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_CONNECTION_STATUS_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiNmeConnectionStatusGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiNmeConnectionStatusGetReq *msg__; \ + CsrWifiNmeConnectionStatusGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeConnectionStatusGetReqSend(src__, interfaceTag__) \ + CsrWifiNmeConnectionStatusGetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiNmeConnectionStatusGetCfmSend + + DESCRIPTION + Reports the connection status of the NME. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + connectionStatus - NME current connection status + +*******************************************************************************/ +#define CsrWifiNmeConnectionStatusGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStatus__) \ + msg__ = (CsrWifiNmeConnectionStatusGetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeConnectionStatusGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_CONNECTION_STATUS_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectionStatus = (connectionStatus__); + +#define CsrWifiNmeConnectionStatusGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionStatus__) \ + { \ + CsrWifiNmeConnectionStatusGetCfm *msg__; \ + CsrWifiNmeConnectionStatusGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStatus__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeConnectionStatusGetCfmSend(dst__, interfaceTag__, status__, connectionStatus__) \ + CsrWifiNmeConnectionStatusGetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, connectionStatus__) + +/******************************************************************************* + + NAME + CsrWifiNmeEventMaskSetReqSend + + DESCRIPTION + The wireless manager application may register with the NME to receive + notification of interesting events. Indications will be sent only if the + wireless manager explicitly registers to be notified of that event. + indMask is a bit mask of values defined in CsrWifiNmeIndicationsMask. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + indMask - Set mask with values from CsrWifiNmeIndications + +*******************************************************************************/ +#define CsrWifiNmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__) \ + msg__ = (CsrWifiNmeEventMaskSetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeEventMaskSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_EVENT_MASK_SET_REQ, dst__, src__); \ + msg__->indMask = (indMask__); + +#define CsrWifiNmeEventMaskSetReqSendTo(dst__, src__, indMask__) \ + { \ + CsrWifiNmeEventMaskSetReq *msg__; \ + CsrWifiNmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeEventMaskSetReqSend(src__, indMask__) \ + CsrWifiNmeEventMaskSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, indMask__) + +/******************************************************************************* + + NAME + CsrWifiNmeEventMaskSetCfmSend + + DESCRIPTION + The NME calls the primitive to report the result of the request + primitive. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiNmeEventMaskSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeEventMaskSetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeEventMaskSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_EVENT_MASK_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeEventMaskSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeEventMaskSetCfm *msg__; \ + CsrWifiNmeEventMaskSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeEventMaskSetCfmSend(dst__, status__) \ + CsrWifiNmeEventMaskSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileConnectReqSend + + DESCRIPTION + Requests the NME to attempt to connect to the specified profile. + Overrides any current connection attempt. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + profileIdentity - Identity (BSSID, SSID) of profile to be connected to. + It must match an existing profile in the NME. + +*******************************************************************************/ +#define CsrWifiNmeProfileConnectReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentity__) \ + msg__ = (CsrWifiNmeProfileConnectReq *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileConnectReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_CONNECT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->profileIdentity = (profileIdentity__); + +#define CsrWifiNmeProfileConnectReqSendTo(dst__, src__, interfaceTag__, profileIdentity__) \ + { \ + CsrWifiNmeProfileConnectReq *msg__; \ + CsrWifiNmeProfileConnectReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentity__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileConnectReqSend(src__, interfaceTag__, profileIdentity__) \ + CsrWifiNmeProfileConnectReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, profileIdentity__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileConnectCfmSend + + DESCRIPTION + Reports the status of the NME PROFILE CONNECT REQ. If unsuccessful the + connectAttempt parameters contain details of the APs that the NME + attempted to connect to before reporting the failure of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an + interface + status - Indicates the success or otherwise of the requested + operation. + connectAttemptsCount - This parameter is relevant only if + status!=CSR_WIFI_NME_STATUS_SUCCESS. + Number of connection attempt elements provided with + this primitive + connectAttempts - This parameter is relevant only if + status!=CSR_WIFI_NME_STATUS_SUCCESS. + Points to the list of connection attempt elements + provided with this primitive + Each element of the list provides information about + an AP on which the connection attempt was made and + the error that occurred during the attempt. + +*******************************************************************************/ +#define CsrWifiNmeProfileConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ + msg__ = (CsrWifiNmeProfileConnectCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileConnectCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_CONNECT_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectAttemptsCount = (connectAttemptsCount__); \ + msg__->connectAttempts = (connectAttempts__); + +#define CsrWifiNmeProfileConnectCfmSendTo(dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ + { \ + CsrWifiNmeProfileConnectCfm *msg__; \ + CsrWifiNmeProfileConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileConnectCfmSend(dst__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ + CsrWifiNmeProfileConnectCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteAllReqSend + + DESCRIPTION + Deletes all profiles present in the NME, but does NOT modify the + preferred profile list. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiNmeProfileDeleteAllReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiNmeProfileDeleteAllReq *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileDeleteAllReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ, dst__, src__); + +#define CsrWifiNmeProfileDeleteAllReqSendTo(dst__, src__) \ + { \ + CsrWifiNmeProfileDeleteAllReq *msg__; \ + CsrWifiNmeProfileDeleteAllReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileDeleteAllReqSend(src__) \ + CsrWifiNmeProfileDeleteAllReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteAllCfmSend + + DESCRIPTION + Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ. + Returns always CSR_WIFI_NME_STATUS_SUCCESS. + + PARAMETERS + queue - Destination Task Queue + status - Indicates the success or otherwise of the requested operation, but + in this case it always set to success. + +*******************************************************************************/ +#define CsrWifiNmeProfileDeleteAllCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeProfileDeleteAllCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileDeleteAllCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_ALL_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeProfileDeleteAllCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeProfileDeleteAllCfm *msg__; \ + CsrWifiNmeProfileDeleteAllCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileDeleteAllCfmSend(dst__, status__) \ + CsrWifiNmeProfileDeleteAllCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteReqSend + + DESCRIPTION + Will delete the profile with a matching identity, but does NOT modify the + preferred profile list. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + profileIdentity - Identity (BSSID, SSID) of profile to be deleted. + +*******************************************************************************/ +#define CsrWifiNmeProfileDeleteReqCreate(msg__, dst__, src__, profileIdentity__) \ + msg__ = (CsrWifiNmeProfileDeleteReq *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileDeleteReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_REQ, dst__, src__); \ + msg__->profileIdentity = (profileIdentity__); + +#define CsrWifiNmeProfileDeleteReqSendTo(dst__, src__, profileIdentity__) \ + { \ + CsrWifiNmeProfileDeleteReq *msg__; \ + CsrWifiNmeProfileDeleteReqCreate(msg__, dst__, src__, profileIdentity__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileDeleteReqSend(src__, profileIdentity__) \ + CsrWifiNmeProfileDeleteReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, profileIdentity__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteCfmSend + + DESCRIPTION + Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_REQ. + Returns CSR_WIFI_NME_STATUS_NOT_FOUND if there is no matching profile. + + PARAMETERS + queue - Destination Task Queue + status - Indicates the success or otherwise of the requested operation. + +*******************************************************************************/ +#define CsrWifiNmeProfileDeleteCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeProfileDeleteCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileDeleteCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeProfileDeleteCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeProfileDeleteCfm *msg__; \ + CsrWifiNmeProfileDeleteCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileDeleteCfmSend(dst__, status__) \ + CsrWifiNmeProfileDeleteCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDisconnectIndSend + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that informs that application that the current profile + connection has disconnected. The indication will contain information + about APs that it attempted to maintain the connection via i.e. in the + case of failed roaming. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an + interface + connectAttemptsCount - Number of connection attempt elements provided with + this primitive + connectAttempts - Points to the list of connection attempt elements + provided with this primitive + Each element of the list provides information about + an AP on which the connection attempt was made and + the error occurred during the attempt. + +*******************************************************************************/ +#define CsrWifiNmeProfileDisconnectIndCreate(msg__, dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ + msg__ = (CsrWifiNmeProfileDisconnectInd *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileDisconnectInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DISCONNECT_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->connectAttemptsCount = (connectAttemptsCount__); \ + msg__->connectAttempts = (connectAttempts__); + +#define CsrWifiNmeProfileDisconnectIndSendTo(dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ + { \ + CsrWifiNmeProfileDisconnectInd *msg__; \ + CsrWifiNmeProfileDisconnectIndCreate(msg__, dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileDisconnectIndSend(dst__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ + CsrWifiNmeProfileDisconnectIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, connectAttemptsCount__, connectAttempts__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileOrderSetReqSend + + DESCRIPTION + Defines the preferred order that profiles present in the NME should be + used during the NME auto-connect behaviour. + If profileIdentitysCount == 0, it removes any existing preferred profile + list already present in the NME, effectively disabling the auto-connect + behaviour. + NOTE: Profile identities that do not match any profile stored in the NME + are ignored during the auto-connect procedure. + NOTE: during auto-connect the NME will only attempt to join an existing + adhoc network and it will never attempt to host an adhoc network; for + hosting and adhoc network, use CSR_WIFI_NME_PROFILE_CONNECT_REQ + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an + interface + profileIdentitysCount - The number of profiles identities in the list. + profileIdentitys - Points to the list of profile identities. + +*******************************************************************************/ +#define CsrWifiNmeProfileOrderSetReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ + msg__ = (CsrWifiNmeProfileOrderSetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileOrderSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_ORDER_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->profileIdentitysCount = (profileIdentitysCount__); \ + msg__->profileIdentitys = (profileIdentitys__); + +#define CsrWifiNmeProfileOrderSetReqSendTo(dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ + { \ + CsrWifiNmeProfileOrderSetReq *msg__; \ + CsrWifiNmeProfileOrderSetReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileOrderSetReqSend(src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ + CsrWifiNmeProfileOrderSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileOrderSetCfmSend + + DESCRIPTION + Confirmation to UNIFI_NME_PROFILE_ORDER_SET.request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + +*******************************************************************************/ +#define CsrWifiNmeProfileOrderSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiNmeProfileOrderSetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileOrderSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_ORDER_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiNmeProfileOrderSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiNmeProfileOrderSetCfm *msg__; \ + CsrWifiNmeProfileOrderSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileOrderSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiNmeProfileOrderSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileSetReqSend + + DESCRIPTION + Creates or updates an existing profile in the NME that matches the unique + identity of the profile. Each profile is identified by the combination of + BSSID and SSID. The profile contains all the required credentials for + attempting to connect to the network. Creating or updating a profile via + the NME PROFILE SET REQ does NOT add the profile to the preferred profile + list within the NME used for the NME auto-connect behaviour. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + profile - Specifies the identity and credentials of the network. + +*******************************************************************************/ +#define CsrWifiNmeProfileSetReqCreate(msg__, dst__, src__, profile__) \ + msg__ = (CsrWifiNmeProfileSetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_SET_REQ, dst__, src__); \ + msg__->profile = (profile__); + +#define CsrWifiNmeProfileSetReqSendTo(dst__, src__, profile__) \ + { \ + CsrWifiNmeProfileSetReq *msg__; \ + CsrWifiNmeProfileSetReqCreate(msg__, dst__, src__, profile__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileSetReqSend(src__, profile__) \ + CsrWifiNmeProfileSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, profile__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileSetCfmSend + + DESCRIPTION + Reports the status of the NME PROFILE SET REQ; the request will only fail + if the details specified in the profile contains an invalid combination + of parameters for example specifying the profile as cloaked but not + specifying the SSID. The NME doesn't limit the number of profiles that + may be created. The NME assumes that the entity configuring it is aware + of the appropriate limits. + + PARAMETERS + queue - Destination Task Queue + status - Indicates the success or otherwise of the requested operation. + +*******************************************************************************/ +#define CsrWifiNmeProfileSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeProfileSetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeProfileSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeProfileSetCfm *msg__; \ + CsrWifiNmeProfileSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileSetCfmSend(dst__, status__) \ + CsrWifiNmeProfileSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileUpdateIndSend + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that informs that application that the contained profile has + changed. + For example, either the credentials EAP-FAST PAC file or the session data + within the profile has changed. + It is up to the application whether it stores this updated profile or + not. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + profile - The identity and credentials of the network. + +*******************************************************************************/ +#define CsrWifiNmeProfileUpdateIndCreate(msg__, dst__, src__, interfaceTag__, profile__) \ + msg__ = (CsrWifiNmeProfileUpdateInd *) CsrPmemAlloc(sizeof(CsrWifiNmeProfileUpdateInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_UPDATE_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->profile = (profile__); + +#define CsrWifiNmeProfileUpdateIndSendTo(dst__, src__, interfaceTag__, profile__) \ + { \ + CsrWifiNmeProfileUpdateInd *msg__; \ + CsrWifiNmeProfileUpdateIndCreate(msg__, dst__, src__, interfaceTag__, profile__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeProfileUpdateIndSend(dst__, interfaceTag__, profile__) \ + CsrWifiNmeProfileUpdateIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, profile__) + +/******************************************************************************* + + NAME + CsrWifiNmeSimGsmAuthIndSend + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the UICC Manager to perform a GSM + authentication on behalf of the NME. This indication is generated when + the NME is attempting to connect to a profile configured for EAP-SIM. An + application MUST register to receive this indication for the NME to + support the EAP-SIM credential types. Otherwise the NME has no route to + obtain the information from the UICC. EAP-SIM authentication requires 2 + or 3 GSM authentication rounds and therefore 2 or 3 RANDS (GSM Random + Challenges) are included. + + PARAMETERS + queue - Destination Task Queue + randsLength - GSM RAND is 16 bytes long hence valid values are 32 (2 RANDS) + or 48 (3 RANDs). + rands - 2 or 3 RANDs values. + +*******************************************************************************/ +#define CsrWifiNmeSimGsmAuthIndCreate(msg__, dst__, src__, randsLength__, rands__) \ + msg__ = (CsrWifiNmeSimGsmAuthInd *) CsrPmemAlloc(sizeof(CsrWifiNmeSimGsmAuthInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_GSM_AUTH_IND, dst__, src__); \ + msg__->randsLength = (randsLength__); \ + msg__->rands = (rands__); + +#define CsrWifiNmeSimGsmAuthIndSendTo(dst__, src__, randsLength__, rands__) \ + { \ + CsrWifiNmeSimGsmAuthInd *msg__; \ + CsrWifiNmeSimGsmAuthIndCreate(msg__, dst__, src__, randsLength__, rands__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimGsmAuthIndSend(dst__, randsLength__, rands__) \ + CsrWifiNmeSimGsmAuthIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, randsLength__, rands__) + +/******************************************************************************* + + NAME + CsrWifiNmeSimGsmAuthResSend + + DESCRIPTION + Response from the application that received the NME SIM GSM AUTH IND. For + each GSM authentication round a GSM Ciphering key (Kc) and a signed + response (SRES) are produced. Since 2 or 3 GSM authentication rounds are + used the 2 or 3 Kc's obtained respectively are combined into one buffer + and similarly the 2 or 3 SRES's obtained are combined into another + buffer. The order of Kc values (SRES values respectively) in their buffer + is the same as that of their corresponding RAND values in the incoming + indication. + + PARAMETERS + status - Indicates the outcome of the requested operation: + STATUS_SUCCESS or STATUS_ERROR + kcsLength - Length in Bytes of Kc buffer. Legal values are: 16 or 24. + kcs - Kc buffer holding 2 or 3 Kc values. + sresLength - Length in Bytes of SRES buffer. Legal values are: 8 or 12. + sres - SRES buffer holding 2 or 3 SRES values. + +*******************************************************************************/ +#define CsrWifiNmeSimGsmAuthResCreate(msg__, dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ + msg__ = (CsrWifiNmeSimGsmAuthRes *) CsrPmemAlloc(sizeof(CsrWifiNmeSimGsmAuthRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_GSM_AUTH_RES, dst__, src__); \ + msg__->status = (status__); \ + msg__->kcsLength = (kcsLength__); \ + msg__->kcs = (kcs__); \ + msg__->sresLength = (sresLength__); \ + msg__->sres = (sres__); + +#define CsrWifiNmeSimGsmAuthResSendTo(dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ + { \ + CsrWifiNmeSimGsmAuthRes *msg__; \ + CsrWifiNmeSimGsmAuthResCreate(msg__, dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimGsmAuthResSend(src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ + CsrWifiNmeSimGsmAuthResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, kcsLength__, kcs__, sresLength__, sres__) + +/******************************************************************************* + + NAME + CsrWifiNmeSimImsiGetIndSend + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the IMSI and UICC type from the UICC Manager. + This indication is generated when the NME is attempting to connect to a + profile configured for EAP-SIM/AKA. An application MUST register to + receive this indication for the NME to support the EAP-SIM/AKA credential + types. Otherwise the NME has no route to obtain the information from the + UICC. + + PARAMETERS + queue - Destination Task Queue + +*******************************************************************************/ +#define CsrWifiNmeSimImsiGetIndCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiNmeSimImsiGetInd *) CsrPmemAlloc(sizeof(CsrWifiNmeSimImsiGetInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_IMSI_GET_IND, dst__, src__); + +#define CsrWifiNmeSimImsiGetIndSendTo(dst__, src__) \ + { \ + CsrWifiNmeSimImsiGetInd *msg__; \ + CsrWifiNmeSimImsiGetIndCreate(msg__, dst__, src__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimImsiGetIndSend(dst__) \ + CsrWifiNmeSimImsiGetIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE) + +/******************************************************************************* + + NAME + CsrWifiNmeSimImsiGetResSend + + DESCRIPTION + Response from the application that received the NME SIM IMSI GET IND. + + PARAMETERS + status - Indicates the outcome of the requested operation: STATUS_SUCCESS + or STATUS_ERROR. + imsi - The value of the IMSI obtained from the UICC. + cardType - The UICC type (GSM only (SIM), UMTS only (USIM), Both). + +*******************************************************************************/ +#define CsrWifiNmeSimImsiGetResCreate(msg__, dst__, src__, status__, imsi__, cardType__) \ + msg__ = (CsrWifiNmeSimImsiGetRes *) CsrPmemAlloc(sizeof(CsrWifiNmeSimImsiGetRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_IMSI_GET_RES, dst__, src__); \ + msg__->status = (status__); \ + msg__->imsi = (imsi__); \ + msg__->cardType = (cardType__); + +#define CsrWifiNmeSimImsiGetResSendTo(dst__, src__, status__, imsi__, cardType__) \ + { \ + CsrWifiNmeSimImsiGetRes *msg__; \ + CsrWifiNmeSimImsiGetResCreate(msg__, dst__, src__, status__, imsi__, cardType__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimImsiGetResSend(src__, status__, imsi__, cardType__) \ + CsrWifiNmeSimImsiGetResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, imsi__, cardType__) + +/******************************************************************************* + + NAME + CsrWifiNmeSimUmtsAuthIndSend + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the UICC Manager to perform a UMTS + authentication on behalf of the NME. This indication is generated when + the NME is attempting to connect to a profile configured for EAP-AKA. An + application MUST register to receive this indication for the NME to + support the EAP-AKA credential types. Otherwise the NME has no route to + obtain the information from the USIM. EAP-AKA requires one UMTS + authentication round and therefore only one RAND and one AUTN values are + included. + + PARAMETERS + queue - Destination Task Queue + rand - UMTS RAND value. + autn - UMTS AUTN value. + +*******************************************************************************/ +#define CsrWifiNmeSimUmtsAuthIndCreate(msg__, dst__, src__, rand__, autn__) \ + msg__ = (CsrWifiNmeSimUmtsAuthInd *) CsrPmemAlloc(sizeof(CsrWifiNmeSimUmtsAuthInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_UMTS_AUTH_IND, dst__, src__); \ + CsrMemCpy(msg__->rand, (rand__), sizeof(CsrUint8) * 16); \ + CsrMemCpy(msg__->autn, (autn__), sizeof(CsrUint8) * 16); + +#define CsrWifiNmeSimUmtsAuthIndSendTo(dst__, src__, rand__, autn__) \ + { \ + CsrWifiNmeSimUmtsAuthInd *msg__; \ + CsrWifiNmeSimUmtsAuthIndCreate(msg__, dst__, src__, rand__, autn__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimUmtsAuthIndSend(dst__, rand__, autn__) \ + CsrWifiNmeSimUmtsAuthIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, rand__, autn__) + +/******************************************************************************* + + NAME + CsrWifiNmeSimUmtsAuthResSend + + DESCRIPTION + Response from the application that received the NME SIM UMTS AUTH IND. + The values of umtsCipherKey, umtsIntegrityKey, resParameterLength and + resParameter are only meanigful when result = UMTS_AUTH_RESULT_SUCCESS. + The value of auts is only meaningful when + result=UMTS_AUTH_RESULT_SYNC_FAIL. + + PARAMETERS + status - Indicates the outcome of the requested operation: + STATUS_SUCCESS or STATUS_ERROR. + result - The result of UMTS authentication as performed by the + UICC which could be: Success, Authentication Reject or + Synchronisation Failure. For all these 3 outcomes the + value of status is success. + umtsCipherKey - The UMTS Cipher Key as calculated and returned by the + UICC. + umtsIntegrityKey - The UMTS Integrity Key as calculated and returned by + the UICC. + resParameterLength - The length (in bytes) of the RES parameter (min=4; max + = 16). + resParameter - The RES parameter as calculated and returned by the + UICC. + auts - The AUTS parameter as calculated and returned by the + UICC. + +*******************************************************************************/ +#define CsrWifiNmeSimUmtsAuthResCreate(msg__, dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ + msg__ = (CsrWifiNmeSimUmtsAuthRes *) CsrPmemAlloc(sizeof(CsrWifiNmeSimUmtsAuthRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_UMTS_AUTH_RES, dst__, src__); \ + msg__->status = (status__); \ + msg__->result = (result__); \ + CsrMemCpy(msg__->umtsCipherKey, (umtsCipherKey__), sizeof(CsrUint8) * 16); \ + CsrMemCpy(msg__->umtsIntegrityKey, (umtsIntegrityKey__), sizeof(CsrUint8) * 16); \ + msg__->resParameterLength = (resParameterLength__); \ + msg__->resParameter = (resParameter__); \ + CsrMemCpy(msg__->auts, (auts__), sizeof(CsrUint8) * 14); + +#define CsrWifiNmeSimUmtsAuthResSendTo(dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ + { \ + CsrWifiNmeSimUmtsAuthRes *msg__; \ + CsrWifiNmeSimUmtsAuthResCreate(msg__, dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeSimUmtsAuthResSend(src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ + CsrWifiNmeSimUmtsAuthResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCancelReqSend + + DESCRIPTION + Requests the NME to cancel any WPS procedure that it is currently + performing. This includes WPS registrar activities started because of + CSR_WIFI_NME_AP_REGISTER.request + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiNmeWpsCancelReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiNmeWpsCancelReq *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsCancelReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CANCEL_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiNmeWpsCancelReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiNmeWpsCancelReq *msg__; \ + CsrWifiNmeWpsCancelReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsCancelReqSend(src__, interfaceTag__) \ + CsrWifiNmeWpsCancelReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCancelCfmSend + + DESCRIPTION + Reports the status of the NME WPS REQ, the request is always SUCCESSFUL. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Only returns CSR_WIFI_NME_STATUS_SUCCESS + +*******************************************************************************/ +#define CsrWifiNmeWpsCancelCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiNmeWpsCancelCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsCancelCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CANCEL_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiNmeWpsCancelCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiNmeWpsCancelCfm *msg__; \ + CsrWifiNmeWpsCancelCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsCancelCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiNmeWpsCancelCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCfmSend + + DESCRIPTION + Reports the status of the NME WPS REQ. + If CSR_WIFI_NME_STATUS_SUCCESS, the profile parameter contains the + identity and credentials of the AP. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + profile - This parameter is relevant only if + status==CSR_WIFI_NME_STATUS_SUCCESS. + The identity and credentials of the network. + +*******************************************************************************/ +#define CsrWifiNmeWpsCfmCreate(msg__, dst__, src__, interfaceTag__, status__, profile__) \ + msg__ = (CsrWifiNmeWpsCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->profile = (profile__); + +#define CsrWifiNmeWpsCfmSendTo(dst__, src__, interfaceTag__, status__, profile__) \ + { \ + CsrWifiNmeWpsCfm *msg__; \ + CsrWifiNmeWpsCfmCreate(msg__, dst__, src__, interfaceTag__, status__, profile__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsCfmSend(dst__, interfaceTag__, status__, profile__) \ + CsrWifiNmeWpsCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, profile__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsConfigSetReqSend + + DESCRIPTION + This primitive passes the WPS information for the device to NME. This may + be accepted only if no interface is active. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + wpsConfig - WPS config. + +*******************************************************************************/ +#define CsrWifiNmeWpsConfigSetReqCreate(msg__, dst__, src__, wpsConfig__) \ + msg__ = (CsrWifiNmeWpsConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CONFIG_SET_REQ, dst__, src__); \ + msg__->wpsConfig = (wpsConfig__); + +#define CsrWifiNmeWpsConfigSetReqSendTo(dst__, src__, wpsConfig__) \ + { \ + CsrWifiNmeWpsConfigSetReq *msg__; \ + CsrWifiNmeWpsConfigSetReqCreate(msg__, dst__, src__, wpsConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsConfigSetReqSend(src__, wpsConfig__) \ + CsrWifiNmeWpsConfigSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, wpsConfig__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsConfigSetCfmSend + + DESCRIPTION + Confirm. + + PARAMETERS + queue - Destination Task Queue + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiNmeWpsConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiNmeWpsConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiNmeWpsConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiNmeWpsConfigSetCfm *msg__; \ + CsrWifiNmeWpsConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsConfigSetCfmSend(dst__, status__) \ + CsrWifiNmeWpsConfigSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiNmeWpsReqSend + + DESCRIPTION + Requests the NME to look for WPS enabled APs and attempt to perform WPS + to determine the appropriate security credentials to connect to the AP. + If the PIN == '00000000' then 'push button mode' is indicated, otherwise + the PIN has to match that of the AP. 4 digit pin is passed by sending the + pin digits in pin[0]..pin[3] and rest of the contents filled with '-'. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + pin - PIN value. + ssid - Service Set identifier + bssid - ID of Basic Service Set for which a WPS connection attempt is + being made. + +*******************************************************************************/ +#define CsrWifiNmeWpsReqCreate(msg__, dst__, src__, interfaceTag__, pin__, ssid__, bssid__) \ + msg__ = (CsrWifiNmeWpsReq *) CsrPmemAlloc(sizeof(CsrWifiNmeWpsReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + CsrMemCpy(msg__->pin, (pin__), sizeof(CsrUint8) * 8); \ + msg__->ssid = (ssid__); \ + msg__->bssid = (bssid__); + +#define CsrWifiNmeWpsReqSendTo(dst__, src__, interfaceTag__, pin__, ssid__, bssid__) \ + { \ + CsrWifiNmeWpsReq *msg__; \ + CsrWifiNmeWpsReqCreate(msg__, dst__, src__, interfaceTag__, pin__, ssid__, bssid__); \ + CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ + } + +#define CsrWifiNmeWpsReqSend(src__, interfaceTag__, pin__, ssid__, bssid__) \ + CsrWifiNmeWpsReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, pin__, ssid__, bssid__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_prim.h b/drivers/staging/csr/csr_wifi_nme_prim.h new file mode 100644 index 000000000000..4d77d2f450c1 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_prim.h @@ -0,0 +1,1666 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_PRIM_H__ +#define CSR_WIFI_NME_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" +#include "csr_wifi_sme_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_prim.h +#endif + +#define CSR_WIFI_NME_PRIM (0x0424) + +typedef CsrPrim CsrWifiNmePrim; + +typedef void (*CsrWifiNmeFrameFreeFunction)(void *frame); + +/******************************************************************************* + + NAME + CsrWifiNmeAuthMode + + DESCRIPTION + WiFi Authentication Mode + + VALUES + CSR_WIFI_NME_AUTH_MODE_80211_OPEN + - Connects to an open system network (i.e. no authentication, + no encryption) or to a WEP enabled network. + CSR_WIFI_NME_AUTH_MODE_80211_SHARED + - Connect to a WEP enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_WPA + - Connects to a WPA Enterprise enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_WPAPSK + - Connects to a WPA with Pre-Shared Key enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_WPA2 + - Connects to a WPA2 Enterprise enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_WPA2PSK + - Connects to a WPA2 with Pre-Shared Key enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_CCKM + - Connects to a CCKM enabled network. + CSR_WIFI_NME_AUTH_MODE_WAPI_WAI + - Connects to a WAPI Enterprise enabled network. + CSR_WIFI_NME_AUTH_MODE_WAPI_WAIPSK + - Connects to a WAPI with Pre-Shared Key enabled network. + CSR_WIFI_NME_AUTH_MODE_8021X_OTHER1X + - For future use. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeAuthMode; +#define CSR_WIFI_NME_AUTH_MODE_80211_OPEN ((CsrWifiNmeAuthMode) 0x0001) +#define CSR_WIFI_NME_AUTH_MODE_80211_SHARED ((CsrWifiNmeAuthMode) 0x0002) +#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA ((CsrWifiNmeAuthMode) 0x0004) +#define CSR_WIFI_NME_AUTH_MODE_8021X_WPAPSK ((CsrWifiNmeAuthMode) 0x0008) +#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA2 ((CsrWifiNmeAuthMode) 0x0010) +#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA2PSK ((CsrWifiNmeAuthMode) 0x0020) +#define CSR_WIFI_NME_AUTH_MODE_8021X_CCKM ((CsrWifiNmeAuthMode) 0x0040) +#define CSR_WIFI_NME_AUTH_MODE_WAPI_WAI ((CsrWifiNmeAuthMode) 0x0080) +#define CSR_WIFI_NME_AUTH_MODE_WAPI_WAIPSK ((CsrWifiNmeAuthMode) 0x0100) +#define CSR_WIFI_NME_AUTH_MODE_8021X_OTHER1X ((CsrWifiNmeAuthMode) 0x0200) + +/******************************************************************************* + + NAME + CsrWifiNmeBssType + + DESCRIPTION + Type of BSS + + VALUES + CSR_WIFI_NME_BSS_TYPE_INFRASTRUCTURE + - Infrastructure BSS type where access to the network is via + one or several Access Points. + CSR_WIFI_NME_BSS_TYPE_ADHOC + - Adhoc or Independent BSS Type where one Station acts as a + host and future stations can join the adhoc network without + needing an access point. + CSR_WIFI_NME_BSS_TYPE_RESERVED + - To be in sync with SME.This is not used. + CSR_WIFI_NME_BSS_TYPE_P2P + - P2P mode of operation. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeBssType; +#define CSR_WIFI_NME_BSS_TYPE_INFRASTRUCTURE ((CsrWifiNmeBssType) 0x00) +#define CSR_WIFI_NME_BSS_TYPE_ADHOC ((CsrWifiNmeBssType) 0x01) +#define CSR_WIFI_NME_BSS_TYPE_RESERVED ((CsrWifiNmeBssType) 0x02) +#define CSR_WIFI_NME_BSS_TYPE_P2P ((CsrWifiNmeBssType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiNmeCcxOptionsMask + + DESCRIPTION + Enumeration type defining possible mask values for setting CCX options. + + VALUES + CSR_WIFI_NME_CCX_OPTION_NONE - No CCX option is set. + CSR_WIFI_NME_CCX_OPTION_CCKM - CCX option cckm is set. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeCcxOptionsMask; +#define CSR_WIFI_NME_CCX_OPTION_NONE ((CsrWifiNmeCcxOptionsMask) 0x00) +#define CSR_WIFI_NME_CCX_OPTION_CCKM ((CsrWifiNmeCcxOptionsMask) 0x01) + +/******************************************************************************* + + NAME + CsrWifiNmeConfigAction + + DESCRIPTION + + VALUES + CSR_WIFI_PIN_ENTRY_PUSH_BUTTON - + CSR_WIFI_PIN_ENTRY_DISPLAY_PIN - + CSR_WIFI_PIN_ENTRY_ENTER_PIN - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeConfigAction; +#define CSR_WIFI_PIN_ENTRY_PUSH_BUTTON ((CsrWifiNmeConfigAction) 0x00) +#define CSR_WIFI_PIN_ENTRY_DISPLAY_PIN ((CsrWifiNmeConfigAction) 0x01) +#define CSR_WIFI_PIN_ENTRY_ENTER_PIN ((CsrWifiNmeConfigAction) 0x02) + +/******************************************************************************* + + NAME + CsrWifiNmeConnectionStatus + + DESCRIPTION + Indicate the NME Connection Status when connecting or when disconnecting + + VALUES + CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTED + - NME is disconnected. + CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTING + - NME is in the process of connecting. + CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_AUTHENTICATING + - NME is in the authentication stage of a connection attempt. + CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTED + - NME is connected. + CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTING + - NME is in the process of disconnecting. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeConnectionStatus; +#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTED ((CsrWifiNmeConnectionStatus) 0x00) +#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTING ((CsrWifiNmeConnectionStatus) 0x01) +#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_AUTHENTICATING ((CsrWifiNmeConnectionStatus) 0x02) +#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTED ((CsrWifiNmeConnectionStatus) 0x03) +#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTING ((CsrWifiNmeConnectionStatus) 0x04) + +/******************************************************************************* + + NAME + CsrWifiNmeCredentialType + + DESCRIPTION + NME Credential Types + + VALUES + CSR_WIFI_NME_CREDENTIAL_TYPE_OPEN_SYSTEM + - Credential Type Open System. + CSR_WIFI_NME_CREDENTIAL_TYPE_WEP64 + - Credential Type WEP-64 + CSR_WIFI_NME_CREDENTIAL_TYPE_WEP128 + - Credential Type WEP-128 + CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PSK + - Credential Type WPA Pre-Shared Key + CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PASSPHRASE + - Credential Type WPA pass phrase + CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PSK + - Credential Type WPA2 Pre-Shared Key. + CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PASSPHRASE + - Credential Type WPA2 pass phrase + CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PSK + - Credential Type WAPI Pre-Shared Key. + CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PASSPHRASE + - Credential Type WAPI pass phrase + CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI + - Credential Type WAPI certificates + CSR_WIFI_NME_CREDENTIAL_TYPE_8021X + - Credential Type 802.1X: the associated type supports + FAST/LEAP/TLS/TTLS/PEAP/etc. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeCredentialType; +#define CSR_WIFI_NME_CREDENTIAL_TYPE_OPEN_SYSTEM ((CsrWifiNmeCredentialType) 0x0000) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WEP64 ((CsrWifiNmeCredentialType) 0x0001) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WEP128 ((CsrWifiNmeCredentialType) 0x0002) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PSK ((CsrWifiNmeCredentialType) 0x0003) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0004) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PSK ((CsrWifiNmeCredentialType) 0x0005) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0006) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PSK ((CsrWifiNmeCredentialType) 0x0007) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0008) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI ((CsrWifiNmeCredentialType) 0x0009) +#define CSR_WIFI_NME_CREDENTIAL_TYPE_8021X ((CsrWifiNmeCredentialType) 0x000A) + +/******************************************************************************* + + NAME + CsrWifiNmeEapMethod + + DESCRIPTION + Outer EAP method with possibly inner method. + + VALUES + CSR_WIFI_NME_EAP_METHOD_TLS + - EAP-TLS Method. + CSR_WIFI_NME_EAP_METHOD_TTLS_MSCHAPV2 + - EAP-TTLS Method with MSCHAPV2. + CSR_WIFI_NME_EAP_METHOD_PEAP_GTC + - EAP-PEAP Method with GTC. + CSR_WIFI_NME_EAP_METHOD_PEAP_MSCHAPV2 + - EAP-PEAP Method with MSCHAPV2. + CSR_WIFI_NME_EAP_METHOD_SIM + - EAP-SIM Method. + CSR_WIFI_NME_EAP_METHOD_AKA + - EAP-AKA Method. + CSR_WIFI_NME_EAP_METHOD_FAST_GTC + - EAP-FAST Method with GTC. + CSR_WIFI_NME_EAP_METHOD_FAST_MSCHAPV2 + - EAP-FAST Method with MSCHAPV2. + CSR_WIFI_NME_EAP_METHOD_LEAP + - EAP-LEAP Method. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeEapMethod; +#define CSR_WIFI_NME_EAP_METHOD_TLS ((CsrWifiNmeEapMethod) 0x0001) +#define CSR_WIFI_NME_EAP_METHOD_TTLS_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0002) +#define CSR_WIFI_NME_EAP_METHOD_PEAP_GTC ((CsrWifiNmeEapMethod) 0x0004) +#define CSR_WIFI_NME_EAP_METHOD_PEAP_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0008) +#define CSR_WIFI_NME_EAP_METHOD_SIM ((CsrWifiNmeEapMethod) 0x0010) +#define CSR_WIFI_NME_EAP_METHOD_AKA ((CsrWifiNmeEapMethod) 0x0020) +#define CSR_WIFI_NME_EAP_METHOD_FAST_GTC ((CsrWifiNmeEapMethod) 0x0040) +#define CSR_WIFI_NME_EAP_METHOD_FAST_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0080) +#define CSR_WIFI_NME_EAP_METHOD_LEAP ((CsrWifiNmeEapMethod) 0x0100) + +/******************************************************************************* + + NAME + CsrWifiNmeEncryption + + DESCRIPTION + WiFi Encryption method + + VALUES + CSR_WIFI_NME_ENCRYPTION_CIPHER_NONE + - No encryprion set. + CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 + - 40 bytes WEP key for peer to peer communication. + CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 + - 104 bytes WEP key for peer to peer communication. + CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_TKIP + - TKIP key for peer to peer communication. + CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP + - CCMP key for peer to peer communication. + CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 + - SMS4 key for peer to peer communication. + CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP40 + - 40 bytes WEP key for broadcast messages. + CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP104 + - 104 bytes WEP key for broadcast messages. + CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_TKIP + - TKIP key for broadcast messages. + CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP + - CCMP key for broadcast messages + CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_SMS4 + - SMS4 key for broadcast messages. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeEncryption; +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_NONE ((CsrWifiNmeEncryption) 0x0000) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 ((CsrWifiNmeEncryption) 0x0001) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 ((CsrWifiNmeEncryption) 0x0002) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_TKIP ((CsrWifiNmeEncryption) 0x0004) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP ((CsrWifiNmeEncryption) 0x0008) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 ((CsrWifiNmeEncryption) 0x0010) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP40 ((CsrWifiNmeEncryption) 0x0020) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP104 ((CsrWifiNmeEncryption) 0x0040) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_TKIP ((CsrWifiNmeEncryption) 0x0080) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP ((CsrWifiNmeEncryption) 0x0100) +#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_SMS4 ((CsrWifiNmeEncryption) 0x0200) + +/******************************************************************************* + + NAME + CsrWifiNmeIndications + + DESCRIPTION + NME indications + + VALUES + CSR_WIFI_NME_INDICATIONS_IND_AP_STATION + - NME AP Station Indication. + CSR_WIFI_NME_INDICATIONS_IND_AP_STOP + - NME AP Stop Indication. + CSR_WIFI_NME_INDICATIONS_IND_SIM_UMTS_AUTH + - NME UMTS Authentication Indication. + CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_START + - NME P2P Group Start Indication. + CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_STATUS + - NME P2P Group Status Indication. + CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_ROLE + - NME P2P Group Role Indication. + CSR_WIFI_NME_INDICATIONS_IND_PROFILE_DISCONNECT + - NME Profile Disconnect Indication. + CSR_WIFI_NME_INDICATIONS_IND_PROFILE_UPDATE + - NME Profile Update Indication. + CSR_WIFI_NME_INDICATIONS_IND_SIM_IMSI_GET + - NME GET IMSI Indication. + CSR_WIFI_NME_INDICATIONS_IND_SIM_GSM_AUTH + - NME GSM Authentication Indication. + CSR_WIFI_NME_INDICATIONS_ALL + - Used to register for all available indications + +*******************************************************************************/ +typedef CsrUint32 CsrWifiNmeIndications; +#define CSR_WIFI_NME_INDICATIONS_IND_AP_STATION ((CsrWifiNmeIndications) 0x00100000) +#define CSR_WIFI_NME_INDICATIONS_IND_AP_STOP ((CsrWifiNmeIndications) 0x00200000) +#define CSR_WIFI_NME_INDICATIONS_IND_SIM_UMTS_AUTH ((CsrWifiNmeIndications) 0x01000000) +#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_START ((CsrWifiNmeIndications) 0x02000000) +#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_STATUS ((CsrWifiNmeIndications) 0x04000000) +#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_ROLE ((CsrWifiNmeIndications) 0x08000000) +#define CSR_WIFI_NME_INDICATIONS_IND_PROFILE_DISCONNECT ((CsrWifiNmeIndications) 0x10000000) +#define CSR_WIFI_NME_INDICATIONS_IND_PROFILE_UPDATE ((CsrWifiNmeIndications) 0x20000000) +#define CSR_WIFI_NME_INDICATIONS_IND_SIM_IMSI_GET ((CsrWifiNmeIndications) 0x40000000) +#define CSR_WIFI_NME_INDICATIONS_IND_SIM_GSM_AUTH ((CsrWifiNmeIndications) 0x80000000) +#define CSR_WIFI_NME_INDICATIONS_ALL ((CsrWifiNmeIndications) 0xFFFFFFFF) + +/******************************************************************************* + + NAME + CsrWifiNmeSecError + + DESCRIPTION + NME Security Errors + place holder for the security library abort reason + + VALUES + CSR_WIFI_NME_SEC_ERROR_SEC_ERROR_UNKNOWN + - Unknown Security Error. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeSecError; +#define CSR_WIFI_NME_SEC_ERROR_SEC_ERROR_UNKNOWN ((CsrWifiNmeSecError) 0x00) + +/******************************************************************************* + + NAME + CsrWifiNmeSimCardType + + DESCRIPTION + (U)SIM Card (or UICC) types + + VALUES + CSR_WIFI_NME_SIM_CARD_TYPE_2G - 2G SIM card, capable of performing GSM + authentication only. + CSR_WIFI_NME_SIM_CARD_TYPE_3G - UICC supporting USIM application, capable + of performing UMTS authentication only. + CSR_WIFI_NME_SIM_CARD_TYPE_2G3G - UICC supporting both USIM and SIM + applications, capable of performing both + UMTS and GSM authentications. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeSimCardType; +#define CSR_WIFI_NME_SIM_CARD_TYPE_2G ((CsrWifiNmeSimCardType) 0x01) +#define CSR_WIFI_NME_SIM_CARD_TYPE_3G ((CsrWifiNmeSimCardType) 0x02) +#define CSR_WIFI_NME_SIM_CARD_TYPE_2G3G ((CsrWifiNmeSimCardType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiNmeUmtsAuthResult + + DESCRIPTION + Only relevant for UMTS Authentication. It indicates if the UICC has + successfully authenticated the network or otherwise. + + VALUES + CSR_WIFI_NME_UMTS_AUTH_RESULT_SUCCESS + - Successful outcome from USIM indicating that the card has + successfully authenticated the network. + CSR_WIFI_NME_UMTS_AUTH_RESULT_SYNC_FAIL + - Unsuccessful outcome from USIM indicating that the card is + requesting the network to synchronise and re-try again. If + no further request is received an NME timer will expire and + the authentication is aborted. + CSR_WIFI_NME_UMTS_AUTH_RESULT_REJECT + - Unsuccessful outcome from USIM indicating that the card has + rejected the network and that the authentication is + aborted. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeUmtsAuthResult; +#define CSR_WIFI_NME_UMTS_AUTH_RESULT_SUCCESS ((CsrWifiNmeUmtsAuthResult) 0x00) +#define CSR_WIFI_NME_UMTS_AUTH_RESULT_SYNC_FAIL ((CsrWifiNmeUmtsAuthResult) 0x01) +#define CSR_WIFI_NME_UMTS_AUTH_RESULT_REJECT ((CsrWifiNmeUmtsAuthResult) 0x02) + +/******************************************************************************* + + NAME + CsrWifiNmeWmmQosInfo + + DESCRIPTION + Defines bits for the QoS Info octect as defined in the WMM specification. + The values of this type are used across the NME/SME/Router API's and they + must be kept consistent with the corresponding types in the .xml of the + other interfaces + + VALUES + CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_ALL + - WMM AP may deliver all buffered frames. + CSR_WIFI_NME_WMM_QOS_INFO_AC_VO + - To enable the triggering and delivery of QoS Voice. + CSR_WIFI_NME_WMM_QOS_INFO_AC_VI + - To enable the triggering and delivery of QoS Video. + CSR_WIFI_NME_WMM_QOS_INFO_AC_BK + - To enable the triggering and delivery of QoS Background. + CSR_WIFI_NME_WMM_QOS_INFO_AC_BE + - To enable the triggering and delivery of QoS Best Effort. + CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_TWO + - WMM AP may deliver a maximum of 2 buffered frames per + Unscheduled Service Period (USP). + CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_FOUR + - WMM AP may deliver a maximum of 4 buffered frames per USP. + CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_SIX + - WMM AP may deliver a maximum of 6 buffered frames per USP. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeWmmQosInfo; +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_ALL ((CsrWifiNmeWmmQosInfo) 0x00) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_VO ((CsrWifiNmeWmmQosInfo) 0x01) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_VI ((CsrWifiNmeWmmQosInfo) 0x02) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_BK ((CsrWifiNmeWmmQosInfo) 0x04) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_BE ((CsrWifiNmeWmmQosInfo) 0x08) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_TWO ((CsrWifiNmeWmmQosInfo) 0x20) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_FOUR ((CsrWifiNmeWmmQosInfo) 0x40) +#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_SIX ((CsrWifiNmeWmmQosInfo) 0x60) + + +/******************************************************************************* + + NAME + CsrWifiNmeEapMethodMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiNmeEapMethod. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeEapMethodMask; +/******************************************************************************* + + NAME + CsrWifiNmeEncryptionMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiNmeEncryption + +*******************************************************************************/ +typedef CsrUint16 CsrWifiNmeEncryptionMask; +/******************************************************************************* + + NAME + CsrWifiNmeIndicationsMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiNmeIndications + +*******************************************************************************/ +typedef CsrUint32 CsrWifiNmeIndicationsMask; +/******************************************************************************* + + NAME + CsrWifiNmeNmeIndicationsMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiNmeNmeIndications. + Used to overlap the unused portion of the unifi_IndicationsMask For NME + specific indications + +*******************************************************************************/ +typedef CsrUint32 CsrWifiNmeNmeIndicationsMask; +/******************************************************************************* + + NAME + CsrWifiNmeWmmQosInfoMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiNmeWmmQosInfo + +*******************************************************************************/ +typedef CsrUint8 CsrWifiNmeWmmQosInfoMask; + + +/******************************************************************************* + + NAME + CsrWifiNmeEmpty + + DESCRIPTION + Empty Structure to indicate that no credentials are available. + + MEMBERS + empty - Only element of the empty structure (always set to 0). + +*******************************************************************************/ +typedef struct +{ + CsrUint8 empty; +} CsrWifiNmeEmpty; + +/******************************************************************************* + + NAME + CsrWifiNmePassphrase + + DESCRIPTION + Structure holding the ASCII Pass Phrase data. + + MEMBERS + encryptionMode - Encryption type as defined in CsrWifiSmeEncryption. + passphrase - Pass phrase ASCII value. + +*******************************************************************************/ +typedef struct +{ + CsrUint16 encryptionMode; + CsrCharString *passphrase; +} CsrWifiNmePassphrase; + +/******************************************************************************* + + NAME + CsrWifiNmePsk + + DESCRIPTION + Structure holding the Pre-Shared Key data. + + MEMBERS + encryptionMode - Encryption type as defined in CsrWifiSmeEncryption. + psk - Pre-Shared Key value. + +*******************************************************************************/ +typedef struct +{ + CsrUint16 encryptionMode; + CsrUint8 psk[32]; +} CsrWifiNmePsk; + +/******************************************************************************* + + NAME + CsrWifiNmeWapiCredentials + + DESCRIPTION + Structure holding WAPI credentials data. + + MEMBERS + certificateLength - Length in bytes of the following client certificate. + certificate - The actual client certificate data (if present). + DER/PEM format supported. + privateKeyLength - Length in bytes of the following private key. + privateKey - The actual private key. DER/PEM format. + caCertificateLength - Length in bytes of the following certificate authority + certificate. + caCertificate - The actual certificate authority certificate data. If + not supplied the received certificate authority + certificate is assumed to be validate, if present the + received certificate is validated against it. DER/PEM + format supported. + +*******************************************************************************/ +typedef struct +{ + CsrUint32 certificateLength; + CsrUint8 *certificate; + CsrUint16 privateKeyLength; + CsrUint8 *privateKey; + CsrUint32 caCertificateLength; + CsrUint8 *caCertificate; +} CsrWifiNmeWapiCredentials; + +/******************************************************************************* + + NAME + CsrWifiNmeConnectAttempt + + DESCRIPTION + Structure holding Connection attempt data. + + MEMBERS + bssid - Id of Basic Service Set connections attempt have been made + to. + status - Status returned to indicate the success or otherwise of the + connection attempt. + securityError - Security error status indicating the nature of the failure + to connect. + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress bssid; + CsrResult status; + CsrWifiNmeSecError securityError; +} CsrWifiNmeConnectAttempt; + +/******************************************************************************* + + NAME + CsrWifiNmeEapCredentials + + DESCRIPTION + Supports the use of multiple EAP methods via a single structure. The + methods required are indicated by the value set in the eapMethodMask + + MEMBERS + eapMethodMask + - Bit mask of supported EAP methods + Currently only supports the setting of one bit. + Required for all the EAP methods. + authMode + - Bit mask representing the authentication types that may be + supported by a suitable AP. An AP must support at least one + of the authentication types specified to be considered for + connection. Required for all EAP methods. + encryptionMode + - Bit mask representing the encryption types that may be + supported by a suitable AP. An AP must support a suitable + mix of the pairwise and group encryption types requested to + be considered for connection. Required for all EAP methods. + userName + - User name. Required for all EAP methods except: SIM or AKA. + userPassword + - User Password. Required for all EAP methods except: TLS, + SIM or AKA. + authServerUserIdentity + - Authentication server user Identity. Required for all EAP + methods except: TLS, SIM, AKA or FAST. + clientCertificateLength + - Length in bytes of the following client certificate (if + present). Only required for TLS. + clientCertificate + - The actual client certificate data (if present). Only + required for TLS. DER/PEM format supported. + certificateAuthorityCertificateLength + - Length in bytes of the following certificate authority + certificate (if present). Optional for TLS, TTLS, PEAP. + certificateAuthorityCertificate + - The actual certificate authority certificate data (if + present). If not supplied the received certificate + authority certificate is assumed to be valid, if present + the received certificate is validated against it. Optional + for TLS, TTLS, PEAP. DER/PEM format supported. + privateKeyLength + - Length in bytes of the following private key (if present). + Only required for TLS. + privateKey + - The actual private key (if present). Only required for TLS. + DER/PEM format, maybe password protected. + privateKeyPassword + - Optional password to protect the private key. + sessionLength + - Length in bytes of the following session field Supported + for all EAP methods except: SIM or AKA. + session + - Session information to support faster re-authentication. + Supported for all EAP methods except: SIM or AKA. + allowPacProvisioning + - If TRUE: PAC provisioning is allowed 'over-the_air'; + If FALSE: a PAC must be supplied. + Only required for FAST. + pacLength + - Length the following PAC field. If allowPacProvisioning is + FALSE then the PAC MUST be supplied (i.e. non-zero). Only + required for FAST. + pac + - The actual PAC data. If allowPacProvisioning is FALSE then + the PAC MUST be supplied. Only required for FAST. + pacPassword + - Optional password to protect the PAC. Only required for + FAST. + +*******************************************************************************/ +typedef struct +{ + CsrWifiNmeEapMethodMask eapMethodMask; + CsrWifiSmeAuthModeMask authMode; + CsrWifiNmeEncryptionMask encryptionMode; + CsrCharString *userName; + CsrCharString *userPassword; + CsrCharString *authServerUserIdentity; + CsrUint32 clientCertificateLength; + CsrUint8 *clientCertificate; + CsrUint32 certificateAuthorityCertificateLength; + CsrUint8 *certificateAuthorityCertificate; + CsrUint16 privateKeyLength; + CsrUint8 *privateKey; + CsrCharString *privateKeyPassword; + CsrUint32 sessionLength; + CsrUint8 *session; + CsrBool allowPacProvisioning; + CsrUint32 pacLength; + CsrUint8 *pac; + CsrCharString *pacPassword; +} CsrWifiNmeEapCredentials; + +/******************************************************************************* + + NAME + CsrWifiNmePeerConfig + + DESCRIPTION + Structure holding Peer Config data. + + MEMBERS + p2pDeviceId - + groupCapabilityMask - + groupOwnerIntent - + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress p2pDeviceId; + CsrWifiSmeP2pGroupCapabilityMask groupCapabilityMask; + CsrUint8 groupOwnerIntent; +} CsrWifiNmePeerConfig; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileIdentity + + DESCRIPTION + The identity of a profile is defined as the unique combination the BSSID + and SSID. + + MEMBERS + bssid - ID of Basic Service Set for or the P2pDevice address of the GO for + which a connection attempt was made. + ssid - Service Set Id. + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress bssid; + CsrWifiSsid ssid; +} CsrWifiNmeProfileIdentity; + +/******************************************************************************* + + NAME + CsrWifiNmeWep128Keys + + DESCRIPTION + Structure holding WEP Authentication Type and WEP keys that can be used + when using WEP128. + + MEMBERS + wepAuthType - Mask to select the WEP authentication type (Open or Shared) + selectedWepKey - Index to one of the four keys below indicating the + currently used WEP key. + key1 - Value for key number 1. + key2 - Value for key number 2. + key3 - Value for key number 3. + key4 - Value for key number 4. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeAuthModeMask wepAuthType; + CsrUint8 selectedWepKey; + CsrUint8 key1[13]; + CsrUint8 key2[13]; + CsrUint8 key3[13]; + CsrUint8 key4[13]; +} CsrWifiNmeWep128Keys; + +/******************************************************************************* + + NAME + CsrWifiNmeWep64Keys + + DESCRIPTION + Structure for holding WEP Authentication Type and WEP keys that can be + used when using WEP64. + + MEMBERS + wepAuthType - Mask to select the WEP authentication type (Open or Shared) + selectedWepKey - Index to one of the four keys below indicating the + currently used WEP key. + key1 - Value for key number 1. + key2 - Value for key number 2. + key3 - Value for key number 3. + key4 - Value for key number 4. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeAuthModeMask wepAuthType; + CsrUint8 selectedWepKey; + CsrUint8 key1[5]; + CsrUint8 key2[5]; + CsrUint8 key3[5]; + CsrUint8 key4[5]; +} CsrWifiNmeWep64Keys; + +/******************************************************************************* + + NAME + CsrWifiNmeCredentials + + DESCRIPTION + Structure containing the Credentials data. + + MEMBERS + credentialType - Credential type value (as defined in the + enumeration type). + credential - Union containing credentials which depends on + credentialType parameter. + credentialeap - + credentialwapiPassphrase - + credentialwpa2Passphrase - + credentialwpa2Psk - + credentialwapiPsk - + credentialwpaPassphrase - + credentialwapi - + credentialwep128Key - + credentialwpaPsk - + credentialopenSystem - + credentialwep64Key - + +*******************************************************************************/ +typedef struct +{ + CsrWifiNmeCredentialType credentialType; + union { + CsrWifiNmeEapCredentials eap; + CsrWifiNmePassphrase wapiPassphrase; + CsrWifiNmePassphrase wpa2Passphrase; + CsrWifiNmePsk wpa2Psk; + CsrWifiNmePsk wapiPsk; + CsrWifiNmePassphrase wpaPassphrase; + CsrWifiNmeWapiCredentials wapi; + CsrWifiNmeWep128Keys wep128Key; + CsrWifiNmePsk wpaPsk; + CsrWifiNmeEmpty openSystem; + CsrWifiNmeWep64Keys wep64Key; + } credential; +} CsrWifiNmeCredentials; + +/******************************************************************************* + + NAME + CsrWifiNmeProfile + + DESCRIPTION + Structure containing the Profile data. + + MEMBERS + profileIdentity - Profile Identity. + wmmQosInfoMask - Mask for WMM QoS information. + bssType - Type of BSS (Infrastructure or Adhoc). + channelNo - Channel Number. + ccxOptionsMask - Options mask for Cisco Compatible Extentions. + cloakedSsid - Flag to decide whether the SSID is cloaked (not + transmitted) or not. + credentials - Credentials data. + +*******************************************************************************/ +typedef struct +{ + CsrWifiNmeProfileIdentity profileIdentity; + CsrWifiNmeWmmQosInfoMask wmmQosInfoMask; + CsrWifiNmeBssType bssType; + CsrUint8 channelNo; + CsrUint8 ccxOptionsMask; + CsrBool cloakedSsid; + CsrWifiNmeCredentials credentials; +} CsrWifiNmeProfile; + + +/* Downstream */ +#define CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_NME_PROFILE_SET_REQ ((CsrWifiNmePrim) (0x0000 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_DELETE_REQ ((CsrWifiNmePrim) (0x0001 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ ((CsrWifiNmePrim) (0x0002 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_ORDER_SET_REQ ((CsrWifiNmePrim) (0x0003 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_CONNECT_REQ ((CsrWifiNmePrim) (0x0004 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_REQ ((CsrWifiNmePrim) (0x0005 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_CANCEL_REQ ((CsrWifiNmePrim) (0x0006 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_CONNECTION_STATUS_GET_REQ ((CsrWifiNmePrim) (0x0007 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_IMSI_GET_RES ((CsrWifiNmePrim) (0x0008 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_GSM_AUTH_RES ((CsrWifiNmePrim) (0x0009 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_UMTS_AUTH_RES ((CsrWifiNmePrim) (0x000A + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_CONFIG_SET_REQ ((CsrWifiNmePrim) (0x000B + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_NME_EVENT_MASK_SET_REQ ((CsrWifiNmePrim) (0x000C + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_NME_PRIM_DOWNSTREAM_HIGHEST (0x000C + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_NME_PROFILE_SET_CFM ((CsrWifiNmePrim)(0x0000 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_DELETE_CFM ((CsrWifiNmePrim)(0x0001 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_DELETE_ALL_CFM ((CsrWifiNmePrim)(0x0002 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_ORDER_SET_CFM ((CsrWifiNmePrim)(0x0003 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_CONNECT_CFM ((CsrWifiNmePrim)(0x0004 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_CFM ((CsrWifiNmePrim)(0x0005 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_CANCEL_CFM ((CsrWifiNmePrim)(0x0006 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_CONNECTION_STATUS_GET_CFM ((CsrWifiNmePrim)(0x0007 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_UPDATE_IND ((CsrWifiNmePrim)(0x0008 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_PROFILE_DISCONNECT_IND ((CsrWifiNmePrim)(0x0009 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_IMSI_GET_IND ((CsrWifiNmePrim)(0x000A + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_GSM_AUTH_IND ((CsrWifiNmePrim)(0x000B + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_SIM_UMTS_AUTH_IND ((CsrWifiNmePrim)(0x000C + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_WPS_CONFIG_SET_CFM ((CsrWifiNmePrim)(0x000D + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_NME_EVENT_MASK_SET_CFM ((CsrWifiNmePrim)(0x000E + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_NME_PRIM_UPSTREAM_HIGHEST (0x000E + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_NME_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_NME_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_NME_PRIM_UPSTREAM_COUNT (CSR_WIFI_NME_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiNmeProfileSetReq + + DESCRIPTION + Creates or updates an existing profile in the NME that matches the unique + identity of the profile. Each profile is identified by the combination of + BSSID and SSID. The profile contains all the required credentials for + attempting to connect to the network. Creating or updating a profile via + the NME PROFILE SET REQ does NOT add the profile to the preferred profile + list within the NME used for the NME auto-connect behaviour. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + profile - Specifies the identity and credentials of the network. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiNmeProfile profile; +} CsrWifiNmeProfileSetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteReq + + DESCRIPTION + Will delete the profile with a matching identity, but does NOT modify the + preferred profile list. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + profileIdentity - Identity (BSSID, SSID) of profile to be deleted. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiNmeProfileIdentity profileIdentity; +} CsrWifiNmeProfileDeleteReq; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteAllReq + + DESCRIPTION + Deletes all profiles present in the NME, but does NOT modify the + preferred profile list. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiNmeProfileDeleteAllReq; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileOrderSetReq + + DESCRIPTION + Defines the preferred order that profiles present in the NME should be + used during the NME auto-connect behaviour. + If profileIdentitysCount == 0, it removes any existing preferred profile + list already present in the NME, effectively disabling the auto-connect + behaviour. + NOTE: Profile identities that do not match any profile stored in the NME + are ignored during the auto-connect procedure. + NOTE: during auto-connect the NME will only attempt to join an existing + adhoc network and it will never attempt to host an adhoc network; for + hosting and adhoc network, use CSR_WIFI_NME_PROFILE_CONNECT_REQ + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an + interface + profileIdentitysCount - The number of profiles identities in the list. + profileIdentitys - Points to the list of profile identities. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 profileIdentitysCount; + CsrWifiNmeProfileIdentity *profileIdentitys; +} CsrWifiNmeProfileOrderSetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileConnectReq + + DESCRIPTION + Requests the NME to attempt to connect to the specified profile. + Overrides any current connection attempt. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + profileIdentity - Identity (BSSID, SSID) of profile to be connected to. + It must match an existing profile in the NME. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiNmeProfileIdentity profileIdentity; +} CsrWifiNmeProfileConnectReq; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsReq + + DESCRIPTION + Requests the NME to look for WPS enabled APs and attempt to perform WPS + to determine the appropriate security credentials to connect to the AP. + If the PIN == '00000000' then 'push button mode' is indicated, otherwise + the PIN has to match that of the AP. 4 digit pin is passed by sending the + pin digits in pin[0]..pin[3] and rest of the contents filled with '-'. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + pin - PIN value. + ssid - Service Set identifier + bssid - ID of Basic Service Set for which a WPS connection attempt is + being made. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 pin[8]; + CsrWifiSsid ssid; + CsrWifiMacAddress bssid; +} CsrWifiNmeWpsReq; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCancelReq + + DESCRIPTION + Requests the NME to cancel any WPS procedure that it is currently + performing. This includes WPS registrar activities started because of + CSR_WIFI_NME_AP_REGISTER.request + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiNmeWpsCancelReq; + +/******************************************************************************* + + NAME + CsrWifiNmeConnectionStatusGetReq + + DESCRIPTION + Requests the current connection status of the NME. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiNmeConnectionStatusGetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeSimImsiGetRes + + DESCRIPTION + Response from the application that received the NME SIM IMSI GET IND. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the outcome of the requested operation: STATUS_SUCCESS + or STATUS_ERROR. + imsi - The value of the IMSI obtained from the UICC. + cardType - The UICC type (GSM only (SIM), UMTS only (USIM), Both). + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrCharString *imsi; + CsrWifiNmeSimCardType cardType; +} CsrWifiNmeSimImsiGetRes; + +/******************************************************************************* + + NAME + CsrWifiNmeSimGsmAuthRes + + DESCRIPTION + Response from the application that received the NME SIM GSM AUTH IND. For + each GSM authentication round a GSM Ciphering key (Kc) and a signed + response (SRES) are produced. Since 2 or 3 GSM authentication rounds are + used the 2 or 3 Kc's obtained respectively are combined into one buffer + and similarly the 2 or 3 SRES's obtained are combined into another + buffer. The order of Kc values (SRES values respectively) in their buffer + is the same as that of their corresponding RAND values in the incoming + indication. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the outcome of the requested operation: + STATUS_SUCCESS or STATUS_ERROR + kcsLength - Length in Bytes of Kc buffer. Legal values are: 16 or 24. + kcs - Kc buffer holding 2 or 3 Kc values. + sresLength - Length in Bytes of SRES buffer. Legal values are: 8 or 12. + sres - SRES buffer holding 2 or 3 SRES values. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint8 kcsLength; + CsrUint8 *kcs; + CsrUint8 sresLength; + CsrUint8 *sres; +} CsrWifiNmeSimGsmAuthRes; + +/******************************************************************************* + + NAME + CsrWifiNmeSimUmtsAuthRes + + DESCRIPTION + Response from the application that received the NME SIM UMTS AUTH IND. + The values of umtsCipherKey, umtsIntegrityKey, resParameterLength and + resParameter are only meanigful when result = UMTS_AUTH_RESULT_SUCCESS. + The value of auts is only meaningful when + result=UMTS_AUTH_RESULT_SYNC_FAIL. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the outcome of the requested operation: + STATUS_SUCCESS or STATUS_ERROR. + result - The result of UMTS authentication as performed by the + UICC which could be: Success, Authentication Reject or + Synchronisation Failure. For all these 3 outcomes the + value of status is success. + umtsCipherKey - The UMTS Cipher Key as calculated and returned by the + UICC. + umtsIntegrityKey - The UMTS Integrity Key as calculated and returned by + the UICC. + resParameterLength - The length (in bytes) of the RES parameter (min=4; max + = 16). + resParameter - The RES parameter as calculated and returned by the + UICC. + auts - The AUTS parameter as calculated and returned by the + UICC. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiNmeUmtsAuthResult result; + CsrUint8 umtsCipherKey[16]; + CsrUint8 umtsIntegrityKey[16]; + CsrUint8 resParameterLength; + CsrUint8 *resParameter; + CsrUint8 auts[14]; +} CsrWifiNmeSimUmtsAuthRes; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsConfigSetReq + + DESCRIPTION + This primitive passes the WPS information for the device to NME. This may + be accepted only if no interface is active. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + wpsConfig - WPS config. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeWpsConfig wpsConfig; +} CsrWifiNmeWpsConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeEventMaskSetReq + + DESCRIPTION + The wireless manager application may register with the NME to receive + notification of interesting events. Indications will be sent only if the + wireless manager explicitly registers to be notified of that event. + indMask is a bit mask of values defined in CsrWifiNmeIndicationsMask. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + indMask - Set mask with values from CsrWifiNmeIndications + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiNmeIndicationsMask indMask; +} CsrWifiNmeEventMaskSetReq; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileSetCfm + + DESCRIPTION + Reports the status of the NME PROFILE SET REQ; the request will only fail + if the details specified in the profile contains an invalid combination + of parameters for example specifying the profile as cloaked but not + specifying the SSID. The NME doesn't limit the number of profiles that + may be created. The NME assumes that the entity configuring it is aware + of the appropriate limits. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the success or otherwise of the requested operation. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeProfileSetCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteCfm + + DESCRIPTION + Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_REQ. + Returns CSR_WIFI_NME_STATUS_NOT_FOUND if there is no matching profile. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the success or otherwise of the requested operation. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeProfileDeleteCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDeleteAllCfm + + DESCRIPTION + Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ. + Returns always CSR_WIFI_NME_STATUS_SUCCESS. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Indicates the success or otherwise of the requested operation, but + in this case it always set to success. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeProfileDeleteAllCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileOrderSetCfm + + DESCRIPTION + Confirmation to UNIFI_NME_PROFILE_ORDER_SET.request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiNmeProfileOrderSetCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileConnectCfm + + DESCRIPTION + Reports the status of the NME PROFILE CONNECT REQ. If unsuccessful the + connectAttempt parameters contain details of the APs that the NME + attempted to connect to before reporting the failure of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an + interface + status - Indicates the success or otherwise of the requested + operation. + connectAttemptsCount - This parameter is relevant only if + status!=CSR_WIFI_NME_STATUS_SUCCESS. + Number of connection attempt elements provided with + this primitive + connectAttempts - This parameter is relevant only if + status!=CSR_WIFI_NME_STATUS_SUCCESS. + Points to the list of connection attempt elements + provided with this primitive + Each element of the list provides information about + an AP on which the connection attempt was made and + the error that occurred during the attempt. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrUint8 connectAttemptsCount; + CsrWifiNmeConnectAttempt *connectAttempts; +} CsrWifiNmeProfileConnectCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCfm + + DESCRIPTION + Reports the status of the NME WPS REQ. + If CSR_WIFI_NME_STATUS_SUCCESS, the profile parameter contains the + identity and credentials of the AP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + profile - This parameter is relevant only if + status==CSR_WIFI_NME_STATUS_SUCCESS. + The identity and credentials of the network. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiNmeProfile profile; +} CsrWifiNmeWpsCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsCancelCfm + + DESCRIPTION + Reports the status of the NME WPS REQ, the request is always SUCCESSFUL. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Only returns CSR_WIFI_NME_STATUS_SUCCESS + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiNmeWpsCancelCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeConnectionStatusGetCfm + + DESCRIPTION + Reports the connection status of the NME. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Indicates the success or otherwise of the requested + operation. + connectionStatus - NME current connection status + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiNmeConnectionStatus connectionStatus; +} CsrWifiNmeConnectionStatusGetCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileUpdateInd + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that informs that application that the contained profile has + changed. + For example, either the credentials EAP-FAST PAC file or the session data + within the profile has changed. + It is up to the application whether it stores this updated profile or + not. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + profile - The identity and credentials of the network. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiNmeProfile profile; +} CsrWifiNmeProfileUpdateInd; + +/******************************************************************************* + + NAME + CsrWifiNmeProfileDisconnectInd + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that informs that application that the current profile + connection has disconnected. The indication will contain information + about APs that it attempted to maintain the connection via i.e. in the + case of failed roaming. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an + interface + connectAttemptsCount - Number of connection attempt elements provided with + this primitive + connectAttempts - Points to the list of connection attempt elements + provided with this primitive + Each element of the list provides information about + an AP on which the connection attempt was made and + the error occurred during the attempt. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 connectAttemptsCount; + CsrWifiNmeConnectAttempt *connectAttempts; +} CsrWifiNmeProfileDisconnectInd; + +/******************************************************************************* + + NAME + CsrWifiNmeSimImsiGetInd + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the IMSI and UICC type from the UICC Manager. + This indication is generated when the NME is attempting to connect to a + profile configured for EAP-SIM/AKA. An application MUST register to + receive this indication for the NME to support the EAP-SIM/AKA credential + types. Otherwise the NME has no route to obtain the information from the + UICC. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiNmeSimImsiGetInd; + +/******************************************************************************* + + NAME + CsrWifiNmeSimGsmAuthInd + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the UICC Manager to perform a GSM + authentication on behalf of the NME. This indication is generated when + the NME is attempting to connect to a profile configured for EAP-SIM. An + application MUST register to receive this indication for the NME to + support the EAP-SIM credential types. Otherwise the NME has no route to + obtain the information from the UICC. EAP-SIM authentication requires 2 + or 3 GSM authentication rounds and therefore 2 or 3 RANDS (GSM Random + Challenges) are included. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + randsLength - GSM RAND is 16 bytes long hence valid values are 32 (2 RANDS) + or 48 (3 RANDs). + rands - 2 or 3 RANDs values. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 randsLength; + CsrUint8 *rands; +} CsrWifiNmeSimGsmAuthInd; + +/******************************************************************************* + + NAME + CsrWifiNmeSimUmtsAuthInd + + DESCRIPTION + Indication generated from the NME (if an application subscribes to + receive it) that requests the UICC Manager to perform a UMTS + authentication on behalf of the NME. This indication is generated when + the NME is attempting to connect to a profile configured for EAP-AKA. An + application MUST register to receive this indication for the NME to + support the EAP-AKA credential types. Otherwise the NME has no route to + obtain the information from the USIM. EAP-AKA requires one UMTS + authentication round and therefore only one RAND and one AUTN values are + included. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + rand - UMTS RAND value. + autn - UMTS AUTN value. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 rand[16]; + CsrUint8 autn[16]; +} CsrWifiNmeSimUmtsAuthInd; + +/******************************************************************************* + + NAME + CsrWifiNmeWpsConfigSetCfm + + DESCRIPTION + Confirm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeWpsConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiNmeEventMaskSetCfm + + DESCRIPTION + The NME calls the primitive to report the result of the request + primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiNmeEventMaskSetCfm; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_nme_serialize.h b/drivers/staging/csr/csr_wifi_nme_serialize.h new file mode 100644 index 000000000000..aeca9c83dc71 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_serialize.h @@ -0,0 +1,177 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_SERIALIZE_H__ +#define CSR_WIFI_NME_SERIALIZE_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_wifi_msgconv.h" + +#include "csr_wifi_nme_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_serialize.h +#endif + +extern void CsrWifiNmePfree(void *ptr); + +extern CsrUint8* CsrWifiNmeProfileSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileSetReqSizeof(void *msg); +extern void CsrWifiNmeProfileSetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeProfileDeleteReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileDeleteReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileDeleteReqSizeof(void *msg); +#define CsrWifiNmeProfileDeleteReqSerFree CsrWifiNmePfree + +#define CsrWifiNmeProfileDeleteAllReqSer CsrWifiEventSer +#define CsrWifiNmeProfileDeleteAllReqDes CsrWifiEventDes +#define CsrWifiNmeProfileDeleteAllReqSizeof CsrWifiEventSizeof +#define CsrWifiNmeProfileDeleteAllReqSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeProfileOrderSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileOrderSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileOrderSetReqSizeof(void *msg); +extern void CsrWifiNmeProfileOrderSetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeProfileConnectReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileConnectReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileConnectReqSizeof(void *msg); +#define CsrWifiNmeProfileConnectReqSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeWpsReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeWpsReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeWpsReqSizeof(void *msg); +#define CsrWifiNmeWpsReqSerFree CsrWifiNmePfree + +#define CsrWifiNmeWpsCancelReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeWpsCancelReqDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeWpsCancelReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeWpsCancelReqSerFree CsrWifiNmePfree + +#define CsrWifiNmeConnectionStatusGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeConnectionStatusGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeConnectionStatusGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeConnectionStatusGetReqSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeSimImsiGetResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeSimImsiGetResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeSimImsiGetResSizeof(void *msg); +extern void CsrWifiNmeSimImsiGetResSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeSimGsmAuthResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeSimGsmAuthResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeSimGsmAuthResSizeof(void *msg); +extern void CsrWifiNmeSimGsmAuthResSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeSimUmtsAuthResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeSimUmtsAuthResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeSimUmtsAuthResSizeof(void *msg); +extern void CsrWifiNmeSimUmtsAuthResSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeWpsConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeWpsConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeWpsConfigSetReqSizeof(void *msg); +extern void CsrWifiNmeWpsConfigSetReqSerFree(void *msg); + +#define CsrWifiNmeEventMaskSetReqSer CsrWifiEventCsrUint32Ser +#define CsrWifiNmeEventMaskSetReqDes CsrWifiEventCsrUint32Des +#define CsrWifiNmeEventMaskSetReqSizeof CsrWifiEventCsrUint32Sizeof +#define CsrWifiNmeEventMaskSetReqSerFree CsrWifiNmePfree + +#define CsrWifiNmeProfileSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeProfileSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeProfileSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeProfileSetCfmSerFree CsrWifiNmePfree + +#define CsrWifiNmeProfileDeleteCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeProfileDeleteCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeProfileDeleteCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeProfileDeleteCfmSerFree CsrWifiNmePfree + +#define CsrWifiNmeProfileDeleteAllCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeProfileDeleteAllCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeProfileDeleteAllCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeProfileDeleteAllCfmSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeProfileOrderSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileOrderSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileOrderSetCfmSizeof(void *msg); +#define CsrWifiNmeProfileOrderSetCfmSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeProfileConnectCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileConnectCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileConnectCfmSizeof(void *msg); +extern void CsrWifiNmeProfileConnectCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeWpsCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeWpsCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeWpsCfmSizeof(void *msg); +extern void CsrWifiNmeWpsCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeWpsCancelCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeWpsCancelCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeWpsCancelCfmSizeof(void *msg); +#define CsrWifiNmeWpsCancelCfmSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeConnectionStatusGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeConnectionStatusGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeConnectionStatusGetCfmSizeof(void *msg); +#define CsrWifiNmeConnectionStatusGetCfmSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeProfileUpdateIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileUpdateIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileUpdateIndSizeof(void *msg); +extern void CsrWifiNmeProfileUpdateIndSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeProfileDisconnectIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeProfileDisconnectIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeProfileDisconnectIndSizeof(void *msg); +extern void CsrWifiNmeProfileDisconnectIndSerFree(void *msg); + +#define CsrWifiNmeSimImsiGetIndSer CsrWifiEventSer +#define CsrWifiNmeSimImsiGetIndDes CsrWifiEventDes +#define CsrWifiNmeSimImsiGetIndSizeof CsrWifiEventSizeof +#define CsrWifiNmeSimImsiGetIndSerFree CsrWifiNmePfree + +extern CsrUint8* CsrWifiNmeSimGsmAuthIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeSimGsmAuthIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeSimGsmAuthIndSizeof(void *msg); +extern void CsrWifiNmeSimGsmAuthIndSerFree(void *msg); + +extern CsrUint8* CsrWifiNmeSimUmtsAuthIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiNmeSimUmtsAuthIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiNmeSimUmtsAuthIndSizeof(void *msg); +#define CsrWifiNmeSimUmtsAuthIndSerFree CsrWifiNmePfree + +#define CsrWifiNmeWpsConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeWpsConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeWpsConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeWpsConfigSetCfmSerFree CsrWifiNmePfree + +#define CsrWifiNmeEventMaskSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiNmeEventMaskSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiNmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiNmeEventMaskSetCfmSerFree CsrWifiNmePfree + + +#ifdef __cplusplus +} +#endif +#endif /* CSR_WIFI_NME_SERIALIZE_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_nme_task.h b/drivers/staging/csr/csr_wifi_nme_task.h new file mode 100644 index 000000000000..2a03a19e402f --- /dev/null +++ b/drivers/staging/csr/csr_wifi_nme_task.h @@ -0,0 +1,38 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_NME_TASK_H__ +#define CSR_WIFI_NME_TASK_H__ + +#include "csr_types.h" +#include "csr_sched.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_NME_ENABLE +#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_task.h +#endif + +#define CSR_WIFI_NME_LOG_ID 0x1203FFFF +extern CsrSchedQid CSR_WIFI_NME_IFACEQUEUE; +void CsrWifiNmeInit(void **gash); +void CsrWifiNmeDeinit(void **gash); +void CsrWifiNmeHandler(void **gash); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_NME_TASK_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_private_common.h b/drivers/staging/csr/csr_wifi_private_common.h new file mode 100644 index 000000000000..b1d12397bd6d --- /dev/null +++ b/drivers/staging/csr/csr_wifi_private_common.h @@ -0,0 +1,91 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_PRIVATE_COMMON_H__ +#define CSR_WIFI_PRIVATE_COMMON_H__ + +#include "csr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief maximum number of STAs allowed to be connected + * + * @par Description + * min & max Beacon Interval + */ +#define CSR_WIFI_AP_MAX_ASSOC_STA 8 + +/** Number of only b rates */ +#define CSR_WIFI_SME_AP_MAX_ONLY_B_RATES 4 + + +/** Number of mandatory b rates */ +#define CSR_WIFI_SME_AP_MAX_MANDATORY_B_RATES 2 + + +/** Number of mandatory bg rates */ +#define CSR_WIFI_SME_AP_MAX_MANDATORY_BG_RATES 4 + + +/** Number of bg rates */ +#define CSR_WIFI_SME_AP_MAX_BG_RATES 12 + + +/** Number of no b only g rates */ +#define CSR_WIFI_SME_AP_MAX_NO_B_ONLY_G_RATES 8 + + +/** Number of mandatory g rates */ +#define CSR_WIFI_SME_AP_MAX_MANDATORY_G_RATES 7 + + +/* Number of g mandatory rates */ +#define CSR_WIFI_SME_AP_G_MANDATORY_RATES_NUM 7 + + +/* Number of b mandatory rates */ +#define CSR_WIFI_SME_AP_B_MANDATORY_RATES_NUM 2 + + +/* Number of b/g mandatory rates */ +#define CSR_WIFI_SME_AP_BG_MANDATORY_RATES_NUM 4 + + +/* The maximum allowed length of SSID */ +#define CSR_WIFI_SME_AP_SSID_MAX_LENGTH 32 + +/* Refer 8.4.2.27 RSN element - we support TKIP, WPA2, WAPI and PSK only, no pmkid, group cipher suite */ +#define CSR_WIFI_SME_RSN_PACKED_SIZE (1 + 1 + 2 + 4 + 2 + 4 * 2 + 2 + 4 * 1 + 2 + 24) + +/* Refer 7.3.2.9 (ISO/IEC 8802-11:2006) WAPI element - we support WAPI PSK only, no bkid, group cipher suite */ +#define CSR_WIFI_SME_WAPI_PACKED_SIZE (1 + 1 + 2 + 2 + 4 * 1 + 2 + 4 * 1 + 4 + 2 + 24) + + +/* Common structure for NME and SME to maintain Interface mode*/ +typedef CsrUint8 CsrWifiInterfaceMode; +#define CSR_WIFI_MODE_NONE ((CsrWifiInterfaceMode) 0xFF) +#define CSR_WIFI_MODE_STA ((CsrWifiInterfaceMode) 0x00) +#define CSR_WIFI_MODE_AP ((CsrWifiInterfaceMode) 0x01) +#define CSR_WIFI_MODE_P2P_DEVICE ((CsrWifiInterfaceMode) 0x02) +#define CSR_WIFI_MODE_P2P_CLI ((CsrWifiInterfaceMode) 0x03) +#define CSR_WIFI_MODE_P2P_GO ((CsrWifiInterfaceMode) 0x04) +#define CSR_WIFI_MODE_AMP ((CsrWifiInterfaceMode) 0x05) +#define CSR_WIFI_MODE_WPS_ENROLLEE ((CsrWifiInterfaceMode) 0x06) +#define CSR_WIFI_MODE_IBSS ((CsrWifiInterfaceMode) 0x07) + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/drivers/staging/csr/csr_wifi_result.h b/drivers/staging/csr/csr_wifi_result.h new file mode 100644 index 000000000000..95b73a0d71e6 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_result.h @@ -0,0 +1,36 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_RESULT_H__ +#define CSR_WIFI_RESULT_H__ + +#include "csr_types.h" +#include "csr_result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* THIS FILE SHOULD CONTAIN ONLY RESULT CODES */ + +/* Result Codes */ +#define CSR_WIFI_HIP_RESULT_INVALID_VALUE ((CsrResult) 1) /* Invalid argument value */ +#define CSR_WIFI_HIP_RESULT_NO_DEVICE ((CsrResult) 2) /* The specified device is no longer present */ +#define CSR_WIFI_HIP_RESULT_NO_SPACE ((CsrResult) 3) /* A queue or buffer is full */ +#define CSR_WIFI_HIP_RESULT_NO_MEMORY ((CsrResult) 4) /* Fatal error, no memory */ +#define CSR_WIFI_HIP_RESULT_RANGE ((CsrResult) 5) /* Request exceeds the range of a file or a buffer */ +#define CSR_WIFI_HIP_RESULT_NOT_FOUND ((CsrResult) 6) /* A file (typically a f/w patch) is not found */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_RESULT_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.c b/drivers/staging/csr/csr_wifi_router_converter_init.c new file mode 100644 index 000000000000..f7ee3f0ec37d --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_converter_init.c @@ -0,0 +1,83 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_msgconv.h" +#include "csr_pmem.h" +#include "csr_util.h" + + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" +#endif + +#ifndef EXCLUDE_CSR_WIFI_ROUTER_MODULE +#include "csr_wifi_router_serialize.h" +#include "csr_wifi_router_prim.h" + +static CsrMsgConvMsgEntry csrwifirouter_conv_lut[] = { + { CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ, CsrWifiRouterMaPacketSubscribeReqSizeof, CsrWifiRouterMaPacketSubscribeReqSer, CsrWifiRouterMaPacketSubscribeReqDes, CsrWifiRouterMaPacketSubscribeReqSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ, CsrWifiRouterMaPacketUnsubscribeReqSizeof, CsrWifiRouterMaPacketUnsubscribeReqSer, CsrWifiRouterMaPacketUnsubscribeReqDes, CsrWifiRouterMaPacketUnsubscribeReqSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_REQ, CsrWifiRouterMaPacketReqSizeof, CsrWifiRouterMaPacketReqSer, CsrWifiRouterMaPacketReqDes, CsrWifiRouterMaPacketReqSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_RES, CsrWifiRouterMaPacketResSizeof, CsrWifiRouterMaPacketResSer, CsrWifiRouterMaPacketResDes, CsrWifiRouterMaPacketResSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ, CsrWifiRouterMaPacketCancelReqSizeof, CsrWifiRouterMaPacketCancelReqSer, CsrWifiRouterMaPacketCancelReqDes, CsrWifiRouterMaPacketCancelReqSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM, CsrWifiRouterMaPacketSubscribeCfmSizeof, CsrWifiRouterMaPacketSubscribeCfmSer, CsrWifiRouterMaPacketSubscribeCfmDes, CsrWifiRouterMaPacketSubscribeCfmSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM, CsrWifiRouterMaPacketUnsubscribeCfmSizeof, CsrWifiRouterMaPacketUnsubscribeCfmSer, CsrWifiRouterMaPacketUnsubscribeCfmDes, CsrWifiRouterMaPacketUnsubscribeCfmSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_CFM, CsrWifiRouterMaPacketCfmSizeof, CsrWifiRouterMaPacketCfmSer, CsrWifiRouterMaPacketCfmDes, CsrWifiRouterMaPacketCfmSerFree }, + { CSR_WIFI_ROUTER_MA_PACKET_IND, CsrWifiRouterMaPacketIndSizeof, CsrWifiRouterMaPacketIndSer, CsrWifiRouterMaPacketIndDes, CsrWifiRouterMaPacketIndSerFree }, + + { 0, NULL, NULL, NULL, NULL }, +}; + +CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16 msgType) +{ + if (msgType & CSR_PRIM_UPSTREAM) + { + CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT; + if (index < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) && + csrwifirouter_conv_lut[index].msgType == msgType) + { + return &csrwifirouter_conv_lut[index]; + } + } + else + { + if (msgType < CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT && + csrwifirouter_conv_lut[msgType].msgType == msgType) + { + return &csrwifirouter_conv_lut[msgType]; + } + } + return NULL; +} + + +void CsrWifiRouterConverterInit(void) +{ + CsrMsgConvInsert(CSR_WIFI_ROUTER_PRIM, csrwifirouter_conv_lut); + CsrMsgConvCustomLookupRegister(CSR_WIFI_ROUTER_PRIM, CsrWifiRouterConverterLookup); +} + + +#ifdef CSR_LOG_ENABLE +static const CsrLogPrimitiveInformation csrwifirouter_conv_info = { + CSR_WIFI_ROUTER_PRIM, + (CsrCharString *)"CSR_WIFI_ROUTER_PRIM", + csrwifirouter_conv_lut +}; +const CsrLogPrimitiveInformation* CsrWifiRouterTechInfoGet(void) +{ + return &csrwifirouter_conv_info; +} + + +#endif /* CSR_LOG_ENABLE */ +#endif /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.h b/drivers/staging/csr/csr_wifi_router_converter_init.h new file mode 100644 index 000000000000..2a293e457ffb --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_converter_init.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_CONVERTER_INIT_H__ +#define CSR_WIFI_ROUTER_CONVERTER_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXCLUDE_CSR_WIFI_ROUTER_MODULE + +#include "csr_msgconv.h" + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" + +extern const CsrLogPrimitiveInformation* CsrWifiRouterTechInfoGet(void); +#endif /* CSR_LOG_ENABLE */ + +extern void CsrWifiRouterConverterInit(void); + +#else /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ + +#define CsrWifiRouterConverterInit() + +#endif /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c new file mode 100644 index 000000000000..36403fcf97e8 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c @@ -0,0 +1,132 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_msgconv.h" +#include "csr_pmem.h" +#include "csr_util.h" + + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" +#endif + +#ifndef EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE +#include "csr_wifi_router_ctrl_serialize.h" +#include "csr_wifi_router_ctrl_prim.h" + +static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = { + { CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ, CsrWifiRouterCtrlConfigurePowerModeReqSizeof, CsrWifiRouterCtrlConfigurePowerModeReqSer, CsrWifiRouterCtrlConfigurePowerModeReqDes, CsrWifiRouterCtrlConfigurePowerModeReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_HIP_REQ, CsrWifiRouterCtrlHipReqSizeof, CsrWifiRouterCtrlHipReqSer, CsrWifiRouterCtrlHipReqDes, CsrWifiRouterCtrlHipReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ, CsrWifiRouterCtrlMediaStatusReqSizeof, CsrWifiRouterCtrlMediaStatusReqSer, CsrWifiRouterCtrlMediaStatusReqDes, CsrWifiRouterCtrlMediaStatusReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES, CsrWifiRouterCtrlMulticastAddressResSizeof, CsrWifiRouterCtrlMulticastAddressResSer, CsrWifiRouterCtrlMulticastAddressResDes, CsrWifiRouterCtrlMulticastAddressResSerFree }, + { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ, CsrWifiRouterCtrlPortConfigureReqSizeof, CsrWifiRouterCtrlPortConfigureReqSer, CsrWifiRouterCtrlPortConfigureReqDes, CsrWifiRouterCtrlPortConfigureReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ, CsrWifiRouterCtrlQosControlReqSizeof, CsrWifiRouterCtrlQosControlReqSer, CsrWifiRouterCtrlQosControlReqDes, CsrWifiRouterCtrlQosControlReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_SUSPEND_RES, CsrWifiRouterCtrlSuspendResSizeof, CsrWifiRouterCtrlSuspendResSer, CsrWifiRouterCtrlSuspendResDes, CsrWifiRouterCtrlSuspendResSerFree }, + { CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ, CsrWifiRouterCtrlTclasAddReqSizeof, CsrWifiRouterCtrlTclasAddReqSer, CsrWifiRouterCtrlTclasAddReqDes, CsrWifiRouterCtrlTclasAddReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_RESUME_RES, CsrWifiRouterCtrlResumeResSizeof, CsrWifiRouterCtrlResumeResSer, CsrWifiRouterCtrlResumeResDes, CsrWifiRouterCtrlResumeResSerFree }, + { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ, CsrWifiRouterCtrlRawSdioDeinitialiseReqSizeof, CsrWifiRouterCtrlRawSdioDeinitialiseReqSer, CsrWifiRouterCtrlRawSdioDeinitialiseReqDes, CsrWifiRouterCtrlRawSdioDeinitialiseReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ, CsrWifiRouterCtrlRawSdioInitialiseReqSizeof, CsrWifiRouterCtrlRawSdioInitialiseReqSer, CsrWifiRouterCtrlRawSdioInitialiseReqDes, CsrWifiRouterCtrlRawSdioInitialiseReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ, CsrWifiRouterCtrlTclasDelReqSizeof, CsrWifiRouterCtrlTclasDelReqSer, CsrWifiRouterCtrlTclasDelReqDes, CsrWifiRouterCtrlTclasDelReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ, CsrWifiRouterCtrlTrafficClassificationReqSizeof, CsrWifiRouterCtrlTrafficClassificationReqSer, CsrWifiRouterCtrlTrafficClassificationReqDes, CsrWifiRouterCtrlTrafficClassificationReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ, CsrWifiRouterCtrlTrafficConfigReqSizeof, CsrWifiRouterCtrlTrafficConfigReqSer, CsrWifiRouterCtrlTrafficConfigReqDes, CsrWifiRouterCtrlTrafficConfigReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ, CsrWifiRouterCtrlWifiOffReqSizeof, CsrWifiRouterCtrlWifiOffReqSer, CsrWifiRouterCtrlWifiOffReqDes, CsrWifiRouterCtrlWifiOffReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES, CsrWifiRouterCtrlWifiOffResSizeof, CsrWifiRouterCtrlWifiOffResSer, CsrWifiRouterCtrlWifiOffResDes, CsrWifiRouterCtrlWifiOffResSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, CsrWifiRouterCtrlWifiOnReqSizeof, CsrWifiRouterCtrlWifiOnReqSer, CsrWifiRouterCtrlWifiOnReqDes, CsrWifiRouterCtrlWifiOnReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES, CsrWifiRouterCtrlWifiOnResSizeof, CsrWifiRouterCtrlWifiOnResSer, CsrWifiRouterCtrlWifiOnResDes, CsrWifiRouterCtrlWifiOnResSerFree }, + { CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ, CsrWifiRouterCtrlM4TransmitReqSizeof, CsrWifiRouterCtrlM4TransmitReqSer, CsrWifiRouterCtrlM4TransmitReqDes, CsrWifiRouterCtrlM4TransmitReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ, CsrWifiRouterCtrlModeSetReqSizeof, CsrWifiRouterCtrlModeSetReqSer, CsrWifiRouterCtrlModeSetReqDes, CsrWifiRouterCtrlModeSetReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ, CsrWifiRouterCtrlPeerAddReqSizeof, CsrWifiRouterCtrlPeerAddReqSer, CsrWifiRouterCtrlPeerAddReqDes, CsrWifiRouterCtrlPeerAddReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ, CsrWifiRouterCtrlPeerDelReqSizeof, CsrWifiRouterCtrlPeerDelReqSer, CsrWifiRouterCtrlPeerDelReqDes, CsrWifiRouterCtrlPeerDelReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ, CsrWifiRouterCtrlPeerUpdateReqSizeof, CsrWifiRouterCtrlPeerUpdateReqSer, CsrWifiRouterCtrlPeerUpdateReqDes, CsrWifiRouterCtrlPeerUpdateReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, CsrWifiRouterCtrlBlockAckDisableReqSizeof, CsrWifiRouterCtrlBlockAckDisableReqSer, CsrWifiRouterCtrlBlockAckDisableReqDes, CsrWifiRouterCtrlBlockAckDisableReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, CsrWifiRouterCtrlWapiMulticastReqSizeof, CsrWifiRouterCtrlWapiMulticastReqSer, CsrWifiRouterCtrlWapiMulticastReqDes, CsrWifiRouterCtrlWapiMulticastReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, CsrWifiRouterCtrlWapiMulticastFilterReqSizeof, CsrWifiRouterCtrlWapiMulticastFilterReqSer, CsrWifiRouterCtrlWapiMulticastFilterReqDes, CsrWifiRouterCtrlWapiMulticastFilterReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, CsrWifiRouterCtrlWapiUnicastFilterReqSizeof, CsrWifiRouterCtrlWapiUnicastFilterReqSer, CsrWifiRouterCtrlWapiUnicastFilterReqDes, CsrWifiRouterCtrlWapiUnicastFilterReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_RESUME_IND, CsrWifiRouterCtrlResumeIndSizeof, CsrWifiRouterCtrlResumeIndSer, CsrWifiRouterCtrlResumeIndDes, CsrWifiRouterCtrlResumeIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_SUSPEND_IND, CsrWifiRouterCtrlSuspendIndSizeof, CsrWifiRouterCtrlSuspendIndSer, CsrWifiRouterCtrlSuspendIndDes, CsrWifiRouterCtrlSuspendIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM, CsrWifiRouterCtrlTclasAddCfmSizeof, CsrWifiRouterCtrlTclasAddCfmSer, CsrWifiRouterCtrlTclasAddCfmDes, CsrWifiRouterCtrlTclasAddCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer, CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM, CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof, CsrWifiRouterCtrlRawSdioInitialiseCfmSer, CsrWifiRouterCtrlRawSdioInitialiseCfmDes, CsrWifiRouterCtrlRawSdioInitialiseCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM, CsrWifiRouterCtrlTclasDelCfmSizeof, CsrWifiRouterCtrlTclasDelCfmSer, CsrWifiRouterCtrlTclasDelCfmDes, CsrWifiRouterCtrlTclasDelCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND, CsrWifiRouterCtrlTrafficProtocolIndSizeof, CsrWifiRouterCtrlTrafficProtocolIndSer, CsrWifiRouterCtrlTrafficProtocolIndDes, CsrWifiRouterCtrlTrafficProtocolIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND, CsrWifiRouterCtrlTrafficSampleIndSizeof, CsrWifiRouterCtrlTrafficSampleIndSer, CsrWifiRouterCtrlTrafficSampleIndDes, CsrWifiRouterCtrlTrafficSampleIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND, CsrWifiRouterCtrlWifiOffIndSizeof, CsrWifiRouterCtrlWifiOffIndSer, CsrWifiRouterCtrlWifiOffIndDes, CsrWifiRouterCtrlWifiOffIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM, CsrWifiRouterCtrlWifiOffCfmSizeof, CsrWifiRouterCtrlWifiOffCfmSer, CsrWifiRouterCtrlWifiOffCfmDes, CsrWifiRouterCtrlWifiOffCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND, CsrWifiRouterCtrlWifiOnIndSizeof, CsrWifiRouterCtrlWifiOnIndSer, CsrWifiRouterCtrlWifiOnIndDes, CsrWifiRouterCtrlWifiOnIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM, CsrWifiRouterCtrlWifiOnCfmSizeof, CsrWifiRouterCtrlWifiOnCfmSer, CsrWifiRouterCtrlWifiOnCfmDes, CsrWifiRouterCtrlWifiOnCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND, CsrWifiRouterCtrlM4ReadyToSendIndSizeof, CsrWifiRouterCtrlM4ReadyToSendIndSer, CsrWifiRouterCtrlM4ReadyToSendIndDes, CsrWifiRouterCtrlM4ReadyToSendIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND, CsrWifiRouterCtrlM4TransmittedIndSizeof, CsrWifiRouterCtrlM4TransmittedIndSer, CsrWifiRouterCtrlM4TransmittedIndDes, CsrWifiRouterCtrlM4TransmittedIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND, CsrWifiRouterCtrlMicFailureIndSizeof, CsrWifiRouterCtrlMicFailureIndSer, CsrWifiRouterCtrlMicFailureIndDes, CsrWifiRouterCtrlMicFailureIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_CONNECTED_IND, CsrWifiRouterCtrlConnectedIndSizeof, CsrWifiRouterCtrlConnectedIndSer, CsrWifiRouterCtrlConnectedIndDes, CsrWifiRouterCtrlConnectedIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM, CsrWifiRouterCtrlPeerAddCfmSizeof, CsrWifiRouterCtrlPeerAddCfmSer, CsrWifiRouterCtrlPeerAddCfmDes, CsrWifiRouterCtrlPeerAddCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM, CsrWifiRouterCtrlPeerDelCfmSizeof, CsrWifiRouterCtrlPeerDelCfmSer, CsrWifiRouterCtrlPeerDelCfmDes, CsrWifiRouterCtrlPeerDelCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND, CsrWifiRouterCtrlUnexpectedFrameIndSizeof, CsrWifiRouterCtrlUnexpectedFrameIndSer, CsrWifiRouterCtrlUnexpectedFrameIndDes, CsrWifiRouterCtrlUnexpectedFrameIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM, CsrWifiRouterCtrlPeerUpdateCfmSizeof, CsrWifiRouterCtrlPeerUpdateCfmSer, CsrWifiRouterCtrlPeerUpdateCfmDes, CsrWifiRouterCtrlPeerUpdateCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM, CsrWifiRouterCtrlCapabilitiesCfmSizeof, CsrWifiRouterCtrlCapabilitiesCfmSer, CsrWifiRouterCtrlCapabilitiesCfmDes, CsrWifiRouterCtrlCapabilitiesCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM, CsrWifiRouterCtrlBlockAckEnableCfmSizeof, CsrWifiRouterCtrlBlockAckEnableCfmSer, CsrWifiRouterCtrlBlockAckEnableCfmDes, CsrWifiRouterCtrlBlockAckEnableCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, CsrWifiRouterCtrlStaInactiveIndSizeof, CsrWifiRouterCtrlStaInactiveIndSer, CsrWifiRouterCtrlStaInactiveIndDes, CsrWifiRouterCtrlStaInactiveIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, CsrWifiRouterCtrlWapiMulticastIndSizeof, CsrWifiRouterCtrlWapiMulticastIndSer, CsrWifiRouterCtrlWapiMulticastIndDes, CsrWifiRouterCtrlWapiMulticastIndSerFree }, + + { 0, NULL, NULL, NULL, NULL }, +}; + +CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16 msgType) +{ + if (msgType & CSR_PRIM_UPSTREAM) + { + CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT; + if (index < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) && + csrwifirouterctrl_conv_lut[index].msgType == msgType) + { + return &csrwifirouterctrl_conv_lut[index]; + } + } + else + { + if (msgType < CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT && + csrwifirouterctrl_conv_lut[msgType].msgType == msgType) + { + return &csrwifirouterctrl_conv_lut[msgType]; + } + } + return NULL; +} + + +void CsrWifiRouterCtrlConverterInit(void) +{ + CsrMsgConvInsert(CSR_WIFI_ROUTER_CTRL_PRIM, csrwifirouterctrl_conv_lut); + CsrMsgConvCustomLookupRegister(CSR_WIFI_ROUTER_CTRL_PRIM, CsrWifiRouterCtrlConverterLookup); +} + + +#ifdef CSR_LOG_ENABLE +static const CsrLogPrimitiveInformation csrwifirouterctrl_conv_info = { + CSR_WIFI_ROUTER_CTRL_PRIM, + (CsrCharString *)"CSR_WIFI_ROUTER_CTRL_PRIM", + csrwifirouterctrl_conv_lut +}; +const CsrLogPrimitiveInformation* CsrWifiRouterCtrlTechInfoGet(void) +{ + return &csrwifirouterctrl_conv_info; +} + + +#endif /* CSR_LOG_ENABLE */ +#endif /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h new file mode 100644 index 000000000000..0c9d26b7a0b4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ +#define CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE + +#include "csr_msgconv.h" + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" + +extern const CsrLogPrimitiveInformation* CsrWifiRouterCtrlTechInfoGet(void); +#endif /* CSR_LOG_ENABLE */ + +extern void CsrWifiRouterCtrlConverterInit(void); + +#else /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ + +#define CsrWifiRouterCtrlConverterInit() + +#endif /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c new file mode 100644 index 000000000000..57aa36739590 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c @@ -0,0 +1,95 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_router_ctrl_prim.h" +#include "csr_wifi_router_ctrl_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiRouterCtrlFreeDownstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_ROUTER_CTRL_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_ROUTER_CTRL_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiRouterCtrlPrim *) message)) + { + case CSR_WIFI_ROUTER_CTRL_HIP_REQ: + { + CsrWifiRouterCtrlHipReq *p = (CsrWifiRouterCtrlHipReq *)message; + CsrPmemFree(p->mlmeCommand); + p->mlmeCommand = NULL; + CsrPmemFree(p->dataRef1); + p->dataRef1 = NULL; + CsrPmemFree(p->dataRef2); + p->dataRef2 = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES: + { + CsrWifiRouterCtrlMulticastAddressRes *p = (CsrWifiRouterCtrlMulticastAddressRes *)message; + CsrPmemFree(p->getAddresses); + p->getAddresses = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ: + { + CsrWifiRouterCtrlTclasAddReq *p = (CsrWifiRouterCtrlTclasAddReq *)message; + CsrPmemFree(p->tclas); + p->tclas = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ: + { + CsrWifiRouterCtrlTclasDelReq *p = (CsrWifiRouterCtrlTclasDelReq *)message; + CsrPmemFree(p->tclas); + p->tclas = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES: + { + CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message; + CsrPmemFree(p->smeVersions.smeBuild); + p->smeVersions.smeBuild = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ: + { + CsrWifiRouterCtrlWapiMulticastReq *p = (CsrWifiRouterCtrlWapiMulticastReq *)message; + CsrPmemFree(p->signal); + p->signal = NULL; + CsrPmemFree(p->data); + p->data = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c new file mode 100644 index 000000000000..25e327357a32 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c @@ -0,0 +1,81 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_router_ctrl_prim.h" +#include "csr_wifi_router_ctrl_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiRouterCtrlFreeUpstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_ROUTER_CTRL_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_ROUTER_CTRL_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiRouterCtrlPrim *) message)) + { + case CSR_WIFI_ROUTER_CTRL_HIP_IND: + { + CsrWifiRouterCtrlHipInd *p = (CsrWifiRouterCtrlHipInd *)message; + CsrPmemFree(p->mlmeCommand); + p->mlmeCommand = NULL; + CsrPmemFree(p->dataRef1); + p->dataRef1 = NULL; + CsrPmemFree(p->dataRef2); + p->dataRef2 = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND: + { + CsrWifiRouterCtrlMulticastAddressInd *p = (CsrWifiRouterCtrlMulticastAddressInd *)message; + CsrPmemFree(p->setAddresses); + p->setAddresses = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND: + { + CsrWifiRouterCtrlWifiOnInd *p = (CsrWifiRouterCtrlWifiOnInd *)message; + CsrPmemFree(p->versions.routerBuild); + p->versions.routerBuild = NULL; + break; + } + case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND: + { + CsrWifiRouterCtrlWapiMulticastInd *p = (CsrWifiRouterCtrlWapiMulticastInd *)message; + CsrPmemFree(p->signal); + p->signal = NULL; + CsrPmemFree(p->data); + p->data = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h new file mode 100644 index 000000000000..f0ad836b00c5 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h @@ -0,0 +1,1958 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_CTRL_LIB_H__ +#define CSR_WIFI_ROUTER_CTRL_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_router_ctrl_prim.h" +#include "csr_wifi_router_task.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiRouterCtrlFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_ROUTER_CTRL upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_ROUTER_CTRL upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiRouterCtrlFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_ROUTER_CTRL downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_ROUTER_CTRL downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiRouterCtrlBlockAckRoleToString(CsrWifiRouterCtrlBlockAckRole value); +const CsrCharString* CsrWifiRouterCtrlControlIndicationToString(CsrWifiRouterCtrlControlIndication value); +const CsrCharString* CsrWifiRouterCtrlListActionToString(CsrWifiRouterCtrlListAction value); +const CsrCharString* CsrWifiRouterCtrlLowPowerModeToString(CsrWifiRouterCtrlLowPowerMode value); +const CsrCharString* CsrWifiRouterCtrlMediaStatusToString(CsrWifiRouterCtrlMediaStatus value); +const CsrCharString* CsrWifiRouterCtrlModeToString(CsrWifiRouterCtrlMode value); +const CsrCharString* CsrWifiRouterCtrlPeerStatusToString(CsrWifiRouterCtrlPeerStatus value); +const CsrCharString* CsrWifiRouterCtrlPortActionToString(CsrWifiRouterCtrlPortAction value); +const CsrCharString* CsrWifiRouterCtrlPowersaveTypeToString(CsrWifiRouterCtrlPowersaveType value); +const CsrCharString* CsrWifiRouterCtrlProtocolDirectionToString(CsrWifiRouterCtrlProtocolDirection value); +const CsrCharString* CsrWifiRouterCtrlQoSControlToString(CsrWifiRouterCtrlQoSControl value); +const CsrCharString* CsrWifiRouterCtrlQueueConfigToString(CsrWifiRouterCtrlQueueConfig value); +const CsrCharString* CsrWifiRouterCtrlTrafficConfigTypeToString(CsrWifiRouterCtrlTrafficConfigType value); +const CsrCharString* CsrWifiRouterCtrlTrafficPacketTypeToString(CsrWifiRouterCtrlTrafficPacketType value); +const CsrCharString* CsrWifiRouterCtrlTrafficTypeToString(CsrWifiRouterCtrlTrafficType value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiRouterCtrlPrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiRouterCtrlUpstreamPrimNames[CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckDisableReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + macAddress - + trafficStreamID - + role - + +*******************************************************************************/ +#define CsrWifiRouterCtrlBlockAckDisableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ + msg__ = (CsrWifiRouterCtrlBlockAckDisableReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckDisableReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->macAddress = (macAddress__); \ + msg__->trafficStreamID = (trafficStreamID__); \ + msg__->role = (role__); + +#define CsrWifiRouterCtrlBlockAckDisableReqSendTo(dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ + { \ + CsrWifiRouterCtrlBlockAckDisableReq *msg__; \ + CsrWifiRouterCtrlBlockAckDisableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlBlockAckDisableReqSend(src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ + CsrWifiRouterCtrlBlockAckDisableReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckDisableCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlBlockAckDisableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlBlockAckDisableCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckDisableCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlBlockAckDisableCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlBlockAckDisableCfm *msg__; \ + CsrWifiRouterCtrlBlockAckDisableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlBlockAckDisableCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlBlockAckDisableCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckEnableReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + macAddress - + trafficStreamID - + role - + bufferSize - + timeout - + ssn - + +*******************************************************************************/ +#define CsrWifiRouterCtrlBlockAckEnableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ + msg__ = (CsrWifiRouterCtrlBlockAckEnableReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckEnableReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->macAddress = (macAddress__); \ + msg__->trafficStreamID = (trafficStreamID__); \ + msg__->role = (role__); \ + msg__->bufferSize = (bufferSize__); \ + msg__->timeout = (timeout__); \ + msg__->ssn = (ssn__); + +#define CsrWifiRouterCtrlBlockAckEnableReqSendTo(dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ + { \ + CsrWifiRouterCtrlBlockAckEnableReq *msg__; \ + CsrWifiRouterCtrlBlockAckEnableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlBlockAckEnableReqSend(src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ + CsrWifiRouterCtrlBlockAckEnableReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckEnableCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlBlockAckEnableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlBlockAckEnableCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckEnableCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlBlockAckEnableCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlBlockAckEnableCfm *msg__; \ + CsrWifiRouterCtrlBlockAckEnableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlBlockAckEnableCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlBlockAckEnableCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckErrorIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + trafficStreamID - + peerMacAddress - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlBlockAckErrorIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ + msg__ = (CsrWifiRouterCtrlBlockAckErrorInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckErrorInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->trafficStreamID = (trafficStreamID__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlBlockAckErrorIndSendTo(dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ + { \ + CsrWifiRouterCtrlBlockAckErrorInd *msg__; \ + CsrWifiRouterCtrlBlockAckErrorIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlBlockAckErrorIndSend(dst__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ + CsrWifiRouterCtrlBlockAckErrorIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlCapabilitiesReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlCapabilitiesReqCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlCapabilitiesReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlCapabilitiesReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlCapabilitiesReqSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlCapabilitiesReq *msg__; \ + CsrWifiRouterCtrlCapabilitiesReqCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlCapabilitiesReqSend(src__, clientData__) \ + CsrWifiRouterCtrlCapabilitiesReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlCapabilitiesCfmSend + + DESCRIPTION + The router sends this primitive to confirm the size of the queues of the + HIP. + + PARAMETERS + queue - Destination Task Queue + clientData - + commandQueueSize - Size of command queue + trafficQueueSize - Size of traffic queue (per AC) + +*******************************************************************************/ +#define CsrWifiRouterCtrlCapabilitiesCfmCreate(msg__, dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__) \ + msg__ = (CsrWifiRouterCtrlCapabilitiesCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlCapabilitiesCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->commandQueueSize = (commandQueueSize__); \ + msg__->trafficQueueSize = (trafficQueueSize__); + +#define CsrWifiRouterCtrlCapabilitiesCfmSendTo(dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__) \ + { \ + CsrWifiRouterCtrlCapabilitiesCfm *msg__; \ + CsrWifiRouterCtrlCapabilitiesCfmCreate(msg__, dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlCapabilitiesCfmSend(dst__, clientData__, commandQueueSize__, trafficQueueSize__) \ + CsrWifiRouterCtrlCapabilitiesCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, commandQueueSize__, trafficQueueSize__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlConfigurePowerModeReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + mode - + wakeHost - + +*******************************************************************************/ +#define CsrWifiRouterCtrlConfigurePowerModeReqCreate(msg__, dst__, src__, clientData__, mode__, wakeHost__) \ + msg__ = (CsrWifiRouterCtrlConfigurePowerModeReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlConfigurePowerModeReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->mode = (mode__); \ + msg__->wakeHost = (wakeHost__); + +#define CsrWifiRouterCtrlConfigurePowerModeReqSendTo(dst__, src__, clientData__, mode__, wakeHost__) \ + { \ + CsrWifiRouterCtrlConfigurePowerModeReq *msg__; \ + CsrWifiRouterCtrlConfigurePowerModeReqCreate(msg__, dst__, src__, clientData__, mode__, wakeHost__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlConfigurePowerModeReqSend(src__, clientData__, mode__, wakeHost__) \ + CsrWifiRouterCtrlConfigurePowerModeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, mode__, wakeHost__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlConnectedIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + peerStatus - + +*******************************************************************************/ +#define CsrWifiRouterCtrlConnectedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ + msg__ = (CsrWifiRouterCtrlConnectedInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlConnectedInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CONNECTED_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->peerStatus = (peerStatus__); + +#define CsrWifiRouterCtrlConnectedIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ + { \ + CsrWifiRouterCtrlConnectedInd *msg__; \ + CsrWifiRouterCtrlConnectedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlConnectedIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ + CsrWifiRouterCtrlConnectedIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlHipReqSend + + DESCRIPTION + This primitive is used for transferring MLME messages to the HIP. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + mlmeCommandLength - Length of the MLME signal + mlmeCommand - Pointer to the MLME signal + dataRef1Length - Length of the dataRef1 bulk data + dataRef1 - Pointer to the bulk data 1 + dataRef2Length - Length of the dataRef2 bulk data + dataRef2 - Pointer to the bulk data 2 + +*******************************************************************************/ +#define CsrWifiRouterCtrlHipReqCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + msg__ = (CsrWifiRouterCtrlHipReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlHipReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_HIP_REQ, dst__, src__); \ + msg__->mlmeCommandLength = (mlmeCommandLength__); \ + msg__->mlmeCommand = (mlmeCommand__); \ + msg__->dataRef1Length = (dataRef1Length__); \ + msg__->dataRef1 = (dataRef1__); \ + msg__->dataRef2Length = (dataRef2Length__); \ + msg__->dataRef2 = (dataRef2__); + +#define CsrWifiRouterCtrlHipReqSendTo(dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + { \ + CsrWifiRouterCtrlHipReq *msg__; \ + CsrWifiRouterCtrlHipReqCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlHipReqSend(src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + CsrWifiRouterCtrlHipReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlHipIndSend + + DESCRIPTION + This primitive is used for transferring MLME messages from the HIP. + + PARAMETERS + queue - Destination Task Queue + mlmeCommandLength - Length of the MLME signal + mlmeCommand - Pointer to the MLME signal + dataRef1Length - Length of the dataRef1 bulk data + dataRef1 - Pointer to the bulk data 1 + dataRef2Length - Length of the dataRef2 bulk data + dataRef2 - Pointer to the bulk data 2 + +*******************************************************************************/ +#define CsrWifiRouterCtrlHipIndCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + msg__ = (CsrWifiRouterCtrlHipInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlHipInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_HIP_IND, dst__, src__); \ + msg__->mlmeCommandLength = (mlmeCommandLength__); \ + msg__->mlmeCommand = (mlmeCommand__); \ + msg__->dataRef1Length = (dataRef1Length__); \ + msg__->dataRef1 = (dataRef1__); \ + msg__->dataRef2Length = (dataRef2Length__); \ + msg__->dataRef2 = (dataRef2__); + +#define CsrWifiRouterCtrlHipIndSendTo(dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + { \ + CsrWifiRouterCtrlHipInd *msg__; \ + CsrWifiRouterCtrlHipIndCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlHipIndSend(dst__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ + CsrWifiRouterCtrlHipIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4ReadyToSendIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +#define CsrWifiRouterCtrlM4ReadyToSendIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ + msg__ = (CsrWifiRouterCtrlM4ReadyToSendInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4ReadyToSendInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); + +#define CsrWifiRouterCtrlM4ReadyToSendIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ + { \ + CsrWifiRouterCtrlM4ReadyToSendInd *msg__; \ + CsrWifiRouterCtrlM4ReadyToSendIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlM4ReadyToSendIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \ + CsrWifiRouterCtrlM4ReadyToSendIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4TransmitReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlM4TransmitReqCreate(msg__, dst__, src__, interfaceTag__, clientData__) \ + msg__ = (CsrWifiRouterCtrlM4TransmitReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4TransmitReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlM4TransmitReqSendTo(dst__, src__, interfaceTag__, clientData__) \ + { \ + CsrWifiRouterCtrlM4TransmitReq *msg__; \ + CsrWifiRouterCtrlM4TransmitReqCreate(msg__, dst__, src__, interfaceTag__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlM4TransmitReqSend(src__, interfaceTag__, clientData__) \ + CsrWifiRouterCtrlM4TransmitReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4TransmittedIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlM4TransmittedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__) \ + msg__ = (CsrWifiRouterCtrlM4TransmittedInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4TransmittedInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlM4TransmittedIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__) \ + { \ + CsrWifiRouterCtrlM4TransmittedInd *msg__; \ + CsrWifiRouterCtrlM4TransmittedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlM4TransmittedIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, status__) \ + CsrWifiRouterCtrlM4TransmittedIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMediaStatusReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + mediaStatus - + +*******************************************************************************/ +#define CsrWifiRouterCtrlMediaStatusReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mediaStatus__) \ + msg__ = (CsrWifiRouterCtrlMediaStatusReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMediaStatusReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->mediaStatus = (mediaStatus__); + +#define CsrWifiRouterCtrlMediaStatusReqSendTo(dst__, src__, interfaceTag__, clientData__, mediaStatus__) \ + { \ + CsrWifiRouterCtrlMediaStatusReq *msg__; \ + CsrWifiRouterCtrlMediaStatusReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mediaStatus__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlMediaStatusReqSend(src__, interfaceTag__, clientData__, mediaStatus__) \ + CsrWifiRouterCtrlMediaStatusReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mediaStatus__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMicFailureIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + unicastPdu - + +*******************************************************************************/ +#define CsrWifiRouterCtrlMicFailureIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ + msg__ = (CsrWifiRouterCtrlMicFailureInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMicFailureInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->unicastPdu = (unicastPdu__); + +#define CsrWifiRouterCtrlMicFailureIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ + { \ + CsrWifiRouterCtrlMicFailureInd *msg__; \ + CsrWifiRouterCtrlMicFailureIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlMicFailureIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ + CsrWifiRouterCtrlMicFailureIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlModeSetReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + mode - + bssid - BSSID of the network the device is going to be a part + of + protection - Set to TRUE if encryption is enabled for the + connection/broadcast frames + intraBssDistEnabled - If set to TRUE, intra BSS destribution will be + enabled. If set to FALSE, any unicast PDU which does + not have the RA as the the local MAC address, shall be + ignored. This field is interpreted by the receive if + mode is set to CSR_WIFI_ROUTER_CTRL_MODE_P2PGO + +*******************************************************************************/ +#define CsrWifiRouterCtrlModeSetReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ + msg__ = (CsrWifiRouterCtrlModeSetReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->mode = (mode__); \ + msg__->bssid = (bssid__); \ + msg__->protection = (protection__); \ + msg__->intraBssDistEnabled = (intraBssDistEnabled__); + +#define CsrWifiRouterCtrlModeSetReqSendTo(dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ + { \ + CsrWifiRouterCtrlModeSetReq *msg__; \ + CsrWifiRouterCtrlModeSetReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ + CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMulticastAddressIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + action - + setAddressesCount - + setAddresses - + +*******************************************************************************/ +#define CsrWifiRouterCtrlMulticastAddressIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + msg__ = (CsrWifiRouterCtrlMulticastAddressInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMulticastAddressInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->setAddressesCount = (setAddressesCount__); \ + msg__->setAddresses = (setAddresses__); + +#define CsrWifiRouterCtrlMulticastAddressIndSendTo(dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + { \ + CsrWifiRouterCtrlMulticastAddressInd *msg__; \ + CsrWifiRouterCtrlMulticastAddressIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlMulticastAddressIndSend(dst__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + CsrWifiRouterCtrlMulticastAddressIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMulticastAddressResSend + + DESCRIPTION + + PARAMETERS + interfaceTag - + clientData - + status - + action - + getAddressesCount - + getAddresses - + +*******************************************************************************/ +#define CsrWifiRouterCtrlMulticastAddressResCreate(msg__, dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ + msg__ = (CsrWifiRouterCtrlMulticastAddressRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMulticastAddressRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); \ + msg__->action = (action__); \ + msg__->getAddressesCount = (getAddressesCount__); \ + msg__->getAddresses = (getAddresses__); + +#define CsrWifiRouterCtrlMulticastAddressResSendTo(dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ + { \ + CsrWifiRouterCtrlMulticastAddressRes *msg__; \ + CsrWifiRouterCtrlMulticastAddressResCreate(msg__, dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlMulticastAddressResSend(src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ + CsrWifiRouterCtrlMulticastAddressResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerAddReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + peerMacAddress - + associationId - + staInfo - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ + msg__ = (CsrWifiRouterCtrlPeerAddReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerAddReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->associationId = (associationId__); \ + msg__->staInfo = (staInfo__); + +#define CsrWifiRouterCtrlPeerAddReqSendTo(dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ + { \ + CsrWifiRouterCtrlPeerAddReq *msg__; \ + CsrWifiRouterCtrlPeerAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerAddReqSend(src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ + CsrWifiRouterCtrlPeerAddReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerAddCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + peerRecordHandle - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ + msg__ = (CsrWifiRouterCtrlPeerAddCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerAddCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->peerRecordHandle = (peerRecordHandle__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlPeerAddCfmSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ + { \ + CsrWifiRouterCtrlPeerAddCfm *msg__; \ + CsrWifiRouterCtrlPeerAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerAddCfmSend(dst__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ + CsrWifiRouterCtrlPeerAddCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerDelReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + peerRecordHandle - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__) \ + msg__ = (CsrWifiRouterCtrlPeerDelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerDelReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->peerRecordHandle = (peerRecordHandle__); + +#define CsrWifiRouterCtrlPeerDelReqSendTo(dst__, src__, interfaceTag__, clientData__, peerRecordHandle__) \ + { \ + CsrWifiRouterCtrlPeerDelReq *msg__; \ + CsrWifiRouterCtrlPeerDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerDelReqSend(src__, interfaceTag__, clientData__, peerRecordHandle__) \ + CsrWifiRouterCtrlPeerDelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerRecordHandle__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerDelCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlPeerDelCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerDelCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlPeerDelCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlPeerDelCfm *msg__; \ + CsrWifiRouterCtrlPeerDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerDelCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlPeerDelCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerUpdateReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + peerRecordHandle - + powersaveMode - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerUpdateReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ + msg__ = (CsrWifiRouterCtrlPeerUpdateReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerUpdateReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->peerRecordHandle = (peerRecordHandle__); \ + msg__->powersaveMode = (powersaveMode__); + +#define CsrWifiRouterCtrlPeerUpdateReqSendTo(dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ + { \ + CsrWifiRouterCtrlPeerUpdateReq *msg__; \ + CsrWifiRouterCtrlPeerUpdateReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerUpdateReqSend(src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ + CsrWifiRouterCtrlPeerUpdateReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerUpdateCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPeerUpdateCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlPeerUpdateCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerUpdateCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlPeerUpdateCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlPeerUpdateCfm *msg__; \ + CsrWifiRouterCtrlPeerUpdateCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPeerUpdateCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlPeerUpdateCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPortConfigureReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + uncontrolledPortAction - + controlledPortAction - + macAddress - + setProtection - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPortConfigureReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ + msg__ = (CsrWifiRouterCtrlPortConfigureReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPortConfigureReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->uncontrolledPortAction = (uncontrolledPortAction__); \ + msg__->controlledPortAction = (controlledPortAction__); \ + msg__->macAddress = (macAddress__); \ + msg__->setProtection = (setProtection__); + +#define CsrWifiRouterCtrlPortConfigureReqSendTo(dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ + { \ + CsrWifiRouterCtrlPortConfigureReq *msg__; \ + CsrWifiRouterCtrlPortConfigureReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPortConfigureReqSend(src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ + CsrWifiRouterCtrlPortConfigureReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPortConfigureCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + macAddress - + +*******************************************************************************/ +#define CsrWifiRouterCtrlPortConfigureCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__, macAddress__) \ + msg__ = (CsrWifiRouterCtrlPortConfigureCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPortConfigureCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->macAddress = (macAddress__); + +#define CsrWifiRouterCtrlPortConfigureCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__, macAddress__) \ + { \ + CsrWifiRouterCtrlPortConfigureCfm *msg__; \ + CsrWifiRouterCtrlPortConfigureCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__, macAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlPortConfigureCfmSend(dst__, clientData__, interfaceTag__, status__, macAddress__) \ + CsrWifiRouterCtrlPortConfigureCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__, macAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlQosControlReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + control - + queueConfig - + +*******************************************************************************/ +#define CsrWifiRouterCtrlQosControlReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, control__, queueConfig__) \ + msg__ = (CsrWifiRouterCtrlQosControlReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlQosControlReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->control = (control__); \ + msg__->queueConfig = (queueConfig__); + +#define CsrWifiRouterCtrlQosControlReqSendTo(dst__, src__, interfaceTag__, clientData__, control__, queueConfig__) \ + { \ + CsrWifiRouterCtrlQosControlReq *msg__; \ + CsrWifiRouterCtrlQosControlReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, control__, queueConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlQosControlReqSend(src__, interfaceTag__, clientData__, control__, queueConfig__) \ + CsrWifiRouterCtrlQosControlReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, control__, queueConfig__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioDeinitialiseReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlRawSdioDeinitialiseReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlRawSdioDeinitialiseReq *msg__; \ + CsrWifiRouterCtrlRawSdioDeinitialiseReqCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSend(src__, clientData__) \ + CsrWifiRouterCtrlRawSdioDeinitialiseReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioDeinitialiseCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + result - + +*******************************************************************************/ +#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmCreate(msg__, dst__, src__, clientData__, result__) \ + msg__ = (CsrWifiRouterCtrlRawSdioDeinitialiseCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->result = (result__); + +#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSendTo(dst__, src__, clientData__, result__) \ + { \ + CsrWifiRouterCtrlRawSdioDeinitialiseCfm *msg__; \ + CsrWifiRouterCtrlRawSdioDeinitialiseCfmCreate(msg__, dst__, src__, clientData__, result__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSend(dst__, clientData__, result__) \ + CsrWifiRouterCtrlRawSdioDeinitialiseCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, result__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioInitialiseReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlRawSdioInitialiseReqCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlRawSdioInitialiseReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlRawSdioInitialiseReqSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlRawSdioInitialiseReq *msg__; \ + CsrWifiRouterCtrlRawSdioInitialiseReqCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlRawSdioInitialiseReqSend(src__, clientData__) \ + CsrWifiRouterCtrlRawSdioInitialiseReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioInitialiseCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + result - + byteRead - + byteWrite - + firmwareDownload - + reset - + coreDumpPrepare - + byteBlockRead - + gpRead16 - + gpWrite16 - + +*******************************************************************************/ +#define CsrWifiRouterCtrlRawSdioInitialiseCfmCreate(msg__, dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ + msg__ = (CsrWifiRouterCtrlRawSdioInitialiseCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->result = (result__); \ + msg__->byteRead = (byteRead__); \ + msg__->byteWrite = (byteWrite__); \ + msg__->firmwareDownload = (firmwareDownload__); \ + msg__->reset = (reset__); \ + msg__->coreDumpPrepare = (coreDumpPrepare__); \ + msg__->byteBlockRead = (byteBlockRead__); \ + msg__->gpRead16 = (gpRead16__); \ + msg__->gpWrite16 = (gpWrite16__); + +#define CsrWifiRouterCtrlRawSdioInitialiseCfmSendTo(dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ + { \ + CsrWifiRouterCtrlRawSdioInitialiseCfm *msg__; \ + CsrWifiRouterCtrlRawSdioInitialiseCfmCreate(msg__, dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlRawSdioInitialiseCfmSend(dst__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ + CsrWifiRouterCtrlRawSdioInitialiseCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlResumeIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + powerMaintained - + +*******************************************************************************/ +#define CsrWifiRouterCtrlResumeIndCreate(msg__, dst__, src__, clientData__, powerMaintained__) \ + msg__ = (CsrWifiRouterCtrlResumeInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlResumeInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RESUME_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->powerMaintained = (powerMaintained__); + +#define CsrWifiRouterCtrlResumeIndSendTo(dst__, src__, clientData__, powerMaintained__) \ + { \ + CsrWifiRouterCtrlResumeInd *msg__; \ + CsrWifiRouterCtrlResumeIndCreate(msg__, dst__, src__, clientData__, powerMaintained__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlResumeIndSend(dst__, clientData__, powerMaintained__) \ + CsrWifiRouterCtrlResumeIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, powerMaintained__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlResumeResSend + + DESCRIPTION + + PARAMETERS + clientData - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlResumeResCreate(msg__, dst__, src__, clientData__, status__) \ + msg__ = (CsrWifiRouterCtrlResumeRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlResumeRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RESUME_RES, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlResumeResSendTo(dst__, src__, clientData__, status__) \ + { \ + CsrWifiRouterCtrlResumeRes *msg__; \ + CsrWifiRouterCtrlResumeResCreate(msg__, dst__, src__, clientData__, status__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlResumeResSend(src__, clientData__, status__) \ + CsrWifiRouterCtrlResumeResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlStaInactiveIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + staAddress - + +*******************************************************************************/ +#define CsrWifiRouterCtrlStaInactiveIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, staAddress__) \ + msg__ = (CsrWifiRouterCtrlStaInactiveInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlStaInactiveInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->staAddress = (staAddress__); + +#define CsrWifiRouterCtrlStaInactiveIndSendTo(dst__, src__, clientData__, interfaceTag__, staAddress__) \ + { \ + CsrWifiRouterCtrlStaInactiveInd *msg__; \ + CsrWifiRouterCtrlStaInactiveIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, staAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlStaInactiveIndSend(dst__, clientData__, interfaceTag__, staAddress__) \ + CsrWifiRouterCtrlStaInactiveIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, staAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlSuspendIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + hardSuspend - + d3Suspend - + +*******************************************************************************/ +#define CsrWifiRouterCtrlSuspendIndCreate(msg__, dst__, src__, clientData__, hardSuspend__, d3Suspend__) \ + msg__ = (CsrWifiRouterCtrlSuspendInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlSuspendInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_SUSPEND_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->hardSuspend = (hardSuspend__); \ + msg__->d3Suspend = (d3Suspend__); + +#define CsrWifiRouterCtrlSuspendIndSendTo(dst__, src__, clientData__, hardSuspend__, d3Suspend__) \ + { \ + CsrWifiRouterCtrlSuspendInd *msg__; \ + CsrWifiRouterCtrlSuspendIndCreate(msg__, dst__, src__, clientData__, hardSuspend__, d3Suspend__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlSuspendIndSend(dst__, clientData__, hardSuspend__, d3Suspend__) \ + CsrWifiRouterCtrlSuspendIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, hardSuspend__, d3Suspend__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlSuspendResSend + + DESCRIPTION + + PARAMETERS + clientData - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlSuspendResCreate(msg__, dst__, src__, clientData__, status__) \ + msg__ = (CsrWifiRouterCtrlSuspendRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlSuspendRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_SUSPEND_RES, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlSuspendResSendTo(dst__, src__, clientData__, status__) \ + { \ + CsrWifiRouterCtrlSuspendRes *msg__; \ + CsrWifiRouterCtrlSuspendResCreate(msg__, dst__, src__, clientData__, status__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlSuspendResSend(src__, clientData__, status__) \ + CsrWifiRouterCtrlSuspendResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasAddReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + tclasLength - + tclas - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTclasAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + msg__ = (CsrWifiRouterCtrlTclasAddReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasAddReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->tclasLength = (tclasLength__); \ + msg__->tclas = (tclas__); + +#define CsrWifiRouterCtrlTclasAddReqSendTo(dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + { \ + CsrWifiRouterCtrlTclasAddReq *msg__; \ + CsrWifiRouterCtrlTclasAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTclasAddReqSend(src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + CsrWifiRouterCtrlTclasAddReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, tclasLength__, tclas__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasAddCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTclasAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlTclasAddCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasAddCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlTclasAddCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlTclasAddCfm *msg__; \ + CsrWifiRouterCtrlTclasAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTclasAddCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlTclasAddCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasDelReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + tclasLength - + tclas - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTclasDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + msg__ = (CsrWifiRouterCtrlTclasDelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasDelReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->tclasLength = (tclasLength__); \ + msg__->tclas = (tclas__); + +#define CsrWifiRouterCtrlTclasDelReqSendTo(dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + { \ + CsrWifiRouterCtrlTclasDelReq *msg__; \ + CsrWifiRouterCtrlTclasDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTclasDelReqSend(src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ + CsrWifiRouterCtrlTclasDelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, tclasLength__, tclas__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasDelCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTclasDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterCtrlTclasDelCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasDelCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlTclasDelCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ + { \ + CsrWifiRouterCtrlTclasDelCfm *msg__; \ + CsrWifiRouterCtrlTclasDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTclasDelCfmSend(dst__, clientData__, interfaceTag__, status__) \ + CsrWifiRouterCtrlTclasDelCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficClassificationReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + trafficType - + period - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTrafficClassificationReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficType__, period__) \ + msg__ = (CsrWifiRouterCtrlTrafficClassificationReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficClassificationReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->trafficType = (trafficType__); \ + msg__->period = (period__); + +#define CsrWifiRouterCtrlTrafficClassificationReqSendTo(dst__, src__, interfaceTag__, clientData__, trafficType__, period__) \ + { \ + CsrWifiRouterCtrlTrafficClassificationReq *msg__; \ + CsrWifiRouterCtrlTrafficClassificationReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficType__, period__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTrafficClassificationReqSend(src__, interfaceTag__, clientData__, trafficType__, period__) \ + CsrWifiRouterCtrlTrafficClassificationReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, trafficType__, period__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficConfigReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + clientData - + trafficConfigType - + config - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTrafficConfigReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ + msg__ = (CsrWifiRouterCtrlTrafficConfigReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficConfigReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->clientData = (clientData__); \ + msg__->trafficConfigType = (trafficConfigType__); \ + msg__->config = (config__); + +#define CsrWifiRouterCtrlTrafficConfigReqSendTo(dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ + { \ + CsrWifiRouterCtrlTrafficConfigReq *msg__; \ + CsrWifiRouterCtrlTrafficConfigReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTrafficConfigReqSend(src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ + CsrWifiRouterCtrlTrafficConfigReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, trafficConfigType__, config__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficProtocolIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + packetType - + direction - + srcAddress - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTrafficProtocolIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ + msg__ = (CsrWifiRouterCtrlTrafficProtocolInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficProtocolInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->packetType = (packetType__); \ + msg__->direction = (direction__); \ + msg__->srcAddress = (srcAddress__); + +#define CsrWifiRouterCtrlTrafficProtocolIndSendTo(dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ + { \ + CsrWifiRouterCtrlTrafficProtocolInd *msg__; \ + CsrWifiRouterCtrlTrafficProtocolIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTrafficProtocolIndSend(dst__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ + CsrWifiRouterCtrlTrafficProtocolIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficSampleIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + stats - + +*******************************************************************************/ +#define CsrWifiRouterCtrlTrafficSampleIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, stats__) \ + msg__ = (CsrWifiRouterCtrlTrafficSampleInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficSampleInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->stats = (stats__); + +#define CsrWifiRouterCtrlTrafficSampleIndSendTo(dst__, src__, clientData__, interfaceTag__, stats__) \ + { \ + CsrWifiRouterCtrlTrafficSampleInd *msg__; \ + CsrWifiRouterCtrlTrafficSampleIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, stats__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlTrafficSampleIndSend(dst__, clientData__, interfaceTag__, stats__) \ + CsrWifiRouterCtrlTrafficSampleIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, stats__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlUnexpectedFrameIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +#define CsrWifiRouterCtrlUnexpectedFrameIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ + msg__ = (CsrWifiRouterCtrlUnexpectedFrameInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlUnexpectedFrameInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); + +#define CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ + { \ + CsrWifiRouterCtrlUnexpectedFrameInd *msg__; \ + CsrWifiRouterCtrlUnexpectedFrameIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \ + CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastFilterReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiRouterCtrlWapiMulticastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, status__) \ + { \ + CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \ + CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, status__) \ + CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + signalLength - + signal - + dataLength - + data - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, dst__, src__); \ + msg__->signalLength = (signalLength__); \ + msg__->signal = (signal__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiRouterCtrlWapiMulticastReqSendTo(dst__, src__, signalLength__, signal__, dataLength__, data__) \ + { \ + CsrWifiRouterCtrlWapiMulticastReq *msg__; \ + CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiMulticastReqSend(src__, signalLength__, signal__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiMulticastReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, signalLength__, signal__, dataLength__, data__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + signalLength - + signal - + dataLength - + data - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->signalLength = (signalLength__); \ + msg__->signal = (signal__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + { \ + CsrWifiRouterCtrlWapiMulticastInd *msg__; \ + CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiMulticastIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastFilterReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiRouterCtrlWapiUnicastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, status__) \ + { \ + CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \ + CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, status__) \ + CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOffReqCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlWifiOffReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOffReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlWifiOffReqSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlWifiOffReq *msg__; \ + CsrWifiRouterCtrlWifiOffReqCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOffReqSend(src__, clientData__) \ + CsrWifiRouterCtrlWifiOffReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + controlIndication - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOffIndCreate(msg__, dst__, src__, clientData__, controlIndication__) \ + msg__ = (CsrWifiRouterCtrlWifiOffInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOffInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->controlIndication = (controlIndication__); + +#define CsrWifiRouterCtrlWifiOffIndSendTo(dst__, src__, clientData__, controlIndication__) \ + { \ + CsrWifiRouterCtrlWifiOffInd *msg__; \ + CsrWifiRouterCtrlWifiOffIndCreate(msg__, dst__, src__, clientData__, controlIndication__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOffIndSend(dst__, clientData__, controlIndication__) \ + CsrWifiRouterCtrlWifiOffIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, controlIndication__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffResSend + + DESCRIPTION + + PARAMETERS + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOffResCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlWifiOffRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOffRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlWifiOffResSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlWifiOffRes *msg__; \ + CsrWifiRouterCtrlWifiOffResCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOffResSend(src__, clientData__) \ + CsrWifiRouterCtrlWifiOffResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOffCfmCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlWifiOffCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOffCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlWifiOffCfmSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlWifiOffCfm *msg__; \ + CsrWifiRouterCtrlWifiOffCfmCreate(msg__, dst__, src__, clientData__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOffCfmSend(dst__, clientData__) \ + CsrWifiRouterCtrlWifiOffCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + clientData - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__) \ + msg__ = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \ + msg__->clientData = (clientData__); + +#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__) \ + { \ + CsrWifiRouterCtrlWifiOnReq *msg__; \ + CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__) \ + CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + status - + versions - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOnIndCreate(msg__, dst__, src__, clientData__, status__, versions__) \ + msg__ = (CsrWifiRouterCtrlWifiOnInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); \ + msg__->versions = (versions__); + +#define CsrWifiRouterCtrlWifiOnIndSendTo(dst__, src__, clientData__, status__, versions__) \ + { \ + CsrWifiRouterCtrlWifiOnInd *msg__; \ + CsrWifiRouterCtrlWifiOnIndCreate(msg__, dst__, src__, clientData__, status__, versions__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOnIndSend(dst__, clientData__, status__, versions__) \ + CsrWifiRouterCtrlWifiOnIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, status__, versions__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnResSend + + DESCRIPTION + + PARAMETERS + clientData - + status - + numInterfaceAddress - + stationMacAddress - array size 1 MUST match CSR_WIFI_NUM_INTERFACES + smeVersions - + scheduledInterrupt - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOnResCreate(msg__, dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ + msg__ = (CsrWifiRouterCtrlWifiOnRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); \ + msg__->numInterfaceAddress = (numInterfaceAddress__); \ + CsrMemCpy(msg__->stationMacAddress, (stationMacAddress__), sizeof(CsrWifiMacAddress) * 2); \ + msg__->smeVersions = (smeVersions__); \ + msg__->scheduledInterrupt = (scheduledInterrupt__); + +#define CsrWifiRouterCtrlWifiOnResSendTo(dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ + { \ + CsrWifiRouterCtrlWifiOnRes *msg__; \ + CsrWifiRouterCtrlWifiOnResCreate(msg__, dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOnResSend(src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ + CsrWifiRouterCtrlWifiOnResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWifiOnCfmCreate(msg__, dst__, src__, clientData__, status__) \ + msg__ = (CsrWifiRouterCtrlWifiOnCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlWifiOnCfmSendTo(dst__, src__, clientData__, status__) \ + { \ + CsrWifiRouterCtrlWifiOnCfm *msg__; \ + CsrWifiRouterCtrlWifiOnCfmCreate(msg__, dst__, src__, clientData__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWifiOnCfmSend(dst__, clientData__, status__) \ + CsrWifiRouterCtrlWifiOnCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, status__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_CTRL_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h new file mode 100644 index 000000000000..954f600b4ff4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h @@ -0,0 +1,2018 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_CTRL_PRIM_H__ +#define CSR_WIFI_ROUTER_CTRL_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSR_WIFI_ROUTER_CTRL_PRIM (0x0401) + +typedef CsrPrim CsrWifiRouterCtrlPrim; + +typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteWrite)(CsrUint8 func, CsrUint32 address, CsrUint8 data); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteRead)(CsrUint8 func, CsrUint32 address, CsrUint8 *pdata); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioFirmwareDownload)(CsrUint32 length, const CsrUint8 *pdata); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioReset)(void); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioCoreDumpPrepare)(CsrBool suspendSme); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteBlockRead)(CsrUint8 func, CsrUint32 address, CsrUint8 *pdata, CsrUint32 length); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioGpRead16)(CsrUint8 func, CsrUint32 address, CsrUint16 *pdata); +typedef CsrResult (*CsrWifiRouterCtrlRawSdioGpWrite16)(CsrUint8 func, CsrUint32 address, CsrUint16 data); + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckRole + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR + - + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlBlockAckRole; +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR ((CsrWifiRouterCtrlBlockAckRole) 0x00) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT ((CsrWifiRouterCtrlBlockAckRole) 0x01) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlControlIndication + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_ERROR + - + CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_EXIT + - + CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_USER_REQUESTED + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlControlIndication; +#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_ERROR ((CsrWifiRouterCtrlControlIndication) 0x01) +#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_EXIT ((CsrWifiRouterCtrlControlIndication) 0x02) +#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_USER_REQUESTED ((CsrWifiRouterCtrlControlIndication) 0x03) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlListAction + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_LIST_ACTION_GET + - + CSR_WIFI_ROUTER_CTRL_LIST_ACTION_ADD + - + CSR_WIFI_ROUTER_CTRL_LIST_ACTION_REMOVE + - + CSR_WIFI_ROUTER_CTRL_LIST_ACTION_FLUSH + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlListAction; +#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_GET ((CsrWifiRouterCtrlListAction) 0x00) +#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_ADD ((CsrWifiRouterCtrlListAction) 0x01) +#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_REMOVE ((CsrWifiRouterCtrlListAction) 0x02) +#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_FLUSH ((CsrWifiRouterCtrlListAction) 0x03) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlLowPowerMode + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED + - + CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_ENABLED + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlLowPowerMode; +#define CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED ((CsrWifiRouterCtrlLowPowerMode) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_ENABLED ((CsrWifiRouterCtrlLowPowerMode) 0x0001) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMediaStatus + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_CONNECTED + - + CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_DISCONNECTED + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlMediaStatus; +#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_CONNECTED ((CsrWifiRouterCtrlMediaStatus) 0x00) +#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_DISCONNECTED ((CsrWifiRouterCtrlMediaStatus) 0x01) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMode + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_MODE_NONE - + CSR_WIFI_ROUTER_CTRL_MODE_IBSS - + CSR_WIFI_ROUTER_CTRL_MODE_STA - + CSR_WIFI_ROUTER_CTRL_MODE_AP - + CSR_WIFI_ROUTER_CTRL_MODE_MONITOR - + CSR_WIFI_ROUTER_CTRL_MODE_AMP - + CSR_WIFI_ROUTER_CTRL_MODE_P2P - + CSR_WIFI_ROUTER_CTRL_MODE_P2PGO - + CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlMode; +#define CSR_WIFI_ROUTER_CTRL_MODE_NONE ((CsrWifiRouterCtrlMode) 0x00) +#define CSR_WIFI_ROUTER_CTRL_MODE_IBSS ((CsrWifiRouterCtrlMode) 0x01) +#define CSR_WIFI_ROUTER_CTRL_MODE_STA ((CsrWifiRouterCtrlMode) 0x02) +#define CSR_WIFI_ROUTER_CTRL_MODE_AP ((CsrWifiRouterCtrlMode) 0x03) +#define CSR_WIFI_ROUTER_CTRL_MODE_MONITOR ((CsrWifiRouterCtrlMode) 0x04) +#define CSR_WIFI_ROUTER_CTRL_MODE_AMP ((CsrWifiRouterCtrlMode) 0x05) +#define CSR_WIFI_ROUTER_CTRL_MODE_P2P ((CsrWifiRouterCtrlMode) 0x06) +#define CSR_WIFI_ROUTER_CTRL_MODE_P2PGO ((CsrWifiRouterCtrlMode) 0x07) +#define CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI ((CsrWifiRouterCtrlMode) 0x08) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerStatus + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE + - + CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE + - + CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlPeerStatus; +#define CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE ((CsrWifiRouterCtrlPeerStatus) 0x00) +#define CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE ((CsrWifiRouterCtrlPeerStatus) 0x01) +#define CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED ((CsrWifiRouterCtrlPeerStatus) 0x02) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPortAction + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN + - + CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD + - + CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlPortAction; +#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN ((CsrWifiRouterCtrlPortAction) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD ((CsrWifiRouterCtrlPortAction) 0x0001) +#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK ((CsrWifiRouterCtrlPortAction) 0x0002) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPowersaveType + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_AC_BK_PS_INFO_PRESENT + - If set, AC BK PS info is present in b4 and b5 + CSR_WIFI_ROUTER_CTRL_AC_BE_PS_INFO_PRESENT + - If set, AC BE PS info is present in b6 and b7 + CSR_WIFI_ROUTER_CTRL_AC_VI_PS_INFO_PRESENT + - If set, AC VI PS info is present in b8 and b9 + CSR_WIFI_ROUTER_CTRL_AC_VO_PS_INFO_PRESENT + - If set, AC VO PS info is present in b10 and b11 + CSR_WIFI_ROUTER_CTRL_AC_BK_TRIGGER_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_BK_DELIVERY_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_BE_TRIGGER_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_BE_DELIVERY_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_VI_TRIGGER_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_VI_DELIVERY_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_VO_TRIGGER_ENABLED + - + CSR_WIFI_ROUTER_CTRL_AC_VO_DELIVERY_ENABLED + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlPowersaveType; +#define CSR_WIFI_ROUTER_CTRL_AC_BK_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0001) +#define CSR_WIFI_ROUTER_CTRL_AC_BE_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0002) +#define CSR_WIFI_ROUTER_CTRL_AC_VI_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0004) +#define CSR_WIFI_ROUTER_CTRL_AC_VO_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0008) +#define CSR_WIFI_ROUTER_CTRL_AC_BK_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0010) +#define CSR_WIFI_ROUTER_CTRL_AC_BK_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0020) +#define CSR_WIFI_ROUTER_CTRL_AC_BE_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0040) +#define CSR_WIFI_ROUTER_CTRL_AC_BE_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0080) +#define CSR_WIFI_ROUTER_CTRL_AC_VI_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0100) +#define CSR_WIFI_ROUTER_CTRL_AC_VI_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0200) +#define CSR_WIFI_ROUTER_CTRL_AC_VO_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0400) +#define CSR_WIFI_ROUTER_CTRL_AC_VO_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0800) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlProtocolDirection + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX + - + CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlProtocolDirection; +#define CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX ((CsrWifiRouterCtrlProtocolDirection) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX ((CsrWifiRouterCtrlProtocolDirection) 0x0001) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlQoSControl + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_OFF + - + CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON + - + CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_80211_ON + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlQoSControl; +#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_OFF ((CsrWifiRouterCtrlQoSControl) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON ((CsrWifiRouterCtrlQoSControl) 0x0001) +#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_80211_ON ((CsrWifiRouterCtrlQoSControl) 0x0002) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlQueueConfig + + DESCRIPTION + Defines which Queues are enabled for use. + + VALUES + CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE + - + CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE + - + CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE + - + CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlQueueConfig; +#define CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x01) +#define CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x02) +#define CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x04) +#define CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x08) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficConfigType + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_CLS + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlTrafficConfigType; +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET ((CsrWifiRouterCtrlTrafficConfigType) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER ((CsrWifiRouterCtrlTrafficConfigType) 0x0001) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_CLS ((CsrWifiRouterCtrlTrafficConfigType) 0x0002) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficPacketType + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ALL + - + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlTrafficPacketType; +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE ((CsrWifiRouterCtrlTrafficPacketType) 0x0000) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL ((CsrWifiRouterCtrlTrafficPacketType) 0x0001) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP ((CsrWifiRouterCtrlTrafficPacketType) 0x0002) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK ((CsrWifiRouterCtrlTrafficPacketType) 0x0004) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP ((CsrWifiRouterCtrlTrafficPacketType) 0x0008) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET ((CsrWifiRouterCtrlTrafficPacketType) 0x0010) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM ((CsrWifiRouterCtrlTrafficPacketType) 0x0020) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ALL ((CsrWifiRouterCtrlTrafficPacketType) 0x00FF) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficType + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_BURSTY + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC + - + CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_CONTINUOUS + - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlTrafficType; +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL ((CsrWifiRouterCtrlTrafficType) 0x00) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_BURSTY ((CsrWifiRouterCtrlTrafficType) 0x01) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC ((CsrWifiRouterCtrlTrafficType) 0x02) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_CONTINUOUS ((CsrWifiRouterCtrlTrafficType) 0x03) + + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerRecordHandle + + DESCRIPTION + +*******************************************************************************/ +typedef CsrUint32 CsrWifiRouterCtrlPeerRecordHandle; +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPowersaveTypeMask + + DESCRIPTION + Mask type for use with the values defined by + CsrWifiRouterCtrlPowersaveType + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlPowersaveTypeMask; +/******************************************************************************* + + NAME + CsrWifiRouterCtrlQueueConfigMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiRouterCtrlQueueConfig + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlQueueConfigMask; +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRequestorInfo + + DESCRIPTION + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterCtrlRequestorInfo; +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficStreamId + + DESCRIPTION + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterCtrlTrafficStreamId; + + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlSmeVersions + + DESCRIPTION + + MEMBERS + firmwarePatch - + smeBuild - + smeHip - + +*******************************************************************************/ +typedef struct +{ + CsrUint32 firmwarePatch; + CsrCharString *smeBuild; + CsrUint32 smeHip; +} CsrWifiRouterCtrlSmeVersions; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlStaInfo + + DESCRIPTION + + MEMBERS + wmmOrQosEnabled - + powersaveMode - + maxSpLength - + listenIntervalInTus - + +*******************************************************************************/ +typedef struct +{ + CsrBool wmmOrQosEnabled; + CsrWifiRouterCtrlPowersaveTypeMask powersaveMode; + CsrUint8 maxSpLength; + CsrUint16 listenIntervalInTus; +} CsrWifiRouterCtrlStaInfo; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficFilter + + DESCRIPTION + + MEMBERS + etherType - + ipType - + udpSourcePort - + udpDestPort - + +*******************************************************************************/ +typedef struct +{ + CsrUint32 etherType; + CsrUint8 ipType; + CsrUint32 udpSourcePort; + CsrUint32 udpDestPort; +} CsrWifiRouterCtrlTrafficFilter; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficStats + + DESCRIPTION + + MEMBERS + rxMeanRate - Mean rx data rate over the interval + rxFramesNum - Keep number of Rx frames per second, for CYCLE_3. + txFramesNum - Keep number of Tx frames per second, for CYCLE_3. + rxBytesCount - Keep calculated Rx throughput per second, for CYCLE_2. + txBytesCount - Keep calculated Tx throughput per second, for CYCLE_2. + intervals - array size 11 MUST match TA_INTERVALS_NUM + +*******************************************************************************/ +typedef struct +{ + CsrUint32 rxMeanRate; + CsrUint32 rxFramesNum; + CsrUint32 txFramesNum; + CsrUint32 rxBytesCount; + CsrUint32 txBytesCount; + CsrUint8 intervals[11]; +} CsrWifiRouterCtrlTrafficStats; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlVersions + + DESCRIPTION + + MEMBERS + chipId - + chipVersion - + firmwareBuild - + firmwareHip - + routerBuild - + routerHip - + +*******************************************************************************/ +typedef struct +{ + CsrUint32 chipId; + CsrUint32 chipVersion; + CsrUint32 firmwareBuild; + CsrUint32 firmwareHip; + CsrCharString *routerBuild; + CsrUint32 routerHip; +} CsrWifiRouterCtrlVersions; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficConfig + + DESCRIPTION + + MEMBERS + packetFilter - + customFilter - + +*******************************************************************************/ +typedef struct +{ + CsrUint16 packetFilter; + CsrWifiRouterCtrlTrafficFilter customFilter; +} CsrWifiRouterCtrlTrafficConfig; + + +/* Downstream */ +#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ ((CsrWifiRouterCtrlPrim) (0x0000 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_HIP_REQ ((CsrWifiRouterCtrlPrim) (0x0001 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ ((CsrWifiRouterCtrlPrim) (0x0002 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES ((CsrWifiRouterCtrlPrim) (0x0003 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ ((CsrWifiRouterCtrlPrim) (0x0004 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ ((CsrWifiRouterCtrlPrim) (0x0005 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_SUSPEND_RES ((CsrWifiRouterCtrlPrim) (0x0006 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ ((CsrWifiRouterCtrlPrim) (0x0007 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RESUME_RES ((CsrWifiRouterCtrlPrim) (0x0008 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ ((CsrWifiRouterCtrlPrim) (0x0009 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ ((CsrWifiRouterCtrlPrim) (0x000A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ ((CsrWifiRouterCtrlPrim) (0x000B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ ((CsrWifiRouterCtrlPrim) (0x000C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ ((CsrWifiRouterCtrlPrim) (0x000D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ ((CsrWifiRouterCtrlPrim) (0x000E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES ((CsrWifiRouterCtrlPrim) (0x000F + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ ((CsrWifiRouterCtrlPrim) (0x0010 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES ((CsrWifiRouterCtrlPrim) (0x0011 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ ((CsrWifiRouterCtrlPrim) (0x0012 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ ((CsrWifiRouterCtrlPrim) (0x0013 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ ((CsrWifiRouterCtrlPrim) (0x0014 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ ((CsrWifiRouterCtrlPrim) (0x0015 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ ((CsrWifiRouterCtrlPrim) (0x0016 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ ((CsrWifiRouterCtrlPrim) (0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_ROUTER_CTRL_HIP_IND ((CsrWifiRouterCtrlPrim)(0x0000 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND ((CsrWifiRouterCtrlPrim)(0x0001 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM ((CsrWifiRouterCtrlPrim)(0x0002 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RESUME_IND ((CsrWifiRouterCtrlPrim)(0x0003 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_SUSPEND_IND ((CsrWifiRouterCtrlPrim)(0x0004 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM ((CsrWifiRouterCtrlPrim)(0x0005 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM ((CsrWifiRouterCtrlPrim)(0x0006 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM ((CsrWifiRouterCtrlPrim)(0x0007 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM ((CsrWifiRouterCtrlPrim)(0x0008 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND ((CsrWifiRouterCtrlPrim)(0x0009 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND ((CsrWifiRouterCtrlPrim)(0x000A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND ((CsrWifiRouterCtrlPrim)(0x000B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM ((CsrWifiRouterCtrlPrim)(0x000C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND ((CsrWifiRouterCtrlPrim)(0x000D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM ((CsrWifiRouterCtrlPrim)(0x000E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND ((CsrWifiRouterCtrlPrim)(0x000F + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND ((CsrWifiRouterCtrlPrim)(0x0010 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND ((CsrWifiRouterCtrlPrim)(0x0011 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_CONNECTED_IND ((CsrWifiRouterCtrlPrim)(0x0012 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM ((CsrWifiRouterCtrlPrim)(0x0013 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM ((CsrWifiRouterCtrlPrim)(0x0014 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND ((CsrWifiRouterCtrlPrim)(0x0015 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM ((CsrWifiRouterCtrlPrim)(0x0016 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM ((CsrWifiRouterCtrlPrim)(0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM ((CsrWifiRouterCtrlPrim)(0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM ((CsrWifiRouterCtrlPrim)(0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND ((CsrWifiRouterCtrlPrim)(0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND ((CsrWifiRouterCtrlPrim)(0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlConfigurePowerModeReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + mode - + wakeHost - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlLowPowerMode mode; + CsrBool wakeHost; +} CsrWifiRouterCtrlConfigurePowerModeReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlHipReq + + DESCRIPTION + This primitive is used for transferring MLME messages to the HIP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mlmeCommandLength - Length of the MLME signal + mlmeCommand - Pointer to the MLME signal + dataRef1Length - Length of the dataRef1 bulk data + dataRef1 - Pointer to the bulk data 1 + dataRef2Length - Length of the dataRef2 bulk data + dataRef2 - Pointer to the bulk data 2 + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 mlmeCommandLength; + CsrUint8 *mlmeCommand; + CsrUint16 dataRef1Length; + CsrUint8 *dataRef1; + CsrUint16 dataRef2Length; + CsrUint8 *dataRef2; +} CsrWifiRouterCtrlHipReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMediaStatusReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + mediaStatus - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlMediaStatus mediaStatus; +} CsrWifiRouterCtrlMediaStatusReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMulticastAddressRes + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + status - + action - + getAddressesCount - + getAddresses - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; + CsrWifiRouterCtrlListAction action; + CsrUint8 getAddressesCount; + CsrWifiMacAddress *getAddresses; +} CsrWifiRouterCtrlMulticastAddressRes; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPortConfigureReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + uncontrolledPortAction - + controlledPortAction - + macAddress - + setProtection - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlPortAction uncontrolledPortAction; + CsrWifiRouterCtrlPortAction controlledPortAction; + CsrWifiMacAddress macAddress; + CsrBool setProtection; +} CsrWifiRouterCtrlPortConfigureReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlQosControlReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + control - + queueConfig - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlQoSControl control; + CsrWifiRouterCtrlQueueConfigMask queueConfig; +} CsrWifiRouterCtrlQosControlReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlSuspendRes + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; +} CsrWifiRouterCtrlSuspendRes; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasAddReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + tclasLength - + tclas - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 tclasLength; + CsrUint8 *tclas; +} CsrWifiRouterCtrlTclasAddReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlResumeRes + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; +} CsrWifiRouterCtrlResumeRes; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioDeinitialiseReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlRawSdioDeinitialiseReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioInitialiseReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlRawSdioInitialiseReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasDelReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + tclasLength - + tclas - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 tclasLength; + CsrUint8 *tclas; +} CsrWifiRouterCtrlTclasDelReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficClassificationReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + trafficType - + period - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlTrafficType trafficType; + CsrUint16 period; +} CsrWifiRouterCtrlTrafficClassificationReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficConfigReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + trafficConfigType - + config - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlTrafficConfigType trafficConfigType; + CsrWifiRouterCtrlTrafficConfig config; +} CsrWifiRouterCtrlTrafficConfigReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlWifiOffReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffRes + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlWifiOffRes; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlWifiOnReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnRes + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + status - + numInterfaceAddress - + stationMacAddress - array size 1 MUST match CSR_WIFI_NUM_INTERFACES + smeVersions - + scheduledInterrupt - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; + CsrUint16 numInterfaceAddress; + CsrWifiMacAddress stationMacAddress[2]; + CsrWifiRouterCtrlSmeVersions smeVersions; + CsrBool scheduledInterrupt; +} CsrWifiRouterCtrlWifiOnRes; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4TransmitReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlM4TransmitReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlModeSetReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + mode - + bssid - BSSID of the network the device is going to be a part + of + protection - Set to TRUE if encryption is enabled for the + connection/broadcast frames + intraBssDistEnabled - If set to TRUE, intra BSS destribution will be + enabled. If set to FALSE, any unicast PDU which does + not have the RA as the the local MAC address, shall be + ignored. This field is interpreted by the receive if + mode is set to CSR_WIFI_ROUTER_CTRL_MODE_P2PGO + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlMode mode; + CsrWifiMacAddress bssid; + CsrBool protection; + CsrBool intraBssDistEnabled; +} CsrWifiRouterCtrlModeSetReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerAddReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + peerMacAddress - + associationId - + staInfo - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiMacAddress peerMacAddress; + CsrUint16 associationId; + CsrWifiRouterCtrlStaInfo staInfo; +} CsrWifiRouterCtrlPeerAddReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerDelReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + peerRecordHandle - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; +} CsrWifiRouterCtrlPeerDelReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerUpdateReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + peerRecordHandle - + powersaveMode - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; + CsrWifiRouterCtrlPowersaveTypeMask powersaveMode; +} CsrWifiRouterCtrlPeerUpdateReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlCapabilitiesReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlCapabilitiesReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckEnableReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + macAddress - + trafficStreamID - + role - + bufferSize - + timeout - + ssn - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiMacAddress macAddress; + CsrWifiRouterCtrlTrafficStreamId trafficStreamID; + CsrWifiRouterCtrlBlockAckRole role; + CsrUint16 bufferSize; + CsrUint16 timeout; + CsrUint16 ssn; +} CsrWifiRouterCtrlBlockAckEnableReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckDisableReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + clientData - + macAddress - + trafficStreamID - + role - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiMacAddress macAddress; + CsrWifiRouterCtrlTrafficStreamId trafficStreamID; + CsrWifiRouterCtrlBlockAckRole role; +} CsrWifiRouterCtrlBlockAckDisableReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + signalLength - + signal - + dataLength - + data - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 signalLength; + CsrUint8 *signal; + CsrUint16 dataLength; + CsrUint8 *data; +} CsrWifiRouterCtrlWapiMulticastReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastFilterReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 status; +} CsrWifiRouterCtrlWapiMulticastFilterReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastFilterReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 status; +} CsrWifiRouterCtrlWapiUnicastFilterReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlHipInd + + DESCRIPTION + This primitive is used for transferring MLME messages from the HIP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mlmeCommandLength - Length of the MLME signal + mlmeCommand - Pointer to the MLME signal + dataRef1Length - Length of the dataRef1 bulk data + dataRef1 - Pointer to the bulk data 1 + dataRef2Length - Length of the dataRef2 bulk data + dataRef2 - Pointer to the bulk data 2 + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 mlmeCommandLength; + CsrUint8 *mlmeCommand; + CsrUint16 dataRef1Length; + CsrUint8 *dataRef1; + CsrUint16 dataRef2Length; + CsrUint8 *dataRef2; +} CsrWifiRouterCtrlHipInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMulticastAddressInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + action - + setAddressesCount - + setAddresses - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlListAction action; + CsrUint8 setAddressesCount; + CsrWifiMacAddress *setAddresses; +} CsrWifiRouterCtrlMulticastAddressInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPortConfigureCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + macAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiMacAddress macAddress; +} CsrWifiRouterCtrlPortConfigureCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlResumeInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + powerMaintained - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrBool powerMaintained; +} CsrWifiRouterCtrlResumeInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlSuspendInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + hardSuspend - + d3Suspend - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrBool hardSuspend; + CsrBool d3Suspend; +} CsrWifiRouterCtrlSuspendInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasAddCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlTclasAddCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioDeinitialiseCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + result - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult result; +} CsrWifiRouterCtrlRawSdioDeinitialiseCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlRawSdioInitialiseCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + result - + byteRead - + byteWrite - + firmwareDownload - + reset - + coreDumpPrepare - + byteBlockRead - + gpRead16 - + gpWrite16 - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult result; + CsrWifiRouterCtrlRawSdioByteRead byteRead; + CsrWifiRouterCtrlRawSdioByteWrite byteWrite; + CsrWifiRouterCtrlRawSdioFirmwareDownload firmwareDownload; + CsrWifiRouterCtrlRawSdioReset reset; + CsrWifiRouterCtrlRawSdioCoreDumpPrepare coreDumpPrepare; + CsrWifiRouterCtrlRawSdioByteBlockRead byteBlockRead; + CsrWifiRouterCtrlRawSdioGpRead16 gpRead16; + CsrWifiRouterCtrlRawSdioGpWrite16 gpWrite16; +} CsrWifiRouterCtrlRawSdioInitialiseCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTclasDelCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlTclasDelCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficProtocolInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + packetType - + direction - + srcAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlTrafficPacketType packetType; + CsrWifiRouterCtrlProtocolDirection direction; + CsrWifiMacAddress srcAddress; +} CsrWifiRouterCtrlTrafficProtocolInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlTrafficSampleInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + stats - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlTrafficStats stats; +} CsrWifiRouterCtrlTrafficSampleInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + controlIndication - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrWifiRouterCtrlControlIndication controlIndication; +} CsrWifiRouterCtrlWifiOffInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOffCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; +} CsrWifiRouterCtrlWifiOffCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + status - + versions - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; + CsrWifiRouterCtrlVersions versions; +} CsrWifiRouterCtrlWifiOnInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWifiOnCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrResult status; +} CsrWifiRouterCtrlWifiOnCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4ReadyToSendInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; +} CsrWifiRouterCtrlM4ReadyToSendInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlM4TransmittedInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; + CsrResult status; +} CsrWifiRouterCtrlM4TransmittedInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlMicFailureInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + unicastPdu - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; + CsrBool unicastPdu; +} CsrWifiRouterCtrlMicFailureInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlConnectedInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + peerStatus - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; + CsrWifiRouterCtrlPeerStatus peerStatus; +} CsrWifiRouterCtrlConnectedInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerAddCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + peerRecordHandle - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; + CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; + CsrResult status; +} CsrWifiRouterCtrlPeerAddCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerDelCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlPeerDelCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlUnexpectedFrameInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; +} CsrWifiRouterCtrlUnexpectedFrameInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlPeerUpdateCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlPeerUpdateCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlCapabilitiesCfm + + DESCRIPTION + The router sends this primitive to confirm the size of the queues of the + HIP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + commandQueueSize - Size of command queue + trafficQueueSize - Size of traffic queue (per AC) + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 commandQueueSize; + CsrUint16 trafficQueueSize; +} CsrWifiRouterCtrlCapabilitiesCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckEnableCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlBlockAckEnableCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckDisableCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterCtrlBlockAckDisableCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlBlockAckErrorInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + trafficStreamID - + peerMacAddress - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlTrafficStreamId trafficStreamID; + CsrWifiMacAddress peerMacAddress; + CsrResult status; +} CsrWifiRouterCtrlBlockAckErrorInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlStaInactiveInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + staAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiMacAddress staAddress; +} CsrWifiRouterCtrlStaInactiveInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiMulticastInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + signalLength - + signal - + dataLength - + data - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrUint16 signalLength; + CsrUint8 *signal; + CsrUint16 dataLength; + CsrUint8 *data; +} CsrWifiRouterCtrlWapiMulticastInd; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_CTRL_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c new file mode 100644 index 000000000000..b7fa6a1eb521 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c @@ -0,0 +1,43 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#include "csr_wifi_router_ctrl_sef.h" + +const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] = +{ + /* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler, + /* 0x0001 */ CsrWifiRouterCtrlHipReqHandler, + /* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler, + /* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler, + /* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler, + /* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler, + /* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler, + /* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler, + /* 0x0008 */ CsrWifiRouterCtrlResumeResHandler, + /* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler, + /* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler, + /* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler, + /* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler, + /* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler, + /* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler, + /* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler, + /* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler, + /* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler, + /* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler, + /* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler, + /* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler, + /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler, + /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler, + /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler, + CsrWifiRouterCtrlBlockAckEnableReqHandler, /* 0x0018 */ + CsrWifiRouterCtrlBlockAckDisableReqHandler, /* 0x0019 */ + CsrWifiRouterCtrlWapiMulticastReqHandler, /* 0x001A */ + CsrWifiRouterCtrlWapiMulticastFilterReqHandler, /* 0x001B */ + CsrWifiRouterCtrlWapiUnicastFilterReqHandler, /* 0x001C */ +}; diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h new file mode 100644 index 000000000000..07382ef8cce4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ +#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ + +#include "csr_wifi_router_ctrl_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + + typedef void (*CsrWifiRouterCtrlStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg); + + extern const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT]; + + extern void CsrWifiRouterCtrlConfigurePowerModeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlHipReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlMulticastAddressResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlPortConfigureReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlQosControlReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlSuspendResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlTclasAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlRawSdioInitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlTclasDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlTrafficClassificationReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlTrafficConfigReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWifiOffResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlM4TransmitReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlPeerAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlPeerDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlPeerUpdateReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlCapabilitiesReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c new file mode 100644 index 000000000000..cb1f6dc29888 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c @@ -0,0 +1,2369 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_msgconv.h" +#include "csr_unicode.h" + + +#include "csr_wifi_router_ctrl_prim.h" +#include "csr_wifi_router_ctrl_serialize.h" + +void CsrWifiRouterCtrlPfree(void *ptr) +{ + CsrPmemFree(ptr); +} + + +CsrSize CsrWifiRouterCtrlConfigurePowerModeReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrWifiRouterCtrlLowPowerMode primitive->mode */ + bufferSize += 1; /* CsrBool primitive->wakeHost */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlConfigurePowerModeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlConfigurePowerModeReq *primitive = (CsrWifiRouterCtrlConfigurePowerModeReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mode); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wakeHost); + return(ptr); +} + + +void* CsrWifiRouterCtrlConfigurePowerModeReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlConfigurePowerModeReq *primitive = (CsrWifiRouterCtrlConfigurePowerModeReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlConfigurePowerModeReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mode, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->wakeHost, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlHipReqSizeof(void *msg) +{ + CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ + bufferSize += 2; /* CsrUint16 primitive->mlmeCommandLength */ + bufferSize += primitive->mlmeCommandLength; /* CsrUint8 primitive->mlmeCommand */ + bufferSize += 2; /* CsrUint16 primitive->dataRef1Length */ + bufferSize += primitive->dataRef1Length; /* CsrUint8 primitive->dataRef1 */ + bufferSize += 2; /* CsrUint16 primitive->dataRef2Length */ + bufferSize += primitive->dataRef2Length; /* CsrUint8 primitive->dataRef2 */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlHipReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mlmeCommandLength); + if (primitive->mlmeCommandLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mlmeCommand, ((CsrUint16) (primitive->mlmeCommandLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataRef1Length); + if (primitive->dataRef1Length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->dataRef1, ((CsrUint16) (primitive->dataRef1Length))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataRef2Length); + if (primitive->dataRef2Length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->dataRef2, ((CsrUint16) (primitive->dataRef2Length))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlHipReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlHipReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mlmeCommandLength, buffer, &offset); + if (primitive->mlmeCommandLength) + { + primitive->mlmeCommand = (CsrUint8 *)CsrPmemAlloc(primitive->mlmeCommandLength); + CsrMemCpyDes(primitive->mlmeCommand, buffer, &offset, ((CsrUint16) (primitive->mlmeCommandLength))); + } + else + { + primitive->mlmeCommand = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataRef1Length, buffer, &offset); + if (primitive->dataRef1Length) + { + primitive->dataRef1 = (CsrUint8 *)CsrPmemAlloc(primitive->dataRef1Length); + CsrMemCpyDes(primitive->dataRef1, buffer, &offset, ((CsrUint16) (primitive->dataRef1Length))); + } + else + { + primitive->dataRef1 = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataRef2Length, buffer, &offset); + if (primitive->dataRef2Length) + { + primitive->dataRef2 = (CsrUint8 *)CsrPmemAlloc(primitive->dataRef2Length); + CsrMemCpyDes(primitive->dataRef2, buffer, &offset, ((CsrUint16) (primitive->dataRef2Length))); + } + else + { + primitive->dataRef2 = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlHipReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *) voidPrimitivePointer; + CsrPmemFree(primitive->mlmeCommand); + CsrPmemFree(primitive->dataRef1); + CsrPmemFree(primitive->dataRef2); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlMediaStatusReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 1; /* CsrWifiRouterCtrlMediaStatus primitive->mediaStatus */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlMediaStatusReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlMediaStatusReq *primitive = (CsrWifiRouterCtrlMediaStatusReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mediaStatus); + return(ptr); +} + + +void* CsrWifiRouterCtrlMediaStatusReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlMediaStatusReq *primitive = (CsrWifiRouterCtrlMediaStatusReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMediaStatusReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mediaStatus, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlMulticastAddressResSizeof(void *msg) +{ + CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiRouterCtrlListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->getAddressesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->getAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlMulticastAddressResSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->getAddressesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiRouterCtrlMulticastAddressResDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMulticastAddressRes)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->getAddressesCount, buffer, &offset); + primitive->getAddresses = NULL; + if (primitive->getAddressesCount) + { + primitive->getAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->getAddressesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiRouterCtrlMulticastAddressResSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *) voidPrimitivePointer; + CsrPmemFree(primitive->getAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlPortConfigureReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 18) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrWifiRouterCtrlPortAction primitive->uncontrolledPortAction */ + bufferSize += 2; /* CsrWifiRouterCtrlPortAction primitive->controlledPortAction */ + bufferSize += 6; /* CsrUint8 primitive->macAddress.a[6] */ + bufferSize += 1; /* CsrBool primitive->setProtection */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPortConfigureReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPortConfigureReq *primitive = (CsrWifiRouterCtrlPortConfigureReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->uncontrolledPortAction); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->controlledPortAction); + CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->setProtection); + return(ptr); +} + + +void* CsrWifiRouterCtrlPortConfigureReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPortConfigureReq *primitive = (CsrWifiRouterCtrlPortConfigureReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPortConfigureReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->uncontrolledPortAction, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->controlledPortAction, buffer, &offset); + CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->setProtection, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlQosControlReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrWifiRouterCtrlQoSControl primitive->control */ + bufferSize += 1; /* CsrWifiRouterCtrlQueueConfigMask primitive->queueConfig */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlQosControlReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlQosControlReq *primitive = (CsrWifiRouterCtrlQosControlReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->control); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->queueConfig); + return(ptr); +} + + +void* CsrWifiRouterCtrlQosControlReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlQosControlReq *primitive = (CsrWifiRouterCtrlQosControlReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlQosControlReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->control, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->queueConfig, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlSuspendResSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlSuspendResSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlSuspendRes *primitive = (CsrWifiRouterCtrlSuspendRes *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlSuspendResDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlSuspendRes *primitive = (CsrWifiRouterCtrlSuspendRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlSuspendRes)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTclasAddReqSizeof(void *msg) +{ + CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->tclasLength */ + bufferSize += primitive->tclasLength; /* CsrUint8 primitive->tclas */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTclasAddReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tclasLength); + if (primitive->tclasLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((CsrUint16) (primitive->tclasLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlTclasAddReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasAddReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->tclasLength, buffer, &offset); + if (primitive->tclasLength) + { + primitive->tclas = (CsrUint8 *)CsrPmemAlloc(primitive->tclasLength); + CsrMemCpyDes(primitive->tclas, buffer, &offset, ((CsrUint16) (primitive->tclasLength))); + } + else + { + primitive->tclas = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlTclasAddReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *) voidPrimitivePointer; + CsrPmemFree(primitive->tclas); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlResumeResSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlResumeResSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlResumeRes *primitive = (CsrWifiRouterCtrlResumeRes *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlResumeResDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlResumeRes *primitive = (CsrWifiRouterCtrlResumeRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlResumeRes)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTclasDelReqSizeof(void *msg) +{ + CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->tclasLength */ + bufferSize += primitive->tclasLength; /* CsrUint8 primitive->tclas */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTclasDelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tclasLength); + if (primitive->tclasLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((CsrUint16) (primitive->tclasLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlTclasDelReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasDelReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->tclasLength, buffer, &offset); + if (primitive->tclasLength) + { + primitive->tclas = (CsrUint8 *)CsrPmemAlloc(primitive->tclasLength); + CsrMemCpyDes(primitive->tclas, buffer, &offset, ((CsrUint16) (primitive->tclasLength))); + } + else + { + primitive->tclas = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlTclasDelReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *) voidPrimitivePointer; + CsrPmemFree(primitive->tclas); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlTrafficClassificationReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 1; /* CsrWifiRouterCtrlTrafficType primitive->trafficType */ + bufferSize += 2; /* CsrUint16 primitive->period */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTrafficClassificationReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTrafficClassificationReq *primitive = (CsrWifiRouterCtrlTrafficClassificationReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->trafficType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->period); + return(ptr); +} + + +void* CsrWifiRouterCtrlTrafficClassificationReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTrafficClassificationReq *primitive = (CsrWifiRouterCtrlTrafficClassificationReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficClassificationReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->trafficType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->period, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 24) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrWifiRouterCtrlTrafficConfigType primitive->trafficConfigType */ + bufferSize += 2; /* CsrUint16 primitive->config.packetFilter */ + bufferSize += 4; /* CsrUint32 primitive->config.customFilter.etherType */ + bufferSize += 1; /* CsrUint8 primitive->config.customFilter.ipType */ + bufferSize += 4; /* CsrUint32 primitive->config.customFilter.udpSourcePort */ + bufferSize += 4; /* CsrUint32 primitive->config.customFilter.udpDestPort */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTrafficConfigReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTrafficConfigReq *primitive = (CsrWifiRouterCtrlTrafficConfigReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->trafficConfigType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->config.packetFilter); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->config.customFilter.etherType); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->config.customFilter.ipType); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->config.customFilter.udpSourcePort); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->config.customFilter.udpDestPort); + return(ptr); +} + + +void* CsrWifiRouterCtrlTrafficConfigReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTrafficConfigReq *primitive = (CsrWifiRouterCtrlTrafficConfigReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficConfigReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->trafficConfigType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->config.packetFilter, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->config.customFilter.etherType, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->config.customFilter.ipType, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->config.customFilter.udpSourcePort, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->config.customFilter.udpDestPort, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg) +{ + CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 30) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->numInterfaceAddress */ + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->stationMacAddress[i1].a[6] */ + } + } + bufferSize += 4; /* CsrUint32 primitive->smeVersions.firmwarePatch */ + bufferSize += (primitive->smeVersions.smeBuild?CsrStrLen(primitive->smeVersions.smeBuild) : 0) + 1; /* CsrCharString* primitive->smeVersions.smeBuild (0 byte len + 1 for NULL Term) */ + bufferSize += 4; /* CsrUint32 primitive->smeVersions.smeHip */ + bufferSize += 1; /* CsrBool primitive->scheduledInterrupt */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->numInterfaceAddress); + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->stationMacAddress[i1].a, ((CsrUint16) (6))); + } + } + CsrUint32Ser(ptr, len, (CsrUint32) primitive->smeVersions.firmwarePatch); + CsrCharStringSer(ptr, len, primitive->smeVersions.smeBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->smeVersions.smeHip); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scheduledInterrupt); + return(ptr); +} + + +void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnRes)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->numInterfaceAddress, buffer, &offset); + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + CsrMemCpyDes(primitive->stationMacAddress[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + CsrUint32Des((CsrUint32 *) &primitive->smeVersions.firmwarePatch, buffer, &offset); + CsrCharStringDes(&primitive->smeVersions.smeBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->smeVersions.smeHip, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scheduledInterrupt, buffer, &offset); + + return primitive; +} + + +void CsrWifiRouterCtrlWifiOnResSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) voidPrimitivePointer; + CsrPmemFree(primitive->smeVersions.smeBuild); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlM4TransmitReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlM4TransmitReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlM4TransmitReq *primitive = (CsrWifiRouterCtrlM4TransmitReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + return(ptr); +} + + +void* CsrWifiRouterCtrlM4TransmitReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlM4TransmitReq *primitive = (CsrWifiRouterCtrlM4TransmitReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4TransmitReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlModeSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 16) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */ + bufferSize += 6; /* CsrUint8 primitive->bssid.a[6] */ + bufferSize += 1; /* CsrBool primitive->protection */ + bufferSize += 1; /* CsrBool primitive->intraBssDistEnabled */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlModeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlModeSetReq *primitive = (CsrWifiRouterCtrlModeSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mode); + CsrMemCpySer(ptr, len, (const void *) primitive->bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->protection); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->intraBssDistEnabled); + return(ptr); +} + + +void* CsrWifiRouterCtrlModeSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlModeSetReq *primitive = (CsrWifiRouterCtrlModeSetReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mode, buffer, &offset); + CsrMemCpyDes(primitive->bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->protection, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->intraBssDistEnabled, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerAddReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->associationId */ + bufferSize += 1; /* CsrBool primitive->staInfo.wmmOrQosEnabled */ + bufferSize += 2; /* CsrWifiRouterCtrlPowersaveTypeMask primitive->staInfo.powersaveMode */ + bufferSize += 1; /* CsrUint8 primitive->staInfo.maxSpLength */ + bufferSize += 2; /* CsrUint16 primitive->staInfo.listenIntervalInTus */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerAddReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerAddReq *primitive = (CsrWifiRouterCtrlPeerAddReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->associationId); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->staInfo.wmmOrQosEnabled); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->staInfo.powersaveMode); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->staInfo.maxSpLength); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->staInfo.listenIntervalInTus); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerAddReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerAddReq *primitive = (CsrWifiRouterCtrlPeerAddReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerAddReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->associationId, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->staInfo.wmmOrQosEnabled, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->staInfo.powersaveMode, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->staInfo.maxSpLength, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->staInfo.listenIntervalInTus, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerDelReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerDelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerDelReq *primitive = (CsrWifiRouterCtrlPeerDelReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->peerRecordHandle); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerDelReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerDelReq *primitive = (CsrWifiRouterCtrlPeerDelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerDelReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->peerRecordHandle, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerUpdateReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ + bufferSize += 2; /* CsrWifiRouterCtrlPowersaveTypeMask primitive->powersaveMode */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerUpdateReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerUpdateReq *primitive = (CsrWifiRouterCtrlPeerUpdateReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->peerRecordHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->powersaveMode); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerUpdateReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerUpdateReq *primitive = (CsrWifiRouterCtrlPeerUpdateReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerUpdateReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->peerRecordHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->powersaveMode, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlBlockAckEnableReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 6; /* CsrUint8 primitive->macAddress.a[6] */ + bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ + bufferSize += 1; /* CsrWifiRouterCtrlBlockAckRole primitive->role */ + bufferSize += 2; /* CsrUint16 primitive->bufferSize */ + bufferSize += 2; /* CsrUint16 primitive->timeout */ + bufferSize += 2; /* CsrUint16 primitive->ssn */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlBlockAckEnableReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlBlockAckEnableReq *primitive = (CsrWifiRouterCtrlBlockAckEnableReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->trafficStreamID); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->role); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->bufferSize); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->timeout); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->ssn); + return(ptr); +} + + +void* CsrWifiRouterCtrlBlockAckEnableReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlBlockAckEnableReq *primitive = (CsrWifiRouterCtrlBlockAckEnableReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckEnableReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->trafficStreamID, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->role, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->bufferSize, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->timeout, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->ssn, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 6; /* CsrUint8 primitive->macAddress.a[6] */ + bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ + bufferSize += 1; /* CsrWifiRouterCtrlBlockAckRole primitive->role */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlBlockAckDisableReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlBlockAckDisableReq *primitive = (CsrWifiRouterCtrlBlockAckDisableReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->trafficStreamID); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->role); + return(ptr); +} + + +void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlBlockAckDisableReq *primitive = (CsrWifiRouterCtrlBlockAckDisableReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckDisableReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->trafficStreamID, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->role, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg) +{ + CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrUint16 primitive->signalLength */ + bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */ + bufferSize += 2; /* CsrUint16 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength); + if (primitive->signalLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->signal, ((CsrUint16) (primitive->signalLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset); + if (primitive->signalLength) + { + primitive->signal = (CsrUint8 *)CsrPmemAlloc(primitive->signalLength); + CsrMemCpyDes(primitive->signal, buffer, &offset, ((CsrUint16) (primitive->signalLength))); + } + else + { + primitive->signal = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) voidPrimitivePointer; + CsrPmemFree(primitive->signal); + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg) +{ + CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ + bufferSize += 2; /* CsrUint16 primitive->mlmeCommandLength */ + bufferSize += primitive->mlmeCommandLength; /* CsrUint8 primitive->mlmeCommand */ + bufferSize += 2; /* CsrUint16 primitive->dataRef1Length */ + bufferSize += primitive->dataRef1Length; /* CsrUint8 primitive->dataRef1 */ + bufferSize += 2; /* CsrUint16 primitive->dataRef2Length */ + bufferSize += primitive->dataRef2Length; /* CsrUint8 primitive->dataRef2 */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mlmeCommandLength); + if (primitive->mlmeCommandLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mlmeCommand, ((CsrUint16) (primitive->mlmeCommandLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataRef1Length); + if (primitive->dataRef1Length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->dataRef1, ((CsrUint16) (primitive->dataRef1Length))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataRef2Length); + if (primitive->dataRef2Length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->dataRef2, ((CsrUint16) (primitive->dataRef2Length))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlHipInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mlmeCommandLength, buffer, &offset); + if (primitive->mlmeCommandLength) + { + primitive->mlmeCommand = (CsrUint8 *)CsrPmemAlloc(primitive->mlmeCommandLength); + CsrMemCpyDes(primitive->mlmeCommand, buffer, &offset, ((CsrUint16) (primitive->mlmeCommandLength))); + } + else + { + primitive->mlmeCommand = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataRef1Length, buffer, &offset); + if (primitive->dataRef1Length) + { + primitive->dataRef1 = (CsrUint8 *)CsrPmemAlloc(primitive->dataRef1Length); + CsrMemCpyDes(primitive->dataRef1, buffer, &offset, ((CsrUint16) (primitive->dataRef1Length))); + } + else + { + primitive->dataRef1 = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataRef2Length, buffer, &offset); + if (primitive->dataRef2Length) + { + primitive->dataRef2 = (CsrUint8 *)CsrPmemAlloc(primitive->dataRef2Length); + CsrMemCpyDes(primitive->dataRef2, buffer, &offset, ((CsrUint16) (primitive->dataRef2Length))); + } + else + { + primitive->dataRef2 = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlHipIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) voidPrimitivePointer; + CsrPmemFree(primitive->mlmeCommand); + CsrPmemFree(primitive->dataRef1); + CsrPmemFree(primitive->dataRef2); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlMulticastAddressIndSizeof(void *msg) +{ + CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiRouterCtrlListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->setAddressesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->setAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlMulticastAddressIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->setAddressesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiRouterCtrlMulticastAddressIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMulticastAddressInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->setAddressesCount, buffer, &offset); + primitive->setAddresses = NULL; + if (primitive->setAddressesCount) + { + primitive->setAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->setAddressesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiRouterCtrlMulticastAddressIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *) voidPrimitivePointer; + CsrPmemFree(primitive->setAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlPortConfigureCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 6; /* CsrUint8 primitive->macAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPortConfigureCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPortConfigureCfm *primitive = (CsrWifiRouterCtrlPortConfigureCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterCtrlPortConfigureCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPortConfigureCfm *primitive = (CsrWifiRouterCtrlPortConfigureCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPortConfigureCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlSuspendIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 1; /* CsrBool primitive->hardSuspend */ + bufferSize += 1; /* CsrBool primitive->d3Suspend */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlSuspendIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlSuspendInd *primitive = (CsrWifiRouterCtrlSuspendInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->hardSuspend); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->d3Suspend); + return(ptr); +} + + +void* CsrWifiRouterCtrlSuspendIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlSuspendInd *primitive = (CsrWifiRouterCtrlSuspendInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlSuspendInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->hardSuspend, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->d3Suspend, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTclasAddCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTclasAddCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTclasAddCfm *primitive = (CsrWifiRouterCtrlTclasAddCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlTclasAddCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTclasAddCfm *primitive = (CsrWifiRouterCtrlTclasAddCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasAddCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->result */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlRawSdioDeinitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioDeinitialiseCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result); + return(ptr); +} + + +void* CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlRawSdioDeinitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioDeinitialiseCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 39) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->result */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteRead primitive->byteRead */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteWrite primitive->byteWrite */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioFirmwareDownload primitive->firmwareDownload */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioReset primitive->reset */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioCoreDumpPrepare primitive->coreDumpPrepare */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteBlockRead primitive->byteBlockRead */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioGpRead16 primitive->gpRead16 */ + bufferSize += 4; /* CsrWifiRouterCtrlRawSdioGpWrite16 primitive->gpWrite16 */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlRawSdioInitialiseCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlRawSdioInitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioInitialiseCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result); + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteRead */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteWrite */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->firmwareDownload */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->reset */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->coreDumpPrepare */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteBlockRead */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->gpRead16 */ + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->gpWrite16 */ + return(ptr); +} + + +void* CsrWifiRouterCtrlRawSdioInitialiseCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlRawSdioInitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioInitialiseCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result, buffer, &offset); + primitive->byteRead = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->byteWrite = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->firmwareDownload = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->reset = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->coreDumpPrepare = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->byteBlockRead = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->gpRead16 = NULL; /* Special for Function Pointers... */ + offset += 4; + primitive->gpWrite16 = NULL; /* Special for Function Pointers... */ + offset += 4; + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTclasDelCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTclasDelCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTclasDelCfm *primitive = (CsrWifiRouterCtrlTclasDelCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlTclasDelCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTclasDelCfm *primitive = (CsrWifiRouterCtrlTclasDelCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTclasDelCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTrafficProtocolIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrWifiRouterCtrlTrafficPacketType primitive->packetType */ + bufferSize += 2; /* CsrWifiRouterCtrlProtocolDirection primitive->direction */ + bufferSize += 6; /* CsrUint8 primitive->srcAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTrafficProtocolIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTrafficProtocolInd *primitive = (CsrWifiRouterCtrlTrafficProtocolInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->packetType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->direction); + CsrMemCpySer(ptr, len, (const void *) primitive->srcAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterCtrlTrafficProtocolIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTrafficProtocolInd *primitive = (CsrWifiRouterCtrlTrafficProtocolInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficProtocolInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->packetType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->direction, buffer, &offset); + CsrMemCpyDes(primitive->srcAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlTrafficSampleIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 38) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 4; /* CsrUint32 primitive->stats.rxMeanRate */ + bufferSize += 4; /* CsrUint32 primitive->stats.rxFramesNum */ + bufferSize += 4; /* CsrUint32 primitive->stats.txFramesNum */ + bufferSize += 4; /* CsrUint32 primitive->stats.rxBytesCount */ + bufferSize += 4; /* CsrUint32 primitive->stats.txBytesCount */ + bufferSize += 11; /* CsrUint8 primitive->stats.intervals[11] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlTrafficSampleIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlTrafficSampleInd *primitive = (CsrWifiRouterCtrlTrafficSampleInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->stats.rxMeanRate); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->stats.rxFramesNum); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->stats.txFramesNum); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->stats.rxBytesCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->stats.txBytesCount); + CsrMemCpySer(ptr, len, (const void *) primitive->stats.intervals, ((CsrUint16) (11))); + return(ptr); +} + + +void* CsrWifiRouterCtrlTrafficSampleIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlTrafficSampleInd *primitive = (CsrWifiRouterCtrlTrafficSampleInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlTrafficSampleInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->stats.rxMeanRate, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->stats.rxFramesNum, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->stats.txFramesNum, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->stats.rxBytesCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->stats.txBytesCount, buffer, &offset); + CsrMemCpyDes(primitive->stats.intervals, buffer, &offset, ((CsrUint16) (11))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlWifiOnIndSizeof(void *msg) +{ + CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 27) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 4; /* CsrUint32 primitive->versions.chipId */ + bufferSize += 4; /* CsrUint32 primitive->versions.chipVersion */ + bufferSize += 4; /* CsrUint32 primitive->versions.firmwareBuild */ + bufferSize += 4; /* CsrUint32 primitive->versions.firmwareHip */ + bufferSize += (primitive->versions.routerBuild?CsrStrLen(primitive->versions.routerBuild) : 0) + 1; /* CsrCharString* primitive->versions.routerBuild (0 byte len + 1 for NULL Term) */ + bufferSize += 4; /* CsrUint32 primitive->versions.routerHip */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWifiOnIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.chipId); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.chipVersion); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.firmwareBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.firmwareHip); + CsrCharStringSer(ptr, len, primitive->versions.routerBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.routerHip); + return(ptr); +} + + +void* CsrWifiRouterCtrlWifiOnIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.chipId, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.chipVersion, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.firmwareBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.firmwareHip, buffer, &offset); + CsrCharStringDes(&primitive->versions.routerBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.routerHip, buffer, &offset); + + return primitive; +} + + +void CsrWifiRouterCtrlWifiOnIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *) voidPrimitivePointer; + CsrPmemFree(primitive->versions.routerBuild); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterCtrlWifiOnCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWifiOnCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWifiOnCfm *primitive = (CsrWifiRouterCtrlWifiOnCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlWifiOnCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWifiOnCfm *primitive = (CsrWifiRouterCtrlWifiOnCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlM4ReadyToSendIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlM4ReadyToSendIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlM4ReadyToSendInd *primitive = (CsrWifiRouterCtrlM4ReadyToSendInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterCtrlM4ReadyToSendIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlM4ReadyToSendInd *primitive = (CsrWifiRouterCtrlM4ReadyToSendInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4ReadyToSendInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlM4TransmittedIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlM4TransmittedIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlM4TransmittedInd *primitive = (CsrWifiRouterCtrlM4TransmittedInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlM4TransmittedIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlM4TransmittedInd *primitive = (CsrWifiRouterCtrlM4TransmittedInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlM4TransmittedInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlMicFailureIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 1; /* CsrBool primitive->unicastPdu */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlMicFailureIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlMicFailureInd *primitive = (CsrWifiRouterCtrlMicFailureInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->unicastPdu); + return(ptr); +} + + +void* CsrWifiRouterCtrlMicFailureIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlMicFailureInd *primitive = (CsrWifiRouterCtrlMicFailureInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlMicFailureInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->unicastPdu, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlConnectedIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 1; /* CsrWifiRouterCtrlPeerStatus primitive->peerStatus */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlConnectedIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlConnectedInd *primitive = (CsrWifiRouterCtrlConnectedInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->peerStatus); + return(ptr); +} + + +void* CsrWifiRouterCtrlConnectedIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlConnectedInd *primitive = (CsrWifiRouterCtrlConnectedInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlConnectedInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->peerStatus, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerAddCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 19) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerAddCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerAddCfm *primitive = (CsrWifiRouterCtrlPeerAddCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->peerRecordHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerAddCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerAddCfm *primitive = (CsrWifiRouterCtrlPeerAddCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerAddCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint32Des((CsrUint32 *) &primitive->peerRecordHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerDelCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerDelCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerDelCfm *primitive = (CsrWifiRouterCtrlPeerDelCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerDelCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerDelCfm *primitive = (CsrWifiRouterCtrlPeerDelCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerDelCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlUnexpectedFrameIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlUnexpectedFrameIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlUnexpectedFrameInd *primitive = (CsrWifiRouterCtrlUnexpectedFrameInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterCtrlUnexpectedFrameIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlUnexpectedFrameInd *primitive = (CsrWifiRouterCtrlUnexpectedFrameInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlUnexpectedFrameInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlPeerUpdateCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlPeerUpdateCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlPeerUpdateCfm *primitive = (CsrWifiRouterCtrlPeerUpdateCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlPeerUpdateCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlPeerUpdateCfm *primitive = (CsrWifiRouterCtrlPeerUpdateCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlPeerUpdateCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlCapabilitiesCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->commandQueueSize */ + bufferSize += 2; /* CsrUint16 primitive->trafficQueueSize */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlCapabilitiesCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlCapabilitiesCfm *primitive = (CsrWifiRouterCtrlCapabilitiesCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->commandQueueSize); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->trafficQueueSize); + return(ptr); +} + + +void* CsrWifiRouterCtrlCapabilitiesCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlCapabilitiesCfm *primitive = (CsrWifiRouterCtrlCapabilitiesCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlCapabilitiesCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->commandQueueSize, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->trafficQueueSize, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlBlockAckEnableCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlBlockAckEnableCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlBlockAckEnableCfm *primitive = (CsrWifiRouterCtrlBlockAckEnableCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlBlockAckEnableCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlBlockAckEnableCfm *primitive = (CsrWifiRouterCtrlBlockAckEnableCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckEnableCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlBlockAckDisableCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlBlockAckDisableCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlBlockAckDisableCfm *primitive = (CsrWifiRouterCtrlBlockAckDisableCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlBlockAckDisableCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlBlockAckDisableCfm *primitive = (CsrWifiRouterCtrlBlockAckDisableCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckDisableCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlBlockAckErrorIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 16) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlBlockAckErrorIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlBlockAckErrorInd *primitive = (CsrWifiRouterCtrlBlockAckErrorInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->trafficStreamID); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlBlockAckErrorIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlBlockAckErrorInd *primitive = (CsrWifiRouterCtrlBlockAckErrorInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlBlockAckErrorInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->trafficStreamID, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->staAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlStaInactiveIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlStaInactiveInd *primitive = (CsrWifiRouterCtrlStaInactiveInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->staAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlStaInactiveInd *primitive = (CsrWifiRouterCtrlStaInactiveInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlStaInactiveInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->staAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg) +{ + CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrUint16 primitive->signalLength */ + bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */ + bufferSize += 2; /* CsrUint16 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength); + if (primitive->signalLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->signal, ((CsrUint16) (primitive->signalLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset); + if (primitive->signalLength) + { + primitive->signal = (CsrUint8 *)CsrPmemAlloc(primitive->signalLength); + CsrMemCpyDes(primitive->signal, buffer, &offset, ((CsrUint16) (primitive->signalLength))); + } + else + { + primitive->signal = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) voidPrimitivePointer; + CsrPmemFree(primitive->signal); + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h new file mode 100644 index 000000000000..5d82f8d0daa6 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h @@ -0,0 +1,323 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ +#define CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_wifi_msgconv.h" + +#include "csr_wifi_router_ctrl_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void CsrWifiRouterCtrlPfree(void *ptr); + +extern CsrUint8* CsrWifiRouterCtrlConfigurePowerModeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlConfigurePowerModeReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlConfigurePowerModeReqSizeof(void *msg); +#define CsrWifiRouterCtrlConfigurePowerModeReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlHipReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlHipReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlHipReqSizeof(void *msg); +extern void CsrWifiRouterCtrlHipReqSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlMediaStatusReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlMediaStatusReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlMediaStatusReqSizeof(void *msg); +#define CsrWifiRouterCtrlMediaStatusReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlMulticastAddressResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlMulticastAddressResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlMulticastAddressResSizeof(void *msg); +extern void CsrWifiRouterCtrlMulticastAddressResSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlPortConfigureReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPortConfigureReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPortConfigureReqSizeof(void *msg); +#define CsrWifiRouterCtrlPortConfigureReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlQosControlReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlQosControlReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlQosControlReqSizeof(void *msg); +#define CsrWifiRouterCtrlQosControlReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlSuspendResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlSuspendResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlSuspendResSizeof(void *msg); +#define CsrWifiRouterCtrlSuspendResSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTclasAddReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTclasAddReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTclasAddReqSizeof(void *msg); +extern void CsrWifiRouterCtrlTclasAddReqSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlResumeResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlResumeResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlResumeResSizeof(void *msg); +#define CsrWifiRouterCtrlResumeResSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlRawSdioInitialiseReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlRawSdioInitialiseReqDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlRawSdioInitialiseReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlRawSdioInitialiseReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTclasDelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTclasDelReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTclasDelReqSizeof(void *msg); +extern void CsrWifiRouterCtrlTclasDelReqSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlTrafficClassificationReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTrafficClassificationReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTrafficClassificationReqSizeof(void *msg); +#define CsrWifiRouterCtrlTrafficClassificationReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTrafficConfigReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTrafficConfigReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg); +#define CsrWifiRouterCtrlTrafficConfigReqSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWifiOffReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlWifiOffReqDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlWifiOffReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlWifiOffReqSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWifiOffResSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlWifiOffResDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWifiOnReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlWifiOnReqDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlWifiOnReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlWifiOnReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg); +extern void CsrWifiRouterCtrlWifiOnResSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlM4TransmitReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlM4TransmitReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlM4TransmitReqSizeof(void *msg); +#define CsrWifiRouterCtrlM4TransmitReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlModeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlModeSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlModeSetReqSizeof(void *msg); +#define CsrWifiRouterCtrlModeSetReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerAddReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerAddReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerAddReqSizeof(void *msg); +#define CsrWifiRouterCtrlPeerAddReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerDelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerDelReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerDelReqSizeof(void *msg); +#define CsrWifiRouterCtrlPeerDelReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerUpdateReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerUpdateReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerUpdateReqSizeof(void *msg); +#define CsrWifiRouterCtrlPeerUpdateReqSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlCapabilitiesReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlCapabilitiesReqDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlCapabilitiesReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlCapabilitiesReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlBlockAckEnableReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlBlockAckEnableReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlBlockAckEnableReqSizeof(void *msg); +#define CsrWifiRouterCtrlBlockAckEnableReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlBlockAckDisableReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg); +#define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *msg); + +#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint8Ser +#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint8Des +#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint8Sizeof +#define CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint8Ser +#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint8Des +#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint8Sizeof +#define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg); +extern void CsrWifiRouterCtrlHipIndSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlMulticastAddressIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlMulticastAddressIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlMulticastAddressIndSizeof(void *msg); +extern void CsrWifiRouterCtrlMulticastAddressIndSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlPortConfigureCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPortConfigureCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPortConfigureCfmSizeof(void *msg); +#define CsrWifiRouterCtrlPortConfigureCfmSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlResumeIndSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterCtrlResumeIndDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterCtrlResumeIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof +#define CsrWifiRouterCtrlResumeIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlSuspendIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlSuspendIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlSuspendIndSizeof(void *msg); +#define CsrWifiRouterCtrlSuspendIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTclasAddCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTclasAddCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTclasAddCfmSizeof(void *msg); +#define CsrWifiRouterCtrlTclasAddCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof(void *msg); +#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlRawSdioInitialiseCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlRawSdioInitialiseCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof(void *msg); +#define CsrWifiRouterCtrlRawSdioInitialiseCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTclasDelCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTclasDelCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTclasDelCfmSizeof(void *msg); +#define CsrWifiRouterCtrlTclasDelCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTrafficProtocolIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTrafficProtocolIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTrafficProtocolIndSizeof(void *msg); +#define CsrWifiRouterCtrlTrafficProtocolIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlTrafficSampleIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlTrafficSampleIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlTrafficSampleIndSizeof(void *msg); +#define CsrWifiRouterCtrlTrafficSampleIndSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWifiOffIndSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterCtrlWifiOffIndDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterCtrlWifiOffIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof +#define CsrWifiRouterCtrlWifiOffIndSerFree CsrWifiRouterCtrlPfree + +#define CsrWifiRouterCtrlWifiOffCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiRouterCtrlWifiOffCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiRouterCtrlWifiOffCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiRouterCtrlWifiOffCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlWifiOnIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWifiOnIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWifiOnIndSizeof(void *msg); +extern void CsrWifiRouterCtrlWifiOnIndSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlWifiOnCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWifiOnCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWifiOnCfmSizeof(void *msg); +#define CsrWifiRouterCtrlWifiOnCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlM4ReadyToSendIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlM4ReadyToSendIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlM4ReadyToSendIndSizeof(void *msg); +#define CsrWifiRouterCtrlM4ReadyToSendIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlM4TransmittedIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlM4TransmittedIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlM4TransmittedIndSizeof(void *msg); +#define CsrWifiRouterCtrlM4TransmittedIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlMicFailureIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlMicFailureIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlMicFailureIndSizeof(void *msg); +#define CsrWifiRouterCtrlMicFailureIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlConnectedIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlConnectedIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlConnectedIndSizeof(void *msg); +#define CsrWifiRouterCtrlConnectedIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerAddCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerAddCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerAddCfmSizeof(void *msg); +#define CsrWifiRouterCtrlPeerAddCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerDelCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerDelCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerDelCfmSizeof(void *msg); +#define CsrWifiRouterCtrlPeerDelCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlUnexpectedFrameIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlUnexpectedFrameIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlUnexpectedFrameIndSizeof(void *msg); +#define CsrWifiRouterCtrlUnexpectedFrameIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlPeerUpdateCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlPeerUpdateCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlPeerUpdateCfmSizeof(void *msg); +#define CsrWifiRouterCtrlPeerUpdateCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlCapabilitiesCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlCapabilitiesCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlCapabilitiesCfmSizeof(void *msg); +#define CsrWifiRouterCtrlCapabilitiesCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlBlockAckEnableCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlBlockAckEnableCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlBlockAckEnableCfmSizeof(void *msg); +#define CsrWifiRouterCtrlBlockAckEnableCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlBlockAckDisableCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlBlockAckDisableCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlBlockAckDisableCfmSizeof(void *msg); +#define CsrWifiRouterCtrlBlockAckDisableCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlBlockAckErrorIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlBlockAckErrorIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlBlockAckErrorIndSizeof(void *msg); +#define CsrWifiRouterCtrlBlockAckErrorIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlStaInactiveIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg); +#define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *msg); + + +#ifdef __cplusplus +} +#endif +#endif /* CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c new file mode 100644 index 000000000000..9ae6cff640ec --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c @@ -0,0 +1,54 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_router_prim.h" +#include "csr_wifi_router_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiRouterFreeDownstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_ROUTER_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiRouterFreeDownstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_ROUTER_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiRouterPrim *) message)) + { + case CSR_WIFI_ROUTER_MA_PACKET_REQ: + { + CsrWifiRouterMaPacketReq *p = (CsrWifiRouterMaPacketReq *)message; + CsrPmemFree(p->frame); + p->frame = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c new file mode 100644 index 000000000000..19d9c23f6dd0 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c @@ -0,0 +1,54 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_router_prim.h" +#include "csr_wifi_router_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiRouterFreeUpstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_ROUTER_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiRouterFreeUpstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_ROUTER_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiRouterPrim *) message)) + { + case CSR_WIFI_ROUTER_MA_PACKET_IND: + { + CsrWifiRouterMaPacketInd *p = (CsrWifiRouterMaPacketInd *)message; + CsrPmemFree(p->frame); + p->frame = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_router_lib.h b/drivers/staging/csr/csr_wifi_router_lib.h new file mode 100644 index 000000000000..553e7d36e35c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_lib.h @@ -0,0 +1,429 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_LIB_H__ +#define CSR_WIFI_ROUTER_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_router_prim.h" +#include "csr_wifi_router_task.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiRouterFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_ROUTER upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_ROUTER upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiRouterFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiRouterFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_ROUTER downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_ROUTER downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiRouterFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiRouterAppTypeToString(CsrWifiRouterAppType value); +const CsrCharString* CsrWifiRouterEncapsulationToString(CsrWifiRouterEncapsulation value); +const CsrCharString* CsrWifiRouterOuiToString(CsrWifiRouterOui value); +const CsrCharString* CsrWifiRouterPriorityToString(CsrWifiRouterPriority value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiRouterPrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiRouterUpstreamPrimNames[CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiRouterDownstreamPrimNames[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketCancelReqSend + + DESCRIPTION + This primitive is used to request cancellation of a previously send + CsrWifiRouterMaPacketReq. + The frame may already have been transmitted so there is no guarantees + that the CsrWifiRouterMaPacketCancelReq actually cancels the transmission + of the frame in question. + If the cancellation fails, the Router will send, if required, + CsrWifiRouterMaPacketCfm. + If the cancellation succeeds, the Router will not send + CsrWifiRouterMaPacketCfm. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + hostTag - The hostTag for the frame, which should be cancelled. + priority - Priority of the frame, which should be cancelled + peerMacAddress - Destination MAC address of the frame, which should be + cancelled + +*******************************************************************************/ +#define CsrWifiRouterMaPacketCancelReqCreate(msg__, dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ + msg__ = (CsrWifiRouterMaPacketCancelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketCancelReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->hostTag = (hostTag__); \ + msg__->priority = (priority__); \ + msg__->peerMacAddress = (peerMacAddress__); + +#define CsrWifiRouterMaPacketCancelReqSendTo(dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ + { \ + CsrWifiRouterMaPacketCancelReq *msg__; \ + CsrWifiRouterMaPacketCancelReqCreate(msg__, dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketCancelReqSend(src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ + CsrWifiRouterMaPacketCancelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketReqSend + + DESCRIPTION + A task sends this primitive to transmit a frame. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + frameLength - Length of the frame to be sent in bytes + frame - Pointer to the frame to be sent + freeFunction - Pointer to function to be used to free the frame + priority - Priority of the frame, which should be sent + hostTag - An application shall set the bits b31..b28 using one of + the CSR_WIFI_ROUTER_APP_TYPE_* masks. Bits b0..b27 can + be used by the requestor without any restrictions, but + the hostTag shall be unique so the hostTag for + CSR_WIFI_ROUTER_APP _TYPE_OTHER should be constructured + in the following way [ CSR_WIFI_ROUTER_APP_TYPE_OTHER + (4 bits) | SubscriptionHandle (8 bits) | Sequence no. + (20 bits) ]. If the hostTag is not unique, the + behaviour of the system is unpredicatable with respect + to data/management frame transfer. + cfmRequested - Indicates if the requestor needs a confirm for packet + requests sent under this subscription. If set to TRUE, + the router will send a confirm, else it will not send + any confirm + +*******************************************************************************/ +#define CsrWifiRouterMaPacketReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ + msg__ = (CsrWifiRouterMaPacketReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->subscriptionHandle = (subscriptionHandle__); \ + msg__->frameLength = (frameLength__); \ + msg__->frame = (frame__); \ + msg__->freeFunction = (freeFunction__); \ + msg__->priority = (priority__); \ + msg__->hostTag = (hostTag__); \ + msg__->cfmRequested = (cfmRequested__); + +#define CsrWifiRouterMaPacketReqSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ + { \ + CsrWifiRouterMaPacketReq *msg__; \ + CsrWifiRouterMaPacketReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketReqSend(src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ + CsrWifiRouterMaPacketReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketIndSend + + DESCRIPTION + The router sends the primitive to a subscribed task when it receives a + frame matching the subscription. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + result - Status of the operation + frameLength - Length of the received frame in bytes + frame - Pointer to the received frame + freeFunction - Pointer to function to be used to free the frame + rssi - Received signal strength indication in dBm + snr - Signal to Noise Ratio + rate - Transmission/Reception rate + +*******************************************************************************/ +#define CsrWifiRouterMaPacketIndCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ + msg__ = (CsrWifiRouterMaPacketInd *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->subscriptionHandle = (subscriptionHandle__); \ + msg__->result = (result__); \ + msg__->frameLength = (frameLength__); \ + msg__->frame = (frame__); \ + msg__->freeFunction = (freeFunction__); \ + msg__->rssi = (rssi__); \ + msg__->snr = (snr__); \ + msg__->rate = (rate__); + +#define CsrWifiRouterMaPacketIndSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ + { \ + CsrWifiRouterMaPacketInd *msg__; \ + CsrWifiRouterMaPacketIndCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketIndSend(dst__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ + CsrWifiRouterMaPacketIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketResSend + + DESCRIPTION + A task send this primitive to confirm the reception of the received + frame. + + PARAMETERS + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + result - Status of the operation + +*******************************************************************************/ +#define CsrWifiRouterMaPacketResCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__) \ + msg__ = (CsrWifiRouterMaPacketRes *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketRes)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_RES, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->subscriptionHandle = (subscriptionHandle__); \ + msg__->result = (result__); + +#define CsrWifiRouterMaPacketResSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, result__) \ + { \ + CsrWifiRouterMaPacketRes *msg__; \ + CsrWifiRouterMaPacketResCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketResSend(src__, interfaceTag__, subscriptionHandle__, result__) \ + CsrWifiRouterMaPacketResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__, result__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketCfmSend + + DESCRIPTION + The router sends the primitive to confirm the result of the transmission + of the packet of the corresponding CSR_WIFI_ROUTER MA_PACKET_REQ request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + result - Status of the operation + hostTag - The hostTrag will match the hostTag sent in the request. + rate - Transmission/Reception rate + +*******************************************************************************/ +#define CsrWifiRouterMaPacketCfmCreate(msg__, dst__, src__, interfaceTag__, result__, hostTag__, rate__) \ + msg__ = (CsrWifiRouterMaPacketCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->result = (result__); \ + msg__->hostTag = (hostTag__); \ + msg__->rate = (rate__); + +#define CsrWifiRouterMaPacketCfmSendTo(dst__, src__, interfaceTag__, result__, hostTag__, rate__) \ + { \ + CsrWifiRouterMaPacketCfm *msg__; \ + CsrWifiRouterMaPacketCfmCreate(msg__, dst__, src__, interfaceTag__, result__, hostTag__, rate__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketCfmSend(dst__, interfaceTag__, result__, hostTag__, rate__) \ + CsrWifiRouterMaPacketCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, result__, hostTag__, rate__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketSubscribeReqSend + + DESCRIPTION + A task can use this primitive to subscribe for a particular OUI/protocol + and transmit and receive frames matching the subscription. + NOTE: Multiple subscriptions for a given protocol and OUI will result in + the first subscription receiving the data and not the subsequent + subscriptions. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + encapsulation - Specifies the encapsulation type, which will be used for the + subscription + protocol - Together with the OUI, specifies the protocol, which a task + wants to subscribe to + oui - Specifies the OUI for the protocol, which a task wants to + subscribe to + +*******************************************************************************/ +#define CsrWifiRouterMaPacketSubscribeReqCreate(msg__, dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__) \ + msg__ = (CsrWifiRouterMaPacketSubscribeReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketSubscribeReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->encapsulation = (encapsulation__); \ + msg__->protocol = (protocol__); \ + msg__->oui = (oui__); + +#define CsrWifiRouterMaPacketSubscribeReqSendTo(dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__) \ + { \ + CsrWifiRouterMaPacketSubscribeReq *msg__; \ + CsrWifiRouterMaPacketSubscribeReqCreate(msg__, dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketSubscribeReqSend(src__, interfaceTag__, encapsulation__, protocol__, oui__) \ + CsrWifiRouterMaPacketSubscribeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, encapsulation__, protocol__, oui__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketSubscribeCfmSend + + DESCRIPTION + The router sends this primitive to confirm the result of the + subscription. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - Handle to the subscription + This handle must be used in all subsequent requests + status - Status of the operation + allocOffset - Size of the offset for the frames of the subscription + +*******************************************************************************/ +#define CsrWifiRouterMaPacketSubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ + msg__ = (CsrWifiRouterMaPacketSubscribeCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketSubscribeCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->subscriptionHandle = (subscriptionHandle__); \ + msg__->status = (status__); \ + msg__->allocOffset = (allocOffset__); + +#define CsrWifiRouterMaPacketSubscribeCfmSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ + { \ + CsrWifiRouterMaPacketSubscribeCfm *msg__; \ + CsrWifiRouterMaPacketSubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketSubscribeCfmSend(dst__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ + CsrWifiRouterMaPacketSubscribeCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, subscriptionHandle__, status__, allocOffset__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketUnsubscribeReqSend + + DESCRIPTION + A task sends this primitive to unsubscribe a subscription + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + +*******************************************************************************/ +#define CsrWifiRouterMaPacketUnsubscribeReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__) \ + msg__ = (CsrWifiRouterMaPacketUnsubscribeReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketUnsubscribeReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->subscriptionHandle = (subscriptionHandle__); + +#define CsrWifiRouterMaPacketUnsubscribeReqSendTo(dst__, src__, interfaceTag__, subscriptionHandle__) \ + { \ + CsrWifiRouterMaPacketUnsubscribeReq *msg__; \ + CsrWifiRouterMaPacketUnsubscribeReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketUnsubscribeReqSend(src__, interfaceTag__, subscriptionHandle__) \ + CsrWifiRouterMaPacketUnsubscribeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketUnsubscribeCfmSend + + DESCRIPTION + The router sends this primitive to confirm the result of the + unsubscription. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Status of the operation + +*******************************************************************************/ +#define CsrWifiRouterMaPacketUnsubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiRouterMaPacketUnsubscribeCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketUnsubscribeCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiRouterMaPacketUnsubscribeCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiRouterMaPacketUnsubscribeCfm *msg__; \ + CsrWifiRouterMaPacketUnsubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ + } + +#define CsrWifiRouterMaPacketUnsubscribeCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiRouterMaPacketUnsubscribeCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, status__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_prim.h b/drivers/staging/csr/csr_wifi_router_prim.h new file mode 100644 index 000000000000..67b71a4739a9 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_prim.h @@ -0,0 +1,430 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_PRIM_H__ +#define CSR_WIFI_ROUTER_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSR_WIFI_ROUTER_PRIM (0x0400) + +typedef CsrPrim CsrWifiRouterPrim; + +typedef void (*CsrWifiRouterFrameFreeFunction)(void *frame); + +/******************************************************************************* + + NAME + CsrWifiRouterAppType + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_APP_TYPE_SME - + CSR_WIFI_ROUTER_APP_TYPE_PAL - + CSR_WIFI_ROUTER_APP_TYPE_NME - + CSR_WIFI_ROUTER_APP_TYPE_OTHER - + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterAppType; +#define CSR_WIFI_ROUTER_APP_TYPE_SME ((CsrWifiRouterAppType) 0x0) +#define CSR_WIFI_ROUTER_APP_TYPE_PAL ((CsrWifiRouterAppType) 0x1) +#define CSR_WIFI_ROUTER_APP_TYPE_NME ((CsrWifiRouterAppType) 0x2) +#define CSR_WIFI_ROUTER_APP_TYPE_OTHER ((CsrWifiRouterAppType) 0x3) + +/******************************************************************************* + + NAME + CsrWifiRouterEncapsulation + + DESCRIPTION + Indicates the type of encapsulation used for the subscription + + VALUES + CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET + - Ethernet encapsulation + CSR_WIFI_ROUTER_ENCAPSULATION_LLC_SNAP + - LLC/SNAP encapsulation + +*******************************************************************************/ +typedef CsrUint8 CsrWifiRouterEncapsulation; +#define CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET ((CsrWifiRouterEncapsulation) 0x00) +#define CSR_WIFI_ROUTER_ENCAPSULATION_LLC_SNAP ((CsrWifiRouterEncapsulation) 0x01) + +/******************************************************************************* + + NAME + CsrWifiRouterOui + + DESCRIPTION + + VALUES + CSR_WIFI_ROUTER_OUI_RFC_1042 - + CSR_WIFI_ROUTER_OUI_BT - + +*******************************************************************************/ +typedef CsrUint32 CsrWifiRouterOui; +#define CSR_WIFI_ROUTER_OUI_RFC_1042 ((CsrWifiRouterOui) 0x000000) +#define CSR_WIFI_ROUTER_OUI_BT ((CsrWifiRouterOui) 0x001958) + +/******************************************************************************* + + NAME + CsrWifiRouterPriority + + DESCRIPTION + As defined in the IEEE 802.11 standards + + VALUES + CSR_WIFI_ROUTER_PRIORITY_QOS_UP0 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP1 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP2 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP3 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP4 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP5 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP6 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_QOS_UP7 + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_CONTENTION + - See IEEE 802.11 Standard + CSR_WIFI_ROUTER_PRIORITY_MANAGEMENT + - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef CsrUint16 CsrWifiRouterPriority; +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP0 ((CsrWifiRouterPriority) 0x0000) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP1 ((CsrWifiRouterPriority) 0x0001) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP2 ((CsrWifiRouterPriority) 0x0002) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP3 ((CsrWifiRouterPriority) 0x0003) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP4 ((CsrWifiRouterPriority) 0x0004) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP5 ((CsrWifiRouterPriority) 0x0005) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP6 ((CsrWifiRouterPriority) 0x0006) +#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP7 ((CsrWifiRouterPriority) 0x0007) +#define CSR_WIFI_ROUTER_PRIORITY_CONTENTION ((CsrWifiRouterPriority) 0x8000) +#define CSR_WIFI_ROUTER_PRIORITY_MANAGEMENT ((CsrWifiRouterPriority) 0x8010) + + +/* Downstream */ +#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ ((CsrWifiRouterPrim) (0x0000 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ ((CsrWifiRouterPrim) (0x0001 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_REQ ((CsrWifiRouterPrim) (0x0002 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_RES ((CsrWifiRouterPrim) (0x0003 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ ((CsrWifiRouterPrim) (0x0004 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_HIGHEST (0x0004 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM ((CsrWifiRouterPrim)(0x0000 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM ((CsrWifiRouterPrim)(0x0001 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_CFM ((CsrWifiRouterPrim)(0x0002 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_MA_PACKET_IND ((CsrWifiRouterPrim)(0x0003 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_HIGHEST (0x0003 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT (CSR_WIFI_ROUTER_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketSubscribeReq + + DESCRIPTION + A task can use this primitive to subscribe for a particular OUI/protocol + and transmit and receive frames matching the subscription. + NOTE: Multiple subscriptions for a given protocol and OUI will result in + the first subscription receiving the data and not the subsequent + subscriptions. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + encapsulation - Specifies the encapsulation type, which will be used for the + subscription + protocol - Together with the OUI, specifies the protocol, which a task + wants to subscribe to + oui - Specifies the OUI for the protocol, which a task wants to + subscribe to + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiRouterEncapsulation encapsulation; + CsrUint16 protocol; + CsrUint32 oui; +} CsrWifiRouterMaPacketSubscribeReq; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketUnsubscribeReq + + DESCRIPTION + A task sends this primitive to unsubscribe a subscription + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 subscriptionHandle; +} CsrWifiRouterMaPacketUnsubscribeReq; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketReq + + DESCRIPTION + A task sends this primitive to transmit a frame. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + frameLength - Length of the frame to be sent in bytes + frame - Pointer to the frame to be sent + freeFunction - Pointer to function to be used to free the frame + priority - Priority of the frame, which should be sent + hostTag - An application shall set the bits b31..b28 using one of + the CSR_WIFI_ROUTER_APP_TYPE_* masks. Bits b0..b27 can + be used by the requestor without any restrictions, but + the hostTag shall be unique so the hostTag for + CSR_WIFI_ROUTER_APP _TYPE_OTHER should be constructured + in the following way [ CSR_WIFI_ROUTER_APP_TYPE_OTHER + (4 bits) | SubscriptionHandle (8 bits) | Sequence no. + (20 bits) ]. If the hostTag is not unique, the + behaviour of the system is unpredicatable with respect + to data/management frame transfer. + cfmRequested - Indicates if the requestor needs a confirm for packet + requests sent under this subscription. If set to TRUE, + the router will send a confirm, else it will not send + any confirm + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 subscriptionHandle; + CsrUint16 frameLength; + CsrUint8 *frame; + CsrWifiRouterFrameFreeFunction freeFunction; + CsrWifiRouterPriority priority; + CsrUint32 hostTag; + CsrBool cfmRequested; +} CsrWifiRouterMaPacketReq; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketRes + + DESCRIPTION + A task send this primitive to confirm the reception of the received + frame. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + result - Status of the operation + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 subscriptionHandle; + CsrResult result; +} CsrWifiRouterMaPacketRes; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketCancelReq + + DESCRIPTION + This primitive is used to request cancellation of a previously send + CsrWifiRouterMaPacketReq. + The frame may already have been transmitted so there is no guarantees + that the CsrWifiRouterMaPacketCancelReq actually cancels the transmission + of the frame in question. + If the cancellation fails, the Router will send, if required, + CsrWifiRouterMaPacketCfm. + If the cancellation succeeds, the Router will not send + CsrWifiRouterMaPacketCfm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + hostTag - The hostTag for the frame, which should be cancelled. + priority - Priority of the frame, which should be cancelled + peerMacAddress - Destination MAC address of the frame, which should be + cancelled + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint32 hostTag; + CsrWifiRouterPriority priority; + CsrWifiMacAddress peerMacAddress; +} CsrWifiRouterMaPacketCancelReq; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketSubscribeCfm + + DESCRIPTION + The router sends this primitive to confirm the result of the + subscription. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - Handle to the subscription + This handle must be used in all subsequent requests + status - Status of the operation + allocOffset - Size of the offset for the frames of the subscription + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 subscriptionHandle; + CsrResult status; + CsrUint16 allocOffset; +} CsrWifiRouterMaPacketSubscribeCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketUnsubscribeCfm + + DESCRIPTION + The router sends this primitive to confirm the result of the + unsubscription. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Status of the operation + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiRouterMaPacketUnsubscribeCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketCfm + + DESCRIPTION + The router sends the primitive to confirm the result of the transmission + of the packet of the corresponding CSR_WIFI_ROUTER MA_PACKET_REQ request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + result - Status of the operation + hostTag - The hostTrag will match the hostTag sent in the request. + rate - Transmission/Reception rate + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult result; + CsrUint32 hostTag; + CsrUint16 rate; +} CsrWifiRouterMaPacketCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterMaPacketInd + + DESCRIPTION + The router sends the primitive to a subscribed task when it receives a + frame matching the subscription. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + subscriptionHandle - The handle of the subscription + result - Status of the operation + frameLength - Length of the received frame in bytes + frame - Pointer to the received frame + freeFunction - Pointer to function to be used to free the frame + rssi - Received signal strength indication in dBm + snr - Signal to Noise Ratio + rate - Transmission/Reception rate + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 subscriptionHandle; + CsrResult result; + CsrUint16 frameLength; + CsrUint8 *frame; + CsrWifiRouterFrameFreeFunction freeFunction; + CsrInt16 rssi; + CsrInt16 snr; + CsrUint16 rate; +} CsrWifiRouterMaPacketInd; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_sef.c b/drivers/staging/csr/csr_wifi_router_sef.c new file mode 100644 index 000000000000..45a10fb77296 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_sef.c @@ -0,0 +1,19 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#include "csr_wifi_router_sef.h" + +const CsrWifiRouterStateHandlerType CsrWifiRouterDownstreamStateHandlers[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT] = +{ + /* 0x0000 */ CsrWifiRouterMaPacketSubscribeReqHandler, + /* 0x0001 */ CsrWifiRouterMaPacketUnsubscribeReqHandler, + /* 0x0002 */ CsrWifiRouterMaPacketReqHandler, + /* 0x0003 */ CsrWifiRouterMaPacketResHandler, + /* 0x0004 */ CsrWifiRouterMaPacketCancelReqHandler, +}; diff --git a/drivers/staging/csr/csr_wifi_router_sef.h b/drivers/staging/csr/csr_wifi_router_sef.h new file mode 100644 index 000000000000..49dd158fa98d --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_sef.h @@ -0,0 +1,33 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ +#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ + +#include "csr_wifi_router_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + + typedef void (*CsrWifiRouterStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg); + + extern const CsrWifiRouterStateHandlerType CsrWifiRouterDownstreamStateHandlers[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT]; + + extern void CsrWifiRouterMaPacketSubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterMaPacketUnsubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_serialize.c b/drivers/staging/csr/csr_wifi_router_serialize.c new file mode 100644 index 000000000000..e1adf8f03646 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_serialize.c @@ -0,0 +1,422 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_msgconv.h" +#include "csr_unicode.h" + + +#include "csr_wifi_router_prim.h" +#include "csr_wifi_router_serialize.h" + +void CsrWifiRouterPfree(void *ptr) +{ + CsrPmemFree(ptr); +} + + +CsrSize CsrWifiRouterMaPacketSubscribeReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiRouterEncapsulation primitive->encapsulation */ + bufferSize += 2; /* CsrUint16 primitive->protocol */ + bufferSize += 4; /* CsrUint32 primitive->oui */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketSubscribeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketSubscribeReq *primitive = (CsrWifiRouterMaPacketSubscribeReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->encapsulation); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->protocol); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->oui); + return(ptr); +} + + +void* CsrWifiRouterMaPacketSubscribeReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketSubscribeReq *primitive = (CsrWifiRouterMaPacketSubscribeReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketSubscribeReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->encapsulation, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->protocol, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->oui, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketReqSizeof(void *msg) +{ + CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 20) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->subscriptionHandle */ + bufferSize += 2; /* CsrUint16 primitive->frameLength */ + bufferSize += primitive->frameLength; /* CsrUint8 primitive->frame */ + bufferSize += 4; /* CsrWifiRouterFrameFreeFunction primitive->freeFunction */ + bufferSize += 2; /* CsrWifiRouterPriority primitive->priority */ + bufferSize += 4; /* CsrUint32 primitive->hostTag */ + bufferSize += 1; /* CsrBool primitive->cfmRequested */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->subscriptionHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->frameLength); + if (primitive->frameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->frame, ((CsrUint16) (primitive->frameLength))); + } + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->freeFunction */ + CsrUint16Ser(ptr, len, (CsrUint16) primitive->priority); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->hostTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->cfmRequested); + return(ptr); +} + + +void* CsrWifiRouterMaPacketReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->subscriptionHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->frameLength, buffer, &offset); + if (primitive->frameLength) + { + primitive->frame = (CsrUint8 *)CsrPmemAlloc(primitive->frameLength); + CsrMemCpyDes(primitive->frame, buffer, &offset, ((CsrUint16) (primitive->frameLength))); + } + else + { + primitive->frame = NULL; + } + primitive->freeFunction = NULL; /* Special for Function Pointers... */ + offset += 4; + CsrUint16Des((CsrUint16 *) &primitive->priority, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->hostTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->cfmRequested, buffer, &offset); + + return primitive; +} + + +void CsrWifiRouterMaPacketReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *) voidPrimitivePointer; + CsrPmemFree(primitive->frame); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiRouterMaPacketResSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->subscriptionHandle */ + bufferSize += 2; /* CsrResult primitive->result */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketResSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketRes *primitive = (CsrWifiRouterMaPacketRes *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->subscriptionHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result); + return(ptr); +} + + +void* CsrWifiRouterMaPacketResDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketRes *primitive = (CsrWifiRouterMaPacketRes *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketRes)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->subscriptionHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketCancelReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 4; /* CsrUint32 primitive->hostTag */ + bufferSize += 2; /* CsrWifiRouterPriority primitive->priority */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketCancelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketCancelReq *primitive = (CsrWifiRouterMaPacketCancelReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->hostTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->priority); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiRouterMaPacketCancelReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketCancelReq *primitive = (CsrWifiRouterMaPacketCancelReq *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketCancelReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->hostTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->priority, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketSubscribeCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->subscriptionHandle */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->allocOffset */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketSubscribeCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketSubscribeCfm *primitive = (CsrWifiRouterMaPacketSubscribeCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->subscriptionHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->allocOffset); + return(ptr); +} + + +void* CsrWifiRouterMaPacketSubscribeCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketSubscribeCfm *primitive = (CsrWifiRouterMaPacketSubscribeCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketSubscribeCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->subscriptionHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->allocOffset, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketUnsubscribeCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketUnsubscribeCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketUnsubscribeCfm *primitive = (CsrWifiRouterMaPacketUnsubscribeCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterMaPacketUnsubscribeCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketUnsubscribeCfm *primitive = (CsrWifiRouterMaPacketUnsubscribeCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketUnsubscribeCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->result */ + bufferSize += 4; /* CsrUint32 primitive->hostTag */ + bufferSize += 2; /* CsrUint16 primitive->rate */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketCfm *primitive = (CsrWifiRouterMaPacketCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->hostTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->rate); + return(ptr); +} + + +void* CsrWifiRouterMaPacketCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketCfm *primitive = (CsrWifiRouterMaPacketCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->hostTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->rate, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterMaPacketIndSizeof(void *msg) +{ + CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->subscriptionHandle */ + bufferSize += 2; /* CsrResult primitive->result */ + bufferSize += 2; /* CsrUint16 primitive->frameLength */ + bufferSize += primitive->frameLength; /* CsrUint8 primitive->frame */ + bufferSize += 4; /* CsrWifiRouterFrameFreeFunction primitive->freeFunction */ + bufferSize += 2; /* CsrInt16 primitive->rssi */ + bufferSize += 2; /* CsrInt16 primitive->snr */ + bufferSize += 2; /* CsrUint16 primitive->rate */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterMaPacketIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->subscriptionHandle); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->frameLength); + if (primitive->frameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->frame, ((CsrUint16) (primitive->frameLength))); + } + CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->freeFunction */ + CsrUint16Ser(ptr, len, (CsrUint16) primitive->rssi); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->snr); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->rate); + return(ptr); +} + + +void* CsrWifiRouterMaPacketIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *) CsrPmemAlloc(sizeof(CsrWifiRouterMaPacketInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->subscriptionHandle, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->frameLength, buffer, &offset); + if (primitive->frameLength) + { + primitive->frame = (CsrUint8 *)CsrPmemAlloc(primitive->frameLength); + CsrMemCpyDes(primitive->frame, buffer, &offset, ((CsrUint16) (primitive->frameLength))); + } + else + { + primitive->frame = NULL; + } + primitive->freeFunction = NULL; /* Special for Function Pointers... */ + offset += 4; + CsrUint16Des((CsrUint16 *) &primitive->rssi, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->snr, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->rate, buffer, &offset); + + return primitive; +} + + +void CsrWifiRouterMaPacketIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *) voidPrimitivePointer; + CsrPmemFree(primitive->frame); + CsrPmemFree(primitive); +} + + diff --git a/drivers/staging/csr/csr_wifi_router_serialize.h b/drivers/staging/csr/csr_wifi_router_serialize.h new file mode 100644 index 000000000000..183a5a48bb4e --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_serialize.h @@ -0,0 +1,78 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_SERIALIZE_H__ +#define CSR_WIFI_ROUTER_SERIALIZE_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_wifi_msgconv.h" + +#include "csr_wifi_router_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void CsrWifiRouterPfree(void *ptr); + +extern CsrUint8* CsrWifiRouterMaPacketSubscribeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketSubscribeReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketSubscribeReqSizeof(void *msg); +#define CsrWifiRouterMaPacketSubscribeReqSerFree CsrWifiRouterPfree + +#define CsrWifiRouterMaPacketUnsubscribeReqSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterMaPacketUnsubscribeReqDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterMaPacketUnsubscribeReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof +#define CsrWifiRouterMaPacketUnsubscribeReqSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketReqSizeof(void *msg); +extern void CsrWifiRouterMaPacketReqSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterMaPacketResSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketResDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketResSizeof(void *msg); +#define CsrWifiRouterMaPacketResSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketCancelReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketCancelReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketCancelReqSizeof(void *msg); +#define CsrWifiRouterMaPacketCancelReqSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketSubscribeCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketSubscribeCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketSubscribeCfmSizeof(void *msg); +#define CsrWifiRouterMaPacketSubscribeCfmSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketUnsubscribeCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketUnsubscribeCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketUnsubscribeCfmSizeof(void *msg); +#define CsrWifiRouterMaPacketUnsubscribeCfmSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketCfmSizeof(void *msg); +#define CsrWifiRouterMaPacketCfmSerFree CsrWifiRouterPfree + +extern CsrUint8* CsrWifiRouterMaPacketIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterMaPacketIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterMaPacketIndSizeof(void *msg); +extern void CsrWifiRouterMaPacketIndSerFree(void *msg); + + +#ifdef __cplusplus +} +#endif +#endif /* CSR_WIFI_ROUTER_SERIALIZE_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_task.h b/drivers/staging/csr/csr_wifi_router_task.h new file mode 100644 index 000000000000..5bc460e4a393 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_task.h @@ -0,0 +1,34 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_ROUTER_TASK_H__ +#define CSR_WIFI_ROUTER_TASK_H__ + +#include "csr_types.h" +#include "csr_sched.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSR_WIFI_ROUTER_LOG_ID 0x1201FFFF +extern CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE; +void CsrWifiRouterInit(void **gash); +void CsrWifiRouterDeinit(void **gash); +void CsrWifiRouterHandler(void **gash); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_TASK_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_router_transport.c b/drivers/staging/csr/csr_wifi_router_transport.c new file mode 100644 index 000000000000..ec7e01dda40c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_transport.c @@ -0,0 +1,210 @@ +/** @file router_transport.c + * + * + * Copyright (C) Cambridge Silicon Radio Ltd 2006-2010. All rights reserved. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + ****************************************************************************/ + +#include "unifi_priv.h" + +#include "csr_types.h" +#include "csr_sched.h" +#include "csr_msgconv.h" + +#include "sme_userspace.h" + +#include "csr_wifi_hostio_prim.h" +#include "csr_wifi_router_lib.h" +#include "csr_wifi_router_sef.h" +#include "csr_wifi_router_converter_init.h" +#include "csr_wifi_router_ctrl_lib.h" +#include "csr_wifi_router_ctrl_sef.h" +#include "csr_wifi_router_ctrl_converter_init.h" +#include "csr_wifi_sme_prim.h" +#include "csr_wifi_sme_sef.h" +#include "csr_wifi_sme_converter_init.h" +#ifdef CSR_SUPPORT_WEXT +#ifdef CSR_SUPPORT_WEXT_AP +#include "csr_wifi_nme_ap_prim.h" +#include "csr_wifi_nme_ap_sef.h" +#include "csr_wifi_nme_ap_converter_init.h" +#endif +#endif + +static unifi_priv_t *drvpriv = NULL; +void CsrWifiRouterTransportInit(unifi_priv_t *priv) +{ + unifi_trace(priv, UDBG1, "CsrWifiRouterTransportInit: \n"); + + drvpriv = priv; + (void)CsrMsgConvInit(); + CsrWifiRouterConverterInit(); + CsrWifiRouterCtrlConverterInit(); + CsrWifiSmeConverterInit(); +#ifdef CSR_SUPPORT_WEXT +#ifdef CSR_SUPPORT_WEXT_AP + CsrWifiNmeApConverterInit(); +#endif +#endif +} + +void CsrWifiRouterTransportDeinit(unifi_priv_t *priv) +{ + unifi_trace(priv, UDBG1, "CsrWifiRouterTransportDeinit: \n"); + if (priv == drvpriv) + { + CsrMsgConvDeinit(); + drvpriv = NULL; + } +} + +void CsrWifiRouterTransportRecv(unifi_priv_t *priv, CsrUint8* buffer, CsrSize bufferLength) +{ + CsrMsgConvMsgEntry* msgEntry; + CsrUint16 primType; + CsrSchedQid src; + CsrSchedQid dest; + CsrUint16 msgType; + CsrSize offset = 0; + CsrWifiFsmEvent* msg; + + /* Decode the prim and message type */ + CsrUint16Des(&primType, buffer, &offset); + CsrUint16Des(&src, buffer, &offset); + CsrUint16Des(&dest, buffer, &offset); + CsrUint16Des(&msgType, buffer, &offset); + offset -= 2; /* Adjust as the Deserialise Function will read this as well */ + + unifi_trace(priv, UDBG4, "CsrWifiRouterTransportRecv: primType=0x%.4X, msgType=0x%.4X, bufferLength=%d\n", + primType, msgType, bufferLength); + + /* Special handling for HOSTIO messages.... */ + if (primType == CSR_WIFI_HOSTIO_PRIM) + { + CsrWifiRouterCtrlHipReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, CSR_WIFI_ROUTER_CTRL_PRIM, dest, src, NULL}, 0, NULL, 0, NULL, 0, NULL}; + + req.mlmeCommandLength = bufferLength; + req.mlmeCommand = buffer; + + offset += 8;/* Skip the id, src, dest and slot number */ + CsrUint16Des(&req.dataRef1Length, buffer, &offset); + offset += 2; /* Skip the slot number */ + CsrUint16Des(&req.dataRef2Length, buffer, &offset); + + if (req.dataRef1Length) + { + CsrUint16 dr1Offset = (bufferLength - req.dataRef2Length) - req.dataRef1Length; + req.dataRef1 = &buffer[dr1Offset]; + } + + if (req.dataRef2Length) + { + CsrUint16 dr2Offset = bufferLength - req.dataRef2Length; + req.dataRef2 = &buffer[dr2Offset]; + } + + /* Copy the hip data but strip off the prim type */ + req.mlmeCommandLength -= (req.dataRef1Length + req.dataRef2Length + 6); + req.mlmeCommand = &buffer[6]; + + CsrWifiRouterCtrlHipReqHandler(priv, &req.common); + return; + } + + msgEntry = CsrMsgConvFindEntry(primType, msgType); + if (!msgEntry) + { + unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n", + primType, msgType); + dump(buffer, bufferLength); + return; + } + + msg = (CsrWifiFsmEvent*)(msgEntry->deserFunc)(&buffer[offset], bufferLength - offset); + + msg->primtype = primType; + msg->type = msgType; + msg->source = src; + msg->destination = dest; + + switch(primType) + { + case CSR_WIFI_ROUTER_CTRL_PRIM: + CsrWifiRouterCtrlDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST](priv, msg); + CsrWifiRouterCtrlFreeDownstreamMessageContents(CSR_WIFI_ROUTER_CTRL_PRIM, msg); + break; + case CSR_WIFI_ROUTER_PRIM: + CsrWifiRouterDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST](priv, msg); + CsrWifiRouterFreeDownstreamMessageContents(CSR_WIFI_ROUTER_PRIM, msg); + break; + case CSR_WIFI_SME_PRIM: + CsrWifiSmeUpstreamStateHandlers[msg->type - CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST](priv, msg); + CsrWifiSmeFreeUpstreamMessageContents(CSR_WIFI_SME_PRIM, msg); + break; +#ifdef CSR_SUPPORT_WEXT +#ifdef CSR_SUPPORT_WEXT_AP + case CSR_WIFI_NME_AP_PRIM: + CsrWifiNmeApUpstreamStateHandlers(priv, msg); + CsrWifiNmeApFreeUpstreamMessageContents(CSR_WIFI_NME_AP_PRIM, msg); + break; +#endif +#endif + default: + unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend unhandled prim type 0x%.4X\n", primType); + break; + } + CsrPmemFree(msg); +} + +static void CsrWifiRouterTransportSerialiseAndSend(CsrUint16 primType, void* msg) +{ + CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)msg; + CsrMsgConvMsgEntry* msgEntry; + CsrSize msgSize; + CsrSize encodeBufferLen = 0; + CsrSize offset = 0; + CsrUint8* encodeBuffer; + + unifi_trace(drvpriv, UDBG4, "CsrWifiRouterTransportSerialiseAndSend: primType=0x%.4X, msgType=0x%.4X\n", + primType, evt->type); + + msgEntry = CsrMsgConvFindEntry(primType, evt->type); + if (!msgEntry) + { + unifi_error(drvpriv, "CsrWifiRouterTransportSerialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n", + primType, evt->type); + return; + } + + msgSize = 6 + (msgEntry->sizeofFunc)((void*)msg); + + encodeBuffer = CsrPmemAlloc(msgSize); + + /* Encode PrimType */ + CsrUint16Ser(encodeBuffer, &encodeBufferLen, primType); + CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->source); + CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->destination); + + (void)(msgEntry->serFunc)(&encodeBuffer[encodeBufferLen], &offset, msg); + encodeBufferLen += offset; + + uf_sme_queue_message(drvpriv, encodeBuffer, encodeBufferLen); + + /* Do not use msgEntry->freeFunc because the memory is owned by the driver */ + CsrPmemFree(msg); +} + +#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) +void CsrSchedMessagePutStringLog(CsrSchedQid q, CsrUint16 mi, void *mv, CsrUint32 line, CsrCharString *file) +#else +void CsrSchedMessagePut(CsrSchedQid q, CsrUint16 mi, void *mv) +#endif +{ + CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)mv; + evt->destination = q; + CsrWifiRouterTransportSerialiseAndSend(mi, mv); +} + diff --git a/drivers/staging/csr/csr_wifi_serialize_primitive_types.c b/drivers/staging/csr/csr_wifi_serialize_primitive_types.c new file mode 100644 index 000000000000..155bf6562569 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_serialize_primitive_types.c @@ -0,0 +1,257 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#include +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_util.h" +#include "csr_msgconv.h" +#include "csr_wifi_msgconv.h" +#include "csr_wifi_lib.h" + +void CsrUint24Des(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset) +{ + CsrUint32 val; + + val = ((buffer[(*offset) + 2] << 16) | + (buffer[(*offset) + 1] << 8) | + (buffer[(*offset)])); + + *offset += 3; + *v = val; +} + + +/* Big endian :e.g WSC, TCLAS */ +void CsrUint16DesBigEndian(CsrUint16 *v, CsrUint8 *buffer, CsrSize *offset) +{ + CsrUint16 val; + + val = (buffer[(*offset)] << 8) | (buffer[(*offset) + 1]); + *offset += 2; + + *v = val; +} + + +void CsrUint24DesBigEndian(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset) +{ + CsrUint32 val; + + val = ((buffer[(*offset)] << 16) | + (buffer[(*offset) + 1] << 8) | + (buffer[(*offset) + 2])); + + *offset += 3; + *v = val; +} + + +void CsrUint32DesBigEndian(CsrUint32 *v, CsrUint8 *buffer, CsrSize *offset) +{ + CsrUint32 val; + + val = ((buffer[(*offset)] << 24) | + (buffer[(*offset) + 1] << 16) | + (buffer[(*offset) + 2] << 8) | + (buffer[(*offset) + 3])); + + *offset += 4; + *v = val; +} + + +void CsrUint24Ser(CsrUint8 *ptr, CsrSize *len, CsrUint32 v) +{ + ptr[(*len) + 2] = (CsrUint8)((v & 0x00ff0000) >> 16); + ptr[(*len) + 1] = (CsrUint8)((v & 0x0000ff00) >> 8); + ptr[(*len)] = (CsrUint8)((v & 0x000000ff)); + + *len += 3; +} + + +/* Big endian :e.g WSC, TCLAS */ +void CsrUint16SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint16 v) +{ + ptr[(*len)] = (CsrUint8)((v & 0xff00) >> 8); + ptr[(*len) + 1] = (CsrUint8)((v & 0x00ff)); + + *len += 2; +} + + +void CsrUint32SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint32 v) +{ + ptr[(*len)] = (CsrUint8)((v & 0xff000000) >> 24); + ptr[(*len) + 1] = (CsrUint8)((v & 0x00ff0000) >> 16); + ptr[(*len) + 2] = (CsrUint8)((v & 0x0000ff00) >> 8); + ptr[(*len) + 3] = (CsrUint8)((v & 0x000000ff)); + + *len += 4; +} + + +void CsrUint24SerBigEndian(CsrUint8 *ptr, CsrSize *len, CsrUint32 v) +{ + ptr[(*len)] = (CsrUint8)((v & 0x00ff0000) >> 16); + ptr[(*len) + 1] = (CsrUint8)((v & 0x0000ff00) >> 8); + ptr[(*len) + 2] = (CsrUint8)((v & 0x000000ff)); + + *len += 3; +} + + +CsrSize CsrWifiEventSizeof(void *msg) +{ + return 2; +} +EXPORT_SYMBOL_GPL(CsrWifiEventSizeof); + +CsrUint8* CsrWifiEventSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiFsmEvent *primitive = (CsrWifiFsmEvent *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->type); + return(ptr); +} +EXPORT_SYMBOL_GPL(CsrWifiEventSer); + +void* CsrWifiEventDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiFsmEvent *primitive = (CsrWifiFsmEvent *) CsrPmemAlloc(sizeof(CsrWifiFsmEvent)); + CsrSize offset = 0; + CsrUint16Des(&primitive->type, buffer, &offset); + + return primitive; +} +EXPORT_SYMBOL_GPL(CsrWifiEventDes); + +CsrSize CsrWifiEventCsrUint8Sizeof(void *msg) +{ + return 3; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Sizeof); + +CsrUint8* CsrWifiEventCsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiEventCsrUint8 *primitive = (CsrWifiEventCsrUint8 *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, primitive->value); + return(ptr); +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Ser); + + +void* CsrWifiEventCsrUint8Des(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiEventCsrUint8 *primitive = (CsrWifiEventCsrUint8 *) CsrPmemAlloc(sizeof(CsrWifiEventCsrUint8)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des(&primitive->value, buffer, &offset); + + return primitive; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Des); + + +CsrSize CsrWifiEventCsrUint16Sizeof(void *msg) +{ + return 4; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Sizeof); + + +CsrUint8* CsrWifiEventCsrUint16Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiEventCsrUint16 *primitive = (CsrWifiEventCsrUint16 *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, primitive->value); + return(ptr); +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Ser); + +void* CsrWifiEventCsrUint16Des(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiEventCsrUint16 *primitive = (CsrWifiEventCsrUint16 *) CsrPmemAlloc(sizeof(CsrWifiEventCsrUint16)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des(&primitive->value, buffer, &offset); + + return primitive; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Des); + + +CsrSize CsrWifiEventCsrUint32Sizeof(void *msg) +{ + return 6; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Sizeof); + +CsrUint8* CsrWifiEventCsrUint32Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiEventCsrUint32 *primitive = (CsrWifiEventCsrUint32 *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint32Ser(ptr, len, primitive->value); + return(ptr); +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Ser); + + +void* CsrWifiEventCsrUint32Des(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiEventCsrUint32 *primitive = (CsrWifiEventCsrUint32 *) CsrPmemAlloc(sizeof(CsrWifiEventCsrUint32)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint32Des(&primitive->value, buffer, &offset); + + return primitive; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Des); + +CsrSize CsrWifiEventCsrUint16CsrUint8Sizeof(void *msg) +{ + return 5; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Sizeof); + +CsrUint8* CsrWifiEventCsrUint16CsrUint8Ser(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiEventCsrUint16CsrUint8 *primitive = (CsrWifiEventCsrUint16CsrUint8 *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, primitive->value16); + CsrUint8Ser(ptr, len, primitive->value8); + return(ptr); +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Ser); + + +void* CsrWifiEventCsrUint16CsrUint8Des(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiEventCsrUint16CsrUint8 *primitive = (CsrWifiEventCsrUint16CsrUint8 *) CsrPmemAlloc(sizeof(CsrWifiEventCsrUint16CsrUint8)); + + CsrSize offset = 0; + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des(&primitive->value16, buffer, &offset); + CsrUint8Des(&primitive->value8, buffer, &offset); + + return primitive; +} +EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Des); + + diff --git a/drivers/staging/csr/csr_wifi_sme_ap_lib.h b/drivers/staging/csr/csr_wifi_sme_ap_lib.h new file mode 100644 index 000000000000..edef7c8de409 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_ap_lib.h @@ -0,0 +1,656 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_AP_LIB_H__ +#define CSR_WIFI_SME_AP_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_sme_ap_prim.h" +#include "csr_wifi_sme_task.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_lib.h +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiSmeApFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_SME_AP upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_SME_AP upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiSmeApFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiSmeApFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_SME_AP downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_SME_AP downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiSmeApFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value); +const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value); +const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value); +const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value); +const CsrCharString* CsrWifiSmeApTypeToString(CsrWifiSmeApType value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiSmeApPrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStartReqSend + + DESCRIPTION + This primitive requests the SME to start AP or GO functionality + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + initialPresence - Set to 0, if Not in a group fomration phase, set to 1 , + during group formation phase + apType - apType : Legacy AP or P2PGO + cloakSsid - cloakSsid flag. + ssid - ssid. + ifIndex - Radio Interface + channel - channel. + maxConnections - Maximum Stations + P2PClients allowed + apCredentials - AP security credeitals used to advertise in beacon /probe + response + smeApConfig - AP configuration + p2pGoParam - P2P specific GO parameters. Ignored if it is a leagacy AP + +*******************************************************************************/ +#define CsrWifiSmeApBeaconingStartReqCreate(msg__, dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ + msg__ = (CsrWifiSmeApBeaconingStartReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApBeaconingStartReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_START_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->initialPresence = (initialPresence__); \ + msg__->apType = (apType__); \ + msg__->cloakSsid = (cloakSsid__); \ + msg__->ssid = (ssid__); \ + msg__->ifIndex = (ifIndex__); \ + msg__->channel = (channel__); \ + msg__->maxConnections = (maxConnections__); \ + msg__->apCredentials = (apCredentials__); \ + msg__->smeApConfig = (smeApConfig__); \ + msg__->p2pGoParam = (p2pGoParam__); + +#define CsrWifiSmeApBeaconingStartReqSendTo(dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ + { \ + CsrWifiSmeApBeaconingStartReq *msg__; \ + CsrWifiSmeApBeaconingStartReqCreate(msg__, dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBeaconingStartReqSend(src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ + CsrWifiSmeApBeaconingStartReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStartCfmSend + + DESCRIPTION + This primitive confirms the completion of the request along with the + status + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + secIeLength - + secIe - + +*******************************************************************************/ +#define CsrWifiSmeApBeaconingStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, secIeLength__, secIe__) \ + msg__ = (CsrWifiSmeApBeaconingStartCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApBeaconingStartCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_START_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->secIeLength = (secIeLength__); \ + msg__->secIe = (secIe__); + +#define CsrWifiSmeApBeaconingStartCfmSendTo(dst__, src__, interfaceTag__, status__, secIeLength__, secIe__) \ + { \ + CsrWifiSmeApBeaconingStartCfm *msg__; \ + CsrWifiSmeApBeaconingStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, secIeLength__, secIe__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBeaconingStartCfmSend(dst__, interfaceTag__, status__, secIeLength__, secIe__) \ + CsrWifiSmeApBeaconingStartCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, secIeLength__, secIe__) + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStopReqSend + + DESCRIPTION + This primitive requests the SME to STOP AP or P2PGO operation + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + +*******************************************************************************/ +#define CsrWifiSmeApBeaconingStopReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeApBeaconingStopReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApBeaconingStopReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_STOP_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeApBeaconingStopReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeApBeaconingStopReq *msg__; \ + CsrWifiSmeApBeaconingStopReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBeaconingStopReqSend(src__, interfaceTag__) \ + CsrWifiSmeApBeaconingStopReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStopCfmSend + + DESCRIPTION + This primitive confirms AP or P2PGO operation is terminated + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiSmeApBeaconingStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeApBeaconingStopCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApBeaconingStopCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_STOP_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeApBeaconingStopCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeApBeaconingStopCfm *msg__; \ + CsrWifiSmeApBeaconingStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBeaconingStopCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeApBeaconingStopCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeApErrorIndSend + + DESCRIPTION + This primitve is sent by SME to indicate some error in AP operationi + after AP operations were started successfully and continuing the AP + operation may lead to undesired behaviour. It is the responsibility of + the upper layers to stop AP operation if needed + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Range 0-1 + apType - + status - Contains the error status + +*******************************************************************************/ +#define CsrWifiSmeApErrorIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__) \ + msg__ = (CsrWifiSmeApErrorInd *) CsrPmemAlloc(sizeof(CsrWifiSmeApErrorInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ERROR_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->apType = (apType__); \ + msg__->status = (status__); + +#define CsrWifiSmeApErrorIndSendTo(dst__, src__, interfaceTag__, apType__, status__) \ + { \ + CsrWifiSmeApErrorInd *msg__; \ + CsrWifiSmeApErrorIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApErrorIndSend(dst__, interfaceTag__, apType__, status__) \ + CsrWifiSmeApErrorIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, apType__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeApStaConnectStartIndSend + + DESCRIPTION + This primitive indicates that a stations request to join the group/BSS is + accepted + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +#define CsrWifiSmeApStaConnectStartIndCreate(msg__, dst__, src__, interfaceTag__, peerMacAddress__) \ + msg__ = (CsrWifiSmeApStaConnectStartInd *) CsrPmemAlloc(sizeof(CsrWifiSmeApStaConnectStartInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_CONNECT_START_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->peerMacAddress = (peerMacAddress__); + +#define CsrWifiSmeApStaConnectStartIndSendTo(dst__, src__, interfaceTag__, peerMacAddress__) \ + { \ + CsrWifiSmeApStaConnectStartInd *msg__; \ + CsrWifiSmeApStaConnectStartIndCreate(msg__, dst__, src__, interfaceTag__, peerMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApStaConnectStartIndSend(dst__, interfaceTag__, peerMacAddress__) \ + CsrWifiSmeApStaConnectStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, peerMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiSmeApStaDisconnectReqSend + + DESCRIPTION + This primitive tells SME to deauth ot disassociate a particular station + within BSS + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + deauthReason - + disassocReason - + peerMacaddress - + keepBlocking - If TRUE, the station is blocked. If FALSE and the station + is connected, disconnect the station. If FALSE and the + station is not connected, no action is taken. + +*******************************************************************************/ +#define CsrWifiSmeApStaDisconnectReqCreate(msg__, dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ + msg__ = (CsrWifiSmeApStaDisconnectReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApStaDisconnectReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_DISCONNECT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->deauthReason = (deauthReason__); \ + msg__->disassocReason = (disassocReason__); \ + msg__->peerMacaddress = (peerMacaddress__); \ + msg__->keepBlocking = (keepBlocking__); + +#define CsrWifiSmeApStaDisconnectReqSendTo(dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ + { \ + CsrWifiSmeApStaDisconnectReq *msg__; \ + CsrWifiSmeApStaDisconnectReqCreate(msg__, dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApStaDisconnectReqSend(src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ + CsrWifiSmeApStaDisconnectReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) + +/******************************************************************************* + + NAME + CsrWifiSmeApStaDisconnectCfmSend + + DESCRIPTION + This primitive confirms the station is disconnected + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + peerMacaddress - + +*******************************************************************************/ +#define CsrWifiSmeApStaDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, peerMacaddress__) \ + msg__ = (CsrWifiSmeApStaDisconnectCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApStaDisconnectCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_DISCONNECT_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->peerMacaddress = (peerMacaddress__); + +#define CsrWifiSmeApStaDisconnectCfmSendTo(dst__, src__, interfaceTag__, status__, peerMacaddress__) \ + { \ + CsrWifiSmeApStaDisconnectCfm *msg__; \ + CsrWifiSmeApStaDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, peerMacaddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApStaDisconnectCfmSend(dst__, interfaceTag__, status__, peerMacaddress__) \ + CsrWifiSmeApStaDisconnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, peerMacaddress__) + +/******************************************************************************* + + NAME + CsrWifiSmeApStaNotifyIndSend + + DESCRIPTION + This primitive indicates that a station has joined or a previously joined + station has left the BSS/group + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + mediaStatus - + peerMacAddress - + peerDeviceAddress - + disassocReason - + deauthReason - + WpsRegistration - + secIeLength - + secIe - + groupKeyId - + seqNumber - + +*******************************************************************************/ +#define CsrWifiSmeApStaNotifyIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ + msg__ = (CsrWifiSmeApStaNotifyInd *) CsrPmemAlloc(sizeof(CsrWifiSmeApStaNotifyInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_NOTIFY_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->mediaStatus = (mediaStatus__); \ + msg__->peerMacAddress = (peerMacAddress__); \ + msg__->peerDeviceAddress = (peerDeviceAddress__); \ + msg__->disassocReason = (disassocReason__); \ + msg__->deauthReason = (deauthReason__); \ + msg__->WpsRegistration = (WpsRegistration__); \ + msg__->secIeLength = (secIeLength__); \ + msg__->secIe = (secIe__); \ + msg__->groupKeyId = (groupKeyId__); \ + CsrMemCpy(msg__->seqNumber, (seqNumber__), sizeof(CsrUint16) * 8); + +#define CsrWifiSmeApStaNotifyIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ + { \ + CsrWifiSmeApStaNotifyInd *msg__; \ + CsrWifiSmeApStaNotifyIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApStaNotifyIndSend(dst__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ + CsrWifiSmeApStaNotifyIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWmmParamUpdateReqSend + + DESCRIPTION + Application uses this primitive to update the WMM parameters on the fly + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + wmmApParams - WMM parameters to be used for local firmware queue + configuration + wmmApBcParams - WMM parameters to be advertised in beacon/probe response + +*******************************************************************************/ +#define CsrWifiSmeApWmmParamUpdateReqCreate(msg__, dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ + msg__ = (CsrWifiSmeApWmmParamUpdateReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApWmmParamUpdateReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + CsrMemCpy(msg__->wmmApParams, (wmmApParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); \ + CsrMemCpy(msg__->wmmApBcParams, (wmmApBcParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); + +#define CsrWifiSmeApWmmParamUpdateReqSendTo(dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ + { \ + CsrWifiSmeApWmmParamUpdateReq *msg__; \ + CsrWifiSmeApWmmParamUpdateReqCreate(msg__, dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWmmParamUpdateReqSend(src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ + CsrWifiSmeApWmmParamUpdateReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWmmParamUpdateCfmSend + + DESCRIPTION + A confirm for CSR_WIFI_SME_AP_WMM_PARAM_UPDATE.request + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiSmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeApWmmParamUpdateCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApWmmParamUpdateCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeApWmmParamUpdateCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeApWmmParamUpdateCfm *msg__; \ + CsrWifiSmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWmmParamUpdateCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeApWmmParamUpdateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsConfigurationReqSend + + DESCRIPTION + This primitive passes the WPS information for the device to SME. This may + be accepted only if no interface is active. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + wpsConfig - WPS config. + +*******************************************************************************/ +#define CsrWifiSmeApWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__) \ + msg__ = (CsrWifiSmeApWpsConfigurationReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsConfigurationReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ, dst__, src__); \ + msg__->wpsConfig = (wpsConfig__); + +#define CsrWifiSmeApWpsConfigurationReqSendTo(dst__, src__, wpsConfig__) \ + { \ + CsrWifiSmeApWpsConfigurationReq *msg__; \ + CsrWifiSmeApWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsConfigurationReqSend(src__, wpsConfig__) \ + CsrWifiSmeApWpsConfigurationReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, wpsConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsConfigurationCfmSend + + DESCRIPTION + Confirm. + + PARAMETERS + queue - Destination Task Queue + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiSmeApWpsConfigurationCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeApWpsConfigurationCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsConfigurationCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeApWpsConfigurationCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeApWpsConfigurationCfm *msg__; \ + CsrWifiSmeApWpsConfigurationCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsConfigurationCfmSend(dst__, status__) \ + CsrWifiSmeApWpsConfigurationCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationFinishedReqSend + + DESCRIPTION + This primitive tells SME that WPS registration procedure has finished + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + +*******************************************************************************/ +#define CsrWifiSmeApWpsRegistrationFinishedReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeApWpsRegistrationFinishedReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsRegistrationFinishedReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeApWpsRegistrationFinishedReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeApWpsRegistrationFinishedReq *msg__; \ + CsrWifiSmeApWpsRegistrationFinishedReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsRegistrationFinishedReqSend(src__, interfaceTag__) \ + CsrWifiSmeApWpsRegistrationFinishedReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationFinishedCfmSend + + DESCRIPTION + A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_FINISHED.request + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiSmeApWpsRegistrationFinishedCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeApWpsRegistrationFinishedCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsRegistrationFinishedCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeApWpsRegistrationFinishedCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeApWpsRegistrationFinishedCfm *msg__; \ + CsrWifiSmeApWpsRegistrationFinishedCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsRegistrationFinishedCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeApWpsRegistrationFinishedCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationStartedReqSend + + DESCRIPTION + This primitive tells SME that WPS registration procedure has started + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + SelectedDevicePasswordId - + SelectedconfigMethod - + +*******************************************************************************/ +#define CsrWifiSmeApWpsRegistrationStartedReqCreate(msg__, dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ + msg__ = (CsrWifiSmeApWpsRegistrationStartedReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsRegistrationStartedReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->SelectedDevicePasswordId = (SelectedDevicePasswordId__); \ + msg__->SelectedconfigMethod = (SelectedconfigMethod__); + +#define CsrWifiSmeApWpsRegistrationStartedReqSendTo(dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ + { \ + CsrWifiSmeApWpsRegistrationStartedReq *msg__; \ + CsrWifiSmeApWpsRegistrationStartedReqCreate(msg__, dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsRegistrationStartedReqSend(src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ + CsrWifiSmeApWpsRegistrationStartedReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationStartedCfmSend + + DESCRIPTION + A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_STARTED.request + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - + +*******************************************************************************/ +#define CsrWifiSmeApWpsRegistrationStartedCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeApWpsRegistrationStartedCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApWpsRegistrationStartedCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeApWpsRegistrationStartedCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeApWpsRegistrationStartedCfm *msg__; \ + CsrWifiSmeApWpsRegistrationStartedCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApWpsRegistrationStartedCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeApWpsRegistrationStartedCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_AP_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_ap_prim.h b/drivers/staging/csr/csr_wifi_sme_ap_prim.h new file mode 100644 index 000000000000..3310cd287fdc --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_ap_prim.h @@ -0,0 +1,904 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_AP_PRIM_H__ +#define CSR_WIFI_SME_AP_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" +#include "csr_wifi_sme_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CSR_WIFI_AP_ENABLE +#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_prim.h +#endif + +#define CSR_WIFI_SME_AP_PRIM (0x0407) + +typedef CsrPrim CsrWifiSmeApPrim; + + +/******************************************************************************* + + NAME + CsrWifiSmeApAccessType + + DESCRIPTION + Allow or deny STAs based on MAC address + + VALUES + CSR_WIFI_AP_ACCESS_TYPE_NONE - None + CSR_WIFI_AP_ACCESS_TYPE_ALLOW - Allow only if MAC address is from the list + CSR_WIFI_AP_ACCESS_TYPE_DENY - Disallow if MAC address is from the list + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApAccessType; +#define CSR_WIFI_AP_ACCESS_TYPE_NONE ((CsrWifiSmeApAccessType) 0x00) +#define CSR_WIFI_AP_ACCESS_TYPE_ALLOW ((CsrWifiSmeApAccessType) 0x01) +#define CSR_WIFI_AP_ACCESS_TYPE_DENY ((CsrWifiSmeApAccessType) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeApAuthSupport + + DESCRIPTION + Define bits for AP authentication support + + VALUES + CSR_WIFI_SME_RSN_AUTH_WPAPSK - RSN WPA-PSK Support + CSR_WIFI_SME_RSN_AUTH_WPA2PSK - RSN WPA2-PSK Support + CSR_WIFI_SME_AUTH_WAPIPSK - WAPI-PSK Support + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApAuthSupport; +#define CSR_WIFI_SME_RSN_AUTH_WPAPSK ((CsrWifiSmeApAuthSupport) 0x01) +#define CSR_WIFI_SME_RSN_AUTH_WPA2PSK ((CsrWifiSmeApAuthSupport) 0x02) +#define CSR_WIFI_SME_AUTH_WAPIPSK ((CsrWifiSmeApAuthSupport) 0x04) + +/******************************************************************************* + + NAME + CsrWifiSmeApAuthType + + DESCRIPTION + Definition of the SME AP Authentication Options + + VALUES + CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM + - Open authentication + CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL + - Personal authentication using a passphrase or a pre-shared + key. + CSR_WIFI_SME_AP_AUTH_TYPE_WEP + - WEP authentication. This can be either open or shared key + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApAuthType; +#define CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM ((CsrWifiSmeApAuthType) 0x00) +#define CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL ((CsrWifiSmeApAuthType) 0x01) +#define CSR_WIFI_SME_AP_AUTH_TYPE_WEP ((CsrWifiSmeApAuthType) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeApPhySupport + + DESCRIPTION + Define bits for CsrWifiSmeApPhySupportMask + + VALUES + CSR_WIFI_SME_AP_PHY_SUPPORT_A - 802.11a. It is not supported in the current + release. + CSR_WIFI_SME_AP_PHY_SUPPORT_B - 802.11b + CSR_WIFI_SME_AP_PHY_SUPPORT_G - 802.11g + CSR_WIFI_SME_AP_PHY_SUPPORT_N - 802.11n + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApPhySupport; +#define CSR_WIFI_SME_AP_PHY_SUPPORT_A ((CsrWifiSmeApPhySupport) 0x01) +#define CSR_WIFI_SME_AP_PHY_SUPPORT_B ((CsrWifiSmeApPhySupport) 0x02) +#define CSR_WIFI_SME_AP_PHY_SUPPORT_G ((CsrWifiSmeApPhySupport) 0x04) +#define CSR_WIFI_SME_AP_PHY_SUPPORT_N ((CsrWifiSmeApPhySupport) 0x08) + +/******************************************************************************* + + NAME + CsrWifiSmeApType + + DESCRIPTION + Definition of AP types + + VALUES + CSR_WIFI_AP_TYPE_LEGACY - Legacy AP + CSR_WIFI_AP_TYPE_P2P - P2P Group Owner(GO) + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApType; +#define CSR_WIFI_AP_TYPE_LEGACY ((CsrWifiSmeApType) 0x00) +#define CSR_WIFI_AP_TYPE_P2P ((CsrWifiSmeApType) 0x01) + + +/******************************************************************************* + + NAME + CsrWifiSmeApAuthSupportMask + + DESCRIPTION + See CsrWifiSmeApAuthSupport for bit definitions + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApAuthSupportMask; +/******************************************************************************* + + NAME + CsrWifiSmeApPhySupportMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeApPhySupport + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApPhySupportMask; +/******************************************************************************* + + NAME + CsrWifiSmeApRsnCapabilities + + DESCRIPTION + Set to 0 for the current release + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeApRsnCapabilities; +/******************************************************************************* + + NAME + CsrWifiSmeApRsnCapabilitiesMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeApRsnCapabilities + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeApRsnCapabilitiesMask; +/******************************************************************************* + + NAME + CsrWifiSmeApWapiCapabilities + + DESCRIPTION + Ignored by the stack as WAPI is not supported for AP operations in the + current release + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeApWapiCapabilities; +/******************************************************************************* + + NAME + CsrWifiSmeApWapiCapabilitiesMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeApWapiCapabilities + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeApWapiCapabilitiesMask; + + +/******************************************************************************* + + NAME + CsrWifiSmeApHtParams + + DESCRIPTION + Structure holding HT parameters + + MEMBERS + greenfieldSupported - Indicates if the AP supports Htgreenfield operation + subject to the chip capability. If the chip does not + support Htgreenfield operation, this parameter will be + ignored. + NOTE: if shortGi20MHz is set to TRUE and the chip + supports short GI operation for 20MHz this field will + be be ignored and the AP will not support Htgreenfield + operation. + NOTE: This field is ignored by the Wi-Fi stack for the + current release. It implies that AP does not support + greenfield operation. + shortGi20MHz - Indicates if the AP support short GI operation for + 20MHz subject to the chip capability.If the chip does + not support short GI for 20MHz, this parameter is + ignored + rxStbc - Support for STBC for receive. 0 => No support for STBC + , 1=> Use STBC for Rx + rifsModeAllowed - RIFS Mode is allowed to protect overlapping non-HT BSS + htProtection - Deprecated + dualCtsProtection - Dual CTS Protection enabled + +*******************************************************************************/ +typedef struct +{ + CsrBool greenfieldSupported; + CsrBool shortGi20MHz; + CsrUint8 rxStbc; + CsrBool rifsModeAllowed; + CsrUint8 htProtection; + CsrBool dualCtsProtection; +} CsrWifiSmeApHtParams; + +/******************************************************************************* + + NAME + CsrWifiSmeApP2pOperatingChanEntry + + DESCRIPTION + + MEMBERS + operatingClass - Channel operating class + operatingChannelCount - Number of channels in this entry + operatingChannel - List of channels + +*******************************************************************************/ +typedef struct +{ + CsrUint8 operatingClass; + CsrUint8 operatingChannelCount; + CsrUint8 *operatingChannel; +} CsrWifiSmeApP2pOperatingChanEntry; + +/******************************************************************************* + + NAME + CsrWifiSmeApP2pOperatingChanList + + DESCRIPTION + This structure contains the lists of P2P operating channels + + MEMBERS + country - Country + channelEntryListCount - Number of entries + channelEntryList - List of entries + +*******************************************************************************/ +typedef struct +{ + CsrUint8 country[3]; + CsrUint8 channelEntryListCount; + CsrWifiSmeApP2pOperatingChanEntry *channelEntryList; +} CsrWifiSmeApP2pOperatingChanList; + +/******************************************************************************* + + NAME + CsrWifiSmeApAuthPers + + DESCRIPTION + + MEMBERS + authSupport - + encryptionModeMask - + rsnCapabilities - + wapiCapabilities - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApAuthSupportMask authSupport; + CsrWifiSmeEncryptionMask encryptionModeMask; + CsrWifiSmeApRsnCapabilitiesMask rsnCapabilities; + CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities; +} CsrWifiSmeApAuthPers; + +/******************************************************************************* + + NAME + CsrWifiSmeApMacConfig + + DESCRIPTION + Structure holding AP MAC configuration. + + MEMBERS + phySupportedBitmap - Indicates supported physical layers + beaconInterval - Beacon interval in terms of TUs + dtimPeriod - DTIM period in terms of number of beacon intervals + maxListenInterval - Maximum allowed listen interval as number of beacon + intervals + supportedRatesCount - Number of supported rates. Range : 0 to 20 + supportedRates - List of supportedRates. A rate is specied in the + units of 500kbps. An entry for a basic rate shall + have the MSB set to 1. + preamble - Preamble to be advertised in beacons and probe + responses + shortSlotTimeEnabled - TRUE indicates the AP shall use short slot time if + all the stations use short slot operation. + ctsProtectionType - CTS protection to be used + wmmEnabled - Indicate whether WMM is enabled or not. If set to + FALSE,the WMM parameters shall be ignored by the + receiver. + wmmApParams - WMM parameters to be used for local firmware queue + configuration. Array index corresponds to the ACI. + wmmApBcParams - WMM parameters to be advertised in beacon/probe + response. Array index corresponds to the ACI + accessType - Specifies whether the MAC addresses from the list + should be allowed or denied + macAddressListCount - Number of MAC addresses + macAddressList - List of MAC addresses + apHtParams - AP HT parameters. The stack shall use these + parameters only if phySupportedBitmap indicates + support for IEEE 802.11n + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApPhySupportMask phySupportedBitmap; + CsrUint16 beaconInterval; + CsrUint8 dtimPeriod; + CsrUint16 maxListenInterval; + CsrUint8 supportedRatesCount; + CsrUint8 supportedRates[20]; + CsrWifiSmePreambleType preamble; + CsrBool shortSlotTimeEnabled; + CsrWifiSmeCtsProtectionType ctsProtectionType; + CsrBool wmmEnabled; + CsrWifiSmeWmmAcParams wmmApParams[4]; + CsrWifiSmeWmmAcParams wmmApBcParams[4]; + CsrWifiSmeApAccessType accessType; + CsrUint8 macAddressListCount; + CsrWifiMacAddress *macAddressList; + CsrWifiSmeApHtParams apHtParams; +} CsrWifiSmeApMacConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeApP2pGoConfig + + DESCRIPTION + + MEMBERS + groupCapability - Indicates the P2P group capabilities + operatingChanList - List of operating channels in the order of + decreasing priority. It may contain channel + entry/entries not supported by the wifi stack. + These shall be filtered out by the wifi stack + opPsEnabled - Indicates whether opportunistic power save can + be used. + Note: This parameter is ignored by the WiFi + stack for the current release + ctWindow - Define Client Traffic window to be used in terms + of number of TUs. Range: 0 to 127. + Note: This parameter is ignored by the WiFi + stack for the current release. + noaConfigMethod - Notice of Absence configuration method. + Note: This parameter is ignored by the WiFi + stack for the current release. + allowNoaWithNonP2pDevices - Indicates if NOA should be allowed if non P2P + devices are connected. If allowed the non P2P + devices may suffer in throughput. + Note: This parameter is ignored by the WiFi + stack for the current release. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeP2pGroupCapabilityMask groupCapability; + CsrWifiSmeApP2pOperatingChanList operatingChanList; + CsrBool opPsEnabled; + CsrUint8 ctWindow; + CsrWifiSmeP2pNoaConfigMethod noaConfigMethod; + CsrBool allowNoaWithNonP2pDevices; +} CsrWifiSmeApP2pGoConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeApCredentials + + DESCRIPTION + + MEMBERS + authType - + smeAuthType - + smeAuthTypeopenSystemEmpty - + smeAuthTypeauthwep - + smeAuthTypeauthPers - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApAuthType authType; + union { + CsrWifiSmeEmpty openSystemEmpty; + CsrWifiSmeWepAuth authwep; + CsrWifiSmeApAuthPers authPers; + } smeAuthType; +} CsrWifiSmeApCredentials; + +/******************************************************************************* + + NAME + CsrWifiSmeApSecConfig + + DESCRIPTION + + MEMBERS + apCredentials - + wpsEnabled - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeApCredentials apCredentials; + CsrBool wpsEnabled; +} CsrWifiSmeApSecConfig; + + +/* Downstream */ +#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_SME_AP_BEACONING_START_REQ ((CsrWifiSmeApPrim) (0x0000 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_BEACONING_STOP_REQ ((CsrWifiSmeApPrim) (0x0001 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_REQ ((CsrWifiSmeApPrim) (0x0002 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_REQ ((CsrWifiSmeApPrim) (0x0003 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ ((CsrWifiSmeApPrim) (0x0004 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_STA_DISCONNECT_REQ ((CsrWifiSmeApPrim) (0x0005 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ ((CsrWifiSmeApPrim) (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_SME_AP_BEACONING_START_CFM ((CsrWifiSmeApPrim)(0x0000 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_BEACONING_STOP_CFM ((CsrWifiSmeApPrim)(0x0001 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_STA_NOTIFY_IND ((CsrWifiSmeApPrim)(0x0002 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_STA_CONNECT_START_IND ((CsrWifiSmeApPrim)(0x0003 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_CFM ((CsrWifiSmeApPrim)(0x0004 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_CFM ((CsrWifiSmeApPrim)(0x0005 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_CFM ((CsrWifiSmeApPrim)(0x0006 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_STA_DISCONNECT_CFM ((CsrWifiSmeApPrim)(0x0007 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM ((CsrWifiSmeApPrim)(0x0008 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_ERROR_IND ((CsrWifiSmeApPrim)(0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST (0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStartReq + + DESCRIPTION + This primitive requests the SME to start AP or GO functionality + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + initialPresence - Set to 0, if Not in a group fomration phase, set to 1 , + during group formation phase + apType - apType : Legacy AP or P2PGO + cloakSsid - cloakSsid flag. + ssid - ssid. + ifIndex - Radio Interface + channel - channel. + maxConnections - Maximum Stations + P2PClients allowed + apCredentials - AP security credeitals used to advertise in beacon /probe + response + smeApConfig - AP configuration + p2pGoParam - P2P specific GO parameters. Ignored if it is a leagacy AP + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 initialPresence; + CsrWifiSmeApType apType; + CsrBool cloakSsid; + CsrWifiSsid ssid; + CsrWifiSmeRadioIF ifIndex; + CsrUint8 channel; + CsrUint8 maxConnections; + CsrWifiSmeApSecConfig apCredentials; + CsrWifiSmeApMacConfig smeApConfig; + CsrWifiSmeApP2pGoConfig p2pGoParam; +} CsrWifiSmeApBeaconingStartReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStopReq + + DESCRIPTION + This primitive requests the SME to STOP AP or P2PGO operation + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeApBeaconingStopReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationStartedReq + + DESCRIPTION + This primitive tells SME that WPS registration procedure has started + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + SelectedDevicePasswordId - + SelectedconfigMethod - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeWpsDpid SelectedDevicePasswordId; + CsrWifiSmeWpsConfigType SelectedconfigMethod; +} CsrWifiSmeApWpsRegistrationStartedReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationFinishedReq + + DESCRIPTION + This primitive tells SME that WPS registration procedure has finished + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeApWpsRegistrationFinishedReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApWmmParamUpdateReq + + DESCRIPTION + Application uses this primitive to update the WMM parameters on the fly + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + wmmApParams - WMM parameters to be used for local firmware queue + configuration + wmmApBcParams - WMM parameters to be advertised in beacon/probe response + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeWmmAcParams wmmApParams[4]; + CsrWifiSmeWmmAcParams wmmApBcParams[4]; +} CsrWifiSmeApWmmParamUpdateReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApStaDisconnectReq + + DESCRIPTION + This primitive tells SME to deauth ot disassociate a particular station + within BSS + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + deauthReason - + disassocReason - + peerMacaddress - + keepBlocking - If TRUE, the station is blocked. If FALSE and the station + is connected, disconnect the station. If FALSE and the + station is not connected, no action is taken. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeIEEE80211Reason deauthReason; + CsrWifiSmeIEEE80211Reason disassocReason; + CsrWifiMacAddress peerMacaddress; + CsrBool keepBlocking; +} CsrWifiSmeApStaDisconnectReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsConfigurationReq + + DESCRIPTION + This primitive passes the WPS information for the device to SME. This may + be accepted only if no interface is active. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + wpsConfig - WPS config. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeWpsConfig wpsConfig; +} CsrWifiSmeApWpsConfigurationReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStartCfm + + DESCRIPTION + This primitive confirms the completion of the request along with the + status + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + secIeLength - + secIe - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrUint16 secIeLength; + CsrUint8 *secIe; +} CsrWifiSmeApBeaconingStartCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApBeaconingStopCfm + + DESCRIPTION + This primitive confirms AP or P2PGO operation is terminated + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeApBeaconingStopCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApStaNotifyInd + + DESCRIPTION + This primitive indicates that a station has joined or a previously joined + station has left the BSS/group + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + mediaStatus - + peerMacAddress - + peerDeviceAddress - + disassocReason - + deauthReason - + WpsRegistration - + secIeLength - + secIe - + groupKeyId - + seqNumber - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeMediaStatus mediaStatus; + CsrWifiMacAddress peerMacAddress; + CsrWifiMacAddress peerDeviceAddress; + CsrWifiSmeIEEE80211Reason disassocReason; + CsrWifiSmeIEEE80211Reason deauthReason; + CsrWifiSmeWpsRegistration WpsRegistration; + CsrUint8 secIeLength; + CsrUint8 *secIe; + CsrUint8 groupKeyId; + CsrUint16 seqNumber[8]; +} CsrWifiSmeApStaNotifyInd; + +/******************************************************************************* + + NAME + CsrWifiSmeApStaConnectStartInd + + DESCRIPTION + This primitive indicates that a stations request to join the group/BSS is + accepted + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + peerMacAddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiMacAddress peerMacAddress; +} CsrWifiSmeApStaConnectStartInd; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationStartedCfm + + DESCRIPTION + A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_STARTED.request + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeApWpsRegistrationStartedCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsRegistrationFinishedCfm + + DESCRIPTION + A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_FINISHED.request + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeApWpsRegistrationFinishedCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApWmmParamUpdateCfm + + DESCRIPTION + A confirm for CSR_WIFI_SME_AP_WMM_PARAM_UPDATE.request + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeApWmmParamUpdateCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApStaDisconnectCfm + + DESCRIPTION + This primitive confirms the station is disconnected + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - + peerMacaddress - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiMacAddress peerMacaddress; +} CsrWifiSmeApStaDisconnectCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApWpsConfigurationCfm + + DESCRIPTION + Confirm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeApWpsConfigurationCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApErrorInd + + DESCRIPTION + This primitve is sent by SME to indicate some error in AP operationi + after AP operations were started successfully and continuing the AP + operation may lead to undesired behaviour. It is the responsibility of + the upper layers to stop AP operation if needed + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Range 0-1 + apType - + status - Contains the error status + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeApType apType; + CsrResult status; +} CsrWifiSmeApErrorInd; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_AP_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.c b/drivers/staging/csr/csr_wifi_sme_converter_init.c new file mode 100644 index 000000000000..bafd1b411a90 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_converter_init.c @@ -0,0 +1,201 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_msgconv.h" +#include "csr_pmem.h" +#include "csr_util.h" + + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" +#endif + +#ifndef EXCLUDE_CSR_WIFI_SME_MODULE +#include "csr_wifi_sme_serialize.h" +#include "csr_wifi_sme_prim.h" + +static CsrMsgConvMsgEntry csrwifisme_conv_lut[] = { + { CSR_WIFI_SME_ACTIVATE_REQ, CsrWifiSmeActivateReqSizeof, CsrWifiSmeActivateReqSer, CsrWifiSmeActivateReqDes, CsrWifiSmeActivateReqSerFree }, + { CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ, CsrWifiSmeAdhocConfigGetReqSizeof, CsrWifiSmeAdhocConfigGetReqSer, CsrWifiSmeAdhocConfigGetReqDes, CsrWifiSmeAdhocConfigGetReqSerFree }, + { CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ, CsrWifiSmeAdhocConfigSetReqSizeof, CsrWifiSmeAdhocConfigSetReqSer, CsrWifiSmeAdhocConfigSetReqDes, CsrWifiSmeAdhocConfigSetReqSerFree }, + { CSR_WIFI_SME_BLACKLIST_REQ, CsrWifiSmeBlacklistReqSizeof, CsrWifiSmeBlacklistReqSer, CsrWifiSmeBlacklistReqDes, CsrWifiSmeBlacklistReqSerFree }, + { CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ, CsrWifiSmeCalibrationDataGetReqSizeof, CsrWifiSmeCalibrationDataGetReqSer, CsrWifiSmeCalibrationDataGetReqDes, CsrWifiSmeCalibrationDataGetReqSerFree }, + { CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ, CsrWifiSmeCalibrationDataSetReqSizeof, CsrWifiSmeCalibrationDataSetReqSer, CsrWifiSmeCalibrationDataSetReqDes, CsrWifiSmeCalibrationDataSetReqSerFree }, + { CSR_WIFI_SME_CCX_CONFIG_GET_REQ, CsrWifiSmeCcxConfigGetReqSizeof, CsrWifiSmeCcxConfigGetReqSer, CsrWifiSmeCcxConfigGetReqDes, CsrWifiSmeCcxConfigGetReqSerFree }, + { CSR_WIFI_SME_CCX_CONFIG_SET_REQ, CsrWifiSmeCcxConfigSetReqSizeof, CsrWifiSmeCcxConfigSetReqSer, CsrWifiSmeCcxConfigSetReqDes, CsrWifiSmeCcxConfigSetReqSerFree }, + { CSR_WIFI_SME_COEX_CONFIG_GET_REQ, CsrWifiSmeCoexConfigGetReqSizeof, CsrWifiSmeCoexConfigGetReqSer, CsrWifiSmeCoexConfigGetReqDes, CsrWifiSmeCoexConfigGetReqSerFree }, + { CSR_WIFI_SME_COEX_CONFIG_SET_REQ, CsrWifiSmeCoexConfigSetReqSizeof, CsrWifiSmeCoexConfigSetReqSer, CsrWifiSmeCoexConfigSetReqDes, CsrWifiSmeCoexConfigSetReqSerFree }, + { CSR_WIFI_SME_COEX_INFO_GET_REQ, CsrWifiSmeCoexInfoGetReqSizeof, CsrWifiSmeCoexInfoGetReqSer, CsrWifiSmeCoexInfoGetReqDes, CsrWifiSmeCoexInfoGetReqSerFree }, + { CSR_WIFI_SME_CONNECT_REQ, CsrWifiSmeConnectReqSizeof, CsrWifiSmeConnectReqSer, CsrWifiSmeConnectReqDes, CsrWifiSmeConnectReqSerFree }, + { CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ, CsrWifiSmeConnectionConfigGetReqSizeof, CsrWifiSmeConnectionConfigGetReqSer, CsrWifiSmeConnectionConfigGetReqDes, CsrWifiSmeConnectionConfigGetReqSerFree }, + { CSR_WIFI_SME_CONNECTION_INFO_GET_REQ, CsrWifiSmeConnectionInfoGetReqSizeof, CsrWifiSmeConnectionInfoGetReqSer, CsrWifiSmeConnectionInfoGetReqDes, CsrWifiSmeConnectionInfoGetReqSerFree }, + { CSR_WIFI_SME_CONNECTION_STATS_GET_REQ, CsrWifiSmeConnectionStatsGetReqSizeof, CsrWifiSmeConnectionStatsGetReqSer, CsrWifiSmeConnectionStatsGetReqDes, CsrWifiSmeConnectionStatsGetReqSerFree }, + { CSR_WIFI_SME_DEACTIVATE_REQ, CsrWifiSmeDeactivateReqSizeof, CsrWifiSmeDeactivateReqSer, CsrWifiSmeDeactivateReqDes, CsrWifiSmeDeactivateReqSerFree }, + { CSR_WIFI_SME_DISCONNECT_REQ, CsrWifiSmeDisconnectReqSizeof, CsrWifiSmeDisconnectReqSer, CsrWifiSmeDisconnectReqDes, CsrWifiSmeDisconnectReqSerFree }, + { CSR_WIFI_SME_EVENT_MASK_SET_REQ, CsrWifiSmeEventMaskSetReqSizeof, CsrWifiSmeEventMaskSetReqSer, CsrWifiSmeEventMaskSetReqDes, CsrWifiSmeEventMaskSetReqSerFree }, + { CSR_WIFI_SME_HOST_CONFIG_GET_REQ, CsrWifiSmeHostConfigGetReqSizeof, CsrWifiSmeHostConfigGetReqSer, CsrWifiSmeHostConfigGetReqDes, CsrWifiSmeHostConfigGetReqSerFree }, + { CSR_WIFI_SME_HOST_CONFIG_SET_REQ, CsrWifiSmeHostConfigSetReqSizeof, CsrWifiSmeHostConfigSetReqSer, CsrWifiSmeHostConfigSetReqDes, CsrWifiSmeHostConfigSetReqSerFree }, + { CSR_WIFI_SME_KEY_REQ, CsrWifiSmeKeyReqSizeof, CsrWifiSmeKeyReqSer, CsrWifiSmeKeyReqDes, CsrWifiSmeKeyReqSerFree }, + { CSR_WIFI_SME_LINK_QUALITY_GET_REQ, CsrWifiSmeLinkQualityGetReqSizeof, CsrWifiSmeLinkQualityGetReqSer, CsrWifiSmeLinkQualityGetReqDes, CsrWifiSmeLinkQualityGetReqSerFree }, + { CSR_WIFI_SME_MIB_CONFIG_GET_REQ, CsrWifiSmeMibConfigGetReqSizeof, CsrWifiSmeMibConfigGetReqSer, CsrWifiSmeMibConfigGetReqDes, CsrWifiSmeMibConfigGetReqSerFree }, + { CSR_WIFI_SME_MIB_CONFIG_SET_REQ, CsrWifiSmeMibConfigSetReqSizeof, CsrWifiSmeMibConfigSetReqSer, CsrWifiSmeMibConfigSetReqDes, CsrWifiSmeMibConfigSetReqSerFree }, + { CSR_WIFI_SME_MIB_GET_NEXT_REQ, CsrWifiSmeMibGetNextReqSizeof, CsrWifiSmeMibGetNextReqSer, CsrWifiSmeMibGetNextReqDes, CsrWifiSmeMibGetNextReqSerFree }, + { CSR_WIFI_SME_MIB_GET_REQ, CsrWifiSmeMibGetReqSizeof, CsrWifiSmeMibGetReqSer, CsrWifiSmeMibGetReqDes, CsrWifiSmeMibGetReqSerFree }, + { CSR_WIFI_SME_MIB_SET_REQ, CsrWifiSmeMibSetReqSizeof, CsrWifiSmeMibSetReqSer, CsrWifiSmeMibSetReqDes, CsrWifiSmeMibSetReqSerFree }, + { CSR_WIFI_SME_MULTICAST_ADDRESS_REQ, CsrWifiSmeMulticastAddressReqSizeof, CsrWifiSmeMulticastAddressReqSer, CsrWifiSmeMulticastAddressReqDes, CsrWifiSmeMulticastAddressReqSerFree }, + { CSR_WIFI_SME_PACKET_FILTER_SET_REQ, CsrWifiSmePacketFilterSetReqSizeof, CsrWifiSmePacketFilterSetReqSer, CsrWifiSmePacketFilterSetReqDes, CsrWifiSmePacketFilterSetReqSerFree }, + { CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ, CsrWifiSmePermanentMacAddressGetReqSizeof, CsrWifiSmePermanentMacAddressGetReqSer, CsrWifiSmePermanentMacAddressGetReqDes, CsrWifiSmePermanentMacAddressGetReqSerFree }, + { CSR_WIFI_SME_PMKID_REQ, CsrWifiSmePmkidReqSizeof, CsrWifiSmePmkidReqSer, CsrWifiSmePmkidReqDes, CsrWifiSmePmkidReqSerFree }, + { CSR_WIFI_SME_POWER_CONFIG_GET_REQ, CsrWifiSmePowerConfigGetReqSizeof, CsrWifiSmePowerConfigGetReqSer, CsrWifiSmePowerConfigGetReqDes, CsrWifiSmePowerConfigGetReqSerFree }, + { CSR_WIFI_SME_POWER_CONFIG_SET_REQ, CsrWifiSmePowerConfigSetReqSizeof, CsrWifiSmePowerConfigSetReqSer, CsrWifiSmePowerConfigSetReqDes, CsrWifiSmePowerConfigSetReqSerFree }, + { CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ, CsrWifiSmeRegulatoryDomainInfoGetReqSizeof, CsrWifiSmeRegulatoryDomainInfoGetReqSer, CsrWifiSmeRegulatoryDomainInfoGetReqDes, CsrWifiSmeRegulatoryDomainInfoGetReqSerFree }, + { CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ, CsrWifiSmeRoamingConfigGetReqSizeof, CsrWifiSmeRoamingConfigGetReqSer, CsrWifiSmeRoamingConfigGetReqDes, CsrWifiSmeRoamingConfigGetReqSerFree }, + { CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ, CsrWifiSmeRoamingConfigSetReqSizeof, CsrWifiSmeRoamingConfigSetReqSer, CsrWifiSmeRoamingConfigSetReqDes, CsrWifiSmeRoamingConfigSetReqSerFree }, + { CSR_WIFI_SME_SCAN_CONFIG_GET_REQ, CsrWifiSmeScanConfigGetReqSizeof, CsrWifiSmeScanConfigGetReqSer, CsrWifiSmeScanConfigGetReqDes, CsrWifiSmeScanConfigGetReqSerFree }, + { CSR_WIFI_SME_SCAN_CONFIG_SET_REQ, CsrWifiSmeScanConfigSetReqSizeof, CsrWifiSmeScanConfigSetReqSer, CsrWifiSmeScanConfigSetReqDes, CsrWifiSmeScanConfigSetReqSerFree }, + { CSR_WIFI_SME_SCAN_FULL_REQ, CsrWifiSmeScanFullReqSizeof, CsrWifiSmeScanFullReqSer, CsrWifiSmeScanFullReqDes, CsrWifiSmeScanFullReqSerFree }, + { CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ, CsrWifiSmeScanResultsFlushReqSizeof, CsrWifiSmeScanResultsFlushReqSer, CsrWifiSmeScanResultsFlushReqDes, CsrWifiSmeScanResultsFlushReqSerFree }, + { CSR_WIFI_SME_SCAN_RESULTS_GET_REQ, CsrWifiSmeScanResultsGetReqSizeof, CsrWifiSmeScanResultsGetReqSer, CsrWifiSmeScanResultsGetReqDes, CsrWifiSmeScanResultsGetReqSerFree }, + { CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ, CsrWifiSmeSmeStaConfigGetReqSizeof, CsrWifiSmeSmeStaConfigGetReqSer, CsrWifiSmeSmeStaConfigGetReqDes, CsrWifiSmeSmeStaConfigGetReqSerFree }, + { CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ, CsrWifiSmeSmeStaConfigSetReqSizeof, CsrWifiSmeSmeStaConfigSetReqSer, CsrWifiSmeSmeStaConfigSetReqDes, CsrWifiSmeSmeStaConfigSetReqSerFree }, + { CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ, CsrWifiSmeStationMacAddressGetReqSizeof, CsrWifiSmeStationMacAddressGetReqSer, CsrWifiSmeStationMacAddressGetReqDes, CsrWifiSmeStationMacAddressGetReqSerFree }, + { CSR_WIFI_SME_TSPEC_REQ, CsrWifiSmeTspecReqSizeof, CsrWifiSmeTspecReqSer, CsrWifiSmeTspecReqDes, CsrWifiSmeTspecReqSerFree }, + { CSR_WIFI_SME_VERSIONS_GET_REQ, CsrWifiSmeVersionsGetReqSizeof, CsrWifiSmeVersionsGetReqSer, CsrWifiSmeVersionsGetReqDes, CsrWifiSmeVersionsGetReqSerFree }, + { CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ, CsrWifiSmeWifiFlightmodeReqSizeof, CsrWifiSmeWifiFlightmodeReqSer, CsrWifiSmeWifiFlightmodeReqDes, CsrWifiSmeWifiFlightmodeReqSerFree }, + { CSR_WIFI_SME_WIFI_OFF_REQ, CsrWifiSmeWifiOffReqSizeof, CsrWifiSmeWifiOffReqSer, CsrWifiSmeWifiOffReqDes, CsrWifiSmeWifiOffReqSerFree }, + { CSR_WIFI_SME_WIFI_ON_REQ, CsrWifiSmeWifiOnReqSizeof, CsrWifiSmeWifiOnReqSer, CsrWifiSmeWifiOnReqDes, CsrWifiSmeWifiOnReqSerFree }, + { CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ, CsrWifiSmeCloakedSsidsSetReqSizeof, CsrWifiSmeCloakedSsidsSetReqSer, CsrWifiSmeCloakedSsidsSetReqDes, CsrWifiSmeCloakedSsidsSetReqSerFree }, + { CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ, CsrWifiSmeCloakedSsidsGetReqSizeof, CsrWifiSmeCloakedSsidsGetReqSer, CsrWifiSmeCloakedSsidsGetReqDes, CsrWifiSmeCloakedSsidsGetReqSerFree }, + { CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ, CsrWifiSmeSmeCommonConfigGetReqSizeof, CsrWifiSmeSmeCommonConfigGetReqSer, CsrWifiSmeSmeCommonConfigGetReqDes, CsrWifiSmeSmeCommonConfigGetReqSerFree }, + { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree }, + { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree }, + { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree }, + { CSR_WIFI_SME_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree }, + { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree }, + { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree }, + { CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND, CsrWifiSmeAssociationCompleteIndSizeof, CsrWifiSmeAssociationCompleteIndSer, CsrWifiSmeAssociationCompleteIndDes, CsrWifiSmeAssociationCompleteIndSerFree }, + { CSR_WIFI_SME_ASSOCIATION_START_IND, CsrWifiSmeAssociationStartIndSizeof, CsrWifiSmeAssociationStartIndSer, CsrWifiSmeAssociationStartIndDes, CsrWifiSmeAssociationStartIndSerFree }, + { CSR_WIFI_SME_BLACKLIST_CFM, CsrWifiSmeBlacklistCfmSizeof, CsrWifiSmeBlacklistCfmSer, CsrWifiSmeBlacklistCfmDes, CsrWifiSmeBlacklistCfmSerFree }, + { CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM, CsrWifiSmeCalibrationDataGetCfmSizeof, CsrWifiSmeCalibrationDataGetCfmSer, CsrWifiSmeCalibrationDataGetCfmDes, CsrWifiSmeCalibrationDataGetCfmSerFree }, + { CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM, CsrWifiSmeCalibrationDataSetCfmSizeof, CsrWifiSmeCalibrationDataSetCfmSer, CsrWifiSmeCalibrationDataSetCfmDes, CsrWifiSmeCalibrationDataSetCfmSerFree }, + { CSR_WIFI_SME_CCX_CONFIG_GET_CFM, CsrWifiSmeCcxConfigGetCfmSizeof, CsrWifiSmeCcxConfigGetCfmSer, CsrWifiSmeCcxConfigGetCfmDes, CsrWifiSmeCcxConfigGetCfmSerFree }, + { CSR_WIFI_SME_CCX_CONFIG_SET_CFM, CsrWifiSmeCcxConfigSetCfmSizeof, CsrWifiSmeCcxConfigSetCfmSer, CsrWifiSmeCcxConfigSetCfmDes, CsrWifiSmeCcxConfigSetCfmSerFree }, + { CSR_WIFI_SME_COEX_CONFIG_GET_CFM, CsrWifiSmeCoexConfigGetCfmSizeof, CsrWifiSmeCoexConfigGetCfmSer, CsrWifiSmeCoexConfigGetCfmDes, CsrWifiSmeCoexConfigGetCfmSerFree }, + { CSR_WIFI_SME_COEX_CONFIG_SET_CFM, CsrWifiSmeCoexConfigSetCfmSizeof, CsrWifiSmeCoexConfigSetCfmSer, CsrWifiSmeCoexConfigSetCfmDes, CsrWifiSmeCoexConfigSetCfmSerFree }, + { CSR_WIFI_SME_COEX_INFO_GET_CFM, CsrWifiSmeCoexInfoGetCfmSizeof, CsrWifiSmeCoexInfoGetCfmSer, CsrWifiSmeCoexInfoGetCfmDes, CsrWifiSmeCoexInfoGetCfmSerFree }, + { CSR_WIFI_SME_CONNECT_CFM, CsrWifiSmeConnectCfmSizeof, CsrWifiSmeConnectCfmSer, CsrWifiSmeConnectCfmDes, CsrWifiSmeConnectCfmSerFree }, + { CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM, CsrWifiSmeConnectionConfigGetCfmSizeof, CsrWifiSmeConnectionConfigGetCfmSer, CsrWifiSmeConnectionConfigGetCfmDes, CsrWifiSmeConnectionConfigGetCfmSerFree }, + { CSR_WIFI_SME_CONNECTION_INFO_GET_CFM, CsrWifiSmeConnectionInfoGetCfmSizeof, CsrWifiSmeConnectionInfoGetCfmSer, CsrWifiSmeConnectionInfoGetCfmDes, CsrWifiSmeConnectionInfoGetCfmSerFree }, + { CSR_WIFI_SME_CONNECTION_QUALITY_IND, CsrWifiSmeConnectionQualityIndSizeof, CsrWifiSmeConnectionQualityIndSer, CsrWifiSmeConnectionQualityIndDes, CsrWifiSmeConnectionQualityIndSerFree }, + { CSR_WIFI_SME_CONNECTION_STATS_GET_CFM, CsrWifiSmeConnectionStatsGetCfmSizeof, CsrWifiSmeConnectionStatsGetCfmSer, CsrWifiSmeConnectionStatsGetCfmDes, CsrWifiSmeConnectionStatsGetCfmSerFree }, + { CSR_WIFI_SME_DEACTIVATE_CFM, CsrWifiSmeDeactivateCfmSizeof, CsrWifiSmeDeactivateCfmSer, CsrWifiSmeDeactivateCfmDes, CsrWifiSmeDeactivateCfmSerFree }, + { CSR_WIFI_SME_DISCONNECT_CFM, CsrWifiSmeDisconnectCfmSizeof, CsrWifiSmeDisconnectCfmSer, CsrWifiSmeDisconnectCfmDes, CsrWifiSmeDisconnectCfmSerFree }, + { CSR_WIFI_SME_EVENT_MASK_SET_CFM, CsrWifiSmeEventMaskSetCfmSizeof, CsrWifiSmeEventMaskSetCfmSer, CsrWifiSmeEventMaskSetCfmDes, CsrWifiSmeEventMaskSetCfmSerFree }, + { CSR_WIFI_SME_HOST_CONFIG_GET_CFM, CsrWifiSmeHostConfigGetCfmSizeof, CsrWifiSmeHostConfigGetCfmSer, CsrWifiSmeHostConfigGetCfmDes, CsrWifiSmeHostConfigGetCfmSerFree }, + { CSR_WIFI_SME_HOST_CONFIG_SET_CFM, CsrWifiSmeHostConfigSetCfmSizeof, CsrWifiSmeHostConfigSetCfmSer, CsrWifiSmeHostConfigSetCfmDes, CsrWifiSmeHostConfigSetCfmSerFree }, + { CSR_WIFI_SME_IBSS_STATION_IND, CsrWifiSmeIbssStationIndSizeof, CsrWifiSmeIbssStationIndSer, CsrWifiSmeIbssStationIndDes, CsrWifiSmeIbssStationIndSerFree }, + { CSR_WIFI_SME_KEY_CFM, CsrWifiSmeKeyCfmSizeof, CsrWifiSmeKeyCfmSer, CsrWifiSmeKeyCfmDes, CsrWifiSmeKeyCfmSerFree }, + { CSR_WIFI_SME_LINK_QUALITY_GET_CFM, CsrWifiSmeLinkQualityGetCfmSizeof, CsrWifiSmeLinkQualityGetCfmSer, CsrWifiSmeLinkQualityGetCfmDes, CsrWifiSmeLinkQualityGetCfmSerFree }, + { CSR_WIFI_SME_MEDIA_STATUS_IND, CsrWifiSmeMediaStatusIndSizeof, CsrWifiSmeMediaStatusIndSer, CsrWifiSmeMediaStatusIndDes, CsrWifiSmeMediaStatusIndSerFree }, + { CSR_WIFI_SME_MIB_CONFIG_GET_CFM, CsrWifiSmeMibConfigGetCfmSizeof, CsrWifiSmeMibConfigGetCfmSer, CsrWifiSmeMibConfigGetCfmDes, CsrWifiSmeMibConfigGetCfmSerFree }, + { CSR_WIFI_SME_MIB_CONFIG_SET_CFM, CsrWifiSmeMibConfigSetCfmSizeof, CsrWifiSmeMibConfigSetCfmSer, CsrWifiSmeMibConfigSetCfmDes, CsrWifiSmeMibConfigSetCfmSerFree }, + { CSR_WIFI_SME_MIB_GET_CFM, CsrWifiSmeMibGetCfmSizeof, CsrWifiSmeMibGetCfmSer, CsrWifiSmeMibGetCfmDes, CsrWifiSmeMibGetCfmSerFree }, + { CSR_WIFI_SME_MIB_GET_NEXT_CFM, CsrWifiSmeMibGetNextCfmSizeof, CsrWifiSmeMibGetNextCfmSer, CsrWifiSmeMibGetNextCfmDes, CsrWifiSmeMibGetNextCfmSerFree }, + { CSR_WIFI_SME_MIB_SET_CFM, CsrWifiSmeMibSetCfmSizeof, CsrWifiSmeMibSetCfmSer, CsrWifiSmeMibSetCfmDes, CsrWifiSmeMibSetCfmSerFree }, + { CSR_WIFI_SME_MIC_FAILURE_IND, CsrWifiSmeMicFailureIndSizeof, CsrWifiSmeMicFailureIndSer, CsrWifiSmeMicFailureIndDes, CsrWifiSmeMicFailureIndSerFree }, + { CSR_WIFI_SME_MULTICAST_ADDRESS_CFM, CsrWifiSmeMulticastAddressCfmSizeof, CsrWifiSmeMulticastAddressCfmSer, CsrWifiSmeMulticastAddressCfmDes, CsrWifiSmeMulticastAddressCfmSerFree }, + { CSR_WIFI_SME_PACKET_FILTER_SET_CFM, CsrWifiSmePacketFilterSetCfmSizeof, CsrWifiSmePacketFilterSetCfmSer, CsrWifiSmePacketFilterSetCfmDes, CsrWifiSmePacketFilterSetCfmSerFree }, + { CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM, CsrWifiSmePermanentMacAddressGetCfmSizeof, CsrWifiSmePermanentMacAddressGetCfmSer, CsrWifiSmePermanentMacAddressGetCfmDes, CsrWifiSmePermanentMacAddressGetCfmSerFree }, + { CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND, CsrWifiSmePmkidCandidateListIndSizeof, CsrWifiSmePmkidCandidateListIndSer, CsrWifiSmePmkidCandidateListIndDes, CsrWifiSmePmkidCandidateListIndSerFree }, + { CSR_WIFI_SME_PMKID_CFM, CsrWifiSmePmkidCfmSizeof, CsrWifiSmePmkidCfmSer, CsrWifiSmePmkidCfmDes, CsrWifiSmePmkidCfmSerFree }, + { CSR_WIFI_SME_POWER_CONFIG_GET_CFM, CsrWifiSmePowerConfigGetCfmSizeof, CsrWifiSmePowerConfigGetCfmSer, CsrWifiSmePowerConfigGetCfmDes, CsrWifiSmePowerConfigGetCfmSerFree }, + { CSR_WIFI_SME_POWER_CONFIG_SET_CFM, CsrWifiSmePowerConfigSetCfmSizeof, CsrWifiSmePowerConfigSetCfmSer, CsrWifiSmePowerConfigSetCfmDes, CsrWifiSmePowerConfigSetCfmSerFree }, + { CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM, CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof, CsrWifiSmeRegulatoryDomainInfoGetCfmSer, CsrWifiSmeRegulatoryDomainInfoGetCfmDes, CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree }, + { CSR_WIFI_SME_ROAM_COMPLETE_IND, CsrWifiSmeRoamCompleteIndSizeof, CsrWifiSmeRoamCompleteIndSer, CsrWifiSmeRoamCompleteIndDes, CsrWifiSmeRoamCompleteIndSerFree }, + { CSR_WIFI_SME_ROAM_START_IND, CsrWifiSmeRoamStartIndSizeof, CsrWifiSmeRoamStartIndSer, CsrWifiSmeRoamStartIndDes, CsrWifiSmeRoamStartIndSerFree }, + { CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM, CsrWifiSmeRoamingConfigGetCfmSizeof, CsrWifiSmeRoamingConfigGetCfmSer, CsrWifiSmeRoamingConfigGetCfmDes, CsrWifiSmeRoamingConfigGetCfmSerFree }, + { CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM, CsrWifiSmeRoamingConfigSetCfmSizeof, CsrWifiSmeRoamingConfigSetCfmSer, CsrWifiSmeRoamingConfigSetCfmDes, CsrWifiSmeRoamingConfigSetCfmSerFree }, + { CSR_WIFI_SME_SCAN_CONFIG_GET_CFM, CsrWifiSmeScanConfigGetCfmSizeof, CsrWifiSmeScanConfigGetCfmSer, CsrWifiSmeScanConfigGetCfmDes, CsrWifiSmeScanConfigGetCfmSerFree }, + { CSR_WIFI_SME_SCAN_CONFIG_SET_CFM, CsrWifiSmeScanConfigSetCfmSizeof, CsrWifiSmeScanConfigSetCfmSer, CsrWifiSmeScanConfigSetCfmDes, CsrWifiSmeScanConfigSetCfmSerFree }, + { CSR_WIFI_SME_SCAN_FULL_CFM, CsrWifiSmeScanFullCfmSizeof, CsrWifiSmeScanFullCfmSer, CsrWifiSmeScanFullCfmDes, CsrWifiSmeScanFullCfmSerFree }, + { CSR_WIFI_SME_SCAN_RESULT_IND, CsrWifiSmeScanResultIndSizeof, CsrWifiSmeScanResultIndSer, CsrWifiSmeScanResultIndDes, CsrWifiSmeScanResultIndSerFree }, + { CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM, CsrWifiSmeScanResultsFlushCfmSizeof, CsrWifiSmeScanResultsFlushCfmSer, CsrWifiSmeScanResultsFlushCfmDes, CsrWifiSmeScanResultsFlushCfmSerFree }, + { CSR_WIFI_SME_SCAN_RESULTS_GET_CFM, CsrWifiSmeScanResultsGetCfmSizeof, CsrWifiSmeScanResultsGetCfmSer, CsrWifiSmeScanResultsGetCfmDes, CsrWifiSmeScanResultsGetCfmSerFree }, + { CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM, CsrWifiSmeSmeStaConfigGetCfmSizeof, CsrWifiSmeSmeStaConfigGetCfmSer, CsrWifiSmeSmeStaConfigGetCfmDes, CsrWifiSmeSmeStaConfigGetCfmSerFree }, + { CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM, CsrWifiSmeSmeStaConfigSetCfmSizeof, CsrWifiSmeSmeStaConfigSetCfmSer, CsrWifiSmeSmeStaConfigSetCfmDes, CsrWifiSmeSmeStaConfigSetCfmSerFree }, + { CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM, CsrWifiSmeStationMacAddressGetCfmSizeof, CsrWifiSmeStationMacAddressGetCfmSer, CsrWifiSmeStationMacAddressGetCfmDes, CsrWifiSmeStationMacAddressGetCfmSerFree }, + { CSR_WIFI_SME_TSPEC_IND, CsrWifiSmeTspecIndSizeof, CsrWifiSmeTspecIndSer, CsrWifiSmeTspecIndDes, CsrWifiSmeTspecIndSerFree }, + { CSR_WIFI_SME_TSPEC_CFM, CsrWifiSmeTspecCfmSizeof, CsrWifiSmeTspecCfmSer, CsrWifiSmeTspecCfmDes, CsrWifiSmeTspecCfmSerFree }, + { CSR_WIFI_SME_VERSIONS_GET_CFM, CsrWifiSmeVersionsGetCfmSizeof, CsrWifiSmeVersionsGetCfmSer, CsrWifiSmeVersionsGetCfmDes, CsrWifiSmeVersionsGetCfmSerFree }, + { CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM, CsrWifiSmeWifiFlightmodeCfmSizeof, CsrWifiSmeWifiFlightmodeCfmSer, CsrWifiSmeWifiFlightmodeCfmDes, CsrWifiSmeWifiFlightmodeCfmSerFree }, + { CSR_WIFI_SME_WIFI_OFF_IND, CsrWifiSmeWifiOffIndSizeof, CsrWifiSmeWifiOffIndSer, CsrWifiSmeWifiOffIndDes, CsrWifiSmeWifiOffIndSerFree }, + { CSR_WIFI_SME_WIFI_OFF_CFM, CsrWifiSmeWifiOffCfmSizeof, CsrWifiSmeWifiOffCfmSer, CsrWifiSmeWifiOffCfmDes, CsrWifiSmeWifiOffCfmSerFree }, + { CSR_WIFI_SME_WIFI_ON_CFM, CsrWifiSmeWifiOnCfmSizeof, CsrWifiSmeWifiOnCfmSer, CsrWifiSmeWifiOnCfmDes, CsrWifiSmeWifiOnCfmSerFree }, + { CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM, CsrWifiSmeCloakedSsidsSetCfmSizeof, CsrWifiSmeCloakedSsidsSetCfmSer, CsrWifiSmeCloakedSsidsSetCfmDes, CsrWifiSmeCloakedSsidsSetCfmSerFree }, + { CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM, CsrWifiSmeCloakedSsidsGetCfmSizeof, CsrWifiSmeCloakedSsidsGetCfmSer, CsrWifiSmeCloakedSsidsGetCfmDes, CsrWifiSmeCloakedSsidsGetCfmSerFree }, + { CSR_WIFI_SME_WIFI_ON_IND, CsrWifiSmeWifiOnIndSizeof, CsrWifiSmeWifiOnIndSer, CsrWifiSmeWifiOnIndDes, CsrWifiSmeWifiOnIndSerFree }, + { CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM, CsrWifiSmeSmeCommonConfigGetCfmSizeof, CsrWifiSmeSmeCommonConfigGetCfmSer, CsrWifiSmeSmeCommonConfigGetCfmDes, CsrWifiSmeSmeCommonConfigGetCfmSerFree }, + { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM, CsrWifiSmeSmeCommonConfigSetCfmSizeof, CsrWifiSmeSmeCommonConfigSetCfmSer, CsrWifiSmeSmeCommonConfigSetCfmDes, CsrWifiSmeSmeCommonConfigSetCfmSerFree }, + { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM, CsrWifiSmeInterfaceCapabilityGetCfmSizeof, CsrWifiSmeInterfaceCapabilityGetCfmSer, CsrWifiSmeInterfaceCapabilityGetCfmDes, CsrWifiSmeInterfaceCapabilityGetCfmSerFree }, + { CSR_WIFI_SME_ERROR_IND, CsrWifiSmeErrorIndSizeof, CsrWifiSmeErrorIndSer, CsrWifiSmeErrorIndDes, CsrWifiSmeErrorIndSerFree }, + { CSR_WIFI_SME_INFO_IND, CsrWifiSmeInfoIndSizeof, CsrWifiSmeInfoIndSer, CsrWifiSmeInfoIndDes, CsrWifiSmeInfoIndSerFree }, + { CSR_WIFI_SME_CORE_DUMP_IND, CsrWifiSmeCoreDumpIndSizeof, CsrWifiSmeCoreDumpIndSer, CsrWifiSmeCoreDumpIndDes, CsrWifiSmeCoreDumpIndSerFree }, + { CSR_WIFI_SME_AMP_STATUS_CHANGE_IND, CsrWifiSmeAmpStatusChangeIndSizeof, CsrWifiSmeAmpStatusChangeIndSer, CsrWifiSmeAmpStatusChangeIndDes, CsrWifiSmeAmpStatusChangeIndSerFree }, + { CSR_WIFI_SME_WPS_CONFIGURATION_CFM, CsrWifiSmeWpsConfigurationCfmSizeof, CsrWifiSmeWpsConfigurationCfmSer, CsrWifiSmeWpsConfigurationCfmDes, CsrWifiSmeWpsConfigurationCfmSerFree }, + + { 0, NULL, NULL, NULL, NULL }, +}; + +CsrMsgConvMsgEntry* CsrWifiSmeConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16 msgType) +{ + if (msgType & CSR_PRIM_UPSTREAM) + { + CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT; + if (index < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) && + csrwifisme_conv_lut[index].msgType == msgType) + { + return &csrwifisme_conv_lut[index]; + } + } + else + { + if (msgType < CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT && + csrwifisme_conv_lut[msgType].msgType == msgType) + { + return &csrwifisme_conv_lut[msgType]; + } + } + return NULL; +} + + +void CsrWifiSmeConverterInit(void) +{ + CsrMsgConvInsert(CSR_WIFI_SME_PRIM, csrwifisme_conv_lut); + CsrMsgConvCustomLookupRegister(CSR_WIFI_SME_PRIM, CsrWifiSmeConverterLookup); +} + + +#ifdef CSR_LOG_ENABLE +static const CsrLogPrimitiveInformation csrwifisme_conv_info = { + CSR_WIFI_SME_PRIM, + (CsrCharString *)"CSR_WIFI_SME_PRIM", + csrwifisme_conv_lut +}; +const CsrLogPrimitiveInformation* CsrWifiSmeTechInfoGet(void) +{ + return &csrwifisme_conv_info; +} + + +#endif /* CSR_LOG_ENABLE */ +#endif /* EXCLUDE_CSR_WIFI_SME_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.h b/drivers/staging/csr/csr_wifi_sme_converter_init.h new file mode 100644 index 000000000000..8637eb7baafe --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_converter_init.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_CONVERTER_INIT_H__ +#define CSR_WIFI_SME_CONVERTER_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXCLUDE_CSR_WIFI_SME_MODULE + +#include "csr_msgconv.h" + +#ifdef CSR_LOG_ENABLE +#include "csr_log.h" + +extern const CsrLogPrimitiveInformation* CsrWifiSmeTechInfoGet(void); +#endif /* CSR_LOG_ENABLE */ + +extern void CsrWifiSmeConverterInit(void); + +#else /* EXCLUDE_CSR_WIFI_SME_MODULE */ + +#define CsrWifiSmeConverterInit() + +#endif /* EXCLUDE_CSR_WIFI_SME_MODULE */ + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c new file mode 100644 index 000000000000..c8e66be899cd --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c @@ -0,0 +1,181 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_sme_prim.h" +#include "csr_wifi_sme_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiSmeFreeDownstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_SME_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_SME_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiSmePrim *) message)) + { + case CSR_WIFI_SME_BLACKLIST_REQ: + { + CsrWifiSmeBlacklistReq *p = (CsrWifiSmeBlacklistReq *)message; + CsrPmemFree(p->setAddresses); + p->setAddresses = NULL; + break; + } + case CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ: + { + CsrWifiSmeCalibrationDataSetReq *p = (CsrWifiSmeCalibrationDataSetReq *)message; + CsrPmemFree(p->calibrationData); + p->calibrationData = NULL; + break; + } + case CSR_WIFI_SME_CONNECT_REQ: + { + CsrWifiSmeConnectReq *p = (CsrWifiSmeConnectReq *)message; + CsrPmemFree(p->connectionConfig.mlmeAssociateReqInformationElements); + p->connectionConfig.mlmeAssociateReqInformationElements = NULL; + break; + } + case CSR_WIFI_SME_MIB_GET_NEXT_REQ: + { + CsrWifiSmeMibGetNextReq *p = (CsrWifiSmeMibGetNextReq *)message; + CsrPmemFree(p->mibAttribute); + p->mibAttribute = NULL; + break; + } + case CSR_WIFI_SME_MIB_GET_REQ: + { + CsrWifiSmeMibGetReq *p = (CsrWifiSmeMibGetReq *)message; + CsrPmemFree(p->mibAttribute); + p->mibAttribute = NULL; + break; + } + case CSR_WIFI_SME_MIB_SET_REQ: + { + CsrWifiSmeMibSetReq *p = (CsrWifiSmeMibSetReq *)message; + CsrPmemFree(p->mibAttribute); + p->mibAttribute = NULL; + break; + } + case CSR_WIFI_SME_MULTICAST_ADDRESS_REQ: + { + CsrWifiSmeMulticastAddressReq *p = (CsrWifiSmeMulticastAddressReq *)message; + CsrPmemFree(p->setAddresses); + p->setAddresses = NULL; + break; + } + case CSR_WIFI_SME_PACKET_FILTER_SET_REQ: + { + CsrWifiSmePacketFilterSetReq *p = (CsrWifiSmePacketFilterSetReq *)message; + CsrPmemFree(p->filter); + p->filter = NULL; + break; + } + case CSR_WIFI_SME_PMKID_REQ: + { + CsrWifiSmePmkidReq *p = (CsrWifiSmePmkidReq *)message; + CsrPmemFree(p->setPmkids); + p->setPmkids = NULL; + break; + } + case CSR_WIFI_SME_SCAN_CONFIG_SET_REQ: + { + CsrWifiSmeScanConfigSetReq *p = (CsrWifiSmeScanConfigSetReq *)message; + CsrPmemFree(p->scanConfig.passiveChannelList); + p->scanConfig.passiveChannelList = NULL; + break; + } + case CSR_WIFI_SME_SCAN_FULL_REQ: + { + CsrWifiSmeScanFullReq *p = (CsrWifiSmeScanFullReq *)message; + CsrPmemFree(p->ssid); + p->ssid = NULL; + CsrPmemFree(p->channelList); + p->channelList = NULL; + CsrPmemFree(p->probeIe); + p->probeIe = NULL; + break; + } + case CSR_WIFI_SME_TSPEC_REQ: + { + CsrWifiSmeTspecReq *p = (CsrWifiSmeTspecReq *)message; + CsrPmemFree(p->tspec); + p->tspec = NULL; + CsrPmemFree(p->tclas); + p->tclas = NULL; + break; + } + case CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ: + { + CsrWifiSmeWifiFlightmodeReq *p = (CsrWifiSmeWifiFlightmodeReq *)message; + { + CsrUint16 i1; + for (i1 = 0; i1 < p->mibFilesCount; i1++) + { + CsrPmemFree(p->mibFiles[i1].data); + p->mibFiles[i1].data = NULL; + } + } + CsrPmemFree(p->mibFiles); + p->mibFiles = NULL; + break; + } + case CSR_WIFI_SME_WIFI_ON_REQ: + { + CsrWifiSmeWifiOnReq *p = (CsrWifiSmeWifiOnReq *)message; + { + CsrUint16 i1; + for (i1 = 0; i1 < p->mibFilesCount; i1++) + { + CsrPmemFree(p->mibFiles[i1].data); + p->mibFiles[i1].data = NULL; + } + } + CsrPmemFree(p->mibFiles); + p->mibFiles = NULL; + break; + } + case CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ: + { + CsrWifiSmeCloakedSsidsSetReq *p = (CsrWifiSmeCloakedSsidsSetReq *)message; + CsrPmemFree(p->cloakedSsids.cloakedSsids); + p->cloakedSsids.cloakedSsids = NULL; + break; + } + case CSR_WIFI_SME_WPS_CONFIGURATION_REQ: + { + CsrWifiSmeWpsConfigurationReq *p = (CsrWifiSmeWpsConfigurationReq *)message; + CsrPmemFree(p->wpsConfig.secondaryDeviceType); + p->wpsConfig.secondaryDeviceType = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c new file mode 100644 index 000000000000..c32bf6877bff --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c @@ -0,0 +1,276 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_wifi_sme_prim.h" +#include "csr_wifi_sme_lib.h" + +/*----------------------------------------------------------------------------* + * NAME + * CsrWifiSmeFreeUpstreamMessageContents + * + * DESCRIPTION + * + * + * PARAMETERS + * eventClass: only the value CSR_WIFI_SME_PRIM will be handled + * message: the message to free + *----------------------------------------------------------------------------*/ +void CsrWifiSmeFreeUpstreamMessageContents(CsrUint16 eventClass, void *message) +{ + if (eventClass != CSR_WIFI_SME_PRIM) + { + return; + } + if (NULL == message) + { + return; + } + + switch (*((CsrWifiSmePrim *) message)) + { + case CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND: + { + CsrWifiSmeAssociationCompleteInd *p = (CsrWifiSmeAssociationCompleteInd *)message; + CsrPmemFree(p->connectionInfo.beaconFrame); + p->connectionInfo.beaconFrame = NULL; + CsrPmemFree(p->connectionInfo.associationReqFrame); + p->connectionInfo.associationReqFrame = NULL; + CsrPmemFree(p->connectionInfo.associationRspFrame); + p->connectionInfo.associationRspFrame = NULL; + CsrPmemFree(p->connectionInfo.assocScanInfoElements); + p->connectionInfo.assocScanInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocReqInfoElements); + p->connectionInfo.assocReqInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocRspInfoElements); + p->connectionInfo.assocRspInfoElements = NULL; + break; + } + case CSR_WIFI_SME_BLACKLIST_CFM: + { + CsrWifiSmeBlacklistCfm *p = (CsrWifiSmeBlacklistCfm *)message; + CsrPmemFree(p->getAddresses); + p->getAddresses = NULL; + break; + } + case CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM: + { + CsrWifiSmeCalibrationDataGetCfm *p = (CsrWifiSmeCalibrationDataGetCfm *)message; + CsrPmemFree(p->calibrationData); + p->calibrationData = NULL; + break; + } + case CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM: + { + CsrWifiSmeConnectionConfigGetCfm *p = (CsrWifiSmeConnectionConfigGetCfm *)message; + CsrPmemFree(p->connectionConfig.mlmeAssociateReqInformationElements); + p->connectionConfig.mlmeAssociateReqInformationElements = NULL; + break; + } + case CSR_WIFI_SME_CONNECTION_INFO_GET_CFM: + { + CsrWifiSmeConnectionInfoGetCfm *p = (CsrWifiSmeConnectionInfoGetCfm *)message; + CsrPmemFree(p->connectionInfo.beaconFrame); + p->connectionInfo.beaconFrame = NULL; + CsrPmemFree(p->connectionInfo.associationReqFrame); + p->connectionInfo.associationReqFrame = NULL; + CsrPmemFree(p->connectionInfo.associationRspFrame); + p->connectionInfo.associationRspFrame = NULL; + CsrPmemFree(p->connectionInfo.assocScanInfoElements); + p->connectionInfo.assocScanInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocReqInfoElements); + p->connectionInfo.assocReqInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocRspInfoElements); + p->connectionInfo.assocRspInfoElements = NULL; + break; + } + case CSR_WIFI_SME_MEDIA_STATUS_IND: + { + CsrWifiSmeMediaStatusInd *p = (CsrWifiSmeMediaStatusInd *)message; + CsrPmemFree(p->connectionInfo.beaconFrame); + p->connectionInfo.beaconFrame = NULL; + CsrPmemFree(p->connectionInfo.associationReqFrame); + p->connectionInfo.associationReqFrame = NULL; + CsrPmemFree(p->connectionInfo.associationRspFrame); + p->connectionInfo.associationRspFrame = NULL; + CsrPmemFree(p->connectionInfo.assocScanInfoElements); + p->connectionInfo.assocScanInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocReqInfoElements); + p->connectionInfo.assocReqInfoElements = NULL; + CsrPmemFree(p->connectionInfo.assocRspInfoElements); + p->connectionInfo.assocRspInfoElements = NULL; + break; + } + case CSR_WIFI_SME_MIB_GET_CFM: + { + CsrWifiSmeMibGetCfm *p = (CsrWifiSmeMibGetCfm *)message; + CsrPmemFree(p->mibAttribute); + p->mibAttribute = NULL; + break; + } + case CSR_WIFI_SME_MIB_GET_NEXT_CFM: + { + CsrWifiSmeMibGetNextCfm *p = (CsrWifiSmeMibGetNextCfm *)message; + CsrPmemFree(p->mibAttribute); + p->mibAttribute = NULL; + break; + } + case CSR_WIFI_SME_MULTICAST_ADDRESS_CFM: + { + CsrWifiSmeMulticastAddressCfm *p = (CsrWifiSmeMulticastAddressCfm *)message; + CsrPmemFree(p->getAddresses); + p->getAddresses = NULL; + break; + } + case CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND: + { + CsrWifiSmePmkidCandidateListInd *p = (CsrWifiSmePmkidCandidateListInd *)message; + CsrPmemFree(p->pmkidCandidates); + p->pmkidCandidates = NULL; + break; + } + case CSR_WIFI_SME_PMKID_CFM: + { + CsrWifiSmePmkidCfm *p = (CsrWifiSmePmkidCfm *)message; + CsrPmemFree(p->getPmkids); + p->getPmkids = NULL; + break; + } + case CSR_WIFI_SME_SCAN_CONFIG_GET_CFM: + { + CsrWifiSmeScanConfigGetCfm *p = (CsrWifiSmeScanConfigGetCfm *)message; + CsrPmemFree(p->scanConfig.passiveChannelList); + p->scanConfig.passiveChannelList = NULL; + break; + } + case CSR_WIFI_SME_SCAN_RESULT_IND: + { + CsrWifiSmeScanResultInd *p = (CsrWifiSmeScanResultInd *)message; + CsrPmemFree(p->result.informationElements); + p->result.informationElements = NULL; + switch (p->result.p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_GO: + { + CsrUint16 i4; + for (i4 = 0; i4 < p->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrPmemFree(p->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); + p->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; + } + } + CsrPmemFree(p->result.deviceInfo.groupInfo.p2PClientInfo); + p->result.deviceInfo.groupInfo.p2PClientInfo = NULL; + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrPmemFree(p->result.deviceInfo.standalonedevInfo.secDeviceType); + p->result.deviceInfo.standalonedevInfo.secDeviceType = NULL; + break; + default: + break; + } + break; + } + case CSR_WIFI_SME_SCAN_RESULTS_GET_CFM: + { + CsrWifiSmeScanResultsGetCfm *p = (CsrWifiSmeScanResultsGetCfm *)message; + { + CsrUint16 i1; + for (i1 = 0; i1 < p->scanResultsCount; i1++) + { + CsrPmemFree(p->scanResults[i1].informationElements); + p->scanResults[i1].informationElements = NULL; + switch (p->scanResults[i1].p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_GO: + { + CsrUint16 i4; + for (i4 = 0; i4 < p->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrPmemFree(p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); + p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; + } + } + CsrPmemFree(p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo); + p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = NULL; + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrPmemFree(p->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType); + p->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = NULL; + break; + default: + break; + } + } + } + CsrPmemFree(p->scanResults); + p->scanResults = NULL; + break; + } + case CSR_WIFI_SME_TSPEC_IND: + { + CsrWifiSmeTspecInd *p = (CsrWifiSmeTspecInd *)message; + CsrPmemFree(p->tspec); + p->tspec = NULL; + break; + } + case CSR_WIFI_SME_TSPEC_CFM: + { + CsrWifiSmeTspecCfm *p = (CsrWifiSmeTspecCfm *)message; + CsrPmemFree(p->tspec); + p->tspec = NULL; + break; + } + case CSR_WIFI_SME_VERSIONS_GET_CFM: + { + CsrWifiSmeVersionsGetCfm *p = (CsrWifiSmeVersionsGetCfm *)message; + CsrPmemFree(p->versions.routerBuild); + p->versions.routerBuild = NULL; + CsrPmemFree(p->versions.smeBuild); + p->versions.smeBuild = NULL; + break; + } + case CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM: + { + CsrWifiSmeCloakedSsidsGetCfm *p = (CsrWifiSmeCloakedSsidsGetCfm *)message; + CsrPmemFree(p->cloakedSsids.cloakedSsids); + p->cloakedSsids.cloakedSsids = NULL; + break; + } + case CSR_WIFI_SME_ERROR_IND: + { + CsrWifiSmeErrorInd *p = (CsrWifiSmeErrorInd *)message; + CsrPmemFree(p->errorMessage); + p->errorMessage = NULL; + break; + } + case CSR_WIFI_SME_INFO_IND: + { + CsrWifiSmeInfoInd *p = (CsrWifiSmeInfoInd *)message; + CsrPmemFree(p->infoMessage); + p->infoMessage = NULL; + break; + } + case CSR_WIFI_SME_CORE_DUMP_IND: + { + CsrWifiSmeCoreDumpInd *p = (CsrWifiSmeCoreDumpInd *)message; + CsrPmemFree(p->data); + p->data = NULL; + break; + } + + default: + break; + } +} + + diff --git a/drivers/staging/csr/csr_wifi_sme_lib.h b/drivers/staging/csr/csr_wifi_sme_lib.h new file mode 100644 index 000000000000..16053fb6ed43 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_lib.h @@ -0,0 +1,4282 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_LIB_H__ +#define CSR_WIFI_SME_LIB_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_sched.h" +#include "csr_util.h" +#include "csr_msg_transport.h" + +#include "csr_wifi_lib.h" + +#include "csr_wifi_sme_prim.h" +#include "csr_wifi_sme_task.h" + + +#ifndef CSR_WIFI_SME_LIB_DESTINATION_QUEUE +# ifdef CSR_WIFI_NME_ENABLE +# include "csr_wifi_nme_task.h" +# define CSR_WIFI_SME_LIB_DESTINATION_QUEUE CSR_WIFI_NME_IFACEQUEUE +# else +# define CSR_WIFI_SME_LIB_DESTINATION_QUEUE CSR_WIFI_SME_IFACEQUEUE +# endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------* + * CsrWifiSmeFreeUpstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_SME upstream message. Does not + * free the message itself, and can only be used for upstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_SME upstream message + *----------------------------------------------------------------------------*/ +void CsrWifiSmeFreeUpstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * CsrWifiSmeFreeDownstreamMessageContents + * + * DESCRIPTION + * Free the allocated memory in a CSR_WIFI_SME downstream message. Does not + * free the message itself, and can only be used for downstream messages. + * + * PARAMETERS + * Deallocates the resources in a CSR_WIFI_SME downstream message + *----------------------------------------------------------------------------*/ +void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message); + +/*----------------------------------------------------------------------------* + * Enum to string functions + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiSme80211NetworkTypeToString(CsrWifiSme80211NetworkType value); +const CsrCharString* CsrWifiSme80211PrivacyModeToString(CsrWifiSme80211PrivacyMode value); +const CsrCharString* CsrWifiSme80211dTrustLevelToString(CsrWifiSme80211dTrustLevel value); +const CsrCharString* CsrWifiSmeAmpStatusToString(CsrWifiSmeAmpStatus value); +const CsrCharString* CsrWifiSmeAuthModeToString(CsrWifiSmeAuthMode value); +const CsrCharString* CsrWifiSmeBasicUsabilityToString(CsrWifiSmeBasicUsability value); +const CsrCharString* CsrWifiSmeBssTypeToString(CsrWifiSmeBssType value); +const CsrCharString* CsrWifiSmeCoexSchemeToString(CsrWifiSmeCoexScheme value); +const CsrCharString* CsrWifiSmeControlIndicationToString(CsrWifiSmeControlIndication value); +const CsrCharString* CsrWifiSmeCtsProtectionTypeToString(CsrWifiSmeCtsProtectionType value); +const CsrCharString* CsrWifiSmeD3AutoScanModeToString(CsrWifiSmeD3AutoScanMode value); +const CsrCharString* CsrWifiSmeEncryptionToString(CsrWifiSmeEncryption value); +const CsrCharString* CsrWifiSmeFirmwareDriverInterfaceToString(CsrWifiSmeFirmwareDriverInterface value); +const CsrCharString* CsrWifiSmeHostPowerModeToString(CsrWifiSmeHostPowerMode value); +const CsrCharString* CsrWifiSmeIEEE80211ReasonToString(CsrWifiSmeIEEE80211Reason value); +const CsrCharString* CsrWifiSmeIEEE80211ResultToString(CsrWifiSmeIEEE80211Result value); +const CsrCharString* CsrWifiSmeIndicationsToString(CsrWifiSmeIndications value); +const CsrCharString* CsrWifiSmeKeyTypeToString(CsrWifiSmeKeyType value); +const CsrCharString* CsrWifiSmeListActionToString(CsrWifiSmeListAction value); +const CsrCharString* CsrWifiSmeMediaStatusToString(CsrWifiSmeMediaStatus value); +const CsrCharString* CsrWifiSmeP2pCapabilityToString(CsrWifiSmeP2pCapability value); +const CsrCharString* CsrWifiSmeP2pGroupCapabilityToString(CsrWifiSmeP2pGroupCapability value); +const CsrCharString* CsrWifiSmeP2pNoaConfigMethodToString(CsrWifiSmeP2pNoaConfigMethod value); +const CsrCharString* CsrWifiSmeP2pRoleToString(CsrWifiSmeP2pRole value); +const CsrCharString* CsrWifiSmeP2pStatusToString(CsrWifiSmeP2pStatus value); +const CsrCharString* CsrWifiSmePacketFilterModeToString(CsrWifiSmePacketFilterMode value); +const CsrCharString* CsrWifiSmePowerSaveLevelToString(CsrWifiSmePowerSaveLevel value); +const CsrCharString* CsrWifiSmePreambleTypeToString(CsrWifiSmePreambleType value); +const CsrCharString* CsrWifiSmeRadioIFToString(CsrWifiSmeRadioIF value); +const CsrCharString* CsrWifiSmeRegulatoryDomainToString(CsrWifiSmeRegulatoryDomain value); +const CsrCharString* CsrWifiSmeRoamReasonToString(CsrWifiSmeRoamReason value); +const CsrCharString* CsrWifiSmeScanTypeToString(CsrWifiSmeScanType value); +const CsrCharString* CsrWifiSmeTrafficTypeToString(CsrWifiSmeTrafficType value); +const CsrCharString* CsrWifiSmeTspecCtrlToString(CsrWifiSmeTspecCtrl value); +const CsrCharString* CsrWifiSmeTspecResultCodeToString(CsrWifiSmeTspecResultCode value); +const CsrCharString* CsrWifiSmeWepAuthModeToString(CsrWifiSmeWepAuthMode value); +const CsrCharString* CsrWifiSmeWepCredentialTypeToString(CsrWifiSmeWepCredentialType value); +const CsrCharString* CsrWifiSmeWmmModeToString(CsrWifiSmeWmmMode value); +const CsrCharString* CsrWifiSmeWmmQosInfoToString(CsrWifiSmeWmmQosInfo value); +const CsrCharString* CsrWifiSmeWpsConfigTypeToString(CsrWifiSmeWpsConfigType value); +const CsrCharString* CsrWifiSmeWpsDeviceCategoryToString(CsrWifiSmeWpsDeviceCategory value); +const CsrCharString* CsrWifiSmeWpsDeviceSubCategoryToString(CsrWifiSmeWpsDeviceSubCategory value); +const CsrCharString* CsrWifiSmeWpsDpidToString(CsrWifiSmeWpsDpid value); +const CsrCharString* CsrWifiSmeWpsRegistrationToString(CsrWifiSmeWpsRegistration value); + + +/*----------------------------------------------------------------------------* + * CsrPrim Type toString function. + * Converts a message type to the String name of the Message + *----------------------------------------------------------------------------*/ +const CsrCharString* CsrWifiSmePrimTypeToString(CsrPrim msgType); + +/*----------------------------------------------------------------------------* + * Lookup arrays for PrimType name Strings + *----------------------------------------------------------------------------*/ +extern const CsrCharString *CsrWifiSmeUpstreamPrimNames[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT]; +extern const CsrCharString *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT]; + +/******************************************************************************* + + NAME + CsrWifiSmeActivateReqSend + + DESCRIPTION + The WMA sends this primitive to activate the SME. + The WMA must activate the SME before it can send any other primitive. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeActivateReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeActivateReq *) CsrPmemAlloc(sizeof(CsrWifiSmeActivateReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ACTIVATE_REQ, dst__, src__); + +#define CsrWifiSmeActivateReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeActivateReq *msg__; \ + CsrWifiSmeActivateReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeActivateReqSend(src__) \ + CsrWifiSmeActivateReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeActivateCfmSend + + DESCRIPTION + The SME sends this primitive when the activation is complete. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeActivateCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeActivateCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeActivateCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ACTIVATE_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeActivateCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeActivateCfm *msg__; \ + CsrWifiSmeActivateCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeActivateCfmSend(dst__, status__) \ + CsrWifiSmeActivateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the adHocConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeAdhocConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeAdhocConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmeAdhocConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeAdhocConfigGetReq *msg__; \ + CsrWifiSmeAdhocConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAdhocConfigGetReqSend(src__) \ + CsrWifiSmeAdhocConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + adHocConfig - Contains the values used when starting an Ad-hoc (IBSS) + connection. + +*******************************************************************************/ +#define CsrWifiSmeAdhocConfigGetCfmCreate(msg__, dst__, src__, status__, adHocConfig__) \ + msg__ = (CsrWifiSmeAdhocConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->adHocConfig = (adHocConfig__); + +#define CsrWifiSmeAdhocConfigGetCfmSendTo(dst__, src__, status__, adHocConfig__) \ + { \ + CsrWifiSmeAdhocConfigGetCfm *msg__; \ + CsrWifiSmeAdhocConfigGetCfmCreate(msg__, dst__, src__, status__, adHocConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAdhocConfigGetCfmSend(dst__, status__, adHocConfig__) \ + CsrWifiSmeAdhocConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, adHocConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the adHocConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + adHocConfig - Sets the values to use when starting an ad hoc network. + +*******************************************************************************/ +#define CsrWifiSmeAdhocConfigSetReqCreate(msg__, dst__, src__, adHocConfig__) \ + msg__ = (CsrWifiSmeAdhocConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ, dst__, src__); \ + msg__->adHocConfig = (adHocConfig__); + +#define CsrWifiSmeAdhocConfigSetReqSendTo(dst__, src__, adHocConfig__) \ + { \ + CsrWifiSmeAdhocConfigSetReq *msg__; \ + CsrWifiSmeAdhocConfigSetReqCreate(msg__, dst__, src__, adHocConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAdhocConfigSetReqSend(src__, adHocConfig__) \ + CsrWifiSmeAdhocConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, adHocConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeAdhocConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeAdhocConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeAdhocConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeAdhocConfigSetCfm *msg__; \ + CsrWifiSmeAdhocConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAdhocConfigSetCfmSend(dst__, status__) \ + CsrWifiSmeAdhocConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeAmpStatusChangeIndSend + + DESCRIPTION + Indication of change to AMP activity. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface on which the AMP activity changed. + ampStatus - The new status of AMP activity.Range: {AMP_ACTIVE, + AMP_INACTIVE}. + +*******************************************************************************/ +#define CsrWifiSmeAmpStatusChangeIndCreate(msg__, dst__, src__, interfaceTag__, ampStatus__) \ + msg__ = (CsrWifiSmeAmpStatusChangeInd *) CsrPmemAlloc(sizeof(CsrWifiSmeAmpStatusChangeInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_AMP_STATUS_CHANGE_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->ampStatus = (ampStatus__); + +#define CsrWifiSmeAmpStatusChangeIndSendTo(dst__, src__, interfaceTag__, ampStatus__) \ + { \ + CsrWifiSmeAmpStatusChangeInd *msg__; \ + CsrWifiSmeAmpStatusChangeIndCreate(msg__, dst__, src__, interfaceTag__, ampStatus__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAmpStatusChangeIndSend(dst__, interfaceTag__, ampStatus__) \ + CsrWifiSmeAmpStatusChangeIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, ampStatus__) + +/******************************************************************************* + + NAME + CsrWifiSmeAssociationCompleteIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it completes an attempt to associate with an AP. If + the association was successful, status will be set to + CSR_WIFI_SME_STATUS_SUCCESS, otherwise status and deauthReason shall be + set to appropriate error codes. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the association procedure + connectionInfo - This parameter is relevant only if result is + CSR_WIFI_SME_STATUS_SUCCESS: + it points to the connection information for the new network + deauthReason - This parameter is relevant only if result is not + CSR_WIFI_SME_STATUS_SUCCESS: + if the AP deauthorised the station, it gives the reason of + the deauthorization + +*******************************************************************************/ +#define CsrWifiSmeAssociationCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ + msg__ = (CsrWifiSmeAssociationCompleteInd *) CsrPmemAlloc(sizeof(CsrWifiSmeAssociationCompleteInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectionInfo = (connectionInfo__); \ + msg__->deauthReason = (deauthReason__); + +#define CsrWifiSmeAssociationCompleteIndSendTo(dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ + { \ + CsrWifiSmeAssociationCompleteInd *msg__; \ + CsrWifiSmeAssociationCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAssociationCompleteIndSend(dst__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ + CsrWifiSmeAssociationCompleteIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionInfo__, deauthReason__) + +/******************************************************************************* + + NAME + CsrWifiSmeAssociationStartIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it begins an attempt to associate with an AP. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + address - BSSID of the associating network + ssid - Service Set identifier of the associating network + +*******************************************************************************/ +#define CsrWifiSmeAssociationStartIndCreate(msg__, dst__, src__, interfaceTag__, address__, ssid__) \ + msg__ = (CsrWifiSmeAssociationStartInd *) CsrPmemAlloc(sizeof(CsrWifiSmeAssociationStartInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ASSOCIATION_START_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->address = (address__); \ + msg__->ssid = (ssid__); + +#define CsrWifiSmeAssociationStartIndSendTo(dst__, src__, interfaceTag__, address__, ssid__) \ + { \ + CsrWifiSmeAssociationStartInd *msg__; \ + CsrWifiSmeAssociationStartIndCreate(msg__, dst__, src__, interfaceTag__, address__, ssid__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeAssociationStartIndSend(dst__, interfaceTag__, address__, ssid__) \ + CsrWifiSmeAssociationStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, address__, ssid__) + +/******************************************************************************* + + NAME + CsrWifiSmeBlacklistReqSend + + DESCRIPTION + The wireless manager application should call this primitive to notify the + driver of any networks that should not be connected to. The interface + allows the wireless manager application to query, add, remove, and flush + the BSSIDs that the driver may not connect or roam to. + When this primitive adds to the black list the BSSID to which the SME is + currently connected, the SME will try to roam, if applicable, to another + BSSID in the same ESS; if the roaming procedure fails, the SME will + disconnect. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs + the driver to modify or provide the list of blacklisted + networks. + setAddressCount - Number of BSSIDs sent with this primitive + setAddresses - Pointer to the list of BBSIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmeBlacklistReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ + msg__ = (CsrWifiSmeBlacklistReq *) CsrPmemAlloc(sizeof(CsrWifiSmeBlacklistReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_BLACKLIST_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->setAddressCount = (setAddressCount__); \ + msg__->setAddresses = (setAddresses__); + +#define CsrWifiSmeBlacklistReqSendTo(dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ + { \ + CsrWifiSmeBlacklistReq *msg__; \ + CsrWifiSmeBlacklistReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeBlacklistReqSend(src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ + CsrWifiSmeBlacklistReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) + +/******************************************************************************* + + NAME + CsrWifiSmeBlacklistCfmSend + + DESCRIPTION + The SME will call this primitive when the action on the blacklist has + completed. For a GET action, this primitive also reports the list of + BBSIDs in the blacklist. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getAddressCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of BSSIDs sent with this primitive + getAddresses - Pointer to the list of BBSIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmeBlacklistCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ + msg__ = (CsrWifiSmeBlacklistCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeBlacklistCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_BLACKLIST_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->action = (action__); \ + msg__->getAddressCount = (getAddressCount__); \ + msg__->getAddresses = (getAddresses__); + +#define CsrWifiSmeBlacklistCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ + { \ + CsrWifiSmeBlacklistCfm *msg__; \ + CsrWifiSmeBlacklistCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeBlacklistCfmSend(dst__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ + CsrWifiSmeBlacklistCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataGetReqSend + + DESCRIPTION + This primitive retrieves the Wi-Fi radio calibration data. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeCalibrationDataGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeCalibrationDataGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ, dst__, src__); + +#define CsrWifiSmeCalibrationDataGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeCalibrationDataGetReq *msg__; \ + CsrWifiSmeCalibrationDataGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCalibrationDataGetReqSend(src__) \ + CsrWifiSmeCalibrationDataGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + calibrationDataLength - Number of bytes in the buffer pointed by + calibrationData + calibrationData - Pointer to a buffer of length calibrationDataLength + containing the calibration data + +*******************************************************************************/ +#define CsrWifiSmeCalibrationDataGetCfmCreate(msg__, dst__, src__, status__, calibrationDataLength__, calibrationData__) \ + msg__ = (CsrWifiSmeCalibrationDataGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->calibrationDataLength = (calibrationDataLength__); \ + msg__->calibrationData = (calibrationData__); + +#define CsrWifiSmeCalibrationDataGetCfmSendTo(dst__, src__, status__, calibrationDataLength__, calibrationData__) \ + { \ + CsrWifiSmeCalibrationDataGetCfm *msg__; \ + CsrWifiSmeCalibrationDataGetCfmCreate(msg__, dst__, src__, status__, calibrationDataLength__, calibrationData__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCalibrationDataGetCfmSend(dst__, status__, calibrationDataLength__, calibrationData__) \ + CsrWifiSmeCalibrationDataGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, calibrationDataLength__, calibrationData__) + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataSetReqSend + + DESCRIPTION + This primitive sets the Wi-Fi radio calibration data. + The usage of the primitive with proper calibration data will avoid + time-consuming configuration after power-up. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + calibrationDataLength - Number of bytes in the buffer pointed by + calibrationData + calibrationData - Pointer to a buffer of length calibrationDataLength + containing the calibration data + +*******************************************************************************/ +#define CsrWifiSmeCalibrationDataSetReqCreate(msg__, dst__, src__, calibrationDataLength__, calibrationData__) \ + msg__ = (CsrWifiSmeCalibrationDataSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ, dst__, src__); \ + msg__->calibrationDataLength = (calibrationDataLength__); \ + msg__->calibrationData = (calibrationData__); + +#define CsrWifiSmeCalibrationDataSetReqSendTo(dst__, src__, calibrationDataLength__, calibrationData__) \ + { \ + CsrWifiSmeCalibrationDataSetReq *msg__; \ + CsrWifiSmeCalibrationDataSetReqCreate(msg__, dst__, src__, calibrationDataLength__, calibrationData__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCalibrationDataSetReqSend(src__, calibrationDataLength__, calibrationData__) \ + CsrWifiSmeCalibrationDataSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, calibrationDataLength__, calibrationData__) + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeCalibrationDataSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeCalibrationDataSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeCalibrationDataSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeCalibrationDataSetCfm *msg__; \ + CsrWifiSmeCalibrationDataSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCalibrationDataSetCfmSend(dst__, status__) \ + CsrWifiSmeCalibrationDataSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the CcxConfig parameter. + CURRENTLY NOT SUPPORTED. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeCcxConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeCcxConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeCcxConfigGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeCcxConfigGetReq *msg__; \ + CsrWifiSmeCcxConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCcxConfigGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeCcxConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + ccxConfig - Currently not supported + +*******************************************************************************/ +#define CsrWifiSmeCcxConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ccxConfig__) \ + msg__ = (CsrWifiSmeCcxConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->ccxConfig = (ccxConfig__); + +#define CsrWifiSmeCcxConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, ccxConfig__) \ + { \ + CsrWifiSmeCcxConfigGetCfm *msg__; \ + CsrWifiSmeCcxConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ccxConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCcxConfigGetCfmSend(dst__, interfaceTag__, status__, ccxConfig__) \ + CsrWifiSmeCcxConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, ccxConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the CcxConfig parameter. + CURRENTLY NOT SUPPORTED. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + ccxConfig - Currently not supported + +*******************************************************************************/ +#define CsrWifiSmeCcxConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, ccxConfig__) \ + msg__ = (CsrWifiSmeCcxConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->ccxConfig = (ccxConfig__); + +#define CsrWifiSmeCcxConfigSetReqSendTo(dst__, src__, interfaceTag__, ccxConfig__) \ + { \ + CsrWifiSmeCcxConfigSetReq *msg__; \ + CsrWifiSmeCcxConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, ccxConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCcxConfigSetReqSend(src__, interfaceTag__, ccxConfig__) \ + CsrWifiSmeCcxConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, ccxConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeCcxConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeCcxConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeCcxConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeCcxConfigSetCfm *msg__; \ + CsrWifiSmeCcxConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCcxConfigSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeCcxConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsGetReqSend + + DESCRIPTION + This primitive gets the value of the CloakedSsids parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeCloakedSsidsGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeCloakedSsidsGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ, dst__, src__); + +#define CsrWifiSmeCloakedSsidsGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeCloakedSsidsGetReq *msg__; \ + CsrWifiSmeCloakedSsidsGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCloakedSsidsGetReqSend(src__) \ + CsrWifiSmeCloakedSsidsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + cloakedSsids - Reports list of cloaked SSIDs that are explicitly scanned for + by the driver + +*******************************************************************************/ +#define CsrWifiSmeCloakedSsidsGetCfmCreate(msg__, dst__, src__, status__, cloakedSsids__) \ + msg__ = (CsrWifiSmeCloakedSsidsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->cloakedSsids = (cloakedSsids__); + +#define CsrWifiSmeCloakedSsidsGetCfmSendTo(dst__, src__, status__, cloakedSsids__) \ + { \ + CsrWifiSmeCloakedSsidsGetCfm *msg__; \ + CsrWifiSmeCloakedSsidsGetCfmCreate(msg__, dst__, src__, status__, cloakedSsids__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCloakedSsidsGetCfmSend(dst__, status__, cloakedSsids__) \ + CsrWifiSmeCloakedSsidsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, cloakedSsids__) + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsSetReqSend + + DESCRIPTION + This primitive sets the list of cloaked SSIDs for which the WMA possesses + profiles. + When the driver detects a cloaked AP, the SME will explicitly scan for it + using the list of cloaked SSIDs provided it, and, if the scan succeeds, + it will report the AP to the WMA either via CSR_WIFI_SME_SCAN_RESULT_IND + (if registered) or via CSR_WIFI_SCAN_RESULT_GET_CFM. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + cloakedSsids - Sets the list of cloaked SSIDs + +*******************************************************************************/ +#define CsrWifiSmeCloakedSsidsSetReqCreate(msg__, dst__, src__, cloakedSsids__) \ + msg__ = (CsrWifiSmeCloakedSsidsSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ, dst__, src__); \ + msg__->cloakedSsids = (cloakedSsids__); + +#define CsrWifiSmeCloakedSsidsSetReqSendTo(dst__, src__, cloakedSsids__) \ + { \ + CsrWifiSmeCloakedSsidsSetReq *msg__; \ + CsrWifiSmeCloakedSsidsSetReqCreate(msg__, dst__, src__, cloakedSsids__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCloakedSsidsSetReqSend(src__, cloakedSsids__) \ + CsrWifiSmeCloakedSsidsSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, cloakedSsids__) + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeCloakedSsidsSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeCloakedSsidsSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeCloakedSsidsSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeCloakedSsidsSetCfm *msg__; \ + CsrWifiSmeCloakedSsidsSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCloakedSsidsSetCfmSend(dst__, status__) \ + CsrWifiSmeCloakedSsidsSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the CoexConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeCoexConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeCoexConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmeCoexConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeCoexConfigGetReq *msg__; \ + CsrWifiSmeCoexConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexConfigGetReqSend(src__) \ + CsrWifiSmeCoexConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + coexConfig - Reports the parameters used to configure the coexistence + behaviour + +*******************************************************************************/ +#define CsrWifiSmeCoexConfigGetCfmCreate(msg__, dst__, src__, status__, coexConfig__) \ + msg__ = (CsrWifiSmeCoexConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->coexConfig = (coexConfig__); + +#define CsrWifiSmeCoexConfigGetCfmSendTo(dst__, src__, status__, coexConfig__) \ + { \ + CsrWifiSmeCoexConfigGetCfm *msg__; \ + CsrWifiSmeCoexConfigGetCfmCreate(msg__, dst__, src__, status__, coexConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexConfigGetCfmSend(dst__, status__, coexConfig__) \ + CsrWifiSmeCoexConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, coexConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the CoexConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + coexConfig - Configures the coexistence behaviour + +*******************************************************************************/ +#define CsrWifiSmeCoexConfigSetReqCreate(msg__, dst__, src__, coexConfig__) \ + msg__ = (CsrWifiSmeCoexConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_SET_REQ, dst__, src__); \ + msg__->coexConfig = (coexConfig__); + +#define CsrWifiSmeCoexConfigSetReqSendTo(dst__, src__, coexConfig__) \ + { \ + CsrWifiSmeCoexConfigSetReq *msg__; \ + CsrWifiSmeCoexConfigSetReqCreate(msg__, dst__, src__, coexConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexConfigSetReqSend(src__, coexConfig__) \ + CsrWifiSmeCoexConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, coexConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeCoexConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeCoexConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeCoexConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeCoexConfigSetCfm *msg__; \ + CsrWifiSmeCoexConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexConfigSetCfmSend(dst__, status__) \ + CsrWifiSmeCoexConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexInfoGetReqSend + + DESCRIPTION + This primitive gets the value of the CoexInfo parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeCoexInfoGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeCoexInfoGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexInfoGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_INFO_GET_REQ, dst__, src__); + +#define CsrWifiSmeCoexInfoGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeCoexInfoGetReq *msg__; \ + CsrWifiSmeCoexInfoGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexInfoGetReqSend(src__) \ + CsrWifiSmeCoexInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexInfoGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + coexInfo - Reports information and state related to coexistence. + +*******************************************************************************/ +#define CsrWifiSmeCoexInfoGetCfmCreate(msg__, dst__, src__, status__, coexInfo__) \ + msg__ = (CsrWifiSmeCoexInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexInfoGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_INFO_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->coexInfo = (coexInfo__); + +#define CsrWifiSmeCoexInfoGetCfmSendTo(dst__, src__, status__, coexInfo__) \ + { \ + CsrWifiSmeCoexInfoGetCfm *msg__; \ + CsrWifiSmeCoexInfoGetCfmCreate(msg__, dst__, src__, status__, coexInfo__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoexInfoGetCfmSend(dst__, status__, coexInfo__) \ + CsrWifiSmeCoexInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, coexInfo__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectReqSend + + DESCRIPTION + The wireless manager application calls this primitive to start the + process of joining an 802.11 wireless network or to start an ad hoc + network. + The structure pointed by connectionConfig contains parameters describing + the network to join or, in case of an ad hoc network, to host or join. + The SME will select a network, perform the IEEE 802.11 Join, Authenticate + and Associate exchanges. + The SME selects the networks from the current scan list that match both + the SSID and BSSID, however either or both of these may be the wildcard + value. Using this rule, the following operations are possible: + * To connect to a network by name, specify the SSID and set the BSSID to + 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF. If there are two or more networks visible, + the SME will select the one with the strongest signal. + * To connect to a specific network, specify the BSSID. The SSID is + optional, but if given it must match the SSID of the network. An empty + SSID may be specified by setting the SSID length to zero. Please note + that if the BSSID is specified (i.e. not equal to 0xFF 0xFF 0xFF 0xFF + 0xFF 0xFF), the SME will not attempt to roam if signal conditions become + poor, even if there is an alternative AP with an SSID that matches the + current network SSID. + * To connect to any network matching the other parameters (i.e. security, + etc), set the SSID length to zero and set the BSSID to 0xFF 0xFF 0xFF + 0xFF 0xFF 0xFF. In this case, the SME will order all available networks + by their signal strengths and will iterate through this list until it + successfully connects. + NOTE: Specifying the BSSID will restrict the selection to one specific + network. If SSID and BSSID are given, they must both match the network + for it to be selected. To select a network based on the SSID only, the + wireless manager application must set the BSSID to 0xFF 0xFF 0xFF 0xFF + 0xFF 0xFF. + The SME will try to connect to each network that matches the provided + parameters, one by one, until it succeeds or has tried unsuccessfully + with all the matching networks. + If there is no network that matches the parameters and the request allows + to host an ad hoc network, the SME will advertise a new ad hoc network + instead. + If the SME cannot connect, it will notify the failure in the confirm. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + connectionConfig - Describes the candidate network to join or to host. + +*******************************************************************************/ +#define CsrWifiSmeConnectReqCreate(msg__, dst__, src__, interfaceTag__, connectionConfig__) \ + msg__ = (CsrWifiSmeConnectReq *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->connectionConfig = (connectionConfig__); + +#define CsrWifiSmeConnectReqSendTo(dst__, src__, interfaceTag__, connectionConfig__) \ + { \ + CsrWifiSmeConnectReq *msg__; \ + CsrWifiSmeConnectReqCreate(msg__, dst__, src__, interfaceTag__, connectionConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectReqSend(src__, interfaceTag__, connectionConfig__) \ + CsrWifiSmeConnectReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, connectionConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectCfmSend + + DESCRIPTION + The SME calls this primitive when the connection exchange is complete or + all connection attempts fail. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request. + CSR_WIFI_SME_STATUS_NOT_FOUND: all attempts by the SME to + locate the requested AP failed + +*******************************************************************************/ +#define CsrWifiSmeConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeConnectCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECT_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeConnectCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeConnectCfm *msg__; \ + CsrWifiSmeConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeConnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the ConnectionConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeConnectionConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeConnectionConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeConnectionConfigGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeConnectionConfigGetReq *msg__; \ + CsrWifiSmeConnectionConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionConfigGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeConnectionConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionConfig - Parameters used by the SME for selecting a network + +*******************************************************************************/ +#define CsrWifiSmeConnectionConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionConfig__) \ + msg__ = (CsrWifiSmeConnectionConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectionConfig = (connectionConfig__); + +#define CsrWifiSmeConnectionConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionConfig__) \ + { \ + CsrWifiSmeConnectionConfigGetCfm *msg__; \ + CsrWifiSmeConnectionConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionConfigGetCfmSend(dst__, interfaceTag__, status__, connectionConfig__) \ + CsrWifiSmeConnectionConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionInfoGetReqSend + + DESCRIPTION + This primitive gets the value of the ConnectionInfo parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeConnectionInfoGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeConnectionInfoGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionInfoGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_INFO_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeConnectionInfoGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeConnectionInfoGetReq *msg__; \ + CsrWifiSmeConnectionInfoGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionInfoGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeConnectionInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionInfoGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionInfo - Information about the current connection + +*******************************************************************************/ +#define CsrWifiSmeConnectionInfoGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__) \ + msg__ = (CsrWifiSmeConnectionInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionInfoGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_INFO_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectionInfo = (connectionInfo__); + +#define CsrWifiSmeConnectionInfoGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionInfo__) \ + { \ + CsrWifiSmeConnectionInfoGetCfm *msg__; \ + CsrWifiSmeConnectionInfoGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionInfoGetCfmSend(dst__, interfaceTag__, status__, connectionInfo__) \ + CsrWifiSmeConnectionInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionInfo__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionQualityIndSend + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever the value of the current connection quality + parameters change by more than a certain configurable amount. + The wireless manager application may configure the trigger thresholds for + this indication using the field in smeConfig parameter of + CSR_WIFI_SME_SME_CONFIG_SET_REQ. + Connection quality messages can be suppressed by setting both thresholds + to zero. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + linkQuality - Indicates the quality of the link + +*******************************************************************************/ +#define CsrWifiSmeConnectionQualityIndCreate(msg__, dst__, src__, interfaceTag__, linkQuality__) \ + msg__ = (CsrWifiSmeConnectionQualityInd *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionQualityInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_QUALITY_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->linkQuality = (linkQuality__); + +#define CsrWifiSmeConnectionQualityIndSendTo(dst__, src__, interfaceTag__, linkQuality__) \ + { \ + CsrWifiSmeConnectionQualityInd *msg__; \ + CsrWifiSmeConnectionQualityIndCreate(msg__, dst__, src__, interfaceTag__, linkQuality__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionQualityIndSend(dst__, interfaceTag__, linkQuality__) \ + CsrWifiSmeConnectionQualityIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, linkQuality__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionStatsGetReqSend + + DESCRIPTION + This primitive gets the value of the ConnectionStats parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeConnectionStatsGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeConnectionStatsGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionStatsGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_STATS_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeConnectionStatsGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeConnectionStatsGetReq *msg__; \ + CsrWifiSmeConnectionStatsGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionStatsGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeConnectionStatsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionStatsGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionStats - Statistics for current connection. + +*******************************************************************************/ +#define CsrWifiSmeConnectionStatsGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStats__) \ + msg__ = (CsrWifiSmeConnectionStatsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionStatsGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_STATS_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->connectionStats = (connectionStats__); + +#define CsrWifiSmeConnectionStatsGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionStats__) \ + { \ + CsrWifiSmeConnectionStatsGetCfm *msg__; \ + CsrWifiSmeConnectionStatsGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStats__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeConnectionStatsGetCfmSend(dst__, interfaceTag__, status__, connectionStats__) \ + CsrWifiSmeConnectionStatsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionStats__) + +/******************************************************************************* + + NAME + CsrWifiSmeCoreDumpIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive Wi-Fi Chip core dump data. + The core dump data may be fragmented and sent using more than one + indication. + To indicate that all the data has been sent, the last indication contains + a 'length' of 0 and 'data' of NULL. + + PARAMETERS + queue - Destination Task Queue + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes of core + dump data + +*******************************************************************************/ +#define CsrWifiSmeCoreDumpIndCreate(msg__, dst__, src__, dataLength__, data__) \ + msg__ = (CsrWifiSmeCoreDumpInd *) CsrPmemAlloc(sizeof(CsrWifiSmeCoreDumpInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CORE_DUMP_IND, dst__, src__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiSmeCoreDumpIndSendTo(dst__, src__, dataLength__, data__) \ + { \ + CsrWifiSmeCoreDumpInd *msg__; \ + CsrWifiSmeCoreDumpIndCreate(msg__, dst__, src__, dataLength__, data__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeCoreDumpIndSend(dst__, dataLength__, data__) \ + CsrWifiSmeCoreDumpIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, dataLength__, data__) + +/******************************************************************************* + + NAME + CsrWifiSmeDeactivateReqSend + + DESCRIPTION + The WMA sends this primitive to deactivate the SME. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeDeactivateReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeDeactivateReq *) CsrPmemAlloc(sizeof(CsrWifiSmeDeactivateReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DEACTIVATE_REQ, dst__, src__); + +#define CsrWifiSmeDeactivateReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeDeactivateReq *msg__; \ + CsrWifiSmeDeactivateReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeDeactivateReqSend(src__) \ + CsrWifiSmeDeactivateReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeDeactivateCfmSend + + DESCRIPTION + The SME sends this primitive when the deactivation is complete. + The WMA cannot send any more primitives until it actives the SME again + sending another CSR_WIFI_SME_ACTIVATE_REQ. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeDeactivateCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeDeactivateCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeDeactivateCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DEACTIVATE_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeDeactivateCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeDeactivateCfm *msg__; \ + CsrWifiSmeDeactivateCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeDeactivateCfmSend(dst__, status__) \ + CsrWifiSmeDeactivateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeDisconnectReqSend + + DESCRIPTION + The wireless manager application may disconnect from the current network + by calling this primitive + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeDisconnectReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeDisconnectReq *) CsrPmemAlloc(sizeof(CsrWifiSmeDisconnectReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DISCONNECT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeDisconnectReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeDisconnectReq *msg__; \ + CsrWifiSmeDisconnectReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeDisconnectReqSend(src__, interfaceTag__) \ + CsrWifiSmeDisconnectReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeDisconnectCfmSend + + DESCRIPTION + On reception of CSR_WIFI_SME_DISCONNECT_REQ the SME will perform a + disconnect operation, sending a CsrWifiSmeMediaStatusInd with + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED and then call this primitive when + disconnection is complete. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeDisconnectCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeDisconnectCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DISCONNECT_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeDisconnectCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeDisconnectCfm *msg__; \ + CsrWifiSmeDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeDisconnectCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeDisconnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeErrorIndSend + + DESCRIPTION + Important error message indicating a error of some importance + + PARAMETERS + queue - Destination Task Queue + errorMessage - Contains the error message. + +*******************************************************************************/ +#define CsrWifiSmeErrorIndCreate(msg__, dst__, src__, errorMessage__) \ + msg__ = (CsrWifiSmeErrorInd *) CsrPmemAlloc(sizeof(CsrWifiSmeErrorInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ERROR_IND, dst__, src__); \ + msg__->errorMessage = (errorMessage__); + +#define CsrWifiSmeErrorIndSendTo(dst__, src__, errorMessage__) \ + { \ + CsrWifiSmeErrorInd *msg__; \ + CsrWifiSmeErrorIndCreate(msg__, dst__, src__, errorMessage__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeErrorIndSend(dst__, errorMessage__) \ + CsrWifiSmeErrorIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, errorMessage__) + +/******************************************************************************* + + NAME + CsrWifiSmeEventMaskSetReqSend + + DESCRIPTION + The wireless manager application may register with the SME to receive + notification of interesting events. Indications will be sent only if the + wireless manager explicitly registers to be notified of that event. + indMask is a bit mask of values defined in CsrWifiSmeIndicationsMask. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + indMask - Set mask with values from CsrWifiSmeIndications + +*******************************************************************************/ +#define CsrWifiSmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__) \ + msg__ = (CsrWifiSmeEventMaskSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeEventMaskSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_EVENT_MASK_SET_REQ, dst__, src__); \ + msg__->indMask = (indMask__); + +#define CsrWifiSmeEventMaskSetReqSendTo(dst__, src__, indMask__) \ + { \ + CsrWifiSmeEventMaskSetReq *msg__; \ + CsrWifiSmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeEventMaskSetReqSend(src__, indMask__) \ + CsrWifiSmeEventMaskSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, indMask__) + +/******************************************************************************* + + NAME + CsrWifiSmeEventMaskSetCfmSend + + DESCRIPTION + The SME calls the primitive to report the result of the request + primitive. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeEventMaskSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeEventMaskSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeEventMaskSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_EVENT_MASK_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeEventMaskSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeEventMaskSetCfm *msg__; \ + CsrWifiSmeEventMaskSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeEventMaskSetCfmSend(dst__, status__) \ + CsrWifiSmeEventMaskSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the hostConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeHostConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeHostConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeHostConfigGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeHostConfigGetReq *msg__; \ + CsrWifiSmeHostConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeHostConfigGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeHostConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + hostConfig - Current host power state. + +*******************************************************************************/ +#define CsrWifiSmeHostConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, hostConfig__) \ + msg__ = (CsrWifiSmeHostConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->hostConfig = (hostConfig__); + +#define CsrWifiSmeHostConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, hostConfig__) \ + { \ + CsrWifiSmeHostConfigGetCfm *msg__; \ + CsrWifiSmeHostConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, hostConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeHostConfigGetCfmSend(dst__, interfaceTag__, status__, hostConfig__) \ + CsrWifiSmeHostConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, hostConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the hostConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + hostConfig - Communicates a change of host power state (for example, on + mains power, on battery power etc) and of the periodicity of + traffic data + +*******************************************************************************/ +#define CsrWifiSmeHostConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, hostConfig__) \ + msg__ = (CsrWifiSmeHostConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->hostConfig = (hostConfig__); + +#define CsrWifiSmeHostConfigSetReqSendTo(dst__, src__, interfaceTag__, hostConfig__) \ + { \ + CsrWifiSmeHostConfigSetReq *msg__; \ + CsrWifiSmeHostConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, hostConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeHostConfigSetReqSend(src__, interfaceTag__, hostConfig__) \ + CsrWifiSmeHostConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, hostConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeHostConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeHostConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeHostConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeHostConfigSetCfm *msg__; \ + CsrWifiSmeHostConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeHostConfigSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeHostConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeIbssStationIndSend + + DESCRIPTION + The SME will send this primitive to indicate that a station has joined or + left the ad-hoc network. + + PARAMETERS + queue - Destination Task Queue + address - MAC address of the station that has joined or left + isconnected - TRUE if the station joined, FALSE if the station left + +*******************************************************************************/ +#define CsrWifiSmeIbssStationIndCreate(msg__, dst__, src__, address__, isconnected__) \ + msg__ = (CsrWifiSmeIbssStationInd *) CsrPmemAlloc(sizeof(CsrWifiSmeIbssStationInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_IBSS_STATION_IND, dst__, src__); \ + msg__->address = (address__); \ + msg__->isconnected = (isconnected__); + +#define CsrWifiSmeIbssStationIndSendTo(dst__, src__, address__, isconnected__) \ + { \ + CsrWifiSmeIbssStationInd *msg__; \ + CsrWifiSmeIbssStationIndCreate(msg__, dst__, src__, address__, isconnected__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeIbssStationIndSend(dst__, address__, isconnected__) \ + CsrWifiSmeIbssStationIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, address__, isconnected__) + +/******************************************************************************* + + NAME + CsrWifiSmeInfoIndSend + + DESCRIPTION + Message indicating a some info about current activity. Mostly of interest + in testing but may be useful in the field. + + PARAMETERS + queue - Destination Task Queue + infoMessage - Contains the message. + +*******************************************************************************/ +#define CsrWifiSmeInfoIndCreate(msg__, dst__, src__, infoMessage__) \ + msg__ = (CsrWifiSmeInfoInd *) CsrPmemAlloc(sizeof(CsrWifiSmeInfoInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INFO_IND, dst__, src__); \ + msg__->infoMessage = (infoMessage__); + +#define CsrWifiSmeInfoIndSendTo(dst__, src__, infoMessage__) \ + { \ + CsrWifiSmeInfoInd *msg__; \ + CsrWifiSmeInfoIndCreate(msg__, dst__, src__, infoMessage__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeInfoIndSend(dst__, infoMessage__) \ + CsrWifiSmeInfoIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, infoMessage__) + +/******************************************************************************* + + NAME + CsrWifiSmeInterfaceCapabilityGetReqSend + + DESCRIPTION + The Wireless Manager calls this primitive to ask the SME for the + capabilities of the supported interfaces + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeInterfaceCapabilityGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeInterfaceCapabilityGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeInterfaceCapabilityGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, dst__, src__); + +#define CsrWifiSmeInterfaceCapabilityGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeInterfaceCapabilityGetReq *msg__; \ + CsrWifiSmeInterfaceCapabilityGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeInterfaceCapabilityGetReqSend(src__) \ + CsrWifiSmeInterfaceCapabilityGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeInterfaceCapabilityGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Result of the request + numInterfaces - Number of the interfaces supported + capBitmap - Points to the list of capabilities bitmaps provided for each + interface. + The bits represent the following capabilities: + -bits 7 to 4-Reserved + -bit 3-AMP + -bit 2-P2P + -bit 1-AP + -bit 0-STA + +*******************************************************************************/ +#define CsrWifiSmeInterfaceCapabilityGetCfmCreate(msg__, dst__, src__, status__, numInterfaces__, capBitmap__) \ + msg__ = (CsrWifiSmeInterfaceCapabilityGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeInterfaceCapabilityGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->numInterfaces = (numInterfaces__); \ + CsrMemCpy(msg__->capBitmap, (capBitmap__), sizeof(CsrUint8) * 2); + +#define CsrWifiSmeInterfaceCapabilityGetCfmSendTo(dst__, src__, status__, numInterfaces__, capBitmap__) \ + { \ + CsrWifiSmeInterfaceCapabilityGetCfm *msg__; \ + CsrWifiSmeInterfaceCapabilityGetCfmCreate(msg__, dst__, src__, status__, numInterfaces__, capBitmap__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeInterfaceCapabilityGetCfmSend(dst__, status__, numInterfaces__, capBitmap__) \ + CsrWifiSmeInterfaceCapabilityGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, numInterfaces__, capBitmap__) + +/******************************************************************************* + + NAME + CsrWifiSmeKeyReqSend + + DESCRIPTION + The wireless manager application calls this primitive to add or remove + keys that the chip should use for encryption of data. + The interface allows the wireless manager application to add and remove + keys according to the specified action. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs the + driver to modify or provide the list of keys. + CSR_WIFI_SME_LIST_ACTION_GET is not supported here. + key - Key to be added or removed + +*******************************************************************************/ +#define CsrWifiSmeKeyReqCreate(msg__, dst__, src__, interfaceTag__, action__, key__) \ + msg__ = (CsrWifiSmeKeyReq *) CsrPmemAlloc(sizeof(CsrWifiSmeKeyReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_KEY_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->key = (key__); + +#define CsrWifiSmeKeyReqSendTo(dst__, src__, interfaceTag__, action__, key__) \ + { \ + CsrWifiSmeKeyReq *msg__; \ + CsrWifiSmeKeyReqCreate(msg__, dst__, src__, interfaceTag__, action__, key__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeKeyReqSend(src__, interfaceTag__, action__, key__) \ + CsrWifiSmeKeyReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, key__) + +/******************************************************************************* + + NAME + CsrWifiSmeKeyCfmSend + + DESCRIPTION + The SME calls the primitive to report the result of the request + primitive. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + keyType - Type of the key added/deleted + peerMacAddress - Peer MAC Address of the key added/deleted + +*******************************************************************************/ +#define CsrWifiSmeKeyCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ + msg__ = (CsrWifiSmeKeyCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeKeyCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_KEY_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->action = (action__); \ + msg__->keyType = (keyType__); \ + msg__->peerMacAddress = (peerMacAddress__); + +#define CsrWifiSmeKeyCfmSendTo(dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ + { \ + CsrWifiSmeKeyCfm *msg__; \ + CsrWifiSmeKeyCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeKeyCfmSend(dst__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ + CsrWifiSmeKeyCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, keyType__, peerMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiSmeLinkQualityGetReqSend + + DESCRIPTION + This primitive gets the value of the LinkQuality parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeLinkQualityGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeLinkQualityGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeLinkQualityGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_LINK_QUALITY_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeLinkQualityGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeLinkQualityGetReq *msg__; \ + CsrWifiSmeLinkQualityGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeLinkQualityGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeLinkQualityGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeLinkQualityGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + linkQuality - Indicates the quality of the link + +*******************************************************************************/ +#define CsrWifiSmeLinkQualityGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, linkQuality__) \ + msg__ = (CsrWifiSmeLinkQualityGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeLinkQualityGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_LINK_QUALITY_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->linkQuality = (linkQuality__); + +#define CsrWifiSmeLinkQualityGetCfmSendTo(dst__, src__, interfaceTag__, status__, linkQuality__) \ + { \ + CsrWifiSmeLinkQualityGetCfm *msg__; \ + CsrWifiSmeLinkQualityGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, linkQuality__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeLinkQualityGetCfmSend(dst__, interfaceTag__, status__, linkQuality__) \ + CsrWifiSmeLinkQualityGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, linkQuality__) + +/******************************************************************************* + + NAME + CsrWifiSmeMediaStatusIndSend + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it when a network connection is established, lost or has moved to + another AP. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + mediaStatus - Indicates the media status + connectionInfo - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_CONNECTED: + it points to the connection information for the new network + disassocReason - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: + if a disassociation has occurred it gives the reason of the + disassociation + deauthReason - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: + if a deauthentication has occurred it gives the reason of + the deauthentication + +*******************************************************************************/ +#define CsrWifiSmeMediaStatusIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ + msg__ = (CsrWifiSmeMediaStatusInd *) CsrPmemAlloc(sizeof(CsrWifiSmeMediaStatusInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MEDIA_STATUS_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->mediaStatus = (mediaStatus__); \ + msg__->connectionInfo = (connectionInfo__); \ + msg__->disassocReason = (disassocReason__); \ + msg__->deauthReason = (deauthReason__); + +#define CsrWifiSmeMediaStatusIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ + { \ + CsrWifiSmeMediaStatusInd *msg__; \ + CsrWifiSmeMediaStatusIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMediaStatusIndSend(dst__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ + CsrWifiSmeMediaStatusIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the MibConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeMibConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeMibConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmeMibConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeMibConfigGetReq *msg__; \ + CsrWifiSmeMibConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibConfigGetReqSend(src__) \ + CsrWifiSmeMibConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + mibConfig - Reports various IEEE 802.11 attributes as currently configured + +*******************************************************************************/ +#define CsrWifiSmeMibConfigGetCfmCreate(msg__, dst__, src__, status__, mibConfig__) \ + msg__ = (CsrWifiSmeMibConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->mibConfig = (mibConfig__); + +#define CsrWifiSmeMibConfigGetCfmSendTo(dst__, src__, status__, mibConfig__) \ + { \ + CsrWifiSmeMibConfigGetCfm *msg__; \ + CsrWifiSmeMibConfigGetCfmCreate(msg__, dst__, src__, status__, mibConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibConfigGetCfmSend(dst__, status__, mibConfig__) \ + CsrWifiSmeMibConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the MibConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + mibConfig - Conveys the desired value of various IEEE 802.11 attributes as + currently configured + +*******************************************************************************/ +#define CsrWifiSmeMibConfigSetReqCreate(msg__, dst__, src__, mibConfig__) \ + msg__ = (CsrWifiSmeMibConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_SET_REQ, dst__, src__); \ + msg__->mibConfig = (mibConfig__); + +#define CsrWifiSmeMibConfigSetReqSendTo(dst__, src__, mibConfig__) \ + { \ + CsrWifiSmeMibConfigSetReq *msg__; \ + CsrWifiSmeMibConfigSetReqCreate(msg__, dst__, src__, mibConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibConfigSetReqSend(src__, mibConfig__) \ + CsrWifiSmeMibConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeMibConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeMibConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeMibConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeMibConfigSetCfm *msg__; \ + CsrWifiSmeMibConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibConfigSetCfmSend(dst__, status__) \ + CsrWifiSmeMibConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetCfmSend + + DESCRIPTION + The SME calls this primitive to return the requested MIB variable values. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names and values of the MIB variables requested + +*******************************************************************************/ +#define CsrWifiSmeMibGetCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ + msg__ = (CsrWifiSmeMibGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->mibAttributeLength = (mibAttributeLength__); \ + msg__->mibAttribute = (mibAttribute__); + +#define CsrWifiSmeMibGetCfmSendTo(dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ + { \ + CsrWifiSmeMibGetCfm *msg__; \ + CsrWifiSmeMibGetCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibGetCfmSend(dst__, status__, mibAttributeLength__, mibAttribute__) \ + CsrWifiSmeMibGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibAttributeLength__, mibAttribute__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetNextReqSend + + DESCRIPTION + To read a sequence of MIB parameters, for example a table, call this + primitive to find the name of the next MIB variable + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to a VarBind or VarBindList containing the + name(s) of the MIB variable(s) to search from. + +*******************************************************************************/ +#define CsrWifiSmeMibGetNextReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ + msg__ = (CsrWifiSmeMibGetNextReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetNextReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_NEXT_REQ, dst__, src__); \ + msg__->mibAttributeLength = (mibAttributeLength__); \ + msg__->mibAttribute = (mibAttribute__); + +#define CsrWifiSmeMibGetNextReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ + { \ + CsrWifiSmeMibGetNextReq *msg__; \ + CsrWifiSmeMibGetNextReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibGetNextReqSend(src__, mibAttributeLength__, mibAttribute__) \ + CsrWifiSmeMibGetNextReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetNextCfmSend + + DESCRIPTION + The SME calls this primitive to return the requested MIB name(s). + The wireless manager application can then read the value of the MIB + variable using CSR_WIFI_SME_MIB_GET_REQ, using the names provided. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to a VarBind or VarBindList containing the + name(s) of the MIB variable(s) lexicographically + following the name(s) given in the request + +*******************************************************************************/ +#define CsrWifiSmeMibGetNextCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ + msg__ = (CsrWifiSmeMibGetNextCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetNextCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_NEXT_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->mibAttributeLength = (mibAttributeLength__); \ + msg__->mibAttribute = (mibAttribute__); + +#define CsrWifiSmeMibGetNextCfmSendTo(dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ + { \ + CsrWifiSmeMibGetNextCfm *msg__; \ + CsrWifiSmeMibGetNextCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibGetNextCfmSend(dst__, status__, mibAttributeLength__, mibAttribute__) \ + CsrWifiSmeMibGetNextCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibAttributeLength__, mibAttribute__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetReqSend + + DESCRIPTION + The wireless manager application calls this primitive to retrieve one or + more MIB variables. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names of the MIB variables to be retrieved + +*******************************************************************************/ +#define CsrWifiSmeMibGetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ + msg__ = (CsrWifiSmeMibGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_REQ, dst__, src__); \ + msg__->mibAttributeLength = (mibAttributeLength__); \ + msg__->mibAttribute = (mibAttribute__); + +#define CsrWifiSmeMibGetReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ + { \ + CsrWifiSmeMibGetReq *msg__; \ + CsrWifiSmeMibGetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibGetReqSend(src__, mibAttributeLength__, mibAttribute__) \ + CsrWifiSmeMibGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibSetReqSend + + DESCRIPTION + The SME provides raw access to the MIB on the chip, which may be used by + some configuration or diagnostic utilities, but is not normally needed by + the wireless manager application. + The MIB access functions use BER encoded names (OID) of the MIB + parameters and BER encoded values, as described in the chip Host + Interface Protocol Specification. + The MIB parameters are described in 'Wi-Fi 5.0.0 Management Information + Base Reference Guide'. + The wireless manager application calls this primitive to set one or more + MIB variables + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names and values of the MIB variables to set + +*******************************************************************************/ +#define CsrWifiSmeMibSetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ + msg__ = (CsrWifiSmeMibSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_SET_REQ, dst__, src__); \ + msg__->mibAttributeLength = (mibAttributeLength__); \ + msg__->mibAttribute = (mibAttribute__); + +#define CsrWifiSmeMibSetReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ + { \ + CsrWifiSmeMibSetReq *msg__; \ + CsrWifiSmeMibSetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibSetReqSend(src__, mibAttributeLength__, mibAttribute__) \ + CsrWifiSmeMibSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) + +/******************************************************************************* + + NAME + CsrWifiSmeMibSetCfmSend + + DESCRIPTION + The SME calls the primitive to report the result of the set primitive. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeMibSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeMibSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeMibSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeMibSetCfm *msg__; \ + CsrWifiSmeMibSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMibSetCfmSend(dst__, status__) \ + CsrWifiSmeMibSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeMicFailureIndSend + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever the chip firmware reports a MIC failure. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + secondFailure - TRUE if this indication is for a second failure in 60 + seconds + count - The number of MIC failure events since the connection was + established + address - MAC address of the transmitter that caused the MIC failure + keyType - Type of key for which the failure occurred + +*******************************************************************************/ +#define CsrWifiSmeMicFailureIndCreate(msg__, dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ + msg__ = (CsrWifiSmeMicFailureInd *) CsrPmemAlloc(sizeof(CsrWifiSmeMicFailureInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIC_FAILURE_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->secondFailure = (secondFailure__); \ + msg__->count = (count__); \ + msg__->address = (address__); \ + msg__->keyType = (keyType__); + +#define CsrWifiSmeMicFailureIndSendTo(dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ + { \ + CsrWifiSmeMicFailureInd *msg__; \ + CsrWifiSmeMicFailureIndCreate(msg__, dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMicFailureIndSend(dst__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ + CsrWifiSmeMicFailureIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, secondFailure__, count__, address__, keyType__) + +/******************************************************************************* + + NAME + CsrWifiSmeMulticastAddressReqSend + + DESCRIPTION + The wireless manager application calls this primitive to specify the + multicast addresses which the chip should recognise. The interface allows + the wireless manager application to query, add, remove and flush the + multicast addresses for the network interface according to the specified + action. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter + instructs the driver to modify or provide the list of + MAC addresses. + setAddressesCount - Number of MAC addresses sent with the primitive + setAddresses - Pointer to the list of MAC Addresses sent with the + primitive, set to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmeMulticastAddressReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + msg__ = (CsrWifiSmeMulticastAddressReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMulticastAddressReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MULTICAST_ADDRESS_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->setAddressesCount = (setAddressesCount__); \ + msg__->setAddresses = (setAddresses__); + +#define CsrWifiSmeMulticastAddressReqSendTo(dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + { \ + CsrWifiSmeMulticastAddressReq *msg__; \ + CsrWifiSmeMulticastAddressReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMulticastAddressReqSend(src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ + CsrWifiSmeMulticastAddressReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) + +/******************************************************************************* + + NAME + CsrWifiSmeMulticastAddressCfmSend + + DESCRIPTION + The SME will call this primitive when the operation is complete. For a + GET action, this primitive reports the current list of MAC addresses. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getAddressesCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of MAC addresses sent with the primitive + getAddresses - Pointer to the list of MAC Addresses sent with the + primitive, set to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmeMulticastAddressCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ + msg__ = (CsrWifiSmeMulticastAddressCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMulticastAddressCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MULTICAST_ADDRESS_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->action = (action__); \ + msg__->getAddressesCount = (getAddressesCount__); \ + msg__->getAddresses = (getAddresses__); + +#define CsrWifiSmeMulticastAddressCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ + { \ + CsrWifiSmeMulticastAddressCfm *msg__; \ + CsrWifiSmeMulticastAddressCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeMulticastAddressCfmSend(dst__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ + CsrWifiSmeMulticastAddressCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) + +/******************************************************************************* + + NAME + CsrWifiSmePacketFilterSetReqSend + + DESCRIPTION + The wireless manager application should call this primitive to enable or + disable filtering of broadcast packets: uninteresting broadcast packets + will be dropped by the Wi-Fi chip, instead of passing them up to the + host. + This has the advantage of saving power in the host application processor + as it removes the need to process unwanted packets. + All broadcast packets are filtered according to the filter and the filter + mode provided, except ARP packets, which are filtered using + arpFilterAddress. + Filters are not cumulative: only the parameters specified in the most + recent successful request are significant. + For more information, see 'UniFi Firmware API Specification'. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + filterLength - Length of the filter in bytes. + filterLength=0 disables the filter previously set + filter - Points to the first byte of the filter provided, if any. + This shall include zero or more instance of the + information elements of one of these types + * Traffic Classification (TCLAS) elements + * WMM-SA TCLAS elements + mode - Specifies whether the filter selects or excludes packets + matching the filter + arpFilterAddress - IPv4 address to be used for filtering the ARP packets. + * If the specified address is the IPv4 broadcast address + (255.255.255.255), all ARP packets are reported to the + host, + * If the specified address is NOT the IPv4 broadcast + address, only ARP packets with the specified address in + the Source or Target Protocol Address fields are reported + to the host + +*******************************************************************************/ +#define CsrWifiSmePacketFilterSetReqCreate(msg__, dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ + msg__ = (CsrWifiSmePacketFilterSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePacketFilterSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PACKET_FILTER_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->filterLength = (filterLength__); \ + msg__->filter = (filter__); \ + msg__->mode = (mode__); \ + msg__->arpFilterAddress = (arpFilterAddress__); + +#define CsrWifiSmePacketFilterSetReqSendTo(dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ + { \ + CsrWifiSmePacketFilterSetReq *msg__; \ + CsrWifiSmePacketFilterSetReqCreate(msg__, dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePacketFilterSetReqSend(src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ + CsrWifiSmePacketFilterSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) + +/******************************************************************************* + + NAME + CsrWifiSmePacketFilterSetCfmSend + + DESCRIPTION + The SME calls the primitive to report the result of the set primitive. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmePacketFilterSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmePacketFilterSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePacketFilterSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PACKET_FILTER_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmePacketFilterSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmePacketFilterSetCfm *msg__; \ + CsrWifiSmePacketFilterSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePacketFilterSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmePacketFilterSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmePermanentMacAddressGetReqSend + + DESCRIPTION + This primitive retrieves the MAC address stored in EEPROM + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmePermanentMacAddressGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmePermanentMacAddressGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePermanentMacAddressGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ, dst__, src__); + +#define CsrWifiSmePermanentMacAddressGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmePermanentMacAddressGetReq *msg__; \ + CsrWifiSmePermanentMacAddressGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePermanentMacAddressGetReqSend(src__) \ + CsrWifiSmePermanentMacAddressGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmePermanentMacAddressGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + permanentMacAddress - MAC address stored in the EEPROM + +*******************************************************************************/ +#define CsrWifiSmePermanentMacAddressGetCfmCreate(msg__, dst__, src__, status__, permanentMacAddress__) \ + msg__ = (CsrWifiSmePermanentMacAddressGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePermanentMacAddressGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->permanentMacAddress = (permanentMacAddress__); + +#define CsrWifiSmePermanentMacAddressGetCfmSendTo(dst__, src__, status__, permanentMacAddress__) \ + { \ + CsrWifiSmePermanentMacAddressGetCfm *msg__; \ + CsrWifiSmePermanentMacAddressGetCfmCreate(msg__, dst__, src__, status__, permanentMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePermanentMacAddressGetCfmSend(dst__, status__, permanentMacAddress__) \ + CsrWifiSmePermanentMacAddressGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, permanentMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiSmePmkidCandidateListIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it when a new network supporting preauthentication and/or PMK + caching is seen. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an + interface + pmkidCandidatesCount - Number of PMKID candidates provided + pmkidCandidates - Points to the first PMKID candidate + +*******************************************************************************/ +#define CsrWifiSmePmkidCandidateListIndCreate(msg__, dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ + msg__ = (CsrWifiSmePmkidCandidateListInd *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidCandidateListInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->pmkidCandidatesCount = (pmkidCandidatesCount__); \ + msg__->pmkidCandidates = (pmkidCandidates__); + +#define CsrWifiSmePmkidCandidateListIndSendTo(dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ + { \ + CsrWifiSmePmkidCandidateListInd *msg__; \ + CsrWifiSmePmkidCandidateListIndCreate(msg__, dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePmkidCandidateListIndSend(dst__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ + CsrWifiSmePmkidCandidateListIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) + +/******************************************************************************* + + NAME + CsrWifiSmePmkidReqSend + + DESCRIPTION + The wireless manager application calls this primitive to request an + operation on the SME PMKID list. + The action argument specifies the operation to perform. + When the connection is complete, the wireless manager application may + then send and receive EAPOL packets to complete WPA or WPA2 + authentication if appropriate. + The wireless manager application can then pass the resulting encryption + keys using this primitive. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs + the driver to modify or provide the list of PMKIDs. + setPmkidsCount - Number of PMKIDs sent with the primitive + setPmkids - Pointer to the list of PMKIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmePmkidReqCreate(msg__, dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ + msg__ = (CsrWifiSmePmkidReq *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->setPmkidsCount = (setPmkidsCount__); \ + msg__->setPmkids = (setPmkids__); + +#define CsrWifiSmePmkidReqSendTo(dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ + { \ + CsrWifiSmePmkidReq *msg__; \ + CsrWifiSmePmkidReqCreate(msg__, dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePmkidReqSend(src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ + CsrWifiSmePmkidReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) + +/******************************************************************************* + + NAME + CsrWifiSmePmkidCfmSend + + DESCRIPTION + The SME will call this primitive when the operation is complete. For a + GET action, this primitive reports the current list of PMKIDs + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getPmkidsCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of PMKIDs sent with the primitive + getPmkids - Pointer to the list of PMKIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +#define CsrWifiSmePmkidCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ + msg__ = (CsrWifiSmePmkidCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->action = (action__); \ + msg__->getPmkidsCount = (getPmkidsCount__); \ + msg__->getPmkids = (getPmkids__); + +#define CsrWifiSmePmkidCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ + { \ + CsrWifiSmePmkidCfm *msg__; \ + CsrWifiSmePmkidCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePmkidCfmSend(dst__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ + CsrWifiSmePmkidCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the PowerConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmePowerConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmePowerConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmePowerConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmePowerConfigGetReq *msg__; \ + CsrWifiSmePowerConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePowerConfigGetReqSend(src__) \ + CsrWifiSmePowerConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + powerConfig - Returns the current parameters for the power configuration of + the firmware + +*******************************************************************************/ +#define CsrWifiSmePowerConfigGetCfmCreate(msg__, dst__, src__, status__, powerConfig__) \ + msg__ = (CsrWifiSmePowerConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->powerConfig = (powerConfig__); + +#define CsrWifiSmePowerConfigGetCfmSendTo(dst__, src__, status__, powerConfig__) \ + { \ + CsrWifiSmePowerConfigGetCfm *msg__; \ + CsrWifiSmePowerConfigGetCfmCreate(msg__, dst__, src__, status__, powerConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePowerConfigGetCfmSend(dst__, status__, powerConfig__) \ + CsrWifiSmePowerConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, powerConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the PowerConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + powerConfig - Power saving configuration + +*******************************************************************************/ +#define CsrWifiSmePowerConfigSetReqCreate(msg__, dst__, src__, powerConfig__) \ + msg__ = (CsrWifiSmePowerConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_SET_REQ, dst__, src__); \ + msg__->powerConfig = (powerConfig__); + +#define CsrWifiSmePowerConfigSetReqSendTo(dst__, src__, powerConfig__) \ + { \ + CsrWifiSmePowerConfigSetReq *msg__; \ + CsrWifiSmePowerConfigSetReqCreate(msg__, dst__, src__, powerConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePowerConfigSetReqSend(src__, powerConfig__) \ + CsrWifiSmePowerConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, powerConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmePowerConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmePowerConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmePowerConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmePowerConfigSetCfm *msg__; \ + CsrWifiSmePowerConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmePowerConfigSetCfmSend(dst__, status__) \ + CsrWifiSmePowerConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomainInfoGetReqSend + + DESCRIPTION + This primitive gets the value of the RegulatoryDomainInfo parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeRegulatoryDomainInfoGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeRegulatoryDomainInfoGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ, dst__, src__); + +#define CsrWifiSmeRegulatoryDomainInfoGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeRegulatoryDomainInfoGetReq *msg__; \ + CsrWifiSmeRegulatoryDomainInfoGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRegulatoryDomainInfoGetReqSend(src__) \ + CsrWifiSmeRegulatoryDomainInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomainInfoGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + regDomInfo - Reports information and state related to regulatory domain + operation. + +*******************************************************************************/ +#define CsrWifiSmeRegulatoryDomainInfoGetCfmCreate(msg__, dst__, src__, status__, regDomInfo__) \ + msg__ = (CsrWifiSmeRegulatoryDomainInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->regDomInfo = (regDomInfo__); + +#define CsrWifiSmeRegulatoryDomainInfoGetCfmSendTo(dst__, src__, status__, regDomInfo__) \ + { \ + CsrWifiSmeRegulatoryDomainInfoGetCfm *msg__; \ + CsrWifiSmeRegulatoryDomainInfoGetCfmCreate(msg__, dst__, src__, status__, regDomInfo__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRegulatoryDomainInfoGetCfmSend(dst__, status__, regDomInfo__) \ + CsrWifiSmeRegulatoryDomainInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, regDomInfo__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamCompleteIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it completes an attempt to roam to an AP. If the roam + attempt was successful, status will be set to CSR_WIFI_SME_SUCCESS, + otherwise it shall be set to the appropriate error code. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the roaming procedure + +*******************************************************************************/ +#define CsrWifiSmeRoamCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeRoamCompleteInd *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamCompleteInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAM_COMPLETE_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeRoamCompleteIndSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeRoamCompleteInd *msg__; \ + CsrWifiSmeRoamCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamCompleteIndSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeRoamCompleteIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamStartIndSend + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it begins an attempt to roam to an AP. + If the wireless manager application connect request specified the SSID + and the BSSID was set to the broadcast address (0xFF 0xFF 0xFF 0xFF 0xFF + 0xFF), the SME monitors the signal quality and maintains a list of + candidates to roam to. When the signal quality of the current connection + falls below a threshold, and there is a candidate with better quality, + the SME will attempt to the candidate AP. + If the roaming procedure succeeds, the SME will also issue a Media + Connect indication to inform the wireless manager application of the + change. + NOTE: to prevent the SME from initiating roaming the WMA must specify the + BSSID in the connection request; this forces the SME to connect only to + that AP. + The wireless manager application can obtain statistics for roaming + purposes using CSR_WIFI_SME_CONNECTION_QUALITY_IND and + CSR_WIFI_SME_CONNECTION_STATS_GET_REQ. + When the wireless manager application wishes to roam to another AP, it + must issue a connection request specifying the BSSID of the desired AP. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + roamReason - Indicates the reason for starting the roaming procedure + reason80211 - Indicates the reason for deauthentication or disassociation + +*******************************************************************************/ +#define CsrWifiSmeRoamStartIndCreate(msg__, dst__, src__, interfaceTag__, roamReason__, reason80211__) \ + msg__ = (CsrWifiSmeRoamStartInd *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamStartInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAM_START_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->roamReason = (roamReason__); \ + msg__->reason80211 = (reason80211__); + +#define CsrWifiSmeRoamStartIndSendTo(dst__, src__, interfaceTag__, roamReason__, reason80211__) \ + { \ + CsrWifiSmeRoamStartInd *msg__; \ + CsrWifiSmeRoamStartIndCreate(msg__, dst__, src__, interfaceTag__, roamReason__, reason80211__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamStartIndSend(dst__, interfaceTag__, roamReason__, reason80211__) \ + CsrWifiSmeRoamStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, roamReason__, reason80211__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the RoamingConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeRoamingConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeRoamingConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeRoamingConfigGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeRoamingConfigGetReq *msg__; \ + CsrWifiSmeRoamingConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamingConfigGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeRoamingConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + roamingConfig - Reports the roaming behaviour of the driver and firmware + +*******************************************************************************/ +#define CsrWifiSmeRoamingConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, roamingConfig__) \ + msg__ = (CsrWifiSmeRoamingConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->roamingConfig = (roamingConfig__); + +#define CsrWifiSmeRoamingConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, roamingConfig__) \ + { \ + CsrWifiSmeRoamingConfigGetCfm *msg__; \ + CsrWifiSmeRoamingConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, roamingConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamingConfigGetCfmSend(dst__, interfaceTag__, status__, roamingConfig__) \ + CsrWifiSmeRoamingConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, roamingConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the RoamingConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + roamingConfig - Desired roaming behaviour values + +*******************************************************************************/ +#define CsrWifiSmeRoamingConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, roamingConfig__) \ + msg__ = (CsrWifiSmeRoamingConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->roamingConfig = (roamingConfig__); + +#define CsrWifiSmeRoamingConfigSetReqSendTo(dst__, src__, interfaceTag__, roamingConfig__) \ + { \ + CsrWifiSmeRoamingConfigSetReq *msg__; \ + CsrWifiSmeRoamingConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, roamingConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamingConfigSetReqSend(src__, interfaceTag__, roamingConfig__) \ + CsrWifiSmeRoamingConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, roamingConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigSetCfmSend + + DESCRIPTION + This primitive sets the value of the RoamingConfig parameter. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeRoamingConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeRoamingConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeRoamingConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeRoamingConfigSetCfm *msg__; \ + CsrWifiSmeRoamingConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeRoamingConfigSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeRoamingConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the ScanConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeScanConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeScanConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmeScanConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeScanConfigGetReq *msg__; \ + CsrWifiSmeScanConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanConfigGetReqSend(src__) \ + CsrWifiSmeScanConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + scanConfig - Returns the current parameters for the autonomous scanning + behaviour of the firmware + +*******************************************************************************/ +#define CsrWifiSmeScanConfigGetCfmCreate(msg__, dst__, src__, status__, scanConfig__) \ + msg__ = (CsrWifiSmeScanConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->scanConfig = (scanConfig__); + +#define CsrWifiSmeScanConfigGetCfmSendTo(dst__, src__, status__, scanConfig__) \ + { \ + CsrWifiSmeScanConfigGetCfm *msg__; \ + CsrWifiSmeScanConfigGetCfmCreate(msg__, dst__, src__, status__, scanConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanConfigGetCfmSend(dst__, status__, scanConfig__) \ + CsrWifiSmeScanConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the ScanConfig parameter. + The SME normally configures the firmware to perform autonomous scanning + without involving the host. + The firmware passes beacon / probe response or indicates loss of beacon + on certain changes of state, for example: + * A new AP is seen for the first time + * An AP is no longer visible + * The signal strength of an AP changes by more than a certain amount, as + configured by the thresholds in the scanConfig parameter + In addition to the autonomous scan, the wireless manager application may + request a scan at any time using CSR_WIFI_SME_SCAN_FULL_REQ. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + scanConfig - Reports the configuration for the autonomous scanning behaviour + of the firmware + +*******************************************************************************/ +#define CsrWifiSmeScanConfigSetReqCreate(msg__, dst__, src__, scanConfig__) \ + msg__ = (CsrWifiSmeScanConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_SET_REQ, dst__, src__); \ + msg__->scanConfig = (scanConfig__); + +#define CsrWifiSmeScanConfigSetReqSendTo(dst__, src__, scanConfig__) \ + { \ + CsrWifiSmeScanConfigSetReq *msg__; \ + CsrWifiSmeScanConfigSetReqCreate(msg__, dst__, src__, scanConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanConfigSetReqSend(src__, scanConfig__) \ + CsrWifiSmeScanConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, scanConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeScanConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeScanConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeScanConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeScanConfigSetCfm *msg__; \ + CsrWifiSmeScanConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanConfigSetCfmSend(dst__, status__) \ + CsrWifiSmeScanConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanFullReqSend + + DESCRIPTION + The wireless manager application should call this primitive to request a + full scan. + Channels are scanned actively or passively according to the requirement + set by regulatory domain. + If the SME receives this primitive while a full scan is going on, the new + request is buffered and it will be served after the current full scan is + completed. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + ssidCount - Number of SSIDs provided. + If it is 0, the SME will attempt to detect any network + ssid - Points to the first SSID provided, if any. + bssid - BSS identifier. + If it is equal to FF-FF-FF-FF-FF, the SME will listen for + messages from any BSS. + If it is different from FF-FF-FF-FF-FF and any SSID is + provided, one SSID must match the network of the BSS. + forceScan - Forces the scan even if the SME is in a state which would + normally prevent it (e.g. autonomous scan is running). + bssType - Type of BSS to scan for + scanType - Type of scan to perform + channelListCount - Number of channels provided. + If it is 0, the SME will initiate a scan of all the + supported channels that are permitted by the current + regulatory domain. + channelList - Points to the first channel , or NULL if channelListCount + is zero. + probeIeLength - Length of the information element in bytes to be sent + with the probe message. + probeIe - Points to the first byte of the information element to be + sent with the probe message. + +*******************************************************************************/ +#define CsrWifiSmeScanFullReqCreate(msg__, dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ + msg__ = (CsrWifiSmeScanFullReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanFullReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_FULL_REQ, dst__, src__); \ + msg__->ssidCount = (ssidCount__); \ + msg__->ssid = (ssid__); \ + msg__->bssid = (bssid__); \ + msg__->forceScan = (forceScan__); \ + msg__->bssType = (bssType__); \ + msg__->scanType = (scanType__); \ + msg__->channelListCount = (channelListCount__); \ + msg__->channelList = (channelList__); \ + msg__->probeIeLength = (probeIeLength__); \ + msg__->probeIe = (probeIe__); + +#define CsrWifiSmeScanFullReqSendTo(dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ + { \ + CsrWifiSmeScanFullReq *msg__; \ + CsrWifiSmeScanFullReqCreate(msg__, dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanFullReqSend(src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ + CsrWifiSmeScanFullReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanFullCfmSend + + DESCRIPTION + The SME calls this primitive when the results from the scan are + available. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeScanFullCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeScanFullCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanFullCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_FULL_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeScanFullCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeScanFullCfm *msg__; \ + CsrWifiSmeScanFullCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanFullCfmSend(dst__, status__) \ + CsrWifiSmeScanFullCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultIndSend + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever a scan indication is received from the firmware. + + PARAMETERS + queue - Destination Task Queue + result - Points to a buffer containing a scan result. + +*******************************************************************************/ +#define CsrWifiSmeScanResultIndCreate(msg__, dst__, src__, result__) \ + msg__ = (CsrWifiSmeScanResultInd *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULT_IND, dst__, src__); \ + msg__->result = (result__); + +#define CsrWifiSmeScanResultIndSendTo(dst__, src__, result__) \ + { \ + CsrWifiSmeScanResultInd *msg__; \ + CsrWifiSmeScanResultIndCreate(msg__, dst__, src__, result__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanResultIndSend(dst__, result__) \ + CsrWifiSmeScanResultIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, result__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsFlushReqSend + + DESCRIPTION + The Wireless Manager calls this primitive to ask the SME to delete all + scan results from its cache, except for the scan result of any currently + connected network. + As scan results are received by the SME from the firmware, they are + cached in the SME memory. + Any time the Wireless Manager requests scan results, they are returned + from the SME internal cache. + For some applications it may be desirable to clear this cache prior to + requesting that a scan be performed; this will ensure that the cache then + only contains the networks detected in the most recent scan. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeScanResultsFlushReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeScanResultsFlushReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultsFlushReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ, dst__, src__); + +#define CsrWifiSmeScanResultsFlushReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeScanResultsFlushReq *msg__; \ + CsrWifiSmeScanResultsFlushReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanResultsFlushReqSend(src__) \ + CsrWifiSmeScanResultsFlushReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsFlushCfmSend + + DESCRIPTION + The SME will call this primitive when the cache has been cleared. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeScanResultsFlushCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeScanResultsFlushCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultsFlushCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeScanResultsFlushCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeScanResultsFlushCfm *msg__; \ + CsrWifiSmeScanResultsFlushCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanResultsFlushCfmSend(dst__, status__) \ + CsrWifiSmeScanResultsFlushCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsGetReqSend + + DESCRIPTION + The wireless manager application calls this primitive to retrieve the + current set of scan results, either after receiving a successful + CSR_WIFI_SME_SCAN_FULL_CFM, or to get autonomous scan results. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeScanResultsGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeScanResultsGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultsGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_GET_REQ, dst__, src__); + +#define CsrWifiSmeScanResultsGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeScanResultsGetReq *msg__; \ + CsrWifiSmeScanResultsGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanResultsGetReqSend(src__) \ + CsrWifiSmeScanResultsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsGetCfmSend + + DESCRIPTION + The SME sends this primitive to provide the current set of scan results. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + scanResultsCount - Number of scan results + scanResults - Points to a buffer containing an array of + CsrWifiSmeScanResult structures. + +*******************************************************************************/ +#define CsrWifiSmeScanResultsGetCfmCreate(msg__, dst__, src__, status__, scanResultsCount__, scanResults__) \ + msg__ = (CsrWifiSmeScanResultsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultsGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->scanResultsCount = (scanResultsCount__); \ + msg__->scanResults = (scanResults__); + +#define CsrWifiSmeScanResultsGetCfmSendTo(dst__, src__, status__, scanResultsCount__, scanResults__) \ + { \ + CsrWifiSmeScanResultsGetCfm *msg__; \ + CsrWifiSmeScanResultsGetCfmCreate(msg__, dst__, src__, status__, scanResultsCount__, scanResults__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \ + CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanResultsCount__, scanResults__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the Sme common parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeSmeCommonConfigGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeSmeCommonConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ, dst__, src__); + +#define CsrWifiSmeSmeCommonConfigGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeSmeCommonConfigGetReq *msg__; \ + CsrWifiSmeSmeCommonConfigGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeCommonConfigGetReqSend(src__) \ + CsrWifiSmeSmeCommonConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + deviceConfig - Configuration options in the SME + +*******************************************************************************/ +#define CsrWifiSmeSmeCommonConfigGetCfmCreate(msg__, dst__, src__, status__, deviceConfig__) \ + msg__ = (CsrWifiSmeSmeCommonConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->deviceConfig = (deviceConfig__); + +#define CsrWifiSmeSmeCommonConfigGetCfmSendTo(dst__, src__, status__, deviceConfig__) \ + { \ + CsrWifiSmeSmeCommonConfigGetCfm *msg__; \ + CsrWifiSmeSmeCommonConfigGetCfmCreate(msg__, dst__, src__, status__, deviceConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeCommonConfigGetCfmSend(dst__, status__, deviceConfig__) \ + CsrWifiSmeSmeCommonConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, deviceConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the Sme common. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + deviceConfig - Configuration options in the SME + +*******************************************************************************/ +#define CsrWifiSmeSmeCommonConfigSetReqCreate(msg__, dst__, src__, deviceConfig__) \ + msg__ = (CsrWifiSmeSmeCommonConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, dst__, src__); \ + msg__->deviceConfig = (deviceConfig__); + +#define CsrWifiSmeSmeCommonConfigSetReqSendTo(dst__, src__, deviceConfig__) \ + { \ + CsrWifiSmeSmeCommonConfigSetReq *msg__; \ + CsrWifiSmeSmeCommonConfigSetReqCreate(msg__, dst__, src__, deviceConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeCommonConfigSetReqSend(src__, deviceConfig__) \ + CsrWifiSmeSmeCommonConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, deviceConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigSetCfmSend + + DESCRIPTION + Reports the result of the request + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeSmeCommonConfigSetCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeSmeCommonConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeSmeCommonConfigSetCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeSmeCommonConfigSetCfm *msg__; \ + CsrWifiSmeSmeCommonConfigSetCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeCommonConfigSetCfmSend(dst__, status__) \ + CsrWifiSmeSmeCommonConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigGetReqSend + + DESCRIPTION + This primitive gets the value of the SmeStaConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +#define CsrWifiSmeSmeStaConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeSmeStaConfigGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeSmeStaConfigGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeSmeStaConfigGetReq *msg__; \ + CsrWifiSmeSmeStaConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeStaConfigGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeSmeStaConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + smeConfig - Current SME Station Parameters + +*******************************************************************************/ +#define CsrWifiSmeSmeStaConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, smeConfig__) \ + msg__ = (CsrWifiSmeSmeStaConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->smeConfig = (smeConfig__); + +#define CsrWifiSmeSmeStaConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, smeConfig__) \ + { \ + CsrWifiSmeSmeStaConfigGetCfm *msg__; \ + CsrWifiSmeSmeStaConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, smeConfig__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeStaConfigGetCfmSend(dst__, interfaceTag__, status__, smeConfig__) \ + CsrWifiSmeSmeStaConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, smeConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigSetReqSend + + DESCRIPTION + This primitive sets the value of the SmeConfig parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + smeConfig - SME Station Parameters to be set + +*******************************************************************************/ +#define CsrWifiSmeSmeStaConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, smeConfig__) \ + msg__ = (CsrWifiSmeSmeStaConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->smeConfig = (smeConfig__); + +#define CsrWifiSmeSmeStaConfigSetReqSendTo(dst__, src__, interfaceTag__, smeConfig__) \ + { \ + CsrWifiSmeSmeStaConfigSetReq *msg__; \ + CsrWifiSmeSmeStaConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, smeConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeStaConfigSetReqSend(src__, interfaceTag__, smeConfig__) \ + CsrWifiSmeSmeStaConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, smeConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigSetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeSmeStaConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ + msg__ = (CsrWifiSmeSmeStaConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); + +#define CsrWifiSmeSmeStaConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ + { \ + CsrWifiSmeSmeStaConfigSetCfm *msg__; \ + CsrWifiSmeSmeStaConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSmeStaConfigSetCfmSend(dst__, interfaceTag__, status__) \ + CsrWifiSmeSmeStaConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeStationMacAddressGetReqSend + + DESCRIPTION + This primitives is used to retrieve the current MAC address used by the + station. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeStationMacAddressGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeStationMacAddressGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeStationMacAddressGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ, dst__, src__); + +#define CsrWifiSmeStationMacAddressGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeStationMacAddressGetReq *msg__; \ + CsrWifiSmeStationMacAddressGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeStationMacAddressGetReqSend(src__) \ + CsrWifiSmeStationMacAddressGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeStationMacAddressGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + stationMacAddress - Current MAC address of the station. + +*******************************************************************************/ +#define CsrWifiSmeStationMacAddressGetCfmCreate(msg__, dst__, src__, status__, stationMacAddress__) \ + msg__ = (CsrWifiSmeStationMacAddressGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeStationMacAddressGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + CsrMemCpy(msg__->stationMacAddress, (stationMacAddress__), sizeof(CsrWifiMacAddress) * 2); + +#define CsrWifiSmeStationMacAddressGetCfmSendTo(dst__, src__, status__, stationMacAddress__) \ + { \ + CsrWifiSmeStationMacAddressGetCfm *msg__; \ + CsrWifiSmeStationMacAddressGetCfmCreate(msg__, dst__, src__, status__, stationMacAddress__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeStationMacAddressGetCfmSend(dst__, status__, stationMacAddress__) \ + CsrWifiSmeStationMacAddressGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, stationMacAddress__) + +/******************************************************************************* + + NAME + CsrWifiSmeTspecReqSend + + DESCRIPTION + The wireless manager application should call this primitive to use the + TSPEC feature. + The chip supports the use of TSPECs and TCLAS for the use of IEEE + 802.11/WMM Quality of Service features. + The API allows the wireless manager application to supply a correctly + formatted TSPEC and TCLAS pair to the driver. + After performing basic validation, the driver negotiates the installation + of the TSPEC with the AP as defined by the 802.11 specification. + The driver retains all TSPEC and TCLAS pairs until they are specifically + removed. + It is not compulsory for a TSPEC to have a TCLAS (NULL is used to + indicate that no TCLAS is supplied), while a TCLASS always require a + TSPEC. + The format of the TSPEC element is specified in 'WMM (including WMM Power + Save) Specification - Version 1.1' and 'ANSI/IEEE Std 802.11-REVmb/D3.0'. + For more information, see 'UniFi Configuring WMM and WMM-PS'. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - Interface Identifier; unique identifier of an interface + action - Specifies the action to be carried out on the list of TSPECs. + CSR_WIFI_SME_LIST_ACTION_FLUSH is not applicable here. + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + strict - If it set to false, allows the SME to perform automatic + TSPEC negotiation + ctrlMask - Additional TSPEC configuration for CCX. + Set mask with values from CsrWifiSmeTspecCtrl. + CURRENTLY NOT SUPPORTED + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + tclasLength - Length of the TCLAS. + If it is equal to 0, no TCLASS is provided for the TSPEC + tclas - Points to the first byte of the TCLAS, if any. + +*******************************************************************************/ +#define CsrWifiSmeTspecReqCreate(msg__, dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ + msg__ = (CsrWifiSmeTspecReq *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->action = (action__); \ + msg__->transactionId = (transactionId__); \ + msg__->strict = (strict__); \ + msg__->ctrlMask = (ctrlMask__); \ + msg__->tspecLength = (tspecLength__); \ + msg__->tspec = (tspec__); \ + msg__->tclasLength = (tclasLength__); \ + msg__->tclas = (tclas__); + +#define CsrWifiSmeTspecReqSendTo(dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ + { \ + CsrWifiSmeTspecReq *msg__; \ + CsrWifiSmeTspecReqCreate(msg__, dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeTspecReqSend(src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ + CsrWifiSmeTspecReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) + +/******************************************************************************* + + NAME + CsrWifiSmeTspecIndSend + + DESCRIPTION + The SME will send this primitive to all the task that have registered to + receive it when a status change in the TSPEC occurs. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + tspecResultCode - Specifies the TSPEC operation requested by the peer + station + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + +*******************************************************************************/ +#define CsrWifiSmeTspecIndCreate(msg__, dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + msg__ = (CsrWifiSmeTspecInd *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_IND, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->transactionId = (transactionId__); \ + msg__->tspecResultCode = (tspecResultCode__); \ + msg__->tspecLength = (tspecLength__); \ + msg__->tspec = (tspec__); + +#define CsrWifiSmeTspecIndSendTo(dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + { \ + CsrWifiSmeTspecInd *msg__; \ + CsrWifiSmeTspecIndCreate(msg__, dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeTspecIndSend(dst__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + CsrWifiSmeTspecIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) + +/******************************************************************************* + + NAME + CsrWifiSmeTspecCfmSend + + DESCRIPTION + The SME calls the primitive to report the result of the TSpec primitive + request. + + PARAMETERS + queue - Destination Task Queue + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + tspecResultCode - Specifies the result of the negotiated TSPEC operation + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + +*******************************************************************************/ +#define CsrWifiSmeTspecCfmCreate(msg__, dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + msg__ = (CsrWifiSmeTspecCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->transactionId = (transactionId__); \ + msg__->tspecResultCode = (tspecResultCode__); \ + msg__->tspecLength = (tspecLength__); \ + msg__->tspec = (tspec__); + +#define CsrWifiSmeTspecCfmSendTo(dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + { \ + CsrWifiSmeTspecCfm *msg__; \ + CsrWifiSmeTspecCfmCreate(msg__, dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeTspecCfmSend(dst__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ + CsrWifiSmeTspecCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) + +/******************************************************************************* + + NAME + CsrWifiSmeVersionsGetReqSend + + DESCRIPTION + This primitive gets the value of the Versions parameter. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeVersionsGetReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeVersionsGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeVersionsGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_VERSIONS_GET_REQ, dst__, src__); + +#define CsrWifiSmeVersionsGetReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeVersionsGetReq *msg__; \ + CsrWifiSmeVersionsGetReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeVersionsGetReqSend(src__) \ + CsrWifiSmeVersionsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeVersionsGetCfmSend + + DESCRIPTION + This primitive reports the result of the request. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + versions - Version IDs of the product + +*******************************************************************************/ +#define CsrWifiSmeVersionsGetCfmCreate(msg__, dst__, src__, status__, versions__) \ + msg__ = (CsrWifiSmeVersionsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeVersionsGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_VERSIONS_GET_CFM, dst__, src__); \ + msg__->status = (status__); \ + msg__->versions = (versions__); + +#define CsrWifiSmeVersionsGetCfmSendTo(dst__, src__, status__, versions__) \ + { \ + CsrWifiSmeVersionsGetCfm *msg__; \ + CsrWifiSmeVersionsGetCfmCreate(msg__, dst__, src__, status__, versions__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeVersionsGetCfmSend(dst__, status__, versions__) \ + CsrWifiSmeVersionsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, versions__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiFlightmodeReqSend + + DESCRIPTION + The wireless manager application may call this primitive on boot-up of + the platform to ensure that the chip is placed in a mode that prevents + any emission of RF energy. + This primitive is an alternative to CSR_WIFI_SME_WIFI_ON_REQ. + As in CSR_WIFI_SME_WIFI_ON_REQ, it causes the download of the patch file + (if any) and the programming of the initial MIB settings (if supplied by + the WMA), but it also ensures that the chip is left in its lowest + possible power-mode with the radio subsystems disabled. + This feature is useful on platforms where power cannot be removed from + the chip (leaving the chip not initialised will cause it to consume more + power so calling this function ensures that the chip is initialised into + a low power mode but without entering a state where it could emit any RF + energy). + NOTE: this primitive does not cause the Wi-Fi to change state: Wi-Fi + stays conceptually off. Configuration primitives can be sent after + CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ and the configuration will be maintained. + Requests that require the state of the Wi-Fi to be ON will return + CSR_WIFI_SME_STATUS_WIFI_OFF in their confirms. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + address - Optionally specifies a station MAC address. + In normal use, the manager should set the address to 0xFF + 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use + the MAC address in the MIB. + mibFilesCount - Number of provided data blocks with initial MIB values + mibFiles - Points to the first data block with initial MIB values. + These data blocks are typically the contents of the provided + files ufmib.dat and localmib.dat, available from the host + file system, if they exist. + These files typically contain radio tuning and calibration + values. + More values can be created using the Host Tools. + +*******************************************************************************/ +#define CsrWifiSmeWifiFlightmodeReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__) \ + msg__ = (CsrWifiSmeWifiFlightmodeReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiFlightmodeReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ, dst__, src__); \ + msg__->address = (address__); \ + msg__->mibFilesCount = (mibFilesCount__); \ + msg__->mibFiles = (mibFiles__); + +#define CsrWifiSmeWifiFlightmodeReqSendTo(dst__, src__, address__, mibFilesCount__, mibFiles__) \ + { \ + CsrWifiSmeWifiFlightmodeReq *msg__; \ + CsrWifiSmeWifiFlightmodeReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiFlightmodeReqSend(src__, address__, mibFilesCount__, mibFiles__) \ + CsrWifiSmeWifiFlightmodeReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, address__, mibFilesCount__, mibFiles__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiFlightmodeCfmSend + + DESCRIPTION + The SME calls this primitive when the chip is initialised for low power + mode and with the radio subsystem disabled. To leave flight mode, and + enable Wi-Fi, the wireless manager application should call + CSR_WIFI_SME_WIFI_ON_REQ. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeWifiFlightmodeCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeWifiFlightmodeCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiFlightmodeCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeWifiFlightmodeCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeWifiFlightmodeCfm *msg__; \ + CsrWifiSmeWifiFlightmodeCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiFlightmodeCfmSend(dst__, status__) \ + CsrWifiSmeWifiFlightmodeCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffReqSend + + DESCRIPTION + The wireless manager application calls this primitive to turn off the + chip, thus saving power when Wi-Fi is not in use. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + +*******************************************************************************/ +#define CsrWifiSmeWifiOffReqCreate(msg__, dst__, src__) \ + msg__ = (CsrWifiSmeWifiOffReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOffReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_REQ, dst__, src__); + +#define CsrWifiSmeWifiOffReqSendTo(dst__, src__) \ + { \ + CsrWifiSmeWifiOffReq *msg__; \ + CsrWifiSmeWifiOffReqCreate(msg__, dst__, src__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOffReqSend(src__) \ + CsrWifiSmeWifiOffReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffIndSend + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it to report that the chip has been turned off. + + PARAMETERS + queue - Destination Task Queue + reason - Indicates the reason why the Wi-Fi has been switched off. + +*******************************************************************************/ +#define CsrWifiSmeWifiOffIndCreate(msg__, dst__, src__, reason__) \ + msg__ = (CsrWifiSmeWifiOffInd *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOffInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_IND, dst__, src__); \ + msg__->reason = (reason__); + +#define CsrWifiSmeWifiOffIndSendTo(dst__, src__, reason__) \ + { \ + CsrWifiSmeWifiOffInd *msg__; \ + CsrWifiSmeWifiOffIndCreate(msg__, dst__, src__, reason__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOffIndSend(dst__, reason__) \ + CsrWifiSmeWifiOffIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, reason__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffCfmSend + + DESCRIPTION + After receiving CSR_WIFI_SME_WIFI_OFF_REQ, if the chip is connected to a + network, the SME will perform a disconnect operation, will send a + CSR_WIFI_SME_MEDIA_STATUS_IND with + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED, and then will call + CSR_WIFI_SME_WIFI_OFF_CFM when the chip is off. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeWifiOffCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeWifiOffCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOffCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeWifiOffCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeWifiOffCfm *msg__; \ + CsrWifiSmeWifiOffCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOffCfmSend(dst__, status__) \ + CsrWifiSmeWifiOffCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnReqSend + + DESCRIPTION + The wireless manager application calls this primitive to turn on the + Wi-Fi chip. + If the Wi-Fi chip is currently off, the SME turns the Wi-Fi chip on, + downloads the patch file (if any), and programs the initial MIB settings + (if supplied by the WMA). + The patch file is not provided with the SME API; its downloading is + automatic and handled internally by the system. + The MIB settings, when provided, override the default values that the + firmware loads from EEPROM. + If the Wi-Fi chip is already on, the SME takes no action and returns a + successful status in the confirm. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + address - Optionally specifies a station MAC address. + In normal use, the manager should set the address to 0xFF + 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use + the MAC address in the MIB + mibFilesCount - Number of provided data blocks with initial MIB values + mibFiles - Points to the first data block with initial MIB values. + These data blocks are typically the contents of the provided + files ufmib.dat and localmib.dat, available from the host + file system, if they exist. + These files typically contain radio tuning and calibration + values. + More values can be created using the Host Tools. + +*******************************************************************************/ +#define CsrWifiSmeWifiOnReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__) \ + msg__ = (CsrWifiSmeWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOnReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_REQ, dst__, src__); \ + msg__->address = (address__); \ + msg__->mibFilesCount = (mibFilesCount__); \ + msg__->mibFiles = (mibFiles__); + +#define CsrWifiSmeWifiOnReqSendTo(dst__, src__, address__, mibFilesCount__, mibFiles__) \ + { \ + CsrWifiSmeWifiOnReq *msg__; \ + CsrWifiSmeWifiOnReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOnReqSend(src__, address__, mibFilesCount__, mibFiles__) \ + CsrWifiSmeWifiOnReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, address__, mibFilesCount__, mibFiles__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnIndSend + + DESCRIPTION + The SME sends this primitive to all tasks that have registered to receive + it once the chip becomes available and ready to use. + + PARAMETERS + queue - Destination Task Queue + address - Current MAC address + +*******************************************************************************/ +#define CsrWifiSmeWifiOnIndCreate(msg__, dst__, src__, address__) \ + msg__ = (CsrWifiSmeWifiOnInd *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOnInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_IND, dst__, src__); \ + msg__->address = (address__); + +#define CsrWifiSmeWifiOnIndSendTo(dst__, src__, address__) \ + { \ + CsrWifiSmeWifiOnInd *msg__; \ + CsrWifiSmeWifiOnIndCreate(msg__, dst__, src__, address__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOnIndSend(dst__, address__) \ + CsrWifiSmeWifiOnIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, address__) + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnCfmSend + + DESCRIPTION + The SME sends this primitive to the task that has sent the request once + the chip has been initialised and is available for use. + + PARAMETERS + queue - Destination Task Queue + status - Reports the result of the request + +*******************************************************************************/ +#define CsrWifiSmeWifiOnCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeWifiOnCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOnCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeWifiOnCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeWifiOnCfm *msg__; \ + CsrWifiSmeWifiOnCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWifiOnCfmSend(dst__, status__) \ + CsrWifiSmeWifiOnCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigurationReqSend + + DESCRIPTION + This primitive passes the WPS information for the device to SME. This may + be accepted only if no interface is active. + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + wpsConfig - WPS config. + +*******************************************************************************/ +#define CsrWifiSmeWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__) \ + msg__ = (CsrWifiSmeWpsConfigurationReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWpsConfigurationReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WPS_CONFIGURATION_REQ, dst__, src__); \ + msg__->wpsConfig = (wpsConfig__); + +#define CsrWifiSmeWpsConfigurationReqSendTo(dst__, src__, wpsConfig__) \ + { \ + CsrWifiSmeWpsConfigurationReq *msg__; \ + CsrWifiSmeWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWpsConfigurationReqSend(src__, wpsConfig__) \ + CsrWifiSmeWpsConfigurationReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, wpsConfig__) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigurationCfmSend + + DESCRIPTION + Confirm. + + PARAMETERS + queue - Destination Task Queue + status - Status of the request. + +*******************************************************************************/ +#define CsrWifiSmeWpsConfigurationCfmCreate(msg__, dst__, src__, status__) \ + msg__ = (CsrWifiSmeWpsConfigurationCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeWpsConfigurationCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WPS_CONFIGURATION_CFM, dst__, src__); \ + msg__->status = (status__); + +#define CsrWifiSmeWpsConfigurationCfmSendTo(dst__, src__, status__) \ + { \ + CsrWifiSmeWpsConfigurationCfm *msg__; \ + CsrWifiSmeWpsConfigurationCfmCreate(msg__, dst__, src__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeWpsConfigurationCfmSend(dst__, status__) \ + CsrWifiSmeWpsConfigurationCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_prim.h b/drivers/staging/csr/csr_wifi_sme_prim.h new file mode 100644 index 000000000000..4bc8520dbd0c --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_prim.h @@ -0,0 +1,6494 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_PRIM_H__ +#define CSR_WIFI_SME_PRIM_H__ + +#include "csr_types.h" +#include "csr_prim_defs.h" +#include "csr_sched.h" +#include "csr_wifi_common.h" +#include "csr_result.h" +#include "csr_wifi_fsm_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSR_WIFI_SME_PRIM (0x0404) + +typedef CsrPrim CsrWifiSmePrim; + + +/******************************************************************************* + + NAME + CsrWifiSme80211NetworkType + + DESCRIPTION + Indicates the physical layer of the network + + VALUES + CSR_WIFI_SME_80211_NETWORK_TYPE_DS + - Direct-sequence spread spectrum + CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM24 + - Orthogonal Frequency Division Multiplexing at 2.4 GHz + CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM5 + - Orthogonal Frequency Division Multiplexing at 5 GHz + CSR_WIFI_SME_80211_NETWORK_TYPE_AUTO + - Automatic + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSme80211NetworkType; +#define CSR_WIFI_SME_80211_NETWORK_TYPE_DS ((CsrWifiSme80211NetworkType) 0x00) +#define CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM24 ((CsrWifiSme80211NetworkType) 0x01) +#define CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM5 ((CsrWifiSme80211NetworkType) 0x02) +#define CSR_WIFI_SME_80211_NETWORK_TYPE_AUTO ((CsrWifiSme80211NetworkType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSme80211PrivacyMode + + DESCRIPTION + Bits to enable or disable the privacy mode + + VALUES + CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED + - Privacy mode is enabled: use of WEP for confidentiality is + required. + CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED + - Privacy mode is disabled + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSme80211PrivacyMode; +#define CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED ((CsrWifiSme80211PrivacyMode) 0x00) +#define CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED ((CsrWifiSme80211PrivacyMode) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSme80211dTrustLevel + + DESCRIPTION + Level of trust for the information coming from the network + + VALUES + CSR_WIFI_SME_80211D_TRUST_LEVEL_STRICT + - Start with passive scanning and only accept country IE for + updating channel lists + CSR_WIFI_SME_80211D_TRUST_LEVEL_ADJUNCT + - As above plus accept adjunct technology location + information + CSR_WIFI_SME_80211D_TRUST_LEVEL_BSS + - As above accept plus receiving channel from infrastructure + networks + CSR_WIFI_SME_80211D_TRUST_LEVEL_IBSS + - As above accept plus receiving channel from the ad hoc + networks + CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB + - Start with active scanning with list of active channels + from the MIB and accept as above + CSR_WIFI_SME_80211D_TRUST_LEVEL_DISABLED + - Start with active scanning with list of active channels + from the MIB and ignore any channel information from the + network + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSme80211dTrustLevel; +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_STRICT ((CsrWifiSme80211dTrustLevel) 0x01) +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_ADJUNCT ((CsrWifiSme80211dTrustLevel) 0x02) +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_BSS ((CsrWifiSme80211dTrustLevel) 0x03) +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_IBSS ((CsrWifiSme80211dTrustLevel) 0x04) +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB ((CsrWifiSme80211dTrustLevel) 0x05) +#define CSR_WIFI_SME_80211D_TRUST_LEVEL_DISABLED ((CsrWifiSme80211dTrustLevel) 0x06) + +/******************************************************************************* + + NAME + CsrWifiSmeAmpStatus + + DESCRIPTION + AMP Current Status + + VALUES + CSR_WIFI_SME_AMP_ACTIVE - AMP ACTIVE. + CSR_WIFI_SME_AMP_INACTIVE - AMP INACTIVE + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeAmpStatus; +#define CSR_WIFI_SME_AMP_ACTIVE ((CsrWifiSmeAmpStatus) 0x00) +#define CSR_WIFI_SME_AMP_INACTIVE ((CsrWifiSmeAmpStatus) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeAuthMode + + DESCRIPTION + Define bits for CsrWifiSmeAuthMode + + VALUES + CSR_WIFI_SME_AUTH_MODE_80211_OPEN + - Connects to an open system network (i.e. no authentication, + no encryption) or to a WEP enabled network. + CSR_WIFI_SME_AUTH_MODE_80211_SHARED + - Connect to a WEP enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_WPA + - Connects to a WPA Enterprise enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK + - Connects to a WPA with Pre-Shared Key enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 + - Connects to a WPA2 Enterprise enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK + - Connects to a WPA2 with Pre-Shared Key enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_CCKM + - Connects to a CCKM enabled network. + CSR_WIFI_SME_AUTH_MODE_WAPI_WAI + - Connects to a WAPI Enterprise enabled network. + CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK + - Connects to a WAPI with Pre-Shared Key enabled network. + CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X + - For future use. + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeAuthMode; +#define CSR_WIFI_SME_AUTH_MODE_80211_OPEN ((CsrWifiSmeAuthMode) 0x0001) +#define CSR_WIFI_SME_AUTH_MODE_80211_SHARED ((CsrWifiSmeAuthMode) 0x0002) +#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA ((CsrWifiSmeAuthMode) 0x0004) +#define CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK ((CsrWifiSmeAuthMode) 0x0008) +#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 ((CsrWifiSmeAuthMode) 0x0010) +#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK ((CsrWifiSmeAuthMode) 0x0020) +#define CSR_WIFI_SME_AUTH_MODE_8021X_CCKM ((CsrWifiSmeAuthMode) 0x0040) +#define CSR_WIFI_SME_AUTH_MODE_WAPI_WAI ((CsrWifiSmeAuthMode) 0x0080) +#define CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK ((CsrWifiSmeAuthMode) 0x0100) +#define CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X ((CsrWifiSmeAuthMode) 0x0200) + +/******************************************************************************* + + NAME + CsrWifiSmeBasicUsability + + DESCRIPTION + Indicates the usability level of a channel + + VALUES + CSR_WIFI_SME_BASIC_USABILITY_UNUSABLE + - Not usable; connection not recommended + CSR_WIFI_SME_BASIC_USABILITY_POOR + - Poor quality; connect only if nothing better is available + CSR_WIFI_SME_BASIC_USABILITY_SATISFACTORY + - Quality is satisfactory + CSR_WIFI_SME_BASIC_USABILITY_NOT_CONNECTED + - Not connected + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeBasicUsability; +#define CSR_WIFI_SME_BASIC_USABILITY_UNUSABLE ((CsrWifiSmeBasicUsability) 0x00) +#define CSR_WIFI_SME_BASIC_USABILITY_POOR ((CsrWifiSmeBasicUsability) 0x01) +#define CSR_WIFI_SME_BASIC_USABILITY_SATISFACTORY ((CsrWifiSmeBasicUsability) 0x02) +#define CSR_WIFI_SME_BASIC_USABILITY_NOT_CONNECTED ((CsrWifiSmeBasicUsability) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeBssType + + DESCRIPTION + Indicates the BSS type + + VALUES + CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE + - Infrastructure BSS. + CSR_WIFI_SME_BSS_TYPE_ADHOC + - Ad hoc or Independent BSS. + CSR_WIFI_SME_BSS_TYPE_ANY_BSS + - Specifies any type of BSS + CSR_WIFI_SME_BSS_TYPE_P2P + - Specifies P2P + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeBssType; +#define CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE ((CsrWifiSmeBssType) 0x00) +#define CSR_WIFI_SME_BSS_TYPE_ADHOC ((CsrWifiSmeBssType) 0x01) +#define CSR_WIFI_SME_BSS_TYPE_ANY_BSS ((CsrWifiSmeBssType) 0x02) +#define CSR_WIFI_SME_BSS_TYPE_P2P ((CsrWifiSmeBssType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeCoexScheme + + DESCRIPTION + Options for the coexistence signalling + Same as MibValues + + VALUES + CSR_WIFI_SME_COEX_SCHEME_DISABLED + - The coexistence signalling is disabled + CSR_WIFI_SME_COEX_SCHEME_CSR + - Basic CSR coexistence signalling + CSR_WIFI_SME_COEX_SCHEME_CSR_CHANNEL + - Full CSR coexistence signalling + CSR_WIFI_SME_COEX_SCHEME_PTA + - Packet Traffic Arbitrator coexistence signalling + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeCoexScheme; +#define CSR_WIFI_SME_COEX_SCHEME_DISABLED ((CsrWifiSmeCoexScheme) 0x00) +#define CSR_WIFI_SME_COEX_SCHEME_CSR ((CsrWifiSmeCoexScheme) 0x01) +#define CSR_WIFI_SME_COEX_SCHEME_CSR_CHANNEL ((CsrWifiSmeCoexScheme) 0x02) +#define CSR_WIFI_SME_COEX_SCHEME_PTA ((CsrWifiSmeCoexScheme) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeControlIndication + + DESCRIPTION + Indicates the reason why the Wi-Fi has been switched off. + The values of this type are used across the NME/SME/Router API's and they + must be kept consistent with the corresponding types in the .xml of the + ottherinterfaces + + VALUES + CSR_WIFI_SME_CONTROL_INDICATION_ERROR + - An unrecoverable error (for example, an unrecoverable SDIO + error) has occurred. + The wireless manager application should reinitialise the + chip by calling CSR_WIFI_SME_WIFI_ON_REQ. + CSR_WIFI_SME_CONTROL_INDICATION_EXIT + - The chip became unavailable due to an external action, for + example, when a plug-in card is ejected or the driver is + unloaded. + CSR_WIFI_SME_CONTROL_INDICATION_USER_REQUESTED + - The Wi-Fi has been switched off as the wireless manager + application has sent CSR_WIFI_SME_WIFI_OFF_REQ + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeControlIndication; +#define CSR_WIFI_SME_CONTROL_INDICATION_ERROR ((CsrWifiSmeControlIndication) 0x01) +#define CSR_WIFI_SME_CONTROL_INDICATION_EXIT ((CsrWifiSmeControlIndication) 0x02) +#define CSR_WIFI_SME_CONTROL_INDICATION_USER_REQUESTED ((CsrWifiSmeControlIndication) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeCtsProtectionType + + DESCRIPTION + SME CTS Protection Types + + VALUES + CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC + - AP CTS Protection automatic based on non-ERP station in own + BSS or neighbouring BSS on the same channel based on OLBC. + This requires monitoring of beacons from other APs. + CSR_WIFI_SME_CTS_PROTECTION_FORCE_ENABLED + - AP CTS Protection Force enabled + CSR_WIFI_SME_CTS_PROTECTION_FORCE_DISABLED + - AP CTS Protection Force disabled. + CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC_NO_OLBC + - AP CTS Protection automatic without considering OLBC but + considering non-ERP station in the own BSS Valid only if AP + is configured to work in 802.11bg or 802.11g mode otherwise + this option specifies the same behaviour as AUTOMATIC + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeCtsProtectionType; +#define CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC ((CsrWifiSmeCtsProtectionType) 0x00) +#define CSR_WIFI_SME_CTS_PROTECTION_FORCE_ENABLED ((CsrWifiSmeCtsProtectionType) 0x01) +#define CSR_WIFI_SME_CTS_PROTECTION_FORCE_DISABLED ((CsrWifiSmeCtsProtectionType) 0x02) +#define CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC_NO_OLBC ((CsrWifiSmeCtsProtectionType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeD3AutoScanMode + + DESCRIPTION + Autonomous scan status while in D3 suspended period + + VALUES + CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSON + - Autonomous scan stays on + CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSOFF + - Autonomous scan is switched off + CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSAUTO + - Automatically select autoscanning behaviour. + CURRENTLY NOT SUPPORTED + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeD3AutoScanMode; +#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSON ((CsrWifiSmeD3AutoScanMode) 0x00) +#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSOFF ((CsrWifiSmeD3AutoScanMode) 0x01) +#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSAUTO ((CsrWifiSmeD3AutoScanMode) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeEncryption + + DESCRIPTION + Defines bits for CsrWifiSmeEncryption + For a WEP enabled network, the caller must specify the correct + combination of flags in the encryptionModeMask. + + VALUES + CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE + - No encryption set + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 + - Selects 40 byte key WEP for unicast communication + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 + - Selects 104 byte key WEP for unicast communication + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP + - Selects TKIP for unicast communication + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP + - Selects CCMP for unicast communication + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 + - Selects SMS4 for unicast communication + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 + - Selects 40 byte key WEP for broadcast messages + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 + - Selects 104 byte key WEP for broadcast messages + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP + - Selects a TKIP for broadcast messages + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP + - Selects CCMP for broadcast messages + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4 + - Selects SMS4 for broadcast messages + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeEncryption; +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE ((CsrWifiSmeEncryption) 0x0000) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 ((CsrWifiSmeEncryption) 0x0001) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 ((CsrWifiSmeEncryption) 0x0002) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP ((CsrWifiSmeEncryption) 0x0004) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP ((CsrWifiSmeEncryption) 0x0008) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 ((CsrWifiSmeEncryption) 0x0010) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 ((CsrWifiSmeEncryption) 0x0020) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 ((CsrWifiSmeEncryption) 0x0040) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP ((CsrWifiSmeEncryption) 0x0080) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP ((CsrWifiSmeEncryption) 0x0100) +#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4 ((CsrWifiSmeEncryption) 0x0200) + +/******************************************************************************* + + NAME + CsrWifiSmeFirmwareDriverInterface + + DESCRIPTION + Type of communication between Host and Firmware + + VALUES + CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_UNIT_DATA_INTERFACE + - No preformated header. NOT SUPPORTED in the current release + CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_PACKET_INTERFACE + - Preformated IEEE 802.11 header for user plane + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeFirmwareDriverInterface; +#define CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_UNIT_DATA_INTERFACE ((CsrWifiSmeFirmwareDriverInterface) 0x00) +#define CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_PACKET_INTERFACE ((CsrWifiSmeFirmwareDriverInterface) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeHostPowerMode + + DESCRIPTION + Defines the power mode + + VALUES + CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE + - Host device is running on external power. + CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE + - Host device is running on (internal) battery power. + CSR_WIFI_SME_HOST_POWER_MODE_FULL_POWER_SAVE + - For future use. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeHostPowerMode; +#define CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE ((CsrWifiSmeHostPowerMode) 0x00) +#define CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE ((CsrWifiSmeHostPowerMode) 0x01) +#define CSR_WIFI_SME_HOST_POWER_MODE_FULL_POWER_SAVE ((CsrWifiSmeHostPowerMode) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeIEEE80211Reason + + DESCRIPTION + As definined in the IEEE 802.11 standards + + VALUES + CSR_WIFI_SME_IEEE80211_REASON_SUCCESS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNSPECIFIED_REASON + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_AUTHENTICATION_NOT_VALID + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DEAUTHENTICATED_LEAVE_BSS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_INACTIVITY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_AP_OVERLOAD + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_CLASS_2FRAME_ERROR + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_CLASS_3FRAME_ERROR + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_LEAVE_BSS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_ASSOCIATION_NOT_AUTHENTICATED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_POWER_CAPABILITY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_SUPPORTED_CHANNELS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_INFORMATION_ELEMENT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_MICHAEL_MIC_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_FOURWAY_HANDSHAKE_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_HANDSHAKE_ELEMENT_DIFFERENT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_GROUP_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_PAIRWISE_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_AKMP + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_RSN_IEVERSION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_RSN_IECAPABILITIES + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_DOT1X_AUTH_FAILED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_CIPHER_REJECTED_BY_POLICY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_SERVICE_CHANGE_PRECLUDES_TS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_QOS_UNSPECIFIED_REASON + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_QOS_INSUFFICIENT_BANDWIDTH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_QOS_EXCESSIVE_NOT_ACK + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_QOS_TXOPLIMIT_EXCEEDED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_QSTA_LEAVING + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_END_TS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_END_DLS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_END_BA + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_TS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_BA + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_DLS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_STAKEY_MISMATCH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNICAST_KEY_NEGOTIATION_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_MULTICAST_KEY_ANNOUNCEMENT_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INCOMPATIBLE_UNICAST_KEY_NEGOTIATION_IE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_MULTICAST_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_UNICAST_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_WAPI_IE_VERSION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_INVALID_WAPI_CAPABILITY_IE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_REASON_WAI_CERTIFICATE_AUTHENTICATION_FAILED + - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeIEEE80211Reason; +#define CSR_WIFI_SME_IEEE80211_REASON_SUCCESS ((CsrWifiSmeIEEE80211Reason) 0x0000) +#define CSR_WIFI_SME_IEEE80211_REASON_UNSPECIFIED_REASON ((CsrWifiSmeIEEE80211Reason) 0x0001) +#define CSR_WIFI_SME_IEEE80211_REASON_AUTHENTICATION_NOT_VALID ((CsrWifiSmeIEEE80211Reason) 0x0002) +#define CSR_WIFI_SME_IEEE80211_REASON_DEAUTHENTICATED_LEAVE_BSS ((CsrWifiSmeIEEE80211Reason) 0x0003) +#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_INACTIVITY ((CsrWifiSmeIEEE80211Reason) 0x0004) +#define CSR_WIFI_SME_IEEE80211_REASON_AP_OVERLOAD ((CsrWifiSmeIEEE80211Reason) 0x0005) +#define CSR_WIFI_SME_IEEE80211_REASON_CLASS_2FRAME_ERROR ((CsrWifiSmeIEEE80211Reason) 0x0006) +#define CSR_WIFI_SME_IEEE80211_REASON_CLASS_3FRAME_ERROR ((CsrWifiSmeIEEE80211Reason) 0x0007) +#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_LEAVE_BSS ((CsrWifiSmeIEEE80211Reason) 0x0008) +#define CSR_WIFI_SME_IEEE80211_REASON_ASSOCIATION_NOT_AUTHENTICATED ((CsrWifiSmeIEEE80211Reason) 0x0009) +#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_POWER_CAPABILITY ((CsrWifiSmeIEEE80211Reason) 0x000a) +#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_SUPPORTED_CHANNELS ((CsrWifiSmeIEEE80211Reason) 0x000b) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_INFORMATION_ELEMENT ((CsrWifiSmeIEEE80211Reason) 0x000d) +#define CSR_WIFI_SME_IEEE80211_REASON_MICHAEL_MIC_FAILURE ((CsrWifiSmeIEEE80211Reason) 0x000e) +#define CSR_WIFI_SME_IEEE80211_REASON_FOURWAY_HANDSHAKE_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x000f) +#define CSR_WIFI_SME_IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x0010) +#define CSR_WIFI_SME_IEEE80211_REASON_HANDSHAKE_ELEMENT_DIFFERENT ((CsrWifiSmeIEEE80211Reason) 0x0011) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_GROUP_CIPHER ((CsrWifiSmeIEEE80211Reason) 0x0012) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_PAIRWISE_CIPHER ((CsrWifiSmeIEEE80211Reason) 0x0013) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_AKMP ((CsrWifiSmeIEEE80211Reason) 0x0014) +#define CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_RSN_IEVERSION ((CsrWifiSmeIEEE80211Reason) 0x0015) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_RSN_IECAPABILITIES ((CsrWifiSmeIEEE80211Reason) 0x0016) +#define CSR_WIFI_SME_IEEE80211_REASON_DOT1X_AUTH_FAILED ((CsrWifiSmeIEEE80211Reason) 0x0017) +#define CSR_WIFI_SME_IEEE80211_REASON_CIPHER_REJECTED_BY_POLICY ((CsrWifiSmeIEEE80211Reason) 0x0018) +#define CSR_WIFI_SME_IEEE80211_REASON_SERVICE_CHANGE_PRECLUDES_TS ((CsrWifiSmeIEEE80211Reason) 0x001F) +#define CSR_WIFI_SME_IEEE80211_REASON_QOS_UNSPECIFIED_REASON ((CsrWifiSmeIEEE80211Reason) 0x0020) +#define CSR_WIFI_SME_IEEE80211_REASON_QOS_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeIEEE80211Reason) 0x0021) +#define CSR_WIFI_SME_IEEE80211_REASON_QOS_EXCESSIVE_NOT_ACK ((CsrWifiSmeIEEE80211Reason) 0x0022) +#define CSR_WIFI_SME_IEEE80211_REASON_QOS_TXOPLIMIT_EXCEEDED ((CsrWifiSmeIEEE80211Reason) 0x0023) +#define CSR_WIFI_SME_IEEE80211_REASON_QSTA_LEAVING ((CsrWifiSmeIEEE80211Reason) 0x0024) +#define CSR_WIFI_SME_IEEE80211_REASON_END_TS ((CsrWifiSmeIEEE80211Reason) 0x0025) +#define CSR_WIFI_SME_IEEE80211_REASON_END_DLS ((CsrWifiSmeIEEE80211Reason) 0x0025) +#define CSR_WIFI_SME_IEEE80211_REASON_END_BA ((CsrWifiSmeIEEE80211Reason) 0x0025) +#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_TS ((CsrWifiSmeIEEE80211Reason) 0x0026) +#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_BA ((CsrWifiSmeIEEE80211Reason) 0x0026) +#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_DLS ((CsrWifiSmeIEEE80211Reason) 0x0026) +#define CSR_WIFI_SME_IEEE80211_REASON_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x0027) +#define CSR_WIFI_SME_IEEE80211_REASON_STAKEY_MISMATCH ((CsrWifiSmeIEEE80211Reason) 0x002d) +#define CSR_WIFI_SME_IEEE80211_REASON_UNICAST_KEY_NEGOTIATION_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0xf019) +#define CSR_WIFI_SME_IEEE80211_REASON_MULTICAST_KEY_ANNOUNCEMENT_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0xf01a) +#define CSR_WIFI_SME_IEEE80211_REASON_INCOMPATIBLE_UNICAST_KEY_NEGOTIATION_IE ((CsrWifiSmeIEEE80211Reason) 0xf01b) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_MULTICAST_CIPHER ((CsrWifiSmeIEEE80211Reason) 0xf01c) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_UNICAST_CIPHER ((CsrWifiSmeIEEE80211Reason) 0xf01d) +#define CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_WAPI_IE_VERSION ((CsrWifiSmeIEEE80211Reason) 0xf01e) +#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_WAPI_CAPABILITY_IE ((CsrWifiSmeIEEE80211Reason) 0xf01f) +#define CSR_WIFI_SME_IEEE80211_REASON_WAI_CERTIFICATE_AUTHENTICATION_FAILED ((CsrWifiSmeIEEE80211Reason) 0xf020) + +/******************************************************************************* + + NAME + CsrWifiSmeIEEE80211Result + + DESCRIPTION + As definined in the IEEE 802.11 standards + + VALUES + CSR_WIFI_SME_IEEE80211_RESULT_SUCCESS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CAPABILITIES_MISMATCH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REASSOCIATION_DENIED_NO_ASSOCIATION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_EXTERNAL_REASON + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_MISMATCH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_INVALID_AUTHENTICATION_SEQUENCE_NUMBER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHALLENGE_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_OUT_OF_MEMORY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_BASIC_RATES_MISMATCH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_PREAMBLE_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PBCC_MODULATION_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHANNEL_AGILITY_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SPECTRUM_MANAGEMENT_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POWER_CAPABILITY_UNACCEPTABLE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SUPPORTED_CHANNELS_UNACCEPTABLE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_SLOT_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_DSSS_OFDMREQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NO_HT_SUPPORT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_R0KH_UNREACHABLE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PCO_TRANSITION_SUPPORT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_ASSOCIATION_REQUEST_REJECTED_TEMPORARILY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_ROBUST_MANAGEMENT_FRAME_POLICY_VIOLATION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_BANDWIDTH_INSUFFICIENT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POOR_OPERATING_CHANNEL + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_QOS_REQUIRED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_REASON_UNSPECIFIED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PARAMETERS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_WITH_SUGGESTED_TSPEC_CHANGES + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_IE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_GROUP_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_PAIRWISE_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_AKMP + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_UNSUPPORTED_RSN_VERSION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_RSN_CAPABILITY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_SECURITY_POLICY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_FOR_DELAY_PERIOD + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_NOT_ALLOWED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_NOT_PRESENT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_NOT_QSTA + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_LISTEN_INTERVAL_TOO_LARGE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FT_ACTION_FRAME_COUNT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PMKID + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MDIE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FTIE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_QOS_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_WRONG_POLICY + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INSUFFICIENT_BANDWIDTH + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_TSPEC_PARAMETERS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_TIMEOUT + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_TOO_MANY_SIMULTANEOUS_REQUESTS + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_BSS_ALREADY_STARTED_OR_JOINED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_NOT_SUPPORTED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_TRANSMISSION_FAILURE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NOT_AUTHENTICATED + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_RESET_REQUIRED_BEFORE_START + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_LM_INFO_UNAVAILABLE + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_UNICAST_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MULTICAST_CIPHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_UNSUPPORTED_WAPI_IE_VERSION + - See IEEE 802.11 Standard + CSR_WIFI_SME_IEEE80211_RESULT_INVALID_WAPI_CAPABILITY_IE + - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeIEEE80211Result; +#define CSR_WIFI_SME_IEEE80211_RESULT_SUCCESS ((CsrWifiSmeIEEE80211Result) 0x0000) +#define CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_FAILURE ((CsrWifiSmeIEEE80211Result) 0x0001) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CAPABILITIES_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x000a) +#define CSR_WIFI_SME_IEEE80211_RESULT_REASSOCIATION_DENIED_NO_ASSOCIATION ((CsrWifiSmeIEEE80211Result) 0x000b) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_EXTERNAL_REASON ((CsrWifiSmeIEEE80211Result) 0x000c) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x000d) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_INVALID_AUTHENTICATION_SEQUENCE_NUMBER ((CsrWifiSmeIEEE80211Result) 0x000e) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHALLENGE_FAILURE ((CsrWifiSmeIEEE80211Result) 0x000f) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_TIMEOUT ((CsrWifiSmeIEEE80211Result) 0x0010) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_OUT_OF_MEMORY ((CsrWifiSmeIEEE80211Result) 0x0011) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_BASIC_RATES_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x0012) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_PREAMBLE_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0013) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PBCC_MODULATION_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0014) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHANNEL_AGILITY_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0015) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SPECTRUM_MANAGEMENT_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0016) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POWER_CAPABILITY_UNACCEPTABLE ((CsrWifiSmeIEEE80211Result) 0x0017) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SUPPORTED_CHANNELS_UNACCEPTABLE ((CsrWifiSmeIEEE80211Result) 0x0018) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_SLOT_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0019) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_DSSS_OFDMREQUIRED ((CsrWifiSmeIEEE80211Result) 0x001a) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NO_HT_SUPPORT ((CsrWifiSmeIEEE80211Result) 0x001b) +#define CSR_WIFI_SME_IEEE80211_RESULT_R0KH_UNREACHABLE ((CsrWifiSmeIEEE80211Result) 0x001c) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PCO_TRANSITION_SUPPORT ((CsrWifiSmeIEEE80211Result) 0x001d) +#define CSR_WIFI_SME_IEEE80211_RESULT_ASSOCIATION_REQUEST_REJECTED_TEMPORARILY ((CsrWifiSmeIEEE80211Result) 0x001e) +#define CSR_WIFI_SME_IEEE80211_RESULT_ROBUST_MANAGEMENT_FRAME_POLICY_VIOLATION ((CsrWifiSmeIEEE80211Result) 0x001f) +#define CSR_WIFI_SME_IEEE80211_RESULT_FAILURE ((CsrWifiSmeIEEE80211Result) 0x0020) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_BANDWIDTH_INSUFFICIENT ((CsrWifiSmeIEEE80211Result) 0x0021) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POOR_OPERATING_CHANNEL ((CsrWifiSmeIEEE80211Result) 0x0022) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_QOS_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0023) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_REASON_UNSPECIFIED ((CsrWifiSmeIEEE80211Result) 0x0025) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED ((CsrWifiSmeIEEE80211Result) 0x0025) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PARAMETERS ((CsrWifiSmeIEEE80211Result) 0x0026) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_WITH_SUGGESTED_TSPEC_CHANGES ((CsrWifiSmeIEEE80211Result) 0x0027) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_IE ((CsrWifiSmeIEEE80211Result) 0x0028) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_GROUP_CIPHER ((CsrWifiSmeIEEE80211Result) 0x0029) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_PAIRWISE_CIPHER ((CsrWifiSmeIEEE80211Result) 0x002a) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_AKMP ((CsrWifiSmeIEEE80211Result) 0x002b) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_UNSUPPORTED_RSN_VERSION ((CsrWifiSmeIEEE80211Result) 0x002c) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_RSN_CAPABILITY ((CsrWifiSmeIEEE80211Result) 0x002d) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_SECURITY_POLICY ((CsrWifiSmeIEEE80211Result) 0x002e) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_FOR_DELAY_PERIOD ((CsrWifiSmeIEEE80211Result) 0x002f) +#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_ALLOWED ((CsrWifiSmeIEEE80211Result) 0x0030) +#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_PRESENT ((CsrWifiSmeIEEE80211Result) 0x0031) +#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_QSTA ((CsrWifiSmeIEEE80211Result) 0x0032) +#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_LISTEN_INTERVAL_TOO_LARGE ((CsrWifiSmeIEEE80211Result) 0x0033) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FT_ACTION_FRAME_COUNT ((CsrWifiSmeIEEE80211Result) 0x0034) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PMKID ((CsrWifiSmeIEEE80211Result) 0x0035) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MDIE ((CsrWifiSmeIEEE80211Result) 0x0036) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FTIE ((CsrWifiSmeIEEE80211Result) 0x0037) +#define CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_QOS_FAILURE ((CsrWifiSmeIEEE80211Result) 0x00c8) +#define CSR_WIFI_SME_IEEE80211_RESULT_WRONG_POLICY ((CsrWifiSmeIEEE80211Result) 0x00c9) +#define CSR_WIFI_SME_IEEE80211_RESULT_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeIEEE80211Result) 0x00ca) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_TSPEC_PARAMETERS ((CsrWifiSmeIEEE80211Result) 0x00cb) +#define CSR_WIFI_SME_IEEE80211_RESULT_TIMEOUT ((CsrWifiSmeIEEE80211Result) 0x8000) +#define CSR_WIFI_SME_IEEE80211_RESULT_TOO_MANY_SIMULTANEOUS_REQUESTS ((CsrWifiSmeIEEE80211Result) 0x8001) +#define CSR_WIFI_SME_IEEE80211_RESULT_BSS_ALREADY_STARTED_OR_JOINED ((CsrWifiSmeIEEE80211Result) 0x8002) +#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_SUPPORTED ((CsrWifiSmeIEEE80211Result) 0x8003) +#define CSR_WIFI_SME_IEEE80211_RESULT_TRANSMISSION_FAILURE ((CsrWifiSmeIEEE80211Result) 0x8004) +#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NOT_AUTHENTICATED ((CsrWifiSmeIEEE80211Result) 0x8005) +#define CSR_WIFI_SME_IEEE80211_RESULT_RESET_REQUIRED_BEFORE_START ((CsrWifiSmeIEEE80211Result) 0x8006) +#define CSR_WIFI_SME_IEEE80211_RESULT_LM_INFO_UNAVAILABLE ((CsrWifiSmeIEEE80211Result) 0x8007) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_UNICAST_CIPHER ((CsrWifiSmeIEEE80211Result) 0xf02f) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MULTICAST_CIPHER ((CsrWifiSmeIEEE80211Result) 0xf030) +#define CSR_WIFI_SME_IEEE80211_RESULT_UNSUPPORTED_WAPI_IE_VERSION ((CsrWifiSmeIEEE80211Result) 0xf031) +#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_WAPI_CAPABILITY_IE ((CsrWifiSmeIEEE80211Result) 0xf032) + +/******************************************************************************* + + NAME + CsrWifiSmeIndications + + DESCRIPTION + Defines bits for CsrWifiSmeIndicationsMask + + VALUES + CSR_WIFI_SME_INDICATIONS_NONE + - Used to cancel the registrations for receiving indications + CSR_WIFI_SME_INDICATIONS_WIFIOFF + - Used to register for CSR_WIFI_SME_WIFI_OFF_IND events + CSR_WIFI_SME_INDICATIONS_SCANRESULT + - Used to register for CSR_WIFI_SME_SCAN_RESULT_IND events + CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY + - Used to register for CSR_WIFI_SME_CONNECTION_QUALITY_IND + events + CSR_WIFI_SME_INDICATIONS_MEDIASTATUS + - Used to register for CSR_WIFI_SME_MEDIA_STATUS_IND events + CSR_WIFI_SME_INDICATIONS_MICFAILURE + - Used to register for CSR_WIFI_SME_MICFAILURE_IND events + CSR_WIFI_SME_INDICATIONS_PMKIDCANDIDATELIST + - Used to register for CSR_WIFI_SME_PMKIDCANDIDATE_LIST_IND + events + CSR_WIFI_SME_INDICATIONS_TSPEC + - Used to register for CSR_WIFI_SME_TSPEC_IND events + CSR_WIFI_SME_INDICATIONS_ROAMSTART + - Used to register for CSR_WIFI_SME_ROAM_START_IND events + CSR_WIFI_SME_INDICATIONS_ROAMCOMPLETE + - Used to register for CSR_WIFI_SME_ROAM_COMPLETE_IND events + CSR_WIFI_SME_INDICATIONS_ASSOCIATIONSTART + - Used to register for CSR_WIFI_SME_ASSOCIATION_START_IND + events + CSR_WIFI_SME_INDICATIONS_ASSOCIATIONCOMPLETE + - Used to register for CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND + events + CSR_WIFI_SME_INDICATIONS_IBSSSTATION + - Used to register for CSR_WIFI_SME_IBSS_STATION_IND events + CSR_WIFI_SME_INDICATIONS_WIFION + - Used to register for CSR_WIFI_SME_WIFI_ON_IND events + CSR_WIFI_SME_INDICATIONS_ERROR + - Used to register for CSR_WIFI_SME_ERROR_IND events + CSR_WIFI_SME_INDICATIONS_INFO + - Used to register for CSR_WIFI_SME_INFO_IND events + CSR_WIFI_SME_INDICATIONS_COREDUMP + - Used to register for CSR_WIFI_SME_CORE_DUMP_IND events + CSR_WIFI_SME_INDICATIONS_ALL + - Used to register for all available indications + +*******************************************************************************/ +typedef CsrUint32 CsrWifiSmeIndications; +#define CSR_WIFI_SME_INDICATIONS_NONE ((CsrWifiSmeIndications) 0x00000000) +#define CSR_WIFI_SME_INDICATIONS_WIFIOFF ((CsrWifiSmeIndications) 0x00000001) +#define CSR_WIFI_SME_INDICATIONS_SCANRESULT ((CsrWifiSmeIndications) 0x00000002) +#define CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY ((CsrWifiSmeIndications) 0x00000004) +#define CSR_WIFI_SME_INDICATIONS_MEDIASTATUS ((CsrWifiSmeIndications) 0x00000008) +#define CSR_WIFI_SME_INDICATIONS_MICFAILURE ((CsrWifiSmeIndications) 0x00000010) +#define CSR_WIFI_SME_INDICATIONS_PMKIDCANDIDATELIST ((CsrWifiSmeIndications) 0x00000020) +#define CSR_WIFI_SME_INDICATIONS_TSPEC ((CsrWifiSmeIndications) 0x00000040) +#define CSR_WIFI_SME_INDICATIONS_ROAMSTART ((CsrWifiSmeIndications) 0x00000080) +#define CSR_WIFI_SME_INDICATIONS_ROAMCOMPLETE ((CsrWifiSmeIndications) 0x00000100) +#define CSR_WIFI_SME_INDICATIONS_ASSOCIATIONSTART ((CsrWifiSmeIndications) 0x00000200) +#define CSR_WIFI_SME_INDICATIONS_ASSOCIATIONCOMPLETE ((CsrWifiSmeIndications) 0x00000400) +#define CSR_WIFI_SME_INDICATIONS_IBSSSTATION ((CsrWifiSmeIndications) 0x00000800) +#define CSR_WIFI_SME_INDICATIONS_WIFION ((CsrWifiSmeIndications) 0x00001000) +#define CSR_WIFI_SME_INDICATIONS_ERROR ((CsrWifiSmeIndications) 0x00002000) +#define CSR_WIFI_SME_INDICATIONS_INFO ((CsrWifiSmeIndications) 0x00004000) +#define CSR_WIFI_SME_INDICATIONS_COREDUMP ((CsrWifiSmeIndications) 0x00008000) +#define CSR_WIFI_SME_INDICATIONS_ALL ((CsrWifiSmeIndications) 0xFFFFFFFF) + +/******************************************************************************* + + NAME + CsrWifiSmeKeyType + + DESCRIPTION + Indicates the type of the key + + VALUES + CSR_WIFI_SME_KEY_TYPE_GROUP - Key for broadcast communication + CSR_WIFI_SME_KEY_TYPE_PAIRWISE - Key for unicast communication + CSR_WIFI_SME_KEY_TYPE_STAKEY - Key for direct link communication to + another station in infrastructure networks + CSR_WIFI_SME_KEY_TYPE_IGTK - Integrity Group Temporal Key + CSR_WIFI_SME_KEY_TYPE_CCKM - Key for Cisco Centralized Key Management + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeKeyType; +#define CSR_WIFI_SME_KEY_TYPE_GROUP ((CsrWifiSmeKeyType) 0x00) +#define CSR_WIFI_SME_KEY_TYPE_PAIRWISE ((CsrWifiSmeKeyType) 0x01) +#define CSR_WIFI_SME_KEY_TYPE_STAKEY ((CsrWifiSmeKeyType) 0x02) +#define CSR_WIFI_SME_KEY_TYPE_IGTK ((CsrWifiSmeKeyType) 0x03) +#define CSR_WIFI_SME_KEY_TYPE_CCKM ((CsrWifiSmeKeyType) 0x04) + +/******************************************************************************* + + NAME + CsrWifiSmeListAction + + DESCRIPTION + Identifies the type of action to be performed on a list of items + The values of this type are used across the NME/SME/Router API's and they + must be kept consistent with the corresponding types in the .xml of the + ottherinterfaces + + VALUES + CSR_WIFI_SME_LIST_ACTION_GET - Retrieve the current list of items + CSR_WIFI_SME_LIST_ACTION_ADD - Add one or more items + CSR_WIFI_SME_LIST_ACTION_REMOVE - Remove one or more items + CSR_WIFI_SME_LIST_ACTION_FLUSH - Remove all items + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeListAction; +#define CSR_WIFI_SME_LIST_ACTION_GET ((CsrWifiSmeListAction) 0x00) +#define CSR_WIFI_SME_LIST_ACTION_ADD ((CsrWifiSmeListAction) 0x01) +#define CSR_WIFI_SME_LIST_ACTION_REMOVE ((CsrWifiSmeListAction) 0x02) +#define CSR_WIFI_SME_LIST_ACTION_FLUSH ((CsrWifiSmeListAction) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeMediaStatus + + DESCRIPTION + Indicates the connection status + The values of this type are used across the NME/SME/Router API's and they + must be kept consistent with the corresponding types in the .xml of the + ottherinterfaces + + VALUES + CSR_WIFI_SME_MEDIA_STATUS_CONNECTED + - Value CSR_WIFI_SME_MEDIA_STATUS_CONNECTED can happen in two + situations: + * A network connection is established. Specifically, this is + when the MLME_ASSOCIATION completes or the first peer + relationship is established in an IBSS. In a WPA/WPA2 + network, this indicates that the stack is ready to perform + the 4-way handshake or 802.1x authentication if CSR NME + security library is not used. If CSR NME security library + is used this indicates, completion of 4way handshake or + 802.1x authentication + * The SME roams to another AP on the same ESS + During the AP operation, it indicates that the peer station + is connected to the AP and is ready for data transfer. + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED + - Value CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED can happen in + two situations: + * when the connection to a network is lost and there is no + alternative on the same ESS to roam to + * when a CSR_WIFI_SME_DISCONNECT_REQ request is issued + During AP or P2PGO operation, it indicates that the peer + station has disconnected from the AP + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeMediaStatus; +#define CSR_WIFI_SME_MEDIA_STATUS_CONNECTED ((CsrWifiSmeMediaStatus) 0x00) +#define CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED ((CsrWifiSmeMediaStatus) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeP2pCapability + + DESCRIPTION + Defines P2P Device Capabilities + + VALUES + CSR_WIFI_SME_P2P_SERVICE_DISCOVERY_CAPABILITY + - This field is set to 1 if the P2P Device supports Service + Discovery, and to 0 otherwise + CSR_WIFI_SME_P2P_CLIENT_DISCOVERABILITY_CAPABILITY + - This field is set to 1 when the P2P Device supports P2P + Client Discoverability, and to 0 otherwise. + CSR_WIFI_SME_P2P_CONCURRENT_OPERATION_CAPABILITY + - This field is set to 1 when the P2P Device supports + Concurrent Operation with WLAN, and to 0 otherwise. + CSR_WIFI_SME_P2P_MANAGED_DEVICE_CAPABILITY + - This field is set to 1 when the P2P interface of the P2P + Device is capable of being managed by the WLAN + (infrastructure network) based on P2P coexistence + parameters, and to 0 otherwise + CSR_WIFI_SME_P2P_INVITAION_CAPABILITY + - This field is set to 1 if the P2P Device is capable of + processing P2P Invitation Procedure signaling, and to 0 + otherwise. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pCapability; +#define CSR_WIFI_SME_P2P_SERVICE_DISCOVERY_CAPABILITY ((CsrWifiSmeP2pCapability) 0x01) +#define CSR_WIFI_SME_P2P_CLIENT_DISCOVERABILITY_CAPABILITY ((CsrWifiSmeP2pCapability) 0x02) +#define CSR_WIFI_SME_P2P_CONCURRENT_OPERATION_CAPABILITY ((CsrWifiSmeP2pCapability) 0x04) +#define CSR_WIFI_SME_P2P_MANAGED_DEVICE_CAPABILITY ((CsrWifiSmeP2pCapability) 0x08) +#define CSR_WIFI_SME_P2P_INVITAION_CAPABILITY ((CsrWifiSmeP2pCapability) 0x20) + +/******************************************************************************* + + NAME + CsrWifiSmeP2pGroupCapability + + DESCRIPTION + Define bits for P2P Group Capability + + VALUES + CSR_WIFI_P2P_GRP_CAP_GO + - Indicates if the local device has become a GO after GO + negotiation + CSR_WIFI_P2P_GRP_CAP_PERSISTENT + - Persistent group + CSR_WIFI_P2P_GRP_CAP_INTRABSS_DIST + - Intra-BSS data distribution support + CSR_WIFI_P2P_GRP_CAP_CROSS_CONN + - Support of cross connection + CSR_WIFI_P2P_GRP_CAP_PERSISTENT_RECONNECT + - Support of persistent reconnect + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pGroupCapability; +#define CSR_WIFI_P2P_GRP_CAP_GO ((CsrWifiSmeP2pGroupCapability) 0x01) +#define CSR_WIFI_P2P_GRP_CAP_PERSISTENT ((CsrWifiSmeP2pGroupCapability) 0x02) +#define CSR_WIFI_P2P_GRP_CAP_INTRABSS_DIST ((CsrWifiSmeP2pGroupCapability) 0x08) +#define CSR_WIFI_P2P_GRP_CAP_CROSS_CONN ((CsrWifiSmeP2pGroupCapability) 0x10) +#define CSR_WIFI_P2P_GRP_CAP_PERSISTENT_RECONNECT ((CsrWifiSmeP2pGroupCapability) 0x20) + +/******************************************************************************* + + NAME + CsrWifiSmeP2pNoaConfigMethod + + DESCRIPTION + Notice of Absece Configuration + + VALUES + CSR_WIFI_P2P_NOA_NONE - Do not use NOA + CSR_WIFI_P2P_NOA_AUTONOMOUS - NOA based on the traffic analysis + CSR_WIFI_P2P_NOA_USER_DEFINED - NOA as specified by the user + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pNoaConfigMethod; +#define CSR_WIFI_P2P_NOA_NONE ((CsrWifiSmeP2pNoaConfigMethod) 0x00) +#define CSR_WIFI_P2P_NOA_AUTONOMOUS ((CsrWifiSmeP2pNoaConfigMethod) 0x01) +#define CSR_WIFI_P2P_NOA_USER_DEFINED ((CsrWifiSmeP2pNoaConfigMethod) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeP2pRole + + DESCRIPTION + Definition of roles for a P2P Device + + VALUES + CSR_WIFI_SME_P2P_ROLE_NONE - A non-P2PDevice device + CSR_WIFI_SME_P2P_ROLE_STANDALONE - A Standalone P2P device + CSR_WIFI_SME_P2P_ROLE_GO - Role Assumed is that of a Group Owner + within a P2P Group + CSR_WIFI_SME_P2P_ROLE_CLI - Role Assumed is that of a P2P Client + within a P2P Group + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pRole; +#define CSR_WIFI_SME_P2P_ROLE_NONE ((CsrWifiSmeP2pRole) 0x00) +#define CSR_WIFI_SME_P2P_ROLE_STANDALONE ((CsrWifiSmeP2pRole) 0x01) +#define CSR_WIFI_SME_P2P_ROLE_GO ((CsrWifiSmeP2pRole) 0x02) +#define CSR_WIFI_SME_P2P_ROLE_CLI ((CsrWifiSmeP2pRole) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeP2pStatus + + DESCRIPTION + This data type enumerates the outcome of P2P procedure + + VALUES + CSR_WIFI_SME_P2P_STATUS_SUCCESS + - Success + CSR_WIFI_SME_P2P_STATUS_FAIL_INFO_UNAVAILABLE + - Fail; information is currently unavailable + CSR_WIFI_SME_P2P_STATUS_FAIL_INCOMPATIBLE_PARAM + - Fail; incompatible parameters + CSR_WIFI_SME_P2P_STATUS_FAIL_LIMIT_REACHED + - Fail; limit reached + CSR_WIFI_SME_P2P_STATUS_FAIL_INVALID_PARAM + - Fail; invalid parameters + CSR_WIFI_SME_P2P_STATUS_FAIL_ACCOMODATE + - Fail; unable to accommodate request + CSR_WIFI_SME_P2P_STATUS_FAIL_PREV_ERROR + - Fail; previous protocol error, or disruptive behavior + CSR_WIFI_SME_P2P_STATUS_FAIL_COMMON_CHANNELS + - Fail; no common channels + CSR_WIFI_SME_P2P_STATUS_FAIL_UNKNOWN_GROUP + - Fail; unknown P2P Group + CSR_WIFI_SME_P2P_STATUS_FAIL_GO_INTENT + - Fail: both P2P Devices indicated an Intent of 15 in Group + Owner Negotiation + CSR_WIFI_SME_P2P_STATUS_FAIL_PROVISION_METHOD_INCOMPATIBLE + - Fail; incompatible provisioning method + CSR_WIFI_SME_P2P_STATUS_FAIL_REJECT + - Fail: rejected by user + CSR_WIFI_SME_P2P_STATUS_FAIL_RESERVED + - Fail; Status Reserved + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pStatus; +#define CSR_WIFI_SME_P2P_STATUS_SUCCESS ((CsrWifiSmeP2pStatus) 0x00) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_INFO_UNAVAILABLE ((CsrWifiSmeP2pStatus) 0x01) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_INCOMPATIBLE_PARAM ((CsrWifiSmeP2pStatus) 0x02) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_LIMIT_REACHED ((CsrWifiSmeP2pStatus) 0x03) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_INVALID_PARAM ((CsrWifiSmeP2pStatus) 0x04) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_ACCOMODATE ((CsrWifiSmeP2pStatus) 0x05) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_PREV_ERROR ((CsrWifiSmeP2pStatus) 0x06) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_COMMON_CHANNELS ((CsrWifiSmeP2pStatus) 0x07) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_UNKNOWN_GROUP ((CsrWifiSmeP2pStatus) 0x08) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_GO_INTENT ((CsrWifiSmeP2pStatus) 0x09) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_PROVISION_METHOD_INCOMPATIBLE ((CsrWifiSmeP2pStatus) 0x0A) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_REJECT ((CsrWifiSmeP2pStatus) 0x0B) +#define CSR_WIFI_SME_P2P_STATUS_FAIL_RESERVED ((CsrWifiSmeP2pStatus) 0xFF) + +/******************************************************************************* + + NAME + CsrWifiSmePacketFilterMode + + DESCRIPTION + Options for the filter mode parameter. + The Values here match the HIP interface + + VALUES + CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_OUT + - Broadcast packets are always reported to the host unless + they match at least one of the specified TCLAS IEs. + CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_IN + - Broadcast packets are reported to the host only if they + match at least one of the specified TCLAS IEs. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmePacketFilterMode; +#define CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_OUT ((CsrWifiSmePacketFilterMode) 0x00) +#define CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_IN ((CsrWifiSmePacketFilterMode) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmePowerSaveLevel + + DESCRIPTION + Power Save Level options as defined in the IEEE 802.11 standards + First 3 values are set to match the mlme PowerManagementMode + + VALUES + CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW - No power save: the driver will remain + active at all times + CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH - Enter power save after all packets in + the queues are transmitted and received + CSR_WIFI_SME_POWER_SAVE_LEVEL_MED - Enter power save after all packets in + the queues are transmitted and received + and a further configurable delay + (default 1s) has elapsed + CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO - The SME will decide when to enter power + save mode according to the traffic + analysis + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmePowerSaveLevel; +#define CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW ((CsrWifiSmePowerSaveLevel) 0x00) +#define CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH ((CsrWifiSmePowerSaveLevel) 0x01) +#define CSR_WIFI_SME_POWER_SAVE_LEVEL_MED ((CsrWifiSmePowerSaveLevel) 0x02) +#define CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO ((CsrWifiSmePowerSaveLevel) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmePreambleType + + DESCRIPTION + SME Preamble Types + + VALUES + CSR_WIFI_SME_USE_LONG_PREAMBLE - Use legacy (long) preamble + CSR_WIFI_SME_USE_SHORT_PREAMBLE - Use short PPDU format + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmePreambleType; +#define CSR_WIFI_SME_USE_LONG_PREAMBLE ((CsrWifiSmePreambleType) 0x00) +#define CSR_WIFI_SME_USE_SHORT_PREAMBLE ((CsrWifiSmePreambleType) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeRadioIF + + DESCRIPTION + Indicates the frequency + + VALUES + CSR_WIFI_SME_RADIO_IF_GHZ_2_4 - Indicates the 2.4 GHZ frequency + CSR_WIFI_SME_RADIO_IF_GHZ_5_0 - Future use: currently not supported + CSR_WIFI_SME_RADIO_IF_BOTH - Future use: currently not supported + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeRadioIF; +#define CSR_WIFI_SME_RADIO_IF_GHZ_2_4 ((CsrWifiSmeRadioIF) 0x01) +#define CSR_WIFI_SME_RADIO_IF_GHZ_5_0 ((CsrWifiSmeRadioIF) 0x02) +#define CSR_WIFI_SME_RADIO_IF_BOTH ((CsrWifiSmeRadioIF) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomain + + DESCRIPTION + Indicates the regulatory domain as defined in IEEE 802.11 standards + + VALUES + CSR_WIFI_SME_REGULATORY_DOMAIN_OTHER + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_FCC + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_IC + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_ETSI + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_SPAIN + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_FRANCE + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_JAPAN + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_JAPANBIS + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_CHINA + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_CHINABIS + - See IEEE 802.11 Standard + CSR_WIFI_SME_REGULATORY_DOMAIN_NONE + - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeRegulatoryDomain; +#define CSR_WIFI_SME_REGULATORY_DOMAIN_OTHER ((CsrWifiSmeRegulatoryDomain) 0x00) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_FCC ((CsrWifiSmeRegulatoryDomain) 0x10) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_IC ((CsrWifiSmeRegulatoryDomain) 0x20) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_ETSI ((CsrWifiSmeRegulatoryDomain) 0x30) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_SPAIN ((CsrWifiSmeRegulatoryDomain) 0x31) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_FRANCE ((CsrWifiSmeRegulatoryDomain) 0x32) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_JAPAN ((CsrWifiSmeRegulatoryDomain) 0x40) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_JAPANBIS ((CsrWifiSmeRegulatoryDomain) 0x41) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_CHINA ((CsrWifiSmeRegulatoryDomain) 0x50) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_CHINABIS ((CsrWifiSmeRegulatoryDomain) 0x51) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_NONE ((CsrWifiSmeRegulatoryDomain) 0xFF) + +/******************************************************************************* + + NAME + CsrWifiSmeRoamReason + + DESCRIPTION + Indicates the reason for roaming + + VALUES + CSR_WIFI_SME_ROAM_REASON_BEACONLOST + - The station cannot receive the beacon signal any more + CSR_WIFI_SME_ROAM_REASON_DISASSOCIATED + - The station has been disassociated + CSR_WIFI_SME_ROAM_REASON_DEAUTHENTICATED + - The station has been deauthenticated + CSR_WIFI_SME_ROAM_REASON_BETTERAPFOUND + - A better AP has been found + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeRoamReason; +#define CSR_WIFI_SME_ROAM_REASON_BEACONLOST ((CsrWifiSmeRoamReason) 0x00) +#define CSR_WIFI_SME_ROAM_REASON_DISASSOCIATED ((CsrWifiSmeRoamReason) 0x01) +#define CSR_WIFI_SME_ROAM_REASON_DEAUTHENTICATED ((CsrWifiSmeRoamReason) 0x02) +#define CSR_WIFI_SME_ROAM_REASON_BETTERAPFOUND ((CsrWifiSmeRoamReason) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeScanType + + DESCRIPTION + Identifies the type of scan to be performed + + VALUES + CSR_WIFI_SME_SCAN_TYPE_ALL - Scan actively or passively according to the + regulatory domain restrictions + CSR_WIFI_SME_SCAN_TYPE_ACTIVE - Scan actively only: send probes and listen + for answers + CSR_WIFI_SME_SCAN_TYPE_PASSIVE - Scan passively only: listen for beacon + messages + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeScanType; +#define CSR_WIFI_SME_SCAN_TYPE_ALL ((CsrWifiSmeScanType) 0x00) +#define CSR_WIFI_SME_SCAN_TYPE_ACTIVE ((CsrWifiSmeScanType) 0x01) +#define CSR_WIFI_SME_SCAN_TYPE_PASSIVE ((CsrWifiSmeScanType) 0x02) + +/******************************************************************************* + + NAME + CsrWifiSmeTrafficType + + DESCRIPTION + Identifies the type of traffic going on on the connection. + The values of this type are used across the NME/SME/Router API's and they + must be kept consistent with the corresponding types in the .xml of the + ottherinterfaces + + VALUES + CSR_WIFI_SME_TRAFFIC_TYPE_OCCASIONAL + - During the last 30 seconds there were fewer than 20 packets + per seconds in each second in both directions + CSR_WIFI_SME_TRAFFIC_TYPE_BURSTY + - During the last 30 seconds there was at least one second + during which more than 20 packets were received in either + direction + CSR_WIFI_SME_TRAFFIC_TYPE_PERIODIC + - During the last 5 seconds there were at least 10 packets + received each second and a defined period for the traffic + can be recognized + CSR_WIFI_SME_TRAFFIC_TYPE_CONTINUOUS + - During the last 5 seconds there were at least 20 packets + received each second in either direction + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeTrafficType; +#define CSR_WIFI_SME_TRAFFIC_TYPE_OCCASIONAL ((CsrWifiSmeTrafficType) 0x00) +#define CSR_WIFI_SME_TRAFFIC_TYPE_BURSTY ((CsrWifiSmeTrafficType) 0x01) +#define CSR_WIFI_SME_TRAFFIC_TYPE_PERIODIC ((CsrWifiSmeTrafficType) 0x02) +#define CSR_WIFI_SME_TRAFFIC_TYPE_CONTINUOUS ((CsrWifiSmeTrafficType) 0x03) + +/******************************************************************************* + + NAME + CsrWifiSmeTspecCtrl + + DESCRIPTION + Defines bits for CsrWifiSmeTspecCtrlMask for additional CCX configuration. + CURRENTLY NOT SUPPORTED. + + VALUES + CSR_WIFI_SME_TSPEC_CTRL_STRICT + - No automatic negotiation + CSR_WIFI_SME_TSPEC_CTRL_CCX_SIGNALLING + - Signalling TSPEC + CSR_WIFI_SME_TSPEC_CTRL_CCX_VOICE + - Voice traffic TSPEC + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeTspecCtrl; +#define CSR_WIFI_SME_TSPEC_CTRL_STRICT ((CsrWifiSmeTspecCtrl) 0x01) +#define CSR_WIFI_SME_TSPEC_CTRL_CCX_SIGNALLING ((CsrWifiSmeTspecCtrl) 0x02) +#define CSR_WIFI_SME_TSPEC_CTRL_CCX_VOICE ((CsrWifiSmeTspecCtrl) 0x04) + +/******************************************************************************* + + NAME + CsrWifiSmeTspecResultCode + + DESCRIPTION + Defines the result of the TSPEC exchanges with the AP + + VALUES + CSR_WIFI_SME_TSPEC_RESULT_SUCCESS + - TSPEC command has been processed correctly + CSR_WIFI_SME_TSPEC_RESULT_UNSPECIFIED_QOS_FAILURE + - The Access Point reported a failure + CSR_WIFI_SME_TSPEC_RESULT_FAILURE + - Internal failure in the SME + CSR_WIFI_SME_TSPEC_RESULT_INVALID_TSPEC_PARAMETERS + - The TSPEC parameters are invalid + CSR_WIFI_SME_TSPEC_RESULT_INVALID_TCLAS_PARAMETERS + - The TCLASS parameters are invalid + CSR_WIFI_SME_TSPEC_RESULT_INSUFFICIENT_BANDWIDTH + - As specified by the WMM Spec + CSR_WIFI_SME_TSPEC_RESULT_WRONG_POLICY + - As specified by the WMM Spec + CSR_WIFI_SME_TSPEC_RESULT_REJECTED_WITH_SUGGESTED_CHANGES + - As specified by the WMM Spec + CSR_WIFI_SME_TSPEC_RESULT_TIMEOUT + - The TSPEC negotiation timed out + CSR_WIFI_SME_TSPEC_RESULT_NOT_SUPPORTED + - The Access Point does not support the TSPEC + CSR_WIFI_SME_TSPEC_RESULT_IE_LENGTH_INCORRECT + - The length of the TSPEC is not correct + CSR_WIFI_SME_TSPEC_RESULT_INVALID_TRANSACTION_ID + - The TSPEC transaction id is not in the list + CSR_WIFI_SME_TSPEC_RESULT_INSTALLED + - The TSPEC has been installed and it is now active. + CSR_WIFI_SME_TSPEC_RESULT_TID_ALREADY_INSTALLED + - The Traffic ID has already been installed + CSR_WIFI_SME_TSPEC_RESULT_TSPEC_REMOTELY_DELETED + - The AP has deleted the TSPEC + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeTspecResultCode; +#define CSR_WIFI_SME_TSPEC_RESULT_SUCCESS ((CsrWifiSmeTspecResultCode) 0x00) +#define CSR_WIFI_SME_TSPEC_RESULT_UNSPECIFIED_QOS_FAILURE ((CsrWifiSmeTspecResultCode) 0x01) +#define CSR_WIFI_SME_TSPEC_RESULT_FAILURE ((CsrWifiSmeTspecResultCode) 0x02) +#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TSPEC_PARAMETERS ((CsrWifiSmeTspecResultCode) 0x05) +#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TCLAS_PARAMETERS ((CsrWifiSmeTspecResultCode) 0x06) +#define CSR_WIFI_SME_TSPEC_RESULT_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeTspecResultCode) 0x07) +#define CSR_WIFI_SME_TSPEC_RESULT_WRONG_POLICY ((CsrWifiSmeTspecResultCode) 0x08) +#define CSR_WIFI_SME_TSPEC_RESULT_REJECTED_WITH_SUGGESTED_CHANGES ((CsrWifiSmeTspecResultCode) 0x09) +#define CSR_WIFI_SME_TSPEC_RESULT_TIMEOUT ((CsrWifiSmeTspecResultCode) 0x0D) +#define CSR_WIFI_SME_TSPEC_RESULT_NOT_SUPPORTED ((CsrWifiSmeTspecResultCode) 0x0E) +#define CSR_WIFI_SME_TSPEC_RESULT_IE_LENGTH_INCORRECT ((CsrWifiSmeTspecResultCode) 0x10) +#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TRANSACTION_ID ((CsrWifiSmeTspecResultCode) 0x11) +#define CSR_WIFI_SME_TSPEC_RESULT_INSTALLED ((CsrWifiSmeTspecResultCode) 0x12) +#define CSR_WIFI_SME_TSPEC_RESULT_TID_ALREADY_INSTALLED ((CsrWifiSmeTspecResultCode) 0x13) +#define CSR_WIFI_SME_TSPEC_RESULT_TSPEC_REMOTELY_DELETED ((CsrWifiSmeTspecResultCode) 0x14) + +/******************************************************************************* + + NAME + CsrWifiSmeWepAuthMode + + DESCRIPTION + Define bits for CsrWifiSmeWepAuthMode + + VALUES + CSR_WIFI_SME_WEP_AUTH_MODE_OPEN - Open-WEP enabled network + CSR_WIFI_SME_WEP_AUTH_MODE_SHARED - Shared-key WEP enabled network. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWepAuthMode; +#define CSR_WIFI_SME_WEP_AUTH_MODE_OPEN ((CsrWifiSmeWepAuthMode) 0x00) +#define CSR_WIFI_SME_WEP_AUTH_MODE_SHARED ((CsrWifiSmeWepAuthMode) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeWepCredentialType + + DESCRIPTION + Definition of types of WEP Credentials + + VALUES + CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64 + - WEP 64 credential + CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128 + - WEP 128 credential + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWepCredentialType; +#define CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64 ((CsrWifiSmeWepCredentialType) 0x00) +#define CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128 ((CsrWifiSmeWepCredentialType) 0x01) + +/******************************************************************************* + + NAME + CsrWifiSmeWmmMode + + DESCRIPTION + Defines bits for wmmModeMask: enable/disable WMM features. + + VALUES + CSR_WIFI_SME_WMM_MODE_DISABLED - Disables the WMM features. + CSR_WIFI_SME_WMM_MODE_AC_ENABLED - Enables support for WMM-AC. + CSR_WIFI_SME_WMM_MODE_PS_ENABLED - Enables support for WMM Power Save. + CSR_WIFI_SME_WMM_MODE_SA_ENABLED - Currently not supported + CSR_WIFI_SME_WMM_MODE_ENABLED - Enables support for all currently + available WMM features. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWmmMode; +#define CSR_WIFI_SME_WMM_MODE_DISABLED ((CsrWifiSmeWmmMode) 0x00) +#define CSR_WIFI_SME_WMM_MODE_AC_ENABLED ((CsrWifiSmeWmmMode) 0x01) +#define CSR_WIFI_SME_WMM_MODE_PS_ENABLED ((CsrWifiSmeWmmMode) 0x02) +#define CSR_WIFI_SME_WMM_MODE_SA_ENABLED ((CsrWifiSmeWmmMode) 0x04) +#define CSR_WIFI_SME_WMM_MODE_ENABLED ((CsrWifiSmeWmmMode) 0xFF) + +/******************************************************************************* + + NAME + CsrWifiSmeWmmQosInfo + + DESCRIPTION + Defines bits for the QoS Info Octect as defined in the WMM specification. + The first four values define one bit each that can be set or cleared. + Each of the last four values define all the remaining 4 bits and only one + of them at the time shall be used. + For more information, see 'WMM (including WMM Power Save) Specification - + Version 1.1' and 'UniFi Configuring WMM and WMM-PS, Application Note'. + + VALUES + CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_ALL + - WMM AP may deliver all buffered frames + CSR_WIFI_SME_WMM_QOS_INFO_AC_VO + - Enable UAPSD(both trigger and delivery) for Voice Access + Category + CSR_WIFI_SME_WMM_QOS_INFO_AC_VI + - Enable UAPSD(both trigger and delivery) for Video Access + Category + CSR_WIFI_SME_WMM_QOS_INFO_AC_BK + - Enable UAPSD(both trigger and delivery) for Background + Access Category + CSR_WIFI_SME_WMM_QOS_INFO_AC_BE + - Enable UAPSD(both trigger and delivery) for Best Effort + Access Category + CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_TWO + - WMM AP may deliver a maximum of 2 buffered frames (MSDUs + and MMPDUs) per USP + CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_FOUR + - WMM AP may deliver a maximum of 4 buffered frames (MSDUs + and MMPDUs) per USP + CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_SIX + - WMM AP may deliver a maximum of 6 buffered frames (MSDUs + and MMPDUs) per USP + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWmmQosInfo; +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_ALL ((CsrWifiSmeWmmQosInfo) 0x00) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_VO ((CsrWifiSmeWmmQosInfo) 0x01) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_VI ((CsrWifiSmeWmmQosInfo) 0x02) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_BK ((CsrWifiSmeWmmQosInfo) 0x04) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_BE ((CsrWifiSmeWmmQosInfo) 0x08) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_TWO ((CsrWifiSmeWmmQosInfo) 0x20) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_FOUR ((CsrWifiSmeWmmQosInfo) 0x40) +#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_SIX ((CsrWifiSmeWmmQosInfo) 0x60) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigType + + DESCRIPTION + WPS config methods supported/used by a device + + VALUES + CSR_WIFI_WPS_CONFIG_LABEL + - Label + CSR_WIFI_WPS_CONFIG_DISPLAY + - Display + CSR_WIFI_WPS_CONFIG_EXT_NFC + - External NFC : Not supported in this release + CSR_WIFI_WPS_CONFIG_INT_NFC + - Internal NFC : Not supported in this release + CSR_WIFI_WPS_CONFIG_NFC_IFACE + - NFC interface : Not supported in this release + CSR_WIFI_WPS_CONFIG_PBC + - PBC + CSR_WIFI_WPS_CONFIG_KEYPAD + - KeyPad + CSR_WIFI_WPS_CONFIG_VIRTUAL_PBC + - PBC through software user interface + CSR_WIFI_WPS_CONFIG_PHYSICAL_PBC + - Physical PBC + CSR_WIFI_WPS_CONFIG_VIRTUAL_DISPLAY + - Virtual Display : via html config page etc + CSR_WIFI_WPS_CONFIG_PHYSICAL_DISPLAY + - Physical Display : Attached to the device + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeWpsConfigType; +#define CSR_WIFI_WPS_CONFIG_LABEL ((CsrWifiSmeWpsConfigType) 0x0004) +#define CSR_WIFI_WPS_CONFIG_DISPLAY ((CsrWifiSmeWpsConfigType) 0x0008) +#define CSR_WIFI_WPS_CONFIG_EXT_NFC ((CsrWifiSmeWpsConfigType) 0x0010) +#define CSR_WIFI_WPS_CONFIG_INT_NFC ((CsrWifiSmeWpsConfigType) 0x0020) +#define CSR_WIFI_WPS_CONFIG_NFC_IFACE ((CsrWifiSmeWpsConfigType) 0x0040) +#define CSR_WIFI_WPS_CONFIG_PBC ((CsrWifiSmeWpsConfigType) 0x0080) +#define CSR_WIFI_WPS_CONFIG_KEYPAD ((CsrWifiSmeWpsConfigType) 0x0100) +#define CSR_WIFI_WPS_CONFIG_VIRTUAL_PBC ((CsrWifiSmeWpsConfigType) 0x0280) +#define CSR_WIFI_WPS_CONFIG_PHYSICAL_PBC ((CsrWifiSmeWpsConfigType) 0x0480) +#define CSR_WIFI_WPS_CONFIG_VIRTUAL_DISPLAY ((CsrWifiSmeWpsConfigType) 0x2008) +#define CSR_WIFI_WPS_CONFIG_PHYSICAL_DISPLAY ((CsrWifiSmeWpsConfigType) 0x4008) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsDeviceCategory + + DESCRIPTION + Wps Primary Device Types + + VALUES + CSR_WIFI_SME_WPS_CATEGORY_UNSPECIFIED + - Unspecified. + CSR_WIFI_SME_WPS_CATEGORY_COMPUTER + - Computer. + CSR_WIFI_SME_WPS_CATEGORY_INPUT_DEV + - Input device + CSR_WIFI_SME_WPS_CATEGORY_PRT_SCAN_FX_CP + - Printer Scanner Fax Copier etc + CSR_WIFI_SME_WPS_CATEGORY_CAMERA + - Camera + CSR_WIFI_SME_WPS_CATEGORY_STORAGE + - Storage + CSR_WIFI_SME_WPS_CATEGORY_NET_INFRA + - Net Infra + CSR_WIFI_SME_WPS_CATEGORY_DISPLAY + - Display + CSR_WIFI_SME_WPS_CATEGORY_MULTIMEDIA + - Multimedia + CSR_WIFI_SME_WPS_CATEGORY_GAMING + - Gaming. + CSR_WIFI_SME_WPS_CATEGORY_TELEPHONE + - Telephone. + CSR_WIFI_SME_WPS_CATEGORY_AUDIO + - Audio + CSR_WIFI_SME_WPS_CATEOARY_OTHERS + - Others. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWpsDeviceCategory; +#define CSR_WIFI_SME_WPS_CATEGORY_UNSPECIFIED ((CsrWifiSmeWpsDeviceCategory) 0x00) +#define CSR_WIFI_SME_WPS_CATEGORY_COMPUTER ((CsrWifiSmeWpsDeviceCategory) 0x01) +#define CSR_WIFI_SME_WPS_CATEGORY_INPUT_DEV ((CsrWifiSmeWpsDeviceCategory) 0x02) +#define CSR_WIFI_SME_WPS_CATEGORY_PRT_SCAN_FX_CP ((CsrWifiSmeWpsDeviceCategory) 0x03) +#define CSR_WIFI_SME_WPS_CATEGORY_CAMERA ((CsrWifiSmeWpsDeviceCategory) 0x04) +#define CSR_WIFI_SME_WPS_CATEGORY_STORAGE ((CsrWifiSmeWpsDeviceCategory) 0x05) +#define CSR_WIFI_SME_WPS_CATEGORY_NET_INFRA ((CsrWifiSmeWpsDeviceCategory) 0x06) +#define CSR_WIFI_SME_WPS_CATEGORY_DISPLAY ((CsrWifiSmeWpsDeviceCategory) 0x07) +#define CSR_WIFI_SME_WPS_CATEGORY_MULTIMEDIA ((CsrWifiSmeWpsDeviceCategory) 0x08) +#define CSR_WIFI_SME_WPS_CATEGORY_GAMING ((CsrWifiSmeWpsDeviceCategory) 0x09) +#define CSR_WIFI_SME_WPS_CATEGORY_TELEPHONE ((CsrWifiSmeWpsDeviceCategory) 0x0A) +#define CSR_WIFI_SME_WPS_CATEGORY_AUDIO ((CsrWifiSmeWpsDeviceCategory) 0x0B) +#define CSR_WIFI_SME_WPS_CATEOARY_OTHERS ((CsrWifiSmeWpsDeviceCategory) 0xFF) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsDeviceSubCategory + + DESCRIPTION + Wps Secondary Device Types + + VALUES + CSR_WIFI_SME_WPS_SUB_CATEGORY_UNSPECIFIED + - Unspecied + CSR_WIFI_SME_WPS_STORAGE_SUB_CATEGORY_NAS + - Network Associated Storage + CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_PRNTR + - Printer or print server + CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_WM + - Windows mobile + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_TUNER + - Audio tuner/receiver + CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_DIG_STL + - Digital still camera + CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_AP + - Access Point + CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_TV + - TV. + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_DAR + - DAR. + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_KEYBD + - Keyboard. + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_PC + - PC. + CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX + - Xbox. + CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_SCNR + - Scanner + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_SERVER + - Server + CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_ROUTER + - Router + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_PVR + - PVR + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_SPEAKER + - Speaker + CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_SM + - Feature phone - Single mode + CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_VIDEO + - Video camera + CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PIC_FRM + - Picture frame + CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX_360 + - Xbox360 + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_MOUSE + - Mouse + CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_SWITCH + - Switch + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_PMP + - Portable music player + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_JOYSTK + - Joy stick + CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PLAY_STN + - Play-station + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MED_CENT + - Media Center + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MCX + - MCX + CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_DM + - Feature phone - Dual mode + CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_WEB + - Web camera + CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_FAX + - Fax + CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PROJECTOR + - Projector + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TRKBL + - Track Ball + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_ST_BOX + - Set-Top-Box + CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_GATEWAY + - GateWay. + CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_SECURITY + - Security camera + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_ULTRA_MOB_PC + - Ultra mobile PC. + CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_CONSOLE + - Game console/Game console adapter + CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_CPR + - Copier + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADSET + - Headset(headphones + microphone) + CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_SM + - Smart phone - Single mode + CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_MONITOR + - Monitor. + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_GAME_CTRL + - Game control. + CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_ALL + - All-in-One + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MEDIA + - Media Server/Media Adapter/Media Extender + CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_DM + - Smart phone - Dual mode + CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PORT_DEV + - Portable gaming device + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADPHONE + - Headphone. + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NOTEBOOK + - Notebook. + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_REMOTE + - Remote control + CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_MIC + - Microphone + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_DESKTOP + - Desktop. + CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_VP + - Portable video player + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MID + - Mobile internet device + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TOUCH_SCRN + - Touch screen + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BIOMET_RDR + - Biometric reader + CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NETBOOK + - Netbook + CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BRCD_RDR + - Bar code reader. + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWpsDeviceSubCategory; +#define CSR_WIFI_SME_WPS_SUB_CATEGORY_UNSPECIFIED ((CsrWifiSmeWpsDeviceSubCategory) 0x00) +#define CSR_WIFI_SME_WPS_STORAGE_SUB_CATEGORY_NAS ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_PRNTR ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_WM ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_TUNER ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_DIG_STL ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_AP ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_TV ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_DAR ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_KEYBD ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_PC ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX ((CsrWifiSmeWpsDeviceSubCategory) 0x01) +#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_SCNR ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_SERVER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_ROUTER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_PVR ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_SPEAKER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_SM ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_VIDEO ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PIC_FRM ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX_360 ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_MOUSE ((CsrWifiSmeWpsDeviceSubCategory) 0x02) +#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_SWITCH ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_PMP ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_JOYSTK ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PLAY_STN ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MED_CENT ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MCX ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_DM ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_WEB ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_FAX ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PROJECTOR ((CsrWifiSmeWpsDeviceSubCategory) 0x03) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TRKBL ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_ST_BOX ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_GATEWAY ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_SECURITY ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_ULTRA_MOB_PC ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_CONSOLE ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_CPR ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADSET ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_SM ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_MONITOR ((CsrWifiSmeWpsDeviceSubCategory) 0x04) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_GAME_CTRL ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_ALL ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MEDIA ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_DM ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PORT_DEV ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADPHONE ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NOTEBOOK ((CsrWifiSmeWpsDeviceSubCategory) 0x05) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_REMOTE ((CsrWifiSmeWpsDeviceSubCategory) 0x06) +#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_MIC ((CsrWifiSmeWpsDeviceSubCategory) 0x06) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_DESKTOP ((CsrWifiSmeWpsDeviceSubCategory) 0x06) +#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_VP ((CsrWifiSmeWpsDeviceSubCategory) 0x06) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MID ((CsrWifiSmeWpsDeviceSubCategory) 0x07) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TOUCH_SCRN ((CsrWifiSmeWpsDeviceSubCategory) 0x07) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BIOMET_RDR ((CsrWifiSmeWpsDeviceSubCategory) 0x08) +#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NETBOOK ((CsrWifiSmeWpsDeviceSubCategory) 0x08) +#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BRCD_RDR ((CsrWifiSmeWpsDeviceSubCategory) 0x09) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsDpid + + DESCRIPTION + Device Password ID for the chosen config method + + VALUES + CSR_WIFI_SME_WPS_DPID_PIN - PIN + CSR_WIFI_SME_WPS_DPID_USER - User specified : Used only during P2P GO + negotiation procedure + CSR_WIFI_SME_WPS_DPID_MACHINE - Machine specified i: Not used in this + release + CSR_WIFI_SME_WPS_DPID_REKEY - Rekey : Not used in this release + CSR_WIFI_SME_WPS_DPID_PBC - PBC + CSR_WIFI_SME_WPS_DPID_REGISTRAR - Registrar specified : Used only in P2P Go + negotiation procedure + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeWpsDpid; +#define CSR_WIFI_SME_WPS_DPID_PIN ((CsrWifiSmeWpsDpid) 0x0000) +#define CSR_WIFI_SME_WPS_DPID_USER ((CsrWifiSmeWpsDpid) 0x0001) +#define CSR_WIFI_SME_WPS_DPID_MACHINE ((CsrWifiSmeWpsDpid) 0x0002) +#define CSR_WIFI_SME_WPS_DPID_REKEY ((CsrWifiSmeWpsDpid) 0x0003) +#define CSR_WIFI_SME_WPS_DPID_PBC ((CsrWifiSmeWpsDpid) 0x0004) +#define CSR_WIFI_SME_WPS_DPID_REGISTRAR ((CsrWifiSmeWpsDpid) 0x0005) + +/******************************************************************************* + + NAME + CsrWifiSmeWpsRegistration + + DESCRIPTION + + VALUES + CSR_WIFI_SME_WPS_REG_NOT_REQUIRED - No encryption set + CSR_WIFI_SME_WPS_REG_REQUIRED - No encryption set + CSR_WIFI_SME_WPS_REG_UNKNOWN - No encryption set + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWpsRegistration; +#define CSR_WIFI_SME_WPS_REG_NOT_REQUIRED ((CsrWifiSmeWpsRegistration) 0x00) +#define CSR_WIFI_SME_WPS_REG_REQUIRED ((CsrWifiSmeWpsRegistration) 0x01) +#define CSR_WIFI_SME_WPS_REG_UNKNOWN ((CsrWifiSmeWpsRegistration) 0x02) + + +/******************************************************************************* + + NAME + CsrWifiSmeAuthModeMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeAuthMode + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeAuthModeMask; +/******************************************************************************* + + NAME + CsrWifiSmeEncryptionMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeEncryption + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeEncryptionMask; +/******************************************************************************* + + NAME + CsrWifiSmeIndicationsMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeIndications + +*******************************************************************************/ +typedef CsrUint32 CsrWifiSmeIndicationsMask; +/******************************************************************************* + + NAME + CsrWifiSmeP2pCapabilityMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeP2pCapability + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pCapabilityMask; +/******************************************************************************* + + NAME + CsrWifiSmeP2pGroupCapabilityMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeP2pGroupCapability + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeP2pGroupCapabilityMask; +/******************************************************************************* + + NAME + CsrWifiSmeTspecCtrlMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeTspecCtrl + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeTspecCtrlMask; +/******************************************************************************* + + NAME + CsrWifiSmeWmmModeMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeWmmMode + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWmmModeMask; +/******************************************************************************* + + NAME + CsrWifiSmeWmmQosInfoMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeWmmQosInfo + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeWmmQosInfoMask; +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigTypeMask + + DESCRIPTION + Mask type for use with the values defined by CsrWifiSmeWpsConfigType + +*******************************************************************************/ +typedef CsrUint16 CsrWifiSmeWpsConfigTypeMask; + + +/******************************************************************************* + + NAME + CsrWifiSmeAdHocConfig + + DESCRIPTION + Defines values to use when starting an Ad-hoc (IBSS) network. + + MEMBERS + atimWindowTu - ATIM window specified for IBSS + beaconPeriodTu - Interval between beacon packets + joinOnlyAttempts - Maximum number of attempts to join an ad-hoc network. + The default value is 1. + Set to 0 for infinite attempts. + joinAttemptIntervalMs - Time between scans for joining the requested IBSS. + +*******************************************************************************/ +typedef struct +{ + CsrUint16 atimWindowTu; + CsrUint16 beaconPeriodTu; + CsrUint16 joinOnlyAttempts; + CsrUint16 joinAttemptIntervalMs; +} CsrWifiSmeAdHocConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeAvailabilityConfig + + DESCRIPTION + + MEMBERS + listenChannel - + availabilityDuration - + avalabilityPeriod - + +*******************************************************************************/ +typedef struct +{ + CsrUint8 listenChannel; + CsrUint16 availabilityDuration; + CsrUint16 avalabilityPeriod; +} CsrWifiSmeAvailabilityConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfig + + DESCRIPTION + This type is reserved for future use and should not be used. + + MEMBERS + keepAliveTimeMs - NOT USED + apRoamingEnabled - NOT USED + measurementsMask - NOT USED + ccxRadioMgtEnabled - NOT USED + +*******************************************************************************/ +typedef struct +{ + CsrUint8 keepAliveTimeMs; + CsrBool apRoamingEnabled; + CsrUint8 measurementsMask; + CsrBool ccxRadioMgtEnabled; +} CsrWifiSmeCcxConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfig + + DESCRIPTION + Parameters for the coexistence behaviour. + + MEMBERS + coexEnableSchemeManagement - Enables the Coexistence Management Scheme + coexPeriodicWakeHost - If TRUE the firmware wakes up the host + periodically according to the traffic + period and latency parameters; the host + will then send the data to transmit only + when woken up. + If FALSE, the firmware does not wake up the + host and the host will send the data to + transmit to the firmware whenever there is + data to transmit + coexTrafficBurstyLatencyMs - Period of awakening for the firmware used + when bursty traffic is detected + coexTrafficContinuousLatencyMs - Period of awakening for the firmware used + when continuous traffic is detected + coexObexBlackoutDurationMs - Blackout Duration when a Obex Connection is + used + coexObexBlackoutPeriodMs - Blackout Period when a Obex Connection is + used + coexA2dpBrBlackoutDurationMs - Blackout Duration when a Basic Rate A2DP + Connection streaming data + coexA2dpBrBlackoutPeriodMs - Blackout Period when a Basic Rate A2DP + Connection streaming data + coexA2dpEdrBlackoutDurationMs - Blackout Duration when an Enhanced Data + Rate A2DP Connection streaming data + coexA2dpEdrBlackoutPeriodMs - Blackout Period when an Enhanced Data Rate + A2DP Connection streaming data + coexPagingBlackoutDurationMs - Blackout Duration when a BT page is active + coexPagingBlackoutPeriodMs - Blackout Period when a BT page is active + coexInquiryBlackoutDurationMs - Blackout Duration when a BT inquiry is + active + coexInquiryBlackoutPeriodMs - Blackout Period when a BT inquiry is active + +*******************************************************************************/ +typedef struct +{ + CsrBool coexEnableSchemeManagement; + CsrBool coexPeriodicWakeHost; + CsrUint16 coexTrafficBurstyLatencyMs; + CsrUint16 coexTrafficContinuousLatencyMs; + CsrUint16 coexObexBlackoutDurationMs; + CsrUint16 coexObexBlackoutPeriodMs; + CsrUint16 coexA2dpBrBlackoutDurationMs; + CsrUint16 coexA2dpBrBlackoutPeriodMs; + CsrUint16 coexA2dpEdrBlackoutDurationMs; + CsrUint16 coexA2dpEdrBlackoutPeriodMs; + CsrUint16 coexPagingBlackoutDurationMs; + CsrUint16 coexPagingBlackoutPeriodMs; + CsrUint16 coexInquiryBlackoutDurationMs; + CsrUint16 coexInquiryBlackoutPeriodMs; +} CsrWifiSmeCoexConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionStats + + DESCRIPTION + Indicates the statistics of the connection. + The dot11 fields are defined in the Annex D of the IEEE 802.11 standard. + + MEMBERS + unifiTxDataRate + - The bit rate currently in use for transmissions of unicast + data frames; a data rate in units of 500kbit/s. + On an infrastructure BSS, this is the data rate used in + communicating with the associated access point; if there is + none, an error is returned. + On an IBSS, this is the data rate used for the last + transmission of a unicast data frame to any station in the + IBSS. If no such transmission has been made, an error is + returned. + unifiRxDataRate + - As above for receiving data + dot11RetryCount + - See IEEE 802.11 Standard + dot11MultipleRetryCount + - See IEEE 802.11 Standard + dot11AckFailureCount + - See IEEE 802.11 Standard + dot11FrameDuplicateCount + - See IEEE 802.11 Standard + dot11FcsErrorCount + - See IEEE 802.11 Standard + dot11RtsSuccessCount + - See IEEE 802.11 Standard + dot11RtsFailureCount + - See IEEE 802.11 Standard + dot11FailedCount + - See IEEE 802.11 Standard + dot11TransmittedFragmentCount + - See IEEE 802.11 Standard + dot11TransmittedFrameCount + - See IEEE 802.11 Standard + dot11WepExcludedCount + - See IEEE 802.11 Standard + dot11WepIcvErrorCount + - See IEEE 802.11 Standard + dot11WepUndecryptableCount + - See IEEE 802.11 Standard + dot11MulticastReceivedFrameCount + - See IEEE 802.11 Standard + dot11MulticastTransmittedFrameCount + - See IEEE 802.11 Standard + dot11ReceivedFragmentCount + - See IEEE 802.11 Standard + dot11Rsna4WayHandshakeFailures + - See IEEE 802.11 Standard + dot11RsnaTkipCounterMeasuresInvoked + - See IEEE 802.11 Standard + dot11RsnaStatsTkipLocalMicFailures + - See IEEE 802.11 Standard + dot11RsnaStatsTkipReplays + - See IEEE 802.11 Standard + dot11RsnaStatsTkipIcvErrors + - See IEEE 802.11 Standard + dot11RsnaStatsCcmpReplays + - See IEEE 802.11 Standard + dot11RsnaStatsCcmpDecryptErrors + - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef struct +{ + CsrUint8 unifiTxDataRate; + CsrUint8 unifiRxDataRate; + CsrUint32 dot11RetryCount; + CsrUint32 dot11MultipleRetryCount; + CsrUint32 dot11AckFailureCount; + CsrUint32 dot11FrameDuplicateCount; + CsrUint32 dot11FcsErrorCount; + CsrUint32 dot11RtsSuccessCount; + CsrUint32 dot11RtsFailureCount; + CsrUint32 dot11FailedCount; + CsrUint32 dot11TransmittedFragmentCount; + CsrUint32 dot11TransmittedFrameCount; + CsrUint32 dot11WepExcludedCount; + CsrUint32 dot11WepIcvErrorCount; + CsrUint32 dot11WepUndecryptableCount; + CsrUint32 dot11MulticastReceivedFrameCount; + CsrUint32 dot11MulticastTransmittedFrameCount; + CsrUint32 dot11ReceivedFragmentCount; + CsrUint32 dot11Rsna4WayHandshakeFailures; + CsrUint32 dot11RsnaTkipCounterMeasuresInvoked; + CsrUint32 dot11RsnaStatsTkipLocalMicFailures; + CsrUint32 dot11RsnaStatsTkipReplays; + CsrUint32 dot11RsnaStatsTkipIcvErrors; + CsrUint32 dot11RsnaStatsCcmpReplays; + CsrUint32 dot11RsnaStatsCcmpDecryptErrors; +} CsrWifiSmeConnectionStats; + +/******************************************************************************* + + NAME + CsrWifiSmeDataBlock + + DESCRIPTION + Holds a generic data block to be passed through the interface + + MEMBERS + length - Length of the data block + data - Points to the first byte of the data block + +*******************************************************************************/ +typedef struct +{ + CsrUint16 length; + CsrUint8 *data; +} CsrWifiSmeDataBlock; + +/******************************************************************************* + + NAME + CsrWifiSmeEmpty + + DESCRIPTION + Empty Structure to indicate that no parameters are available. + + MEMBERS + empty - Only element of the empty structure (always set to 0). + +*******************************************************************************/ +typedef struct +{ + CsrUint8 empty; +} CsrWifiSmeEmpty; + +/******************************************************************************* + + NAME + CsrWifiSmeLinkQuality + + DESCRIPTION + Indicates the quality of the link + + MEMBERS + unifiRssi - Indicates the received signal strength indication of the link in + dBm + unifiSnr - Indicates the signal to noise ratio of the link in dB + +*******************************************************************************/ +typedef struct +{ + CsrInt16 unifiRssi; + CsrInt16 unifiSnr; +} CsrWifiSmeLinkQuality; + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfig + + DESCRIPTION + Allows low level configuration in the chip. + + MEMBERS + unifiFixMaxTxDataRate - This attribute is used in combination with + unifiFixTxDataRate. If it is FALSE, then + unifiFixTxDataRate specifies a specific data + rate to use. If it is TRUE, unifiFixTxDataRate + instead specifies a maximum data rate. + unifiFixTxDataRate - Transmit rate for unicast data. + See MIB description for more details + dot11RtsThreshold - See IEEE 802.11 Standard + dot11FragmentationThreshold - See IEEE 802.11 Standard + dot11CurrentTxPowerLevel - See IEEE 802.11 Standard + +*******************************************************************************/ +typedef struct +{ + CsrBool unifiFixMaxTxDataRate; + CsrUint8 unifiFixTxDataRate; + CsrUint16 dot11RtsThreshold; + CsrUint16 dot11FragmentationThreshold; + CsrUint16 dot11CurrentTxPowerLevel; +} CsrWifiSmeMibConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeP2pProfileIdentity + + DESCRIPTION + Details to be filled in + + MEMBERS + listenChannel - + availabilityDuration - + avalabilityPeriod - + +*******************************************************************************/ +typedef struct +{ + CsrUint8 listenChannel; + CsrUint16 availabilityDuration; + CsrUint16 avalabilityPeriod; +} CsrWifiSmeP2pProfileIdentity; + +/******************************************************************************* + + NAME + CsrWifiSmePmkid + + DESCRIPTION + Defines a PMKID association with BSS + + MEMBERS + bssid - BSS identifier + pmkid - PMKID + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress bssid; + CsrUint8 pmkid[16]; +} CsrWifiSmePmkid; + +/******************************************************************************* + + NAME + CsrWifiSmePmkidCandidate + + DESCRIPTION + Information for a PMKID candidate + + MEMBERS + bssid - BSS identifier + preAuthAllowed - Indicates whether preauthentication is allowed + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress bssid; + CsrBool preAuthAllowed; +} CsrWifiSmePmkidCandidate; + +/******************************************************************************* + + NAME + CsrWifiSmePmkidList + + DESCRIPTION + NOT USED + Used in the Sync access API + + MEMBERS + pmkidsCount - Number of PMKIDs in the list + pmkids - Points to the first PMKID in the list + +*******************************************************************************/ +typedef struct +{ + CsrUint8 pmkidsCount; + CsrWifiSmePmkid *pmkids; +} CsrWifiSmePmkidList; + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomainInfo + + DESCRIPTION + Regulatory domain options. + + MEMBERS + dot11MultiDomainCapabilityImplemented + - TRUE is the multi domain capability is implemented + dot11MultiDomainCapabilityEnabled + - TRUE is the multi domain capability is enabled + currentRegulatoryDomain + - Current regulatory domain + currentCountryCode + - Current country code as defined by the IEEE 802.11 + standards + +*******************************************************************************/ +typedef struct +{ + CsrBool dot11MultiDomainCapabilityImplemented; + CsrBool dot11MultiDomainCapabilityEnabled; + CsrWifiSmeRegulatoryDomain currentRegulatoryDomain; + CsrUint8 currentCountryCode[2]; +} CsrWifiSmeRegulatoryDomainInfo; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingBandData + + DESCRIPTION + Thresholds to define one usability level category for the received signal + + MEMBERS + rssiHighThreshold - Received Signal Strength Indication upper bound in dBm + for the usability level + rssiLowThreshold - Received Signal Strength Indication lower bound in dBm + for the usability level + snrHighThreshold - Signal to Noise Ratio upper bound in dB for the + usability level + snrLowThreshold - Signal to Noise Ratio lower bound in dB for the + usability level + +*******************************************************************************/ +typedef struct +{ + CsrInt16 rssiHighThreshold; + CsrInt16 rssiLowThreshold; + CsrInt16 snrHighThreshold; + CsrInt16 snrLowThreshold; +} CsrWifiSmeRoamingBandData; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigData + + DESCRIPTION + Configures the scanning behaviour of the driver and firmware + + MEMBERS + intervalSeconds - All the channels will be scanned once in this time + interval. + If connected, the channel scans are spread across + the interval. + If disconnected, all the channels will be scanned + together + validitySeconds - How long the scan result are cached + minActiveChannelTimeTu - Minimum time of listening on a channel being + actively scanned before leaving if no probe + responses or beacon frames have been received + maxActiveChannelTimeTu - Maximum time of listening on a channel being + actively scanned + minPassiveChannelTimeTu - Minimum time of listening on a channel being + passive scanned before leaving if no beacon frames + have been received + maxPassiveChannelTimeTu - Maximum time of listening on a channel being + passively scanned + +*******************************************************************************/ +typedef struct +{ + CsrUint16 intervalSeconds; + CsrUint16 validitySeconds; + CsrUint16 minActiveChannelTimeTu; + CsrUint16 maxActiveChannelTimeTu; + CsrUint16 minPassiveChannelTimeTu; + CsrUint16 maxPassiveChannelTimeTu; +} CsrWifiSmeScanConfigData; + +/******************************************************************************* + + NAME + CsrWifiSmeStaConfig + + DESCRIPTION + Station configuration options in the SME + + MEMBERS + connectionQualityRssiChangeTrigger - Sets the difference of RSSI + measurements which triggers reports + from the Firmware + connectionQualitySnrChangeTrigger - Sets the difference of SNR measurements + which triggers reports from the + Firmware + wmmModeMask - Mask containing one or more values from + CsrWifiSmeWmmMode + ifIndex - Indicates the band of frequencies used + allowUnicastUseGroupCipher - If TRUE, it allows to use groupwise + keys if no pairwise key is specified + enableOpportunisticKeyCaching - If TRUE, enables the Opportunistic Key + Caching feature + +*******************************************************************************/ +typedef struct +{ + CsrUint8 connectionQualityRssiChangeTrigger; + CsrUint8 connectionQualitySnrChangeTrigger; + CsrUint8 wmmModeMask; + CsrWifiSmeRadioIF ifIndex; + CsrBool allowUnicastUseGroupCipher; + CsrBool enableOpportunisticKeyCaching; +} CsrWifiSmeStaConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeTsfTime + + DESCRIPTION + Time stamp representation + + MEMBERS + data - TSF Bytes + +*******************************************************************************/ +typedef struct +{ + CsrUint8 data[8]; +} CsrWifiSmeTsfTime; + +/******************************************************************************* + + NAME + CsrWifiSmeVersions + + DESCRIPTION + Reports version information for the chip, the firmware and the driver and + the SME. + + MEMBERS + chipId - Chip ID + chipVersion - Chip version ID + firmwareBuild - Firmware Rom build number + firmwarePatch - Firmware Patch build number (if applicable) + firmwareHip - Firmware HIP protocol version number + routerBuild - Router build number + routerHip - Router HIP protocol version number + smeBuild - SME build number + smeHip - SME HIP protocol version number + +*******************************************************************************/ +typedef struct +{ + CsrUint32 chipId; + CsrUint32 chipVersion; + CsrUint32 firmwareBuild; + CsrUint32 firmwarePatch; + CsrUint32 firmwareHip; + CsrCharString *routerBuild; + CsrUint32 routerHip; + CsrCharString *smeBuild; + CsrUint32 smeHip; +} CsrWifiSmeVersions; + +/******************************************************************************* + + NAME + CsrWifiSmeWmmAcParams + + DESCRIPTION + Structure holding WMM AC params data. + + MEMBERS + cwMin - Exponent for the calculation of CWmin. Range: 0 + to 15 + cwMax - Exponent for the calculation of CWmax. Range: 0 + to15 + aifs - Arbitration Inter Frame Spacing in terms of + number of timeslots. Range 2 to 15 + txopLimit - TXOP Limit in the units of 32 microseconds + admissionControlMandatory - Indicates whether the admission control is + mandatory or not. Current release does not + support admission control , hence shall be set + to FALSE. + +*******************************************************************************/ +typedef struct +{ + CsrUint8 cwMin; + CsrUint8 cwMax; + CsrUint8 aifs; + CsrUint16 txopLimit; + CsrBool admissionControlMandatory; +} CsrWifiSmeWmmAcParams; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsDeviceType + + DESCRIPTION + Structure holding AP WPS device type data. + + MEMBERS + deviceDetails - category , sub category etc + +*******************************************************************************/ +typedef struct +{ + CsrUint8 deviceDetails[8]; +} CsrWifiSmeWpsDeviceType; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsDeviceTypeCommon + + DESCRIPTION + + MEMBERS + spportWps - + deviceType - + +*******************************************************************************/ +typedef struct +{ + CsrBool spportWps; + CsrUint8 deviceType; +} CsrWifiSmeWpsDeviceTypeCommon; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsInfo + + DESCRIPTION + + MEMBERS + version - + configMethods - + devicePassworId - + +*******************************************************************************/ +typedef struct +{ + CsrUint16 version; + CsrUint16 configMethods; + CsrUint16 devicePassworId; +} CsrWifiSmeWpsInfo; + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidConfig + + DESCRIPTION + List of cloaked SSIDs . + + MEMBERS + cloakedSsidsCount - Number of cloaked SSID + cloakedSsids - Points to the first byte of the first SSID provided + +*******************************************************************************/ +typedef struct +{ + CsrUint8 cloakedSsidsCount; + CsrWifiSsid *cloakedSsids; +} CsrWifiSmeCloakedSsidConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexInfo + + DESCRIPTION + Information and state related to coexistence. + + MEMBERS + hasTrafficData - TRUE if any Wi-Fi traffic is detected + currentTrafficType - Current type of traffic + currentPeriodMs - Period of the traffic as detected by the traffic + analysis. + If the traffic is not periodic, it is set to 0. + currentPowerSave - Current power save level + currentCoexPeriodMs - Period of awakening for the firmware used when + periodic traffic is detected. + If the traffic is not periodic, it is set to 0. + currentCoexLatencyMs - Period of awakening for the firmware used when + non-periodic traffic is detected + hasBtDevice - TRUE if there is a Bluetooth device connected + currentBlackoutDurationUs - Current blackout duration for protecting + Bluetooth + currentBlackoutPeriodUs - Current blackout period + currentCoexScheme - Defines the scheme for the coexistence + signalling + +*******************************************************************************/ +typedef struct +{ + CsrBool hasTrafficData; + CsrWifiSmeTrafficType currentTrafficType; + CsrUint16 currentPeriodMs; + CsrWifiSmePowerSaveLevel currentPowerSave; + CsrUint16 currentCoexPeriodMs; + CsrUint16 currentCoexLatencyMs; + CsrBool hasBtDevice; + CsrUint32 currentBlackoutDurationUs; + CsrUint32 currentBlackoutPeriodUs; + CsrWifiSmeCoexScheme currentCoexScheme; +} CsrWifiSmeCoexInfo; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionConfig + + DESCRIPTION + Specifies the parameters that the SME should use in selecting a network. + + MEMBERS + ssid + - Service Set identifier + bssid + - BSS identifier + bssType + - Indicates the type of BSS + ifIndex + - Indicates the radio interface + privacyMode + - Specifies whether the privacy mode is enabled or disabled. + authModeMask + - Sets the authentication options that the SME can use while + associating to the AP + Set mask with values from CsrWifiSmeAuthMode + encryptionModeMask + - Sets the encryption options that the SME can use while + associating to the AP + Set mask with values from CsrWifiSmeEncryption + mlmeAssociateReqInformationElementsLength + - Length in bytes of information elements to be sent in the + Association Request. + mlmeAssociateReqInformationElements + - Points to the first byte of the information elements, if + any. + wmmQosInfo + - This parameter allows the driver's WMM behaviour to be + configured. + To enable support for WMM, use + CSR_WIFI_SME_SME_CONFIG_SET_REQ with the + CSR_WIFI_SME_WMM_MODE_AC_ENABLED bit set in wmmModeMask + field in smeConfig parameter. + Set mask with values from CsrWifiSmeWmmQosInfo + adhocJoinOnly + - This parameter is relevant only if bssType is NOT set to + CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: + if TRUE the SME will only try to join an ad-hoc network if + there is one already established; + if FALSE the SME will try to join an ad-hoc network if + there is one already established or it will try to + establish a new one + adhocChannel + - This parameter is relevant only if bssType is NOT set to + CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: + it indicates the channel to use joining an ad hoc network. + Setting this to 0 causes the SME to select a channel from + those permitted in the regulatory domain. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSsid ssid; + CsrWifiMacAddress bssid; + CsrWifiSmeBssType bssType; + CsrWifiSmeRadioIF ifIndex; + CsrWifiSme80211PrivacyMode privacyMode; + CsrWifiSmeAuthModeMask authModeMask; + CsrWifiSmeEncryptionMask encryptionModeMask; + CsrUint16 mlmeAssociateReqInformationElementsLength; + CsrUint8 *mlmeAssociateReqInformationElements; + CsrWifiSmeWmmQosInfoMask wmmQosInfo; + CsrBool adhocJoinOnly; + CsrUint8 adhocChannel; +} CsrWifiSmeConnectionConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionInfo + + DESCRIPTION + Parameters that the SME should use in selecting a network + + MEMBERS + ssid - Service set identifier + bssid - BSS identifier + networkType80211 - Physical layer used for the connection + channelNumber - Channel number + channelFrequency - Channel frequency + authMode - Authentication mode used for the connection + pairwiseCipher - Encryption type for peer to peer communication + groupCipher - Encryption type for broadcast and multicast + communication + ifIndex - Indicates the radio interface + atimWindowTu - ATIM window specified for IBSS + beaconPeriodTu - Interval between beacon packets + reassociation - Indicates whether a reassociation occurred + beaconFrameLength - Indicates the number of bytes of the beacon + frame + beaconFrame - Points at the first byte of the beacon frame + associationReqFrameLength - Indicates the number of bytes of the + association request frame + associationReqFrame - Points at the first byte of the association + request frame + associationRspFrameLength - Indicates the number of bytes of the + association response frame + associationRspFrame - Points at the first byte of the association + response frame + assocScanInfoElementsLength - Indicates the number of bytes in the buffer + pointed by assocScanInfoElements + assocScanInfoElements - Pointer to the buffer containing the + information elements of the probe response + received after the probe requests sent before + attempting to authenticate to the network + assocReqCapabilities - Reports the content of the Capability + information element as specified in the + association request. + assocReqListenIntervalTu - Listen Interval specified in the association + request + assocReqApAddress - AP address to which the association requests + has been sent + assocReqInfoElementsLength - Indicates the number of bytes of the + association request information elements + assocReqInfoElements - Points at the first byte of the association + request information elements + assocRspResult - Result reported in the association response + assocRspCapabilityInfo - Reports the content of the Capability + information element as received in the + association response. + assocRspAssociationId - Reports the association ID received in the + association response. + assocRspInfoElementsLength - Indicates the number of bytes of the + association response information elements + assocRspInfoElements - Points at the first byte of the association + response information elements + +*******************************************************************************/ +typedef struct +{ + CsrWifiSsid ssid; + CsrWifiMacAddress bssid; + CsrWifiSme80211NetworkType networkType80211; + CsrUint8 channelNumber; + CsrUint16 channelFrequency; + CsrWifiSmeAuthMode authMode; + CsrWifiSmeEncryption pairwiseCipher; + CsrWifiSmeEncryption groupCipher; + CsrWifiSmeRadioIF ifIndex; + CsrUint16 atimWindowTu; + CsrUint16 beaconPeriodTu; + CsrBool reassociation; + CsrUint16 beaconFrameLength; + CsrUint8 *beaconFrame; + CsrUint16 associationReqFrameLength; + CsrUint8 *associationReqFrame; + CsrUint16 associationRspFrameLength; + CsrUint8 *associationRspFrame; + CsrUint16 assocScanInfoElementsLength; + CsrUint8 *assocScanInfoElements; + CsrUint16 assocReqCapabilities; + CsrUint16 assocReqListenIntervalTu; + CsrWifiMacAddress assocReqApAddress; + CsrUint16 assocReqInfoElementsLength; + CsrUint8 *assocReqInfoElements; + CsrWifiSmeIEEE80211Result assocRspResult; + CsrUint16 assocRspCapabilityInfo; + CsrUint16 assocRspAssociationId; + CsrUint16 assocRspInfoElementsLength; + CsrUint8 *assocRspInfoElements; +} CsrWifiSmeConnectionInfo; + +/******************************************************************************* + + NAME + CsrWifiSmeDeviceConfig + + DESCRIPTION + General configuration options in the SME + + MEMBERS + trustLevel - Level of trust of the information coming from the + network + countryCode - Country code as specified by IEEE 802.11 standard + firmwareDriverInterface - Specifies the type of communication between Host + and Firmware + enableStrictDraftN - If TRUE TKIP is disallowed when connecting to + 802.11n enabled access points + +*******************************************************************************/ +typedef struct +{ + CsrWifiSme80211dTrustLevel trustLevel; + CsrUint8 countryCode[2]; + CsrWifiSmeFirmwareDriverInterface firmwareDriverInterface; + CsrBool enableStrictDraftN; +} CsrWifiSmeDeviceConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeDeviceInfo + + DESCRIPTION + P2P Information for a P2P Device + + MEMBERS + deviceAddress - Device Address of the P2P device + configMethods - Supported WPS configuration methods. + p2PDeviceCap - P2P device capabilities + primDeviceType - Primary WPS device type + secondaryDeviceTypeCount - Number of secondary device types + secDeviceType - list of secondary WPS device types + deviceName - Device name without up to 32 characters'\0'. + deviceNameLength - Number of characters of the device name + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress deviceAddress; + CsrWifiSmeWpsConfigTypeMask configMethods; + CsrWifiSmeP2pCapabilityMask p2PDeviceCap; + CsrWifiSmeWpsDeviceType primDeviceType; + CsrUint8 secondaryDeviceTypeCount; + CsrWifiSmeWpsDeviceType *secDeviceType; + CsrUint8 deviceName[32]; + CsrUint8 deviceNameLength; +} CsrWifiSmeDeviceInfo; + +/******************************************************************************* + + NAME + CsrWifiSmeDeviceInfoCommon + + DESCRIPTION + Structure holding device information. + + MEMBERS + p2pDeviceAddress - + primaryDeviceType - + secondaryDeviceTypesCount - + secondaryDeviceTypes - + deviceNameLength - + deviceName - + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress p2pDeviceAddress; + CsrWifiSmeWpsDeviceTypeCommon primaryDeviceType; + CsrUint8 secondaryDeviceTypesCount; + CsrUint8 secondaryDeviceTypes[10]; + CsrUint8 deviceNameLength; + CsrUint8 deviceName[32]; +} CsrWifiSmeDeviceInfoCommon; + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfig + + DESCRIPTION + Defines the host power state (for example, on mains power, on battery + power etc) and the periodicity of the traffic data. + + MEMBERS + powerMode - The wireless manager application should use the + powerMode parameter to inform the SME of the host + power state. + applicationDataPeriodMs - The applicationDataPeriodMs parameter allows a + wireless manager application to inform the SME + that an application is running that generates + periodic network traffic and the period of the + traffic. + An example of such an application is a VoIP client. + The wireless manager application should set + applicationDataPeriodMs to the period in + milliseconds between data packets or zero if no + periodic application is running. + Voip etc 0 = No Periodic Data + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeHostPowerMode powerMode; + CsrUint16 applicationDataPeriodMs; +} CsrWifiSmeHostConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeKey + + DESCRIPTION + Information for a key to be used for encryption + + MEMBERS + keyType - Specifies whether the key is a pairwise or group key; it + should be set to CSR_WIFI_SME_GROUP_KEY or + CSR_WIFI_SME_PAIRWISE_KEY, as required. + keyIndex - Specifies which WEP key (0-3) to set; it should be set to 0 + for a WPA/WPA2 pairwise key and non-zero for a WPA/WPA2 + group key. + wepTxKey - If wepTxKey is TRUE, and the key is a WEP key, the key will + be selected for encrypting transmitted packets. + To select a previously defined key as the transmit + encryption key, set keyIndex to the required key, wepTxKey + to TRUE and the keyLength to 0. + keyRsc - Key Receive Sequence Counter + authenticator - If TRUE the WMA will act as authenticator. + CURRENTLY NOT SUPPORTED + address - BSS identifier of the AP + keyLength - Length of the key in bytes + key - Points to the first byte of the key + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeKeyType keyType; + CsrUint8 keyIndex; + CsrBool wepTxKey; + CsrUint16 keyRsc[8]; + CsrBool authenticator; + CsrWifiMacAddress address; + CsrUint8 keyLength; + CsrUint8 key[32]; +} CsrWifiSmeKey; + +/******************************************************************************* + + NAME + CsrWifiSmeP2pClientInfoType + + DESCRIPTION + P2P Information for a P2P Client + + MEMBERS + p2PClientInterfaceAddress - MAC address of the P2P Client + clientDeviceInfo - Device Information + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress p2PClientInterfaceAddress; + CsrWifiSmeDeviceInfo clientDeviceInfo; +} CsrWifiSmeP2pClientInfoType; + +/******************************************************************************* + + NAME + CsrWifiSmeP2pGroupInfo + + DESCRIPTION + P2P Information for a P2P Group + + MEMBERS + groupCapability - P2P group capabilities + p2pDeviceAddress - Device Address of the GO + p2pClientInfoCount - Number of P2P Clients that belong to the group. + p2PClientInfo - Pointer to the list containing client information for + each client in the group + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeP2pGroupCapabilityMask groupCapability; + CsrWifiMacAddress p2pDeviceAddress; + CsrUint8 p2pClientInfoCount; + CsrWifiSmeP2pClientInfoType *p2PClientInfo; +} CsrWifiSmeP2pGroupInfo; + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfig + + DESCRIPTION + Configures the power-save behaviour of the driver and firmware. + + MEMBERS + powerSaveLevel - Power Save Level option + listenIntervalTu - Interval for waking to receive beacon frames + rxDtims - If TRUE, wake for DTIM every beacon period, to + allow the reception broadcast packets + d3AutoScanMode - Defines whether the autonomous scanning will be + turned off or will stay on during a D3 suspended + period + clientTrafficWindow - Deprecated + opportunisticPowerSave - Deprecated + noticeOfAbsence - Deprecated + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmePowerSaveLevel powerSaveLevel; + CsrUint16 listenIntervalTu; + CsrBool rxDtims; + CsrWifiSmeD3AutoScanMode d3AutoScanMode; + CsrUint8 clientTrafficWindow; + CsrBool opportunisticPowerSave; + CsrBool noticeOfAbsence; +} CsrWifiSmePowerConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfig + + DESCRIPTION + Configures the roaming behaviour of the driver and firmware + + MEMBERS + roamingBands - Defines the thresholds to determine the usability + level of the current connection. + roamingBands is indexed by the first 3 entries of + the CsrWifiSmeBasicUsability enum + disableSmoothRoaming - Disable the RSSI/SNR triggers from the Firmware + that the SME uses to detect the quality of the + connection. + This implicitly disables disableRoamScans + disableRoamScans - Disables the scanning for the roaming operation + reconnectLimit - Maximum number of times SME may reconnect in the + given interval + reconnectLimitIntervalMs - Interval for maximum number of times SME may + reconnect to the same Access Point + roamScanCfg - Scanning behaviour for the specifically aimed at + improving roaming performance. + roamScanCfg is indexed by the first 3 entries of + the CsrWifiSmeBasicUsability enum + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeRoamingBandData roamingBands[3]; + CsrBool disableSmoothRoaming; + CsrBool disableRoamScans; + CsrUint8 reconnectLimit; + CsrUint16 reconnectLimitIntervalMs; + CsrWifiSmeScanConfigData roamScanCfg[3]; +} CsrWifiSmeRoamingConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfig + + DESCRIPTION + Parameters for the autonomous scanning behaviour of the system + + MEMBERS + scanCfg - Scan configuration data. + Indexed by the CsrWifiSmeBasicUsability enum + disableAutonomousScans - Enables or disables the autonomous scan + maxResults - Maximum number of results to be cached in the SME + highRssiThreshold - High received signal strength indication threshold + in dBm for an AP above which the system will + report scan indications + lowRssiThreshold - Low received signal strength indication threshold + in dBm for an AP below which the system will + report scan indications + deltaRssiThreshold - Minimum difference for received signal strength + indication in dBm for an AP which trigger a scan + indication to be sent. + highSnrThreshold - High Signal to Noise Ratio threshold in dB for an + AP above which the system will report scan + indications + lowSnrThreshold - Low Signal to Noise Ratio threshold in dB for an + AP below which the system will report scan + indications + deltaSnrThreshold - Minimum difference for Signal to Noise Ratio in dB + for an AP which trigger a scan indication to be + sent. + passiveChannelListCount - Number of channels to be scanned passively. + passiveChannelList - Points to the first channel to be scanned + passively , if any. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeScanConfigData scanCfg[4]; + CsrBool disableAutonomousScans; + CsrUint16 maxResults; + CsrInt8 highRssiThreshold; + CsrInt8 lowRssiThreshold; + CsrInt8 deltaRssiThreshold; + CsrInt8 highSnrThreshold; + CsrInt8 lowSnrThreshold; + CsrInt8 deltaSnrThreshold; + CsrUint16 passiveChannelListCount; + CsrUint8 *passiveChannelList; +} CsrWifiSmeScanConfig; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResult + + DESCRIPTION + This structure defines the scan result for each BSS found + + MEMBERS + ssid - Service set identifier + bssid - BSS identifier + rssi - Received signal strength indication in dBm + snr - Signal to noise ratio in dB + ifIndex - Indicates the radio interface + beaconPeriodTu - Interval between beacon frames + timeStamp - Timestamp in the BSS + localTime - Timestamp in the Access Point + channelFrequency - Channel frequency + capabilityInformation - Capabilities of the BSS. + channelNumber - Channel number + usability - Indicates the usability level. + bssType - Type of BSS. + informationElementsLength - Number of bytes of the information elements + received as part of the beacon or probe + response. + informationElements - Points to the first byte of the IEs received + as part of the beacon or probe response. + The format of the IEs is as specified in the + IEEE 802.11 specification. + p2pDeviceRole - Role of the P2P device. + Relevant only if bssType is + CSR_WIFI_SME_BSS_TYPE_P2P + deviceInfo - Union containing P2P device info which + depends on p2pDeviceRole parameter. + deviceInforeservedCli - + deviceInfogroupInfo - + deviceInforeservedNone - + deviceInfostandalonedevInfo - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSsid ssid; + CsrWifiMacAddress bssid; + CsrInt16 rssi; + CsrInt16 snr; + CsrWifiSmeRadioIF ifIndex; + CsrUint16 beaconPeriodTu; + CsrWifiSmeTsfTime timeStamp; + CsrWifiSmeTsfTime localTime; + CsrUint16 channelFrequency; + CsrUint16 capabilityInformation; + CsrUint8 channelNumber; + CsrWifiSmeBasicUsability usability; + CsrWifiSmeBssType bssType; + CsrUint16 informationElementsLength; + CsrUint8 *informationElements; + CsrWifiSmeP2pRole p2pDeviceRole; + union { + CsrWifiSmeEmpty reservedCli; + CsrWifiSmeP2pGroupInfo groupInfo; + CsrWifiSmeEmpty reservedNone; + CsrWifiSmeDeviceInfo standalonedevInfo; + } deviceInfo; +} CsrWifiSmeScanResult; + +/******************************************************************************* + + NAME + CsrWifiSmeWep128Keys + + DESCRIPTION + Structure holding WEP Authentication Type and WEP keys that can be used + when using WEP128. + + MEMBERS + wepAuthType - Mask to select the WEP authentication type (Open or Shared) + selectedWepKey - Index to one of the four keys below indicating the + currently used WEP key. Mapping From SME/User -> firmware. + Key 1 -> Index 0. Key 2 -> Index 1. key 3 -> Index 2. Key + 4-> Index 3. + key1 - Value for key number 1. + key2 - Value for key number 2. + key3 - Value for key number 3. + key4 - Value for key number 4. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeWepAuthMode wepAuthType; + CsrUint8 selectedWepKey; + CsrUint8 key1[13]; + CsrUint8 key2[13]; + CsrUint8 key3[13]; + CsrUint8 key4[13]; +} CsrWifiSmeWep128Keys; + +/******************************************************************************* + + NAME + CsrWifiSmeWep64Keys + + DESCRIPTION + Structure holding WEP Authentication Type and WEP keys that can be used + when using WEP64. + + MEMBERS + wepAuthType - Mask to select the WEP authentication type (Open or Shared) + selectedWepKey - Index to one of the four keys below indicating the + currently used WEP key. Mapping From SME/User -> firmware. + Key 1 -> Index 0. Key 2 -> Index 1. key 3 -> Index 2. Key + 4-> Index 3. + key1 - Value for key number 1. + key2 - Value for key number 2. + key3 - Value for key number 3. + key4 - Value for key number 4. + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeWepAuthMode wepAuthType; + CsrUint8 selectedWepKey; + CsrUint8 key1[5]; + CsrUint8 key2[5]; + CsrUint8 key3[5]; + CsrUint8 key4[5]; +} CsrWifiSmeWep64Keys; + +/******************************************************************************* + + NAME + CsrWifiSmeWepAuth + + DESCRIPTION + WEP authentication parameter structure + + MEMBERS + wepKeyType - WEP key try (128 bit or 64 bit) + wepCredentials - Union containing credentials which depends on + wepKeyType parameter. + wepCredentialswep128Key - + wepCredentialswep64Key - + +*******************************************************************************/ +typedef struct +{ + CsrWifiSmeWepCredentialType wepKeyType; + union { + CsrWifiSmeWep128Keys wep128Key; + CsrWifiSmeWep64Keys wep64Key; + } wepCredentials; +} CsrWifiSmeWepAuth; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfig + + DESCRIPTION + Structure holding AP WPS Config data. + + MEMBERS + wpsVersion - wpsVersion should be 0x10 for WPS1.0h or 0x20 for + WSC2.0 + uuid - uuid. + deviceName - Device name upto 32 characters without '\0'. + deviceNameLength - deviceNameLen. + manufacturer - manufacturer: CSR + manufacturerLength - manufacturerLen. + modelName - modelName Unifi + modelNameLength - modelNameLen. + modelNumber - modelNumber + modelNumberLength - modelNumberLen. + serialNumber - serialNumber + primDeviceType - Primary WPS device type + secondaryDeviceTypeCount - Number of secondary device types + secondaryDeviceType - list of secondary WPS device types + configMethods - Supported WPS config methods + rfBands - RfBands. + osVersion - Os version on which the device is running + +*******************************************************************************/ +typedef struct +{ + CsrUint8 wpsVersion; + CsrUint8 uuid[16]; + CsrUint8 deviceName[32]; + CsrUint8 deviceNameLength; + CsrUint8 manufacturer[64]; + CsrUint8 manufacturerLength; + CsrUint8 modelName[32]; + CsrUint8 modelNameLength; + CsrUint8 modelNumber[32]; + CsrUint8 modelNumberLength; + CsrUint8 serialNumber[32]; + CsrWifiSmeWpsDeviceType primDeviceType; + CsrUint8 secondaryDeviceTypeCount; + CsrWifiSmeWpsDeviceType *secondaryDeviceType; + CsrWifiSmeWpsConfigTypeMask configMethods; + CsrUint8 rfBands; + CsrUint8 osVersion[4]; +} CsrWifiSmeWpsConfig; + + +/* Downstream */ +#define CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST (0x0000) + +#define CSR_WIFI_SME_ACTIVATE_REQ ((CsrWifiSmePrim) (0x0000 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0001 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0002 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_BLACKLIST_REQ ((CsrWifiSmePrim) (0x0003 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ ((CsrWifiSmePrim) (0x0004 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ ((CsrWifiSmePrim) (0x0005 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CCX_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0006 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CCX_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0007 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0008 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0009 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_INFO_GET_REQ ((CsrWifiSmePrim) (0x000A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECT_REQ ((CsrWifiSmePrim) (0x000B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x000C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_INFO_GET_REQ ((CsrWifiSmePrim) (0x000D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_STATS_GET_REQ ((CsrWifiSmePrim) (0x000E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_DEACTIVATE_REQ ((CsrWifiSmePrim) (0x000F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_DISCONNECT_REQ ((CsrWifiSmePrim) (0x0010 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_EVENT_MASK_SET_REQ ((CsrWifiSmePrim) (0x0011 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_HOST_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0012 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_HOST_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0013 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_KEY_REQ ((CsrWifiSmePrim) (0x0014 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_LINK_QUALITY_GET_REQ ((CsrWifiSmePrim) (0x0015 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0016 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0017 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_GET_NEXT_REQ ((CsrWifiSmePrim) (0x0018 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_GET_REQ ((CsrWifiSmePrim) (0x0019 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_SET_REQ ((CsrWifiSmePrim) (0x001A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_MULTICAST_ADDRESS_REQ ((CsrWifiSmePrim) (0x001B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_PACKET_FILTER_SET_REQ ((CsrWifiSmePrim) (0x001C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ ((CsrWifiSmePrim) (0x001D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_PMKID_REQ ((CsrWifiSmePrim) (0x001E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_POWER_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x001F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_POWER_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0020 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ ((CsrWifiSmePrim) (0x0021 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0022 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0023 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0024 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0025 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_FULL_REQ ((CsrWifiSmePrim) (0x0026 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ ((CsrWifiSmePrim) (0x0027 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_RESULTS_GET_REQ ((CsrWifiSmePrim) (0x0028 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0029 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x002A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ ((CsrWifiSmePrim) (0x002B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_TSPEC_REQ ((CsrWifiSmePrim) (0x002C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_VERSIONS_GET_REQ ((CsrWifiSmePrim) (0x002D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ ((CsrWifiSmePrim) (0x002E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_OFF_REQ ((CsrWifiSmePrim) (0x002F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_ON_REQ ((CsrWifiSmePrim) (0x0030 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ ((CsrWifiSmePrim) (0x0031 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ ((CsrWifiSmePrim) (0x0032 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0033 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0034 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ ((CsrWifiSmePrim) (0x0035 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_WPS_CONFIGURATION_REQ ((CsrWifiSmePrim) (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) + + +#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) + +/* Upstream */ +#define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) + +#define CSR_WIFI_SME_ACTIVATE_CFM ((CsrWifiSmePrim)(0x0000 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0001 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0002 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND ((CsrWifiSmePrim)(0x0003 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ASSOCIATION_START_IND ((CsrWifiSmePrim)(0x0004 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_BLACKLIST_CFM ((CsrWifiSmePrim)(0x0005 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM ((CsrWifiSmePrim)(0x0006 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM ((CsrWifiSmePrim)(0x0007 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CCX_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0008 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CCX_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0009 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x000A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x000B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_COEX_INFO_GET_CFM ((CsrWifiSmePrim)(0x000C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECT_CFM ((CsrWifiSmePrim)(0x000D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x000E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_INFO_GET_CFM ((CsrWifiSmePrim)(0x000F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_QUALITY_IND ((CsrWifiSmePrim)(0x0010 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CONNECTION_STATS_GET_CFM ((CsrWifiSmePrim)(0x0011 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_DEACTIVATE_CFM ((CsrWifiSmePrim)(0x0012 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_DISCONNECT_CFM ((CsrWifiSmePrim)(0x0013 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_EVENT_MASK_SET_CFM ((CsrWifiSmePrim)(0x0014 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_HOST_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0015 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_HOST_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0016 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_IBSS_STATION_IND ((CsrWifiSmePrim)(0x0017 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_KEY_CFM ((CsrWifiSmePrim)(0x0018 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_LINK_QUALITY_GET_CFM ((CsrWifiSmePrim)(0x0019 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MEDIA_STATUS_IND ((CsrWifiSmePrim)(0x001A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x001B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x001C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_GET_CFM ((CsrWifiSmePrim)(0x001D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_GET_NEXT_CFM ((CsrWifiSmePrim)(0x001E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIB_SET_CFM ((CsrWifiSmePrim)(0x001F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MIC_FAILURE_IND ((CsrWifiSmePrim)(0x0020 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_MULTICAST_ADDRESS_CFM ((CsrWifiSmePrim)(0x0021 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_PACKET_FILTER_SET_CFM ((CsrWifiSmePrim)(0x0022 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM ((CsrWifiSmePrim)(0x0023 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND ((CsrWifiSmePrim)(0x0024 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_PMKID_CFM ((CsrWifiSmePrim)(0x0025 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_POWER_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0026 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_POWER_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0027 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM ((CsrWifiSmePrim)(0x0028 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAM_COMPLETE_IND ((CsrWifiSmePrim)(0x0029 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAM_START_IND ((CsrWifiSmePrim)(0x002A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x002B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x002C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x002D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x002E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_FULL_CFM ((CsrWifiSmePrim)(0x002F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_RESULT_IND ((CsrWifiSmePrim)(0x0030 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM ((CsrWifiSmePrim)(0x0031 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SCAN_RESULTS_GET_CFM ((CsrWifiSmePrim)(0x0032 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0033 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0034 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM ((CsrWifiSmePrim)(0x0035 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_TSPEC_IND ((CsrWifiSmePrim)(0x0036 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_TSPEC_CFM ((CsrWifiSmePrim)(0x0037 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_VERSIONS_GET_CFM ((CsrWifiSmePrim)(0x0038 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM ((CsrWifiSmePrim)(0x0039 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_OFF_IND ((CsrWifiSmePrim)(0x003A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_OFF_CFM ((CsrWifiSmePrim)(0x003B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_ON_CFM ((CsrWifiSmePrim)(0x003C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM ((CsrWifiSmePrim)(0x003D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM ((CsrWifiSmePrim)(0x003E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WIFI_ON_IND ((CsrWifiSmePrim)(0x003F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0040 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0041 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM ((CsrWifiSmePrim)(0x0042 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_ERROR_IND ((CsrWifiSmePrim)(0x0043 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_INFO_IND ((CsrWifiSmePrim)(0x0044 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_CORE_DUMP_IND ((CsrWifiSmePrim)(0x0045 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AMP_STATUS_CHANGE_IND ((CsrWifiSmePrim)(0x0046 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_WPS_CONFIGURATION_CFM ((CsrWifiSmePrim)(0x0047 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) + +#define CSR_WIFI_SME_PRIM_UPSTREAM_HIGHEST (0x0047 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST) + +#define CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_SME_PRIM_UPSTREAM_COUNT (CSR_WIFI_SME_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST) + +/******************************************************************************* + + NAME + CsrWifiSmeActivateReq + + DESCRIPTION + The WMA sends this primitive to activate the SME. + The WMA must activate the SME before it can send any other primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeActivateReq; + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigGetReq + + DESCRIPTION + This primitive gets the value of the adHocConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeAdhocConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigSetReq + + DESCRIPTION + This primitive sets the value of the adHocConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + adHocConfig - Sets the values to use when starting an ad hoc network. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeAdHocConfig adHocConfig; +} CsrWifiSmeAdhocConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeBlacklistReq + + DESCRIPTION + The wireless manager application should call this primitive to notify the + driver of any networks that should not be connected to. The interface + allows the wireless manager application to query, add, remove, and flush + the BSSIDs that the driver may not connect or roam to. + When this primitive adds to the black list the BSSID to which the SME is + currently connected, the SME will try to roam, if applicable, to another + BSSID in the same ESS; if the roaming procedure fails, the SME will + disconnect. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs + the driver to modify or provide the list of blacklisted + networks. + setAddressCount - Number of BSSIDs sent with this primitive + setAddresses - Pointer to the list of BBSIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeListAction action; + CsrUint8 setAddressCount; + CsrWifiMacAddress *setAddresses; +} CsrWifiSmeBlacklistReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataGetReq + + DESCRIPTION + This primitive retrieves the Wi-Fi radio calibration data. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeCalibrationDataGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataSetReq + + DESCRIPTION + This primitive sets the Wi-Fi radio calibration data. + The usage of the primitive with proper calibration data will avoid + time-consuming configuration after power-up. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + calibrationDataLength - Number of bytes in the buffer pointed by + calibrationData + calibrationData - Pointer to a buffer of length calibrationDataLength + containing the calibration data + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 calibrationDataLength; + CsrUint8 *calibrationData; +} CsrWifiSmeCalibrationDataSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigGetReq + + DESCRIPTION + This primitive gets the value of the CcxConfig parameter. + CURRENTLY NOT SUPPORTED. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeCcxConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigSetReq + + DESCRIPTION + This primitive sets the value of the CcxConfig parameter. + CURRENTLY NOT SUPPORTED. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + ccxConfig - Currently not supported + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeCcxConfig ccxConfig; +} CsrWifiSmeCcxConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigGetReq + + DESCRIPTION + This primitive gets the value of the CoexConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeCoexConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigSetReq + + DESCRIPTION + This primitive sets the value of the CoexConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + coexConfig - Configures the coexistence behaviour + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeCoexConfig coexConfig; +} CsrWifiSmeCoexConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexInfoGetReq + + DESCRIPTION + This primitive gets the value of the CoexInfo parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeCoexInfoGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectReq + + DESCRIPTION + The wireless manager application calls this primitive to start the + process of joining an 802.11 wireless network or to start an ad hoc + network. + The structure pointed by connectionConfig contains parameters describing + the network to join or, in case of an ad hoc network, to host or join. + The SME will select a network, perform the IEEE 802.11 Join, Authenticate + and Associate exchanges. + The SME selects the networks from the current scan list that match both + the SSID and BSSID, however either or both of these may be the wildcard + value. Using this rule, the following operations are possible: + * To connect to a network by name, specify the SSID and set the BSSID to + 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF. If there are two or more networks visible, + the SME will select the one with the strongest signal. + * To connect to a specific network, specify the BSSID. The SSID is + optional, but if given it must match the SSID of the network. An empty + SSID may be specified by setting the SSID length to zero. Please note + that if the BSSID is specified (i.e. not equal to 0xFF 0xFF 0xFF 0xFF + 0xFF 0xFF), the SME will not attempt to roam if signal conditions become + poor, even if there is an alternative AP with an SSID that matches the + current network SSID. + * To connect to any network matching the other parameters (i.e. security, + etc), set the SSID length to zero and set the BSSID to 0xFF 0xFF 0xFF + 0xFF 0xFF 0xFF. In this case, the SME will order all available networks + by their signal strengths and will iterate through this list until it + successfully connects. + NOTE: Specifying the BSSID will restrict the selection to one specific + network. If SSID and BSSID are given, they must both match the network + for it to be selected. To select a network based on the SSID only, the + wireless manager application must set the BSSID to 0xFF 0xFF 0xFF 0xFF + 0xFF 0xFF. + The SME will try to connect to each network that matches the provided + parameters, one by one, until it succeeds or has tried unsuccessfully + with all the matching networks. + If there is no network that matches the parameters and the request allows + to host an ad hoc network, the SME will advertise a new ad hoc network + instead. + If the SME cannot connect, it will notify the failure in the confirm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + connectionConfig - Describes the candidate network to join or to host. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeConnectionConfig connectionConfig; +} CsrWifiSmeConnectReq; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionConfigGetReq + + DESCRIPTION + This primitive gets the value of the ConnectionConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeConnectionConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionInfoGetReq + + DESCRIPTION + This primitive gets the value of the ConnectionInfo parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeConnectionInfoGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionStatsGetReq + + DESCRIPTION + This primitive gets the value of the ConnectionStats parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeConnectionStatsGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeDeactivateReq + + DESCRIPTION + The WMA sends this primitive to deactivate the SME. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeDeactivateReq; + +/******************************************************************************* + + NAME + CsrWifiSmeDisconnectReq + + DESCRIPTION + The wireless manager application may disconnect from the current network + by calling this primitive + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeDisconnectReq; + +/******************************************************************************* + + NAME + CsrWifiSmeEventMaskSetReq + + DESCRIPTION + The wireless manager application may register with the SME to receive + notification of interesting events. Indications will be sent only if the + wireless manager explicitly registers to be notified of that event. + indMask is a bit mask of values defined in CsrWifiSmeIndicationsMask. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + indMask - Set mask with values from CsrWifiSmeIndications + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeIndicationsMask indMask; +} CsrWifiSmeEventMaskSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigGetReq + + DESCRIPTION + This primitive gets the value of the hostConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeHostConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigSetReq + + DESCRIPTION + This primitive sets the value of the hostConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + hostConfig - Communicates a change of host power state (for example, on + mains power, on battery power etc) and of the periodicity of + traffic data + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeHostConfig hostConfig; +} CsrWifiSmeHostConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeKeyReq + + DESCRIPTION + The wireless manager application calls this primitive to add or remove + keys that the chip should use for encryption of data. + The interface allows the wireless manager application to add and remove + keys according to the specified action. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs the + driver to modify or provide the list of keys. + CSR_WIFI_SME_LIST_ACTION_GET is not supported here. + key - Key to be added or removed + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeListAction action; + CsrWifiSmeKey key; +} CsrWifiSmeKeyReq; + +/******************************************************************************* + + NAME + CsrWifiSmeLinkQualityGetReq + + DESCRIPTION + This primitive gets the value of the LinkQuality parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeLinkQualityGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigGetReq + + DESCRIPTION + This primitive gets the value of the MibConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeMibConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigSetReq + + DESCRIPTION + This primitive sets the value of the MibConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mibConfig - Conveys the desired value of various IEEE 802.11 attributes as + currently configured + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeMibConfig mibConfig; +} CsrWifiSmeMibConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetNextReq + + DESCRIPTION + To read a sequence of MIB parameters, for example a table, call this + primitive to find the name of the next MIB variable + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to a VarBind or VarBindList containing the + name(s) of the MIB variable(s) to search from. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 mibAttributeLength; + CsrUint8 *mibAttribute; +} CsrWifiSmeMibGetNextReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetReq + + DESCRIPTION + The wireless manager application calls this primitive to retrieve one or + more MIB variables. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names of the MIB variables to be retrieved + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 mibAttributeLength; + CsrUint8 *mibAttribute; +} CsrWifiSmeMibGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMibSetReq + + DESCRIPTION + The SME provides raw access to the MIB on the chip, which may be used by + some configuration or diagnostic utilities, but is not normally needed by + the wireless manager application. + The MIB access functions use BER encoded names (OID) of the MIB + parameters and BER encoded values, as described in the chip Host + Interface Protocol Specification. + The MIB parameters are described in 'Wi-Fi 5.0.0 Management Information + Base Reference Guide'. + The wireless manager application calls this primitive to set one or more + MIB variables + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names and values of the MIB variables to set + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 mibAttributeLength; + CsrUint8 *mibAttribute; +} CsrWifiSmeMibSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeMulticastAddressReq + + DESCRIPTION + The wireless manager application calls this primitive to specify the + multicast addresses which the chip should recognise. The interface allows + the wireless manager application to query, add, remove and flush the + multicast addresses for the network interface according to the specified + action. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter + instructs the driver to modify or provide the list of + MAC addresses. + setAddressesCount - Number of MAC addresses sent with the primitive + setAddresses - Pointer to the list of MAC Addresses sent with the + primitive, set to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeListAction action; + CsrUint8 setAddressesCount; + CsrWifiMacAddress *setAddresses; +} CsrWifiSmeMulticastAddressReq; + +/******************************************************************************* + + NAME + CsrWifiSmePacketFilterSetReq + + DESCRIPTION + The wireless manager application should call this primitive to enable or + disable filtering of broadcast packets: uninteresting broadcast packets + will be dropped by the Wi-Fi chip, instead of passing them up to the + host. + This has the advantage of saving power in the host application processor + as it removes the need to process unwanted packets. + All broadcast packets are filtered according to the filter and the filter + mode provided, except ARP packets, which are filtered using + arpFilterAddress. + Filters are not cumulative: only the parameters specified in the most + recent successful request are significant. + For more information, see 'UniFi Firmware API Specification'. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + filterLength - Length of the filter in bytes. + filterLength=0 disables the filter previously set + filter - Points to the first byte of the filter provided, if any. + This shall include zero or more instance of the + information elements of one of these types + * Traffic Classification (TCLAS) elements + * WMM-SA TCLAS elements + mode - Specifies whether the filter selects or excludes packets + matching the filter + arpFilterAddress - IPv4 address to be used for filtering the ARP packets. + * If the specified address is the IPv4 broadcast address + (255.255.255.255), all ARP packets are reported to the + host, + * If the specified address is NOT the IPv4 broadcast + address, only ARP packets with the specified address in + the Source or Target Protocol Address fields are reported + to the host + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint16 filterLength; + CsrUint8 *filter; + CsrWifiSmePacketFilterMode mode; + CsrWifiIp4Address arpFilterAddress; +} CsrWifiSmePacketFilterSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmePermanentMacAddressGetReq + + DESCRIPTION + This primitive retrieves the MAC address stored in EEPROM + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmePermanentMacAddressGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmePmkidReq + + DESCRIPTION + The wireless manager application calls this primitive to request an + operation on the SME PMKID list. + The action argument specifies the operation to perform. + When the connection is complete, the wireless manager application may + then send and receive EAPOL packets to complete WPA or WPA2 + authentication if appropriate. + The wireless manager application can then pass the resulting encryption + keys using this primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + action - The value of the CsrWifiSmeListAction parameter instructs + the driver to modify or provide the list of PMKIDs. + setPmkidsCount - Number of PMKIDs sent with the primitive + setPmkids - Pointer to the list of PMKIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeListAction action; + CsrUint8 setPmkidsCount; + CsrWifiSmePmkid *setPmkids; +} CsrWifiSmePmkidReq; + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigGetReq + + DESCRIPTION + This primitive gets the value of the PowerConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmePowerConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigSetReq + + DESCRIPTION + This primitive sets the value of the PowerConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + powerConfig - Power saving configuration + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmePowerConfig powerConfig; +} CsrWifiSmePowerConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomainInfoGetReq + + DESCRIPTION + This primitive gets the value of the RegulatoryDomainInfo parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeRegulatoryDomainInfoGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigGetReq + + DESCRIPTION + This primitive gets the value of the RoamingConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeRoamingConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigSetReq + + DESCRIPTION + This primitive sets the value of the RoamingConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + roamingConfig - Desired roaming behaviour values + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeRoamingConfig roamingConfig; +} CsrWifiSmeRoamingConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigGetReq + + DESCRIPTION + This primitive gets the value of the ScanConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeScanConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigSetReq + + DESCRIPTION + This primitive sets the value of the ScanConfig parameter. + The SME normally configures the firmware to perform autonomous scanning + without involving the host. + The firmware passes beacon / probe response or indicates loss of beacon + on certain changes of state, for example: + * A new AP is seen for the first time + * An AP is no longer visible + * The signal strength of an AP changes by more than a certain amount, as + configured by the thresholds in the scanConfig parameter + In addition to the autonomous scan, the wireless manager application may + request a scan at any time using CSR_WIFI_SME_SCAN_FULL_REQ. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + scanConfig - Reports the configuration for the autonomous scanning behaviour + of the firmware + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeScanConfig scanConfig; +} CsrWifiSmeScanConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeScanFullReq + + DESCRIPTION + The wireless manager application should call this primitive to request a + full scan. + Channels are scanned actively or passively according to the requirement + set by regulatory domain. + If the SME receives this primitive while a full scan is going on, the new + request is buffered and it will be served after the current full scan is + completed. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + ssidCount - Number of SSIDs provided. + If it is 0, the SME will attempt to detect any network + ssid - Points to the first SSID provided, if any. + bssid - BSS identifier. + If it is equal to FF-FF-FF-FF-FF, the SME will listen for + messages from any BSS. + If it is different from FF-FF-FF-FF-FF and any SSID is + provided, one SSID must match the network of the BSS. + forceScan - Forces the scan even if the SME is in a state which would + normally prevent it (e.g. autonomous scan is running). + bssType - Type of BSS to scan for + scanType - Type of scan to perform + channelListCount - Number of channels provided. + If it is 0, the SME will initiate a scan of all the + supported channels that are permitted by the current + regulatory domain. + channelList - Points to the first channel , or NULL if channelListCount + is zero. + probeIeLength - Length of the information element in bytes to be sent + with the probe message. + probeIe - Points to the first byte of the information element to be + sent with the probe message. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint8 ssidCount; + CsrWifiSsid *ssid; + CsrWifiMacAddress bssid; + CsrBool forceScan; + CsrWifiSmeBssType bssType; + CsrWifiSmeScanType scanType; + CsrUint16 channelListCount; + CsrUint8 *channelList; + CsrUint16 probeIeLength; + CsrUint8 *probeIe; +} CsrWifiSmeScanFullReq; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsFlushReq + + DESCRIPTION + The Wireless Manager calls this primitive to ask the SME to delete all + scan results from its cache, except for the scan result of any currently + connected network. + As scan results are received by the SME from the firmware, they are + cached in the SME memory. + Any time the Wireless Manager requests scan results, they are returned + from the SME internal cache. + For some applications it may be desirable to clear this cache prior to + requesting that a scan be performed; this will ensure that the cache then + only contains the networks detected in the most recent scan. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeScanResultsFlushReq; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsGetReq + + DESCRIPTION + The wireless manager application calls this primitive to retrieve the + current set of scan results, either after receiving a successful + CSR_WIFI_SME_SCAN_FULL_CFM, or to get autonomous scan results. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeScanResultsGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigGetReq + + DESCRIPTION + This primitive gets the value of the SmeStaConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeSmeStaConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigSetReq + + DESCRIPTION + This primitive sets the value of the SmeConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + smeConfig - SME Station Parameters to be set + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeStaConfig smeConfig; +} CsrWifiSmeSmeStaConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeStationMacAddressGetReq + + DESCRIPTION + This primitives is used to retrieve the current MAC address used by the + station. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeStationMacAddressGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeTspecReq + + DESCRIPTION + The wireless manager application should call this primitive to use the + TSPEC feature. + The chip supports the use of TSPECs and TCLAS for the use of IEEE + 802.11/WMM Quality of Service features. + The API allows the wireless manager application to supply a correctly + formatted TSPEC and TCLAS pair to the driver. + After performing basic validation, the driver negotiates the installation + of the TSPEC with the AP as defined by the 802.11 specification. + The driver retains all TSPEC and TCLAS pairs until they are specifically + removed. + It is not compulsory for a TSPEC to have a TCLAS (NULL is used to + indicate that no TCLAS is supplied), while a TCLASS always require a + TSPEC. + The format of the TSPEC element is specified in 'WMM (including WMM Power + Save) Specification - Version 1.1' and 'ANSI/IEEE Std 802.11-REVmb/D3.0'. + For more information, see 'UniFi Configuring WMM and WMM-PS'. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + action - Specifies the action to be carried out on the list of TSPECs. + CSR_WIFI_SME_LIST_ACTION_FLUSH is not applicable here. + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + strict - If it set to false, allows the SME to perform automatic + TSPEC negotiation + ctrlMask - Additional TSPEC configuration for CCX. + Set mask with values from CsrWifiSmeTspecCtrl. + CURRENTLY NOT SUPPORTED + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + tclasLength - Length of the TCLAS. + If it is equal to 0, no TCLASS is provided for the TSPEC + tclas - Points to the first byte of the TCLAS, if any. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeListAction action; + CsrUint32 transactionId; + CsrBool strict; + CsrWifiSmeTspecCtrlMask ctrlMask; + CsrUint16 tspecLength; + CsrUint8 *tspec; + CsrUint16 tclasLength; + CsrUint8 *tclas; +} CsrWifiSmeTspecReq; + +/******************************************************************************* + + NAME + CsrWifiSmeVersionsGetReq + + DESCRIPTION + This primitive gets the value of the Versions parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeVersionsGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiFlightmodeReq + + DESCRIPTION + The wireless manager application may call this primitive on boot-up of + the platform to ensure that the chip is placed in a mode that prevents + any emission of RF energy. + This primitive is an alternative to CSR_WIFI_SME_WIFI_ON_REQ. + As in CSR_WIFI_SME_WIFI_ON_REQ, it causes the download of the patch file + (if any) and the programming of the initial MIB settings (if supplied by + the WMA), but it also ensures that the chip is left in its lowest + possible power-mode with the radio subsystems disabled. + This feature is useful on platforms where power cannot be removed from + the chip (leaving the chip not initialised will cause it to consume more + power so calling this function ensures that the chip is initialised into + a low power mode but without entering a state where it could emit any RF + energy). + NOTE: this primitive does not cause the Wi-Fi to change state: Wi-Fi + stays conceptually off. Configuration primitives can be sent after + CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ and the configuration will be maintained. + Requests that require the state of the Wi-Fi to be ON will return + CSR_WIFI_SME_STATUS_WIFI_OFF in their confirms. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + address - Optionally specifies a station MAC address. + In normal use, the manager should set the address to 0xFF + 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use + the MAC address in the MIB. + mibFilesCount - Number of provided data blocks with initial MIB values + mibFiles - Points to the first data block with initial MIB values. + These data blocks are typically the contents of the provided + files ufmib.dat and localmib.dat, available from the host + file system, if they exist. + These files typically contain radio tuning and calibration + values. + More values can be created using the Host Tools. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiMacAddress address; + CsrUint16 mibFilesCount; + CsrWifiSmeDataBlock *mibFiles; +} CsrWifiSmeWifiFlightmodeReq; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffReq + + DESCRIPTION + The wireless manager application calls this primitive to turn off the + chip, thus saving power when Wi-Fi is not in use. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeWifiOffReq; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnReq + + DESCRIPTION + The wireless manager application calls this primitive to turn on the + Wi-Fi chip. + If the Wi-Fi chip is currently off, the SME turns the Wi-Fi chip on, + downloads the patch file (if any), and programs the initial MIB settings + (if supplied by the WMA). + The patch file is not provided with the SME API; its downloading is + automatic and handled internally by the system. + The MIB settings, when provided, override the default values that the + firmware loads from EEPROM. + If the Wi-Fi chip is already on, the SME takes no action and returns a + successful status in the confirm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + address - Optionally specifies a station MAC address. + In normal use, the manager should set the address to 0xFF + 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use + the MAC address in the MIB + mibFilesCount - Number of provided data blocks with initial MIB values + mibFiles - Points to the first data block with initial MIB values. + These data blocks are typically the contents of the provided + files ufmib.dat and localmib.dat, available from the host + file system, if they exist. + These files typically contain radio tuning and calibration + values. + More values can be created using the Host Tools. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiMacAddress address; + CsrUint16 mibFilesCount; + CsrWifiSmeDataBlock *mibFiles; +} CsrWifiSmeWifiOnReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsSetReq + + DESCRIPTION + This primitive sets the list of cloaked SSIDs for which the WMA possesses + profiles. + When the driver detects a cloaked AP, the SME will explicitly scan for it + using the list of cloaked SSIDs provided it, and, if the scan succeeds, + it will report the AP to the WMA either via CSR_WIFI_SME_SCAN_RESULT_IND + (if registered) or via CSR_WIFI_SCAN_RESULT_GET_CFM. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + cloakedSsids - Sets the list of cloaked SSIDs + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeCloakedSsidConfig cloakedSsids; +} CsrWifiSmeCloakedSsidsSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsGetReq + + DESCRIPTION + This primitive gets the value of the CloakedSsids parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeCloakedSsidsGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigGetReq + + DESCRIPTION + This primitive gets the value of the Sme common parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeSmeCommonConfigGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigSetReq + + DESCRIPTION + This primitive sets the value of the Sme common. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + deviceConfig - Configuration options in the SME + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeDeviceConfig deviceConfig; +} CsrWifiSmeSmeCommonConfigSetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeInterfaceCapabilityGetReq + + DESCRIPTION + The Wireless Manager calls this primitive to ask the SME for the + capabilities of the supported interfaces + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; +} CsrWifiSmeInterfaceCapabilityGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigurationReq + + DESCRIPTION + This primitive passes the WPS information for the device to SME. This may + be accepted only if no interface is active. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + wpsConfig - WPS config. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeWpsConfig wpsConfig; +} CsrWifiSmeWpsConfigurationReq; + +/******************************************************************************* + + NAME + CsrWifiSmeActivateCfm + + DESCRIPTION + The SME sends this primitive when the activation is complete. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeActivateCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + adHocConfig - Contains the values used when starting an Ad-hoc (IBSS) + connection. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeAdHocConfig adHocConfig; +} CsrWifiSmeAdhocConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeAdhocConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeAdhocConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeAssociationCompleteInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it completes an attempt to associate with an AP. If + the association was successful, status will be set to + CSR_WIFI_SME_STATUS_SUCCESS, otherwise status and deauthReason shall be + set to appropriate error codes. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the association procedure + connectionInfo - This parameter is relevant only if result is + CSR_WIFI_SME_STATUS_SUCCESS: + it points to the connection information for the new network + deauthReason - This parameter is relevant only if result is not + CSR_WIFI_SME_STATUS_SUCCESS: + if the AP deauthorised the station, it gives the reason of + the deauthorization + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeConnectionInfo connectionInfo; + CsrWifiSmeIEEE80211Reason deauthReason; +} CsrWifiSmeAssociationCompleteInd; + +/******************************************************************************* + + NAME + CsrWifiSmeAssociationStartInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it begins an attempt to associate with an AP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + address - BSSID of the associating network + ssid - Service Set identifier of the associating network + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiMacAddress address; + CsrWifiSsid ssid; +} CsrWifiSmeAssociationStartInd; + +/******************************************************************************* + + NAME + CsrWifiSmeBlacklistCfm + + DESCRIPTION + The SME will call this primitive when the action on the blacklist has + completed. For a GET action, this primitive also reports the list of + BBSIDs in the blacklist. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getAddressCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of BSSIDs sent with this primitive + getAddresses - Pointer to the list of BBSIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeListAction action; + CsrUint8 getAddressCount; + CsrWifiMacAddress *getAddresses; +} CsrWifiSmeBlacklistCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + calibrationDataLength - Number of bytes in the buffer pointed by + calibrationData + calibrationData - Pointer to a buffer of length calibrationDataLength + containing the calibration data + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint16 calibrationDataLength; + CsrUint8 *calibrationData; +} CsrWifiSmeCalibrationDataGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCalibrationDataSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeCalibrationDataSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + ccxConfig - Currently not supported + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeCcxConfig ccxConfig; +} CsrWifiSmeCcxConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCcxConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeCcxConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + coexConfig - Reports the parameters used to configure the coexistence + behaviour + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeCoexConfig coexConfig; +} CsrWifiSmeCoexConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeCoexConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCoexInfoGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + coexInfo - Reports information and state related to coexistence. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeCoexInfo coexInfo; +} CsrWifiSmeCoexInfoGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectCfm + + DESCRIPTION + The SME calls this primitive when the connection exchange is complete or + all connection attempts fail. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request. + CSR_WIFI_SME_STATUS_NOT_FOUND: all attempts by the SME to + locate the requested AP failed + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeConnectCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionConfig - Parameters used by the SME for selecting a network + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeConnectionConfig connectionConfig; +} CsrWifiSmeConnectionConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionInfoGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionInfo - Information about the current connection + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeConnectionInfo connectionInfo; +} CsrWifiSmeConnectionInfoGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionQualityInd + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever the value of the current connection quality + parameters change by more than a certain configurable amount. + The wireless manager application may configure the trigger thresholds for + this indication using the field in smeConfig parameter of + CSR_WIFI_SME_SME_CONFIG_SET_REQ. + Connection quality messages can be suppressed by setting both thresholds + to zero. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + linkQuality - Indicates the quality of the link + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeLinkQuality linkQuality; +} CsrWifiSmeConnectionQualityInd; + +/******************************************************************************* + + NAME + CsrWifiSmeConnectionStatsGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + connectionStats - Statistics for current connection. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeConnectionStats connectionStats; +} CsrWifiSmeConnectionStatsGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeDeactivateCfm + + DESCRIPTION + The SME sends this primitive when the deactivation is complete. + The WMA cannot send any more primitives until it actives the SME again + sending another CSR_WIFI_SME_ACTIVATE_REQ. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeDeactivateCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeDisconnectCfm + + DESCRIPTION + On reception of CSR_WIFI_SME_DISCONNECT_REQ the SME will perform a + disconnect operation, sending a CsrWifiSmeMediaStatusInd with + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED and then call this primitive when + disconnection is complete. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeDisconnectCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeEventMaskSetCfm + + DESCRIPTION + The SME calls the primitive to report the result of the request + primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeEventMaskSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + hostConfig - Current host power state. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeHostConfig hostConfig; +} CsrWifiSmeHostConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeHostConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeHostConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeIbssStationInd + + DESCRIPTION + The SME will send this primitive to indicate that a station has joined or + left the ad-hoc network. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + address - MAC address of the station that has joined or left + isconnected - TRUE if the station joined, FALSE if the station left + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiMacAddress address; + CsrBool isconnected; +} CsrWifiSmeIbssStationInd; + +/******************************************************************************* + + NAME + CsrWifiSmeKeyCfm + + DESCRIPTION + The SME calls the primitive to report the result of the request + primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + keyType - Type of the key added/deleted + peerMacAddress - Peer MAC Address of the key added/deleted + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeListAction action; + CsrWifiSmeKeyType keyType; + CsrWifiMacAddress peerMacAddress; +} CsrWifiSmeKeyCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeLinkQualityGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + linkQuality - Indicates the quality of the link + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeLinkQuality linkQuality; +} CsrWifiSmeLinkQualityGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMediaStatusInd + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it when a network connection is established, lost or has moved to + another AP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + mediaStatus - Indicates the media status + connectionInfo - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_CONNECTED: + it points to the connection information for the new network + disassocReason - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: + if a disassociation has occurred it gives the reason of the + disassociation + deauthReason - This parameter is relevant only if the mediaStatus is + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: + if a deauthentication has occurred it gives the reason of + the deauthentication + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeMediaStatus mediaStatus; + CsrWifiSmeConnectionInfo connectionInfo; + CsrWifiSmeIEEE80211Reason disassocReason; + CsrWifiSmeIEEE80211Reason deauthReason; +} CsrWifiSmeMediaStatusInd; + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + mibConfig - Reports various IEEE 802.11 attributes as currently configured + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeMibConfig mibConfig; +} CsrWifiSmeMibConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMibConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeMibConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetCfm + + DESCRIPTION + The SME calls this primitive to return the requested MIB variable values. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to the VarBind or VarBindList containing the + names and values of the MIB variables requested + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint16 mibAttributeLength; + CsrUint8 *mibAttribute; +} CsrWifiSmeMibGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMibGetNextCfm + + DESCRIPTION + The SME calls this primitive to return the requested MIB name(s). + The wireless manager application can then read the value of the MIB + variable using CSR_WIFI_SME_MIB_GET_REQ, using the names provided. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + mibAttributeLength - Length of mibAttribute + mibAttribute - Points to a VarBind or VarBindList containing the + name(s) of the MIB variable(s) lexicographically + following the name(s) given in the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint16 mibAttributeLength; + CsrUint8 *mibAttribute; +} CsrWifiSmeMibGetNextCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMibSetCfm + + DESCRIPTION + The SME calls the primitive to report the result of the set primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeMibSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeMicFailureInd + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever the chip firmware reports a MIC failure. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + secondFailure - TRUE if this indication is for a second failure in 60 + seconds + count - The number of MIC failure events since the connection was + established + address - MAC address of the transmitter that caused the MIC failure + keyType - Type of key for which the failure occurred + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrBool secondFailure; + CsrUint16 count; + CsrWifiMacAddress address; + CsrWifiSmeKeyType keyType; +} CsrWifiSmeMicFailureInd; + +/******************************************************************************* + + NAME + CsrWifiSmeMulticastAddressCfm + + DESCRIPTION + The SME will call this primitive when the operation is complete. For a + GET action, this primitive reports the current list of MAC addresses. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getAddressesCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of MAC addresses sent with the primitive + getAddresses - Pointer to the list of MAC Addresses sent with the + primitive, set to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeListAction action; + CsrUint8 getAddressesCount; + CsrWifiMacAddress *getAddresses; +} CsrWifiSmeMulticastAddressCfm; + +/******************************************************************************* + + NAME + CsrWifiSmePacketFilterSetCfm + + DESCRIPTION + The SME calls the primitive to report the result of the set primitive. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmePacketFilterSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmePermanentMacAddressGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + permanentMacAddress - MAC address stored in the EEPROM + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiMacAddress permanentMacAddress; +} CsrWifiSmePermanentMacAddressGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmePmkidCandidateListInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it when a new network supporting preauthentication and/or PMK + caching is seen. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an + interface + pmkidCandidatesCount - Number of PMKID candidates provided + pmkidCandidates - Points to the first PMKID candidate + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint8 pmkidCandidatesCount; + CsrWifiSmePmkidCandidate *pmkidCandidates; +} CsrWifiSmePmkidCandidateListInd; + +/******************************************************************************* + + NAME + CsrWifiSmePmkidCfm + + DESCRIPTION + The SME will call this primitive when the operation is complete. For a + GET action, this primitive reports the current list of PMKIDs + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + action - Action in the request + getPmkidsCount - This parameter is only relevant if action is + CSR_WIFI_SME_LIST_ACTION_GET: + number of PMKIDs sent with the primitive + getPmkids - Pointer to the list of PMKIDs sent with the primitive, set + to NULL if none is sent. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeListAction action; + CsrUint8 getPmkidsCount; + CsrWifiSmePmkid *getPmkids; +} CsrWifiSmePmkidCfm; + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + powerConfig - Returns the current parameters for the power configuration of + the firmware + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmePowerConfig powerConfig; +} CsrWifiSmePowerConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmePowerConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmePowerConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeRegulatoryDomainInfoGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + regDomInfo - Reports information and state related to regulatory domain + operation. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeRegulatoryDomainInfo regDomInfo; +} CsrWifiSmeRegulatoryDomainInfoGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamCompleteInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it completes an attempt to roam to an AP. If the roam + attempt was successful, status will be set to CSR_WIFI_SME_SUCCESS, + otherwise it shall be set to the appropriate error code. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the roaming procedure + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeRoamCompleteInd; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamStartInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive it whenever it begins an attempt to roam to an AP. + If the wireless manager application connect request specified the SSID + and the BSSID was set to the broadcast address (0xFF 0xFF 0xFF 0xFF 0xFF + 0xFF), the SME monitors the signal quality and maintains a list of + candidates to roam to. When the signal quality of the current connection + falls below a threshold, and there is a candidate with better quality, + the SME will attempt to the candidate AP. + If the roaming procedure succeeds, the SME will also issue a Media + Connect indication to inform the wireless manager application of the + change. + NOTE: to prevent the SME from initiating roaming the WMA must specify the + BSSID in the connection request; this forces the SME to connect only to + that AP. + The wireless manager application can obtain statistics for roaming + purposes using CSR_WIFI_SME_CONNECTION_QUALITY_IND and + CSR_WIFI_SME_CONNECTION_STATS_GET_REQ. + When the wireless manager application wishes to roam to another AP, it + must issue a connection request specifying the BSSID of the desired AP. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + roamReason - Indicates the reason for starting the roaming procedure + reason80211 - Indicates the reason for deauthentication or disassociation + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeRoamReason roamReason; + CsrWifiSmeIEEE80211Reason reason80211; +} CsrWifiSmeRoamStartInd; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + roamingConfig - Reports the roaming behaviour of the driver and firmware + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeRoamingConfig roamingConfig; +} CsrWifiSmeRoamingConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeRoamingConfigSetCfm + + DESCRIPTION + This primitive sets the value of the RoamingConfig parameter. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeRoamingConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + scanConfig - Returns the current parameters for the autonomous scanning + behaviour of the firmware + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeScanConfig scanConfig; +} CsrWifiSmeScanConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeScanConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeScanConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeScanFullCfm + + DESCRIPTION + The SME calls this primitive when the results from the scan are + available. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeScanFullCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultInd + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it whenever a scan indication is received from the firmware. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + result - Points to a buffer containing a scan result. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeScanResult result; +} CsrWifiSmeScanResultInd; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsFlushCfm + + DESCRIPTION + The SME will call this primitive when the cache has been cleared. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeScanResultsFlushCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeScanResultsGetCfm + + DESCRIPTION + The SME sends this primitive to provide the current set of scan results. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + scanResultsCount - Number of scan results + scanResults - Points to a buffer containing an array of + CsrWifiSmeScanResult structures. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint16 scanResultsCount; + CsrWifiSmeScanResult *scanResults; +} CsrWifiSmeScanResultsGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + smeConfig - Current SME Station Parameters + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeStaConfig smeConfig; +} CsrWifiSmeSmeStaConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeStaConfigSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; +} CsrWifiSmeSmeStaConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeStationMacAddressGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + stationMacAddress - Current MAC address of the station. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiMacAddress stationMacAddress[2]; +} CsrWifiSmeStationMacAddressGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeTspecInd + + DESCRIPTION + The SME will send this primitive to all the task that have registered to + receive it when a status change in the TSPEC occurs. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + tspecResultCode - Specifies the TSPEC operation requested by the peer + station + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint32 transactionId; + CsrWifiSmeTspecResultCode tspecResultCode; + CsrUint16 tspecLength; + CsrUint8 *tspec; +} CsrWifiSmeTspecInd; + +/******************************************************************************* + + NAME + CsrWifiSmeTspecCfm + + DESCRIPTION + The SME calls the primitive to report the result of the TSpec primitive + request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface Identifier; unique identifier of an interface + status - Reports the result of the request + transactionId - Unique Transaction ID for the TSPEC, as assigned by the + driver + tspecResultCode - Specifies the result of the negotiated TSPEC operation + tspecLength - Length of the TSPEC. + tspec - Points to the first byte of the TSPEC + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrUint32 transactionId; + CsrWifiSmeTspecResultCode tspecResultCode; + CsrUint16 tspecLength; + CsrUint8 *tspec; +} CsrWifiSmeTspecCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeVersionsGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + versions - Version IDs of the product + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeVersions versions; +} CsrWifiSmeVersionsGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiFlightmodeCfm + + DESCRIPTION + The SME calls this primitive when the chip is initialised for low power + mode and with the radio subsystem disabled. To leave flight mode, and + enable Wi-Fi, the wireless manager application should call + CSR_WIFI_SME_WIFI_ON_REQ. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeWifiFlightmodeCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffInd + + DESCRIPTION + The SME sends this primitive to all the tasks that have registered to + receive it to report that the chip has been turned off. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + reason - Indicates the reason why the Wi-Fi has been switched off. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiSmeControlIndication reason; +} CsrWifiSmeWifiOffInd; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOffCfm + + DESCRIPTION + After receiving CSR_WIFI_SME_WIFI_OFF_REQ, if the chip is connected to a + network, the SME will perform a disconnect operation, will send a + CSR_WIFI_SME_MEDIA_STATUS_IND with + CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED, and then will call + CSR_WIFI_SME_WIFI_OFF_CFM when the chip is off. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeWifiOffCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnCfm + + DESCRIPTION + The SME sends this primitive to the task that has sent the request once + the chip has been initialised and is available for use. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeWifiOnCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsSetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeCloakedSsidsSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeCloakedSsidsGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + cloakedSsids - Reports list of cloaked SSIDs that are explicitly scanned for + by the driver + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeCloakedSsidConfig cloakedSsids; +} CsrWifiSmeCloakedSsidsGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeWifiOnInd + + DESCRIPTION + The SME sends this primitive to all tasks that have registered to receive + it once the chip becomes available and ready to use. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + address - Current MAC address + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiMacAddress address; +} CsrWifiSmeWifiOnInd; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + deviceConfig - Configuration options in the SME + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrWifiSmeDeviceConfig deviceConfig; +} CsrWifiSmeSmeCommonConfigGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeSmeCommonConfigSetCfm + + DESCRIPTION + Reports the result of the request + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Reports the result of the request + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeSmeCommonConfigSetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeInterfaceCapabilityGetCfm + + DESCRIPTION + This primitive reports the result of the request. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Result of the request + numInterfaces - Number of the interfaces supported + capBitmap - Points to the list of capabilities bitmaps provided for each + interface. + The bits represent the following capabilities: + -bits 7 to 4-Reserved + -bit 3-AMP + -bit 2-P2P + -bit 1-AP + -bit 0-STA + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; + CsrUint16 numInterfaces; + CsrUint8 capBitmap[2]; +} CsrWifiSmeInterfaceCapabilityGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeErrorInd + + DESCRIPTION + Important error message indicating a error of some importance + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + errorMessage - Contains the error message. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrCharString *errorMessage; +} CsrWifiSmeErrorInd; + +/******************************************************************************* + + NAME + CsrWifiSmeInfoInd + + DESCRIPTION + Message indicating a some info about current activity. Mostly of interest + in testing but may be useful in the field. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + infoMessage - Contains the message. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrCharString *infoMessage; +} CsrWifiSmeInfoInd; + +/******************************************************************************* + + NAME + CsrWifiSmeCoreDumpInd + + DESCRIPTION + The SME will send this primitive to all the tasks that have registered to + receive Wi-Fi Chip core dump data. + The core dump data may be fragmented and sent using more than one + indication. + To indicate that all the data has been sent, the last indication contains + a 'length' of 0 and 'data' of NULL. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes of core + dump data + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint32 dataLength; + CsrUint8 *data; +} CsrWifiSmeCoreDumpInd; + +/******************************************************************************* + + NAME + CsrWifiSmeAmpStatusChangeInd + + DESCRIPTION + Indication of change to AMP activity. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - Interface on which the AMP activity changed. + ampStatus - The new status of AMP activity.Range: {AMP_ACTIVE, + AMP_INACTIVE}. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeAmpStatus ampStatus; +} CsrWifiSmeAmpStatusChangeInd; + +/******************************************************************************* + + NAME + CsrWifiSmeWpsConfigurationCfm + + DESCRIPTION + Confirm. + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + status - Status of the request. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrResult status; +} CsrWifiSmeWpsConfigurationCfm; + + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_PRIM_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_sme_sef.c b/drivers/staging/csr/csr_wifi_sme_sef.c new file mode 100644 index 000000000000..cf32254335c4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_sef.c @@ -0,0 +1,85 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + + *****************************************************************************/ +#include "csr_wifi_sme_sef.h" + +const CsrWifiSmeStateHandlerType CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT] = +{ + /* 0x8000 */ CsrWifiSmeActivateCfmHandler, + /* 0x8001 */ CsrWifiSmeAdhocConfigGetCfmHandler, + /* 0x8002 */ CsrWifiSmeAdhocConfigSetCfmHandler, + /* 0x8003 */ CsrWifiSmeAssociationCompleteIndHandler, + /* 0x8004 */ CsrWifiSmeAssociationStartIndHandler, + /* 0x8005 */ CsrWifiSmeBlacklistCfmHandler, + /* 0x8006 */ CsrWifiSmeCalibrationDataGetCfmHandler, + /* 0x8007 */ CsrWifiSmeCalibrationDataSetCfmHandler, + /* 0x8008 */ CsrWifiSmeCcxConfigGetCfmHandler, + /* 0x8009 */ CsrWifiSmeCcxConfigSetCfmHandler, + /* 0x800A */ CsrWifiSmeCoexConfigGetCfmHandler, + /* 0x800B */ CsrWifiSmeCoexConfigSetCfmHandler, + /* 0x800C */ CsrWifiSmeCoexInfoGetCfmHandler, + /* 0x800D */ CsrWifiSmeConnectCfmHandler, + /* 0x800E */ CsrWifiSmeConnectionConfigGetCfmHandler, + /* 0x800F */ CsrWifiSmeConnectionInfoGetCfmHandler, + /* 0x8010 */ CsrWifiSmeConnectionQualityIndHandler, + /* 0x8011 */ CsrWifiSmeConnectionStatsGetCfmHandler, + /* 0x8012 */ CsrWifiSmeDeactivateCfmHandler, + /* 0x8013 */ CsrWifiSmeDisconnectCfmHandler, + /* 0x8014 */ CsrWifiSmeEventMaskSetCfmHandler, + /* 0x8015 */ CsrWifiSmeHostConfigGetCfmHandler, + /* 0x8016 */ CsrWifiSmeHostConfigSetCfmHandler, + /* 0x8017 */ CsrWifiSmeIbssStationIndHandler, + /* 0x8018 */ CsrWifiSmeKeyCfmHandler, + /* 0x8019 */ CsrWifiSmeLinkQualityGetCfmHandler, + /* 0x801A */ CsrWifiSmeMediaStatusIndHandler, + /* 0x801B */ CsrWifiSmeMibConfigGetCfmHandler, + /* 0x801C */ CsrWifiSmeMibConfigSetCfmHandler, + /* 0x801D */ CsrWifiSmeMibGetCfmHandler, + /* 0x801E */ CsrWifiSmeMibGetNextCfmHandler, + /* 0x801F */ CsrWifiSmeMibSetCfmHandler, + /* 0x8020 */ CsrWifiSmeMicFailureIndHandler, + /* 0x8021 */ CsrWifiSmeMulticastAddressCfmHandler, + /* 0x8022 */ CsrWifiSmePacketFilterSetCfmHandler, + /* 0x8023 */ CsrWifiSmePermanentMacAddressGetCfmHandler, + /* 0x8024 */ CsrWifiSmePmkidCandidateListIndHandler, + /* 0x8025 */ CsrWifiSmePmkidCfmHandler, + /* 0x8026 */ CsrWifiSmePowerConfigGetCfmHandler, + /* 0x8027 */ CsrWifiSmePowerConfigSetCfmHandler, + /* 0x8028 */ CsrWifiSmeRegulatoryDomainInfoGetCfmHandler, + /* 0x8029 */ CsrWifiSmeRoamCompleteIndHandler, + /* 0x802A */ CsrWifiSmeRoamStartIndHandler, + /* 0x802B */ CsrWifiSmeRoamingConfigGetCfmHandler, + /* 0x802C */ CsrWifiSmeRoamingConfigSetCfmHandler, + /* 0x802D */ CsrWifiSmeScanConfigGetCfmHandler, + /* 0x802E */ CsrWifiSmeScanConfigSetCfmHandler, + /* 0x802F */ CsrWifiSmeScanFullCfmHandler, + /* 0x8030 */ CsrWifiSmeScanResultIndHandler, + /* 0x8031 */ CsrWifiSmeScanResultsFlushCfmHandler, + /* 0x8032 */ CsrWifiSmeScanResultsGetCfmHandler, + /* 0x8033 */ CsrWifiSmeSmeStaConfigGetCfmHandler, + /* 0x8034 */ CsrWifiSmeSmeStaConfigSetCfmHandler, + /* 0x8035 */ CsrWifiSmeStationMacAddressGetCfmHandler, + /* 0x8036 */ CsrWifiSmeTspecIndHandler, + /* 0x8037 */ CsrWifiSmeTspecCfmHandler, + /* 0x8038 */ CsrWifiSmeVersionsGetCfmHandler, + /* 0x8039 */ CsrWifiSmeWifiFlightmodeCfmHandler, + /* 0x803A */ CsrWifiSmeWifiOffIndHandler, + /* 0x803B */ CsrWifiSmeWifiOffCfmHandler, + /* 0x803C */ CsrWifiSmeWifiOnCfmHandler, + /* 0x803D */ CsrWifiSmeCloakedSsidsSetCfmHandler, + /* 0x803E */ CsrWifiSmeCloakedSsidsGetCfmHandler, + /* 0x803F */ CsrWifiSmeWifiOnIndHandler, + /* 0x8040 */ CsrWifiSmeSmeCommonConfigGetCfmHandler, + /* 0x8041 */ CsrWifiSmeSmeCommonConfigSetCfmHandler, + /* 0x8042 */ CsrWifiSmeGetInterfaceCapabilityCfmHandler, + /* 0x8043 */ CsrWifiSmeErrorIndHandler, + /* 0x8044 */ CsrWifiSmeInfoIndHandler, + /* 0x8045 */ CsrWifiSmeCoreDumpIndHandler, + /* 0x8046 */ CsrWifiSmeAmpStatusChangeIndHandler, +}; diff --git a/drivers/staging/csr/csr_wifi_sme_sef.h b/drivers/staging/csr/csr_wifi_sme_sef.h new file mode 100644 index 000000000000..c8741811b2e4 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_sef.h @@ -0,0 +1,101 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + Confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ +#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ + +#include "csr_wifi_sme_prim.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*CsrWifiSmeStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg); + +extern const CsrWifiSmeStateHandlerType CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT]; + + +extern void CsrWifiSmeActivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeAdhocConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeAdhocConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeAssociationCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeAssociationStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeBlacklistCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCalibrationDataGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCalibrationDataSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCcxConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCcxConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCoexConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCoexConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCoexInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeConnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeConnectionConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeConnectionInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeConnectionQualityIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeConnectionStatsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeDeactivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeDisconnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeEventMaskSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeHostConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeHostConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeIbssStationIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeKeyCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeLinkQualityGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMibConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMibConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMibGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMibGetNextCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMibSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMicFailureIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeMulticastAddressCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePacketFilterSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePmkidCandidateListIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePmkidCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePowerConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmePowerConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeRoamCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeRoamStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeRoamingConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeRoamingConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanFullCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanResultIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanResultsFlushCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeScanResultsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeStationMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeTspecIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeTspecCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeVersionsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeWifiFlightmodeCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeWifiOffIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeWifiOffCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeWifiOnCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeWifiOnIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeErrorIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeInfoIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeCoreDumpIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); +extern void CsrWifiSmeAmpStatusChangeIndHandler(void* drvpriv, CsrWifiFsmEvent* msg); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.c b/drivers/staging/csr/csr_wifi_sme_serialize.c new file mode 100644 index 000000000000..489c378186bd --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_serialize.c @@ -0,0 +1,5756 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#include "csr_pmem.h" +#include "csr_msgconv.h" +#include "csr_unicode.h" + + +#include "csr_wifi_sme_prim.h" +#include "csr_wifi_sme_serialize.h" + +void CsrWifiSmePfree(void *ptr) +{ + CsrPmemFree(ptr); +} + + +CsrSize CsrWifiSmeAdhocConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.atimWindowTu */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.beaconPeriodTu */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.joinOnlyAttempts */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.joinAttemptIntervalMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeAdhocConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeAdhocConfigSetReq *primitive = (CsrWifiSmeAdhocConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.atimWindowTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.beaconPeriodTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.joinOnlyAttempts); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.joinAttemptIntervalMs); + return(ptr); +} + + +void* CsrWifiSmeAdhocConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeAdhocConfigSetReq *primitive = (CsrWifiSmeAdhocConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.atimWindowTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.beaconPeriodTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.joinOnlyAttempts, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.joinAttemptIntervalMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeBlacklistReqSizeof(void *msg) +{ + CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->setAddressCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->setAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeBlacklistReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->setAddressCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiSmeBlacklistReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *) CsrPmemAlloc(sizeof(CsrWifiSmeBlacklistReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->setAddressCount, buffer, &offset); + primitive->setAddresses = NULL; + if (primitive->setAddressCount) + { + primitive->setAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->setAddressCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressCount; i1++) + { + CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiSmeBlacklistReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *) voidPrimitivePointer; + CsrPmemFree(primitive->setAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCalibrationDataSetReqSizeof(void *msg) +{ + CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ + bufferSize += 2; /* CsrUint16 primitive->calibrationDataLength */ + bufferSize += primitive->calibrationDataLength; /* CsrUint8 primitive->calibrationData */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCalibrationDataSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->calibrationDataLength); + if (primitive->calibrationDataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->calibrationData, ((CsrUint16) (primitive->calibrationDataLength))); + } + return(ptr); +} + + +void* CsrWifiSmeCalibrationDataSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->calibrationDataLength, buffer, &offset); + if (primitive->calibrationDataLength) + { + primitive->calibrationData = (CsrUint8 *)CsrPmemAlloc(primitive->calibrationDataLength); + CsrMemCpyDes(primitive->calibrationData, buffer, &offset, ((CsrUint16) (primitive->calibrationDataLength))); + } + else + { + primitive->calibrationData = NULL; + } + + return primitive; +} + + +void CsrWifiSmeCalibrationDataSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->calibrationData); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCcxConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->ccxConfig.keepAliveTimeMs */ + bufferSize += 1; /* CsrBool primitive->ccxConfig.apRoamingEnabled */ + bufferSize += 1; /* CsrUint8 primitive->ccxConfig.measurementsMask */ + bufferSize += 1; /* CsrBool primitive->ccxConfig.ccxRadioMgtEnabled */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCcxConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCcxConfigSetReq *primitive = (CsrWifiSmeCcxConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.keepAliveTimeMs); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.apRoamingEnabled); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.measurementsMask); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.ccxRadioMgtEnabled); + return(ptr); +} + + +void* CsrWifiSmeCcxConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCcxConfigSetReq *primitive = (CsrWifiSmeCcxConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.keepAliveTimeMs, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.apRoamingEnabled, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.measurementsMask, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.ccxRadioMgtEnabled, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeCoexConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 29) */ + bufferSize += 1; /* CsrBool primitive->coexConfig.coexEnableSchemeManagement */ + bufferSize += 1; /* CsrBool primitive->coexConfig.coexPeriodicWakeHost */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexTrafficBurstyLatencyMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexTrafficContinuousLatencyMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexObexBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexObexBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpBrBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpBrBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpEdrBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexPagingBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexPagingBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexInquiryBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexInquiryBlackoutPeriodMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCoexConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCoexConfigSetReq *primitive = (CsrWifiSmeCoexConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexConfig.coexEnableSchemeManagement); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexConfig.coexPeriodicWakeHost); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexTrafficBurstyLatencyMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexTrafficContinuousLatencyMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexObexBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexObexBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpBrBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpBrBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpEdrBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexPagingBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexPagingBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexInquiryBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexInquiryBlackoutPeriodMs); + return(ptr); +} + + +void* CsrWifiSmeCoexConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCoexConfigSetReq *primitive = (CsrWifiSmeCoexConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexConfig.coexEnableSchemeManagement, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexConfig.coexPeriodicWakeHost, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexTrafficBurstyLatencyMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexTrafficContinuousLatencyMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexObexBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexObexBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpBrBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpBrBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpEdrBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexPagingBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexPagingBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexInquiryBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexInquiryBlackoutPeriodMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeConnectReqSizeof(void *msg) +{ + CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 57) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 32; /* CsrUint8 primitive->connectionConfig.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->connectionConfig.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->connectionConfig.bssid.a[6] */ + bufferSize += 1; /* CsrWifiSmeBssType primitive->connectionConfig.bssType */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionConfig.ifIndex */ + bufferSize += 1; /* CsrWifiSme80211PrivacyMode primitive->connectionConfig.privacyMode */ + bufferSize += 2; /* CsrWifiSmeAuthModeMask primitive->connectionConfig.authModeMask */ + bufferSize += 2; /* CsrWifiSmeEncryptionMask primitive->connectionConfig.encryptionModeMask */ + bufferSize += 2; /* CsrUint16 primitive->connectionConfig.mlmeAssociateReqInformationElementsLength */ + bufferSize += primitive->connectionConfig.mlmeAssociateReqInformationElementsLength; /* CsrUint8 primitive->connectionConfig.mlmeAssociateReqInformationElements */ + bufferSize += 1; /* CsrWifiSmeWmmQosInfoMask primitive->connectionConfig.wmmQosInfo */ + bufferSize += 1; /* CsrBool primitive->connectionConfig.adhocJoinOnly */ + bufferSize += 1; /* CsrUint8 primitive->connectionConfig.adhocChannel */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.bssType); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.ifIndex); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.privacyMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.authModeMask); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.encryptionModeMask); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); + if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.mlmeAssociateReqInformationElements, ((CsrUint16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.wmmQosInfo); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.adhocJoinOnly); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.adhocChannel); + return(ptr); +} + + +void* CsrWifiSmeConnectReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->connectionConfig.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->connectionConfig.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.bssType, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.ifIndex, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.privacyMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.authModeMask, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.encryptionModeMask, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, buffer, &offset); + if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) + { + primitive->connectionConfig.mlmeAssociateReqInformationElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); + CsrMemCpyDes(primitive->connectionConfig.mlmeAssociateReqInformationElements, buffer, &offset, ((CsrUint16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); + } + else + { + primitive->connectionConfig.mlmeAssociateReqInformationElements = NULL; + } + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.wmmQosInfo, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.adhocJoinOnly, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.adhocChannel, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeConnectReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *) voidPrimitivePointer; + CsrPmemFree(primitive->connectionConfig.mlmeAssociateReqInformationElements); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeHostConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeHostPowerMode primitive->hostConfig.powerMode */ + bufferSize += 2; /* CsrUint16 primitive->hostConfig.applicationDataPeriodMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeHostConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeHostConfigSetReq *primitive = (CsrWifiSmeHostConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->hostConfig.powerMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->hostConfig.applicationDataPeriodMs); + return(ptr); +} + + +void* CsrWifiSmeHostConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeHostConfigSetReq *primitive = (CsrWifiSmeHostConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->hostConfig.powerMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->hostConfig.applicationDataPeriodMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeKeyReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 65) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrWifiSmeKeyType primitive->key.keyType */ + bufferSize += 1; /* CsrUint8 primitive->key.keyIndex */ + bufferSize += 1; /* CsrBool primitive->key.wepTxKey */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 8; i2++) + { + bufferSize += 2; /* CsrUint16 primitive->key.keyRsc[8] */ + } + } + bufferSize += 1; /* CsrBool primitive->key.authenticator */ + bufferSize += 6; /* CsrUint8 primitive->key.address.a[6] */ + bufferSize += 1; /* CsrUint8 primitive->key.keyLength */ + bufferSize += 32; /* CsrUint8 primitive->key.key[32] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeKeyReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeKeyReq *primitive = (CsrWifiSmeKeyReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->key.keyType); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->key.keyIndex); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->key.wepTxKey); + { + CsrUint16 i2; + for (i2 = 0; i2 < 8; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->key.keyRsc[i2]); + } + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->key.authenticator); + CsrMemCpySer(ptr, len, (const void *) primitive->key.address.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->key.keyLength); + CsrMemCpySer(ptr, len, (const void *) primitive->key.key, ((CsrUint16) (32))); + return(ptr); +} + + +void* CsrWifiSmeKeyReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeKeyReq *primitive = (CsrWifiSmeKeyReq *) CsrPmemAlloc(sizeof(CsrWifiSmeKeyReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->key.keyType, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->key.keyIndex, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->key.wepTxKey, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 8; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->key.keyRsc[i2], buffer, &offset); + } + } + CsrUint8Des((CsrUint8 *) &primitive->key.authenticator, buffer, &offset); + CsrMemCpyDes(primitive->key.address.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->key.keyLength, buffer, &offset); + CsrMemCpyDes(primitive->key.key, buffer, &offset, ((CsrUint16) (32))); + + return primitive; +} + + +CsrSize CsrWifiSmeMibConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 1; /* CsrBool primitive->mibConfig.unifiFixMaxTxDataRate */ + bufferSize += 1; /* CsrUint8 primitive->mibConfig.unifiFixTxDataRate */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11RtsThreshold */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11FragmentationThreshold */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11CurrentTxPowerLevel */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibConfigSetReq *primitive = (CsrWifiSmeMibConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mibConfig.unifiFixMaxTxDataRate); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mibConfig.unifiFixTxDataRate); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11RtsThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11FragmentationThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11CurrentTxPowerLevel); + return(ptr); +} + + +void* CsrWifiSmeMibConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibConfigSetReq *primitive = (CsrWifiSmeMibConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mibConfig.unifiFixMaxTxDataRate, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mibConfig.unifiFixTxDataRate, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11RtsThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11FragmentationThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11CurrentTxPowerLevel, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeMibGetNextReqSizeof(void *msg) +{ + CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ + bufferSize += 2; /* CsrUint16 primitive->mibAttributeLength */ + bufferSize += primitive->mibAttributeLength; /* CsrUint8 primitive->mibAttribute */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibGetNextReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibAttributeLength); + if (primitive->mibAttributeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((CsrUint16) (primitive->mibAttributeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeMibGetNextReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetNextReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibAttributeLength, buffer, &offset); + if (primitive->mibAttributeLength) + { + primitive->mibAttribute = (CsrUint8 *)CsrPmemAlloc(primitive->mibAttributeLength); + CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((CsrUint16) (primitive->mibAttributeLength))); + } + else + { + primitive->mibAttribute = NULL; + } + + return primitive; +} + + +void CsrWifiSmeMibGetNextReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *) voidPrimitivePointer; + CsrPmemFree(primitive->mibAttribute); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMibGetReqSizeof(void *msg) +{ + CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ + bufferSize += 2; /* CsrUint16 primitive->mibAttributeLength */ + bufferSize += primitive->mibAttributeLength; /* CsrUint8 primitive->mibAttribute */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibGetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibAttributeLength); + if (primitive->mibAttributeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((CsrUint16) (primitive->mibAttributeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeMibGetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibAttributeLength, buffer, &offset); + if (primitive->mibAttributeLength) + { + primitive->mibAttribute = (CsrUint8 *)CsrPmemAlloc(primitive->mibAttributeLength); + CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((CsrUint16) (primitive->mibAttributeLength))); + } + else + { + primitive->mibAttribute = NULL; + } + + return primitive; +} + + +void CsrWifiSmeMibGetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->mibAttribute); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMibSetReqSizeof(void *msg) +{ + CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ + bufferSize += 2; /* CsrUint16 primitive->mibAttributeLength */ + bufferSize += primitive->mibAttributeLength; /* CsrUint8 primitive->mibAttribute */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibAttributeLength); + if (primitive->mibAttributeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((CsrUint16) (primitive->mibAttributeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeMibSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMibSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibAttributeLength, buffer, &offset); + if (primitive->mibAttributeLength) + { + primitive->mibAttribute = (CsrUint8 *)CsrPmemAlloc(primitive->mibAttributeLength); + CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((CsrUint16) (primitive->mibAttributeLength))); + } + else + { + primitive->mibAttribute = NULL; + } + + return primitive; +} + + +void CsrWifiSmeMibSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->mibAttribute); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMulticastAddressReqSizeof(void *msg) +{ + CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->setAddressesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->setAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMulticastAddressReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->setAddressesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiSmeMulticastAddressReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *) CsrPmemAlloc(sizeof(CsrWifiSmeMulticastAddressReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->setAddressesCount, buffer, &offset); + primitive->setAddresses = NULL; + if (primitive->setAddressesCount) + { + primitive->setAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->setAddressesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setAddressesCount; i1++) + { + CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiSmeMulticastAddressReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *) voidPrimitivePointer; + CsrPmemFree(primitive->setAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePacketFilterSetReqSizeof(void *msg) +{ + CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrUint16 primitive->filterLength */ + bufferSize += primitive->filterLength; /* CsrUint8 primitive->filter */ + bufferSize += 1; /* CsrWifiSmePacketFilterMode primitive->mode */ + bufferSize += 4; /* CsrUint8 primitive->arpFilterAddress.a[4] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmePacketFilterSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->filterLength); + if (primitive->filterLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->filter, ((CsrUint16) (primitive->filterLength))); + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mode); + CsrMemCpySer(ptr, len, (const void *) primitive->arpFilterAddress.a, ((CsrUint16) (4))); + return(ptr); +} + + +void* CsrWifiSmePacketFilterSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePacketFilterSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->filterLength, buffer, &offset); + if (primitive->filterLength) + { + primitive->filter = (CsrUint8 *)CsrPmemAlloc(primitive->filterLength); + CsrMemCpyDes(primitive->filter, buffer, &offset, ((CsrUint16) (primitive->filterLength))); + } + else + { + primitive->filter = NULL; + } + CsrUint8Des((CsrUint8 *) &primitive->mode, buffer, &offset); + CsrMemCpyDes(primitive->arpFilterAddress.a, buffer, &offset, ((CsrUint16) (4))); + + return primitive; +} + + +void CsrWifiSmePacketFilterSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->filter); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePmkidReqSizeof(void *msg) +{ + CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 29) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->setPmkidsCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->setPmkids[i1].bssid.a[6] */ + bufferSize += 16; /* CsrUint8 primitive->setPmkids[i1].pmkid[16] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmePmkidReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->setPmkidsCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->setPmkids[i1].bssid.a, ((CsrUint16) (6))); + CsrMemCpySer(ptr, len, (const void *) primitive->setPmkids[i1].pmkid, ((CsrUint16) (16))); + } + } + return(ptr); +} + + +void* CsrWifiSmePmkidReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->setPmkidsCount, buffer, &offset); + primitive->setPmkids = NULL; + if (primitive->setPmkidsCount) + { + primitive->setPmkids = (CsrWifiSmePmkid *)CsrPmemAlloc(sizeof(CsrWifiSmePmkid) * primitive->setPmkidsCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) + { + CsrMemCpyDes(primitive->setPmkids[i1].bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrMemCpyDes(primitive->setPmkids[i1].pmkid, buffer, &offset, ((CsrUint16) (16))); + } + } + + return primitive; +} + + +void CsrWifiSmePmkidReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *) voidPrimitivePointer; + CsrPmemFree(primitive->setPmkids); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePowerConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->powerConfig.powerSaveLevel */ + bufferSize += 2; /* CsrUint16 primitive->powerConfig.listenIntervalTu */ + bufferSize += 1; /* CsrBool primitive->powerConfig.rxDtims */ + bufferSize += 1; /* CsrWifiSmeD3AutoScanMode primitive->powerConfig.d3AutoScanMode */ + bufferSize += 1; /* CsrUint8 primitive->powerConfig.clientTrafficWindow */ + bufferSize += 1; /* CsrBool primitive->powerConfig.opportunisticPowerSave */ + bufferSize += 1; /* CsrBool primitive->powerConfig.noticeOfAbsence */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmePowerConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePowerConfigSetReq *primitive = (CsrWifiSmePowerConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.powerSaveLevel); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->powerConfig.listenIntervalTu); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.rxDtims); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.d3AutoScanMode); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.clientTrafficWindow); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.opportunisticPowerSave); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.noticeOfAbsence); + return(ptr); +} + + +void* CsrWifiSmePowerConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePowerConfigSetReq *primitive = (CsrWifiSmePowerConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.powerSaveLevel, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->powerConfig.listenIntervalTu, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.rxDtims, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.d3AutoScanMode, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.clientTrafficWindow, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.opportunisticPowerSave, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.noticeOfAbsence, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeRoamingConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 70) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].rssiHighThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].rssiLowThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].snrHighThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].snrLowThreshold */ + } + } + bufferSize += 1; /* CsrBool primitive->roamingConfig.disableSmoothRoaming */ + bufferSize += 1; /* CsrBool primitive->roamingConfig.disableRoamScans */ + bufferSize += 1; /* CsrUint8 primitive->roamingConfig.reconnectLimit */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.reconnectLimitIntervalMs */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].intervalSeconds */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].validitySeconds */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRoamingConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRoamingConfigSetReq *primitive = (CsrWifiSmeRoamingConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].rssiHighThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].rssiLowThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].snrHighThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].snrLowThreshold); + } + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.disableSmoothRoaming); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.disableRoamScans); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.reconnectLimit); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.reconnectLimitIntervalMs); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].intervalSeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].validitySeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu); + } + } + return(ptr); +} + + +void* CsrWifiSmeRoamingConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRoamingConfigSetReq *primitive = (CsrWifiSmeRoamingConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].rssiHighThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].rssiLowThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].snrHighThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].snrLowThreshold, buffer, &offset); + } + } + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.disableSmoothRoaming, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.disableRoamScans, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.reconnectLimit, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.reconnectLimitIntervalMs, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].intervalSeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].validitySeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); + } + } + + return primitive; +} + + +CsrSize CsrWifiSmeScanConfigSetReqSizeof(void *msg) +{ + CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 63) */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].intervalSeconds */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].validitySeconds */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu */ + } + } + bufferSize += 1; /* CsrBool primitive->scanConfig.disableAutonomousScans */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.maxResults */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.highRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.lowRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.deltaRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.highSnrThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.lowSnrThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.deltaSnrThreshold */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.passiveChannelListCount */ + bufferSize += primitive->scanConfig.passiveChannelListCount; /* CsrUint8 primitive->scanConfig.passiveChannelList */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeScanConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].intervalSeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].validitySeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu); + } + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.disableAutonomousScans); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.maxResults); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.highRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.lowRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.deltaRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.highSnrThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.lowSnrThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.deltaSnrThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.passiveChannelListCount); + if (primitive->scanConfig.passiveChannelListCount) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanConfig.passiveChannelList, ((CsrUint16) (primitive->scanConfig.passiveChannelListCount))); + } + return(ptr); +} + + +void* CsrWifiSmeScanConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].intervalSeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].validitySeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); + } + } + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.disableAutonomousScans, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.maxResults, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.highRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.lowRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.deltaRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.highSnrThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.lowSnrThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.deltaSnrThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.passiveChannelListCount, buffer, &offset); + if (primitive->scanConfig.passiveChannelListCount) + { + primitive->scanConfig.passiveChannelList = (CsrUint8 *)CsrPmemAlloc(primitive->scanConfig.passiveChannelListCount); + CsrMemCpyDes(primitive->scanConfig.passiveChannelList, buffer, &offset, ((CsrUint16) (primitive->scanConfig.passiveChannelListCount))); + } + else + { + primitive->scanConfig.passiveChannelList = NULL; + } + + return primitive; +} + + +void CsrWifiSmeScanConfigSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->scanConfig.passiveChannelList); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeScanFullReqSizeof(void *msg) +{ + CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 52) */ + bufferSize += 1; /* CsrUint8 primitive->ssidCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->ssidCount; i1++) + { + bufferSize += 32; /* CsrUint8 primitive->ssid[i1].ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->ssid[i1].length */ + } + } + bufferSize += 6; /* CsrUint8 primitive->bssid.a[6] */ + bufferSize += 1; /* CsrBool primitive->forceScan */ + bufferSize += 1; /* CsrWifiSmeBssType primitive->bssType */ + bufferSize += 1; /* CsrWifiSmeScanType primitive->scanType */ + bufferSize += 2; /* CsrUint16 primitive->channelListCount */ + bufferSize += primitive->channelListCount; /* CsrUint8 primitive->channelList */ + bufferSize += 2; /* CsrUint16 primitive->probeIeLength */ + bufferSize += primitive->probeIeLength; /* CsrUint8 primitive->probeIe */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeScanFullReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ssidCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->ssidCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->ssid[i1].ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ssid[i1].length); + } + } + CsrMemCpySer(ptr, len, (const void *) primitive->bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->forceScan); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->bssType); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->channelListCount); + if (primitive->channelListCount) + { + CsrMemCpySer(ptr, len, (const void *) primitive->channelList, ((CsrUint16) (primitive->channelListCount))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->probeIeLength); + if (primitive->probeIeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->probeIe, ((CsrUint16) (primitive->probeIeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeScanFullReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *) CsrPmemAlloc(sizeof(CsrWifiSmeScanFullReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ssidCount, buffer, &offset); + primitive->ssid = NULL; + if (primitive->ssidCount) + { + primitive->ssid = (CsrWifiSsid *)CsrPmemAlloc(sizeof(CsrWifiSsid) * primitive->ssidCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->ssidCount; i1++) + { + CsrMemCpyDes(primitive->ssid[i1].ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->ssid[i1].length, buffer, &offset); + } + } + CsrMemCpyDes(primitive->bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->forceScan, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->bssType, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->channelListCount, buffer, &offset); + if (primitive->channelListCount) + { + primitive->channelList = (CsrUint8 *)CsrPmemAlloc(primitive->channelListCount); + CsrMemCpyDes(primitive->channelList, buffer, &offset, ((CsrUint16) (primitive->channelListCount))); + } + else + { + primitive->channelList = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->probeIeLength, buffer, &offset); + if (primitive->probeIeLength) + { + primitive->probeIe = (CsrUint8 *)CsrPmemAlloc(primitive->probeIeLength); + CsrMemCpyDes(primitive->probeIe, buffer, &offset, ((CsrUint16) (primitive->probeIeLength))); + } + else + { + primitive->probeIe = NULL; + } + + return primitive; +} + + +void CsrWifiSmeScanFullReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *) voidPrimitivePointer; + CsrPmemFree(primitive->ssid); + CsrPmemFree(primitive->channelList); + CsrPmemFree(primitive->probeIe); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ + bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */ + bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSmeStaConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSmeStaConfigSetReq *primitive = (CsrWifiSmeSmeStaConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.connectionQualityRssiChangeTrigger); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.connectionQualitySnrChangeTrigger); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.wmmModeMask); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.ifIndex); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.allowUnicastUseGroupCipher); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.enableOpportunisticKeyCaching); + return(ptr); +} + + +void* CsrWifiSmeSmeStaConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSmeStaConfigSetReq *primitive = (CsrWifiSmeSmeStaConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.connectionQualityRssiChangeTrigger, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.connectionQualitySnrChangeTrigger, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.wmmModeMask, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.ifIndex, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.allowUnicastUseGroupCipher, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.enableOpportunisticKeyCaching, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeTspecReqSizeof(void *msg) +{ + CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 18) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 4; /* CsrUint32 primitive->transactionId */ + bufferSize += 1; /* CsrBool primitive->strict */ + bufferSize += 1; /* CsrWifiSmeTspecCtrlMask primitive->ctrlMask */ + bufferSize += 2; /* CsrUint16 primitive->tspecLength */ + bufferSize += primitive->tspecLength; /* CsrUint8 primitive->tspec */ + bufferSize += 2; /* CsrUint16 primitive->tclasLength */ + bufferSize += primitive->tclasLength; /* CsrUint8 primitive->tclas */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeTspecReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->transactionId); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->strict); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ctrlMask); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tspecLength); + if (primitive->tspecLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((CsrUint16) (primitive->tspecLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tclasLength); + if (primitive->tclasLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((CsrUint16) (primitive->tclasLength))); + } + return(ptr); +} + + +void* CsrWifiSmeTspecReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->transactionId, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->strict, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ctrlMask, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->tspecLength, buffer, &offset); + if (primitive->tspecLength) + { + primitive->tspec = (CsrUint8 *)CsrPmemAlloc(primitive->tspecLength); + CsrMemCpyDes(primitive->tspec, buffer, &offset, ((CsrUint16) (primitive->tspecLength))); + } + else + { + primitive->tspec = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->tclasLength, buffer, &offset); + if (primitive->tclasLength) + { + primitive->tclas = (CsrUint8 *)CsrPmemAlloc(primitive->tclasLength); + CsrMemCpyDes(primitive->tclas, buffer, &offset, ((CsrUint16) (primitive->tclasLength))); + } + else + { + primitive->tclas = NULL; + } + + return primitive; +} + + +void CsrWifiSmeTspecReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *) voidPrimitivePointer; + CsrPmemFree(primitive->tspec); + CsrPmemFree(primitive->tclas); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeWifiFlightmodeReqSizeof(void *msg) +{ + CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->mibFilesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + bufferSize += 2; /* CsrUint16 primitive->mibFiles[i1].length */ + bufferSize += primitive->mibFiles[i1].length; /* CsrUint8 primitive->mibFiles[i1].data */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeWifiFlightmodeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibFilesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibFiles[i1].length); + if (primitive->mibFiles[i1].length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibFiles[i1].data, ((CsrUint16) (primitive->mibFiles[i1].length))); + } + } + } + return(ptr); +} + + +void* CsrWifiSmeWifiFlightmodeReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiFlightmodeReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->mibFilesCount, buffer, &offset); + primitive->mibFiles = NULL; + if (primitive->mibFilesCount) + { + primitive->mibFiles = (CsrWifiSmeDataBlock *)CsrPmemAlloc(sizeof(CsrWifiSmeDataBlock) * primitive->mibFilesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrUint16Des((CsrUint16 *) &primitive->mibFiles[i1].length, buffer, &offset); + if (primitive->mibFiles[i1].length) + { + primitive->mibFiles[i1].data = (CsrUint8 *)CsrPmemAlloc(primitive->mibFiles[i1].length); + CsrMemCpyDes(primitive->mibFiles[i1].data, buffer, &offset, ((CsrUint16) (primitive->mibFiles[i1].length))); + } + else + { + primitive->mibFiles[i1].data = NULL; + } + } + } + + return primitive; +} + + +void CsrWifiSmeWifiFlightmodeReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *) voidPrimitivePointer; + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrPmemFree(primitive->mibFiles[i1].data); + } + } + CsrPmemFree(primitive->mibFiles); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeWifiOnReqSizeof(void *msg) +{ + CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->mibFilesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + bufferSize += 2; /* CsrUint16 primitive->mibFiles[i1].length */ + bufferSize += primitive->mibFiles[i1].length; /* CsrUint8 primitive->mibFiles[i1].data */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibFilesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibFiles[i1].length); + if (primitive->mibFiles[i1].length) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibFiles[i1].data, ((CsrUint16) (primitive->mibFiles[i1].length))); + } + } + } + return(ptr); +} + + +void* CsrWifiSmeWifiOnReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOnReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->mibFilesCount, buffer, &offset); + primitive->mibFiles = NULL; + if (primitive->mibFilesCount) + { + primitive->mibFiles = (CsrWifiSmeDataBlock *)CsrPmemAlloc(sizeof(CsrWifiSmeDataBlock) * primitive->mibFilesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrUint16Des((CsrUint16 *) &primitive->mibFiles[i1].length, buffer, &offset); + if (primitive->mibFiles[i1].length) + { + primitive->mibFiles[i1].data = (CsrUint8 *)CsrPmemAlloc(primitive->mibFiles[i1].length); + CsrMemCpyDes(primitive->mibFiles[i1].data, buffer, &offset, ((CsrUint16) (primitive->mibFiles[i1].length))); + } + else + { + primitive->mibFiles[i1].data = NULL; + } + } + } + + return primitive; +} + + +void CsrWifiSmeWifiOnReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *) voidPrimitivePointer; + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->mibFilesCount; i1++) + { + CsrPmemFree(primitive->mibFiles[i1].data); + } + } + CsrPmemFree(primitive->mibFiles); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg) +{ + CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 37) */ + bufferSize += 1; /* CsrUint8 primitive->cloakedSsids.cloakedSsidsCount */ + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + bufferSize += 32; /* CsrUint8 primitive->cloakedSsids.cloakedSsids[i2].ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->cloakedSsids.cloakedSsids[i2].length */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCloakedSsidsSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->cloakedSsids.cloakedSsidsCount); + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->cloakedSsids.cloakedSsids[i2].ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->cloakedSsids.cloakedSsids[i2].length); + } + } + return(ptr); +} + + +void* CsrWifiSmeCloakedSsidsSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->cloakedSsids.cloakedSsidsCount, buffer, &offset); + primitive->cloakedSsids.cloakedSsids = NULL; + if (primitive->cloakedSsids.cloakedSsidsCount) + { + primitive->cloakedSsids.cloakedSsids = (CsrWifiSsid *)CsrPmemAlloc(sizeof(CsrWifiSsid) * primitive->cloakedSsids.cloakedSsidsCount); + } + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + CsrMemCpyDes(primitive->cloakedSsids.cloakedSsids[i2].ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->cloakedSsids.cloakedSsids[i2].length, buffer, &offset); + } + } + + return primitive; +} + + +void CsrWifiSmeCloakedSsidsSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->cloakedSsids.cloakedSsids); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 1; /* CsrWifiSme80211dTrustLevel primitive->deviceConfig.trustLevel */ + bufferSize += 2; /* CsrUint8 primitive->deviceConfig.countryCode[2] */ + bufferSize += 1; /* CsrWifiSmeFirmwareDriverInterface primitive->deviceConfig.firmwareDriverInterface */ + bufferSize += 1; /* CsrBool primitive->deviceConfig.enableStrictDraftN */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSmeCommonConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSmeCommonConfigSetReq *primitive = (CsrWifiSmeSmeCommonConfigSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.trustLevel); + CsrMemCpySer(ptr, len, (const void *) primitive->deviceConfig.countryCode, ((CsrUint16) (2))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.firmwareDriverInterface); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.enableStrictDraftN); + return(ptr); +} + + +void* CsrWifiSmeSmeCommonConfigSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSmeCommonConfigSetReq *primitive = (CsrWifiSmeSmeCommonConfigSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.trustLevel, buffer, &offset); + CsrMemCpyDes(primitive->deviceConfig.countryCode, buffer, &offset, ((CsrUint16) (2))); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.firmwareDriverInterface, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.enableStrictDraftN, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg) +{ + CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 240) */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.wpsVersion */ + bufferSize += 16; /* CsrUint8 primitive->wpsConfig.uuid[16] */ + bufferSize += 32; /* CsrUint8 primitive->wpsConfig.deviceName[32] */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.deviceNameLength */ + bufferSize += 64; /* CsrUint8 primitive->wpsConfig.manufacturer[64] */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.manufacturerLength */ + bufferSize += 32; /* CsrUint8 primitive->wpsConfig.modelName[32] */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.modelNameLength */ + bufferSize += 32; /* CsrUint8 primitive->wpsConfig.modelNumber[32] */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.modelNumberLength */ + bufferSize += 32; /* CsrUint8 primitive->wpsConfig.serialNumber[32] */ + bufferSize += 8; /* CsrUint8 primitive->wpsConfig.primDeviceType.deviceDetails[8] */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.secondaryDeviceTypeCount */ + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) + { + bufferSize += 8; /* CsrUint8 primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails[8] */ + } + } + bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->wpsConfig.configMethods */ + bufferSize += 1; /* CsrUint8 primitive->wpsConfig.rfBands */ + bufferSize += 4; /* CsrUint8 primitive->wpsConfig.osVersion[4] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeWpsConfigurationReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.wpsVersion); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.uuid, ((CsrUint16) (16))); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.deviceName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.deviceNameLength); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.manufacturer, ((CsrUint16) (64))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.manufacturerLength); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.modelName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.modelNameLength); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.modelNumber, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.modelNumberLength); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.serialNumber, ((CsrUint16) (32))); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.primDeviceType.deviceDetails, ((CsrUint16) (8))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.secondaryDeviceTypeCount); + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails, ((CsrUint16) (8))); + } + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->wpsConfig.configMethods); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->wpsConfig.rfBands); + CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.osVersion, ((CsrUint16) (4))); + return(ptr); +} + + +void* CsrWifiSmeWpsConfigurationReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *) CsrPmemAlloc(sizeof(CsrWifiSmeWpsConfigurationReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.wpsVersion, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.uuid, buffer, &offset, ((CsrUint16) (16))); + CsrMemCpyDes(primitive->wpsConfig.deviceName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.deviceNameLength, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.manufacturer, buffer, &offset, ((CsrUint16) (64))); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.manufacturerLength, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.modelName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.modelNameLength, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.modelNumber, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.modelNumberLength, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.serialNumber, buffer, &offset, ((CsrUint16) (32))); + CsrMemCpyDes(primitive->wpsConfig.primDeviceType.deviceDetails, buffer, &offset, ((CsrUint16) (8))); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.secondaryDeviceTypeCount, buffer, &offset); + primitive->wpsConfig.secondaryDeviceType = NULL; + if (primitive->wpsConfig.secondaryDeviceTypeCount) + { + primitive->wpsConfig.secondaryDeviceType = (CsrWifiSmeWpsDeviceType *)CsrPmemAlloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->wpsConfig.secondaryDeviceTypeCount); + } + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) + { + CsrMemCpyDes(primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails, buffer, &offset, ((CsrUint16) (8))); + } + } + CsrUint16Des((CsrUint16 *) &primitive->wpsConfig.configMethods, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->wpsConfig.rfBands, buffer, &offset); + CsrMemCpyDes(primitive->wpsConfig.osVersion, buffer, &offset, ((CsrUint16) (4))); + + return primitive; +} + + +void CsrWifiSmeWpsConfigurationReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *) voidPrimitivePointer; + CsrPmemFree(primitive->wpsConfig.secondaryDeviceType); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.atimWindowTu */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.beaconPeriodTu */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.joinOnlyAttempts */ + bufferSize += 2; /* CsrUint16 primitive->adHocConfig.joinAttemptIntervalMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeAdhocConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeAdhocConfigGetCfm *primitive = (CsrWifiSmeAdhocConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.atimWindowTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.beaconPeriodTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.joinOnlyAttempts); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->adHocConfig.joinAttemptIntervalMs); + return(ptr); +} + + +void* CsrWifiSmeAdhocConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeAdhocConfigGetCfm *primitive = (CsrWifiSmeAdhocConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeAdhocConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.atimWindowTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.beaconPeriodTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.joinOnlyAttempts, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->adHocConfig.joinAttemptIntervalMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeAssociationCompleteIndSizeof(void *msg) +{ + CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 98) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 32; /* CsrUint8 primitive->connectionInfo.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.bssid.a[6] */ + bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.channelNumber */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.channelFrequency */ + bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.atimWindowTu */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconPeriodTu */ + bufferSize += 1; /* CsrBool primitive->connectionInfo.reassociation */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconFrameLength */ + bufferSize += primitive->connectionInfo.beaconFrameLength; /* CsrUint8 primitive->connectionInfo.beaconFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationReqFrameLength */ + bufferSize += primitive->connectionInfo.associationReqFrameLength; /* CsrUint8 primitive->connectionInfo.associationReqFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationRspFrameLength */ + bufferSize += primitive->connectionInfo.associationRspFrameLength; /* CsrUint8 primitive->connectionInfo.associationRspFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocScanInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocScanInfoElements */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqCapabilities */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqListenIntervalTu */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.assocReqApAddress.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocReqInfoElements */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspCapabilityInfo */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspAssociationId */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocRspInfoElements */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->deauthReason */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeAssociationCompleteIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.networkType80211); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.channelNumber); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.channelFrequency); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.authMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.pairwiseCipher); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.groupCipher); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ifIndex); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.atimWindowTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconPeriodTu); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.reassociation); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconFrameLength); + if (primitive->connectionInfo.beaconFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationReqFrameLength); + if (primitive->connectionInfo.associationReqFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationRspFrameLength); + if (primitive->connectionInfo.associationRspFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocScanInfoElementsLength); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqCapabilities); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqListenIntervalTu); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqInfoElementsLength); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspResult); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspCapabilityInfo); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspAssociationId); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspInfoElementsLength); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->deauthReason); + return(ptr); +} + + +void* CsrWifiSmeAssociationCompleteIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *) CsrPmemAlloc(sizeof(CsrWifiSmeAssociationCompleteInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.authMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.reassociation, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); + if (primitive->connectionInfo.beaconFrameLength) + { + primitive->connectionInfo.beaconFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.beaconFrameLength); + CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + else + { + primitive->connectionInfo.beaconFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationReqFrameLength) + { + primitive->connectionInfo.associationReqFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationReqFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + else + { + primitive->connectionInfo.associationReqFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationRspFrameLength) + { + primitive->connectionInfo.associationRspFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationRspFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + else + { + primitive->connectionInfo.associationRspFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + primitive->connectionInfo.assocScanInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocScanInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocScanInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + primitive->connectionInfo.assocReqInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocReqInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocReqInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + primitive->connectionInfo.assocRspInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocRspInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocRspInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->deauthReason, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeAssociationCompleteIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *) voidPrimitivePointer; + CsrPmemFree(primitive->connectionInfo.beaconFrame); + CsrPmemFree(primitive->connectionInfo.associationReqFrame); + CsrPmemFree(primitive->connectionInfo.associationRspFrame); + CsrPmemFree(primitive->connectionInfo.assocScanInfoElements); + CsrPmemFree(primitive->connectionInfo.assocReqInfoElements); + CsrPmemFree(primitive->connectionInfo.assocRspInfoElements); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeAssociationStartIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 44) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + bufferSize += 32; /* CsrUint8 primitive->ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->ssid.length */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeAssociationStartIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeAssociationStartInd *primitive = (CsrWifiSmeAssociationStartInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + CsrMemCpySer(ptr, len, (const void *) primitive->ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ssid.length); + return(ptr); +} + + +void* CsrWifiSmeAssociationStartIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeAssociationStartInd *primitive = (CsrWifiSmeAssociationStartInd *) CsrPmemAlloc(sizeof(CsrWifiSmeAssociationStartInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + CsrMemCpyDes(primitive->ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->ssid.length, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeBlacklistCfmSizeof(void *msg) +{ + CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->getAddressCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->getAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeBlacklistCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->getAddressCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiSmeBlacklistCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeBlacklistCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->getAddressCount, buffer, &offset); + primitive->getAddresses = NULL; + if (primitive->getAddressCount) + { + primitive->getAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->getAddressCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressCount; i1++) + { + CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiSmeBlacklistCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->getAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg) +{ + CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->calibrationDataLength */ + bufferSize += primitive->calibrationDataLength; /* CsrUint8 primitive->calibrationData */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCalibrationDataGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->calibrationDataLength); + if (primitive->calibrationDataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->calibrationData, ((CsrUint16) (primitive->calibrationDataLength))); + } + return(ptr); +} + + +void* CsrWifiSmeCalibrationDataGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCalibrationDataGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->calibrationDataLength, buffer, &offset); + if (primitive->calibrationDataLength) + { + primitive->calibrationData = (CsrUint8 *)CsrPmemAlloc(primitive->calibrationDataLength); + CsrMemCpyDes(primitive->calibrationData, buffer, &offset, ((CsrUint16) (primitive->calibrationDataLength))); + } + else + { + primitive->calibrationData = NULL; + } + + return primitive; +} + + +void CsrWifiSmeCalibrationDataGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->calibrationData); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCcxConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrUint8 primitive->ccxConfig.keepAliveTimeMs */ + bufferSize += 1; /* CsrBool primitive->ccxConfig.apRoamingEnabled */ + bufferSize += 1; /* CsrUint8 primitive->ccxConfig.measurementsMask */ + bufferSize += 1; /* CsrBool primitive->ccxConfig.ccxRadioMgtEnabled */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCcxConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCcxConfigGetCfm *primitive = (CsrWifiSmeCcxConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.keepAliveTimeMs); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.apRoamingEnabled); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.measurementsMask); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->ccxConfig.ccxRadioMgtEnabled); + return(ptr); +} + + +void* CsrWifiSmeCcxConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCcxConfigGetCfm *primitive = (CsrWifiSmeCcxConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.keepAliveTimeMs, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.apRoamingEnabled, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.measurementsMask, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->ccxConfig.ccxRadioMgtEnabled, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeCcxConfigSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCcxConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCcxConfigSetCfm *primitive = (CsrWifiSmeCcxConfigSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeCcxConfigSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCcxConfigSetCfm *primitive = (CsrWifiSmeCcxConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCcxConfigSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeCoexConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 31) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrBool primitive->coexConfig.coexEnableSchemeManagement */ + bufferSize += 1; /* CsrBool primitive->coexConfig.coexPeriodicWakeHost */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexTrafficBurstyLatencyMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexTrafficContinuousLatencyMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexObexBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexObexBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpBrBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpBrBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpEdrBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexPagingBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexPagingBlackoutPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexInquiryBlackoutDurationMs */ + bufferSize += 2; /* CsrUint16 primitive->coexConfig.coexInquiryBlackoutPeriodMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCoexConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCoexConfigGetCfm *primitive = (CsrWifiSmeCoexConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexConfig.coexEnableSchemeManagement); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexConfig.coexPeriodicWakeHost); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexTrafficBurstyLatencyMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexTrafficContinuousLatencyMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexObexBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexObexBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpBrBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpBrBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpEdrBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexPagingBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexPagingBlackoutPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexInquiryBlackoutDurationMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexConfig.coexInquiryBlackoutPeriodMs); + return(ptr); +} + + +void* CsrWifiSmeCoexConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCoexConfigGetCfm *primitive = (CsrWifiSmeCoexConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexConfig.coexEnableSchemeManagement, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexConfig.coexPeriodicWakeHost, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexTrafficBurstyLatencyMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexTrafficContinuousLatencyMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexObexBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexObexBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpBrBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpBrBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpEdrBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexPagingBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexPagingBlackoutPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexInquiryBlackoutDurationMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexConfig.coexInquiryBlackoutPeriodMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeCoexInfoGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 24) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrBool primitive->coexInfo.hasTrafficData */ + bufferSize += 1; /* CsrWifiSmeTrafficType primitive->coexInfo.currentTrafficType */ + bufferSize += 2; /* CsrUint16 primitive->coexInfo.currentPeriodMs */ + bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->coexInfo.currentPowerSave */ + bufferSize += 2; /* CsrUint16 primitive->coexInfo.currentCoexPeriodMs */ + bufferSize += 2; /* CsrUint16 primitive->coexInfo.currentCoexLatencyMs */ + bufferSize += 1; /* CsrBool primitive->coexInfo.hasBtDevice */ + bufferSize += 4; /* CsrUint32 primitive->coexInfo.currentBlackoutDurationUs */ + bufferSize += 4; /* CsrUint32 primitive->coexInfo.currentBlackoutPeriodUs */ + bufferSize += 1; /* CsrWifiSmeCoexScheme primitive->coexInfo.currentCoexScheme */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCoexInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCoexInfoGetCfm *primitive = (CsrWifiSmeCoexInfoGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexInfo.hasTrafficData); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexInfo.currentTrafficType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexInfo.currentPeriodMs); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexInfo.currentPowerSave); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexInfo.currentCoexPeriodMs); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->coexInfo.currentCoexLatencyMs); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexInfo.hasBtDevice); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->coexInfo.currentBlackoutDurationUs); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->coexInfo.currentBlackoutPeriodUs); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->coexInfo.currentCoexScheme); + return(ptr); +} + + +void* CsrWifiSmeCoexInfoGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCoexInfoGetCfm *primitive = (CsrWifiSmeCoexInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCoexInfoGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexInfo.hasTrafficData, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexInfo.currentTrafficType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexInfo.currentPeriodMs, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexInfo.currentPowerSave, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexInfo.currentCoexPeriodMs, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->coexInfo.currentCoexLatencyMs, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexInfo.hasBtDevice, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->coexInfo.currentBlackoutDurationUs, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->coexInfo.currentBlackoutPeriodUs, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->coexInfo.currentCoexScheme, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeConnectCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectCfm *primitive = (CsrWifiSmeConnectCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeConnectCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectCfm *primitive = (CsrWifiSmeConnectCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg) +{ + CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 59) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 32; /* CsrUint8 primitive->connectionConfig.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->connectionConfig.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->connectionConfig.bssid.a[6] */ + bufferSize += 1; /* CsrWifiSmeBssType primitive->connectionConfig.bssType */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionConfig.ifIndex */ + bufferSize += 1; /* CsrWifiSme80211PrivacyMode primitive->connectionConfig.privacyMode */ + bufferSize += 2; /* CsrWifiSmeAuthModeMask primitive->connectionConfig.authModeMask */ + bufferSize += 2; /* CsrWifiSmeEncryptionMask primitive->connectionConfig.encryptionModeMask */ + bufferSize += 2; /* CsrUint16 primitive->connectionConfig.mlmeAssociateReqInformationElementsLength */ + bufferSize += primitive->connectionConfig.mlmeAssociateReqInformationElementsLength; /* CsrUint8 primitive->connectionConfig.mlmeAssociateReqInformationElements */ + bufferSize += 1; /* CsrWifiSmeWmmQosInfoMask primitive->connectionConfig.wmmQosInfo */ + bufferSize += 1; /* CsrBool primitive->connectionConfig.adhocJoinOnly */ + bufferSize += 1; /* CsrUint8 primitive->connectionConfig.adhocChannel */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectionConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.bssType); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.ifIndex); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.privacyMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.authModeMask); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.encryptionModeMask); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); + if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.mlmeAssociateReqInformationElements, ((CsrUint16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.wmmQosInfo); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.adhocJoinOnly); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionConfig.adhocChannel); + return(ptr); +} + + +void* CsrWifiSmeConnectionConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrMemCpyDes(primitive->connectionConfig.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->connectionConfig.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.bssType, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.ifIndex, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.privacyMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.authModeMask, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.encryptionModeMask, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, buffer, &offset); + if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) + { + primitive->connectionConfig.mlmeAssociateReqInformationElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); + CsrMemCpyDes(primitive->connectionConfig.mlmeAssociateReqInformationElements, buffer, &offset, ((CsrUint16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); + } + else + { + primitive->connectionConfig.mlmeAssociateReqInformationElements = NULL; + } + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.wmmQosInfo, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.adhocJoinOnly, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionConfig.adhocChannel, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeConnectionConfigGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->connectionConfig.mlmeAssociateReqInformationElements); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg) +{ + CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 96) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 32; /* CsrUint8 primitive->connectionInfo.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.bssid.a[6] */ + bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.channelNumber */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.channelFrequency */ + bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.atimWindowTu */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconPeriodTu */ + bufferSize += 1; /* CsrBool primitive->connectionInfo.reassociation */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconFrameLength */ + bufferSize += primitive->connectionInfo.beaconFrameLength; /* CsrUint8 primitive->connectionInfo.beaconFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationReqFrameLength */ + bufferSize += primitive->connectionInfo.associationReqFrameLength; /* CsrUint8 primitive->connectionInfo.associationReqFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationRspFrameLength */ + bufferSize += primitive->connectionInfo.associationRspFrameLength; /* CsrUint8 primitive->connectionInfo.associationRspFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocScanInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocScanInfoElements */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqCapabilities */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqListenIntervalTu */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.assocReqApAddress.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocReqInfoElements */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspCapabilityInfo */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspAssociationId */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocRspInfoElements */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectionInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.networkType80211); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.channelNumber); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.channelFrequency); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.authMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.pairwiseCipher); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.groupCipher); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ifIndex); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.atimWindowTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconPeriodTu); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.reassociation); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconFrameLength); + if (primitive->connectionInfo.beaconFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationReqFrameLength); + if (primitive->connectionInfo.associationReqFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationRspFrameLength); + if (primitive->connectionInfo.associationRspFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocScanInfoElementsLength); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqCapabilities); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqListenIntervalTu); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqInfoElementsLength); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspResult); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspCapabilityInfo); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspAssociationId); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspInfoElementsLength); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + return(ptr); +} + + +void* CsrWifiSmeConnectionInfoGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionInfoGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.authMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.reassociation, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); + if (primitive->connectionInfo.beaconFrameLength) + { + primitive->connectionInfo.beaconFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.beaconFrameLength); + CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + else + { + primitive->connectionInfo.beaconFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationReqFrameLength) + { + primitive->connectionInfo.associationReqFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationReqFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + else + { + primitive->connectionInfo.associationReqFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationRspFrameLength) + { + primitive->connectionInfo.associationRspFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationRspFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + else + { + primitive->connectionInfo.associationRspFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + primitive->connectionInfo.assocScanInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocScanInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocScanInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + primitive->connectionInfo.assocReqInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocReqInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocReqInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + primitive->connectionInfo.assocRspInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocRspInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocRspInfoElements = NULL; + } + + return primitive; +} + + +void CsrWifiSmeConnectionInfoGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->connectionInfo.beaconFrame); + CsrPmemFree(primitive->connectionInfo.associationReqFrame); + CsrPmemFree(primitive->connectionInfo.associationRspFrame); + CsrPmemFree(primitive->connectionInfo.assocScanInfoElements); + CsrPmemFree(primitive->connectionInfo.assocReqInfoElements); + CsrPmemFree(primitive->connectionInfo.assocRspInfoElements); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeConnectionQualityIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrInt16 primitive->linkQuality.unifiRssi */ + bufferSize += 2; /* CsrInt16 primitive->linkQuality.unifiSnr */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectionQualityIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectionQualityInd *primitive = (CsrWifiSmeConnectionQualityInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->linkQuality.unifiRssi); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->linkQuality.unifiSnr); + return(ptr); +} + + +void* CsrWifiSmeConnectionQualityIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectionQualityInd *primitive = (CsrWifiSmeConnectionQualityInd *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionQualityInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->linkQuality.unifiRssi, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->linkQuality.unifiSnr, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 101) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrUint8 primitive->connectionStats.unifiTxDataRate */ + bufferSize += 1; /* CsrUint8 primitive->connectionStats.unifiRxDataRate */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RetryCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11MultipleRetryCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11AckFailureCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11FrameDuplicateCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11FcsErrorCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RtsSuccessCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RtsFailureCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11FailedCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11TransmittedFragmentCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11TransmittedFrameCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11WepExcludedCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11WepIcvErrorCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11WepUndecryptableCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11MulticastReceivedFrameCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11MulticastTransmittedFrameCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11ReceivedFragmentCount */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11Rsna4WayHandshakeFailures */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaStatsTkipReplays */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaStatsTkipIcvErrors */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaStatsCcmpReplays */ + bufferSize += 4; /* CsrUint32 primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeConnectionStatsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeConnectionStatsGetCfm *primitive = (CsrWifiSmeConnectionStatsGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionStats.unifiTxDataRate); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionStats.unifiRxDataRate); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RetryCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11MultipleRetryCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11AckFailureCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11FrameDuplicateCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11FcsErrorCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RtsSuccessCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RtsFailureCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11FailedCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11TransmittedFragmentCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11TransmittedFrameCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11WepExcludedCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11WepIcvErrorCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11WepUndecryptableCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11MulticastReceivedFrameCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11MulticastTransmittedFrameCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11ReceivedFragmentCount); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11Rsna4WayHandshakeFailures); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaStatsTkipReplays); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaStatsTkipIcvErrors); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaStatsCcmpReplays); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors); + return(ptr); +} + + +void* CsrWifiSmeConnectionStatsGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeConnectionStatsGetCfm *primitive = (CsrWifiSmeConnectionStatsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeConnectionStatsGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionStats.unifiTxDataRate, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionStats.unifiRxDataRate, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RetryCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11MultipleRetryCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11AckFailureCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11FrameDuplicateCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11FcsErrorCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RtsSuccessCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RtsFailureCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11FailedCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11TransmittedFragmentCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11TransmittedFrameCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11WepExcludedCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11WepIcvErrorCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11WepUndecryptableCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11MulticastReceivedFrameCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11MulticastTransmittedFrameCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11ReceivedFragmentCount, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11Rsna4WayHandshakeFailures, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaStatsTkipReplays, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaStatsTkipIcvErrors, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaStatsCcmpReplays, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeDisconnectCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeDisconnectCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeDisconnectCfm *primitive = (CsrWifiSmeDisconnectCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeDisconnectCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeDisconnectCfm *primitive = (CsrWifiSmeDisconnectCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeDisconnectCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeHostConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmeHostPowerMode primitive->hostConfig.powerMode */ + bufferSize += 2; /* CsrUint16 primitive->hostConfig.applicationDataPeriodMs */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeHostConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeHostConfigGetCfm *primitive = (CsrWifiSmeHostConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->hostConfig.powerMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->hostConfig.applicationDataPeriodMs); + return(ptr); +} + + +void* CsrWifiSmeHostConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeHostConfigGetCfm *primitive = (CsrWifiSmeHostConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->hostConfig.powerMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->hostConfig.applicationDataPeriodMs, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeHostConfigSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeHostConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeHostConfigSetCfm *primitive = (CsrWifiSmeHostConfigSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeHostConfigSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeHostConfigSetCfm *primitive = (CsrWifiSmeHostConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeHostConfigSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeIbssStationIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + bufferSize += 1; /* CsrBool primitive->isconnected */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeIbssStationIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeIbssStationInd *primitive = (CsrWifiSmeIbssStationInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->isconnected); + return(ptr); +} + + +void* CsrWifiSmeIbssStationIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeIbssStationInd *primitive = (CsrWifiSmeIbssStationInd *) CsrPmemAlloc(sizeof(CsrWifiSmeIbssStationInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->isconnected, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeKeyCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrWifiSmeKeyType primitive->keyType */ + bufferSize += 6; /* CsrUint8 primitive->peerMacAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeKeyCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeKeyCfm *primitive = (CsrWifiSmeKeyCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->keyType); + CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiSmeKeyCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeKeyCfm *primitive = (CsrWifiSmeKeyCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeKeyCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->keyType, buffer, &offset); + CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiSmeLinkQualityGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrInt16 primitive->linkQuality.unifiRssi */ + bufferSize += 2; /* CsrInt16 primitive->linkQuality.unifiSnr */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeLinkQualityGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeLinkQualityGetCfm *primitive = (CsrWifiSmeLinkQualityGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->linkQuality.unifiRssi); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->linkQuality.unifiSnr); + return(ptr); +} + + +void* CsrWifiSmeLinkQualityGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeLinkQualityGetCfm *primitive = (CsrWifiSmeLinkQualityGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeLinkQualityGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->linkQuality.unifiRssi, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->linkQuality.unifiSnr, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeMediaStatusIndSizeof(void *msg) +{ + CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 99) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeMediaStatus primitive->mediaStatus */ + bufferSize += 32; /* CsrUint8 primitive->connectionInfo.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.bssid.a[6] */ + bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ + bufferSize += 1; /* CsrUint8 primitive->connectionInfo.channelNumber */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.channelFrequency */ + bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ + bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.atimWindowTu */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconPeriodTu */ + bufferSize += 1; /* CsrBool primitive->connectionInfo.reassociation */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.beaconFrameLength */ + bufferSize += primitive->connectionInfo.beaconFrameLength; /* CsrUint8 primitive->connectionInfo.beaconFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationReqFrameLength */ + bufferSize += primitive->connectionInfo.associationReqFrameLength; /* CsrUint8 primitive->connectionInfo.associationReqFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.associationRspFrameLength */ + bufferSize += primitive->connectionInfo.associationRspFrameLength; /* CsrUint8 primitive->connectionInfo.associationRspFrame */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocScanInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocScanInfoElements */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqCapabilities */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqListenIntervalTu */ + bufferSize += 6; /* CsrUint8 primitive->connectionInfo.assocReqApAddress.a[6] */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocReqInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocReqInfoElements */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspCapabilityInfo */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspAssociationId */ + bufferSize += 2; /* CsrUint16 primitive->connectionInfo.assocRspInfoElementsLength */ + bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* CsrUint8 primitive->connectionInfo.assocRspInfoElements */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->disassocReason */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->deauthReason */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMediaStatusIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mediaStatus); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.networkType80211); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.channelNumber); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.channelFrequency); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.authMode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.pairwiseCipher); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.groupCipher); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.ifIndex); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.atimWindowTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconPeriodTu); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->connectionInfo.reassociation); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.beaconFrameLength); + if (primitive->connectionInfo.beaconFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationReqFrameLength); + if (primitive->connectionInfo.associationReqFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.associationRspFrameLength); + if (primitive->connectionInfo.associationRspFrameLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocScanInfoElementsLength); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqCapabilities); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqListenIntervalTu); + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocReqInfoElementsLength); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspResult); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspCapabilityInfo); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspAssociationId); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->connectionInfo.assocRspInfoElementsLength); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + CsrUint16Ser(ptr, len, (CsrUint16) primitive->disassocReason); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->deauthReason); + return(ptr); +} + + +void* CsrWifiSmeMediaStatusIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *) CsrPmemAlloc(sizeof(CsrWifiSmeMediaStatusInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mediaStatus, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.authMode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->connectionInfo.reassociation, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); + if (primitive->connectionInfo.beaconFrameLength) + { + primitive->connectionInfo.beaconFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.beaconFrameLength); + CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.beaconFrameLength))); + } + else + { + primitive->connectionInfo.beaconFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationReqFrameLength) + { + primitive->connectionInfo.associationReqFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationReqFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationReqFrameLength))); + } + else + { + primitive->connectionInfo.associationReqFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); + if (primitive->connectionInfo.associationRspFrameLength) + { + primitive->connectionInfo.associationRspFrame = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.associationRspFrameLength); + CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.associationRspFrameLength))); + } + else + { + primitive->connectionInfo.associationRspFrame = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocScanInfoElementsLength) + { + primitive->connectionInfo.assocScanInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocScanInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocScanInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocScanInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); + CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocReqInfoElementsLength) + { + primitive->connectionInfo.assocReqInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocReqInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocReqInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocReqInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); + if (primitive->connectionInfo.assocRspInfoElementsLength) + { + primitive->connectionInfo.assocRspInfoElements = (CsrUint8 *)CsrPmemAlloc(primitive->connectionInfo.assocRspInfoElementsLength); + CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((CsrUint16) (primitive->connectionInfo.assocRspInfoElementsLength))); + } + else + { + primitive->connectionInfo.assocRspInfoElements = NULL; + } + CsrUint16Des((CsrUint16 *) &primitive->disassocReason, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->deauthReason, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeMediaStatusIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *) voidPrimitivePointer; + CsrPmemFree(primitive->connectionInfo.beaconFrame); + CsrPmemFree(primitive->connectionInfo.associationReqFrame); + CsrPmemFree(primitive->connectionInfo.associationRspFrame); + CsrPmemFree(primitive->connectionInfo.assocScanInfoElements); + CsrPmemFree(primitive->connectionInfo.assocReqInfoElements); + CsrPmemFree(primitive->connectionInfo.assocRspInfoElements); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMibConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrBool primitive->mibConfig.unifiFixMaxTxDataRate */ + bufferSize += 1; /* CsrUint8 primitive->mibConfig.unifiFixTxDataRate */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11RtsThreshold */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11FragmentationThreshold */ + bufferSize += 2; /* CsrUint16 primitive->mibConfig.dot11CurrentTxPowerLevel */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibConfigGetCfm *primitive = (CsrWifiSmeMibConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mibConfig.unifiFixMaxTxDataRate); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mibConfig.unifiFixTxDataRate); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11RtsThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11FragmentationThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibConfig.dot11CurrentTxPowerLevel); + return(ptr); +} + + +void* CsrWifiSmeMibConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibConfigGetCfm *primitive = (CsrWifiSmeMibConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mibConfig.unifiFixMaxTxDataRate, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mibConfig.unifiFixTxDataRate, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11RtsThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11FragmentationThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibConfig.dot11CurrentTxPowerLevel, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeMibGetCfmSizeof(void *msg) +{ + CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->mibAttributeLength */ + bufferSize += primitive->mibAttributeLength; /* CsrUint8 primitive->mibAttribute */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibAttributeLength); + if (primitive->mibAttributeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((CsrUint16) (primitive->mibAttributeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeMibGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibAttributeLength, buffer, &offset); + if (primitive->mibAttributeLength) + { + primitive->mibAttribute = (CsrUint8 *)CsrPmemAlloc(primitive->mibAttributeLength); + CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((CsrUint16) (primitive->mibAttributeLength))); + } + else + { + primitive->mibAttribute = NULL; + } + + return primitive; +} + + +void CsrWifiSmeMibGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->mibAttribute); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMibGetNextCfmSizeof(void *msg) +{ + CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->mibAttributeLength */ + bufferSize += primitive->mibAttributeLength; /* CsrUint8 primitive->mibAttribute */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMibGetNextCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->mibAttributeLength); + if (primitive->mibAttributeLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((CsrUint16) (primitive->mibAttributeLength))); + } + return(ptr); +} + + +void* CsrWifiSmeMibGetNextCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMibGetNextCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->mibAttributeLength, buffer, &offset); + if (primitive->mibAttributeLength) + { + primitive->mibAttribute = (CsrUint8 *)CsrPmemAlloc(primitive->mibAttributeLength); + CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((CsrUint16) (primitive->mibAttributeLength))); + } + else + { + primitive->mibAttribute = NULL; + } + + return primitive; +} + + +void CsrWifiSmeMibGetNextCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->mibAttribute); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeMicFailureIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrBool primitive->secondFailure */ + bufferSize += 2; /* CsrUint16 primitive->count */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + bufferSize += 1; /* CsrWifiSmeKeyType primitive->keyType */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMicFailureIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMicFailureInd *primitive = (CsrWifiSmeMicFailureInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->secondFailure); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->count); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->keyType); + return(ptr); +} + + +void* CsrWifiSmeMicFailureIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMicFailureInd *primitive = (CsrWifiSmeMicFailureInd *) CsrPmemAlloc(sizeof(CsrWifiSmeMicFailureInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->secondFailure, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->count, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->keyType, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeMulticastAddressCfmSizeof(void *msg) +{ + CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->getAddressesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->getAddresses[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeMulticastAddressCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->getAddressesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiSmeMulticastAddressCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeMulticastAddressCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->getAddressesCount, buffer, &offset); + primitive->getAddresses = NULL; + if (primitive->getAddressesCount) + { + primitive->getAddresses = (CsrWifiMacAddress *)CsrPmemAlloc(sizeof(CsrWifiMacAddress) * primitive->getAddressesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getAddressesCount; i1++) + { + CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +void CsrWifiSmeMulticastAddressCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->getAddresses); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePacketFilterSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmePacketFilterSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePacketFilterSetCfm *primitive = (CsrWifiSmePacketFilterSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmePacketFilterSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePacketFilterSetCfm *primitive = (CsrWifiSmePacketFilterSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePacketFilterSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 6; /* CsrUint8 primitive->permanentMacAddress.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmePermanentMacAddressGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePermanentMacAddressGetCfm *primitive = (CsrWifiSmePermanentMacAddressGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrMemCpySer(ptr, len, (const void *) primitive->permanentMacAddress.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiSmePermanentMacAddressGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePermanentMacAddressGetCfm *primitive = (CsrWifiSmePermanentMacAddressGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePermanentMacAddressGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrMemCpyDes(primitive->permanentMacAddress.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiSmePmkidCandidateListIndSizeof(void *msg) +{ + CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrUint8 primitive->pmkidCandidatesCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->pmkidCandidates[i1].bssid.a[6] */ + bufferSize += 1; /* CsrBool primitive->pmkidCandidates[i1].preAuthAllowed */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmePmkidCandidateListIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->pmkidCandidatesCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->pmkidCandidates[i1].bssid.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->pmkidCandidates[i1].preAuthAllowed); + } + } + return(ptr); +} + + +void* CsrWifiSmePmkidCandidateListIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidCandidateListInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->pmkidCandidatesCount, buffer, &offset); + primitive->pmkidCandidates = NULL; + if (primitive->pmkidCandidatesCount) + { + primitive->pmkidCandidates = (CsrWifiSmePmkidCandidate *)CsrPmemAlloc(sizeof(CsrWifiSmePmkidCandidate) * primitive->pmkidCandidatesCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) + { + CsrMemCpyDes(primitive->pmkidCandidates[i1].bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->pmkidCandidates[i1].preAuthAllowed, buffer, &offset); + } + } + + return primitive; +} + + +void CsrWifiSmePmkidCandidateListIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *) voidPrimitivePointer; + CsrPmemFree(primitive->pmkidCandidates); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePmkidCfmSizeof(void *msg) +{ + CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 31) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ + bufferSize += 1; /* CsrUint8 primitive->getPmkidsCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->getPmkids[i1].bssid.a[6] */ + bufferSize += 16; /* CsrUint8 primitive->getPmkids[i1].pmkid[16] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmePmkidCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->action); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->getPmkidsCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->getPmkids[i1].bssid.a, ((CsrUint16) (6))); + CsrMemCpySer(ptr, len, (const void *) primitive->getPmkids[i1].pmkid, ((CsrUint16) (16))); + } + } + return(ptr); +} + + +void* CsrWifiSmePmkidCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePmkidCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->action, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->getPmkidsCount, buffer, &offset); + primitive->getPmkids = NULL; + if (primitive->getPmkidsCount) + { + primitive->getPmkids = (CsrWifiSmePmkid *)CsrPmemAlloc(sizeof(CsrWifiSmePmkid) * primitive->getPmkidsCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) + { + CsrMemCpyDes(primitive->getPmkids[i1].bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrMemCpyDes(primitive->getPmkids[i1].pmkid, buffer, &offset, ((CsrUint16) (16))); + } + } + + return primitive; +} + + +void CsrWifiSmePmkidCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->getPmkids); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmePowerConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->powerConfig.powerSaveLevel */ + bufferSize += 2; /* CsrUint16 primitive->powerConfig.listenIntervalTu */ + bufferSize += 1; /* CsrBool primitive->powerConfig.rxDtims */ + bufferSize += 1; /* CsrWifiSmeD3AutoScanMode primitive->powerConfig.d3AutoScanMode */ + bufferSize += 1; /* CsrUint8 primitive->powerConfig.clientTrafficWindow */ + bufferSize += 1; /* CsrBool primitive->powerConfig.opportunisticPowerSave */ + bufferSize += 1; /* CsrBool primitive->powerConfig.noticeOfAbsence */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmePowerConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmePowerConfigGetCfm *primitive = (CsrWifiSmePowerConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.powerSaveLevel); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->powerConfig.listenIntervalTu); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.rxDtims); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.d3AutoScanMode); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.clientTrafficWindow); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.opportunisticPowerSave); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->powerConfig.noticeOfAbsence); + return(ptr); +} + + +void* CsrWifiSmePowerConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmePowerConfigGetCfm *primitive = (CsrWifiSmePowerConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmePowerConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.powerSaveLevel, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->powerConfig.listenIntervalTu, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.rxDtims, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.d3AutoScanMode, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.clientTrafficWindow, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.opportunisticPowerSave, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->powerConfig.noticeOfAbsence, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrBool primitive->regDomInfo.dot11MultiDomainCapabilityImplemented */ + bufferSize += 1; /* CsrBool primitive->regDomInfo.dot11MultiDomainCapabilityEnabled */ + bufferSize += 1; /* CsrWifiSmeRegulatoryDomain primitive->regDomInfo.currentRegulatoryDomain */ + bufferSize += 2; /* CsrUint8 primitive->regDomInfo.currentCountryCode[2] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRegulatoryDomainInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRegulatoryDomainInfoGetCfm *primitive = (CsrWifiSmeRegulatoryDomainInfoGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->regDomInfo.dot11MultiDomainCapabilityImplemented); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->regDomInfo.dot11MultiDomainCapabilityEnabled); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->regDomInfo.currentRegulatoryDomain); + CsrMemCpySer(ptr, len, (const void *) primitive->regDomInfo.currentCountryCode, ((CsrUint16) (2))); + return(ptr); +} + + +void* CsrWifiSmeRegulatoryDomainInfoGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRegulatoryDomainInfoGetCfm *primitive = (CsrWifiSmeRegulatoryDomainInfoGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->regDomInfo.dot11MultiDomainCapabilityImplemented, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->regDomInfo.dot11MultiDomainCapabilityEnabled, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->regDomInfo.currentRegulatoryDomain, buffer, &offset); + CsrMemCpyDes(primitive->regDomInfo.currentCountryCode, buffer, &offset, ((CsrUint16) (2))); + + return primitive; +} + + +CsrSize CsrWifiSmeRoamCompleteIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRoamCompleteIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRoamCompleteInd *primitive = (CsrWifiSmeRoamCompleteInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeRoamCompleteIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRoamCompleteInd *primitive = (CsrWifiSmeRoamCompleteInd *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamCompleteInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeRoamStartIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiSmeRoamReason primitive->roamReason */ + bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->reason80211 */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRoamStartIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRoamStartInd *primitive = (CsrWifiSmeRoamStartInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamReason); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->reason80211); + return(ptr); +} + + +void* CsrWifiSmeRoamStartIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRoamStartInd *primitive = (CsrWifiSmeRoamStartInd *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamStartInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->roamReason, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->reason80211, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 72) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].rssiHighThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].rssiLowThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].snrHighThreshold */ + bufferSize += 2; /* CsrInt16 primitive->roamingConfig.roamingBands[i2].snrLowThreshold */ + } + } + bufferSize += 1; /* CsrBool primitive->roamingConfig.disableSmoothRoaming */ + bufferSize += 1; /* CsrBool primitive->roamingConfig.disableRoamScans */ + bufferSize += 1; /* CsrUint8 primitive->roamingConfig.reconnectLimit */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.reconnectLimitIntervalMs */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].intervalSeconds */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].validitySeconds */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRoamingConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRoamingConfigGetCfm *primitive = (CsrWifiSmeRoamingConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].rssiHighThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].rssiLowThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].snrHighThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamingBands[i2].snrLowThreshold); + } + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.disableSmoothRoaming); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.disableRoamScans); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->roamingConfig.reconnectLimit); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.reconnectLimitIntervalMs); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].intervalSeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].validitySeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu); + } + } + return(ptr); +} + + +void* CsrWifiSmeRoamingConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRoamingConfigGetCfm *primitive = (CsrWifiSmeRoamingConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].rssiHighThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].rssiLowThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].snrHighThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamingBands[i2].snrLowThreshold, buffer, &offset); + } + } + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.disableSmoothRoaming, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.disableRoamScans, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->roamingConfig.reconnectLimit, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.reconnectLimitIntervalMs, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 3; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].intervalSeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].validitySeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); + } + } + + return primitive; +} + + +CsrSize CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeRoamingConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeRoamingConfigSetCfm *primitive = (CsrWifiSmeRoamingConfigSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeRoamingConfigSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeRoamingConfigSetCfm *primitive = (CsrWifiSmeRoamingConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeRoamingConfigSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeScanConfigGetCfmSizeof(void *msg) +{ + CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 65) */ + bufferSize += 2; /* CsrResult primitive->status */ + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].intervalSeconds */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].validitySeconds */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu */ + } + } + bufferSize += 1; /* CsrBool primitive->scanConfig.disableAutonomousScans */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.maxResults */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.highRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.lowRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.deltaRssiThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.highSnrThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.lowSnrThreshold */ + bufferSize += 1; /* CsrInt8 primitive->scanConfig.deltaSnrThreshold */ + bufferSize += 2; /* CsrUint16 primitive->scanConfig.passiveChannelListCount */ + bufferSize += primitive->scanConfig.passiveChannelListCount; /* CsrUint8 primitive->scanConfig.passiveChannelList */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeScanConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].intervalSeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].validitySeconds); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu); + } + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.disableAutonomousScans); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.maxResults); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.highRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.lowRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.deltaRssiThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.highSnrThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.lowSnrThreshold); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanConfig.deltaSnrThreshold); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanConfig.passiveChannelListCount); + if (primitive->scanConfig.passiveChannelListCount) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanConfig.passiveChannelList, ((CsrUint16) (primitive->scanConfig.passiveChannelListCount))); + } + return(ptr); +} + + +void* CsrWifiSmeScanConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + { + CsrUint16 i2; + for (i2 = 0; i2 < 4; i2++) + { + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].intervalSeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].validitySeconds, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); + } + } + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.disableAutonomousScans, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.maxResults, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.highRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.lowRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.deltaRssiThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.highSnrThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.lowSnrThreshold, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanConfig.deltaSnrThreshold, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanConfig.passiveChannelListCount, buffer, &offset); + if (primitive->scanConfig.passiveChannelListCount) + { + primitive->scanConfig.passiveChannelList = (CsrUint8 *)CsrPmemAlloc(primitive->scanConfig.passiveChannelListCount); + CsrMemCpyDes(primitive->scanConfig.passiveChannelList, buffer, &offset, ((CsrUint16) (primitive->scanConfig.passiveChannelListCount))); + } + else + { + primitive->scanConfig.passiveChannelList = NULL; + } + + return primitive; +} + + +void CsrWifiSmeScanConfigGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->scanConfig.passiveChannelList); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeScanResultIndSizeof(void *msg) +{ + CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 149) */ + bufferSize += 32; /* CsrUint8 primitive->result.ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->result.ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->result.bssid.a[6] */ + bufferSize += 2; /* CsrInt16 primitive->result.rssi */ + bufferSize += 2; /* CsrInt16 primitive->result.snr */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->result.ifIndex */ + bufferSize += 2; /* CsrUint16 primitive->result.beaconPeriodTu */ + bufferSize += 8; /* CsrUint8 primitive->result.timeStamp.data[8] */ + bufferSize += 8; /* CsrUint8 primitive->result.localTime.data[8] */ + bufferSize += 2; /* CsrUint16 primitive->result.channelFrequency */ + bufferSize += 2; /* CsrUint16 primitive->result.capabilityInformation */ + bufferSize += 1; /* CsrUint8 primitive->result.channelNumber */ + bufferSize += 1; /* CsrWifiSmeBasicUsability primitive->result.usability */ + bufferSize += 1; /* CsrWifiSmeBssType primitive->result.bssType */ + bufferSize += 2; /* CsrUint16 primitive->result.informationElementsLength */ + bufferSize += primitive->result.informationElementsLength; /* CsrUint8 primitive->result.informationElements */ + bufferSize += 1; /* CsrWifiSmeP2pRole primitive->result.p2pDeviceRole */ + switch (primitive->result.p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.reservedCli.empty */ + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + bufferSize += 1; /* CsrWifiSmeP2pGroupCapabilityMask primitive->result.deviceInfo.groupInfo.groupCapability */ + bufferSize += 6; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a[6] */ + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2pClientInfoCount */ + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + bufferSize += 6; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a[6] */ + bufferSize += 6; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a[6] */ + bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods */ + bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap */ + bufferSize += 8; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails[8] */ + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount */ + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + bufferSize += 8; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails[8] */ + } + } + bufferSize += 32; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName[32] */ + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength */ + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.reservedNone.empty */ + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + bufferSize += 6; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a[6] */ + bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->result.deviceInfo.standalonedevInfo.configMethods */ + bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap */ + bufferSize += 8; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails[8] */ + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount */ + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + bufferSize += 8; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails[8] */ + } + } + bufferSize += 32; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.deviceName[32] */ + bufferSize += 1; /* CsrUint8 primitive->result.deviceInfo.standalonedevInfo.deviceNameLength */ + break; + default: + break; + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeScanResultIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrMemCpySer(ptr, len, (const void *) primitive->result.ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->result.bssid.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.rssi); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.snr); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.ifIndex); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.beaconPeriodTu); + CsrMemCpySer(ptr, len, (const void *) primitive->result.timeStamp.data, ((CsrUint16) (8))); + CsrMemCpySer(ptr, len, (const void *) primitive->result.localTime.data, ((CsrUint16) (8))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.channelFrequency); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.capabilityInformation); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.channelNumber); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.usability); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.bssType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.informationElementsLength); + if (primitive->result.informationElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->result.informationElements, ((CsrUint16) (primitive->result.informationElementsLength))); + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.p2pDeviceRole); + switch (primitive->result.p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.reservedCli.empty); + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.groupInfo.groupCapability); + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.groupInfo.p2pClientInfoCount); + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, ((CsrUint16) (6))); + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap); + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, ((CsrUint16) (8))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, ((CsrUint16) (8))); + } + } + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength); + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.reservedNone.empty); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->result.deviceInfo.standalonedevInfo.configMethods); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap); + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, ((CsrUint16) (8))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, ((CsrUint16) (8))); + } + } + CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.deviceName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->result.deviceInfo.standalonedevInfo.deviceNameLength); + break; + default: + break; + } + return(ptr); +} + + +void* CsrWifiSmeScanResultIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrMemCpyDes(primitive->result.ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->result.ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->result.bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->result.rssi, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result.snr, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.ifIndex, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result.beaconPeriodTu, buffer, &offset); + CsrMemCpyDes(primitive->result.timeStamp.data, buffer, &offset, ((CsrUint16) (8))); + CsrMemCpyDes(primitive->result.localTime.data, buffer, &offset, ((CsrUint16) (8))); + CsrUint16Des((CsrUint16 *) &primitive->result.channelFrequency, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result.capabilityInformation, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.channelNumber, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.usability, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.bssType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->result.informationElementsLength, buffer, &offset); + if (primitive->result.informationElementsLength) + { + primitive->result.informationElements = (CsrUint8 *)CsrPmemAlloc(primitive->result.informationElementsLength); + CsrMemCpyDes(primitive->result.informationElements, buffer, &offset, ((CsrUint16) (primitive->result.informationElementsLength))); + } + else + { + primitive->result.informationElements = NULL; + } + CsrUint8Des((CsrUint8 *) &primitive->result.p2pDeviceRole, buffer, &offset); + switch (primitive->result.p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.reservedCli.empty, buffer, &offset); + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.groupInfo.groupCapability, buffer, &offset); + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.groupInfo.p2pClientInfoCount, buffer, &offset); + primitive->result.deviceInfo.groupInfo.p2PClientInfo = NULL; + if (primitive->result.deviceInfo.groupInfo.p2pClientInfoCount) + { + primitive->result.deviceInfo.groupInfo.p2PClientInfo = (CsrWifiSmeP2pClientInfoType *)CsrPmemAlloc(sizeof(CsrWifiSmeP2pClientInfoType) * primitive->result.deviceInfo.groupInfo.p2pClientInfoCount); + } + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap, buffer, &offset); + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, buffer, &offset, ((CsrUint16) (8))); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, buffer, &offset); + primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; + if (primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount) + { + primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = (CsrWifiSmeWpsDeviceType *)CsrPmemAlloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); + } + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, buffer, &offset, ((CsrUint16) (8))); + } + } + CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength, buffer, &offset); + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.reservedNone.empty, buffer, &offset); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->result.deviceInfo.standalonedevInfo.configMethods, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap, buffer, &offset); + CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, buffer, &offset, ((CsrUint16) (8))); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, buffer, &offset); + primitive->result.deviceInfo.standalonedevInfo.secDeviceType = NULL; + if (primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount) + { + primitive->result.deviceInfo.standalonedevInfo.secDeviceType = (CsrWifiSmeWpsDeviceType *)CsrPmemAlloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); + } + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, buffer, &offset, ((CsrUint16) (8))); + } + } + CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.deviceName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->result.deviceInfo.standalonedevInfo.deviceNameLength, buffer, &offset); + break; + default: + break; + } + + return primitive; +} + + +void CsrWifiSmeScanResultIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *) voidPrimitivePointer; + CsrPmemFree(primitive->result.informationElements); + switch (primitive->result.p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_GO: + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrPmemFree(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); + } + } + CsrPmemFree(primitive->result.deviceInfo.groupInfo.p2PClientInfo); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrPmemFree(primitive->result.deviceInfo.standalonedevInfo.secDeviceType); + break; + default: + break; + } + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeScanResultsGetCfmSizeof(void *msg) +{ + CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 153) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->scanResultsCount */ + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->scanResultsCount; i1++) + { + bufferSize += 32; /* CsrUint8 primitive->scanResults[i1].ssid.ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].ssid.length */ + bufferSize += 6; /* CsrUint8 primitive->scanResults[i1].bssid.a[6] */ + bufferSize += 2; /* CsrInt16 primitive->scanResults[i1].rssi */ + bufferSize += 2; /* CsrInt16 primitive->scanResults[i1].snr */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->scanResults[i1].ifIndex */ + bufferSize += 2; /* CsrUint16 primitive->scanResults[i1].beaconPeriodTu */ + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].timeStamp.data[8] */ + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].localTime.data[8] */ + bufferSize += 2; /* CsrUint16 primitive->scanResults[i1].channelFrequency */ + bufferSize += 2; /* CsrUint16 primitive->scanResults[i1].capabilityInformation */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].channelNumber */ + bufferSize += 1; /* CsrWifiSmeBasicUsability primitive->scanResults[i1].usability */ + bufferSize += 1; /* CsrWifiSmeBssType primitive->scanResults[i1].bssType */ + bufferSize += 2; /* CsrUint16 primitive->scanResults[i1].informationElementsLength */ + bufferSize += primitive->scanResults[i1].informationElementsLength; /* CsrUint8 primitive->scanResults[i1].informationElements */ + bufferSize += 1; /* CsrWifiSmeP2pRole primitive->scanResults[i1].p2pDeviceRole */ + switch (primitive->scanResults[i1].p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.reservedCli.empty */ + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + bufferSize += 1; /* CsrWifiSmeP2pGroupCapabilityMask primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability */ + bufferSize += 6; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a[6] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount */ + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + bufferSize += 6; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a[6] */ + bufferSize += 6; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a[6] */ + bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods */ + bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap */ + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails[8] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount */ + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails[8] */ + } + } + bufferSize += 32; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName[32] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength */ + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.reservedNone.empty */ + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + bufferSize += 6; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a[6] */ + bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods */ + bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap */ + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails[8] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount */ + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + bufferSize += 8; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails[8] */ + } + } + bufferSize += 32; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName[32] */ + bufferSize += 1; /* CsrUint8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength */ + break; + default: + break; + } + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeScanResultsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResultsCount); + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->scanResultsCount; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].ssid.ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].ssid.length); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].bssid.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].rssi); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].snr); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].ifIndex); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].beaconPeriodTu); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].timeStamp.data, ((CsrUint16) (8))); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].localTime.data, ((CsrUint16) (8))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].channelFrequency); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].capabilityInformation); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].channelNumber); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].usability); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].bssType); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].informationElementsLength); + if (primitive->scanResults[i1].informationElementsLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].informationElements, ((CsrUint16) (primitive->scanResults[i1].informationElementsLength))); + } + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].p2pDeviceRole); + switch (primitive->scanResults[i1].p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.reservedCli.empty); + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a, ((CsrUint16) (6))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount); + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, ((CsrUint16) (6))); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, ((CsrUint16) (8))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, ((CsrUint16) (8))); + } + } + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength); + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.reservedNone.empty); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a, ((CsrUint16) (6))); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap); + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, ((CsrUint16) (8))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, ((CsrUint16) (8))); + } + } + CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength); + break; + default: + break; + } + } + } + return(ptr); +} + + +void* CsrWifiSmeScanResultsGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeScanResultsGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanResultsCount, buffer, &offset); + primitive->scanResults = NULL; + if (primitive->scanResultsCount) + { + primitive->scanResults = (CsrWifiSmeScanResult *)CsrPmemAlloc(sizeof(CsrWifiSmeScanResult) * primitive->scanResultsCount); + } + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->scanResultsCount; i1++) + { + CsrMemCpyDes(primitive->scanResults[i1].ssid.ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].ssid.length, buffer, &offset); + CsrMemCpyDes(primitive->scanResults[i1].bssid.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].rssi, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].snr, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].ifIndex, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].beaconPeriodTu, buffer, &offset); + CsrMemCpyDes(primitive->scanResults[i1].timeStamp.data, buffer, &offset, ((CsrUint16) (8))); + CsrMemCpyDes(primitive->scanResults[i1].localTime.data, buffer, &offset, ((CsrUint16) (8))); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].channelFrequency, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].capabilityInformation, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].channelNumber, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].usability, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].bssType, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].informationElementsLength, buffer, &offset); + if (primitive->scanResults[i1].informationElementsLength) + { + primitive->scanResults[i1].informationElements = (CsrUint8 *)CsrPmemAlloc(primitive->scanResults[i1].informationElementsLength); + CsrMemCpyDes(primitive->scanResults[i1].informationElements, buffer, &offset, ((CsrUint16) (primitive->scanResults[i1].informationElementsLength))); + } + else + { + primitive->scanResults[i1].informationElements = NULL; + } + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].p2pDeviceRole, buffer, &offset); + switch (primitive->scanResults[i1].p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_CLI: + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.reservedCli.empty, buffer, &offset); + break; + case CSR_WIFI_SME_P2P_ROLE_GO: + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability, buffer, &offset); + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount, buffer, &offset); + primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = NULL; + if (primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount) + { + primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = (CsrWifiSmeP2pClientInfoType *)CsrPmemAlloc(sizeof(CsrWifiSmeP2pClientInfoType) * primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount); + } + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap, buffer, &offset); + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, buffer, &offset, ((CsrUint16) (8))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, buffer, &offset); + primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; + if (primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount) + { + primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = (CsrWifiSmeWpsDeviceType *)CsrPmemAlloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); + } + { + CsrUint16 i6; + for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) + { + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, buffer, &offset, ((CsrUint16) (8))); + } + } + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength, buffer, &offset); + } + } + break; + case CSR_WIFI_SME_P2P_ROLE_NONE: + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.reservedNone.empty, buffer, &offset); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a, buffer, &offset, ((CsrUint16) (6))); + CsrUint16Des((CsrUint16 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap, buffer, &offset); + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, buffer, &offset, ((CsrUint16) (8))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, buffer, &offset); + primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = NULL; + if (primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount) + { + primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = (CsrWifiSmeWpsDeviceType *)CsrPmemAlloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); + } + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) + { + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, buffer, &offset, ((CsrUint16) (8))); + } + } + CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength, buffer, &offset); + break; + default: + break; + } + } + } + + return primitive; +} + + +void CsrWifiSmeScanResultsGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *) voidPrimitivePointer; + { + CsrUint16 i1; + for (i1 = 0; i1 < primitive->scanResultsCount; i1++) + { + CsrPmemFree(primitive->scanResults[i1].informationElements); + switch (primitive->scanResults[i1].p2pDeviceRole) + { + case CSR_WIFI_SME_P2P_ROLE_GO: + { + CsrUint16 i4; + for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) + { + CsrPmemFree(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); + } + } + CsrPmemFree(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo); + break; + case CSR_WIFI_SME_P2P_ROLE_STANDALONE: + CsrPmemFree(primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType); + break; + default: + break; + } + } + } + CsrPmemFree(primitive->scanResults); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ + bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */ + bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ + bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */ + bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSmeStaConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSmeStaConfigGetCfm *primitive = (CsrWifiSmeSmeStaConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.connectionQualityRssiChangeTrigger); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.connectionQualitySnrChangeTrigger); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.wmmModeMask); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.ifIndex); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.allowUnicastUseGroupCipher); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->smeConfig.enableOpportunisticKeyCaching); + return(ptr); +} + + +void* CsrWifiSmeSmeStaConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSmeStaConfigGetCfm *primitive = (CsrWifiSmeSmeStaConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.connectionQualityRssiChangeTrigger, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.connectionQualitySnrChangeTrigger, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.wmmModeMask, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.ifIndex, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.allowUnicastUseGroupCipher, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->smeConfig.enableOpportunisticKeyCaching, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSmeStaConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSmeStaConfigSetCfm *primitive = (CsrWifiSmeSmeStaConfigSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiSmeSmeStaConfigSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSmeStaConfigSetCfm *primitive = (CsrWifiSmeSmeStaConfigSetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeStaConfigSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ + bufferSize += 2; /* CsrResult primitive->status */ + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + bufferSize += 6; /* CsrUint8 primitive->stationMacAddress[i1].a[6] */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeStationMacAddressGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeStationMacAddressGetCfm *primitive = (CsrWifiSmeStationMacAddressGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->stationMacAddress[i1].a, ((CsrUint16) (6))); + } + } + return(ptr); +} + + +void* CsrWifiSmeStationMacAddressGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeStationMacAddressGetCfm *primitive = (CsrWifiSmeStationMacAddressGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeStationMacAddressGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + { + CsrUint16 i1; + for (i1 = 0; i1 < 2; i1++) + { + CsrMemCpyDes(primitive->stationMacAddress[i1].a, buffer, &offset, ((CsrUint16) (6))); + } + } + + return primitive; +} + + +CsrSize CsrWifiSmeTspecIndSizeof(void *msg) +{ + CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 4; /* CsrUint32 primitive->transactionId */ + bufferSize += 1; /* CsrWifiSmeTspecResultCode primitive->tspecResultCode */ + bufferSize += 2; /* CsrUint16 primitive->tspecLength */ + bufferSize += primitive->tspecLength; /* CsrUint8 primitive->tspec */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeTspecIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->transactionId); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->tspecResultCode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tspecLength); + if (primitive->tspecLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((CsrUint16) (primitive->tspecLength))); + } + return(ptr); +} + + +void* CsrWifiSmeTspecIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->transactionId, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->tspecResultCode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->tspecLength, buffer, &offset); + if (primitive->tspecLength) + { + primitive->tspec = (CsrUint8 *)CsrPmemAlloc(primitive->tspecLength); + CsrMemCpyDes(primitive->tspec, buffer, &offset, ((CsrUint16) (primitive->tspecLength))); + } + else + { + primitive->tspec = NULL; + } + + return primitive; +} + + +void CsrWifiSmeTspecIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *) voidPrimitivePointer; + CsrPmemFree(primitive->tspec); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeTspecCfmSizeof(void *msg) +{ + CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 4; /* CsrUint32 primitive->transactionId */ + bufferSize += 1; /* CsrWifiSmeTspecResultCode primitive->tspecResultCode */ + bufferSize += 2; /* CsrUint16 primitive->tspecLength */ + bufferSize += primitive->tspecLength; /* CsrUint8 primitive->tspec */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeTspecCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->transactionId); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->tspecResultCode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->tspecLength); + if (primitive->tspecLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((CsrUint16) (primitive->tspecLength))); + } + return(ptr); +} + + +void* CsrWifiSmeTspecCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeTspecCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->transactionId, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->tspecResultCode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->tspecLength, buffer, &offset); + if (primitive->tspecLength) + { + primitive->tspec = (CsrUint8 *)CsrPmemAlloc(primitive->tspecLength); + CsrMemCpyDes(primitive->tspec, buffer, &offset, ((CsrUint16) (primitive->tspecLength))); + } + else + { + primitive->tspec = NULL; + } + + return primitive; +} + + +void CsrWifiSmeTspecCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->tspec); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeVersionsGetCfmSizeof(void *msg) +{ + CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 33) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 4; /* CsrUint32 primitive->versions.chipId */ + bufferSize += 4; /* CsrUint32 primitive->versions.chipVersion */ + bufferSize += 4; /* CsrUint32 primitive->versions.firmwareBuild */ + bufferSize += 4; /* CsrUint32 primitive->versions.firmwarePatch */ + bufferSize += 4; /* CsrUint32 primitive->versions.firmwareHip */ + bufferSize += (primitive->versions.routerBuild?CsrStrLen(primitive->versions.routerBuild) : 0) + 1; /* CsrCharString* primitive->versions.routerBuild (0 byte len + 1 for NULL Term) */ + bufferSize += 4; /* CsrUint32 primitive->versions.routerHip */ + bufferSize += (primitive->versions.smeBuild?CsrStrLen(primitive->versions.smeBuild) : 0) + 1; /* CsrCharString* primitive->versions.smeBuild (0 byte len + 1 for NULL Term) */ + bufferSize += 4; /* CsrUint32 primitive->versions.smeHip */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeVersionsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.chipId); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.chipVersion); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.firmwareBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.firmwarePatch); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.firmwareHip); + CsrCharStringSer(ptr, len, primitive->versions.routerBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.routerHip); + CsrCharStringSer(ptr, len, primitive->versions.smeBuild); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->versions.smeHip); + return(ptr); +} + + +void* CsrWifiSmeVersionsGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeVersionsGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.chipId, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.chipVersion, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.firmwareBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.firmwarePatch, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.firmwareHip, buffer, &offset); + CsrCharStringDes(&primitive->versions.routerBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.routerHip, buffer, &offset); + CsrCharStringDes(&primitive->versions.smeBuild, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->versions.smeHip, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeVersionsGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->versions.routerBuild); + CsrPmemFree(primitive->versions.smeBuild); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg) +{ + CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 39) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrUint8 primitive->cloakedSsids.cloakedSsidsCount */ + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + bufferSize += 32; /* CsrUint8 primitive->cloakedSsids.cloakedSsids[i2].ssid[32] */ + bufferSize += 1; /* CsrUint8 primitive->cloakedSsids.cloakedSsids[i2].length */ + } + } + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCloakedSsidsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->cloakedSsids.cloakedSsidsCount); + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + CsrMemCpySer(ptr, len, (const void *) primitive->cloakedSsids.cloakedSsids[i2].ssid, ((CsrUint16) (32))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->cloakedSsids.cloakedSsids[i2].length); + } + } + return(ptr); +} + + +void* CsrWifiSmeCloakedSsidsGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeCloakedSsidsGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->cloakedSsids.cloakedSsidsCount, buffer, &offset); + primitive->cloakedSsids.cloakedSsids = NULL; + if (primitive->cloakedSsids.cloakedSsidsCount) + { + primitive->cloakedSsids.cloakedSsids = (CsrWifiSsid *)CsrPmemAlloc(sizeof(CsrWifiSsid) * primitive->cloakedSsids.cloakedSsidsCount); + } + { + CsrUint16 i2; + for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) + { + CsrMemCpyDes(primitive->cloakedSsids.cloakedSsids[i2].ssid, buffer, &offset, ((CsrUint16) (32))); + CsrUint8Des((CsrUint8 *) &primitive->cloakedSsids.cloakedSsids[i2].length, buffer, &offset); + } + } + + return primitive; +} + + +void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *) voidPrimitivePointer; + CsrPmemFree(primitive->cloakedSsids.cloakedSsids); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeWifiOnIndSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 6; /* CsrUint8 primitive->address.a[6] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeWifiOnIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeWifiOnInd *primitive = (CsrWifiSmeWifiOnInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((CsrUint16) (6))); + return(ptr); +} + + +void* CsrWifiSmeWifiOnIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeWifiOnInd *primitive = (CsrWifiSmeWifiOnInd *) CsrPmemAlloc(sizeof(CsrWifiSmeWifiOnInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrMemCpyDes(primitive->address.a, buffer, &offset, ((CsrUint16) (6))); + + return primitive; +} + + +CsrSize CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 1; /* CsrWifiSme80211dTrustLevel primitive->deviceConfig.trustLevel */ + bufferSize += 2; /* CsrUint8 primitive->deviceConfig.countryCode[2] */ + bufferSize += 1; /* CsrWifiSmeFirmwareDriverInterface primitive->deviceConfig.firmwareDriverInterface */ + bufferSize += 1; /* CsrBool primitive->deviceConfig.enableStrictDraftN */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSmeCommonConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSmeCommonConfigGetCfm *primitive = (CsrWifiSmeSmeCommonConfigGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.trustLevel); + CsrMemCpySer(ptr, len, (const void *) primitive->deviceConfig.countryCode, ((CsrUint16) (2))); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.firmwareDriverInterface); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->deviceConfig.enableStrictDraftN); + return(ptr); +} + + +void* CsrWifiSmeSmeCommonConfigGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSmeCommonConfigGetCfm *primitive = (CsrWifiSmeSmeCommonConfigGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeSmeCommonConfigGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.trustLevel, buffer, &offset); + CsrMemCpyDes(primitive->deviceConfig.countryCode, buffer, &offset, ((CsrUint16) (2))); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.firmwareDriverInterface, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->deviceConfig.enableStrictDraftN, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + bufferSize += 2; /* CsrResult primitive->status */ + bufferSize += 2; /* CsrUint16 primitive->numInterfaces */ + bufferSize += 2; /* CsrUint8 primitive->capBitmap[2] */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeInterfaceCapabilityGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeInterfaceCapabilityGetCfm *primitive = (CsrWifiSmeInterfaceCapabilityGetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->numInterfaces); + CsrMemCpySer(ptr, len, (const void *) primitive->capBitmap, ((CsrUint16) (2))); + return(ptr); +} + + +void* CsrWifiSmeInterfaceCapabilityGetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeInterfaceCapabilityGetCfm *primitive = (CsrWifiSmeInterfaceCapabilityGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeInterfaceCapabilityGetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->numInterfaces, buffer, &offset); + CsrMemCpyDes(primitive->capBitmap, buffer, &offset, ((CsrUint16) (2))); + + return primitive; +} + + +CsrSize CsrWifiSmeErrorIndSizeof(void *msg) +{ + CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 3) */ + bufferSize += (primitive->errorMessage?CsrStrLen(primitive->errorMessage) : 0) + 1; /* CsrCharString* primitive->errorMessage (0 byte len + 1 for NULL Term) */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeErrorIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrCharStringSer(ptr, len, primitive->errorMessage); + return(ptr); +} + + +void* CsrWifiSmeErrorIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *) CsrPmemAlloc(sizeof(CsrWifiSmeErrorInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrCharStringDes(&primitive->errorMessage, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeErrorIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *) voidPrimitivePointer; + CsrPmemFree(primitive->errorMessage); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeInfoIndSizeof(void *msg) +{ + CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 3) */ + bufferSize += (primitive->infoMessage?CsrStrLen(primitive->infoMessage) : 0) + 1; /* CsrCharString* primitive->infoMessage (0 byte len + 1 for NULL Term) */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeInfoIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrCharStringSer(ptr, len, primitive->infoMessage); + return(ptr); +} + + +void* CsrWifiSmeInfoIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *) CsrPmemAlloc(sizeof(CsrWifiSmeInfoInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrCharStringDes(&primitive->infoMessage, buffer, &offset); + + return primitive; +} + + +void CsrWifiSmeInfoIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *) voidPrimitivePointer; + CsrPmemFree(primitive->infoMessage); + CsrPmemFree(primitive); +} + + +CsrSize CsrWifiSmeCoreDumpIndSizeof(void *msg) +{ + CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 4; /* CsrUint32 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeCoreDumpIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiSmeCoreDumpIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *) CsrPmemAlloc(sizeof(CsrWifiSmeCoreDumpInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiSmeCoreDumpIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *) voidPrimitivePointer; + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.h b/drivers/staging/csr/csr_wifi_sme_serialize.h new file mode 100644 index 000000000000..c2d7fd68c4ae --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_serialize.h @@ -0,0 +1,668 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_SERIALIZE_H__ +#define CSR_WIFI_SME_SERIALIZE_H__ + +#include "csr_types.h" +#include "csr_pmem.h" +#include "csr_wifi_msgconv.h" + +#include "csr_wifi_sme_prim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void CsrWifiSmePfree(void *ptr); + +#define CsrWifiSmeActivateReqSer CsrWifiEventSer +#define CsrWifiSmeActivateReqDes CsrWifiEventDes +#define CsrWifiSmeActivateReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeActivateReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeAdhocConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmeAdhocConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmeAdhocConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeAdhocConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeAdhocConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeAdhocConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeAdhocConfigSetReqSizeof(void *msg); +#define CsrWifiSmeAdhocConfigSetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeBlacklistReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeBlacklistReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeBlacklistReqSizeof(void *msg); +extern void CsrWifiSmeBlacklistReqSerFree(void *msg); + +#define CsrWifiSmeCalibrationDataGetReqSer CsrWifiEventSer +#define CsrWifiSmeCalibrationDataGetReqDes CsrWifiEventDes +#define CsrWifiSmeCalibrationDataGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeCalibrationDataGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCalibrationDataSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCalibrationDataSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCalibrationDataSetReqSizeof(void *msg); +extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg); + +#define CsrWifiSmeCcxConfigGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeCcxConfigGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeCcxConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeCcxConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCcxConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCcxConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCcxConfigSetReqSizeof(void *msg); +#define CsrWifiSmeCcxConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeCoexConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmeCoexConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmeCoexConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeCoexConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCoexConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCoexConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCoexConfigSetReqSizeof(void *msg); +#define CsrWifiSmeCoexConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeCoexInfoGetReqSer CsrWifiEventSer +#define CsrWifiSmeCoexInfoGetReqDes CsrWifiEventDes +#define CsrWifiSmeCoexInfoGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeCoexInfoGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeConnectReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectReqSizeof(void *msg); +extern void CsrWifiSmeConnectReqSerFree(void *msg); + +#define CsrWifiSmeConnectionConfigGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeConnectionConfigGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeConnectionConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeConnectionConfigGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeConnectionInfoGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeConnectionInfoGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeConnectionInfoGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeConnectionInfoGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeConnectionStatsGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeConnectionStatsGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeConnectionStatsGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeConnectionStatsGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeDeactivateReqSer CsrWifiEventSer +#define CsrWifiSmeDeactivateReqDes CsrWifiEventDes +#define CsrWifiSmeDeactivateReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeDeactivateReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeDisconnectReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeDisconnectReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeDisconnectReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeDisconnectReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeEventMaskSetReqSer CsrWifiEventCsrUint32Ser +#define CsrWifiSmeEventMaskSetReqDes CsrWifiEventCsrUint32Des +#define CsrWifiSmeEventMaskSetReqSizeof CsrWifiEventCsrUint32Sizeof +#define CsrWifiSmeEventMaskSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeHostConfigGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeHostConfigGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeHostConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeHostConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeHostConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeHostConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeHostConfigSetReqSizeof(void *msg); +#define CsrWifiSmeHostConfigSetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeKeyReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeKeyReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeKeyReqSizeof(void *msg); +#define CsrWifiSmeKeyReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeLinkQualityGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeLinkQualityGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeLinkQualityGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeLinkQualityGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeMibConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmeMibConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmeMibConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeMibConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMibConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibConfigSetReqSizeof(void *msg); +#define CsrWifiSmeMibConfigSetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMibGetNextReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibGetNextReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibGetNextReqSizeof(void *msg); +extern void CsrWifiSmeMibGetNextReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeMibGetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibGetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibGetReqSizeof(void *msg); +extern void CsrWifiSmeMibGetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeMibSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibSetReqSizeof(void *msg); +extern void CsrWifiSmeMibSetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeMulticastAddressReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMulticastAddressReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMulticastAddressReqSizeof(void *msg); +extern void CsrWifiSmeMulticastAddressReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmePacketFilterSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePacketFilterSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePacketFilterSetReqSizeof(void *msg); +extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg); + +#define CsrWifiSmePermanentMacAddressGetReqSer CsrWifiEventSer +#define CsrWifiSmePermanentMacAddressGetReqDes CsrWifiEventDes +#define CsrWifiSmePermanentMacAddressGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmePermanentMacAddressGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmePmkidReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePmkidReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePmkidReqSizeof(void *msg); +extern void CsrWifiSmePmkidReqSerFree(void *msg); + +#define CsrWifiSmePowerConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmePowerConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmePowerConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmePowerConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmePowerConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePowerConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePowerConfigSetReqSizeof(void *msg); +#define CsrWifiSmePowerConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeRegulatoryDomainInfoGetReqSer CsrWifiEventSer +#define CsrWifiSmeRegulatoryDomainInfoGetReqDes CsrWifiEventDes +#define CsrWifiSmeRegulatoryDomainInfoGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeRegulatoryDomainInfoGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeRoamingConfigGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeRoamingConfigGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeRoamingConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeRoamingConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRoamingConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRoamingConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRoamingConfigSetReqSizeof(void *msg); +#define CsrWifiSmeRoamingConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeScanConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmeScanConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmeScanConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeScanConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeScanConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeScanConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeScanConfigSetReqSizeof(void *msg); +extern void CsrWifiSmeScanConfigSetReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeScanFullReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeScanFullReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeScanFullReqSizeof(void *msg); +extern void CsrWifiSmeScanFullReqSerFree(void *msg); + +#define CsrWifiSmeScanResultsFlushReqSer CsrWifiEventSer +#define CsrWifiSmeScanResultsFlushReqDes CsrWifiEventDes +#define CsrWifiSmeScanResultsFlushReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeScanResultsFlushReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeScanResultsGetReqSer CsrWifiEventSer +#define CsrWifiSmeScanResultsGetReqDes CsrWifiEventDes +#define CsrWifiSmeScanResultsGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeScanResultsGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeSmeStaConfigGetReqSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeSmeStaConfigGetReqDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeSmeStaConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeSmeStaConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeSmeStaConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSmeStaConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg); +#define CsrWifiSmeSmeStaConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeStationMacAddressGetReqSer CsrWifiEventSer +#define CsrWifiSmeStationMacAddressGetReqDes CsrWifiEventDes +#define CsrWifiSmeStationMacAddressGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeStationMacAddressGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeTspecReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeTspecReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeTspecReqSizeof(void *msg); +extern void CsrWifiSmeTspecReqSerFree(void *msg); + +#define CsrWifiSmeVersionsGetReqSer CsrWifiEventSer +#define CsrWifiSmeVersionsGetReqDes CsrWifiEventDes +#define CsrWifiSmeVersionsGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeVersionsGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeWifiFlightmodeReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeWifiFlightmodeReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeWifiFlightmodeReqSizeof(void *msg); +extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg); + +#define CsrWifiSmeWifiOffReqSer CsrWifiEventSer +#define CsrWifiSmeWifiOffReqDes CsrWifiEventDes +#define CsrWifiSmeWifiOffReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeWifiOffReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeWifiOnReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeWifiOnReqSizeof(void *msg); +extern void CsrWifiSmeWifiOnReqSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeCloakedSsidsSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCloakedSsidsSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg); +extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg); + +#define CsrWifiSmeCloakedSsidsGetReqSer CsrWifiEventSer +#define CsrWifiSmeCloakedSsidsGetReqDes CsrWifiEventDes +#define CsrWifiSmeCloakedSsidsGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeCloakedSsidsGetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeSmeCommonConfigGetReqSer CsrWifiEventSer +#define CsrWifiSmeSmeCommonConfigGetReqDes CsrWifiEventDes +#define CsrWifiSmeSmeCommonConfigGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeSmeCommonConfigGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeSmeCommonConfigSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSmeCommonConfigSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg); +#define CsrWifiSmeSmeCommonConfigSetReqSerFree CsrWifiSmePfree + +#define CsrWifiSmeInterfaceCapabilityGetReqSer CsrWifiEventSer +#define CsrWifiSmeInterfaceCapabilityGetReqDes CsrWifiEventDes +#define CsrWifiSmeInterfaceCapabilityGetReqSizeof CsrWifiEventSizeof +#define CsrWifiSmeInterfaceCapabilityGetReqSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeWpsConfigurationReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeWpsConfigurationReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg); +extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg); + +#define CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeActivateCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeAdhocConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeAdhocConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeAdhocConfigGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeAdhocConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeAdhocConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeAdhocConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeAdhocConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeAssociationCompleteIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeAssociationCompleteIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeAssociationCompleteIndSizeof(void *msg); +extern void CsrWifiSmeAssociationCompleteIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeAssociationStartIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeAssociationStartIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeAssociationStartIndSizeof(void *msg); +#define CsrWifiSmeAssociationStartIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeBlacklistCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeBlacklistCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeBlacklistCfmSizeof(void *msg); +extern void CsrWifiSmeBlacklistCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeCalibrationDataGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCalibrationDataGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg); +extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg); + +#define CsrWifiSmeCalibrationDataSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeCalibrationDataSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeCalibrationDataSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeCalibrationDataSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCcxConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCcxConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCcxConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeCcxConfigGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCcxConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCcxConfigSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCcxConfigSetCfmSizeof(void *msg); +#define CsrWifiSmeCcxConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCoexConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCoexConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCoexConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeCoexConfigGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeCoexConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeCoexConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeCoexConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeCoexConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCoexInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCoexInfoGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCoexInfoGetCfmSizeof(void *msg); +#define CsrWifiSmeCoexInfoGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeConnectCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectCfmSizeof(void *msg); +#define CsrWifiSmeConnectCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeConnectionConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectionConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg); +extern void CsrWifiSmeConnectionConfigGetCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeConnectionInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectionInfoGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg); +extern void CsrWifiSmeConnectionInfoGetCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeConnectionQualityIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectionQualityIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectionQualityIndSizeof(void *msg); +#define CsrWifiSmeConnectionQualityIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeConnectionStatsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeConnectionStatsGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg); +#define CsrWifiSmeConnectionStatsGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeDeactivateCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeDeactivateCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeDeactivateCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeDeactivateCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeDisconnectCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeDisconnectCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeDisconnectCfmSizeof(void *msg); +#define CsrWifiSmeDisconnectCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeEventMaskSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeEventMaskSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeEventMaskSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeHostConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeHostConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeHostConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeHostConfigGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeHostConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeHostConfigSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeHostConfigSetCfmSizeof(void *msg); +#define CsrWifiSmeHostConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeIbssStationIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeIbssStationIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeIbssStationIndSizeof(void *msg); +#define CsrWifiSmeIbssStationIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeKeyCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeKeyCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeKeyCfmSizeof(void *msg); +#define CsrWifiSmeKeyCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeLinkQualityGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeLinkQualityGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeLinkQualityGetCfmSizeof(void *msg); +#define CsrWifiSmeLinkQualityGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMediaStatusIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMediaStatusIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMediaStatusIndSizeof(void *msg); +extern void CsrWifiSmeMediaStatusIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeMibConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeMibConfigGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeMibConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeMibConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeMibConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeMibConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMibGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibGetCfmSizeof(void *msg); +extern void CsrWifiSmeMibGetCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeMibGetNextCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMibGetNextCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMibGetNextCfmSizeof(void *msg); +extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg); + +#define CsrWifiSmeMibSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeMibSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeMibSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeMibSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMicFailureIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMicFailureIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMicFailureIndSizeof(void *msg); +#define CsrWifiSmeMicFailureIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeMulticastAddressCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeMulticastAddressCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeMulticastAddressCfmSizeof(void *msg); +extern void CsrWifiSmeMulticastAddressCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmePacketFilterSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePacketFilterSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePacketFilterSetCfmSizeof(void *msg); +#define CsrWifiSmePacketFilterSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmePermanentMacAddressGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePermanentMacAddressGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg); +#define CsrWifiSmePermanentMacAddressGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmePmkidCandidateListIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePmkidCandidateListIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePmkidCandidateListIndSizeof(void *msg); +extern void CsrWifiSmePmkidCandidateListIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmePmkidCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePmkidCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePmkidCfmSizeof(void *msg); +extern void CsrWifiSmePmkidCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmePowerConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmePowerConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmePowerConfigGetCfmSizeof(void *msg); +#define CsrWifiSmePowerConfigGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmePowerConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmePowerConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmePowerConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmePowerConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRegulatoryDomainInfoGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRegulatoryDomainInfoGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg); +#define CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRoamCompleteIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRoamCompleteIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRoamCompleteIndSizeof(void *msg); +#define CsrWifiSmeRoamCompleteIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRoamStartIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRoamStartIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRoamStartIndSizeof(void *msg); +#define CsrWifiSmeRoamStartIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRoamingConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRoamingConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeRoamingConfigGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeRoamingConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeRoamingConfigSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg); +#define CsrWifiSmeRoamingConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeScanConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeScanConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeScanConfigGetCfmSizeof(void *msg); +extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg); + +#define CsrWifiSmeScanConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeScanConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeScanConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeScanConfigSetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeScanFullCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeScanFullCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeScanFullCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeScanFullCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeScanResultIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeScanResultIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeScanResultIndSizeof(void *msg); +extern void CsrWifiSmeScanResultIndSerFree(void *msg); + +#define CsrWifiSmeScanResultsFlushCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeScanResultsFlushCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeScanResultsFlushCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeScanResultsFlushCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeScanResultsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeScanResultsGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeScanResultsGetCfmSizeof(void *msg); +extern void CsrWifiSmeScanResultsGetCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeSmeStaConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSmeStaConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeSmeStaConfigGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeSmeStaConfigSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSmeStaConfigSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg); +#define CsrWifiSmeSmeStaConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeStationMacAddressGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeStationMacAddressGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg); +#define CsrWifiSmeStationMacAddressGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeTspecIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeTspecIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeTspecIndSizeof(void *msg); +extern void CsrWifiSmeTspecIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeTspecCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeTspecCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeTspecCfmSizeof(void *msg); +extern void CsrWifiSmeTspecCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeVersionsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeVersionsGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeVersionsGetCfmSizeof(void *msg); +extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg); + +#define CsrWifiSmeWifiFlightmodeCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeWifiFlightmodeCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeWifiFlightmodeCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeWifiFlightmodeCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeWifiOffIndSer CsrWifiEventCsrUint8Ser +#define CsrWifiSmeWifiOffIndDes CsrWifiEventCsrUint8Des +#define CsrWifiSmeWifiOffIndSizeof CsrWifiEventCsrUint8Sizeof +#define CsrWifiSmeWifiOffIndSerFree CsrWifiSmePfree + +#define CsrWifiSmeWifiOffCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeWifiOffCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeWifiOffCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeWifiOffCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeWifiOnCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeWifiOnCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeWifiOnCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeWifiOnCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeCloakedSsidsSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeCloakedSsidsSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeCloakedSsidsSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeCloakedSsidsSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeCloakedSsidsGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCloakedSsidsGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg); +extern void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeWifiOnIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeWifiOnIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeWifiOnIndSizeof(void *msg); +#define CsrWifiSmeWifiOnIndSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeSmeCommonConfigGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSmeCommonConfigGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg); +#define CsrWifiSmeSmeCommonConfigGetCfmSerFree CsrWifiSmePfree + +#define CsrWifiSmeSmeCommonConfigSetCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeSmeCommonConfigSetCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeSmeCommonConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeSmeCommonConfigSetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeInterfaceCapabilityGetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeInterfaceCapabilityGetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg); +#define CsrWifiSmeInterfaceCapabilityGetCfmSerFree CsrWifiSmePfree + +extern CsrUint8* CsrWifiSmeErrorIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeErrorIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeErrorIndSizeof(void *msg); +extern void CsrWifiSmeErrorIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeInfoIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeInfoIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeInfoIndSizeof(void *msg); +extern void CsrWifiSmeInfoIndSerFree(void *msg); + +extern CsrUint8* CsrWifiSmeCoreDumpIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeCoreDumpIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeCoreDumpIndSizeof(void *msg); +extern void CsrWifiSmeCoreDumpIndSerFree(void *msg); + +#define CsrWifiSmeAmpStatusChangeIndSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiSmeAmpStatusChangeIndDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiSmeAmpStatusChangeIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof +#define CsrWifiSmeAmpStatusChangeIndSerFree CsrWifiSmePfree + +#define CsrWifiSmeWpsConfigurationCfmSer CsrWifiEventCsrUint16Ser +#define CsrWifiSmeWpsConfigurationCfmDes CsrWifiEventCsrUint16Des +#define CsrWifiSmeWpsConfigurationCfmSizeof CsrWifiEventCsrUint16Sizeof +#define CsrWifiSmeWpsConfigurationCfmSerFree CsrWifiSmePfree + + +#ifdef __cplusplus +} +#endif +#endif /* CSR_WIFI_SME_SERIALIZE_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_sme_task.h b/drivers/staging/csr/csr_wifi_sme_task.h new file mode 100644 index 000000000000..62cc8b77fe4a --- /dev/null +++ b/drivers/staging/csr/csr_wifi_sme_task.h @@ -0,0 +1,34 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +/* Note: this is an auto-generated file. */ + +#ifndef CSR_WIFI_SME_TASK_H__ +#define CSR_WIFI_SME_TASK_H__ + +#include "csr_types.h" +#include "csr_sched.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSR_WIFI_SME_LOG_ID 0x1202FFFF +extern CsrSchedQid CSR_WIFI_SME_IFACEQUEUE; +void CsrWifiSmeInit(void **gash); +void CsrWifiSmeDeinit(void **gash); +void CsrWifiSmeHandler(void **gash); + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_SME_TASK_H__ */ + diff --git a/drivers/staging/csr/csr_wifi_vif_utils.h b/drivers/staging/csr/csr_wifi_vif_utils.h new file mode 100644 index 000000000000..c534588c4c56 --- /dev/null +++ b/drivers/staging/csr/csr_wifi_vif_utils.h @@ -0,0 +1,108 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2011 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifndef CSR_WIFI_VIF_UTILS_H +#define CSR_WIFI_VIF_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* STANDARD INCLUDES ********************************************************/ + +/* PROJECT INCLUDES *********************************************************/ +/* including this file for CsrWifiInterfaceMode*/ +#include "csr_wifi_private_common.h" + +/* MACROS *******************************************************************/ + +/* Common macros for NME and SME to be used temporarily until SoftMAC changes are made */ +#define CSR_WIFI_NUM_INTERFACES (CsrUint8)0x1 +#define CSR_WIFI_INTERFACE_IN_USE (CsrUint16)0x0 + +/* This is used at places where interface Id isn't available*/ +#define CSR_WIFI_INTERFACE_ZERO 0 +#define CSR_WIFI_INTERFACE_STA 0 +#define CSR_WIFI_INTERFACE_AMP 0 + + +#define CSR_WIFI_VIF_UTILS_UNDEFINED_TAG 0xFFFF + +/* Extract the Interface Id from the event */ +#define CsrWifiVifUtilsGetVifTagFromEvent(msg) \ + ((CsrUint16) * ((CsrUint16 *) ((CsrUint8 *) (msg) + sizeof(CsrWifiFsmEvent)))) + +/* The HPI Vif combines the type and the interface id */ +#define CsrWifiVifUtilsGetVifTagFromHipEvent(msg) \ + ((msg)->virtualInterfaceIdentifier & 0x00FF) + +#define CsrWifiVifUtilsPackHipEventVif(type, interfaceId) \ + ((CsrUint16)((interfaceId) | ((type) << 8))) + + +/* TYPES DEFINITIONS ********************************************************/ + +/* GLOBAL VARIABLE DECLARATIONS *********************************************/ + +/* PUBLIC FUNCTION PROTOTYPES ***********************************************/ + +/** + * @brief + * First checks if the mode is supported capability bitmap of the interface. + * If this succeeds, then checks if running this mode on this interface is allowed. + * + * @param[in] CsrUint8 : interface capability bitmap + * @param[in] CsrUint8* : pointer to the array of current interface modes + * @param[in] CsrUint16 : interfaceTag + * @param[in] CsrWifiInterfaceMode : mode + * + * @return + * CsrBool : returns true if the interface is allowed to operate in the mode otherwise false. + */ +extern CsrBool CsrWifiVifUtilsCheckCompatibility(CsrUint8 interfaceCapability, + CsrUint8 *currentInterfaceModes, + CsrUint16 interfaceTag, + CsrWifiInterfaceMode mode); + +/** + * @brief + * Checks if the specified interface is supported. + * NOTE: Only checks that the interface is supported, no checks are made to + * determine whether a supported interface may be made active. + * + * @param[in] CsrUint16 : interfaceTag + * + * @return + * CsrBool : returns true if the interface is supported, otherwise false. + */ +extern CsrBool CsrWifiVifUtilsIsSupported(CsrUint16 interfaceTag); + +#ifdef CSR_LOG_ENABLE +/** + * @brief + * Registers the virtual interface utils logging details. + * Should only be called once at initialisation. + * + * @param[in/out] None + * + * @return + * None + */ +void CsrWifiVifUtilsLogTextRegister(void); +#else +#define CsrWifiVifUtilsLogTextRegister() +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CSR_WIFI_VIF_UTILS_H */ + diff --git a/drivers/staging/csr/data_tx.c b/drivers/staging/csr/data_tx.c new file mode 100644 index 000000000000..c5858a58f3c1 --- /dev/null +++ b/drivers/staging/csr/data_tx.c @@ -0,0 +1,57 @@ +/* + * --------------------------------------------------------------------------- + * FILE: data_tx.c + * + * PURPOSE: + * This file provides functions to send data requests to the UniFi. + * + * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + +int +uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length) +{ + const unsigned char *p = packet; + CsrUint16 keyinfo; + + + if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8)) { + return 1; + } + + p += 8; + keyinfo = p[5] << 8 | p[6]; /* big-endian */ + if ( + (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ && + p[1] == 3 /* EAPOL-Key */ && + /* don't bother checking p[2] p[3] (hh ll, packet body length) */ + (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ && + ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ && + (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */ + (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */ + p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0) + ) { + unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected \n"); + return 0; + } + else + { + return 1; + } +} + +/* + * --------------------------------------------------------------------------- + * + * Data transport signals. + * + * --------------------------------------------------------------------------- + */ + diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c new file mode 100644 index 000000000000..4545fb2b063b --- /dev/null +++ b/drivers/staging/csr/drv.c @@ -0,0 +1,2150 @@ +/* + * --------------------------------------------------------------------------- + * FILE: drv.c + * + * PURPOSE: + * Conventional device interface for debugging/monitoring of the + * driver and h/w using unicli. This interface is also being used + * by the SME linux implementation and the helper apps. + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + + + +/* + * Porting Notes: + * Part of this file contains an example for how to glue the OS layer + * with the HIP core lib, the SDIO glue layer, and the SME. + * + * When the unifi_sdio.ko modules loads, the linux kernel calls unifi_load(). + * unifi_load() calls uf_sdio_load() which is exported by the SDIO glue + * layer. uf_sdio_load() registers this driver with the underlying SDIO driver. + * When a card is detected, the SDIO glue layer calls register_unifi_sdio() + * to pass the SDIO function context and ask the OS layer to initialise + * the card. register_unifi_sdio() allocates all the private data of the OS + * layer and calls uf_run_unifihelper() to start the SME. The SME calls + * unifi_sys_wifi_on_req() which uses the HIP core lib to initialise the card. + */ + +#include +#include +#include +#include +#include + +#include "csr_wifi_hip_unifiversion.h" +#include "unifi_priv.h" +#include "csr_wifi_hip_conversions.h" +#include "unifi_native.h" + +/* Module parameter variables */ +int buswidth = 0; /* 0 means use default, values 1,4 */ +int sdio_clock = 50000; /* kHz */ +int unifi_debug = 0; +/* + * fw_init prevents f/w initialisation on error. + * Unless necessary, avoid usage in the CSR_SME_EMB build because it prevents + * UniFi initialisation after getting out of suspend and also leaves + * UniFi powered when the module unloads. + */ +int fw_init[MAX_UNIFI_DEVS] = {-1, -1}; +int use_5g = 0; +int led_mask = 0; /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */ +int disable_hw_reset = 0; +int disable_power_control = 0; +int enable_wol = UNIFI_WOL_OFF; /* 0 for none, 1 for SDIO IRQ, 2 for PIO */ +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) +int tl_80211d = (int)CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB; +#endif +int sdio_block_size = -1; /* Override SDIO block size */ +int sdio_byte_mode = 0; /* 0 for block mode + padding, 1 for byte mode */ +int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; +int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ +int bh_priority = -1; + +MODULE_DESCRIPTION("CSR UniFi (SDIO)"); + +module_param(buswidth, int, S_IRUGO|S_IWUSR); +module_param(sdio_clock, int, S_IRUGO|S_IWUSR); +module_param(unifi_debug, int, S_IRUGO|S_IWUSR); +module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR); +module_param(use_5g, int, S_IRUGO|S_IWUSR); +module_param(led_mask, int, S_IRUGO|S_IWUSR); +module_param(disable_hw_reset, int, S_IRUGO|S_IWUSR); +module_param(disable_power_control, int, S_IRUGO|S_IWUSR); +module_param(enable_wol, int, S_IRUGO|S_IWUSR); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) +module_param(tl_80211d, int, S_IRUGO|S_IWUSR); +#endif +module_param(sdio_block_size, int, S_IRUGO|S_IWUSR); +module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR); +module_param(coredump_max, int, S_IRUGO|S_IWUSR); +module_param(run_bh_once, int, S_IRUGO|S_IWUSR); +module_param(bh_priority, int, S_IRUGO|S_IWUSR); + +MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode"); +MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)"); +MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level"); +MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error"); +MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band"); +MODULE_PARM_DESC(led_mask, "LED mask flags"); +MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset"); +MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control"); +MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO"); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) +MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)"); +#endif +MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size"); +MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO"); +MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate"); +MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts"); +MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority"); + +/* Callback for event logging to UDI clients */ +static void udi_log_event(ul_client_t *client, + const u8 *signal, int signal_len, + const bulk_data_param_t *bulkdata, + int dir); + +static void udi_set_log_filter(ul_client_t *pcli, + unifiio_filter_t *udi_filter); + + +/* Mutex to protect access to priv->sme_cli */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +DEFINE_SEMAPHORE(udi_mutex); +#else +DECLARE_MUTEX(udi_mutex); +#endif + +CsrInt32 CsrHipResultToStatus(CsrResult csrResult) +{ + CsrInt32 r = -EIO; + + switch (csrResult) + { + case CSR_RESULT_SUCCESS: + r = 0; + break; + case CSR_WIFI_HIP_RESULT_RANGE: + r = -ERANGE; + break; + case CSR_WIFI_HIP_RESULT_NO_DEVICE: + r = -ENODEV; + break; + case CSR_WIFI_HIP_RESULT_INVALID_VALUE: + r = -EINVAL; + break; + case CSR_WIFI_HIP_RESULT_NOT_FOUND: + r = -ENOENT; + break; + case CSR_WIFI_HIP_RESULT_NO_SPACE: + r = -ENOSPC; + break; + case CSR_WIFI_HIP_RESULT_NO_MEMORY: + r = -ENOMEM; + break; + case CSR_RESULT_FAILURE: + r = -EIO; + break; + default: + /*unifi_warning(card->ospriv, "CsrHipResultToStatus: Unrecognised csrResult error code: %d\n", csrResult);*/ + r = -EIO; + } + return r; +} + + +static const char* +trace_putest_cmdid(unifi_putest_command_t putest_cmd) +{ + switch (putest_cmd) + { + case UNIFI_PUTEST_START: + return "START"; + case UNIFI_PUTEST_STOP: + return "STOP"; + case UNIFI_PUTEST_SET_SDIO_CLOCK: + return "SET CLOCK"; + case UNIFI_PUTEST_CMD52_READ: + return "CMD52R"; + case UNIFI_PUTEST_CMD52_BLOCK_READ: + return "CMD52BR"; + case UNIFI_PUTEST_CMD52_WRITE: + return "CMD52W"; + case UNIFI_PUTEST_DL_FW: + return "D/L FW"; + case UNIFI_PUTEST_DL_FW_BUFF: + return "D/L FW BUFFER"; + case UNIFI_PUTEST_COREDUMP_PREPARE: + return "PREPARE COREDUMP"; + case UNIFI_PUTEST_GP_READ16: + return "GP16R"; + case UNIFI_PUTEST_GP_WRITE16: + return "GP16W"; + default: + return "ERROR: unrecognised command"; + } + } + + + +/* + * --------------------------------------------------------------------------- + * unifi_open + * unifi_release + * + * Open and release entry points for the UniFi debug driver. + * + * Arguments: + * Normal linux driver args. + * + * Returns: + * Linux error code. + * --------------------------------------------------------------------------- + */ +static int +unifi_open(struct inode *inode, struct file *file) +{ + int devno; + unifi_priv_t *priv; + ul_client_t *udi_cli; + + func_enter(); + + devno = MINOR(inode->i_rdev) >> 1; + + /* + * Increase the ref_count for the char device clients. + * Make sure you call uf_put_instance() to decreace it if + * unifi_open returns an error. + */ + priv = uf_get_instance(devno); + if (priv == NULL) { + unifi_error(NULL, "unifi_open: No device present\n"); + func_exit(); + return -ENODEV; + } + + /* Register this instance in the client's list. */ + /* The minor number determines the nature of the client (Unicli or SME). */ + if (MINOR(inode->i_rdev) & 0x1) { + udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); + if (udi_cli == NULL) { + /* Too many clients already using this device */ + unifi_error(priv, "Too many clients already open\n"); + uf_put_instance(devno); + func_exit(); + return -ENOSPC; + } + unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno); + } else { + /* + * Even-numbered device nodes are the control application. + * This is the userspace helper containing SME or + * unifi_manager. + */ + + down(&udi_mutex); + +#ifdef CSR_SME_USERSPACE + /* Check if a config client is already attached */ + if (priv->sme_cli) { + up(&udi_mutex); + uf_put_instance(devno); + + unifi_info(priv, "There is already a configuration client using the character device\n"); + func_exit(); + return -EBUSY; + } +#endif /* CSR_SME_USERSPACE */ + +#ifdef CSR_SUPPORT_SME + udi_cli = ul_register_client(priv, + CLI_USING_WIRE_FORMAT | CLI_SME_USERSPACE, + sme_log_event); +#else + /* Config client for native driver */ + udi_cli = ul_register_client(priv, + 0, + sme_native_log_event); +#endif + if (udi_cli == NULL) { + /* Too many clients already using this device */ + up(&udi_mutex); + uf_put_instance(devno); + + unifi_error(priv, "Too many clients already open\n"); + func_exit(); + return -ENOSPC; + } + + /* + * Fill-in the pointer to the configuration client. + * This is the SME userspace helper or unifi_manager. + * Not used in the SME embedded version. + */ + unifi_trace(priv, UDBG1, "SME client (id:%d s:0x%X) is registered\n", + udi_cli->client_id, udi_cli->sender_id); + /* Store the SME UniFi Linux Client */ + if (priv->sme_cli == NULL) { + priv->sme_cli = udi_cli; + } + + up(&udi_mutex); + } + + + /* + * Store the pointer to the client. + * All char driver's entry points will pass this pointer. + */ + file->private_data = udi_cli; + + func_exit(); + return 0; +} /* unifi_open() */ + + + +static int +unifi_release(struct inode *inode, struct file *filp) +{ + ul_client_t *udi_cli = (void*)filp->private_data; + int devno; + unifi_priv_t *priv; + + func_enter(); + + priv = uf_find_instance(udi_cli->instance); + if (!priv) { + unifi_error(priv, "unifi_close: instance for device not found\n"); + return -ENODEV; + } + + devno = MINOR(inode->i_rdev) >> 1; + + /* Even device nodes are the config client (i.e. SME or unifi_manager) */ + if ((MINOR(inode->i_rdev) & 0x1) == 0) { + + if (priv->sme_cli != udi_cli) { + unifi_notice(priv, "Surprise closing config device: not the sme client\n"); + } + unifi_notice(priv, "SME client close (unifi%d)\n", devno); + + /* + * Clear sme_cli before calling unifi_sys_... so it doesn't try to + * queue a reply to the (now gone) SME. + */ + down(&udi_mutex); + priv->sme_cli = NULL; + up(&udi_mutex); + +#ifdef CSR_SME_USERSPACE + /* Power-down when config client closes */ + { + CsrWifiRouterCtrlWifiOffReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, 0, 0, 0, NULL}}; + CsrWifiRouterCtrlWifiOffReqHandler(priv, &req.common); + } + + uf_sme_deinit(priv); +#endif /* CSR_SME_USERSPACE */ + } else { + + unifi_trace(priv, UDBG2, "UDI client close (unifiudi%d)\n", devno); + + /* If the pointer matches the logging client, stop logging. */ + down(&priv->udi_logging_mutex); + if (udi_cli == priv->logging_client) { + priv->logging_client = NULL; + } + up(&priv->udi_logging_mutex); + + if (udi_cli == priv->amp_client) { + priv->amp_client = NULL; + } + } + + /* Deregister this instance from the client's list. */ + ul_deregister_client(udi_cli); + + uf_put_instance(devno); + + return 0; +} /* unifi_release() */ + + + +/* + * --------------------------------------------------------------------------- + * unifi_read + * + * The read() driver entry point. + * + * Arguments: + * filp The file descriptor returned by unifi_open() + * p The user space buffer to copy the read data + * len The size of the p buffer + * poff + * + * Returns: + * number of bytes read or an error code on failure + * --------------------------------------------------------------------------- + */ +static ssize_t +unifi_read(struct file *filp, char *p, size_t len, loff_t *poff) +{ + ul_client_t *pcli = (void*)filp->private_data; + unifi_priv_t *priv; + udi_log_t *logptr = NULL; + udi_msg_t *msgptr; + struct list_head *l; + int msglen; + + func_enter(); + + priv = uf_find_instance(pcli->instance); + if (!priv) { + unifi_error(priv, "invalid priv\n"); + return -ENODEV; + } + + if (!pcli->udi_enabled) { + unifi_error(priv, "unifi_read: unknown client."); + return -EINVAL; + } + + if (list_empty(&pcli->udi_log)) { + if (filp->f_flags & O_NONBLOCK) { + /* Non-blocking - just return if the udi_log is empty */ + return 0; + } else { + /* Blocking - wait on the UDI wait queue */ + if (wait_event_interruptible(pcli->udi_wq, + !list_empty(&pcli->udi_log))) + { + unifi_error(priv, "unifi_read: wait_event_interruptible failed."); + return -ERESTARTSYS; + } + } + } + + /* Read entry from list head and remove it from the list */ + if (down_interruptible(&pcli->udi_sem)) { + return -ERESTARTSYS; + } + l = pcli->udi_log.next; + list_del(l); + up(&pcli->udi_sem); + + /* Get a pointer to whole struct */ + logptr = list_entry(l, udi_log_t, q); + if (logptr == NULL) { + unifi_error(priv, "unifi_read: failed to get event.\n"); + return -EINVAL; + } + + /* Get the real message */ + msgptr = &logptr->msg; + msglen = msgptr->length; + if (msglen > len) { + printk(KERN_WARNING "truncated read to %d actual msg len is %lu\n", msglen, (long unsigned int)len); + msglen = len; + } + + /* and pass it to the client (SME or Unicli). */ + if (copy_to_user(p, msgptr, msglen)) + { + printk(KERN_ERR "Failed to copy UDI log to user\n"); + kfree(logptr); + return -EFAULT; + } + + /* It is our resposibility to free the message buffer. */ + kfree(logptr); + + func_exit_r(msglen); + return msglen; + +} /* unifi_read() */ + + + +/* + * --------------------------------------------------------------------------- + * udi_send_signal_unpacked + * + * Sends an unpacked signal to UniFi. + * + * Arguments: + * priv Pointer to private context struct + * data Pointer to request structure and data to send + * data_len Length of data in data pointer. + * + * Returns: + * Number of bytes written, error otherwise. + * + * Notes: + * All clients that use this function to send a signal to the unifi + * must use the host formatted structures. + * --------------------------------------------------------------------------- + */ +static int +udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len) +{ + CSR_SIGNAL *sigptr = (CSR_SIGNAL*)data; + CSR_DATAREF *datarefptr; + bulk_data_param_t bulk_data; + uint signal_size, i; + uint bulk_data_offset = 0; + int bytecount, r; + CsrResult csrResult; + + /* Number of bytes in the signal */ + signal_size = SigGetSize(sigptr); + if (!signal_size || (signal_size > data_len)) { + unifi_error(priv, "unifi_sme_mlme_req - Invalid signal 0x%x size should be %d bytes\n", + sigptr->SignalPrimitiveHeader.SignalId, + signal_size); + return -EINVAL; + } + bytecount = signal_size; + + /* Get a pointer to the information of the first data reference */ + datarefptr = (CSR_DATAREF*)&sigptr->u; + + /* Initialize the offset in the data buffer, bulk data is right after the signal. */ + bulk_data_offset = signal_size; + + /* store the references and the size of the bulk data to the bulkdata structure */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + /* the length of the bulk data is in the signal */ + if ((datarefptr+i)->DataLength) { + void *dest; + + csrResult = unifi_net_data_malloc(priv, &bulk_data.d[i], (datarefptr+i)->DataLength); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "udi_send_signal_unpacked: failed to allocate request_data.\n"); + return -EIO; + } + + dest = (void*)bulk_data.d[i].os_data_ptr; + memcpy(dest, data + bulk_data_offset, bulk_data.d[i].data_length); + } else { + bulk_data.d[i].data_length = 0; + } + + bytecount += bulk_data.d[i].data_length; + /* advance the offset, to point the next bulk data */ + bulk_data_offset += bulk_data.d[i].data_length; + } + + + unifi_trace(priv, UDBG3, "SME Send: signal 0x%.4X\n", sigptr->SignalPrimitiveHeader.SignalId); + + /* Send the signal. */ + r = ul_send_signal_unpacked(priv, sigptr, &bulk_data); + if (r < 0) { + unifi_error(priv, "udi_send_signal_unpacked: send failed (%d)\n", r); + for(i=0;i buflen)) { + unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n", + sig_id); + func_exit(); + return -EINVAL; + } + unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n", + sig_id, signal_size); + /* Zero the data ref arrays */ + memset(&data_ptrs, 0, sizeof(data_ptrs)); + + /* + * Find the number of associated bulk data packets. Scan through + * the data refs to check that we have enough data and pick out + * pointers to appended bulk data. + */ + num_data_refs = 0; + bytecount = signal_size; + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) + { + unsigned int len = GET_PACKED_DATAREF_LEN(buf, i); + unifi_trace(priv, UDBG3, "udi_send_signal_raw: data_ref length = %d\n", len); + + if (len != 0) { + void *dest; + + csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[i], len); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "udi_send_signal_raw: failed to allocate request_data.\n"); + return -EIO; + } + + dest = (void*)data_ptrs.d[i].os_data_ptr; + memcpy(dest, buf + bytecount, len); + + bytecount += len; + num_data_refs++; + } + data_ptrs.d[i].data_length = len; + } + + unifi_trace(priv, UDBG3, "Queueing signal 0x%.4X from UDI with %u data refs\n", + sig_id, + num_data_refs); + + if (bytecount > buflen) { + unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount); + func_exit(); + return -EINVAL; + } + + /* Send the signal calling the function that uses the wire-formatted signals. */ + r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs); + if (r < 0) { + unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r); + func_exit(); + return -EIO; + } + +#ifdef CSR_NATIVE_LINUX + if (sig_id == CSR_MLME_POWERMGT_REQUEST_ID) { + int power_mode = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((buf + + SIZEOF_SIGNAL_HEADER + (UNIFI_MAX_DATA_REFERENCES*SIZEOF_DATAREF))); +#ifdef CSR_SUPPORT_WEXT + /* Overide the wext power mode to the new value */ + priv->wext_conf.power_mode = power_mode; +#endif + /* Configure deep sleep signaling */ + if (power_mode || (priv->interfacePriv[0]->connected == UnifiNotConnected)) { + csrResult = unifi_configure_low_power_mode(priv->card, + UNIFI_LOW_POWER_ENABLED, + UNIFI_PERIODIC_WAKE_HOST_DISABLED); + } else { + csrResult = unifi_configure_low_power_mode(priv->card, + UNIFI_LOW_POWER_DISABLED, + UNIFI_PERIODIC_WAKE_HOST_DISABLED); + } + } +#endif + + func_exit_r(bytecount); + + return bytecount; +} /* udi_send_signal_raw */ + +/* + * --------------------------------------------------------------------------- + * unifi_write + * + * The write() driver entry point. + * A UniFi Debug Interface client such as unicli can write a signal + * plus bulk data to the driver for sending to the UniFi chip. + * + * Only one signal may be sent per write operation. + * + * Arguments: + * filp The file descriptor returned by unifi_open() + * p The user space buffer to get the data from + * len The size of the p buffer + * poff + * + * Returns: + * number of bytes written or an error code on failure + * --------------------------------------------------------------------------- + */ +static ssize_t +unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff) +{ + ul_client_t *pcli = (ul_client_t*)filp->private_data; + unifi_priv_t *priv; + unsigned char *buf; + unsigned char *bufptr; + int remaining; + int bytes_written; + int r; + bulk_data_param_t bulkdata; + CsrResult csrResult; + + func_enter(); + + priv = uf_find_instance(pcli->instance); + if (!priv) { + unifi_error(priv, "invalid priv\n"); + return -ENODEV; + } + + unifi_trace(priv, UDBG5, "unifi_write: len = %d\n", len); + + if (!pcli->udi_enabled) { + unifi_error(priv, "udi disabled\n"); + return -EINVAL; + } + + /* + * AMP client sends only one signal at a time, so we can use + * unifi_net_data_malloc to save the extra copy. + */ + if (pcli == priv->amp_client) { + int signal_size; + int sig_id; + unsigned char *signal_buf; + char *user_data_buf; + + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "unifi_write: failed to allocate request_data.\n"); + func_exit(); + return -ENOMEM; + } + + user_data_buf = (char*)bulkdata.d[0].os_data_ptr; + + /* Get the data from the AMP client. */ + if (copy_from_user((void*)user_data_buf, p, len)) { + unifi_error(priv, "unifi_write: copy from user failed\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + func_exit(); + return -EFAULT; + } + + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].data_length = 0; + + /* Number of bytes in the signal */ + sig_id = GET_SIGNAL_ID(bulkdata.d[0].os_data_ptr); + signal_size = len; + signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 0); + signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 1); + if ((signal_size <= 0) || (signal_size > len)) { + unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n", + sig_id); + unifi_net_data_free(priv, &bulkdata.d[0]); + func_exit(); + return -EINVAL; + } + + unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n", + sig_id, signal_size); + + /* Allocate a buffer for the signal */ + signal_buf = kmalloc(signal_size, GFP_KERNEL); + if (!signal_buf) { + unifi_net_data_free(priv, &bulkdata.d[0]); + func_exit(); + return -ENOMEM; + } + + /* Get the signal from the os_data_ptr */ + memcpy(signal_buf, bulkdata.d[0].os_data_ptr, signal_size); + signal_buf[5] = (pcli->sender_id >> 8) & 0xff; + + if (signal_size < len) { + /* Remove the signal from the os_data_ptr */ + bulkdata.d[0].data_length -= signal_size; + bulkdata.d[0].os_data_ptr += signal_size; + } else { + bulkdata.d[0].data_length = 0; + bulkdata.d[0].os_data_ptr = NULL; + } + + /* Send the signal calling the function that uses the wire-formatted signals. */ + r = ul_send_signal_raw(priv, signal_buf, signal_size, &bulkdata); + if (r < 0) { + unifi_error(priv, "unifi_write: send failed (%d)\n", r); + if (bulkdata.d[0].os_data_ptr != NULL) { + unifi_net_data_free(priv, &bulkdata.d[0]); + } + } + + /* Free the signal buffer and return */ + kfree(signal_buf); + return len; + } + + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + return -ENOMEM; + } + + /* Get the data from the client (SME or Unicli). */ + if (copy_from_user((void*)buf, p, len)) { + unifi_error(priv, "copy from user failed\n"); + kfree(buf); + return -EFAULT; + } + + /* + * In SME userspace build read() contains a SYS or MGT message. + * Note that even though the SME sends one signal at a time, we can not + * use unifi_net_data_malloc because in the early stages, before having + * initialised the core, it will fail since the I/O block size is unknown. + */ +#ifdef CSR_SME_USERSPACE + if (pcli->configuration & CLI_SME_USERSPACE) { + CsrWifiRouterTransportRecv(priv, buf, len); + kfree(buf); + return len; + } +#endif + + /* ul_send_signal_raw will do a sanity check of len against signal content */ + + /* + * udi_send_signal_raw() and udi_send_signal_unpacked() return the number of bytes consumed. + * A write call can pass multiple signal concatenated together. + */ + bytes_written = 0; + remaining = len; + bufptr = buf; + while (remaining > 0) + { + int r; + + /* + * Set the SenderProcessId. + * The SignalPrimitiveHeader is the first 3 16-bit words of the signal, + * the SenderProcessId is bytes 4,5. + * The MSB of the sender ID needs to be set to the client ID. + * The LSB is controlled by the SME. + */ + bufptr[5] = (pcli->sender_id >> 8) & 0xff; + + /* use the appropriate interface, depending on the clients' configuration */ + if (pcli->configuration & CLI_USING_WIRE_FORMAT) { + unifi_trace(priv, UDBG1, "unifi_write: call udi_send_signal().\n"); + r = udi_send_signal_raw(priv, bufptr, remaining); + } else { + r = udi_send_signal_unpacked(priv, bufptr, remaining); + } + if (r < 0) { + /* Set the return value to the error code */ + unifi_error(priv, "unifi_write: (udi or sme)_send_signal() returns %d\n", r); + bytes_written = r; + break; + } + bufptr += r; + remaining -= r; + bytes_written += r; + } + + kfree(buf); + + func_exit_r(bytes_written); + + return bytes_written; +} /* unifi_write() */ + + +static const char* build_type_to_string(unsigned char build_type) +{ + switch (build_type) + { + case UNIFI_BUILD_NME: return "NME"; + case UNIFI_BUILD_WEXT: return "WEXT"; + case UNIFI_BUILD_AP: return "AP"; + } + return "unknown"; +} + + +/* + * ---------------------------------------------------------------- + * unifi_ioctl + * + * Ioctl handler for unifi driver. + * + * Arguments: + * inodep Pointer to inode structure. + * filp Pointer to file structure. + * cmd Ioctl cmd passed by user. + * arg Ioctl arg passed by user. + * + * Returns: + * 0 on success, -ve error code on error. + * ---------------------------------------------------------------- + */ +static long +unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + ul_client_t *pcli = (ul_client_t*)filp->private_data; + unifi_priv_t *priv; + struct net_device *dev; + int r = 0; + int int_param, i; + u8* buf; + CsrResult csrResult; +#if (defined CSR_SUPPORT_SME) + unifi_cfg_command_t cfg_cmd; +#if (defined CSR_SUPPORT_WEXT) + CsrWifiSmeCoexConfig coex_config; + unsigned char uchar_param; + unsigned char varbind[MAX_VARBIND_LENGTH]; + int vblen; +#endif +#endif + unifi_putest_command_t putest_cmd; + + priv = uf_find_instance(pcli->instance); + if (!priv) { + unifi_error(priv, "ioctl error: unknown instance=%d\n", pcli->instance); + r = -ENODEV; + goto out; + } + unifi_trace(priv, UDBG5, "unifi_ioctl: cmd=0x%X, arg=0x%lX\n", cmd, arg); + + switch (cmd) { + + case UNIFI_GET_UDI_ENABLE: + unifi_trace(priv, UDBG4, "UniFi Get UDI Enable\n"); + + down(&priv->udi_logging_mutex); + int_param = (priv->logging_client == NULL) ? 0 : 1; + up(&priv->udi_logging_mutex); + + if (put_user(int_param, (int*)arg)) + { + unifi_error(priv, "UNIFI_GET_UDI_ENABLE: Failed to copy to user\n"); + r = -EFAULT; + goto out; + } + break; + + case UNIFI_SET_UDI_ENABLE: + unifi_trace(priv, UDBG4, "UniFi Set UDI Enable\n"); + if (get_user(int_param, (int*)arg)) + { + unifi_error(priv, "UNIFI_SET_UDI_ENABLE: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + + down(&priv->udi_logging_mutex); + if (int_param) { + pcli->event_hook = udi_log_event; + unifi_set_udi_hook(priv->card, logging_handler); + /* Log all signals by default */ + for (i = 0; i < SIG_FILTER_SIZE; i++) { + pcli->signal_filter[i] = 0xFFFF; + } + priv->logging_client = pcli; + + } else { + priv->logging_client = NULL; + pcli->event_hook = NULL; + } + up(&priv->udi_logging_mutex); + + break; + + case UNIFI_SET_MIB: + unifi_trace(priv, UDBG4, "UniFi Set MIB\n"); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + /* Read first 2 bytes and check length */ + if (copy_from_user((void*)varbind, (void*)arg, 2)) { + unifi_error(priv, + "UNIFI_SET_MIB: Failed to copy in varbind header\n"); + r = -EFAULT; + goto out; + } + vblen = varbind[1]; + if ((vblen + 2) > MAX_VARBIND_LENGTH) { + unifi_error(priv, + "UNIFI_SET_MIB: Varbind too long (%d, limit %d)\n", + (vblen+2), MAX_VARBIND_LENGTH); + r = -EINVAL; + goto out; + } + /* Read rest of varbind */ + if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { + unifi_error(priv, "UNIFI_SET_MIB: Failed to copy in varbind\n"); + r = -EFAULT; + goto out; + } + + /* send to SME */ + vblen += 2; + r = sme_mgt_mib_set(priv, varbind, vblen); + if (r) { + goto out; + } +#else + unifi_notice(priv, "UNIFI_SET_MIB: Unsupported.\n"); +#endif /* CSR_SUPPORT_WEXT */ + break; + + case UNIFI_GET_MIB: + unifi_trace(priv, UDBG4, "UniFi Get MIB\n"); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + /* Read first 2 bytes and check length */ + if (copy_from_user((void*)varbind, (void*)arg, 2)) { + unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind header\n"); + r = -EFAULT; + goto out; + } + vblen = varbind[1]; + if ((vblen+2) > MAX_VARBIND_LENGTH) { + unifi_error(priv, "UNIFI_GET_MIB: Varbind too long (%d, limit %d)\n", + (vblen+2), MAX_VARBIND_LENGTH); + r = -EINVAL; + goto out; + } + /* Read rest of varbind */ + if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { + unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind\n"); + r = -EFAULT; + goto out; + } + + vblen += 2; + r = sme_mgt_mib_get(priv, varbind, &vblen); + if (r) { + goto out; + } + /* copy out varbind */ + if (vblen > MAX_VARBIND_LENGTH) { + unifi_error(priv, + "UNIFI_GET_MIB: Varbind result too long (%d, limit %d)\n", + vblen, MAX_VARBIND_LENGTH); + r = -EINVAL; + goto out; + } + if (copy_to_user((void*)arg, varbind, vblen)) { + r = -EFAULT; + goto out; + } +#else + unifi_notice(priv, "UNIFI_GET_MIB: Unsupported.\n"); +#endif /* CSR_SUPPORT_WEXT */ + break; + + case UNIFI_CFG: +#if (defined CSR_SUPPORT_SME) + if (get_user(cfg_cmd, (unifi_cfg_command_t*)arg)) + { + unifi_error(priv, "UNIFI_CFG: Failed to get the command\n"); + r = -EFAULT; + goto out; + } + + unifi_trace(priv, UDBG1, "UNIFI_CFG: Command is %d (t=%u) sz=%d\n", + cfg_cmd, jiffies_to_msecs(jiffies), sizeof(unifi_cfg_command_t)); + switch (cfg_cmd) { + case UNIFI_CFG_POWER: + r = unifi_cfg_power(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_POWERSAVE: + r = unifi_cfg_power_save(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_POWERSUPPLY: + r = unifi_cfg_power_supply(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_FILTER: + r = unifi_cfg_packet_filters(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_GET: + r = unifi_cfg_get_info(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_WMM_QOSINFO: + r = unifi_cfg_wmm_qos_info(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_WMM_ADDTS: + r = unifi_cfg_wmm_addts(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_WMM_DELTS: + r = unifi_cfg_wmm_delts(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_STRICT_DRAFT_N: + r = unifi_cfg_strict_draft_n(priv, (unsigned char*)arg); + break; + case UNIFI_CFG_ENABLE_OKC: + r = unifi_cfg_enable_okc(priv, (unsigned char*)arg); + break; +#ifdef CSR_SUPPORT_SME + case UNIFI_CFG_CORE_DUMP: + CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,CSR_WIFI_SME_CONTROL_INDICATION_ERROR); + unifi_trace(priv, UDBG2, "UNIFI_CFG_CORE_DUMP: sent wifi off indication\n"); + break; +#endif +#ifdef CSR_SUPPORT_WEXT_AP + case UNIFI_CFG_SET_AP_CONFIG: + r= unifi_cfg_set_ap_config(priv,(unsigned char*)arg); + break; +#endif + default: + unifi_error(priv, "UNIFI_CFG: Unknown Command (%d)\n", cfg_cmd); + r = -EINVAL; + goto out; + } +#endif + + break; + + case UNIFI_PUTEST: + if (get_user(putest_cmd, (unifi_putest_command_t*)arg)) + { + unifi_error(priv, "UNIFI_PUTEST: Failed to get the command\n"); + r = -EFAULT; + goto out; + } + + unifi_trace(priv, UDBG1, "UNIFI_PUTEST: Command is %s\n", + trace_putest_cmdid(putest_cmd)); + switch (putest_cmd) { + case UNIFI_PUTEST_START: + r = unifi_putest_start(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_STOP: + r = unifi_putest_stop(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_SET_SDIO_CLOCK: + r = unifi_putest_set_sdio_clock(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_CMD52_READ: + r = unifi_putest_cmd52_read(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_CMD52_BLOCK_READ: + r = unifi_putest_cmd52_block_read(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_CMD52_WRITE: + r = unifi_putest_cmd52_write(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_DL_FW: + r = unifi_putest_dl_fw(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_DL_FW_BUFF: + r = unifi_putest_dl_fw_buff(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_COREDUMP_PREPARE: + r = unifi_putest_coredump_prepare(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_GP_READ16: + r = unifi_putest_gp_read16(priv, (unsigned char*)arg); + break; + case UNIFI_PUTEST_GP_WRITE16: + r = unifi_putest_gp_write16(priv, (unsigned char*)arg); + break; + default: + unifi_error(priv, "UNIFI_PUTEST: Unknown Command (%d)\n", putest_cmd); + r = -EINVAL; + goto out; + } + + break; + case UNIFI_BUILD_TYPE: + unifi_trace(priv, UDBG2, "UNIFI_BUILD_TYPE userspace=%s\n", build_type_to_string(*(unsigned char*)arg)); +#ifndef CSR_SUPPORT_WEXT_AP + if (UNIFI_BUILD_AP == *(unsigned char*)arg) + { + unifi_error(priv, "Userspace has AP support, which is incompatible\n"); + } +#endif + +#ifndef CSR_SUPPORT_WEXT + if (UNIFI_BUILD_WEXT == *(unsigned char*)arg) + { + unifi_error(priv, "Userspace has WEXT support, which is incompatible\n"); + } +#endif + break; + case UNIFI_INIT_HW: + unifi_trace(priv, UDBG2, "UNIFI_INIT_HW.\n"); + priv->init_progress = UNIFI_INIT_NONE; + +#if defined(CSR_SUPPORT_WEXT) || defined (CSR_NATIVE_LINUX) + /* At this point we are ready to start the SME. */ + r = sme_mgt_wifi_on(priv); + if (r) { + goto out; + } +#endif + + break; + + case UNIFI_INIT_NETDEV: + { + /* get the proper interfaceTagId */ + CsrUint16 interfaceTag=0; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + dev = priv->netdev[interfaceTag]; + unifi_trace(priv, UDBG2, "UNIFI_INIT_NETDEV.\n"); + + if (copy_from_user((void*)dev->dev_addr, (void*)arg, 6)) { + r = -EFAULT; + goto out; + } + + /* Attach the network device to the stack */ + if (!interfacePriv->netdev_registered) + { + r = uf_register_netdev(priv,interfaceTag); + if (r) { + unifi_error(priv, "Failed to register the network device.\n"); + goto out; + } + } + + /* Apply scheduled interrupt mode, if requested by module param */ + if (run_bh_once != -1) { + unifi_set_interrupt_mode(priv->card, (CsrUint32)run_bh_once); + } + + priv->init_progress = UNIFI_INIT_COMPLETED; + + /* Firmware initialisation is complete, so let the SDIO bus + * clock be raised when convienent to the core. + */ + unifi_request_max_sdio_clock(priv->card); + +#ifdef CSR_SUPPORT_WEXT + /* Notify the Android wpa_supplicant that we are ready */ + wext_send_started_event(priv); +#endif + + unifi_info(priv, "UniFi ready\n"); + +#ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */ + { + struct net_device *dev = priv->netdev[interfaceTag]; +#ifdef CSR_SUPPORT_WEXT + interfacePriv->wait_netdev_change = TRUE; +#endif + netif_carrier_on(dev); + } +#endif + } + break; + case UNIFI_GET_INIT_STATUS: + unifi_trace(priv, UDBG2, "UNIFI_GET_INIT_STATUS.\n"); + if (put_user(priv->init_progress, (int*)arg)) + { + printk(KERN_ERR "UNIFI_GET_INIT_STATUS: Failed to copy to user\n"); + r = -EFAULT; + goto out; + } + break; + + case UNIFI_KICK: + unifi_trace(priv, UDBG4, "Kick UniFi\n"); + unifi_sdio_interrupt_handler(priv->card); + break; + + case UNIFI_SET_DEBUG: + unifi_debug = arg; + unifi_trace(priv, UDBG4, "unifi_debug set to %d\n", unifi_debug); + break; + + case UNIFI_SET_TRACE: + /* no longer supported */ + r = -EINVAL; + break; + + + case UNIFI_SET_UDI_LOG_MASK: + { + unifiio_filter_t udi_filter; + uint16_t *sig_ids_addr; +#define UF_MAX_SIG_IDS 128 /* Impose a sensible limit */ + + if (copy_from_user((void*)(&udi_filter), (void*)arg, sizeof(udi_filter))) { + r = -EFAULT; + goto out; + } + if ((udi_filter.action < UfSigFil_AllOn) || + (udi_filter.action > UfSigFil_SelectOff)) + { + printk(KERN_WARNING + "UNIFI_SET_UDI_LOG_MASK: Bad action value: %d\n", + udi_filter.action); + r = -EINVAL; + goto out; + } + /* No signal list for "All" actions */ + if ((udi_filter.action == UfSigFil_AllOn) || + (udi_filter.action == UfSigFil_AllOff)) + { + udi_filter.num_sig_ids = 0; + } + + if (udi_filter.num_sig_ids > UF_MAX_SIG_IDS) { + printk(KERN_WARNING + "UNIFI_SET_UDI_LOG_MASK: too many signal ids (%d, max %d)\n", + udi_filter.num_sig_ids, UF_MAX_SIG_IDS); + r = -EINVAL; + goto out; + } + + /* Copy in signal id list if given */ + if (udi_filter.num_sig_ids > 0) { + /* Preserve userspace address of sig_ids array */ + sig_ids_addr = udi_filter.sig_ids; + /* Allocate kernel memory for sig_ids and copy to it */ + udi_filter.sig_ids = + kmalloc(udi_filter.num_sig_ids * sizeof(uint16_t), GFP_KERNEL); + if (!udi_filter.sig_ids) { + r = -ENOMEM; + goto out; + } + if (copy_from_user((void*)udi_filter.sig_ids, + (void*)sig_ids_addr, + udi_filter.num_sig_ids * sizeof(uint16_t))) + { + kfree(udi_filter.sig_ids); + r = -EFAULT; + goto out; + } + } + + udi_set_log_filter(pcli, &udi_filter); + + if (udi_filter.num_sig_ids > 0) { + kfree(udi_filter.sig_ids); + } + } + break; + + case UNIFI_SET_AMP_ENABLE: + unifi_trace(priv, UDBG4, "UniFi Set AMP Enable\n"); + if (get_user(int_param, (int*)arg)) + { + unifi_error(priv, "UNIFI_SET_AMP_ENABLE: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + + if (int_param) { + priv->amp_client = pcli; + } else { + priv->amp_client = NULL; + } + + int_param = 0; + buf = (u8*)&int_param; + buf[0] = UNIFI_SOFT_COMMAND_Q_LENGTH - 1; + buf[1] = UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1; + if (copy_to_user((void*)arg, &int_param, sizeof(int))) { + r = -EFAULT; + goto out; + } + break; + + case UNIFI_SET_UDI_SNAP_MASK: + { + unifiio_snap_filter_t snap_filter; + + if (copy_from_user((void*)(&snap_filter), (void*)arg, sizeof(snap_filter))) { + r = -EFAULT; + goto out; + } + + if (pcli->snap_filter.count) { + pcli->snap_filter.count = 0; + CsrPmemFree(pcli->snap_filter.protocols); + } + + if (snap_filter.count == 0) { + break; + } + + pcli->snap_filter.protocols = CsrPmemAlloc(snap_filter.count * sizeof(CsrUint16)); + if (!pcli->snap_filter.protocols) { + r = -ENOMEM; + goto out; + } + if (copy_from_user((void*)pcli->snap_filter.protocols, + (void*)snap_filter.protocols, + snap_filter.count * sizeof(CsrUint16))) + { + CsrPmemFree(pcli->snap_filter.protocols); + r = -EFAULT; + goto out; + } + + pcli->snap_filter.count = snap_filter.count; + + } + break; + + case UNIFI_SME_PRESENT: + { + u8 ind; + unifi_trace(priv, UDBG4, "UniFi SME Present IOCTL.\n"); + if (copy_from_user((void*)(&int_param), (void*)arg, sizeof(int))) + { + printk(KERN_ERR "UNIFI_SME_PRESENT: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + + priv->sme_is_present = int_param; + if (priv->sme_is_present == 1) { + ind = CONFIG_SME_PRESENT; + } else { + ind = CONFIG_SME_NOT_PRESENT; + } + /* Send an indication to the helper app. */ + ul_log_config_ind(priv, &ind, sizeof(u8)); + } + break; + + case UNIFI_CFG_PERIOD_TRAFFIC: + { +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + CsrWifiSmeCoexConfig coexConfig; +#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ + unifi_trace(priv, UDBG4, "UniFi Configure Periodic Traffic.\n"); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { + unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + + if (uchar_param == 0) { + r = sme_mgt_coex_config_get(priv, &coexConfig); + if (r) { + unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Get unifi_CoexInfoValue failed.\n"); + goto out; + } + if (copy_to_user((void*)(arg + 1), + (void*)&coexConfig, + sizeof(CsrWifiSmeCoexConfig))) { + r = -EFAULT; + goto out; + } + goto out; + } + + if (copy_from_user((void*)(&coex_config), (void*)(arg + 1), sizeof(CsrWifiSmeCoexConfig))) + { + unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + + coexConfig = coex_config; + r = sme_mgt_coex_config_set(priv, &coexConfig); + if (r) { + unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Set unifi_CoexInfoValue failed.\n"); + goto out; + } + +#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ + break; + } + case UNIFI_CFG_UAPSD_TRAFFIC: + unifi_trace(priv, UDBG4, "UniFi Configure U-APSD Mask.\n"); +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { + unifi_error(priv, "UNIFI_CFG_UAPSD_TRAFFIC: Failed to copy from user\n"); + r = -EFAULT; + goto out; + } + unifi_trace(priv, UDBG4, "New U-APSD Mask: 0x%x\n", uchar_param); +#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ + break; + +#ifndef UNIFI_DISABLE_COREDUMP + case UNIFI_COREDUMP_GET_REG: + unifi_trace(priv, UDBG4, "Mini-coredump data request\n"); + { + unifiio_coredump_req_t dump_req; /* Public OS layer structure */ + unifi_coredump_req_t priv_req; /* Private HIP structure */ + + if (copy_from_user((void*)(&dump_req), (void*)arg, sizeof(dump_req))) { + r = -EFAULT; + goto out; + } + memset(&priv_req, 0, sizeof(priv_req)); + priv_req.index = dump_req.index; + priv_req.offset = dump_req.offset; + + /* Convert OS-layer's XAP memory space ID to HIP's ID in case they differ */ + switch (dump_req.space) { + case UNIFIIO_COREDUMP_MAC_REG: priv_req.space = UNIFI_COREDUMP_MAC_REG; break; + case UNIFIIO_COREDUMP_PHY_REG: priv_req.space = UNIFI_COREDUMP_PHY_REG; break; + case UNIFIIO_COREDUMP_SH_DMEM: priv_req.space = UNIFI_COREDUMP_SH_DMEM; break; + case UNIFIIO_COREDUMP_MAC_DMEM: priv_req.space = UNIFI_COREDUMP_MAC_DMEM; break; + case UNIFIIO_COREDUMP_PHY_DMEM: priv_req.space = UNIFI_COREDUMP_PHY_DMEM; break; + case UNIFIIO_COREDUMP_TRIGGER_MAGIC: priv_req.space = UNIFI_COREDUMP_TRIGGER_MAGIC; break; + default: + r = -EINVAL; + goto out; + } + + if (priv_req.space == UNIFI_COREDUMP_TRIGGER_MAGIC) { + /* Force a coredump grab now */ + unifi_trace(priv, UDBG2, "UNIFI_COREDUMP_GET_REG: Force capture\n"); + csrResult = unifi_coredump_capture(priv->card, &priv_req); + r = CsrHipResultToStatus(csrResult); + unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: status %d\n", r); + } else { + /* Retrieve the appropriate register entry */ + csrResult = unifi_coredump_get_value(priv->card, &priv_req); + r = CsrHipResultToStatus(csrResult); + if (r) { + unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: Status %d\n", r); + goto out; + } + /* Update the OS-layer structure with values returned in the private */ + dump_req.value = priv_req.value; + dump_req.timestamp = priv_req.timestamp; + dump_req.requestor = priv_req.requestor; + dump_req.serial = priv_req.serial; + dump_req.chip_ver = priv_req.chip_ver; + dump_req.fw_ver = priv_req.fw_ver; + dump_req.drv_build = 0; + + unifi_trace(priv, UDBG6, + "Dump: %d (seq %d): V:0x%04x (%d) @0x%02x:%04x = 0x%04x\n", + dump_req.index, dump_req.serial, + dump_req.chip_ver, dump_req.drv_build, + dump_req.space, dump_req.offset, dump_req.value); + } + if (copy_to_user((void*)arg, (void*)&dump_req, sizeof(dump_req))) { + r = -EFAULT; + goto out; + } + } + break; +#endif + default: + r = -EINVAL; + } + +out: + return (long)r; +} /* unifi_ioctl() */ + + + +static unsigned int +unifi_poll(struct file *filp, poll_table *wait) +{ + ul_client_t *pcli = (ul_client_t*)filp->private_data; + unsigned int mask = 0; + int ready; + + func_enter(); + + ready = !list_empty(&pcli->udi_log); + + poll_wait(filp, &pcli->udi_wq, wait); + + if (ready) { + mask |= POLLIN | POLLRDNORM; /* readable */ + } + + func_exit(); + + return mask; +} /* unifi_poll() */ + + + +/* + * --------------------------------------------------------------------------- + * udi_set_log_filter + * + * Configure the bit mask that determines which signal primitives are + * passed to the logging process. + * + * Arguments: + * pcli Pointer to the client to configure. + * udi_filter Pointer to a unifiio_filter_t containing instructions. + * + * Returns: + * None. + * + * Notes: + * SigGetFilterPos() returns a 32-bit value that contains an index and a + * mask for accessing a signal_filter array. The top 16 bits specify an + * index into a signal_filter, the bottom 16 bits specify a mask to + * apply. + * --------------------------------------------------------------------------- + */ +static void +udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter) +{ + CsrUint32 filter_pos; + int i; + + if (udi_filter->action == UfSigFil_AllOn) + { + for (i = 0; i < SIG_FILTER_SIZE; i++) { + pcli->signal_filter[i] = 0xFFFF; + } + } + else if (udi_filter->action == UfSigFil_AllOff) + { + for (i = 0; i < SIG_FILTER_SIZE; i++) { + pcli->signal_filter[i] = 0; + } + } + else if (udi_filter->action == UfSigFil_SelectOn) + { + for (i = 0; i < udi_filter->num_sig_ids; i++) { + filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); + if (filter_pos == 0xFFFFFFFF) + { + printk(KERN_WARNING + "Unrecognised signal id (0x%X) specifed in logging filter\n", + udi_filter->sig_ids[i]); + } else { + pcli->signal_filter[filter_pos >> 16] |= (filter_pos & 0xFFFF); + } + } + } + else if (udi_filter->action == UfSigFil_SelectOff) + { + for (i = 0; i < udi_filter->num_sig_ids; i++) { + filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); + if (filter_pos == 0xFFFFFFFF) + { + printk(KERN_WARNING + "Unrecognised signal id (0x%X) specifed in logging filter\n", + udi_filter->sig_ids[i]); + } else { + pcli->signal_filter[filter_pos >> 16] &= ~(filter_pos & 0xFFFF); + } + } + } + +} /* udi_set_log_filter() */ + + +/* + * --------------------------------------------------------------------------- + * udi_log_event + * + * Callback function to be registered as the UDI hook callback. + * Copies the signal content into a new udi_log_t struct and adds + * it to the read queue for this UDI client. + * + * Arguments: + * pcli A pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointers to any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +udi_log_event(ul_client_t *pcli, + const u8 *signal, int signal_len, + const bulk_data_param_t *bulkdata, + int dir) +{ + udi_log_t *logptr; + u8 *p; + int i; + int total_len; + udi_msg_t *msgptr; + CsrUint32 filter_pos; +#ifdef OMNICLI_LINUX_EXTRA_LOG + static volatile unsigned int printk_cpu = UINT_MAX; + unsigned long long t; + unsigned long nanosec_rem; + unsigned long n_1000; +#endif + + func_enter(); + + /* Just a sanity check */ + if ((signal == NULL) || (signal_len <= 0)) { + return; + } + +#ifdef CSR_NATIVE_LINUX + uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir); +#endif + + /* + * Apply the logging filter - only report signals that have their + * bit set in the filter mask. + */ + filter_pos = SigGetFilterPos(GET_SIGNAL_ID(signal)); + + if ((filter_pos != 0xFFFFFFFF) && + ((pcli->signal_filter[filter_pos >> 16] & (filter_pos & 0xFFFF)) == 0)) + { + /* Signal is not wanted by client */ + return; + } + + + /* Calculate the buffer we need to store signal plus bulk data */ + total_len = signal_len; + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + total_len += bulkdata->d[i].data_length; + } + + /* Allocate log structure plus actual signal. */ + logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL); + + if (logptr == NULL) { + printk(KERN_ERR + "Failed to allocate %lu bytes for a UDI log record\n", + (long unsigned int)(sizeof(udi_log_t) + total_len)); + return; + } + + /* Fill in udi_log struct */ + INIT_LIST_HEAD(&logptr->q); + msgptr = &logptr->msg; + msgptr->length = sizeof(udi_msg_t) + total_len; +#ifdef OMNICLI_LINUX_EXTRA_LOG + t = cpu_clock(printk_cpu); + nanosec_rem = do_div(t, 1000000000); + n_1000 = nanosec_rem/1000; + msgptr->timestamp = (t <<10 ) | ((unsigned long)(n_1000 >> 10) & 0x3ff); +#else + msgptr->timestamp = jiffies_to_msecs(jiffies); +#endif + msgptr->direction = dir; + msgptr->signal_length = signal_len; + + /* Copy signal and bulk data to the log */ + p = (u8 *)(msgptr + 1); + memcpy(p, signal, signal_len); + p += signal_len; + + /* Append any bulk data */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + int len = bulkdata->d[i].data_length; + + /* + * Len here might not be the same as the length in the bulk data slot. + * The slot length will always be even, but len could be odd. + */ + if (len > 0) { + if (bulkdata->d[i].os_data_ptr) { + memcpy(p, bulkdata->d[i].os_data_ptr, len); + } else { + memset(p, 0, len); + } + p += len; + } + } + + /* Add to tail of log queue */ + if (down_interruptible(&pcli->udi_sem)) { + printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n"); + kfree(logptr); + func_exit(); + return; + } + list_add_tail(&logptr->q, &pcli->udi_log); + up(&pcli->udi_sem); + + /* Wake any waiting user process */ + wake_up_interruptible(&pcli->udi_wq); + + func_exit(); +} /* udi_log_event() */ + +#ifdef CSR_SME_USERSPACE +int +uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length) +{ + udi_log_t *logptr; + udi_msg_t *msgptr; + u8 *p; + + func_enter(); + + /* Just a sanity check */ + if ((buffer == NULL) || (length <= 0)) { + return -EINVAL; + } + + /* Allocate log structure plus actual signal. */ + logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC); + if (logptr == NULL) { + unifi_error(priv, "Failed to allocate %d bytes for an SME message\n", + sizeof(udi_log_t) + length); + CsrPmemFree(buffer); + return -ENOMEM; + } + + /* Fill in udi_log struct */ + INIT_LIST_HEAD(&logptr->q); + msgptr = &logptr->msg; + msgptr->length = sizeof(udi_msg_t) + length; + msgptr->signal_length = length; + + /* Copy signal and bulk data to the log */ + p = (u8 *)(msgptr + 1); + memcpy(p, buffer, length); + + /* Add to tail of log queue */ + down(&udi_mutex); + if (priv->sme_cli == NULL) { + kfree(logptr); + CsrPmemFree(buffer); + up(&udi_mutex); + unifi_info(priv, "Message for the SME dropped, SME has gone away\n"); + return 0; + } + + down(&priv->sme_cli->udi_sem); + list_add_tail(&logptr->q, &priv->sme_cli->udi_log); + up(&priv->sme_cli->udi_sem); + + /* Wake any waiting user process */ + wake_up_interruptible(&priv->sme_cli->udi_wq); + up(&udi_mutex); + + /* It is our responsibility to free the buffer allocated in build_packed_*() */ + CsrPmemFree(buffer); + + func_exit(); + + return 0; + +} /* uf_sme_queue_message() */ +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _priv, _fmt, _args) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args) +#else +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _fmt, _args) +#endif + +/* + **************************************************************************** + * + * Driver instantiation + * + **************************************************************************** + */ +static struct file_operations unifi_fops = { + .owner = THIS_MODULE, + .open = unifi_open, + .release = unifi_release, + .read = unifi_read, + .write = unifi_write, + .unlocked_ioctl = unifi_ioctl, + .poll = unifi_poll, +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _priv, _fmt, _args) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args) +#else +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _fmt, _args) +#endif + +static dev_t unifi_first_devno; +static struct class *unifi_class; + + +int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) +{ + dev_t devno; + int r; + + cdev_init(&priv->unifi_cdev, &unifi_fops); + + /* cdev_init() should set the cdev owner, but it does not */ + priv->unifi_cdev.owner = THIS_MODULE; + + devno = MKDEV(MAJOR(unifi_first_devno), + MINOR(unifi_first_devno) + (bus_id * 2)); + r = cdev_add(&priv->unifi_cdev, devno, 1); + if (r) { + return r; + } + +#ifdef SDIO_EXPORTS_STRUCT_DEVICE + if (!UF_DEVICE_CREATE(unifi_class, priv->unifi_device, + devno, priv, "unifi%d", bus_id)) { +#else + priv->unifi_device = UF_DEVICE_CREATE(unifi_class, NULL, + devno, priv, "unifi%d", bus_id); + if (priv->unifi_device == NULL) { +#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ + + cdev_del(&priv->unifi_cdev); + return -EINVAL; + } + + cdev_init(&priv->unifiudi_cdev, &unifi_fops); + + /* cdev_init() should set the cdev owner, but it does not */ + priv->unifiudi_cdev.owner = THIS_MODULE; + + devno = MKDEV(MAJOR(unifi_first_devno), + MINOR(unifi_first_devno) + (bus_id * MAX_UNIFI_DEVS) + 1); + r = cdev_add(&priv->unifiudi_cdev, devno, 1); + if (r) { + device_destroy(unifi_class, priv->unifi_cdev.dev); + cdev_del(&priv->unifi_cdev); + return r; + } + + if (!UF_DEVICE_CREATE(unifi_class, +#ifdef SDIO_EXPORTS_STRUCT_DEVICE + priv->unifi_device, +#else + NULL, +#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ + devno, priv, "unifiudi%d", bus_id)) { + device_destroy(unifi_class, priv->unifi_cdev.dev); + cdev_del(&priv->unifiudi_cdev); + cdev_del(&priv->unifi_cdev); + return -EINVAL; + } + + return 0; +} + + +void uf_destroy_device_nodes(unifi_priv_t *priv) +{ + device_destroy(unifi_class, priv->unifiudi_cdev.dev); + device_destroy(unifi_class, priv->unifi_cdev.dev); + cdev_del(&priv->unifiudi_cdev); + cdev_del(&priv->unifi_cdev); +} + + + +/* + * ---------------------------------------------------------------- + * uf_create_debug_device + * + * Allocates device numbers for unifi character device nodes + * and creates a unifi class in sysfs + * + * Arguments: + * fops Pointer to the char device operations structure. + * + * Returns: + * 0 on success, -ve error code on error. + * ---------------------------------------------------------------- + */ +static int +uf_create_debug_device(struct file_operations *fops) +{ + int ret; + + /* Allocate two device numbers for each device. */ + ret = alloc_chrdev_region(&unifi_first_devno, 0, MAX_UNIFI_DEVS*2, UNIFI_NAME); + if (ret) { + unifi_error(NULL, "Failed to add alloc dev numbers: %d\n", ret); + return ret; + } + + /* Create a UniFi class */ + unifi_class = class_create(THIS_MODULE, UNIFI_NAME); + if (IS_ERR(unifi_class)) { + unifi_error(NULL, "Failed to create UniFi class\n"); + + /* Release device numbers */ + unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); + unifi_first_devno = 0; + return -EINVAL; + } + + return 0; +} /* uf_create_debug_device() */ + + +/* + * ---------------------------------------------------------------- + * uf_remove_debug_device + * + * Destroys the unifi class and releases the allocated + * device numbers for unifi character device nodes. + * + * Arguments: + * + * Returns: + * ---------------------------------------------------------------- + */ +static void +uf_remove_debug_device(void) +{ + /* Destroy the UniFi class */ + class_destroy(unifi_class); + + /* Release device numbers */ + unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); + unifi_first_devno = 0; + +} /* uf_remove_debug_device() */ + + +/* + * --------------------------------------------------------------------------- + * + * Module loading. + * + * --------------------------------------------------------------------------- + */ +int __init +unifi_load(void) +{ + int r; + + printk("UniFi SDIO Driver: %s %s %s\n", + CSR_WIFI_VERSION, + __DATE__, __TIME__); + +#ifdef CSR_SME_USERSPACE +#ifdef CSR_SUPPORT_WEXT + printk("CSR SME with WEXT support\n"); +#else + printk("CSR SME no WEXT support\n"); +#endif /* CSR_SUPPORT_WEXT */ +#endif /* CSR_SME_USERSPACE */ + +#ifdef CSR_NATIVE_LINUX +#ifdef CSR_SUPPORT_WEXT +#error WEXT unsupported in the native driver +#endif + printk("CSR native no WEXT support\n"); +#endif + + printk("Kernel %d.%d.%d\n", + ((LINUX_VERSION_CODE) >> 16) & 0xff, + ((LINUX_VERSION_CODE) >> 8) & 0xff, + (LINUX_VERSION_CODE) & 0xff); + /* + * Instantiate the /dev/unifi* device nodes. + * We must do this before registering with the SDIO driver because it + * will immediately call the "insert" callback if the card is + * already present. + */ + r = uf_create_debug_device(&unifi_fops); + if (r) { + return r; + } + + /* Now register with the SDIO driver */ + r = uf_sdio_load(); + if (r) { + uf_remove_debug_device(); + return r; + } + + if (sdio_block_size > -1) { + unifi_info(NULL, "sdio_block_size %d\n", sdio_block_size); + } + + if (sdio_byte_mode) { + unifi_info(NULL, "sdio_byte_mode\n"); + } + + if (disable_power_control) { + unifi_info(NULL, "disable_power_control\n"); + } + + if (disable_hw_reset) { + unifi_info(NULL, "disable_hw_reset\n"); + } + + if (enable_wol) { + unifi_info(NULL, "enable_wol %d\n", enable_wol); + } + + if (run_bh_once != -1) { + unifi_info(NULL, "run_bh_once %d\n", run_bh_once); + } + + return 0; +} /* unifi_load() */ + + +void __exit +unifi_unload(void) +{ + /* The SDIO remove hook will call unifi_disconnect(). */ + uf_sdio_unload(); + + uf_remove_debug_device(); + +} /* unifi_unload() */ + +module_init(unifi_load); +module_exit(unifi_unload); + +MODULE_DESCRIPTION("UniFi Device driver"); +MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c new file mode 100644 index 000000000000..4ac3c89baa5d --- /dev/null +++ b/drivers/staging/csr/firmware.c @@ -0,0 +1,398 @@ +/* + * --------------------------------------------------------------------------- + * FILE: firmware.c + * + * PURPOSE: + * Implements the f/w related HIP core lib API. + * It is part of the porting exercise in Linux. + * + * Also, it contains example code for reading the loader and f/w files + * from the userspace and starting the SME in Linux. + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifi_udi.h" +#include "unifiio.h" +#include "unifi_priv.h" + +/* + * --------------------------------------------------------------------------- + * + * F/W download. Part of the HIP core API + * + * --------------------------------------------------------------------------- + */ + + +/* + * --------------------------------------------------------------------------- + * unifi_fw_read_start + * + * Returns a structure to be passed in unifi_fw_read(). + * This structure is an OS specific description of the f/w file. + * In the linux implementation it is a buffer with the f/w and its' length. + * The HIP driver calls this functions to request for the loader or + * the firmware file. + * The structure pointer can be freed when unifi_fw_read_stop() is called. + * + * Arguments: + * ospriv Pointer to driver context. + * is_fw Type of firmware to retrieve + * info Versions information. Can be used to determine + * the appropriate f/w file to load. + * + * Returns: + * O on success, non-zero otherwise. + * + * --------------------------------------------------------------------------- + */ +void* +unifi_fw_read_start(void *ospriv, CsrInt8 is_fw, const card_info_t *info) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + CSR_UNUSED(info); + + func_enter(); + + if (is_fw == UNIFI_FW_STA) { + /* F/w may have been released after a previous successful download. */ + if (priv->fw_sta.dl_data == NULL) { + unifi_trace(priv, UDBG2, "Attempt reload of sta f/w\n"); + uf_request_firmware_files(priv, UNIFI_FW_STA); + } + /* Set up callback struct for readfunc() */ + if (priv->fw_sta.dl_data != NULL) { + func_exit(); + return &priv->fw_sta; + } + + } else { + unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw); + } + + func_exit(); + return NULL; +} /* unifi_fw_read_start() */ + + + +/* + * --------------------------------------------------------------------------- + * unifi_fw_read_stop + * + * Called when the HIP driver has finished using the loader or + * the firmware file. + * The firmware buffer may be released now. + * + * Arguments: + * ospriv Pointer to driver context. + * dlpriv The pointer returned by unifi_fw_read_start() + * + * --------------------------------------------------------------------------- + */ +void +unifi_fw_read_stop(void *ospriv, void *dlpriv) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + struct dlpriv *dl_struct = (struct dlpriv *)dlpriv; + func_enter(); + + if (dl_struct != NULL) { + if (dl_struct->dl_data != NULL) { + unifi_trace(priv, UDBG2, "Release f/w buffer %p, %d bytes\n", + dl_struct->dl_data, dl_struct->dl_len); + } + uf_release_firmware(priv, dl_struct); + } + + func_exit(); +} /* unifi_fw_read_stop() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_fw_open_buffer + * + * Returns a handle for a buffer dynamically allocated by the driver, + * e.g. into which a firmware file may have been converted from another format + * which is the case with some production test images. + * + * The handle may then be used by unifi_fw_read() to access the contents of + * the buffer. + * + * Arguments: + * ospriv Pointer to driver context. + * fwbuf Buffer containing firmware image + * len Length of buffer in bytes + * + * Returns + * Handle for buffer, or NULL on error + * --------------------------------------------------------------------------- + */ +void * +unifi_fw_open_buffer(void *ospriv, void *fwbuf, CsrUint32 len) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + func_enter(); + + if (fwbuf == NULL) { + func_exit(); + return NULL; + } + priv->fw_conv.dl_data = fwbuf; + priv->fw_conv.dl_len = len; + priv->fw_conv.fw_desc = NULL; /* No OS f/w resource is associated */ + + func_exit(); + return &priv->fw_conv; +} + +/* + * --------------------------------------------------------------------------- + * unifi_fw_close_buffer + * + * Releases any handle for a buffer dynamically allocated by the driver, + * e.g. into which a firmware file may have been converted from another format + * which is the case with some production test images. + * + * + * Arguments: + * ospriv Pointer to driver context. + * fwbuf Buffer containing firmware image + * + * Returns + * Handle for buffer, or NULL on error + * --------------------------------------------------------------------------- + */ +void unifi_fw_close_buffer(void *ospriv, void *fwbuf) +{ +} + +/* + * --------------------------------------------------------------------------- + * unifi_fw_read + * + * The HIP driver calls this function to ask for a part of the loader or + * the firmware file. + * + * Arguments: + * ospriv Pointer to driver context. + * arg The pointer returned by unifi_fw_read_start(). + * offset The offset in the file to return from. + * buf A buffer to store the requested data. + * len The size of the buf and the size of the requested data. + * + * Returns + * The number of bytes read from the firmware image, or -ve on error + * --------------------------------------------------------------------------- + */ +CsrInt32 +unifi_fw_read(void *ospriv, void *arg, CsrUint32 offset, void *buf, CsrUint32 len) +{ + const struct dlpriv *dlpriv = arg; + + if (offset >= dlpriv->dl_len) { + /* at end of file */ + return 0; + } + + if ((offset + len) > dlpriv->dl_len) { + /* attempt to read past end of file */ + return -1; + } + + memcpy(buf, dlpriv->dl_data+offset, len); + + return len; + +} /* unifi_fw_read() */ + + + + +#define UNIFIHELPER_INIT_MODE_SMEEMB 0 +#define UNIFIHELPER_INIT_MODE_SMEUSER 2 +#define UNIFIHELPER_INIT_MODE_NATIVE 1 + +/* + * --------------------------------------------------------------------------- + * uf_run_unifihelper + * + * Ask userspace to send us firmware for download by running + * '/usr/sbin/unififw'. + * The same script starts the SME userspace application. + * Derived from net_run_sbin_hotplug(). + * + * Arguments: + * priv Pointer to OS private struct. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int +uf_run_unifihelper(unifi_priv_t *priv) +{ +#ifdef CONFIG_HOTPLUG + +#ifdef ANDROID_BUILD + char *prog = "/system/bin/unififw"; +#else + char *prog = "/usr/sbin/unififw"; +#endif /* ANDROID_BUILD */ + + char *argv[6], *envp[4]; + char inst_str[8]; + char init_mode[8]; + int i, r; + +#if (defined CSR_SME_USERSPACE) && (!defined CSR_SUPPORT_WEXT) + unifi_trace(priv, UDBG1, "SME userspace build: run unifi_helper manually\n"); + return 0; +#endif + + unifi_trace(priv, UDBG1, "starting %s\n", prog); + + snprintf(inst_str, 8, "%d", priv->instance); +#if (defined CSR_SME_USERSPACE) + snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_SMEUSER); +#else + snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_NATIVE); +#endif /* CSR_SME_USERSPACE */ + + i = 0; + argv[i++] = prog; + argv[i++] = inst_str; + argv[i++] = init_mode; + argv[i++] = 0; + argv[i] = 0; + /* Don't add more args without making argv bigger */ + + /* minimal command environment */ + i = 0; + envp[i++] = "HOME=/"; + envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + envp[i] = 0; + /* Don't add more without making envp bigger */ + + unifi_trace(priv, UDBG2, "running %s %s %s\n", argv[0], argv[1], argv[2]); + + r = call_usermodehelper(argv[0], argv, envp, 0); + + return r; +#else + unifi_trace(priv, UDBG1, "Can't automatically download firmware because kernel does not have HOTPLUG\n"); + return -1; +#endif +} /* uf_run_unifihelper() */ + + + +/* + * --------------------------------------------------------------------------- + * uf_request_firmware_files + * + * Get the firmware files from userspace. + * + * Arguments: + * priv Pointer to OS private struct. + * is_fw type of firmware to load (UNIFI_FW_STA/LOADER) + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int uf_request_firmware_files(unifi_priv_t *priv, int is_fw) +{ + /* uses the default method to get the firmware */ + const struct firmware *fw_entry; + int postfix; +#define UNIFI_MAX_FW_PATH_LEN 32 + char fw_name[UNIFI_MAX_FW_PATH_LEN]; + int r; + +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + if (priv->mib_data.length) { + vfree(priv->mib_data.data); + priv->mib_data.data = NULL; + priv->mib_data.length = 0; + } +#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/ + + postfix = priv->instance; + + if (is_fw == UNIFI_FW_STA) { + /* Free kernel buffer and reload */ + uf_release_firmware(priv, &priv->fw_sta); + scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", + postfix, "sta.xbv"); + r = request_firmware(&fw_entry, fw_name, priv->unifi_device); + if (r == 0) { + priv->fw_sta.dl_data = fw_entry->data; + priv->fw_sta.dl_len = fw_entry->size; + priv->fw_sta.fw_desc = (void *)fw_entry; + } else { + unifi_trace(priv, UDBG2, "Firmware file not available\n"); + } + } + + return 0; + +} /* uf_request_firmware_files() */ + +/* + * --------------------------------------------------------------------------- + * uf_release_firmware_files + * + * Release all buffers used to store firmware files + * + * Arguments: + * priv Pointer to OS private struct. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int uf_release_firmware_files(unifi_priv_t *priv) +{ + uf_release_firmware(priv, &priv->fw_sta); + + return 0; +} + +/* + * --------------------------------------------------------------------------- + * uf_release_firmware + * + * Release specific buffer used to store firmware + * + * Arguments: + * priv Pointer to OS private struct. + * to_free Pointer to specific buffer to release + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free) +{ + if (to_free != NULL) { + if (to_free->fw_desc != NULL) { + release_firmware((const struct firmware *)to_free->fw_desc); + } + to_free->fw_desc = NULL; + to_free->dl_data = NULL; + to_free->dl_len = 0; + } + return 0; +} diff --git a/drivers/staging/csr/indications.c b/drivers/staging/csr/indications.c new file mode 100644 index 000000000000..834b5f3e3b5d --- /dev/null +++ b/drivers/staging/csr/indications.c @@ -0,0 +1,18 @@ +/* + * *************************************************************************** + * FILE: indications.c + * + * PURPOSE: + * Callbacks to process signals sent to us by the UniFi chip. + * + * This file is linux-specific. + * + * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" diff --git a/drivers/staging/csr/inet.c b/drivers/staging/csr/inet.c new file mode 100644 index 000000000000..b4acb54ecc62 --- /dev/null +++ b/drivers/staging/csr/inet.c @@ -0,0 +1,106 @@ +/* + * --------------------------------------------------------------------------- + * FILE: inet.c + * + * PURPOSE: + * Routines related to IP address changes. + * Optional part of the porting exercise. It uses system network + * handlers to obtain the UniFi IP address and pass it to the SME + * using the unifi_sys_ip_configured_ind(). + * + * Copyright (C) 2008-2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include +#include + +#include "unifi_priv.h" +#include "csr_wifi_hip_conversions.h" + +/* + * The inet notifier is global and not per-netdev. To avoid having a + * notifier registered when there are no unifi devices present, it's + * registered after the first unifi network device is registered, and + * unregistered when the last unifi network device is unregistered. + */ + +static atomic_t inet_notif_refs = ATOMIC_INIT(0); + +static int uf_inetaddr_event(struct notifier_block *notif, unsigned long event, void *ifa) +{ + struct net_device *ndev; + unifi_priv_t *priv; + struct in_ifaddr *if_addr; + netInterface_priv_t *InterfacePriv = (netInterface_priv_t *)NULL; + + if (!ifa || !((struct in_ifaddr *)ifa)->ifa_dev) { + unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ifa=%p\n", event, ifa); + return NOTIFY_DONE; + } + + ndev = ((struct in_ifaddr *)ifa)->ifa_dev->dev; + InterfacePriv = (netInterface_priv_t*) netdev_priv(ndev); + + /* As the notifier is global, the call may be for a non-UniFi netdev. + * Therefore check the netdev_priv to make sure it's a known UniFi one. + */ + if (uf_find_netdev_priv(InterfacePriv) == -1) { + unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ndev=%p, other netdev_priv=%p\n", + event, ndev, InterfacePriv); + return NOTIFY_DONE; + } + + if (!InterfacePriv->privPtr) { + unifi_error(NULL, "uf_inetaddr_event null priv (%lu) ndev=%p, InterfacePriv=%p\n", + event, ndev, InterfacePriv); + return NOTIFY_DONE; + } + + priv = InterfacePriv->privPtr; + if_addr = (struct in_ifaddr *)ifa; + + /* If this event is for a UniFi device, notify the SME that an IP + * address has been added or removed. */ + if (uf_find_priv(priv) != -1) { + switch (event) { + case NETDEV_UP: + unifi_info(priv, "IP address assigned for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); + priv->sta_ip_address = if_addr->ifa_address; +#ifdef CSR_SUPPORT_WEXT + sme_mgt_packet_filter_set(priv); +#endif + break; + case NETDEV_DOWN: + unifi_info(priv, "IP address removed for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); + priv->sta_ip_address = 0xFFFFFFFF; +#ifdef CSR_SUPPORT_WEXT + sme_mgt_packet_filter_set(priv); +#endif + break; + } + } + + return NOTIFY_DONE; +} + +static struct notifier_block uf_inetaddr_notifier = { + .notifier_call = uf_inetaddr_event, +}; + +void uf_register_inet_notifier(void) +{ + if (atomic_inc_return(&inet_notif_refs) == 1) { + register_inetaddr_notifier(&uf_inetaddr_notifier); + } +} + +void uf_unregister_inet_notifier(void) +{ + if (atomic_dec_return(&inet_notif_refs) == 0) { + unregister_inetaddr_notifier(&uf_inetaddr_notifier); + } +} diff --git a/drivers/staging/csr/init_hw.c b/drivers/staging/csr/init_hw.c new file mode 100644 index 000000000000..3b8a4babf9a6 --- /dev/null +++ b/drivers/staging/csr/init_hw.c @@ -0,0 +1,108 @@ +/* + * --------------------------------------------------------------------------- + * FILE: init_hw.c + * + * PURPOSE: + * Use the HIP core lib to initialise the UniFi chip. + * It is part of the porting exercise in Linux. + * + * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + +#define MAX_INIT_ATTEMPTS 4 + +extern int led_mask; + + +/* + * --------------------------------------------------------------------------- + * uf_init_hw + * + * Resets hardware, downloads and initialises f/w. + * This function demonstrates how to use the HIP core lib API + * to implement the SME unifi_sys_wifi_on_req() part of the SYS API. + * + * In a simple implementation, all this function needs to do is call + * unifi_init_card() and then unifi_card_info(). + * In the Linux implementation, it will retry to initialise UniFi or + * try to debug the reasons if unifi_init_card() returns an error. + * + * Arguments: + * ospriv Pointer to OS driver structure for the device. + * + * Returns: + * O on success, non-zero otherwise. + * + * --------------------------------------------------------------------------- + */ +int +uf_init_hw(unifi_priv_t *priv) +{ + int attempts = 0; + int priv_instance; + CsrResult csrResult = CSR_RESULT_FAILURE; + + priv_instance = uf_find_priv(priv); + if (priv_instance == -1) { + unifi_warning(priv, "uf_init_hw: Unknown priv instance, will use fw_init[0]\n"); + priv_instance = 0; + } + + while (1) { + if (attempts > MAX_INIT_ATTEMPTS) { + unifi_error(priv, "Failed to initialise UniFi after %d attempts, " + "giving up.\n", + attempts); + break; + } + attempts++; + + unifi_info(priv, "Initialising UniFi, attempt %d\n", attempts); + + if (fw_init[priv_instance] > 0) { + unifi_notice(priv, "f/w init prevented by module parameter\n"); + break; + } else if (fw_init[priv_instance] == 0) { + fw_init[priv_instance] ++; + } + + /* + * Initialise driver core. This will perform a reset of UniFi + * internals, but not the SDIO CCCR. + */ + CsrSdioClaim(priv->sdio); + csrResult = unifi_init_card(priv->card, led_mask); + CsrSdioRelease(priv->sdio); + + if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) { + return CsrHipResultToStatus(csrResult); + } + if (csrResult == CSR_WIFI_HIP_RESULT_NOT_FOUND) { + unifi_error(priv, "Firmware file required, but not found.\n"); + return CsrHipResultToStatus(csrResult); + } + if (csrResult != CSR_RESULT_SUCCESS) { + /* failed. Reset h/w and try again */ + unifi_error(priv, "Failed to initialise UniFi chip.\n"); + continue; + } + + /* Get the version information from the lib_hip */ + unifi_card_info(priv->card, &priv->card_info); + + return CsrHipResultToStatus(csrResult); + } + + return CsrHipResultToStatus(csrResult); + +} /* uf_init_hw */ + + diff --git a/drivers/staging/csr/io.c b/drivers/staging/csr/io.c new file mode 100644 index 000000000000..fbf1b2099cc9 --- /dev/null +++ b/drivers/staging/csr/io.c @@ -0,0 +1,1146 @@ +/* + * --------------------------------------------------------------------------- + * FILE: io.c + * + * PURPOSE: + * This file contains routines that the SDIO driver can call when a + * UniFi card is first inserted (or detected) and removed. + * + * When used with sdioemb, the udev scripts (at least on Ubuntu) don't + * recognise a UniFi being added to the system. This is because sdioemb + * does not register itself as a device_driver, it uses it's own code + * to handle insert and remove. + * To have Ubuntu recognise UniFi, edit /etc/udev/rules.d/85-ifupdown.rules + * to change this line: + * SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" + * to these: + * #SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" + * SUBSYSTEM=="net", GOTO="net_start" + * + * Then you can add a stanza to /etc/network/interfaces like this: + * auto eth1 + * iface eth1 inet dhcp + * wpa-conf /etc/wpa_supplicant.conf + * This will then automatically associate when a car dis inserted. + * + * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifiversion.h" +#include "csr_wifi_hip_unifi_udi.h" /* for unifi_print_status() */ +#include "unifiio.h" +#include "unifi_priv.h" + + +/* + * Array of pointers to context structs for unifi devices that are present. + * The index in the array corresponds to the wlan interface number + * (if "wlan*" is used). If "eth*" is used, the eth* numbers are allocated + * after any Ethernet cards. + * + * The Arasan PCI-SDIO controller card supported by this driver has 2 slots, + * hence a max of 2 devices. + */ +static unifi_priv_t *Unifi_instances[MAX_UNIFI_DEVS]; + +/* Array of pointers to netdev objects used by the UniFi driver, as there + * are now many per instance. This is used to determine which netdev events + * are for UniFi as opposed to other net interfaces. + */ +static netInterface_priv_t *Unifi_netdev_instances[MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES]; + +/* + * Array to hold the status of each unifi device in each slot. + * We only process an insert event when In_use[] for the slot is + * UNIFI_DEV_NOT_IN_USE. Otherwise, it means that the slot is in use or + * we are in the middle of a cleanup (the action on unplug). + */ +#define UNIFI_DEV_NOT_IN_USE 0 +#define UNIFI_DEV_IN_USE 1 +#define UNIFI_DEV_CLEANUP 2 +static int In_use[MAX_UNIFI_DEVS]; +/* + * Mutex to prevent UDI clients to open the character device before the priv + * is created and initialised. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +DEFINE_SEMAPHORE(Unifi_instance_mutex); +#else +DECLARE_MUTEX(Unifi_instance_mutex); +#endif +/* + * When the device is removed, unregister waits on Unifi_cleanup_wq + * until all the UDI clients release the character device. + */ +DECLARE_WAIT_QUEUE_HEAD(Unifi_cleanup_wq); + + +static int uf_read_proc(char *page, char **start, off_t offset, int count, + int *eof, void *data); + +#ifdef CSR_WIFI_RX_PATH_SPLIT + +static CsrResult signal_buffer_init(unifi_priv_t * priv, int size) +{ + int i; + func_enter(); + + priv->rxSignalBuffer.writePointer = + priv->rxSignalBuffer.readPointer = 0; + priv->rxSignalBuffer.size = size; + /* Allocating Memory for Signal primitive pointer */ + for(i=0; irxSignalBuffer.rx_buff[i].sig_len=0; + priv->rxSignalBuffer.rx_buff[i].bufptr = CsrMemAlloc(UNIFI_PACKED_SIGBUF_SIZE); + if (priv->rxSignalBuffer.rx_buff[i].bufptr == NULL) + { + int j; + unifi_error(priv,"signal_buffer_init:Failed to Allocate shared memory for T-H signals \n"); + for(j=0;jrxSignalBuffer.rx_buff[j].sig_len=0; + CsrMemFree(priv->rxSignalBuffer.rx_buff[j].bufptr); + priv->rxSignalBuffer.rx_buff[j].bufptr = NULL; + } + func_exit(); + return -1; + } + } + func_exit(); + return 0; +} + + +static void signal_buffer_free(unifi_priv_t * priv, int size) +{ + int i; + + for(i=0; irxSignalBuffer.rx_buff[i].sig_len=0; + CsrMemFree(priv->rxSignalBuffer.rx_buff[i].bufptr); + priv->rxSignalBuffer.rx_buff[i].bufptr = NULL; + } +} +#endif +/* + * --------------------------------------------------------------------------- + * uf_register_netdev + * + * Registers the network interface, installes the qdisc, + * and registers the inet handler. + * In the porting exercise, register the driver to the network + * stack if necessary. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * O on success, non-zero otherwise. + * + * Notes: + * We will only unregister when the card is ejected, so we must + * only do it once. + * --------------------------------------------------------------------------- + */ +int +uf_register_netdev(unifi_priv_t *priv, int interfaceTag) +{ + int r; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_register_netdev bad interfaceTag\n"); + return -EINVAL; + } + + /* + * Allocates a device number and registers device with the network + * stack. + */ + unifi_trace(priv, UDBG5, "uf_register_netdev: netdev %d - 0x%p\n", + interfaceTag, priv->netdev[interfaceTag]); + r = register_netdev(priv->netdev[interfaceTag]); + if (r) { + unifi_error(priv, "Failed to register net device\n"); + return -EINVAL; + } + + /* The device is registed */ + interfacePriv->netdev_registered = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* + * IMPORTANT: + * uf_install_qdisc() holds the network device lock, we can not + * install the qdisk before the network device is registered. + */ + r = uf_install_qdisc(priv->netdev[interfaceTag]); + if (r) { + unifi_error(priv, "Failed to install qdisc\n"); + return r; + } +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + +#ifdef CSR_SUPPORT_SME + /* + * Register the inet handler; it notifies us for changes in the IP address. + */ + uf_register_inet_notifier(); +#endif /* CSR_SUPPORT_SME */ + + unifi_notice(priv, "unifi%d is %s\n", + priv->instance, priv->netdev[interfaceTag]->name); + + return 0; +} /* uf_register_netdev */ + + +/* + * --------------------------------------------------------------------------- + * uf_unregister_netdev + * + * Unregisters the network interface and the inet handler. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * None. + * + * --------------------------------------------------------------------------- + */ +void +uf_unregister_netdev(unifi_priv_t *priv) +{ + int i=0; + +#ifdef CSR_SUPPORT_SME + /* Unregister the inet handler... */ + uf_unregister_inet_notifier(); +#endif /* CSR_SUPPORT_SME */ + + for (i=0; iinterfacePriv[i]; + if (interfacePriv->netdev_registered) { + unifi_trace(priv, UDBG5, + "uf_unregister_netdev: netdev %d - 0x%p\n", + i, priv->netdev[i]); + + /* ... and the netdev */ + unregister_netdev(priv->netdev[i]); + interfacePriv->netdev_registered = 0; + } + + interfacePriv->interfaceMode = 0; + + /* Enable all queues by default */ + interfacePriv->queueEnabled[0] = 1; + interfacePriv->queueEnabled[1] = 1; + interfacePriv->queueEnabled[2] = 1; + interfacePriv->queueEnabled[3] = 1; + } + + priv->totalInterfaceCount = 0; +} /* uf_unregister_netdev() */ + + +/* + * --------------------------------------------------------------------------- + * register_unifi_sdio + * + * This function is called from the Probe (or equivalent) method of + * the SDIO driver when a UniFi card is detected. + * We allocate the Linux net_device struct, initialise the HIP core + * lib, create the char device nodes and start the userspace helper + * to initialise the device. + * + * Arguments: + * sdio_dev Pointer to SDIO context handle to use for all + * SDIO ops. + * bus_id A small number indicating the SDIO card position on the + * bus. Typically this is the slot number, e.g. 0, 1 etc. + * Valid values are 0 to MAX_UNIFI_DEVS-1. + * dev Pointer to kernel device manager struct. + * + * Returns: + * Pointer to the unifi instance, or NULL on error. + * --------------------------------------------------------------------------- + */ +static unifi_priv_t * +register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) +{ + unifi_priv_t *priv = NULL; + int r = -1; + CsrResult csrResult; + + func_enter(); + + if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { + unifi_error(priv, "register_unifi_sdio: invalid device %d\n", + bus_id); + return NULL; + } + + down(&Unifi_instance_mutex); + + if (In_use[bus_id] != UNIFI_DEV_NOT_IN_USE) { + unifi_error(priv, "register_unifi_sdio: device %d is already in use\n", + bus_id); + goto failed0; + } + + + /* Allocate device private and net_device structs */ + priv = uf_alloc_netdevice(sdio_dev, bus_id); + if (priv == NULL) { + unifi_error(priv, "Failed to allocate driver private\n"); + goto failed0; + } + + priv->unifi_device = dev; + + SET_NETDEV_DEV(priv->netdev[0], dev); + + /* We are not ready to send data yet. */ + netif_carrier_off(priv->netdev[0]); + + /* Allocate driver context. */ + priv->card = unifi_alloc_card(priv->sdio, priv); + if (priv->card == NULL) { + unifi_error(priv, "Failed to allocate UniFi driver card struct.\n"); + goto failed1; + } + + if (Unifi_instances[bus_id]) { + unifi_error(priv, "Internal error: instance for slot %d is already taken\n", + bus_id); + } + Unifi_instances[bus_id] = priv; + In_use[bus_id] = UNIFI_DEV_IN_USE; + + /* Save the netdev_priv for use by the netdev event callback mechanism */ + Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES] = netdev_priv(priv->netdev[0]); + + /* Initialise the mini-coredump capture buffers */ + csrResult = unifi_coredump_init(priv->card, (CsrUint16)coredump_max); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Couldn't allocate mini-coredump buffers\n"); + } + + /* Create the character device nodes */ + r = uf_create_device_nodes(priv, bus_id); + if (r) { + goto failed1; + } + + /* + * We use the slot number as unifi device index. + */ + snprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance); + /* + * The following complex casting is in place in order to eliminate 64-bit compilation warning + * "cast to/from pointer from/to integer of different size" + */ + if (!create_proc_read_entry(priv->proc_entry_name, 0, 0, + uf_read_proc, (void *)(long)priv->instance)) + { + unifi_error(priv, "unifi: can't create /proc/driver/unifi\n"); + } + + /* Allocate the net_device for interfaces other than 0. */ + { + int i; + priv->totalInterfaceCount =0; + + for(i=1;inetdev[i], dev); + + /* We are not ready to send data yet. */ + netif_carrier_off(priv->netdev[i]); + + /* Save the netdev_priv for use by the netdev event callback mechanism */ + Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES + i] = netdev_priv(priv->netdev[i]); + } + } + + for(i=0;iinterfacePriv[i]; + interfacePriv->netdev_registered=0; + } + } + +#ifdef CSR_WIFI_RX_PATH_SPLIT + if (signal_buffer_init(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE)) + { + unifi_error(priv,"Failed to allocate shared memory for T-H signals\n"); + goto failed2; + } + priv->rx_workqueue = create_singlethread_workqueue("rx_workq"); + if (priv->rx_workqueue == NULL) { + unifi_error(priv,"create_singlethread_workqueue failed \n"); + goto failed3; + } + INIT_WORK(&priv->rx_work_struct, rx_wq_handler); +#endif + + /* Initialise the SME related threads and parameters */ + r = uf_sme_init(priv); + if (r) { + unifi_error(priv, "SME initialisation failed.\n"); + goto failed4; + } + + /* + * Run the userspace helper program (unififw) to perform + * the device initialisation. + */ + unifi_trace(priv, UDBG1, "run UniFi helper app...\n"); + r = uf_run_unifihelper(priv); + if (r) { + unifi_notice(priv, "unable to run UniFi helper app\n"); + /* Not a fatal error. */ + } + + up(&Unifi_instance_mutex); + + func_exit(); + return priv; + +failed4: +#ifdef CSR_WIFI_RX_PATH_SPLIT + flush_workqueue(priv->rx_workqueue); + destroy_workqueue(priv->rx_workqueue); +failed3: + signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); +failed2: +#endif + /* Remove the device nodes */ + uf_destroy_device_nodes(priv); +failed1: + /* Deregister priv->netdev_client */ + ul_deregister_client(priv->netdev_client); + +failed0: + if (priv && priv->card) { + unifi_coredump_free(priv->card); + unifi_free_card(priv->card); + } + if (priv) { + uf_free_netdevice(priv); + } + + up(&Unifi_instance_mutex); + + func_exit(); + return NULL; +} /* register_unifi_sdio() */ + + +/* + * --------------------------------------------------------------------------- + * ask_unifi_sdio_cleanup + * + * We can not free our private context, until all the char device + * clients have closed the file handles. unregister_unifi_sdio() which + * is called when a card is removed, waits on Unifi_cleanup_wq until + * the reference count becomes zero. It is time to wake it up now. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +ask_unifi_sdio_cleanup(unifi_priv_t *priv) +{ + func_enter(); + + /* + * Now clear the flag that says the old instance is in use. + * This is used to prevent a new instance being started before old + * one has finshed closing down, for example if bounce makes the card + * appear to be ejected and re-inserted quickly. + */ + In_use[priv->instance] = UNIFI_DEV_CLEANUP; + + unifi_trace(NULL, UDBG5, "ask_unifi_sdio_cleanup: wake up cleanup workqueue.\n"); + wake_up(&Unifi_cleanup_wq); + + func_exit(); + +} /* ask_unifi_sdio_cleanup() */ + + +/* + * --------------------------------------------------------------------------- + * cleanup_unifi_sdio + * + * Release any resources owned by a unifi instance. + * + * Arguments: + * priv Pointer to the instance to free. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +cleanup_unifi_sdio(unifi_priv_t *priv) +{ + int priv_instance; + int i; + static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + + func_enter(); + + /* Remove the device nodes */ + uf_destroy_device_nodes(priv); + + /* Mark this device as gone away by NULLing the entry in Unifi_instances */ + Unifi_instances[priv->instance] = NULL; + + unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: remove_proc_entry\n"); + /* + * Free the children of priv before unifi_free_netdevice() frees + * the priv struct + */ + remove_proc_entry(priv->proc_entry_name, 0); + + + /* Unregister netdev as a client. */ + if (priv->netdev_client) { + unifi_trace(priv, UDBG2, "Netdev client (id:%d s:0x%X) is unregistered\n", + priv->netdev_client->client_id, priv->netdev_client->sender_id); + ul_deregister_client(priv->netdev_client); + } + + /* Destroy the SME related threads and parameters */ + uf_sme_deinit(priv); + +#ifdef CSR_SME_USERSPACE + priv->smepriv = NULL; +#endif + + /* Free any packets left in the Rx queues */ + for(i=0;icard) { + unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: free card\n"); + unifi_coredump_free(priv->card); + unifi_free_card(priv->card); + priv->card = NULL; + } + + /* + * Unregister the network device. + * We can not unregister the netdev before we release + * all pending packets in the core. + */ + uf_unregister_netdev(priv); + priv->totalInterfaceCount = 0; + + /* Clear the table of registered netdev_priv's */ + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + Unifi_netdev_instances[priv->instance * CSR_WIFI_NUM_INTERFACES + i] = NULL; + } + + unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: uf_free_netdevice\n"); + /* + * When uf_free_netdevice() returns, the priv is invalid + * so we need to remember the instance to clear the global flag later. + */ + priv_instance = priv->instance; + +#ifdef CSR_WIFI_RX_PATH_SPLIT + flush_workqueue(priv->rx_workqueue); + destroy_workqueue(priv->rx_workqueue); + signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); +#endif + + /* Priv is freed as part of the net_device */ + uf_free_netdevice(priv); + + /* + * Now clear the flag that says the old instance is in use. + * This is used to prevent a new instance being started before old + * one has finshed closing down, for example if bounce makes the card + * appear to be ejected and re-inserted quickly. + */ + In_use[priv_instance] = UNIFI_DEV_NOT_IN_USE; + + unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n"); + + func_exit(); + +} /* cleanup_unifi_sdio() */ + + +/* + * --------------------------------------------------------------------------- + * unregister_unifi_sdio + * + * Call from SDIO driver when it detects that UniFi has been removed. + * + * Arguments: + * bus_id Number of the card that was ejected. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +unregister_unifi_sdio(int bus_id) +{ + unifi_priv_t *priv; + int interfaceTag=0; + u8 reason = CONFIG_IND_EXIT; + + if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { + unifi_error(NULL, "unregister_unifi_sdio: invalid device %d\n", + bus_id); + return; + } + + priv = Unifi_instances[bus_id]; + if (priv == NULL) { + unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n", + bus_id); + func_exit(); + return; + } + + /* Stop the network traffic before freeing the core. */ + for(interfaceTag=0;interfaceTagtotalInterfaceCount;interfaceTag++) + { + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + if(interfacePriv->netdev_registered) + { + netif_carrier_off(priv->netdev[interfaceTag]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); + } + } + +#ifdef CSR_NATIVE_LINUX + /* + * If the unifi thread was started, signal it to stop. This + * should cause any userspace processes with open unifi device to + * close them. + */ + uf_stop_thread(priv, &priv->bh_thread); + + /* Unregister the interrupt handler */ + if (csr_sdio_linux_remove_irq(priv->sdio)) { + unifi_notice(priv, + "csr_sdio_linux_remove_irq failed to talk to card.\n"); + } + + /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ + uf_abort_mlme(priv); +#endif /* CSR_NATIVE_LINUX */ + + ul_log_config_ind(priv, &reason, sizeof(u8)); + + /* Deregister the UDI hook from the core. */ + unifi_remove_udi_hook(priv->card, logging_handler); + + uf_put_instance(bus_id); + + /* + * Wait until the device is cleaned up. i.e., when all userspace + * processes have closed any open unifi devices. + */ + wait_event(Unifi_cleanup_wq, In_use[bus_id] == UNIFI_DEV_CLEANUP); + unifi_trace(NULL, UDBG5, "Received clean up event\n"); + + /* Now we can free the private context and the char device nodes */ + cleanup_unifi_sdio(priv); + +} /* unregister_unifi_sdio() */ + + +/* + * --------------------------------------------------------------------------- + * uf_find_instance + * + * Find the context structure for a given UniFi device instance. + * + * Arguments: + * inst The instance number to look for. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +unifi_priv_t * +uf_find_instance(int inst) +{ + if ((inst < 0) || (inst >= MAX_UNIFI_DEVS)) { + return NULL; + } + return Unifi_instances[inst]; +} /* uf_find_instance() */ + + +/* + * --------------------------------------------------------------------------- + * uf_find_priv + * + * Find the device instance for a given context structure. + * + * Arguments: + * priv The context structure pointer to look for. + * + * Returns: + * index of instance, -1 otherwise. + * --------------------------------------------------------------------------- + */ +int +uf_find_priv(unifi_priv_t *priv) +{ + int inst; + + if (!priv) { + return -1; + } + + for (inst = 0; inst < MAX_UNIFI_DEVS; inst++) { + if (Unifi_instances[inst] == priv) { + return inst; + } + } + + return -1; +} /* uf_find_priv() */ + +/* + * --------------------------------------------------------------------------- + * uf_find_netdev_priv + * + * Find the device instance for a given netdev context structure. + * + * Arguments: + * priv The context structure pointer to look for. + * + * Returns: + * index of instance, -1 otherwise. + * --------------------------------------------------------------------------- + */ +int +uf_find_netdev_priv(netInterface_priv_t *priv) +{ + int inst; + + if (!priv) { + return -1; + } + + for (inst = 0; inst < MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES; inst++) { + if (Unifi_netdev_instances[inst] == priv) { + return inst; + } + } + + return -1; +} /* uf_find_netdev_priv() */ + +/* + * --------------------------------------------------------------------------- + * uf_get_instance + * + * Find the context structure for a given UniFi device instance + * and increment the reference count. + * + * Arguments: + * inst The instance number to look for. + * + * Returns: + * Pointer to the instance or NULL if no instance exists. + * --------------------------------------------------------------------------- + */ +unifi_priv_t * +uf_get_instance(int inst) +{ + unifi_priv_t *priv; + + down(&Unifi_instance_mutex); + + priv = uf_find_instance(inst); + if (priv) { + priv->ref_count++; + } + + up(&Unifi_instance_mutex); + + return priv; +} + +/* + * --------------------------------------------------------------------------- + * uf_put_instance + * + * Decrement the context reference count, freeing resources and + * shutting down the driver when the count reaches zero. + * + * Arguments: + * inst The instance number to look for. + * + * Returns: + * Pointer to the instance or NULL if no instance exists. + * --------------------------------------------------------------------------- + */ +void +uf_put_instance(int inst) +{ + unifi_priv_t *priv; + + down(&Unifi_instance_mutex); + + priv = uf_find_instance(inst); + if (priv) { + priv->ref_count--; + if (priv->ref_count == 0) { + ask_unifi_sdio_cleanup(priv); + } + } + + up(&Unifi_instance_mutex); +} + + +/* + * --------------------------------------------------------------------------- + * uf_read_proc + * + * Read method for driver node in /proc/driver/unifi0 + * + * Arguments: + * page + * start + * offset + * count + * eof + * data + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +#ifdef CONFIG_PROC_FS +static int +uf_read_proc(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ +#define UNIFI_DEBUG_TXT_BUFFER 8*1024 + unifi_priv_t *priv; + int actual_amount_to_copy; + char *p, *orig_p; + CsrInt32 remain = UNIFI_DEBUG_TXT_BUFFER; + CsrInt32 written; + int i; + + /* + * The following complex casting is in place in order to eliminate 64-bit compilation warning + * "cast to/from pointer from/to integer of different size" + */ + priv = uf_find_instance((int)(long)data); + if (!priv) { + return 0; + } + + p = kmalloc( UNIFI_DEBUG_TXT_BUFFER, GFP_KERNEL ); + + orig_p = p; + + written = CsrSnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n", + CSR_WIFI_VERSION, __DATE__, __TIME__); + UNIFI_SNPRINTF_RET(p, remain, written); +#ifdef CSR_SME_USERSPACE + written = CsrSnprintf(p, remain, "SME: CSR userspace "); + UNIFI_SNPRINTF_RET(p, remain, written); +#ifdef CSR_SUPPORT_WEXT + written = CsrSnprintf(p, remain, "with WEXT support\n"); +#else + written = CsrSnprintf(p, remain, "\n"); +#endif /* CSR_SUPPORT_WEXT */ + UNIFI_SNPRINTF_RET(p, remain, written); +#endif /* CSR_SME_USERSPACE */ +#ifdef CSR_NATIVE_LINUX + written = CsrSnprintf(p, remain, "SME: native\n"); + UNIFI_SNPRINTF_RET(p, remain, written); +#endif + +#ifdef CSR_SUPPORT_SME + written = CsrSnprintf(p, remain, + "Firmware (ROM) build:%lu, Patch:%lu\n", + priv->card_info.fw_build, + priv->sme_versions.firmwarePatch); + UNIFI_SNPRINTF_RET(p, remain, written); +#endif + p += unifi_print_status(priv->card, p, &remain); + + written = CsrSnprintf(p, remain, "Last dbg str: %s\n", + priv->last_debug_string); + UNIFI_SNPRINTF_RET(p, remain, written); + + written = CsrSnprintf(p, remain, "Last dbg16:"); + UNIFI_SNPRINTF_RET(p, remain, written); + for (i = 0; i < 8; i++) { + written = CsrSnprintf(p, remain, " %04X", + priv->last_debug_word16[i]); + UNIFI_SNPRINTF_RET(p, remain, written); + } + written = CsrSnprintf(p, remain, "\n"); + UNIFI_SNPRINTF_RET(p, remain, written); + written = CsrSnprintf(p, remain, " "); + UNIFI_SNPRINTF_RET(p, remain, written); + for (; i < 16; i++) { + written = CsrSnprintf(p, remain, " %04X", + priv->last_debug_word16[i]); + UNIFI_SNPRINTF_RET(p, remain, written); + } + written = CsrSnprintf(p, remain, "\n"); + UNIFI_SNPRINTF_RET(p, remain, written); + *start = page; + + written = UNIFI_DEBUG_TXT_BUFFER - remain; + + if( offset >= written ) + { + *eof = 1; + kfree( orig_p ); + return(0); + } + + if( offset + count > written ) + { + actual_amount_to_copy = written - offset; + *eof = 1; + } + else + { + actual_amount_to_copy = count; + } + + memcpy( page, &(orig_p[offset]), actual_amount_to_copy ); + + kfree( orig_p ); + + return( actual_amount_to_copy ); +} /* uf_read_proc() */ +#endif + + + + +static void +uf_lx_suspend(CsrSdioFunction *sdio_ctx) +{ + unifi_priv_t *priv = sdio_ctx->driverData; + unifi_suspend(priv); + + CsrSdioSuspendAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); +} + +static void +uf_lx_resume(CsrSdioFunction *sdio_ctx) +{ + unifi_priv_t *priv = sdio_ctx->driverData; + unifi_resume(priv); + + CsrSdioResumeAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); +} + +static int active_slot = MAX_UNIFI_DEVS; +static struct device *os_devices[MAX_UNIFI_DEVS]; + +void +uf_add_os_device(int bus_id, struct device *os_device) +{ + if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { + unifi_error(NULL, "uf_add_os_device: invalid device %d\n", + bus_id); + return; + } + + active_slot = bus_id; + os_devices[bus_id] = os_device; +} /* uf_add_os_device() */ + +void +uf_remove_os_device(int bus_id) +{ + if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { + unifi_error(NULL, "uf_remove_os_device: invalid device %d\n", + bus_id); + return; + } + + active_slot = bus_id; + os_devices[bus_id] = NULL; +} /* uf_remove_os_device() */ + +static void +uf_sdio_inserted(CsrSdioFunction *sdio_ctx) +{ + unifi_priv_t *priv; + + unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n", + sdio_ctx, active_slot, os_devices[active_slot]); + + priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]); + if (priv == NULL) { + CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE); + return; + } + + sdio_ctx->driverData = priv; + + CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); +} /* uf_sdio_inserted() */ + + +static void +uf_sdio_removed(CsrSdioFunction *sdio_ctx) +{ + unregister_unifi_sdio(active_slot); + CsrSdioRemovedAcknowledge(sdio_ctx); +} /* uf_sdio_removed() */ + + +static void +uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx) +{ + unifi_priv_t *priv = sdio_ctx->driverData; + + unifi_sdio_interrupt_handler(priv->card); +} /* uf_sdio_dsr_handler() */ + +/* + * --------------------------------------------------------------------------- + * uf_sdio_int_handler + * + * Interrupt callback function for SDIO interrupts. + * This is called in kernel context (i.e. not interrupt context). + * We retrieve the unifi context pointer and call the main UniFi + * interrupt handler. + * + * Arguments: + * fdev SDIO context pointer + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static CsrSdioInterruptDsrCallback +uf_sdio_int_handler(CsrSdioFunction *sdio_ctx) +{ + return uf_sdio_dsr_handler; +} /* uf_sdio_int_handler() */ + + + + +static CsrSdioFunctionId unifi_ids[] = +{ + { + .manfId = SDIO_MANF_ID_CSR, + .cardId = SDIO_CARD_ID_UNIFI_3, + .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3, + .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, + }, + { + .manfId = SDIO_MANF_ID_CSR, + .cardId = SDIO_CARD_ID_UNIFI_4, + .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4, + .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, + } +}; + + +/* + * Structure to register with the glue layer. + */ +static CsrSdioFunctionDriver unifi_sdioFunction_drv = +{ + .inserted = uf_sdio_inserted, + .removed = uf_sdio_removed, + .intr = uf_sdio_int_handler, + .suspend = uf_lx_suspend, + .resume = uf_lx_resume, + + .ids = unifi_ids, + .idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0]) +}; + + +/* + * --------------------------------------------------------------------------- + * uf_sdio_load + * uf_sdio_unload + * + * These functions are called from the main module load and unload + * functions. They perform the appropriate operations for the monolithic + * driver. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int __init +uf_sdio_load(void) +{ + CsrResult csrResult; + + csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult); + return -EIO; + } + + return 0; +} /* uf_sdio_load() */ + + + +void __exit +uf_sdio_unload(void) +{ + CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv); +} /* uf_sdio_unload() */ + diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c new file mode 100644 index 000000000000..790d5d77375f --- /dev/null +++ b/drivers/staging/csr/mlme.c @@ -0,0 +1,441 @@ +/* + * --------------------------------------------------------------------------- + * FILE: mlme.c + * + * PURPOSE: + * This file provides functions to send MLME requests to the UniFi. + * + * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + +/* The additional time taken by the UniFi to do a scan per channel */ +#define SCAN_STARTUP_TIME 300 /* in millisecs */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_wait_for_reply + * + * Wait for a reply after sending a signal. + * + * Arguments: + * priv Pointer to device private context struct + * ul_client Pointer to linux client + * sig_reply_id ID of the expected reply (defined in sigs.h). + * timeout timeout in ms + * + * Returns: + * 0 on success, -ve POSIX code on error. + * + * Notes: + * This function waits for a specific (sig_reply_id) signal from UniFi. + * It also match the sequence number of the received (cfm) signal, with + * the latest sequence number of the signal (req) we have sent. + * These two number match be equal. + * Should only be used for waiting xxx.cfm signals and only after + * we have sent the matching xxx.req signal to UniFi. + * If no response is received within the expected time (timeout), we assume + * that the UniFi is busy and return an error. + * If the wait is aborted by a kernel signal arriving, we stop waiting. + * If a response from UniFi is not what we expected, we discard it and + * wait again. This could be a response from an aborted request. If we + * see several bad responses we assume we have lost synchronisation with + * UniFi. + * --------------------------------------------------------------------------- + */ +static int +unifi_mlme_wait_for_reply(unifi_priv_t *priv, ul_client_t *pcli, int sig_reply_id, int timeout) +{ + int retries = 0; + long r; + long t = timeout; + unsigned int sent_seq_no; + + /* Convert t in ms to jiffies */ + t = msecs_to_jiffies(t); + + do { + /* Wait for the confirm or timeout. */ + r = wait_event_interruptible_timeout(pcli->udi_wq, + (pcli->wake_up_wq_id) || (priv->io_aborted == 1), + t); + /* Check for general i/o error */ + if (priv->io_aborted) { + unifi_error(priv, "MLME operation aborted\n"); + return -EIO; + } + + /* + * If r=0 the request has timed-out. + * If r>0 the request has completed successfully. + * If r=-ERESTARTSYS an event (kill signal) has interrupted the wait_event. + */ + if ((r == 0) && (pcli->wake_up_wq_id == 0)) { + unifi_error(priv, "mlme_wait: timed-out waiting for 0x%.4X, after %lu msec.\n", + sig_reply_id, jiffies_to_msecs(t)); + pcli->wake_up_wq_id = 0; + return -ETIMEDOUT; + } else if (r == -ERESTARTSYS) { + unifi_error(priv, "mlme_wait: waiting for 0x%.4X was aborted.\n", sig_reply_id); + pcli->wake_up_wq_id = 0; + return -EINTR; + } else { + /* Get the sequence number of the signal that we previously set. */ + if (pcli->seq_no != 0) { + sent_seq_no = pcli->seq_no - 1; + } else { + sent_seq_no = 0x0F; + } + + unifi_trace(priv, UDBG5, "Received 0x%.4X, seq: (r:%d, s:%d)\n", + pcli->wake_up_wq_id, + pcli->wake_seq_no, sent_seq_no); + + /* The two sequence ids must match. */ + if (pcli->wake_seq_no == sent_seq_no) { + /* and the signal ids must match. */ + if (sig_reply_id == pcli->wake_up_wq_id) { + /* Found the expected signal */ + break; + } else { + /* This should never happen ... */ + unifi_error(priv, "mlme_wait: mismatching signal id (0x%.4X - exp 0x%.4X) (seq %d)\n", + pcli->wake_up_wq_id, + sig_reply_id, + pcli->wake_seq_no); + pcli->wake_up_wq_id = 0; + return -EIO; + } + } + /* Wait for the next signal. */ + pcli->wake_up_wq_id = 0; + + retries ++; + if (retries >= 3) { + unifi_error(priv, "mlme_wait: confirm wait retries exhausted (0x%.4X - exp 0x%.4X)\n", + pcli->wake_up_wq_id, + sig_reply_id); + pcli->wake_up_wq_id = 0; + return -EIO; + } + } + } while (1); + + pcli->wake_up_wq_id = 0; + + return 0; +} /* unifi_mlme_wait_for_reply() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_blocking_request + * + * Send a MLME request signal to UniFi. + * + * Arguments: + * priv Pointer to device private context struct + * pcli Pointer to context of calling process + * sig Pointer to the signal to send + * data_ptrs Pointer to the bulk data of the signal + * timeout The request's timeout. + * + * Returns: + * 0 on success, 802.11 result code on error. + * --------------------------------------------------------------------------- + */ +int +unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli, + CSR_SIGNAL *sig, bulk_data_param_t *data_ptrs, + int timeout) +{ + int r; + + func_enter(); + + if (sig->SignalPrimitiveHeader.SignalId == 0) { + unifi_error(priv, "unifi_mlme_blocking_request: Invalid Signal Id (0x%x)\n", + sig->SignalPrimitiveHeader.SignalId); + return -EINVAL; + } + + down(&priv->mlme_blocking_mutex); + + sig->SignalPrimitiveHeader.ReceiverProcessId = 0; + sig->SignalPrimitiveHeader.SenderProcessId = pcli->sender_id | pcli->seq_no; + + unifi_trace(priv, UDBG2, "Send client=%d, S:0x%04X, sig 0x%.4X\n", + pcli->client_id, + sig->SignalPrimitiveHeader.SenderProcessId, + sig->SignalPrimitiveHeader.SignalId); + /* Send the signal to UniFi */ + r = ul_send_signal_unpacked(priv, sig, data_ptrs); + if (r) { + up(&priv->mlme_blocking_mutex); + unifi_error(priv, "Error queueing MLME REQUEST signal\n"); + return r; + } + + unifi_trace(priv, UDBG5, "Send 0x%.4X, seq = %d\n", + sig->SignalPrimitiveHeader.SignalId, pcli->seq_no); + + /* + * Advance the sequence number of the last sent signal, only + * if the signal has been successfully set. + */ + pcli->seq_no++; + if (pcli->seq_no > 0x0F) { + pcli->seq_no = 0; + } + + r = unifi_mlme_wait_for_reply(priv, pcli, (sig->SignalPrimitiveHeader.SignalId + 1), timeout); + up(&priv->mlme_blocking_mutex); + + if (r) { + unifi_error(priv, "Error waiting for MLME CONFIRM signal\n"); + return r; + } + + func_exit(); + return 0; +} /* unifi_mlme_blocking_request() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_copy_reply_and_wakeup_client + * + * Copy the reply signal from UniFi to the client's structure + * and wake up the waiting client. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_mlme_copy_reply_and_wakeup_client(ul_client_t *pcli, + CSR_SIGNAL *signal, int signal_len, + const bulk_data_param_t *bulkdata) +{ + int i; + + /* Copy the signal to the reply */ + memcpy(pcli->reply_signal, signal, signal_len); + + /* Get the sequence number of the signal that woke us up. */ + pcli->wake_seq_no = pcli->reply_signal->SignalPrimitiveHeader.ReceiverProcessId & 0x0F; + + /* Append any bulk data */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length > 0) { + if (bulkdata->d[i].os_data_ptr) { + memcpy(pcli->reply_bulkdata[i]->ptr, bulkdata->d[i].os_data_ptr, bulkdata->d[i].data_length); + pcli->reply_bulkdata[i]->length = bulkdata->d[i].data_length; + } else { + pcli->reply_bulkdata[i]->length = 0; + } + } + } + + /* Wake the requesting MLME function. */ + pcli->wake_up_wq_id = pcli->reply_signal->SignalPrimitiveHeader.SignalId; + wake_up_interruptible(&pcli->udi_wq); + +} /* unifi_mlme_copy_reply_and_wakeup_client() */ + + +/* + * --------------------------------------------------------------------------- + * uf_abort_mlme + * + * Abort any MLME operation in progress. + * This is used in the error recovery mechanism. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * 0 on success. + * --------------------------------------------------------------------------- + */ +int +uf_abort_mlme(unifi_priv_t *priv) +{ + ul_client_t *ul_cli; + + /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ + priv->io_aborted = 1; + + ul_cli = priv->netdev_client; + if (ul_cli) { + wake_up_interruptible(&ul_cli->udi_wq); + } + + ul_cli = priv->wext_client; + if (ul_cli) { + wake_up_interruptible(&ul_cli->udi_wq); + } + + return 0; +} /* uf_abort_mlme() */ + + + +/* + * --------------------------------------------------------------------------- + * + * Human-readable decoding of Reason and Result codes. + * + * --------------------------------------------------------------------------- + */ + +struct mlme_code { + const char *name; + int id; +}; + +static const struct mlme_code Result_codes[] = { + { "Success", 0x0000 }, + { "Unspecified Failure", 0x0001 }, + /* (Reserved) 0x0002 - 0x0009 */ + { "Refused Capabilities Mismatch", 0x000A }, + /* (Reserved) 0x000B */ + { "Refused External Reason", 0x000C }, + /* (Reserved) 0x000D - 0x0010 */ + { "Refused AP Out Of Memory", 0x0011 }, + { "Refused Basic Rates Mismatch", 0x0012 }, + /* (Reserved) 0x0013 - 0x001F */ + { "Failure", 0x0020 }, + /* (Reserved) 0x0021 - 0x0024 */ + { "Refused Reason Unspecified", 0x0025 }, + { "Invalid Parameters", 0x0026 }, + { "Rejected With Suggested Changes", 0x0027 }, + /* (Reserved) 0x0028 - 0x002E */ + { "Rejected For Delay Period", 0x002F }, + { "Not Allowed", 0x0030 }, + { "Not Present", 0x0031 }, + { "Not QSTA", 0x0032 }, + /* (Reserved) 0x0033 - 0x7FFF */ + { "Timeout", 0x8000 }, + { "Too Many Simultaneous Requests", 0x8001 }, + { "BSS Already Started Or Joined", 0x8002 }, + { "Not Supported", 0x8003 }, + { "Transmission Failure", 0x8004 }, + { "Refused Not Authenticated", 0x8005 }, + { "Reset Required Before Start", 0x8006 }, + { "LM Info Unavailable", 0x8007 }, + { NULL, -1 } +}; + +static const struct mlme_code Reason_codes[] = { + /* (Reserved) 0x0000 */ + { "Unspecified Reason", 0x0001 }, + { "Authentication Not Valid", 0x0002 }, + { "Deauthenticated Leave BSS", 0x0003 }, + { "Disassociated Inactivity", 0x0004 }, + { "AP Overload", 0x0005 }, + { "Class2 Frame Error", 0x0006 }, + { "Class3 Frame Error", 0x0007 }, + { "Disassociated Leave BSS", 0x0008 }, + { "Association Not Authenticated", 0x0009 }, + { "Disassociated Power Capability", 0x000A }, + { "Disassociated Supported Channels", 0x000B }, + /* (Reserved) 0x000C */ + { "Invalid Information Element", 0x000D }, + { "Michael MIC Failure", 0x000E }, + { "Fourway Handshake Timeout", 0x000F }, + { "Group Key Update Timeout", 0x0010 }, + { "Handshake Element Different", 0x0011 }, + { "Invalid Group Cipher", 0x0012 }, + { "Invalid Pairwise Cipher", 0x0013 }, + { "Invalid AKMP", 0x0014 }, + { "Unsupported RSN IE Version", 0x0015 }, + { "Invalid RSN IE Capabilities", 0x0016 }, + { "Dot1X Auth Failed", 0x0017 }, + { "Cipher Rejected By Policy", 0x0018 }, + /* (Reserved) 0x0019 - 0x001F */ + { "QoS Unspecified Reason", 0x0020 }, + { "QoS Insufficient Bandwidth", 0x0021 }, + { "QoS Excessive Not Ack", 0x0022 }, + { "QoS TXOP Limit Exceeded", 0x0023 }, + { "QSTA Leaving", 0x0024 }, + { "End TS, End DLS, End BA", 0x0025 }, + { "Unknown TS, Unknown DLS, Unknown BA", 0x0026 }, + { "Timeout", 0x0027 }, + /* (Reserved) 0x0028 - 0x002C */ + { "STAKey Mismatch", 0x002D }, + { NULL, -1 } +}; + + +static const char * +lookup_something(const struct mlme_code *n, int id) +{ + for (; n->name; n++) { + if (n->id == id) { + return n->name; + } + } + + /* not found */ + return NULL; +} /* lookup_something() */ + + +const char * +lookup_result_code(int result) +{ + static char fallback[16]; + const char *str; + + str = lookup_something(Result_codes, result); + + if (str == NULL) { + snprintf(fallback, 16, "%d", result); + str = fallback; + } + + return str; +} /* lookup_result_code() */ + + +/* + * --------------------------------------------------------------------------- + * lookup_reason + * + * Return a description string for a WiFi MLME ReasonCode. + * + * Arguments: + * reason The ReasonCode to interpret. + * + * Returns: + * Pointer to description string. + * --------------------------------------------------------------------------- + */ +const char * +lookup_reason_code(int reason) +{ + static char fallback[16]; + const char *str; + + str = lookup_something(Reason_codes, reason); + + if (str == NULL) { + snprintf(fallback, 16, "%d", reason); + str = fallback; + } + + return str; +} /* lookup_reason_code() */ + diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c new file mode 100644 index 000000000000..7648d2bbad43 --- /dev/null +++ b/drivers/staging/csr/monitor.c @@ -0,0 +1,458 @@ +/* + * --------------------------------------------------------------------------- + * FILE: monitor.c + * + * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + +#include "unifi_priv.h" + +#ifdef UNIFI_SNIFF_ARPHRD + + +#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) +#include +#endif + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW ETH_P_ALL +#endif + + + +/* + * --------------------------------------------------------------------------- + * uf_start_sniff + * + * Start UniFi capture in SNIFF mode, i.e capture everything it hears. + * + * Arguments: + * priv Pointer to device private context struct + * + * Returns: + * 0 on success or kernel error code + * --------------------------------------------------------------------------- + */ +int +uf_start_sniff(unifi_priv_t *priv) +{ + ul_client_t *pcli = priv->wext_client; + CSR_SIGNAL signal; + CSR_MLME_SNIFFJOIN_REQUEST *req = &signal.u.MlmeSniffjoinRequest; + int timeout = 1000; + int r; + + req->Ifindex = priv->if_index; + req->Channel = priv->wext_conf.channel; + req->ChannelStartingFactor = 0; + +#if 0 + printk("SniffJoin: Ifindex=%d, Channel=%d, ChannelStartingFactor=%d\n", + req->Ifindex, + req->Channel, + req->ChannelStartingFactor); +#endif + + signal.SignalPrimitiveHeader.SignalId = CSR_MLME_SNIFFJOIN_REQUEST_ID; + + r = unifi_mlme_blocking_request(priv, pcli, &signal, NULL, timeout); + if (r < 0) { + unifi_error(priv, "failed to send SNIFFJOIN request, error %d\n", r); + return r; + } + + r = pcli->reply_signal->u.MlmeSniffjoinConfirm.Resultcode; + if (r) { + unifi_notice(priv, "SNIFFJOIN request was rejected with result 0x%X (%s)\n", + r, lookup_result_code(r)); + return -EIO; + } + + return 0; +} /* uf_start_sniff() */ + + + +/* + * --------------------------------------------------------------------------- + * netrx_radiotap + * + * Reformat a UniFi SNIFFDATA signal into a radiotap packet. + * + * Arguments: + * priv OS private context pointer. + * ind Pointer to a MA_UNITDATA_INDICATION or + * DS_UNITDATA_INDICATION indication structure. + * + * Notes: + * Radiotap header values are all little-endian, UniFi signals will have + * been converted to host-endian. + * --------------------------------------------------------------------------- + */ +#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) +static void +netrx_radiotap(unifi_priv_t *priv, + const CSR_MA_SNIFFDATA_INDICATION *ind, + struct sk_buff *skb_orig) +{ + struct net_device *dev = priv->netdev; + struct sk_buff *skb = NULL; + unsigned char *ptr; + unsigned char *base; + int ind_data_len = skb_orig->len - 2 - ETH_HLEN; + struct unifi_rx_radiotap_header { + struct ieee80211_radiotap_header rt_hdr; + /* IEEE80211_RADIOTAP_TSFT */ + u64 rt_tsft; + /* IEEE80211_RADIOTAP_FLAGS */ + u8 rt_flags; + /* IEEE80211_RADIOTAP_RATE */ + u8 rt_rate; + /* IEEE80211_RADIOTAP_CHANNEL */ + u16 rt_chan; + u16 rt_chan_flags; + /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ + u8 rt_dbm_antsignal; + /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ + u8 rt_dbm_antnoise; + /* IEEE80211_RADIOTAP_ANTENNA */ + u8 rt_antenna; + + /* pad to 4-byte boundary */ + u8 pad[3]; + } __attribute__((__packed__)); + + struct unifi_rx_radiotap_header *unifi_rt; + int signal, noise, snr; + + func_enter(); + + if (ind_data_len <= 0) { + unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n"); + return; + } + + /* + * Allocate a SKB for the received data packet, including radiotap + * header. + */ + skb = dev_alloc_skb(ind_data_len + sizeof(struct unifi_rx_radiotap_header) + 4); + if (! skb) { + unifi_error(priv, "alloc_skb failed.\n"); + priv->stats.rx_errors++; + return; + } + + base = skb->data; + + /* Reserve the radiotap header at the front of skb */ + unifi_rt = (struct unifi_rx_radiotap_header *) + skb_put(skb, sizeof(struct unifi_rx_radiotap_header)); + + /* Copy in the 802.11 frame */ + ptr = skb_put(skb, ind_data_len); + memcpy(ptr, skb_orig->data, ind_data_len); + + unifi_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + unifi_rt->rt_hdr.it_pad = 0; /* always good to zero */ + unifi_rt->rt_hdr.it_len = sizeof(struct unifi_rx_radiotap_header); + + /* Big bitfield of all the fields we provide in radiotap */ + unifi_rt->rt_hdr.it_present = 0 + | (1 << IEEE80211_RADIOTAP_TSFT) + | (1 << IEEE80211_RADIOTAP_FLAGS) + | (1 << IEEE80211_RADIOTAP_RATE) + | (1 << IEEE80211_RADIOTAP_CHANNEL) + | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) + | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) + | (1 << IEEE80211_RADIOTAP_ANTENNA) + ; + + + /* No flags to set */ + unifi_rt->rt_tsft = (((u64)ind->Timestamp.x[7]) | (((u64)ind->Timestamp.x[6]) << 8) | + (((u64)ind->Timestamp.x[5]) << 16) | (((u64)ind->Timestamp.x[4]) << 24) | + (((u64)ind->Timestamp.x[3]) << 32) | (((u64)ind->Timestamp.x[2]) << 40) | + (((u64)ind->Timestamp.x[1]) << 48) | (((u64)ind->Timestamp.x[0]) << 56)); + + unifi_rt->rt_flags = 0; + + unifi_rt->rt_rate = ind->Rate; + + unifi_rt->rt_chan = cpu_to_le16(ieee80211chan2mhz(priv->wext_conf.channel)); + unifi_rt->rt_chan_flags = 0; + + /* Convert signal to dBm */ + signal = (s16)unifi2host_16(ind->Rssi); /* in dBm */ + snr = (s16)unifi2host_16(ind->Snr); /* in dB */ + noise = signal - snr; + + unifi_rt->rt_dbm_antsignal = signal; + unifi_rt->rt_dbm_antnoise = noise; + + unifi_rt->rt_antenna = ind->AntennaId; + + +#if 0 + printk("skb datalen=%d\n", skb->len); + dump(skb->data, 48); +#endif + + skb->dev = dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_80211_RAW); + memset(skb->cb, 0, sizeof(skb->cb)); + + /* Pass up to Linux network stack */ + netif_rx_ni(skb); + + dev->last_rx = jiffies; + + /* Bump the rx stats */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += ind_data_len; + + func_exit(); +} /* netrx_radiotap() */ +#endif /* RADIOTAP */ + + +/* + * --------------------------------------------------------------------------- + * netrx_prism + * + * Reformat a UniFi SNIFFDATA signal into a Prism format sniff packet. + * + * Arguments: + * priv OS private context pointer. + * ind Pointer to a MA_UNITDATA_INDICATION or + * DS_UNITDATA_INDICATION indication structure. + * + * Notes: + * Radiotap header values are all little-endian, UniFi signals will have + * been converted to host-endian. + * --------------------------------------------------------------------------- + */ +#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_PRISM) +static void +netrx_prism(unifi_priv_t *priv, + const CSR_MA_SNIFFDATA_INDICATION *ind, + struct sk_buff *skb_orig) +{ + struct net_device *dev = priv->netdev; + struct sk_buff *skb = NULL; + unsigned char *ptr; + unsigned char *base; + int ind_data_len = skb_orig->len - 2 - ETH_HLEN; +#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 +#define WLANCAP_MAGIC_COOKIE_V1 0x80211001 +#define WLANCAP_MAGIC_COOKIE_V2 0x80211002 + struct avs_header_v1 { + uint32 version; + uint32 length; + uint64 mactime; + uint64 hosttime; + uint32 phytype; + uint32 channel; + uint32 datarate; + uint32 antenna; + uint32 priority; + uint32 ssi_type; + int32 ssi_signal; + int32 ssi_noise; + uint32 preamble; + uint32 encoding; + } *avs; + int signal, noise, snr; + + func_enter(); + + if (ind_data_len <= 0) { + unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n"); + return; + } + +#if 0 + printk("MA-SINFFDATA.ind: DataLen=%d bytes, TSF %02X %02X %02X %02X %02X %02X %02X %02X, Rate=%d, Antenna=%d\n", + ind->Data.DataLength, + ind->Timestamp.x[0], + ind->Timestamp.x[1], + ind->Timestamp.x[2], + ind->Timestamp.x[3], + ind->Timestamp.x[4], + ind->Timestamp.x[5], + ind->Timestamp.x[6], + ind->Timestamp.x[7], + ind->Rate, + ind->Antenna); + + printk("payload, len %d\n", length); + dump((unsigned char *)payload, 32); +#endif + + /* + * Allocate a SKB for the received data packet, including radiotap + * header. + */ + skb = dev_alloc_skb(ind_data_len + sizeof(struct avs_header_v1) + 4); + if (! skb) { + unifi_error(priv, "alloc_skb failed.\n"); + priv->stats.rx_errors++; + return; + } + + base = skb->data; + + /* Reserve the radiotap header at the front of skb */ + avs = (struct avs_header_v1 *)skb_put(skb, sizeof(struct avs_header_v1)); + + /* Copy in the 802.11 frame */ + ptr = skb_put(skb, ind_data_len); + memcpy(ptr, skb_orig->data, ind_data_len); + + /* Convert signal to dBm */ + signal = 0x10000 - ((s16)unifi2host_16(ind->Rssi)); /* in dBm */ + snr = (s16)unifi2host_16(ind->Snr); /* in dB */ + noise = signal - snr; + + avs->version = htonl(WLANCAP_MAGIC_COOKIE_V1); + avs->length = htonl(sizeof(struct avs_header_v1)); + avs->mactime = __cpu_to_be64(ind->Timestamp); + avs->hosttime = __cpu_to_be64(jiffies); + avs->phytype = htonl(9); /* dss_ofdm_dot11_g */ + avs->channel = htonl(priv->wext_conf.channel); + avs->datarate = htonl(ind->Rate * 5); + avs->antenna = htonl(ind->Antenna); + avs->priority = htonl(0); /* unknown */ + avs->ssi_type = htonl(2); /* dBm */ + avs->ssi_signal = htonl(signal); + avs->ssi_noise = htonl(noise); + avs->preamble = htonl(0); /* unknown */ + avs->encoding = htonl(0); /* unknown */ + + +#if 0 + printk("skb datalen=%d\n", skb->len); + dump(skb->data, 48); +#endif + + skb->dev = dev; + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_80211_RAW); + memset(skb->cb, 0, sizeof(skb->cb)); + + /* Pass up to Linux network stack */ + netif_rx_ni(skb); + + dev->last_rx = jiffies; + + /* Bump the rx stats */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += ind_data_len; + + func_exit(); +} /* netrx_prism() */ +#endif /* PRISM */ + + +/* + * --------------------------------------------------------------------------- + * ma_sniffdata_ind + * + * Reformat a UniFi SNIFFDATA signal into a network + * + * Arguments: + * ospriv OS private context pointer. + * ind Pointer to a MA_UNITDATA_INDICATION or + * DS_UNITDATA_INDICATION indication structure. + * bulkdata Pointer to a bulk data structure, describing + * the data received. + * + * Notes: + * Radiotap header values are all little-endian, UniFi signals will have + * been converted to host-endian. + * --------------------------------------------------------------------------- + */ +void +ma_sniffdata_ind(void *ospriv, + const CSR_MA_SNIFFDATA_INDICATION *ind, + const bulk_data_param_t *bulkdata) +{ + unifi_priv_t *priv = ospriv; + struct net_device *dev = priv->netdev; + struct sk_buff *skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + + func_enter(); + + if (bulkdata->d[0].data_length == 0) { + unifi_warning(priv, "rx: MA-SNIFFDATA indication with zero bulk data\n"); + func_exit(); + return; + } + + skb->len = bulkdata->d[0].data_length; +#if 0 + printk("MA-SNIFFDATA.ind: DataLen=%d bytes, TSF %02X %02X %02X %02X %02X %02X %02X %02X, Rate=%d, Antenna=%d\n", + ind->Data.DataLength, + ind->Timestamp.x[0], + ind->Timestamp.x[1], + ind->Timestamp.x[2], + ind->Timestamp.x[3], + ind->Timestamp.x[4], + ind->Timestamp.x[5], + ind->Timestamp.x[6], + ind->Timestamp.x[7], + ind->Rate, + ind->AntennaId); + + printk("payload, len %lu\n", bulkdata->d[0].data_length); + if (bulkdata->d[0].os_data_ptr && (bulkdata->d[0].data_length >= 32)) { + dump((unsigned char *)bulkdata->d[0].os_data_ptr, 32); + } +#endif + + /* We only process data packets if the interface is open */ + if (unlikely(!netif_running(dev))) { + priv->stats.rx_dropped++; + priv->wext_conf.wireless_stats.discard.misc++; +#if 0 + printk("Dropping packet while interface is not up.\n"); +#endif + dev_kfree_skb(skb); + return; + } + + if (ind->ReceptionStatus) { + priv->stats.rx_dropped++; + priv->wext_conf.wireless_stats.discard.misc++; + printk(KERN_INFO "unifi: Dropping corrupt sniff packet\n"); + dev_kfree_skb(skb); + return; + } + +#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_PRISM) + netrx_prism(priv, ind, skb); +#endif /* PRISM */ + +#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) + netrx_radiotap(priv, ind, skb); +#endif /* RADIOTAP */ + + dev_kfree_skb(skb); + +} /* ma_sniffdata_ind() */ + + +#endif /* UNIFI_SNIFF_ARPHRD */ + diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c new file mode 100644 index 000000000000..b0335f6fff4e --- /dev/null +++ b/drivers/staging/csr/netdev.c @@ -0,0 +1,3902 @@ +/* + * --------------------------------------------------------------------------- + * FILE: netdev.c + * + * PURPOSE: + * This file provides the upper edge interface to the linux netdevice + * and wireless extensions. + * It is part of the porting exercise. + * + * Copyright (C) 2005-2010 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + + +/* + * Porting Notes: + * This file implements the data plane of the UniFi linux driver. + * + * All the Tx packets are passed to the HIP core lib, using the + * unifi_send_signal() API. For EAPOL packets use the MLME-EAPOL.req + * signal, for all other use the MLME-UNITDATA.req. The unifi_send_signal() + * expects the wire-formatted (packed) signal. For convenience, in the OS + * layer we only use the native (unpacked) signal structures. The HIP core lib + * provides the write_pack() helper function to convert to the packed signal. + * The packet is stored in the bulk data of the signal. We do not need to + * allocate new memory to store the packet, because unifi_net_data_malloc() + * is implemented to return a skb, which is the format of packet in Linux. + * The HIP core lib frees the bulk data buffers, so we do not need to do + * this in the OS layer. + * + * All the Rx packets are MLME-UNITDATA.ind signals, passed by the HIP core lib + * in unifi_receive_event(). We do not need to allocate an skb and copy the + * received packet because the HIP core lib has stored in memory allocated by + * unifi_net_data_malloc(). Also, we can perform the 802.11 to Ethernet + * translation in-place because we allocate the extra memory allocated in + * unifi_net_data_malloc(). + * + * If possible, the porting exercise should appropriately implement + * unifi_net_data_malloc() and unifi_net_data_free() to save copies between + * network and driver buffers. + */ + +#include +#include +#include +#include + +#include +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "unifi_priv.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +#include +#endif +#include + + +/* ALLOW_Q_PAUSE: Pre 2.6.28 kernels do not support multiple driver queues (required for QoS). + * In order to support QoS in these kernels, multiple queues are implemented in the driver. But since + * there is only a single queue in the kernel (leading to multiple queues in the driver) there is no possibility + * of stopping a particular queue in the kernel. Stopping the single kernel queue leads to undesirable starvation + * of driver queues. One of the proposals is to not stop the kernel queue but to prevent dequeuing from the + * 'stopped' driver queue. Allow q pause is an experimental implementation of this scheme for pre 2.6.28 kernels. + * When NOT defined, queues are paused locally in the driver and packets are dequeued for transmission only from the + * unpaused queues. When Allow q pause is defined the kernel queue is stopped whenever any driver queue is paused. + */ +#define ALLOW_Q_PAUSE + +#define ieee2host16(n) __le16_to_cpu(n) +#define ieee2host32(n) __le32_to_cpu(n) +#define host2ieee16(n) __cpu_to_le16(n) +#define host2ieee32(n) __cpu_to_le32(n) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +#ifdef UNIFI_NET_NAME +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + static char name[8]; \ + sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ + _dev = alloc_netdev_mq(_size, name, _setup, _num_of_queues); \ + } while (0); +#else +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + _dev = alloc_etherdev_mq(_size, _num_of_queues); \ + } while (0); +#endif /* UNIFI_NET_NAME */ +#else +#ifdef UNIFI_NET_NAME +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + static char name[8]; \ + sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ + _dev = alloc_netdev(_size, name, _setup); \ + } while (0); +#else +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + _dev = alloc_etherdev(_size); \ + } while (0); +#endif /* UNIFI_NET_NAME */ +#endif /* LINUX_VERSION_CODE */ + + +/* Wext handler is suported only if CSR_SUPPORT_WEXT is defined */ +#ifdef CSR_SUPPORT_WEXT +extern struct iw_handler_def unifi_iw_handler_def; +#endif /* CSR_SUPPORT_WEXT */ +static void check_ba_frame_age_timeout( unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session); +static void process_ba_frame(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + frame_desc_struct *frame_desc); +static void process_ba_complete(unifi_priv_t *priv, netInterface_priv_t *interfacePriv); +static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata); +static void process_amsdu(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata); +static int uf_net_open(struct net_device *dev); +static int uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int uf_net_stop(struct net_device *dev); +static struct net_device_stats *uf_net_get_stats(struct net_device *dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +static u16 uf_net_select_queue(struct net_device *dev, struct sk_buff *skb); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +static netdev_tx_t uf_net_xmit(struct sk_buff *skb, struct net_device *dev); +#else +static int uf_net_xmit(struct sk_buff *skb, struct net_device *dev); +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif +#endif +static void uf_set_multicast_list(struct net_device *dev); + + +typedef int (*tx_signal_handler)(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, CSR_PRIORITY priority); + +#ifdef CONFIG_NET_SCHED +/* + * Queueing Discipline Interface + * Only used if kernel is configured with CONFIG_NET_SCHED + */ + +/* + * The driver uses the qdisc interface to buffer and control all + * outgoing traffic. We create a root qdisc, register our qdisc operations + * and later we create two subsiduary pfifo queues for the uncontrolled + * and controlled ports. + * + * The network stack delivers all outgoing packets in our enqueue handler. + * There, we classify the packet and decide whether to store it or drop it + * (if the controlled port state is set to "discard"). + * If the packet is enqueued, the network stack call our dequeue handler. + * There, we decide whether we can send the packet, delay it or drop it + * (the controlled port configuration might have changed meanwhile). + * If a packet is dequeued, then the network stack calls our hard_start_xmit + * handler where finally we send the packet. + * + * If the hard_start_xmit handler fails to send the packet, we return + * NETDEV_TX_BUSY and the network stack call our requeue handler where + * we put the packet back in the same queue in came from. + * + */ + +struct uf_sched_data +{ + /* Traffic Classifier TBD */ + struct tcf_proto *filter_list; + /* Our two queues */ + struct Qdisc *queues[UNIFI_TRAFFIC_Q_MAX]; +}; + +struct uf_tx_packet_data { + /* Queue the packet is stored in */ + unifi_TrafficQueue queue; + /* QoS Priority determined when enqueing packet */ + CSR_PRIORITY priority; + /* Debug */ + unsigned long host_tag; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd); +static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd); +static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd); +static void uf_qdiscop_reset(struct Qdisc* qd); +static void uf_qdiscop_destroy(struct Qdisc* qd); +static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt); +static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt); +#else +static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt); +static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt); +#endif +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +/* queueing discipline operations */ +static struct Qdisc_ops uf_qdisc_ops = +{ + .next = NULL, + .cl_ops = NULL, + .id = "UniFi Qdisc", + .priv_size = sizeof(struct uf_sched_data), + + .enqueue = uf_qdiscop_enqueue, + .dequeue = uf_qdiscop_dequeue, + .requeue = uf_qdiscop_requeue, + .drop = NULL, /* drop not needed since we are always the root qdisc */ + + .init = uf_qdiscop_init, + .reset = uf_qdiscop_reset, + .destroy = uf_qdiscop_destroy, + .change = uf_qdiscop_tune, + + .dump = uf_qdiscop_dump, +}; +#endif /* LINUX_VERSION_CODE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, netdev_get_tx_queue(_dev, 0), _ops, _root) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, _ops, _root) +#else +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, _ops) +#endif /* LINUX_VERSION_CODE */ + +#endif /* CONFIG_NET_SCHED */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static const struct net_device_ops uf_netdev_ops = +{ + .ndo_open = uf_net_open, + .ndo_stop = uf_net_stop, + .ndo_start_xmit = uf_net_xmit, + .ndo_do_ioctl = uf_net_ioctl, + .ndo_get_stats = uf_net_get_stats, /* called by /proc/net/dev */ + .ndo_set_rx_mode = uf_set_multicast_list, + .ndo_select_queue = uf_net_select_queue, +}; +#endif + +static u8 oui_rfc1042[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; +static u8 oui_8021h[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; + + +/* Callback for event logging to blocking clients */ +static void netdev_mlme_event_handler(ul_client_t *client, + const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata, + int dir); + +#ifdef CSR_SUPPORT_WEXT +/* Declare netdev_notifier block which will contain the state change + * handler callback function + */ +static struct notifier_block uf_netdev_notifier; +#endif + +/* + * --------------------------------------------------------------------------- + * uf_alloc_netdevice + * + * Allocate memory for the net_device and device private structs + * for this interface. + * Fill in the fields, but don't register the interface yet. + * We need to configure the UniFi first. + * + * Arguments: + * sdio_dev Pointer to SDIO context handle to use for all + * SDIO ops. + * bus_id A small number indicating the SDIO card position on the + * bus. Typically this is the slot number, e.g. 0, 1 etc. + * Valid values are 0 to MAX_UNIFI_DEVS-1. + * + * Returns: + * Pointer to device private struct. + * + * Notes: + * The net_device and device private structs are allocated together + * and should be freed by freeing the net_device pointer. + * --------------------------------------------------------------------------- + */ +unifi_priv_t * +uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) +{ + struct net_device *dev; + unifi_priv_t *priv; + netInterface_priv_t *interfacePriv; +#ifdef CSR_SUPPORT_WEXT + int rc; +#endif + unsigned char i; /* loop index */ + + /* + * Allocate netdevice struct, assign name template and + * setup as an ethernet device. + * The net_device and private structs are zeroed. Ether_setup() then + * sets up ethernet handlers and values. + * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, + * so use "eth*" (like other wireless extns drivers). + */ + UF_ALLOC_NETDEV(dev, sizeof(unifi_priv_t)+sizeof(netInterface_priv_t), "%d", ether_setup, UNIFI_TRAFFIC_Q_MAX); + + if (dev == NULL) { + return NULL; + } + + /* Set up back pointer from priv to netdev */ + interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + priv = (unifi_priv_t *)(interfacePriv + 1); + interfacePriv->privPtr = priv; + interfacePriv->InterfaceTag = 0; + + + /* Initialize all supported netdev interface to be NULL */ + for(i=0; inetdev[i] = NULL; + priv->interfacePriv[i] = NULL; + } + priv->netdev[0] = dev; + priv->interfacePriv[0] = interfacePriv; + + /* Setup / override net_device fields */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + dev->netdev_ops = &uf_netdev_ops; +#else + dev->open = uf_net_open; + dev->stop = uf_net_stop; + dev->hard_start_xmit = uf_net_xmit; + dev->do_ioctl = uf_net_ioctl; + + /* called by /proc/net/dev */ + dev->get_stats = uf_net_get_stats; + + dev->set_multicast_list = uf_set_multicast_list; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + dev->select_queue = uf_net_select_queue; +#endif +#endif + +#ifdef CSR_SUPPORT_WEXT + dev->wireless_handlers = &unifi_iw_handler_def; +#if IW_HANDLER_VERSION < 6 + dev->get_wireless_stats = unifi_get_wireless_stats; +#endif /* IW_HANDLER_VERSION */ +#endif /* CSR_SUPPORT_WEXT */ + + /* This gives us enough headroom to add the 802.11 header */ + dev->needed_headroom = 32; + + /* Use bus_id as instance number */ + priv->instance = bus_id; + /* Store SDIO pointer to pass in the core */ + priv->sdio = sdio_dev; + + sdio_dev->driverData = (void*)priv; + /* Consider UniFi to be uninitialised */ + priv->init_progress = UNIFI_INIT_NONE; + + priv->prev_queue = 0; + + /* + * Initialise the clients structure array. + * We do not need protection around ul_init_clients() because + * the character device can not be used until uf_alloc_netdevice() + * returns and Unifi_instances[bus_id]=priv is set, since unifi_open() + * will return -ENODEV. + */ + ul_init_clients(priv); + + /* + * Register a new ul client to send the multicast list signals. + * Note: priv->instance must be set before calling this. + */ + priv->netdev_client = ul_register_client(priv, + 0, + netdev_mlme_event_handler); + if (priv->netdev_client == NULL) { + unifi_error(priv, + "Failed to register a unifi client for background netdev processing\n"); + free_netdev(priv->netdev[0]); + return NULL; + } + unifi_trace(priv, UDBG2, "Netdev %p client (id:%d s:0x%X) is registered\n", + dev, priv->netdev_client->client_id, priv->netdev_client->sender_id); + + priv->sta_wmm_capabilities = 0; + + priv->wapi_multicast_filter = 0; + priv->wapi_unicast_filter = 0; + priv->wapi_unicast_queued_pkt_filter = 0; + + /* Enable all queues by default */ + interfacePriv->queueEnabled[0] = 1; + interfacePriv->queueEnabled[1] = 1; + interfacePriv->queueEnabled[2] = 1; + interfacePriv->queueEnabled[3] = 1; + +#ifdef CSR_SUPPORT_SME + priv->allPeerDozing = 0; +#endif + /* + * Initialise the OS private struct. + */ + /* + * Instead of deciding in advance to use 11bg or 11a, we could do a more + * clever scan on both radios. + */ + if (use_5g) { + priv->if_index = CSR_INDEX_5G; + unifi_info(priv, "Using the 802.11a radio\n"); + } else { + priv->if_index = CSR_INDEX_2G4; + } + + /* Initialise bh thread structure */ + priv->bh_thread.thread_task = NULL; + priv->bh_thread.block_thread = 1; + init_waitqueue_head(&priv->bh_thread.wakeup_q); + priv->bh_thread.wakeup_flag = 0; + sprintf(priv->bh_thread.name, "uf_bh_thread"); + + /* reset the connected state for the interface */ + interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ + +#ifdef USE_DRIVER_LOCK +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) + sema_init(&priv->lock, 1); +#else + init_MUTEX(&priv->lock); +#endif +#endif /* USE_DRIVER_LOCK */ + + spin_lock_init(&priv->send_signal_lock); + + spin_lock_init(&priv->m4_lock); + spin_lock_init(&priv->ba_lock); + +#ifdef CSR_SUPPORT_SME + spin_lock_init(&priv->staRecord_lock); + spin_lock_init(&priv->tx_q_lock); +#endif + + /* Create the Traffic Analysis workqueue */ + priv->unifi_workqueue = create_singlethread_workqueue("unifi_workq"); + if (priv->unifi_workqueue == NULL) { + /* Deregister priv->netdev_client */ + ul_deregister_client(priv->netdev_client); + free_netdev(priv->netdev[0]); + return NULL; + } + +#ifdef CSR_SUPPORT_SME + /* Create the Multicast Addresses list work structure */ + INIT_WORK(&priv->multicast_list_task, uf_multicast_list_wq); + + /* Create m4 buffering work structure */ + INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* Register the qdisc operations */ + register_qdisc(&uf_qdisc_ops); +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + + priv->ref_count = 1; + + + priv->amp_client = NULL; + priv->coredump_mode = 0; + priv->ptest_mode = 0; + priv->wol_suspend = FALSE; + INIT_LIST_HEAD(&interfacePriv->rx_uncontrolled_list); + INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); + sema_init(&priv->rx_q_sem, 1); + +#ifdef CSR_SUPPORT_WEXT + interfacePriv->netdev_callback_registered = FALSE; + interfacePriv->wait_netdev_change = FALSE; + /* Register callback for netdevice state changes */ + if ((rc = register_netdevice_notifier(&uf_netdev_notifier)) == 0) { + interfacePriv->netdev_callback_registered = TRUE; + } + else { + unifi_warning(priv, "Failed to register netdevice notifier : %d %p\n", rc, dev); + } +#endif /* CSR_SUPPORT_WEXT */ + + return priv; +} /* uf_alloc_netdevice() */ + +/* + *--------------------------------------------------------------------------- + * uf_alloc_netdevice_for_other_interfaces + * + * Allocate memory for the net_device and device private structs + * for this interface. + * Fill in the fields, but don't register the interface yet. + * We need to configure the UniFi first. + * + * Arguments: + * interfaceTag Interface number. + * sdio_dev Pointer to SDIO context handle to use for all + * SDIO ops. + * bus_id A small number indicating the SDIO card position on the + * bus. Typically this is the slot number, e.g. 0, 1 etc. + * Valid values are 0 to MAX_UNIFI_DEVS-1. + * + * Returns: + * Pointer to device private struct. + * + * Notes: + * The device private structure contains the interfaceTag and pointer to the unifi_priv + * structure created allocated by net_device od interface0. + * The net_device and device private structs are allocated together + * and should be freed by freeing the net_device pointer. + * --------------------------------------------------------------------------- + */ +CsrBool +uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + struct net_device *dev; + netInterface_priv_t *interfacePriv; + + /* + * Allocate netdevice struct, assign name template and + * setup as an ethernet device. + * The net_device and private structs are zeroed. Ether_setup() then + * sets up ethernet handlers and values. + * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, + * so use "eth*" (like other wireless extns drivers). + */ + UF_ALLOC_NETDEV(dev, sizeof(netInterface_priv_t), "%d", ether_setup, 1); + if (dev == NULL) { + return FALSE; + } + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_alloc_netdevice_for_other_interfaces bad interfaceTag\n"); + return FALSE; + } + + /* Set up back pointer from priv to netdev */ + interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + interfacePriv->privPtr = priv; + interfacePriv->InterfaceTag = interfaceTag; + priv->netdev[interfaceTag] = dev; + priv->interfacePriv[interfacePriv->InterfaceTag] = interfacePriv; + + /* reset the connected state for the interface */ + interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ + INIT_LIST_HEAD(&interfacePriv->rx_uncontrolled_list); + INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); + + /* Setup / override net_device fields */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + dev->netdev_ops = &uf_netdev_ops; +#else + dev->open = uf_net_open; + dev->stop = uf_net_stop; + dev->hard_start_xmit = uf_net_xmit; + dev->do_ioctl = uf_net_ioctl; + + /* called by /proc/net/dev */ + dev->get_stats = uf_net_get_stats; + + dev->set_multicast_list = uf_set_multicast_list; +#endif + +#ifdef CSR_SUPPORT_WEXT + dev->wireless_handlers = &unifi_iw_handler_def; +#if IW_HANDLER_VERSION < 6 + dev->get_wireless_stats = unifi_get_wireless_stats; +#endif /* IW_HANDLER_VERSION */ +#endif /* CSR_SUPPORT_WEXT */ + return TRUE; +} /* uf_alloc_netdevice() */ + + + +/* + * --------------------------------------------------------------------------- + * uf_free_netdevice + * + * Unregister the network device and free the memory allocated for it. + * NB This includes the memory for the priv struct. + * + * Arguments: + * priv Device private pointer. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +int +uf_free_netdevice(unifi_priv_t *priv) +{ + int i; + unsigned long flags; + + func_enter(); + + unifi_trace(priv, UDBG1, "uf_free_netdevice\n"); + + if (!priv) { + return -EINVAL; + } + + /* + * Free any buffers used for holding firmware + */ + uf_release_firmware_files(priv); + +#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) + if (priv->connection_config.mlmeAssociateReqInformationElements) { + kfree(priv->connection_config.mlmeAssociateReqInformationElements); + } + priv->connection_config.mlmeAssociateReqInformationElements = NULL; + priv->connection_config.mlmeAssociateReqInformationElementsLength = 0; + + if (priv->mib_data.length) { + vfree(priv->mib_data.data); + } + priv->mib_data.data = NULL; + priv->mib_data.length = 0; + +#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/ + + /* Free any bulkdata buffers allocated for M4 caching */ + spin_lock_irqsave(&priv->m4_lock, flags); + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; + if (interfacePriv->m4_bulk_data.data_length > 0) { + unifi_trace(priv, UDBG5, "uf_free_netdevice: free M4 bulkdata %d\n", i); + unifi_net_data_free(priv, &interfacePriv->m4_bulk_data); + } + } + spin_unlock_irqrestore(&priv->m4_lock, flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* Unregister the qdisc operations */ + unregister_qdisc(&uf_qdisc_ops); +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + +#ifdef CSR_SUPPORT_WEXT + /* Unregister callback for netdevice state changes */ + unregister_netdevice_notifier(&uf_netdev_notifier); +#endif /* CSR_SUPPORT_WEXT */ + +#ifdef CSR_SUPPORT_SME + /* Cancel work items and destroy the workqueue */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + cancel_work_sync(&priv->multicast_list_task); +#endif +#endif +/* Destroy the workqueues. */ + flush_workqueue(priv->unifi_workqueue); + destroy_workqueue(priv->unifi_workqueue); + + /* Free up netdev in reverse order: priv is allocated with netdev[0]. + * So, netdev[0] should be freed after all other netdevs are freed up + */ + for (i=CSR_WIFI_NUM_INTERFACES-1; i>=0; i--) { + /*Free the netdev struct and priv, which are all one lump*/ + if (priv->netdev[i]) { + unifi_error(priv, "uf_free_netdevice: netdev %d %p\n", i, priv->netdev[i]); + free_netdev(priv->netdev[i]); + } + } + + func_exit(); + return 0; +} /* uf_free_netdevice() */ + + +/* + * --------------------------------------------------------------------------- + * uf_net_open + * + * Called when userland does "ifconfig wlan0 up". + * + * Arguments: + * dev Device pointer. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static int +uf_net_open(struct net_device *dev) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + func_enter(); + + /* If we haven't finished UniFi initialisation, we can't start */ + if (priv->init_progress != UNIFI_INIT_COMPLETED) { + unifi_warning(priv, "%s: unifi not ready, failing net_open\n", __FUNCTION__); + return -EINVAL; + } + +#if (defined CSR_NATIVE_LINUX) && (defined UNIFI_SNIFF_ARPHRD) && defined(CSR_SUPPORT_WEXT) + /* + * To sniff, the user must do "iwconfig mode monitor", which sets + * priv->wext_conf.mode to IW_MODE_MONITOR. + * Then he/she must do "ifconfig ethn up", which calls this fn. + * There is no point in starting the sniff with SNIFFJOIN until + * this point. + */ + if (priv->wext_conf.mode == IW_MODE_MONITOR) { + int err; + err = uf_start_sniff(priv); + if (err) { + return err; + } + netif_carrier_on(dev); + } +#endif + +#ifdef CSR_SUPPORT_WEXT + if (interfacePriv->wait_netdev_change) { + unifi_trace(priv, UDBG1, "%s: Waiting for NETDEV_CHANGE, assume connected\n", + __FUNCTION__); + interfacePriv->connected = UnifiConnected; + interfacePriv->wait_netdev_change = FALSE; + } +#endif + + UF_NETIF_TX_START_ALL_QUEUES(dev); + + func_exit(); + return 0; +} /* uf_net_open() */ + + +static int +uf_net_stop(struct net_device *dev) +{ +#if defined(CSR_NATIVE_LINUX) && defined(UNIFI_SNIFF_ARPHRD) && defined(CSR_SUPPORT_WEXT) + netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + func_enter(); + + /* Stop sniffing if in Monitor mode */ + if (priv->wext_conf.mode == IW_MODE_MONITOR) { + if (priv->card) { + int err; + err = unifi_reset_state(priv, dev->dev_addr, 1); + if (err) { + return err; + } + } + } +#else + func_enter(); +#endif + + UF_NETIF_TX_STOP_ALL_QUEUES(dev); + + func_exit(); + return 0; +} /* uf_net_stop() */ + + +/* This is called after the WE handlers */ +static int +uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc; + + rc = -EOPNOTSUPP; + + return rc; +} /* uf_net_ioctl() */ + + + +static struct net_device_stats * +uf_net_get_stats(struct net_device *dev) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + + return &interfacePriv->stats; +} /* uf_net_get_stats() */ + +static CSR_PRIORITY uf_get_packet_priority(unifi_priv_t *priv, netInterface_priv_t *interfacePriv, struct sk_buff *skb, const int proto) +{ + CSR_PRIORITY priority = CSR_CONTENTION; + + func_enter(); + priority = (CSR_PRIORITY) (skb->priority >> 5); + + if (priority == CSR_QOS_UP0) { /* 0 */ + + unifi_trace(priv, UDBG5, "uf_get_packet_priority: proto = 0x%.4X\n", proto); + + switch (proto) { + case 0x0800: /* IPv4 */ + case 0x814C: /* SNMP */ + case 0x880C: /* GSMP */ + priority = (CSR_PRIORITY) (skb->data[1 + ETH_HLEN] >> 5); + break; + + case 0x8100: /* VLAN */ + priority = (CSR_PRIORITY) (skb->data[0 + ETH_HLEN] >> 5); + break; + + case 0x86DD: /* IPv6 */ + priority = (CSR_PRIORITY) ((skb->data[0 + ETH_HLEN] & 0x0E) >> 1); + break; + + default: + priority = CSR_QOS_UP0; + break; + } + } + + /* Check if we are allowed to transmit on this AC. Because of ACM we may have to downgrade to a lower + * priority */ + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) { + unifi_TrafficQueue queue; + + /* Keep trying lower priorities until we find a queue + * Priority to queue mapping is 1,2 - BK, 0,3 - BE, 4,5 - VI, 6,7 - VO */ + queue = unifi_frame_priority_to_queue(priority); + + while (queue > UNIFI_TRAFFIC_Q_BK && !interfacePriv->queueEnabled[queue]) { + queue--; + priority = unifi_get_default_downgrade_priority(queue); + } + } + + unifi_trace(priv, UDBG5, "Packet priority = %d\n", priority); + + func_exit(); + return priority; +} + +/* + */ +/* + * --------------------------------------------------------------------------- + * get_packet_priority + * + * Arguments: + * priv private data area of functional driver + * skb socket buffer + * ehdr ethernet header to fetch protocol + * interfacePriv For accessing station record database + * + * + * Returns: + * CSR_PRIORITY. + * --------------------------------------------------------------------------- + */ +CSR_PRIORITY +get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, netInterface_priv_t *interfacePriv) +{ + CSR_PRIORITY priority = CSR_CONTENTION; + const int proto = ntohs(ehdr->h_proto); + + CsrUint8 interfaceMode = interfacePriv->interfaceMode; + + func_enter(); + + /* Priority Mapping for all the Modes */ + switch(interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + unifi_trace(priv, UDBG4, "mode is STA \n"); + if ((priv->sta_wmm_capabilities & QOS_CAPABILITY_WMM_ENABLED) == 1) { + priority = uf_get_packet_priority(priv, interfacePriv, skb, proto); + } else { + priority = CSR_CONTENTION; + } + break; +#ifdef CSR_SUPPORT_SME + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + { + CsrWifiRouterCtrlStaInfo_t * dstStaInfo = + CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,ehdr->h_dest, interfacePriv->InterfaceTag); + unifi_trace(priv, UDBG4, "mode is AP \n"); + if (!(ehdr->h_dest[0] & 0x01) && dstStaInfo && dstStaInfo->wmmOrQosEnabled) { + /* If packet is not Broadcast/multicast */ + priority = uf_get_packet_priority(priv, interfacePriv, skb, proto); + } else { + /* Since packet destination is not QSTA, set priority to CSR_CONTENTION */ + unifi_trace(priv, UDBG4, "Destination is not QSTA or BroadCast/Multicast\n"); + priority = CSR_CONTENTION; + } + } + break; +#endif + default: + unifi_trace(priv, UDBG3, " mode unknown in %s func, mode=%x\n", __FUNCTION__, interfaceMode); + } + unifi_trace(priv, UDBG5, "priority = %x\n", priority); + + func_exit(); + return priority; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +/* + * --------------------------------------------------------------------------- + * uf_net_select_queue + * + * Called by the kernel to select which queue to put the packet in + * + * Arguments: + * dev Device pointer + * skb Packet + * + * Returns: + * Queue index + * --------------------------------------------------------------------------- + */ +static u16 +uf_net_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = (unifi_priv_t *)interfacePriv->privPtr; + struct ethhdr ehdr; + unifi_TrafficQueue queue; + int proto; + CSR_PRIORITY priority; + + func_enter(); + + memcpy(&ehdr, skb->data, ETH_HLEN); + proto = ntohs(ehdr.h_proto); + + /* 802.1x - apply controlled/uncontrolled port rules */ + if ((proto != ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + && (proto != ETH_P_WAI) +#endif + ) { + /* queues 0 - 3 */ + priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); + queue = unifi_frame_priority_to_queue(priority); + } else { + /* queue 4 */ + queue = UNIFI_TRAFFIC_Q_EAPOL; + } + + + func_exit(); + return (u16)queue; +} /* uf_net_select_queue() */ +#endif + +int +skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto) +{ + llc_snap_hdr_t *snap; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int headroom; + + /* get the headroom available in skb */ + headroom = skb_headroom(skb); + /* step 1: classify ether frame, DIX or 802.3? */ + + if (proto < 0x600) { + /* codes <= 1500 reserved for 802.3 lengths */ + /* it's 802.3, pass ether payload unchanged, */ + unifi_trace(priv, UDBG3, "802.3 len: %d\n", skb->len); + + /* leave off any PAD octets. */ + skb_trim(skb, proto); + } else if (proto == ETH_P_8021Q) { + + /* Store the VLAN SNAP (should be 87-65). */ + u16 vlan_snap = *(u16*)skb->data; + /* check for headroom availability before skb_push 14 = (4 + 10) */ + if (headroom < 14) { + unifi_trace(priv, UDBG3, "cant append vlan snap: debug\n"); + return -1; + } + /* Add AA-AA-03-00-00-00 */ + snap = (llc_snap_hdr_t *)skb_push(skb, 4); + snap->dsap = snap->ssap = 0xAA; + snap->ctrl = 0x03; + memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); + + /* Add AA-AA-03-00-00-00 */ + snap = (llc_snap_hdr_t *)skb_push(skb, 10); + snap->dsap = snap->ssap = 0xAA; + snap->ctrl = 0x03; + memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); + + /* Add the VLAN specific information */ + snap->protocol = htons(proto); + *(u16*)(snap + 1) = vlan_snap; + + } else + { + /* it's DIXII, time for some conversion */ + unifi_trace(priv, UDBG3, "DIXII len: %d\n", skb->len); + + /* check for headroom availability before skb_push */ + if (headroom < sizeof(llc_snap_hdr_t)) { + unifi_trace(priv, UDBG3, "cant append snap: debug\n"); + return -1; + } + /* tack on SNAP */ + snap = (llc_snap_hdr_t *)skb_push(skb, sizeof(llc_snap_hdr_t)); + snap->dsap = snap->ssap = 0xAA; + snap->ctrl = 0x03; + /* Use the appropriate OUI. */ + if ((proto == ETH_P_AARP) || (proto == ETH_P_IPX)) { + memcpy(snap->oui, oui_8021h, P80211_OUI_LEN); + } else { + memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); + } + snap->protocol = htons(proto); + } + + return 0; +} /* skb_add_llc_snap() */ + +#ifdef CSR_SUPPORT_SME +static int +_identify_sme_ma_pkt_ind(unifi_priv_t *priv, + const CsrInt8 *oui, CsrUint16 protocol, + const CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata, + const unsigned char *daddr, + const unsigned char *saddr) +{ + CSR_MA_PACKET_INDICATION *pkt_ind = (CSR_MA_PACKET_INDICATION*)&signal->u.MaPacketIndication; + int r; + CsrUint8 i; + + unifi_trace(priv, UDBG5, + "_identify_sme_ma_pkt_ind -->\n"); + for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { + if (priv->sme_unidata_ind_filters[i].in_use) { + if (!memcmp(oui, priv->sme_unidata_ind_filters[i].oui, 3) && + (protocol == priv->sme_unidata_ind_filters[i].protocol)) { + + /* Send to client */ + if (priv->sme_cli) { + /* + * Pass the packet to the SME, using unifi_sys_ma_unitdata_ind(). + * The frame needs to be converted according to the encapsulation. + */ + unifi_trace(priv, UDBG1, + "_identify_sme_ma_pkt_ind: handle=%d, encap=%d, proto=%x\n", + i, priv->sme_unidata_ind_filters[i].encapsulation, + priv->sme_unidata_ind_filters[i].protocol); + if (priv->sme_unidata_ind_filters[i].encapsulation == CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET) { + struct sk_buff *skb; + /* The translation is performed on skb... */ + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + skb->len = bulkdata->d[0].data_length; + + unifi_trace(priv, UDBG1, + "_identify_sme_ma_pkt_ind: skb_80211_to_ether -->\n"); + r = skb_80211_to_ether(priv, skb, daddr, saddr, + signal, bulkdata); + unifi_trace(priv, UDBG1, + "_identify_sme_ma_pkt_ind: skb_80211_to_ether <--\n"); + if (r) { + return -EINVAL; + } + + /* ... but we indicate buffer and length */ + bulkdata->d[0].os_data_ptr = skb->data; + bulkdata->d[0].data_length = skb->len; + } else { + /* Add the MAC addresses before the SNAP */ + bulkdata->d[0].os_data_ptr -= 2*ETH_ALEN; + bulkdata->d[0].data_length += 2*ETH_ALEN; + memcpy((void*)bulkdata->d[0].os_data_ptr, daddr, ETH_ALEN); + memcpy((void*)bulkdata->d[0].os_data_ptr + ETH_ALEN, saddr, ETH_ALEN); + } + + unifi_trace(priv, UDBG1, + "_identify_sme_ma_pkt_ind: unifi_sys_ma_pkt_ind -->\n"); + CsrWifiRouterMaPacketIndSend(priv->sme_unidata_ind_filters[i].appHandle, + (pkt_ind->VirtualInterfaceIdentifier & 0xff), + i, + pkt_ind->ReceptionStatus, + bulkdata->d[0].data_length, + (CsrUint8*)bulkdata->d[0].os_data_ptr, + NULL, + pkt_ind->Rssi, + pkt_ind->Snr, + pkt_ind->ReceivedRate); + + + unifi_trace(priv, UDBG1, + "_identify_sme_ma_pkt_ind: unifi_sys_ma_pkt_ind <--\n"); + } + + return 1; + } + } + } + + return -1; +} +#endif /* CSR_SUPPORT_SME */ + +/* + * --------------------------------------------------------------------------- + * skb_80211_to_ether + * + * Make sure the received frame is in Ethernet (802.3) form. + * De-encapsulates SNAP if necessary, adds a ethernet header. + * The source buffer should not contain an 802.11 MAC header + * + * Arguments: + * payload Pointer to packet data received from UniFi. + * payload_length Number of bytes of data received from UniFi. + * daddr Destination MAC address. + * saddr Source MAC address. + * + * Returns: + * 0 on success, -1 if the packet is bad and should be dropped, + * 1 if the packet was forwarded to the SME or AMP client. + * --------------------------------------------------------------------------- + */ +int +skb_80211_to_ether(unifi_priv_t *priv, struct sk_buff *skb, + const unsigned char *daddr, const unsigned char *saddr, + const CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata) +{ + unsigned char *payload; + int payload_length; + struct ethhdr *eth; + llc_snap_hdr_t *snap; + int headroom; +#define UF_VLAN_LLC_HEADER_SIZE 18 + static const u8 vlan_inner_snap[] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 }; +#if defined(CSR_NATIVE_SOFTMAC) && defined(CSR_SUPPORT_SME) + const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; +#endif + + if(skb== NULL || daddr == NULL || saddr == NULL){ + unifi_error(priv,"skb_80211_to_ether: PBC fail\n"); + return 1; + } + + payload = skb->data; + payload_length = skb->len; + + snap = (llc_snap_hdr_t *)payload; + eth = (struct ethhdr *)payload; + + /* get the skb headroom size */ + headroom = skb_headroom(skb); + + /* + * Test for the various encodings + */ + if ((payload_length >= sizeof(llc_snap_hdr_t)) && + (snap->dsap == 0xAA) && + (snap->ssap == 0xAA) && + (snap->ctrl == 0x03) && + (snap->oui[0] == 0) && + (snap->oui[1] == 0) && + ((snap->oui[2] == 0) || (snap->oui[2] == 0xF8))) + { + /* AppleTalk AARP (2) or IPX SNAP */ + if ((snap->oui[2] == 0) && + ((ntohs(snap->protocol) == ETH_P_AARP) || (ntohs(snap->protocol) == ETH_P_IPX))) + { + u16 len; + + unifi_trace(priv, UDBG3, "%s len: %d\n", + (ntohs(snap->protocol) == ETH_P_AARP) ? "ETH_P_AARP" : "ETH_P_IPX", + payload_length); + + /* check for headroom availability before skb_push */ + if (headroom < (2 * ETH_ALEN + 2)) { + unifi_warning(priv, "headroom not available to skb_push ether header\n"); + return -1; + } + + /* Add 802.3 header and leave full payload */ + len = htons(skb->len); + memcpy(skb_push(skb, 2), &len, 2); + memcpy(skb_push(skb, ETH_ALEN), saddr, ETH_ALEN); + memcpy(skb_push(skb, ETH_ALEN), daddr, ETH_ALEN); + + return 0; + } + /* VLAN-tagged IP */ + if ((snap->oui[2] == 0) && (ntohs(snap->protocol) == ETH_P_8021Q)) + { + /* + * The translation doesn't change the packet length, so is done in-place. + * + * Example header (from Std 802.11-2007 Annex M): + * AA-AA-03-00-00-00-81-00-87-65-AA-AA-03-00-00-00-08-06 + * -------SNAP-------p1-p1-ll-ll-------SNAP--------p2-p2 + * dd-dd-dd-dd-dd-dd-aa-aa-aa-aa-aa-aa-p1-p1-ll-ll-p2-p2 + * dd-dd-dd-dd-dd-dd-aa-aa-aa-aa-aa-aa-81-00-87-65-08-06 + */ + u16 vlan_snap; + + if (payload_length < UF_VLAN_LLC_HEADER_SIZE) { + unifi_warning(priv, "VLAN SNAP header too short: %d bytes\n", payload_length); + return -1; + } + + if (memcmp(payload + 10, vlan_inner_snap, 6)) { + unifi_warning(priv, "VLAN malformatted SNAP header.\n"); + return -1; + } + + unifi_trace(priv, UDBG3, "VLAN SNAP: %02x-%02x\n", payload[8], payload[9]); + unifi_trace(priv, UDBG3, "VLAN len: %d\n", payload_length); + + /* Create the 802.3 header */ + + vlan_snap = *((u16*)(payload + 8)); + + /* Create LLC header without byte-swapping */ + eth->h_proto = snap->protocol; + + memcpy(eth->h_dest, daddr, ETH_ALEN); + memcpy(eth->h_source, saddr, ETH_ALEN); + *(u16*)(eth + 1) = vlan_snap; + return 0; + } + + /* it's a SNAP + RFC1042 frame */ + unifi_trace(priv, UDBG3, "SNAP+RFC1042 len: %d\n", payload_length); + + /* chop SNAP+llc header from skb. */ + skb_pull(skb, sizeof(llc_snap_hdr_t)); + + /* Since skb_pull called above to chop snap+llc, no need to check for headroom + * availability before skb_push + */ + /* create 802.3 header at beginning of skb. */ + eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); + memcpy(eth->h_dest, daddr, ETH_ALEN); + memcpy(eth->h_source, saddr, ETH_ALEN); + /* Copy protocol field without byte-swapping */ + eth->h_proto = snap->protocol; + } else { + u16 len; + + /* check for headroom availability before skb_push */ + if (headroom < (2 * ETH_ALEN + 2)) { + unifi_warning(priv, "headroom not available to skb_push ether header\n"); + return -1; + } + /* Add 802.3 header and leave full payload */ + len = htons(skb->len); + memcpy(skb_push(skb, 2), &len, 2); + memcpy(skb_push(skb, ETH_ALEN), saddr, ETH_ALEN); + memcpy(skb_push(skb, ETH_ALEN), daddr, ETH_ALEN); + + return 1; + } + + return 0; +} /* skb_80211_to_ether() */ + + +static CsrWifiRouterCtrlPortAction verify_port(unifi_priv_t *priv, unsigned char *address, int queue, CsrUint16 interfaceTag) +{ +#ifdef CSR_NATIVE_LINUX +#ifdef CSR_SUPPORT_WEXT + if (queue == UF_CONTROLLED_PORT_Q) { + return priv->wext_conf.block_controlled_port; + } else { + return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; + } +#else + return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; /* default to open for softmac dev */ +#endif +#else + return uf_sme_port_state(priv, address, queue, interfaceTag); +#endif +} + +/* + * --------------------------------------------------------------------------- + * prepare_and_add_macheader + * + * + * These functions adds mac header for packet from netdev + * to UniFi for transmission. + * EAP protocol packets are also appended with Mac header & + * sent using send_ma_pkt_request(). + * + * Arguments: + * priv Pointer to device private context struct + * skb Socket buffer containing data packet to transmit + * newSkb Socket buffer containing data packet + Mac header if no sufficient headroom in skb + * serviceClass to append QOS control header in Mac header + * bulkdata if newSkb allocated then bulkdata updated to send to unifi + * interfaceTag the interfaceID on which activity going on + * daddr destination address + * saddr source address + * protection protection bit set in framce control of mac header + * + * Returns: + * Zero on success or error code. + * --------------------------------------------------------------------------- + */ + +int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk_buff *newSkb, + CSR_PRIORITY priority, + bulk_data_param_t *bulkdata, + CsrUint16 interfaceTag, + const CsrUint8 *daddr, + const CsrUint8 *saddr, + CsrBool protection) +{ + CsrUint16 fc = 0; + CsrUint8 qc = 0; + CsrUint8 macHeaderLengthInBytes = MAC_HEADER_SIZE, *bufPtr = NULL; + bulk_data_param_t data_ptrs; + CsrResult csrResult; + int headroom =0; + CsrUint8 direction = 0; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrUint8 *addressOne; + CsrBool bQosNull = false; + + if (skb == NULL) { + unifi_error(priv,"prepare_and_add_macheader: Invalid SKB reference\n"); + return -1; + } + + /* add a MAC header refer: 7.1.3.1 Frame Control field in P802.11REVmb.book */ + if (priority != CSR_CONTENTION) { + /* EAPOL packets don't go as QOS_DATA */ + if (priority == CSR_MANAGEMENT) { + fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); + } else { + /* Qos Control Field */ + macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; + + if (skb->len) { + + fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_DATA); + } else { + fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_NULL); + bQosNull = true; + } + } + } else { + if(skb->len == 0) { + fc |= cpu_to_le16(IEEE802_11_FC_TYPE_NULL); + } else { + fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); + } + } + + switch (interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + direction = 2; + fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK); + break; + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + direction = 0; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + direction = 1; + fc |= cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK); + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AMP: + if (priority == CSR_MANAGEMENT ) { + + direction = 2; + fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK); + } else { + /* Data frames have to use WDS 4 address frames */ + direction = 3; + fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK | IEEE802_11_FC_FROM_DS_MASK); + macHeaderLengthInBytes += 6; + } + break; + default: + unifi_warning(priv, "prepare_and_add_macheader: Unknown mode %d\n", + interfacePriv->interfaceMode); + } + + + /* If Sta is QOS & HTC is supported then need to set 'order' bit */ + /* We don't support HT Control for now */ + + if(protection) { + fc |= cpu_to_le16(IEEE802_11_FC_PROTECTED_MASK); + } + + /* check the skb headroom before pushing mac header */ + headroom = skb_headroom(skb); + + if (headroom < macHeaderLengthInBytes) { + unifi_trace(priv, UDBG5, + "prepare_and_add_macheader: Allocate headroom extra %d bytes\n", + macHeaderLengthInBytes); + + csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, " failed to allocate request_data. in %s func\n", __FUNCTION__); + return -1; + } + newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); + newSkb->len = skb->len + macHeaderLengthInBytes; + + memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, + skb->data, skb->len); + + bulkdata->d[0].os_data_ptr = newSkb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; + bulkdata->d[0].data_length = newSkb->len; + + bufPtr = (CsrUint8*)data_ptrs.d[0].os_data_ptr; + + /* The old skb will not be used again */ + kfree_skb(skb); + } else { + + /* headroom has sufficient size, so will get proper pointer */ + bufPtr = (CsrUint8*)skb_push(skb, macHeaderLengthInBytes); + bulkdata->d[0].os_data_ptr = skb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata->d[0].data_length = skb->len; + } + + /* Frame the actual MAC header */ + + memset(bufPtr, 0, macHeaderLengthInBytes); + + /* copy frameControl field */ + memcpy(bufPtr, &fc, sizeof(fc)); + bufPtr += sizeof(fc); + macHeaderLengthInBytes -= sizeof(fc); + + /* Duration/ID field which is 2 bytes */ + bufPtr += 2; + macHeaderLengthInBytes -= 2; + + switch(direction) + { + case 0: + /* Its an Ad-Hoc no need to route it through AP */ + /* Address1: MAC address of the destination from eth header */ + memcpy(bufPtr, daddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address2: MAC address of the source */ + memcpy(bufPtr, saddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address3: the BSSID (locally generated in AdHoc (creators Bssid)) */ + memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + break; + case 1: + /* Address1: MAC address of the actual destination */ + memcpy(bufPtr, daddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + /* Address2: The MAC address of the AP */ + memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address3: MAC address of the source from eth header */ + memcpy(bufPtr, saddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + break; + case 2: + /* Address1: To AP is the MAC address of the AP to which its associated */ + memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address2: MAC address of the source from eth header */ + memcpy(bufPtr, saddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address3: MAC address of the actual destination on the distribution system */ + memcpy(bufPtr, daddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + break; + case 3: + memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address2: MAC address of the source from eth header */ + memcpy(bufPtr, saddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + + /* Address3: MAC address of the actual destination on the distribution system */ + memcpy(bufPtr, daddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + break; + default: + unifi_error(priv,"Unknown direction =%d : Not handled now\n",direction); + return -1; + } + /* 2 bytes of frame control field, appended by firmware */ + bufPtr += 2; + macHeaderLengthInBytes -= 2; + + if (3 == direction) { + /* Address4: MAC address of the source */ + memcpy(bufPtr, saddr, ETH_ALEN); + bufPtr += ETH_ALEN; + macHeaderLengthInBytes -= ETH_ALEN; + } + + /* IF Qos Data or Qos Null Data then set QosControl field */ + if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) { + + if (priority >= 7) { + unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority); + qc |= 7; + } else { + qc |= priority; + } + /*assigning address1 + * Address1 offset taken fromm bufPtr(currently bufPtr pointing to Qos contorl) variable in reverse direction + * Address4 don't exit + */ + + addressOne = bufPtr- ADDRESS_ONE_OFFSET; + + if (addressOne[0] & 0x1) { + /* multicast/broadcast frames, no acknowledgement needed */ + qc |= 1 << 5; + } + /* non-AP mode only for now */ + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) { + /* In case of STA and IBSS case eosp and txop limit is 0. */ + } else { + if(bQosNull) { + qc |= 1 << 4; + } + } + + /* append Qos control field to mac header */ + bufPtr[0] = qc; + /* txop limit is 0 */ + bufPtr[1] = 0; + macHeaderLengthInBytes -= QOS_CONTROL_HEADER_SIZE; + } + if (macHeaderLengthInBytes) { + unifi_warning(priv, " Mac header not appended properly\n"); + return -1; + } + return 0; +} + +/* + * --------------------------------------------------------------------------- + * send_ma_pkt_request + * + * These functions send a data packet to UniFi for transmission. + * EAP protocol packets are also sent as send_ma_pkt_request(). + * + * Arguments: + * priv Pointer to device private context struct + * skb Socket buffer containing data packet to transmit + * ehdr Pointer to Ethernet header within skb. + * + * Returns: + * Zero on success or error code. + * --------------------------------------------------------------------------- + */ + +static int +send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, CSR_PRIORITY priority) +{ + int r; + CsrUint16 i; + CsrBool eapolStore = FALSE; + struct sk_buff *newSkb = NULL; + bulk_data_param_t bulkdata; + const int proto = ntohs(ehdr->h_proto); + CsrUint16 interfaceTag; + CsrWifiMacAddress peerAddress; + CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED; + CsrInt8 protection; + netInterface_priv_t *interfacePriv = NULL; + + unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n"); + + /* Get the interface Tag by means of source Mac address */ + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + if (!memcmp(priv->netdev[i]->dev_addr, ehdr->h_source, ETH_ALEN)) { + interfaceTag = i; + interfacePriv = priv->interfacePriv[interfaceTag]; + break; + } + } + + if (interfacePriv == NULL) { + /* No match found - error */ + interfaceTag = 0; + interfacePriv = priv->interfacePriv[interfaceTag]; + unifi_warning(priv, "Mac address not matching ... debugging needed\n"); + interfacePriv->stats.tx_dropped++; + kfree_skb(skb); + return -1; + } + + /* Add a SNAP header if necessary */ + if (skb_add_llc_snap(priv->netdev[interfaceTag], skb, proto) != 0) { + /* convert failed */ + unifi_error(priv, "skb_add_llc_snap failed.\n"); + kfree_skb(skb); + return -1; + } + + bulkdata.d[0].os_data_ptr = skb->data; + bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; + +#ifdef CSR_SUPPORT_SME + /* Notify the TA module for the Tx frame for non AP/P2PGO mode*/ + if ((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AP) && + (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) { + unifi_ta_sample(priv->card, CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX, + &bulkdata.d[0], ehdr->h_source, + priv->netdev[interfaceTag]->dev_addr, + jiffies_to_msecs(jiffies), + 0); /* rate is unknown on tx */ + } +#endif /* CSR_SUPPORT_SME */ + + if ((proto == ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + || (proto == ETH_P_WAI) +#endif + ) + { + /* check for m4 detection */ + if (0 == uf_verify_m4(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length)) { + eapolStore = TRUE; + } + } + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + if (proto == ETH_P_WAI) + { + protection = 0; /*WAI packets always sent unencrypted*/ + } + else + { +#endif +#ifdef CSR_SUPPORT_SME + if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, ehdr->h_dest)) < 0) { + unifi_warning(priv, "unicast address, but destination not in station record database\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return -1; + } +#else + protection = 0; +#endif +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + } +#endif + + /* append Mac header for Eapol as well as data packet */ + if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, ehdr->h_dest, ehdr->h_source, protection)) { + unifi_error(priv, "failed to create MAC header\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return -1; + } + + /* RA adrress must contain the immediate destination MAC address that is similiar to + * the Address 1 field of 802.11 Mac header here 4 is: (sizeof(framecontrol) + sizeof (durationID)) + * which is address 1 field + */ + memcpy(peerAddress.a, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); + + unifi_trace(priv, UDBG5, "RA[0]=%x, RA[1]=%x, RA[2]=%x, RA[3]=%x, RA[4]=%x, RA[5]=%x\n", + peerAddress.a[0],peerAddress.a[1], peerAddress.a[2], peerAddress.a[3], + peerAddress.a[4],peerAddress.a[5]); + + + if ((proto == ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + || (proto == ETH_P_WAI) +#endif + ) + { + CSR_SIGNAL signal; + CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; + + /* initialize signal to zero */ + memset(&signal, 0, sizeof(CSR_SIGNAL)); + + /* Frame MA_PACKET request */ + signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; + signal.SignalPrimitiveHeader.ReceiverProcessId = 0; + signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; + + transmissionControl = req->TransmissionControl = 0; +#ifdef CSR_SUPPORT_SME + if (eapolStore) + { + netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]); + + /* Fill the MA-PACKET.req */ + + req->Priority = priority; + unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority); + + /* rate selected by firmware */ + req->TransmitRate = 0; + req->HostTag = CSR_WIFI_EAPOL_M4_HOST_TAG; + /* RA address matching with address 1 of Mac header */ + memcpy(req->Ra.x, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); + + spin_lock(&priv->m4_lock); + /* Store the M4-PACKET.req for later */ + interfacePriv->m4_signal = signal; + interfacePriv->m4_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; + interfacePriv->m4_bulk_data.data_length = bulkdata.d[0].data_length; + interfacePriv->m4_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; + interfacePriv->m4_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; + spin_unlock(&priv->m4_lock); + + /* Signal the workqueue to call CsrWifiRouterCtrlM4ReadyToSendIndSend(). + * It cannot be called directly from the tx path because it + * does a non-atomic kmalloc via the framework's CsrPmemAlloc(). + */ + queue_work(priv->unifi_workqueue, &netpriv->send_m4_ready_task); + + return 0; + } +#endif + } + + /* Send UniFi msg */ + /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */ + r = uf_process_ma_packet_req(priv, + peerAddress.a, + 0xffffffff, /* Ask for a new HostTag */ + interfaceTag, + transmissionControl, + (CSR_RATE)0, + priority, + priv->netdev_client->sender_id, + &bulkdata); + + if (r) { + unifi_trace(priv, UDBG1, "(HIP validation failure) r = %x\n", r); + unifi_net_data_free(priv, &bulkdata.d[0]); + return -1; + } + + unifi_trace(priv, UDBG3, "leaving send_ma_pkt_request, UNITDATA result code = %d\n", r); + + return r; +} /* send_ma_pkt_request() */ + +/* + * --------------------------------------------------------------------------- + * uf_net_xmit + * + * This function is called by the higher level stack to transmit an + * ethernet packet. + * + * Arguments: + * skb Ethernet packet to send. + * dev Pointer to the linux net device. + * + * Returns: + * 0 on success (packet was consumed, not necessarily transmitted) + * 1 if packet was requeued + * -1 on error + * + * + * Notes: + * The controlled port is handled in the qdisc dequeue handler. + * --------------------------------------------------------------------------- + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +static netdev_tx_t +#else +static int +#endif +uf_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct ethhdr ehdr; + int proto, port; + int result; + static tx_signal_handler tx_handler; + CSR_PRIORITY priority; +#if !defined (CONFIG_NET_SCHED) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) + CsrWifiRouterCtrlPortAction port_action; +#endif /* CONFIG_NET_SCHED */ + + func_enter(); + + unifi_trace(priv, UDBG5, "unifi_net_xmit: skb = %x\n", skb); + + memcpy(&ehdr, skb->data, ETH_HLEN); + proto = ntohs(ehdr.h_proto); + priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); + + /* All frames are sent as MA-PACKET.req (EAPOL also) */ + tx_handler = send_ma_pkt_request; + + /* 802.1x - apply controlled/uncontrolled port rules */ + if ((proto != ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + && (proto != ETH_P_WAI) +#endif + ) { + port = UF_CONTROLLED_PORT_Q; + } else { + /* queue 4 */ + port = UF_UNCONTROLLED_PORT_Q; + } + +#if defined (CONFIG_NET_SCHED) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) + /* Remove the ethernet header */ + skb_pull(skb, ETH_HLEN); + result = tx_handler(priv, skb, &ehdr, priority); +#else + /* Uncontrolled port rules apply */ + port_action = verify_port(priv + , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode)||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI== interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) + , port + , interfacePriv->InterfaceTag); + + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + unifi_trace(priv, UDBG5, + "uf_net_xmit: %s controlled port open\n", + port ? "" : "un"); + /* Remove the ethernet header */ + skb_pull(skb, ETH_HLEN); + result = tx_handler(priv, skb, &ehdr, priority); + } else { + + /* Discard the packet if necessary */ + unifi_trace(priv, UDBG2, + "uf_net_xmit: %s controlled port %s\n", + port ? "" : "un", port_action==CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK ? "blocked" : "closed"); + interfacePriv->stats.tx_dropped++; + kfree_skb(skb); + + func_exit(); + return NETDEV_TX_OK; + } +#endif /* CONFIG_NET_SCHED */ + + if (result == NETDEV_TX_OK) { + + dev->trans_start = jiffies; + + /* + * Should really count tx stats in the UNITDATA.status signal but + * that doesn't have the length. + */ + interfacePriv->stats.tx_packets++; + /* count only the packet payload */ + interfacePriv->stats.tx_bytes += skb->len; + + } else if (result < 0) { + + /* Failed to send: fh queue was full, and the skb was discarded. + * Return OK to indicate that the buffer was consumed, to stop the + * kernel re-transmitting the freed buffer. + */ + interfacePriv->stats.tx_dropped++; + unifi_trace(priv, UDBG1, "unifi_net_xmit: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped); + result = NETDEV_TX_OK; + } + + /* The skb will have been freed by send_XXX_request() */ + + func_exit(); + return result; +} /* uf_net_xmit() */ + +/* + * --------------------------------------------------------------------------- + * unifi_pause_xmit + * unifi_restart_xmit + * + * These functions are called from the UniFi core to control the flow + * of packets from the upper layers. + * unifi_pause_xmit() is called when the internal queue is full and + * should take action to stop unifi_ma_unitdata() being called. + * When the queue has drained, unifi_restart_xmit() will be called to + * re-enable the flow of packets for transmission. + * + * Arguments: + * ospriv OS private context pointer. + * + * Returns: + * unifi_pause_xmit() is called from interrupt context. + * --------------------------------------------------------------------------- + */ +void +unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) +{ + unifi_priv_t *priv = ospriv; + int i; /* used as a loop counter */ + + func_enter(); + unifi_trace(priv, UDBG2, "Stopping queue %d\n", queue); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + for(i=0;inetdev[i])) + { + netif_stop_subqueue(priv->netdev[i], (u16)queue); + } + } +#else +#ifdef ALLOW_Q_PAUSE + unifi_trace(priv, UDBG2, "Stopping netif\n"); + /* stop the traffic from all the interfaces. */ + for(i=0;inetdev[i])) { + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); + } + } +#else + if (net_is_tx_q_paused(priv, queue)) { + unifi_trace(priv, UDBG2, "Queue already stopped\n"); + return; + } + net_tx_q_pause(priv, queue); +#endif +#endif + +#ifdef CSR_SUPPORT_SME + if(queue<=3) { + routerStartBuffering(priv,queue); + unifi_trace(priv,UDBG2,"Start buffering %d\n", queue); + } else { + routerStartBuffering(priv,0); + unifi_error(priv, "Start buffering %d defaulting to 0\n", queue); + } +#endif + func_exit(); + +} /* unifi_pause_xmit() */ + +void +unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) +{ + unifi_priv_t *priv = ospriv; + int i=0; /* used as a loop counter */ + + func_enter(); + unifi_trace(priv, UDBG2, "Waking queue %d\n", queue); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + for(i=0;inetdev[i])) + { + netif_wake_subqueue(priv->netdev[i], (u16)queue); + } + } +#else +#ifdef ALLOW_Q_PAUSE + /* Need to supply queue number depending on Kernel support */ + /* Resume the traffic from all the interfaces */ + for(i=0;inetdev[i])) { + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[i]); + } + } +#else + if (!(net_is_tx_q_paused(priv, queue))) { + unifi_trace(priv, UDBG2, "Queue already running\n"); + func_exit(); + return; + } + net_tx_q_unpause(priv, queue); +#endif +#endif + +#ifdef CSR_SUPPORT_SME + if(queue <=3) { + routerStopBuffering(priv,queue); + uf_send_buffered_frames(priv,queue); + } else { + routerStopBuffering(priv,0); + uf_send_buffered_frames(priv,0); + } +#endif + func_exit(); +} /* unifi_restart_xmit() */ + + +static void +indicate_rx_skb(unifi_priv_t *priv, CsrUint16 ifTag, CsrUint8* dst_a, CsrUint8* src_a, struct sk_buff *skb, CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata) +{ + int r, sr = 0; + struct net_device *dev; + +#ifdef CSR_SUPPORT_SME + llc_snap_hdr_t *snap; + + snap = (llc_snap_hdr_t *)skb->data; + + sr = _identify_sme_ma_pkt_ind(priv, + snap->oui, ntohs(snap->protocol), + signal, + bulkdata, + dst_a, src_a ); +#endif + + /* + * Decapsulate any SNAP header and + * prepend an ethernet header so that the skb manipulation and ARP + * stuff works. + */ + r = skb_80211_to_ether(priv, skb, dst_a, src_a, + signal, bulkdata); + if (r == -1) { + /* Drop the packet and return */ + priv->interfacePriv[ifTag]->stats.rx_errors++; + priv->interfacePriv[ifTag]->stats.rx_frame_errors++; + unifi_net_data_free(priv, &bulkdata->d[0]); + unifi_notice(priv, "indicate_rx_skb: Discard unknown frame.\n"); + func_exit(); + return; + } + + /* Handle the case where packet is sent up through the subscription + * API but should not be given to the network stack (AMP PAL case) + * LLC header is different from WiFi and the packet has been subscribed for + */ + if (r == 1 && sr == 1) { + unifi_net_data_free(priv, &bulkdata->d[0]); + unifi_trace(priv, UDBG5, "indicate_rx_skb: Data given to subscription" + "API, not being given to kernel\n"); + func_exit(); + return; + } + + dev = priv->netdev[ifTag]; + /* Now we look like a regular ethernet frame */ + /* Fill in SKB meta data */ + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* Test for an overlength frame */ + if (skb->len > (dev->mtu + ETH_HLEN)) { + /* A bogus length ethfrm has been encap'd. */ + /* Is someone trying an oflow attack? */ + unifi_error(priv, "%s: oversize frame (%d > %d)\n", + dev->name, + skb->len, dev->mtu + ETH_HLEN); + + /* Drop the packet and return */ + priv->interfacePriv[ifTag]->stats.rx_errors++; + priv->interfacePriv[ifTag]->stats.rx_length_errors++; + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + + /* Pass SKB up the stack */ +#ifdef CSR_WIFI_USE_NETIF_RX + netif_rx(skb); +#else + netif_rx_ni(skb); +#endif + + if (dev != NULL) { + dev->last_rx = jiffies; + } + + /* Bump rx stats */ + priv->interfacePriv[ifTag]->stats.rx_packets++; + priv->interfacePriv[ifTag]->stats.rx_bytes += bulkdata->d[0].data_length; + + func_exit(); + return; +} + +void +uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, + CsrWifiMacAddress source_address, + int indicate, CsrUint16 interfaceTag) +{ + rx_buffered_packets_t *rx_q_item; + struct list_head *rx_list; + struct list_head *n; + struct list_head *l_h; + static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_process_rx_pending_queue bad interfaceTag\n"); + return; + } + + if (queue == UF_CONTROLLED_PORT_Q) { + rx_list = &interfacePriv->rx_controlled_list; + } else { + rx_list = &interfacePriv->rx_uncontrolled_list; + } + + down(&priv->rx_q_sem); + list_for_each_safe(l_h, n, rx_list) { + rx_q_item = list_entry(l_h, rx_buffered_packets_t, q); + + /* Validate against the source address */ + if (memcmp(broadcast_address.a, source_address.a, ETH_ALEN) && + memcmp(rx_q_item->sa.a, source_address.a, ETH_ALEN)) { + + unifi_trace(priv, UDBG2, + "uf_process_rx_pending_queue: Skipping sa=%02X%02X%02X%02X%02X%02X skb=%p, bulkdata=%p\n", + rx_q_item->sa.a[0], rx_q_item->sa.a[1], + rx_q_item->sa.a[2], rx_q_item->sa.a[3], + rx_q_item->sa.a[4], rx_q_item->sa.a[5], + rx_q_item->skb, &rx_q_item->bulkdata.d[0]); + continue; + } + + list_del(l_h); + + + unifi_trace(priv, UDBG2, + "uf_process_rx_pending_queue: Was Blocked skb=%p, bulkdata=%p\n", + rx_q_item->skb, &rx_q_item->bulkdata); + + if (indicate) { + indicate_rx_skb(priv, interfaceTag, rx_q_item->da.a, rx_q_item->sa.a, rx_q_item->skb, &rx_q_item->signal, &rx_q_item->bulkdata); + } else { + interfacePriv->stats.rx_dropped++; + unifi_net_data_free(priv, &rx_q_item->bulkdata.d[0]); + } + + /* It is our resposibility to free the Rx structure object. */ + kfree(rx_q_item); + } + up(&priv->rx_q_sem); +} + +/* + * --------------------------------------------------------------------------- + * uf_resume_data_plane + * + * Is called when the (un)controlled port is set to open, + * to notify the network stack to schedule for transmission + * any packets queued in the qdisk while port was closed and + * indicated to the stack any packets buffered in the Rx queues. + * + * Arguments: + * priv Pointer to device private struct + * + * Returns: + * --------------------------------------------------------------------------- + */ +void +uf_resume_data_plane(unifi_priv_t *priv, int queue, + CsrWifiMacAddress peer_address, + CsrUint16 interfaceTag) +{ +#ifdef CSR_SUPPORT_WEXT + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; +#endif + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_resume_data_plane bad interfaceTag\n"); + return; + } + + unifi_trace(priv, UDBG2, "Resuming netif\n"); + + /* + * If we are waiting for the net device to enter the up state, don't + * process the rx queue yet as it will be done by the callback when + * the device is ready. + */ +#ifdef CSR_SUPPORT_WEXT + if (!interfacePriv->wait_netdev_change) +#endif + { +#ifdef CONFIG_NET_SCHED + if (netif_running(priv->netdev[interfaceTag])) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + netif_tx_schedule_all(priv->netdev[interfaceTag]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netif_schedule_queue(netdev_get_tx_queue(priv->netdev[interfaceTag], 0)); +#else + netif_schedule(priv->netdev[interfaceTag]); +#endif /* LINUX_VERSION_CODE */ + } +#endif + uf_process_rx_pending_queue(priv, queue, peer_address, 1,interfaceTag); + } +} /* uf_resume_data_plane() */ + + +void uf_free_pending_rx_packets(unifi_priv_t *priv, int queue, CsrWifiMacAddress peer_address,CsrUint16 interfaceTag) +{ + uf_process_rx_pending_queue(priv, queue, peer_address, 0,interfaceTag); + +} /* uf_free_pending_rx_packets() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_rx + * + * Reformat a UniFi data received packet into a p80211 packet and + * pass it up the protocol stack. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) +{ + CsrUint16 interfaceTag; + bulk_data_desc_t *pData; + const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; + struct sk_buff *skb; + CsrWifiRouterCtrlPortAction port_action; + CsrUint8 dataFrameType; + int proto; + int queue; + + CsrUint8 da[ETH_ALEN], sa[ETH_ALEN]; + CsrUint8 toDs, fromDs, frameType, macHeaderLengthInBytes = MAC_HEADER_SIZE; + CsrUint16 frameControl; + netInterface_priv_t *interfacePriv; + struct ethhdr ehdr; + + func_enter(); + + interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff); + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* Sanity check that the VIF refers to a sensible interface */ + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + + /* Sanity check that the VIF refers to an allocated netdev */ + if (!interfacePriv->netdev_registered) + { + unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag); + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + if (bulkdata->d[0].data_length == 0) { + unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + + + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + skb->len = bulkdata->d[0].data_length; + + /* Point to the addresses */ + toDs = (skb->data[1] & 0x01) ? 1 : 0; + fromDs = (skb->data[1] & 0x02) ? 1 : 0; + + memcpy(da,(skb->data+4+toDs*12),ETH_ALEN);/* Address1 or 3 */ + memcpy(sa,(skb->data+10+fromDs*(6+toDs*8)),ETH_ALEN); /* Address2, 3 or 4 */ + + + pData = &bulkdata->d[0]; + frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr); + frameType = ((frameControl & 0x000C) >> 2); + + dataFrameType =((frameControl & 0x00f0) >> 4); + unifi_trace(priv, UDBG6, + "%s: Receive Data Frame Type %d \n", __FUNCTION__,dataFrameType); + + switch(dataFrameType) + { + case QOS_DATA: + case QOS_DATA_NULL: + /* If both are set then the Address4 exists (only for AP) */ + if (fromDs && toDs) + { + /* 6 is the size of Address4 field */ + macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6); + } + else + { + macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; + } + + /* If order bit set then HT control field is the part of MAC header */ + if (frameControl & FRAME_CONTROL_ORDER_BIT) + macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE; + break; + default: + if (fromDs && toDs) + macHeaderLengthInBytes += 6; + } + + /* Prepare the ethernet header from snap header of skb data */ + switch(dataFrameType) + { + case DATA_NULL: + case QOS_DATA_NULL: + /* This is for only queue info fetching, EAPOL wont come as + * null data so the proto is initialized as zero + */ + proto = 0x0; + break; + default: + { + llc_snap_hdr_t *snap; + /* Fetch a snap header to find protocol (for IPV4/IPV6 packets + * the snap header fetching offset is same) + */ + snap = (llc_snap_hdr_t *) (skb->data + macHeaderLengthInBytes); + + /* prepare the ethernet header from the snap header & addresses */ + ehdr.h_proto = snap->protocol; + memcpy(ehdr.h_dest, da, ETH_ALEN); + memcpy(ehdr.h_source, sa, ETH_ALEN); + } + proto = ntohs(ehdr.h_proto); + } + unifi_trace(priv, UDBG3, "in unifi_rx protocol from snap header = 0x%x\n", proto); + + if ((proto != ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + && (proto != ETH_P_WAI) +#endif + ) { + queue = UF_CONTROLLED_PORT_Q; + } else { + queue = UF_UNCONTROLLED_PORT_Q; + } + + port_action = verify_port(priv, (unsigned char*)sa, queue, interfaceTag); + unifi_trace(priv, UDBG3, "in unifi_rx port action is = 0x%x & queue = %x\n", port_action, queue); + +#ifdef CSR_SUPPORT_SME + /* Notify the TA module for the Rx frame for non P2PGO and AP cases*/ + if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AP) && + (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) + { + /* Remove MAC header of length(macHeaderLengthInBytes) before sampling */ + skb_pull(skb, macHeaderLengthInBytes); + pData->os_data_ptr = skb->data; + pData->data_length -= macHeaderLengthInBytes; + + if (pData->data_length) { + unifi_ta_sample(priv->card, CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX, + &bulkdata->d[0], + sa, priv->netdev[interfaceTag]->dev_addr, + jiffies_to_msecs(jiffies), + pkt_ind->ReceivedRate); + } + } else { + + /* AP/P2PGO specific handling here */ + CsrWifiRouterCtrlStaInfo_t * srcStaInfo = + CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,sa,interfaceTag); + + /* Defensive check only; Source address is already checked in + process_ma_packet_ind and we should have a valid source address here */ + + if(srcStaInfo == NULL) { + CsrWifiMacAddress peerMacAddress; + /* Unknown data PDU */ + memcpy(peerMacAddress.a,sa,ETH_ALEN); + unifi_trace(priv, UDBG1, "%s: Unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", __FUNCTION__, + sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]); + CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress); + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + /* For AP GO mode, don't store the PDUs */ + if (port_action != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + /* Drop the packet and return */ + CsrWifiMacAddress peerMacAddress; + memcpy(peerMacAddress.a,sa,ETH_ALEN); + unifi_trace(priv, UDBG3, "%s: Port is not open: unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", + __FUNCTION__, sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]); + + CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress); + interfacePriv->stats.rx_dropped++; + unifi_net_data_free(priv, &bulkdata->d[0]); + unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n", __FUNCTION__, + proto, queue ? "Controlled" : "Un-controlled"); + func_exit(); + return; + } + + /* Qos NULL/Data NULL are freed here and not processed further */ + if((dataFrameType == QOS_DATA_NULL) || (dataFrameType == DATA_NULL)){ + unifi_trace(priv, UDBG5, "%s: Null Frame Received and Freed\n", __FUNCTION__); + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + /* Now we have done with MAC header so proceed with the real data part*/ + /* This function takes care of appropriate routing for AP/P2PGO case*/ + /* the function hadnles following things + 2. Routing the PDU to appropriate location + 3. Error case handling + */ + if(!(uf_ap_process_data_pdu(priv, skb, &ehdr, srcStaInfo, + signal, + bulkdata, + macHeaderLengthInBytes))) + { + func_exit(); + return; + } + unifi_trace(priv, UDBG5, "unifi_rx: no specific AP handling process as normal frame, MAC Header len %d\n",macHeaderLengthInBytes); + /* Remove the MAC header for subsequent conversion */ + skb_pull(skb, macHeaderLengthInBytes); + pData->os_data_ptr = skb->data; + pData->data_length -= macHeaderLengthInBytes; + pData->os_net_buf_ptr = (unsigned char*)skb; + pData->net_buf_length = skb->len; + } +#endif /* CSR_SUPPORT_SME */ + + + /* Now that the MAC header is removed, null-data frames have zero length + * and can be dropped + */ + if (pData->data_length == 0) { + if (((frameControl & 0x00f0) >> 4) != QOS_DATA_NULL && + ((frameControl & 0x00f0) >> 4) != DATA_NULL) { + unifi_trace(priv, UDBG1, "Zero length frame, but not null-data %04x\n", frameControl); + } + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { + /* Drop the packet and return */ + interfacePriv->stats.rx_dropped++; + unifi_net_data_free(priv, &bulkdata->d[0]); + unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n", + __FUNCTION__, proto, queue ? "controlled" : "uncontrolled"); + func_exit(); + return; + } else if ( (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK) || + (interfacePriv->connected != UnifiConnected) ) { + + /* Buffer the packet into the Rx queues */ + rx_buffered_packets_t *rx_q_item; + struct list_head *rx_list; + + rx_q_item = (rx_buffered_packets_t *)kmalloc(sizeof(rx_buffered_packets_t), + GFP_KERNEL); + if (rx_q_item == NULL) { + unifi_error(priv, "%s: Failed to allocate %d bytes for rx packet record\n", + __FUNCTION__, sizeof(rx_buffered_packets_t)); + interfacePriv->stats.rx_dropped++; + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + INIT_LIST_HEAD(&rx_q_item->q); + rx_q_item->bulkdata = *bulkdata; + rx_q_item->skb = skb; + rx_q_item->signal = *signal; + memcpy(rx_q_item->sa.a, sa, ETH_ALEN); + memcpy(rx_q_item->da.a, da, ETH_ALEN); + unifi_trace(priv, UDBG2, "%s: Blocked skb=%p, bulkdata=%p\n", + __FUNCTION__, rx_q_item->skb, &rx_q_item->bulkdata); + + if (queue == UF_CONTROLLED_PORT_Q) { + rx_list = &interfacePriv->rx_controlled_list; + } else { + rx_list = &interfacePriv->rx_uncontrolled_list; + } + + /* Add to tail of packets queue */ + down(&priv->rx_q_sem); + list_add_tail(&rx_q_item->q, rx_list); + up(&priv->rx_q_sem); + + func_exit(); + return; + + } + + indicate_rx_skb(priv, interfaceTag, da, sa, skb, signal, bulkdata); + + func_exit(); + +} /* unifi_rx() */ + +static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) +{ + CsrUint16 interfaceTag; + const CSR_MA_PACKET_CONFIRM *pkt_cfm = &signal->u.MaPacketConfirm; + netInterface_priv_t *interfacePriv; + + func_enter(); + interfaceTag = (pkt_cfm->VirtualInterfaceIdentifier & 0xff); + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* Sanity check that the VIF refers to a sensible interface */ + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "%s: MA-PACKET confirm with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); + func_exit(); + return; + } +#ifdef CSR_SUPPORT_SME + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + + uf_process_ma_pkt_cfm_for_ap(priv,interfaceTag,pkt_cfm); + } else if (interfacePriv->m4_sent && (pkt_cfm->HostTag == interfacePriv->m4_hostTag)) { + /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/ + CsrResult result = pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE; + CsrWifiMacAddress peerMacAddress; + memcpy(peerMacAddress.a, interfacePriv->m4_signal.u.MaPacketRequest.Ra.x, ETH_ALEN); + + unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__); + CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, + interfaceTag, + peerMacAddress, + result); + interfacePriv->m4_sent = FALSE; + interfacePriv->m4_hostTag = 0xffffffff; + } +#endif + func_exit(); + return; +} + + +/* + * --------------------------------------------------------------------------- + * unifi_rx + * + * Reformat a UniFi data received packet into a p80211 packet and + * pass it up the protocol stack. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) +{ + CsrUint16 interfaceTag; + bulk_data_desc_t *pData; + CSR_MA_PACKET_INDICATION *pkt_ind = (CSR_MA_PACKET_INDICATION*)&signal->u.MaPacketIndication; + struct sk_buff *skb; + CsrUint16 frameControl; + netInterface_priv_t *interfacePriv; + CsrUint8 da[ETH_ALEN], sa[ETH_ALEN]; + CsrUint8 *bssid = NULL, *ba_addr = NULL; + CsrUint8 toDs, fromDs, frameType; + CsrUint8 i =0; + +#ifdef CSR_SUPPORT_SME + CsrUint8 dataFrameType = 0; + CsrBool powerSaveChanged = FALSE; + CsrUint8 pmBit = 0; + CsrWifiRouterCtrlStaInfo_t *srcStaInfo = NULL; + CsrUint16 qosControl; + +#endif + + func_enter(); + + interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff); + interfacePriv = priv->interfacePriv[interfaceTag]; + + + /* Sanity check that the VIF refers to a sensible interface */ + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + + /* Sanity check that the VIF refers to an allocated netdev */ + if (!interfacePriv->netdev_registered) + { + unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag); + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + if (bulkdata->d[0].data_length == 0) { + unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + /* For monitor mode we need to pass this indication to the registered application + handle this seperately*/ + /* MIC failure is already taken care of so no need to send the PDUs which are not successfully received in non-monitor mode*/ + if(pkt_ind->ReceptionStatus != CSR_RX_SUCCESS) + { + unifi_warning(priv, "%s: MA-PACKET indication with status = %d\n",__FUNCTION__, pkt_ind->ReceptionStatus); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + + + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + skb->len = bulkdata->d[0].data_length; + + /* Point to the addresses */ + toDs = (skb->data[1] & 0x01) ? 1 : 0; + fromDs = (skb->data[1] & 0x02) ? 1 : 0; + + memcpy(da,(skb->data+4+toDs*12),ETH_ALEN);/* Address1 or 3 */ + memcpy(sa,(skb->data+10+fromDs*(6+toDs*8)),ETH_ALEN); /* Address2, 3 or 4 */ + + /* Find the BSSID, which will be used to match the BA session */ + if (toDs && fromDs) + { + unifi_trace(priv, UDBG6, "4 address frame - don't try to find BSSID\n"); + bssid = NULL; + } + else + { + bssid = (CsrUint8 *) (skb->data + 4 + 12 - (fromDs * 6) - (toDs * 12)); + } + + pData = &bulkdata->d[0]; + frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr); + frameType = ((frameControl & 0x000C) >> 2); + + unifi_trace(priv, UDBG3, "Rx Frame Type: %d sn: %d\n",frameType, + (le16_to_cpu(*((CsrUint16*)(bulkdata->d[0].os_data_ptr + IEEE802_11_SEQUENCE_CONTROL_OFFSET))) >> 4) & 0xfff); + if(frameType == IEEE802_11_FRAMETYPE_CONTROL){ +#ifdef CSR_SUPPORT_SME + unifi_trace(priv, UDBG6, "%s: Received Control Frame\n", __FUNCTION__); + + if((frameControl & 0x00f0) == 0x00A0){ + /* This is a PS-POLL request */ + CsrUint8 pmBit = (frameControl & 0x1000)?0x01:0x00; + unifi_trace(priv, UDBG6, "%s: Received PS-POLL Frame\n", __FUNCTION__); + + uf_process_ps_poll(priv,sa,da,pmBit,interfaceTag); + } + else { + unifi_warning(priv, "%s: Non PS-POLL control frame is received\n", __FUNCTION__); + } +#endif + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + if(frameType != IEEE802_11_FRAMETYPE_DATA) { + unifi_warning(priv, "%s: Non control Non Data frame is received\n",__FUNCTION__); + unifi_net_data_free(priv,&bulkdata->d[0]); + func_exit(); + return; + } + +#ifdef CSR_SUPPORT_SME + if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || + (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)){ + + srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,sa,interfaceTag); + + if(srcStaInfo == NULL) { + CsrWifiMacAddress peerMacAddress; + /* Unknown data PDU */ + memcpy(peerMacAddress.a,sa,ETH_ALEN); + unifi_trace(priv, UDBG1, "%s: Unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", __FUNCTION__, + sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]); + CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress); + unifi_net_data_free(priv, &bulkdata->d[0]); + func_exit(); + return; + } + + /* + verify power management bit here so as to ensure host and unifi are always + in sync with power management status of peer. + + If we do it later, it may so happen we have stored the frame in BA re-ordering + buffer and hence host and unifi are out of sync for power management status + */ + + pmBit = (frameControl & 0x1000)?0x01:0x00; + powerSaveChanged = uf_process_pm_bit_for_peer(priv,srcStaInfo,pmBit,interfaceTag); + + /* Update station last activity time */ + srcStaInfo->activity_flag = TRUE; + + /* For Qos Frame if PM bit is toggled to indicate the change in power save state then it shall not be + considered as Trigger Frame. Enter only if WMM STA and peer is in Power save */ + + dataFrameType = ((frameControl & 0x00f0) >> 4); + + if((powerSaveChanged == FALSE)&&(srcStaInfo->wmmOrQosEnabled == TRUE)&& + (srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)){ + + if((dataFrameType == QOS_DATA) || (dataFrameType == QOS_DATA_NULL)){ + + /* + QoS control field is offset from frame control by 2 (frame control) + + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN + */ + if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){ + qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30); + } + else{ + qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24); + } + + if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){ + CSR_PRIORITY priority; + unifi_TrafficQueue priority_q; + priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); + if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) + ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){ + unsigned long lock_flags; + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->uapsdSuspended = TRUE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + unifi_trace(priv, UDBG3, "%s: qos Trigger Frame received while DTIM Active for staid: 0x%x\n",__FUNCTION__,srcStaInfo->aid); + } + } + else{ + + + unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl); + uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag); + } + } + } + } + +#endif + + if( ((frameControl & 0x00f0) >> 4) == QOS_DATA) { + CsrUint8 *qos_control_ptr = (CsrUint8*)bulkdata->d[0].os_data_ptr + (((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK))?30: 24); + int tID = *qos_control_ptr & IEEE802_11_QC_TID_MASK; /* using ls octet of qos control */ + ba_session_rx_struct *ba_session; + CsrUint8 ba_session_idx = 0; + /* Get the BA originator address */ + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO){ + ba_addr = sa; + }else{ + ba_addr = bssid; + } + + spin_lock(&priv->ba_lock); + for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + ba_session = interfacePriv->ba_session_rx[ba_session_idx]; + if (ba_session){ + unifi_trace(priv, UDBG6, "found ba_session=0x%x ba_session_idx=%d", ba_session, ba_session_idx); + if ((!memcmp(ba_session->macAddress.a, ba_addr, ETH_ALEN)) && (ba_session->tID == tID)){ + frame_desc_struct frame_desc; + frame_desc.bulkdata = *bulkdata; + frame_desc.signal = *signal; + frame_desc.sn = (le16_to_cpu(*((CsrUint16*)(bulkdata->d[0].os_data_ptr + IEEE802_11_SEQUENCE_CONTROL_OFFSET))) >> 4) & 0xfff; + frame_desc.active = TRUE; + unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx); + process_ba_frame(priv, interfacePriv, ba_session, &frame_desc); + spin_unlock(&priv->ba_lock); + process_ba_complete(priv, interfacePriv); + break; + } + } + } + if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ + spin_unlock(&priv->ba_lock); + unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__); + process_amsdu(priv, signal, bulkdata); + } + } else { + unifi_trace(priv, UDBG6, "calling unifi_rx()"); + unifi_rx(priv, signal, bulkdata); + } + + /* check if the frames in reorder buffer has aged, the check + * is done after receive processing so that if the missing frame + * has arrived in this receive process, then it is handled cleanly. + * + * And also this code here takes care that timeout check is made for all + * the receive indications + */ + spin_lock(&priv->ba_lock); + for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){ + ba_session_rx_struct *ba_session; + ba_session = interfacePriv->ba_session_rx[i]; + if (ba_session){ + check_ba_frame_age_timeout(priv, interfacePriv, ba_session); + } + } + process_ba_complete(priv, interfacePriv); + spin_unlock(&priv->ba_lock); + + func_exit(); +} +/* + * --------------------------------------------------------------------------- + * uf_set_multicast_list + * + * This function is called by the higher level stack to set + * a list of multicast rx addresses. + * + * Arguments: + * dev Network Device pointer. + * + * Returns: + * None. + * + * Notes: + * --------------------------------------------------------------------------- + */ + +static void +uf_set_multicast_list(struct net_device *dev) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + +#ifdef CSR_NATIVE_LINUX + unifi_trace(priv, UDBG3, "uf_set_multicast_list unsupported\n"); + return; +#else + + u8 *mc_list = interfacePriv->mc_list; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + struct netdev_hw_addr *mc_addr; + int mc_addr_count; +#else + struct dev_mc_list *p; /* Pointer to the addresses structure. */ + int i; +#endif + + if (priv->init_progress != UNIFI_INIT_COMPLETED) { + return; + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + mc_addr_count = netdev_mc_count(dev); + + unifi_trace(priv, UDBG3, + "uf_set_multicast_list (count=%d)\n", mc_addr_count); + + + /* Not enough space? */ + if (mc_addr_count > UNIFI_MAX_MULTICAST_ADDRESSES) { + return; + } + + /* Store the list to be processed by the work item. */ + interfacePriv->mc_list_count = mc_addr_count; + netdev_hw_addr_list_for_each(mc_addr, &dev->mc) { + memcpy(mc_list, mc_addr->addr, ETH_ALEN); + mc_list += ETH_ALEN; + } + +#else + unifi_trace(priv, UDBG3, + "uf_set_multicast_list (count=%d)\n", dev->mc_count); + + /* Not enough space? */ + if (dev->mc_count > UNIFI_MAX_MULTICAST_ADDRESSES) { + return; + } + + /* Store the list to be processed by the work item. */ + interfacePriv->mc_list_count = dev->mc_count; + p = dev->mc_list; + for (i = 0; i < dev->mc_count; i++) { + memcpy(mc_list, p->dmi_addr, ETH_ALEN); + p = p->next; + mc_list += ETH_ALEN; + } +#endif + + /* Send a message to the workqueue */ + queue_work(priv->unifi_workqueue, &priv->multicast_list_task); +#endif + +} /* uf_set_multicast_list() */ + +/* + * --------------------------------------------------------------------------- + * netdev_mlme_event_handler + * + * Callback function to be used as the udi_event_callback when registering + * as a netdev client. + * To use it, a client specifies this function as the udi_event_callback + * to ul_register_client(). The signal dispatcher in + * unifi_receive_event() will call this function to deliver a signal. + * + * Arguments: + * pcli Pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointer to structure containing any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +netdev_mlme_event_handler(ul_client_t *pcli, const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata_o, int dir) +{ + CSR_SIGNAL signal; + unifi_priv_t *priv = uf_find_instance(pcli->instance); + int id, r; + bulk_data_param_t bulkdata; + + func_enter(); + + /* Just a sanity check */ + if (sig_packed == NULL) { + return; + } + + /* + * This copy is to silence a compiler warning about discarding the + * const qualifier. + */ + bulkdata = *bulkdata_o; + + /* Get the unpacked signal */ + r = read_unpack_signal(sig_packed, &signal); + if (r) { + /* + * The CSR_MLME_CONNECTED_INDICATION_ID has a receiverID=0 so will + * fall through this case. It is safe to ignore this signal. + */ + unifi_trace(priv, UDBG1, + "Netdev - Received unknown signal 0x%.4X.\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); + return; + } + + id = signal.SignalPrimitiveHeader.SignalId; + unifi_trace(priv, UDBG3, "Netdev - Process signal 0x%.4X\n", id); + + /* + * Take the appropriate action for the signal. + */ + switch (id) { + case CSR_MA_PACKET_ERROR_INDICATION_ID: + process_ma_packet_error_ind(priv, &signal, &bulkdata); + break; + case CSR_MA_PACKET_INDICATION_ID: + process_ma_packet_ind(priv, &signal, &bulkdata); + break; + case CSR_MA_PACKET_CONFIRM_ID: + process_ma_packet_cfm(priv, &signal, &bulkdata); + break; +#ifdef CSR_SUPPORT_SME + case CSR_MLME_SET_TIM_CONFIRM_ID: + /* Handle TIM confirms from FW & set the station record's TIM state appropriately, + * In case of failures, tries with max_retransmit limit + */ + uf_handle_tim_cfm(priv, &signal.u.MlmeSetTimConfirm, signal.SignalPrimitiveHeader.ReceiverProcessId); + break; +#endif + case CSR_DEBUG_STRING_INDICATION_ID: + debug_string_indication(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length); + break; + + case CSR_DEBUG_WORD16_INDICATION_ID: + debug_word16_indication(priv, &signal); + break; + + case CSR_DEBUG_GENERIC_CONFIRM_ID: + case CSR_DEBUG_GENERIC_INDICATION_ID: + debug_generic_indication(priv, &signal); + break; + default: + break; + } + + func_exit(); +} /* netdev_mlme_event_handler() */ + + +/* + * --------------------------------------------------------------------------- + * uf_net_get_name + * + * Retrieve the name (e.g. eth1) associated with this network device + * + * Arguments: + * dev Pointer to the network device. + * name Buffer to write name + * len Size of buffer in bytes + * + * Returns: + * None + * + * Notes: + * --------------------------------------------------------------------------- + */ +void uf_net_get_name(struct net_device *dev, char *name, int len) +{ + *name = '\0'; + if (dev) { + strlcpy(name, dev->name, (len > IFNAMSIZ) ? IFNAMSIZ : len); + } + +} /* uf_net_get_name */ + + + + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + +/* + * --------------------------------------------------------------------------- + * uf_install_qdisc + * + * Creates a root qdisc, registers our qdisc handlers and + * overrides the device's qdisc_sleeping to prevent the system + * from creating a new one for our network device. + * + * Arguments: + * dev Pointer to the network device. + * + * Returns: + * 0 on success, Linux error code otherwise. + * + * Notes: + * This function holds the qdisk lock so it needs to be called + * after registering the network device in uf_register_netdev(). + * Also, the qdisc_create_dflt() API has changed in 2.6.20 to + * include the parentid. + * --------------------------------------------------------------------------- + */ +int uf_install_qdisc(struct net_device *dev) +{ + struct Qdisc *qdisc; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + struct netdev_queue *queue0; +#endif /* LINUX_VERSION_CODE */ + + + func_enter(); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + /* + * check that there is no qdisc currently attached to device + * this ensures that we will be the root qdisc. (I can't find a better + * way to test this explicitly) + */ + if (dev->qdisc_sleeping != &noop_qdisc) { + func_exit_r(-EFAULT); + return -EINVAL; + } +#endif /* LINUX_VERSION_CODE */ + + qdisc = UF_QDISC_CREATE_DFLT(dev, &uf_qdisc_ops, TC_H_ROOT); + if (!qdisc) { + unifi_error(NULL, "%s: qdisc installation failed\n", dev->name); + func_exit_r(-EFAULT); + return -EFAULT; + } + unifi_trace(NULL, UDBG5, "%s: parent qdisc=0x%p\n", + dev->name, qdisc); + + qdisc->handle = 0x80020000; + qdisc->flags = 0x0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + queue0 = netdev_get_tx_queue(dev, 0); + if (queue0 == NULL) { + unifi_error(NULL, "%s: netdev_get_tx_queue returned no queue\n", + dev->name); + func_exit_r(-EFAULT); + return -EFAULT; + } + queue0->qdisc = qdisc; + queue0->qdisc_sleeping = qdisc; +#else + qdisc_lock_tree(dev); + list_add_tail(&qdisc->list, &dev->qdisc_list); + dev->qdisc_sleeping = qdisc; + qdisc_unlock_tree(dev); +#endif /* LINUX_VERSION_CODE */ + + func_exit_r(0); + return 0; + +} /* uf_install_qdisc() */ + +static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; + struct ethhdr ehdr; + struct Qdisc *qdisc; + int r, proto; + + func_enter(); + + memcpy(&ehdr, skb->data, ETH_HLEN); + proto = ntohs(ehdr.h_proto); + + /* 802.1x - apply controlled/uncontrolled port rules */ + if ((proto != ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + && (proto != ETH_P_WAI) +#endif + ) { + /* queues 0 - 3 */ + pkt_data->priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); + pkt_data->queue = unifi_frame_priority_to_queue(pkt_data->priority); + } else { + pkt_data->queue = UNIFI_TRAFFIC_Q_EAPOL; + } + + qdisc = q->queues[pkt_data->queue]; + r = qdisc->enqueue(skb, qdisc); + if (r == NET_XMIT_SUCCESS) { + qd->q.qlen++; + qd->bstats.bytes += skb->len; + qd->bstats.packets++; + func_exit_r(NET_XMIT_SUCCESS); + return NET_XMIT_SUCCESS; + } + + unifi_error(priv, "uf_qdiscop_enqueue: dropped\n"); + qd->qstats.drops++; + + func_exit_r(r); + return r; + +} /* uf_qdiscop_enqueue() */ + + +static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; + struct Qdisc *qdisc; + int r; + + func_enter(); + + unifi_trace(priv, UDBG5, "uf_qdiscop_requeue: (q=%d), tag=%u\n", + pkt_data->queue, pkt_data->host_tag); + + /* we recorded which queue to use earlier! */ + qdisc = q->queues[pkt_data->queue]; + + if ((r = qdisc->ops->requeue(skb, qdisc)) == 0) { + qd->q.qlen++; + func_exit_r(0); + return 0; + } + + unifi_error(priv, "uf_qdiscop_requeue: dropped\n"); + qd->qstats.drops++; + + func_exit_r(r); + return r; +} /* uf_qdiscop_requeue() */ + +static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct sk_buff *skb; + struct Qdisc *qdisc; + int queue, i; + struct ethhdr ehdr; + struct uf_tx_packet_data *pkt_data; + CsrWifiRouterCtrlPortAction port_action; + + func_enter(); + + /* check all the queues */ + for (i = UNIFI_TRAFFIC_Q_MAX - 1; i >= 0; i--) { + + if (i != UNIFI_TRAFFIC_Q_EAPOL) { + queue = priv->prev_queue; + if (++priv->prev_queue >= UNIFI_TRAFFIC_Q_EAPOL) { + priv->prev_queue = 0; + } + } else { + queue = i; + } + +#ifndef ALLOW_Q_PAUSE + /* If queue is paused, do not dequeue */ + if (net_is_tx_q_paused(priv, queue)) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: tx queue paused (q=%d)\n", queue); + continue; + } +#endif + + qdisc = q->queues[queue]; + skb = qdisc->dequeue(qdisc); + if (skb) { + /* A packet has been dequeued, decrease the queued packets count */ + qd->q.qlen--; + + pkt_data = (struct uf_tx_packet_data *) skb->cb; + + /* Check the (un)controlled port status */ + memcpy(&ehdr, skb->data, ETH_HLEN); + + port_action = verify_port(priv + , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) ||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI == interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) + , (UNIFI_TRAFFIC_Q_EAPOL == queue? UF_UNCONTROLLED_PORT_Q: UF_CONTROLLED_PORT_Q) + , interfacePriv->InterfaceTag); + + /* Dequeue packet if port is open */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: new (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + + func_exit(); + return skb; + } + + /* Discard or block the packet if necessary */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: drop (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + kfree_skb(skb); + break; + } + + /* We can not send the packet now, put it back to the queue */ + if (qdisc->ops->requeue(skb, qdisc) != 0) { + unifi_error(priv, + "uf_qdiscop_dequeue: requeue (q=%d) failed, tag=%u, drop it\n", + queue, pkt_data->host_tag); + + /* Requeue failed, drop the packet */ + kfree_skb(skb); + break; + } + /* We requeued the packet, increase the queued packets count */ + qd->q.qlen++; + + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: skip (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + } + } + + func_exit(); + return NULL; +} /* uf_qdiscop_dequeue() */ + + +static void uf_qdiscop_reset(struct Qdisc* qd) +{ + struct uf_sched_data *q = qdisc_priv(qd); + int queue; + func_enter(); + + for (queue = 0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { + qdisc_reset(q->queues[queue]); + } + qd->q.qlen = 0; + + func_exit(); +} /* uf_qdiscop_reset() */ + + +static void uf_qdiscop_destroy(struct Qdisc* qd) +{ + struct uf_sched_data *q = qdisc_priv(qd); + int queue; + + func_enter(); + + for (queue=0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { + qdisc_destroy(q->queues[queue]); + q->queues[queue] = &noop_qdisc; + } + + func_exit(); +} /* uf_qdiscop_destroy() */ + + +/* called whenever parameters are updated on existing qdisc */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt) +#else +static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt) +#endif +{ + func_enter(); + func_exit(); + return 0; +} /* uf_qdiscop_tune() */ + + +/* called during initial creation of qdisc on device */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) +#else +static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + struct net_device *dev = qd->dev_queue->dev; +#else + struct net_device *dev = qd->dev; +#endif /* LINUX_VERSION_CODE */ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + int err = 0, i; + + func_enter(); + + /* make sure we do not mess with the ingress qdisc */ + if (qd->flags & TCQ_F_INGRESS) { + func_exit(); + return -EINVAL; + } + + /* if options were passed in, set them */ + if (opt) { + err = uf_qdiscop_tune(qd, opt); + } + + /* create child queues */ + for (i = 0; i < UNIFI_TRAFFIC_Q_MAX; i++) { + q->queues[i] = UF_QDISC_CREATE_DFLT(dev, &pfifo_qdisc_ops, + qd->handle); + if (!q->queues[i]) { + q->queues[i] = &noop_qdisc; + unifi_error(priv, "%s child qdisc %i creation failed\n"); + } + + unifi_trace(priv, UDBG5, "%s: child qdisc=0x%p\n", + dev->name, q->queues[i]); + } + + func_exit_r(err); + return err; +} /* uf_qdiscop_init() */ + + +static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) +{ + func_enter(); + func_exit_r(skb->len); + return skb->len; +} /* uf_qdiscop_dump() */ + +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + +#ifdef CSR_SUPPORT_WEXT + +/* + * --------------------------------------------------------------------------- + * uf_netdev_event + * + * Callback function to handle netdev state changes + * + * Arguments: + * notif Pointer to a notifier_block. + * event Event prompting notification + * ptr net_device pointer + * + * Returns: + * None + * + * Notes: + * The event handler is global, and may occur on non-UniFi netdevs. + * --------------------------------------------------------------------------- + */ +static int +uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) { + struct net_device *netdev = ptr; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(netdev); + unifi_priv_t *priv = NULL; + static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + + /* Check that the event is for a UniFi netdev. If it's not, the netdev_priv + * structure is not safe to use. + */ + if (uf_find_netdev_priv(interfacePriv) == -1) { + unifi_trace(NULL, UDBG1, "uf_netdev_event: ignore e=%d, ptr=%p, priv=%p %s\n", + event, ptr, interfacePriv, netdev->name); + return 0; + } + + switch(event) { + case NETDEV_CHANGE: + priv = interfacePriv->privPtr; + unifi_trace(priv, UDBG1, "NETDEV_CHANGE: %p %s %s waiting for it\n", + ptr, + netdev->name, + interfacePriv->wait_netdev_change ? "" : "not"); + + if (interfacePriv->wait_netdev_change) { + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[interfacePriv->InterfaceTag]); + interfacePriv->connected = UnifiConnected; + interfacePriv->wait_netdev_change = FALSE; + /* Note: passing the broadcast address here will allow anyone to attempt to join our adhoc network */ + uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1,interfacePriv->InterfaceTag); + uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1,interfacePriv->InterfaceTag); + } + break; + + default: + break; + } + return 0; +} + +static struct notifier_block uf_netdev_notifier = { + .notifier_call = uf_netdev_event, +}; +#endif /* CSR_SUPPORT_WEXT */ + + +static void + process_amsdu(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) +{ + CsrUint32 offset; + CsrUint32 length = bulkdata->d[0].data_length; + CsrUint32 subframe_length, subframe_body_length, dot11_hdr_size; + CsrUint8 *ptr; + bulk_data_param_t subframe_bulkdata; + CsrUint8 *dot11_hdr_ptr = (CsrUint8*)bulkdata->d[0].os_data_ptr; + CsrResult csrResult; + CsrUint16 frameControl; + CsrUint8 *qos_control_ptr; + + frameControl = le16_to_cpu(*((CsrUint16*)dot11_hdr_ptr)); + qos_control_ptr = dot11_hdr_ptr + (((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK))?30: 24); + if(!(*qos_control_ptr & IEEE802_11_QC_A_MSDU_PRESENT)) { + unifi_trace(priv, UDBG6, "%s: calling unifi_rx()", __FUNCTION__); + unifi_rx(priv, signal, bulkdata); + return; + } + *qos_control_ptr &= ~(IEEE802_11_QC_A_MSDU_PRESENT); + + ptr = qos_control_ptr + 2; + offset = dot11_hdr_size = ptr - dot11_hdr_ptr; + + while(length > (offset + sizeof(struct ethhdr) + sizeof(llc_snap_hdr_t))) { + subframe_body_length = ntohs(((struct ethhdr*)ptr)->h_proto); + if(subframe_body_length > IEEE802_11_MAX_DATA_LEN) { + unifi_error(priv, "%s: bad subframe_body_length = %d\n", __FUNCTION__, subframe_body_length); + break; + } + subframe_length = sizeof(struct ethhdr) + subframe_body_length; + memset(&subframe_bulkdata, 0, sizeof(bulk_data_param_t)); + + csrResult = unifi_net_data_malloc(priv, &subframe_bulkdata.d[0], dot11_hdr_size + subframe_body_length); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "%s: unifi_net_data_malloc failed\n", __FUNCTION__); + break; + } + + memcpy((CsrUint8*)subframe_bulkdata.d[0].os_data_ptr, dot11_hdr_ptr, dot11_hdr_size); + + + /* When to DS=0 and from DS=0, address 3 will already have BSSID so no need to re-program */ + if ((frameControl & IEEE802_11_FC_TO_DS_MASK) && !(frameControl & IEEE802_11_FC_FROM_DS_MASK)){ + memcpy((CsrUint8*)subframe_bulkdata.d[0].os_data_ptr + IEEE802_11_ADDR3_OFFSET, ((struct ethhdr*)ptr)->h_dest, ETH_ALEN); + } + else if (!(frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){ + memcpy((CsrUint8*)subframe_bulkdata.d[0].os_data_ptr + IEEE802_11_ADDR3_OFFSET, + ((struct ethhdr*)ptr)->h_source, + ETH_ALEN); + } + + memcpy((CsrUint8*)subframe_bulkdata.d[0].os_data_ptr + dot11_hdr_size, + ptr + sizeof(struct ethhdr), + subframe_body_length); + unifi_trace(priv, UDBG6, "%s: calling unifi_rx. length = %d subframe_length = %d\n", __FUNCTION__, length, subframe_length); + unifi_rx(priv, signal, &subframe_bulkdata); + + subframe_length = (subframe_length + 3)&(~0x3); + ptr += subframe_length; + offset += subframe_length; + } + unifi_net_data_free(priv, &bulkdata->d[0]); +} + + +#define SN_TO_INDEX(__ba_session, __sn) (((__sn - __ba_session->start_sn) & 0xFFF) % __ba_session->wind_size) + + +#define ADVANCE_EXPECTED_SN(__ba_session) \ +{ \ + __ba_session->expected_sn++; \ + __ba_session->expected_sn &= 0xFFF; \ +} + +#define FREE_BUFFER_SLOT(__ba_session, __index) \ +{ \ + __ba_session->occupied_slots--; \ + __ba_session->buffer[__index].active = FALSE; \ + ADVANCE_EXPECTED_SN(__ba_session); \ +} + +static void add_frame_to_ba_complete(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + frame_desc_struct *frame_desc) +{ + interfacePriv->ba_complete[interfacePriv->ba_complete_index] = *frame_desc; + interfacePriv->ba_complete_index++; +} + + +static void update_expected_sn(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + CsrUint16 sn) +{ + int i, j; + CsrUint16 gap; + + gap = (sn - ba_session->expected_sn) & 0xFFF; + unifi_trace(priv, UDBG6, "%s: proccess the frames up to new_expected_sn = %d gap = %d\n", __FUNCTION__, sn, gap); + for(j = 0; j < gap && j < ba_session->wind_size; j++) { + i = SN_TO_INDEX(ba_session, ba_session->expected_sn); + unifi_trace(priv, UDBG6, "%s: proccess the slot index = %d\n", __FUNCTION__, i); + if(ba_session->buffer[i].active) { + add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); + unifi_trace(priv, UDBG6, "%s: proccess the frame at index = %d expected_sn = %d\n", __FUNCTION__, i, ba_session->expected_sn); + FREE_BUFFER_SLOT(ba_session, i); + } else { + unifi_trace(priv, UDBG6, "%s: empty slot at index = %d\n", __FUNCTION__, i); + ADVANCE_EXPECTED_SN(ba_session); + } + } + ba_session->expected_sn = sn; +} + + +static void complete_ready_sequence(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session) +{ + int i; + + i = SN_TO_INDEX(ba_session, ba_session->expected_sn); + while (ba_session->buffer[i].active) { + add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); + unifi_trace(priv, UDBG6, "%s: completed stored frame(expected_sn=%d) at i = %d\n", __FUNCTION__, ba_session->expected_sn, i); + FREE_BUFFER_SLOT(ba_session, i); + i = SN_TO_INDEX(ba_session, ba_session->expected_sn); + } +} + + +void scroll_ba_window(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + CsrUint16 sn) +{ + if(((sn - ba_session->expected_sn) & 0xFFF) <= 2048) { + update_expected_sn(priv, interfacePriv, ba_session, sn); + complete_ready_sequence(priv, interfacePriv, ba_session); + } +} + + +static int consume_frame_or_get_buffer_index(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + CsrUint16 sn, + frame_desc_struct *frame_desc) { + int i; + CsrUint16 sn_temp; + + if(((sn - ba_session->expected_sn) & 0xFFF) <= 2048) { + + /* once we are in BA window, set the flag for BA trigger */ + if(!ba_session->trigger_ba_after_ssn){ + ba_session->trigger_ba_after_ssn = TRUE; + } + + sn_temp = ba_session->expected_sn + ba_session->wind_size; + unifi_trace(priv, UDBG6, "%s: new frame: sn=%d\n", __FUNCTION__, sn); + if(!(((sn - sn_temp) & 0xFFF) > 2048)) { + CsrUint16 new_expected_sn; + unifi_trace(priv, UDBG6, "%s: frame is out of window\n", __FUNCTION__); + sn_temp = (sn - ba_session->wind_size) & 0xFFF; + new_expected_sn = (sn_temp + 1) & 0xFFF; + update_expected_sn(priv, interfacePriv, ba_session, new_expected_sn); + } + i = -1; + if (sn == ba_session->expected_sn) { + unifi_trace(priv, UDBG6, "%s: sn = ba_session->expected_sn = %d\n", __FUNCTION__, sn); + ADVANCE_EXPECTED_SN(ba_session); + add_frame_to_ba_complete(priv, interfacePriv, frame_desc); + } else { + i = SN_TO_INDEX(ba_session, sn); + unifi_trace(priv, UDBG6, "%s: sn(%d) != ba_session->expected_sn(%d), i = %d\n", __FUNCTION__, sn, ba_session->expected_sn, i); + if (ba_session->buffer[i].active) { + unifi_trace(priv, UDBG6, "%s: free frame at i = %d\n", __FUNCTION__, i); + i = -1; + unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); + } + } + } else { + i = -1; + if(!ba_session->trigger_ba_after_ssn){ + unifi_trace(priv, UDBG6, "%s: frame before ssn, pass it up: sn=%d\n", __FUNCTION__, sn); + add_frame_to_ba_complete(priv, interfacePriv, frame_desc); + }else{ + unifi_trace(priv, UDBG6, "%s: old frame, drop: sn=%d, expected_sn=%d\n", __FUNCTION__, sn, ba_session->expected_sn); + unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); + } + } + return i; +} + + + +static void process_ba_frame(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + frame_desc_struct *frame_desc) +{ + int i; + CsrUint16 sn = frame_desc->sn; + + if (ba_session->timeout) { + mod_timer(&ba_session->timer, (jiffies + usecs_to_jiffies((ba_session->timeout) * 1024))); + } + unifi_trace(priv, UDBG6, "%s: got frame(sn=%d)\n", __FUNCTION__, sn); + + i = consume_frame_or_get_buffer_index(priv, interfacePriv, ba_session, sn, frame_desc); + if(i >= 0) { + unifi_trace(priv, UDBG6, "%s: store frame(sn=%d) at i = %d\n", __FUNCTION__, sn, i); + ba_session->buffer[i] = *frame_desc; + ba_session->buffer[i].recv_time = CsrTimeGet(NULL); + ba_session->occupied_slots++; + } else { + unifi_trace(priv, UDBG6, "%s: frame consumed - sn = %d\n", __FUNCTION__, sn); + } + complete_ready_sequence(priv, interfacePriv, ba_session); +} + + +static void process_ba_complete(unifi_priv_t *priv, netInterface_priv_t *interfacePriv) +{ + frame_desc_struct *frame_desc; + CsrUint8 i; + + for(i = 0; i < interfacePriv->ba_complete_index; i++) { + frame_desc = &interfacePriv->ba_complete[i]; + unifi_trace(priv, UDBG6, "%s: calling process_amsdu()\n", __FUNCTION__); + process_amsdu(priv, &frame_desc->signal, &frame_desc->bulkdata); + } + interfacePriv->ba_complete_index = 0; + +} + + +/* Check if the frames in BA reoder buffer has aged and + * if so release the frames to upper processes and move + * the window + */ +static void check_ba_frame_age_timeout( unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session) +{ + CsrTime now; + CsrTime age; + CsrUint8 i, j; + CsrUint16 sn_temp; + + /* gap is started at 1 because we have buffered frames and + * hence a minimum gap of 1 exists + */ + CsrUint8 gap=1; + + now = CsrTimeGet(NULL); + + if (ba_session->occupied_slots) + { + /* expected sequence has not arrived so start searching from next + * sequence number until a frame is available and determine the gap. + * Check if the frame available has timedout, if so advance the + * expected sequence number and release the frames + */ + sn_temp = (ba_session->expected_sn + 1) & 0xFFF; + + for(j = 0; j < ba_session->wind_size; j++) + { + i = SN_TO_INDEX(ba_session, sn_temp); + + if(ba_session->buffer[i].active) + { + unifi_trace(priv, UDBG6, "check age at slot index = %d sn = %d recv_time = %u now = %u\n", + i, + ba_session->buffer[i].sn, + ba_session->buffer[i].recv_time, + now); + + if (ba_session->buffer[i].recv_time > now) + { + /* timer wrap */ + age = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now); + } + else + { + age = (CsrTime)CsrTimeSub(now, ba_session->buffer[i].recv_time); + } + + if (age >= CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT) + { + unifi_trace(priv, UDBG2, "release the frame at index = %d gap = %d expected_sn = %d sn = %d\n", + i, + gap, + ba_session->expected_sn, + ba_session->buffer[i].sn); + + /* if it has timedout don't wait for missing frames, move the window */ + while (gap--) + { + ADVANCE_EXPECTED_SN(ba_session); + } + add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); + FREE_BUFFER_SLOT(ba_session, i); + complete_ready_sequence(priv, interfacePriv, ba_session); + } + break; + + } + else + { + /* advance temp sequence number and frame gap */ + sn_temp = (sn_temp + 1) & 0xFFF; + gap++; + } + } + } +} + + +static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) +{ + CsrUint16 interfaceTag; + const CSR_MA_PACKET_ERROR_INDICATION *pkt_err_ind = &signal->u.MaPacketErrorIndication; + netInterface_priv_t *interfacePriv; + ba_session_rx_struct *ba_session; + CsrUint8 ba_session_idx = 0; + CSR_PRIORITY UserPriority; + CSR_SEQUENCE_NUMBER sn; + + func_enter(); + + interfaceTag = (pkt_err_ind->VirtualInterfaceIdentifier & 0xff); + + + /* Sanity check that the VIF refers to a sensible interface */ + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "%s: MaPacketErrorIndication indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); + func_exit(); + return; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + UserPriority = pkt_err_ind->UserPriority; + if(UserPriority > 15) { + unifi_error(priv, "%s: MaPacketErrorIndication indication with bad UserPriority=%d\n", __FUNCTION__, UserPriority); + func_exit(); + } + sn = pkt_err_ind->SequenceNumber; + + spin_lock(&priv->ba_lock); + /* To find the right ba_session loop through the BA sessions, compare MAC address and tID */ + for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + ba_session = interfacePriv->ba_session_rx[ba_session_idx]; + if (ba_session){ + if ((!memcmp(ba_session->macAddress.a, pkt_err_ind->PeerQstaAddress.x, ETH_ALEN)) && (ba_session->tID == UserPriority)){ + if (ba_session->timeout) { + mod_timer(&ba_session->timer, (jiffies + usecs_to_jiffies((ba_session->timeout) * 1024))); + } + scroll_ba_window(priv, interfacePriv, ba_session, sn); + break; + } + } + } + + spin_unlock(&priv->ba_lock); + process_ba_complete(priv, interfacePriv); + func_exit(); +} + + diff --git a/drivers/staging/csr/os.c b/drivers/staging/csr/os.c new file mode 100644 index 000000000000..6dfce4226750 --- /dev/null +++ b/drivers/staging/csr/os.c @@ -0,0 +1,479 @@ +/* + * --------------------------------------------------------------------------- + * FILE: os.c + * + * PURPOSE: + * Routines to fulfil the OS-abstraction for the HIP lib. + * It is part of the porting exercise. + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + +/** + * The HIP lib OS abstraction consists of the implementation + * of the functions in this file. It is part of the porting exercise. + */ + +#include "unifi_priv.h" + + +/* + * --------------------------------------------------------------------------- + * unifi_net_data_malloc + * + * Allocate an OS specific net data buffer of "size" bytes. + * The bulk_data_slot.os_data_ptr must be initialised to point + * to the buffer allocated. The bulk_data_slot.length must be + * initialised to the requested size, zero otherwise. + * The bulk_data_slot.os_net_buf_ptr can be initialised to + * an OS specific pointer to be used in the unifi_net_data_free(). + * + * + * Arguments: + * ospriv Pointer to device private context struct. + * bulk_data_slot Pointer to the bulk data structure to initialise. + * size Size of the buffer to be allocated. + * + * Returns: + * CSR_RESULT_SUCCESS on success, CSR_RESULT_FAILURE otherwise. + * --------------------------------------------------------------------------- + */ +CsrResult +unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size) +{ + struct sk_buff *skb; + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + int rounded_length; + + if (priv->card_info.sdio_block_size == 0) { + unifi_error(priv, "unifi_net_data_malloc: Invalid SDIO block size\n"); + return CSR_RESULT_FAILURE; + } + + rounded_length = (size + priv->card_info.sdio_block_size - 1) & ~(priv->card_info.sdio_block_size - 1); + + /* + * (ETH_HLEN + 2) bytes tailroom for header manipulation + * CSR_WIFI_ALIGN_BYTES bytes headroom for alignment manipulation + */ + skb = dev_alloc_skb(rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES); + if (! skb) { + unifi_error(ospriv, "alloc_skb failed.\n"); + bulk_data_slot->os_net_buf_ptr = NULL; + bulk_data_slot->net_buf_length = 0; + bulk_data_slot->os_data_ptr = NULL; + bulk_data_slot->data_length = 0; + return CSR_RESULT_FAILURE; + } + + bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb; + bulk_data_slot->net_buf_length = rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES; + bulk_data_slot->os_data_ptr = (const void*)skb->data; + bulk_data_slot->data_length = size; + + return CSR_RESULT_SUCCESS; +} /* unifi_net_data_malloc() */ + +/* + * --------------------------------------------------------------------------- + * unifi_net_data_free + * + * Free an OS specific net data buffer. + * The bulk_data_slot.length must be initialised to 0. + * + * + * Arguments: + * ospriv Pointer to device private context struct. + * bulk_data_slot Pointer to the bulk data structure that + * holds the data to be freed. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot) +{ + struct sk_buff *skb; + CSR_UNUSED(ospriv); + + skb = (struct sk_buff *)bulk_data_slot->os_net_buf_ptr; + dev_kfree_skb(skb); + + bulk_data_slot->net_buf_length = 0; + bulk_data_slot->data_length = 0; + bulk_data_slot->os_data_ptr = bulk_data_slot->os_net_buf_ptr = NULL; + +} /* unifi_net_data_free() */ + + +/* +* --------------------------------------------------------------------------- +* unifi_net_dma_align +* +* DMA align an OS specific net data buffer. +* The buffer must be empty. +* +* +* Arguments: +* ospriv Pointer to device private context struct. +* bulk_data_slot Pointer to the bulk data structure that +* holds the data to be aligned. +* +* Returns: +* None. +* --------------------------------------------------------------------------- +*/ +CsrResult +unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot) +{ + struct sk_buff *skb; + unsigned long buf_address; + int offset; + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + if ((bulk_data_slot == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) { + return CSR_RESULT_SUCCESS; + } + + if ((bulk_data_slot->os_data_ptr == NULL) || (bulk_data_slot->data_length == 0)) { + return CSR_RESULT_SUCCESS; + } + + buf_address = (unsigned long)(bulk_data_slot->os_data_ptr) & (CSR_WIFI_ALIGN_BYTES - 1); + + unifi_trace(priv, UDBG5, + "unifi_net_dma_align: Allign buffer (0x%p) by %d bytes\n", + bulk_data_slot->os_data_ptr, buf_address); + + offset = CSR_WIFI_ALIGN_BYTES - buf_address; + if (offset < 0) { + unifi_error(priv, "unifi_net_dma_align: Failed (offset=%d)\n", offset); + return CSR_RESULT_FAILURE; + } + + skb = (struct sk_buff*)(bulk_data_slot->os_net_buf_ptr); + skb_reserve(skb, offset); + bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb; + bulk_data_slot->os_data_ptr = (const void*)(skb->data); + + return CSR_RESULT_SUCCESS; + +} /* unifi_net_dma_align() */ + +#ifdef ANDROID_TIMESTAMP +static volatile unsigned int printk_cpu = UINT_MAX; +char tbuf[30]; + +char* print_time(void ) +{ + unsigned long long t; + unsigned long nanosec_rem; + + t = cpu_clock(printk_cpu); + nanosec_rem = do_div(t, 1000000000); + sprintf(tbuf, "[%5lu.%06lu] ", + (unsigned long) t, + nanosec_rem / 1000); + + return tbuf; +} +#endif + + +/* Module parameters */ +extern int unifi_debug; + +#ifdef UNIFI_DEBUG +#define DEBUG_BUFFER_SIZE 120 + +#define FORMAT_TRACE(_s, _len, _args, _fmt) \ + do { \ + va_start(_args, _fmt); \ + _len += vsnprintf(&(_s)[_len], \ + (DEBUG_BUFFER_SIZE - _len), \ + _fmt, _args); \ + va_end(_args); \ + if (_len >= DEBUG_BUFFER_SIZE) { \ + (_s)[DEBUG_BUFFER_SIZE - 2] = '\n'; \ + (_s)[DEBUG_BUFFER_SIZE - 1] = 0; \ + } \ + } while (0) +#endif /* UNIFI_DEBUG */ + +void +unifi_error(void* ospriv, const char *fmt, ...) +{ +#ifdef UNIFI_DEBUG + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time()); + } +#else + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: "); + } +#endif /* ANDROID_TIMESTAMP */ + FORMAT_TRACE(s, len, args, fmt); + + printk("%s", s); +#endif /* UNIFI_DEBUG */ +} + +void +unifi_warning(void* ospriv, const char *fmt, ...) +{ +#ifdef UNIFI_DEBUG + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; + +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi%d: ", print_time(), priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi: ", print_time()); + } +#else + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi%d: ", priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi: "); + } +#endif /* ANDROID_TIMESTAMP */ + + FORMAT_TRACE(s, len, args, fmt); + + printk("%s", s); +#endif /* UNIFI_DEBUG */ +} + + +void +unifi_notice(void* ospriv, const char *fmt, ...) +{ +#ifdef UNIFI_DEBUG + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; + +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi%d: ", print_time(), priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi: ", print_time()); + } +#else + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi%d: ", priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi: "); + } +#endif /* ANDROID_TIMESTAMP */ + + FORMAT_TRACE(s, len, args, fmt); + + printk("%s", s); +#endif /* UNIFI_DEBUG */ +} + + +void +unifi_info(void* ospriv, const char *fmt, ...) +{ +#ifdef UNIFI_DEBUG + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; + +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi%d: ", print_time(), priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi: ", print_time()); + } +#else + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi%d: ", priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi: "); + } +#endif /* ANDROID_TIMESTAMP */ + + FORMAT_TRACE(s, len, args, fmt); + + printk("%s", s); +#endif /* UNIFI_DEBUG */ +} + +/* debugging */ +void +unifi_trace(void* ospriv, int level, const char *fmt, ...) +{ +#ifdef UNIFI_DEBUG + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; + + if (unifi_debug >= level) { +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time()); + } +#else + if (priv != NULL) { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance); + } else { + len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: "); + } +#endif /* ANDROID_TIMESTAMP */ + + FORMAT_TRACE(s, len, args, fmt); + + printk("%s", s); + } +#endif /* UNIFI_DEBUG */ +} + +/* + * --------------------------------------------------------------------------- + * + * Debugging support. + * + * --------------------------------------------------------------------------- + */ + +#ifdef UNIFI_DEBUG + +/* Memory dump with level filter controlled by unifi_debug */ +void +unifi_dump(void *ospriv, int level, const char *msg, void *mem, CsrUint16 len) +{ + unifi_priv_t *priv = (unifi_priv_t*) ospriv; + + if (unifi_debug >= level) { +#ifdef ANDROID_TIMESTAMP + if (priv != NULL) { + printk(KERN_ERR "%s unifi%d: --- dump: %s ---\n", print_time(), priv->instance, msg ? msg : ""); + } else { + printk(KERN_ERR "%s unifi: --- dump: %s ---\n", print_time(), msg ? msg : ""); + } +#else + if (priv != NULL) { + printk(KERN_ERR "unifi%d: --- dump: %s ---\n", priv->instance, msg ? msg : ""); + } else { + printk(KERN_ERR "unifi: --- dump: %s ---\n", msg ? msg : ""); + } +#endif /* ANDROID_TIMESTAMP */ + dump(mem, len); + + if (priv != NULL) { + printk(KERN_ERR "unifi%d: --- end of dump ---\n", priv->instance); + } else { + printk(KERN_ERR "unifi: --- end of dump ---\n"); + } + } +} + +/* Memory dump that appears all the time, use sparingly */ +void +dump(void *mem, CsrUint16 len) +{ + int i, col = 0; + unsigned char *pdata = (unsigned char *)mem; +#ifdef ANDROID_TIMESTAMP + printk("timestamp %s \n", print_time()); +#endif /* ANDROID_TIMESTAMP */ + if (mem == NULL) { + printk("(null dump)\n"); + return; + } + for (i = 0; i < len; i++) { + if (col == 0) { + printk("0x%02X: ", i); + } + + printk(" %02X", pdata[i]); + + if (++col == 16) { + printk("\n"); + col = 0; + } + } + if (col) { + printk("\n"); + } +} /* dump() */ + + +void +dump16(void *mem, CsrUint16 len) +{ + int i, col=0; + unsigned short *p = (unsigned short *)mem; +#ifdef ANDROID_TIMESTAMP + printk("timestamp %s \n", print_time()); +#endif /* ANDROID_TIMESTAMP */ + for (i = 0; i < len; i+=2) { + if (col == 0) { + printk("0x%02X: ", i); + } + + printk(" %04X", *p++); + + if (++col == 8) { + printk("\n"); + col = 0; + } + } + if (col) { + printk("\n"); + } +} + + +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +void +dump_str(void *mem, CsrUint16 len) +{ + int i, col = 0; + unsigned char *pdata = (unsigned char *)mem; +#ifdef ANDROID_TIMESTAMP + printk("timestamp %s \n", print_time()); +#endif /* ANDROID_TIMESTAMP */ + for (i = 0; i < len; i++) { + printk("%c", pdata[i]); + } + if (col) { + printk("\n"); + } + +} /* dump_str() */ +#endif /* CSR_ONLY_NOTES */ + + +#endif /* UNIFI_DEBUG */ + + +/* --------------------------------------------------------------------------- + * - End - + * ------------------------------------------------------------------------- */ diff --git a/drivers/staging/csr/putest.c b/drivers/staging/csr/putest.c new file mode 100644 index 000000000000..1b2c7c299a6c --- /dev/null +++ b/drivers/staging/csr/putest.c @@ -0,0 +1,664 @@ +/* + * *************************************************************************** + * FILE: putest.c + * + * PURPOSE: putest related functions. + * + * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ + +#include +#include + +#include "unifi_priv.h" +#include "csr_wifi_hip_chiphelper.h" + +#define UNIFI_PROC_BOTH 3 + + +int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg) +{ + struct unifi_putest_cmd52 cmd52_params; + CsrUint8 *arg_pos; + unsigned int cmd_param_size; + int r; + CsrResult csrResult; + unsigned char ret_buffer[32]; + CsrUint8 *ret_buffer_pos; + CsrUint8 retries; + + arg_pos = (CsrUint8*)(((unifi_putest_command_t*)arg) + 1); + if (get_user(cmd_param_size, (int*)arg_pos)) { + unifi_error(priv, + "unifi_putest_cmd52_read: Failed to get the argument\n"); + return -EFAULT; + } + + if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { + unifi_error(priv, + "unifi_putest_cmd52_read: cmd52 struct mismatch\n"); + return -EINVAL; + } + + arg_pos += sizeof(unsigned int); + if (copy_from_user(&cmd52_params, + (void*)arg_pos, + sizeof(struct unifi_putest_cmd52))) { + unifi_error(priv, + "unifi_putest_cmd52_read: Failed to get the cmd52 params\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "cmd52r: func=%d addr=0x%x ", + cmd52_params.funcnum, cmd52_params.addr); + + retries = 3; + CsrSdioClaim(priv->sdio); + do { + if (cmd52_params.funcnum == 0) { + csrResult = CsrSdioF0Read8(priv->sdio, cmd52_params.addr, &cmd52_params.data); + } else { + csrResult = CsrSdioRead8(priv->sdio, cmd52_params.addr, &cmd52_params.data); + } + } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); + CsrSdioRelease(priv->sdio); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "\nunifi_putest_cmd52_read: Read8() failed (csrResult=0x%x)\n", csrResult); + return -EFAULT; + } + unifi_trace(priv, UDBG2, "data=%d\n", cmd52_params.data); + + /* Copy the info to the out buffer */ + *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_CMD52_READ; + ret_buffer_pos = (CsrUint8*)(((unifi_putest_command_t*)ret_buffer) + 1); + *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_cmd52); + ret_buffer_pos += sizeof(unsigned int); + memcpy(ret_buffer_pos, &cmd52_params, sizeof(struct unifi_putest_cmd52)); + ret_buffer_pos += sizeof(struct unifi_putest_cmd52); + + r = copy_to_user((void*)arg, + ret_buffer, + ret_buffer_pos - ret_buffer); + if (r) { + unifi_error(priv, + "unifi_putest_cmd52_read: Failed to return the data\n"); + return -EFAULT; + } + + return 0; +} + + +int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg) +{ + struct unifi_putest_cmd52 cmd52_params; + CsrUint8 *arg_pos; + unsigned int cmd_param_size; + CsrResult csrResult; + CsrUint8 retries; + + arg_pos = (CsrUint8*)(((unifi_putest_command_t*)arg) + 1); + if (get_user(cmd_param_size, (int*)arg_pos)) { + unifi_error(priv, + "unifi_putest_cmd52_write: Failed to get the argument\n"); + return -EFAULT; + } + + if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { + unifi_error(priv, + "unifi_putest_cmd52_write: cmd52 struct mismatch\n"); + return -EINVAL; + } + + arg_pos += sizeof(unsigned int); + if (copy_from_user(&cmd52_params, + (void*)(arg_pos), + sizeof(struct unifi_putest_cmd52))) { + unifi_error(priv, + "unifi_putest_cmd52_write: Failed to get the cmd52 params\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "cmd52w: func=%d addr=0x%x data=%d\n", + cmd52_params.funcnum, cmd52_params.addr, cmd52_params.data); + + retries = 3; + CsrSdioClaim(priv->sdio); + do { + if (cmd52_params.funcnum == 0) { + csrResult = CsrSdioF0Write8(priv->sdio, cmd52_params.addr, cmd52_params.data); + } else { + csrResult = CsrSdioWrite8(priv->sdio, cmd52_params.addr, cmd52_params.data); + } + } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); + CsrSdioRelease(priv->sdio); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_cmd52_write: Write8() failed (csrResult=0x%x)\n", csrResult); + return -EFAULT; + } + + return 0; +} + +int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg) +{ + struct unifi_putest_gp_rw16 gp_r16_params; + CsrUint8 *arg_pos; + unsigned int cmd_param_size; + int r; + CsrResult csrResult; + unsigned char ret_buffer[32]; + CsrUint8 *ret_buffer_pos; + + arg_pos = (CsrUint8*)(((unifi_putest_command_t*)arg) + 1); + if (get_user(cmd_param_size, (int*)arg_pos)) { + unifi_error(priv, + "unifi_putest_gp_read16: Failed to get the argument\n"); + return -EFAULT; + } + + if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { + unifi_error(priv, + "unifi_putest_gp_read16: struct mismatch\n"); + return -EINVAL; + } + + arg_pos += sizeof(unsigned int); + if (copy_from_user(&gp_r16_params, + (void*)arg_pos, + sizeof(struct unifi_putest_gp_rw16))) { + unifi_error(priv, + "unifi_putest_gp_read16: Failed to get the params\n"); + return -EFAULT; + } + + csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "gp_r16: GP=0x%08x, data=0x%04x\n", gp_r16_params.addr, gp_r16_params.data); + + /* Copy the info to the out buffer */ + *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_GP_READ16; + ret_buffer_pos = (CsrUint8*)(((unifi_putest_command_t*)ret_buffer) + 1); + *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_gp_rw16); + ret_buffer_pos += sizeof(unsigned int); + memcpy(ret_buffer_pos, &gp_r16_params, sizeof(struct unifi_putest_gp_rw16)); + ret_buffer_pos += sizeof(struct unifi_putest_gp_rw16); + + r = copy_to_user((void*)arg, + ret_buffer, + ret_buffer_pos - ret_buffer); + if (r) { + unifi_error(priv, + "unifi_putest_gp_read16: Failed to return the data\n"); + return -EFAULT; + } + + return 0; +} + +int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg) +{ + struct unifi_putest_gp_rw16 gp_w16_params; + CsrUint8 *arg_pos; + unsigned int cmd_param_size; + CsrResult csrResult; + + arg_pos = (CsrUint8*)(((unifi_putest_command_t*)arg) + 1); + if (get_user(cmd_param_size, (int*)arg_pos)) { + unifi_error(priv, + "unifi_putest_gp_write16: Failed to get the argument\n"); + return -EFAULT; + } + + if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { + unifi_error(priv, + "unifi_putest_gp_write16: struct mismatch\n"); + return -EINVAL; + } + + arg_pos += sizeof(unsigned int); + if (copy_from_user(&gp_w16_params, + (void*)(arg_pos), + sizeof(struct unifi_putest_gp_rw16))) { + unifi_error(priv, + "unifi_putest_gp_write16: Failed to get the params\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data); + + csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult); + return -EFAULT; + } + + return 0; +} + +int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg) +{ + int sdio_clock_speed; + CsrResult csrResult; + + if (get_user(sdio_clock_speed, (int*)(((unifi_putest_command_t*)arg) + 1))) { + unifi_error(priv, + "unifi_putest_set_sdio_clock: Failed to get the argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed); + + CsrSdioClaim(priv->sdio); + csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed); + CsrSdioRelease(priv->sdio); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_set_sdio_clock: Set clock failed (csrResult=0x%x)\n", csrResult); + return -EFAULT; + } + + return 0; +} + + +int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg) +{ + int r; + CsrResult csrResult; + int already_in_test = priv->ptest_mode; + + /* Ensure that sme_sys_suspend() doesn't power down the chip because: + * 1) Power is needed anyway for ptest. + * 2) The app code uses the START ioctl as a reset, so it gets called + * multiple times. If the app stops the XAPs, but the power_down/up + * sequence doesn't actually power down the chip, there can be problems + * resetting, because part of the power_up sequence disables function 1 + */ + priv->ptest_mode = 1; + + /* Suspend the SME and UniFi */ + if (priv->sme_cli) { + r = sme_sys_suspend(priv); + if (r) { + unifi_error(priv, + "unifi_putest_start: failed to suspend UniFi\n"); + return r; + } + } + + /* Application may have stopped the XAPs, but they are needed for reset */ + if (already_in_test) { + csrResult = unifi_start_processors(priv->card); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); + } + } else { + /* Ensure chip is powered for the case where there's no unifi_helper */ + CsrSdioClaim(priv->sdio); + csrResult = CsrSdioPowerOn(priv->sdio); + CsrSdioRelease(priv->sdio); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult); + } + } + + csrResult = unifi_init(priv->card); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_start: failed to init UniFi\n"); + return CsrHipResultToStatus(csrResult); + } + + return 0; +} + + +int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg) +{ + int r = 0; + CsrResult csrResult; + + /* Application may have stopped the XAPs, but they are needed for reset */ + csrResult = unifi_start_processors(priv->card); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); + } + + /* PUTEST_STOP is also used to resume the XAPs after SME coredump. + * Don't power off the chip, leave that to the normal wifi-off which is + * about to carry on. No need to resume the SME either, as it wasn't suspended. + */ + if (priv->coredump_mode) { + priv->coredump_mode = 0; + return 0; + } + + /* At this point function 1 is enabled and the XAPs are running, so it is + * safe to let the card power down. Power is restored later, asynchronously, + * during the wifi_on requested by the SME. + */ + CsrSdioClaim(priv->sdio); + CsrSdioPowerOff(priv->sdio); + CsrSdioRelease(priv->sdio); + + /* Resume the SME and UniFi */ + if (priv->sme_cli) { + r = sme_sys_resume(priv); + if (r) { + unifi_error(priv, + "unifi_putest_stop: failed to resume SME\n"); + } + } + priv->ptest_mode = 0; + + return r; +} + + +int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) +{ +#define UF_PUTEST_MAX_FW_FILE_NAME 16 +#define UNIFI_MAX_FW_PATH_LEN 32 + unsigned int fw_name_length; + unsigned char fw_name[UF_PUTEST_MAX_FW_FILE_NAME+1]; + unsigned char *name_buffer; + int postfix; + char fw_path[UNIFI_MAX_FW_PATH_LEN]; + const struct firmware *fw_entry; + struct dlpriv temp_fw_sta; + int r; + CsrResult csrResult; + + /* Get the f/w file name length */ + if (get_user(fw_name_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { + unifi_error(priv, + "unifi_putest_dl_fw: Failed to get the length argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file name size = %d\n", fw_name_length); + + /* Sanity check for the f/w file name length */ + if (fw_name_length > UF_PUTEST_MAX_FW_FILE_NAME) { + unifi_error(priv, + "unifi_putest_dl_fw: F/W file name is too long\n"); + return -EINVAL; + } + + /* Get the f/w file name */ + name_buffer = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); + if (copy_from_user(fw_name, (void*)name_buffer, fw_name_length)) { + unifi_error(priv, "unifi_putest_dl_fw: Failed to get the file name\n"); + return -EFAULT; + } + fw_name[fw_name_length] = '\0'; + unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file = %s\n", fw_name); + + /* Keep the existing f/w to a temp, we need to restore it later */ + temp_fw_sta = priv->fw_sta; + + /* Get the putest f/w */ + postfix = priv->instance; + scnprintf(fw_path, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", + postfix, fw_name); + r = request_firmware(&fw_entry, fw_path, priv->unifi_device); + if (r == 0) { + priv->fw_sta.fw_desc = (void *)fw_entry; + priv->fw_sta.dl_data = fw_entry->data; + priv->fw_sta.dl_len = fw_entry->size; + } else { + unifi_error(priv, "Firmware file not available\n"); + return -EINVAL; + } + + /* Application may have stopped the XAPs, but they are needed for reset */ + csrResult = unifi_start_processors(priv->card); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); + } + + /* Download the f/w. On UF6xxx this will cause the f/w file to convert + * into patch format and download via the ROM boot loader + */ + csrResult = unifi_download(priv->card, 0x0c00); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_dl_fw: failed to download the f/w\n"); + goto free_fw; + } + + /* Free the putest f/w... */ +free_fw: + uf_release_firmware(priv, &priv->fw_sta); + /* ... and restore the original f/w */ + priv->fw_sta = temp_fw_sta; + + return CsrHipResultToStatus(csrResult); +} + + +int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg) +{ + unsigned int fw_length; + unsigned char *fw_buf = NULL; + unsigned char *fw_user_ptr; + struct dlpriv temp_fw_sta; + CsrResult csrResult; + + /* Get the f/w buffer length */ + if (get_user(fw_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { + unifi_error(priv, + "unifi_putest_dl_fw_buff: Failed to get the length arg\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "unifi_putest_dl_fw_buff: size = %d\n", fw_length); + + /* Sanity check for the buffer length */ + if (fw_length == 0 || fw_length > 0xfffffff) { + unifi_error(priv, + "unifi_putest_dl_fw_buff: buffer length bad %u\n", fw_length); + return -EINVAL; + } + + /* Buffer for kernel copy of the f/w image */ + fw_buf = CsrPmemAlloc(fw_length); + if (!fw_buf) { + unifi_error(priv, "unifi_putest_dl_fw_buff: malloc fail\n"); + return -ENOMEM; + } + + /* Get the f/w image */ + fw_user_ptr = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); + if (copy_from_user(fw_buf, (void*)fw_user_ptr, fw_length)) { + unifi_error(priv, "unifi_putest_dl_fw_buff: Failed to get the buffer\n"); + CsrPmemFree(fw_buf); + return -EFAULT; + } + + /* Save the existing f/w to a temp, we need to restore it later */ + temp_fw_sta = priv->fw_sta; + + /* Setting fw_desc NULL indicates to the core that no f/w file was loaded + * via the kernel request_firmware() mechanism. This indicates to the core + * that it shouldn't call release_firmware() after the download is done. + */ + priv->fw_sta.fw_desc = NULL; /* No OS f/w resource */ + priv->fw_sta.dl_data = fw_buf; + priv->fw_sta.dl_len = fw_length; + + /* Application may have stopped the XAPs, but they are needed for reset */ + csrResult = unifi_start_processors(priv->card); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); + } + + /* Download the f/w. On UF6xxx this will cause the f/w file to convert + * into patch format and download via the ROM boot loader + */ + csrResult = unifi_download(priv->card, 0x0c00); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, + "unifi_putest_dl_fw_buff: failed to download the f/w\n"); + goto free_fw; + } + +free_fw: + /* Finished with the putest f/w, so restore the station f/w */ + priv->fw_sta = temp_fw_sta; + CsrPmemFree(fw_buf); + + return CsrHipResultToStatus(csrResult); +} + + +int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg) +{ + CsrUint16 data_u16; + CsrInt32 i; + CsrResult r; + + unifi_info(priv, "Preparing for SDIO coredump\n"); +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) + unifi_debug_buf_dump(); +#endif + + /* Sanity check that userspace hasn't called a PUTEST_START, because that + * would have reset UniFi, potentially power cycling it and losing context + */ + if (priv->ptest_mode) { + unifi_error(priv, "PUTEST_START shouldn't be used before a coredump\n"); + } + + /* Flag that the userspace has requested coredump. Even if this preparation + * fails, the SME will call PUTEST_STOP to tidy up. + */ + priv->coredump_mode = 1; + + for (i = 0; i < 3; i++) { + CsrSdioClaim(priv->sdio); + r = CsrSdioRead16(priv->sdio, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION*2, &data_u16); + CsrSdioRelease(priv->sdio); + if (r != CSR_RESULT_SUCCESS) { + unifi_info(priv, "Failed to read chip version! Try %d\n", i); + + /* First try, re-enable function which may have been disabled by f/w panic */ + if (i == 0) { + unifi_info(priv, "Try function enable\n"); + CsrSdioClaim(priv->sdio); + r = CsrSdioFunctionEnable(priv->sdio); + CsrSdioRelease(priv->sdio); + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrSdioFunctionEnable failed %d\n", r); + } + continue; + } + + /* Subsequent tries, reset */ + + /* Set clock speed low */ + CsrSdioClaim(priv->sdio); + r = CsrSdioMaxBusClockFrequencySet(priv->sdio, UNIFI_SDIO_CLOCK_SAFE_HZ); + CsrSdioRelease(priv->sdio); + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrSdioMaxBusClockFrequencySet() failed %d\n", r); + } + + /* Card software reset */ + r = unifi_card_hard_reset(priv->card); + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r); + } + } else { + unifi_info(priv, "Read chip version of 0x%04x\n", data_u16); + break; + } + } + + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to prepare chip\n"); + return -EIO; + } + + /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at + * Raw SDIO deinit, to resume them. + */ + r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH); + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Failed to stop processors\n"); + } + + return 0; +} + +int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg) +{ + struct unifi_putest_block_cmd52_r block_cmd52; + CsrUint8 *arg_pos; + unsigned int cmd_param_size; + CsrResult r; + CsrUint8 *block_local_buffer; + + arg_pos = (CsrUint8*)(((unifi_putest_command_t*)arg) + 1); + if (get_user(cmd_param_size, (int*)arg_pos)) { + unifi_error(priv, + "cmd52r_block: Failed to get the argument\n"); + return -EFAULT; + } + + if (cmd_param_size != sizeof(struct unifi_putest_block_cmd52_r)) { + unifi_error(priv, + "cmd52r_block: cmd52 struct mismatch\n"); + return -EINVAL; + } + + arg_pos += sizeof(unsigned int); + if (copy_from_user(&block_cmd52, + (void*)arg_pos, + sizeof(struct unifi_putest_block_cmd52_r))) { + unifi_error(priv, + "cmd52r_block: Failed to get the cmd52 params\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG2, "cmd52r_block: func=%d addr=0x%x len=0x%x ", + block_cmd52.funcnum, block_cmd52.addr, block_cmd52.length); + + block_local_buffer = vmalloc(block_cmd52.length); + if (block_local_buffer == NULL) { + unifi_error(priv, "cmd52r_block: Failed to allocate buffer\n"); + return -ENOMEM; + } + + r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length); + if (r != CSR_RESULT_SUCCESS) { + unifi_error(priv, "cmd52r_block: unifi_readn failed\n"); + return -EIO; + } + + if (copy_to_user((void*)block_cmd52.data, + block_local_buffer, + block_cmd52.length)) { + unifi_error(priv, + "cmd52r_block: Failed to return the data\n"); + return -EFAULT; + } + + return 0; +} diff --git a/drivers/staging/csr/sdio_emb.c b/drivers/staging/csr/sdio_emb.c new file mode 100644 index 000000000000..f61fdb130e61 --- /dev/null +++ b/drivers/staging/csr/sdio_emb.c @@ -0,0 +1,732 @@ +/* + * --------------------------------------------------------------------------- + * + * FILE: sdio_emb.c + * + * PURPOSE: Driver instantiation and deletion for SDIO on Linux. + * + * This file brings together the SDIO bus interface, the UniFi + * driver core and the Linux net_device stack. + * + * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include +#include +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + +#include "sdioemb/sdio_api.h" + +/* The function driver context, i.e the UniFi Driver */ +static CsrSdioFunctionDriver *sdio_func_drv; + + + +/* sdioemb driver uses POSIX error codes */ +static CsrResult +ConvertSdioToCsrSdioResult(int r) +{ + CsrResult csrResult = CSR_RESULT_FAILURE; + + switch (r) { + case 0: + csrResult = CSR_RESULT_SUCCESS; + break; + case -EIO: + csrResult = CSR_SDIO_RESULT_CRC_ERROR; + break; + /* Timeout errors */ + case -ETIMEDOUT: + case -EBUSY: + csrResult = CSR_SDIO_RESULT_TIMEOUT; + break; + case -ENODEV: + case -ENOMEDIUM: + csrResult = CSR_SDIO_RESULT_NO_DEVICE; + break; + case -EINVAL: + csrResult = CSR_SDIO_RESULT_INVALID_VALUE; + break; + case -ENOMEM: + case -ENOSYS: + case -EILSEQ: + case -ERANGE: + case -ENXIO: + csrResult = CSR_RESULT_FAILURE; + break; + default: + unifi_warning(NULL, "Unrecognised SDIO error code: %d\n", r); + break; + } + + return csrResult; +} + + +CsrResult +CsrSdioRead8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_read8(fdev, address, data); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead8() */ + +CsrResult +CsrSdioWrite8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_write8(fdev, address, data); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite8() */ + +CsrResult +CsrSdioRead16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + r = sdioemb_read16(fdev, address, data); + if (r) { + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead16() */ + +CsrResult +CsrSdioWrite16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + r = sdioemb_write16(fdev, address, data); + if (r) { + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite16() */ + + +CsrResult +CsrSdioF0Read8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_f0_read8(fdev, address, data); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioF0Read8() */ + + +CsrResult +CsrSdioF0Write8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_f0_write8(fdev, address, data); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioF0Write8() */ + +CsrResult +CsrSdioRead(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_read(fdev, address, data, length); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead() */ + +CsrResult +CsrSdioWrite(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int err; + err = sdioemb_write(fdev, address, data, length); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite() */ + + +CsrResult +CsrSdioBlockSizeSet(CsrSdioFunction *function, CsrUint16 blockSize) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r = 0; + + /* Module parameter overrides */ + if (sdio_block_size > -1) { + blockSize = sdio_block_size; + } + + unifi_trace(NULL, UDBG1, "Set SDIO function block size to %d\n", + blockSize); + + r = sdioemb_set_block_size(fdev, blockSize); + if (r) { + unifi_error(NULL, "Error %d setting block size\n", r); + } + + /* Determine the achieved block size to report to the core */ + function->blockSize = fdev->blocksize; + + return ConvertSdioToCsrSdioResult(r); +} /* CsrSdioBlockSizeSet() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioMaxBusClockFrequencySet + * + * Set the maximum SDIO bus clock speed to use. + * + * Arguments: + * sdio SDIO context pointer + * maxFrequency maximum clock speed in Hz + * + * Returns: + * an error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, CsrUint32 maxFrequency) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + CsrUint32 max_khz = maxFrequency/1000; + + if (!max_khz || max_khz > sdio_clock) { + max_khz = sdio_clock; + } + unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", max_khz); + sdioemb_set_max_bus_freq(fdev, 1000 * max_khz); + + return CSR_RESULT_SUCCESS; +} /* CsrSdioMaxBusClockFrequencySet() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioInterruptEnable + * CsrSdioInterruptDisable + * + * Enable or disable the SDIO interrupt. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * Zero on success or a UniFi driver error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioInterruptEnable(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + r = sdioemb_interrupt_enable(fdev); + if (r) { + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioInterruptEnable() */ + +CsrResult +CsrSdioInterruptDisable(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + r = sdioemb_interrupt_disable(fdev); + if (r) { + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioInterruptDisable() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioInterruptAcknowledge + * + * Acknowledge an SDIO interrupt. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * Zero on success or a UniFi driver error code. + * --------------------------------------------------------------------------- + */ +void CsrSdioInterruptAcknowledge(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + + sdioemb_interrupt_acknowledge(fdev); +} /* CsrSdioInterruptAcknowledge() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionEnable + * + * Enable i/o on this function. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionEnable(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + /* Enable UniFi function (the 802.11 part). */ + r = sdioemb_enable_function(fdev); + if (r) { + unifi_error(NULL, "Failed to enable SDIO function %d\n", fdev->function); + return ConvertSdioToCsrSdioResult(r); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioFunctionEnable() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionDisable + * + * Disable i/o on this function. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionDisable(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + /* Disable UniFi function (the 802.11 part). */ + r = sdioemb_disable_function(fdev); + if (r) { + unifi_error(NULL, "Failed to disable SDIO function %d\n", fdev->function); + return ConvertSdioToCsrSdioResult(r); + } + return CSR_RESULT_SUCCESS; +} /* CsrSdioFunctionDisable() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionActive + * + * No-op as the bus goes to an active state at the start of every + * command. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +void +CsrSdioFunctionActive(CsrSdioFunction *function) +{ +} /* CsrSdioFunctionActive() */ + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionIdle + * + * Set the function as idle. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +void +CsrSdioFunctionIdle(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + + sdioemb_idle_function(fdev); +} /* CsrSdioFunctionIdle() */ + + +CsrResult +CsrSdioPowerOn(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + + if (disable_power_control != 1) { + sdioemb_power_on(fdev); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioPowerOn() */ + +void +CsrSdioPowerOff(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + if (disable_power_control != 1) { + sdioemb_power_off(fdev); + } +} /* CsrSdioPowerOff() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioHardReset + * + * Hard Resets UniFi is possible. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * 1 if the SDIO driver is not capable of doing a hard reset. + * 0 if a hard reset was successfully performed. + * -CSR_EIO if an I/O error occured while re-initializing the card. + * This is a fatal, non-recoverable error. + * -CSR_ENODEV if the card is no longer present. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioHardReset(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + int r; + + /* Hard reset can be disabled by a module parameter */ + r = 1; + if (disable_hw_reset != 1) { + r = sdioemb_hard_reset(fdev); /* may return 1 if can't reset */ + if (r < 0) { + return ConvertSdioToCsrSdioResult(r); /* fatal error */ + } + } + + /* Set the SDIO bus width after a hard reset */ + if (buswidth == 1) { + unifi_info(NULL, "Setting SDIO bus width to 1\n"); + sdioemb_set_bus_width(fdev, buswidth); + } else if (buswidth == 4) { + unifi_info(NULL, "Setting SDIO bus width to 4\n"); + sdioemb_set_bus_width(fdev, buswidth); + } + + if(r == 1) + { + return CSR_SDIO_RESULT_NOT_RESET; + } + + return ConvertSdioToCsrSdioResult(r); + +} /* CsrSdioHardReset() */ + + +int csr_sdio_linux_remove_irq(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + + return sdioemb_interrupt_disable(fdev); +} + +int csr_sdio_linux_install_irq(CsrSdioFunction *function) +{ + struct sdioemb_dev *fdev = (struct sdioemb_dev *)function->priv; + + return sdioemb_interrupt_enable(fdev); +} + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_int_handler + * Card interrupt callback. + * + * Arguments: + * fdev SDIO context pointer + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +uf_glue_sdio_int_handler(struct sdioemb_dev *fdev) +{ + CsrSdioFunction *sdio_ctx = fdev->drv_data; + CsrSdioInterruptDsrCallback func_dsr_callback; + + /* If the function driver has registered a handler, call it */ + if (sdio_func_drv && sdio_func_drv->intr) { + /* The function driver may return a DSR. */ + func_dsr_callback = sdio_func_drv->intr(sdio_ctx); + /* If it did return a DSR handle, call it */ + if (func_dsr_callback) { + func_dsr_callback(sdio_ctx); + } + } +} + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_probe + * + * Card insert callback. + * + * Arguments: + * fdev SDIO context pointer + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +static int +uf_glue_sdio_probe(struct sdioemb_dev *fdev) +{ + CsrSdioFunction *sdio_ctx; + + unifi_info(NULL, "UniFi card inserted\n"); + + /* Allocate context and private in one lump */ + sdio_ctx = (CsrSdioFunction *)kmalloc(sizeof(CsrSdioFunction), + GFP_KERNEL); + if (sdio_ctx == NULL) { + return -ENOMEM; + } + + + sdio_ctx->sdioId.manfId = fdev->vendor_id; + sdio_ctx->sdioId.cardId = fdev->device_id; + sdio_ctx->sdioId.sdioFunction = fdev->function; + sdio_ctx->sdioId.sdioInterface = 0; + sdio_ctx->blockSize = fdev->blocksize; + sdio_ctx->priv = (void *)fdev; + sdio_ctx->features = 0; + + /* Module parameter enables byte mode */ + if (sdio_byte_mode) { + sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE; + } + + /* Set up pointer to func_priv in middle of lump */ + fdev->drv_data = sdio_ctx; + + /* Always override default SDIO bus clock */ + unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", sdio_clock); + sdioemb_set_max_bus_freq(fdev, 1000 * sdio_clock); + + /* Call the main UniFi driver inserted handler */ + if (sdio_func_drv && sdio_func_drv->inserted) { + uf_add_os_device(fdev->slot_id, fdev->os_device); + sdio_func_drv->inserted(sdio_ctx); + } + + return 0; +} /* uf_glue_sdio_probe() */ + + +/* + * --------------------------------------------------------------------------- + * uf_sdio_remove + * + * Card removal callback. + * + * Arguments: + * fdev SDIO device + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +static void +uf_sdio_remove(struct sdioemb_dev *fdev) +{ + CsrSdioFunction *sdio_ctx = fdev->drv_data; + + unifi_info(NULL, "UniFi card removed\n"); + + /* Clean up the SDIO function driver */ + if (sdio_func_drv && sdio_func_drv->removed) { + sdio_func_drv->removed(sdio_ctx); + } + + kfree(sdio_ctx); + +} /* uf_sdio_remove */ + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_suspend + * + * System suspend callback. + * + * Arguments: + * fdev SDIO device + * + * Returns: + * + * --------------------------------------------------------------------------- + */ +static void +uf_glue_sdio_suspend(struct sdioemb_dev *fdev) +{ + CsrSdioFunction *sdio_ctx = fdev->drv_data; + + unifi_trace(NULL, UDBG3, "Suspending...\n"); + + /* Pass event to UniFi Driver. */ + if (sdio_func_drv && sdio_func_drv->suspend) { + sdio_func_drv->suspend(sdio_ctx); + } + +} /* uf_glue_sdio_suspend() */ + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_resume + * + * System resume callback. + * + * Arguments: + * fdev SDIO device + * + * Returns: + * + * --------------------------------------------------------------------------- + */ +static void +uf_glue_sdio_resume(struct sdioemb_dev *fdev) +{ + CsrSdioFunction *sdio_ctx = fdev->drv_data; + + unifi_trace(NULL, UDBG3, "Resuming...\n"); + + /* Pass event to UniFi Driver. */ + if (sdio_func_drv && sdio_func_drv->resume) { + sdio_func_drv->resume(sdio_ctx); + } +} /* uf_glue_sdio_resume() */ + + + + +static struct sdioemb_func_driver unifi_sdioemb = { + .name = "unifi", + .id_table = NULL, /* Filled in when main driver registers */ + + .probe = uf_glue_sdio_probe, + .remove = uf_sdio_remove, + .card_int_handler = uf_glue_sdio_int_handler, + .suspend = uf_glue_sdio_suspend, + .resume = uf_glue_sdio_resume, +}; + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionDriverRegister + * CsrSdioFunctionDriverUnregister + * + * These functions are called from the main module load and unload + * functions. They perform the appropriate operations for the + * SDIOemb driver. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) +{ + int r; + int i; + + printk("Unifi: Using CSR embedded SDIO driver\n"); + + if (sdio_func_drv) { + unifi_error(NULL, "sdio_emb: UniFi driver already registered\n"); + return CSR_SDIO_RESULT_INVALID_VALUE; + } + + /* Build ID table to pass to sdioemb */ + unifi_sdioemb.id_table = CsrPmemAlloc(sizeof(struct sdioemb_id_table) * (sdio_drv->idsCount + 1)); + if (unifi_sdioemb.id_table == NULL) { + unifi_error(NULL, "sdio_emb: Failed to allocate memory for ID table (%d IDs)\n", sdio_drv->idsCount); + return CSR_RESULT_FAILURE; + } + for (i = 0; i < sdio_drv->idsCount; i++) { + unifi_sdioemb.id_table[i].vendor_id = sdio_drv->ids[i].manfId; + unifi_sdioemb.id_table[i].device_id = sdio_drv->ids[i].cardId; + unifi_sdioemb.id_table[i].function = sdio_drv->ids[i].sdioFunction; + unifi_sdioemb.id_table[i].interface = sdio_drv->ids[i].sdioInterface; + } + unifi_sdioemb.id_table[i].vendor_id = 0; + unifi_sdioemb.id_table[i].device_id = 0; + unifi_sdioemb.id_table[i].function = 0; + unifi_sdioemb.id_table[i].interface = 0; + + /* Save the registered driver description */ + sdio_func_drv = sdio_drv; + + /* Register ourself with sdioemb */ + r = sdioemb_driver_register(&unifi_sdioemb); + if (r) { + unifi_error(NULL, "Failed to register UniFi SDIO driver: %d\n", r); + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioFunctionDriverRegister() */ + + +void +CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv) +{ + sdioemb_driver_unregister(&unifi_sdioemb); + + sdio_func_drv = NULL; + + CsrPmemFree(unifi_sdioemb.id_table); + unifi_sdioemb.id_table = NULL; +} /* CsrSdioFunctionDriverUnregister() */ + diff --git a/drivers/staging/csr/sdio_events.c b/drivers/staging/csr/sdio_events.c new file mode 100644 index 000000000000..e4f2d0d82fbf --- /dev/null +++ b/drivers/staging/csr/sdio_events.c @@ -0,0 +1,87 @@ +/* + * --------------------------------------------------------------------------- + * FILE: sdio_events.c + * + * PURPOSE: + * Process the events received by the SDIO glue layer. + * Optional part of the porting exercise. + * + * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "unifi_priv.h" + + +/* + * Porting Notes: + * There are two ways to support the suspend/resume system events in a driver. + * In some operating systems these events are delivered to the OS driver + * directly from the system. In this case, the OS driver needs to pass these + * events to the API described in the CSR SDIO Abstration API document. + * In Linux, and other embedded operating systems, the suspend/resume events + * come from the SDIO driver. In this case, simply get these events in the + * SDIO glue layer and notify the OS layer. + * + * In either case, typically, the events are processed by the SME. + * Use the unifi_sys_suspend_ind() and unifi_sys_resume_ind() to pass + * the events to the SME. + */ + +/* + * --------------------------------------------------------------------------- + * unifi_suspend + * + * Handles a suspend request from the SDIO driver. + * + * Arguments: + * ospriv Pointer to OS driver context. + * + * --------------------------------------------------------------------------- + */ +void unifi_suspend(void *ospriv) +{ + unifi_priv_t *priv = ospriv; + int interfaceTag=0; + + /* Stop network traffic. */ + /* need to stop all the netdevices*/ + for( interfaceTag=0;interfaceTaginterfacePriv[interfaceTag]; + if (interfacePriv->netdev_registered == 1) + { + netif_carrier_off(priv->netdev[interfaceTag]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); + } + } + sme_sys_suspend(priv); +} /* unifi_suspend() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_resume + * + * Handles a resume request from the SDIO driver. + * + * Arguments: + * ospriv Pointer to OS driver context. + * + * --------------------------------------------------------------------------- + */ +void unifi_resume(void *ospriv) +{ + unifi_priv_t *priv = ospriv; + int r; + + r = sme_sys_resume(priv); + if (r) { + unifi_error(priv, "Failed to resume UniFi\n"); + } + +} /* unifi_resume() */ + diff --git a/drivers/staging/csr/sdio_mmc.c b/drivers/staging/csr/sdio_mmc.c new file mode 100644 index 000000000000..c8508341597a --- /dev/null +++ b/drivers/staging/csr/sdio_mmc.c @@ -0,0 +1,1165 @@ +/* + * --------------------------------------------------------------------------- + * + * FILE: sdio_mmc.c + * + * PURPOSE: SDIO driver interface for generic MMC stack. + * + * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. + * + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "unifi_priv.h" + + +static CsrSdioFunctionDriver *sdio_func_drv; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +/* + * We need to keep track of the power on/off because we can not call + * mmc_power_restore_host() when the card is already powered. + * Even then, we need to patch the MMC driver to add a power_restore handler + * in the mmc_sdio_ops structure. If the MMC driver is not patched, + * mmc_power_save_host() and mmc_power_restore_host() are no-ops. + */ +static int card_is_powered = 1; +#endif /* 2.6.32 */ + +/* MMC uses ENOMEDIUM to indicate card gone away */ + +static CsrResult +ConvertSdioToCsrSdioResult(int r) +{ + CsrResult csrResult = CSR_RESULT_FAILURE; + + switch (r) { + case 0: + csrResult = CSR_RESULT_SUCCESS; + break; + case -EIO: + case -EILSEQ: + csrResult = CSR_SDIO_RESULT_CRC_ERROR; + break; + /* Timeout errors */ + case -ETIMEDOUT: + case -EBUSY: + csrResult = CSR_SDIO_RESULT_TIMEOUT; + break; + case -ENODEV: + case -ENOMEDIUM: + csrResult = CSR_SDIO_RESULT_NO_DEVICE; + break; + case -EINVAL: + csrResult = CSR_SDIO_RESULT_INVALID_VALUE; + break; + case -ENOMEM: + case -ENOSYS: + case -ERANGE: + case -ENXIO: + csrResult = CSR_RESULT_FAILURE; + break; + default: + unifi_warning(NULL, "Unrecognised SDIO error code: %d\n", r); + break; + } + + return csrResult; +} + + +static int +csr_io_rw_direct(struct mmc_card *card, int write, uint8_t fn, + uint32_t addr, uint8_t in, uint8_t* out) +{ + struct mmc_command cmd; + int err; + + BUG_ON(!card); + BUG_ON(fn > 7); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_IO_RW_DIRECT; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= fn << 28; + cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; + cmd.arg |= addr << 9; + cmd.arg |= in; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (err) + return err; + + /* this function is not exported, so we will need to sort it out here + * for now, lets hard code it to sdio */ + if (0) { + /* old arg (mmc_host_is_spi(card->host)) { */ + /* host driver already reported errors */ + } else { + if (cmd.resp[0] & R5_ERROR) { + printk(KERN_ERR "%s: r5 error 0x%02x\n", + __FUNCTION__, cmd.resp[0]); + return -EIO; + } + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -EINVAL; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -ERANGE; + } + + if (out) { + if (0) { /* old argument (mmc_host_is_spi(card->host)) */ + *out = (cmd.resp[0] >> 8) & 0xFF; + } + else { + *out = cmd.resp[0] & 0xFF; + } + } + + return CSR_RESULT_SUCCESS; +} + + +CsrResult +CsrSdioRead8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + + _sdio_claim_host(func); + *data = sdio_readb(func, address, &err); + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead8() */ + +CsrResult +CsrSdioWrite8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + + _sdio_claim_host(func); + sdio_writeb(func, data, address, &err); + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite8() */ + +CsrResult +CsrSdioRead16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + uint8_t b0, b1; + + _sdio_claim_host(func); + b0 = sdio_readb(func, address, &err); + if (err) { + _sdio_release_host(func); + return ConvertSdioToCsrSdioResult(err); + } + + b1 = sdio_readb(func, address+1, &err); + if (err) { + _sdio_release_host(func); + return ConvertSdioToCsrSdioResult(err); + } + _sdio_release_host(func); + + *data = ((uint16_t)b1 << 8) | b0; + + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead16() */ + + +CsrResult +CsrSdioWrite16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + uint8_t b0, b1; + + _sdio_claim_host(func); + b1 = (data >> 8) & 0xFF; + sdio_writeb(func, b1, address+1, &err); + if (err) { + _sdio_release_host(func); + return ConvertSdioToCsrSdioResult(err); + } + + b0 = data & 0xFF; + sdio_writeb(func, b0, address, &err); + if (err) { + _sdio_release_host(func); + return ConvertSdioToCsrSdioResult(err); + } + + _sdio_release_host(func); + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite16() */ + + +CsrResult +CsrSdioF0Read8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + + _sdio_claim_host(func); +#ifdef MMC_QUIRK_LENIENT_FN0 + *data = sdio_f0_readb(func, address, &err); +#else + err = csr_io_rw_direct(func->card, 0, 0, address, 0, data); +#endif + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioF0Read8() */ + +CsrResult +CsrSdioF0Write8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + + _sdio_claim_host(func); +#ifdef MMC_QUIRK_LENIENT_FN0 + sdio_f0_writeb(func, data, address, &err); +#else + err = csr_io_rw_direct(func->card, 1, 0, address, data, NULL); +#endif + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioF0Write8() */ + + +CsrResult +CsrSdioRead(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + + _sdio_claim_host(func); + err = sdio_readsb(func, data, address, length); + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioRead() */ + +CsrResult +CsrSdioWrite(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + + _sdio_claim_host(func); + err = sdio_writesb(func, address, (void*)data, length); + _sdio_release_host(func); + + if (err) { + func_exit_r(err); + return ConvertSdioToCsrSdioResult(err); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioWrite() */ + + +static int +csr_sdio_enable_hs(struct mmc_card *card) +{ + int ret; + u8 speed; + + if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) + return 0; + + if (!card->cccr.high_speed) + return 0; + + ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); + if (ret) + return ret; + + speed |= SDIO_SPEED_EHS; + + ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); + if (ret) + return ret; + + mmc_card_set_highspeed(card); + card->host->ios.timing = MMC_TIMING_SD_HS; + card->host->ops->set_ios(card->host, &card->host->ios); + + return 0; +} + +static int +csr_sdio_disable_hs(struct mmc_card *card) +{ + int ret; + u8 speed; + + if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) + return 0; + + if (!card->cccr.high_speed) + return 0; + + ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); + if (ret) + return ret; + + speed &= ~SDIO_SPEED_EHS; + + ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); + if (ret) + return ret; + + card->state &= ~MMC_STATE_HIGHSPEED; + card->host->ios.timing = MMC_TIMING_LEGACY; + card->host->ops->set_ios(card->host, &card->host->ios); + + return 0; +} + + +/* + * --------------------------------------------------------------------------- + * CsrSdioMaxBusClockFrequencySet + * + * Set the maximum SDIO bus clock speed to use. + * + * Arguments: + * sdio SDIO context pointer + * maxFrequency maximum clock speed in Hz + * + * Returns: + * an error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, CsrUint32 maxFrequency) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + struct mmc_host *host = func->card->host; + struct mmc_ios *ios = &host->ios; + unsigned int max_hz; + int err; + CsrUint32 max_khz = maxFrequency/1000; + + if (!max_khz || max_khz > sdio_clock) { + max_khz = sdio_clock; + } + + _sdio_claim_host(func); + max_hz = 1000 * max_khz; + if (max_hz > host->f_max) { + max_hz = host->f_max; + } + + if (max_hz > 25000000) { + err = csr_sdio_enable_hs(func->card); + } else { + err = csr_sdio_disable_hs(func->card); + } + if (err) { + printk(KERN_ERR "SDIO warning: Failed to configure SDIO clock mode\n"); + _sdio_release_host(func); + return CSR_RESULT_SUCCESS; + } + + ios->clock = max_hz; + host->ops->set_ios(host, ios); + + _sdio_release_host(func); + + return CSR_RESULT_SUCCESS; +} /* CsrSdioMaxBusClockFrequencySet() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioInterruptEnable + * CsrSdioInterruptDisable + * + * Enable or disable the SDIO interrupt. + * The driver disables the SDIO interrupt until the i/o thread can + * process it. + * The SDIO interrupt can be disabled by modifying the SDIO_INT_ENABLE + * register in the Card Common Control Register block, but this requires + * two CMD52 operations. A better solution is to mask the interrupt at + * the host controller. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * Zero on success or a UniFi driver error code. + * + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioInterruptEnable(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + +#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD + sdio_unblock_card_irq(func); +#else + _sdio_claim_host(func); + /* Write the Int Enable in CCCR block */ +#ifdef MMC_QUIRK_LENIENT_FN0 + sdio_f0_writeb(func, 0x3, SDIO_CCCR_IENx, &err); +#else + err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x03, NULL); +#endif + _sdio_release_host(func); + + func_exit(); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } +#endif + return CSR_RESULT_SUCCESS; +} /* CsrSdioInterruptEnable() */ + +CsrResult +CsrSdioInterruptDisable(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err = 0; + +#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD + sdio_block_card_irq(func); +#else + _sdio_claim_host(func); + /* Write the Int Enable in CCCR block */ +#ifdef MMC_QUIRK_LENIENT_FN0 + sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &err); +#else + err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL); +#endif + _sdio_release_host(func); + + func_exit(); + if (err) { + return ConvertSdioToCsrSdioResult(err); + } +#endif + return CSR_RESULT_SUCCESS; +} /* CsrSdioInterruptDisable() */ + + +void CsrSdioInterruptAcknowledge(CsrSdioFunction *function) +{ +} + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionEnable + * + * Enable i/o on function 1. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionEnable(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + + func_enter(); + + /* Enable UniFi function 1 (the 802.11 part). */ + _sdio_claim_host(func); + err = sdio_enable_func(func); + _sdio_release_host(func); + if (err) { + unifi_error(NULL, "Failed to enable SDIO function %d\n", func->num); + } + + func_exit(); + return ConvertSdioToCsrSdioResult(err); +} /* CsrSdioFunctionEnable() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionDisable + * + * Enable i/o on function 1. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionDisable(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int err; + + func_enter(); + + /* Disable UniFi function 1 (the 802.11 part). */ + _sdio_claim_host(func); + err = sdio_disable_func(func); + _sdio_release_host(func); + if (err) { + unifi_error(NULL, "Failed to disable SDIO function %d\n", func->num); + } + + func_exit(); + return ConvertSdioToCsrSdioResult(err); +} /* CsrSdioFunctionDisable() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionActive + * + * No-op as the bus goes to an active state at the start of every + * command. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +void +CsrSdioFunctionActive(CsrSdioFunction *function) +{ +} /* CsrSdioFunctionActive() */ + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionIdle + * + * Set the function as idle. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +void +CsrSdioFunctionIdle(CsrSdioFunction *function) +{ +} /* CsrSdioFunctionIdle() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioPowerOn + * + * Power on UniFi. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioPowerOn(CsrSdioFunction *function) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + struct sdio_func *func = (struct sdio_func *)function->priv; + struct mmc_host *host = func->card->host; + + _sdio_claim_host(func); + if (!card_is_powered) { + mmc_power_restore_host(host); + card_is_powered = 1; + } else { + printk(KERN_INFO "SDIO: Skip power on; card is already powered.\n"); + } + _sdio_release_host(func); +#endif /* 2.6.32 */ + + return CSR_RESULT_SUCCESS; +} /* CsrSdioPowerOn() */ + +/* + * --------------------------------------------------------------------------- + * CsrSdioPowerOff + * + * Power off UniFi. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +void +CsrSdioPowerOff(CsrSdioFunction *function) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + struct sdio_func *func = (struct sdio_func *)function->priv; + struct mmc_host *host = func->card->host; + + _sdio_claim_host(func); + if (card_is_powered) { + mmc_power_save_host(host); + card_is_powered = 0; + } else { + printk(KERN_INFO "SDIO: Skip power off; card is already powered off.\n"); + } + _sdio_release_host(func); +#endif /* 2.6.32 */ +} /* CsrSdioPowerOff() */ + + +static int +sdio_set_block_size_ignore_first_error(struct sdio_func *func, unsigned blksz) +{ + int ret; + + if (blksz > func->card->host->max_blk_size) + return -EINVAL; + + if (blksz == 0) { + blksz = min(func->max_blksize, func->card->host->max_blk_size); + blksz = min(blksz, 512u); + } + + /* + * Ignore -ERANGE (OUT_OF_RANGE in R5) on the first byte as + * the block size may be invalid until both bytes are written. + */ + ret = csr_io_rw_direct(func->card, 1, 0, + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE, + blksz & 0xff, NULL); + if (ret && ret != -ERANGE) + return ret; + ret = csr_io_rw_direct(func->card, 1, 0, + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1, + (blksz >> 8) & 0xff, NULL); + if (ret) + return ret; + func->cur_blksize = blksz; + + return 0; +} + +CsrResult +CsrSdioBlockSizeSet(CsrSdioFunction *function, CsrUint16 blockSize) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int r = 0; + + /* Module parameter overrides */ + if (sdio_block_size > -1) { + blockSize = sdio_block_size; + } + + unifi_trace(NULL, UDBG1, "Set SDIO function block size to %d\n", + blockSize); + + _sdio_claim_host(func); + r = sdio_set_block_size(func, blockSize); + _sdio_release_host(func); + + /* + * The MMC driver for kernels prior to 2.6.32 may fail this request + * with -ERANGE. In this case use our workaround. + */ + if (r == -ERANGE) { + _sdio_claim_host(func); + r = sdio_set_block_size_ignore_first_error(func, blockSize); + _sdio_release_host(func); + } + if (r) { + unifi_error(NULL, "Error %d setting block size\n", r); + } + + /* Determine the achieved block size to pass to the core */ + function->blockSize = func->cur_blksize; + + return ConvertSdioToCsrSdioResult(r); +} /* CsrSdioBlockSizeSet() */ + + +/* + * --------------------------------------------------------------------------- + * CsrSdioHardReset + * + * Hard Resets UniFi is possible. + * + * Arguments: + * sdio SDIO context pointer + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioHardReset(CsrSdioFunction *function) +{ + return CSR_RESULT_FAILURE; +} /* CsrSdioHardReset() */ + + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_int_handler + * + * Interrupt callback function for SDIO interrupts. + * This is called in kernel context (i.e. not interrupt context). + * + * Arguments: + * func SDIO context pointer + * + * Returns: + * None. + * + * Note: Called with host already claimed. + * --------------------------------------------------------------------------- + */ +static void +uf_glue_sdio_int_handler(struct sdio_func *func) +{ + CsrSdioFunction *sdio_ctx; + CsrSdioInterruptDsrCallback func_dsr_callback; + int r; + + sdio_ctx = sdio_get_drvdata(func); + if (!sdio_ctx) { + return; + } +#ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD + /* + * Normally, we are not allowed to do any SDIO commands here. + * However, this is called in a thread context and with the SDIO lock + * so we disable the interrupts here instead of trying to do complicated + * things with the SDIO lock. + */ +#ifdef MMC_QUIRK_LENIENT_FN0 + sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &r); +#else + r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL); +#endif + if (r) { + printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts\n"); + } +#endif + + /* If the function driver has registered a handler, call it */ + if (sdio_func_drv && sdio_func_drv->intr) { + + func_dsr_callback = sdio_func_drv->intr(sdio_ctx); + + /* If interrupt handle returns a DSR handle, call it */ + if (func_dsr_callback) { + func_dsr_callback(sdio_ctx); + } + } + +} /* uf_glue_sdio_int_handler() */ + + + +/* + * --------------------------------------------------------------------------- + * csr_sdio_linux_remove_irq + * + * Unregister the interrupt handler. + * This means that the linux layer can not process interrupts any more. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * Status of the removal. + * --------------------------------------------------------------------------- + */ +int +csr_sdio_linux_remove_irq(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int r; + + sdio_claim_host(func); + r = sdio_release_irq(func); + sdio_release_host(func); + + return r; + +} /* csr_sdio_linux_remove_irq() */ + + +/* + * --------------------------------------------------------------------------- + * csr_sdio_linux_install_irq + * + * Register the interrupt handler. + * This means that the linux layer can process interrupts. + * + * Arguments: + * sdio SDIO context pointer + * + * Returns: + * Status of the removal. + * --------------------------------------------------------------------------- + */ +int +csr_sdio_linux_install_irq(CsrSdioFunction *function) +{ + struct sdio_func *func = (struct sdio_func *)function->priv; + int r; + + /* Register our interrupt handle */ + sdio_claim_host(func); + r = sdio_claim_irq(func, uf_glue_sdio_int_handler); + sdio_release_host(func); + + /* If the interrupt was installed earlier, is fine */ + if (r == -EBUSY) { + r = 0; + } + + return r; +} /* csr_sdio_linux_install_irq() */ + + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_probe + * + * Card insert callback. + * + * Arguments: + * func Our (glue layer) context pointer. + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +static int +uf_glue_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int instance; + CsrSdioFunction *sdio_ctx; + + func_enter(); + + /* First of all claim the SDIO driver */ + sdio_claim_host(func); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + /* Assume that the card is already powered */ + card_is_powered = 1; +#endif + + /* Assumes one card per host, which is true for SDIO */ + instance = func->card->host->index; + printk("sdio bus_id: %16s - UniFi card 0x%X inserted\n", + sdio_func_id(func), instance); + + /* Allocate context */ + sdio_ctx = (CsrSdioFunction *)kmalloc(sizeof(CsrSdioFunction), + GFP_KERNEL); + if (sdio_ctx == NULL) { + sdio_release_host(func); + return -ENOMEM; + } + + /* Initialise the context */ + sdio_ctx->sdioId.manfId = func->vendor; + sdio_ctx->sdioId.cardId = func->device; + sdio_ctx->sdioId.sdioFunction = func->num; + sdio_ctx->sdioId.sdioInterface = func->class; + sdio_ctx->blockSize = func->cur_blksize; + sdio_ctx->priv = (void *)func; + sdio_ctx->features = 0; + + /* Module parameter enables byte mode */ + if (sdio_byte_mode) { + sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE; + } + +#ifdef MMC_QUIRK_LENIENT_FN0 + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; +#endif + + /* Pass context to the SDIO driver */ + sdio_set_drvdata(func, sdio_ctx); + + /* Register this device with the SDIO function driver */ + /* Call the main UniFi driver inserted handler */ + if (sdio_func_drv && sdio_func_drv->inserted) { + uf_add_os_device(instance, &func->dev); + sdio_func_drv->inserted(sdio_ctx); + } + + /* We have finished, so release the SDIO driver */ + sdio_release_host(func); + + func_exit(); + return 0; +} /* uf_glue_sdio_probe() */ + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_remove + * + * Card removal callback. + * + * Arguments: + * func Our (glue layer) context pointer. + * + * Returns: + * UniFi driver error code. + * --------------------------------------------------------------------------- + */ +static void +uf_glue_sdio_remove(struct sdio_func *func) +{ + CsrSdioFunction *sdio_ctx; + + sdio_ctx = sdio_get_drvdata(func); + if (!sdio_ctx) { + return; + } + + func_enter(); + + unifi_info(NULL, "UniFi card removed\n"); + + /* Clean up the SDIO function driver */ + if (sdio_func_drv && sdio_func_drv->removed) { + uf_remove_os_device(func->card->host->index); + sdio_func_drv->removed(sdio_ctx); + } + + kfree(sdio_ctx); + + func_exit(); + +} /* uf_glue_sdio_remove */ + + +/* + * SDIO ids *must* be statically declared, so we can't take + * them from the list passed in csr_sdio_register_driver(). + */ +static const struct sdio_device_id unifi_ids[] = { + { SDIO_DEVICE(SDIO_MANF_ID_CSR,SDIO_CARD_ID_UNIFI_3) }, + { SDIO_DEVICE(SDIO_MANF_ID_CSR,SDIO_CARD_ID_UNIFI_4) }, + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(sdio, unifi_ids); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_suspend + * + * Card suspend callback. + * + * Arguments: + * dev The struct device owned by the MMC driver + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +static int +uf_glue_sdio_suspend(struct device *dev) +{ + struct sdio_func *func; + CsrSdioFunction *sdio_ctx; + + func_enter(); + + func = dev_to_sdio_func(dev); + WARN_ON(!func); + + sdio_ctx = sdio_get_drvdata(func); + WARN_ON(!sdio_ctx); + + unifi_trace(NULL, UDBG1, "System Suspend...\n"); + + /* Clean up the SDIO function driver */ + if (sdio_func_drv && sdio_func_drv->suspend) { + sdio_func_drv->suspend(sdio_ctx); + } + + func_exit(); + return 0; +} /* uf_glue_sdio_suspend */ + + +/* + * --------------------------------------------------------------------------- + * uf_glue_sdio_resume + * + * Card resume callback. + * + * Arguments: + * dev The struct device owned by the MMC driver + * + * Returns: + * None + * --------------------------------------------------------------------------- + */ +static int +uf_glue_sdio_resume(struct device *dev) +{ + struct sdio_func *func; + CsrSdioFunction *sdio_ctx; + + func_enter(); + + func = dev_to_sdio_func(dev); + WARN_ON(!func); + + sdio_ctx = sdio_get_drvdata(func); + WARN_ON(!sdio_ctx); + + unifi_trace(NULL, UDBG1, "System Resume...\n"); + + /* Clean up the SDIO function driver */ + if (sdio_func_drv && sdio_func_drv->resume) { + sdio_func_drv->resume(sdio_ctx); + } + + func_exit(); + return 0; + +} /* uf_glue_sdio_resume */ + +static struct dev_pm_ops unifi_pm_ops = { + .suspend = uf_glue_sdio_suspend, + .resume = uf_glue_sdio_resume, +}; + +#define UNIFI_PM_OPS (&unifi_pm_ops) + +#else + +#define UNIFI_PM_OPS NULL + +#endif /* CONFIG_PM */ +#endif /* 2.6.32 */ + +static struct sdio_driver unifi_driver = { + .probe = uf_glue_sdio_probe, + .remove = uf_glue_sdio_remove, + .name = "unifi", + .id_table = unifi_ids, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + .drv.pm = UNIFI_PM_OPS, +#endif /* 2.6.32 */ +}; + + +/* + * --------------------------------------------------------------------------- + * CsrSdioFunctionDriverRegister + * CsrSdioFunctionDriverUnregister + * + * These functions are called from the main module load and unload + * functions. They perform the appropriate operations for the + * linux MMC/SDIO driver. + * + * Arguments: + * sdio_drv Pointer to the function driver's SDIO structure. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +CsrResult +CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) +{ + int r; + + printk("UniFi: Using native Linux MMC driver for SDIO.\n"); + + if (sdio_func_drv) { + unifi_error(NULL, "sdio_mmc: UniFi driver already registered\n"); + return CSR_SDIO_RESULT_INVALID_VALUE; + } + + /* Save the registered driver description */ + /* + * FIXME: + * Need a table here to handle a call to register for just one function. + * mmc only allows us to register for the whole device + */ + sdio_func_drv = sdio_drv; + + /* Register ourself with mmc_core */ + r = sdio_register_driver(&unifi_driver); + if (r) { + printk(KERN_ERR "unifi_sdio: Failed to register UniFi SDIO driver: %d\n", r); + return ConvertSdioToCsrSdioResult(r); + } + + return CSR_RESULT_SUCCESS; +} /* CsrSdioFunctionDriverRegister() */ + + + +void +CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv) +{ + printk(KERN_INFO "UniFi: unregister from MMC sdio\n"); + sdio_unregister_driver(&unifi_driver); + + sdio_func_drv = NULL; + +} /* CsrSdioFunctionDriverUnregister() */ + diff --git a/drivers/staging/csr/sdio_stubs.c b/drivers/staging/csr/sdio_stubs.c new file mode 100644 index 000000000000..bc6a3697c000 --- /dev/null +++ b/drivers/staging/csr/sdio_stubs.c @@ -0,0 +1,82 @@ +/* + * Stubs for some of the bottom edge functions. + * + * These stubs are optional functions in the bottom edge (SDIO driver + * interface) API that not all platforms or SDIO drivers may support. + * + * They're declared as weak symbols so they can be overridden by + * simply providing a non-weak declaration. + * + * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + */ +#include "csr_wifi_hip_unifi.h" + +void __attribute__((weak)) CsrSdioFunctionIdle(CsrSdioFunction *function) +{ +} + +void __attribute__((weak)) CsrSdioFunctionActive(CsrSdioFunction *function) +{ +} + +CsrResult __attribute__((weak)) CsrSdioPowerOn(CsrSdioFunction *function) +{ + return CSR_RESULT_SUCCESS; +} + +void __attribute__((weak)) CsrSdioPowerOff(CsrSdioFunction *function) +{ +} + +CsrResult __attribute__((weak)) CsrSdioHardReset(CsrSdioFunction *function) +{ + return CSR_SDIO_RESULT_NOT_RESET; +} + +CsrResult __attribute__((weak)) CsrSdioBlockSizeSet(CsrSdioFunction *function, + CsrUint16 blockSize) +{ + return CSR_RESULT_SUCCESS; +} + +CsrResult __attribute__((weak)) CsrSdioSuspend(CsrSdioFunction *function) +{ + return CSR_RESULT_SUCCESS; +} + +CsrResult __attribute__((weak)) CsrSdioResume(CsrSdioFunction *function) +{ + return CSR_RESULT_SUCCESS; +} + +int __attribute__((weak)) csr_sdio_linux_install_irq(CsrSdioFunction *function) +{ + return 0; +} + +int __attribute__((weak)) csr_sdio_linux_remove_irq(CsrSdioFunction *function) +{ + return 0; +} + +void __attribute__((weak)) CsrSdioInsertedAcknowledge(CsrSdioFunction *function, CsrResult result) +{ +} + +void __attribute__((weak)) CsrSdioRemovedAcknowledge(CsrSdioFunction *function) +{ +} + +void __attribute__((weak)) CsrSdioSuspendAcknowledge(CsrSdioFunction *function, CsrResult result) +{ +} + +void __attribute__((weak)) CsrSdioResumeAcknowledge(CsrSdioFunction *function, CsrResult result) +{ +} + + diff --git a/drivers/staging/csr/sdioemb/cspi.h b/drivers/staging/csr/sdioemb/cspi.h new file mode 100644 index 000000000000..b0a2886970ab --- /dev/null +++ b/drivers/staging/csr/sdioemb/cspi.h @@ -0,0 +1,62 @@ +/* + * CSPI definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_CSPI_H +#define SDIOEMB_CSPI_H + +/** + * @addtogroup sdriver + *@{*/ + +#define CSPI_FUNC(f) (f) +#define CSPI_READ 0x10 +#define CSPI_WRITE 0x20 +#define CSPI_BURST 0x40 +#define CSPI_TYPE_MASK 0x70 + +/** + * CSPI_MODE function 0 register. + * + * Various CSPI mode settings. + * + * @see CSPI specification (CS-110124-SP) + */ +#define CSPI_MODE 0xf7 +# define CSPI_MODE_PADDED_WRITE_HDRS (1 << 7) +# define CSPI_MODE_PADDED_READ_HDRS (1 << 6) +/** + * BigEndianRegisters bit of \ref CSPI_MODE -- enable big-endian CSPI + * register reads and writes. + * + * @warning This bit should never be set as it's not possible to use + * this mode without knowledge of which registers are 8 bit and which + * are 16 bit. + */ +# define CSPI_MODE_BE_REG (1 << 5) +# define CSPI_MODE_BE_BURST (1 << 4) +# define CSPI_MODE_INT_ACTIVE_HIGH (1 << 3) +# define CSPI_MODE_INT_ON_ERR (1 << 2) +# define CSPI_MODE_LEN_FIELD_PRESENT (1 << 1) +# define CSPI_MODE_DRV_MISO_ON_RISING_CLK (1 << 0) + +#define CSPI_STATUS 0xf8 + +#define CSPI_PADDING 0xf9 +# define CSPI_PADDING_REG(p) ((p) << 0) +# define CSPI_PADDING_BURST(p) ((p) << 4) + +#define CSPI_PADDING_MAX 15 +#define CSPI_PADDING_REG_DFLT 0 +#define CSPI_PADDING_BURST_DFLT 2 + +/* cmd byte, 3 byte addr, padding, error byte, data word */ +#define CSPI_REG_TRANSFER_LEN (1 + 3 + CSPI_PADDING_MAX + 1 + 2) + +/*@}*/ + +#endif /* #ifndef SDIOEMB_CSPI_H */ diff --git a/drivers/staging/csr/sdioemb/csr_result.h b/drivers/staging/csr/sdioemb/csr_result.h new file mode 100644 index 000000000000..9813f3f86ee6 --- /dev/null +++ b/drivers/staging/csr/sdioemb/csr_result.h @@ -0,0 +1,16 @@ +/* + * Synergy compatible API -- common result codes. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef CSR_RESULT_H__ +#define CSR_RESULT_H__ + +typedef CsrUint16 CsrResult; +#define CSR_RESULT_SUCCESS ((CsrResult) 0x0000) +#define CSR_RESULT_FAILURE ((CsrResult) 0xffff) + +#endif diff --git a/drivers/staging/csr/sdioemb/csr_sdio.h b/drivers/staging/csr/sdioemb/csr_sdio.h new file mode 100644 index 000000000000..5d05d96d3958 --- /dev/null +++ b/drivers/staging/csr/sdioemb/csr_sdio.h @@ -0,0 +1,711 @@ +/* + * Synergy compatible API -- SDIO. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef CSR_SDIO_H__ +#define CSR_SDIO_H__ + +#include "csr_types.h" +#include "csr_result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Result Codes */ +#define CSR_SDIO_RESULT_INVALID_VALUE ((CsrResult) 1) /* Invalid argument value */ +#define CSR_SDIO_RESULT_NO_DEVICE ((CsrResult) 2) /* The specified device is no longer present */ +#define CSR_SDIO_RESULT_CRC_ERROR ((CsrResult) 3) /* The transmitted/received data or command response contained a CRC error */ +#define CSR_SDIO_RESULT_TIMEOUT ((CsrResult) 4) /* No command response or data received from device, or function enable/disable did not succeed within timeout period */ +#define CSR_SDIO_RESULT_NOT_RESET ((CsrResult) 5) /* The device was not reset */ + +/* Features (for use in features member of CsrSdioFunction) */ +#define CSR_SDIO_FEATURE_BYTE_MODE 0x00000001 /* Transfer sizes do not have to be a multiple of block size */ +#define CSR_SDIO_FEATURE_DMA_CAPABLE_MEM_REQUIRED 0x00000002 /* Bulk operations require DMA friendly memory */ + +/* CsrSdioFunctionId wildcards (for use in CsrSdioFunctionId members) */ +#define CSR_SDIO_ANY_MANF_ID 0xFFFF +#define CSR_SDIO_ANY_CARD_ID 0xFFFF +#define CSR_SDIO_ANY_SDIO_FUNCTION 0xFF +#define CSR_SDIO_ANY_SDIO_INTERFACE 0xFF + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionId + * + * DESCRIPTION + * This structure describes one or more functions of a device, based on + * four qualitative measures. The CsrSdioFunctionId wildcard defines can be + * used for making the CsrSdioFunctionId match more than one function. + * + * MEMBERS + * manfId - Vendor ID (or CSR_SDIO_ANY_MANF_ID). + * cardId - Device ID (or CSR_SDIO_ANY_CARD_ID). + * sdioFunction - SDIO Function number (or CSR_SDIO_ANY_SDIO_FUNCTION). + * sdioInterface - SDIO Standard Interface Code (or CSR_SDIO_ANY_SDIO_INTERFACE) + * + *----------------------------------------------------------------------------*/ +typedef struct +{ + CsrUint16 manfId; /* Vendor ID to match or CSR_SDIO_ANY_MANF_ID */ + CsrUint16 cardId; /* Device ID to match or CSR_SDIO_ANY_CARD_ID */ + CsrUint8 sdioFunction; /* SDIO Function number to match or CSR_SDIO_ANY_SDIO_FUNCTION */ + CsrUint8 sdioInterface; /* SDIO Standard Interface Code to match or CSR_SDIO_ANY_SDIO_INTERFACE */ +} CsrSdioFunctionId; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunction + * + * DESCRIPTION + * This structure represents a single function on a device. + * + * MEMBERS + * sdioId - A CsrSdioFunctionId describing this particular function. The + * subfield shall not contain any CsrSdioFunctionId wildcards. The + * subfields shall describe the specific single function + * represented by this structure. + * blockSize - Actual configured block size, or 0 if unconfigured. + * features - Bit mask with any of CSR_SDIO_FEATURE_* set. + * driverData - For use by the Function Driver. The SDIO Driver shall not + * attempt to dereference the pointer. + * priv - For use by the SDIO Driver. The Function Driver shall not attempt + * to dereference the pointer. + * + *----------------------------------------------------------------------------*/ +typedef struct +{ + CsrSdioFunctionId sdioId; + CsrUint16 blockSize; /* Actual configured block size, or 0 if unconfigured */ + CsrUint32 features; /* Bit mask with any of CSR_SDIO_FEATURE_* set */ + void *cardHandle; /* An opaque handle for this function's card. */ + void *osDevice; + void *driverData; /* For use by the Function Driver */ + void *priv; /* For use by the SDIO Driver */ +} CsrSdioFunction; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInsertedCallback, CsrSdioRemovedCallback + * + * DESCRIPTION + * CsrSdioInsertedCallback is called when a function becomes available to + * a registered Function Driver that supports the function. + * CsrSdioRemovedCallback is called when a function is no longer available + * to a Function Driver, either because the device has been removed, or the + * Function Driver has been unregistered. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioInsertedCallback)(CsrSdioFunction *function); +typedef void (*CsrSdioRemovedCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptDsrCallback, CsrSdioInterruptCallback + * + * DESCRIPTION + * CsrSdioInterruptCallback is called when an interrupt occurs on the + * the device associated with the specified function. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS (only CsrSdioInterruptCallback) + * A pointer to a CsrSdioInterruptDsrCallback function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioInterruptDsrCallback)(CsrSdioFunction *function); +typedef CsrSdioInterruptDsrCallback (*CsrSdioInterruptCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioSuspendCallback, CsrSdioResumeCallback + * + * DESCRIPTION + * CsrSdioSuspendCallback is called when the system is preparing to go + * into a suspended state. CsrSdioResumeCallback is called when the system + * has entered an active state again. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the CsrSdioFunctionDriver struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioSuspendCallback)(CsrSdioFunction *function); +typedef void (*CsrSdioResumeCallback)(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioAsyncCallback, CsrSdioAsyncDsrCallback + * + * DESCRIPTION + * CsrSdioAsyncCallback is called when an asynchronous operation completes. + * + * NOTE: These functions are implemented by the Function Driver, and are + * passed as function pointers in the function calls that initiate + * the operation. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * result - The result of the operation that completed. See the description + * of the initiating function for possible result values. + * + * RETURNS (only CsrSdioAsyncCallback) + * A pointer to a CsrSdioAsyncDsrCallback function. + * + *----------------------------------------------------------------------------*/ +typedef void (*CsrSdioAsyncDsrCallback)(CsrSdioFunction *function, CsrResult result); +typedef CsrSdioAsyncDsrCallback (*CsrSdioAsyncCallback)(CsrSdioFunction *function, CsrResult result); + +typedef struct +{ + CsrSdioInsertedCallback inserted; + CsrSdioRemovedCallback removed; + CsrSdioInterruptCallback intr; + CsrSdioSuspendCallback suspend; + CsrSdioResumeCallback resume; + CsrSdioFunctionId *ids; + CsrUint8 idsCount; + void *priv; +} CsrSdioFunctionDriver; + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionDriverRegister + * + * DESCRIPTION + * Register a Function Driver. + * + * PARAMETERS + * functionDriver - Pointer to struct describing the Function Driver. + * + * RETURNS + * CSR_RESULT_SUCCESS - The Function Driver was successfully + * registered. + * CSR_RESULT_FAILURE - Unable to register the function driver, + * because of an unspecified/unknown error. The + * Function Driver has not been registered. + * CSR_SDIO_RESULT_INVALID_VALUE - The specified Function Driver pointer + * does not point at a valid Function + * Driver structure, or some of the members + * contain invalid entries. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *functionDriver); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionDriverUnregister + * + * DESCRIPTION + * Unregister a previously registered Function Driver. + * + * PARAMETERS + * functionDriver - pointer to struct describing the Function Driver. + * + *----------------------------------------------------------------------------*/ +void CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *functionDriver); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionEnable, CsrSdioFunctionDisable + * + * DESCRIPTION + * Enable/disable the specified function by setting/clearing the + * corresponding bit in the I/O Enable register in function 0, and then + * periodically reading the related bit in the I/O Ready register until it + * is set/clear, limited by an implementation defined timeout. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS + * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The state of the + * related bit in the I/O Enable register is + * undefined. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device, or the related + * bit in the I/O ready register was not + * set/cleared within the timeout period. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioFunctionEnable(CsrSdioFunction *function); +CsrResult CsrSdioFunctionDisable(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptEnable, CsrSdioInterruptDisable + * + * DESCRIPTION + * Enable/disable the interrupt for the specified function by + * setting/clearing the corresponding bit in the INT Enable register in + * function 0. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + * RETURNS + * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The state of the + * related bit in the INT Enable register is + * unchanged. + * CSR_SDIO_RESULT_INVALID_VALUE - The specified function cannot be + * enabled/disabled, because it either + * does not exist or it is not possible to + * individually enable/disable functions. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioInterruptEnable(CsrSdioFunction *function); +CsrResult CsrSdioInterruptDisable(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInterruptAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled interrupt has been handled. Shall only + * be called once, and exactly once for each signalled interrupt to the + * corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * event was signalled. + * + *----------------------------------------------------------------------------*/ +void CsrSdioInterruptAcknowledge(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioInsertedAcknowledge, CsrSdioRemovedAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled inserted/removed event has been handled. + * Shall only be called once, and exactly once for each signalled event to + * the corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * inserted was signalled. + * result (CsrSdioInsertedAcknowledge only) + * CSR_RESULT_SUCCESS - The Function Driver has accepted the + * function, and the function is attached to + * the Function Driver until the + * CsrSdioRemovedCallback is called and + * acknowledged. + * CSR_RESULT_FAILURE - Unable to accept the function. The + * function is not attached to the Function + * Driver, and it may be passed to another + * Function Driver which supports the + * function. + * + *----------------------------------------------------------------------------*/ +void CsrSdioInsertedAcknowledge(CsrSdioFunction *function, CsrResult result); +void CsrSdioRemovedAcknowledge(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioSuspendAcknowledge, CsrSdioResumeAcknowledge + * + * DESCRIPTION + * Acknowledge that a signalled suspend event has been handled. Shall only + * be called once, and exactly once for each signalled event to the + * corresponding function. + * + * PARAMETERS + * function - Pointer to struct representing the function to which the + * event was signalled. + * result + * CSR_RESULT_SUCCESS - Successfully suspended/resumed. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * + *----------------------------------------------------------------------------*/ +void CsrSdioSuspendAcknowledge(CsrSdioFunction *function, CsrResult result); +void CsrSdioResumeAcknowledge(CsrSdioFunction *function, CsrResult result); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioBlockSizeSet + * + * DESCRIPTION + * Set the block size to use for the function. The actual configured block + * size shall be the minimum of: + * 1) Maximum block size supported by the function. + * 2) Maximum block size supported by the host controller. + * 3) The block size specified by the blockSize argument. + * + * When this function returns, the actual configured block size is + * available in the blockSize member of the function struct. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * blockSize - Block size to use for the function. Valid range is 1 to + * 2048. + * + * RETURNS + * CSR_RESULT_SUCCESS - The block size register on the chip + * was updated. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. The configured block + * size is undefined. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER + * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. + * If the ERROR bit is set (but not FUNCTION_NUMBER), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: Setting the block size requires two individual operations. The + * implementation shall ignore the OUT_OF_RANGE bit of the SDIO R5 + * response for the first operation, as the partially configured + * block size may be out of range, even if the final block size + * (after the second operation) is in the valid range. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioBlockSizeSet(CsrSdioFunction *function, CsrUint16 blockSize); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioMaxBusClockFrequencySet + * + * DESCRIPTION + * Set the maximum clock frequency to use for the device associated with + * the specified function. The actual configured clock frequency for the + * device shall be the minimum of: + * 1) Maximum clock frequency supported by the device. + * 2) Maximum clock frequency supported by the host controller. + * 3) Maximum clock frequency specified for any function on the same + * device. + * + * If the clock frequency exceeds 25MHz, it is the responsibility of the + * SDIO driver to enable high speed mode on the device, using the standard + * defined procedure, before increasing the frequency beyond the limit. + * + * Note that the clock frequency configured affects all functions on the + * same device. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * maxFrequency - The maximum clock frequency for the function in Hertz. + * + * RETURNS + * CSR_RESULT_SUCCESS - The maximum clock frequency was succesfully + * set for the function. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * + * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER + * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. + * If the ERROR bit is set (but not FUNCTION_NUMBER), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, CsrUint32 maxFrequency); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead8, CsrSdioWrite8, CsrSdioRead8Async, CsrSdioWrite8Async + * + * DESCRIPTION + * Read/write an 8bit value from/to the specified register address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. No data read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioRead8Async and CsrSdioWrite8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data); +CsrResult CsrSdioWrite8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data); +void CsrSdioRead8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data, CsrSdioAsyncCallback callback); +void CsrSdioWrite8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead16, CsrSdioWrite16, CsrSdioRead16Async, CsrSdioWrite16Async + * + * DESCRIPTION + * Read/write a 16bit value from/to the specified register address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. Data may have been + * partially read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioRead16Async and CsrSdioWrite16Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data); +CsrResult CsrSdioWrite16(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data); +void CsrSdioRead16Async(CsrSdioFunction *function, CsrUint32 address, CsrUint16 *data, CsrSdioAsyncCallback callback); +void CsrSdioWrite16Async(CsrSdioFunction *function, CsrUint32 address, CsrUint16 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioF0Read8, CsrSdioF0Write8, CsrSdioF0Read8Async, + * CsrSdioF0Write8Async + * + * DESCRIPTION + * Read/write an 8bit value from/to the specified register address in + * function 0. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. No data read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioF0Read8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data); +CsrResult CsrSdioF0Write8(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data); +void CsrSdioF0Read8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 *data, CsrSdioAsyncCallback callback); +void CsrSdioF0Write8Async(CsrSdioFunction *function, CsrUint32 address, CsrUint8 data, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioRead, CsrSdioWrite, CsrSdioReadAsync, CsrSdioWriteAsync + * + * DESCRIPTION + * Read/write a specified number of bytes from/to the specified register + * address. + * + * PARAMETERS + * function - Pointer to struct representing the function. + * address - Register address within the function. + * data - The data to read/write. + * length - Number of byte to read/write. + * callback - The function to call on operation completion. + * + * RETURNS + * CSR_RESULT_SUCCESS - The data was successfully read/written. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured. Data may have been + * partially read/written. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device. + * + * NOTE: If the SDIO R5 response is available, and either of the + * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit + * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), + * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and + * COM_CRC_ERROR bits shall be ignored. + * + * If the CSPI response is available, and any of the + * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, + * CSR_SDIO_RESULT_INVALID_VALUE will be returned. + * + * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return + * immediately, and the supplied callback function is called when the + * operation is complete. The result value is given as an argument to + * the callback function. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioRead(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length); +CsrResult CsrSdioWrite(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length); +void CsrSdioReadAsync(CsrSdioFunction *function, CsrUint32 address, void *data, CsrUint32 length, CsrSdioAsyncCallback callback); +void CsrSdioWriteAsync(CsrSdioFunction *function, CsrUint32 address, const void *data, CsrUint32 length, CsrSdioAsyncCallback callback); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioPowerOn, CsrSdioPowerOff + * + * DESCRIPTION + * Power on/off the device. + * + * PARAMETERS + * function - Pointer to struct representing the function that resides on + * the device to power on/off. + * + * RETURNS (only CsrSdioPowerOn) + * CSR_RESULT_SUCCESS - Power was succesfully reapplied and the device + * has been reinitialised. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured during reinitialisation. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device during + * reinitialisation. + * CSR_SDIO_RESULT_NOT_RESET - The power was not removed by the + * CsrSdioPowerOff call. The state of the + * device is unchanged. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioPowerOn(CsrSdioFunction *function); +void CsrSdioPowerOff(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioHardReset + * + * DESCRIPTION + * Perform a hardware reset of the device. + * + * PARAMETERS + * function - Pointer to struct representing the function that resides on + * the device to hard reset. + * + * RETURNS + * CSR_RESULT_SUCCESS - Reset was succesfully performed and the device + * has been reinitialised. + * CSR_RESULT_FAILURE - Unspecified/unknown error. + * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. + * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occured during reinitialisation. + * CSR_SDIO_RESULT_TIMEOUT - No response from the device during + * reinitialisation. + * CSR_SDIO_RESULT_NOT_RESET - The reset was not applied because it is not + * supported. The state of the device is + * unchanged. + * + *----------------------------------------------------------------------------*/ +CsrResult CsrSdioHardReset(CsrSdioFunction *function); + +/*----------------------------------------------------------------------------* + * NAME + * CsrSdioFunctionActive, CsrSdioFunctionIdle + * + * DESCRIPTION + * + * PARAMETERS + * function - Pointer to struct representing the function. + * + *----------------------------------------------------------------------------*/ +void CsrSdioFunctionActive(CsrSdioFunction *function); +void CsrSdioFunctionIdle(CsrSdioFunction *function); + +void CsrSdioCallbackInhibitEnter(CsrSdioFunction *function); +void CsrSdioCallbackInhibitLeave(CsrSdioFunction *function); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/csr/sdioemb/csr_sdio_lib.h b/drivers/staging/csr/sdioemb/csr_sdio_lib.h new file mode 100644 index 000000000000..15c70f6e716c --- /dev/null +++ b/drivers/staging/csr/sdioemb/csr_sdio_lib.h @@ -0,0 +1,30 @@ +/* + * Synergy compatible API -- SDIO utility library. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef CSR_SDIO_LIB_H__ +#define CSR_SDIO_LIB_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CsrResult CsrSdioFunctionReenable(CsrSdioFunction *function); + +typedef int CsrStatus; /* platform specific */ +#define CSR_STATUS_FAILURE(status) ((status) < 0) /* platform specific */ + +CsrResult CsrSdioStatusToResult(CsrStatus status); +CsrStatus CsrSdioResultToStatus(CsrResult result); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef CSR_SDIO_LIB_H__ */ diff --git a/drivers/staging/csr/sdioemb/csr_sdio_wdf.h b/drivers/staging/csr/sdioemb/csr_sdio_wdf.h new file mode 100644 index 000000000000..6f0d71c47336 --- /dev/null +++ b/drivers/staging/csr/sdioemb/csr_sdio_wdf.h @@ -0,0 +1,22 @@ +/* + * Synergy compatible API -- helpers for Windows Driver Framework drivers. + * + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef CSR_SDIO_WDF_H__ +#define CSR_SDIO_WDF_H__ + +#include + +NTSTATUS CsrSdioWdfDeviceInit(WDFDEVICE device); +void CsrSdioWdfDeviceCleanup(WDFDEVICE device); + +NTSTATUS CsrSdioWdfDeviceAdd(WDFDEVICE device); +void CsrSdioWdfDeviceDel(WDFDEVICE device); + +NTSTATUS CsrSdioWdfDeviceSuspend(WDFDEVICE device); +NTSTATUS CsrSdioWdfDeviceResume(WDFDEVICE device); + +#endif /* #ifndef CSR_SDIO_WDF_H__ */ diff --git a/drivers/staging/csr/sdioemb/csr_types.h b/drivers/staging/csr/sdioemb/csr_types.h new file mode 100644 index 000000000000..c0d95b33e758 --- /dev/null +++ b/drivers/staging/csr/sdioemb/csr_types.h @@ -0,0 +1,53 @@ +/* + * Synergy compatible API -- basic types. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef CSR_TYPES_H__ +#define CSR_TYPES_H__ + +#include + +#ifndef FALSE +#define FALSE false +#endif + +#ifndef TRUE +#define TRUE true +#endif + +/* Data types */ + +typedef size_t CsrSize; + +typedef uint8_t CsrUint8; +typedef uint16_t CsrUint16; +typedef uint32_t CsrUint32; + +typedef int8_t CsrInt8; +typedef int16_t CsrInt16; +typedef int32_t CsrInt32; + +typedef bool CsrBool; + +typedef char CsrCharString; +typedef unsigned char CsrUtf8String; +typedef CsrUint16 CsrUtf16String; /* 16-bit UTF16 strings */ +typedef CsrUint32 CsrUint24; + +/* + * 64-bit integers + * + * Note: If a given compiler does not support 64-bit types, it is + * OK to omit these definitions; 32-bit versions of the code using + * these types may be available. Consult the relevant documentation + * or the customer support group for information on this. + */ +#define CSR_HAVE_64_BIT_INTEGERS +typedef uint64_t CsrUint64; +typedef int64_t CsrInt64; + +#endif diff --git a/drivers/staging/csr/sdioemb/libsdio.h b/drivers/staging/csr/sdioemb/libsdio.h new file mode 100644 index 000000000000..29ac4115d60a --- /dev/null +++ b/drivers/staging/csr/sdioemb/libsdio.h @@ -0,0 +1,404 @@ +/* + * SDIO Userspace Interface library. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_LIBSDIO_H +#define SDIOEMB_LIBSDIO_H + +/** + * \defgroup libsdio Userspace SDIO library (libsdio) + * + * \brief \e libsdio is a Linux C library for accessing SDIO cards. + * + * Use of this library requires several \e sdioemb kernel modules to be + * loaded: + * - \c sdio. + * - \c An SDIO slot driver (e.g., \c slot_shc for a standard PCI + * SDIO Host Controller). + * - \c sdio_uif which provides the required character devices + * (/dev/sdio_uif0 for the card in SDIO slot 0 etc.). + */ +/*@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# define LIBSDIOAPI __stdcall +#else +# define LIBSDIOAPI +#endif + +struct sdio_uif; + +/** + * Handle to an opened SDIO Userspace Interface device. + */ +typedef struct sdio_uif *sdio_uif_t; + +enum sdio_status { + SDIO_SUCCESS = 0, + SDIO_EAGAIN = -1, + SDIO_EINVAL = -2, + SDIO_EIO = -3, + SDIO_ENODEV = -4, + SDIO_ENOMEM = -5, + SDIO_ENOTSUPP = -6, + SDIO_ENXIO = -7, + SDIO_ETIMEDOUT = -8, +}; + +/** + * Card interrupt handler function. + * + * @param uif handle to the interrupting device. + * @param arg data supplied by the caller of sdio_open(). + */ +typedef void (LIBSDIOAPI *sdio_int_handler_t)(sdio_uif_t uif, void *arg); + +/** + * Asynchronous IO completion callback function. + * + * @param uif handle to the device that completed the IO operation. + * @param arg data supplied by the caller of the asynchronous IO operation. + * @param status status of the IO operation. 0 is success; -EIO, + * -EINVAL, -ETIMEDOUT etc. on an error. + */ +typedef void (LIBSDIOAPI *sdio_io_callback_t)(sdio_uif_t uif, void *arg, int status); + +/** + * Open a SDIO Userspace Interface device and (optionally) register a + * card interrupt handler and enable card interrupts. + * + * Card interrupts are masked before calling int_handler and are + * unmasked when int_handler returns (unless sdio_interrupt_mask() is + * called). + * + * @param dev_filename filename of the device to open. + * @param int_handler card interrupt handler; or NULL if no + * interrupt handler is required. + * @param arg argument to be passed to the interrupt handler. + * + * @return handle to the opened device; or NULL on error with errno + * set. + */ +sdio_uif_t LIBSDIOAPI sdio_open(const char *dev_filename, + sdio_int_handler_t int_handler, void *arg); + +/** + * Mask the SDIO interrupt. + * + * Call this in an interrupt handler to allow the processing of + * interrupts to be deferred until after the interrupt handler has + * returned. + * + * @note \e Must only be called from within the interrupt handler + * registered with sdio_open(). + * + * @param uif device handle. + */ +void LIBSDIOAPI sdio_interrupt_mask(sdio_uif_t uif); + +/** + * Unmask the SDIO interrupt. + * + * Unmasks the SDIO interrupt if it had previously been masked with + * sdio_interrupt_mask(). + * + * @param uif device handle. + */ +void LIBSDIOAPI sdio_interrupt_unmask(sdio_uif_t uif); + +/** + * Close an opened SDIO Userspace Interface device, freeing all + * associated resources. + * + * @param uif handle to the device. + */ +void LIBSDIOAPI sdio_close(sdio_uif_t uif); + +/** + * Return the number of functions the card has. + * + * @param uif device handle. + * + * @return number of card functions. + */ +int LIBSDIOAPI sdio_num_functions(sdio_uif_t uif); + +/** + * Set an SDIO bus to 1 bit or 4 bit wide mode. + * + * The CCCR bus interface control register will be read and rewritten + * with the new bus width. + * + * @param uif device handle. + * @param bus_width bus width (1 or 4). + * + * @return 0 on success; -ve on error with errno set. + * + * @note The card capabilities are \e not checked. The user should + * ensure 4 bit mode is not enabled on a card that does not support + * it. + */ +int LIBSDIOAPI sdio_set_bus_width(sdio_uif_t uif, int bus_width); + +/** + * Limit the frequency of (or stop) the SD bus clock. + * + * The frequency cannot be set greater than that supported by the card + * or the controller. + * + * @note Stopping the bus clock while other device drivers are + * executing commands may result in those commands not completing + * until the bus clock is restarted. + * + * @param uif device handle. + * @param max_freq maximum frequency (Hz) or 0 to stop the bus clock + * until the start of the next command. + */ +void LIBSDIOAPI sdio_set_max_bus_freq(sdio_uif_t uif, int max_freq); + +/** + * Return the card's manufacturer (vendor) ID. + * + * @param uif device handle. + * + * @return manufacturer ID. + */ +uint16_t LIBSDIOAPI sdio_manf_id(sdio_uif_t uif); + +/** + * Return the card's card (device) ID. + * + * @param uif device handle. + * + * @return card ID. + */ +uint16_t LIBSDIOAPI sdio_card_id(sdio_uif_t uif); + +/** + * Return the standard interface code for a function. + * + * @param uif device handle. + * @param func card function to query. + * + * @return the standard interface. + */ +uint8_t LIBSDIOAPI sdio_std_if(sdio_uif_t uif, int func); + +/** + * Return a function's maximum supported block size. + * + * @param uif device handle. + * @param func card function to query. + * + * @return maximum block size. + */ +int LIBSDIOAPI sdio_max_block_size(sdio_uif_t uif, int func); + +/** + * Return a function's current block size. + * + * @note This returns the driver's view of the block size and not the + * value in the function's block size register. + * + * @param uif device handle. + * @param func card function to query. + * + * @return the current block size. + */ +int LIBSDIOAPI sdio_block_size(sdio_uif_t uif, int func); + +/** + * Set a function's block size. + * + * The function's block size registers will be written if necessary. + * + * @param uif device handle. + * @param func function to modify. + * @param blksz the new block size; or 0 for the default size. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_set_block_size(sdio_uif_t uif, int func, int blksz); + +/** + * Read an 8 bit register. + * + * @param uif device handle. + * @param func card function. + * @param addr register address. + * @param data the data read. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_read8(sdio_uif_t uif, int func, uint32_t addr, uint8_t *data); + +/** + * Write an 8 bit register. + * + * @param uif device handle. + * @param func card function. + * @param addr register address. + * @param data the data to write. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_write8(sdio_uif_t uif, int func, uint32_t addr, uint8_t data); + +/** + * Read a buffer from a 8 bit wide register/FIFO. + * + * The buffer read uses a fixed (not incrementing) address. + * + * \a block_size \e must be set to the value writted into \a func's + * I/O block size FBR register. + * + * If \a len % \a block_size == 0, a block mode transfer is used; a + * byte mode transfer is used if \a len < \a block_size. + * + * @param uif device handle. + * @param func card function. + * @param addr register/FIFO address. + * @param data buffer to store the data read. + * @param len length of data to read. + * @param block_size block size to use for this transfer. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_read(sdio_uif_t uif, int func, uint32_t addr, uint8_t *data, + size_t len, int block_size); + +/** + * Write a buffer to an 8 bit wide register/FIFO. + * + * The buffer write uses a fixed (not incrementing) address. + * + * \a block_size \e must be set to the value writted into \a func's + * I/O block size FBR register. + * + * If \a len % \a block_size == 0, a block mode transfer is used; a + * byte mode transfer is used if \a len < \a block_size. + * + * @param uif device handle. + * @param func card function. + * @param addr register/FIFO address. + * @param data buffer of data to write. + * @param len length of the data to write. + * @param block_size block size to use for this transfer. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_write(sdio_uif_t uif, int func, uint32_t addr, const uint8_t *data, + size_t len, int block_size); + +/** + * Read an 8 bit register, without waiting for completion. + * + * @param uif device handle. + * @param func card function. + * @param addr register address. + * @param data the data read. + * @param callback function to be called when the read completes. + * @param arg argument to be passed to callback. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_read8_async(sdio_uif_t uif, int func, uint32_t addr, uint8_t *data, + sdio_io_callback_t callback, void *arg); + +/** + * Write an 8 bit register, without waiting for completion. + * + * @param uif device handle. + * @param func card function. + * @param addr register address. + * @param data the data to write. + * @param callback function to be called when the write completes. + * @param arg argument to be passed to callback. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_write8_async(sdio_uif_t uif, int func, uint32_t addr, uint8_t data, + sdio_io_callback_t callback, void *arg); + +/** + * Read a buffer from a 8 bit wide register/FIFO, without waiting for + * completion. + * + * The buffer read uses a fixed (not incrementing) address. + * + * \a block_size \e must be set to the value writted into \a func's + * I/O block size FBR register. + * + * If \a len % \a block_size == 0, a block mode transfer is used; a + * byte mode transfer is used if \a len < \a block_size. + * + * @param uif device handle. + * @param func card function. + * @param addr register/FIFO address. + * @param data buffer to store the data read. + * @param len length of data to read. + * @param block_size block size to use for this transfer. + * @param callback function to be called when the read completes. + * @param arg argument to be passed to callback. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_read_async(sdio_uif_t uif, int func, uint32_t addr, uint8_t *data, + size_t len, int block_size, + sdio_io_callback_t callback, void *arg); + +/** + * Write a buffer to an 8 bit wide register/FIFO, without waiting for + * completion. + * + * The buffer write uses a fixed (not incrementing) address. + * + * \a block_size \e must be set to the value writted into \a func's + * I/O block size FBR register. + * + * If \a len % \a block_size == 0, a block mode transfer is used; a + * byte mode transfer is used if \a len < \a block_size. + * + * @param uif device handle. + * @param func card function. + * @param addr register/FIFO address. + * @param data buffer of data to write. + * @param len length of the data to write. + * @param block_size block size to use for this transfer. + * @param callback function to be called when the write completes. + * @param arg argument to be passed to callback. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_write_async(sdio_uif_t uif, int func, uint32_t addr, const uint8_t *data, + size_t len, int block_size, + sdio_io_callback_t callback, void *arg); +/** + * Force a card removal and reinsertion. + * + * This will power cycle the card if the slot hardware supports power + * control. + * + * @note The device handle will no longer be valid. + * + * @param uif device handle. + * + * @return 0 on success; or -ve on error with errno set. + */ +int LIBSDIOAPI sdio_reinsert_card(sdio_uif_t uif); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/*@}*/ + +#endif /* #ifndef SDIOEMB_LIBSDIO_H */ diff --git a/drivers/staging/csr/sdioemb/linux.h b/drivers/staging/csr/sdioemb/linux.h new file mode 100644 index 000000000000..f574f716d74c --- /dev/null +++ b/drivers/staging/csr/sdioemb/linux.h @@ -0,0 +1,16 @@ +/* + * Linux helpers for slot drivers. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_LINUX_H +#define SDIOEMB_LINUX_H + +#include + +int sdioemb_linux_slot_register(struct sdioemb_slot *slot); + +#endif /* #ifndef SDIOEMB_LINUX_H */ diff --git a/drivers/staging/csr/sdioemb/sdio.h b/drivers/staging/csr/sdioemb/sdio.h new file mode 100644 index 000000000000..50bb8fdd6b0f --- /dev/null +++ b/drivers/staging/csr/sdioemb/sdio.h @@ -0,0 +1,117 @@ +/* + * Standard SDIO definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_SDIO_H +#define SDIOEMB_SDIO_H + +/* Maximum time for VDD to rise to VDD min. */ +#define SDIO_POWER_UP_TIME_MS 250 + +/* Minimum SD bus clock a card must support (Hz). */ +#define SDIO_CLOCK_FREQ_MIN 400000 + +/* Maximum clock frequency for normal mode (Hz). + * + * Although high speed mode should be suitable for all speeds not all + * controller/card combinations are capable of meeting the higher + * tolerances for (e.g.) clock rise/fall times. Therefore, default + * mode is used where possible for improved compatibility. */ +#define SDIO_CLOCK_FREQ_NORMAL_SPD 25000000 + +/* Maximum clock frequency for high speed mode (Hz). */ +#define SDIO_CLOCK_FREQ_HIGH_SPD 50000000 + +#define SDIO_MAX_FUNCTIONS 8 /* incl. F0 */ + +/* Command argument format. */ + +#define SDIO_CMD52_ARG_WRITE 0x80000000 +#define SDIO_CMD52_ARG_FUNC(f) ((f) << 28) +#define SDIO_CMD52_ARG_ADDR(a) ((a) << 9) +#define SDIO_CMD52_ARG_DATA(d) ((d) << 0) + +#define SDIO_CMD53_ARG_WRITE 0x80000000 +#define SDIO_CMD53_ARG_FUNC(f) ((f) << 28) +#define SDIO_CMD53_ARG_BLK_MODE 0x08000000 +#define SDIO_CMD53_ARG_ADDR(a) ((a) << 9) +#define SDIO_CMD53_ARG_CNT(c) ((c) << 0) + +/* Response format. */ + +#define SDIO_R5_DATA(r) (((r) >> 0) & 0xff) +#define SDIO_R5_OUT_OF_RANGE (1 << 8) +#define SDIO_R5_FUNCTION_NUMBER (1 << 9) +#define SDIO_R5_ERROR (1 << 11) + +/* Register offsets and bits. */ + +#define SDIO_OCR_CARD_READY 0x80000000 +#define SDIO_OCR_NUM_FUNCS_MASK 0x70000000 +#define SDIO_OCR_NUM_FUNCS_OFFSET 28 +#define SDIO_OCR_VOLTAGE_3V3 0x00300000 /* 3.2-3.3V & 3.3-3.4V */ + +#define SDIO_CCCR_SDIO_REV 0x00 +#define SDIO_CCCR_SD_REV 0x01 +#define SDIO_CCCR_IO_EN 0x02 +#define SDIO_CCCR_IO_READY 0x03 +#define SDIO_CCCR_INT_EN 0x04 +# define SDIO_CCCR_INT_EN_MIE 0x01 +#define SDIO_CCCR_INT_PENDING 0x05 +#define SDIO_CCCR_IO_ABORT 0x06 +#define SDIO_CCCR_BUS_IFACE_CNTL 0x07 +# define SDIO_CCCR_BUS_IFACE_CNTL_CD_R_DISABLE 0x80 +# define SDIO_CCCR_BUS_IFACE_CNTL_ECSI 0x20 +# define SDIO_CCCR_BUS_IFACE_CNTL_4BIT_BUS 0x02 +#define SDIO_CCCR_CARD_CAPS 0x08 +# define SDIO_CCCR_CARD_CAPS_LSC 0x40 +# define SDIO_CCCR_CARD_CAPS_4BLS 0x80 +#define SDIO_CCCR_CIS_PTR 0x09 +#define SDIO_CCCR_BUS_SUSPEND 0x0c +#define SDIO_CCCR_FUNC_SEL 0x0d +#define SDIO_CCCR_EXEC_FLAGS 0x0e +#define SDIO_CCCR_READY_FLAGS 0x0f +#define SDIO_CCCR_F0_BLK_SIZE 0x10 +#define SDIO_CCCR_PWR_CNTL 0x12 +#define SDIO_CCCR_HIGH_SPEED 0x13 +# define SDIO_CCCR_HIGH_SPEED_SHS 0x01 +# define SDIO_CCCR_HIGH_SPEED_EHS 0x02 + +#define SDIO_FBR_REG(f, r) (0x100*(f) + (r)) + +#define SDIO_FBR_STD_IFACE(f) SDIO_FBR_REG(f, 0x00) +#define SDIO_FBR_STD_IFACE_EXT(f) SDIO_FBR_REG(f, 0x01) +#define SDIO_FBR_CIS_PTR(f) SDIO_FBR_REG(f, 0x09) +#define SDIO_FBR_CSA_PTR(f) SDIO_FBR_REG(f, 0x0c) +#define SDIO_FBR_CSA_DATA(f) SDIO_FBR_REG(f, 0x0f) +#define SDIO_FBR_BLK_SIZE(f) SDIO_FBR_REG(f, 0x10) + +#define SDIO_STD_IFACE_UART 0x01 +#define SDIO_STD_IFACE_BT_TYPE_A 0x02 +#define SDIO_STD_IFACE_BT_TYPE_B 0x03 +#define SDIO_STD_IFACE_GPS 0x04 +#define SDIO_STD_IFACE_CAMERA 0x05 +#define SDIO_STD_IFACE_PHS 0x06 +#define SDIO_STD_IFACE_WLAN 0x07 +#define SDIO_STD_IFACE_BT_TYPE_A_AMP 0x09 + +/* + * Manufacturer and card IDs. + */ +#define SDIO_MANF_ID_CSR 0x032a + +#define SDIO_CARD_ID_CSR_UNIFI_1 0x0001 +#define SDIO_CARD_ID_CSR_UNIFI_2 0x0002 +#define SDIO_CARD_ID_CSR_BC6 0x0004 +#define SDIO_CARD_ID_CSR_DASH_D00 0x0005 +#define SDIO_CARD_ID_CSR_BC7 0x0006 +#define SDIO_CARD_ID_CSR_CINDERELLA 0x0007 +#define SDIO_CARD_ID_CSR_UNIFI_3 0x0007 +#define SDIO_CARD_ID_CSR_UNIFI_4 0x0008 +#define SDIO_CARD_ID_CSR_DASH 0x0010 + +#endif /* #ifndef SDIOEMB_SDIO_H */ diff --git a/drivers/staging/csr/sdioemb/sdio_api.h b/drivers/staging/csr/sdioemb/sdio_api.h new file mode 100644 index 000000000000..cd8aded7229f --- /dev/null +++ b/drivers/staging/csr/sdioemb/sdio_api.h @@ -0,0 +1,408 @@ +/* + * SDIO device driver API. + * + * Copyright (C) 2007-2008 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SDIO_API_H +#define _SDIO_API_H + +/** + * @defgroup fdriver SDIO function driver API + * + * @brief The SDIO function driver API is used to implement drivers + * for SDIO card functions. + * + * Function drivers register with the SDIO driver core + * (sdio_register_driver()), listing which functions it supports and + * providing callback functions for card inserts, removes and + * interrupts. + * + * @par \anchor card_io_ops Card I/O operations: + * + * - \link sdioemb_read8(struct sdioemb_dev *, uint32_t, uint8_t *) sdioemb_read8()\endlink + * - \link sdioemb_read16(struct sdioemb_dev *, uint32_t, uint16_t *) sdioemb_read16()\endlink + * - \link sdioemb_write8(struct sdioemb_dev *, uint32_t, uint8_t) sdioemb_write8()\endlink + * - \link sdioemb_write16(struct sdioemb_dev *, uint32_t, uint16_t) sdioemb_write16()\endlink + * - \link sdioemb_f0_read8(struct sdioemb_dev *, uint32_t, uint8_t *) sdioemb_f0_read8()\endlink + * - \link sdioemb_f0_write8(struct sdioemb_dev *, uint32_t, uint8_t) sdioemb_f0_write8()\endlink + * - \link sdioemb_read(struct sdioemb_dev *, uint32_t, void *, size_t) sdioemb_read()\endlink + * - \link sdioemb_write(struct sdioemb_dev *, uint32_t, const void *, size_t) sdioemb_write()\endlink + */ + +struct sdioemb_func_driver; +struct sdioemb_dev; +struct sdioemb_dev_priv; + +/** + * An SDIO device. + * + * Each SDIO card will have an sdio_dev for each function. + * + * None of the fields (except for drv_data) should be written. + * + * @ingroup fdriver + */ +struct sdioemb_dev { + struct sdioemb_func_driver *driver; /**< Function driver for this device. */ + uint16_t vendor_id; /**< Vendor ID of the card. */ + uint16_t device_id; /**< Device ID of the card. */ + int function; /**< Function number of this device. */ + uint8_t interface; /**< SDIO standard interface number. */ + uint16_t max_blocksize; /**< Maximum block size supported. */ + uint16_t blocksize; /**< Blocksize in use. */ + int slot_id; /**< ID of the slot this card is inserted into. */ + void * os_device; /**< Pointer to an OS-specific device structure. */ + struct sdioemb_dev_priv *priv; /**< Data private to the SDIO core. */ + void * drv_data; /**< Data private to the function driver. */ +}; + +#define SDIOEMB_ANY_ID 0xffff +#define SDIOEMB_UIF_FUNC 0 +#define SDIOEMB_ANY_FUNC 0xff +#define SDIOEMB_ANY_IFACE 0xff + +/** + * An entry for an SDIO device ID table. + * + * Functions are matched to drivers using any combination of vendor + * ID, device ID, function number or standard interface. + * + * Matching on #function == SDIOEMB_UIF_FUNC is reserved for the SDIO + * Userspace Interface driver. Card management drivers can match on + * #function == 0, these will be probed before any function drivers. + * + * @ingroup fdriver + */ +struct sdioemb_id_table { + uint16_t vendor_id; /**< Vendor ID to match or SDIOEMB_ANY_ID */ + uint16_t device_id; /**< Device ID to match or SDIOEMB_ANY_ID */ + int function; /**< Function number to match or SDIOEMB_ANY_FUNC */ + uint8_t interface; /**< SDIO standard interface to match or SDIOEMB_ANY_IFACE */ +}; + +/** + * A driver for an SDIO function. + * + * @ingroup fdriver + */ +struct sdioemb_func_driver { + /** + * Driver name used in diagnostics. + */ + const char *name; + + /** + * 0 terminated array of functions supported by this device. + * + * The driver may (for example) match on a number of vendor + * ID/device ID/function number triplets or on an SDIO standard + * interface. + */ + struct sdioemb_id_table *id_table; + + /** + * Called by the core when an inserted card has functions which + * match those listed in id_table. + * + * The driver's implementation should (if required): + * + * - perform any additional probing + * - do function specific initialization + * - allocate and register any function/OS specific devices or interfaces. + * + * Called in: thread context. + * + * @param fdev the newly inserted device. + * + * @return 0 on success; -ve on error. + */ + int (*probe)(struct sdioemb_dev *fdev); + + /** + * Called by the core when a card is removed. This is only called + * if the probe() call succeeded. + * + * The driver's implementation should (if required); + * + * - do any function specific shutdown. + * - cleanup any data structures created/registers during probe(). + * + * Called in: thread context. + * + * @param fdev the device being removed. + */ + void (*remove)(struct sdioemb_dev *fdev); + + /** + * Called by the core to signal an SDIO interrupt for this card + * occurs, if interrupts have been enabled with + * sdioemb_interrupt_enable(). + * + * The driver's implementation should signal a thread (or similar) + * to actually handle the interrupt as no card I/O may be + * performed whilst in interrupt context. When the interrupt is + * handled, the driver should call sdioemb_interrupt_acknowledge() to + * enable further interrupts to be signalled. + * + * Called in: interrupt context. + * + * @param fdev the device which may have raised the interrupt. + */ + void (*card_int_handler)(struct sdioemb_dev *fdev); + + /** + * Called by the core to signal a suspend power management + * event occured. + * + * The driver's implementation should (if required) + * set the card to a low power mode and return as soon + * as possible. After this function returns, the + * driver should not start any SDIO commands. + * + * Called in: thread context. + * + * @param fdev the device handler. + */ + void (*suspend)(struct sdioemb_dev *fdev); + + /** + * Called by the core to signal a resume power management + * event occured. + * + * The driver's implementation should (if required) + * initialise the card to an operational mode and return + * as soon as possible. If the card has been powered off + * during suspend, the driver would have to initialise + * the card from scratch (f/w download, h/w initialisation, etc.). + * + * Called in: thread context. + * + * @param fdev the device handler. + */ + void (*resume)(struct sdioemb_dev *fdev); +}; + +int sdioemb_driver_register(struct sdioemb_func_driver *fdriver); +void sdioemb_driver_unregister(struct sdioemb_func_driver *fdriver); + +int sdioemb_driver_probe(struct sdioemb_func_driver *fdriver, struct sdioemb_dev *fdev); +void sdioemb_driver_remove(struct sdioemb_func_driver *fdriver, struct sdioemb_dev *fdev); + +/* For backward compatibility. */ +#define sdio_register_driver sdioemb_driver_register +#define sdio_unregister_driver sdioemb_driver_unregister + +int sdioemb_set_block_size(struct sdioemb_dev *fdev, uint16_t blksz); +void sdioemb_set_max_bus_freq(struct sdioemb_dev *fdev, int max_freq); +int sdioemb_set_bus_width(struct sdioemb_dev *fdev, int bus_width); + +int sdioemb_enable_function(struct sdioemb_dev *fdev); +int sdioemb_disable_function(struct sdioemb_dev *fdev); +int sdioemb_reenable_csr_function(struct sdioemb_dev *dev); +void sdioemb_idle_function(struct sdioemb_dev *fdev); + +int sdioemb_read8(struct sdioemb_dev *fdev, uint32_t addr, uint8_t *val); +int sdioemb_read16(struct sdioemb_dev *fdev, uint32_t addr, uint16_t *val); +int sdioemb_write8(struct sdioemb_dev *fdev, uint32_t addr, uint8_t val); +int sdioemb_write16(struct sdioemb_dev *fdev, uint32_t addr, uint16_t val); +int sdioemb_f0_read8(struct sdioemb_dev *fdev, uint32_t addr, uint8_t *val); +int sdioemb_f0_write8(struct sdioemb_dev *fdev, uint32_t addr, uint8_t val); +int sdioemb_read(struct sdioemb_dev *fdev, uint32_t addr, void *data, size_t len); +int sdioemb_write(struct sdioemb_dev *fdev, uint32_t addr, const void *data, size_t len); + +int sdioemb_hard_reset(struct sdioemb_dev *fdev); + +void sdioemb_power_on(struct sdioemb_dev *fdev); +void sdioemb_power_off(struct sdioemb_dev *fdev); + +int sdioemb_interrupt_enable(struct sdioemb_dev *fdev); +int sdioemb_interrupt_disable(struct sdioemb_dev *fdev); +void sdioemb_interrupt_acknowledge(struct sdioemb_dev *fdev); + +int sdioemb_cis_get_tuple(struct sdioemb_dev *fdev, uint8_t tuple, + void *buf, size_t len); + +void sdioemb_suspend_function(struct sdioemb_dev *fdev); +void sdioemb_resume_function(struct sdioemb_dev *fdev); + +/** + * SDIO command status. + * + * @ingroup fdriver + */ +enum sdioemb_cmd_status { + SDIOEMB_CMD_OK = 0x00, /**< Command successful. */ + + SDIOEMB_CMD_ERR_CMD = 0x01, + SDIOEMB_CMD_ERR_DAT = 0x02, + + SDIOEMB_CMD_ERR_CRC = 0x10, + SDIOEMB_CMD_ERR_TIMEOUT = 0x20, + SDIOEMB_CMD_ERR_OTHER = 0x40, + + SDIOEMB_CMD_ERR_CMD_CRC = SDIOEMB_CMD_ERR_CMD | SDIOEMB_CMD_ERR_CRC, /**< Response CRC error. */ + SDIOEMB_CMD_ERR_CMD_TIMEOUT = SDIOEMB_CMD_ERR_CMD | SDIOEMB_CMD_ERR_TIMEOUT, /**< Response time out. */ + SDIOEMB_CMD_ERR_CMD_OTHER = SDIOEMB_CMD_ERR_CMD | SDIOEMB_CMD_ERR_OTHER, /**< Other response error. */ + SDIOEMB_CMD_ERR_DAT_CRC = SDIOEMB_CMD_ERR_DAT | SDIOEMB_CMD_ERR_CRC, /**< Data CRC error. */ + SDIOEMB_CMD_ERR_DAT_TIMEOUT = SDIOEMB_CMD_ERR_DAT | SDIOEMB_CMD_ERR_TIMEOUT, /**< Data receive time out. */ + SDIOEMB_CMD_ERR_DAT_OTHER = SDIOEMB_CMD_ERR_DAT | SDIOEMB_CMD_ERR_OTHER, /**< Other data error. */ + + SDIOEMB_CMD_ERR_NO_CARD = 0x04, /**< No card present. */ + + SDIOEMB_CMD_IN_PROGRESS = 0xff, /**< Command still in progress. */ +}; + +/** + * A response to an SDIO command. + * + * For R1, R4, R5, and R6 responses only the middle 32 bits of the + * response are stored, the leading octet (start and direction bits + * and command index) and trailing octet (CRC and stop bit) are + * discarded. + * + * @bug R2 and R3 responses are not used by SDIO and are not + * supported. + * + * @ingroup fdriver + */ +union sdioemb_response { + uint32_t r1; + uint32_t r4; + uint32_t r5; + uint32_t r6; +}; + +/** + * SDIO command parameters and response. + */ +struct sdioemb_cmd_resp { + uint8_t cmd; /**< Command index (0 to 63). */ + uint32_t arg; /**< Command argument. */ + union sdioemb_response response; /**< Response to the command. Valid + iff the command has completed and + (sdio_cmd::status & SDIOEMB_CMD_ERR_CMD) == 0.*/ +}; + +/** + * CSPI command parameters and response. + */ +struct cspi_cmd_resp { + unsigned cmd : 8; /**< Command octet (type, and function). */ + unsigned addr: 24; /**< 24 bit address. */ + uint16_t val; /**< Word to write or read from the card (for non-burst commands). */ + uint8_t response; /**< Response octet. Valid iff the command has completed and + (sdio_cmd::status & SDIOEMB_CMD_ERR_CMD) == 0. */ +}; + + +/** + * An SDIO command, its status and response. + * + * sdio_cmd is used to submit SDIO commands to a device and return its + * status and any response or data. + * + * @ingroup fdriver + */ +struct sdioemb_cmd { + /** + * The SDIO device which submitted the command. Set by the + * core. + */ + struct sdioemb_dev *owner; + + /** + * Called by the core when the command has been completed. + * + * Called in: interrupt context. + * + * @param cmd the completed command. + */ + void (*callback)(struct sdioemb_cmd *cmd); + + /** + * Set of flags specifying the response type, data transfer + * direction and other parameters. + * + * For SDIO commands set at least one of the response types: + * - #SDIOEMB_CMD_FLAG_RESP_NONE + * - #SDIOEMB_CMD_FLAG_RESP_R1 + * - #SDIOEMB_CMD_FLAG_RESP_R1B + * - #SDIOEMB_CMD_FLAG_RESP_R2 + * - #SDIOEMB_CMD_FLAG_RESP_R3 + * - #SDIOEMB_CMD_FLAG_RESP_R4 + * - #SDIOEMB_CMD_FLAG_RESP_R5 + * - #SDIOEMB_CMD_FLAG_RESP_R5B + * - #SDIOEMB_CMD_FLAG_RESP_R6 + * + * and any of the additional flags: + * - #SDIOEMB_CMD_FLAG_READ + * + * For CSPI commands set: + * - #SDIOEMB_CMD_FLAG_CSPI + */ + unsigned flags; + + /** + * SDIO command parameters and response. + * + * Valid only if #SDIOEMB_CMD_FLAG_CSPI is \e not set in #flags. + */ + struct sdioemb_cmd_resp sdio; + + /** + * CSPI command parameters and response. + * + * Valid only if #SDIOEMB_CMD_FLAG_CSPI is set in #flags. + */ + struct cspi_cmd_resp cspi; + + /** + * Buffer of data to read or write. + * + * Must be set to NULL if the command is not a data transfer. + */ + uint8_t *data; + + /** + * Length of #data in octets. + * + * len must be either: less than the device's sdio_dev::blocksize; + * or a multiple of the device's sdio_dev::blocksize. + */ + size_t len; + + /** + * Status of the command after it has completed. + */ + enum sdioemb_cmd_status status; + + /** + * Data private to caller of sdioemb_start_cmd(). + */ + void *priv; +}; + +/** @addtogroup fdriver + *@{*/ +#define SDIOEMB_CMD_FLAG_RESP_NONE 0x00 /**< No response. */ +#define SDIOEMB_CMD_FLAG_RESP_R1 0x01 /**< R1 response. */ +#define SDIOEMB_CMD_FLAG_RESP_R1B 0x02 /**< R1b response. */ +#define SDIOEMB_CMD_FLAG_RESP_R2 0x03 /**< R2 response. */ +#define SDIOEMB_CMD_FLAG_RESP_R3 0x04 /**< R3 response. */ +#define SDIOEMB_CMD_FLAG_RESP_R4 0x05 /**< R4 response. */ +#define SDIOEMB_CMD_FLAG_RESP_R5 0x06 /**< R5 response. */ +#define SDIOEMB_CMD_FLAG_RESP_R5B 0x07 /**< R5b response. */ +#define SDIOEMB_CMD_FLAG_RESP_R6 0x08 /**< R6 response. */ +#define SDIOEMB_CMD_FLAG_RESP_MASK 0xff /**< Mask for response type. */ +#define SDIOEMB_CMD_FLAG_RAW 0x0100 /**< @internal Bypass the command queues. */ +#define SDIOEMB_CMD_FLAG_READ 0x0200 /**< Data transfer is a read, not a write. */ +#define SDIOEMB_CMD_FLAG_CSPI 0x0400 /**< CSPI transfer, not SDIO or SDIO-SPI. */ +#define SDIOEMB_CMD_FLAG_ABORT 0x0800 /**< Data transfer abort command. */ +/*@}*/ + +int sdioemb_start_cmd(struct sdioemb_dev *fdev, struct sdioemb_cmd *cmd); + +#endif /* #ifndef _SDIO_API_H */ diff --git a/drivers/staging/csr/sdioemb/sdio_bt_a.h b/drivers/staging/csr/sdioemb/sdio_bt_a.h new file mode 100644 index 000000000000..9efe4a390db5 --- /dev/null +++ b/drivers/staging/csr/sdioemb/sdio_bt_a.h @@ -0,0 +1,143 @@ +/* + * SDIO Bluetooth Type-A interface definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_SDIO_BT_A_H +#define SDIOEMB_SDIO_BT_A_H + +#include +#include + +/* + * Standard SDIO function registers for a Bluetooth Type-A interface. + */ +#define SDIO_BT_A_RD 0x00 +#define SDIO_BT_A_TD 0x00 + +#define SDIO_BT_A_RX_PKT_CTRL 0x10 +# define PC_RRT 0x01 + +#define SDIO_BT_A_TX_PKT_CTRL 0x11 +# define PC_WRT 0x01 + +#define SDIO_BT_A_RETRY_CTRL 0x12 +# define RTC_STAT 0x01 +# define RTC_SET 0x01 + +#define SDIO_BT_A_INTRD 0x13 +# define INTRD 0x01 +# define CL_INTRD 0x01 + +#define SDIO_BT_A_INT_EN 0x14 +# define EN_INTRD 0x01 + +#define SDIO_BT_A_BT_MODE 0x20 +# define MD_STAT 0x01 + +/* + * Length of the Type-A header. + * + * Packet length (3 octets) plus Service ID (1 octet). + */ +#define SDIO_BT_A_HEADER_LEN 4 + +/* + * Maximum length of a Type-A transport packet. + * + * Type-A header length and maximum length of a HCI packet (65535 + * octets). + */ +#define SDIO_BT_A_PACKET_LEN_MAX 65543 + +enum sdioemb_bt_a_service_id { + SDIO_BT_A_SID_CMD = 0x01, + SDIO_BT_A_SID_ACL = 0x02, + SDIO_BT_A_SID_SCO = 0x03, + SDIO_BT_A_SID_EVT = 0x04, + SDIO_BT_A_SID_VENDOR = 0xfe, +}; + +static __inline int sdioemb_bt_a_packet_len(const char *p) +{ + return (p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16); +} + +static __inline int sdioemb_bt_a_service_id(const char *p) +{ + return p[3]; +} + +/* + * Minimum amount to read (including the Type-A header). This allows + * short packets (e.g., flow control packets) to be read with a single + * command. + */ +#define SDIO_BT_A_MIN_READ 32 + +#define SDIO_BT_A_NAME_LEN 16 + +struct sdioemb_bt_a_dev { + CsrSdioFunction *func; + char name[SDIO_BT_A_NAME_LEN]; + void *drv_data; + + /** + * Get a buffer to receive a packet into. + * + * @param bt the BT device. + * @param header a buffer of length #SDIO_BT_A_MIN_READ containing + * (part of) the packet the buffer is for. It will contain + * the Type-A header and as much of the payload that will + * fit. + * @param buffer_min_len the minimum length of buffer required to + * receive the whole packet. This includes space for padding + * the read to a whole number of blocks (if more than 512 + * octets is still to be read). + * @param buffer returns the buffer. The packet (including the + * Type-A header will be placed at the beginning of this + * buffer. + * @param buffer_handle returns a buffer handle passed to the + * subsequent call of the receive() callback. + * + * @return 0 if a buffer was provided. + * @return -ENOMEM if no buffer could be provided. + */ + int (*get_rx_buffer)(struct sdioemb_bt_a_dev *bt, const uint8_t *header, + size_t buffer_min_len, uint8_t **buffer, void **buffer_handle); + void (*receive)(struct sdioemb_bt_a_dev *bt, void *buffer_handle, int status); + void (*sleep_state_changed)(struct sdioemb_bt_a_dev *bt); + + enum sdio_sleep_state sleep_state; + + uint8_t max_tx_retries; + uint8_t max_rx_retries; + unsigned needs_read_ack:1; + unsigned wait_for_firmware:1; + + unsigned rx_off:1; + + /** + * A buffer to read the packet header into before the real buffer + * is requested with the get_rx_buffer() callback. + * + * @internal + */ + uint8_t *header; +}; + +int sdioemb_bt_a_setup(struct sdioemb_bt_a_dev *bt, CsrSdioFunction *func); +void sdioemb_bt_a_cleanup(struct sdioemb_bt_a_dev *bt); +int sdioemb_bt_a_send(struct sdioemb_bt_a_dev *bt, const uint8_t *packet, size_t len); +void sdioemb_bt_a_handle_interrupt(struct sdioemb_bt_a_dev *bt); +void sdioemb_bt_a_set_sleep_state(struct sdioemb_bt_a_dev *bt, enum sdio_sleep_state state); +int sdioemb_bt_a_check_for_reset(struct sdioemb_bt_a_dev *bt); +void sdioemb_bt_a_start(struct sdioemb_bt_a_dev *bt); +void sdioemb_bt_a_stop(struct sdioemb_bt_a_dev *bt); +void sdioemb_bt_a_rx_on(struct sdioemb_bt_a_dev *bt); +void sdioemb_bt_a_rx_off(struct sdioemb_bt_a_dev *bt); + +#endif /* #ifndef SDIOEMB_SDIO_BT_A_H */ diff --git a/drivers/staging/csr/sdioemb/sdio_cis.h b/drivers/staging/csr/sdioemb/sdio_cis.h new file mode 100644 index 000000000000..ec5e8fc38006 --- /dev/null +++ b/drivers/staging/csr/sdioemb/sdio_cis.h @@ -0,0 +1,27 @@ +/* + * SDIO CIS definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SDIO_CIS_H +#define _SDIO_CIS_H + +#define CISTPL_NULL 0x00 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_MANFID 0x20 +# define CISTPL_MANFID_SIZE 0x04 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SDIO_STD 0x91 +#define CISTPL_SDIO_EXT 0x92 +#define CISTPL_END 0xff +#define CISTPL_FUNCE 0x22 +# define CISTPL_FUNCE_00_SIZE 0x04 +# define CISTPL_FUNCE_01_SIZE 0x2a + +#endif /* #ifndef _SDIO_CIS_H */ diff --git a/drivers/staging/csr/sdioemb/sdio_csr.h b/drivers/staging/csr/sdioemb/sdio_csr.h new file mode 100644 index 000000000000..3b00e4626cab --- /dev/null +++ b/drivers/staging/csr/sdioemb/sdio_csr.h @@ -0,0 +1,134 @@ +/* + * CSR specific SDIO registers. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef SDIOEMB_SDIO_CSR_H +#define SDIOEMB_SDIO_CSR_H + +/** + * @defgroup registers CSR specific SDIO registers + * + * Registers at 0xF0 - 0xFF in the CCCR are reserved for vendor + * specific registers. The registers documented here are specific to + * following CSR chips: + * + * - BlueCore (6 and later) + * - UltraCore + *@{ + */ + +/** + * Interrupt status/host wakeup register. + * + * This controls a function's deep sleep state. + * + * @see enum sdio_sleep_state + */ +#define SDIO_CSR_SLEEP_STATE 0xf0 +# define SDIO_CSR_SLEEP_STATE_FUNC(f) ((f) << 4) +# define SDIO_CSR_SLEEP_STATE_RDY_INT_EN 0x02 +# define SDIO_CSR_SLEEP_STATE_WAKE_REQ 0x01 + +/** + * Host interrupt clear register. + * + * Writing a 1 to bit 0 clears an SDIO interrupt raised by a generic + * function. + */ +#define SDIO_CSR_HOST_INT 0xf1 +# define SDIO_CSR_HOST_INT_CL 0x01 + +/** + * From host scratch register 0. + * + * A read/write register that can be used for signalling between the + * host and the chip. + * + * The usage of this register depends on the version of the chip or + * firmware. + */ +#define SDIO_CSR_FROM_HOST_SCRATCH0 0xf2 + +/** + * From host scratch register 1. + * + * @see SDIO_CSR_FROM_HOST_SCRATCH0 + */ +#define SDIO_CSR_FROM_HOST_SCRATCH1 0xf3 + +/** + * To host scratch register 0. + * + * A read only register that may be used for signalling between the + * chip and the host. + * + * The usage of this register depends on the version of the chip or + * firmware. + */ +#define SDIO_CSR_TO_HOST_SCRATCH0 0xf4 + +/** + * To host scratch register 1. + * + * @see SDIO_CSR_TO_HOST_SCRATCH0 + */ +#define SDIO_CSR_TO_HOST_SCRATCH1 0xf5 + +/** + * Extended I/O enable. + * + * Similar to the standard CCCR I/O Enable register, this is used to + * detect if an internal reset of a function has occured and + * (optionally) reenable it. + * + * An internal reset is detected by CCCR I/O Enable bit being set and + * the corresponding EXT_IO_EN bit being clear. + */ +#define SDIO_CSR_EXT_IO_EN 0xf6 + +/** + * Deep sleep states as set via the sleep state register. + * + * These states are used to control when the chip may go into a deep + * sleep (a low power mode). + * + * Since a chip in deep sleep may not respond to SDIO commands, the + * host should ensure that the chip is not in deep sleep before + * attempting SDIO commands to functions 1 to 7. + * + * The available states are: + * + * AWAKE - chip must not enter deep sleep and should exit deep sleep + * if it's currently sleeping. + * + * TORPID - chip may enter deep sleep. + * + * DROWSY - a transition state between TORPID and AWAKE. This is + * AWAKE plus the chip asserts an interrupt when the chip is awake. + * + * @see SDIO_CSR_SLEEP_STATE + */ +enum sdio_sleep_state { + SLEEP_STATE_AWAKE = SDIO_CSR_SLEEP_STATE_WAKE_REQ, + SLEEP_STATE_DROWSY = SDIO_CSR_SLEEP_STATE_WAKE_REQ | SDIO_CSR_SLEEP_STATE_RDY_INT_EN, + SLEEP_STATE_TORPID = 0x00, +}; + +/*@}*/ + +/* + * Generic function registers (with byte addresses). + */ + +/* + * SDIO_MODE is chip dependant, see the sdio_mode table in sdio_cspi.c + * to add support for new chips. + */ +#define SDIO_MODE /* chip dependant */ +# define SDIO_MODE_CSPI_EN 0x40 + +#endif /* SDIOEMB_SDIO_CSR_H */ diff --git a/drivers/staging/csr/sdioemb/slot_api.h b/drivers/staging/csr/sdioemb/slot_api.h new file mode 100644 index 000000000000..777bdd4a6df8 --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_api.h @@ -0,0 +1,313 @@ +/* + * Slot driver API. + * + * Copyright (C) 2007-2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_API_H +#define _SLOT_API_H + +#include + +struct sdioemb_slot; + +/** + * @defgroup sdriver SDIO slot driver API + * + * @brief The SDIO slot driver API provides an interface for the SDIO + * layer to driver an SDIO slot (socket). + * + * Slot drivers register with the SDIO layer (sdioemb_slot_register()), + * providing functions to starting commands, enabling/disable card + * interrupts, card detection and bus power control. + * + * Functions are provided to notify the SDIO layer when a command has + * completed (sdioemb_cmd_complete()) and when an SDIO card interrupt has + * occurred (sdioemb_interrupt()). + */ + +#define SDIOEMB_BUS_FREQ_OFF 0 +#define SDIOEMB_BUS_FREQ_DEFAULT -1 +#define SDIOEMB_BUS_FREQ_IDLE -2 + +/** + * Valid SDIO bus voltage levels. + * + * @ingroup sdriver + */ +enum sdioemb_power { + SDIOEMB_POWER_OFF = 0, /**< Power switched off. */ + SDIOEMB_POWER_3V3 = 33, /**< Voltage set to 3.3V. */ +}; + +/** + * SDIO slot capabilities. + * + * @ingroup sdriver + */ +struct slot_caps { + int max_bus_freq; /**< Maximum bus frequency (Hz). */ + int max_bus_width; /**< Maximum bus width supported (1 or 4 data lines). */ + uint8_t cspi_mode; /**< CSPI_MODE register value (for CSPI capable slots). */ +}; + +/** + * Controller hardware type. + * + * @ingroup sdriver + */ +enum slot_controller_type { + SDIOEMB_SLOT_TYPE_SD = 0, /**< SD/SDIO controller. */ + SDIOEMB_SLOT_TYPE_SPI, /**< SPI controller. */ + SDIOEMB_SLOT_TYPE_SPI_CSPI, /**< SPI controller capable of CSPI. */ +}; + +/** + * Return values from the add_function() notifier. + * + * @ingroup sdriver + */ +enum sdioemb_add_func_status { + /** + * The core will call sdioemb_add_function(). + */ + SDIOEMB_ADD_FUNC_NOW = 0, + /** + * The slot driver will call sdioemb_add_function() or the + * function driver will call sdioemb_driver_probe() directly. + */ + SDIOEMB_ADD_FUNC_DEFERRED = 1, +}; + +/** + * Slot/card event notifiers. + * + * A slot driver may be notified when certain slot or card events + * occur. + * + * @ingroup sdriver + */ +struct sdioemb_slot_notifiers { + /** + * This is called when a card function has been enumerated + * and initialized but before can be bound to a function driver. + * + * A slot driver may use this to create an OS-specific object for + * the function. The slot driver must either (a) return + * SDIOEMB_ADD_FUNC_NOW; (b) return SDIOEMB_ADD_FUNC_DEFERRED and + * call sdioemb_add_function() later on; (c) return + * SDIOEMB_ADD_FUNC_DEFERRED and pass the fdev to the function + * driver for it to call sdioemb_driver_probe() directly; or (d) + * return an error. + * + * The slot driver may need to get a reference to the fdev with + * sdioemb_get_function() if the lifetime of the OS-specific + * object extends beyond the subsequent return of the + * del_function() callback. + * + * If this is non-NULL the slot driver must also provide + * del_function(). + * + * @param slot the SDIO slot producing the notification. + * @param fdev the SDIO function being added. + * + * @return SDIOEMB_ADD_FUNC_NOW if the function is ready for use. + * @return SDIOEMB_ADD_FUNC_DEFERRED if sdioemb_add_function() or + * sdioemb_driver_probe() will be called later. + * @return -ve on a error. + */ + int (*add_function)(struct sdioemb_slot *slot, struct sdioemb_dev *fdev); + + /** + * This is called when a card function is being removed and after + * any function driver has been unbound. + * + * A slot driver may use this to delete any OS-specific object + * created by the add_function() notifier. + * + * @param slot the SDIO slot producing the notification. + * @param fdev the SDIO function being deleted. + */ + void (*del_function)(struct sdioemb_slot *slot, struct sdioemb_dev *fdev); +}; + +struct sdioemb_slot_priv; + +/** + * An SDIO slot driver. + * + * Allocate and free with sdioemb_slot_alloc() and sdioemb_slot_free(). + * + * @ingroup sdriver + */ +struct sdioemb_slot { + /** + * Name of the slot used in diagnostic messages. + * + * This would typically include the name of the SDIO controller + * and the slot number if the controller has multiple slots. + * + * This will be set by sdioemb_slot_register() if it is left as an + * empty string. + */ + char name[64]; + + /** + * Controller hardware type. + */ + enum slot_controller_type type; + + /** + * Set the SD bus clock frequency. + * + * The driver's implementation should set the SD bus clock to not + * more than \a clk Hz (unless \a clk is equal to + * #SDIOEMB_BUS_FREQ_OFF or #SDIOEMB_BUS_FREQ_IDLE). + * + * If \a clk == SDIOEMB_BUS_FREQ_OFF the clock should be stopped. + * + * \a clk == SDIOEMB_BUS_FREQ_IDLE indicates that the bus is idle + * (currently unused) and the host controller may slow (or stop) + * the SD bus clock to save power on the card. During this idle + * state the host controller must be capable of receiving SDIO + * interrupts (for certain host controllers this may require + * leaving the clock running). + * + * If \a clk is greater than #SDIO_CLOCK_FREQ_NORMAL_SPD (25 MHz) + * subsequent commands should be done with the controller in high + * speed mode. + * + * Called from: interrupt context. + * + * @param slot the slot to configure. + * @param clk new SD bus clock frequency in Hz, SDIOEMB_BUS_FREQ_OFF + * or SDIOEMB_BUS_FREQ_IDLE. + * + * @return The bus frequency actually configured in Hz. + */ + int (*set_bus_freq)(struct sdioemb_slot *slot, int clk); + + /** + * Set the SD bus width. + * + * The driver's implementation should set the width of the SD bus + * for all subsequent data transfers to the specified value. + * + * This may be NULL if the driver sets the bus width when starting + * a command, or the driver is for an SDIO-SPI or CSPI controller. + * + * Called from: thread context. + * + * @param slot the slot to configure. + * @param bus_width new SD bus width (either 1 or 4). + * + * @return 0 on success. + * @return -ve if a low-level error occured when setting the bus width. + */ + int (*set_bus_width)(struct sdioemb_slot *slot, int bus_width); + + /** + * Start an SDIO command. + * + * The driver's implementation should: + * + * - set the controller's bus width to #bus_width, + * - program the controller to start the command. + * + * Called from: interrupt context. + * + * @param slot slot to perform the command. + * @param cmd SDIO command to start. + */ + int (*start_cmd)(struct sdioemb_slot *slot, struct sdioemb_cmd *cmd); + + /** + * Detect if a card is inserted into the slot. + * + * Called from: thread context. + * + * @param slot slot to check. + * + * @return non-zero if a card is inserted; 0 otherwise. + */ + int (*card_present)(struct sdioemb_slot *slot); + + /** + * Switch on/off the SDIO bus power and set the SDIO bus voltage. + * + * Called from: thread context. + * + * @param slot the slot. + * @param power the requested voltage. + * + * @return 0 on success; -ve on error: -EINVAL - requested voltage + * is not supported. + */ + int (*card_power)(struct sdioemb_slot *slot, enum sdioemb_power power); + + /** + * Enable (unmask) the SDIO card interrupt on the controller. + * + * Called from: interrupt context. + * + * @param slot the slot to enable the interrupt on.. + */ + void (*enable_card_int)(struct sdioemb_slot *slot); + + /** + * Disable (mask) the SDIO card interrupt on the controller. + * + * Called from: thread context. + * + * @param slot the slot to disable the interrupt on. + */ + void (*disable_card_int)(struct sdioemb_slot *slot); + + /** + * Perform a hard reset of the card. + * + * Hard resets can be achieved in two ways: + * + * -# Power cycle (if the slot has power control). + * -# Platform-specific assertion of a card/chip reset line. + * + * If hard resets are not supported, either return 0 or set + * hard_reset to NULL. + * + * @param slot the slot for the card to reset. + * + * @return 0 if a hard reset was performed. + * @return 1 if hard resets are not supported. + */ + int (*hard_reset)(struct sdioemb_slot *slot); + + struct slot_caps caps; /**< Slot capabilities. */ + int clock_freq; /**< SD bus frequency requested by the SDIO layer. */ + int bus_width; /**< Bus width requested by the SDIO layer. */ + struct sdioemb_slot_notifiers notifs; /**< Slot event notifiers. */ + int cspi_reg_pad; /**< Padding for CSPI register reads. */ + int cspi_burst_pad; /**< Padding for CSPI burst reads. */ + struct sdioemb_slot_priv *priv; /**< Data private to the SDIO layer. */ + void * drv_data; /**< Data private to the slot driver. */ +}; + +struct sdioemb_slot *sdioemb_slot_alloc(size_t drv_data_size); +void sdioemb_slot_free(struct sdioemb_slot *slot); +int sdioemb_slot_register(struct sdioemb_slot *slot); +void sdioemb_slot_unregister(struct sdioemb_slot *slot); +int sdioemb_card_inserted(struct sdioemb_slot *slot); +void sdioemb_card_removed(struct sdioemb_slot *slot); +void sdioemb_interrupt(struct sdioemb_slot *slot); +void sdioemb_cmd_complete(struct sdioemb_slot *slot, struct sdioemb_cmd *cmd); + +void sdioemb_suspend(struct sdioemb_slot *slot); +void sdioemb_resume(struct sdioemb_slot *slot); + +void sdioemb_add_function(struct sdioemb_dev *fdev); +void sdioemb_del_function(struct sdioemb_dev *fdev); +void sdioemb_get_function(struct sdioemb_dev *fdev); +void sdioemb_put_function(struct sdioemb_dev *fdev); + +#endif /* #ifndef _SLOT_API_H */ diff --git a/drivers/staging/csr/sdioemb/slot_imx27.h b/drivers/staging/csr/sdioemb/slot_imx27.h new file mode 100644 index 000000000000..3aa2235d87c1 --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_imx27.h @@ -0,0 +1,86 @@ +/* + * i.MX27 SDHC definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_IMX27_H +#define _SLOT_IMX27_H + +/* + * i.MX27 SDHC registers. + */ + +#define SDHC_STR_STP_CLK 0x00 +# define STR_STP_CLK_MMCSD_RESET 0x0008 +# define STR_STP_CLK_START_CLK 0x0002 +# define STR_STP_CLK_STOP_CLK 0x0001 + +#define SDHC_STATUS 0x04 +# define STATUS_CARD_PRESENCE 0x8000 +# define STATUS_SDIO_INT_ACTIVE 0x4000 +# define STATUS_END_CMD_RESP 0x2000 +# define STATUS_WRITE_OP_DONE 0x1000 +# define STATUS_READ_OP_DONE 0x0800 +# define STATUS_CARD_BUS_CLK_RUN 0x0100 +# define STATUS_APPL_BUFF_FF 0x0080 +# define STATUS_APPL_BUFF_FE 0x0040 +# define STATUS_RESP_CRC_ERR 0x0020 +# define STATUS_CRC_READ_ERR 0x0008 +# define STATUS_CRC_WRITE_ERR 0x0004 +# define STATUS_TIME_OUT_RESP 0x0002 +# define STATUS_TIME_OUT_READ 0x0001 +# define STATUS_ERR_CMD_MASK (STATUS_RESP_CRC_ERR | STATUS_TIME_OUT_RESP) +# define STATUS_ERR_DATA_MASK (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR | STATUS_TIME_OUT_READ) +# define STATUS_ERR_MASK (STATUS_ERR_CMD_MASK | STATUS_ERR_DATA_MASK) + +#define SDHC_CLK_RATE 0x08 + +#define SDHC_CMD_DAT_CTRL 0x0c /* CMD_DAT_CONT */ +# define CMD_DAT_CTRL_CMD_RESUME 0x8000 +# define CMD_DAT_CTRL_CMD_RESP_LONG_OFF 0x1000 +# define CMD_DAT_CTRL_STOP_READ_WAIT 0x0800 +# define CMD_DAT_CTRL_START_READ_WAIT 0x0400 +# define CMD_DAT_CTRL_BUS_WIDTH_4 0x0200 +# define CMD_DAT_CTRL_INIT 0x0080 +# define CMD_DAT_CTRL_WRITE 0x0010 +# define CMD_DAT_CTRL_DATA_ENABLE 0x0008 +# define CMD_DAT_CTRL_RESP_NONE 0x0000 +# define CMD_DAT_CTRL_RESP_R1_R5_R6 0x0001 +# define CMD_DAT_CTRL_RESP_R2 0x0002 +# define CMD_DAT_CTRL_RESP_R3_R4 0x0003 + +#define SDHC_RES_TO 0x10 + +#define SDHC_READ_TO 0x14 +# define READ_TO_RECOMMENDED 0x2db4 + +#define SDHC_BLK_LEN 0x18 + +#define SDHC_NOB 0x1c + +#define SDHC_REV_NO 0x20 + +#define SDHC_INT_CTRL 0x24 /* INT_CNTR */ +# define INT_CTRL_CARD_INSERTION_EN 0x8000 +# define INT_CTRL_SDIO_REMOVAL_EN 0x4000 +# define INT_CTRL_SDIO_IRQ_EN 0x2000 +# define INT_CTRL_DAT0_EN 0x1000 +# define INT_CTRL_BUF_READ_EN 0x0010 +# define INT_CTRL_BUF_WRITE_EN 0x0008 +# define INT_CTRL_END_CMD_RES 0x0004 +# define INT_CTRL_WRITE_OP_DONE 0x0002 +# define INT_CTRL_READ_OP_DONE 0x0001 +# define INT_CTRL_INT_EN_MASK 0xe01f + +#define SDHC_CMD 0x28 + +#define SDHC_ARG 0x2c + +#define SDHC_RES_FIFO 0x34 + +#define SDHC_BUFFER_ACCESS 0x38 + +#endif /* #ifndef _SLOT_IMX27_H */ diff --git a/drivers/staging/csr/sdioemb/slot_imx31.h b/drivers/staging/csr/sdioemb/slot_imx31.h new file mode 100644 index 000000000000..b11894a4baec --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_imx31.h @@ -0,0 +1,86 @@ +/* + * i.MX31 SDHC definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_IMX31_H +#define _SLOT_IMX31_H + +/* + * i.MX31 SDHC registers. + */ + +#define SDHC_STR_STP_CLK 0x00 +# define STR_STP_CLK_MMCSD_RESET 0x0008 +# define STR_STP_CLK_START_CLK 0x0002 +# define STR_STP_CLK_STOP_CLK 0x0001 + +#define SDHC_STATUS 0x04 +# define STATUS_CARD_PRESENCE 0x8000 +# define STATUS_SDIO_INT_ACTIVE 0x4000 +# define STATUS_END_CMD_RESP 0x2000 +# define STATUS_WRITE_OP_DONE 0x1000 +# define STATUS_READ_OP_DONE 0x0800 +# define STATUS_CARD_BUS_CLK_RUN 0x0100 +# define STATUS_APPL_BUFF_FF 0x0080 +# define STATUS_APPL_BUFF_FE 0x0040 +# define STATUS_RESP_CRC_ERR 0x0020 +# define STATUS_CRC_READ_ERR 0x0008 +# define STATUS_CRC_WRITE_ERR 0x0004 +# define STATUS_TIME_OUT_RESP 0x0002 +# define STATUS_TIME_OUT_READ 0x0001 +# define STATUS_ERR_CMD_MASK (STATUS_RESP_CRC_ERR | STATUS_TIME_OUT_RESP) +# define STATUS_ERR_DATA_MASK (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR | STATUS_TIME_OUT_READ) +# define STATUS_ERR_MASK (STATUS_ERR_CMD_MASK | STATUS_ERR_DATA_MASK) + +#define SDHC_CLK_RATE 0x08 + +#define SDHC_CMD_DAT_CTRL 0x0c /* CMD_DAT_CONT */ +# define CMD_DAT_CTRL_CMD_RESUME 0x8000 +# define CMD_DAT_CTRL_CMD_RESP_LONG_OFF 0x1000 +# define CMD_DAT_CTRL_STOP_READ_WAIT 0x0800 +# define CMD_DAT_CTRL_START_READ_WAIT 0x0400 +# define CMD_DAT_CTRL_BUS_WIDTH_4 0x0200 +# define CMD_DAT_CTRL_INIT 0x0080 +# define CMD_DAT_CTRL_WRITE 0x0010 +# define CMD_DAT_CTRL_DATA_ENABLE 0x0008 +# define CMD_DAT_CTRL_RESP_NONE 0x0000 +# define CMD_DAT_CTRL_RESP_R1_R5_R6 0x0001 +# define CMD_DAT_CTRL_RESP_R2 0x0002 +# define CMD_DAT_CTRL_RESP_R3_R4 0x0003 + +#define SDHC_RES_TO 0x10 + +#define SDHC_READ_TO 0x14 +# define READ_TO_RECOMMENDED 0x2db4 + +#define SDHC_BLK_LEN 0x18 + +#define SDHC_NOB 0x1c + +#define SDHC_REV_NO 0x20 + +#define SDHC_INT_CTRL 0x24 /* INT_CNTR */ +# define INT_CTRL_CARD_INSERTION_EN 0x8000 +# define INT_CTRL_SDIO_REMOVAL_EN 0x4000 +# define INT_CTRL_SDIO_IRQ_EN 0x2000 +# define INT_CTRL_DAT0_EN 0x1000 +# define INT_CTRL_BUF_READ_EN 0x0010 +# define INT_CTRL_BUF_WRITE_EN 0x0008 +# define INT_CTRL_END_CMD_RES 0x0004 +# define INT_CTRL_WRITE_OP_DONE 0x0002 +# define INT_CTRL_READ_OP_DONE 0x0001 +# define INT_CTRL_INT_EN_MASK 0xe01f + +#define SDHC_CMD 0x28 + +#define SDHC_ARG 0x2c + +#define SDHC_RES_FIFO 0x34 + +#define SDHC_BUFFER_ACCESS 0x38 + +#endif /* #ifndef _SLOT_IMX31_H */ diff --git a/drivers/staging/csr/sdioemb/slot_pxa27x.h b/drivers/staging/csr/sdioemb/slot_pxa27x.h new file mode 100644 index 000000000000..cca853ad0e05 --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_pxa27x.h @@ -0,0 +1,70 @@ +/* + * PXA27x MMC/SD controller definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_PXA27X_H +#define _SLOT_PXA27X_H + +#define PXA27X_MMC_MMCLK_BASE_FREQ 19500000 +#define PXA27X_MMC_FIFO_SIZE 32 + +#define STOP_CLOCK (1 << 0) +#define START_CLOCK (2 << 0) + +#define STAT_END_CMD_RES (1 << 13) +#define STAT_PRG_DONE (1 << 12) +#define STAT_DATA_TRAN_DONE (1 << 11) +#define STAT_CLK_EN (1 << 8) +#define STAT_RECV_FIFO_FULL (1 << 7) +#define STAT_XMIT_FIFO_EMPTY (1 << 6) +#define STAT_RES_CRC_ERR (1 << 5) +#define STAT_SPI_READ_ERROR_TOKEN (1 << 4) +#define STAT_CRC_READ_ERROR (1 << 3) +#define STAT_CRC_WRITE_ERROR (1 << 2) +#define STAT_TIME_OUT_RESPONSE (1 << 1) +#define STAT_READ_TIME_OUT (1 << 0) + +#define SPI_CS_ADDRESS (1 << 3) +#define SPI_CS_EN (1 << 2) +#define CRC_ON (1 << 1) +#define SPI_EN (1 << 0) + +#define CMDAT_SDIO_INT_EN (1 << 11) +#define CMDAT_STOP_TRAN (1 << 10) +#define CMDAT_SD_4DAT (1 << 8) +#define CMDAT_DMAEN (1 << 7) +#define CMDAT_INIT (1 << 6) +#define CMDAT_BUSY (1 << 5) +#define CMDAT_STREAM (1 << 4) /* 1 = stream */ +#define CMDAT_WRITE (1 << 3) /* 1 = write */ +#define CMDAT_DATAEN (1 << 2) +#define CMDAT_RESP_NONE (0 << 0) +#define CMDAT_RESP_SHORT (1 << 0) +#define CMDAT_RESP_R2 (2 << 0) +#define CMDAT_RESP_R3 (3 << 0) + +#define RDTO_MAX 0xffff + +#define BUF_PART_FULL (1 << 0) + +#define SDIO_SUSPEND_ACK (1 << 12) +#define SDIO_INT (1 << 11) +#define RD_STALLED (1 << 10) +#define RES_ERR (1 << 9) +#define DAT_ERR (1 << 8) +#define TINT (1 << 7) +#define TXFIFO_WR_REQ (1 << 6) +#define RXFIFO_RD_REQ (1 << 5) +#define CLK_IS_OFF (1 << 4) +#define STOP_CMD (1 << 3) +#define END_CMD_RES (1 << 2) +#define PRG_DONE (1 << 1) +#define DATA_TRAN_DONE (1 << 0) + +#define MMC_I_MASK_ALL 0x00001fff + +#endif /* #ifndef _SLOT_PXA27X_H */ diff --git a/drivers/staging/csr/sdioemb/slot_shc.h b/drivers/staging/csr/sdioemb/slot_shc.h new file mode 100644 index 000000000000..0eb5e535a5a2 --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_shc.h @@ -0,0 +1,223 @@ +/* + * Standard Host Controller definitions. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_SHC_H +#define _SLOT_SHC_H + +#include + +/* SHC registers */ +#define SHC_SYSTEM_ADDRESS 0x00 + +#define SHC_BLOCK_SIZE 0x04 +# define SHC_BLOCK_SIZE_DMA_BOUNDARY_4K (0x0 << 12) +# define SHC_BLOCK_SIZE_DMA_BOUNDARY_512K (0x7 << 12) + +#define SHC_BLOCK_COUNT 0x06 +#define SHC_ARG 0x08 + +#define SHC_TRANSFER_MODE 0x0c +# define SHC_TRANSFER_MODE_DMA_EN 0x0001 +# define SHC_TRANSFER_MODE_BLK_CNT_EN 0x0002 +# define SHC_TRANSFER_MODE_AUTO_CMD12_EN 0x0004 +# define SHC_TRANSFER_MODE_DATA_READ 0x0010 +# define SHC_TRANSFER_MODE_MULTI_BLK 0x0020 + +#define SHC_CMD 0x0e +# define SHC_CMD_RESP_NONE 0x0000 +# define SHC_CMD_RESP_136 0x0001 +# define SHC_CMD_RESP_48 0x0002 +# define SHC_CMD_RESP_48B 0x0003 +# define SHC_CMD_RESP_CRC_CHK 0x0008 +# define SHC_CMD_RESP_IDX_CHK 0x0010 +# define SHC_CMD_DATA_PRESENT 0x0020 +# define SHC_CMD_TYPE_ABORT (0x3 << 6) +# define SHC_CMD_IDX(c) ((c) << 8) + +#define SHC_RESPONSE_0_31 0x10 + +#define SHC_BUFFER_DATA_PORT 0x20 + +#define SHC_PRESENT_STATE 0x24 +# define SHC_PRESENT_STATE_CMD_INHIBIT 0x00000001 +# define SHC_PRESENT_STATE_DAT_INHIBIT 0x00000002 +# define SHC_PRESENT_STATE_CARD_PRESENT 0x00010000 + +#define SHC_HOST_CTRL 0x28 +# define SHC_HOST_CTRL_LED_ON 0x01 +# define SHC_HOST_CTRL_4BIT 0x02 +# define SHC_HOST_CTRL_HIGH_SPD_EN 0x04 + + +#define SHC_PWR_CTRL 0x29 +# define SHC_PWR_CTRL_3V3 0x0e +# define SHC_PWR_CTRL_ON 0x01 + +#define SHC_BLOCK_GAP_CTRL 0x2a +#define SHC_WAKEUP_CTRL 0x2b + +#define SHC_CLOCK_CTRL 0x2c +# define SHC_CLOCK_CTRL_INT_CLK_EN 0x01 +# define SHC_CLOCK_CTRL_INT_CLK_STABLE 0x02 +# define SHC_CLOCK_CTRL_SD_CLK_EN 0x04 +# define SHC_CLOCK_CTRL_DIV(d) (((d) >> 1) << 8) /* divisor must be power of 2 */ + +#define SHC_TIMEOUT_CTRL 0x2e +# define SHC_TIMEOUT_CTRL_MAX 0x0e + +#define SHC_SOFTWARE_RST 0x2f +# define SHC_SOFTWARE_RST_ALL 0x01 +# define SHC_SOFTWARE_RST_CMD 0x02 +# define SHC_SOFTWARE_RST_DAT 0x04 + +#define SHC_INT_STATUS 0x30 +#define SHC_INT_STATUS_EN 0x34 +#define SHC_INT_SIGNAL_EN 0x38 +# define SHC_INT_CMD_COMPLETE 0x00000001 +# define SHC_INT_TRANSFER_COMPLETE 0x00000002 +# define SHC_INT_BLOCK_GAP 0x00000004 +# define SHC_INT_DMA 0x00000008 +# define SHC_INT_WR_BUF_RDY 0x00000010 +# define SHC_INT_RD_BUF_RDY 0x00000020 +# define SHC_INT_CARD_INSERTED 0x00000040 +# define SHC_INT_CARD_REMOVED 0x00000080 +# define SHC_INT_CARD_INT 0x00000100 +# define SHC_INT_ERR_ANY 0x00008000 +# define SHC_INT_ERR_CMD_TIMEOUT 0x00010000 +# define SHC_INT_ERR_CMD_CRC 0x00020000 +# define SHC_INT_ERR_CMD_ENDBIT 0x00040000 +# define SHC_INT_ERR_CMD_INDEX 0x00080000 +# define SHC_INT_ERR_CMD_ALL 0x000f0000 +# define SHC_INT_ERR_DAT_TIMEOUT 0x00100000 +# define SHC_INT_ERR_DAT_CRC 0x00200000 +# define SHC_INT_ERR_DAT_ENDBIT 0x00400000 +# define SHC_INT_ERR_DAT_ALL 0x00700000 +# define SHC_INT_ERR_CURRENT_LIMIT 0x00800000 +# define SHC_INT_ERR_AUTO_CMD12 0x01000000 +# define SHC_INT_ERR_ALL 0x01ff0000 +# define SHC_INT_ALL 0x01ff81ff + +#define SHC_AUTO_CMD12_STATUS 0x3c + +#define SHC_CAPS 0x40 +# define SHC_CAPS_TO_BASE_CLK_FREQ(c) (((c) & 0x00003f00) >> 8) +# define SHC_CAPS_PWR_3V3 (1 << 24) + +#define SHC_MAX_CURRENT_CAPS 0x4c + +/* PCI configuration registers. */ +#define PCI_SHC_SLOT_INFO 0x40 + +/* Maximum time to wait for a software reset. */ +#define SHC_RESET_TIMEOUT_MS 100 /* ms */ + +/* Maximum time to wait for internal clock to stabilize */ +#define SHC_INT_CLK_STABLE_TIMEOUT_MS 100 + +/* + * No supported voltages in the capabilities register. + * + * Workaround: Assume 3.3V is supported. + */ +#define SLOT_SHC_QUIRK_NO_VOLTAGE_CAPS (1 << 0) + +/* + * Commands with an R5B (busy) response do not complete. + * + * Workaround: Use R5 instead. This will only work if the busy signal + * is cleared sufficiently quickly before the next command is started. + */ +#define SLOT_SHC_QUIRK_R5B_BROKEN (1 << 1) + +/* + * High speed mode doesn't work. + * + * Workaround: limit maximum bus frequency to 25 MHz. + */ +#define SLOT_SHC_QUIRK_HIGH_SPD_BROKEN (1 << 2) + +/* + * Data timeout (TIMEOUT_CTRL) uses SDCLK and not TMCLK. + * + * Workaround: set TIMEOUT_CTRL using SDCLK. + */ +#define SLOT_SHC_QUIRK_DATA_TIMEOUT_USES_SDCLK (1 << 3) + +/* + * Controller can only start DMA on dword (32 bit) aligned addresses. + * + * Workaround: PIO is used on data transfers with a non-dword aligned + * address. + */ +#define SHC_QUIRK_DMA_NEEDS_DWORD_ALIGNED_ADDR (1 << 4) + +/* + * Controller is unreliable following multiple transfers + * + * Workaround: The controller is reset following every command, not just + * erroneous ones + */ +#define SHC_QUIRK_RESET_EVERY_CMD_COMPLETE (1 << 5) + +/* + * JMicron JMB381 to JMB385 controllers require some non-standard PCI + * config space writes. + */ +#define SHC_QUIRK_JMICRON_JMB38X (1 << 6) + +/* + * Controller can only do DMA if the length is a whole number of + * dwords. + * + * Controller with this quirk probably also need + * SHC_QUIRK_DMA_NEEDS_DWORD_ALIGNED_ADDR. + * + * Workaround: PIO is used on data transfers that don't end on an + * aligned address. + */ +#define SHC_QUIRK_DMA_NEEDS_DWORD_ALIGNED_LEN (1 << 7) + +struct sdioemb_shc { + struct sdioemb_slot *slot; + void (*enable_int)(struct sdioemb_slot *slot, uint32_t ints); + void (*disable_int)(struct sdioemb_slot *slot, uint32_t ints); + void (*cmd_complete)(struct sdioemb_slot *slot, struct sdioemb_cmd *cmd); + uint32_t quirks; + os_io_mem_t addr; + + os_spinlock_t lock; + os_timer_t lockup_timer; + uint32_t base_clk; + struct sdioemb_cmd *current_cmd; + uint8_t *data; + size_t remaining; + size_t block_size; +}; + +void sdioemb_shc_init(struct sdioemb_shc *shc); +void sdioemb_shc_clean_up(struct sdioemb_shc *shc); + +int sdioemb_shc_start(struct sdioemb_shc *shc); +void sdioemb_shc_stop(struct sdioemb_shc *shc); + +bool sdioemb_shc_isr(struct sdioemb_shc *shc, uint32_t *int_stat); +void sdioemb_shc_dsr(struct sdioemb_shc *shc, uint32_t int_stat); + +int sdioemb_shc_set_bus_freq(struct sdioemb_shc *shc, int clk); +int sdioemb_shc_set_bus_width(struct sdioemb_shc *shc, int bus_width); +int sdioemb_shc_start_cmd(struct sdioemb_shc *shc, struct sdioemb_cmd *cmd, + bool use_dma, uint64_t dma_addr); +int sdioemb_shc_card_present(struct sdioemb_shc *shc); +int sdioemb_shc_card_power(struct sdioemb_shc *shc, enum sdioemb_power power); +void sdioemb_shc_enable_card_int(struct sdioemb_shc *shc); +void sdioemb_shc_disable_card_int(struct sdioemb_shc *shc); +int sdioemb_shc_hard_reset(struct sdioemb_shc *shc); + +void sdioemb_shc_show_quirks(struct sdioemb_shc *shc); + +#endif /* #ifndef _SLOT_SHC_H */ diff --git a/drivers/staging/csr/sdioemb/slot_ushc.h b/drivers/staging/csr/sdioemb/slot_ushc.h new file mode 100644 index 000000000000..efe3310ee37c --- /dev/null +++ b/drivers/staging/csr/sdioemb/slot_ushc.h @@ -0,0 +1,133 @@ +/* + * USB Standard Host Controller definitions. + * + * Copyright (C) 2010 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef _SLOT_USHC_H +#define _SLOT_USHC_H + +#include + +enum ushc_request +{ + USHC_GET_CAPS = 0x00, + USHC_HOST_CTRL = 0x01, + USHC_PWR_CTRL = 0x02, + USHC_CLK_FREQ = 0x03, + USHC_EXEC_CMD = 0x04, + USHC_READ_RESP = 0x05, + USHC_RESET = 0x06 +}; + +enum ushc_request_recipient +{ + USHC_RECIPIENT_DEVICE = 0x00, + USHC_RECIPIENT_INTERFACE = 0x01, + USHC_RECIPIENT_ENDPOINT = 0x02, + USHC_RECIPIENT_OTHER = 0x03 +}; + +enum ushc_request_direction +{ + USHC_HOST_TO_DEVICE = 0x00, + USHC_DEVICE_TO_HOST = 0x01 +}; + +struct sdioemb_ushc +{ + struct sdioemb_slot *slot; + + void (*enable_int)(struct sdioemb_slot *slot, uint32_t ints); + void (*disable_int)(struct sdioemb_slot *slot, uint32_t ints); + void (*cmd_complete)(struct sdioemb_slot *slot, struct sdioemb_cmd *cmd); + int (*set_host_ctrl)(struct sdioemb_slot *slot, uint16_t controler_state); + int (*submit_vendor_request)(struct sdioemb_slot *slot, + enum ushc_request request, + enum ushc_request_direction direction, + enum ushc_request_recipient recipient, + uint16_t value, + uint16_t index, + void* io_buffer, + uint32_t io_buffer_length); + int (*submit_cbw_request)(struct sdioemb_slot *slot, uint8_t cmd_index, uint16_t block_size, uint32_t cmd_arg); + int (*submit_data_request)(struct sdioemb_slot *slot, + enum ushc_request_direction direction, + void* request_buffer, + uint32_t request_buffer_length); + int (*submit_csw_request)(struct sdioemb_slot *slot); + + os_spinlock_t lock; + + uint32_t base_clock; + uint32_t controler_capabilities; + uint16_t controler_state; + struct sdioemb_cmd* current_cmd; + +#define DISCONNECTED 0 +#define INT_EN 1 +#define IGNORE_NEXT_INT 2 +#define STOP 4 + uint32_t flags; + +#define USHC_INT_STATUS_SDIO_INT (1 << 1) +#define USHC_INT_STATUS_CARD_PRESENT (1 << 0) + uint8_t interrupt_status; + + size_t block_size; +}; + +#define USHC_GET_CAPS_VERSION_MASK 0xff +#define USHC_GET_CAPS_3V3 (1 << 8) +#define USHC_GET_CAPS_3V0 (1 << 9) +#define USHC_GET_CAPS_1V8 (1 << 10) +#define USHC_GET_CAPS_HIGH_SPD (1 << 16) + +#define USHC_PWR_CTRL_OFF 0x00 +#define USHC_PWR_CTRL_3V3 0x01 +#define USHC_PWR_CTRL_3V0 0x02 +#define USHC_PWR_CTRL_1V8 0x03 + +#define USHC_HOST_CTRL_4BIT (1 << 1) +#define USHC_HOST_CTRL_HIGH_SPD (1 << 0) + +#define USHC_READ_RESP_BUSY (1 << 4) +#define USHC_READ_RESP_ERR_TIMEOUT (1 << 3) +#define USHC_READ_RESP_ERR_CRC (1 << 2) +#define USHC_READ_RESP_ERR_DAT (1 << 1) +#define USHC_READ_RESP_ERR_CMD (1 << 0) +#define USHC_READ_RESP_ERR_MASK 0x0f + +void sdioemb_ushc_init(struct sdioemb_ushc* ushc); +void sdioemb_ushc_clean_up(struct sdioemb_ushc* ushc); + +int sdioemb_ushc_start(struct sdioemb_ushc* ushc); +void sdioemb_ushc_stop(struct sdioemb_ushc* ushc); + +bool sdioemb_ushc_isr(struct sdioemb_ushc* ushc, uint8_t int_stat); + +int sdioemb_ushc_set_bus_freq(struct sdioemb_ushc* ushc, int clk); +int sdioemb_ushc_set_bus_width(struct sdioemb_ushc* ushc, int bus_width); +int sdioemb_ushc_start_cmd(struct sdioemb_ushc* ushc, struct sdioemb_cmd *cmd); +int sdioemb_ushc_card_present(struct sdioemb_ushc* ushc); +int sdioemb_ushc_card_power(struct sdioemb_ushc* ushc, enum sdioemb_power power); +void sdioemb_ushc_enable_card_int(struct sdioemb_ushc* ushc); +void sdioemb_ushc_disable_card_int(struct sdioemb_ushc* ushc); +int sdioemb_ushc_hard_reset(struct sdioemb_ushc* ushc); + +void sdioemb_ushc_command_complete(struct sdioemb_ushc* ushc, uint8_t status, uint32_t respones); + +int ushc_hw_get_caps(struct sdioemb_ushc* ushc); +static int ushc_hw_set_host_ctrl(struct sdioemb_ushc* ushc, uint16_t mask, uint16_t val); +static int ushc_hw_submit_vendor_request(struct sdioemb_ushc* ushc, + enum ushc_request request, + enum ushc_request_recipient recipient, + enum ushc_request_direction direction, + uint16_t value, + uint16_t index, + void* io_buffer, + uint32_t io_buffer_length); + +#endif diff --git a/drivers/staging/csr/sdioemb/trace.h b/drivers/staging/csr/sdioemb/trace.h new file mode 100644 index 000000000000..57cbb010eced --- /dev/null +++ b/drivers/staging/csr/sdioemb/trace.h @@ -0,0 +1,19 @@ +/* + * Sdioemb trace messages. + * + * Copyright (C) 2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ + +#ifndef SDIOEMB_TRACE_H +#define SDIOEMB_TRACE_H + +#if defined(__linux__) +# define OS_TRACE_PREFIX "sdioemb: " +#endif + +#include + +#endif /* #ifndef SDIOEMB_TRACE_H */ diff --git a/drivers/staging/csr/sdioemb/uif.h b/drivers/staging/csr/sdioemb/uif.h new file mode 100644 index 000000000000..c09357fd2fbc --- /dev/null +++ b/drivers/staging/csr/sdioemb/uif.h @@ -0,0 +1,41 @@ +/* + * Userspace interface to the SDIO Userspace Interface driver. + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + */ +#ifndef LINUX_SDIOEMB_UIF_H +#define LINUX_SDIOEMB_UIF_H + +enum sdioemb_uif_cmd_type { + SDIOEMB_UIF_CMD52_READ, SDIOEMB_UIF_CMD52_WRITE, + SDIOEMB_UIF_CMD53_READ, SDIOEMB_UIF_CMD53_WRITE, +}; + +struct sdioemb_uif_cmd { + enum sdioemb_uif_cmd_type type; + int function; + uint32_t address; + uint8_t * data; + size_t len; + int block_size; +}; + +#define SDIOEMB_UIF_IOC_MAGIC 's' + +#define SDIOEMB_UIF_IOCQNUMFUNCS _IO(SDIOEMB_UIF_IOC_MAGIC, 0) +#define SDIOEMB_UIF_IOCCMD _IOWR(SDIOEMB_UIF_IOC_MAGIC, 1, struct sdioemb_uif_cmd) +#define SDIOEMB_UIF_IOCWAITFORINT _IO(SDIOEMB_UIF_IOC_MAGIC, 2) +#define SDIOEMB_UIF_IOCTBUSWIDTH _IO(SDIOEMB_UIF_IOC_MAGIC, 3) +#define SDIOEMB_UIF_IOCREINSERT _IO(SDIOEMB_UIF_IOC_MAGIC, 4) +#define SDIOEMB_UIF_IOCTBUSFREQ _IO(SDIOEMB_UIF_IOC_MAGIC, 5) +#define SDIOEMB_UIF_IOCQMANFID _IO(SDIOEMB_UIF_IOC_MAGIC, 6) +#define SDIOEMB_UIF_IOCQCARDID _IO(SDIOEMB_UIF_IOC_MAGIC, 7) +#define SDIOEMB_UIF_IOCQSTDIF _IO(SDIOEMB_UIF_IOC_MAGIC, 8) +#define SDIOEMB_UIF_IOCQMAXBLKSZ _IO(SDIOEMB_UIF_IOC_MAGIC, 9) +#define SDIOEMB_UIF_IOCQBLKSZ _IO(SDIOEMB_UIF_IOC_MAGIC, 10) +#define SDIOEMB_UIF_IOCTBLKSZ _IO(SDIOEMB_UIF_IOC_MAGIC, 11) + +#endif /* #ifndef LINUX_SDIOEMB_UIF_H */ diff --git a/drivers/staging/csr/sdioemb/version.h b/drivers/staging/csr/sdioemb/version.h new file mode 100644 index 000000000000..b88ef6e4ec9f --- /dev/null +++ b/drivers/staging/csr/sdioemb/version.h @@ -0,0 +1,11 @@ +/* Autogenerated by the sdioemb release procedure. */ +#ifndef SDIOEMB_VERSION_H +#define SDIOEMB_VERSION_H + +#define SDIOEMB_RELEASE 31 + +#ifndef SDIOEMB_RELEASE_EXTRA +#define SDIOEMB_RELEASE_EXTRA "" +#endif + +#endif /* #ifndef SDIOEMB_VERSION_H */ diff --git a/drivers/staging/csr/sme_blocking.c b/drivers/staging/csr/sme_blocking.c new file mode 100644 index 000000000000..f30eda950ad6 --- /dev/null +++ b/drivers/staging/csr/sme_blocking.c @@ -0,0 +1,1468 @@ +/* + * --------------------------------------------------------------------------- + * FILE: sme_mgt_blocking.c + * + * PURPOSE: + * This file contains the driver specific implementation of + * the WEXT <==> SME MGT interface for all SME builds that support WEXT. + * + * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + +#include "unifi_priv.h" + + +/* + * This file also contains the implementation of the asyncronous + * requests to the SME. + * + * Before calling an asyncronous SME function, we call sme_init_request() + * which gets hold of the SME semaphore and updates the request status. + * The semaphore makes sure that there is only one pending request to + * the SME at a time. + * + * Now we are ready to call the SME function, but only if + * sme_init_request() has returned 0. + * + * When the SME function returns, we need to wait + * for the reply. This is done in sme_wait_for_reply(). + * If the request times-out, the request status is set to SME_REQUEST_TIMEDOUT + * and the sme_wait_for_reply() returns. + * + * If the SME replies in time, we call sme_complete_request(). + * There we change the request status to SME_REQUEST_RECEIVED. This will + * wake up the process waiting on sme_wait_for_reply(). + * It is important that we copy the reply data in priv->sme_reply + * before calling sme_complete_request(). + * + * Handling the wext requests, we need to block + * until the SME sends the response to our request. + * We use the sme_init_request() and sme_wait_for_reply() + * to implement this behavior in the following functions: + * sme_mgt_wifi_on() + * sme_mgt_wifi_off() + * sme_mgt_scan_full() + * sme_mgt_scan_results_get_async() + * sme_mgt_connect() + * unifi_mgt_media_status_ind() + * sme_mgt_disconnect() + * sme_mgt_pmkid() + * sme_mgt_key() + * sme_mgt_mib_get() + * sme_mgt_mib_set() + * sme_mgt_versions_get() + * sme_mgt_set_value() + * sme_mgt_get_value() + * sme_mgt_set_value_async() + * sme_mgt_get_value_async() + * sme_mgt_packet_filter_set() + * sme_mgt_tspec() + */ + + +/* + * Handling the suspend and resume system events, we need to block + * until the SME sends the response to our indication. + * We use the sme_init_request() and sme_wait_for_reply() + * to implement this behavior in the following functions: + * sme_sys_suspend() + * sme_sys_resume() + */ + +#define UNIFI_SME_MGT_SHORT_TIMEOUT 10000 +#define UNIFI_SME_MGT_LONG_TIMEOUT 19000 +#define UNIFI_SME_SYS_LONG_TIMEOUT 10000 + +#ifdef UNIFI_DEBUG +# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, __func__) +#else +# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, NULL) +#endif + +static int +sme_init_request(unifi_priv_t *priv) +{ + if (priv == NULL) { + unifi_error(priv, "sme_init_request: Invalid priv\n"); + return -EIO; + } + + /* Grab the SME semaphore until the reply comes, or timeout */ + if (down_interruptible(&priv->sme_sem)) { + unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n"); + return -EIO; + } + priv->sme_reply.request_status = SME_REQUEST_PENDING; + + return 0; + +} /* sme_init_request() */ + + +void +uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func) +{ + if (priv == NULL) { + unifi_error(priv, "sme_complete_request: Invalid priv\n"); + return; + } + + if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { + unifi_notice(priv, + "sme_complete_request: request not pending %s (s:%d)\n", + (func ? func : ""), priv->sme_reply.request_status); + return; + } + priv->sme_reply.request_status = SME_REQUEST_RECEIVED; + priv->sme_reply.reply_status = reply_status; + + wake_up_interruptible(&priv->sme_request_wq); + + return; +} + + +static int +_sme_wait_for_reply(unifi_priv_t *priv, + unsigned long timeout, const char *func) +{ + long r; + + unifi_trace(priv, UDBG5, "sme_wait_for_reply: sleep\n"); + r = wait_event_interruptible_timeout(priv->sme_request_wq, + (priv->sme_reply.request_status != SME_REQUEST_PENDING), + msecs_to_jiffies(timeout)); + unifi_trace(priv, UDBG5, "sme_wait_for_reply: awake\n"); + + if (r == -ERESTARTSYS) { + /* The thread was killed */ + up(&priv->sme_sem); + return r; + } + if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) { + unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n", + (func ? func : ""), priv->sme_reply.request_status, timeout); + + priv->sme_reply.request_status = SME_REQUEST_TIMEDOUT; + + /* Release the SME semaphore that was downed in sme_init_request() */ + up(&priv->sme_sem); + + return -ETIMEDOUT; + } + + /* Release the SME semaphore that was downed in sme_init_request() */ + up(&priv->sme_sem); + + return 0; +} /* sme_wait_for_reply() */ + + + + +#ifdef CSR_SUPPORT_WEXT +int sme_mgt_wifi_on(unifi_priv_t *priv) +{ + CsrUint16 numElements; + CsrWifiSmeDataBlock* dataList; +#ifdef CSR_SUPPORT_WEXT_AP + int r; +#endif + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_wifi_on: invalid smepriv\n"); + return -EIO; + } + + if (priv->mib_data.length) { + numElements = 1; + dataList = &priv->mib_data; + } else { + numElements = 0; + dataList = NULL; + } + /* Start the SME */ +#ifdef CSR_SUPPORT_WEXT_AP + r = sme_init_request(priv); + if (r) { + return -EIO; + } +#endif + CsrWifiSmeWifiOnReqSend(0, priv->sta_mac_address, numElements, dataList); +#ifdef CSR_SUPPORT_WEXT_AP + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); + unifi_trace(priv, UDBG4, + "sme_mgt_wifi_on: unifi_mgt_wifi_oo_req <-- (r=%d, status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +#else + return 0; +#endif +} /* sme_mgt_wifi_on() */ + + +int sme_mgt_wifi_off(unifi_priv_t *priv) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_wifi_off: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + /* Stop the SME */ + CsrWifiSmeWifiOffReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); + +} /* sme_mgt_wifi_off */ + +int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key, + CsrWifiSmeListAction action) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_key: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + return convert_sme_error(priv->sme_reply.reply_status); +} + + +int sme_mgt_scan_full(unifi_priv_t *priv, + CsrWifiSsid *specific_ssid, + int num_channels, + unsigned char *channel_list) +{ + CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; + CsrBool is_active = (num_channels > 0) ? TRUE : FALSE; + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n"); + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + /* If a channel list is provided, do an active scan */ + if (is_active) { + unifi_trace(priv, UDBG1, + "channel list - num_channels: %d, active scan\n", + num_channels); + } + + CsrWifiSmeScanFullReqSend(0, + specific_ssid->length?1:0, /* 0 or 1 SSIDS */ + specific_ssid, + bcastAddress, + is_active, + CSR_WIFI_SME_BSS_TYPE_ANY_BSS, + CSR_WIFI_SME_SCAN_TYPE_ALL, + (CsrUint16)num_channels, channel_list, + 0, NULL); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status); + if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE) { + return 0; /* initial scan already underway */ + } else { + return convert_sme_error(priv->sme_reply.reply_status); + } +} + + +int sme_mgt_scan_results_get_async(unifi_priv_t *priv, + struct iw_request_info *info, + char *scan_results, + long scan_results_len) +{ + CsrUint16 scan_result_list_count; + CsrWifiSmeScanResult *scan_result_list; + CsrWifiSmeScanResult *scan_result; + int r; + int i; + char *current_ev = scan_results; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_scan_results_get_async: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeScanResultsGetReqSend(0); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); + if (r) { + return r; + } + + scan_result_list_count = priv->sme_reply.reply_scan_results_count; + scan_result_list = priv->sme_reply.reply_scan_results; + unifi_trace(priv, UDBG2, + "scan_results: Scan returned %d, numElements=%d\n", + r, scan_result_list_count); + + /* OK, now we have the scan results */ + for (i = 0; i < scan_result_list_count; ++i) { + scan_result = &scan_result_list[i]; + + unifi_trace(priv, UDBG2, "Scan Result: %.*s\n", + scan_result->ssid.length, + scan_result->ssid.ssid); + + r = unifi_translate_scan(priv->netdev[0], info, + current_ev, + scan_results + scan_results_len, + scan_result, i+1); + + if (r < 0) { + CsrPmemFree(scan_result_list); + priv->sme_reply.reply_scan_results_count = 0; + priv->sme_reply.reply_scan_results = NULL; + return r; + } + + current_ev += r; + } + + /* + * Free the scan results allocated in unifi_mgt_scan_results_get_cfm() + * and invalidate the reply_scan_results to avoid re-using + * the freed pointers. + */ + CsrPmemFree(scan_result_list); + priv->sme_reply.reply_scan_results_count = 0; + priv->sme_reply.reply_scan_results = NULL; + + unifi_trace(priv, UDBG2, + "scan_results: Scan translated to %d bytes\n", + current_ev - scan_results); + return (current_ev - scan_results); +} + + +int sme_mgt_connect(unifi_priv_t *priv) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_connect: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n", + priv->connection_config.ssid.length, + priv->connection_config.ssid.ssid); + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + if (priv->sme_reply.reply_status) { + unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n", + priv->sme_reply.reply_status); + } + + return convert_sme_error(priv->sme_reply.reply_status); +} + + +int sme_mgt_disconnect(unifi_priv_t *priv) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_disconnect: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + + +int sme_mgt_pmkid(unifi_priv_t *priv, + CsrWifiSmeListAction action, + CsrWifiSmePmkidList *pmkid_list) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, + pmkid_list->pmkidsCount, pmkid_list->pmkids); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + + +int sme_mgt_mib_get(unifi_priv_t *priv, + unsigned char *varbind, int *length) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + priv->mib_cfm_buffer = varbind; + priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH; + + CsrWifiSmeMibGetReqSend(0, *length, varbind); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + priv->mib_cfm_buffer_length = 0; + priv->mib_cfm_buffer = NULL; + return r; + } + + *length = priv->mib_cfm_buffer_length; + + priv->mib_cfm_buffer_length = 0; + priv->mib_cfm_buffer = NULL; + unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + +int sme_mgt_mib_set(unifi_priv_t *priv, + unsigned char *varbind, int length) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeMibSetReqSend(0, length, varbind); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + +#endif /* CSR_SUPPORT_WEXT */ + +int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_set_value_async: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmePowerConfigSetReqSend(0, *powerConfig); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_set_value: invalid smepriv\n"); + return -EIO; + } + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtPowerConfigSetReq(priv->smepriv, *powerConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + unifi_trace(priv, UDBG4, + "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); + return -EIO; + } + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig); + status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#ifdef CSR_SUPPORT_WEXT + +int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeMibConfigSetReqSend(0, *mibConfig); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n"); + return -EIO; + } + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtMibConfigSetReq(priv->smepriv, *mibConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n"); + return -EIO; + } + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtCoexConfigSetReq(priv->smepriv, *coexConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#endif /* CSR_SUPPORT_WEXT */ + +int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n"); + return -EIO; + } + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtHostConfigSetReq(priv->smepriv, *hostConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#ifdef CSR_SUPPORT_WEXT + +int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeVersionsGetReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (versions != NULL) { + memcpy((unsigned char*)versions, + (unsigned char*)&priv->sme_reply.versions, + sizeof(CsrWifiSmeVersions)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#endif /* CSR_SUPPORT_WEXT */ + +int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_power_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmePowerConfigGetReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (powerConfig != NULL) { + memcpy((unsigned char*)powerConfig, + (unsigned char*)&priv->sme_reply.powerConfig, + sizeof(CsrWifiSmePowerConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_get_versions: unifi_mgt_power_config_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtPowerConfigGetReq(priv->smepriv, powerConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (hostConfig != NULL) { + memcpy((unsigned char*)hostConfig, + (unsigned char*)&priv->sme_reply.hostConfig, + sizeof(CsrWifiSmeHostConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_sme_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req -->\n"); + + /* Common device config */ + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeSmeCommonConfigGetReqSend(0); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (deviceConfig != NULL) { + memcpy((unsigned char*)deviceConfig, + (unsigned char*)&priv->sme_reply.deviceConfig, + sizeof(CsrWifiSmeDeviceConfig)); + } + + /* STA config */ + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (staConfig != NULL) { + memcpy((unsigned char*)staConfig, + (unsigned char*)&priv->sme_reply.staConfig, + sizeof(CsrWifiSmeStaConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtSmeConfigGetReq(priv->smepriv, staConfig); + status = CsrWifiSmeMgtDeviceConfigGetReq(priv->smepriv, deviceConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_coex_info_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeCoexInfoGetReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (coexInfo != NULL) { + memcpy((unsigned char*)coexInfo, + (unsigned char*)&priv->sme_reply.coexInfo, + sizeof(CsrWifiSmeCoexInfo)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtCoexInfoGetReq(priv->smepriv, coexInfo); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#ifdef CSR_SUPPORT_WEXT + +int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_coex_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeCoexConfigGetReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (coexConfig != NULL) { + memcpy((unsigned char*)coexConfig, + (unsigned char*)&priv->sme_reply.coexConfig, + sizeof(CsrWifiSmeCoexConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtCoexConfigGetReq(priv->smepriv, coexConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_mib_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeMibConfigGetReqSend(0); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (mibConfig != NULL) { + memcpy((unsigned char*)mibConfig, + (unsigned char*)&priv->sme_reply.mibConfig, + sizeof(CsrWifiSmeMibConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtMibConfigGetReq(priv->smepriv, mibConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_connection_info_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (connectionInfo != NULL) { + memcpy((unsigned char*)connectionInfo, + (unsigned char*)&priv->sme_reply.connectionInfo, + sizeof(CsrWifiSmeConnectionInfo)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtConnectionInfoGetReq(priv->smepriv, connectionInfo); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_connection_config_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (connectionConfig != NULL) { + memcpy((unsigned char*)connectionConfig, + (unsigned char*)&priv->sme_reply.connectionConfig, + sizeof(CsrWifiSmeConnectionConfig)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtConnectionConfigGetReq(priv->smepriv, connectionConfig); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats) +{ +#ifdef CSR_SME_USERSPACE + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_connection_stats_get: invalid smepriv\n"); + return -EIO; + } + + unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n"); + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + /* store the reply */ + if (connectionStats != NULL) { + memcpy((unsigned char*)connectionStats, + (unsigned char*)&priv->sme_reply.connectionStats, + sizeof(CsrWifiSmeConnectionStats)); + } + + unifi_trace(priv, UDBG4, + "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + + return convert_sme_error(priv->sme_reply.reply_status); +#else + CsrResult status; + CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); + status = CsrWifiSmeMgtConnectionStatsGetReq(priv->smepriv, connectionStats); + CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); + return convert_sme_error(status); +#endif +} + +#endif /* CSR_SUPPORT_WEXT */ + +int sme_mgt_packet_filter_set(unifi_priv_t *priv) +{ + CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }}; + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n"); + return -EIO; + } + if (priv->packet_filters.arp_filter) { + ipAddress.a[0] = (priv->sta_ip_address ) & 0xFF; + ipAddress.a[1] = (priv->sta_ip_address >> 8) & 0xFF; + ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF; + ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF; + } + + unifi_trace(priv, UDBG5, + "sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n", + ipAddress.a[0], ipAddress.a[1], + ipAddress.a[2], ipAddress.a[3]); + + /* Doesn't block for a confirm */ + CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, + priv->packet_filters.tclas_ies_length, + priv->filter_tclas_ies, + priv->packet_filters.filter_mode, + ipAddress); + return 0; +} + +int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action, + CsrUint32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE, + action, tid, TRUE, 0, + tspec->length, tspec->data, + tclas->length, tclas->data); + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + + + +int sme_sys_suspend(unifi_priv_t *priv) +{ + int r; + CsrResult csrResult; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_sys_suspend: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ + priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; + + /* Suspend the SME, which will cause it to power down UniFi */ + CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend); + r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); + if (r) { + /* No reply - forcibly power down in case the request wasn't processed */ + unifi_notice(priv, + "suspend: SME did not reply %s, ", + priv->ptest_mode ? "leave powered" : "power off UniFi anyway\n"); + + /* Leave power on for production test, though */ + if (!priv->ptest_mode) { + /* Put UniFi to deep sleep, in case we can not power it off */ + CsrSdioClaim(priv->sdio); + csrResult = unifi_force_low_power_mode(priv->card); + + /* For WOL, the UniFi must stay powered */ + if (!priv->wol_suspend) { + unifi_trace(priv, UDBG1, "Power off\n"); + CsrSdioPowerOff(priv->sdio); + } + CsrSdioRelease(priv->sdio); + } + } + + if (priv->wol_suspend) { + unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n"); + + /* For PIO WOL, disable SDIO interrupt to enable PIO mode in the f/w */ + if (enable_wol == UNIFI_WOL_PIO) { + unifi_trace(priv, UDBG1, "Remove IRQ to enable PIO WOL\n"); + if (csr_sdio_linux_remove_irq(priv->sdio)) { + unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n"); + } + } + } + + /* Consider UniFi to be uninitialised */ + priv->init_progress = UNIFI_INIT_NONE; + + unifi_trace(priv, UDBG1, "sme_sys_suspend: <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + + +int sme_sys_resume(unifi_priv_t *priv) +{ + int r; + + unifi_trace(priv, UDBG1, "sme_sys_resume %s\n", priv->wol_suspend ? "warm" : ""); + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_sys_resume: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend); + + if (priv->ptest_mode == 1) { + r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); + if (r) { + /* No reply - forcibly power down in case the request wasn't processed */ + unifi_notice(priv, + "resume: SME did not reply, return success anyway\n"); + } + } else { + + /* + * We are not going to wait for the reply because the SME might be in + * the userspace. In this case the event will reach it when the kernel + * resumes. So, release now the SME semaphore that was downed in + * sme_init_request(). + */ + up(&priv->sme_sem); + } + + return 0; +} + +#ifdef CSR_SUPPORT_WEXT_AP +int sme_ap_stop(unifi_priv_t *priv,CsrUint16 interface_tag) +{ + int r; + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_ap_stop: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiNmeApStopReqSend(0,interface_tag); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_ap_stop <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); + +} + +int sme_ap_start(unifi_priv_t *priv,CsrUint16 interface_tag, + CsrWifiSmeApConfig_t * ap_config) +{ + int r; + CsrWifiSmeApP2pGoConfig p2p_go_param; + memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig)); + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_ap_start: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiNmeApStartReqSend(0,interface_tag,CSR_WIFI_AP_TYPE_LEGACY,FALSE, + ap_config->ssid,1,ap_config->channel, + ap_config->credentials,ap_config->max_connections, + p2p_go_param,FALSE); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + if (r) { + return r; + } + + unifi_trace(priv, UDBG4, + "sme_ap_start <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} + +int sme_ap_config(unifi_priv_t *priv, + CsrWifiSmeApMacConfig *ap_mac_config, + CsrWifiNmeApConfig *group_security_config) +{ + int r; + CsrWifiSmeApP2pGoConfig p2p_go_param; + memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig)); + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_ap_config: invalid smepriv\n"); + return -EIO; + } + + r = sme_init_request(priv); + if (r) { + return -EIO; + } + + CsrWifiNmeApConfigSetReqSend(0,*group_security_config, + *ap_mac_config); + + r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); + + unifi_trace(priv, UDBG4, + "sme_ap_config <-- (r=%d status=%d)\n", + r, priv->sme_reply.reply_status); + return convert_sme_error(priv->sme_reply.reply_status); +} +#endif diff --git a/drivers/staging/csr/sme_mgt.c b/drivers/staging/csr/sme_mgt.c new file mode 100644 index 000000000000..ab70216516b3 --- /dev/null +++ b/drivers/staging/csr/sme_mgt.c @@ -0,0 +1,1018 @@ +/* + * --------------------------------------------------------------------------- + * FILE: sme_mgt.c + * + * PURPOSE: + * This file contains the driver specific implementation of + * the SME MGT SAP. + * It is part of the porting exercise. + * + * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + +#include "csr_wifi_hip_unifiversion.h" +#include "unifi_priv.h" +#include "csr_wifi_hip_conversions.h" +/* + * This file implements the SME MGT API. It contains the following functions: + * CsrWifiSmeWifiFlightmodeCfmSend() + * CsrWifiSmeWifiOnCfmSend() + * CsrWifiSmeWifiOffCfmSend() + * CsrWifiSmeWifiOffIndSend() + * CsrWifiSmeScanFullCfmSend() + * CsrWifiSmeScanResultsGetCfmSend() + * CsrWifiSmeScanResultIndSend() + * CsrWifiSmeScanResultsFlushCfmSend() + * CsrWifiSmeConnectCfmSend() + * CsrWifiSmeMediaStatusIndSend() + * CsrWifiSmeDisconnectCfmSend() + * CsrWifiSmeKeyCfmSend() + * CsrWifiSmeMulticastAddressCfmSend() + * CsrWifiSmeSetValueCfmSend() + * CsrWifiSmeGetValueCfmSend() + * CsrWifiSmeMicFailureIndSend() + * CsrWifiSmePmkidCfmSend() + * CsrWifiSmePmkidCandidateListIndSend() + * CsrWifiSmeMibSetCfmSend() + * CsrWifiSmeMibGetCfmSend() + * CsrWifiSmeMibGetNextCfmSend() + * CsrWifiSmeConnectionQualityIndSend() + * CsrWifiSmePacketFilterSetCfmSend() + * CsrWifiSmeTspecCfmSend() + * CsrWifiSmeTspecIndSend() + * CsrWifiSmeBlacklistCfmSend() + * CsrWifiSmeEventMaskSetCfmSend() + * CsrWifiSmeRoamStartIndSend() + * CsrWifiSmeRoamCompleteIndSend() + * CsrWifiSmeAssociationStartIndSend() + * CsrWifiSmeAssociationCompleteIndSend() + * CsrWifiSmeIbssStationIndSend() + */ + + +void CsrWifiSmeMicFailureIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMicFailureInd* ind = (CsrWifiSmeMicFailureInd*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMicFailureIndSend: invalid priv\n"); + return; + } + + unifi_trace(priv, UDBG1, + "CsrWifiSmeMicFailureIndSend: count=%d, KeyType=%d\n", + ind->count, ind->keyType); + + wext_send_michaelmicfailure_event(priv, ind->count, ind->address, ind->keyType, ind->interfaceTag); +#endif +} + + +void CsrWifiSmePmkidCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmePmkidCfm* cfm = (CsrWifiSmePmkidCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmePmkidCfmSend: Invalid ospriv.\n"); + return; + } + + /* + * WEXT never does a GET operation the PMKIDs, so we don't need + * handle data returned in pmkids. + */ + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmePmkidCandidateListIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmePmkidCandidateListInd* ind = (CsrWifiSmePmkidCandidateListInd*)msg; + int i; + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiSmePmkidCandidateListIndSend: invalid smepriv\n"); + return; + } + + for (i = 0; i < ind->pmkidCandidatesCount; i++) + { + wext_send_pmkid_candidate_event(priv, ind->pmkidCandidates[i].bssid, ind->pmkidCandidates[i].preAuthAllowed, ind->interfaceTag); + } +#endif +} + +void CsrWifiSmeScanResultsFlushCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeScanResultsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeScanResultsGetCfm* cfm = (CsrWifiSmeScanResultsGetCfm*)msg; + int bytesRequired = cfm->scanResultsCount * sizeof(CsrWifiSmeScanResult); + int i; + CsrUint8* current_buff; + CsrWifiSmeScanResult* scanCopy; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeScanResultsGetCfmSend: Invalid ospriv.\n"); + return; + } + + /* Calc the size of the buffer reuired */ + for (i = 0; i < cfm->scanResultsCount; ++i) { + const CsrWifiSmeScanResult *scan_result = &cfm->scanResults[i]; + bytesRequired += scan_result->informationElementsLength; + } + + /* Take a Copy of the scan Results :-) */ + scanCopy = CsrPmemAlloc(bytesRequired); + memcpy(scanCopy, cfm->scanResults, sizeof(CsrWifiSmeScanResult) * cfm->scanResultsCount); + + /* Take a Copy of the Info Elements AND update the scan result pointers */ + current_buff = (CsrUint8*)&scanCopy[cfm->scanResultsCount]; + for (i = 0; i < cfm->scanResultsCount; ++i) + { + CsrWifiSmeScanResult *scan_result = &scanCopy[i]; + CsrMemCpy(current_buff, scan_result->informationElements, scan_result->informationElementsLength); + scan_result->informationElements = current_buff; + current_buff += scan_result->informationElementsLength; + } + + priv->sme_reply.reply_scan_results_count = cfm->scanResultsCount; + priv->sme_reply.reply_scan_results = scanCopy; + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeScanFullCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeScanFullCfm* cfm = (CsrWifiSmeScanFullCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeScanFullCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeScanResultIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + +} + + +void CsrWifiSmeConnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeConnectCfm* cfm = (CsrWifiSmeConnectCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeConnectCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeDisconnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeDisconnectCfm* cfm = (CsrWifiSmeDisconnectCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeDisconnectCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeKeyCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeKeyCfm* cfm = (CsrWifiSmeKeyCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeKeyCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeMulticastAddressCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMulticastAddressCfm* cfm = (CsrWifiSmeMulticastAddressCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMulticastAddressCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeWifiFlightmodeCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeWifiFlightmodeCfm* cfm = (CsrWifiSmeWifiFlightmodeCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeWifiFlightmodeCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeWifiOnCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeWifiOnCfm* cfm = (CsrWifiSmeWifiOnCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeWifiOnCfmSend: Invalid ospriv.\n"); + return; + } + + unifi_trace(priv, UDBG4, + "CsrWifiSmeWifiOnCfmSend: wake up status %d\n", cfm->status); +#ifdef CSR_SUPPORT_WEXT_AP + sme_complete_request(priv, cfm->status); +#endif + +#endif +} + +void CsrWifiSmeWifiOffCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeWifiOffCfm* cfm = (CsrWifiSmeWifiOffCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeWifiOffCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeWifiOffIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeWifiOffInd* ind = (CsrWifiSmeWifiOffInd*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiRouterCtrlStoppedReqSend: Invalid ospriv.\n"); + return; + } + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlStoppedReqSend: invalid smepriv\n"); + return; + } + + /* + * If the status indicates an error, the SME is in a stopped state. + * We need to start it again in order to reinitialise UniFi. + */ + switch (ind->reason) { + case CSR_WIFI_SME_CONTROL_INDICATION_ERROR: + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlStoppedReqSend: Restarting SME (ind:%d)\n", + ind->reason); + + /* On error, restart the SME */ + sme_mgt_wifi_on(priv); + break; + case CSR_WIFI_SME_CONTROL_INDICATION_EXIT: +#ifdef CSR_SUPPORT_WEXT_AP + sme_complete_request(priv, 0); +#endif + break; + default: + break; + } + +#endif +} + +void CsrWifiSmeVersionsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeVersionsGetCfm* cfm = (CsrWifiSmeVersionsGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeVersionsGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.versions = cfm->versions; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmePowerConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmePowerConfigGetCfm* cfm = (CsrWifiSmePowerConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmePowerConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.powerConfig = cfm->powerConfig; + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeHostConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeHostConfigGetCfm* cfm = (CsrWifiSmeHostConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeHostConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.hostConfig = cfm->hostConfig; + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeCoexInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCoexInfoGetCfm* cfm = (CsrWifiSmeCoexInfoGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeCoexInfoGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.coexInfo = cfm->coexInfo; + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeCoexConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCoexConfigGetCfm* cfm = (CsrWifiSmeCoexConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeCoexConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.coexConfig = cfm->coexConfig; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeMibConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMibConfigGetCfm* cfm = (CsrWifiSmeMibConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMibConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.mibConfig = cfm->mibConfig; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeConnectionInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeConnectionInfoGetCfm* cfm = (CsrWifiSmeConnectionInfoGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeConnectionInfoGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.connectionInfo = cfm->connectionInfo; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeConnectionConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeConnectionConfigGetCfm* cfm = (CsrWifiSmeConnectionConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeConnectionConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.connectionConfig = cfm->connectionConfig; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeConnectionStatsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeConnectionStatsGetCfm* cfm = (CsrWifiSmeConnectionStatsGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeConnectionStatsGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.connectionStats = cfm->connectionStats; + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeMibSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMibSetCfm* cfm = (CsrWifiSmeMibSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMibSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeMibGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMibGetCfm* cfm = (CsrWifiSmeMibGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMibGetCfmSend: Invalid ospriv.\n"); + return; + } + + if (cfm->mibAttribute == NULL) { + unifi_error(priv, "CsrWifiSmeMibGetCfmSend: Empty reply.\n"); + sme_complete_request(priv, cfm->status); + return; + } + + if ((priv->mib_cfm_buffer != NULL) && + (priv->mib_cfm_buffer_length >= cfm->mibAttributeLength)) { + memcpy(priv->mib_cfm_buffer, cfm->mibAttribute, cfm->mibAttributeLength); + priv->mib_cfm_buffer_length = cfm->mibAttributeLength; + } else { + unifi_error(priv, + "CsrWifiSmeMibGetCfmSend: No room to store MIB data (have=%d need=%d).\n", + priv->mib_cfm_buffer_length, cfm->mibAttributeLength); + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeMibGetNextCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMibGetNextCfm* cfm = (CsrWifiSmeMibGetNextCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeMibGetNextCfmSend: Invalid ospriv.\n"); + return; + } + + /* Need to copy MIB data */ + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeConnectionQualityIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeConnectionQualityInd* ind = (CsrWifiSmeConnectionQualityInd*)msg; + int signal, noise, snr; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeConnectionQualityIndSend: Invalid ospriv.\n"); + return; + } + + /* + * level and noise below are mapped into an unsigned 8 bit number, + * ranging from [-192; 63]. The way this is achieved is simply to + * add 0x100 onto the number if it is negative, + * once clipped to the correct range. + */ + signal = ind->linkQuality.unifiRssi; + /* Clip range of snr */ + snr = (ind->linkQuality.unifiSnr > 0) ? ind->linkQuality.unifiSnr : 0; /* In dB relative, from 0 - 255 */ + snr = (snr < 255) ? snr : 255; + noise = signal - snr; + + /* Clip range of signal */ + signal = (signal < 63) ? signal : 63; + signal = (signal > -192) ? signal : -192; + + /* Clip range of noise */ + noise = (noise < 63) ? noise : 63; + noise = (noise > -192) ? noise : -192; + + /* Make u8 */ + signal = ( signal < 0 ) ? signal + 0x100 : signal; + noise = ( noise < 0 ) ? noise + 0x100 : noise; + + priv->wext_wireless_stats.qual.level = (u8)signal; /* -192 : 63 */ + priv->wext_wireless_stats.qual.noise = (u8)noise; /* -192 : 63 */ + priv->wext_wireless_stats.qual.qual = snr; /* 0 : 255 */ + priv->wext_wireless_stats.qual.updated = 0; + +#if WIRELESS_EXT > 16 + priv->wext_wireless_stats.qual.updated |= IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED | + IW_QUAL_QUAL_UPDATED; +#if WIRELESS_EXT > 18 + priv->wext_wireless_stats.qual.updated |= IW_QUAL_DBM; +#endif +#endif +#endif +} + +void CsrWifiSmePacketFilterSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmePacketFilterSetCfmSend: Invalid ospriv.\n"); + return; + } + + /* The packet filter set request does not block for a reply */ +} + +void CsrWifiSmeTspecCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeTspecCfm* cfm = (CsrWifiSmeTspecCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeTspecCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeTspecIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeBlacklistCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeEventMaskSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + + +void CsrWifiSmeRoamStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeRoamCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + /* This is called when the association completes, before any 802.1x authentication */ +} + +void CsrWifiSmeAssociationStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeAssociationCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeIbssStationIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeWifiOnIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeRestrictedAccessEnableCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeRestrictedAccessDisableCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + + +void CsrWifiSmeAdhocConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeAdhocConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeAdhocConfigSetCfm* cfm = (CsrWifiSmeAdhocConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeCalibrationDataGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeCalibrationDataSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCalibrationDataSetCfm* cfm = (CsrWifiSmeCalibrationDataSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeCcxConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeCcxConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCcxConfigSetCfm* cfm = (CsrWifiSmeCcxConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeCloakedSsidsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeCloakedSsidsSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCloakedSsidsSetCfm* cfm = (CsrWifiSmeCloakedSsidsSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + + +void CsrWifiSmeCoexConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeCoexConfigSetCfm* cfm = (CsrWifiSmeCoexConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeHostConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeHostConfigSetCfm* cfm = (CsrWifiSmeHostConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeLinkQualityGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + + +void CsrWifiSmeMibConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMibConfigSetCfm* cfm = (CsrWifiSmeMibConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmePermanentMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmePowerConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmePowerConfigSetCfm* cfm = (CsrWifiSmePowerConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeRoamingConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeMediaStatusInd* ind = (CsrWifiSmeMediaStatusInd*)msg; + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiSmeMediaStatusIndSend: invalid smepriv\n"); + return; + } + + if (ind->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) { + /* + * Send wireless-extension event up to userland to announce + * connection. + */ + wext_send_assoc_event(priv, + (unsigned char *)ind->connectionInfo.bssid.a, + (unsigned char *)ind->connectionInfo.assocReqInfoElements, + ind->connectionInfo.assocReqInfoElementsLength, + (unsigned char *)ind->connectionInfo.assocRspInfoElements, + ind->connectionInfo.assocRspInfoElementsLength, + (unsigned char *)ind->connectionInfo.assocScanInfoElements, + ind->connectionInfo.assocScanInfoElementsLength); + + unifi_trace(priv, UDBG2, + "CsrWifiSmeMediaStatusIndSend: IBSS=%02X:%02X:%02X:%02X:%02X:%02X\n", + ind->connectionInfo.bssid.a[0], + ind->connectionInfo.bssid.a[1], + ind->connectionInfo.bssid.a[2], + ind->connectionInfo.bssid.a[3], + ind->connectionInfo.bssid.a[4], + ind->connectionInfo.bssid.a[5]); + + sme_mgt_packet_filter_set(priv); + + } else { + /* + * Send wireless-extension event up to userland to announce + * connection lost to a BSS. + */ + wext_send_disassoc_event(priv); + } +#endif +} + +void CsrWifiSmeRoamingConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeRoamingConfigSetCfm* cfm = (CsrWifiSmeRoamingConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeRoamingConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeScanConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeScanConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_SUPPORT_WEXT + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeScanConfigSetCfm* cfm = (CsrWifiSmeScanConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +#endif +} + +void CsrWifiSmeStationMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeSmeCommonConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeSmeCommonConfigGetCfm* cfm = (CsrWifiSmeSmeCommonConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeCommonConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.deviceConfig = cfm->deviceConfig; + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeSmeStaConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeSmeStaConfigGetCfm* cfm = (CsrWifiSmeSmeStaConfigGetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeStaConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + priv->sme_reply.staConfig = cfm->smeConfig; + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeSmeCommonConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeSmeCommonConfigSetCfm* cfm = (CsrWifiSmeSmeCommonConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeCommonConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeSmeStaConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiSmeSmeStaConfigSetCfm* cfm = (CsrWifiSmeSmeStaConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiSmeSmeStaConfigGetCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeErrorIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeInfoIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeCoreDumpIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} +void CsrWifiSmeAmpStatusChangeIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiSmeActivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} +void CsrWifiSmeDeactivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +#ifdef CSR_SUPPORT_WEXT +#ifdef CSR_SUPPORT_WEXT_AP +void CsrWifiNmeApStartCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiNmeApStartCfm* cfm = (CsrWifiNmeApStartCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiNmeApStartCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiNmeApStopCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiNmeApStopCfm* cfm = (CsrWifiNmeApStopCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiNmeApStopCfmSend: Invalid ospriv.\n"); + return; + } + + sme_complete_request(priv, cfm->status); +} + +void CsrWifiNmeApConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiNmeApConfigSetCfm* cfm = (CsrWifiNmeApConfigSetCfm*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiNmeApConfigSetCfmSend: Invalid ospriv.\n"); + return; + } + sme_complete_request(priv, cfm->status); +} +#endif +#endif diff --git a/drivers/staging/csr/sme_native.c b/drivers/staging/csr/sme_native.c new file mode 100644 index 000000000000..2091109f7c16 --- /dev/null +++ b/drivers/staging/csr/sme_native.c @@ -0,0 +1,591 @@ +/* + * *************************************************************************** + * + * FILE: sme_native.c + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ + +#include + +#include "unifi_priv.h" +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" + +static const unsigned char wildcard_address[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +int +uf_sme_init(unifi_priv_t *priv) +{ + func_enter(); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) + sema_init(&priv->mlme_blocking_mutex, 1); +#else + init_MUTEX(&priv->mlme_blocking_mutex); +#endif + +#ifdef CSR_SUPPORT_WEXT + { + int r = uf_init_wext_interface(priv); + if (r != 0) { + func_exit(); + return r; + } + } +#endif + + + + func_exit(); + return 0; +} /* uf_sme_init() */ + + +void +uf_sme_deinit(unifi_priv_t *priv) +{ + + func_enter(); + + /* Free memory allocated for the scan table */ +/* unifi_clear_scan_table(priv); */ + + /* Cancel any pending workqueue tasks */ + flush_workqueue(priv->unifi_workqueue); + +#ifdef CSR_SUPPORT_WEXT + uf_deinit_wext_interface(priv); +#endif + + + func_exit(); +} /* uf_sme_deinit() */ + + +int sme_mgt_wifi_on(unifi_priv_t *priv) +{ + int r,i; + CsrInt32 csrResult; + + if (priv == NULL) { + return -EINVAL; + } + /* Initialize the interface mode to None */ + for (i=0; iinterfacePriv[i]->interfaceMode = 0; + } + + /* Set up interface mode so that get_packet_priority() can + * select the right QOS priority when WMM is enabled. + */ + priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA; + + r = uf_request_firmware_files(priv, UNIFI_FW_STA); + if (r) { + unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n"); + return r; + } + + /* + * The request to initialise UniFi might come while UniFi is running. + * We need to block all I/O activity until the reset completes, otherwise + * an SDIO error might occur resulting an indication to the SME which + * makes it think that the initialisation has failed. + */ + priv->bh_thread.block_thread = 1; + + /* Power on UniFi */ + CsrSdioClaim(priv->sdio); + csrResult = CsrSdioPowerOn(priv->sdio); + CsrSdioRelease(priv->sdio); + if(csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) { + return -EIO; + } + + if (csrResult == CSR_RESULT_SUCCESS) { + /* Initialise UniFi hardware */ + r = uf_init_hw(priv); + if (r) { + return r; + } + } + + /* Re-enable the I/O thread */ + priv->bh_thread.block_thread = 0; + + /* Disable deep sleep signalling during the firmware initialisation, to + * prevent the wakeup mechanism raising the SDIO clock beyond INIT before + * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind, + * immediately after the MLME-RESET.ind + */ + csrResult = unifi_configure_low_power_mode(priv->card, + UNIFI_LOW_POWER_DISABLED, + UNIFI_PERIODIC_WAKE_HOST_DISABLED); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_warning(priv, + "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n"); + } + + + /* Start the I/O thread */ + CsrSdioClaim(priv->sdio); + r = uf_init_bh(priv); + if (r) { + CsrSdioPowerOff(priv->sdio); + CsrSdioRelease(priv->sdio); + return r; + } + CsrSdioRelease(priv->sdio); + + priv->init_progress = UNIFI_INIT_FW_DOWNLOADED; + + return 0; +} + +int +sme_sys_suspend(unifi_priv_t *priv) +{ + const int interfaceNum = 0; /* FIXME */ + CsrResult csrResult; + + /* Abort any pending requests. */ + uf_abort_mlme(priv); + + /* Allow our mlme request to go through. */ + priv->io_aborted = 0; + + /* Send MLME-RESET.req to UniFi. */ + unifi_reset_state(priv, priv->netdev[interfaceNum]->dev_addr, 0); + + /* Stop the network traffic */ + netif_carrier_off(priv->netdev[interfaceNum]); + + /* Put UniFi to deep sleep */ + CsrSdioClaim(priv->sdio); + csrResult = unifi_force_low_power_mode(priv->card); + CsrSdioRelease(priv->sdio); + + return 0; +} /* sme_sys_suspend() */ + + +int +sme_sys_resume(unifi_priv_t *priv) +{ +#ifdef CSR_SUPPORT_WEXT + /* Send disconnect event so clients will re-initialise connection. */ + memset(priv->wext_conf.current_ssid, 0, UNIFI_MAX_SSID_LEN); + memset((void*)priv->wext_conf.current_bssid, 0, ETH_ALEN); + priv->wext_conf.capability = 0; + wext_send_disassoc_event(priv); +#endif + return 0; +} /* sme_sys_resume() */ + + +/* + * --------------------------------------------------------------------------- + * sme_native_log_event + * + * Callback function to be registered as the SME event callback. + * Copies the signal content into a new udi_log_t struct and adds + * it to the read queue for the SME client. + * + * Arguments: + * arg This is the value given to unifi_add_udi_hook, in + * this case a pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointers to any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +sme_native_log_event(ul_client_t *pcli, + const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata, + int dir) +{ + unifi_priv_t *priv; + udi_log_t *logptr; + u8 *p; + int i, r; + int signal_len; + int total_len; + udi_msg_t *msgptr; + CSR_SIGNAL signal; + ul_client_t *client = pcli; + + func_enter(); + + if (client == NULL) { + unifi_error(NULL, "sme_native_log_event: client has exited\n"); + return; + } + + priv = uf_find_instance(client->instance); + if (!priv) { + unifi_error(priv, "invalid priv\n"); + return; + } + + /* Just a sanity check */ + if ((sig_packed == NULL) || (sig_len <= 0)) { + return; + } + + /* Get the unpacked signal */ + r = read_unpack_signal(sig_packed, &signal); + if (r == 0) { + signal_len = SigGetSize(&signal); + } else { + CsrUint16 receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed) + sizeof(CsrUint16)) & 0xFF00; + + /* The control indications are 1 byte, pass them to client. */ + if (sig_len == 1) { + unifi_trace(priv, UDBG5, + "Control indication (0x%x) for native SME.\n", + *sig_packed); + + *(u8*)&signal = *sig_packed; + signal_len = sig_len; + } else if (receiver_id == 0) { + /* + * Also "unknown" signals with a ReceiverId of 0 are passed to the client + * without unpacking. (This is a code size optimisation to allow signals + * that the driver not interested in to be dropped from the unpack code). + */ + unifi_trace(priv, UDBG5, + "Signal 0x%.4X with ReceiverId 0 for native SME.\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); + + *(u8*)&signal = *sig_packed; + signal_len = sig_len; + } else { + unifi_error(priv, + "sme_native_log_event - Received unknown signal 0x%.4X.\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); + return; + } + } + + unifi_trace(priv, UDBG3, "sme_native_log_event: signal 0x%.4X for %d\n", + signal.SignalPrimitiveHeader.SignalId, + client->client_id); + + total_len = signal_len; + /* Calculate the buffer we need to store signal plus bulk data */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + total_len += bulkdata->d[i].data_length; + } + + /* Allocate log structure plus actual signal. */ + logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL); + + if (logptr == NULL) { + unifi_error(priv, + "Failed to allocate %d bytes for a UDI log record\n", + sizeof(udi_log_t) + total_len); + return; + } + + /* Fill in udi_log struct */ + INIT_LIST_HEAD(&logptr->q); + msgptr = &logptr->msg; + msgptr->length = sizeof(udi_msg_t) + total_len; + msgptr->timestamp = jiffies_to_msecs(jiffies); + msgptr->direction = dir; + msgptr->signal_length = signal_len; + + /* Copy signal and bulk data to the log */ + p = (u8 *)(msgptr + 1); + memcpy(p, &signal, signal_len); + p += signal_len; + + /* Append any bulk data */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + int len = bulkdata->d[i].data_length; + + /* + * Len here might not be the same as the length in the bulk data slot. + * The slot length will always be even, but len could be odd. + */ + if (len > 0) { + if (bulkdata->d[i].os_data_ptr) { + memcpy(p, bulkdata->d[i].os_data_ptr, len); + } else { + memset(p, 0, len); + } + p += len; + } + } + + /* Add to tail of log queue */ + down(&client->udi_sem); + list_add_tail(&logptr->q, &client->udi_log); + up(&client->udi_sem); + + /* Wake any waiting user process */ + wake_up_interruptible(&client->udi_wq); + + func_exit(); + +} /* sme_native_log_event() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_ta_indicate_protocol + * + * Report that a packet of a particular type has been seen + * + * Arguments: + * drv_priv The device context pointer passed to ta_init. + * protocol The protocol type enum value. + * direction Whether the packet was a tx or rx. + * src_addr The source MAC address from the data packet. + * + * Returns: + * None. + * + * Notes: + * We defer the actual sending to a background workqueue, + * see uf_ta_ind_wq(). + * --------------------------------------------------------------------------- + */ +void +unifi_ta_indicate_protocol(void *ospriv, + CsrWifiRouterCtrlTrafficPacketType packet_type, + CsrWifiRouterCtrlProtocolDirection direction, + const CsrWifiMacAddress *src_addr) +{ + +} /* unifi_ta_indicate_protocol */ + +/* + * --------------------------------------------------------------------------- + * unifi_ta_indicate_sampling + * + * Send the TA sampling information to the SME. + * + * Arguments: + * drv_priv The device context pointer passed to ta_init. + * stats The TA sampling data to send. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats) +{ + +} /* unifi_ta_indicate_sampling() */ + + +void +unifi_ta_indicate_l4stats(void *ospriv, + CsrUint32 rxTcpThroughput, + CsrUint32 txTcpThroughput, + CsrUint32 rxUdpThroughput, + CsrUint32 txUdpThroughput) +{ + +} /* unifi_ta_indicate_l4stats() */ + +/* + * --------------------------------------------------------------------------- + * uf_native_process_udi_signal + * + * Process interesting signals from the UDI interface. + * + * Arguments: + * pcli A pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointers to any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +uf_native_process_udi_signal(ul_client_t *pcli, + const u8 *packed_signal, int packed_signal_len, + const bulk_data_param_t *bulkdata, int dir) +{ + +} /* uf_native_process_udi_signal() */ + + +/* + * --------------------------------------------------------------------------- + * sme_native_mlme_event_handler + * + * Callback function to be used as the udi_event_callback when registering + * as a client. + * This function implements a blocking request-reply interface for WEXT. + * To use it, a client specifies this function as the udi_event_callback + * to ul_register_client(). The signal dispatcher in + * unifi_receive_event() will call this function to deliver a signal. + * + * Arguments: + * pcli Pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointer to structure containing any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +sme_native_mlme_event_handler(ul_client_t *pcli, + const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata, + int dir) +{ + CSR_SIGNAL signal; + int signal_len; + unifi_priv_t *priv = uf_find_instance(pcli->instance); + int id, r; + + func_enter(); + + /* Just a sanity check */ + if ((sig_packed == NULL) || (sig_len <= 0)) { + return; + } + + /* Get the unpacked signal */ + r = read_unpack_signal(sig_packed, &signal); + if (r == 0) { + signal_len = SigGetSize(&signal); + } else { + unifi_error(priv, + "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); + return; + } + + id = signal.SignalPrimitiveHeader.SignalId; + unifi_trace(priv, UDBG4, "wext - Process signal 0x%.4X\n", id); + + /* + * Take the appropriate action for the signal. + */ + switch (id) { + /* + * Confirm replies from UniFi. + * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac) + */ + case CSR_MA_PACKET_CONFIRM_ID: + case CSR_MLME_RESET_CONFIRM_ID: + case CSR_MLME_GET_CONFIRM_ID: + case CSR_MLME_SET_CONFIRM_ID: + case CSR_MLME_GET_NEXT_CONFIRM_ID: + case CSR_MLME_POWERMGT_CONFIRM_ID: + case CSR_MLME_SCAN_CONFIRM_ID: + case CSR_MLME_HL_SYNC_CONFIRM_ID: + case CSR_MLME_MEASURE_CONFIRM_ID: + case CSR_MLME_SETKEYS_CONFIRM_ID: + case CSR_MLME_DELETEKEYS_CONFIRM_ID: + case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: + case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: + case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: + case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: + case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: + case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: + case CSR_MLME_STOP_MEASURE_CONFIRM_ID: + case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: + case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: + case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: + case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: + case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: + case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: + case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: + case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: + case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: + case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: + case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: + case CSR_MLME_ADD_TSPEC_CONFIRM_ID: + case CSR_MLME_DEL_TSPEC_CONFIRM_ID: + case CSR_MLME_START_AGGREGATION_CONFIRM_ID: + case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: + case CSR_MLME_SM_START_CONFIRM_ID: + case CSR_MLME_LEAVE_CONFIRM_ID: + case CSR_MLME_SET_TIM_CONFIRM_ID: + case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: + case CSR_MLME_SET_CHANNEL_CONFIRM_ID: + case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: + case CSR_DEBUG_GENERIC_CONFIRM_ID: + unifi_mlme_copy_reply_and_wakeup_client(pcli, &signal, signal_len, bulkdata); + break; + + case CSR_MLME_CONNECTED_INDICATION_ID: + /* We currently ignore the connected-ind for softmac f/w development */ + unifi_info(priv, "CSR_MLME_CONNECTED_INDICATION_ID ignored\n"); + break; + + default: + break; + } + + func_exit(); +} /* sme_native_mlme_event_handler() */ + + + +/* + * ------------------------------------------------------------------------- + * unifi_reset_state + * + * Ensure that a MAC address has been set. + * Send the MLME-RESET signal. + * This must be called at least once before starting to do any + * network activities (e.g. scan, join etc). + * + * Arguments: + * priv Pointer to device private context struct + * macaddr Pointer to chip MAC address. + * If this is FF:FF:FF:FF:FF:FF it will be replaced + * with the MAC address from the chip. + * set_default_mib 1 if the f/w must reset the MIB to the default values + * 0 otherwise + * + * Returns: + * 0 on success, an error code otherwise. + * ------------------------------------------------------------------------- + */ +int +unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr, + unsigned char set_default_mib) +{ + int r = 0; + + func_enter(); + +#ifdef CSR_SUPPORT_WEXT + /* The reset clears any 802.11 association. */ + priv->wext_conf.flag_associated = 0; +#endif + + func_exit(); + return r; +} /* unifi_reset_state() */ + diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c new file mode 100644 index 000000000000..f5760444bfea --- /dev/null +++ b/drivers/staging/csr/sme_sys.c @@ -0,0 +1,2950 @@ +/* + * --------------------------------------------------------------------------- + * FILE: sme_sys.c + * + * PURPOSE: + * Driver specific implementation of the SME SYS SAP. + * It is part of the porting exercise. + * + * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + +#include "csr_wifi_hip_unifiversion.h" +#include "unifi_priv.h" +#include "csr_wifi_hip_conversions.h" +#ifdef CSR_SUPPORT_WEXT_AP +#include "sme_csr/csr_wifi_sme_sef.h" +#endif +/* + * This file implements the SME SYS API and contains the following functions: + * CsrWifiRouterCtrlMediaStatusReqHandler() + * CsrWifiRouterCtrlHipReqHandler() + * CsrWifiRouterCtrlPortConfigureReqHandler() + * CsrWifiRouterCtrlWifiOnReqHandler() + * CsrWifiRouterCtrlWifiOffReqHandler() + * CsrWifiRouterCtrlSuspendResHandler() + * CsrWifiRouterCtrlResumeResHandler() + * CsrWifiRouterCtrlQosControlReqHandler() + * CsrWifiRouterCtrlConfigurePowerModeReqHandler() + * CsrWifiRouterCtrlWifiOnResHandler() + * CsrWifiRouterCtrlWifiOffRspHandler() + * CsrWifiRouterCtrlMulticastAddressResHandler() + * CsrWifiRouterCtrlTrafficConfigReqHandler() + * CsrWifiRouterCtrlTrafficClassificationReqHandler() + * CsrWifiRouterCtrlTclasAddReqHandler() + * CsrWifiRouterCtrlTclasDelReqHandler() + * CsrWifiRouterCtrlSetModeReqHandler() + * CsrWifiRouterCtrlWapiMulticastFilterReqHandler() + * CsrWifiRouterCtrlWapiMulticastReqHandler() + * CsrWifiRouterCtrlWapiUnicastFilterReqHandler() + */ + +#ifdef CSR_SUPPORT_SME +static void check_inactivity_timer_expire_func(unsigned long data); +void uf_send_disconnected_ind_wq(struct work_struct *work); +#endif + +void send_auto_ma_packet_confirm(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + struct list_head *buffered_frames_list) +{ + tx_buffered_packets_t *buffered_frame_item = NULL; + struct list_head *listHead; + struct list_head *placeHolder; + int client_id; + + CSR_SIGNAL unpacked_signal; + CsrUint8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; + CsrUint16 packed_siglen; + + + list_for_each_safe(listHead, placeHolder, buffered_frames_list) + { + buffered_frame_item = list_entry(listHead, tx_buffered_packets_t, q); + + if(!buffered_frame_item) { + unifi_error(priv, "Entry should exist, otherwise it is a (BUG)\n"); + continue; + } + + if ((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_NONE) && + (priv->wifi_on_state == wifi_on_done)) + { + + unifi_warning(priv, "Send MA_PACKET_CONFIRM to SenderProcessId = %x for (HostTag = %x TransmissionControl = %x)\n", + (buffered_frame_item->leSenderProcessId), + buffered_frame_item->hostTag, + buffered_frame_item->transmissionControl); + + client_id = buffered_frame_item->leSenderProcessId & 0xFF00; + + if (client_id == priv->sme_cli->sender_id) + { + /* construct a MA-PACKET.confirm message for SME */ + memset(&unpacked_signal, 0, sizeof(unpacked_signal)); + unpacked_signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_CONFIRM_ID; + unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId = buffered_frame_item->leSenderProcessId; + unpacked_signal.SignalPrimitiveHeader.SenderProcessId = CSR_WIFI_ROUTER_IFACEQUEUE; + + unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, + interfacePriv->InterfaceTag); + unpacked_signal.u.MaPacketConfirm.TransmissionStatus = CSR_RESULT_FAILURE; + unpacked_signal.u.MaPacketConfirm.RetryCount = 0; + unpacked_signal.u.MaPacketConfirm.Rate = buffered_frame_item->rate; + unpacked_signal.u.MaPacketConfirm.HostTag = buffered_frame_item->hostTag; + + write_pack(&unpacked_signal, sigbuf, &packed_siglen); + unifi_warning(priv, "MA_PACKET_CONFIRM for SME (0x%x, 0x%x, 0x%x, 0x%x)\n", + unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId, + unpacked_signal.SignalPrimitiveHeader.SenderProcessId, + unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier, + unpacked_signal.u.MaPacketConfirm.HostTag); + + CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, + packed_siglen, + (CsrUint8 *)sigbuf, + 0, NULL, + 0, NULL); + } + else if((buffered_frame_item->hostTag & 0x80000000)) + { + /* construct a MA-PACKET.confirm message for NME */ + unifi_warning(priv, "MA_PACKET_CONFIRM for NME (0x%x, 0x%x, 0x%x, 0x%x)\n", + buffered_frame_item->leSenderProcessId, + buffered_frame_item->interfaceTag, + buffered_frame_item->transmissionControl, + (buffered_frame_item->hostTag & 0x3FFFFFFF)); + + CsrWifiRouterMaPacketCfmSend((buffered_frame_item->leSenderProcessId & 0xFF), + buffered_frame_item->interfaceTag, + CSR_RESULT_FAILURE, + (buffered_frame_item->hostTag & 0x3FFFFFFF), + buffered_frame_item->rate); + + } + else + { + unifi_warning(priv, "Buffered packet dropped without sending a confirm\n"); + } + + } + + list_del(listHead); + kfree(buffered_frame_item); + buffered_frame_item = NULL; + } +} + +void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlMediaStatusReq* req = (CsrWifiRouterCtrlMediaStatusReq*)msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + unsigned long flags; + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid smepriv\n"); + return; + } + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid interfaceTag\n"); + return; + } + unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlMediaStatusReqHandler: Mode = %d req->mediaStatus = %d\n",interfacePriv->interfaceMode,req->mediaStatus); + if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AMP) { + bulk_data_desc_t bulk_data; + + bulk_data.data_length = 0; + + spin_lock_irqsave(&priv->m4_lock, flags); + if (interfacePriv->m4_bulk_data.data_length > 0) { + bulk_data = interfacePriv->m4_bulk_data; + interfacePriv->m4_bulk_data.net_buf_length = 0; + interfacePriv->m4_bulk_data.data_length = 0; + interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; + } + spin_unlock_irqrestore(&priv->m4_lock, flags); + + if (bulk_data.data_length != 0) { + unifi_trace(priv, UDBG5, "CsrWifiRouterCtrlMediaStatusReqHandler: free M4\n"); + unifi_net_data_free(priv, &bulk_data); + } + + if ((req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) && + (interfacePriv->connected != UnifiConnected)) { + + switch(interfacePriv->interfaceMode){ + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + interfacePriv->connected = UnifiConnected; + netif_carrier_on(priv->netdev[req->interfaceTag]); +#ifdef CSR_SUPPORT_WEXT + wext_send_started_event(priv); +#endif + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlMediaStatusReqHandler: AP/P2PGO setting netif_carrier_on\n"); + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[req->interfaceTag]); + break; + + default: +#ifdef CSR_SUPPORT_WEXT + /* In the WEXT builds (sme and native), the userspace is not ready + * to process any EAPOL or WAPI packets, until it has been informed + * of the NETDEV_CHANGE. + */ + if (interfacePriv->netdev_callback_registered && (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI)) { + interfacePriv->wait_netdev_change = TRUE; + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlMediaStatusReqHandler: waiting for NETDEV_CHANGE\n"); + /* + * Carrier can go to on, only after wait_netdev_change is set to TRUE. + * Otherwise there can be a race in uf_netdev_event(). + */ + netif_carrier_on(priv->netdev[req->interfaceTag]); + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlMediaStatusReqHandler: STA/P2PCLI setting netif_carrier_on\n"); + } + else +#endif + { + /* In the NME build, the userspace does not wait for the NETDEV_CHANGE + * so it is ready to process all the EAPOL or WAPI packets. + * At this point, we enable all the Tx queues, and we indicate any packets + * that are queued (and the respective port is opened). + */ + static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + interfacePriv->connected = UnifiConnected; + unifi_trace(priv, UDBG1, + "CsrWifiRouterMediaStatusReqHandler: UnifiConnected && netif_carrier_on\n"); + netif_carrier_on(priv->netdev[req->interfaceTag]); + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[req->interfaceTag]); + uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); + uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); + } + break; + } + } + + if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED) { +#ifdef CSR_SUPPORT_WEXT + unifi_trace(priv, UDBG1, + "CsrWifiRouterMediaStatusReqHandler: cancel waiting for NETDEV_CHANGE\n"); + interfacePriv->wait_netdev_change = FALSE; +#endif + unifi_trace(priv, UDBG1, + "CsrWifiRouterMediaStatusReqHandler: setting netif_carrier_off\n"); + netif_carrier_off(priv->netdev[req->interfaceTag]); +#ifdef CSR_SUPPORT_WEXT + switch(interfacePriv->interfaceMode){ + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + wext_send_started_event(priv); + break; + default: + break; + } +#endif + interfacePriv->connected = UnifiNotConnected; + } + } else { + /* For AMP, just update the L2 connected flag */ + if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) { + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP connected\n"); + interfacePriv->connected = UnifiConnected; + } else { + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP disconnected\n"); + interfacePriv->connected = UnifiNotConnected; + } + } +} + + +void CsrWifiRouterCtrlHipReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlHipReq* hipreq = (CsrWifiRouterCtrlHipReq*)msg; + bulk_data_param_t bulkdata; + u8 *signal_ptr; + int signal_length; + int r=0; + void *dest; + CsrResult csrResult; + CSR_SIGNAL *signal; + CsrUint16 interfaceTag = 0; + CSR_MA_PACKET_REQUEST *req; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (priv == NULL) { + return; + } + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid smepriv\n"); + return; + } + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid interfaceTag\n"); + return; + } + + /* Initialize bulkdata to avoid os_net_buf is garbage */ + memset(&bulkdata, 0, sizeof(bulk_data_param_t)); + + signal = (CSR_SIGNAL *)hipreq->mlmeCommand; + + unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: 0x04%X ---->\n", + *((CsrUint16*)hipreq->mlmeCommand)); + + /* Construct the signal. */ + signal_ptr = (u8*)hipreq->mlmeCommand; + signal_length = hipreq->mlmeCommandLength; + + /* + * The MSB of the sender ID needs to be set to the client ID. + * The LSB is controlled by the SME. + */ + signal_ptr[5] = (priv->sme_cli->sender_id >> 8) & 0xff; + + /* Allocate buffers for the bulk data. */ + if (hipreq->dataRef1Length) { + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], hipreq->dataRef1Length); + if (csrResult == CSR_RESULT_SUCCESS) { + dest = (void*)bulkdata.d[0].os_data_ptr; + memcpy(dest, hipreq->dataRef1, hipreq->dataRef1Length); + bulkdata.d[0].data_length = hipreq->dataRef1Length; + } else { + unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); + return; + } + } else { + bulkdata.d[0].os_data_ptr = NULL; + bulkdata.d[0].data_length = 0; + } + if (hipreq->dataRef2Length) { + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[1], hipreq->dataRef2Length); + if (csrResult == CSR_RESULT_SUCCESS) { + dest = (void*)bulkdata.d[1].os_data_ptr; + memcpy(dest, hipreq->dataRef2, hipreq->dataRef2Length); + bulkdata.d[1].data_length = hipreq->dataRef2Length; + } else { + if (bulkdata.d[0].data_length) + { + unifi_net_data_free(priv, &bulkdata.d[0]); + } + unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); + return; + } + } else { + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].data_length = 0; + } + + unifi_trace(priv, UDBG3, "SME SEND: Signal 0x%.4X \n", + *((CsrUint16*)signal_ptr)); + if (signal->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) + { + CSR_SIGNAL unpacked_signal; + read_unpack_signal((u8 *) signal, &unpacked_signal); + req = &unpacked_signal.u.MaPacketRequest; + interfaceTag = req->VirtualInterfaceIdentifier & 0xff; + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_NONE: + unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid mode: NONE \n"); + break; + default: + unifi_trace(priv, UDBG5, "mode is %x\n", interfacePriv->interfaceMode); + } + /* While sending ensure that first 2 bits b31 and b30 are 00. These are used for local routing*/ + r = uf_process_ma_packet_req(priv, req->Ra.x, (req->HostTag & 0x3FFFFFFF), interfaceTag, + req->TransmissionControl, req->TransmitRate, + req->Priority, signal->SignalPrimitiveHeader.SenderProcessId, + &bulkdata); + if (r) + { + if (bulkdata.d[0].data_length) + { + unifi_net_data_free(priv, &bulkdata.d[0]); + } + if (bulkdata.d[1].data_length) + { + unifi_net_data_free(priv, &bulkdata.d[1]); + } + } + } else { + /* ul_send_signal_raw frees the bulk data if it fails */ + r = ul_send_signal_raw(priv, signal_ptr, signal_length, &bulkdata); + } + + if (r) { + unifi_error(priv, + "CsrWifiRouterCtrlHipReqHandler: Failed to send signal (0x%.4X - %u)\n", + *((CsrUint16*)signal_ptr), r); + CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,CSR_WIFI_SME_CONTROL_INDICATION_ERROR); + } + + unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: <----\n"); +} + +#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP +static void +uf_send_gratuitous_arp(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CSR_PRIORITY priority; + CSR_SIGNAL signal; + bulk_data_param_t bulkdata; + CsrResult csrResult; + struct sk_buff *skb, *newSkb = NULL; + CsrInt8 protection; + int r; + static const CsrUint8 arp_req[36] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, + 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x02, 0x5f, 0x20, 0x2f, 0x02, + 0xc0, 0xa8, 0x00, 0x02, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xa8, 0x00, 0x02}; + + func_enter(); + + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], sizeof(arp_req)); + if (csrResult != CSR_RESULT_SUCCESS) + { + unifi_error(priv, "Failed to allocate bulk data in CsrWifiSmeRoamCompleteIndHandler()\n"); + return; + } + skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); + skb->len = bulkdata.d[0].data_length; + + memcpy(skb->data, arp_req, sizeof(arp_req)); + /* add MAC and IP address */ + memcpy(skb->data + 16, priv->netdev[interfaceTag]->dev_addr, ETH_ALEN); + skb->data[22] = (priv->sta_ip_address ) & 0xFF; + skb->data[23] = (priv->sta_ip_address >> 8) & 0xFF; + skb->data[24] = (priv->sta_ip_address >> 16) & 0xFF; + skb->data[25] = (priv->sta_ip_address >> 24) & 0xFF; + skb->data[32] = (priv->sta_ip_address ) & 0xFF; + skb->data[33] = (priv->sta_ip_address >> 8) & 0xFF; + skb->data[34] = (priv->sta_ip_address >> 16) & 0xFF; + skb->data[35] = (priv->sta_ip_address >> 24) & 0xFF; + + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; + + if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, &arp_req[26])) < 0) + { + unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: Failed to determine protection mode\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return; + } + + if ((priv->sta_wmm_capabilities & QOS_CAPABILITY_WMM_ENABLED) == 1) + { + priority = CSR_QOS_UP0; + } + else + { + priority = CSR_CONTENTION; + } + + if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, + interfaceTag, &arp_req[26], + priv->netdev[interfaceTag]->dev_addr, protection)) + { + unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to create MAC header\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return; + } + bulkdata.d[0].os_data_ptr = skb->data; + bulkdata.d[0].os_net_buf_ptr = skb; + bulkdata.d[0].data_length = skb->len; + + unifi_frame_ma_packet_req(priv, priority, 0, 0xffffffff, interfaceTag, + CSR_NO_CONFIRM_REQUIRED, priv->netdev_client->sender_id, + interfacePriv->bssid.a, &signal); + + r = ul_send_signal_unpacked(priv, &signal, &bulkdata); + if (r) + { + unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to send QOS data null packet result: %d\n",r); + unifi_net_data_free(priv, &bulkdata.d[0]); + return; + } + + func_exit(); + +} +#endif /* CSR_WIFI_SEND_GRATUITOUS_ARP */ + +/* + * --------------------------------------------------------------------------- + * configure_data_port + * + * Store the new controlled port configuration. + * + * Arguments: + * priv Pointer to device private context struct + * port_cfg Pointer to the port configuration + * + * Returns: + * An unifi_ControlledPortAction value. + * --------------------------------------------------------------------------- + */ +static int +configure_data_port(unifi_priv_t *priv, + CsrWifiRouterCtrlPortAction port_action, + const CsrWifiMacAddress *macAddress, + const int queue, + CsrUint16 interfaceTag) +{ + const CsrUint8 broadcast_mac_address[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + unifi_port_config_t *port; + netInterface_priv_t *interfacePriv; + int i; + const char* controlled_string; /* cosmetic "controlled"/"uncontrolled" for trace */ + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "configure_data_port: bad interfaceTag\n"); + return -EFAULT; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + if (queue == UF_CONTROLLED_PORT_Q) { + port = &interfacePriv->controlled_data_port; + controlled_string = "controlled"; + } else { + port = &interfacePriv->uncontrolled_data_port; + controlled_string = "uncontrolled"; + } + + unifi_trace(priv, UDBG2, "port config request %02x:%02x:%02x:%02x:%02x:%02x %s with port_action %d.\n", + macAddress->a[0], macAddress->a[1], macAddress->a[2], + macAddress->a[3], macAddress->a[4], macAddress->a[5], + controlled_string, port_action); + + + /* If the new configuration has the broadcast MAC address or if we are in infrastructure mode then clear the list first and set port overide mode */ + if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) || + !memcmp(macAddress->a, broadcast_mac_address, ETH_ALEN)) { + + port->port_cfg[0].port_action = port_action; + port->port_cfg[0].mac_address = *macAddress; + port->port_cfg[0].in_use = TRUE; + port->entries_in_use = 1; + port->overide_action = UF_DATA_PORT_OVERIDE; + + unifi_trace(priv, UDBG2, "%s port override on\n", + (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); + + /* Discard the remaining entries in the port config table */ + for (i = 1; i < UNIFI_MAX_CONNECTIONS; i++) { + port->port_cfg[i].in_use = FALSE; + } + + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + unifi_trace(priv, UDBG1, "%s port broadcast set to open.\n", + (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); + + /* + * Ask stack to schedule for transmission any packets queued + * while controlled port was not open. + * Use netif_schedule() instead of netif_wake_queue() because + * transmission should be already enabled at this point. If it + * is not, probably the interface is down and should remain as is. + */ + uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); + +#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP + if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && + (queue == UF_CONTROLLED_PORT_Q) && (priv->sta_ip_address != 0xFFFFFFFF)) + { + uf_send_gratuitous_arp(priv, interfaceTag); + } +#endif + } else { + unifi_trace(priv, UDBG1, "%s port broadcast set to %s.\n", + (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled", + (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) ? "discard": "closed"); + + /* If port is closed, discard all the pending Rx packets */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { + uf_free_pending_rx_packets(priv, queue, *macAddress,interfaceTag); + } + } + } else { + /* store the new configuration, either in the entry with matching mac address (if already present), + * otherwise in a new entry + */ + + int found_entry_flag; + int first_free_slot = -1; + + /* If leaving override mode, free the port entry used for override */ + if (port->overide_action == UF_DATA_PORT_OVERIDE) { + port->port_cfg[0].in_use = FALSE; + port->entries_in_use = 0; + port->overide_action = UF_DATA_PORT_NOT_OVERIDE; + + unifi_trace(priv, UDBG2, "%s port override off\n", + (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); + } + + found_entry_flag = 0; + for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + if (port->port_cfg[i].in_use) { + if (!memcmp(&port->port_cfg[i].mac_address.a, macAddress->a, ETH_ALEN)) { + /* We've seen this address before, reconfigure it */ + port->port_cfg[i].port_action = port_action; + found_entry_flag = 1; + break; + } + } else if (first_free_slot == -1) { + /* Remember the first free slot on the way past so it can be claimed + * if this turns out to be a new MAC address (to save walking the list again). + */ + first_free_slot = i; + } + } + + /* At this point we found an existing entry and have updated it, or need to + * add a new entry. If all slots are allocated, give up and return an error. + */ + if (!found_entry_flag) { + if (first_free_slot == -1) { + unifi_error(priv, "no free slot found in port config array (%d used)\n", port->entries_in_use); + return -EFAULT; + } else { + port->entries_in_use++; + } + + unifi_trace(priv, UDBG3, "port config index assigned in config_data_port = %d\n", first_free_slot); + port->port_cfg[first_free_slot].in_use = TRUE; + port->port_cfg[first_free_slot].port_action = port_action; + port->port_cfg[first_free_slot].mac_address = *macAddress; + } + + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + /* + * Ask stack to schedule for transmission any packets queued + * while controlled port was not open. + * Use netif_schedule() instead of netif_wake_queue() because + * transmission should be already enabled at this point. If it + * is not, probably the interface is down and should remain as is. + */ + uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); + } + + /* + * If port is closed, discard all the pending Rx packets + * coming from the peer station. + */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { + uf_free_pending_rx_packets(priv, queue, *macAddress,interfaceTag); + } + + unifi_trace(priv, UDBG2, "port config %02x:%02x:%02x:%02x:%02x:%02x with port_action %d.\n", + *(macAddress->a+0), *(macAddress->a+1), *(macAddress->a+2), + *(macAddress->a+3), *(macAddress->a+4), *(macAddress->a+5), + port_action); + } + return 0; +} /* configure_data_port() */ + + +void CsrWifiRouterCtrlPortConfigureReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlPortConfigureReq* req = (CsrWifiRouterCtrlPortConfigureReq*)msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + + unifi_trace(priv, UDBG3, "entering CsrWifiRouterCtrlPortConfigureReqHandler\n"); + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlPortConfigureReqHandler: invalid smepriv\n"); + return; + } + + /* To update the protection status of the peer/station */ + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_AMP: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + /* Since for Unifi as a station, the station record not maintained & interfaceID is + * only needed to update the peer protection status + */ + interfacePriv->protect = req->setProtection; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + { + CsrUint8 i; + CsrWifiRouterCtrlStaInfo_t *staRecord; + /* Ifscontrolled port is open means, The peer has been added to station record + * so that the protection corresponding to the peer is valid in this req + */ + if (req->controlledPortAction == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { + staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); + if (staRecord) { + /* Find the matching station record & set the protection type */ + if (!memcmp(req->macAddress.a, staRecord->peerMacAddress.a, ETH_ALEN)) { + staRecord->protection = req->setProtection; + break; + } + } + } + } + } + break; + default: + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlPortConfigureReqHandler(0x%.4X) Uncaught mode %d\n", + msg->source, interfacePriv->interfaceMode); + } + + configure_data_port(priv, req->uncontrolledPortAction, (const CsrWifiMacAddress *)&req->macAddress, + UF_UNCONTROLLED_PORT_Q, req->interfaceTag); + configure_data_port(priv, req->controlledPortAction, (const CsrWifiMacAddress *)&req->macAddress, + UF_CONTROLLED_PORT_Q, req->interfaceTag); + + CsrWifiRouterCtrlPortConfigureCfmSend(msg->source,req->clientData,req->interfaceTag, + CSR_RESULT_SUCCESS, req->macAddress); + unifi_trace(priv, UDBG3, "leaving CsrWifiRouterCtrlPortConfigureReqHandler\n"); +} + + +void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlVersions versions; + CsrWifiRouterCtrlWifiOnReq* req = (CsrWifiRouterCtrlWifiOnReq*)msg; + int r,i; + CsrResult csrResult; + + if (priv == NULL) { + return; + } + for (i=0; iinterfacePriv[i]->interfaceMode = 0; + } + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X)\n", msg->source); + + /* + * The request to initialise UniFi might come while UniFi is running. + * We need to block all I/O activity until the reset completes, otherwise + * an SDIO error might occur resulting an indication to the SME which + * makes it think that the initialisation has failed. + */ + priv->bh_thread.block_thread = 1; + + /* Update the wifi_on state */ + priv->wifi_on_state = wifi_on_in_progress; + + r = uf_request_firmware_files(priv, UNIFI_FW_STA); + if (r) { + unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n"); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); + return; + } + + /* Power on UniFi (which may not necessarily have been off) */ + CsrSdioClaim(priv->sdio); + csrResult = CsrSdioPowerOn(priv->sdio); + CsrSdioRelease(priv->sdio); + if (csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) { + unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to power on UniFi\n"); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); + return; + } + + /* If CsrSdioPowerOn() returns CSR_RESULT_SUCCESS, it means that we need to initialise UniFi */ + if (csrResult == CSR_RESULT_SUCCESS && !priv->wol_suspend) { + /* Initialise UniFi hardware */ + r = uf_init_hw(priv); + if (r) { + unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); + return; + } + } else { + unifi_trace(priv, UDBG1, "UniFi already initialised\n"); + } + + /* Completed handling of wake up from suspend with UniFi powered */ + priv->wol_suspend = FALSE; + + /* Re-enable the I/O thread */ + priv->bh_thread.block_thread = 0; + + /* + * Start the I/O thread. The thread might be already running. + * This fine, just carry on with the request. + */ + r = uf_init_bh(priv); + if (r) { + CsrSdioClaim(priv->sdio); + CsrSdioPowerOff(priv->sdio); + CsrSdioRelease(priv->sdio); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); + return; + } + + /* Get the version information from the core */ + unifi_card_info(priv->card, &priv->card_info); + + /* Set the sme queue id */ + priv->CSR_WIFI_SME_IFACEQUEUE = msg->source; + CSR_WIFI_SME_IFACEQUEUE = msg->source; + + + /* Copy to the unifiio_card_info structure. */ + versions.chipId = priv->card_info.chip_id; + versions.chipVersion = priv->card_info.chip_version; + versions.firmwareBuild = priv->card_info.fw_build; + versions.firmwareHip = priv->card_info.fw_hip_version; + versions.routerBuild = (CsrCharString*)CSR_WIFI_VERSION; + versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; + + CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); + + /* Update the wifi_on state */ + priv->wifi_on_state = wifi_on_done; +} + + +/* + * wifi_off: + * Common code for CsrWifiRouterCtrlWifiOffReqHandler() and + * CsrWifiRouterCtrlWifiOffRspHandler(). + */ +static void +wifi_off(unifi_priv_t *priv) +{ + int power_off; + int priv_instance; + int i; + CsrResult csrResult; + + unifi_trace(priv, UDBG1, "wifi_off\n"); + + /* Destroy the Traffic Analysis Module */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + cancel_work_sync(&priv->ta_ind_work.task); + cancel_work_sync(&priv->ta_sample_ind_work.task); +#ifdef CSR_SUPPORT_WEXT + cancel_work_sync(&priv->sme_config_task); +#endif + + /* Cancel pending M4 stuff */ + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + if (priv->netdev[i]) { + netInterface_priv_t *netpriv = (netInterface_priv_t *) netdev_priv(priv->netdev[i]); + cancel_work_sync(&netpriv->send_m4_ready_task); + } + } +#endif + flush_workqueue(priv->unifi_workqueue); + + /* fw_init parameter can prevent power off UniFi, for debugging */ + priv_instance = uf_find_priv(priv); + if (priv_instance == -1) { + unifi_warning(priv, + "CsrWifiRouterCtrlStopReqHandler: Unknown priv instance, will power off card.\n"); + power_off = 1; + } else { + power_off = (fw_init[priv_instance] > 0) ? 0 : 1; + } + + /* Production test mode requires power to the chip, too */ + if (priv->ptest_mode) { + power_off = 0; + } + + /* Stop the bh_thread */ + uf_stop_thread(priv, &priv->bh_thread); + + /* Read the f/w panic codes, if any. Protect against second wifi_off() call, + * which may happen if SME requests a wifi_off and closes the char device */ + if (priv->init_progress != UNIFI_INIT_NONE) { + CsrSdioClaim(priv->sdio); + unifi_capture_panic(priv->card); + CsrSdioRelease(priv->sdio); + } + + /* Unregister the interrupt handler */ + if (csr_sdio_linux_remove_irq(priv->sdio)) { + unifi_notice(priv, + "csr_sdio_linux_remove_irq failed to talk to card.\n"); + } + + if (power_off) { + unifi_trace(priv, UDBG2, + "Force low power and try to power off\n"); + /* Put UniFi to deep sleep, in case we can not power it off */ + CsrSdioClaim(priv->sdio); + csrResult = unifi_force_low_power_mode(priv->card); + CsrSdioRelease(priv->sdio); + + CsrSdioPowerOff(priv->sdio); + } + + /* Consider UniFi to be uninitialised */ + priv->init_progress = UNIFI_INIT_NONE; + priv->wifi_on_state = wifi_on_unspecified; + + +} /* wifi_off() */ + + +void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg; + int i = 0; +#ifdef CSR_SUPPORT_WEXT_AP + CsrWifiSmeWifiOffCfm cfm; +#endif + + if (priv == NULL) { + return; + } + + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOffReqHandler(0x%.4X)\n", msg->source); + + /* Stop the network traffic on all interfaces before freeing the core. */ + for (i=0; iinterfacePriv[i]; + if (interfacePriv->netdev_registered == 1) { + netif_carrier_off(priv->netdev[i]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); + } + interfacePriv->interfaceMode = 0; + + /* Enable all queues by default */ + interfacePriv->queueEnabled[0] = 1; + interfacePriv->queueEnabled[1] = 1; + interfacePriv->queueEnabled[2] = 1; + interfacePriv->queueEnabled[3] = 1; + } + wifi_off(priv); + + CsrWifiRouterCtrlWifiOffCfmSend(msg->source,req->clientData); +#ifdef CSR_SUPPORT_WEXT_AP + /* Router is turned off when WifiOffCfm is received + * hence for wext we don't see WifiOffCfm in the wext + * files. So just tell the waiting process that + * Wifi off is successful + */ + cfm.status = CSR_RESULT_SUCCESS; + CsrWifiSmeWifiOffCfmHandler(priv,(CsrWifiFsmEvent*)(&cfm)); +#endif +} + + +void CsrWifiRouterCtrlQosControlReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlQosControlReq* req = (CsrWifiRouterCtrlQosControlReq*)msg; + netInterface_priv_t *interfacePriv; + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: invalid smepriv\n"); + return; + } + + unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlQosControlReqHandler:scontrol = %d", req->control); + + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); + return; + } + interfacePriv = priv->interfacePriv[req->interfaceTag]; + + if (req->control == CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON) { + priv->sta_wmm_capabilities |= QOS_CAPABILITY_WMM_ENABLED; + unifi_trace(priv, UDBG1, "WMM enabled\n"); + + unifi_trace(priv, UDBG1, "Queue Config %x\n", req->queueConfig); + + interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BK] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE)?1:0; + interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BE] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE)?1:0; + interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VI] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE)?1:0; + interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VO] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE)?1:0; + + } else { + priv->sta_wmm_capabilities = 0; + unifi_trace(priv, UDBG1, "WMM disabled\n"); + } +} + + +void CsrWifiRouterCtrlTclasAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlTclasAddReq* req = (CsrWifiRouterCtrlTclasAddReq*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlTclasAddReqHandler: invalid smepriv\n"); + return; + } + + CsrWifiRouterCtrlTclasAddCfmSend(msg->source, req->clientData, req->interfaceTag , CSR_RESULT_SUCCESS); +} + +void CsrWifiRouterCtrlTclasDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlTclasDelReq* req = (CsrWifiRouterCtrlTclasDelReq*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlTclasDelReqHandler: invalid smepriv\n"); + return; + } + + CsrWifiRouterCtrlTclasDelCfmSend(msg->source, req->clientData, req->interfaceTag, CSR_RESULT_SUCCESS); +} + + +void CsrWifiRouterCtrlConfigurePowerModeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlConfigurePowerModeReq* req = (CsrWifiRouterCtrlConfigurePowerModeReq*)msg; + enum unifi_low_power_mode pm; + CsrResult csrResult; + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlConfigurePowerModeReqHandler: invalid smepriv\n"); + return; + } + + if (req->mode == CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED) { + pm = UNIFI_LOW_POWER_DISABLED; + } else { + pm = UNIFI_LOW_POWER_ENABLED; + } + + unifi_trace(priv, UDBG2, + "CsrWifiRouterCtrlConfigurePowerModeReqHandler (mode=%d, wake=%d)\n", + req->mode, req->wakeHost); + csrResult = unifi_configure_low_power_mode(priv->card, pm, + (req->wakeHost ? UNIFI_PERIODIC_WAKE_HOST_ENABLED : UNIFI_PERIODIC_WAKE_HOST_DISABLED)); +} + + +void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWifiOnRes* res = (CsrWifiRouterCtrlWifiOnRes*)msg; + + if (priv == NULL) { + unifi_error(NULL, "CsrWifiRouterCtrlWifiOnResHandler: Invalid ospriv.\n"); + return; + } + + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlWifiOnResHandler: status %d (patch %u)\n", res->status, res->smeVersions.firmwarePatch); + + if (res->smeVersions.firmwarePatch != 0) { + unifi_info(priv, "Firmware patch %d\n", res->smeVersions.firmwarePatch); + } + + if (res->numInterfaceAddress > CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "WifiOnResHandler bad numInterfaceAddress %d\n", res->numInterfaceAddress); + return; + } + + /* UniFi is now initialised, complete the init. */ + if (res->status == CSR_RESULT_SUCCESS) + { + int i; /* used as a loop counter */ + CsrUint32 intmode = CSR_WIFI_INTMODE_DEFAULT; + + /* Register the UniFi device with the OS network manager */ + unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n"); + + /* Store the MAC address in the netdev */ + for(i=0;inumInterfaceAddress;i++) + { + memcpy(priv->netdev[i]->dev_addr, res->stationMacAddress[i].a, ETH_ALEN); + } + + /* Copy version structure into the private versions field */ + priv->sme_versions = res->smeVersions; + + unifi_trace(priv, UDBG2, "network interfaces count = %d\n", + res->numInterfaceAddress); + + /* Register the netdevs for each interface. */ + for(i=0;inumInterfaceAddress;i++) + { + netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; + if(!interfacePriv->netdev_registered) + { + int r; + unifi_trace(priv, UDBG3, "registering net device %d\n", i); + r = uf_register_netdev(priv, i); + if (r) + { + /* unregister the net_device that are registered in the previous iterations */ + uf_unregister_netdev(priv); + unifi_error(priv, "Failed to register the network device.\n"); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); + return; + } + } + } + priv->totalInterfaceCount = res->numInterfaceAddress; + + /* If the MIB has selected f/w scheduled interrupt mode, apply it now + * but let module param override. + */ + if (run_bh_once != -1) { + intmode = (CsrUint32)run_bh_once; + } else if (res->scheduledInterrupt) { + intmode = CSR_WIFI_INTMODE_RUN_BH_ONCE; + } + unifi_set_interrupt_mode(priv->card, intmode); + + priv->init_progress = UNIFI_INIT_COMPLETED; + + /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS); + + unifi_info(priv, "UniFi ready\n"); + + /* Firmware initialisation is complete, so let the SDIO bus + * clock be raised when convienent to the core. + */ + unifi_request_max_sdio_clock(priv->card); + +#ifdef CSR_SUPPORT_WEXT + /* Notify the Android wpa_supplicant that we are ready */ + wext_send_started_event(priv); + + queue_work(priv->unifi_workqueue, &priv->sme_config_task); +#endif + + } else { + /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); + } +} + + +void CsrWifiRouterCtrlWifiOffResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + + +void CsrWifiRouterCtrlMulticastAddressResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + + +void CsrWifiRouterMaPacketSubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterMaPacketSubscribeReq* req = (CsrWifiRouterMaPacketSubscribeReq*)msg; + CsrUint8 i; + CsrResult result; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterMaPacketSubscribeReqHandler: invalid priv\n"); + return; + } + + /* Look for an unused filter */ + + result = CSR_WIFI_RESULT_NO_ROOM; + for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { + + if (!priv->sme_unidata_ind_filters[i].in_use) { + + priv->sme_unidata_ind_filters[i].in_use = 1; + priv->sme_unidata_ind_filters[i].appHandle = msg->source; + priv->sme_unidata_ind_filters[i].encapsulation = req->encapsulation; + priv->sme_unidata_ind_filters[i].protocol = req->protocol; + + priv->sme_unidata_ind_filters[i].oui[2] = (CsrUint8) (req->oui & 0xFF); + priv->sme_unidata_ind_filters[i].oui[1] = (CsrUint8) ((req->oui >> 8) & 0xFF); + priv->sme_unidata_ind_filters[i].oui[0] = (CsrUint8) ((req->oui >> 16) & 0xFF); + + result = CSR_RESULT_SUCCESS; + break; + } + } + + unifi_trace(priv, UDBG1, + "subscribe_req: encap=%d, handle=%d, result=%d\n", + req->encapsulation, i, result); + CsrWifiRouterMaPacketSubscribeCfmSend(msg->source,req->interfaceTag, i, result, 0); +} + + +void CsrWifiRouterMaPacketUnsubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterMaPacketUnsubscribeReq* req = (CsrWifiRouterMaPacketUnsubscribeReq*)msg; + CsrResult result; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterMaPacketUnsubscribeReqHandler: invalid priv\n"); + return; + } + + result = CSR_WIFI_RESULT_NOT_FOUND; + + if (req->subscriptionHandle < MAX_MA_UNIDATA_IND_FILTERS) { + if (priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use) { + priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use = 0; + result = CSR_RESULT_SUCCESS; + } else { + result = CSR_WIFI_RESULT_NOT_FOUND; + } + } + + unifi_trace(priv, UDBG1, + "unsubscribe_req: handle=%d, result=%d\n", + req->subscriptionHandle, result); + CsrWifiRouterMaPacketUnsubscribeCfmSend(msg->source,req->interfaceTag, result); +} + + +void CsrWifiRouterCtrlCapabilitiesReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlCapabilitiesReq* req = (CsrWifiRouterCtrlCapabilitiesReq*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlCapabilitiesReqHandler: invalid priv\n"); + return; + } + + CsrWifiRouterCtrlCapabilitiesCfmSend(msg->source,req->clientData, + UNIFI_SOFT_COMMAND_Q_LENGTH - 1, + UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1); +} + + +void CsrWifiRouterCtrlSuspendResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlSuspendRes* res = (CsrWifiRouterCtrlSuspendRes*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlSuspendResHandler: invalid priv\n"); + return; + } + + sme_complete_request(priv, res->status); +} + + +void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlResumeRes* res = (CsrWifiRouterCtrlResumeRes*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlResumeResHandler: invalid priv\n"); + return; + } + + /* + * Unless we are in ptest mode, nothing is waiting for the response. + * Do not call sme_complete_request(), otherwise the driver + * and the SME will be out of step. + */ + if (priv->ptest_mode == 1) { + sme_complete_request(priv, res->status); + } + +} + + +void CsrWifiRouterCtrlTrafficConfigReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlTrafficConfigReq* req = (CsrWifiRouterCtrlTrafficConfigReq*)msg; + CsrResult csrResult; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlTrafficConfigReqHandler: invalid smepriv\n"); + return; + } + if (req->trafficConfigType == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER) + { + req->config.packetFilter |= CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM; + } + csrResult = unifi_ta_configure(priv->card, req->trafficConfigType, (const CsrWifiRouterCtrlTrafficConfig *)&req->config); +} + +void CsrWifiRouterCtrlTrafficClassificationReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlTrafficClassificationReq* req = (CsrWifiRouterCtrlTrafficClassificationReq*)msg; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlTrafficClassificationReqHandler: invalid smepriv\n"); + return; + } + + unifi_ta_classification(priv->card, req->trafficType, req->period); +} + +static int +_sys_packet_req(unifi_priv_t *priv, const CSR_SIGNAL *signal, + CsrUint8 subscriptionHandle, + CsrUint16 frameLength, CsrUint8 *frame, + int proto) +{ + int r; + const sme_ma_unidata_ind_filter_t *subs; + bulk_data_param_t bulkdata; + CSR_MA_PACKET_REQUEST req = signal->u.MaPacketRequest; + struct sk_buff *skb, *newSkb = NULL; + CsrWifiMacAddress peerMacAddress; + CsrResult csrResult; + CsrUint16 interfaceTag = req.VirtualInterfaceIdentifier & 0xff; + CsrBool eapolStore = FALSE; + CsrInt8 protection = 0; + netInterface_priv_t *interfacePriv; + unsigned long flags; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "_sys_packet_req: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); + return -EINVAL; + } + interfacePriv = priv->interfacePriv[interfaceTag]; + if (!priv->sme_unidata_ind_filters[subscriptionHandle].in_use) { + unifi_error(priv, "_sys_packet_req: unknown subscription.\n"); + return -EINVAL; + } + + subs = &priv->sme_unidata_ind_filters[subscriptionHandle]; + unifi_trace(priv, UDBG1, + "_sys_packet_req: handle=%d, subs=%p, encap=%d\n", + subscriptionHandle, subs, subs->encapsulation); + + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], frameLength); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "_sys_packet_req: failed to allocate bulkdata.\n"); + return (int)CsrHipResultToStatus(csrResult); + } + + /* get the peer Mac address */ + memcpy(&peerMacAddress, frame, ETH_ALEN); + + /* Determine if we need to add encapsulation header */ + if (subs->encapsulation == CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET) { + memcpy((void*)bulkdata.d[0].os_data_ptr, frame, frameLength); + + /* The translation is performed on the skb */ + skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; + + unifi_trace(priv, UDBG1, + "_sys_packet_req: skb_add_llc_snap -->\n"); + r = skb_add_llc_snap(priv->netdev[interfaceTag], skb, proto); + unifi_trace(priv, UDBG1, + "_sys_packet_req: skb_add_llc_snap <--\n"); + if (r) { + unifi_error(priv, + "_sys_packet_req: failed to translate eth frame.\n"); + unifi_net_data_free(priv,&bulkdata.d[0]); + return r; + } + + bulkdata.d[0].data_length = skb->len; + } else { + /* Crop the MAC addresses from the packet */ + memcpy((void*)bulkdata.d[0].os_data_ptr, frame + 2*ETH_ALEN, frameLength - 2*ETH_ALEN); + bulkdata.d[0].data_length = frameLength - 2*ETH_ALEN; + skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; + skb->len = bulkdata.d[0].data_length; + + } + + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].data_length = 0; + + /* check for m4 detection */ + if (0 == uf_verify_m4(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length)) { + eapolStore = TRUE; + } + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + if (proto == ETH_P_WAI) + { + protection = 0; /*WAI packets always sent unencrypted*/ + } + else + { +#endif + +#ifdef CSR_SUPPORT_SME + if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, peerMacAddress.a)) < 0) { + unifi_error(priv, "unicast address, but destination not in station record database\n"); + unifi_net_data_free(priv,&bulkdata.d[0]); + return -1; + } +#else + protection = 0; +#endif + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + } +#endif + + /* add Mac header */ + if (prepare_and_add_macheader(priv, skb, newSkb, req.Priority, &bulkdata, interfaceTag, frame, frame + ETH_ALEN, protection)) { + unifi_error(priv, "failed to create MAC header\n"); + unifi_net_data_free(priv,&bulkdata.d[0]); + return -1; + } + + if (eapolStore) { + spin_lock_irqsave(&priv->m4_lock, flags); + /* Store the EAPOL M4 packet for later */ + interfacePriv->m4_signal = *signal; + interfacePriv->m4_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; + interfacePriv->m4_bulk_data.data_length = bulkdata.d[0].data_length; + interfacePriv->m4_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; + interfacePriv->m4_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; + spin_unlock_irqrestore(&priv->m4_lock, flags); + /* Send a signal to SME */ + unifi_trace(priv, UDBG1, "_sys_packet_req: Sending CsrWifiRouterCtrlM4ReadyToSendInd\n"); + CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); + return 0; + } + + /* Send the signal to UniFi */ + /* Set the B31 to 1 for local routing*/ + r= uf_process_ma_packet_req(priv, peerMacAddress.a, (req.HostTag | 0x80000000), interfaceTag, 0, + (CSR_RATE)0, req.Priority, signal->SignalPrimitiveHeader.SenderProcessId, &bulkdata); + if (r) { + unifi_error(priv, + "_sys_packet_req: failed to send signal.\n"); + unifi_net_data_free(priv,&bulkdata.d[0]); + return r; + } + /* The final CsrWifiRouterMaPacketCfmSend() will called when the actual MA-PACKET.cfm is received from the chip */ + + return 0; +} + +void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + int r; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterMaPacketReq* mareq = (CsrWifiRouterMaPacketReq*)msg; + llc_snap_hdr_t *snap; + CsrUint16 snap_protocol; + CSR_SIGNAL signal; + CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; + CsrWifiRouterCtrlPortAction controlPortaction; + CsrUint8 *daddr, *saddr; + CsrUint16 interfaceTag = mareq->interfaceTag & 0x00ff; + int queue; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (!mareq->frame || !priv || !priv->smepriv) + { + unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: invalid frame/priv/priv->smepriv\n"); + return; + } + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); + return; + } + /* get a pointer to dest & source Mac address */ + daddr = mareq->frame; + saddr = (mareq->frame + ETH_ALEN); + /* point to the proper position of frame, since frame has MAC header */ + snap = (llc_snap_hdr_t *) (mareq->frame + 2 * ETH_ALEN); + snap_protocol = ntohs(snap->protocol); + if((snap_protocol == ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + || (snap_protocol == ETH_P_WAI) +#endif + ) + { + queue = UF_UNCONTROLLED_PORT_Q; + } + else + { + queue = UF_CONTROLLED_PORT_Q; + } + + /* Controlled port restrictions apply to the packets */ + controlPortaction = uf_sme_port_state(priv, daddr, queue, interfaceTag); + if (controlPortaction != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) + { + unifi_warning(priv, "CsrWifiRouterMaPacketReqHandler: (%s)controlled port is closed.\n", (queue == UF_CONTROLLED_PORT_Q)?"":"un"); + if(mareq->cfmRequested) + { + CsrWifiRouterMaPacketCfmSend(msg->source, + interfaceTag, + CSR_RESULT_FAILURE, + mareq->hostTag, 0); + } + return; + } + + signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; + /* Store the appHandle in the LSB of the SenderId. */ + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(((priv->sme_cli->sender_id & 0xff00) | (unsigned int)msg->source), + (u8*)&signal.SignalPrimitiveHeader.SenderProcessId); + signal.SignalPrimitiveHeader.ReceiverProcessId = 0; + + /* Fill in the MA-PACKET.req signal */ + memcpy(req->Ra.x, daddr, ETH_ALEN); + req->Priority = mareq->priority; + req->TransmitRate = 0; /* Let firmware select the rate*/ + req->VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag); + req->HostTag = mareq->hostTag; + + if(mareq->cfmRequested) + req->TransmissionControl = 0; + else + req->TransmissionControl = CSR_NO_CONFIRM_REQUIRED; + + r = _sys_packet_req(priv, &signal, mareq->subscriptionHandle, + mareq->frameLength, mareq->frame, snap_protocol); + +#define MAX_RETRY 2 + if (r && mareq->cfmRequested) + { + CsrWifiRouterMaPacketCfmSend(msg->source,interfaceTag, + CSR_RESULT_FAILURE, + mareq->hostTag, 0); + } + return; +} + +void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +void CsrWifiRouterCtrlM4TransmitReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlM4TransmitReq* req = (CsrWifiRouterCtrlM4TransmitReq*)msg; + int r; + bulk_data_param_t bulkdata; + netInterface_priv_t *interfacePriv; + CSR_SIGNAL m4_signal; + unsigned long flags; + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid smepriv\n"); + return; + } + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "M4TransmitReqHandler: interfaceTag >= CSR_WIFI_NUM_INTERFACES\n"); + return; + } + + interfacePriv = priv->interfacePriv[req->interfaceTag]; + spin_lock_irqsave(&priv->m4_lock, flags); + if (interfacePriv->m4_bulk_data.data_length == 0) { + spin_unlock_irqrestore(&priv->m4_lock, flags); + unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid buffer\n"); + return; + } + + memcpy(&bulkdata.d[0], &interfacePriv->m4_bulk_data, sizeof(bulk_data_desc_t)); + + interfacePriv->m4_bulk_data.net_buf_length = 0; + interfacePriv->m4_bulk_data.data_length = 0; + interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; + m4_signal = interfacePriv->m4_signal; + spin_unlock_irqrestore(&priv->m4_lock, flags); + + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].data_length = 0; + + interfacePriv->m4_sent = TRUE; + m4_signal.u.MaPacketRequest.HostTag |= 0x80000000; + /* Store the hostTag for later varification */ + interfacePriv->m4_hostTag = m4_signal.u.MaPacketRequest.HostTag; + r = ul_send_signal_unpacked(priv, &m4_signal, &bulkdata); + unifi_trace(priv, UDBG1, + "CsrWifiRouterCtrlM4TransmitReqHandler: sent\n"); + if (r) { + unifi_error(priv, + "CsrWifiRouterCtrlM4TransmitReqHandler: failed to send signal.\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + } +} + +/* reset the station records when the mode is set as CSR_WIFI_ROUTER_CTRL_MODE_NONE */ +static void CsrWifiRouterCtrlResetStationRecordList(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + CsrUint8 i,j; + CsrWifiRouterCtrlStaInfo_t *staInfo=NULL; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + unsigned long lock_flags; + + /* create a list for sending confirms of un-delivered packets */ + struct list_head send_cfm_list; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterCtrlResetStationRecordList: bad interfaceTag\n"); + return; + } + + INIT_LIST_HEAD(&send_cfm_list); + + /* Reset the station record to NULL if mode is NONE */ + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + if ((staInfo=interfacePriv->staInfo[i]) != NULL) { + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staInfo->mgtFrames)); + uf_flush_list(priv,&(staInfo->mgtFrames)); + for(j=0;jdataPdu[j])); + uf_flush_list(priv,&(staInfo->dataPdu[j])); + } + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + /* Removing station record information from port config array */ + memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); + staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + staInfo->peerControlledPort->in_use = FALSE; + interfacePriv->controlled_data_port.entries_in_use--; + + memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); + staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + staInfo->peerUnControlledPort->in_use = FALSE; + interfacePriv->uncontrolled_data_port.entries_in_use--; + + kfree(interfacePriv->staInfo[i]); + interfacePriv->staInfo[i] = NULL; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } + } + /* after the critical region process the list of frames that requested cfm + * and send cfm to requestor one by one + */ + send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); + +#ifdef CSR_SUPPORT_SME + /* Interface Independent, no of packet queued, incase of mode is None or AP set to 0 */ + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + case CSR_WIFI_ROUTER_CTRL_MODE_NONE: + if (priv->noOfPktQueuedInDriver) { + unifi_warning(priv, "After reset the noOfPktQueuedInDriver = %x\n", priv->noOfPktQueuedInDriver); + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + priv->noOfPktQueuedInDriver = 0; + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + } + break; + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + break; + default: + unifi_error(priv, "interfacemode is not correct in CsrWifiRouterCtrlResetStationRecordList: debug\n"); + } +#endif + + if (((interfacePriv->controlled_data_port.entries_in_use != 0) || (interfacePriv->uncontrolled_data_port.entries_in_use != 0)) + && (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_NONE)) { + /* Print in case if the value of entries goes to -ve/+ve (apart from 0) + * we expect the entries should be zero here if mode is set as NONE + */ + unifi_trace(priv, UDBG3, "In %s controlled port entries = %d, uncontrolled port entries = %d\n", + __FUNCTION__, interfacePriv->controlled_data_port.entries_in_use, + interfacePriv->uncontrolled_data_port.entries_in_use); + } +} + +void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + netInterface_priv_t *interfacePriv; + + /* create a list for sending confirms of un-delivered packets */ + struct list_head send_cfm_list; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "CsrWifiRouterCtrlInterfaceReset: bad interfaceTag\n"); + return; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + INIT_LIST_HEAD(&send_cfm_list); + + /* Enable all queues by default */ + interfacePriv->queueEnabled[0] = 1; + interfacePriv->queueEnabled[1] = 1; + interfacePriv->queueEnabled[2] = 1; + interfacePriv->queueEnabled[3] = 1; + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(interfacePriv->genericMgtFrames)); + uf_flush_list(priv,&(interfacePriv->genericMgtFrames)); + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(interfacePriv->genericMulticastOrBroadCastMgtFrames)); + uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastMgtFrames)); + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(interfacePriv->genericMulticastOrBroadCastFrames)); + + uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames)); + uf_flush_maPktlist(priv,&(interfacePriv->directedMaPktReq)); + + /* process the list of frames that requested cfm + and send cfm to requestor one by one */ + send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); + + /* Reset the station record to NULL if mode is tried to set as NONE */ + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + case CSR_WIFI_ROUTER_CTRL_MODE_MONITOR: + case CSR_WIFI_ROUTER_CTRL_MODE_AMP: + /* station records not available in these modes */ + break; + default: + CsrWifiRouterCtrlResetStationRecordList(priv,interfaceTag); + } + + interfacePriv->num_stations_joined = 0; + interfacePriv->sta_activity_check_enabled = FALSE; +} + + +void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlModeSetReq* req = (CsrWifiRouterCtrlModeSetReq*)msg; + + if (priv == NULL) + { + unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid smepriv\n"); + return; + } + + if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES) + { + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n", + interfacePriv->interfaceMode); + + /* Cleanup the database first for current existing mode, Then take + * care of setting the new mode (Transition seq: AnyMode->NoneMode->newMode) + * So for Every mode changes, Database Initialization/cleanup needed + */ + CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag); + + interfacePriv->interfaceMode = req->mode; + interfacePriv->bssid = req->bssid; + /* For modes other than AP/P2PGO, set below member FALSE */ + interfacePriv->intraBssEnabled = FALSE; + + + if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + interfacePriv->protect = req->protection; + interfacePriv->dtimActive=FALSE; + interfacePriv->multicastPduHostTag = 0xffffffff; + /* For AP/P2PGO mode SME sending intraBssDistEnabled + * i.e. for AP: intraBssDistEnabled = TRUE, for P2PGO + * intraBssDistEnabled = TRUE/FALSE on requirement + */ + interfacePriv->intraBssEnabled = req->intraBssDistEnabled; + unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlModeSetReqHandler: IntraBssDisEnabled = %d\n", + req->intraBssDistEnabled); + } else if (req->mode == CSR_WIFI_ROUTER_CTRL_MODE_NONE) { + netif_carrier_off(priv->netdev[req->interfaceTag]); + interfacePriv->connected = UnifiConnectedUnknown; + } + } + else { + unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid interfaceTag :%d\n",req->interfaceTag); + } +} + +void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +} + +/* delete the station record from the station record data base */ +static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *req) +{ + CsrUint8 j; + CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; + unifi_port_config_t *controlledPort; + unifi_port_config_t *unControlledPort; + netInterface_priv_t *interfacePriv; + maPktReqList_t *maPktreq; + struct list_head *listHeadMaPktreq,*placeHolderMaPktreq; + + CsrUint8 ba_session_idx = 0; + ba_session_rx_struct *ba_session_rx = NULL; + ba_session_tx_struct *ba_session_tx = NULL; + + /* create a list for sending confirms of un-delivered packets */ + struct list_head send_cfm_list; + + unsigned long lock_flags; + + if ((req->peerRecordHandle >= UNIFI_MAX_CONNECTIONS) || (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES)) { + unifi_error(priv, "handle/interfaceTag is not proper, handle = %d, interfaceTag = %d\n", req->peerRecordHandle, req->interfaceTag); + return CSR_RESULT_FAILURE; + } + + INIT_LIST_HEAD(&send_cfm_list); + + interfacePriv = priv->interfacePriv[req->interfaceTag]; + /* remove the station record & make it NULL */ + if ((staInfo=interfacePriv->staInfo[req->peerRecordHandle])!=NULL) { + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staInfo->mgtFrames)); + + uf_flush_list(priv,&(staInfo->mgtFrames)); + for(j=0;jdataPdu[j])); + uf_flush_list(priv,&(staInfo->dataPdu[j])); + } + + /* There may be race condition + before getting the ma_packet_cfm from f/w, driver may receive peer del from SME + */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) { + maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); + if(maPktreq->staHandler== staInfo->assignedHandle){ + dev_kfree_skb(maPktreq->skb); + list_del(listHeadMaPktreq); + kfree(maPktreq); + } + + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + /* clear the port configure array info, for the corresponding peer entry */ + controlledPort = &interfacePriv->controlled_data_port; + unControlledPort = &interfacePriv->uncontrolled_data_port; + + unifi_trace(priv, UDBG1, "peer_delete_record: Peer found handle = %d, port in use: cont(%d), unCont(%d)\n", + req->peerRecordHandle, controlledPort->entries_in_use, unControlledPort->entries_in_use); + + memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); + staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + staInfo->peerControlledPort->in_use = FALSE; + if (controlledPort->entries_in_use) { + controlledPort->entries_in_use--; + } else { + unifi_warning(priv, "number of controlled port entries is zero, trying to decrement: debug\n"); + } + + memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); + staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + staInfo->peerUnControlledPort->in_use = FALSE; + if (unControlledPort->entries_in_use) { + unControlledPort->entries_in_use--; + } else { + unifi_warning(priv, "number of uncontrolled port entries is zero, trying to decrement: debug\n"); + } + + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + /* update the TIM with zero */ + if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS && + staInfo->timSet == CSR_WIFI_TIM_SET) { + unifi_trace(priv, UDBG3, "peer is deleted so TIM updated to 0, in firmware\n"); + update_tim(priv,staInfo->aid,0,req->interfaceTag, req->peerRecordHandle); + } + + + /* Stop BA session if it is active, for this peer address all BA sessions + (per tID per role) are closed */ + + spin_lock(&priv->ba_lock); + for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx]; + if(ba_session_rx) { + if(!memcmp(ba_session_rx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ + blockack_session_stop(priv, + req->interfaceTag, + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT, + ba_session_rx->tID, + ba_session_rx->macAddress); + } + } + } + + for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ + ba_session_tx = priv->interfacePriv[req->interfaceTag]->ba_session_tx[ba_session_idx]; + if(ba_session_tx) { + if(!memcmp(ba_session_tx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ + blockack_session_stop(priv, + req->interfaceTag, + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR, + ba_session_tx->tID, + ba_session_tx->macAddress); + } + } + } + + spin_unlock(&priv->ba_lock); + +#ifdef CSR_SUPPORT_SME + unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid); + cancel_work_sync(&staInfo->send_disconnected_ind_task); +#endif + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); +#ifdef CSR_SUPPORT_SME + interfacePriv->num_stations_joined--; + + staInfo->nullDataHostTag = INVALID_HOST_TAG; + + if ((interfacePriv->sta_activity_check_enabled) && + (interfacePriv->num_stations_joined < STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)) + { + unifi_trace(priv, UDBG1, "STOPPING the Inactivity Timer (num of stations = %d)\n", interfacePriv->num_stations_joined); + interfacePriv->sta_activity_check_enabled = FALSE; + del_timer_sync(&interfacePriv->sta_activity_check_timer); + } +#endif + + /* Free the station record for corresponding peer */ + kfree(interfacePriv->staInfo[req->peerRecordHandle]); + interfacePriv->staInfo[req->peerRecordHandle] = NULL; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + /* after the critical region process the list of frames that requested cfm + and send cfm to requestor one by one */ + send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); + + + } + else + { + unifi_trace(priv, UDBG3, " peer not found: Delete request Peer handle[%d]\n", req->peerRecordHandle); + } + + return CSR_RESULT_SUCCESS; +} + +void CsrWifiRouterCtrlPeerDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + CsrWifiRouterCtrlPeerDelReq* req = (CsrWifiRouterCtrlPeerDelReq*)msg; + CsrResult status = CSR_RESULT_SUCCESS; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + + unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerDelReqHandler \n"); + if (priv == NULL) + { + unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: invalid smepriv\n"); + return; + } + + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: bad interfaceTag\n"); + return; + } + + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + /* remove the station from station record data base */ + status = peer_delete_record(priv, req); + break; + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + default: + /* No station record to maintain in these modes */ + break; + } + + CsrWifiRouterCtrlPeerDelCfmSend(msg->source,req->clientData,req->interfaceTag,status); + unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerDelReqHandler \n"); +} + +/* Add the new station to the station record data base */ +static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *req,CsrUint32 *handle) +{ + CsrUint8 i, powerModeTemp = 0; + CsrBool freeSlotFound = FALSE; + CsrWifiRouterCtrlStaInfo_t *newRecord = NULL; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + CsrTime currentTime, currentTimeHi; + unsigned long lock_flags; + + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "peer_add_new_record: bad interfaceTag\n"); + return CSR_RESULT_FAILURE; + } + + currentTime = CsrTimeGet(¤tTimeHi); + + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + if(interfacePriv->staInfo[i] == NULL) { + /* Slot is empty, so can be used for station record */ + freeSlotFound = TRUE; + *handle = i; + + /* Allocate for the new station record , to avoid race condition would happen between ADD_PEER & + * DEL_PEER the allocation made atomic memory rather than kernel memory + */ + newRecord = (CsrWifiRouterCtrlStaInfo_t *) kmalloc(sizeof(CsrWifiRouterCtrlStaInfo_t), GFP_ATOMIC); + if (!newRecord) { + unifi_error(priv, "failed to allocate the %d bytes of mem for station record\n", + sizeof(CsrWifiRouterCtrlStaInfo_t)); + return CSR_RESULT_FAILURE; + } + + unifi_trace(priv, UDBG1, "peer_add_new_record: handle = %d AID = %d addr = %x:%x:%x:%x:%x:%x LI=%u\n", + *handle, req->associationId, req->peerMacAddress.a[0], req->peerMacAddress.a[1], req->peerMacAddress.a[2], + req->peerMacAddress.a[3], req->peerMacAddress.a[4], req->peerMacAddress.a[5], + req->staInfo.listenIntervalInTus); + + /* disable the preemption until station record updated */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + + interfacePriv->staInfo[i] = newRecord; + /* Initialize the record*/ + memset(newRecord,0,sizeof(CsrWifiRouterCtrlStaInfo_t)); + /* update the station record */ + memcpy(newRecord->peerMacAddress.a, req->peerMacAddress.a, ETH_ALEN); + newRecord->wmmOrQosEnabled = req->staInfo.wmmOrQosEnabled; + + /* maxSpLength is bit map in qosInfo field, so converting accordingly */ + newRecord->maxSpLength = req->staInfo.maxSpLength * 2; + + /*Max SP 0 mean any number of packets. since we buffer only 512 + packets we are hard coding this to zero for the moment */ + + if(newRecord->maxSpLength == 0) + newRecord->maxSpLength=512; + + newRecord->assignedHandle = i; + + /* copy power save mode of all access catagory (Trigger/Delivery/both enabled/disabled) */ + powerModeTemp = (CsrUint8) ((req->staInfo.powersaveMode >> 4) & 0xff); + + if(!(req->staInfo.powersaveMode & 0x0001)) + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= CSR_WIFI_AC_LEGACY_POWER_SAVE; + else + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= powerModeTemp & 0x03; + + if(!(req->staInfo.powersaveMode & 0x0002)) + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= CSR_WIFI_AC_LEGACY_POWER_SAVE; + else + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= ((powerModeTemp & 0x0C)>> 2); + + if(!(req->staInfo.powersaveMode & 0x0004)) + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= CSR_WIFI_AC_LEGACY_POWER_SAVE; + else + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= ((powerModeTemp & 0x30)>> 4); + + if(!(req->staInfo.powersaveMode & 0x0008)) + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= CSR_WIFI_AC_LEGACY_POWER_SAVE; + else + newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= ((powerModeTemp & 0xC0)>> 6); + + { + CsrUint8 k; + for(k=0; k< MAX_ACCESS_CATOGORY ;k++) + unifi_trace(priv, UDBG2, "peer_add_new_record: WMM : %d ,AC %d, powersaveMode %x \n", + req->staInfo.wmmOrQosEnabled,k,newRecord->powersaveMode[k]); + } + + unifi_trace(priv, UDBG3, "newRecord->wmmOrQosEnabled : %d , MAX SP : %d\n", + newRecord->wmmOrQosEnabled,newRecord->maxSpLength); + + /* Initialize the mgtFrames & data Pdu list */ + { + CsrUint8 j; + INIT_LIST_HEAD(&newRecord->mgtFrames); + for(j = 0; j < MAX_ACCESS_CATOGORY; j++) { + INIT_LIST_HEAD(&newRecord->dataPdu[j]); + } + } + + newRecord->lastActivity = currentTime; + newRecord->activity_flag = TRUE; + + /* enable the preemption as station record updated */ + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + /* First time port actions are set for the peer with below information */ + configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, + UF_UNCONTROLLED_PORT_Q, req->interfaceTag); + + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { + configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, + UF_CONTROLLED_PORT_Q, req->interfaceTag); + } else { + configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD, &newRecord->peerMacAddress, + UF_CONTROLLED_PORT_Q, req->interfaceTag); + } + + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + /* Port status must be already set before calling the Add Peer request */ + newRecord->peerControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, + UF_CONTROLLED_PORT_Q, req->interfaceTag); + newRecord->peerUnControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, + UF_UNCONTROLLED_PORT_Q, req->interfaceTag); + + if (!newRecord->peerControlledPort || !newRecord->peerUnControlledPort) { + /* enable the preemption as station record failed to update */ + unifi_warning(priv, "Un/ControlledPort record not found in port configuration array index = %d\n", i); + kfree(interfacePriv->staInfo[i]); + interfacePriv->staInfo[i] = NULL; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + return CSR_RESULT_FAILURE; + } + + newRecord->currentPeerState = CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE; + + /* changes done during block ack handling */ + newRecord->txSuspend = FALSE; + + /*U-APSD related data structure*/ + newRecord->uapsdActive = FALSE; + newRecord->noOfSpFramesSent =0; + + /* The protection bit is updated once the port opens for corresponding peer in + * routerPortConfigure request */ + + /* update the association ID */ + newRecord->aid = req->associationId; + +#ifdef CSR_SUPPORT_SME + interfacePriv->num_stations_joined++; + newRecord->interfacePriv = interfacePriv; + newRecord->listenIntervalInTus = req->staInfo.listenIntervalInTus; + newRecord->nullDataHostTag = INVALID_HOST_TAG; + + INIT_WORK(&newRecord->send_disconnected_ind_task, uf_send_disconnected_ind_wq); + + if(!(interfacePriv->sta_activity_check_enabled) && + (interfacePriv->num_stations_joined >= STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)){ + unifi_trace(priv, UDBG1, + "peer_add_new_record: STARTING the Inactivity Timer (num of stations = %d)", + interfacePriv->num_stations_joined); + + interfacePriv->sta_activity_check_enabled = TRUE; + interfacePriv->sta_activity_check_timer.function = check_inactivity_timer_expire_func; + interfacePriv->sta_activity_check_timer.data = (unsigned long)interfacePriv; + + init_timer(&interfacePriv->sta_activity_check_timer); + mod_timer(&interfacePriv->sta_activity_check_timer, + (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); + + } +#endif + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + break; + } + } + + if(!freeSlotFound) { + unifi_error(priv, "Limited connectivity, Free slot not found for station record addition\n"); + return CSR_RESULT_FAILURE; + } + return CSR_RESULT_SUCCESS; +} + +#ifdef CSR_SUPPORT_SME +static void check_inactivity_timer_expire_func(unsigned long data) +{ + struct unifi_priv *priv; + CsrWifiRouterCtrlStaInfo_t *sta_record = NULL; + CsrUint8 i = 0; + CsrTime now; + CsrTime inactive_time; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *) data; + + if (!interfacePriv) + { + return; + } + + priv = interfacePriv->privPtr; + + if (interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "check_inactivity_timer_expire_func: Invalid interfaceTag\n"); + return; + } + + /* RUN Algorithm to check inactivity for each connected station */ + now = CsrTimeGet(NULL); + + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + if(interfacePriv->staInfo[i] != NULL) { + sta_record = interfacePriv->staInfo[i]; + + if (sta_record->activity_flag == TRUE){ + sta_record->activity_flag = FALSE; + sta_record->lastActivity = now; + continue; + } + + if (sta_record->lastActivity > now) + { + /* simple timer wrap (for 1 wrap) */ + inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now); + } + else + { + inactive_time = (CsrTime)CsrTimeSub(now, sta_record->lastActivity); + } + + if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) + { + unifi_trace(priv, UDBG1, "STA is Inactive - AID = %d inactive_time = %d\n", + sta_record->aid, + inactive_time); + + /* station is in-active, if it is in active mode send a null frame + * and the station should acknowledge the null frame, if acknowledgement + * is not received throw out the station. + * If the station is in Power Save, update TIM for the station so + * that it wakes up and register some activity through PS-Poll or + * trigger frame. + */ + if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) + { + unifi_trace(priv, UDBG1, "STA power save state - Active, send a NULL frame to check if it is ALIVE\n"); + uf_send_nulldata ( priv, + sta_record->interfacePriv->InterfaceTag, + sta_record->peerMacAddress.a, + CSR_CONTENTION, + sta_record); + } + else if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + { + if((sta_record->timSet == CSR_WIFI_TIM_SET) || + (sta_record->timSet == CSR_WIFI_TIM_SETTING)) + { + unifi_trace(priv, UDBG1, "STA power save state - PS, TIM is already SET\n"); + + /* If TIM is set and we do not have any activity for + * more than 3 listen intervals then send a disconnected + * indication to SME, to delete the station from station + * record list. + * The inactivity is already more than STA_INACTIVE_TIMEOUT_VAL + * and this check ensures if the listen interval is a larger + * value than STA_INACTIVE_TIMEOUT_VAL. + */ + if (inactive_time > (3 * (sta_record->listenIntervalInTus * 1024))) + { + unifi_trace(priv, UDBG1, "STA is inactive for more than 3 listen intervals\n"); + queue_work( priv->unifi_workqueue, + &sta_record->send_disconnected_ind_task); + } + + } + else + { + unifi_trace(priv, UDBG1, "STA power save state - PS, update TIM to see if it is ALIVE\n"); + update_tim(priv, + sta_record->aid, + CSR_WIFI_TIM_SET, + interfacePriv->InterfaceTag, + sta_record->assignedHandle); + } + } + } + } + } + + /* re-run the timer interrupt */ + mod_timer(&interfacePriv->sta_activity_check_timer, + (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); + +} + + +void uf_send_disconnected_ind_wq(struct work_struct *work) +{ + + CsrWifiRouterCtrlStaInfo_t *staInfo = container_of(work, CsrWifiRouterCtrlStaInfo_t, send_disconnected_ind_task); + unifi_priv_t *priv; + CsrUint16 interfaceTag; + struct list_head send_cfm_list; + CsrUint8 j; + + func_enter(); + + if(!staInfo) { + return; + } + + if(!staInfo->interfacePriv) { + return; + } + + priv = staInfo->interfacePriv->privPtr; + interfaceTag = staInfo->interfacePriv->InterfaceTag; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_send_disconnected_ind_wq: invalid interfaceTag\n"); + return; + } + + /* The SME/NME may be waiting for confirmation for requested frames to this station. + * So loop through buffered frames for this station and if confirmation is + * requested, send auto confirmation with failure status. Also flush the frames so + * that these are not processed again in PEER_DEL_REQ handler. + */ + INIT_LIST_HEAD(&send_cfm_list); + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staInfo->mgtFrames)); + + uf_flush_list(priv, &(staInfo->mgtFrames)); + + for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staInfo->dataPdu[j])); + + uf_flush_list(priv,&(staInfo->dataPdu[j])); + } + + send_auto_ma_packet_confirm(priv, staInfo->interfacePriv, &send_cfm_list); + + unifi_warning(priv, "uf_send_disconnected_ind_wq: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", + staInfo->peerMacAddress.a[0], + staInfo->peerMacAddress.a[1], + staInfo->peerMacAddress.a[2], + staInfo->peerMacAddress.a[3], + staInfo->peerMacAddress.a[4], + staInfo->peerMacAddress.a[5]); + + CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, + 0, + staInfo->interfacePriv->InterfaceTag, + staInfo->peerMacAddress, + CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); + + + return; +} + + +#endif +void CsrWifiRouterCtrlPeerAddReqHandler(void* drvpriv,CsrWifiFsmEvent* msg) +{ + CsrWifiRouterCtrlPeerAddReq* req = (CsrWifiRouterCtrlPeerAddReq*)msg; + CsrResult status = CSR_RESULT_SUCCESS; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrUint32 handle = 0; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + + unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerAddReqHandler \n"); + if (priv == NULL) + { + unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: invalid smepriv\n"); + return; + } + + if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: bad interfaceTag\n"); + return; + } + + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + /* Add station record */ + status = peer_add_new_record(priv,req,&handle); + break; + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + default: + /* No station record to maintain in these modes */ + break; + } + + CsrWifiRouterCtrlPeerAddCfmSend(msg->source,req->clientData,req->interfaceTag,req->peerMacAddress,handle,status); + unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerAddReqHandler \n"); +} + +void CsrWifiRouterCtrlPeerUpdateReqHandler(void* drvpriv,CsrWifiFsmEvent* msg) +{ + CsrWifiRouterCtrlPeerUpdateReq* req = (CsrWifiRouterCtrlPeerUpdateReq*)msg; + CsrResult status = CSR_RESULT_SUCCESS; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + + unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerUpdateReqHandler \n"); + if (priv == NULL) + { + unifi_error(priv, "CsrWifiRouterCtrlPeerUpdateReqHandler: invalid smepriv\n"); + return; + } + + CsrWifiRouterCtrlPeerUpdateCfmSend(msg->source,req->clientData,req->interfaceTag,status); + unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerUpdateReqHandler \n"); +} + + + void CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + /* This will never be called as it is intercepted in the Userspace */ +} + +void CsrWifiRouterCtrlRawSdioInitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + /* This will never be called as it is intercepted in the Userspace */ +} + +void +uf_send_ba_err_wq(struct work_struct *work) +{ + ba_session_rx_struct *ba_session = container_of(work, ba_session_rx_struct, send_ba_err_task); + unifi_priv_t *priv; + + if(!ba_session) { + return; + } + + if(!ba_session->interfacePriv) { + return; + } + + priv = ba_session->interfacePriv->privPtr; + + if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); + return; + } + + unifi_warning(priv, "%s: Calling CsrWifiRouterCtrlBlockAckErrorIndSend(%d, %d, %d, %d, %x:%x:%x:%x:%x:%x, %d)\n", + __FUNCTION__, + priv->CSR_WIFI_SME_IFACEQUEUE, + 0, + ba_session->interfacePriv->InterfaceTag, + ba_session->tID, + ba_session->macAddress.a[0], + ba_session->macAddress.a[1], + ba_session->macAddress.a[2], + ba_session->macAddress.a[3], + ba_session->macAddress.a[4], + ba_session->macAddress.a[5], + CSR_RESULT_SUCCESS + ); + CsrWifiRouterCtrlBlockAckErrorIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, + 0, + ba_session->interfacePriv->InterfaceTag, + ba_session->tID, + ba_session->macAddress, + CSR_RESULT_SUCCESS); +} + + +static void ba_session_terminate_timer_func(unsigned long data) +{ + ba_session_rx_struct *ba_session = (ba_session_rx_struct*)data; + struct unifi_priv *priv; + + if(!ba_session) { + return; + } + + if(!ba_session->interfacePriv) { + return; + } + + priv = ba_session->interfacePriv->privPtr; + + if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); + return; + } + + queue_work(priv->unifi_workqueue, &ba_session->send_ba_err_task); +} + + +CsrBool blockack_session_stop(unifi_priv_t *priv, + CsrUint16 interfaceTag, + CsrWifiRouterCtrlBlockAckRole role, + CsrUint16 tID, + CsrWifiMacAddress macAddress) +{ + netInterface_priv_t *interfacePriv; + ba_session_rx_struct *ba_session_rx = NULL; + ba_session_tx_struct *ba_session_tx = NULL; + CsrUint8 ba_session_idx = 0; + int i; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); + return FALSE; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + if(!interfacePriv) { + unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); + return FALSE; + } + + if(tID > 15) { + unifi_error(priv, "%s: bad tID = %d\n", __FUNCTION__, tID); + return FALSE; + } + + if((role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR) && + (role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT)) { + unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); + return FALSE; + } + + unifi_warning(priv, "%s: stopping ba_session for peer = %02x:%02x:%02x:%02x:%02x:%02x role = %d tID = %d\n", __FUNCTION__, + macAddress.a[0], macAddress.a[1], macAddress.a[2], + macAddress.a[3], macAddress.a[4], macAddress.a[5], + role, + tID); + + /* find out the appropriate ba session (/station /tid /role) for which stop is requested */ + if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ + for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + + ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; + + if(ba_session_rx){ + if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ + break; + } + } + } + + if (!ba_session_rx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX)) { + unifi_error(priv, "%s: bad ba_session for Rx [tID=%d]\n", __FUNCTION__, tID); + return FALSE; + } + + + if(ba_session_rx->timeout) { + del_timer_sync(&ba_session_rx->timer); + } + cancel_work_sync(&ba_session_rx->send_ba_err_task); + for (i = 0; i < ba_session_rx->wind_size; i++) { + if(ba_session_rx->buffer[i].active) { + frame_desc_struct *frame_desc = &ba_session_rx->buffer[i]; + unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); + } + } + kfree(ba_session_rx->buffer); + + interfacePriv->ba_session_rx[ba_session_idx] = NULL; + kfree(ba_session_rx); + }else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ + for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ + ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; + if(ba_session_tx){ + if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ + break; + } + } + } + + if (!ba_session_tx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX)) { + unifi_error(priv, "%s: bad ba_session for Tx [tID=%d]\n", __FUNCTION__, tID); + return FALSE; + } + interfacePriv->ba_session_tx[ba_session_idx] = NULL; + kfree(ba_session_tx); + + } + + return TRUE; +} + + +void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + CsrWifiRouterCtrlBlockAckDisableReq* req = (CsrWifiRouterCtrlBlockAckDisableReq*)msg; + CsrBool r; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + + unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__); + + spin_lock(&priv->ba_lock); + r = blockack_session_stop(priv, + req->interfaceTag, + req->role, + req->trafficStreamID, + req->macAddress); + spin_unlock(&priv->ba_lock); + + CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source, + req->clientData, + req->interfaceTag, + r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); + + unifi_trace(priv, UDBG6, "%s: out ok\n", __FUNCTION__); +} + + +CsrBool blockack_session_start(unifi_priv_t *priv, + CsrUint16 interfaceTag, + CsrUint16 tID, + CsrUint16 timeout, + CsrWifiRouterCtrlBlockAckRole role, + CsrUint16 wind_size, + CsrUint16 start_sn, + CsrWifiMacAddress macAddress + ) +{ + netInterface_priv_t *interfacePriv; + ba_session_rx_struct *ba_session_rx = NULL; + ba_session_tx_struct *ba_session_tx = NULL; + CsrUint8 ba_session_idx = 0; + + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); + return FALSE; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + if(!interfacePriv) { + unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); + return FALSE; + } + + if(tID > 15) + { + unifi_error(priv, "%s: bad tID=%d\n", __FUNCTION__, tID); + return FALSE; + } + + if(wind_size > MAX_BA_WIND_SIZE) { + unifi_error(priv, "%s: bad wind_size = %d\n", __FUNCTION__, wind_size); + return FALSE; + } + + if(role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR && + role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT) { + unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); + return FALSE; + } + + unifi_warning(priv, "%s: ba session with peer= (%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, + macAddress.a[0], macAddress.a[1], macAddress.a[2], + macAddress.a[3], macAddress.a[4], macAddress.a[5]); + + unifi_warning(priv, "%s: ba session for tID=%d timeout=%d role=%d wind_size=%d start_sn=%d\n", __FUNCTION__, + tID, + timeout, + role, + wind_size, + start_sn); + + /* Check if BA session exists for per station, per TID, per role or not. + if BA session exists update parameters and if it does not exist + create a new BA session */ + if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ + for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ + ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; + if (ba_session_tx) { + if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ + unifi_warning(priv, "%s: ba_session for Tx already exists\n", __FUNCTION__); + return TRUE; + } + } + } + + /* we have to create new ba_session_tx struct */ + ba_session_tx = NULL; + + /* loop through until an empty BA session slot is there and save the session there */ + for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX ; ba_session_idx++){ + if (!(interfacePriv->ba_session_tx[ba_session_idx])){ + break; + } + } + if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX){ + unifi_error(priv, "%s: All ba_session used for Tx, NO free session available\n", __FUNCTION__); + return FALSE; + } + + /* create and populate the new BA session structure */ + ba_session_tx = kmalloc(sizeof(ba_session_tx_struct), GFP_KERNEL); + if (!ba_session_tx) { + unifi_error(priv, "%s: kmalloc failed for ba_session_tx\n", __FUNCTION__); + return FALSE; + } + memset(ba_session_tx, 0, sizeof(ba_session_tx_struct)); + + ba_session_tx->interfacePriv = interfacePriv; + ba_session_tx->tID = tID; + ba_session_tx->macAddress = macAddress; + + interfacePriv->ba_session_tx[ba_session_idx] = ba_session_tx; + + } else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ + + for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; + if (ba_session_rx) { + if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ + unifi_warning(priv, "%s: ba_session for Rx[tID = %d] already exists\n", __FUNCTION__, tID); + + if(ba_session_rx->wind_size == wind_size && + ba_session_rx->timeout == timeout && + ba_session_rx->expected_sn == start_sn) { + return TRUE; + } + + if(ba_session_rx->timeout) { + del_timer_sync(&ba_session_rx->timer); + ba_session_rx->timeout = 0; + } + + if(ba_session_rx->wind_size != wind_size) { + blockack_session_stop(priv, interfaceTag, role, tID, macAddress); + } else { + if (timeout) { + ba_session_rx->timeout = timeout; + ba_session_rx->timer.function = ba_session_terminate_timer_func; + ba_session_rx->timer.data = (unsigned long)ba_session_rx; + init_timer(&ba_session_rx->timer); + mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); + } + return TRUE; + } + } + } + } + + /* we could have a valid BA session pointer here or un-initialized + ba session pointer. but in any case we have to create a new session. + so re-initialize the ba_session pointer */ + ba_session_rx = NULL; + + /* loop through until an empty BA session slot is there and save the session there */ + for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX ; ba_session_idx++){ + if (!(interfacePriv->ba_session_rx[ba_session_idx])){ + break; + } + } + if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ + unifi_error(priv, "%s: All ba_session used for Rx, NO free session available\n", __FUNCTION__); + return FALSE; + } + + + ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); + if (!ba_session_rx) { + unifi_error(priv, "%s: kmalloc failed for ba_session_rx\n", __FUNCTION__); + return FALSE; + } + memset(ba_session_rx, 0, sizeof(ba_session_rx_struct)); + + ba_session_rx->wind_size = wind_size; + ba_session_rx->start_sn = ba_session_rx->expected_sn = start_sn; + ba_session_rx->trigger_ba_after_ssn = FALSE; + + ba_session_rx->buffer = kmalloc(ba_session_rx->wind_size*sizeof(frame_desc_struct), GFP_KERNEL); + if (!ba_session_rx->buffer) { + kfree(ba_session_rx); + unifi_error(priv, "%s: kmalloc failed for buffer\n", __FUNCTION__); + return FALSE; + } + + memset(ba_session_rx->buffer, 0, ba_session_rx->wind_size*sizeof(frame_desc_struct)); + + INIT_WORK(&ba_session_rx->send_ba_err_task, uf_send_ba_err_wq); + if (timeout) { + ba_session_rx->timeout = timeout; + ba_session_rx->timer.function = ba_session_terminate_timer_func; + ba_session_rx->timer.data = (unsigned long)ba_session_rx; + init_timer(&ba_session_rx->timer); + mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); + } + + ba_session_rx->interfacePriv = interfacePriv; + ba_session_rx->tID = tID; + ba_session_rx->macAddress = macAddress; + + interfacePriv->ba_session_rx[ba_session_idx] = ba_session_rx; + } + return TRUE; +} + +void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + CsrWifiRouterCtrlBlockAckEnableReq* req = (CsrWifiRouterCtrlBlockAckEnableReq*)msg; + CsrBool r; + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + spin_lock(&priv->ba_lock); + r = blockack_session_start(priv, + req->interfaceTag, + req->trafficStreamID, + req->timeout, + req->role, + req->bufferSize, + req->ssn, + req->macAddress + ); + spin_unlock(&priv->ba_lock); + + CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source, + req->clientData, + req->interfaceTag, + r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); + unifi_trace(priv, UDBG6, "<<%s: r=%d\n", __FUNCTION__, r); + +} + +void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg; + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status); + + /* status 1 - Filter on + * status 0 - Filter off */ + priv->wapi_multicast_filter = req->status; + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); +} + +void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg; + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status); + + if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) { + /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */ + priv->wapi_unicast_queued_pkt_filter = 1; + } + + /* status 1 - Filter ON + * status 0 - Filter OFF */ + priv->wapi_unicast_filter = req->status; + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); +} + + +void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWapiMulticastReq* req = (CsrWifiRouterCtrlWapiMulticastReq*)msg; + + int client_id, receiver_id; + bulk_data_param_t bulkdata; + CsrResult res; + ul_client_t *client; + + CSR_SIGNAL signal; + CSR_MA_PACKET_INDICATION *pkt_ind; + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiMulticastReqHandler: \n"); + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid priv\n",__FUNCTION__); + return; + } + + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid sme priv\n",__FUNCTION__); + return; + } + + if (req->dataLength == 0 || req->data == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: invalid request\n",__FUNCTION__); + return; + } + + res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); + if (res != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: Could not allocate net data\n",__FUNCTION__); + return; + } + + /* This function is expected to be called only when the MIC has been verified by SME to be correct + * So reset the reception status to rx_success */ + res = read_unpack_signal(req->signal, &signal); + if (res) { + unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Received unknown or corrupted signal.\n"); + return; + } + pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication); + if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) { + unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus); + return; + } + else { + unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiMulticastReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__); + pkt_ind->ReceptionStatus = CSR_RX_SUCCESS; + write_pack(&signal, req->signal, &(req->signalLength)); + } + + memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); + + receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0; + client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; + + client = &priv->ul_clients[client_id]; + + if (client && client->event_hook) { + unifi_trace(priv, UDBG3, + "CsrWifiRouterCtrlWapiMulticastReqHandler: " + "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n", + client->client_id, client->sender_id, receiver_id, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal)); + + client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST); + } + else { + unifi_trace(priv, UDBG4, "No client to give the packet to\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + } + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); +} diff --git a/drivers/staging/csr/sme_userspace.c b/drivers/staging/csr/sme_userspace.c new file mode 100644 index 000000000000..38df94b69e9f --- /dev/null +++ b/drivers/staging/csr/sme_userspace.c @@ -0,0 +1,316 @@ +/* + ***************************************************************************** + * + * FILE : sme_userspace.c + * + * PURPOSE : Support functions for userspace SME helper application. + * + * + * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + ***************************************************************************** + */ + +#include "unifi_priv.h" + +/* + * Fix Me..... These need to be the correct values... + * Dynamic from the user space. + */ +CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE = 0xFFFF; +CsrSchedQid CSR_WIFI_SME_IFACEQUEUE = 0xFFFF; +#ifdef CSR_SUPPORT_WEXT_AP +CsrSchedQid CSR_WIFI_NME_IFACEQUEUE = 0xFFFF; +#endif +int +uf_sme_init(unifi_priv_t *priv) +{ + int i, j; + + CsrWifiRouterTransportInit(priv); + + priv->smepriv = priv; + + init_waitqueue_head(&priv->sme_request_wq); + + priv->filter_tclas_ies = NULL; + memset(&priv->packet_filters, 0, sizeof(uf_cfg_bcast_packet_filter_t)); + +#ifdef CSR_SUPPORT_WEXT + priv->ignore_bssid_join = FALSE; + priv->mib_data.length = 0; + + uf_sme_wext_set_defaults(priv); +#endif /* CSR_SUPPORT_WEXT*/ + + priv->sta_ip_address = 0xFFFFFFFF; + + priv->wifi_on_state = wifi_on_unspecified; + + sema_init(&priv->sme_sem, 1); + memset(&priv->sme_reply, 0, sizeof(sme_reply_t)); + + priv->ta_ind_work.in_use = 0; + priv->ta_sample_ind_work.in_use = 0; + + priv->CSR_WIFI_SME_IFACEQUEUE = 0xFFFF; + + for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { + priv->sme_unidata_ind_filters[i].in_use = 0; + } + + /* Create a work queue item for Traffic Analysis indications to SME */ + INIT_WORK(&priv->ta_ind_work.task, uf_ta_ind_wq); + INIT_WORK(&priv->ta_sample_ind_work.task, uf_ta_sample_ind_wq); +#ifdef CSR_SUPPORT_WEXT + INIT_WORK(&priv->sme_config_task, uf_sme_config_wq); +#endif + + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; + interfacePriv->m4_sent = FALSE; + interfacePriv->m4_bulk_data.net_buf_length = 0; + interfacePriv->m4_bulk_data.data_length = 0; + interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; + + memset(&interfacePriv->controlled_data_port, 0, sizeof(unifi_port_config_t)); + interfacePriv->controlled_data_port.entries_in_use = 1; + interfacePriv->controlled_data_port.port_cfg[0].in_use = TRUE; + interfacePriv->controlled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + interfacePriv->controlled_data_port.overide_action = UF_DATA_PORT_OVERIDE; + + memset(&interfacePriv->uncontrolled_data_port, 0, sizeof(unifi_port_config_t)); + interfacePriv->uncontrolled_data_port.entries_in_use = 1; + interfacePriv->uncontrolled_data_port.port_cfg[0].in_use = TRUE; + interfacePriv->uncontrolled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + interfacePriv->uncontrolled_data_port.overide_action = UF_DATA_PORT_OVERIDE; + + /* Mark the remainder of the port config table as unallocated */ + for(j = 1; j < UNIFI_MAX_CONNECTIONS; j++) { + interfacePriv->controlled_data_port.port_cfg[j].in_use = FALSE; + interfacePriv->controlled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + + interfacePriv->uncontrolled_data_port.port_cfg[j].in_use = FALSE; + interfacePriv->uncontrolled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + } + + /* intializing the lists */ + INIT_LIST_HEAD(&interfacePriv->genericMgtFrames); + INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames); + INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames); + INIT_LIST_HEAD(&interfacePriv->directedMaPktReq); + + for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { + interfacePriv->staInfo[j] = NULL; + } + + interfacePriv->num_stations_joined = 0; + interfacePriv->sta_activity_check_enabled = FALSE; + } + + + return 0; +} /* uf_sme_init() */ + + +void +uf_sme_deinit(unifi_priv_t *priv) +{ + int i,j; + CsrUint8 ba_session_idx; + ba_session_rx_struct *ba_session_rx = NULL; + ba_session_tx_struct *ba_session_tx = NULL; + CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; + netInterface_priv_t *interfacePriv = NULL; + + /* Free any TCLASs previously allocated */ + if (priv->packet_filters.tclas_ies_length) { + priv->packet_filters.tclas_ies_length = 0; + CsrPmemFree(priv->filter_tclas_ies); + priv->filter_tclas_ies = NULL; + } + + for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { + priv->sme_unidata_ind_filters[i].in_use = 0; + } + + /* Remove all the Peer database, before going down */ + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + spin_lock(&priv->ba_lock); + for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ + ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx]; + if(ba_session_rx) { + blockack_session_stop(priv, + i, + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT, + ba_session_rx->tID, + ba_session_rx->macAddress); + } + } + for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ + ba_session_tx = priv->interfacePriv[i]->ba_session_tx[ba_session_idx]; + if(ba_session_tx) { + blockack_session_stop(priv, + i, + CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR, + ba_session_tx->tID, + ba_session_tx->macAddress); + } + } + + spin_unlock(&priv->ba_lock); + interfacePriv = priv->interfacePriv[i]; + if(interfacePriv){ + for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { + if ((staInfo=interfacePriv->staInfo[j]) != NULL) { + /* Clear the STA activity parameters before freeing station Record */ + unifi_trace(priv, UDBG1, "uf_sme_deinit: Canceling work queue for STA with AID: %d\n", staInfo->aid); + cancel_work_sync(&staInfo->send_disconnected_ind_task); + staInfo->nullDataHostTag = INVALID_HOST_TAG; + } + } + if (interfacePriv->sta_activity_check_enabled){ + interfacePriv->sta_activity_check_enabled = FALSE; + del_timer_sync(&interfacePriv->sta_activity_check_timer); + } + } + CsrWifiRouterCtrlInterfaceReset(priv, i); + priv->interfacePriv[i]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_NONE; + } + + +} /* uf_sme_deinit() */ + + + + + +/* + * --------------------------------------------------------------------------- + * unifi_ta_indicate_protocol + * + * Report that a packet of a particular type has been seen + * + * Arguments: + * drv_priv The device context pointer passed to ta_init. + * protocol The protocol type enum value. + * direction Whether the packet was a tx or rx. + * src_addr The source MAC address from the data packet. + * + * Returns: + * None. + * + * Notes: + * We defer the actual sending to a background workqueue, + * see uf_ta_ind_wq(). + * --------------------------------------------------------------------------- + */ +void +unifi_ta_indicate_protocol(void *ospriv, + CsrWifiRouterCtrlTrafficPacketType packet_type, + CsrWifiRouterCtrlProtocolDirection direction, + const CsrWifiMacAddress *src_addr) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + if (priv->ta_ind_work.in_use) { + unifi_warning(priv, + "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n"); + return; + } + + if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX == direction) + { + CsrUint16 interfaceTag = 0; + CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, + interfaceTag, + packet_type, + direction, + *src_addr); + } + else + { + priv->ta_ind_work.packet_type = packet_type; + priv->ta_ind_work.direction = direction; + priv->ta_ind_work.src_addr = *src_addr; + + queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task); + } + +} /* unifi_ta_indicate_protocol() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_ta_indicate_sampling + * + * Send the TA sampling information to the SME. + * + * Arguments: + * drv_priv The device context pointer passed to ta_init. + * stats The TA sampling data to send. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + if (!priv) { + return; + } + + if (priv->ta_sample_ind_work.in_use) { + unifi_warning(priv, + "unifi_ta_indicate_sampling: workqueue item still in use, not sending\n"); + return; + } + + priv->ta_sample_ind_work.stats = *stats; + + queue_work(priv->unifi_workqueue, &priv->ta_sample_ind_work.task); + +} /* unifi_ta_indicate_sampling() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_ta_indicate_l4stats + * + * Send the TA TCP/UDP throughput information to the driver. + * + * Arguments: + * drv_priv The device context pointer passed to ta_init. + * rxTcpThroughput TCP RX throughput in KiloBytes + * txTcpThroughput TCP TX throughput in KiloBytes + * rxUdpThroughput UDP RX throughput in KiloBytes + * txUdpThroughput UDP TX throughput in KiloBytes + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_ta_indicate_l4stats(void *ospriv, + CsrUint32 rxTcpThroughput, + CsrUint32 txTcpThroughput, + CsrUint32 rxUdpThroughput, + CsrUint32 txUdpThroughput) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + if (!priv) { + return; + } + /* Save the info. The actual action will be taken in unifi_ta_indicate_sampling() */ + priv->rxTcpThroughput = rxTcpThroughput; + priv->txTcpThroughput = txTcpThroughput; + priv->rxUdpThroughput = rxUdpThroughput; + priv->txUdpThroughput = txUdpThroughput; +} /* unifi_ta_indicate_l4stats() */ diff --git a/drivers/staging/csr/sme_userspace.h b/drivers/staging/csr/sme_userspace.h new file mode 100644 index 000000000000..19f484f863b1 --- /dev/null +++ b/drivers/staging/csr/sme_userspace.h @@ -0,0 +1,38 @@ +/* + * *************************************************************************** + * FILE: sme_userspace.h + * + * PURPOSE: SME related definitions. + * + * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ +#ifndef __LINUX_SME_USERSPACE_H__ +#define __LINUX_SME_USERSPACE_H__ 1 + +#include + +int uf_sme_init(unifi_priv_t *priv); +void uf_sme_deinit(unifi_priv_t *priv); +int uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length); + + +#include "csr_wifi_router_lib.h" +#include "csr_wifi_router_sef.h" +#include "csr_wifi_router_ctrl_lib.h" +#include "csr_wifi_router_ctrl_sef.h" +#include "csr_wifi_sme_task.h" +#ifdef CSR_SUPPORT_WEXT_AP +#include "csr_wifi_nme_ap_lib.h" +#endif +#include "csr_wifi_sme_lib.h" + +void CsrWifiRouterTransportInit(unifi_priv_t *priv); +void CsrWifiRouterTransportRecv(unifi_priv_t *priv, CsrUint8* buffer, CsrSize bufferLength); +void CsrWifiRouterTransportDeInit(unifi_priv_t *priv); + +#endif /* __LINUX_SME_USERSPACE_H__ */ diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c new file mode 100644 index 000000000000..384ccd46982e --- /dev/null +++ b/drivers/staging/csr/sme_wext.c @@ -0,0 +1,3394 @@ +/* + * --------------------------------------------------------------------------- + * FILE: sme_wext.c + * + * PURPOSE: + * Handlers for ioctls from iwconfig. + * These provide the control plane operations. + * + * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include "unifi_priv.h" +#include + +#define CHECK_INITED(_priv) \ + do { \ + if (_priv->init_progress != UNIFI_INIT_COMPLETED) { \ + unifi_trace(_priv, UDBG2, "%s unifi not ready, failing wext call\n", __FUNCTION__); \ + return -ENODEV; \ + } \ + } while (0) + +/* Workaround for the wpa_supplicant hanging issue */ +#define CSR_WIFI_WEXT_HANG_WORKAROUND + +#ifdef CSR_WIFI_WEXT_HANG_WORKAROUND +# define UF_RTNL_LOCK() rtnl_lock() +# define UF_RTNL_UNLOCK() rtnl_unlock() +#else +# define UF_RTNL_LOCK() +# define UF_RTNL_UNLOCK() +#endif + + +/* + * --------------------------------------------------------------------------- + * Helper functions + * --------------------------------------------------------------------------- + */ + +/* + * --------------------------------------------------------------------------- + * wext_freq_to_channel + * channel_to_mhz + * + * These functions convert between channel number and frequency. + * + * Arguments: + * ch Channel number, as defined in 802.11 specs + * m, e Mantissa and exponent as provided by wireless extension. + * + * Returns: + * channel or frequency (in MHz) value + * --------------------------------------------------------------------------- + */ +static int +wext_freq_to_channel(int m, int e) +{ + int mhz; + + mhz = m; + while (e < 6) { + mhz /= 10; + e++; + } + while (e > 6) { + mhz *= 10; + e--; + } + + if (mhz >= 5000) { + return ((mhz - 5000) / 5); + } + + if (mhz == 2482) { + return 14; + } + + if (mhz >= 2407) { + return ((mhz - 2407) / 5); + } + + return 0; +} /* wext_freq_to_channel() */ + +static int +channel_to_mhz(int ch, int dot11a) +{ + + if (ch == 0) return 0; + if (ch > 200) return 0; + + /* 5G */ + if (dot11a) { + return (5000 + (5 * ch)); + } + + /* 2.4G */ + if (ch == 14) { + return 2484; + } + + if ((ch < 14) && (ch > 0)) { + return (2407 + (5 * ch)); + } + + return 0; +} +#ifdef CSR_SUPPORT_WEXT_AP +void uf_sme_wext_ap_set_defaults(unifi_priv_t *priv) +{ + memcpy(priv->ap_config.ssid.ssid,"defaultssid",sizeof("defaultssid")); + + priv->ap_config.ssid.length = 8; + priv->ap_config.channel = 6; + priv->ap_config.if_index = 1; + priv->ap_config.credentials.authType = 0; + priv->ap_config.max_connections=8; + + priv->group_sec_config.apGroupkeyTimeout = 0; + priv->group_sec_config.apStrictGtkRekey = 0; + priv->group_sec_config.apGmkTimeout = 0; + priv->group_sec_config.apResponseTimeout = 100; /* Default*/ + priv->group_sec_config.apRetransLimit = 3; /* Default*/ + /* Set default params even if they may not be used*/ + /* Until Here*/ + + priv->ap_mac_config.preamble = CSR_WIFI_SME_USE_LONG_PREAMBLE; + priv->ap_mac_config.shortSlotTimeEnabled = FALSE; + priv->ap_mac_config.ctsProtectionType=CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC; + + priv->ap_mac_config.wmmEnabled = TRUE; + priv->ap_mac_config.wmmApParams[0].cwMin=4; + priv->ap_mac_config.wmmApParams[0].cwMax=10; + priv->ap_mac_config.wmmApParams[0].aifs=3; + priv->ap_mac_config.wmmApParams[0].txopLimit=0; + priv->ap_mac_config.wmmApParams[0].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApParams[1].cwMin=4; + priv->ap_mac_config.wmmApParams[1].cwMax=10; + priv->ap_mac_config.wmmApParams[1].aifs=7; + priv->ap_mac_config.wmmApParams[1].txopLimit=0; + priv->ap_mac_config.wmmApParams[1].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApParams[2].cwMin=3; + priv->ap_mac_config.wmmApParams[2].cwMax=4; + priv->ap_mac_config.wmmApParams[2].aifs=1; + priv->ap_mac_config.wmmApParams[2].txopLimit=94; + priv->ap_mac_config.wmmApParams[2].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApParams[3].cwMin=2; + priv->ap_mac_config.wmmApParams[3].cwMax=3; + priv->ap_mac_config.wmmApParams[3].aifs=1; + priv->ap_mac_config.wmmApParams[3].txopLimit=47; + priv->ap_mac_config.wmmApParams[3].admissionControlMandatory=FALSE; + + priv->ap_mac_config.wmmApBcParams[0].cwMin=4; + priv->ap_mac_config.wmmApBcParams[0].cwMax=10; + priv->ap_mac_config.wmmApBcParams[0].aifs=3; + priv->ap_mac_config.wmmApBcParams[0].txopLimit=0; + priv->ap_mac_config.wmmApBcParams[0].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApBcParams[1].cwMin=4; + priv->ap_mac_config.wmmApBcParams[1].cwMax=10; + priv->ap_mac_config.wmmApBcParams[1].aifs=7; + priv->ap_mac_config.wmmApBcParams[1].txopLimit=0; + priv->ap_mac_config.wmmApBcParams[1].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApBcParams[2].cwMin=3; + priv->ap_mac_config.wmmApBcParams[2].cwMax=4; + priv->ap_mac_config.wmmApBcParams[2].aifs=2; + priv->ap_mac_config.wmmApBcParams[2].txopLimit=94; + priv->ap_mac_config.wmmApBcParams[2].admissionControlMandatory=FALSE; + priv->ap_mac_config.wmmApBcParams[3].cwMin=2; + priv->ap_mac_config.wmmApBcParams[3].cwMax=3; + priv->ap_mac_config.wmmApBcParams[3].aifs=2; + priv->ap_mac_config.wmmApBcParams[3].txopLimit=47; + priv->ap_mac_config.wmmApBcParams[3].admissionControlMandatory=FALSE; + + priv->ap_mac_config.accessType=CSR_WIFI_AP_ACCESS_TYPE_NONE; + priv->ap_mac_config.macAddressListCount=0; + priv->ap_mac_config.macAddressList=NULL; + + priv->ap_mac_config.apHtParams.rxStbc=1; + priv->ap_mac_config.apHtParams.rifsModeAllowed=TRUE; + priv->ap_mac_config.apHtParams.greenfieldSupported=FALSE; + priv->ap_mac_config.apHtParams.shortGi20MHz=TRUE; + priv->ap_mac_config.apHtParams.htProtection=0; + priv->ap_mac_config.apHtParams.dualCtsProtection=FALSE; + + priv->ap_mac_config.phySupportedBitmap = + (CSR_WIFI_SME_AP_PHY_SUPPORT_B|CSR_WIFI_SME_AP_PHY_SUPPORT_G|CSR_WIFI_SME_AP_PHY_SUPPORT_N); + priv->ap_mac_config.beaconInterval= 100; + priv->ap_mac_config.dtimPeriod=3; + priv->ap_mac_config.maxListenInterval=0x00ff;/* Set it to a large value + to enable different types of + devices to join us */ + priv->ap_mac_config.supportedRatesCount = + uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap); +} +#endif +/* + * --------------------------------------------------------------------------- + * uf_sme_wext_set_defaults + * + * Set up power-on defaults for driver config. + * + * Note: The SME Management API *cannot* be used in this function. + * + * Arguments: + * priv Pointer to device private context struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +uf_sme_wext_set_defaults(unifi_priv_t *priv) +{ + memset(&priv->connection_config, 0, sizeof(CsrWifiSmeConnectionConfig)); + + priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE; + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; + priv->connection_config.privacyMode = CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; + priv->connection_config.wmmQosInfo = 0xFF; + priv->connection_config.ifIndex = CSR_WIFI_SME_RADIO_IF_BOTH; + priv->connection_config.adhocJoinOnly = FALSE; + priv->connection_config.adhocChannel = 6; + + priv->wep_tx_key_index = 0; + + priv->wext_wireless_stats.qual.qual = 0; + priv->wext_wireless_stats.qual.level = 0; + priv->wext_wireless_stats.qual.noise = 0; + priv->wext_wireless_stats.qual.updated = 0x70; +#ifdef CSR_SUPPORT_WEXT_AP + /* Initialize the default configuration for AP */ + uf_sme_wext_ap_set_defaults(priv); +#endif + + +} /* uf_sme_wext_set_defaults() */ + + +/* + * --------------------------------------------------------------------------- + * WEXT methods + * --------------------------------------------------------------------------- + */ + +/* + * --------------------------------------------------------------------------- + * unifi_giwname - handler for SIOCGIWNAME + * unifi_siwfreq - handler for SIOCSIWFREQ + * unifi_giwfreq - handler for SIOCGIWFREQ + * unifi_siwmode - handler for SIOCSIWMODE + * unifi_giwmode - handler for SIOCGIWMODE + * unifi_giwrange - handler for SIOCGIWRANGE + * unifi_siwap - handler for SIOCSIWAP + * unifi_giwap - handler for SIOCGIWAP + * unifi_siwscan - handler for SIOCSIWSCAN + * unifi_giwscan - handler for SIOCGIWSCAN + * unifi_siwessid - handler for SIOCSIWESSID + * unifi_giwessid - handler for SIOCGIWESSID + * unifi_siwencode - handler for SIOCSIWENCODE + * unifi_giwencode - handler for SIOCGIWENCODE + * + * Handler functions for IW extensions. + * These are registered via the unifi_iw_handler_def struct below + * and called by the generic IW driver support code. + * See include/net/iw_handler.h. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static int +iwprivsdefs(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int r; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + CsrWifiSmeMibConfig mibConfig; + CsrWifiSmePowerConfig powerConfig; + + unifi_trace(priv, UDBG1, "iwprivs80211defaults: reload defaults\n"); + + uf_sme_wext_set_defaults(priv); + + /* Get, modify and set the MIB data */ + r = sme_mgt_mib_config_get(priv, &mibConfig); + if (r) { + unifi_error(priv, "iwprivs80211defaults: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + mibConfig.dot11RtsThreshold = 2347; + mibConfig.dot11FragmentationThreshold = 2346; + r = sme_mgt_mib_config_set(priv, &mibConfig); + if (r) { + unifi_error(priv, "iwprivs80211defaults: Set CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; + powerConfig.listenIntervalTu = 100; + powerConfig.rxDtims = 1; + + r = sme_mgt_power_config_set(priv, &powerConfig); + if (r) { + unifi_error(priv, "iwprivs80211defaults: Set unifi_PowerConfigValue failed.\n"); + return r; + } + + return 0; +} /* iwprivsdefs() */ + +static int +iwprivs80211ps(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int r = 0; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + int ps_mode = (int)(*extra); + CsrWifiSmePowerConfig powerConfig; + + unifi_trace(priv, UDBG1, "iwprivs80211ps: power save mode = %d\n", ps_mode); + + r = sme_mgt_power_config_get(priv, &powerConfig); + if (r) { + unifi_error(priv, "iwprivs80211ps: Get unifi_PowerConfigValue failed.\n"); + return r; + } + + switch (ps_mode) { + case CSR_PMM_ACTIVE_MODE: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; + break; + case CSR_PMM_POWER_SAVE: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; + break; + case CSR_PMM_FAST_POWER_SAVE: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED; + break; + default: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO; + break; + } + + r = sme_mgt_power_config_set(priv, &powerConfig); + if (r) { + unifi_error(priv, "iwprivs80211ps: Set unifi_PowerConfigValue failed.\n"); + } + + return r; +} + +static int +iwprivg80211ps(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + CsrWifiSmePowerConfig powerConfig; + int r; + + r = sme_mgt_power_config_get(priv, &powerConfig); + if (r) { + unifi_error(priv, "iwprivg80211ps: Get 802.11 power mode failed.\n"); + return r; + } + + switch (powerConfig.powerSaveLevel) { + case CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW: + snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, + "Power save mode: %d (Active)", + powerConfig.powerSaveLevel); + break; + case CSR_WIFI_SME_POWER_SAVE_LEVEL_MED: + snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, + "Power save mode: %d (Fast)", + powerConfig.powerSaveLevel); + break; + case CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH: + snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, + "Power save mode: %d (Full)", + powerConfig.powerSaveLevel); + break; + case CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO: + snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, + "Power save mode: %d (Auto)", + powerConfig.powerSaveLevel); + break; + default: + snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, + "Power save mode: %d (Unknown)", + powerConfig.powerSaveLevel); + break; + } + + wrqu->data.length = strlen(extra) + 1; + + return 0; +} + +static int +iwprivssmedebug(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* No longer supported on the API */ +#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) + unifi_debug_buf_dump(); +#endif + + return 0; +} + +#ifdef CSR_SUPPORT_WEXT_AP +#define PARAM_TYPE_INT 0 +#define PARAM_TYPE_STRING 1 +#define CSR_WIFI_MAX_SSID_LEN 32 +#define CSR_WIFI_MAX_SEC_LEN 16 +#define CSR_WIFI_MAX_KEY_LEN 65 + +static int hex_look_up(char x) +{ + if(x>='0' && x<='9') + return (x-48); + if(x>= 'a' && x <= 'f') + return (x-87); + return -1; +} + +static int power (int a, int b) +{ + int i; + int num =1; + for(i=0;i param_max_len) { + unifi_notice(priv,"extracted param len:%d is > MAX:%d\n",param_str_len, param_max_len); + param_str_len = param_max_len; + } + switch (param_type) { + case PARAM_TYPE_INT: + { + CsrUint32 *pdst_int = dst,num =0; + int i,j=0; + if (param_str_len > sizeof(int_str)) { + param_str_len = sizeof(int_str); + } + memcpy(int_str, param_str_begin, param_str_len); + for(i = param_str_len; i>0;i--) { + if(int_str[i-1] >= '0' && int_str[i-1] <='9') { + num += ((int_str[i-1]-'0')*power(10,j)); + j++; + } else { + unifi_error(priv,"decode_parameter_from_string:not a number %c\n",(int_str[i-1])); + return -1; + } + } + *pdst_int = num; + unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded int = %d\n",*pdst_int); + } + break; + default: + memcpy(dst, param_str_begin, param_str_len); + *((char *)dst + param_str_len) = 0; + unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded string = %s\n",(char *)dst); + break; + } + } else { + unifi_error(priv,"decode_parameter_from_string: Token:%s not found in %s \n",token,orig_str); + return -1; + } + return 0; +} +static int store_ap_advanced_config_from_string(unifi_priv_t *priv, char *param_str) +{ + char * str_ptr=param_str; + int ret = 0,tmp_var; + char phy_mode[6]; + CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config; + + /* Check for BI */ + ret = decode_parameter_from_string(priv, &str_ptr, "BI=", + PARAM_TYPE_INT, &tmp_var, 5); + if(ret) { + unifi_error(priv,"store_ap_advanced_config_from_string: BI not found\n"); + return -1; + } + ap_mac_config->beaconInterval = tmp_var; + ret = decode_parameter_from_string(priv, &str_ptr, "DTIM_PER=", + PARAM_TYPE_INT, &tmp_var, 5); + if(ret) { + unifi_error(priv,"store_ap_advanced_config_from_string: DTIM_PER not found\n"); + return -1; + } + ap_mac_config->dtimPeriod = tmp_var; + ret = decode_parameter_from_string(priv, &str_ptr, "WMM=", + PARAM_TYPE_INT, &tmp_var, 5); + if(ret) { + unifi_error(priv,"store_ap_advanced_config_from_string: WMM not found\n"); + return -1; + } + ap_mac_config->wmmEnabled = tmp_var; + ret = decode_parameter_from_string(priv, &str_ptr, "PHY=", + PARAM_TYPE_STRING, phy_mode, 5); + if(ret) { + unifi_error(priv,"store_ap_advanced_config_from_string: PHY not found\n"); + } else { + if(strstr(phy_mode,"b")){ + ap_mac_config->phySupportedBitmap = CSR_WIFI_SME_AP_PHY_SUPPORT_B; + } + if(strstr(phy_mode,"g")) { + ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_G; + } + if(strstr(phy_mode,"n")) { + ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_N; + } + ap_mac_config->supportedRatesCount = + uf_configure_supported_rates(ap_mac_config->supportedRates, ap_mac_config->phySupportedBitmap); + } + return ret; +} + +static int store_ap_config_from_string( unifi_priv_t * priv,char *param_str) + +{ + char *str_ptr = param_str; + char sub_cmd[16]; + char sec[CSR_WIFI_MAX_SEC_LEN]; + char key[CSR_WIFI_MAX_KEY_LEN]; + int ret = 0,tmp_var; + CsrWifiSmeApConfig_t *ap_config = &priv->ap_config; + CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config; + memset(sub_cmd, 0, sizeof(sub_cmd)); + if(!strstr(param_str,"END")) { + unifi_error(priv,"store_ap_config_from_string:Invalid config string:%s\n",param_str); + return -1; + } + if (decode_parameter_from_string(priv,&str_ptr, "ASCII_CMD=", + PARAM_TYPE_STRING, sub_cmd, 6) != 0) { + return -1; + } + if (strncmp(sub_cmd, "AP_CFG", 6)) { + + if(!strncmp(sub_cmd ,"ADVCFG", 6)) { + return store_ap_advanced_config_from_string(priv, str_ptr); + } + unifi_error(priv,"store_ap_config_from_string: sub_cmd:%s != 'AP_CFG or ADVCFG'!\n", sub_cmd); + return -1; + } + memset(ap_config, 0, sizeof(CsrWifiSmeApConfig_t)); + ret = decode_parameter_from_string(priv,&str_ptr, "SSID=", + PARAM_TYPE_STRING, ap_config->ssid.ssid, + CSR_WIFI_MAX_SSID_LEN); + if(ret) { + unifi_error(priv,"store_ap_config_from_string: SSID not found\n"); + return -1; + } + ap_config->ssid.length = strlen(ap_config->ssid.ssid); + + ret = decode_parameter_from_string(priv, &str_ptr, "SEC=", + PARAM_TYPE_STRING, sec, CSR_WIFI_MAX_SEC_LEN); + if(ret) { + unifi_error(priv,"store_ap_config_from_string: SEC not found\n"); + return -1; + } + ret = decode_parameter_from_string(priv,&str_ptr, "KEY=", + PARAM_TYPE_STRING, key, CSR_WIFI_MAX_KEY_LEN); + if(!strcasecmp(sec,"open")) { + unifi_trace(priv,UDBG2,"store_ap_config_from_string: security open"); + ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM; + if(ret) { + unifi_notice(priv,"store_ap_config_from_string: KEY not found:fine with Open\n"); + } + } + else if(!strcasecmp(sec,"wpa2-psk")) { + int i,j=0; + CsrWifiNmeApAuthPers *pers = + ((CsrWifiNmeApAuthPers *)&(ap_config->credentials.nmeAuthType.authTypePersonal)); + CsrUint8 *psk = pers->authPers_credentials.psk.psk; + + unifi_trace(priv,UDBG2,"store_ap_config_from_string: security WPA2"); + if(ret) { + unifi_error(priv,"store_ap_config_from_string: KEY not found for WPA2\n"); + return -1; + } + ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL; + pers->authSupport = CSR_WIFI_SME_RSN_AUTH_WPA2PSK; + pers->rsnCapabilities =0; + pers->wapiCapabilities =0; + pers->pskOrPassphrase=CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK; + pers->authPers_credentials.psk.encryptionMode = + (CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP |CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP) ; + for(i=0;i<32;i++){ + psk[i] = (16*hex_look_up(key[j]))+hex_look_up(key[j+1]); + j+=2; + } + + } else { + unifi_notice(priv,"store_ap_config_from_string: Unknown security: Assuming Open"); + ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM; + return -1; + } + /* Get the decoded value in a temp int variable to ensure that other fields within the struct + which are of type other than int are not over written */ + ret = decode_parameter_from_string(priv,&str_ptr, "CHANNEL=", PARAM_TYPE_INT, &tmp_var, 5); + if(ret) + return -1; + ap_config->channel = tmp_var; + ret = decode_parameter_from_string(priv,&str_ptr, "PREAMBLE=", PARAM_TYPE_INT, &tmp_var, 5); + if(ret) + return -1; + ap_mac_config->preamble = tmp_var; + ret = decode_parameter_from_string(priv,&str_ptr, "MAX_SCB=", PARAM_TYPE_INT, &tmp_var, 5); + ap_config->max_connections = tmp_var; + return ret; +} + +static int +iwprivsapstart(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int r; + + unifi_trace(priv, UDBG1, "iwprivsapstart\n" ); + r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config); + if(r) { + unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r); + } + return r; +} + +static int +iwprivsapconfig(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + char *cfg_str = NULL; + int r; + + unifi_trace(priv, UDBG1, "iwprivsapconfig\n" ); + if (wrqu->data.length != 0) { + char *str; + if (!(cfg_str = kmalloc(wrqu->data.length+1, GFP_KERNEL))) + { + return -ENOMEM; + } + if (copy_from_user(cfg_str, wrqu->data.pointer, wrqu->data.length)) { + kfree(cfg_str); + return -EFAULT; + } + cfg_str[wrqu->data.length] = 0; + unifi_trace(priv,UDBG2,"length:%d\n",wrqu->data.length); + unifi_trace(priv,UDBG2,"AP configuration string:%s\n",cfg_str); + str = cfg_str; + if ((r = store_ap_config_from_string(priv,str))) { + unifi_error(priv, "iwprivsapconfig:Failed to decode the string %d\n",r); + kfree(cfg_str); + return -EIO; + + } + } else { + unifi_error(priv,"iwprivsapconfig argument length = 0 \n"); + return -EIO; + } + r = sme_ap_config(priv, &priv->ap_mac_config, &priv->group_sec_config); + if(r) { + unifi_error(priv,"iwprivsapstop AP Config failed : %d\n",-r); + } else if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_trace(priv, UDBG1, "iwprivsapconfig: Starting the AP"); + r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config); + if(r) { + unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r); + } + } + kfree(cfg_str); + return r; +} + +static int +iwprivsapstop(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int r; + CsrUint16 interface_tag = interfacePriv->InterfaceTag; + + unifi_trace(priv, UDBG1, "iwprivsapstop\n" ); + r = sme_ap_stop(priv,interface_tag); + if(r) { + unifi_error(priv,"iwprivsapstop AP STOP failed : %d\n",-r); + } + return r; +} + +#ifdef ANDROID_BUILD +static int +iwprivsapfwreload(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + unifi_trace(priv, UDBG1, "iwprivsapfwreload\n" ); + return 0; +} + +static int +iwprivsstackstart(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + unifi_trace(priv, UDBG1, "iwprivsstackstart\n" ); + return 0; +} + +static int +iwprivsstackstop(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int r = 0; + CsrUint16 interface_tag = interfacePriv->InterfaceTag; + + unifi_trace(priv, UDBG1, "iwprivsstackstop\n" ); + + switch(interfacePriv->interfaceMode) { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + r = sme_mgt_disconnect(priv); + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + r = sme_ap_stop(priv,interface_tag); + break; + default : + break; + } + + if(r) { + unifi_error(priv,"iwprivsstackstop Stack stop failed : %d\n",-r); + } + return 0; +} +#endif /* ANDROID_BUILD */ +#endif /* CSR_SUPPORT_WEXT_AP */ + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE +static int +iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + CsrUint8 enable; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + func_enter(); + + unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" ); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + enable = *(CsrUint8*)(extra); + + if (enable) { + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI); + priv->connection_config.encryptionModeMask |= + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4; + } else { + priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI); + priv->connection_config.encryptionModeMask &= + ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4); + } + + func_exit(); + return 0; +} + +static int +iwprivswpikey(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int r = 0, i; + CsrWifiSmeKey key; + unifiio_wapi_key_t inKey; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + func_enter(); + + unifi_trace(priv, UDBG1, "iwprivswpikey\n" ); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + inKey = *(unifiio_wapi_key_t*)(extra); + + if (inKey.unicastKey) { + key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; + } else { + key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; + } + + key.keyIndex = inKey.keyIndex; + + /* memcpy(key.keyRsc, inKey.keyRsc, 16); */ + for (i = 0; i < 16; i+= 2) + { + key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i]; + } + + memcpy(key.address.a, inKey.address, 6); + key.keyLength = 32; + memcpy(key.key, inKey.key, 32); + key.authenticator = 0; + key.wepTxKey = 0; + + unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, " + "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey, + key.keyRsc[0], key.keyRsc[7], key.authenticator, + key.address.a[0], key.address.a[5], key.keyLength, key.key[0], + key.key[15]); + + r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD); + if (r) { + unifi_error(priv, "SETKEYS request was rejected with result %d\n", r); + return convert_sme_error(r); + } + + func_exit(); + return r; +} +#endif + + +static int +unifi_giwname(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + char *name = wrqu->name; + unifi_trace(priv, UDBG2, "unifi_giwname\n"); + + if (priv->if_index == CSR_INDEX_5G) { + strcpy(name, "IEEE 802.11-a"); + } else { + strcpy(name, "IEEE 802.11-bgn"); + } + return 0; +} /* unifi_giwname() */ + + +static int +unifi_siwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_freq *freq = (struct iw_freq *)wrqu; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_siwfreq\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + /* + * Channel is stored in the connection configuration, + * and set later when ask for a connection. + */ + if ((freq->e == 0) && (freq->m <= 1000)) { + priv->connection_config.adhocChannel = freq->m; + } else { + priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e); + } + + func_exit(); + return 0; +} /* unifi_siwfreq() */ + + +static int +unifi_giwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_freq *freq = (struct iw_freq *)wrqu; + int err = 0; + CsrWifiSmeConnectionInfo connectionInfo; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_giwfreq\n"); + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + UF_RTNL_UNLOCK(); + err = sme_mgt_connection_info_get(priv, &connectionInfo); + UF_RTNL_LOCK(); + + freq->m = channel_to_mhz(connectionInfo.channelNumber, + (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0)); + freq->e = 6; + + func_exit(); + return convert_sme_error(err); +} /* unifi_giwfreq() */ + + +static int +unifi_siwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_siwmode\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + switch(wrqu->mode) { + case IW_MODE_ADHOC: + priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC; + break; + case IW_MODE_INFRA: + priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE; + break; + case IW_MODE_AUTO: + priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS; + break; + default: + unifi_notice(priv, "Unknown IW MODE value.\n"); + } + + /* Clear the SSID and BSSID configuration */ + priv->connection_config.ssid.length = 0; + memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN); + + func_exit(); + return 0; +} /* unifi_siwmode() */ + + + +static int +unifi_giwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int r = 0; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + CsrWifiSmeConnectionConfig connectionConfig; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_giwmode\n"); + CHECK_INITED(priv); + + unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n", + interfacePriv->interfaceMode); + switch(interfacePriv->interfaceMode) { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + wrqu->mode = IW_MODE_INFRA; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + wrqu->mode = IW_MODE_MASTER; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + wrqu->mode = IW_MODE_ADHOC; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_P2P: + case CSR_WIFI_ROUTER_CTRL_MODE_NONE: + UF_RTNL_UNLOCK(); + r = sme_mgt_connection_config_get(priv, &connectionConfig); + UF_RTNL_LOCK(); + if (r == 0) { + switch(connectionConfig.bssType) { + case CSR_WIFI_SME_BSS_TYPE_ADHOC: + wrqu->mode = IW_MODE_ADHOC; + break; + case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: + wrqu->mode = IW_MODE_INFRA; + break; + default: + wrqu->mode = IW_MODE_AUTO; + unifi_notice(priv, "Unknown IW MODE value.\n"); + } + } + break; + default: + wrqu->mode = IW_MODE_AUTO; + unifi_notice(priv, "Unknown IW MODE value.\n"); + + } + unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode); + func_exit(); + return r; +} /* unifi_giwmode() */ + + + +static int +unifi_giwrange(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + struct iw_range *range = (struct iw_range *) extra; + int i; + + unifi_trace(NULL, UDBG2, "unifi_giwrange\n"); + + dwrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(*range)); + range->min_nwid = 0x0000; + range->max_nwid = 0x0000; + + /* + * Don't report the frequency/channel table, then the channel + * number returned elsewhere will be printed as a channel number. + */ + + /* Ranges of values reported in quality structs */ + range->max_qual.qual = 40; /* Max expected qual value */ + range->max_qual.level = -120; /* Noise floor in dBm */ + range->max_qual.noise = -120; /* Noise floor in dBm */ + + + /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */ + i = 0; +#if WIRELESS_EXT > 15 + range->bitrate[i++] = 2 * 500000; + range->bitrate[i++] = 4 * 500000; + range->bitrate[i++] = 11 * 500000; + range->bitrate[i++] = 22 * 500000; + range->bitrate[i++] = 12 * 500000; + range->bitrate[i++] = 18 * 500000; + range->bitrate[i++] = 24 * 500000; + range->bitrate[i++] = 36 * 500000; + range->bitrate[i++] = 48 * 500000; + range->bitrate[i++] = 72 * 500000; + range->bitrate[i++] = 96 * 500000; + range->bitrate[i++] = 108 * 500000; +#else + range->bitrate[i++] = 2 * 500000; + range->bitrate[i++] = 4 * 500000; + range->bitrate[i++] = 11 * 500000; + range->bitrate[i++] = 22 * 500000; + range->bitrate[i++] = 24 * 500000; + range->bitrate[i++] = 48 * 500000; + range->bitrate[i++] = 96 * 500000; + range->bitrate[i++] = 108 * 500000; +#endif /* WIRELESS_EXT < 16 */ + range->num_bitrates = i; + + range->max_encoding_tokens = NUM_WEPKEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->we_version_source = 20; + range->we_version_compiled = WIRELESS_EXT; + + /* Number of channels available in h/w */ + range->num_channels = 14; + /* Number of entries in freq[] array */ + range->num_frequency = 14; + for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) { + int chan = i + 1; + range->freq[i].i = chan; + range->freq[i].m = channel_to_mhz(chan, 0); + range->freq[i].e = 6; + } + if ((i+3) < IW_MAX_FREQUENCIES) { + range->freq[i].i = 36; + range->freq[i].m = channel_to_mhz(36, 1); + range->freq[i].e = 6; + range->freq[i+1].i = 40; + range->freq[i+1].m = channel_to_mhz(40, 1); + range->freq[i+1].e = 6; + range->freq[i+2].i = 44; + range->freq[i+2].m = channel_to_mhz(44, 1); + range->freq[i+2].e = 6; + range->freq[i+3].i = 48; + range->freq[i+3].m = channel_to_mhz(48, 1); + range->freq[i+3].e = 6; + } + +#if WIRELESS_EXT > 16 + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) | + IW_EVENT_CAPA_MASK(IWEVREGISTERED) | + IW_EVENT_CAPA_MASK(IWEVEXPIRED)); +#endif /* WIRELESS_EXT > 16 */ + +#if WIRELESS_EXT > 17 + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif /* WIRELESS_EXT > 17 */ + + + return 0; +} /* unifi_giwrange() */ + + +static int +unifi_siwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int err = 0; + const unsigned char zero_bssid[ETH_ALEN] = {0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + func_enter(); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) { + return -EINVAL; + } + + unifi_trace(priv, UDBG1, "unifi_siwap: asked for %02X:%02X:%02X:%02X:%02X:%02X\n", + (u8)wrqu->ap_addr.sa_data[0], + (u8)wrqu->ap_addr.sa_data[1], + (u8)wrqu->ap_addr.sa_data[2], + (u8)wrqu->ap_addr.sa_data[3], + (u8)wrqu->ap_addr.sa_data[4], + (u8)wrqu->ap_addr.sa_data[5]); + + if (!memcmp(wrqu->ap_addr.sa_data, zero_bssid, ETH_ALEN)) { + priv->ignore_bssid_join = FALSE; + err = sme_mgt_disconnect(priv); + if (err) { + unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err); + } + return 0; + } + + if (priv->ignore_bssid_join) { + unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n"); + priv->ignore_bssid_join = FALSE; + } else { + memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN); + unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n", + priv->connection_config.bssid.a[0], + priv->connection_config.bssid.a[1], + priv->connection_config.bssid.a[2], + priv->connection_config.bssid.a[3], + priv->connection_config.bssid.a[4], + priv->connection_config.bssid.a[5]); + err = sme_mgt_connect(priv); + if (err) { + unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err); + func_exit(); + return convert_sme_error(err); + } + } + func_exit(); + + return 0; +} /* unifi_siwap() */ + + +static int +unifi_giwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + CsrWifiSmeConnectionInfo connectionInfo; + int r = 0; + CsrUint8 *bssid; + + func_enter(); + + CHECK_INITED(priv); + unifi_trace(priv, UDBG2, "unifi_giwap\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + UF_RTNL_UNLOCK(); + r = sme_mgt_connection_info_get(priv, &connectionInfo); + UF_RTNL_LOCK(); + + if (r == 0) { + bssid = connectionInfo.bssid.a; + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + unifi_trace(priv, UDBG4, + "unifi_giwap: BSSID = %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5]); + + memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN); + } else { + memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); + } + + func_exit(); + return 0; +} /* unifi_giwap() */ + + +static int +unifi_siwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int scantype; + int r; + CsrWifiSsid scan_ssid; + unsigned char *channel_list = NULL; + int chans_good = 0; +#if WIRELESS_EXT > 17 + struct iw_point *data = &wrqu->data; + struct iw_scan_req *req = (struct iw_scan_req *) extra; +#endif + + func_enter(); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + scantype = UNIFI_SCAN_ACTIVE; + +#if WIRELESS_EXT > 17 + /* Providing a valid channel list will force an active scan */ + if (req) { + if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) { + channel_list = kmalloc(req->num_channels, GFP_KERNEL); + if (channel_list) { + int i; + for (i = 0; i < req->num_channels; i++) { + /* Convert frequency to channel number */ + int ch = wext_freq_to_channel(req->channel_list[i].m, + req->channel_list[i].e); + if (ch) { + channel_list[chans_good++] = ch; + } + } + unifi_trace(priv, UDBG1, + "SIWSCAN: Scanning %d channels\n", chans_good); + } else { + /* Fall back to scanning all */ + unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n", + req->num_channels); + } + } + } + + if (req && (data->flags & IW_SCAN_THIS_ESSID)) { + memcpy(scan_ssid.ssid, req->essid, req->essid_len); + scan_ssid.length = req->essid_len; + unifi_trace(priv, UDBG1, + "SIWSCAN: Scanning for %.*s\n", + scan_ssid.length, scan_ssid.ssid); + } else +#endif + { + unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n"); + scan_ssid.length = 0; + } + + r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list); + if (r) { + unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r); + } else { + unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n"); + wext_send_scan_results_event(priv); + } + + if (channel_list) { + kfree(channel_list); + } + + func_exit(); + return r; + +} /* unifi_siwscan() */ + + +static const unsigned char * +unifi_find_info_element(int id, const unsigned char *info, int len) +{ + const unsigned char *ie = info; + + while (len > 1) + { + int e_id, e_len; + e_id = ie[0]; + e_len = ie[1]; + + /* Return if we find a match */ + if (e_id == id) + { + return ie; + } + + len -= (e_len + 2); + ie += (e_len + 2); + } + + return NULL; +} /* unifi_find_info_element() */ + + +/* + * Translate scan data returned from the card to a card independent + * format that the Wireless Tools will understand - Jean II + */ +int +unifi_translate_scan(struct net_device *dev, + struct iw_request_info *info, + char *current_ev, char *end_buf, + CsrWifiSmeScanResult *scan_data, + int scan_index) +{ + struct iw_event iwe; /* Temporary buffer */ + unsigned char *info_elems; + int info_elem_len; + const unsigned char *elem; + u16 capabilities; + int signal, noise, snr; + char *start_buf = current_ev; + char *current_val; /* For rates */ + int i, r; + + info_elems = scan_data->informationElements; + info_elem_len = scan_data->informationElementsLength; + + if (!scan_data->informationElementsLength || !scan_data->informationElements) { + unifi_error(NULL, "*** NULL SCAN IEs ***\n"); + return -EIO; + } + + /* get capinfo bits */ + capabilities = scan_data->capabilityInformation; + + unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities); + + /* First entry *MUST* be the AP MAC address */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN); + iwe.len = IW_EV_ADDR_LEN; + r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN); + if (r < 0) { + return r; + } + start_buf += r; + + /* Other entries will be displayed in the order we give them */ + + /* Add the ESSID */ + /* find SSID in Info Elems */ + elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len); + if (elem) { + int e_len = elem[1]; + const unsigned char *e_ptr = elem + 2; + unsigned char buf[33]; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.essid.length = e_len; + if (iwe.u.essid.length > 32) { + iwe.u.essid.length = 32; + } + iwe.u.essid.flags = scan_index; + memcpy(buf, e_ptr, iwe.u.essid.length); + buf[iwe.u.essid.length] = '\0'; + r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf); + if (r < 0) { + return r; + } + start_buf += r; + + } + + /* Add mode */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) { + iwe.u.mode = IW_MODE_INFRA; + } else { + iwe.u.mode = IW_MODE_ADHOC; + } + iwe.len = IW_EV_UINT_LEN; + r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN); + if (r < 0) { + return r; + } + start_buf += r; + + /* Add frequency. iwlist will convert to channel using table given in giwrange */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = scan_data->channelFrequency; + iwe.u.freq.e = 6; + r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN); + if (r < 0) { + return r; + } + start_buf += r; + + + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + /* + * level and noise below are mapped into an unsigned 8 bit number, + * ranging from [-192; 63]. The way this is achieved is simply to + * add 0x100 onto the number if it is negative, + * once clipped to the correct range. + */ + signal = scan_data->rssi; /* This value is in dBm */ + /* Clip range of snr */ + snr = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */ + snr = (snr < 255) ? snr : 255; + noise = signal - snr; + + /* Clip range of signal */ + signal = (signal < 63) ? signal : 63; + signal = (signal > -192) ? signal : -192; + + /* Clip range of noise */ + noise = (noise < 63) ? noise : 63; + noise = (noise > -192) ? noise : -192; + + /* Make u8 */ + signal = ( signal < 0 ) ? signal + 0x100 : signal; + noise = ( noise < 0 ) ? noise + 0x100 : noise; + + iwe.u.qual.level = (u8)signal; /* -192 : 63 */ + iwe.u.qual.noise = (u8)noise; /* -192 : 63 */ + iwe.u.qual.qual = snr; /* 0 : 255 */ + iwe.u.qual.updated = 0; +#if WIRELESS_EXT > 16 + iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED | + IW_QUAL_QUAL_UPDATED; +#if WIRELESS_EXT > 18 + iwe.u.qual.updated |= IW_QUAL_DBM; +#endif +#endif + r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN); + if (r < 0) { + return r; + } + start_buf += r; + + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if (capabilities & SIG_CAP_PRIVACY) { + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + } else { + iwe.u.data.flags = IW_ENCODE_DISABLED; + } + iwe.u.data.length = 0; + iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; + r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, ""); + if (r < 0) { + return r; + } + start_buf += r; + + + /* + * Rate : stuffing multiple values in a single event require a bit + * more of magic - Jean II + */ + current_val = start_buf + IW_EV_LCP_LEN; + + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + + elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID, + info_elems, info_elem_len); + if (elem) { + int e_len = elem[1]; + const unsigned char *e_ptr = elem + 2; + + /* + * Count how many rates we have. + * Zero marks the end of the list, if the list is not truncated. + */ + /* Max 8 values */ + for (i = 0; i < e_len; i++) { + if (e_ptr[i] == 0) { + break; + } + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000); + /* Add new value to event */ + r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + if (r < 0) { + return r; + } + current_val +=r; + + } + } + elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID, + info_elems, info_elem_len); + if (elem) { + int e_len = elem[1]; + const unsigned char *e_ptr = elem + 2; + + /* + * Count how many rates we have. + * Zero marks the end of the list, if the list is not truncated. + */ + /* Max 8 values */ + for (i = 0; i < e_len; i++) { + if (e_ptr[i] == 0) { + break; + } + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000); + /* Add new value to event */ + r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + if (r < 0) { + return r; + } + current_val +=r; + } + } + /* Check if we added any rates event */ + if ((current_val - start_buf) > IW_EV_LCP_LEN) { + start_buf = current_val; + } + + +#if WIRELESS_EXT > 17 + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = info_elem_len; + + r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems); + if (r < 0) { + return r; + } + + start_buf += r; +#endif /* WE > 17 */ + + return (start_buf - current_ev); +} /* unifi_translate_scan() */ + + + +static int +unifi_giwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_point *dwrq = &wrqu->data; + int r; + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + unifi_trace(priv, UDBG1, + "unifi_giwscan: buffer (%d bytes) \n", + dwrq->length); + UF_RTNL_UNLOCK(); + r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length); + UF_RTNL_LOCK(); + if (r < 0) { + unifi_trace(priv, UDBG1, + "unifi_giwscan: buffer (%d bytes) not big enough.\n", + dwrq->length); + return r; + } + + dwrq->length = r; + dwrq->flags = 0; + + return 0; +} /* unifi_giwscan() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_siwessid + * + * Request to join a network or start and AdHoc. + * + * Arguments: + * dev Pointer to network device struct. + * info Pointer to broken-out ioctl request. + * data Pointer to argument data. + * essid Pointer to string giving name of network to join + * or start + * + * Returns: + * 0 on success and everything complete + * -EINPROGRESS to have the higher level call the commit method. + * --------------------------------------------------------------------------- + */ +static int +unifi_siwessid(struct net_device *dev, struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int len; + int err = 0; + + func_enter(); + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + len = 0; + if (data->flags & 1) { + /* Limit length */ + len = data->length; + if (len > UNIFI_MAX_SSID_LEN) { + len = UNIFI_MAX_SSID_LEN; + } + } + +#ifdef UNIFI_DEBUG + { + char essid_str[UNIFI_MAX_SSID_LEN+1]; + int i; + + for (i = 0; i < len; i++) { + essid_str[i] = (isprint(essid[i]) ? essid[i] : '?'); + } + essid_str[i] = '\0'; + + unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len); + unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask); + } +#endif + + memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN); + if (len) { + if (essid[len - 1] == 0) { + len --; + } + + memcpy(priv->connection_config.ssid.ssid, essid, len); + priv->connection_config.ssid.length = len; + + } else { + priv->connection_config.ssid.length = 0; + } + + UF_RTNL_UNLOCK(); + err = sme_mgt_connect(priv); + UF_RTNL_LOCK(); + if (err) { + unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err); + func_exit(); + return convert_sme_error(err); + } + + func_exit(); + return 0; +} /* unifi_siwessid() */ + + +static int +unifi_giwessid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *essid) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_point *data = &wrqu->essid; + CsrWifiSmeConnectionInfo connectionInfo; + int r = 0; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_giwessid\n"); + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + UF_RTNL_UNLOCK(); + r = sme_mgt_connection_info_get(priv, &connectionInfo); + UF_RTNL_LOCK(); + + if (r == 0) { + data->length = connectionInfo.ssid.length; + strncpy(essid, + connectionInfo.ssid.ssid, + data->length); + data->flags = 1; /* active */ + + unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n", + data->length, essid); + } + + func_exit(); + + return 0; +} /* unifi_giwessid() */ + + +static int +unifi_siwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_param *args = &wrqu->bitrate; + CsrWifiSmeMibConfig mibConfig; + int r; + + func_enter(); + + CHECK_INITED(priv); + unifi_trace(priv, UDBG2, "unifi_siwrate\n"); + + /* + * If args->fixed == 0, value is max rate or -1 for best + * If args->fixed == 1, value is rate to set or -1 for best + * args->disabled and args->flags are not used in SIOCSIWRATE + */ + + /* Get, modify and set the MIB data */ + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + /* Default to auto rate algorithm */ + /* in 500Kbit/s, 0 means auto */ + mibConfig.unifiFixTxDataRate = 0; + + if (args->value != -1) { + mibConfig.unifiFixTxDataRate = args->value / 500000; + } + + /* 1 means rate is a maximum, 2 means rate is a set value */ + if (args->fixed == 1) { + mibConfig.unifiFixMaxTxDataRate = 0; + } else { + mibConfig.unifiFixMaxTxDataRate = 1; + } + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_set(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + func_exit(); + + return 0; +} /* unifi_siwrate() */ + + + +static int +unifi_giwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_param *args = &wrqu->bitrate; + int r; + int bitrate, flag; + CsrWifiSmeMibConfig mibConfig; + CsrWifiSmeConnectionStats connectionStats; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_giwrate\n"); + CHECK_INITED(priv); + + flag = 0; + bitrate = 0; + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + bitrate = mibConfig.unifiFixTxDataRate; + flag = mibConfig.unifiFixMaxTxDataRate; + + /* Used the value returned by the SME if MIB returns 0 */ + if (bitrate == 0) { + UF_RTNL_UNLOCK(); + r = sme_mgt_connection_stats_get(priv, &connectionStats); + UF_RTNL_LOCK(); + /* Ignore errors, we may be disconnected */ + if (r == 0) { + bitrate = connectionStats.unifiTxDataRate; + } + } + + args->value = bitrate * 500000; + args->fixed = !flag; + + func_exit(); + + return 0; +} /* unifi_giwrate() */ + + +static int +unifi_siwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int val = wrqu->rts.value; + int r = 0; + CsrWifiSmeMibConfig mibConfig; + + unifi_trace(priv, UDBG2, "unifi_siwrts\n"); + CHECK_INITED(priv); + + if (wrqu->rts.disabled) { + val = 2347; + } + + if ( (val < 0) || (val > 2347) ) + { + return -EINVAL; + } + + /* Get, modify and set the MIB data */ + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + mibConfig.dot11RtsThreshold = val; + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_set(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + return 0; +} + + +static int +unifi_giwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int r; + int rts_thresh; + CsrWifiSmeMibConfig mibConfig; + + unifi_trace(priv, UDBG2, "unifi_giwrts\n"); + CHECK_INITED(priv); + + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + rts_thresh = mibConfig.dot11RtsThreshold; + if (rts_thresh > 2347) { + rts_thresh = 2347; + } + + wrqu->rts.value = rts_thresh; + wrqu->rts.disabled = (rts_thresh == 2347); + wrqu->rts.fixed = 1; + + return 0; +} + + +static int +unifi_siwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int val = wrqu->frag.value; + int r = 0; + CsrWifiSmeMibConfig mibConfig; + + unifi_trace(priv, UDBG2, "unifi_siwfrag\n"); + CHECK_INITED(priv); + + if (wrqu->frag.disabled) + val = 2346; + + if ( (val < 256) || (val > 2347) ) + return -EINVAL; + + /* Get, modify and set the MIB data */ + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + /* Fragmentation Threashold must be even */ + mibConfig.dot11FragmentationThreshold = (val & ~0x1); + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_set(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + return 0; +} + + +static int +unifi_giwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int r; + int frag_thresh; + CsrWifiSmeMibConfig mibConfig; + + unifi_trace(priv, UDBG2, "unifi_giwfrag\n"); + CHECK_INITED(priv); + + UF_RTNL_UNLOCK(); + r = sme_mgt_mib_config_get(priv, &mibConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n"); + return r; + } + + frag_thresh = mibConfig.dot11FragmentationThreshold; + + /* Build the return structure */ + wrqu->frag.value = frag_thresh; + wrqu->frag.disabled = (frag_thresh >= 2346); + wrqu->frag.fixed = 1; + + return 0; +} + + +static int +unifi_siwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_point *erq = &wrqu->encoding; + int index; + int rc = 0; + int privacy = -1; + CsrWifiSmeKey sme_key; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_siwencode\n"); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + /* + * Key index is encoded in the flags. + * 0 - use current default, + * 1-4 - if a key value is given set that key + * if not use that key + */ + index = (erq->flags & IW_ENCODE_INDEX); /* key number, 1-4 */ + if ((index < 0) || (index > 4)) { + unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index); + return -EINVAL; + } + + /* + * Basic checking: do we have a key to set ? + * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags), + * but older versions rely on sending a key id 1-4. + */ + if (erq->length > 0) { + + /* Check the size of the key */ + if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) { + unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)", + erq->length); + return -EINVAL; + } + + /* Check the index (none (i.e. 0) means use current) */ + if ((index < 1) || (index > 4)) { + /* If we do not have a previous key, use 1 as default */ + if (!priv->wep_tx_key_index) { + priv->wep_tx_key_index = 1; + } + index = priv->wep_tx_key_index; + } + + /* If we didn't have a key and a valid index is set, we want to remember it*/ + if (!priv->wep_tx_key_index) { + priv->wep_tx_key_index = index; + } + + unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index); + + privacy = 1; + + /* Check if the key is not marked as invalid */ + if ((erq->flags & IW_ENCODE_NOKEY) == 0) { + + unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n", + (priv->wep_tx_key_index == index) ? "tx" : "", + erq->length, index); + + sme_key.wepTxKey = (priv->wep_tx_key_index == index); + if (priv->wep_tx_key_index == index) { + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; + } else { + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; + } + /* Key index is zero based in SME but 1 based in wext */ + sme_key.keyIndex = (index - 1); + sme_key.keyLength = erq->length; + sme_key.authenticator = 0; + memset(sme_key.address.a, 0xFF, ETH_ALEN); + memcpy(sme_key.key, extra, erq->length); + + UF_RTNL_UNLOCK(); + rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); + UF_RTNL_LOCK(); + if (rc) { + unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc); + return convert_sme_error(rc); + } + + /* Store the key to be reported by the SIOCGIWENCODE handler */ + priv->wep_keys[index - 1].len = erq->length; + memcpy(priv->wep_keys[index - 1].key, extra, erq->length); + } + } else { + /* + * No additional key data, so it must be a request to change the + * active key. + */ + if (index != 0) { + unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1); + + /* Store the index to be reported by the SIOCGIWENCODE handler */ + priv->wep_tx_key_index = index; + + sme_key.wepTxKey = 1; + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; + + /* Key index is zero based in SME but 1 based in wext */ + sme_key.keyIndex = (index - 1); + sme_key.keyLength = 0; + sme_key.authenticator = 0; + UF_RTNL_UNLOCK(); + rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); + UF_RTNL_LOCK(); + if (rc) { + unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc); + return convert_sme_error(rc); + } + + /* Turn on encryption */ + privacy = 1; + } + } + + /* Read the flags */ + if (erq->flags & IW_ENCODE_DISABLED) { + /* disable encryption */ + unifi_trace(priv, UDBG1, "disable WEP encryption\n"); + privacy = 0; + + priv->wep_tx_key_index = 0; + + unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + } + + if (erq->flags & IW_ENCODE_RESTRICTED) { + /* Use shared key auth */ + unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n"); + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED; + + /* Turn on encryption */ + privacy = 1; + } + if (erq->flags & IW_ENCODE_OPEN) { + unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + } + + /* Commit the changes to flags if needed */ + if (privacy != -1) { + priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; + priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 | + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) : + CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; + } + + func_exit_r(rc); + return convert_sme_error(rc); + +} /* unifi_siwencode() */ + + + +static int +unifi_giwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_point *erq = &wrqu->encoding; + + unifi_trace(priv, UDBG2, "unifi_giwencode\n"); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) { + erq->flags = IW_ENCODE_RESTRICTED; + } + else { + if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) { + erq->flags = IW_ENCODE_DISABLED; + } else { + erq->flags = IW_ENCODE_OPEN; + } + } + + erq->length = 0; + + if (erq->flags != IW_ENCODE_DISABLED) { + int index = priv->wep_tx_key_index; + + if ((index > 0) && (index <= NUM_WEPKEYS)) { + erq->flags |= (index & IW_ENCODE_INDEX); + erq->length = priv->wep_keys[index - 1].len; + memcpy(extra, priv->wep_keys[index - 1].key, erq->length); + } else { + unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n", + index); + } + } + + return 0; +} /* unifi_giwencode() */ + + +static int +unifi_siwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_param *args = &wrqu->power; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int listen_interval, wake_for_dtim; + int r = 0; + CsrWifiSmePowerConfig powerConfig; + + unifi_trace(priv, UDBG2, "unifi_siwpower\n"); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + UF_RTNL_UNLOCK(); + r = sme_mgt_power_config_get(priv, &powerConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n"); + return r; + } + + listen_interval = -1; + wake_for_dtim = -1; + if (args->disabled) { + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; + } + else + { + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; + + switch (args->flags & IW_POWER_TYPE) { + case 0: + /* not specified */ + break; + case IW_POWER_PERIOD: + listen_interval = args->value / 1000; + break; + default: + return -EINVAL; + } + + switch (args->flags & IW_POWER_MODE) { + case 0: + /* not specified */ + break; + case IW_POWER_UNICAST_R: + /* not interested in broadcast packets */ + wake_for_dtim = 0; + break; + case IW_POWER_ALL_R: + /* yes, we are interested in broadcast packets */ + wake_for_dtim = 1; + break; + default: + return -EINVAL; + } + } + + if (listen_interval > 0) { + powerConfig.listenIntervalTu = listen_interval; + unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n", + powerConfig.listenIntervalTu); + } + + if (wake_for_dtim >= 0) { + powerConfig.rxDtims = wake_for_dtim; + } + UF_RTNL_UNLOCK(); + r = sme_mgt_power_config_set(priv, &powerConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n"); + return r; + } + + return 0; +} /* unifi_siwpower() */ + + +static int +unifi_giwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_param *args = &wrqu->power; + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + CsrWifiSmePowerConfig powerConfig; + int r; + + unifi_trace(priv, UDBG2, "unifi_giwpower\n"); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + args->flags = 0; + UF_RTNL_UNLOCK(); + r = sme_mgt_power_config_get(priv, &powerConfig); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n"); + return r; + } + + unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n", + powerConfig.powerSaveLevel); + + args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW); + if (args->disabled) { + args->flags = 0; + return 0; + } + + args->value = powerConfig.listenIntervalTu * 1000; + args->flags |= IW_POWER_PERIOD; + + if (powerConfig.rxDtims) { + args->flags |= IW_POWER_ALL_R; + } else { + args->flags |= IW_POWER_UNICAST_R; + } + + return 0; +} /* unifi_giwpower() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_siwcommit - handler for SIOCSIWCOMMIT + * + * Apply all the parameters that have been set. + * In practice this means: + * - do a scan + * - join a network or start an AdHoc + * - authenticate and associate. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static int +unifi_siwcommit(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return 0; +} /* unifi_siwcommit() */ + + + +static int +unifi_siwmlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + func_enter(); + + unifi_trace(priv, UDBG2, "unifi_siwmlme\n"); + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + case IW_MLME_DISASSOC: + UF_RTNL_UNLOCK(); + sme_mgt_disconnect(priv); + UF_RTNL_LOCK(); + break; + default: + func_exit_r(-EOPNOTSUPP); + return -EOPNOTSUPP; + } + + func_exit(); + return 0; +} /* unifi_siwmlme() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_siwgenie + * unifi_giwgenie + * + * WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM). + * Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE + * + * The host program (e.g. wpa_supplicant) uses this call to set the + * additional IEs to accompany the next (Associate?) request. + * + * Arguments: + * None. + * + * Returns: + * None. + * Notes: + * From wireless.h: + * This ioctl uses struct iw_point and data buffer that includes IE id + * and len fields. More than one IE may be included in the + * request. Setting the generic IE to empty buffer (len=0) removes the + * generic IE from the driver. + * --------------------------------------------------------------------------- + */ +static int +unifi_siwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int len; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_siwgenie\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + if ( priv->connection_config.mlmeAssociateReqInformationElements) { + kfree( priv->connection_config.mlmeAssociateReqInformationElements); + } + priv->connection_config.mlmeAssociateReqInformationElementsLength = 0; + priv->connection_config.mlmeAssociateReqInformationElements = NULL; + + len = wrqu->data.length; + if (len == 0) { + func_exit(); + return 0; + } + + priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL); + if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) { + func_exit(); + return -ENOMEM; + } + + priv->connection_config.mlmeAssociateReqInformationElementsLength = len; + memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len); + + func_exit(); + return 0; +} /* unifi_siwgenie() */ + + +static int +unifi_giwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + int len; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_giwgenie\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + len = priv->connection_config.mlmeAssociateReqInformationElementsLength; + + if (len == 0) { + wrqu->data.length = 0; + return 0; + } + + if (wrqu->data.length < len) { + return -E2BIG; + } + + wrqu->data.length = len; + memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len); + + func_exit(); + return 0; +} /* unifi_giwgenie() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_siwauth + * unifi_giwauth + * + * Handlers for SIOCSIWAUTH, SIOCGIWAUTH + * Set/get various authentication parameters. + * + * Arguments: + * + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static int +_unifi_siwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + CsrWifiSmeAuthModeMask new_auth; + + func_enter(); + unifi_trace(priv, UDBG2, "unifi_siwauth\n"); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + /* + * This ioctl is safe to call even when UniFi is powered off. + * wpa_supplicant calls it to test whether we support WPA. + */ + + switch (wrqu->param.flags & IW_AUTH_INDEX) { + + case IW_AUTH_WPA_ENABLED: + unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value); + + if (wrqu->param.value == 0) { + unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + } + break; + + case IW_AUTH_PRIVACY_INVOKED: + unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value); + + priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; + if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) + { + priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; + } + break; + + case IW_AUTH_80211_AUTH_ALG: + /* + IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 + IW_AUTH_ALG_SHARED_KEY 0x00000002 + IW_AUTH_ALG_LEAP 0x00000004 + */ + new_auth = 0; + if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) { + unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value); + new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + } + if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) { + unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value); + new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED; + } + if (wrqu->param.value & IW_AUTH_ALG_LEAP) { + /* Initial exchanges using open-system to set EAP */ + unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value); + new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X; + } + if (new_auth == 0) { + unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n", + wrqu->param.value); + return -EINVAL; + } else { + priv->connection_config.authModeMask = new_auth; + } + break; + + case IW_AUTH_WPA_VERSION: + unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value); + priv->ignore_bssid_join = TRUE; + /* + IW_AUTH_WPA_VERSION_DISABLED 0x00000001 + IW_AUTH_WPA_VERSION_WPA 0x00000002 + IW_AUTH_WPA_VERSION_WPA2 0x00000004 + */ + + if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) { + + priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; + + if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) { + unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n"); + priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK); + } + if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) { + unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n"); + priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK); + } + } + break; + + case IW_AUTH_CIPHER_PAIRWISE: + unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value); + /* + * one of: + IW_AUTH_CIPHER_NONE 0x00000001 + IW_AUTH_CIPHER_WEP40 0x00000002 + IW_AUTH_CIPHER_TKIP 0x00000004 + IW_AUTH_CIPHER_CCMP 0x00000008 + IW_AUTH_CIPHER_WEP104 0x00000010 + */ + + priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; + + if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) { + priv->connection_config.encryptionModeMask |= + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40; + } + if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) { + priv->connection_config.encryptionModeMask |= + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104; + } + if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) { + priv->connection_config.encryptionModeMask |= + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP; + } + if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) { + priv->connection_config.encryptionModeMask |= + CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP; + } + + break; + + case IW_AUTH_CIPHER_GROUP: + unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value); + /* + * Use the WPA version and the group cipher suite to set the permitted + * group key in the MIB. f/w uses this value to validate WPA and RSN IEs + * in the probe responses from the desired BSS(ID) + */ + + priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 | + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 | + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP | + CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP); + if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) { + priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40; + } + if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) { + priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104; + } + if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) { + priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP; + } + if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) { + priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP; + } + + break; + + case IW_AUTH_KEY_MGMT: + unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value); + /* + IW_AUTH_KEY_MGMT_802_1X 1 + IW_AUTH_KEY_MGMT_PSK 2 + */ + if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) { + /* Check for explicitly set mode. */ + if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) { + priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK; + } + if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) { + priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA; + } + unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n", + priv->connection_config.authModeMask); + } + if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) { + /* Check for explicitly set mode. */ + if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) { + priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK; + } + if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) { + priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2; + } + unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n", + priv->connection_config.authModeMask); + } + + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + /* + * Set to true at the start of the 60 second backup-off period + * following 2 MichaelMIC failures within 60s. + */ + unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value); + break; + + case IW_AUTH_DROP_UNENCRYPTED: + /* + * Set to true on init. + * Set to false just before associate if encryption will not be + * required. + * + * Note this is not the same as the 802.1X controlled port + */ + unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value); + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + /* + * This is set by wpa_supplicant to allow unencrypted EAPOL messages + * even if pairwise keys are set when not using WPA. IEEE 802.1X + * specifies that these frames are not encrypted, but WPA encrypts + * them when pairwise keys are in use. + * I think the UniFi f/w handles this decision for us. + */ + unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value); + break; + + case IW_AUTH_ROAMING_CONTROL: + unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value); + break; + + default: + unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n", + wrqu->param.flags & IW_AUTH_INDEX, + wrqu->param.value); + return -EOPNOTSUPP; + } + + unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask); + func_exit(); + + return 0; +} /* _unifi_siwauth() */ + + +static int +unifi_siwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int err = 0; + + UF_RTNL_UNLOCK(); + err = _unifi_siwauth(dev, info, wrqu, extra); + UF_RTNL_LOCK(); + + return err; +} /* unifi_siwauth() */ + + +static int +unifi_giwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + unifi_trace(NULL, UDBG2, "unifi_giwauth\n"); + return -EOPNOTSUPP; +} /* unifi_giwauth() */ + +/* + * --------------------------------------------------------------------------- + * unifi_siwencodeext + * unifi_giwencodeext + * + * Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get + * encoding token & mode + * + * Arguments: + * None. + * + * Returns: + * None. + * + * Notes: + * For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag. + * This flag means "use this key to encode transmissions"; we just + * assume only one key will be set and that is the one to use. + * --------------------------------------------------------------------------- + */ +static int +_unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int r = 0; + unsigned char *keydata; + unsigned char tkip_key[32]; + int keyid; + unsigned char *a = (unsigned char *)ext->addr.sa_data; + CsrWifiSmeKey sme_key; + CsrWifiSmeKeyType key_type; + + func_enter(); + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n", + wrqu->encoding.flags, ext->alg, ext->ext_flags, + ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX)); + unifi_trace(priv, UDBG3, " addr=%02X:%02X:%02X:%02X:%02X:%02X\n", + a[0], a[1], a[2], a[3], a[4], a[5]); + + if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { + /* This means use a different key (given by key_idx) for Tx. */ + /* NYI */ + unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n"); + return -ENOTSUPP; + } + + memset(&sme_key, 0, sizeof(sme_key)); + + keydata = (unsigned char *)(ext + 1); + keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX); + + /* + * Check for request to delete keys for an address. + */ + /* Pick out request for no privacy. */ + if (ext->alg == IW_ENCODE_ALG_NONE) { + + unifi_trace(priv, UDBG1, "Deleting %s key %d\n", + (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE", + keyid); + + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; + } else { + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; + } + sme_key.keyIndex = (keyid - 1); + sme_key.keyLength = 0; + sme_key.authenticator = 0; + memcpy(sme_key.address.a, a, ETH_ALEN); + UF_RTNL_UNLOCK(); + r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "Delete key request was rejected with result %d\n", r); + return convert_sme_error(r); + } + + return 0; + } + + /* + * Request is to set a key, not delete + */ + + /* Pick out WEP and use set_wep_key(). */ + if (ext->alg == IW_ENCODE_ALG_WEP) { + /* WEP-40, WEP-104 */ + + /* Check for valid key length */ + if (!((ext->key_len == 5) || (ext->key_len == 13))) { + unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len); + return -EINVAL; + } + + unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n", + keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY); + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + sme_key.wepTxKey = TRUE; + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; + } else { + sme_key.wepTxKey = FALSE; + sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; + } + sme_key.keyIndex = (keyid - 1); + sme_key.keyLength = ext->key_len; + sme_key.authenticator = 0; + memset(sme_key.address.a, 0xFF, ETH_ALEN); + memcpy(sme_key.key, keydata, ext->key_len); + UF_RTNL_UNLOCK(); + r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "siwencodeext: Set key failed (%d)", r); + return convert_sme_error(r); + } + + return 0; + } + + /* + * + * If we reach here, we are dealing with a WPA/WPA2 key + * + */ + if (ext->key_len > 32) { + return -EINVAL; + } + + /* + * TKIP keys from wpa_supplicant need swapping. + * What about other supplicants (when they come along)? + */ + if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) { + memcpy(tkip_key, keydata, 16); + memcpy(tkip_key + 16, keydata + 24, 8); + memcpy(tkip_key + 24, keydata + 16, 8); + keydata = tkip_key; + } + + key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? + CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */ + CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */ + + sme_key.keyType = key_type; + sme_key.keyIndex = (keyid - 1); + sme_key.keyLength = ext->key_len; + sme_key.authenticator = 0; + memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN); + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + + unifi_trace(priv, UDBG5, "RSC first 6 bytes = %02X:%02X:%02X:%02X:%02X:%02X\n", + ext->rx_seq[0], ext->rx_seq[1], ext->rx_seq[2], ext->rx_seq[3], ext->rx_seq[4], ext->rx_seq[5]); + + /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */ + sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0]; + sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2]; + sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4]; + sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6]; + + } + + memcpy(sme_key.key, keydata, ext->key_len); + UF_RTNL_UNLOCK(); + r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "SETKEYS request was rejected with result %d\n", r); + return convert_sme_error(r); + } + + func_exit(); + return r; +} /* _unifi_siwencodeext() */ + + +static int +unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int err = 0; + + err = _unifi_siwencodeext(dev, info, wrqu, extra); + + return err; +} /* unifi_siwencodeext() */ + + +static int +unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return -EOPNOTSUPP; +} /* unifi_giwencodeext() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_siwpmksa + * + * SIOCSIWPMKSA - PMKSA cache operation + * The caller passes a pmksa structure: + * - cmd one of ADD, REMOVE, FLUSH + * - bssid MAC address + * - pmkid ID string (16 bytes) + * + * Arguments: + * None. + * + * Returns: + * None. + * + * Notes: + * This is not needed since we provide a siwgenie method. + * --------------------------------------------------------------------------- + */ +#define UNIFI_PMKID_KEY_SIZE 16 +static int +unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; + CsrResult r = 0; + CsrWifiSmePmkidList pmkid_list; + CsrWifiSmePmkid pmkid; + CsrWifiSmeListAction action; + + CHECK_INITED(priv); + + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n", + interfacePriv->interfaceMode); + return -EPERM; + } + + + unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %02x:%02x:%02x:%02x:%02x:%02x\n", + pmksa->cmd, + pmksa->bssid.sa_data[0], + pmksa->bssid.sa_data[1], + pmksa->bssid.sa_data[2], + pmksa->bssid.sa_data[3], + pmksa->bssid.sa_data[4], + pmksa->bssid.sa_data[5]); + + pmkid_list.pmkids = NULL; + switch (pmksa->cmd) { + case IW_PMKSA_ADD: + pmkid_list.pmkids = &pmkid; + action = CSR_WIFI_SME_LIST_ACTION_ADD; + pmkid_list.pmkidsCount = 1; + memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN); + memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE); + break; + case IW_PMKSA_REMOVE: + pmkid_list.pmkids = &pmkid; + action = CSR_WIFI_SME_LIST_ACTION_REMOVE; + pmkid_list.pmkidsCount = 1; + memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN); + memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE); + break; + case IW_PMKSA_FLUSH: + /* Replace current PMKID's with an empty list */ + pmkid_list.pmkidsCount = 0; + action = CSR_WIFI_SME_LIST_ACTION_FLUSH; + break; + default: + unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd); + return -EINVAL; + } + + /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */ + UF_RTNL_UNLOCK(); + r = sme_mgt_pmkid(priv, action, &pmkid_list); + UF_RTNL_LOCK(); + if (r) { + unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n"); + } + + return r; + +} /* unifi_siwpmksa() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_get_wireless_stats + * + * get_wireless_stats method for Linux wireless extensions. + * + * Arguments: + * dev Pointer to associated netdevice. + * + * Returns: + * Pointer to iw_statistics struct. + * --------------------------------------------------------------------------- + */ +struct iw_statistics * +unifi_get_wireless_stats(struct net_device *dev) +{ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + + if (priv->init_progress != UNIFI_INIT_COMPLETED) { + return NULL; + } + + return &priv->wext_wireless_stats; +} /* unifi_get_wireless_stats() */ + + +/* + * Structures to export the Wireless Handlers + */ + +static const struct iw_priv_args unifi_private_args[] = { + /*{ cmd, set_args, get_args, name } */ + { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "iwprivs80211ps" }, + { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" }, + { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_NONE, "iwprivsdefs" }, + { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" }, +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "iwprivsconfwapi" }, + { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t), + IW_PRIV_TYPE_NONE, "iwprivswpikey" }, +#endif +#ifdef CSR_SUPPORT_WEXT_AP + { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" }, + { SIOCIWSAPSTARTPRIV, 0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING,"AP_BSS_START" }, + { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, + IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" }, +#ifdef ANDROID_BUILD + { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256, + IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" }, + { SIOCIWSSTACKSTART, 0, + IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" }, + { SIOCIWSSTACKSTOP, 0, + IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" }, +#endif /* ANDROID_BUILD */ +#endif /* CSR_SUPPORT_WEXT_AP */ +}; + +static const iw_handler unifi_handler[] = +{ + (iw_handler) unifi_siwcommit, /* SIOCSIWCOMMIT */ + (iw_handler) unifi_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) unifi_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) unifi_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) unifi_siwmode, /* SIOCSIWMODE */ + (iw_handler) unifi_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) unifi_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) unifi_siwap, /* SIOCSIWAP */ + (iw_handler) unifi_giwap, /* SIOCGIWAP */ +#if WIRELESS_EXT > 17 + /* WPA : IEEE 802.11 MLME requests */ + unifi_siwmlme, /* SIOCSIWMLME, request MLME operation */ +#else + (iw_handler) NULL, /* -- hole -- */ +#endif + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) unifi_siwscan, /* SIOCSIWSCAN */ + (iw_handler) unifi_giwscan, /* SIOCGIWSCAN */ + (iw_handler) unifi_siwessid, /* SIOCSIWESSID */ + (iw_handler) unifi_giwessid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) NULL, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + unifi_siwrate, /* SIOCSIWRATE */ + unifi_giwrate, /* SIOCGIWRATE */ + unifi_siwrts, /* SIOCSIWRTS */ + unifi_giwrts, /* SIOCGIWRTS */ + unifi_siwfrag, /* SIOCSIWFRAG */ + unifi_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + unifi_siwencode, /* SIOCSIWENCODE */ + unifi_giwencode, /* SIOCGIWENCODE */ + unifi_siwpower, /* SIOCSIWPOWER */ + unifi_giwpower, /* SIOCGIWPOWER */ +#if WIRELESS_EXT > 17 + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + + /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */ + unifi_siwgenie, /* SIOCSIWGENIE */ /* set generic IE */ + unifi_giwgenie, /* SIOCGIWGENIE */ /* get generic IE */ + + /* WPA : Authentication mode parameters */ + unifi_siwauth, /* SIOCSIWAUTH */ /* set authentication mode params */ + unifi_giwauth, /* SIOCGIWAUTH */ /* get authentication mode params */ + + /* WPA : Extended version of encoding configuration */ + unifi_siwencodeext, /* SIOCSIWENCODEEXT */ /* set encoding token & mode */ + unifi_giwencodeext, /* SIOCGIWENCODEEXT */ /* get encoding token & mode */ + + /* WPA2 : PMKSA cache management */ + unifi_siwpmksa, /* SIOCSIWPMKSA */ /* PMKSA cache operation */ + (iw_handler) NULL, /* -- hole -- */ +#endif /* WIRELESS_EXT > 17 */ +}; + + +static const iw_handler unifi_private_handler[] = +{ + iwprivs80211ps, /* SIOCIWFIRSTPRIV */ + iwprivg80211ps, /* SIOCIWFIRSTPRIV + 1 */ + iwprivsdefs, /* SIOCIWFIRSTPRIV + 2 */ + (iw_handler) NULL, +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + iwprivsconfwapi, /* SIOCIWFIRSTPRIV + 4 */ + (iw_handler) NULL, /* SIOCIWFIRSTPRIV + 5 */ + iwprivswpikey, /* SIOCIWFIRSTPRIV + 6 */ +#else + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, +#endif + (iw_handler) NULL, + iwprivssmedebug, /* SIOCIWFIRSTPRIV + 8 */ +#ifdef CSR_SUPPORT_WEXT_AP + (iw_handler) NULL, + iwprivsapconfig, + (iw_handler) NULL, + iwprivsapstart, + (iw_handler) NULL, + iwprivsapstop, + (iw_handler) NULL, +#ifdef ANDROID_BUILD + iwprivsapfwreload, + (iw_handler) NULL, + iwprivsstackstart, + (iw_handler) NULL, + iwprivsstackstop, +#else + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, +#endif /* ANDROID_BUILD */ +#else + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, + (iw_handler) NULL, +#endif /* CSR_SUPPORT_WEXT_AP */ +}; + +struct iw_handler_def unifi_iw_handler_def = +{ + .num_standard = sizeof(unifi_handler) / sizeof(iw_handler), + .num_private = sizeof(unifi_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(unifi_private_args) / sizeof(struct iw_priv_args), + .standard = (iw_handler *) unifi_handler, + .private = (iw_handler *) unifi_private_handler, + .private_args = (struct iw_priv_args *) unifi_private_args, +#if IW_HANDLER_VERSION >= 6 + .get_wireless_stats = unifi_get_wireless_stats, +#endif +}; + + diff --git a/drivers/staging/csr/ul_int.c b/drivers/staging/csr/ul_int.c new file mode 100644 index 000000000000..ae14f2354362 --- /dev/null +++ b/drivers/staging/csr/ul_int.c @@ -0,0 +1,552 @@ +/* + * *************************************************************************** + * FILE: ul_int.c + * + * PURPOSE: + * Manage list of client applications using UniFi. + * + * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "unifi_priv.h" +#include "unifiio.h" +#include "unifi_os.h" + +static void free_bulkdata_buffers(unifi_priv_t *priv, bulk_data_param_t *bulkdata); +static void reset_driver_status(unifi_priv_t *priv); + +/* + * --------------------------------------------------------------------------- + * ul_init_clients + * + * Initialise the clients array to empty. + * + * Arguments: + * priv Pointer to device private context struct + * + * Returns: + * None. + * + * Notes: + * This function needs to be called before priv is stored in + * Unifi_instances[]. + * --------------------------------------------------------------------------- + */ +void +ul_init_clients(unifi_priv_t *priv) +{ + int id; + ul_client_t *ul_clients; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) + sema_init(&priv->udi_logging_mutex, 1); +#else + init_MUTEX(&priv->udi_logging_mutex); +#endif + priv->logging_client = NULL; + + ul_clients = priv->ul_clients; + + for (id = 0; id < MAX_UDI_CLIENTS; id++) { + memset(&ul_clients[id], 0, sizeof(ul_client_t)); + + ul_clients[id].client_id = id; + ul_clients[id].sender_id = UDI_SENDER_ID_BASE + (id << UDI_SENDER_ID_SHIFT); + ul_clients[id].instance = -1; + ul_clients[id].event_hook = NULL; + + INIT_LIST_HEAD(&ul_clients[id].udi_log); + init_waitqueue_head(&ul_clients[id].udi_wq); + sema_init(&ul_clients[id].udi_sem, 1); + + ul_clients[id].wake_up_wq_id = 0; + ul_clients[id].seq_no = 0; + ul_clients[id].wake_seq_no = 0; + ul_clients[id].snap_filter.count = 0; + } +} /* ul_init_clients() */ + + +/* + * --------------------------------------------------------------------------- + * ul_register_client + * + * This function registers a new ul client. + * + * Arguments: + * priv Pointer to device private context struct + * configuration Special configuration for the client. + * udi_event_clbk Callback for receiving event from unifi. + * + * Returns: + * 0 if a new clients is registered, -1 otherwise. + * --------------------------------------------------------------------------- + */ +ul_client_t * +ul_register_client(unifi_priv_t *priv, unsigned int configuration, + udi_event_t udi_event_clbk) +{ + unsigned char id, ref; + ul_client_t *ul_clients; + + ul_clients = priv->ul_clients; + + /* check for an unused entry */ + for (id = 0; id < MAX_UDI_CLIENTS; id++) { + if (ul_clients[id].udi_enabled == 0) { + ul_clients[id].instance = priv->instance; + ul_clients[id].udi_enabled = 1; + ul_clients[id].configuration = configuration; + + /* Allocate memory for the reply signal.. */ + ul_clients[id].reply_signal = (CSR_SIGNAL*) CsrPmemAlloc(sizeof(CSR_SIGNAL)); + if (ul_clients[id].reply_signal == NULL) { + unifi_error(priv, "Failed to allocate reply signal for client.\n"); + return NULL; + } + /* .. and the bulk data of the reply signal. */ + for (ref = 0; ref < UNIFI_MAX_DATA_REFERENCES; ref ++) { + ul_clients[id].reply_bulkdata[ref] = + (bulk_data_t*) CsrPmemAlloc(sizeof(bulk_data_t)); + /* If allocation fails, free allocated memory. */ + if (ul_clients[id].reply_bulkdata[ref] == NULL) { + for (; ref > 0; ref --) { + CsrPmemFree(ul_clients[id].reply_bulkdata[ref - 1]); + } + CsrPmemFree(ul_clients[id].reply_signal); + unifi_error(priv, "Failed to allocate bulk data buffers for client.\n"); + return NULL; + } + } + + /* Set the event callback. */ + ul_clients[id].event_hook = udi_event_clbk; + + unifi_trace(priv, UDBG2, "UDI %d (0x%x) registered. configuration = 0x%x\n", + id, &ul_clients[id], configuration); + return &ul_clients[id]; + } + } + return NULL; +} /* ul_register_client() */ + + +/* + * --------------------------------------------------------------------------- + * ul_deregister_client + * + * This function deregisters a blocking UDI client. + * + * Arguments: + * client Pointer to the client we deregister. + * + * Returns: + * 0 if a new clients is deregistered. + * --------------------------------------------------------------------------- + */ +int +ul_deregister_client(ul_client_t *ul_client) +{ + struct list_head *pos, *n; + udi_log_t *logptr; + unifi_priv_t *priv = uf_find_instance(ul_client->instance); + int ref; + + ul_client->instance = -1; + ul_client->event_hook = NULL; + ul_client->udi_enabled = 0; + unifi_trace(priv, UDBG5, "UDI (0x%x) deregistered.\n", ul_client); + + /* Free memory allocated for the reply signal and its bulk data. */ + CsrPmemFree(ul_client->reply_signal); + for (ref = 0; ref < UNIFI_MAX_DATA_REFERENCES; ref ++) { + CsrPmemFree(ul_client->reply_bulkdata[ref]); + } + + if (ul_client->snap_filter.count) { + ul_client->snap_filter.count = 0; + CsrPmemFree(ul_client->snap_filter.protocols); + } + + /* Free anything pending on the udi_log list */ + down(&ul_client->udi_sem); + list_for_each_safe(pos, n, &ul_client->udi_log) + { + logptr = list_entry(pos, udi_log_t, q); + list_del(pos); + kfree(logptr); + } + up(&ul_client->udi_sem); + + return 0; +} /* ul_deregister_client() */ + + + +/* + * --------------------------------------------------------------------------- + * logging_handler + * + * This function is registered with the driver core. + * It is called every time a UniFi HIP Signal is sent. It iterates over + * the list of processes interested in receiving log events and + * delivers the events to them. + * + * Arguments: + * ospriv Pointer to driver's private data. + * sigdata Pointer to the packed signal buffer. + * signal_len Length of the packed signal. + * bulkdata Pointer to the signal's bulk data. + * dir Direction of the signal + * 0 = from-host + * 1 = to-host + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +logging_handler(void *ospriv, + CsrUint8 *sigdata, CsrUint32 signal_len, + const bulk_data_param_t *bulkdata, + enum udi_log_direction direction) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + ul_client_t *client; + int dir; + + dir = (direction == UDI_LOG_FROM_HOST) ? UDI_FROM_HOST : UDI_TO_HOST; + + down(&priv->udi_logging_mutex); + client = priv->logging_client; + if (client != NULL) { + client->event_hook(client, sigdata, signal_len, + bulkdata, dir); + } + up(&priv->udi_logging_mutex); + +} /* logging_handler() */ + + + +/* + * --------------------------------------------------------------------------- + * ul_log_config_ind + * + * This function uses the client's register callback + * to indicate configuration information e.g core errors. + * + * Arguments: + * priv Pointer to driver's private data. + * conf_param Pointer to the configuration data. + * len Length of the configuration data. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len) +{ +#ifdef CSR_SUPPORT_SME + if (priv->smepriv == NULL) + { + return; + } + if ((CONFIG_IND_ERROR == (*conf_param)) && (priv->wifi_on_state == wifi_on_in_progress)) { + unifi_notice(priv, "ul_log_config_ind: wifi on in progress, suppress error\n"); + } else { + /* wifi_off_ind (error or exit) */ + CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param)); + } + +#else + bulk_data_param_t bulkdata; + + /* + * If someone killed unifi_managed before the driver was unloaded + * the g_drvpriv pointer is going to be NULL. In this case it is + * safe to assume that there is no client to get the indication. + */ + if (!priv) { + unifi_notice(NULL, "uf_sme_event_ind: NULL priv\n"); + return; + } + + /* Create a null bulkdata structure. */ + bulkdata.d[0].data_length = 0; + bulkdata.d[1].data_length = 0; + + sme_native_log_event(priv->sme_cli, conf_param, sizeof(CsrUint8), + &bulkdata, UDI_CONFIG_IND); + +#endif /* CSR_SUPPORT_SME */ + +} /* ul_log_config_ind */ + + +/* + * --------------------------------------------------------------------------- + * free_bulkdata_buffers + * + * Free the bulkdata buffers e.g. after a failed unifi_send_signal(). + * + * Arguments: + * priv Pointer to device private struct + * bulkdata Pointer to bulkdata parameter table + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +free_bulkdata_buffers(unifi_priv_t *priv, bulk_data_param_t *bulkdata) +{ + int i; + + if (bulkdata) { + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (bulk_data_desc_t *)(&bulkdata->d[i])); + /* data_length is now 0 */ + } + } + } + +} /* free_bulkdata_buffers */ + +static int +_align_bulk_data_buffers(unifi_priv_t *priv, CsrUint8 *signal, + bulk_data_param_t *bulkdata) +{ + unsigned int i; + + if ((bulkdata == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) { + return 0; + } + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) + { + struct sk_buff *skb; + /* + * The following complex casting is in place in order to eliminate 64-bit compilation warning + * "cast to/from pointer from/to integer of different size" + */ + CsrUint32 align_offset = (CsrUint32)(long)(bulkdata->d[i].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); + if (align_offset) + { + skb = (struct sk_buff*)bulkdata->d[i].os_net_buf_ptr; + if (skb == NULL) { + unifi_warning(priv, + "_align_bulk_data_buffers: Align offset found (%d) but skb is NULL!\n", + align_offset); + return -EINVAL; + } + if (bulkdata->d[i].data_length == 0) { + unifi_warning(priv, + "_align_bulk_data_buffers: Align offset found (%d) but length is zero\n", + align_offset); + return CSR_RESULT_SUCCESS; + } + unifi_trace(priv, UDBG5, + "Align f-h buffer (0x%p) by %d bytes (skb->data: 0x%p)\n", + bulkdata->d[i].os_data_ptr, align_offset, skb->data); + + + /* Check if there is enough headroom... */ + if (unlikely(skb_headroom(skb) < align_offset)) + { + struct sk_buff *tmp = skb; + + unifi_trace(priv, UDBG5, "Headroom not enough - realloc it\n"); + skb = skb_realloc_headroom(skb, align_offset); + if (skb == NULL) { + unifi_error(priv, + "_align_bulk_data_buffers: skb_realloc_headroom failed - signal is dropped\n"); + return -EFAULT; + } + /* Free the old bulk data only if allocation succeeds */ + kfree_skb(tmp); + /* Bulkdata needs to point to the new skb */ + bulkdata->d[i].os_net_buf_ptr = (const unsigned char*)skb; + bulkdata->d[i].os_data_ptr = (const void*)skb->data; + } + /* ... before pushing the data to the right alignment offset */ + skb_push(skb, align_offset); + + } + /* The direction bit is zero for the from-host */ + signal[SIZEOF_SIGNAL_HEADER + (i * SIZEOF_DATAREF) + 1] = align_offset; + + } + return 0; +} /* _align_bulk_data_buffers() */ + + +/* + * --------------------------------------------------------------------------- + * ul_send_signal_unpacked + * + * This function sends a host formatted signal to unifi. + * + * Arguments: + * priv Pointer to driver's private data. + * sigptr Pointer to the signal. + * bulkdata Pointer to the signal's bulk data. + * + * Returns: + * O on success, error code otherwise. + * + * Notes: + * The signals have to be sent in the format described in the host interface + * specification, i.e wire formatted. Certain clients use the host formatted + * structures. The write_pack() transforms the host formatted signal + * into the wired formatted signal. The code is in the core, since the signals + * are defined therefore binded to the host interface specification. + * --------------------------------------------------------------------------- + */ +int +ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, + bulk_data_param_t *bulkdata) +{ + CsrUint8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; + CsrUint16 packed_siglen; + CsrResult csrResult; + unsigned long lock_flags; + int r; +#ifdef CSR_SUPPORT_SME + netInterface_priv_t *interfacePriv = priv->interfacePriv[0]; + CsrUint32 alignOffset = 0; +#endif + + + csrResult = write_pack(sigptr, sigbuf, &packed_siglen); + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n"); + return CsrHipResultToStatus(csrResult); + } +#ifdef CSR_SUPPORT_SME + if (bulkdata != NULL){ + alignOffset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); + + } +#endif + r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata); + if (r) { + return r; + } + + spin_lock_irqsave(&priv->send_signal_lock, lock_flags); + csrResult = unifi_send_signal(priv->card, sigbuf, packed_siglen, bulkdata); + if (csrResult != CSR_RESULT_SUCCESS) { + /* free_bulkdata_buffers(priv, (bulk_data_param_t *)bulkdata); */ + spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); + return CsrHipResultToStatus(csrResult); + } +#ifdef CSR_SUPPORT_SME + if (sigptr->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) { + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + + uf_store_directed_ma_packet_referenece(priv, bulkdata, sigptr,alignOffset); + + } + } +#endif + + spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); + + return 0; +} /* ul_send_signal_unpacked() */ + + +/* + * --------------------------------------------------------------------------- + * reset_driver_status + * + * This function is called from ul_send_signal_raw() when it detects + * that the SME has sent a MLME-RESET request. + * + * Arguments: + * priv Pointer to device private struct + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +static void +reset_driver_status(unifi_priv_t *priv) +{ + priv->sta_wmm_capabilities = 0; +#ifdef CSR_NATIVE_LINUX +#ifdef CSR_SUPPORT_WEXT + priv->wext_conf.flag_associated = 0; + priv->wext_conf.block_controlled_port = CSR_WIFI_ROUTER_PORT_ACTION_8021X_PORT_OPEN; + priv->wext_conf.bss_wmm_capabilities = 0; + priv->wext_conf.disable_join_on_ssid_set = 0; +#endif +#endif +} /* reset_driver_status() */ + + +/* + * --------------------------------------------------------------------------- + * ul_send_signal_raw + * + * This function sends a wire formatted data signal to unifi. + * + * Arguments: + * priv Pointer to driver's private data. + * sigptr Pointer to the signal. + * siglen Length of the signal. + * bulkdata Pointer to the signal's bulk data. + * + * Returns: + * O on success, error code otherwise. + * --------------------------------------------------------------------------- + */ +int +ul_send_signal_raw(unifi_priv_t *priv, unsigned char *sigptr, int siglen, + bulk_data_param_t *bulkdata) +{ + CsrResult csrResult; + unsigned long lock_flags; + int r; + + /* + * Make sure that the signal is updated with the bulk data + * alignment for DMA. + */ + r = _align_bulk_data_buffers(priv, (CsrUint8*)sigptr, bulkdata); + if (r) { + return r; + } + + spin_lock_irqsave(&priv->send_signal_lock, lock_flags); + csrResult = unifi_send_signal(priv->card, sigptr, siglen, bulkdata); + if (csrResult != CSR_RESULT_SUCCESS) { + free_bulkdata_buffers(priv, bulkdata); + spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); + return CsrHipResultToStatus(csrResult); + } + spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); + + /* + * Since this is use by unicli, if we get an MLME reset request + * we need to initialize a few status parameters + * that the driver uses to make decisions. + */ + if (GET_SIGNAL_ID(sigptr) == CSR_MLME_RESET_REQUEST_ID) { + reset_driver_status(priv); + } + + return 0; +} /* ul_send_signal_raw() */ + + diff --git a/drivers/staging/csr/unifi_clients.h b/drivers/staging/csr/unifi_clients.h new file mode 100644 index 000000000000..206b8cffd5b7 --- /dev/null +++ b/drivers/staging/csr/unifi_clients.h @@ -0,0 +1,129 @@ +/* + ***************************************************************************** + * + * FILE : unifi_clients.h + * + * PURPOSE : Private header file for unifi clients. + * + * UDI = UniFi Debug Interface + * + * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + ***************************************************************************** + */ +#ifndef __LINUX_UNIFI_CLIENTS_H__ +#define __LINUX_UNIFI_CLIENTS_H__ 1 + +#include + +#define MAX_UDI_CLIENTS 8 + +/* The start of the range of process ids allocated for ul clients */ +#define UDI_SENDER_ID_BASE 0xC000 +#define UDI_SENDER_ID_SHIFT 8 + + +/* Structure to hold a UDI logged signal */ +typedef struct { + + /* List link structure */ + struct list_head q; + + /* The message that will be passed to the user app */ + udi_msg_t msg; + + /* Signal body and data follow */ + +} udi_log_t; + + + +typedef struct ul_client ul_client_t; + +typedef void (*udi_event_t)(ul_client_t *client, + const u8 *sigdata, int signal_len, + const bulk_data_param_t *bulkdata, + int dir); + +void logging_handler(void *ospriv, + CsrUint8 *sigdata, CsrUint32 signal_len, + const bulk_data_param_t *bulkdata, + enum udi_log_direction direction); + + +/* + * Structure describing a bulk data slot. + * The length field is used to indicate empty/occupied state. + */ +typedef struct _bulk_data +{ + unsigned char ptr[2000]; + unsigned int length; +} bulk_data_t; + + +struct ul_client { + /* Index of this client in the ul_clients array. */ + int client_id; + + /* Index of UniFi device to which this client is attached. */ + int instance; + + /* Flag to say whether this client has been enabled. */ + int udi_enabled; + + /* Value to use in signal->SenderProcessId */ + int sender_id; + + /* Configuration flags, e.g blocking, logging, etc. */ + unsigned int configuration; + + udi_event_t event_hook; + + /* A list to hold signals received from UniFi for reading by read() */ + struct list_head udi_log; + + /* Semaphore to protect the udi_log list */ + struct semaphore udi_sem; + + /* + * Linux waitqueue to support blocking read and poll. + * Logging clients should wait on udi_log. while + * blocking clients should wait on wake_up_wq. + */ + wait_queue_head_t udi_wq; + CSR_SIGNAL* reply_signal; + bulk_data_t* reply_bulkdata[UNIFI_MAX_DATA_REFERENCES]; + + CsrUint16 signal_filter[SIG_FILTER_SIZE]; + + + /* ------------------------------------------------------------------- */ + /* Code below here is used by the sme_native configuration only */ + + /* Flag to wake up blocking clients waiting on udi_wq. */ + int wake_up_wq_id; + + /* + * A 0x00 - 0x0F mask to apply in signal->SenderProcessId. + * Every time we do a blocking mlme request we increase this value. + * The mlme_wait_for_reply() will wait for this sequence number. + * Only the MLME blocking functions update this field. + */ + unsigned char seq_no; + + /* + * A 0x00 - 0x0F counter, containing the sequence number of + * the signal that this client has last received. + * Only the MLME blocking functions update this field. + */ + unsigned char wake_seq_no; + + unifiio_snap_filter_t snap_filter; +}; /* struct ul_client */ + + +#endif /* __LINUX_UNIFI_CLIENTS_H__ */ diff --git a/drivers/staging/csr/unifi_config.h b/drivers/staging/csr/unifi_config.h new file mode 100644 index 000000000000..fe119707844a --- /dev/null +++ b/drivers/staging/csr/unifi_config.h @@ -0,0 +1,34 @@ +/* + * --------------------------------------------------------------------------- + * + * FILE: unifi_config.h + * + * PURPOSE: + * This header file provides parameters that configure the operation + * of the driver. + * + * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#ifndef __UNIFI_CONFIG_H__ +#define __UNIFI_CONFIG_H__ 1 + +/* + * Override for the SDIO function block size on this host. When byte mode CMD53s + * are not used/supported by the SD host controller, transfers are padded up to + * the next block boundary. The 512-byte default on UF6xxx wastes too much space + * on the chip, so the block size is reduced to support this configuration. + */ +#define CSR_WIFI_HIP_SDIO_BLOCK_SIZE 64 + +/* Define the number of mini-coredump buffers to allocate at startup. These are + * used to record chip status for the last n unexpected resets. + */ +#define CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS 5 + + +#endif /* __UNIFI_CONFIG_H__ */ diff --git a/drivers/staging/csr/unifi_dbg.c b/drivers/staging/csr/unifi_dbg.c new file mode 100644 index 000000000000..38d57085a26a --- /dev/null +++ b/drivers/staging/csr/unifi_dbg.c @@ -0,0 +1,110 @@ +/* + * *************************************************************************** + * FILE: unifi_dbg.c + * + * PURPOSE: + * Handle debug signals received from UniFi. + * + * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ +#include "unifi_priv.h" + +/* + * --------------------------------------------------------------------------- + * debug_string_indication + * debug_word16_indication + * + * Handlers for debug indications. + * + * Arguments: + * priv Pointer to private context structure. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +debug_string_indication(unifi_priv_t *priv, const unsigned char *extra, unsigned int extralen) +{ + const unsigned int maxlen = sizeof(priv->last_debug_string) - 1; + + if (extralen > maxlen) { + extralen = maxlen; + } + + strncpy(priv->last_debug_string, extra, extralen); + + /* Make sure the string is terminated */ + priv->last_debug_string[extralen] = '\0'; + + unifi_info(priv, "unifi debug: %s\n", priv->last_debug_string); + +} /* debug_string_indication() */ + + + +void +debug_word16_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr) +{ + int i; + + if (priv == NULL) { + unifi_info(priv, "Priv is NULL\n"); + return; + } + + for (i = 0; i < 16; i++) { + priv->last_debug_word16[i] = + sigptr->u.DebugWord16Indication.DebugWords[i]; + } + + if (priv->last_debug_word16[0] == 0xFA11) { + unsigned long ts; + ts = (priv->last_debug_word16[6] << 16) | priv->last_debug_word16[5]; + unifi_info(priv, " %10lu: %s fault %04x, arg %04x (x%d)\n", + ts, + priv->last_debug_word16[3] == 0x8000 ? "MAC" : + priv->last_debug_word16[3] == 0x4000 ? "PHY" : + "???", + priv->last_debug_word16[1], + priv->last_debug_word16[2], + priv->last_debug_word16[4]); + } + else if (priv->last_debug_word16[0] != 0xDBAC) + /* suppress SDL Trace output (note: still available to unicli). */ + { + unifi_info(priv, "unifi debug: %04X %04X %04X %04X %04X %04X %04X %04X\n", + priv->last_debug_word16[0], priv->last_debug_word16[1], + priv->last_debug_word16[2], priv->last_debug_word16[3], + priv->last_debug_word16[4], priv->last_debug_word16[5], + priv->last_debug_word16[6], priv->last_debug_word16[7]); + unifi_info(priv, " %04X %04X %04X %04X %04X %04X %04X %04X\n", + priv->last_debug_word16[8], priv->last_debug_word16[9], + priv->last_debug_word16[10], priv->last_debug_word16[11], + priv->last_debug_word16[12], priv->last_debug_word16[13], + priv->last_debug_word16[14], priv->last_debug_word16[15]); + } + +} /* debug_word16_indication() */ + + +void +debug_generic_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr) +{ + unifi_info(priv, "debug: %04X %04X %04X %04X %04X %04X %04X %04X\n", + sigptr->u.DebugGenericIndication.DebugWords[0], + sigptr->u.DebugGenericIndication.DebugWords[1], + sigptr->u.DebugGenericIndication.DebugWords[2], + sigptr->u.DebugGenericIndication.DebugWords[3], + sigptr->u.DebugGenericIndication.DebugWords[4], + sigptr->u.DebugGenericIndication.DebugWords[5], + sigptr->u.DebugGenericIndication.DebugWords[6], + sigptr->u.DebugGenericIndication.DebugWords[7]); + +} /* debug_generic_indication() */ + diff --git a/drivers/staging/csr/unifi_event.c b/drivers/staging/csr/unifi_event.c new file mode 100644 index 000000000000..cfc5b32d4a66 --- /dev/null +++ b/drivers/staging/csr/unifi_event.c @@ -0,0 +1,794 @@ +/* + * *************************************************************************** + * FILE: unifi_event.c + * + * PURPOSE: + * Process the signals received by UniFi. + * It is part of the porting exercise. + * + * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ + + +/* + * Porting notes: + * The implementation of unifi_receive_event() in Linux is fairly complicated. + * The linux driver support multiple userspace applications and several + * build configurations, so the received signals are processed by different + * processes and multiple times. + * In a simple implementation, this function needs to deliver: + * - The MLME-UNITDATA.ind signals to the Rx data plane and to the Traffic + * Analysis using unifi_ta_sample(). + * - The MLME-UNITDATA-STATUS.ind signals to the Tx data plane. + * - All the other signals to the SME using unifi_sys_hip_ind(). + */ + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "unifi_priv.h" + + +/* + * --------------------------------------------------------------------------- + * send_to_client + * + * Helper for unifi_receive_event. + * + * This function forwards a signal to one client. + * + * Arguments: + * priv Pointer to driver's private data. + * client Pointer to the client structure. + * receiver_id The reciever id of the signal. + * sigdata Pointer to the packed signal buffer. + * siglen Length of the packed signal. + * bulkdata Pointer to the signal's bulk data. + * + * Returns: + * None. + * + * --------------------------------------------------------------------------- + */ +static void send_to_client(unifi_priv_t *priv, ul_client_t *client, + int receiver_id, + unsigned char *sigdata, int siglen, + const bulk_data_param_t *bulkdata) +{ + if (client && client->event_hook) { + /*unifi_trace(priv, UDBG3, + "Receive: client %d, (s:0x%X, r:0x%X) - Signal 0x%.4X \n", + client->client_id, client->sender_id, receiver_id, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));*/ + + client->event_hook(client, sigdata, siglen, bulkdata, UDI_TO_HOST); + } +} + +/* + * --------------------------------------------------------------------------- + * process_pkt_data_ind + * + * Dispatcher for received signals. + * + * This function receives the 'to host' signals and forwards + * them to the unifi linux clients. + * + * Arguments: + * priv Context + * sigdata Pointer to the packed signal buffer(Its in form of MA-PACKET.ind). + * bulkdata Pointer to signal's bulkdata + * freeBulkData Pointer to a flag which gets set if the bulkdata needs to + * be freed after calling the logging handlers. If it is not + * set the bulkdata must be freed by the MLME handler or + * passed to the network stack. + * Returns: + * TRUE if the packet should be routed to the SME etc. + * FALSE if the packet is for the driver or network stack + * --------------------------------------------------------------------------- + */ +static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, + CsrUint8 *sigdata, + const bulk_data_param_t* bulkdata, + CsrBool *freeBulkData, + netInterface_priv_t *interfacePriv) +{ + CsrUint16 frmCtrl, receptionStatus, frmCtrlSubType; + CsrUint8 *macHdrLocation; + CsrUint8 interfaceTag; + CsrBool isDataFrame; + CsrBool isProtocolVerInvalid = FALSE; + CsrBool isDataFrameSubTypeNoData = FALSE; + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + static const CsrUint8 wapiProtocolIdSNAPHeader[] = {0x88,0xb4}; + static const CsrUint8 wapiProtocolIdSNAPHeaderOffset = 6; + CsrUint8 *destAddr; + CsrUint8 *srcAddr; + CsrBool isUnicastPkt = FALSE; + + CsrUint8 llcSnapHeaderOffset = 0; + + destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; + srcAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; + + /*Individual/Group bit - Bit 0 of first byte*/ + isUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; +#endif + +#define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 + + *freeBulkData = FALSE; + + /* Fetch the MAC header location from MA_PKT_IND packet */ + macHdrLocation = (CsrUint8 *) bulkdata->d[0].os_data_ptr; + /* Fetch the Frame Control value from MAC header */ + frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); + + /* Pull out interface tag from virtual interface identifier */ + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; + + /* check for MIC failure before processing the signal */ + receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET); + + /* To discard any spurious MIC failures that could be reported by the firmware */ + isDataFrame = ((frmCtrl & IEEE80211_FC_TYPE_MASK) == (IEEE802_11_FC_TYPE_DATA & IEEE80211_FC_TYPE_MASK)) ? TRUE : FALSE; + /* 0x00 is the only valid protocol version*/ + isProtocolVerInvalid = (frmCtrl & IEEE80211_FC_PROTO_VERSION_MASK) ? TRUE : FALSE; + frmCtrlSubType = (frmCtrl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET; + /*Exclude the no data & reserved sub-types from MIC failure processing*/ + isDataFrameSubTypeNoData = (((frmCtrlSubType>0x03)&&(frmCtrlSubType<0x08)) || (frmCtrlSubType>0x0B)) ? TRUE : FALSE; + if ((receptionStatus == CSR_MICHAEL_MIC_ERROR) && + ((!isDataFrame) || isProtocolVerInvalid || (isDataFrame && isDataFrameSubTypeNoData))) { + /* Currently MIC errors are discarded for frames other than data frames. This might need changing when we start + * supporting 802.11w (Protected Management frames) + */ + *freeBulkData = TRUE; + unifi_trace(priv, UDBG4, "Discarding this frame and ignoring the MIC failure as this is a garbage/non-data/no data frame\n"); + return FALSE; + } + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + + if (receptionStatus == CSR_MICHAEL_MIC_ERROR) { + + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { + + /* If this MIC ERROR reported by the firmware is either for + * [1] a WAPI Multicast Packet and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR + * [2] a WAPI Unicast Packet and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set + * then report a MIC FAILURE indication to the SME. + */ + if ((priv->wapi_multicast_filter == 0) || isUnicastPkt) { + + /*Discard the frame*/ + *freeBulkData = TRUE; + unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n"); + + if (isUnicastPkt && + ((uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag) != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN)|| + (priv->wapi_unicast_filter) || + (priv->wapi_unicast_queued_pkt_filter))) { + + /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP + * while we are in the process of re-association induced by unsupported WAPI Unicast key index + * - Discard the packets with MIC failures "until" we have + * a. negotiated a key, + * b. opened the CONTROL PORT and + * c. the AP has started using the new key + */ + unifi_trace(priv, UDBG4, "Ignoring the MIC failure as either a. CONTROL PORT isn't OPEN or b. Unicast filter is set or c. WAPI AP using old key for buffered pkts\n"); + + /*Ignore this MIC failure*/ + return FALSE; + + }/*WAPI re-key specific workaround*/ + + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", + interfaceTag, srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3], srcAddr[4], srcAddr[5]); + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Dest Addr %x:%x:%x:%x:%x:%x\n", + destAddr[0], destAddr[1], destAddr[2], destAddr[3], destAddr[4], destAddr[5]); + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Control Port State - 0x%.4X \n", + uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag)); + + unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); + + /*Report the MIC failure to the SME*/ + return TRUE; + } + }/* STA mode */ + else { + /* Its AP Mode . Just Return */ + *freeBulkData = TRUE; + unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); + return TRUE; + } /* AP mode */ + }/* MIC error */ +#else + if (receptionStatus == CSR_MICHAEL_MIC_ERROR) { + *freeBulkData = TRUE; + unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); + return TRUE; + } +#endif /*CSR_WIFI_SECURITY_WAPI_ENABLE*/ + + unifi_trace(priv, UDBG4, "frmCtrl = 0x%04x %s\n", + frmCtrl, + (((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) == IEEE802_11_FRAMETYPE_MANAGEMENT) ? + "Mgt" : "Ctrl/Data"); + +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + /* To ignore MIC failures reported due to the WAPI AP using the old key for queued packets before + * starting to use the new key negotiated as part of unicast re-keying + */ + if (isUnicastPkt && + (receptionStatus == CSR_RX_SUCCESS) && + (priv->wapi_unicast_queued_pkt_filter==1)) { + + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI unicast pkt received when the (wapi_unicast_queued_pkt_filter) is set\n"); + + if (isDataFrame) { + switch(frmCtrl & IEEE80211_FC_SUBTYPE_MASK) { + case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: + llcSnapHeaderOffset = MAC_HEADER_SIZE + 2; + break; + case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK: + case IEEE802_11_FC_TYPE_NULL & IEEE80211_FC_SUBTYPE_MASK: + break; + default: + llcSnapHeaderOffset = MAC_HEADER_SIZE; + } + } + + if (llcSnapHeaderOffset > 0) { + /* QoS data or Data */ + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): SNAP header found & its offset %d\n",llcSnapHeaderOffset); + if (memcmp((CsrUint8 *)(bulkdata->d[0].os_data_ptr+llcSnapHeaderOffset+wapiProtocolIdSNAPHeaderOffset), + wapiProtocolIdSNAPHeader,sizeof(wapiProtocolIdSNAPHeader))) { + + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): This is a data & NOT a WAI protocol packet\n"); + /* On the first unicast data pkt that is decrypted successfully after re-keying, reset the filter */ + priv->wapi_unicast_queued_pkt_filter = 0; + unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind(): WAPI AP has started using the new unicast key, no more MIC failures expected (reset filter)\n"); + } + else { + unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI - This is a WAI protocol packet\n"); + } + } + } +#endif + + + switch ((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) { + case IEEE802_11_FRAMETYPE_MANAGEMENT: + *freeBulkData = TRUE; /* Free (after SME handler copies it) */ + + /* In P2P device mode, filter the legacy AP beacons here */ + if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2P)&&\ + ((CSR_WIFI_80211_GET_FRAME_SUBTYPE(macHdrLocation)) == CSR_WIFI_80211_FRAME_SUBTYPE_BEACON)){ + + CsrUint8 *pSsid, *pSsidLen; + static CsrUint8 P2PWildCardSsid[CSR_WIFI_P2P_WILDCARD_SSID_LENGTH] = {'D', 'I', 'R', 'E', 'C', 'T', '-'}; + + pSsidLen = macHdrLocation + MAC_HEADER_SIZE + CSR_WIFI_BEACON_FIXED_LENGTH; + pSsid = pSsidLen + 2; + + if(*(pSsidLen + 1) >= CSR_WIFI_P2P_WILDCARD_SSID_LENGTH){ + if(memcmp(pSsid, P2PWildCardSsid, CSR_WIFI_P2P_WILDCARD_SSID_LENGTH) == 0){ + unifi_trace(priv, UDBG6, "Received a P2P Beacon, pass it to SME\n"); + return TRUE; + } + } + unifi_trace(priv, UDBG6, "Received a Legacy AP beacon in P2P mode, drop it\n"); + return FALSE; + } + return TRUE; /* Route to SME */ + case IEEE802_11_FRAMETYPE_DATA: + case IEEE802_11_FRAMETYPE_CONTROL: + *freeBulkData = FALSE; /* Network stack or MLME handler frees */ + return FALSE; + default: + unifi_error(priv, "Unhandled frame type %04x\n", frmCtrl); + *freeBulkData = TRUE; /* Not interested, but must free it */ + return FALSE; + } +} +#ifdef CSR_WIFI_RX_PATH_SPLIT +static CsrBool signal_buffer_is_full(unifi_priv_t* priv) +{ + return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); + +} +#endif +/* + * --------------------------------------------------------------------------- + * unifi_receive_event + * + * Dispatcher for received signals. + * + * This function receives the 'to host' signals and forwards + * them to the unifi linux clients. + * + * Arguments: + * ospriv Pointer to driver's private data. + * sigdata Pointer to the packed signal buffer. + * siglen Length of the packed signal. + * bulkdata Pointer to the signal's bulk data. + * + * Returns: + * None. + * + * Notes: + * The signals are received in the format described in the host interface + * specification, i.e wire formatted. Certain clients use the same format + * to interpret them and other clients use the host formatted structures. + * Each client has to call read_unpack_signal() to transform the wire + * formatted signal into the host formatted signal, if necessary. + * The code is in the core, since the signals are defined therefore + * binded to the host interface specification. + * --------------------------------------------------------------------------- + */ + + +void +unifi_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) +{ +#ifdef CSR_WIFI_RX_PATH_SPLIT + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + CsrUint8 writePointer; + int i; + rx_buff_struct_t * rx_buff; + func_enter(); + + unifi_trace(priv, UDBG5, "unifi_receive_event: " + "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); + if(signal_buffer_is_full(priv)) { + unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n"); + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + return; + } + writePointer = priv->rxSignalBuffer.writePointer; + rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; + memcpy(rx_buff->bufptr,sigdata,siglen); + rx_buff->sig_len = siglen; + rx_buff->data_ptrs = *bulkdata; + writePointer++; + if(writePointer >= priv->rxSignalBuffer.size) { + writePointer =0; + } + unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer); + priv->rxSignalBuffer.writePointer = writePointer; + +#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ + queue_work(priv->rx_workqueue, &priv->rx_work_struct); +#endif + +#else + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + int i, receiver_id; + int client_id; + CsrInt16 signal_id; + CsrBool pktIndToSme = FALSE, freeBulkData = FALSE; + + func_enter(); + + unifi_trace(priv, UDBG5, "unifi_receive_event: " + "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); + + receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; + client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; + signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); + + + + /* check for the type of frame received (checks for 802.11 management frames) */ + if (signal_id == CSR_MA_PACKET_INDICATION_ID) + { + CsrUint8 interfaceTag; + netInterface_priv_t *interfacePriv; + + /* Pull out interface tag from virtual interface identifier */ + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* Update activity for this station in case of IBSS */ +#ifdef CSR_SUPPORT_SME + + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { + + CsrUint8 *saddr; + /* Fetch the source address from mac header */ + saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; + unifi_trace(priv, UDBG5, + "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", + interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]); + + uf_update_sta_activity(priv, interfaceTag, saddr); + } +#endif + + pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); + + unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); + } + + if (pktIndToSme) + { + /* Management MA_PACKET_IND for SME */ + if(sigdata != NULL && bulkdata != NULL){ + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); + } + else{ + unifi_error(priv, "unifi_receive_event: sigdata or Bulkdata is NULL \n"); + } +#ifdef CSR_NATIVE_LINUX + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); +#endif + } + else + { + /* Signals with ReceiverId==0 are also reported to SME / WEXT, + * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs + */ + if (!receiver_id) { + if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) + { + uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); + } + else if (signal_id != CSR_MA_PACKET_INDICATION_ID) + { + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); +#ifdef CSR_NATIVE_LINUX + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); +#endif + } + }/*if (receiver_id==0) */ + +#ifdef CSR_SUPPORT_SME +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + /* Send a WAPI Multicast Indication to SME if the filter has been set + * and this is a multicast data packet + */ + if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { + CSR_SIGNAL signal; + CsrUint8 *destAddr; + CsrResult res; + CsrUint16 interfaceTag = 0; + + /* Check if it is a multicast packet from the destination address in the MAC header */ + res = read_unpack_signal(sigdata, &signal); + destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; + if (res) { + unifi_error(priv, "Received unknown or corrupted signal.\n"); + return; + } + /*Individual/Group bit - Bit 0 of first byte*/ + if (destAddr[0] & 0x01) { + unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); + + CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + func_exit(); + return; + } + } +#endif +#endif + + /* calls the registered clients handler callback func. + * netdev_mlme_event_handler is one of the registered handler used to route + * data packet to network stack or AMP/EAPOL related data to SME + */ + /* The freeBulkData check ensures that, it has received a management frame and + * the frame needs to be freed here. So not to be passed to netdev handler + */ + if(!freeBulkData){ + if ((client_id < MAX_UDI_CLIENTS) && + (&priv->ul_clients[client_id] != priv->logging_client)) { + send_to_client(priv, &priv->ul_clients[client_id], + receiver_id, + sigdata, siglen, bulkdata); + } + } + } + + /* + * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION + */ + switch (signal_id) + { +#ifdef UNIFI_SNIFF_ARPHRD + case CSR_MA_SNIFFDATA_INDICATION_ID: +#endif + break; + + case CSR_MA_PACKET_INDICATION_ID: + if (!freeBulkData) + { + break; + } + /* FALLS THROUGH... */ + default: + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + } +#endif + func_exit(); +} /* unifi_receive_event() */ + +#ifdef CSR_WIFI_RX_PATH_SPLIT +/* + * --------------------------------------------------------------------------- + * unifi_receive_event2 + * + * Dispatcher for received signals. + * + * This function receives the 'to host' signals and forwards + * them to the unifi linux clients. + * + * Arguments: + * ospriv Pointer to driver's private data. + * sigdata Pointer to the packed signal buffer. + * siglen Length of the packed signal. + * bulkdata Pointer to the signal's bulk data. + * + * Returns: + * None. + * + * Notes: + * The signals are received in the format described in the host interface + * specification, i.e wire formatted. Certain clients use the same format + * to interpret them and other clients use the host formatted structures. + * Each client has to call read_unpack_signal() to transform the wire + * formatted signal into the host formatted signal, if necessary. + * The code is in the core, since the signals are defined therefore + * binded to the host interface specification. + * --------------------------------------------------------------------------- + */ +static void +unifi_receive_event2(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + int i, receiver_id; + int client_id; + CsrInt16 signal_id; + CsrBool pktIndToSme = FALSE, freeBulkData = FALSE; + + func_enter(); + + unifi_trace(priv, UDBG5, "unifi_receive_event2: " + "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); + + receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; + client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; + signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); + + + + /* check for the type of frame received (checks for 802.11 management frames) */ + if (signal_id == CSR_MA_PACKET_INDICATION_ID) + { + CsrUint8 interfaceTag; + netInterface_priv_t *interfacePriv; + + /* Pull out interface tag from virtual interface identifier */ + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* Update activity for this station in case of IBSS */ +#ifdef CSR_SUPPORT_SME + + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { + + CsrUint8 *saddr; + /* Fetch the source address from mac header */ + saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; + unifi_trace(priv, UDBG5, + "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", + interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]); + + uf_update_sta_activity(priv, interfaceTag, saddr); + } +#endif + + pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); + + unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); + + } + + if (pktIndToSme) + { + /* Management MA_PACKET_IND for SME */ + if(sigdata != NULL && bulkdata != NULL){ + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); + } + else{ + unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); + } +#ifdef CSR_NATIVE_LINUX + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); +#endif + } + else + { + /* Signals with ReceiverId==0 are also reported to SME / WEXT, + * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs + */ + if (!receiver_id) { + if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) + { + uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); + } + else if (signal_id != CSR_MA_PACKET_INDICATION_ID) + { + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); +#ifdef CSR_NATIVE_LINUX + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); +#endif + } + } + +#ifdef CSR_SUPPORT_SME +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + /* Send a WAPI Multicast Indication to SME if the filter has been set + * and this is a multicast data packet + */ + if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { + CSR_SIGNAL signal; + CsrUint8 *destAddr; + CsrResult res; + CsrUint16 interfaceTag = 0; + + /* Check if it is a multicast packet from the destination address in the MAC header */ + res = read_unpack_signal(sigdata, &signal); + destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; + if (res) { + unifi_error(priv, "Received unknown or corrupted signal.\n"); + return; + } + /*Individual/Group bit - Bit 0 of first byte*/ + if (destAddr[0] & 0x01) { + unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); + + CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + func_exit(); + return; + } + } +#endif +#endif + + /* calls the registered clients handler callback func. + * netdev_mlme_event_handler is one of the registered handler used to route + * data packet to network stack or AMP/EAPOL related data to SME + */ + /* The freeBulkData check ensures that, it has received a management frame and + * the frame needs to be freed here. So not to be passed to netdev handler + */ + if(!freeBulkData){ + if ((client_id < MAX_UDI_CLIENTS) && + (&priv->ul_clients[client_id] != priv->logging_client)) { + send_to_client(priv, &priv->ul_clients[client_id], + receiver_id, + sigdata, siglen, bulkdata); + } + } + } + + /* + * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION + */ + switch (signal_id) + { +#ifdef UNIFI_SNIFF_ARPHRD + case CSR_MA_SNIFFDATA_INDICATION_ID: +#endif + break; + + case CSR_MA_PACKET_INDICATION_ID: + if (!freeBulkData) + { + break; + } + /* FALLS THROUGH... */ + default: + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + } + + func_exit(); +} /* unifi_receive_event2() */ + +void unifi_rx_queue_flush(void *ospriv) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + func_enter(); + unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer); + if(priv != NULL) { + CsrUint8 readPointer = priv->rxSignalBuffer.readPointer; + while(readPointer != priv->rxSignalBuffer.writePointer) { + rx_buff_struct_t * buf = &priv->rxSignalBuffer.rx_buff[readPointer]; + unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + readPointer,priv->rxSignalBuffer.writePointer); + unifi_receive_event2(priv,buf->bufptr,buf->sig_len,&buf->data_ptrs); + readPointer ++; + if(readPointer >= priv->rxSignalBuffer.size) { + readPointer = 0; + } + } + priv->rxSignalBuffer.readPointer = readPointer; + } + func_exit(); +} + +void rx_wq_handler(struct work_struct *work) +{ + unifi_priv_t *priv = container_of(work,unifi_priv_t,rx_work_struct); + unifi_rx_queue_flush(priv); +} + +#endif diff --git a/drivers/staging/csr/unifi_native.h b/drivers/staging/csr/unifi_native.h new file mode 100644 index 000000000000..0015ec2cdb00 --- /dev/null +++ b/drivers/staging/csr/unifi_native.h @@ -0,0 +1,276 @@ +/* + ***************************************************************************** + * + * FILE : unifi_native.h + * + * PURPOSE : Private header file for unifi driver support to wireless extensions. + * + * UDI = UniFi Debug Interface + * + * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + ***************************************************************************** + */ +#ifndef __LINUX_UNIFI_NATIVE_H__ +#define __LINUX_UNIFI_NATIVE_H__ 1 + +#include +#include + + +/* + * scan.c wext.c autojoin.c + */ +/* Structure to hold results of a scan */ +typedef struct scan_info { + +/* CSR_MLME_SCAN_INDICATION msi; */ + + unsigned char *info_elems; + int info_elem_length; + +} scan_info_t; + + +#define IE_VECTOR_MAXLEN 1024 + +#ifdef CSR_SUPPORT_WEXT +/* + * Structre to hold the wireless network configuration info. + */ +struct wext_config { + + /* Requested channel when setting up an adhoc network */ + int channel; + + /* wireless extns mode: IW_MODE_AUTO, ADHOC, INFRA, MASTER ... MONITOR */ + int mode; + + /* The capabilities of the currently joined network */ + int capability; + + /* The interval between beacons if we create an IBSS */ + int beacon_period; + + /* + * Power-save parameters + */ + /* The listen interval to ask for in Associate req. */ + int assoc_listen_interval; + /* Power-mode to put UniFi into */ + + unsigned char desired_ssid[UNIFI_MAX_SSID_LEN]; /* the last ESSID set by SIOCSIWESSID */ + int power_mode; + /* Whether to wake for broadcast packets (using DTIM interval) */ + int wakeup_for_dtims; + + /* Currently selected WEP Key ID (0..3) */ + int wep_key_id; + + wep_key_t wep_keys[NUM_WEPKEYS]; + +/* CSR_AUTHENTICATION_TYPE auth_type; */ + int privacy; + + u32 join_failure_timeout; + u32 auth_failure_timeout; + u32 assoc_failure_timeout; + + unsigned char generic_ie[IE_VECTOR_MAXLEN]; + int generic_ie_len; + + struct iw_statistics wireless_stats; + + + /* the ESSID we are currently associated to */ + unsigned char current_ssid[UNIFI_MAX_SSID_LEN]; + /* the BSSID we are currently associated to */ + unsigned char current_bssid[6]; + + /* + * IW_AUTH_WPA_VERSION_DISABLED 0x00000001 + * IW_AUTH_WPA_VERSION_WPA 0x00000002 + * IW_AUTH_WPA_VERSION_WPA2 0x00000004 + */ + unsigned char wpa_version; + + /* + * cipher selection: + * IW_AUTH_CIPHER_NONE 0x00000001 + * IW_AUTH_CIPHER_WEP40 0x00000002 + * IW_AUTH_CIPHER_TKIP 0x00000004 + * IW_AUTH_CIPHER_CCMP 0x00000008 + * IW_AUTH_CIPHER_WEP104 0x00000010 + */ + unsigned char pairwise_cipher_used; + unsigned char group_cipher_used; + + unsigned int frag_thresh; + unsigned int rts_thresh; + + /* U-APSD value, send with Association Request to WMM Enabled APs */ + unsigned char wmm_bss_uapsd_mask; + /* The WMM capabilities of the selected BSS */ + unsigned int bss_wmm_capabilities; + + /* Flag to prevent a join when the ssid is set */ + int disable_join_on_ssid_set; + + /* Scan info */ +#define UNIFI_MAX_SCANS 32 + scan_info_t scan_list[UNIFI_MAX_SCANS]; + int num_scan_info; + + /* Flag on whether non-802.1x packets are allowed out */ + CsrWifiRouterPortAction block_controlled_port; + + /* Flag on whether we have completed an authenticate/associate process */ + unsigned int flag_associated : 1; +}; /* struct wext_config */ + +#endif /* CSR_SUPPORT_WEXT */ + + +/* + * wext.c + */ +/*int mlme_set_protection(unifi_priv_t *priv, unsigned char *addr, + CSR_PROTECT_TYPE prot, CSR_KEY_TYPE key_type); +*/ + +/* + * scan.c + */ +/* +void unifi_scan_indication_handler(unifi_priv_t *priv, + const CSR_MLME_SCAN_INDICATION *msg, + const unsigned char *extra, + unsigned int len); +*/ +void unifi_clear_scan_table(unifi_priv_t *priv); +scan_info_t *unifi_get_scan_report(unifi_priv_t *priv, int index); + + +/* + * Utility functions + */ +const unsigned char *unifi_find_info_element(int id, + const unsigned char *info, + int len); +int unifi_add_info_element(unsigned char *info, + int ie_id, + const unsigned char *ie_data, + int ie_len); + +/* + * autojoin.c + */ +/* Higher level fns */ +int unifi_autojoin(unifi_priv_t *priv, const char *ssid); +/* +int unifi_do_scan(unifi_priv_t *priv, int scantype, CSR_BSS_TYPE bsstype, + const char *ssid, int ssid_len); +*/ +int unifi_set_powermode(unifi_priv_t *priv); +int unifi_join_ap(unifi_priv_t *priv, scan_info_t *si); +int unifi_join_bss(unifi_priv_t *priv, unsigned char *macaddr); +int unifi_leave(unifi_priv_t *priv); +unsigned int unifi_get_wmm_bss_capabilities(unifi_priv_t *priv, + unsigned char *ie_vector, + int ie_len, int *ap_capabilities); + +/* + * Status and management. + */ +int uf_init_wext_interface(unifi_priv_t *priv); +void uf_deinit_wext_interface(unifi_priv_t *priv); + +/* + * Function to reset UniFi's 802.11 state by sending MLME-RESET.req + */ +int unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr, unsigned char set_default_mib); + + +/* + * mlme.c + */ +/* Abort an MLME operation - useful in error recovery */ +int uf_abort_mlme(unifi_priv_t *priv); + +int unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli, + CSR_SIGNAL *sig, bulk_data_param_t *data_ptrs, + int timeout); +void unifi_mlme_copy_reply_and_wakeup_client(ul_client_t *pcli, + CSR_SIGNAL *signal, int signal_len, + const bulk_data_param_t *bulkdata); + +/* + * Utility functions + */ +const char *lookup_reason_code(int reason); +const char *lookup_result_code(int result); + + +/* + * sme_native.c + */ +int uf_sme_init(unifi_priv_t *priv); +void uf_sme_deinit(unifi_priv_t *priv); +int sme_sys_suspend(unifi_priv_t *priv); +int sme_sys_resume(unifi_priv_t *priv); +int sme_mgt_wifi_on(unifi_priv_t *priv); + +/* Callback for event logging to SME clients (unifi_manager) */ +void sme_native_log_event(ul_client_t *client, + const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata, + int dir); + +void sme_native_mlme_event_handler(ul_client_t *pcli, + const u8 *sig_packed, int sig_len, + const bulk_data_param_t *bulkdata, + int dir); + +/* Task to query statistics from the MIB */ +#define UF_SME_STATS_WQ_TIMEOUT 2000 /* in msecs */ +void uf_sme_stats_wq(struct work_struct *work); + +void uf_native_process_udi_signal(ul_client_t *pcli, + const u8 *packed_signal, + int packed_signal_len, + const bulk_data_param_t *bulkdata, int dir); +#if 0 +/* + * Choose one of these if available in linux/if_arp.h: + * #define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_RADIOTAP + * #define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_PRISM + * + * Radiotap is the newer standard for softmac WLAN devices, it works with + * Wireshark but not Ethereal (due to a bug in the Ethereal dissector). + * Prism is an older (less desirable) format but it does work with Ethereal. + */ +#ifdef ARPHRD_IEEE80211_RADIOTAP +#define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_RADIOTAP +#else +#ifdef ARPHRD_IEEE80211_PRISM +#define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_PRISM +#endif +#endif +#endif + +#ifdef UNIFI_SNIFF_ARPHRD +/* + * monitor.c + */ +int uf_start_sniff(unifi_priv_t *priv); +/* +void ma_sniffdata_ind(void *ospriv, + const CSR_MA_SNIFFDATA_INDICATION *ind, + const bulk_data_param_t *bulkdata); +*/ +#endif /* ARPHRD_IEEE80211_PRISM */ + +#endif /* __LINUX_UNIFI_NATIVE_H__ */ diff --git a/drivers/staging/csr/unifi_os.h b/drivers/staging/csr/unifi_os.h new file mode 100644 index 000000000000..579c7e0544a3 --- /dev/null +++ b/drivers/staging/csr/unifi_os.h @@ -0,0 +1,137 @@ +/* + * --------------------------------------------------------------------------- + * + * FILE: os_linux/unifi_os.h + * + * PURPOSE: + * This header file provides the OS-dependent facilities for a linux + * environment. + * + * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#ifndef __UNIFI_OS_LINUX_H__ +#define __UNIFI_OS_LINUX_H__ 1 + +#include +#include +#include +#include +#include + +/* + * Needed for core/signals.c + */ +#include + + +/* Define INLINE directive*/ +#define INLINE inline + +/* Malloc and free */ +CsrResult unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size); +void unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot); +#define CSR_WIFI_ALIGN_BYTES 4 +CsrResult unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot); + +/* + * Byte Order + * Note that __le*_to_cpu and __cpu_to_le* return an unsigned value! + */ +#ifdef __KERNEL__ +#define unifi2host_16(n) (__le16_to_cpu((n))) +#define unifi2host_32(n) (__le32_to_cpu((n))) +#define host2unifi_16(n) (__cpu_to_le16((n))) +#define host2unifi_32(n) (__cpu_to_le32((n))) +#endif + +/* Module parameters */ +extern int unifi_debug; + +/* debugging */ +#ifdef UNIFI_DEBUG +/* + * unifi_debug is a verbosity level for debug messages + * UDBG0 msgs are always printed if UNIFI_DEBUG is defined + * UDBG1 msgs are printed if UNIFI_DEBUG is defined and unifi_debug > 0 + * etc. + */ + +#define func_enter() \ + do { \ + if (unifi_debug >= 5) { \ + printk("unifi: => %s\n", __FUNCTION__); \ + } \ + } while (0) +#define func_exit() \ + do { \ + if (unifi_debug >= 5) { \ + printk("unifi: <= %s\n", __FUNCTION__); \ + } \ + } while (0) +#define func_exit_r(_rc) \ + do { \ + if (unifi_debug >= 5) { \ + printk("unifi: <= %s %d\n", __FUNCTION__, (int)(_rc)); \ + } \ + } while (0) + + +#define ASSERT(cond) \ + do { \ + if (!(cond)) { \ + printk("Assertion failed in %s at %s:%d: %s\n", \ + __FUNCTION__, __FILE__, __LINE__, #cond); \ + } \ + } while (0) + + +void unifi_dump(void *ospriv, int lvl, const char *msg, void *mem, CsrUint16 len); +void dump(void *mem, CsrUint16 len); +void dump16(void *mem, CsrUint16 len); +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +void dump_str(void *mem, CsrUint16 len); +#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ + +#else + +/* Stubs */ +#define func_enter() +#define func_exit() +#define func_exit_r(_rc) + +#define ASSERT(cond) + +static inline void unifi_dump(void *ospriv, int lvl, const char *msg, void *mem, CsrUint16 len) {} +static inline void dump(void *mem, CsrUint16 len) {} +static inline void dump16(void *mem, CsrUint16 len) {} +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +static inline void dump_str(void *mem, CsrUint16 len) {} +#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ + +#endif /* UNIFI_DEBUG */ + + +void unifi_error(void* ospriv, const char *fmt, ...); +void unifi_warning(void* ospriv, const char *fmt, ...); +void unifi_notice(void* ospriv, const char *fmt, ...); +void unifi_info(void* ospriv, const char *fmt, ...); + +void unifi_trace(void* ospriv, int level, const char *fmt, ...); + +/* Different levels of diagnostic detail... */ +#define UDBG0 0 /* always prints in debug build */ +#define UDBG1 1 +#define UDBG2 2 +#define UDBG3 3 +#define UDBG4 4 +#define UDBG5 5 +#define UDBG6 6 +#define UDBG7 7 + + +#endif /* __UNIFI_OS_LINUX_H__ */ diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c new file mode 100644 index 000000000000..36b871e02c98 --- /dev/null +++ b/drivers/staging/csr/unifi_pdu_processing.c @@ -0,0 +1,3728 @@ +/* + * --------------------------------------------------------------------------- + * FILE: unifi_pdu_processing.c + * + * PURPOSE: + * This file provides the PDU handling functionality before it gets sent to unfi and after + * receiving a PDU from unifi + * + * Copyright (C) 2010 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ + + +#include +#include +#include + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" +#include "csr_time.h" +#include "unifi_priv.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +#include +#endif +#include + +#ifdef CSR_SUPPORT_SME +static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata, + tx_buffered_packets_t* buffered_pkt) +{ + + struct sk_buff *skb ; + CsrUint32 align_offset; + + if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){ + return; + } + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + align_offset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); + if(align_offset){ + skb_pull(skb,align_offset); + } + buffered_pkt->bulkdata.os_data_ptr = skb->data; + buffered_pkt->bulkdata.data_length = skb->len; + + +} +#endif + +void +unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, + CSR_RATE TransmitRate, CSR_CLIENT_TAG hostTag, + CsrUint16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, + CSR_PROCESS_ID leSenderProcessId, CsrUint8 *peerMacAddress, + CSR_SIGNAL *signal) +{ + + CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; + netInterface_priv_t *interfacePriv; + CsrUint8 ba_session_idx = 0; + ba_session_tx_struct *ba_session = NULL; + CsrUint8 *ba_addr = NULL; + + interfacePriv = priv->interfacePriv[interfaceTag]; + + UF_TRACE_MAC(priv, UDBG5, "In unifi_frame_ma_packet_req, Frame for Peer:", peerMacAddress); + signal->SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; + signal->SignalPrimitiveHeader.ReceiverProcessId = 0; + signal->SignalPrimitiveHeader.SenderProcessId = leSenderProcessId; + + /* Fill the MA-PACKET.req */ + req->Priority = priority; + unifi_trace(priv, UDBG3, "Tx Frame with Priority: 0x%x\n", req->Priority); + + /* A value of 0 is used for auto selection of rates. But for P2P GO case + * for action frames the rate is governed by SME. Hence instead of 0, + * the rate is filled in with the value passed here + */ + req->TransmitRate = TransmitRate; + + /* packets from netdev then no confirm required but packets from + * Nme/Sme eapol data frames requires the confirmation + */ + req->TransmissionControl = transmissionControl; + req->VirtualInterfaceIdentifier = + uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag); + memcpy(req->Ra.x, peerMacAddress, ETH_ALEN); + + if (hostTag == 0xffffffff) { + req->HostTag = interfacePriv->tag++; + req->HostTag |= 0x40000000; + unifi_trace(priv, UDBG3, "new host tag assigned = 0x%x\n", req->HostTag); + interfacePriv->tag &= 0x0fffffff; + } else { + req->HostTag = hostTag; + unifi_trace(priv, UDBG3, "host tag got from SME = 0x%x\n", req->HostTag); + } + /* check if BA session exists for the peer MAC address on same tID */ + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO){ + ba_addr = peerMacAddress; + }else{ + ba_addr = interfacePriv->bssid.a; + } + for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ + ba_session = interfacePriv->ba_session_tx[ba_session_idx]; + if (ba_session){ + if ((!memcmp(ba_session->macAddress.a, ba_addr, ETH_ALEN)) && (ba_session->tID == priority)){ + req->TransmissionControl |= CSR_ALLOW_BA; + break; + } + } + } + + unifi_trace(priv, UDBG5, "leaving unifi_frame_ma_packet_req\n"); +} + +#ifdef CSR_SUPPORT_SME + +#define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001 +#define TRANSMISSION_CONTROL_ESOP_MASK 0x0002 + +static +int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered_pkt, + CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool moreData , CsrBool eosp) +{ + + CSR_SIGNAL signal; + bulk_data_param_t bulkdata; + int result; + CsrUint8 toDs, fromDs, macHeaderLengthInBytes = MAC_HEADER_SIZE; + CsrUint8 *qc; + CsrUint16 *fc = (CsrUint16*)(buffered_pkt->bulkdata.os_data_ptr); + unsigned long lock_flags; + unifi_trace(priv, UDBG3, "frame_and_send_queued_pdu with moreData: %d , EOSP: %d\n",moreData,eosp); + unifi_frame_ma_packet_req(priv, buffered_pkt->priority, buffered_pkt->rate, buffered_pkt->hostTag, + buffered_pkt->interfaceTag, buffered_pkt->transmissionControl, + buffered_pkt->leSenderProcessId, buffered_pkt->peerMacAddress.a, &signal); + bulkdata.d[0].os_data_ptr = buffered_pkt->bulkdata.os_data_ptr; + bulkdata.d[0].data_length = buffered_pkt->bulkdata.data_length; + bulkdata.d[0].os_net_buf_ptr = buffered_pkt->bulkdata.os_net_buf_ptr; + bulkdata.d[0].net_buf_length = buffered_pkt->bulkdata.net_buf_length; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].data_length = 0; + bulkdata.d[1].os_net_buf_ptr =0; + bulkdata.d[1].net_buf_length =0; + + if(moreData) { + *fc |= cpu_to_le16(IEEE802_11_FC_MOREDATA_MASK); + } else { + *fc &= cpu_to_le16(~IEEE802_11_FC_MOREDATA_MASK); + } + + if((staRecord != NULL)&& (staRecord->wmmOrQosEnabled == TRUE)) + { + unifi_trace(priv, UDBG3, "frame_and_send_queued_pdu WMM Enabled: %d \n",staRecord->wmmOrQosEnabled); + + toDs = (*fc & cpu_to_le16(IEEE802_11_FC_TO_DS_MASK))?1 : 0; + fromDs = (*fc & cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK))? 1: 0; + + switch(le16_to_cpu(*fc) & IEEE80211_FC_SUBTYPE_MASK) + { + case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: + case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK: + /* If both are set then the Address4 exists (only for AP) */ + if (fromDs && toDs) + { + /* 6 is the size of Address4 field */ + macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6); + } + else + { + macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; + } + + /* If order bit set then HT control field is the part of MAC header */ + if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { + macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE; + } + break; + default: + if (fromDs && toDs) + macHeaderLengthInBytes += 6; + break; + } + + if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { + qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6)); + } else { + qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2)); + } + + *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4)); + } + result = ul_send_signal_unpacked(priv, &signal, &bulkdata); + if(result){ + _update_buffered_pkt_params_after_alignment(priv, &bulkdata,buffered_pkt); + } + + /* Decrement the packet counts queued in driver */ + if (result != -ENOSPC) { + /* protect entire counter updation by disabling preemption */ + if (!priv->noOfPktQueuedInDriver) { + unifi_error(priv, "packets queued in driver 0 still decrementing\n"); + } else { + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + priv->noOfPktQueuedInDriver--; + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + } + /* Sta Record is available for all unicast (except genericMgt Frames) & in other case its NULL */ + if (staRecord) { + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + if (!staRecord->noOfPktQueued) { + unifi_error(priv, "packets queued in driver per station is 0 still decrementing\n"); + } else { + staRecord->noOfPktQueued--; + } + /* if the STA alive probe frame has failed then reset the saved host tag */ + if (result){ + if (staRecord->nullDataHostTag == buffered_pkt->hostTag){ + staRecord->nullDataHostTag = INVALID_HOST_TAG; + } + } + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } + + } + return result; +} +#ifdef CSR_SUPPORT_SME +static +void set_eosp_transmit_ctrl(unifi_priv_t *priv, struct list_head *txList) +{ + /* dequeue the tx data packets from the appropriate queue */ + tx_buffered_packets_t *tx_q_item = NULL; + struct list_head *listHead; + struct list_head *placeHolder; + unsigned long lock_flags; + + + unifi_trace(priv, UDBG5, "entering set_eosp_transmit_ctrl\n"); + /* check for list empty */ + if (list_empty(txList)) { + unifi_warning(priv, "In set_eosp_transmit_ctrl, the list is empty\n"); + return; + } + + /* return the last node , and modify it. */ + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_prev_safe(listHead, placeHolder, txList) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); + unifi_trace(priv, UDBG1, + "set_eosp_transmit_ctrl Transmission Control = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag); + unifi_trace(priv,UDBG3,"in set_eosp_transmit_ctrl no.of buffered frames %d\n",priv->noOfPktQueuedInDriver); + break; + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + unifi_trace(priv, UDBG1,"List Empty %d\n",list_empty(txList)); + unifi_trace(priv, UDBG5, "leaving set_eosp_transmit_ctrl\n"); + return; +} + +static +void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RESULT_CODE resultCode) +{ + CSR_SIGNAL signal; + CSR_MA_VIF_AVAILABILITY_RESPONSE *rsp; + bulk_data_param_t *bulkdata = NULL; + int r; + + memset(&signal,0,sizeof(CSR_SIGNAL)); + rsp = &signal.u.MaVifAvailabilityResponse; + rsp->VirtualInterfaceIdentifier = vif; + rsp->ResultCode = resultCode; + signal.SignalPrimitiveHeader.SignalId = CSR_MA_VIF_AVAILABILITY_RESPONSE_ID; + signal.SignalPrimitiveHeader.ReceiverProcessId = 0; + signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; + + /* Send the signal to UniFi */ + r = ul_send_signal_unpacked(priv, &signal, bulkdata); + if(r) { + unifi_error(priv,"Availibility response sending failed %x status %d\n",vif,r); + } +} +#endif + +static +void verify_and_accomodate_tx_packet(unifi_priv_t *priv) +{ + tx_buffered_packets_t *tx_q_item; + unsigned long lock_flags; + struct list_head *listHead, *list; + struct list_head *placeHolder; + CsrUint8 i, j,eospFramedeleted=0; + CsrBool thresholdExcedeDueToBroadcast = TRUE; + /* it will be made it interface Specific in the future when multi interfaces are supported , + right now interface 0 is considered */ + netInterface_priv_t *interfacePriv = priv->interfacePriv[0]; + CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; + + unifi_trace(priv, UDBG3, "entering verify_and_accomodate_tx_packet\n"); + + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + staInfo = interfacePriv->staInfo[i]; + if (staInfo && (staInfo->noOfPktQueued >= CSR_WIFI_DRIVER_MAX_PKT_QUEUING_THRESHOLD_PER_PEER)) { + /* remove the first(oldest) packet from the all the access catogory, since data + * packets for station record crossed the threshold limit (64 for AP supporting + * 8 peers) + */ + unifi_trace(priv,UDBG3,"number of station pkts queued= %d for sta id = %d\n", staInfo->noOfPktQueued, staInfo->aid); + for(j = 0; j < MAX_ACCESS_CATOGORY; j++) { + list = &staInfo->dataPdu[j]; + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHead, placeHolder, list) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + list_del(listHead); + thresholdExcedeDueToBroadcast = FALSE; + unifi_net_data_free(priv, &tx_q_item->bulkdata); + kfree(tx_q_item); + tx_q_item = NULL; + if (!priv->noOfPktQueuedInDriver) { + unifi_error(priv, "packets queued in driver 0 still decrementing in %s\n", __FUNCTION__); + } else { + /* protection provided by spinlock */ + priv->noOfPktQueuedInDriver--; + + } + /* Sta Record is available for all unicast (except genericMgt Frames) & in other case its NULL */ + if (!staInfo->noOfPktQueued) { + unifi_error(priv, "packets queued in driver per station is 0 still decrementing in %s\n", __FUNCTION__); + } else { + spin_lock(&priv->staRecord_lock); + staInfo->noOfPktQueued--; + spin_unlock(&priv->staRecord_lock); + } + break; + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + } + } + } + if (thresholdExcedeDueToBroadcast && interfacePriv->noOfbroadcastPktQueued > CSR_WIFI_DRIVER_MINIMUM_BROADCAST_PKT_THRESHOLD ) { + /* Remove the packets from genericMulticastOrBroadCastFrames queue + * (the max packets in driver is reached due to broadcast/multicast frames) + */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + if(eospFramedeleted){ + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); + unifi_trace(priv, UDBG1,"updating eosp for next packet hostTag:= 0x%x ",tx_q_item->hostTag); + eospFramedeleted =0; + break; + } + + if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK ){ + eospFramedeleted = 1; + } + unifi_trace(priv,UDBG1, "freeing of multicast packets ToC = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag); + list_del(listHead); + unifi_net_data_free(priv, &tx_q_item->bulkdata); + kfree(tx_q_item); + priv->noOfPktQueuedInDriver--; + spin_lock(&priv->staRecord_lock); + interfacePriv->noOfbroadcastPktQueued--; + spin_unlock(&priv->staRecord_lock); + if(!eospFramedeleted){ + break; + } + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + } + unifi_trace(priv, UDBG3, "leaving verify_and_accomodate_tx_packet\n"); +} + +static +CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata, + struct list_head *list, CSR_SIGNAL *signal, + CsrBool requeueOnSamePos) +{ + + /* queue the tx data packets on to appropriate queue */ + CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; + tx_buffered_packets_t *tx_q_item; + unsigned long lock_flags; + + unifi_trace(priv, UDBG5, "entering enque_tx_data_pdu\n"); + if(!list) { + unifi_error(priv,"List is not specified\n"); + return CSR_RESULT_FAILURE; + } + + /* Removes aged packets & adds the incoming packet */ + if (priv->noOfPktQueuedInDriver >= CSR_WIFI_DRIVER_SUPPORT_FOR_MAX_PKT_QUEUEING) { + unifi_trace(priv,UDBG3,"number of pkts queued= %d \n", priv->noOfPktQueuedInDriver); + verify_and_accomodate_tx_packet(priv); + } + + + + tx_q_item = (tx_buffered_packets_t *)kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); + if (tx_q_item == NULL) { + unifi_error(priv, + "Failed to allocate %d bytes for tx packet record\n", + sizeof(tx_buffered_packets_t)); + func_exit(); + return CSR_RESULT_FAILURE; + } + + /* disable the preemption */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + INIT_LIST_HEAD(&tx_q_item->q); + /* fill the tx_q structure members */ + tx_q_item->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; + tx_q_item->bulkdata.data_length = bulkdata->d[0].data_length; + tx_q_item->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; + tx_q_item->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; + tx_q_item->interfaceTag = req->VirtualInterfaceIdentifier & 0xff; + tx_q_item->hostTag = req->HostTag; + tx_q_item->leSenderProcessId = signal->SignalPrimitiveHeader.SenderProcessId; + tx_q_item->transmissionControl = req->TransmissionControl; + tx_q_item->priority = req->Priority; + tx_q_item->rate = req->TransmitRate; + memcpy(tx_q_item->peerMacAddress.a, req->Ra.x, ETH_ALEN); + + + + if (requeueOnSamePos) { + list_add(&tx_q_item->q, list); + } else { + list_add_tail(&tx_q_item->q, list); + } + + /* Count of packet queued in driver */ + priv->noOfPktQueuedInDriver++; + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n"); + return CSR_RESULT_SUCCESS; +} +static +CsrResult enque_direceted_ma_pkt_cfm_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata, + struct list_head *list, CSR_SIGNAL *signal, + CsrBool requeueOnSamePos) +{ + + /* queue the tx data packets on to appropriate queue */ + CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; + tx_buffered_packets_t *tx_q_item; + + + unifi_trace(priv, UDBG5, "entering enque_tx_data_pdu\n"); + if(!list ) { + unifi_error(priv,"List is not specified\n"); + return CSR_RESULT_FAILURE; + } + if(!requeueOnSamePos && !list->prev){ + unifi_error(priv,"List prev is NULL so don't requeu it\n"); + return CSR_RESULT_FAILURE; + + } + + + + tx_q_item = (tx_buffered_packets_t *)kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); + if (tx_q_item == NULL) { + unifi_error(priv, + "Failed to allocate %d bytes for tx packet record\n", + sizeof(tx_buffered_packets_t)); + func_exit(); + return CSR_RESULT_FAILURE; + } + /* disable the preemption */ + INIT_LIST_HEAD(&tx_q_item->q); + /* fill the tx_q structure members */ + tx_q_item->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; + tx_q_item->bulkdata.data_length = bulkdata->d[0].data_length; + tx_q_item->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; + tx_q_item->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; + tx_q_item->interfaceTag = req->VirtualInterfaceIdentifier & 0xff; + tx_q_item->hostTag = req->HostTag; + tx_q_item->leSenderProcessId = signal->SignalPrimitiveHeader.SenderProcessId; + tx_q_item->transmissionControl = req->TransmissionControl; + tx_q_item->priority = req->Priority; + tx_q_item->rate = req->TransmitRate; + memcpy(tx_q_item->peerMacAddress.a, req->Ra.x, ETH_ALEN); + + + + if (requeueOnSamePos) { + list_add(&tx_q_item->q, list); + } else { + list_add_tail(&tx_q_item->q, list); + } + + /* Count of packet queued in driver */ + priv->noOfPktQueuedInDriver++; + unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n"); + return CSR_RESULT_SUCCESS; +} + +static void is_all_ac_deliver_enabled_and_moredata(CsrWifiRouterCtrlStaInfo_t *staRecord, CsrUint8 *allDeliveryEnabled, CsrUint8 *dataAvailable) +{ + CsrUint8 i; + *allDeliveryEnabled = TRUE; + for (i = 0 ;i < MAX_ACCESS_CATOGORY; i++) { + if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) { + /* One is is not Delivery Enabled */ + *allDeliveryEnabled = FALSE; + break; + } + } + if (*allDeliveryEnabled) { + *dataAvailable = (!list_empty(&staRecord->dataPdu[0]) || !list_empty(&staRecord->dataPdu[1]) + ||!list_empty(&staRecord->dataPdu[2]) ||!list_empty(&staRecord->dataPdu[3]) + ||!list_empty(&staRecord->mgtFrames)); + } +} + +/* + * --------------------------------------------------------------------------- + * uf_handle_tim_cfm + * + * + * This function updates tim status in host depending confirm status from firmware + * + * Arguments: + * priv Pointer to device private context struct + * cfm CSR_MLME_SET_TIM_CONFIRM + * receiverProcessId SenderProcessID to fetch handle & timSet status + * + * --------------------------------------------------------------------------- + */ +void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUint16 receiverProcessId) +{ + CsrUint8 handle = CSR_WIFI_GET_STATION_HANDLE_FROM_RECEIVER_ID(receiverProcessId); + CsrUint8 timSetStatus = CSR_WIFI_GET_TIMSET_STATE_FROM_RECEIVER_ID(receiverProcessId); + CsrUint16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff); + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + /* This variable holds what TIM value we wanted to set in firmware */ + CsrUint16 timSetValue = 0; + /* Irrespective of interface the count maintained */ + static CsrUint8 retryCount = 0; + unsigned long lock_flags; + unifi_trace(priv, UDBG3, "entering %s, handle = %x, timSetStatus = %x\n", __FUNCTION__, handle, timSetStatus); + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_warning(priv, "bad interfaceTag = %x\n", interfaceTag); + return; + } + + if ((handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) && (handle >= UNIFI_MAX_CONNECTIONS)) { + unifi_warning(priv, "bad station Handle = %x\n", handle); + return; + } + + if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + if ((staRecord = ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle]))) == NULL) { + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + unifi_warning(priv, "uf_handle_tim_cfm: station record is NULL handle = %x\n", handle); + return; + } + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } + switch(timSetStatus) + { + case CSR_WIFI_TIM_SETTING: + timSetValue = CSR_WIFI_TIM_SET; + break; + case CSR_WIFI_TIM_RESETTING: + timSetValue = CSR_WIFI_TIM_RESET; + break; + default: + unifi_warning(priv, "timSet state is %x: Debug\n", timSetStatus); + return; + } + + /* check TIM confirm for success/failures */ + switch(cfm->ResultCode) + { + case CSR_RC_SUCCESS: + if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { + /* Unicast frame & station record available */ + if (timSetStatus == staRecord->timSet) { + staRecord->timSet = timSetValue; + /* fh_cmd_q can also be full at some point of time!, + * resetting count as queue is cleaned by firmware at this point + */ + retryCount = 0; + unifi_trace(priv, UDBG2, "tim (%s) successfully in firmware\n", (timSetValue)?"SET":"RESET"); + } else { + unifi_trace(priv, UDBG3, "receiver processID = %x, success: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x, handle = %x\n", + receiverProcessId, timSetStatus, staRecord->timSet, handle); + } + } else { + /* fh_cmd_q can also be full at some point of time!, + * resetting count as queue is cleaned by firmware at this point + */ + retryCount = 0; + unifi_trace(priv, UDBG3, "tim (%s) successfully for broadcast frame in firmware\n", (timSetValue)?"SET":"RESET"); + } + break; + case CSR_RC_INVALID_PARAMETERS: + case CSR_RC_INSUFFICIENT_RESOURCE: + /* check for max retry limit & send again + * MAX_RETRY_LIMIT is not maintained for each set of transactions..Its generic + * If failure crosses this Limit, we have to take a call to FIX + */ + if (retryCount > UNIFI_MAX_RETRY_LIMIT) { + CsrBool moreData = FALSE; + retryCount = 0; + /* Because of continuos traffic in fh_cmd_q the tim set request is failing (exceeding retry limit) + * but if we didn't synchronize our timSet varible state with firmware then it can cause below issues + * cond 1. We want to SET tim in firmware if its fails & max retry limit reached + * -> If host set's the timSet to 1, we wont try to send(as max retry reached) update tim but + * firmware is not updated with queue(TIM) status so it wont set TIM in beacon finally host start piling + * up data & wont try to set tim in firmware (This can cause worser performance) + * cond 2. We want to reset tim in firmware it fails & reaches max retry limit + * -> If host sets the timSet to Zero, it wont try to set a TIM request unless we wont have any packets + * to be queued, so beacon unnecessarily advertizes the TIM + */ + + if(staRecord) { + if(!staRecord->wmmOrQosEnabled) { + moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || + !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || + !list_empty(&staRecord->mgtFrames)); + } else { + /* Peer is QSTA */ + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); + /*check for more data in non-delivery enabled queues*/ + moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)); + + } + /* To avoid cond 1 & 2, check internal Queues status, if we have more Data then set RESET the timSet(0), + * so we are trying to be in sync with firmware & next packets before queuing atleast try to + * set TIM in firmware otherwise it SET timSet(1) + */ + if (moreData) { + staRecord->timSet = CSR_WIFI_TIM_RESET; + } else { + staRecord->timSet = CSR_WIFI_TIM_SET; + } + } else { + /* Its a broadcast frames */ + moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || + !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); + if (moreData) { + update_tim(priv, 0, CSR_WIFI_TIM_SET, interfaceTag, 0xFFFFFFFF); + } else { + update_tim(priv, 0, CSR_WIFI_TIM_RESET, interfaceTag, 0xFFFFFFFF); + } + } + + unifi_error(priv, "no of error's for TIM setting crossed the Limit: verify\n"); + return; + } + retryCount++; + + if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { + if (timSetStatus == staRecord->timSet) { + unifi_warning(priv, "tim request failed, retry for AID = %x\n", staRecord->aid); + update_tim(priv, staRecord->aid, timSetValue, interfaceTag, handle); + } else { + unifi_trace(priv, UDBG1, "failure: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x\n", + timSetStatus, staRecord->timSet); + } + } else { + unifi_warning(priv, "tim request failed, retry for broadcast frames\n"); + update_tim(priv, 0, timSetValue, interfaceTag, 0xFFFFFFFF); + } + break; + default: + unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode); + } + unifi_trace(priv, UDBG2, "leaving %s\n", __FUNCTION__); +} + +/* + * --------------------------------------------------------------------------- + * update_tim + * + * + * This function updates tim status in firmware for AID[1 to UNIFI_MAX_CONNECTIONS] or + * AID[0] for broadcast/multicast packets. + * + * NOTE: The LSB (least significant BYTE) of senderId while sending this MLME premitive + * has been modified(utilized) as below + * + * SenderID in signal's SignalPrimitiveHeader is 2 byte the lowe byte bitmap is below + * + * station handle(6 bits) timSet Status (2 bits) + * --------------------- ---------------------- + * 0 0 0 0 0 0 | 0 0 + * + * timSet Status can be one of below: + * + * CSR_WIFI_TIM_RESET + * CSR_WIFI_TIM_RESETTING + * CSR_WIFI_TIM_SET + * CSR_WIFI_TIM_SETTING + * + * Arguments: + * priv Pointer to device private context struct + * aid can be 1 t0 UNIFI_MAX_CONNECTIONS & 0 means multicast/broadcast + * setTim value SET(1) / RESET(0) + * interfaceTag the interfaceID on which activity going on + * handle from (0 <= handle < UNIFI_MAX_CONNECTIONS) + * + * --------------------------------------------------------------------------- + */ +void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 interfaceTag, CsrUint32 handle) +{ + CSR_SIGNAL signal; + CsrInt32 r; + CSR_MLME_SET_TIM_REQUEST *req = &signal.u.MlmeSetTimRequest; + bulk_data_param_t *bulkdata = NULL; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrUint8 senderIdLsb = 0; + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + CsrUint32 oldTimSetStatus = 0, timSetStatus = 0; + + unifi_trace(priv, UDBG5, "entering the update_tim routine\n"); + + if (handle == 0xFFFFFFFF) { + handle &= CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE; + } else if ((handle != 0xFFFFFFFF) && (handle >= UNIFI_MAX_CONNECTIONS)) { + unifi_warning(priv, "bad station Handle = %x\n", handle); + return; + } + + if (setTim) { + timSetStatus = CSR_WIFI_TIM_SETTING; + } else { + timSetStatus = CSR_WIFI_TIM_RESETTING; + } + + if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { + if ((staRecord = ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle]))) == NULL) { + unifi_warning(priv, "station record is NULL in update_tim: handle = %x :debug\n", handle); + return; + } + /* In case of signal sending failed, revert back to old state */ + oldTimSetStatus = staRecord->timSet; + staRecord->timSet = timSetStatus; + } + + /* pack senderID LSB */ + senderIdLsb = CSR_WIFI_PACK_SENDER_ID_LSB_FOR_TIM_REQ(handle, timSetStatus); + + /* initialize signal to zero */ + memset(&signal, 0, sizeof(CSR_SIGNAL)); + + /* Frame the MLME-SET-TIM request */ + signal.SignalPrimitiveHeader.SignalId = CSR_MLME_SET_TIM_REQUEST_ID; + signal.SignalPrimitiveHeader.ReceiverProcessId = 0; + CSR_COPY_UINT16_TO_LITTLE_ENDIAN(((priv->netdev_client->sender_id & 0xff00) | senderIdLsb), + (u8*)&signal.SignalPrimitiveHeader.SenderProcessId); + + /* set The virtual interfaceIdentifier, aid, tim value */ + req->VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag); + req->AssociationId = aid; + req->TimValue = setTim; + + + unifi_trace(priv, UDBG2, "update_tim:AID %x,senderIdLsb = 0x%x, handle = 0x%x, timSetStatus = %x, sender proceesID = %x \n", + aid,senderIdLsb, handle, timSetStatus, signal.SignalPrimitiveHeader.SenderProcessId); + + /* Send the signal to UniFi */ + r = ul_send_signal_unpacked(priv, &signal, bulkdata); + if (r) { + /* No need to free bulk data, as TIM request doesn't carries any data */ + unifi_error(priv, "Error queueing CSR_MLME_SET_TIM_REQUEST signal\n"); + if (staRecord) { + staRecord->timSet = oldTimSetStatus ; + } + } + unifi_trace(priv, UDBG5, "leaving the update_tim routine\n"); +} + +static +void process_peer_active_transition(unifi_priv_t * priv, + CsrWifiRouterCtrlStaInfo_t *staRecord, + CsrUint16 interfaceTag) +{ + int r,i; + CsrBool spaceAvail[4] = {TRUE,TRUE,TRUE,TRUE}; + tx_buffered_packets_t * buffered_pkt = NULL; + unsigned long lock_flags; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + unifi_trace(priv, UDBG5, "entering process_peer_active_transition\n"); + + if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) { + /* giving more priority to multicast packets so delaying unicast packets*/ + unifi_trace(priv,UDBG2," multicast transmission is going on so resume unicast transmission after DTIM over\n"); + return; + } + while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) { + unifi_trace(priv, UDBG2, "p_p_a_t:(ENOSPC) Mgt Frame queueing \n"); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->mgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[3]=(CsrUint8)(staRecord->assignedHandle); + spaceAvail[3] = FALSE; + break; + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + if (staRecord->txSuspend) { + if(staRecord->timSet == CSR_WIFI_TIM_SET) { + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + return; + } + for(i=3;i>=0;i--) { + if(!spaceAvail[i]) + continue; + unifi_trace(priv, UDBG6, "p_p_a_t:data pkt sending for AC %d \n",i); + while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->dataPdu[i]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[i]=(CsrUint8)(staRecord->assignedHandle); + break; + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + } + if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){ + unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n"); + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + unifi_trace(priv, UDBG5, "leaving process_peer_active_transition\n"); +} + + + +void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm) +{ + netInterface_priv_t *interfacePriv; + CsrUint8 i; + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + struct list_head *listHeadMaPktreq,*listHeadStaQueue; + struct list_head *placeHolderMaPktreq,*placeHolderStaQueue; + unsigned long lock_flags; + unsigned long lock_flags1; + maPktReqList_t *maPktreq = NULL; + tx_buffered_packets_t *tx_q_item = NULL; + bulk_data_param_t bulkdata; + CsrBool entryFound = FALSE; + interfacePriv = priv->interfacePriv[interfaceTag]; + + + if(pkt_cfm->HostTag == interfacePriv->multicastPduHostTag) { + unifi_trace(priv,UDBG2,"CFM for marked Multicast Tag = %x\n",interfacePriv->multicastPduHostTag); + interfacePriv->multicastPduHostTag = 0xffffffff; + resume_suspended_uapsd(priv,interfaceTag); + resume_unicast_buffered_frames(priv,interfaceTag); + if(list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) && + list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { + unifi_trace(priv,UDBG1,"Resetting multicastTIM"); + update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF); + } + return; + } + + /* Check if a copy of the same frame (identified by host tag) is queued in driver */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) { + maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); + if(maPktreq->hostTag == pkt_cfm->HostTag){ + entryFound = TRUE; + break; + } + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + + if(entryFound){ + + /* Monitor the time difference between the MA-PACKET.req and MA-PACKET.cfm */ + unsigned long timeout; + timeout = (long)jiffies - (long)maPktreq->jiffeTime; + + /* convert into milliseconds */ + timeout = jiffies_to_msecs(timeout); + unifi_trace(priv, UDBG3, "Jiffies Time: Host Tag(%x) --> Req(%u) Cfm(%u) Diff (in ms): %u\n",maPktreq->hostTag,maPktreq->jiffeTime, jiffies, timeout); + + if( (timeout/1000) > 1) + { + unifi_trace(priv, UDBG1, "Confirm time > 2 Seconds: time = %u Status = %x\n", (timeout/1000), pkt_cfm->TransmissionStatus); + } + + if( CSR_TX_LIFETIME == pkt_cfm->TransmissionStatus || + CSR_TX_BLOCK_ACK_TIMEOUT== pkt_cfm->TransmissionStatus || + CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED== pkt_cfm->TransmissionStatus || + CSR_TX_REJECTED_PEER_STATION_SLEEPING== pkt_cfm->TransmissionStatus || + CSR_TX_REJECTED_DTIM_STARTED== pkt_cfm->TransmissionStatus ){ + + CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler]; + unifi_TrafficQueue priority_q; + struct list_head *list; + CsrResult result; + CSR_MA_PACKET_REQUEST *req = &maPktreq->signal.u.MaPacketRequest; + CsrUint16 ii=0; + CsrBool locationFound = FALSE; + CsrUint8 *sigbuffer; + + sigbuffer = (CsrUint8*)&maPktreq->signal; + if(req->Priority == CSR_MANAGEMENT){ + list = &staRecord->mgtFrames; + unifi_trace(priv,UDBG5,"mgmt list priority %d\n",req->Priority); + } + else{ + priority_q= unifi_frame_priority_to_queue(req->Priority); + list = &staRecord->dataPdu[priority_q]; + unifi_trace(priv,UDBG5,"data list priority %d\n",req->Priority); + } + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHeadStaQueue, placeHolderStaQueue, list){ + tx_q_item = list_entry(listHeadStaQueue, tx_buffered_packets_t, q); + COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item->hostTag ,maPktreq->hostTag) + + + } + if(sigbuffer[SIZEOF_SIGNAL_HEADER + 1]){ + skb_pull(maPktreq->skb,sigbuffer[SIZEOF_SIGNAL_HEADER + 1]); + } + + /* enqueue the failed packet sta queue*/ + bulkdata.d[0].os_net_buf_ptr= (unsigned char*)maPktreq->skb; + bulkdata.d[0].os_data_ptr = maPktreq->skb->data; + bulkdata.d[0].data_length = bulkdata.d[0].net_buf_length = maPktreq->skb->len; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].data_length = bulkdata.d[0].net_buf_length = 0; + unifi_trace(priv,UDBG4,"Cfm Fail for HosTag = %x with status %d so requeue it\n",maPktreq->hostTag,pkt_cfm->TransmissionStatus ); + req->TransmissionControl = 0; + + if(!locationFound){ + + if(list_empty(list)){ + result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1); + } + else{ + unifi_trace(priv,UDBG4,"did not find location so add to end of list \n"); + result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,0); + } + + + } + + else { + if(ii > 1){ + unifi_trace(priv,UDBG4,"find the location in the middle of list \n"); + result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, listHeadStaQueue,&maPktreq->signal,0); + + } + else{ + unifi_trace(priv,UDBG4," add at begining of list \n"); + result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1); + } + } + + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + + /* Increment the counter */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags1); + staRecord->noOfPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags1); + + + + + /* after enqueuing update the TIM */ + if(CSR_RESULT_SUCCESS == result){ + if(CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE == staRecord->currentPeerState) { + if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) { + if(!staRecord->wmmOrQosEnabled) { + unifi_trace(priv, UDBG3, "uf_process_ma_pkt_cfm_for_ap :tim set due to unicast pkt & peer in powersave\n"); + update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle); + } + else { + /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); + if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) { + update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle); + } + } + } + } + } + else{ + dev_kfree_skb(maPktreq->skb); + } + } + else + { + CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler]; + if (CSR_TX_RETRY_LIMIT == pkt_cfm->TransmissionStatus || + CSR_TX_NO_BSS == pkt_cfm->TransmissionStatus) + { + if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) + { + unifi_trace(priv, UDBG2, "CFM failed with Retry Limit or No BSS --> update TIM\n"); + update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle); + } + } + else if (CSR_TX_SUCCESSFUL == pkt_cfm->TransmissionStatus) + { + staRecord->activity_flag = TRUE; + } + unifi_trace(priv, UDBG5, "CFM for HosTag = %x Status = %d, Free SKB reference\n", + maPktreq->hostTag, + pkt_cfm->TransmissionStatus ); + + dev_kfree_skb(maPktreq->skb); + + } + list_del(listHeadMaPktreq); + kfree(maPktreq); + + }else{ + /* Check if it is a Confirm for null data frame used + * for probing station activity + */ + for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { + staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); + if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) { + + unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n", + pkt_cfm->HostTag, + pkt_cfm->TransmissionStatus + ); + staRecord->nullDataHostTag = INVALID_HOST_TAG; + + if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){ + CsrTime now; + CsrTime inactive_time; + + unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n"); + /* Recheck if there is some activity after null data is sent. + * + * If still there is no activity then send a disconnected indication + * to SME to delete the station record. + */ + if (staRecord->activity_flag){ + return; + } + now = CsrTimeGet(NULL); + + if (staRecord->lastActivity > now) + { + /* simple timer wrap (for 1 wrap) */ + inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity), + now); + } + else + { + inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity); + } + + if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) + { + struct list_head send_cfm_list; + CsrUint8 j; + + /* The SME/NME may be waiting for confirmation for requested frames to this station. + * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a + * a defensive check, it loops through buffered frames for this station and if confirmation + * is requested, send auto confirmation with failure status. Also flush the frames so + * that these are not processed again in PEER_DEL_REQ handler. + */ + INIT_LIST_HEAD(&send_cfm_list); + + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staRecord->mgtFrames)); + + uf_flush_list(priv, &(staRecord->mgtFrames)); + + for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staRecord->dataPdu[j])); + + uf_flush_list(priv,&(staRecord->dataPdu[j])); + } + + send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list); + + + + unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", + staRecord->peerMacAddress.a[0], + staRecord->peerMacAddress.a[1], + staRecord->peerMacAddress.a[2], + staRecord->peerMacAddress.a[3], + staRecord->peerMacAddress.a[4], + staRecord->peerMacAddress.a[5]); + + CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, + 0, + staRecord->interfacePriv->InterfaceTag, + staRecord->peerMacAddress, + CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); + } + + } + else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL) + { + staRecord->activity_flag = TRUE; + } + } + } + } +} + +#endif +CsrUint16 uf_get_vif_identifier (CsrWifiRouterCtrlMode mode, CsrUint16 tag) +{ + switch(mode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + return (0x02<<8|tag); + + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + return (0x03<<8|tag); + + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + return (0x01<<8|tag); + + case CSR_WIFI_ROUTER_CTRL_MODE_MONITOR: + return (0x04<<8|tag); + case CSR_WIFI_ROUTER_CTRL_MODE_AMP: + return (0x05<<8|tag); + default: + return tag; + } +} + +#ifdef CSR_SUPPORT_SME + +/* + * --------------------------------------------------------------------------- + * update_macheader + * + * + * These functions updates mac header for intra BSS packet + * routing. + * NOTE: This function always has to be called in rx context which + * is in bh thread context since GFP_KERNEL is used. In soft IRQ/ Interrupt + * context shouldn't be used + * + * Arguments: + * priv Pointer to device private context struct + * skb Socket buffer containing data packet to transmit + * newSkb Socket buffer containing data packet + Mac header if no sufficient headroom in skb + * priority to append QOS control header in Mac header + * bulkdata if newSkb allocated then bulkdata updated to send to unifi + * interfaceTag the interfaceID on which activity going on + * macHeaderLengthInBytes no. of bytes of mac header in received frame + * qosDestination used to append Qos control field + * + * Returns: + * Zero on success or -1 on error. + * --------------------------------------------------------------------------- + */ + +static int update_macheader(unifi_priv_t *priv, struct sk_buff *skb, + struct sk_buff *newSkb, CSR_PRIORITY *priority, + bulk_data_param_t *bulkdata, CsrUint16 interfaceTag, + CsrUint8 macHeaderLengthInBytes, + CsrUint8 qosDestination) +{ + + CsrUint16 *fc = NULL; + CsrUint8 direction = 0, toDs, fromDs; + CsrUint8 *bufPtr = NULL; + CsrUint8 sa[ETH_ALEN], da[ETH_ALEN]; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + int headroom; + CsrUint8 macHeaderBuf[IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE] = {0}; + + unifi_trace(priv, UDBG5, "entering the update_macheader function\n"); + + /* temporary buffer for the Mac header storage */ + memcpy(macHeaderBuf, skb->data, macHeaderLengthInBytes); + + /* remove the Macheader from the skb */ + skb_pull(skb, macHeaderLengthInBytes); + + /* get the skb headroom for skb_push check */ + headroom = skb_headroom(skb); + + /* pointer to frame control field */ + fc = (CsrUint16*) macHeaderBuf; + + toDs = (*fc & cpu_to_le16(IEEE802_11_FC_TO_DS_MASK))?1 : 0; + fromDs = (*fc & cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK))? 1: 0; + unifi_trace(priv, UDBG5, "In update_macheader function, fromDs = %x, toDs = %x\n", fromDs, toDs); + direction = ((fromDs | (toDs << 1)) & 0x3); + + /* Address1 or 3 from the macheader */ + memcpy(da, macHeaderBuf+4+toDs*12, ETH_ALEN); + /* Address2, 3 or 4 from the mac header */ + memcpy(sa, macHeaderBuf+10+fromDs*(6+toDs*8), ETH_ALEN); + + unifi_trace(priv, UDBG3, "update_macheader:direction = %x\n", direction); + /* update the toDs, fromDs & address fields in Mac header */ + switch(direction) + { + case 2: + /* toDs = 1 & fromDs = 0 , toAp when frames received from peer + * while sending this packet to Destination the Mac header changed + * as fromDs = 1 & toDs = 0, fromAp + */ + *fc &= cpu_to_le16(~IEEE802_11_FC_TO_DS_MASK); + *fc |= cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK); + /* Address1: MAC address of the actual destination (4 = 2+2) */ + memcpy(macHeaderBuf + 4, da, ETH_ALEN); + /* Address2: The MAC address of the AP (10 = 2+2+6) */ + memcpy(macHeaderBuf + 10, &interfacePriv->bssid, ETH_ALEN); + /* Address3: MAC address of the actual source from mac header (16 = 2+2+6+6) */ + memcpy(macHeaderBuf + 16, sa, ETH_ALEN); + break; + case 3: + unifi_trace(priv, UDBG3, "when both the toDs & fromDS set, NOT SUPPORTED\n"); + break; + default: + unifi_trace(priv, UDBG3, "problem in decoding packet in update_macheader \n"); + return -1; + } + + /* frameType is Data always, Validation is done before calling this function */ + + /* check for the souce station type */ + switch(le16_to_cpu(*fc) & IEEE80211_FC_SUBTYPE_MASK) + { + case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: + /* No need to modify the qos control field */ + if (!qosDestination) { + + /* If source Sta is QOS enabled & if this bit set, then HTC is supported by + * peer station & htc field present in macHeader + */ + if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { + /* HT control field present in Mac header + * 6 = sizeof(qosControl) + sizeof(htc) + */ + macHeaderLengthInBytes -= 6; + } else { + macHeaderLengthInBytes -= 2; + } + /* Destination STA is non qos so change subtype to DATA */ + *fc &= cpu_to_le16(~IEEE80211_FC_SUBTYPE_MASK); + *fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); + /* remove the qos control field & HTC(if present). new macHeaderLengthInBytes is less than old + * macHeaderLengthInBytes so no need to verify skb headroom + */ + if (headroom < macHeaderLengthInBytes) { + unifi_trace(priv, UDBG1, " sufficient headroom not there to push updated mac header \n"); + return -1; + } + bufPtr = (CsrUint8 *) skb_push(skb, macHeaderLengthInBytes); + + /* update bulk data os_data_ptr */ + bulkdata->d[0].os_data_ptr = skb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata->d[0].data_length = skb->len; + + } else { + /* pointing to QOS control field */ + CsrUint8 qc; + if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { + qc = *((CsrUint8*)(macHeaderBuf + (macHeaderLengthInBytes - 4 - 2))); + } else { + qc = *((CsrUint8*)(macHeaderBuf + (macHeaderLengthInBytes - 2))); + } + + if ((qc & IEEE802_11_QC_TID_MASK) > 7) { + *priority = 7; + } else { + *priority = qc & IEEE802_11_QC_TID_MASK; + } + + unifi_trace(priv, UDBG1, "Incoming packet priority from QSTA is %x\n", *priority); + + if (headroom < macHeaderLengthInBytes) { + unifi_trace(priv, UDBG3, " sufficient headroom not there to push updated mac header \n"); + return -1; + } + bufPtr = (CsrUint8 *) skb_push(skb, macHeaderLengthInBytes); + } + break; + default: + { + bulk_data_param_t data_ptrs; + CsrResult csrResult; + unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n"); + + *priority = CSR_CONTENTION; + if (qosDestination) { + CsrUint8 qc = 0; + unifi_trace(priv, UDBG3, "destination is QOS station \n"); + /* prepare the qos control field */ + + qc |= CSR_QOS_UP0; + + /* no Amsdu is in ap buffer so eosp is left 0 */ + + if (da[0] & 0x1) { + /* multicast/broadcast frames, no acknowledgement needed */ + qc |= 1 << 5; + } + + /* update new Mac header Length with 2 = sizeof(qos control) */ + macHeaderLengthInBytes += 2; + + /* received DATA frame but destiantion is QOS station so update subtype to QOS*/ + *fc &= cpu_to_le16(~IEEE80211_FC_SUBTYPE_MASK); + *fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_DATA); + + /* appendQosControlOffset = macHeaderLengthInBytes - 2, since source sta is not QOS */ + macHeaderBuf[macHeaderLengthInBytes - 2] = qc; + /* txopLimit is 0 */ + macHeaderBuf[macHeaderLengthInBytes - 1] = 0; + if (headroom < macHeaderLengthInBytes) { + csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, " failed to allocate request_data. in update_macheader func\n"); + return -1; + } + newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); + newSkb->len = skb->len + macHeaderLengthInBytes; + + memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, + skb->data, skb->len); + + bulkdata->d[0].os_data_ptr = newSkb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; + bulkdata->d[0].data_length = newSkb->len; + + bufPtr = (CsrUint8*)data_ptrs.d[0].os_data_ptr; + + /* The old skb will not be used again */ + kfree_skb(skb); + } else { + /* skb headroom is sufficient to append Macheader */ + bufPtr = (CsrUint8*)skb_push(skb, macHeaderLengthInBytes); + bulkdata->d[0].os_data_ptr = skb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata->d[0].data_length = skb->len; + } + } else { + unifi_trace(priv, UDBG3, "destination is not a QSTA\n"); + if (headroom < macHeaderLengthInBytes) { + csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, " failed to allocate request_data. in update_macheader func\n"); + return -1; + } + newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); + newSkb->len = skb->len + macHeaderLengthInBytes; + + memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, + skb->data, skb->len); + + bulkdata->d[0].os_data_ptr = newSkb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; + bulkdata->d[0].data_length = newSkb->len; + + bufPtr = (CsrUint8*)data_ptrs.d[0].os_data_ptr; + + /* The old skb will not be used again */ + kfree_skb(skb); + } else { + /* skb headroom is sufficient to append Macheader */ + bufPtr = (CsrUint8*)skb_push(skb, macHeaderLengthInBytes); + bulkdata->d[0].os_data_ptr = skb->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata->d[0].data_length = skb->len; + } + } + } + } + + /* prepare the complete skb, by pushing the MAC header to the begining of the skb->data */ + unifi_trace(priv, UDBG5, "updated Mac Header: %d \n",macHeaderLengthInBytes); + memcpy(bufPtr, macHeaderBuf, macHeaderLengthInBytes); + + unifi_trace(priv, UDBG5, "leaving the update_macheader function\n"); + return 0; +} +/* + * --------------------------------------------------------------------------- + * uf_ap_process_data_pdu + * + * + * Takes care of intra BSS admission control & routing packets within BSS + * + * Arguments: + * priv Pointer to device private context struct + * skb Socket buffer containing data packet to transmit + * ehdr ethernet header to fetch priority of packet + * srcStaInfo source stations record for connection verification + * packed_signal + * signal_len + * signal MA-PACKET.indication signal + * bulkdata if newSkb allocated then bulkdata updated to send to unifi + * macHeaderLengthInBytes no. of bytes of mac header in received frame + * + * Returns: + * Zero on success(ap processing complete) or -1 if packet also have to be sent to NETDEV. + * --------------------------------------------------------------------------- + */ +int +uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, + struct ethhdr *ehdr, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + const CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata, + CsrUint8 macHeaderLengthInBytes) +{ + const CSR_MA_PACKET_INDICATION *ind = &(signal->u.MaPacketIndication); + CsrUint16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0x00ff); + struct sk_buff *newSkb = NULL; + /* pointer to skb or private skb created using skb_copy() */ + struct sk_buff *skbPtr = skb; + CsrBool sendToNetdev = FALSE; + CsrBool qosDestination = FALSE; + CSR_PRIORITY priority = CSR_CONTENTION; + CsrWifiRouterCtrlStaInfo_t *dstStaInfo = NULL; + netInterface_priv_t *interfacePriv; + + unifi_trace(priv, UDBG5, "entering uf_ap_process_data_pdu %d\n",macHeaderLengthInBytes); + /* InterfaceTag validation from MA_PACKET.indication */ + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_trace(priv, UDBG1, "Interface Tag is Invalid in uf_ap_process_data_pdu\n"); + unifi_net_data_free(priv, &bulkdata->d[0]); + return 0; + } + interfacePriv = priv->interfacePriv[interfaceTag]; + + if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) && + (interfacePriv->intraBssEnabled == FALSE)) { + unifi_trace(priv, UDBG2, "uf_ap_process_data_pdu:P2P GO intrabssEnabled?= %d\n", interfacePriv->intraBssEnabled); + + /*In P2P GO case, if intraBSS distribution Disabled then don't do IntraBSS routing */ + /* If destination in our BSS then drop otherwise give packet to netdev */ + dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfaceTag); + if (dstStaInfo) { + unifi_net_data_free(priv, &bulkdata->d[0]); + return 0; + } + /* May be associated P2PCLI trying to send the packets on backbone (Netdev) */ + return -1; + } + + if(!memcmp(ehdr->h_dest, interfacePriv->bssid.a, ETH_ALEN)) { + /* This packet will be given to the TCP/IP stack since this packet is for us(AP) + * No routing needed */ + unifi_trace(priv, UDBG4, "destination address is csr_ap\n"); + return -1; + } + + /* fetch the destination record from staion record database */ + dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfaceTag); + + /* AP mode processing, & if packet is unicast */ + if(!dstStaInfo) { + if (!(ehdr->h_dest[0] & 0x1)) { + /* destination not in station record & its a unicast packet, so pass the packet to network stack */ + unifi_trace(priv, UDBG3, "unicast frame & destination record not exist, send to netdev proto = %x\n", htons(skb->protocol)); + return -1; + } else { + /* packet is multicast/broadcast */ + /* copy the skb to skbPtr, send skb to netdev & skbPtr to multicast/broad cast list */ + unifi_trace(priv, UDBG5, "skb_copy, in uf_ap_process_data_pdu, protocol = %x\n", htons(skb->protocol)); + skbPtr = skb_copy(skb, GFP_KERNEL); + if(skbPtr == NULL) { + /* We don't have memory to don't send the frame in BSS*/ + unifi_notice(priv, "broacast/multicast frame can't be sent in BSS No memeory: proto = %x\n", htons(skb->protocol)); + return -1; + } + sendToNetdev = TRUE; + } + } else { + + /* validate the Peer & Destination Station record */ + if (uf_process_station_records_for_sending_data(priv, interfaceTag, srcStaInfo, dstStaInfo)) { + unifi_notice(priv, "uf_ap_process_data_pdu: station record validation failed \n"); + interfacePriv->stats.rx_errors++; + unifi_net_data_free(priv, &bulkdata->d[0]); + return 0; + } + } + + /* BroadCast packet received and it's been sent as non QOS packets. + * Since WMM spec not mandates broadcast/multicast to be sent as QOS data only, + * if all Peers are QSTA + */ + if(sendToNetdev) { + /* BroadCast packet and it's been sent as non QOS packets */ + qosDestination = FALSE; + } else if(dstStaInfo && (dstStaInfo->wmmOrQosEnabled == TRUE)) { + qosDestination = TRUE; + } + + unifi_trace(priv, UDBG3, "uf_ap_process_data_pdu QoS destination = %s\n", (qosDestination)? "TRUE": "FALSE"); + + /* packet is allowed to send to unifi, update the Mac header */ + if (update_macheader(priv, skbPtr, newSkb, &priority, bulkdata, interfaceTag, macHeaderLengthInBytes, qosDestination)) { + interfacePriv->stats.rx_errors++; + unifi_notice(priv, "(Packet Drop) failed to update the Mac header in uf_ap_process_data_pdu\n"); + if (sendToNetdev) { + /* Free's the skb_copy(skbPtr) data since packet processing failed */ + bulkdata->d[0].os_data_ptr = skbPtr->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skbPtr; + bulkdata->d[0].data_length = skbPtr->len; + unifi_net_data_free(priv, &bulkdata->d[0]); + } + return -1; + } + + unifi_trace(priv, UDBG3, "Mac Header updated...calling uf_process_ma_packet_req \n"); + + /* Packet is ready to send to unifi ,transmissionControl = 0x0004, confirmation is not needed for data packets */ + if (uf_process_ma_packet_req(priv, ehdr->h_dest, 0xffffffff, interfaceTag, CSR_NO_CONFIRM_REQUIRED, (CSR_RATE)0,priority, priv->netdev_client->sender_id, bulkdata)) { + if (sendToNetdev) { + unifi_trace(priv, UDBG1, "In uf_ap_process_data_pdu, (Packet Drop) uf_process_ma_packet_req failed. freeing skb_copy data (original data sent to Netdev)\n"); + /* Free's the skb_copy(skbPtr) data since packet processing failed */ + bulkdata->d[0].os_data_ptr = skbPtr->data; + bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skbPtr; + bulkdata->d[0].data_length = skbPtr->len; + unifi_net_data_free(priv, &bulkdata->d[0]); + } else { + /* This free's the skb data */ + unifi_trace(priv, UDBG1, "In uf_ap_process_data_pdu, (Packet Drop). Unicast data so freeing original skb \n"); + unifi_net_data_free(priv, &bulkdata->d[0]); + } + } + unifi_trace(priv, UDBG5, "leaving uf_ap_process_data_pdu\n"); + + if (sendToNetdev) { + /* The packet is multicast/broadcast, so after AP processing packet has to + * be sent to netdev, if peer port state is open + */ + unifi_trace(priv, UDBG4, "Packet will be routed to NetDev\n"); + return -1; + } + /* Ap handled the packet & its a unicast packet, no need to send to netdev */ + return 0; +} + +#endif + +CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, + CsrUint8 *peerMacAddress, + CSR_CLIENT_TAG hostTag, + CsrUint16 interfaceTag, + CSR_TRANSMISSION_CONTROL transmissionControl, + CSR_RATE TransmitRate, + CSR_PRIORITY priority, + CSR_PROCESS_ID leSenderProcessId, + bulk_data_param_t *bulkdata) +{ + CsrResult status = CSR_RESULT_SUCCESS; + CSR_SIGNAL signal; + int result; +#ifdef CSR_SUPPORT_SME + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + const CsrUint8 *macHdrLocation = bulkdata->d[0].os_data_ptr; + CsrWifiPacketType pktType; + int frameType = 0; + CsrBool queuePacketDozing = FALSE; + CsrUint32 priority_q; + CsrUint16 frmCtrl; + struct list_head * list = NULL; /* List to which buffered PDUs are to be enqueued*/ + CsrBool setBcTim=FALSE; + netInterface_priv_t *interfacePriv; + CsrBool requeueOnSamePos = FALSE; + CsrUint32 handle = 0xFFFFFFFF; + unsigned long lock_flags; + + UF_TRACE_MAC(priv, UDBG5, "entering uf_process_ma_packet_req, peer: ", peerMacAddress); + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "interfaceTag >= CSR_WIFI_NUM_INTERFACES, interfacetag = %d\n", interfaceTag); + return CSR_RESULT_FAILURE; + } + interfacePriv = priv->interfacePriv[interfaceTag]; + + + /* fetch the station record for corresponding peer mac address */ + if ((staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, peerMacAddress, interfaceTag))) { + handle = staRecord->assignedHandle; + } + + /* Frame ma-packet.req, this is saved/transmitted depend on queue state */ + unifi_frame_ma_packet_req(priv, priority, TransmitRate, hostTag, + interfaceTag, transmissionControl, leSenderProcessId, + peerMacAddress, &signal); + + /* Since it's common path between STA & AP mode, in case of STA packet + * need not to be queued but in AP case we have to queue PDU's in + * different scenarios + */ + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + /* For this mode processing done below */ + break; + default: + /* In case of STA/IBSS/P2PCLI/AMP, no checks needed send the packet down & return */ + unifi_trace(priv, UDBG5, "In %s, interface mode is %x \n", __FUNCTION__, interfacePriv->interfaceMode); + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_NONE) { + unifi_warning(priv, "In %s, interface mode NONE \n", __FUNCTION__); + } + if ((result = ul_send_signal_unpacked(priv, &signal, bulkdata))) { + status = CSR_RESULT_FAILURE; + } + return status; + } + + /* -----Only AP/P2pGO mode handling falls below----- */ + + /* convert priority to queue */ + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); + + /* check the powersave status of the peer */ + if (staRecord && (staRecord->currentPeerState == + CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)) { + /* Peer is dozing & packet have to be delivered, so buffer the packet & + * update the TIM + */ + queuePacketDozing = TRUE; + } + + /* find the type of frame unicast or mulicast/broadcast */ + if (*peerMacAddress & 0x1) { + /* Multicast/broadCast data are always triggered by vif_availability.ind + * at the DTIM + */ + pktType = CSR_WIFI_MULTICAST_PDU; + } else { + pktType = CSR_WIFI_UNICAST_PDU; + } + + /* Fetch the frame control field from mac header & check for frame type */ + frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); + + /* Processing done according to Frame/Packet type */ + frameType = ((frmCtrl & 0x000c) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); + switch(frameType) + { + case IEEE802_11_FRAMETYPE_MANAGEMENT: + + switch(pktType) + { + case CSR_WIFI_UNICAST_PDU: + unifi_trace(priv, UDBG5, "management unicast PDU in uf_process_ma_packet_req \n"); + /* push the packet in to the queue with appropriate mgt list */ + if (!staRecord) { + /* push the packet to the unifi if list is empty (if packet lost how to re-enque) */ + if (list_empty(&interfacePriv->genericMgtFrames)) { +#ifdef CSR_SUPPORT_SME + if(!(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) { +#endif + + unifi_trace(priv, UDBG3, "genericMgtFrames list is empty uf_process_ma_packet_req \n"); + result = ul_send_signal_unpacked(priv, &signal, bulkdata); + /* reque only on ENOSPC */ + if(result == -ENOSPC) { + /* requeue the failed packet to genericMgtFrame with same position */ + unifi_trace(priv, UDBG1, "(ENOSPC) Sending genericMgtFrames Failed so buffering\n"); + list = &interfacePriv->genericMgtFrames; + requeueOnSamePos = TRUE; + } +#ifdef CSR_SUPPORT_SME + }else{ + list = &interfacePriv->genericMgtFrames; + unifi_trace(priv, UDBG3, "genericMgtFrames queue empty and dtim started\n hosttag is 0x%x,\n",signal.u.MaPacketRequest.HostTag); + update_eosp_to_head_of_broadcast_list_head(priv,interfaceTag); + } +#endif + } else { + /* Queue the packet to genericMgtFrame of unifi_priv_t data structure */ + list = &interfacePriv->genericMgtFrames; + unifi_trace(priv, UDBG2, "genericMgtFrames queue not empty\n"); + } + } else { + /* check peer power state */ + if (queuePacketDozing || !list_empty(&staRecord->mgtFrames) || IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) { + /* peer is in dozing mode, so queue packet in mgt frame list of station record */ + /*if multicast traffic is going on, buffer the unicast packets*/ + list = &staRecord->mgtFrames; + + unifi_trace(priv, UDBG1, "staRecord->MgtFrames list empty? = %s, handle = %d, queuePacketDozing = %d\n", + (list_empty(&staRecord->mgtFrames))? "YES": "NO", staRecord->assignedHandle, queuePacketDozing); + if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)){ + update_eosp_to_head_of_broadcast_list_head(priv,interfaceTag); + } + + } else { + unifi_trace(priv, UDBG5, "staRecord->mgtFrames list is empty uf_process_ma_packet_req \n"); + result = ul_send_signal_unpacked(priv, &signal, bulkdata); + if(result == -ENOSPC) { + /* requeue the failed packet to staRecord->mgtFrames with same position */ + list = &staRecord->mgtFrames; + requeueOnSamePos = TRUE; + unifi_trace(priv, UDBG1, "(ENOSPC) Sending MgtFrames Failed handle = %d so buffering\n",staRecord->assignedHandle); + priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); + } else if (result) { + status = CSR_RESULT_FAILURE; + } + } + } + break; + case CSR_WIFI_MULTICAST_PDU: + unifi_trace(priv, UDBG5, "management multicast/broadcast PDU in uf_process_ma_packet_req 'QUEUE it' \n"); + /* Queue the packet to genericMulticastOrBroadCastMgtFrames of unifi_priv_t data structure + * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM + */ + + list = &interfacePriv->genericMulticastOrBroadCastMgtFrames; + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + interfacePriv->noOfbroadcastPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS) && + (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) { + setBcTim=TRUE; + } + break; + default: + unifi_error(priv, "condition never meets: packet type unrecognized\n"); + } + break; + case IEEE802_11_FRAMETYPE_DATA: + switch(pktType) + { + case CSR_WIFI_UNICAST_PDU: + unifi_trace(priv, UDBG5, "data unicast PDU in uf_process_ma_packet_req \n"); + /* check peer power state, list status & peer port status */ + if(!staRecord) { + unifi_error(priv, "In %s unicast but staRecord = NULL\n", __FUNCTION__); + return CSR_RESULT_FAILURE; + } else if (queuePacketDozing || isRouterBufferEnabled(priv,priority_q)|| !list_empty(&staRecord->dataPdu[priority_q]) || IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) { + /* peer is in dozing mode, so queue packet in mgt frame list of station record */ + /* if multicast traffic is going on, buffet the unicast packets */ + unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\ + Buffering enabled = %d \n", priority_q,queuePacketDozing,isRouterBufferEnabled(priv,priority_q)); + signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); + list = &staRecord->dataPdu[priority_q]; + } else { + unifi_trace(priv, UDBG5, "staRecord->dataPdu[%d] list is empty uf_process_ma_packet_req \n", priority_q); + signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); + /* Pdu allowed to send to unifi */ + result = ul_send_signal_unpacked(priv, &signal, bulkdata); + if(result == -ENOSPC) { + /* requeue the failed packet to staRecord->dataPdu[priority_q] with same position */ + unifi_trace(priv, UDBG1, "(ENOSPC) Sending Unicast DataPDU to queue %d Failed so buffering\n",priority_q); + requeueOnSamePos = TRUE; + list = &staRecord->dataPdu[priority_q]; + priv->pausedStaHandle[priority_q]=(CsrUint8)(staRecord->assignedHandle); + if(!isRouterBufferEnabled(priv,priority_q)) { + unifi_error(priv,"Buffering Not enabled for queue %d \n",priority_q); + } + } else if (result) { + status = CSR_RESULT_FAILURE; + } + } + break; + case CSR_WIFI_MULTICAST_PDU: + unifi_trace(priv, UDBG5, "data multicast/broadcast PDU in uf_process_ma_packet_req \n"); + /* Queue the packet to genericMulticastOrBroadCastFrames list of unifi_priv_t data structure + * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM + */ + list = &interfacePriv->genericMulticastOrBroadCastFrames; + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + interfacePriv->noOfbroadcastPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { + setBcTim = TRUE; + } + break; + default: + unifi_error(priv, "condition never meets: packet type un recognized\n"); + } + break; + default: + unifi_error(priv, "unrecognized frame type\n"); + } + if(list) { + status = enque_tx_data_pdu(priv, bulkdata,list, &signal,requeueOnSamePos); + /* Record no. of packet queued for each peer */ + if (staRecord && (pktType == CSR_WIFI_UNICAST_PDU) && (!status)) { + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staRecord->noOfPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } + } + if(setBcTim) { + unifi_trace(priv, UDBG3, "tim set due to broadcast pkt\n"); + update_tim(priv,0,1,interfaceTag, handle); + } else if(staRecord && staRecord->currentPeerState == + CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) { + if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) { + if(!staRecord->wmmOrQosEnabled) { + if(!list_empty(&staRecord->mgtFrames) || + !list_empty(&staRecord->dataPdu[3]) || + !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) { + unifi_trace(priv, UDBG3, "tim set due to unicast pkt & peer in powersave\n"); + update_tim(priv,staRecord->aid,1,interfaceTag, handle); + } + } else { + /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); + if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) { + update_tim(priv,staRecord->aid,1,interfaceTag, handle); + } + } + } + } + + if((list) && (pktType == CSR_WIFI_UNICAST_PDU && !queuePacketDozing) && !(isRouterBufferEnabled(priv,priority_q)) && !(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) { + unifi_trace(priv, UDBG2, "buffering cleared for queue = %d So resending buffered frames\n",priority_q); + uf_send_buffered_frames(priv, priority_q); + } + unifi_trace(priv, UDBG5, "leaving uf_process_ma_packet_req \n"); + return status; +#else +#ifdef CSR_NATIVE_LINUX + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "interfaceTag >= CSR_WIFI_NUM_INTERFACES, interfacetag = %d\n", interfaceTag); + return CSR_RESULT_FAILURE; + } + /* Frame ma-packet.req, this is saved/transmitted depend on queue state */ + unifi_frame_ma_packet_req(priv, priority, TransmitRate, hostTag, interfaceTag, + transmissionControl, leSenderProcessId, + peerMacAddress, &signal); + result = ul_send_signal_unpacked(priv, &signal, bulkdata); + if (result) { + return CSR_RESULT_FAILURE; + } +#endif + return status; +#endif +} + +#ifdef CSR_SUPPORT_SME +CsrInt8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, CsrUint16 interfaceTag, const CsrUint8 *daddr) +{ + CsrInt8 protection = 0; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + switch(interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_STA: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: + case CSR_WIFI_ROUTER_CTRL_MODE_AMP: + case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: + protection = interfacePriv->protect; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + { + CsrWifiRouterCtrlStaInfo_t *dstStaInfo = NULL; + if (daddr[0] & 0x1) { + unifi_trace(priv, UDBG3, "broadcast/multicast packet in send_ma_pkt_request\n"); + /* In this mode, the protect member of priv structure has an information of how + * AP/P2PGO has started, & the member updated in set mode request for AP/P2PGO + */ + protection = interfacePriv->protect; + } else { + /* fetch the destination record from staion record database */ + dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, daddr, interfaceTag); + if (!dstStaInfo) { + unifi_trace(priv, UDBG3, "peer not found in station record in send_ma_pkt_request\n"); + return -1; + } + protection = dstStaInfo->protection; + } + } + break; + default: + unifi_trace(priv, UDBG2, "mode unknown in send_ma_pkt_request\n"); + } + return protection; +} +#endif +#ifdef CSR_SUPPORT_SME +CsrUint8 send_multicast_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + int r; + tx_buffered_packets_t * buffered_pkt = NULL; + CsrBool moreData = FALSE; + CsrUint8 pduSent =0; + unsigned long lock_flags; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrUint32 hostTag = 0xffffffff; + + func_enter(); + if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_VO)) { + while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) { + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK); + moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE; + + + unifi_trace(priv,UDBG2,"DTIM Occurred for interface:sending Mgt packet %d\n",interfaceTag); + + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,moreData,FALSE)) == -ENOSPC) { + unifi_trace(priv,UDBG1,"frame_and_send_queued_pdu failed with ENOSPC for host tag = %x\n", buffered_pkt->hostTag); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &interfacePriv->genericMulticastOrBroadCastMgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + break; + } else { + unifi_trace(priv,UDBG1,"send_multicast_frames: Send genericMulticastOrBroadCastMgtFrames (%x, %x)\n", + buffered_pkt->hostTag, + r); + if(r) { + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + if(!moreData) { + + interfacePriv->dtimActive = FALSE; + if(!r) { + hostTag = buffered_pkt->hostTag; + pduSent++; + } else { + send_vif_availibility_rsp(priv,uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag),CSR_RC_UNSPECIFIED_FAILURE); + } + } + /* Buffered frame sent successfully */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + interfacePriv->noOfbroadcastPktQueued--; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + kfree(buffered_pkt); + } + + } + } + if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_CONTENTION)) { + while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastFrames))) { + buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; + moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE; + + + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &interfacePriv->genericMulticastOrBroadCastFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + break; + } else { + if(r) { + unifi_trace(priv,UDBG1,"send_multicast_frames: Send genericMulticastOrBroadCastFrame failed (%x, %x)\n", + buffered_pkt->hostTag, + r); + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + if(!moreData) { + interfacePriv->dtimActive = FALSE; + if(!r) { + pduSent ++; + hostTag = buffered_pkt->hostTag; + } else { + send_vif_availibility_rsp(priv,uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag),CSR_RC_UNSPECIFIED_FAILURE); + } + } + /* Buffered frame sent successfully */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + interfacePriv->noOfbroadcastPktQueued--; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + kfree(buffered_pkt); + } + } + } + if((interfacePriv->dtimActive == FALSE)) { + /* Record the host Tag*/ + unifi_trace(priv,UDBG2,"send_multicast_frames: Recorded hostTag of EOSP packet: = 0x%x\n",hostTag); + interfacePriv->multicastPduHostTag = hostTag; + } + return pduSent; +} +#endif +void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata, + CsrUint32 siglen) +{ +#ifdef CSR_SUPPORT_SME + CSR_SIGNAL signal; + CSR_MA_VIF_AVAILABILITY_INDICATION *ind; + int r; + CsrUint16 interfaceTag; + CsrUint8 pduSent =0; + CSR_RESULT_CODE resultCode = CSR_RC_SUCCESS; + netInterface_priv_t *interfacePriv; + + func_enter(); + unifi_trace(priv, UDBG3, + "uf_process_ma_vif_availibility_ind: Process signal 0x%.4X\n", + *((CsrUint16*)sigdata)); + + r = read_unpack_signal(sigdata, &signal); + if (r) { + unifi_error(priv, + "uf_process_ma_vif_availibility_ind: Received unknown signal 0x%.4X.\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata)); + func_exit(); + return; + } + ind = &signal.u.MaVifAvailabilityIndication; + interfaceTag=ind->VirtualInterfaceIdentifier & 0xff; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "in vif_availability_ind interfaceTag is wrong\n"); + return; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + if(ind->Multicast) { + if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames) && + list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames)) { + /* This condition can occur because of a potential race where the + TIM is not yet reset as host is waiting for confirm but it is sent + by firmware and DTIM occurs*/ + unifi_notice(priv,"ma_vif_availibility_ind recevied for multicast but queues are empty%d\n",interfaceTag); + send_vif_availibility_rsp(priv,ind->VirtualInterfaceIdentifier,CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES); + interfacePriv->dtimActive = FALSE; + if(interfacePriv->multicastPduHostTag == 0xffffffff) { + unifi_notice(priv,"ma_vif_availibility_ind recevied for multicast but queues are empty%d\n",interfaceTag); + /* This may be an extra request in very rare race conditions but it is fine as it would atleast remove the potential lock up */ + update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF); + } + return; + } + if(interfacePriv->dtimActive) { + unifi_trace(priv,UDBG2,"DTIM Occurred for already active DTIM interface %d\n",interfaceTag); + return; + } else { + unifi_trace(priv,UDBG2,"DTIM Occurred for interface %d\n",interfaceTag); + if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { + set_eosp_transmit_ctrl(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames); + } else { + set_eosp_transmit_ctrl(priv,&interfacePriv->genericMulticastOrBroadCastFrames); + } + } + interfacePriv->dtimActive = TRUE; + pduSent = send_multicast_frames(priv,interfaceTag); + } + else { + unifi_error(priv,"Interface switching is not supported %d\n",interfaceTag); + resultCode = CSR_RC_NOT_SUPPORTED; + send_vif_availibility_rsp(priv,ind->VirtualInterfaceIdentifier,CSR_RC_NOT_SUPPORTED); + } +#endif +} +#ifdef CSR_SUPPORT_SME + +#define GET_ACTIVE_INTERFACE_TAG(priv) 0 + + +void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo) +{ + + CsrInt8 i; + + func_enter(); + + if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| + (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) + &&(!list_empty(&staInfo->mgtFrames))){ + + unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n"); + uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); + + /*This may happen because U-APSD was completed + with previous AC transfer*/ + + if(staInfo->uapsdActive == FALSE) { + return; + } + } + + for(i=3;i>=0;i--) { + + if(((staInfo->powersaveMode[i]== CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(staInfo->powersaveMode[i] == CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + &&(!list_empty(&staInfo->dataPdu[i]))) { + unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered data frames\n"); + uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]); + } + + /*This may happen because U-APSD was completed + with previous AC transfer*/ + if (staInfo->uapsdActive == FALSE) { + return; + } + } + + if (staInfo->uapsdActive && !uf_is_more_data_for_delivery_ac(priv, staInfo, TRUE)) { + /* If last packet not able to transfer due to ENOSPC & buffer management algorithm + * would have removed last packet. Then we wont update staInfo->UapsdActive = FALSE (suppose + * to update as we dont have packet to transfer at this USP) because above if loop fails as list is empty & + * update of UAPSD activity done in uf_send_buffered_data_from_delivery_ac(). + * In this situation we send QOS null & mean time update UapsdActive to FALSE here + */ + staInfo->uapsdActive = FALSE; + uf_send_qos_null(priv, GET_ACTIVE_INTERFACE_TAG(priv), staInfo->peerMacAddress.a, CSR_QOS_UP0 , staInfo); + } + func_exit(); +} + + +void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, + CsrWifiRouterCtrlStaInfo_t * staInfo, + CsrUint8 queue, + struct list_head *txList) +{ + + CsrUint16 interfaceTag = GET_ACTIVE_INTERFACE_TAG(priv); + tx_buffered_packets_t * buffered_pkt = NULL; + unsigned long lock_flags; + CsrBool eosp=FALSE; + CsrInt8 r =0; + CsrBool moreData = FALSE; + + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + netInterface_priv_t *interfacePriv; + interfacePriv = priv->interfacePriv[interfaceTag]; + func_enter(); + + /*Check U-APSD conditions if not met return from here*/ + if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)&& + (staInfo->uapsdActive == TRUE)&& + (!IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){ + + unifi_trace(priv,UDBG4,"uf_send_buffered_data_from_queue : U-APSD active. %d :Queue NOT delivery enbaled.return %\n",queue); + + return; + } + + while(!isRouterBufferEnabled(priv,queue) && + ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){ + if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->uapsdSuspended = TRUE; + staInfo->uapsdActive = FALSE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + /* re-queueing the packet as DTIM started */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q,txList); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + unifi_trace(priv, UDBG3, "%s: DTIM Active while UAPSD in progress for staId: 0x%x\n",__FUNCTION__,staInfo->aid); + break; + } + + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + + + if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)){ + + moreData = uf_is_more_data_for_delivery_ac(priv,staInfo,TRUE); + + buffered_pkt->transmissionControl = TRANSMISSION_CONTROL_TRIGGER_MASK; + + if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength-1)){ + moreData = FALSE; + } + + if(moreData == FALSE){ + eosp = TRUE; + staInfo->uapsdActive = FALSE; + staInfo->noOfSpFramesSent = FALSE; + buffered_pkt->transmissionControl = + (TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable); + if ((allDeliveryEnabled && !dataAvailable)) { + update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle); + } + /* check the moer data for non delivery ac and update accordingly */ + else if(uf_is_more_data_for_non_delivery_ac(staInfo) ) { + update_tim(priv,staInfo->aid,1,interfaceTag, staInfo->assignedHandle); + } + else if(!uf_is_more_data_for_non_delivery_ac(staInfo) ){ + unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_send_buffered_data_from_delivery_ac\n"); + update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle); + } + + } + } + else + { + /*Non QoS and non U-APSD.*/ + eosp = FALSE; + moreData = FALSE; + unifi_warning(priv,"uf_send_buffered_data_from_delivery_ac :non U-APSD !!! \n"); + } + + unifi_trace(priv,UDBG2,"uf_send_buffered_data_from_delivery_ac : MoreData:%d, EOSP:%d\n",moreData,eosp); + + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,moreData,eosp)) == -ENOSPC) { + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q,txList); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle); + unifi_notice (priv," U-APSD: PDU sending failed .. no space for queue %d \n",queue); + /*Break the loop for this queue.Try for next available Delivery enabled + Queue*/ + break; + } else { + if(r){ + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + + kfree(buffered_pkt); + if(staInfo->uapsdActive == TRUE){ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->noOfSpFramesSent = staInfo->noOfSpFramesSent + 1; + if(staInfo->noOfSpFramesSent == staInfo->maxSpLength){ + staInfo->uapsdActive = FALSE; + staInfo->noOfSpFramesSent = FALSE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + break; + } + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } + } + } + + func_exit(); + +} + +void uf_send_buffered_data_from_ac(unifi_priv_t *priv, + CsrWifiRouterCtrlStaInfo_t * staInfo, + CsrUint8 queue, + struct list_head *txList) +{ + tx_buffered_packets_t * buffered_pkt = NULL; + unsigned long lock_flags; + CsrBool eosp=FALSE; + CsrBool moreData = FALSE; + CsrInt8 r =0; + + func_enter(); + + unifi_trace(priv,UDBG2,"uf_send_buffered_data_from_ac :\n"); + + while(!isRouterBufferEnabled(priv,queue) && + ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){ + + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + + unifi_trace(priv,UDBG3,"uf_send_buffered_data_from_ac : MoreData:%d, EOSP:%d\n",moreData,eosp); + + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,moreData,eosp)) == -ENOSPC) { + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q,txList); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + if(staInfo != NULL){ + priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle); + } + unifi_trace(priv,UDBG3," uf_send_buffered_data_from_ac: PDU sending failed .. no space for queue %d \n",queue); + } else { + if(r){ + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + + func_exit(); + +} + +void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) +{ + CsrUint16 interfaceTag = GET_ACTIVE_INTERFACE_TAG(priv); + CsrUint32 startIndex=0,endIndex=0; + CsrWifiRouterCtrlStaInfo_t * staInfo = NULL; + CsrUint8 queue; + CsrBool moreData = FALSE; + + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || + (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO))) + return; + func_enter(); + + queue = (q<=3)?q:0; + + if(interfacePriv->dtimActive) { + /* this function updates dtimActive*/ + send_multicast_frames(priv,interfaceTag); + if(!interfacePriv->dtimActive) { + moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || + !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); + if(!moreData) { + update_tim(priv,0,0,interfaceTag, 0XFFFFFFFF); + } + } else { + moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || + !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); + if(!moreData) { + /* This should never happen but if it happens, we need a way out */ + unifi_error(priv,"ERROR: No More Data but DTIM is active sending Response\n"); + send_vif_availibility_rsp(priv,uf_get_vif_identifier(interfacePriv->interfaceMode,interfaceTag),CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES); + interfacePriv->dtimActive = FALSE; + } + } + func_exit(); + return; + } + if(priv->pausedStaHandle[queue] > 7) { + priv->pausedStaHandle[queue] = 0; + } + + if(queue == UNIFI_TRAFFIC_Q_VO) { + + + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying mgt from queue=%d\n",queue); + for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { + staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); + if(!staInfo ) { + continue; + } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdActive == FALSE) ) { + continue; + } + + if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) + &&(staInfo->uapsdActive == FALSE)){ + /*Non-UAPSD case push the management frames out*/ + if(!list_empty(&staInfo->mgtFrames)){ + uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); + } + } + else if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]))){ + + + if(!list_empty(&staInfo->mgtFrames)){ + /*UNIFI_TRAFFIC_Q_VO is delivery enabled push the managment frames out*/ + uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); + + } + } + + if(isRouterBufferEnabled(priv,queue)) { + unifi_notice(priv,"uf_send_buffered_frames : No space Left for queue = %d\n",queue); + break; + } + } + + + /*push generic management frames out*/ + + if(!list_empty(&interfacePriv->genericMgtFrames)){ + + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying generic mgt from queue=%d\n",queue); + uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames); + + } + + } + + + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : Resume called for Queue=%d\n",queue); + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : start=%d end=%d\n",startIndex,endIndex); + + startIndex = priv->pausedStaHandle[queue]; + endIndex = (startIndex + UNIFI_MAX_CONNECTIONS -1) % UNIFI_MAX_CONNECTIONS; + + while(startIndex != endIndex) { + staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); + if(!staInfo) { + startIndex ++; + if(startIndex >= UNIFI_MAX_CONNECTIONS){ + startIndex = 0; + } + continue; + } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdActive == FALSE)){ + startIndex ++; + if(startIndex >= UNIFI_MAX_CONNECTIONS){ + startIndex = 0; + } + continue; + } + /* Peer is active or U-APSD is active so send PDUs to the peer */ + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying data from queue=%d\n",queue); + + + if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) + &&(staInfo->uapsdActive == FALSE)){ + + if(!list_empty(&staInfo->dataPdu[queue])){ + + /*Non-UAPSD case push the AC frames out*/ + uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue])); + } + } + else if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){ + if(!list_empty(&staInfo->dataPdu[queue])){ + uf_send_buffered_data_from_delivery_ac(priv, staInfo, queue, &staInfo->dataPdu[queue]); + } + } + + startIndex ++; + if(startIndex >= UNIFI_MAX_CONNECTIONS){ + startIndex = 0; + } + } + if(isRouterBufferEnabled(priv,queue)) { + priv->pausedStaHandle[queue] = endIndex; + } else { + priv->pausedStaHandle[queue] = 0; + } + + /*U-APSD might have stopped because of pause.So restart it if U-APSD + was active with any of the station*/ + for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { + staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); + if(!staInfo ) { + continue; + } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdActive == TRUE)) { + + /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by + sending data from remaining delivery enabled queues*/ + uf_continue_uapsd(priv,staInfo); + } + } + func_exit(); +} + +CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck) +{ + CsrUint8 i; + + for(i=0;i<=3;i++) + { + if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + &&(!list_empty(&staRecord->dataPdu[i]))){ + unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data Available \n"); + return TRUE; + } + } + if((mgtCheck == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO])) + &&(!list_empty(&staRecord->mgtFrames))){ + + unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Management Data Available \n"); + + return TRUE; + } + + unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data NOT Available \n"); + return FALSE; +} + +CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord) +{ + CsrUint8 i; + + for(i=0;i<=3;i++) + { + if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) + ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_LEGACY_POWER_SAVE)) + &&(!list_empty(&staRecord->dataPdu[i]))){ + + return TRUE; + } + } + + if(((staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) + ||(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_LEGACY_POWER_SAVE)) + &&(!list_empty(&staRecord->mgtFrames))){ + + return TRUE; + } + + + + return FALSE; +} + + +int uf_process_station_records_for_sending_data(unifi_priv_t *priv,CsrUint16 interfaceTag, + CsrWifiRouterCtrlStaInfo_t *srcStaInfo, + CsrWifiRouterCtrlStaInfo_t *dstStaInfo) +{ + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + unifi_trace(priv, UDBG5, "entering uf_process_station_records_for_sending_data\n"); + + if (srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED) { + unifi_error(priv, "Peer State not connected AID = %x, handle = %x, control port state = %x\n", + srcStaInfo->aid, srcStaInfo->assignedHandle, srcStaInfo->peerControlledPort->port_action); + return -1; + } + switch (interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + unifi_trace(priv, UDBG5, "mode is AP/P2PGO\n"); + break; + default: + unifi_warning(priv, "mode is nor AP neither P2PGO, packet cant be xmit\n"); + return -1; + } + + switch(dstStaInfo->peerControlledPort->port_action) + { + case CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD: + case CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK: + unifi_trace(priv, UDBG5, "destination port is closed/blocked, discarding the packet\n"); + return -1; + default: + unifi_trace(priv, UDBG5, "destination port state is open\n"); + } + + /* port state is open, destination station record is valid, Power save state is + * validated in uf_process_ma_packet_req function + */ + unifi_trace(priv, UDBG5, "leaving uf_process_station_records_for_sending_data\n"); + return 0; +} + +void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv, + CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + CsrUint16 qosControl, + CsrUint16 interfaceTag) +{ + + CSR_PRIORITY priority; + CsrInt8 i; + unifi_TrafficQueue priority_q; + unsigned long lock_flags; + + func_enter(); + + /* start the U-APSD operation only if it not active*/ + if(srcStaInfo->uapsdActive == FALSE){ + /*if recceived Frames trigger Frame and Devlivery enabled AC has data + then transmit from High priorty delivery enabled AC*/ + + + priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); + + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); + + if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) + ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){ + + unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd starting U-APSD operations\n"); + + /*Received Frame is trigger frame*/ + unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : Received Frame is trigger frame %d\n",priority_q); + + if(((srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| + (srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) + &&(!list_empty(&srcStaInfo->mgtFrames))){ + + /*Trigger frame received and Data available in Delivery enabled AC + or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->uapsdActive = TRUE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n"); + + /* uf_send_buffered_frames(priv, priority_q); */ + uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, UNIFI_TRAFFIC_Q_VO, &srcStaInfo->mgtFrames); + + + /*This may happen because U-APSD was completed + with previous AC transfer*/ + + if(srcStaInfo->uapsdActive == FALSE){ + return; + } + + } + + + for(i=3;i>=0;i--){ + + if(((srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + &&(!list_empty(&srcStaInfo->dataPdu[i]))){ + + + /*Trigger frame received and Data available in Delivery enabled AC + or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->uapsdActive = TRUE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered data frames\n"); + + uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, i, &srcStaInfo->dataPdu[i]); + + /*This may happen because U-APSD was completed + with previous AC transfer*/ + + if(srcStaInfo->uapsdActive == FALSE){ + return; + } + } + + } + if(srcStaInfo->uapsdActive == FALSE && !(uf_is_more_data_for_delivery_ac(priv,srcStaInfo,TRUE))){ + unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd : No buffer frames so sending QOS Null in response of trigger frame\n"); + uf_send_qos_null(priv,interfaceTag,srcStaInfo->peerMacAddress.a,priority,srcStaInfo); + } + + } + + } + + func_exit(); + +} +void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo) +{ + bulk_data_param_t bulkdata; + CsrResult csrResult; + struct sk_buff *skb, *newSkb = NULL; + CsrWifiMacAddress peerAddress; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_ESOP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK); + int r; + CSR_SIGNAL signal; + CsrUint32 priority_q; + CSR_RATE transmitRate = 0; + + + func_enter(); + /* Send a Null Frame to Peer, + * 32= size of mac header */ + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE + QOS_CONTROL_HEADER_SIZE); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, " failed to allocate request_data. in uf_send_qos_null func\n"); + return ; + } + skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); + skb->len = 0; + bulkdata.d[0].os_data_ptr = skb->data; + bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; + + /* For null frames protection bit should not be set in MAC header, so passing value 0 below for protection field */ + + if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, da, interfacePriv->bssid.a, 0)) { + unifi_error(priv, "failed to create MAC header\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return; + } + memcpy(peerAddress.a, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); + /* convert priority to queue */ + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); + + /* Frame ma-packet.req, this is saved/transmitted depend on queue state + * send the null frame at data rate of 1 Mb/s for AP or 6 Mb/s for P2PGO + */ + switch (interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + transmitRate = 2; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + transmitRate = 12; + break; + default: + transmitRate = 0; + } + unifi_frame_ma_packet_req(priv, priority, transmitRate, 0xffffffff, interfaceTag, + transmissionControl, priv->netdev_client->sender_id, + peerAddress.a, &signal); + + r = ul_send_signal_unpacked(priv, &signal, &bulkdata); + if(r) { + unifi_error(priv, "failed to send QOS data null packet result: %d\n",r); + unifi_net_data_free(priv, &bulkdata.d[0]); + } + + func_exit(); + return; + +} +void uf_send_nulldata(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo) +{ + bulk_data_param_t bulkdata; + CsrResult csrResult; + struct sk_buff *skb, *newSkb = NULL; + CsrWifiMacAddress peerAddress; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CSR_TRANSMISSION_CONTROL transmissionControl = 0; + int r; + CSR_SIGNAL signal; + CsrUint32 priority_q; + CSR_RATE transmitRate = 0; + CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; + unsigned long lock_flags; + + func_enter(); + /* Send a Null Frame to Peer, size = 24 for MAC header */ + csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "uf_send_nulldata: Failed to allocate memory for NULL frame\n"); + return ; + } + skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); + skb->len = 0; + bulkdata.d[0].os_data_ptr = skb->data; + bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; + bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].os_net_buf_ptr = NULL; + bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; + + /* For null frames protection bit should not be set in MAC header, so passing value 0 below for protection field */ + if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, da, interfacePriv->bssid.a, 0)) { + unifi_error(priv, "uf_send_nulldata: Failed to create MAC header\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + return; + } + memcpy(peerAddress.a, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); + /* convert priority to queue */ + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); + transmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); + + /* Frame ma-packet.req, this is saved/transmitted depend on queue state + * send the null frame at data rate of 1 Mb/s for AP or 6 Mb/s for P2PGO + */ + switch (interfacePriv->interfaceMode) + { + case CSR_WIFI_ROUTER_CTRL_MODE_AP: + transmitRate = 2; + break; + case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: + transmitRate = 12; + break; + default: + transmitRate = 0; + } + unifi_frame_ma_packet_req(priv, priority, transmitRate, INVALID_HOST_TAG, interfaceTag, + transmissionControl, priv->netdev_client->sender_id, + peerAddress.a, &signal); + + /* Save host tag to check the status on reception of MA packet confirm */ + srcStaInfo->nullDataHostTag = req->HostTag; + unifi_trace(priv, UDBG1, "uf_send_nulldata: STA AID = %d hostTag = %x\n", srcStaInfo->aid, req->HostTag); + + r = ul_send_signal_unpacked(priv, &signal, &bulkdata); + + if(r == -ENOSPC) { + unifi_trace(priv, UDBG1, "uf_send_nulldata: ENOSPC Requeue the Null frame\n"); + enque_tx_data_pdu(priv, &bulkdata, &srcStaInfo->dataPdu[priority_q], &signal, 1); + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->noOfPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + + } + if(r && r != -ENOSPC){ + unifi_error(priv, "uf_send_nulldata: Failed to send Null frame Error = %d\n",r); + unifi_net_data_free(priv, &bulkdata.d[0]); + srcStaInfo->nullDataHostTag = INVALID_HOST_TAG; + } + + func_exit(); + return; +} + +CsrBool uf_check_broadcast_bssid(unifi_priv_t *priv, const bulk_data_param_t *bulkdata) +{ + CsrUint8 *bssid = NULL; + static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + CsrUint8 toDs, fromDs; + + toDs = (((bulkdata->d[0].os_data_ptr)[1]) & 0x01) ? 1 : 0; + fromDs =(((bulkdata->d[0].os_data_ptr)[1]) & 0x02) ? 1 : 0; + + if (toDs && fromDs) + { + unifi_trace(priv, UDBG6, "Address 4 present, Don't try to find BSSID\n"); + bssid = NULL; + } + else if((toDs == 0) && (fromDs ==0)) + { + /* BSSID is Address 3 */ + bssid = (CsrUint8 *) (bulkdata->d[0].os_data_ptr + 4 + (2 * ETH_ALEN)); + } + else if(toDs) + { + /* BSSID is Address 1 */ + bssid = (CsrUint8 *) (bulkdata->d[0].os_data_ptr + 4); + } + else if(fromDs) + { + /* BSSID is Address 2 */ + bssid = (CsrUint8 *) (bulkdata->d[0].os_data_ptr + 4 + ETH_ALEN); + } + + if (memcmp(broadcast_address.a, bssid, ETH_ALEN)== 0) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + CsrUint8 pmBit,CsrUint16 interfaceTag) +{ + CsrBool moreData = FALSE; + CsrBool powerSaveChanged = FALSE; + unsigned long lock_flags; + + unifi_trace(priv, UDBG3, "entering uf_process_pm_bit_for_peer\n"); + if (pmBit) { + priv->allPeerDozing |= (0x01 << (srcStaInfo->assignedHandle)); + } else { + priv->allPeerDozing &= ~(0x01 << (srcStaInfo->assignedHandle)); + } + if(pmBit) { + if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) { + + /* disable the preemption */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->currentPeerState =CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE; + powerSaveChanged = TRUE; + /* enable the preemption */ + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } else { + return powerSaveChanged; + } + } else { + if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) { + /* disable the preemption */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->currentPeerState = CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE; + powerSaveChanged = TRUE; + /* enable the preemption */ + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + }else { + return powerSaveChanged; + } + } + + + if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) { + unifi_trace(priv,UDBG3, "Peer with AID = %d is active now\n",srcStaInfo->aid); + process_peer_active_transition(priv,srcStaInfo,interfaceTag); + } else { + unifi_trace(priv,UDBG3, "Peer with AID = %d is in PS Now\n",srcStaInfo->aid); + /* Set TIM if needed */ + if(!srcStaInfo->wmmOrQosEnabled) { + moreData = (!list_empty(&srcStaInfo->mgtFrames) || + !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_VO])|| + !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])); + if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { + unifi_trace(priv, UDBG3, "This condition should not occur\n"); + update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + } + } else { + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + unifi_trace(priv, UDBG5, "Qos in AP Mode\n"); + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(srcStaInfo, &allDeliveryEnabled, &dataAvailable); + /*check for more data in non-delivery enabled queues*/ + moreData = (uf_is_more_data_for_non_delivery_ac(srcStaInfo) || (allDeliveryEnabled && dataAvailable)); + + if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { + update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + } + } + } + unifi_trace(priv, UDBG3, "leaving uf_process_pm_bit_for_peer\n"); + return powerSaveChanged; +} + + + +void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pmBit,CsrUint16 interfaceTag) +{ + CsrWifiRouterCtrlStaInfo_t *staRecord = + CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, sa, interfaceTag); + tx_buffered_packets_t * buffered_pkt = NULL; + CsrWifiMacAddress peerMacAddress; + unsigned long lock_flags; + CsrInt8 r =0; + CsrBool moreData = FALSE; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + unifi_trace(priv, UDBG3, "entering uf_process_ps_poll\n"); + if(!staRecord) { + memcpy(peerMacAddress.a,sa,ETH_ALEN); + unifi_trace(priv, UDBG3, "In uf_process_ps_poll, sta record not found:unexpected frame addr = %x:%x:%x:%x:%x:%x\n", + sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]); + CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress); + return; + } + + uf_process_pm_bit_for_peer(priv,staRecord,pmBit,interfaceTag); + + /* Update station last activity time */ + staRecord->activity_flag = TRUE; + + /* This should not change the PM bit as PS-POLL has PM bit always set */ + if(!pmBit) { + unifi_notice (priv," PM bit reset in PS-POLL\n"); + return; + } + + if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) { + /* giving more priority to multicast packets so dropping ps-poll*/ + unifi_notice (priv," multicast transmission is going on so don't take action on PS-POLL\n"); + return; + } + + if(!staRecord->wmmOrQosEnabled) { + if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { + buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; + moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || + !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || + !list_empty(&staRecord->mgtFrames)); + + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->mgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + priv->pausedStaHandle[3]=(CsrUint8)(staRecord->assignedHandle); + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } else if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]))) { + buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; + moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || + !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO])); + + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[3]=(CsrUint8)(staRecord->assignedHandle); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } else if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]))) { + buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; + moreData = !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); + + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } else { + /* Actually since we have sent an ACK, there + * there is no need to send a NULL frame*/ + } + moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || + !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || + !list_empty(&staRecord->mgtFrames)); + if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { + unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + } else { + + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + unifi_trace(priv, UDBG3,"Qos Support station.Processing PS-Poll\n"); + + /*Send Data From Management Frames*/ + /* Priority orders for delivering the buffered packets are + * 1. UNIFI_TRAFFIC_Q_VO, if its non delivery enabled + * 2. management frames + * 3. Other access catagory frames which are non deliver enable + */ + + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); + + if (allDeliveryEnabled) { + unifi_trace(priv, UDBG3, "uf_process_ps_poll: All ACs are delivery enable so Sending QOS Null in response of Ps-poll\n"); + uf_send_qos_null(priv,interfaceTag,sa,CSR_QOS_UP0,staRecord); + return; + } + + if ((!IS_DELIVERY_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO])) && + (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || !list_empty(&staRecord->mgtFrames))) { + /* UNIFI_TRAFFIC_Q_VO is non delivery enabled, & check for packets are there to send from this AC */ + if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]))) { + moreData = uf_is_more_data_for_non_delivery_ac(staRecord); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + + /* Last parameter is EOSP & its false always for PS-POLL processing */ + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } else if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { + /* We dont have packets in non delivery enabled UNIFI_TRAFFIC_Q_VO, So we are looking in management + * queue of the station record + */ + moreData = uf_is_more_data_for_non_delivery_ac(staRecord); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + + /* Last parameter is EOSP & its false always for PS-POLL processing */ + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->mgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + } else { + CsrInt8 i; + /* We dont have buffered packet in UNIFI_TRAFFIC_Q_VO & mangement frame queue (1 & 2 failed), So proceed with 3 condition + * UNIFI_TRAFFIC_Q_VO is taken care so start with i index = 2 + */ + for(i= 2; i>=0; i--) { + if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) { + /* Send One packet, if queue is NULL then continue */ + if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { + moreData = uf_is_more_data_for_non_delivery_ac(staRecord); + + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + + /* Last parameter is EOSP & its false always for PS-POLL processing */ + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { + /* Clear the trigger bit transmission control*/ + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staRecord->dataPdu[i]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); + unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); + } else { + if(r) { + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + break; + } + } + } + } + /* Check if all AC's are Delivery Enabled */ + is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); + /*check for more data in non-delivery enabled queues*/ + moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)); + if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { + unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + } + + unifi_trace(priv, UDBG3, "leaving uf_process_ps_poll\n"); +} + + + +void add_to_send_cfm_list(unifi_priv_t * priv, + tx_buffered_packets_t *tx_q_item, + struct list_head *frames_need_cfm_list) +{ + tx_buffered_packets_t *send_cfm_list_item = NULL; + + send_cfm_list_item = (tx_buffered_packets_t *) kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); + + if(send_cfm_list_item == NULL){ + unifi_warning(priv, "%s: Failed to allocate memory for new list item \n"); + return; + } + + INIT_LIST_HEAD(&send_cfm_list_item->q); + + send_cfm_list_item->hostTag = tx_q_item->hostTag; + send_cfm_list_item->interfaceTag = tx_q_item->interfaceTag; + send_cfm_list_item->transmissionControl = tx_q_item->transmissionControl; + send_cfm_list_item->leSenderProcessId = tx_q_item->leSenderProcessId; + send_cfm_list_item->rate = tx_q_item->rate; + memcpy(send_cfm_list_item->peerMacAddress.a, tx_q_item->peerMacAddress.a, ETH_ALEN); + send_cfm_list_item->priority = tx_q_item->priority; + + list_add_tail(&send_cfm_list_item->q, frames_need_cfm_list); +} + +void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv, + struct list_head *frames_need_cfm_list, + struct list_head * list) +{ + tx_buffered_packets_t *tx_q_item = NULL; + struct list_head *listHead; + struct list_head *placeHolder; + unsigned long lock_flags; + + func_enter(); + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + + /* Search through the list and if confirmation required for any frames, + add it to the send_cfm list */ + list_for_each_safe(listHead, placeHolder, list) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + + if(!tx_q_item) { + unifi_error(priv, "Entry should exist, otherwise it is a (BUG)\n"); + continue; + } + + /* check if confirmation is requested and if the sender ID + is not netdevice client then save the entry in the list for need cfms */ + if (!(tx_q_item->transmissionControl & CSR_NO_CONFIRM_REQUIRED) && + (tx_q_item->leSenderProcessId != priv->netdev_client->sender_id)){ + unifi_trace(priv, UDBG1, "%s: SenderProcessID=%x host tag=%x transmission control=%x\n", + __FUNCTION__, + tx_q_item->leSenderProcessId, + tx_q_item->hostTag, + tx_q_item->transmissionControl); + + add_to_send_cfm_list(priv, tx_q_item, frames_need_cfm_list); + } + } + + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + + func_exit(); +} + + + +void uf_flush_list(unifi_priv_t * priv, struct list_head * list) +{ + tx_buffered_packets_t *tx_q_item; + struct list_head *listHead; + struct list_head *placeHolder; + unsigned long lock_flags; + + unifi_trace(priv, UDBG5, "entering the uf_flush_list \n"); + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + /* go through list, delete & free memory */ + list_for_each_safe(listHead, placeHolder, list) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + + if(!tx_q_item) { + unifi_error(priv, "entry should exists, otherwise crashes (bug)\n"); + } + unifi_trace(priv, UDBG5, + "proccess_tx: in uf_flush_list peerMacAddress=%02X%02X%02X%02X%02X%02X senderProcessId=%x\n", + tx_q_item->peerMacAddress.a[0], tx_q_item->peerMacAddress.a[1], + tx_q_item->peerMacAddress.a[2], tx_q_item->peerMacAddress.a[3], + tx_q_item->peerMacAddress.a[4], tx_q_item->peerMacAddress.a[5], + tx_q_item->leSenderProcessId); + + list_del(listHead); + /* free the allocated memory */ + unifi_net_data_free(priv, &tx_q_item->bulkdata); + kfree(tx_q_item); + tx_q_item = NULL; + if (!priv->noOfPktQueuedInDriver) { + unifi_error(priv, "packets queued in driver 0 still decrementing in %s\n", __FUNCTION__); + } else { + priv->noOfPktQueuedInDriver--; + } + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); +} +void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list) +{ + struct list_head *listHeadMaPktreq,*placeHolderMaPktreq; + maPktReqList_t *maPktreq; + unsigned long lock_flags; + + unifi_trace(priv, UDBG5, "entering the uf_flush_maPktlist \n"); + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + /* go through list, delete & free memory */ + list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, list) { + maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); + + if(!maPktreq) { + unifi_error(priv, "entry should exists, otherwise crashes (bug)\n"); + } + /* free the allocated memory */ + dev_kfree_skb(maPktreq->skb); + list_del(listHeadMaPktreq); + kfree(maPktreq); + maPktreq = NULL; + + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); +} +tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList) +{ + /* dequeue the tx data packets from the appropriate queue */ + tx_buffered_packets_t *tx_q_item = NULL; + struct list_head *listHead; + struct list_head *placeHolder; + unsigned long lock_flags; + + unifi_trace(priv, UDBG5, "entering dequeue_tx_data_pdu\n"); + /* check for list empty */ + if (list_empty(txList)) { + unifi_trace(priv, UDBG5, "In dequeue_tx_data_pdu, the list is empty\n"); + return NULL; + } + + /* Verification, if packet count is negetive */ + if (priv->noOfPktQueuedInDriver == 0xFFFF) { + unifi_warning(priv, "no packet available in queue: debug"); + return NULL; + } + + /* return first node after header, & delete from the list && atleast one item exist */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHead, placeHolder, txList) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + list_del(listHead); + break; + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + + if (tx_q_item) { + unifi_trace(priv, UDBG5, + "proccess_tx: In dequeue_tx_data_pdu peerMacAddress=%02X%02X%02X%02X%02X%02X senderProcessId=%x\n", + tx_q_item->peerMacAddress.a[0], tx_q_item->peerMacAddress.a[1], + tx_q_item->peerMacAddress.a[2], tx_q_item->peerMacAddress.a[3], + tx_q_item->peerMacAddress.a[4], tx_q_item->peerMacAddress.a[5], + tx_q_item->leSenderProcessId); + } + + unifi_trace(priv, UDBG5, "leaving dequeue_tx_data_pdu\n"); + return tx_q_item; +} +/* generic function to get the station record handler */ +CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(unifi_priv_t *priv, + const CsrUint8 *peerMacAddress, + CsrUint16 interfaceTag) +{ + CsrUint8 i; + netInterface_priv_t *interfacePriv; + unsigned long lock_flags; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "interfaceTag is not proper, interfaceTag = %d\n", interfaceTag); + return NULL; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* disable the preemption untill station record is fetched */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + + for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + if (interfacePriv->staInfo[i]!= NULL) { + if (!memcmp(((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]))->peerMacAddress.a, peerMacAddress, ETH_ALEN)) { + /* enable the preemption as station record is fetched */ + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + unifi_trace(priv, UDBG5, "peer entry found in station record\n"); + return ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i])); + } + } + } + /* enable the preemption as station record is fetched */ + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + unifi_trace(priv, UDBG5, "peer entry not found in station record\n"); + return NULL; +} +/* generic function to get the station record handler from the handle */ +CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_priv_t *priv, + CsrUint32 handle, + CsrUint16 interfaceTag) +{ + netInterface_priv_t *interfacePriv; + + if ((handle >= UNIFI_MAX_CONNECTIONS) || (interfaceTag >= CSR_WIFI_NUM_INTERFACES)) { + unifi_error(priv, "handle/interfaceTag is not proper, handle = %d, interfaceTag = %d\n", handle, interfaceTag); + return NULL; + } + interfacePriv = priv->interfacePriv[interfaceTag]; + return ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle])); +} + +/* Function to do inactivity */ +void uf_check_inactivity(unifi_priv_t *priv, CsrUint16 interfaceTag, CsrTime currentTime) +{ + CsrUint32 i; + CsrWifiRouterCtrlStaInfo_t *staInfo; + CsrTime elapsedTime; /* Time in microseconds */ + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrWifiMacAddress peerMacAddress; + unsigned long lock_flags; + + if (interfacePriv == NULL) { + unifi_trace(priv, UDBG3, "uf_check_inactivity: Interface priv is NULL \n"); + return; + } + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + /* Go through the list of stations to check for inactivity */ + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv, i, interfaceTag); + if(!staInfo ) { + continue; + } + + unifi_trace(priv, UDBG3, "Running Inactivity handler Time %xus station's last activity %xus\n", + currentTime, staInfo->lastActivity); + + + elapsedTime = (currentTime >= staInfo->lastActivity)? + (currentTime - staInfo->lastActivity): + (~((CsrUint32)0) - staInfo->lastActivity + currentTime); + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + if (elapsedTime > MAX_INACTIVITY_INTERVAL) { + memcpy((CsrUint8*)&peerMacAddress, (CsrUint8*)&staInfo->peerMacAddress, sizeof(CsrWifiMacAddress)); + + /* Indicate inactivity for the station */ + unifi_trace(priv, UDBG3, "Station %x:%x:%x:%x:%x:%x inactive since %xus\n sending Inactive Ind\n", + peerMacAddress.a[0], peerMacAddress.a[1], + peerMacAddress.a[2], peerMacAddress.a[3], + peerMacAddress.a[4], peerMacAddress.a[5], + elapsedTime); + + CsrWifiRouterCtrlStaInactiveIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); + } + } + + interfacePriv->last_inactivity_check = currentTime; +} + +/* Function to update activity of a station */ +void uf_update_sta_activity(unifi_priv_t *priv, CsrUint16 interfaceTag, const CsrUint8 *peerMacAddress) +{ + CsrTime elapsedTime, currentTime; /* Time in microseconds */ + CsrTime timeHi; /* Not used - Time in microseconds */ + CsrWifiRouterCtrlStaInfo_t *staInfo; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + unsigned long lock_flags; + + if (interfacePriv == NULL) { + unifi_trace(priv, UDBG3, "uf_check_inactivity: Interface priv is NULL \n"); + return; + } + + currentTime = CsrTimeGet(&timeHi); + + + staInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, peerMacAddress, interfaceTag); + + if (staInfo == NULL) { + unifi_trace(priv, UDBG4, "Sta does not exist yet"); + return; + } + + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + /* Update activity */ + staInfo->lastActivity = currentTime; + + /* See if inactivity handler needs to be run + * Here it is theoretically possible that the counter may have wrapped around. But + * since we just want to know when to run the inactivity handler it does not really matter. + * Especially since this is data path it makes sense in keeping it simple and avoiding + * 64 bit handling */ + elapsedTime = (currentTime >= interfacePriv->last_inactivity_check)? + (currentTime - interfacePriv->last_inactivity_check): + (~((CsrUint32)0) - interfacePriv->last_inactivity_check + currentTime); + + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + /* Check if it is time to run the inactivity handler */ + if (elapsedTime > INACTIVITY_CHECK_INTERVAL) { + uf_check_inactivity(priv, interfaceTag, currentTime); + } +} +void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) +{ + + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrUint8 i; + int j; + tx_buffered_packets_t * buffered_pkt = NULL; + CsrBool hipslotFree[4] = {TRUE,TRUE,TRUE,TRUE}; + int r; + unsigned long lock_flags; + + func_enter(); + while(!isRouterBufferEnabled(priv,3) && + ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) { + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,0,FALSE)) == -ENOSPC) { + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &interfacePriv->genericMgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + hipslotFree[3]=FALSE; + break; + }else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + CsrWifiRouterCtrlStaInfo_t *staInfo = interfacePriv->staInfo[i]; + if(!hipslotFree[0] && !hipslotFree[1] && !hipslotFree[2] && !hipslotFree[3]) { + unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full \n"); + break; + } + if (staInfo && (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)) { + while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) { + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) { + unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full for voice queue\n"); + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staInfo->mgtFrames); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[3]=(CsrUint8)(staInfo->assignedHandle); + hipslotFree[3] = FALSE; + break; + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + + for(j=3;j>=0;j--) { + if(!hipslotFree[j]) + continue; + + while((buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->dataPdu[j]))) { + buffered_pkt->transmissionControl &= + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) { + /* Enqueue at the head of the queue */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q, &staInfo->dataPdu[j]); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[j]=(CsrUint8)(staInfo->assignedHandle); + hipslotFree[j]=FALSE; + break; + } else { + if(r){ + unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); + /* the PDU failed where we can't do any thing so free the storage */ + unifi_net_data_free(priv, &buffered_pkt->bulkdata); + } + kfree(buffered_pkt); + } + } + } + } + } + func_exit(); +} +void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 interfaceTag) +{ + + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + unsigned long lock_flags; + struct list_head *listHead; + struct list_head *placeHolder; + tx_buffered_packets_t *tx_q_item; + + func_enter(); + if (interfacePriv->noOfbroadcastPktQueued) { + + /* Update the EOSP to the HEAD of b/c list + * beacuse we have received any mgmt packet so it should not hold for long time + * peer may time out. + */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { + tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); + unifi_trace(priv, UDBG1,"updating eosp for list Head hostTag:= 0x%x ",tx_q_item->hostTag); + break; + } + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + } + func_exit(); +} +void resume_suspended_uapsd(unifi_priv_t* priv,CsrUint16 interfaceTag) +{ + + CsrUint8 startIndex; + CsrWifiRouterCtrlStaInfo_t * staInfo = NULL; + unsigned long lock_flags; + /*U-APSD might have stopped because of multicast. So restart it if U-APSD + was active with any of the station*/ + for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { + staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); + if(!staInfo ) { + continue; + } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) + &&(staInfo->uapsdSuspended == TRUE)) { + + /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by + sending data from remaining delivery enabled queues*/ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->uapsdActive = TRUE; + staInfo->uapsdSuspended = FALSE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + uf_continue_uapsd(priv,staInfo); + } + } + +} +void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata, + CSR_SIGNAL *sigptr, CsrUint32 alignOffset) +{ + + maPktReqList_t *maPktreq = NULL; + CSR_MA_PACKET_REQUEST *req = &sigptr->u.MaPacketRequest; + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + CsrUint16 frmCtrl,interfaceTag = 0; + const CsrUint8* macHdrLocation; + struct sk_buff *skb ; + unsigned long lock_flags; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + CsrUint8 *sigbuffer; + CsrUint8 frameType = 0; + func_enter(); + + if(bulkdata == NULL || (0 == bulkdata->d[0].data_length )){ + unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece:bulk data NULL \n"); + func_exit(); + return; + } + macHdrLocation = bulkdata->d[0].os_data_ptr; + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; + /* fectch the frame control value from mac header */ + frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); + + /* Processing done according to Frame/Packet type */ + frameType = ((frmCtrl & 0x000c) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); + + if( (((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_QOS_NULL) || + ((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_NULL ) ) || + ( IEEE802_11_FRAMETYPE_MANAGEMENT== frameType)){ + + /* if packet is NULL or Qos Null no need of retransmit so dont queue it*/ + unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: NULL data Pkt or mgmt\n"); + func_exit(); + return; + } + + /* fetch the station record for corresponding peer mac address */ + if ((staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, req->Ra.x, interfaceTag))) { + maPktreq = (maPktReqList_t*)kmalloc(sizeof(maPktReqList_t),GFP_ATOMIC); + if(maPktreq == NULL){ + unifi_error(priv, + "uf_store_directed_ma_packet_referenece :: Failed to allocate %d byter for maPktreq\n", + sizeof(maPktReqList_t)); + func_exit(); + return; + } + } + + /* staRecord not present that means packet is multicast or generic mgmt so no need to queue it */ + else{ + unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: multicast pkt \n"); + func_exit(); + return ; + } + + /* disbale preemption */ + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + INIT_LIST_HEAD(&maPktreq->q); + maPktreq->staHandler = staRecord->assignedHandle; + memcpy(&maPktreq->signal,sigptr,sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + sizeof(CSR_MA_PACKET_REQUEST)); + sigbuffer = (CsrUint8*)&maPktreq->signal; + sigbuffer[SIZEOF_SIGNAL_HEADER + 1] = alignOffset; + maPktreq->skb = skb_get(skb); + maPktreq->hostTag = req->HostTag; + maPktreq->jiffeTime = jiffies; + list_add_tail(&maPktreq->q,&interfacePriv->directedMaPktReq); + + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + func_exit(); + +} + +#endif diff --git a/drivers/staging/csr/unifi_priv.h b/drivers/staging/csr/unifi_priv.h new file mode 100644 index 000000000000..f687f270a699 --- /dev/null +++ b/drivers/staging/csr/unifi_priv.h @@ -0,0 +1,1148 @@ +/* + ***************************************************************************** + * + * FILE : unifi_priv.h + * + * PURPOSE : Private header file for unifi driver. + * + * UDI = UniFi Debug Interface + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + ***************************************************************************** + */ +#ifndef __LINUX_UNIFI_PRIV_H__ +#define __LINUX_UNIFI_PRIV_H__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19) +#include +#endif + +#ifdef CSR_WIFI_SUPPORT_MMC_DRIVER +#include +#include +#include +#include +#include +#include +#endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ + +#include + +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_unifi_udi.h" +#include "csr_wifi_router_lib.h" +#include "unifiio.h" +#ifndef CSR_WIFI_HIP_TA_DISABLE +#include "csr_wifi_vif_utils.h" +#endif + +/* Define the unifi_priv_t before include the unifi_native.h */ +struct unifi_priv; +typedef struct unifi_priv unifi_priv_t; +#ifdef CSR_SUPPORT_WEXT_AP +struct CsrWifiSmeApConfig; +typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; +#endif +#ifdef CSR_SUPPORT_WEXT +#include "unifi_wext.h" +#endif + +#include "unifi_clients.h" + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#include + +#undef INIT_WORK +#define INIT_WORK(_work, _func) \ + do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + PREPARE_WORK((_work), (_func), (_work)); \ + init_timer(&(_work)->timer); \ + } while(0) + +#endif /* Linux kernel < 2.6.20 */ + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_NETIF_TX_WAKE_ALL_QUEUES(_netdev) netif_tx_wake_all_queues(_netdev) +#define UF_NETIF_TX_START_ALL_QUEUES(_netdev) netif_tx_start_all_queues(_netdev) +#define UF_NETIF_TX_STOP_ALL_QUEUES(_netdev) netif_tx_stop_all_queues(_netdev) +#else +#define UF_NETIF_TX_WAKE_ALL_QUEUES(_netdev) netif_wake_queue(_netdev) +#define UF_NETIF_TX_START_ALL_QUEUES(_netdev) netif_start_queue(_netdev) +#define UF_NETIF_TX_STOP_ALL_QUEUES(_netdev) netif_stop_queue(_netdev) +#endif /* Linux kernel >= 2.6.27 */ + + +#ifdef CSR_NATIVE_LINUX +#include "sme_native/unifi_native.h" +#else +#include "unifi_sme.h" +#endif + +#undef COMPARE_HOST_TAG_TO_ENQUEUE +#define COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item_hosttag,maPktHostTag) \ + if(tx_q_item_hosttag > maPktHostTag){ \ + locationFound = TRUE; \ + ii++; \ + break; \ + } \ + ii++; \ + + +/* The device major number to use when registering the udi driver */ +#define UNIFI_NAME "unifi" +#define MAX_UNIFI_DEVS 2 + +/* 802.11 Mac header offsets */ +#define MAC_HEADER_SIZE 24 +#define QOS_CONTROL_HEADER_SIZE 2 +#define HT_CONTROL_HEADER_SIZE 4 +#define QOS_DATA 0x8 +#define QOS_DATA_NULL 0xc +#define DATA_NULL 0x04 +#define FRAME_CONTROL_ORDER_BIT 0x8000 +#define FRAME_CONTROL_TYPE_FIELD_OFFSET 2 +#define FRAME_CONTROL_SUBTYPE_FIELD_OFFSET 4 +#define IEEE802_11_FRAMETYPE_DATA 0x02 +#define IEEE802_11_FRAMETYPE_CONTROL 0x01 +#define IEEE802_11_FRAMETYPE_MANAGEMENT 0x00 +#define IEEE802_11_FRAMETYPE_RESERVED 0x03 + +/* octet offset from start of mac header for certain fields */ +#define IEEE802_11_ADDR3_OFFSET 16 +#define IEEE802_11_SEQUENCE_CONTROL_OFFSET 22 +#define IEEE802_11_MAX_DATA_LEN 2304 + +/* frame control (FC) masks, for frame control as 16 bit integer */ +#define IEEE802_11_FC_TO_DS_MASK 0x100 +#define IEEE802_11_FC_FROM_DS_MASK 0x200 +#define IEEE802_11_FC_MOREDATA_MASK 0x2000 +#define IEEE802_11_FC_PROTECTED_MASK 0x4000 +#define IEEE80211_FC_ORDER_MASK 0x8000 +#define IEEE80211_FC_SUBTYPE_MASK 0x00f0 +#define IEEE80211_FC_TYPE_MASK 0x000c +#define IEEE80211_FC_PROTO_VERSION_MASK 0x0003 + +/* selected type and subtype combinations as in 7.1.3.1 table 1 + For frame control as 16 bit integer, or for ls octet +*/ +#define IEEE802_11_FC_TYPE_DATA 0x08 +#define IEEE802_11_FC_TYPE_NULL 0x48 +#define IEEE802_11_FC_TYPE_QOS_NULL 0xc8 +#define IEEE802_11_FC_TYPE_QOS_DATA 0x88 + +#define IEEE802_11_FC_TYPE_DATA_SUBTYPE_RESERVED 0x0D + +/* qos control (QC) masks for qos control as 16 bit integer, or for ls octet */ +#define IEEE802_11_QC_TID_MASK 0x0f +#define IEEE802_11_QC_A_MSDU_PRESENT 0x80 + +#define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000 +#define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36 +#define MAX_ACCESS_CATOGORY 4 + +/* Time in us to check for inactivity of stations 5 mins */ +#define INACTIVITY_CHECK_INTERVAL 300000000 +/* Time in us before a station is flagged as inactive */ +#define MAX_INACTIVITY_INTERVAL 300000000 + + +/* Define for maximum BA session */ +#define MAX_SUPPORTED_BA_SESSIONS_TX 1 +#define MAX_SUPPORTED_BA_SESSIONS_RX 4 + +#define MAX_BA_WIND_SIZE 64 +#define MAC_HEADER_ADDR1_OFFSET 4 +#define MAC_HEADER_ADDR2_OFFSET 10 + +/* Define for age (in us) value for frames in MPDU reorder buffer */ +#define CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT 30000 /* 30 milli seconds */ + +/* This macro used in prepare_and_add_macheader*/ +#define ADDRESS_ONE_OFFSET 20 + +/* Defines for STA inactivity detection */ +#define STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD 1 /* in number of stations */ +#define STA_INACTIVE_DETECTION_TIMER_INTERVAL 30 /* in seconds */ +#define STA_INACTIVE_TIMEOUT_VAL 120*1000*1000 /* 120 seconds */ + + +/* Defines used in beacon filtering in case of P2P */ +#define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH 0x7 +#define CSR_WIFI_80211_FRAME_SUBTYPE_BEACON 0x8 +#define CSR_WIFI_BEACON_FIXED_LENGTH 12 +#define CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET 4 +#define CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK ((CsrUint8)(0xF << CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET)) + +#define CSR_WIFI_80211_GET_FRAME_SUBTYPE(frameBuffer) \ + ((CsrUint8)(((CsrUint8 *)frameBuffer)[0] & CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK) >> CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET) + +/* For M4 request received via netdev*/ + +typedef CsrUint8 CsrWifiPacketType; +#define CSR_WIFI_UNICAST_PDU ((CsrWifiPacketType) 0x00) +#define CSR_WIFI_MULTICAST_PDU ((CsrWifiPacketType) 0x1) +#define CSR_WIFI_BROADCAST_PDU ((CsrWifiPacketType) 0x2) + +#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) + +/* Module parameter variables */ +extern int buswidth; +extern int sdio_clock; +extern int use_5g; +extern int disable_hw_reset; +extern int disable_power_control; +extern int enable_wol; +extern int sme_debug; +extern int fw_init[MAX_UNIFI_DEVS]; +extern int tl_80211d; +extern int sdio_byte_mode; +extern int sdio_block_size; +extern int coredump_max; +extern int run_bh_once; +extern int bh_priority; + +struct dlpriv { + const unsigned char *dl_data; + int dl_len; + void *fw_desc; +}; + + +struct uf_thread { + + struct task_struct *thread_task; + + /* wait_queue for waking the unifi_thread kernel thread */ + wait_queue_head_t wakeup_q; + unsigned int wakeup_flag; + + /* + * Use it to block the I/O thread when + * an error occurs or UniFi is reinitialised. + */ + int block_thread; + + char name[16]; + int prio; +}; + +/* + * Link list to hold the received packets for the period the port + * remains closed. + */ +typedef struct rx_buffered_packets { + /* List link structure */ + struct list_head q; + /* Packet to indicate when the port reopens */ + struct sk_buff *skb; + /* Bulkdata to free in case the port closes and need to discard the packet */ + bulk_data_param_t bulkdata; + /* The source address of the packet */ + CsrWifiMacAddress sa; + /* The destination address of the packet */ + CsrWifiMacAddress da; + /* Corresponding signal */ + CSR_SIGNAL signal; +} rx_buffered_packets_t; + + +typedef CsrUint8 CsrWifiAcPowersaveMode; +#define CSR_WIFI_AC_TRIGGER_ONLY_ENABLED 0x00 +#define CSR_WIFI_AC_DELIVERY_ONLY_ENABLE 0X01 +#define CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED 0X03 +#define CSR_WIFI_AC_LEGACY_POWER_SAVE 0X02 + + +#define IS_DELIVERY_ENABLED(mode) (mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)? 1: 0 +#define IS_DELIVERY_AND_TRIGGER_ENABLED(mode) ((mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)||(mode & CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))? 1: 0 +#define IS_DTIM_ACTIVE(flag,hostTag) ((flag == TRUE || hostTag != INVALID_HOST_TAG)) +#define INVALID_HOST_TAG 0xFFFFFFFF +#define UNIFI_TRAFFIC_Q_CONTENTION UNIFI_TRAFFIC_Q_BE + + + + +/* Queue to be used for contention priority */ + +/* + * Link list to hold the tx packets for the period the peer + * powersave/free slots in unifi + */ +typedef struct tx_buffered_packets { + /* List link structure */ + struct list_head q; + CsrUint16 interfaceTag; + CSR_CLIENT_TAG hostTag; + CSR_PROCESS_ID leSenderProcessId; + CSR_TRANSMISSION_CONTROL transmissionControl; + CSR_RATE rate; + /* Bulkdata to free in case the port closes and need to discard the packet */ + bulk_data_desc_t bulkdata; + /* The source address of the packet */ + CsrWifiMacAddress peerMacAddress; + CSR_PRIORITY priority; +} tx_buffered_packets_t; + +/* station record has this data structure */ +typedef struct CsrWifiRouterCtrlStaInfo_t { + + /* Sme sends these parameters */ + CsrWifiMacAddress peerMacAddress; + CsrUint32 assignedHandle; + CsrBool wmmOrQosEnabled; + CsrWifiAcPowersaveMode powersaveMode[MAX_ACCESS_CATOGORY]; + CsrUint16 maxSpLength; + CsrBool uapsdActive; + CsrUint16 noOfSpFramesSent; + + /* Router/Driver database */ +#ifdef CSR_SUPPORT_SME + unifi_port_cfg_t *peerControlledPort; + unifi_port_cfg_t *peerUnControlledPort; + + /* Inactivity feature parameters */ + struct netInterface_priv *interfacePriv; + struct work_struct send_disconnected_ind_task; + CsrBool activity_flag; + CsrUint16 listenIntervalInTus; + CSR_CLIENT_TAG nullDataHostTag; + + /* Activity timestamps for the station */ + CsrTime lastActivity; + + /* during m/c transmission sp suspended */ + CsrBool uapsdSuspended; +#endif + CsrWifiRouterCtrlPeerStatus currentPeerState; + struct list_head dataPdu[MAX_ACCESS_CATOGORY]; + struct list_head mgtFrames; + CsrUint8 spStatus; + CsrUint8 prevFrmType; + CsrUint8 prevFrmAccessCatogory; + CsrBool protection; + CsrUint16 aid; + CsrBool txSuspend; + CsrUint8 timSet; + /* Dont change the value of below macro for SET & RESET */ +#define CSR_WIFI_TIM_RESET 0 +#define CSR_WIFI_TIM_SET 1 +#define CSR_WIFI_TIM_RESETTING 2 +#define CSR_WIFI_TIM_SETTING 3 + + CsrUint16 noOfPktQueued; +}CsrWifiRouterCtrlStaInfo_t; + +#ifdef CSR_SUPPORT_WEXT_AP +struct CsrWifiSmeApConfig { + CsrWifiSsid ssid; + CsrUint16 channel; + CsrWifiNmeApCredentials credentials; + CsrUint8 max_connections; + CsrUint8 if_index; +}; +#endif + +#ifdef CSR_WIFI_RX_PATH_SPLIT +/* This is a test code and may be removed later*/ +#define CSR_WIFI_RX_SIGNAL_BUFFER_SIZE (60+1) + +typedef struct +{ + CsrUint8 *bufptr; /* Signal Primitive */ + bulk_data_param_t data_ptrs; /* Bulk Data pointers */ + CsrUint16 sig_len; +}rx_buff_struct_t; + +typedef struct +{ + CsrUint8 writePointer; /**< write pointer */ + CsrUint8 readPointer; /**< read pointer */ + CsrUint8 size; /**< size of circular buffer */ + rx_buff_struct_t rx_buff[CSR_WIFI_RX_SIGNAL_BUFFER_SIZE]; /**< Element of ciruclar buffer */ +} rxCircularBuffer_t; + +void rx_wq_handler(struct work_struct *work); +#endif + +struct unifi_priv { + + card_t *card; + CsrSdioFunction *sdio; + + /* Index into Unifi_instances[] for this device. */ + int instance; + /* Reference count for this instance */ + int ref_count; + + /* Firmware images */ + struct dlpriv fw_sta; + struct dlpriv fw_conv; /* used for conversion of production test image */ + + /* Char device related structures */ + struct cdev unifi_cdev; + struct cdev unifiudi_cdev; + struct device *unifi_device; + + /* Which wireless interface to use (1 - 2.4GHz, 2 - 5GHz) */ + CSR_IFINTERFACE if_index; + + /* For multiple interface support */ + struct net_device *netdev[CSR_WIFI_NUM_INTERFACES]; + struct netInterface_priv *interfacePriv[CSR_WIFI_NUM_INTERFACES]; + + CsrUint8 totalInterfaceCount; + + int prev_queue; + + /* Name of node under /proc */ + char proc_entry_name[64]; + + /* + * Flags: + * drop_unencrypted + * - Not used? + * netdev_registered + * - whether the netdev has been registered. + */ + unsigned int drop_unencrypted : 1; + + /* Our list of unifi linux clients. */ + ul_client_t ul_clients[MAX_UDI_CLIENTS]; + + /* Mutex to protect using the logging hook after UDI client is gone */ + struct semaphore udi_logging_mutex; + /* Pointer to the ul_clients[] array */ + ul_client_t *logging_client; + + /* A ul_client_t* used to send the netdev related MIB requests. */ + ul_client_t *netdev_client; + + /* The SME ul_client_t pointer. */ + ul_client_t *sme_cli; + + /* The AMP ul_client_t pointer. */ + ul_client_t *amp_client; + + /* + * Semaphore for locking the top-half to one user process. + * This is necessary to prevent multiple processes calling driver + * operations. This can happen because the network driver entry points + * can be called from multiple processes. + */ +#ifdef USE_DRIVER_LOCK + struct semaphore lock; +#endif /* USE_DRIVER_LOCK */ + + /* Flag to say that an operation was aborted */ + int io_aborted; + + struct uf_thread bh_thread; + +#define UNIFI_INIT_NONE 0x00 +#define UNIFI_INIT_IN_PROGRESS 0x01 +#define UNIFI_INIT_FW_DOWNLOADED 0x02 +#define UNIFI_INIT_COMPLETED 0x04 + unsigned char init_progress; + + int sme_is_present; + + /* The WMM features that UniFi uses in the current BSS */ + unsigned int sta_wmm_capabilities; + + /* Debug only */ + char last_debug_string[256]; + unsigned short last_debug_word16[16]; + +#ifdef CSR_SUPPORT_SME + /* lock to protect the tx queues list */ + spinlock_t tx_q_lock; + CsrUint8 allPeerDozing; + CsrUint8 pausedStaHandle[MAX_ACCESS_CATOGORY]; + /* Max packet the driver can queue, irrespective of interface number */ + CsrUint16 noOfPktQueuedInDriver; +#define CSR_WIFI_DRIVER_SUPPORT_FOR_MAX_PKT_QUEUEING 512 +#define CSR_WIFI_DRIVER_MAX_PKT_QUEUING_THRESHOLD_PER_PEER 64 +#define CSR_WIFI_DRIVER_MINIMUM_BROADCAST_PKT_THRESHOLD 3 + + CsrBool routerBufferEnable[MAX_ACCESS_CATOGORY]; + /* lock to protect stainfo members and priv members*/ + spinlock_t staRecord_lock; +#endif +#ifdef CSR_NATIVE_LINUX +#ifdef CSR_SUPPORT_WEXT + /* wireless config */ + struct wext_config wext_conf; +#endif + + /* Mutex to protect the MLME blocking requests */ + struct semaphore mlme_blocking_mutex; + + /* The ul_client that provides the blocking API for WEXT calls */ + ul_client_t *wext_client; + +#endif /* CSR_NATIVE_LINUX */ + +#ifdef CSR_SUPPORT_SME + wait_queue_head_t sme_request_wq; + /* Semaphore to protect the SME blocking requests */ + struct semaphore sme_sem; + /* Structure to hold the SME blocking requests data*/ + sme_reply_t sme_reply; + + /* Structure to hold a traffic protocol indication */ + struct ta_ind { + struct work_struct task; + CsrWifiRouterCtrlTrafficPacketType packet_type; + CsrWifiRouterCtrlProtocolDirection direction; + CsrWifiMacAddress src_addr; + int in_use; + } ta_ind_work; + + struct ta_sample_ind { + struct work_struct task; + CsrWifiRouterCtrlTrafficStats stats; + int in_use; + } ta_sample_ind_work; + + __be32 sta_ip_address; + CsrWifiRouterCtrlSmeVersions sme_versions; + + /* + * Flag to reflect state of unifi_sys_wifi_on_*() progress. + * This indicates whether we are in an "wifi on" state when we are + * allowed to indication errors with unifi_mgt_wifi_off_ind() + */ + enum { + wifi_on_unspecified = -1, + wifi_on_in_progress = 0, + wifi_on_done = 1, + } wifi_on_state; + + /* Userspace TaskId for the SME Set when a wifi on req is received */ + CsrSchedQid CSR_WIFI_SME_IFACEQUEUE; + + struct work_struct multicast_list_task; + /* + * The SME installs filters to ask for specific MA-UNITDATA.req + * to be passed to different SME components. + */ +#define MAX_MA_UNIDATA_IND_FILTERS 8 + sme_ma_unidata_ind_filter_t sme_unidata_ind_filters[MAX_MA_UNIDATA_IND_FILTERS]; + +/* UNIFI_CFG related parameters */ + uf_cfg_bcast_packet_filter_t packet_filters; + unsigned char *filter_tclas_ies; + /* The structure that holds all the connection configuration. */ + CsrWifiSmeConnectionConfig connection_config; +#ifdef CSR_SUPPORT_WEXT + + int ignore_bssid_join; + struct iw_statistics wext_wireless_stats; + + /* The MIB and MAC address files contents, read from userspace */ + CsrWifiSmeDataBlock mib_data; + CsrWifiMacAddress sta_mac_address; + + int wep_tx_key_index; + wep_key_t wep_keys[NUM_WEPKEYS]; + + +#ifdef CSR_SUPPORT_WEXT_AP + CsrWifiSmeApMacConfig ap_mac_config; + CsrWifiNmeApConfig group_sec_config; + CsrWifiSmeApConfig_t ap_config; +#endif + struct work_struct sme_config_task; + +#endif /* CSR_SUPPORT_WEXT */ + +#endif /* CSR_SUPPORT_SME */ + +#ifdef CSR_SME_USERSPACE + void *smepriv; +#endif /* CSR_SME_USERSPACE */ + + card_info_t card_info; + + /* Mutex to protect unifi_send_signal() */ + spinlock_t send_signal_lock; + + + /* + * The workqueue to offload the TA run + * and the multicast addresses list set + */ + struct workqueue_struct *unifi_workqueue; + + unsigned char *mib_cfm_buffer; + unsigned int mib_cfm_buffer_length; + + int ptest_mode; /* Set when in production test mode */ + int coredump_mode; /* Set when SME has requested a coredump */ + CsrBool wol_suspend; /* Set when suspending with UniFi powered */ + +#define UF_UNCONTROLLED_PORT_Q 0 +#define UF_CONTROLLED_PORT_Q 1 + + /* Semaphore to protect the rx queues list */ + struct semaphore rx_q_sem; + + /* Spinlock to protect M4 data */ + spinlock_t m4_lock; + /* Spinlock to protect BA RX data */ + spinlock_t ba_lock; +#ifndef ALLOW_Q_PAUSE + /* Array to indicate if a particular Tx queue is paused, this may not be + * required in a multiqueue implementation since we can directly stop kernel + * queues */ + CsrUint8 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX]; +#endif + +#ifdef CSR_WIFI_RX_PATH_SPLIT + struct workqueue_struct *rx_workqueue; + struct work_struct rx_work_struct; + rxCircularBuffer_t rxSignalBuffer; + +#endif + + CsrUint32 rxTcpThroughput; + CsrUint32 txTcpThroughput; + CsrUint32 rxUdpThroughput; + CsrUint32 txUdpThroughput; + + + CsrUint8 wapi_multicast_filter; + CsrUint8 wapi_unicast_filter; + CsrUint8 wapi_unicast_queued_pkt_filter; +}; + +typedef struct { + CsrUint16 queue_length[4]; + CsrUint8 os_queue_paused; +} unifi_OsQosInfo; + + +typedef struct { + CsrBool active; + bulk_data_param_t bulkdata; + CSR_SIGNAL signal; + CsrUint16 sn; + CsrTime recv_time; +} frame_desc_struct; + +typedef struct { + frame_desc_struct *buffer; + CsrUint16 wind_size; + CsrUint16 occupied_slots; + struct timer_list timer; + CsrUint16 timeout; + CsrUint16 expected_sn; + CsrUint16 start_sn; + CsrBool trigger_ba_after_ssn; + struct netInterface_priv *interfacePriv; + CsrUint16 tID; + CsrWifiMacAddress macAddress; + struct work_struct send_ba_err_task; +} ba_session_rx_struct; + + +typedef struct { + struct netInterface_priv *interfacePriv; + CsrUint16 tID; + CsrWifiMacAddress macAddress; +} ba_session_tx_struct; + +typedef struct netInterface_priv +{ + CsrUint16 InterfaceTag; + struct unifi_priv *privPtr; + ba_session_tx_struct *ba_session_tx[MAX_SUPPORTED_BA_SESSIONS_TX]; + ba_session_rx_struct *ba_session_rx[MAX_SUPPORTED_BA_SESSIONS_RX]; + frame_desc_struct ba_complete[MAX_BA_WIND_SIZE]; + CsrUint8 ba_complete_index; + CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS]; + struct work_struct send_m4_ready_task; + struct net_device_stats stats; + CsrUint8 interfaceMode; + CsrBool protect; + CsrWifiMacAddress bssid; + /* + * Flag to reflect state of CONNECTED indication signal. + * This indicates whether we are "joined" an Access Point (i.e. have + * nominated an AP and are receiving beacons) but give no indication + * of whether we are authenticated and/or associated. + */ + enum { + UnifiConnectedUnknown = -1, + UnifiNotConnected = 0, + UnifiConnected = 1, + } connected; +#ifdef CSR_SUPPORT_WEXT + /* Tracks when we are waiting for a netdevice state change callback */ + CsrBool wait_netdev_change; + /* True if we have successfully registered for netdev callbacks */ + CsrBool netdev_callback_registered; +#endif /* CSR_SUPPORT_WEXT */ + unsigned int netdev_registered; +#define UNIFI_MAX_MULTICAST_ADDRESSES 10 + /* The multicast addresses list that the thread needs to set. */ + u8 mc_list[UNIFI_MAX_MULTICAST_ADDRESSES*ETH_ALEN]; + /* The multicast addresses count that the thread needs to set. */ + int mc_list_count; + CsrUint32 tag; +#ifdef CSR_SUPPORT_SME + /* (un)controlled port configuration */ + unifi_port_config_t controlled_data_port; + unifi_port_config_t uncontrolled_data_port; + + /* station record maintenance related data structures */ + CsrUint8 num_stations_joined; + CsrWifiRouterCtrlStaInfo_t *(staInfo)[UNIFI_MAX_CONNECTIONS]; + struct list_head genericMgtFrames; + struct list_head genericMulticastOrBroadCastFrames; + struct list_head genericMulticastOrBroadCastMgtFrames; + struct list_head directedMaPktReq; + + /* Timer for detecting station inactivity */ + struct timer_list sta_activity_check_timer; + CsrBool sta_activity_check_enabled; + + /* Timestamp when the last inactivity check was done */ + CsrTime last_inactivity_check; + + /*number of multicast or borad cast packets queued*/ + CsrUint16 noOfbroadcastPktQueued; +#endif + /* A list to hold the buffered uncontrolled port packets */ + struct list_head rx_uncontrolled_list; + /* A list to hold the buffered controlled port packets */ + struct list_head rx_controlled_list; + /* Buffered M4 signal to take care of WPA race condition */ + CSR_SIGNAL m4_signal; + bulk_data_desc_t m4_bulk_data; + /* This should be removed and m4_hostTag should be used for checking*/ + CsrBool m4_sent; + CSR_CLIENT_TAG m4_hostTag; + CsrBool dtimActive; + CsrBool intraBssEnabled; + CsrUint32 multicastPduHostTag; /* Used to set the tim after getting + a confirm for it */ +} netInterface_priv_t; + +typedef struct maPktReqList{ + struct list_head q; + struct sk_buff *skb; + CSR_SIGNAL signal; + CSR_CLIENT_TAG hostTag; + CsrUint32 staHandler; + unsigned long jiffeTime; +}maPktReqList_t; + +#ifndef ALLOW_Q_PAUSE +#define net_is_tx_q_paused(priv, q) (priv->tx_q_paused_flag[q]) +#define net_tx_q_unpause(priv, q) (priv->tx_q_paused_flag[q] = 0) +#define net_tx_q_pause(priv, q) (priv->tx_q_paused_flag[q] = 1) +#endif + +#ifdef CSR_SUPPORT_SME +#define routerStartBuffering(priv,queue) priv->routerBufferEnable[(queue)] = TRUE; +#define routerStopBuffering(priv,queue) priv->routerBufferEnable[(queue)] = FALSE; +#define isRouterBufferEnabled(priv,queue) priv->routerBufferEnable[(queue)] +#endif + +#ifdef USE_DRIVER_LOCK +#define LOCK_DRIVER(_p) down_interruptible(&(_p)->lock) +#define UNLOCK_DRIVER(_p) up(&(_p)->lock) +#else +#define LOCK_DRIVER(_p) (void)(_p); /* as nothing */ +#define UNLOCK_DRIVER(_p) (void)(_p); /* as nothing */ +#endif /* USE_DRIVER_LOCK */ + +CsrInt32 CsrHipResultToStatus(CsrResult csrResult); + + +/* + * SDIO related functions and callbacks + */ +int uf_sdio_load(void); +void uf_sdio_unload(void); +unifi_priv_t *uf_find_instance(int inst); +int uf_find_priv(unifi_priv_t *priv); +int uf_find_netdev_priv(netInterface_priv_t *priv); +unifi_priv_t *uf_get_instance(int inst); +void uf_put_instance(int inst); +int csr_sdio_linux_install_irq(CsrSdioFunction *sdio); +int csr_sdio_linux_remove_irq(CsrSdioFunction *sdio); + +void uf_add_os_device(int bus_id, struct device *os_device); +void uf_remove_os_device(int bus_id); + + + +/* + * Claim/release SDIO + * + * For multifunction cards, we cannot grub the SDIO lock around the unifi_bh() + * as this prevents other functions using SDIO. + * Since some of CSR SDIO API is used regardless of trying to lock unifi_bh() + * we have followed this scheme: + * 1. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is defined + * then we call CsrSdioClaim/CsrSdioRelease(). + * 2. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is not defined + * then we call _sdio_claim_host/_sdio_claim_host(). Use of this should be restricted + * to the SDIO glue layer only (e.g. sdio_mmc.c). + * 3. If a function needs protection, regardless of the CSR_WIFI_SINGLE_FUNCTION + * then we call directly the sdio_claim_host/sdio_release_host(). + * Use of this must be restricted to the SDIO glue layer only (e.g. sdio_mmc.c). + * + * Note: The _func and function pointers are _not_ the same. + * The former is the (struct sdio_func*) context, which restricts the use to the SDIO glue layer. + * The latter is the (CsrSdioFunction*) context, which allows calls from all layers. + */ + +#ifdef CSR_WIFI_SUPPORT_MMC_DRIVER + +#ifdef CSR_WIFI_SINGLE_FUNCTION +#define CsrSdioClaim(function) sdio_claim_host((function)->priv); +#define CsrSdioRelease(function) sdio_release_host((function)->priv); + +#define _sdio_claim_host(_func) +#define _sdio_release_host(_func) + +#else +#define CsrSdioClaim(function) +#define CsrSdioRelease(function) + +#define _sdio_claim_host(_func) sdio_claim_host(_func) +#define _sdio_release_host(_func) sdio_release_host(_func) + +#endif /* CSR_WIFI_SINGLE_FUNCTION */ + +#else +#define _sdio_claim_host(_func) +#define _sdio_release_host(_func) + +#define CsrSdioClaim(function) +#define CsrSdioRelease(function) + +#endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ + + +/* + * Functions to allocate and free an ethernet device. + */ +unifi_priv_t *uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id); +int uf_free_netdevice(unifi_priv_t *priv); + +/* Allocating function for other interfaces */ +CsrBool uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, CsrUint16 interfaceTag); + +/* + * Firmware download related functions. + */ +int uf_run_unifihelper(unifi_priv_t *priv); +int uf_request_firmware_files(unifi_priv_t *priv, int is_fw); +int uf_release_firmware_files(unifi_priv_t *priv); +int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free); + +/* + * Functions to create and delete the device nodes. + */ +int uf_create_device_nodes(unifi_priv_t *priv, int bus_id); +void uf_destroy_device_nodes(unifi_priv_t *priv); + +/* + * Upper Edge Initialisation functions + */ +int uf_init_bh(unifi_priv_t *priv); +int uf_init_hw(unifi_priv_t *priv); + +/* Thread related helper functions */ +int uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *)); +void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread); +void uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread); + + +/* + * Unifi Linux functions + */ +void ul_init_clients(unifi_priv_t *priv); + +/* Configuration flags */ +#define CLI_USING_WIRE_FORMAT 0x0002 +#define CLI_SME_USERSPACE 0x0020 +ul_client_t *ul_register_client(unifi_priv_t *priv, + unsigned int configuration, + udi_event_t udi_event_clbk); +int ul_deregister_client(ul_client_t *pcli); + +int ul_send_signal_unpacked(unifi_priv_t *priv, + CSR_SIGNAL *sigptr, + bulk_data_param_t *bulkdata); +int ul_send_signal_raw(unifi_priv_t *priv, + unsigned char *sigptr, int siglen, + bulk_data_param_t *bulkdata); + +void ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len); + + +/* + * Data plane operations + */ +/* + * data_tx.c + */ +int uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, + unsigned int length); + +#ifdef CSR_SUPPORT_SME +CsrBool uf_check_broadcast_bssid(unifi_priv_t *priv, const bulk_data_param_t *bulkdata); +CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo,CsrUint8 pmBit,CsrUint16 interfaceTag); +void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pmBit,CsrUint16 interfaceTag); +int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, + struct ethhdr *ehdr, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + const CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata, + CsrUint8 macHeaderLengthInBytes); +CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord); +CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck); +void uf_process_wmm_deliver_ac_uapsd ( unifi_priv_t * priv, + CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + CsrUint16 qosControl, + CsrUint16 interfaceTag); + +void uf_send_buffered_data_from_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, CsrUint8 queue, struct list_head *txList); +void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, CsrUint8 queue, struct list_head *txList); + +void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo); +void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); +void uf_send_nulldata(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); +void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata,CSR_SIGNAL *sigptr,CsrUint32 alignOffset); + + + +#endif +CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, CsrUint8 *peerMacAddress, CSR_CLIENT_TAG hostTag, CsrUint16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, CSR_RATE TransmitRate, CSR_PRIORITY priority, CSR_PROCESS_ID senderId, bulk_data_param_t *bulkdata); +void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata, CsrUint32 siglen); +#ifdef CSR_SUPPORT_SME +void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue queue); +int uf_process_station_records_for_sending_data(unifi_priv_t *priv,CsrUint16 interfaceTag, + CsrWifiRouterCtrlStaInfo_t *srcStaInfo, + CsrWifiRouterCtrlStaInfo_t *dstStaInfo); +void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv, + struct list_head *frames_need_cfm_list, + struct list_head * list); +void send_auto_ma_packet_confirm(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + struct list_head *buffered_frames_list); +void uf_flush_list(unifi_priv_t * priv, struct list_head * list); +void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list); +tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList); +void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag); +void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 interfaceTag); +void resume_suspended_uapsd(unifi_priv_t* priv,CsrUint16 interfaceTag); +#endif +/* + * netdev.c + */ + +#ifndef P80211_OUI_LEN +#define P80211_OUI_LEN 3 +#endif +typedef struct { + u8 dsap; /* always 0xAA */ + u8 ssap; /* always 0xAA */ + u8 ctrl; /* always 0x03 */ + u8 oui[P80211_OUI_LEN]; /* organizational universal id */ + u16 protocol; +} __attribute__ ((packed)) llc_snap_hdr_t; +int skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto); +int skb_80211_to_ether(unifi_priv_t *priv, struct sk_buff *skb, + const unsigned char *daddr, const unsigned char *saddr, + const CSR_SIGNAL *signal, + bulk_data_param_t *bulkdata); + +const char *result_code_str(int result); + + +/* prepares & appends the Mac header for the payload */ +int prepare_and_add_macheader(unifi_priv_t *priv, + struct sk_buff *skb, + struct sk_buff *newSkb, + CSR_PRIORITY priority, + bulk_data_param_t *bulkdata, + CsrUint16 interfaceTag, + const CsrUint8 *daddr, + const CsrUint8 *saddr, + CsrBool protection); +CSR_PRIORITY +get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, netInterface_priv_t *interfacePriv); + +void +unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, + CSR_RATE TransmitRate, CSR_CLIENT_TAG hostTag, + CsrUint16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, + CSR_PROCESS_ID leSenderProcessId, CsrUint8 *peerMacAddress, + CSR_SIGNAL *signal); + + +/* Pack the LSB to include station handle & status of tim set */ +#define CSR_WIFI_PACK_SENDER_ID_LSB_FOR_TIM_REQ(handle, timState) ((handle << 2) | timState) +/* get the station record handle from the sender ID */ +#define CSR_WIFI_GET_STATION_HANDLE_FROM_RECEIVER_ID(receiverProcessId) (CsrUint8) ((receiverProcessId & 0xff) >> 2) +/* get the timSet status from the sender ID */ +#define CSR_WIFI_GET_TIMSET_STATE_FROM_RECEIVER_ID(receiverProcessId) (CsrUint8) (receiverProcessId & 0x03) + +/* handle is 6 bits to accomodate in senderId LSB (only 64 station can be associated) */ +#define CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE 0x3F + +void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 interfaceTag, CsrUint32 handle); +void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUint16 senderProcessId); + +/* Clear the Peer station Record, in case of wifioff/unexpected card removal */ +void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, CsrUint16 interfaceTag); + +void scroll_ba_window(unifi_priv_t *priv, + netInterface_priv_t *interfacePriv, + ba_session_rx_struct *ba_session, + CsrUint16 sn); + +CsrBool blockack_session_stop(unifi_priv_t *priv, + CsrUint16 interfaceTag, + CsrWifiRouterCtrlBlockAckRole role, + CsrUint16 tID, + CsrWifiMacAddress macAddress); +#ifdef CSR_SUPPORT_SME +/* Fetch the protection information from interface Mode */ +CsrInt8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, CsrUint16 interfaceTag, const CsrUint8 *daddr); +#endif + +/* Fetch the station record handler from data base for matching Mac address */ +#ifdef CSR_SUPPORT_SME +CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(unifi_priv_t *priv, + const CsrUint8 *peerMacAddress, + CsrUint16 interfaceTag); + +/* Fetch the station record handler from data base for matching handle */ +CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_priv_t *priv, + CsrUint32 handle, + CsrUint16 interfaceTag); + +void uf_update_sta_activity(unifi_priv_t *priv, CsrUint16 interfaceTag, const CsrUint8 *peerMacAddress); +void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +int uf_install_qdisc(struct net_device *dev); +#endif + +void uf_resume_data_plane(unifi_priv_t *priv, int queue, + CsrWifiMacAddress peer_address, + CsrUint16 interfaceTag); +void uf_free_pending_rx_packets(unifi_priv_t *priv, int queue, + CsrWifiMacAddress peer_address,CsrUint16 interfaceTag); + +int uf_register_netdev(unifi_priv_t *priv, int numOfInterface); +void uf_unregister_netdev(unifi_priv_t *priv); + +void uf_net_get_name(struct net_device *dev, char *name, int len); + +void uf_send_queue_info(unifi_priv_t *priv); +CsrUint16 uf_get_vif_identifier(CsrWifiRouterCtrlMode mode, CsrUint16 tag); + +void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, + CsrWifiMacAddress source_address, + int indicate, CsrUint16 interfaceTag); + +/* + * inet.c + */ +void uf_register_inet_notifier(void); +void uf_unregister_inet_notifier(void); + + +/* + * Suspend / Resume handlers + */ +void unifi_resume(void *ospriv); +void unifi_suspend(void *ospriv); + + +#define QOS_CAPABILITY_WMM_ENABLED 0x0001 +#define QOS_CAPABILITY_WMM_UAPSD 0x0002 +#define QOS_CAPABILITY_ACM_BE_ENABLED 0x0010 +#define QOS_CAPABILITY_ACM_BK_ENABLED 0x0020 +#define QOS_CAPABILITY_ACM_VI_ENABLED 0x0040 +#define QOS_CAPABILITY_ACM_VO_ENABLED 0x0080 +#define QOS_CAPABILITY_TS_BE_ENABLED 0x0100 +#define QOS_CAPABILITY_TS_BK_ENABLED 0x0200 +#define QOS_CAPABILITY_TS_VI_ENABLED 0x0400 +#define QOS_CAPABILITY_TS_VO_ENABLED 0x0800 + + +/* EAPOL PDUS */ +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888e +#endif +#ifndef ETH_P_WAI +#define ETH_P_WAI 0x88b4 +#endif +/* + * unifi_dbg.c + */ +void debug_string_indication(unifi_priv_t *priv, + const unsigned char *extra, + unsigned int extralen); +void debug_word16_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); +void debug_generic_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); + + +/* + * putest.c + */ +int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg); + +int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg); +int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg); + + +/* Macro for formatting a MAC address with a prefix string */ +#define UF_TRACE_MAC(priv, lvl, msg, addr) \ + unifi_trace(priv, lvl, \ + "%s %02x-%02x-%02x-%02x-%02x-%02x\n", \ + msg, \ + *(((CsrUint8 *)addr)+0), \ + *(((CsrUint8 *)addr)+1), \ + *(((CsrUint8 *)addr)+2), \ + *(((CsrUint8 *)addr)+3), \ + *(((CsrUint8 *)addr)+4), \ + *(((CsrUint8 *)addr)+5)) + +#endif /* __LINUX_UNIFI_PRIV_H__ */ diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c new file mode 100644 index 000000000000..4ee663fe4e4a --- /dev/null +++ b/drivers/staging/csr/unifi_sme.c @@ -0,0 +1,1164 @@ +/* + * *************************************************************************** + * FILE: unifi_sme.c + * + * PURPOSE: SME related functions. + * + * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ + +#include "unifi_priv.h" +#include "csr_wifi_hip_unifi.h" +#include "csr_wifi_hip_conversions.h" + + + + + int +convert_sme_error(CsrResult error) +{ + switch (error) { + case CSR_RESULT_SUCCESS: + return 0; + case CSR_RESULT_FAILURE: + case CSR_WIFI_RESULT_NOT_FOUND: + case CSR_WIFI_RESULT_TIMED_OUT: + case CSR_WIFI_RESULT_CANCELLED: + case CSR_WIFI_RESULT_UNAVAILABLE: + return -EIO; + case CSR_WIFI_RESULT_NO_ROOM: + return -EBUSY; + case CSR_WIFI_RESULT_INVALID_PARAMETER: + return -EINVAL; + case CSR_WIFI_RESULT_UNSUPPORTED: + return -EOPNOTSUPP; + default: + return -EIO; + } +} + + +/* + * --------------------------------------------------------------------------- + * sme_log_event + * + * Callback function to be registered as the SME event callback. + * Copies the signal content into a new udi_log_t struct and adds + * it to the read queue for the SME client. + * + * Arguments: + * arg This is the value given to unifi_add_udi_hook, in + * this case a pointer to the client instance. + * signal Pointer to the received signal. + * signal_len Size of the signal structure in bytes. + * bulkdata Pointers to any associated bulk data. + * dir Direction of the signal. Zero means from host, + * non-zero means to host. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ + void +sme_log_event(ul_client_t *pcli, + const u8 *signal, int signal_len, + const bulk_data_param_t *bulkdata, + int dir) +{ + unifi_priv_t *priv; + CSR_SIGNAL unpacked_signal; + CsrWifiSmeDataBlock mlmeCommand; + CsrWifiSmeDataBlock dataref1; + CsrWifiSmeDataBlock dataref2; + CsrResult result = CSR_RESULT_SUCCESS; + int r; + + /* Following bits are encoded in hostTag These are there to ensure that hostTags are unique*/ +#define CSR_SME_DATA 0x00000000 /* Frames Sent by SME */ +#define CSR_PAL_DATA 0X10000000 /* Frames Sent by PAL-D*/ +#define CSR_NME_DATA 0x20000000 /* Frames Sent by NME*/ +#define APPLICATION_DATA 0x30000000 /* Frames Sent by Application*/ + + func_enter(); + /* Just a sanity check */ + if ((signal == NULL) || (signal_len <= 0)) { + func_exit(); + return; + } + + priv = uf_find_instance(pcli->instance); + if (!priv) { + unifi_error(priv, "sme_log_event: invalid priv\n"); + func_exit(); + return; + } + + if (priv->smepriv == NULL) { + unifi_error(priv, "sme_log_event: invalid smepriv\n"); + func_exit(); + return; + } + + unifi_trace(priv, UDBG3, + "sme_log_event: Process signal 0x%.4X\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal)); + + + /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */ + r = read_unpack_signal(signal, &unpacked_signal); + if (r == CSR_RESULT_SUCCESS) { + if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) || + (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID)) + { + func_exit(); + return; + } + if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID) + { + CsrUint16 frmCtrl; + CsrBool unicastPdu = TRUE; + CsrUint8 *macHdrLocation; + CsrUint8 *raddr = NULL, *taddr = NULL; + CsrWifiMacAddress peerMacAddress; + /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/ + CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication; + + macHdrLocation = (CsrUint8 *) bulkdata->d[0].os_data_ptr; + /* Fetch the frame control value from mac header */ + frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); + + /* Point to the addresses */ + raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET; + taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET; + + CsrMemCpy(peerMacAddress.a, taddr, ETH_ALEN); + + if(ind->ReceptionStatus == CSR_MICHAEL_MIC_ERROR) + { + if (*raddr & 0x1) + unicastPdu = FALSE; + + CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0, + (ind->VirtualInterfaceIdentifier & 0xff),peerMacAddress, + unicastPdu); + return; + } + else + { + if(ind->ReceptionStatus == CSR_RX_SUCCESS) + { + CsrUint8 pmBit = (frmCtrl & 0x1000)?0x01:0x00; + CsrUint16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff); + CsrWifiRouterCtrlStaInfo_t *srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,taddr,interfaceTag); + if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE)) + { + uf_process_pm_bit_for_peer(priv,srcStaInfo,pmBit,interfaceTag); + + /* Update station last activity flag */ + srcStaInfo->activity_flag = TRUE; + } + } + } + } + + if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_CONFIRM_ID) + { + CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm; + CsrUint16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff); + netInterface_priv_t *interfacePriv; + CSR_MA_PACKET_REQUEST *req; + CsrWifiMacAddress peerMacAddress; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) + { + unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag); + func_exit(); + return; + } + + unifi_trace(priv,UDBG1,"MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus); + + interfacePriv = priv->interfacePriv[interfaceTag]; +#ifdef CSR_SUPPORT_SME + if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || + interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { + + if(cfm->HostTag == interfacePriv->multicastPduHostTag){ + uf_process_ma_pkt_cfm_for_ap(priv ,interfaceTag, cfm); + } + } +#endif + + req = &interfacePriv->m4_signal.u.MaPacketRequest; + + if(cfm->HostTag & 0x80000000) + { + if (cfm->TransmissionStatus != CSR_TX_SUCCESSFUL) + { + result = CSR_RESULT_FAILURE; + } +#ifdef CSR_SUPPORT_SME + memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN); + /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/ + if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag)) + { + unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__); + CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, + interfaceTag, + peerMacAddress, + result); + interfacePriv->m4_sent = FALSE; + interfacePriv->m4_hostTag = 0xffffffff; + } +#endif + /* If EAPOL was requested via router APIs then send cfm else ignore*/ + if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) { + CsrWifiRouterMaPacketCfmSend((CsrUint16)signal[2], + cfm->VirtualInterfaceIdentifier, + result, + (cfm->HostTag & 0x3fffffff), cfm->Rate); + } else { + unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__); + } + func_exit(); + return; + } + } + } + + mlmeCommand.length = signal_len; + mlmeCommand.data = (CsrUint8*)signal; + + dataref1.length = bulkdata->d[0].data_length; + if (dataref1.length > 0) { + dataref1.data = (CsrUint8 *) bulkdata->d[0].os_data_ptr; + } else + { + dataref1.data = NULL; + } + + dataref2.length = bulkdata->d[1].data_length; + if (dataref2.length > 0) { + dataref2.data = (CsrUint8 *) bulkdata->d[1].os_data_ptr; + } else + { + dataref2.data = NULL; + } + + CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data, + dataref1.length, dataref1.data, + dataref2.length, dataref2.data); + + func_exit(); +} /* sme_log_event() */ + + +/* + * --------------------------------------------------------------------------- + * uf_sme_port_state + * + * Return the state of the controlled port. + * + * Arguments: + * priv Pointer to device private context struct + * address Pointer to the destination for tx or sender for rx address + * queue Controlled or uncontrolled queue + * + * Returns: + * An unifi_ControlledPortAction value. + * --------------------------------------------------------------------------- + */ +CsrWifiRouterCtrlPortAction +uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, CsrUint16 interfaceTag) +{ + int i; + unifi_port_config_t *port; + netInterface_priv_t *interfacePriv; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n"); + return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + } + + interfacePriv = priv->interfacePriv[interfaceTag]; + + if (queue == UF_CONTROLLED_PORT_Q) { + port = &interfacePriv->controlled_data_port; + } else { + port = &interfacePriv->uncontrolled_data_port; + } + + if (!port->entries_in_use) { + unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); + return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; + } + + /* If the port configuration is common for all destinations, return it. */ + if (port->overide_action == UF_DATA_PORT_OVERIDE) { + unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", + port->port_cfg[0].port_action); + return port->port_cfg[0].port_action; + } + + unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use); + + /* If multiple configurations exist.. */ + for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + /* .. go through the list and match the destination address. */ + if (port->port_cfg[i].in_use && + memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { + /* Return the desired action. */ + return port->port_cfg[i].port_action; + } + } + + /* Could not find any information, return Open. */ + unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n"); + return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; +} /* uf_sme_port_state() */ + +/* + * --------------------------------------------------------------------------- + * uf_sme_port_config_handle + * + * Return the port config handle of the controlled/uncontrolled port. + * + * Arguments: + * priv Pointer to device private context struct + * address Pointer to the destination for tx or sender for rx address + * queue Controlled or uncontrolled queue + * + * Returns: + * An unifi_port_cfg_t* . + * --------------------------------------------------------------------------- + */ +unifi_port_cfg_t* +uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, CsrUint16 interfaceTag) +{ + int i; + unifi_port_config_t *port; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n"); + return NULL; + } + + if (queue == UF_CONTROLLED_PORT_Q) { + port = &interfacePriv->controlled_data_port; + } else { + port = &interfacePriv->uncontrolled_data_port; + } + + if (!port->entries_in_use) { + unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); + return NULL; + } + + /* If the port configuration is common for all destinations, return it. */ + if (port->overide_action == UF_DATA_PORT_OVERIDE) { + unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", + port->port_cfg[0].port_action); + if (address) { + unifi_trace(priv, UDBG5, "addr[0] = %x, addr[1] = %x, addr[2] = %x, addr[3] = %x\n", address[0], address[1], address[2], address[3]); + } + return &port->port_cfg[0]; + } + + unifi_trace(priv, UDBG5, "Multiple port configurations.\n"); + + /* If multiple configurations exist.. */ + for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { + /* .. go through the list and match the destination address. */ + if (port->port_cfg[i].in_use && + memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { + /* Return the desired action. */ + return &port->port_cfg[i]; + } + } + + /* Could not find any information, return Open. */ + unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n"); + return NULL; +} /* uf_sme_port_config_handle */ + +void +uf_multicast_list_wq(struct work_struct *work) +{ + unifi_priv_t *priv = container_of(work, unifi_priv_t, + multicast_list_task); + int i; + CsrUint16 interfaceTag = 0; + CsrWifiMacAddress* multicast_address_list = NULL; + int mc_count; + u8 *mc_list; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n"); + return; + } + + unifi_trace(priv, UDBG5, + "uf_multicast_list_wq: list count = %d\n", + interfacePriv->mc_list_count); + + /* Flush the current list */ + CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL); + + mc_count = interfacePriv->mc_list_count; + mc_list = interfacePriv->mc_list; + /* + * Allocate a new list, need to free it later + * in unifi_mgt_multicast_address_cfm(). + */ + multicast_address_list = CsrPmemAlloc(mc_count * sizeof(CsrWifiMacAddress)); + + if (multicast_address_list == NULL) { + return; + } + + for (i = 0; i < mc_count; i++) { + memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN); + mc_list += ETH_ALEN; + } + + if (priv->smepriv == NULL) { + CsrPmemFree(multicast_address_list); + return; + } + + CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, + interfaceTag, + CSR_WIFI_SME_LIST_ACTION_ADD, + mc_count, multicast_address_list); + + /* The SME will take a copy of the addreses*/ + CsrPmemFree(multicast_address_list); +} + + +int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg) +{ + unifi_cfg_power_t cfg_power; + int rc; + + if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); + return -EFAULT; + } + + switch (cfg_power) { + case UNIFI_CFG_POWER_OFF: + rc = sme_sys_suspend(priv); + if (rc) { + return rc; + } + break; + case UNIFI_CFG_POWER_ON: + rc = sme_sys_resume(priv); + if (rc) { + return rc; + } + break; + default: + unifi_error(priv, "WIFI POWER: Unknown value.\n"); + return -EINVAL; + } + + return 0; +} + + +int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg) +{ + unifi_cfg_powersave_t cfg_power_save; + CsrWifiSmePowerConfig powerConfig; + int rc; + + if (get_user(cfg_power_save, (unifi_cfg_powersave_t*)(((unifi_cfg_command_t*)arg) + 1))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); + return -EFAULT; + } + + /* Get the coex info from the SME */ + rc = sme_mgt_power_config_get(priv, &powerConfig); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n"); + return rc; + } + + switch (cfg_power_save) { + case UNIFI_CFG_POWERSAVE_NONE: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; + break; + case UNIFI_CFG_POWERSAVE_FAST: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED; + break; + case UNIFI_CFG_POWERSAVE_FULL: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; + break; + case UNIFI_CFG_POWERSAVE_AUTO: + powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO; + break; + default: + unifi_error(priv, "POWERSAVE: Unknown value.\n"); + return -EINVAL; + } + + rc = sme_mgt_power_config_set(priv, &powerConfig); + + if (rc) { + unifi_error(priv, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n"); + } + + return rc; +} + + +int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg) +{ + unifi_cfg_powersupply_t cfg_power_supply; + CsrWifiSmeHostConfig hostConfig; + int rc; + + if (get_user(cfg_power_supply, (unifi_cfg_powersupply_t*)(((unifi_cfg_command_t*)arg) + 1))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); + return -EFAULT; + } + + /* Get the coex info from the SME */ + rc = sme_mgt_host_config_get(priv, &hostConfig); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n"); + return rc; + } + + switch (cfg_power_supply) { + case UNIFI_CFG_POWERSUPPLY_MAINS: + hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE; + break; + case UNIFI_CFG_POWERSUPPLY_BATTERIES: + hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE; + break; + default: + unifi_error(priv, "POWERSUPPLY: Unknown value.\n"); + return -EINVAL; + } + + rc = sme_mgt_host_config_set(priv, &hostConfig); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n"); + } + + return rc; +} + + +int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg) +{ + unsigned char *tclas_buffer; + unsigned int tclas_buffer_length; + tclas_t *dhcp_tclas; + int rc; + + /* Free any TCLASs previously allocated */ + if (priv->packet_filters.tclas_ies_length) { + CsrPmemFree(priv->filter_tclas_ies); + priv->filter_tclas_ies = NULL; + } + + tclas_buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int); + if (copy_from_user(&priv->packet_filters, (void*)tclas_buffer, + sizeof(uf_cfg_bcast_packet_filter_t))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the filter struct\n"); + return -EFAULT; + } + + tclas_buffer_length = priv->packet_filters.tclas_ies_length; + + /* Allocate TCLASs if necessary */ + if (priv->packet_filters.dhcp_filter) { + priv->packet_filters.tclas_ies_length += sizeof(tclas_t); + } + if (priv->packet_filters.tclas_ies_length > 0) { + priv->filter_tclas_ies = CsrPmemAlloc(priv->packet_filters.tclas_ies_length); + if (priv->filter_tclas_ies == NULL) { + return -ENOMEM; + } + if (tclas_buffer_length) { + tclas_buffer += sizeof(uf_cfg_bcast_packet_filter_t) - sizeof(unsigned char*); + if (copy_from_user(priv->filter_tclas_ies, + tclas_buffer, + tclas_buffer_length)) { + unifi_error(priv, "UNIFI_CFG: Failed to get the TCLAS buffer\n"); + return -EFAULT; + } + } + } + + if(priv->packet_filters.dhcp_filter) + { + /* Append the DHCP tclas IE */ + dhcp_tclas = (tclas_t*)(priv->filter_tclas_ies + tclas_buffer_length); + memset(dhcp_tclas, 0, sizeof(tclas_t)); + dhcp_tclas->element_id = 14; + dhcp_tclas->length = sizeof(tcpip_clsfr_t) + 1; + dhcp_tclas->user_priority = 0; + dhcp_tclas->tcp_ip_cls_fr.cls_fr_type = 1; + dhcp_tclas->tcp_ip_cls_fr.version = 4; + ((CsrUint8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[0] = 0x00; + ((CsrUint8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[1] = 0x44; + ((CsrUint8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[0] = 0x00; + ((CsrUint8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[1] = 0x43; + dhcp_tclas->tcp_ip_cls_fr.protocol = 0x11; + dhcp_tclas->tcp_ip_cls_fr.cls_fr_mask = 0x58; //bits: 3,4,6 + } + + rc = sme_mgt_packet_filter_set(priv); + + return rc; +} + + +int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg) +{ + CsrUint8 wmm_qos_info; + int rc = 0; + + if (get_user(wmm_qos_info, (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); + return -EFAULT; + } + + /* Store the value in the connection info */ + priv->connection_config.wmmQosInfo = wmm_qos_info; + + return rc; +} + + +int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg) +{ + CsrUint32 addts_tid; + CsrUint8 addts_ie_length; + CsrUint8 *addts_ie; + CsrUint8 *addts_params; + CsrWifiSmeDataBlock tspec; + CsrWifiSmeDataBlock tclas; + int rc; + + addts_params = (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1); + if (get_user(addts_tid, (CsrUint32*)addts_params)) { + unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); + return -EFAULT; + } + + addts_params += sizeof(CsrUint32); + if (get_user(addts_ie_length, (CsrUint8*)addts_params)) { + unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n", + addts_tid, addts_ie_length); + + addts_ie = CsrPmemAlloc(addts_ie_length); + if (addts_ie == NULL) { + unifi_error(priv, + "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n", + addts_ie_length); + return -ENOMEM; + } + + addts_params += sizeof(CsrUint8); + rc = copy_from_user(addts_ie, addts_params, addts_ie_length); + if (rc) { + unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n"); + CsrPmemFree(addts_ie); + return -EFAULT; + } + + tspec.data = addts_ie; + tspec.length = addts_ie_length; + tclas.data = NULL; + tclas.length = 0; + + rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid, + &tspec, &tclas); + + CsrPmemFree(addts_ie); + return rc; +} + + +int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg) +{ + CsrUint32 delts_tid; + CsrUint8 *delts_params; + CsrWifiSmeDataBlock tspec; + CsrWifiSmeDataBlock tclas; + int rc; + + delts_params = (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1); + if (get_user(delts_tid, (CsrUint32*)delts_params)) { + unifi_error(priv, "unifi_cfg_wmm_delts: Failed to get the argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG4, "delts: tid = 0x%x\n", delts_tid); + + tspec.data = tclas.data = NULL; + tspec.length = tclas.length = 0; + + rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_REMOVE, delts_tid, + &tspec, &tclas); + + return rc; +} + +int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg) +{ + CsrBool strict_draft_n; + CsrUint8 *strict_draft_n_params; + int rc; + + CsrWifiSmeStaConfig staConfig; + CsrWifiSmeDeviceConfig deviceConfig; + + strict_draft_n_params = (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1); + if (get_user(strict_draft_n, (CsrBool*)strict_draft_n_params)) { + unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no")); + + rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); + + if (rc) { + unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n"); + return -EFAULT; + } + + deviceConfig.enableStrictDraftN = strict_draft_n; + + rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); + if (rc) { + unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n"); + rc = -EFAULT; + } + + return rc; +} + + +int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg) +{ + CsrBool enable_okc; + CsrUint8 *enable_okc_params; + int rc; + + CsrWifiSmeStaConfig staConfig; + CsrWifiSmeDeviceConfig deviceConfig; + + enable_okc_params = (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1); + if (get_user(enable_okc, (CsrBool*)enable_okc_params)) { + unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n"); + return -EFAULT; + } + + unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no")); + + rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); + if (rc) { + unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n"); + return -EFAULT; + } + + staConfig.enableOpportunisticKeyCaching = enable_okc; + + rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); + if (rc) { + unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n"); + rc = -EFAULT; + } + + return rc; +} + + +int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg) +{ + unifi_cfg_get_t get_cmd; + char inst_name[IFNAMSIZ]; + int rc; + + if (get_user(get_cmd, (unifi_cfg_get_t*)(((unifi_cfg_command_t*)arg) + 1))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); + return -EFAULT; + } + + switch (get_cmd) { + case UNIFI_CFG_GET_COEX: + { + CsrWifiSmeCoexInfo coexInfo; + /* Get the coex info from the SME */ + rc = sme_mgt_coex_info_get(priv, &coexInfo); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n"); + return rc; + } + + /* Copy the info to the out buffer */ + if (copy_to_user((void*)arg, + &coexInfo, + sizeof(CsrWifiSmeCoexInfo))) { + unifi_error(priv, "UNIFI_CFG: Failed to copy the coex info\n"); + return -EFAULT; + } + break; + } + case UNIFI_CFG_GET_POWER_MODE: + { + CsrWifiSmePowerConfig powerConfig; + rc = sme_mgt_power_config_get(priv, &powerConfig); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n"); + return rc; + } + + /* Copy the info to the out buffer */ + if (copy_to_user((void*)arg, + &powerConfig.powerSaveLevel, + sizeof(CsrWifiSmePowerSaveLevel))) { + unifi_error(priv, "UNIFI_CFG: Failed to copy the power save info\n"); + return -EFAULT; + } + break; + } + case UNIFI_CFG_GET_POWER_SUPPLY: + { + CsrWifiSmeHostConfig hostConfig; + rc = sme_mgt_host_config_get(priv, &hostConfig); + if (rc) { + unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n"); + return rc; + } + + /* Copy the info to the out buffer */ + if (copy_to_user((void*)arg, + &hostConfig.powerMode, + sizeof(CsrWifiSmeHostPowerMode))) { + unifi_error(priv, "UNIFI_CFG: Failed to copy the host power mode\n"); + return -EFAULT; + } + break; + } + case UNIFI_CFG_GET_VERSIONS: + break; + case UNIFI_CFG_GET_INSTANCE: + { + CsrUint16 InterfaceId=0; + uf_net_get_name(priv->netdev[InterfaceId], &inst_name[0], sizeof(inst_name)); + + /* Copy the info to the out buffer */ + if (copy_to_user((void*)arg, + &inst_name[0], + sizeof(inst_name))) { + unifi_error(priv, "UNIFI_CFG: Failed to copy the instance name\n"); + return -EFAULT; + } + } + break; + + case UNIFI_CFG_GET_AP_CONFIG: + { +#ifdef CSR_SUPPORT_WEXT_AP + uf_cfg_ap_config_t cfg_ap_config; + cfg_ap_config.channel = priv->ap_config.channel; + cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval; + cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled; + cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod; + cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap; + if (copy_to_user((void*)arg, + &cfg_ap_config, + sizeof(uf_cfg_ap_config_t))) { + unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n"); + return -EFAULT; + } +#else + return -EPERM; +#endif + } + break; + + + default: + unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n"); + return -EINVAL; + } + + return 0; +} +#ifdef CSR_SUPPORT_WEXT_AP +int + uf_configure_supported_rates(CsrUint8 * supportedRates, CsrUint8 phySupportedBitmap) +{ + int i=0; + CsrBool b=FALSE, g = FALSE, n = FALSE; + b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B; + n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N; + g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G; + if(b || g) { + supportedRates[i++]=0x82; + supportedRates[i++]=0x84; + supportedRates[i++]=0x8b; + supportedRates[i++]=0x96; + } else if(n) { + supportedRates[i++]=0x02; + supportedRates[i++]=0x04; + supportedRates[i++]=0x0b; + supportedRates[i++]=0x16; + } + if(g) { + if(!b) { + supportedRates[i++]=0x8c; + supportedRates[i++]=0x98; + supportedRates[i++]=0xb0; + } else { + supportedRates[i++]=0x0c; + supportedRates[i++]=0x18; + supportedRates[i++]=0x30; + } + supportedRates[i++]=0x48; + supportedRates[i++]=0x12; + supportedRates[i++]=0x24; + supportedRates[i++]=0x60; + supportedRates[i++]=0x6c; + } + return i; +} +int unifi_cfg_set_ap_config(unifi_priv_t * priv,unsigned char* arg) +{ + uf_cfg_ap_config_t cfg_ap_config; + char *buffer; + + buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int); + if (copy_from_user(&cfg_ap_config, (void*)buffer, + sizeof(uf_cfg_ap_config_t))) { + unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n"); + return -EFAULT; + } + priv->ap_config.channel = cfg_ap_config.channel; + priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod; + priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval; + priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout; + priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled; + priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout; + priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout; + priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit; + + priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled; + priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType; + + priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled; + + priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc; + priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed; + + priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap; + priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval; + + priv->ap_mac_config.supportedRatesCount= uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap); + + return 0; +} + +#endif +#ifdef CSR_SUPPORT_WEXT + + void +uf_sme_config_wq(struct work_struct *work) +{ + CsrWifiSmeStaConfig staConfig; + CsrWifiSmeDeviceConfig deviceConfig; + unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task); + + /* Register to receive indications from the SME */ + CsrWifiSmeEventMaskSetReqSend(0, + CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY | + CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE); + + if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) { + unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n"); + return; + } + + if (priv->if_index == CSR_INDEX_5G) { + staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0; + } else { + staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4; + } + + deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d; + if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) { + unifi_warning(priv, + "SME config for 802.11d Trust Level and Radio Band failed.\n"); + return; + } + +} /* uf_sme_config_wq() */ + +#endif /* CSR_SUPPORT_WEXT */ + + +/* + * --------------------------------------------------------------------------- + * uf_ta_ind_wq + * + * Deferred work queue function to send Traffic Analysis protocols + * indications to the SME. + * These are done in a deferred work queue for two reasons: + * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context + * - we want to load the main driver data path as lightly as possible + * + * The TA classifications already come from a workqueue. + * + * Arguments: + * work Pointer to work queue item. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ + void +uf_ta_ind_wq(struct work_struct *work) +{ + struct ta_ind *ind = container_of(work, struct ta_ind, task); + unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work); + CsrUint16 interfaceTag = 0; + + + CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, + interfaceTag, + ind->packet_type, + ind->direction, + ind->src_addr); + ind->in_use = 0; + +} /* uf_ta_ind_wq() */ + + +/* + * --------------------------------------------------------------------------- + * uf_ta_sample_ind_wq + * + * Deferred work queue function to send Traffic Analysis sample + * indications to the SME. + * These are done in a deferred work queue for two reasons: + * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context + * - we want to load the main driver data path as lightly as possible + * + * The TA classifications already come from a workqueue. + * + * Arguments: + * work Pointer to work queue item. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ + void +uf_ta_sample_ind_wq(struct work_struct *work) +{ + struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task); + unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work); + CsrUint16 interfaceTag = 0; + + unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n", + priv->rxTcpThroughput, + priv->txTcpThroughput, + priv->rxUdpThroughput, + priv->txUdpThroughput, + priv->bh_thread.prio); + + if(priv->rxTcpThroughput > 1000) + { + if (bh_priority == -1 && priv->bh_thread.prio != 1) + { + struct sched_param param; + priv->bh_thread.prio = 1; + unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n", + priv->bh_thread.name, priv->bh_thread.prio); + param.sched_priority = priv->bh_thread.prio; + sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, ¶m); + } + } else + { + if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO) + { + struct sched_param param; + param.sched_priority = 0; + sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, ¶m); + priv->bh_thread.prio = DEFAULT_PRIO; + unifi_trace(priv, UDBG1, "%s new thread priority = %d\n", + priv->bh_thread.name, priv->bh_thread.prio); + set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio)); + } + } + + CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, ind->stats); + + ind->in_use = 0; + +} /* uf_ta_sample_ind_wq() */ + + +/* + * --------------------------------------------------------------------------- + * uf_send_m4_ready_wq + * + * Deferred work queue function to send M4 ReadyToSend inds to the SME. + * These are done in a deferred work queue for two reasons: + * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context + * - we want to load the main driver data path as lightly as possible + * + * Arguments: + * work Pointer to work queue item. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +uf_send_m4_ready_wq(struct work_struct *work) +{ + netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task); + CsrUint16 iface = InterfacePriv->InterfaceTag; + unifi_priv_t *priv = InterfacePriv->privPtr; + CSR_MA_PACKET_REQUEST *req = &InterfacePriv->m4_signal.u.MaPacketRequest; + CsrWifiMacAddress peer; + unsigned long flags; + + func_enter(); + + /* The peer address was stored in the signal */ + spin_lock_irqsave(&priv->m4_lock, flags); + memcpy(peer.a, req->Ra.x, sizeof(peer.a)); + spin_unlock_irqrestore(&priv->m4_lock, flags); + + /* Send a signal to SME */ + CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer); + + UF_TRACE_MAC(priv, UDBG1, "M4ReadyToSendInd sent for peer", peer.a); + + func_exit(); + +} /* uf_send_m4_ready_wq() */ + diff --git a/drivers/staging/csr/unifi_sme.h b/drivers/staging/csr/unifi_sme.h new file mode 100644 index 000000000000..51ca92e89055 --- /dev/null +++ b/drivers/staging/csr/unifi_sme.h @@ -0,0 +1,236 @@ +/* + * *************************************************************************** + * FILE: unifi_sme.h + * + * PURPOSE: SME related definitions. + * + * Copyright (C) 2007-2011 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * *************************************************************************** + */ +#ifndef __LINUX_UNIFI_SME_H__ +#define __LINUX_UNIFI_SME_H__ 1 + +#include + +#ifdef CSR_SME_USERSPACE +#include "sme_userspace.h" +#endif + +#include "csr_wifi_sme_lib.h" + +typedef int unifi_data_port_action; + +typedef struct unifi_port_cfg +{ + /* TRUE if this port entry is allocated */ + CsrBool in_use; + CsrWifiRouterCtrlPortAction port_action; + CsrWifiMacAddress mac_address; +} unifi_port_cfg_t; + +#define UNIFI_MAX_CONNECTIONS 8 +#define UNIFI_MAX_RETRY_LIMIT 5 +#define UF_DATA_PORT_NOT_OVERIDE 0 +#define UF_DATA_PORT_OVERIDE 1 + +typedef struct unifi_port_config +{ + int entries_in_use; + int overide_action; + unifi_port_cfg_t port_cfg[UNIFI_MAX_CONNECTIONS]; +} unifi_port_config_t; + + +enum sme_request_status { + SME_REQUEST_EMPTY, + SME_REQUEST_PENDING, + SME_REQUEST_RECEIVED, + SME_REQUEST_TIMEDOUT, +}; + +/* Structure to hold a UDI logged signal */ +typedef struct { + + /* The current status of the request */ + enum sme_request_status request_status; + + /* The status the SME has passed to us */ + CsrResult reply_status; + + /* SME's reply to a get request */ + CsrWifiSmeVersions versions; + CsrWifiSmePowerConfig powerConfig; + CsrWifiSmeHostConfig hostConfig; + CsrWifiSmeStaConfig staConfig; + CsrWifiSmeDeviceConfig deviceConfig; + CsrWifiSmeCoexInfo coexInfo; + CsrWifiSmeCoexConfig coexConfig; + CsrWifiSmeMibConfig mibConfig; + CsrWifiSmeConnectionInfo connectionInfo; + CsrWifiSmeConnectionConfig connectionConfig; + CsrWifiSmeConnectionStats connectionStats; + + + /* SME's reply to a scan request */ + CsrUint16 reply_scan_results_count; + CsrWifiSmeScanResult* reply_scan_results; + +} sme_reply_t; + + +typedef struct { + CsrUint16 appHandle; + CsrWifiRouterEncapsulation encapsulation; + CsrUint16 protocol; + CsrUint8 oui[3]; + CsrUint8 in_use; +} sme_ma_unidata_ind_filter_t; + + +CsrWifiRouterCtrlPortAction uf_sme_port_state(unifi_priv_t *priv, + unsigned char *address, + int queue, + CsrUint16 interfaceTag); +unifi_port_cfg_t *uf_sme_port_config_handle(unifi_priv_t *priv, + unsigned char *address, + int queue, + CsrUint16 interfaceTag); + + + +/* Callback for event logging to SME clients */ +void sme_log_event(ul_client_t *client, const u8 *signal, int signal_len, + const bulk_data_param_t *bulkdata, int dir); + +/* The workqueue task to the set the multicast addresses list */ +void uf_multicast_list_wq(struct work_struct *work); + +/* The workqueue task to execute the TA module */ +void uf_ta_wq(struct work_struct *work); + + +/* + * SME blocking helper functions + */ +#ifdef UNIFI_DEBUG +# define sme_complete_request(priv, status) uf_sme_complete_request(priv, status, __func__) +#else +# define sme_complete_request(priv, status) uf_sme_complete_request(priv, status, NULL) +#endif + +void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func); + + +/* + * Blocking functions using the SME SYS API. + */ +int sme_sys_suspend(unifi_priv_t *priv); +int sme_sys_resume(unifi_priv_t *priv); + + +/* + * Traffic Analysis workqueue jobs + */ +void uf_ta_ind_wq(struct work_struct *work); +void uf_ta_sample_ind_wq(struct work_struct *work); + +/* + * SME config workqueue job + */ +void uf_sme_config_wq(struct work_struct *work); + +/* + * To send M4 read to send IND + */ +void uf_send_m4_ready_wq(struct work_struct *work); + +int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); +int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); +int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig); +int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig); +int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig); +int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig); +int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo); +int sme_mgt_packet_filter_set(unifi_priv_t *priv); +int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action, + CsrUint32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas); + +#ifdef CSR_SUPPORT_WEXT +/* + * Blocking functions using the SME MGT API. + */ +int sme_mgt_wifi_on(unifi_priv_t *priv); +int sme_mgt_wifi_off(unifi_priv_t *priv); +/*int sme_mgt_set_value_async(unifi_priv_t *priv, unifi_AppValue *app_value); +int sme_mgt_get_value_async(unifi_priv_t *priv, unifi_AppValue *app_value); +int sme_mgt_get_value(unifi_priv_t *priv, unifi_AppValue *app_value); +int sme_mgt_set_value(unifi_priv_t *priv, unifi_AppValue *app_value); +*/ +int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig); +int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig); +int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig); +int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig); + +int sme_mgt_connection_info_set(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo); +int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo); +int sme_mgt_connection_config_set(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig); +int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig); +int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats); + +int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions); + + +int sme_mgt_scan_full(unifi_priv_t *priv, CsrWifiSsid *specific_ssid, + int num_channels, unsigned char *channel_list); +int sme_mgt_scan_results_get_async(unifi_priv_t *priv, + struct iw_request_info *info, + char *scan_results, + long scan_results_len); +int sme_mgt_disconnect(unifi_priv_t *priv); +int sme_mgt_connect(unifi_priv_t *priv); +int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key, + CsrWifiSmeListAction action); +int sme_mgt_pmkid(unifi_priv_t *priv, CsrWifiSmeListAction action, + CsrWifiSmePmkidList *pmkid_list); +int sme_mgt_mib_get(unifi_priv_t *priv, + unsigned char *varbind, int *length); +int sme_mgt_mib_set(unifi_priv_t *priv, + unsigned char *varbind, int length); +#ifdef CSR_SUPPORT_WEXT_AP +int sme_ap_start(unifi_priv_t *priv,CsrUint16 interface_tag,CsrWifiSmeApConfig_t *ap_config); +int sme_ap_stop(unifi_priv_t *priv,CsrUint16 interface_tag); +int sme_ap_config(unifi_priv_t *priv,CsrWifiSmeApMacConfig *ap_mac_config, CsrWifiNmeApConfig *group_security_config); +int uf_configure_supported_rates(CsrUint8 * supportedRates, CsrUint8 phySupportedBitmap); +#endif +int unifi_translate_scan(struct net_device *dev, + struct iw_request_info *info, + char *current_ev, char *end_buf, + CsrWifiSmeScanResult *scan_data, + int scan_index); + +#endif /* CSR_SUPPORT_WEXT */ + +int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg); +int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg); +#ifdef CSR_SUPPORT_WEXT_AP +int unifi_cfg_set_ap_config(unifi_priv_t * priv,unsigned char* arg); +#endif + + + +int convert_sme_error(CsrResult error); + + +#endif /* __LINUX_UNIFI_SME_H__ */ diff --git a/drivers/staging/csr/unifi_wext.h b/drivers/staging/csr/unifi_wext.h new file mode 100644 index 000000000000..ac86df92d955 --- /dev/null +++ b/drivers/staging/csr/unifi_wext.h @@ -0,0 +1,124 @@ +/* + ***************************************************************************** + * + * FILE : unifi_wext.h + * + * PURPOSE : Private header file for unifi driver support to wireless extensions. + * + * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * +***************************************************************************** + */ +#ifndef __LINUX_UNIFI_WEXT_H__ +#define __LINUX_UNIFI_WEXT_H__ 1 + +#include +#include +#include "csr_wifi_sme_prim.h" + +/* + * wext.c + */ +/* A few details needed for WEP (Wireless Equivalent Privacy) */ +#define UNIFI_MAX_KEY_SIZE 16 +#define NUM_WEPKEYS 4 +#define SMALL_KEY_SIZE 5 +#define LARGE_KEY_SIZE 13 +typedef struct wep_key_t { + int len; + unsigned char key[UNIFI_MAX_KEY_SIZE]; /* 40-bit and 104-bit keys */ +} wep_key_t; + +#define UNIFI_SCAN_ACTIVE 0 +#define UNIFI_SCAN_PASSIVE 1 +#define UNIFI_MAX_SSID_LEN 32 + +#define MAX_WPA_IE_LEN 64 +#define MAX_RSN_IE_LEN 255 + +/* + * Function to register in the netdev to report wireless stats. + */ +struct iw_statistics *unifi_get_wireless_stats(struct net_device *dev); + +void uf_sme_wext_set_defaults(unifi_priv_t *priv); + + +/* + * wext_events.c + */ +/* Functions to generate Wireless Extension events */ +void wext_send_scan_results_event(unifi_priv_t *priv); +void wext_send_assoc_event(unifi_priv_t *priv, unsigned char *bssid, + unsigned char *req_ie, int req_ie_len, + unsigned char *resp_ie, int resp_ie_len, + unsigned char *scan_ie, unsigned int scan_ie_len); +void wext_send_disassoc_event(unifi_priv_t *priv); +void wext_send_michaelmicfailure_event(unifi_priv_t *priv, + CsrUint16 count, CsrWifiMacAddress address, + CsrWifiSmeKeyType keyType, CsrUint16 interfaceTag); +void wext_send_pmkid_candidate_event(unifi_priv_t *priv, CsrWifiMacAddress bssid, CsrBool preauth_allowed, CsrUint16 interfaceTag); +void wext_send_started_event(unifi_priv_t *priv); + + +static inline int +uf_iwe_stream_add_point(struct iw_request_info *info, char *start, char *stop, + struct iw_event *piwe, char *extra) +{ + char *new_start; + + new_start = iwe_stream_add_point( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined (IW_REQUEST_FLAG_COMPAT) + info, +#endif + start, stop, piwe, extra); + if (unlikely(new_start == start)) + { + return -E2BIG; + } + + return (new_start - start); +} + + +static inline int +uf_iwe_stream_add_event(struct iw_request_info *info, char *start, char *stop, + struct iw_event *piwe, int len) +{ + char *new_start; + + new_start = iwe_stream_add_event( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined(IW_REQUEST_FLAG_COMPAT) + info, +#endif + start, stop, piwe, len); + if (unlikely(new_start == start)) { + return -E2BIG; + } + + return (new_start - start); +} + +static inline int +uf_iwe_stream_add_value(struct iw_request_info *info, char *stream, char *start, + char *stop, struct iw_event *piwe, int len) +{ + char *new_start; + + new_start = iwe_stream_add_value( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined(IW_REQUEST_FLAG_COMPAT) + info, +#endif + stream, start, stop, piwe, len); + if (unlikely(new_start == start)) { + return -E2BIG; + } + + return (new_start - start); +} + + +#endif /* __LINUX_UNIFI_WEXT_H__ */ diff --git a/drivers/staging/csr/unifiio.h b/drivers/staging/csr/unifiio.h new file mode 100644 index 000000000000..e707eedef29d --- /dev/null +++ b/drivers/staging/csr/unifiio.h @@ -0,0 +1,400 @@ +/* + * --------------------------------------------------------------------------- + * + * FILE: unifiio.h + * + * Public definitions for the UniFi linux driver. + * This is mostly ioctl command values and structs. + * + * Include or similar before this file + * + * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#ifndef __UNIFIIO_H__ +#define __UNIFIIO_H__ + +#include +#include "csr_types.h" + +#define UNIFI_GET_UDI_ENABLE _IOR('u', 1, int) +#define UNIFI_SET_UDI_ENABLE _IOW('u', 2, int) +/* Values for UDI_ENABLE */ +#define UDI_ENABLE_DATA 0x1 +#define UDI_ENABLE_CONTROL 0x2 + +/* MIB set/get. Arg is a pointer to a varbind */ +#define UNIFI_GET_MIB _IOWR('u', 3, unsigned char *) +#define UNIFI_SET_MIB _IOW ('u', 4, unsigned char *) +#define MAX_VARBIND_LENGTH 127 + +/* Private IOCTLs */ +#define SIOCIWS80211POWERSAVEPRIV SIOCIWFIRSTPRIV +#define SIOCIWG80211POWERSAVEPRIV SIOCIWFIRSTPRIV + 1 +#define SIOCIWS80211RELOADDEFAULTSPRIV SIOCIWFIRSTPRIV + 2 +#define SIOCIWSCONFWAPIPRIV SIOCIWFIRSTPRIV + 4 +#define SIOCIWSWAPIKEYPRIV SIOCIWFIRSTPRIV + 6 +#define SIOCIWSSMEDEBUGPRIV SIOCIWFIRSTPRIV + 8 +#define SIOCIWSAPCFGPRIV SIOCIWFIRSTPRIV + 10 +#define SIOCIWSAPSTARTPRIV SIOCIWFIRSTPRIV + 12 +#define SIOCIWSAPSTOPPRIV SIOCIWFIRSTPRIV + 14 +#define SIOCIWSFWRELOADPRIV SIOCIWFIRSTPRIV + 16 +#define SIOCIWSSTACKSTART SIOCIWFIRSTPRIV + 18 +#define SIOCIWSSTACKSTOP SIOCIWFIRSTPRIV + 20 + + + +#define IWPRIV_POWER_SAVE_MAX_STRING 32 +#define IWPRIV_SME_DEBUG_MAX_STRING 32 +#define IWPRIV_SME_MAX_STRING 120 + + +/* Private configuration commands */ +#define UNIFI_CFG _IOWR('u', 5, unsigned char *) +/* + * <------------------ Read/Write Buffer --------------------> + * _____________________________________________________________ + * | Cmd | Arg | ... Buffer (opt) ... | + * ------------------------------------------------------------- + * <-- uint --><-- uint --><----- unsigned char buffer ------> + * + * Cmd: A unifi_cfg_command_t command. + * Arg: Out:Length if Cmd==UNIFI_CFG_GET + * In:PowerOnOff if Cmd==UNIFI_CFG_POWER + * In:PowerMode if Cmd==UNIFI_CFG_POWERSAVE + * In:Length if Cmd==UNIFI_CFG_FILTER + * In:WMM Qos Info if Cmd==UNIFI_CFG_WMM_QOS_INFO + * Buffer: Out:Data if Cmd==UNIFI_CFG_GET + * NULL if Cmd==UNIFI_CFG_POWER + * NULL if Cmd==UNIFI_CFG_POWERSAVE + * In:Filters if Cmd==UNIFI_CFG_FILTER + * + * where Filters is a uf_cfg_bcast_packet_filter_t structure + * followed by 0 - n tclas_t structures. The length of the tclas_t + * structures is obtained by uf_cfg_bcast_packet_filter_t::tclas_ies_length. + */ + + +#define UNIFI_PUTEST _IOWR('u', 6, unsigned char *) +/* + * <------------------ Read/Write Buffer --------------------> + * _____________________________________________________________ + * | Cmd | Arg | ... Buffer (opt) ... | + * ------------------------------------------------------------- + * <-- uint --><-- uint --><----- unsigned char buffer ------> + * + * Cmd: A unifi_putest_command_t command. + * Arg: N/A if Cmd==UNIFI_PUTEST_START + * N/A if Cmd==UNIFI_PUTEST_STOP + * In:int (Clock Speed) if Cmd==UNIFI_PUTEST_SET_SDIO_CLOCK + * In/Out:sizeof(unifi_putest_cmd52) if Cmd==UNIFI_PUTEST_CMD52_READ + * In:sizeof(unifi_putest_cmd52) if Cmd==UNIFI_PUTEST_CMD52_WRITE + * In:uint (f/w file name length) if Cmd==UNIFI_PUTEST_DL_FW + * Buffer: NULL if Cmd==UNIFI_PUTEST_START + * NULL if Cmd==UNIFI_PUTEST_STOP + * NULL if Cmd==UNIFI_PUTEST_SET_SDIO_CLOCK + * In/Out:unifi_putest_cmd52 if Cmd==UNIFI_PUTEST_CMD52_READ + * In:unifi_putest_cmd52 if Cmd==UNIFI_PUTEST_CMD52_WRITE + * In:f/w file name if Cmd==UNIFI_PUTEST_DL_FW + */ + +#define UNIFI_BUILD_TYPE _IOWR('u', 7, unsigned char) +#define UNIFI_BUILD_NME 1 +#define UNIFI_BUILD_WEXT 2 +#define UNIFI_BUILD_AP 3 + +/* debugging */ +#define UNIFI_KICK _IO ('u', 0x10) +#define UNIFI_SET_DEBUG _IO ('u', 0x11) +#define UNIFI_SET_TRACE _IO ('u', 0x12) + +#define UNIFI_GET_INIT_STATUS _IOR ('u', 0x15, int) +#define UNIFI_SET_UDI_LOG_MASK _IOR('u', 0x18, unifiio_filter_t) +#define UNIFI_SET_UDI_SNAP_MASK _IOW('u', 0x1a, unifiio_snap_filter_t) +#define UNIFI_SET_AMP_ENABLE _IOWR('u', 0x1b, int) + +#define UNIFI_INIT_HW _IOR ('u', 0x13, unsigned char) +#define UNIFI_INIT_NETDEV _IOW ('u', 0x14, unsigned char[6]) +#define UNIFI_SME_PRESENT _IOW ('u', 0x19, int) + +#define UNIFI_CFG_PERIOD_TRAFFIC _IOW ('u', 0x21, unsigned char *) +#define UNIFI_CFG_UAPSD_TRAFFIC _IOW ('u', 0x22, unsigned char) + +#define UNIFI_COREDUMP_GET_REG _IOWR('u', 0x23, unifiio_coredump_req_t) + + +/* + * Following reset, f/w may only be downloaded using CMD52. + * This is slow, so there is a facility to download a secondary + * loader first which supports CMD53. + * If loader_len is > 0, then loader_data is assumed to point to + * a suitable secondary loader that can be used to download the + * main image. + * + * The driver will run the host protocol initialisation sequence + * after downloading the image. + * + * If both lengths are zero, then the f/w is assumed to have been + * booted from Flash and the host protocol initialisation sequence + * is run. + */ +typedef struct { + + /* Number of bytes in the image */ + int img_len; + + /* Pointer to image data. */ + unsigned char *img_data; + + + /* Number of bytes in the loader image */ + int loader_len; + + /* Pointer to loader image data. */ + unsigned char *loader_data; + +} unifiio_img_t; + + +/* Structure of data read from the unifi device. */ +typedef struct +{ + /* Length (in bytes) of entire structure including appended bulk data */ + int length; + + /* System time (in milliseconds) that signal was transferred */ + int timestamp; + + /* Direction in which signal was transferred. */ + int direction; +#define UDI_FROM_HOST 0 +#define UDI_TO_HOST 1 +#define UDI_CONFIG_IND 2 + + /* The length of the signal (in bytes) not including bulk data */ + int signal_length; + + /* Signal body follows, then any bulk data */ + +} udi_msg_t; + + +typedef enum +{ + UfSigFil_AllOn = 0, /* Log all signal IDs */ + UfSigFil_AllOff = 1, /* Don't log any signal IDs */ + UfSigFil_SelectOn = 2, /* Log these signal IDs */ + UfSigFil_SelectOff = 3 /* Don't log these signal IDs */ +} uf_sigfilter_action_t; + +typedef struct { + + /* Number of 16-bit ints in the sig_ids array */ + int num_sig_ids; + /* The action to perform */ + uf_sigfilter_action_t action; + /* List of signal IDs to pass or block */ + unsigned short *sig_ids; + +} unifiio_filter_t; + + +typedef struct { + /* Number of 16-bit ints in the protocols array */ + CsrUint16 count; + /* List of protocol ids to pass */ + CsrUint16 *protocols; +} unifiio_snap_filter_t; + + + +typedef enum unifi_putest_command { + UNIFI_PUTEST_START, + UNIFI_PUTEST_STOP, + UNIFI_PUTEST_SET_SDIO_CLOCK, + UNIFI_PUTEST_CMD52_READ, + UNIFI_PUTEST_CMD52_WRITE, + UNIFI_PUTEST_DL_FW, + UNIFI_PUTEST_DL_FW_BUFF, + UNIFI_PUTEST_CMD52_BLOCK_READ, + UNIFI_PUTEST_COREDUMP_PREPARE, + UNIFI_PUTEST_GP_READ16, + UNIFI_PUTEST_GP_WRITE16 + +} unifi_putest_command_t; + + +struct unifi_putest_cmd52 { + int funcnum; + unsigned long addr; + unsigned char data; +}; + + +struct unifi_putest_block_cmd52_r { + int funcnum; + unsigned long addr; + unsigned int length; + unsigned char *data; +}; + +struct unifi_putest_gp_rw16 { + unsigned long addr; /* generic address */ + unsigned short data; +}; + +typedef enum unifi_cfg_command { + UNIFI_CFG_GET, + UNIFI_CFG_POWER, + UNIFI_CFG_POWERSAVE, + UNIFI_CFG_FILTER, + UNIFI_CFG_POWERSUPPLY, + UNIFI_CFG_WMM_QOSINFO, + UNIFI_CFG_WMM_ADDTS, + UNIFI_CFG_WMM_DELTS, + UNIFI_CFG_STRICT_DRAFT_N, + UNIFI_CFG_ENABLE_OKC, + UNIFI_CFG_SET_AP_CONFIG, + UNIFI_CFG_CORE_DUMP /* request to take a fw core dump */ +} unifi_cfg_command_t; + +typedef enum unifi_cfg_power { + UNIFI_CFG_POWER_UNSPECIFIED, + UNIFI_CFG_POWER_OFF, + UNIFI_CFG_POWER_ON +} unifi_cfg_power_t; + +typedef enum unifi_cfg_powersupply { + UNIFI_CFG_POWERSUPPLY_UNSPECIFIED, + UNIFI_CFG_POWERSUPPLY_MAINS, + UNIFI_CFG_POWERSUPPLY_BATTERIES +} unifi_cfg_powersupply_t; + +typedef enum unifi_cfg_powersave { + UNIFI_CFG_POWERSAVE_UNSPECIFIED, + UNIFI_CFG_POWERSAVE_NONE, + UNIFI_CFG_POWERSAVE_FAST, + UNIFI_CFG_POWERSAVE_FULL, + UNIFI_CFG_POWERSAVE_AUTO +} unifi_cfg_powersave_t; + +typedef enum unifi_cfg_get { + UNIFI_CFG_GET_COEX, + UNIFI_CFG_GET_POWER_MODE, + UNIFI_CFG_GET_VERSIONS, + UNIFI_CFG_GET_POWER_SUPPLY, + UNIFI_CFG_GET_INSTANCE, + UNIFI_CFG_GET_AP_CONFIG +} unifi_cfg_get_t; + +#define UNIFI_CFG_FILTER_NONE 0x0000 +#define UNIFI_CFG_FILTER_DHCP 0x0001 +#define UNIFI_CFG_FILTER_ARP 0x0002 +#define UNIFI_CFG_FILTER_NBNS 0x0004 +#define UNIFI_CFG_FILTER_NBDS 0x0008 +#define UNIFI_CFG_FILTER_CUPS 0x0010 +#define UNIFI_CFG_FILTER_ALL 0xFFFF + + +typedef struct uf_cfg_bcast_packet_filter +{ + unsigned long filter_mode; //as defined by HIP protocol + unsigned char arp_filter; + unsigned char dhcp_filter; + unsigned long tclas_ies_length; // length of tclas_ies in bytes + unsigned char tclas_ies[1]; // variable length depending on above field +} uf_cfg_bcast_packet_filter_t; + +typedef struct uf_cfg_ap_config +{ + CsrUint8 phySupportedBitmap; + CsrUint8 channel; + CsrUint16 beaconInterval; + CsrUint8 dtimPeriod; + CsrBool wmmEnabled; + CsrUint8 shortSlotTimeEnabled; + CsrUint16 groupkeyTimeout; + CsrBool strictGtkRekeyEnabled; + CsrUint16 gmkTimeout; + CsrUint16 responseTimeout; + CsrUint8 retransLimit; + CsrUint8 rxStbc; + CsrBool rifsModeAllowed; + CsrUint8 dualCtsProtection; + CsrUint8 ctsProtectionType; + CsrUint16 maxListenInterval; +}uf_cfg_ap_config_t; + +typedef struct tcpic_clsfr +{ + __u8 cls_fr_type; + __u8 cls_fr_mask; + __u8 version; + __u8 source_ip_addr[4]; + __u8 dest_ip_addr[4]; + __u16 source_port; + __u16 dest_port; + __u8 dscp; + __u8 protocol; + __u8 reserved; +} __attribute__ ((packed)) tcpip_clsfr_t; + +typedef struct tclas { + __u8 element_id; + __u8 length; + __u8 user_priority; + tcpip_clsfr_t tcp_ip_cls_fr; +} __attribute__ ((packed)) tclas_t; + + +#define CONFIG_IND_ERROR 0x01 +#define CONFIG_IND_EXIT 0x02 +#define CONFIG_SME_NOT_PRESENT 0x10 +#define CONFIG_SME_PRESENT 0x20 + +/* WAPI Key */ +typedef struct +{ + CsrUint8 unicastKey; + /* If non zero, then unicast key otherwise group key */ + CsrUint8 keyIndex; + CsrUint8 keyRsc[16]; + CsrUint8 authenticator; + /* If non zero, then authenticator otherwise supplicant */ + CsrUint8 address[6]; + CsrUint8 key[32]; +} unifiio_wapi_key_t; + +/* Values describing XAP memory regions captured by the mini-coredump system */ +typedef enum unifiio_coredump_space { + UNIFIIO_COREDUMP_MAC_REG, + UNIFIIO_COREDUMP_PHY_REG, + UNIFIIO_COREDUMP_SH_DMEM, + UNIFIIO_COREDUMP_MAC_DMEM, + UNIFIIO_COREDUMP_PHY_DMEM, + UNIFIIO_COREDUMP_TRIGGER_MAGIC = 0xFEED +} unifiio_coredump_space_t; + +/* Userspace tool uses this structure to retrieve a register value from a + * mini-coredump buffer previously saved by the HIP + */ +typedef struct unifiio_coredump_req { + /* From user */ + int index; /* 0=newest, -1=oldest */ + unsigned int offset; /* register offset in space */ + unifiio_coredump_space_t space; /* memory space */ + /* Filled by driver */ + unsigned int drv_build; /* driver build id */ + unsigned int chip_ver; /* chip version */ + unsigned int fw_ver; /* firmware version */ + int requestor; /* requestor: 0=auto dump, 1=manual */ + unsigned int timestamp; /* time of capture by driver */ + unsigned int serial; /* capture serial number */ + int value; /* 16 bit register value, -ve for error */ +} unifiio_coredump_req_t; /* Core-dumped register value request */ + +#endif /* __UNIFIIO_H__ */ diff --git a/drivers/staging/csr/wext_events.c b/drivers/staging/csr/wext_events.c new file mode 100644 index 000000000000..5674782b19a7 --- /dev/null +++ b/drivers/staging/csr/wext_events.c @@ -0,0 +1,285 @@ +/* + * --------------------------------------------------------------------------- + * FILE: wext_events.c + * + * PURPOSE: + * Code to generate iwevents. + * + * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + + +/* + * --------------------------------------------------------------------------- + * wext_send_assoc_event + * + * Send wireless-extension events up to userland to announce + * successful association with an AP. + * + * Arguments: + * priv Pointer to driver context. + * bssid MAC address of AP we associated with + * req_ie, req_ie_len IEs in the original request + * resp_ie, resp_ie_len IEs in the response + * + * Returns: + * None. + * + * Notes: + * This is sent on first successful association, and again if we + * roam to another AP. + * --------------------------------------------------------------------------- + */ +void +wext_send_assoc_event(unifi_priv_t *priv, unsigned char *bssid, + unsigned char *req_ie, int req_ie_len, + unsigned char *resp_ie, int resp_ie_len, + unsigned char *scan_ie, unsigned int scan_ie_len) +{ +#if WIRELESS_EXT > 17 + union iwreq_data wrqu; + + if (req_ie_len == 0) req_ie = NULL; + wrqu.data.length = req_ie_len; + wrqu.data.flags = 0; + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCREQIE, &wrqu, req_ie); + + if (resp_ie_len == 0) resp_ie = NULL; + wrqu.data.length = resp_ie_len; + wrqu.data.flags = 0; + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCRESPIE, &wrqu, resp_ie); + + if (scan_ie_len > 0) { + wrqu.data.length = scan_ie_len; + wrqu.data.flags = 0; + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVGENIE, &wrqu, scan_ie); + } + + memcpy(&wrqu.ap_addr.sa_data, bssid, ETH_ALEN); + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL); +#endif +} /* wext_send_assoc_event() */ + + + +/* + * --------------------------------------------------------------------------- + * wext_send_disassoc_event + * + * Send a wireless-extension event up to userland to announce + * that we disassociated from an AP. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * None. + * + * Notes: + * The semantics of wpa_supplicant (the userland SME application) are + * that a SIOCGIWAP event with MAC address of all zero means + * disassociate. + * --------------------------------------------------------------------------- + */ +void +wext_send_disassoc_event(unifi_priv_t *priv) +{ +#if WIRELESS_EXT > 17 + union iwreq_data wrqu; + + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL); +#endif +} /* wext_send_disassoc_event() */ + + + +/* + * --------------------------------------------------------------------------- + * wext_send_scan_results_event + * + * Send wireless-extension events up to userland to announce + * completion of a scan. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * None. + * + * Notes: + * This doesn't actually report the results, they are retrieved + * using the SIOCGIWSCAN ioctl command. + * --------------------------------------------------------------------------- + */ +void +wext_send_scan_results_event(unifi_priv_t *priv) +{ +#if WIRELESS_EXT > 17 + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWSCAN, &wrqu, NULL); + +#endif +} /* wext_send_scan_results_event() */ + + + +/* + * --------------------------------------------------------------------------- + * wext_send_michaelmicfailure_event + * + * Send wireless-extension events up to userland to announce + * completion of a scan. + * + * Arguments: + * priv Pointer to driver context. + * count, macaddr, key_type, key_idx, tsc + * Parameters from report from UniFi. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +#if WIRELESS_EXT >= 18 +static inline void +_send_michaelmicfailure_event(struct net_device *dev, + int count, const unsigned char *macaddr, + int key_type, int key_idx, + unsigned char *tsc) +{ + union iwreq_data wrqu; + struct iw_michaelmicfailure mmf; + + memset(&mmf, 0, sizeof(mmf)); + + mmf.flags = key_idx & IW_MICFAILURE_KEY_ID; + if (key_type == CSR_GROUP) { + mmf.flags |= IW_MICFAILURE_GROUP; + } else { + mmf.flags |= IW_MICFAILURE_PAIRWISE; + } + mmf.flags |= ((count << 5) & IW_MICFAILURE_COUNT); + + mmf.src_addr.sa_family = ARPHRD_ETHER; + memcpy(mmf.src_addr.sa_data, macaddr, ETH_ALEN); + + memcpy(mmf.tsc, tsc, IW_ENCODE_SEQ_MAX_SIZE); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(mmf); + + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&mmf); +} +#elif WIRELESS_EXT >= 15 +static inline void +_send_michaelmicfailure_event(struct net_device *dev, + int count, const unsigned char *macaddr, + int key_type, int key_idx, + unsigned char *tsc) +{ + union iwreq_data wrqu; + char buf[128]; + + sprintf(buf, + "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%02x:%02x:%02x:%02x:%02x:%02x)", + key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); +} +#else /* WIRELESS_EXT >= 15 */ +static inline void +_send_michaelmicfailure_event(struct net_device *dev, + int count, const unsigned char *macaddr, + int key_type, int key_idx, + unsigned char *tsc) +{ + /* Not supported before WEXT 15 */ +} +#endif /* WIRELESS_EXT >= 15 */ + + +void +wext_send_michaelmicfailure_event(unifi_priv_t *priv, + CsrUint16 count, + CsrWifiMacAddress address, + CsrWifiSmeKeyType keyType, + CsrUint16 interfaceTag) +{ + unsigned char tsc[8] = {0}; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "wext_send_michaelmicfailure_event bad interfaceTag\n"); + return; + } + + _send_michaelmicfailure_event(priv->netdev[interfaceTag], + count, + address.a, + keyType, + 0, + tsc); +} /* wext_send_michaelmicfailure_event() */ + +void +wext_send_pmkid_candidate_event(unifi_priv_t *priv, CsrWifiMacAddress bssid, CsrBool preauth_allowed, CsrUint16 interfaceTag) +{ +#if WIRELESS_EXT > 17 + union iwreq_data wrqu; + struct iw_pmkid_cand pmkid_cand; + + if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { + unifi_error(priv, "wext_send_pmkid_candidate_event bad interfaceTag\n"); + return; + } + + memset(&pmkid_cand, 0, sizeof(pmkid_cand)); + + if (preauth_allowed) { + pmkid_cand.flags |= IW_PMKID_CAND_PREAUTH; + } + pmkid_cand.bssid.sa_family = ARPHRD_ETHER; + memcpy(pmkid_cand.bssid.sa_data, bssid.a, ETH_ALEN); + /* Used as priority, smaller the number higher the priority, not really used in our case */ + pmkid_cand.index = 1; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(pmkid_cand); + + wireless_send_event(priv->netdev[interfaceTag], IWEVPMKIDCAND, &wrqu, (char *)&pmkid_cand); +#endif +} /* wext_send_pmkid_candidate_event() */ + +/* + * Send a custom WEXT event to say we have completed initialisation + * and are now ready for WEXT ioctls. Used by Android wpa_supplicant. + */ +void +wext_send_started_event(unifi_priv_t *priv) +{ +#if WIRELESS_EXT > 17 + union iwreq_data wrqu; + char data[] = "STARTED"; + + wrqu.data.length = sizeof(data); + wrqu.data.flags = 0; + wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVCUSTOM, &wrqu, data); +#endif +} /* wext_send_started_event() */ + -- GitLab From 3824c47714f28091f74ca2505146514b4da1f390 Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Sun, 6 May 2012 18:16:44 +0530 Subject: [PATCH 0910/5711] power_supply: Add constant charge_current and charge_voltage properties Constant Charge Current(CC) is charging parameter which limit the maximum current which can be pumped into the battery during charge cycle. Constant Charge Voltage(CV) is also charging parameter which limit the maximum voltage that battery can reach during charge cycle. It is very common practice that at low or high temperatures we do not charge the batteries upto it's fullest charge voltage to avoid battery and user safety issues. These sysfs properties will be useful for debug and to implement certain user space policies like "Charging limited due to OverTemp". Signed-off-by: Ramakrishna Pallala Signed-off-by: Anton Vorontsov --- Documentation/power/power_supply_class.txt | 4 ++++ drivers/power/power_supply_sysfs.c | 2 ++ include/linux/power_supply.h | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt index 211831d4095f..c0f62ae2b5e0 100644 --- a/Documentation/power/power_supply_class.txt +++ b/Documentation/power/power_supply_class.txt @@ -112,6 +112,10 @@ CHARGE_COUNTER - the current charge counter (in µAh). This could easily be negative; there is no empty or full value. It is only useful for relative, time-based measurements. +CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger. + +CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. + ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. CAPACITY - capacity in percents. diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 4150747f9186..58846d929b34 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -159,6 +159,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(charge_now), POWER_SUPPLY_ATTR(charge_avg), POWER_SUPPLY_ATTR(charge_counter), + POWER_SUPPLY_ATTR(constant_charge_current), + POWER_SUPPLY_ATTR(constant_charge_voltage), POWER_SUPPLY_ATTR(energy_full_design), POWER_SUPPLY_ATTR(energy_empty_design), POWER_SUPPLY_ATTR(energy_full), diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 59ed2dd9dba9..53f177db6ac9 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -109,6 +109,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_AVG, POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, @@ -239,6 +241,7 @@ static inline bool power_supply_is_amp_property(enum power_supply_property psp) case POWER_SUPPLY_PROP_CHARGE_NOW: case POWER_SUPPLY_PROP_CHARGE_AVG: case POWER_SUPPLY_PROP_CHARGE_COUNTER: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_CURRENT_AVG: @@ -266,6 +269,7 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp) case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_AVG: case POWER_SUPPLY_PROP_VOLTAGE_OCV: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: case POWER_SUPPLY_PROP_POWER_NOW: return 1; default: -- GitLab From 19dd6bcd1136d254c1f12b0f69e827c3e1679b43 Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Tue, 19 Jun 2012 16:45:05 -0700 Subject: [PATCH 0911/5711] smb347-charger: Add constant charge and current properties This patch makes use of the two new properties in smb347 charger driver. Signed-off-by: Ramakrishna Pallala Signed-off-by: Anton Vorontsov --- drivers/power/smb347-charger.c | 123 +++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 6 deletions(-) diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c index f8eedd8a676f..332dd0110bda 100644 --- a/drivers/power/smb347-charger.c +++ b/drivers/power/smb347-charger.c @@ -196,6 +196,14 @@ static const unsigned int ccc_tbl[] = { 1200000, }; +/* Convert register value to current using lookup table */ +static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val) +{ + if (val >= size) + return -EINVAL; + return tbl[val]; +} + /* Convert current to register value using lookup table */ static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) { @@ -841,22 +849,101 @@ fail: return ret; } +/* + * Returns the constant charge current programmed + * into the charger in uA. + */ +static int get_const_charge_current(struct smb347_charger *smb) +{ + int ret, intval; + unsigned int v; + + if (!smb347_is_ps_online(smb)) + return -ENODATA; + + ret = regmap_read(smb->regmap, STAT_B, &v); + if (ret < 0) + return ret; + + /* + * The current value is composition of FCC and PCC values + * and we can detect which table to use from bit 5. + */ + if (v & 0x20) { + intval = hw_to_current(fcc_tbl, ARRAY_SIZE(fcc_tbl), v & 7); + } else { + v >>= 3; + intval = hw_to_current(pcc_tbl, ARRAY_SIZE(pcc_tbl), v & 7); + } + + return intval; +} + +/* + * Returns the constant charge voltage programmed + * into the charger in uV. + */ +static int get_const_charge_voltage(struct smb347_charger *smb) +{ + int ret, intval; + unsigned int v; + + if (!smb347_is_ps_online(smb)) + return -ENODATA; + + ret = regmap_read(smb->regmap, STAT_A, &v); + if (ret < 0) + return ret; + + v &= STAT_A_FLOAT_VOLTAGE_MASK; + if (v > 0x3d) + v = 0x3d; + + intval = 3500000 + v * 20000; + + return intval; +} + static int smb347_mains_get_property(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *val) { struct smb347_charger *smb = container_of(psy, struct smb347_charger, mains); + int ret; - if (prop == POWER_SUPPLY_PROP_ONLINE) { + switch (prop) { + case POWER_SUPPLY_PROP_ONLINE: val->intval = smb->mains_online; - return 0; + break; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + ret = get_const_charge_voltage(smb); + if (ret < 0) + return ret; + else + val->intval = ret; + break; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + ret = get_const_charge_current(smb); + if (ret < 0) + return ret; + else + val->intval = ret; + break; + + default: + return -EINVAL; } - return -EINVAL; + + return 0; } static enum power_supply_property smb347_mains_properties[] = { POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, }; static int smb347_usb_get_property(struct power_supply *psy, @@ -865,16 +952,40 @@ static int smb347_usb_get_property(struct power_supply *psy, { struct smb347_charger *smb = container_of(psy, struct smb347_charger, usb); + int ret; - if (prop == POWER_SUPPLY_PROP_ONLINE) { + switch (prop) { + case POWER_SUPPLY_PROP_ONLINE: val->intval = smb->usb_online; - return 0; + break; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + ret = get_const_charge_voltage(smb); + if (ret < 0) + return ret; + else + val->intval = ret; + break; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + ret = get_const_charge_current(smb); + if (ret < 0) + return ret; + else + val->intval = ret; + break; + + default: + return -EINVAL; } - return -EINVAL; + + return 0; } static enum power_supply_property smb347_usb_properties[] = { POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, }; static int smb347_battery_get_property(struct power_supply *psy, -- GitLab From 5fc55bc8225d5a5c13b978e3e3dbf51e6cd6a333 Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Mon, 7 May 2012 10:25:58 +0530 Subject: [PATCH 0912/5711] max17042_battery: Support CHARGE_COUNTER power supply attribute This patch adds the support for CHARGE_COUNTER power supply attribute to max17042/47 driver. Note:QH(Charge Counter) register is not documented in max17042 the Spec. Signed-off-by: Ramakrishna Pallala Signed-off-by: Anton Vorontsov --- drivers/power/max17042_battery.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index 140788b309f8..74abc6c755b4 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c @@ -113,6 +113,7 @@ static enum power_supply_property max17042_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_OCV, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_AVG, @@ -199,6 +200,13 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; + val->intval = ret * 1000 / 2; + break; + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + ret = max17042_read_reg(chip->client, MAX17042_QH); + if (ret < 0) + return ret; + val->intval = ret * 1000 / 2; break; case POWER_SUPPLY_PROP_TEMP: -- GitLab From 95edd09ec3b15b165e2c7ba1e54cc508eafb2321 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jun 2012 17:33:16 -0700 Subject: [PATCH 0913/5711] Staging: csr: update to version 5.1.0 of the driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This brings the in-kernel driver up to the level of the csr-linux-wifi-5.1.0-oss.tar.gz tarball. Cc: Mikko Virkkilä Cc: Lauri Hintsala Cc: Riku Mettälä Cc: Veli-Pekka Peltola Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/csr_framework_ext.c | 35 + drivers/staging/csr/csr_types.h | 1 + drivers/staging/csr/csr_util.c | 4 + drivers/staging/csr/csr_util.h | 45 +- drivers/staging/csr/csr_wifi_common.h | 2 +- drivers/staging/csr/csr_wifi_hip_card.h | 11 +- drivers/staging/csr/csr_wifi_hip_card_sdio.c | 85 +- .../staging/csr/csr_wifi_hip_card_sdio_intr.c | 40 +- .../staging/csr/csr_wifi_hip_card_sdio_mem.c | 4 +- drivers/staging/csr/csr_wifi_hip_download.c | 6 +- drivers/staging/csr/csr_wifi_hip_dump.c | 6 +- .../staging/csr/csr_wifi_hip_ta_sampling.c | 30 +- drivers/staging/csr/csr_wifi_hip_unifi.h | 32 +- drivers/staging/csr/csr_wifi_hip_xbv.c | 12 +- drivers/staging/csr/csr_wifi_nme_ap_lib.h | 3 +- drivers/staging/csr/csr_wifi_nme_ap_prim.h | 3 +- .../csr/csr_wifi_router_converter_init.c | 10 +- .../csr/csr_wifi_router_ctrl_converter_init.c | 18 +- ...ifi_router_ctrl_free_downstream_contents.c | 20 +- ..._wifi_router_ctrl_free_upstream_contents.c | 13 +- .../staging/csr/csr_wifi_router_ctrl_lib.h | 226 ++- .../staging/csr/csr_wifi_router_ctrl_prim.h | 130 +- .../staging/csr/csr_wifi_router_ctrl_sef.c | 12 +- .../staging/csr/csr_wifi_router_ctrl_sef.h | 4 +- .../csr/csr_wifi_router_ctrl_serialize.c | 261 ++- .../csr/csr_wifi_router_ctrl_serialize.h | 58 +- drivers/staging/csr/csr_wifi_sme_ap_lib.h | 131 +- drivers/staging/csr/csr_wifi_sme_ap_prim.h | 141 +- .../staging/csr/csr_wifi_sme_converter_init.c | 11 +- .../staging/csr/csr_wifi_sme_converter_init.h | 2 +- .../csr_wifi_sme_free_downstream_contents.c | 9 +- drivers/staging/csr/csr_wifi_sme_lib.h | 35 +- drivers/staging/csr/csr_wifi_sme_prim.h | 99 +- drivers/staging/csr/csr_wifi_sme_serialize.c | 62 +- drivers/staging/csr/csr_wifi_sme_serialize.h | 7 +- drivers/staging/csr/drv.c | 131 +- drivers/staging/csr/firmware.c | 18 +- drivers/staging/csr/io.c | 20 + drivers/staging/csr/netdev.c | 168 +- drivers/staging/csr/os.c | 26 +- drivers/staging/csr/putest.c | 29 +- drivers/staging/csr/sdio_emb.c | 187 +- drivers/staging/csr/sdio_events.c | 49 +- drivers/staging/csr/sdio_mmc.c | 247 ++- drivers/staging/csr/sme_blocking.c | 123 +- drivers/staging/csr/sme_sys.c | 582 ++++-- drivers/staging/csr/sme_userspace.c | 5 +- drivers/staging/csr/sme_wext.c | 4 +- drivers/staging/csr/ul_int.c | 25 +- drivers/staging/csr/unifi_event.c | 540 +++--- drivers/staging/csr/unifi_os.h | 22 +- drivers/staging/csr/unifi_pdu_processing.c | 1559 +++++++++-------- drivers/staging/csr/unifi_priv.h | 96 +- drivers/staging/csr/unifi_sme.c | 80 + drivers/staging/csr/unifi_sme.h | 9 + drivers/staging/csr/unifiio.h | 27 +- 56 files changed, 3845 insertions(+), 1670 deletions(-) diff --git a/drivers/staging/csr/csr_framework_ext.c b/drivers/staging/csr/csr_framework_ext.c index 0406a4b0f786..1586b235e296 100644 --- a/drivers/staging/csr/csr_framework_ext.c +++ b/drivers/staging/csr/csr_framework_ext.c @@ -211,3 +211,38 @@ void CsrMemFree(void *pointer) kfree(pointer); } EXPORT_SYMBOL_GPL(CsrMemFree); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemAllocDma + * + * DESCRIPTION + * Allocate DMA capable dynamic memory of a given size. + * + * RETURNS + * Pointer to allocated memory, or NULL in case of failure. + * Allocated memory is not initialised. + * + *----------------------------------------------------------------------------*/ +void *CsrMemAllocDma(CsrSize size) +{ + return kmalloc(size, GFP_KERNEL | GFP_DMA); +} +EXPORT_SYMBOL_GPL(CsrMemAllocDma); + +/*----------------------------------------------------------------------------* + * NAME + * CsrMemFreeDma + * + * DESCRIPTION + * Free DMA capable dynamic allocated memory. + * + * RETURNS + * void + * + *----------------------------------------------------------------------------*/ +void CsrMemFreeDma(void *pointer) +{ + kfree(pointer); +} +EXPORT_SYMBOL_GPL(CsrMemFreeDma); diff --git a/drivers/staging/csr/csr_types.h b/drivers/staging/csr/csr_types.h index d7d2c5d061fe..23193ea4429f 100644 --- a/drivers/staging/csr/csr_types.h +++ b/drivers/staging/csr/csr_types.h @@ -21,6 +21,7 @@ #include #include #include +#include #endif #ifdef __cplusplus diff --git a/drivers/staging/csr/csr_util.c b/drivers/staging/csr/csr_util.c index 0ae11531e26d..939c87c638a1 100644 --- a/drivers/staging/csr/csr_util.c +++ b/drivers/staging/csr/csr_util.c @@ -221,6 +221,7 @@ void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str) /*------------------------------------------------------------------*/ /* String */ /*------------------------------------------------------------------*/ +#ifndef CSR_USE_STDC_LIB void *CsrMemCpy(void *dest, const void *src, CsrSize count) { return memcpy(dest, src, count); @@ -257,7 +258,9 @@ void *CsrMemDup(const void *buf1, CsrSize count) return buf2; } +#endif +#ifndef CSR_USE_STDC_LIB CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src) { return strcpy(dest, src); @@ -303,6 +306,7 @@ CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c) { return strchr(string, c); } +#endif CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args) { diff --git a/drivers/staging/csr/csr_util.h b/drivers/staging/csr/csr_util.h index a19baddc0213..ce39c7e8dab7 100644 --- a/drivers/staging/csr/csr_util.h +++ b/drivers/staging/csr/csr_util.h @@ -35,26 +35,53 @@ void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str); void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str); /*------------------------------------------------------------------*/ -/* String */ +/* Standard C Library functions */ /*------------------------------------------------------------------*/ +#ifdef CSR_USE_STDC_LIB +#define CsrMemCpy memcpy +#define CsrMemMove memmove +#define CsrStrCpy strcpy +#define CsrStrNCpy strncpy +#define CsrStrCat strcat +#define CsrStrNCat strncat +#define CsrMemCmp(s1, s2, n) ((CsrInt32) memcmp((s1), (s2), (n))) +#define CsrStrCmp(s1, s2) ((CsrInt32) strcmp((s1), (s2))) +#define CsrStrNCmp(s1, s2, n) ((CsrInt32) strncmp((s1), (s2), (n))) +/*#define CsrMemChr memchr*/ +#define CsrStrChr strchr +/*#define CsrStrCSpn strcspn*/ +/*#define CsrStrPBrk strpbrk*/ +/*#define CsrStrRChr strrchr*/ +/*#define CsrStrSpn strspn*/ +#define CsrStrStr strstr +/*#define CsrStrTok strtok*/ +#define CsrMemSet memset +#define CsrStrLen strlen +/*#define CsrVsnprintf(s, n, format, arg) ((CsrInt32) vsnprintf((s), (n), (format), (arg)))*/ +#else /* !CSR_USE_STDC_LIB */ void *CsrMemCpy(void *dest, const void *src, CsrSize count); -void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count); void *CsrMemMove(void *dest, const void *src, CsrSize count); -CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count); -void *CsrMemDup(const void *buf1, CsrSize count); CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src); CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count); -int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count); CsrCharString *CsrStrCat(CsrCharString *dest, const CsrCharString *src); CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count); -CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2); -CsrSize CsrStrLen(const CsrCharString *string); +CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count); CsrInt32 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2); CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count); -CsrCharString *CsrStrDup(const CsrCharString *string); CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c); -CsrUint32 CsrStrToInt(const CsrCharString *string); +CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2); +void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count); +CsrSize CsrStrLen(const CsrCharString *string); +#endif /* !CSR_USE_STDC_LIB */ CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args); + +/*------------------------------------------------------------------*/ +/* Non-standard utility functions */ +/*------------------------------------------------------------------*/ +void *CsrMemDup(const void *buf1, CsrSize count); +int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count); +CsrCharString *CsrStrDup(const CsrCharString *string); +CsrUint32 CsrStrToInt(const CsrCharString *string); CsrCharString *CsrStrNCpyZero(CsrCharString *dest, const CsrCharString *src, CsrSize count); /*------------------------------------------------------------------*/ diff --git a/drivers/staging/csr/csr_wifi_common.h b/drivers/staging/csr/csr_wifi_common.h index 1cdde5c7bd8d..442dcc6e4e06 100644 --- a/drivers/staging/csr/csr_wifi_common.h +++ b/drivers/staging/csr/csr_wifi_common.h @@ -99,7 +99,7 @@ typedef struct #define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG ((CsrResult) 0x000B) #define CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT ((CsrResult) 0x000C) -#define CSR_WIFI_VERSION "5.0.3.0" +#define CSR_WIFI_VERSION "5.1.0.0" #ifdef __cplusplus } diff --git a/drivers/staging/csr/csr_wifi_hip_card.h b/drivers/staging/csr/csr_wifi_hip_card.h index 8904211d3317..2ab47843bcc6 100644 --- a/drivers/staging/csr/csr_wifi_hip_card.h +++ b/drivers/staging/csr/csr_wifi_hip_card.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -81,6 +81,15 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue */ void CardClearFromHostDataSlot(card_t *card, const CsrInt16 aSlotNum); +#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL +/***************************************************************************** + * CardClearFromHostDataSlotWithoutFreeingBulkData - Clear the data stot + * without freeing the bulk data + */ + +void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 aSlotNum); +#endif + /***************************************************************************** * CardGetFreeFromHostDataSlots - */ diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c index 719c608d18b4..91976b824a4e 100644 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -323,7 +323,7 @@ CsrResult unifi_init(card_t *card) * have requested a mini-coredump which needs to be captured now the * SDIO interface is alive. */ - unifi_coredump_handle_request(card); + (void)unifi_coredump_handle_request(card); /* * Probe to see if the UniFi has ROM/flash to boot from. CSR6xxx should do. @@ -1616,14 +1616,14 @@ static CsrResult card_allocate_memory_resources(card_t *card) /* Reset any state carried forward from a previous life */ card->fh_command_queue.q_rd_ptr = 0; card->fh_command_queue.q_wr_ptr = 0; - CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, - "fh_cmd_q"); + (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + "fh_cmd_q"); for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) { card->fh_traffic_queue[i].q_rd_ptr = 0; card->fh_traffic_queue[i].q_wr_ptr = 0; - CsrSnprintf(card->fh_traffic_queue[i].name, - UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); + (void)CsrSnprintf(card->fh_traffic_queue[i].name, + UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); } #ifndef CSR_WIFI_HIP_TA_DISABLE unifi_ta_sampling_init(card); @@ -1634,7 +1634,7 @@ static CsrResult card_allocate_memory_resources(card_t *card) /* * Allocate memory for the from-host and to-host signal buffers. */ - card->fh_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE); + card->fh_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE); if (card->fh_buffer.buf == NULL) { unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n"); @@ -1645,7 +1645,7 @@ static CsrResult card_allocate_memory_resources(card_t *card) card->fh_buffer.ptr = card->fh_buffer.buf; card->fh_buffer.count = 0; - card->th_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE); + card->th_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE); if (card->th_buffer.buf == NULL) { unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n"); @@ -1693,6 +1693,12 @@ static CsrResult card_allocate_memory_resources(card_t *card) return CSR_WIFI_HIP_RESULT_NO_MEMORY; } + /* Initialise host tag entries for from-host bulk data slots */ + for (i = 0; i < n; i++) + { + card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; + } + /* Allocate memory for the array of pointers */ n = cfg_data->num_tohost_data_slots; @@ -1811,7 +1817,7 @@ static void card_free_memory_resources(card_t *card) if (card->fh_buffer.buf) { - CsrMemFree(card->fh_buffer.buf); + CsrMemFreeDma(card->fh_buffer.buf); } card->fh_buffer.ptr = card->fh_buffer.buf = NULL; card->fh_buffer.bufsize = 0; @@ -1819,7 +1825,7 @@ static void card_free_memory_resources(card_t *card) if (card->th_buffer.buf) { - CsrMemFree(card->th_buffer.buf); + CsrMemFreeDma(card->th_buffer.buf); } card->th_buffer.ptr = card->th_buffer.buf = NULL; card->th_buffer.bufsize = 0; @@ -1842,14 +1848,14 @@ static void card_init_soft_queues(card_t *card) /* Reset any state carried forward from a previous life */ card->fh_command_queue.q_rd_ptr = 0; card->fh_command_queue.q_wr_ptr = 0; - CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, - "fh_cmd_q"); + (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + "fh_cmd_q"); for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) { card->fh_traffic_queue[i].q_rd_ptr = 0; card->fh_traffic_queue[i].q_wr_ptr = 0; - CsrSnprintf(card->fh_traffic_queue[i].name, - UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); + (void)CsrSnprintf(card->fh_traffic_queue[i].name, + UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); } #ifndef CSR_WIFI_HIP_TA_DISABLE unifi_ta_sampling_init(card); @@ -2399,6 +2405,57 @@ void CardClearFromHostDataSlot(card_t *card, const CsrInt16 slot) } /* CardClearFromHostDataSlot() */ +#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL +/* + * --------------------------------------------------------------------------- + * CardClearFromHostDataSlotWithoutFreeingBulkData + * + * Clear the given data slot with out freeing the bulk data. + * + * Arguments: + * card Pointer to Card object + * slot Index of the signal slot to clear. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 slot) +{ + CsrUint8 queue = card->from_host_data[slot].queue; + + /* Initialise the from_host data slot so it can be re-used, + * Set length field in from_host_data array to 0. + */ + UNIFI_INIT_BULK_DATA(&card->from_host_data[slot].bd); + + queue = card->from_host_data[slot].queue; + + if (queue < UNIFI_NO_OF_TX_QS) + { + if (card->dynamic_slot_data.from_host_used_slots[queue] == 0) + { + unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n", + queue, + card->dynamic_slot_data.from_host_used_slots[queue]); + } + else + { + card->dynamic_slot_data.from_host_used_slots[queue]--; + } + card->dynamic_slot_data.packets_txed[queue]++; + card->dynamic_slot_data.total_packets_txed++; + if (card->dynamic_slot_data.total_packets_txed >= + card->dynamic_slot_data.packets_interval) + { + CardReassignDynamicReservation(card); + } + } +} /* CardClearFromHostDataSlotWithoutFreeingBulkData() */ + + +#endif + CsrUint16 CardGetDataSlotSize(card_t *card) { return card->config_data.data_slot_size; diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c index 3d563c13ff5a..8fefbdfc7156 100644 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -148,9 +148,9 @@ void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length) CsrCharString s[5]; CsrUint16 i; - for (i = 0; i < length; i++) + for (i = 0; i < length; i = i + 2) { - CsrUInt16ToHex(0xff & buff[i], s); + CsrUInt16ToHex(*((CsrUint16 *)(buff + i)), s); unifi_debug_string_to_buf(s); } } @@ -277,7 +277,7 @@ void unifi_sdio_interrupt_handler(card_t *card) * Then ask the OS layer to run the unifi_bh to give attention to the UniFi. */ card->bh_reason_unifi = 1; - unifi_run_bh(card->ospriv); + (void)unifi_run_bh(card->ospriv); } /* sdio_interrupt_handler() */ @@ -309,7 +309,7 @@ CsrResult unifi_configure_low_power_mode(card_t *card, (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled", (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE"); - unifi_run_bh(card->ospriv); + (void)unifi_run_bh(card->ospriv); return CSR_RESULT_SUCCESS; } /* unifi_configure_low_power_mode() */ @@ -614,10 +614,10 @@ exit: (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled"); /* Try to capture firmware panic codes */ - unifi_capture_panic(card); + (void)unifi_capture_panic(card); /* Ask for a mini-coredump when the driver has reset UniFi */ - unifi_coredump_request_at_next_reset(card, 1); + (void)unifi_coredump_request_at_next_reset(card, 1); } return r; @@ -932,9 +932,13 @@ static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something return r; } } + +#ifdef CSR_WIFI_RX_PATH_SPLIT #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ unifi_rx_queue_flush(card->ospriv); #endif +#endif + /* See if we can re-enable transmission now */ restart_packet_flow(card); @@ -1324,7 +1328,6 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed) if (status && (card->fh_slot_host_tag_record)) { CsrUint16 num_fh_slots = card->config_data.num_fromhost_data_slots; - CsrUint16 i = 0; /* search through the list of slot records and match with host tag * If a slot is not yet cleared then clear the slot from here @@ -1333,12 +1336,27 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed) { if (card->fh_slot_host_tag_record[i] == host_tag) { +#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL + /* Invoke the HAL module function to requeue it back to HAL Queues */ + r = unifi_reque_ma_packet_request(card->ospriv, host_tag, status, &card->from_host_data[i].bd); + card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; + if (CSR_RESULT_SUCCESS != r) + { + unifi_trace(card->ospriv, UDBG5, "process_to_host_signals: Failed to requeue Packet(hTag:%x) back to HAL \n", host_tag); + CardClearFromHostDataSlot(card, i); + } + else + { + CardClearFromHostDataSlotWithoutFreeingBulkData(card, i); + } + +#else unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag); card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; /* Set length field in from_host_data array to 0 */ CardClearFromHostDataSlot(card, i); - +#endif break; } } @@ -1724,7 +1742,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr, if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3)) { - host_bulk_data_slot = CsrMemAlloc(len); + host_bulk_data_slot = CsrMemAllocDma(len); if (!host_bulk_data_slot) { @@ -1783,7 +1801,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr, /* moving this check before we clear host data slot */ if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3)) { - CsrMemFree(host_bulk_data_slot); + CsrMemFreeDma(host_bulk_data_slot); } #endif diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c index 403641d4df02..8bc2d74e8d5e 100644 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -1565,7 +1565,7 @@ CsrResult unifi_bulk_rw(card_t *card, CsrUint32 handle, void *pdata, */ if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) { - unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); + (void)unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); } /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted diff --git a/drivers/staging/csr/csr_wifi_hip_download.c b/drivers/staging/csr/csr_wifi_hip_download.c index fb6f04e1bbf4..47178afe5865 100644 --- a/drivers/staging/csr/csr_wifi_hip_download.c +++ b/drivers/staging/csr/csr_wifi_hip_download.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -674,7 +674,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv, return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } - buf = CsrMemAlloc(buf_size); + buf = CsrMemAllocDma(buf_size); if (buf == NULL) { unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n"); @@ -720,7 +720,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv, } } - CsrMemFree(buf); + CsrMemFreeDma(buf); if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) { diff --git a/drivers/staging/csr/csr_wifi_hip_dump.c b/drivers/staging/csr/csr_wifi_hip_dump.c index c191ea135040..5297f103e9eb 100644 --- a/drivers/staging/csr/csr_wifi_hip_dump.c +++ b/drivers/staging/csr/csr_wifi_hip_dump.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -293,7 +293,7 @@ done: * Notes: * --------------------------------------------------------------------------- */ -static CsrInt32 get_value_from_coredump(const coredump_buffer *dump, +static CsrInt32 get_value_from_coredump(const coredump_buffer *coreDump, const unifi_coredump_space_t space, const CsrUint16 offset_in_space) { @@ -316,7 +316,7 @@ static CsrInt32 get_value_from_coredump(const coredump_buffer *dump, { /* Calculate the offset of data within the zone buffer */ offset_in_zone = offset_in_space - def->offset; - r = (CsrInt32) * (dump->zone[i] + offset_in_zone); + r = (CsrInt32) * (coreDump->zone[i] + offset_in_zone); unifi_trace(NULL, UDBG6, "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n", diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.c b/drivers/staging/csr/csr_wifi_hip_ta_sampling.c index 4fa8f607f15c..7afcd3c90fc6 100644 --- a/drivers/staging/csr/csr_wifi_hip_ta_sampling.c +++ b/drivers/staging/csr/csr_wifi_hip_ta_sampling.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -69,9 +69,9 @@ enum ta_frame_identity #define TA_EAPOL_TYPE_OFFSET 9 #define TA_EAPOL_TYPE_START 0x01 -static const CsrUint8 snap_802_2[3] = { 0xAA, 0xAA, 0x03 }; -static const CsrUint8 oui_rfc1042[3] = { 0x00, 0x00, 0x00 }; -static const CsrUint8 oui_8021h[3] = { 0x00, 0x00, 0xf8 }; +#define snap_802_2 0xAAAA0300 +#define oui_rfc1042 0x00000000 +#define oui_8021h 0x0000f800 static const CsrUint8 aironet_snap[5] = { 0x00, 0x40, 0x96, 0x00, 0x00 }; @@ -100,13 +100,17 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl CsrUint16 proto; CsrUint16 source_port, dest_port; CsrWifiMacAddress srcAddress; + CsrUint32 snap_hdr, oui_hdr; if (data->data_length < TA_LLC_HEADER_SIZE) { return TA_FRAME_UNKNOWN; } - if (CsrMemCmp(data->os_data_ptr, snap_802_2, 3)) + snap_hdr = (((CsrUint32)data->os_data_ptr[0]) << 24) | + (((CsrUint32)data->os_data_ptr[1]) << 16) | + (((CsrUint32)data->os_data_ptr[2]) << 8); + if (snap_hdr != snap_802_2) { return TA_FRAME_UNKNOWN; } @@ -118,8 +122,10 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl */ } - if (!CsrMemCmp(data->os_data_ptr + 3, oui_rfc1042, 3) || - !CsrMemCmp(data->os_data_ptr + 3, oui_8021h, 3)) + oui_hdr = (((CsrUint32)data->os_data_ptr[3]) << 24) | + (((CsrUint32)data->os_data_ptr[4]) << 16) | + (((CsrUint32)data->os_data_ptr[5]) << 8); + if ((oui_hdr == oui_rfc1042) || (oui_hdr == oui_8021h)) { proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) + data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1]; @@ -177,7 +183,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl /* The DHCP should have at least a message type (request, ack, nack, etc) */ if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6) { - CsrMemCpy(srcAddress.a, saddr, 6); + UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) { @@ -189,7 +195,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl } /* DHCPACK is a special indication */ - if (!CsrMemCmp(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr, 6)) + if (UNIFI_MAC_ADDRESS_CMP(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr) == TRUE) { if (data->os_data_ptr[TA_DHCP_MESSAGE_TYPE_OFFSET] == TA_DHCP_MESSAGE_TYPE_ACK) { @@ -224,7 +230,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl if ((TA_PROTO_TYPE_WAI == proto) || (direction != CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) || (data->os_data_ptr[TA_EAPOL_TYPE_OFFSET] == TA_EAPOL_TYPE_START)) { - CsrMemCpy(srcAddress.a, saddr, 6); + UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL, direction, &srcAddress); @@ -238,7 +244,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl { if (proto == TA_PROTO_TYPE_ARP) { - CsrMemCpy(srcAddress.a, saddr, 6); + UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP, direction, &srcAddress); @@ -253,7 +259,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl /* detect Aironet frames */ if (!CsrMemCmp(data->os_data_ptr + 3, aironet_snap, 5)) { - CsrMemCpy(srcAddress.a, saddr, 6); + UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET, direction, &srcAddress); } diff --git a/drivers/staging/csr/csr_wifi_hip_unifi.h b/drivers/staging/csr/csr_wifi_hip_unifi.h index feda2e051c21..5f1c67b7c6ea 100644 --- a/drivers/staging/csr/csr_wifi_hip_unifi.h +++ b/drivers/staging/csr/csr_wifi_hip_unifi.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -103,6 +103,17 @@ extern "C" { #include "csr_formatted_io.h" /* from the synergy gsp folder */ #include "csr_wifi_result.h" +/* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */ +#define UNIFI_MAC_ADDRESS_COPY(dst, src) \ + do { (dst)[0] = (src)[0]; (dst)[1] = (src)[1]; \ + (dst)[2] = (src)[2]; (dst)[3] = (src)[3]; \ + (dst)[4] = (src)[4]; (dst)[5] = (src)[5]; \ + } while (0) + +#define UNIFI_MAC_ADDRESS_CMP(addr1, addr2) \ + (((addr1)[0] == (addr2)[0]) && ((addr1)[1] == (addr2)[1]) && \ + ((addr1)[2] == (addr2)[2]) && ((addr1)[3] == (addr2)[3]) && \ + ((addr1)[4] == (addr2)[4]) && ((addr1)[5] == (addr2)[5])) /* Traffic queue ordered according to priority * EAPOL/Uncontrolled port Queue should be the last @@ -635,7 +646,24 @@ void unifi_receive_event(void *ospriv, CsrUint8 *sigdata, CsrUint32 siglen, const bulk_data_param_t *bulkdata); +#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL +/** + * + * Used to reque the failed ma packet request back to hal queues + * + * @param ospriv the OS layer context. + * + * @param host_tag host tag for the packet to requeue. + * + * @param bulkDataDesc pointer to the bulk data. + * + * @ingroup upperedge + */ +CsrResult unifi_reque_ma_packet_request(void *ospriv, CsrUint32 host_tag, + CsrUint16 status, + bulk_data_desc_t *bulkDataDesc); +#endif typedef struct { CsrUint16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS]; @@ -836,6 +864,8 @@ const CsrCharString* lookup_bulkcmd_name(CsrUint16 id); /* Function to log HIP's global debug buffer */ #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE void unifi_debug_buf_dump(void); +void unifi_debug_log_to_buf(const CsrCharString *fmt, ...); +void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length); #endif /* Mini-coredump utility functions */ diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.c b/drivers/staging/csr/csr_wifi_hip_xbv.c index 5d0fdcce1a97..5aaec4da441b 100644 --- a/drivers/staging/csr/csr_wifi_hip_xbv.c +++ b/drivers/staging/csr/csr_wifi_hip_xbv.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -579,8 +579,8 @@ static CsrUint32 write_uint16(void *buf, const CsrUint32 offset, const CsrUint16 static CsrUint32 write_uint32(void *buf, const CsrUint32 offset, const CsrUint32 val) { - write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff)); - write_uint16(buf, offset + 2, (CsrUint16)(val >> 16)); + (void)write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff)); + (void)write_uint16(buf, offset + 2, (CsrUint16)(val >> 16)); return sizeof(CsrUint32); } @@ -1055,11 +1055,11 @@ void* xbv_to_patch(card_t *card, fwreadfn_t readfn, patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id); /* Now the length is known, update the LIST.length */ - write_uint32(patch_buf, list_len_offs, - (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE); + (void)write_uint32(patch_buf, list_len_offs, + (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE); /* Re write XBV headers just to fill in the correct file size */ - write_xbv_header(patch_buf, 0, (patch_offs - payload_offs)); + (void)write_xbv_header(patch_buf, 0, (patch_offs - payload_offs)); unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n", patch_offs, fw_id); diff --git a/drivers/staging/csr/csr_wifi_nme_ap_lib.h b/drivers/staging/csr/csr_wifi_nme_ap_lib.h index fc5692476ddc..aa632d5dd0d4 100644 --- a/drivers/staging/csr/csr_wifi_nme_ap_lib.h +++ b/drivers/staging/csr/csr_wifi_nme_ap_lib.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -196,7 +196,6 @@ extern const CsrCharString *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM apCredentials - Security credential configuration. maxConnections - Maximum number of stations/P2P clients allowed p2pGoParam - P2P specific GO parameters. - NOT USED FOR CURRENT RELEASE wpsEnabled - Indicates whether WPS should be enabled or not *******************************************************************************/ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_prim.h b/drivers/staging/csr/csr_wifi_nme_ap_prim.h index e3b56b4b44e3..561c2fdc3799 100644 --- a/drivers/staging/csr/csr_wifi_nme_ap_prim.h +++ b/drivers/staging/csr/csr_wifi_nme_ap_prim.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -248,7 +248,6 @@ typedef struct apCredentials - Security credential configuration. maxConnections - Maximum number of stations/P2P clients allowed p2pGoParam - P2P specific GO parameters. - NOT USED FOR CURRENT RELEASE wpsEnabled - Indicates whether WPS should be enabled or not *******************************************************************************/ diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.c b/drivers/staging/csr/csr_wifi_router_converter_init.c index f7ee3f0ec37d..6ff59c01e149 100644 --- a/drivers/staging/csr/csr_wifi_router_converter_init.c +++ b/drivers/staging/csr/csr_wifi_router_converter_init.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -41,11 +41,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint { if (msgType & CSR_PRIM_UPSTREAM) { - CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT; - if (index < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) && - csrwifirouter_conv_lut[index].msgType == msgType) + CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT; + if (idx < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) && + csrwifirouter_conv_lut[idx].msgType == msgType) { - return &csrwifirouter_conv_lut[index]; + return &csrwifirouter_conv_lut[idx]; } } else diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c index 36403fcf97e8..32d0bb632d99 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c +++ b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -50,9 +50,11 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = { { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree }, { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree }, { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, CsrWifiRouterCtrlBlockAckDisableReqSizeof, CsrWifiRouterCtrlBlockAckDisableReqSer, CsrWifiRouterCtrlBlockAckDisableReqDes, CsrWifiRouterCtrlBlockAckDisableReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, CsrWifiRouterCtrlWapiMulticastReqSizeof, CsrWifiRouterCtrlWapiMulticastReqSer, CsrWifiRouterCtrlWapiMulticastReqDes, CsrWifiRouterCtrlWapiMulticastReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, CsrWifiRouterCtrlWapiRxPktReqSizeof, CsrWifiRouterCtrlWapiRxPktReqSer, CsrWifiRouterCtrlWapiRxPktReqDes, CsrWifiRouterCtrlWapiRxPktReqSerFree }, { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, CsrWifiRouterCtrlWapiMulticastFilterReqSizeof, CsrWifiRouterCtrlWapiMulticastFilterReqSer, CsrWifiRouterCtrlWapiMulticastFilterReqDes, CsrWifiRouterCtrlWapiMulticastFilterReqSerFree }, { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, CsrWifiRouterCtrlWapiUnicastFilterReqSizeof, CsrWifiRouterCtrlWapiUnicastFilterReqSer, CsrWifiRouterCtrlWapiUnicastFilterReqDes, CsrWifiRouterCtrlWapiUnicastFilterReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof, CsrWifiRouterCtrlWapiUnicastTxPktReqSer, CsrWifiRouterCtrlWapiUnicastTxPktReqDes, CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, CsrWifiRouterCtrlWapiFilterReqSizeof, CsrWifiRouterCtrlWapiFilterReqSer, CsrWifiRouterCtrlWapiFilterReqDes, CsrWifiRouterCtrlWapiFilterReqSerFree }, { CSR_WIFI_ROUTER_CTRL_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree }, { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree }, { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree }, @@ -81,7 +83,9 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = { { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree }, { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree }, { CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, CsrWifiRouterCtrlStaInactiveIndSizeof, CsrWifiRouterCtrlStaInactiveIndSer, CsrWifiRouterCtrlStaInactiveIndDes, CsrWifiRouterCtrlStaInactiveIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, CsrWifiRouterCtrlWapiMulticastIndSizeof, CsrWifiRouterCtrlWapiMulticastIndSer, CsrWifiRouterCtrlWapiMulticastIndDes, CsrWifiRouterCtrlWapiMulticastIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, CsrWifiRouterCtrlWapiRxMicCheckIndSizeof, CsrWifiRouterCtrlWapiRxMicCheckIndSer, CsrWifiRouterCtrlWapiRxMicCheckIndDes, CsrWifiRouterCtrlWapiRxMicCheckIndSerFree }, + { CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, CsrWifiRouterCtrlModeSetCfmSizeof, CsrWifiRouterCtrlModeSetCfmSer, CsrWifiRouterCtrlModeSetCfmDes, CsrWifiRouterCtrlModeSetCfmSerFree }, + { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer, CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree }, { 0, NULL, NULL, NULL, NULL }, }; @@ -90,11 +94,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, Csr { if (msgType & CSR_PRIM_UPSTREAM) { - CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT; - if (index < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) && - csrwifirouterctrl_conv_lut[index].msgType == msgType) + CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT; + if (idx < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) && + csrwifirouterctrl_conv_lut[idx].msgType == msgType) { - return &csrwifirouterctrl_conv_lut[index]; + return &csrwifirouterctrl_conv_lut[idx]; } } else diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c index 57aa36739590..d161fad84608 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c +++ b/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -70,6 +70,13 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void * p->tclas = NULL; break; } + case CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ: + { + CsrWifiRouterCtrlWifiOnReq *p = (CsrWifiRouterCtrlWifiOnReq *)message; + CsrPmemFree(p->data); + p->data = NULL; + break; + } case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES: { CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message; @@ -77,15 +84,22 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void * p->smeVersions.smeBuild = NULL; break; } - case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ: + case CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ: { - CsrWifiRouterCtrlWapiMulticastReq *p = (CsrWifiRouterCtrlWapiMulticastReq *)message; + CsrWifiRouterCtrlWapiRxPktReq *p = (CsrWifiRouterCtrlWapiRxPktReq *)message; CsrPmemFree(p->signal); p->signal = NULL; CsrPmemFree(p->data); p->data = NULL; break; } + case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ: + { + CsrWifiRouterCtrlWapiUnicastTxPktReq *p = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)message; + CsrPmemFree(p->data); + p->data = NULL; + break; + } default: break; diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c index 25e327357a32..b6bf11d566d7 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c +++ b/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -63,15 +63,22 @@ void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *me p->versions.routerBuild = NULL; break; } - case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND: + case CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND: { - CsrWifiRouterCtrlWapiMulticastInd *p = (CsrWifiRouterCtrlWapiMulticastInd *)message; + CsrWifiRouterCtrlWapiRxMicCheckInd *p = (CsrWifiRouterCtrlWapiRxMicCheckInd *)message; CsrPmemFree(p->signal); p->signal = NULL; CsrPmemFree(p->data); p->data = NULL; break; } + case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND: + { + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *p = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)message; + CsrPmemFree(p->data); + p->data = NULL; + break; + } default: break; diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h index f0ad836b00c5..6c7e97437570 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h +++ b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -658,6 +658,39 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER #define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) +/******************************************************************************* + + NAME + CsrWifiRouterCtrlModeSetCfmSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + mode - + status - + +*******************************************************************************/ +#define CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__) \ + msg__ = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->mode = (mode__); \ + msg__->status = (status__); + +#define CsrWifiRouterCtrlModeSetCfmSendTo(dst__, src__, clientData__, interfaceTag__, mode__, status__) \ + { \ + CsrWifiRouterCtrlModeSetCfm *msg__; \ + CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlModeSetCfmSend(dst__, clientData__, interfaceTag__, mode__, status__) \ + CsrWifiRouterCtrlModeSetCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, mode__, status__) + /******************************************************************************* NAME @@ -1594,6 +1627,35 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER #define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \ CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__) +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiFilterReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + isWapiConnected - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__) \ + msg__ = (CsrWifiRouterCtrlWapiFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiFilterReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->isWapiConnected = (isWapiConnected__); + +#define CsrWifiRouterCtrlWapiFilterReqSendTo(dst__, src__, interfaceTag__, isWapiConnected__) \ + { \ + CsrWifiRouterCtrlWapiFilterReq *msg__; \ + CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiFilterReqSend(src__, interfaceTag__, isWapiConnected__) \ + CsrWifiRouterCtrlWapiFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, isWapiConnected__) + /******************************************************************************* NAME @@ -1602,68 +1664,73 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER DESCRIPTION PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - status - + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + status - *******************************************************************************/ -#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__) \ +#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \ msg__ = (CsrWifiRouterCtrlWapiMulticastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq)); \ CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ msg__->status = (status__); -#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, status__) \ +#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \ { \ CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \ - CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__); \ + CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \ CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ } -#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, status__) \ - CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__) +#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, interfaceTag__, status__) \ + CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__) /******************************************************************************* NAME - CsrWifiRouterCtrlWapiMulticastReqSend + CsrWifiRouterCtrlWapiRxMicCheckIndSend DESCRIPTION PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) + queue - Destination Task Queue + clientData - + interfaceTag - signalLength - signal - dataLength - data - *******************************************************************************/ -#define CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__) \ - msg__ = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, dst__, src__); \ +#define CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ msg__->signalLength = (signalLength__); \ msg__->signal = (signal__); \ msg__->dataLength = (dataLength__); \ msg__->data = (data__); -#define CsrWifiRouterCtrlWapiMulticastReqSendTo(dst__, src__, signalLength__, signal__, dataLength__, data__) \ +#define CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ { \ - CsrWifiRouterCtrlWapiMulticastReq *msg__; \ - CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + CsrWifiRouterCtrlWapiRxMicCheckInd *msg__; \ + CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ } -#define CsrWifiRouterCtrlWapiMulticastReqSend(src__, signalLength__, signal__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiMulticastReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, signalLength__, signal__, dataLength__, data__) +#define CsrWifiRouterCtrlWapiRxMicCheckIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) /******************************************************************************* NAME - CsrWifiRouterCtrlWapiMulticastIndSend + CsrWifiRouterCtrlWapiRxPktReqSend DESCRIPTION PARAMETERS - queue - Destination Task Queue - clientData - + queue - Message Source Task Queue (Cfm's will be sent to this Queue) interfaceTag - signalLength - signal - @@ -1671,25 +1738,24 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER data - *******************************************************************************/ -#define CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - msg__ = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ +#define CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, dst__, src__); \ msg__->interfaceTag = (interfaceTag__); \ msg__->signalLength = (signalLength__); \ msg__->signal = (signal__); \ msg__->dataLength = (dataLength__); \ msg__->data = (data__); -#define CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ +#define CsrWifiRouterCtrlWapiRxPktReqSendTo(dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ { \ - CsrWifiRouterCtrlWapiMulticastInd *msg__; \ - CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + CsrWifiRouterCtrlWapiRxPktReq *msg__; \ + CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ } -#define CsrWifiRouterCtrlWapiMulticastIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) +#define CsrWifiRouterCtrlWapiRxPktReqSend(src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiRxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) /******************************************************************************* @@ -1699,24 +1765,90 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER DESCRIPTION PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - status - + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + status - *******************************************************************************/ -#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__) \ +#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \ msg__ = (CsrWifiRouterCtrlWapiUnicastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq)); \ CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ msg__->status = (status__); -#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, status__) \ +#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \ { \ CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \ - CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__); \ + CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \ + CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, interfaceTag__, status__) \ + CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend + + DESCRIPTION + + PARAMETERS + queue - Destination Task Queue + clientData - + interfaceTag - + dataLength - + data - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, dst__, src__); \ + msg__->clientData = (clientData__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \ + { \ + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *msg__; \ + CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ + } + +#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(dst__, clientData__, interfaceTag__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, dataLength__, data__) + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastTxPktReqSend + + DESCRIPTION + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + dataLength - + data - + +*******************************************************************************/ +#define CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__) \ + msg__ = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(dst__, src__, interfaceTag__, dataLength__, data__) \ + { \ + CsrWifiRouterCtrlWapiUnicastTxPktReq *msg__; \ + CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__); \ CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ } -#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, status__) \ - CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__) +#define CsrWifiRouterCtrlWapiUnicastTxPktReqSend(src__, interfaceTag__, dataLength__, data__) \ + CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, dataLength__, data__) /******************************************************************************* @@ -1837,22 +1969,26 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER PARAMETERS queue - Message Source Task Queue (Cfm's will be sent to this Queue) clientData - + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes *******************************************************************************/ -#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__) \ +#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__) \ msg__ = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); \ CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \ - msg__->clientData = (clientData__); + msg__->clientData = (clientData__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); -#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__) \ +#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__, dataLength__, data__) \ { \ CsrWifiRouterCtrlWifiOnReq *msg__; \ - CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__); \ + CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__); \ CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ } -#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__) \ - CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) +#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__, dataLength__, data__) \ + CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, dataLength__, data__) /******************************************************************************* diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h index 954f600b4ff4..810482a8fbab 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h +++ b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -616,12 +616,14 @@ typedef struct #define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ ((CsrWifiRouterCtrlPrim) (0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ ((CsrWifiRouterCtrlPrim) (0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) /* Upstream */ #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) @@ -654,9 +656,11 @@ typedef struct #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM ((CsrWifiRouterCtrlPrim)(0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND ((CsrWifiRouterCtrlPrim)(0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) #define CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND ((CsrWifiRouterCtrlPrim)(0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM ((CsrWifiRouterCtrlPrim)(0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND ((CsrWifiRouterCtrlPrim)(0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) +#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) #define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) @@ -1032,12 +1036,16 @@ typedef struct MEMBERS common - Common header for use with the CsrWifiFsm Module clientData - + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes *******************************************************************************/ typedef struct { CsrWifiFsmEvent common; CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint32 dataLength; + CsrUint8 *data; } CsrWifiRouterCtrlWifiOnReq; /******************************************************************************* @@ -1273,12 +1281,13 @@ typedef struct /******************************************************************************* NAME - CsrWifiRouterCtrlWapiMulticastReq + CsrWifiRouterCtrlWapiRxPktReq DESCRIPTION MEMBERS common - Common header for use with the CsrWifiFsm Module + interfaceTag - signalLength - signal - dataLength - @@ -1288,11 +1297,12 @@ typedef struct typedef struct { CsrWifiFsmEvent common; + CsrUint16 interfaceTag; CsrUint16 signalLength; CsrUint8 *signal; CsrUint16 dataLength; CsrUint8 *data; -} CsrWifiRouterCtrlWapiMulticastReq; +} CsrWifiRouterCtrlWapiRxPktReq; /******************************************************************************* @@ -1302,13 +1312,15 @@ typedef struct DESCRIPTION MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - *******************************************************************************/ typedef struct { CsrWifiFsmEvent common; + CsrUint16 interfaceTag; CsrUint8 status; } CsrWifiRouterCtrlWapiMulticastFilterReq; @@ -1320,16 +1332,60 @@ typedef struct DESCRIPTION MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - *******************************************************************************/ typedef struct { CsrWifiFsmEvent common; + CsrUint16 interfaceTag; CsrUint8 status; } CsrWifiRouterCtrlWapiUnicastFilterReq; +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastTxPktReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + dataLength - + data - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrUint16 dataLength; + CsrUint8 *data; +} CsrWifiRouterCtrlWapiUnicastTxPktReq; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiFilterReq + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + isWapiConnected - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrBool isWapiConnected; +} CsrWifiRouterCtrlWapiFilterReq; + /******************************************************************************* NAME @@ -1984,7 +2040,7 @@ typedef struct /******************************************************************************* NAME - CsrWifiRouterCtrlWapiMulticastInd + CsrWifiRouterCtrlWapiRxMicCheckInd DESCRIPTION @@ -2007,7 +2063,55 @@ typedef struct CsrUint8 *signal; CsrUint16 dataLength; CsrUint8 *data; -} CsrWifiRouterCtrlWapiMulticastInd; +} CsrWifiRouterCtrlWapiRxMicCheckInd; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlModeSetCfm + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + mode - + status - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrWifiRouterCtrlMode mode; + CsrResult status; +} CsrWifiRouterCtrlModeSetCfm; + +/******************************************************************************* + + NAME + CsrWifiRouterCtrlWapiUnicastTxEncryptInd + + DESCRIPTION + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + clientData - + interfaceTag - + dataLength - + data - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrWifiRouterCtrlRequestorInfo clientData; + CsrUint16 interfaceTag; + CsrUint16 dataLength; + CsrUint8 *data; +} CsrWifiRouterCtrlWapiUnicastTxEncryptInd; #ifdef __cplusplus diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c index b7fa6a1eb521..33d92b698c59 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c +++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c @@ -35,9 +35,11 @@ const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler, /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler, /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler, - CsrWifiRouterCtrlBlockAckEnableReqHandler, /* 0x0018 */ - CsrWifiRouterCtrlBlockAckDisableReqHandler, /* 0x0019 */ - CsrWifiRouterCtrlWapiMulticastReqHandler, /* 0x001A */ - CsrWifiRouterCtrlWapiMulticastFilterReqHandler, /* 0x001B */ - CsrWifiRouterCtrlWapiUnicastFilterReqHandler, /* 0x001C */ + /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler, + /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler, + /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler, + /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler, + /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler, + /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler, + /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler, }; diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h index 07382ef8cce4..e0ee5cf45f9e 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h +++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h @@ -47,8 +47,10 @@ extern "C" { extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); + extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); #ifdef __cplusplus } #endif diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c index cb1f6dc29888..3239c9bad18d 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c +++ b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -656,6 +656,65 @@ void* CsrWifiRouterCtrlTrafficConfigReqDes(CsrUint8 *buffer, CsrSize length) } +CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg) +{ + CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 4; /* CsrUint32 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlWifiOnReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) voidPrimitivePointer; + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg) { CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) msg; @@ -1055,12 +1114,13 @@ void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize length) } -CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg) +CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg) { - CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) msg; + CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) msg; CsrSize bufferSize = 2; - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ bufferSize += 2; /* CsrUint16 primitive->signalLength */ bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */ bufferSize += 2; /* CsrUint16 primitive->dataLength */ @@ -1069,11 +1129,12 @@ CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg) } -CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) { - CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *)msg; + CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *)msg; *len = 0; CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength); if (primitive->signalLength) { @@ -1088,13 +1149,14 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void } -void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length) +void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize length) { - CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); + CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq)); CsrSize offset; offset = 0; CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset); if (primitive->signalLength) { @@ -1120,15 +1182,74 @@ void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length) } -void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *voidPrimitivePointer) +void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *voidPrimitivePointer) { - CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) voidPrimitivePointer; + CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) voidPrimitivePointer; CsrPmemFree(primitive->signal); CsrPmemFree(primitive->data); CsrPmemFree(primitive); } +CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg) +{ + CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrUint16 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) voidPrimitivePointer; + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg) { CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) msg; @@ -2287,9 +2408,9 @@ void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize length) } -CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg) +CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg) { - CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) msg; + CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) msg; CsrSize bufferSize = 2; /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ @@ -2303,9 +2424,9 @@ CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg) } -CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) { - CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *)msg; + CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *)msg; *len = 0; CsrUint16Ser(ptr, len, primitive->common.type); CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); @@ -2324,9 +2445,9 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void } -void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length) +void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize length) { - CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); + CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd)); CsrSize offset; offset = 0; @@ -2358,12 +2479,116 @@ void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length) } -void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *voidPrimitivePointer) +void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *voidPrimitivePointer) { - CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) voidPrimitivePointer; + CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) voidPrimitivePointer; CsrPmemFree(primitive->signal); CsrPmemFree(primitive->data); CsrPmemFree(primitive); } +CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg) +{ + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */ + bufferSize += 2; /* CsrResult primitive->status */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint8Ser(ptr, len, (CsrUint8) primitive->mode); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->status); + return(ptr); +} + + +void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint8Des((CsrUint8 *) &primitive->mode, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset); + + return primitive; +} + + +CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg) +{ + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ + bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ + bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ + bufferSize += 2; /* CsrUint16 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag); + CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset); + CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *voidPrimitivePointer) +{ + CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) voidPrimitivePointer; + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h index 5d82f8d0daa6..3b7834dad524 100644 --- a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h +++ b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -105,10 +105,10 @@ extern CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg); #define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof #define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree -#define CsrWifiRouterCtrlWifiOnReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlWifiOnReqDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlWifiOnReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlWifiOnReqSerFree CsrWifiRouterCtrlPfree +extern CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg); +extern void CsrWifiRouterCtrlWifiOnReqSerFree(void *msg); extern CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg); extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len); @@ -155,21 +155,31 @@ extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize le extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg); #define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree -extern CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); -extern void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize len); -extern CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *msg); +extern CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *msg); -#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint8Ser -#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint8Des -#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint8Sizeof +#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof #define CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree -#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint8Ser -#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint8Des -#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint8Sizeof +#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof #define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree +extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *msg); + +#define CsrWifiRouterCtrlWapiFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser +#define CsrWifiRouterCtrlWapiFilterReqDes CsrWifiEventCsrUint16CsrUint8Des +#define CsrWifiRouterCtrlWapiFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof +#define CsrWifiRouterCtrlWapiFilterReqSerFree CsrWifiRouterCtrlPfree + extern CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len); extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg); @@ -310,10 +320,20 @@ extern void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize len); extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg); #define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree -extern CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); -extern void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize len); -extern CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *msg); +extern CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *msg); + +extern CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg); +#define CsrWifiRouterCtrlModeSetCfmSerFree CsrWifiRouterCtrlPfree + +extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg); +extern void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *msg); #ifdef __cplusplus diff --git a/drivers/staging/csr/csr_wifi_sme_ap_lib.h b/drivers/staging/csr/csr_wifi_sme_ap_lib.h index edef7c8de409..bb9e79f95ec2 100644 --- a/drivers/staging/csr/csr_wifi_sme_ap_lib.h +++ b/drivers/staging/csr/csr_wifi_sme_ap_lib.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -63,6 +63,7 @@ void CsrWifiSmeApFreeDownstreamMessageContents(CsrUint16 eventClass, void *messa const CsrCharString* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value); const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value); const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value); +const CsrCharString* CsrWifiSmeApDirectionToString(CsrWifiSmeApDirection value); const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value); const CsrCharString* CsrWifiSmeApTypeToString(CsrWifiSmeApType value); @@ -79,6 +80,134 @@ const CsrCharString* CsrWifiSmeApPrimTypeToString(CsrPrim msgType); extern const CsrCharString *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT]; extern const CsrCharString *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT]; +/******************************************************************************* + + NAME + CsrWifiSmeApActiveBaGetReqSend + + DESCRIPTION + This primitive used to retrieve information related to the active block + ack sessions + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + +*******************************************************************************/ +#define CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__) \ + msg__ = (CsrWifiSmeApActiveBaGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); + +#define CsrWifiSmeApActiveBaGetReqSendTo(dst__, src__, interfaceTag__) \ + { \ + CsrWifiSmeApActiveBaGetReq *msg__; \ + CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApActiveBaGetReqSend(src__, interfaceTag__) \ + CsrWifiSmeApActiveBaGetReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) + +/******************************************************************************* + + NAME + CsrWifiSmeApActiveBaGetCfmSend + + DESCRIPTION + This primitive carries the information related to the active ba sessions + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - Reports the result of the request + activeBaCount - Number of active block ack session + activeBaSessions - Points to a buffer containing an array of + CsrWifiSmeApBaSession structures. + +*******************************************************************************/ +#define CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ + msg__ = (CsrWifiSmeApActiveBaGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->activeBaCount = (activeBaCount__); \ + msg__->activeBaSessions = (activeBaSessions__); + +#define CsrWifiSmeApActiveBaGetCfmSendTo(dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ + { \ + CsrWifiSmeApActiveBaGetCfm *msg__; \ + CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApActiveBaGetCfmSend(dst__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ + CsrWifiSmeApActiveBaGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, activeBaCount__, activeBaSessions__) + +/******************************************************************************* + + NAME + CsrWifiSmeApBaDeleteReqSend + + DESCRIPTION + This primitive is used to delete an active block ack session + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + interfaceTag - + reason - + baSession - BA session to be deleted + +*******************************************************************************/ +#define CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__) \ + msg__ = (CsrWifiSmeApBaDeleteReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_REQ, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->reason = (reason__); \ + msg__->baSession = (baSession__); + +#define CsrWifiSmeApBaDeleteReqSendTo(dst__, src__, interfaceTag__, reason__, baSession__) \ + { \ + CsrWifiSmeApBaDeleteReq *msg__; \ + CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBaDeleteReqSend(src__, interfaceTag__, reason__, baSession__) \ + CsrWifiSmeApBaDeleteReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, reason__, baSession__) + +/******************************************************************************* + + NAME + CsrWifiSmeApBaDeleteCfmSend + + DESCRIPTION + This primitive confirms the BA is deleted + + PARAMETERS + queue - Destination Task Queue + interfaceTag - + status - Reports the result of the request + baSession - deleted BA session + +*******************************************************************************/ +#define CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__) \ + msg__ = (CsrWifiSmeApBaDeleteCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteCfm)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_CFM, dst__, src__); \ + msg__->interfaceTag = (interfaceTag__); \ + msg__->status = (status__); \ + msg__->baSession = (baSession__); + +#define CsrWifiSmeApBaDeleteCfmSendTo(dst__, src__, interfaceTag__, status__, baSession__) \ + { \ + CsrWifiSmeApBaDeleteCfm *msg__; \ + CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__); \ + CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ + } + +#define CsrWifiSmeApBaDeleteCfmSend(dst__, interfaceTag__, status__, baSession__) \ + CsrWifiSmeApBaDeleteCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, baSession__) + /******************************************************************************* NAME diff --git a/drivers/staging/csr/csr_wifi_sme_ap_prim.h b/drivers/staging/csr/csr_wifi_sme_ap_prim.h index 3310cd287fdc..41594395c651 100644 --- a/drivers/staging/csr/csr_wifi_sme_ap_prim.h +++ b/drivers/staging/csr/csr_wifi_sme_ap_prim.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -95,6 +95,23 @@ typedef CsrUint8 CsrWifiSmeApAuthType; #define CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL ((CsrWifiSmeApAuthType) 0x01) #define CSR_WIFI_SME_AP_AUTH_TYPE_WEP ((CsrWifiSmeApAuthType) 0x02) +/******************************************************************************* + + NAME + CsrWifiSmeApDirection + + DESCRIPTION + Definition of Direction + + VALUES + CSR_WIFI_AP_DIRECTION_RECEIPIENT - Receipient + CSR_WIFI_AP_DIRECTION_ORIGINATOR - Originator + +*******************************************************************************/ +typedef CsrUint8 CsrWifiSmeApDirection; +#define CSR_WIFI_AP_DIRECTION_RECEIPIENT ((CsrWifiSmeApDirection) 0x00) +#define CSR_WIFI_AP_DIRECTION_ORIGINATOR ((CsrWifiSmeApDirection) 0x01) + /******************************************************************************* NAME @@ -302,6 +319,28 @@ typedef struct CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities; } CsrWifiSmeApAuthPers; +/******************************************************************************* + + NAME + CsrWifiSmeApBaSession + + DESCRIPTION + + MEMBERS + peerMacAddress - Indicates MAC address of the peer station + tid - Specifies the TID of the MSDUs for which this Block Ack has + been set up. Range: 0-15 + direction - Specifies if the AP is the originator or the recipient of + the data stream that uses the Block Ack. + +*******************************************************************************/ +typedef struct +{ + CsrWifiMacAddress peerMacAddress; + CsrUint8 tid; + CsrWifiSmeApDirection direction; +} CsrWifiSmeApBaSession; + /******************************************************************************* NAME @@ -456,9 +495,11 @@ typedef struct #define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ ((CsrWifiSmeApPrim) (0x0004 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_SME_AP_STA_DISCONNECT_REQ ((CsrWifiSmeApPrim) (0x0005 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ ((CsrWifiSmeApPrim) (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ ((CsrWifiSmeApPrim) (0x0007 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_BA_DELETE_REQ ((CsrWifiSmeApPrim) (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) /* Upstream */ #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) @@ -473,8 +514,10 @@ typedef struct #define CSR_WIFI_SME_AP_STA_DISCONNECT_CFM ((CsrWifiSmeApPrim)(0x0007 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM ((CsrWifiSmeApPrim)(0x0008 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) #define CSR_WIFI_SME_AP_ERROR_IND ((CsrWifiSmeApPrim)(0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM ((CsrWifiSmeApPrim)(0x000A + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) +#define CSR_WIFI_SME_AP_BA_DELETE_CFM ((CsrWifiSmeApPrim)(0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST (0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) +#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST (0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) #define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) @@ -655,6 +698,49 @@ typedef struct CsrWifiSmeWpsConfig wpsConfig; } CsrWifiSmeApWpsConfigurationReq; +/******************************************************************************* + + NAME + CsrWifiSmeApActiveBaGetReq + + DESCRIPTION + This primitive used to retrieve information related to the active block + ack sessions + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; +} CsrWifiSmeApActiveBaGetReq; + +/******************************************************************************* + + NAME + CsrWifiSmeApBaDeleteReq + + DESCRIPTION + This primitive is used to delete an active block ack session + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + reason - + baSession - BA session to be deleted + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrWifiSmeIEEE80211Reason reason; + CsrWifiSmeApBaSession baSession; +} CsrWifiSmeApBaDeleteReq; + /******************************************************************************* NAME @@ -895,6 +981,55 @@ typedef struct CsrResult status; } CsrWifiSmeApErrorInd; +/******************************************************************************* + + NAME + CsrWifiSmeApActiveBaGetCfm + + DESCRIPTION + This primitive carries the information related to the active ba sessions + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - Reports the result of the request + activeBaCount - Number of active block ack session + activeBaSessions - Points to a buffer containing an array of + CsrWifiSmeApBaSession structures. + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrUint16 activeBaCount; + CsrWifiSmeApBaSession *activeBaSessions; +} CsrWifiSmeApActiveBaGetCfm; + +/******************************************************************************* + + NAME + CsrWifiSmeApBaDeleteCfm + + DESCRIPTION + This primitive confirms the BA is deleted + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + interfaceTag - + status - Reports the result of the request + baSession - deleted BA session + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint16 interfaceTag; + CsrResult status; + CsrWifiSmeApBaSession baSession; +} CsrWifiSmeApBaDeleteCfm; + #ifdef __cplusplus } diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.c b/drivers/staging/csr/csr_wifi_sme_converter_init.c index bafd1b411a90..6897a77faf27 100644 --- a/drivers/staging/csr/csr_wifi_sme_converter_init.c +++ b/drivers/staging/csr/csr_wifi_sme_converter_init.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -79,6 +79,7 @@ static CsrMsgConvMsgEntry csrwifisme_conv_lut[] = { { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree }, { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree }, { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree }, + { CSR_WIFI_SME_SET_REQ, CsrWifiSmeSetReqSizeof, CsrWifiSmeSetReqSer, CsrWifiSmeSetReqDes, CsrWifiSmeSetReqSerFree }, { CSR_WIFI_SME_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree }, { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree }, { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree }, @@ -159,11 +160,11 @@ CsrMsgConvMsgEntry* CsrWifiSmeConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16 { if (msgType & CSR_PRIM_UPSTREAM) { - CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT; - if (index < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) && - csrwifisme_conv_lut[index].msgType == msgType) + CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT; + if (idx < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) && + csrwifisme_conv_lut[idx].msgType == msgType) { - return &csrwifisme_conv_lut[index]; + return &csrwifisme_conv_lut[idx]; } } else diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.h b/drivers/staging/csr/csr_wifi_sme_converter_init.h index 8637eb7baafe..fb895dec7688 100644 --- a/drivers/staging/csr/csr_wifi_sme_converter_init.h +++ b/drivers/staging/csr/csr_wifi_sme_converter_init.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details diff --git a/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c index c8e66be899cd..93e75e5ace18 100644 --- a/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c +++ b/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -172,6 +172,13 @@ void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message p->wpsConfig.secondaryDeviceType = NULL; break; } + case CSR_WIFI_SME_SET_REQ: + { + CsrWifiSmeSetReq *p = (CsrWifiSmeSetReq *)message; + CsrPmemFree(p->data); + p->data = NULL; + break; + } default: break; diff --git a/drivers/staging/csr/csr_wifi_sme_lib.h b/drivers/staging/csr/csr_wifi_sme_lib.h index 16053fb6ed43..67dcb48448c3 100644 --- a/drivers/staging/csr/csr_wifi_sme_lib.h +++ b/drivers/staging/csr/csr_wifi_sme_lib.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -3442,6 +3442,39 @@ extern const CsrCharString *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWN #define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \ CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanResultsCount__, scanResults__) +/******************************************************************************* + + NAME + CsrWifiSmeSetReqSend + + DESCRIPTION + Used to pass custom data to the SME. Format is the same as 802.11 Info + Elements => | Id | Length | Data + 1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01 + (0x00|0x01)" + + PARAMETERS + queue - Message Source Task Queue (Cfm's will be sent to this Queue) + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes + +*******************************************************************************/ +#define CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__) \ + msg__ = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq)); \ + CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SET_REQ, dst__, src__); \ + msg__->dataLength = (dataLength__); \ + msg__->data = (data__); + +#define CsrWifiSmeSetReqSendTo(dst__, src__, dataLength__, data__) \ + { \ + CsrWifiSmeSetReq *msg__; \ + CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__); \ + CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ + } + +#define CsrWifiSmeSetReqSend(src__, dataLength__, data__) \ + CsrWifiSmeSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, dataLength__, data__) + /******************************************************************************* NAME diff --git a/drivers/staging/csr/csr_wifi_sme_prim.h b/drivers/staging/csr/csr_wifi_sme_prim.h index 4bc8520dbd0c..8ffa50a6c048 100644 --- a/drivers/staging/csr/csr_wifi_sme_prim.h +++ b/drivers/staging/csr/csr_wifi_sme_prim.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -1434,7 +1434,7 @@ typedef CsrUint8 CsrWifiSmeWepCredentialType; CsrWifiSmeWmmMode DESCRIPTION - Defines bits for wmmModeMask: enable/disable WMM features. + Defines bits for CsrWifiSmeWmmModeMask: enable/disable WMM features. VALUES CSR_WIFI_SME_WMM_MODE_DISABLED - Disables the WMM features. @@ -2410,40 +2410,6 @@ typedef struct CsrUint16 maxPassiveChannelTimeTu; } CsrWifiSmeScanConfigData; -/******************************************************************************* - - NAME - CsrWifiSmeStaConfig - - DESCRIPTION - Station configuration options in the SME - - MEMBERS - connectionQualityRssiChangeTrigger - Sets the difference of RSSI - measurements which triggers reports - from the Firmware - connectionQualitySnrChangeTrigger - Sets the difference of SNR measurements - which triggers reports from the - Firmware - wmmModeMask - Mask containing one or more values from - CsrWifiSmeWmmMode - ifIndex - Indicates the band of frequencies used - allowUnicastUseGroupCipher - If TRUE, it allows to use groupwise - keys if no pairwise key is specified - enableOpportunisticKeyCaching - If TRUE, enables the Opportunistic Key - Caching feature - -*******************************************************************************/ -typedef struct -{ - CsrUint8 connectionQualityRssiChangeTrigger; - CsrUint8 connectionQualitySnrChangeTrigger; - CsrUint8 wmmModeMask; - CsrWifiSmeRadioIF ifIndex; - CsrBool allowUnicastUseGroupCipher; - CsrBool enableOpportunisticKeyCaching; -} CsrWifiSmeStaConfig; - /******************************************************************************* NAME @@ -3197,6 +3163,40 @@ typedef struct } deviceInfo; } CsrWifiSmeScanResult; +/******************************************************************************* + + NAME + CsrWifiSmeStaConfig + + DESCRIPTION + Station configuration options in the SME + + MEMBERS + connectionQualityRssiChangeTrigger - Sets the difference of RSSI + measurements which triggers reports + from the Firmware + connectionQualitySnrChangeTrigger - Sets the difference of SNR measurements + which triggers reports from the + Firmware + wmmModeMask - Mask containing one or more values from + CsrWifiSmeWmmMode + ifIndex - Indicates the band of frequencies used + allowUnicastUseGroupCipher - If TRUE, it allows to use groupwise + keys if no pairwise key is specified + enableOpportunisticKeyCaching - If TRUE, enables the Opportunistic Key + Caching feature + +*******************************************************************************/ +typedef struct +{ + CsrUint8 connectionQualityRssiChangeTrigger; + CsrUint8 connectionQualitySnrChangeTrigger; + CsrWifiSmeWmmModeMask wmmModeMask; + CsrWifiSmeRadioIF ifIndex; + CsrBool allowUnicastUseGroupCipher; + CsrBool enableOpportunisticKeyCaching; +} CsrWifiSmeStaConfig; + /******************************************************************************* NAME @@ -3393,9 +3393,10 @@ typedef struct #define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0034 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ ((CsrWifiSmePrim) (0x0035 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) #define CSR_WIFI_SME_WPS_CONFIGURATION_REQ ((CsrWifiSmePrim) (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) +#define CSR_WIFI_SME_SET_REQ ((CsrWifiSmePrim) (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) +#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) /* Upstream */ #define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) @@ -4809,6 +4810,30 @@ typedef struct CsrWifiSmeWpsConfig wpsConfig; } CsrWifiSmeWpsConfigurationReq; +/******************************************************************************* + + NAME + CsrWifiSmeSetReq + + DESCRIPTION + Used to pass custom data to the SME. Format is the same as 802.11 Info + Elements => | Id | Length | Data + 1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01 + (0x00|0x01)" + + MEMBERS + common - Common header for use with the CsrWifiFsm Module + dataLength - Number of bytes in the buffer pointed to by 'data' + data - Pointer to the buffer containing 'dataLength' bytes + +*******************************************************************************/ +typedef struct +{ + CsrWifiFsmEvent common; + CsrUint32 dataLength; + CsrUint8 *data; +} CsrWifiSmeSetReq; + /******************************************************************************* NAME diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.c b/drivers/staging/csr/csr_wifi_sme_serialize.c index 489c378186bd..5c1bc31f2dd6 100644 --- a/drivers/staging/csr/csr_wifi_sme_serialize.c +++ b/drivers/staging/csr/csr_wifi_sme_serialize.c @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -1356,7 +1356,7 @@ CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg) bufferSize += 2; /* CsrUint16 primitive->interfaceTag */ bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ - bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */ + bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */ bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */ bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */ @@ -1898,6 +1898,62 @@ void CsrWifiSmeWpsConfigurationReqSerFree(void *voidPrimitivePointer) } +CsrSize CsrWifiSmeSetReqSizeof(void *msg) +{ + CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) msg; + CsrSize bufferSize = 2; + + /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ + bufferSize += 4; /* CsrUint32 primitive->dataLength */ + bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */ + return bufferSize; +} + + +CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg) +{ + CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *)msg; + *len = 0; + CsrUint16Ser(ptr, len, primitive->common.type); + CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength); + if (primitive->dataLength) + { + CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength))); + } + return(ptr); +} + + +void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize length) +{ + CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq)); + CsrSize offset; + offset = 0; + + CsrUint16Des(&primitive->common.type, buffer, &offset); + CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset); + if (primitive->dataLength) + { + primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength); + CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength))); + } + else + { + primitive->data = NULL; + } + + return primitive; +} + + +void CsrWifiSmeSetReqSerFree(void *voidPrimitivePointer) +{ + CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) voidPrimitivePointer; + CsrPmemFree(primitive->data); + CsrPmemFree(primitive); +} + + CsrSize CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg) { CsrSize bufferSize = 2; @@ -5085,7 +5141,7 @@ CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg) bufferSize += 2; /* CsrResult primitive->status */ bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ - bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */ + bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */ bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */ bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */ diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.h b/drivers/staging/csr/csr_wifi_sme_serialize.h index c2d7fd68c4ae..0080bf43a6c4 100644 --- a/drivers/staging/csr/csr_wifi_sme_serialize.h +++ b/drivers/staging/csr/csr_wifi_sme_serialize.h @@ -1,6 +1,6 @@ /***************************************************************************** - (c) Cambridge Silicon Radio Limited 2011 + (c) Cambridge Silicon Radio Limited 2012 All rights reserved and confidential information of CSR Refer to LICENSE.txt included with this source for details @@ -300,6 +300,11 @@ extern void* CsrWifiSmeWpsConfigurationReqDes(CsrUint8 *buffer, CsrSize len); extern CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg); extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg); +extern CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg); +extern void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize len); +extern CsrSize CsrWifiSmeSetReqSizeof(void *msg); +extern void CsrWifiSmeSetReqSerFree(void *msg); + #define CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser #define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c index 4545fb2b063b..fbe86301816c 100644 --- a/drivers/staging/csr/drv.c +++ b/drivers/staging/csr/drv.c @@ -47,12 +47,7 @@ int buswidth = 0; /* 0 means use default, values 1,4 */ int sdio_clock = 50000; /* kHz */ int unifi_debug = 0; -/* - * fw_init prevents f/w initialisation on error. - * Unless necessary, avoid usage in the CSR_SME_EMB build because it prevents - * UniFi initialisation after getting out of suspend and also leaves - * UniFi powered when the module unloads. - */ +/* fw_init prevents f/w initialisation on error. */ int fw_init[MAX_UNIFI_DEVS] = {-1, -1}; int use_5g = 0; int led_mask = 0; /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */ @@ -67,6 +62,12 @@ int sdio_byte_mode = 0; /* 0 for block mode + padding, 1 for byte mode */ int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ int bh_priority = -1; +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +#define UNIFI_LOG_HIP_SIGNALS_FILTER_SIGNAL (1 << 0) +#define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1) +#define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2) +int log_hip_signals = 0; +#endif MODULE_DESCRIPTION("CSR UniFi (SDIO)"); @@ -87,6 +88,9 @@ module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR); module_param(coredump_max, int, S_IRUGO|S_IWUSR); module_param(run_bh_once, int, S_IRUGO|S_IWUSR); module_param(bh_priority, int, S_IRUGO|S_IWUSR); +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +module_param(log_hip_signals, int, S_IRUGO|S_IWUSR); +#endif MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode"); MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)"); @@ -105,6 +109,10 @@ MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO"); MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate"); MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts"); MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority"); +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging"); +#endif + /* Callback for event logging to UDI clients */ static void udi_log_event(ul_client_t *client, @@ -193,6 +201,54 @@ trace_putest_cmdid(unifi_putest_command_t putest_cmd) } } +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +int uf_register_hip_offline_debug(unifi_priv_t *priv) +{ + ul_client_t *udi_cli; + int i; + + udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); + if (udi_cli == NULL) { + /* Too many clients already using this device */ + unifi_error(priv, "Too many UDI clients already open\n"); + return -ENOSPC; + } + unifi_trace(priv, UDBG1, "Offline HIP client is registered\n"); + + down(&priv->udi_logging_mutex); + udi_cli->event_hook = udi_log_event; + unifi_set_udi_hook(priv->card, logging_handler); + /* Log all signals by default */ + for (i = 0; i < SIG_FILTER_SIZE; i++) { + udi_cli->signal_filter[i] = 0xFFFF; + } + priv->logging_client = udi_cli; + up(&priv->udi_logging_mutex); + + return 0; +} + +int uf_unregister_hip_offline_debug(unifi_priv_t *priv) +{ + ul_client_t *udi_cli = priv->logging_client; + if (udi_cli == NULL) + { + unifi_error(priv, "Unknown HIP client unregister request\n"); + return -ERANGE; + } + + unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n"); + + down(&priv->udi_logging_mutex); + priv->logging_client = NULL; + udi_cli->event_hook = NULL; + up(&priv->udi_logging_mutex); + + ul_deregister_client(udi_cli); + + return 0; +} +#endif /* @@ -312,7 +368,6 @@ unifi_open(struct inode *inode, struct file *file) } /* unifi_open() */ - static int unifi_release(struct inode *inode, struct file *filp) { @@ -354,6 +409,15 @@ unifi_release(struct inode *inode, struct file *filp) } uf_sme_deinit(priv); + + /* It is possible that a blocking SME request was made from another process + * which did not get read by the SME before the WifiOffReq. + * So check for a pending request which will go unanswered and cancel + * the wait for event. As only one blocking request can be in progress at + * a time, up to one event should be completed. + */ + uf_sme_cancel_request(priv, 0); + #endif /* CSR_SME_USERSPACE */ } else { @@ -979,6 +1043,14 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto out; } +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + if (log_hip_signals) { + unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n"); + r = -EFAULT; + goto out; + } +#endif + down(&priv->udi_logging_mutex); if (int_param) { pcli->event_hook = udi_log_event; @@ -1264,6 +1336,11 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) unifi_info(priv, "UniFi ready\n"); +#ifdef ANDROID_BUILD + /* Release the wakelock */ + unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n"); + wake_unlock(&unifi_sdio_wake_lock); +#endif #ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */ { struct net_device *dev = priv->netdev[interfaceTag]; @@ -1720,6 +1797,40 @@ udi_log_event(ul_client_t *pcli, return; } +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + /* When HIP offline signal logging is enabled, omnicli cannot run */ + if (log_hip_signals) + { + /* Add timestamp */ + if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP) + { + int timestamp = jiffies_to_msecs(jiffies); + unifi_debug_log_to_buf("T:"); + unifi_debug_log_to_buf("%04X%04X ", *(((CsrUint16*)×tamp) + 1), + *(CsrUint16*)×tamp); + } + + /* Add signal */ + unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ", + dir ? "T" : "F", + *(CsrUint16*)signal, + *(CsrUint16*)(signal + 2), + *(CsrUint16*)(signal + 4)); + unifi_debug_hex_to_buf(signal + 6, signal_len - 6); + + /* Add bulk data (assume 1 bulk data per signal) */ + if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) && + (bulkdata->d[0].data_length > 0)) + { + unifi_debug_log_to_buf("\nD:"); + unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length); + } + unifi_debug_log_to_buf("\n"); + + return; + } +#endif + #ifdef CSR_NATIVE_LINUX uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir); #endif @@ -1950,7 +2061,7 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) priv->unifiudi_cdev.owner = THIS_MODULE; devno = MKDEV(MAJOR(unifi_first_devno), - MINOR(unifi_first_devno) + (bus_id * MAX_UNIFI_DEVS) + 1); + MINOR(unifi_first_devno) + (bus_id * 2) + 1); r = cdev_add(&priv->unifiudi_cdev, devno, 1); if (r) { device_destroy(unifi_class, priv->unifi_cdev.dev); @@ -2081,7 +2192,9 @@ unifi_load(void) #endif printk("CSR native no WEXT support\n"); #endif - +#ifdef CSR_WIFI_SPLIT_PATCH + printk("Split patch support\n"); +#endif printk("Kernel %d.%d.%d\n", ((LINUX_VERSION_CODE) >> 16) & 0xff, ((LINUX_VERSION_CODE) >> 8) & 0xff, diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c index 4ac3c89baa5d..03da0d5c247a 100644 --- a/drivers/staging/csr/firmware.c +++ b/drivers/staging/csr/firmware.c @@ -296,7 +296,18 @@ uf_run_unifihelper(unifi_priv_t *priv) #endif } /* uf_run_unifihelper() */ +#ifdef CSR_WIFI_SPLIT_PATCH +static CsrBool is_ap_mode(unifi_priv_t *priv) +{ + if (priv == NULL || priv->interfacePriv[0] == NULL) + { + return FALSE; + } + /* Test for mode requiring AP patch */ + return(CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode)); +} +#endif /* * --------------------------------------------------------------------------- @@ -334,8 +345,13 @@ int uf_request_firmware_files(unifi_priv_t *priv, int is_fw) if (is_fw == UNIFI_FW_STA) { /* Free kernel buffer and reload */ uf_release_firmware(priv, &priv->fw_sta); +#ifdef CSR_WIFI_SPLIT_PATCH scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", - postfix, "sta.xbv"); + postfix, (is_ap_mode(priv) ? "ap.xbv" : "staonly.xbv") ); +#else + scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", + postfix, "sta.xbv" ); +#endif r = request_firmware(&fw_entry, fw_name, priv->unifi_device); if (r == 0) { priv->fw_sta.dl_data = fw_entry->data; diff --git a/drivers/staging/csr/io.c b/drivers/staging/csr/io.c index fbf1b2099cc9..f489ade7f1ba 100644 --- a/drivers/staging/csr/io.c +++ b/drivers/staging/csr/io.c @@ -407,6 +407,13 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) INIT_WORK(&priv->rx_work_struct, rx_wq_handler); #endif +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + if (log_hip_signals) + { + uf_register_hip_offline_debug(priv); + } +#endif + /* Initialise the SME related threads and parameters */ r = uf_sme_init(priv); if (r) { @@ -431,6 +438,12 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) return priv; failed4: +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +if (log_hip_signals) +{ + uf_unregister_hip_offline_debug(priv); +} +#endif #ifdef CSR_WIFI_RX_PATH_SPLIT flush_workqueue(priv->rx_workqueue); destroy_workqueue(priv->rx_workqueue); @@ -547,6 +560,13 @@ cleanup_unifi_sdio(unifi_priv_t *priv) priv->smepriv = NULL; #endif +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + if (log_hip_signals) + { + uf_unregister_hip_offline_debug(priv); + } +#endif + /* Free any packets left in the Rx queues */ for(i=0;ista_wmm_capabilities = 0; +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_SUPPORT_SME)) priv->wapi_multicast_filter = 0; priv->wapi_unicast_filter = 0; priv->wapi_unicast_queued_pkt_filter = 0; +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + priv->isWapiConnection = FALSE; +#endif +#endif /* Enable all queues by default */ interfacePriv->queueEnabled[0] = 1; @@ -450,7 +455,15 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) spin_lock_init(&priv->send_signal_lock); spin_lock_init(&priv->m4_lock); - spin_lock_init(&priv->ba_lock); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) + sema_init(&priv->ba_mutex, 1); +#else + init_MUTEX(&priv->ba_mutex); +#endif + +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + spin_lock_init(&priv->wapi_lock); +#endif #ifdef CSR_SUPPORT_SME spin_lock_init(&priv->staRecord_lock); @@ -472,6 +485,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) /* Create m4 buffering work structure */ INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq); + +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + /* Create work structure to buffer the WAPI data packets to be sent to SME for encryption */ + INIT_WORK(&interfacePriv->send_pkt_to_encrypt, uf_send_pkt_to_encrypt); +#endif #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) @@ -504,6 +522,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) } #endif /* CSR_SUPPORT_WEXT */ +#ifdef CSR_WIFI_SPLIT_PATCH + /* set it to some invalid value */ + priv->pending_mode_set.common.destination = 0xaaaa; +#endif + return priv; } /* uf_alloc_netdevice() */ @@ -655,6 +678,19 @@ uf_free_netdevice(unifi_priv_t *priv) } spin_unlock_irqrestore(&priv->m4_lock, flags); +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + /* Free any bulkdata buffers allocated for M4 caching */ + spin_lock_irqsave(&priv->wapi_lock, flags); + for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { + netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; + if (interfacePriv->wapi_unicast_bulk_data.data_length > 0) { + unifi_trace(priv, UDBG5, "uf_free_netdevice: free WAPI PKT bulk data %d\n", i); + unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data); + } + } + spin_unlock_irqrestore(&priv->wapi_lock, flags); +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) #ifdef CONFIG_NET_SCHED /* Unregister the qdisc operations */ @@ -1556,7 +1592,7 @@ int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk /* IF Qos Data or Qos Null Data then set QosControl field */ if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) { - if (priority >= 7) { + if (priority > 7) { unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority); qc |= 7; } else { @@ -1628,6 +1664,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED; CsrInt8 protection; netInterface_priv_t *interfacePriv = NULL; + CSR_RATE TransmitRate = (CSR_RATE)0; unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n"); @@ -1780,6 +1817,63 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr return 0; } #endif + }/*EAPOL or WAI packet*/ + +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && \ + (priv->wapi_unicast_filter) && \ + (proto != ETH_P_PAE) && \ + (proto != ETH_P_WAI) && \ + (skb->len > 0)) + { + CSR_SIGNAL signal; + CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; + netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]); + + unifi_trace(priv, UDBG4, "send_ma_pkt_request() - WAPI unicast data packet when USKID = 1 \n"); + + /* initialize signal to zero */ + memset(&signal, 0, sizeof(CSR_SIGNAL)); + /* Frame MA_PACKET request */ + signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; + signal.SignalPrimitiveHeader.ReceiverProcessId = 0; + signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; + + /* Fill the MA-PACKET.req */ + req->TransmissionControl = 0; + req->Priority = priority; + unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority); + req->TransmitRate = (CSR_RATE) 0; /* rate selected by firmware */ + req->HostTag = 0xffffffff; /* Ask for a new HostTag */ + /* RA address matching with address 1 of Mac header */ + memcpy(req->Ra.x, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); + + /* Store the M4-PACKET.req for later */ + spin_lock(&priv->wapi_lock); + interfacePriv->wapi_unicast_ma_pkt_sig = signal; + interfacePriv->wapi_unicast_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; + interfacePriv->wapi_unicast_bulk_data.data_length = bulkdata.d[0].data_length; + interfacePriv->wapi_unicast_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; + interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; + spin_unlock(&priv->wapi_lock); + + /* Signal the workqueue to call CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(). + * It cannot be called directly from the tx path because it + * does a non-atomic kmalloc via the framework's CsrPmemAlloc(). + */ + queue_work(priv->unifi_workqueue, &netpriv->send_pkt_to_encrypt); + + return 0; + } +#endif + + if(priv->cmanrTestMode) + { + TransmitRate = priv->cmanrTestModeTransmitRate; + unifi_trace(priv, UDBG2, "send_ma_pkt_request: cmanrTestModeTransmitRate = %d TransmitRate=%d\n", + priv->cmanrTestModeTransmitRate, + TransmitRate + ); } /* Send UniFi msg */ @@ -1789,7 +1883,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr 0xffffffff, /* Ask for a new HostTag */ interfaceTag, transmissionControl, - (CSR_RATE)0, + TransmitRate, priority, priv->netdev_client->sender_id, &bulkdata); @@ -1900,8 +1994,22 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) #endif /* CONFIG_NET_SCHED */ if (result == NETDEV_TX_OK) { +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + /* Don't update the tx stats when the pkt is to be sent for sw encryption*/ + if (!((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && + (priv->wapi_unicast_filter == 1))) + { + dev->trans_start = jiffies; + /* Should really count tx stats in the UNITDATA.status signal but + * that doesn't have the length. + */ + interfacePriv->stats.tx_packets++; + /* count only the packet payload */ + interfacePriv->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; + } +#else + dev->trans_start = jiffies; /* * Should really count tx stats in the UNITDATA.status signal but @@ -1910,7 +2018,7 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) interfacePriv->stats.tx_packets++; /* count only the packet payload */ interfacePriv->stats.tx_bytes += skb->len; - +#endif } else if (result < 0) { /* Failed to send: fh queue was full, and the skb was discarded. @@ -2118,6 +2226,13 @@ indicate_rx_skb(unifi_priv_t *priv, CsrUint16 ifTag, CsrUint8* dst_a, CsrUint8* } + if(priv->cmanrTestMode) + { + const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; + priv->cmanrTestModeTransmitRate = pkt_ind->ReceivedRate; + unifi_trace(priv, UDBG2, "indicate_rx_skb: cmanrTestModeTransmitRate=%d\n", priv->cmanrTestModeTransmitRate); + } + /* Pass SKB up the stack */ #ifdef CSR_WIFI_USE_NETIF_RX netif_rx(skb); @@ -2780,36 +2895,17 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d if((dataFrameType == QOS_DATA) || (dataFrameType == QOS_DATA_NULL)){ /* - QoS control field is offset from frame control by 2 (frame control) - + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN - */ + * QoS control field is offset from frame control by 2 (frame control) + * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN + */ if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){ qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30); } else{ qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24); } - - if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){ - CSR_PRIORITY priority; - unifi_TrafficQueue priority_q; - priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) - ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){ - unsigned long lock_flags; - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - srcStaInfo->uapsdSuspended = TRUE; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - unifi_trace(priv, UDBG3, "%s: qos Trigger Frame received while DTIM Active for staid: 0x%x\n",__FUNCTION__,srcStaInfo->aid); - } - } - else{ - - - unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl); - uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag); - } + unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl); + uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag); } } } @@ -2829,7 +2925,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d ba_addr = bssid; } - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ ba_session = interfacePriv->ba_session_rx[ba_session_idx]; if (ba_session){ @@ -2842,14 +2938,14 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d frame_desc.active = TRUE; unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx); process_ba_frame(priv, interfacePriv, ba_session, &frame_desc); - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); process_ba_complete(priv, interfacePriv); break; } } } if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__); process_amsdu(priv, signal, bulkdata); } @@ -2865,7 +2961,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d * And also this code here takes care that timeout check is made for all * the receive indications */ - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){ ba_session_rx_struct *ba_session; ba_session = interfacePriv->ba_session_rx[i]; @@ -2873,8 +2969,8 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d check_ba_frame_age_timeout(priv, interfacePriv, ba_session); } } + up(&priv->ba_mutex); process_ba_complete(priv, interfacePriv); - spin_unlock(&priv->ba_lock); func_exit(); } @@ -3879,7 +3975,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, } sn = pkt_err_ind->SequenceNumber; - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); /* To find the right ba_session loop through the BA sessions, compare MAC address and tID */ for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ ba_session = interfacePriv->ba_session_rx[ba_session_idx]; @@ -3894,7 +3990,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, } } - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); process_ba_complete(priv, interfacePriv); func_exit(); } diff --git a/drivers/staging/csr/os.c b/drivers/staging/csr/os.c index 6dfce4226750..f5a9352ce784 100644 --- a/drivers/staging/csr/os.c +++ b/drivers/staging/csr/os.c @@ -204,12 +204,10 @@ extern int unifi_debug; (_s)[DEBUG_BUFFER_SIZE - 1] = 0; \ } \ } while (0) -#endif /* UNIFI_DEBUG */ void unifi_error(void* ospriv, const char *fmt, ...) { -#ifdef UNIFI_DEBUG unifi_priv_t *priv = (unifi_priv_t*) ospriv; char s[DEBUG_BUFFER_SIZE]; va_list args; @@ -230,13 +228,11 @@ unifi_error(void* ospriv, const char *fmt, ...) FORMAT_TRACE(s, len, args, fmt); printk("%s", s); -#endif /* UNIFI_DEBUG */ } void unifi_warning(void* ospriv, const char *fmt, ...) { -#ifdef UNIFI_DEBUG unifi_priv_t *priv = (unifi_priv_t*) ospriv; char s[DEBUG_BUFFER_SIZE]; va_list args; @@ -259,14 +255,12 @@ unifi_warning(void* ospriv, const char *fmt, ...) FORMAT_TRACE(s, len, args, fmt); printk("%s", s); -#endif /* UNIFI_DEBUG */ } void unifi_notice(void* ospriv, const char *fmt, ...) { -#ifdef UNIFI_DEBUG unifi_priv_t *priv = (unifi_priv_t*) ospriv; char s[DEBUG_BUFFER_SIZE]; va_list args; @@ -289,14 +283,12 @@ unifi_notice(void* ospriv, const char *fmt, ...) FORMAT_TRACE(s, len, args, fmt); printk("%s", s); -#endif /* UNIFI_DEBUG */ } void unifi_info(void* ospriv, const char *fmt, ...) { -#ifdef UNIFI_DEBUG unifi_priv_t *priv = (unifi_priv_t*) ospriv; char s[DEBUG_BUFFER_SIZE]; va_list args; @@ -319,14 +311,12 @@ unifi_info(void* ospriv, const char *fmt, ...) FORMAT_TRACE(s, len, args, fmt); printk("%s", s); -#endif /* UNIFI_DEBUG */ } /* debugging */ void unifi_trace(void* ospriv, int level, const char *fmt, ...) { -#ifdef UNIFI_DEBUG unifi_priv_t *priv = (unifi_priv_t*) ospriv; char s[DEBUG_BUFFER_SIZE]; va_list args; @@ -351,9 +341,23 @@ unifi_trace(void* ospriv, int level, const char *fmt, ...) printk("%s", s); } -#endif /* UNIFI_DEBUG */ } +#else + +void +unifi_error_nop(void* ospriv, const char *fmt, ...) +{ +} + +void +unifi_trace_nop(void* ospriv, int level, const char *fmt, ...) +{ +} + +#endif /* UNIFI_DEBUG */ + + /* * --------------------------------------------------------------------------- * diff --git a/drivers/staging/csr/putest.c b/drivers/staging/csr/putest.c index 1b2c7c299a6c..22614e7e8f7e 100644 --- a/drivers/staging/csr/putest.c +++ b/drivers/staging/csr/putest.c @@ -180,8 +180,9 @@ int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg) "unifi_putest_gp_read16: Failed to get the params\n"); return -EFAULT; } - + CsrSdioClaim(priv->sdio); csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult); @@ -240,8 +241,9 @@ int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg) } unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data); - + CsrSdioClaim(priv->sdio); csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult); @@ -265,7 +267,7 @@ int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg) unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed); CsrSdioClaim(priv->sdio); - csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed); + csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000); CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, @@ -304,7 +306,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg) /* Application may have stopped the XAPs, but they are needed for reset */ if (already_in_test) { + CsrSdioClaim(priv->sdio); csrResult = unifi_start_processors(priv->card); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); } @@ -317,8 +321,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg) unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult); } } - + CsrSdioClaim(priv->sdio); csrResult = unifi_init(priv->card); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_putest_start: failed to init UniFi\n"); @@ -335,7 +340,9 @@ int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg) CsrResult csrResult; /* Application may have stopped the XAPs, but they are needed for reset */ + CsrSdioClaim(priv->sdio); csrResult = unifi_start_processors(priv->card); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); } @@ -428,7 +435,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) } /* Application may have stopped the XAPs, but they are needed for reset */ + CsrSdioClaim(priv->sdio); csrResult = unifi_start_processors(priv->card); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); } @@ -436,7 +445,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) /* Download the f/w. On UF6xxx this will cause the f/w file to convert * into patch format and download via the ROM boot loader */ + CsrSdioClaim(priv->sdio); csrResult = unifi_download(priv->card, 0x0c00); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_putest_dl_fw: failed to download the f/w\n"); @@ -504,7 +515,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg) priv->fw_sta.dl_len = fw_length; /* Application may have stopped the XAPs, but they are needed for reset */ + CsrSdioClaim(priv->sdio); csrResult = unifi_start_processors(priv->card); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); } @@ -512,7 +525,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg) /* Download the f/w. On UF6xxx this will cause the f/w file to convert * into patch format and download via the ROM boot loader */ + CsrSdioClaim(priv->sdio); csrResult = unifi_download(priv->card, 0x0c00); + CsrSdioRelease(priv->sdio); if (csrResult != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_putest_dl_fw_buff: failed to download the f/w\n"); @@ -581,7 +596,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg) } /* Card software reset */ + CsrSdioClaim(priv->sdio); r = unifi_card_hard_reset(priv->card); + CsrSdioRelease(priv->sdio); if (r != CSR_RESULT_SUCCESS) { unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r); } @@ -599,7 +616,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg) /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at * Raw SDIO deinit, to resume them. */ + CsrSdioClaim(priv->sdio); r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH); + CsrSdioRelease(priv->sdio); if (r != CSR_RESULT_SUCCESS) { unifi_error(priv, "Failed to stop processors\n"); } @@ -646,7 +665,9 @@ int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg) return -ENOMEM; } + CsrSdioClaim(priv->sdio); r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length); + CsrSdioRelease(priv->sdio); if (r != CSR_RESULT_SUCCESS) { unifi_error(priv, "cmd52r_block: unifi_readn failed\n"); return -EIO; diff --git a/drivers/staging/csr/sdio_emb.c b/drivers/staging/csr/sdio_emb.c index f61fdb130e61..b6a7d6f513b0 100644 --- a/drivers/staging/csr/sdio_emb.c +++ b/drivers/staging/csr/sdio_emb.c @@ -17,6 +17,7 @@ */ #include #include +#include #include "csr_wifi_hip_unifi.h" #include "unifi_priv.h" @@ -25,7 +26,16 @@ /* The function driver context, i.e the UniFi Driver */ static CsrSdioFunctionDriver *sdio_func_drv; +#ifdef CONFIG_PM +static int uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr); +#endif +/* The Android wakelock is here for completeness. Typically the MMC driver is used + * instead of sdioemb, but sdioemb may be used for CSPI. + */ +#ifdef ANDROID_BUILD +struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */ +#endif /* sdioemb driver uses POSIX error codes */ static CsrResult @@ -501,6 +511,131 @@ uf_glue_sdio_int_handler(struct sdioemb_dev *fdev) } } +#ifdef CONFIG_PM + +/* + * Power Management notifier + */ +struct uf_sdio_emb_pm_notifier +{ + struct list_head list; + + CsrSdioFunction *sdio_ctx; + struct notifier_block pm_notifier; +}; + +/* PM notifier list head */ +static struct uf_sdio_emb_pm_notifier uf_sdio_emb_pm_notifiers = { + .sdio_ctx = NULL, +}; + +/* + * --------------------------------------------------------------------------- + * uf_sdio_emb_register_pm_notifier + * uf_sdio_emb_unregister_pm_notifier + * + * Register/unregister for power management events. A list is used to + * allow multiple card instances to be supported. + * + * Arguments: + * sdio_ctx - CSR SDIO context to associate PM notifier to + * + * Returns: + * Register function returns NULL on error + * --------------------------------------------------------------------------- + */ +static struct uf_sdio_emb_pm_notifier * +uf_sdio_emb_register_pm_notifier(CsrSdioFunction *sdio_ctx) +{ + /* Allocate notifier context for this card instance */ + struct uf_sdio_emb_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_emb_pm_notifier), GFP_KERNEL); + + if (notifier_ctx) + { + notifier_ctx->sdio_ctx = sdio_ctx; + notifier_ctx->pm_notifier.notifier_call = uf_sdio_emb_power_event; + + list_add(¬ifier_ctx->list, &uf_sdio_emb_pm_notifiers.list); + + if (register_pm_notifier(¬ifier_ctx->pm_notifier)) { + printk(KERN_ERR "unifi: register_pm_notifier failed\n"); + } + } + + return notifier_ctx; +} + +static void +uf_sdio_emb_unregister_pm_notifier(CsrSdioFunction *sdio_ctx) +{ + struct uf_sdio_emb_pm_notifier *notifier_ctx; + struct list_head *node, *q; + + list_for_each_safe(node, q, &uf_sdio_emb_pm_notifiers.list) { + notifier_ctx = list_entry(node, struct uf_sdio_emb_pm_notifier, list); + + /* If it matches, unregister and free the notifier context */ + if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx) + { + if (unregister_pm_notifier(¬ifier_ctx->pm_notifier)) { + printk(KERN_ERR "unifi: unregister_pm_notifier failed\n"); + } + + /* Remove from list */ + notifier_ctx->sdio_ctx = NULL; + list_del(node); + kfree(notifier_ctx); + } + } +} + +/* + * --------------------------------------------------------------------------- + * uf_sdio_emb_power_event + * + * Handler for power management events. + * + * We need to handle suspend/resume events while the userspace is unsuspended + * to allow the SME to run its suspend/resume state machines. + * + * Arguments: + * event event ID + * + * Returns: + * Status of the event handling + * --------------------------------------------------------------------------- + */ +static int +uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct uf_sdio_emb_pm_notifier *notifier_ctx = container_of(this, + struct uf_sdio_emb_pm_notifier, + pm_notifier); + + /* Call the CSR SDIO function driver's suspend/resume method + * while the userspace is unsuspended. + */ + switch (event) { + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ ); + if (sdio_func_drv && sdio_func_drv->resume) { + sdio_func_drv->resume(notifier_ctx->sdio_ctx); + } + break; + + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ ); + if (sdio_func_drv && sdio_func_drv->suspend) { + sdio_func_drv->suspend(notifier_ctx->sdio_ctx); + } + break; + } + return NOTIFY_DONE; +} + +#endif /* CONFIG_PM */ /* * --------------------------------------------------------------------------- @@ -550,16 +685,30 @@ uf_glue_sdio_probe(struct sdioemb_dev *fdev) unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", sdio_clock); sdioemb_set_max_bus_freq(fdev, 1000 * sdio_clock); +#ifdef CONFIG_PM + /* Register to get PM events */ + if (uf_sdio_emb_register_pm_notifier(sdio_ctx) == NULL) { + unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__); + } +#endif + /* Call the main UniFi driver inserted handler */ if (sdio_func_drv && sdio_func_drv->inserted) { uf_add_os_device(fdev->slot_id, fdev->os_device); sdio_func_drv->inserted(sdio_ctx); } +#ifdef ANDROID_BUILD + /* Take the wakelock */ + unifi_trace(NULL, UDBG1, "emb probe: take wake lock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif + return 0; } /* uf_glue_sdio_probe() */ + /* * --------------------------------------------------------------------------- * uf_sdio_remove @@ -585,6 +734,11 @@ uf_sdio_remove(struct sdioemb_dev *fdev) sdio_func_drv->removed(sdio_ctx); } +#ifdef CONFIG_PM + /* Unregister for PM events */ + uf_sdio_emb_unregister_pm_notifier(sdio_ctx); +#endif + kfree(sdio_ctx); } /* uf_sdio_remove */ @@ -606,14 +760,7 @@ uf_sdio_remove(struct sdioemb_dev *fdev) static void uf_glue_sdio_suspend(struct sdioemb_dev *fdev) { - CsrSdioFunction *sdio_ctx = fdev->drv_data; - - unifi_trace(NULL, UDBG3, "Suspending...\n"); - - /* Pass event to UniFi Driver. */ - if (sdio_func_drv && sdio_func_drv->suspend) { - sdio_func_drv->suspend(sdio_ctx); - } + unifi_info(NULL, "Suspending...\n"); } /* uf_glue_sdio_suspend() */ @@ -634,14 +781,13 @@ uf_glue_sdio_suspend(struct sdioemb_dev *fdev) static void uf_glue_sdio_resume(struct sdioemb_dev *fdev) { - CsrSdioFunction *sdio_ctx = fdev->drv_data; + unifi_info(NULL, "Resuming...\n"); - unifi_trace(NULL, UDBG3, "Resuming...\n"); +#ifdef ANDROID_BUILD + unifi_trace(NULL, UDBG1, "emb resume: take wakelock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif - /* Pass event to UniFi Driver. */ - if (sdio_func_drv && sdio_func_drv->resume) { - sdio_func_drv->resume(sdio_ctx); - } } /* uf_glue_sdio_resume() */ @@ -708,6 +854,15 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) /* Save the registered driver description */ sdio_func_drv = sdio_drv; +#ifdef CONFIG_PM + /* Initialise PM notifier list */ + INIT_LIST_HEAD(&uf_sdio_emb_pm_notifiers.list); +#endif + +#ifdef ANDROID_BUILD + wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work"); +#endif + /* Register ourself with sdioemb */ r = sdioemb_driver_register(&unifi_sdioemb); if (r) { @@ -724,6 +879,10 @@ CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv) { sdioemb_driver_unregister(&unifi_sdioemb); +#ifdef ANDROID_BUILD + wake_lock_destroy(&unifi_sdio_wake_lock); +#endif + sdio_func_drv = NULL; CsrPmemFree(unifi_sdioemb.id_table); diff --git a/drivers/staging/csr/sdio_events.c b/drivers/staging/csr/sdio_events.c index e4f2d0d82fbf..6892c2e281bc 100644 --- a/drivers/staging/csr/sdio_events.c +++ b/drivers/staging/csr/sdio_events.c @@ -47,6 +47,12 @@ void unifi_suspend(void *ospriv) unifi_priv_t *priv = ospriv; int interfaceTag=0; + /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ + priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; + + unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d", + priv->wol_suspend, enable_wol ); + /* Stop network traffic. */ /* need to stop all the netdevices*/ for( interfaceTag=0;interfaceTaginterfacePriv[interfaceTag]; if (interfacePriv->netdev_registered == 1) { - netif_carrier_off(priv->netdev[interfaceTag]); + if( priv->wol_suspend ) { + unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off"); + } else { + unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off"); + netif_carrier_off(priv->netdev[interfaceTag]); + } UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } + + unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME"); + sme_sys_suspend(priv); + } /* unifi_suspend() */ @@ -76,12 +91,44 @@ void unifi_suspend(void *ospriv) void unifi_resume(void *ospriv) { unifi_priv_t *priv = ospriv; + int interfaceTag=0; int r; + int wol = priv->wol_suspend; + + unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol); + /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */ r = sme_sys_resume(priv); if (r) { unifi_error(priv, "Failed to resume UniFi\n"); } + /* Resume the network interfaces. For the cold resume case, this will + * happen upon reconnection. + */ + if (wol) { + unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier"); + + /* need to start all the netdevices*/ + for( interfaceTag=0;interfaceTaginterfacePriv[interfaceTag]; + + unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n", + interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode); + + if (interfacePriv->netdev_registered == 1) + { + netif_carrier_on(priv->netdev[interfaceTag]); + UF_NETIF_TX_START_ALL_QUEUES(priv->netdev[interfaceTag]); + } + } + + /* Kick the BH thread (with reason=host) to poll for data that may have + * arrived during a powered suspend. This caters for the case where the SME + * doesn't interact with the chip (e.g install autonomous scans) during resume. + */ + unifi_send_signal(priv->card, NULL, 0, NULL); + } + } /* unifi_resume() */ diff --git a/drivers/staging/csr/sdio_mmc.c b/drivers/staging/csr/sdio_mmc.c index c8508341597a..24be0872b0aa 100644 --- a/drivers/staging/csr/sdio_mmc.c +++ b/drivers/staging/csr/sdio_mmc.c @@ -21,19 +21,28 @@ #include #include #include +#include #include "unifi_priv.h" +#ifdef ANDROID_BUILD +struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */ +#endif static CsrSdioFunctionDriver *sdio_func_drv; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM +static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr); +#endif + /* * We need to keep track of the power on/off because we can not call * mmc_power_restore_host() when the card is already powered. * Even then, we need to patch the MMC driver to add a power_restore handler - * in the mmc_sdio_ops structure. If the MMC driver is not patched, - * mmc_power_save_host() and mmc_power_restore_host() are no-ops. + * in the mmc_sdio_ops structure. If the MMC driver before 2.6.37 is not patched, + * mmc_power_save_host() and mmc_power_restore_host() are no-ops in the kernel, + * returning immediately (at least on x86). */ static int card_is_powered = 1; #endif /* 2.6.32 */ @@ -312,17 +321,28 @@ csr_sdio_enable_hs(struct mmc_card *card) int ret; u8 speed; - if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) + if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) { + /* We've asked for HS clock rates, but controller doesn't + * claim to support it. We should limit the clock + * to 25MHz via module parameter. + */ + printk(KERN_INFO "unifi: request HS but not MMC_CAP_SD_HIGHSPEED"); return 0; + } if (!card->cccr.high_speed) return 0; +#if 1 ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); if (ret) return ret; speed |= SDIO_SPEED_EHS; +#else + /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */ + speed = SDIO_SPEED_EHS | SDIO_SPEED_SHS; +#endif ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); if (ret) @@ -346,12 +366,16 @@ csr_sdio_disable_hs(struct mmc_card *card) if (!card->cccr.high_speed) return 0; - +#if 1 ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); if (ret) return ret; speed &= ~SDIO_SPEED_EHS; +#else + /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */ + speed = SDIO_SPEED_SHS; /* clear SDIO_SPEED_EHS */ +#endif ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); if (ret) @@ -460,6 +484,7 @@ CsrSdioInterruptEnable(CsrSdioFunction *function) func_exit(); if (err) { + printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err); return ConvertSdioToCsrSdioResult(err); } #endif @@ -486,6 +511,7 @@ CsrSdioInterruptDisable(CsrSdioFunction *function) func_exit(); if (err) { + printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err); return ConvertSdioToCsrSdioResult(err); } #endif @@ -772,6 +798,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func) if (!sdio_ctx) { return; } + #ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD /* * Normally, we are not allowed to do any SDIO commands here. @@ -785,7 +812,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func) r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL); #endif if (r) { - printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts\n"); + printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts %d\n", r); } #endif @@ -824,6 +851,8 @@ csr_sdio_linux_remove_irq(CsrSdioFunction *function) struct sdio_func *func = (struct sdio_func *)function->priv; int r; + unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n"); + sdio_claim_host(func); r = sdio_release_irq(func); sdio_release_host(func); @@ -853,6 +882,8 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function) struct sdio_func *func = (struct sdio_func *)function->priv; int r; + unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n"); + /* Register our interrupt handle */ sdio_claim_host(func); r = sdio_claim_irq(func, uf_glue_sdio_int_handler); @@ -866,7 +897,133 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function) return r; } /* csr_sdio_linux_install_irq() */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM + +/* + * Power Management notifier + */ +struct uf_sdio_mmc_pm_notifier +{ + struct list_head list; + + CsrSdioFunction *sdio_ctx; + struct notifier_block pm_notifier; +}; + +/* PM notifier list head */ +static struct uf_sdio_mmc_pm_notifier uf_sdio_mmc_pm_notifiers = { + .sdio_ctx = NULL, +}; + +/* + * --------------------------------------------------------------------------- + * uf_sdio_mmc_register_pm_notifier + * uf_sdio_mmc_unregister_pm_notifier + * + * Register/unregister for power management events. A list is used to + * allow multiple card instances to be supported. + * + * Arguments: + * sdio_ctx - CSR SDIO context to associate PM notifier to + * + * Returns: + * Register function returns NULL on error + * --------------------------------------------------------------------------- + */ +static struct uf_sdio_mmc_pm_notifier * +uf_sdio_mmc_register_pm_notifier(CsrSdioFunction *sdio_ctx) +{ + /* Allocate notifier context for this card instance */ + struct uf_sdio_mmc_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_mmc_pm_notifier), GFP_KERNEL); + + if (notifier_ctx) + { + notifier_ctx->sdio_ctx = sdio_ctx; + notifier_ctx->pm_notifier.notifier_call = uf_sdio_mmc_power_event; + + list_add(¬ifier_ctx->list, &uf_sdio_mmc_pm_notifiers.list); + + if (register_pm_notifier(¬ifier_ctx->pm_notifier)) { + printk(KERN_ERR "unifi: register_pm_notifier failed\n"); + } + } + + return notifier_ctx; +} + +static void +uf_sdio_mmc_unregister_pm_notifier(CsrSdioFunction *sdio_ctx) +{ + struct uf_sdio_mmc_pm_notifier *notifier_ctx; + struct list_head *node, *q; + + list_for_each_safe(node, q, &uf_sdio_mmc_pm_notifiers.list) { + notifier_ctx = list_entry(node, struct uf_sdio_mmc_pm_notifier, list); + + /* If it matches, unregister and free the notifier context */ + if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx) + { + if (unregister_pm_notifier(¬ifier_ctx->pm_notifier)) { + printk(KERN_ERR "unifi: unregister_pm_notifier failed\n"); + } + + /* Remove from list */ + notifier_ctx->sdio_ctx = NULL; + list_del(node); + kfree(notifier_ctx); + } + } +} + +/* + * --------------------------------------------------------------------------- + * uf_sdio_mmc_power_event + * + * Handler for power management events. + * + * We need to handle suspend/resume events while the userspace is unsuspended + * to allow the SME to run its suspend/resume state machines. + * + * Arguments: + * event event ID + * + * Returns: + * Status of the event handling + * --------------------------------------------------------------------------- + */ +static int +uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct uf_sdio_mmc_pm_notifier *notifier_ctx = container_of(this, + struct uf_sdio_mmc_pm_notifier, + pm_notifier); + + /* Call the CSR SDIO function driver's suspend/resume method + * while the userspace is unsuspended. + */ + switch (event) { + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ ); + if (sdio_func_drv && sdio_func_drv->resume) { + sdio_func_drv->resume(notifier_ctx->sdio_ctx); + } + break; + + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ ); + if (sdio_func_drv && sdio_func_drv->suspend) { + sdio_func_drv->suspend(notifier_ctx->sdio_ctx); + } + break; + } + return NOTIFY_DONE; +} +#endif /* CONFIG_PM */ +#endif /* 2.6.32 */ /* * --------------------------------------------------------------------------- @@ -925,6 +1082,10 @@ uf_glue_sdio_probe(struct sdio_func *func, sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE; } + if (func->card->host->caps & MMC_CAP_SD_HIGHSPEED) { + unifi_trace(NULL, UDBG1, "MMC_CAP_SD_HIGHSPEED is available\n"); + } + #ifdef MMC_QUIRK_LENIENT_FN0 func->card->quirks |= MMC_QUIRK_LENIENT_FN0; #endif @@ -932,6 +1093,15 @@ uf_glue_sdio_probe(struct sdio_func *func, /* Pass context to the SDIO driver */ sdio_set_drvdata(func, sdio_ctx); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM + /* Register to get PM events */ + if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) { + unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__); + } +#endif +#endif + /* Register this device with the SDIO function driver */ /* Call the main UniFi driver inserted handler */ if (sdio_func_drv && sdio_func_drv->inserted) { @@ -942,6 +1112,12 @@ uf_glue_sdio_probe(struct sdio_func *func, /* We have finished, so release the SDIO driver */ sdio_release_host(func); +#ifdef ANDROID_BUILD + /* Take the wakelock */ + unifi_trace(NULL, UDBG1, "probe: take wake lock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif + func_exit(); return 0; } /* uf_glue_sdio_probe() */ @@ -980,6 +1156,13 @@ uf_glue_sdio_remove(struct sdio_func *func) sdio_func_drv->removed(sdio_ctx); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM + /* Unregister for PM events */ + uf_sdio_mmc_unregister_pm_notifier(sdio_ctx); +#endif +#endif + kfree(sdio_ctx); func_exit(); @@ -1006,7 +1189,7 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids); * --------------------------------------------------------------------------- * uf_glue_sdio_suspend * - * Card suspend callback. + * Card suspend callback. The userspace will already be suspended. * * Arguments: * dev The struct device owned by the MMC driver @@ -1018,23 +1201,9 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids); static int uf_glue_sdio_suspend(struct device *dev) { - struct sdio_func *func; - CsrSdioFunction *sdio_ctx; - func_enter(); - func = dev_to_sdio_func(dev); - WARN_ON(!func); - - sdio_ctx = sdio_get_drvdata(func); - WARN_ON(!sdio_ctx); - - unifi_trace(NULL, UDBG1, "System Suspend...\n"); - - /* Clean up the SDIO function driver */ - if (sdio_func_drv && sdio_func_drv->suspend) { - sdio_func_drv->suspend(sdio_ctx); - } + unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend"); func_exit(); return 0; @@ -1045,7 +1214,7 @@ uf_glue_sdio_suspend(struct device *dev) * --------------------------------------------------------------------------- * uf_glue_sdio_resume * - * Card resume callback. + * Card resume callback. The userspace will still be suspended. * * Arguments: * dev The struct device owned by the MMC driver @@ -1057,23 +1226,14 @@ uf_glue_sdio_suspend(struct device *dev) static int uf_glue_sdio_resume(struct device *dev) { - struct sdio_func *func; - CsrSdioFunction *sdio_ctx; - func_enter(); - func = dev_to_sdio_func(dev); - WARN_ON(!func); - - sdio_ctx = sdio_get_drvdata(func); - WARN_ON(!sdio_ctx); + unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume"); - unifi_trace(NULL, UDBG1, "System Resume...\n"); - - /* Clean up the SDIO function driver */ - if (sdio_func_drv && sdio_func_drv->resume) { - sdio_func_drv->resume(sdio_ctx); - } +#ifdef ANDROID_BUILD + unifi_trace(NULL, UDBG1, "resume: take wakelock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif func_exit(); return 0; @@ -1133,6 +1293,10 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) return CSR_SDIO_RESULT_INVALID_VALUE; } +#ifdef ANDROID_BUILD + wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work"); +#endif + /* Save the registered driver description */ /* * FIXME: @@ -1141,6 +1305,13 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) */ sdio_func_drv = sdio_drv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#ifdef CONFIG_PM + /* Initialise PM notifier list */ + INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list); +#endif +#endif + /* Register ourself with mmc_core */ r = sdio_register_driver(&unifi_driver); if (r) { @@ -1157,6 +1328,10 @@ void CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv) { printk(KERN_INFO "UniFi: unregister from MMC sdio\n"); + +#ifdef ANDROID_BUILD + wake_lock_destroy(&unifi_sdio_wake_lock); +#endif sdio_unregister_driver(&unifi_driver); sdio_func_drv = NULL; diff --git a/drivers/staging/csr/sme_blocking.c b/drivers/staging/csr/sme_blocking.c index f30eda950ad6..8461baca2dea 100644 --- a/drivers/staging/csr/sme_blocking.c +++ b/drivers/staging/csr/sme_blocking.c @@ -92,11 +92,15 @@ sme_init_request(unifi_priv_t *priv) return -EIO; } + unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n"); + /* Grab the SME semaphore until the reply comes, or timeout */ if (down_interruptible(&priv->sme_sem)) { unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n"); return -EIO; } + unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n"); + priv->sme_reply.request_status = SME_REQUEST_PENDING; return 0; @@ -118,6 +122,10 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char * (func ? func : ""), priv->sme_reply.request_status); return; } + unifi_trace(priv, UDBG5, + "sme_complete_request: completed %s (s:%d)\n", + (func ? func : ""), priv->sme_reply.request_status); + priv->sme_reply.request_status = SME_REQUEST_RECEIVED; priv->sme_reply.reply_status = reply_status; @@ -127,23 +135,66 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char * } +void +uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status) +{ + /* Check for a blocking SME request in progress, and cancel the wait. + * This should be used when the character device is closed. + */ + + if (priv == NULL) { + unifi_error(priv, "sme_cancel_request: Invalid priv\n"); + return; + } + + /* If no request is pending, nothing to wake up */ + if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { + unifi_trace(priv, UDBG5, + "sme_cancel_request: no request was pending (s:%d)\n", + priv->sme_reply.request_status); + /* Nothing to do */ + return; + } + unifi_trace(priv, UDBG5, + "sme_cancel_request: request cancelled (s:%d)\n", + priv->sme_reply.request_status); + + /* Wake up the wait with an error status */ + priv->sme_reply.request_status = SME_REQUEST_CANCELLED; + priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */ + + wake_up_interruptible(&priv->sme_request_wq); + + return; +} + + static int _sme_wait_for_reply(unifi_priv_t *priv, unsigned long timeout, const char *func) { long r; - unifi_trace(priv, UDBG5, "sme_wait_for_reply: sleep\n"); + unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : ""); r = wait_event_interruptible_timeout(priv->sme_request_wq, (priv->sme_reply.request_status != SME_REQUEST_PENDING), msecs_to_jiffies(timeout)); - unifi_trace(priv, UDBG5, "sme_wait_for_reply: awake\n"); + unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r); if (r == -ERESTARTSYS) { /* The thread was killed */ + unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n"); up(&priv->sme_sem); return r; } + if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) { + unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n", + (func ? func : ""), priv->sme_reply.request_status, timeout, r); + + /* Release the SME semaphore that was downed in sme_init_request() */ + up(&priv->sme_sem); + return -EIO; /* fail the ioctl */ + } if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) { unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n", (func ? func : ""), priv->sme_reply.request_status, timeout); @@ -156,6 +207,9 @@ _sme_wait_for_reply(unifi_priv_t *priv, return -ETIMEDOUT; } + unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n", + func ? func : "", r); + /* Release the SME semaphore that was downed in sme_init_request() */ up(&priv->sme_sem); @@ -1289,22 +1343,20 @@ int sme_sys_suspend(unifi_priv_t *priv) return -EIO; } - /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ - priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; - - /* Suspend the SME, which will cause it to power down UniFi */ + /* Suspend the SME, which MAY cause it to power down UniFi */ CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend); r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); if (r) { /* No reply - forcibly power down in case the request wasn't processed */ unifi_notice(priv, "suspend: SME did not reply %s, ", - priv->ptest_mode ? "leave powered" : "power off UniFi anyway\n"); + (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n"); /* Leave power on for production test, though */ if (!priv->ptest_mode) { /* Put UniFi to deep sleep, in case we can not power it off */ CsrSdioClaim(priv->sdio); + unifi_trace(priv, UDBG1, "Force deep sleep"); csrResult = unifi_force_low_power_mode(priv->card); /* For WOL, the UniFi must stay powered */ @@ -1319,13 +1371,40 @@ int sme_sys_suspend(unifi_priv_t *priv) if (priv->wol_suspend) { unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n"); - /* For PIO WOL, disable SDIO interrupt to enable PIO mode in the f/w */ - if (enable_wol == UNIFI_WOL_PIO) { - unifi_trace(priv, UDBG1, "Remove IRQ to enable PIO WOL\n"); - if (csr_sdio_linux_remove_irq(priv->sdio)) { - unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n"); + /* Remove the IRQ, which also disables the card SDIO interrupt. + * Disabling the card SDIO interrupt enables the PIO WOL source. + * Removal of the of the handler ensures that in both SDIO and PIO cases + * the card interrupt only wakes the host. The card will be polled + * after resume to handle any pending data. + */ + if (csr_sdio_linux_remove_irq(priv->sdio)) { + unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n"); + } + + if (enable_wol == UNIFI_WOL_SDIO) { + /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt, + * it must be left enabled to wake-on-SDIO. + */ + unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n"); + + CsrSdioClaim(priv->sdio); + csrResult = CsrSdioInterruptEnable(priv->sdio); + CsrSdioRelease(priv->sdio); + + if (csrResult != CSR_RESULT_SUCCESS) { + unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult); } + } else { + unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n"); } + + /* Prevent the BH thread from running during the suspend. + * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause + * the BH thread to be re-enabled and reinstall the ISR. + */ + priv->bh_thread.block_thread = 1; + + unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH"); } /* Consider UniFi to be uninitialised */ @@ -1354,22 +1433,10 @@ int sme_sys_resume(unifi_priv_t *priv) CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend); - if (priv->ptest_mode == 1) { - r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); - if (r) { - /* No reply - forcibly power down in case the request wasn't processed */ - unifi_notice(priv, - "resume: SME did not reply, return success anyway\n"); - } - } else { - - /* - * We are not going to wait for the reply because the SME might be in - * the userspace. In this case the event will reach it when the kernel - * resumes. So, release now the SME semaphore that was downed in - * sme_init_request(). - */ - up(&priv->sme_sem); + r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); + if (r) { + unifi_notice(priv, + "resume: SME did not reply, return success anyway\n"); } return 0; diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c index f5760444bfea..da12807434b4 100644 --- a/drivers/staging/csr/sme_sys.c +++ b/drivers/staging/csr/sme_sys.c @@ -20,6 +20,8 @@ #ifdef CSR_SUPPORT_WEXT_AP #include "sme_csr/csr_wifi_sme_sef.h" #endif + + /* * This file implements the SME SYS API and contains the following functions: * CsrWifiRouterCtrlMediaStatusReqHandler() @@ -40,8 +42,10 @@ * CsrWifiRouterCtrlTclasDelReqHandler() * CsrWifiRouterCtrlSetModeReqHandler() * CsrWifiRouterCtrlWapiMulticastFilterReqHandler() - * CsrWifiRouterCtrlWapiMulticastReqHandler() * CsrWifiRouterCtrlWapiUnicastFilterReqHandler() + * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler() + * CsrWifiRouterCtrlWapiRxPktReqHandler() + * CsrWifiRouterCtrlWapiFilterReqHandler() */ #ifdef CSR_SUPPORT_SME @@ -731,10 +735,31 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) if (priv == NULL) { return; } - for (i=0; iinterfacePriv[i]->interfaceMode = 0; + if( priv->wol_suspend ) { + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Don't reset mode\n"); + } else { +#ifdef ANDROID_BUILD + /* Take the wakelock while Wi-Fi On is in progress */ + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: take wake lock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif + for (i=0; iinterfacePriv[i]->interfaceMode = 0; + } + } + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X) req->dataLength=%d req->data=0x%x\n", msg->source, req->dataLength, req->data); + + if(req->dataLength==3 && req->data && req->data[0]==0 && req->data[1]==1 && req->data[2]==1) + { + priv->cmanrTestMode = TRUE; + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: cmanrTestMode=%d\n", priv->cmanrTestMode); + } + else + { + priv->cmanrTestMode = FALSE; } - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X)\n", msg->source); /* * The request to initialise UniFi might come while UniFi is running. @@ -747,11 +772,16 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) /* Update the wifi_on state */ priv->wifi_on_state = wifi_on_in_progress; - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; + /* If UniFi was unpowered, acquire the firmware for download to chip */ + if (!priv->wol_suspend) { + r = uf_request_firmware_files(priv, UNIFI_FW_STA); + if (r) { + unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n"); + CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); + return; + } + } else { + unifi_trace(priv, UDBG1, "Don't need firmware\n"); } /* Power on UniFi (which may not necessarily have been off) */ @@ -832,6 +862,13 @@ wifi_off(unifi_priv_t *priv) int i; CsrResult csrResult; + + /* Already off? */ + if (priv->wifi_on_state == wifi_on_unspecified) { + unifi_trace(priv, UDBG1, "wifi_off already\n"); + return; + } + unifi_trace(priv, UDBG1, "wifi_off\n"); /* Destroy the Traffic Analysis Module */ @@ -840,6 +877,7 @@ wifi_off(unifi_priv_t *priv) cancel_work_sync(&priv->ta_sample_ind_work.task); #ifdef CSR_SUPPORT_WEXT cancel_work_sync(&priv->sme_config_task); + wext_send_disassoc_event(priv); #endif /* Cancel pending M4 stuff */ @@ -908,9 +946,6 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) unifi_priv_t *priv = (unifi_priv_t*)drvpriv; CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg; int i = 0; -#ifdef CSR_SUPPORT_WEXT_AP - CsrWifiSmeWifiOffCfm cfm; -#endif if (priv == NULL) { return; @@ -924,6 +959,7 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) if (interfacePriv->netdev_registered == 1) { netif_carrier_off(priv->netdev[i]); UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); + interfacePriv->connected = UnifiConnectedUnknown; } interfacePriv->interfaceMode = 0; @@ -936,15 +972,11 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) wifi_off(priv); CsrWifiRouterCtrlWifiOffCfmSend(msg->source,req->clientData); -#ifdef CSR_SUPPORT_WEXT_AP - /* Router is turned off when WifiOffCfm is received - * hence for wext we don't see WifiOffCfm in the wext - * files. So just tell the waiting process that - * Wifi off is successful + + /* If this is called in response to closing the character device, the + * caller must use uf_sme_cancel_request() to terminate any pending SME + * blocking request or there will be a delay while the operation times out. */ - cfm.status = CSR_RESULT_SUCCESS; - CsrWifiSmeWifiOffCfmHandler(priv,(CsrWifiFsmEvent*)(&cfm)); -#endif } @@ -1065,7 +1097,9 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) { int i; /* used as a loop counter */ CsrUint32 intmode = CSR_WIFI_INTMODE_DEFAULT; - +#ifdef CSR_WIFI_SPLIT_PATCH + CsrBool switching_ap_fw = FALSE; +#endif /* Register the UniFi device with the OS network manager */ unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n"); @@ -1099,6 +1133,16 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) return; } } +#ifdef CSR_WIFI_SPLIT_PATCH + else + { + /* If a netdev is already registered, we have received this WifiOnRes + * in response to switching AP/STA firmware in a ModeSetReq. + * Rememeber this in order to send a ModeSetCfm once + */ + switching_ap_fw = TRUE; + } +#endif } priv->totalInterfaceCount = res->numInterfaceAddress; @@ -1117,8 +1161,27 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS); +#ifdef CSR_WIFI_SPLIT_PATCH + if (switching_ap_fw && (priv->pending_mode_set.common.destination != 0xaaaa)) { + unifi_info(priv, "Completed firmware reload with %s patch\n", + CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode) ? "AP" : "STA"); + + /* Confirm the ModeSetReq that requested the AP/STA patch switch */ + CsrWifiRouterCtrlModeSetCfmSend(priv->pending_mode_set.common.source, + priv->pending_mode_set.clientData, + priv->pending_mode_set.interfaceTag, + priv->pending_mode_set.mode, + CSR_RESULT_SUCCESS); + priv->pending_mode_set.common.destination = 0xaaaa; + } +#endif unifi_info(priv, "UniFi ready\n"); +#ifdef ANDROID_BUILD + /* Release the wakelock */ + unifi_trace(priv, UDBG1, "ready: release wake lock\n"); + wake_unlock(&unifi_sdio_wake_lock); +#endif /* Firmware initialisation is complete, so let the SDIO bus * clock be raised when convienent to the core. */ @@ -1257,15 +1320,7 @@ void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg) return; } - /* - * Unless we are in ptest mode, nothing is waiting for the response. - * Do not call sme_complete_request(), otherwise the driver - * and the SME will be out of step. - */ - if (priv->ptest_mode == 1) { - sme_complete_request(priv, res->status); - } - + sme_complete_request(priv, res->status); } @@ -1709,7 +1764,6 @@ void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, CsrUint16 interfaceTag) &(interfacePriv->genericMulticastOrBroadCastFrames)); uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames)); - uf_flush_maPktlist(priv,&(interfacePriv->directedMaPktReq)); /* process the list of frames that requested cfm and send cfm to requestor one by one */ @@ -1747,21 +1801,93 @@ void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES) { netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - +#ifdef CSR_WIFI_SPLIT_PATCH + CsrUint8 old_mode = interfacePriv->interfaceMode; +#endif unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n", interfacePriv->interfaceMode); - /* Cleanup the database first for current existing mode, Then take - * care of setting the new mode (Transition seq: AnyMode->NoneMode->newMode) - * So for Every mode changes, Database Initialization/cleanup needed + interfacePriv->interfaceMode = req->mode; + +#ifdef CSR_WIFI_SPLIT_PATCH + /* Detect a change in mode that requires a switch to/from the AP firmware patch. + * This should only happen when transitioning in/out of AP modes. */ - CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag); + if (CSR_WIFI_HIP_IS_AP_FW(req->mode) != CSR_WIFI_HIP_IS_AP_FW(old_mode)) + { + CsrWifiRouterCtrlVersions versions; + int r; + +#ifdef ANDROID_BUILD + /* Take the wakelock while switching patch */ + unifi_trace(priv, UDBG1, "patch switch: take wake lock\n"); + wake_lock(&unifi_sdio_wake_lock); +#endif + unifi_info(priv, "Resetting UniFi with %s patch\n", CSR_WIFI_HIP_IS_AP_FW(req->mode) ? "AP" : "STA"); + + r = uf_request_firmware_files(priv, UNIFI_FW_STA); + if (r) { + unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: Failed to get f/w\n"); + CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, + req->mode, CSR_RESULT_FAILURE); + return; + } + + /* Block the I/O thread */ + priv->bh_thread.block_thread = 1; + + /* Reset and download the new patch */ + r = uf_init_hw(priv); + if (r) { + unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); + CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, + req->mode, CSR_RESULT_FAILURE); + return; + } + + /* Re-enable the I/O thread */ + priv->bh_thread.block_thread = 0; + + /* Get the version information from the core */ + unifi_card_info(priv->card, &priv->card_info); + + /* Copy to the unifiio_card_info structure. */ + versions.chipId = priv->card_info.chip_id; + versions.chipVersion = priv->card_info.chip_version; + versions.firmwareBuild = priv->card_info.fw_build; + versions.firmwareHip = priv->card_info.fw_hip_version; + versions.routerBuild = (CsrCharString*)CSR_WIFI_VERSION; + versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; + + /* Now that new firmware is running, send a WifiOnInd to the NME. This will + * cause it to retransfer the MIB. + */ + CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); + + /* Store the request so we know where to send the ModeSetCfm */ + priv->pending_mode_set = *req; + } + else +#endif + { + /* No patch switch, confirm straightaway */ + CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, + req->mode, CSR_RESULT_SUCCESS); + } - interfacePriv->interfaceMode = req->mode; interfacePriv->bssid = req->bssid; /* For modes other than AP/P2PGO, set below member FALSE */ interfacePriv->intraBssEnabled = FALSE; - + /* Initialise the variable bcTimSet with a value + * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value + */ + interfacePriv->bcTimSet = 0xFF; + interfacePriv->bcTimSetReqPendingFlag = FALSE; + /* Initialise the variable bcTimSetReqQueued with a value + * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value + */ + interfacePriv->bcTimSetReqQueued =0xFF; + CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag); if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP || req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { @@ -1797,8 +1923,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r unifi_port_config_t *controlledPort; unifi_port_config_t *unControlledPort; netInterface_priv_t *interfacePriv; - maPktReqList_t *maPktreq; - struct list_head *listHeadMaPktreq,*placeHolderMaPktreq; CsrUint8 ba_session_idx = 0; ba_session_rx_struct *ba_session_rx = NULL; @@ -1832,21 +1956,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r uf_flush_list(priv,&(staInfo->dataPdu[j])); } - /* There may be race condition - before getting the ma_packet_cfm from f/w, driver may receive peer del from SME - */ - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) { - maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); - if(maPktreq->staHandler== staInfo->assignedHandle){ - dev_kfree_skb(maPktreq->skb); - list_del(listHeadMaPktreq); - kfree(maPktreq); - } - - } - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); /* clear the port configure array info, for the corresponding peer entry */ controlledPort = &interfacePriv->controlled_data_port; @@ -1885,7 +1994,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r /* Stop BA session if it is active, for this peer address all BA sessions (per tID per role) are closed */ - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx]; if(ba_session_rx) { @@ -1912,7 +2021,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r } } - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); #ifdef CSR_SUPPORT_SME unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid); @@ -2134,8 +2243,16 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r newRecord->txSuspend = FALSE; /*U-APSD related data structure*/ + newRecord->timRequestPendingFlag = FALSE; + + /* Initialise the variable updateTimReqQueued with a value + * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value + */ + newRecord->updateTimReqQueued = 0xFF; + newRecord->timSet = CSR_WIFI_TIM_RESET; newRecord->uapsdActive = FALSE; newRecord->noOfSpFramesSent =0; + newRecord->triggerFramePriority = CSR_QOS_UP0; /* The protection bit is updated once the port opens for corresponding peer in * routerPortConfigure request */ @@ -2602,13 +2719,13 @@ void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__); - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); r = blockack_session_stop(priv, req->interfaceTag, req->role, req->trafficStreamID, req->macAddress); - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source, req->clientData, @@ -2746,6 +2863,16 @@ CsrBool blockack_session_start(unifi_priv_t *priv, init_timer(&ba_session_rx->timer); mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); } + /* + * The starting sequence number shall remain same if the BA + * enable request is issued to update BA parameters only. If + * it is not same, then we scroll our window to the new starting + * sequence number. This could happen if the DELBA frame from + * originator is lost and then we receive ADDBA frame with new SSN. + */ + if(ba_session_rx->start_sn != start_sn) { + scroll_ba_window(priv, interfacePriv, ba_session_rx, start_sn); + } return TRUE; } } @@ -2768,6 +2895,21 @@ CsrBool blockack_session_start(unifi_priv_t *priv, return FALSE; } + /* It is observed that with some devices there is a race between + * EAPOL exchanges and BA session establishment. This results in + * some EAPOL authentication packets getting stuck in BA reorder + * buffer and hence the conection cannot be established. To avoid + * this we check here if the EAPOL authentication is complete and + * if so then only allow the BA session to establish. + * + * It is verified that the peers normally re-establish + * the BA session after the initial rejection. + */ + if (CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN != uf_sme_port_state(priv, macAddress.a, UF_CONTROLLED_PORT_Q, interfacePriv->InterfaceTag)) + { + unifi_warning(priv, "blockack_session_start: Controlled port not opened, Reject BA request\n"); + return FALSE; + } ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); if (!ba_session_rx) { @@ -2814,7 +2956,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m unifi_priv_t *priv = (unifi_priv_t*)drvpriv; unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); r = blockack_session_start(priv, req->interfaceTag, req->trafficStreamID, @@ -2824,7 +2966,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m req->ssn, req->macAddress ); - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source, req->clientData, @@ -2836,115 +2978,291 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) { +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status); + if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status); + + /* status 1 - Filter on + * status 0 - Filter off */ + priv->wapi_multicast_filter = req->status; + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + } else { - /* status 1 - Filter on - * status 0 - Filter off */ - priv->wapi_multicast_filter = req->status; + unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode); - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + } +#elif defined(UNIFI_DEBUG) + /*WAPI Disabled*/ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastFilterReqHandler: called when WAPI isn't enabled\n"); +#endif } void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) { +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status); + if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) { - /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */ - priv->wapi_unicast_queued_pkt_filter = 1; - } + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - /* status 1 - Filter ON - * status 0 - Filter OFF */ - priv->wapi_unicast_filter = req->status; + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status); - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); -} + if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) { + /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */ + priv->wapi_unicast_queued_pkt_filter = 1; + } + /* status 1 - Filter ON + * status 0 - Filter OFF */ + priv->wapi_unicast_filter = req->status; -void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + } else { + + unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode); + + } +#elif defined(UNIFI_DEBUG) + /*WAPI Disabled*/ unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiMulticastReq* req = (CsrWifiRouterCtrlWapiMulticastReq*)msg; + unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastFilterReqHandler: called when WAPI isn't enabled\n"); +#endif +} + +void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWapiRxPktReq* req = (CsrWifiRouterCtrlWapiRxPktReq*)msg; int client_id, receiver_id; bulk_data_param_t bulkdata; CsrResult res; ul_client_t *client; - CSR_SIGNAL signal; CSR_MA_PACKET_INDICATION *pkt_ind; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiMulticastReqHandler: \n"); + if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid priv\n",__FUNCTION__); - return; - } + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid sme priv\n",__FUNCTION__); - return; - } + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid priv\n",__FUNCTION__); + return; + } - if (req->dataLength == 0 || req->data == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: invalid request\n",__FUNCTION__); - return; - } + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid sme priv\n",__FUNCTION__); + return; + } - res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); - if (res != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: Could not allocate net data\n",__FUNCTION__); - return; - } + if (req->dataLength == 0 || req->data == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: invalid request\n",__FUNCTION__); + return; + } - /* This function is expected to be called only when the MIC has been verified by SME to be correct - * So reset the reception status to rx_success */ - res = read_unpack_signal(req->signal, &signal); - if (res) { - unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Received unknown or corrupted signal.\n"); - return; - } - pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication); - if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) { - unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus); - return; - } - else { - unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiMulticastReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__); - pkt_ind->ReceptionStatus = CSR_RX_SUCCESS; - write_pack(&signal, req->signal, &(req->signalLength)); + res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); + if (res != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: Could not allocate net data\n",__FUNCTION__); + return; + } + + /* This function is expected to be called only when the MIC has been verified by SME to be correct + * So reset the reception status to rx_success */ + res = read_unpack_signal(req->signal, &signal); + if (res) { + unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Received unknown or corrupted signal.\n"); + return; + } + pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication); + if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) { + unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus); + return; + } else { + unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiRxPktReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__); + pkt_ind->ReceptionStatus = CSR_RX_SUCCESS; + write_pack(&signal, req->signal, &(req->signalLength)); + } + + memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); + + receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0; + client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; + + client = &priv->ul_clients[client_id]; + + if (client && client->event_hook) { + unifi_trace(priv, UDBG3, + "CsrWifiRouterCtrlWapiRxPktReq: " + "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n", + client->client_id, client->sender_id, receiver_id, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal)); + + client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST); + } else { + unifi_trace(priv, UDBG4, "No client to give the packet to\n"); + unifi_net_data_free(priv, &bulkdata.d[0]); + } + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + } else { + unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode); } +#elif defined(UNIFI_DEBUG) + /*WAPI Disabled*/ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: called when WAPI isn't enabled\n"); +#endif +} - memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); +void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; + unifi_priv_t *priv = (unifi_priv_t*) drvpriv; + CsrWifiRouterCtrlWapiUnicastTxPktReq *req = (CsrWifiRouterCtrlWapiUnicastTxPktReq*) msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + bulk_data_param_t bulkdata; + CsrUint8 macHeaderLengthInBytes = MAC_HEADER_SIZE; + /*KeyID, Reserved, PN, MIC*/ + CsrUint8 appendedCryptoFields = 1 + 1 + 16 + 16; + CsrResult result; + /* Retrieve the MA PACKET REQ fields from the Signal retained from send_ma_pkt_request() */ + CSR_MA_PACKET_REQUEST *storedSignalMAPktReq = &interfacePriv->wapi_unicast_ma_pkt_sig.u.MaPacketRequest; - client = &priv->ul_clients[client_id]; + if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + + if (priv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid priv\n",__FUNCTION__); + return; + } + if (priv->smepriv == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid sme priv\n",__FUNCTION__); + return; + } + if (req->data == NULL) { + unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid request\n",__FUNCTION__); + return; + } else { + /* If it is QoS data (type = data subtype = QoS), frame header contains QoS control field */ + if ((req->data[0] & 0x88) == 0x88) { + macHeaderLengthInBytes = macHeaderLengthInBytes + QOS_CONTROL_HEADER_SIZE; + } + } + if ( !(req->dataLength>(macHeaderLengthInBytes+appendedCryptoFields)) ) { + unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid dataLength\n",__FUNCTION__); + return; + } + + /* Encrypted DATA Packet contained in (req->data) + * ------------------------------------------------------------------- + * |MAC Header| KeyId | Reserved | PN | xxDataxx | xxMICxxx | + * ------------------------------------------------------------------- + * (<-----Encrypted----->) + * ------------------------------------------------------------------- + * |24/26(QoS)| 1 | 1 | 16 | x | 16 | + * ------------------------------------------------------------------- + */ + result = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); + if (result != CSR_RESULT_SUCCESS) { + unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: Could not allocate net data\n",__FUNCTION__); + return; + } + memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); + bulkdata.d[0].data_length = req->dataLength; + bulkdata.d[1].os_data_ptr = NULL; + bulkdata.d[1].data_length = 0; + + /* Send UniFi msg */ + /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */ + result = uf_process_ma_packet_req(priv, + storedSignalMAPktReq->Ra.x, + storedSignalMAPktReq->HostTag,/* Ask for a new HostTag */ + req->interfaceTag, + storedSignalMAPktReq->TransmissionControl, + storedSignalMAPktReq->TransmitRate, + storedSignalMAPktReq->Priority, /* Retained value */ + interfacePriv->wapi_unicast_ma_pkt_sig.SignalPrimitiveHeader.SenderProcessId, /*FIXME AP: VALIDATE ???*/ + &bulkdata); + + if (result == NETDEV_TX_OK) { + (priv->netdev[req->interfaceTag])->trans_start = jiffies; + /* Should really count tx stats in the UNITDATA.status signal but + * that doesn't have the length. + */ + interfacePriv->stats.tx_packets++; + + /* count only the packet payload */ + interfacePriv->stats.tx_bytes += req->dataLength - macHeaderLengthInBytes - appendedCryptoFields; + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Sent), sent count = %x\n", interfacePriv->stats.tx_packets); + } else { + /* Failed to send: fh queue was full, and the skb was discarded*/ + unifi_trace(priv, UDBG1, "(HIP validation failure) Result = %d\n", result); + unifi_net_data_free(priv, &bulkdata.d[0]); + + interfacePriv->stats.tx_dropped++; + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped); + } - if (client && client->event_hook) { - unifi_trace(priv, UDBG3, - "CsrWifiRouterCtrlWapiMulticastReqHandler: " - "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n", - client->client_id, client->sender_id, receiver_id, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal)); + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + + } else { + + unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode); - client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST); } - else { - unifi_trace(priv, UDBG4, "No client to give the packet to\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); +#elif defined(UNIFI_DEBUG) + /*WAPI Disabled*/ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: called when WAPI SW ENCRYPTION isn't enabled\n"); +#endif +} + +void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) +{ +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + CsrWifiRouterCtrlWapiFilterReq* req = (CsrWifiRouterCtrlWapiFilterReq*)msg; + netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; + + if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { + + unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); + + unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiFilterReq: req->isWapiConnected [0/1] = %d \n",req->isWapiConnected); + + priv->isWapiConnection = req->isWapiConnected; + + unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); + } else { + + unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode); + } +#endif - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); +#elif defined(UNIFI_DEBUG) + /*WAPI Disabled*/ + unifi_priv_t *priv = (unifi_priv_t*)drvpriv; + unifi_error(priv,"CsrWifiRouterCtrlWapiFilterReq: called when WAPI isn't enabled\n"); +#endif } diff --git a/drivers/staging/csr/sme_userspace.c b/drivers/staging/csr/sme_userspace.c index 38df94b69e9f..d87a6e304ff2 100644 --- a/drivers/staging/csr/sme_userspace.c +++ b/drivers/staging/csr/sme_userspace.c @@ -101,7 +101,6 @@ uf_sme_init(unifi_priv_t *priv) INIT_LIST_HEAD(&interfacePriv->genericMgtFrames); INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames); INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames); - INIT_LIST_HEAD(&interfacePriv->directedMaPktReq); for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { interfacePriv->staInfo[j] = NULL; @@ -139,7 +138,7 @@ uf_sme_deinit(unifi_priv_t *priv) /* Remove all the Peer database, before going down */ for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - spin_lock(&priv->ba_lock); + down(&priv->ba_mutex); for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx]; if(ba_session_rx) { @@ -161,7 +160,7 @@ uf_sme_deinit(unifi_priv_t *priv) } } - spin_unlock(&priv->ba_lock); + up(&priv->ba_mutex); interfacePriv = priv->interfacePriv[i]; if(interfacePriv){ for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c index 384ccd46982e..3ba7b4cef2dd 100644 --- a/drivers/staging/csr/sme_wext.c +++ b/drivers/staging/csr/sme_wext.c @@ -29,8 +29,10 @@ } \ } while (0) -/* Workaround for the wpa_supplicant hanging issue */ +/* Workaround for the wpa_supplicant hanging issue - disabled on Android */ +#ifndef ANDROID_BUILD #define CSR_WIFI_WEXT_HANG_WORKAROUND +#endif #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND # define UF_RTNL_LOCK() rtnl_lock() diff --git a/drivers/staging/csr/ul_int.c b/drivers/staging/csr/ul_int.c index ae14f2354362..958b8a1a9eb3 100644 --- a/drivers/staging/csr/ul_int.c +++ b/drivers/staging/csr/ul_int.c @@ -265,7 +265,9 @@ ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len) /* wifi_off_ind (error or exit) */ CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param)); } - +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE + unifi_debug_buf_dump(); +#endif #else bulk_data_param_t bulkdata; @@ -420,10 +422,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, CsrResult csrResult; unsigned long lock_flags; int r; -#ifdef CSR_SUPPORT_SME - netInterface_priv_t *interfacePriv = priv->interfacePriv[0]; - CsrUint32 alignOffset = 0; -#endif csrResult = write_pack(sigptr, sigbuf, &packed_siglen); @@ -431,12 +429,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n"); return CsrHipResultToStatus(csrResult); } -#ifdef CSR_SUPPORT_SME - if (bulkdata != NULL){ - alignOffset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); - - } -#endif r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata); if (r) { return r; @@ -449,17 +441,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); return CsrHipResultToStatus(csrResult); } -#ifdef CSR_SUPPORT_SME - if (sigptr->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) { - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - - uf_store_directed_ma_packet_referenece(priv, bulkdata, sigptr,alignOffset); - - } - } -#endif - spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); return 0; diff --git a/drivers/staging/csr/unifi_event.c b/drivers/staging/csr/unifi_event.c index cfc5b32d4a66..8b5d4669e127 100644 --- a/drivers/staging/csr/unifi_event.c +++ b/drivers/staging/csr/unifi_event.c @@ -109,7 +109,11 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, static const CsrUint8 wapiProtocolIdSNAPHeaderOffset = 6; CsrUint8 *destAddr; CsrUint8 *srcAddr; - CsrBool isUnicastPkt = FALSE; + CsrBool isWapiUnicastPkt = FALSE; + +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + CsrUint16 qosControl; +#endif CsrUint8 llcSnapHeaderOffset = 0; @@ -117,7 +121,7 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, srcAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; /*Individual/Group bit - Bit 0 of first byte*/ - isUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; + isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; #endif #define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 @@ -158,20 +162,54 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + if ((isDataFrame) && + ((IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK) == (frmCtrl & IEEE80211_FC_SUBTYPE_MASK)) && + (priv->isWapiConnection)) + { + qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation + (((frmCtrl & IEEE802_11_FC_TO_DS_MASK) && (frmCtrl & IEEE802_11_FC_FROM_DS_MASK)) ? 30 : 24) ); + + unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind() :: Value of the QoS control field - 0x%04x \n", qosControl); + + if (qosControl & IEEE802_11_QC_NON_TID_BITS_MASK) + { + unifi_trace(priv, UDBG4, "Ignore the MIC failure and pass the MPDU to the stack when any of bits [4-15] is set in the QoS control field\n"); + + /*Exclude the MIC [16] and the PN [16] that are appended by the firmware*/ + ((bulk_data_param_t*)bulkdata)->d[0].data_length = bulkdata->d[0].data_length - 32; + + /*Clear the reception status of the signal (CSR_RX_SUCCESS)*/ + *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET) = 0x00; + *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET+1) = 0x00; + + *freeBulkData = FALSE; + + return FALSE; + } + } +#endif /* If this MIC ERROR reported by the firmware is either for - * [1] a WAPI Multicast Packet and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR - * [2] a WAPI Unicast Packet and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set + * [1] a WAPI Multicast MPDU and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR + * [2] a WAPI Unicast MPDU and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set * then report a MIC FAILURE indication to the SME. */ - if ((priv->wapi_multicast_filter == 0) || isUnicastPkt) { - +#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + if ((priv->wapi_multicast_filter == 0) || isWapiUnicastPkt) { +#else + /*When SW encryption is enabled and USKID=1 (wapi_unicast_filter = 1), we are expected + *to receive MIC failure INDs for unicast MPDUs*/ + if ( ((priv->wapi_multicast_filter == 0) && !isWapiUnicastPkt) || + ((priv->wapi_unicast_filter == 0) && isWapiUnicastPkt) ) { +#endif /*Discard the frame*/ *freeBulkData = TRUE; unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n"); - if (isUnicastPkt && + if (isWapiUnicastPkt && ((uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag) != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN)|| +#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION (priv->wapi_unicast_filter) || +#endif (priv->wapi_unicast_queued_pkt_filter))) { /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP @@ -225,7 +263,8 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, /* To ignore MIC failures reported due to the WAPI AP using the old key for queued packets before * starting to use the new key negotiated as part of unicast re-keying */ - if (isUnicastPkt && + if ((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA)&& + isWapiUnicastPkt && (receptionStatus == CSR_RX_SUCCESS) && (priv->wapi_unicast_queued_pkt_filter==1)) { @@ -297,16 +336,10 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, return FALSE; } } -#ifdef CSR_WIFI_RX_PATH_SPLIT -static CsrBool signal_buffer_is_full(unifi_priv_t* priv) -{ - return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); -} -#endif /* * --------------------------------------------------------------------------- - * unifi_receive_event + * unifi_process_receive_event * * Dispatcher for received signals. * @@ -332,56 +365,11 @@ static CsrBool signal_buffer_is_full(unifi_priv_t* priv) * binded to the host interface specification. * --------------------------------------------------------------------------- */ - - -void -unifi_receive_event(void *ospriv, - CsrUint8 *sigdata, CsrUint32 siglen, - const bulk_data_param_t *bulkdata) +static void +unifi_process_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) { -#ifdef CSR_WIFI_RX_PATH_SPLIT - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - CsrUint8 writePointer; - int i; - rx_buff_struct_t * rx_buff; - func_enter(); - - unifi_trace(priv, UDBG5, "unifi_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); - if(signal_buffer_is_full(priv)) { - unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n"); - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - return; - } - writePointer = priv->rxSignalBuffer.writePointer; - rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; - memcpy(rx_buff->bufptr,sigdata,siglen); - rx_buff->sig_len = siglen; - rx_buff->data_ptrs = *bulkdata; - writePointer++; - if(writePointer >= priv->rxSignalBuffer.size) { - writePointer =0; - } - unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer); - priv->rxSignalBuffer.writePointer = writePointer; - -#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ - queue_work(priv->rx_workqueue, &priv->rx_work_struct); -#endif - -#else unifi_priv_t *priv = (unifi_priv_t*)ospriv; int i, receiver_id; int client_id; @@ -390,16 +378,17 @@ unifi_receive_event(void *ospriv, func_enter(); - unifi_trace(priv, UDBG5, "unifi_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); + unifi_trace(priv, UDBG5, "unifi_process_receive_event: " + "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, + siglen); receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; @@ -410,18 +399,18 @@ unifi_receive_event(void *ospriv, /* check for the type of frame received (checks for 802.11 management frames) */ if (signal_id == CSR_MA_PACKET_INDICATION_ID) { +#define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14 CsrUint8 interfaceTag; netInterface_priv_t *interfacePriv; /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; interfacePriv = priv->interfacePriv[interfaceTag]; /* Update activity for this station in case of IBSS */ #ifdef CSR_SUPPORT_SME - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) + { CsrUint8 *saddr; /* Fetch the source address from mac header */ saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; @@ -436,6 +425,7 @@ unifi_receive_event(void *ospriv, pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); + } if (pktIndToSme) @@ -445,7 +435,7 @@ unifi_receive_event(void *ospriv, send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); } else{ - unifi_error(priv, "unifi_receive_event: sigdata or Bulkdata is NULL \n"); + unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); } #ifdef CSR_NATIVE_LINUX send_to_client(priv, priv->wext_client, @@ -459,67 +449,99 @@ unifi_receive_event(void *ospriv, * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs */ if (!receiver_id) { - if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) - { - uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); - } - else if (signal_id != CSR_MA_PACKET_INDICATION_ID) - { - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); + if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) { + uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); + } + else if (signal_id != CSR_MA_PACKET_INDICATION_ID) { + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); #ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); #endif - } - }/*if (receiver_id==0) */ - -#ifdef CSR_SUPPORT_SME -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /* Send a WAPI Multicast Indication to SME if the filter has been set - * and this is a multicast data packet - */ - if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { - CSR_SIGNAL signal; - CsrUint8 *destAddr; - CsrResult res; - CsrUint16 interfaceTag = 0; - - /* Check if it is a multicast packet from the destination address in the MAC header */ - res = read_unpack_signal(sigdata, &signal); - destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - if (res) { - unifi_error(priv, "Received unknown or corrupted signal.\n"); - return; - } - /*Individual/Group bit - Bit 0 of first byte*/ - if (destAddr[0] & 0x01) { - unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); - - CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - func_exit(); - return; - } - } + } + else + { + +#if (defined(CSR_SUPPORT_SME) && defined(CSR_WIFI_SECURITY_WAPI_ENABLE)) + #define CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 + netInterface_priv_t *interfacePriv; + CsrUint8 interfaceTag; + CsrUint16 receptionStatus = CSR_RX_SUCCESS; + + /* Pull out interface tag from virtual interface identifier */ + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* check for MIC failure */ + receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET); + + /* Send a WAPI MPDU to SME for re-check MIC if the respective filter has been set*/ + if ((!freeBulkData) && + (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) && + (receptionStatus == CSR_MICHAEL_MIC_ERROR) && + ((priv->wapi_multicast_filter == 1) +#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + || (priv->wapi_unicast_filter == 1) #endif + )) + { + CSR_SIGNAL signal; + CsrUint8 *destAddr; + CsrResult res; + CsrUint16 interfaceTag = 0; + CsrBool isMcastPkt = TRUE; + + unifi_trace(priv, UDBG6, "Received a WAPI data packet when the Unicast/Multicast filter is set\n"); + res = read_unpack_signal(sigdata, &signal); + if (res) { + unifi_error(priv, "Received unknown or corrupted signal (0x%x).\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata)); + return; + } + + /* Check if the type of MPDU and the respective filter status*/ + destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; + isMcastPkt = (destAddr[0] & 0x01) ? TRUE : FALSE; + unifi_trace(priv, UDBG6, + "1.MPDU type: (%s), 2.Multicast filter: (%s), 3. Unicast filter: (%s)\n", + ((isMcastPkt) ? "Multiast":"Unicast"), + ((priv->wapi_multicast_filter) ? "Enabled":"Disabled"), + ((priv->wapi_unicast_filter) ? "Enabled":"Disabled")); + + if (((isMcastPkt) && (priv->wapi_multicast_filter == 1)) +#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + || ((!isMcastPkt) && (priv->wapi_unicast_filter == 1)) #endif + ) + { + unifi_trace(priv, UDBG4, "Sending the WAPI MPDU for MIC check\n"); + CsrWifiRouterCtrlWapiRxMicCheckIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + func_exit(); + return; + } + } /* CSR_MA_PACKET_INDICATION_ID */ +#endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/ + } + } /* calls the registered clients handler callback func. * netdev_mlme_event_handler is one of the registered handler used to route * data packet to network stack or AMP/EAPOL related data to SME - */ - /* The freeBulkData check ensures that, it has received a management frame and + * + * The freeBulkData check ensures that, it has received a management frame and * the frame needs to be freed here. So not to be passed to netdev handler */ if(!freeBulkData){ if ((client_id < MAX_UDI_CLIENTS) && (&priv->ul_clients[client_id] != priv->logging_client)) { + unifi_trace(priv, UDBG6, "Call the registered clients handler callback func\n"); send_to_client(priv, &priv->ul_clients[client_id], receiver_id, sigdata, siglen, bulkdata); @@ -550,14 +572,54 @@ unifi_receive_event(void *ospriv, } } } -#endif + func_exit(); -} /* unifi_receive_event() */ +} /* unifi_process_receive_event() */ + #ifdef CSR_WIFI_RX_PATH_SPLIT +static CsrBool signal_buffer_is_full(unifi_priv_t* priv) +{ + return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); +} + +void unifi_rx_queue_flush(void *ospriv) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + func_enter(); + unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer); + if(priv != NULL) { + CsrUint8 readPointer = priv->rxSignalBuffer.readPointer; + while (readPointer != priv->rxSignalBuffer.writePointer) + { + rx_buff_struct_t *buf = &priv->rxSignalBuffer.rx_buff[readPointer]; + unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + readPointer,priv->rxSignalBuffer.writePointer); + unifi_process_receive_event(priv, buf->bufptr, buf->sig_len, &buf->data_ptrs); + readPointer ++; + if(readPointer >= priv->rxSignalBuffer.size) { + readPointer = 0; + } + } + priv->rxSignalBuffer.readPointer = readPointer; + } + func_exit(); +} + +void rx_wq_handler(struct work_struct *work) +{ + unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct); + unifi_rx_queue_flush(priv); +} +#endif + + + /* * --------------------------------------------------------------------------- - * unifi_receive_event2 + * unifi_receive_event * * Dispatcher for received signals. * @@ -583,20 +645,19 @@ unifi_receive_event(void *ospriv, * binded to the host interface specification. * --------------------------------------------------------------------------- */ -static void -unifi_receive_event2(void *ospriv, - CsrUint8 *sigdata, CsrUint32 siglen, - const bulk_data_param_t *bulkdata) +void +unifi_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) { +#ifdef CSR_WIFI_RX_PATH_SPLIT unifi_priv_t *priv = (unifi_priv_t*)ospriv; - int i, receiver_id; - int client_id; - CsrInt16 signal_id; - CsrBool pktIndToSme = FALSE, freeBulkData = FALSE; - + CsrUint8 writePointer; + int i; + rx_buff_struct_t * rx_buff; func_enter(); - unifi_trace(priv, UDBG5, "unifi_receive_event2: " + unifi_trace(priv, UDBG5, "unifi_receive_event: " "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, @@ -606,189 +667,34 @@ unifi_receive_event2(void *ospriv, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); - - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; - signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); - - - - /* check for the type of frame received (checks for 802.11 management frames) */ - if (signal_id == CSR_MA_PACKET_INDICATION_ID) - { - CsrUint8 interfaceTag; - netInterface_priv_t *interfacePriv; - - /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Update activity for this station in case of IBSS */ -#ifdef CSR_SUPPORT_SME - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - - CsrUint8 *saddr; - /* Fetch the source address from mac header */ - saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; - unifi_trace(priv, UDBG5, - "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", - interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]); - - uf_update_sta_activity(priv, interfaceTag, saddr); + if(signal_buffer_is_full(priv)) { + unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n"); + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } } -#endif - - pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); - - unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); - + return; } - - if (pktIndToSme) - { - /* Management MA_PACKET_IND for SME */ - if(sigdata != NULL && bulkdata != NULL){ - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); - } - else{ - unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); - } -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif + writePointer = priv->rxSignalBuffer.writePointer; + rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; + memcpy(rx_buff->bufptr,sigdata,siglen); + rx_buff->sig_len = siglen; + rx_buff->data_ptrs = *bulkdata; + writePointer++; + if(writePointer >= priv->rxSignalBuffer.size) { + writePointer =0; } - else - { - /* Signals with ReceiverId==0 are also reported to SME / WEXT, - * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs - */ - if (!receiver_id) { - if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) - { - uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); - } - else if (signal_id != CSR_MA_PACKET_INDICATION_ID) - { - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif - } - } - -#ifdef CSR_SUPPORT_SME -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /* Send a WAPI Multicast Indication to SME if the filter has been set - * and this is a multicast data packet - */ - if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { - CSR_SIGNAL signal; - CsrUint8 *destAddr; - CsrResult res; - CsrUint16 interfaceTag = 0; - - /* Check if it is a multicast packet from the destination address in the MAC header */ - res = read_unpack_signal(sigdata, &signal); - destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - if (res) { - unifi_error(priv, "Received unknown or corrupted signal.\n"); - return; - } - /*Individual/Group bit - Bit 0 of first byte*/ - if (destAddr[0] & 0x01) { - unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); - - CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer); + priv->rxSignalBuffer.writePointer = writePointer; - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - func_exit(); - return; - } - } -#endif +#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ + queue_work(priv->rx_workqueue, &priv->rx_work_struct); #endif - /* calls the registered clients handler callback func. - * netdev_mlme_event_handler is one of the registered handler used to route - * data packet to network stack or AMP/EAPOL related data to SME - */ - /* The freeBulkData check ensures that, it has received a management frame and - * the frame needs to be freed here. So not to be passed to netdev handler - */ - if(!freeBulkData){ - if ((client_id < MAX_UDI_CLIENTS) && - (&priv->ul_clients[client_id] != priv->logging_client)) { - send_to_client(priv, &priv->ul_clients[client_id], - receiver_id, - sigdata, siglen, bulkdata); - } - } - } - - /* - * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION - */ - switch (signal_id) - { -#ifdef UNIFI_SNIFF_ARPHRD - case CSR_MA_SNIFFDATA_INDICATION_ID: +#else + unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata); #endif - break; - - case CSR_MA_PACKET_INDICATION_ID: - if (!freeBulkData) - { - break; - } - /* FALLS THROUGH... */ - default: - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - } - func_exit(); -} /* unifi_receive_event2() */ - -void unifi_rx_queue_flush(void *ospriv) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - func_enter(); - unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer); - if(priv != NULL) { - CsrUint8 readPointer = priv->rxSignalBuffer.readPointer; - while(readPointer != priv->rxSignalBuffer.writePointer) { - rx_buff_struct_t * buf = &priv->rxSignalBuffer.rx_buff[readPointer]; - unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - readPointer,priv->rxSignalBuffer.writePointer); - unifi_receive_event2(priv,buf->bufptr,buf->sig_len,&buf->data_ptrs); - readPointer ++; - if(readPointer >= priv->rxSignalBuffer.size) { - readPointer = 0; - } - } - priv->rxSignalBuffer.readPointer = readPointer; - } - func_exit(); -} - -void rx_wq_handler(struct work_struct *work) -{ - unifi_priv_t *priv = container_of(work,unifi_priv_t,rx_work_struct); - unifi_rx_queue_flush(priv); -} +} /* unifi_receive_event() */ -#endif diff --git a/drivers/staging/csr/unifi_os.h b/drivers/staging/csr/unifi_os.h index 579c7e0544a3..0a9749450688 100644 --- a/drivers/staging/csr/unifi_os.h +++ b/drivers/staging/csr/unifi_os.h @@ -97,6 +97,13 @@ void dump16(void *mem, CsrUint16 len); void dump_str(void *mem, CsrUint16 len); #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ +void unifi_error(void* ospriv, const char *fmt, ...); +void unifi_warning(void* ospriv, const char *fmt, ...); +void unifi_notice(void* ospriv, const char *fmt, ...); +void unifi_info(void* ospriv, const char *fmt, ...); + +void unifi_trace(void* ospriv, int level, const char *fmt, ...); + #else /* Stubs */ @@ -113,15 +120,16 @@ static inline void dump16(void *mem, CsrUint16 len) {} static inline void dump_str(void *mem, CsrUint16 len) {} #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ -#endif /* UNIFI_DEBUG */ +void unifi_error_nop(void* ospriv, const char *fmt, ...); +void unifi_trace_nop(void* ospriv, int level, const char *fmt, ...); +#define unifi_error if(1);else unifi_error_nop +#define unifi_warning if(1);else unifi_error_nop +#define unifi_notice if(1);else unifi_error_nop +#define unifi_info if(1);else unifi_error_nop +#define unifi_trace if(1);else unifi_trace_nop +#endif /* UNIFI_DEBUG */ -void unifi_error(void* ospriv, const char *fmt, ...); -void unifi_warning(void* ospriv, const char *fmt, ...); -void unifi_notice(void* ospriv, const char *fmt, ...); -void unifi_info(void* ospriv, const char *fmt, ...); - -void unifi_trace(void* ospriv, int level, const char *fmt, ...); /* Different levels of diagnostic detail... */ #define UDBG0 0 /* always prints in debug build */ diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c index 36b871e02c98..e35747c08317 100644 --- a/drivers/staging/csr/unifi_pdu_processing.c +++ b/drivers/staging/csr/unifi_pdu_processing.c @@ -32,22 +32,23 @@ static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata, tx_buffered_packets_t* buffered_pkt) { - struct sk_buff *skb ; CsrUint32 align_offset; if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){ return; } + skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; align_offset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); if(align_offset){ skb_pull(skb,align_offset); } - buffered_pkt->bulkdata.os_data_ptr = skb->data; - buffered_pkt->bulkdata.data_length = skb->len; - + buffered_pkt->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; + buffered_pkt->bulkdata.data_length = bulkdata->d[0].data_length; + buffered_pkt->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; + buffered_pkt->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; } #endif @@ -122,7 +123,7 @@ unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, #ifdef CSR_SUPPORT_SME #define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001 -#define TRANSMISSION_CONTROL_ESOP_MASK 0x0002 +#define TRANSMISSION_CONTROL_EOSP_MASK 0x0002 static int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered_pkt, @@ -167,34 +168,27 @@ int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK: /* If both are set then the Address4 exists (only for AP) */ - if (fromDs && toDs) - { + if (fromDs && toDs) { /* 6 is the size of Address4 field */ macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6); - } - else - { + } else { macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; } /* If order bit set then HT control field is the part of MAC header */ if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE; + qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6)); + } else { + qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2)); } + *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4)); break; default: if (fromDs && toDs) macHeaderLengthInBytes += 6; - break; - } - - if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { - qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6)); - } else { - qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2)); } - *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4)); } result = ul_send_signal_unpacked(priv, &signal, &bulkdata); if(result){ @@ -254,7 +248,7 @@ void set_eosp_transmit_ctrl(unifi_priv_t *priv, struct list_head *txList) spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_for_each_prev_safe(listHead, placeHolder, txList) { tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); unifi_trace(priv, UDBG1, "set_eosp_transmit_ctrl Transmission Control = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag); @@ -275,6 +269,8 @@ void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RES bulk_data_param_t *bulkdata = NULL; int r; + unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : invoked with resultCode = %d \n", resultCode); + memset(&signal,0,sizeof(CSR_SIGNAL)); rsp = &signal.u.MaVifAvailabilityResponse; rsp->VirtualInterfaceIdentifier = vif; @@ -288,6 +284,9 @@ void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RES if(r) { unifi_error(priv,"Availibility response sending failed %x status %d\n",vif,r); } + else { + unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : status = %d \n", r); + } } #endif @@ -354,14 +353,14 @@ void verify_and_accomodate_tx_packet(unifi_priv_t *priv) list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); if(eospFramedeleted){ - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); unifi_trace(priv, UDBG1,"updating eosp for next packet hostTag:= 0x%x ",tx_q_item->hostTag); eospFramedeleted =0; break; } - if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK ){ + if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK ){ eospFramedeleted = 1; } unifi_trace(priv,UDBG1, "freeing of multicast packets ToC = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag); @@ -445,66 +444,162 @@ CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata, unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n"); return CSR_RESULT_SUCCESS; } -static -CsrResult enque_direceted_ma_pkt_cfm_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata, - struct list_head *list, CSR_SIGNAL *signal, - CsrBool requeueOnSamePos) + +#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL +CsrResult unifi_reque_ma_packet_request (void *ospriv, CsrUint32 host_tag, + CsrUint16 txStatus, bulk_data_desc_t *bulkDataDesc) { + CsrResult status = CSR_RESULT_SUCCESS; + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + netInterface_priv_t *interfacePriv; + struct list_head *list = NULL; + CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; + bulk_data_param_t bulkData; + CSR_SIGNAL signal; + CSR_PRIORITY priority = 0; + CsrUint16 interfaceTag = 0; + unifi_TrafficQueue priority_q; + CsrUint16 frameControl = 0, frameType = 0; + unsigned long lock_flags; - /* queue the tx data packets on to appropriate queue */ - CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; - tx_buffered_packets_t *tx_q_item; + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* If the current mode is not AP or P2PGO then just return failure + * to clear the hip slot + */ + if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || + (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO))) { + return CSR_RESULT_FAILURE; + } + unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: host_tag = 0x%x\n", host_tag); - unifi_trace(priv, UDBG5, "entering enque_tx_data_pdu\n"); - if(!list ) { - unifi_error(priv,"List is not specified\n"); - return CSR_RESULT_FAILURE; + staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, + (((CsrUint8 *) bulkDataDesc->os_data_ptr) + 4), + interfaceTag); + if (NULL == staRecord) { + unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid STA record \n"); + return CSR_RESULT_FAILURE; } - if(!requeueOnSamePos && !list->prev){ - unifi_error(priv,"List prev is NULL so don't requeu it\n"); - return CSR_RESULT_FAILURE; + /* Update TIM if MA-PACKET.cfm fails with status as Tx-retry-limit or No-BSS and then just return failure + * to clear the hip slot associated with the Packet + */ + if (CSR_TX_RETRY_LIMIT == txStatus || CSR_TX_NO_BSS == txStatus) { + if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) + { + unifi_trace(priv, UDBG2, "unifi_reque_ma_packet_request: CFM failed with Retry Limit or No BSS-->update TIM\n"); + if (!staRecord->timRequestPendingFlag) { + update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle); + } + else { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 1; + unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: One more UpdateTim Request(:%d)Queued for AID %x\n", + staRecord->updateTimReqQueued, staRecord->aid); + } + } + return CSR_RESULT_FAILURE; } + else if ((CSR_TX_LIFETIME == txStatus) || (CSR_TX_BLOCK_ACK_TIMEOUT == txStatus) || + (CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED == txStatus) || + (CSR_TX_REJECTED_PEER_STATION_SLEEPING == txStatus) || + (CSR_TX_REJECTED_DTIM_STARTED == txStatus)) { + /* Extract the Frame control and the frame type */ + frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr); + frameType = ((frameControl & IEEE80211_FC_TYPE_MASK) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); + /* Mgmt frames will not be re-queued for Tx + * so just return failure to clear the hip slot + */ + if (IEEE802_11_FRAMETYPE_MANAGEMENT == frameType) { + return CSR_RESULT_FAILURE; + } + else if (IEEE802_11_FRAMETYPE_DATA == frameType) { + /* QOS NULL and DATA NULL frames will not be re-queued for Tx + * so just return failure to clear the hip slot + */ + if ((((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET) == QOS_DATA_NULL) || + (((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET)== DATA_NULL )) { + return CSR_RESULT_FAILURE; + } + } + /* Extract the Packet priority */ + if (TRUE == staRecord->wmmOrQosEnabled) { + CsrUint16 qosControl = 0; + CsrUint8 dataFrameType = 0; - tx_q_item = (tx_buffered_packets_t *)kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); - if (tx_q_item == NULL) { - unifi_error(priv, - "Failed to allocate %d bytes for tx packet record\n", - sizeof(tx_buffered_packets_t)); - func_exit(); - return CSR_RESULT_FAILURE; - } - /* disable the preemption */ - INIT_LIST_HEAD(&tx_q_item->q); - /* fill the tx_q structure members */ - tx_q_item->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; - tx_q_item->bulkdata.data_length = bulkdata->d[0].data_length; - tx_q_item->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; - tx_q_item->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; - tx_q_item->interfaceTag = req->VirtualInterfaceIdentifier & 0xff; - tx_q_item->hostTag = req->HostTag; - tx_q_item->leSenderProcessId = signal->SignalPrimitiveHeader.SenderProcessId; - tx_q_item->transmissionControl = req->TransmissionControl; - tx_q_item->priority = req->Priority; - tx_q_item->rate = req->TransmitRate; - memcpy(tx_q_item->peerMacAddress.a, req->Ra.x, ETH_ALEN); + dataFrameType =((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> 4); + if (dataFrameType == QOS_DATA) { + /* QoS control field is offset from frame control by 2 (frame control) + * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN + */ + if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)) { + qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 30); + } + else { + qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 24); + } + } + priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); - if (requeueOnSamePos) { - list_add(&tx_q_item->q, list); - } else { - list_add_tail(&tx_q_item->q, list); + if (priority < CSR_QOS_UP0 || priority > CSR_QOS_UP7) { + unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid priority:%x \n", priority); + return CSR_RESULT_FAILURE; + } + } + else { + priority = CSR_CONTENTION; + } + + /* Frame Bulk data to requeue it back to HAL Queues */ + bulkData.d[0].os_data_ptr = bulkDataDesc->os_data_ptr; + bulkData.d[0].data_length = bulkDataDesc->data_length; + bulkData.d[0].os_net_buf_ptr = bulkDataDesc->os_net_buf_ptr; + bulkData.d[0].net_buf_length = bulkDataDesc->net_buf_length; + + bulkData.d[1].os_data_ptr = NULL; + bulkData.d[1].os_net_buf_ptr = NULL; + bulkData.d[1].data_length = bulkData.d[1].net_buf_length = 0; + + /* Initialize signal to zero */ + memset(&signal, 0, sizeof(CSR_SIGNAL)); + + /* Frame MA Packet Req */ + unifi_frame_ma_packet_req(priv, priority, 0, host_tag, + interfaceTag, CSR_NO_CONFIRM_REQUIRED, + priv->netdev_client->sender_id, + staRecord->peerMacAddress.a, &signal); + + /* Find the Q-Priority */ + priority_q = unifi_frame_priority_to_queue(priority); + list = &staRecord->dataPdu[priority_q]; + + /* Place the Packet on to HAL Queue */ + status = enque_tx_data_pdu(priv, &bulkData, list, &signal, TRUE); + + /* Update the Per-station queued packet counter */ + if (!status) { + spin_lock_irqsave(&priv->staRecord_lock, lock_flags); + staRecord->noOfPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); + } + } + else { + /* Packet will not be re-queued for any of the other MA Packet Tx failure + * reasons so just return failure to clear the hip slot + */ + return CSR_RESULT_FAILURE; } - /* Count of packet queued in driver */ - priv->noOfPktQueuedInDriver++; - unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n"); - return CSR_RESULT_SUCCESS; + return status; } +#endif static void is_all_ac_deliver_enabled_and_moredata(CsrWifiRouterCtrlStaInfo_t *staRecord, CsrUint8 *allDeliveryEnabled, CsrUint8 *dataAvailable) { @@ -601,12 +696,53 @@ void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUin unifi_trace(priv, UDBG3, "receiver processID = %x, success: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x, handle = %x\n", receiverProcessId, timSetStatus, staRecord->timSet, handle); } + + /* Reset TIM pending flag to send next TIM request */ + staRecord->timRequestPendingFlag = FALSE; + + /* Make sure that one more UpdateTim request is queued, if Queued its value + * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET + */ + if (0xFF != staRecord->updateTimReqQueued) + { + /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */ + if (staRecord->timSet != staRecord->updateTimReqQueued) + { + unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateTimReq \n"); + + update_tim(priv, staRecord->aid, staRecord->updateTimReqQueued, interfaceTag, handle); + + staRecord->updateTimReqQueued = 0xFF; + } + } } else { + + interfacePriv->bcTimSet = timSetValue; /* fh_cmd_q can also be full at some point of time!, * resetting count as queue is cleaned by firmware at this point */ retryCount = 0; unifi_trace(priv, UDBG3, "tim (%s) successfully for broadcast frame in firmware\n", (timSetValue)?"SET":"RESET"); + + /* Reset DTIM pending flag to send next DTIM request */ + interfacePriv->bcTimSetReqPendingFlag = FALSE; + + /* Make sure that one more UpdateDTim request is queued, if Queued its value + * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET + */ + if (0xFF != interfacePriv->bcTimSetReqQueued) + { + /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */ + if (interfacePriv->bcTimSet != interfacePriv->bcTimSetReqQueued) + { + unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateDTimReq \n"); + + update_tim(priv, 0, interfacePriv->bcTimSetReqQueued, interfaceTag, 0xFFFFFFFF); + + interfacePriv->bcTimSetReqQueued = 0xFF; + } + } + } break; case CSR_RC_INVALID_PARAMETERS: @@ -684,6 +820,7 @@ void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUin default: unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode); } + unifi_trace(priv, UDBG2, "leaving %s\n", __FUNCTION__); } @@ -733,8 +870,14 @@ void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 i unifi_trace(priv, UDBG5, "entering the update_tim routine\n"); + if (handle == 0xFFFFFFFF) { handle &= CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE; + if (setTim == interfacePriv->bcTimSet) + { + unifi_trace(priv, UDBG3, "update_tim, Drop:Hdl=%x, timval=%d, globalTim=%d\n", handle, setTim, interfacePriv->bcTimSet); + return; + } } else if ((handle != 0xFFFFFFFF) && (handle >= UNIFI_MAX_CONNECTIONS)) { unifi_warning(priv, "bad station Handle = %x\n", handle); return; @@ -785,6 +928,25 @@ void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 i if (staRecord) { staRecord->timSet = oldTimSetStatus ; } + else + { + /* MLME_SET_TIM.req sending failed here for AID0, so revert back our bcTimSet status */ + interfacePriv->bcTimSet = !setTim; + } + } + else { + /* Update tim request pending flag and ensure no more TIM set requests are send + for the same station until TIM confirm is received */ + if (staRecord) { + staRecord->timRequestPendingFlag = TRUE; + } + else + { + /* Update tim request (for AID 0) pending flag and ensure no more DTIM set requests are send + * for the same station until TIM confirm is received + */ + interfacePriv->bcTimSetReqPendingFlag = TRUE; + } } unifi_trace(priv, UDBG5, "leaving the update_tim routine\n"); } @@ -804,12 +966,30 @@ void process_peer_active_transition(unifi_priv_t * priv, if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) { /* giving more priority to multicast packets so delaying unicast packets*/ - unifi_trace(priv,UDBG2," multicast transmission is going on so resume unicast transmission after DTIM over\n"); + unifi_trace(priv,UDBG2, "Multicast transmission is going on so resume unicast transmission after DTIM over\n"); + + /* As station is active now, even though AP is not able to send frames to it + * because of DTIM, it needs to reset the TIM here + */ + if (!staRecord->timRequestPendingFlag){ + if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){ + update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); + } + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 0; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); + } return; } while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) { unifi_trace(priv, UDBG2, "p_p_a_t:(ENOSPC) Mgt Frame queueing \n"); /* Enqueue at the head of the queue */ @@ -828,11 +1008,22 @@ void process_peer_active_transition(unifi_priv_t * priv, kfree(buffered_pkt); } } - if (staRecord->txSuspend) { - if(staRecord->timSet == CSR_WIFI_TIM_SET) { - update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + if (!staRecord->timRequestPendingFlag) { + if (staRecord->txSuspend) { + if(staRecord->timSet == CSR_WIFI_TIM_SET) { + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + return; } - return; + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 0; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); } for(i=3;i>=0;i--) { if(!spaceAvail[i]) @@ -840,7 +1031,7 @@ void process_peer_active_transition(unifi_priv_t * priv, unifi_trace(priv, UDBG6, "p_p_a_t:data pkt sending for AC %d \n",i); while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ /* Enqueue at the head of the queue */ @@ -859,9 +1050,20 @@ void process_peer_active_transition(unifi_priv_t * priv, } } } - if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){ - unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n"); - update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + if (!staRecord->timRequestPendingFlag){ + if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)) { + unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n"); + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 0; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); } unifi_trace(priv, UDBG5, "leaving process_peer_active_transition\n"); } @@ -873,14 +1075,6 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, con netInterface_priv_t *interfacePriv; CsrUint8 i; CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - struct list_head *listHeadMaPktreq,*listHeadStaQueue; - struct list_head *placeHolderMaPktreq,*placeHolderStaQueue; - unsigned long lock_flags; - unsigned long lock_flags1; - maPktReqList_t *maPktreq = NULL; - tx_buffered_packets_t *tx_q_item = NULL; - bulk_data_param_t bulkdata; - CsrBool entryFound = FALSE; interfacePriv = priv->interfacePriv[interfaceTag]; @@ -892,260 +1086,113 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, con if(list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) && list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { unifi_trace(priv,UDBG1,"Resetting multicastTIM"); - update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF); - } - return; - } - - /* Check if a copy of the same frame (identified by host tag) is queued in driver */ - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) { - maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); - if(maPktreq->hostTag == pkt_cfm->HostTag){ - entryFound = TRUE; - break; - } - } - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - - if(entryFound){ - - /* Monitor the time difference between the MA-PACKET.req and MA-PACKET.cfm */ - unsigned long timeout; - timeout = (long)jiffies - (long)maPktreq->jiffeTime; - - /* convert into milliseconds */ - timeout = jiffies_to_msecs(timeout); - unifi_trace(priv, UDBG3, "Jiffies Time: Host Tag(%x) --> Req(%u) Cfm(%u) Diff (in ms): %u\n",maPktreq->hostTag,maPktreq->jiffeTime, jiffies, timeout); - - if( (timeout/1000) > 1) - { - unifi_trace(priv, UDBG1, "Confirm time > 2 Seconds: time = %u Status = %x\n", (timeout/1000), pkt_cfm->TransmissionStatus); - } - - if( CSR_TX_LIFETIME == pkt_cfm->TransmissionStatus || - CSR_TX_BLOCK_ACK_TIMEOUT== pkt_cfm->TransmissionStatus || - CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED== pkt_cfm->TransmissionStatus || - CSR_TX_REJECTED_PEER_STATION_SLEEPING== pkt_cfm->TransmissionStatus || - CSR_TX_REJECTED_DTIM_STARTED== pkt_cfm->TransmissionStatus ){ - - CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler]; - unifi_TrafficQueue priority_q; - struct list_head *list; - CsrResult result; - CSR_MA_PACKET_REQUEST *req = &maPktreq->signal.u.MaPacketRequest; - CsrUint16 ii=0; - CsrBool locationFound = FALSE; - CsrUint8 *sigbuffer; - - sigbuffer = (CsrUint8*)&maPktreq->signal; - if(req->Priority == CSR_MANAGEMENT){ - list = &staRecord->mgtFrames; - unifi_trace(priv,UDBG5,"mgmt list priority %d\n",req->Priority); - } - else{ - priority_q= unifi_frame_priority_to_queue(req->Priority); - list = &staRecord->dataPdu[priority_q]; - unifi_trace(priv,UDBG5,"data list priority %d\n",req->Priority); - } - - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - list_for_each_safe(listHeadStaQueue, placeHolderStaQueue, list){ - tx_q_item = list_entry(listHeadStaQueue, tx_buffered_packets_t, q); - COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item->hostTag ,maPktreq->hostTag) - - - } - if(sigbuffer[SIZEOF_SIGNAL_HEADER + 1]){ - skb_pull(maPktreq->skb,sigbuffer[SIZEOF_SIGNAL_HEADER + 1]); - } - - /* enqueue the failed packet sta queue*/ - bulkdata.d[0].os_net_buf_ptr= (unsigned char*)maPktreq->skb; - bulkdata.d[0].os_data_ptr = maPktreq->skb->data; - bulkdata.d[0].data_length = bulkdata.d[0].net_buf_length = maPktreq->skb->len; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].data_length = bulkdata.d[0].net_buf_length = 0; - unifi_trace(priv,UDBG4,"Cfm Fail for HosTag = %x with status %d so requeue it\n",maPktreq->hostTag,pkt_cfm->TransmissionStatus ); - req->TransmissionControl = 0; - - if(!locationFound){ - - if(list_empty(list)){ - result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1); - } - else{ - unifi_trace(priv,UDBG4,"did not find location so add to end of list \n"); - result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,0); - } - - - } - - else { - if(ii > 1){ - unifi_trace(priv,UDBG4,"find the location in the middle of list \n"); - result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, listHeadStaQueue,&maPktreq->signal,0); - - } - else{ - unifi_trace(priv,UDBG4," add at begining of list \n"); - result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1); + if (!interfacePriv->bcTimSetReqPendingFlag) + { + update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0xFFFFFFFF); } - } - - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - - /* Increment the counter */ - spin_lock_irqsave(&priv->staRecord_lock,lock_flags1); - staRecord->noOfPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags1); - - - - - /* after enqueuing update the TIM */ - if(CSR_RESULT_SUCCESS == result){ - if(CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE == staRecord->currentPeerState) { - if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) { - if(!staRecord->wmmOrQosEnabled) { - unifi_trace(priv, UDBG3, "uf_process_ma_pkt_cfm_for_ap :tim set due to unicast pkt & peer in powersave\n"); - update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle); - } - else { - /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ - CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) { - update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle); - } - } - } - } - } - else{ - dev_kfree_skb(maPktreq->skb); - } - } - else - { - CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler]; - if (CSR_TX_RETRY_LIMIT == pkt_cfm->TransmissionStatus || - CSR_TX_NO_BSS == pkt_cfm->TransmissionStatus) - { - if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) + else { - unifi_trace(priv, UDBG2, "CFM failed with Retry Limit or No BSS --> update TIM\n"); - update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle); + /* Cache the DTimSet value so that it will processed immidiatly after + * completing the current setDTim Request + */ + interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; + unifi_trace(priv, UDBG2, "uf_process_ma_pkt_cfm_for_ap : One more UpdateDTim Request(%d) Queued \n", + interfacePriv->bcTimSetReqQueued); } + } - else if (CSR_TX_SUCCESSFUL == pkt_cfm->TransmissionStatus) - { - staRecord->activity_flag = TRUE; - } - unifi_trace(priv, UDBG5, "CFM for HosTag = %x Status = %d, Free SKB reference\n", - maPktreq->hostTag, - pkt_cfm->TransmissionStatus ); + return; + } - dev_kfree_skb(maPktreq->skb); + /* Check if it is a Confirm for null data frame used + * for probing station activity + */ + for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { + staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); + if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) { + + unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n", + pkt_cfm->HostTag, + pkt_cfm->TransmissionStatus + ); + staRecord->nullDataHostTag = INVALID_HOST_TAG; + + if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){ + CsrTime now; + CsrTime inactive_time; + + unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n"); + /* Recheck if there is some activity after null data is sent. + * + * If still there is no activity then send a disconnected indication + * to SME to delete the station record. + */ + if (staRecord->activity_flag){ + return; + } + now = CsrTimeGet(NULL); - } - list_del(listHeadMaPktreq); - kfree(maPktreq); + if (staRecord->lastActivity > now) + { + /* simple timer wrap (for 1 wrap) */ + inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity), + now); + } + else + { + inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity); + } - }else{ - /* Check if it is a Confirm for null data frame used - * for probing station activity - */ - for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { - staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); - if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) { - - unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n", - pkt_cfm->HostTag, - pkt_cfm->TransmissionStatus - ); - staRecord->nullDataHostTag = INVALID_HOST_TAG; - - if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){ - CsrTime now; - CsrTime inactive_time; - - unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n"); - /* Recheck if there is some activity after null data is sent. - * - * If still there is no activity then send a disconnected indication - * to SME to delete the station record. - */ - if (staRecord->activity_flag){ - return; - } - now = CsrTimeGet(NULL); + if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) + { + struct list_head send_cfm_list; + CsrUint8 j; + + /* The SME/NME may be waiting for confirmation for requested frames to this station. + * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a + * a defensive check, it loops through buffered frames for this station and if confirmation + * is requested, send auto confirmation with failure status. Also flush the frames so + * that these are not processed again in PEER_DEL_REQ handler. + */ + INIT_LIST_HEAD(&send_cfm_list); - if (staRecord->lastActivity > now) - { - /* simple timer wrap (for 1 wrap) */ - inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity), - now); - } - else - { - inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity); - } + uf_prepare_send_cfm_list_for_queued_pkts(priv, + &send_cfm_list, + &(staRecord->mgtFrames)); - if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) - { - struct list_head send_cfm_list; - CsrUint8 j; - - /* The SME/NME may be waiting for confirmation for requested frames to this station. - * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a - * a defensive check, it loops through buffered frames for this station and if confirmation - * is requested, send auto confirmation with failure status. Also flush the frames so - * that these are not processed again in PEER_DEL_REQ handler. - */ - INIT_LIST_HEAD(&send_cfm_list); + uf_flush_list(priv, &(staRecord->mgtFrames)); + for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ uf_prepare_send_cfm_list_for_queued_pkts(priv, &send_cfm_list, - &(staRecord->mgtFrames)); - - uf_flush_list(priv, &(staRecord->mgtFrames)); + &(staRecord->dataPdu[j])); - for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staRecord->dataPdu[j])); - - uf_flush_list(priv,&(staRecord->dataPdu[j])); - } - - send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list); + uf_flush_list(priv,&(staRecord->dataPdu[j])); + } + send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list); - unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", - staRecord->peerMacAddress.a[0], - staRecord->peerMacAddress.a[1], - staRecord->peerMacAddress.a[2], - staRecord->peerMacAddress.a[3], - staRecord->peerMacAddress.a[4], - staRecord->peerMacAddress.a[5]); - CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - staRecord->interfacePriv->InterfaceTag, - staRecord->peerMacAddress, - CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); - } + unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", + staRecord->peerMacAddress.a[0], + staRecord->peerMacAddress.a[1], + staRecord->peerMacAddress.a[2], + staRecord->peerMacAddress.a[3], + staRecord->peerMacAddress.a[4], + staRecord->peerMacAddress.a[5]); + CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, + 0, + staRecord->interfacePriv->InterfaceTag, + staRecord->peerMacAddress, + CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); } - else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL) - { - staRecord->activity_flag = TRUE; - } + + } + else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL) + { + staRecord->activity_flag = TRUE; } } } @@ -1336,16 +1383,16 @@ static int update_macheader(unifi_priv_t *priv, struct sk_buff *skb, CsrResult csrResult; unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n"); - *priority = CSR_CONTENTION; if (qosDestination) { CsrUint8 qc = 0; unifi_trace(priv, UDBG3, "destination is QOS station \n"); - /* prepare the qos control field */ - qc |= CSR_QOS_UP0; + /* Set Ma-Packet.req UP to UP0 */ + *priority = CSR_QOS_UP0; + /* prepare the qos control field */ + qc |= CSR_QOS_UP0; /* no Amsdu is in ap buffer so eosp is left 0 */ - if (da[0] & 0x1) { /* multicast/broadcast frames, no acknowledgement needed */ qc |= 1 << 5; @@ -1763,9 +1810,6 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, */ list = &interfacePriv->genericMulticastOrBroadCastMgtFrames; - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - interfacePriv->noOfbroadcastPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS) && (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) { setBcTim=TRUE; @@ -1789,11 +1833,9 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, /* if multicast traffic is going on, buffet the unicast packets */ unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\ Buffering enabled = %d \n", priority_q,queuePacketDozing,isRouterBufferEnabled(priv,priority_q)); - signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); list = &staRecord->dataPdu[priority_q]; } else { unifi_trace(priv, UDBG5, "staRecord->dataPdu[%d] list is empty uf_process_ma_packet_req \n", priority_q); - signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); /* Pdu allowed to send to unifi */ result = ul_send_signal_unpacked(priv, &signal, bulkdata); if(result == -ENOSPC) { @@ -1816,9 +1858,6 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM */ list = &interfacePriv->genericMulticastOrBroadCastFrames; - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - interfacePriv->noOfbroadcastPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { setBcTim = TRUE; } @@ -1838,10 +1877,30 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, staRecord->noOfPktQueued++; spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); } + else if ((pktType == CSR_WIFI_MULTICAST_PDU) && (!status)) + { + /* If broadcast Tim is set && queuing is successfull, then only update TIM */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + interfacePriv->noOfbroadcastPktQueued++; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } } - if(setBcTim) { + /* If broadcast Tim is set && queuing is successfull, then only update TIM */ + if(setBcTim && !status) { unifi_trace(priv, UDBG3, "tim set due to broadcast pkt\n"); - update_tim(priv,0,1,interfaceTag, handle); + if (!interfacePriv->bcTimSetReqPendingFlag) + { + update_tim(priv,0,CSR_WIFI_TIM_SET,interfaceTag, handle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_SET; + unifi_trace(priv, UDBG2, "uf_process_ma_packet_req : One more UpdateDTim Request(:%d) Queued \n", + interfacePriv->bcTimSetReqQueued); + } } else if(staRecord && staRecord->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) { if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) { @@ -1850,15 +1909,38 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, !list_empty(&staRecord->dataPdu[3]) || !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) { unifi_trace(priv, UDBG3, "tim set due to unicast pkt & peer in powersave\n"); - update_tim(priv,staRecord->aid,1,interfaceTag, handle); - } - } else { - /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ - CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + if (!staRecord->timRequestPendingFlag){ + update_tim(priv,staRecord->aid,1,interfaceTag, handle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 1; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); + } + } + } else { + /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; /* Check if all AC's are Delivery Enabled */ is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) { - update_tim(priv,staRecord->aid,1,interfaceTag, handle); + if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable) + || (!list_empty(&staRecord->mgtFrames))) { + if (!staRecord->timRequestPendingFlag) { + update_tim(priv,staRecord->aid,1,interfaceTag, handle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 1; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); + } } } } @@ -1945,7 +2027,7 @@ CsrUint8 send_multicast_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_VO)) { while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) { buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK); - moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE; + moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE; unifi_trace(priv,UDBG2,"DTIM Occurred for interface:sending Mgt packet %d\n",interfaceTag); @@ -1986,7 +2068,7 @@ CsrUint8 send_multicast_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_CONTENTION)) { while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastFrames))) { buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; - moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE; + moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE; if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,moreData,FALSE)) == -ENOSPC) { @@ -2076,7 +2158,19 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata, if(interfacePriv->multicastPduHostTag == 0xffffffff) { unifi_notice(priv,"ma_vif_availibility_ind recevied for multicast but queues are empty%d\n",interfaceTag); /* This may be an extra request in very rare race conditions but it is fine as it would atleast remove the potential lock up */ - update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF); + if (!interfacePriv->bcTimSetReqPendingFlag) + { + update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0xFFFFFFFF); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; + unifi_trace(priv, UDBG2, "uf_process_ma_vif_availibility_ind : One more UpdateDTim Request(%d) Queued \n", + interfacePriv->bcTimSetReqQueued); + } } return; } @@ -2105,59 +2199,62 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata, #define GET_ACTIVE_INTERFACE_TAG(priv) 0 - -void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo) +static CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord) { - CsrInt8 i; - func_enter(); - - if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| - (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) - &&(!list_empty(&staInfo->mgtFrames))){ - - unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n"); - uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); - - /*This may happen because U-APSD was completed - with previous AC transfer*/ - - if(staInfo->uapsdActive == FALSE) { - return; + for(i=UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--) + { + if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + &&(!list_empty(&staRecord->dataPdu[i]))) { + unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data Available AC = %d\n", i); + return TRUE; } } - for(i=3;i>=0;i--) { + unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data NOT Available \n"); + return FALSE; +} - if(((staInfo->powersaveMode[i]== CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(staInfo->powersaveMode[i] == CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - &&(!list_empty(&staInfo->dataPdu[i]))) { - unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered data frames\n"); - uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]); - } +static CsrBool uf_is_more_data_for_usp_delivery(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord, unifi_TrafficQueue queue) +{ + CsrInt8 i; - /*This may happen because U-APSD was completed - with previous AC transfer*/ - if (staInfo->uapsdActive == FALSE) { - return; + for(i = queue; i >= UNIFI_TRAFFIC_Q_BK; i--) + { + if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + &&(!list_empty(&staRecord->dataPdu[i]))) { + unifi_trace(priv,UDBG2,"uf_is_more_data_for_usp_delivery: Data Available AC = %d\n", i); + return TRUE; } } - if (staInfo->uapsdActive && !uf_is_more_data_for_delivery_ac(priv, staInfo, TRUE)) { - /* If last packet not able to transfer due to ENOSPC & buffer management algorithm - * would have removed last packet. Then we wont update staInfo->UapsdActive = FALSE (suppose - * to update as we dont have packet to transfer at this USP) because above if loop fails as list is empty & - * update of UAPSD activity done in uf_send_buffered_data_from_delivery_ac(). - * In this situation we send QOS null & mean time update UapsdActive to FALSE here - */ - staInfo->uapsdActive = FALSE; - uf_send_qos_null(priv, GET_ACTIVE_INTERFACE_TAG(priv), staInfo->peerMacAddress.a, CSR_QOS_UP0 , staInfo); - } - func_exit(); + unifi_trace(priv,UDBG2,"uf_is_more_data_for_usp_delivery: Data NOT Available \n"); + return FALSE; } - +/* + * --------------------------------------------------------------------------- + * uf_send_buffered_data_from_delivery_ac + * + * This function takes care of + * -> Parsing the delivery enabled queue & sending frame down to HIP + * -> Setting EOSP=1 when USP to be terminated + * -> Depending on MAX SP length services the USP + * + * NOTE:This function always called from uf_handle_uspframes_delivery(), Dont + * call this function from any other location in code + * + * Arguments: + * priv Pointer to device private context struct + * vif interface specific HIP vif instance + * staInfo peer for which UAPSD to be scheduled + * queue AC from which Data to be sent in USP + * txList access category for processing list + * --------------------------------------------------------------------------- + */ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, CsrUint8 queue, @@ -2170,117 +2267,94 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrBool eosp=FALSE; CsrInt8 r =0; CsrBool moreData = FALSE; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; - netInterface_priv_t *interfacePriv; - interfacePriv = priv->interfacePriv[interfaceTag]; - func_enter(); - - /*Check U-APSD conditions if not met return from here*/ - if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)&& - (staInfo->uapsdActive == TRUE)&& - (!IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){ - - unifi_trace(priv,UDBG4,"uf_send_buffered_data_from_queue : U-APSD active. %d :Queue NOT delivery enbaled.return %\n",queue); + unifi_trace(priv, UDBG2, "++uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive); + if (queue > UNIFI_TRAFFIC_Q_VO) + { return; - } + } + while((buffered_pkt=dequeue_tx_data_pdu(priv, txList))) { + if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) { + unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: DTIM Active, suspend UAPSD, staId: 0x%x\n", + staInfo->aid); - while(!isRouterBufferEnabled(priv,queue) && - ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){ - if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){ + /* Once resume called, the U-APSD delivery operation will resume */ spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - staInfo->uapsdSuspended = TRUE; - staInfo->uapsdActive = FALSE; + staInfo->uspSuspend = TRUE; spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); /* re-queueing the packet as DTIM started */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q,txList); spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - unifi_trace(priv, UDBG3, "%s: DTIM Active while UAPSD in progress for staId: 0x%x\n",__FUNCTION__,staInfo->aid); break; } buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); - + ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)){ - moreData = uf_is_more_data_for_delivery_ac(priv,staInfo,TRUE); + if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)) { buffered_pkt->transmissionControl = TRANSMISSION_CONTROL_TRIGGER_MASK; - if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength-1)){ - moreData = FALSE; - } - - if(moreData == FALSE){ - eosp = TRUE; - staInfo->uapsdActive = FALSE; - staInfo->noOfSpFramesSent = FALSE; - buffered_pkt->transmissionControl = - (TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + /* Check All delivery enables Ac for more data, because caller of this + * function not aware about last packet + * (First check in moreData fetching helps in draining out Mgt frames Q) + */ + moreData = (!list_empty(txList) || uf_is_more_data_for_usp_delivery(priv, staInfo, queue)); - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable); - if ((allDeliveryEnabled && !dataAvailable)) { - update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle); - } - /* check the moer data for non delivery ac and update accordingly */ - else if(uf_is_more_data_for_non_delivery_ac(staInfo) ) { - update_tim(priv,staInfo->aid,1,interfaceTag, staInfo->assignedHandle); - } - else if(!uf_is_more_data_for_non_delivery_ac(staInfo) ){ - unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_send_buffered_data_from_delivery_ac\n"); - update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle); - } + if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength - 1)) { + moreData = FALSE; + } - } - } - else - { - /*Non QoS and non U-APSD.*/ - eosp = FALSE; - moreData = FALSE; - unifi_warning(priv,"uf_send_buffered_data_from_delivery_ac :non U-APSD !!! \n"); + if(moreData == FALSE) { + eosp = TRUE; + buffered_pkt->transmissionControl = + (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); + } + } else { + /* Non QoS and non U-APSD */ + unifi_warning(priv, "uf_send_buffered_data_from_delivery_ac: non U-APSD !!! \n"); } unifi_trace(priv,UDBG2,"uf_send_buffered_data_from_delivery_ac : MoreData:%d, EOSP:%d\n",moreData,eosp); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,moreData,eosp)) == -ENOSPC) { - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - list_add(&buffered_pkt->q,txList); - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle); - unifi_notice (priv," U-APSD: PDU sending failed .. no space for queue %d \n",queue); - /*Break the loop for this queue.Try for next available Delivery enabled - Queue*/ - break; + + unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: UASPD suspended, ENOSPC in hipQ=%x\n", queue); + + /* Once resume called, the U-APSD delivery operation will resume */ + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->uspSuspend = TRUE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + + spin_lock_irqsave(&priv->tx_q_lock,lock_flags); + list_add(&buffered_pkt->q,txList); + spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); + priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle); + break; } else { if(r){ /* the PDU failed where we can't do any thing so free the storage */ unifi_net_data_free(priv, &buffered_pkt->bulkdata); } - kfree(buffered_pkt); - if(staInfo->uapsdActive == TRUE){ - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - staInfo->noOfSpFramesSent = staInfo->noOfSpFramesSent + 1; - if(staInfo->noOfSpFramesSent == staInfo->maxSpLength){ - staInfo->uapsdActive = FALSE; - staInfo->noOfSpFramesSent = FALSE; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - break; - } + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->noOfSpFramesSent++; + if((!moreData) || (staInfo->noOfSpFramesSent == staInfo->maxSpLength)) { + unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: Terminating USP\n"); + staInfo->uapsdActive = FALSE; + staInfo->uspSuspend = FALSE; + staInfo->noOfSpFramesSent = 0; spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + break; } + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); } } - - func_exit(); - + unifi_trace(priv, UDBG2, "--uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive); } void uf_send_buffered_data_from_ac(unifi_priv_t *priv, @@ -2302,7 +2376,7 @@ void uf_send_buffered_data_from_ac(unifi_priv_t *priv, ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){ buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); unifi_trace(priv,UDBG3,"uf_send_buffered_data_from_ac : MoreData:%d, EOSP:%d\n",moreData,eosp); @@ -2352,7 +2426,19 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); if(!moreData) { - update_tim(priv,0,0,interfaceTag, 0XFFFFFFFF); + if (!interfacePriv->bcTimSetReqPendingFlag) + { + update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0XFFFFFFFF); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; + unifi_trace(priv, UDBG2, "uf_send_buffered_frames : One more UpdateDTim Request(%d) Queued \n", + interfacePriv->bcTimSetReqQueued); + } } } else { moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || @@ -2391,33 +2477,17 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); } } - else if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]))){ - - - if(!list_empty(&staInfo->mgtFrames)){ - /*UNIFI_TRAFFIC_Q_VO is delivery enabled push the managment frames out*/ - uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); - - } - } if(isRouterBufferEnabled(priv,queue)) { unifi_notice(priv,"uf_send_buffered_frames : No space Left for queue = %d\n",queue); break; } } - - /*push generic management frames out*/ - - if(!list_empty(&interfacePriv->genericMgtFrames)){ - - unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying generic mgt from queue=%d\n",queue); - uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames); - + if(!list_empty(&interfacePriv->genericMgtFrames)) { + unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying generic mgt from queue=%d\n",queue); + uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames); } - } @@ -2431,14 +2501,14 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); if(!staInfo) { startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS){ + if(startIndex >= UNIFI_MAX_CONNECTIONS) { startIndex = 0; } continue; } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == FALSE)){ + &&(staInfo->uapsdActive == FALSE)) { startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS){ + if(startIndex >= UNIFI_MAX_CONNECTIONS) { startIndex = 0; } continue; @@ -2448,23 +2518,15 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - &&(staInfo->uapsdActive == FALSE)){ - - if(!list_empty(&staInfo->dataPdu[queue])){ + &&(staInfo->uapsdActive == FALSE)) { + if(!list_empty(&staInfo->dataPdu[queue])) { - /*Non-UAPSD case push the AC frames out*/ - uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue])); + /*Non-UAPSD case push the AC frames out*/ + uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue])); } } - else if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){ - if(!list_empty(&staInfo->dataPdu[queue])){ - uf_send_buffered_data_from_delivery_ac(priv, staInfo, queue, &staInfo->dataPdu[queue]); - } - } - startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS){ + if(startIndex >= UNIFI_MAX_CONNECTIONS) { startIndex = 0; } } @@ -2474,47 +2536,14 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q) priv->pausedStaHandle[queue] = 0; } - /*U-APSD might have stopped because of pause.So restart it if U-APSD - was active with any of the station*/ - for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { - staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); - if(!staInfo ) { - continue; - } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == TRUE)) { - - /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by - sending data from remaining delivery enabled queues*/ - uf_continue_uapsd(priv,staInfo); - } - } + /* U-APSD might have stopped because of ENOSPC in lib_hip (pause activity). + * So restart it if U-APSD was active with any of the station + */ + unifi_trace(priv, UDBG4, "csrWifiHipSendBufferedFrames: UAPSD Resume Q=%x\n", queue); + resume_suspended_uapsd(priv, interfaceTag); func_exit(); } -CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck) -{ - CsrUint8 i; - - for(i=0;i<=3;i++) - { - if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - &&(!list_empty(&staRecord->dataPdu[i]))){ - unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data Available \n"); - return TRUE; - } - } - if((mgtCheck == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO])) - &&(!list_empty(&staRecord->mgtFrames))){ - - unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Management Data Available \n"); - - return TRUE; - } - - unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data NOT Available \n"); - return FALSE; -} CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord) { @@ -2584,101 +2613,148 @@ int uf_process_station_records_for_sending_data(unifi_priv_t *priv,CsrUint16 int return 0; } -void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv, - CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - CsrUint16 qosControl, - CsrUint16 interfaceTag) + +/* + * --------------------------------------------------------------------------- + * uf_handle_uspframes_delivery + * + * This function takes care of handling USP session for peer, when + * -> trigger frame from peer + * -> suspended USP to be processed (resumed) + * + * NOTE: uf_send_buffered_data_from_delivery_ac() always called from this function, Dont + * make a direct call to uf_send_buffered_data_from_delivery_ac() from any other part of + * code + * + * Arguments: + * priv Pointer to device private context struct + * staInfo peer for which UAPSD to be scheduled + * interfaceTag virtual interface tag + * --------------------------------------------------------------------------- + */ +static void uf_handle_uspframes_delivery(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t *staInfo, CsrUint16 interfaceTag) { - CSR_PRIORITY priority; CsrInt8 i; - unifi_TrafficQueue priority_q; + CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; + netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; unsigned long lock_flags; - func_enter(); - - /* start the U-APSD operation only if it not active*/ - if(srcStaInfo->uapsdActive == FALSE){ - /*if recceived Frames trigger Frame and Devlivery enabled AC has data - then transmit from High priorty delivery enabled AC*/ + unifi_trace(priv, UDBG2, " ++ uf_handle_uspframes_delivery, uapsd active=%x, suspended?=%x\n", + staInfo->uapsdActive, staInfo->uspSuspend); + /* Check for Buffered frames according to priority order & deliver it + * 1. AC_VO delivery enable & Mgt frames available + * 2. Process remaining Ac's from order AC_VO to AC_BK + */ - priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); - - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - - if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) - ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){ + /* USP initiated by WMMPS enabled peer & SET the status flag to TRUE */ + if (!staInfo->uspSuspend && staInfo->uapsdActive) + { + unifi_notice(priv, "uf_handle_uspframes_delivery: U-APSD already active! STA=%x:%x:%x:%x:%x:%x\n", + staInfo->peerMacAddress.a[0], staInfo->peerMacAddress.a[1], + staInfo->peerMacAddress.a[2], staInfo->peerMacAddress.a[3], + staInfo->peerMacAddress.a[4], staInfo->peerMacAddress.a[5]); + return; + } - unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd starting U-APSD operations\n"); + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->uapsdActive = TRUE; + staInfo->uspSuspend = FALSE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - /*Received Frame is trigger frame*/ - unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : Received Frame is trigger frame %d\n",priority_q); + if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| + (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) + && (!list_empty(&staInfo->mgtFrames))) { - if(((srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| - (srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) - &&(!list_empty(&srcStaInfo->mgtFrames))){ + /* Management queue has data && UNIFI_TRAFFIC_Q_VO is delivery enable */ + unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Sending buffered management frames\n"); + uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); + } - /*Trigger frame received and Data available in Delivery enabled AC - or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/ + if (!uf_is_more_data_for_delivery_ac(priv, staInfo)) { + /* All delivery enable AC's are empty, so QNULL to be sent to terminate the USP + * NOTE: If we have sent Mgt frame also, we must send QNULL followed to terminate USP + */ + if (!staInfo->uspSuspend) { spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - srcStaInfo->uapsdActive = TRUE; + staInfo->uapsdActive = FALSE; spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n"); - - /* uf_send_buffered_frames(priv, priority_q); */ - uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, UNIFI_TRAFFIC_Q_VO, &srcStaInfo->mgtFrames); - - - /*This may happen because U-APSD was completed - with previous AC transfer*/ - - if(srcStaInfo->uapsdActive == FALSE){ - return; - } - - } - - - for(i=3;i>=0;i--){ - - if(((srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - &&(!list_empty(&srcStaInfo->dataPdu[i]))){ - - - /*Trigger frame received and Data available in Delivery enabled AC - or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/ - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - srcStaInfo->uapsdActive = TRUE; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - - unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered data frames\n"); - - uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, i, &srcStaInfo->dataPdu[i]); + unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: sending QNull for trigger\n"); + uf_send_qos_null(priv, interfaceTag, staInfo->peerMacAddress.a, (CSR_PRIORITY) staInfo->triggerFramePriority, staInfo); + staInfo->triggerFramePriority = CSR_QOS_UP0; + } else { + unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: MgtQ xfer suspended\n"); + } + } else { + for(i = UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--) { + if(((staInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) + ||(staInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) + && (!list_empty(&staInfo->dataPdu[i]))) { + /* Deliver Data according to AC priority (from VO to BK) as part of USP */ + unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Buffered data frames from Queue (%d) for USP\n", i); + uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]); + } - /*This may happen because U-APSD was completed - with previous AC transfer*/ + if ((!staInfo->uapsdActive) || + (staInfo->uspSuspend && IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) { + /* If DTIM active found on one AC, No need to parse the remaining AC's + * as USP suspended. Break out of loop + */ + unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: suspend=%x, DTIM=%x, USP terminated=%s\n", + staInfo->uspSuspend, IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag), + staInfo->uapsdActive?"NO":"YES"); + break; + } + } + } - if(srcStaInfo->uapsdActive == FALSE){ - return; - } + /* Depending on the USP status, update the TIM accordingly for delivery enabled AC only + * (since we are not manipulating any Non-delivery list(AC)) + */ + is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable); + if ((allDeliveryEnabled && !dataAvailable)) { + if ((staInfo->timSet != CSR_WIFI_TIM_RESET) || (staInfo->timSet != CSR_WIFI_TIM_RESETTING)) { + staInfo->updateTimReqQueued = (CsrUint8) CSR_WIFI_TIM_RESET; + unifi_trace(priv, UDBG4, " --uf_handle_uspframes_delivery, UAPSD timset\n"); + if (!staInfo->timRequestPendingFlag) { + update_tim(priv, staInfo->aid, 0, interfaceTag, staInfo->assignedHandle); } + } + } + unifi_trace(priv, UDBG2, " --uf_handle_uspframes_delivery, uapsd active=%x, suspend?=%x\n", + staInfo->uapsdActive, staInfo->uspSuspend); +} - } - if(srcStaInfo->uapsdActive == FALSE && !(uf_is_more_data_for_delivery_ac(priv,srcStaInfo,TRUE))){ - unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd : No buffer frames so sending QOS Null in response of trigger frame\n"); - uf_send_qos_null(priv,interfaceTag,srcStaInfo->peerMacAddress.a,priority,srcStaInfo); - } +void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv, + CsrWifiRouterCtrlStaInfo_t * srcStaInfo, + CsrUint16 qosControl, + CsrUint16 interfaceTag) +{ + CSR_PRIORITY priority; + unifi_TrafficQueue priority_q; + unsigned long lock_flags; - } + unifi_trace(priv, UDBG2, "++uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive); + /* If recceived Frames trigger Frame and Devlivery enabled AC has data + * then transmit from High priorty delivery enabled AC + */ + priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); + priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - } + if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) + ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) { + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + srcStaInfo->triggerFramePriority = priority; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + unifi_trace(priv, UDBG2, "uf_process_wmm_deliver_ac_uapsd: trigger frame, Begin U-APSD, triggerQ=%x\n", priority_q); + uf_handle_uspframes_delivery(priv, srcStaInfo, interfaceTag); + } + unifi_trace(priv, UDBG2, "--uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive); +} - func_exit(); -} void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo) { bulk_data_param_t bulkdata; @@ -2686,7 +2762,7 @@ void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 struct sk_buff *skb, *newSkb = NULL; CsrWifiMacAddress peerAddress; netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_ESOP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK); + CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_EOSP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK); int r; CSR_SIGNAL signal; CsrUint32 priority_q; @@ -2928,7 +3004,19 @@ CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])); if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { unifi_trace(priv, UDBG3, "This condition should not occur\n"); - update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + if (!srcStaInfo->timRequestPendingFlag){ + update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + srcStaInfo->updateTimReqQueued = 1; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued, + srcStaInfo->aid); + } + } } else { CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0; @@ -2939,7 +3027,18 @@ CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo moreData = (uf_is_more_data_for_non_delivery_ac(srcStaInfo) || (allDeliveryEnabled && dataAvailable)); if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { - update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + if (!srcStaInfo->timRequestPendingFlag){ + update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + srcStaInfo->updateTimReqQueued = 1; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued, + srcStaInfo->aid); + } } } } @@ -2993,10 +3092,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || !list_empty(&staRecord->mgtFrames)); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q, &staRecord->mgtFrames); @@ -3016,10 +3115,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO])); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]); @@ -3038,10 +3137,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; moreData = !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); @@ -3065,7 +3164,18 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm !list_empty(&staRecord->mgtFrames)); if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); - update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + if (!staRecord->timRequestPendingFlag){ + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 0; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); + } } } else { @@ -3074,9 +3184,9 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm /*Send Data From Management Frames*/ /* Priority orders for delivering the buffered packets are - * 1. UNIFI_TRAFFIC_Q_VO, if its non delivery enabled - * 2. management frames - * 3. Other access catagory frames which are non deliver enable + * 1. Deliver the Management frames if there + * 2. Other access catagory frames which are non deliver enable including UNIFI_TRAFFIC_Q_VO + * priority is from VO->BK */ /* Check if all AC's are Delivery Enabled */ @@ -3088,42 +3198,18 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm return; } - if ((!IS_DELIVERY_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO])) && - (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || !list_empty(&staRecord->mgtFrames))) { - /* UNIFI_TRAFFIC_Q_VO is non delivery enabled, & check for packets are there to send from this AC */ - if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]))) { - moreData = uf_is_more_data_for_non_delivery_ac(staRecord); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); - - /* Last parameter is EOSP & its false always for PS-POLL processing */ - if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]); - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } else if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { + if (!list_empty(&staRecord->mgtFrames)) { + if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { /* We dont have packets in non delivery enabled UNIFI_TRAFFIC_Q_VO, So we are looking in management * queue of the station record */ moreData = uf_is_more_data_for_non_delivery_ac(staRecord); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Last parameter is EOSP & its false always for PS-POLL processing */ if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q, &staRecord->mgtFrames); @@ -3138,24 +3224,27 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm } kfree(buffered_pkt); } + } else { + unifi_error(priv, "uf_process_ps_poll: Mgt frame list empty!! \n"); } + } else { CsrInt8 i; - /* We dont have buffered packet in UNIFI_TRAFFIC_Q_VO & mangement frame queue (1 & 2 failed), So proceed with 3 condition - * UNIFI_TRAFFIC_Q_VO is taken care so start with i index = 2 + /* We dont have buffered packet in mangement frame queue (1 failed), So proceed with condition 2 + * UNIFI_TRAFFIC_Q_VO -> VI -> BE -> BK */ - for(i= 2; i>=0; i--) { + for(i= 3; i>=0; i--) { if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) { /* Send One packet, if queue is NULL then continue */ if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { moreData = uf_is_more_data_for_non_delivery_ac(staRecord); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Last parameter is EOSP & its false always for PS-POLL processing */ if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) { /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK); + buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_add(&buffered_pkt->q, &staRecord->dataPdu[i]); @@ -3181,7 +3270,19 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)); if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); - update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + if (!staRecord->timRequestPendingFlag){ + update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle); + } + else + { + /* Cache the TimSet value so that it will processed immidiatly after + * completing the current setTim Request + */ + staRecord->updateTimReqQueued = 0; + unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, + staRecord->aid); + } + } } @@ -3297,31 +3398,7 @@ void uf_flush_list(unifi_priv_t * priv, struct list_head * list) } spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); } -void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list) -{ - struct list_head *listHeadMaPktreq,*placeHolderMaPktreq; - maPktReqList_t *maPktreq; - unsigned long lock_flags; - unifi_trace(priv, UDBG5, "entering the uf_flush_maPktlist \n"); - - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - /* go through list, delete & free memory */ - list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, list) { - maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q); - - if(!maPktreq) { - unifi_error(priv, "entry should exists, otherwise crashes (bug)\n"); - } - /* free the allocated memory */ - dev_kfree_skb(maPktreq->skb); - list_del(listHeadMaPktreq); - kfree(maPktreq); - maPktreq = NULL; - - } - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); -} tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList) { /* dequeue the tx data packets from the appropriate queue */ @@ -3521,7 +3598,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) while(!isRouterBufferEnabled(priv,3) && ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) { buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,0,FALSE)) == -ENOSPC) { /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); @@ -3547,7 +3624,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) if (staInfo && (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)) { while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) { buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) { unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full for voice queue\n"); /* Enqueue at the head of the queue */ @@ -3573,7 +3650,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag) while((buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->dataPdu[j]))) { buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK); + ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) { /* Enqueue at the head of the queue */ spin_lock_irqsave(&priv->tx_q_lock,lock_flags); @@ -3615,7 +3692,7 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 int spin_lock_irqsave(&priv->tx_q_lock,lock_flags); list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK; + tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); unifi_trace(priv, UDBG1,"updating eosp for list Head hostTag:= 0x%x ",tx_q_item->hostTag); break; @@ -3624,105 +3701,51 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 int } func_exit(); } + +/* + * --------------------------------------------------------------------------- + * resume_suspended_uapsd + * + * This function takes care processing packets of Unscheduled Service Period, + * which been suspended earlier due to DTIM/HIP ENOSPC scenarios + * + * Arguments: + * priv Pointer to device private context struct + * interfaceTag For which resume should happen + * --------------------------------------------------------------------------- + */ void resume_suspended_uapsd(unifi_priv_t* priv,CsrUint16 interfaceTag) { CsrUint8 startIndex; CsrWifiRouterCtrlStaInfo_t * staInfo = NULL; - unsigned long lock_flags; - /*U-APSD might have stopped because of multicast. So restart it if U-APSD - was active with any of the station*/ + unsigned long lock_flags; + + unifi_trace(priv, UDBG2, "++resume_suspended_uapsd: \n"); for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag); - if(!staInfo ) { + + if(!staInfo || !staInfo->wmmOrQosEnabled) { continue; } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdSuspended == TRUE)) { - - /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by - sending data from remaining delivery enabled queues*/ - spin_lock_irqsave(&priv->staRecord_lock,lock_flags); - staInfo->uapsdActive = TRUE; - staInfo->uapsdSuspended = FALSE; - spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); - uf_continue_uapsd(priv,staInfo); - } - } - -} -void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata, - CSR_SIGNAL *sigptr, CsrUint32 alignOffset) -{ - - maPktReqList_t *maPktreq = NULL; - CSR_MA_PACKET_REQUEST *req = &sigptr->u.MaPacketRequest; - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - CsrUint16 frmCtrl,interfaceTag = 0; - const CsrUint8* macHdrLocation; - struct sk_buff *skb ; - unsigned long lock_flags; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CsrUint8 *sigbuffer; - CsrUint8 frameType = 0; - func_enter(); - - if(bulkdata == NULL || (0 == bulkdata->d[0].data_length )){ - unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece:bulk data NULL \n"); - func_exit(); - return; - } - macHdrLocation = bulkdata->d[0].os_data_ptr; - skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - /* fectch the frame control value from mac header */ - frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); - - /* Processing done according to Frame/Packet type */ - frameType = ((frmCtrl & 0x000c) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); - - if( (((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_QOS_NULL) || - ((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_NULL ) ) || - ( IEEE802_11_FRAMETYPE_MANAGEMENT== frameType)){ - - /* if packet is NULL or Qos Null no need of retransmit so dont queue it*/ - unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: NULL data Pkt or mgmt\n"); - func_exit(); - return; - } - - /* fetch the station record for corresponding peer mac address */ - if ((staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, req->Ra.x, interfaceTag))) { - maPktreq = (maPktReqList_t*)kmalloc(sizeof(maPktReqList_t),GFP_ATOMIC); - if(maPktreq == NULL){ - unifi_error(priv, - "uf_store_directed_ma_packet_referenece :: Failed to allocate %d byter for maPktreq\n", - sizeof(maPktReqList_t)); - func_exit(); - return; + &&staInfo->uapsdActive && staInfo->uspSuspend) { + /* U-APSD Still active & previously suspended either ENOSPC of FH queues OR + * due to DTIM activity + */ + uf_handle_uspframes_delivery(priv, staInfo, interfaceTag); + } else { + unifi_trace(priv, UDBG2, "resume_suspended_uapsd: PS state=%x, uapsdActive?=%x, suspend?=%x\n", + staInfo->currentPeerState, staInfo->uapsdActive, staInfo->uspSuspend); + if (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) + { + spin_lock_irqsave(&priv->staRecord_lock,lock_flags); + staInfo->uapsdActive = FALSE; + staInfo->uspSuspend = FALSE; + spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags); + } } } - - /* staRecord not present that means packet is multicast or generic mgmt so no need to queue it */ - else{ - unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: multicast pkt \n"); - func_exit(); - return ; - } - - /* disbale preemption */ - spin_lock_irqsave(&priv->tx_q_lock,lock_flags); - INIT_LIST_HEAD(&maPktreq->q); - maPktreq->staHandler = staRecord->assignedHandle; - memcpy(&maPktreq->signal,sigptr,sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + sizeof(CSR_MA_PACKET_REQUEST)); - sigbuffer = (CsrUint8*)&maPktreq->signal; - sigbuffer[SIZEOF_SIGNAL_HEADER + 1] = alignOffset; - maPktreq->skb = skb_get(skb); - maPktreq->hostTag = req->HostTag; - maPktreq->jiffeTime = jiffies; - list_add_tail(&maPktreq->q,&interfacePriv->directedMaPktReq); - - spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags); - func_exit(); - + unifi_trace(priv, UDBG2, "--resume_suspended_uapsd:\n"); } #endif diff --git a/drivers/staging/csr/unifi_priv.h b/drivers/staging/csr/unifi_priv.h index f687f270a699..b23c84456578 100644 --- a/drivers/staging/csr/unifi_priv.h +++ b/drivers/staging/csr/unifi_priv.h @@ -44,6 +44,10 @@ #include +#ifdef ANDROID_BUILD +#include +#endif + #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_unifi_udi.h" #include "csr_wifi_router_lib.h" @@ -63,6 +67,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; #include "unifi_wext.h" #endif +#ifdef ANDROID_BUILD +extern struct wake_lock unifi_sdio_wake_lock; +#endif + #include "unifi_clients.h" @@ -98,18 +106,14 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; #include "unifi_sme.h" #endif -#undef COMPARE_HOST_TAG_TO_ENQUEUE -#define COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item_hosttag,maPktHostTag) \ - if(tx_q_item_hosttag > maPktHostTag){ \ - locationFound = TRUE; \ - ii++; \ - break; \ - } \ - ii++; \ - - /* The device major number to use when registering the udi driver */ #define UNIFI_NAME "unifi" +/* + * MAX_UNIFI_DEVS defines the maximum number of UniFi devices that can be present. + * This number should be set to the number of SDIO slots supported by the SDIO + * host controller on the platform. + * Note: If MAX_UNIFI_DEVS value changes, fw_init[] needs to be corrected in drv.c + */ #define MAX_UNIFI_DEVS 2 /* 802.11 Mac header offsets */ @@ -156,6 +160,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; #define IEEE802_11_QC_TID_MASK 0x0f #define IEEE802_11_QC_A_MSDU_PRESENT 0x80 +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND)) +#define IEEE802_11_QC_NON_TID_BITS_MASK 0xFFF0 +#endif + #define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36 #define MAX_ACCESS_CATOGORY 4 @@ -185,6 +193,9 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; #define STA_INACTIVE_DETECTION_TIMER_INTERVAL 30 /* in seconds */ #define STA_INACTIVE_TIMEOUT_VAL 120*1000*1000 /* 120 seconds */ +/* Test for modes requiring AP firmware patch */ +#define CSR_WIFI_HIP_IS_AP_FW(mode) ((((mode) == CSR_WIFI_ROUTER_CTRL_MODE_AP) || \ + ((mode) == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) ? TRUE : FALSE) /* Defines used in beacon filtering in case of P2P */ #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH 0x7 @@ -220,6 +231,9 @@ extern int sdio_block_size; extern int coredump_max; extern int run_bh_once; extern int bh_priority; +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +extern int log_hip_signals; +#endif struct dlpriv { const unsigned char *dl_data; @@ -331,7 +345,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t { CsrTime lastActivity; /* during m/c transmission sp suspended */ - CsrBool uapsdSuspended; + CsrBool uspSuspend; + CSR_PRIORITY triggerFramePriority; #endif CsrWifiRouterCtrlPeerStatus currentPeerState; struct list_head dataPdu[MAX_ACCESS_CATOGORY]; @@ -349,6 +364,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t { #define CSR_WIFI_TIM_RESETTING 2 #define CSR_WIFI_TIM_SETTING 3 + CsrBool timRequestPendingFlag; + CsrUint8 updateTimReqQueued; CsrUint16 noOfPktQueued; }CsrWifiRouterCtrlStaInfo_t; @@ -609,8 +626,14 @@ struct unifi_priv { /* Spinlock to protect M4 data */ spinlock_t m4_lock; - /* Spinlock to protect BA RX data */ - spinlock_t ba_lock; + /* Mutex to protect BA RX data */ + struct semaphore ba_mutex; + +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + /* Spinlock to protect the WAPI data */ + spinlock_t wapi_lock; +#endif + #ifndef ALLOW_Q_PAUSE /* Array to indicate if a particular Tx queue is paused, this may not be * required in a multiqueue implementation since we can directly stop kernel @@ -630,10 +653,24 @@ struct unifi_priv { CsrUint32 rxUdpThroughput; CsrUint32 txUdpThroughput; - +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + /*Set if multicast KeyID = 1*/ CsrUint8 wapi_multicast_filter; + /*Set if unicast KeyID = 1*/ CsrUint8 wapi_unicast_filter; CsrUint8 wapi_unicast_queued_pkt_filter; +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + CsrBool isWapiConnection; +#endif +#endif + +#ifdef CSR_WIFI_SPLIT_PATCH + CsrWifiRouterCtrlModeSetReq pending_mode_set; +#endif + + CsrBool cmanrTestMode; + CSR_RATE cmanrTestModeTransmitRate; + }; typedef struct { @@ -682,6 +719,9 @@ typedef struct netInterface_priv CsrUint8 ba_complete_index; CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS]; struct work_struct send_m4_ready_task; +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + struct work_struct send_pkt_to_encrypt; +#endif struct net_device_stats stats; CsrUint8 interfaceMode; CsrBool protect; @@ -721,7 +761,6 @@ typedef struct netInterface_priv struct list_head genericMgtFrames; struct list_head genericMulticastOrBroadCastFrames; struct list_head genericMulticastOrBroadCastMgtFrames; - struct list_head directedMaPktReq; /* Timer for detecting station inactivity */ struct timer_list sta_activity_check_timer; @@ -740,6 +779,13 @@ typedef struct netInterface_priv /* Buffered M4 signal to take care of WPA race condition */ CSR_SIGNAL m4_signal; bulk_data_desc_t m4_bulk_data; + +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) + /* Buffered WAPI Unicast MA Packet Request for encryption in Sme */ + CSR_SIGNAL wapi_unicast_ma_pkt_sig; + bulk_data_desc_t wapi_unicast_bulk_data; +#endif + /* This should be removed and m4_hostTag should be used for checking*/ CsrBool m4_sent; CSR_CLIENT_TAG m4_hostTag; @@ -747,17 +793,11 @@ typedef struct netInterface_priv CsrBool intraBssEnabled; CsrUint32 multicastPduHostTag; /* Used to set the tim after getting a confirm for it */ + CsrBool bcTimSet; + CsrBool bcTimSetReqPendingFlag; + CsrBool bcTimSetReqQueued; } netInterface_priv_t; -typedef struct maPktReqList{ - struct list_head q; - struct sk_buff *skb; - CSR_SIGNAL signal; - CSR_CLIENT_TAG hostTag; - CsrUint32 staHandler; - unsigned long jiffeTime; -}maPktReqList_t; - #ifndef ALLOW_Q_PAUSE #define net_is_tx_q_paused(priv, q) (priv->tx_q_paused_flag[q]) #define net_tx_q_unpause(priv, q) (priv->tx_q_paused_flag[q] = 0) @@ -925,7 +965,6 @@ int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, bulk_data_param_t *bulkdata, CsrUint8 macHeaderLengthInBytes); CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord); -CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck); void uf_process_wmm_deliver_ac_uapsd ( unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, CsrUint16 qosControl, @@ -937,7 +976,6 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtr void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo); void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); void uf_send_nulldata(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); -void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata,CSR_SIGNAL *sigptr,CsrUint32 alignOffset); @@ -956,7 +994,6 @@ void send_auto_ma_packet_confirm(unifi_priv_t *priv, netInterface_priv_t *interfacePriv, struct list_head *buffered_frames_list); void uf_flush_list(unifi_priv_t * priv, struct list_head * list); -void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list); tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList); void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag); void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 interfaceTag); @@ -1073,6 +1110,11 @@ void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, CsrWifiMacAddress source_address, int indicate, CsrUint16 interfaceTag); +#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE +int uf_register_hip_offline_debug(unifi_priv_t *priv); +int uf_unregister_hip_offline_debug(unifi_priv_t *priv); +#endif + /* * inet.c */ diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c index 4ee663fe4e4a..54414ed2ed1c 100644 --- a/drivers/staging/csr/unifi_sme.c +++ b/drivers/staging/csr/unifi_sme.c @@ -447,6 +447,7 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg) { unifi_cfg_power_t cfg_power; int rc; + int wol; if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) { unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); @@ -455,16 +456,24 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg) switch (cfg_power) { case UNIFI_CFG_POWER_OFF: + priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; rc = sme_sys_suspend(priv); if (rc) { return rc; } break; case UNIFI_CFG_POWER_ON: + wol = priv->wol_suspend; rc = sme_sys_resume(priv); if (rc) { return rc; } + if (wol) { + /* Kick the BH to ensure pending transfers are handled when + * a suspend happened with card powered. + */ + unifi_send_signal(priv->card, NULL, 0, NULL); + } break; default: unifi_error(priv, "WIFI POWER: Unknown value.\n"); @@ -921,10 +930,19 @@ int supportedRates[i++]=0x8b; supportedRates[i++]=0x96; } else if(n) { + /* For some strange reasons WiFi stack needs both b and g rates*/ supportedRates[i++]=0x02; supportedRates[i++]=0x04; supportedRates[i++]=0x0b; supportedRates[i++]=0x16; + supportedRates[i++]=0x0c; + supportedRates[i++]=0x12; + supportedRates[i++]=0x18; + supportedRates[i++]=0x24; + supportedRates[i++]=0x30; + supportedRates[i++]=0x48; + supportedRates[i++]=0x60; + supportedRates[i++]=0x6c; } if(g) { if(!b) { @@ -1162,3 +1180,65 @@ uf_send_m4_ready_wq(struct work_struct *work) } /* uf_send_m4_ready_wq() */ +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) +/* + * --------------------------------------------------------------------------- + * uf_send_pkt_to_encrypt + * + * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1 + * These are done in a deferred work queue for two reasons: + * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context + * - we want to load the main driver data path as lightly as possible + * + * Arguments: + * work Pointer to work queue item. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void uf_send_pkt_to_encrypt(struct work_struct *work) +{ + netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt); + CsrUint16 interfaceTag = interfacePriv->InterfaceTag; + unifi_priv_t *priv = interfacePriv->privPtr; + + CsrUint32 pktBulkDataLength; + CsrUint8 *pktBulkData; + unsigned long flags; + + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { + + func_enter(); + + pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length; + + if (pktBulkDataLength > 0) { + pktBulkData = (CsrUint8 *)CsrPmemAlloc(pktBulkDataLength); + CsrMemSet(pktBulkData, 0, pktBulkDataLength); + } else { + unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n"); + return; + } + + spin_lock_irqsave(&priv->wapi_lock, flags); + /* Copy over the MA PKT REQ bulk data */ + CsrMemCpy(pktBulkData, (CsrUint8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength); + /* Free any bulk data buffers allocated for the WAPI Data pkt */ + unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data); + interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0; + interfacePriv->wapi_unicast_bulk_data.data_length = 0; + interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL; + spin_unlock_irqrestore(&priv->wapi_lock, flags); + + CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData); + unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n"); + + CsrPmemFree(pktBulkData); /* Would have been copied over by the SME Handler */ + + func_exit(); + } else { + unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode); + } +}/* uf_send_pkt_to_encrypt() */ +#endif diff --git a/drivers/staging/csr/unifi_sme.h b/drivers/staging/csr/unifi_sme.h index 51ca92e89055..3cbee81f1b0a 100644 --- a/drivers/staging/csr/unifi_sme.h +++ b/drivers/staging/csr/unifi_sme.h @@ -50,6 +50,7 @@ enum sme_request_status { SME_REQUEST_PENDING, SME_REQUEST_RECEIVED, SME_REQUEST_TIMEDOUT, + SME_REQUEST_CANCELLED, }; /* Structure to hold a UDI logged signal */ @@ -123,6 +124,7 @@ void uf_ta_wq(struct work_struct *work); #endif void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func); +void uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status); /* @@ -148,6 +150,13 @@ void uf_sme_config_wq(struct work_struct *work); */ void uf_send_m4_ready_wq(struct work_struct *work); +#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) +/* + * To send data pkt to Sme for encryption + */ +void uf_send_pkt_to_encrypt(struct work_struct *work); +#endif + int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig); diff --git a/drivers/staging/csr/unifiio.h b/drivers/staging/csr/unifiio.h index e707eedef29d..4ab050bc71cb 100644 --- a/drivers/staging/csr/unifiio.h +++ b/drivers/staging/csr/unifiio.h @@ -212,20 +212,19 @@ typedef struct { -typedef enum unifi_putest_command { - UNIFI_PUTEST_START, - UNIFI_PUTEST_STOP, - UNIFI_PUTEST_SET_SDIO_CLOCK, - UNIFI_PUTEST_CMD52_READ, - UNIFI_PUTEST_CMD52_WRITE, - UNIFI_PUTEST_DL_FW, - UNIFI_PUTEST_DL_FW_BUFF, - UNIFI_PUTEST_CMD52_BLOCK_READ, - UNIFI_PUTEST_COREDUMP_PREPARE, - UNIFI_PUTEST_GP_READ16, - UNIFI_PUTEST_GP_WRITE16 - -} unifi_putest_command_t; +typedef CsrUint8 unifi_putest_command_t; + +#define UNIFI_PUTEST_START 0 +#define UNIFI_PUTEST_STOP 1 +#define UNIFI_PUTEST_SET_SDIO_CLOCK 2 +#define UNIFI_PUTEST_CMD52_READ 3 +#define UNIFI_PUTEST_CMD52_WRITE 4 +#define UNIFI_PUTEST_DL_FW 5 +#define UNIFI_PUTEST_DL_FW_BUFF 6 +#define UNIFI_PUTEST_CMD52_BLOCK_READ 7 +#define UNIFI_PUTEST_COREDUMP_PREPARE 8 +#define UNIFI_PUTEST_GP_READ16 9 +#define UNIFI_PUTEST_GP_WRITE16 10 struct unifi_putest_cmd52 { -- GitLab From 9c645d2f887bd92df487b2c5dcd44d5fc0e7c761 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 07:40:39 +1000 Subject: [PATCH 0914/5711] twl4030_charger: Fix some typos Signed-off-by: NeilBrown Signed-off-by: Anton Vorontsov --- drivers/power/twl4030_charger.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index fdad850c77d3..3e6e99101106 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -103,7 +103,7 @@ static int twl4030_bci_read(u8 reg, u8 *val) static int twl4030_clear_set_boot_bci(u8 clear, u8 set) { - return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0, + return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear, TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, TWL4030_PM_MASTER_BOOT_BCI); } @@ -151,14 +151,14 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci) } /* - * Enable/Disable USB Charge funtionality. + * Enable/Disable USB Charge functionality. */ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) { int ret; if (enable) { - /* Check for USB charger conneted */ + /* Check for USB charger connected */ if (!twl4030_bci_have_vbus(bci)) return -ENODEV; -- GitLab From 210d4bc8a3128e3e61ac3bf4657114f8e6450e2a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 07:40:40 +1000 Subject: [PATCH 0915/5711] twl4030_charger: Add backup-battery charging This allows a voltage and current (bb_uvolts and bb_uamps) to be specified in the platform_data, and charging of the backup battery will be enabled with those specification. As it is not possible to monitor the backup battery at all there is no new device created to represent it. Signed-off-by: NeilBrown Signed-off-by: Anton Vorontsov --- drivers/power/twl4030_charger.c | 59 +++++++++++++++++++++++++++++++++ include/linux/i2c/twl.h | 2 ++ 2 files changed, 61 insertions(+) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 3e6e99101106..0511610b235f 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -28,6 +28,7 @@ #define TWL4030_BCIVBUS 0x0c #define TWL4030_BCIMFSTS4 0x10 #define TWL4030_BCICTL1 0x23 +#define TWL4030_BB_CFG 0x12 #define TWL4030_BCIAUTOWEN BIT(5) #define TWL4030_CONFIG_DONE BIT(4) @@ -37,6 +38,17 @@ #define TWL4030_USBFASTMCHG BIT(2) #define TWL4030_STS_VBUS BIT(7) #define TWL4030_STS_USB_ID BIT(2) +#define TWL4030_BBCHEN BIT(4) +#define TWL4030_BBSEL_MASK 0b1100 +#define TWL4030_BBSEL_2V5 0b0000 +#define TWL4030_BBSEL_3V0 0b0100 +#define TWL4030_BBSEL_3V1 0b1000 +#define TWL4030_BBSEL_3V2 0b1100 +#define TWL4030_BBISEL_MASK 0b11 +#define TWL4030_BBISEL_25uA 0b00 +#define TWL4030_BBISEL_150uA 0b01 +#define TWL4030_BBISEL_500uA 0b10 +#define TWL4030_BBISEL_1000uA 0b11 /* BCI interrupts */ #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ @@ -201,6 +213,49 @@ static int twl4030_charger_enable_ac(bool enable) return ret; } +/* + * Enable/Disable charging of Backup Battery. + */ +static int twl4030_charger_enable_backup(int uvolt, int uamp) +{ + int ret; + u8 flags; + + if (uvolt < 2500000 || + uamp < 25) { + /* disable charging of backup battery */ + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, + TWL4030_BBCHEN, 0, TWL4030_BB_CFG); + return ret; + } + + flags = TWL4030_BBCHEN; + if (uvolt >= 3200000) + flags |= TWL4030_BBSEL_3V2; + else if (uvolt >= 3100000) + flags |= TWL4030_BBSEL_3V1; + else if (uvolt >= 3000000) + flags |= TWL4030_BBSEL_3V0; + else + flags |= TWL4030_BBSEL_2V5; + + if (uamp >= 1000) + flags |= TWL4030_BBISEL_1000uA; + else if (uamp >= 500) + flags |= TWL4030_BBISEL_500uA; + else if (uamp >= 150) + flags |= TWL4030_BBISEL_150uA; + else + flags |= TWL4030_BBISEL_25uA; + + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, + TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, + flags, + TWL4030_BB_CFG); + + return ret; +} + /* * TWL4030 CHG_PRES (AC charger presence) events */ @@ -424,6 +479,7 @@ static enum power_supply_property twl4030_charger_props[] = { static int __init twl4030_bci_probe(struct platform_device *pdev) { struct twl4030_bci *bci; + struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; int ret; u32 reg; @@ -503,6 +559,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) twl4030_charger_enable_ac(true); twl4030_charger_enable_usb(bci, true); + twl4030_charger_enable_backup(pdata->bb_uvolt, + pdata->bb_uamp); return 0; @@ -531,6 +589,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) twl4030_charger_enable_ac(false); twl4030_charger_enable_usb(bci, false); + twl4030_charger_enable_backup(0, 0); /* mask interrupts */ twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 3993477103a5..8eec4403b170 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -555,6 +555,8 @@ struct twl4030_clock_init_data { struct twl4030_bci_platform_data { int *battery_tmp_tbl; unsigned int tblsize; + int bb_uvolt; /* voltage to charge backup battery */ + int bb_uamp; /* current for backup battery charging */ }; /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */ -- GitLab From ab37813f4093a5f59cb8e083cde277289dc72ed3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 07:40:40 +1000 Subject: [PATCH 0916/5711] twl4030_charger: Allow charger to control the regulator that feeds it The charger needs usb3v1 to be running, so add a new consumer to keep it running. This allows the charger to draw current even when the USB driver has powered down. Signed-off-by: NeilBrown Acked-by: Tero Kristo Acked-by: Samuel Ortiz Signed-off-by: Anton Vorontsov --- drivers/mfd/twl-core.c | 9 +++++---- drivers/power/twl4030_charger.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 6fc90befa79e..269b296a0975 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -716,8 +716,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, static struct regulator_consumer_supply usb1v8 = { .supply = "usb1v8", }; - static struct regulator_consumer_supply usb3v1 = { - .supply = "usb3v1", + static struct regulator_consumer_supply usb3v1[] = { + { .supply = "usb3v1" }, + { .supply = "bci3v1" }, }; /* First add the regulators so that they can be used by transceiver */ @@ -745,7 +746,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); child = add_regulator_linked(TWL4030_REG_VUSB3V1, - &usb_fixed, &usb3v1, 1, + &usb_fixed, usb3v1, 2, features); if (IS_ERR(child)) return PTR_ERR(child); @@ -766,7 +767,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, if (twl_has_regulator() && child) { usb1v5.dev_name = dev_name(child); usb1v8.dev_name = dev_name(child); - usb3v1.dev_name = dev_name(child); + usb3v1[0].dev_name = dev_name(child); } } if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 0511610b235f..bbda08377a42 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -21,6 +21,7 @@ #include #include #include +#include #define TWL4030_BCIMSTATEC 0x02 #define TWL4030_BCIICHG 0x08 @@ -86,6 +87,8 @@ struct twl4030_bci { struct work_struct work; int irq_chg; int irq_bci; + struct regulator *usb_reg; + int usb_enabled; unsigned long event; }; @@ -183,6 +186,12 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) return -EACCES; } + /* Need to keep regulator on */ + if (!bci->usb_enabled) { + regulator_enable(bci->usb_reg); + bci->usb_enabled = 1; + } + /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); if (ret < 0) @@ -193,6 +202,10 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); } else { ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); + if (bci->usb_enabled) { + regulator_disable(bci->usb_reg); + bci->usb_enabled = 0; + } } return ret; @@ -511,6 +524,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props); bci->usb.get_property = twl4030_bci_get_property; + bci->usb_reg = regulator_get(bci->dev, "bci3v1"); + ret = power_supply_register(&pdev->dev, &bci->usb); if (ret) { dev_err(&pdev->dev, "failed to register usb: %d\n", ret); -- GitLab From 5da50988a1bf8c05611db77521777baaca14da29 Mon Sep 17 00:00:00 2001 From: Nikolaus Voss Date: Wed, 9 May 2012 08:30:44 +0200 Subject: [PATCH 0917/5711] sbs-battery: Don't trigger false supply_changed event power_supply_changed() events are triggerd based on the return value of a get_property() call. However the property TECHNOLOGY is hard-coded to LION in this driver, thus always succeeds. So, with the battery removed, this triggers a false battery present uevent. This uevent triggers a new query via power_supply_uevent() which again starts to query all known properties and thus leads to an infinite loop of battery present/not-present uevents. This patch skips the battery presence detection for the hard-coded property TECHNOLOGY. Signed-off-by: Nikolaus Voss Acked-by Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/sbs-battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c index a5b6849d4123..a65e8f54157e 100644 --- a/drivers/power/sbs-battery.c +++ b/drivers/power/sbs-battery.c @@ -469,7 +469,7 @@ static int sbs_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; - break; + goto done; /* don't trigger power_supply_changed()! */ case POWER_SUPPLY_PROP_ENERGY_NOW: case POWER_SUPPLY_PROP_ENERGY_FULL: -- GitLab From 9903e62700a122a366ad4c9be8f8f97115cf9a68 Mon Sep 17 00:00:00 2001 From: Syed Rafiuddin Date: Thu, 17 May 2012 12:51:15 +0530 Subject: [PATCH 0918/5711] bq27x00_battery: Add support for power average and health properties Addition of power average and health properties. Signed-off-by: Syed Rafiuddin Signed-off-by: Anton Vorontsov --- drivers/power/bq27x00_battery.c | 71 +++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index f5d6d379f2fb..5657990b7ace 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -51,6 +51,7 @@ #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ #define BQ27x00_REG_AE 0x22 /* Available energy */ +#define BQ27x00_POWER_AVG 0x24 #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ @@ -66,8 +67,10 @@ #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ #define BQ27500_FLAG_FC BIT(9) +#define BQ27500_FLAG_OTC BIT(15) #define BQ27000_RS 20 /* Resistor sense */ +#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) struct bq27x00_device_info; struct bq27x00_access_methods { @@ -86,6 +89,8 @@ struct bq27x00_reg_cache { int capacity; int energy; int flags; + int power_avg; + int health; }; struct bq27x00_device_info { @@ -123,6 +128,8 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_POWER_AVG, + POWER_SUPPLY_PROP_HEALTH, }; static unsigned int poll_interval = 360; @@ -306,6 +313,60 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg) return tval * 60; } +/* + * Read a power avg register. + * Return < 0 if something fails. + */ +static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg) +{ + int tval; + + tval = bq27x00_read(di, reg, false); + if (tval < 0) { + dev_err(di->dev, "error reading power avg rgister %02x: %d\n", + reg, tval); + return tval; + } + + if (di->chip == BQ27500) + return tval; + else + return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS; +} + +/* + * Read flag register. + * Return < 0 if something fails. + */ +static int bq27x00_battery_read_health(struct bq27x00_device_info *di) +{ + int tval; + + tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false); + if (tval < 0) { + dev_err(di->dev, "error reading flag register:%d\n", tval); + return tval; + } + + if ((di->chip == BQ27500)) { + if (tval & BQ27500_FLAG_SOCF) + tval = POWER_SUPPLY_HEALTH_DEAD; + else if (tval & BQ27500_FLAG_OTC) + tval = POWER_SUPPLY_HEALTH_OVERHEAT; + else + tval = POWER_SUPPLY_HEALTH_GOOD; + return tval; + } else { + if (tval & BQ27000_FLAG_EDV1) + tval = POWER_SUPPLY_HEALTH_DEAD; + else + tval = POWER_SUPPLY_HEALTH_GOOD; + return tval; + } + + return -1; +} + static void bq27x00_update(struct bq27x00_device_info *di) { struct bq27x00_reg_cache cache = {0, }; @@ -321,6 +382,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) cache.time_to_empty_avg = -ENODATA; cache.time_to_full = -ENODATA; cache.charge_full = -ENODATA; + cache.health = -ENODATA; } else { cache.capacity = bq27x00_battery_read_rsoc(di); cache.energy = bq27x00_battery_read_energy(di); @@ -328,9 +390,12 @@ static void bq27x00_update(struct bq27x00_device_info *di) cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); cache.charge_full = bq27x00_battery_read_lmd(di); + cache.health = bq27x00_battery_read_health(di); } cache.temperature = bq27x00_battery_read_temperature(di); cache.cycle_count = bq27x00_battery_read_cyct(di); + cache.power_avg = + bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); /* We only have to read charge design full once */ if (di->charge_design_full <= 0) @@ -550,6 +615,12 @@ static int bq27x00_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ENERGY_NOW: ret = bq27x00_simple_value(di->cache.energy, val); break; + case POWER_SUPPLY_PROP_POWER_AVG: + ret = bq27x00_simple_value(di->cache.power_avg, val); + break; + case POWER_SUPPLY_PROP_HEALTH: + ret = bq27x00_simple_value(di->cache.health, val); + break; default: return -EINVAL; } -- GitLab From ecb7a8ebdc4b063715d5a37919f9118c3f1031a8 Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Tue, 22 May 2012 14:20:04 +0530 Subject: [PATCH 0919/5711] gpio-charger: Use cansleep version of gpio_set_value Context of gpio_charger_get_property is sleepable so we should use gpio_set_value_cansleep instead of gpio_set_value. It will remove WARN_ON incase of using gpio from i2c-to-gpio expander like pca953x. Signed-off-by: Pritesh Raithatha Acked-by: Lars-Peter Clausen Signed-off-by: Anton Vorontsov --- drivers/power/gpio-charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 8672c9177dd7..cb2aa3195687 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c @@ -54,7 +54,7 @@ static int gpio_charger_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: - val->intval = gpio_get_value(pdata->gpio); + val->intval = gpio_get_value_cansleep(pdata->gpio); val->intval ^= pdata->gpio_active_low; break; default: -- GitLab From d7dc9e32ae64b5db777017344da61a285c2347f8 Mon Sep 17 00:00:00 2001 From: Markus Bollinger Date: Wed, 20 Jun 2012 08:32:48 +0200 Subject: [PATCH 0920/5711] ALSA: pcxhr: Fix a counter wrap fix a counter wrap to avoid resynchronization of stream positions every several minutes. The resynchronization may create stream position jitter Signed-off-by: Markus Bollinger Signed-off-by: Takashi Iwai --- sound/pci/pcxhr/pcxhr_core.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 304411c1fe4b..841703b5c52a 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -1133,13 +1133,12 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; hw_sample_count += (u_int64_t)rmh.stat[1]; - snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", + snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", stream->pipe->is_capture ? 'C' : 'P', stream->substream->number, - (long unsigned int)hw_sample_count, - (long unsigned int)(stream->timer_abs_periods + - stream->timer_period_frag + - mgr->granularity)); + hw_sample_count, + stream->timer_abs_periods + stream->timer_period_frag + + mgr->granularity); return hw_sample_count; } @@ -1243,10 +1242,18 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) if ((dsp_time_diff < 0) && (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { - snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " - "resynchronize all streams\n", + /* handle dsp counter wraparound without resync */ + int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; + snd_printdd("WARNING DSP timestamp old(%d) new(%d)", mgr->dsp_time_last, dsp_time_new); - mgr->dsp_time_err++; + if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { + snd_printdd("-> timestamp wraparound OK: " + "diff=%d\n", tmp_diff); + dsp_time_diff = tmp_diff; + } else { + snd_printdd("-> resynchronize all streams\n"); + mgr->dsp_time_err++; + } } #ifdef CONFIG_SND_DEBUG_VERBOSE if (dsp_time_diff == 0) -- GitLab From fdfbaf69e0b9d6843c0da6501caf4ecacec0f775 Mon Sep 17 00:00:00 2001 From: Markus Bollinger Date: Wed, 20 Jun 2012 08:34:40 +0200 Subject: [PATCH 0921/5711] ALSA: pcxhr: Add LTC support add LTC (linear timecode) read function via proc interface to the pcxhr driver Signed-off-by: Markus Bollinger Signed-off-by: Takashi Iwai --- sound/pci/pcxhr/pcxhr.c | 63 +++++++++++++++++++++++++++++++++++ sound/pci/pcxhr/pcxhr.h | 1 + sound/pci/pcxhr/pcxhr_core.c | 4 +++ sound/pci/pcxhr/pcxhr_core.h | 4 ++- sound/pci/pcxhr/pcxhr_mix22.c | 11 ++++++ sound/pci/pcxhr/pcxhr_mix22.h | 1 + 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 0435f45e9513..e3ac1f768ff6 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1368,6 +1368,67 @@ static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, } } +/* Access to the results of the CMD_GET_TIME_CODE RMH */ +#define TIME_CODE_VALID_MASK 0x00800000 +#define TIME_CODE_NEW_MASK 0x00400000 +#define TIME_CODE_BACK_MASK 0x00200000 +#define TIME_CODE_WAIT_MASK 0x00100000 + +/* Values for the CMD_MANAGE_SIGNAL RMH */ +#define MANAGE_SIGNAL_TIME_CODE 0x01 +#define MANAGE_SIGNAL_MIDI 0x02 + +/* linear time code read proc*/ +static void pcxhr_proc_ltc(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct snd_pcxhr *chip = entry->private_data; + struct pcxhr_mgr *mgr = chip->mgr; + struct pcxhr_rmh rmh; + unsigned int ltcHrs, ltcMin, ltcSec, ltcFrm; + int err; + /* commands available when embedded DSP is running */ + if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) { + snd_iprintf(buffer, "no firmware loaded\n"); + return; + } + if (!mgr->capture_ltc) { + pcxhr_init_rmh(&rmh, CMD_MANAGE_SIGNAL); + rmh.cmd[0] |= MANAGE_SIGNAL_TIME_CODE; + err = pcxhr_send_msg(mgr, &rmh); + if (err) { + snd_iprintf(buffer, "ltc not activated (%d)\n", err); + return; + } + if (mgr->is_hr_stereo) + hr222_manage_timecode(mgr, 1); + else + pcxhr_write_io_num_reg_cont(mgr, REG_CONT_VALSMPTE, + REG_CONT_VALSMPTE, NULL); + mgr->capture_ltc = 1; + } + pcxhr_init_rmh(&rmh, CMD_GET_TIME_CODE); + err = pcxhr_send_msg(mgr, &rmh); + if (err) { + snd_iprintf(buffer, "ltc read error (err=%d)\n", err); + return ; + } + ltcHrs = 10*((rmh.stat[0] >> 8) & 0x3) + (rmh.stat[0] & 0xf); + ltcMin = 10*((rmh.stat[1] >> 16) & 0x7) + ((rmh.stat[1] >> 8) & 0xf); + ltcSec = 10*(rmh.stat[1] & 0x7) + ((rmh.stat[2] >> 16) & 0xf); + ltcFrm = 10*((rmh.stat[2] >> 8) & 0x3) + (rmh.stat[2] & 0xf); + + snd_iprintf(buffer, "timecode: %02u:%02u:%02u-%02u\n", + ltcHrs, ltcMin, ltcSec, ltcFrm); + snd_iprintf(buffer, "raw: 0x%04x%06x%06x\n", rmh.stat[0] & 0x00ffff, + rmh.stat[1] & 0xffffff, rmh.stat[2] & 0xffffff); + /*snd_iprintf(buffer, "dsp ref time: 0x%06x%06x\n", + rmh.stat[3] & 0xffffff, rmh.stat[4] & 0xffffff);*/ + if (!(rmh.stat[0] & TIME_CODE_VALID_MASK)) { + snd_iprintf(buffer, "warning: linear timecode not valid\n"); + } +} + static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) { struct snd_info_entry *entry; @@ -1383,6 +1444,8 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) entry->c.text.write = pcxhr_proc_gpo_write; entry->mode |= S_IWUSR; } + if (!snd_card_proc_new(chip->card, "ltc", &entry)) + snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc); } /* end of proc interface */ diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index bda776c49884..a4c602c45173 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h @@ -103,6 +103,7 @@ struct pcxhr_mgr { unsigned int board_has_mic:1; /* if 1 the board has microphone input */ unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ unsigned int mono_capture:1; /* if 1 the board does mono capture */ + unsigned int capture_ltc:1; /* if 1 the board captures LTC input */ struct snd_dma_buffer hostport; diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 841703b5c52a..b33db1e006e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -504,6 +504,8 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, +[CMD_GET_TIME_CODE] = { 0x060000, 5, RMH_SSIZE_FIXED }, +[CMD_MANAGE_SIGNAL] = { 0x0f0000, 0, RMH_SSIZE_FIXED }, }; #ifdef CONFIG_SND_DEBUG_VERBOSE @@ -533,6 +535,8 @@ static char* cmd_names[] = { [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", +[CMD_GET_TIME_CODE] = "CMD_GET_TIME_CODE", +[CMD_MANAGE_SIGNAL] = "CMD_MANAGE_SIGNAL", }; #endif diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index be0173796cdb..a81ab6b811e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h @@ -79,6 +79,8 @@ enum { CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ + CMD_GET_TIME_CODE, /* cmd_len = 1 stat_len = 5 */ + CMD_MANAGE_SIGNAL, /* cmd_len = 1 stat_len = 0 */ CMD_LAST_INDEX }; @@ -116,7 +118,7 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh); #define IO_NUM_REG_OUT_ANA_LEVEL 20 #define IO_NUM_REG_IN_ANA_LEVEL 21 - +#define REG_CONT_VALSMPTE 0x000800 #define REG_CONT_UNMUTE_INPUTS 0x020000 /* parameters used with register IO_NUM_REG_STATUS */ diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index 1cb82c0a9cb3..84fe57626eba 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c @@ -53,6 +53,7 @@ #define PCXHR_DSP_RESET_DSP 0x01 #define PCXHR_DSP_RESET_MUTE 0x02 #define PCXHR_DSP_RESET_CODEC 0x08 +#define PCXHR_DSP_RESET_SMPTE 0x10 #define PCXHR_DSP_RESET_GPO_OFFSET 5 #define PCXHR_DSP_RESET_GPO_MASK 0x60 @@ -527,6 +528,16 @@ int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) return 0; } +int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable) +{ + if (enable) + mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE; + else + mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE; + + PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); + return 0; +} int hr222_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h index 5a37a0007e8f..5971b9933f41 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.h +++ b/sound/pci/pcxhr/pcxhr_mix22.h @@ -34,6 +34,7 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); +int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable); #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ -- GitLab From 24fe5ddc5f189606bde68136ac808da37e4dfe04 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 19 Jun 2012 16:20:23 -0300 Subject: [PATCH 0922/5711] sound: swarm_cs4297: Provide definitions for AC97 registers This patch removes the last usage of linux/ac97_codec.h by re-defining used AC97 registers. We can't use sound/ac97_codec.h here, since it is an OSS driver. Cc: Ralf Baechle Cc: Jaroslav Kysela Cc: Clemens Ladisch Signed-off-by: Ezequiel Garcia Signed-off-by: Takashi Iwai --- sound/oss/swarm_cs4297a.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 09d46484bc1a..7d8803a00b79 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -199,6 +198,22 @@ static const char invalid_magic[] = } \ }) +/* AC97 registers */ +#define AC97_MASTER_VOL_STEREO 0x0002 /* Line Out */ +#define AC97_PCBEEP_VOL 0x000a /* none */ +#define AC97_PHONE_VOL 0x000c /* TAD Input (mono) */ +#define AC97_MIC_VOL 0x000e /* MIC Input (mono) */ +#define AC97_LINEIN_VOL 0x0010 /* Line Input (stereo) */ +#define AC97_CD_VOL 0x0012 /* CD Input (stereo) */ +#define AC97_AUX_VOL 0x0016 /* Aux Input (stereo) */ +#define AC97_PCMOUT_VOL 0x0018 /* Wave Output (stereo) */ +#define AC97_RECORD_SELECT 0x001a /* */ +#define AC97_RECORD_GAIN 0x001c +#define AC97_GENERAL_PURPOSE 0x0020 +#define AC97_3D_CONTROL 0x0022 +#define AC97_POWER_CONTROL 0x0026 +#define AC97_VENDOR_ID1 0x007c + struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; typedef struct serdma_descr_s { -- GitLab From 33eb3311f3ad4a14f2e55d36fdb0d3ec54712231 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 19 Jun 2012 16:20:24 -0300 Subject: [PATCH 0923/5711] sound: Remove unused include/linux/ac97_codec.h header This file has been superseded by include/sound/ac97_codec.h, and has currently no users. Cc: Ralf Baechle Cc: Jaroslav Kysela Cc: Clemens Ladisch Signed-off-by: Ezequiel Garcia Signed-off-by: Takashi Iwai --- include/linux/ac97_codec.h | 362 ------------------------------------- 1 file changed, 362 deletions(-) delete mode 100644 include/linux/ac97_codec.h diff --git a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h deleted file mode 100644 index 0260c3e79fdd..000000000000 --- a/include/linux/ac97_codec.h +++ /dev/null @@ -1,362 +0,0 @@ -#ifndef _AC97_CODEC_H_ -#define _AC97_CODEC_H_ - -#include -#include - -/* AC97 1.0 */ -#define AC97_RESET 0x0000 // -#define AC97_MASTER_VOL_STEREO 0x0002 // Line Out -#define AC97_HEADPHONE_VOL 0x0004 // -#define AC97_MASTER_VOL_MONO 0x0006 // TAD Output -#define AC97_MASTER_TONE 0x0008 // -#define AC97_PCBEEP_VOL 0x000a // none -#define AC97_PHONE_VOL 0x000c // TAD Input (mono) -#define AC97_MIC_VOL 0x000e // MIC Input (mono) -#define AC97_LINEIN_VOL 0x0010 // Line Input (stereo) -#define AC97_CD_VOL 0x0012 // CD Input (stereo) -#define AC97_VIDEO_VOL 0x0014 // none -#define AC97_AUX_VOL 0x0016 // Aux Input (stereo) -#define AC97_PCMOUT_VOL 0x0018 // Wave Output (stereo) -#define AC97_RECORD_SELECT 0x001a // -#define AC97_RECORD_GAIN 0x001c -#define AC97_RECORD_GAIN_MIC 0x001e -#define AC97_GENERAL_PURPOSE 0x0020 -#define AC97_3D_CONTROL 0x0022 -#define AC97_MODEM_RATE 0x0024 -#define AC97_POWER_CONTROL 0x0026 - -/* AC'97 2.0 */ -#define AC97_EXTENDED_ID 0x0028 /* Extended Audio ID */ -#define AC97_EXTENDED_STATUS 0x002A /* Extended Audio Status */ -#define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */ -#define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */ -#define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */ -#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR ADC Rate */ -#define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */ -#define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */ -#define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */ -#define AC97_RESERVED_3A 0x003A /* Reserved in AC '97 < 2.2 */ - -/* AC'97 2.2 */ -#define AC97_SPDIF_CONTROL 0x003A /* S/PDIF Control */ - -/* range 0x3c-0x58 - MODEM */ -#define AC97_EXTENDED_MODEM_ID 0x003C -#define AC97_EXTEND_MODEM_STAT 0x003E -#define AC97_LINE1_RATE 0x0040 -#define AC97_LINE2_RATE 0x0042 -#define AC97_HANDSET_RATE 0x0044 -#define AC97_LINE1_LEVEL 0x0046 -#define AC97_LINE2_LEVEL 0x0048 -#define AC97_HANDSET_LEVEL 0x004A -#define AC97_GPIO_CONFIG 0x004C -#define AC97_GPIO_POLARITY 0x004E -#define AC97_GPIO_STICKY 0x0050 -#define AC97_GPIO_WAKE_UP 0x0052 -#define AC97_GPIO_STATUS 0x0054 -#define AC97_MISC_MODEM_STAT 0x0056 -#define AC97_RESERVED_58 0x0058 - -/* registers 0x005a - 0x007a are vendor reserved */ - -#define AC97_VENDOR_ID1 0x007c -#define AC97_VENDOR_ID2 0x007e - -/* volume control bit defines */ -#define AC97_MUTE 0x8000 -#define AC97_MICBOOST 0x0040 -#define AC97_LEFTVOL 0x3f00 -#define AC97_RIGHTVOL 0x003f - -/* record mux defines */ -#define AC97_RECMUX_MIC 0x0000 -#define AC97_RECMUX_CD 0x0101 -#define AC97_RECMUX_VIDEO 0x0202 -#define AC97_RECMUX_AUX 0x0303 -#define AC97_RECMUX_LINE 0x0404 -#define AC97_RECMUX_STEREO_MIX 0x0505 -#define AC97_RECMUX_MONO_MIX 0x0606 -#define AC97_RECMUX_PHONE 0x0707 - -/* general purpose register bit defines */ -#define AC97_GP_LPBK 0x0080 /* Loopback mode */ -#define AC97_GP_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 */ -#define AC97_GP_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic */ -#define AC97_GP_RLBK 0x0400 /* Remote Loopback - Modem line codec */ -#define AC97_GP_LLBK 0x0800 /* Local Loopback - Modem Line codec */ -#define AC97_GP_LD 0x1000 /* Loudness 1=on */ -#define AC97_GP_3D 0x2000 /* 3D Enhancement 1=on */ -#define AC97_GP_ST 0x4000 /* Stereo Enhancement 1=on */ -#define AC97_GP_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ - -/* extended audio status and control bit defines */ -#define AC97_EA_VRA 0x0001 /* Variable bit rate enable bit */ -#define AC97_EA_DRA 0x0002 /* Double-rate audio enable bit */ -#define AC97_EA_SPDIF 0x0004 /* S/PDIF Enable bit */ -#define AC97_EA_VRM 0x0008 /* Variable bit rate for MIC enable bit */ -#define AC97_EA_CDAC 0x0040 /* PCM Center DAC is ready (Read only) */ -#define AC97_EA_SDAC 0x0040 /* PCM Surround DACs are ready (Read only) */ -#define AC97_EA_LDAC 0x0080 /* PCM LFE DAC is ready (Read only) */ -#define AC97_EA_MDAC 0x0100 /* MIC ADC is ready (Read only) */ -#define AC97_EA_SPCV 0x0400 /* S/PDIF configuration valid (Read only) */ -#define AC97_EA_PRI 0x0800 /* Turns the PCM Center DAC off */ -#define AC97_EA_PRJ 0x1000 /* Turns the PCM Surround DACs off */ -#define AC97_EA_PRK 0x2000 /* Turns the PCM LFE DAC off */ -#define AC97_EA_PRL 0x4000 /* Turns the MIC ADC off */ -#define AC97_EA_SLOT_MASK 0xffcf /* Mask for slot assignment bits */ -#define AC97_EA_SPSA_3_4 0x0000 /* Slot assigned to 3 & 4 */ -#define AC97_EA_SPSA_7_8 0x0010 /* Slot assigned to 7 & 8 */ -#define AC97_EA_SPSA_6_9 0x0020 /* Slot assigned to 6 & 9 */ -#define AC97_EA_SPSA_10_11 0x0030 /* Slot assigned to 10 & 11 */ - -/* S/PDIF control bit defines */ -#define AC97_SC_PRO 0x0001 /* Professional status */ -#define AC97_SC_NAUDIO 0x0002 /* Non audio stream */ -#define AC97_SC_COPY 0x0004 /* Copyright status */ -#define AC97_SC_PRE 0x0008 /* Preemphasis status */ -#define AC97_SC_CC_MASK 0x07f0 /* Category Code mask */ -#define AC97_SC_L 0x0800 /* Generation Level status */ -#define AC97_SC_SPSR_MASK 0xcfff /* S/PDIF Sample Rate bits */ -#define AC97_SC_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */ -#define AC97_SC_SPSR_48K 0x2000 /* Use 48kHz Sample rate */ -#define AC97_SC_SPSR_32K 0x3000 /* Use 32kHz Sample rate */ -#define AC97_SC_DRS 0x4000 /* Double Rate S/PDIF */ -#define AC97_SC_V 0x8000 /* Validity status */ - -/* powerdown control and status bit defines */ - -/* status */ -#define AC97_PWR_MDM 0x0010 /* Modem section ready */ -#define AC97_PWR_REF 0x0008 /* Vref nominal */ -#define AC97_PWR_ANL 0x0004 /* Analog section ready */ -#define AC97_PWR_DAC 0x0002 /* DAC section ready */ -#define AC97_PWR_ADC 0x0001 /* ADC section ready */ - -/* control */ -#define AC97_PWR_PR0 0x0100 /* ADC and Mux powerdown */ -#define AC97_PWR_PR1 0x0200 /* DAC powerdown */ -#define AC97_PWR_PR2 0x0400 /* Output mixer powerdown (Vref on) */ -#define AC97_PWR_PR3 0x0800 /* Output mixer powerdown (Vref off) */ -#define AC97_PWR_PR4 0x1000 /* AC-link powerdown */ -#define AC97_PWR_PR5 0x2000 /* Internal Clk disable */ -#define AC97_PWR_PR6 0x4000 /* HP amp powerdown */ -#define AC97_PWR_PR7 0x8000 /* Modem off - if supported */ - -/* extended audio ID register bit defines */ -#define AC97_EXTID_VRA 0x0001 -#define AC97_EXTID_DRA 0x0002 -#define AC97_EXTID_SPDIF 0x0004 -#define AC97_EXTID_VRM 0x0008 -#define AC97_EXTID_DSA0 0x0010 -#define AC97_EXTID_DSA1 0x0020 -#define AC97_EXTID_CDAC 0x0040 -#define AC97_EXTID_SDAC 0x0080 -#define AC97_EXTID_LDAC 0x0100 -#define AC97_EXTID_AMAP 0x0200 -#define AC97_EXTID_REV0 0x0400 -#define AC97_EXTID_REV1 0x0800 -#define AC97_EXTID_ID0 0x4000 -#define AC97_EXTID_ID1 0x8000 - -/* extended status register bit defines */ -#define AC97_EXTSTAT_VRA 0x0001 -#define AC97_EXTSTAT_DRA 0x0002 -#define AC97_EXTSTAT_SPDIF 0x0004 -#define AC97_EXTSTAT_VRM 0x0008 -#define AC97_EXTSTAT_SPSA0 0x0010 -#define AC97_EXTSTAT_SPSA1 0x0020 -#define AC97_EXTSTAT_CDAC 0x0040 -#define AC97_EXTSTAT_SDAC 0x0080 -#define AC97_EXTSTAT_LDAC 0x0100 -#define AC97_EXTSTAT_MADC 0x0200 -#define AC97_EXTSTAT_SPCV 0x0400 -#define AC97_EXTSTAT_PRI 0x0800 -#define AC97_EXTSTAT_PRJ 0x1000 -#define AC97_EXTSTAT_PRK 0x2000 -#define AC97_EXTSTAT_PRL 0x4000 - -/* extended audio ID register bit defines */ -#define AC97_EXTID_VRA 0x0001 -#define AC97_EXTID_DRA 0x0002 -#define AC97_EXTID_SPDIF 0x0004 -#define AC97_EXTID_VRM 0x0008 -#define AC97_EXTID_DSA0 0x0010 -#define AC97_EXTID_DSA1 0x0020 -#define AC97_EXTID_CDAC 0x0040 -#define AC97_EXTID_SDAC 0x0080 -#define AC97_EXTID_LDAC 0x0100 -#define AC97_EXTID_AMAP 0x0200 -#define AC97_EXTID_REV0 0x0400 -#define AC97_EXTID_REV1 0x0800 -#define AC97_EXTID_ID0 0x4000 -#define AC97_EXTID_ID1 0x8000 - -/* extended status register bit defines */ -#define AC97_EXTSTAT_VRA 0x0001 -#define AC97_EXTSTAT_DRA 0x0002 -#define AC97_EXTSTAT_SPDIF 0x0004 -#define AC97_EXTSTAT_VRM 0x0008 -#define AC97_EXTSTAT_SPSA0 0x0010 -#define AC97_EXTSTAT_SPSA1 0x0020 -#define AC97_EXTSTAT_CDAC 0x0040 -#define AC97_EXTSTAT_SDAC 0x0080 -#define AC97_EXTSTAT_LDAC 0x0100 -#define AC97_EXTSTAT_MADC 0x0200 -#define AC97_EXTSTAT_SPCV 0x0400 -#define AC97_EXTSTAT_PRI 0x0800 -#define AC97_EXTSTAT_PRJ 0x1000 -#define AC97_EXTSTAT_PRK 0x2000 -#define AC97_EXTSTAT_PRL 0x4000 - -/* useful power states */ -#define AC97_PWR_D0 0x0000 /* everything on */ -#define AC97_PWR_D1 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4 -#define AC97_PWR_D2 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 -#define AC97_PWR_D3 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 -#define AC97_PWR_ANLOFF AC97_PWR_PR2|AC97_PWR_PR3 /* analog section off */ - -/* Total number of defined registers. */ -#define AC97_REG_CNT 64 - - -/* OSS interface to the ac97s.. */ -#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|SOUND_MASK_PCM|\ - SOUND_MASK_LINE|SOUND_MASK_CD|\ - SOUND_MASK_ALTPCM|SOUND_MASK_IGAIN|\ - SOUND_MASK_LINE1|SOUND_MASK_VIDEO) - -#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \ - SOUND_MASK_BASS|SOUND_MASK_TREBLE|\ - SOUND_MASK_SPEAKER|SOUND_MASK_MIC|\ - SOUND_MASK_PHONEIN|SOUND_MASK_PHONEOUT) - -#define AC97_RECORD_MASK (SOUND_MASK_MIC|\ - SOUND_MASK_CD|SOUND_MASK_IGAIN|SOUND_MASK_VIDEO|\ - SOUND_MASK_LINE1| SOUND_MASK_LINE|\ - SOUND_MASK_PHONEIN) - -/* original check is not good enough in case FOO is greater than - * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly - * SOUND_MIXER_NRDEVICES elements. - * before matching the given mixer against the bitmask in supported_mixers we - * check if mixer number exceeds maximum allowed size which is as mentioned - * above SOUND_MIXER_NRDEVICES */ -#define supported_mixer(CODEC,FOO) ((FOO >= 0) && \ - (FOO < SOUND_MIXER_NRDEVICES) && \ - (CODEC)->supported_mixers & (1< Date: Sat, 9 Jun 2012 02:40:03 -0700 Subject: [PATCH 0924/5711] slab/mempolicy: always use local policy from interrupt context slab_node() could access current->mempolicy from interrupt context. However there's a race condition during exit where the mempolicy is first freed and then the pointer zeroed. Using this from interrupts seems bogus anyways. The interrupt will interrupt a random process and therefore get a random mempolicy. Many times, this will be idle's, which noone can change. Just disable this here and always use local for slab from interrupts. I also cleaned up the callers of slab_node a bit which always passed the same argument. I believe the original mempolicy code did that in fact, so it's likely a regression. v2: send version with correct logic v3: simplify. fix typo. Reported-by: Arun Sharma Cc: penberg@kernel.org Cc: cl@linux.com Signed-off-by: Andi Kleen [tdmackey@twitter.com: Rework control flow based on feedback from cl@linux.com, fix logic, and cleanup current task_struct reference] Acked-by: David Rientjes Acked-by: Christoph Lameter Acked-by: KOSAKI Motohiro Signed-off-by: David Mackey Signed-off-by: Pekka Enberg --- include/linux/mempolicy.h | 2 +- mm/mempolicy.c | 8 +++++++- mm/slab.c | 4 ++-- mm/slub.c | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 4aa42732e47f..95b738c7abff 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -215,7 +215,7 @@ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, extern bool init_nodemask_of_mempolicy(nodemask_t *mask); extern bool mempolicy_nodemask_intersects(struct task_struct *tsk, const nodemask_t *mask); -extern unsigned slab_node(struct mempolicy *policy); +extern unsigned slab_node(void); extern enum zone_type policy_zone; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f15c1b24ca18..cb0b230aa3f2 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1602,8 +1602,14 @@ static unsigned interleave_nodes(struct mempolicy *policy) * task can change it's policy. The system default policy requires no * such protection. */ -unsigned slab_node(struct mempolicy *policy) +unsigned slab_node(void) { + struct mempolicy *policy; + + if (in_interrupt()) + return numa_node_id(); + + policy = current->mempolicy; if (!policy || policy->flags & MPOL_F_LOCAL) return numa_node_id(); diff --git a/mm/slab.c b/mm/slab.c index fc4a77446700..dd607a8e6706 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3310,7 +3310,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD)) nid_alloc = cpuset_slab_spread_node(); else if (current->mempolicy) - nid_alloc = slab_node(current->mempolicy); + nid_alloc = slab_node(); if (nid_alloc != nid_here) return ____cache_alloc_node(cachep, flags, nid_alloc); return NULL; @@ -3342,7 +3342,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) retry_cpuset: cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); retry: /* diff --git a/mm/slub.c b/mm/slub.c index 797271f5afb8..348fed1643f4 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1617,7 +1617,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, do { cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { struct kmem_cache_node *n; -- GitLab From d24ac77f71ded6a013bacb09f359eac0b0f29a80 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Fri, 18 May 2012 22:01:17 +0900 Subject: [PATCH 0925/5711] slub: use __cmpxchg_double_slab() at interrupt disabled place get_freelist(), unfreeze_partials() are only called with interrupt disabled, so __cmpxchg_double_slab() is suitable. Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg --- mm/slub.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 348fed1643f4..4f406cd899b7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1872,7 +1872,11 @@ redo: } } -/* Unfreeze all the cpu partial slabs */ +/* + * Unfreeze all the cpu partial slabs. + * + * This function must be called with interrupt disabled. + */ static void unfreeze_partials(struct kmem_cache *s) { struct kmem_cache_node *n = NULL; @@ -1928,7 +1932,7 @@ static void unfreeze_partials(struct kmem_cache *s) l = m; } - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, old.freelist, old.counters, new.freelist, new.counters, "unfreezing slab")); @@ -2165,6 +2169,8 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * The page is still frozen if the return value is not NULL. * * If this function returns NULL then the page has been unfrozen. + * + * This function must be called with interrupt disabled. */ static inline void *get_freelist(struct kmem_cache *s, struct page *page) { @@ -2182,7 +2188,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) new.inuse = page->objects; new.frozen = freelist != NULL; - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, freelist, counters, NULL, new.counters, "get_freelist")); -- GitLab From 43d77867a4f333de4e4189114c480dd365133c09 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Sat, 9 Jun 2012 02:23:16 +0900 Subject: [PATCH 0926/5711] slub: refactoring unfreeze_partials() Current implementation of unfreeze_partials() is so complicated, but benefit from it is insignificant. In addition many code in do {} while loop have a bad influence to a fail rate of cmpxchg_double_slab. Under current implementation which test status of cpu partial slab and acquire list_lock in do {} while loop, we don't need to acquire a list_lock and gain a little benefit when front of the cpu partial slab is to be discarded, but this is a rare case. In case that add_partial is performed and cmpxchg_double_slab is failed, remove_partial should be called case by case. I think that these are disadvantages of current implementation, so I do refactoring unfreeze_partials(). Minimizing code in do {} while loop introduce a reduced fail rate of cmpxchg_double_slab. Below is output of 'slabinfo -r kmalloc-256' when './perf stat -r 33 hackbench 50 process 4000 > /dev/null' is done. ** before ** Cmpxchg_double Looping ------------------------ Locked Cmpxchg Double redos 182685 Unlocked Cmpxchg Double redos 0 ** after ** Cmpxchg_double Looping ------------------------ Locked Cmpxchg Double redos 177995 Unlocked Cmpxchg Double redos 1 We can see cmpxchg_double_slab fail rate is improved slightly. Bolow is output of './perf stat -r 30 hackbench 50 process 4000 > /dev/null'. ** before ** Performance counter stats for './hackbench 50 process 4000' (30 runs): 108517.190463 task-clock # 7.926 CPUs utilized ( +- 0.24% ) 2,919,550 context-switches # 0.027 M/sec ( +- 3.07% ) 100,774 CPU-migrations # 0.929 K/sec ( +- 4.72% ) 124,201 page-faults # 0.001 M/sec ( +- 0.15% ) 401,500,234,387 cycles # 3.700 GHz ( +- 0.24% ) stalled-cycles-frontend stalled-cycles-backend 250,576,913,354 instructions # 0.62 insns per cycle ( +- 0.13% ) 45,934,956,860 branches # 423.297 M/sec ( +- 0.14% ) 188,219,787 branch-misses # 0.41% of all branches ( +- 0.56% ) 13.691837307 seconds time elapsed ( +- 0.24% ) ** after ** Performance counter stats for './hackbench 50 process 4000' (30 runs): 107784.479767 task-clock # 7.928 CPUs utilized ( +- 0.22% ) 2,834,781 context-switches # 0.026 M/sec ( +- 2.33% ) 93,083 CPU-migrations # 0.864 K/sec ( +- 3.45% ) 123,967 page-faults # 0.001 M/sec ( +- 0.15% ) 398,781,421,836 cycles # 3.700 GHz ( +- 0.22% ) stalled-cycles-frontend stalled-cycles-backend 250,189,160,419 instructions # 0.63 insns per cycle ( +- 0.09% ) 45,855,370,128 branches # 425.436 M/sec ( +- 0.10% ) 169,881,248 branch-misses # 0.37% of all branches ( +- 0.43% ) 13.596272341 seconds time elapsed ( +- 0.22% ) No regression is found, but rather we can see slightly better result. Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg --- mm/slub.c | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 4f406cd899b7..f96d8bcec54f 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1879,18 +1879,24 @@ redo: */ static void unfreeze_partials(struct kmem_cache *s) { - struct kmem_cache_node *n = NULL; + struct kmem_cache_node *n = NULL, *n2 = NULL; struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); struct page *page, *discard_page = NULL; while ((page = c->partial)) { - enum slab_modes { M_PARTIAL, M_FREE }; - enum slab_modes l, m; struct page new; struct page old; c->partial = page->next; - l = M_FREE; + + n2 = get_node(s, page_to_nid(page)); + if (n != n2) { + if (n) + spin_unlock(&n->list_lock); + + n = n2; + spin_lock(&n->list_lock); + } do { @@ -1903,43 +1909,17 @@ static void unfreeze_partials(struct kmem_cache *s) new.frozen = 0; - if (!new.inuse && (!n || n->nr_partial > s->min_partial)) - m = M_FREE; - else { - struct kmem_cache_node *n2 = get_node(s, - page_to_nid(page)); - - m = M_PARTIAL; - if (n != n2) { - if (n) - spin_unlock(&n->list_lock); - - n = n2; - spin_lock(&n->list_lock); - } - } - - if (l != m) { - if (l == M_PARTIAL) { - remove_partial(n, page); - stat(s, FREE_REMOVE_PARTIAL); - } else { - add_partial(n, page, - DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); - } - - l = m; - } - } while (!__cmpxchg_double_slab(s, page, old.freelist, old.counters, new.freelist, new.counters, "unfreezing slab")); - if (m == M_FREE) { + if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) { page->next = discard_page; discard_page = page; + } else { + add_partial(n, page, DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); } } -- GitLab From 21cd683d318041c63876b4acbebb3f6d9d80597b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2012 09:19:32 +0200 Subject: [PATCH 0927/5711] ALSA: hda - Fix the pin nid assignment in patch_hdmi.c This fixes the regression introduced by the commit d0b1252d for refactoring simple_hdmi*(). The pin NID wasn't assigned correctly. Reported-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8891fa658382..72a3b26736ae 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1607,7 +1607,7 @@ static int patch_simple_hdmi(struct hda_codec *codec, spec->num_cvts = 1; spec->num_pins = 1; spec->cvts[0].cvt_nid = cvt_nid; - spec->cvts[0].cvt_nid = pin_nid; + spec->pins[0].pin_nid = pin_nid; spec->pcm_playback = simple_pcm_playback; codec->patch_ops = simple_hdmi_patch_ops; -- GitLab From ccfcf7d151c01969133b5555eed635537c41c944 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2012 09:30:42 +0200 Subject: [PATCH 0928/5711] ALSA: hda - Add missing snd_hda_jack_detect_enable() for simple_hdmi*() Reported-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 72a3b26736ae..db8f6928f839 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1415,13 +1415,15 @@ static int simple_playback_init(struct hda_codec *codec) int i; for (i = 0; i < spec->num_pins; i++) { - snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + hda_nid_t pin = spec->pins[i].pin_nid; + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); /* some codecs require to unmute the pin */ - if (get_wcaps(codec, spec->pins[i].pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_jack_detect_enable(codec, pin, pin); } snd_hda_jack_report_sync(codec); return 0; -- GitLab From e6765ffa6897f7fb84469bab2e1be885c57ea519 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 14 Jun 2012 09:53:33 +0200 Subject: [PATCH 0929/5711] fbdev: sh_mipi_dsi: fix a section mismatch sh_mipi_setup() is called from a .text function, therefore it cannot be __init. Additionally, sh_mipi_remove() can be moved to the .devexit.text section. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Laurent Pinchart --- drivers/video/sh_mipi_dsi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 4c6b84488561..3951fdae5f68 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -127,8 +127,7 @@ static void sh_mipi_shutdown(struct platform_device *pdev) sh_mipi_dsi_enable(mipi, false); } -static int __init sh_mipi_setup(struct sh_mipi *mipi, - struct sh_mipi_dsi_info *pdata) +static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) { void __iomem *base = mipi->base; struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; @@ -551,7 +550,7 @@ efindslot: return ret; } -static int __exit sh_mipi_remove(struct platform_device *pdev) +static int __devexit sh_mipi_remove(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -592,7 +591,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) } static struct platform_driver sh_mipi_driver = { - .remove = __exit_p(sh_mipi_remove), + .remove = __devexit_p(sh_mipi_remove), .shutdown = sh_mipi_shutdown, .driver = { .name = "sh-mipi-dsi", -- GitLab From 3281e54c80195b90ed12a5b6cddef4ab42e656e1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Nov 2011 00:56:58 +0100 Subject: [PATCH 0930/5711] fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure The structure is only read, make it const. Signed-off-by: Laurent Pinchart --- drivers/video/sh_mobile_lcdcfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e672698bd820..5461abeb5c5a 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -1003,7 +1003,7 @@ static int sh_mobile_lcdc_setcolreg(u_int regno, return 0; } -static struct fb_fix_screeninfo sh_mobile_lcdc_fix = { +static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { .id = "SH Mobile LCDC", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, -- GitLab From d7ad33421863308fe7ddf865737d4d83b64e5b81 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Nov 2011 00:56:58 +0100 Subject: [PATCH 0931/5711] fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common prefix Make all fb operation handlers start with sh_mobile_lcdc_ in preparation for the multi-plane support. Signed-off-by: Laurent Pinchart --- drivers/video/sh_mobile_lcdcfb.c | 48 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 5461abeb5c5a..799f87171e04 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -384,8 +384,8 @@ sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, return true; } -static int sh_mobile_check_var(struct fb_var_screeninfo *var, - struct fb_info *info); +static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, enum sh_mobile_lcdc_entity_event event, @@ -439,7 +439,7 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, fb_videomode_to_var(&var, mode); var.bits_per_pixel = info->var.bits_per_pixel; var.grayscale = info->var.grayscale; - ret = sh_mobile_check_var(&var, info); + ret = sh_mobile_lcdc_check_var(&var, info); break; } @@ -585,7 +585,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) return IRQ_HANDLED; } -static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) +static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) { unsigned long ldintr; int ret; @@ -686,7 +686,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) } /* - * __sh_mobile_lcdc_start - Configure and tart the LCDC + * __sh_mobile_lcdc_start - Configure and start the LCDC * @priv: LCDC device * * Configure all enabled channels and start the LCDC device. All external @@ -1035,8 +1035,8 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info, sh_mobile_lcdc_deferred_io_touch(info); } -static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) +static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + struct fb_info *info) { struct sh_mobile_lcdc_chan *ch = info->par; struct sh_mobile_lcdc_priv *priv = ch->lcdc; @@ -1099,14 +1099,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, return 0; } -static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { + struct sh_mobile_lcdc_chan *ch = info->par; int retval; switch (cmd) { case FBIO_WAITFORVSYNC: - retval = sh_mobile_wait_for_vsync(info->par); + retval = sh_mobile_lcdc_wait_for_vsync(ch); break; default: @@ -1158,7 +1159,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) * Locking: both .fb_release() and .fb_open() are called with info->lock held if * user == 1, or with console sem held, if user == 0. */ -static int sh_mobile_release(struct fb_info *info, int user) +static int sh_mobile_lcdc_release(struct fb_info *info, int user) { struct sh_mobile_lcdc_chan *ch = info->par; @@ -1179,7 +1180,7 @@ static int sh_mobile_release(struct fb_info *info, int user) return 0; } -static int sh_mobile_open(struct fb_info *info, int user) +static int sh_mobile_lcdc_open(struct fb_info *info, int user) { struct sh_mobile_lcdc_chan *ch = info->par; @@ -1192,7 +1193,8 @@ static int sh_mobile_open(struct fb_info *info, int user) return 0; } -static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) { struct sh_mobile_lcdc_chan *ch = info->par; struct sh_mobile_lcdc_priv *p = ch->lcdc; @@ -1313,7 +1315,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in return 0; } -static int sh_mobile_set_par(struct fb_info *info) +static int sh_mobile_lcdc_set_par(struct fb_info *info) { struct sh_mobile_lcdc_chan *ch = info->par; int ret; @@ -1383,8 +1385,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info) * mode will reenable the clocks and update the screen in time, * so it does not need this. */ if (!info->fbdefio) { - sh_mobile_wait_for_vsync(ch); - sh_mobile_wait_for_vsync(ch); + sh_mobile_lcdc_wait_for_vsync(ch); + sh_mobile_lcdc_wait_for_vsync(ch); } sh_mobile_lcdc_clk_off(p); } @@ -1402,12 +1404,12 @@ static struct fb_ops sh_mobile_lcdc_ops = { .fb_copyarea = sh_mobile_lcdc_copyarea, .fb_imageblit = sh_mobile_lcdc_imageblit, .fb_blank = sh_mobile_lcdc_blank, - .fb_pan_display = sh_mobile_fb_pan_display, - .fb_ioctl = sh_mobile_ioctl, - .fb_open = sh_mobile_open, - .fb_release = sh_mobile_release, - .fb_check_var = sh_mobile_check_var, - .fb_set_par = sh_mobile_set_par, + .fb_pan_display = sh_mobile_lcdc_pan, + .fb_ioctl = sh_mobile_lcdc_ioctl, + .fb_open = sh_mobile_lcdc_open, + .fb_release = sh_mobile_lcdc_release, + .fb_check_var = sh_mobile_lcdc_check_var, + .fb_set_par = sh_mobile_lcdc_set_par, }; static void @@ -1537,7 +1539,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, else var->grayscale = ch->format->fourcc; - ret = sh_mobile_check_var(var, info); + ret = sh_mobile_lcdc_check_var(var, info); if (ret) return ret; -- GitLab From c5deac3c9b2284a64326e8799dfe7416bc619c02 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 12 Dec 2011 18:43:16 +0100 Subject: [PATCH 0932/5711] fbdev: sh_mobile_lcdc: Implement overlays support Signed-off-by: Laurent Pinchart --- .../sysfs-devices-platform-sh_mobile_lcdc_fb | 44 + drivers/video/sh_mobile_lcdcfb.c | 932 ++++++++++++++++-- include/video/sh_mobile_lcdc.h | 7 + 3 files changed, 911 insertions(+), 72 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb diff --git a/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb new file mode 100644 index 000000000000..2107082426da --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb @@ -0,0 +1,44 @@ +What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_alpha +Date: May 2012 +Contact: Laurent Pinchart +Description: + This file is only available on fb[0-9] devices corresponding + to overlay planes. + + Stores the alpha blending value for the overlay. Values range + from 0 (transparent) to 255 (opaque). The value is ignored if + the mode is not set to Alpha Blending. + +What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_mode +Date: May 2012 +Contact: Laurent Pinchart +Description: + This file is only available on fb[0-9] devices corresponding + to overlay planes. + + Selects the composition mode for the overlay. Possible values + are + + 0 - Alpha Blending + 1 - ROP3 + +What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position +Date: May 2012 +Contact: Laurent Pinchart +Description: + This file is only available on fb[0-9] devices corresponding + to overlay planes. + + Stores the x,y overlay position on the display in pixels. The + position format is `[0-9]+,[0-9]+'. + +What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3 +Date: May 2012 +Contact: Laurent Pinchart +Description: + This file is only available on fb[0-9] devices corresponding + to overlay planes. + + Stores the raster operation (ROP3) for the overlay. Values + range from 0 to 255. The value is ignored if the mode is not + set to ROP3. diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 799f87171e04..98e81b31fbc4 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -32,12 +33,176 @@ #include "sh_mobile_lcdcfb.h" +/* ---------------------------------------------------------------------------- + * Overlay register definitions + */ + +#define LDBCR 0xb00 +#define LDBCR_UPC(n) (1 << ((n) + 16)) +#define LDBCR_UPF(n) (1 << ((n) + 8)) +#define LDBCR_UPD(n) (1 << ((n) + 0)) +#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00) +#define LDBBSIFR_EN (1 << 31) +#define LDBBSIFR_VS (1 << 29) +#define LDBBSIFR_BRSEL (1 << 28) +#define LDBBSIFR_MX (1 << 27) +#define LDBBSIFR_MY (1 << 26) +#define LDBBSIFR_CV3 (3 << 24) +#define LDBBSIFR_CV2 (2 << 24) +#define LDBBSIFR_CV1 (1 << 24) +#define LDBBSIFR_CV0 (0 << 24) +#define LDBBSIFR_CV_MASK (3 << 24) +#define LDBBSIFR_LAY_MASK (0xff << 16) +#define LDBBSIFR_LAY_SHIFT 16 +#define LDBBSIFR_ROP3_MASK (0xff << 16) +#define LDBBSIFR_ROP3_SHIFT 16 +#define LDBBSIFR_AL_PL8 (3 << 14) +#define LDBBSIFR_AL_PL1 (2 << 14) +#define LDBBSIFR_AL_PK (1 << 14) +#define LDBBSIFR_AL_1 (0 << 14) +#define LDBBSIFR_AL_MASK (3 << 14) +#define LDBBSIFR_SWPL (1 << 10) +#define LDBBSIFR_SWPW (1 << 9) +#define LDBBSIFR_SWPB (1 << 8) +#define LDBBSIFR_RY (1 << 7) +#define LDBBSIFR_CHRR_420 (2 << 0) +#define LDBBSIFR_CHRR_422 (1 << 0) +#define LDBBSIFR_CHRR_444 (0 << 0) +#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0) +#define LDBBSIFR_RPKF_RGB16 (0x03 << 0) +#define LDBBSIFR_RPKF_RGB24 (0x0b << 0) +#define LDBBSIFR_RPKF_MASK (0x1f << 0) +#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04) +#define LDBBSSZR_BVSS_MASK (0xfff << 16) +#define LDBBSSZR_BVSS_SHIFT 16 +#define LDBBSSZR_BHSS_MASK (0xfff << 0) +#define LDBBSSZR_BHSS_SHIFT 0 +#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08) +#define LDBBLOCR_CVLC_MASK (0xfff << 16) +#define LDBBLOCR_CVLC_SHIFT 16 +#define LDBBLOCR_CHLC_MASK (0xfff << 0) +#define LDBBLOCR_CHLC_SHIFT 0 +#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c) +#define LDBBSMWR_BSMWA_MASK (0xffff << 16) +#define LDBBSMWR_BSMWA_SHIFT 16 +#define LDBBSMWR_BSMW_MASK (0xffff << 0) +#define LDBBSMWR_BSMW_SHIFT 0 +#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10) +#define LDBBSAYR_FG1A_MASK (0xff << 24) +#define LDBBSAYR_FG1A_SHIFT 24 +#define LDBBSAYR_FG1R_MASK (0xff << 16) +#define LDBBSAYR_FG1R_SHIFT 16 +#define LDBBSAYR_FG1G_MASK (0xff << 8) +#define LDBBSAYR_FG1G_SHIFT 8 +#define LDBBSAYR_FG1B_MASK (0xff << 0) +#define LDBBSAYR_FG1B_SHIFT 0 +#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14) +#define LDBBSACR_FG2A_MASK (0xff << 24) +#define LDBBSACR_FG2A_SHIFT 24 +#define LDBBSACR_FG2R_MASK (0xff << 16) +#define LDBBSACR_FG2R_SHIFT 16 +#define LDBBSACR_FG2G_MASK (0xff << 8) +#define LDBBSACR_FG2G_SHIFT 8 +#define LDBBSACR_FG2B_MASK (0xff << 0) +#define LDBBSACR_FG2B_SHIFT 0 +#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18) +#define LDBBSAAR_AP_MASK (0xff << 24) +#define LDBBSAAR_AP_SHIFT 24 +#define LDBBSAAR_R_MASK (0xff << 16) +#define LDBBSAAR_R_SHIFT 16 +#define LDBBSAAR_GY_MASK (0xff << 8) +#define LDBBSAAR_GY_SHIFT 8 +#define LDBBSAAR_B_MASK (0xff << 0) +#define LDBBSAAR_B_SHIFT 0 +#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c) +#define LDBBPPCR_AP_MASK (0xff << 24) +#define LDBBPPCR_AP_SHIFT 24 +#define LDBBPPCR_R_MASK (0xff << 16) +#define LDBBPPCR_R_SHIFT 16 +#define LDBBPPCR_GY_MASK (0xff << 8) +#define LDBBPPCR_GY_SHIFT 8 +#define LDBBPPCR_B_MASK (0xff << 0) +#define LDBBPPCR_B_SHIFT 0 +#define LDBnBBGCL(n) (0xb10 + (n) * 0x04) +#define LDBBBGCL_BGA_MASK (0xff << 24) +#define LDBBBGCL_BGA_SHIFT 24 +#define LDBBBGCL_BGR_MASK (0xff << 16) +#define LDBBBGCL_BGR_SHIFT 16 +#define LDBBBGCL_BGG_MASK (0xff << 8) +#define LDBBBGCL_BGG_SHIFT 8 +#define LDBBBGCL_BGB_MASK (0xff << 0) +#define LDBBBGCL_BGB_SHIFT 0 + #define SIDE_B_OFFSET 0x1000 #define MIRROR_OFFSET 0x2000 #define MAX_XRES 1920 #define MAX_YRES 1080 +enum sh_mobile_lcdc_overlay_mode { + LCDC_OVERLAY_BLEND, + LCDC_OVERLAY_ROP3, +}; + +/* + * struct sh_mobile_lcdc_overlay - LCDC display overlay + * + * @channel: LCDC channel this overlay belongs to + * @cfg: Overlay configuration + * @info: Frame buffer device + * @index: Overlay index (0-3) + * @base: Overlay registers base address + * @enabled: True if the overlay is enabled + * @mode: Overlay blending mode (alpha blend or ROP3) + * @alpha: Global alpha blending value (0-255, for alpha blending mode) + * @rop3: Raster operation (for ROP3 mode) + * @fb_mem: Frame buffer virtual memory address + * @fb_size: Frame buffer size in bytes + * @dma_handle: Frame buffer DMA address + * @base_addr_y: Overlay base address (RGB or luma component) + * @base_addr_c: Overlay base address (chroma component) + * @pan_offset: Current pan offset in bytes + * @format: Current pixelf format + * @xres: Horizontal visible resolution + * @xres_virtual: Horizontal total resolution + * @yres: Vertical visible resolution + * @yres_virtual: Vertical total resolution + * @pitch: Overlay line pitch + * @pos_x: Horizontal overlay position + * @pos_y: Vertical overlay position + */ +struct sh_mobile_lcdc_overlay { + struct sh_mobile_lcdc_chan *channel; + + const struct sh_mobile_lcdc_overlay_cfg *cfg; + struct fb_info *info; + + unsigned int index; + unsigned long base; + + bool enabled; + enum sh_mobile_lcdc_overlay_mode mode; + unsigned int alpha; + unsigned int rop3; + + void *fb_mem; + unsigned long fb_size; + + dma_addr_t dma_handle; + unsigned long base_addr_y; + unsigned long base_addr_c; + unsigned long pan_offset; + + const struct sh_mobile_lcdc_format_info *format; + unsigned int xres; + unsigned int xres_virtual; + unsigned int yres; + unsigned int yres_virtual; + unsigned int pitch; + int pos_x; + int pos_y; +}; + struct sh_mobile_lcdc_priv { void __iomem *base; int irq; @@ -45,7 +210,10 @@ struct sh_mobile_lcdc_priv { struct device *dev; struct clk *dot_clk; unsigned long lddckr; + struct sh_mobile_lcdc_chan ch[2]; + struct sh_mobile_lcdc_overlay overlays[4]; + struct notifier_block notifier; int started; int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ @@ -141,6 +309,13 @@ static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); } +static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl, + int reg, unsigned long data) +{ + iowrite32(data, ovl->channel->lcdc->base + reg); + iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET); +} + static void lcdc_write(struct sh_mobile_lcdc_priv *priv, unsigned long reg_offs, unsigned long data) { @@ -685,6 +860,96 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) lcdc_write_chan(ch, LDHAJR, tmp); } +static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) +{ + u32 format = 0; + + if (!ovl->enabled) { + lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); + lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); + lcdc_write(ovl->channel->lcdc, LDBCR, + LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); + return; + } + + ovl->base_addr_y = ovl->dma_handle; + ovl->base_addr_c = ovl->base_addr_y + ovl->xres + * ovl->yres_virtual; + + switch (ovl->mode) { + case LCDC_OVERLAY_BLEND: + format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); + break; + + case LCDC_OVERLAY_ROP3: + format = LDBBSIFR_EN | LDBBSIFR_BRSEL + | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); + break; + } + + switch (ovl->format->fourcc) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV42: + format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW; + break; + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV24: + format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB; + break; + case V4L2_PIX_FMT_BGR32: + default: + format |= LDBBSIFR_SWPL; + break; + } + + switch (ovl->format->fourcc) { + case V4L2_PIX_FMT_RGB565: + format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16; + break; + case V4L2_PIX_FMT_BGR24: + format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; + break; + case V4L2_PIX_FMT_BGR32: + format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420; + break; + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422; + break; + case V4L2_PIX_FMT_NV24: + case V4L2_PIX_FMT_NV42: + format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444; + break; + } + + lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); + + lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); + + lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), + (ovl->yres << LDBBSSZR_BVSS_SHIFT) | + (ovl->xres << LDBBSSZR_BHSS_SHIFT)); + lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), + (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | + (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); + lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), + ovl->pitch << LDBBSMWR_BSMW_SHIFT); + + lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); + lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); + + lcdc_write(ovl->channel->lcdc, LDBCR, + LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); +} + /* * __sh_mobile_lcdc_start - Configure and start the LCDC * @priv: LCDC device @@ -892,6 +1157,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } } + for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { + struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; + sh_mobile_lcdc_overlay_setup(ovl); + } + /* Start the LCDC. */ __sh_mobile_lcdc_start(priv); @@ -975,8 +1245,506 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) sh_mobile_lcdc_clk_off(priv); } +static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + if (var->xres > MAX_XRES || var->yres > MAX_YRES) + return -EINVAL; + + /* Make sure the virtual resolution is at least as big as the visible + * resolution. + */ + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + if (sh_mobile_format_is_fourcc(var)) { + const struct sh_mobile_lcdc_format_info *format; + + format = sh_mobile_format_info(var->grayscale); + if (format == NULL) + return -EINVAL; + var->bits_per_pixel = format->bpp; + + /* Default to RGB and JPEG color-spaces for RGB and YUV formats + * respectively. + */ + if (!format->yuv) + var->colorspace = V4L2_COLORSPACE_SRGB; + else if (var->colorspace != V4L2_COLORSPACE_REC709) + var->colorspace = V4L2_COLORSPACE_JPEG; + } else { + if (var->bits_per_pixel <= 16) { /* RGB 565 */ + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ + var->bits_per_pixel = 24; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ + var->bits_per_pixel = 32; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + } else + return -EINVAL; + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + } + + /* Make sure we don't exceed our allocated memory. */ + if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > + info->fix.smem_len) + return -EINVAL; + + return 0; +} + +/* ----------------------------------------------------------------------------- + * Frame buffer operations - Overlays + */ + +static ssize_t +overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + + return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha); +} + +static ssize_t +overlay_alpha_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + unsigned int alpha; + char *endp; + + alpha = simple_strtoul(buf, &endp, 10); + if (isspace(*endp)) + endp++; + + if (endp - buf != count) + return -EINVAL; + + if (alpha > 255) + return -EINVAL; + + if (ovl->alpha != alpha) { + ovl->alpha = alpha; + + if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) + sh_mobile_lcdc_overlay_setup(ovl); + } + + return count; +} + +static ssize_t +overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + + return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode); +} + +static ssize_t +overlay_mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + unsigned int mode; + char *endp; + + mode = simple_strtoul(buf, &endp, 10); + if (isspace(*endp)) + endp++; + + if (endp - buf != count) + return -EINVAL; + + if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3) + return -EINVAL; + + if (ovl->mode != mode) { + ovl->mode = mode; + + if (ovl->enabled) + sh_mobile_lcdc_overlay_setup(ovl); + } + + return count; +} + +static ssize_t +overlay_position_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + + return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y); +} + +static ssize_t +overlay_position_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + char *endp; + int pos_x; + int pos_y; + + pos_x = simple_strtol(buf, &endp, 10); + if (*endp != ',') + return -EINVAL; + + pos_y = simple_strtol(endp + 1, &endp, 10); + if (isspace(*endp)) + endp++; + + if (endp - buf != count) + return -EINVAL; + + if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { + ovl->pos_x = pos_x; + ovl->pos_y = pos_y; + + if (ovl->enabled) + sh_mobile_lcdc_overlay_setup(ovl); + } + + return count; +} + +static ssize_t +overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + + return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3); +} + +static ssize_t +overlay_rop3_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct sh_mobile_lcdc_overlay *ovl = info->par; + unsigned int rop3; + char *endp; + + rop3 = !!simple_strtoul(buf, &endp, 10); + if (isspace(*endp)) + endp++; + + if (endp - buf != count) + return -EINVAL; + + if (rop3 > 255) + return -EINVAL; + + if (ovl->rop3 != rop3) { + ovl->rop3 = rop3; + + if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) + sh_mobile_lcdc_overlay_setup(ovl); + } + + return count; +} + +static const struct device_attribute overlay_sysfs_attrs[] = { + __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, + overlay_alpha_show, overlay_alpha_store), + __ATTR(ovl_mode, S_IRUGO|S_IWUSR, + overlay_mode_show, overlay_mode_store), + __ATTR(ovl_position, S_IRUGO|S_IWUSR, + overlay_position_show, overlay_position_store), + __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, + overlay_rop3_show, overlay_rop3_store), +}; + +static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { + .id = "SH Mobile LCDC", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .accel = FB_ACCEL_NONE, + .xpanstep = 0, + .ypanstep = 1, + .ywrapstep = 0, + .capabilities = FB_CAP_FOURCC, +}; + +static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct sh_mobile_lcdc_overlay *ovl = info->par; + unsigned long base_addr_y; + unsigned long base_addr_c; + unsigned long pan_offset; + unsigned long c_offset; + + if (!ovl->format->yuv) + pan_offset = var->yoffset * ovl->pitch + + var->xoffset * (ovl->format->bpp / 8); + else + pan_offset = var->yoffset * ovl->pitch + var->xoffset; + + if (pan_offset == ovl->pan_offset) + return 0; /* No change, do nothing */ + + /* Set the source address for the next refresh */ + base_addr_y = ovl->dma_handle + pan_offset; + + ovl->base_addr_y = base_addr_y; + ovl->base_addr_c = base_addr_y; + + if (ovl->format->yuv) { + /* Set Y offset */ + c_offset = var->yoffset * ovl->pitch + * (ovl->format->bpp - 8) / 8; + base_addr_c = ovl->dma_handle + + ovl->xres * ovl->yres_virtual + + c_offset; + /* Set X offset */ + if (ovl->format->fourcc == V4L2_PIX_FMT_NV24) + base_addr_c += 2 * var->xoffset; + else + base_addr_c += var->xoffset; + + ovl->base_addr_c = base_addr_c; + } + + lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); + lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); + + ovl->pan_offset = pan_offset; + + return 0; +} + +static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct sh_mobile_lcdc_overlay *ovl = info->par; + + switch (cmd) { + case FBIO_WAITFORVSYNC: + return sh_mobile_lcdc_wait_for_vsync(ovl->channel); + + default: + return -ENOIOCTLCMD; + } +} + +static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + return __sh_mobile_lcdc_check_var(var, info); +} + +static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) +{ + struct sh_mobile_lcdc_overlay *ovl = info->par; + + ovl->format = + sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); + + ovl->xres = info->var.xres; + ovl->xres_virtual = info->var.xres_virtual; + ovl->yres = info->var.yres; + ovl->yres_virtual = info->var.yres_virtual; + + if (ovl->format->yuv) + ovl->pitch = info->var.xres; + else + ovl->pitch = info->var.xres * ovl->format->bpp / 8; + + sh_mobile_lcdc_overlay_setup(ovl); + + info->fix.line_length = ovl->pitch; + + if (sh_mobile_format_is_fourcc(&info->var)) { + info->fix.type = FB_TYPE_FOURCC; + info->fix.visual = FB_VISUAL_FOURCC; + } else { + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + } + + return 0; +} + +/* Overlay blanking. Disable the overlay when blanked. */ +static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) +{ + struct sh_mobile_lcdc_overlay *ovl = info->par; + + ovl->enabled = !blank; + sh_mobile_lcdc_overlay_setup(ovl); + + /* Prevent the backlight from receiving a blanking event by returning + * a non-zero value. + */ + return 1; +} + +static struct fb_ops sh_mobile_lcdc_overlay_ops = { + .owner = THIS_MODULE, + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_blank = sh_mobile_lcdc_overlay_blank, + .fb_pan_display = sh_mobile_lcdc_overlay_pan, + .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, + .fb_check_var = sh_mobile_lcdc_overlay_check_var, + .fb_set_par = sh_mobile_lcdc_overlay_set_par, +}; + +static void +sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl) +{ + struct fb_info *info = ovl->info; + + if (info == NULL || info->dev == NULL) + return; + + unregister_framebuffer(ovl->info); +} + +static int __devinit +sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) +{ + struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; + struct fb_info *info = ovl->info; + unsigned int i; + int ret; + + if (info == NULL) + return 0; + + ret = register_framebuffer(info); + if (ret < 0) + return ret; + + dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", + dev_name(lcdc->dev), ovl->index, info->var.xres, + info->var.yres, info->var.bits_per_pixel); + + for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { + ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +static void +sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl) +{ + struct fb_info *info = ovl->info; + + if (info == NULL || info->device == NULL) + return; + + framebuffer_release(info); +} + +static int __devinit +sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) +{ + struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; + struct fb_var_screeninfo *var; + struct fb_info *info; + + /* Allocate and initialize the frame buffer device. */ + info = framebuffer_alloc(0, priv->dev); + if (info == NULL) { + dev_err(priv->dev, "unable to allocate fb_info\n"); + return -ENOMEM; + } + + ovl->info = info; + + info->flags = FBINFO_FLAG_DEFAULT; + info->fbops = &sh_mobile_lcdc_overlay_ops; + info->device = priv->dev; + info->screen_base = ovl->fb_mem; + info->par = ovl; + + /* Initialize fixed screen information. Restrict pan to 2 lines steps + * for NV12 and NV21. + */ + info->fix = sh_mobile_lcdc_overlay_fix; + snprintf(info->fix.id, sizeof(info->fix.id), + "SH Mobile LCDC Overlay %u", ovl->index); + info->fix.smem_start = ovl->dma_handle; + info->fix.smem_len = ovl->fb_size; + info->fix.line_length = ovl->pitch; + + if (ovl->format->yuv) + info->fix.visual = FB_VISUAL_FOURCC; + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + + if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 || + ovl->format->fourcc == V4L2_PIX_FMT_NV21) + info->fix.ypanstep = 2; + + /* Initialize variable screen information. */ + var = &info->var; + memset(var, 0, sizeof(*var)); + var->xres = ovl->xres; + var->yres = ovl->yres; + var->xres_virtual = ovl->xres_virtual; + var->yres_virtual = ovl->yres_virtual; + var->activate = FB_ACTIVATE_NOW; + + /* Use the legacy API by default for RGB formats, and the FOURCC API + * for YUV formats. + */ + if (!ovl->format->yuv) + var->bits_per_pixel = ovl->format->bpp; + else + var->grayscale = ovl->format->fourcc; + + return sh_mobile_lcdc_overlay_check_var(var, info); +} + /* ----------------------------------------------------------------------------- - * Frame buffer operations + * Frame buffer operations - main frame buffer */ static int sh_mobile_lcdc_setcolreg(u_int regno, @@ -1202,9 +1970,7 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, unsigned int best_xres = 0; unsigned int best_yres = 0; unsigned int i; - - if (var->xres > MAX_XRES || var->yres > MAX_YRES) - return -EINVAL; + int ret; /* If board code provides us with a list of available modes, make sure * we use one of them. Find the mode closest to the requested one. The @@ -1239,73 +2005,9 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, var->yres = best_yres; } - /* Make sure the virtual resolution is at least as big as the visible - * resolution. - */ - if (var->xres_virtual < var->xres) - var->xres_virtual = var->xres; - if (var->yres_virtual < var->yres) - var->yres_virtual = var->yres; - - if (sh_mobile_format_is_fourcc(var)) { - const struct sh_mobile_lcdc_format_info *format; - - format = sh_mobile_format_info(var->grayscale); - if (format == NULL) - return -EINVAL; - var->bits_per_pixel = format->bpp; - - /* Default to RGB and JPEG color-spaces for RGB and YUV formats - * respectively. - */ - if (!format->yuv) - var->colorspace = V4L2_COLORSPACE_SRGB; - else if (var->colorspace != V4L2_COLORSPACE_REC709) - var->colorspace = V4L2_COLORSPACE_JPEG; - } else { - if (var->bits_per_pixel <= 16) { /* RGB 565 */ - var->bits_per_pixel = 16; - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ - var->bits_per_pixel = 24; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ - var->bits_per_pixel = 32; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - } else - return -EINVAL; - - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; - } - - /* Make sure we don't exceed our allocated memory. */ - if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > - info->fix.smem_len) - return -EINVAL; + ret = __sh_mobile_lcdc_check_var(var, info); + if (ret < 0) + return ret; /* only accept the forced_fourcc for dual channel configurations */ if (p->forced_fourcc && @@ -1714,15 +2416,27 @@ static const struct fb_videomode default_720p __devinitconst = { static int sh_mobile_lcdc_remove(struct platform_device *pdev) { struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); - int i; + unsigned int i; fb_unregister_client(&priv->notifier); + for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) + sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); for (i = 0; i < ARRAY_SIZE(priv->ch); i++) sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); sh_mobile_lcdc_stop(priv); + for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { + struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; + + sh_mobile_lcdc_overlay_fb_cleanup(ovl); + + if (ovl->fb_mem) + dma_free_coherent(&pdev->dev, ovl->fb_size, + ovl->fb_mem, ovl->dma_handle); + } + for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; @@ -1797,6 +2511,61 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan * return 0; } +static int __devinit +sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, + struct sh_mobile_lcdc_overlay *ovl) +{ + const struct sh_mobile_lcdc_format_info *format; + int ret; + + if (ovl->cfg->fourcc == 0) + return 0; + + /* Validate the format. */ + format = sh_mobile_format_info(ovl->cfg->fourcc); + if (format == NULL) { + dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); + return -EINVAL; + } + + ovl->enabled = false; + ovl->mode = LCDC_OVERLAY_BLEND; + ovl->alpha = 255; + ovl->rop3 = 0; + ovl->pos_x = 0; + ovl->pos_y = 0; + + /* The default Y virtual resolution is twice the panel size to allow for + * double-buffering. + */ + ovl->format = format; + ovl->xres = ovl->cfg->max_xres; + ovl->xres_virtual = ovl->xres; + ovl->yres = ovl->cfg->max_yres; + ovl->yres_virtual = ovl->yres * 2; + + if (!format->yuv) + ovl->pitch = ovl->xres * format->bpp / 8; + else + ovl->pitch = ovl->xres; + + /* Allocate frame buffer memory. */ + ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres + * format->bpp / 8 * 2; + ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size, + &ovl->dma_handle, GFP_KERNEL); + if (!ovl->fb_mem) { + dev_err(priv->dev, "unable to allocate buffer\n"); + return -ENOMEM; + } + + ret = sh_mobile_lcdc_overlay_fb_init(ovl); + if (ret < 0) + return ret; + + return 0; +} + static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, struct sh_mobile_lcdc_chan *ch) @@ -2005,6 +2774,17 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) goto err1; } + for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { + struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; + + ovl->cfg = &pdata->overlays[i]; + ovl->channel = &priv->ch[0]; + + error = sh_mobile_lcdc_overlay_init(priv, ovl); + if (error) + goto err1; + } + error = sh_mobile_lcdc_start(priv); if (error) { dev_err(&pdev->dev, "unable to start hardware\n"); @@ -2019,6 +2799,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) goto err1; } + for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { + struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; + + error = sh_mobile_lcdc_overlay_fb_register(ovl); + if (error) + goto err1; + } + /* Failure ignored */ priv->notifier.notifier_call = sh_mobile_lcdc_notify; fb_register_client(&priv->notifier); diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h index 7571b27a0ba1..ff43ffc1aab2 100644 --- a/include/video/sh_mobile_lcdc.h +++ b/include/video/sh_mobile_lcdc.h @@ -166,6 +166,12 @@ struct sh_mobile_lcdc_bl_info { int (*get_brightness)(void); }; +struct sh_mobile_lcdc_overlay_cfg { + int fourcc; + unsigned int max_xres; + unsigned int max_yres; +}; + struct sh_mobile_lcdc_chan_cfg { int chan; int fourcc; @@ -186,6 +192,7 @@ struct sh_mobile_lcdc_chan_cfg { struct sh_mobile_lcdc_info { int clock_source; struct sh_mobile_lcdc_chan_cfg ch[2]; + struct sh_mobile_lcdc_overlay_cfg overlays[4]; struct sh_mobile_meram_info *meram_dev; }; -- GitLab From 55a6662837a5efe48c836bfc3570ace348f3db09 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 21:55:32 +0200 Subject: [PATCH 0933/5711] drm/i915: fix module unload after context merge commit 8e96d9c4d9843f00ebeb4a9b33596d96602ea101 Author: Ben Widawsky Date: Mon Jun 4 14:42:56 2012 -0700 drm/i915: reset the GPU on context fini broke module unload because it reset the gpu before we've stopped touching it. Later on in the unload sequence the ringbuffer code complained that the gpu would idle properly (because intel_gpu_reset only resets the hw and not our sw state). v2: Reorder things so that we reset the gpu _before_ we release the backing storage of the default context. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51183 Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ba75af12f1fd..9913a77478a3 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1669,7 +1669,6 @@ int i915_driver_unload(struct drm_device *dev) if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); i915_gem_retire_requests(dev); - i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); /* Cancel the retire work handler, which should be idle now. */ @@ -1720,6 +1719,7 @@ int i915_driver_unload(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ringbuffer(dev); + i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_aliasing_ppgtt(dev); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8fb8cd8f6320..48e41df075b9 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -277,11 +277,14 @@ void i915_gem_context_fini(struct drm_device *dev) if (dev_priv->hw_contexts_disabled) return; + /* The only known way to stop the gpu from accessing the hw context is + * to reset it. Do this as the very last operation to avoid confusing + * other code, leading to spurious errors. */ + intel_gpu_reset(dev); + i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); do_destroy(dev_priv->ring[RCS].default_context); - - intel_gpu_reset(dev); } void i915_gem_context_open(struct drm_device *dev, struct drm_file *file) -- GitLab From df12c6d5ec9b88fc45c672b77dac015327dd8497 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 16:52:30 +0200 Subject: [PATCH 0934/5711] drm/i915: initialize the context idr unconditionally It doesn't hurt and it at least prevents us from OOPSing left and right at quite a few places. This also allows us to simplify the code a bit by folding the only line of context_open into the callsite. We obviuosly also need to run the cleanup code unconditionally, too. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem_context.c | 15 --------------- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9913a77478a3..9563ab8390e7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1759,7 +1759,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); - i915_gem_context_open(dev, file); + idr_init(&file_priv->context_idr); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6f29fd141ab0..82e657eafd55 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1383,7 +1383,6 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, /* i915_gem_context.c */ void i915_gem_context_init(struct drm_device *dev); void i915_gem_context_fini(struct drm_device *dev); -void 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 intel_ring_buffer *ring, struct drm_file *file, int to_id); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 48e41df075b9..047f81c206b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -287,17 +287,6 @@ void i915_gem_context_fini(struct drm_device *dev) do_destroy(dev_priv->ring[RCS].default_context); } -void i915_gem_context_open(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_file_private *file_priv = file->driver_priv; - - if (dev_priv->hw_contexts_disabled) - return; - - idr_init(&file_priv->context_idr); -} - static int context_idr_cleanup(int id, void *p, void *data) { struct drm_file *file = (struct drm_file *)data; @@ -316,12 +305,8 @@ static int context_idr_cleanup(int id, void *p, void *data) void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; - if (dev_priv->hw_contexts_disabled) - return; - mutex_lock(&dev->struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, file); idr_destroy(&file_priv->context_idr); -- GitLab From 0d326013763bd4610cb72d9e2fa7f8ff2f414995 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 16:52:31 +0200 Subject: [PATCH 0935/5711] drm/i915: return -ENOENT if the context doesn't exist This is our customary "no such object" errno, not -EINVAL. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 047f81c206b3..f775d861f052 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -460,7 +460,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, } else { to = i915_gem_context_get(file_priv, to_id); if (to == NULL) - return -EINVAL; + return -ENOENT; } if (from_obj == to->obj) @@ -526,7 +526,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, ctx = i915_gem_context_get(file_priv, args->ctx_id); if (!ctx) { mutex_unlock(&dev->struct_mutex); - return -EINVAL; + return -ENOENT; } do_destroy(ctx); -- GitLab From 6f4c45c12c6775b8158fc143115037d084df12c3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 16:52:32 +0200 Subject: [PATCH 0936/5711] drm/i915/context: shut up compiler It found some unused variables. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f775d861f052..a52fd21e4807 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -485,7 +485,6 @@ int i915_switch_context(struct intel_ring_buffer *ring, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_context_create *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; @@ -512,7 +511,6 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_context_destroy *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; - struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *ctx; int ret; -- GitLab From 73c273eb7547d2557b49f9d1f42e298145c1e635 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 20:27:39 +0200 Subject: [PATCH 0937/5711] drm/i915: simplify context_idr_cleanup The idr code already passes us the pointer associated with that id, so no need to look it up again. Also, we'll kill the idr right away, so there's no issue with leaving these dangling pointers behind - the current code does the same. v2: Also drop the file argument, spotted by Ben Widawsky. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index a52fd21e4807..1b5041c52569 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -289,14 +289,9 @@ void i915_gem_context_fini(struct drm_device *dev) static int context_idr_cleanup(int id, void *p, void *data) { - struct drm_file *file = (struct drm_file *)data; - struct drm_i915_file_private *file_priv = file->driver_priv; - struct i915_hw_context *ctx; + struct i915_hw_context *ctx = p; BUG_ON(id == DEFAULT_CONTEXT_ID); - ctx = i915_gem_context_get(file_priv, id); - if (WARN_ON(ctx == NULL)) - return -ENXIO; do_destroy(ctx); @@ -308,7 +303,7 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; mutex_lock(&dev->struct_mutex); - idr_for_each(&file_priv->context_idr, context_idr_cleanup, file); + idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); mutex_unlock(&dev->struct_mutex); } -- GitLab From 5fa8be65e950e4f2a4e7dc31f823fca41b9e650e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 17:16:01 +0200 Subject: [PATCH 0938/5711] drm/i915: return -ENODEV if hw context are not supported Otherwise userspace has no way to figure this out. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 1b5041c52569..e58e8366f473 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -480,6 +480,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_context_create *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; @@ -488,6 +489,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; + if (dev_priv->hw_contexts_disabled) + return -ENODEV; + ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; -- GitLab From 8e88a2bd5987178d16d53686197404e149e996d9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jun 2012 18:40:00 +0200 Subject: [PATCH 0939/5711] drm/i915: don't call modeset_init_hw in i915_reset It seems to blow up my ilk in all kinds of strange ways. And now that we're no longer resetting the entire modeset state, it shouldn't be necessary any longer. This essentially reverts commit f817586cebf1b946d1f327f9a596048efd6b64e9 Author: Daniel Vetter Date: Tue Apr 10 15:50:11 2012 +0200 drm/i915: re-init modeset hw state after gpu reset safe for the introduction of modeset_init_hw, that one is nice to prevent code duplication between driver load and resume. v2: Add a comment to the code to warn future travellers of the dragon dungeon ahead, suggested by Chris Wilson. Acked-by: Chris Wilson Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e41aadef9937..d7dd60bb2745 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -904,10 +904,13 @@ int i915_reset(struct drm_device *dev) i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); - mutex_unlock(&dev->struct_mutex); + /* + * It would make sense to re-init all the other hw state, at + * least the rps/rc6/emon init done within modeset_init_hw. For + * some unknown reason, this blows up my ilk, so don't. + */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) - intel_modeset_init_hw(dev); + mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_irq_install(dev); -- GitLab From f3761c3950bd2ad813095a240d6a3dcb885d2431 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 19 Jun 2012 19:31:48 +0100 Subject: [PATCH 0940/5711] ALSA: Add missing include of pcm.h to pcm_params.h There's a dependency but no #include. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai --- include/sound/pcm_params.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index f494f1e3c900..37ae12e0ab06 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -22,6 +22,8 @@ * */ +#include + int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, int *dir); -- GitLab From d2aae47f804830da904d2454d73959eda4ebb0fd Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 20 Jun 2012 17:00:30 -0400 Subject: [PATCH 0941/5711] ASoC: add sport driver for bf6xx soc The SPORT(Serial Port) module on bf6xx soc has a totally different ip comparing to bf5xx soc. An individual SPORT module consists of two independently configurable SPORT halves with identical functionality. Each SPORT half can be configured for either transmitter or receiver. Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 10 +- sound/soc/blackfin/Makefile | 2 + sound/soc/blackfin/bf6xx-sport.c | 422 +++++++++++++++++++++++++++++++ sound/soc/blackfin/bf6xx-sport.h | 82 ++++++ 4 files changed, 513 insertions(+), 3 deletions(-) create mode 100644 sound/soc/blackfin/bf6xx-sport.c create mode 100644 sound/soc/blackfin/bf6xx-sport.h diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 9f6bc55fc399..0374a3965095 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -1,7 +1,8 @@ config SND_BF5XX_I2S - tristate "SoC I2S Audio for the ADI BF5xx chip" + tristate "SoC I2S Audio for the ADI Blackfin chip" depends on BLACKFIN - select SND_BF5XX_SOC_SPORT + select SND_BF5XX_SOC_SPORT if !BF60x + select SND_BF6XX_SOC_SPORT if BF60x help Say Y or M if you want to add support for codecs attached to the Blackfin SPORT (synchronous serial ports) interface in I2S @@ -162,6 +163,9 @@ config SND_BF5XX_SOC_AD1980 config SND_BF5XX_SOC_SPORT tristate +config SND_BF6XX_SOC_SPORT + tristate + config SND_BF5XX_SOC_I2S tristate @@ -173,7 +177,7 @@ config SND_BF5XX_SOC_AC97 config SND_BF5XX_SPORT_NUM int "Set a SPORT for Sound chip" - depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) + depends on (SND_BF5XX_SOC_SPORT || SND_BF6XX_SOC_SPORT) range 0 3 if BF54x range 0 1 if !BF54x default 0 diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 1bf86ccaa8de..13b092239a82 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile @@ -3,6 +3,7 @@ snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o snd-soc-bf5xx-sport-objs := bf5xx-sport.o +snd-soc-bf6xx-sport-objs := bf6xx-sport.o snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o @@ -11,6 +12,7 @@ obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o +obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o diff --git a/sound/soc/blackfin/bf6xx-sport.c b/sound/soc/blackfin/bf6xx-sport.c new file mode 100644 index 000000000000..f19a72b8e0c2 --- /dev/null +++ b/sound/soc/blackfin/bf6xx-sport.c @@ -0,0 +1,422 @@ +/* + * bf6xx_sport.c Analog Devices BF6XX SPORT driver + * + * Copyright (c) 2012 Analog Devices 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "bf6xx-sport.h" + +int sport_set_tx_params(struct sport_device *sport, + struct sport_params *params) +{ + if (sport->tx_regs->spctl & SPORT_CTL_SPENPRI) + return -EBUSY; + sport->tx_regs->spctl = params->spctl | SPORT_CTL_SPTRAN; + sport->tx_regs->div = params->div; + SSYNC(); + return 0; +} +EXPORT_SYMBOL(sport_set_tx_params); + +int sport_set_rx_params(struct sport_device *sport, + struct sport_params *params) +{ + if (sport->rx_regs->spctl & SPORT_CTL_SPENPRI) + return -EBUSY; + sport->rx_regs->spctl = params->spctl & ~SPORT_CTL_SPTRAN; + sport->rx_regs->div = params->div; + SSYNC(); + return 0; +} +EXPORT_SYMBOL(sport_set_rx_params); + +static int compute_wdsize(size_t wdsize) +{ + switch (wdsize) { + case 1: + return WDSIZE_8 | PSIZE_8; + case 2: + return WDSIZE_16 | PSIZE_16; + default: + return WDSIZE_32 | PSIZE_32; + } +} + +void sport_tx_start(struct sport_device *sport) +{ + set_dma_next_desc_addr(sport->tx_dma_chan, sport->tx_desc); + set_dma_config(sport->tx_dma_chan, DMAFLOW_LIST | DI_EN + | compute_wdsize(sport->wdsize) | NDSIZE_6); + enable_dma(sport->tx_dma_chan); + sport->tx_regs->spctl |= SPORT_CTL_SPENPRI; + SSYNC(); +} +EXPORT_SYMBOL(sport_tx_start); + +void sport_rx_start(struct sport_device *sport) +{ + set_dma_next_desc_addr(sport->rx_dma_chan, sport->rx_desc); + set_dma_config(sport->rx_dma_chan, DMAFLOW_LIST | DI_EN | WNR + | compute_wdsize(sport->wdsize) | NDSIZE_6); + enable_dma(sport->rx_dma_chan); + sport->rx_regs->spctl |= SPORT_CTL_SPENPRI; + SSYNC(); +} +EXPORT_SYMBOL(sport_rx_start); + +void sport_tx_stop(struct sport_device *sport) +{ + sport->tx_regs->spctl &= ~SPORT_CTL_SPENPRI; + SSYNC(); + disable_dma(sport->tx_dma_chan); +} +EXPORT_SYMBOL(sport_tx_stop); + +void sport_rx_stop(struct sport_device *sport) +{ + sport->rx_regs->spctl &= ~SPORT_CTL_SPENPRI; + SSYNC(); + disable_dma(sport->rx_dma_chan); +} +EXPORT_SYMBOL(sport_rx_stop); + +void sport_set_tx_callback(struct sport_device *sport, + void (*tx_callback)(void *), void *tx_data) +{ + sport->tx_callback = tx_callback; + sport->tx_data = tx_data; +} +EXPORT_SYMBOL(sport_set_tx_callback); + +void sport_set_rx_callback(struct sport_device *sport, + void (*rx_callback)(void *), void *rx_data) +{ + sport->rx_callback = rx_callback; + sport->rx_data = rx_data; +} +EXPORT_SYMBOL(sport_set_rx_callback); + +static void setup_desc(struct dmasg *desc, void *buf, int fragcount, + size_t fragsize, unsigned int cfg, + unsigned int count, size_t wdsize) +{ + + int i; + + for (i = 0; i < fragcount; ++i) { + desc[i].next_desc_addr = &(desc[i + 1]); + desc[i].start_addr = (unsigned long)buf + i*fragsize; + desc[i].cfg = cfg; + desc[i].x_count = count; + desc[i].x_modify = wdsize; + desc[i].y_count = 0; + desc[i].y_modify = 0; + } + + /* make circular */ + desc[fragcount-1].next_desc_addr = desc; +} + +int sport_config_tx_dma(struct sport_device *sport, void *buf, + int fragcount, size_t fragsize) +{ + unsigned int count; + unsigned int cfg; + dma_addr_t addr; + + count = fragsize/sport->wdsize; + + if (sport->tx_desc) + dma_free_coherent(NULL, sport->tx_desc_size, + sport->tx_desc, 0); + + sport->tx_desc = dma_alloc_coherent(NULL, + fragcount * sizeof(struct dmasg), &addr, 0); + sport->tx_desc_size = fragcount * sizeof(struct dmasg); + if (!sport->tx_desc) + return -ENOMEM; + + sport->tx_buf = buf; + sport->tx_fragsize = fragsize; + sport->tx_frags = fragcount; + cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | NDSIZE_6; + + setup_desc(sport->tx_desc, buf, fragcount, fragsize, + cfg|DMAEN, count, sport->wdsize); + + return 0; +} +EXPORT_SYMBOL(sport_config_tx_dma); + +int sport_config_rx_dma(struct sport_device *sport, void *buf, + int fragcount, size_t fragsize) +{ + unsigned int count; + unsigned int cfg; + dma_addr_t addr; + + count = fragsize/sport->wdsize; + + if (sport->rx_desc) + dma_free_coherent(NULL, sport->rx_desc_size, + sport->rx_desc, 0); + + sport->rx_desc = dma_alloc_coherent(NULL, + fragcount * sizeof(struct dmasg), &addr, 0); + sport->rx_desc_size = fragcount * sizeof(struct dmasg); + if (!sport->rx_desc) + return -ENOMEM; + + sport->rx_buf = buf; + sport->rx_fragsize = fragsize; + sport->rx_frags = fragcount; + cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) + | WNR | NDSIZE_6; + + setup_desc(sport->rx_desc, buf, fragcount, fragsize, + cfg|DMAEN, count, sport->wdsize); + + return 0; +} +EXPORT_SYMBOL(sport_config_rx_dma); + +unsigned long sport_curr_offset_tx(struct sport_device *sport) +{ + unsigned long curr = get_dma_curr_addr(sport->tx_dma_chan); + + return (unsigned char *)curr - sport->tx_buf; +} +EXPORT_SYMBOL(sport_curr_offset_tx); + +unsigned long sport_curr_offset_rx(struct sport_device *sport) +{ + unsigned long curr = get_dma_curr_addr(sport->rx_dma_chan); + + return (unsigned char *)curr - sport->rx_buf; +} +EXPORT_SYMBOL(sport_curr_offset_rx); + +static irqreturn_t sport_tx_irq(int irq, void *dev_id) +{ + struct sport_device *sport = dev_id; + static unsigned long status; + + status = get_dma_curr_irqstat(sport->tx_dma_chan); + if (status & (DMA_DONE|DMA_ERR)) { + clear_dma_irqstat(sport->tx_dma_chan); + SSYNC(); + } + if (sport->tx_callback) + sport->tx_callback(sport->tx_data); + return IRQ_HANDLED; +} + +static irqreturn_t sport_rx_irq(int irq, void *dev_id) +{ + struct sport_device *sport = dev_id; + unsigned long status; + + status = get_dma_curr_irqstat(sport->rx_dma_chan); + if (status & (DMA_DONE|DMA_ERR)) { + clear_dma_irqstat(sport->rx_dma_chan); + SSYNC(); + } + if (sport->rx_callback) + sport->rx_callback(sport->rx_data); + return IRQ_HANDLED; +} + +static irqreturn_t sport_err_irq(int irq, void *dev_id) +{ + struct sport_device *sport = dev_id; + struct device *dev = &sport->pdev->dev; + + if (sport->tx_regs->spctl & SPORT_CTL_DERRPRI) + dev_dbg(dev, "sport error: TUVF\n"); + if (sport->rx_regs->spctl & SPORT_CTL_DERRPRI) + dev_dbg(dev, "sport error: ROVF\n"); + + return IRQ_HANDLED; +} + +static int sport_get_resource(struct sport_device *sport) +{ + struct platform_device *pdev = sport->pdev; + struct device *dev = &pdev->dev; + struct bfin_snd_platform_data *pdata = dev->platform_data; + struct resource *res; + + if (!pdata) { + dev_err(dev, "No platform data\n"); + return -ENODEV; + } + sport->pin_req = pdata->pin_req; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "No tx MEM resource\n"); + return -ENODEV; + } + sport->tx_regs = (struct sport_register *)res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "No rx MEM resource\n"); + return -ENODEV; + } + sport->rx_regs = (struct sport_register *)res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!res) { + dev_err(dev, "No tx DMA resource\n"); + return -ENODEV; + } + sport->tx_dma_chan = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!res) { + dev_err(dev, "No rx DMA resource\n"); + return -ENODEV; + } + sport->rx_dma_chan = res->start; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "No tx error irq resource\n"); + return -ENODEV; + } + sport->tx_err_irq = res->start; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + if (!res) { + dev_err(dev, "No rx error irq resource\n"); + return -ENODEV; + } + sport->rx_err_irq = res->start; + + return 0; +} + +static int sport_request_resource(struct sport_device *sport) +{ + struct device *dev = &sport->pdev->dev; + int ret; + + ret = peripheral_request_list(sport->pin_req, "soc-audio"); + if (ret) { + dev_err(dev, "Unable to request sport pin\n"); + return ret; + } + + ret = request_dma(sport->tx_dma_chan, "SPORT TX Data"); + if (ret) { + dev_err(dev, "Unable to allocate DMA channel for sport tx\n"); + goto err_tx_dma; + } + set_dma_callback(sport->tx_dma_chan, sport_tx_irq, sport); + + ret = request_dma(sport->rx_dma_chan, "SPORT RX Data"); + if (ret) { + dev_err(dev, "Unable to allocate DMA channel for sport rx\n"); + goto err_rx_dma; + } + set_dma_callback(sport->rx_dma_chan, sport_rx_irq, sport); + + ret = request_irq(sport->tx_err_irq, sport_err_irq, + 0, "SPORT TX ERROR", sport); + if (ret) { + dev_err(dev, "Unable to allocate tx error IRQ for sport\n"); + goto err_tx_irq; + } + + ret = request_irq(sport->rx_err_irq, sport_err_irq, + 0, "SPORT RX ERROR", sport); + if (ret) { + dev_err(dev, "Unable to allocate rx error IRQ for sport\n"); + goto err_rx_irq; + } + + return 0; +err_rx_irq: + free_irq(sport->tx_err_irq, sport); +err_tx_irq: + free_dma(sport->rx_dma_chan); +err_rx_dma: + free_dma(sport->tx_dma_chan); +err_tx_dma: + peripheral_free_list(sport->pin_req); + return ret; +} + +static void sport_free_resource(struct sport_device *sport) +{ + free_irq(sport->rx_err_irq, sport); + free_irq(sport->tx_err_irq, sport); + free_dma(sport->rx_dma_chan); + free_dma(sport->tx_dma_chan); + peripheral_free_list(sport->pin_req); +} + +struct sport_device *sport_create(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sport_device *sport; + int ret; + + sport = kzalloc(sizeof(*sport), GFP_KERNEL); + if (!sport) { + dev_err(dev, "Unable to allocate memory for sport device\n"); + return NULL; + } + sport->pdev = pdev; + + ret = sport_get_resource(sport); + if (ret) { + kfree(sport); + return NULL; + } + + ret = sport_request_resource(sport); + if (ret) { + kfree(sport); + return NULL; + } + + dev_dbg(dev, "SPORT create success\n"); + return sport; +} +EXPORT_SYMBOL(sport_create); + +void sport_delete(struct sport_device *sport) +{ + sport_free_resource(sport); +} +EXPORT_SYMBOL(sport_delete); + +MODULE_DESCRIPTION("Analog Devices BF6XX SPORT driver"); +MODULE_AUTHOR("Scott Jiang "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/blackfin/bf6xx-sport.h b/sound/soc/blackfin/bf6xx-sport.h new file mode 100644 index 000000000000..307d193cfcef --- /dev/null +++ b/sound/soc/blackfin/bf6xx-sport.h @@ -0,0 +1,82 @@ +/* + * bf6xx_sport - Analog Devices BF6XX SPORT driver + * + * Copyright (c) 2012 Analog Devices 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _BF6XX_SPORT_H_ +#define _BF6XX_SPORT_H_ + +#include +#include + +struct sport_device { + struct platform_device *pdev; + const unsigned short *pin_req; + struct sport_register *tx_regs; + struct sport_register *rx_regs; + int tx_dma_chan; + int rx_dma_chan; + int tx_err_irq; + int rx_err_irq; + + void (*tx_callback)(void *data); + void *tx_data; + void (*rx_callback)(void *data); + void *rx_data; + + struct dmasg *tx_desc; + struct dmasg *rx_desc; + unsigned int tx_desc_size; + unsigned int rx_desc_size; + unsigned char *tx_buf; + unsigned char *rx_buf; + unsigned int tx_fragsize; + unsigned int rx_fragsize; + unsigned int tx_frags; + unsigned int rx_frags; + unsigned int wdsize; +}; + +struct sport_params { + u32 spctl; + u32 div; +}; + +struct sport_device *sport_create(struct platform_device *pdev); +void sport_delete(struct sport_device *sport); +int sport_set_tx_params(struct sport_device *sport, + struct sport_params *params); +int sport_set_rx_params(struct sport_device *sport, + struct sport_params *params); +void sport_tx_start(struct sport_device *sport); +void sport_rx_start(struct sport_device *sport); +void sport_tx_stop(struct sport_device *sport); +void sport_rx_stop(struct sport_device *sport); +void sport_set_tx_callback(struct sport_device *sport, + void (*tx_callback)(void *), void *tx_data); +void sport_set_rx_callback(struct sport_device *sport, + void (*rx_callback)(void *), void *rx_data); +int sport_config_tx_dma(struct sport_device *sport, void *buf, + int fragcount, size_t fragsize); +int sport_config_rx_dma(struct sport_device *sport, void *buf, + int fragcount, size_t fragsize); +unsigned long sport_curr_offset_tx(struct sport_device *sport); +unsigned long sport_curr_offset_rx(struct sport_device *sport); + + + +#endif -- GitLab From f62ae7bda434ac5d2bcd6feb4f5bdb5885633177 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 20 Jun 2012 17:00:31 -0400 Subject: [PATCH 0942/5711] ASoC: add i2s dai driver for bf6xx soc This driver enables i2s mode support on blackfin bf6xx platform. We reuse bf5xx-i2s-pcm.c as its i2s pcm driver because it's the same for both bf5xx and bf6xx soc. Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 11 +- sound/soc/blackfin/Makefile | 2 + sound/soc/blackfin/bf6xx-i2s.c | 234 +++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 sound/soc/blackfin/bf6xx-i2s.c diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 0374a3965095..16b88f5c26e2 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -10,12 +10,14 @@ config SND_BF5XX_I2S You will also need to select the audio interfaces to support below. config SND_BF5XX_SOC_SSM2602 - tristate "SoC SSM2602 Audio support for BF52x ezkit" + tristate "SoC SSM2602 Audio Codec Add-On Card support" depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) - select SND_BF5XX_SOC_I2S + select SND_BF5XX_SOC_I2S if !BF60x + select SND_BF6XX_SOC_I2S if BF60x select SND_SOC_SSM2602 help - Say Y if you want to add support for SoC audio on BF527-EZKIT. + Say Y if you want to add support for the Analog Devices + SSM2602 Audio Codec Add-On Card. config SND_SOC_BFIN_EVAL_ADAU1701 tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" @@ -169,6 +171,9 @@ config SND_BF6XX_SOC_SPORT config SND_BF5XX_SOC_I2S tristate +config SND_BF6XX_SOC_I2S + tristate + config SND_BF5XX_SOC_TDM tristate diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 13b092239a82..6fea1f4cbee2 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile @@ -6,6 +6,7 @@ snd-soc-bf5xx-sport-objs := bf5xx-sport.o snd-soc-bf6xx-sport-objs := bf6xx-sport.o snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o +snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o @@ -15,6 +16,7 @@ obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o +obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o # Blackfin Machine Support diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c new file mode 100644 index 000000000000..c3c2466d3a42 --- /dev/null +++ b/sound/soc/blackfin/bf6xx-i2s.c @@ -0,0 +1,234 @@ +/* + * bf6xx-i2s.c - Analog Devices BF6XX i2s interface driver + * + * Copyright (c) 2012 Analog Devices 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bf6xx-sport.h" + +struct sport_params param; + +static int bfin_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct sport_device *sport = snd_soc_dai_get_drvdata(cpu_dai); + struct device *dev = &sport->pdev->dev; + int ret = 0; + + param.spctl &= ~(SPORT_CTL_OPMODE | SPORT_CTL_CKRE | SPORT_CTL_FSR + | SPORT_CTL_LFS | SPORT_CTL_LAFS); + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_CKRE + | SPORT_CTL_LFS; + break; + case SND_SOC_DAIFMT_DSP_A: + param.spctl |= SPORT_CTL_FSR; + break; + case SND_SOC_DAIFMT_LEFT_J: + param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_LFS + | SPORT_CTL_LAFS; + break; + default: + dev_err(dev, "%s: Unknown DAI format type\n", __func__); + ret = -EINVAL; + break; + } + + param.spctl &= ~(SPORT_CTL_ICLK | SPORT_CTL_IFS); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + break; + case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBS_CFM: + ret = -EINVAL; + break; + default: + dev_err(dev, "%s: Unknown DAI master type\n", __func__); + ret = -EINVAL; + break; + } + + return ret; +} + +static int bfin_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); + struct device *dev = &sport->pdev->dev; + int ret = 0; + + param.spctl &= ~SPORT_CTL_SLEN; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + param.spctl |= 0x70; + sport->wdsize = 1; + case SNDRV_PCM_FORMAT_S16_LE: + param.spctl |= 0xf0; + sport->wdsize = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + param.spctl |= 0x170; + sport->wdsize = 3; + break; + case SNDRV_PCM_FORMAT_S32_LE: + param.spctl |= 0x1f0; + sport->wdsize = 4; + break; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = sport_set_tx_params(sport, ¶m); + if (ret) { + dev_err(dev, "SPORT tx is busy!\n"); + return ret; + } + } else { + ret = sport_set_rx_params(sport, ¶m); + if (ret) { + dev_err(dev, "SPORT rx is busy!\n"); + return ret; + } + } + return 0; +} + +#ifdef CONFIG_PM +static int bfin_i2s_suspend(struct snd_soc_dai *dai) +{ + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); + + if (dai->capture_active) + sport_rx_stop(sport); + if (dai->playback_active) + sport_tx_stop(sport); + return 0; +} + +static int bfin_i2s_resume(struct snd_soc_dai *dai) +{ + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); + struct device *dev = &sport->pdev->dev; + int ret; + + ret = sport_set_tx_params(sport, ¶m); + if (ret) { + dev_err(dev, "SPORT tx is busy!\n"); + return ret; + } + ret = sport_set_rx_params(sport, ¶m); + if (ret) { + dev_err(dev, "SPORT rx is busy!\n"); + return ret; + } + + return 0; +} + +#else +#define bfin_i2s_suspend NULL +#define bfin_i2s_resume NULL +#endif + +#define BFIN_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define BFIN_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops bfin_i2s_dai_ops = { + .hw_params = bfin_i2s_hw_params, + .set_fmt = bfin_i2s_set_dai_fmt, +}; + +static struct snd_soc_dai_driver bfin_i2s_dai = { + .suspend = bfin_i2s_suspend, + .resume = bfin_i2s_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = BFIN_I2S_RATES, + .formats = BFIN_I2S_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = BFIN_I2S_RATES, + .formats = BFIN_I2S_FORMATS, + }, + .ops = &bfin_i2s_dai_ops, +}; + +static int __devinit bfin_i2s_probe(struct platform_device *pdev) +{ + struct sport_device *sport; + struct device *dev = &pdev->dev; + int ret; + + sport = sport_create(pdev); + if (!sport) + return -ENODEV; + + /* register with the ASoC layers */ + ret = snd_soc_register_dai(dev, &bfin_i2s_dai); + if (ret) { + dev_err(dev, "Failed to register DAI: %d\n", ret); + sport_delete(sport); + return ret; + } + platform_set_drvdata(pdev, sport); + + return 0; +} + +static int __devexit bfin_i2s_remove(struct platform_device *pdev) +{ + struct sport_device *sport = platform_get_drvdata(pdev); + + snd_soc_unregister_dai(&pdev->dev); + sport_delete(sport); + + return 0; +} + +static struct platform_driver bfin_i2s_driver = { + .probe = bfin_i2s_probe, + .remove = __devexit_p(bfin_i2s_remove), + .driver = { + .name = "bfin-i2s", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(bfin_i2s_driver); + +MODULE_DESCRIPTION("Analog Devices BF6XX i2s interface driver"); +MODULE_AUTHOR("Scott Jiang "); +MODULE_LICENSE("GPL v2"); -- GitLab From 7d7136cabcad632a81cd568a9c1135db276fe0f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:35:15 -0700 Subject: [PATCH 0943/5711] ARM: shmobile: r8a7740: add HDMI interrupt support It is required from sh_mobile_hdmi driver. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/intc-r8a7740.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c index 09c42afcb22d..9a69a31918ba 100644 --- a/arch/arm/mach-shmobile/intc-r8a7740.c +++ b/arch/arm/mach-shmobile/intc-r8a7740.c @@ -71,10 +71,12 @@ enum { DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3, DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, + HDMI, USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND, RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, SPU2_0, SPU2_1, FSI, FMSI, + HDMI_SSS, HDMI_KEY, IPMMU, AP_ARM_CTIIRQ, AP_ARM_PMURQ, MFIS2, @@ -182,6 +184,7 @@ static struct intc_vect intca_vectors[] __initdata = { INTC_VECT(USBH_EHCI, 0x1580), INTC_VECT(USBH_PME, 0x15A0), INTC_VECT(USBH_BIND, 0x15C0), + INTC_VECT(HDMI, 0x1700), INTC_VECT(RSPI_OVRF, 0x1780), INTC_VECT(RSPI_SPTEF, 0x17A0), INTC_VECT(RSPI_SPRF, 0x17C0), @@ -189,6 +192,8 @@ static struct intc_vect intca_vectors[] __initdata = { INTC_VECT(SPU2_1, 0x1820), INTC_VECT(FSI, 0x1840), INTC_VECT(FMSI, 0x1860), + INTC_VECT(HDMI_SSS, 0x18A0), + INTC_VECT(HDMI_KEY, 0x18C0), INTC_VECT(IPMMU, 0x1920), INTC_VECT(AP_ARM_CTIIRQ, 0x1980), INTC_VECT(AP_ARM_PMURQ, 0x19A0), @@ -304,11 +309,11 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { USBH_EHCI, USBH_PME, USBH_BIND, 0 } }, /* IMR3A3 / IMCR3A3 */ { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8, - { 0, 0, 0, 0, + { HDMI, 0, 0, 0, RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } }, { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8, { SPU2_0, SPU2_1, FSI, FMSI, - 0, 0, 0, 0 } }, + 0, HDMI_SSS, HDMI_KEY, 0 } }, { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8, { 0, IPMMU, 0, 0, AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } }, @@ -353,10 +358,10 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = { { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } }, /* IPRGA3 */ /* IPRHA3 */ - /* IPRIA3 */ + { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } }, { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } }, { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } }, - /* IPRLA3 */ + { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } }, { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } }, { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } }, { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S, -- GitLab From c6750acb3b54c77c011045467770d5143be749ee Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:35:36 -0700 Subject: [PATCH 0944/5711] ARM: shmobile: r8a7740: add HDMI clock support It is required from sh_mobile_hdmi driver. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/clock-r8a7740.c | 84 ++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 26eea5f21054..b09534352f97 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -54,6 +54,7 @@ #define MSTPSR2 0xe6150040 #define MSTPSR3 0xe6150048 #define MSTPSR4 0xe615004c +#define HDMICKCR 0xe6150094 #define SMSTPCR0 0xe6150130 #define SMSTPCR1 0xe6150134 #define SMSTPCR2 0xe6150138 @@ -313,6 +314,79 @@ static struct clk_div4_table div4_table = { .kick = div4_kick, }; +/* DIV6 reparent */ +enum { + DIV6_HDMI, + DIV6_REPARENT_NR, +}; + +static struct clk *hdmi_parent[] = { + [0] = &pllc1_div2_clk, + [1] = &system_clk, + [2] = &dv_clk +}; + +static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { + [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, + hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), +}; + +/* HDMI1/2 clock */ +static unsigned long hdmi12_recalc(struct clk *clk) +{ + u32 val = __raw_readl(HDMICKCR); + int shift = (int)clk->priv; + + val >>= shift; + val &= 0x3; + + return clk->parent->rate / (1 << val); +}; + +static int hdmi12_set_rate(struct clk *clk, unsigned long rate) +{ + u32 val, mask; + int i, shift; + + for (i = 0; i < 3; i++) + if (rate == clk->parent->rate / (1 << i)) + goto find; + return -ENODEV; + +find: + shift = (int)clk->priv; + + val = __raw_readl(HDMICKCR); + mask = ~(0x3 << shift); + val = (val & mask) | i << shift; + __raw_writel(val, HDMICKCR); + + return 0; +}; + +static struct sh_clk_ops hdmi12_clk_ops = { + .recalc = hdmi12_recalc, + .set_rate = hdmi12_set_rate, +}; + +static struct clk hdmi1_clk = { + .ops = &hdmi12_clk_ops, + .priv = (void *)9, + .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ +}; + +static struct clk hdmi2_clk = { + .ops = &hdmi12_clk_ops, + .priv = (void *)11, + .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ +}; + +static struct clk *late_main_clks[] = { + &hdmi1_clk, + &hdmi2_clk, +}; + +/* MSTP */ enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, @@ -408,6 +482,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), CLKDEV_CON_ID("usb24s", &usb24s_clk), + CLKDEV_CON_ID("hdmi1", &hdmi1_clk), + CLKDEV_CON_ID("hdmi2", &hdmi2_clk), /* DIV4 clocks */ CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), @@ -459,6 +535,7 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), + CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), }; void __init r8a7740_clock_init(u8 md_ck) @@ -494,9 +571,16 @@ void __init r8a7740_clock_init(u8 md_ck) if (!ret) ret = sh_clk_div6_register(div6_clks, DIV6_NR); + if (!ret) + ret = sh_clk_div6_reparent_register(div6_reparent_clks, + DIV6_REPARENT_NR); + if (!ret) ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); if (!ret) -- GitLab From e2dcd461a7ba0c3deb44336136ea784c8b972292 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:35:58 -0700 Subject: [PATCH 0945/5711] ARM: shmobile: r8a7740: add HDMI GPIO support In order to enable HDMI GPIO selection from platform board, this patch adds its interface to GPIO framework. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/r8a7740.h | 4 ++++ arch/arm/mach-shmobile/pfc-r8a7740.c | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index 9d447abb969c..276484629fb2 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -565,6 +565,10 @@ enum { GPIO_FN_RESETP_PULLUP, GPIO_FN_RESETP_PLAIN, + /* HDMI */ + GPIO_FN_HDMI_HPD, + GPIO_FN_HDMI_CEC, + /* SDENC */ GPIO_FN_SDENC_CPG, GPIO_FN_SDENC_DV_CLKI, diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index 670fe1869dbc..0dda816feff8 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c @@ -560,6 +560,9 @@ enum { /* SDENC */ SDENC_CPG_MARK, SDENC_DV_CLKI_MARK, + /* HDMI */ + HDMI_HPD_MARK, HDMI_CEC_MARK, + /* DEBUG */ EDEBGREQ_PULLUP_MARK, /* for JTAG */ EDEBGREQ_PULLDOWN_MARK, @@ -1620,9 +1623,11 @@ static pinmux_enum_t pinmux_data[] = { /* Port210 */ PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), + PINMUX_DATA(HDMI_HPD_MARK, PORT210_FN1), /* Port211 */ PINMUX_DATA(IRQ16_PORT211_MARK, PORT211_FN0, MSEL1CR_16_1), + PINMUX_DATA(HDMI_CEC_MARK, PORT211_FN1), /* LCDC select */ PINMUX_DATA(LCDC0_SELECT_MARK, MSEL3CR_6_0), @@ -2097,6 +2102,10 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(SDENC_CPG), GPIO_FN(SDENC_DV_CLKI), + /* HDMI */ + GPIO_FN(HDMI_HPD), + GPIO_FN(HDMI_CEC), + /* SYSC */ GPIO_FN(RESETP_PULLUP), GPIO_FN(RESETP_PLAIN), -- GitLab From d49679e5928709bce8937dce396458b139c4b34d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:36:21 -0700 Subject: [PATCH 0946/5711] ARM: shmobile: r8a7740: add MERAM work-around r8a7740 chip has lasting errata on MERAM buffer, and this patch adds its work-around on setup-r8a7740.c It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error. But MERAM driver can't control this issue, since this work-around requires access to non-MERAM register address. So, This it will be called as board specific code at this point. Signed-off-by: Kuninori Morimoto Tested-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 + arch/arm/mach-shmobile/include/mach/common.h | 1 + arch/arm/mach-shmobile/setup-r8a7740.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 9e37026ef9dd..6e6839d0a2dc 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -587,6 +587,7 @@ static void __init eva_init(void) eva_clock_init(); r8a7740_pinmux_init(); + r8a7740_meram_workaround(); /* SCIFA1 */ gpio_request(GPIO_FN_SCIFA1_RXD, NULL); diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 01e2bc014f15..45e61dada030 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -77,6 +77,7 @@ extern void r8a7779_add_standard_devices(void); extern void r8a7779_clock_init(void); extern void r8a7779_pinmux_init(void); extern void r8a7779_pm_init(void); +extern void r8a7740_meram_workaround(void); extern unsigned int r8a7779_get_core_count(void); extern int r8a7779_platform_cpu_kill(unsigned int cpu); diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index ec4eb49c1693..366311b3dc73 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -324,6 +324,24 @@ static struct platform_device *r8a7740_late_devices[] __initdata = { &i2c1_device, }; +/* + * r8a7740 chip has lasting errata on MERAM buffer. + * this is work-around for it. + * see + * "Media RAM (MERAM)" on r8a7740 documentation + */ +#define MEBUFCNTR 0xFE950098 +void r8a7740_meram_workaround(void) +{ + void __iomem *reg; + + reg = ioremap_nocache(MEBUFCNTR, 4); + if (reg) { + iowrite32(0x01600164, reg); + iounmap(reg); + } +} + #define ICCR 0x0004 #define ICSTART 0x0070 -- GitLab From ad9f1721c15b84f1a2e45a8a03f1ff7c86c2829b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:36:39 -0700 Subject: [PATCH 0947/5711] ARM: shmobile: r8a7740: add CEU clock support It is required from sh_mobile_ceu_camera driver. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Tested-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/clock-r8a7740.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index b09534352f97..ce0930a415e8 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -43,6 +43,8 @@ /* CPG registers */ #define FRQCRA 0xe6150000 #define FRQCRB 0xe6150004 +#define VCLKCR1 0xE6150008 +#define VCLKCR2 0xE615000c #define FRQCRC 0xe61500e0 #define PLLC01CR 0xe6150028 @@ -317,6 +319,7 @@ static struct clk_div4_table div4_table = { /* DIV6 reparent */ enum { DIV6_HDMI, + DIV6_VCLK1, DIV6_VCLK2, DIV6_REPARENT_NR, }; @@ -326,9 +329,21 @@ static struct clk *hdmi_parent[] = { [2] = &dv_clk }; +static struct clk *vclk_parents[8] = { + [0] = &pllc1_div2_clk, + [2] = &dv_clk, + [3] = &usb24s_clk, + [4] = &extal1_div2_clk, + [5] = &extalr_clk, +}; + static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), + [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), }; /* HDMI1/2 clock */ @@ -417,7 +432,7 @@ static struct clk div6_clks[DIV6_NR] = { }; enum { - MSTP125, + MSTP128, MSTP127, MSTP125, MSTP116, MSTP111, MSTP100, MSTP117, MSTP230, @@ -434,6 +449,8 @@ enum { }; static struct clk mstp_clks[MSTP_NR] = { + [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */ + [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */ [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ @@ -484,6 +501,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("usb24s", &usb24s_clk), CLKDEV_CON_ID("hdmi1", &hdmi1_clk), CLKDEV_CON_ID("hdmi2", &hdmi2_clk), + CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), + CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), /* DIV4 clocks */ CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), @@ -506,6 +525,8 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), + CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), -- GitLab From 69efac9a8bc6d479bc4c339ae4ac4d353460def6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:36:58 -0700 Subject: [PATCH 0948/5711] ARM: shmobile: r8a7740: add FSI parent clock support r8a7740 FSI can select its parent clock, and its selection is dependent on platform board. In order to enable FSI parent selection from platform board, this patch adds its interface to clock framework. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Tested-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/clock-r8a7740.c | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index ce0930a415e8..7b9e4ab34fa2 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -46,6 +46,7 @@ #define VCLKCR1 0xE6150008 #define VCLKCR2 0xE615000c #define FRQCRC 0xe61500e0 +#define FSIACKCR 0xe6150018 #define PLLC01CR 0xe6150028 #define SUBCKCR 0xe6150080 @@ -56,6 +57,7 @@ #define MSTPSR2 0xe6150040 #define MSTPSR3 0xe6150048 #define MSTPSR4 0xe615004c +#define FSIBCKCR 0xe6150090 #define HDMICKCR 0xe6150094 #define SMSTPCR0 0xe6150130 #define SMSTPCR1 0xe6150134 @@ -274,6 +276,13 @@ static struct clk usb24_clk = { .parent = &usb24s_clk, }; +/* External FSIACK/FSIBCK clock */ +static struct clk fsiack_clk = { +}; + +static struct clk fsibck_clk = { +}; + struct clk *main_clks[] = { &extalr_clk, &extal1_clk, @@ -291,6 +300,8 @@ struct clk *main_clks[] = { &pllc1_div2_clk, &usb24s_clk, &usb24_clk, + &fsiack_clk, + &fsibck_clk, }; static void div4_kick(struct clk *clk) @@ -320,6 +331,7 @@ static struct clk_div4_table div4_table = { enum { DIV6_HDMI, DIV6_VCLK1, DIV6_VCLK2, + DIV6_FSIA, DIV6_FSIB, DIV6_REPARENT_NR, }; @@ -337,6 +349,16 @@ static struct clk *vclk_parents[8] = { [5] = &extalr_clk, }; +static struct clk *fsia_parents[] = { + [0] = &pllc1_div2_clk, + [1] = &fsiack_clk, /* external clock */ +}; + +static struct clk *fsib_parents[] = { + [0] = &pllc1_div2_clk, + [1] = &fsibck_clk, /* external clock */ +}; + static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), @@ -344,6 +366,10 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, + fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2), + [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, + fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2), }; /* HDMI1/2 clock */ @@ -503,6 +529,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("hdmi2", &hdmi2_clk), CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), + CLKDEV_CON_ID("fsiack", &fsiack_clk), + CLKDEV_CON_ID("fsibck", &fsibck_clk), /* DIV4 clocks */ CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), @@ -557,6 +585,9 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), + + CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), + CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), }; void __init r8a7740_clock_init(u8 md_ck) -- GitLab From 147d1ffdc21d067f0084f0911dbf1eee57e3d76b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:37:16 -0700 Subject: [PATCH 0949/5711] ARM: shmobile: r8a7740: add FSI-B (for HDMI) GPIO support In order to enable FSI-B selection from platform board, this patch adds its interface to GPIO framework. This patch is based on v1.0 manual Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/r8a7740.h | 5 ++++- arch/arm/mach-shmobile/pfc-r8a7740.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index 276484629fb2..6468fcc5ee49 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -139,7 +139,7 @@ enum { GPIO_FN_DBGMD10, GPIO_FN_DBGMD11, GPIO_FN_DBGMD20, GPIO_FN_DBGMD21, - /* FSI */ + /* FSI-A */ GPIO_FN_FSIAISLD_PORT0, /* FSIAISLD Port 0/5 */ GPIO_FN_FSIAISLD_PORT5, GPIO_FN_FSIASPDIF_PORT9, /* FSIASPDIF Port 9/18 */ @@ -150,6 +150,9 @@ enum { GPIO_FN_FSIACK, GPIO_FN_FSIAILR, GPIO_FN_FSIAIBT, + /* FSI-B */ + GPIO_FN_FSIBCK, + /* FMSI */ GPIO_FN_FMSISLD_PORT1, /* FMSISLD Port 1/6 */ GPIO_FN_FMSISLD_PORT6, diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index 0dda816feff8..03def0fd7a05 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c @@ -169,7 +169,7 @@ enum { DBGMD10_MARK, DBGMD11_MARK, DBGMD20_MARK, DBGMD21_MARK, - /* FSI */ + /* FSI-A */ FSIAISLD_PORT0_MARK, /* FSIAISLD Port 0/5 */ FSIAISLD_PORT5_MARK, FSIASPDIF_PORT9_MARK, /* FSIASPDIF Port 9/18 */ @@ -178,6 +178,9 @@ enum { FSIAOBT_MARK, FSIAOSLD_MARK, FSIAOMC_MARK, FSIACK_MARK, FSIAILR_MARK, FSIAIBT_MARK, + /* FSI-B */ + FSIBCK_MARK, + /* FMSI */ FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */ FMSISLD_PORT6_MARK, @@ -774,6 +777,7 @@ static pinmux_enum_t pinmux_data[] = { /* Port11 */ PINMUX_DATA(FSIACK_MARK, PORT11_FN1), + PINMUX_DATA(FSIBCK_MARK, PORT11_FN2), PINMUX_DATA(IRQ2_PORT11_MARK, PORT11_FN0, MSEL1CR_2_0), /* Port12 */ @@ -1696,7 +1700,7 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(DBGMD10), GPIO_FN(DBGMD11), GPIO_FN(DBGMD20), GPIO_FN(DBGMD21), - /* FSI */ + /* FSI-A */ GPIO_FN(FSIAISLD_PORT0), /* FSIAISLD Port 0/5 */ GPIO_FN(FSIAISLD_PORT5), GPIO_FN(FSIASPDIF_PORT9), /* FSIASPDIF Port 9/18 */ @@ -1705,6 +1709,9 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(FSIAOBT), GPIO_FN(FSIAOSLD), GPIO_FN(FSIAOMC), GPIO_FN(FSIACK), GPIO_FN(FSIAILR), GPIO_FN(FSIAIBT), + /* FSI-B */ + GPIO_FN(FSIBCK), + /* FMSI */ GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */ GPIO_FN(FMSISLD_PORT6), -- GitLab From 910c14d0b8f121df420a878cbd973ffa7d549393 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 Jun 2012 02:39:11 -0700 Subject: [PATCH 0950/5711] ARM: shmobile: armadillo800eva: enable HDMI This patch enable HDMI support on CON3. And removed unnecessary CONFIG_SYSFS_DEPRECATED_xxx config. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/configs/armadillo800eva_defconfig | 10 +- .../arm/mach-shmobile/board-armadillo800eva.c | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig index ddc9fe6a78ac..f6ebdde380ee 100644 --- a/arch/arm/configs/armadillo800eva_defconfig +++ b/arch/arm/configs/armadillo800eva_defconfig @@ -5,10 +5,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 # CONFIG_UTS_NS is not set # CONFIG_IPC_NS is not set -# CONFIG_USER_NS is not set # CONFIG_PID_NS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SLAB=y CONFIG_MODULES=y @@ -90,25 +87,21 @@ CONFIG_I2C=y CONFIG_I2C_SH_MOBILE=y # CONFIG_HWMON is not set CONFIG_FB=y -CONFIG_FB_MODE_HELPERS=y CONFIG_FB_SH_MOBILE_LCDC=y +CONFIG_FB_SH_MOBILE_HDMI=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_SOUND=y -CONFIG_SND=y # CONFIG_SND_SUPPORT_OLD_API is not set # CONFIG_SND_VERBOSE_PROCFS is not set # CONFIG_SND_DRIVERS is not set # CONFIG_SND_ARM is not set -CONFIG_SND_SOC=y CONFIG_SND_SOC_SH4_FSI=y # CONFIG_HID_SUPPORT is not set CONFIG_USB=y -# CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_GADGET=y CONFIG_USB_RENESAS_USBHS_UDC=y @@ -124,7 +117,6 @@ CONFIG_VFAT_FS=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 6e6839d0a2dc..4e6893f9e0da 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -45,6 +45,7 @@ #include #include #include +
+ V4L2 in Linux 3.5 + + + Replaced input in + v4l2_buffer by + reserved2 and removed + V4L2_BUF_FLAG_INPUT. + + +
+
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml index fd6aca2922b6..1885cc0755cb 100644 --- a/Documentation/DocBook/media/v4l/io.xml +++ b/Documentation/DocBook/media/v4l/io.xml @@ -683,14 +683,12 @@ memory, set by the application. See for details. __u32 - input + reserved2 - Some video capture drivers support rapid and -synchronous video input changes, a function useful for example in -video surveillance applications. For this purpose applications set the -V4L2_BUF_FLAG_INPUT flag, and this field to the -number of a video input as in &v4l2-input; field -index. + A place holder for future extensions and custom +(driver defined) buffer types +V4L2_BUF_TYPE_PRIVATE and higher. Applications +should set this to 0. __u32 @@ -921,13 +919,6 @@ previous key frame. The timecode field is valid. Drivers set or clear this flag when the VIDIOC_DQBUF ioctl is called. - - - V4L2_BUF_FLAG_INPUT - 0x0200 - The input field is valid. -Applications set or clear this flag before calling the -VIDIOC_QBUF ioctl. V4L2_BUF_FLAG_PREPARED diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml index 9caa49af580f..77ff5be0809d 100644 --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml @@ -71,12 +71,9 @@ initialize the bytesused, field and timestamp fields, see for details. -Applications must also set flags to 0. If a driver -supports capturing from specific video inputs and you want to specify a video -input, then flags should be set to -V4L2_BUF_FLAG_INPUT and the field -input must be initialized to the desired input. -The reserved field must be set to 0. When using +Applications must also set flags to 0. +The reserved2 and +reserved fields must be set to 0. When using the multi-planar API, the m.planes field must contain a userspace pointer to a filled-in array of &v4l2-plane; and the length diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 55e92902a76c..a62a7b739991 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -932,7 +932,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->sequence = cam->buffers[buf->index].seq; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; - buf->input = 0; + buf->reserved2 = 0; buf->reserved = 0; memset(&buf->timecode, 0, sizeof(buf->timecode)); diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 5327ad3a6390..658ba46ee9d2 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -327,7 +327,7 @@ struct v4l2_buffer32 { compat_caddr_t planes; } m; __u32 length; - __u32 input; + __u32 reserved2; __u32 reserved; }; @@ -387,8 +387,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory) || - get_user(kp->input, &up->input)) + get_user(kp->memory, &up->memory) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -472,8 +471,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user put_user(kp->index, &up->index) || put_user(kp->type, &up->type) || put_user(kp->flags, &up->flags) || - put_user(kp->memory, &up->memory) || - put_user(kp->input, &up->input)) + put_user(kp->memory, &up->memory) return -EFAULT; if (put_user(kp->bytesused, &up->bytesused) || @@ -482,7 +480,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || - put_user(kp->reserved, &up->reserved)) + put_user(kp->reserved2, &up->reserved2) || + put_user(kp->reserved, &up->reserved) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index ffdf59cfe405..bf7a326b1cdc 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -359,11 +359,6 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, break; } - if (vb->input != UNSET) { - b->flags |= V4L2_BUF_FLAG_INPUT; - b->input = vb->input; - } - b->field = vb->field; b->timestamp = vb->ts; b->bytesused = vb->size; @@ -402,7 +397,6 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, break; q->bufs[i]->i = i; - q->bufs[i]->input = UNSET; q->bufs[i]->memory = memory; q->bufs[i]->bsize = bsize; switch (memory) { @@ -566,16 +560,6 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) goto done; } - if (b->flags & V4L2_BUF_FLAG_INPUT) { - if (b->input >= q->inputs) { - dprintk(1, "qbuf: wrong input.\n"); - goto done; - } - buf->input = b->input; - } else { - buf->input = UNSET; - } - switch (b->memory) { case V4L2_MEMORY_MMAP: if (0 == buf->baddr) { diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 9d4e9edbd2e7..ec24718b3ed0 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -336,9 +336,9 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) struct vb2_queue *q = vb->vb2_queue; int ret; - /* Copy back data such as timestamp, flags, input, etc. */ + /* Copy back data such as timestamp, flags, etc. */ memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m)); - b->input = vb->v4l2_buf.input; + b->reserved2 = vb->v4l2_buf.reserved2; b->reserved = vb->v4l2_buf.reserved; if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) { @@ -860,7 +860,6 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b, vb->v4l2_buf.field = b->field; vb->v4l2_buf.timestamp = b->timestamp; - vb->v4l2_buf.input = b->input; vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS; return 0; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index f79d0cc565ab..a61edb353273 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -657,7 +657,7 @@ struct v4l2_buffer { struct v4l2_plane *planes; } m; __u32 length; - __u32 input; + __u32 reserved2; __u32 reserved; }; @@ -671,7 +671,6 @@ struct v4l2_buffer { /* Buffer is ready, but the data contained within is corrupted. */ #define V4L2_BUF_FLAG_ERROR 0x0040 #define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ -#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ #define V4L2_BUF_FLAG_PREPARED 0x0400 /* Buffer is prepared for queuing */ /* Cache handling flags */ #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x0800 -- GitLab From 31361fc4632f20e3a108f56b1a1a9c9bf2dfc07c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Jul 2012 18:01:55 -0300 Subject: [PATCH 1841/5711] [media] videobuf-core.h: remove input fields Now that the input fields got removed from the userspace API, there's no sense to keep there at the VB struct. Remove it. Cc: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/videobuf-core.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 90ed895e217d..8c6e825940e5 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -72,7 +72,6 @@ struct videobuf_buffer { unsigned int height; unsigned int bytesperline; /* use only if != 0 */ unsigned long size; - unsigned int input; enum v4l2_field field; enum videobuf_state state; struct list_head stream; /* QBUF/DQBUF list */ @@ -142,7 +141,6 @@ struct videobuf_queue { wait_queue_head_t wait; /* wait if queue is empty */ enum v4l2_buf_type type; - unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ unsigned int msize; enum v4l2_field field; enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ -- GitLab From f3328a0d4b29c060117cb238be862dedbc690fa9 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:46 -0600 Subject: [PATCH 1842/5711] cris/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. This patch fixes what looks like a bug in cris, which implements pcibios_setup() such that pci_setup() doesn't look for any generic options. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/cris/arch-v32/drivers/pci/bios.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index bc0cfdad1cbc..5b1ee82f63c5 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -6,11 +6,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) { } -char * __devinit pcibios_setup(char *str) -{ - return NULL; -} - void pcibios_set_master(struct pci_dev *dev) { u8 lat; -- GitLab From 8421a35a511be699cfab08f623ce5c32706219e6 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:17 -0600 Subject: [PATCH 1843/5711] ia64/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: Tony Luck Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/pci.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 524df4295c90..e51941fe8a04 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -496,15 +496,6 @@ pcibios_align_resource (void *data, const struct resource *res, return res->start; } -/* - * PCI BIOS setup, always defaults to SAL interface - */ -char * __init -pcibios_setup (char *str) -{ - return str; -} - int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) -- GitLab From 483dae5893e11e00a0f9dbd75788844fae2221a0 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:23 -0600 Subject: [PATCH 1844/5711] microblaze/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: Michal Simek Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/microblaze/pci/pci-common.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db14..7b510ae906fa 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -192,11 +192,6 @@ void pcibios_set_master(struct pci_dev *dev) /* No special bus mastering setup handling */ } -char __devinit *pcibios_setup(char *str) -{ - return str; -} - /* * Reads the interrupt pin to determine if interrupt is use by card. * If the interrupt is used, then gets the interrupt line from the -- GitLab From 11206c93c85b2968616f9ef1672f3889f55992d4 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:30 -0600 Subject: [PATCH 1845/5711] MIPS/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/mips/pmc-sierra/yosemite/ht.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c index 63be40e470db..14dc9c8fff0e 100644 --- a/arch/mips/pmc-sierra/yosemite/ht.c +++ b/arch/mips/pmc-sierra/yosemite/ht.c @@ -395,17 +395,6 @@ void __init pcibios_init(void) pci_scan_bus(3, &titan_pci_ops, NULL); } -/* - * for parsing "pci=" kernel boot arguments. - */ -char *pcibios_setup(char *str) -{ - printk(KERN_INFO "rr: pcibios_setup\n"); - /* Nothing to do for now. */ - - return str; -} - unsigned __init int pcibios_assign_all_busses(void) { /* We want to use the PCI bus detection done by PMON */ -- GitLab From 938ca5162ec9a835078924447a6f55667e47e857 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:37 -0600 Subject: [PATCH 1846/5711] MIPS/PCI: adjust section annotations for pcibios_setup() Make pcibios_setup() consistently use the "__init" section annotation. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/mips/pci/pci.c | 4 ++-- arch/mips/txx9/generic/pci.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 271e8c4a54c7..0e111d2741ac 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -348,9 +348,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, vma->vm_end - vma->vm_start, vma->vm_page_prot); } -char * (*pcibios_plat_setup)(char *str) __devinitdata; +char * (*pcibios_plat_setup)(char *str) __initdata; -char *__devinit pcibios_setup(char *str) +char *__init pcibios_setup(char *str) { if (pcibios_plat_setup) return pcibios_plat_setup(str); diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index 682efb0c108d..f028e3dc25fb 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -398,9 +398,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return txx9_board_vec->pci_map_irq(dev, slot, pin); } -char * (*txx9_board_pcibios_setup)(char *str) __devinitdata; +char * (*txx9_board_pcibios_setup)(char *str) __initdata; -char *__devinit txx9_pcibios_setup(char *str) +char *__init txx9_pcibios_setup(char *str) { if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str)) return NULL; -- GitLab From a45639c8d367a93acce1622c8847e9e828fbb1f9 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:44 -0600 Subject: [PATCH 1847/5711] parisc/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/parisc/kernel/pci.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 24644aca10cb..60309051875e 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -139,11 +139,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) } -char *pcibios_setup(char *str) -{ - return str; -} - /* * Called by pci_set_master() - a driver interface. * -- GitLab From 67ea194ad312b8916917480faebf76fa5d9454a2 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:51 -0600 Subject: [PATCH 1848/5711] powerpc/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: Benjamin Herrenschmidt Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/powerpc/kernel/pci-common.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c8185..bf2306bfa756 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -200,11 +200,6 @@ int pcibios_add_platform_entries(struct pci_dev *pdev) return device_create_file(&pdev->dev, &dev_attr_devspec); } -char __devinit *pcibios_setup(char *str) -{ - return str; -} - /* * Reads the interrupt pin to determine if interrupt is use by card. * If the interrupt is used, then gets the interrupt line from the -- GitLab From 86927f9344ebfc1e4059eb774dbd975d50b7766b Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:58 -0600 Subject: [PATCH 1849/5711] sh/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Tested-by: Nobuhiro Iwamatsu Acked-by: Paul Mundt Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/sh/drivers/pci/pci.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 9d10a3cb8797..7d42288e1057 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -197,11 +197,6 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -char * __devinit __weak pcibios_setup(char *str) -{ - return str; -} - static void __init pcibios_bus_report_status_early(struct pci_channel *hose, int top_bus, int current_bus, -- GitLab From ce8dd71ad7cb9480d6003473630f0fbc4d67af71 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:05 -0600 Subject: [PATCH 1850/5711] sh/PCI: adjust section annotations for pcibios_setup() Make pcibios_setup() consistently use the "__init" section annotation. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/sh/drivers/pci/fixups-sdk7786.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c index 0e18ee332553..36eb6fc3c18a 100644 --- a/arch/sh/drivers/pci/fixups-sdk7786.c +++ b/arch/sh/drivers/pci/fixups-sdk7786.c @@ -23,9 +23,9 @@ * Misconfigurations can be detected through the FPGA via the slot * resistors to determine card presence. Hotplug remains unsupported. */ -static unsigned int slot4en __devinitdata; +static unsigned int slot4en __initdata; -char *__devinit pcibios_setup(char *str) +char *__init pcibios_setup(char *str) { if (strcmp(str, "slot4en") == 0) { slot4en = 1; -- GitLab From c53a25543e69d23caf2514c3ce3e734e0a68f4e9 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:12 -0600 Subject: [PATCH 1851/5711] sparc/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: David S. Miller Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/leon_pci.c | 8 -------- arch/sparc/kernel/pci.c | 5 ----- arch/sparc/kernel/pcic.c | 8 -------- 3 files changed, 21 deletions(-) diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index 19f56058742b..21dcda75a520 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c @@ -91,14 +91,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *pbus) } } -/* - * Other archs parse arguments here. - */ -char * __devinit pcibios_setup(char *str) -{ - return str; -} - resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index fdaf21811670..3e7fba0a5583 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -747,11 +747,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } -char * __devinit pcibios_setup(char *str) -{ - return str; -} - /* Platform support for /proc/bus/pci/X/Y mmap()s. */ /* If the user uses a host-bridge as the PCI device, he may use diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index ded3f6090c3f..97eb52937b82 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -767,14 +767,6 @@ static void watchdog_reset() { } #endif -/* - * Other archs parse arguments here. - */ -char * __devinit pcibios_setup(char *str) -{ - return str; -} - resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { -- GitLab From 7477dc291b5618da02e2aee388e3a4815c90906f Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:19 -0600 Subject: [PATCH 1852/5711] tile/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: Chris Metcalf Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/tile/kernel/pci.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index b56d12bf5900..e25722658c14 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -400,16 +400,6 @@ void pcibios_set_master(struct pci_dev *dev) /* No special bus mastering setup handling. */ } -/* - * This can be called from the generic PCI layer, but doesn't need to - * do anything. - */ -char __devinit *pcibios_setup(char *str) -{ - /* Nothing needs to be done. */ - return str; -} - /* * This is called from the generic Linux layer. */ -- GitLab From 5d9a19e834815c5d224662d51e4634d14fe0ba54 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:25 -0600 Subject: [PATCH 1853/5711] unicore32/PCI: adjust section annotations for pcibios_setup() Make pcibios_setup() consistently use the "__init" section annotation. Acked-by: Guan Xuetao Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/unicore32/kernel/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index 2fc2b1ba825e..46cb6c9de6c9 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -296,7 +296,7 @@ static int __init pci_common_init(void) } subsys_initcall(pci_common_init); -char * __devinit pcibios_setup(char *str) +char * __init pcibios_setup(char *str) { if (!strcmp(str, "debug")) { debug_pci = 1; -- GitLab From 15fa325bebbe11184a051ed64965164fca8c1df2 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:32 -0600 Subject: [PATCH 1854/5711] x86/PCI: adjust section annotations for pcibios_setup() Make pcibios_setup() consistently use the "__init" section annotation. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/x86/pci/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0ad990a20d4a..720e973fc34a 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -494,7 +494,7 @@ int __init pcibios_init(void) return 0; } -char * __devinit pcibios_setup(char *str) +char * __init pcibios_setup(char *str) { if (!strcmp(str, "off")) { pci_probe = 0; -- GitLab From 29e8d7bff2f52dd5464a9fb24ece608bbf8fd5ae Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:32:39 -0600 Subject: [PATCH 1855/5711] xtensa/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/xtensa/kernel/pci.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index eb30e356f5be..3a2cae4558b3 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -46,7 +46,6 @@ * pcibios_fixups * pcibios_align_resource * pcibios_fixup_bus - * pcibios_setup * pci_bus_add_device * pci_mmap_page_range */ @@ -206,11 +205,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) } } -char __init *pcibios_setup(char *str) -{ - return str; -} - void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ -- GitLab From 591e2ac424434ad1e9ee508ea021f37655b59eed Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 5 Jul 2012 14:46:07 +0900 Subject: [PATCH 1856/5711] ARM: shmobile: Use INTCA with sh7372 A3SM power domain Convert the sh7372 A3SM power domain code to allow waking up through INTCA and SYSC instead of only relying on SYSC for wakeups. This allows us to enter A3SM more or less regardless of the state of the rest of the system. Signed-off-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pm-sh7372.c | 57 +++++++++++++++--------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 44daaee9df93..9edd95f4beda 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -293,12 +293,6 @@ struct sh7372_pm_domain sh7372_a3sg = { #endif /* CONFIG_PM */ #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) -static int sh7372_do_idle_core_standby(unsigned long unused) -{ - cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ - return 0; -} - static void sh7372_set_reset_vector(unsigned long address) { /* set reset vector, translate 4k */ @@ -306,18 +300,6 @@ static void sh7372_set_reset_vector(unsigned long address) __raw_writel(0, APARMBAREA); } -static void sh7372_enter_core_standby(void) -{ - sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); - - /* enter sleep mode with SYSTBCR to 0x10 */ - __raw_writel(0x10, SYSTBCR); - cpu_suspend(0, sh7372_do_idle_core_standby); - __raw_writel(0, SYSTBCR); - - /* disable reset vector translation */ - __raw_writel(0, SBAR); -} #endif #ifdef CONFIG_SUSPEND @@ -460,6 +442,8 @@ static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2) static void sh7372_enter_a3sm_common(int pllc0_on) { + /* use INTCA together with SYSC for wakeup */ + sh7372_setup_sysc(1 << 0, 0); sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); sh7372_enter_sysc(pllc0_on, 1 << 12); } @@ -476,6 +460,24 @@ static void sh7372_enter_a4s_common(int pllc0_on) #endif #ifdef CONFIG_CPU_IDLE +static int sh7372_do_idle_core_standby(unsigned long unused) +{ + cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ + return 0; +} + +static void sh7372_enter_core_standby(void) +{ + sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); + + /* enter sleep mode with SYSTBCR to 0x10 */ + __raw_writel(0x10, SYSTBCR); + cpu_suspend(0, sh7372_do_idle_core_standby); + __raw_writel(0, SYSTBCR); + + /* disable reset vector translation */ + __raw_writel(0, SBAR); +} static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) { @@ -507,24 +509,21 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) /* check active clocks to determine potential wakeup sources */ if (sh7372_sysc_valid(&msk, &msk2)) { - /* convert INTC mask and sense to SYSC mask and sense */ - sh7372_setup_sysc(msk, msk2); - if (!console_suspend_enabled && sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { + /* convert INTC mask/sense to SYSC mask/sense */ + sh7372_setup_sysc(msk, msk2); + /* enter A4S sleep with PLLC0 off */ pr_debug("entering A4S\n"); sh7372_enter_a4s_common(0); - } else { - /* enter A3SM sleep with PLLC0 off */ - pr_debug("entering A3SM\n"); - sh7372_enter_a3sm_common(0); + return 0; } - } else { - /* default to Core Standby that supports all wakeup sources */ - pr_debug("entering Core Standby\n"); - sh7372_enter_core_standby(); } + + /* default to enter A3SM sleep with PLLC0 off */ + pr_debug("entering A3SM\n"); + sh7372_enter_a3sm_common(0); return 0; } -- GitLab From 3abd69d28b7ec7607bd6f559fe618bb7db815e1c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 5 Jul 2012 14:46:47 +0900 Subject: [PATCH 1857/5711] ARM: shmobile: sh7372 A3SM CPUIdle support Add CPUIdle support for the A3SM power domain on sh7372. With this in place we can turn off more of the SoC during run time and save power. Makes use of the recently introduced sh7372 INTCA A3SM power domain wakeup support. Signed-off-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pm-sh7372.c | 50 +++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 9edd95f4beda..a38be7f06d6a 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -300,9 +300,6 @@ static void sh7372_set_reset_vector(unsigned long address) __raw_writel(0, APARMBAREA); } -#endif - -#ifdef CONFIG_SUSPEND static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode) { if (pllc0_on) @@ -448,17 +445,6 @@ static void sh7372_enter_a3sm_common(int pllc0_on) sh7372_enter_sysc(pllc0_on, 1 << 12); } -static void sh7372_enter_a4s_common(int pllc0_on) -{ - sh7372_intca_suspend(); - memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); - sh7372_set_reset_vector(SMFRAM); - sh7372_enter_sysc(pllc0_on, 1 << 10); - sh7372_intca_resume(); -} - -#endif - #ifdef CONFIG_CPU_IDLE static int sh7372_do_idle_core_standby(unsigned long unused) { @@ -479,6 +465,16 @@ static void sh7372_enter_core_standby(void) __raw_writel(0, SBAR); } +static void sh7372_enter_a3sm_pll_on(void) +{ + sh7372_enter_a3sm_common(1); +} + +static void sh7372_enter_a3sm_pll_off(void) +{ + sh7372_enter_a3sm_common(0); +} + static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) { struct cpuidle_state *state = &drv->states[drv->state_count]; @@ -489,7 +485,24 @@ static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) state->target_residency = 20 + 10; state->flags = CPUIDLE_FLAG_TIME_VALID; shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; + drv->state_count++; + state = &drv->states[drv->state_count]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); + strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN); + state->exit_latency = 20; + state->target_residency = 30 + 20; + state->flags = CPUIDLE_FLAG_TIME_VALID; + shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on; + drv->state_count++; + + state = &drv->states[drv->state_count]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C4"); + strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN); + state->exit_latency = 120; + state->target_residency = 30 + 120; + state->flags = CPUIDLE_FLAG_TIME_VALID; + shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off; drv->state_count++; } @@ -502,6 +515,14 @@ static void sh7372_cpuidle_init(void) {} #endif #ifdef CONFIG_SUSPEND +static void sh7372_enter_a4s_common(int pllc0_on) +{ + sh7372_intca_suspend(); + memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); + sh7372_set_reset_vector(SMFRAM); + sh7372_enter_sysc(pllc0_on, 1 << 10); + sh7372_intca_resume(); +} static int sh7372_enter_suspend(suspend_state_t suspend_state) { @@ -562,6 +583,7 @@ static void sh7372_suspend_init(void) #else static void sh7372_suspend_init(void) {} #endif +#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ void __init sh7372_pm_init(void) { -- GitLab From db288c9c5f9db45610dab3940377625132b4af41 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 5 Jul 2012 15:20:00 -0600 Subject: [PATCH 1858/5711] PCI / PM: restore the original behavior of pci_set_power_state() Commit cc2893b6 (PCI: Ensure we re-enable devices on resume) addressed the problem with USB not being powered after resume on recent Lenovo machines, but it did that in a suboptimal way. Namely, it should have changed the relevant code paths only, which are pci_pm_resume_noirq() and pci_pm_restore_noirq() supposed to restore the device's power and standard configuration registers after system resume from suspend or hibernation. Instead, however, it modified pci_set_power_state() which is executed in several other situations too. That resulted in some undesirable effects, like attempting to change a device's power state in the same way multiple times in a row (up to as many as 4 times in a row in the snd_hda_intel driver). Fix the bug addressed by commit cc2893b6 in an alternative way, by forcibly powering up all devices in pci_pm_default_resume_early(), which is called by pci_pm_resume_noirq() and pci_pm_restore_noirq() to restore the device's power and standard configuration registers, and modifying pci_pm_runtime_resume() to avoid the forcible power-up if not necessary. Then, revert the changes made by commit cc2893b6 to make the confusion introduced by it go away. Acked-by: Matthew Garrett Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-driver.c | 14 ++++++++------ drivers/pci/pci.c | 19 ++++++++++++++++++- drivers/pci/pci.h | 1 + 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index ca2e4c79a588..1dd1d9dfa173 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -459,16 +459,17 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) return 0; } +#endif + +#ifdef CONFIG_PM_SLEEP + static void pci_pm_default_resume_early(struct pci_dev *pci_dev) { - pci_restore_standard_config(pci_dev); + pci_power_up(pci_dev); + pci_restore_state(pci_dev); pci_fixup_device(pci_fixup_resume_early, pci_dev); } -#endif - -#ifdef CONFIG_PM_SLEEP - /* * Default "suspend" method for devices that have no driver provided suspend, * or not even a driver at all (second part). @@ -1054,7 +1055,8 @@ static int pci_pm_runtime_resume(struct device *dev) if (!pm || !pm->runtime_resume) return -ENOSYS; - pci_pm_default_resume_early(pci_dev); + pci_restore_standard_config(pci_dev); + pci_fixup_device(pci_fixup_resume_early, pci_dev); __pci_enable_wake(pci_dev, PCI_D0, true, false); pci_fixup_device(pci_fixup_resume, pci_dev); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8effb9b23eec..acae2705e7f6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -672,6 +672,19 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state) } } +/** + * pci_power_up - Put the given device into D0 forcibly + * @dev: PCI device to power up + */ +void pci_power_up(struct pci_dev *dev) +{ + if (platform_pci_power_manageable(dev)) + platform_pci_set_power_state(dev, PCI_D0); + + pci_raw_set_power_state(dev, PCI_D0); + pci_update_current_state(dev, PCI_D0); +} + /** * pci_platform_power_transition - Use platform to change device power state * @dev: PCI device to handle. @@ -762,7 +775,7 @@ int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state) { int ret; - if (state < PCI_D0) + if (state <= PCI_D0) return -EINVAL; ret = pci_platform_power_transition(dev, state); /* Power off the bridge may power off the whole hierarchy */ @@ -804,6 +817,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) */ return 0; + /* Check if we're already there */ + if (dev->current_state == state) + return 0; + __pci_start_power_transition(dev, state); /* This device is quirked not to be put into D3, so diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5cd3dce7a245..331857855eb4 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -67,6 +67,7 @@ struct pci_platform_pm_ops { extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); +extern void pci_power_up(struct pci_dev *dev); extern void pci_disable_enabled_device(struct pci_dev *dev); extern int pci_finish_runtime_suspend(struct pci_dev *dev); extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); -- GitLab From b4c184e506a4cdb9b77bff4a1d39237581540b33 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 May 2012 08:17:47 -0300 Subject: [PATCH 1859/5711] [media] media: reorganize the main Kconfig items Change the main items to: Multimedia support ---> [ ] Cameras/video grabbers support [ ] Analog TV support [ ] Digital TV support [ ] AM/FM radio receivers/transmitters support [ ] Remote Controller support This provides an interface that is clearer to end users that are compiling the Kernel, and will allow the building system to automatically unselect drivers for unused functions. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 109 +++++++++++++++++++--------- drivers/media/common/tuners/Kconfig | 1 + drivers/media/dvb/frontends/Kconfig | 1 + drivers/media/rc/Kconfig | 29 ++++---- 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9575db429df4..323b2f042d85 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -6,20 +6,82 @@ menuconfig MEDIA_SUPPORT tristate "Multimedia support" depends on HAS_IOMEM help - If you want to use Video for Linux, DVB for Linux, or DAB adapters, + If you want to use Webcams, Video grabber devices and/or TV devices enable this option and other options below. + Additional info and docs are available on the web at + if MEDIA_SUPPORT comment "Multimedia core support" +# +# Multimedia support - automatically enable V4L2 and DVB core +# +config MEDIA_CAMERA_SUPPORT + bool "Cameras/video grabbers support" + ---help--- + Enable support for webcams and video grabbers. + + Say Y when you have a webcam or a video capture grabber board. + +config MEDIA_ANALOG_TV_SUPPORT + bool "Analog TV support" + ---help--- + Enable analog TV support. + + Say Y when you have a TV board with analog support or with a + hybrid analog/digital TV chipset. + + Note: There are several DVB cards that are based on chips that + support both analog and digital TV. Disabling this option + will disable support for them. + +config MEDIA_DIGITAL_TV_SUPPORT + bool "Digital TV support" + ---help--- + Enable digital TV support. + + Say Y when you have a board with digital support or a board with + hybrid digital TV and analog TV. + +config MEDIA_RADIO_SUPPORT + bool "AM/FM radio receivers/transmitters support" + ---help--- + Enable AM/FM radio support. + + Additional info and docs are available on the web at + + + Say Y when you have a board with radio support. + + Note: There are several TV cards that are based on chips that + support radio reception. Disabling this option will + disable support for them. + +menuconfig MEDIA_RC_SUPPORT + bool "Remote Controller support" + depends on INPUT + ---help--- + Enable support for Remote Controllers on Linux. This is + needed in order to support several video capture adapters, + standalone IR receivers/transmitters, and RF receivers. + + Enable this option if you have a video capture board even + if you don't need IR, as otherwise, you may not be able to + compile the driver for your adapter. + + Say Y when you have a TV or an IR device. + # # Media controller +# Selectable only for webcam/grabbers, as other drivers don't use it # config MEDIA_CONTROLLER bool "Media Controller API (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on MEDIA_CAMERA_SUPPORT ---help--- Enable the media controller API used to query media devices internal topology and configure it dynamically. @@ -27,26 +89,15 @@ config MEDIA_CONTROLLER This API is mostly used by camera interfaces in embedded platforms. # -# V4L core and enabled API's +# Video4Linux support +# Only enables if one of the V4L2 types (ATV, webcam, radio) is selected # config VIDEO_DEV - tristate "Video For Linux" - ---help--- - V4L core support for video capture and overlay devices, webcams and - AM/FM radio cards. - - This kernel includes support for the new Video for Linux Two API, - (V4L2). - - Additional info and docs are available on the web at - - - Documentation for V4L2 is also available on the web at - . - - To compile this driver as a module, choose M here: the - module will be called videodev. + tristate + depends on MEDIA_SUPPORT + depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT + default y config VIDEO_V4L2_COMMON tristate @@ -64,25 +115,15 @@ config VIDEO_V4L2_SUBDEV_API # # DVB Core +# Only enables if one of DTV is selected # config DVB_CORE - tristate "DVB for Linux" + tristate + depends on MEDIA_SUPPORT + depends on MEDIA_DIGITAL_TV_SUPPORT + default y select CRC32 - help - DVB core utility functions for device handling, software fallbacks etc. - - Enable this if you own a DVB/ATSC adapter and want to use it or if - you compile Linux for a digital SetTopBox. - - Say Y when you have a DVB or an ATSC card and want to use it. - - API specs and user tools are available from . - - Please report problems regarding this support to the LinuxDVB - mailing list. - - If unsure say N. config DVB_NET bool "DVB Network Support" @@ -101,8 +142,6 @@ config VIDEO_MEDIA tristate default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV) -comment "Multimedia drivers" - source "drivers/media/common/Kconfig" source "drivers/media/rc/Kconfig" diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index bbf4945149a9..16ee1a45e820 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -2,6 +2,7 @@ config MEDIA_ATTACH bool "Load and attach frontend and tuner driver modules as needed" depends on VIDEO_MEDIA depends on MODULES + default y if !EXPERT help Remove the static dependency of DVB card drivers on all frontend modules for all possible card variants. Instead, diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 2d4f1b6adc69..a08c2152d0ee 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -1,6 +1,7 @@ config DVB_FE_CUSTOMISE bool "Customise the frontend modules to build" depends on DVB_CORE + depends on EXPERT default y if EXPERT help This allows the user to select/deselect frontend drivers for their diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index f97eeb870455..d2655f103faa 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -1,21 +1,12 @@ -menuconfig RC_CORE - tristate "Remote Controller adapters" +config RC_CORE + tristate + depends on MEDIA_RC_SUPPORT depends on INPUT - default INPUT - ---help--- - Enable support for Remote Controllers on Linux. This is - needed in order to support several video capture adapters, - standalone IR receivers/transmitters, and RF receivers. - - Enable this option if you have a video capture board even - if you don't need IR, as otherwise, you may not be able to - compile the driver for your adapter. - -if RC_CORE + default y config LIRC - tristate - default y + tristate "LIRC interface driver" + depends on RC_CORE ---help--- Enable this option to build the Linux Infrared Remote @@ -109,6 +100,12 @@ config IR_MCE_KBD_DECODER Windows Media Center Edition, which you would like to use with a raw IR receiver in your system. +menuconfig RC_DEVICES + bool "Remote Controller devices" + depends on RC_CORE + +if RC_DEVICES + config IR_LIRC_CODEC tristate "Enable IR to LIRC bridge" depends on RC_CORE @@ -276,4 +273,4 @@ config IR_GPIO_CIR To compile this driver as a module, choose M here: the module will be called gpio-ir-recv. -endif #RC_CORE +endif #RC_DEVICES -- GitLab From 8cfd9dccf2693774d28c2d4ea7b2a7301c99d190 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 May 2012 08:17:48 -0300 Subject: [PATCH 1860/5711] [media] media: Remove VIDEO_MEDIA Kconfig option In the past, it was possible to have either DVB or V4L2 core as module and the other as builtin. Such config never make much sense, and created several issues in order to make the Kconfig dependency to work, as all drivers that depend on both (most TV drivers) would need to be compiled as 'm'. Due to that, the VIDEO_MEDIA config option were added. Instead of such weird approach, let's just use the MEDIA_SUPPORT =y or =m to select if the media subsystem core will be either builtin or module, simplifying the building system logic. Also, fix the tuners configuration, by enabling them only if a tuner is required. So, if just webcam/grabbers support is selected, no tuner option will be selected. Also, if only digital TV is selected, no analog tuner support is selected. That removes the need of using EXPERT customise options, when analog TV is not selected. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 4 -- drivers/media/common/tuners/Kconfig | 63 +++++++++++++++-------------- drivers/media/video/pvrusb2/Kconfig | 1 - 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 323b2f042d85..6d10ccb692a9 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -138,10 +138,6 @@ config DVB_NET You may want to disable the network support on embedded devices. If unsure say Y. -config VIDEO_MEDIA - tristate - default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV) - source "drivers/media/common/Kconfig" source "drivers/media/rc/Kconfig" diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 16ee1a45e820..94c6ff7a5da3 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -1,6 +1,6 @@ config MEDIA_ATTACH bool "Load and attach frontend and tuner driver modules as needed" - depends on VIDEO_MEDIA + depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT depends on MODULES default y if !EXPERT help @@ -20,15 +20,15 @@ config MEDIA_ATTACH config MEDIA_TUNER tristate - default VIDEO_MEDIA && I2C - depends on VIDEO_MEDIA && I2C + depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C + default y select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL - select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL + select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE @@ -48,10 +48,11 @@ config MEDIA_TUNER_CUSTOMISE menu "Customize TV tuners" visible if MEDIA_TUNER_CUSTOMISE + depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C select MEDIA_TUNER_TDA9887 default m if MEDIA_TUNER_CUSTOMISE help @@ -59,7 +60,7 @@ config MEDIA_TUNER_SIMPLE config MEDIA_TUNER_TDA8290 tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 default m if MEDIA_TUNER_CUSTOMISE @@ -68,21 +69,21 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for Philips TDA9885/6/7 @@ -90,7 +91,7 @@ config MEDIA_TUNER_TDA9887 config MEDIA_TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C depends on EXPERIMENTAL default m if MEDIA_TUNER_CUSTOMISE help @@ -98,63 +99,63 @@ config MEDIA_TUNER_TEA5761 config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2063 tristate "Microtune MT2063 silicon IF tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon IF tuner MT2063 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the xc2028/xc3028 tuners. config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner XC5000 from Xceive. @@ -163,7 +164,7 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_XC4000 tristate "Xceive XC4000 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner XC4000 from Xceive. @@ -172,70 +173,70 @@ config MEDIA_TUNER_XC4000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Say Y here to support the Freescale MC44S803 based tuners config MEDIA_TUNER_MAX2165 tristate "Maxim MAX2165 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MAX2165 from Maxim. config MEDIA_TUNER_TDA18218 tristate "NXP TDA18218 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help NXP TDA18218 silicon tuner driver. config MEDIA_TUNER_FC0011 tristate "Fitipower FC0011 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Fitipower FC0011 silicon tuner driver. config MEDIA_TUNER_FC0012 tristate "Fitipower FC0012 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Fitipower FC0012 silicon tuner driver. config MEDIA_TUNER_FC0013 tristate "Fitipower FC0013 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Fitipower FC0013 silicon tuner driver. config MEDIA_TUNER_TDA18212 tristate "NXP TDA18212 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help NXP TDA18212 silicon tuner driver. config MEDIA_TUNER_TUA9001 tristate "Infineon TUA 9001 silicon tuner" - depends on VIDEO_MEDIA && I2C + depends on MEDIA_SUPPORT && I2C default m if MEDIA_TUNER_CUSTOMISE help Infineon TUA 9001 silicon tuner driver. diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index f9b6001e1dd7..25e412ecad2c 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -1,7 +1,6 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" depends on VIDEO_V4L2 && I2C - depends on VIDEO_MEDIA # Avoids pvrusb = Y / DVB = M select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X -- GitLab From 724f4a321ff5f6d4dd6176e95063d05a85520736 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 May 2012 08:17:49 -0300 Subject: [PATCH 1861/5711] [media] media: only show V4L devices based on device type selection After this patch, the MEDIA*_SUPPORT will be used as a filter, exposing only devices that are pertinent to one of the 3 V4L types: webcam/grabber, radio, analog TV. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/Kconfig | 1 + drivers/media/video/Kconfig | 76 ++++++++++++++++++++++-------- drivers/media/video/m5mols/Kconfig | 1 + drivers/media/video/smiapp/Kconfig | 1 + 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index c257da13d766..24ce5a47f955 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -5,6 +5,7 @@ menuconfig RADIO_ADAPTERS bool "Radio Adapters" depends on VIDEO_V4L2 + depends on MEDIA_RADIO_SUPPORT default y ---help--- Say Y here to enable selecting AM/FM radio adapters. diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 99937c94d7df..da363c44fab2 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -5,7 +5,7 @@ config VIDEO_V4L2 tristate depends on VIDEO_DEV && VIDEO_V4L2_COMMON - default VIDEO_DEV && VIDEO_V4L2_COMMON + default y config VIDEOBUF_GEN tristate @@ -73,6 +73,7 @@ config VIDEOBUF2_DMA_SG menuconfig VIDEO_CAPTURE_DRIVERS bool "Video capture adapters" depends on VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT default y ---help--- Say Y here to enable selecting the video adapters for @@ -478,6 +479,7 @@ config VIDEO_SMIAPP_PLL config VIDEO_OV7670 tristate "OmniVision OV7670 sensor support" depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a Video4Linux2 sensor-level driver for the OmniVision OV7670 VGA camera. It currently only works with the M88ALP01 @@ -486,6 +488,7 @@ config VIDEO_OV7670 config VIDEO_VS6624 tristate "ST VS6624 sensor support" depends on VIDEO_V4L2 && I2C + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a Video4Linux2 sensor-level driver for the ST VS6624 camera. @@ -496,6 +499,7 @@ config VIDEO_VS6624 config VIDEO_MT9M032 tristate "MT9M032 camera sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT select VIDEO_APTINA_PLL ---help--- This driver supports MT9M032 camera sensors from Aptina, monochrome @@ -504,6 +508,7 @@ config VIDEO_MT9M032 config VIDEO_MT9P031 tristate "Aptina MT9P031 support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT select VIDEO_APTINA_PLL ---help--- This is a Video4Linux2 sensor-level driver for the Aptina @@ -512,6 +517,7 @@ config VIDEO_MT9P031 config VIDEO_MT9T001 tristate "Aptina MT9T001 support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a Video4Linux2 sensor-level driver for the Aptina (Micron) mt0t001 3 Mpixel camera. @@ -519,6 +525,7 @@ config VIDEO_MT9T001 config VIDEO_MT9V011 tristate "Micron mt9v011 sensor support" depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a Video4Linux2 sensor-level driver for the Micron mt0v011 1.3 Mpixel camera. It currently only works with the @@ -527,6 +534,7 @@ config VIDEO_MT9V011 config VIDEO_MT9V032 tristate "Micron MT9V032 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a Video4Linux2 sensor-level driver for the Micron MT9V032 752x480 CMOS sensor. @@ -534,6 +542,7 @@ config VIDEO_MT9V032 config VIDEO_TCM825X tristate "TCM825x camera sensor support" depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a driver for the Toshiba TCM825x VGA camera sensor. It is used for example in Nokia N800. @@ -541,12 +550,14 @@ config VIDEO_TCM825X config VIDEO_SR030PC30 tristate "Siliconfile SR030PC30 sensor support" depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT ---help--- This driver supports SR030PC30 VGA camera from Siliconfile config VIDEO_NOON010PC30 tristate "Siliconfile NOON010PC30 sensor support" depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT ---help--- This driver supports NOON010PC30 CIF camera from Siliconfile @@ -554,6 +565,7 @@ source "drivers/media/video/m5mols/Kconfig" config VIDEO_S5K6AA tristate "Samsung S5K6AAFX sensor support" + depends on MEDIA_CAMERA_SUPPORT depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API ---help--- This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M @@ -566,6 +578,7 @@ comment "Flash devices" config VIDEO_ADP1653 tristate "ADP1653 flash support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a driver for the ADP1653 flash controller. It is used for example in Nokia N900. @@ -573,6 +586,7 @@ config VIDEO_ADP1653 config VIDEO_AS3645A tristate "AS3645A flash driver support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on MEDIA_CAMERA_SUPPORT ---help--- This is a driver for the AS3645A and LM3555 flash controllers. It has build in control for flash, torch and indicator LEDs. @@ -647,30 +661,14 @@ menuconfig V4L_USB_DRIVERS depends on USB default y -if V4L_USB_DRIVERS +if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT -source "drivers/media/video/au0828/Kconfig" + comment "Webcam devices" source "drivers/media/video/uvc/Kconfig" source "drivers/media/video/gspca/Kconfig" -source "drivers/media/video/pvrusb2/Kconfig" - -source "drivers/media/video/hdpvr/Kconfig" - -source "drivers/media/video/em28xx/Kconfig" - -source "drivers/media/video/tlg2300/Kconfig" - -source "drivers/media/video/cx231xx/Kconfig" - -source "drivers/media/video/tm6000/Kconfig" - -source "drivers/media/video/usbvision/Kconfig" - -source "drivers/media/video/sn9c102/Kconfig" - source "drivers/media/video/pwc/Kconfig" source "drivers/media/video/cpia2/Kconfig" @@ -711,15 +709,46 @@ config USB_S2255 Say Y here if you want support for the Sensoray 2255 USB device. This driver can be compiled as a module, called s2255drv. +source "drivers/media/video/sn9c102/Kconfig" + +endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT + +if V4L_USB_DRIVERS + + comment "Webcam and/or TV USB devices" + +source "drivers/media/video/em28xx/Kconfig" + +endif + +if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT + + comment "TV USB devices" + +source "drivers/media/video/au0828/Kconfig" + +source "drivers/media/video/pvrusb2/Kconfig" + +source "drivers/media/video/hdpvr/Kconfig" + +source "drivers/media/video/tlg2300/Kconfig" + +source "drivers/media/video/cx231xx/Kconfig" + +source "drivers/media/video/tm6000/Kconfig" + +source "drivers/media/video/usbvision/Kconfig" + endif # V4L_USB_DRIVERS # -# PCI drivers configuration +# PCI drivers configuration - No devices here are for webcams # menuconfig V4L_PCI_DRIVERS bool "V4L PCI(e) devices" depends on PCI + depends on MEDIA_ANALOG_TV_SUPPORT default y ---help--- Say Y here to enable support for these PCI(e) drivers. @@ -814,11 +843,13 @@ endif # V4L_PCI_DRIVERS # # ISA & parallel port drivers configuration +# All devices here are webcam or grabber devices # menuconfig V4L_ISA_PARPORT_DRIVERS bool "V4L ISA and parallel port devices" depends on ISA || PARPORT + depends on MEDIA_CAMERA_SUPPORT default n ---help--- Say Y here to enable support for these ISA and parallel port drivers. @@ -871,8 +902,13 @@ config VIDEO_W9966 endif # V4L_ISA_PARPORT_DRIVERS +# +# Platform drivers +# All drivers here are currently for webcam support + menuconfig V4L_PLATFORM_DRIVERS bool "V4L platform devices" + depends on MEDIA_CAMERA_SUPPORT default n ---help--- Say Y here to enable support for platform-specific V4L drivers. diff --git a/drivers/media/video/m5mols/Kconfig b/drivers/media/video/m5mols/Kconfig index 302dc3d70193..dc8c2505907e 100644 --- a/drivers/media/video/m5mols/Kconfig +++ b/drivers/media/video/m5mols/Kconfig @@ -1,5 +1,6 @@ config VIDEO_M5MOLS tristate "Fujitsu M-5MOLS 8MP sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT ---help--- This driver supports Fujitsu M-5MOLS camera sensor with ISP diff --git a/drivers/media/video/smiapp/Kconfig b/drivers/media/video/smiapp/Kconfig index fb99ff18be07..3149cda1d0db 100644 --- a/drivers/media/video/smiapp/Kconfig +++ b/drivers/media/video/smiapp/Kconfig @@ -1,6 +1,7 @@ config VIDEO_SMIAPP tristate "SMIA++/SMIA sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAVE_CLK + depends on MEDIA_CAMERA_SUPPORT select VIDEO_SMIAPP_PLL ---help--- This is a generic driver for SMIA++/SMIA camera modules. -- GitLab From b5ab5e24e960b9f780a4cc96815cfd4b0d412720 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 30 May 2012 22:01:25 +0300 Subject: [PATCH 1862/5711] remoteproc: maintain a generic child device for each rproc For each registered rproc, maintain a generic remoteproc device whose parent is the low level platform-specific device (commonly a pdev, but it may certainly be any other type of device too). With this in hand, the resulting device hierarchy might then look like: omap-rproc.0 | - remoteproc0 <---- new ! | - virtio0 | - virtio1 | - rpmsg0 | - rpmsg1 | - rpmsg2 Where: - omap-rproc.0 is the low level device that's bound to the driver which invokes rproc_register() - remoteproc0 is the result of this patch, and will be added by the remoteproc framework when rproc_register() is invoked - virtio0 and virtio1 are vdevs that are registered by remoteproc when it realizes that they are supported by the firmware of the physical remote processor represented by omap-rproc.0 - rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg channels, and are registerd by the rpmsg bus when it gets notified about their existence Technically, this patch: - changes 'struct rproc' to contain this generic remoteproc.x device - creates a new "remoteproc" type, to which this new generic remoteproc.x device belong to. - adds a super simple enumeration method for the indices of the remoteproc.x devices - updates all dev_* messaging to use the generic remoteproc.x device instead of the low level platform-specific device - updates all dma_* allocations to use the parent of remoteproc.x (where the platform-specific memory pools, most commonly CMA, are to be found) Adding this generic device has several merits: - we can now add remoteproc runtime PM support simply by hooking onto the new "remoteproc" type - all remoteproc log messages will now carry a common name prefix instead of having a platform-specific one - having a device as part of the rproc struct makes it possible to simplify refcounting (see subsequent patch) Thanks to Stephen Boyd for suggesting and discussing these ideas in one of the remoteproc review threads and to Fernando Guzman Lugo for trying them out with the (upcoming) runtime PM support for remoteproc. Cc: Fernando Guzman Lugo Reviewed-by: Stephen Boyd Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/omap_remoteproc.c | 17 +-- drivers/remoteproc/remoteproc_core.c | 135 ++++++++++++++++-------- drivers/remoteproc/remoteproc_debugfs.c | 4 +- drivers/remoteproc/remoteproc_virtio.c | 13 +-- drivers/rpmsg/virtio_rpmsg_bus.c | 3 +- include/linux/remoteproc.h | 6 +- 6 files changed, 117 insertions(+), 61 deletions(-) diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 69425c4e86f3..b5e6d2981741 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -66,7 +66,7 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, { mbox_msg_t msg = (mbox_msg_t) data; struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); - struct device *dev = oproc->rproc->dev; + struct device *dev = oproc->rproc->dev.parent; const char *name = oproc->rproc->name; dev_dbg(dev, "mbox msg: 0x%x\n", msg); @@ -92,12 +92,13 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, static void omap_rproc_kick(struct rproc *rproc, int vqid) { struct omap_rproc *oproc = rproc->priv; + struct device *dev = rproc->dev.parent; int ret; /* send the index of the triggered virtqueue in the mailbox payload */ ret = omap_mbox_msg_send(oproc->mbox, vqid); if (ret) - dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret); + dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret); } /* @@ -110,7 +111,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) static int omap_rproc_start(struct rproc *rproc) { struct omap_rproc *oproc = rproc->priv; - struct platform_device *pdev = to_platform_device(rproc->dev); + struct device *dev = rproc->dev.parent; + struct platform_device *pdev = to_platform_device(dev); struct omap_rproc_pdata *pdata = pdev->dev.platform_data; int ret; @@ -120,7 +122,7 @@ static int omap_rproc_start(struct rproc *rproc) oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); if (IS_ERR(oproc->mbox)) { ret = PTR_ERR(oproc->mbox); - dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); + dev_err(dev, "omap_mbox_get failed: %d\n", ret); return ret; } @@ -133,13 +135,13 @@ static int omap_rproc_start(struct rproc *rproc) */ ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); if (ret) { - dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); + dev_err(dev, "omap_mbox_get failed: %d\n", ret); goto put_mbox; } ret = pdata->device_enable(pdev); if (ret) { - dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret); + dev_err(dev, "omap_device_enable failed: %d\n", ret); goto put_mbox; } @@ -153,7 +155,8 @@ put_mbox: /* power off the remote processor */ static int omap_rproc_stop(struct rproc *rproc) { - struct platform_device *pdev = to_platform_device(rproc->dev); + struct device *dev = rproc->dev.parent; + struct platform_device *pdev = to_platform_device(dev); struct omap_rproc_pdata *pdata = pdev->dev.platform_data; struct omap_rproc *oproc = rproc->priv; int ret; diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 288d4175bbf6..25f937843836 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,9 @@ typedef int (*rproc_handle_resources_t)(struct rproc *rproc, struct resource_table *table, int len); typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); +/* Unique indices for remoteproc devices */ +static DEFINE_IDA(rproc_dev_index); + /* * This is the IOMMU fault handler we register with the IOMMU API * (when relevant; not all remote processors access memory through @@ -92,7 +96,7 @@ static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, static int rproc_enable_iommu(struct rproc *rproc) { struct iommu_domain *domain; - struct device *dev = rproc->dev; + struct device *dev = rproc->dev.parent; int ret; /* @@ -137,7 +141,7 @@ free_domain: static void rproc_disable_iommu(struct rproc *rproc) { struct iommu_domain *domain = rproc->domain; - struct device *dev = rproc->dev; + struct device *dev = rproc->dev.parent; if (!domain) return; @@ -217,7 +221,7 @@ static void *rproc_da_to_va(struct rproc *rproc, u64 da, int len) static int rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct elf32_hdr *ehdr; struct elf32_phdr *phdr; int i, ret = 0; @@ -282,7 +286,7 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) { struct rproc *rproc = rvdev->rproc; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct rproc_vring *rvring = &rvdev->vring[i]; dma_addr_t dma; void *va; @@ -301,9 +305,9 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) * this call will also configure the IOMMU for us * TODO: let the rproc know the da of this vring */ - va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); + va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); if (!va) { - dev_err(dev, "dma_alloc_coherent failed\n"); + dev_err(dev->parent, "dma_alloc_coherent failed\n"); return -EINVAL; } @@ -316,7 +320,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) ret = idr_get_new(&rproc->notifyids, rvring, ¬ifyid); if (ret) { dev_err(dev, "idr_get_new failed: %d\n", ret); - dma_free_coherent(dev, size, va, dma); + dma_free_coherent(dev->parent, size, va, dma); return ret; } @@ -334,7 +338,7 @@ static int rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) { struct rproc *rproc = rvdev->rproc; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; struct rproc_vring *rvring = &rvdev->vring[i]; @@ -366,7 +370,7 @@ void rproc_free_vring(struct rproc_vring *rvring) int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); struct rproc *rproc = rvring->rvdev->rproc; - dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma); + dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma); idr_remove(&rproc->notifyids, rvring->notifyid); } @@ -400,14 +404,14 @@ void rproc_free_vring(struct rproc_vring *rvring) static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, int avail) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct rproc_vdev *rvdev; int i, ret; /* make sure resource isn't truncated */ if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) + rsc->config_len > avail) { - dev_err(rproc->dev, "vdev rsc is truncated\n"); + dev_err(dev, "vdev rsc is truncated\n"); return -EINVAL; } @@ -476,12 +480,12 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, int avail) { struct rproc_mem_entry *trace; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; void *ptr; char name[15]; if (sizeof(*rsc) > avail) { - dev_err(rproc->dev, "trace rsc is truncated\n"); + dev_err(dev, "trace rsc is truncated\n"); return -EINVAL; } @@ -558,6 +562,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, int avail) { struct rproc_mem_entry *mapping; + struct device *dev = &rproc->dev; int ret; /* no point in handling this resource without a valid iommu domain */ @@ -565,25 +570,25 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, return -EINVAL; if (sizeof(*rsc) > avail) { - dev_err(rproc->dev, "devmem rsc is truncated\n"); + dev_err(dev, "devmem rsc is truncated\n"); return -EINVAL; } /* make sure reserved bytes are zeroes */ if (rsc->reserved) { - dev_err(rproc->dev, "devmem rsc has non zero reserved bytes\n"); + dev_err(dev, "devmem rsc has non zero reserved bytes\n"); return -EINVAL; } mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); if (!mapping) { - dev_err(rproc->dev, "kzalloc mapping failed\n"); + dev_err(dev, "kzalloc mapping failed\n"); return -ENOMEM; } ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags); if (ret) { - dev_err(rproc->dev, "failed to map devmem: %d\n", ret); + dev_err(dev, "failed to map devmem: %d\n", ret); goto out; } @@ -598,7 +603,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, mapping->len = rsc->len; list_add_tail(&mapping->node, &rproc->mappings); - dev_dbg(rproc->dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", + dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", rsc->pa, rsc->da, rsc->len); return 0; @@ -630,13 +635,13 @@ static int rproc_handle_carveout(struct rproc *rproc, struct fw_rsc_carveout *rsc, int avail) { struct rproc_mem_entry *carveout, *mapping; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; dma_addr_t dma; void *va; int ret; if (sizeof(*rsc) > avail) { - dev_err(rproc->dev, "carveout rsc is truncated\n"); + dev_err(dev, "carveout rsc is truncated\n"); return -EINVAL; } @@ -662,9 +667,9 @@ static int rproc_handle_carveout(struct rproc *rproc, goto free_mapping; } - va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL); + va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); if (!va) { - dev_err(dev, "failed to dma alloc carveout: %d\n", rsc->len); + dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len); ret = -ENOMEM; goto free_carv; } @@ -735,7 +740,7 @@ static int rproc_handle_carveout(struct rproc *rproc, return 0; dma_free: - dma_free_coherent(dev, rsc->len, va, dma); + dma_free_coherent(dev->parent, rsc->len, va, dma); free_carv: kfree(carveout); free_mapping: @@ -758,7 +763,7 @@ static rproc_handle_resource_t rproc_handle_rsc[] = { static int rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; rproc_handle_resource_t handler; int ret = 0, i; @@ -797,7 +802,7 @@ rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len static int rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int len) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; int ret = 0, i; for (i = 0; i < table->num; i++) { @@ -850,7 +855,7 @@ rproc_find_rsc_table(struct rproc *rproc, const u8 *elf_data, size_t len, struct elf32_hdr *ehdr; struct elf32_shdr *shdr; const char *name_table; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct resource_table *table = NULL; int i; @@ -916,7 +921,7 @@ rproc_find_rsc_table(struct rproc *rproc, const u8 *elf_data, size_t len, static void rproc_resource_cleanup(struct rproc *rproc) { struct rproc_mem_entry *entry, *tmp; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; /* clean up debugfs trace entries */ list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { @@ -928,7 +933,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) /* clean up carveout allocations */ list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { - dma_free_coherent(dev, entry->len, entry->va, entry->dma); + dma_free_coherent(dev->parent, entry->len, entry->va, entry->dma); list_del(&entry->node); kfree(entry); } @@ -953,7 +958,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) { const char *name = rproc->firmware; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct elf32_hdr *ehdr; char class; @@ -1014,7 +1019,7 @@ static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) */ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; const char *name = rproc->firmware; struct elf32_hdr *ehdr; struct resource_table *table; @@ -1138,7 +1143,7 @@ int rproc_boot(struct rproc *rproc) return -EINVAL; } - dev = rproc->dev; + dev = &rproc->dev; ret = mutex_lock_interruptible(&rproc->lock); if (ret) { @@ -1154,7 +1159,7 @@ int rproc_boot(struct rproc *rproc) } /* prevent underlying implementation from being removed */ - if (!try_module_get(dev->driver->owner)) { + if (!try_module_get(dev->parent->driver->owner)) { dev_err(dev, "%s: can't get owner\n", __func__); ret = -EINVAL; goto unlock_mutex; @@ -1181,7 +1186,7 @@ int rproc_boot(struct rproc *rproc) downref_rproc: if (ret) { - module_put(dev->driver->owner); + module_put(dev->parent->driver->owner); atomic_dec(&rproc->power); } unlock_mutex: @@ -1215,7 +1220,7 @@ EXPORT_SYMBOL(rproc_boot); */ void rproc_shutdown(struct rproc *rproc) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; int ret; ret = mutex_lock_interruptible(&rproc->lock); @@ -1248,7 +1253,7 @@ void rproc_shutdown(struct rproc *rproc) out: mutex_unlock(&rproc->lock); if (!ret) - module_put(dev->driver->owner); + module_put(dev->parent->driver->owner); } EXPORT_SYMBOL(rproc_shutdown); @@ -1271,7 +1276,7 @@ void rproc_release(struct kref *kref) { struct rproc *rproc = container_of(kref, struct rproc, refcount); - dev_info(rproc->dev, "removing %s\n", rproc->name); + dev_info(&rproc->dev, "removing %s\n", rproc->name); rproc_delete_debug_dir(rproc); @@ -1403,13 +1408,17 @@ EXPORT_SYMBOL(rproc_put); */ int rproc_register(struct rproc *rproc) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; int ret = 0; + ret = device_add(dev); + if (ret < 0) + return ret; + /* expose to rproc_get_by_name users */ klist_add_tail(&rproc->node, &rprocs); - dev_info(rproc->dev, "%s is available\n", rproc->name); + dev_info(dev, "%s is available\n", rproc->name); dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n"); dev_info(dev, "THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.\n"); @@ -1441,6 +1450,33 @@ int rproc_register(struct rproc *rproc) } EXPORT_SYMBOL(rproc_register); +/** + * rproc_type_release() - release a remote processor instance + * @dev: the rproc's device + * + * This function should _never_ be called directly. + * + * It will be called by the driver core when no one holds a valid pointer + * to @dev anymore. + */ +static void rproc_type_release(struct device *dev) +{ + struct rproc *rproc = container_of(dev, struct rproc, dev); + + idr_remove_all(&rproc->notifyids); + idr_destroy(&rproc->notifyids); + + if (rproc->index >= 0) + ida_simple_remove(&rproc_dev_index, rproc->index); + + kfree(rproc); +} + +static struct device_type rproc_type = { + .name = "remoteproc", + .release = rproc_type_release, +}; + /** * rproc_alloc() - allocate a remote processor handle * @dev: the underlying device @@ -1479,12 +1515,25 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, return NULL; } - rproc->dev = dev; rproc->name = name; rproc->ops = ops; rproc->firmware = firmware; rproc->priv = &rproc[1]; + device_initialize(&rproc->dev); + rproc->dev.parent = dev; + rproc->dev.type = &rproc_type; + + /* Assign a unique device index and name */ + rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL); + if (rproc->index < 0) { + dev_err(dev, "ida_simple_get failed: %d\n", rproc->index); + put_device(&rproc->dev); + return NULL; + } + + dev_set_name(&rproc->dev, "remoteproc%d", rproc->index); + atomic_set(&rproc->power, 0); kref_init(&rproc->refcount); @@ -1516,10 +1565,7 @@ EXPORT_SYMBOL(rproc_alloc); */ void rproc_free(struct rproc *rproc) { - idr_remove_all(&rproc->notifyids); - idr_destroy(&rproc->notifyids); - - kfree(rproc); + put_device(&rproc->dev); } EXPORT_SYMBOL(rproc_free); @@ -1560,6 +1606,8 @@ int rproc_unregister(struct rproc *rproc) /* the rproc is downref'ed as soon as it's removed from the klist */ klist_del(&rproc->node); + device_del(&rproc->dev); + /* the rproc will only be released after its refcount drops to zero */ kref_put(&rproc->refcount, rproc_release); @@ -1570,6 +1618,7 @@ EXPORT_SYMBOL(rproc_unregister); static int __init remoteproc_init(void) { rproc_init_debugfs(); + return 0; } module_init(remoteproc_init); diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 85d31a69e117..03833850f214 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -124,7 +124,7 @@ struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, tfile = debugfs_create_file(name, 0400, rproc->dbg_dir, trace, &trace_rproc_ops); if (!tfile) { - dev_err(rproc->dev, "failed to create debugfs trace entry\n"); + dev_err(&rproc->dev, "failed to create debugfs trace entry\n"); return NULL; } @@ -141,7 +141,7 @@ void rproc_delete_debug_dir(struct rproc *rproc) void rproc_create_debug_dir(struct rproc *rproc) { - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; if (!rproc_dbg) return; diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 26a7144e7f3b..b6621831a58a 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -36,7 +36,7 @@ static void rproc_virtio_notify(struct virtqueue *vq) struct rproc *rproc = rvring->rvdev->rproc; int notifyid = rvring->notifyid; - dev_dbg(rproc->dev, "kicking vq index: %d\n", notifyid); + dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); rproc->ops->kick(rproc, notifyid); } @@ -57,7 +57,7 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) { struct rproc_vring *rvring; - dev_dbg(rproc->dev, "vq index %d is interrupted\n", notifyid); + dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid); rvring = idr_find(&rproc->notifyids, notifyid); if (!rvring || !rvring->vq) @@ -74,6 +74,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct rproc *rproc = vdev_to_rproc(vdev); + struct device *dev = &rproc->dev; struct rproc_vring *rvring; struct virtqueue *vq; void *addr; @@ -95,7 +96,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, size = vring_size(len, rvring->align); memset(addr, 0, size); - dev_dbg(rproc->dev, "vring%d: va %p qsz %d notifyid %d\n", + dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n", id, addr, len, rvring->notifyid); /* @@ -105,7 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr, rproc_virtio_notify, callback, name); if (!vq) { - dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); + dev_err(dev, "vring_new_virtqueue %s failed\n", name); rproc_free_vring(rvring); return ERR_PTR(-ENOMEM); } @@ -152,7 +153,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, /* now that the vqs are all set, boot the remote processor */ ret = rproc_boot(rproc); if (ret) { - dev_err(rproc->dev, "rproc_boot() failed %d\n", ret); + dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret); goto error; } @@ -254,7 +255,7 @@ static void rproc_vdev_release(struct device *dev) int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) { struct rproc *rproc = rvdev->rproc; - struct device *dev = rproc->dev; + struct device *dev = &rproc->dev; struct virtio_device *vdev = &rvdev->vdev; int ret; diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 75506ec2840e..691e52ec48d9 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -911,7 +911,8 @@ static int rpmsg_probe(struct virtio_device *vdev) vrp->svq = vqs[1]; /* allocate coherent memory for the buffers */ - bufs_va = dma_alloc_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, + bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, + RPMSG_TOTAL_BUF_SPACE, &vrp->bufs_dma, GFP_KERNEL); if (!bufs_va) goto vqs_del; diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index f1ffabb978d3..7f806dcf5278 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -369,7 +369,7 @@ enum rproc_state { * @firmware: name of firmware file to be loaded * @priv: private data which belongs to the platform-specific rproc module * @ops: platform-specific start/stop rproc handlers - * @dev: underlying device + * @dev: virtual device for refcounting and common remoteproc behavior * @refcount: refcount of users that have a valid pointer to this rproc * @power: refcount of users who need this rproc powered up * @state: state of the device @@ -383,6 +383,7 @@ enum rproc_state { * @bootaddr: address of first instruction to boot rproc with (optional) * @rvdevs: list of remote virtio devices * @notifyids: idr for dynamically assigning rproc-wide unique notify ids + * @index: index of this rproc device */ struct rproc { struct klist_node node; @@ -391,7 +392,7 @@ struct rproc { const char *firmware; void *priv; const struct rproc_ops *ops; - struct device *dev; + struct device dev; struct kref refcount; atomic_t power; unsigned int state; @@ -405,6 +406,7 @@ struct rproc { u32 bootaddr; struct list_head rvdevs; struct idr notifyids; + int index; }; /* we currently support only two vrings per rvdev */ -- GitLab From 7183a2a799b81490354973117ecd810c23cdc668 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 30 May 2012 22:02:24 +0300 Subject: [PATCH 1863/5711] remoteproc: remove the now-redundant kref Now that every rproc instance contains a device, we don't need a kref anymore to maintain the refcount of the rproc instances: that's what device are good with! This patch removes the now-redundant kref, and switches to {get, put}_device instead of kref_{get, put}. We also don't need the kref's release function anymore, and instead, we just utilize the class's release handler (which is now responsible for all memory de-allocations). Cc: Stephen Boyd Cc: Fernando Guzman Lugo Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 50 ++++++-------------------- drivers/remoteproc/remoteproc_virtio.c | 8 ++--- include/linux/remoteproc.h | 3 -- 3 files changed, 15 insertions(+), 46 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 25f937843836..aa713aade30e 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1257,42 +1257,12 @@ out: } EXPORT_SYMBOL(rproc_shutdown); -/** - * rproc_release() - completely deletes the existence of a remote processor - * @kref: the rproc's kref - * - * This function should _never_ be called directly. - * - * The only reasonable location to use it is as an argument when kref_put'ing - * @rproc's refcount. - * - * This way it will be called when no one holds a valid pointer to this @rproc - * anymore (and obviously after it is removed from the rprocs klist). - * - * Note: this function is not static because rproc_vdev_release() needs it when - * it decrements @rproc's refcount. - */ -void rproc_release(struct kref *kref) -{ - struct rproc *rproc = container_of(kref, struct rproc, refcount); - - dev_info(&rproc->dev, "removing %s\n", rproc->name); - - rproc_delete_debug_dir(rproc); - - /* - * At this point no one holds a reference to rproc anymore, - * so we can directly unroll rproc_alloc() - */ - rproc_free(rproc); -} - /* will be called when an rproc is added to the rprocs klist */ static void klist_rproc_get(struct klist_node *n) { struct rproc *rproc = container_of(n, struct rproc, node); - kref_get(&rproc->refcount); + get_device(&rproc->dev); } /* will be called when an rproc is removed from the rprocs klist */ @@ -1300,7 +1270,7 @@ static void klist_rproc_put(struct klist_node *n) { struct rproc *rproc = container_of(n, struct rproc, node); - kref_put(&rproc->refcount, rproc_release); + put_device(&rproc->dev); } static struct rproc *next_rproc(struct klist_iter *i) @@ -1342,7 +1312,7 @@ struct rproc *rproc_get_by_name(const char *name) klist_iter_init(&rprocs, &i); while ((rproc = next_rproc(&i)) != NULL) if (!strcmp(rproc->name, name)) { - kref_get(&rproc->refcount); + get_device(&rproc->dev); break; } klist_iter_exit(&i); @@ -1355,7 +1325,7 @@ struct rproc *rproc_get_by_name(const char *name) ret = rproc_boot(rproc); if (ret < 0) { - kref_put(&rproc->refcount, rproc_release); + put_device(&rproc->dev); return NULL; } @@ -1382,7 +1352,7 @@ void rproc_put(struct rproc *rproc) rproc_shutdown(rproc); /* downref rproc's refcount */ - kref_put(&rproc->refcount, rproc_release); + put_device(&rproc->dev); } EXPORT_SYMBOL(rproc_put); @@ -1463,6 +1433,10 @@ static void rproc_type_release(struct device *dev) { struct rproc *rproc = container_of(dev, struct rproc, dev); + dev_info(&rproc->dev, "releasing %s\n", rproc->name); + + rproc_delete_debug_dir(rproc); + idr_remove_all(&rproc->notifyids); idr_destroy(&rproc->notifyids); @@ -1536,8 +1510,6 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, atomic_set(&rproc->power, 0); - kref_init(&rproc->refcount); - mutex_init(&rproc->lock); idr_init(&rproc->notifyids); @@ -1608,8 +1580,8 @@ int rproc_unregister(struct rproc *rproc) device_del(&rproc->dev); - /* the rproc will only be released after its refcount drops to zero */ - kref_put(&rproc->refcount, rproc_release); + /* unroll rproc_alloc. TODO: we may want to let the users do that */ + put_device(&rproc->dev); return 0; } diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index b6621831a58a..3541b4492f64 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -225,7 +225,7 @@ static struct virtio_config_ops rproc_virtio_config_ops = { /* * This function is called whenever vdev is released, and is responsible - * to decrement the remote processor's refcount taken when vdev was + * to decrement the remote processor's refcount which was taken when vdev was * added. * * Never call this function directly; it will be called by the driver @@ -240,7 +240,7 @@ static void rproc_vdev_release(struct device *dev) list_del(&rvdev->node); kfree(rvdev); - kref_put(&rproc->refcount, rproc_release); + put_device(&rproc->dev); } /** @@ -272,11 +272,11 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) * Therefore we must increment the rproc refcount here, and decrement * it _only_ when the vdev is released. */ - kref_get(&rproc->refcount); + get_device(&rproc->dev); ret = register_virtio_device(vdev); if (ret) { - kref_put(&rproc->refcount, rproc_release); + put_device(&rproc->dev); dev_err(dev, "failed to register vdev: %d\n", ret); goto out; } diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 7f806dcf5278..cbe8a51a21de 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -36,7 +36,6 @@ #define REMOTEPROC_H #include -#include #include #include #include @@ -370,7 +369,6 @@ enum rproc_state { * @priv: private data which belongs to the platform-specific rproc module * @ops: platform-specific start/stop rproc handlers * @dev: virtual device for refcounting and common remoteproc behavior - * @refcount: refcount of users that have a valid pointer to this rproc * @power: refcount of users who need this rproc powered up * @state: state of the device * @lock: lock which protects concurrent manipulations of the rproc @@ -393,7 +391,6 @@ struct rproc { void *priv; const struct rproc_ops *ops; struct device dev; - struct kref refcount; atomic_t power; unsigned int state; struct mutex lock; -- GitLab From c6b5a27628faf6657b741d828a1462d832d0dbc5 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Mon, 2 Jul 2012 11:41:16 +0300 Subject: [PATCH 1864/5711] remoteproc: simplify unregister/free interfaces Simplify the unregister/free interfaces, and make them easier to understand and use, by moving to a symmetric and consistent alloc() -> register() -> unregister() -> free() flow. To create and register an rproc instance, one needed to invoke rproc_alloc() followed by rproc_register(). To unregister and free an rproc instance, one now needs to invoke rproc_unregister() followed by rproc_free(). Cc: Stephen Boyd Signed-off-by: Ohad Ben-Cohen --- Documentation/remoteproc.txt | 21 ++++++++------------- drivers/remoteproc/omap_remoteproc.c | 5 ++++- drivers/remoteproc/remoteproc_core.c | 25 ++++++++----------------- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index 70a048cd3fa3..ad6ded4bca5c 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt @@ -120,14 +120,14 @@ int dummy_rproc_example(struct rproc *my_rproc) On success, the new rproc is returned, and on failure, NULL. Note: _never_ directly deallocate @rproc, even if it was not registered - yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free(). + yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). void rproc_free(struct rproc *rproc) - Free an rproc handle that was allocated by rproc_alloc. - This function should _only_ be used if @rproc was only allocated, - but not registered yet. - If @rproc was already successfully registered (by calling - rproc_register()), then use rproc_unregister() instead. + This function essentially unrolls rproc_alloc(), by decrementing the + rproc's refcount. It doesn't directly free rproc; that would happen + only if there are no other references to rproc and its refcount now + dropped to zero. int rproc_register(struct rproc *rproc) - Register @rproc with the remoteproc framework, after it has been @@ -143,19 +143,14 @@ int dummy_rproc_example(struct rproc *my_rproc) probed. int rproc_unregister(struct rproc *rproc) - - Unregister a remote processor, and decrement its refcount. - If its refcount drops to zero, then @rproc will be freed. If not, - it will be freed later once the last reference is dropped. - + - Unroll rproc_register(). This function should be called when the platform specific rproc implementation decides to remove the rproc device. it should _only_ be called if a previous invocation of rproc_register() has completed successfully. - After rproc_unregister() returns, @rproc is _not_ valid anymore and - it shouldn't be used. More specifically, don't call rproc_free() - or try to directly free @rproc after rproc_unregister() returns; - none of these are needed, and calling them is a bug. + After rproc_unregister() returns, @rproc is still valid, and its + last refcount should be decremented by calling rproc_free(). Returns 0 on success and -EINVAL if @rproc isn't valid. diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index b5e6d2981741..4f2fe8fd7fe6 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -214,7 +214,10 @@ static int __devexit omap_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); - return rproc_unregister(rproc); + rproc_unregister(rproc); + rproc_free(rproc); + + return 0; } static struct platform_driver omap_rproc_driver = { diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index aa713aade30e..4a77dc1df3d8 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1472,7 +1472,7 @@ static struct device_type rproc_type = { * On success the new rproc is returned, and on failure, NULL. * * Note: _never_ directly deallocate @rproc, even if it was not registered - * yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free(). + * yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). */ struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -1526,14 +1526,13 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, EXPORT_SYMBOL(rproc_alloc); /** - * rproc_free() - free an rproc handle that was allocated by rproc_alloc + * rproc_free() - unroll rproc_alloc() * @rproc: the remote processor handle * - * This function should _only_ be used if @rproc was only allocated, - * but not registered yet. + * This function decrements the rproc dev refcount. * - * If @rproc was already successfully registered (by calling rproc_register()), - * then use rproc_unregister() instead. + * If no one holds any reference to rproc anymore, then its refcount would + * now drop to zero, and it would be freed. */ void rproc_free(struct rproc *rproc) { @@ -1545,19 +1544,14 @@ EXPORT_SYMBOL(rproc_free); * rproc_unregister() - unregister a remote processor * @rproc: rproc handle to unregister * - * Unregisters a remote processor, and decrements its refcount. - * If its refcount drops to zero, then @rproc will be freed. If not, - * it will be freed later once the last reference is dropped. - * * This function should be called when the platform specific rproc * implementation decides to remove the rproc device. it should * _only_ be called if a previous invocation of rproc_register() * has completed successfully. * - * After rproc_unregister() returns, @rproc is _not_ valid anymore and - * it shouldn't be used. More specifically, don't call rproc_free() - * or try to directly free @rproc after rproc_unregister() returns; - * none of these are needed, and calling them is a bug. + * After rproc_unregister() returns, @rproc isn't freed yet, because + * of the outstanding reference created by rproc_alloc. To decrement that + * one last refcount, one still needs to call rproc_free(). * * Returns 0 on success and -EINVAL if @rproc isn't valid. */ @@ -1580,9 +1574,6 @@ int rproc_unregister(struct rproc *rproc) device_del(&rproc->dev); - /* unroll rproc_alloc. TODO: we may want to let the users do that */ - put_device(&rproc->dev); - return 0; } EXPORT_SYMBOL(rproc_unregister); -- GitLab From 0e49b72c8c91f9ea65ae62ca3061f885aa06a6f6 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Sun, 1 Jul 2012 11:30:57 +0300 Subject: [PATCH 1865/5711] remoteproc: support non-iommu carveout assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publish carveout addresses on non-iommu setups too. Reported-and-acked-by: Sjur Brændeland Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 4a77dc1df3d8..c85db123ba0a 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -713,23 +713,27 @@ static int rproc_handle_carveout(struct rproc *rproc, list_add_tail(&mapping->node, &rproc->mappings); dev_dbg(dev, "carveout mapped 0x%x to 0x%x\n", rsc->da, dma); - - /* - * Some remote processors might need to know the pa - * even though they are behind an IOMMU. E.g., OMAP4's - * remote M3 processor needs this so it can control - * on-chip hardware accelerators that are not behind - * the IOMMU, and therefor must know the pa. - * - * Generally we don't want to expose physical addresses - * if we don't have to (remote processors are generally - * _not_ trusted), so we might want to do this only for - * remote processor that _must_ have this (e.g. OMAP4's - * dual M3 subsystem). - */ - rsc->pa = dma; } + /* + * Some remote processors might need to know the pa + * even though they are behind an IOMMU. E.g., OMAP4's + * remote M3 processor needs this so it can control + * on-chip hardware accelerators that are not behind + * the IOMMU, and therefor must know the pa. + * + * Generally we don't want to expose physical addresses + * if we don't have to (remote processors are generally + * _not_ trusted), so we might want to do this only for + * remote processor that _must_ have this (e.g. OMAP4's + * dual M3 subsystem). + * + * Non-IOMMU processors might also want to have this info. + * In this case, the device address and the physical address + * are the same. + */ + rsc->pa = dma; + carveout->va = va; carveout->len = rsc->len; carveout->dma = dma; -- GitLab From 40e575b1d0b34b38519d361c10bdf8e0c688957b Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Mon, 2 Jul 2012 20:20:53 +0300 Subject: [PATCH 1866/5711] remoteproc: remove the get_by_name/put API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove rproc_get_by_name() and rproc_put(), and the associated remoteproc infrastructure that supports it (i.e. klist and friends), because: 1. No one uses them 2. Using them is highly discouraged, and any potential user will be deeply scrutinized and encouraged to move. If a user, that absolutely can't live with the direct boot/shutdown model, does show up one day, then bringing this functionality back is going to be trivial. At this point though, keeping this functionality around is way too much of a maintenance burden. Cc: Sjur Brændeland Cc: Loic Pallardy Cc: Ludovic BARRE Cc: Michal Simek Cc: Fernando Guzman Lugo Cc: Suman Anna Cc: Mark Grosen Acked-by: Stephen Boyd Signed-off-by: Ohad Ben-Cohen --- Documentation/remoteproc.txt | 27 +----- drivers/remoteproc/remoteproc_core.c | 130 --------------------------- include/linux/remoteproc.h | 3 - 3 files changed, 1 insertion(+), 159 deletions(-) diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index ad6ded4bca5c..f33c3bbbc867 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt @@ -36,8 +36,7 @@ cost. Note: to use this function you should already have a valid rproc handle. There are several ways to achieve that cleanly (devres, pdata, the way remoteproc_rpmsg.c does this, or, if this becomes prevalent, we - might also consider using dev_archdata for this). See also - rproc_get_by_name() below. + might also consider using dev_archdata for this). void rproc_shutdown(struct rproc *rproc) - Power off a remote processor (previously booted with rproc_boot()). @@ -51,30 +50,6 @@ cost. which means that the @rproc handle stays valid even after rproc_shutdown() returns, and users can still use it with a subsequent rproc_boot(), if needed. - - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly - because rproc_shutdown() _does not_ decrement the refcount of @rproc. - To decrement the refcount of @rproc, use rproc_put() (but _only_ if - you acquired @rproc using rproc_get_by_name()). - - struct rproc *rproc_get_by_name(const char *name) - - Find an rproc handle using the remote processor's name, and then - boot it. If it's already powered on, then just immediately return - (successfully). Returns the rproc handle on success, and NULL on failure. - This function increments the remote processor's refcount, so always - use rproc_put() to decrement it back once rproc isn't needed anymore. - Note: currently rproc_get_by_name() and rproc_put() are not used anymore - by the rpmsg bus and its drivers. We need to scrutinize the use cases - that still need them, and see if we can migrate them to use the non - name-based boot/shutdown interface. - - void rproc_put(struct rproc *rproc) - - Decrement @rproc's power refcount and shut it down if it reaches zero - (essentially by just calling rproc_shutdown), and then decrement @rproc's - validity refcount too. - After this function returns, @rproc may _not_ be used anymore, and its - handle should be considered invalid. - This function should be called _iff_ the @rproc handle was grabbed by - calling rproc_get_by_name(). 3. Typical usage diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index c85db123ba0a..0c77c4fcf436 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -44,25 +43,6 @@ #include "remoteproc_internal.h" -static void klist_rproc_get(struct klist_node *n); -static void klist_rproc_put(struct klist_node *n); - -/* - * klist of the available remote processors. - * - * We need this in order to support name-based lookups (needed by the - * rproc_get_by_name()). - * - * That said, we don't use rproc_get_by_name() at this point. - * The use cases that do require its existence should be - * scrutinized, and hopefully migrated to rproc_boot() using device-based - * binding. - * - * If/when this materializes, we could drop the klist (and the by_name - * API). - */ -static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put); - typedef int (*rproc_handle_resources_t)(struct rproc *rproc, struct resource_table *table, int len); typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); @@ -1217,10 +1197,6 @@ EXPORT_SYMBOL(rproc_boot); * which means that the @rproc handle stays valid even after rproc_shutdown() * returns, and users can still use it with a subsequent rproc_boot(), if * needed. - * - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly - * because rproc_shutdown() _does not_ decrement the refcount of @rproc. - * To decrement the refcount of @rproc, use rproc_put() (but _only_ if - * you acquired @rproc using rproc_get_by_name()). */ void rproc_shutdown(struct rproc *rproc) { @@ -1261,105 +1237,6 @@ out: } EXPORT_SYMBOL(rproc_shutdown); -/* will be called when an rproc is added to the rprocs klist */ -static void klist_rproc_get(struct klist_node *n) -{ - struct rproc *rproc = container_of(n, struct rproc, node); - - get_device(&rproc->dev); -} - -/* will be called when an rproc is removed from the rprocs klist */ -static void klist_rproc_put(struct klist_node *n) -{ - struct rproc *rproc = container_of(n, struct rproc, node); - - put_device(&rproc->dev); -} - -static struct rproc *next_rproc(struct klist_iter *i) -{ - struct klist_node *n; - - n = klist_next(i); - if (!n) - return NULL; - - return container_of(n, struct rproc, node); -} - -/** - * rproc_get_by_name() - find a remote processor by name and boot it - * @name: name of the remote processor - * - * Finds an rproc handle using the remote processor's name, and then - * boot it. If it's already powered on, then just immediately return - * (successfully). - * - * Returns the rproc handle on success, and NULL on failure. - * - * This function increments the remote processor's refcount, so always - * use rproc_put() to decrement it back once rproc isn't needed anymore. - * - * Note: currently this function (and its counterpart rproc_put()) are not - * being used. We need to scrutinize the use cases - * that still need them, and see if we can migrate them to use the non - * name-based boot/shutdown interface. - */ -struct rproc *rproc_get_by_name(const char *name) -{ - struct rproc *rproc; - struct klist_iter i; - int ret; - - /* find the remote processor, and upref its refcount */ - klist_iter_init(&rprocs, &i); - while ((rproc = next_rproc(&i)) != NULL) - if (!strcmp(rproc->name, name)) { - get_device(&rproc->dev); - break; - } - klist_iter_exit(&i); - - /* can't find this rproc ? */ - if (!rproc) { - pr_err("can't find remote processor %s\n", name); - return NULL; - } - - ret = rproc_boot(rproc); - if (ret < 0) { - put_device(&rproc->dev); - return NULL; - } - - return rproc; -} -EXPORT_SYMBOL(rproc_get_by_name); - -/** - * rproc_put() - decrement the refcount of a remote processor, and shut it down - * @rproc: the remote processor - * - * This function tries to shutdown @rproc, and it then decrements its - * refcount. - * - * After this function returns, @rproc may _not_ be used anymore, and its - * handle should be considered invalid. - * - * This function should be called _iff_ the @rproc handle was grabbed by - * calling rproc_get_by_name(). - */ -void rproc_put(struct rproc *rproc) -{ - /* try to power off the remote processor */ - rproc_shutdown(rproc); - - /* downref rproc's refcount */ - put_device(&rproc->dev); -} -EXPORT_SYMBOL(rproc_put); - /** * rproc_register() - register a remote processor * @rproc: the remote processor handle to register @@ -1389,9 +1266,6 @@ int rproc_register(struct rproc *rproc) if (ret < 0) return ret; - /* expose to rproc_get_by_name users */ - klist_add_tail(&rproc->node, &rprocs); - dev_info(dev, "%s is available\n", rproc->name); dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n"); @@ -1417,7 +1291,6 @@ int rproc_register(struct rproc *rproc) if (ret < 0) { dev_err(dev, "request_firmware_nowait failed: %d\n", ret); complete_all(&rproc->firmware_loading_complete); - klist_remove(&rproc->node); } return ret; @@ -1573,9 +1446,6 @@ int rproc_unregister(struct rproc *rproc) list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node) rproc_remove_virtio_dev(rvdev); - /* the rproc is downref'ed as soon as it's removed from the klist */ - klist_del(&rproc->node); - device_del(&rproc->dev); return 0; diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index cbe8a51a21de..b88d6af5ba52 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -449,9 +449,6 @@ struct rproc_vdev { unsigned long gfeatures; }; -struct rproc *rproc_get_by_name(const char *name); -void rproc_put(struct rproc *rproc); - struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, const char *firmware, int len); -- GitLab From 160e7c840fe85836040c43e0058d5afced470c85 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 4 Jul 2012 16:25:06 +0300 Subject: [PATCH 1867/5711] remoteproc: adopt the driver core's alloc/add/del/put naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make remoteproc's API more intuitive for developers, we adopt the driver core's naming, i.e. alloc -> add -> del -> put. We'll also add register/unregister when their first user shows up. Otherwise - there's no functional change here. Suggested by Russell King . Cc: Russell King Cc: Fernando Guzman Lugo Cc: Sjur Brændeland Reviewed-by: Linus Walleij Acked-by: Stephen Boyd Signed-off-by: Ohad Ben-Cohen --- Documentation/remoteproc.txt | 18 ++++++++-------- drivers/remoteproc/omap_remoteproc.c | 8 +++---- drivers/remoteproc/remoteproc_core.c | 32 ++++++++++++++-------------- include/linux/remoteproc.h | 6 +++--- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index f33c3bbbc867..23a09b884bc7 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt @@ -90,21 +90,21 @@ int dummy_rproc_example(struct rproc *my_rproc) This function should be used by rproc implementations during initialization of the remote processor. After creating an rproc handle using this function, and when ready, - implementations should then call rproc_register() to complete + implementations should then call rproc_add() to complete the registration of the remote processor. On success, the new rproc is returned, and on failure, NULL. Note: _never_ directly deallocate @rproc, even if it was not registered - yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). + yet. Instead, when you need to unroll rproc_alloc(), use rproc_put(). - void rproc_free(struct rproc *rproc) + void rproc_put(struct rproc *rproc) - Free an rproc handle that was allocated by rproc_alloc. This function essentially unrolls rproc_alloc(), by decrementing the rproc's refcount. It doesn't directly free rproc; that would happen only if there are no other references to rproc and its refcount now dropped to zero. - int rproc_register(struct rproc *rproc) + int rproc_add(struct rproc *rproc) - Register @rproc with the remoteproc framework, after it has been allocated with rproc_alloc(). This is called by the platform-specific rproc implementation, whenever @@ -117,15 +117,15 @@ int dummy_rproc_example(struct rproc *my_rproc) of registering this remote processor, additional virtio drivers might get probed. - int rproc_unregister(struct rproc *rproc) - - Unroll rproc_register(). + int rproc_del(struct rproc *rproc) + - Unroll rproc_add(). This function should be called when the platform specific rproc implementation decides to remove the rproc device. it should - _only_ be called if a previous invocation of rproc_register() + _only_ be called if a previous invocation of rproc_add() has completed successfully. - After rproc_unregister() returns, @rproc is still valid, and its - last refcount should be decremented by calling rproc_free(). + After rproc_del() returns, @rproc is still valid, and its + last refcount should be decremented by calling rproc_put(). Returns 0 on success and -EINVAL if @rproc isn't valid. diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 4f2fe8fd7fe6..02bae3a5264f 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -199,14 +199,14 @@ static int __devinit omap_rproc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rproc); - ret = rproc_register(rproc); + ret = rproc_add(rproc); if (ret) goto free_rproc; return 0; free_rproc: - rproc_free(rproc); + rproc_put(rproc); return ret; } @@ -214,8 +214,8 @@ static int __devexit omap_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); - rproc_unregister(rproc); - rproc_free(rproc); + rproc_del(rproc); + rproc_put(rproc); return 0; } diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 0c77c4fcf436..25fd9733d5df 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1101,7 +1101,7 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context) out: release_firmware(fw); - /* allow rproc_unregister() contexts, if any, to proceed */ + /* allow rproc_del() contexts, if any, to proceed */ complete_all(&rproc->firmware_loading_complete); } @@ -1238,7 +1238,7 @@ out: EXPORT_SYMBOL(rproc_shutdown); /** - * rproc_register() - register a remote processor + * rproc_add() - register a remote processor * @rproc: the remote processor handle to register * * Registers @rproc with the remoteproc framework, after it has been @@ -1257,7 +1257,7 @@ EXPORT_SYMBOL(rproc_shutdown); * of registering this remote processor, additional virtio drivers might be * probed. */ -int rproc_register(struct rproc *rproc) +int rproc_add(struct rproc *rproc) { struct device *dev = &rproc->dev; int ret = 0; @@ -1274,7 +1274,7 @@ int rproc_register(struct rproc *rproc) /* create debugfs entries */ rproc_create_debug_dir(rproc); - /* rproc_unregister() calls must wait until async loader completes */ + /* rproc_del() calls must wait until async loader completes */ init_completion(&rproc->firmware_loading_complete); /* @@ -1295,7 +1295,7 @@ int rproc_register(struct rproc *rproc) return ret; } -EXPORT_SYMBOL(rproc_register); +EXPORT_SYMBOL(rproc_add); /** * rproc_type_release() - release a remote processor instance @@ -1343,13 +1343,13 @@ static struct device_type rproc_type = { * of the remote processor. * * After creating an rproc handle using this function, and when ready, - * implementations should then call rproc_register() to complete + * implementations should then call rproc_add() to complete * the registration of the remote processor. * * On success the new rproc is returned, and on failure, NULL. * * Note: _never_ directly deallocate @rproc, even if it was not registered - * yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). + * yet. Instead, when you need to unroll rproc_alloc(), use rproc_put(). */ struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -1403,7 +1403,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, EXPORT_SYMBOL(rproc_alloc); /** - * rproc_free() - unroll rproc_alloc() + * rproc_put() - unroll rproc_alloc() * @rproc: the remote processor handle * * This function decrements the rproc dev refcount. @@ -1411,28 +1411,28 @@ EXPORT_SYMBOL(rproc_alloc); * If no one holds any reference to rproc anymore, then its refcount would * now drop to zero, and it would be freed. */ -void rproc_free(struct rproc *rproc) +void rproc_put(struct rproc *rproc) { put_device(&rproc->dev); } -EXPORT_SYMBOL(rproc_free); +EXPORT_SYMBOL(rproc_put); /** - * rproc_unregister() - unregister a remote processor + * rproc_del() - unregister a remote processor * @rproc: rproc handle to unregister * * This function should be called when the platform specific rproc * implementation decides to remove the rproc device. it should - * _only_ be called if a previous invocation of rproc_register() + * _only_ be called if a previous invocation of rproc_add() * has completed successfully. * - * After rproc_unregister() returns, @rproc isn't freed yet, because + * After rproc_del() returns, @rproc isn't freed yet, because * of the outstanding reference created by rproc_alloc. To decrement that - * one last refcount, one still needs to call rproc_free(). + * one last refcount, one still needs to call rproc_put(). * * Returns 0 on success and -EINVAL if @rproc isn't valid. */ -int rproc_unregister(struct rproc *rproc) +int rproc_del(struct rproc *rproc) { struct rproc_vdev *rvdev, *tmp; @@ -1450,7 +1450,7 @@ int rproc_unregister(struct rproc *rproc) return 0; } -EXPORT_SYMBOL(rproc_unregister); +EXPORT_SYMBOL(rproc_del); static int __init remoteproc_init(void) { diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index b88d6af5ba52..eea3ac86b2b7 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -452,9 +452,9 @@ struct rproc_vdev { struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, const char *firmware, int len); -void rproc_free(struct rproc *rproc); -int rproc_register(struct rproc *rproc); -int rproc_unregister(struct rproc *rproc); +void rproc_put(struct rproc *rproc); +int rproc_add(struct rproc *rproc); +int rproc_del(struct rproc *rproc); int rproc_boot(struct rproc *rproc); void rproc_shutdown(struct rproc *rproc); -- GitLab From 7985a90d5bb608be221e135415fa63885981ca3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Thu, 21 Jun 2012 15:52:03 -0300 Subject: [PATCH 1868/5711] [media] staging: solo6x10: Fix TODO file with proper maintainer Mauro Carvalho Chehab is the current maintainer of staging/media. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/solo6x10/TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/solo6x10/TODO b/drivers/staging/media/solo6x10/TODO index 7e6c4fa130df..539f739fe9e6 100644 --- a/drivers/staging/media/solo6x10/TODO +++ b/drivers/staging/media/solo6x10/TODO @@ -20,5 +20,5 @@ TODO (general): - implement loopback of external sound jack with incoming audio? - implement pause/resume -Plase send patches to Greg Kroah-Hartman and Cc Ben Collins +Plase send patches to Mauro Carvalho Chehab and Cc Ben Collins -- GitLab From cc831f843c807ac9050707f7b2c403f9c400a197 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Jul 2012 21:48:58 -0300 Subject: [PATCH 1869/5711] [media] v4l2-compat-ioctl32: fix compilation breakage changeset 2b719d7baf (v4l: drop v4l2_buffer.input and V4L2_BUF_FLAG_INPUT) broke compilation on x86_64: v4l2-compat-ioctl32.c: In function 'get_v4l2_buffer32': v4l2-compat-ioctl32.c:391:4: error: expected ')' before 'return' ... v4l2-compat-ioctl32.c: In function 'put_v4l2_buffer32': v4l2-compat-ioctl32.c:475:4: error: expected ')' before 'return' ... Add the missing close parenthesis character. Cc: Sakari Ailus Cc: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-compat-ioctl32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 658ba46ee9d2..ac365cfb3706 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -387,7 +387,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory) + get_user(kp->memory, &up->memory)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -471,7 +471,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user put_user(kp->index, &up->index) || put_user(kp->type, &up->type) || put_user(kp->flags, &up->flags) || - put_user(kp->memory, &up->memory) + put_user(kp->memory, &up->memory)) return -EFAULT; if (put_user(kp->bytesused, &up->bytesused) || @@ -481,7 +481,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved2, &up->reserved2) || - put_user(kp->reserved, &up->reserved) + put_user(kp->reserved, &up->reserved)) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { -- GitLab From f244e6c308be3acc445719f0fd72b5fb182c0895 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Jul 2012 22:35:55 -0300 Subject: [PATCH 1870/5711] [media] get_dvb_firmware: add logic to get sms1xx-hcw* firmware The firmwares are there at the same place for a long time. However, each time I need to remember where it is, I need to seek at the net. The better is to just add a logic at the get_dvb_firmare script, in order to obtain it from a reliable source. Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/get_dvb_firmware | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 94b01689808d..12d3952e83d5 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -29,7 +29,7 @@ use IO::Handle; "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395", "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137", - "drxk_pctv", "drxk_terratec_htc_stick"); + "drxk_pctv", "drxk_terratec_htc_stick", "sms1xxx_hcw"); # Check args syntax() if (scalar(@ARGV) != 1); @@ -766,6 +766,28 @@ sub drxk_pctv { "$fwfile"; } +sub sms1xxx_hcw { + my $url = "http://steventoth.net/linux/sms1xxx/"; + my %files = ( + 'sms1xxx-hcw-55xxx-dvbt-01.fw' => "afb6f9fb9a71d64392e8564ef9577e5a", + 'sms1xxx-hcw-55xxx-dvbt-02.fw' => "b44807098ba26e52cbedeadc052ba58f", + 'sms1xxx-hcw-55xxx-isdbt-02.fw' => "dae934eeea85225acbd63ce6cfe1c9e4", + ); + + checkstandard(); + + my $allfiles; + foreach my $fwfile (keys %files) { + wgetfile($fwfile, "$url/$fwfile"); + verify($fwfile, $files{$fwfile}); + $allfiles .= " $fwfile"; + } + + $allfiles =~ s/^\s//; + + $allfiles; +} + # --------------------------------------------------------------- # Utilities -- GitLab From 739c905baa018c99003564ebc367d93aa44d4861 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1871/5711] libceph: encapsulate out message data setup Move the code that prepares to write the data portion of a message into its own function. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ab690e2e1206..56448660883d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -565,6 +565,24 @@ static void con_out_kvec_add(struct ceph_connection *con, con->out_kvec_bytes += size; } +static void prepare_write_message_data(struct ceph_connection *con) +{ + struct ceph_msg *msg = con->out_msg; + + BUG_ON(!msg); + BUG_ON(!msg->hdr.data_len); + + /* initialize page iterator */ + con->out_msg_pos.page = 0; + if (msg->pages) + con->out_msg_pos.page_pos = msg->page_alignment; + else + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.data_pos = 0; + con->out_msg_pos.did_page_crc = false; + con->out_more = 1; /* data + footer will follow */ +} + /* * Prepare footer for currently outgoing message, and finish things * off. Assumes out_kvec* are already valid.. we just add on to the end. @@ -657,26 +675,17 @@ static void prepare_write_message(struct ceph_connection *con) con->out_msg->footer.middle_crc = cpu_to_le32(crc); } else con->out_msg->footer.middle_crc = 0; - con->out_msg->footer.data_crc = 0; - dout("prepare_write_message front_crc %u data_crc %u\n", + dout("%s front_crc %u middle_crc %u\n", __func__, le32_to_cpu(con->out_msg->footer.front_crc), le32_to_cpu(con->out_msg->footer.middle_crc)); /* is there a data payload? */ - if (le32_to_cpu(m->hdr.data_len) > 0) { - /* initialize page iterator */ - con->out_msg_pos.page = 0; - if (m->pages) - con->out_msg_pos.page_pos = m->page_alignment; - else - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.data_pos = 0; - con->out_msg_pos.did_page_crc = false; - con->out_more = 1; /* data + footer will follow */ - } else { + con->out_msg->footer.data_crc = 0; + if (m->hdr.data_len) + prepare_write_message_data(con); + else /* no, queue up footer too and be done */ prepare_write_message_footer(con); - } set_bit(WRITE_PENDING, &con->flags); } -- GitLab From 84ca8fc87fcf4ab97bb8acdb59bf97bb4820cb14 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1872/5711] libceph: encapsulate advancing msg page In write_partial_msg_pages(), once all the data from a page has been sent we advance to the next one. Put the code that takes care of this into its own function. While modifying write_partial_msg_pages(), make its local variable "in_trail" be Boolean, and use the local variable "msg" (which is just the connection's current out_msg pointer) consistently. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 58 ++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 56448660883d..1b92e3b16c0d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -891,6 +891,33 @@ static void iter_bio_next(struct bio **bio_iter, int *seg) } #endif +static void out_msg_pos_next(struct ceph_connection *con, struct page *page, + size_t len, size_t sent, bool in_trail) +{ + struct ceph_msg *msg = con->out_msg; + + BUG_ON(!msg); + BUG_ON(!sent); + + con->out_msg_pos.data_pos += sent; + con->out_msg_pos.page_pos += sent; + if (sent == len) { + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.page++; + con->out_msg_pos.did_page_crc = false; + if (in_trail) + list_move_tail(&page->lru, + &msg->trail->head); + else if (msg->pagelist) + list_move_tail(&page->lru, + &msg->pagelist->head); +#ifdef CONFIG_BLOCK + else if (msg->bio) + iter_bio_next(&msg->bio_iter, &msg->bio_seg); +#endif + } +} + /* * Write as much message data payload as we can. If we finish, queue * up the footer. @@ -906,11 +933,11 @@ static int write_partial_msg_pages(struct ceph_connection *con) bool do_datacrc = !con->msgr->nocrc; int ret; int total_max_write; - int in_trail = 0; + bool in_trail = false; size_t trail_len = (msg->trail ? msg->trail->length : 0); dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", - con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, + con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); #ifdef CONFIG_BLOCK @@ -934,13 +961,12 @@ static int write_partial_msg_pages(struct ceph_connection *con) /* have we reached the trail part of the data? */ if (con->out_msg_pos.data_pos >= data_len - trail_len) { - in_trail = 1; + in_trail = true; total_max_write = data_len - con->out_msg_pos.data_pos; page = list_first_entry(&msg->trail->head, struct page, lru); - max_write = PAGE_SIZE; } else if (msg->pages) { page = msg->pages[con->out_msg_pos.page]; } else if (msg->pagelist) { @@ -964,14 +990,14 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (do_datacrc && !con->out_msg_pos.did_page_crc) { void *base; u32 crc; - u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); + u32 tmpcrc = le32_to_cpu(msg->footer.data_crc); char *kaddr; kaddr = kmap(page); BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc = crc32c(tmpcrc, base, len); - con->out_msg->footer.data_crc = cpu_to_le32(crc); + msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, @@ -984,30 +1010,14 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (ret <= 0) goto out; - con->out_msg_pos.data_pos += ret; - con->out_msg_pos.page_pos += ret; - if (ret == len) { - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.page++; - con->out_msg_pos.did_page_crc = false; - if (in_trail) - list_move_tail(&page->lru, - &msg->trail->head); - else if (msg->pagelist) - list_move_tail(&page->lru, - &msg->pagelist->head); -#ifdef CONFIG_BLOCK - else if (msg->bio) - iter_bio_next(&msg->bio_iter, &msg->bio_seg); -#endif - } + out_msg_pos_next(con, page, len, (size_t) ret, in_trail); } dout("write_partial_msg_pages %p msg %p done\n", con, msg); /* prepare and queue up footer, too */ if (!do_datacrc) - con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; + msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; con_out_kvec_reset(con); prepare_write_message_footer(con); ret = 1; -- GitLab From fd154f3c75465abd83b7a395033e3755908a1e6e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1873/5711] libceph: don't mark footer complete before it is This is a nit, but prepare_write_message() sets the FOOTER_COMPLETE flag before the CRC for the data portion (recorded in the footer) has been completely computed. Hold off setting the complete flag until we've decided it's ready to send. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1b92e3b16c0d..5354d59ba8b9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -592,6 +592,8 @@ static void prepare_write_message_footer(struct ceph_connection *con) struct ceph_msg *m = con->out_msg; int v = con->out_kvec_left; + m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; + dout("prepare_write_message_footer %p\n", con); con->out_kvec_is_msg = true; con->out_kvec[v].iov_base = &m->footer; @@ -665,7 +667,7 @@ static void prepare_write_message(struct ceph_connection *con) /* fill in crc (except data pages), footer */ crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); con->out_msg->hdr.crc = cpu_to_le32(crc); - con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; + con->out_msg->footer.flags = 0; crc = crc32c(0, m->front.iov_base, m->front.iov_len); con->out_msg->footer.front_crc = cpu_to_le32(crc); -- GitLab From df6ad1f97342ebc4270128222e896541405eecdb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1874/5711] libceph: move init_bio_*() functions up Move init_bio_iter() and iter_bio_next() up in their source file so the'll be defined before they're needed. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5354d59ba8b9..7b5ff4545bf3 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -565,6 +565,31 @@ static void con_out_kvec_add(struct ceph_connection *con, con->out_kvec_bytes += size; } +#ifdef CONFIG_BLOCK +static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) +{ + if (!bio) { + *iter = NULL; + *seg = 0; + return; + } + *iter = bio; + *seg = bio->bi_idx; +} + +static void iter_bio_next(struct bio **bio_iter, int *seg) +{ + if (*bio_iter == NULL) + return; + + BUG_ON(*seg >= (*bio_iter)->bi_vcnt); + + (*seg)++; + if (*seg == (*bio_iter)->bi_vcnt) + init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); +} +#endif + static void prepare_write_message_data(struct ceph_connection *con) { struct ceph_msg *msg = con->out_msg; @@ -868,31 +893,6 @@ out: return ret; /* done! */ } -#ifdef CONFIG_BLOCK -static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) -{ - if (!bio) { - *iter = NULL; - *seg = 0; - return; - } - *iter = bio; - *seg = bio->bi_idx; -} - -static void iter_bio_next(struct bio **bio_iter, int *seg) -{ - if (*bio_iter == NULL) - return; - - BUG_ON(*seg >= (*bio_iter)->bi_vcnt); - - (*seg)++; - if (*seg == (*bio_iter)->bi_vcnt) - init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); -} -#endif - static void out_msg_pos_next(struct ceph_connection *con, struct page *page, size_t len, size_t sent, bool in_trail) { -- GitLab From 572c588edadaa3da3992bd8a0fed830bbcc861f8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1875/5711] libceph: move init of bio_iter If a message has a non-null bio pointer, its bio_iter field is initialized in write_partial_msg_pages() if this has not been done already. This is really a one-time setup operation for sending a message's (bio) data, so move that initialization code into prepare_write_message_data() which serves that purpose. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7b5ff4545bf3..fedad914b238 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -603,6 +603,10 @@ static void prepare_write_message_data(struct ceph_connection *con) con->out_msg_pos.page_pos = msg->page_alignment; else con->out_msg_pos.page_pos = 0; +#ifdef CONFIG_BLOCK + if (msg->bio && !msg->bio_iter) + init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); +#endif con->out_msg_pos.data_pos = 0; con->out_msg_pos.did_page_crc = false; con->out_more = 1; /* data + footer will follow */ @@ -942,11 +946,6 @@ static int write_partial_msg_pages(struct ceph_connection *con) con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); -#ifdef CONFIG_BLOCK - if (msg->bio && !msg->bio_iter) - init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); -#endif - while (data_len > con->out_msg_pos.data_pos) { struct page *page = NULL; int max_write = PAGE_SIZE; -- GitLab From abdaa6a849af1d63153682c11f5bbb22dacb1f6b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1876/5711] libceph: don't use bio_iter as a flag Recently a bug was fixed in which the bio_iter field in a ceph message was not being properly re-initialized when a message got re-transmitted: commit 43643528cce60ca184fe8197efa8e8da7c89a037 Author: Yan, Zheng rbd: Clear ceph_msg->bio_iter for retransmitted message We are now only initializing the bio_iter field when we are about to start to write message data (in prepare_write_message_data()), rather than every time we are attempting to write any portion of the message data (in write_partial_msg_pages()). This means we no longer need to use the msg->bio_iter field as a flag. So just don't do that any more. Trust prepare_write_message_data() to ensure msg->bio_iter is properly initialized, every time we are about to begin writing (or re-writing) a message's bio data. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index fedad914b238..3a4330371d88 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -604,7 +604,7 @@ static void prepare_write_message_data(struct ceph_connection *con) else con->out_msg_pos.page_pos = 0; #ifdef CONFIG_BLOCK - if (msg->bio && !msg->bio_iter) + if (msg->bio) init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); #endif con->out_msg_pos.data_pos = 0; @@ -672,10 +672,6 @@ static void prepare_write_message(struct ceph_connection *con) m->hdr.seq = cpu_to_le64(++con->out_seq); m->needs_out_seq = false; } -#ifdef CONFIG_BLOCK - else - m->bio_iter = NULL; -#endif dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), -- GitLab From a8d00e3cdef4c1c4f194414b72b24cd995439a05 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1877/5711] libceph: SOCK_CLOSED is a flag, not a state The following commit changed it so SOCK_CLOSED bit was stored in a connection's new "flags" field rather than its "state" field. libceph: start separating connection flags from state commit 928443cd That bit is used in con_close_socket() to protect against setting an error message more than once in the socket event handler function. Unfortunately, the field being operated on in that function was not updated to be "flags" as it should have been. This fixes that error. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3a4330371d88..39653944f21b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -397,11 +397,11 @@ static int con_close_socket(struct ceph_connection *con) dout("con_close_socket on %p sock %p\n", con, con->sock); if (!con->sock) return 0; - set_bit(SOCK_CLOSED, &con->state); + set_bit(SOCK_CLOSED, &con->flags); rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); sock_release(con->sock); con->sock = NULL; - clear_bit(SOCK_CLOSED, &con->state); + clear_bit(SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; } -- GitLab From 188048bce311ee41e5178bc3255415d0eae28423 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1878/5711] libceph: don't change socket state on sock event Currently the socket state change event handler records an error message on a connection to distinguish a close while connecting from a close while a connection was already established. Changing connection information during handling of a socket event is not very clean, so instead move this assignment inside con_work(), where it can be done during normal connection-level processing (and under protection of the connection mutex as well). Move the handling of a socket closed event up to the top of the processing loop in con_work(); there's no point in handling backoff etc. if we have a newly-closed socket to take care of. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 39653944f21b..56381b973d02 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -261,13 +261,8 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { - if (test_bit(CONNECTING, &con->state)) - con->error_msg = "connection failed"; - else - con->error_msg = "socket closed"; + if (!test_and_set_bit(SOCK_CLOSED, &con->flags)) queue_con(con); - } break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); @@ -2187,6 +2182,14 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: + if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { + if (test_bit(CONNECTING, &con->state)) + con->error_msg = "connection failed"; + else + con->error_msg = "socket closed"; + goto fault; + } + if (test_and_clear_bit(BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, @@ -2216,9 +2219,6 @@ restart: con_close_socket(con); } - if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) - goto fault; - ret = try_read(con); if (ret == -EAGAIN) goto restart; -- GitLab From d65c9e0b9eb43d14ece9dd843506ccba06162ee7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1879/5711] libceph: just set SOCK_CLOSED when state changes When a TCP_CLOSE or TCP_CLOSE_WAIT event occurs, the SOCK_CLOSED connection flag bit is set, and if it had not been previously set queue_con() is called to ensure con_work() will get a chance to handle the changed state. con_work() atomically checks--and if set, clears--the SOCK_CLOSED bit if it was set. This means that even if the bit were set repeatedly, the related processing in con_work() only gets called once per transition of the bit from 0 to 1. What's important then is that we ensure con_work() gets called *at least* once when a socket close event occurs, not that it gets called *exactly* once. The work queue mechanism already takes care of queueing work only if it is not already queued, so there's no need for us to call queue_con() conditionally. So this patch just makes it so the SOCK_CLOSED flag gets set unconditionally in ceph_sock_state_change(). Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 56381b973d02..cebef8560586 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -261,8 +261,8 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - if (!test_and_set_bit(SOCK_CLOSED, &con->flags)) - queue_con(con); + set_bit(SOCK_CLOSED, &con->flags); + queue_con(con); break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); -- GitLab From 456ea46865787283088b23a8a7f69244513b95f0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1880/5711] libceph: don't touch con state in con_close_socket() In con_close_socket(), a connection's SOCK_CLOSED flag gets set and then cleared while its shutdown method is called and its reference gets dropped. Previously, that flag got set only if it had not already been set, so setting it in con_close_socket() might have prevented additional processing being done on a socket being shut down. We no longer set SOCK_CLOSED in the socket event routine conditionally, so setting that bit here no longer provides whatever benefit it might have provided before. A race condition could still leave the SOCK_CLOSED bit set even after we've issued the call to con_close_socket(), so we still clear that bit after shutting the socket down. Add a comment explaining the reason for this. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cebef8560586..cfcca1f5be67 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -392,10 +392,16 @@ static int con_close_socket(struct ceph_connection *con) dout("con_close_socket on %p sock %p\n", con, con->sock); if (!con->sock) return 0; - set_bit(SOCK_CLOSED, &con->flags); rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); sock_release(con->sock); con->sock = NULL; + + /* + * Forcibly clear the SOCK_CLOSE flag. It gets set + * independent of the connection mutex, and we could have + * received a socket close event before we had the chance to + * shut the socket down. + */ clear_bit(SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; -- GitLab From bb9e6bba5d8b85b631390f8dbe8a24ae1ff5b48a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1881/5711] libceph: clear CONNECTING in ceph_con_close() A connection that is closed will no longer be connecting. So clear the CONNECTING state bit in ceph_con_close(). Similarly, if the socket has been closed we no longer are in connecting state (a new connect sequence will need to be initiated). Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cfcca1f5be67..beee382d784e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -462,6 +462,7 @@ void ceph_con_close(struct ceph_connection *con) dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); + clear_bit(CONNECTING, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ set_bit(CLOSED, &con->state); @@ -2189,7 +2190,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_bit(CONNECTING, &con->state)) + if (test_and_clear_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; else con->error_msg = "socket closed"; -- GitLab From 3ec50d1868a9e0493046400bb1fdd054c7f64ebd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 1882/5711] libceph: clear NEGOTIATING when done A connection state's NEGOTIATING bit gets set while in CONNECTING state after we have successfully exchanged a ceph banner and IP addresses with the connection's peer (the server). But that bit is not cleared again--at least not until another connection attempt is initiated. Instead, clear it as soon as the connection is fully established. Also, clear it when a socket connection gets prematurely closed in the midst of establishing a ceph connection (in case we had reached the point where it was set). Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index beee382d784e..500207bad5d6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1562,6 +1562,7 @@ static int process_connect(struct ceph_connection *con) fail_protocol(con); return -1; } + clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; @@ -1951,7 +1952,6 @@ more: /* open the socket first? */ if (con->sock == NULL) { - clear_bit(NEGOTIATING, &con->state); set_bit(CONNECTING, &con->state); con_out_kvec_reset(con); @@ -2190,10 +2190,12 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTING, &con->state)) + if (test_and_clear_bit(CONNECTING, &con->state)) { + clear_bit(NEGOTIATING, &con->state); con->error_msg = "connection failed"; - else + } else { con->error_msg = "socket closed"; + } goto fault; } -- GitLab From e27947c767f5bed15048f4e4dad3e2eb69133697 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 1883/5711] libceph: define and use an explicit CONNECTED state There is no state explicitly defined when a ceph connection is fully operational. So define one. It's set when the connection sequence completes successfully, and is cleared when the connection gets closed. Be a little more careful when examining the old state when a socket disconnect event is reported. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- include/linux/ceph/messenger.h | 1 + net/ceph/messenger.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index cc6f9bdcf466..002d504df3b7 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -120,6 +120,7 @@ struct ceph_msg_pos { */ #define CONNECTING 1 #define NEGOTIATING 2 +#define CONNECTED 5 #define STANDBY 8 /* no outgoing messages, socket closed. we keep * the ceph_connection around to maintain shared * state with the peer. */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 500207bad5d6..83bcf977e9b9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -463,6 +463,7 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); + clear_bit(CONNECTED, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ set_bit(CLOSED, &con->state); @@ -1564,6 +1565,7 @@ static int process_connect(struct ceph_connection *con) } clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); + set_bit(CONNECTED, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; @@ -2114,6 +2116,7 @@ more: prepare_read_ack(con); break; case CEPH_MSGR_TAG_CLOSE: + clear_bit(CONNECTED, &con->state); set_bit(CLOSED, &con->state); /* fixme */ goto out; default: @@ -2190,11 +2193,13 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTING, &con->state)) { + if (test_and_clear_bit(CONNECTED, &con->state)) + con->error_msg = "socket closed"; + else if (test_and_clear_bit(CONNECTING, &con->state)) { clear_bit(NEGOTIATING, &con->state); con->error_msg = "connection failed"; } else { - con->error_msg = "socket closed"; + con->error_msg = "unrecognized con state"; } goto fault; } -- GitLab From ab166d5aa3bc036fba7efaca6e4e43a7e9510acf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 31 May 2012 11:37:29 -0500 Subject: [PATCH 1884/5711] libceph: separate banner and connect writes There are two phases in the process of linking together the two ends of a ceph connection. The first involves exchanging a banner and IP addresses, and if that is successful a second phase exchanges some detail about each side's connection capabilities. When initiating a connection, the client side now queues to send its information for both phases of this process at the same time. This is probably a bit more efficient, but it is slightly messier from a layering perspective in the code. So rearrange things so that the client doesn't send the connection information until it has received and processed the response in the initial banner phase (in process_banner()). Move the code (in the (con->sock == NULL) case in try_write()) that prepares for writing the connection information, delaying doing that until the banner exchange has completed. Move the code that begins the transition to this second "NEGOTIATING" phase out of process_banner() and into its caller, so preparing to write the connection information and preparing to read the response are adjacent to each other. Finally, preparing to write the connection information now requires the output kvec to be reset in all cases, so move that into the prepare_write_connect() and delete it from all callers. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 83bcf977e9b9..5e67be3fa296 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -841,6 +841,7 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; + con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) @@ -1430,8 +1431,6 @@ static int process_banner(struct ceph_connection *con) ceph_pr_addr(&con->msgr->inst.addr.in_addr)); } - set_bit(NEGOTIATING, &con->state); - prepare_read_connect(con); return 0; } @@ -1481,7 +1480,6 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1502,7 +1500,6 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1528,7 +1525,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1545,7 +1541,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1958,9 +1953,6 @@ more: con_out_kvec_reset(con); prepare_write_banner(con); - ret = prepare_write_connect(con); - if (ret < 0) - goto out; prepare_read_banner(con); BUG_ON(con->in_msg); @@ -2073,6 +2065,16 @@ more: ret = process_banner(con); if (ret < 0) goto out; + + /* Banner is good, exchange connection info */ + ret = prepare_write_connect(con); + if (ret < 0) + goto out; + prepare_read_connect(con); + set_bit(NEGOTIATING, &con->state); + + /* Send connection info before awaiting response */ + goto out; } ret = read_partial_connect(con); if (ret <= 0) -- GitLab From 7593af920baac37752190a0db703d2732bed4a3b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 24 May 2012 11:55:03 -0500 Subject: [PATCH 1885/5711] libceph: distinguish two phases of connect sequence Currently a ceph connection enters a "CONNECTING" state when it begins the process of (re-)connecting with its peer. Once the two ends have successfully exchanged their banner and addresses, an additional NEGOTIATING bit is set in the ceph connection's state to indicate the connection information exhange has begun. The CONNECTING bit/state continues to be set during this phase. Rather than have the CONNECTING state continue while the NEGOTIATING bit is set, interpret these two phases as distinct states. In other words, when NEGOTIATING is set, clear CONNECTING. That way only one of them will be active at a time. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 52 ++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5e67be3fa296..32a3a2a72580 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1559,7 +1559,6 @@ static int process_connect(struct ceph_connection *con) return -1; } clear_bit(NEGOTIATING, &con->state); - clear_bit(CONNECTING, &con->state); set_bit(CONNECTED, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; @@ -2000,7 +1999,8 @@ more_kvec: } do_next: - if (!test_bit(CONNECTING, &con->state)) { + if (!test_bit(CONNECTING, &con->state) && + !test_bit(NEGOTIATING, &con->state)) { /* is anything else pending? */ if (!list_empty(&con->out_queue)) { prepare_write_message(con); @@ -2057,25 +2057,29 @@ more: } if (test_bit(CONNECTING, &con->state)) { - if (!test_bit(NEGOTIATING, &con->state)) { - dout("try_read connecting\n"); - ret = read_partial_banner(con); - if (ret <= 0) - goto out; - ret = process_banner(con); - if (ret < 0) - goto out; - - /* Banner is good, exchange connection info */ - ret = prepare_write_connect(con); - if (ret < 0) - goto out; - prepare_read_connect(con); - set_bit(NEGOTIATING, &con->state); - - /* Send connection info before awaiting response */ + dout("try_read connecting\n"); + ret = read_partial_banner(con); + if (ret <= 0) goto out; - } + ret = process_banner(con); + if (ret < 0) + goto out; + + clear_bit(CONNECTING, &con->state); + set_bit(NEGOTIATING, &con->state); + + /* Banner is good, exchange connection info */ + ret = prepare_write_connect(con); + if (ret < 0) + goto out; + prepare_read_connect(con); + + /* Send connection info before awaiting response */ + goto out; + } + + if (test_bit(NEGOTIATING, &con->state)) { + dout("try_read negotiating\n"); ret = read_partial_connect(con); if (ret <= 0) goto out; @@ -2197,12 +2201,12 @@ restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { if (test_and_clear_bit(CONNECTED, &con->state)) con->error_msg = "socket closed"; - else if (test_and_clear_bit(CONNECTING, &con->state)) { - clear_bit(NEGOTIATING, &con->state); + else if (test_and_clear_bit(NEGOTIATING, &con->state)) + con->error_msg = "negotiation failed"; + else if (test_and_clear_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; - } else { + else con->error_msg = "unrecognized con state"; - } goto fault; } -- GitLab From 5821bd8ccdf5d17ab2c391c773756538603838c3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1886/5711] libceph: small changes to messenger.c This patch gathers a few small changes in "net/ceph/messenger.c": out_msg_pos_next() - small logic change that mostly affects indentation write_partial_msg_pages(). - use a local variable trail_off to represent the offset into a message of the trail portion of the data (if present) - once we are in the trail portion we will always be there, so we don't always need to check against our data position - avoid computing len twice after we've reached the trail - get rid of the variable tmpcrc, which is not needed - trail_off and trail_len never change so mark them const - update some comments read_partial_message_bio() - bio_iovec_idx() will never return an error, so don't bother checking for it Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 63 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 32a3a2a72580..4578e99bbef1 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -907,21 +907,23 @@ static void out_msg_pos_next(struct ceph_connection *con, struct page *page, con->out_msg_pos.data_pos += sent; con->out_msg_pos.page_pos += sent; - if (sent == len) { - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.page++; - con->out_msg_pos.did_page_crc = false; - if (in_trail) - list_move_tail(&page->lru, - &msg->trail->head); - else if (msg->pagelist) - list_move_tail(&page->lru, - &msg->pagelist->head); + if (sent < len) + return; + + BUG_ON(sent != len); + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.page++; + con->out_msg_pos.did_page_crc = false; + if (in_trail) + list_move_tail(&page->lru, + &msg->trail->head); + else if (msg->pagelist) + list_move_tail(&page->lru, + &msg->pagelist->head); #ifdef CONFIG_BLOCK - else if (msg->bio) - iter_bio_next(&msg->bio_iter, &msg->bio_seg); + else if (msg->bio) + iter_bio_next(&msg->bio_iter, &msg->bio_seg); #endif - } } /* @@ -940,30 +942,31 @@ static int write_partial_msg_pages(struct ceph_connection *con) int ret; int total_max_write; bool in_trail = false; - size_t trail_len = (msg->trail ? msg->trail->length : 0); + const size_t trail_len = (msg->trail ? msg->trail->length : 0); + const size_t trail_off = data_len - trail_len; dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); + /* + * Iterate through each page that contains data to be + * written, and send as much as possible for each. + * + * If we are calculating the data crc (the default), we will + * need to map the page. If we have no pages, they have + * been revoked, so use the zero page. + */ while (data_len > con->out_msg_pos.data_pos) { struct page *page = NULL; int max_write = PAGE_SIZE; int bio_offset = 0; - total_max_write = data_len - trail_len - - con->out_msg_pos.data_pos; - - /* - * if we are calculating the data crc (the default), we need - * to map the page. if our pages[] has been revoked, use the - * zero page. - */ - - /* have we reached the trail part of the data? */ - if (con->out_msg_pos.data_pos >= data_len - trail_len) { - in_trail = true; + in_trail = in_trail || con->out_msg_pos.data_pos >= trail_off; + if (!in_trail) + total_max_write = trail_off - con->out_msg_pos.data_pos; + if (in_trail) { total_max_write = data_len - con->out_msg_pos.data_pos; page = list_first_entry(&msg->trail->head, @@ -990,14 +993,13 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (do_datacrc && !con->out_msg_pos.did_page_crc) { void *base; - u32 crc; - u32 tmpcrc = le32_to_cpu(msg->footer.data_crc); + u32 crc = le32_to_cpu(msg->footer.data_crc); char *kaddr; kaddr = kmap(page); BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; - crc = crc32c(tmpcrc, base, len); + crc = crc32c(crc, base, len); msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } @@ -1702,9 +1704,6 @@ static int read_partial_message_bio(struct ceph_connection *con, void *p; int ret, left; - if (IS_ERR(bv)) - return PTR_ERR(bv); - left = min((int)(data_len - con->in_msg_pos.data_pos), (int)(bv->bv_len - con->in_msg_pos.page_pos)); -- GitLab From bc18f4b1c850ab355e38373fbb60fd28568d84b5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1887/5711] libceph: add some fine ASCII art Sage liked the state diagram I put in my commit description so I'm putting it in with the code. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/messenger.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 4578e99bbef1..dcc50e4cd5cd 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -29,7 +29,47 @@ * the sender. */ -/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */ +/* + * We track the state of the socket on a given connection using + * values defined below. The transition to a new socket state is + * handled by a function which verifies we aren't coming from an + * unexpected state. + * + * -------- + * | NEW* | transient initial state + * -------- + * | con_sock_state_init() + * v + * ---------- + * | CLOSED | initialized, but no socket (and no + * ---------- TCP connection) + * ^ \ + * | \ con_sock_state_connecting() + * | ---------------------- + * | \ + * + con_sock_state_closed() \ + * |\ \ + * | \ \ + * | ----------- \ + * | | CLOSING | socket event; \ + * | ----------- await close \ + * | ^ | + * | | | + * | + con_sock_state_closing() | + * | / \ | + * | / --------------- | + * | / \ v + * | / -------------- + * | / -----------------| CONNECTING | socket created, TCP + * | | / -------------- connect initiated + * | | | con_sock_state_connected() + * | | v + * ------------- + * | CONNECTED | TCP connection established + * ------------- + * + * State values for ceph_connection->sock_state; NEW is assumed to be 0. + */ #define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ #define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ -- GitLab From 261030215d970c62f799e6e508e3c68fc7ec2aa9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 21 Jun 2012 12:49:23 -0700 Subject: [PATCH 1888/5711] libceph: drop declaration of ceph_con_get() For some reason the declaration of ceph_con_get() and ceph_con_put() did not get deleted in this commit: d59315ca libceph: drop ceph_con_get/put helpers and nref member Clean that up. Signed-off-by: Alex Elder --- include/linux/ceph/messenger.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 002d504df3b7..dd4ef1f8ec93 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -244,8 +244,6 @@ extern void ceph_msg_revoke(struct ceph_msg *msg); extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); extern void ceph_con_keepalive(struct ceph_connection *con); -extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); -extern void ceph_con_put(struct ceph_connection *con); extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, bool can_fail); -- GitLab From b7a9e5dd40f17a48a72f249b8bbc989b63bae5fd Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:24:08 -0700 Subject: [PATCH 1889/5711] libceph: set peer name on con_open, not init The peer name may change on each open attempt, even when the connection is reused. Signed-off-by: Sage Weil --- fs/ceph/mds_client.c | 7 ++++--- include/linux/ceph/messenger.h | 4 ++-- net/ceph/messenger.c | 12 +++++++----- net/ceph/mon_client.c | 4 ++-- net/ceph/osd_client.c | 10 ++++++---- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index ecd7f15741c1..5ac6434185ae 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,8 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr, - CEPH_ENTITY_TYPE_MDS, mds); + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr); spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; @@ -437,7 +436,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, mdsc->sessions[mds] = s; atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */ - ceph_con_open(&s->s_con, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); + ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds, + ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); return s; @@ -2529,6 +2529,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, session->s_seq = 0; ceph_con_open(&session->s_con, + CEPH_ENTITY_TYPE_MDS, mds, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); /* replay unsafe requests */ diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index dd4ef1f8ec93..478f814f2100 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -232,9 +232,9 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, extern void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, - struct ceph_messenger *msgr, __u8 entity_type, - __u64 entity_num); + struct ceph_messenger *msgr); extern void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, struct ceph_entity_addr *addr); extern bool ceph_con_opened(struct ceph_connection *con); extern void ceph_con_close(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index dcc50e4cd5cd..ae082d95fc72 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -523,12 +523,17 @@ EXPORT_SYMBOL(ceph_con_close); /* * Reopen a closed connection, with a new peer address. */ -void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) +void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, + struct ceph_entity_addr *addr) { dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + con->peer_name.type = (__u8) entity_type; + con->peer_name.num = cpu_to_le64(entity_num); + memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ queue_con(con); @@ -548,7 +553,7 @@ bool ceph_con_opened(struct ceph_connection *con) */ void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, - struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num) + struct ceph_messenger *msgr) { dout("con_init %p\n", con); memset(con, 0, sizeof(*con)); @@ -558,9 +563,6 @@ void ceph_con_init(struct ceph_connection *con, void *private, con_sock_state_init(con); - con->peer_name.type = (__u8) entity_type; - con->peer_name.num = cpu_to_le64(entity_num); - mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index e9db3de20b2e..bcc80a0e2a98 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -143,11 +143,11 @@ static int __open_session(struct ceph_mon_client *monc) monc->want_next_osdmap = !!monc->want_next_osdmap; ceph_con_init(&monc->con, monc, &mon_con_ops, - &monc->client->msgr, - CEPH_ENTITY_TYPE_MON, monc->cur_mon); + &monc->client->msgr); dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, + CEPH_ENTITY_TYPE_MON, monc->cur_mon, &monc->monmap->mon_inst[monc->cur_mon].addr); /* initiatiate authentication handshake */ diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index db2da54f7336..c2527113d2ae 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -639,8 +639,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr, - CEPH_ENTITY_TYPE_OSD, onum); + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; @@ -750,7 +749,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) ret = -EAGAIN; } else { ceph_con_close(&osd->o_con); - ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]); + ceph_con_open(&osd->o_con, CEPH_ENTITY_TYPE_OSD, osd->o_osd, + &osdc->osdmap->osd_addr[osd->o_osd]); osd->o_incarnation++; } return ret; @@ -1005,7 +1005,9 @@ static int __map_request(struct ceph_osd_client *osdc, dout("map_request osd %p is osd%d\n", req->r_osd, o); __insert_osd(osdc, req->r_osd); - ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); + ceph_con_open(&req->r_osd->o_con, + CEPH_ENTITY_TYPE_OSD, o, + &osdc->osdmap->osd_addr[o]); } if (req->r_osd) { -- GitLab From 735a72ef952d42a256f79ae3e6dc1c17a45c041b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:24:34 -0700 Subject: [PATCH 1890/5711] libceph: initialize mon_client con only once Do not re-initialize the con on every connection attempt. When we ceph_con_close, there may still be work queued on the socket (e.g., to close it), and re-initializing will clobber the work_struct state. Signed-off-by: Sage Weil --- net/ceph/mon_client.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index bcc80a0e2a98..bfd21a891d69 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -119,7 +119,6 @@ static void __close_session(struct ceph_mon_client *monc) dout("__close_session closing mon%d\n", monc->cur_mon); ceph_msg_revoke(monc->m_auth); ceph_con_close(&monc->con); - monc->con.private = NULL; monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -142,9 +141,6 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - ceph_con_init(&monc->con, monc, &mon_con_ops, - &monc->client->msgr); - dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, CEPH_ENTITY_TYPE_MON, monc->cur_mon, @@ -798,6 +794,9 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) if (!monc->m_auth) goto out_auth_reply; + ceph_con_init(&monc->con, monc, &mon_con_ops, + &monc->client->msgr); + monc->cur_mon = -1; monc->hunting = true; monc->sub_renew_after = jiffies; -- GitLab From fbb85a478f6d4cce6942f1c25c6a68ec5b1e7e7f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:31:02 -0700 Subject: [PATCH 1891/5711] libceph: allow sock transition from CONNECTING to CLOSED It is possible to close a socket that is in the OPENING state. For example, it can happen if ceph_con_close() is called on the con before the TCP connection is established. con_work() will come around and shut down the socket. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ae082d95fc72..09ada7924874 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -48,17 +48,17 @@ * | ---------------------- * | \ * + con_sock_state_closed() \ - * |\ \ - * | \ \ - * | ----------- \ - * | | CLOSING | socket event; \ - * | ----------- await close \ - * | ^ | - * | | | - * | + con_sock_state_closing() | - * | / \ | - * | / --------------- | - * | / \ v + * |+--------------------------- \ + * | \ \ \ + * | ----------- \ \ + * | | CLOSING | socket event; \ \ + * | ----------- await close \ \ + * | ^ \ | + * | | \ | + * | + con_sock_state_closing() \ | + * | / \ | | + * | / --------------- | | + * | / \ v v * | / -------------- * | / -----------------| CONNECTING | socket created, TCP * | | / -------------- connect initiated @@ -241,7 +241,8 @@ static void con_sock_state_closed(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && - old_state != CON_SOCK_STATE_CLOSING)) + old_state != CON_SOCK_STATE_CLOSING && + old_state != CON_SOCK_STATE_CONNECTING)) printk("%s: unexpected old state %d\n", __func__, old_state); } -- GitLab From 460a4de77d3b8f82fce98a9ed10e10464f767f97 Mon Sep 17 00:00:00 2001 From: David Dillow Date: Mon, 18 Jun 2012 00:20:06 -0300 Subject: [PATCH 1892/5711] [media] cx231xx: use TRANSFER_TYPE enum for cleanup Most calls to cx231xx_capture_start() already use the values from TRANSFER_TYPE, but cx231xx_capture_start() and cx231xx_initialize_stream_xfer() were hand coding the values. Use the named values (81 is never passed in), and simplify cx231xx_capture_start(), as the switch statements were identical and pcb_config->config_num is a u8, so any non-zero config got the same result. Signed-off-by: David Dillow Cc: Sri Deevi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-avcore.c | 56 ++++++-------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index b085a3c6dc04..447148eff958 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -89,7 +89,7 @@ void initGPIO(struct cx231xx *dev) verve_read_byte(dev, 0x07, &val); cx231xx_info(" verve_read_byte address0x07=0x%x\n", val); - cx231xx_capture_start(dev, 1, 2); + cx231xx_capture_start(dev, 1, Vbi); cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00); cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF); @@ -99,7 +99,7 @@ void uninitGPIO(struct cx231xx *dev) { u8 value[4] = { 0, 0, 0, 0 }; - cx231xx_capture_start(dev, 0, 2); + cx231xx_capture_start(dev, 0, Vbi); verve_write_byte(dev, 0x07, 0x14); cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, 0x68, value, 4); @@ -2516,29 +2516,29 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) if (dev->udev->speed == USB_SPEED_HIGH) { switch (media_type) { - case 81: /* audio */ + case Audio: cx231xx_info("%s: Audio enter HANC\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); break; - case 2: /* vbi */ + case Vbi: cx231xx_info("%s: set vanc registers\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); break; - case 3: /* sliced cc */ + case Sliced_cc: cx231xx_info("%s: set hanc registers\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); break; - case 0: /* video */ + case Raw_Video: cx231xx_info("%s: set video registers\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); break; - case 4: /* ts1 */ + case TS1_serial_mode: cx231xx_info("%s: set ts1 registers", __func__); if (dev->board.has_417) { @@ -2569,7 +2569,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) } break; - case 6: /* ts1 parallel mode */ + case TS1_parallel_mode: cx231xx_info("%s: set ts1 parallel mode registers\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); @@ -2592,52 +2592,28 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) /* get EP for media type */ pcb_config = (struct pcb_config *)&dev->current_pcb_config; - if (pcb_config->config_num == 1) { + if (pcb_config->config_num) { switch (media_type) { - case 0: /* Video */ + case Raw_Video: ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ break; - case 1: /* Audio */ + case Audio: ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ break; - case 2: /* Vbi */ + case Vbi: ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ break; - case 3: /* Sliced_cc */ + case Sliced_cc: ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ break; - case 4: /* ts1 */ - case 6: /* ts1 parallel mode */ + case TS1_serial_mode: + case TS1_parallel_mode: ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ break; - case 5: /* ts2 */ + case TS2: ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ break; } - - } else if (pcb_config->config_num > 1) { - switch (media_type) { - case 0: /* Video */ - ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ - break; - case 1: /* Audio */ - ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ - break; - case 2: /* Vbi */ - ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ - break; - case 3: /* Sliced_cc */ - ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ - break; - case 4: /* ts1 */ - case 6: /* ts1 parallel mode */ - ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ - break; - case 5: /* ts2 */ - ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ - break; - } - } if (start) { -- GitLab From cd5534be6bc681d6a5ca62b3b6066ff8515e1aac Mon Sep 17 00:00:00 2001 From: David Dillow Date: Mon, 18 Jun 2012 00:15:21 -0300 Subject: [PATCH 1893/5711] [media] cx231xx: don't DMA to random addresses Commit 7a6f6c29d264cdd2fe0eb3d923217eed5f0ad134 (cx231xx: use URB_NO_TRANSFER_DMA_MAP) was intended to avoid mapping the DMA buffer for URB twice. This works for the URBs allocated with usb_alloc_urb(), as those are allocated from cohernent DMA pools, but the flag was also added for the VBI and audio URBs, which have a manually allocated area. This leaves the random trash in the structure after allocation as the DMA address, corrupting memory and preventing VBI and audio from working. Letting the USB core map the buffers solves the problem. Signed-off-by: David Dillow Cc: Sri Deevi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-audio.c | 4 ++-- drivers/media/video/cx231xx/cx231xx-vbi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index 068f78dc5d13..b4c99c7270cf 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c @@ -307,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; urb->complete = cx231xx_audio_isocirq; @@ -368,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvbulkpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->complete = cx231xx_audio_bulkirq; urb->transfer_buffer_length = sb_size; diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 3d15314e1f88..ac7db52f404f 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -448,7 +448,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, return -ENOMEM; } dev->vbi_mode.bulk_ctl.urb[i] = urb; - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; dev->vbi_mode.bulk_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); -- GitLab From 89d71486b293565aa345e1b722647cb29ade465c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 5 Jul 2012 15:18:50 +0200 Subject: [PATCH 1894/5711] sh: select the fixed regulator driver on several boards On systems, using regulators to supply power to devices, if the REGULATOR Kconfig option is disabled, regulator API stubs will be used, which often suffices to bring a default configuration up. If REGULATOR is enabled but respective regulator drivers are inactive, the real regulator API calls will be used, which in the absence of drivers will fail to provide services. This patch prevents such a problem on sh-mobile boards by forcing REGULATOR_FIXED_VOLTAGE on if REGULATOR is selected. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 1f56b35d3248..6047f9436990 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -55,6 +55,7 @@ config SH_7724_SOLUTION_ENGINE depends on CPU_SUBTYPE_SH7724 select ARCH_REQUIRE_GPIOLIB select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Select 7724 SolutionEngine if configuring for a Hitachi SH7724 evaluation board. @@ -136,6 +137,7 @@ config SH_RSK bool "Renesas Starter Kit" depends on CPU_SUBTYPE_SH7201 || CPU_SUBTYPE_SH7203 || \ CPU_SUBTYPE_SH7264 || CPU_SUBTYPE_SH7269 + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Select this option if configuring for any of the RSK+ MCU evaluation platforms. @@ -155,6 +157,7 @@ config SH_SDK7786 select NO_IOPORT if !PCI select ARCH_WANT_OPTIONAL_GPIOLIB select HAVE_SRAM_POOL + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Select SDK7786 if configuring for a Renesas Technology Europe SH7786-65nm board. @@ -169,6 +172,7 @@ config SH_SH7757LCR bool "SH7757LCR" depends on CPU_SUBTYPE_SH7757 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR config SH_SH7785LCR bool "SH7785LCR" @@ -202,6 +206,7 @@ config SH_MIGOR bool "Migo-R" depends on CPU_SUBTYPE_SH7722 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Select Migo-R if configuring for the SH7722 Migo-R platform by Renesas System Solutions Asia Pte. Ltd. @@ -210,6 +215,7 @@ config SH_AP325RXA bool "AP-325RXA" depends on CPU_SUBTYPE_SH7723 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Renesas "AP-325RXA" support. Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" @@ -218,6 +224,7 @@ config SH_KFR2R09 bool "KFR2R09" depends on CPU_SUBTYPE_SH7724 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR help "Kit For R2R for 2009" support. @@ -226,6 +233,7 @@ config SH_ECOVEC depends on CPU_SUBTYPE_SH7724 select ARCH_REQUIRE_GPIOLIB select SND_SOC_DA7210 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Renesas "R0P7724LC0011/21RL (EcoVec)" support. @@ -300,6 +308,7 @@ config SH_MAGIC_PANEL_R2 bool "Magic Panel R2" depends on CPU_SUBTYPE_SH7720 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR help Select Magic Panel R2 if configuring for Magic Panel R2. @@ -311,6 +320,7 @@ config SH_CAYMAN config SH_POLARIS bool "SMSC Polaris" select CPU_HAS_IPR_IRQ + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on CPU_SUBTYPE_SH7709 help Select if configuring for an SMSC Polaris development board @@ -318,6 +328,7 @@ config SH_POLARIS config SH_SH2007 bool "SH-2007 board" select NO_IOPORT + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on CPU_SUBTYPE_SH7780 help SH-2007 is a single-board computer based around SH7780 chip @@ -329,6 +340,7 @@ config SH_SH2007 config SH_APSH4A3A bool "AP-SH4A-3A" select SH_ALPHA_BOARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on CPU_SUBTYPE_SH7785 help Select AP-SH4A-3A if configuring for an ALPHAPROJECT AP-SH4A-3A. @@ -337,6 +349,7 @@ config SH_APSH4AD0A bool "AP-SH4AD-0A" select SH_ALPHA_BOARD select SYS_SUPPORTS_PCI + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on CPU_SUBTYPE_SH7786 help Select AP-SH4AD-0A if configuring for an ALPHAPROJECT AP-SH4AD-0A. -- GitLab From c455f5c85ab79d065d09915e73c643f4cfa0eb16 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Jul 2012 09:12:59 -0300 Subject: [PATCH 1895/5711] [media] Kconfig: Split the core support options from the driver ones Better arrange the remote controller driver items to happen after the core support, on their proper menus, and making clerarer what is media core options and what is media driver options. Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 3 ++- drivers/media/rc/Kconfig | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 6d10ccb692a9..d941581ab921 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -59,7 +59,7 @@ config MEDIA_RADIO_SUPPORT support radio reception. Disabling this option will disable support for them. -menuconfig MEDIA_RC_SUPPORT +config MEDIA_RC_SUPPORT bool "Remote Controller support" depends on INPUT ---help--- @@ -138,6 +138,7 @@ config DVB_NET You may want to disable the network support on embedded devices. If unsure say Y. +comment "Media drivers" source "drivers/media/common/Kconfig" source "drivers/media/rc/Kconfig" diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index d2655f103faa..2478b06a768b 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -4,6 +4,14 @@ config RC_CORE depends on INPUT default y +source "drivers/media/rc/keymaps/Kconfig" + +menuconfig RC_DECODERS + bool "Remote controller decoders" + depends on RC_CORE + default y + +if RC_DECODERS config LIRC tristate "LIRC interface driver" depends on RC_CORE @@ -15,8 +23,6 @@ config LIRC LIRC daemon handles protocol decoding for IR reception and encoding for IR transmitting (aka "blasting"). -source "drivers/media/rc/keymaps/Kconfig" - config IR_NEC_DECODER tristate "Enable IR raw decoder for the NEC protocol" depends on RC_CORE @@ -99,6 +105,7 @@ config IR_MCE_KBD_DECODER Enable this option if you have a Microsoft Remote Keyboard for Windows Media Center Edition, which you would like to use with a raw IR receiver in your system. +endif #RC_DECODERS menuconfig RC_DEVICES bool "Remote Controller devices" -- GitLab From bf6c973440f2a21ab168fb34d3b4db2590bcd72a Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 6 Jul 2012 07:16:14 -0500 Subject: [PATCH 1896/5711] of: fix a few typos in the binding documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König [rob herring: drop conflicting atmel-nand.txt changes] Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mtd/partition.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt index f114ce1657c2..6e1f61f1e789 100644 --- a/Documentation/devicetree/bindings/mtd/partition.txt +++ b/Documentation/devicetree/bindings/mtd/partition.txt @@ -35,4 +35,4 @@ flash@0 { uimage@100000 { reg = <0x0100000 0x200000>; }; -]; +}; -- GitLab From 177259c3ecca713b5995988309ea0ffd7383c286 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 23 Jun 2012 20:41:17 +0200 Subject: [PATCH 1897/5711] LED: Fix missing semicolon in OF documentation Trivial fix Signed-off-by: Marek Vasut Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/gpio/led.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/gpio/led.txt index fd2bd56e7195..9bb308abd221 100644 --- a/Documentation/devicetree/bindings/gpio/led.txt +++ b/Documentation/devicetree/bindings/gpio/led.txt @@ -55,4 +55,4 @@ run-control { gpios = <&mpc8572 7 0>; default-state = "on"; }; -} +}; -- GitLab From a3a7cab17d36bb591867a6d3ea41b5fdb4e44d87 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 27 Jun 2012 09:44:45 +0530 Subject: [PATCH 1898/5711] of: Fix null pointer related warnings in base.c file Fixes the following sparse warnings: drivers/of/base.c:176:41: warning: Using plain integer as NULL pointer drivers/of/base.c:178:37: warning: Using plain integer as NULL pointer drivers/of/base.c:500:49: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Rob Herring --- drivers/of/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index d9bfd49b1935..ddba57799fd7 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -173,9 +173,9 @@ struct property *of_find_property(const struct device_node *np, return NULL; read_lock(&devtree_lock); - for (pp = np->properties; pp != 0; pp = pp->next) { + for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { - if (lenp != 0) + if (lenp) *lenp = pp->length; break; } @@ -497,7 +497,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np; np = np->allnext) { - for (pp = np->properties; pp != 0; pp = pp->next) { + for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, prop_name) == 0) { of_node_get(np); goto out; -- GitLab From 5d781108bc6524b92d6a6789e852b8a7e96aa3f3 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 29 Jun 2012 12:44:46 +0200 Subject: [PATCH 1899/5711] usage-model.txt: fix typo machine_init->init_machine machine_init was used intead of init_machine which clearly was not intended. Signed-off-by: Richard Genoud Signed-off-by: Rob Herring --- Documentation/devicetree/usage-model.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/usage-model.txt b/Documentation/devicetree/usage-model.txt index c5a80099b71c..dca90fe22a90 100644 --- a/Documentation/devicetree/usage-model.txt +++ b/Documentation/devicetree/usage-model.txt @@ -312,7 +312,7 @@ device tree for the NVIDIA Tegra board. }; }; -At .machine_init() time, Tegra board support code will need to look at +At .init_machine() time, Tegra board support code will need to look at this DT and decide which nodes to create platform_devices for. However, looking at the tree, it is not immediately obvious what kind of device each node represents, or even if a node represents a device -- GitLab From 1af4c7f18a442771d86d496c761e9816349f98c9 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 29 Jun 2012 13:57:58 +0900 Subject: [PATCH 1900/5711] of: return -ENOENT when no property Make of_parse_phandle_with_args return -ENOENT instead of -EINVAL when no matching property is found, which allows to discriminate between absence of property and parsing error. Signed-off-by: Alexandre Courbot Signed-off-by: Rob Herring --- drivers/of/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ddba57799fd7..85757952f12d 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -902,7 +902,7 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name, /* Retrieve the phandle list property */ list = of_get_property(np, list_name, &size); if (!list) - return -EINVAL; + return -ENOENT; list_end = list + size / sizeof(*list); /* Loop over the phandles until all the requested entry is found */ -- GitLab From 74a7f08448adea6cb47cd9b260c98ff168117e92 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 15 Jun 2012 11:50:25 -0600 Subject: [PATCH 1901/5711] devicetree: add helper inline for retrieving a node's full name The pattern (np ? np->full_name : "") is rather common in the kernel, but can also make for quite long lines. This patch adds a new inline function, of_node_full_name() so that the test for a valid node pointer doesn't need to be open coded at all call sites. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Signed-off-by: Rob Herring --- arch/microblaze/pci/pci-common.c | 6 ++---- arch/powerpc/kernel/pci-common.c | 6 ++---- arch/powerpc/kernel/vio.c | 5 ++--- arch/powerpc/platforms/cell/iommu.c | 3 +-- arch/powerpc/platforms/pseries/iommu.c | 2 +- arch/sparc/kernel/of_device_64.c | 2 +- drivers/of/base.c | 2 +- drivers/of/irq.c | 2 +- include/linux/of.h | 10 ++++++++++ kernel/irq/irqdomain.c | 8 ++++---- 10 files changed, 25 insertions(+), 21 deletions(-) diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db14..ca8f6e769960 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev) } else { pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller ? oirq.controller->full_name : - ""); + of_node_full_name(oirq.controller)); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -1493,8 +1492,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) struct pci_bus *bus; struct device_node *node = hose->dn; - pr_debug("PCI: Scanning PHB %s\n", - node ? node->full_name : ""); + pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); pcibios_setup_phb_resources(hose, &resources); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c8185..886c254fd565 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) } else { pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller ? oirq.controller->full_name : - ""); + of_node_full_name(oirq.controller)); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) struct device_node *node = hose->dn; int mode; - pr_debug("PCI: Scanning PHB %s\n", - node ? node->full_name : ""); + pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); /* Get some IO space for the new PHB */ pcibios_setup_phb_io_space(hose); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb87301ccd55..63f72ede4341 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1296,8 +1296,7 @@ static void __devinit vio_dev_release(struct device *dev) struct iommu_table *tbl = get_iommu_table_base(dev); if (tbl) - iommu_free_table(tbl, dev->of_node ? - dev->of_node->full_name : dev_name(dev)); + iommu_free_table(tbl, of_node_full_name(dev->of_node)); of_node_put(dev->of_node); kfree(to_vio_dev(dev)); } @@ -1509,7 +1508,7 @@ static ssize_t devspec_show(struct device *dev, { struct device_node *of_node = dev->of_node; - return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); + return sprintf(buf, "%s\n", of_node_full_name(of_node)); } static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index b9f509a34c01..b6732004c882 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) iommu = cell_iommu_for_node(dev_to_node(dev)); if (iommu == NULL || list_empty(&iommu->windows)) { printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", - dev->of_node ? dev->of_node->full_name : "?", - dev_to_node(dev)); + of_node_full_name(dev->of_node), dev_to_node(dev)); return NULL; } window = list_entry(iommu->windows.next, struct iommu_window, list); diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2d311c0caf8e..6b58a395dff6 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) if (!pdn || !PCI_DN(pdn)) { printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " "no DMA window found for pci dev=%s dn=%s\n", - pci_name(dev), dn? dn->full_name : ""); + pci_name(dev), of_node_full_name(dn)); return; } pr_debug(" parent is %s\n", pdn->full_name); diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 7a3be6f6737a..7bbdc26d9512 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -580,7 +580,7 @@ static unsigned int __init build_one_device_irq(struct platform_device *op, printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", op->dev.of_node->full_name, pp->full_name, this_orig_irq, - (iret ? iret->full_name : "NULL"), irq); + of_node_full_name(iret), irq); if (!iret) break; diff --git a/drivers/of/base.c b/drivers/of/base.c index 85757952f12d..9ec0a2f1b028 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1173,7 +1173,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, ap->stem[stem_len] = 0; list_add_tail(&ap->link, &aliases_lookup); pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", - ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); + ap->alias, ap->stem, ap->id, of_node_full_name(np)); } /** diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9cf00602f566..ff8ab7b27373 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, skiplevel: /* Iterate again with new parent */ - pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); + pr_debug(" -> new parent: %s\n", of_node_full_name(newpar)); of_node_put(ipar); ipar = newpar; newpar = NULL; diff --git a/include/linux/of.h b/include/linux/of.h index 2ec1083af7ff..1012377cae92 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -163,6 +163,11 @@ static inline int of_node_to_nid(struct device_node *np) { return -1; } #define of_node_to_nid of_node_to_nid #endif +static inline const char* of_node_full_name(struct device_node *np) +{ + return np ? np->full_name : ""; +} + extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); #define for_each_node_by_name(dn, name) \ @@ -303,6 +308,11 @@ const char *of_prop_next_string(struct property *prop, const char *cur); #else /* CONFIG_OF */ +static inline const char* of_node_full_name(struct device_node *np) +{ + return ""; +} + static inline bool of_have_populated_dt(void) { return false; diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 41c1564103f1..38c5eb839c92 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, } pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", - hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); + hwirq, of_node_full_name(domain->of_node), virq); return virq; } @@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, return intspec[0]; #endif pr_warning("no irq domain found for %s !\n", - controller->full_name); + of_node_full_name(controller)); return 0; } @@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_file *m, void *private) data = irq_desc_get_chip_data(desc); seq_printf(m, data ? "0x%p " : " %p ", data); - if (desc->irq_data.domain && desc->irq_data.domain->of_node) - p = desc->irq_data.domain->of_node->full_name; + if (desc->irq_data.domain) + p = of_node_full_name(desc->irq_data.domain->of_node); else p = none; seq_printf(m, "%s\n", p); -- GitLab From 94f74767160ab0d288f3b416971cf259f2a38b3d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Jul 2012 09:21:13 -0300 Subject: [PATCH 1902/5711] [media] rc/Kconfig: Move a LIRC sub-option to the right place The IR to LIRC option were at the wrong sub-menu. Move it to the right place. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 2478b06a768b..908ef70430e9 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -23,6 +23,17 @@ config LIRC LIRC daemon handles protocol decoding for IR reception and encoding for IR transmitting (aka "blasting"). +config IR_LIRC_CODEC + tristate "Enable IR to LIRC bridge" + depends on RC_CORE + depends on LIRC + default y + + ---help--- + Enable this option to pass raw IR to and from userspace via + the LIRC interface. + + config IR_NEC_DECODER tristate "Enable IR raw decoder for the NEC protocol" depends on RC_CORE @@ -113,16 +124,6 @@ menuconfig RC_DEVICES if RC_DEVICES -config IR_LIRC_CODEC - tristate "Enable IR to LIRC bridge" - depends on RC_CORE - depends on LIRC - default y - - ---help--- - Enable this option to pass raw IR to and from userspace via - the LIRC interface. - config RC_ATI_REMOTE tristate "ATI / X10 based USB RF remote controls" depends on USB_ARCH_HAS_HCD -- GitLab From 81059812c246cc4308447c0f2964c0b26d963778 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Jul 2012 10:41:53 -0300 Subject: [PATCH 1903/5711] [media] uvc/Kconfig: Fix INPUT/EVDEV dependencies USB_VIDEO_CLASS_INPUT_EVDEV should be dependent on the UVC selection, as otherwise, when UVC is unselected, this dependent config still appears. Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig index 6c197da531b2..541c9f1e4c6a 100644 --- a/drivers/media/video/uvc/Kconfig +++ b/drivers/media/video/uvc/Kconfig @@ -10,6 +10,7 @@ config USB_VIDEO_CLASS config USB_VIDEO_CLASS_INPUT_EVDEV bool "UVC input events device support" default y + depends on USB_VIDEO_CLASS depends on USB_VIDEO_CLASS=INPUT || INPUT=y ---help--- This option makes USB Video Class devices register an input device -- GitLab From ab9cbcd36ce2f2d10de1610abeaa89ee0b619ae7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jun 2012 15:34:22 -0300 Subject: [PATCH 1904/5711] [media] tuner-xc2028: tag the usual firmwares to help dracut When tuner-xc2028 is not compiled as a module, dracut will need to copy the firmware inside the initfs image. So, use MODULE_FIRMWARE() to indicate such need. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tuner-xc2028.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 4857e86259a1..f88f948efee2 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -1506,3 +1506,5 @@ MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver"); MODULE_AUTHOR("Michel Ludwig "); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE); +MODULE_FIRMWARE(XC3028L_DEFAULT_FIRMWARE); -- GitLab From e864abed546f9f4b76a3580fb3c53cd389e0c015 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Jun 2012 16:49:42 +0900 Subject: [PATCH 1905/5711] USB: ohci-exynos: add clock gating to suspend/resume This patch adds clock gating to suspend and resume functions. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-exynos.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 2909621ea196..fedb0eff35d5 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -225,6 +225,9 @@ static int exynos_ohci_suspend(struct device *dev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + + clk_disable(exynos_ohci->clk); + fail: spin_unlock_irqrestore(&ohci->lock, flags); @@ -238,6 +241,8 @@ static int exynos_ohci_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + clk_enable(exynos_ohci->clk); + if (pdata && pdata->phy_init) pdata->phy_init(pdev, S5P_USB_PHY_HOST); -- GitLab From 390a0a78067c487609ba5bd18c264f7d5b6f4e96 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Jun 2012 16:30:30 +0900 Subject: [PATCH 1906/5711] USB: ohci-exynos: use devm_ functions The devm_ functions allocate memory that is released when a driver detaches. This makes the code smaller and a bit simpler. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-exynos.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index fedb0eff35d5..8bcbdb5ade2d 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -87,7 +87,8 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) return -EINVAL; } - exynos_ohci = kzalloc(sizeof(struct exynos_ohci_hcd), GFP_KERNEL); + exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd), + GFP_KERNEL); if (!exynos_ohci) return -ENOMEM; @@ -97,8 +98,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto fail_hcd; + return -ENOMEM; } exynos_ohci->hcd = hcd; @@ -123,7 +123,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(res->start, resource_size(res)); + hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; @@ -134,7 +134,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) if (!irq) { dev_err(&pdev->dev, "Failed to get IRQ\n"); err = -ENODEV; - goto fail; + goto fail_io; } if (pdata->phy_init) @@ -146,23 +146,19 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto fail; + goto fail_io; } platform_set_drvdata(pdev, exynos_ohci); return 0; -fail: - iounmap(hcd->regs); fail_io: clk_disable(exynos_ohci->clk); fail_clken: clk_put(exynos_ohci->clk); fail_clk: usb_put_hcd(hcd); -fail_hcd: - kfree(exynos_ohci); return err; } @@ -177,13 +173,10 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - iounmap(hcd->regs); - clk_disable(exynos_ohci->clk); clk_put(exynos_ohci->clk); usb_put_hcd(hcd); - kfree(exynos_ohci); return 0; } -- GitLab From 9cb07563721cb05f91b517aefd70b57ba8a1d5aa Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Jun 2012 16:29:46 +0900 Subject: [PATCH 1907/5711] USB: ehci-s5p: use devm_ functions The devm_ functions allocate memory that is released when a driver detaches. This makes the code smaller and a bit simpler. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-s5p.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index c474cec064e4..1e483f052ff7 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -79,7 +79,8 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) return -EINVAL; } - s5p_ehci = kzalloc(sizeof(struct s5p_ehci_hcd), GFP_KERNEL); + s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd), + GFP_KERNEL); if (!s5p_ehci) return -ENOMEM; @@ -89,8 +90,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto fail_hcd; + return -ENOMEM; } s5p_ehci->hcd = hcd; @@ -115,7 +115,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(res->start, resource_size(res)); + hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; @@ -126,7 +126,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) if (!irq) { dev_err(&pdev->dev, "Failed to get IRQ\n"); err = -ENODEV; - goto fail; + goto fail_io; } if (pdata->phy_init) @@ -151,23 +151,19 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto fail; + goto fail_io; } platform_set_drvdata(pdev, s5p_ehci); return 0; -fail: - iounmap(hcd->regs); fail_io: clk_disable(s5p_ehci->clk); fail_clken: clk_put(s5p_ehci->clk); fail_clk: usb_put_hcd(hcd); -fail_hcd: - kfree(s5p_ehci); return err; } @@ -182,13 +178,10 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - iounmap(hcd->regs); - clk_disable(s5p_ehci->clk); clk_put(s5p_ehci->clk); usb_put_hcd(hcd); - kfree(s5p_ehci); return 0; } -- GitLab From 02f824ac75d1c861aae59be5d6d739043c2066e7 Mon Sep 17 00:00:00 2001 From: Jeffrin Jose Date: Sun, 1 Jul 2012 21:25:16 +0530 Subject: [PATCH 1908/5711] USB: class: cdc-acm: Fixed coding style issue. Fixed coding style issue related to prohibited space in drivers/usb/class/cdc-acm.c Signed-off-by: Jeffrin Jose Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 36a2a0b7b82c..56d6bf668488 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -996,7 +996,7 @@ static int acm_probe(struct usb_interface *intf, case USB_CDC_CALL_MANAGEMENT_TYPE: call_management_function = buffer[3]; call_interface_num = buffer[4]; - if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) + if ((quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); break; default: -- GitLab From 2102e06a5f2e414694921f23591f072a5ba7db9f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Jul 2012 09:18:01 +0200 Subject: [PATCH 1909/5711] usbdevfs: Correct amount of data copied to user in processcompl_compat iso data buffers may have holes in them if some packets were short, so for iso urbs we should always copy the entire buffer, just like the regular processcompl does. Signed-off-by: Hans de Goede Acked-by: Alan Stern CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e0f107948eba..62679bc031fb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1604,10 +1604,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer && urb->actual_length) - if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->actual_length)) + if (as->userbuffer && urb->actual_length) { + if (urb->number_of_packets > 0) /* Isochronous */ + i = urb->transfer_buffer_length; + else /* Non-Isoc */ + i = urb->actual_length; + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) return -EFAULT; + } if (put_user(as->status, &userurb->status)) return -EFAULT; if (put_user(urb->actual_length, &userurb->actual_length)) -- GitLab From 19181bc50e1b8e92a7a3b3d78637c6dc5c0b5a1b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Jul 2012 09:18:02 +0200 Subject: [PATCH 1910/5711] usbdevfs: Add a USBDEVFS_GET_CAPABILITIES ioctl There are a few (new) usbdevfs capabilities which an application cannot discover in any other way then checking the kernel version. There are 3 problems with this: 1) It is just not very pretty. 2) Given the tendency of enterprise distros to backport stuff it is not reliable. 3) As discussed in length on the mailinglist, USBDEVFS_URB_BULK_CONTINUATION does not work as it should when combined with USBDEVFS_URB_SHORT_NOT_OK (which is its intended use) on devices attached to an XHCI controller. So the availability of these features can be host controller dependent, making depending on them based on the kernel version not a good idea. This patch besides adding the new ioctl also adds flags for the following existing capabilities: USBDEVFS_CAP_ZERO_PACKET, available since 2.6.31 USBDEVFS_CAP_BULK_CONTINUATION, available since 2.6.32, except for XHCI USBDEVFS_CAP_NO_PACKET_SIZE_LIM, available since 3.3 Note that this patch only does not advertise the USBDEVFS_URB_BULK_CONTINUATION cap for XHCI controllers, bulk transfers with this flag set will still be accepted when submitted to XHCI controllers. Returning -EINVAL for them would break existing apps, and in most cases the troublesome scenario wrt USBDEVFS_URB_SHORT_NOT_OK urbs on XHCI controllers will never get hit, so this would break working use cases. The disadvantage of not returning -EINVAL is that cases were it is causing real trouble may go undetected / the cause of the trouble may be unclear, but this is the best we can do. Signed-off-by: Hans de Goede Acked-by: Alan Stern Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 17 +++++++++++++++++ drivers/usb/host/xhci.c | 2 ++ include/linux/usb.h | 5 +++++ include/linux/usbdevice_fs.h | 7 +++++++ 4 files changed, 31 insertions(+) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 62679bc031fb..0b387c1a8b7e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1824,6 +1824,20 @@ static int proc_release_port(struct dev_state *ps, void __user *arg) return usb_hub_release_port(ps->dev, portnum, ps); } +static int proc_get_capabilities(struct dev_state *ps, void __user *arg) +{ + __u32 caps; + + caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM; + if (!ps->dev->bus->no_stop_on_short) + caps |= USBDEVFS_CAP_BULK_CONTINUATION; + + if (put_user(caps, (__u32 __user *)arg)) + return -EFAULT; + + return 0; +} + /* * NOTE: All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from @@ -1994,6 +2008,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__); ret = proc_release_port(ps, p); break; + case USBDEVFS_GET_CAPABILITIES: + ret = proc_get_capabilities(ps, p); + break; } usb_unlock_device(dev); if (ret >= 0) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a979cd0dbe0f..7648b2d4b268 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4450,6 +4450,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* Accept arbitrarily long scatter-gather lists */ hcd->self.sg_tablesize = ~0; + /* XHCI controllers don't stop the ep queue on short packets :| */ + hcd->self.no_stop_on_short = 1; if (usb_hcd_is_primary_hcd(hcd)) { xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); diff --git a/include/linux/usb.h b/include/linux/usb.h index f717fbdaee8e..d4f9de1acd45 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -331,6 +331,11 @@ struct usb_bus { u8 otg_port; /* 0, or number of OTG/HNP port */ unsigned is_b_host:1; /* true during some HNP roleswitches */ unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */ + unsigned no_stop_on_short:1; /* + * Quirk: some controllers don't stop + * the ep queue on a short transfer + * with the URB_SHORT_NOT_OK flag set. + */ unsigned sg_tablesize; /* 0 or largest number of sg list entries */ int devnum_next; /* Next open device number in diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 15591d2ea400..07b2ceaaad70 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -125,6 +125,11 @@ struct usbdevfs_hub_portinfo { char port [127]; /* e.g. port 3 connects to device 27 */ }; +/* Device capability flags */ +#define USBDEVFS_CAP_ZERO_PACKET 0x01 +#define USBDEVFS_CAP_BULK_CONTINUATION 0x02 +#define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 + #ifdef __KERNEL__ #ifdef CONFIG_COMPAT #include @@ -204,4 +209,6 @@ struct usbdevfs_ioctl32 { #define USBDEVFS_CONNECT _IO('U', 23) #define USBDEVFS_CLAIM_PORT _IOR('U', 24, unsigned int) #define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int) +#define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32) + #endif /* _LINUX_USBDEVICE_FS_H */ -- GitLab From 3d97ff63f8997761f12c8fbe8082996c6eeaba1a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Jul 2012 09:18:03 +0200 Subject: [PATCH 1911/5711] usbdevfs: Use scatter-gather lists for large bulk transfers When using urb->transfer_buffer we need to allocate physical contiguous buffers for the entire transfer, which is pretty much guaranteed to fail with large transfers. Currently userspace works around this by breaking large transfers into multiple urbs. For large bulk transfers this leads to all kind of complications. This patch makes it possible for userspace to reliable submit large bulk transfers to scatter-gather capable host controllers in one go, by using a scatterlist to break the transfer up in managable chunks. Signed-off-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 152 ++++++++++++++++++++++++++++------- include/linux/usbdevice_fs.h | 1 + 2 files changed, 122 insertions(+), 31 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 0b387c1a8b7e..ebb8a9de8b5f 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #define USB_MAXBUS 64 #define USB_DEVICE_MAX USB_MAXBUS * 128 +#define USB_SG_SIZE 16384 /* split-size for large txs */ /* Mutual exclusion for removal, open, and release */ DEFINE_MUTEX(usbfs_mutex); @@ -285,9 +287,16 @@ static struct async *alloc_async(unsigned int numisoframes) static void free_async(struct async *as) { + int i; + put_pid(as->pid); if (as->cred) put_cred(as->cred); + for (i = 0; i < as->urb->num_sgs; i++) { + if (sg_page(&as->urb->sg[i])) + kfree(sg_virt(&as->urb->sg[i])); + } + kfree(as->urb->sg); kfree(as->urb->transfer_buffer); kfree(as->urb->setup_packet); usb_free_urb(as->urb); @@ -388,6 +397,53 @@ static void snoop_urb(struct usb_device *udev, } } +static void snoop_urb_data(struct urb *urb, unsigned len) +{ + int i, size; + + if (!usbfs_snoop) + return; + + if (urb->num_sgs == 0) { + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, + urb->transfer_buffer, len, 1); + return; + } + + for (i = 0; i < urb->num_sgs && len; i++) { + size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, + sg_virt(&urb->sg[i]), size, 1); + len -= size; + } +} + +static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb) +{ + unsigned i, len, size; + + if (urb->number_of_packets > 0) /* Isochronous */ + len = urb->transfer_buffer_length; + else /* Non-Isoc */ + len = urb->actual_length; + + if (urb->num_sgs == 0) { + if (copy_to_user(userbuffer, urb->transfer_buffer, len)) + return -EFAULT; + return 0; + } + + for (i = 0; i < urb->num_sgs && len; i++) { + size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; + if (copy_to_user(userbuffer, sg_virt(&urb->sg[i]), size)) + return -EFAULT; + userbuffer += size; + len -= size; + } + + return 0; +} + #define AS_CONTINUATION 1 #define AS_UNLINK 2 @@ -454,9 +510,10 @@ static void async_completed(struct urb *urb) } snoop(&urb->dev->dev, "urb complete\n"); snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, - as->status, COMPLETE, - ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_OUT) ? - NULL : urb->transfer_buffer, urb->actual_length); + as->status, COMPLETE, NULL, 0); + if ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_IN) + snoop_urb_data(urb, urb->actual_length); + if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && as->status != -ENOENT) cancel_bulk_urbs(ps, as->bulk_addr); @@ -1114,8 +1171,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, struct async *as = NULL; struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; - int ret, ifnum = -1; - int is_in; + int i, ret, is_in, num_sgs = 0, ifnum = -1; + void *buf; if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | USBDEVFS_URB_SHORT_NOT_OK | @@ -1199,6 +1256,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, goto interrupt_urb; } uurb->number_of_packets = 0; + num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE); + if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize) + num_sgs = 0; break; case USBDEVFS_URB_TYPE_INTERRUPT: @@ -1255,26 +1315,67 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ret = -ENOMEM; goto error; } - u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length; + + u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + + num_sgs * sizeof(struct scatterlist); ret = usbfs_increase_memory_usage(u); if (ret) goto error; as->mem_usage = u; - if (uurb->buffer_length > 0) { + if (num_sgs) { + as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), + GFP_KERNEL); + if (!as->urb->sg) { + ret = -ENOMEM; + goto error; + } + as->urb->num_sgs = num_sgs; + sg_init_table(as->urb->sg, as->urb->num_sgs); + + totlen = uurb->buffer_length; + for (i = 0; i < as->urb->num_sgs; i++) { + u = (totlen > USB_SG_SIZE) ? USB_SG_SIZE : totlen; + buf = kmalloc(u, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto error; + } + sg_set_buf(&as->urb->sg[i], buf, u); + + if (!is_in) { + if (copy_from_user(buf, uurb->buffer, u)) { + ret = -EFAULT; + goto error; + } + } + totlen -= u; + } + } else if (uurb->buffer_length > 0) { as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); if (!as->urb->transfer_buffer) { ret = -ENOMEM; goto error; } - /* Isochronous input data may end up being discontiguous - * if some of the packets are short. Clear the buffer so - * that the gaps don't leak kernel data to userspace. - */ - if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) + + if (!is_in) { + if (copy_from_user(as->urb->transfer_buffer, + uurb->buffer, + uurb->buffer_length)) { + ret = -EFAULT; + goto error; + } + } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) { + /* + * Isochronous input data may end up being + * discontiguous if some of the packets are short. + * Clear the buffer so that the gaps don't leak + * kernel data to userspace. + */ memset(as->urb->transfer_buffer, 0, uurb->buffer_length); + } } as->urb->dev = ps->dev; as->urb->pipe = (uurb->type << 30) | @@ -1328,17 +1429,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->pid = get_pid(task_pid(current)); as->cred = get_current_cred(); security_task_getsecid(current, &as->secid); - if (!is_in && uurb->buffer_length > 0) { - if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, - uurb->buffer_length)) { - ret = -EFAULT; - goto error; - } - } snoop_urb(ps->dev, as->userurb, as->urb->pipe, as->urb->transfer_buffer_length, 0, SUBMIT, - is_in ? NULL : as->urb->transfer_buffer, - uurb->buffer_length); + NULL, 0); + if (!is_in) + snoop_urb_data(as->urb, as->urb->transfer_buffer_length); + async_newpending(as); if (usb_endpoint_xfer_bulk(&ep->desc)) { @@ -1433,11 +1529,7 @@ static int processcompl(struct async *as, void __user * __user *arg) unsigned int i; if (as->userbuffer && urb->actual_length) { - if (urb->number_of_packets > 0) /* Isochronous */ - i = urb->transfer_buffer_length; - else /* Non-Isoc */ - i = urb->actual_length; - if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) + if (copy_urb_data_to_user(as->userbuffer, urb)) goto err_out; } if (put_user(as->status, &userurb->status)) @@ -1605,11 +1697,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) unsigned int i; if (as->userbuffer && urb->actual_length) { - if (urb->number_of_packets > 0) /* Isochronous */ - i = urb->transfer_buffer_length; - else /* Non-Isoc */ - i = urb->actual_length; - if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) + if (copy_urb_data_to_user(as->userbuffer, urb)) return -EFAULT; } if (put_user(as->status, &userurb->status)) @@ -1831,6 +1919,8 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg) caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM; if (!ps->dev->bus->no_stop_on_short) caps |= USBDEVFS_CAP_BULK_CONTINUATION; + if (ps->dev->bus->sg_tablesize) + caps |= USBDEVFS_CAP_BULK_SCATTER_GATHER; if (put_user(caps, (__u32 __user *)arg)) return -EFAULT; diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 07b2ceaaad70..3b74666be027 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -129,6 +129,7 @@ struct usbdevfs_hub_portinfo { #define USBDEVFS_CAP_ZERO_PACKET 0x01 #define USBDEVFS_CAP_BULK_CONTINUATION 0x02 #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 +#define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 #ifdef __KERNEL__ #ifdef CONFIG_COMPAT -- GitLab From 22a09b439af25fefbe0ebd1c6c2a0d81e923f2f5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 26 Jun 2012 04:40:38 -0300 Subject: [PATCH 1912/5711] [media] drxk: fix a '&' vs '|' bug IQM_AF_CLKNEG_CLKNEGDATA__M is 0x2 and IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS is 0. (clkNeg | 0x2) is never equal to zero so the condition can never be true. I consulted with Ralph Metzler and the '|' should be changed to a '&'. Signed-off-by: Dan Carpenter CC: Ralph Metzler Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk_hard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 8fa28bb47088..317530f891c0 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -3004,7 +3004,7 @@ static int ADCSynchronization(struct drxk_state *state) status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); if (status < 0) goto error; - if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) == + if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) == IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); clkNeg |= -- GitLab From 9e23f50a762c236049b4965a42d86d55fcdbbfb3 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Wed, 4 Jul 2012 17:36:55 -0300 Subject: [PATCH 1913/5711] [media] drxk: Make the QAM demodulator command parameters configurable Currently there are two different implementations (in the firmware) for the QAM demodulator command: one takes 4 and the other takes 2 parameters. The driver shows an error in dmesg When using the 4-parameter command with firmware that implements the 2-parameter command. Unfortunately this happens every time when chaning the frequency (on DVB-C). This patch simply makes configurable, how many command parameters will be used. All existing drxk_config instances using the "drxk_a3.mc" were updated because this firmware is the only loadable firmware where the QAM demodulator command takes 4 parameters. Some firmwares in the ROM might also use it. The drxk instances in the em28xx-dvb driver were also updated to silence the warnings. If no qam_demod_parameter_count is given in the drxk_config struct, then the correct number of parameters will be auto-detected. [mchehab@redhat.com: Fix a small CodingStyle issue at one comment] Signed-off-by: Martin Blumenstingl Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ddbridge/ddbridge-core.c | 1 + drivers/media/dvb/frontends/drxk.h | 11 +- drivers/media/dvb/frontends/drxk_hard.c | 112 ++++++++++++++++----- drivers/media/dvb/frontends/drxk_hard.h | 1 + drivers/media/dvb/ngene/ngene-cards.c | 1 + drivers/media/video/em28xx/em28xx-dvb.c | 4 + 6 files changed, 104 insertions(+), 26 deletions(-) diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c index 131b938e9e81..ebf3f05839d2 100644 --- a/drivers/media/dvb/ddbridge/ddbridge-core.c +++ b/drivers/media/dvb/ddbridge/ddbridge-core.c @@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input) memset(&config, 0, sizeof(config)); config.microcode_name = "drxk_a3.mc"; + config.qam_demod_parameter_count = 4; config.adr = 0x29 + (input->nr & 1); fe = input->fe = dvb_attach(drxk_attach, &config, i2c); diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index 9d64e4fea066..d615d7d055a2 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -20,6 +20,14 @@ * means that 1=DVBC, 0 = DVBT. Zero means the opposite. * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. * @microcode_name: Name of the firmware file with the microcode + * @qam_demod_parameter_count: The number of parameters used for the command + * to set the demodulator parameters. All + * firmwares are using the 2-parameter commmand. + * An exception is the "drxk_a3.mc" firmware, + * which uses the 4-parameter command. + * A value of 0 (default) or lower indicates that + * the correct number of parameters will be + * automatically detected. * * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * UIO-3. @@ -38,7 +46,8 @@ struct drxk_config { u8 mpeg_out_clk_strength; int chunk_size; - const char *microcode_name; + const char *microcode_name; + int qam_demod_parameter_count; }; #if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \ diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 317530f891c0..f370ec1c9bd3 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -5415,12 +5415,67 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) #define QAM_LOCKRANGE__M 0x10 #define QAM_LOCKRANGE_NORMAL 0x10 +static int QAMDemodulatorCommand(struct drxk_state *state, + int numberOfParameters) +{ + int status; + u16 cmdResult; + u16 setParamParameters[4] = { 0, 0, 0, 0 }; + + setParamParameters[0] = state->m_Constellation; /* modulation */ + setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ + + if (numberOfParameters == 2) { + u16 setEnvParameters[1] = { 0 }; + + if (state->m_OperationMode == OM_QAM_ITU_C) + setEnvParameters[0] = QAM_TOP_ANNEX_C; + else + setEnvParameters[0] = QAM_TOP_ANNEX_A; + + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, + 1, setEnvParameters, 1, &cmdResult); + if (status < 0) + goto error; + + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + numberOfParameters, setParamParameters, + 1, &cmdResult); + } else if (numberOfParameters == 4) { + if (state->m_OperationMode == OM_QAM_ITU_C) + setParamParameters[2] = QAM_TOP_ANNEX_C; + else + setParamParameters[2] = QAM_TOP_ANNEX_A; + + setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); + /* Env parameters */ + /* check for LOCKRANGE Extented */ + /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ + + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + numberOfParameters, setParamParameters, + 1, &cmdResult); + } else { + printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter " + "count %d\n", numberOfParameters); + } + +error: + if (status < 0) + printk(KERN_WARNING "drxk: Warning %d on %s\n", + status, __func__); + return status; +} + static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, s32 tunerFreqOffset) { int status; - u16 setParamParameters[4] = { 0, 0, 0, 0 }; u16 cmdResult; + int qamDemodParamCount = state->qam_demod_parameter_count; dprintk(1, "\n"); /* @@ -5472,34 +5527,40 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, } if (status < 0) goto error; - setParamParameters[0] = state->m_Constellation; /* modulation */ - setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ - if (state->m_OperationMode == OM_QAM_ITU_C) - setParamParameters[2] = QAM_TOP_ANNEX_C; - else - setParamParameters[2] = QAM_TOP_ANNEX_A; - setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); - /* Env parameters */ - /* check for LOCKRANGE Extented */ - /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult); - if (status < 0) { - /* Fall-back to the simpler call */ - if (state->m_OperationMode == OM_QAM_ITU_C) - setParamParameters[0] = QAM_TOP_ANNEX_C; - else - setParamParameters[0] = QAM_TOP_ANNEX_A; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult); - if (status < 0) - goto error; + /* Use the 4-parameter if it's requested or we're probing for + * the correct command. */ + if (state->qam_demod_parameter_count == 4 + || !state->qam_demod_parameter_count) { + qamDemodParamCount = 4; + status = QAMDemodulatorCommand(state, qamDemodParamCount); + } - setParamParameters[0] = state->m_Constellation; /* modulation */ - setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult); + /* Use the 2-parameter command if it was requested or if we're + * probing for the correct command and the 4-parameter command + * failed. */ + if (state->qam_demod_parameter_count == 2 + || (!state->qam_demod_parameter_count && status < 0)) { + qamDemodParamCount = 2; + status = QAMDemodulatorCommand(state, qamDemodParamCount); } - if (status < 0) + + if (status < 0) { + dprintk(1, "Could not set demodulator parameters. Make " + "sure qam_demod_parameter_count (%d) is correct for " + "your firmware (%s).\n", + state->qam_demod_parameter_count, + state->microcode_name); goto error; + } else if (!state->qam_demod_parameter_count) { + dprintk(1, "Auto-probing the correct QAM demodulator command " + "parameters was successful - using %d parameters.\n", + qamDemodParamCount); + + /* One of our commands was successful. We don't need to + /* auto-probe anymore, now that we got the correct command. */ + state->qam_demod_parameter_count = qamDemodParamCount; + } /* * STEP 3: enable the system in a mode where the ADC provides valid @@ -6502,6 +6563,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->demod_address = adr; state->single_master = config->single_master; state->microcode_name = config->microcode_name; + state->qam_demod_parameter_count = config->qam_demod_parameter_count; state->no_i2c_bridge = config->no_i2c_bridge; state->antenna_gpio = config->antenna_gpio; state->antenna_dvbt = config->antenna_dvbt; diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h index f41779700106..6bb9fc4a7b96 100644 --- a/drivers/media/dvb/frontends/drxk_hard.h +++ b/drivers/media/dvb/frontends/drxk_hard.h @@ -353,6 +353,7 @@ struct drxk_state { const char *microcode_name; struct completion fw_wait_load; const struct firmware *fw; + int qam_demod_parameter_count; }; #define NEVER_LOCK 0 diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c index 7539a5d71029..72ee8de02260 100644 --- a/drivers/media/dvb/ngene/ngene-cards.c +++ b/drivers/media/dvb/ngene/ngene-cards.c @@ -217,6 +217,7 @@ static int demod_attach_drxk(struct ngene_channel *chan, memset(&config, 0, sizeof(config)); config.microcode_name = "drxk_a3.mc"; + config.qam_demod_parameter_count = 4; config.adr = 0x29 + (chan->number ^ 2); chan->fe = dvb_attach(drxk_attach, &config, i2c); diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index f8ffe102d295..a16531fa937a 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -315,6 +315,7 @@ static struct drxk_config terratec_h5_drxk = { .single_master = 1, .no_i2c_bridge = 1, .microcode_name = "dvb-usb-terratec-h5-drxk.fw", + .qam_demod_parameter_count = 2, }; static struct drxk_config hauppauge_930c_drxk = { @@ -323,6 +324,7 @@ static struct drxk_config hauppauge_930c_drxk = { .no_i2c_bridge = 1, .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", .chunk_size = 56, + .qam_demod_parameter_count = 2, }; struct drxk_config terratec_htc_stick_drxk = { @@ -331,6 +333,7 @@ struct drxk_config terratec_htc_stick_drxk = { .no_i2c_bridge = 1, .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw", .chunk_size = 54, + .qam_demod_parameter_count = 2, /* Required for the antenna_gpio to disable LNA. */ .antenna_dvbt = true, /* The windows driver uses the same. This will disable LNA. */ @@ -347,6 +350,7 @@ static struct drxk_config pctv_520e_drxk = { .adr = 0x29, .single_master = 1, .microcode_name = "dvb-demod-drxk-pctv.fw", + .qam_demod_parameter_count = 2, .chunk_size = 58, .antenna_dvbt = true, /* disable LNA */ .antenna_gpio = (1 << 2), /* disable LNA */ -- GitLab From 7eaf718844c585e293b8d0d1173baab9b9c20d7d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Jul 2012 14:53:51 -0300 Subject: [PATCH 1914/5711] fixupSigned-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk_hard.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index f370ec1c9bd3..6eef3df3687d 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -5557,8 +5557,10 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, "parameters was successful - using %d parameters.\n", qamDemodParamCount); - /* One of our commands was successful. We don't need to - /* auto-probe anymore, now that we got the correct command. */ + /* + * One of our commands was successful. We don't need to + * auto-probe anymore, now that we got the correct command. + */ state->qam_demod_parameter_count = qamDemodParamCount; } -- GitLab From 257ee97eeb90aaf70cc891577d69afa63d81ceea Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Wed, 4 Jul 2012 17:38:23 -0300 Subject: [PATCH 1915/5711] [media] drxk: Improve logging This patch simply fixes some logging calls: - Use KERN_INFO when printing the chip status. - Add a missing space when logging the drxk_gate_ctrl call. - Use the same logging text as always if the scu_command in GetQAMLockStatus fails. Signed-off-by: Martin Blumenstingl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk_hard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 6eef3df3687d..1ab8154542da 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -959,7 +959,7 @@ static int GetDeviceCapabilities(struct drxk_state *state) if (status < 0) goto error; -printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo); + printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo); /* driver 0.9.0 */ switch ((sioTopJtagidLo >> 29) & 0xF) { @@ -5388,7 +5388,7 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, Result); if (status < 0) - printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status); + printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { /* 0x0000 NOT LOCKED */ @@ -6329,7 +6329,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct drxk_state *state = fe->demodulator_priv; - dprintk(1, "%s\n", enable ? "enable" : "disable"); + dprintk(1, ": %s\n", enable ? "enable" : "disable"); if (state->m_DrxkState == DRXK_NO_DEV) return -ENODEV; -- GitLab From b7283d5a044c010d5e68afccc0598846f254db7b Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 29 Jun 2012 17:48:49 +0800 Subject: [PATCH 1916/5711] usb: chipidea: remove unneeded NULL check As reported by Dan Carpenter, there is a NULL check in udc_start() that follows a dereference of the pointer that's being checked. However, at that point udc pointer shouldn't ever be NULL and if it is, the dereference should cause an oops. Signed-off-by: Alexander Shishkin Reported-by: Dan Carpenter Acked-by: Felipe Balbi Signed-off-by: Richard Zhao Acked-by: Marek Vasut Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 4688ab71bd27..80e71021f186 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1648,9 +1648,6 @@ static int udc_start(struct ci13xxx *udc) struct device *dev = udc->dev; int retval = 0; - if (!udc) - return -EINVAL; - spin_lock_init(&udc->lock); udc->gadget.ops = &usb_gadget_ops; -- GitLab From b2006d91d8e389a04ffbf603b3896af93b0af427 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 29 Jun 2012 17:48:50 +0800 Subject: [PATCH 1917/5711] usb: chipidea: drop useless arch-check msm glue layer compiles on all arches just fine. Let's drop the unnecessary ARCH check so we have easier compile tests. Signed-off-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Richard Zhao Acked-by: Marek Vasut Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index cc3493769724..b69900a62a4d 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -5,10 +5,12 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o +# Glue/Bridge layers go here + +obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o + +# PCI doesn't provide stubs, need to check ifneq ($(CONFIG_PCI),) obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o endif -ifneq ($(CONFIG_ARCH_MSM),) - obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o -endif -- GitLab From 17d2fcc393bfe58cc1e2bc34603a48e447ff7afb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 29 Jun 2012 17:48:51 +0800 Subject: [PATCH 1918/5711] usb: chipidea: msm: add missing section annotation No functional changes, it will just free up some code if we don't have hotplug. Signed-off-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Richard Zhao Acked-by: Marek Vasut Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci13xxx_msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index 958069ef95e3..8d438b82e868 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -55,7 +55,7 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { .notify_event = ci13xxx_msm_notify_event, }; -static int ci13xxx_msm_probe(struct platform_device *pdev) +static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) { struct platform_device *plat_ci; int ret; -- GitLab From 6bf83594e3fa1b1147ed1baff356d4fd30846b84 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 29 Jun 2012 17:48:52 +0800 Subject: [PATCH 1919/5711] usb: chipidea: msm: add remove method allow this driver to be removed too. Signed-off-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Richard Zhao Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci13xxx_msm.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index 8d438b82e868..11a7befdc4ef 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -84,6 +84,8 @@ static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) if (ret) goto put_platform; + platform_set_drvdata(pdev, plat_ci); + pm_runtime_no_callbacks(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -95,16 +97,23 @@ put_platform: return ret; } +static int __devexit ci13xxx_msm_remove(struct platform_device *pdev) +{ + struct platform_device *plat_ci = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + platform_device_unregister(plat_ci); + + return 0; +} + static struct platform_driver ci13xxx_msm_driver = { .probe = ci13xxx_msm_probe, + .remove = __devexit_p(ci13xxx_msm_remove), .driver = { .name = "msm_hsusb", }, }; -MODULE_ALIAS("platform:msm_hsusb"); -static int __init ci13xxx_msm_init(void) -{ - return platform_driver_register(&ci13xxx_msm_driver); -} -module_init(ci13xxx_msm_init); +module_platform_driver(ci13xxx_msm_driver); +MODULE_ALIAS("platform:msm_hsusb"); MODULE_LICENSE("GPL v2"); -- GitLab From 01005a729a17ab419f61a366e22f3419e7a2c3fe Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2012 16:57:05 +0100 Subject: [PATCH 1920/5711] ASoC: dapm: Fix locking during codec shutdown Codec shutdown performs a DAPM power sequence that might cause conflicts and/or race conditions if another stream power event is running simultaneously. Use card's dapm mutex to protect any potential race condition between them. Signed-off-by: Misael Lopez Cruz Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/soc-dapm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5be4f9a2edb8..114f2af5f304 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3537,10 +3537,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_free); static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) { + struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; LIST_HEAD(down_list); int powerdown = 0; + mutex_lock(&card->dapm_mutex); + list_for_each_entry(w, &dapm->card->widgets, list) { if (w->dapm != dapm) continue; @@ -3563,6 +3566,8 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY); } + + mutex_unlock(&card->dapm_mutex); } /* -- GitLab From 5cb9b7482270972421a1f2d4145efc60d7ee1176 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2012 16:54:52 +0100 Subject: [PATCH 1921/5711] ASoC: pcm: Clean up logging in soc_new_pcm() Use dev_ style logging throughout soc_new_pcm() Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 48fd15b312c1..7063b8f926c6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2003,7 +2003,6 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; @@ -2042,7 +2041,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) capture, &pcm); } if (ret < 0) { - printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); + dev_err(rtd->card->dev, "can't create pcm for %s\n", + rtd->dai_link->name); return ret; } dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name); @@ -2099,14 +2099,14 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (platform->driver->pcm_new) { ret = platform->driver->pcm_new(rtd); if (ret < 0) { - pr_err("asoc: platform pcm constructor failed\n"); + dev_err(platform->dev, "pcm constructor failed\n"); return ret; } } pcm->private_free = platform->driver->pcm_free; out: - printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, + dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name, cpu_dai->name); return ret; } -- GitLab From 77c4400f2f0fd8384ab5cbe41d81ccc664896b2d Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 29 Jun 2012 17:48:53 +0800 Subject: [PATCH 1922/5711] USB: Chipidea: rename struct ci13xxx_udc_driver to struct ci13xxx_platform_data This patch rename struct ci13xxx_udc_driver and var with the type. ci13xxx_platform_data reflect it's passed from platfrom driver. Signed-off-by: Richard Zhao Reviewed-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci.h | 4 ++-- drivers/usb/chipidea/ci13xxx_msm.c | 6 +++--- drivers/usb/chipidea/ci13xxx_pci.c | 20 ++++++++++---------- drivers/usb/chipidea/core.c | 12 ++++++------ drivers/usb/chipidea/host.c | 2 +- drivers/usb/chipidea/udc.c | 24 ++++++++++++------------ include/linux/usb/chipidea.h | 2 +- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 50911f8490d4..0b093308548d 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -125,7 +125,7 @@ struct hw_bank { * @remote_wakeup: host-enabled remote wakeup * @suspended: suspended by host * @test_mode: the selected test mode - * @udc_driver: platform specific information supplied by parent device + * @platdata: platform specific information supplied by parent device * @vbus_active: is VBUS active * @transceiver: pointer to USB PHY, if any * @hcd: pointer to usb_hcd for ehci host driver @@ -158,7 +158,7 @@ struct ci13xxx { u8 suspended; u8 test_mode; - struct ci13xxx_udc_driver *udc_driver; + struct ci13xxx_platform_data *platdata; int vbus_active; struct usb_phy *transceiver; struct usb_hcd *hcd; diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index 11a7befdc4ef..12c0dd6a300c 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -45,7 +45,7 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) } } -static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { +static struct ci13xxx_platform_data ci13xxx_msm_platdata = { .name = "ci13xxx_msm", .flags = CI13XXX_REGS_SHARED | CI13XXX_REQUIRE_TRANSCEIVER | @@ -75,8 +75,8 @@ static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) goto put_platform; } - ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver, - sizeof(ci13xxx_msm_udc_driver)); + ret = platform_device_add_data(plat_ci, &ci13xxx_msm_platdata, + sizeof(ci13xxx_msm_platdata)); if (ret) goto put_platform; diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c index e3dab27f5c75..cdcac3a0e94d 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci13xxx_pci.c @@ -23,17 +23,17 @@ /****************************************************************************** * PCI block *****************************************************************************/ -struct ci13xxx_udc_driver pci_driver = { +struct ci13xxx_platform_data pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = DEF_CAPOFFSET, }; -struct ci13xxx_udc_driver langwell_pci_driver = { +struct ci13xxx_platform_data langwell_pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = 0, }; -struct ci13xxx_udc_driver penwell_pci_driver = { +struct ci13xxx_platform_data penwell_pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = 0, .power_budget = 200, @@ -51,12 +51,12 @@ struct ci13xxx_udc_driver penwell_pci_driver = { static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct ci13xxx_udc_driver *driver = (void *)id->driver_data; + struct ci13xxx_platform_data *platdata = (void *)id->driver_data; struct platform_device *plat_ci; struct resource res[3]; int retval = 0, nres = 2; - if (!driver) { + if (!platdata) { dev_err(&pdev->dev, "device doesn't provide driver data\n"); return -ENODEV; } @@ -95,7 +95,7 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, goto put_platform; } - retval = platform_device_add_data(plat_ci, driver, sizeof(*driver)); + retval = platform_device_add_data(plat_ci, platdata, sizeof(*platdata)); if (retval) goto put_platform; @@ -147,19 +147,19 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { { PCI_DEVICE(0x153F, 0x1004), - .driver_data = (kernel_ulong_t)&pci_driver, + .driver_data = (kernel_ulong_t)&pci_platdata, }, { PCI_DEVICE(0x153F, 0x1006), - .driver_data = (kernel_ulong_t)&pci_driver, + .driver_data = (kernel_ulong_t)&pci_platdata, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), - .driver_data = (kernel_ulong_t)&langwell_pci_driver, + .driver_data = (kernel_ulong_t)&langwell_pci_platdata, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), - .driver_data = (kernel_ulong_t)&penwell_pci_driver, + .driver_data = (kernel_ulong_t)&penwell_pci_platdata, }, { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } }; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 15e03b308f8a..9a883bd5e113 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -179,7 +179,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) ci->hw_bank.abs = base; ci->hw_bank.cap = ci->hw_bank.abs; - ci->hw_bank.cap += ci->udc_driver->capoffset; + ci->hw_bank.cap += ci->platdata->capoffset; ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap); hw_alloc_regmap(ci, false); @@ -227,11 +227,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) udelay(10); /* not RTOS friendly */ - if (ci->udc_driver->notify_event) - ci->udc_driver->notify_event(ci, + if (ci->platdata->notify_event) + ci->platdata->notify_event(ci, CI13XXX_CONTROLLER_RESET_EVENT); - if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING) + if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); /* USBMODE should be configured step by step */ @@ -364,7 +364,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) } ci->dev = dev; - ci->udc_driver = dev->platform_data; + ci->platdata = dev->platform_data; ret = hw_device_init(ci, base); if (ret < 0) { @@ -419,7 +419,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, ci); - ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name, + ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, ci); if (ret) goto stop; diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 9eacd21c0cd9..4a4fdb8c65f8 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -116,7 +116,7 @@ static int host_start(struct ci13xxx *ci) hcd->regs = ci->hw_bank.abs; hcd->has_tt = 1; - hcd->power_budget = ci->udc_driver->power_budget; + hcd->power_budget = ci->platdata->power_budget; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 80e71021f186..3094c85dc0b5 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1363,7 +1363,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) unsigned long flags; int gadget_ready = 0; - if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS)) + if (!(udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) return -EOPNOTSUPP; spin_lock_irqsave(&udc->lock, flags); @@ -1379,8 +1379,8 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) hw_device_state(udc, udc->ep0out->qh.dma); } else { hw_device_state(udc, 0); - if (udc->udc_driver->notify_event) - udc->udc_driver->notify_event(udc, + if (udc->platdata->notify_event) + udc->platdata->notify_event(udc, CI13XXX_CONTROLLER_STOPPED_EVENT); _gadget_stop_activity(&udc->gadget); pm_runtime_put_sync(&_gadget->dev); @@ -1515,9 +1515,9 @@ static int ci13xxx_start(struct usb_gadget *gadget, udc->driver = driver; pm_runtime_get_sync(&udc->gadget.dev); - if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { + if (udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { if (udc->vbus_active) { - if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) + if (udc->platdata->flags & CI13XXX_REGS_SHARED) hw_device_reset(udc, USBMODE_CM_DC); } else { pm_runtime_put_sync(&udc->gadget.dev); @@ -1545,11 +1545,11 @@ static int ci13xxx_stop(struct usb_gadget *gadget, spin_lock_irqsave(&udc->lock, flags); - if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) || + if (!(udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || udc->vbus_active) { hw_device_state(udc, 0); - if (udc->udc_driver->notify_event) - udc->udc_driver->notify_event(udc, + if (udc->platdata->notify_event) + udc->platdata->notify_event(udc, CI13XXX_CONTROLLER_STOPPED_EVENT); udc->driver = NULL; spin_unlock_irqrestore(&udc->lock, flags); @@ -1582,7 +1582,7 @@ static irqreturn_t udc_irq(struct ci13xxx *udc) spin_lock(&udc->lock); - if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) { + if (udc->platdata->flags & CI13XXX_REGS_SHARED) { if (hw_read(udc, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DC) { spin_unlock(&udc->lock); @@ -1654,7 +1654,7 @@ static int udc_start(struct ci13xxx *udc) udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.max_speed = USB_SPEED_HIGH; udc->gadget.is_otg = 0; - udc->gadget.name = udc->udc_driver->name; + udc->gadget.name = udc->platdata->name; INIT_LIST_HEAD(&udc->gadget.ep_list); @@ -1687,14 +1687,14 @@ static int udc_start(struct ci13xxx *udc) udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); - if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { + if (udc->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (udc->transceiver == NULL) { retval = -ENODEV; goto free_pools; } } - if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) { + if (!(udc->platdata->flags & CI13XXX_REGS_SHARED)) { retval = hw_device_reset(udc, USBMODE_CM_DC); if (retval) goto put_transceiver; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index edb90d6cfd12..d4cf970656fb 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -6,7 +6,7 @@ #define __LINUX_USB_CHIPIDEA_H struct ci13xxx; -struct ci13xxx_udc_driver { +struct ci13xxx_platform_data { const char *name; /* offset of the capability registers */ uintptr_t capoffset; -- GitLab From 4123128ee4854a955dd4a94b31991f8cc38c9b5e Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2012 16:56:16 +0100 Subject: [PATCH 1923/5711] ASoC: dapm: Make sure all dapm contexts are updated Make sure we set the bias level for all DAPM contexts when changing level. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 114f2af5f304..7c9cd276c2fc 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -288,9 +288,9 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (dapm->codec->driver->set_bias_level) ret = dapm->codec->driver->set_bias_level(dapm->codec, level); - else - dapm->bias_level = level; - } + } else + dapm->bias_level = level; + if (ret != 0) goto out; -- GitLab From 3e4536546beb5295e6e0459e745327ebffeade9d Mon Sep 17 00:00:00 2001 From: Simon Wilson Date: Fri, 6 Jul 2012 17:04:17 +0100 Subject: [PATCH 1924/5711] ASoC: twl6040: fix spelling mistake Fix spelling mistake in "High-Performance" option of twl6040 power mode. Signed-off-by: Simon Wilson Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index a36e9fcdf184..0ff1e70b7770 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -553,7 +553,7 @@ static const struct snd_kcontrol_new vibrar_mux_controls = /* Headset power mode */ static const char *twl6040_power_mode_texts[] = { - "Low-Power", "High-Perfomance", + "Low-Power", "High-Performance", }; static const struct soc_enum twl6040_power_mode_enum = -- GitLab From 3ac3f5ca91afc03587b1d2d642f126efc5be37ca Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2012 17:07:00 +0100 Subject: [PATCH 1925/5711] ASoC: dpcm: Allow FE to be opened without valid BE routes. Some userspace will open a PCM device and then configure mixers for routing before triggering. This patch allows userspace to do this sequence. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7063b8f926c6..ef22d0bd9e9e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1955,10 +1955,8 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; if (dpcm_path_get(fe, stream, &list) <= 0) { - dev_warn(fe->dev, "asoc: %s no valid %s route\n", + dev_dbg(fe->dev, "asoc: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); - mutex_unlock(&fe->card->mutex); - return -EINVAL; } /* calculate valid and active FE <-> BE dpcms */ -- GitLab From fabd03842b77b1eb6c9b08c79be86fa38afbe310 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 17:20:06 +0100 Subject: [PATCH 1926/5711] ASoC: dapm: Mark widgets as dirty when a route is added If we add a new route at runtime then we'll need to recheck the connections to the affected widgets. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-dapm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 912330b147e0..19fda1339510 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2251,6 +2251,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, path->connect = 0; return 0; } + + dapm_mark_dirty(wsource, "Route added"); + dapm_mark_dirty(wsink, "Route added"); + return 0; err: -- GitLab From efcc3c61b9b1e4f764e14c48c553e6d477f40512 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 17:24:19 +0100 Subject: [PATCH 1927/5711] ASoC: dapm: Allow routes to be deleted at runtime Since we're now relying on DAPM for things like enabling clocks when we reparent the clocks for widgets we need to either use conditional routes (which are expensive) or remove routes at runtime. Add a route removal API to support this use case. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- include/sound/soc-dapm.h | 2 ++ sound/soc/soc-dapm.c | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 05559e571d44..abe373d57adc 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -374,6 +374,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm); void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route, int num); +int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_route *route, int num); int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route, int num); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 19fda1339510..4ba47aab9801 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2264,6 +2264,59 @@ err: return ret; } +static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_route *route) +{ + struct snd_soc_dapm_path *path, *p; + const char *sink; + const char *source; + char prefixed_sink[80]; + char prefixed_source[80]; + + if (route->control) { + dev_err(dapm->dev, + "Removal of routes with controls not supported\n"); + return -EINVAL; + } + + if (dapm->codec && dapm->codec->name_prefix) { + snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", + dapm->codec->name_prefix, route->sink); + sink = prefixed_sink; + snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", + dapm->codec->name_prefix, route->source); + source = prefixed_source; + } else { + sink = route->sink; + source = route->source; + } + + path = NULL; + list_for_each_entry(p, &dapm->card->paths, list) { + if (strcmp(p->source->name, source) != 0) + continue; + if (strcmp(p->sink->name, sink) != 0) + continue; + path = p; + break; + } + + if (path) { + dapm_mark_dirty(path->source, "Route removed"); + dapm_mark_dirty(path->sink, "Route removed"); + + list_del(&path->list); + list_del(&path->list_sink); + list_del(&path->list_source); + kfree(path); + } else { + dev_warn(dapm->dev, "Route %s->%s does not exist\n", + source, sink); + } + + return 0; +} + /** * snd_soc_dapm_add_routes - Add routes between DAPM widgets * @dapm: DAPM context @@ -2298,6 +2351,30 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, } EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); +/** + * snd_soc_dapm_del_routes - Remove routes between DAPM widgets + * @dapm: DAPM context + * @route: audio routes + * @num: number of routes + * + * Removes routes from the DAPM context. + */ +int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_route *route, int num) +{ + int i, ret = 0; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + for (i = 0; i < num; i++) { + snd_soc_dapm_del_route(dapm, route); + route++; + } + mutex_unlock(&dapm->card->dapm_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes); + static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route) { -- GitLab From 410837a7a29efa2402f496215244569c988bf0db Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 17:26:59 +0100 Subject: [PATCH 1928/5711] ASoC: arizona: Change DAPM routes for AIF clocks when we change them Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/arizona.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index d0bcca959111..901b53e1d7bc 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -588,12 +588,25 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, return 0; } +static const char *arizona_dai_clk_str(int clk_id) +{ + switch (clk_id) { + case ARIZONA_CLK_SYSCLK: + return "SYSCLK"; + case ARIZONA_CLK_ASYNCCLK: + return "ASYNCCLK"; + default: + return "Unknown clock"; + } +} + static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; + struct snd_soc_dapm_route routes[2]; switch (clk_id) { case ARIZONA_CLK_SYSCLK: @@ -603,15 +616,28 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - if (clk_id != dai_priv->clk && dai->active) { + if (clk_id == dai_priv->clk) + return 0; + + if (dai->active) { dev_err(codec->dev, "Can't change clock on active DAI %d\n", dai->id); return -EBUSY; } - dai_priv->clk = clk_id; + memset(&routes, 0, sizeof(routes)); + routes[0].sink = dai->driver->capture.stream_name; + routes[1].sink = dai->driver->playback.stream_name; - return 0; + routes[0].source = arizona_dai_clk_str(dai_priv->clk); + routes[1].source = arizona_dai_clk_str(dai_priv->clk); + snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); + + routes[0].source = arizona_dai_clk_str(clk_id); + routes[1].source = arizona_dai_clk_str(clk_id); + snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); + + return snd_soc_dapm_sync(&codec->dapm); } const struct snd_soc_dai_ops arizona_dai_ops = { -- GitLab From d66a547cddb9124cea6308c33e1f54c7c8db288f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Jul 2012 12:19:10 +0200 Subject: [PATCH 1929/5711] ASoC: omap-mcpdm: Add missing MODULE_ALIAS The MODULE_ALIAS() was missing from the driver. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 59d47ab5b15d..2c66e2498a45 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -527,6 +527,7 @@ static struct platform_driver asoc_mcpdm_driver = { module_platform_driver(asoc_mcpdm_driver); +MODULE_ALIAS("platform:omap-mcpdm"); MODULE_AUTHOR("Misael Lopez Cruz "); MODULE_DESCRIPTION("OMAP PDM SoC Interface"); MODULE_LICENSE("GPL"); -- GitLab From 336c5c310e8f0d5baba7973765339eaf5d989fe1 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 6 Jul 2012 14:13:52 +0800 Subject: [PATCH 1930/5711] usb: convert port_owners type from void * to struct dev_state * This patch is to convert port_owners type from void * to struct dev_state * in order to make code more readable. Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 21 ++++++++++++--------- drivers/usb/core/usb.h | 9 ++++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 25a7422ee657..4cc8dc96940e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -81,7 +81,7 @@ struct usb_hub { u8 indicator[USB_MAXCHILDREN]; struct delayed_work leds; struct delayed_work init_work; - void **port_owners; + struct dev_state **port_owners; }; static inline int hub_is_superspeed(struct usb_device *hdev) @@ -1271,7 +1271,8 @@ static int hub_configure(struct usb_hub *hub, hdev->children = kzalloc(hdev->maxchild * sizeof(struct usb_device *), GFP_KERNEL); - hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL); + hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), + GFP_KERNEL); if (!hdev->children || !hub->port_owners) { ret = -ENOMEM; goto fail; @@ -1649,7 +1650,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) * to one of these "claimed" ports, the program will "own" the device. */ static int find_port_owner(struct usb_device *hdev, unsigned port1, - void ***ppowner) + struct dev_state ***ppowner) { if (hdev->state == USB_STATE_NOTATTACHED) return -ENODEV; @@ -1664,10 +1665,11 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, } /* In the following three functions, the caller must hold hdev's lock */ -int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) +int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, + struct dev_state *owner) { int rc; - void **powner; + struct dev_state **powner; rc = find_port_owner(hdev, port1, &powner); if (rc) @@ -1678,10 +1680,11 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) return rc; } -int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) +int usb_hub_release_port(struct usb_device *hdev, unsigned port1, + struct dev_state *owner) { int rc; - void **powner; + struct dev_state **powner; rc = find_port_owner(hdev, port1, &powner); if (rc) @@ -1692,10 +1695,10 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) return rc; } -void usb_hub_release_all_ports(struct usb_device *hdev, void *owner) +void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) { int n; - void **powner; + struct dev_state **powner; n = find_port_owner(hdev, 1, &powner); if (n == 0) { diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 5c5c538ea73d..67875a89cfa1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,5 +1,7 @@ #include +struct dev_state; + /* Functions local to drivers/usb/core/ */ extern int usb_create_sysfs_dev_files(struct usb_device *dev); @@ -41,10 +43,11 @@ extern void usb_forced_unbind_intf(struct usb_interface *intf); extern void usb_rebind_intf(struct usb_interface *intf); extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, - void *owner); + struct dev_state *owner); extern int usb_hub_release_port(struct usb_device *hdev, unsigned port, - void *owner); -extern void usb_hub_release_all_ports(struct usb_device *hdev, void *owner); + struct dev_state *owner); +extern void usb_hub_release_all_ports(struct usb_device *hdev, + struct dev_state *owner); extern bool usb_device_is_owned(struct usb_device *udev); extern int usb_hub_init(void); -- GitLab From 74feec5dd83d879368c1081aec5b6a1cb6dd7ce2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 6 Jul 2012 14:03:18 -0400 Subject: [PATCH 1931/5711] random: fix up sparse warnings Add extern and static declarations to suppress sparse warnings Signed-off-by: "Theodore Ts'o" --- drivers/char/random.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ec04a754733..cb541b9a5231 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1279,6 +1279,7 @@ static int proc_do_uuid(ctl_table *table, int write, } static int sysctl_poolsize = INPUT_POOL_WORDS * 32; +extern ctl_table random_table[]; ctl_table random_table[] = { { .procname = "poolsize", @@ -1344,7 +1345,7 @@ late_initcall(random_int_secret_init); * value is not cryptographically secure but for several uses the cost of * depleting entropy is too high */ -DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); +static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); unsigned int get_random_int(void) { __u32 *hash; -- GitLab From 34767f8dccc326026f97cd63f759dd36bd83502d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 5 Jul 2012 15:17:42 +0200 Subject: [PATCH 1932/5711] ARM: mach-shmobile: select the fixed regulator driver on several boards On systems, using regulators to supply power to devices, if the REGULATOR Kconfig option is disabled, regulator API stubs will be used, which often suffices to bring a default configuration up. If REGULATOR is enabled but respective regulator drivers are inactive, the real regulator API calls will be used, which in the absence of drivers will fail to provide services. This patch prevents such a problem on sh-mobile boards by forcing REGULATOR_FIXED_VOLTAGE on if REGULATOR is selected. Signed-off-by: Guennadi Liakhovetski Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index df33909205e2..8854019651c0 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -58,6 +58,7 @@ config MACH_G4EVM bool "G4EVM board" depends on ARCH_SH7377 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_AP4EVB bool "AP4EVB board" @@ -65,6 +66,7 @@ config MACH_AP4EVB select ARCH_REQUIRE_GPIOLIB select SH_LCD_MIPI_DSI select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR choice prompt "AP4EVB LCD panel selection" @@ -83,6 +85,7 @@ config MACH_AG5EVM bool "AG5EVM board" select ARCH_REQUIRE_GPIOLIB select SH_LCD_MIPI_DSI + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_SH73A0 config MACH_MACKEREL @@ -90,15 +93,18 @@ config MACH_MACKEREL depends on ARCH_SH7372 select ARCH_REQUIRE_GPIOLIB select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KOTA2 bool "KOTA2 board" select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_SH73A0 config MACH_BONITO bool "bonito board" select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_R8A7740 config MACH_ARMADILLO800EVA @@ -106,22 +112,26 @@ config MACH_ARMADILLO800EVA depends on ARCH_R8A7740 select ARCH_REQUIRE_GPIOLIB select USE_OF + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_MARZEN bool "MARZEN board" depends on ARCH_R8A7779 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KZM9D bool "KZM9D board" depends on ARCH_EMEV2 select USE_OF + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KZM9G bool "KZM-A9-GT board" depends on ARCH_SH73A0 select ARCH_REQUIRE_GPIOLIB select USE_OF + select REGULATOR_FIXED_VOLTAGE if REGULATOR comment "SH-Mobile System Configuration" -- GitLab From 7078daa020db5ba501fa3de64b8653c221a640b4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 May 2012 04:34:34 -0300 Subject: [PATCH 1933/5711] [media] uvcvideo: Document the struct uvc_xu_control_query query field Several developers have reported that the lack of macros for the struct uvc_xu_control_query query field in uvcvideo.h was confusing and forced them to look at the driver source code to find out what applications were supposed to pass in that field. Add a comment to the header to clarify the expected usage of the query field. Reported-by: Paulo Assis Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/linux/uvcvideo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/uvcvideo.h b/include/linux/uvcvideo.h index f46a53f060d7..3b081862b9e8 100644 --- a/include/linux/uvcvideo.h +++ b/include/linux/uvcvideo.h @@ -58,7 +58,8 @@ struct uvc_xu_control_mapping { struct uvc_xu_control_query { __u8 unit; __u8 selector; - __u8 query; + __u8 query; /* Video Class-Specific Request Code, */ + /* defined in linux/usb/video.h A.8. */ __u16 size; __u8 __user *data; }; -- GitLab From c854a48a97feb94ccd4501593badd1b9907326c2 Mon Sep 17 00:00:00 2001 From: Jayakrishnan Date: Fri, 9 Mar 2012 10:10:49 -0300 Subject: [PATCH 1934/5711] [media] uvcvideo: Fix frame drop in bulk video stream When video endpoint is configured as bulk, a ZLP is sent after every video frames with size as multiple of 512 bytes. This is done so that host can detect end of transfer and pass data for processing. Still, frames that are multiple of 16K in size gets dropped. The ZLP sent by camera is ignored by uvc_video_decode_bulk(). The makes sure that the ZLP is not part of a video frame before ignoring it. If ZLP follows a video frame, then it triggers completion callback. [mchehab@redhat.com: Fix a small CodingStyle issue] Signed-off-by: Jayakrishnan Memana Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index b76b0ac0958f..39f5c85dd4b4 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1188,7 +1188,11 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, u8 *mem; int len, ret; - if (urb->actual_length == 0) + /* + * Ignore ZLPs if they're not part of a frame, otherwise process them + * to trigger the end of payload detection. + */ + if (urb->actual_length == 0 && stream->bulk.header_size == 0) return; mem = urb->transfer_buffer; -- GitLab From 4807063faa08f279b4ca9c2b1f0101a4670f7d43 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 Jun 2012 06:35:04 -0300 Subject: [PATCH 1935/5711] [media] uvcvideo: Fix alternate setting selection The alternate setting number is not equal to the alternate setting index in the interface alternate settings table. Use the alternate setting number from the interface descriptor when calling usb_set_interface(). Signed-off-by: Laurent Pinchart Signed-off-by: Ming Lei Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 39f5c85dd4b4..7ac4347ca09e 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1598,7 +1598,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); if (psize >= bandwidth && psize <= best_psize) { - altsetting = i; + altsetting = alts->desc.bAlternateSetting; best_psize = psize; best_ep = ep; } -- GitLab From d252f644789188743b55339f5756a8bcc86fbaa5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 6 Jul 2012 19:05:43 +0900 Subject: [PATCH 1936/5711] ARM: mach-shmobile: kzm9d: Add defconfig Original work by Magnus Damm, tested and tweaked by Simon Horman Signed-off-by: Magnus Damm Signed-off-by: Simon Horman Signed-off-by: Rafael J. Wysocki --- arch/arm/configs/kzm9d_defconfig | 89 ++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 arch/arm/configs/kzm9d_defconfig diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig new file mode 100644 index 000000000000..26146ffea1a5 --- /dev/null +++ b/arch/arm/configs/kzm9d_defconfig @@ -0,0 +1,89 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_EMEV2=y +CONFIG_MACH_KZM9D=y +CONFIG_MEMORY_START=0x40000000 +CONFIG_MEMORY_SIZE=0x10000000 +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_SWP_EMULATE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +# CONFIG_LOCAL_TIMERS is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_CMDLINE="console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" +CONFIG_CMDLINE_FORCE=y +CONFIG_VFP=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EM=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_EM=y +# CONFIG_HWMON is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +# CONFIG_FTRACE is not set -- GitLab From 993568d4912aa5f4692b060496a4a8d487b86515 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Jul 2012 15:11:15 -0300 Subject: [PATCH 1937/5711] [media] [V3] stv090x: variable 'no_signal' set but not used Remove variable and ignore return value of stv090x_chk_signal(). Tested by compilation only. [mchehab@redhat.com: instead of reverting and applying V3, applied just the diff patch, for the sake of a cleaner history] Signed-off-by: Peter Senna Tschudin Reviewed-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index d229dba42bef..ea86a5603e57 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3411,9 +3411,10 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) /* Reset the packet Error counter2 */ if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) goto err; - } else + } else { signal_state = STV090x_NODATA; - + stv090x_chk_signal(state); + } } return signal_state; -- GitLab From 8f45b112fc66ef6869ccca4c3966976982f496a9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:24:46 -0700 Subject: [PATCH 1938/5711] ARM: shmobile: soc-core: add R-mobile PM domain common APIs This patch adds Renesas R-mobile series common PM domain APIs. R-mobile CPU can use/switch this API Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/Makefile | 1 + .../mach-shmobile/include/mach/pm-rmobile.h | 44 +++++ arch/arm/mach-shmobile/pm-rmobile.c | 167 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 arch/arm/mach-shmobile/include/mach/pm-rmobile.h create mode 100644 arch/arm/mach-shmobile/pm-rmobile.c diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 8aa1962c22a2..3ffe4126922f 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o # PM objects obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o +obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h new file mode 100644 index 000000000000..5a402840fe28 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Renesas Solutions Corp. + * + * Kuninori Morimoto + * + * 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. + */ +#ifndef PM_RMOBILE_H +#define PM_RMOBILE_H + +#include + +struct platform_device; + +struct rmobile_pm_domain { + struct generic_pm_domain genpd; + struct dev_power_governor *gov; + int (*suspend)(void); + void (*resume)(void); + unsigned int bit_shift; + bool no_debug; +}; + +static inline +struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct rmobile_pm_domain, genpd); +} + +#ifdef CONFIG_PM +extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd); +extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, + struct platform_device *pdev); +extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, + struct rmobile_pm_domain *rmobile_sd); +#else +#define rmobile_init_pm_domain(pd) do { } while (0) +#define rmobile_add_device_to_domain(pd, pdev) do { } while (0) +#define rmobile_pm_add_subdomain(pd, sd) do { } while (0) +#endif /* CONFIG_PM */ + +#endif /* PM_RMOBILE_H */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c new file mode 100644 index 000000000000..a8562540f1d6 --- /dev/null +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -0,0 +1,167 @@ +/* + * rmobile power management support + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto + * + * based on pm-sh7372.c + * Copyright (C) 2011 Magnus Damm + * + * 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 +#include +#include +#include + +/* SYSC */ +#define SPDCR 0xe6180008 +#define SWUCR 0xe6180014 +#define PSTR 0xe6180080 + +#define PSTR_RETRIES 100 +#define PSTR_DELAY_US 10 + +#ifdef CONFIG_PM +static int rmobile_pd_power_down(struct generic_pm_domain *genpd) +{ + struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); + unsigned int mask = 1 << rmobile_pd->bit_shift; + + if (rmobile_pd->suspend) { + int ret = rmobile_pd->suspend(); + + if (ret) + return ret; + } + + if (__raw_readl(PSTR) & mask) { + unsigned int retry_count; + __raw_writel(mask, SPDCR); + + for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(SPDCR) & mask)) + break; + cpu_relax(); + } + } + + if (!rmobile_pd->no_debug) + pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", + genpd->name, mask, __raw_readl(PSTR)); + + return 0; +} + +static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, + bool do_resume) +{ + unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int retry_count; + int ret = 0; + + if (__raw_readl(PSTR) & mask) + goto out; + + __raw_writel(mask, SWUCR); + + for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(SWUCR) & mask)) + break; + if (retry_count > PSTR_RETRIES) + udelay(PSTR_DELAY_US); + else + cpu_relax(); + } + if (!retry_count) + ret = -EIO; + + if (!rmobile_pd->no_debug) + pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", + rmobile_pd->genpd.name, mask, __raw_readl(PSTR)); + +out: + if (ret == 0 && rmobile_pd->resume && do_resume) + rmobile_pd->resume(); + + return ret; +} + +static int rmobile_pd_power_up(struct generic_pm_domain *genpd) +{ + return __rmobile_pd_power_up(to_rmobile_pd(genpd), true); +} + +static bool rmobile_pd_active_wakeup(struct device *dev) +{ + bool (*active_wakeup)(struct device *dev); + + active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; + return active_wakeup ? active_wakeup(dev) : true; +} + +static int rmobile_pd_stop_dev(struct device *dev) +{ + int (*stop)(struct device *dev); + + stop = dev_gpd_data(dev)->ops.stop; + if (stop) { + int ret = stop(dev); + if (ret) + return ret; + } + return pm_clk_suspend(dev); +} + +static int rmobile_pd_start_dev(struct device *dev) +{ + int (*start)(struct device *dev); + int ret; + + ret = pm_clk_resume(dev); + if (ret) + return ret; + + start = dev_gpd_data(dev)->ops.start; + if (start) + ret = start(dev); + + return ret; +} + +void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) +{ + struct generic_pm_domain *genpd = &rmobile_pd->genpd; + struct dev_power_governor *gov = rmobile_pd->gov; + + pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); + genpd->dev_ops.stop = rmobile_pd_stop_dev; + genpd->dev_ops.start = rmobile_pd_start_dev; + genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; + genpd->dev_irq_safe = true; + genpd->power_off = rmobile_pd_power_down; + genpd->power_on = rmobile_pd_power_up; + __rmobile_pd_power_up(rmobile_pd, false); +} + +void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + pm_genpd_add_device(&rmobile_pd->genpd, dev); + if (pm_clk_no_clocks(dev)) + pm_clk_add(dev, NULL); +} + +void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, + struct rmobile_pm_domain *rmobile_sd) +{ + pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd); +} +#endif /* CONFIG_PM */ -- GitLab From 444c5ed8d746140cd8f5591f708e5f1f84a9876e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:25:24 -0700 Subject: [PATCH 1939/5711] ARM: shmobile: r8a7740: fixup: MSEL1CR 7bit control MSEL1CR 7bit selects IRQ7 source pin which was VBUS pin or A21/MSIOF0_RSYNC/MSIOF1_TSYNC pin. But current pfc-r8a7740 MSEL1CR 7bit setting was wrong. This patch fix it up Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pfc-r8a7740.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index 03def0fd7a05..ce9e7fa5cc8a 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c @@ -1261,7 +1261,7 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(A21_MARK, PORT120_FN1), PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT120_FN2), PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK, PORT120_FN3, MSEL4CR_10_0), - PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_0), + PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_1), /* Port121 */ PINMUX_DATA(A20_MARK, PORT121_FN1), @@ -1623,7 +1623,7 @@ static pinmux_enum_t pinmux_data[] = { /* Port209 */ PINMUX_DATA(VBUS_MARK, PORT209_FN1), - PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_1), + PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_0), /* Port210 */ PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), -- GitLab From 8459293c27bcd13aabacb7ee8097f6818f2ceedb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:25:58 -0700 Subject: [PATCH 1940/5711] ARM: shmobile: r8a7740: add A4S pm domain support This patch adds basic A4S pm domain support. Now, below devices can be controled by PM Common-SHwy, Common-HPB, BSC, MFI, MMFROM, HS-SHwy, SYS-HPB, INTCA, DBSC, DDRPHY (Logic), ATAPI, GbEther, AXI-bus Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/Makefile | 1 + arch/arm/mach-shmobile/include/mach/r8a7740.h | 6 ++++ arch/arm/mach-shmobile/pm-r8a7740.c | 30 +++++++++++++++++++ arch/arm/mach-shmobile/setup-r8a7740.c | 5 ++++ 4 files changed, 42 insertions(+) create mode 100644 arch/arm/mach-shmobile/pm-r8a7740.c diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 3ffe4126922f..0df5ae6740c6 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o +obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o # Board objects diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index 8bd7b9c136a1..e8c87e92a60d 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -19,6 +19,8 @@ #ifndef __ASM_R8A7740_H__ #define __ASM_R8A7740_H__ +#include + /* * MD_CKx pin */ @@ -604,4 +606,8 @@ enum { SHDMA_SLAVE_USBHS_RX, }; +#ifdef CONFIG_PM +extern struct rmobile_pm_domain r8a7740_pd_a4s; +#endif /* CONFIG_PM */ + #endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c new file mode 100644 index 000000000000..d2fe81570a74 --- /dev/null +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -0,0 +1,30 @@ +/* + * r8a7740 power management support + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto + * + * 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 + +#ifdef CONFIG_PM +static int r8a7740_pd_a4s_suspend(void) +{ + /* + * The A4S domain contains the CPU core and therefore it should + * only be turned off if the CPU is in use. + */ + return -EBUSY; +} + +struct rmobile_pm_domain r8a7740_pd_a4s = { + .genpd.name = "A4S", + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a4s_suspend, +}; +#endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 48d7bbf0d2e2..c37ad75151f3 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -671,6 +672,10 @@ void __init r8a7740_add_standard_devices(void) r8a7740_i2c_workaround(&i2c0_device); r8a7740_i2c_workaround(&i2c1_device); + /* PM domain */ + rmobile_init_pm_domain(&r8a7740_pd_a4s); + + /* add devices */ platform_add_devices(r8a7740_early_devices, ARRAY_SIZE(r8a7740_early_devices)); platform_add_devices(r8a7740_late_devices, -- GitLab From 802a5639aa7041b27cb865d3be289cd8afe3387b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:26:31 -0700 Subject: [PATCH 1941/5711] ARM: shmobile: r8a7740: add A3SP pm domain support This patch adds basic A3SP pm domain support. Now, below devices can be controled by PM DMAC1/2/3, IPMMU, DDM, FLCTL, SYS-HPB, BBIF1, MSIOF1/2, SCIFA,SCIFB, IIC1, IrDA, USBH, USBDMAC, SDHI0/1/2, TPU, DREQPAK (Sys), MMCIF, RSPI, SIM, USBF Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 + arch/arm/mach-shmobile/pm-r8a7740.c | 19 +++++++++++++++++++ arch/arm/mach-shmobile/setup-r8a7740.c | 16 ++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index e8c87e92a60d..a5691cf38475 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -608,6 +608,7 @@ enum { #ifdef CONFIG_PM extern struct rmobile_pm_domain r8a7740_pd_a4s; +extern struct rmobile_pm_domain r8a7740_pd_a3sp; #endif /* CONFIG_PM */ #endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index d2fe81570a74..de7c6214ce63 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -8,6 +8,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#include #include #ifdef CONFIG_PM @@ -27,4 +28,22 @@ struct rmobile_pm_domain r8a7740_pd_a4s = { .no_debug = true, .suspend = r8a7740_pd_a4s_suspend, }; + +static int r8a7740_pd_a3sp_suspend(void) +{ + /* + * Serial consoles make use of SCIF hardware located in A3SP, + * keep such power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +struct rmobile_pm_domain r8a7740_pd_a3sp = { + .genpd.name = "A3SP", + .bit_shift = 11, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a3sp_suspend, +}; + #endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index c37ad75151f3..59c794122804 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -674,12 +674,28 @@ void __init r8a7740_add_standard_devices(void) /* PM domain */ rmobile_init_pm_domain(&r8a7740_pd_a4s); + rmobile_init_pm_domain(&r8a7740_pd_a3sp); + + rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); /* add devices */ platform_add_devices(r8a7740_early_devices, ARRAY_SIZE(r8a7740_early_devices)); platform_add_devices(r8a7740_late_devices, ARRAY_SIZE(r8a7740_late_devices)); + + /* add devices to PM domain */ + + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device); } static void __init r8a7740_earlytimer_init(void) -- GitLab From a330ce3cdaba5202051edf8ae69482e15fdc9db5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:26:53 -0700 Subject: [PATCH 1942/5711] ARM: shmobile: r8a7740: add A4LC pm domain support This patch adds basic A4LC pm domain support. Now, below devices can be controled by PM MERAM, LCDC, VOU, ICBS, SDENC-Link Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 + arch/arm/mach-shmobile/pm-r8a7740.c | 5 +++++ arch/arm/mach-shmobile/setup-r8a7740.c | 1 + 3 files changed, 7 insertions(+) diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index a5691cf38475..7143147780df 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -609,6 +609,7 @@ enum { #ifdef CONFIG_PM extern struct rmobile_pm_domain r8a7740_pd_a4s; extern struct rmobile_pm_domain r8a7740_pd_a3sp; +extern struct rmobile_pm_domain r8a7740_pd_a4lc; #endif /* CONFIG_PM */ #endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index de7c6214ce63..893504d012a6 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -46,4 +46,9 @@ struct rmobile_pm_domain r8a7740_pd_a3sp = { .suspend = r8a7740_pd_a3sp_suspend, }; +struct rmobile_pm_domain r8a7740_pd_a4lc = { + .genpd.name = "A4LC", + .bit_shift = 1, +}; + #endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 59c794122804..c006d8ddbbe5 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -675,6 +675,7 @@ void __init r8a7740_add_standard_devices(void) /* PM domain */ rmobile_init_pm_domain(&r8a7740_pd_a4s); rmobile_init_pm_domain(&r8a7740_pd_a3sp); + rmobile_init_pm_domain(&r8a7740_pd_a4lc); rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); -- GitLab From d483b983a5efaa101714186a8485a5fd4de42fba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:27:14 -0700 Subject: [PATCH 1943/5711] ARM: shmobile: armadillo800eva: USB Func enables external IRQ mode We can control renesas_usbhs driver as 2 way which are autonomy mode and external IRQ trigger mode. Autonomy mode is very easy settings for platform, but it required USB power domain always ON, since its connection/disconnection IRQ come from it. If platform uses external IRQ trigger mode, USB power domain can be OFF, since its connection/disconnection IRQ come from external IRQ. This patch enable external IRQ mode. Now it is possible to add USB support on A4SP domain. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- .../arm/mach-shmobile/board-armadillo800eva.c | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 12f9666302fc..79891a6d0dec 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -133,14 +133,8 @@ * These are a little bit complex. * see * usbhsf_power_ctrl() - * - * CAUTION - * - * It uses autonomy mode for USB hotplug at this point - * (= usbhs_private.platform_callback.get_vbus is NULL), - * since we don't know what's happen on PM control - * on this workaround. */ +#define IRQ7 evt2irq(0x02e0) #define USBCR1 0xe605810a #define USBH 0xC6700000 #define USBH_USBCTR 0x10834 @@ -220,6 +214,20 @@ static void usbhsf_power_ctrl(struct platform_device *pdev, } } +static int usbhsf_get_vbus(struct platform_device *pdev) +{ + return gpio_get_value(GPIO_PORT209); +} + +static irqreturn_t usbhsf_interrupt(int irq, void *data) +{ + struct platform_device *pdev = data; + + renesas_usbhs_call_notify_hotplug(pdev); + + return IRQ_HANDLED; +} + static void usbhsf_hardware_exit(struct platform_device *pdev) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); @@ -243,11 +251,14 @@ static void usbhsf_hardware_exit(struct platform_device *pdev) priv->host = NULL; priv->func = NULL; priv->usbh_base = NULL; + + free_irq(IRQ7, pdev); } static int usbhsf_hardware_init(struct platform_device *pdev) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); + int ret; priv->phy = clk_get(&pdev->dev, "phy"); priv->usb24 = clk_get(&pdev->dev, "usb24"); @@ -267,6 +278,14 @@ static int usbhsf_hardware_init(struct platform_device *pdev) return -EIO; } + ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE, + dev_name(&pdev->dev), pdev); + if (ret) { + dev_err(&pdev->dev, "request_irq err\n"); + return ret; + } + irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH); + /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */ clk_set_rate(priv->usb24, clk_get_rate(clk_get_parent(priv->usb24))); @@ -278,6 +297,7 @@ static struct usbhsf_private usbhsf_private = { .info = { .platform_callback = { .get_id = usbhsf_get_id, + .get_vbus = usbhsf_get_vbus, .hardware_init = usbhsf_hardware_init, .hardware_exit = usbhsf_hardware_exit, .power_ctrl = usbhsf_power_ctrl, @@ -1018,7 +1038,17 @@ static void __init eva_init(void) /* USB Host */ } else { /* USB Func */ - gpio_request(GPIO_FN_VBUS, NULL); + /* + * A1 chip has 2 IRQ7 pin and it was controled by MSEL register. + * OTOH, usbhs interrupt needs its value (HI/LOW) to decide + * USB connection/disconnection (usbhsf_get_vbus()). + * This means we needs to select GPIO_FN_IRQ7_PORT209 first, + * and select GPIO_PORT209 here + */ + gpio_request(GPIO_FN_IRQ7_PORT209, NULL); + gpio_request(GPIO_PORT209, NULL); + gpio_direction_input(GPIO_PORT209); + platform_device_register(&usbhsf_device); } -- GitLab From 1000076a88d58acf77d8fa8bf5d2567425b8ea1b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:27:37 -0700 Subject: [PATCH 1944/5711] ARM: shmobile: armadillo800eva: A4LC domain includes LCDC It is possible to control LCDC under A4LC domain to reduce power. This patch enable it. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-armadillo800eva.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 79891a6d0dec..9038bc9d856e 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1177,6 +1177,9 @@ static void __init eva_init(void) ARRAY_SIZE(eva_devices)); eva_clock_init(); + + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); } static void __init eva_earlytimer_init(void) -- GitLab From 0f54788d8b4f7aa8d74b0a5a0ad706bcc216b3c7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:28:00 -0700 Subject: [PATCH 1945/5711] ARM: shmobile: armadillo800eva: A3SP domain includes USB Because USB Func is controlled by external IRQ mode, it is possible to control USB under A3SP domain to reduce power. This patch enables it. Armadillo800eva board switchs USB Host/Func by SW1.6, So, the device to adds into domain is selected on this patch. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 9038bc9d856e..aeb7a4db49f4 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -953,6 +953,8 @@ clock_error: #define GPIO_PORT8CR 0xe6050008 static void __init eva_init(void) { + struct platform_device *usb = NULL; + regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, ARRAY_SIZE(fixed3v3_power_consumers), 3300000); @@ -1050,6 +1052,7 @@ static void __init eva_init(void) gpio_direction_input(GPIO_PORT209); platform_device_register(&usbhsf_device); + usb = &usbhsf_device; } /* SDHI0 */ @@ -1180,6 +1183,8 @@ static void __init eva_init(void) rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); + if (usb) + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); } static void __init eva_earlytimer_init(void) -- GitLab From ebc04047b398d415627f82653c4e722e8fc2c083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Thu, 28 Jun 2012 12:12:13 -0300 Subject: [PATCH 1946/5711] [PATCH] media: add Analog Devices ADV7393 video encoder driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ADV7393 I²C-based video encoder driver. This driver has been tested on custom hardware. It has been tested for composite output. It is derived from the ADV7343 driver. Signed-off-by: Benoît Thébaudeau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 9 + drivers/media/video/Makefile | 1 + drivers/media/video/adv7393.c | 487 +++++++++++++++++++++++++++++ drivers/media/video/adv7393_regs.h | 188 +++++++++++ include/media/adv7393.h | 28 ++ include/media/v4l2-chip-ident.h | 3 + 6 files changed, 716 insertions(+) create mode 100644 drivers/media/video/adv7393.c create mode 100644 drivers/media/video/adv7393_regs.h create mode 100644 include/media/adv7393.h diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index da363c44fab2..c128fac0ce2c 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -462,6 +462,15 @@ config VIDEO_ADV7343 To compile this driver as a module, choose M here: the module will be called adv7343. +config VIDEO_ADV7393 + tristate "ADV7393 video encoder" + depends on I2C + help + Support for Analog Devices I2C bus based ADV7393 encoder. + + To compile this driver as a module, choose M here: the + module will be called adv7393. + config VIDEO_AK881X tristate "AK8813/AK8814 video encoders" depends on I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index d209de0e0ca8..b7da9faa3b0a 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o +obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o obj-$(CONFIG_VIDEO_VS6624) += vs6624.o obj-$(CONFIG_VIDEO_BT819) += bt819.o diff --git a/drivers/media/video/adv7393.c b/drivers/media/video/adv7393.c new file mode 100644 index 000000000000..3dc6098c7267 --- /dev/null +++ b/drivers/media/video/adv7393.c @@ -0,0 +1,487 @@ +/* + * adv7393 - ADV7393 Video Encoder Driver + * + * The encoder hardware does not support SECAM. + * + * Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * + * Based on ADV7343 driver, + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "adv7393_regs.h" + +MODULE_DESCRIPTION("ADV7393 video encoder driver"); +MODULE_LICENSE("GPL"); + +static bool debug; +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +struct adv7393_state { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + u8 reg00; + u8 reg01; + u8 reg02; + u8 reg35; + u8 reg80; + u8 reg82; + u32 output; + v4l2_std_id std; +}; + +static inline struct adv7393_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7393_state, sd); +} + +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, struct adv7393_state, hdl)->sd; +} + +static inline int adv7393_write(struct v4l2_subdev *sd, u8 reg, u8 value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, reg, value); +} + +static const u8 adv7393_init_reg_val[] = { + ADV7393_SOFT_RESET, ADV7393_SOFT_RESET_DEFAULT, + ADV7393_POWER_MODE_REG, ADV7393_POWER_MODE_REG_DEFAULT, + + ADV7393_HD_MODE_REG1, ADV7393_HD_MODE_REG1_DEFAULT, + ADV7393_HD_MODE_REG2, ADV7393_HD_MODE_REG2_DEFAULT, + ADV7393_HD_MODE_REG3, ADV7393_HD_MODE_REG3_DEFAULT, + ADV7393_HD_MODE_REG4, ADV7393_HD_MODE_REG4_DEFAULT, + ADV7393_HD_MODE_REG5, ADV7393_HD_MODE_REG5_DEFAULT, + ADV7393_HD_MODE_REG6, ADV7393_HD_MODE_REG6_DEFAULT, + ADV7393_HD_MODE_REG7, ADV7393_HD_MODE_REG7_DEFAULT, + + ADV7393_SD_MODE_REG1, ADV7393_SD_MODE_REG1_DEFAULT, + ADV7393_SD_MODE_REG2, ADV7393_SD_MODE_REG2_DEFAULT, + ADV7393_SD_MODE_REG3, ADV7393_SD_MODE_REG3_DEFAULT, + ADV7393_SD_MODE_REG4, ADV7393_SD_MODE_REG4_DEFAULT, + ADV7393_SD_MODE_REG5, ADV7393_SD_MODE_REG5_DEFAULT, + ADV7393_SD_MODE_REG6, ADV7393_SD_MODE_REG6_DEFAULT, + ADV7393_SD_MODE_REG7, ADV7393_SD_MODE_REG7_DEFAULT, + ADV7393_SD_MODE_REG8, ADV7393_SD_MODE_REG8_DEFAULT, + + ADV7393_SD_TIMING_REG0, ADV7393_SD_TIMING_REG0_DEFAULT, + + ADV7393_SD_HUE_ADJUST, ADV7393_SD_HUE_ADJUST_DEFAULT, + ADV7393_SD_CGMS_WSS0, ADV7393_SD_CGMS_WSS0_DEFAULT, + ADV7393_SD_BRIGHTNESS_WSS, ADV7393_SD_BRIGHTNESS_WSS_DEFAULT, +}; + +/* + * 2^32 + * FSC(reg) = FSC (HZ) * -------- + * 27000000 + */ +static const struct adv7393_std_info stdinfo[] = { + { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443, + }, { + /* FSC(Hz) = 3,579,545.45 Hz */ + SD_STD_NTSC, 569408542, V4L2_STD_NTSC, + }, { + /* FSC(Hz) = 3,575,611.00 Hz */ + SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M, + }, { + /* FSC(Hz) = 3,582,056.00 Hz */ + SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL, + }, +}; + +static int adv7393_setstd(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7393_state *state = to_state(sd); + const struct adv7393_std_info *std_info; + int num_std; + u8 reg; + u32 val; + int err = 0; + int i; + + num_std = ARRAY_SIZE(stdinfo); + + for (i = 0; i < num_std; i++) { + if (stdinfo[i].stdid & std) + break; + } + + if (i == num_std) { + v4l2_dbg(1, debug, sd, + "Invalid std or std is not supported: %llx\n", + (unsigned long long)std); + return -EINVAL; + } + + std_info = &stdinfo[i]; + + /* Set the standard */ + val = state->reg80 & ~SD_STD_MASK; + val |= std_info->standard_val3; + err = adv7393_write(sd, ADV7393_SD_MODE_REG1, val); + if (err < 0) + goto setstd_exit; + + state->reg80 = val; + + /* Configure the input mode register */ + val = state->reg01 & ~INPUT_MODE_MASK; + val |= SD_INPUT_MODE; + err = adv7393_write(sd, ADV7393_MODE_SELECT_REG, val); + if (err < 0) + goto setstd_exit; + + state->reg01 = val; + + /* Program the sub carrier frequency registers */ + val = std_info->fsc_val; + for (reg = ADV7393_FSC_REG0; reg <= ADV7393_FSC_REG3; reg++) { + err = adv7393_write(sd, reg, val); + if (err < 0) + goto setstd_exit; + val >>= 8; + } + + val = state->reg82; + + /* Pedestal settings */ + if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443)) + val |= SD_PEDESTAL_EN; + else + val &= SD_PEDESTAL_DI; + + err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val); + if (err < 0) + goto setstd_exit; + + state->reg82 = val; + +setstd_exit: + if (err != 0) + v4l2_err(sd, "Error setting std, write failed\n"); + + return err; +} + +static int adv7393_setoutput(struct v4l2_subdev *sd, u32 output_type) +{ + struct adv7393_state *state = to_state(sd); + u8 val; + int err = 0; + + if (output_type > ADV7393_SVIDEO_ID) { + v4l2_dbg(1, debug, sd, + "Invalid output type or output type not supported:%d\n", + output_type); + return -EINVAL; + } + + /* Enable Appropriate DAC */ + val = state->reg00 & 0x03; + + if (output_type == ADV7393_COMPOSITE_ID) + val |= ADV7393_COMPOSITE_POWER_VALUE; + else if (output_type == ADV7393_COMPONENT_ID) + val |= ADV7393_COMPONENT_POWER_VALUE; + else + val |= ADV7393_SVIDEO_POWER_VALUE; + + err = adv7393_write(sd, ADV7393_POWER_MODE_REG, val); + if (err < 0) + goto setoutput_exit; + + state->reg00 = val; + + /* Enable YUV output */ + val = state->reg02 | YUV_OUTPUT_SELECT; + err = adv7393_write(sd, ADV7393_MODE_REG0, val); + if (err < 0) + goto setoutput_exit; + + state->reg02 = val; + + /* configure SD DAC Output 1 bit */ + val = state->reg82; + if (output_type == ADV7393_COMPONENT_ID) + val &= SD_DAC_OUT1_DI; + else + val |= SD_DAC_OUT1_EN; + err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val); + if (err < 0) + goto setoutput_exit; + + state->reg82 = val; + + /* configure ED/HD Color DAC Swap bit to zero */ + val = state->reg35 & HD_DAC_SWAP_DI; + err = adv7393_write(sd, ADV7393_HD_MODE_REG6, val); + if (err < 0) + goto setoutput_exit; + + state->reg35 = val; + +setoutput_exit: + if (err != 0) + v4l2_err(sd, "Error setting output, write failed\n"); + + return err; +} + +static int adv7393_log_status(struct v4l2_subdev *sd) +{ + struct adv7393_state *state = to_state(sd); + + v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std); + v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" : + ((state->output == 1) ? "Component" : "S-Video")); + return 0; +} + +static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + return adv7393_write(sd, ADV7393_SD_BRIGHTNESS_WSS, + ctrl->val & SD_BRIGHTNESS_VALUE_MASK); + + case V4L2_CID_HUE: + return adv7393_write(sd, ADV7393_SD_HUE_ADJUST, + ctrl->val - ADV7393_HUE_MIN); + + case V4L2_CID_GAIN: + return adv7393_write(sd, ADV7393_DAC123_OUTPUT_LEVEL, + ctrl->val); + } + return -EINVAL; +} + +static int adv7393_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7393, 0); +} + +static const struct v4l2_ctrl_ops adv7393_ctrl_ops = { + .s_ctrl = adv7393_s_ctrl, +}; + +static const struct v4l2_subdev_core_ops adv7393_core_ops = { + .log_status = adv7393_log_status, + .g_chip_ident = adv7393_g_chip_ident, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, +}; + +static int adv7393_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7393_state *state = to_state(sd); + int err = 0; + + if (state->std == std) + return 0; + + err = adv7393_setstd(sd, std); + if (!err) + state->std = std; + + return err; +} + +static int adv7393_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) +{ + struct adv7393_state *state = to_state(sd); + int err = 0; + + if (state->output == output) + return 0; + + err = adv7393_setoutput(sd, output); + if (!err) + state->output = output; + + return err; +} + +static const struct v4l2_subdev_video_ops adv7393_video_ops = { + .s_std_output = adv7393_s_std_output, + .s_routing = adv7393_s_routing, +}; + +static const struct v4l2_subdev_ops adv7393_ops = { + .core = &adv7393_core_ops, + .video = &adv7393_video_ops, +}; + +static int adv7393_initialize(struct v4l2_subdev *sd) +{ + struct adv7393_state *state = to_state(sd); + int err = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(adv7393_init_reg_val); i += 2) { + + err = adv7393_write(sd, adv7393_init_reg_val[i], + adv7393_init_reg_val[i+1]); + if (err) { + v4l2_err(sd, "Error initializing\n"); + return err; + } + } + + /* Configure for default video standard */ + err = adv7393_setoutput(sd, state->output); + if (err < 0) { + v4l2_err(sd, "Error setting output during init\n"); + return -EINVAL; + } + + err = adv7393_setstd(sd, state->std); + if (err < 0) { + v4l2_err(sd, "Error setting std during init\n"); + return -EINVAL; + } + + return err; +} + +static int adv7393_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adv7393_state *state; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + state = kzalloc(sizeof(struct adv7393_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + + state->reg00 = ADV7393_POWER_MODE_REG_DEFAULT; + state->reg01 = 0x00; + state->reg02 = 0x20; + state->reg35 = ADV7393_HD_MODE_REG6_DEFAULT; + state->reg80 = ADV7393_SD_MODE_REG1_DEFAULT; + state->reg82 = ADV7393_SD_MODE_REG2_DEFAULT; + + state->output = ADV7393_COMPOSITE_ID; + state->std = V4L2_STD_NTSC; + + v4l2_i2c_subdev_init(&state->sd, client, &adv7393_ops); + + v4l2_ctrl_handler_init(&state->hdl, 3); + v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops, + V4L2_CID_BRIGHTNESS, ADV7393_BRIGHTNESS_MIN, + ADV7393_BRIGHTNESS_MAX, 1, + ADV7393_BRIGHTNESS_DEF); + v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops, + V4L2_CID_HUE, ADV7393_HUE_MIN, + ADV7393_HUE_MAX, 1, + ADV7393_HUE_DEF); + v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops, + V4L2_CID_GAIN, ADV7393_GAIN_MIN, + ADV7393_GAIN_MAX, 1, + ADV7393_GAIN_DEF); + state->sd.ctrl_handler = &state->hdl; + if (state->hdl.error) { + int err = state->hdl.error; + + v4l2_ctrl_handler_free(&state->hdl); + kfree(state); + return err; + } + v4l2_ctrl_handler_setup(&state->hdl); + + err = adv7393_initialize(&state->sd); + if (err) { + v4l2_ctrl_handler_free(&state->hdl); + kfree(state); + } + return err; +} + +static int adv7393_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct adv7393_state *state = to_state(sd); + + v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&state->hdl); + kfree(state); + + return 0; +} + +static const struct i2c_device_id adv7393_id[] = { + {"adv7393", 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, adv7393_id); + +static struct i2c_driver adv7393_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "adv7393", + }, + .probe = adv7393_probe, + .remove = adv7393_remove, + .id_table = adv7393_id, +}; +module_i2c_driver(adv7393_driver); diff --git a/drivers/media/video/adv7393_regs.h b/drivers/media/video/adv7393_regs.h new file mode 100644 index 000000000000..78968330f0be --- /dev/null +++ b/drivers/media/video/adv7393_regs.h @@ -0,0 +1,188 @@ +/* + * ADV7393 encoder related structure and register definitions + * + * Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * + * Based on ADV7343 driver, + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#ifndef ADV7393_REGS_H +#define ADV7393_REGS_H + +struct adv7393_std_info { + u32 standard_val3; + u32 fsc_val; + v4l2_std_id stdid; +}; + +/* Register offset macros */ +#define ADV7393_POWER_MODE_REG (0x00) +#define ADV7393_MODE_SELECT_REG (0x01) +#define ADV7393_MODE_REG0 (0x02) + +#define ADV7393_DAC123_OUTPUT_LEVEL (0x0B) + +#define ADV7393_SOFT_RESET (0x17) + +#define ADV7393_HD_MODE_REG1 (0x30) +#define ADV7393_HD_MODE_REG2 (0x31) +#define ADV7393_HD_MODE_REG3 (0x32) +#define ADV7393_HD_MODE_REG4 (0x33) +#define ADV7393_HD_MODE_REG5 (0x34) +#define ADV7393_HD_MODE_REG6 (0x35) + +#define ADV7393_HD_MODE_REG7 (0x39) + +#define ADV7393_SD_MODE_REG1 (0x80) +#define ADV7393_SD_MODE_REG2 (0x82) +#define ADV7393_SD_MODE_REG3 (0x83) +#define ADV7393_SD_MODE_REG4 (0x84) +#define ADV7393_SD_MODE_REG5 (0x86) +#define ADV7393_SD_MODE_REG6 (0x87) +#define ADV7393_SD_MODE_REG7 (0x88) +#define ADV7393_SD_MODE_REG8 (0x89) + +#define ADV7393_SD_TIMING_REG0 (0x8A) + +#define ADV7393_FSC_REG0 (0x8C) +#define ADV7393_FSC_REG1 (0x8D) +#define ADV7393_FSC_REG2 (0x8E) +#define ADV7393_FSC_REG3 (0x8F) + +#define ADV7393_SD_CGMS_WSS0 (0x99) + +#define ADV7393_SD_HUE_ADJUST (0xA0) +#define ADV7393_SD_BRIGHTNESS_WSS (0xA1) + +/* Default values for the registers */ +#define ADV7393_POWER_MODE_REG_DEFAULT (0x10) +#define ADV7393_HD_MODE_REG1_DEFAULT (0x3C) /* Changed Default + 720p EAV/SAV code*/ +#define ADV7393_HD_MODE_REG2_DEFAULT (0x01) /* Changed Pixel data + valid */ +#define ADV7393_HD_MODE_REG3_DEFAULT (0x00) /* Color delay 0 clks */ +#define ADV7393_HD_MODE_REG4_DEFAULT (0xEC) /* Changed */ +#define ADV7393_HD_MODE_REG5_DEFAULT (0x08) +#define ADV7393_HD_MODE_REG6_DEFAULT (0x00) +#define ADV7393_HD_MODE_REG7_DEFAULT (0x00) +#define ADV7393_SOFT_RESET_DEFAULT (0x02) +#define ADV7393_COMPOSITE_POWER_VALUE (0x10) +#define ADV7393_COMPONENT_POWER_VALUE (0x1C) +#define ADV7393_SVIDEO_POWER_VALUE (0x0C) +#define ADV7393_SD_HUE_ADJUST_DEFAULT (0x80) +#define ADV7393_SD_BRIGHTNESS_WSS_DEFAULT (0x00) + +#define ADV7393_SD_CGMS_WSS0_DEFAULT (0x10) + +#define ADV7393_SD_MODE_REG1_DEFAULT (0x10) +#define ADV7393_SD_MODE_REG2_DEFAULT (0xC9) +#define ADV7393_SD_MODE_REG3_DEFAULT (0x00) +#define ADV7393_SD_MODE_REG4_DEFAULT (0x00) +#define ADV7393_SD_MODE_REG5_DEFAULT (0x02) +#define ADV7393_SD_MODE_REG6_DEFAULT (0x8C) +#define ADV7393_SD_MODE_REG7_DEFAULT (0x14) +#define ADV7393_SD_MODE_REG8_DEFAULT (0x00) + +#define ADV7393_SD_TIMING_REG0_DEFAULT (0x0C) + +/* Bit masks for Mode Select Register */ +#define INPUT_MODE_MASK (0x70) +#define SD_INPUT_MODE (0x00) +#define HD_720P_INPUT_MODE (0x10) +#define HD_1080I_INPUT_MODE (0x10) + +/* Bit masks for Mode Register 0 */ +#define TEST_PATTERN_BLACK_BAR_EN (0x04) +#define YUV_OUTPUT_SELECT (0x20) +#define RGB_OUTPUT_SELECT (0xDF) + +/* Bit masks for SD brightness/WSS */ +#define SD_BRIGHTNESS_VALUE_MASK (0x7F) +#define SD_BLANK_WSS_DATA_MASK (0x80) + +/* Bit masks for soft reset register */ +#define SOFT_RESET (0x02) + +/* Bit masks for HD Mode Register 1 */ +#define OUTPUT_STD_MASK (0x03) +#define OUTPUT_STD_SHIFT (0) +#define OUTPUT_STD_EIA0_2 (0x00) +#define OUTPUT_STD_EIA0_1 (0x01) +#define OUTPUT_STD_FULL (0x02) +#define EMBEDDED_SYNC (0x04) +#define EXTERNAL_SYNC (0xFB) +#define STD_MODE_MASK (0x1F) +#define STD_MODE_SHIFT (3) +#define STD_MODE_720P (0x05) +#define STD_MODE_720P_25 (0x08) +#define STD_MODE_720P_30 (0x07) +#define STD_MODE_720P_50 (0x06) +#define STD_MODE_1080I (0x0D) +#define STD_MODE_1080I_25 (0x0E) +#define STD_MODE_1080P_24 (0x11) +#define STD_MODE_1080P_25 (0x10) +#define STD_MODE_1080P_30 (0x0F) +#define STD_MODE_525P (0x00) +#define STD_MODE_625P (0x03) + +/* Bit masks for SD Mode Register 1 */ +#define SD_STD_MASK (0x03) +#define SD_STD_NTSC (0x00) +#define SD_STD_PAL_BDGHI (0x01) +#define SD_STD_PAL_M (0x02) +#define SD_STD_PAL_N (0x03) +#define SD_LUMA_FLTR_MASK (0x07) +#define SD_LUMA_FLTR_SHIFT (2) +#define SD_CHROMA_FLTR_MASK (0x07) +#define SD_CHROMA_FLTR_SHIFT (5) + +/* Bit masks for SD Mode Register 2 */ +#define SD_PRPB_SSAF_EN (0x01) +#define SD_PRPB_SSAF_DI (0xFE) +#define SD_DAC_OUT1_EN (0x02) +#define SD_DAC_OUT1_DI (0xFD) +#define SD_PEDESTAL_EN (0x08) +#define SD_PEDESTAL_DI (0xF7) +#define SD_SQUARE_PIXEL_EN (0x10) +#define SD_SQUARE_PIXEL_DI (0xEF) +#define SD_PIXEL_DATA_VALID (0x40) +#define SD_ACTIVE_EDGE_EN (0x80) +#define SD_ACTIVE_EDGE_DI (0x7F) + +/* Bit masks for HD Mode Register 6 */ +#define HD_PRPB_SYNC_EN (0x04) +#define HD_PRPB_SYNC_DI (0xFB) +#define HD_DAC_SWAP_EN (0x08) +#define HD_DAC_SWAP_DI (0xF7) +#define HD_GAMMA_CURVE_A (0xEF) +#define HD_GAMMA_CURVE_B (0x10) +#define HD_GAMMA_EN (0x20) +#define HD_GAMMA_DI (0xDF) +#define HD_ADPT_FLTR_MODEA (0xBF) +#define HD_ADPT_FLTR_MODEB (0x40) +#define HD_ADPT_FLTR_EN (0x80) +#define HD_ADPT_FLTR_DI (0x7F) + +#define ADV7393_BRIGHTNESS_MAX (63) +#define ADV7393_BRIGHTNESS_MIN (-64) +#define ADV7393_BRIGHTNESS_DEF (0) +#define ADV7393_HUE_MAX (127) +#define ADV7393_HUE_MIN (-128) +#define ADV7393_HUE_DEF (0) +#define ADV7393_GAIN_MAX (64) +#define ADV7393_GAIN_MIN (-64) +#define ADV7393_GAIN_DEF (0) + +#endif diff --git a/include/media/adv7393.h b/include/media/adv7393.h new file mode 100644 index 000000000000..b28edf351842 --- /dev/null +++ b/include/media/adv7393.h @@ -0,0 +1,28 @@ +/* + * ADV7393 header file + * + * Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * + * Based on ADV7343 driver, + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#ifndef ADV7393_H +#define ADV7393_H + +#define ADV7393_COMPOSITE_ID (0) +#define ADV7393_COMPONENT_ID (1) +#define ADV7393_SVIDEO_ID (2) + +#endif /* End of #ifndef ADV7393_H */ diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 7395c815939d..58f914a40b20 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -180,6 +180,9 @@ enum { /* module adv7343: just ident 7343 */ V4L2_IDENT_ADV7343 = 7343, + /* module adv7393: just ident 7393 */ + V4L2_IDENT_ADV7393 = 7393, + /* module saa7706h: just ident 7706 */ V4L2_IDENT_SAA7706H = 7706, -- GitLab From b9299a72702adc6d4d52a7425689255784431daa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:28:32 -0700 Subject: [PATCH 1947/5711] ARM: shmobile: sh7372: add pm-rmobile domain support This patch adds pm-rmobile common API base PM domain. sh7372 CPU/platform will switch to using it from original implementation Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/sh7372.h | 11 +++ arch/arm/mach-shmobile/pm-sh7372.c | 84 +++++++++++++++++++- arch/arm/mach-shmobile/setup-sh7372.c | 41 ++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 915d0093da08..a7620c1afceb 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -13,6 +13,7 @@ #include #include +#include /* * Pin Function Controller: @@ -494,6 +495,16 @@ static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) } #ifdef CONFIG_PM +extern struct rmobile_pm_domain sh7372_pd_a4lc; +extern struct rmobile_pm_domain sh7372_pd_a4mp; +extern struct rmobile_pm_domain sh7372_pd_d4; +extern struct rmobile_pm_domain sh7372_pd_a4r; +extern struct rmobile_pm_domain sh7372_pd_a3rv; +extern struct rmobile_pm_domain sh7372_pd_a3ri; +extern struct rmobile_pm_domain sh7372_pd_a4s; +extern struct rmobile_pm_domain sh7372_pd_a3sp; +extern struct rmobile_pm_domain sh7372_pd_a3sg; + extern struct sh7372_pm_domain sh7372_a4lc; extern struct sh7372_pm_domain sh7372_a4mp; extern struct sh7372_pm_domain sh7372_d4; diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index a38be7f06d6a..3b131c7a79d0 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -26,6 +26,7 @@ #include #include #include +#include /* DBG */ #define DBGREG1 0xe6100020 @@ -290,6 +291,85 @@ struct sh7372_pm_domain sh7372_a3sg = { .genpd.name = "A3SG", .bit_shift = 13, }; + +struct rmobile_pm_domain sh7372_pd_a4lc = { + .genpd.name = "A4LC", + .bit_shift = 1, +}; + +struct rmobile_pm_domain sh7372_pd_a4mp = { + .genpd.name = "A4MP", + .bit_shift = 2, +}; + +struct rmobile_pm_domain sh7372_pd_d4 = { + .genpd.name = "D4", + .bit_shift = 3, +}; + +static int sh7372_a4r_pd_suspend(void) +{ + sh7372_intcs_suspend(); + __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ + return 0; +} + +struct rmobile_pm_domain sh7372_pd_a4r = { + .genpd.name = "A4R", + .bit_shift = 5, + .suspend = sh7372_a4r_pd_suspend, + .resume = sh7372_intcs_resume, +}; + +struct rmobile_pm_domain sh7372_pd_a3rv = { + .genpd.name = "A3RV", + .bit_shift = 6, +}; + +struct rmobile_pm_domain sh7372_pd_a3ri = { + .genpd.name = "A3RI", + .bit_shift = 8, +}; + +static int sh7372_pd_a4s_suspend(void) +{ + /* + * The A4S domain contains the CPU core and therefore it should + * only be turned off if the CPU is in use. + */ + return -EBUSY; +} + +struct rmobile_pm_domain sh7372_pd_a4s = { + .genpd.name = "A4S", + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = sh7372_pd_a4s_suspend, +}; + +static int sh7372_a3sp_pd_suspend(void) +{ + /* + * Serial consoles make use of SCIF hardware located in A3SP, + * keep such power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +struct rmobile_pm_domain sh7372_pd_a3sp = { + .genpd.name = "A3SP", + .bit_shift = 11, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = sh7372_a3sp_pd_suspend, +}; + +struct rmobile_pm_domain sh7372_pd_a3sg = { + .genpd.name = "A3SG", + .bit_shift = 13, +}; + #endif /* CONFIG_PM */ #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) @@ -531,7 +611,7 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) /* check active clocks to determine potential wakeup sources */ if (sh7372_sysc_valid(&msk, &msk2)) { if (!console_suspend_enabled && - sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { + sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) { /* convert INTC mask/sense to SYSC mask/sense */ sh7372_setup_sysc(msk, msk2); @@ -565,7 +645,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier, * executed during system suspend and resume, respectively, so * that those functions don't crash while accessing the INTCS. */ - pm_genpd_poweron(&sh7372_a4r.genpd); + pm_genpd_poweron(&sh7372_pd_a4r.genpd); break; case PM_POST_SUSPEND: pm_genpd_poweroff_unused(); diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 4f473320f921..3648b35c238b 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1017,6 +1017,22 @@ void __init sh7372_add_standard_devices(void) sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg); sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp); + rmobile_init_pm_domain(&sh7372_pd_a4lc); + rmobile_init_pm_domain(&sh7372_pd_a4mp); + rmobile_init_pm_domain(&sh7372_pd_d4); + rmobile_init_pm_domain(&sh7372_pd_a4r); + rmobile_init_pm_domain(&sh7372_pd_a3rv); + rmobile_init_pm_domain(&sh7372_pd_a3ri); + rmobile_init_pm_domain(&sh7372_pd_a4s); + rmobile_init_pm_domain(&sh7372_pd_a3sp); + rmobile_init_pm_domain(&sh7372_pd_a3sg); + + rmobile_pm_add_subdomain(&sh7372_pd_a4lc, &sh7372_pd_a3rv); + rmobile_pm_add_subdomain(&sh7372_pd_a4r, &sh7372_pd_a4lc); + + rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sg); + rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sp); + platform_add_devices(sh7372_early_devices, ARRAY_SIZE(sh7372_early_devices)); @@ -1047,6 +1063,31 @@ void __init sh7372_add_standard_devices(void) sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device); sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device); + + rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif2_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif3_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif4_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif5_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif6_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &iic1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma2_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &iic0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu2_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu3_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &jpu_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu00_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu01_device); } static void __init sh7372_earlytimer_init(void) -- GitLab From aa7541fd682110352b85d241021fe24bfe8a41c5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:28:54 -0700 Subject: [PATCH 1948/5711] ARM: shmobile: mackerel: switch to using pm-rmobile API This patch switches mackerel platform to use pm-rmobile base common API. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-mackerel.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index b577f7c44678..52170b1d017c 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -1611,20 +1611,20 @@ static void __init mackerel_init(void) platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &nand_flash_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); #endif - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device); - sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); hdmi_init_pm_clock(); sh7372_pm_init(); -- GitLab From c99cc71efdaecf2e32608fba474bb0fd096b49ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:29:17 -0700 Subject: [PATCH 1949/5711] ARM: shmobile: ap4evb: switch to using pm-rmobile API This patch switches ap4evb platform to use pm-rmobile base common API. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-ap4evb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index ace60246a5df..7cac1df3085c 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -1447,14 +1447,14 @@ static void __init ap4evb_init(void) platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); - - sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); + + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); hdmi_init_pm_clock(); fsi_init_pm_clock(); -- GitLab From 3aa99a3498403d23fe4a0cfa4fcbbedaf7c8134a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 5 Jul 2012 01:29:37 -0700 Subject: [PATCH 1950/5711] ARM: shmobile: sh7372: completely switch over to using pm-rmobile API Now, all sh7372 platforms are switched over to use pm-rmobile base PM domain, and no one is using original sh7372_pm_domain APIs. We can remove these, switching has been fully completed. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/include/mach/sh7372.h | 36 --- arch/arm/mach-shmobile/pm-sh7372.c | 221 ------------------- arch/arm/mach-shmobile/setup-sh7372.c | 41 ---- 3 files changed, 298 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index a7620c1afceb..b59048e6d8fd 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -478,22 +478,6 @@ extern struct clk sh7372_fsibck_clk; extern struct clk sh7372_fsidiva_clk; extern struct clk sh7372_fsidivb_clk; -struct platform_device; - -struct sh7372_pm_domain { - struct generic_pm_domain genpd; - struct dev_power_governor *gov; - int (*suspend)(void); - void (*resume)(void); - unsigned int bit_shift; - bool no_debug; -}; - -static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct sh7372_pm_domain, genpd); -} - #ifdef CONFIG_PM extern struct rmobile_pm_domain sh7372_pd_a4lc; extern struct rmobile_pm_domain sh7372_pd_a4mp; @@ -504,26 +488,6 @@ extern struct rmobile_pm_domain sh7372_pd_a3ri; extern struct rmobile_pm_domain sh7372_pd_a4s; extern struct rmobile_pm_domain sh7372_pd_a3sp; extern struct rmobile_pm_domain sh7372_pd_a3sg; - -extern struct sh7372_pm_domain sh7372_a4lc; -extern struct sh7372_pm_domain sh7372_a4mp; -extern struct sh7372_pm_domain sh7372_d4; -extern struct sh7372_pm_domain sh7372_a4r; -extern struct sh7372_pm_domain sh7372_a3rv; -extern struct sh7372_pm_domain sh7372_a3ri; -extern struct sh7372_pm_domain sh7372_a4s; -extern struct sh7372_pm_domain sh7372_a3sp; -extern struct sh7372_pm_domain sh7372_a3sg; - -extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); -extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, - struct platform_device *pdev); -extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, - struct sh7372_pm_domain *sh7372_sd); -#else -#define sh7372_init_pm_domain(pd) do { } while(0) -#define sh7372_add_device_to_domain(pd, pdev) do { } while(0) -#define sh7372_pm_add_subdomain(pd, sd) do { } while(0) #endif /* CONFIG_PM */ extern void sh7372_intcs_suspend(void); diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 3b131c7a79d0..6a23e7c449ea 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -42,13 +42,10 @@ #define PLLC01STPCR 0xe61500c8 /* SYSC */ -#define SPDCR 0xe6180008 -#define SWUCR 0xe6180014 #define SBAR 0xe6180020 #define WUPRMSK 0xe6180028 #define WUPSMSK 0xe618002c #define WUPSMSK2 0xe6180048 -#define PSTR 0xe6180080 #define WUPSFAC 0xe6180098 #define IRQCR 0xe618022c #define IRQCR2 0xe6180238 @@ -72,226 +69,8 @@ /* AP-System Core */ #define APARMBAREA 0xe6f10020 -#define PSTR_RETRIES 100 -#define PSTR_DELAY_US 10 - #ifdef CONFIG_PM -static int pd_power_down(struct generic_pm_domain *genpd) -{ - struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); - unsigned int mask = 1 << sh7372_pd->bit_shift; - - if (sh7372_pd->suspend) { - int ret = sh7372_pd->suspend(); - - if (ret) - return ret; - } - - if (__raw_readl(PSTR) & mask) { - unsigned int retry_count; - - __raw_writel(mask, SPDCR); - - for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SPDCR) & mask)) - break; - cpu_relax(); - } - } - - if (!sh7372_pd->no_debug) - pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", - genpd->name, mask, __raw_readl(PSTR)); - - return 0; -} - -static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume) -{ - unsigned int mask = 1 << sh7372_pd->bit_shift; - unsigned int retry_count; - int ret = 0; - - if (__raw_readl(PSTR) & mask) - goto out; - - __raw_writel(mask, SWUCR); - - for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SWUCR) & mask)) - break; - if (retry_count > PSTR_RETRIES) - udelay(PSTR_DELAY_US); - else - cpu_relax(); - } - if (!retry_count) - ret = -EIO; - - if (!sh7372_pd->no_debug) - pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - sh7372_pd->genpd.name, mask, __raw_readl(PSTR)); - - out: - if (ret == 0 && sh7372_pd->resume && do_resume) - sh7372_pd->resume(); - - return ret; -} - -static int pd_power_up(struct generic_pm_domain *genpd) -{ - return __pd_power_up(to_sh7372_pd(genpd), true); -} - -static int sh7372_a4r_suspend(void) -{ - sh7372_intcs_suspend(); - __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ - return 0; -} - -static bool pd_active_wakeup(struct device *dev) -{ - bool (*active_wakeup)(struct device *dev); - - active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; - return active_wakeup ? active_wakeup(dev) : true; -} - -static int sh7372_stop_dev(struct device *dev) -{ - int (*stop)(struct device *dev); - - stop = dev_gpd_data(dev)->ops.stop; - if (stop) { - int ret = stop(dev); - if (ret) - return ret; - } - return pm_clk_suspend(dev); -} - -static int sh7372_start_dev(struct device *dev) -{ - int (*start)(struct device *dev); - int ret; - - ret = pm_clk_resume(dev); - if (ret) - return ret; - - start = dev_gpd_data(dev)->ops.start; - if (start) - ret = start(dev); - - return ret; -} - -void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) -{ - struct generic_pm_domain *genpd = &sh7372_pd->genpd; - struct dev_power_governor *gov = sh7372_pd->gov; - - pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); - genpd->dev_ops.stop = sh7372_stop_dev; - genpd->dev_ops.start = sh7372_start_dev; - genpd->dev_ops.active_wakeup = pd_active_wakeup; - genpd->dev_irq_safe = true; - genpd->power_off = pd_power_down; - genpd->power_on = pd_power_up; - __pd_power_up(sh7372_pd, false); -} - -void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, - struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - - pm_genpd_add_device(&sh7372_pd->genpd, dev); - if (pm_clk_no_clocks(dev)) - pm_clk_add(dev, NULL); -} - -void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, - struct sh7372_pm_domain *sh7372_sd) -{ - pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd); -} - -struct sh7372_pm_domain sh7372_a4lc = { - .genpd.name = "A4LC", - .bit_shift = 1, -}; - -struct sh7372_pm_domain sh7372_a4mp = { - .genpd.name = "A4MP", - .bit_shift = 2, -}; - -struct sh7372_pm_domain sh7372_d4 = { - .genpd.name = "D4", - .bit_shift = 3, -}; - -struct sh7372_pm_domain sh7372_a4r = { - .genpd.name = "A4R", - .bit_shift = 5, - .suspend = sh7372_a4r_suspend, - .resume = sh7372_intcs_resume, -}; - -struct sh7372_pm_domain sh7372_a3rv = { - .genpd.name = "A3RV", - .bit_shift = 6, -}; - -struct sh7372_pm_domain sh7372_a3ri = { - .genpd.name = "A3RI", - .bit_shift = 8, -}; - -static int sh7372_a4s_suspend(void) -{ - /* - * The A4S domain contains the CPU core and therefore it should - * only be turned off if the CPU is in use. - */ - return -EBUSY; -} - -struct sh7372_pm_domain sh7372_a4s = { - .genpd.name = "A4S", - .bit_shift = 10, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = sh7372_a4s_suspend, -}; - -static int sh7372_a3sp_suspend(void) -{ - /* - * Serial consoles make use of SCIF hardware located in A3SP, - * keep such power domain on if "no_console_suspend" is set. - */ - return console_suspend_enabled ? 0 : -EBUSY; -} - -struct sh7372_pm_domain sh7372_a3sp = { - .genpd.name = "A3SP", - .bit_shift = 11, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = sh7372_a3sp_suspend, -}; - -struct sh7372_pm_domain sh7372_a3sg = { - .genpd.name = "A3SG", - .bit_shift = 13, -}; - struct rmobile_pm_domain sh7372_pd_a4lc = { .genpd.name = "A4LC", .bit_shift = 1, diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 3648b35c238b..04eef92b891c 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1001,22 +1001,6 @@ static struct platform_device *sh7372_late_devices[] __initdata = { void __init sh7372_add_standard_devices(void) { - sh7372_init_pm_domain(&sh7372_a4lc); - sh7372_init_pm_domain(&sh7372_a4mp); - sh7372_init_pm_domain(&sh7372_d4); - sh7372_init_pm_domain(&sh7372_a4r); - sh7372_init_pm_domain(&sh7372_a3rv); - sh7372_init_pm_domain(&sh7372_a3ri); - sh7372_init_pm_domain(&sh7372_a4s); - sh7372_init_pm_domain(&sh7372_a3sp); - sh7372_init_pm_domain(&sh7372_a3sg); - - sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); - sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); - - sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg); - sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp); - rmobile_init_pm_domain(&sh7372_pd_a4lc); rmobile_init_pm_domain(&sh7372_pd_a4mp); rmobile_init_pm_domain(&sh7372_pd_d4); @@ -1039,31 +1023,6 @@ void __init sh7372_add_standard_devices(void) platform_add_devices(sh7372_late_devices, ARRAY_SIZE(sh7372_late_devices)); - sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); - sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); - sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device); - sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device); - rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device); rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device); rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device); -- GitLab From 755d57b2229bd8cfa1d553c0b6878f2096f55ec3 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 6 Jul 2012 17:08:07 +0900 Subject: [PATCH 1951/5711] ARM: mach-shmobile: r8a7740 generic board support via DT Add generic DT board support for the r8a7740 SoC. SCIF serial ports and timers are kept as regular platform devices. Other on-chip and on-board devices should be configured via the device tree. At this point there is no interrupt controller support in place but such code will be added over time when proper IRQ domain support has been added to INTC. Signed-off-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/boot/dts/r8a7740.dtsi | 21 ++++++++++++ arch/arm/mach-shmobile/setup-r8a7740.c | 47 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 arch/arm/boot/dts/r8a7740.dtsi diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi new file mode 100644 index 000000000000..798fa35c0005 --- /dev/null +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -0,0 +1,21 @@ +/* + * Device Tree Source for the r8a7740 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,r8a7740"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a9"; + }; + }; +}; diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index c006d8ddbbe5..78948a9dba0e 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -716,3 +717,49 @@ void __init r8a7740_add_early_devices(void) /* override timer setup with soc-specific code */ shmobile_timer.init = r8a7740_earlytimer_init; } + +#ifdef CONFIG_USE_OF + +void __init r8a7740_add_early_devices_dt(void) +{ + shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */ + + early_platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + + /* setup early console here as well */ + shmobile_setup_console(); +} + +static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = { + { } +}; + +void __init r8a7740_add_standard_devices_dt(void) +{ + /* clocks are setup late during boot in the case of DT */ + r8a7740_clock_init(0); + + platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + + of_platform_populate(NULL, of_default_bus_match_table, + r8a7740_auxdata_lookup, NULL); +} + +static const char *r8a7740_boards_compat_dt[] __initdata = { + "renesas,r8a7740", + NULL, +}; + +DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)") + .map_io = r8a7740_map_io, + .init_early = r8a7740_add_early_devices_dt, + .init_irq = r8a7740_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = r8a7740_add_standard_devices_dt, + .timer = &shmobile_timer, + .dt_compat = r8a7740_boards_compat_dt, +MACHINE_END + +#endif /* CONFIG_USE_OF */ -- GitLab From c54d6eca4f717b44e26ca8f91fbf2314d083625e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 6 Jul 2012 17:10:02 +0900 Subject: [PATCH 1952/5711] ARM: mach-shmobile: sh7377 generic board support via DT Add generic DT board support for the sh7377 SoC. SCIF serial ports and timers are kept as regular platform devices. Other on-chip and on-board devices should be configured via the device tree. At this point there is no interrupt controller support in place but such code will be added over time when proper IRQ domain support has been added to INTC. Signed-off-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/boot/dts/sh7377.dtsi | 21 ++++++++++++ arch/arm/mach-shmobile/setup-sh7377.c | 47 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 arch/arm/boot/dts/sh7377.dtsi diff --git a/arch/arm/boot/dts/sh7377.dtsi b/arch/arm/boot/dts/sh7377.dtsi new file mode 100644 index 000000000000..767ee0796daa --- /dev/null +++ b/arch/arm/boot/dts/sh7377.dtsi @@ -0,0 +1,21 @@ +/* + * Device Tree Source for the sh7377 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,sh7377"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a8"; + }; + }; +}; diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c index d576a6abbade..855b1506caf8 100644 --- a/arch/arm/mach-shmobile/setup-sh7377.c +++ b/arch/arm/mach-shmobile/setup-sh7377.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -500,3 +501,49 @@ void __init sh7377_add_early_devices(void) /* override timer setup with soc-specific code */ shmobile_timer.init = sh7377_earlytimer_init; } + +#ifdef CONFIG_USE_OF + +void __init sh7377_add_early_devices_dt(void) +{ + shmobile_setup_delay(600, 1, 3); /* Cortex-A8 @ 600MHz */ + + early_platform_add_devices(sh7377_early_devices, + ARRAY_SIZE(sh7377_early_devices)); + + /* setup early console here as well */ + shmobile_setup_console(); +} + +static const struct of_dev_auxdata sh7377_auxdata_lookup[] __initconst = { + { } +}; + +void __init sh7377_add_standard_devices_dt(void) +{ + /* clocks are setup late during boot in the case of DT */ + sh7377_clock_init(); + + platform_add_devices(sh7377_early_devices, + ARRAY_SIZE(sh7377_early_devices)); + + of_platform_populate(NULL, of_default_bus_match_table, + sh7377_auxdata_lookup, NULL); +} + +static const char *sh7377_boards_compat_dt[] __initdata = { + "renesas,sh7377", + NULL, +}; + +DT_MACHINE_START(SH7377_DT, "Generic SH7377 (Flattened Device Tree)") + .map_io = sh7377_map_io, + .init_early = sh7377_add_early_devices_dt, + .init_irq = sh7377_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = sh7377_add_standard_devices_dt, + .timer = &shmobile_timer, + .dt_compat = sh7377_boards_compat_dt, +MACHINE_END + +#endif /* CONFIG_USE_OF */ -- GitLab From b61097ee1a99b5689f044895470ef44e7cc73c27 Mon Sep 17 00:00:00 2001 From: Thomas Betker Date: Sun, 1 Jul 2012 10:22:08 -0300 Subject: [PATCH 1953/5711] [media] bttv-cards.c: Allow radio for CHP05x/CHP06x Add ".has_radio = 1" for BTTV_BOARD_MAGICTVIEW061 because there are some CHP05x/CHP06x boards with a radio tuner. I still have an analog Askey Magic TView card (CHP051, PCI 144f:3002) which I use for radio only. This worked fine with kernel 2.6.37 (openSUSE 11.4), but no longer works with kernel 3.1.10 (openSUSE 12.1). The reason apparently is that ".has_radio = 1" is missing in bttv-cards.c for BTTV_BOARD_MAGICTVIEW061; when I add this line and recompile the kernel, radio is working again. The line is still missing in the latest git tree, for which I have generated the attached patch. I can't test what will happen for CHP05x/CHP06x devices without radio; however, it seems that other cards also have the problem that there are some boards with radio and some without, so I hope that this can be sorted out. Signed-off-by: Thomas Betker Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 856ab962cd63..5f3a00c2c4f6 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -676,6 +676,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .has_remote = 1, + .has_radio = 1, /* not every card has radio */ }, [BTTV_BOARD_VOBIS_BOOSTAR] = { .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", -- GitLab From 4839e6c2ac7c1a25d285b66240e702bb9b5fdcbf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Jun 2012 05:23:40 -0300 Subject: [PATCH 1954/5711] [media] v4l2-ioctl.c: move a block of code down, no other changes A block of code is moved down in the code to make later changes easier. Do just the move without other changes to keep the diff readable for the upcoming patch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 288 +++++++++++++++---------------- 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index d7fa8962d8b3..46fd95327630 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -183,150 +183,6 @@ static const char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ -struct v4l2_ioctl_info { - unsigned int ioctl; - u16 flags; - const char * const name; -}; - -/* This control needs a priority check */ -#define INFO_FL_PRIO (1 << 0) -/* This control can be valid if the filehandle passes a control handler. */ -#define INFO_FL_CTRL (1 << 1) - -#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl, \ - .flags = _flags, \ - .name = #_ioctl, \ -} - -static struct v4l2_ioctl_info v4l2_ioctls[] = { - IOCTL_INFO(VIDIOC_QUERYCAP, 0), - IOCTL_INFO(VIDIOC_ENUM_FMT, 0), - IOCTL_INFO(VIDIOC_G_FMT, 0), - IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYBUF, 0), - IOCTL_INFO(VIDIOC_G_FBUF, 0), - IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QBUF, 0), - IOCTL_INFO(VIDIOC_DQBUF, 0), - IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_PARM, 0), - IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_STD, 0), - IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUMSTD, 0), - IOCTL_INFO(VIDIOC_ENUMINPUT, 0), - IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_G_TUNER, 0), - IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_AUDIO, 0), - IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_G_INPUT, 0), - IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_OUTPUT, 0), - IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0), - IOCTL_INFO(VIDIOC_G_AUDOUT, 0), - IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_MODULATOR, 0), - IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_FREQUENCY, 0), - IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_CROPCAP, 0), - IOCTL_INFO(VIDIOC_G_CROP, 0), - IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_SELECTION, 0), - IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), - IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYSTD, 0), - IOCTL_INFO(VIDIOC_TRY_FMT, 0), - IOCTL_INFO(VIDIOC_ENUMAUDIO, 0), - IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0), - IOCTL_INFO(VIDIOC_G_PRIORITY, 0), - IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0), - IOCTL_INFO(VIDIOC_LOG_STATUS, 0), - IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0), - IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0), - IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0), - IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0), - IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0), - IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0), -#ifdef CONFIG_VIDEO_ADV_DEBUG - IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), - IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), -#endif - IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), - IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), - IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_DV_PRESET, 0), - IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0), - IOCTL_INFO(VIDIOC_S_DV_TIMINGS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0), - IOCTL_INFO(VIDIOC_DQEVENT, 0), - IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0), - IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0), - IOCTL_INFO(VIDIOC_CREATE_BUFS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_PREPARE_BUF, 0), - IOCTL_INFO(VIDIOC_ENUM_DV_TIMINGS, 0), - IOCTL_INFO(VIDIOC_QUERY_DV_TIMINGS, 0), - IOCTL_INFO(VIDIOC_DV_TIMINGS_CAP, 0), -}; -#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) - -bool v4l2_is_known_ioctl(unsigned int cmd) -{ - if (_IOC_NR(cmd) >= V4L2_IOCTLS) - return false; - return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; -} - -/* Common ioctl debug function. This function can be used by - external ioctl messages as well as internal V4L ioctl */ -void v4l_printk_ioctl(unsigned int cmd) -{ - char *dir, *type; - - switch (_IOC_TYPE(cmd)) { - case 'd': - type = "v4l2_int"; - break; - case 'V': - if (_IOC_NR(cmd) >= V4L2_IOCTLS) { - type = "v4l2"; - break; - } - printk("%s", v4l2_ioctls[_IOC_NR(cmd)].name); - return; - default: - type = "unknown"; - } - - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: dir = "--"; break; - case _IOC_READ: dir = "r-"; break; - case _IOC_WRITE: dir = "-w"; break; - case _IOC_READ | _IOC_WRITE: dir = "rw"; break; - default: dir = "*ERR*"; break; - } - printk("%s ioctl '%c', dir=%s, #%d (0x%08x)", - type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); -} -EXPORT_SYMBOL(v4l_printk_ioctl); - static void dbgbuf(unsigned int cmd, struct video_device *vfd, struct v4l2_buffer *p) { @@ -536,6 +392,150 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) return -EINVAL; } +struct v4l2_ioctl_info { + unsigned int ioctl; + u16 flags; + const char * const name; +}; + +/* This control needs a priority check */ +#define INFO_FL_PRIO (1 << 0) +/* This control can be valid if the filehandle passes a control handler. */ +#define INFO_FL_CTRL (1 << 1) + +#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .flags = _flags, \ + .name = #_ioctl, \ +} + +static struct v4l2_ioctl_info v4l2_ioctls[] = { + IOCTL_INFO(VIDIOC_QUERYCAP, 0), + IOCTL_INFO(VIDIOC_ENUM_FMT, 0), + IOCTL_INFO(VIDIOC_G_FMT, 0), + IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_QUERYBUF, 0), + IOCTL_INFO(VIDIOC_G_FBUF, 0), + IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_QBUF, 0), + IOCTL_INFO(VIDIOC_DQBUF, 0), + IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_PARM, 0), + IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_STD, 0), + IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_ENUMSTD, 0), + IOCTL_INFO(VIDIOC_ENUMINPUT, 0), + IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_G_TUNER, 0), + IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_AUDIO, 0), + IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_G_INPUT, 0), + IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_OUTPUT, 0), + IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0), + IOCTL_INFO(VIDIOC_G_AUDOUT, 0), + IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_MODULATOR, 0), + IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_FREQUENCY, 0), + IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_CROPCAP, 0), + IOCTL_INFO(VIDIOC_G_CROP, 0), + IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_SELECTION, 0), + IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), + IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_QUERYSTD, 0), + IOCTL_INFO(VIDIOC_TRY_FMT, 0), + IOCTL_INFO(VIDIOC_ENUMAUDIO, 0), + IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0), + IOCTL_INFO(VIDIOC_G_PRIORITY, 0), + IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0), + IOCTL_INFO(VIDIOC_LOG_STATUS, 0), + IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0), + IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0), + IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0), + IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0), + IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0), + IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0), +#ifdef CONFIG_VIDEO_ADV_DEBUG + IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), + IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), +#endif + IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), + IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), + IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_DV_PRESET, 0), + IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0), + IOCTL_INFO(VIDIOC_S_DV_TIMINGS, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0), + IOCTL_INFO(VIDIOC_DQEVENT, 0), + IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0), + IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0), + IOCTL_INFO(VIDIOC_CREATE_BUFS, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_PREPARE_BUF, 0), + IOCTL_INFO(VIDIOC_ENUM_DV_TIMINGS, 0), + IOCTL_INFO(VIDIOC_QUERY_DV_TIMINGS, 0), + IOCTL_INFO(VIDIOC_DV_TIMINGS_CAP, 0), +}; +#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) + +bool v4l2_is_known_ioctl(unsigned int cmd) +{ + if (_IOC_NR(cmd) >= V4L2_IOCTLS) + return false; + return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; +} + +/* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl */ +void v4l_printk_ioctl(unsigned int cmd) +{ + char *dir, *type; + + switch (_IOC_TYPE(cmd)) { + case 'd': + type = "v4l2_int"; + break; + case 'V': + if (_IOC_NR(cmd) >= V4L2_IOCTLS) { + type = "v4l2"; + break; + } + printk("%s", v4l2_ioctls[_IOC_NR(cmd)].name); + return; + default: + type = "unknown"; + } + + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "*ERR*"; break; + } + printk("%s ioctl '%c', dir=%s, #%d (0x%08x)", + type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); +} +EXPORT_SYMBOL(v4l_printk_ioctl); + static long __video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { -- GitLab From 27cd2aba172dffb7819b9ca49a6a8acdbb8cf7e5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 08:55:31 -0300 Subject: [PATCH 1955/5711] [media] v4l2-ioctl.c: introduce INFO_FL_CLEAR to replace switch The switch statement that determines how much data should be copied from userspace is replaced by a table lookup. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 103 ++++++++++++------------------- 1 file changed, 41 insertions(+), 62 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 46fd95327630..e2f77bc15954 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -394,7 +394,7 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) struct v4l2_ioctl_info { unsigned int ioctl; - u16 flags; + u32 flags; const char * const name; }; @@ -402,6 +402,11 @@ struct v4l2_ioctl_info { #define INFO_FL_PRIO (1 << 0) /* This control can be valid if the filehandle passes a control handler. */ #define INFO_FL_CTRL (1 << 1) +/* Zero struct from after the field to the end */ +#define INFO_FL_CLEAR(v4l2_struct, field) \ + ((offsetof(struct v4l2_struct, field) + \ + sizeof(((struct v4l2_struct *)0)->field)) << 16) +#define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) #define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \ .ioctl = _ioctl, \ @@ -411,11 +416,11 @@ struct v4l2_ioctl_info { static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_QUERYCAP, 0), - IOCTL_INFO(VIDIOC_ENUM_FMT, 0), - IOCTL_INFO(VIDIOC_G_FMT, 0), + IOCTL_INFO(VIDIOC_ENUM_FMT, INFO_FL_CLEAR(v4l2_fmtdesc, type)), + IOCTL_INFO(VIDIOC_G_FMT, INFO_FL_CLEAR(v4l2_format, type)), IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYBUF, 0), + IOCTL_INFO(VIDIOC_QUERYBUF, INFO_FL_CLEAR(v4l2_buffer, length)), IOCTL_INFO(VIDIOC_G_FBUF, 0), IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO), @@ -423,33 +428,33 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_DQBUF, 0), IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_PARM, 0), + IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_STD, 0), IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUMSTD, 0), - IOCTL_INFO(VIDIOC_ENUMINPUT, 0), + IOCTL_INFO(VIDIOC_ENUMSTD, INFO_FL_CLEAR(v4l2_standard, index)), + IOCTL_INFO(VIDIOC_ENUMINPUT, INFO_FL_CLEAR(v4l2_input, index)), IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_G_TUNER, 0), + IOCTL_INFO(VIDIOC_G_TUNER, INFO_FL_CLEAR(v4l2_tuner, index)), IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_AUDIO, 0), IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL), + IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), + IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), IOCTL_INFO(VIDIOC_G_INPUT, 0), IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_OUTPUT, 0), + IOCTL_INFO(VIDIOC_G_OUTPUT, INFO_FL_CLEAR(v4l2_output, index)), IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0), IOCTL_INFO(VIDIOC_G_AUDOUT, 0), IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_MODULATOR, 0), + IOCTL_INFO(VIDIOC_G_MODULATOR, INFO_FL_CLEAR(v4l2_modulator, index)), IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_FREQUENCY, 0), + IOCTL_INFO(VIDIOC_G_FREQUENCY, INFO_FL_CLEAR(v4l2_frequency, tuner)), IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_CROPCAP, 0), - IOCTL_INFO(VIDIOC_G_CROP, 0), + IOCTL_INFO(VIDIOC_CROPCAP, INFO_FL_CLEAR(v4l2_cropcap, type)), + IOCTL_INFO(VIDIOC_G_CROP, INFO_FL_CLEAR(v4l2_crop, type)), IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_SELECTION, 0), IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO), @@ -457,20 +462,20 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYSTD, 0), IOCTL_INFO(VIDIOC_TRY_FMT, 0), - IOCTL_INFO(VIDIOC_ENUMAUDIO, 0), - IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0), + IOCTL_INFO(VIDIOC_ENUMAUDIO, INFO_FL_CLEAR(v4l2_audio, index)), + IOCTL_INFO(VIDIOC_ENUMAUDOUT, INFO_FL_CLEAR(v4l2_audioout, index)), IOCTL_INFO(VIDIOC_G_PRIORITY, 0), IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0), + IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), IOCTL_INFO(VIDIOC_LOG_STATUS, 0), IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL), IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0), - IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0), - IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0), + IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), + IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, INFO_FL_CLEAR(v4l2_frmivalenum, height)), IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0), - IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0), + IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), + IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0), #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -2106,45 +2111,6 @@ static long __video_do_ioctl(struct file *file, return ret; } -/* In some cases, only a few fields are used as input, i.e. when the app sets - * "index" and then the driver fills in the rest of the structure for the thing - * with that index. We only need to copy up the first non-input field. */ -static unsigned long cmd_input_size(unsigned int cmd) -{ - /* Size of structure up to and including 'field' */ -#define CMDINSIZE(cmd, type, field) \ - case VIDIOC_##cmd: \ - return offsetof(struct v4l2_##type, field) + \ - sizeof(((struct v4l2_##type *)0)->field); - - switch (cmd) { - CMDINSIZE(ENUM_FMT, fmtdesc, type); - CMDINSIZE(G_FMT, format, type); - CMDINSIZE(QUERYBUF, buffer, length); - CMDINSIZE(G_PARM, streamparm, type); - CMDINSIZE(ENUMSTD, standard, index); - CMDINSIZE(ENUMINPUT, input, index); - CMDINSIZE(G_CTRL, control, id); - CMDINSIZE(G_TUNER, tuner, index); - CMDINSIZE(QUERYCTRL, queryctrl, id); - CMDINSIZE(QUERYMENU, querymenu, index); - CMDINSIZE(ENUMOUTPUT, output, index); - CMDINSIZE(G_MODULATOR, modulator, index); - CMDINSIZE(G_FREQUENCY, frequency, tuner); - CMDINSIZE(CROPCAP, cropcap, type); - CMDINSIZE(G_CROP, crop, type); - CMDINSIZE(ENUMAUDIO, audio, index); - CMDINSIZE(ENUMAUDOUT, audioout, index); - CMDINSIZE(ENCODER_CMD, encoder_cmd, flags); - CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags); - CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type); - CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format); - CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height); - default: - return _IOC_SIZE(cmd); - } -} - static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, void * __user *user_ptr, void ***kernel_ptr) { @@ -2219,7 +2185,20 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, err = -EFAULT; if (_IOC_DIR(cmd) & _IOC_WRITE) { - unsigned long n = cmd_input_size(cmd); + unsigned int n = _IOC_SIZE(cmd); + + /* + * In some cases, only a few fields are used as input, + * i.e. when the app sets "index" and then the driver + * fills in the rest of the structure for the thing + * with that index. We only need to copy up the first + * non-input field. + */ + if (v4l2_is_known_ioctl(cmd)) { + u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; + if (flags & INFO_FL_CLEAR_MASK) + n = (flags & INFO_FL_CLEAR_MASK) >> 16; + } if (copy_from_user(parg, (void __user *)arg, n)) goto out; -- GitLab From 86748f35da3e2eacd613c546d6fa67c2b6428be3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:04:16 -0300 Subject: [PATCH 1956/5711] [media] v4l2-ioctl.c: v4l2-ioctl: add debug and callback/offset functionality Add the necessary plumbing to make it possible to replace the switch by a table driven implementation. The ioctls ops can either be called directly, or by calling a small function that does some additional work if needed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 91 +++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index e2f77bc15954..7a15f351395f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -396,12 +396,22 @@ struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; const char * const name; + union { + u32 offset; + int (*func)(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *p); + }; + void (*debug)(const void *arg, bool write_only); }; /* This control needs a priority check */ #define INFO_FL_PRIO (1 << 0) /* This control can be valid if the filehandle passes a control handler. */ #define INFO_FL_CTRL (1 << 1) +/* This is a standard ioctl, no need for special code */ +#define INFO_FL_STD (1 << 2) +/* This is ioctl has its own function */ +#define INFO_FL_FUNC (1 << 3) /* Zero struct from after the field to the end */ #define INFO_FL_CLEAR(v4l2_struct, field) \ ((offsetof(struct v4l2_struct, field) + \ @@ -414,6 +424,24 @@ struct v4l2_ioctl_info { .name = #_ioctl, \ } +#define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .flags = _flags | INFO_FL_STD, \ + .name = #_ioctl, \ + .offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ + .debug = _debug, \ + } + +#define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .flags = _flags | INFO_FL_FUNC, \ + .name = #_ioctl, \ + .func = _func, \ + .debug = _debug, \ + } + static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_QUERYCAP, 0), IOCTL_INFO(VIDIOC_ENUM_FMT, INFO_FL_CLEAR(v4l2_fmtdesc, type)), @@ -512,7 +540,7 @@ bool v4l2_is_known_ioctl(unsigned int cmd) external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(unsigned int cmd) { - char *dir, *type; + const char *dir, *type; switch (_IOC_TYPE(cmd)) { case 'd': @@ -523,10 +551,11 @@ void v4l_printk_ioctl(unsigned int cmd) type = "v4l2"; break; } - printk("%s", v4l2_ioctls[_IOC_NR(cmd)].name); + pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name); return; default: type = "unknown"; + break; } switch (_IOC_DIR(cmd)) { @@ -536,7 +565,7 @@ void v4l_printk_ioctl(unsigned int cmd) case _IOC_READ | _IOC_WRITE: dir = "rw"; break; default: dir = "*ERR*"; break; } - printk("%s ioctl '%c', dir=%s, #%d (0x%08x)", + pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)", type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); } EXPORT_SYMBOL(v4l_printk_ioctl); @@ -546,6 +575,9 @@ static long __video_do_ioctl(struct file *file, { struct video_device *vfd = video_devdata(file); const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; + bool write_only = false; + struct v4l2_ioctl_info default_info; + const struct v4l2_ioctl_info *info; void *fh = file->private_data; struct v4l2_fh *vfh = NULL; int use_fh_prio = 0; @@ -563,23 +595,40 @@ static long __video_do_ioctl(struct file *file, } if (v4l2_is_known_ioctl(cmd)) { - struct v4l2_ioctl_info *info = &v4l2_ioctls[_IOC_NR(cmd)]; + info = &v4l2_ioctls[_IOC_NR(cmd)]; if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) && !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) - return -ENOTTY; + goto done; if (use_fh_prio && (info->flags & INFO_FL_PRIO)) { ret = v4l2_prio_check(vfd->prio, vfh->prio); if (ret) - return ret; + goto done; } + } else { + default_info.ioctl = cmd; + default_info.flags = 0; + default_info.debug = NULL; + info = &default_info; } - if ((vfd->debug & V4L2_DEBUG_IOCTL) && - !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { + write_only = _IOC_DIR(cmd) == _IOC_WRITE; + if (info->debug && write_only && vfd->debug > V4L2_DEBUG_IOCTL) { v4l_print_ioctl(vfd->name, cmd); - printk(KERN_CONT "\n"); + pr_cont(": "); + info->debug(arg, write_only); + } + if (info->flags & INFO_FL_STD) { + typedef int (*vidioc_op)(struct file *file, void *fh, void *p); + const void *p = vfd->ioctl_ops; + const vidioc_op *vidioc = p + info->offset; + + ret = (*vidioc)(file, fh, arg); + goto done; + } else if (info->flags & INFO_FL_FUNC) { + ret = info->func(ops, file, fh, arg); + goto done; } switch (cmd) { @@ -2101,10 +2150,26 @@ static long __video_do_ioctl(struct file *file, break; } /* switch */ - if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { - if (ret < 0) { - v4l_print_ioctl(vfd->name, cmd); - printk(KERN_CONT " error %ld\n", ret); +done: + if (vfd->debug) { + if (write_only && vfd->debug > V4L2_DEBUG_IOCTL) { + if (ret < 0) + printk(KERN_DEBUG "%s: error %ld\n", + video_device_node_name(vfd), ret); + return ret; + } + v4l_print_ioctl(vfd->name, cmd); + if (ret < 0) + pr_cont(": error %ld\n", ret); + else if (vfd->debug == V4L2_DEBUG_IOCTL) + pr_cont("\n"); + else if (!info->debug) + return ret; + else if (_IOC_DIR(cmd) == _IOC_NONE) + info->debug(arg, write_only); + else { + pr_cont(": "); + info->debug(arg, write_only); } } -- GitLab From 2ba60ac018f886de1203bc5c81969a4219706623 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:00:51 -0300 Subject: [PATCH 1957/5711] [media] v4l2-ioctl.c: remove an unnecessary #ifdef Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7a15f351395f..be89dade6e2c 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -506,10 +506,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0), -#ifdef CONFIG_VIDEO_ADV_DEBUG IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), -#endif IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), -- GitLab From 59076122cbd325a9ee6ab062ebbbc4604768f97f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:09:54 -0300 Subject: [PATCH 1958/5711] [media] v4l2-ioctl.c: use the new table for querycap and i/o ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 328 +++++++++++++------------------ 1 file changed, 133 insertions(+), 195 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index be89dade6e2c..7556678846f9 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -183,6 +183,63 @@ static const char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ +static void v4l_print_querycap(const void *arg, bool write_only) +{ + const struct v4l2_capability *p = arg; + + pr_cont("driver=%s, card=%s, bus=%s, version=0x%08x, " + "capabilities=0x%08x, device_caps=0x%08x\n", + p->driver, p->card, p->bus_info, + p->version, p->capabilities, p->device_caps); +} + +static void v4l_print_enuminput(const void *arg, bool write_only) +{ + const struct v4l2_input *p = arg; + + pr_cont("index=%u, name=%s, type=%u, audioset=0x%x, tuner=%u, " + "std=0x%08Lx, status=0x%x, capabilities=0x%x\n", + p->index, p->name, p->type, p->audioset, p->tuner, + (unsigned long long)p->std, p->status, p->capabilities); +} + +static void v4l_print_enumoutput(const void *arg, bool write_only) +{ + const struct v4l2_output *p = arg; + + pr_cont("index=%u, name=%s, type=%u, audioset=0x%x, " + "modulator=%u, std=0x%08Lx, capabilities=0x%x\n", + p->index, p->name, p->type, p->audioset, p->modulator, + (unsigned long long)p->std, p->capabilities); +} + +static void v4l_print_audio(const void *arg, bool write_only) +{ + const struct v4l2_audio *p = arg; + + if (write_only) + pr_cont("index=%u, mode=0x%x\n", p->index, p->mode); + else + pr_cont("index=%u, name=%s, capability=0x%x, mode=0x%x\n", + p->index, p->name, p->capability, p->mode); +} + +static void v4l_print_audioout(const void *arg, bool write_only) +{ + const struct v4l2_audioout *p = arg; + + if (write_only) + pr_cont("index=%u\n", p->index); + else + pr_cont("index=%u, name=%s, capability=0x%x, mode=0x%x\n", + p->index, p->name, p->capability, p->mode); +} + +static void v4l_print_u32(const void *arg, bool write_only) +{ + pr_cont("value=%u\n", *(const u32 *)arg); +} + static void dbgbuf(unsigned int cmd, struct video_device *vfd, struct v4l2_buffer *p) { @@ -392,6 +449,69 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) return -EINVAL; } +static int v4l_querycap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_capability *cap = (struct v4l2_capability *)arg; + + cap->version = LINUX_VERSION_CODE; + return ops->vidioc_querycap(file, fh, cap); +} + +static int v4l_s_input(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); +} + +static int v4l_s_output(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); +} + +static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_input *p = arg; + + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific input, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_IN_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_IN_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; + + return ops->vidioc_enum_input(file, fh, p); +} + +static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_output *p = arg; + + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific output, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_OUT_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_OUT_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; + + return ops->vidioc_enum_output(file, fh, p); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -443,7 +563,7 @@ struct v4l2_ioctl_info { } static struct v4l2_ioctl_info v4l2_ioctls[] = { - IOCTL_INFO(VIDIOC_QUERYCAP, 0), + IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), IOCTL_INFO(VIDIOC_ENUM_FMT, INFO_FL_CLEAR(v4l2_fmtdesc, type)), IOCTL_INFO(VIDIOC_G_FMT, INFO_FL_CLEAR(v4l2_format, type)), IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO), @@ -461,22 +581,22 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_G_STD, 0), IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_ENUMSTD, INFO_FL_CLEAR(v4l2_standard, index)), - IOCTL_INFO(VIDIOC_ENUMINPUT, INFO_FL_CLEAR(v4l2_input, index)), + IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO(VIDIOC_G_TUNER, INFO_FL_CLEAR(v4l2_tuner, index)), IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_AUDIO, 0), - IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), + IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), - IOCTL_INFO(VIDIOC_G_INPUT, 0), - IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_OUTPUT, INFO_FL_CLEAR(v4l2_output, index)), - IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0), - IOCTL_INFO(VIDIOC_G_AUDOUT, 0), - IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), + IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), + IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_MODULATOR, INFO_FL_CLEAR(v4l2_modulator, index)), IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_FREQUENCY, INFO_FL_CLEAR(v4l2_frequency, tuner)), @@ -490,8 +610,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYSTD, 0), IOCTL_INFO(VIDIOC_TRY_FMT, 0), - IOCTL_INFO(VIDIOC_ENUMAUDIO, INFO_FL_CLEAR(v4l2_audio, index)), - IOCTL_INFO(VIDIOC_ENUMAUDOUT, INFO_FL_CLEAR(v4l2_audioout, index)), + IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), + IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), IOCTL_INFO(VIDIOC_G_PRIORITY, 0), IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), @@ -631,25 +751,6 @@ static long __video_do_ioctl(struct file *file, switch (cmd) { - /* --- capabilities ------------------------------------------ */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = (struct v4l2_capability *)arg; - - cap->version = LINUX_VERSION_CODE; - ret = ops->vidioc_querycap(file, fh, cap); - if (!ret) - dbgarg(cmd, "driver=%s, card=%s, bus=%s, " - "version=0x%08x, " - "capabilities=0x%08x, " - "device_caps=0x%08x\n", - cap->driver, cap->card, cap->bus_info, - cap->version, - cap->capabilities, - cap->device_caps); - break; - } - /* --- priority ------------------------------------------ */ case VIDIOC_G_PRIORITY: { @@ -1164,98 +1265,6 @@ static long __video_do_ioctl(struct file *file, (unsigned long long)*p); break; } - /* ------ input switching ---------- */ - /* FIXME: Inputs can be handled inside videodev2 */ - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *p = arg; - - /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & - * CAP_STD here based on ioctl handler provided by the - * driver. If the driver doesn't support these - * for a specific input, it must override these flags. - */ - if (ops->vidioc_s_std) - p->capabilities |= V4L2_IN_CAP_STD; - if (ops->vidioc_s_dv_preset) - p->capabilities |= V4L2_IN_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; - - ret = ops->vidioc_enum_input(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "audioset=%d, " - "tuner=%d, std=%08Lx, status=%d\n", - p->index, p->name, p->type, p->audioset, - p->tuner, - (unsigned long long)p->std, - p->status); - break; - } - case VIDIOC_G_INPUT: - { - unsigned int *i = arg; - - ret = ops->vidioc_g_input(file, fh, i); - if (!ret) - dbgarg(cmd, "value=%d\n", *i); - break; - } - case VIDIOC_S_INPUT: - { - unsigned int *i = arg; - - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_s_input(file, fh, *i); - break; - } - - /* ------ output switching ---------- */ - case VIDIOC_ENUMOUTPUT: - { - struct v4l2_output *p = arg; - - /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & - * CAP_STD here based on ioctl handler provided by the - * driver. If the driver doesn't support these - * for a specific output, it must override these flags. - */ - if (ops->vidioc_s_std) - p->capabilities |= V4L2_OUT_CAP_STD; - if (ops->vidioc_s_dv_preset) - p->capabilities |= V4L2_OUT_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; - - ret = ops->vidioc_enum_output(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "audioset=0x%x, " - "modulator=%d, std=0x%08Lx\n", - p->index, p->name, p->type, p->audioset, - p->modulator, (unsigned long long)p->std); - break; - } - case VIDIOC_G_OUTPUT: - { - unsigned int *i = arg; - - ret = ops->vidioc_g_output(file, fh, i); - if (!ret) - dbgarg(cmd, "value=%d\n", *i); - break; - } - case VIDIOC_S_OUTPUT: - { - unsigned int *i = arg; - - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_s_output(file, fh, *i); - break; - } /* --- controls ---------------------------------------------- */ case VIDIOC_QUERYCTRL: @@ -1426,77 +1435,6 @@ static long __video_do_ioctl(struct file *file, p->id, p->index); break; } - /* --- audio ---------------------------------------------- */ - case VIDIOC_ENUMAUDIO: - { - struct v4l2_audio *p = arg; - - ret = ops->vidioc_enumaudio(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, p->name, - p->capability, p->mode); - else - dbgarg(cmd, "index=%d\n", p->index); - break; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *p = arg; - - ret = ops->vidioc_g_audio(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, - p->name, p->capability, p->mode); - else - dbgarg(cmd, "index=%d\n", p->index); - break; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *p = arg; - - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, p->name, - p->capability, p->mode); - ret = ops->vidioc_s_audio(file, fh, p); - break; - } - case VIDIOC_ENUMAUDOUT: - { - struct v4l2_audioout *p = arg; - - dbgarg(cmd, "Enum for index=%d\n", p->index); - ret = ops->vidioc_enumaudout(file, fh, p); - if (!ret) - dbgarg2("index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); - break; - } - case VIDIOC_G_AUDOUT: - { - struct v4l2_audioout *p = arg; - - ret = ops->vidioc_g_audout(file, fh, p); - if (!ret) - dbgarg2("index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); - break; - } - case VIDIOC_S_AUDOUT: - { - struct v4l2_audioout *p = arg; - - dbgarg(cmd, "index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); - - ret = ops->vidioc_s_audout(file, fh, p); - break; - } case VIDIOC_G_MODULATOR: { struct v4l2_modulator *p = arg; -- GitLab From d0547cba60775d9deaddbc1e0646a4b71833015d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 09:27:10 -0300 Subject: [PATCH 1959/5711] [media] v4l2-ioctl.c: use the new table for priority ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 60 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7556678846f9..4029d12f984d 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -470,6 +470,33 @@ static int v4l_s_output(const struct v4l2_ioctl_ops *ops, return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); } +static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd; + u32 *p = arg; + + if (ops->vidioc_g_priority) + return ops->vidioc_g_priority(file, fh, arg); + vfd = video_devdata(file); + *p = v4l2_prio_max(&vfd->v4l2_dev->prio); + return 0; +} + +static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd; + struct v4l2_fh *vfh; + u32 *p = arg; + + if (ops->vidioc_s_priority) + return ops->vidioc_s_priority(file, fh, *p); + vfd = video_devdata(file); + vfh = file->private_data; + return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p); +} + static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -612,8 +639,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_TRY_FMT, 0), IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), - IOCTL_INFO(VIDIOC_G_PRIORITY, 0), - IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), IOCTL_INFO(VIDIOC_LOG_STATUS, 0), IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL), @@ -750,35 +777,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - - /* --- priority ------------------------------------------ */ - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - - if (ops->vidioc_g_priority) { - ret = ops->vidioc_g_priority(file, fh, p); - } else if (use_fh_prio) { - *p = v4l2_prio_max(&vfd->v4l2_dev->prio); - ret = 0; - } - if (!ret) - dbgarg(cmd, "priority is %d\n", *p); - break; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *p = arg; - - dbgarg(cmd, "setting priority to %d\n", *p); - if (ops->vidioc_s_priority) - ret = ops->vidioc_s_priority(file, fh, *p); - else - ret = v4l2_prio_change(&vfd->v4l2_dev->prio, - &vfh->prio, *p); - break; - } - /* --- capture ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: { -- GitLab From be6c64e419da80233c71f981436d7be474defba5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:12:57 -0300 Subject: [PATCH 1960/5711] [media] v4l2-ioctl.c: use the new table for format/framebuffer ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 692 +++++++++++++++---------------- 1 file changed, 346 insertions(+), 346 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 4029d12f984d..25c0a8acc791 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -235,6 +235,130 @@ static void v4l_print_audioout(const void *arg, bool write_only) p->index, p->name, p->capability, p->mode); } +static void v4l_print_fmtdesc(const void *arg, bool write_only) +{ + const struct v4l2_fmtdesc *p = arg; + + pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%s'\n", + p->index, prt_names(p->type, v4l2_type_names), + p->flags, (p->pixelformat & 0xff), + (p->pixelformat >> 8) & 0xff, + (p->pixelformat >> 16) & 0xff, + (p->pixelformat >> 24) & 0xff, + p->description); +} + +static void v4l_print_format(const void *arg, bool write_only) +{ + const struct v4l2_format *p = arg; + const struct v4l2_pix_format *pix; + const struct v4l2_pix_format_mplane *mp; + const struct v4l2_vbi_format *vbi; + const struct v4l2_sliced_vbi_format *sliced; + const struct v4l2_window *win; + const struct v4l2_clip *clip; + unsigned i; + + pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + pix = &p->fmt.pix; + pr_cont(", width=%u, height=%u, " + "pixelformat=%c%c%c%c, field=%s, " + "bytesperline=%u sizeimage=%u, colorspace=%d\n", + pix->width, pix->height, + (pix->pixelformat & 0xff), + (pix->pixelformat >> 8) & 0xff, + (pix->pixelformat >> 16) & 0xff, + (pix->pixelformat >> 24) & 0xff, + prt_names(pix->field, v4l2_field_names), + pix->bytesperline, pix->sizeimage, + pix->colorspace); + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + mp = &p->fmt.pix_mp; + pr_cont(", width=%u, height=%u, " + "format=%c%c%c%c, field=%s, " + "colorspace=%d, num_planes=%u\n", + mp->width, mp->height, + (mp->pixelformat & 0xff), + (mp->pixelformat >> 8) & 0xff, + (mp->pixelformat >> 16) & 0xff, + (mp->pixelformat >> 24) & 0xff, + prt_names(mp->field, v4l2_field_names), + mp->colorspace, mp->num_planes); + for (i = 0; i < mp->num_planes; i++) + printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i, + mp->plane_fmt[i].bytesperline, + mp->plane_fmt[i].sizeimage); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + win = &p->fmt.win; + pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, " + "chromakey=0x%08x, bitmap=%p, " + "global_alpha=0x%02x\n", + win->w.width, win->w.height, + win->w.left, win->w.top, + prt_names(win->field, v4l2_field_names), + win->chromakey, win->bitmap, win->global_alpha); + clip = win->clips; + for (i = 0; i < win->clipcount; i++) { + printk(KERN_DEBUG "clip %u: wxh=%dx%d, x,y=%d,%d\n", + i, clip->c.width, clip->c.height, + clip->c.left, clip->c.top); + clip = clip->next; + } + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + vbi = &p->fmt.vbi; + pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, " + "sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n", + vbi->sampling_rate, vbi->offset, + vbi->samples_per_line, + (vbi->sample_format & 0xff), + (vbi->sample_format >> 8) & 0xff, + (vbi->sample_format >> 16) & 0xff, + (vbi->sample_format >> 24) & 0xff, + vbi->start[0], vbi->start[1], + vbi->count[0], vbi->count[1]); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + sliced = &p->fmt.sliced; + pr_cont(", service_set=0x%08x, io_size=%d\n", + sliced->service_set, sliced->io_size); + for (i = 0; i < 24; i++) + printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, + sliced->service_lines[0][i], + sliced->service_lines[1][i]); + break; + case V4L2_BUF_TYPE_PRIVATE: + pr_cont("\n"); + break; + } +} + +static void v4l_print_framebuffer(const void *arg, bool write_only) +{ + const struct v4l2_framebuffer *p = arg; + + pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, " + "height=%u, pixelformat=%c%c%c%c, " + "bytesperline=%u sizeimage=%u, colorspace=%d\n", + p->capability, p->flags, p->base, + p->fmt.width, p->fmt.height, + (p->fmt.pixelformat & 0xff), + (p->fmt.pixelformat >> 8) & 0xff, + (p->fmt.pixelformat >> 16) & 0xff, + (p->fmt.pixelformat >> 24) & 0xff, + p->fmt.bytesperline, p->fmt.sizeimage, + p->fmt.colorspace); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -312,41 +436,6 @@ static void dbgtimings(struct video_device *vfd, } } -static inline void v4l_print_pix_fmt(struct video_device *vfd, - struct v4l2_pix_format *fmt) -{ - dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, " - "bytesperline=%d sizeimage=%d, colorspace=%d\n", - fmt->width, fmt->height, - (fmt->pixelformat & 0xff), - (fmt->pixelformat >> 8) & 0xff, - (fmt->pixelformat >> 16) & 0xff, - (fmt->pixelformat >> 24) & 0xff, - prt_names(fmt->field, v4l2_field_names), - fmt->bytesperline, fmt->sizeimage, fmt->colorspace); -}; - -static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd, - struct v4l2_pix_format_mplane *fmt) -{ - int i; - - dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, " - "colorspace=%d, num_planes=%d\n", - fmt->width, fmt->height, - (fmt->pixelformat & 0xff), - (fmt->pixelformat >> 8) & 0xff, - (fmt->pixelformat >> 16) & 0xff, - (fmt->pixelformat >> 24) & 0xff, - prt_names(fmt->field, v4l2_field_names), - fmt->colorspace, fmt->num_planes); - - for (i = 0; i < fmt->num_planes; ++i) - dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i, - fmt->plane_fmt[i].bytesperline, - fmt->plane_fmt[i].sizeimage); -} - static inline void v4l_print_ext_ctrls(unsigned int cmd, struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals) { @@ -539,6 +628,222 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, return ops->vidioc_enum_output(file, fh, p); } +static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_fmtdesc *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) + break; + return ops->vidioc_enum_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) + break; + return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) + break; + return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_enum_fmt_vid_out)) + break; + return ops->vidioc_enum_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) + break; + return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_enum_fmt_type_private)) + break; + return ops->vidioc_enum_fmt_type_private(file, fh, arg); + } + return -EINVAL; +} + +static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_format *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_vid_cap)) + break; + return ops->vidioc_g_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_g_fmt_vid_cap_mplane)) + break; + return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_g_fmt_vid_overlay)) + break; + return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_vid_out)) + break; + return ops->vidioc_g_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_g_fmt_vid_out_mplane)) + break; + return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_g_fmt_vid_out_overlay)) + break; + return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_vbi_cap)) + break; + return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_vbi_out)) + break; + return ops->vidioc_g_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_cap)) + break; + return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_out)) + break; + return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_g_fmt_type_private)) + break; + return ops->vidioc_g_fmt_type_private(file, fh, arg); + } + return -EINVAL; +} + +static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_format *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_vid_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_s_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_vid_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_s_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_s_fmt_type_private)) + break; + return ops->vidioc_s_fmt_type_private(file, fh, arg); + } + return -EINVAL; +} + +static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_format *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_vid_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_try_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_vid_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_try_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_try_fmt_type_private)) + break; + return ops->vidioc_try_fmt_type_private(file, fh, arg); + } + return -EINVAL; +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -591,13 +896,13 @@ struct v4l2_ioctl_info { static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), - IOCTL_INFO(VIDIOC_ENUM_FMT, INFO_FL_CLEAR(v4l2_fmtdesc, type)), - IOCTL_INFO(VIDIOC_G_FMT, INFO_FL_CLEAR(v4l2_format, type)), - IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), + IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)), + IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYBUF, INFO_FL_CLEAR(v4l2_buffer, length)), - IOCTL_INFO(VIDIOC_G_FBUF, 0), - IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), + IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QBUF, 0), IOCTL_INFO(VIDIOC_DQBUF, 0), @@ -636,7 +941,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYSTD, 0), - IOCTL_INFO(VIDIOC_TRY_FMT, 0), + IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), @@ -777,288 +1082,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - /* --- capture ioctls ---------------------------------------- */ - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (likely(ops->vidioc_enum_fmt_vid_cap)) - ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (likely(ops->vidioc_enum_fmt_vid_cap_mplane)) - ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (likely(ops->vidioc_enum_fmt_vid_overlay)) - ret = ops->vidioc_enum_fmt_vid_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (likely(ops->vidioc_enum_fmt_vid_out)) - ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (likely(ops->vidioc_enum_fmt_vid_out_mplane)) - ret = ops->vidioc_enum_fmt_vid_out_mplane(file, - fh, f); - break; - case V4L2_BUF_TYPE_PRIVATE: - if (likely(ops->vidioc_enum_fmt_type_private)) - ret = ops->vidioc_enum_fmt_type_private(file, - fh, f); - break; - default: - break; - } - if (likely(!ret)) - dbgarg(cmd, "index=%d, type=%d, flags=%d, " - "pixelformat=%c%c%c%c, description='%s'\n", - f->index, f->type, f->flags, - (f->pixelformat & 0xff), - (f->pixelformat >> 8) & 0xff, - (f->pixelformat >> 16) & 0xff, - (f->pixelformat >> 24) & 0xff, - f->description); - break; - } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); - - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_g_fmt_vid_cap) - ret = ops->vidioc_g_fmt_vid_cap(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (ops->vidioc_g_fmt_vid_cap_mplane) - ret = ops->vidioc_g_fmt_vid_cap_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (likely(ops->vidioc_g_fmt_vid_overlay)) - ret = ops->vidioc_g_fmt_vid_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_g_fmt_vid_out) - ret = ops->vidioc_g_fmt_vid_out(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (ops->vidioc_g_fmt_vid_out_mplane) - ret = ops->vidioc_g_fmt_vid_out_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (likely(ops->vidioc_g_fmt_vid_out_overlay)) - ret = ops->vidioc_g_fmt_vid_out_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (likely(ops->vidioc_g_fmt_vbi_cap)) - ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - if (likely(ops->vidioc_g_fmt_vbi_out)) - ret = ops->vidioc_g_fmt_vbi_out(file, fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (likely(ops->vidioc_g_fmt_sliced_vbi_cap)) - ret = ops->vidioc_g_fmt_sliced_vbi_cap(file, - fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (likely(ops->vidioc_g_fmt_sliced_vbi_out)) - ret = ops->vidioc_g_fmt_sliced_vbi_out(file, - fh, f); - break; - case V4L2_BUF_TYPE_PRIVATE: - if (likely(ops->vidioc_g_fmt_type_private)) - ret = ops->vidioc_g_fmt_type_private(file, - fh, f); - break; - } - break; - } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - ret = -EINVAL; - - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.pix); - v4l_print_pix_fmt(vfd, &f->fmt.pix); - if (ops->vidioc_s_fmt_vid_cap) - ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - if (ops->vidioc_s_fmt_vid_cap_mplane) - ret = ops->vidioc_s_fmt_vid_cap_mplane(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (ops->vidioc_s_fmt_vid_overlay) - ret = ops->vidioc_s_fmt_vid_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.pix); - v4l_print_pix_fmt(vfd, &f->fmt.pix); - if (ops->vidioc_s_fmt_vid_out) - ret = ops->vidioc_s_fmt_vid_out(file, fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - if (ops->vidioc_s_fmt_vid_out_mplane) - ret = ops->vidioc_s_fmt_vid_out_mplane(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (ops->vidioc_s_fmt_vid_out_overlay) - ret = ops->vidioc_s_fmt_vid_out_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_s_fmt_vbi_cap)) - ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_s_fmt_vbi_out)) - ret = ops->vidioc_s_fmt_vbi_out(file, fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_s_fmt_sliced_vbi_cap)) - ret = ops->vidioc_s_fmt_sliced_vbi_cap(file, - fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_s_fmt_sliced_vbi_out)) - ret = ops->vidioc_s_fmt_sliced_vbi_out(file, - fh, f); - - break; - case V4L2_BUF_TYPE_PRIVATE: - /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ - if (likely(ops->vidioc_s_fmt_type_private)) - ret = ops->vidioc_s_fmt_type_private(file, - fh, f); - break; - } - break; - } - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, - v4l2_type_names)); - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.pix); - if (ops->vidioc_try_fmt_vid_cap) - ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - if (ops->vidioc_try_fmt_vid_cap_mplane) - ret = ops->vidioc_try_fmt_vid_cap_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (likely(ops->vidioc_try_fmt_vid_overlay)) - ret = ops->vidioc_try_fmt_vid_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.pix); - if (ops->vidioc_try_fmt_vid_out) - ret = ops->vidioc_try_fmt_vid_out(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - if (ops->vidioc_try_fmt_vid_out_mplane) - ret = ops->vidioc_try_fmt_vid_out_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (likely(ops->vidioc_try_fmt_vid_out_overlay)) - ret = ops->vidioc_try_fmt_vid_out_overlay(file, - fh, f); - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_try_fmt_vbi_cap)) - ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_try_fmt_vbi_out)) - ret = ops->vidioc_try_fmt_vbi_out(file, fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_try_fmt_sliced_vbi_cap)) - ret = ops->vidioc_try_fmt_sliced_vbi_cap(file, - fh, f); - break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_try_fmt_sliced_vbi_out)) - ret = ops->vidioc_try_fmt_sliced_vbi_out(file, - fh, f); - break; - case V4L2_BUF_TYPE_PRIVATE: - /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ - if (likely(ops->vidioc_try_fmt_type_private)) - ret = ops->vidioc_try_fmt_type_private(file, - fh, f); - break; - } - break; - } /* FIXME: Those buf reqs could be handled here, with some changes on videobuf to allow its header to be included at videodev2.h or being merged at videodev2. @@ -1128,29 +1151,6 @@ static long __video_do_ioctl(struct file *file, ret = ops->vidioc_overlay(file, fh, *i); break; } - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *p = arg; - - ret = ops->vidioc_g_fbuf(file, fh, arg); - if (!ret) { - dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n", - p->capability, p->flags, - (unsigned long)p->base); - v4l_print_pix_fmt(vfd, &p->fmt); - } - break; - } - case VIDIOC_S_FBUF: - { - struct v4l2_framebuffer *p = arg; - - dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n", - p->capability, p->flags, (unsigned long)p->base); - v4l_print_pix_fmt(vfd, &p->fmt); - ret = ops->vidioc_s_fbuf(file, fh, arg); - break; - } case VIDIOC_STREAMON: { enum v4l2_buf_type i = *(int *)arg; -- GitLab From e325b24478a8c0af906110174eb7c74fcb455b34 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 12:50:15 -0300 Subject: [PATCH 1961/5711] [media] v4l2-ioctl.c: use the new table for overlay/streamon/off ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 47 ++++++++++++++------------------ 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 25c0a8acc791..78ff09f559be 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -359,6 +359,11 @@ static void v4l_print_framebuffer(const void *arg, bool write_only) p->fmt.colorspace); } +static void v4l_print_buftype(const void *arg, bool write_only) +{ + pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names)); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -844,6 +849,18 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, return -EINVAL; } +static int v4l_streamon(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_streamon(file, fh, *(unsigned int *)arg); +} + +static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -903,11 +920,11 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_QUERYBUF, INFO_FL_CLEAR(v4l2_buffer, length)), IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QBUF, 0), IOCTL_INFO(VIDIOC_DQBUF, 0), - IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_STD, 0), @@ -1143,30 +1160,6 @@ static long __video_do_ioctl(struct file *file, dbgbuf(cmd, vfd, p); break; } - case VIDIOC_OVERLAY: - { - int *i = arg; - - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_overlay(file, fh, *i); - break; - } - case VIDIOC_STREAMON: - { - enum v4l2_buf_type i = *(int *)arg; - - dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); - ret = ops->vidioc_streamon(file, fh, i); - break; - } - case VIDIOC_STREAMOFF: - { - enum v4l2_buf_type i = *(int *)arg; - - dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); - ret = ops->vidioc_streamoff(file, fh, i); - break; - } /* ---------- tv norms ---------- */ case VIDIOC_ENUMSTD: { -- GitLab From 4b1e2e4ddfa2847559e8e63bb4ac4b2310465561 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:17:48 -0300 Subject: [PATCH 1962/5711] [media] v4l2-ioctl.c: use the new table for std/tuner/modulator ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 430 ++++++++++++++++--------------- 1 file changed, 220 insertions(+), 210 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 78ff09f559be..4d2d0d6590fb 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -364,6 +364,68 @@ static void v4l_print_buftype(const void *arg, bool write_only) pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names)); } +static void v4l_print_modulator(const void *arg, bool write_only) +{ + const struct v4l2_modulator *p = arg; + + if (write_only) + pr_cont("index=%u, txsubchans=0x%x", p->index, p->txsubchans); + else + pr_cont("index=%u, name=%s, capability=0x%x, " + "rangelow=%u, rangehigh=%u, txsubchans=0x%x\n", + p->index, p->name, p->capability, + p->rangelow, p->rangehigh, p->txsubchans); +} + +static void v4l_print_tuner(const void *arg, bool write_only) +{ + const struct v4l2_tuner *p = arg; + + if (write_only) + pr_cont("index=%u, audmode=%u\n", p->index, p->audmode); + else + pr_cont("index=%u, name=%s, type=%u, capability=0x%x, " + "rangelow=%u, rangehigh=%u, signal=%u, afc=%d, " + "rxsubchans=0x%x, audmode=%u\n", + p->index, p->name, p->type, + p->capability, p->rangelow, + p->rangehigh, p->signal, p->afc, + p->rxsubchans, p->audmode); +} + +static void v4l_print_frequency(const void *arg, bool write_only) +{ + const struct v4l2_frequency *p = arg; + + pr_cont("tuner=%u, type=%u, frequency=%u\n", + p->tuner, p->type, p->frequency); +} + +static void v4l_print_standard(const void *arg, bool write_only) +{ + const struct v4l2_standard *p = arg; + + pr_cont("index=%u, id=0x%Lx, name=%s, fps=%u/%u, " + "framelines=%u\n", p->index, + (unsigned long long)p->id, p->name, + p->frameperiod.numerator, + p->frameperiod.denominator, + p->framelines); +} + +static void v4l_print_std(const void *arg, bool write_only) +{ + pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg); +} + +static void v4l_print_hw_freq_seek(const void *arg, bool write_only) +{ + const struct v4l2_hw_freq_seek *p = arg; + + pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", + p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -861,6 +923,153 @@ static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); } +static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_tuner *p = arg; + + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_g_tuner(file, fh, p); +} + +static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_tuner *p = arg; + + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_s_tuner(file, fh, p); +} + +static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_frequency *p = arg; + + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_g_frequency(file, fh, p); +} + +static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_frequency *p = arg; + enum v4l2_tuner_type type; + + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + if (p->type != type) + return -EINVAL; + return ops->vidioc_s_frequency(file, fh, p); +} + +static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_standard *p = arg; + v4l2_std_id id = vfd->tvnorms, curr_id = 0; + unsigned int index = p->index, i, j = 0; + const char *descr = ""; + + /* Return norm array in a canonical way */ + for (i = 0; i <= index && id; i++) { + /* last std value in the standards array is 0, so this + while always ends there since (id & 0) == 0. */ + while ((id & standards[j].std) != standards[j].std) + j++; + curr_id = standards[j].std; + descr = standards[j].descr; + j++; + if (curr_id == 0) + break; + if (curr_id != V4L2_STD_PAL && + curr_id != V4L2_STD_SECAM && + curr_id != V4L2_STD_NTSC) + id &= ~curr_id; + } + if (i <= index) + return -EINVAL; + + v4l2_video_std_construct(p, curr_id, descr); + return 0; +} + +static int v4l_g_std(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + v4l2_std_id *id = arg; + + /* Calls the specific handler */ + if (ops->vidioc_g_std) + return ops->vidioc_g_std(file, fh, arg); + if (vfd->current_norm) { + *id = vfd->current_norm; + return 0; + } + return -ENOTTY; +} + +static int v4l_s_std(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + v4l2_std_id *id = arg, norm; + int ret; + + norm = (*id) & vfd->tvnorms; + if (vfd->tvnorms && !norm) /* Check if std is supported */ + return -EINVAL; + + /* Calls the specific handler */ + ret = ops->vidioc_s_std(file, fh, &norm); + + /* Updates standard information */ + if (ret >= 0) + vfd->current_norm = norm; + return ret; +} + +static int v4l_querystd(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + v4l2_std_id *p = arg; + + /* + * If nothing detected, it should return all supported + * standard. + * Drivers just need to mask the std argument, in order + * to remove the standards that don't apply from the mask. + * This means that tuners, audio and video decoders can join + * their efforts to improve the standards detection. + */ + *p = vfd->tvnorms; + return ops->vidioc_querystd(file, fh, arg); +} + +static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_hw_freq_seek *p = arg; + enum v4l2_tuner_type type; + + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + if (p->type != type) + return -EINVAL; + return ops->vidioc_s_hw_freq_seek(file, fh, p); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -927,14 +1136,14 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_STD, 0), - IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUMSTD, INFO_FL_CLEAR(v4l2_standard, index)), + IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), + IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_G_TUNER, INFO_FL_CLEAR(v4l2_tuner, index)), - IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)), + IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), @@ -946,10 +1155,10 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_MODULATOR, INFO_FL_CLEAR(v4l2_modulator, index)), - IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_FREQUENCY, INFO_FL_CLEAR(v4l2_frequency, tuner)), - IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_MODULATOR, vidioc_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), + IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), + IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_CROPCAP, INFO_FL_CLEAR(v4l2_cropcap, type)), IOCTL_INFO(VIDIOC_G_CROP, INFO_FL_CLEAR(v4l2_crop, type)), IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO), @@ -957,7 +1166,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYSTD, 0), + IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), @@ -978,7 +1187,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), - IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_DV_PRESET, 0), @@ -1160,102 +1369,6 @@ static long __video_do_ioctl(struct file *file, dbgbuf(cmd, vfd, p); break; } - /* ---------- tv norms ---------- */ - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *p = arg; - v4l2_std_id id = vfd->tvnorms, curr_id = 0; - unsigned int index = p->index, i, j = 0; - const char *descr = ""; - - if (id == 0) - break; - ret = -EINVAL; - - /* Return norm array in a canonical way */ - for (i = 0; i <= index && id; i++) { - /* last std value in the standards array is 0, so this - while always ends there since (id & 0) == 0. */ - while ((id & standards[j].std) != standards[j].std) - j++; - curr_id = standards[j].std; - descr = standards[j].descr; - j++; - if (curr_id == 0) - break; - if (curr_id != V4L2_STD_PAL && - curr_id != V4L2_STD_SECAM && - curr_id != V4L2_STD_NTSC) - id &= ~curr_id; - } - if (i <= index) - break; - - v4l2_video_std_construct(p, curr_id, descr); - - dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, " - "framelines=%d\n", p->index, - (unsigned long long)p->id, p->name, - p->frameperiod.numerator, - p->frameperiod.denominator, - p->framelines); - - ret = 0; - break; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - - /* Calls the specific handler */ - if (ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, id); - else if (vfd->current_norm) { - ret = 0; - *id = vfd->current_norm; - } - - if (likely(!ret)) - dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id); - break; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg, norm; - - dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id); - - ret = -EINVAL; - norm = (*id) & vfd->tvnorms; - if (vfd->tvnorms && !norm) /* Check if std is supported */ - break; - - /* Calls the specific handler */ - ret = ops->vidioc_s_std(file, fh, &norm); - - /* Updates standard information */ - if (ret >= 0) - vfd->current_norm = norm; - break; - } - case VIDIOC_QUERYSTD: - { - v4l2_std_id *p = arg; - - /* - * If nothing detected, it should return all supported - * Drivers just need to mask the std argument, in order - * to remove the standards that don't apply from the mask. - * This means that tuners, audio and video decoders can join - * their efforts to improve the standards detection - */ - *p = vfd->tvnorms; - ret = ops->vidioc_querystd(file, fh, arg); - if (!ret) - dbgarg(cmd, "detected std=%08Lx\n", - (unsigned long long)*p); - break; - } /* --- controls ---------------------------------------------- */ case VIDIOC_QUERYCTRL: @@ -1426,31 +1539,6 @@ static long __video_do_ioctl(struct file *file, p->id, p->index); break; } - case VIDIOC_G_MODULATOR: - { - struct v4l2_modulator *p = arg; - - ret = ops->vidioc_g_modulator(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, " - "capability=%d, rangelow=%d," - " rangehigh=%d, txsubchans=%d\n", - p->index, p->name, p->capability, - p->rangelow, p->rangehigh, - p->txsubchans); - break; - } - case VIDIOC_S_MODULATOR: - { - struct v4l2_modulator *p = arg; - - dbgarg(cmd, "index=%d, name=%s, capability=%d, " - "rangelow=%d, rangehigh=%d, txsubchans=%d\n", - p->index, p->name, p->capability, p->rangelow, - p->rangehigh, p->txsubchans); - ret = ops->vidioc_s_modulator(file, fh, p); - break; - } case VIDIOC_G_CROP: { struct v4l2_crop *p = arg; @@ -1684,68 +1772,6 @@ static long __video_do_ioctl(struct file *file, ret = ops->vidioc_s_parm(file, fh, p); break; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *p = arg; - - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - ret = ops->vidioc_g_tuner(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "capability=0x%x, rangelow=%d, " - "rangehigh=%d, signal=%d, afc=%d, " - "rxsubchans=0x%x, audmode=%d\n", - p->index, p->name, p->type, - p->capability, p->rangelow, - p->rangehigh, p->signal, p->afc, - p->rxsubchans, p->audmode); - break; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *p = arg; - - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "capability=0x%x, rangelow=%d, " - "rangehigh=%d, signal=%d, afc=%d, " - "rxsubchans=0x%x, audmode=%d\n", - p->index, p->name, p->type, - p->capability, p->rangelow, - p->rangehigh, p->signal, p->afc, - p->rxsubchans, p->audmode); - ret = ops->vidioc_s_tuner(file, fh, p); - break; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *p = arg; - - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - ret = ops->vidioc_g_frequency(file, fh, p); - if (!ret) - dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", - p->tuner, p->type, p->frequency); - break; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *p = arg; - enum v4l2_tuner_type type; - - type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", - p->tuner, p->type, p->frequency); - if (p->type != type) - ret = -EINVAL; - else - ret = ops->vidioc_s_frequency(file, fh, p); - break; - } case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p = arg; @@ -1805,22 +1831,6 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } - case VIDIOC_S_HW_FREQ_SEEK: - { - struct v4l2_hw_freq_seek *p = arg; - enum v4l2_tuner_type type; - - type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, - "tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", - p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); - if (p->type != type) - ret = -EINVAL; - else - ret = ops->vidioc_s_hw_freq_seek(file, fh, p); - break; - } case VIDIOC_ENUM_FRAMESIZES: { struct v4l2_frmsizeenum *p = arg; -- GitLab From eb3728edf156c094385dc662d208ab95a305d20a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:23:59 -0300 Subject: [PATCH 1963/5711] [media] v4l2-ioctl.c: use the new table for queuing/parm ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 317 ++++++++++++++++--------------- 1 file changed, 166 insertions(+), 151 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 4d2d0d6590fb..1f75a6c127ee 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -426,48 +426,97 @@ static void v4l_print_hw_freq_seek(const void *arg, bool write_only) p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); } -static void v4l_print_u32(const void *arg, bool write_only) +static void v4l_print_requestbuffers(const void *arg, bool write_only) { - pr_cont("value=%u\n", *(const u32 *)arg); + const struct v4l2_requestbuffers *p = arg; + + pr_cont("count=%d, type=%s, memory=%s\n", + p->count, + prt_names(p->type, v4l2_type_names), + prt_names(p->memory, v4l2_memory_names)); } -static void dbgbuf(unsigned int cmd, struct video_device *vfd, - struct v4l2_buffer *p) +static void v4l_print_buffer(const void *arg, bool write_only) { - struct v4l2_timecode *tc = &p->timecode; - struct v4l2_plane *plane; + const struct v4l2_buffer *p = arg; + const struct v4l2_timecode *tc = &p->timecode; + const struct v4l2_plane *plane; int i; - dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " - "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n", + pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, " + "flags=0x%08x, field=%s, sequence=%d, memory=%s", p->timestamp.tv_sec / 3600, (int)(p->timestamp.tv_sec / 60) % 60, (int)(p->timestamp.tv_sec % 60), (long)p->timestamp.tv_usec, p->index, prt_names(p->type, v4l2_type_names), - p->flags, p->field, p->sequence, - prt_names(p->memory, v4l2_memory_names)); + p->flags, prt_names(p->field, v4l2_field_names), + p->sequence, prt_names(p->memory, v4l2_memory_names)); if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) { + pr_cont("\n"); for (i = 0; i < p->length; ++i) { plane = &p->m.planes[i]; - dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x " - "offset/userptr=0x%08lx, length=%d\n", + printk(KERN_DEBUG + "plane %d: bytesused=%d, data_offset=0x%08x " + "offset/userptr=0x%lx, length=%d\n", i, plane->bytesused, plane->data_offset, plane->m.userptr, plane->length); } } else { - dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n", + pr_cont("bytesused=%d, offset/userptr=0x%lx, length=%d\n", p->bytesused, p->m.userptr, p->length); } - dbgarg2("timecode=%02d:%02d:%02d type=%d, " - "flags=0x%08d, frames=%d, userbits=0x%08x\n", + printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, " + "flags=0x%08x, frames=%d, userbits=0x%08x\n", tc->hours, tc->minutes, tc->seconds, tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits); } +static void v4l_print_create_buffers(const void *arg, bool write_only) +{ + const struct v4l2_create_buffers *p = arg; + + pr_cont("index=%d, count=%d, memory=%s, ", + p->index, p->count, + prt_names(p->memory, v4l2_memory_names)); + v4l_print_format(&p->format, write_only); +} + +static void v4l_print_streamparm(const void *arg, bool write_only) +{ + const struct v4l2_streamparm *p = arg; + + pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); + + if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || + p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + const struct v4l2_captureparm *c = &p->parm.capture; + + pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, " + "extendedmode=%d, readbuffers=%d\n", + c->capability, c->capturemode, + c->timeperframe.numerator, c->timeperframe.denominator, + c->extendedmode, c->readbuffers); + } else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || + p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + const struct v4l2_outputparm *c = &p->parm.output; + + pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, " + "extendedmode=%d, writebuffers=%d\n", + c->capability, c->outputmode, + c->timeperframe.numerator, c->timeperframe.denominator, + c->extendedmode, c->writebuffers); + } +} + +static void v4l_print_u32(const void *arg, bool write_only) +{ + pr_cont("value=%u\n", *(const u32 *)arg); +} + static inline void dbgrect(struct video_device *vfd, char *s, struct v4l2_rect *r) { @@ -1070,6 +1119,100 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, return ops->vidioc_s_hw_freq_seek(file, fh, p); } +static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_requestbuffers *p = arg; + int ret = check_fmt(ops, p->type); + + if (ret) + return ret; + + if (p->type < V4L2_BUF_TYPE_PRIVATE) + CLEAR_AFTER_FIELD(p, memory); + + return ops->vidioc_reqbufs(file, fh, p); +} + +static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); + + return ret ? ret : ops->vidioc_querybuf(file, fh, p); +} + +static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); + + return ret ? ret : ops->vidioc_qbuf(file, fh, p); +} + +static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); + + return ret ? ret : ops->vidioc_dqbuf(file, fh, p); +} + +static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_create_buffers *create = arg; + int ret = check_fmt(ops, create->format.type); + + return ret ? ret : ops->vidioc_create_bufs(file, fh, create); +} + +static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_buffer *b = arg; + int ret = check_fmt(ops, b->type); + + return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); +} + +static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_streamparm *p = arg; + v4l2_std_id std; + int ret = check_fmt(ops, p->type); + + if (ret) + return ret; + if (ops->vidioc_g_parm) + return ops->vidioc_g_parm(file, fh, p); + std = vfd->current_norm; + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + return -EINVAL; + p->parm.capture.readbuffers = 2; + if (ops->vidioc_g_std) + ret = ops->vidioc_g_std(file, fh, &std); + if (ret == 0) + v4l2_video_std_frame_period(std, + &p->parm.capture.timeperframe); + return ret; +} + +static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_streamparm *p = arg; + int ret = check_fmt(ops, p->type); + + return ret ? ret : ops->vidioc_s_parm(file, fh, p); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1125,17 +1268,17 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)), IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYBUF, INFO_FL_CLEAR(v4l2_buffer, length)), + IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_CLEAR(v4l2_buffer, length)), IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QBUF, 0), - IOCTL_INFO(VIDIOC_DQBUF, 0), + IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, 0), + IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, 0), IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)), - IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), + IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), @@ -1197,8 +1340,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_DQEVENT, 0), IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0), IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0), - IOCTL_INFO(VIDIOC_CREATE_BUFS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_PREPARE_BUF, 0), + IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, 0), IOCTL_INFO(VIDIOC_ENUM_DV_TIMINGS, 0), IOCTL_INFO(VIDIOC_QUERY_DV_TIMINGS, 0), IOCTL_INFO(VIDIOC_DV_TIMINGS_CAP, 0), @@ -1308,68 +1451,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - /* FIXME: Those buf reqs could be handled here, - with some changes on videobuf to allow its header to be included at - videodev2.h or being merged at videodev2. - */ - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; - - if (p->type < V4L2_BUF_TYPE_PRIVATE) - CLEAR_AFTER_FIELD(p, memory); - - ret = ops->vidioc_reqbufs(file, fh, p); - dbgarg(cmd, "count=%d, type=%s, memory=%s\n", - p->count, - prt_names(p->type, v4l2_type_names), - prt_names(p->memory, v4l2_memory_names)); - break; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; - - ret = ops->vidioc_querybuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - case VIDIOC_QBUF: - { - struct v4l2_buffer *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; - - ret = ops->vidioc_qbuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - case VIDIOC_DQBUF: - { - struct v4l2_buffer *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; - - ret = ops->vidioc_dqbuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - /* --- controls ---------------------------------------------- */ case VIDIOC_QUERYCTRL: { @@ -1732,46 +1813,6 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); break; } - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *p = arg; - - if (ops->vidioc_g_parm) { - ret = check_fmt(ops, p->type); - if (ret) - break; - ret = ops->vidioc_g_parm(file, fh, p); - } else { - v4l2_std_id std = vfd->current_norm; - - ret = -EINVAL; - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - break; - - ret = 0; - p->parm.capture.readbuffers = 2; - if (ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, &std); - if (ret == 0) - v4l2_video_std_frame_period(std, - &p->parm.capture.timeperframe); - } - - dbgarg(cmd, "type=%d\n", p->type); - break; - } - case VIDIOC_S_PARM: - { - struct v4l2_streamparm *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; - - dbgarg(cmd, "type=%d\n", p->type); - ret = ops->vidioc_s_parm(file, fh, p); - break; - } case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p = arg; @@ -2052,32 +2093,6 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "type=0x%8.8x", sub->type); break; } - case VIDIOC_CREATE_BUFS: - { - struct v4l2_create_buffers *create = arg; - - ret = check_fmt(ops, create->format.type); - if (ret) - break; - - ret = ops->vidioc_create_bufs(file, fh, create); - - dbgarg(cmd, "count=%d @ %d\n", create->count, create->index); - break; - } - case VIDIOC_PREPARE_BUF: - { - struct v4l2_buffer *b = arg; - - ret = check_fmt(ops, b->type); - if (ret) - break; - - ret = ops->vidioc_prepare_buf(file, fh, b); - - dbgarg(cmd, "index=%d", b->index); - break; - } default: if (!ops->vidioc_default) break; -- GitLab From efbceecd4522a41b8442c6b4f68b4508d57d1ccf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 12:54:02 -0300 Subject: [PATCH 1964/5711] [media] v4l2-ioctl.c: use the new table for control ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 395 ++++++++++++++++--------------- 1 file changed, 198 insertions(+), 197 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 1f75a6c127ee..798ee42d4e1a 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -512,6 +512,49 @@ static void v4l_print_streamparm(const void *arg, bool write_only) } } +static void v4l_print_queryctrl(const void *arg, bool write_only) +{ + const struct v4l2_queryctrl *p = arg; + + pr_cont("id=0x%x, type=%d, name=%s, min/max=%d/%d, " + "step=%d, default=%d, flags=0x%08x\n", + p->id, p->type, p->name, + p->minimum, p->maximum, + p->step, p->default_value, p->flags); +} + +static void v4l_print_querymenu(const void *arg, bool write_only) +{ + const struct v4l2_querymenu *p = arg; + + pr_cont("id=0x%x, index=%d\n", p->id, p->index); +} + +static void v4l_print_control(const void *arg, bool write_only) +{ + const struct v4l2_control *p = arg; + + pr_cont("id=0x%x, value=%d\n", p->id, p->value); +} + +static void v4l_print_ext_controls(const void *arg, bool write_only) +{ + const struct v4l2_ext_controls *p = arg; + int i; + + pr_cont("class=0x%x, count=%d, error_idx=%d", + p->ctrl_class, p->count, p->error_idx); + for (i = 0; i < p->count; i++) { + if (p->controls[i].size) + pr_cont(", id/val=0x%x/0x%x", + p->controls[i].id, p->controls[i].value); + else + pr_cont(", id/size=0x%x/%u", + p->controls[i].id, p->controls[i].size); + } + pr_cont("\n"); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -552,27 +595,7 @@ static void dbgtimings(struct video_device *vfd, } } -static inline void v4l_print_ext_ctrls(unsigned int cmd, - struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals) -{ - __u32 i; - - if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) - return; - dbgarg(cmd, ""); - printk(KERN_CONT "class=0x%x", c->ctrl_class); - for (i = 0; i < c->count; i++) { - if (show_vals && !c->controls[i].size) - printk(KERN_CONT " id/val=0x%x/0x%x", - c->controls[i].id, c->controls[i].value); - else - printk(KERN_CONT " id=0x%x,size=%u", - c->controls[i].id, c->controls[i].size); - } - printk(KERN_CONT "\n"); -}; - -static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) +static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) { __u32 i; @@ -1213,6 +1236,153 @@ static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, return ret ? ret : ops->vidioc_s_parm(file, fh, p); } +static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_queryctrl *p = arg; + struct v4l2_fh *vfh = fh; + + if (vfh && vfh->ctrl_handler) + return v4l2_queryctrl(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_queryctrl(vfd->ctrl_handler, p); + if (ops->vidioc_queryctrl) + return ops->vidioc_queryctrl(file, fh, p); + return -ENOTTY; +} + +static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_querymenu *p = arg; + struct v4l2_fh *vfh = fh; + + if (vfh && vfh->ctrl_handler) + return v4l2_querymenu(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_querymenu(vfd->ctrl_handler, p); + if (ops->vidioc_querymenu) + return ops->vidioc_querymenu(file, fh, p); + return -ENOTTY; +} + +static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_control *p = arg; + struct v4l2_fh *vfh = fh; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + if (vfh && vfh->ctrl_handler) + return v4l2_g_ctrl(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_g_ctrl(vfd->ctrl_handler, p); + if (ops->vidioc_g_ctrl) + return ops->vidioc_g_ctrl(file, fh, p); + if (ops->vidioc_g_ext_ctrls == NULL) + return -ENOTTY; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls, 1)) { + int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); + + if (ret == 0) + p->value = ctrl.value; + return ret; + } + return -EINVAL; +} + +static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_control *p = arg; + struct v4l2_fh *vfh = fh; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + if (vfh && vfh->ctrl_handler) + return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); + if (ops->vidioc_s_ctrl) + return ops->vidioc_s_ctrl(file, fh, p); + if (ops->vidioc_s_ext_ctrls == NULL) + return -ENOTTY; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls, 1)) + return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); + return -EINVAL; +} + +static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); + if (ops->vidioc_g_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : + -EINVAL; +} + +static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); + if (ops->vidioc_s_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : + -EINVAL; +} + +static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); + if (ops->vidioc_try_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : + -EINVAL; +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1283,14 +1453,14 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), - IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)), + IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)), IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), - IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), + IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), + IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), @@ -1317,9 +1487,9 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), IOCTL_INFO(VIDIOC_LOG_STATUS, 0), - IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL), - IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0), + IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, 0), IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, INFO_FL_CLEAR(v4l2_frmivalenum, height)), IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0), @@ -1451,175 +1621,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - /* --- controls ---------------------------------------------- */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_queryctrl(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_queryctrl(vfd->ctrl_handler, p); - else if (ops->vidioc_queryctrl) - ret = ops->vidioc_queryctrl(file, fh, p); - else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, " - "step=%d, default=%d, flags=0x%08x\n", - p->id, p->type, p->name, - p->minimum, p->maximum, - p->step, p->default_value, p->flags); - else - dbgarg(cmd, "id=0x%x\n", p->id); - break; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_g_ctrl(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_g_ctrl(vfd->ctrl_handler, p); - else if (ops->vidioc_g_ctrl) - ret = ops->vidioc_g_ctrl(file, fh, p); - else if (ops->vidioc_g_ext_ctrls) { - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; - - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); - ctrls.count = 1; - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) { - ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); - if (ret == 0) - p->value = ctrl.value; - } - } else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); - else - dbgarg(cmd, "id=0x%x\n", p->id); - break; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *p = arg; - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; - - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls) - break; - - dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); - - if (vfh && vfh->ctrl_handler) { - ret = v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); - break; - } - if (vfd->ctrl_handler) { - ret = v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); - break; - } - if (ops->vidioc_s_ctrl) { - ret = ops->vidioc_s_ctrl(file, fh, p); - break; - } - if (!ops->vidioc_s_ext_ctrls) - break; - - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); - ctrls.count = 1; - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) - ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); - else - ret = -EINVAL; - break; - } - case VIDIOC_G_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; - - p->error_idx = p->count; - if (vfh && vfh->ctrl_handler) - ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p); - else if (ops->vidioc_g_ext_ctrls) - ret = check_ext_ctrls(p, 0) ? - ops->vidioc_g_ext_ctrls(file, fh, p) : - -EINVAL; - else - break; - v4l_print_ext_ctrls(cmd, vfd, p, !ret); - break; - } - case VIDIOC_S_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; - - p->error_idx = p->count; - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_s_ext_ctrls) - break; - v4l_print_ext_ctrls(cmd, vfd, p, 1); - if (vfh && vfh->ctrl_handler) - ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); - else if (check_ext_ctrls(p, 0)) - ret = ops->vidioc_s_ext_ctrls(file, fh, p); - else - ret = -EINVAL; - break; - } - case VIDIOC_TRY_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; - - p->error_idx = p->count; - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_try_ext_ctrls) - break; - v4l_print_ext_ctrls(cmd, vfd, p, 1); - if (vfh && vfh->ctrl_handler) - ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p); - else if (check_ext_ctrls(p, 0)) - ret = ops->vidioc_try_ext_ctrls(file, fh, p); - else - ret = -EINVAL; - break; - } - case VIDIOC_QUERYMENU: - { - struct v4l2_querymenu *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_querymenu(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_querymenu(vfd->ctrl_handler, p); - else if (ops->vidioc_querymenu) - ret = ops->vidioc_querymenu(file, fh, p); - else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, index=%d, name=%s\n", - p->id, p->index, p->name); - else - dbgarg(cmd, "id=0x%x, index=%d\n", - p->id, p->index); - break; - } case VIDIOC_G_CROP: { struct v4l2_crop *p = arg; -- GitLab From d84f2d9483efa6fc69afb82b89ed9615c159470f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 11:57:46 -0300 Subject: [PATCH 1965/5711] [media] v4l2-ioctl.c: use the new table for selection ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 262 +++++++++++++++---------------- 1 file changed, 127 insertions(+), 135 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 798ee42d4e1a..179b22c80b4d 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -555,17 +555,45 @@ static void v4l_print_ext_controls(const void *arg, bool write_only) pr_cont("\n"); } -static void v4l_print_u32(const void *arg, bool write_only) +static void v4l_print_cropcap(const void *arg, bool write_only) { - pr_cont("value=%u\n", *(const u32 *)arg); + const struct v4l2_cropcap *p = arg; + + pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, " + "defrect wxh=%dx%d, x,y=%d,%d\n, " + "pixelaspect %d/%d\n", + prt_names(p->type, v4l2_type_names), + p->bounds.width, p->bounds.height, + p->bounds.left, p->bounds.top, + p->defrect.width, p->defrect.height, + p->defrect.left, p->defrect.top, + p->pixelaspect.numerator, p->pixelaspect.denominator); } -static inline void dbgrect(struct video_device *vfd, char *s, - struct v4l2_rect *r) +static void v4l_print_crop(const void *arg, bool write_only) { - dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top, - r->width, r->height); -}; + const struct v4l2_crop *p = arg; + + pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n", + prt_names(p->type, v4l2_type_names), + p->c.width, p->c.height, + p->c.left, p->c.top); +} + +static void v4l_print_selection(const void *arg, bool write_only) +{ + const struct v4l2_selection *p = arg; + + pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n", + prt_names(p->type, v4l2_type_names), + p->target, p->flags, + p->r.width, p->r.height, p->r.left, p->r.top); +} + +static void v4l_print_u32(const void *arg, bool write_only) +{ + pr_cont("value=%u\n", *(const u32 *)arg); +} static void dbgtimings(struct video_device *vfd, const struct v4l2_dv_timings *p) @@ -1383,6 +1411,93 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, -EINVAL; } +static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_crop *p = arg; + struct v4l2_selection s = { + .type = p->type, + }; + int ret; + + if (ops->vidioc_g_crop) + return ops->vidioc_g_crop(file, fh, p); + /* simulate capture crop using selection api */ + + /* crop means compose for output devices */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; + else + s.target = V4L2_SEL_TGT_CROP_ACTIVE; + + ret = ops->vidioc_g_selection(file, fh, &s); + + /* copying results to old structure on success */ + if (!ret) + p->c = s.r; + return ret; +} + +static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_crop *p = arg; + struct v4l2_selection s = { + .type = p->type, + .r = p->c, + }; + + if (ops->vidioc_s_crop) + return ops->vidioc_s_crop(file, fh, p); + /* simulate capture crop using selection api */ + + /* crop means compose for output devices */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; + else + s.target = V4L2_SEL_TGT_CROP_ACTIVE; + + return ops->vidioc_s_selection(file, fh, &s); +} + +static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_cropcap *p = arg; + struct v4l2_selection s = { .type = p->type }; + int ret; + + if (ops->vidioc_cropcap) + return ops->vidioc_cropcap(file, fh, p); + + /* obtaining bounds */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + else + s.target = V4L2_SEL_TGT_CROP_BOUNDS; + + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->bounds = s.r; + + /* obtaining defrect */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; + else + s.target = V4L2_SEL_TGT_CROP_DEFAULT; + + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->defrect = s.r; + + /* setting trivial pixelaspect */ + p->pixelaspect.numerator = 1; + p->pixelaspect.denominator = 1; + return 0; +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1472,11 +1587,11 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_CROPCAP, INFO_FL_CLEAR(v4l2_cropcap, type)), - IOCTL_INFO(VIDIOC_G_CROP, INFO_FL_CLEAR(v4l2_crop, type)), - IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_SELECTION, 0), - IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), + IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)), + IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0), + IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), @@ -1621,129 +1736,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - case VIDIOC_G_CROP: - { - struct v4l2_crop *p = arg; - - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - - if (ops->vidioc_g_crop) { - ret = ops->vidioc_g_crop(file, fh, p); - } else { - /* simulate capture crop using selection api */ - struct v4l2_selection s = { - .type = p->type, - }; - - /* crop means compose for output devices */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; - else - s.target = V4L2_SEL_TGT_CROP_ACTIVE; - - ret = ops->vidioc_g_selection(file, fh, &s); - - /* copying results to old structure on success */ - if (!ret) - p->c = s.r; - } - - if (!ret) - dbgrect(vfd, "", &p->c); - break; - } - case VIDIOC_S_CROP: - { - struct v4l2_crop *p = arg; - - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - dbgrect(vfd, "", &p->c); - - if (ops->vidioc_s_crop) { - ret = ops->vidioc_s_crop(file, fh, p); - } else { - /* simulate capture crop using selection api */ - struct v4l2_selection s = { - .type = p->type, - .r = p->c, - }; - - /* crop means compose for output devices */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; - else - s.target = V4L2_SEL_TGT_CROP_ACTIVE; - - ret = ops->vidioc_s_selection(file, fh, &s); - } - break; - } - case VIDIOC_G_SELECTION: - { - struct v4l2_selection *p = arg; - - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - - ret = ops->vidioc_g_selection(file, fh, p); - if (!ret) - dbgrect(vfd, "", &p->r); - break; - } - case VIDIOC_S_SELECTION: - { - struct v4l2_selection *p = arg; - - - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - dbgrect(vfd, "", &p->r); - - ret = ops->vidioc_s_selection(file, fh, p); - break; - } - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *p = arg; - - /*FIXME: Should also show v4l2_fract pixelaspect */ - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - if (ops->vidioc_cropcap) { - ret = ops->vidioc_cropcap(file, fh, p); - } else { - struct v4l2_selection s = { .type = p->type }; - - /* obtaining bounds */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; - else - s.target = V4L2_SEL_TGT_CROP_BOUNDS; - - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - break; - p->bounds = s.r; - - /* obtaining defrect */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; - else - s.target = V4L2_SEL_TGT_CROP_DEFAULT; - - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - break; - p->defrect = s.r; - - /* setting trivial pixelaspect */ - p->pixelaspect.numerator = 1; - p->pixelaspect.denominator = 1; - } - - if (!ret) { - dbgrect(vfd, "bounds ", &p->bounds); - dbgrect(vfd, "defrect ", &p->defrect); - } - break; - } case VIDIOC_G_JPEGCOMP: { struct v4l2_jpegcompression *p = arg; -- GitLab From d806f2df48098efca104d00a7db237dc39eea858 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:02:49 -0300 Subject: [PATCH 1966/5711] [media] v4l2-ioctl.c: use the new table for compression ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 123 ++++++++++++------------------- 1 file changed, 46 insertions(+), 77 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 179b22c80b4d..935fcbc2d50b 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -590,6 +590,45 @@ static void v4l_print_selection(const void *arg, bool write_only) p->r.width, p->r.height, p->r.left, p->r.top); } +static void v4l_print_jpegcompression(const void *arg, bool write_only) +{ + const struct v4l2_jpegcompression *p = arg; + + pr_cont("quality=%d, APPn=%d, APP_len=%d, " + "COM_len=%d, jpeg_markers=0x%x\n", + p->quality, p->APPn, p->APP_len, + p->COM_len, p->jpeg_markers); +} + +static void v4l_print_enc_idx(const void *arg, bool write_only) +{ + const struct v4l2_enc_idx *p = arg; + + pr_cont("entries=%d, entries_cap=%d\n", + p->entries, p->entries_cap); +} + +static void v4l_print_encoder_cmd(const void *arg, bool write_only) +{ + const struct v4l2_encoder_cmd *p = arg; + + pr_cont("cmd=%d, flags=0x%x\n", + p->cmd, p->flags); +} + +static void v4l_print_decoder_cmd(const void *arg, bool write_only) +{ + const struct v4l2_decoder_cmd *p = arg; + + pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags); + + if (p->cmd == V4L2_DEC_CMD_START) + pr_info("speed=%d, format=%u\n", + p->start.speed, p->start.format); + else if (p->cmd == V4L2_DEC_CMD_STOP) + pr_info("pts=%llu\n", p->stop.pts); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -1592,8 +1631,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0), IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0), - IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0), + IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), @@ -1607,11 +1646,11 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, 0), IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, INFO_FL_CLEAR(v4l2_frmivalenum, height)), - IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0), - IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), - IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), - IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0), + IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0), + IOCTL_INFO_STD(VIDIOC_ENCODER_CMD, vidioc_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), + IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), + IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), @@ -1736,76 +1775,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - case VIDIOC_G_JPEGCOMP: - { - struct v4l2_jpegcompression *p = arg; - - ret = ops->vidioc_g_jpegcomp(file, fh, p); - if (!ret) - dbgarg(cmd, "quality=%d, APPn=%d, " - "APP_len=%d, COM_len=%d, " - "jpeg_markers=%d\n", - p->quality, p->APPn, p->APP_len, - p->COM_len, p->jpeg_markers); - break; - } - case VIDIOC_S_JPEGCOMP: - { - struct v4l2_jpegcompression *p = arg; - - dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, " - "COM_len=%d, jpeg_markers=%d\n", - p->quality, p->APPn, p->APP_len, - p->COM_len, p->jpeg_markers); - ret = ops->vidioc_s_jpegcomp(file, fh, p); - break; - } - case VIDIOC_G_ENC_INDEX: - { - struct v4l2_enc_idx *p = arg; - - ret = ops->vidioc_g_enc_index(file, fh, p); - if (!ret) - dbgarg(cmd, "entries=%d, entries_cap=%d\n", - p->entries, p->entries_cap); - break; - } - case VIDIOC_ENCODER_CMD: - { - struct v4l2_encoder_cmd *p = arg; - - ret = ops->vidioc_encoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_TRY_ENCODER_CMD: - { - struct v4l2_encoder_cmd *p = arg; - - ret = ops->vidioc_try_encoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_DECODER_CMD: - { - struct v4l2_decoder_cmd *p = arg; - - ret = ops->vidioc_decoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_TRY_DECODER_CMD: - { - struct v4l2_decoder_cmd *p = arg; - - ret = ops->vidioc_try_decoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p = arg; -- GitLab From f16f77b0193c04e0c549c8e22546a8cd24e44d79 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:06:25 -0300 Subject: [PATCH 1967/5711] [media] v4l2-ioctl.c: use the new table for debug ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 139 ++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 50 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 935fcbc2d50b..ee11e08cb04c 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -629,11 +629,42 @@ static void v4l_print_decoder_cmd(const void *arg, bool write_only) pr_info("pts=%llu\n", p->stop.pts); } +static void v4l_print_dbg_chip_ident(const void *arg, bool write_only) +{ + const struct v4l2_dbg_chip_ident *p = arg; + + pr_cont("type=%u, ", p->match.type); + if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) + pr_cont("name=%s, ", p->match.name); + else + pr_cont("addr=%u, ", p->match.addr); + pr_cont("chip_ident=%u, revision=0x%x\n", + p->ident, p->revision); +} + +static void v4l_print_dbg_register(const void *arg, bool write_only) +{ + const struct v4l2_dbg_register *p = arg; + + pr_cont("type=%u, ", p->match.type); + if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) + pr_cont("name=%s, ", p->match.name); + else + pr_cont("addr=%u, ", p->match.addr); + pr_cont("reg=0x%llx, val=0x%llx\n", + p->reg, p->val); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); } +static void v4l_print_newline(const void *arg, bool write_only) +{ + pr_cont("\n"); +} + static void dbgtimings(struct video_device *vfd, const struct v4l2_dv_timings *p) { @@ -1537,6 +1568,60 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, return 0; } +static int v4l_log_status(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + int ret; + + if (vfd->v4l2_dev) + pr_info("%s: ================= START STATUS =================\n", + vfd->v4l2_dev->name); + ret = ops->vidioc_log_status(file, fh); + if (vfd->v4l2_dev) + pr_info("%s: ================== END STATUS ==================\n", + vfd->v4l2_dev->name); + return ret; +} + +static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ +#ifdef CONFIG_VIDEO_ADV_DEBUG + struct v4l2_dbg_register *p = arg; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return ops->vidioc_g_register(file, fh, p); +#else + return -ENOTTY; +#endif +} + +static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ +#ifdef CONFIG_VIDEO_ADV_DEBUG + struct v4l2_dbg_register *p = arg; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return ops->vidioc_s_register(file, fh, p); +#else + return -ENOTTY; +#endif +} + +static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_dbg_chip_ident *p = arg; + + p->ident = V4L2_IDENT_NONE; + p->revision = 0; + return ops->vidioc_g_chip_ident(file, fh, p); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1640,7 +1725,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), - IOCTL_INFO(VIDIOC_LOG_STATUS, 0), + IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, 0), @@ -1651,9 +1736,9 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), - IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0), - IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0), - IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0), IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO), @@ -1788,52 +1873,6 @@ static long __video_do_ioctl(struct file *file, dbgarg2("service_set=%d\n", p->service_set); break; } - case VIDIOC_LOG_STATUS: - { - if (vfd->v4l2_dev) - pr_info("%s: ================= START STATUS =================\n", - vfd->v4l2_dev->name); - ret = ops->vidioc_log_status(file, fh); - if (vfd->v4l2_dev) - pr_info("%s: ================== END STATUS ==================\n", - vfd->v4l2_dev->name); - break; - } - case VIDIOC_DBG_G_REGISTER: - { -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register *p = arg; - - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else - ret = ops->vidioc_g_register(file, fh, p); -#endif - break; - } - case VIDIOC_DBG_S_REGISTER: - { -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register *p = arg; - - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else - ret = ops->vidioc_s_register(file, fh, p); -#endif - break; - } - case VIDIOC_DBG_G_CHIP_IDENT: - { - struct v4l2_dbg_chip_ident *p = arg; - - p->ident = V4L2_IDENT_NONE; - p->revision = 0; - ret = ops->vidioc_g_chip_ident(file, fh, p); - if (!ret) - dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); - break; - } case VIDIOC_ENUM_FRAMESIZES: { struct v4l2_frmsizeenum *p = arg; -- GitLab From efc626b013900c5fc23b9900943356d0ece96d48 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:09:07 -0300 Subject: [PATCH 1968/5711] [media] v4l2-ioctl.c: use the new table for preset/timings ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 207 ++++++++++--------------------- 1 file changed, 67 insertions(+), 140 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index ee11e08cb04c..fdceac803b6f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -655,29 +655,35 @@ static void v4l_print_dbg_register(const void *arg, bool write_only) p->reg, p->val); } -static void v4l_print_u32(const void *arg, bool write_only) +static void v4l_print_dv_enum_presets(const void *arg, bool write_only) { - pr_cont("value=%u\n", *(const u32 *)arg); + const struct v4l2_dv_enum_preset *p = arg; + + pr_cont("index=%u, preset=%u, name=%s, width=%u, height=%u\n", + p->index, p->preset, p->name, p->width, p->height); } -static void v4l_print_newline(const void *arg, bool write_only) +static void v4l_print_dv_preset(const void *arg, bool write_only) { - pr_cont("\n"); + const struct v4l2_dv_preset *p = arg; + + pr_cont("preset=%u\n", p->preset); } -static void dbgtimings(struct video_device *vfd, - const struct v4l2_dv_timings *p) +static void v4l_print_dv_timings(const void *arg, bool write_only) { + const struct v4l2_dv_timings *p = arg; + switch (p->type) { case V4L2_DV_BT_656_1120: - dbgarg2("bt-656/1120:interlaced=%d," - " pixelclock=%lld," - " width=%d, height=%d, polarities=%x," - " hfrontporch=%d, hsync=%d," - " hbackporch=%d, vfrontporch=%d," - " vsync=%d, vbackporch=%d," - " il_vfrontporch=%d, il_vsync=%d," - " il_vbackporch=%d, standards=%x, flags=%x\n", + pr_cont("type=bt-656/1120, interlaced=%u, " + "pixelclock=%llu, " + "width=%u, height=%u, polarities=0x%x, " + "hfrontporch=%u, hsync=%u, " + "hbackporch=%u, vfrontporch=%u, " + "vsync=%u, vbackporch=%u, " + "il_vfrontporch=%u, il_vsync=%u, " + "il_vbackporch=%u, standards=0x%x, flags=0x%x\n", p->bt.interlaced, p->bt.pixelclock, p->bt.width, p->bt.height, p->bt.polarities, p->bt.hfrontporch, @@ -688,11 +694,48 @@ static void dbgtimings(struct video_device *vfd, p->bt.standards, p->bt.flags); break; default: - dbgarg2("Unknown type %d!\n", p->type); + pr_cont("type=%d\n", p->type); break; } } +static void v4l_print_enum_dv_timings(const void *arg, bool write_only) +{ + const struct v4l2_enum_dv_timings *p = arg; + + pr_cont("index=%u, ", p->index); + v4l_print_dv_timings(&p->timings, write_only); +} + +static void v4l_print_dv_timings_cap(const void *arg, bool write_only) +{ + const struct v4l2_dv_timings_cap *p = arg; + + switch (p->type) { + case V4L2_DV_BT_656_1120: + pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, " + "pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n", + p->bt.min_width, p->bt.max_width, + p->bt.min_height, p->bt.max_height, + p->bt.min_pixelclock, p->bt.max_pixelclock, + p->bt.standards, p->bt.capabilities); + break; + default: + pr_cont("type=%u\n", p->type); + break; + } +} + +static void v4l_print_u32(const void *arg, bool write_only) +{ + pr_cont("value=%u\n", *(const u32 *)arg); +} + +static void v4l_print_newline(const void *arg, bool write_only) +{ + pr_cont("\n"); +} + static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) { __u32 i; @@ -1740,20 +1783,20 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0), IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0), - IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_DV_PRESET, 0), - IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0), - IOCTL_INFO(VIDIOC_S_DV_TIMINGS, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0), + IOCTL_INFO_STD(VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets, v4l_print_dv_enum_presets, 0), + IOCTL_INFO_STD(VIDIOC_S_DV_PRESET, vidioc_s_dv_preset, v4l_print_dv_preset, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_DV_PRESET, vidioc_g_dv_preset, v4l_print_dv_preset, 0), + IOCTL_INFO_STD(VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset, v4l_print_dv_preset, 0), + IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), IOCTL_INFO(VIDIOC_DQEVENT, 0), IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0), IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0), IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, 0), - IOCTL_INFO(VIDIOC_ENUM_DV_TIMINGS, 0), - IOCTL_INFO(VIDIOC_QUERY_DV_TIMINGS, 0), - IOCTL_INFO(VIDIOC_DV_TIMINGS_CAP, 0), + IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), + IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), + IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, 0), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -1938,122 +1981,6 @@ static long __video_do_ioctl(struct file *file, } break; } - case VIDIOC_ENUM_DV_PRESETS: - { - struct v4l2_dv_enum_preset *p = arg; - - ret = ops->vidioc_enum_dv_presets(file, fh, p); - if (!ret) - dbgarg(cmd, - "index=%d, preset=%d, name=%s, width=%d," - " height=%d ", - p->index, p->preset, p->name, p->width, - p->height); - break; - } - case VIDIOC_S_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; - - dbgarg(cmd, "preset=%d\n", p->preset); - ret = ops->vidioc_s_dv_preset(file, fh, p); - break; - } - case VIDIOC_G_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; - - ret = ops->vidioc_g_dv_preset(file, fh, p); - if (!ret) - dbgarg(cmd, "preset=%d\n", p->preset); - break; - } - case VIDIOC_QUERY_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; - - ret = ops->vidioc_query_dv_preset(file, fh, p); - if (!ret) - dbgarg(cmd, "preset=%d\n", p->preset); - break; - } - case VIDIOC_S_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; - - dbgtimings(vfd, p); - switch (p->type) { - case V4L2_DV_BT_656_1120: - ret = ops->vidioc_s_dv_timings(file, fh, p); - break; - default: - ret = -EINVAL; - break; - } - break; - } - case VIDIOC_G_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; - - ret = ops->vidioc_g_dv_timings(file, fh, p); - if (!ret) - dbgtimings(vfd, p); - break; - } - case VIDIOC_ENUM_DV_TIMINGS: - { - struct v4l2_enum_dv_timings *p = arg; - - if (!ops->vidioc_enum_dv_timings) - break; - - ret = ops->vidioc_enum_dv_timings(file, fh, p); - if (!ret) { - dbgarg(cmd, "index=%d: ", p->index); - dbgtimings(vfd, &p->timings); - } - break; - } - case VIDIOC_QUERY_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; - - if (!ops->vidioc_query_dv_timings) - break; - - ret = ops->vidioc_query_dv_timings(file, fh, p); - if (!ret) - dbgtimings(vfd, p); - break; - } - case VIDIOC_DV_TIMINGS_CAP: - { - struct v4l2_dv_timings_cap *p = arg; - - if (!ops->vidioc_dv_timings_cap) - break; - - ret = ops->vidioc_dv_timings_cap(file, fh, p); - if (ret) - break; - switch (p->type) { - case V4L2_DV_BT_656_1120: - dbgarg(cmd, - "type=%d, width=%u-%u, height=%u-%u, " - "pixelclock=%llu-%llu, standards=%x, capabilities=%x ", - p->type, - p->bt.min_width, p->bt.max_width, - p->bt.min_height, p->bt.max_height, - p->bt.min_pixelclock, p->bt.max_pixelclock, - p->bt.standards, p->bt.capabilities); - break; - default: - dbgarg(cmd, "unknown type "); - break; - } - break; - } case VIDIOC_DQEVENT: { struct v4l2_event *ev = arg; -- GitLab From 458aa4a6922bf4cc22a34adfe3bd56331bbf663e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 12:55:52 -0300 Subject: [PATCH 1969/5711] [media] v4l2-ioctl.c: use the new table for the remaining ioctls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 278 +++++++++++++++++-------------- 1 file changed, 154 insertions(+), 124 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index fdceac803b6f..74fe6a2797e8 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -726,6 +726,125 @@ static void v4l_print_dv_timings_cap(const void *arg, bool write_only) } } +static void v4l_print_frmsizeenum(const void *arg, bool write_only) +{ + const struct v4l2_frmsizeenum *p = arg; + + pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u", + p->index, + (p->pixel_format & 0xff), + (p->pixel_format >> 8) & 0xff, + (p->pixel_format >> 16) & 0xff, + (p->pixel_format >> 24) & 0xff, + p->type); + switch (p->type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + pr_cont(" wxh=%ux%u\n", + p->discrete.width, p->discrete.height); + break; + case V4L2_FRMSIZE_TYPE_STEPWISE: + pr_cont(" min=%ux%u, max=%ux%u, step=%ux%u\n", + p->stepwise.min_width, p->stepwise.min_height, + p->stepwise.step_width, p->stepwise.step_height, + p->stepwise.max_width, p->stepwise.max_height); + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + /* fall through */ + default: + pr_cont("\n"); + break; + } +} + +static void v4l_print_frmivalenum(const void *arg, bool write_only) +{ + const struct v4l2_frmivalenum *p = arg; + + pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u", + p->index, + (p->pixel_format & 0xff), + (p->pixel_format >> 8) & 0xff, + (p->pixel_format >> 16) & 0xff, + (p->pixel_format >> 24) & 0xff, + p->width, p->height, p->type); + switch (p->type) { + case V4L2_FRMIVAL_TYPE_DISCRETE: + pr_cont(" fps=%d/%d\n", + p->discrete.numerator, + p->discrete.denominator); + break; + case V4L2_FRMIVAL_TYPE_STEPWISE: + pr_cont(" min=%d/%d, max=%d/%d, step=%d/%d\n", + p->stepwise.min.numerator, + p->stepwise.min.denominator, + p->stepwise.max.numerator, + p->stepwise.max.denominator, + p->stepwise.step.numerator, + p->stepwise.step.denominator); + break; + case V4L2_FRMIVAL_TYPE_CONTINUOUS: + /* fall through */ + default: + pr_cont("\n"); + break; + } +} + +static void v4l_print_event(const void *arg, bool write_only) +{ + const struct v4l2_event *p = arg; + const struct v4l2_event_ctrl *c; + + pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, " + "timestamp=%lu.%9.9lu\n", + p->type, p->pending, p->sequence, p->id, + p->timestamp.tv_sec, p->timestamp.tv_nsec); + switch (p->type) { + case V4L2_EVENT_VSYNC: + printk(KERN_DEBUG "field=%s\n", + prt_names(p->u.vsync.field, v4l2_field_names)); + break; + case V4L2_EVENT_CTRL: + c = &p->u.ctrl; + printk(KERN_DEBUG "changes=0x%x, type=%u, ", + c->changes, c->type); + if (c->type == V4L2_CTRL_TYPE_INTEGER64) + pr_cont("value64=%lld, ", c->value64); + else + pr_cont("value=%d, ", c->value); + pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d," + " default_value=%d\n", + c->flags, c->minimum, c->maximum, + c->step, c->default_value); + break; + case V4L2_EVENT_FRAME_SYNC: + pr_cont("frame_sequence=%u\n", + p->u.frame_sync.frame_sequence); + break; + } +} + +static void v4l_print_event_subscription(const void *arg, bool write_only) +{ + const struct v4l2_event_subscription *p = arg; + + pr_cont("type=0x%x, id=0x%x, flags=0x%x\n", + p->type, p->id, p->flags); +} + +static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only) +{ + const struct v4l2_sliced_vbi_cap *p = arg; + int i; + + pr_cont("type=%s, service_set=0x%08x\n", + prt_names(p->type, v4l2_type_names), p->service_set); + for (i = 0; i < 24; i++) + printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, + p->service_lines[0][i], + p->service_lines[1][i]); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -1665,6 +1784,35 @@ static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops, return ops->vidioc_g_chip_ident(file, fh, p); } +static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); +} + +static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_subscribe_event(fh, arg); +} + +static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_unsubscribe_event(fh, arg); +} + +static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_sliced_vbi_cap *p = arg; + + /* Clear up to type, everything after type is zeroed already */ + memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); + + return ops->vidioc_g_sliced_vbi_cap(file, fh, p); +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1767,13 +1915,13 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), - IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), + IOCTL_INFO_FNC(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, 0), - IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), - IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, INFO_FL_CLEAR(v4l2_frmivalenum, height)), + IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), + IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)), IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0), IOCTL_INFO_STD(VIDIOC_ENCODER_CMD, vidioc_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), @@ -1789,9 +1937,9 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset, v4l_print_dv_preset, 0), IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), - IOCTL_INFO(VIDIOC_DQEVENT, 0), - IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0), - IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0), + IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0), + IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0), + IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0), IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, 0), IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), @@ -1903,124 +2051,6 @@ static long __video_do_ioctl(struct file *file, } switch (cmd) { - case VIDIOC_G_SLICED_VBI_CAP: - { - struct v4l2_sliced_vbi_cap *p = arg; - - /* Clear up to type, everything after type is zerod already */ - memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); - - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p); - if (!ret) - dbgarg2("service_set=%d\n", p->service_set); - break; - } - case VIDIOC_ENUM_FRAMESIZES: - { - struct v4l2_frmsizeenum *p = arg; - - ret = ops->vidioc_enum_framesizes(file, fh, p); - dbgarg(cmd, - "index=%d, pixelformat=%c%c%c%c, type=%d ", - p->index, - (p->pixel_format & 0xff), - (p->pixel_format >> 8) & 0xff, - (p->pixel_format >> 16) & 0xff, - (p->pixel_format >> 24) & 0xff, - p->type); - switch (p->type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - dbgarg3("width = %d, height=%d\n", - p->discrete.width, p->discrete.height); - break; - case V4L2_FRMSIZE_TYPE_STEPWISE: - dbgarg3("min %dx%d, max %dx%d, step %dx%d\n", - p->stepwise.min_width, p->stepwise.min_height, - p->stepwise.step_width, p->stepwise.step_height, - p->stepwise.max_width, p->stepwise.max_height); - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - dbgarg3("continuous\n"); - break; - default: - dbgarg3("- Unknown type!\n"); - } - - break; - } - case VIDIOC_ENUM_FRAMEINTERVALS: - { - struct v4l2_frmivalenum *p = arg; - - ret = ops->vidioc_enum_frameintervals(file, fh, p); - dbgarg(cmd, - "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ", - p->index, p->pixel_format, - p->width, p->height, p->type); - switch (p->type) { - case V4L2_FRMIVAL_TYPE_DISCRETE: - dbgarg2("fps=%d/%d\n", - p->discrete.numerator, - p->discrete.denominator); - break; - case V4L2_FRMIVAL_TYPE_STEPWISE: - dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n", - p->stepwise.min.numerator, - p->stepwise.min.denominator, - p->stepwise.max.numerator, - p->stepwise.max.denominator, - p->stepwise.step.numerator, - p->stepwise.step.denominator); - break; - case V4L2_FRMIVAL_TYPE_CONTINUOUS: - dbgarg2("continuous\n"); - break; - default: - dbgarg2("- Unknown type!\n"); - } - break; - } - case VIDIOC_DQEVENT: - { - struct v4l2_event *ev = arg; - - ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); - if (ret < 0) { - dbgarg(cmd, "no pending events?"); - break; - } - dbgarg(cmd, - "pending=%d, type=0x%8.8x, sequence=%d, " - "timestamp=%lu.%9.9lu ", - ev->pending, ev->type, ev->sequence, - ev->timestamp.tv_sec, ev->timestamp.tv_nsec); - break; - } - case VIDIOC_SUBSCRIBE_EVENT: - { - struct v4l2_event_subscription *sub = arg; - - ret = ops->vidioc_subscribe_event(fh, sub); - if (ret < 0) { - dbgarg(cmd, "failed, ret=%ld", ret); - break; - } - dbgarg(cmd, "type=0x%8.8x", sub->type); - break; - } - case VIDIOC_UNSUBSCRIBE_EVENT: - { - struct v4l2_event_subscription *sub = arg; - - ret = ops->vidioc_unsubscribe_event(fh, sub); - if (ret < 0) { - dbgarg(cmd, "failed, ret=%ld", ret); - break; - } - dbgarg(cmd, "type=0x%8.8x", sub->type); - break; - } default: if (!ops->vidioc_default) break; -- GitLab From f18d8e07b28e2950679edaa4edaa7ce410dd57fc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:35:01 -0300 Subject: [PATCH 1970/5711] [media] v4l2-ioctl.c: finalize table conversion Implement the default case which finalizes the table conversion and allows us to remove the last part of the switch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 35 ++++++++++++-------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 74fe6a2797e8..9ded54b16e88 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -855,6 +855,11 @@ static void v4l_print_newline(const void *arg, bool write_only) pr_cont("\n"); } +static void v4l_print_default(const void *arg, bool write_only) +{ + pr_cont("driver-specific ioctl\n"); +} + static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) { __u32 i; @@ -1839,12 +1844,6 @@ struct v4l2_ioctl_info { sizeof(((struct v4l2_struct *)0)->field)) << 16) #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) -#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl, \ - .flags = _flags, \ - .name = #_ioctl, \ -} - #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ [_IOC_NR(_ioctl)] = { \ .ioctl = _ioctl, \ @@ -2028,12 +2027,12 @@ static long __video_do_ioctl(struct file *file, } else { default_info.ioctl = cmd; default_info.flags = 0; - default_info.debug = NULL; + default_info.debug = v4l_print_default; info = &default_info; } write_only = _IOC_DIR(cmd) == _IOC_WRITE; - if (info->debug && write_only && vfd->debug > V4L2_DEBUG_IOCTL) { + if (write_only && vfd->debug > V4L2_DEBUG_IOCTL) { v4l_print_ioctl(vfd->name, cmd); pr_cont(": "); info->debug(arg, write_only); @@ -2044,22 +2043,16 @@ static long __video_do_ioctl(struct file *file, const vidioc_op *vidioc = p + info->offset; ret = (*vidioc)(file, fh, arg); - goto done; } else if (info->flags & INFO_FL_FUNC) { ret = info->func(ops, file, fh, arg); - goto done; + } else if (!ops->vidioc_default) { + ret = -ENOTTY; + } else { + ret = ops->vidioc_default(file, fh, + use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, + cmd, arg); } - switch (cmd) { - default: - if (!ops->vidioc_default) - break; - ret = ops->vidioc_default(file, fh, use_fh_prio ? - v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, - cmd, arg); - break; - } /* switch */ - done: if (vfd->debug) { if (write_only && vfd->debug > V4L2_DEBUG_IOCTL) { @@ -2073,8 +2066,6 @@ done: pr_cont(": error %ld\n", ret); else if (vfd->debug == V4L2_DEBUG_IOCTL) pr_cont("\n"); - else if (!info->debug) - return ret; else if (_IOC_DIR(cmd) == _IOC_NONE) info->debug(arg, write_only); else { -- GitLab From 80131fe06e0bdd7b429594493c1317ddede89a61 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:37:38 -0300 Subject: [PATCH 1971/5711] [media] v4l2-dev.c: add debug sysfs entry Since this could theoretically change the debug value while in the middle of v4l2-ioctl.c, we make a copy of vfd->debug to ensure consistent debug behavior. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 24 ++++++++++++++++++++++++ drivers/media/video/v4l2-ioctl.c | 9 +++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 83dbb2ddff10..c2122e53f051 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -46,6 +46,29 @@ static ssize_t show_index(struct device *cd, return sprintf(buf, "%i\n", vdev->index); } +static ssize_t show_debug(struct device *cd, + struct device_attribute *attr, char *buf) +{ + struct video_device *vdev = to_video_device(cd); + + return sprintf(buf, "%i\n", vdev->debug); +} + +static ssize_t set_debug(struct device *cd, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct video_device *vdev = to_video_device(cd); + int res = 0; + u16 value; + + res = kstrtou16(buf, 0, &value); + if (res) + return res; + + vdev->debug = value; + return len; +} + static ssize_t show_name(struct device *cd, struct device_attribute *attr, char *buf) { @@ -56,6 +79,7 @@ static ssize_t show_name(struct device *cd, static struct device_attribute video_device_attrs[] = { __ATTR(name, S_IRUGO, show_name, NULL), + __ATTR(debug, 0644, show_debug, set_debug), __ATTR(index, S_IRUGO, show_index, NULL), __ATTR_NULL }; diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 9ded54b16e88..273c6d7bef65 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1999,6 +1999,7 @@ static long __video_do_ioctl(struct file *file, void *fh = file->private_data; struct v4l2_fh *vfh = NULL; int use_fh_prio = 0; + int debug = vfd->debug; long ret = -ENOTTY; if (ops == NULL) { @@ -2032,7 +2033,7 @@ static long __video_do_ioctl(struct file *file, } write_only = _IOC_DIR(cmd) == _IOC_WRITE; - if (write_only && vfd->debug > V4L2_DEBUG_IOCTL) { + if (write_only && debug > V4L2_DEBUG_IOCTL) { v4l_print_ioctl(vfd->name, cmd); pr_cont(": "); info->debug(arg, write_only); @@ -2054,8 +2055,8 @@ static long __video_do_ioctl(struct file *file, } done: - if (vfd->debug) { - if (write_only && vfd->debug > V4L2_DEBUG_IOCTL) { + if (debug) { + if (write_only && debug > V4L2_DEBUG_IOCTL) { if (ret < 0) printk(KERN_DEBUG "%s: error %ld\n", video_device_node_name(vfd), ret); @@ -2064,7 +2065,7 @@ done: v4l_print_ioctl(vfd->name, cmd); if (ret < 0) pr_cont(": error %ld\n", ret); - else if (vfd->debug == V4L2_DEBUG_IOCTL) + else if (debug == V4L2_DEBUG_IOCTL) pr_cont("\n"); else if (_IOC_DIR(cmd) == _IOC_NONE) info->debug(arg, write_only); -- GitLab From 4a085168b59ec0fb18eb7fa023dcc47f4db14655 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 06:38:06 -0300 Subject: [PATCH 1972/5711] [media] v4l2-ioctl: remove v4l_(i2c_)print_ioctl v4l_i2c_print_ioctl wasn't used and v4l_print_ioctl could be replaced by v4l_printk_ioctl. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 +-- drivers/media/video/sn9c102/sn9c102.h | 2 +- drivers/media/video/uvc/uvc_v4l2.c | 2 +- drivers/media/video/v4l2-ioctl.c | 34 +++++----------------- include/media/v4l2-ioctl.h | 20 ++----------- 5 files changed, 15 insertions(+), 47 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index cbe40806bd71..f344aed32a93 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -957,7 +957,7 @@ static long pvr2_v4l2_ioctl(struct file *file, long ret = -EINVAL; if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) - v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); + v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); if (!pvr2_hdw_dev_ok(hdw)) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -990,7 +990,7 @@ static long pvr2_v4l2_ioctl(struct file *file, pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl failure, ret=%ld" " command was:", ret); - v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), + v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); } } diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 22ea211ab54f..2bc153e869be 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -182,7 +182,7 @@ do { \ # define V4LDBG(level, name, cmd) \ do { \ if (debug >= (level)) \ - v4l_print_ioctl(name, cmd); \ + v4l_printk_ioctl(name, cmd); \ } while (0) # define KDBG(level, fmt, args...) \ do { \ diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 759bef8897e9..f00db3060e0e 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1051,7 +1051,7 @@ static long uvc_v4l2_ioctl(struct file *file, { if (uvc_trace_param & UVC_TRACE_IOCTL) { uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl("); - v4l_printk_ioctl(cmd); + v4l_printk_ioctl(NULL, cmd); printk(")\n"); } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 273c6d7bef65..fd6436edde70 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -28,27 +28,6 @@ #include #include -#define dbgarg(cmd, fmt, arg...) \ - do { \ - if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \ - printk(KERN_DEBUG "%s: ", vfd->name); \ - v4l_printk_ioctl(cmd); \ - printk(" " fmt, ## arg); \ - } \ - } while (0) - -#define dbgarg2(fmt, arg...) \ - do { \ - if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ - printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\ - } while (0) - -#define dbgarg3(fmt, arg...) \ - do { \ - if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ - printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\ - } while (0) - /* Zero out the end of the struct pointed to by p. Everything after, but * not including, the specified field is cleared. */ #define CLEAR_AFTER_FIELD(p, field) \ @@ -1956,10 +1935,13 @@ bool v4l2_is_known_ioctl(unsigned int cmd) /* Common ioctl debug function. This function can be used by external ioctl messages as well as internal V4L ioctl */ -void v4l_printk_ioctl(unsigned int cmd) +void v4l_printk_ioctl(const char *prefix, unsigned int cmd) { const char *dir, *type; + if (prefix) + printk(KERN_DEBUG "%s: ", prefix); + switch (_IOC_TYPE(cmd)) { case 'd': type = "v4l2_int"; @@ -2003,8 +1985,8 @@ static long __video_do_ioctl(struct file *file, long ret = -ENOTTY; if (ops == NULL) { - printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", - vfd->name); + pr_warn("%s: has no ioctl_ops.\n", + video_device_node_name(vfd)); return ret; } @@ -2034,7 +2016,7 @@ static long __video_do_ioctl(struct file *file, write_only = _IOC_DIR(cmd) == _IOC_WRITE; if (write_only && debug > V4L2_DEBUG_IOCTL) { - v4l_print_ioctl(vfd->name, cmd); + v4l_printk_ioctl(video_device_node_name(vfd), cmd); pr_cont(": "); info->debug(arg, write_only); } @@ -2062,7 +2044,7 @@ done: video_device_node_name(vfd), ret); return ret; } - v4l_print_ioctl(vfd->name, cmd); + v4l_printk_ioctl(video_device_node_name(vfd), cmd); if (ret < 0) pr_cont(": error %ld\n", ret); else if (debug == V4L2_DEBUG_IOCTL) diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index d8b76f7392f8..dfd984f10d42 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -295,28 +295,14 @@ struct v4l2_ioctl_ops { #define V4L2_DEBUG_IOCTL 0x01 #define V4L2_DEBUG_IOCTL_ARG 0x02 -/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ -#define v4l_print_ioctl(name, cmd) \ - do { \ - printk(KERN_DEBUG "%s: ", name); \ - v4l_printk_ioctl(cmd); \ - } while (0) - -/* Use this macro in I2C drivers where 'client' is the struct i2c_client - pointer */ -#define v4l_i2c_print_ioctl(client, cmd) \ - do { \ - v4l_client_printk(KERN_DEBUG, client, ""); \ - v4l_printk_ioctl(cmd); \ - } while (0) - /* Video standard functions */ extern const char *v4l2_norm_to_name(v4l2_std_id id); extern void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod); extern int v4l2_video_std_construct(struct v4l2_standard *vs, int id, const char *name); -/* Prints the ioctl in a human-readable format */ -extern void v4l_printk_ioctl(unsigned int cmd); +/* Prints the ioctl in a human-readable format. If prefix != NULL, + then do printk(KERN_DEBUG "%s: ", prefix) first. */ +extern void v4l_printk_ioctl(const char *prefix, unsigned int cmd); /* names for fancy debug output */ extern const char *v4l2_field_names[]; -- GitLab From 074689d692e129082e1846e71870a0c95c1eb3eb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:48:53 -0300 Subject: [PATCH 1973/5711] [media] ivtv: don't mess with vfd->debug This is now controlled by sysfs. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 12 ------------ drivers/media/video/ivtv/ivtv-ioctl.h | 1 - drivers/media/video/ivtv/ivtv-streams.c | 4 ++-- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index f7d57b3f2842..32a591062d0b 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1830,18 +1830,6 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, return 0; } -long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct video_device *vfd = video_devdata(filp); - long ret; - - if (ivtv_debug & IVTV_DBGFLG_IOCTL) - vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; - ret = video_ioctl2(filp, cmd, arg); - vfd->debug = 0; - return ret; -} - static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { .vidioc_querycap = ivtv_querycap, .vidioc_s_audio = ivtv_s_audio, diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index 89185caeafae..7c553d16579b 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h @@ -31,6 +31,5 @@ void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std); void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std); int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int ivtv_s_input(struct file *file, void *fh, unsigned int inp); -long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #endif diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6738592aa35d..87990c5f0910 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -50,7 +50,7 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, - .unlocked_ioctl = ivtv_v4l2_ioctl, + .unlocked_ioctl = video_ioctl2, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_enc_poll, }; @@ -60,7 +60,7 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = { .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, - .unlocked_ioctl = ivtv_v4l2_ioctl, + .unlocked_ioctl = video_ioctl2, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_dec_poll, }; -- GitLab From dcaded7e5f7c66facfd0ced5b368e757cbf576ed Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 10:54:19 -0300 Subject: [PATCH 1974/5711] [media] cx18: don't mess with vfd->debug This is now controlled by sysfs. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 18 ------------------ drivers/media/video/cx18/cx18-ioctl.h | 2 -- drivers/media/video/cx18/cx18-streams.c | 4 ++-- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 35fde4e931f5..e9912db3b496 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -1142,24 +1142,6 @@ static long cx18_default(struct file *file, void *fh, bool valid_prio, return 0; } -long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct video_device *vfd = video_devdata(filp); - struct cx18_open_id *id = file2id(filp); - struct cx18 *cx = id->cx; - long res; - - mutex_lock(&cx->serialize_lock); - - if (cx18_debug & CX18_DBGFLG_IOCTL) - vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; - res = video_ioctl2(filp, cmd, arg); - vfd->debug = 0; - mutex_unlock(&cx->serialize_lock); - return res; -} - static const struct v4l2_ioctl_ops cx18_ioctl_ops = { .vidioc_querycap = cx18_querycap, .vidioc_s_audio = cx18_s_audio, diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h index dcb2559ad520..2f9dd591ee0f 100644 --- a/drivers/media/video/cx18/cx18-ioctl.h +++ b/drivers/media/video/cx18/cx18-ioctl.h @@ -29,5 +29,3 @@ void cx18_set_funcs(struct video_device *vdev); int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std); int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int cx18_s_input(struct file *file, void *fh, unsigned int inp); -long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 4185bcb80ca3..9d598ab88615 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -40,8 +40,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = { .owner = THIS_MODULE, .read = cx18_v4l2_read, .open = cx18_v4l2_open, - /* FIXME change to video_ioctl2 if serialization lock can be removed */ - .unlocked_ioctl = cx18_v4l2_ioctl, + .unlocked_ioctl = video_ioctl2, .release = cx18_v4l2_close, .poll = cx18_v4l2_enc_poll, .mmap = cx18_v4l2_mmap, @@ -376,6 +375,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) s->video_dev->fops = &cx18_v4l2_enc_fops; s->video_dev->release = video_device_release; s->video_dev->tvnorms = V4L2_STD_ALL; + s->video_dev->lock = &cx->serialize_lock; set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags); cx18_set_funcs(s->video_dev); return 0; -- GitLab From 37d9ed94b97efdacf1cbff91216920d1a620b8cd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jun 2012 17:10:30 -0300 Subject: [PATCH 1975/5711] [media] vb2-core: refactor reqbufs/create_bufs Split off the memory and type validation. This is done both from reqbufs and create_bufs, and will also be done by vb2 helpers in a later patch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 145 ++++++++++++++------------- 1 file changed, 77 insertions(+), 68 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index ec24718b3ed0..60e7bc78d190 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -454,7 +454,50 @@ static int __verify_mmap_ops(struct vb2_queue *q) } /** - * vb2_reqbufs() - Initiate streaming + * __verify_memory_type() - Check whether the memory type and buffer type + * passed to a buffer operation are compatible with the queue. + */ +static int __verify_memory_type(struct vb2_queue *q, + enum v4l2_memory memory, enum v4l2_buf_type type) +{ + if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR) { + dprintk(1, "reqbufs: unsupported memory type\n"); + return -EINVAL; + } + + if (type != q->type) { + dprintk(1, "reqbufs: requested type is incorrect\n"); + return -EINVAL; + } + + /* + * Make sure all the required memory ops for given memory type + * are available. + */ + if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) { + dprintk(1, "reqbufs: MMAP for current setup unsupported\n"); + return -EINVAL; + } + + if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) { + dprintk(1, "reqbufs: USERPTR for current setup unsupported\n"); + return -EINVAL; + } + + /* + * Place the busy tests at the end: -EBUSY can be ignored when + * create_bufs is called with count == 0, but count == 0 should still + * do the memory and type validation. + */ + if (q->fileio) { + dprintk(1, "reqbufs: file io in progress\n"); + return -EBUSY; + } + return 0; +} + +/** + * __reqbufs() - Initiate streaming * @q: videobuf2 queue * @req: struct passed from userspace to vidioc_reqbufs handler in driver * @@ -476,46 +519,16 @@ static int __verify_mmap_ops(struct vb2_queue *q) * The return values from this function are intended to be directly returned * from vidioc_reqbufs handler in driver. */ -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) +static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) { unsigned int num_buffers, allocated_buffers, num_planes = 0; - int ret = 0; - - if (q->fileio) { - dprintk(1, "reqbufs: file io in progress\n"); - return -EBUSY; - } - - if (req->memory != V4L2_MEMORY_MMAP - && req->memory != V4L2_MEMORY_USERPTR) { - dprintk(1, "reqbufs: unsupported memory type\n"); - return -EINVAL; - } - - if (req->type != q->type) { - dprintk(1, "reqbufs: requested type is incorrect\n"); - return -EINVAL; - } + int ret; if (q->streaming) { dprintk(1, "reqbufs: streaming active\n"); return -EBUSY; } - /* - * Make sure all the required memory ops for given memory type - * are available. - */ - if (req->memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) { - dprintk(1, "reqbufs: MMAP for current setup unsupported\n"); - return -EINVAL; - } - - if (req->memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) { - dprintk(1, "reqbufs: USERPTR for current setup unsupported\n"); - return -EINVAL; - } - if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) { /* * We already have buffers allocated, so first check if they @@ -595,10 +608,23 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) return 0; } + +/** + * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and + * type values. + * @q: videobuf2 queue + * @req: struct passed from userspace to vidioc_reqbufs handler in driver + */ +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) +{ + int ret = __verify_memory_type(q, req->memory, req->type); + + return ret ? ret : __reqbufs(q, req); +} EXPORT_SYMBOL_GPL(vb2_reqbufs); /** - * vb2_create_bufs() - Allocate buffers and any required auxiliary structs + * __create_bufs() - Allocate buffers and any required auxiliary structs * @q: videobuf2 queue * @create: creation parameters, passed from userspace to vidioc_create_bufs * handler in driver @@ -612,40 +638,10 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs); * The return values from this function are intended to be directly returned * from vidioc_create_bufs handler in driver. */ -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) +static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) { unsigned int num_planes = 0, num_buffers, allocated_buffers; - int ret = 0; - - if (q->fileio) { - dprintk(1, "%s(): file io in progress\n", __func__); - return -EBUSY; - } - - if (create->memory != V4L2_MEMORY_MMAP - && create->memory != V4L2_MEMORY_USERPTR) { - dprintk(1, "%s(): unsupported memory type\n", __func__); - return -EINVAL; - } - - if (create->format.type != q->type) { - dprintk(1, "%s(): requested type is incorrect\n", __func__); - return -EINVAL; - } - - /* - * Make sure all the required memory ops for given memory type - * are available. - */ - if (create->memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) { - dprintk(1, "%s(): MMAP for current setup unsupported\n", __func__); - return -EINVAL; - } - - if (create->memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) { - dprintk(1, "%s(): USERPTR for current setup unsupported\n", __func__); - return -EINVAL; - } + int ret; if (q->num_buffers == VIDEO_MAX_FRAME) { dprintk(1, "%s(): maximum number of buffers already allocated\n", @@ -653,8 +649,6 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) return -ENOBUFS; } - create->index = q->num_buffers; - if (!q->num_buffers) { memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); @@ -719,6 +713,21 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) return 0; } + +/** + * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and + * type values. + * @q: videobuf2 queue + * @create: creation parameters, passed from userspace to vidioc_create_bufs + * handler in driver + */ +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) +{ + int ret = __verify_memory_type(q, create->memory, create->format.type); + + create->index = q->num_buffers; + return ret ? ret : __create_bufs(q, create); +} EXPORT_SYMBOL_GPL(vb2_create_bufs); /** -- GitLab From f05393d2eb45b3cc9663223c3709134ccef51290 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 05:44:14 -0300 Subject: [PATCH 1976/5711] [media] vb2-core: add support for count == 0 in create_bufs This also fixes incorrect error handling in create_bufs: the return code of __vb2_queue_alloc is the number of allocated buffers, and not a traditional error code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 60e7bc78d190..ed38eb748357 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -669,9 +669,9 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create /* Finally, allocate buffers and video memory */ ret = __vb2_queue_alloc(q, create->memory, num_buffers, num_planes); - if (ret < 0) { - dprintk(1, "Memory allocation failed with error: %d\n", ret); - return ret; + if (ret == 0) { + dprintk(1, "Memory allocation failed\n"); + return -ENOMEM; } allocated_buffers = ret; @@ -702,7 +702,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create if (ret < 0) { __vb2_queue_free(q, allocated_buffers); - return ret; + return -ENOMEM; } /* @@ -726,6 +726,8 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) int ret = __verify_memory_type(q, create->memory, create->format.type); create->index = q->num_buffers; + if (create->count == 0) + return ret != -EBUSY ? ret : 0; return ret ? ret : __create_bufs(q, create); } EXPORT_SYMBOL_GPL(vb2_create_bufs); -- GitLab From 5d44f5e3e388739f017a74e73dab2a995673915f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 05:47:30 -0300 Subject: [PATCH 1977/5711] [media] Spec: document CREATE_BUFS behavior if count == 0 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-create-bufs.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index a2474ecb574a..5e73b1c8d095 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml @@ -97,7 +97,13 @@ information. __u32 count - The number of buffers requested or granted. + The number of buffers requested or granted. If count == 0, then + VIDIOC_CREATE_BUFS will set index + to the current number of created buffers, and it will check the validity of + memory and format.type. + If those are invalid -1 is returned and errno is set to &EINVAL;, + otherwise VIDIOC_CREATE_BUFS returns 0. It will + never set errno to &EBUSY; in this particular case. __u32 -- GitLab From 5a5adf6b669cf1a3dd2af419cd68a4c491f384a3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 07:29:35 -0300 Subject: [PATCH 1978/5711] [media] v4l2-dev/ioctl.c: add vb2_queue support to video_device This prepares struct video_device for easier integration with vb2. It also introduces a new lock that protects the vb2_queue. It is up to the driver to use it or not. And the driver can associate an owner filehandle with the queue to check whether queuing requests are permitted for the calling filehandle. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 16 +++++----------- drivers/media/video/v4l2-ioctl.c | 31 +++++++++++++++++++++++-------- include/media/v4l2-dev.h | 3 +++ include/media/v4l2-ioctl.h | 5 +++++ include/media/videobuf2-core.h | 13 +++++++++++++ 5 files changed, 49 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index c2122e53f051..b82778174eef 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -348,20 +348,14 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int ret = -ENODEV; if (vdev->fops->unlocked_ioctl) { - bool locked = false; + struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd); - if (vdev->lock) { - /* always lock unless the cmd is marked as "don't use lock" */ - locked = !v4l2_is_known_ioctl(cmd) || - !test_bit(_IOC_NR(cmd), vdev->disable_locking); - - if (locked && mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; - } + if (lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); - if (locked) - mutex_unlock(vdev->lock); + if (lock) + mutex_unlock(lock); } else if (vdev->fops->ioctl) { /* This code path is a replacement for the BKL. It is a major * hack but it will have to do for those drivers that are not diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index fd6436edde70..70e0efb127a6 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -27,6 +27,7 @@ #include #include #include +#include /* Zero out the end of the struct pointed to by p. Everything after, but * not including, the specified field is cleared. */ @@ -1817,6 +1818,8 @@ struct v4l2_ioctl_info { #define INFO_FL_STD (1 << 2) /* This is ioctl has its own function */ #define INFO_FL_FUNC (1 << 3) +/* Queuing ioctl */ +#define INFO_FL_QUEUE (1 << 4) /* Zero struct from after the field to the end */ #define INFO_FL_CLEAR(v4l2_struct, field) \ ((offsetof(struct v4l2_struct, field) + \ @@ -1846,15 +1849,15 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)), IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_CLEAR(v4l2_buffer, length)), + IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, 0), - IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, 0), - IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), @@ -1918,8 +1921,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0), IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0), IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0), - IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, 0), + IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, 0), @@ -1933,6 +1936,18 @@ bool v4l2_is_known_ioctl(unsigned int cmd) return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; } +struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd) +{ + if (_IOC_NR(cmd) >= V4L2_IOCTLS) + return vdev->lock; + if (test_bit(_IOC_NR(cmd), vdev->disable_locking)) + return NULL; + if (vdev->queue && vdev->queue->lock && + (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) + return vdev->queue->lock; + return vdev->lock; +} + /* Common ioctl debug function. This function can be used by external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(const char *prefix, unsigned int cmd) diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index a056e6ee1b68..5c416cdc88d5 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -100,6 +100,9 @@ struct video_device /* Control handler associated with this device node. May be NULL. */ struct v4l2_ctrl_handler *ctrl_handler; + /* vb2_queue associated with this device node. May be NULL. */ + struct vb2_queue *queue; + /* Priority state. If NULL, then v4l2_dev->prio will be used. */ struct v4l2_prio_state *prio; diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index dfd984f10d42..19e93523c2d8 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -304,6 +304,11 @@ extern int v4l2_video_std_construct(struct v4l2_standard *vs, then do printk(KERN_DEBUG "%s: ", prefix) first. */ extern void v4l_printk_ioctl(const char *prefix, unsigned int cmd); +/* Internal use only: get the mutex (if any) that we need to lock for the + given command. */ +struct video_device; +extern struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd); + /* names for fancy debug output */ extern const char *v4l2_field_names[]; extern const char *v4l2_type_names[]; diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index a15d1f1b319e..924e95e0a0a6 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -244,12 +244,23 @@ struct vb2_ops { void (*buf_queue)(struct vb2_buffer *vb); }; +struct v4l2_fh; + /** * struct vb2_queue - a videobuf queue * * @type: queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h * @io_modes: supported io methods (see vb2_io_modes enum) * @io_flags: additional io flags (see vb2_fileio_flags enum) + * @lock: pointer to a mutex that protects the vb2_queue struct. The + * driver can set this to a mutex to let the v4l2 core serialize + * the queuing ioctls. If the driver wants to handle locking + * itself, then this should be set to NULL. This lock is not used + * by the videobuf2 core API. + * @owner: The filehandle that 'owns' the buffers, i.e. the filehandle + * that called reqbufs, create_buffers or started fileio. + * This field is not used by the videobuf2 core API, but it allows + * drivers to easily associate an owner filehandle with the queue. * @ops: driver-specific callbacks * @mem_ops: memory allocator specific callbacks * @drv_priv: driver private data @@ -273,6 +284,8 @@ struct vb2_queue { enum v4l2_buf_type type; unsigned int io_modes; unsigned int io_flags; + struct mutex *lock; + struct v4l2_fh *owner; const struct vb2_ops *ops; const struct vb2_mem_ops *mem_ops; -- GitLab From 4c1ffcaad5070ea5bca9b8057bdd7b4925237bc0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 05:59:18 -0300 Subject: [PATCH 1979/5711] [media] videobuf2-core: add helper functions Add helper functions to make it easier to adapt drivers to vb2. These helpers take care of core locking and check if the filehandle is the owner of the queue. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 257 +++++++++++++++++++++++++++ include/media/videobuf2-core.h | 41 +++++ 2 files changed, 298 insertions(+) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index ed38eb748357..4e0290ab5071 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -2125,6 +2125,263 @@ size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, } EXPORT_SYMBOL_GPL(vb2_write); + +/* + * The following functions are not part of the vb2 core API, but are helper + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations + * and struct vb2_ops. + * They contain boilerplate code that most if not all drivers have to do + * and so they simplify the driver code. + */ + +/* The queue is busy if there is a owner and you are not that owner. */ +static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file) +{ + return vdev->queue->owner && vdev->queue->owner != file->private_data; +} + +/* vb2 ioctl helpers */ + +int vb2_ioctl_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + struct video_device *vdev = video_devdata(file); + int res = __verify_memory_type(vdev->queue, p->memory, p->type); + + if (res) + return res; + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + res = __reqbufs(vdev->queue, p); + /* If count == 0, then the owner has released all buffers and he + is no longer owner of the queue. Otherwise we have a new owner. */ + if (res == 0) + vdev->queue->owner = p->count ? file->private_data : NULL; + return res; +} +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs); + +int vb2_ioctl_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *p) +{ + struct video_device *vdev = video_devdata(file); + int res = __verify_memory_type(vdev->queue, p->memory, p->format.type); + + p->index = vdev->queue->num_buffers; + /* If count == 0, then just check if memory and type are valid. + Any -EBUSY result from __verify_memory_type can be mapped to 0. */ + if (p->count == 0) + return res != -EBUSY ? res : 0; + if (res) + return res; + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + res = __create_bufs(vdev->queue, p); + if (res == 0) + vdev->queue->owner = file->private_data; + return res; +} +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs); + +int vb2_ioctl_prepare_buf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_prepare_buf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf); + +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + /* No need to call vb2_queue_is_busy(), anyone can query buffers. */ + return vb2_querybuf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf); + +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_qbuf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf); + +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf); + +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_streamon(vdev->queue, i); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon); + +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_streamoff(vdev->queue, i); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); + +/* v4l2_file_operations helpers */ + +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = video_devdata(file); + + return vb2_mmap(vdev->queue, vma); +} +EXPORT_SYMBOL_GPL(vb2_fop_mmap); + +int vb2_fop_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + + if (file->private_data == vdev->queue->owner) { + vb2_queue_release(vdev->queue); + vdev->queue->owner = NULL; + } + return v4l2_fh_release(file); +} +EXPORT_SYMBOL_GPL(vb2_fop_release); + +ssize_t vb2_fop_write(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && lock; + int err = -EBUSY; + + if (must_lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; + if (vb2_queue_is_busy(vdev, file)) + goto exit; + err = vb2_write(vdev->queue, buf, count, ppos, + file->f_flags & O_NONBLOCK); + if (err >= 0) + vdev->queue->owner = file->private_data; +exit: + if (must_lock) + mutex_unlock(lock); + return err; +} +EXPORT_SYMBOL_GPL(vb2_fop_write); + +ssize_t vb2_fop_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && vdev->lock; + int err = -EBUSY; + + if (must_lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; + if (vb2_queue_is_busy(vdev, file)) + goto exit; + err = vb2_read(vdev->queue, buf, count, ppos, + file->f_flags & O_NONBLOCK); + if (err >= 0) + vdev->queue->owner = file->private_data; +exit: + if (must_lock) + mutex_unlock(lock); + return err; +} +EXPORT_SYMBOL_GPL(vb2_fop_read); + +unsigned int vb2_fop_poll(struct file *file, poll_table *wait) +{ + struct video_device *vdev = video_devdata(file); + struct vb2_queue *q = vdev->queue; + struct mutex *lock = q->lock ? q->lock : vdev->lock; + unsigned long req_events = poll_requested_events(wait); + unsigned res; + void *fileio; + /* Yuck. We really need to get rid of this flag asap. If it is + set, then the core took the serialization lock before calling + poll(). This is being phased out, but for now we have to handle + this case. */ + bool locked = test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); + bool must_lock = false; + + /* Try to be smart: only lock if polling might start fileio, + otherwise locking will only introduce unwanted delays. */ + if (q->num_buffers == 0 && q->fileio == NULL) { + if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && + (req_events & (POLLIN | POLLRDNORM))) + must_lock = true; + else if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && + (req_events & (POLLOUT | POLLWRNORM))) + must_lock = true; + } + + /* If locking is needed, but this helper doesn't know how, then you + shouldn't be using this helper but you should write your own. */ + WARN_ON(must_lock && !locked && !lock); + + if (must_lock && !locked && lock && mutex_lock_interruptible(lock)) + return POLLERR; + + fileio = q->fileio; + + res = vb2_poll(vdev->queue, file, wait); + + /* If fileio was started, then we have a new queue owner. */ + if (must_lock && !fileio && q->fileio) + q->owner = file->private_data; + if (must_lock && !locked && lock) + mutex_unlock(lock); + return res; +} +EXPORT_SYMBOL_GPL(vb2_fop_poll); + +#ifndef CONFIG_MMU +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct video_device *vdev = video_devdata(file); + + return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); +} +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); +#endif + +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */ + +void vb2_ops_wait_prepare(struct vb2_queue *vq) +{ + mutex_unlock(vq->lock); +} +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare); + +void vb2_ops_wait_finish(struct vb2_queue *vq) +{ + mutex_lock(vq->lock); +} +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish); + MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski"); MODULE_LICENSE("GPL"); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 924e95e0a0a6..8dd9b6cc296b 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -417,4 +417,45 @@ vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no) return 0; } +/* + * The following functions are not part of the vb2 core API, but are simple + * helper functions that you can use in your struct v4l2_file_operations, + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock + * or video_device->lock is set, and they will set and test vb2_queue->owner + * to check if the calling filehandle is permitted to do the queuing operation. + */ + +/* struct v4l2_ioctl_ops helpers */ + +int vb2_ioctl_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p); +int vb2_ioctl_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *p); +int vb2_ioctl_prepare_buf(struct file *file, void *priv, + struct v4l2_buffer *p); +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p); +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p); +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); + +/* struct v4l2_file_operations helpers */ + +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma); +int vb2_fop_release(struct file *file); +ssize_t vb2_fop_write(struct file *file, char __user *buf, + size_t count, loff_t *ppos); +ssize_t vb2_fop_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos); +unsigned int vb2_fop_poll(struct file *file, poll_table *wait); +#ifndef CONFIG_MMU +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags); +#endif + +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */ + +void vb2_ops_wait_prepare(struct vb2_queue *vq); +void vb2_ops_wait_finish(struct vb2_queue *vq); + #endif /* _MEDIA_VIDEOBUF2_CORE_H */ -- GitLab From 4e1d2ac63368843d63dc38ed42f141506bd1e988 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 05:49:33 -0300 Subject: [PATCH 1980/5711] [media] vivi: remove pointless g/s_std support Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 08c10240e70f..e00efcf02571 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1072,11 +1072,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) return vb2_streamoff(&dev->vb_vidq, i); } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) -{ - return 0; -} - /* only one input in this sample driver */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) @@ -1085,7 +1080,6 @@ static int vidioc_enum_input(struct file *file, void *priv, return -EINVAL; inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_525_60; sprintf(inp->name, "Camera %u", inp->index); return 0; } @@ -1318,7 +1312,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1334,9 +1327,6 @@ static struct video_device vivi_template = { .fops = &vivi_fops, .ioctl_ops = &vivi_ioctl_ops, .release = video_device_release, - - .tvnorms = V4L2_STD_525_60, - .current_norm = V4L2_STD_NTSC_M, }; /* ----------------------------------------------------------------- -- GitLab From 70bd97ae5f12299b152d4220cfc77d8078b21d35 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 11:27:43 -0300 Subject: [PATCH 1981/5711] [media] vivi: embed struct video_device instead of allocating it Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index e00efcf02571..1e4da5e43a32 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -188,6 +188,7 @@ struct vivi_dev { struct list_head vivi_devlist; struct v4l2_device v4l2_dev; struct v4l2_ctrl_handler ctrl_handler; + struct video_device vdev; /* controls */ struct v4l2_ctrl *brightness; @@ -213,9 +214,6 @@ struct vivi_dev { spinlock_t slock; struct mutex mutex; - /* various device info */ - struct video_device *vfd; - struct vivi_dmaqueue vidq; /* Several counters */ @@ -1326,7 +1324,7 @@ static struct video_device vivi_template = { .name = "vivi", .fops = &vivi_fops, .ioctl_ops = &vivi_ioctl_ops, - .release = video_device_release, + .release = video_device_release_empty, }; /* ----------------------------------------------------------------- @@ -1344,8 +1342,8 @@ static int vivi_release(void) dev = list_entry(list, struct vivi_dev, vivi_devlist); v4l2_info(&dev->v4l2_dev, "unregistering %s\n", - video_device_node_name(dev->vfd)); - video_unregister_device(dev->vfd); + video_device_node_name(&dev->vdev)); + video_unregister_device(&dev->vdev); v4l2_device_unregister(&dev->v4l2_dev); v4l2_ctrl_handler_free(&dev->ctrl_handler); kfree(dev); @@ -1430,11 +1428,7 @@ static int __init vivi_create_instance(int inst) INIT_LIST_HEAD(&dev->vidq.active); init_waitqueue_head(&dev->vidq.wq); - ret = -ENOMEM; - vfd = video_device_alloc(); - if (!vfd) - goto unreg_dev; - + vfd = &dev->vdev; *vfd = vivi_template; vfd->debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; @@ -1445,12 +1439,11 @@ static int __init vivi_create_instance(int inst) * all fops and v4l2 ioctls. */ vfd->lock = &dev->mutex; + video_set_drvdata(vfd, dev); ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); if (ret < 0) - goto rel_vdev; - - video_set_drvdata(vfd, dev); + goto unreg_dev; /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); @@ -1458,13 +1451,10 @@ static int __init vivi_create_instance(int inst) if (video_nr != -1) video_nr++; - dev->vfd = vfd; v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(vfd)); return 0; -rel_vdev: - video_device_release(vfd); unreg_dev: v4l2_ctrl_handler_free(hdl); v4l2_device_unregister(&dev->v4l2_dev); -- GitLab From f2ba5a0b469952328b03e239acacd77858f19fb3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 05:53:02 -0300 Subject: [PATCH 1982/5711] [media] vivi: use vb2 helper functions Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 150 +++---------------------------------- 1 file changed, 12 insertions(+), 138 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 1e4da5e43a32..f6d7c6e3390e 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -790,27 +790,6 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, return 0; } -static int buffer_init(struct vb2_buffer *vb) -{ - struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - - BUG_ON(NULL == dev->fmt); - - /* - * This callback is called once per buffer, after its allocation. - * - * Vivi does not allow changing format during streaming, but it is - * possible to do so when streaming is paused (i.e. in streamoff state). - * Buffers however are not freed when going into streamoff and so - * buffer size verification has to be done in buffer_prepare, on each - * qbuf. - * It would be best to move verification code here to buf_init and - * s_fmt though. - */ - - return 0; -} - static int buffer_prepare(struct vb2_buffer *vb) { struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue); @@ -848,20 +827,6 @@ static int buffer_prepare(struct vb2_buffer *vb) return 0; } -static int buffer_finish(struct vb2_buffer *vb) -{ - struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - dprintk(dev, 1, "%s\n", __func__); - return 0; -} - -static void buffer_cleanup(struct vb2_buffer *vb) -{ - struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - dprintk(dev, 1, "%s\n", __func__); - -} - static void buffer_queue(struct vb2_buffer *vb) { struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue); @@ -907,10 +872,7 @@ static void vivi_unlock(struct vb2_queue *vq) static struct vb2_ops vivi_video_qops = { .queue_setup = queue_setup, - .buf_init = buffer_init, .buf_prepare = buffer_prepare, - .buf_finish = buffer_finish, - .buf_cleanup = buffer_cleanup, .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, @@ -1019,7 +981,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (ret < 0) return ret; - if (vb2_is_streaming(q)) { + if (vb2_is_busy(q)) { dprintk(dev, 1, "%s device busy\n", __func__); return -EBUSY; } @@ -1033,43 +995,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_reqbufs(&dev->vb_vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_querybuf(&dev->vb_vidq, p); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_qbuf(&dev->vb_vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK); -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_streamon(&dev->vb_vidq, i); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct vivi_dev *dev = video_drvdata(file); - return vb2_streamoff(&dev->vb_vidq, i); -} - /* only one input in this sample driver */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) @@ -1137,58 +1062,6 @@ static int vivi_s_ctrl(struct v4l2_ctrl *ctrl) File operations for the device ------------------------------------------------------------------*/ -static ssize_t -vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct vivi_dev *dev = video_drvdata(file); - int err; - - dprintk(dev, 1, "read called\n"); - mutex_lock(&dev->mutex); - err = vb2_read(&dev->vb_vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - mutex_unlock(&dev->mutex); - return err; -} - -static unsigned int -vivi_poll(struct file *file, struct poll_table_struct *wait) -{ - struct vivi_dev *dev = video_drvdata(file); - struct vb2_queue *q = &dev->vb_vidq; - - dprintk(dev, 1, "%s\n", __func__); - return vb2_poll(q, file, wait); -} - -static int vivi_close(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct vivi_dev *dev = video_drvdata(file); - - dprintk(dev, 1, "close called (dev=%s), file %p\n", - video_device_node_name(vdev), file); - - if (v4l2_fh_is_singular_file(file)) - vb2_queue_release(&dev->vb_vidq); - return v4l2_fh_release(file); -} - -static int vivi_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vivi_dev *dev = video_drvdata(file); - int ret; - - dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); - - ret = vb2_mmap(&dev->vb_vidq, vma); - dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, - ret); - return ret; -} - static const struct v4l2_ctrl_ops vivi_ctrl_ops = { .g_volatile_ctrl = vivi_g_volatile_ctrl, .s_ctrl = vivi_s_ctrl, @@ -1293,11 +1166,11 @@ static const struct v4l2_ctrl_config vivi_ctrl_int_menu = { static const struct v4l2_file_operations vivi_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, - .release = vivi_close, - .read = vivi_read, - .poll = vivi_poll, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .mmap = vivi_mmap, + .mmap = vb2_fop_mmap, }; static const struct v4l2_ioctl_ops vivi_ioctl_ops = { @@ -1306,15 +1179,15 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -1432,6 +1305,7 @@ static int __init vivi_create_instance(int inst) *vfd = vivi_template; vfd->debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; + vfd->queue = q; set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); /* -- GitLab From 2e90c6c38a3a5775cccd728eea74fdacbb29e029 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jun 2012 05:53:31 -0300 Subject: [PATCH 1983/5711] [media] vivi: add create_bufs/preparebuf support Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index f6d7c6e3390e..1e8c4f3ab602 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -767,7 +767,13 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, struct vivi_dev *dev = vb2_get_drv_priv(vq); unsigned long size; - size = dev->width * dev->height * dev->pixelsize; + if (fmt) + size = fmt->fmt.pix.sizeimage; + else + size = dev->width * dev->height * dev->pixelsize; + + if (size == 0) + return -EINVAL; if (0 == *nbuffers) *nbuffers = 32; @@ -1180,6 +1186,8 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, -- GitLab From cc4b7e7f5755d304ffbfc1d44c11ba8e981347b0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Jun 2012 12:13:29 -0300 Subject: [PATCH 1984/5711] [media] v4l2-dev.c: also add debug support for the fops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index b82778174eef..d13c47fc7202 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -305,6 +305,9 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, ret = vdev->fops->read(filp, buf, sz, off); if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) mutex_unlock(vdev->lock); + if (vdev->debug) + printk(KERN_DEBUG "%s: read: %zd (%d)\n", + video_device_node_name(vdev), sz, ret); return ret; } @@ -323,6 +326,9 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, ret = vdev->fops->write(filp, buf, sz, off); if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) mutex_unlock(vdev->lock); + if (vdev->debug) + printk(KERN_DEBUG "%s: write: %zd (%d)\n", + video_device_node_name(vdev), sz, ret); return ret; } @@ -339,6 +345,9 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) ret = vdev->fops->poll(filp, poll); if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) mutex_unlock(vdev->lock); + if (vdev->debug) + printk(KERN_DEBUG "%s: poll: %08x\n", + video_device_node_name(vdev), ret); return ret; } @@ -403,12 +412,17 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp, unsigned long flags) { struct video_device *vdev = video_devdata(filp); + int ret; if (!vdev->fops->get_unmapped_area) return -ENOSYS; if (!video_is_registered(vdev)) return -ENODEV; - return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); + ret = vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); + if (vdev->debug) + printk(KERN_DEBUG "%s: get_unmapped_area (%d)\n", + video_device_node_name(vdev), ret); + return ret; } #endif @@ -426,6 +440,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) ret = vdev->fops->mmap(filp, vm); if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) mutex_unlock(vdev->lock); + if (vdev->debug) + printk(KERN_DEBUG "%s: mmap (%d)\n", + video_device_node_name(vdev), ret); return ret; } @@ -464,6 +481,9 @@ err: /* decrease the refcount in case of an error */ if (ret) video_put(vdev); + if (vdev->debug) + printk(KERN_DEBUG "%s: open (%d)\n", + video_device_node_name(vdev), ret); return ret; } @@ -483,6 +503,9 @@ static int v4l2_release(struct inode *inode, struct file *filp) /* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); + if (vdev->debug) + printk(KERN_DEBUG "%s: release\n", + video_device_node_name(vdev)); return ret; } -- GitLab From 2e43dec0eeb6bca13212b583e750b0aed1c51cd1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 05:51:58 -0300 Subject: [PATCH 1985/5711] [media] pwc: use the new vb2 helpers Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-if.c | 171 +++--------------------------- drivers/media/video/pwc/pwc-v4l.c | 140 ++---------------------- drivers/media/video/pwc/pwc.h | 3 - 3 files changed, 26 insertions(+), 288 deletions(-) diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index ec4e2ef54e65..de7c7ba99ef4 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -136,19 +136,13 @@ static int leds[2] = { 100, 0 }; /***/ -static int pwc_video_close(struct file *file); -static ssize_t pwc_video_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); -static unsigned int pwc_video_poll(struct file *file, poll_table *wait); -static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); - static const struct v4l2_file_operations pwc_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, - .release = pwc_video_close, - .read = pwc_video_read, - .poll = pwc_video_poll, - .mmap = pwc_video_mmap, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; static struct video_device pwc_template = { @@ -562,17 +556,6 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type) /***************************************************************************/ /* Video4Linux functions */ -int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file) -{ - if (pdev->capt_file != NULL && - pdev->capt_file != file) - return -EBUSY; - - pdev->capt_file = file; - - return 0; -} - static void pwc_video_release(struct v4l2_device *v) { struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); @@ -583,113 +566,6 @@ static void pwc_video_release(struct v4l2_device *v) kfree(pdev); } -static int pwc_video_close(struct file *file) -{ - struct pwc_device *pdev = video_drvdata(file); - - /* - * If we're still streaming vb2_queue_release will call stream_stop - * so we must take both the v4l2_lock and the vb_queue_lock. - */ - if (mutex_lock_interruptible(&pdev->v4l2_lock)) - return -ERESTARTSYS; - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) { - mutex_unlock(&pdev->v4l2_lock); - return -ERESTARTSYS; - } - - if (pdev->capt_file == file) { - vb2_queue_release(&pdev->vb_queue); - pdev->capt_file = NULL; - } - - mutex_unlock(&pdev->vb_queue_lock); - mutex_unlock(&pdev->v4l2_lock); - - return v4l2_fh_release(file); -} - -static ssize_t pwc_video_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct pwc_device *pdev = video_drvdata(file); - int lock_v4l2 = 0; - ssize_t ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret) - goto out; - - /* stream_start will get called so we must take the v4l2_lock */ - if (pdev->vb_queue.fileio == NULL) - lock_v4l2 = 1; - - /* Use try_lock, since we're taking the locks in the *wrong* order! */ - if (lock_v4l2 && !mutex_trylock(&pdev->v4l2_lock)) { - ret = -ERESTARTSYS; - goto out; - } - ret = vb2_read(&pdev->vb_queue, buf, count, ppos, - file->f_flags & O_NONBLOCK); - if (lock_v4l2) - mutex_unlock(&pdev->v4l2_lock); -out: - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static unsigned int pwc_video_poll(struct file *file, poll_table *wait) -{ - struct pwc_device *pdev = video_drvdata(file); - struct vb2_queue *q = &pdev->vb_queue; - unsigned long req_events = poll_requested_events(wait); - unsigned int ret = POLL_ERR; - int lock_v4l2 = 0; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return POLL_ERR; - - /* Will this start fileio and thus call start_stream? */ - if ((req_events & (POLLIN | POLLRDNORM)) && - q->num_buffers == 0 && !q->streaming && q->fileio == NULL) { - if (pwc_test_n_set_capt_file(pdev, file)) - goto out; - lock_v4l2 = 1; - } - - /* Use try_lock, since we're taking the locks in the *wrong* order! */ - if (lock_v4l2 && !mutex_trylock(&pdev->v4l2_lock)) - goto out; - ret = vb2_poll(&pdev->vb_queue, file, wait); - if (lock_v4l2) - mutex_unlock(&pdev->v4l2_lock); - -out: - if (!pdev->udev) - ret |= POLLHUP; - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_mmap(&pdev->vb_queue, vma); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - /***************************************************************************/ /* Videobuf2 operations */ @@ -782,6 +658,8 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) if (!pdev->udev) return -ENODEV; + if (mutex_lock_interruptible(&pdev->v4l2_lock)) + return -ERESTARTSYS; /* Turn on camera and set LEDS on */ pwc_camera_power(pdev, 1); pwc_set_leds(pdev, leds[0], leds[1]); @@ -794,6 +672,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) /* And cleanup any queued bufs!! */ pwc_cleanup_queued_bufs(pdev); } + mutex_unlock(&pdev->v4l2_lock); return r; } @@ -802,6 +681,8 @@ static int stop_streaming(struct vb2_queue *vq) { struct pwc_device *pdev = vb2_get_drv_priv(vq); + if (mutex_lock_interruptible(&pdev->v4l2_lock)) + return -ERESTARTSYS; if (pdev->udev) { pwc_set_leds(pdev, 0, 0); pwc_camera_power(pdev, 0); @@ -809,22 +690,11 @@ static int stop_streaming(struct vb2_queue *vq) } pwc_cleanup_queued_bufs(pdev); + mutex_unlock(&pdev->v4l2_lock); return 0; } -static void wait_prepare(struct vb2_queue *vq) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vq); - mutex_unlock(&pdev->vb_queue_lock); -} - -static void wait_finish(struct vb2_queue *vq) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vq); - mutex_lock(&pdev->vb_queue_lock); -} - static struct vb2_ops pwc_vb_queue_ops = { .queue_setup = queue_setup, .buf_init = buffer_init, @@ -834,8 +704,8 @@ static struct vb2_ops pwc_vb_queue_ops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = wait_prepare, - .wait_finish = wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; /***************************************************************************/ @@ -1136,6 +1006,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id /* Init video_device structure */ memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); strcpy(pdev->vdev.name, name); + pdev->vdev.queue = &pdev->vb_queue; + pdev->vdev.queue->lock = &pdev->vb_queue_lock; set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags); video_set_drvdata(&pdev->vdev, pdev); @@ -1190,15 +1062,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vdev.v4l2_dev = &pdev->v4l2_dev; pdev->vdev.lock = &pdev->v4l2_lock; - /* - * Don't take v4l2_lock for these ioctls. This improves latency if - * v4l2_lock is taken for a long time, e.g. when changing a control - * value, and a new frame is ready to be dequeued. - */ - v4l2_disable_ioctl_locking(&pdev->vdev, VIDIOC_DQBUF); - v4l2_disable_ioctl_locking(&pdev->vdev, VIDIOC_QBUF); - v4l2_disable_ioctl_locking(&pdev->vdev, VIDIOC_QUERYBUF); - rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1); if (rc < 0) { PWC_ERROR("Failed to register as video device (%d).\n", rc); @@ -1253,20 +1116,18 @@ static void usb_pwc_disconnect(struct usb_interface *intf) struct v4l2_device *v = usb_get_intfdata(intf); struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); - mutex_lock(&pdev->v4l2_lock); - mutex_lock(&pdev->vb_queue_lock); + mutex_lock(&pdev->v4l2_lock); /* No need to keep the urbs around after disconnection */ if (pdev->vb_queue.streaming) pwc_isoc_cleanup(pdev); pdev->udev = NULL; pwc_cleanup_queued_bufs(pdev); - mutex_unlock(&pdev->vb_queue_lock); v4l2_device_disconnect(&pdev->v4l2_dev); video_unregister_device(&pdev->vdev); - mutex_unlock(&pdev->v4l2_lock); + mutex_unlock(pdev->vb_queue.lock); #ifdef CONFIG_USB_PWC_INPUT_EVDEV if (pdev->button_dev) diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index c691e29cc36e..114ae41bc4af 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -468,17 +468,8 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) if (ret < 0) return ret; - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret) - goto leave; - - if (pdev->vb_queue.streaming) { - ret = -EBUSY; - goto leave; - } + if (vb2_is_busy(&pdev->vb_queue)) + return -EBUSY; pixelformat = f->fmt.pix.pixelformat; @@ -496,8 +487,6 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); -leave: - mutex_unlock(&pdev->vb_queue_lock); return ret; } @@ -933,104 +922,6 @@ static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format * return pwc_vidioc_try_fmt(pdev, f); } -static int pwc_reqbufs(struct file *file, void *fh, - struct v4l2_requestbuffers *rb) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_reqbufs(&pdev->vb_queue, rb); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_querybuf(&pdev->vb_queue, buf); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_qbuf(&pdev->vb_queue, buf); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_dqbuf(&pdev->vb_queue, buf, - file->f_flags & O_NONBLOCK); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_streamon(&pdev->vb_queue, i); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - -static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret == 0) - ret = vb2_streamoff(&pdev->vb_queue, i); - - mutex_unlock(&pdev->vb_queue_lock); - return ret; -} - static int pwc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { @@ -1119,25 +1010,14 @@ static int pwc_s_parm(struct file *file, void *fh, fps = parm->parm.capture.timeperframe.denominator / parm->parm.capture.timeperframe.numerator; - if (mutex_lock_interruptible(&pdev->vb_queue_lock)) - return -ERESTARTSYS; - - ret = pwc_test_n_set_capt_file(pdev, file); - if (ret) - goto leave; - - if (pdev->vb_queue.streaming) { - ret = -EBUSY; - goto leave; - } + if (vb2_is_busy(&pdev->vb_queue)) + return -EBUSY; ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt, fps, &compression, 0); pwc_g_parm(file, fh, parm); -leave: - mutex_unlock(&pdev->vb_queue_lock); return ret; } @@ -1150,12 +1030,12 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { .vidioc_g_fmt_vid_cap = pwc_g_fmt_vid_cap, .vidioc_s_fmt_vid_cap = pwc_s_fmt_vid_cap, .vidioc_try_fmt_vid_cap = pwc_try_fmt_vid_cap, - .vidioc_reqbufs = pwc_reqbufs, - .vidioc_querybuf = pwc_querybuf, - .vidioc_qbuf = pwc_qbuf, - .vidioc_dqbuf = pwc_dqbuf, - .vidioc_streamon = pwc_streamon, - .vidioc_streamoff = pwc_streamoff, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_enum_framesizes = pwc_enum_framesizes, .vidioc_enum_frameintervals = pwc_enum_frameintervals, diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index d6b5b216b9d6..7a6a0d39c2c6 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -239,7 +239,6 @@ struct pwc_device int features; /* feature bits */ /*** Video data ***/ - struct file *capt_file; /* file doing video capture */ int vendpoint; /* video isoc endpoint */ int vcinterface; /* video control interface */ int valternate; /* alternate interface needed */ @@ -355,8 +354,6 @@ struct pwc_device extern int pwc_trace; #endif -int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file); - /** Functions in pwc-misc.c */ /* sizes in pixels */ extern const int pwc_image_sizes[PSZ_MAX][2]; -- GitLab From 387c71b262a7a62d271dc9deb00c173264e33357 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 10 Jun 2012 04:34:10 -0300 Subject: [PATCH 1986/5711] [media] pwc: v4l2-compliance fixes - add device_caps - set colorspace - s_parm should support a fps of 0 (== reset to nominal fps) Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-v4l.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 114ae41bc4af..545e9bbdeede 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -405,6 +405,7 @@ static void pwc_vidioc_fill_fmt(struct v4l2_format *f, f->fmt.pix.pixelformat = pixfmt; f->fmt.pix.bytesperline = f->fmt.pix.width; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", f->fmt.pix.width, @@ -497,10 +498,9 @@ static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap strcpy(cap->driver, PWC_NAME); strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -509,7 +509,8 @@ static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i) if (i->index) /* Only one INPUT is supported */ return -EINVAL; - strcpy(i->name, "usb"); + strlcpy(i->name, "Camera", sizeof(i->name)); + i->type = V4L2_INPUT_TYPE_CAMERA; return 0; } @@ -1003,12 +1004,18 @@ static int pwc_s_parm(struct file *file, void *fh, int compression = 0; int ret, fps; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - parm->parm.capture.timeperframe.numerator == 0) + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - fps = parm->parm.capture.timeperframe.denominator / - parm->parm.capture.timeperframe.numerator; + /* If timeperframe == 0, then reset the framerate to the nominal value. + We pick a high framerate here, and let pwc_set_video_mode() figure + out the best match. */ + if (parm->parm.capture.timeperframe.numerator == 0 || + parm->parm.capture.timeperframe.denominator == 0) + fps = 30; + else + fps = parm->parm.capture.timeperframe.denominator / + parm->parm.capture.timeperframe.numerator; if (vb2_is_busy(&pdev->vb_queue)) return -EBUSY; -- GitLab From 4a77a8361fe79b78b741640b484a97c8d47e307f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 05:43:34 -0300 Subject: [PATCH 1987/5711] [media] v4l2-framework.txt: Update the locking documentation This documents the new queue->lock and how to use it. It also removes the documentation of v4l2_disable_ioctl_locking: this is only used in gspca and will be removed once gspca has been converted to vb2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 73 +++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 1f5905270050..89318be6c1d2 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -594,6 +594,15 @@ You should also set these fields: unlocked_ioctl file operation is called this lock will be taken by the core and released afterwards. See the next section for more details. +- queue: a pointer to the struct vb2_queue associated with this device node. + If queue is non-NULL, and queue->lock is non-NULL, then queue->lock is + used for the queuing ioctls (VIDIOC_REQBUFS, CREATE_BUFS, QBUF, DQBUF, + QUERYBUF, PREPARE_BUF, STREAMON and STREAMOFF) instead of the lock above. + That way the vb2 queuing framework does not have to wait for other ioctls. + This queue pointer is also used by the vb2 helper functions to check for + queuing ownership (i.e. is the filehandle calling it allowed to do the + operation). + - prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY. If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device. If you want to have a separate priority state per (group of) device node(s), @@ -647,47 +656,43 @@ manually set the struct media_entity type and name fields. A reference to the entity will be automatically acquired/released when the video device is opened/closed. -v4l2_file_operations and locking --------------------------------- - -You can set a pointer to a mutex_lock in struct video_device. Usually this -will be either a top-level mutex or a mutex per device node. By default this -lock will be used for unlocked_ioctl, but you can disable locking for -selected ioctls by calling: - - void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd); - -E.g.: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF); +ioctls and locking +------------------ -You have to call this before you register the video_device. +The V4L core provides optional locking services. The main service is the +lock field in struct video_device, which is a pointer to a mutex. If you set +this pointer, then that will be used by unlocked_ioctl to serialize all ioctls. -Particularly with USB drivers where certain commands such as setting controls -can take a long time you may want to do your own locking for the buffer queuing -ioctls. +If you are using the videobuf2 framework, then there is a second lock that you +can set: video_device->queue->lock. If set, then this lock will be used instead +of video_device->lock to serialize all queuing ioctls (see the previous section +for the full list of those ioctls). -If you want still finer-grained locking then you have to set mutex_lock to NULL -and do you own locking completely. +The advantage of using a different lock for the queuing ioctls is that for some +drivers (particularly USB drivers) certain commands such as setting controls +can take a long time, so you want to use a separate lock for the buffer queuing +ioctls. That way your VIDIOC_DQBUF doesn't stall because the driver is busy +changing the e.g. exposure of the webcam. -It is up to the driver developer to decide which method to use. However, if -your driver has high-latency operations (for example, changing the exposure -of a USB webcam might take a long time), then you might be better off with -doing your own locking if you want to allow the user to do other things with -the device while waiting for the high-latency command to finish. +Of course, you can always do all the locking yourself by leaving both lock +pointers at NULL. -If a lock is specified then all ioctl commands will be serialized on that -lock. If you use videobuf then you must pass the same lock to the videobuf -queue initialize function: if videobuf has to wait for a frame to arrive, then -it will temporarily unlock the lock and relock it afterwards. If your driver -also waits in the code, then you should do the same to allow other processes -to access the device node while the first process is waiting for something. +If you use the old videobuf then you must pass the video_device lock to the +videobuf queue initialize function: if videobuf has to wait for a frame to +arrive, then it will temporarily unlock the lock and relock it afterwards. If +your driver also waits in the code, then you should do the same to allow other +processes to access the device node while the first process is waiting for +something. In the case of videobuf2 you will need to implement the wait_prepare and -wait_finish callbacks to unlock/lock if applicable. In particular, if you use -the lock in struct video_device then you must unlock/lock this mutex in -wait_prepare and wait_finish. - -The implementation of a hotplug disconnect should also take the lock before -calling v4l2_device_disconnect. +wait_finish callbacks to unlock/lock if applicable. If you use the queue->lock +pointer, then you can use the helper functions vb2_ops_wait_prepare/finish. + +The implementation of a hotplug disconnect should also take the lock from +video_device before calling v4l2_device_disconnect. If you are also using +video_device->queue->lock, then you have to first lock video_device->queue->lock +followed by video_device->lock. That way you can be sure no ioctl is running +when you call v4l2_device_disconnect. video_device registration ------------------------- -- GitLab From 902e197dcc36138e1f40f4435b7de8893ffc6c15 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 9 May 2012 16:23:07 -0300 Subject: [PATCH 1988/5711] [media] cx88: fix querycap Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 12 +-- drivers/media/video/cx88/cx88-video.c | 90 ++++++++--------------- drivers/media/video/cx88/cx88.h | 2 + 3 files changed, 36 insertions(+), 68 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index ed7b2aa1ed83..cbacdf634fd8 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -722,21 +722,15 @@ static int vidioc_querymenu (struct file *file, void *priv, cx2341x_ctrl_get_menu(&dev->params, qmenu->id)); } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx88_core *core = dev->core; strcpy(cap->driver, "cx88_blackbird"); - strlcpy(cap->card, core->board.name, sizeof(cap->card)); - sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - if (UNSET != core->board.tuner_type) - cap->capabilities |= V4L2_CAP_TUNER; + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + cx88_querycap(file, core, cap); return 0; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 921c56d115d6..5d9973680614 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1195,22 +1195,42 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_querycap (struct file *file, void *priv, +void cx88_querycap(struct file *file, struct cx88_core *core, + struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + strlcpy(cap->card, core->board.name, sizeof(cap->card)); + cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (UNSET != core->board.tuner_type) + cap->device_caps |= V4L2_CAP_TUNER; + switch (vdev->vfl_type) { + case VFL_TYPE_RADIO: + cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; + break; + case VFL_TYPE_GRABBER: + cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + cap->device_caps |= V4L2_CAP_VBI_CAPTURE; + break; + } + cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS; + if (core->board.radio.type == CX88_RADIO) + cap->capabilities |= V4L2_CAP_RADIO; +} +EXPORT_SYMBOL(cx88_querycap); + +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; struct cx88_core *core = dev->core; strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, core->board.name, sizeof(cap->card)); - sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - V4L2_CAP_VBI_CAPTURE; - if (UNSET != core->board.tuner_type) - cap->capabilities |= V4L2_CAP_TUNER; + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + cx88_querycap(file, core, cap); return 0; } @@ -1513,19 +1533,6 @@ static int vidioc_s_register (struct file *file, void *fh, /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ -static int radio_querycap (struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; - struct cx88_core *core = dev->core; - - strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, core->board.name, sizeof(cap->card)); - sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); - cap->capabilities = V4L2_CAP_TUNER; - return 0; -} - static int radio_g_tuner (struct file *file, void *priv, struct v4l2_tuner *t) { @@ -1541,26 +1548,6 @@ static int radio_g_tuner (struct file *file, void *priv, return 0; } -static int radio_enum_input (struct file *file, void *priv, - struct v4l2_input *i) -{ - if (i->index != 0) - return -EINVAL; - strcpy(i->name,"Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a) -{ - if (unlikely(a->index)) - return -EINVAL; - - strcpy(a->name,"Radio"); - return 0; -} - /* FIXME: Should add a standard for radio */ static int radio_s_tuner (struct file *file, void *priv, @@ -1576,17 +1563,6 @@ static int radio_s_tuner (struct file *file, void *priv, return 0; } -static int radio_s_audio (struct file *file, void *fh, - struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input (struct file *file, void *fh, unsigned int i) -{ - return 0; -} - static int radio_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *c) { @@ -1797,13 +1773,9 @@ static const struct v4l2_file_operations radio_fops = }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, + .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, .vidioc_queryctrl = radio_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index c9659def2a78..8e9820cf454e 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -730,3 +730,5 @@ int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_video_mux(struct cx88_core *core, unsigned int input); +void cx88_querycap(struct file *file, struct cx88_core *core, + struct v4l2_capability *cap); -- GitLab From bac639818c2c720ea8f79f932601f9209579bf14 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 10 Jun 2012 07:39:52 -0300 Subject: [PATCH 1989/5711] [media] cx88: first phase to convert cx88 to the control framework Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 31 +- drivers/media/video/cx88/cx88-blackbird.c | 71 ---- drivers/media/video/cx88/cx88-cards.c | 11 + drivers/media/video/cx88/cx88-core.c | 3 +- drivers/media/video/cx88/cx88-video.c | 493 +++++++--------------- drivers/media/video/cx88/cx88.h | 48 ++- 6 files changed, 211 insertions(+), 446 deletions(-) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 04bf6627d362..dfac6e34859f 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -585,13 +585,10 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core = chip->core; - struct v4l2_control client_ctl; int left = value->value.integer.value[0]; int right = value->value.integer.value[1]; int v, b; - memset(&client_ctl, 0, sizeof(client_ctl)); - /* Pass volume & balance onto any WM8775 */ if (left >= right) { v = left << 10; @@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, v = right << 10; b = right ? 0xffff - (0x8000 * left) / right : 0x8000; } - client_ctl.value = v; - client_ctl.id = V4L2_CID_AUDIO_VOLUME; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - - client_ctl.value = b; - client_ctl.id = V4L2_CID_AUDIO_BALANCE; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); + wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); + wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); } /* OK - TODO: test it */ @@ -687,14 +679,8 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); /* Pass mute onto any WM8775 */ if ((core->board.audio_chip == V4L2_IDENT_WM8775) && - ((1<<6) == bit)) { - struct v4l2_control client_ctl; - - memset(&client_ctl, 0, sizeof(client_ctl)); - client_ctl.value = 0 != (vol & bit); - client_ctl.id = V4L2_CID_AUDIO_MUTE; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - } + ((1<<6) == bit)) + wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); ret = 1; } spin_unlock_irq(&chip->reg_lock); @@ -724,13 +710,10 @@ static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core = chip->core; - struct v4l2_control client_ctl; - - memset(&client_ctl, 0, sizeof(client_ctl)); - client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; - call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); - value->value.integer.value[0] = client_ctl.value ? 1 : 0; + s32 val; + val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); + value->value.integer.value[0] = val ? 1 : 0; return 0; } diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index cbacdf634fd8..c9bbe9fc9c7e 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -685,43 +685,6 @@ static struct videobuf_queue_ops blackbird_qops = { /* ------------------------------------------------------------------ */ -static const u32 *ctrl_classes[] = { - cx88_user_ctrls, - cx2341x_mpeg_ctrls, - NULL -}; - -static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl) -{ - qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); - if (qctrl->id == 0) - return -EINVAL; - - /* Standard V4L2 controls */ - if (cx8800_ctrl_query(dev->core, qctrl) == 0) - return 0; - - /* MPEG V4L2 controls */ - if (cx2341x_ctrl_query(&dev->params, qctrl)) - qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - return 0; -} - -/* ------------------------------------------------------------------ */ -/* IOCTL Handlers */ - -static int vidioc_querymenu (struct file *file, void *priv, - struct v4l2_querymenu *qmenu) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct v4l2_queryctrl qctrl; - - qctrl.id = qmenu->id; - blackbird_queryctrl(dev, &qctrl); - return v4l2_ctrl_query_menu(qmenu, &qctrl, - cx2341x_ctrl_get_menu(&dev->params, qmenu->id)); -} - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -917,20 +880,6 @@ static int vidioc_log_status (struct file *file, void *priv) return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, - struct v4l2_queryctrl *qctrl) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - - if (blackbird_queryctrl(dev, qctrl) == 0) - return 0; - - qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); - if (unlikely(qctrl->id == 0)) - return -EINVAL; - return cx8800_ctrl_query(dev->core, qctrl); -} - static int vidioc_enum_input (struct file *file, void *priv, struct v4l2_input *i) { @@ -938,22 +887,6 @@ static int vidioc_enum_input (struct file *file, void *priv, return cx88_enum_input (core,i); } -static int vidioc_g_ctrl (struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - return - cx88_get_control(core,ctl); -} - -static int vidioc_s_ctrl (struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - return - cx88_set_control(core,ctl); -} - static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { @@ -1178,7 +1111,6 @@ static const struct v4l2_file_operations mpeg_fops = }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { - .vidioc_querymenu = vidioc_querymenu, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, @@ -1195,10 +1127,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_log_status = vidioc_log_status, - .vidioc_queryctrl = vidioc_queryctrl, .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cbd5d119a2c6..cd8c3bf698ea 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3693,7 +3693,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) return NULL; } + if (v4l2_ctrl_handler_init(&core->hdl, 13)) { + v4l2_device_unregister(&core->v4l2_dev); + kfree(core); + return NULL; + } + if (0 != cx88_get_resources(core, pci)) { + v4l2_ctrl_handler_free(&core->hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; @@ -3706,6 +3713,10 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->bmmio = (u8 __iomem *)core->lmmio; if (core->lmmio == NULL) { + release_mem_region(pci_resource_start(pci, 0), + pci_resource_len(pci, 0)); + v4l2_ctrl_handler_free(&core->hdl); + v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index fbfdd8067937..a6480aaa8a0b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1030,7 +1030,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, return NULL; *vfd = *template_; vfd->v4l2_dev = &core->v4l2_dev; - vfd->parent = &pci->dev; + vfd->ctrl_handler = &core->hdl; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); @@ -1086,6 +1086,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) iounmap(core->lmmio); cx88_devcount--; mutex_unlock(&devlist); + v4l2_ctrl_handler_free(&core->hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5d9973680614..2f3d4df33f7e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -160,210 +160,144 @@ static const struct v4l2_queryctrl no_ctl = { .flags = V4L2_CTRL_FLAG_DISABLED, }; + +struct cx88_ctrl { + /* control information */ + u32 id; + s32 minimum; + s32 maximum; + u32 step; + s32 default_value; + + /* control register information */ + u32 off; + u32 reg; + u32 sreg; + u32 mask; + u32 shift; +}; + static const struct cx88_ctrl cx8800_ctls[] = { /* --- video --- */ { - .v = { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = MO_CONTR_BRIGHT, - .mask = 0x00ff, - .shift = 0, + .id = V4L2_CID_BRIGHTNESS, + .minimum = 0x00, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .off = 128, + .reg = MO_CONTR_BRIGHT, + .mask = 0x00ff, + .shift = 0, },{ - .v = { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = MO_CONTR_BRIGHT, - .mask = 0xff00, - .shift = 8, + .id = V4L2_CID_CONTRAST, + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x3f, + .off = 0, + .reg = MO_CONTR_BRIGHT, + .mask = 0xff00, + .shift = 8, },{ - .v = { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = MO_HUE, - .mask = 0x00ff, - .shift = 0, + .id = V4L2_CID_HUE, + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .off = 128, + .reg = MO_HUE, + .mask = 0x00ff, + .shift = 0, },{ /* strictly, this only describes only U saturation. * V saturation is handled specially through code. */ - .v = { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = MO_UV_SATURATION, - .mask = 0x00ff, - .shift = 0, + .id = V4L2_CID_SATURATION, + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .off = 0, + .reg = MO_UV_SATURATION, + .mask = 0x00ff, + .shift = 0, }, { - .v = { - .id = V4L2_CID_SHARPNESS, - .name = "Sharpness", - .minimum = 0, - .maximum = 4, - .step = 1, - .default_value = 0x0, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, + .id = V4L2_CID_SHARPNESS, + .minimum = 0, + .maximum = 4, + .step = 1, + .default_value = 0x0, + .off = 0, /* NOTE: the value is converted and written to both even and odd registers in the code */ - .reg = MO_FILTER_ODD, - .mask = 7 << 7, - .shift = 7, + .reg = MO_FILTER_ODD, + .mask = 7 << 7, + .shift = 7, }, { - .v = { - .id = V4L2_CID_CHROMA_AGC, - .name = "Chroma AGC", - .minimum = 0, - .maximum = 1, - .default_value = 0x1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = MO_INPUT_FORMAT, - .mask = 1 << 10, - .shift = 10, + .id = V4L2_CID_CHROMA_AGC, + .minimum = 0, + .maximum = 1, + .default_value = 0x1, + .reg = MO_INPUT_FORMAT, + .mask = 1 << 10, + .shift = 10, }, { - .v = { - .id = V4L2_CID_COLOR_KILLER, - .name = "Color killer", - .minimum = 0, - .maximum = 1, - .default_value = 0x1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = MO_INPUT_FORMAT, - .mask = 1 << 9, - .shift = 9, + .id = V4L2_CID_COLOR_KILLER, + .minimum = 0, + .maximum = 1, + .default_value = 0x1, + .reg = MO_INPUT_FORMAT, + .mask = 1 << 9, + .shift = 9, }, { - .v = { - .id = V4L2_CID_BAND_STOP_FILTER, - .name = "Notch filter", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0x0, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = MO_HTOTAL, - .mask = 3 << 11, - .shift = 11, + .id = V4L2_CID_BAND_STOP_FILTER, + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0x0, + .off = 0, + .reg = MO_HTOTAL, + .mask = 3 << 11, + .shift = 11, }, { - /* --- audio --- */ - .v = { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = AUD_VOL_CTL, - .sreg = SHADOW_AUD_VOL_CTL, - .mask = (1 << 6), - .shift = 6, + /* --- audio --- */ + .id = V4L2_CID_AUDIO_MUTE, + .minimum = 0, + .maximum = 1, + .default_value = 1, + .reg = AUD_VOL_CTL, + .sreg = SHADOW_AUD_VOL_CTL, + .mask = (1 << 6), + .shift = 6, },{ - .v = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0x3f, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .reg = AUD_VOL_CTL, - .sreg = SHADOW_AUD_VOL_CTL, - .mask = 0x3f, - .shift = 0, + .id = V4L2_CID_AUDIO_VOLUME, + .minimum = 0, + .maximum = 0x3f, + .step = 1, + .default_value = 0x3f, + .reg = AUD_VOL_CTL, + .sreg = SHADOW_AUD_VOL_CTL, + .mask = 0x3f, + .shift = 0, },{ - .v = { - .id = V4L2_CID_AUDIO_BALANCE, - .name = "Balance", - .minimum = 0, - .maximum = 0x7f, - .step = 1, - .default_value = 0x40, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .reg = AUD_BAL_CTL, - .sreg = SHADOW_AUD_BAL_CTL, - .mask = 0x7f, - .shift = 0, + .id = V4L2_CID_AUDIO_BALANCE, + .minimum = 0, + .maximum = 0x7f, + .step = 1, + .default_value = 0x40, + .reg = AUD_BAL_CTL, + .sreg = SHADOW_AUD_BAL_CTL, + .mask = 0x7f, + .shift = 0, } }; -enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; -/* Must be sorted from low to high control ID! */ -const u32 cx88_user_ctrls[] = { - V4L2_CID_USER_CLASS, - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_AUDIO_VOLUME, - V4L2_CID_AUDIO_BALANCE, - V4L2_CID_AUDIO_MUTE, - V4L2_CID_SHARPNESS, - V4L2_CID_CHROMA_AGC, - V4L2_CID_COLOR_KILLER, - V4L2_CID_BAND_STOP_FILTER, - 0 -}; -EXPORT_SYMBOL(cx88_user_ctrls); +enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; -static const u32 * const ctrl_classes[] = { - cx88_user_ctrls, - NULL -}; int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) { - int i; - - if (qctrl->id < V4L2_CID_BASE || - qctrl->id >= V4L2_CID_LASTP1) - return -EINVAL; - for (i = 0; i < CX8800_CTLS; i++) - if (cx8800_ctls[i].v.id == qctrl->id) - break; - if (i == CX8800_CTLS) { - *qctrl = no_ctl; - return 0; - } - *qctrl = cx8800_ctls[i].v; - /* Report chroma AGC as inactive when SECAM is selected */ - if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC && - core->tvnorm & V4L2_STD_SECAM) - qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return 0; } EXPORT_SYMBOL(cx8800_ctrl_query); @@ -974,98 +908,43 @@ video_mmap(struct file *file, struct vm_area_struct * vma) /* ------------------------------------------------------------------ */ /* VIDEO CTRL IOCTLS */ -int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl) -{ - const struct cx88_ctrl *c = NULL; - u32 value; - int i; - - for (i = 0; i < CX8800_CTLS; i++) - if (cx8800_ctls[i].v.id == ctl->id) - c = &cx8800_ctls[i]; - if (unlikely(NULL == c)) - return -EINVAL; - - value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); - switch (ctl->id) { - case V4L2_CID_AUDIO_BALANCE: - ctl->value = ((value & 0x7f) < 0x40) ? ((value & 0x7f) + 0x40) - : (0x7f - (value & 0x7f)); - break; - case V4L2_CID_AUDIO_VOLUME: - ctl->value = 0x3f - (value & 0x3f); - break; - case V4L2_CID_SHARPNESS: - ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1) - : 0); - break; - default: - ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; - break; - } - dprintk(1,"get_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctl->id, c->v.name, ctl->value, c->reg, - value,c->mask, c->sreg ? " [shadowed]" : ""); - return 0; -} -EXPORT_SYMBOL(cx88_get_control); - -int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) +static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl) { - const struct cx88_ctrl *c = NULL; + struct cx88_core *core = + container_of(ctrl->handler, struct cx88_core, hdl); + const struct cx88_ctrl *cc = ctrl->priv; u32 value,mask; - int i; - - for (i = 0; i < CX8800_CTLS; i++) { - if (cx8800_ctls[i].v.id == ctl->id) { - c = &cx8800_ctls[i]; - } - } - if (unlikely(NULL == c)) - return -EINVAL; - - if (ctl->value < c->v.minimum) - ctl->value = c->v.minimum; - if (ctl->value > c->v.maximum) - ctl->value = c->v.maximum; /* Pass changes onto any WM8775 */ if (core->board.audio_chip == V4L2_IDENT_WM8775) { - struct v4l2_control client_ctl; - memset(&client_ctl, 0, sizeof(client_ctl)); - client_ctl.id = ctl->id; - - switch (ctl->id) { + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - client_ctl.value = ctl->value; + wm8775_s_ctrl(core, ctrl->id, ctrl->val); break; case V4L2_CID_AUDIO_VOLUME: - client_ctl.value = (ctl->value) ? - (0x90 + ctl->value) << 8 : 0; + wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ? + (0x90 + ctrl->val) << 8 : 0); break; case V4L2_CID_AUDIO_BALANCE: - client_ctl.value = ctl->value << 9; + wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9); break; default: - client_ctl.id = 0; break; } - if (client_ctl.id) - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); } - mask=c->mask; - switch (ctl->id) { + mask = cc->mask; + switch (ctrl->id) { case V4L2_CID_AUDIO_BALANCE: - value = (ctl->value < 0x40) ? (0x7f - ctl->value) : (ctl->value - 0x40); + value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40); break; case V4L2_CID_AUDIO_VOLUME: - value = 0x3f - (ctl->value & 0x3f); + value = 0x3f - (ctrl->val & 0x3f); break; case V4L2_CID_SATURATION: /* special v_sat handling */ - value = ((ctl->value - c->off) << c->shift) & c->mask; + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; if (core->tvnorm & V4L2_STD_SECAM) { /* For SECAM, both U and V sat should be equal */ @@ -1078,44 +957,29 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) break; case V4L2_CID_SHARPNESS: /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ - value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7)); + value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7)); /* needs to be set for both fields */ cx_andor(MO_FILTER_EVEN, mask, value); break; case V4L2_CID_CHROMA_AGC: /* Do not allow chroma AGC to be enabled for SECAM */ - value = ((ctl->value - c->off) << c->shift) & c->mask; - if (core->tvnorm & V4L2_STD_SECAM && value) + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; + if ((core->tvnorm & V4L2_STD_SECAM) && value) return -EINVAL; break; default: - value = ((ctl->value - c->off) << c->shift) & c->mask; + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; break; } dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctl->id, c->v.name, ctl->value, c->reg, value, - mask, c->sreg ? " [shadowed]" : ""); - if (c->sreg) { - cx_sandor(c->sreg, c->reg, mask, value); - } else { - cx_andor(c->reg, mask, value); - } + ctrl->id, ctrl->name, ctrl->val, cc->reg, value, + mask, cc->sreg ? " [shadowed]" : ""); + if (cc->sreg) + cx_sandor(cc->sreg, cc->reg, mask, value); + else + cx_andor(cc->reg, mask, value); return 0; } -EXPORT_SYMBOL(cx88_set_control); - -static void init_controls(struct cx88_core *core) -{ - struct v4l2_control ctrl; - int i; - - for (i = 0; i < CX8800_CTLS; i++) { - ctrl.id=cx8800_ctls[i].v.id; - ctrl.value=cx8800_ctls[i].v.default_value; - - cx88_set_control(core, &ctrl); - } -} /* ------------------------------------------------------------------ */ /* VIDEO IOCTLS */ @@ -1382,35 +1246,6 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i) return 0; } - - -static int vidioc_queryctrl (struct file *file, void *priv, - struct v4l2_queryctrl *qctrl) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); - if (unlikely(qctrl->id == 0)) - return -EINVAL; - return cx8800_ctrl_query(core, qctrl); -} - -static int vidioc_g_ctrl (struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - return - cx88_get_control(core,ctl); -} - -static int vidioc_s_ctrl (struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - return - cx88_set_control(core,ctl); -} - static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *t) { @@ -1563,29 +1398,6 @@ static int radio_s_tuner (struct file *file, void *priv, return 0; } -static int radio_queryctrl (struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - int i; - - if (c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) - return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE || - c->id == V4L2_CID_AUDIO_VOLUME || - c->id == V4L2_CID_AUDIO_BALANCE) { - for (i = 0; i < CX8800_CTLS; i++) { - if (cx8800_ctls[i].v.id == c->id) - break; - } - if (i == CX8800_CTLS) - return -EINVAL; - *c = cx8800_ctls[i].v; - } else - *c = no_ctl; - return 0; -} - /* ----------------------------------------------------------- */ static void cx8800_vid_timeout(unsigned long data) @@ -1739,9 +1551,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_tuner = vidioc_g_tuner, @@ -1776,9 +1585,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = radio_g_tuner, .vidioc_s_tuner = radio_s_tuner, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1793,6 +1599,10 @@ static const struct video_device cx8800_radio_template = { .ioctl_ops = &radio_ioctl_ops, }; +static const struct v4l2_ctrl_ops cx8800_ctrl_ops = { + .s_ctrl = cx8800_s_ctrl, +}; + /* ----------------------------------------------------------- */ static void cx8800_unregister_video(struct cx8800_dev *dev) @@ -1825,8 +1635,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, { struct cx8800_dev *dev; struct cx88_core *core; - int err; + int i; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) @@ -1897,6 +1707,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } cx_set(MO_PCI_INTMSK, core->pci_irqmask); + for (i = 0; i < CX8800_CTLS; i++) { + const struct cx88_ctrl *cc = &cx8800_ctls[i]; + struct v4l2_ctrl *vc; + + vc = v4l2_ctrl_new_std(&core->hdl, &cx8800_ctrl_ops, + cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); + if (vc == NULL) { + err = core->hdl.error; + goto fail_core; + } + vc->priv = (void *)cc; + } + /* load and configure helper modules */ if (core->board.audio_chip == V4L2_IDENT_WM8775) { @@ -1914,8 +1737,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap, &wm8775_info, NULL); - if (sd != NULL) + if (sd != NULL) { + core->sd_wm8775 = sd; sd->grp_id = WM8775_GID; + } } if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { @@ -1946,7 +1771,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* initial device configuration */ mutex_lock(&core->lock); cx88_set_tvnorm(core, core->tvnorm); - init_controls(core); + v4l2_ctrl_handler_setup(&core->hdl); cx88_video_mux(core, 0); /* register v4l devices */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 8e9820cf454e..f12a77b4532d 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -115,15 +115,6 @@ struct cx8800_fmt { u32 cxformat; }; -struct cx88_ctrl { - struct v4l2_queryctrl v; - u32 off; - u32 reg; - u32 sreg; - u32 mask; - u32 shift; -}; - /* ----------------------------------------------------------- */ /* SRAM memory management data (see cx88-core.c) */ @@ -359,6 +350,8 @@ struct cx88_core { /* config info -- analog */ struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler hdl; + struct v4l2_subdev *sd_wm8775; struct i2c_client *i2c_rtc; unsigned int boardnr; struct cx88_board board; @@ -409,8 +402,6 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx88_core, v4l2_dev); } -#define WM8775_GID (1 << 0) - #define call_hw(core, grpid, o, f, args...) \ do { \ if (!core->i2c_rc) { \ @@ -424,6 +415,36 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) #define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) +#define WM8775_GID (1 << 0) + +#define wm8775_s_ctrl(core, id, val) \ + do { \ + struct v4l2_ctrl *ctrl_ = \ + v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ + if (ctrl_ && !core->i2c_rc) { \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 1); \ + v4l2_ctrl_s_ctrl(ctrl_, val); \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 0); \ + } \ + } while (0) + +#define wm8775_g_ctrl(core, id) \ + ({ \ + struct v4l2_ctrl *ctrl_ = \ + v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ + s32 val = 0; \ + if (ctrl_ && !core->i2c_rc) { \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 1); \ + val = v4l2_ctrl_g_ctrl(ctrl_); \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 0); \ + } \ + val; \ + }) + struct cx8800_dev; struct cx8802_dev; @@ -722,13 +743,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev); /* ----------------------------------------------------------- */ /* cx88-video.c*/ -extern const u32 cx88_user_ctrls[]; -extern int cx8800_ctrl_query(struct cx88_core *core, - struct v4l2_queryctrl *qctrl); int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); -int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); -int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_video_mux(struct cx88_core *core, unsigned int input); void cx88_querycap(struct file *file, struct cx88_core *core, struct v4l2_capability *cap); -- GitLab From 8c7cb12ac1cc4ecc318765e0e2dcd853fa4a4d62 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 May 2012 09:07:45 -0300 Subject: [PATCH 1990/5711] [media] cx88: each device node gets the right controls radio only sees audio controls, video sees video and audio and vbi sees none. Also disable the chroma_agc control if secam is selected. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 15 ++- drivers/media/video/cx88/cx88-core.c | 7 +- drivers/media/video/cx88/cx88-video.c | 139 ++++++++++++++++---------- drivers/media/video/cx88/cx88.h | 4 +- 4 files changed, 108 insertions(+), 57 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cd8c3bf698ea..4e9d4f722960 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3693,14 +3693,22 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) return NULL; } - if (v4l2_ctrl_handler_init(&core->hdl, 13)) { + if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) { + v4l2_device_unregister(&core->v4l2_dev); + kfree(core); + return NULL; + } + + if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) { + v4l2_ctrl_handler_free(&core->video_hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; } if (0 != cx88_get_resources(core, pci)) { - v4l2_ctrl_handler_free(&core->hdl); + v4l2_ctrl_handler_free(&core->video_hdl); + v4l2_ctrl_handler_free(&core->audio_hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; @@ -3715,7 +3723,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) if (core->lmmio == NULL) { release_mem_region(pci_resource_start(pci, 0), pci_resource_len(pci, 0)); - v4l2_ctrl_handler_free(&core->hdl); + v4l2_ctrl_handler_free(&core->video_hdl); + v4l2_ctrl_handler_free(&core->audio_hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index a6480aaa8a0b..8bd925db412b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1012,6 +1012,9 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) // tell i2c chips call_all(core, core, s_std, norm); + /* The chroma_agc control should be inaccessible if the video format is SECAM */ + v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM); + // done return 0; } @@ -1030,7 +1033,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, return NULL; *vfd = *template_; vfd->v4l2_dev = &core->v4l2_dev; - vfd->ctrl_handler = &core->hdl; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); @@ -1086,7 +1088,8 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) iounmap(core->lmmio); cx88_devcount--; mutex_unlock(&devlist); - v4l2_ctrl_handler_free(&core->hdl); + v4l2_ctrl_handler_free(&core->video_hdl); + v4l2_ctrl_handler_free(&core->audio_hdl); v4l2_device_unregister(&core->v4l2_dev); kfree(core); } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 2f3d4df33f7e..104a85c265f3 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -155,12 +155,6 @@ static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc) /* ------------------------------------------------------------------- */ -static const struct v4l2_queryctrl no_ctl = { - .name = "42", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; - - struct cx88_ctrl { /* control information */ u32 id; @@ -177,7 +171,7 @@ struct cx88_ctrl { u32 shift; }; -static const struct cx88_ctrl cx8800_ctls[] = { +static const struct cx88_ctrl cx8800_vid_ctls[] = { /* --- video --- */ { .id = V4L2_CID_BRIGHTNESS, @@ -260,7 +254,11 @@ static const struct cx88_ctrl cx8800_ctls[] = { .reg = MO_HTOTAL, .mask = 3 << 11, .shift = 11, - }, { + } +}; + +static const struct cx88_ctrl cx8800_aud_ctls[] = { + { /* --- audio --- */ .id = V4L2_CID_AUDIO_MUTE, .minimum = 0, @@ -293,14 +291,10 @@ static const struct cx88_ctrl cx8800_ctls[] = { } }; -enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; - - -int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) -{ - return 0; -} -EXPORT_SYMBOL(cx8800_ctrl_query); +enum { + CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls), + CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), +}; /* ------------------------------------------------------------------- */ /* resource management */ @@ -908,10 +902,56 @@ video_mmap(struct file *file, struct vm_area_struct * vma) /* ------------------------------------------------------------------ */ /* VIDEO CTRL IOCTLS */ -static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl) +static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl) +{ + struct cx88_core *core = + container_of(ctrl->handler, struct cx88_core, video_hdl); + const struct cx88_ctrl *cc = ctrl->priv; + u32 value, mask; + + mask = cc->mask; + switch (ctrl->id) { + case V4L2_CID_SATURATION: + /* special v_sat handling */ + + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; + + if (core->tvnorm & V4L2_STD_SECAM) { + /* For SECAM, both U and V sat should be equal */ + value = value << 8 | value; + } else { + /* Keeps U Saturation proportional to V Sat */ + value = (value * 0x5a) / 0x7f << 8 | value; + } + mask = 0xffff; + break; + case V4L2_CID_SHARPNESS: + /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ + value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7)); + /* needs to be set for both fields */ + cx_andor(MO_FILTER_EVEN, mask, value); + break; + case V4L2_CID_CHROMA_AGC: + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; + break; + default: + value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; + break; + } + dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", + ctrl->id, ctrl->name, ctrl->val, cc->reg, value, + mask, cc->sreg ? " [shadowed]" : ""); + if (cc->sreg) + cx_sandor(cc->sreg, cc->reg, mask, value); + else + cx_andor(cc->reg, mask, value); + return 0; +} + +static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl) { struct cx88_core *core = - container_of(ctrl->handler, struct cx88_core, hdl); + container_of(ctrl->handler, struct cx88_core, audio_hdl); const struct cx88_ctrl *cc = ctrl->priv; u32 value,mask; @@ -941,32 +981,6 @@ static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_AUDIO_VOLUME: value = 0x3f - (ctrl->val & 0x3f); break; - case V4L2_CID_SATURATION: - /* special v_sat handling */ - - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - - if (core->tvnorm & V4L2_STD_SECAM) { - /* For SECAM, both U and V sat should be equal */ - value=value<<8|value; - } else { - /* Keeps U Saturation proportional to V Sat */ - value=(value*0x5a)/0x7f<<8|value; - } - mask=0xffff; - break; - case V4L2_CID_SHARPNESS: - /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ - value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7)); - /* needs to be set for both fields */ - cx_andor(MO_FILTER_EVEN, mask, value); - break; - case V4L2_CID_CHROMA_AGC: - /* Do not allow chroma AGC to be enabled for SECAM */ - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - if ((core->tvnorm & V4L2_STD_SECAM) && value) - return -EINVAL; - break; default: value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; break; @@ -1599,8 +1613,12 @@ static const struct video_device cx8800_radio_template = { .ioctl_ops = &radio_ioctl_ops, }; -static const struct v4l2_ctrl_ops cx8800_ctrl_ops = { - .s_ctrl = cx8800_s_ctrl, +static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = { + .s_ctrl = cx8800_s_vid_ctrl, +}; + +static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = { + .s_ctrl = cx8800_s_aud_ctrl, }; /* ----------------------------------------------------------- */ @@ -1707,18 +1725,34 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } cx_set(MO_PCI_INTMSK, core->pci_irqmask); - for (i = 0; i < CX8800_CTLS; i++) { - const struct cx88_ctrl *cc = &cx8800_ctls[i]; + for (i = 0; i < CX8800_AUD_CTLS; i++) { + const struct cx88_ctrl *cc = &cx8800_aud_ctls[i]; + struct v4l2_ctrl *vc; + + vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops, + cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); + if (vc == NULL) { + err = core->audio_hdl.error; + goto fail_core; + } + vc->priv = (void *)cc; + } + + for (i = 0; i < CX8800_VID_CTLS; i++) { + const struct cx88_ctrl *cc = &cx8800_vid_ctls[i]; struct v4l2_ctrl *vc; - vc = v4l2_ctrl_new_std(&core->hdl, &cx8800_ctrl_ops, + vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops, cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); if (vc == NULL) { - err = core->hdl.error; + err = core->video_hdl.error; goto fail_core; } vc->priv = (void *)cc; + if (vc->id == V4L2_CID_CHROMA_AGC) + core->chroma_agc = vc; } + v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl); /* load and configure helper modules */ @@ -1771,13 +1805,15 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* initial device configuration */ mutex_lock(&core->lock); cx88_set_tvnorm(core, core->tvnorm); - v4l2_ctrl_handler_setup(&core->hdl); + v4l2_ctrl_handler_setup(&core->video_hdl); + v4l2_ctrl_handler_setup(&core->audio_hdl); cx88_video_mux(core, 0); /* register v4l devices */ dev->video_dev = cx88_vdev_init(core,dev->pci, &cx8800_video_template,"video"); video_set_drvdata(dev->video_dev, dev); + dev->video_dev->ctrl_handler = &core->video_hdl; err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[core->nr]); if (err < 0) { @@ -1804,6 +1840,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->radio_dev = cx88_vdev_init(core,dev->pci, &cx8800_radio_template,"radio"); video_set_drvdata(dev->radio_dev, dev); + dev->radio_dev->ctrl_handler = &core->audio_hdl; err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, radio_nr[core->nr]); if (err < 0) { diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index f12a77b4532d..280bf6ab7b75 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -350,7 +350,9 @@ struct cx88_core { /* config info -- analog */ struct v4l2_device v4l2_dev; - struct v4l2_ctrl_handler hdl; + struct v4l2_ctrl_handler video_hdl; + struct v4l2_ctrl *chroma_agc; + struct v4l2_ctrl_handler audio_hdl; struct v4l2_subdev *sd_wm8775; struct i2c_client *i2c_rtc; unsigned int boardnr; -- GitLab From 7bb34c8e42fe2e7cfa0a46db52dc2a79f2ba723a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 08:47:11 -0300 Subject: [PATCH 1991/5711] [media] cx88: convert cx88-blackbird to the control framework Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 106 ++++++++-------------- drivers/media/video/cx88/cx88.h | 2 +- 2 files changed, 39 insertions(+), 69 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index c9bbe9fc9c7e..d8c25c5bb323 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -523,11 +523,10 @@ static void blackbird_codec_settings(struct cx8802_dev *dev) blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, dev->height, dev->width); - dev->params.width = dev->width; - dev->params.height = dev->height; - dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0; - - cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params); + dev->cxhdl.width = dev->width; + dev->cxhdl.height = dev->height; + cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); + cx2341x_handler_setup(&dev->cxhdl); } static int blackbird_initialize_codec(struct cx8802_dev *dev) @@ -618,6 +617,8 @@ static int blackbird_start_codec(struct file *file, void *priv) /* initialize the video input */ blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); + cx2341x_handler_set_busy(&dev->cxhdl, 1); + /* start capturing to the host interface */ blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, @@ -636,6 +637,8 @@ static int blackbird_stop_codec(struct cx8802_dev *dev) BLACKBIRD_RAW_BITS_NONE ); + cx2341x_handler_set_busy(&dev->cxhdl, 0); + dev->mpeg_active = 0; return 0; } @@ -721,7 +724,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->mpegq.field; - dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", + dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", dev->width, dev->height, fh->mpegq.field ); return 0; } @@ -736,7 +739,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.colorspace = 0; - dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", + dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->width, dev->height, fh->mpegq.field ); return 0; } @@ -758,7 +761,7 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, f->fmt.pix.height, f->fmt.pix.width); - dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", + dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); return 0; } @@ -791,60 +794,21 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct cx8802_fh *fh = priv; + struct cx8802_dev *dev = fh->dev; + + if (!dev->mpeg_active) + blackbird_start_codec(file, fh); return videobuf_streamon(&fh->mpegq); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { struct cx8802_fh *fh = priv; - return videobuf_streamoff(&fh->mpegq); -} - -static int vidioc_g_ext_ctrls (struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS); -} - -static int vidioc_s_ext_ctrls (struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct cx2341x_mpeg_params p; - int err; - - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; + struct cx8802_dev *dev = fh->dev; if (dev->mpeg_active) blackbird_stop_codec(dev); - - p = dev->params; - err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); - if (!err) { - err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); - dev->params = p; - } - return err; -} - -static int vidioc_try_ext_ctrls (struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct cx2341x_mpeg_params p; - int err; - - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - p = dev->params; - err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); - - return err; + return videobuf_streamoff(&fh->mpegq); } static int vidioc_s_frequency (struct file *file, void *priv, @@ -871,12 +835,8 @@ static int vidioc_log_status (struct file *file, void *priv) char name[32 + 2]; snprintf(name, sizeof(name), "%s/2", core->name); - printk("%s/2: ============ START LOG STATUS ============\n", - core->name); call_all(core, core, log_status); - cx2341x_log_status(&dev->params, name); - printk("%s/2: ============= END LOG STATUS =============\n", - core->name); + v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name); return 0; } @@ -1082,10 +1042,11 @@ mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static unsigned int mpeg_poll(struct file *file, struct poll_table_struct *wait) { + unsigned long req_events = poll_requested_events(wait); struct cx8802_fh *fh = file->private_data; struct cx8802_dev *dev = fh->dev; - if (!dev->mpeg_active) + if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM))) blackbird_start_codec(file, fh); return videobuf_poll_stream(file, &fh->mpegq, wait); @@ -1122,9 +1083,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_log_status = vidioc_log_status, .vidioc_enum_input = vidioc_enum_input, @@ -1209,6 +1167,7 @@ static int blackbird_register_video(struct cx8802_dev *dev) dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, &cx8802_mpeg_template,"mpeg"); + dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; video_set_drvdata(dev->mpeg_dev, dev); err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); if (err < 0) { @@ -1240,18 +1199,23 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) goto fail_core; - dev->width = 720; - dev->height = 576; - cx2341x_fill_defaults(&dev->params); - dev->params.port = CX2341X_PORT_STREAMING; - cx8802_mpeg_template.current_norm = core->tvnorm; + dev->width = 720; if (core->tvnorm & V4L2_STD_525_60) { dev->height = 480; } else { dev->height = 576; } + dev->cxhdl.port = CX2341X_PORT_STREAMING; + dev->cxhdl.width = dev->width; + dev->cxhdl.height = dev->height; + dev->cxhdl.func = blackbird_mbox_func; + dev->cxhdl.priv = dev; + err = cx2341x_handler_init(&dev->cxhdl, 36); + if (err) + goto fail_core; + v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl); /* blackbird stuff */ printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", @@ -1259,12 +1223,14 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) host_setup(dev->core); blackbird_initialize_codec(dev); - blackbird_register_video(dev); /* initial device configuration: needed ? */ // init_controls(core); cx88_set_tvnorm(core,core->tvnorm); cx88_video_mux(core,0); + cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576); + cx2341x_handler_setup(&dev->cxhdl); + blackbird_register_video(dev); return 0; @@ -1274,8 +1240,12 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) static int cx8802_blackbird_remove(struct cx8802_driver *drv) { + struct cx88_core *core = drv->core; + struct cx8802_dev *dev = core->dvbdev; + /* blackbird */ blackbird_unregister_video(drv->core->dvbdev); + v4l2_ctrl_handler_free(&dev->cxhdl.hdl); return 0; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 280bf6ab7b75..e79cb878379a 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -575,7 +575,7 @@ struct cx8802_dev { unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ /* mpeg params */ - struct cx2341x_mpeg_params params; + struct cx2341x_handler cxhdl; #endif #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) -- GitLab From edbd138ed0cae5abe469b61e368d2629815d4c37 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 May 2012 10:33:25 -0300 Subject: [PATCH 1992/5711] [media] cx88: remove radio and type from cx8800_fh This information is available elsewhere already. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 89 +++++++++++---------------- drivers/media/video/cx88/cx88.h | 2 - 2 files changed, 37 insertions(+), 54 deletions(-) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 104a85c265f3..e5e551090d1c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -683,12 +683,15 @@ static const struct videobuf_queue_ops cx8800_video_qops = { /* ------------------------------------------------------------------ */ -static struct videobuf_queue* get_queue(struct cx8800_fh *fh) +static struct videobuf_queue *get_queue(struct file *file) { - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + struct video_device *vdev = video_devdata(file); + struct cx8800_fh *fh = file->private_data; + + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: return &fh->vidq; - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: return &fh->vbiq; default: BUG(); @@ -696,12 +699,14 @@ static struct videobuf_queue* get_queue(struct cx8800_fh *fh) } } -static int get_ressource(struct cx8800_fh *fh) +static int get_resource(struct file *file) { - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + struct video_device *vdev = video_devdata(file); + + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: return RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: return RESOURCE_VBI; default: BUG(); @@ -740,8 +745,6 @@ static int video_open(struct file *file) file->private_data = fh; fh->dev = dev; - fh->radio = radio; - fh->type = type; fh->width = 320; fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); @@ -761,7 +764,7 @@ static int video_open(struct file *file) sizeof(struct cx88_buffer), fh, NULL); - if (fh->radio) { + if (vdev->vfl_type == VFL_TYPE_RADIO) { dprintk(1,"video_open: setting radio device\n"); cx_write(MO_GP3_IO, core->board.radio.gpio3); cx_write(MO_GP0_IO, core->board.radio.gpio0); @@ -794,15 +797,16 @@ static int video_open(struct file *file) static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { + struct video_device *vdev = video_devdata(file); struct cx8800_fh *fh = file->private_data; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: if (res_locked(fh->dev,RESOURCE_VIDEO)) return -EBUSY; return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: if (!res_get(fh->dev,fh,RESOURCE_VBI)) return -EBUSY; return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, @@ -816,11 +820,12 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) { + struct video_device *vdev = video_devdata(file); struct cx8800_fh *fh = file->private_data; struct cx88_buffer *buf; unsigned int rc = POLLERR; - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + if (vdev->vfl_type == VFL_TYPE_VBI) { if (!res_get(fh->dev,fh,RESOURCE_VBI)) return POLLERR; return videobuf_poll_stream(file, &fh->vbiq, wait); @@ -894,9 +899,7 @@ static int video_release(struct file *file) static int video_mmap(struct file *file, struct vm_area_struct * vma) { - struct cx8800_fh *fh = file->private_data; - - return videobuf_mmap_mapper(get_queue(fh), vma); + return videobuf_mmap_mapper(get_queue(file), vma); } /* ------------------------------------------------------------------ */ @@ -1126,63 +1129,53 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct cx8800_fh *fh = priv; - return (videobuf_reqbufs(get_queue(fh), p)); + return videobuf_reqbufs(get_queue(file), p); } static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx8800_fh *fh = priv; - return (videobuf_querybuf(get_queue(fh), p)); + return videobuf_querybuf(get_queue(file), p); } static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx8800_fh *fh = priv; - return (videobuf_qbuf(get_queue(fh), p)); + return videobuf_qbuf(get_queue(file), p); } static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx8800_fh *fh = priv; - return (videobuf_dqbuf(get_queue(fh), p, - file->f_flags & O_NONBLOCK)); + return videobuf_dqbuf(get_queue(file), p, + file->f_flags & O_NONBLOCK); } static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { + struct video_device *vdev = video_devdata(file); struct cx8800_fh *fh = priv; struct cx8800_dev *dev = fh->dev; - /* We should remember that this driver also supports teletext, */ - /* so we have to test if the v4l2_buf_type is VBI capture data. */ - if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))) + if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; - if (unlikely(i != fh->type)) - return -EINVAL; - - if (unlikely(!res_get(dev,fh,get_ressource(fh)))) + if (unlikely(!res_get(dev, fh, get_resource(file)))) return -EBUSY; - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(file)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { + struct video_device *vdev = video_devdata(file); struct cx8800_fh *fh = priv; struct cx8800_dev *dev = fh->dev; int err, res; - if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - if (i != fh->type) + if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; - res = get_ressource(fh); - err = videobuf_streamoff(get_queue(fh)); + res = get_resource(file); + err = videobuf_streamoff(get_queue(file)); if (err < 0) return err; res_free(dev,fh,res); @@ -1305,8 +1298,6 @@ static int vidioc_g_frequency (struct file *file, void *priv, if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; - /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; call_all(core, tuner, g_frequency, f); @@ -1343,13 +1334,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct cx8800_fh *fh = priv; struct cx88_core *core = fh->dev->core; - if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) - return -EINVAL; - - return - cx88_set_freq (core,f); + return cx88_set_freq(core, f); } #ifdef CONFIG_VIDEO_ADV_DEBUG diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e79cb878379a..1426993079b0 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -455,8 +455,6 @@ struct cx8802_dev; struct cx8800_fh { struct cx8800_dev *dev; - enum v4l2_buf_type type; - int radio; unsigned int resources; /* video overlay */ -- GitLab From c5a861449fcd4f50d30376986ebdb0692f0bf1f1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 May 2012 10:45:18 -0300 Subject: [PATCH 1993/5711] [media] cx88: move fmt, width and height to cx8800_dev These are global properties and do not belong in the filehandle struct. Note: the overlay related fields were just removed: they weren't used at all. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 49 +++++++++++++++------------ drivers/media/video/cx88/cx88.h | 9 ++--- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index e5e551090d1c..bd1f52f6e264 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -519,8 +519,9 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { struct cx8800_fh *fh = q->priv_data; + struct cx8800_dev *dev = fh->dev; - *size = fh->fmt->depth*fh->width*fh->height >> 3; + *size = dev->fmt->depth * dev->width * dev->height >> 3; if (0 == *count) *count = 32; if (*size * *count > vid_limit * 1024 * 1024) @@ -539,21 +540,21 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); int rc, init_buffer = 0; - BUG_ON(NULL == fh->fmt); - if (fh->width < 48 || fh->width > norm_maxw(core->tvnorm) || - fh->height < 32 || fh->height > norm_maxh(core->tvnorm)) + BUG_ON(NULL == dev->fmt); + if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) || + dev->height < 32 || dev->height > norm_maxh(core->tvnorm)) return -EINVAL; - buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || + if (buf->fmt != dev->fmt || + buf->vb.width != dev->width || + buf->vb.height != dev->height || buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; + buf->fmt = dev->fmt; + buf->vb.width = dev->width; + buf->vb.height = dev->height; buf->vb.field = field; init_buffer = 1; } @@ -603,7 +604,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, } dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", buf, buf->vb.i, - fh->width, fh->height, fh->fmt->depth, fh->fmt->name, + dev->width, dev->height, dev->fmt->depth, dev->fmt->name, (unsigned long)buf->risc.dma); buf->vb.state = VIDEOBUF_PREPARED; @@ -745,9 +746,6 @@ static int video_open(struct file *file) file->private_data = fh; fh->dev = dev; - fh->width = 320; - fh->height = 240; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); mutex_lock(&core->lock); @@ -1005,15 +1003,17 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cx8800_fh *fh = priv; + struct cx8800_dev *dev = fh->dev; - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.pixelformat = dev->fmt->fourcc; f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; + (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } @@ -1065,13 +1065,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cx8800_fh *fh = priv; + struct cx8800_dev *dev = fh->dev; int err = vidioc_try_fmt_vid_cap (file,priv,f); if (0 != err) return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; + dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + dev->width = f->fmt.pix.width; + dev->height = f->fmt.pix.height; fh->vidq.field = f->fmt.pix.field; return 0; } @@ -1787,6 +1788,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* Sets device info at pci_dev */ pci_set_drvdata(pci_dev, dev); + dev->width = 320; + dev->height = 240; + dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + /* initial device configuration */ mutex_lock(&core->lock); cx88_set_tvnorm(core, core->tvnorm); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 1426993079b0..94af48e91b52 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -457,14 +457,7 @@ struct cx8800_fh { struct cx8800_dev *dev; unsigned int resources; - /* video overlay */ - struct v4l2_window win; - struct v4l2_clip *clips; - unsigned int nclips; - /* video capture */ - const struct cx8800_fmt *fmt; - unsigned int width,height; struct videobuf_queue vidq; /* vbi capture */ @@ -489,6 +482,8 @@ struct cx8800_dev { struct pci_dev *pci; unsigned char pci_rev,pci_lat; + const struct cx8800_fmt *fmt; + unsigned int width, height; /* capture queues */ struct cx88_dmaqueue vidq; -- GitLab From 88bb42fb5a556ffc918279cad3f86d83c353f055 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 May 2012 10:57:59 -0300 Subject: [PATCH 1994/5711] [media] cx88: add priority support Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 ++++ drivers/media/video/cx88/cx88-core.c | 1 + drivers/media/video/cx88/cx88-video.c | 4 ++++ drivers/media/video/cx88/cx88.h | 3 +++ 4 files changed, 12 insertions(+) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index d8c25c5bb323..95cdfed80f4e 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -974,6 +974,7 @@ static int mpeg_open(struct file *file) mutex_unlock(&dev->core->lock); return -ENOMEM; } + v4l2_fh_init(&fh->fh, vdev); file->private_data = fh; fh->dev = dev; @@ -990,6 +991,7 @@ static int mpeg_open(struct file *file) dev->core->mpeg_users++; mutex_unlock(&dev->core->lock); + v4l2_fh_add(&fh->fh); return 0; } @@ -1010,6 +1012,8 @@ static int mpeg_release(struct file *file) videobuf_mmap_free(&fh->mpegq); + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); file->private_data = NULL; kfree(fh); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8bd925db412b..e81c735f012a 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1036,6 +1036,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); + set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); return vfd; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index bd1f52f6e264..673f88be325f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -744,6 +744,7 @@ static int video_open(struct file *file) if (unlikely(!fh)) return -ENOMEM; + v4l2_fh_init(&fh->fh, vdev); file->private_data = fh; fh->dev = dev; @@ -788,6 +789,7 @@ static int video_open(struct file *file) core->users++; mutex_unlock(&core->lock); + v4l2_fh_add(&fh->fh); return 0; } @@ -883,6 +885,8 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vbiq); mutex_lock(&dev->core->lock); + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); file->private_data = NULL; kfree(fh); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 94af48e91b52..0cae0fd9e164 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -454,6 +455,7 @@ struct cx8802_dev; /* function 0: video stuff */ struct cx8800_fh { + struct v4l2_fh fh; struct cx8800_dev *dev; unsigned int resources; @@ -504,6 +506,7 @@ struct cx8800_dev { /* function 2: mpeg stuff */ struct cx8802_fh { + struct v4l2_fh fh; struct cx8802_dev *dev; struct videobuf_queue mpegq; }; -- GitLab From 1a3c60a072dda4e845c40d47384794510a74eaf9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 May 2012 11:25:03 -0300 Subject: [PATCH 1995/5711] [media] cx88: support control events Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 5 ++++- drivers/media/video/cx88/cx88-video.c | 16 ++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 95cdfed80f4e..0f1cc8dba957 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "cx88.h" @@ -1053,7 +1054,7 @@ mpeg_poll(struct file *file, struct poll_table_struct *wait) if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM))) blackbird_start_codec(file, fh); - return videobuf_poll_stream(file, &fh->mpegq, wait); + return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait); } static int @@ -1096,6 +1097,8 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_s_std = vidioc_s_std, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct video_device cx8802_mpeg_template = { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 673f88be325f..930d43b0d89e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -40,6 +40,7 @@ #include "cx88.h" #include #include +#include #include MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); @@ -823,12 +824,12 @@ video_poll(struct file *file, struct poll_table_struct *wait) struct video_device *vdev = video_devdata(file); struct cx8800_fh *fh = file->private_data; struct cx88_buffer *buf; - unsigned int rc = POLLERR; + unsigned int rc = v4l2_ctrl_poll(file, wait); if (vdev->vfl_type == VFL_TYPE_VBI) { if (!res_get(fh->dev,fh,RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(file, &fh->vbiq, wait); + return rc | POLLERR; + return rc | videobuf_poll_stream(file, &fh->vbiq, wait); } mutex_lock(&fh->vidq.vb_lock); @@ -846,9 +847,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - rc = POLLIN|POLLRDNORM; - else - rc = 0; + rc |= POLLIN|POLLRDNORM; done: mutex_unlock(&fh->vidq.vb_lock); return rc; @@ -1561,6 +1560,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1581,6 +1582,7 @@ static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, + .poll = v4l2_ctrl_poll, .release = video_release, .unlocked_ioctl = video_ioctl2, }; @@ -1591,6 +1593,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_tuner = radio_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, -- GitLab From f33e9868a46d943624fd34a4fba28b7f076e6d33 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 25 May 2012 12:04:10 -0300 Subject: [PATCH 1996/5711] [media] cx88: fix a number of v4l2-compliance violations - missing COMPRESSED flag for MPEG formats - set colorspace - set sizeimage - add tuner index checks - setup the frequency ranges correctly - add missing g_chip_ident ioctl - fix audmode handling - don't handle vbi formats on a video node and vice versa. cx88 now passes the v4l2-compliance tests. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 24 +++++--- drivers/media/video/cx88/cx88-video.c | 71 ++++++++++++++++++----- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 0f1cc8dba957..38efc1fdb75f 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -709,6 +709,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, strlcpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; + f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; } @@ -720,8 +721,8 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ - f->fmt.pix.colorspace = 0; + f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->mpegq.field; @@ -738,8 +739,8 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; - f->fmt.pix.colorspace = 0; + f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->width, dev->height, fh->mpegq.field ); return 0; @@ -754,8 +755,8 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; - f->fmt.pix.colorspace = 0; + f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; fh->mpegq.field = f->fmt.pix.field; @@ -819,6 +820,10 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; + if (unlikely(UNSET == core->board.tuner_type)) + return -EINVAL; + if (unlikely(f->tuner != 0)) + return -EINVAL; if (dev->mpeg_active) blackbird_stop_codec(dev); @@ -856,8 +861,9 @@ static int vidioc_g_frequency (struct file *file, void *priv, if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; + if (unlikely(f->tuner != 0)) + return -EINVAL; - f->type = V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; call_all(core, tuner, g_frequency, f); @@ -878,6 +884,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i) if (i >= 4) return -EINVAL; + if (0 == INPUT(i).type) + return -EINVAL; mutex_lock(&core->lock); cx88_newstation(core); @@ -898,9 +906,9 @@ static int vidioc_g_tuner (struct file *file, void *priv, return -EINVAL; strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; + call_all(core, tuner, g_tuner, t); cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 930d43b0d89e..3dee42141979 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -831,7 +831,6 @@ video_poll(struct file *file, struct poll_table_struct *wait) return rc | POLLERR; return rc | videobuf_poll_stream(file, &fh->vbiq, wait); } - mutex_lock(&fh->vidq.vb_lock); if (res_check(fh,RESOURCE_VIDEO)) { /* streaming capture */ @@ -1222,8 +1221,8 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) if ((CX88_VMUX_TELEVISION == INPUT(n).type) || (CX88_VMUX_CABLE == INPUT(n).type)) { i->type = V4L2_INPUT_TYPE_TUNER; - i->std = CX88_NORMS; } + i->std = CX88_NORMS; return 0; } EXPORT_SYMBOL(cx88_enum_input); @@ -1249,6 +1248,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i) if (i >= 4) return -EINVAL; + if (0 == INPUT(i).type) + return -EINVAL; mutex_lock(&core->lock); cx88_newstation(core); @@ -1269,9 +1270,9 @@ static int vidioc_g_tuner (struct file *file, void *priv, return -EINVAL; strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; + call_all(core, tuner, g_tuner, t); cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); @@ -1301,6 +1302,8 @@ static int vidioc_g_frequency (struct file *file, void *priv, if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; + if (f->tuner) + return -EINVAL; f->frequency = core->freq; @@ -1318,9 +1321,10 @@ int cx88_set_freq (struct cx88_core *core, return -EINVAL; mutex_lock(&core->lock); - core->freq = f->frequency; cx88_newstation(core); call_all(core, tuner, s_frequency, f); + call_all(core, tuner, g_frequency, f); + core->freq = f->frequency; /* When changing channels it is required to reset TVAUDIO */ msleep (10); @@ -1341,6 +1345,16 @@ static int vidioc_s_frequency (struct file *file, void *priv, return cx88_set_freq(core, f); } +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + if (!v4l2_chip_match_host(&chip->match)) + return -EINVAL; + chip->revision = 0; + chip->ident = V4L2_IDENT_UNKNOWN; + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *fh, struct v4l2_dbg_register *reg) @@ -1380,7 +1394,6 @@ static int radio_g_tuner (struct file *file, void *priv, return -EINVAL; strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; call_all(core, tuner, g_tuner, t); return 0; @@ -1395,6 +1408,8 @@ static int radio_s_tuner (struct file *file, void *priv, if (0 != t->index) return -EINVAL; + if (t->audmode > V4L2_TUNER_MODE_STEREO) + t->audmode = V4L2_TUNER_MODE_STEREO; call_all(core, tuner, s_tuner, t); @@ -1543,9 +1558,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, - .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, - .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, .vidioc_reqbufs = vidioc_reqbufs, .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, @@ -1562,14 +1574,13 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif }; -static struct video_device cx8800_vbi_template; - static const struct video_device cx8800_video_template = { .name = "cx8800-video", .fops = &video_fops, @@ -1578,6 +1589,40 @@ static const struct video_device cx8800_video_template = { .current_norm = V4L2_STD_NTSC_M, }; +static const struct v4l2_ioctl_ops vbi_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, + .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, + .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_chip_ident = vidioc_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +static const struct video_device cx8800_vbi_template = { + .name = "cx8800-vbi", + .fops = &video_fops, + .ioctl_ops = &vbi_ioctl_ops, + .tvnorms = CX88_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, @@ -1595,6 +1640,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1682,11 +1728,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, goto fail_core; } - /* Initialize VBI template */ - memcpy( &cx8800_vbi_template, &cx8800_video_template, - sizeof(cx8800_vbi_template) ); - strcpy(cx8800_vbi_template.name,"cx8800-vbi"); - /* initialize driver struct */ spin_lock_init(&dev->slock); core->tvnorm = cx8800_video_template.current_norm; -- GitLab From 48d68801d7fe2cefd3963428917b74c93a69ff99 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 25 May 2012 12:15:30 -0300 Subject: [PATCH 1997/5711] [media] cx88: don't use current_norm current_norm can only be used if there is a single device node since it is local to the device node. In this case multiple device nodes share a single tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 12 +++++++++--- drivers/media/video/cx88/cx88-video.c | 14 +++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 38efc1fdb75f..e3bc8f7fcff4 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -930,6 +930,14 @@ static int vidioc_s_tuner (struct file *file, void *priv, return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) +{ + struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; + + *tvnorm = core->tvnorm; + return 0; +} + static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) { struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; @@ -1104,6 +1112,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_input = vidioc_s_input, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -1114,7 +1123,6 @@ static struct video_device cx8802_mpeg_template = { .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, .tvnorms = CX88_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; /* ------------------------------------------------------------------ */ @@ -1214,8 +1222,6 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) goto fail_core; - cx8802_mpeg_template.current_norm = core->tvnorm; - dev->width = 720; if (core->tvnorm & V4L2_STD_525_60) { dev->height = 480; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 3dee42141979..f6fcc7e763ab 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1185,6 +1185,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) +{ + struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; + + *tvnorm = core->tvnorm; + return 0; +} + static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms) { struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; @@ -1562,6 +1570,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, @@ -1586,7 +1595,6 @@ static const struct video_device cx8800_video_template = { .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX88_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_ioctl_ops vbi_ioctl_ops = { @@ -1598,6 +1606,7 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, @@ -1620,7 +1629,6 @@ static const struct video_device cx8800_vbi_template = { .fops = &video_fops, .ioctl_ops = &vbi_ioctl_ops, .tvnorms = CX88_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_file_operations radio_fops = @@ -1730,7 +1738,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* initialize driver struct */ spin_lock_init(&dev->slock); - core->tvnorm = cx8800_video_template.current_norm; + core->tvnorm = V4L2_STD_NTSC_M; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); -- GitLab From fcbd504989739897db0c7bd1c3e55e42c1682e21 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 25 May 2012 12:30:18 -0300 Subject: [PATCH 1998/5711] [media] cx88-blackbird: replace ioctl by unlocked_ioctl Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index e3bc8f7fcff4..843ffd9e533b 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1089,7 +1089,7 @@ static const struct v4l2_file_operations mpeg_fops = .read = mpeg_read, .poll = mpeg_poll, .mmap = mpeg_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { -- GitLab From 91268a5e788c5bf246650c3a8c1a4626b9f0fe11 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 2 Jul 2012 17:27:41 -0300 Subject: [PATCH 1999/5711] [media] saa7134: fix spelling of detach in label Signed-off-by: Peter Meerwald Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 82 +++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5dfd826d734e..cc7f3d6ee966 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1282,7 +1282,7 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: if (configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: @@ -1322,7 +1322,7 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_KWORLD_DVBT_210: if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_HAUPPAUGE_HVR1120: fe0->dvb.frontend = dvb_attach(tda10048_attach, @@ -1340,17 +1340,17 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_PHILIPS_TIGER: if (configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_PINNACLE_PCTV_310i: if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_HAUPPAUGE_HVR1150: fe0->dvb.frontend = dvb_attach(lgdt3305_attach, @@ -1368,30 +1368,30 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_ASUSTeK_P7131_DUAL: if (configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_FLYDVBT_LR301: if (configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_FLYDVB_TRIO: if (!use_frontend) { /* terrestrial */ if (configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; } else { /* satellite */ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (fe0->dvb.frontend) { if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } } } @@ -1407,7 +1407,7 @@ static int dvb_init(struct saa7134_dev *dev) &ads_duo_cfg) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", ads_tech_duo_config.tuner_address); - goto dettach_frontend; + goto detach_frontend; } } else wprintk("failed to attach tda10046\n"); @@ -1415,13 +1415,13 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_TEVION_DVBT_220RF: if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: if (!use_frontend) { /* terrestrial */ if (configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; } else { /* satellite */ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); @@ -1435,7 +1435,7 @@ static int dvb_init(struct saa7134_dev *dev) 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Medion Quadro, no tda826x " "found !\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dev_id != 0x08) { /* we need to open the i2c gate (we know it exists) */ @@ -1444,7 +1444,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Medion Quadro, no ISL6405 " "found !\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dev_id == 0x07) { /* fire up the 2nd section of the LNB supply since @@ -1503,12 +1503,12 @@ static int dvb_init(struct saa7134_dev *dev) if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: No ISL6421 found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } } break; @@ -1537,37 +1537,37 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_CINERGY_HT_PCMCIA: if (configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_CINERGY_HT_PCI: if (configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_PHILIPS_TIGER_S: if (configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_ASUS_P7131_4871: if (configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_AVERMEDIA_SUPER_007: if (configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_PHILIPS_SNAKE: fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, @@ -1576,24 +1576,24 @@ static int dvb_init(struct saa7134_dev *dev) if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: No lnbp21 found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } } break; case SAA7134_BOARD_CREATIX_CTX953: if (configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_MSI_TVANYWHERE_AD11: if (configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: dprintk("AverMedia E506R dvb setup\n"); @@ -1614,7 +1614,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) { wprintk("%s: MD7134 DVB-S, no SD1878 " "found !\n", __func__); - goto dettach_frontend; + goto detach_frontend; } /* we need to open the i2c gate (we know it exists) */ fe = fe0->dvb.frontend; @@ -1623,7 +1623,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: MD7134 DVB-S, no ISL6405 " "found !\n", __func__); - goto dettach_frontend; + goto detach_frontend; } fe->ops.i2c_gate_ctrl(fe, 0); dev->original_set_voltage = fe->ops.set_voltage; @@ -1645,7 +1645,7 @@ static int dvb_init(struct saa7134_dev *dev) if (!use_frontend) { /* terrestrial */ if (configure_tda827x_fe(dev, &asus_tiger_3in1_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; } else { /* satellite */ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); @@ -1655,13 +1655,13 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no " "tda826x found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no lnbp21" " found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } } } @@ -1670,7 +1670,7 @@ static int dvb_init(struct saa7134_dev *dev) if (!use_frontend) { /* terrestrial */ if (configure_tda827x_fe(dev, &asus_ps3_100_config, &tda827x_cfg_2) < 0) - goto dettach_frontend; + goto detach_frontend; } else { /* satellite */ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); @@ -1680,13 +1680,13 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, 0) == NULL) { wprintk("%s: Asus My Cinema PS3-100, no " "tda826x found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: Asus My Cinema PS3-100, no lnbp21" " found!\n", __func__); - goto dettach_frontend; + goto detach_frontend; } } } @@ -1694,7 +1694,7 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_ASUSTeK_TIGER: if (configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0) < 0) - goto dettach_frontend; + goto detach_frontend; break; case SAA7134_BOARD_BEHOLD_H6: fe0->dvb.frontend = dvb_attach(zl10353_attach, @@ -1830,19 +1830,19 @@ static int dvb_init(struct saa7134_dev *dev) }; if (!fe0->dvb.frontend) - goto dettach_frontend; + goto detach_frontend; fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->name); - goto dettach_frontend; + goto detach_frontend; } } if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); - goto dettach_frontend; + goto detach_frontend; } /* define general-purpose callback pointer */ fe0->dvb.frontend->callback = saa7134_tuner_callback; @@ -1864,7 +1864,7 @@ static int dvb_init(struct saa7134_dev *dev) } return ret; -dettach_frontend: +detach_frontend: videobuf_dvb_dealloc_frontends(&dev->frontends); return -EINVAL; } -- GitLab From 87e9429490dfe610faaf209795942272bc7a730a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 3 Jul 2012 05:54:33 -0300 Subject: [PATCH 2000/5711] [media] s5p-jpeg: Use module_platform_driver in jpeg-core.c file module_platform_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-jpeg/jpeg-core.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c index 28b5225d94f5..e40e79b33df6 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.c +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c @@ -1503,29 +1503,7 @@ static struct platform_driver s5p_jpeg_driver = { }, }; -static int __init -s5p_jpeg_register(void) -{ - int ret; - - pr_info("S5P JPEG V4L2 Driver, (c) 2011 Samsung Electronics\n"); - - ret = platform_driver_register(&s5p_jpeg_driver); - - if (ret) - pr_err("%s: failed to register jpeg driver\n", __func__); - - return ret; -} - -static void __exit -s5p_jpeg_unregister(void) -{ - platform_driver_unregister(&s5p_jpeg_driver); -} - -module_init(s5p_jpeg_register); -module_exit(s5p_jpeg_unregister); +module_platform_driver(s5p_jpeg_driver); MODULE_AUTHOR("Andrzej Pietrasiewicz "); MODULE_DESCRIPTION("Samsung JPEG codec driver"); -- GitLab From 500c3201e2aed201f2de0468dfeb3ceb98a9f981 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Tue, 3 Jul 2012 06:27:19 -0300 Subject: [PATCH 2001/5711] [media] media: gpio-ir-recv: add allowed_protos for platform data It's better to give platform code a chance to specify the allowed protocols to use. [mchehab@redhat.com: fix merge conflict with a patch that made half of this change] Signed-off-by: Du, Changbin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 5 ++++- include/media/gpio-ir-recv.h | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 59fe60cd1e02..04cb272db16a 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -84,7 +84,6 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev) rcdev->priv = gpio_dev; rcdev->driver_type = RC_DRIVER_IR_RAW; - rcdev->allowed_protos = RC_TYPE_ALL; rcdev->input_name = GPIO_IR_DEVICE_NAME; rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0"; rcdev->input_id.bustype = BUS_HOST; @@ -93,6 +92,10 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev) rcdev->input_id.version = 0x0100; rcdev->dev.parent = &pdev->dev; rcdev->driver_name = GPIO_IR_DRIVER_NAME; + if (pdata->allowed_protos) + rcdev->allowed_protos = pdata->allowed_protos; + else + rcdev->allowed_protos = RC_TYPE_ALL; rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY; gpio_dev->rcdev = rcdev; diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h index 91546f35b7e1..0142736a59db 100644 --- a/include/media/gpio-ir-recv.h +++ b/include/media/gpio-ir-recv.h @@ -14,9 +14,10 @@ #define __GPIO_IR_RECV_H__ struct gpio_ir_recv_platform_data { - int gpio_nr; - bool active_low; - const char *map_name; + int gpio_nr; + bool active_low; + u64 allowed_protos; + const char *map_name; }; #endif /* __GPIO_IR_RECV_H__ */ -- GitLab From 02a890d6262df653e5efdf47658f2330a6407f3e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 4 Jul 2012 02:33:15 -0300 Subject: [PATCH 2002/5711] [media] s5p-tv: Use module_i2c_driver in sii9234_drv.c file module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Acked-by: Tomasz Stanislawski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-tv/sii9234_drv.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/media/video/s5p-tv/sii9234_drv.c b/drivers/media/video/s5p-tv/sii9234_drv.c index 0f31eccd7b80..6d348f90237a 100644 --- a/drivers/media/video/s5p-tv/sii9234_drv.c +++ b/drivers/media/video/s5p-tv/sii9234_drv.c @@ -419,14 +419,4 @@ static struct i2c_driver sii9234_driver = { .id_table = sii9234_id, }; -static int __init sii9234_init(void) -{ - return i2c_add_driver(&sii9234_driver); -} -module_init(sii9234_init); - -static void __exit sii9234_exit(void) -{ - i2c_del_driver(&sii9234_driver); -} -module_exit(sii9234_exit); +module_i2c_driver(sii9234_driver); -- GitLab From 936148a71e5e55a301b274e98b0ad8b246a6f11b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 11:31:51 -0300 Subject: [PATCH 2003/5711] [media] media: dvb-usb: print mac address via native %pM Signed-off-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 4008b9c50fbd..8ffcad000ad3 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -593,9 +593,7 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) memcpy(mac, st->data, sizeof(mac)); if (ret > 0) - deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", - __func__, mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]); + deb_info("%s: mac is %pM\n", __func__, mac); return ret; } -- GitLab From e74f209ca99568865dfca5a456a114734cb7ef8c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:46:44 -0700 Subject: [PATCH 2004/5711] staging: comedi: cb_pcidas: remove forward declarations 1 Move the attach/detach functions to remove the need for some of the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 494 +++++++++------------ 1 file changed, 219 insertions(+), 275 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index e2bf22270561..5460410e6c7c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,37 +447,9 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int cb_pcidas_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); -static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); -static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); -static int cb_pcidas_ai_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); -static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int cb_pcidas_ao_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); static int cb_pcidas_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *subdev, unsigned int trig_num); -static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static irqreturn_t cb_pcidas_interrupt(int irq, void *d); static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status); static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s); @@ -485,30 +457,6 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, int round_flags); -static int eeprom_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int caldac_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int caldac_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int trimpot_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int cb_pcidas_trimpot_write(struct comedi_device *dev, - unsigned int channel, unsigned int value); -static int trimpot_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int dac08_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int dac08_write(struct comedi_device *dev, unsigned int value); -static int dac08_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); static int caldac_8800_write(struct comedi_device *dev, unsigned int address, uint8_t value); static int trimpot_7376_write(struct comedi_device *dev, uint8_t value); @@ -522,229 +470,6 @@ static inline unsigned int cal_enable_bits(struct comedi_device *dev) return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); } -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. - */ -static int cb_pcidas_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - struct comedi_subdevice *s; - struct pci_dev *pcidev = NULL; - int index; - int i; - int ret; - -/* - * Allocate the private structure area. - */ - if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) - return -ENOMEM; - -/* - * Probe the device to determine what device in the series it is. - */ - - for_each_pci_dev(pcidev) { - /* is it not a computer boards card? */ - if (pcidev->vendor != PCI_VENDOR_ID_CB) - continue; - /* loop through cards supported by this driver */ - for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) { - if (cb_pcidas_boards[index].device_id != pcidev->device) - continue; - /* was a particular bus/slot requested? */ - if (it->options[0] || it->options[1]) { - /* are we on the wrong bus/slot? */ - if (pcidev->bus->number != it->options[0] || - PCI_SLOT(pcidev->devfn) != it->options[1]) { - continue; - } - } - devpriv->pci_dev = pcidev; - dev->board_ptr = cb_pcidas_boards + index; - goto found; - } - } - - dev_err(dev->class_dev, - "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); - return -EIO; - -found: - - dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", - cb_pcidas_boards[index].name, pcidev->bus->number, - PCI_SLOT(pcidev->devfn)); - - /* - * Enable PCI device and reserve I/O ports. - */ - if (comedi_pci_enable(pcidev, "cb_pcidas")) { - dev_err(dev->class_dev, - "Failed to enable PCI device and request regions\n"); - return -EIO; - } - /* - * Initialize devpriv->control_status and devpriv->adc_fifo to point to - * their base address. - */ - devpriv->s5933_config = - pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); - devpriv->control_status = - pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); - devpriv->adc_fifo = - pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); - devpriv->pacer_counter_dio = - pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); - if (thisboard->ao_nchan) { - devpriv->ao_registers = - pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); - } - /* disable and clear interrupts on amcc s5933 */ - outl(INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); - - /* get irq */ - if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, - IRQF_SHARED, "cb_pcidas", dev)) { - dev_dbg(dev->class_dev, "unable to allocate irq %d\n", - devpriv->pci_dev->irq); - return -EINVAL; - } - dev->irq = devpriv->pci_dev->irq; - - /* Initialize dev->board_name */ - dev->board_name = thisboard->name; - - ret = comedi_alloc_subdevices(dev, 7); - if (ret) - return ret; - - s = dev->subdevices + 0; - /* analog input subdevice */ - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; - /* WARNING: Number of inputs in differential mode is ignored */ - s->n_chan = thisboard->ai_se_chans; - s->len_chanlist = thisboard->ai_se_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ranges; - s->insn_read = cb_pcidas_ai_rinsn; - s->insn_config = ai_config_insn; - s->do_cmd = cb_pcidas_ai_cmd; - s->do_cmdtest = cb_pcidas_ai_cmdtest; - s->cancel = cb_pcidas_cancel; - - /* analog output subdevice */ - s = dev->subdevices + 1; - if (thisboard->ao_nchan) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; - s->n_chan = thisboard->ao_nchan; - /* analog out resolution is the same as analog input resolution, so use ai_bits */ - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = &cb_pcidas_ao_ranges; - s->insn_read = cb_pcidas_ao_readback_insn; - if (thisboard->has_ao_fifo) { - dev->write_subdev = s; - s->subdev_flags |= SDF_CMD_WRITE; - s->insn_write = cb_pcidas_ao_fifo_winsn; - s->do_cmdtest = cb_pcidas_ao_cmdtest; - s->do_cmd = cb_pcidas_ao_cmd; - s->cancel = cb_pcidas_ao_cancel; - } else { - s->insn_write = cb_pcidas_ao_nofifo_winsn; - } - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - /* 8255 */ - s = dev->subdevices + 2; - subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); - - /* serial EEPROM, */ - s = dev->subdevices + 3; - s->type = COMEDI_SUBD_MEMORY; - s->subdev_flags = SDF_READABLE | SDF_INTERNAL; - s->n_chan = 256; - s->maxdata = 0xff; - s->insn_read = eeprom_read_insn; - - /* 8800 caldac */ - s = dev->subdevices + 4; - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = NUM_CHANNELS_8800; - s->maxdata = 0xff; - s->insn_read = caldac_read_insn; - s->insn_write = caldac_write_insn; - for (i = 0; i < s->n_chan; i++) - caldac_8800_write(dev, i, s->maxdata / 2); - - /* trim potentiometer */ - s = dev->subdevices + 5; - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - if (thisboard->trimpot == AD7376) { - s->n_chan = NUM_CHANNELS_7376; - s->maxdata = 0x7f; - } else { - s->n_chan = NUM_CHANNELS_8402; - s->maxdata = 0xff; - } - s->insn_read = trimpot_read_insn; - s->insn_write = trimpot_write_insn; - for (i = 0; i < s->n_chan; i++) - cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); - - /* dac08 caldac */ - s = dev->subdevices + 6; - if (thisboard->has_dac08) { - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = NUM_CHANNELS_DAC08; - s->insn_read = dac08_read_insn; - s->insn_write = dac08_write_insn; - s->maxdata = 0xff; - dac08_write(dev, s->maxdata / 2); - } else - s->type = COMEDI_SUBD_UNUSED; - - /* make sure mailbox 4 is empty */ - inl(devpriv->s5933_config + AMCC_OP_REG_IMB4); - /* Set bits to enable incoming mailbox interrupts on amcc s5933. */ - devpriv->s5933_intcsr_bits = - INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | - INTCSR_INBOX_FULL_INT; - /* clear and enable interrupt on amcc s5933 */ - outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); - - return 1; -} - -static void cb_pcidas_detach(struct comedi_device *dev) -{ - if (devpriv) { - if (devpriv->s5933_config) { - outl(INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); - } - } - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->subdevices) - subdev_8255_cleanup(dev, dev->subdevices + 2); - if (devpriv && devpriv->pci_dev) { - if (devpriv->s5933_config) - comedi_pci_disable(devpriv->pci_dev); - pci_dev_put(devpriv->pci_dev); - } -} - /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -1872,6 +1597,225 @@ static int nvram_read(struct comedi_device *dev, unsigned int address, return 0; } +static int cb_pcidas_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct comedi_subdevice *s; + struct pci_dev *pcidev = NULL; + int index; + int i; + int ret; + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) + return -ENOMEM; + +/* + * Probe the device to determine what device in the series it is. + */ + + for_each_pci_dev(pcidev) { + /* is it not a computer boards card? */ + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + /* loop through cards supported by this driver */ + for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) { + if (cb_pcidas_boards[index].device_id != pcidev->device) + continue; + /* was a particular bus/slot requested? */ + if (it->options[0] || it->options[1]) { + /* are we on the wrong bus/slot? */ + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != it->options[1]) { + continue; + } + } + devpriv->pci_dev = pcidev; + dev->board_ptr = cb_pcidas_boards + index; + goto found; + } + } + + dev_err(dev->class_dev, + "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); + return -EIO; + +found: + + dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", + cb_pcidas_boards[index].name, pcidev->bus->number, + PCI_SLOT(pcidev->devfn)); + + /* + * Enable PCI device and reserve I/O ports. + */ + if (comedi_pci_enable(pcidev, "cb_pcidas")) { + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); + return -EIO; + } + /* + * Initialize devpriv->control_status and devpriv->adc_fifo to point to + * their base address. + */ + devpriv->s5933_config = + pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); + devpriv->control_status = + pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); + devpriv->adc_fifo = + pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); + devpriv->pacer_counter_dio = + pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); + if (thisboard->ao_nchan) { + devpriv->ao_registers = + pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); + } + /* disable and clear interrupts on amcc s5933 */ + outl(INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + + /* get irq */ + if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, + IRQF_SHARED, "cb_pcidas", dev)) { + dev_dbg(dev->class_dev, "unable to allocate irq %d\n", + devpriv->pci_dev->irq); + return -EINVAL; + } + dev->irq = devpriv->pci_dev->irq; + + /* Initialize dev->board_name */ + dev->board_name = thisboard->name; + + ret = comedi_alloc_subdevices(dev, 7); + if (ret) + return ret; + + s = dev->subdevices + 0; + /* analog input subdevice */ + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + /* WARNING: Number of inputs in differential mode is ignored */ + s->n_chan = thisboard->ai_se_chans; + s->len_chanlist = thisboard->ai_se_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = thisboard->ranges; + s->insn_read = cb_pcidas_ai_rinsn; + s->insn_config = ai_config_insn; + s->do_cmd = cb_pcidas_ai_cmd; + s->do_cmdtest = cb_pcidas_ai_cmdtest; + s->cancel = cb_pcidas_cancel; + + /* analog output subdevice */ + s = dev->subdevices + 1; + if (thisboard->ao_nchan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; + s->n_chan = thisboard->ao_nchan; + /* analog out resolution is the same as analog input resolution, so use ai_bits */ + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &cb_pcidas_ao_ranges; + s->insn_read = cb_pcidas_ao_readback_insn; + if (thisboard->has_ao_fifo) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->insn_write = cb_pcidas_ao_fifo_winsn; + s->do_cmdtest = cb_pcidas_ao_cmdtest; + s->do_cmd = cb_pcidas_ao_cmd; + s->cancel = cb_pcidas_ao_cancel; + } else { + s->insn_write = cb_pcidas_ao_nofifo_winsn; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* 8255 */ + s = dev->subdevices + 2; + subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); + + /* serial EEPROM, */ + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 256; + s->maxdata = 0xff; + s->insn_read = eeprom_read_insn; + + /* 8800 caldac */ + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_CHANNELS_8800; + s->maxdata = 0xff; + s->insn_read = caldac_read_insn; + s->insn_write = caldac_write_insn; + for (i = 0; i < s->n_chan; i++) + caldac_8800_write(dev, i, s->maxdata / 2); + + /* trim potentiometer */ + s = dev->subdevices + 5; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + if (thisboard->trimpot == AD7376) { + s->n_chan = NUM_CHANNELS_7376; + s->maxdata = 0x7f; + } else { + s->n_chan = NUM_CHANNELS_8402; + s->maxdata = 0xff; + } + s->insn_read = trimpot_read_insn; + s->insn_write = trimpot_write_insn; + for (i = 0; i < s->n_chan; i++) + cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); + + /* dac08 caldac */ + s = dev->subdevices + 6; + if (thisboard->has_dac08) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_CHANNELS_DAC08; + s->insn_read = dac08_read_insn; + s->insn_write = dac08_write_insn; + s->maxdata = 0xff; + dac08_write(dev, s->maxdata / 2); + } else + s->type = COMEDI_SUBD_UNUSED; + + /* make sure mailbox 4 is empty */ + inl(devpriv->s5933_config + AMCC_OP_REG_IMB4); + /* Set bits to enable incoming mailbox interrupts on amcc s5933. */ + devpriv->s5933_intcsr_bits = + INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | + INTCSR_INBOX_FULL_INT; + /* clear and enable interrupt on amcc s5933 */ + outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + + return 1; +} + +static void cb_pcidas_detach(struct comedi_device *dev) +{ + if (devpriv) { + if (devpriv->s5933_config) { + outl(INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + } + } + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 2); + if (devpriv && devpriv->pci_dev) { + if (devpriv->s5933_config) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } +} + static struct comedi_driver cb_pcidas_driver = { .driver_name = "cb_pcidas", .module = THIS_MODULE, -- GitLab From 1706fcc18b8e27f2e8895b6ced83112ab8a0ad20 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:47:28 -0700 Subject: [PATCH 2005/5711] staging: comedi: cb_pcidas: remove forward declarations 2 Move the cb_pcidas_ao_inttrig function to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 103 ++++++++++----------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 5460410e6c7c..e94a6b16a38b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,9 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int cb_pcidas_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *subdev, - unsigned int trig_num); static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status); static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s); @@ -1132,6 +1129,56 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, return 0; } +static int cb_pcidas_ao_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + unsigned int num_bytes, num_points = thisboard->fifo_size; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long flags; + + if (trig_num != 0) + return -EINVAL; + + /* load up fifo */ + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points) + num_points = devpriv->ao_count; + + num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer, + num_points * sizeof(short)); + num_points = num_bytes / sizeof(short); + + if (cmd->stop_src == TRIG_COUNT) + devpriv->ao_count -= num_points; + /* write data to board's fifo */ + outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes); + + /* enable dac half-full and empty interrupts */ + spin_lock_irqsave(&dev->spinlock, flags); + devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; +#ifdef CB_PCIDAS_DEBUG + dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", + devpriv->adc_fifo_bits); +#endif + /* enable and clear interrupts */ + outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, + devpriv->control_status + INT_ADCFIFO); + + /* start dac */ + devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); +#ifdef CB_PCIDAS_DEBUG + dev_dbg(dev->class_dev, "sent 0x%x to dac control\n", + devpriv->ao_control_bits); +#endif + spin_unlock_irqrestore(&dev->spinlock, flags); + + async->inttrig = NULL; + + return 0; +} + static int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -1198,56 +1245,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, return 0; } -static int cb_pcidas_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int trig_num) -{ - unsigned int num_bytes, num_points = thisboard->fifo_size; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned long flags; - - if (trig_num != 0) - return -EINVAL; - - /* load up fifo */ - if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points) - num_points = devpriv->ao_count; - - num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer, - num_points * sizeof(short)); - num_points = num_bytes / sizeof(short); - - if (cmd->stop_src == TRIG_COUNT) - devpriv->ao_count -= num_points; - /* write data to board's fifo */ - outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes); - - /* enable dac half-full and empty interrupts */ - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", - devpriv->adc_fifo_bits); -#endif - /* enable and clear interrupts */ - outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, - devpriv->control_status + INT_ADCFIFO); - - /* start dac */ - devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "sent 0x%x to dac control\n", - devpriv->ao_control_bits); -#endif - spin_unlock_irqrestore(&dev->spinlock, flags); - - async->inttrig = NULL; - - return 0; -} - static irqreturn_t cb_pcidas_interrupt(int irq, void *d) { struct comedi_device *dev = (struct comedi_device *)d; -- GitLab From 9e11d05f89b44e5f2672a74e5fe0f7eced7a4cad Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:48:05 -0700 Subject: [PATCH 2006/5711] staging: comedi: cb_pcidas: remove forward declarations 3 Move the handle_ao_interrupt function to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 111 ++++++++++----------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index e94a6b16a38b..584f85b434e8 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,7 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status); static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static int cb_pcidas_ao_cancel(struct comedi_device *dev, @@ -1245,6 +1244,61 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, return 0; } +static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) +{ + struct comedi_subdevice *s = dev->write_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int half_fifo = thisboard->fifo_size / 2; + unsigned int num_points; + unsigned long flags; + + async->events = 0; + + if (status & DAEMI) { + /* clear dac empty interrupt latch */ + spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | DAEMI, + devpriv->control_status + INT_ADCFIFO); + spin_unlock_irqrestore(&dev->spinlock, flags); + if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { + if (cmd->stop_src == TRIG_NONE || + (cmd->stop_src == TRIG_COUNT + && devpriv->ao_count)) { + comedi_error(dev, "dac fifo underflow"); + cb_pcidas_ao_cancel(dev, s); + async->events |= COMEDI_CB_ERROR; + } + async->events |= COMEDI_CB_EOA; + } + } else if (status & DAHFI) { + unsigned int num_bytes; + + /* figure out how many points we are writing to fifo */ + num_points = half_fifo; + if (cmd->stop_src == TRIG_COUNT && + devpriv->ao_count < num_points) + num_points = devpriv->ao_count; + num_bytes = + cfc_read_array_from_buffer(s, devpriv->ao_buffer, + num_points * sizeof(short)); + num_points = num_bytes / sizeof(short); + + if (async->cmd.stop_src == TRIG_COUNT) + devpriv->ao_count -= num_points; + /* write data to board's fifo */ + outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, + num_points); + /* clear half-full interrupt latch */ + spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | DAHFI, + devpriv->control_status + INT_ADCFIFO); + spin_unlock_irqrestore(&dev->spinlock, flags); + } + + comedi_event(dev, s); +} + static irqreturn_t cb_pcidas_interrupt(int irq, void *d) { struct comedi_device *dev = (struct comedi_device *)d; @@ -1355,61 +1409,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) -{ - struct comedi_subdevice *s = dev->write_subdev; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; - unsigned int half_fifo = thisboard->fifo_size / 2; - unsigned int num_points; - unsigned long flags; - - async->events = 0; - - if (status & DAEMI) { - /* clear dac empty interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | DAEMI, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { - if (cmd->stop_src == TRIG_NONE || - (cmd->stop_src == TRIG_COUNT - && devpriv->ao_count)) { - comedi_error(dev, "dac fifo underflow"); - cb_pcidas_ao_cancel(dev, s); - async->events |= COMEDI_CB_ERROR; - } - async->events |= COMEDI_CB_EOA; - } - } else if (status & DAHFI) { - unsigned int num_bytes; - - /* figure out how many points we are writing to fifo */ - num_points = half_fifo; - if (cmd->stop_src == TRIG_COUNT && - devpriv->ao_count < num_points) - num_points = devpriv->ao_count; - num_bytes = - cfc_read_array_from_buffer(s, devpriv->ao_buffer, - num_points * sizeof(short)); - num_points = num_bytes / sizeof(short); - - if (async->cmd.stop_src == TRIG_COUNT) - devpriv->ao_count -= num_points; - /* write data to board's fifo */ - outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, - num_points); - /* clear half-full interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | DAHFI, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - } - - comedi_event(dev, s); -} - /* cancel analog input command */ static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s) -- GitLab From 9a0f7631f26cd9d9fc9f8fd1513427e13912a63c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:48:43 -0700 Subject: [PATCH 2007/5711] staging: comedi: cb_pcidas: remove forward declarations 4 Move the cb_pcida_cancel function to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 42 +++++++++++----------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 584f85b434e8..fa3ed0e01b33 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,8 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int cb_pcidas_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, @@ -1128,6 +1126,26 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, return 0; } +/* cancel analog input command */ +static int cb_pcidas_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + /* disable interrupts */ + devpriv->adc_fifo_bits &= ~INTE & ~EOAIE; + outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + spin_unlock_irqrestore(&dev->spinlock, flags); + + /* disable start trigger source and burst mode */ + outw(0, devpriv->control_status + TRIG_CONTSTAT); + /* software pacer source */ + outw(0, devpriv->control_status + ADCMUX_CONT); + + return 0; +} + static int cb_pcidas_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) @@ -1409,26 +1427,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -/* cancel analog input command */ -static int cb_pcidas_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->spinlock, flags); - /* disable interrupts */ - devpriv->adc_fifo_bits &= ~INTE & ~EOAIE; - outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - - /* disable start trigger source and burst mode */ - outw(0, devpriv->control_status + TRIG_CONTSTAT); - /* software pacer source */ - outw(0, devpriv->control_status + ADCMUX_CONT); - - return 0; -} - /* cancel analog output command */ static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) -- GitLab From 0aa2030467e4dfad59aef42211728221a973c329 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:49:22 -0700 Subject: [PATCH 2008/5711] staging: comedi: cb_pcidas: remove forward declarations 5 Move the cb_pcida_ao_cancel function to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 40 ++++++++++------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index fa3ed0e01b33..24574082691e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,8 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int cb_pcidas_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, int round_flags); static int caldac_8800_write(struct comedi_device *dev, unsigned int address, @@ -1262,6 +1260,25 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, return 0; } +/* cancel analog output command */ +static int cb_pcidas_ao_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + /* disable interrupts */ + devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE; + outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + + /* disable output */ + devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK; + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + spin_unlock_irqrestore(&dev->spinlock, flags); + + return 0; +} + static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) { struct comedi_subdevice *s = dev->write_subdev; @@ -1427,25 +1444,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -/* cancel analog output command */ -static int cb_pcidas_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->spinlock, flags); - /* disable interrupts */ - devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE; - outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); - - /* disable output */ - devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK; - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); - spin_unlock_irqrestore(&dev->spinlock, flags); - - return 0; -} - static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, int rounding_flags) { -- GitLab From bb03694323561da47fb6a15d977a0b5275134cdd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:49:58 -0700 Subject: [PATCH 2009/5711] staging: comedi: cb_pcidas: remove forward declarations 6 Move the cb_pcidas_load_counters function to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 24574082691e..1e5616e15fb5 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,8 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, - int round_flags); static int caldac_8800_write(struct comedi_device *dev, unsigned int address, uint8_t value); static int trimpot_7376_write(struct comedi_device *dev, uint8_t value); @@ -915,6 +913,20 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, return 0; } +static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, + int rounding_flags) +{ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), ns, + rounding_flags & TRIG_ROUND_MASK); + + /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ + i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, + devpriv->divisor1, 2); + i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2, + devpriv->divisor2, 2); +} + static int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -1444,20 +1456,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, - int rounding_flags) -{ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), - &(devpriv->divisor2), ns, - rounding_flags & TRIG_ROUND_MASK); - - /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, - devpriv->divisor1, 2); - i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2, - devpriv->divisor2, 2); -} - static void write_calibration_bitstream(struct comedi_device *dev, unsigned int register_bits, unsigned int bitstream, -- GitLab From 0c15d553252657d895492252203bcccdbe4a9b21 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:50:36 -0700 Subject: [PATCH 2010/5711] staging: comedi: cb_pcidas: remove forward declarations 7 Move the caldac_8800_write function, and it's helper, to remove the need for the forward declaration. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 98 +++++++++++----------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 1e5616e15fb5..28bcb64cbf0f 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,8 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int caldac_8800_write(struct comedi_device *dev, unsigned int address, - uint8_t value); static int trimpot_7376_write(struct comedi_device *dev, uint8_t value); static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, uint8_t value); @@ -638,6 +636,54 @@ static int eeprom_read_insn(struct comedi_device *dev, return 1; } +static void write_calibration_bitstream(struct comedi_device *dev, + unsigned int register_bits, + unsigned int bitstream, + unsigned int bitstream_length) +{ + static const int write_delay = 1; + unsigned int bit; + + for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { + if (bitstream & bit) + register_bits |= SERIAL_DATA_IN_BIT; + else + register_bits &= ~SERIAL_DATA_IN_BIT; + udelay(write_delay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + } +} + +static int caldac_8800_write(struct comedi_device *dev, unsigned int address, + uint8_t value) +{ + static const int num_caldac_channels = 8; + static const int bitstream_length = 11; + unsigned int bitstream = ((address & 0x7) << 8) | value; + static const int caldac_8800_udelay = 1; + + if (address >= num_caldac_channels) { + comedi_error(dev, "illegal caldac channel"); + return -1; + } + + if (value == devpriv->caldac_value[address]) + return 1; + + devpriv->caldac_value[address] = value; + + write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, + bitstream_length); + + udelay(caldac_8800_udelay); + outw(cal_enable_bits(dev) | SELECT_8800_BIT, + devpriv->control_status + CALIBRATION_REG); + udelay(caldac_8800_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 1; +} + static int caldac_write_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1456,54 +1502,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static void write_calibration_bitstream(struct comedi_device *dev, - unsigned int register_bits, - unsigned int bitstream, - unsigned int bitstream_length) -{ - static const int write_delay = 1; - unsigned int bit; - - for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { - if (bitstream & bit) - register_bits |= SERIAL_DATA_IN_BIT; - else - register_bits &= ~SERIAL_DATA_IN_BIT; - udelay(write_delay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); - } -} - -static int caldac_8800_write(struct comedi_device *dev, unsigned int address, - uint8_t value) -{ - static const int num_caldac_channels = 8; - static const int bitstream_length = 11; - unsigned int bitstream = ((address & 0x7) << 8) | value; - static const int caldac_8800_udelay = 1; - - if (address >= num_caldac_channels) { - comedi_error(dev, "illegal caldac channel"); - return -1; - } - - if (value == devpriv->caldac_value[address]) - return 1; - - devpriv->caldac_value[address] = value; - - write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, - bitstream_length); - - udelay(caldac_8800_udelay); - outw(cal_enable_bits(dev) | SELECT_8800_BIT, - devpriv->control_status + CALIBRATION_REG); - udelay(caldac_8800_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 1; -} - static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) { static const int bitstream_length = 7; -- GitLab From 20535c1f3c010fffd84e1d9dc24ac352a0b9ad36 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:51:14 -0700 Subject: [PATCH 2011/5711] staging: comedi: cb_pcidas: remove forward declarations 8 Move the trimpot_{7376,8402}_write functions to remove the need for the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 91 +++++++++++----------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 28bcb64cbf0f..9c7f24aefd36 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,9 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int trimpot_7376_write(struct comedi_device *dev, uint8_t value); -static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, - uint8_t value); static int nvram_read(struct comedi_device *dev, unsigned int address, uint8_t *data); @@ -739,6 +736,50 @@ static int dac08_read_insn(struct comedi_device *dev, return 1; } +static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) +{ + static const int bitstream_length = 7; + unsigned int bitstream = value & 0x7f; + unsigned int register_bits; + static const int ad7376_udelay = 1; + + register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; + udelay(ad7376_udelay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + + write_calibration_bitstream(dev, register_bits, bitstream, + bitstream_length); + + udelay(ad7376_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 0; +} + +/* For 1602/16 only + * ch 0 : adc gain + * ch 1 : adc postgain offset */ +static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, + uint8_t value) +{ + static const int bitstream_length = 10; + unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); + unsigned int register_bits; + static const int ad8402_udelay = 1; + + register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; + udelay(ad8402_udelay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + + write_calibration_bitstream(dev, register_bits, bitstream, + bitstream_length); + + udelay(ad8402_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 0; +} + static int cb_pcidas_trimpot_write(struct comedi_device *dev, unsigned int channel, unsigned int value) { @@ -1502,50 +1543,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) -{ - static const int bitstream_length = 7; - unsigned int bitstream = value & 0x7f; - unsigned int register_bits; - static const int ad7376_udelay = 1; - - register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; - udelay(ad7376_udelay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); - - write_calibration_bitstream(dev, register_bits, bitstream, - bitstream_length); - - udelay(ad7376_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 0; -} - -/* For 1602/16 only - * ch 0 : adc gain - * ch 1 : adc postgain offset */ -static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, - uint8_t value) -{ - static const int bitstream_length = 10; - unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); - unsigned int register_bits; - static const int ad8402_udelay = 1; - - register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; - udelay(ad8402_udelay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); - - write_calibration_bitstream(dev, register_bits, bitstream, - bitstream_length); - - udelay(ad8402_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 0; -} - static int wait_for_nvram_ready(unsigned long s5933_base_addr) { static const int timeout = 1000; -- GitLab From 536af69e90b03966928ed59448f5ccd95ebd13ea Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:51:53 -0700 Subject: [PATCH 2012/5711] staging: comedi: cb_pcidas: remove forward declarations 9 Move the nvram_read function, and its helper, to remove the need for the last of the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 81 +++++++++++----------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 9c7f24aefd36..5c3758c49949 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -447,9 +447,6 @@ struct cb_pcidas_private { */ #define devpriv ((struct cb_pcidas_private *)dev->private) -static int nvram_read(struct comedi_device *dev, unsigned int address, - uint8_t *data); - static inline unsigned int cal_enable_bits(struct comedi_device *dev) { return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); @@ -617,6 +614,45 @@ static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, return 1; } +static int wait_for_nvram_ready(unsigned long s5933_base_addr) +{ + static const int timeout = 1000; + unsigned int i; + + for (i = 0; i < timeout; i++) { + if ((inb(s5933_base_addr + + AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY) + == 0) + return 0; + udelay(1); + } + return -1; +} + +static int nvram_read(struct comedi_device *dev, unsigned int address, + uint8_t *data) +{ + unsigned long iobase = devpriv->s5933_config; + + if (wait_for_nvram_ready(iobase) < 0) + return -ETIMEDOUT; + + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, + iobase + AMCC_OP_REG_MCSR_NVCMD); + outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, + iobase + AMCC_OP_REG_MCSR_NVCMD); + outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); + + if (wait_for_nvram_ready(iobase) < 0) + return -ETIMEDOUT; + + *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); + + return 0; +} + static int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1543,45 +1579,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static int wait_for_nvram_ready(unsigned long s5933_base_addr) -{ - static const int timeout = 1000; - unsigned int i; - - for (i = 0; i < timeout; i++) { - if ((inb(s5933_base_addr + - AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY) - == 0) - return 0; - udelay(1); - } - return -1; -} - -static int nvram_read(struct comedi_device *dev, unsigned int address, - uint8_t *data) -{ - unsigned long iobase = devpriv->s5933_config; - - if (wait_for_nvram_ready(iobase) < 0) - return -ETIMEDOUT; - - outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, - iobase + AMCC_OP_REG_MCSR_NVCMD); - outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); - outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, - iobase + AMCC_OP_REG_MCSR_NVCMD); - outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); - outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); - - if (wait_for_nvram_ready(iobase) < 0) - return -ETIMEDOUT; - - *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); - - return 0; -} - static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it) { -- GitLab From 82d8c74dcc75235740db3ed947267bfa5baa3117 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:52:29 -0700 Subject: [PATCH 2013/5711] staging: comedi: cb_pcidas: remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables where used. use the comedi_board() helper to get the 'thisboard' pointer. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 58 +++++++++++++++++----- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 5c3758c49949..146d0788f3db 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -404,11 +404,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr) - /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ @@ -441,14 +436,10 @@ struct cb_pcidas_private { unsigned int calibration_source; }; -/* - * most drivers define the following macro to make it easy to - * access the private structure. - */ -#define devpriv ((struct cb_pcidas_private *)dev->private) - static inline unsigned int cal_enable_bits(struct comedi_device *dev) { + struct cb_pcidas_private *devpriv = dev->private; + return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); } @@ -460,6 +451,7 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; int n, i; unsigned int bits; static const int timeout = 10000; @@ -512,6 +504,7 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, static int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; static const int num_calibration_sources = 8; unsigned int source = data[1]; @@ -548,6 +541,7 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; int channel; unsigned long flags; @@ -574,6 +568,7 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; int channel; unsigned long flags; @@ -609,6 +604,8 @@ static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; + data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; return 1; @@ -632,6 +629,7 @@ static int wait_for_nvram_ready(unsigned long s5933_base_addr) static int nvram_read(struct comedi_device *dev, unsigned int address, uint8_t *data) { + struct cb_pcidas_private *devpriv = dev->private; unsigned long iobase = devpriv->s5933_config; if (wait_for_nvram_ready(iobase) < 0) @@ -674,6 +672,7 @@ static void write_calibration_bitstream(struct comedi_device *dev, unsigned int bitstream, unsigned int bitstream_length) { + struct cb_pcidas_private *devpriv = dev->private; static const int write_delay = 1; unsigned int bit; @@ -690,6 +689,7 @@ static void write_calibration_bitstream(struct comedi_device *dev, static int caldac_8800_write(struct comedi_device *dev, unsigned int address, uint8_t value) { + struct cb_pcidas_private *devpriv = dev->private; static const int num_caldac_channels = 8; static const int bitstream_length = 11; unsigned int bitstream = ((address & 0x7) << 8) | value; @@ -730,6 +730,8 @@ static int caldac_read_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; + data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)]; return 1; @@ -738,6 +740,8 @@ static int caldac_read_insn(struct comedi_device *dev, /* 1602/16 pregain offset */ static int dac08_write(struct comedi_device *dev, unsigned int value) { + struct cb_pcidas_private *devpriv = dev->private; + if (devpriv->dac08_value == value) return 1; @@ -767,6 +771,8 @@ static int dac08_read_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; + data[0] = devpriv->dac08_value; return 1; @@ -774,6 +780,7 @@ static int dac08_read_insn(struct comedi_device *dev, static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) { + struct cb_pcidas_private *devpriv = dev->private; static const int bitstream_length = 7; unsigned int bitstream = value & 0x7f; unsigned int register_bits; @@ -798,6 +805,7 @@ static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, uint8_t value) { + struct cb_pcidas_private *devpriv = dev->private; static const int bitstream_length = 10; unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); unsigned int register_bits; @@ -819,6 +827,9 @@ static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, static int cb_pcidas_trimpot_write(struct comedi_device *dev, unsigned int channel, unsigned int value) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; + if (devpriv->trimpot_value[channel] == value) return 1; @@ -852,6 +863,7 @@ static int trimpot_read_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; unsigned int channel = CR_CHAN(insn->chanspec); data[0] = devpriv->trimpot_value[channel]; @@ -863,6 +875,8 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; int err = 0; int tmp; int i, gain, start_chan; @@ -1039,6 +1053,8 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, int rounding_flags) { + struct cb_pcidas_private *devpriv = dev->private; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), &(devpriv->divisor2), ns, rounding_flags & TRIG_ROUND_MASK); @@ -1053,6 +1069,8 @@ static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, static int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int bits; @@ -1147,6 +1165,8 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; int err = 0; int tmp; @@ -1263,6 +1283,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { + struct cb_pcidas_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); @@ -1283,6 +1304,8 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; unsigned int num_bytes, num_points = thisboard->fifo_size; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &s->async->cmd; @@ -1332,6 +1355,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, static int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct cb_pcidas_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int i; @@ -1399,6 +1423,7 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { + struct cb_pcidas_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); @@ -1416,6 +1441,8 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev, static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) { + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; struct comedi_subdevice *s = dev->write_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -1472,6 +1499,8 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) static irqreturn_t cb_pcidas_interrupt(int irq, void *d) { struct comedi_device *dev = (struct comedi_device *)d; + const struct cb_pcidas_board *thisboard = comedi_board(dev); + struct cb_pcidas_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; int status, s5933_status; @@ -1582,6 +1611,8 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct cb_pcidas_board *thisboard; + struct cb_pcidas_private *devpriv; struct comedi_subdevice *s; struct pci_dev *pcidev = NULL; int index; @@ -1593,6 +1624,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, */ if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) return -ENOMEM; + devpriv = dev->private; /* * Probe the device to determine what device in the series it is. @@ -1625,7 +1657,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, return -EIO; found: - + thisboard = comedi_board(dev); dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name, pcidev->bus->number, PCI_SLOT(pcidev->devfn)); @@ -1781,6 +1813,8 @@ found: static void cb_pcidas_detach(struct comedi_device *dev) { + struct cb_pcidas_private *devpriv = dev->private; + if (devpriv) { if (devpriv->s5933_config) { outl(INTCSR_INBOX_INTR_STATUS, -- GitLab From 327be979c1819d4404927af4b6e3ba8f22a4fa07 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:53:08 -0700 Subject: [PATCH 2014/5711] staging: comedi: cb_pcidas: factor out the find pci device code Factor the "find pci device" code out of the attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 70 ++++++++++++---------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 146d0788f3db..051c94cc01f8 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1608,64 +1608,70 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static int cb_pcidas_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct cb_pcidas_board *thisboard; - struct cb_pcidas_private *devpriv; - struct comedi_subdevice *s; struct pci_dev *pcidev = NULL; - int index; + int bus = it->options[0]; + int slot = it->options[1]; int i; - int ret; - -/* - * Allocate the private structure area. - */ - if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) - return -ENOMEM; - devpriv = dev->private; - -/* - * Probe the device to determine what device in the series it is. - */ for_each_pci_dev(pcidev) { /* is it not a computer boards card? */ if (pcidev->vendor != PCI_VENDOR_ID_CB) continue; /* loop through cards supported by this driver */ - for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) { - if (cb_pcidas_boards[index].device_id != pcidev->device) + for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) { + thisboard = &cb_pcidas_boards[i]; + if (thisboard->device_id != pcidev->device) continue; /* was a particular bus/slot requested? */ - if (it->options[0] || it->options[1]) { + if (bus || slot) { /* are we on the wrong bus/slot? */ - if (pcidev->bus->number != it->options[0] || - PCI_SLOT(pcidev->devfn) != it->options[1]) { + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) { continue; } } - devpriv->pci_dev = pcidev; - dev->board_ptr = cb_pcidas_boards + index; - goto found; + dev->board_ptr = thisboard; + return pcidev; } } + return NULL; +} + +static int cb_pcidas_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + const struct cb_pcidas_board *thisboard; + struct cb_pcidas_private *devpriv; + struct comedi_subdevice *s; + int i; + int ret; - dev_err(dev->class_dev, - "No supported ComputerBoards/MeasurementComputing card found on requested position\n"); - return -EIO; +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) + return -ENOMEM; + devpriv = dev->private; + + devpriv->pci_dev = cb_pcidas_find_pci_device(dev, it); + if (!devpriv->pci_dev) { + dev_err(dev->class_dev, "No supported card found\n"); + return -EIO; + } -found: thisboard = comedi_board(dev); dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", - cb_pcidas_boards[index].name, pcidev->bus->number, - PCI_SLOT(pcidev->devfn)); + thisboard->name, devpriv->pci_dev->bus->number, + PCI_SLOT(devpriv->pci_dev->devfn)); /* * Enable PCI device and reserve I/O ports. */ - if (comedi_pci_enable(pcidev, "cb_pcidas")) { + if (comedi_pci_enable(devpriv->pci_dev, "cb_pcidas")) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); return -EIO; -- GitLab From 9795f562bd72387da8c9e5bc99e2cce869aa1bc1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:53:55 -0700 Subject: [PATCH 2015/5711] staging: comedi: cb_pcidas: remove some obvious comments in the attach These comments are unnecessary. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 051c94cc01f8..990e6aba9c0f 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1650,9 +1650,6 @@ static int cb_pcidas_attach(struct comedi_device *dev, int i; int ret; -/* - * Allocate the private structure area. - */ if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) return -ENOMEM; devpriv = dev->private; @@ -1668,9 +1665,6 @@ static int cb_pcidas_attach(struct comedi_device *dev, thisboard->name, devpriv->pci_dev->bus->number, PCI_SLOT(devpriv->pci_dev->devfn)); - /* - * Enable PCI device and reserve I/O ports. - */ if (comedi_pci_enable(devpriv->pci_dev, "cb_pcidas")) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); @@ -1696,7 +1690,6 @@ static int cb_pcidas_attach(struct comedi_device *dev, outl(INTCSR_INBOX_INTR_STATUS, devpriv->s5933_config + AMCC_OP_REG_INTCSR); - /* get irq */ if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, IRQF_SHARED, "cb_pcidas", dev)) { dev_dbg(dev->class_dev, "unable to allocate irq %d\n", @@ -1705,7 +1698,6 @@ static int cb_pcidas_attach(struct comedi_device *dev, } dev->irq = devpriv->pci_dev->irq; - /* Initialize dev->board_name */ dev->board_name = thisboard->name; ret = comedi_alloc_subdevices(dev, 7); -- GitLab From 7302abef2ef3c6aae739f578a67504bb84974199 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:54:38 -0700 Subject: [PATCH 2016/5711] staging: comedi: cb_pcidas: remove the PCI BAR index defines The defines for the "indices of the base address regions" don't add much to the readability of the code. They are only used in the pci_resource_start() calls to get the base address for the various io regions and the names of the variables provide adequate documentation. Remove the defines and just use the open-coded values for the BARs. Also, remove the incomplete comment above the initialization of the variables. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 32 ++++++---------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 990e6aba9c0f..4e5f1ba77ac7 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -92,14 +92,6 @@ analog triggering on 1602 series #define NUM_CHANNELS_8402 2 #define NUM_CHANNELS_DAC08 1 -/* PCI-DAS base addresses */ - -/* indices of base address regions */ -#define S5933_BADRINDEX 0 -#define CONT_STAT_BADRINDEX 1 -#define ADC_FIFO_BADRINDEX 2 -#define PACER_BADRINDEX 3 -#define AO_BADRINDEX 4 /* sizes of io regions */ #define CONT_STAT_SIZE 10 #define ADC_FIFO_SIZE 4 @@ -1670,22 +1662,14 @@ static int cb_pcidas_attach(struct comedi_device *dev, "Failed to enable PCI device and request regions\n"); return -EIO; } - /* - * Initialize devpriv->control_status and devpriv->adc_fifo to point to - * their base address. - */ - devpriv->s5933_config = - pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); - devpriv->control_status = - pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); - devpriv->adc_fifo = - pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); - devpriv->pacer_counter_dio = - pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); - if (thisboard->ao_nchan) { - devpriv->ao_registers = - pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); - } + + devpriv->s5933_config = pci_resource_start(devpriv->pci_dev, 0); + devpriv->control_status = pci_resource_start(devpriv->pci_dev, 1); + devpriv->adc_fifo = pci_resource_start(devpriv->pci_dev, 2); + devpriv->pacer_counter_dio = pci_resource_start(devpriv->pci_dev, 3); + if (thisboard->ao_nchan) + devpriv->ao_registers = pci_resource_start(devpriv->pci_dev, 4); + /* disable and clear interrupts on amcc s5933 */ outl(INTCSR_INBOX_INTR_STATUS, devpriv->s5933_config + AMCC_OP_REG_INTCSR); -- GitLab From 193debd1987656a33773395e38c8427d2f02fbbc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:55:21 -0700 Subject: [PATCH 2017/5711] staging: comedi: cb_pcidas: remove CB_PCIDAS_DEBUG define This define enables some debug code that output a number of dev_dbg() messages. These might be useful for development but should not be in the final driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 34 ++-------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 4e5f1ba77ac7..e790ab0711c2 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -79,9 +79,6 @@ analog triggering on 1602 series #include "amcc_s5933.h" #include "comedi_fc.h" -#undef CB_PCIDAS_DEBUG /* disable debugging code */ -/* #define CB_PCIDAS_DEBUG enable debugging code */ - /* PCI vendor number of ComputerBoards/MeasurementComputing */ #define PCI_VENDOR_ID_CB 0x1307 #define TIMER_BASE 100 /* 10MHz master clock */ @@ -1092,10 +1089,6 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, bits |= PACER_INT; outw(bits, devpriv->control_status + ADCMUX_CONT); -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "sent 0x%x to adcmux control\n", bits); -#endif - /* load counters */ if (cmd->convert_src == TRIG_TIMER) cb_pcidas_load_counters(dev, &cmd->convert_arg, @@ -1119,10 +1112,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, } else { devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */ } -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", - devpriv->adc_fifo_bits); -#endif + /* enable (and clear) interrupts */ outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL, devpriv->control_status + INT_ADCFIFO); @@ -1146,9 +1136,6 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) bits |= BURSTE; outw(bits, devpriv->control_status + TRIG_CONTSTAT); -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "sent 0x%x to trig control\n", bits); -#endif return 0; } @@ -1322,10 +1309,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, /* enable dac half-full and empty interrupts */ spin_lock_irqsave(&dev->spinlock, flags); devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n", - devpriv->adc_fifo_bits); -#endif + /* enable and clear interrupts */ outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, devpriv->control_status + INT_ADCFIFO); @@ -1333,10 +1317,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, /* start dac */ devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "sent 0x%x to dac control\n", - devpriv->ao_control_bits); -#endif + spin_unlock_irqrestore(&dev->spinlock, flags); async->inttrig = NULL; @@ -1508,11 +1489,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) async->events = 0; s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); -#ifdef CB_PCIDAS_DEBUG - dev_dbg(dev->class_dev, "intcsr 0x%x\n", s5933_status); - dev_dbg(dev->class_dev, "mbef 0x%x\n", - inl(devpriv->s5933_config + AMCC_OP_REG_MBEF)); -#endif if ((INTCSR_INTR_ASSERTED & s5933_status) == 0) return IRQ_NONE; @@ -1524,10 +1500,6 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) devpriv->s5933_config + AMCC_OP_REG_INTCSR); status = inw(devpriv->control_status + INT_ADCFIFO); -#ifdef CB_PCIDAS_DEBUG - if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) - comedi_error(dev, "spurious interrupt"); -#endif /* check for analog output interrupt */ if (status & (DAHFI | DAEMI)) -- GitLab From 4466fc45007c346971ae537cc64e82a8a4961160 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:56:04 -0700 Subject: [PATCH 2018/5711] staging: comedi: cb_pcidas: remove unused io region size defines The defines for the size of the io regions are not used in the driver. Also, this information can be found using the pci helper pci_resource_len(). Remove the defines. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index e790ab0711c2..4b653c5edf53 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -89,12 +89,6 @@ analog triggering on 1602 series #define NUM_CHANNELS_8402 2 #define NUM_CHANNELS_DAC08 1 -/* sizes of io regions */ -#define CONT_STAT_SIZE 10 -#define ADC_FIFO_SIZE 4 -#define PACER_SIZE 12 -#define AO_SIZE 4 - /* Control/Status registers */ #define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */ #define INT_EOS 0x1 /* interrupt end of scan */ -- GitLab From 23e3cce3270b5f0d9c094c9bcb34d919713e02eb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:56:43 -0700 Subject: [PATCH 2019/5711] staging: comedi: cb_pcidas: simplify the boardinfo The boardinfo values 'has_ai_trig_gated' and 'has_ai_trig_invert' are both only set for the "1602" versions of the boards supported by this driver. Simplify the boardinfo, and the code, by replacing these two variables with one "is_1602" variable. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 41 +++++++++------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 4b653c5edf53..0c14582085f8 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -250,8 +250,7 @@ struct cb_pcidas_board { const struct comedi_lrange *ranges; enum trimpot_model trimpot; unsigned has_dac08:1; - unsigned has_ai_trig_gated:1; /* Tells if the AI trigger can be gated */ - unsigned has_ai_trig_invert:1; /* Tells if the AI trigger can be inverted */ + unsigned is_1602:1; }; static const struct cb_pcidas_board cb_pcidas_boards[] = { @@ -269,8 +268,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD8402, .has_dac08 = 1, - .has_ai_trig_gated = 1, - .has_ai_trig_invert = 1, + .is_1602 = 1, }, { .name = "pci-das1200", @@ -285,8 +283,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 0, - .has_ai_trig_invert = 0, + .is_1602 = 0, }, { .name = "pci-das1602/12", @@ -302,8 +299,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 1, - .has_ai_trig_invert = 1, + .is_1602 = 1, }, { .name = "pci-das1200/jr", @@ -318,8 +314,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 0, - .has_ai_trig_invert = 0, + .is_1602 = 0, }, { .name = "pci-das1602/16/jr", @@ -334,8 +329,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD8402, .has_dac08 = 1, - .has_ai_trig_gated = 1, - .has_ai_trig_invert = 1, + .is_1602 = 1, }, { .name = "pci-das1000", @@ -350,8 +344,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 0, - .has_ai_trig_invert = 0, + .is_1602 = 0, }, { .name = "pci-das1001", @@ -366,8 +359,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_alt_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 0, - .has_ai_trig_invert = 0, + .is_1602 = 0, }, { .name = "pci-das1002", @@ -382,8 +374,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .has_dac08 = 0, - .has_ai_trig_gated = 0, - .has_ai_trig_invert = 0, + .is_1602 = 0, }, }; @@ -938,8 +929,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT)); err++; } - if (!thisboard->has_ai_trig_invert && - (cmd->start_arg & CR_INVERT)) { + if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) { cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT); err++; } @@ -1118,11 +1108,12 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, bits |= SW_TRIGGER; else if (cmd->start_src == TRIG_EXT) { bits |= EXT_TRIGGER | TGEN | XTRCL; - if (thisboard->has_ai_trig_invert - && (cmd->start_arg & CR_INVERT)) - bits |= TGPOL; - if (thisboard->has_ai_trig_gated && (cmd->start_arg & CR_EDGE)) - bits |= TGSEL; + if (thisboard->is_1602) { + if (cmd->start_arg & CR_INVERT) + bits |= TGPOL; + if (cmd->start_arg & CR_EDGE) + bits |= TGSEL; + } } else { comedi_error(dev, "bug!"); return -1; -- GitLab From 17883d63b32390098e42cb1a0739d361e38b528e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:57:20 -0700 Subject: [PATCH 2020/5711] staging: comedi: cb_pcidas: cleanup the boardinfo 1 For aesthetic reasons, add whitespace to the boardinfo to improve readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 235 ++++++++++----------- 1 file changed, 114 insertions(+), 121 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 0c14582085f8..a5b3659bc1ca 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -255,127 +255,120 @@ struct cb_pcidas_board { static const struct cb_pcidas_board cb_pcidas_boards[] = { { - .name = "pci-das1602/16", - .device_id = 0x1, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 2, - .has_ao_fifo = 1, - .ao_scan_speed = 10000, - .fifo_size = 512, - .ranges = &cb_pcidas_ranges, - .trimpot = AD8402, - .has_dac08 = 1, - .is_1602 = 1, - }, - { - .name = "pci-das1200", - .device_id = 0xF, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 3200, - .ao_nchan = 2, - .has_ao_fifo = 0, - .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, - }, - { - .name = "pci-das1602/12", - .device_id = 0x10, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 3200, - .ao_nchan = 2, - .has_ao_fifo = 1, - .ao_scan_speed = 4000, - .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 1, - }, - { - .name = "pci-das1200/jr", - .device_id = 0x19, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 3200, - .ao_nchan = 0, - .has_ao_fifo = 0, - .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, - }, - { - .name = "pci-das1602/16/jr", - .device_id = 0x1C, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 0, - .has_ao_fifo = 0, - .fifo_size = 512, - .ranges = &cb_pcidas_ranges, - .trimpot = AD8402, - .has_dac08 = 1, - .is_1602 = 1, - }, - { - .name = "pci-das1000", - .device_id = 0x4C, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 4000, - .ao_nchan = 0, - .has_ao_fifo = 0, - .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, - }, - { - .name = "pci-das1001", - .device_id = 0x1a, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 6800, - .ao_nchan = 2, - .has_ao_fifo = 0, - .fifo_size = 1024, - .ranges = &cb_pcidas_alt_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, - }, - { - .name = "pci-das1002", - .device_id = 0x1b, - .ai_se_chans = 16, - .ai_diff_chans = 8, - .ai_bits = 12, - .ai_speed = 6800, - .ao_nchan = 2, - .has_ao_fifo = 0, - .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, - }, + .name = "pci-das1602/16", + .device_id = 0x1, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 2, + .has_ao_fifo = 1, + .ao_scan_speed = 10000, + .fifo_size = 512, + .ranges = &cb_pcidas_ranges, + .trimpot = AD8402, + .has_dac08 = 1, + .is_1602 = 1, + }, { + .name = "pci-das1200", + .device_id = 0xF, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 3200, + .ao_nchan = 2, + .has_ao_fifo = 0, + .fifo_size = 1024, + .ranges = &cb_pcidas_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 0, + }, { + .name = "pci-das1602/12", + .device_id = 0x10, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 3200, + .ao_nchan = 2, + .has_ao_fifo = 1, + .ao_scan_speed = 4000, + .fifo_size = 1024, + .ranges = &cb_pcidas_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 1, + }, { + .name = "pci-das1200/jr", + .device_id = 0x19, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 3200, + .ao_nchan = 0, + .has_ao_fifo = 0, + .fifo_size = 1024, + .ranges = &cb_pcidas_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 0, + }, { + .name = "pci-das1602/16/jr", + .device_id = 0x1C, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 0, + .has_ao_fifo = 0, + .fifo_size = 512, + .ranges = &cb_pcidas_ranges, + .trimpot = AD8402, + .has_dac08 = 1, + .is_1602 = 1, + }, { + .name = "pci-das1000", + .device_id = 0x4C, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 4000, + .ao_nchan = 0, + .has_ao_fifo = 0, + .fifo_size = 1024, + .ranges = &cb_pcidas_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 0, + }, { + .name = "pci-das1001", + .device_id = 0x1a, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 6800, + .ao_nchan = 2, + .has_ao_fifo = 0, + .fifo_size = 1024, + .ranges = &cb_pcidas_alt_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 0, + }, { + .name = "pci-das1002", + .device_id = 0x1b, + .ai_se_chans = 16, + .ai_diff_chans = 8, + .ai_bits = 12, + .ai_speed = 6800, + .ao_nchan = 2, + .has_ao_fifo = 0, + .fifo_size = 1024, + .ranges = &cb_pcidas_ranges, + .trimpot = AD7376, + .has_dac08 = 0, + .is_1602 = 0, + }, }; /* this structure is for data unique to this hardware driver. If -- GitLab From 0c5ecbb0b77833e8ac5c90b7652684ae5f16480f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:58:27 -0700 Subject: [PATCH 2021/5711] staging: comedi: cb_pcidas: cleanup the boardinfo 2 Remove all the boardinfo values that are = 0. They will default to that value. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index a5b3659bc1ca..f7090dec71c3 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -277,12 +277,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_bits = 12, .ai_speed = 3200, .ao_nchan = 2, - .has_ao_fifo = 0, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, }, { .name = "pci-das1602/12", .device_id = 0x10, @@ -296,7 +293,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - .has_dac08 = 0, .is_1602 = 1, }, { .name = "pci-das1200/jr", @@ -305,13 +301,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 3200, - .ao_nchan = 0, - .has_ao_fifo = 0, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, }, { .name = "pci-das1602/16/jr", .device_id = 0x1C, @@ -319,8 +311,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_diff_chans = 8, .ai_bits = 16, .ai_speed = 5000, - .ao_nchan = 0, - .has_ao_fifo = 0, .fifo_size = 512, .ranges = &cb_pcidas_ranges, .trimpot = AD8402, @@ -333,13 +323,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 4000, - .ao_nchan = 0, - .has_ao_fifo = 0, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, }, { .name = "pci-das1001", .device_id = 0x1a, @@ -348,12 +334,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, - .has_ao_fifo = 0, .fifo_size = 1024, .ranges = &cb_pcidas_alt_ranges, .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, }, { .name = "pci-das1002", .device_id = 0x1b, @@ -362,12 +345,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, - .has_ao_fifo = 0, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - .has_dac08 = 0, - .is_1602 = 0, }, }; -- GitLab From a605be0c68f4c7585255bdb5a8ddbc1782d829ad Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 17:59:17 -0700 Subject: [PATCH 2022/5711] staging: comedi: cb_pcidas: cleanup the boardinfo 3 Remove the ai_diff_chans variable. This option is not used in the driver. If it is used later, the value can be easily found by using ai_se_chans/2. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index f7090dec71c3..59b0f9116cd8 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -240,7 +240,6 @@ struct cb_pcidas_board { const char *name; unsigned short device_id; int ai_se_chans; /* Inputs in single-ended mode */ - int ai_diff_chans; /* Inputs in differential mode */ int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ int ao_nchan; /* number of analog out channels */ @@ -258,7 +257,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1602/16", .device_id = 0x1, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 16, .ai_speed = 5000, .ao_nchan = 2, @@ -273,7 +271,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1200", .device_id = 0xF, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 3200, .ao_nchan = 2, @@ -284,7 +281,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1602/12", .device_id = 0x10, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 3200, .ao_nchan = 2, @@ -298,7 +294,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1200/jr", .device_id = 0x19, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 3200, .fifo_size = 1024, @@ -308,7 +303,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1602/16/jr", .device_id = 0x1C, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 16, .ai_speed = 5000, .fifo_size = 512, @@ -320,7 +314,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1000", .device_id = 0x4C, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 4000, .fifo_size = 1024, @@ -330,7 +323,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1001", .device_id = 0x1a, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, @@ -341,7 +333,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .name = "pci-das1002", .device_id = 0x1b, .ai_se_chans = 16, - .ai_diff_chans = 8, .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, -- GitLab From 8f608fc8eefc9bff17a7139801eb4b4f571f262d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:00:19 -0700 Subject: [PATCH 2023/5711] staging: comedi: cb_pcidas: cleanup the boardinfo 4 For aesthetic reasons, rename the ai_se_chans variable to ai_nchan. It's a bit shorter and provides the necessary information about the variable. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 59b0f9116cd8..3cdd026767c1 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -239,7 +239,7 @@ enum trimpot_model { struct cb_pcidas_board { const char *name; unsigned short device_id; - int ai_se_chans; /* Inputs in single-ended mode */ + int ai_nchan; /* Inputs in single-ended mode */ int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ int ao_nchan; /* number of analog out channels */ @@ -256,7 +256,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { { .name = "pci-das1602/16", .device_id = 0x1, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 16, .ai_speed = 5000, .ao_nchan = 2, @@ -270,7 +270,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1200", .device_id = 0xF, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, .ao_nchan = 2, @@ -280,7 +280,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1602/12", .device_id = 0x10, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, .ao_nchan = 2, @@ -293,7 +293,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1200/jr", .device_id = 0x19, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, .fifo_size = 1024, @@ -302,7 +302,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1602/16/jr", .device_id = 0x1C, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 16, .ai_speed = 5000, .fifo_size = 512, @@ -313,7 +313,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1000", .device_id = 0x4C, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 4000, .fifo_size = 1024, @@ -322,7 +322,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1001", .device_id = 0x1a, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, @@ -332,7 +332,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, { .name = "pci-das1002", .device_id = 0x1b, - .ai_se_chans = 16, + .ai_nchan = 16, .ai_bits = 12, .ai_speed = 6800, .ao_nchan = 2, @@ -1615,8 +1615,8 @@ static int cb_pcidas_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; /* WARNING: Number of inputs in differential mode is ignored */ - s->n_chan = thisboard->ai_se_chans; - s->len_chanlist = thisboard->ai_se_chans; + s->n_chan = thisboard->ai_nchan; + s->len_chanlist = thisboard->ai_nchan; s->maxdata = (1 << thisboard->ai_bits) - 1; s->range_table = thisboard->ranges; s->insn_read = cb_pcidas_ai_rinsn; -- GitLab From f3c34b2fc6ccc36f171633fa86b3d59a36792c25 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:01:05 -0700 Subject: [PATCH 2024/5711] staging: comedi: cb_pcidas: cleanup ai_config_insn() Absorb the helper function ai_config_calibration_source() into ai_config_insn() and remove the static const variable that was in the helper function. Return an error code (-EINVAL) when appropriate and the number of data values used (insn->n) for success. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 30 ++++++++-------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 3cdd026767c1..a2901bb50e01 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -439,38 +439,28 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, return n; } -static int ai_config_calibration_source(struct comedi_device *dev, - unsigned int *data) -{ - struct cb_pcidas_private *devpriv = dev->private; - static const int num_calibration_sources = 8; - unsigned int source = data[1]; - - if (source >= num_calibration_sources) { - dev_err(dev->class_dev, "invalid calibration source: %i\n", - source); - return -EINVAL; - } - - devpriv->calibration_source = source; - - return 2; -} - static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct cb_pcidas_private *devpriv = dev->private; int id = data[0]; + unsigned int source = data[1]; switch (id) { case INSN_CONFIG_ALT_SOURCE: - return ai_config_calibration_source(dev, data); + if (source >= 8) { + dev_err(dev->class_dev, + "invalid calibration source: %i\n", + source); + return -EINVAL; + } + devpriv->calibration_source = source; break; default: return -EINVAL; break; } - return -EINVAL; + return insn->n; } /* analog output insn for pcidas-1000 and 1200 series */ -- GitLab From b8ac8c63429e8b354067e3dcaa549dc0b53be5d4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:01:51 -0700 Subject: [PATCH 2025/5711] staging: comedi: cb_pcidas: move the "find pci" dev_printk messages Move the dev_printk messages associated with the "find pci device" from the *attach function into the *find_pci_device function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index a2901bb50e01..9f883dd77b34 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1537,10 +1537,15 @@ static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev, continue; } } + dev_dbg(dev->class_dev, + "Found %s on bus %i, slot %i\n", + thisboard->name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); dev->board_ptr = thisboard; return pcidev; } } + dev_err(dev->class_dev, "No supported card found\n"); return NULL; } @@ -1558,15 +1563,9 @@ static int cb_pcidas_attach(struct comedi_device *dev, devpriv = dev->private; devpriv->pci_dev = cb_pcidas_find_pci_device(dev, it); - if (!devpriv->pci_dev) { - dev_err(dev->class_dev, "No supported card found\n"); + if (!devpriv->pci_dev) return -EIO; - } - thisboard = comedi_board(dev); - dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n", - thisboard->name, devpriv->pci_dev->bus->number, - PCI_SLOT(devpriv->pci_dev->devfn)); if (comedi_pci_enable(devpriv->pci_dev, "cb_pcidas")) { dev_err(dev->class_dev, -- GitLab From 0a5aed487645b13531b876775c1390afd20296a5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:02:40 -0700 Subject: [PATCH 2026/5711] staging: comedi: cb_pcidas: use the driver_name for the resource name Use the dev->driver->driver_name for the resource name passed to pci_request_regions(), by way of comedi_pci_enable(), and to request_irq() instead of the open coded "cb_pcidas". Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 9f883dd77b34..9379d2517702 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1567,7 +1567,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, return -EIO; thisboard = comedi_board(dev); - if (comedi_pci_enable(devpriv->pci_dev, "cb_pcidas")) { + if (comedi_pci_enable(devpriv->pci_dev, dev->driver->driver_name)) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); return -EIO; @@ -1585,7 +1585,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, devpriv->s5933_config + AMCC_OP_REG_INTCSR); if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, - IRQF_SHARED, "cb_pcidas", dev)) { + IRQF_SHARED, dev->driver->driver_name, dev)) { dev_dbg(dev->class_dev, "unable to allocate irq %d\n", devpriv->pci_dev->irq); return -EINVAL; -- GitLab From 4f0036ef09387a49b709d9b319ad93492e53d790 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:03:34 -0700 Subject: [PATCH 2027/5711] staging: comedi: cb_pcidas: check for failure of subdev_8255_init It's possible for subdev_8255_init() to fail due to its kzalloc(). Make sure to check for this failure and pass on the error code. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 9379d2517702..a0330714dd55 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1640,7 +1640,10 @@ static int cb_pcidas_attach(struct comedi_device *dev, /* 8255 */ s = dev->subdevices + 2; - subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); + ret = subdev_8255_init(dev, s, NULL, + devpriv->pacer_counter_dio + DIO_8255); + if (ret) + return ret; /* serial EEPROM, */ s = dev->subdevices + 3; -- GitLab From 93c58378b5498f6810a2f269dc3c9a13731c3cf7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:04:26 -0700 Subject: [PATCH 2028/5711] staging: comedi: cb_pcidas: fix a space before tab issue As reported by checkpatch.pl, spaces should not be used before tabs. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index a0330714dd55..ff08f9ec72df 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1063,7 +1063,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, else if (cmd->start_src == TRIG_EXT) { bits |= EXT_TRIGGER | TGEN | XTRCL; if (thisboard->is_1602) { - if (cmd->start_arg & CR_INVERT) + if (cmd->start_arg & CR_INVERT) bits |= TGPOL; if (cmd->start_arg & CR_EDGE) bits |= TGSEL; -- GitLab From 55acaf2d10d268d7db59877615955f910add5b1b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:05:12 -0700 Subject: [PATCH 2029/5711] staging: comedi: cb_pcidas: fix some > 80 char lines Fix some of the comments that cause checkpatch.pl to complain about WARNING: line over 80 characters. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index ff08f9ec72df..12fb087f2b47 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1043,12 +1043,16 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, devpriv->adc_fifo_bits |= INTE; devpriv->adc_fifo_bits &= ~INT_MASK; if (cmd->flags & TRIG_WAKE_EOS) { - if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) - devpriv->adc_fifo_bits |= INT_EOS; /* interrupt end of burst */ - else - devpriv->adc_fifo_bits |= INT_FNE; /* interrupt fifo not empty */ + if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) { + /* interrupt end of burst */ + devpriv->adc_fifo_bits |= INT_EOS; + } else { + /* interrupt fifo not empty */ + devpriv->adc_fifo_bits |= INT_FNE; + } } else { - devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */ + /* interrupt fifo half full */ + devpriv->adc_fifo_bits |= INT_FHF; } /* enable (and clear) interrupts */ @@ -1474,7 +1478,9 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) INT_ADCFIFO)) == 0) break; cfc_write_to_buffer(s, inw(devpriv->adc_fifo)); - if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */ + if (async->cmd.stop_src == TRIG_COUNT && + --devpriv->count == 0) { + /* end of acquisition */ cb_pcidas_cancel(dev, s); async->events |= COMEDI_CB_EOA; break; @@ -1620,7 +1626,10 @@ static int cb_pcidas_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; s->n_chan = thisboard->ao_nchan; - /* analog out resolution is the same as analog input resolution, so use ai_bits */ + /* + * analog out resolution is the same as + * analog input resolution, so use ai_bits + */ s->maxdata = (1 << thisboard->ai_bits) - 1; s->range_table = &cb_pcidas_ao_ranges; s->insn_read = cb_pcidas_ao_readback_insn; -- GitLab From 0c4ef0b90c4f77bb397e30c408118a1e0edbaddb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:06:08 -0700 Subject: [PATCH 2030/5711] staging: comedi: cb_pcidas: fix comments in *_cmdtest functions Remove some cut-and-paste comments from the skel driver in the *_cmdtest functions. Shorten some others to fix the checkpatch.pl complaints about WARNING: line over 80 characters. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 26 +++++----------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 12fb087f2b47..95ce54635932 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -809,14 +809,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, int tmp; int i, gain, start_chan; - /* cmdtest tests a particular command to see if it is valid. - * Using the cmdtest ioctl, a user can create a valid cmd - * and then have it executes by the cmd ioctl. - * - * cmdtest returns 1,2,3,4 or 0, depending on which tests - * the command passes. */ - - /* step 1: make sure trigger sources are trivially valid */ + /* step 1: trigger sources are trivially valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_NOW | TRIG_EXT; @@ -846,7 +839,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* step 2: trigger sources are unique and mutually compatible */ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) err++; @@ -872,7 +865,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, if (err) return 2; - /* step 3: make sure arguments are trivially compatible */ + /* step 3: arguments are trivially compatible */ switch (cmd->start_src) { case TRIG_EXT: @@ -1092,14 +1085,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* cmdtest tests a particular command to see if it is valid. - * Using the cmdtest ioctl, a user can create a valid cmd - * and then have it executes by the cmd ioctl. - * - * cmdtest returns 1,2,3,4 or 0, depending on which tests - * the command passes. */ - - /* step 1: make sure trigger sources are trivially valid */ + /* step 1: trigger sources are trivially valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_INT; @@ -1129,7 +1115,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* step 2: trigger sources are unique and mutually compatible */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) @@ -1140,7 +1126,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, if (err) return 2; - /* step 3: make sure arguments are trivially compatible */ + /* step 3: arguments are trivially compatible */ if (cmd->start_arg != 0) { cmd->start_arg = 0; -- GitLab From f6cf9a02600aa23780bc75da6ee7d315ce027db0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:06:52 -0700 Subject: [PATCH 2031/5711] staging: comedi: cb_pcidas: remove 'volatile' on private data variables As indicated by checkpatch.pl, "WARNING: Use of volatile is usually wrong: ...". The variables in the private data that are marked volatile don't need to be. Remove the volatile. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 95ce54635932..eba39b4f7247 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -357,16 +357,16 @@ struct cb_pcidas_private { /* divisors of master clock for analog input pacing */ unsigned int divisor1; unsigned int divisor2; - volatile unsigned int count; /* number of analog input samples remaining */ - volatile unsigned int adc_fifo_bits; /* bits to write to interrupt/adcfifo register */ - volatile unsigned int s5933_intcsr_bits; /* bits to write to amcc s5933 interrupt control/status register */ - volatile unsigned int ao_control_bits; /* bits to write to ao control and status register */ + unsigned int count; /* number of analog input samples remaining */ + unsigned int adc_fifo_bits; /* bits to write to interrupt/adcfifo register */ + unsigned int s5933_intcsr_bits; /* bits to write to amcc s5933 interrupt control/status register */ + unsigned int ao_control_bits; /* bits to write to ao control and status register */ short ai_buffer[AI_BUFFER_SIZE]; short ao_buffer[AO_BUFFER_SIZE]; /* divisors of master clock for analog output pacing */ unsigned int ao_divisor1; unsigned int ao_divisor2; - volatile unsigned int ao_count; /* number of analog output samples remaining */ + unsigned int ao_count; /* number of analog output samples remaining */ int ao_value[2]; /* remember what the analog outputs are set to, to allow readback */ unsigned int caldac_value[NUM_CHANNELS_8800]; /* for readback of caldac */ unsigned int trimpot_value[NUM_CHANNELS_8402]; /* for readback of trimpot */ -- GitLab From 0cdfbe157cd2244951568e6d3ffe3423ce7f2f50 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:07:32 -0700 Subject: [PATCH 2032/5711] staging: comedi: cb_pcidas: fix comments in private data struct A number of the comments in the private data struct definition are causing checkpatch.pl to complain about "WARNING: line over 80 characters". Fix the comments. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index eba39b4f7247..9e21e6818415 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -342,34 +342,35 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { }, }; -/* this structure is for data unique to this hardware driver. If - several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device struct. */ struct cb_pcidas_private { - /* would be useful for a PCI device */ struct pci_dev *pci_dev; - /* base addresses */ + /* base addresses */ unsigned long s5933_config; unsigned long control_status; unsigned long adc_fifo; unsigned long pacer_counter_dio; unsigned long ao_registers; - /* divisors of master clock for analog input pacing */ + /* divisors of master clock for analog input pacing */ unsigned int divisor1; unsigned int divisor2; - unsigned int count; /* number of analog input samples remaining */ - unsigned int adc_fifo_bits; /* bits to write to interrupt/adcfifo register */ - unsigned int s5933_intcsr_bits; /* bits to write to amcc s5933 interrupt control/status register */ - unsigned int ao_control_bits; /* bits to write to ao control and status register */ + /* number of analog input samples remaining */ + unsigned int count; + /* bits to write to registers */ + unsigned int adc_fifo_bits; + unsigned int s5933_intcsr_bits; + unsigned int ao_control_bits; + /* fifo buffers */ short ai_buffer[AI_BUFFER_SIZE]; short ao_buffer[AO_BUFFER_SIZE]; - /* divisors of master clock for analog output pacing */ + /* divisors of master clock for analog output pacing */ unsigned int ao_divisor1; unsigned int ao_divisor2; - unsigned int ao_count; /* number of analog output samples remaining */ - int ao_value[2]; /* remember what the analog outputs are set to, to allow readback */ - unsigned int caldac_value[NUM_CHANNELS_8800]; /* for readback of caldac */ - unsigned int trimpot_value[NUM_CHANNELS_8402]; /* for readback of trimpot */ + /* number of analog output samples remaining */ + unsigned int ao_count; + /* cached values for readback */ + int ao_value[2]; + unsigned int caldac_value[NUM_CHANNELS_8800]; + unsigned int trimpot_value[NUM_CHANNELS_8402]; unsigned int dac08_value; unsigned int calibration_source; }; -- GitLab From 7368348ccb51f652fea3f2554874ad11456fb9fc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:08:17 -0700 Subject: [PATCH 2033/5711] staging: comedi: cb_pcidas: change dac bit enums into defines The 'bits' for the DAC_CSR register are currently defined as enums. All the other registers use defines for the bit definitions. Change the dac bit enums to defines to follow the other registers. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 9e21e6818415..0188cf17cecb 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -140,11 +140,10 @@ analog triggering on 1602 series #define CAL_EN_BIT 0x4000 /* read calibration source instead of analog input channel 0 */ #define SERIAL_DATA_IN_BIT 0x8000 /* serial data stream going to 8800 and 7376 */ -#define DAC_CSR 0x8 /* dac control and status register */ -enum dac_csr_bits { - DACEN = 0x2, /* dac enable */ - DAC_MODE_UPDATE_BOTH = 0x80, /* update both dacs when dac0 is written */ -}; +#define DAC_CSR 0x8 /* dac control and status register */ +#define DACEN 0x02 /* dac enable */ +#define DAC_MODE_UPDATE_BOTH 0x80 /* update both dacs */ + static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range) { return (range & 0x3) << (8 + 2 * (channel & 0x1)); @@ -156,14 +155,13 @@ static inline unsigned int DAC_RANGE_MASK(unsigned int channel) }; /* bits for 1602 series only */ -enum dac_csr_bits_1602 { - DAC_EMPTY = 0x1, /* dac fifo empty, read, write clear */ - DAC_START = 0x4, /* start/arm dac fifo operations */ - DAC_PACER_MASK = 0x18, /* bits that set dac pacer source */ - DAC_PACER_INT = 0x8, /* dac internal pacing */ - DAC_PACER_EXT_FALL = 0x10, /* dac external pacing, falling edge */ - DAC_PACER_EXT_RISE = 0x18, /* dac external pacing, rising edge */ -}; +#define DAC_EMPTY 0x1 /* fifo empty, read, write clear */ +#define DAC_START 0x4 /* start/arm fifo operations */ +#define DAC_PACER_MASK 0x18 /* bits that set pacer source */ +#define DAC_PACER_INT 0x8 /* int. pacing */ +#define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */ +#define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */ + static inline unsigned int DAC_CHAN_EN(unsigned int channel) { return 1 << (5 + (channel & 0x1)); /* enable channel 0 or 1 */ -- GitLab From 6993197b75686f79a2b6107d51ba57180ba33212 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:09:01 -0700 Subject: [PATCH 2034/5711] staging: comedi: cb_pcidas: add whitespace to all the #define's Add whitespace to all the #define's in the driver in order to improve the readability. Fix all the comments that are, or already were, > 80 characters. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 141 +++++++++++---------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 0188cf17cecb..c0d934097e54 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -81,64 +81,65 @@ analog triggering on 1602 series /* PCI vendor number of ComputerBoards/MeasurementComputing */ #define PCI_VENDOR_ID_CB 0x1307 -#define TIMER_BASE 100 /* 10MHz master clock */ -#define AI_BUFFER_SIZE 1024 /* maximum fifo size of any supported board */ -#define AO_BUFFER_SIZE 1024 /* maximum fifo size of any supported board */ -#define NUM_CHANNELS_8800 8 -#define NUM_CHANNELS_7376 1 -#define NUM_CHANNELS_8402 2 -#define NUM_CHANNELS_DAC08 1 + +#define TIMER_BASE 100 /* 10MHz master clock */ +#define AI_BUFFER_SIZE 1024 /* max ai fifo size */ +#define AO_BUFFER_SIZE 1024 /* max ao fifo size */ +#define NUM_CHANNELS_8800 8 +#define NUM_CHANNELS_7376 1 +#define NUM_CHANNELS_8402 2 +#define NUM_CHANNELS_DAC08 1 /* Control/Status registers */ -#define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */ -#define INT_EOS 0x1 /* interrupt end of scan */ -#define INT_FHF 0x2 /* interrupt fifo half full */ -#define INT_FNE 0x3 /* interrupt fifo not empty */ -#define INT_MASK 0x3 /* mask of interrupt select bits */ -#define INTE 0x4 /* interrupt enable */ -#define DAHFIE 0x8 /* dac half full interrupt enable */ -#define EOAIE 0x10 /* end of acquisition interrupt enable */ -#define DAHFI 0x20 /* dac half full read status / write interrupt clear */ -#define EOAI 0x40 /* read end of acq. interrupt status / write clear */ -#define INT 0x80 /* read interrupt status / write clear */ -#define EOBI 0x200 /* read end of burst interrupt status */ -#define ADHFI 0x400 /* read half-full interrupt status */ -#define ADNEI 0x800 /* read fifo not empty interrupt latch status */ -#define ADNE 0x1000 /* read, fifo not empty (realtime, not latched) status */ -#define DAEMIE 0x1000 /* write, dac empty interrupt enable */ -#define LADFUL 0x2000 /* read fifo overflow / write clear */ -#define DAEMI 0x4000 /* dac fifo empty interrupt status / write clear */ - -#define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL register */ -#define BEGIN_SCAN(x) ((x) & 0xf) -#define END_SCAN(x) (((x) & 0xf) << 4) -#define GAIN_BITS(x) (((x) & 0x3) << 8) -#define UNIP 0x800 /* Analog front-end unipolar for range */ -#define SE 0x400 /* Inputs in single-ended mode */ -#define PACER_MASK 0x3000 /* pacer source bits */ -#define PACER_INT 0x1000 /* internal pacer */ -#define PACER_EXT_FALL 0x2000 /* external falling edge */ -#define PACER_EXT_RISE 0x3000 /* external rising edge */ -#define EOC 0x4000 /* adc not busy */ - -#define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */ -#define SW_TRIGGER 0x1 /* software start trigger */ -#define EXT_TRIGGER 0x2 /* external start trigger */ -#define ANALOG_TRIGGER 0x3 /* external analog trigger */ -#define TRIGGER_MASK 0x3 /* mask of bits that determine start trigger */ -#define TGPOL 0x04 /* invert the edge/level of the external trigger (1602 only) */ -#define TGSEL 0x08 /* if set edge triggered, otherwise level trigerred (1602 only) */ -#define TGEN 0x10 /* enable external start trigger */ -#define BURSTE 0x20 /* burst mode enable */ -#define XTRCL 0x80 /* clear external trigger */ - -#define CALIBRATION_REG 6 /* CALIBRATION register */ -#define SELECT_8800_BIT 0x100 /* select 8800 caldac */ -#define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */ -#define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */ +#define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */ +#define INT_EOS 0x1 /* int end of scan */ +#define INT_FHF 0x2 /* int fifo half full */ +#define INT_FNE 0x3 /* int fifo not empty */ +#define INT_MASK 0x3 /* mask of int select bits */ +#define INTE 0x4 /* int enable */ +#define DAHFIE 0x8 /* dac half full int enable */ +#define EOAIE 0x10 /* end of acq. int enable */ +#define DAHFI 0x20 /* dac half full status / clear */ +#define EOAI 0x40 /* end of acq. int status / clear */ +#define INT 0x80 /* int status / clear */ +#define EOBI 0x200 /* end of burst int status */ +#define ADHFI 0x400 /* half-full int status */ +#define ADNEI 0x800 /* fifo not empty int status (latch) */ +#define ADNE 0x1000 /* fifo not empty status (realtime) */ +#define DAEMIE 0x1000 /* dac empty int enable */ +#define LADFUL 0x2000 /* fifo overflow / clear */ +#define DAEMI 0x4000 /* dac fifo empty int status / clear */ + +#define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL reg */ +#define BEGIN_SCAN(x) ((x) & 0xf) +#define END_SCAN(x) (((x) & 0xf) << 4) +#define GAIN_BITS(x) (((x) & 0x3) << 8) +#define UNIP 0x800 /* Analog front-end unipolar mode */ +#define SE 0x400 /* Inputs in single-ended mode */ +#define PACER_MASK 0x3000 /* pacer source bits */ +#define PACER_INT 0x1000 /* int. pacer */ +#define PACER_EXT_FALL 0x2000 /* ext. falling edge */ +#define PACER_EXT_RISE 0x3000 /* ext. rising edge */ +#define EOC 0x4000 /* adc not busy */ + +#define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */ +#define SW_TRIGGER 0x1 /* software start trigger */ +#define EXT_TRIGGER 0x2 /* ext. start trigger */ +#define ANALOG_TRIGGER 0x3 /* ext. analog trigger */ +#define TRIGGER_MASK 0x3 /* start trigger mask */ +#define TGPOL 0x04 /* invert trigger (1602 only) */ +#define TGSEL 0x08 /* edge/level trigerred (1602 only) */ +#define TGEN 0x10 /* enable external start trigger */ +#define BURSTE 0x20 /* burst mode enable */ +#define XTRCL 0x80 /* clear external trigger */ + +#define CALIBRATION_REG 6 /* CALIBRATION register */ +#define SELECT_8800_BIT 0x100 /* select 8800 caldac */ +#define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */ +#define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */ #define CAL_SRC_BITS(x) (((x) & 0x7) << 11) -#define CAL_EN_BIT 0x4000 /* read calibration source instead of analog input channel 0 */ -#define SERIAL_DATA_IN_BIT 0x8000 /* serial data stream going to 8800 and 7376 */ +#define CAL_EN_BIT 0x4000 /* calibration source enable */ +#define SERIAL_DATA_IN_BIT 0x8000 /* serial data bit going to caldac */ #define DAC_CSR 0x8 /* dac control and status register */ #define DACEN 0x02 /* dac enable */ @@ -155,12 +156,12 @@ static inline unsigned int DAC_RANGE_MASK(unsigned int channel) }; /* bits for 1602 series only */ -#define DAC_EMPTY 0x1 /* fifo empty, read, write clear */ -#define DAC_START 0x4 /* start/arm fifo operations */ -#define DAC_PACER_MASK 0x18 /* bits that set pacer source */ -#define DAC_PACER_INT 0x8 /* int. pacing */ -#define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */ -#define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */ +#define DAC_EMPTY 0x1 /* fifo empty, read, write clear */ +#define DAC_START 0x4 /* start/arm fifo operations */ +#define DAC_PACER_MASK 0x18 /* bits that set pacer source */ +#define DAC_PACER_INT 0x8 /* int. pacing */ +#define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */ +#define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */ static inline unsigned int DAC_CHAN_EN(unsigned int channel) { @@ -168,13 +169,13 @@ static inline unsigned int DAC_CHAN_EN(unsigned int channel) }; /* analog input fifo */ -#define ADCDATA 0 /* ADC DATA register */ -#define ADCFIFOCLR 2 /* ADC FIFO CLEAR */ +#define ADCDATA 0 /* ADC DATA register */ +#define ADCFIFOCLR 2 /* ADC FIFO CLEAR */ /* pacer, counter, dio registers */ -#define ADC8254 0 -#define DIO_8255 4 -#define DAC8254 8 +#define ADC8254 0 +#define DIO_8255 4 +#define DAC8254 8 /* analog output registers for 100x, 1200 series */ static inline unsigned int DAC_DATA_REG(unsigned int channel) @@ -183,11 +184,11 @@ static inline unsigned int DAC_DATA_REG(unsigned int channel) } /* analog output registers for 1602 series*/ -#define DACDATA 0 /* DAC DATA register */ -#define DACFIFOCLR 2 /* DAC FIFO CLEAR */ +#define DACDATA 0 /* DAC DATA register */ +#define DACFIFOCLR 2 /* DAC FIFO CLEAR */ + +#define IS_UNIPOLAR 0x4 /* unipolar range mask */ -/* bit in hexadecimal representation of range index that indicates unipolar input range */ -#define IS_UNIPOLAR 0x4 /* analog input ranges for most boards */ static const struct comedi_lrange cb_pcidas_ranges = { 8, -- GitLab From d478b5f6f4d48a130533efb8da98b5526772f219 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:09:40 -0700 Subject: [PATCH 2035/5711] staging: comedi: cb_pcidas: fix remaining checkpatch.pl issues Fix the remaining three "WARNING: line over 80 characters" issues reported by checkpatch.pl. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index c0d934097e54..2a282d3c9c2c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -28,7 +28,8 @@ */ /* Driver: cb_pcidas -Description: MeasurementComputing PCI-DAS series with the AMCC S5933 PCI controller +Description: MeasurementComputing PCI-DAS series + with the AMCC S5933 PCI controller Author: Ivan Martinez , Frank Mori Hess Updated: 2003-3-11 @@ -243,7 +244,7 @@ struct cb_pcidas_board { int ai_speed; /* fastest conversion period in ns */ int ao_nchan; /* number of analog out channels */ int has_ao_fifo; /* analog output has fifo */ - int ao_scan_speed; /* analog output speed for 1602 series (for a scan, not conversion) */ + int ao_scan_speed; /* analog output scan speed for 1602 series */ int fifo_size; /* number of samples fifo can hold */ const struct comedi_lrange *ranges; enum trimpot_model trimpot; @@ -525,8 +526,6 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, return 1; } -/* analog output readback insn */ -/* XXX loses track of analog output value back after an analog ouput command is executed */ static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, -- GitLab From b78332daf47b624bef6220f1acf64ee49d38c1ad Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:10:22 -0700 Subject: [PATCH 2036/5711] staging: comedi: cb_pcidas: cleanup cb_pcidas_ao_fifo_winsn() Create local variables for the channel and range in order to cleanup to mask/set of the ao_control_bits. Remove the extra space in all the comments. Return the number of data parameters used (insn->n) to indicate success instead of the open coded '1'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 2a282d3c9c2c..bbbb9e43d504 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -498,32 +498,29 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; - int channel; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned long flags; - /* clear dac fifo */ + /* clear dac fifo */ outw(0, devpriv->ao_registers + DACFIFOCLR); - /* set channel and range */ - channel = CR_CHAN(insn->chanspec); + /* set channel and range */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->ao_control_bits &= - ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) & - ~DAC_PACER_MASK; - devpriv->ao_control_bits |= - DACEN | DAC_RANGE(channel, - CR_RANGE(insn-> - chanspec)) | DAC_CHAN_EN(channel) | - DAC_START; + devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & + ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK); + devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) | + DAC_CHAN_EN(chan) | DAC_START); outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); spin_unlock_irqrestore(&dev->spinlock, flags); - /* remember value for readback */ - devpriv->ao_value[channel] = data[0]; - /* send data */ + /* remember value for readback */ + devpriv->ao_value[chan] = data[0]; + + /* send data */ outw(data[0], devpriv->ao_registers + DACDATA); - return 1; + return insn->n; } static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, -- GitLab From 7671896c4f7f66116798d7314a03995eddac4134 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:10:59 -0700 Subject: [PATCH 2037/5711] staging: comedi: cb_pcidas: cleanup cb_pcidas_ao_nofifo_winsn() Create local variables for the channel and range in order to cleanup to mask/set of the ao_control_bits. Remove the extra space in all the comments. Return the number of data parameters used (insn->n) to indicate success instead of the open coded '1'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index bbbb9e43d504..b00ccad6022b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -471,25 +471,25 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; - int channel; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned long flags; - /* set channel and range */ - channel = CR_CHAN(insn->chanspec); + /* set channel and range */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->ao_control_bits &= - ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel); - devpriv->ao_control_bits |= - DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec)); + devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH & + ~DAC_RANGE_MASK(chan)); + devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range)); outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); spin_unlock_irqrestore(&dev->spinlock, flags); - /* remember value for readback */ - devpriv->ao_value[channel] = data[0]; - /* send data */ - outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel)); + /* remember value for readback */ + devpriv->ao_value[chan] = data[0]; + + /* send data */ + outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan)); - return 1; + return insn->n; } /* analog output insn for pcidas-1602 series */ -- GitLab From f66faa576f084bed49d4a34e0bc2289ff0d07a70 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:11:38 -0700 Subject: [PATCH 2038/5711] staging: comedi: cb_pcidas: cleanup cb_pcidas_ai_rinsn() Create local variables for the channel, range, and aref in order to make the remaining code a bit cleaner. Remove the extra space in all the comments. Remove the 'static const int timeout' and just use the open coded value in the loop. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 35 ++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index b00ccad6022b..1479325ab7ea 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -382,36 +382,33 @@ static inline unsigned int cal_enable_bits(struct comedi_device *dev) return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); } -/* - * "instructions" read/write data in "one-shot" or "software-triggered" - * mode. - */ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; - int n, i; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); unsigned int bits; - static const int timeout = 10000; - int channel; - /* enable calibration input if appropriate */ + int n, i; + + /* enable calibration input if appropriate */ if (insn->chanspec & CR_ALT_SOURCE) { outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - channel = 0; + chan = 0; } else { outw(0, devpriv->control_status + CALIBRATION_REG); - channel = CR_CHAN(insn->chanspec); } - /* set mux limits and gain */ - bits = BEGIN_SCAN(channel) | - END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec)); - /* set unipolar/bipolar */ - if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR) + + /* set mux limits and gain */ + bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range); + /* set unipolar/bipolar */ + if (range & IS_UNIPOLAR) bits |= UNIP; - /* set singleended/differential */ - if (CR_AREF(insn->chanspec) != AREF_DIFF) + /* set single-ended/differential */ + if (aref != AREF_DIFF) bits |= SE; outw(bits, devpriv->control_status + ADCMUX_CONT); @@ -425,11 +422,11 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, /* wait for conversion to end */ /* return -ETIMEDOUT if there is a timeout */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < 10000; i++) { if (inw(devpriv->control_status + ADCMUX_CONT) & EOC) break; } - if (i == timeout) + if (i == 10000) return -ETIMEDOUT; /* read data */ -- GitLab From b436356dcc67a665da07441ab113e9a5652073e5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Jun 2012 18:12:15 -0700 Subject: [PATCH 2039/5711] staging: comedi: cb_pcidas: cleanup dac08_write() Reverse the logic of the test against the cached value so that the function only has one exit point. Make the logic of the dac write a bit clearer by create a local variable for the address used in the outw() calls and masking the value to write and setting the enable bits before doing the outw() calls. Add a comment just to make sure it's clear. Also, add a comment about the 'return 1;'. This should be insn->n which is the number of data parameters used to do the dac08_write_insn() but the insn is not a parameter to this function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 28 ++++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 1479325ab7ea..3ba75afe4e05 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -662,23 +662,25 @@ static int caldac_read_insn(struct comedi_device *dev, static int dac08_write(struct comedi_device *dev, unsigned int value) { struct cb_pcidas_private *devpriv = dev->private; + unsigned long cal_reg; - if (devpriv->dac08_value == value) - return 1; + if (devpriv->dac08_value != value) { + devpriv->dac08_value = value; - devpriv->dac08_value = value; + cal_reg = devpriv->control_status + CALIBRATION_REG; - outw(cal_enable_bits(dev) | (value & 0xff), - devpriv->control_status + CALIBRATION_REG); - udelay(1); - outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff), - devpriv->control_status + CALIBRATION_REG); - udelay(1); - outw(cal_enable_bits(dev) | (value & 0xff), - devpriv->control_status + CALIBRATION_REG); - udelay(1); + value &= 0xff; + value |= cal_enable_bits(dev); - return 1; + /* latch the new value into the caldac */ + outw(value, cal_reg); + udelay(1); + outw(value | SELECT_DAC08_BIT, cal_reg); + udelay(1); + outw(value, cal_reg); + udelay(1); + } + return 1; /* insn->n */ } static int dac08_write_insn(struct comedi_device *dev, -- GitLab From ac55ca32ca40de3cb52a1ca73ca4a9250e07eefd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 09:17:17 -0700 Subject: [PATCH 2040/5711] staging: comedi: cb_pcidas: fix dac08_write_insn() As pointed out by Ian Abbott, the comedi INSN_WRITE instructions are meant to iterate over, and write, all the data[] passed from the comedi core. Modify dac08_write_insn() to work as intended. Since doc08_write_insn() now returns the proper response to the core, make the dac08_write() helper return void. Signed-off-by: H Hartley Sweeten Reported-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 3ba75afe4e05..301444e09433 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -659,7 +659,7 @@ static int caldac_read_insn(struct comedi_device *dev, } /* 1602/16 pregain offset */ -static int dac08_write(struct comedi_device *dev, unsigned int value) +static void dac08_write(struct comedi_device *dev, unsigned int value) { struct cb_pcidas_private *devpriv = dev->private; unsigned long cal_reg; @@ -680,14 +680,18 @@ static int dac08_write(struct comedi_device *dev, unsigned int value) outw(value, cal_reg); udelay(1); } - return 1; /* insn->n */ } static int dac08_write_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - return dac08_write(dev, data[0]); + int i; + + for (i = 0; i < insn->n; i++) + dac08_write(dev, data[i]); + + return insn->n; } static int dac08_read_insn(struct comedi_device *dev, -- GitLab From 949a18d39d75e92f516d562befe5447d368ab67d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:53:28 -0700 Subject: [PATCH 2041/5711] staging: comedi: adl_pci6208: remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables where used. Use the comedi_board() helper to get the 'thisboard' pointer. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 79f6765c46c1..720f870d8271 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -82,21 +82,17 @@ static const struct pci6208_board pci6208_boards[] = { } }; -/* Will be initialized in pci6208_find device(). */ -#define thisboard ((const struct pci6208_board *)dev->board_ptr) - struct pci6208_private { int data; struct pci_dev *pci_dev; /* for a PCI device */ unsigned int ao_readback[2]; /* Used for AO readback */ }; -#define devpriv ((struct pci6208_private *)dev->private) - static int pci6208_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci6208_private *devpriv = dev->private; int i = 0, Data_Read; unsigned short chan = CR_CHAN(insn->chanspec); unsigned long invert = 1 << (16 - 1); @@ -123,6 +119,7 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci6208_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -183,6 +180,7 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, static int pci6208_find_device(struct comedi_device *dev, int bus, int slot) { + struct pci6208_private *devpriv = dev->private; struct pci_dev *pci_dev = NULL; int i; @@ -278,19 +276,23 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, static int pci6208_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct pci6208_board *thisboard; + struct pci6208_private *devpriv; struct comedi_subdevice *s; int retval; unsigned long io_base; printk(KERN_INFO "comedi%d: pci6208: ", dev->minor); - retval = alloc_private(dev, sizeof(struct pci6208_private)); + retval = alloc_private(dev, sizeof(*devpriv)); if (retval < 0) return retval; + devpriv = dev->private; retval = pci6208_find_device(dev, it->options[0], it->options[1]); if (retval < 0) return retval; + thisboard = comedi_board(dev); retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor); if (retval < 0) @@ -330,6 +332,8 @@ static int pci6208_attach(struct comedi_device *dev, static void pci6208_detach(struct comedi_device *dev) { + struct pci6208_private *devpriv = dev->private; + if (devpriv && devpriv->pci_dev) { if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); -- GitLab From cde6f08a5e28e2f0c08ecadd98465bfb48e01472 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:55:19 -0700 Subject: [PATCH 2042/5711] staging: comedi: adl_pci6208: refactor pci6208_find_device() Make the "find pci device" functions consistent in the comedi drivers. Hopefully well be able to move it into the core... Refactor the "find pci device" function to return a pointer to the found struct pci_dev instead of an error code. Also, change some of the tests to reduce the indent level of the code. Pass the struct comedi_devconfig pointer to the function instead of the bus/slot numbers. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 81 ++++++++------------ 1 file changed, 32 insertions(+), 49 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 720f870d8271..5f073c576e14 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -178,60 +178,43 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, /* return 1; */ /* } */ -static int pci6208_find_device(struct comedi_device *dev, int bus, int slot) +static struct pci_dev *pci6208_find_device(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct pci6208_private *devpriv = dev->private; + const struct pci6208_board *thisboard; struct pci_dev *pci_dev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; for_each_pci_dev(pci_dev) { - if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) { - for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { - if (pci6208_boards[i].dev_id == - pci_dev->device) { - /* - * was a particular bus/slot requested? - */ - if ((bus != 0) || (slot != 0)) { - /* - * are we on the - * wrong bus/slot? - */ - if (pci_dev->bus->number - != bus || - PCI_SLOT(pci_dev->devfn) - != slot) { - continue; - } - } - dev->board_ptr = pci6208_boards + i; - goto found; - } + if (pci_dev->vendor != PCI_VENDOR_ID_ADLINK) + continue; + for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { + thisboard = &pci6208_boards[i]; + if (thisboard->dev_id != pci_dev->device) + continue; + /* was a particular bus/slot requested? */ + if (bus || slot) { + /* are we on the wrong bus/slot? */ + if (pci_dev->bus->number != bus || + PCI_SLOT(pci_dev->devfn) != slot) + continue; } + dev_dbg(dev->class_dev, + "Found %s on bus %d, slot, %d, irq=%d\n", + thisboard->name, + pci_dev->bus->number, + PCI_SLOT(pci_dev->devfn), + pci_dev->irq); + dev->board_ptr = thisboard; + return pci_dev; } } - - printk(KERN_ERR "comedi%d: no supported board found! " - "(req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); - return -EIO; - -found: - printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n", - dev->minor, - pci6208_boards[i].name, - pci_dev->bus->number, - PCI_SLOT(pci_dev->devfn), - PCI_FUNC(pci_dev->devfn), pci_dev->irq); - - /* TODO: Warn about non-tested boards. */ - /* switch(board->device_id) */ - /* { */ - /* }; */ - - devpriv->pci_dev = pci_dev; - - return 0; + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; } static int @@ -289,9 +272,9 @@ static int pci6208_attach(struct comedi_device *dev, return retval; devpriv = dev->private; - retval = pci6208_find_device(dev, it->options[0], it->options[1]); - if (retval < 0) - return retval; + devpriv->pci_dev = pci6208_find_device(dev, it); + if (!devpriv->pci_dev) + return -EIO; thisboard = comedi_board(dev); retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor); -- GitLab From 745c22a016b28912fdc802656186da59121edbb1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:56:03 -0700 Subject: [PATCH 2043/5711] staging: comedi: adl_pci6208: remove the boardinfo 'ao_bits' All the boards supported by this driver have 16-bit DACs. The ao_bits variable in the boardinfo is commented out anyway. Just remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 5f073c576e14..f949d201f90e 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -58,7 +58,6 @@ struct pci6208_board { const char *name; unsigned short dev_id; /* `lspci` will show you this */ int ao_chans; - /* int ao_bits; */ }; static const struct pci6208_board pci6208_boards[] = { @@ -66,19 +65,16 @@ static const struct pci6208_board pci6208_boards[] = { .name = "pci6208v", .dev_id = 0x6208, // not sure .ao_chans = 8 - // , .ao_bits = 16 }, { .name = "pci6216v", .dev_id = 0x6208, // not sure .ao_chans = 16 - // , .ao_bits = 16 }, */ { .name = "pci6208a", .dev_id = 0x6208, .ao_chans = 8 - /* , .ao_bits = 16 */ } }; -- GitLab From 7b6afad100f50130e6c5a347760e83b83aaa7cc7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:56:43 -0700 Subject: [PATCH 2044/5711] staging: comedi: adl_pci6208: document the register map of the device Add defines for the register map of the device. These will be used to clarify the code. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index f949d201f90e..b6a843941df4 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -53,6 +53,18 @@ References: */ #include "../comedidev.h" +/* + * PCI-6208/6216-GL register map + */ +#define PCI6208_AO_CONTROL(x) (0x00 + (2 * (x))) +#define PCI6208_AO_STATUS 0x00 +#define PCI6208_AO_STATUS_DATA_SEND (1 << 0) +#define PCI6208_DIO 0x40 +#define PCI6208_DIO_DO_MASK (0x0f) +#define PCI6208_DIO_DO_SHIFT (0) +#define PCI6208_DIO_DI_MASK (0xf0) +#define PCI6208_DIO_DI_SHIFT (4) + /* Board descriptions */ struct pci6208_board { const char *name; -- GitLab From a28c98524c2634a5d84151de253ee7e99e38564d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:57:22 -0700 Subject: [PATCH 2045/5711] staging: comedi: adl_pci6208: cleanup pci6208_pci_setup() The "local configuration register" stuff is not required. The io base/range are only queried for use in a kernel message that it just added noise. Similar with the io range for the actual io base used by the driver. Remove both printk's and all the unnecessary code. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index b6a843941df4..a96fac42a3a0 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -229,7 +229,7 @@ static int pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, int dev_minor) { - unsigned long io_base, io_range, lcr_io_base, lcr_io_range; + unsigned long io_base; /* Enable PCI device and request regions */ if (comedi_pci_enable(pci_dev, "adl_pci6208") < 0) { @@ -238,28 +238,11 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, dev_minor); return -EIO; } - /* Read local configuration register - * base address [PCI_BASE_ADDRESS #1]. - */ - lcr_io_base = pci_resource_start(pci_dev, 1); - lcr_io_range = pci_resource_len(pci_dev, 1); - - printk(KERN_INFO "comedi%d: local config registers at address" - " 0x%4lx [0x%4lx]\n", - dev_minor, lcr_io_base, lcr_io_range); /* Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. */ io_base = pci_resource_start(pci_dev, 2); - io_range = pci_resource_end(pci_dev, 2) - io_base + 1; - - printk("comedi%d: 6208 registers at address 0x%4lx [0x%4lx]\n", - dev_minor, io_base, io_range); *io_base_ptr = io_base; - /* devpriv->io_range = io_range; */ - /* devpriv->is_valid=0; */ - /* devpriv->lcr_io_base=lcr_io_base; */ - /* devpriv->lcr_io_range=lcr_io_range; */ return 0; } -- GitLab From db7c275d9ffd2c58648b1bf023ab62cf993ddfac Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:58:03 -0700 Subject: [PATCH 2046/5711] staging: comedi: adl_pci6208: remove pci6208_pci_setup() Refactor pci6208_pci_setup() into the attach function. This function simply enables the pci device and gets the PCI iobase address used by the driver. There's no need for a separate function to handle this. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 34 ++++---------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index a96fac42a3a0..e2ca685dd299 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -225,28 +225,6 @@ static struct pci_dev *pci6208_find_device(struct comedi_device *dev, return NULL; } -static int -pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, - int dev_minor) -{ - unsigned long io_base; - - /* Enable PCI device and request regions */ - if (comedi_pci_enable(pci_dev, "adl_pci6208") < 0) { - printk(KERN_ERR "comedi%d: Failed to enable PCI device " - "and request regions\n", - dev_minor); - return -EIO; - } - - /* Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. */ - io_base = pci_resource_start(pci_dev, 2); - - *io_base_ptr = io_base; - - return 0; -} - static int pci6208_attach(struct comedi_device *dev, struct comedi_devconfig *it) { @@ -254,7 +232,6 @@ static int pci6208_attach(struct comedi_device *dev, struct pci6208_private *devpriv; struct comedi_subdevice *s; int retval; - unsigned long io_base; printk(KERN_INFO "comedi%d: pci6208: ", dev->minor); @@ -268,11 +245,14 @@ static int pci6208_attach(struct comedi_device *dev, return -EIO; thisboard = comedi_board(dev); - retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor); - if (retval < 0) - return retval; + if (comedi_pci_enable(devpriv->pci_dev, "adl_pci6208") < 0) { + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); + return -EIO; + } + + dev->iobase = pci_resource_start(devpriv->pci_dev, 2); - dev->iobase = io_base; dev->board_name = thisboard->name; retval = comedi_alloc_subdevices(dev, 2); -- GitLab From 9d639b6b252759e6333aa576645f25624c4b9a99 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 14:59:19 -0700 Subject: [PATCH 2047/5711] staging: comedi: adl_pci6208: pass on the error code from comedi_pci_enable Return the actual error code from comedi_pci_enable instead of assuming -EIO on failure. Also, shorten the local variable name 'retval' to 'ret'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index e2ca685dd299..8ec266052860 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -231,13 +231,13 @@ static int pci6208_attach(struct comedi_device *dev, const struct pci6208_board *thisboard; struct pci6208_private *devpriv; struct comedi_subdevice *s; - int retval; + int ret; printk(KERN_INFO "comedi%d: pci6208: ", dev->minor); - retval = alloc_private(dev, sizeof(*devpriv)); - if (retval < 0) - return retval; + ret = alloc_private(dev, sizeof(*devpriv)); + if (ret < 0) + return ret; devpriv = dev->private; devpriv->pci_dev = pci6208_find_device(dev, it); @@ -245,19 +245,20 @@ static int pci6208_attach(struct comedi_device *dev, return -EIO; thisboard = comedi_board(dev); - if (comedi_pci_enable(devpriv->pci_dev, "adl_pci6208") < 0) { + ret = comedi_pci_enable(devpriv->pci_dev, "adl_pci6208"); + if (ret) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); - return -EIO; + return ret; } dev->iobase = pci_resource_start(devpriv->pci_dev, 2); dev->board_name = thisboard->name; - retval = comedi_alloc_subdevices(dev, 2); - if (retval) - return retval; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; s = dev->subdevices + 0; /* analog output subdevice */ -- GitLab From b4dda059056a9be086fc95abe2a7410b87e6c33f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:00:02 -0700 Subject: [PATCH 2048/5711] staging: comedi: adl_pci6208: consolidate the attach messages Consolidate the attach messages into one dev_info() output at the end of a successful attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 8ec266052860..13cdbcc9eb13 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -233,8 +233,6 @@ static int pci6208_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - printk(KERN_INFO "comedi%d: pci6208: ", dev->minor); - ret = alloc_private(dev, sizeof(*devpriv)); if (ret < 0) return ret; @@ -280,7 +278,8 @@ static int pci6208_attach(struct comedi_device *dev, /* s->insn_bits = pci6208_dio_insn_bits; */ /* s->insn_config = pci6208_dio_insn_config; */ - printk(KERN_INFO "attached\n"); + dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", + dev->driver->driver_name, dev->board_name, dev->iobase); return 1; } -- GitLab From fc2536fd814ea1e4399ccbfc913b5742e467320a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:00:50 -0700 Subject: [PATCH 2049/5711] staging: comedi: adl_pci6208: fix the digital i/o subdevice The PCI-6208 board has 4 digital outputs and 4 digital inputs. The support for the digital i/o subdevice was commented out and the code was just cut-and-paste from the skel driver. Enable the digital i/o subdevice by uncommenting the code and fixing the insn_bits and insn_config functions. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 106 +++++++++---------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 13cdbcc9eb13..e3f459baa142 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -137,54 +137,45 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, return i; } -/* DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write */ -/* static int pci6208_dio_insn_bits(struct comedi_device *dev, - * struct comedi_subdevice *s, */ -/* struct comedi_insn *insn,unsigned int *data) */ -/* { */ - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ -/* if(data[0]){ */ -/* s->state &= ~data[0]; */ -/* s->state |= data[0]&data[1]; */ - /* Write out the new digital output lines */ - /* outw(s->state,dev->iobase + SKEL_DIO); */ -/* } */ - - /* on return, data[1] contains the value of the digital - * input and output lines. */ - /* data[1]=inw(dev->iobase + SKEL_DIO); */ - /* or we could just return the software copy of the output values if - * it was a purely digital output subdevice */ - /* data[1]=s->state; */ - -/* return insn->n; */ -/* } */ - -/* static int pci6208_dio_insn_config(struct comedi_device *dev, - * struct comedi_subdevice *s, */ -/* struct comedi_insn *insn,unsigned int *data) */ -/* { */ -/* int chan=CR_CHAN(insn->chanspec); */ - - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ - -/* if(data[0]==COMEDI_OUTPUT){ */ -/* s->io_bits |= 1<io_bits &= ~(1<io_bits,dev->iobase + SKEL_DIO_CONFIG); */ - -/* return 1; */ -/* } */ +static int pci6208_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int mask = data[0] & PCI6208_DIO_DO_MASK; + unsigned int bits = data[1]; + + if (mask) { + s->state &= ~mask; + s->state |= bits & mask; + + outw(s->state, dev->iobase + PCI6208_DIO); + } + + s->state = inw(dev->iobase + PCI6208_DIO); + data[1] = s->state; + + return insn->n; +} + +static int pci6208_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + int chan = CR_CHAN(insn->chanspec); + unsigned int mask = 1 << chan; + + switch (data[0]) { + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; + break; + default: + return -EINVAL; + } + + return insn->n; +} static struct pci_dev *pci6208_find_device(struct comedi_device *dev, struct comedi_devconfig *it) @@ -268,15 +259,18 @@ static int pci6208_attach(struct comedi_device *dev, s->insn_write = pci6208_ao_winsn; s->insn_read = pci6208_ao_rinsn; - /* s=dev->subdevices+1; */ + s = dev->subdevices + 1; /* digital i/o subdevice */ - /* s->type=COMEDI_SUBD_DIO; */ - /* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */ - /* s->n_chan=16; */ - /* s->maxdata=1; */ - /* s->range_table=&range_digital; */ - /* s->insn_bits = pci6208_dio_insn_bits; */ - /* s->insn_config = pci6208_dio_insn_config; */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci6208_dio_insn_bits; + s->insn_config = pci6208_dio_insn_config; + + s->io_bits = 0x0f; + s->state = inw(dev->iobase + PCI6208_DIO); dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", dev->driver->driver_name, dev->board_name, dev->iobase); -- GitLab From 111b62e48139767a42fc87b422f39b5909c27ac6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:01:26 -0700 Subject: [PATCH 2050/5711] staging: comedi: adl_pci6208: add whitespace to the subdev init Add whitespace to the subdev initialization and remove the unnecessary comments to improve readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index e3f459baa142..b65fed78e442 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -251,26 +251,26 @@ static int pci6208_attach(struct comedi_device *dev, s = dev->subdevices + 0; /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; /* anything else to add here?? */ - s->n_chan = thisboard->ao_chans; - s->maxdata = 0xffff; /* 16-bit DAC */ - s->range_table = &range_bipolar10; /* this needs to be checked. */ - s->insn_write = pci6208_ao_winsn; - s->insn_read = pci6208_ao_rinsn; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = pci6208_ao_winsn; + s->insn_read = pci6208_ao_rinsn; s = dev->subdevices + 1; /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci6208_dio_insn_bits; - s->insn_config = pci6208_dio_insn_config; - - s->io_bits = 0x0f; - s->state = inw(dev->iobase + PCI6208_DIO); + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci6208_dio_insn_bits; + s->insn_config = pci6208_dio_insn_config; + + s->io_bits = 0x0f; + s->state = inw(dev->iobase + PCI6208_DIO); dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", dev->driver->driver_name, dev->board_name, dev->iobase); -- GitLab From 98bcf9119cbcab67768a548bcb6dfc2b9464cb96 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:01:58 -0700 Subject: [PATCH 2051/5711] staging: comedi: adl_pci6208: return '0' for successful attach The comedi core expects a < 0 value during the attach to indicate an error. The normal 'success' return for the kernel is '0' so use that here. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index b65fed78e442..39bdf32d8efb 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -275,7 +275,7 @@ static int pci6208_attach(struct comedi_device *dev, dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", dev->driver->driver_name, dev->board_name, dev->iobase); - return 1; + return 0; } static void pci6208_detach(struct comedi_device *dev) -- GitLab From dcff1681cb49b2b2be3a3cddee620a81fc81e8e6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:02:53 -0700 Subject: [PATCH 2052/5711] staging: comedi: adl_pci6208: remove the bogus pci devices Remove the commented out pci device entries in the MODULE_DEVICE_TABLE as well as the associated boardinfo, which is also commented out. Add some whitespace to the boardinfo to improve readability. This driver should also support the pci-6216 card which has an additional 8 analog outputs (16 total). But the device id needs to be determined. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 22 ++++---------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 39bdf32d8efb..fe97db234808 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -73,21 +73,11 @@ struct pci6208_board { }; static const struct pci6208_board pci6208_boards[] = { - /*{ - .name = "pci6208v", - .dev_id = 0x6208, // not sure - .ao_chans = 8 - }, - { - .name = "pci6216v", - .dev_id = 0x6208, // not sure - .ao_chans = 16 - }, */ { - .name = "pci6208a", - .dev_id = 0x6208, - .ao_chans = 8 - } + .name = "pci6208a", + .dev_id = 0x6208, + .ao_chans = 8, + }, }; struct pci6208_private { @@ -307,11 +297,7 @@ static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev) comedi_pci_auto_unconfig(dev); } -/* This is used by modprobe to translate PCI IDs to drivers. Should - * only be used for PCI and ISA-PnP devices */ static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = { - /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ - /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) }, { 0 } }; -- GitLab From a7c6de4cf6712771155778c454a762cc2b38e12d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:03:31 -0700 Subject: [PATCH 2053/5711] staging: comedi: adl_pci6208: remove some useless comments Remove a number of useless comments that are cut-and-paste from the skel driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 25 ++++---------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index fe97db234808..18ca4009d89a 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -41,16 +41,7 @@ References: - adl_pci9111.c copied the entire pci setup section - adl_pci9118.c */ -/* - * These headers should be followed by a blank line, and any comments - * you wish to say about the driver. The comment area is the place - * to put any known bugs, limitations, unsupported features, supported - * command triggers, whether or not commands are supported on particular - * subdevices, etc. - * - * Somewhere in the comment should be information about configuration - * options that are used with comedi_config. - */ + #include "../comedidev.h" /* @@ -65,10 +56,9 @@ References: #define PCI6208_DIO_DI_MASK (0xf0) #define PCI6208_DIO_DI_SHIFT (4) -/* Board descriptions */ struct pci6208_board { const char *name; - unsigned short dev_id; /* `lspci` will show you this */ + unsigned short dev_id; int ao_chans; }; @@ -82,8 +72,8 @@ static const struct pci6208_board pci6208_boards[] = { struct pci6208_private { int data; - struct pci_dev *pci_dev; /* for a PCI device */ - unsigned int ao_readback[2]; /* Used for AO readback */ + struct pci_dev *pci_dev; + unsigned int ao_readback[2]; }; static int pci6208_ao_winsn(struct comedi_device *dev, @@ -95,11 +85,9 @@ static int pci6208_ao_winsn(struct comedi_device *dev, unsigned short chan = CR_CHAN(insn->chanspec); unsigned long invert = 1 << (16 - 1); unsigned long out_value; - /* Writing a list of values to an AO channel is probably not - * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { out_value = data[i] ^ invert; - /* a typical programming sequence */ do { Data_Read = (inw(dev->iobase) & 1); } while (Data_Read); @@ -107,12 +95,9 @@ static int pci6208_ao_winsn(struct comedi_device *dev, devpriv->ao_readback[chan] = out_value; } - /* return the number of samples read/written */ return i; } -/* AO subdevices should have a read insn as well as a write insn. - * Usually this means copying a value stored in devpriv. */ static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) -- GitLab From 149b98d1ea4e5d798cd7f954a239ed512c3bf7e5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:04:04 -0700 Subject: [PATCH 2054/5711] staging: comedi: adl_pci6208: remove unused variable in the private data The 'data' variable in the private data struct is not used by the driver. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 18ca4009d89a..dcaebfc22586 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -71,7 +71,6 @@ static const struct pci6208_board pci6208_boards[] = { }; struct pci6208_private { - int data; struct pci_dev *pci_dev; unsigned int ao_readback[2]; }; -- GitLab From 5c67df8b98316fbfede8d4d6bac64d52d4327357 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:04:47 -0700 Subject: [PATCH 2055/5711] staging: comedi: adl_pci6208: fix the ao_readback variable size The 'ao_readback' variable in the private data struct is used to cache the last value written to the analog output DAC channels. The PCI-6208 has 8 analog output channels but the variable only allowed space to cache 2 values. Since the PCI-6216 board could be supported by this driver and it has 16 analog outputs, create a define for the maximum number of channels and use that to set the size of 'ao_readback'. For now, set the max to 8 to save space since the PCI-6216 is not currently supported. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index dcaebfc22586..d15f0cbc2e67 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -56,6 +56,8 @@ References: #define PCI6208_DIO_DI_MASK (0xf0) #define PCI6208_DIO_DI_SHIFT (4) +#define PCI6208_MAX_AO_CHANNELS 8 + struct pci6208_board { const char *name; unsigned short dev_id; @@ -72,7 +74,7 @@ static const struct pci6208_board pci6208_boards[] = { struct pci6208_private { struct pci_dev *pci_dev; - unsigned int ao_readback[2]; + unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS]; }; static int pci6208_ao_winsn(struct comedi_device *dev, -- GitLab From 8366404bf1c034d902af06a6a6d88fe77a2cc7fb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:06:14 -0700 Subject: [PATCH 2056/5711] staging: comedi: adl_pci6208: cleanup pci6208_ao_winsn() Use the defines for the register map to make the code a bit clearer. Shorten or rename some of the local variables for the same reason. Only the last value written to the DAC needs to be cached in the ao_readback variable. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index d15f0cbc2e67..712087801be2 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -82,21 +82,24 @@ static int pci6208_ao_winsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci6208_private *devpriv = dev->private; - int i = 0, Data_Read; - unsigned short chan = CR_CHAN(insn->chanspec); + int chan = CR_CHAN(insn->chanspec); unsigned long invert = 1 << (16 - 1); - unsigned long out_value; + unsigned long value = 0; + unsigned short status; + int i; for (i = 0; i < insn->n; i++) { - out_value = data[i] ^ invert; + value = data[i] ^ invert; + do { - Data_Read = (inw(dev->iobase) & 1); - } while (Data_Read); - outw(out_value, dev->iobase + (0x02 * chan)); - devpriv->ao_readback[chan] = out_value; + status = inw(dev->iobase + PCI6208_AO_STATUS); + } while (status & PCI6208_AO_STATUS_DATA_SEND); + + outw(value, dev->iobase + PCI6208_AO_CONTROL(chan)); } + devpriv->ao_readback[chan] = value; - return i; + return insn->n; } static int pci6208_ao_rinsn(struct comedi_device *dev, -- GitLab From 7c1e5bc7544db67985fed627cba206fc5dee6405 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:07:05 -0700 Subject: [PATCH 2057/5711] staging: comedi: adl_pci6208: cleanup pci6208_ao_rinsn() For aesthetic reasons, reorder the local variables and change the return value to 'insn->n'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 712087801be2..aa2db5d532af 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -107,13 +107,13 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci6208_private *devpriv = dev->private; - int i; int chan = CR_CHAN(insn->chanspec); + int i; for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; - return i; + return insn->n; } static int pci6208_dio_insn_bits(struct comedi_device *dev, -- GitLab From 2d993c242fea1dc41395a40fd7001127afa3b090 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:07:56 -0700 Subject: [PATCH 2058/5711] staging: comedi: adl_pci6208: cleanup pci6208_attach() For aesthetic reasons, set the dev->board_name as soon as the thisboard pointer is available. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index aa2db5d532af..cb14ffd9967e 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -213,17 +213,16 @@ static int pci6208_attach(struct comedi_device *dev, return -EIO; thisboard = comedi_board(dev); + dev->board_name = thisboard->name; + ret = comedi_pci_enable(devpriv->pci_dev, "adl_pci6208"); if (ret) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); return ret; } - dev->iobase = pci_resource_start(devpriv->pci_dev, 2); - dev->board_name = thisboard->name; - ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; -- GitLab From 404f99910eb06b92e034112533bab997569dc0d4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Jun 2012 15:08:39 -0700 Subject: [PATCH 2059/5711] staging: comedi: adl_pci6208: use the driver_name for the resource name Use the dev->driver->driver_name for the resource name passed to pci_request_regions(), by way of comedi_pci_enable(), instead of the open coded string "adl_pci6208". Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci6208.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index cb14ffd9967e..487fd4a8124a 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -215,7 +215,7 @@ static int pci6208_attach(struct comedi_device *dev, dev->board_name = thisboard->name; - ret = comedi_pci_enable(devpriv->pci_dev, "adl_pci6208"); + ret = comedi_pci_enable(devpriv->pci_dev, dev->driver->driver_name); if (ret) { dev_err(dev->class_dev, "Failed to enable PCI device and request regions\n"); -- GitLab From 6f37e28821c38ea1981cef26ca6187cf307ea612 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:35:26 -0700 Subject: [PATCH 2060/5711] staging: comedi: ni_670x: use module_comedi_pci_driver Refactor the driver to use the module_comedi_pci_driver() helper. This gets rid of some of the module boilerplate code. For aesthetic reasons, rename the comedi_driver and pci_driver to follow the convention of the other comedi pci drivers. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 90 +++++++++--------------- 1 file changed, 33 insertions(+), 57 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 9032baccf3aa..cea43debc2ef 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -88,14 +88,6 @@ static const struct ni_670x_board ni_670x_boards[] = { }, }; -static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c90)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1920)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, ni_670x_pci_table); - #define thisboard ((struct ni_670x_board *)dev->board_ptr) struct ni_670x_private { @@ -109,55 +101,6 @@ struct ni_670x_private { #define devpriv ((struct ni_670x_private *)dev->private) #define n_ni_670x_boards ARRAY_SIZE(ni_670x_boards) -static int ni_670x_attach(struct comedi_device *dev, - struct comedi_devconfig *it); -static void ni_670x_detach(struct comedi_device *dev); - -static struct comedi_driver driver_ni_670x = { - .driver_name = "ni_670x", - .module = THIS_MODULE, - .attach = ni_670x_attach, - .detach = ni_670x_detach, -}; - -static int __devinit driver_ni_670x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - return comedi_pci_auto_config(dev, &driver_ni_670x); -} - -static void __devexit driver_ni_670x_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static struct pci_driver driver_ni_670x_pci_driver = { - .id_table = ni_670x_pci_table, - .probe = &driver_ni_670x_pci_probe, - .remove = __devexit_p(&driver_ni_670x_pci_remove) -}; - -static int __init driver_ni_670x_init_module(void) -{ - int retval; - - retval = comedi_driver_register(&driver_ni_670x); - if (retval < 0) - return retval; - - driver_ni_670x_pci_driver.name = (char *)driver_ni_670x.driver_name; - return pci_register_driver(&driver_ni_670x_pci_driver); -} - -static void __exit driver_ni_670x_cleanup_module(void) -{ - pci_unregister_driver(&driver_ni_670x_pci_driver); - comedi_driver_unregister(&driver_ni_670x); -} - -module_init(driver_ni_670x_init_module); -module_exit(driver_ni_670x_cleanup_module); - static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot); @@ -377,6 +320,39 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) return -EIO; } +static struct comedi_driver ni_670x_driver = { + .driver_name = "ni_670x", + .module = THIS_MODULE, + .attach = ni_670x_attach, + .detach = ni_670x_detach, +}; + +static int __devinit ni_670x_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &ni_670x_driver); +} + +static void __devexit ni_670x_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c90) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1920) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, ni_670x_pci_table); + +static struct pci_driver ni_670x_pci_driver = { + .name ="ni_670x", + .id_table = ni_670x_pci_table, + .probe = ni_670x_pci_probe, + .remove = __devexit_p(ni_670x_pci_remove), +}; +module_comedi_pci_driver(ni_670x_driver, ni_670x_pci_driver); + MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -- GitLab From 944a2f111f5cb82c46b75a4990aa3afa4b243b35 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:36:09 -0700 Subject: [PATCH 2061/5711] staging: comedi: ni_670x: remove forward declarations Move the attach and detach functions to remove the need for the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 182 +++++++++++------------ 1 file changed, 83 insertions(+), 99 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index cea43debc2ef..e9270afdb582 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -103,105 +103,6 @@ struct ni_670x_private { static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; -static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot); - -static int ni_670x_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_670x_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_670x_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_670x_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); - -static int ni_670x_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - struct comedi_subdevice *s; - int ret; - int i; - - printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor); - - ret = alloc_private(dev, sizeof(struct ni_670x_private)); - if (ret < 0) - return ret; - - ret = ni_670x_find_device(dev, it->options[0], it->options[1]); - if (ret < 0) - return ret; - - ret = mite_setup(devpriv->mite); - if (ret < 0) { - printk(KERN_WARNING "error setting up mite\n"); - return ret; - } - dev->board_name = thisboard->name; - dev->irq = mite_irq(devpriv->mite); - printk(KERN_INFO " %s", dev->board_name); - - ret = comedi_alloc_subdevices(dev, 2); - if (ret) - return ret; - - s = dev->subdevices + 0; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; - s->maxdata = 0xffff; - if (s->n_chan == 32) { - const struct comedi_lrange **range_table_list; - - range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, - GFP_KERNEL); - if (!range_table_list) - return -ENOMEM; - s->range_table_list = range_table_list; - for (i = 0; i < 16; i++) { - range_table_list[i] = &range_bipolar10; - range_table_list[16 + i] = &range_0_20mA; - } - } else { - s->range_table = &range_bipolar10; - } - s->insn_write = &ni_670x_ao_winsn; - s->insn_read = &ni_670x_ao_rinsn; - - s = dev->subdevices + 1; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = ni_670x_dio_insn_bits; - s->insn_config = ni_670x_dio_insn_config; - - /* Config of misc registers */ - writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET); - /* Config of ao registers */ - writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); - - printk(KERN_INFO "attached\n"); - - return 1; -} - -static void ni_670x_detach(struct comedi_device *dev) -{ - kfree(dev->subdevices[0].range_table_list); - if (dev->private && devpriv->mite) - mite_unsetup(devpriv->mite); - if (dev->irq) - free_irq(dev->irq, dev); -} - static int ni_670x_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -320,6 +221,89 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) return -EIO; } +static int ni_670x_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct comedi_subdevice *s; + int ret; + int i; + + printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor); + + ret = alloc_private(dev, sizeof(struct ni_670x_private)); + if (ret < 0) + return ret; + + ret = ni_670x_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + ret = mite_setup(devpriv->mite); + if (ret < 0) { + printk(KERN_WARNING "error setting up mite\n"); + return ret; + } + dev->board_name = thisboard->name; + dev->irq = mite_irq(devpriv->mite); + printk(KERN_INFO " %s", dev->board_name); + + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = 0xffff; + if (s->n_chan == 32) { + const struct comedi_lrange **range_table_list; + + range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, + GFP_KERNEL); + if (!range_table_list) + return -ENOMEM; + s->range_table_list = range_table_list; + for (i = 0; i < 16; i++) { + range_table_list[i] = &range_bipolar10; + range_table_list[16 + i] = &range_0_20mA; + } + } else { + s->range_table = &range_bipolar10; + } + s->insn_write = &ni_670x_ao_winsn; + s->insn_read = &ni_670x_ao_rinsn; + + s = dev->subdevices + 1; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_670x_dio_insn_bits; + s->insn_config = ni_670x_dio_insn_config; + + /* Config of misc registers */ + writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET); + /* Config of ao registers */ + writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); + + printk(KERN_INFO "attached\n"); + + return 1; +} + +static void ni_670x_detach(struct comedi_device *dev) +{ + kfree(dev->subdevices[0].range_table_list); + if (dev->private && devpriv->mite) + mite_unsetup(devpriv->mite); + if (dev->irq) + free_irq(dev->irq, dev); +} + static struct comedi_driver ni_670x_driver = { .driver_name = "ni_670x", .module = THIS_MODULE, -- GitLab From 289a40339149300c42308afd917a5c9dbbc9bcd9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:36:45 -0700 Subject: [PATCH 2062/5711] staging: comedi: ni_670x: remove thisboard and devpriv macros The 'thisboard' and 'devpriv' macros rely on a local variable having a specific name and yield pointers derived from that local variable. Replace the macros with local variables where used. Use the comedi_board() helper to get the 'thisboard' pointer. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index e9270afdb582..b75eed4388c6 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -88,8 +88,6 @@ static const struct ni_670x_board ni_670x_boards[] = { }, }; -#define thisboard ((struct ni_670x_board *)dev->board_ptr) - struct ni_670x_private { struct mite_struct *mite; @@ -98,7 +96,6 @@ struct ni_670x_private { unsigned int ao_readback[32]; }; -#define devpriv ((struct ni_670x_private *)dev->private) #define n_ni_670x_boards ARRAY_SIZE(ni_670x_boards) static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; @@ -107,6 +104,7 @@ static int ni_670x_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct ni_670x_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -137,6 +135,7 @@ static int ni_670x_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct ni_670x_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -150,6 +149,8 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct ni_670x_private *devpriv = dev->private; + /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { @@ -170,6 +171,7 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct ni_670x_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); switch (data[0]) { @@ -195,6 +197,7 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev, static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) { + struct ni_670x_private *devpriv = dev->private; struct mite_struct *mite; int i; @@ -224,19 +227,23 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) static int ni_670x_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct ni_670x_board *thisboard; + struct ni_670x_private *devpriv; struct comedi_subdevice *s; int ret; int i; printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor); - ret = alloc_private(dev, sizeof(struct ni_670x_private)); + ret = alloc_private(dev, sizeof(*devpriv)); if (ret < 0) return ret; + devpriv = dev->private; ret = ni_670x_find_device(dev, it->options[0], it->options[1]); if (ret < 0) return ret; + thisboard = comedi_board(dev); ret = mite_setup(devpriv->mite); if (ret < 0) { @@ -297,8 +304,10 @@ static int ni_670x_attach(struct comedi_device *dev, static void ni_670x_detach(struct comedi_device *dev) { + struct ni_670x_private *devpriv = dev->private; + kfree(dev->subdevices[0].range_table_list); - if (dev->private && devpriv->mite) + if (devpriv && devpriv->mite) mite_unsetup(devpriv->mite); if (dev->irq) free_irq(dev->irq, dev); -- GitLab From 2be036653663f809d1034d365f8285a967e589da Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:37:25 -0700 Subject: [PATCH 2063/5711] staging: comedi: ni_670x: remove n_ni_670x_boards macro This macro is simply the ARRAY_SIZE() of the boardinfo. Just use the ARRAY_SIZE and remove the macro. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index b75eed4388c6..d53d20c6392a 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -96,8 +96,6 @@ struct ni_670x_private { unsigned int ao_readback[32]; }; -#define n_ni_670x_boards ARRAY_SIZE(ni_670x_boards) - static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; static int ni_670x_ao_winsn(struct comedi_device *dev, @@ -210,7 +208,7 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) continue; } - for (i = 0; i < n_ni_670x_boards; i++) { + for (i = 0; i < ARRAY_SIZE(ni_670x_boards); i++) { if (mite_device_id(mite) == ni_670x_boards[i].dev_id) { dev->board_ptr = ni_670x_boards + i; devpriv->mite = mite; -- GitLab From b48ad330d56a6cce7897132d9cb68cc2f19358e8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:38:18 -0700 Subject: [PATCH 2064/5711] staging: comedi: ni_670x: change printk's to cleaned up dev_printk's Convert all the prink's in this file to dev_prink's. Change the INFO message in ni_670x_find_device into a dev_warn(). This message is only displayed if a matching device was not found. A warning is more appropriate here than info. Consolidate the attach messages into one dev_info() output after the successful attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index d53d20c6392a..c9c72c51f323 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -217,7 +217,7 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) } } } - printk(KERN_INFO "no device found\n"); + dev_warn(dev->class_dev, "no device found\n"); mite_list_devices(); return -EIO; } @@ -231,8 +231,6 @@ static int ni_670x_attach(struct comedi_device *dev, int ret; int i; - printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor); - ret = alloc_private(dev, sizeof(*devpriv)); if (ret < 0) return ret; @@ -245,12 +243,11 @@ static int ni_670x_attach(struct comedi_device *dev, ret = mite_setup(devpriv->mite); if (ret < 0) { - printk(KERN_WARNING "error setting up mite\n"); + dev_warn(dev->class_dev, "error setting up mite\n"); return ret; } dev->board_name = thisboard->name; dev->irq = mite_irq(devpriv->mite); - printk(KERN_INFO " %s", dev->board_name); ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -295,7 +292,8 @@ static int ni_670x_attach(struct comedi_device *dev, /* Config of ao registers */ writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); - printk(KERN_INFO "attached\n"); + dev_info(dev->class_dev, "%s: %s attached\n", + dev->driver->driver_name, dev->board_name); return 1; } -- GitLab From 464c94514c703bc61c3f85db397582aa8f17cf9d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:38:54 -0700 Subject: [PATCH 2065/5711] staging: comedi: ni_670x: return '0' for successful attach The comedi core expects a < 0 value during the attach to indicate an error. The normal 'success' return for the kernel is '0' so use that here. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index c9c72c51f323..bab964477118 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -295,7 +295,7 @@ static int ni_670x_attach(struct comedi_device *dev, dev_info(dev->class_dev, "%s: %s attached\n", dev->driver->driver_name, dev->board_name); - return 1; + return 0; } static void ni_670x_detach(struct comedi_device *dev) -- GitLab From 70fcd1b7a6be4f4f60f4d05beeb3976bb0eaf6a2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:39:45 -0700 Subject: [PATCH 2066/5711] staging: comedi: ni_670x: fix dereference of an invalid pointer The attach if this driver can fail before the subdevices are allocated. If the attach fails the comedi core will call the detach routine to allow the driver to do it's cleanup. We need to make sure that the subdevice allocation was successful before trying to dereference subdevice[0] to free the allocated range table list. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index bab964477118..46f373a0c0ca 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -301,8 +301,13 @@ static int ni_670x_attach(struct comedi_device *dev, static void ni_670x_detach(struct comedi_device *dev) { struct ni_670x_private *devpriv = dev->private; + struct comedi_subdevice *s; - kfree(dev->subdevices[0].range_table_list); + if (dev->n_subdevices) { + s = dev->subdevices + 0; + if (s) + kfree(s->range_table_list); + } if (devpriv && devpriv->mite) mite_unsetup(devpriv->mite); if (dev->irq) -- GitLab From 04b136b68d3c46480d0297efae56d736cd4ac379 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:40:23 -0700 Subject: [PATCH 2067/5711] staging: comedi: ni_670x: cleanup the boardinfo For aesthetic reasons, reorder the boardinfo struct so that the 'name' pointer is first. Also, add some whitespace to the boardinfo to improve readability. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 34 +++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 46f373a0c0ca..1d3590e4386e 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -61,31 +61,29 @@ Commands are not supported. /* Board description*/ struct ni_670x_board { - unsigned short dev_id; const char *name; + unsigned short dev_id; unsigned short ao_chans; unsigned short ao_bits; }; static const struct ni_670x_board ni_670x_boards[] = { { - .dev_id = 0x2c90, - .name = "PCI-6703", - .ao_chans = 16, - .ao_bits = 16, - }, - { - .dev_id = 0x1920, - .name = "PXI-6704", - .ao_chans = 32, - .ao_bits = 16, - }, - { - .dev_id = 0x1290, - .name = "PCI-6704", - .ao_chans = 32, - .ao_bits = 16, - }, + .name = "PCI-6703", + .dev_id = 0x2c90, + .ao_chans = 16, + .ao_bits = 16, + }, { + .name = "PXI-6704", + .dev_id = 0x1920, + .ao_chans = 32, + .ao_bits = 16, + }, { + .name = "PCI-6704", + .dev_id = 0x1290, + .ao_chans = 32, + .ao_bits = 16, + }, }; struct ni_670x_private { -- GitLab From ebbc09797ee5caf3e3bb5419a4ed930d2781e23b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:41:10 -0700 Subject: [PATCH 2068/5711] staging: comedi: ni_670x: cleanup ni_670x_dio_insn_bits() Add local variable for the io_addr, mask. and bits used in this function so that the comments are not needed and the writel/readl calls are a bit cleaner. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 1d3590e4386e..86e9e706da85 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -146,19 +146,19 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct ni_670x_private *devpriv = dev->private; + void __iomem *io_addr = devpriv->mite->daq_io_addr + + DIO_PORT0_DATA_OFFSET; + unsigned int mask = data[0]; + unsigned int bits = data[1]; - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - writel(s->state, - devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET); + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); + + writel(s->state, io_addr); } - /* on return, data[1] contains the value of the digital - * input lines. */ - data[1] = readl(devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET); + data[1] = readl(io_addr); return insn->n; } -- GitLab From 442bcd237296bc2ffcfcf9c1f243385674bef285 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 17:41:47 -0700 Subject: [PATCH 2069/5711] staging: comedi: ni_670x: removve unused 'ao_bits' All the NI 670x boards have 16-bit anaolog output DACs. The 'ao_bits' in the boardinfo is not used so remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_670x.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 86e9e706da85..9c57618f2c5b 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -64,7 +64,6 @@ struct ni_670x_board { const char *name; unsigned short dev_id; unsigned short ao_chans; - unsigned short ao_bits; }; static const struct ni_670x_board ni_670x_boards[] = { @@ -72,17 +71,14 @@ static const struct ni_670x_board ni_670x_boards[] = { .name = "PCI-6703", .dev_id = 0x2c90, .ao_chans = 16, - .ao_bits = 16, }, { .name = "PXI-6704", .dev_id = 0x1920, .ao_chans = 32, - .ao_bits = 16, }, { .name = "PCI-6704", .dev_id = 0x1290, .ao_chans = 32, - .ao_bits = 16, }, }; -- GitLab From c952e019b99d9d8fb486f843c6225fb659dcd40b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 10:58:41 -0700 Subject: [PATCH 2070/5711] staging: comedi: das_08: use the 8253 helper functions Instead of open-coding the 8254 timer io, use the helper functions provided by 8253.h. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 39 +++++--------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index d0128e0e15cc..036953e3b715 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -56,6 +56,7 @@ #include #include "8255.h" +#include "8253.h" #include "das08.h" #define DRV_NAME "das08" @@ -434,38 +435,13 @@ das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, static unsigned int i8254_read_channel_low(unsigned int base, int chan) { - unsigned int msb, lsb; - - /* The following instructions must be in order. - We must avoid other process reading the counter's value in the - middle. - The spin_lock isn't needed since ioctl calls grab the big kernel - lock automatically */ - /*spin_lock(sp); */ - outb(chan << 6, base + I8254_CTRL); - base += chan; - lsb = inb(base); - msb = inb(base); - /*spin_unlock(sp); */ - - return lsb | (msb << 8); + return i8254_read(base, 0, chan); } static void i8254_write_channel_low(unsigned int base, int chan, unsigned int value) { - unsigned int msb, lsb; - - lsb = value & 0xFF; - msb = value >> 8; - - /* write lsb, then msb */ - base += chan; - /* See comments in i8254_read_channel_low */ - /*spin_lock(sp); */ - outb(lsb, base); - outb(msb, base); - /*spin_unlock(sp); */ + i8254_write(base, 0, chan, value); } static unsigned int i8254_read_channel(struct i8254_struct *st, int channel) @@ -486,10 +462,10 @@ static void i8254_write_channel(struct i8254_struct *st, int channel, static void i8254_set_mode_low(unsigned int base, int channel, unsigned int mode) { - outb((channel << 6) | 0x30 | (mode & 0x0F), base + I8254_CTRL); + i8254_set_mode(base, 0, channel, mode); } -static void i8254_set_mode(struct i8254_struct *st, int channel, +static void __i8254_set_mode(struct i8254_struct *st, int channel, unsigned int mode) { int chan = st->logic2phys[channel]; @@ -500,8 +476,7 @@ static void i8254_set_mode(struct i8254_struct *st, int channel, static unsigned int i8254_read_status_low(unsigned int base, int channel) { - outb(0xE0 | (2 << channel), base + I8254_CTRL); - return inb(base + channel); + return i8254_status(base, 0, channel); } static unsigned int i8254_read_status(struct i8254_struct *st, int channel) @@ -550,7 +525,7 @@ static int das08_counter_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - i8254_set_mode(&devpriv->i8254, chan, data[1]); + __i8254_set_mode(&devpriv->i8254, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: data[1] = i8254_read_status(&devpriv->i8254, chan); -- GitLab From afdd107c054ca135559a331f08630fdf76dacbfe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 10:59:21 -0700 Subject: [PATCH 2071/5711] staging: comedi: das_08: unwind the 8254 timer support Refactor the 8254 timer support by removing the various functions that handle the io and consolidating the logic into the initialize, read, write, and config functions used by the driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 76 +++++--------------------- 1 file changed, 15 insertions(+), 61 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 036953e3b715..78c33140e92f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -433,64 +433,12 @@ das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -static unsigned int i8254_read_channel_low(unsigned int base, int chan) -{ - return i8254_read(base, 0, chan); -} - -static void i8254_write_channel_low(unsigned int base, int chan, - unsigned int value) -{ - i8254_write(base, 0, chan, value); -} - -static unsigned int i8254_read_channel(struct i8254_struct *st, int channel) -{ - int chan = st->logic2phys[channel]; - - return i8254_read_channel_low(st->iobase, chan); -} - -static void i8254_write_channel(struct i8254_struct *st, int channel, - unsigned int value) -{ - int chan = st->logic2phys[channel]; - - i8254_write_channel_low(st->iobase, chan, value); -} - -static void i8254_set_mode_low(unsigned int base, int channel, - unsigned int mode) -{ - i8254_set_mode(base, 0, channel, mode); -} - -static void __i8254_set_mode(struct i8254_struct *st, int channel, - unsigned int mode) -{ - int chan = st->logic2phys[channel]; - - st->mode[chan] = mode; - return i8254_set_mode_low(st->iobase, chan, mode); -} - -static unsigned int i8254_read_status_low(unsigned int base, int channel) -{ - return i8254_status(base, 0, channel); -} - -static unsigned int i8254_read_status(struct i8254_struct *st, int channel) -{ - int chan = st->logic2phys[channel]; - - return i8254_read_status_low(st->iobase, chan); -} - static void i8254_initialize(struct i8254_struct *st) { int i; + for (i = 0; i < 3; ++i) - i8254_set_mode_low(st->iobase, i, st->mode[i]); + i8254_set_mode(st->iobase, 0, i, st->mode[i]); } static int das08_counter_read(struct comedi_device *dev, @@ -498,8 +446,10 @@ static int das08_counter_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - int chan = insn->chanspec; - data[0] = i8254_read_channel(&devpriv->i8254, chan); + struct i8254_struct *st = &devpriv->i8254; + int chan = st->logic2phys[insn->chanspec]; + + data[0] = i8254_read(st->iobase, 0, chan); return 1; } @@ -508,8 +458,10 @@ static int das08_counter_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - int chan = insn->chanspec; - i8254_write_channel(&devpriv->i8254, chan, data[0]); + struct i8254_struct *st = &devpriv->i8254; + int chan = st->logic2phys[insn->chanspec]; + + i8254_write(st->iobase, 0, chan, data[0]); return 1; } @@ -518,17 +470,19 @@ static int das08_counter_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - int chan = insn->chanspec; + struct i8254_struct *st = &devpriv->i8254; + int chan = st->logic2phys[insn->chanspec]; if (insn->n != 2) return -EINVAL; switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - __i8254_set_mode(&devpriv->i8254, chan, data[1]); + st->mode[chan] = data[1]; + i8254_set_mode(st->iobase, 0, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: - data[1] = i8254_read_status(&devpriv->i8254, chan); + data[1] = i8254_status(st->iobase, 0, chan); break; default: return -EINVAL; -- GitLab From cba9d4aa4e55547894d4625bc3f99bab2016a6c8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 10:59:55 -0700 Subject: [PATCH 2072/5711] staging: comedi: das_08: remove the cached 8254 'mode' The driver initially sets all the cached 'mode' values for the 8254 timers to (I8254_MODE0 | I8254_BINARY). It then sets the timers to that 'mode'. Configuring the counters with the comedi INSN_CONFIG_SET_COUNTER_MODE updates the 'mode' and then sets the timers to the 'mode'. The cached value is never read or used other than for storage. Just remove the 'mode' usage as it serves no purpose. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 78c33140e92f..c0c93ea36b51 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -435,10 +435,11 @@ das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, static void i8254_initialize(struct i8254_struct *st) { + unsigned int mode = I8254_MODE0 | I8254_BINARY; int i; for (i = 0; i < 3; ++i) - i8254_set_mode(st->iobase, 0, i, st->mode[i]); + i8254_set_mode(st->iobase, 0, i, mode); } static int das08_counter_read(struct comedi_device *dev, @@ -478,7 +479,6 @@ static int das08_counter_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - st->mode[chan] = data[1]; i8254_set_mode(st->iobase, 0, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: @@ -852,9 +852,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) devpriv->i8254.logic2phys[1] = 1; devpriv->i8254.logic2phys[2] = 2; devpriv->i8254.iobase = iobase + thisboard->i8254_offset; - devpriv->i8254.mode[0] = - devpriv->i8254.mode[1] = - devpriv->i8254.mode[2] = I8254_MODE0 | I8254_BINARY; i8254_initialize(&devpriv->i8254); } else { s->type = COMEDI_SUBD_UNUSED; -- GitLab From 6daf1e0547ab6b9797a45ea9f45a035a5abb7821 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 11:00:40 -0700 Subject: [PATCH 2073/5711] staging: comedi: das_08: remove the 8254 'logic2phys' usage The three 8254 timers have a 1:1 relationship to the comedi channels. The 'logic2phys' usage just makes the driver more complex. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c0c93ea36b51..2ad66f270b47 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -448,7 +448,7 @@ static int das08_counter_read(struct comedi_device *dev, { struct das08_private_struct *devpriv = dev->private; struct i8254_struct *st = &devpriv->i8254; - int chan = st->logic2phys[insn->chanspec]; + int chan = insn->chanspec; data[0] = i8254_read(st->iobase, 0, chan); return 1; @@ -460,7 +460,7 @@ static int das08_counter_write(struct comedi_device *dev, { struct das08_private_struct *devpriv = dev->private; struct i8254_struct *st = &devpriv->i8254; - int chan = st->logic2phys[insn->chanspec]; + int chan = insn->chanspec; i8254_write(st->iobase, 0, chan, data[0]); return 1; @@ -472,7 +472,7 @@ static int das08_counter_config(struct comedi_device *dev, { struct das08_private_struct *devpriv = dev->private; struct i8254_struct *st = &devpriv->i8254; - int chan = st->logic2phys[insn->chanspec]; + int chan = insn->chanspec; if (insn->n != 2) return -EINVAL; @@ -848,9 +848,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->insn_config = das08_counter_config; /* Set-up the 8254 structure */ devpriv->i8254.channels = 3; - devpriv->i8254.logic2phys[0] = 0; - devpriv->i8254.logic2phys[1] = 1; - devpriv->i8254.logic2phys[2] = 2; devpriv->i8254.iobase = iobase + thisboard->i8254_offset; i8254_initialize(&devpriv->i8254); } else { -- GitLab From f97733d9885ece037f44dbb8083eeb772f549415 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 11:01:22 -0700 Subject: [PATCH 2074/5711] staging: comedi: das_08: remove the 8254 'channels' usage The internal 8254 'channels' count is the same as the comedi subdevice 'n_chan'. There is no need to keep the internal count. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 2ad66f270b47..20f79b7b4efc 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -847,7 +847,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->insn_write = das08_counter_write; s->insn_config = das08_counter_config; /* Set-up the 8254 structure */ - devpriv->i8254.channels = 3; devpriv->i8254.iobase = iobase + thisboard->i8254_offset; i8254_initialize(&devpriv->i8254); } else { -- GitLab From b47e30a9e5970dea1a75a4f88bc6eb1c4a5dc941 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 11:02:02 -0700 Subject: [PATCH 2075/5711] staging: comedi: das_08: remove the unneeded 8254 variables and defines Now that the driver is using the 8253 helper functions, remove the unused variables in the i8254_struct as well as the unused defines for the 8254 register offsets. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index 0b92f24b261f..ee3cf4b9a9ad 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -50,17 +50,9 @@ struct das08_board_struct { }; struct i8254_struct { - int channels; /* available channels. Some could be used internally. */ - int logic2phys[3]; /* to know which physical channel is. */ - int mode[3]; /* the index is the real counter. */ unsigned int iobase; }; -#define I8254_CNT0 0 -#define I8254_CNT1 1 -#define I8254_CNT2 2 -#define I8254_CTRL 3 - struct das08_private_struct { unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */ unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */ -- GitLab From 807271462037e47b9a053a6547f3efc569bb7596 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 29 Jun 2012 11:02:59 -0700 Subject: [PATCH 2076/5711] staging: comedi: das_08: absorb i8254_struct into the private data The i8254_struct now only contains the iobase address used to read/write the 8254 timer device. Move that variable into the das08 private data struct and remove the i8254_struct. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 22 ++++++++++------------ drivers/staging/comedi/drivers/das08.h | 6 +----- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 20f79b7b4efc..874e02e47668 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -433,13 +433,14 @@ das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -static void i8254_initialize(struct i8254_struct *st) +static void i8254_initialize(struct comedi_device *dev) { + struct das08_private_struct *devpriv = dev->private; unsigned int mode = I8254_MODE0 | I8254_BINARY; int i; for (i = 0; i < 3; ++i) - i8254_set_mode(st->iobase, 0, i, mode); + i8254_set_mode(devpriv->i8254_iobase, 0, i, mode); } static int das08_counter_read(struct comedi_device *dev, @@ -447,10 +448,9 @@ static int das08_counter_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - struct i8254_struct *st = &devpriv->i8254; int chan = insn->chanspec; - data[0] = i8254_read(st->iobase, 0, chan); + data[0] = i8254_read(devpriv->i8254_iobase, 0, chan); return 1; } @@ -459,10 +459,9 @@ static int das08_counter_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - struct i8254_struct *st = &devpriv->i8254; int chan = insn->chanspec; - i8254_write(st->iobase, 0, chan, data[0]); + i8254_write(devpriv->i8254_iobase, 0, chan, data[0]); return 1; } @@ -471,7 +470,6 @@ static int das08_counter_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - struct i8254_struct *st = &devpriv->i8254; int chan = insn->chanspec; if (insn->n != 2) @@ -479,10 +477,10 @@ static int das08_counter_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - i8254_set_mode(st->iobase, 0, chan, data[1]); + i8254_set_mode(devpriv->i8254_iobase, 0, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: - data[1] = i8254_status(st->iobase, 0, chan); + data[1] = i8254_status(devpriv->i8254_iobase, 0, chan); break; default: return -EINVAL; @@ -846,9 +844,9 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->insn_read = das08_counter_read; s->insn_write = das08_counter_write; s->insn_config = das08_counter_config; - /* Set-up the 8254 structure */ - devpriv->i8254.iobase = iobase + thisboard->i8254_offset; - i8254_initialize(&devpriv->i8254); + + devpriv->i8254_iobase = iobase + thisboard->i8254_offset; + i8254_initialize(dev); } else { s->type = COMEDI_SUBD_UNUSED; } diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index ee3cf4b9a9ad..27b6d4ec9032 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -49,17 +49,13 @@ struct das08_board_struct { unsigned int iosize; /* number of ioports used */ }; -struct i8254_struct { - unsigned int iobase; -}; - struct das08_private_struct { unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */ unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */ const unsigned int *pg_gainlist; struct pci_dev *pdev; /* struct for pci-das08 */ unsigned int pci_iobase; /* additional base address for pci-das08 */ - struct i8254_struct i8254; + unsigned int i8254_iobase; }; #define NUM_DAS08_CS_BOARDS 2 -- GitLab From 3a36ad17c6709efb353f25f3b57b2443acb6bcd7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:42:41 -0700 Subject: [PATCH 2077/5711] staging: comedi: das08_cs: move the MODULE_* stuff to the EOF Move the MODULE_* declarations to the end of the file. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 8bf6ec2dddba..f62e5f81862a 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -224,10 +224,6 @@ static const struct pcmcia_device_id das08_cs_id_table[] = { }; MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); -MODULE_AUTHOR("David A. Schleef , " - "Frank Mori Hess "); -MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards"); -MODULE_LICENSE("GPL"); struct pcmcia_driver das08_cs_driver = { .probe = das08_pcmcia_attach, @@ -270,3 +266,8 @@ static void __exit das08_cs_exit_module(void) module_init(das08_cs_init_module); module_exit(das08_cs_exit_module); + +MODULE_AUTHOR("David A. Schleef , " + "Frank Mori Hess "); +MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards"); +MODULE_LICENSE("GPL"); -- GitLab From 468777024e3f635c78cc7b0370f447978669431d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:43:19 -0700 Subject: [PATCH 2078/5711] staging: comedi: das08_cs: consolidate the init and exit functions The register/unregister of the pcmcia driver is done in separate functions that are called by the module_{init,exit} routines. Simplify the code a bit by moving the register/unregister into the module_{init,exit} routines. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f62e5f81862a..14dfc81d78c6 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -235,36 +235,23 @@ struct pcmcia_driver das08_cs_driver = { .name = "pcm-das08", }; -static int __init init_das08_pcmcia_cs(void) -{ - pcmcia_register_driver(&das08_cs_driver); - return 0; -} - -static void __exit exit_das08_pcmcia_cs(void) -{ - pr_debug("das08_pcmcia_cs: unloading\n"); - pcmcia_unregister_driver(&das08_cs_driver); -} - static int __init das08_cs_init_module(void) { int ret; - ret = init_das08_pcmcia_cs(); + ret = pcmcia_register_driver(&das08_cs_driver); if (ret < 0) return ret; return comedi_driver_register(&driver_das08_cs); } +module_init(das08_cs_init_module); static void __exit das08_cs_exit_module(void) { - exit_das08_pcmcia_cs(); + pcmcia_unregister_driver(&das08_cs_driver); comedi_driver_unregister(&driver_das08_cs); } - -module_init(das08_cs_init_module); module_exit(das08_cs_exit_module); MODULE_AUTHOR("David A. Schleef , " -- GitLab From 36061c842be56f62bf77d7339bc4581a38e03846 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:43:52 -0700 Subject: [PATCH 2079/5711] staging: comedi: das08_cs: change driver registration order As done with the other comedi driver types, register the comedi_driver first then the pcmcia_driver. Also, make sure the pcmcia_driver registration succeeds and unregister the comedi_driver if it fails. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 14dfc81d78c6..493078a26a7a 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -239,11 +239,18 @@ static int __init das08_cs_init_module(void) { int ret; - ret = pcmcia_register_driver(&das08_cs_driver); + ret = comedi_driver_register(&driver_das08_cs); if (ret < 0) return ret; - return comedi_driver_register(&driver_das08_cs); + ret = pcmcia_register_driver(&das08_cs_driver); + if (ret < 0) { + comedi_driver_unregister(&driver_das08_cs); + return ret; + } + + return 0; + } module_init(das08_cs_init_module); -- GitLab From 27fa05bc3726430c5b369a3ffbe63d38ac7196d7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:44:30 -0700 Subject: [PATCH 2080/5711] staging: comedi: das08_cs: cleanup the pcmcia_driver declaration For aesthetic reasons, add some whitespace to the declaration of the pcmcia_driver and reorder it a bit. Also, the symbol 'das08_cs_driver' is only referenced in this file, make it static. This quiets the following sparse warning: warning: symbol 'das08_cs_driver' was not declared. Should it be static? Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 493078a26a7a..de094ad66592 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -225,14 +225,14 @@ static const struct pcmcia_device_id das08_cs_id_table[] = { MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); -struct pcmcia_driver das08_cs_driver = { - .probe = das08_pcmcia_attach, - .remove = das08_pcmcia_detach, - .suspend = das08_pcmcia_suspend, - .resume = das08_pcmcia_resume, - .id_table = das08_cs_id_table, - .owner = THIS_MODULE, - .name = "pcm-das08", +static struct pcmcia_driver das08_cs_driver = { + .name = "pcm-das08", + .owner = THIS_MODULE, + .probe = das08_pcmcia_attach, + .remove = das08_pcmcia_detach, + .suspend = das08_pcmcia_suspend, + .resume = das08_pcmcia_resume, + .id_table = das08_cs_id_table, }; static int __init das08_cs_init_module(void) -- GitLab From c332d969e4874c00bcf3d37fc69157558e1ca04b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:45:03 -0700 Subject: [PATCH 2081/5711] staging: comedi: das08_cs: cleanup and remove useless comments Move the comment about the PCMCIA support and reword it a bit because of the move. Remove a number of useless comments. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 33 +++++++++-------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index de094ad66592..f56fd401568c 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -20,6 +20,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + PCMCIA support code for this driver is adapted from the dummy_cs.c + driver of the Linux PCMCIA Card Services package. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + ***************************************************************** */ @@ -97,17 +104,6 @@ static int das08_cs_attach(struct comedi_device *dev, return das08_common_attach(dev, iobase); } -/*====================================================================== - - The following pcmcia code for the pcm-das08 is adapted from the - dummy_cs.c driver of the Linux PCMCIA Card Services package. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - -======================================================================*/ - static void das08_pcmcia_config(struct pcmcia_device *link); static void das08_pcmcia_release(struct pcmcia_device *link); static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); @@ -140,7 +136,7 @@ static int das08_pcmcia_attach(struct pcmcia_device *link) das08_pcmcia_config(link); return 0; -} /* das08_pcmcia_attach */ +} static void das08_pcmcia_detach(struct pcmcia_device *link) { @@ -153,7 +149,7 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) /* This points to the parent struct local_info_t struct */ kfree(link->priv); -} /* das08_pcmcia_detach */ +} static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, @@ -191,13 +187,13 @@ static void das08_pcmcia_config(struct pcmcia_device *link) failed: das08_pcmcia_release(link); -} /* das08_pcmcia_config */ +} static void das08_pcmcia_release(struct pcmcia_device *link) { dev_dbg(&link->dev, "das08_pcmcia_release\n"); pcmcia_disable_device(link); -} /* das08_pcmcia_release */ +} static int das08_pcmcia_suspend(struct pcmcia_device *link) { @@ -206,7 +202,7 @@ static int das08_pcmcia_suspend(struct pcmcia_device *link) local->stop = 1; return 0; -} /* das08_pcmcia_suspend */ +} static int das08_pcmcia_resume(struct pcmcia_device *link) { @@ -214,15 +210,12 @@ static int das08_pcmcia_resume(struct pcmcia_device *link) local->stop = 0; return 0; -} /* das08_pcmcia_resume */ - -/*====================================================================*/ +} static const struct pcmcia_device_id das08_cs_id_table[] = { PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), PCMCIA_DEVICE_NULL }; - MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); static struct pcmcia_driver das08_cs_driver = { -- GitLab From fb795746195bb8566ecfb50dec9f63676fc29575 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:45:34 -0700 Subject: [PATCH 2082/5711] staging: comedi: das08_cs: refactor the pcmcia support code Refactor the pcmcia support code to remove the need for the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 87 ++++++++++------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f56fd401568c..43322c3477bc 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -104,54 +104,12 @@ static int das08_cs_attach(struct comedi_device *dev, return das08_common_attach(dev, iobase); } -static void das08_pcmcia_config(struct pcmcia_device *link); -static void das08_pcmcia_release(struct pcmcia_device *link); -static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); -static int das08_pcmcia_resume(struct pcmcia_device *p_dev); - -static int das08_pcmcia_attach(struct pcmcia_device *); -static void das08_pcmcia_detach(struct pcmcia_device *); - -struct local_info_t { - struct pcmcia_device *link; - int stop; - struct bus_operations *bus; -}; - -static int das08_pcmcia_attach(struct pcmcia_device *link) -{ - struct local_info_t *local; - - dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); - - /* Allocate space for private device-specific data */ - local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); - if (!local) - return -ENOMEM; - local->link = link; - link->priv = local; - - cur_dev = link; - - das08_pcmcia_config(link); - - return 0; -} - -static void das08_pcmcia_detach(struct pcmcia_device *link) +static void das08_pcmcia_release(struct pcmcia_device *link) { - - dev_dbg(&link->dev, "das08_pcmcia_detach\n"); - - ((struct local_info_t *)link->priv)->stop = 1; - das08_pcmcia_release(link); - - /* This points to the parent struct local_info_t struct */ - kfree(link->priv); - + dev_dbg(&link->dev, "das08_pcmcia_release\n"); + pcmcia_disable_device(link); } - static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { @@ -189,10 +147,43 @@ failed: } -static void das08_pcmcia_release(struct pcmcia_device *link) +struct local_info_t { + struct pcmcia_device *link; + int stop; + struct bus_operations *bus; +}; + +static int das08_pcmcia_attach(struct pcmcia_device *link) { - dev_dbg(&link->dev, "das08_pcmcia_release\n"); - pcmcia_disable_device(link); + struct local_info_t *local; + + dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + cur_dev = link; + + das08_pcmcia_config(link); + + return 0; +} + +static void das08_pcmcia_detach(struct pcmcia_device *link) +{ + + dev_dbg(&link->dev, "das08_pcmcia_detach\n"); + + ((struct local_info_t *)link->priv)->stop = 1; + das08_pcmcia_release(link); + + /* This points to the parent struct local_info_t struct */ + kfree(link->priv); + } static int das08_pcmcia_suspend(struct pcmcia_device *link) -- GitLab From 44378f65f1b528d3a368a515598e44a73a9c3a76 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:46:08 -0700 Subject: [PATCH 2083/5711] staging: comedi: das08_cs: remove unused pcmcia 'stop' logic The pcmcia support code in this driver is cut-and-paste from the dummy_cs.c driver of the Linux PCMCIA Card Services package. It has code in it to stop the device during suspend but nothing in the main comedi_driver uses it. Remove the 'stop' variable from the pcmcia private data and all the logic that deals with it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 43322c3477bc..044c5860421b 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -149,7 +149,6 @@ failed: struct local_info_t { struct pcmcia_device *link; - int stop; struct bus_operations *bus; }; @@ -178,7 +177,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) dev_dbg(&link->dev, "das08_pcmcia_detach\n"); - ((struct local_info_t *)link->priv)->stop = 1; das08_pcmcia_release(link); /* This points to the parent struct local_info_t struct */ @@ -188,18 +186,11 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) static int das08_pcmcia_suspend(struct pcmcia_device *link) { - struct local_info_t *local = link->priv; - /* Mark the device as stopped, to block IO until later */ - local->stop = 1; - return 0; } static int das08_pcmcia_resume(struct pcmcia_device *link) { - struct local_info_t *local = link->priv; - - local->stop = 0; return 0; } -- GitLab From eb97e08e04048d47d5a16a9c6428cda5dda8c4f1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:46:40 -0700 Subject: [PATCH 2084/5711] staging: comedi: das08_cs: remove the pcmcia suspend/resume The pcmcia suspend/resume callbacks don't do anything. Remove them. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 044c5860421b..b7efcb4f4239 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -184,16 +184,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) } -static int das08_pcmcia_suspend(struct pcmcia_device *link) -{ - return 0; -} - -static int das08_pcmcia_resume(struct pcmcia_device *link) -{ - return 0; -} - static const struct pcmcia_device_id das08_cs_id_table[] = { PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), PCMCIA_DEVICE_NULL @@ -205,8 +195,6 @@ static struct pcmcia_driver das08_cs_driver = { .owner = THIS_MODULE, .probe = das08_pcmcia_attach, .remove = das08_pcmcia_detach, - .suspend = das08_pcmcia_suspend, - .resume = das08_pcmcia_resume, .id_table = das08_cs_id_table, }; -- GitLab From 6d4ef6d6360193c6acd0d41a88ddd7034af286f3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:47:14 -0700 Subject: [PATCH 2085/5711] staging: comedi: das08_cs: remove unneeded pcmcia private data The pcmcia device-specific data is no longer needed by this driver. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index b7efcb4f4239..d02250e6f0c1 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -147,24 +147,10 @@ failed: } -struct local_info_t { - struct pcmcia_device *link; - struct bus_operations *bus; -}; - static int das08_pcmcia_attach(struct pcmcia_device *link) { - struct local_info_t *local; - dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); - /* Allocate space for private device-specific data */ - local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); - if (!local) - return -ENOMEM; - local->link = link; - link->priv = local; - cur_dev = link; das08_pcmcia_config(link); @@ -178,10 +164,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) dev_dbg(&link->dev, "das08_pcmcia_detach\n"); das08_pcmcia_release(link); - - /* This points to the parent struct local_info_t struct */ - kfree(link->priv); - } static const struct pcmcia_device_id das08_cs_id_table[] = { -- GitLab From ae6eba84efd2ccc214ed50e8b35bbc54cb50121b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:47:47 -0700 Subject: [PATCH 2086/5711] staging: comedi: das08_cs: refactor the pcmcia probe/remove Move the pcmcia_disable_device() call where needed in the pcmcia probe/remove and delete the das08_pcmcia_release() function. Move the logic of the das08_pcmcia_config() directly into the probe function and properly return an error code when the config fails. Only set cur_dev, used by the comedi_driver, if the pcmcia probe is successful. Also, make sure to NULL it in the remove. Remove all the kernel messages in the pcmcia support code. They are just added noise. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 38 +++++------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index d02250e6f0c1..f2f33e1ea516 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -104,12 +104,6 @@ static int das08_cs_attach(struct comedi_device *dev, return das08_common_attach(dev, iobase); } -static void das08_pcmcia_release(struct pcmcia_device *link) -{ - dev_dbg(&link->dev, "das08_pcmcia_release\n"); - pcmcia_disable_device(link); -} - static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { @@ -119,19 +113,15 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, return pcmcia_request_io(p_dev); } -static void das08_pcmcia_config(struct pcmcia_device *link) +static int das08_pcmcia_attach(struct pcmcia_device *link) { int ret; - dev_dbg(&link->dev, "das08_pcmcia_config\n"); - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); - if (ret) { - dev_warn(&link->dev, "no configuration found\n"); + if (ret) goto failed; - } if (!link->irq) goto failed; @@ -140,30 +130,18 @@ static void das08_pcmcia_config(struct pcmcia_device *link) if (ret) goto failed; - return; - -failed: - das08_pcmcia_release(link); - -} - -static int das08_pcmcia_attach(struct pcmcia_device *link) -{ - dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); - cur_dev = link; - - das08_pcmcia_config(link); - return 0; + +failed: + pcmcia_disable_device(link); + return ret; } static void das08_pcmcia_detach(struct pcmcia_device *link) { - - dev_dbg(&link->dev, "das08_pcmcia_detach\n"); - - das08_pcmcia_release(link); + pcmcia_disable_device(link); + cur_dev = NULL; } static const struct pcmcia_device_id das08_cs_id_table[] = { -- GitLab From 6b7de35e32882226654ea3ac28620e8c82f8cb0f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:48:26 -0700 Subject: [PATCH 2087/5711] staging: comedi: das08_cs: move the comedi_driver variable Move the comedi_driver variable to remove the need for the forward declarations. Add some whitespace to the declaration for aesthetic reasons. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f2f33e1ea516..9ec9b122f979 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -62,19 +62,6 @@ static struct pcmcia_device *cur_dev; #define thisboard ((const struct das08_board_struct *)dev->board_ptr) -static int das08_cs_attach(struct comedi_device *dev, - struct comedi_devconfig *it); - -static struct comedi_driver driver_das08_cs = { - .driver_name = "das08_cs", - .module = THIS_MODULE, - .attach = das08_cs_attach, - .detach = das08_common_detach, - .board_name = &das08_cs_boards[0].name, - .num_names = ARRAY_SIZE(das08_cs_boards), - .offset = sizeof(struct das08_board_struct), -}; - static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) { @@ -104,6 +91,16 @@ static int das08_cs_attach(struct comedi_device *dev, return das08_common_attach(dev, iobase); } +static struct comedi_driver driver_das08_cs = { + .driver_name = "das08_cs", + .module = THIS_MODULE, + .attach = das08_cs_attach, + .detach = das08_common_detach, + .board_name = &das08_cs_boards[0].name, + .num_names = ARRAY_SIZE(das08_cs_boards), + .offset = sizeof(struct das08_board_struct), +}; + static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { -- GitLab From 6f88a20a7ff0b8724b9832c139fc06095e71b9bf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 15:48:58 -0700 Subject: [PATCH 2088/5711] staging: comedi: das08_cs: remove thisboard macro The 'thisboard' macro relies on a local variable having a specific name and yields a pointer derived from that local variable. Replace the macro with a local variable where used. Use the comedi_board() helper to get the pointer. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 9ec9b122f979..f5700de7b6c0 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -60,11 +60,10 @@ Command support does not exist, but could be added for this board. static struct pcmcia_device *cur_dev; -#define thisboard ((const struct das08_board_struct *)dev->board_ptr) - static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das08_board_struct *thisboard = comedi_board(dev); int ret; unsigned long iobase; struct pcmcia_device *link = cur_dev; /* XXX hack */ -- GitLab From 17f49dd46c5db2912d2dd985f400f6237fd30255 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:10:46 -0700 Subject: [PATCH 2089/5711] staging: comedi: dmm32at: use module_comedi_driver Convert driver to use the module_comedi_driver() macro to remove some of the boilerplate. Move the comedi_driver variable to the end of the file to keep it with the module_comedi_driver() macro. This also removes the need for some of the forward declarations. While moving the variable: 1) strip out the unnecessary cut-and-paste skel driver comments 2) add whitespace to improve the readability 3) rename the variable from driver* to *driver Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 63 ++++-------------------- 1 file changed, 10 insertions(+), 53 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index af3531676e81..ad7fef915395 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -211,43 +211,6 @@ struct dmm32at_private { */ #define devpriv ((struct dmm32at_private *)dev->private) -/* - * The struct comedi_driver structure tells the Comedi core module - * which functions to call to configure/deconfigure (attach/detach) - * the board, and also about the kernel module that contains - * the device code. - */ -static int dmm32at_attach(struct comedi_device *dev, - struct comedi_devconfig *it); -static void dmm32at_detach(struct comedi_device *dev); -static struct comedi_driver driver_dmm32at = { - .driver_name = "dmm32at", - .module = THIS_MODULE, - .attach = dmm32at_attach, - .detach = dmm32at_detach, -/* It is not necessary to implement the following members if you are - * writing a driver for a ISA PnP or PCI card */ -/* Most drivers will support multiple types of boards by - * having an array of board structures. These were defined - * in dmm32at_boards[] above. Note that the element 'name' - * was first in the structure -- Comedi uses this fact to - * extract the name of the board without knowing any details - * about the structure except for its length. - * When a device is attached (by comedi_config), the name - * of the device is given to Comedi, and Comedi tries to - * match it by going through the list of board names. If - * there is a match, the address of the pointer is put - * into dev->board_ptr and driver->attach() is called. - * - * Note that these are not necessary if you can determine - * the type of board in software. ISA PnP, PCI, and PCMCIA - * devices are such boards. - */ - .board_name = &dmm32at_boards[0].name, - .offset = sizeof(struct dmm32at_board), - .num_names = ARRAY_SIZE(dmm32at_boards), -}; - /* prototypes for driver functions below */ static int dmm32at_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, @@ -1027,22 +990,16 @@ void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) } -/* - * A convenient macro that defines init_module() and cleanup_module(), - * as necessary. - */ -static int __init driver_dmm32at_init_module(void) -{ - return comedi_driver_register(&driver_dmm32at); -} - -static void __exit driver_dmm32at_cleanup_module(void) -{ - comedi_driver_unregister(&driver_dmm32at); -} - -module_init(driver_dmm32at_init_module); -module_exit(driver_dmm32at_cleanup_module); +static struct comedi_driver dmm32at_driver = { + .driver_name = "dmm32at", + .module = THIS_MODULE, + .attach = dmm32at_attach, + .detach = dmm32at_detach, + .board_name = &dmm32at_boards[0].name, + .offset = sizeof(struct dmm32at_board), + .num_names = ARRAY_SIZE(dmm32at_boards), +}; +module_comedi_driver(dmm32at_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); -- GitLab From 4f793db33dc3bab1b77a540386a662fbfd595e08 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:11:23 -0700 Subject: [PATCH 2090/5711] staging: comedi: dmm32at: remove forward declarations 1 Move the attach/detach functions as well as the boardinfo variable to remove the need to most of the forward declarations. Add some whitespace to the boardinfo during the move. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 373 +++++++++++------------ 1 file changed, 172 insertions(+), 201 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index ad7fef915395..9c3d322d0e39 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -175,19 +175,6 @@ struct dmm32at_board { int have_dio; int dio_chans; }; -static const struct dmm32at_board dmm32at_boards[] = { - { - .name = "dmm32at", - .ai_chans = 32, - .ai_bits = 16, - .ai_ranges = &dmm32at_airanges, - .ao_chans = 4, - .ao_bits = 12, - .ao_ranges = &dmm32at_aoranges, - .have_dio = 1, - .dio_chans = 24, - }, -}; /* this structure is for data unique to this hardware driver. If * several hardware drivers keep similar information in this structure, @@ -212,197 +199,9 @@ struct dmm32at_private { #define devpriv ((struct dmm32at_private *)dev->private) /* prototypes for driver functions below */ -static int dmm32at_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int dmm32at_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int dmm32at_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int dmm32at_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int dmm32at_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); -static int dmm32at_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int dmm32at_ai_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); -static int dmm32at_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); static int dmm32at_ns_to_timer(unsigned int *ns, int round); -static irqreturn_t dmm32at_isr(int irq, void *d); void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec); -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ -static int dmm32at_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - const struct dmm32at_board *board = comedi_board(dev); - int ret; - struct comedi_subdevice *s; - unsigned char aihi, ailo, fifostat, aistat, intstat, airback; - unsigned long iobase; - unsigned int irq; - - iobase = it->options[0]; - irq = it->options[1]; - - printk(KERN_INFO "comedi%d: dmm32at: attaching\n", dev->minor); - printk(KERN_DEBUG "dmm32at: probing at address 0x%04lx, irq %u\n", - iobase, irq); - - /* register address space */ - if (!request_region(iobase, DMM32AT_MEMSIZE, board->name)) { - printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n", - dev->minor); - return -EIO; - } - dev->iobase = iobase; - - /* the following just makes sure the board is there and gets - it to a known state */ - - /* reset the board */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_RESET); - - /* allow a millisecond to reset */ - udelay(1000); - - /* zero scan and fifo control */ - dmm_outb(dev, DMM32AT_FIFOCNTRL, 0x0); - - /* zero interrupt and clock control */ - dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); - - /* write a test channel range, the high 3 bits should drop */ - dmm_outb(dev, DMM32AT_AILOW, 0x80); - dmm_outb(dev, DMM32AT_AIHIGH, 0xff); - - /* set the range at 10v unipolar */ - dmm_outb(dev, DMM32AT_AICONF, DMM32AT_RANGE_U10); - - /* should take 10 us to settle, here's a hundred */ - udelay(100); - - /* read back the values */ - ailo = dmm_inb(dev, DMM32AT_AILOW); - aihi = dmm_inb(dev, DMM32AT_AIHIGH); - fifostat = dmm_inb(dev, DMM32AT_FIFOSTAT); - aistat = dmm_inb(dev, DMM32AT_AISTAT); - intstat = dmm_inb(dev, DMM32AT_INTCLOCK); - airback = dmm_inb(dev, DMM32AT_AIRBACK); - - printk(KERN_DEBUG "dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n", - ailo, aihi, fifostat); - printk(KERN_DEBUG - "dmm32at: aistat=0x%02x intstat=0x%02x airback=0x%02x\n", - aistat, intstat, airback); - - if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) || - (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) { - printk(KERN_ERR "dmmat32: board detection failed\n"); - return -EIO; - } - - /* board is there, register interrupt */ - if (irq) { - ret = request_irq(irq, dmm32at_isr, 0, board->name, dev); - if (ret < 0) { - printk(KERN_ERR "dmm32at: irq conflict\n"); - return ret; - } - dev->irq = irq; - } - - dev->board_name = board->name; - -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ - if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) - return -ENOMEM; - - ret = comedi_alloc_subdevices(dev, 3); - if (ret) - return ret; - - s = dev->subdevices + 0; - dev->read_subdev = s; - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - /* we support single-ended (ground) and differential */ - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; - s->n_chan = board->ai_chans; - s->maxdata = (1 << board->ai_bits) - 1; - s->range_table = board->ai_ranges; - s->len_chanlist = 32; /* This is the maximum chanlist length that - the board can handle */ - s->insn_read = dmm32at_ai_rinsn; - s->do_cmd = dmm32at_ai_cmd; - s->do_cmdtest = dmm32at_ai_cmdtest; - s->cancel = dmm32at_ai_cancel; - - s = dev->subdevices + 1; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = board->ao_chans; - s->maxdata = (1 << board->ao_bits) - 1; - s->range_table = board->ao_ranges; - s->insn_write = dmm32at_ao_winsn; - s->insn_read = dmm32at_ao_rinsn; - - s = dev->subdevices + 2; - /* digital i/o subdevice */ - if (board->have_dio) { - - /* get access to the DIO regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); - /* set the DIO's to the defualt input setting */ - devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | - DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; - dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); - - /* set up the subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = board->dio_chans; - s->maxdata = 1; - s->state = 0; - s->range_table = &range_digital; - s->insn_bits = dmm32at_dio_insn_bits; - s->insn_config = dmm32at_dio_insn_config; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - /* success */ - printk(KERN_INFO "comedi%d: dmm32at: attached\n", dev->minor); - - return 1; - -} - -static void dmm32at_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DMM32AT_MEMSIZE); -} - /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -990,6 +789,178 @@ void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) } +static int dmm32at_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + const struct dmm32at_board *board = comedi_board(dev); + int ret; + struct comedi_subdevice *s; + unsigned char aihi, ailo, fifostat, aistat, intstat, airback; + unsigned long iobase; + unsigned int irq; + + iobase = it->options[0]; + irq = it->options[1]; + + printk(KERN_INFO "comedi%d: dmm32at: attaching\n", dev->minor); + printk(KERN_DEBUG "dmm32at: probing at address 0x%04lx, irq %u\n", + iobase, irq); + + /* register address space */ + if (!request_region(iobase, DMM32AT_MEMSIZE, board->name)) { + printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n", + dev->minor); + return -EIO; + } + dev->iobase = iobase; + + /* the following just makes sure the board is there and gets + it to a known state */ + + /* reset the board */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_RESET); + + /* allow a millisecond to reset */ + udelay(1000); + + /* zero scan and fifo control */ + dmm_outb(dev, DMM32AT_FIFOCNTRL, 0x0); + + /* zero interrupt and clock control */ + dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); + + /* write a test channel range, the high 3 bits should drop */ + dmm_outb(dev, DMM32AT_AILOW, 0x80); + dmm_outb(dev, DMM32AT_AIHIGH, 0xff); + + /* set the range at 10v unipolar */ + dmm_outb(dev, DMM32AT_AICONF, DMM32AT_RANGE_U10); + + /* should take 10 us to settle, here's a hundred */ + udelay(100); + + /* read back the values */ + ailo = dmm_inb(dev, DMM32AT_AILOW); + aihi = dmm_inb(dev, DMM32AT_AIHIGH); + fifostat = dmm_inb(dev, DMM32AT_FIFOSTAT); + aistat = dmm_inb(dev, DMM32AT_AISTAT); + intstat = dmm_inb(dev, DMM32AT_INTCLOCK); + airback = dmm_inb(dev, DMM32AT_AIRBACK); + + printk(KERN_DEBUG "dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n", + ailo, aihi, fifostat); + printk(KERN_DEBUG + "dmm32at: aistat=0x%02x intstat=0x%02x airback=0x%02x\n", + aistat, intstat, airback); + + if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) || + (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) { + printk(KERN_ERR "dmmat32: board detection failed\n"); + return -EIO; + } + + /* board is there, register interrupt */ + if (irq) { + ret = request_irq(irq, dmm32at_isr, 0, board->name, dev); + if (ret < 0) { + printk(KERN_ERR "dmm32at: irq conflict\n"); + return ret; + } + dev->irq = irq; + } + + dev->board_name = board->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) + return -ENOMEM; + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + s = dev->subdevices + 0; + dev->read_subdev = s; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + /* we support single-ended (ground) and differential */ + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; + s->range_table = board->ai_ranges; + s->len_chanlist = 32; /* This is the maximum chanlist length that + the board can handle */ + s->insn_read = dmm32at_ai_rinsn; + s->do_cmd = dmm32at_ai_cmd; + s->do_cmdtest = dmm32at_ai_cmdtest; + s->cancel = dmm32at_ai_cancel; + + s = dev->subdevices + 1; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = board->ao_chans; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_ranges; + s->insn_write = dmm32at_ao_winsn; + s->insn_read = dmm32at_ao_rinsn; + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (board->have_dio) { + + /* get access to the DIO regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + /* set the DIO's to the defualt input setting */ + devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | + DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; + dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); + + /* set up the subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = board->dio_chans; + s->maxdata = 1; + s->state = 0; + s->range_table = &range_digital; + s->insn_bits = dmm32at_dio_insn_bits; + s->insn_config = dmm32at_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* success */ + printk(KERN_INFO "comedi%d: dmm32at: attached\n", dev->minor); + + return 1; + +} + +static void dmm32at_detach(struct comedi_device *dev) +{ + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, DMM32AT_MEMSIZE); +} + +static const struct dmm32at_board dmm32at_boards[] = { + { + .name = "dmm32at", + .ai_chans = 32, + .ai_bits = 16, + .ai_ranges = &dmm32at_airanges, + .ao_chans = 4, + .ao_bits = 12, + .ao_ranges = &dmm32at_aoranges, + .have_dio = 1, + .dio_chans = 24, + }, +}; + static struct comedi_driver dmm32at_driver = { .driver_name = "dmm32at", .module = THIS_MODULE, -- GitLab From 47ae6a72597c29745fc18d693fe00bc8a537cfdf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:11:56 -0700 Subject: [PATCH 2091/5711] staging: comedi: dmm32at: remove forward declarations 2 Move the dmm32at_ns_to_timer() and dmm32at_setaitimer() functions to remove the need for the remaining forward declarations. Also, make dmm32at_setaitimer() static, it's only referenced in this file. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 100 +++++++++++------------ 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 9c3d322d0e39..c139eff61643 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -198,10 +198,6 @@ struct dmm32at_private { */ #define devpriv ((struct dmm32at_private *)dev->private) -/* prototypes for driver functions below */ -static int dmm32at_ns_to_timer(unsigned int *ns, int round); -void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec); - /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -279,6 +275,23 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, return n; } +/* This function doesn't require a particular form, this is just + * what happens to be used in some of the drivers. It should + * convert ns nanoseconds to a counter value suitable for programming + * the device. Also, it should adjust ns so that it cooresponds to + * the actual time that the device will use. */ +static int dmm32at_ns_to_timer(unsigned int *ns, int round) +{ + /* trivial timer */ + /* if your timing is done through two cascaded timers, the + * i8253_cascade_ns_to_timer() function in 8253.h can be + * very helpful. There are also i8254_load() and i8254_mm_load() + * which can be used to load values into the ubiquitous 8254 counters + */ + + return *ns; +} + static int dmm32at_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -465,6 +478,37 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, return 0; } +static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) +{ + unsigned char lo1, lo2, hi2; + unsigned short both2; + + /* based on 10mhz clock */ + lo1 = 200; + both2 = nansec / 20000; + hi2 = (both2 & 0xff00) >> 8; + lo2 = both2 & 0x00ff; + + /* set the counter frequency to 10mhz */ + dmm_outb(dev, DMM32AT_CNTRDIO, 0); + + /* get access to the clock regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_CLKACC); + + /* write the counter 1 control word and low byte to counter */ + dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT1); + dmm_outb(dev, DMM32AT_CLK1, lo1); + + /* write the counter 2 control word and low byte then to counter */ + dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT2); + dmm_outb(dev, DMM32AT_CLK2, lo2); + dmm_outb(dev, DMM32AT_CLK2, hi2); + + /* enable the ai conversion interrupt and the clock to start scans */ + dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT | DMM32AT_CLKSEL); + +} + static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; @@ -591,23 +635,6 @@ static irqreturn_t dmm32at_isr(int irq, void *d) return IRQ_HANDLED; } -/* This function doesn't require a particular form, this is just - * what happens to be used in some of the drivers. It should - * convert ns nanoseconds to a counter value suitable for programming - * the device. Also, it should adjust ns so that it cooresponds to - * the actual time that the device will use. */ -static int dmm32at_ns_to_timer(unsigned int *ns, int round) -{ - /* trivial timer */ - /* if your timing is done through two cascaded timers, the - * i8253_cascade_ns_to_timer() function in 8253.h can be - * very helpful. There are also i8254_load() and i8254_mm_load() - * which can be used to load values into the ubiquitous 8254 counters - */ - - return *ns; -} - static int dmm32at_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -758,37 +785,6 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev, return 1; } -void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) -{ - unsigned char lo1, lo2, hi2; - unsigned short both2; - - /* based on 10mhz clock */ - lo1 = 200; - both2 = nansec / 20000; - hi2 = (both2 & 0xff00) >> 8; - lo2 = both2 & 0x00ff; - - /* set the counter frequency to 10mhz */ - dmm_outb(dev, DMM32AT_CNTRDIO, 0); - - /* get access to the clock regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_CLKACC); - - /* write the counter 1 control word and low byte to counter */ - dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT1); - dmm_outb(dev, DMM32AT_CLK1, lo1); - - /* write the counter 2 control word and low byte then to counter */ - dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT2); - dmm_outb(dev, DMM32AT_CLK2, lo2); - dmm_outb(dev, DMM32AT_CLK2, hi2); - - /* enable the ai conversion interrupt and the clock to start scans */ - dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT | DMM32AT_CLKSEL); - -} - static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it) { -- GitLab From 99953ea1ec780c22bacf065fc7c9750f0182c0f4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:12:35 -0700 Subject: [PATCH 2092/5711] staging: comedi: dmm32at: remove dmm_inb macro The macro is just a wrapper for inb(). Just use the inb() directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 39 ++++++++++++------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index c139eff61643..ee4e8ab3485b 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -78,7 +78,6 @@ Configuration Options: #define DMM32AT_DIOC 0x0e #define DMM32AT_DIOCONF 0x0f -#define dmm_inb(cdev, reg) inb((cdev->iobase)+reg) #define dmm_outb(cdev, reg, valu) outb(valu, (cdev->iobase)+reg) /* Board register values. */ @@ -232,7 +231,7 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, /* wait for circuit to settle */ for (i = 0; i < 40000; i++) { - status = dmm_inb(dev, DMM32AT_AIRBACK); + status = inb(dev->iobase + DMM32AT_AIRBACK); if ((status & DMM32AT_STATUS) == 0) break; } @@ -247,7 +246,7 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, dmm_outb(dev, DMM32AT_CONV, 0xff); /* wait for conversion to end */ for (i = 0; i < 40000; i++) { - status = dmm_inb(dev, DMM32AT_AISTAT); + status = inb(dev->iobase + DMM32AT_AISTAT); if ((status & DMM32AT_STATUS) == 0) break; } @@ -257,8 +256,8 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, } /* read data */ - lsb = dmm_inb(dev, DMM32AT_AILSB); - msb = dmm_inb(dev, DMM32AT_AIMSB); + lsb = inb(dev->iobase + DMM32AT_AILSB); + msb = inb(dev->iobase + DMM32AT_AIMSB); /* invert sign bit to make range unsigned, this is an idiosyncrasy of the diamond board, it return @@ -550,7 +549,7 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* wait for circuit to settle */ for (i = 0; i < 40000; i++) { - status = dmm_inb(dev, DMM32AT_AIRBACK); + status = inb(dev->iobase + DMM32AT_AIRBACK); if ((status & DMM32AT_STATUS) == 0) break; } @@ -600,7 +599,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) return IRQ_HANDLED; } - intstat = dmm_inb(dev, DMM32AT_INTCLOCK); + intstat = inb(dev->iobase + DMM32AT_INTCLOCK); if (intstat & DMM32AT_ADINT) { struct comedi_subdevice *s = dev->read_subdev; @@ -608,8 +607,8 @@ static irqreturn_t dmm32at_isr(int irq, void *d) for (i = 0; i < cmd->chanlist_len; i++) { /* read data */ - lsb = dmm_inb(dev, DMM32AT_AILSB); - msb = dmm_inb(dev, DMM32AT_AIMSB); + lsb = inb(dev->iobase + DMM32AT_AILSB); + msb = inb(dev->iobase + DMM32AT_AIMSB); /* invert sign bit to make range unsigned */ samp = ((msb ^ 0x0080) << 8) + lsb; @@ -660,7 +659,7 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, /* wait for circuit to settle */ for (i = 0; i < 40000; i++) { - status = dmm_inb(dev, DMM32AT_DACSTAT); + status = inb(dev->iobase + DMM32AT_DACSTAT); if ((status & DMM32AT_DACBUSY) == 0) break; } @@ -669,7 +668,7 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, return -ETIMEDOUT; } /* dummy read to update trigger the output */ - status = dmm_inb(dev, DMM32AT_DACMSB); + status = inb(dev->iobase + DMM32AT_DACMSB); } @@ -731,11 +730,11 @@ static int dmm32at_dio_insn_bits(struct comedi_device *dev, } /* now read the state back in */ - s->state = dmm_inb(dev, DMM32AT_DIOC); + s->state = inb(dev->iobase + DMM32AT_DIOC); s->state <<= 8; - s->state |= dmm_inb(dev, DMM32AT_DIOB); + s->state |= inb(dev->iobase + DMM32AT_DIOB); s->state <<= 8; - s->state |= dmm_inb(dev, DMM32AT_DIOA); + s->state |= inb(dev->iobase + DMM32AT_DIOA); data[1] = s->state; /* on return, data[1] contains the value of the digital @@ -836,12 +835,12 @@ static int dmm32at_attach(struct comedi_device *dev, udelay(100); /* read back the values */ - ailo = dmm_inb(dev, DMM32AT_AILOW); - aihi = dmm_inb(dev, DMM32AT_AIHIGH); - fifostat = dmm_inb(dev, DMM32AT_FIFOSTAT); - aistat = dmm_inb(dev, DMM32AT_AISTAT); - intstat = dmm_inb(dev, DMM32AT_INTCLOCK); - airback = dmm_inb(dev, DMM32AT_AIRBACK); + ailo = inb(dev->iobase + DMM32AT_AILOW); + aihi = inb(dev->iobase + DMM32AT_AIHIGH); + fifostat = inb(dev->iobase + DMM32AT_FIFOSTAT); + aistat = inb(dev->iobase + DMM32AT_AISTAT); + intstat = inb(dev->iobase + DMM32AT_INTCLOCK); + airback = inb(dev->iobase + DMM32AT_AIRBACK); printk(KERN_DEBUG "dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n", ailo, aihi, fifostat); -- GitLab From 29f747c21e4318cc41efa82dac217da9ee8d5533 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:13:11 -0700 Subject: [PATCH 2093/5711] staging: comedi: dmm32at: remove dmm_outb macro The macro is just a wrapper for outb(). Just use the outb() directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 81 ++++++++++++------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index ee4e8ab3485b..2ae31e8aab40 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -78,8 +78,6 @@ Configuration Options: #define DMM32AT_DIOC 0x0e #define DMM32AT_DIOCONF 0x0f -#define dmm_outb(cdev, reg, valu) outb(valu, (cdev->iobase)+reg) - /* Board register values. */ /* DMM32AT_DACSTAT 0x04 */ @@ -221,13 +219,13 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, /* printk("channel=0x%02x, range=%d\n",chan,range); */ /* zero scan and fifo control and reset fifo */ - dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET); + outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL); /* write the ai channel range regs */ - dmm_outb(dev, DMM32AT_AILOW, chan); - dmm_outb(dev, DMM32AT_AIHIGH, chan); + outb(chan, dev->iobase + DMM32AT_AILOW); + outb(chan, dev->iobase + DMM32AT_AIHIGH); /* set the range bits */ - dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]); + outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF); /* wait for circuit to settle */ for (i = 0; i < 40000; i++) { @@ -243,7 +241,7 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion */ - dmm_outb(dev, DMM32AT_CONV, 0xff); + outb(0xff, dev->iobase + DMM32AT_CONV); /* wait for conversion to end */ for (i = 0; i < 40000; i++) { status = inb(dev->iobase + DMM32AT_AISTAT); @@ -489,23 +487,22 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) lo2 = both2 & 0x00ff; /* set the counter frequency to 10mhz */ - dmm_outb(dev, DMM32AT_CNTRDIO, 0); + outb(0, dev->iobase + DMM32AT_CNTRDIO); /* get access to the clock regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_CLKACC); + outb(DMM32AT_CLKACC, dev->iobase + DMM32AT_CNTRL); /* write the counter 1 control word and low byte to counter */ - dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT1); - dmm_outb(dev, DMM32AT_CLK1, lo1); + outb(DMM32AT_CLKCT1, dev->iobase + DMM32AT_CLKCT); + outb(lo1, dev->iobase + DMM32AT_CLK1); /* write the counter 2 control word and low byte then to counter */ - dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT2); - dmm_outb(dev, DMM32AT_CLK2, lo2); - dmm_outb(dev, DMM32AT_CLK2, hi2); + outb(DMM32AT_CLKCT2, dev->iobase + DMM32AT_CLKCT); + outb(lo2, dev->iobase + DMM32AT_CLK2); + outb(hi2, dev->iobase + DMM32AT_CLK2); /* enable the ai conversion interrupt and the clock to start scans */ - dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT | DMM32AT_CLKSEL); - + outb(DMM32AT_ADINT | DMM32AT_CLKSEL, dev->iobase + DMM32AT_INTCLOCK); } static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) @@ -525,20 +522,20 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) range = CR_RANGE(cmd->chanlist[0]); /* reset fifo */ - dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET); + outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL); /* set scan enable */ - dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_SCANENABLE); + outb(DMM32AT_SCANENABLE, dev->iobase + DMM32AT_FIFOCNTRL); /* write the ai channel range regs */ - dmm_outb(dev, DMM32AT_AILOW, chanlo); - dmm_outb(dev, DMM32AT_AIHIGH, chanhi); + outb(chanlo, dev->iobase + DMM32AT_AILOW); + outb(chanhi, dev->iobase + DMM32AT_AIHIGH); /* set the range bits */ - dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]); + outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF); /* reset the interrupt just in case */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET); + outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL); if (cmd->stop_src == TRIG_COUNT) devpriv->ai_scans_left = cmd->stop_arg; @@ -563,8 +560,8 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dmm32at_setaitimer(dev, cmd->scan_begin_arg); } else { /* start the interrups and initiate a single scan */ - dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT); - dmm_outb(dev, DMM32AT_CONV, 0xff); + outb(DMM32AT_ADINT, dev->iobase + DMM32AT_INTCLOCK); + outb(0xff, dev->iobase + DMM32AT_CONV); } /* printk("dmmat32 in command\n"); */ @@ -619,7 +616,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) devpriv->ai_scans_left--; if (devpriv->ai_scans_left == 0) { /* disable further interrupts and clocks */ - dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); + outb(0x0, dev->iobase + DMM32AT_INTCLOCK); /* set the buffer to be flushed with an EOF */ s->async->events |= COMEDI_CB_EOA; } @@ -630,7 +627,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) } /* reset the interrupt */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET); + outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL); return IRQ_HANDLED; } @@ -654,8 +651,8 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, hi = (data[i] >> 8) + chan * (1 << 6); /* printk("writing 0x%02x 0x%02x\n",hi,lo); */ /* write the low and high values to the board */ - dmm_outb(dev, DMM32AT_DACLSB, lo); - dmm_outb(dev, DMM32AT_DACMSB, hi); + outb(lo, dev->iobase + DMM32AT_DACLSB); + outb(hi, dev->iobase + DMM32AT_DACMSB); /* wait for circuit to settle */ for (i = 0; i < 40000; i++) { @@ -712,21 +709,21 @@ static int dmm32at_dio_insn_bits(struct comedi_device *dev, } /* get access to the DIO regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); /* if either part of dio is set for output */ if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) || ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) { diobits = (s->state & 0x00ff0000) >> 16; - dmm_outb(dev, DMM32AT_DIOC, diobits); + outb(diobits, dev->iobase + DMM32AT_DIOC); } if ((devpriv->dio_config & DMM32AT_DIRB) == 0) { diobits = (s->state & 0x0000ff00) >> 8; - dmm_outb(dev, DMM32AT_DIOB, diobits); + outb(diobits, dev->iobase + DMM32AT_DIOB); } if ((devpriv->dio_config & DMM32AT_DIRA) == 0) { diobits = (s->state & 0x000000ff); - dmm_outb(dev, DMM32AT_DIOA, diobits); + outb(diobits, dev->iobase + DMM32AT_DIOA); } /* now read the state back in */ @@ -777,9 +774,9 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev, else devpriv->dio_config |= chanbit; /* get access to the DIO regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); /* set the DIO's to the new configuration setting */ - dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); + outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF); return 1; } @@ -813,23 +810,23 @@ static int dmm32at_attach(struct comedi_device *dev, it to a known state */ /* reset the board */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_RESET); + outb(DMM32AT_RESET, dev->iobase + DMM32AT_CNTRL); /* allow a millisecond to reset */ udelay(1000); /* zero scan and fifo control */ - dmm_outb(dev, DMM32AT_FIFOCNTRL, 0x0); + outb(0x0, dev->iobase + DMM32AT_FIFOCNTRL); /* zero interrupt and clock control */ - dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); + outb(0x0, dev->iobase + DMM32AT_INTCLOCK); /* write a test channel range, the high 3 bits should drop */ - dmm_outb(dev, DMM32AT_AILOW, 0x80); - dmm_outb(dev, DMM32AT_AIHIGH, 0xff); + outb(0x80, dev->iobase + DMM32AT_AILOW); + outb(0xff, dev->iobase + DMM32AT_AIHIGH); /* set the range at 10v unipolar */ - dmm_outb(dev, DMM32AT_AICONF, DMM32AT_RANGE_U10); + outb(DMM32AT_RANGE_U10, dev->iobase + DMM32AT_AICONF); /* should take 10 us to settle, here's a hundred */ udelay(100); @@ -908,11 +905,11 @@ static int dmm32at_attach(struct comedi_device *dev, if (board->have_dio) { /* get access to the DIO regs */ - dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); /* set the DIO's to the defualt input setting */ devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; - dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); + outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF); /* set up the subdevice */ s->type = COMEDI_SUBD_DIO; -- GitLab From 2792182816be376391c2cfc142bfd32f3ab8c5cd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:13:53 -0700 Subject: [PATCH 2094/5711] staging: comedi: dmm32at: remove unneeded boardinfo variables Like most of the comedi drivers, this one appears to have been started based on the skel driver. Cut-and-paste from that driver has resulted in an unnecessarily complex boardinfo struct. Remove everything from the boardinfo struct, except the 'name', and just use the open coded values in the attach function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 71 ++++++++---------------- 1 file changed, 23 insertions(+), 48 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 2ae31e8aab40..1d21e2291315 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -156,21 +156,8 @@ static const struct comedi_lrange dmm32at_aoranges = { } }; -/* - * Board descriptions for two imaginary boards. Describing the - * boards in this way is optional, and completely driver-dependent. - * Some drivers use arrays such as this, other do not. - */ struct dmm32at_board { const char *name; - int ai_chans; - int ai_bits; - const struct comedi_lrange *ai_ranges; - int ao_chans; - int ao_bits; - const struct comedi_lrange *ao_ranges; - int have_dio; - int dio_chans; }; /* this structure is for data unique to this hardware driver. If @@ -880,9 +867,9 @@ static int dmm32at_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AI; /* we support single-ended (ground) and differential */ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; - s->n_chan = board->ai_chans; - s->maxdata = (1 << board->ai_bits) - 1; - s->range_table = board->ai_ranges; + s->n_chan = 32; + s->maxdata = 0xffff; + s->range_table = &dmm32at_airanges; s->len_chanlist = 32; /* This is the maximum chanlist length that the board can handle */ s->insn_read = dmm32at_ai_rinsn; @@ -894,35 +881,31 @@ static int dmm32at_attach(struct comedi_device *dev, /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = board->ao_chans; - s->maxdata = (1 << board->ao_bits) - 1; - s->range_table = board->ao_ranges; + s->n_chan = 4; + s->maxdata = 0x0fff; + s->range_table = &dmm32at_aoranges; s->insn_write = dmm32at_ao_winsn; s->insn_read = dmm32at_ao_rinsn; s = dev->subdevices + 2; /* digital i/o subdevice */ - if (board->have_dio) { - - /* get access to the DIO regs */ - outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); - /* set the DIO's to the defualt input setting */ - devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | - DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; - outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF); - - /* set up the subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = board->dio_chans; - s->maxdata = 1; - s->state = 0; - s->range_table = &range_digital; - s->insn_bits = dmm32at_dio_insn_bits; - s->insn_config = dmm32at_dio_insn_config; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + + /* get access to the DIO regs */ + outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); + /* set the DIO's to the defualt input setting */ + devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | + DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; + outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF); + + /* set up the subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->maxdata = 1; + s->state = 0; + s->range_table = &range_digital; + s->insn_bits = dmm32at_dio_insn_bits; + s->insn_config = dmm32at_dio_insn_config; /* success */ printk(KERN_INFO "comedi%d: dmm32at: attached\n", dev->minor); @@ -942,14 +925,6 @@ static void dmm32at_detach(struct comedi_device *dev) static const struct dmm32at_board dmm32at_boards[] = { { .name = "dmm32at", - .ai_chans = 32, - .ai_bits = 16, - .ai_ranges = &dmm32at_airanges, - .ao_chans = 4, - .ao_bits = 12, - .ao_ranges = &dmm32at_aoranges, - .have_dio = 1, - .dio_chans = 24, }, }; -- GitLab From 3eff01744009de100f03a1dc2e3d5f98da2235e5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:14:27 -0700 Subject: [PATCH 2095/5711] staging: comedi: dmm32at: remove devpriv macro The 'devpriv' macro relies on a local variable having a specific name and yields a pointer derived from that local variable. Replace the macro with a local variable where used. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 1d21e2291315..f0221e9b3623 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -176,12 +176,6 @@ struct dmm32at_private { }; -/* - * most drivers define the following macro to make it easy to - * access the private structure. - */ -#define devpriv ((struct dmm32at_private *)dev->private) - /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -494,6 +488,7 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct dmm32at_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int i, range; unsigned char chanlo, chanhi, status; @@ -566,17 +561,20 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int dmm32at_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { + struct dmm32at_private *devpriv = dev->private; + devpriv->ai_scans_left = 1; return 0; } static irqreturn_t dmm32at_isr(int irq, void *d) { + struct comedi_device *dev = d; + struct dmm32at_private *devpriv = dev->private; unsigned char intstat; unsigned int samp; unsigned short msb, lsb; int i; - struct comedi_device *dev = d; if (!dev->attached) { comedi_error(dev, "spurious interrupt"); @@ -622,6 +620,7 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct dmm32at_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); unsigned char hi, lo, status; @@ -666,6 +665,7 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct dmm32at_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -684,6 +684,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct dmm32at_private *devpriv = dev->private; unsigned char diobits; /* The insn data is a mask in data[0] and the new data @@ -735,6 +736,7 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct dmm32at_private *devpriv = dev->private; unsigned char chanbit; int chan = CR_CHAN(insn->chanspec); @@ -772,6 +774,7 @@ static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct dmm32at_board *board = comedi_board(dev); + struct dmm32at_private *devpriv; int ret; struct comedi_subdevice *s; unsigned char aihi, ailo, fifostat, aistat, intstat, airback; @@ -854,8 +857,9 @@ static int dmm32at_attach(struct comedi_device *dev, * Allocate the private structure area. alloc_private() is a * convenient macro defined in comedidev.h. */ - if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) + if (alloc_private(dev, sizeof(*devpriv)) < 0) return -ENOMEM; + devpriv = dev->private; ret = comedi_alloc_subdevices(dev, 3); if (ret) -- GitLab From f4ce61a0ca021d9226da9c3269899ae75725468a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 18:15:02 -0700 Subject: [PATCH 2096/5711] staging: comedi: dmm32at: remove skel driver cut-and-paste comments Remove the cut-and-paste comments from the skel driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 40 ------------------------ 1 file changed, 40 deletions(-) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index f0221e9b3623..7107f590b1fe 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -160,10 +160,6 @@ struct dmm32at_board { const char *name; }; -/* this structure is for data unique to this hardware driver. If - * several hardware drivers keep similar information in this structure, - * feel free to suggest moving the variable to the struct comedi_device struct. - */ struct dmm32at_private { int data; @@ -176,11 +172,6 @@ struct dmm32at_private { }; -/* - * "instructions" read/write data in "one-shot" or "software-triggered" - * mode. - */ - static int dmm32at_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -253,20 +244,9 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, return n; } -/* This function doesn't require a particular form, this is just - * what happens to be used in some of the drivers. It should - * convert ns nanoseconds to a counter value suitable for programming - * the device. Also, it should adjust ns so that it cooresponds to - * the actual time that the device will use. */ static int dmm32at_ns_to_timer(unsigned int *ns, int round) { /* trivial timer */ - /* if your timing is done through two cascaded timers, the - * i8253_cascade_ns_to_timer() function in 8253.h can be - * very helpful. There are also i8254_load() and i8254_mm_load() - * which can be used to load values into the ubiquitous 8254 counters - */ - return *ns; } @@ -278,15 +258,6 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, int tmp; int start_chan, gain, i; - /* printk("dmmat32 in command test\n"); */ - - /* cmdtest tests a particular command to see if it is valid. - * Using the cmdtest ioctl, a user can create a valid cmd - * and then have it executes by the cmd ioctl. - * - * cmdtest returns 1,2,3,4 or 0, depending on which tests - * the command passes. */ - /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; @@ -659,8 +630,6 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, return i; } -/* AO subdevices should have a read insn as well as a write insn. - * Usually this means copying a value stored in devpriv. */ static int dmm32at_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -675,11 +644,6 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev, return i; } -/* DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write */ static int dmm32at_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -853,10 +817,6 @@ static int dmm32at_attach(struct comedi_device *dev, dev->board_name = board->name; -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ if (alloc_private(dev, sizeof(*devpriv)) < 0) return -ENOMEM; devpriv = dev->private; -- GitLab From c14d1769ba81ed084adb450d2fa1bacaee3cd2c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 2 Jul 2012 14:26:24 -0700 Subject: [PATCH 2097/5711] staging: comedi: s626: fix the number of dio channels The first digital i/o subdevice has its n_chan set to S626_DIO_CHANNELS which is defined as 48. This is actually the total number of channels provided by all three digital i/o subdevices. Each subdevice only has 16 channels. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index bef9649960b8..f90578e5e727 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2636,7 +2636,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital I/O subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = S626_DIO_CHANNELS; + s->n_chan = 16; s->maxdata = 1; s->io_bits = 0xffff; s->private = &dio_private_A; -- GitLab From 3ec50be588d773b408e82643c87c5a681b0354ad Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:28:55 +0200 Subject: [PATCH 2098/5711] Staging: echo: One variable per line Our convention is one (statement and) variable per line. Enforce this in drivers/staging/echo/echo.[ch] . Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/echo/echo.c | 9 ++++++--- drivers/staging/echo/echo.h | 28 ++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c index afbf5442b42b..ca87ce9874b1 100644 --- a/drivers/staging/echo/echo.c +++ b/drivers/staging/echo/echo.c @@ -118,7 +118,8 @@ #ifdef __bfin__ static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) { - int i, j; + int i; + int j; int offset1; int offset2; int factor; @@ -335,7 +336,8 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx) { int32_t echo_value; int clean_bg; - int tmp, tmp1; + int tmp; + int tmp1; /* * Input scaling was found be required to prevent problems when tx @@ -624,7 +626,8 @@ EXPORT_SYMBOL_GPL(oslec_update); int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx) { - int tmp, tmp1; + int tmp; + int tmp1; if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) { tmp = tx << 15; diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h index 754e66d30c1b..32ca9dedeca4 100644 --- a/drivers/staging/echo/echo.h +++ b/drivers/staging/echo/echo.h @@ -36,7 +36,6 @@ What does it do? This module aims to provide G.168-2002 compliant echo cancellation, to remove electrical echoes (e.g. from 2-4 wire hybrids) from voice calls. - How does it work? The heart of the echo cancellor is FIR filter. This is adapted to match the @@ -128,7 +127,8 @@ a minor burden. echo canceller. */ struct oslec_state { - int16_t tx, rx; + int16_t tx; + int16_t rx; int16_t clean; int16_t clean_nlp; @@ -145,11 +145,18 @@ struct oslec_state { int16_t shift; /* Average levels and averaging filter states */ - int Ltxacc, Lrxacc, Lcleanacc, Lclean_bgacc; - int Ltx, Lrx; + int Ltxacc; + int Lrxacc; + int Lcleanacc; + int Lclean_bgacc; + int Ltx; + int Lrx; int Lclean; int Lclean_bg; - int Lbgn, Lbgn_acc, Lbgn_upper, Lbgn_upper_acc; + int Lbgn; + int Lbgn_acc; + int Lbgn_upper; + int Lbgn_upper_acc; /* foreground and background filter states */ struct fir16_state_t fir_state; @@ -157,11 +164,16 @@ struct oslec_state { int16_t *fir_taps16[2]; /* DC blocking filter states */ - int tx_1, tx_2, rx_1, rx_2; + int tx_1; + int tx_2; + int rx_1; + int rx_2; /* optional High Pass Filter states */ - int32_t xvtx[5], yvtx[5]; - int32_t xvrx[5], yvrx[5]; + int32_t xvtx[5]; + int32_t yvtx[5]; + int32_t xvrx[5]; + int32_t yvrx[5]; /* Parameters for the optional Hoth noise generator */ int cng_level; -- GitLab From 7813296d2259dd5056278bcf8b2fdeaaf8499f1f Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Wed, 27 Jun 2012 14:10:14 +0200 Subject: [PATCH 2099/5711] staging: sm7xxfb: rename vars holding device and revision ids This patch fixes CamelCase var names in smtcfb_info holding device and revision identifiers. Tested with SM712. Signed-off-by: Javier M. Mellid Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xxfb.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 16d2b5eda80c..c603e8c2c360 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -42,8 +42,9 @@ struct screen_info smtc_screen_info; struct smtcfb_info { struct fb_info fb; struct pci_dev *pdev; + u16 chip_id; + u8 chip_rev_id; - u16 chipID; unsigned char __iomem *m_pMMIO; char __iomem *m_pLFB; char *m_pDPR; @@ -53,8 +54,6 @@ struct smtcfb_info { u_int width; u_int height; u_int hz; - - u8 chipRevID; }; struct vesa_mode_table { @@ -231,7 +230,7 @@ static void sm712_setpalette(int regno, unsigned red, unsigned green, static void smtc_set_timing(struct smtcfb_info *sfb) { - switch (sfb->chipID) { + switch (sfb->chip_id) { case 0x710: case 0x712: case 0x720: @@ -812,8 +811,8 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, if (!sfb) goto failed_free; - sfb->chipID = ent->device; - sprintf(name, "sm%Xfb", sfb->chipID); + sfb->chip_id = ent->device; + sprintf(name, "sm%Xfb", sfb->chip_id); pci_set_drvdata(pdev, sfb); @@ -837,9 +836,9 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, #endif /* Map address and memory detection */ pFramebufferPhysical = pci_resource_start(pdev, 0); - pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chipRevID); + pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id); - switch (sfb->chipID) { + switch (sfb->chip_id) { case 0x710: case 0x712: sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000; @@ -925,7 +924,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.", - sfb->chipID, sfb->chipRevID, sfb->fb.var.xres, + sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres, sfb->fb.var.yres, sfb->fb.var.bits_per_pixel); return 0; @@ -1001,7 +1000,7 @@ static int smtcfb_pci_resume(struct device *device) /* reinit hardware */ sm7xx_init_hw(); - switch (sfb->chipID) { + switch (sfb->chip_id) { case 0x710: case 0x712: /* set MCLK = 14.31818 * (0x16 / 0x2) */ -- GitLab From 501b02e4d6a3c29ce4e7cef9a5a1a21f236c3c63 Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Wed, 27 Jun 2012 14:10:15 +0200 Subject: [PATCH 2100/5711] staging: sm7xxfb: erase hardcode cast between smtcfb_info and fb_info This patch erases hardcode cast between smtcfb_info and fb_info in order to get a more robust and less rigid smtcfb_info structure. fb_info doesn't need to be the first field in smtcfb_info after this patch. Tested with SM712. Signed-off-by: Javier M. Mellid Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xxfb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index c603e8c2c360..e3511ecd0980 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -40,8 +40,8 @@ struct screen_info smtc_screen_info; * Private structure */ struct smtcfb_info { - struct fb_info fb; struct pci_dev *pdev; + struct fb_info fb; u16 chip_id; u8 chip_rev_id; @@ -328,9 +328,11 @@ static int smtc_blank(int blank_mode, struct fb_info *info) static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned trans, struct fb_info *info) { - struct smtcfb_info *sfb = (struct smtcfb_info *)info; + struct smtcfb_info *sfb; u32 val; + sfb = info->par; + if (regno > 255) return 1; @@ -623,9 +625,7 @@ static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int smtc_set_par(struct fb_info *info) { - struct smtcfb_info *sfb = (struct smtcfb_info *)info; - - smtcfb_setmode(sfb); + smtcfb_setmode(info->par); return 0; } -- GitLab From fec3c80da1abfb4c66ba0adf77f3c7a97a8162da Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:00:14 +0200 Subject: [PATCH 2101/5711] staging: vt6656: int: Redundant blank line removal This trivial cleanup patch removes some completely redundant blank lines from drivers/staging/vt6656/int.[ch] Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 4 ---- drivers/staging/vt6656/int.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 0a114231145f..36ed23407030 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -44,7 +44,6 @@ /* static int msglevel = MSG_LEVEL_DEBUG; */ static int msglevel = MSG_LEVEL_INFO; - /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ @@ -53,10 +52,8 @@ static int msglevel = MSG_LEVEL_INFO; /*--------------------- Export Variables --------------------------*/ - /*--------------------- Export Functions --------------------------*/ - /*+ * * Function: InterruptPollingThread @@ -202,7 +199,6 @@ void INTnsProcessData(PSDevice pDevice) pINTData->byISR0, pINTData->byISR1); } - if (pINTData->byISR1 != 0) if (pINTData->byISR1 & ISR_GPIO3) bScheduleCommand((void *) pDevice, diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index a5d96b968176..30986305d28f 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -60,7 +60,6 @@ typedef struct tagSINTData { } __attribute__ ((__packed__)) SINTData, *PSINTData; - /*--------------------- Export Classes ----------------------------*/ /*--------------------- Export Variables --------------------------*/ -- GitLab From c6058cb3c7f1e2204aca958a0f91473b2cd14684 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:00:41 +0200 Subject: [PATCH 2102/5711] staging: vt6656: int.h: Fix indentation and spacing We use tabs for indentation and once space between variable types and variable name. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.h | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index 30986305d28f..3734e2c953d9 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -36,27 +36,27 @@ /*--------------------- Export Definitions -------------------------*/ #pragma pack(1) typedef struct tagSINTData { - BYTE byTSR0; - BYTE byPkt0; - WORD wTime0; - BYTE byTSR1; - BYTE byPkt1; - WORD wTime1; - BYTE byTSR2; - BYTE byPkt2; - WORD wTime2; - BYTE byTSR3; - BYTE byPkt3; - WORD wTime3; - DWORD dwLoTSF; - DWORD dwHiTSF; - BYTE byISR0; - BYTE byISR1; - BYTE byRTSSuccess; - BYTE byRTSFail; - BYTE byACKFail; - BYTE byFCSErr; - BYTE abySW[2]; + BYTE byTSR0; + BYTE byPkt0; + WORD wTime0; + BYTE byTSR1; + BYTE byPkt1; + WORD wTime1; + BYTE byTSR2; + BYTE byPkt2; + WORD wTime2; + BYTE byTSR3; + BYTE byPkt3; + WORD wTime3; + DWORD dwLoTSF; + DWORD dwHiTSF; + BYTE byISR0; + BYTE byISR1; + BYTE byRTSSuccess; + BYTE byRTSFail; + BYTE byACKFail; + BYTE byFCSErr; + BYTE abySW[2]; } __attribute__ ((__packed__)) SINTData, *PSINTData; -- GitLab From ea15b7b219b19c9ddb668ab3d5d727f46900605e Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:01:18 +0200 Subject: [PATCH 2103/5711] staging: vt6656: int.c: Put comment about DEBUG print define on same line as code A small comment at the end of the line, mentioning the debug level, is enough - no need to repeat the entire line of code just for that. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 36ed23407030..286ac3e46075 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -41,8 +41,7 @@ #include "usbpipe.h" /*--------------------- Static Definitions -------------------------*/ -/* static int msglevel = MSG_LEVEL_DEBUG; */ -static int msglevel = MSG_LEVEL_INFO; +static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */ /*--------------------- Static Classes ----------------------------*/ -- GitLab From 92fa8971f31b25e041a74a1913bca8f7f3d6e48d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:01:47 +0200 Subject: [PATCH 2104/5711] staging: vt6656: int.c: Remove unneeded cast When assigning a void* to a variable , the value is cast implicitly - there's no need for explicit cast. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 286ac3e46075..e7f66241b9b5 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -77,7 +77,7 @@ static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */ -*/ void INTvWorkItem(void *Context) { - PSDevice pDevice = (PSDevice) Context; + PSDevice pDevice = Context; int ntStatus; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Interrupt Polling Thread\n"); -- GitLab From 0d12698671e6d6e39804cdadc6e65a40e5d0f491 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:02:19 +0200 Subject: [PATCH 2105/5711] staging: vt6656: int.c: Use one space between variable type and name The style of most kernel code is that there is 1 *space* between the type of a variable and its name. This patch enforces that in drivers/staging/vt6656/int.c . Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index e7f66241b9b5..40605c8137e3 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -90,8 +90,8 @@ void INTvWorkItem(void *Context) void INTnsProcessData(PSDevice pDevice) { - PSINTData pINTData; - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PSINTData pINTData; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); struct net_device_stats *pStats = &pDevice->stats; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n"); -- GitLab From 7b4cabb658fdf9171ecea4e10fb14ee76d14cb37 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:02:48 +0200 Subject: [PATCH 2106/5711] staging: vt6656: int.c: We don't use spaces between a cast and the variable being converted Remove spaces between casts and variables from drivers/staging/vt6656/int.c . Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 40605c8137e3..e9fab455d805 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -99,8 +99,8 @@ void INTnsProcessData(PSDevice pDevice) pINTData = (PSINTData) pDevice->intBuf.pDataBuf; if (pINTData->byTSR0 & TSR_VALID) { STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (BYTE) (pINTData->byPkt0 & 0x0F), - (BYTE) (pINTData->byPkt0>>4), + (BYTE)(pINTData->byPkt0 & 0x0F), + (BYTE)(pINTData->byPkt0>>4), pINTData->byTSR0); BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), @@ -110,8 +110,8 @@ void INTnsProcessData(PSDevice pDevice) } if (pINTData->byTSR1 & TSR_VALID) { STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (BYTE) (pINTData->byPkt1 & 0x0F), - (BYTE) (pINTData->byPkt1>>4), + (BYTE)(pINTData->byPkt1 & 0x0F), + (BYTE)(pINTData->byPkt1>>4), pINTData->byTSR1); BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), @@ -121,8 +121,8 @@ void INTnsProcessData(PSDevice pDevice) } if (pINTData->byTSR2 & TSR_VALID) { STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (BYTE) (pINTData->byPkt2 & 0x0F), - (BYTE) (pINTData->byPkt2>>4), + (BYTE)(pINTData->byPkt2 & 0x0F), + (BYTE)(pINTData->byPkt2>>4), pINTData->byTSR2); BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), @@ -132,8 +132,8 @@ void INTnsProcessData(PSDevice pDevice) } if (pINTData->byTSR3 & TSR_VALID) { STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (BYTE) (pINTData->byPkt3 & 0x0F), - (BYTE) (pINTData->byPkt3>>4), + (BYTE)(pINTData->byPkt3 & 0x0F), + (BYTE)(pINTData->byPkt3>>4), pINTData->byTSR3); BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), -- GitLab From ce3eaedfc0df2f115051b19d303e4c7ff1e0aaaa Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jun 2012 22:03:30 +0200 Subject: [PATCH 2107/5711] staging: vt6656: int.c: correct indentation to use tabs rather than spaces Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index e9fab455d805..eba4b5061cf7 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -182,11 +182,11 @@ void INTnsProcessData(PSDevice pDevice) LODWORD(pDevice->qwCurrTSF) = pINTData->dwLoTSF; HIDWORD(pDevice->qwCurrTSF) = pINTData->dwHiTSF; /*DBG_PRN_GRP01(("ISR0 = %02x , - LoTsf = %08x, - HiTsf = %08x\n", - pINTData->byISR0, - pINTData->dwLoTSF, - pINTData->dwHiTSF)); */ + LoTsf = %08x, + HiTsf = %08x\n", + pINTData->byISR0, + pINTData->dwLoTSF, + pINTData->dwHiTSF)); */ STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, @@ -208,8 +208,8 @@ void INTnsProcessData(PSDevice pDevice) pStats->tx_packets = pDevice->scStatistic.ullTsrOK; pStats->tx_bytes = pDevice->scStatistic.ullTxDirectedBytes + - pDevice->scStatistic.ullTxMulticastBytes + - pDevice->scStatistic.ullTxBroadcastBytes; + pDevice->scStatistic.ullTxMulticastBytes + + pDevice->scStatistic.ullTxBroadcastBytes; pStats->tx_errors = pDevice->scStatistic.dwTsrErr; pStats->tx_dropped = pDevice->scStatistic.dwTsrErr; } -- GitLab From 50836770601d3cc8408367de34fa5ece23e7e9b8 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 27 Jun 2012 15:11:38 -0500 Subject: [PATCH 2108/5711] staging: drm/omap: update TODO Update TODO file, which had been neglected. Signed-off-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/TODO | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO index 55b18377ac4f..938c7888ca31 100644 --- a/drivers/staging/omapdrm/TODO +++ b/drivers/staging/omapdrm/TODO @@ -1,9 +1,7 @@ TODO -. check error handling/cleanup paths -. add drm_plane / overlay support . add video decode/encode support (via syslink3 + codec-engine) -. still some rough edges with flipping.. event back to userspace should - really come after VSYNC interrupt + . NOTE: with dmabuf this probably could be split into different driver + so perhaps this TODO doesn't belong here . where should we do eviction (detatch_pages())? We aren't necessarily accessing the pages via a GART, so maybe we need some other threshold to put a cap on the # of pages that can be pin'd. (It is mostly only @@ -27,7 +25,6 @@ TODO CRTC's should be disabled, and on resume the LUT should be reprogrammed before CRTC's are re-enabled, to prevent DSS from trying to DMA from a buffer mapped in DMM/TILER before LUT is reloaded. -. Add debugfs information for DMM/TILER Userspace: . git://github.com/robclark/xf86-video-omap.git -- GitLab From 2471c0933988eede8040d58cefd6be4fbef9c057 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:25:55 +0200 Subject: [PATCH 2109/5711] staging: line6: changed interface of line6_transmit_parameter() Interface of line6_transmit_parameter() adjusted to clarify internal workings Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/driver.c | 2 +- drivers/staging/line6/driver.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index 4513f78f1127..d86123041194 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -526,7 +526,7 @@ int line6_send_program(struct usb_line6 *line6, int value) /* Transmit Line6 control parameter. */ -int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) +int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value) { int retval; unsigned char *buffer; diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h index 117bf9943568..140ccfe0815d 100644 --- a/drivers/staging/line6/driver.h +++ b/drivers/staging/line6/driver.h @@ -224,7 +224,7 @@ extern void line6_start_timer(struct timer_list *timer, unsigned int msecs, void (*function) (unsigned long), unsigned long data); extern int line6_transmit_parameter(struct usb_line6 *line6, int param, - int value); + u8 value); extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_write_data(struct usb_line6 *line6, int address, void *data, size_t datalen); -- GitLab From 1383ec4dad392a1c316820e9afb27b5fb95a6f57 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:25:56 +0200 Subject: [PATCH 2110/5711] staging: line6: Changed some strict_strtouls to kstrtou8 Adjusted strict_strtoul calls to kstrtou8 in order to take the changes of line6_transmit_parameter() into account. Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/variax.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c index d36622228b2d..bb99ee4919e7 100644 --- a/drivers/staging/line6/variax.c +++ b/drivers/staging/line6/variax.c @@ -319,10 +319,10 @@ static ssize_t variax_set_volume(struct device *dev, { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - unsigned long value; + u8 value; int ret; - ret = strict_strtoul(buf, 10, &value); + ret = kstrtou8(buf, 10, &value); if (ret) return ret; @@ -418,10 +418,10 @@ static ssize_t variax_set_tone(struct device *dev, { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - unsigned long value; + u8 value; int ret; - ret = strict_strtoul(buf, 10, &value); + ret = kstrtou8(buf, 10, &value); if (ret) return ret; -- GitLab From 5b9bd2ad5116c735cf8e4fa1689319849086a55e Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:25:57 +0200 Subject: [PATCH 2111/5711] staging: line6: changed interface of line6_pod_transmit_parameter() Adjusted interface of line6_pod_transmit_parameter() to take changes of line6_transmit_parameter() into account Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pod.c | 2 +- drivers/staging/line6/pod.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 4dadc571d961..8667aaf51459 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -419,7 +419,7 @@ static void pod_send_channel(struct usb_line6_pod *pod, int value) Transmit PODxt Pro control parameter. */ void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, - int value) + u8 value) { if (line6_transmit_parameter(&pod->line6, param, value) == 0) pod_store_parameter(pod, param, value); diff --git a/drivers/staging/line6/pod.h b/drivers/staging/line6/pod.h index 18b9d08c3288..47e0d1a1c4b9 100644 --- a/drivers/staging/line6/pod.h +++ b/drivers/staging/line6/pod.h @@ -200,6 +200,6 @@ extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length); extern void line6_pod_process_message(struct usb_line6_pod *pod); extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, - int value); + u8 value); #endif -- GitLab From 317e188b2d48b7bc8537619b6c01208e1b03001a Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:25:58 +0200 Subject: [PATCH 2112/5711] staging: line6: adjusted interface of line6_send_program() Adjusted interface of line6_send_program() to clarify internal working Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/driver.c | 2 +- drivers/staging/line6/driver.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index d86123041194..b8358ca71bdd 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -490,7 +490,7 @@ static void line6_data_received(struct urb *urb) /* Send channel number (i.e., switch to a different sound). */ -int line6_send_program(struct usb_line6 *line6, int value) +int line6_send_program(struct usb_line6 *line6, u8 value) { int retval; unsigned char *buffer; diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h index 140ccfe0815d..a3029eb223d6 100644 --- a/drivers/staging/line6/driver.h +++ b/drivers/staging/line6/driver.h @@ -209,7 +209,7 @@ extern int line6_read_data(struct usb_line6 *line6, int address, void *data, size_t datalen); extern int line6_read_serial_number(struct usb_line6 *line6, int *serial_number); -extern int line6_send_program(struct usb_line6 *line6, int value); +extern int line6_send_program(struct usb_line6 *line6, u8 value); extern int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int size); extern int line6_send_raw_message_async(struct usb_line6 *line6, -- GitLab From 8d6b7f7c9b3c346f2fef496827c3fbbc2ebef1a9 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:25:59 +0200 Subject: [PATCH 2113/5711] staging: line6: changed interface of pod_send_channel() Adjusted interface of pod_send_channel() in order to take changes of line6_send_program() into account. Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 8667aaf51459..459f325ed7b8 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -405,7 +405,7 @@ void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, /* Send channel number (i.e., switch to a different sound). */ -static void pod_send_channel(struct usb_line6_pod *pod, int value) +static void pod_send_channel(struct usb_line6_pod *pod, u8 value) { line6_invalidate_current(&pod->dumpreq); -- GitLab From 336cab9afa2567fd41d2813d3f0f9249371219cb Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:26:00 +0200 Subject: [PATCH 2114/5711] staging: line6: control.c eliminate strict_strtoul() in pod_set_param_int() Exchange strict_strtoul() with kstrtou8() and make "value" a u8 instead of a unsigned long. This is also needed for the changed line6_pod_transmit_parameter(). Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c index 67e23b6e2d35..f8326f587e38 100644 --- a/drivers/staging/line6/control.c +++ b/drivers/staging/line6/control.c @@ -55,10 +55,10 @@ static ssize_t pod_set_param_int(struct device *dev, const char *buf, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - unsigned long value; + u8 value; int retval; - retval = strict_strtoul(buf, 10, &value); + retval = kstrtou8(buf, 10, &value); if (retval) return retval; -- GitLab From 1d0e834d62c6810385c2f0673cf6bd97a59aae68 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:26:01 +0200 Subject: [PATCH 2115/5711] staging: line6: Exchanged strict_strtoul with kstrtou8() in pod.c:pod_resolve() Exchanged call to strict_strtoul() with kstrtou8() in pod_resolve(). Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 459f325ed7b8..4c81914759a9 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -434,11 +434,11 @@ void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, static int pod_resolve(const char *buf, short block0, short block1, unsigned char *location) { - unsigned long value; + u8 value; short block; int ret; - ret = strict_strtoul(buf, 10, &value); + ret = kstrtou8(buf, 10, &value); if (ret) return ret; -- GitLab From a4fb7d53869f848fcef91fc6b571e0e8f6e835ce Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:26:02 +0200 Subject: [PATCH 2116/5711] staging: line6: Changed strict_strtoul() to kstrtou8() in pod_set_channel() Changed strict_strtoul() to kstrtou() in pod_set_channel() to take changes in pod_send_channel() into account. Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 4c81914759a9..2a85ec39fe47 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -560,10 +560,10 @@ static ssize_t pod_set_channel(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - unsigned long value; + u8 value; int ret; - ret = strict_strtoul(buf, 10, &value); + ret = kstrtou8(buf, 10, &value); if (ret) return ret; -- GitLab From 06501787d843608c83864cc241f4fd464ce385ca Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jun 2012 21:26:03 +0200 Subject: [PATCH 2117/5711] staging: line6: Changed strict_strtoul() to kstrtou8() in pod_set_midi_postprocess() Changed a call to strict_strtoul() into kstrtou8() in pod_set_midi_postprocess(). Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 2a85ec39fe47..9edd053fb9ae 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -892,10 +892,10 @@ static ssize_t pod_set_midi_postprocess(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - unsigned long value; + u8 value; int ret; - ret = strict_strtoul(buf, 10, &value); + ret = kstrtou8(buf, 10, &value); if (ret) return ret; -- GitLab From c133482300113b3b71fa4a1fd2118531e765b36a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 20 May 2012 11:17:12 -0300 Subject: [PATCH 2118/5711] [media] V4L: Remove "_ACTIVE" from the selection target name definitions This patch drops the _ACTIVE part from the selection target names as a prerequisite to unify the selection target names across the subdev and regular video node API. The meaning of V4L2_SEL_TGT_*_ACTIVE and V4L2_SUBDEV_SEL_TGT_*_ACTUAL selection targets is logically the same. Different names add to confusion where both APIs are used in a single driver or an application. For some system configurations different names may lead to interoperability issues. For backwards compatibility V4L2_SEL_TGT_CROP_ACTIVE and V4L2_SEL_TGT_COMPOSE_ACTIVE are defined as aliases to V4L2_SEL_TGT_CROP and V4L2_SEL_TGT_COMPOSE. These aliases will be removed after deprecation period, according to Documentation/feature-removal-schedule.txt. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/selection-api.xml | 24 +++++++++---------- .../DocBook/media/v4l/vidioc-g-selection.xml | 15 ++++++------ drivers/media/video/s5p-fimc/fimc-capture.c | 14 +++++------ drivers/media/video/s5p-fimc/fimc-lite.c | 4 ++-- drivers/media/video/s5p-jpeg/jpeg-core.c | 4 ++-- drivers/media/video/s5p-tv/mixer_video.c | 8 +++---- include/linux/videodev2.h | 8 +++++-- 7 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml index b299e4779354..ac013e50e0bd 100644 --- a/Documentation/DocBook/media/v4l/selection-api.xml +++ b/Documentation/DocBook/media/v4l/selection-api.xml @@ -91,7 +91,7 @@ top/left corner at position (0,0) . The rectangle's coordinates are expressed in pixels. The top left corner, width and height of the source rectangle, that is -the area actually sampled, is given by the V4L2_SEL_TGT_CROP_ACTIVE +the area actually sampled, is given by the V4L2_SEL_TGT_CROP target. It uses the same coordinate system as V4L2_SEL_TGT_CROP_BOUNDS . The active cropping area must lie completely inside the capture boundaries. The driver may further adjust the @@ -111,7 +111,7 @@ height are equal to the image size set by VIDIOC_S_FMT . The part of a buffer into which the image is inserted by the hardware is -controlled by the V4L2_SEL_TGT_COMPOSE_ACTIVE target. +controlled by the V4L2_SEL_TGT_COMPOSE target. The rectangle's coordinates are also expressed in the same coordinate system as the bounds rectangle. The composing rectangle must lie completely inside bounds rectangle. The driver must adjust the composing rectangle to fit to the @@ -125,7 +125,7 @@ bounding rectangle. The part of a buffer that is modified by the hardware is given by V4L2_SEL_TGT_COMPOSE_PADDED . It contains all pixels -defined using V4L2_SEL_TGT_COMPOSE_ACTIVE plus all +defined using V4L2_SEL_TGT_COMPOSE plus all padding data modified by hardware during insertion process. All pixels outside this rectangle must not be changed by the hardware. The content of pixels that lie inside the padded area but outside active area is @@ -153,7 +153,7 @@ specified using VIDIOC_S_FMT ioctl. The top left corner, width and height of the source rectangle, that is the area from which image date are processed by the hardware, is given by the - V4L2_SEL_TGT_CROP_ACTIVE . Its coordinates are expressed + V4L2_SEL_TGT_CROP . Its coordinates are expressed in in the same coordinate system as the bounds rectangle. The active cropping area must lie completely inside the crop boundaries and the driver may further adjust the requested size and/or position according to hardware @@ -165,7 +165,7 @@ bounding rectangle. The part of a video signal or graphics display where the image is inserted by the hardware is controlled by -V4L2_SEL_TGT_COMPOSE_ACTIVE target. The rectangle's coordinates +V4L2_SEL_TGT_COMPOSE target. The rectangle's coordinates are expressed in pixels. The composing rectangle must lie completely inside the bounds rectangle. The driver must adjust the area to fit to the bounding limits. Moreover, the driver can perform other adjustments according to @@ -184,7 +184,7 @@ such a padded area is driver-dependent feature not covered by this document. Driver developers are encouraged to keep padded rectangle equal to active one. The padded target is accessed by the V4L2_SEL_TGT_COMPOSE_PADDED identifier. It must contain all pixels from the -V4L2_SEL_TGT_COMPOSE_ACTIVE target. +V4L2_SEL_TGT_COMPOSE target.
@@ -193,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE target. Scaling control An application can detect if scaling is performed by comparing the width -and the height of rectangles obtained using V4L2_SEL_TGT_CROP_ACTIVE - and V4L2_SEL_TGT_COMPOSE_ACTIVE targets. If +and the height of rectangles obtained using V4L2_SEL_TGT_CROP + and V4L2_SEL_TGT_COMPOSE targets. If these are not equal then the scaling is applied. The application can compute the scaling ratios using these values. @@ -252,7 +252,7 @@ area) ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel); if (ret) exit(-1); - sel.target = V4L2_SEL_TGT_CROP_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP; ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel); if (ret) exit(-1); @@ -281,7 +281,7 @@ area) r.left = sel.r.width / 4; r.top = sel.r.height / 4; sel.r = r; - sel.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; + sel.target = V4L2_SEL_TGT_COMPOSE; sel.flags = V4L2_SEL_FLAG_LE; ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel); if (ret) @@ -298,11 +298,11 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT for other devices &v4l2-selection; compose = { .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, - .target = V4L2_SEL_TGT_COMPOSE_ACTIVE, + .target = V4L2_SEL_TGT_COMPOSE, }; &v4l2-selection; crop = { .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, - .target = V4L2_SEL_TGT_CROP_ACTIVE, + .target = V4L2_SEL_TGT_CROP, }; double hscale, vscale; diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml index bb04eff75f45..6376e57ff576 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml @@ -65,8 +65,8 @@ Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is setting the value of &v4l2-selection; target field -to V4L2_SEL_TGT_CROP_ACTIVE ( -V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table V4L2_SEL_TGT_CROP ( +V4L2_SEL_TGT_COMPOSE ). Please refer to table or for additional targets. The flags and reserved fields of &v4l2-selection; are ignored and they must be filled @@ -86,8 +86,8 @@ use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is setting the value of &v4l2-selection; target to -V4L2_SEL_TGT_CROP_ACTIVE ( -V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table V4L2_SEL_TGT_CROP ( +V4L2_SEL_TGT_COMPOSE ). Please refer to table or for additional targets. The &v4l2-rect; r rectangle need to be set to the desired active area. Field &v4l2-selection; reserved @@ -161,7 +161,7 @@ exist no rectangle that satisfies the constraints. &cs-def;
- V4L2_SEL_TGT_CROP_ACTIVE + V4L2_SEL_TGT_CROP 0x0000 The area that is currently cropped by hardware. @@ -176,7 +176,7 @@ exist no rectangle that satisfies the constraints.Limits for the cropping rectangle. - V4L2_SEL_TGT_COMPOSE_ACTIVE + V4L2_SEL_TGT_COMPOSE 0x0100 The area to which data is composed by hardware. @@ -193,7 +193,8 @@ exist no rectangle that satisfies the constraints. V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 - The active area and all padding pixels that are inserted or modified by hardware. + The active area and all padding pixels that are inserted or + modified by hardware. diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 62ce5399c4cf..a3cd78d33913 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -655,7 +655,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx, r->left = r->top = 0; return; } - if (target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { + if (target == V4L2_SEL_TGT_COMPOSE) { if (ctx->rotation != 90 && ctx->rotation != 270) align_h = 1; max_sc_h = min(SCALER_MAX_HRATIO, 1 << (ffs(sink->width) - 3)); @@ -682,7 +682,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx, rotate ? sink->f_height : sink->f_width); max_h = min_t(u32, FIMC_CAMIF_MAX_HEIGHT, sink->f_height); - if (target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { + if (target == V4L2_SEL_TGT_COMPOSE) { min_w = min_t(u32, max_w, sink->f_width / max_sc_h); min_h = min_t(u32, max_h, sink->f_height / max_sc_v); if (rotate) { @@ -1147,9 +1147,9 @@ static int fimc_cap_g_selection(struct file *file, void *fh, s->r.height = f->o_height; return 0; - case V4L2_SEL_TGT_COMPOSE_ACTIVE: + case V4L2_SEL_TGT_COMPOSE: f = &ctx->d_frame; - case V4L2_SEL_TGT_CROP_ACTIVE: + case V4L2_SEL_TGT_CROP: s->r.left = f->offs_h; s->r.top = f->offs_v; s->r.width = f->width; @@ -1185,9 +1185,9 @@ static int fimc_cap_s_selection(struct file *file, void *fh, if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; - if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) + if (s->target == V4L2_SEL_TGT_COMPOSE) f = &ctx->d_frame; - else if (s->target == V4L2_SEL_TGT_CROP_ACTIVE) + else if (s->target == V4L2_SEL_TGT_CROP) f = &ctx->s_frame; else return -EINVAL; @@ -1483,7 +1483,7 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, return -EINVAL; mutex_lock(&fimc->lock); - fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP_ACTIVE); + fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP); switch (sel->target) { case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/video/s5p-fimc/fimc-lite.c index 400d701aef04..52ede56e0758 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite.c +++ b/drivers/media/video/s5p-fimc/fimc-lite.c @@ -871,7 +871,7 @@ static int fimc_lite_g_selection(struct file *file, void *fh, sel->r.height = f->f_height; return 0; - case V4L2_SEL_TGT_COMPOSE_ACTIVE: + case V4L2_SEL_TGT_COMPOSE: sel->r = f->rect; return 0; } @@ -888,7 +888,7 @@ static int fimc_lite_s_selection(struct file *file, void *fh, unsigned long flags; if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || - sel->target != V4L2_SEL_TGT_COMPOSE_ACTIVE) + sel->target != V4L2_SEL_TGT_COMPOSE) return -EINVAL; fimc_lite_try_compose(fimc, &rect); diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c index e40e79b33df6..95f23024b17d 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.c +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c @@ -824,10 +824,10 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, /* For JPEG blob active == default == bounds */ switch (s->target) { - case V4L2_SEL_TGT_CROP_ACTIVE: + case V4L2_SEL_TGT_CROP: case V4L2_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_ACTIVE: + case V4L2_SEL_TGT_COMPOSE: case V4L2_SEL_TGT_COMPOSE_DEFAULT: s->r.width = ctx->out_q.w; s->r.height = ctx->out_q.h; diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index 33fde2a763ec..6c74b05d1f95 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c @@ -367,7 +367,7 @@ static int mxr_g_selection(struct file *file, void *fh, return -EINVAL; switch (s->target) { - case V4L2_SEL_TGT_CROP_ACTIVE: + case V4L2_SEL_TGT_CROP: s->r.left = geo->src.x_offset; s->r.top = geo->src.y_offset; s->r.width = geo->src.width; @@ -380,7 +380,7 @@ static int mxr_g_selection(struct file *file, void *fh, s->r.width = geo->src.full_width; s->r.height = geo->src.full_height; break; - case V4L2_SEL_TGT_COMPOSE_ACTIVE: + case V4L2_SEL_TGT_COMPOSE: case V4L2_SEL_TGT_COMPOSE_PADDED: s->r.left = geo->dst.x_offset; s->r.top = geo->dst.y_offset; @@ -449,11 +449,11 @@ static int mxr_s_selection(struct file *file, void *fh, res.height = geo->dst.full_height; break; - case V4L2_SEL_TGT_CROP_ACTIVE: + case V4L2_SEL_TGT_CROP: target = &geo->src; stage = MXR_GEOMETRY_CROP; break; - case V4L2_SEL_TGT_COMPOSE_ACTIVE: + case V4L2_SEL_TGT_COMPOSE: case V4L2_SEL_TGT_COMPOSE_PADDED: target = &geo->dst; stage = MXR_GEOMETRY_COMPOSE; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a61edb353273..ac1ad33ba3e0 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -767,13 +767,13 @@ struct v4l2_crop { /* Selection targets */ /* Current cropping area */ -#define V4L2_SEL_TGT_CROP_ACTIVE 0x0000 +#define V4L2_SEL_TGT_CROP 0x0000 /* Default cropping area */ #define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 /* Cropping bounds */ #define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 /* Current composing area */ -#define V4L2_SEL_TGT_COMPOSE_ACTIVE 0x0100 +#define V4L2_SEL_TGT_COMPOSE 0x0100 /* Default composing area */ #define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 /* Composing bounds */ @@ -781,6 +781,10 @@ struct v4l2_crop { /* Current composing area plus all padding pixels */ #define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 +/* Backward compatibility definitions */ +#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP +#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE + /** * struct v4l2_selection - selection info * @type: buffer type (do not use *_MPLANE types) -- GitLab From 68cacda10dc0fd1e57153055473c4030873bcea1 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Fri, 29 Jun 2012 01:19:22 -0300 Subject: [PATCH 2119/5711] staging: sep: sep_crypto.c: Remove useless function crypto_sep_dump_message The function crypto_sep_dump_message don't have any use in this driver. So remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_crypto.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index 045493b61995..41380567a9fa 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -84,28 +84,6 @@ static struct crypto_queue sep_queue; static void sep_dequeuer(void *data); /* TESTING */ -/** - * crypto_sep_dump_message - dump the message that is pending - * @sep: SEP device - * This will only print dump if DEBUG is set; it does - * follow kernel debug print enabling - */ -static void crypto_sep_dump_message(struct sep_device *sep, void *msg) -{ -#if 0 - u32 *p; - u32 *i; - int count; - - p = sep->shared_addr; - i = (u32 *)msg; - for (count = 0; count < 10 * 4; count += 4) - dev_dbg(&sep->pdev->dev, - "[PID%d] Word %d of the message is %x (local)%x\n", - current->pid, count/4, *p++, *i++); -#endif -} - /** * sep_do_callback * @work: pointer to work_struct @@ -1646,7 +1624,6 @@ static u32 crypto_post_op(struct sep_device *sep) dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op\n"); dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op message dump\n"); - crypto_sep_dump_message(ta_ctx->sep_used, ta_ctx->msg); /* first bring msg from shared area to local area */ memcpy(ta_ctx->msg, sep->shared_addr, -- GitLab From 0e7e10fe49213ba4e9dc8a74615b81dd8a57ba2a Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Fri, 29 Jun 2012 01:19:23 -0300 Subject: [PATCH 2120/5711] staging: sep: sep_crypto.c: Remove useless functions sep_dump and sep_dump_sg These two functions only has commented code, so remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_crypto.c | 77 -------------------------------- 1 file changed, 77 deletions(-) diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index 41380567a9fa..3c0611607984 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -465,55 +465,6 @@ static int partial_overlap(void *src_ptr, void *dst_ptr, u32 nbytes) return 0; } -/* Debug - prints only if DEBUG is defined; follows kernel debug model */ -static void sep_dump(struct sep_device *sep, char *stg, void *start, int len) -{ -#if 0 - int ct1; - u8 *ptt; - - dev_dbg(&sep->pdev->dev, - "Dump of %s starting at %08lx for %08x bytes\n", - stg, (unsigned long)start, len); - for (ct1 = 0; ct1 < len; ct1 += 1) { - ptt = (u8 *)(start + ct1); - dev_dbg(&sep->pdev->dev, "%02x ", *ptt); - if (ct1 % 16 == 15) - dev_dbg(&sep->pdev->dev, "\n"); - } - dev_dbg(&sep->pdev->dev, "\n"); -#endif -} - -/* Debug - prints only if DEBUG is defined; follows kernel debug model */ -static void sep_dump_sg(struct sep_device *sep, char *stg, - struct scatterlist *sg) -{ -#if 0 - int ct1, ct2; - u8 *ptt; - - dev_dbg(&sep->pdev->dev, "Dump of scatterlist %s\n", stg); - - ct1 = 0; - while (sg) { - dev_dbg(&sep->pdev->dev, "page %x\n size %x", ct1, - sg->length); - dev_dbg(&sep->pdev->dev, "phys addr is %lx", - (unsigned long)sg_phys(sg)); - ptt = sg_virt(sg); - for (ct2 = 0; ct2 < sg->length; ct2 += 1) { - dev_dbg(&sep->pdev->dev, "byte %x is %02x\n", - ct2, (unsigned char)*(ptt + ct2)); - } - - ct1 += 1; - sg = sg_next(sg); - } - dev_dbg(&sep->pdev->dev, "\n"); -#endif -} - /* Debug - prints only if DEBUG is defined */ static void sep_dump_ivs(struct ablkcipher_request *req, char *reason) @@ -1216,9 +1167,6 @@ static int sep_crypto_block_data(struct ablkcipher_request *req) /* Key already done; this is for data */ dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending data\n"); - sep_dump_sg(ta_ctx->sep_used, - "block sg in", ta_ctx->src_sg); - /* check for valid data and proper spacing */ src_ptr = sg_virt(ta_ctx->src_sg); dst_ptr = sg_virt(ta_ctx->dst_sg); @@ -1340,14 +1288,10 @@ static int sep_crypto_block_data(struct ablkcipher_request *req) sep_write_context(ta_ctx, &msg_offset, &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); - sep_dump(ta_ctx->sep_used, "ctx to block des", - &sctx->des_private_ctx, 40); } else { sep_write_context(ta_ctx, &msg_offset, &sctx->aes_private_ctx, sizeof(struct sep_aes_private_context)); - sep_dump(ta_ctx->sep_used, "ctx to block aes", - &sctx->aes_private_ctx, 20); } /* conclude message */ @@ -1404,8 +1348,6 @@ static int sep_crypto_send_key(struct ablkcipher_request *req) } memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - sep_dump(ta_ctx->sep_used, "iv", - ta_ctx->iv, SEP_DES_IV_SIZE_BYTES); } if ((ta_ctx->current_request == AES_CBC) && @@ -1416,8 +1358,6 @@ static int sep_crypto_send_key(struct ablkcipher_request *req) } memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - sep_dump(ta_ctx->sep_used, "iv", - ta_ctx->iv, SEP_AES_IV_SIZE_BYTES); } /* put together message to SEP */ @@ -1430,8 +1370,6 @@ static int sep_crypto_send_key(struct ablkcipher_request *req) sep_write_msg(ta_ctx, ta_ctx->iv, SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, &msg_offset, 1); - sep_dump(ta_ctx->sep_used, "initial IV", - ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); } else { /* Skip if ECB */ msg_offset += 4 * sizeof(u32); @@ -1443,8 +1381,6 @@ static int sep_crypto_send_key(struct ablkcipher_request *req) sep_write_msg(ta_ctx, ta_ctx->iv, SEP_AES_IV_SIZE_BYTES, max_length, &msg_offset, 1); - sep_dump(ta_ctx->sep_used, "initial IV", - ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); } else { /* Skip if ECB */ msg_offset += max_length; @@ -1647,16 +1583,10 @@ static u32 crypto_post_op(struct sep_device *sep) sep_read_context(ta_ctx, &msg_offset, &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); - - sep_dump(ta_ctx->sep_used, "ctx init des", - &sctx->des_private_ctx, 40); } else { sep_read_context(ta_ctx, &msg_offset, &sctx->aes_private_ctx, sizeof(struct sep_aes_private_context)); - - sep_dump(ta_ctx->sep_used, "ctx init aes", - &sctx->aes_private_ctx, 20); } sep_dump_ivs(req, "after sending key to sep\n"); @@ -1735,9 +1665,6 @@ static u32 crypto_post_op(struct sep_device *sep) sizeof(struct sep_aes_private_context)); } - sep_dump_sg(ta_ctx->sep_used, - "block sg out", ta_ctx->dst_sg); - /* Copy to correct sg if this block had oddball pages */ if (ta_ctx->dst_sg_hold) sep_copy_sg(ta_ctx->sep_used, @@ -2251,8 +2178,6 @@ static void sep_hash_update(void *data) src_ptr = NULL; } - sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - ta_ctx->dcb_input_data.app_in_address = src_ptr; ta_ctx->dcb_input_data.data_in_size = req->nbytes - (head_len + tail_len); @@ -2484,8 +2409,6 @@ static void sep_hash_digest(void *data) src_ptr = NULL; } - sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - ta_ctx->dcb_input_data.app_in_address = src_ptr; ta_ctx->dcb_input_data.data_in_size = req->nbytes - tail_len; ta_ctx->dcb_input_data.app_out_address = NULL; -- GitLab From 1ec0ed083988ae433305d7f4158fda8c3a1a23b9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 17 May 2012 17:50:45 -0300 Subject: [PATCH 2121/5711] [media] v4l: Remove "_ACTUAL" from subdev selection API target definition names The string "_ACTUAL" does not say anything more about the target names. Drop it. V4L2 selection API was changed by "V4L: Remove "_ACTIVE" from the selection target name definitions" by Sylwester Nawrocki. This patch does the same for the V4L2 subdev API. Signed-off-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/dev-subdev.xml | 28 +++++++++---------- .../media/v4l/vidioc-subdev-g-selection.xml | 12 ++++---- drivers/media/video/omap3isp/ispccdc.c | 4 +-- drivers/media/video/omap3isp/isppreview.c | 4 +-- drivers/media/video/omap3isp/ispresizer.c | 4 +-- drivers/media/video/smiapp/smiapp-core.c | 22 +++++++-------- drivers/media/video/v4l2-subdev.c | 4 +-- include/linux/v4l2-subdev.h | 9 ++++-- 8 files changed, 46 insertions(+), 41 deletions(-) diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index 4afcbbec5eda..e88d5ea8f826 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -289,9 +289,9 @@ &v4l2-rect; by the coordinates of the top left corner and the rectangle size. Both the coordinates and sizes are expressed in pixels. - As for pad formats, drivers store try and active - rectangles for the selection targets of ACTUAL type . + As for pad formats, drivers store try and active rectangles for + the selection targets . On sink pads, cropping is applied relative to the current pad format. The pad format represents the image size as @@ -308,7 +308,7 @@ Scaling support is optional. When supported by a subdev, the crop rectangle on the subdev's sink pad is scaled to the size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL - using V4L2_SUBDEV_SEL_COMPOSE_ACTUAL + using V4L2_SUBDEV_SEL_TGT_COMPOSE selection target on the same pad. If the subdev supports scaling but not composing, the top and left values are not used and must always be set to zero. @@ -333,22 +333,22 @@ Types of selection targets
- ACTUAL targets + Actual targets - ACTUAL targets reflect the actual hardware configuration - at any point of time. There is a BOUNDS target - corresponding to every ACTUAL. + Actual targets (without a postfix) reflect the actual + hardware configuration at any point of time. There is a BOUNDS + target corresponding to every actual target.
BOUNDS targets - BOUNDS targets is the smallest rectangle that contains - all valid ACTUAL rectangles. It may not be possible to set the - ACTUAL rectangle as large as the BOUNDS rectangle, however. - This may be because e.g. a sensor's pixel array is not - rectangular but cross-shaped or round. The maximum size may - also be smaller than the BOUNDS rectangle. + BOUNDS targets is the smallest rectangle that contains all + valid actual rectangles. It may not be possible to set the actual + rectangle as large as the BOUNDS rectangle, however. This may be + because e.g. a sensor's pixel array is not rectangular but + cross-shaped or round. The maximum size may also be smaller than the + BOUNDS rectangle.
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml index 208e9f0da3f3..4c44808ab25c 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -72,10 +72,10 @@
Types of selection targets - There are two types of selection targets: actual and bounds. - The ACTUAL targets are the targets which configure the hardware. - The BOUNDS target will return a rectangle that contain all - possible ACTUAL rectangles. + There are two types of selection targets: actual and bounds. The + actual targets are the targets which configure the hardware. The BOUNDS + target will return a rectangle that contain all possible actual + rectangles.
@@ -93,7 +93,7 @@ &cs-def;
- V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL + V4L2_SUBDEV_SEL_TGT_CROP 0x0000 Actual crop. Defines the cropping performed by the processing step. @@ -104,7 +104,7 @@ Bounds of the crop rectangle. - V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL + V4L2_SUBDEV_SEL_TGT_COMPOSE 0x0100 Actual compose rectangle. Used to configure scaling on sink pads and composition on source pads. diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index 7e32331b60fb..f19774f8396a 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -2024,7 +2024,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, ccdc_try_crop(ccdc, format, &sel->r); break; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: sel->r = *__ccdc_get_crop(ccdc, fh, sel->which); break; @@ -2052,7 +2052,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || + if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || sel->pad != CCDC_PAD_SOURCE_OF) return -EINVAL; diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index 8a4935ecc655..1086f6a9ff76 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c @@ -1960,7 +1960,7 @@ static int preview_get_selection(struct v4l2_subdev *sd, preview_try_crop(prev, format, &sel->r); break; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: sel->r = *__preview_get_crop(prev, fh, sel->which); break; @@ -1988,7 +1988,7 @@ static int preview_set_selection(struct v4l2_subdev *sd, struct isp_prev_device *prev = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || + if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || sel->pad != PREV_PAD_SINK) return -EINVAL; diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c index 14041c9c8643..945665295571 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/video/omap3isp/ispresizer.c @@ -1259,7 +1259,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd, resizer_calc_ratios(res, &sel->r, format_source, &ratio); break; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: sel->r = *__resizer_get_crop(res, fh, sel->which); resizer_calc_ratios(res, &sel->r, format_source, &ratio); break; @@ -1293,7 +1293,7 @@ static int resizer_set_selection(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format_sink, *format_source; struct resizer_ratio ratio; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || + if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || sel->pad != RESZ_PAD_SINK) return -EINVAL; diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/video/smiapp/smiapp-core.c index e8c93c89265a..37622bb6c667 100644 --- a/drivers/media/video/smiapp/smiapp-core.c +++ b/drivers/media/video/smiapp/smiapp-core.c @@ -1630,7 +1630,7 @@ static void smiapp_propagate(struct v4l2_subdev *subdev, smiapp_get_crop_compose(subdev, fh, crops, &comp, which); switch (target) { - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: comp->width = crops[SMIAPP_PAD_SINK]->width; comp->height = crops[SMIAPP_PAD_SINK]->height; if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { @@ -1646,7 +1646,7 @@ static void smiapp_propagate(struct v4l2_subdev *subdev, } } /* Fall through */ - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_COMPOSE: *crops[SMIAPP_PAD_SRC] = *comp; break; default: @@ -1722,7 +1722,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev, if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) ssd->sink_fmt = *crops[ssd->sink_pad]; smiapp_propagate(subdev, fh, fmt->which, - V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL); + V4L2_SUBDEV_SEL_TGT_CROP); mutex_unlock(&sensor->mutex); @@ -1957,7 +1957,7 @@ static int smiapp_set_compose(struct v4l2_subdev *subdev, *comp = sel->r; smiapp_propagate(subdev, fh, sel->which, - V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL); + V4L2_SUBDEV_SEL_TGT_COMPOSE); if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) return smiapp_update_mode(sensor); @@ -1973,7 +1973,7 @@ static int __smiapp_sel_supported(struct v4l2_subdev *subdev, /* We only implement crop in three places. */ switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: if (ssd == sensor->pixel_array && sel->pad == SMIAPP_PA_PAD_SRC) @@ -1987,7 +1987,7 @@ static int __smiapp_sel_supported(struct v4l2_subdev *subdev, == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) return 0; return -EINVAL; - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_COMPOSE: case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: if (sel->pad == ssd->source_pad) return -EINVAL; @@ -2050,7 +2050,7 @@ static int smiapp_set_crop(struct v4l2_subdev *subdev, if (ssd != sensor->pixel_array && sel->pad == SMIAPP_PAD_SINK) smiapp_propagate(subdev, fh, sel->which, - V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL); + V4L2_SUBDEV_SEL_TGT_CROP); return 0; } @@ -2096,11 +2096,11 @@ static int __smiapp_get_selection(struct v4l2_subdev *subdev, sel->r = *comp; } break; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: sel->r = *crops[sel->pad]; break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_COMPOSE: sel->r = *comp; break; } @@ -2147,10 +2147,10 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev, sel->r.height); switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_CROP: ret = smiapp_set_crop(subdev, fh, sel); break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SUBDEV_SEL_TGT_COMPOSE: ret = smiapp_set_compose(subdev, fh, sel); break; default: diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index db6e859b93d4..cd86f0c3ec74 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -245,7 +245,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; - sel.target = V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL; + sel.target = V4L2_SUBDEV_SEL_TGT_CROP; rval = v4l2_subdev_call( sd, pad, get_selection, subdev_fh, &sel); @@ -274,7 +274,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; - sel.target = V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL; + sel.target = V4L2_SUBDEV_SEL_TGT_CROP; sel.r = crop->rect; rval = v4l2_subdev_call( diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 812019ee1e06..3cbe6889fcb5 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -128,14 +128,19 @@ struct v4l2_subdev_frame_interval_enum { #define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG (1 << 2) /* active cropping area */ -#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL 0x0000 +#define V4L2_SUBDEV_SEL_TGT_CROP 0x0000 /* cropping bounds */ #define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS 0x0002 /* current composing area */ -#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL 0x0100 +#define V4L2_SUBDEV_SEL_TGT_COMPOSE 0x0100 /* composing bounds */ #define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS 0x0102 +/* backward compatibility definitions */ +#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL \ + V4L2_SUBDEV_SEL_TGT_CROP +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL \ + V4L2_SUBDEV_SEL_TGT_COMPOSE /** * struct v4l2_subdev_selection - selection info -- GitLab From 5689b28890f4a7c4e12290dbf2c29a9d23047335 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 18 May 2012 09:31:18 -0300 Subject: [PATCH 2122/5711] [media] v4l: Unify selection targets across V4L2 and V4L2 subdev interfaces Change the users of V4L2_SUBDEV_SEL_TGT_* targets to use V4L2_SEL_TGT_* instead. The common definitions are moved to a new header file, include/linux/v4l2-common.h. Signed-off-by: Sakari Ailus Signed-off-by: Sylwester Nawrocki Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/ispccdc.c | 6 +-- drivers/media/video/omap3isp/isppreview.c | 6 +-- drivers/media/video/omap3isp/ispresizer.c | 6 +-- drivers/media/video/s5p-fimc/fimc-capture.c | 18 +++---- drivers/media/video/s5p-fimc/fimc-lite.c | 11 ++-- drivers/media/video/smiapp/smiapp-core.c | 30 +++++------ drivers/media/video/v4l2-subdev.c | 4 +- include/linux/v4l2-common.h | 57 +++++++++++++++++++++ include/linux/v4l2-subdev.h | 19 ++----- include/linux/videodev2.h | 25 ++------- 10 files changed, 103 insertions(+), 79 deletions(-) create mode 100644 include/linux/v4l2-common.h diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index f19774f8396a..82df7a06dc36 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -2014,7 +2014,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return -EINVAL; switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: sel->r.left = 0; sel->r.top = 0; sel->r.width = INT_MAX; @@ -2024,7 +2024,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, ccdc_try_crop(ccdc, format, &sel->r); break; - case V4L2_SUBDEV_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP: sel->r = *__ccdc_get_crop(ccdc, fh, sel->which); break; @@ -2052,7 +2052,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || + if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != CCDC_PAD_SOURCE_OF) return -EINVAL; diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index 1086f6a9ff76..6fa70f4e8ea4 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c @@ -1949,7 +1949,7 @@ static int preview_get_selection(struct v4l2_subdev *sd, return -EINVAL; switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: sel->r.left = 0; sel->r.top = 0; sel->r.width = INT_MAX; @@ -1960,7 +1960,7 @@ static int preview_get_selection(struct v4l2_subdev *sd, preview_try_crop(prev, format, &sel->r); break; - case V4L2_SUBDEV_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP: sel->r = *__preview_get_crop(prev, fh, sel->which); break; @@ -1988,7 +1988,7 @@ static int preview_set_selection(struct v4l2_subdev *sd, struct isp_prev_device *prev = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || + if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != PREV_PAD_SINK) return -EINVAL; diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c index 945665295571..ae17d917f77b 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/video/omap3isp/ispresizer.c @@ -1249,7 +1249,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd, sel->which); switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: sel->r.left = 0; sel->r.top = 0; sel->r.width = INT_MAX; @@ -1259,7 +1259,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd, resizer_calc_ratios(res, &sel->r, format_source, &ratio); break; - case V4L2_SUBDEV_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP: sel->r = *__resizer_get_crop(res, fh, sel->which); resizer_calc_ratios(res, &sel->r, format_source, &ratio); break; @@ -1293,7 +1293,7 @@ static int resizer_set_selection(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format_sink, *format_source; struct resizer_ratio ratio; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP || + if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != RESZ_PAD_SINK) return -EINVAL; diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index a3cd78d33913..521e3715b9ee 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -1429,9 +1429,9 @@ static int fimc_subdev_get_selection(struct v4l2_subdev *sd, mutex_lock(&fimc->lock); switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: f = &ctx->d_frame; - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: r->width = f->o_width; r->height = f->o_height; r->left = 0; @@ -1439,10 +1439,10 @@ static int fimc_subdev_get_selection(struct v4l2_subdev *sd, mutex_unlock(&fimc->lock); return 0; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SEL_TGT_CROP: try_sel = v4l2_subdev_get_try_crop(fh, sel->pad); break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SEL_TGT_COMPOSE: try_sel = v4l2_subdev_get_try_compose(fh, sel->pad); f = &ctx->d_frame; break; @@ -1486,9 +1486,9 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP); switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: f = &ctx->d_frame; - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: r->width = f->o_width; r->height = f->o_height; r->left = 0; @@ -1496,10 +1496,10 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, mutex_unlock(&fimc->lock); return 0; - case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: + case V4L2_SEL_TGT_CROP: try_sel = v4l2_subdev_get_try_crop(fh, sel->pad); break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL: + case V4L2_SEL_TGT_COMPOSE: try_sel = v4l2_subdev_get_try_compose(fh, sel->pad); f = &ctx->d_frame; break; @@ -1515,7 +1515,7 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd, set_frame_crop(f, r->left, r->top, r->width, r->height); set_bit(ST_CAPT_APPLY_CFG, &fimc->state); spin_unlock_irqrestore(&fimc->slock, flags); - if (sel->target == V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL) + if (sel->target == V4L2_SEL_TGT_COMPOSE) ctx->state |= FIMC_COMPOSE; } diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/video/s5p-fimc/fimc-lite.c index 52ede56e0758..8785089c4460 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite.c +++ b/drivers/media/video/s5p-fimc/fimc-lite.c @@ -1086,9 +1086,9 @@ static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd, struct fimc_lite *fimc = v4l2_get_subdevdata(sd); struct flite_frame *f = &fimc->inp_frame; - if ((sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL && - sel->target != V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS) || - sel->pad != FLITE_SD_PAD_SINK) + if ((sel->target != V4L2_SEL_TGT_CROP && + sel->target != V4L2_SEL_TGT_CROP_BOUNDS) || + sel->pad != FLITE_SD_PAD_SINK) return -EINVAL; if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { @@ -1097,7 +1097,7 @@ static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd, } mutex_lock(&fimc->lock); - if (sel->target == V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL) { + if (sel->target == V4L2_SEL_TGT_CROP) { sel->r = f->rect; } else { sel->r.left = 0; @@ -1122,8 +1122,7 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd, struct flite_frame *f = &fimc->inp_frame; int ret = 0; - if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || - sel->pad != FLITE_SD_PAD_SINK) + if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != FLITE_SD_PAD_SINK) return -EINVAL; mutex_lock(&fimc->lock); diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/video/smiapp/smiapp-core.c index 37622bb6c667..9bbb5d3f003b 100644 --- a/drivers/media/video/smiapp/smiapp-core.c +++ b/drivers/media/video/smiapp/smiapp-core.c @@ -1630,7 +1630,7 @@ static void smiapp_propagate(struct v4l2_subdev *subdev, smiapp_get_crop_compose(subdev, fh, crops, &comp, which); switch (target) { - case V4L2_SUBDEV_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP: comp->width = crops[SMIAPP_PAD_SINK]->width; comp->height = crops[SMIAPP_PAD_SINK]->height; if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { @@ -1646,7 +1646,7 @@ static void smiapp_propagate(struct v4l2_subdev *subdev, } } /* Fall through */ - case V4L2_SUBDEV_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE: *crops[SMIAPP_PAD_SRC] = *comp; break; default: @@ -1722,7 +1722,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev, if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) ssd->sink_fmt = *crops[ssd->sink_pad]; smiapp_propagate(subdev, fh, fmt->which, - V4L2_SUBDEV_SEL_TGT_CROP); + V4L2_SEL_TGT_CROP); mutex_unlock(&sensor->mutex); @@ -1957,7 +1957,7 @@ static int smiapp_set_compose(struct v4l2_subdev *subdev, *comp = sel->r; smiapp_propagate(subdev, fh, sel->which, - V4L2_SUBDEV_SEL_TGT_COMPOSE); + V4L2_SEL_TGT_COMPOSE); if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) return smiapp_update_mode(sensor); @@ -1973,8 +1973,8 @@ static int __smiapp_sel_supported(struct v4l2_subdev *subdev, /* We only implement crop in three places. */ switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP: - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP_BOUNDS: if (ssd == sensor->pixel_array && sel->pad == SMIAPP_PA_PAD_SRC) return 0; @@ -1987,8 +1987,8 @@ static int __smiapp_sel_supported(struct v4l2_subdev *subdev, == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) return 0; return -EINVAL; - case V4L2_SUBDEV_SEL_TGT_COMPOSE: - case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: if (sel->pad == ssd->source_pad) return -EINVAL; if (ssd == sensor->binner) @@ -2050,7 +2050,7 @@ static int smiapp_set_crop(struct v4l2_subdev *subdev, if (ssd != sensor->pixel_array && sel->pad == SMIAPP_PAD_SINK) smiapp_propagate(subdev, fh, sel->which, - V4L2_SUBDEV_SEL_TGT_CROP); + V4L2_SEL_TGT_CROP); return 0; } @@ -2084,7 +2084,7 @@ static int __smiapp_get_selection(struct v4l2_subdev *subdev, } switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: if (ssd == sensor->pixel_array) { sel->r.width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1; @@ -2096,11 +2096,11 @@ static int __smiapp_get_selection(struct v4l2_subdev *subdev, sel->r = *comp; } break; - case V4L2_SUBDEV_SEL_TGT_CROP: - case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: sel->r = *crops[sel->pad]; break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE: sel->r = *comp; break; } @@ -2147,10 +2147,10 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev, sel->r.height); switch (sel->target) { - case V4L2_SUBDEV_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP: ret = smiapp_set_crop(subdev, fh, sel); break; - case V4L2_SUBDEV_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE: ret = smiapp_set_compose(subdev, fh, sel); break; default: diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index cd86f0c3ec74..9182f81deb5b 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -245,7 +245,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; - sel.target = V4L2_SUBDEV_SEL_TGT_CROP; + sel.target = V4L2_SEL_TGT_CROP; rval = v4l2_subdev_call( sd, pad, get_selection, subdev_fh, &sel); @@ -274,7 +274,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; - sel.target = V4L2_SUBDEV_SEL_TGT_CROP; + sel.target = V4L2_SEL_TGT_CROP; sel.r = crop->rect; rval = v4l2_subdev_call( diff --git a/include/linux/v4l2-common.h b/include/linux/v4l2-common.h new file mode 100644 index 000000000000..e85bf15b5994 --- /dev/null +++ b/include/linux/v4l2-common.h @@ -0,0 +1,57 @@ +/* + * include/linux/v4l2-common.h + * + * Common V4L2 and V4L2 subdev definitions. + * + * Users are advised to #include this file either through videodev2.h + * (V4L2) or through v4l2-subdev.h (V4L2 subdev) rather than to refer + * to this file directly. + * + * Copyright (C) 2012 Nokia Corporation + * Contact: Sakari Ailus + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __V4L2_COMMON__ +#define __V4L2_COMMON__ + +/* Selection target definitions */ + +/* Current cropping area */ +#define V4L2_SEL_TGT_CROP 0x0000 +/* Default cropping area */ +#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 +/* Cropping bounds */ +#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 +/* Current composing area */ +#define V4L2_SEL_TGT_COMPOSE 0x0100 +/* Default composing area */ +#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 +/* Composing bounds */ +#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 +/* Current composing area plus all padding pixels */ +#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 + +/* Backward compatibility definitions */ +#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP +#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE +#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL \ + V4L2_SEL_TGT_CROP +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL \ + V4L2_SEL_TGT_COMPOSE + +#endif /* __V4L2_COMMON__ */ diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 3cbe6889fcb5..1d7d45739260 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -25,6 +25,7 @@ #include #include +#include #include /** @@ -127,27 +128,13 @@ struct v4l2_subdev_frame_interval_enum { #define V4L2_SUBDEV_SEL_FLAG_SIZE_LE (1 << 1) #define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG (1 << 2) -/* active cropping area */ -#define V4L2_SUBDEV_SEL_TGT_CROP 0x0000 -/* cropping bounds */ -#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS 0x0002 -/* current composing area */ -#define V4L2_SUBDEV_SEL_TGT_COMPOSE 0x0100 -/* composing bounds */ -#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS 0x0102 - -/* backward compatibility definitions */ -#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL \ - V4L2_SUBDEV_SEL_TGT_CROP -#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL \ - V4L2_SUBDEV_SEL_TGT_COMPOSE - /** * struct v4l2_subdev_selection - selection info * * @which: either V4L2_SUBDEV_FORMAT_ACTIVE or V4L2_SUBDEV_FORMAT_TRY * @pad: pad number, as reported by the media API - * @target: selection target, used to choose one of possible rectangles + * @target: Selection target, used to choose one of possible rectangles, + * defined in v4l2-common.h; V4L2_SEL_TGT_* . * @flags: constraint flags * @r: coordinates of the selection window * @reserved: for future use, set to zero for now diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ac1ad33ba3e0..7fdb8710c831 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -64,6 +64,7 @@ #include #include #include +#include /* * Common stuff for both V4L1 and V4L2 @@ -764,31 +765,11 @@ struct v4l2_crop { #define V4L2_SEL_FLAG_GE 0x00000001 #define V4L2_SEL_FLAG_LE 0x00000002 -/* Selection targets */ - -/* Current cropping area */ -#define V4L2_SEL_TGT_CROP 0x0000 -/* Default cropping area */ -#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 -/* Cropping bounds */ -#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 -/* Current composing area */ -#define V4L2_SEL_TGT_COMPOSE 0x0100 -/* Default composing area */ -#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 -/* Composing bounds */ -#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 -/* Current composing area plus all padding pixels */ -#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 - -/* Backward compatibility definitions */ -#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP -#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE - /** * struct v4l2_selection - selection info * @type: buffer type (do not use *_MPLANE types) - * @target: selection target, used to choose one of possible rectangles + * @target: Selection target, used to choose one of possible rectangles; + * defined in v4l2-common.h; V4L2_SEL_TGT_* . * @flags: constraints flags * @r: coordinates of selection window * @reserved: for future use, rounds structure size to 64 bytes, set to zero -- GitLab From 64b9ce83a446277d3ffdb5e25e9aeb66442da2a9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 1 Jun 2012 13:56:53 -0300 Subject: [PATCH 2123/5711] [media] v4l: Common documentation for selection targets Both V4L2 and V4L2 subdev interface have very similar selection APIs with differences foremost related to in-memory and media bus formats. However, the selection targets are the same for both. Most targets are and in the future will likely continue to be more the same than with any differences. Thus it makes sense to unify the documentation of the targets. Signed-off-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 9 +- .../DocBook/media/v4l/dev-subdev.xml | 12 +-- .../DocBook/media/v4l/selection-api.xml | 6 +- .../DocBook/media/v4l/selections-common.xml | 92 +++++++++++++++++++ Documentation/DocBook/media/v4l/v4l2.xml | 5 + .../DocBook/media/v4l/vidioc-g-selection.xml | 54 +---------- .../media/v4l/vidioc-subdev-g-selection.xml | 34 +------ 7 files changed, 119 insertions(+), 93 deletions(-) create mode 100644 Documentation/DocBook/media/v4l/selections-common.xml diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index a8b374930405..97b895151bb0 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2377,10 +2377,11 @@ that used it. It was originally scheduled for removal in 2.6.35. V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace. - Add selection API for extended control over cropping and -composing. Does not affect the compatibility of current drivers and -applications. See selection API for -details. + Add selection API for extended control over cropping + and composing. Does not affect the compatibility of current + drivers and applications. See selection API for + details. diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index e88d5ea8f826..afeb196adce5 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -276,7 +276,7 @@ -
+
Selections: cropping, scaling and composition Many sub-devices support cropping frames on their input or output @@ -289,9 +289,9 @@ &v4l2-rect; by the coordinates of the top left corner and the rectangle size. Both the coordinates and sizes are expressed in pixels. - As for pad formats, drivers store try and active rectangles for - the selection targets . + As for pad formats, drivers store try and active + rectangles for the selection targets . On sink pads, cropping is applied relative to the current pad format. The pad format represents the image size as @@ -308,7 +308,7 @@ Scaling support is optional. When supported by a subdev, the crop rectangle on the subdev's sink pad is scaled to the size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL - using V4L2_SUBDEV_SEL_TGT_COMPOSE + using V4L2_SEL_TGT_COMPOSE selection target on the same pad. If the subdev supports scaling but not composing, the top and left values are not used and must always be set to zero. @@ -362,7 +362,7 @@ performed by the user: the changes made will be propagated to any subsequent stages. If this behaviour is not desired, the user must set - V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG flag. This + V4L2_SEL_FLAG_KEEP_CONFIG flag. This flag causes no propagation of the changes are allowed in any circumstances. This may also cause the accessed rectangle to be adjusted by the driver, depending on the properties of the diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml index ac013e50e0bd..24dec10259d2 100644 --- a/Documentation/DocBook/media/v4l/selection-api.xml +++ b/Documentation/DocBook/media/v4l/selection-api.xml @@ -53,11 +53,11 @@ cropping and composing rectangles have the same size. -For complete list of the available selection targets see table -
+ See for more + information. +
Configuration diff --git a/Documentation/DocBook/media/v4l/selections-common.xml b/Documentation/DocBook/media/v4l/selections-common.xml new file mode 100644 index 000000000000..6728688d28df --- /dev/null +++ b/Documentation/DocBook/media/v4l/selections-common.xml @@ -0,0 +1,92 @@ +
+ + Selection targets + + While the V4L2 selection + API and V4L2 subdev + selection APIs are very similar, there's one fundamental + difference between the two. On sub-device API, the selection + rectangle refers to the media bus format, and is bound to a + sub-device's pad. On the V4L2 interface the selection rectangles + refer to the in-memory pixel format. + + The precise meaning of the selection targets may thus be + affected on which of the two interfaces they are used. + +
+ Selection target definitions + + + + + + + &cs-def; + + + Target name + id + Definition + Valid for V4L2 + Valid for V4L2 subdev + + + + + V4L2_SEL_TGT_CROP + 0x0000 + Crop rectangle. Defines the cropped area. + Yes + Yes + + + V4L2_SEL_TGT_CROP_DEFAULT + 0x0001 + Suggested cropping rectangle that covers the "whole picture". + Yes + No + + + V4L2_SEL_TGT_CROP_BOUNDS + 0x0002 + Bounds of the crop rectangle. All valid crop + rectangles fit inside the crop bounds rectangle. + + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE + 0x0100 + Compose rectangle. Used to configure scaling + and composition. + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE_DEFAULT + 0x0101 + Suggested composition rectangle that covers the "whole picture". + Yes + No + + + V4L2_SEL_TGT_COMPOSE_BOUNDS + 0x0102 + Bounds of the compose rectangle. All valid compose + rectangles fit inside the compose bounds rectangle. + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE_PADDED + 0x0103 + The active area and all padding pixels that are inserted or + modified by hardware. + Yes + No + + + +
+ diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index 008c2d73a484..36bafc48e03b 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -589,6 +589,11 @@ and discussions on the V4L mailing list. &sub-write; + + Common definitions for V4L2 and V4L2 subdev interfaces + &sub-selections-common; + + Video For Linux Two Header File &sub-videodev2-h; diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml index 6376e57ff576..c6f83257ecee 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml @@ -67,7 +67,7 @@ Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE setting the value of &v4l2-selection; target field to V4L2_SEL_TGT_CROP ( V4L2_SEL_TGT_COMPOSE ). Please refer to table or for additional +linkend="v4l2-selections-common" /> or for additional targets. The flags and reserved fields of &v4l2-selection; are ignored and they must be filled with zeros. The driver fills the rest of the structure or @@ -88,7 +88,7 @@ use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE setting the value of &v4l2-selection; target to V4L2_SEL_TGT_CROP ( V4L2_SEL_TGT_COMPOSE ). Please refer to table or for additional +linkend="v4l2-selections-common" /> or for additional targets. The &v4l2-rect; r rectangle need to be set to the desired active area. Field &v4l2-selection; reserved is ignored and must be filled with zeros. The driver may adjust @@ -154,52 +154,8 @@ exist no rectangle that satisfies the constraints. - - - Selection targets. - - &cs-def; - - - V4L2_SEL_TGT_CROP - 0x0000 - The area that is currently cropped by hardware. - - - V4L2_SEL_TGT_CROP_DEFAULT - 0x0001 - Suggested cropping rectangle that covers the "whole picture". - - - V4L2_SEL_TGT_CROP_BOUNDS - 0x0002 - Limits for the cropping rectangle. - - - V4L2_SEL_TGT_COMPOSE - 0x0100 - The area to which data is composed by hardware. - - - V4L2_SEL_TGT_COMPOSE_DEFAULT - 0x0101 - Suggested composing rectangle that covers the "whole picture". - - - V4L2_SEL_TGT_COMPOSE_BOUNDS - 0x0102 - Limits for the composing rectangle. - - - V4L2_SEL_TGT_COMPOSE_PADDED - 0x0103 - The active area and all padding pixels that are inserted or - modified by hardware. - - - -
-
+ Selection targets are documented in . @@ -253,7 +209,7 @@ exist no rectangle that satisfies the constraints. __u32 target - Used to select between cropping + Used to select between cropping and composing rectangles. diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml index 4c44808ab25c..ace147806e48 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -87,36 +87,8 @@ EINVAL. -
- V4L2 subdev selection targets - - &cs-def; - - - V4L2_SUBDEV_SEL_TGT_CROP - 0x0000 - Actual crop. Defines the cropping - performed by the processing step. - - - V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS - 0x0002 - Bounds of the crop rectangle. - - - V4L2_SUBDEV_SEL_TGT_COMPOSE - 0x0100 - Actual compose rectangle. Used to configure scaling - on sink pads and composition on source pads. - - - V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS - 0x0102 - Bounds of the compose rectangle. - - - -
+ Selection targets are documented in . V4L2 subdev selection flags @@ -173,7 +145,7 @@ __u32targetTarget selection rectangle. See - .. + . __u32 -- GitLab From a454ad15e015526ca84f15460bf8a56fccfffeea Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Fri, 29 Jun 2012 13:49:17 -0500 Subject: [PATCH 2124/5711] staging: tidspbridge: add pud code And fix the following warning for passing an incorrect variable type. ../tiomap3430.c: In function 'user_va2_pa': ../tiomap3430.c:1555: warning: passing argument 1 of 'pmd_offset' from incompatible pointer type arch/arm/include/asm/pgtable-2level.h:156: note: expected 'struct pud_t *' but argument is of type 'pmdval_t (*)[2]' While at it, eliminate 'if' nesting to increase readability. Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/core/tiomap3430.c | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index 9cf29fcea11e..f9609ce2c163 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -1547,20 +1547,27 @@ EXIT_LOOP: static u32 user_va2_pa(struct mm_struct *mm, u32 address) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *ptep, pte; pgd = pgd_offset(mm, address); - if (!(pgd_none(*pgd) || pgd_bad(*pgd))) { - pmd = pmd_offset(pgd, address); - if (!(pmd_none(*pmd) || pmd_bad(*pmd))) { - ptep = pte_offset_map(pmd, address); - if (ptep) { - pte = *ptep; - if (pte_present(pte)) - return pte & PAGE_MASK; - } - } + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + pud = pud_offset(pgd, address); + if (pud_none(*pud) || pud_bad(*pud)) + return 0; + + pmd = pmd_offset(pud, address); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return 0; + + ptep = pte_offset_map(pmd, address); + if (ptep) { + pte = *ptep; + if (pte_present(pte)) + return pte & PAGE_MASK; } return 0; -- GitLab From e8cfe4116de12c1e0b815af0da6187e7b4695eb1 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Fri, 29 Jun 2012 13:49:18 -0500 Subject: [PATCH 2125/5711] staging: tidspbridge: split bridge_io_on_loaded Due to its size, this function declares too many variables, to split it a new structure has been declared to hold values as they are read from the baseimage. While at it, indentation was reduced by renaming variables and reducing blocks of code with the following structure: if (success) { ... if (success) ... } This fixes the following warning: drivers/staging/tidspbridge/core/io_sm.c: In function 'bridge_io_on_loaded': drivers/staging/tidspbridge/core/io_sm.c:777: warning: the frame size of 1032 bytes is larger than 1024 bytes Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/core/io_sm.c | 704 +++++++++++------------ 1 file changed, 343 insertions(+), 361 deletions(-) diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index c51f651dfd1b..480a3845a24c 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -128,6 +128,16 @@ struct io_mgr { }; +struct shm_symbol_val { + u32 shm_base; + u32 shm_lim; + u32 msg_base; + u32 msg_lim; + u32 shm0_end; + u32 dyn_ext; + u32 ext_end; +}; + /* Function Prototypes */ static void io_dispatch_pm(struct io_mgr *pio_mgr); static void notify_chnl_complete(struct chnl_object *pchnl, @@ -256,6 +266,75 @@ int bridge_io_destroy(struct io_mgr *hio_mgr) return status; } +struct shm_symbol_val *_get_shm_symbol_values(struct io_mgr *hio_mgr) +{ + struct shm_symbol_val *s; + struct cod_manager *cod_man; + int status; + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return ERR_PTR(-ENOMEM); + + status = dev_get_cod_mgr(hio_mgr->dev_obj, &cod_man); + if (status) + goto free_symbol; + + /* Get start and length of channel part of shared memory */ + status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_BASE_SYM, + &s->shm_base); + if (status) + goto free_symbol; + + status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_LIMIT_SYM, + &s->shm_lim); + if (status) + goto free_symbol; + + if (s->shm_lim <= s->shm_base) { + status = -EINVAL; + goto free_symbol; + } + + /* Get start and length of message part of shared memory */ + status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_BASE_SYM, + &s->msg_base); + if (status) + goto free_symbol; + + status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_LIMIT_SYM, + &s->msg_lim); + if (status) + goto free_symbol; + + if (s->msg_lim <= s->msg_base) { + status = -EINVAL; + goto free_symbol; + } + +#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE + status = cod_get_sym_value(cod_man, DSP_TRACESEC_END, &s->shm0_end); +#else + status = cod_get_sym_value(cod_man, SHM0_SHARED_END_SYM, &s->shm0_end); +#endif + if (status) + goto free_symbol; + + status = cod_get_sym_value(cod_man, DYNEXTBASE, &s->dyn_ext); + if (status) + goto free_symbol; + + status = cod_get_sym_value(cod_man, EXTEND, &s->ext_end); + if (status) + goto free_symbol; + + return s; + +free_symbol: + kfree(s); + return ERR_PTR(status); +} + /* * ======== bridge_io_on_loaded ======== * Purpose: @@ -265,193 +344,112 @@ int bridge_io_destroy(struct io_mgr *hio_mgr) */ int bridge_io_on_loaded(struct io_mgr *hio_mgr) { + struct bridge_dev_context *dc = hio_mgr->bridge_context; + struct cfg_hostres *cfg_res = dc->resources; + struct bridge_ioctl_extproc *eproc; struct cod_manager *cod_man; struct chnl_mgr *hchnl_mgr; struct msg_mgr *hmsg_mgr; - u32 ul_shm_base; - u32 ul_shm_base_offset; - u32 ul_shm_limit; - u32 ul_shm_length = -1; - u32 ul_mem_length = -1; - u32 ul_msg_base; - u32 ul_msg_limit; - u32 ul_msg_length = -1; - u32 ul_ext_end; - u32 ul_gpp_pa = 0; - u32 ul_gpp_va = 0; - u32 ul_dsp_va = 0; - u32 ul_seg_size = 0; - u32 ul_pad_size = 0; + struct shm_symbol_val *s; + int status; + u8 num_procs; + s32 ndx; u32 i; - int status = 0; - u8 num_procs = 0; - s32 ndx = 0; - /* DSP MMU setup table */ - struct bridge_ioctl_extproc ae_proc[BRDIOCTL_NUMOFMMUTLB]; - struct cfg_hostres *host_res; - struct bridge_dev_context *pbridge_context; - u32 map_attrs; - u32 shm0_end; - u32 ul_dyn_ext_base; - u32 ul_seg1_size = 0; - u32 pa_curr = 0; - u32 va_curr = 0; - u32 gpp_va_curr = 0; - u32 num_bytes = 0; + u32 mem_sz, msg_sz, pad_sz, shm_sz, shm_base_offs; + u32 seg0_sz, seg1_sz; + u32 pa, va, da; + u32 pa_curr, va_curr, da_curr; + u32 bytes; u32 all_bits = 0; - u32 page_size[] = { HW_PAGE_SIZE16MB, HW_PAGE_SIZE1MB, + u32 page_size[] = { + HW_PAGE_SIZE16MB, HW_PAGE_SIZE1MB, HW_PAGE_SIZE64KB, HW_PAGE_SIZE4KB }; + u32 map_attrs = DSP_MAPLITTLEENDIAN | DSP_MAPPHYSICALADDR | + DSP_MAPELEMSIZE32 | DSP_MAPDONOTLOCK; - status = dev_get_bridge_context(hio_mgr->dev_obj, &pbridge_context); - if (!pbridge_context) { - status = -EFAULT; - goto func_end; - } - - host_res = pbridge_context->resources; - if (!host_res) { - status = -EFAULT; - goto func_end; - } status = dev_get_cod_mgr(hio_mgr->dev_obj, &cod_man); - if (!cod_man) { - status = -EFAULT; - goto func_end; - } + if (status) + return status; + hchnl_mgr = hio_mgr->chnl_mgr; - /* The message manager is destroyed when the board is stopped. */ + + /* The message manager is destroyed when the board is stopped */ dev_get_msg_mgr(hio_mgr->dev_obj, &hio_mgr->msg_mgr); hmsg_mgr = hio_mgr->msg_mgr; - if (!hchnl_mgr || !hmsg_mgr) { - status = -EFAULT; - goto func_end; - } + if (!hchnl_mgr || !hmsg_mgr) + return -EFAULT; + if (hio_mgr->shared_mem) hio_mgr->shared_mem = NULL; - /* Get start and length of channel part of shared memory */ - status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_BASE_SYM, - &ul_shm_base); - if (status) { - status = -EFAULT; - goto func_end; - } - status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_LIMIT_SYM, - &ul_shm_limit); - if (status) { - status = -EFAULT; - goto func_end; - } - if (ul_shm_limit <= ul_shm_base) { - status = -EINVAL; - goto func_end; - } + s = _get_shm_symbol_values(hio_mgr); + if (IS_ERR(s)) + return PTR_ERR(s); + /* Get total length in bytes */ - ul_shm_length = (ul_shm_limit - ul_shm_base + 1) * hio_mgr->word_size; + shm_sz = (s->shm_lim - s->shm_base + 1) * hio_mgr->word_size; + /* Calculate size of a PROCCOPY shared memory region */ dev_dbg(bridge, "%s: (proc)proccopy shmmem size: 0x%x bytes\n", - __func__, (ul_shm_length - sizeof(struct shm))); + __func__, shm_sz - sizeof(struct shm)); - /* Get start and length of message part of shared memory */ - status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_BASE_SYM, - &ul_msg_base); - if (!status) { - status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_LIMIT_SYM, - &ul_msg_limit); - if (!status) { - if (ul_msg_limit <= ul_msg_base) { - status = -EINVAL; - } else { - /* - * Length (bytes) of messaging part of shared - * memory. - */ - ul_msg_length = - (ul_msg_limit - ul_msg_base + - 1) * hio_mgr->word_size; - /* - * Total length (bytes) of shared memory: - * chnl + msg. - */ - ul_mem_length = ul_shm_length + ul_msg_length; - } - } else { - status = -EFAULT; - } - } else { - status = -EFAULT; - } - if (!status) { -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) - status = - cod_get_sym_value(cod_man, DSP_TRACESEC_END, &shm0_end); -#else - status = cod_get_sym_value(cod_man, SHM0_SHARED_END_SYM, - &shm0_end); -#endif - if (status) - status = -EFAULT; - } - if (!status) { - status = - cod_get_sym_value(cod_man, DYNEXTBASE, &ul_dyn_ext_base); - if (status) - status = -EFAULT; - } - if (!status) { - status = cod_get_sym_value(cod_man, EXTEND, &ul_ext_end); - if (status) - status = -EFAULT; + /* Length (bytes) of messaging part of shared memory */ + msg_sz = (s->msg_lim - s->msg_base + 1) * hio_mgr->word_size; + + /* Total length (bytes) of shared memory: chnl + msg */ + mem_sz = shm_sz + msg_sz; + + /* Get memory reserved in host resources */ + (void)mgr_enum_processor_info(0, + (struct dsp_processorinfo *) + &hio_mgr->ext_proc_info, + sizeof(struct mgr_processorextinfo), + &num_procs); + + /* IO supports only one DSP for now */ + if (num_procs != 1) { + status = -EINVAL; + goto free_symbol; } - if (!status) { - /* Get memory reserved in host resources */ - (void)mgr_enum_processor_info(0, (struct dsp_processorinfo *) - &hio_mgr->ext_proc_info, - sizeof(struct - mgr_processorextinfo), - &num_procs); - - /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */ - ndx = 0; - ul_gpp_pa = host_res->mem_phys[1]; - ul_gpp_va = host_res->mem_base[1]; - /* This is the virtual uncached ioremapped address!!! */ - /* Why can't we directly take the DSPVA from the symbols? */ - ul_dsp_va = hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt; - ul_seg_size = (shm0_end - ul_dsp_va) * hio_mgr->word_size; - ul_seg1_size = - (ul_ext_end - ul_dyn_ext_base) * hio_mgr->word_size; - /* 4K align */ - ul_seg1_size = (ul_seg1_size + 0xFFF) & (~0xFFFUL); - /* 64K align */ - ul_seg_size = (ul_seg_size + 0xFFFF) & (~0xFFFFUL); - ul_pad_size = UL_PAGE_ALIGN_SIZE - ((ul_gpp_pa + ul_seg1_size) % - UL_PAGE_ALIGN_SIZE); - if (ul_pad_size == UL_PAGE_ALIGN_SIZE) - ul_pad_size = 0x0; - - dev_dbg(bridge, "%s: ul_gpp_pa %x, ul_gpp_va %x, ul_dsp_va %x, " - "shm0_end %x, ul_dyn_ext_base %x, ul_ext_end %x, " - "ul_seg_size %x ul_seg1_size %x \n", __func__, - ul_gpp_pa, ul_gpp_va, ul_dsp_va, shm0_end, - ul_dyn_ext_base, ul_ext_end, ul_seg_size, ul_seg1_size); - - if ((ul_seg_size + ul_seg1_size + ul_pad_size) > - host_res->mem_length[1]) { - pr_err("%s: shm Error, reserved 0x%x required 0x%x\n", - __func__, host_res->mem_length[1], - ul_seg_size + ul_seg1_size + ul_pad_size); - status = -ENOMEM; - } + + /* The first MMU TLB entry(TLB_0) in DCD is ShmBase */ + pa = cfg_res->mem_phys[1]; + va = cfg_res->mem_base[1]; + + /* This is the virtual uncached ioremapped address!!! */ + /* Why can't we directly take the DSPVA from the symbols? */ + da = hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt; + seg0_sz = (s->shm0_end - da) * hio_mgr->word_size; + seg1_sz = (s->ext_end - s->dyn_ext) * hio_mgr->word_size; + + /* 4K align */ + seg1_sz = (seg1_sz + 0xFFF) & (~0xFFFUL); + + /* 64K align */ + seg0_sz = (seg0_sz + 0xFFFF) & (~0xFFFFUL); + + pad_sz = UL_PAGE_ALIGN_SIZE - ((pa + seg1_sz) % UL_PAGE_ALIGN_SIZE); + if (pad_sz == UL_PAGE_ALIGN_SIZE) + pad_sz = 0x0; + + dev_dbg(bridge, "%s: pa %x, va %x, da %x\n", __func__, pa, va, da); + dev_dbg(bridge, + "shm0_end %x, dyn_ext %x, ext_end %x, seg0_sz %x seg1_sz %x\n", + s->shm0_end, s->dyn_ext, s->ext_end, seg0_sz, seg1_sz); + + if ((seg0_sz + seg1_sz + pad_sz) > cfg_res->mem_length[1]) { + pr_err("%s: shm Error, reserved 0x%x required 0x%x\n", + __func__, cfg_res->mem_length[1], + seg0_sz + seg1_sz + pad_sz); + status = -ENOMEM; + goto free_symbol; } - if (status) - goto func_end; - pa_curr = ul_gpp_pa; - va_curr = ul_dyn_ext_base * hio_mgr->word_size; - gpp_va_curr = ul_gpp_va; - num_bytes = ul_seg1_size; + pa_curr = pa; + va_curr = s->dyn_ext * hio_mgr->word_size; + da_curr = va; + bytes = seg1_sz; /* * Try to fit into TLB entries. If not possible, push them to page @@ -459,37 +457,30 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) * bigger page boundary, we may end up making several small pages. * So, push them onto page tables, if that is the case. */ - map_attrs = 0x00000000; - map_attrs = DSP_MAPLITTLEENDIAN; - map_attrs |= DSP_MAPPHYSICALADDR; - map_attrs |= DSP_MAPELEMSIZE32; - map_attrs |= DSP_MAPDONOTLOCK; - - while (num_bytes) { + while (bytes) { /* * To find the max. page size with which both PA & VA are * aligned. */ all_bits = pa_curr | va_curr; - dev_dbg(bridge, "all_bits %x, pa_curr %x, va_curr %x, " - "num_bytes %x\n", all_bits, pa_curr, va_curr, - num_bytes); + dev_dbg(bridge, + "seg all_bits %x, pa_curr %x, va_curr %x, bytes %x\n", + all_bits, pa_curr, va_curr, bytes); + for (i = 0; i < 4; i++) { - if ((num_bytes >= page_size[i]) && ((all_bits & - (page_size[i] - - 1)) == 0)) { - status = - hio_mgr->intf_fxns-> - brd_mem_map(hio_mgr->bridge_context, - pa_curr, va_curr, - page_size[i], map_attrs, - NULL); + if ((bytes >= page_size[i]) && + ((all_bits & (page_size[i] - 1)) == 0)) { + status = hio_mgr->intf_fxns->brd_mem_map(dc, + pa_curr, va_curr, + page_size[i], map_attrs, + NULL); if (status) - goto func_end; + goto free_symbol; + pa_curr += page_size[i]; va_curr += page_size[i]; - gpp_va_curr += page_size[i]; - num_bytes -= page_size[i]; + da_curr += page_size[i]; + bytes -= page_size[i]; /* * Don't try smaller sizes. Hopefully we have * reached an address aligned to a bigger page @@ -499,71 +490,75 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) } } } - pa_curr += ul_pad_size; - va_curr += ul_pad_size; - gpp_va_curr += ul_pad_size; + pa_curr += pad_sz; + va_curr += pad_sz; + da_curr += pad_sz; + bytes = seg0_sz; + va_curr = da * hio_mgr->word_size; + + eproc = kzalloc(sizeof(*eproc) * BRDIOCTL_NUMOFMMUTLB, GFP_KERNEL); + if (!eproc) { + status = -ENOMEM; + goto free_symbol; + } + + ndx = 0; /* Configure the TLB entries for the next cacheable segment */ - num_bytes = ul_seg_size; - va_curr = ul_dsp_va * hio_mgr->word_size; - while (num_bytes) { + while (bytes) { /* * To find the max. page size with which both PA & VA are * aligned. */ all_bits = pa_curr | va_curr; - dev_dbg(bridge, "all_bits for Seg1 %x, pa_curr %x, " - "va_curr %x, num_bytes %x\n", all_bits, pa_curr, - va_curr, num_bytes); + dev_dbg(bridge, + "seg1 all_bits %x, pa_curr %x, va_curr %x, bytes %x\n", + all_bits, pa_curr, va_curr, bytes); + for (i = 0; i < 4; i++) { - if (!(num_bytes >= page_size[i]) || + if (!(bytes >= page_size[i]) || !((all_bits & (page_size[i] - 1)) == 0)) continue; - if (ndx < MAX_LOCK_TLB_ENTRIES) { - /* - * This is the physical address written to - * DSP MMU. - */ - ae_proc[ndx].gpp_pa = pa_curr; - /* - * This is the virtual uncached ioremapped - * address!!! - */ - ae_proc[ndx].gpp_va = gpp_va_curr; - ae_proc[ndx].dsp_va = - va_curr / hio_mgr->word_size; - ae_proc[ndx].size = page_size[i]; - ae_proc[ndx].endianism = HW_LITTLE_ENDIAN; - ae_proc[ndx].elem_size = HW_ELEM_SIZE16BIT; - ae_proc[ndx].mixed_mode = HW_MMU_CPUES; - dev_dbg(bridge, "shm MMU TLB entry PA %x" - " VA %x DSP_VA %x Size %x\n", - ae_proc[ndx].gpp_pa, - ae_proc[ndx].gpp_va, - ae_proc[ndx].dsp_va * - hio_mgr->word_size, page_size[i]); - ndx++; - } else { - status = - hio_mgr->intf_fxns-> - brd_mem_map(hio_mgr->bridge_context, - pa_curr, va_curr, - page_size[i], map_attrs, - NULL); + + if (ndx >= MAX_LOCK_TLB_ENTRIES) { + status = hio_mgr->intf_fxns->brd_mem_map(dc, + pa_curr, va_curr, + page_size[i], map_attrs, + NULL); dev_dbg(bridge, - "shm MMU PTE entry PA %x" - " VA %x DSP_VA %x Size %x\n", - ae_proc[ndx].gpp_pa, - ae_proc[ndx].gpp_va, - ae_proc[ndx].dsp_va * + "PTE pa %x va %x dsp_va %x sz %x\n", + eproc[ndx].gpp_pa, + eproc[ndx].gpp_va, + eproc[ndx].dsp_va * hio_mgr->word_size, page_size[i]); if (status) - goto func_end; + goto free_eproc; } + + /* This is the physical address written to DSP MMU */ + eproc[ndx].gpp_pa = pa_curr; + + /* + * This is the virtual uncached ioremapped + * address!!! + */ + eproc[ndx].gpp_va = da_curr; + eproc[ndx].dsp_va = va_curr / hio_mgr->word_size; + eproc[ndx].size = page_size[i]; + eproc[ndx].endianism = HW_LITTLE_ENDIAN; + eproc[ndx].elem_size = HW_ELEM_SIZE16BIT; + eproc[ndx].mixed_mode = HW_MMU_CPUES; + dev_dbg(bridge, "%s: tlb pa %x va %x dsp_va %x sz %x\n", + __func__, eproc[ndx].gpp_pa, + eproc[ndx].gpp_va, + eproc[ndx].dsp_va * hio_mgr->word_size, + page_size[i]); + ndx++; + pa_curr += page_size[i]; va_curr += page_size[i]; - gpp_va_curr += page_size[i]; - num_bytes -= page_size[i]; + da_curr += page_size[i]; + bytes -= page_size[i]; /* * Don't try smaller sizes. Hopefully we have reached * an address aligned to a bigger page size. @@ -577,146 +572,127 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) * should not conflict with shm entries on MPU or DSP side. */ for (i = 3; i < 7 && ndx < BRDIOCTL_NUMOFMMUTLB; i++) { - if (hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys == 0) + struct mgr_processorextinfo *ep = &hio_mgr->ext_proc_info; + u32 word_sz = hio_mgr->word_size; + + if (ep->ty_tlb[i].gpp_phys == 0) continue; - if ((hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys > - ul_gpp_pa - 0x100000 - && hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys <= - ul_gpp_pa + ul_seg_size) - || (hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt > - ul_dsp_va - 0x100000 / hio_mgr->word_size - && hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt <= - ul_dsp_va + ul_seg_size / hio_mgr->word_size)) { + if ((ep->ty_tlb[i].gpp_phys > pa - 0x100000 && + ep->ty_tlb[i].gpp_phys <= pa + seg0_sz) || + (ep->ty_tlb[i].dsp_virt > da - 0x100000 / word_sz && + ep->ty_tlb[i].dsp_virt <= da + seg0_sz / word_sz)) { dev_dbg(bridge, - "CDB MMU entry %d conflicts with " - "shm.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: " - "GppPa %x, DspVa %x, Bytes %x.\n", i, - hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys, - hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt, - ul_gpp_pa, ul_dsp_va, ul_seg_size); + "err cdb%d pa %x da %x shm pa %x da %x sz %x\n", + i, ep->ty_tlb[i].gpp_phys, + ep->ty_tlb[i].dsp_virt, pa, da, seg0_sz); status = -EPERM; - } else { - if (ndx < MAX_LOCK_TLB_ENTRIES) { - ae_proc[ndx].dsp_va = - hio_mgr->ext_proc_info.ty_tlb[i]. - dsp_virt; - ae_proc[ndx].gpp_pa = - hio_mgr->ext_proc_info.ty_tlb[i]. - gpp_phys; - ae_proc[ndx].gpp_va = 0; - /* 1 MB */ - ae_proc[ndx].size = 0x100000; - dev_dbg(bridge, "shm MMU entry PA %x " - "DSP_VA 0x%x\n", ae_proc[ndx].gpp_pa, - ae_proc[ndx].dsp_va); - ndx++; - } else { - status = hio_mgr->intf_fxns->brd_mem_map - (hio_mgr->bridge_context, - hio_mgr->ext_proc_info.ty_tlb[i]. - gpp_phys, - hio_mgr->ext_proc_info.ty_tlb[i]. - dsp_virt, 0x100000, map_attrs, - NULL); - } + goto free_eproc; + } + + if (ndx >= MAX_LOCK_TLB_ENTRIES) { + status = hio_mgr->intf_fxns->brd_mem_map(dc, + ep->ty_tlb[i].gpp_phys, + ep->ty_tlb[i].dsp_virt, + 0x100000, map_attrs, NULL); + if (status) + goto free_eproc; } - if (status) - goto func_end; - } - map_attrs = 0x00000000; - map_attrs = DSP_MAPLITTLEENDIAN; - map_attrs |= DSP_MAPPHYSICALADDR; - map_attrs |= DSP_MAPELEMSIZE32; - map_attrs |= DSP_MAPDONOTLOCK; + eproc[ndx].dsp_va = ep->ty_tlb[i].dsp_virt; + eproc[ndx].gpp_pa = ep->ty_tlb[i].gpp_phys; + eproc[ndx].gpp_va = 0; + + /* 1 MB */ + eproc[ndx].size = 0x100000; + dev_dbg(bridge, "shm MMU entry pa %x da 0x%x\n", + eproc[ndx].gpp_pa, eproc[ndx].dsp_va); + ndx++; + } /* Map the L4 peripherals */ i = 0; while (l4_peripheral_table[i].phys_addr) { - status = hio_mgr->intf_fxns->brd_mem_map - (hio_mgr->bridge_context, l4_peripheral_table[i].phys_addr, - l4_peripheral_table[i].dsp_virt_addr, HW_PAGE_SIZE4KB, - map_attrs, NULL); + status = hio_mgr->intf_fxns->brd_mem_map(dc, + l4_peripheral_table[i].phys_addr, + l4_peripheral_table[i].dsp_virt_addr, + HW_PAGE_SIZE4KB, map_attrs, NULL); if (status) - goto func_end; + goto free_eproc; i++; } for (i = ndx; i < BRDIOCTL_NUMOFMMUTLB; i++) { - ae_proc[i].dsp_va = 0; - ae_proc[i].gpp_pa = 0; - ae_proc[i].gpp_va = 0; - ae_proc[i].size = 0; + eproc[i].dsp_va = 0; + eproc[i].gpp_pa = 0; + eproc[i].gpp_va = 0; + eproc[i].size = 0; } + /* * Set the shm physical address entry (grayed out in CDB file) * to the virtual uncached ioremapped address of shm reserved * on MPU. */ hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys = - (ul_gpp_va + ul_seg1_size + ul_pad_size); + (va + seg1_sz + pad_sz); /* * Need shm Phys addr. IO supports only one DSP for now: * num_procs = 1. */ - if (!hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys || num_procs != 1) { - status = -EFAULT; - goto func_end; - } else { - if (ae_proc[0].dsp_va > ul_shm_base) { - status = -EPERM; - goto func_end; - } - /* ul_shm_base may not be at ul_dsp_va address */ - ul_shm_base_offset = (ul_shm_base - ae_proc[0].dsp_va) * + if (!hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys) + return -EFAULT; + + if (eproc[0].dsp_va > s->shm_base) + return -EPERM; + + /* shm_base may not be at ul_dsp_va address */ + shm_base_offs = (s->shm_base - eproc[0].dsp_va) * hio_mgr->word_size; - /* - * bridge_dev_ctrl() will set dev context dsp-mmu info. In - * bridge_brd_start() the MMU will be re-programed with MMU - * DSPVa-GPPPa pair info while DSP is in a known - * (reset) state. - */ + /* + * bridge_dev_ctrl() will set dev context dsp-mmu info. In + * bridge_brd_start() the MMU will be re-programed with MMU + * DSPVa-GPPPa pair info while DSP is in a known + * (reset) state. + */ + status = hio_mgr->intf_fxns->dev_cntrl(hio_mgr->bridge_context, + BRDIOCTL_SETMMUCONFIG, eproc); + if (status) + goto free_eproc; - status = - hio_mgr->intf_fxns->dev_cntrl(hio_mgr->bridge_context, - BRDIOCTL_SETMMUCONFIG, - ae_proc); - if (status) - goto func_end; - ul_shm_base = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys; - ul_shm_base += ul_shm_base_offset; - ul_shm_base = (u32) MEM_LINEAR_ADDRESS((void *)ul_shm_base, - ul_mem_length); - if (ul_shm_base == 0) { - status = -EFAULT; - goto func_end; - } - /* Register SM */ - status = - register_shm_segs(hio_mgr, cod_man, ae_proc[0].gpp_pa); + s->shm_base = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys; + s->shm_base += shm_base_offs; + s->shm_base = (u32) MEM_LINEAR_ADDRESS((void *)s->shm_base, + mem_sz); + if (!s->shm_base) { + status = -EFAULT; + goto free_eproc; } - hio_mgr->shared_mem = (struct shm *)ul_shm_base; + /* Register SM */ + status = register_shm_segs(hio_mgr, cod_man, eproc[0].gpp_pa); + + hio_mgr->shared_mem = (struct shm *)s->shm_base; hio_mgr->input = (u8 *) hio_mgr->shared_mem + sizeof(struct shm); - hio_mgr->output = hio_mgr->input + (ul_shm_length - + hio_mgr->output = hio_mgr->input + (shm_sz - sizeof(struct shm)) / 2; hio_mgr->sm_buf_size = hio_mgr->output - hio_mgr->input; - /* Set up Shared memory addresses for messaging. */ - hio_mgr->msg_input_ctrl = (struct msg_ctrl *)((u8 *) hio_mgr->shared_mem - + ul_shm_length); + /* Set up Shared memory addresses for messaging */ + hio_mgr->msg_input_ctrl = + (struct msg_ctrl *)((u8 *) hio_mgr->shared_mem + shm_sz); hio_mgr->msg_input = - (u8 *) hio_mgr->msg_input_ctrl + sizeof(struct msg_ctrl); + (u8 *) hio_mgr->msg_input_ctrl + sizeof(struct msg_ctrl); hio_mgr->msg_output_ctrl = - (struct msg_ctrl *)((u8 *) hio_mgr->msg_input_ctrl + - ul_msg_length / 2); + (struct msg_ctrl *)((u8 *) hio_mgr->msg_input_ctrl + + msg_sz / 2); hio_mgr->msg_output = - (u8 *) hio_mgr->msg_output_ctrl + sizeof(struct msg_ctrl); + (u8 *) hio_mgr->msg_output_ctrl + sizeof(struct msg_ctrl); hmsg_mgr->max_msgs = - ((u8 *) hio_mgr->msg_output_ctrl - hio_mgr->msg_input) - / sizeof(struct msg_dspmsg); + ((u8 *) hio_mgr->msg_output_ctrl - hio_mgr->msg_input) / + sizeof(struct msg_dspmsg); + dev_dbg(bridge, "IO MGR shm details: shared_mem %p, input %p, " "output %p, msg_input_ctrl %p, msg_input %p, " "msg_output_ctrl %p, msg_output %p\n", @@ -732,47 +708,53 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) /* Get the start address of trace buffer */ status = cod_get_sym_value(cod_man, SYS_PUTCBEG, &hio_mgr->trace_buffer_begin); - if (status) { - status = -EFAULT; - goto func_end; - } + if (status) + goto free_eproc; + + hio_mgr->gpp_read_pointer = + hio_mgr->trace_buffer_begin = + (va + seg1_sz + pad_sz) + + (hio_mgr->trace_buffer_begin - da); - hio_mgr->gpp_read_pointer = hio_mgr->trace_buffer_begin = - (ul_gpp_va + ul_seg1_size + ul_pad_size) + - (hio_mgr->trace_buffer_begin - ul_dsp_va); /* Get the end address of trace buffer */ status = cod_get_sym_value(cod_man, SYS_PUTCEND, &hio_mgr->trace_buffer_end); - if (status) { - status = -EFAULT; - goto func_end; - } + if (status) + goto free_eproc; + hio_mgr->trace_buffer_end = - (ul_gpp_va + ul_seg1_size + ul_pad_size) + - (hio_mgr->trace_buffer_end - ul_dsp_va); + (va + seg1_sz + pad_sz) + + (hio_mgr->trace_buffer_end - da); + /* Get the current address of DSP write pointer */ status = cod_get_sym_value(cod_man, BRIDGE_SYS_PUTC_CURRENT, &hio_mgr->trace_buffer_current); - if (status) { - status = -EFAULT; - goto func_end; - } + if (status) + goto free_eproc; + hio_mgr->trace_buffer_current = - (ul_gpp_va + ul_seg1_size + ul_pad_size) + - (hio_mgr->trace_buffer_current - ul_dsp_va); + (va + seg1_sz + pad_sz) + + (hio_mgr->trace_buffer_current - da); + /* Calculate the size of trace buffer */ kfree(hio_mgr->msg); hio_mgr->msg = kmalloc(((hio_mgr->trace_buffer_end - hio_mgr->trace_buffer_begin) * hio_mgr->word_size) + 2, GFP_KERNEL); - if (!hio_mgr->msg) + if (!hio_mgr->msg) { status = -ENOMEM; + goto free_eproc; + } - hio_mgr->dsp_va = ul_dsp_va; - hio_mgr->gpp_va = (ul_gpp_va + ul_seg1_size + ul_pad_size); - + hio_mgr->dsp_va = da; + hio_mgr->gpp_va = (va + seg1_sz + pad_sz); #endif -func_end: + +free_eproc: + kfree(eproc); +free_symbol: + kfree(s); + return status; } -- GitLab From a2fa68fd769647b114829ba2a198a062cdb1c686 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Fri, 29 Jun 2012 13:49:19 -0500 Subject: [PATCH 2126/5711] staging: tidspbridge: dynamically allocate ibuf in dload_data Dynamically allocate ibuf to silence the following warning: drivers/staging/tidspbridge/dynload/cload.c: In function 'dload_data': drivers/staging/tidspbridge/dynload/cload.c:1337: warning: the frame size of 1216 bytes is larger than 1024 bytes Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/dynload/cload.c | 54 ++++++++++++--------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c index fe1ef0addb09..3a12b435382d 100644 --- a/drivers/staging/tidspbridge/dynload/cload.c +++ b/drivers/staging/tidspbridge/dynload/cload.c @@ -14,6 +14,8 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#include + #include "header.h" #include "module_list.h" @@ -1116,6 +1118,11 @@ static int relocate_packet(struct dload_state *dlthis, /* VERY dangerous */ static const char imagepak[] = { "image packet" }; +struct img_buffer { + struct image_packet_t ipacket; + u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)]; +}; + /************************************************************************* * Procedure dload_data * @@ -1131,16 +1138,16 @@ static void dload_data(struct dload_state *dlthis) u16 curr_sect; struct doff_scnhdr_t *sptr = dlthis->sect_hdrs; struct ldr_section_info *lptr = dlthis->ldr_sections; + struct img_buffer *ibuf; u8 *dest; - struct { - struct image_packet_t ipacket; - u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)]; - } ibuf; - /* Indicates whether CINIT processing has occurred */ bool cinit_processed = false; + ibuf = kzalloc(sizeof(*ibuf), GFP_KERNEL); + if (!ibuf) + return; + /* Loop through the sections and load them one at a time. */ for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns; @@ -1168,37 +1175,37 @@ static void dload_data(struct dload_state *dlthis) /* get the fixed header bits */ if (dlthis->strm->read_buffer(dlthis->strm, - &ibuf.ipacket, + &ibuf->ipacket, IPH_SIZE) != IPH_SIZE) { DL_ERROR(readstrm, imagepak); - return; + goto free_ibuf; } /* reorder the header if need be */ if (dlthis->reorder_map) { - dload_reorder(&ibuf.ipacket, IPH_SIZE, + dload_reorder(&ibuf->ipacket, IPH_SIZE, dlthis->reorder_map); } /* now read the rest of the packet */ ipsize = BYTE_TO_HOST(DOFF_ALIGN - (ibuf.ipacket.packet_size)); + (ibuf->ipacket.packet_size)); if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) { DL_ERROR("Bad image packet size %d", ipsize); - return; + goto free_ibuf; } - dest = ibuf.bufr; + dest = ibuf->bufr; /* End of determination */ if (dlthis->strm->read_buffer(dlthis->strm, - ibuf.bufr, + ibuf->bufr, ipsize) != ipsize) { DL_ERROR(readstrm, imagepak); - return; + goto free_ibuf; } - ibuf.ipacket.img_data = dest; + ibuf->ipacket.img_data = dest; /* reorder the bytes if need be */ #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16) @@ -1225,16 +1232,16 @@ static void dload_data(struct dload_state *dlthis) #endif #endif - checks += dload_checksum(&ibuf.ipacket, + checks += dload_checksum(&ibuf->ipacket, IPH_SIZE); /* relocate the image bits as needed */ - if (ibuf.ipacket.num_relocs) { + if (ibuf->ipacket.num_relocs) { dlthis->image_offset = image_offset; if (!relocate_packet(dlthis, - &ibuf.ipacket, + &ibuf->ipacket, &checks, &tramp_generated)) - return; /* serious error */ + goto free_ibuf; /* error */ } if (~checks) DL_ERROR(err_checksum, imagepak); @@ -1249,20 +1256,20 @@ static void dload_data(struct dload_state *dlthis) if (dload_check_type(sptr, DLOAD_CINIT)) { cload_cinit(dlthis, - &ibuf.ipacket); + &ibuf->ipacket); cinit_processed = true; } else { /* FIXME */ if (!dlthis->myio-> writemem(dlthis-> myio, - ibuf.bufr, + ibuf->bufr, lptr-> load_addr + image_offset, lptr, BYTE_TO_HOST - (ibuf. + (ibuf-> ipacket. packet_size))) { DL_ERROR @@ -1276,7 +1283,7 @@ static void dload_data(struct dload_state *dlthis) } } image_offset += - BYTE_TO_TADDR(ibuf.ipacket.packet_size); + BYTE_TO_TADDR(ibuf->ipacket.packet_size); } /* process packets */ /* if this is a BSS section, we may want to fill it */ if (!dload_check_type(sptr, DLOAD_BSS)) @@ -1334,6 +1341,9 @@ loop_cont: DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32 ") failed", dlthis->tramp.tramp_sect_next_addr); } +free_ibuf: + kfree(ibuf); + return; } /* dload_data */ /************************************************************************* -- GitLab From ec4c6675230402384976d34d38e2b828be6ad0d9 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Fri, 29 Jun 2012 13:49:20 -0500 Subject: [PATCH 2127/5711] staging: tidspbridge: dynamically allocate my_sym_buf in dload_symbols Dynamically allocate my_sym_buf to silence the following warning: drivers/staging/tidspbridge/dynload/cload.c: In function 'dload_symbols': drivers/staging/tidspbridge/dynload/cload.c:890: warning: the frame size of 1040 bytes is larger than 1024 bytes Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/dynload/cload.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c index 3a12b435382d..9d54744805b8 100644 --- a/drivers/staging/tidspbridge/dynload/cload.c +++ b/drivers/staging/tidspbridge/dynload/cload.c @@ -708,6 +708,7 @@ static void dload_symbols(struct dload_state *dlthis) struct local_symbol *sp; struct dynload_symbol *symp; struct dynload_symbol *newsym; + struct doff_syment_t *my_sym_buf; sym_count = dlthis->dfile_hdr.df_no_syms; if (sym_count == 0) @@ -741,13 +742,18 @@ static void dload_symbols(struct dload_state *dlthis) become defined from the global symbol table */ checks = dlthis->verify.dv_sym_tab_checksum; symbols_left = sym_count; + + my_sym_buf = kzalloc(sizeof(*my_sym_buf) * MY_SYM_BUF_SIZ, GFP_KERNEL); + if (!my_sym_buf) + return; + do { /* read all symbols */ char *sname; u32 val; s32 delta; struct doff_syment_t *input_sym; unsigned syms_in_buf; - struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ]; + input_sym = my_sym_buf; syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ? MY_SYM_BUF_SIZ : symbols_left; @@ -755,7 +761,7 @@ static void dload_symbols(struct dload_state *dlthis) if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) != siz) { DL_ERROR(readstrm, sym_errid); - return; + goto free_sym_buf; } if (dlthis->reorder_map) dload_reorder(input_sym, siz, dlthis->reorder_map); @@ -858,7 +864,7 @@ static void dload_symbols(struct dload_state *dlthis) DL_ERROR("Absolute symbol %s is " "defined multiple times with " "different values", sname); - return; + goto free_sym_buf; } } loop_itr: @@ -889,6 +895,9 @@ loop_cont: if (~checks) dload_error(dlthis, "Checksum of symbols failed"); +free_sym_buf: + kfree(my_sym_buf); + return; } /* dload_symbols */ /***************************************************************************** -- GitLab From 563df3d0bc2ca103e5ddb76c8b7b3386ed2da0d6 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 13 Jun 2012 16:01:10 -0300 Subject: [PATCH 2128/5711] [media] v4l: Unify selection flags Unify flags on the selection interfaces on V4L2 and V4L2 subdev. Flags are very similar to targets in this case: there are more similarities than differences between the two interfaces. Signed-off-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/ispccdc.c | 2 +- drivers/media/video/omap3isp/isppreview.c | 2 +- drivers/media/video/smiapp/smiapp-core.c | 10 +++++----- include/linux/v4l2-common.h | 20 +++++++++++++++++--- include/linux/v4l2-subdev.h | 6 +----- include/linux/videodev2.h | 6 +----- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index 82df7a06dc36..f1220d3d4970 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -2064,7 +2064,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, * pad. If the KEEP_CONFIG flag is set, just return the current crop * rectangle. */ - if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) { + if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { sel->r = *__ccdc_get_crop(ccdc, fh, sel->which); return 0; } diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index 6fa70f4e8ea4..99d5cc4fd623 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c @@ -2000,7 +2000,7 @@ static int preview_set_selection(struct v4l2_subdev *sd, * pad. If the KEEP_CONFIG flag is set, just return the current crop * rectangle. */ - if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) { + if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { sel->r = *__preview_get_crop(prev, fh, sel->which); return 0; } diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/video/smiapp/smiapp-core.c index 9bbb5d3f003b..8a5d4f7932a0 100644 --- a/drivers/media/video/smiapp/smiapp-core.c +++ b/drivers/media/video/smiapp/smiapp-core.c @@ -38,9 +38,9 @@ #include "smiapp.h" -#define SMIAPP_ALIGN_DIM(dim, flags) \ - ((flags) & V4L2_SUBDEV_SEL_FLAG_SIZE_GE \ - ? ALIGN((dim), 2) \ +#define SMIAPP_ALIGN_DIM(dim, flags) \ + ((flags) & V4L2_SEL_FLAG_GE \ + ? ALIGN((dim), 2) \ : (dim) & ~1) /* @@ -1747,14 +1747,14 @@ static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w, h &= ~1; ask_h &= ~1; - if (flags & V4L2_SUBDEV_SEL_FLAG_SIZE_GE) { + if (flags & V4L2_SEL_FLAG_GE) { if (w < ask_w) val -= SCALING_GOODNESS; if (h < ask_h) val -= SCALING_GOODNESS; } - if (flags & V4L2_SUBDEV_SEL_FLAG_SIZE_LE) { + if (flags & V4L2_SEL_FLAG_LE) { if (w > ask_w) val -= SCALING_GOODNESS; if (h > ask_h) diff --git a/include/linux/v4l2-common.h b/include/linux/v4l2-common.h index e85bf15b5994..0fa8b64c3cdb 100644 --- a/include/linux/v4l2-common.h +++ b/include/linux/v4l2-common.h @@ -29,7 +29,11 @@ #ifndef __V4L2_COMMON__ #define __V4L2_COMMON__ -/* Selection target definitions */ +/* + * + * Selection interface definitions + * + */ /* Current cropping area */ #define V4L2_SEL_TGT_CROP 0x0000 @@ -46,7 +50,7 @@ /* Current composing area plus all padding pixels */ #define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 -/* Backward compatibility definitions */ +/* Backward compatibility target definitions --- to be removed. */ #define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP #define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE #define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL \ @@ -54,4 +58,14 @@ #define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL \ V4L2_SEL_TGT_COMPOSE -#endif /* __V4L2_COMMON__ */ +/* Selection flags */ +#define V4L2_SEL_FLAG_GE (1 << 0) +#define V4L2_SEL_FLAG_LE (1 << 1) +#define V4L2_SEL_FLAG_KEEP_CONFIG (1 << 2) + +/* Backward compatibility flag definitions --- to be removed. */ +#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE V4L2_SEL_FLAG_GE +#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE V4L2_SEL_FLAG_LE +#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG + +#endif /* __V4L2_COMMON__ */ diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 1d7d45739260..8c57ee9872bb 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -124,10 +124,6 @@ struct v4l2_subdev_frame_interval_enum { __u32 reserved[9]; }; -#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE (1 << 0) -#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE (1 << 1) -#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG (1 << 2) - /** * struct v4l2_subdev_selection - selection info * @@ -135,7 +131,7 @@ struct v4l2_subdev_frame_interval_enum { * @pad: pad number, as reported by the media API * @target: Selection target, used to choose one of possible rectangles, * defined in v4l2-common.h; V4L2_SEL_TGT_* . - * @flags: constraint flags + * @flags: constraint flags, defined in v4l2-common.h; V4L2_SEL_FLAG_*. * @r: coordinates of the selection window * @reserved: for future use, set to zero for now * diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 7fdb8710c831..5d78910f926c 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -761,16 +761,12 @@ struct v4l2_crop { struct v4l2_rect c; }; -/* Hints for adjustments of selection rectangle */ -#define V4L2_SEL_FLAG_GE 0x00000001 -#define V4L2_SEL_FLAG_LE 0x00000002 - /** * struct v4l2_selection - selection info * @type: buffer type (do not use *_MPLANE types) * @target: Selection target, used to choose one of possible rectangles; * defined in v4l2-common.h; V4L2_SEL_TGT_* . - * @flags: constraints flags + * @flags: constraints flags, defined in v4l2-common.h; V4L2_SEL_FLAG_*. * @r: coordinates of selection window * @reserved: for future use, rounds structure size to 64 bytes, set to zero * -- GitLab From 9fe75aac380bb0399756a14d14f29346a020a647 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 13 Jun 2012 16:01:10 -0300 Subject: [PATCH 2129/5711] [media] v4l: Unify selection flags documentation As for the selection targets, the selection flags are now the same on V4L2 and V4L2 subdev interfaces. Also document them so. Signed-off-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/dev-subdev.xml | 6 +- .../DocBook/media/v4l/selection-api.xml | 6 +- .../DocBook/media/v4l/selections-common.xml | 226 ++++++++++++------ .../DocBook/media/v4l/vidioc-g-selection.xml | 27 +-- .../media/v4l/vidioc-subdev-g-selection.xml | 39 +-- 5 files changed, 159 insertions(+), 145 deletions(-) diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index afeb196adce5..a3d9dd093268 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -323,10 +323,10 @@ The drivers should always use the closest possible rectangle the user requests on all selection targets, unless specifically told otherwise. - V4L2_SUBDEV_SEL_FLAG_SIZE_GE and - V4L2_SUBDEV_SEL_FLAG_SIZE_LE flags may be + V4L2_SEL_FLAG_GE and + V4L2_SEL_FLAG_LE flags may be used to round the image size either up or down. + linkend="v4l2-selection-flags" />
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml index 24dec10259d2..e7ed5077834d 100644 --- a/Documentation/DocBook/media/v4l/selection-api.xml +++ b/Documentation/DocBook/media/v4l/selection-api.xml @@ -55,7 +55,7 @@ cropping and composing rectangles have the same size.
- See for more + See for more information.
@@ -74,7 +74,7 @@ cropping/composing rectangles may have to be aligned, and both the source and the sink may have arbitrary upper and lower size limits. Therefore, as usual, drivers are expected to adjust the requested parameters and return the actual values selected. An application can control the rounding behaviour using constraint flags . +linkend="v4l2-selection-flags"> constraint flags .
@@ -117,7 +117,7 @@ the bounds rectangle. The composing rectangle must lie completely inside bounds rectangle. The driver must adjust the composing rectangle to fit to the bounding limits. Moreover, the driver can perform other adjustments according to hardware limitations. The application can control rounding behaviour using - constraint flags . + constraint flags . For capture devices the default composing rectangle is queried using V4L2_SEL_TGT_COMPOSE_DEFAULT . It is usually equal to the diff --git a/Documentation/DocBook/media/v4l/selections-common.xml b/Documentation/DocBook/media/v4l/selections-common.xml index 6728688d28df..b6618709ee7a 100644 --- a/Documentation/DocBook/media/v4l/selections-common.xml +++ b/Documentation/DocBook/media/v4l/selections-common.xml @@ -1,6 +1,6 @@
- Selection targets + Common selection definitions While the V4L2 selection API and V4L2 subdev @@ -10,83 +10,155 @@ sub-device's pad. On the V4L2 interface the selection rectangles refer to the in-memory pixel format. - The precise meaning of the selection targets may thus be - affected on which of the two interfaces they are used. + This section defines the common definitions of the + selection interfaces on the two APIs. -
- Selection target definitions - - - - - - - &cs-def; - - - Target name - id - Definition - Valid for V4L2 - Valid for V4L2 subdev - - - - - V4L2_SEL_TGT_CROP - 0x0000 - Crop rectangle. Defines the cropped area. - Yes - Yes - - - V4L2_SEL_TGT_CROP_DEFAULT - 0x0001 - Suggested cropping rectangle that covers the "whole picture". - Yes - No - - - V4L2_SEL_TGT_CROP_BOUNDS - 0x0002 - Bounds of the crop rectangle. All valid crop - rectangles fit inside the crop bounds rectangle. - - Yes - Yes - - - V4L2_SEL_TGT_COMPOSE - 0x0100 - Compose rectangle. Used to configure scaling - and composition. - Yes - Yes - - - V4L2_SEL_TGT_COMPOSE_DEFAULT - 0x0101 - Suggested composition rectangle that covers the "whole picture". - Yes - No - - - V4L2_SEL_TGT_COMPOSE_BOUNDS - 0x0102 - Bounds of the compose rectangle. All valid compose - rectangles fit inside the compose bounds rectangle. - Yes - Yes - - - V4L2_SEL_TGT_COMPOSE_PADDED - 0x0103 - The active area and all padding pixels that are inserted or +
+ + Selection targets + + The precise meaning of the selection targets may be + dependent on which of the two interfaces they are used. + +
+ Selection target definitions + + + + + + + &cs-def; + + + Target name + id + Definition + Valid for V4L2 + Valid for V4L2 subdev + + + + + V4L2_SEL_TGT_CROP + 0x0000 + Crop rectangle. Defines the cropped area. + Yes + Yes + + + V4L2_SEL_TGT_CROP_DEFAULT + 0x0001 + Suggested cropping rectangle that covers the "whole picture". + Yes + No + + + V4L2_SEL_TGT_CROP_BOUNDS + 0x0002 + Bounds of the crop rectangle. All valid crop + rectangles fit inside the crop bounds rectangle. + + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE + 0x0100 + Compose rectangle. Used to configure scaling + and composition. + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE_DEFAULT + 0x0101 + Suggested composition rectangle that covers the "whole picture". + Yes + No + + + V4L2_SEL_TGT_COMPOSE_BOUNDS + 0x0102 + Bounds of the compose rectangle. All valid compose + rectangles fit inside the compose bounds rectangle. + Yes + Yes + + + V4L2_SEL_TGT_COMPOSE_PADDED + 0x0103 + The active area and all padding pixels that are inserted or modified by hardware. - Yes - No + Yes + No + + + +
+ + + +
+ + Selection flags + + + Selection flag definitions + + + + + + + &cs-def; + + + Flag name + id + Definition + Valid for V4L2 + Valid for V4L2 subdev - - -
+ + + + V4L2_SEL_FLAG_GE + (1 << 0) + Suggest the driver it should choose greater or + equal rectangle (in size) than was requested. Albeit the + driver may choose a lesser size, it will only do so due to + hardware limitations. Without this flag (and + V4L2_SEL_FLAG_LE) the + behaviour is to choose the closest possible + rectangle. + Yes + Yes + + + V4L2_SEL_FLAG_LE + (1 << 1) + Suggest the driver it + should choose lesser or equal rectangle (in size) than was + requested. Albeit the driver may choose a greater size, it + will only do so due to hardware limitations. + Yes + Yes + + + V4L2_SEL_FLAG_KEEP_CONFIG + (1 << 2) + The configuration should not be propagated to any + further processing steps. If this flag is not given, the + configuration is propagated inside the subdevice to all + further processing steps. + No + Yes + + + + + +
+ diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml index c6f83257ecee..f76d8a6d9b92 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml @@ -154,32 +154,9 @@ exist no rectangle that satisfies the constraints.
- Selection targets are documented in Selection targets and flags are documented in . - - - Selection constraint flags - - &cs-def; - - - V4L2_SEL_FLAG_GE - 0x00000001 - Indicates that the adjusted rectangle must contain the original - &v4l2-selection; r rectangle. - - - V4L2_SEL_FLAG_LE - 0x00000002 - Indicates that the adjusted rectangle must be inside the original - &v4l2-rect; r rectangle. - - - -
-
-
Size adjustments with constraint flags. @@ -216,7 +193,7 @@ exist no rectangle that satisfies the constraints. __u32 flags Flags controlling the selection rectangle adjustments, refer to - selection flags. + selection flags. &v4l2-rect; diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml index ace147806e48..f33cc814a01d 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -87,44 +87,9 @@ EINVAL.
- Selection targets are documented in Selection targets and flags are documented in . - - V4L2 subdev selection flags - - &cs-def; - - - V4L2_SUBDEV_SEL_FLAG_SIZE_GE - (1 << 0) Suggest the driver it - should choose greater or equal rectangle (in size) than - was requested. Albeit the driver may choose a lesser size, - it will only do so due to hardware limitations. Without - this flag (and - V4L2_SUBDEV_SEL_FLAG_SIZE_LE) the - behaviour is to choose the closest possible - rectangle. - - - V4L2_SUBDEV_SEL_FLAG_SIZE_LE - (1 << 1) Suggest the driver it - should choose lesser or equal rectangle (in size) than was - requested. Albeit the driver may choose a greater size, it - will only do so due to hardware limitations. - - - V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG - (1 << 2) - The configuration should not be propagated to any - further processing steps. If this flag is not given, the - configuration is propagated inside the subdevice to all - further processing steps. - - - -
- struct <structname>v4l2_subdev_selection</structname> @@ -151,7 +116,7 @@ __u32 flags Flags. See - . + . &v4l2-rect; -- GitLab From aab048923955ca2fa050a06b5a54568b4e6c5f4c Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sun, 1 Jul 2012 23:31:35 +0530 Subject: [PATCH 2130/5711] staging/ft1000: fix minor coding style problem this following warn is fixed up drivers/staging/ft1000/ft1000-usb/ft1000_hw.c:1754: ERROR: open brace '{' following function declarations go on the next line Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index c1f4f13bf485..31929ef5332d 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1751,8 +1751,8 @@ out: return status; } -int ft1000_poll(void* dev_id) { - +int ft1000_poll(void* dev_id) +{ struct ft1000_device *dev = (struct ft1000_device *)dev_id; struct ft1000_info *info = netdev_priv(dev->net); -- GitLab From 599e6b2e90b4c152a633a2bcd7c583b0dff9bf98 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 2 Jul 2012 07:44:41 -0700 Subject: [PATCH 2131/5711] staging "telephony" Fix typos. Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/telephony/ixj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c index fd7757ad7fa3..b303c9192e17 100644 --- a/drivers/staging/telephony/ixj.c +++ b/drivers/staging/telephony/ixj.c @@ -7094,7 +7094,7 @@ static int ixj_selfprobe(IXJ *j) for (cnt = 0; cnt < 35; cnt++) j->ixj_signals[cnt] = SIGIO; - /* Set the excetion signal enable flags */ + /* Set the exception signal enable flags */ j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; @@ -7132,7 +7132,7 @@ IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx) return j; } -EXPORT_SYMBOL(ixj_pcmcia_probe); /* Fpr PCMCIA */ +EXPORT_SYMBOL(ixj_pcmcia_probe); /* For PCMCIA */ static int ixj_get_status_proc(char *buf) { -- GitLab From 24b46f9e4b3e0aa33e5fada23284e14a15dfa487 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 2 Jul 2012 23:59:30 -0300 Subject: [PATCH 2132/5711] staging: vt6656: main_usb.c: Remove useless macros All these macros are not used. So, remove this all. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 35 +------------------------------ 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ee5261a36886..5048341518c3 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -92,22 +92,14 @@ MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM); module_param_array(N, int, NULL, 0);\ MODULE_PARM_DESC(N, D); -#define RX_DESC_MIN0 16 -#define RX_DESC_MAX0 128 #define RX_DESC_DEF0 64 DEVICE_PARAM(RxDescriptors0,"Number of receive usb desc buffer"); -#define TX_DESC_MIN0 16 -#define TX_DESC_MAX0 128 #define TX_DESC_DEF0 64 DEVICE_PARAM(TxDescriptors0,"Number of transmit usb desc buffer"); - -#define CHANNEL_MIN 1 -#define CHANNEL_MAX 14 #define CHANNEL_DEF 6 - DEVICE_PARAM(Channel, "Channel number"); @@ -120,23 +112,13 @@ DEVICE_PARAM(Channel, "Channel number"); DEVICE_PARAM(PreambleType, "Preamble Type"); - -#define RTS_THRESH_MIN 512 -#define RTS_THRESH_MAX 2347 #define RTS_THRESH_DEF 2347 - DEVICE_PARAM(RTSThreshold, "RTS threshold"); - -#define FRAG_THRESH_MIN 256 -#define FRAG_THRESH_MAX 2346 #define FRAG_THRESH_DEF 2346 - DEVICE_PARAM(FragThreshold, "Fragmentation threshold"); -#define DATA_RATE_MIN 0 -#define DATA_RATE_MAX 13 #define DATA_RATE_DEF 13 /* datarate[] index 0: indicate 1 Mbps 0x02 @@ -157,10 +139,7 @@ DEVICE_PARAM(FragThreshold, "Fragmentation threshold"); DEVICE_PARAM(ConnectionRate, "Connection data rate"); -#define OP_MODE_MAX 2 #define OP_MODE_DEF 0 -#define OP_MODE_MIN 0 - DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode "); /* OpMode[] is used for transmit. @@ -176,34 +155,22 @@ DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode "); */ #define PS_MODE_DEF 0 - DEVICE_PARAM(PSMode, "Power saving mode"); -#define SHORT_RETRY_MIN 0 -#define SHORT_RETRY_MAX 31 #define SHORT_RETRY_DEF 8 - - DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); -#define LONG_RETRY_MIN 0 -#define LONG_RETRY_MAX 15 #define LONG_RETRY_DEF 4 - - DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); - /* BasebandType[] baseband type selected 0: indicate 802.11a type 1: indicate 802.11b type 2: indicate 802.11g type */ -#define BBP_TYPE_MIN 0 -#define BBP_TYPE_MAX 2 -#define BBP_TYPE_DEF 2 +#define BBP_TYPE_DEF 2 DEVICE_PARAM(BasebandType, "baseband type"); -- GitLab From 7183f337fef677165d3dbd09a42ee9578c94f890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Iglesias=20Gons=C3=A1lvez?= Date: Wed, 4 Jul 2012 16:11:10 +0200 Subject: [PATCH 2133/5711] Staging: ipack/devices/ipoctal: save IRQ vector in MEM space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IRQ vector should be saved in MEM space base address according to the datasheet. Signed-off-by: Samuel Iglesias Gonsálvez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/devices/ipoctal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index ec7b2f9c89ad..a5af423a4e7c 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -435,7 +435,8 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, */ ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector, ipoctal_irq_handler, ipoctal); - ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_ID_SPACE, 0, vector); + ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_MEM_SPACE, 0, + vector); /* Register the TTY device */ -- GitLab From e97e6c4f9a5d23a1bd7141b6fa73e2f96282c03d Mon Sep 17 00:00:00 2001 From: David Murray Date: Fri, 6 Jul 2012 09:20:43 -0500 Subject: [PATCH 2134/5711] Drivers: Staging: ccg: Made checkpatch.pl clean Fixed a tiny checkpatch.pl warning. Signed-off-by: David Murray Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccg/ccg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c index a5b36a97598d..c50fa020e5c8 100644 --- a/drivers/staging/ccg/ccg.c +++ b/drivers/staging/ccg/ccg.c @@ -1143,7 +1143,7 @@ static int ccg_bind(struct usb_composite_dev *cdev) if (gcnum >= 0) device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); else { - pr_warning("%s: controller '%s' not recognized\n", + pr_warn("%s: controller '%s' not recognized\n", longname, gadget->name); device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); } -- GitLab From a7f3943cd055f73e82e1b57468286f3d7cf9fb27 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 6 Jul 2012 11:21:49 +0300 Subject: [PATCH 2135/5711] Staging: vme: silence a Sparse warning Sparse complains that "arg" is not a __user pointer. The "argp" and "arg" variables are equivalent but argp is declared as a __user pointer. Signed-off-by: Dan Carpenter Acked-By: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/devices/vme_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index e24a6f95db12..0c2479e41938 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -474,7 +474,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file, case CONTROL_MINOR: switch (cmd) { case VME_IRQ_GEN: - copied = copy_from_user(&irq_req, (char *)arg, + copied = copy_from_user(&irq_req, argp, sizeof(struct vme_irq_id)); if (copied != 0) { printk(KERN_WARNING "Partial copy from userspace\n"); -- GitLab From 2c27d008c856a65eeb0612108127240d05a66bdb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:28:13 +0300 Subject: [PATCH 2136/5711] staging: bcm: use %pM to print MAC addresses Signed-off-by: Andy Shevchenko Cc: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/CmHost.c | 44 +++++++++++++----------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 189d243878c9..9c8c9b14e8d4 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -967,24 +967,18 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, + DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: %pM", + psfCSType->cCPacketClassificationRule. + u8EthernetDestMacAddress); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, + DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: " + "%pM", psfCSType->cCPacketClassificationRule. + u8EthernetSourceMACAddress); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength); @@ -1123,24 +1117,18 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, + DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: %pM", + psfCSType->cCPacketClassificationRule. + u8EthernetDestMacAddress); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, + DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: " + "%pM", psfCSType->cCPacketClassificationRule. + u8EthernetSourceMACAddress); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X %02X %02X", -- GitLab From a6737c738c327b982a4251ad6be06153220da722 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:28:14 +0300 Subject: [PATCH 2137/5711] staging: csr: print MAC addresses via %pM Signed-off-by: Andy Shevchenko Cc: Lauri Hintsala Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/sme_mgt.c | 10 ++------ drivers/staging/csr/sme_sys.c | 29 +++++++++------------- drivers/staging/csr/sme_wext.c | 27 +++++--------------- drivers/staging/csr/unifi_pdu_processing.c | 8 ++++-- drivers/staging/csr/unifi_priv.h | 13 ---------- drivers/staging/csr/unifi_sme.c | 3 ++- 6 files changed, 28 insertions(+), 62 deletions(-) diff --git a/drivers/staging/csr/sme_mgt.c b/drivers/staging/csr/sme_mgt.c index ab70216516b3..c27c0a73aa47 100644 --- a/drivers/staging/csr/sme_mgt.c +++ b/drivers/staging/csr/sme_mgt.c @@ -838,14 +838,8 @@ void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) (unsigned char *)ind->connectionInfo.assocScanInfoElements, ind->connectionInfo.assocScanInfoElementsLength); - unifi_trace(priv, UDBG2, - "CsrWifiSmeMediaStatusIndSend: IBSS=%02X:%02X:%02X:%02X:%02X:%02X\n", - ind->connectionInfo.bssid.a[0], - ind->connectionInfo.bssid.a[1], - ind->connectionInfo.bssid.a[2], - ind->connectionInfo.bssid.a[3], - ind->connectionInfo.bssid.a[4], - ind->connectionInfo.bssid.a[5]); + unifi_trace(priv, UDBG2, "CsrWifiSmeMediaStatusIndSend: IBSS=%pM\n", + ind->connectionInfo.bssid.a); sme_mgt_packet_filter_set(priv); diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c index 283e3025641e..9c3aa7494604 100644 --- a/drivers/staging/csr/sme_sys.c +++ b/drivers/staging/csr/sme_sys.c @@ -527,11 +527,9 @@ configure_data_port(unifi_priv_t *priv, controlled_string = "uncontrolled"; } - unifi_trace(priv, UDBG2, "port config request %02x:%02x:%02x:%02x:%02x:%02x %s with port_action %d.\n", - macAddress->a[0], macAddress->a[1], macAddress->a[2], - macAddress->a[3], macAddress->a[4], macAddress->a[5], - controlled_string, port_action); - + unifi_trace(priv, UDBG2, + "port config request %pM %s with port_action %d.\n", + macAddress->a, controlled_string, port_action); /* If the new configuration has the broadcast MAC address or if we are in infrastructure mode then clear the list first and set port overide mode */ if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode || @@ -653,10 +651,9 @@ configure_data_port(unifi_priv_t *priv, uf_free_pending_rx_packets(priv, queue, *macAddress,interfaceTag); } - unifi_trace(priv, UDBG2, "port config %02x:%02x:%02x:%02x:%02x:%02x with port_action %d.\n", - *(macAddress->a+0), *(macAddress->a+1), *(macAddress->a+2), - *(macAddress->a+3), *(macAddress->a+4), *(macAddress->a+5), - port_action); + unifi_trace(priv, UDBG2, + "port config %pM with port_action %d.\n", + macAddress->a, port_action); } return 0; } /* configure_data_port() */ @@ -2649,11 +2646,9 @@ CsrBool blockack_session_stop(unifi_priv_t *priv, return FALSE; } - unifi_warning(priv, "%s: stopping ba_session for peer = %02x:%02x:%02x:%02x:%02x:%02x role = %d tID = %d\n", __FUNCTION__, - macAddress.a[0], macAddress.a[1], macAddress.a[2], - macAddress.a[3], macAddress.a[4], macAddress.a[5], - role, - tID); + unifi_warning(priv, + "%s: stopping ba_session for peer = %pM role = %d tID = %d\n", + __func__, macAddress.a, role, tID); /* find out the appropriate ba session (/station /tid /role) for which stop is requested */ if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ @@ -2781,9 +2776,9 @@ CsrBool blockack_session_start(unifi_priv_t *priv, return FALSE; } - unifi_warning(priv, "%s: ba session with peer= (%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, - macAddress.a[0], macAddress.a[1], macAddress.a[2], - macAddress.a[3], macAddress.a[4], macAddress.a[5]); + unifi_warning(priv, + "%s: ba session with peer= (%pM)\n", __func__, + macAddress.a); unifi_warning(priv, "%s: ba session for tID=%d timeout=%d role=%d wind_size=%d start_sn=%d\n", __FUNCTION__, tID, diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c index 3ba7b4cef2dd..cdc72dbd11c0 100644 --- a/drivers/staging/csr/sme_wext.c +++ b/drivers/staging/csr/sme_wext.c @@ -1210,13 +1210,8 @@ unifi_siwap(struct net_device *dev, struct iw_request_info *info, return -EINVAL; } - unifi_trace(priv, UDBG1, "unifi_siwap: asked for %02X:%02X:%02X:%02X:%02X:%02X\n", - (u8)wrqu->ap_addr.sa_data[0], - (u8)wrqu->ap_addr.sa_data[1], - (u8)wrqu->ap_addr.sa_data[2], - (u8)wrqu->ap_addr.sa_data[3], - (u8)wrqu->ap_addr.sa_data[4], - (u8)wrqu->ap_addr.sa_data[5]); + unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n", + wrqu->ap_addr.sa_data); if (!memcmp(wrqu->ap_addr.sa_data, zero_bssid, ETH_ALEN)) { priv->ignore_bssid_join = FALSE; @@ -1281,10 +1276,7 @@ unifi_giwap(struct net_device *dev, struct iw_request_info *info, if (r == 0) { bssid = connectionInfo.bssid.a; wrqu->ap_addr.sa_family = ARPHRD_ETHER; - unifi_trace(priv, UDBG4, - "unifi_giwap: BSSID = %02X:%02X:%02X:%02X:%02X:%02X\n", - bssid[0], bssid[1], bssid[2], - bssid[3], bssid[4], bssid[5]); + unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid); memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN); } else { @@ -2936,8 +2928,7 @@ _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n", wrqu->encoding.flags, ext->alg, ext->ext_flags, ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX)); - unifi_trace(priv, UDBG3, " addr=%02X:%02X:%02X:%02X:%02X:%02X\n", - a[0], a[1], a[2], a[3], a[4], a[5]); + unifi_trace(priv, UDBG3, " addr=%pM\n", a); if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { /* This means use a different key (given by key_idx) for Tx. */ @@ -3140,14 +3131,8 @@ unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info, } - unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %02x:%02x:%02x:%02x:%02x:%02x\n", - pmksa->cmd, - pmksa->bssid.sa_data[0], - pmksa->bssid.sa_data[1], - pmksa->bssid.sa_data[2], - pmksa->bssid.sa_data[3], - pmksa->bssid.sa_data[4], - pmksa->bssid.sa_data[5]); + unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd, + pmksa->bssid.sa_data); pmkid_list.pmkids = NULL; switch (pmksa->cmd) { diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c index e35747c08317..45c69a9d3832 100644 --- a/drivers/staging/csr/unifi_pdu_processing.c +++ b/drivers/staging/csr/unifi_pdu_processing.c @@ -68,7 +68,9 @@ unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, interfacePriv = priv->interfacePriv[interfaceTag]; - UF_TRACE_MAC(priv, UDBG5, "In unifi_frame_ma_packet_req, Frame for Peer:", peerMacAddress); + unifi_trace(priv, UDBG5, + "In unifi_frame_ma_packet_req, Frame for Peer: %pMF\n", + peerMacAddress); signal->SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; signal->SignalPrimitiveHeader.ReceiverProcessId = 0; signal->SignalPrimitiveHeader.SenderProcessId = leSenderProcessId; @@ -1668,7 +1670,9 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, CsrUint32 handle = 0xFFFFFFFF; unsigned long lock_flags; - UF_TRACE_MAC(priv, UDBG5, "entering uf_process_ma_packet_req, peer: ", peerMacAddress); + unifi_trace(priv, UDBG5, + "entering uf_process_ma_packet_req, peer: %pMF\n", + peerMacAddress); if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { unifi_error(priv, "interfaceTag >= CSR_WIFI_NUM_INTERFACES, interfacetag = %d\n", interfaceTag); diff --git a/drivers/staging/csr/unifi_priv.h b/drivers/staging/csr/unifi_priv.h index b23c84456578..7e940ef6acda 100644 --- a/drivers/staging/csr/unifi_priv.h +++ b/drivers/staging/csr/unifi_priv.h @@ -1174,17 +1174,4 @@ int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg); - -/* Macro for formatting a MAC address with a prefix string */ -#define UF_TRACE_MAC(priv, lvl, msg, addr) \ - unifi_trace(priv, lvl, \ - "%s %02x-%02x-%02x-%02x-%02x-%02x\n", \ - msg, \ - *(((CsrUint8 *)addr)+0), \ - *(((CsrUint8 *)addr)+1), \ - *(((CsrUint8 *)addr)+2), \ - *(((CsrUint8 *)addr)+3), \ - *(((CsrUint8 *)addr)+4), \ - *(((CsrUint8 *)addr)+5)) - #endif /* __LINUX_UNIFI_PRIV_H__ */ diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c index 54414ed2ed1c..6e7cbbf70c88 100644 --- a/drivers/staging/csr/unifi_sme.c +++ b/drivers/staging/csr/unifi_sme.c @@ -1174,7 +1174,8 @@ uf_send_m4_ready_wq(struct work_struct *work) /* Send a signal to SME */ CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer); - UF_TRACE_MAC(priv, UDBG1, "M4ReadyToSendInd sent for peer", peer.a); + unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n", + peer.a); func_exit(); -- GitLab From d3cc13a24beb9cda3d56f5cfd4cc894b8df454ff Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:28:17 +0300 Subject: [PATCH 2138/5711] staging: vt6656: use %pM for the BSSID Signed-off-by: Andy Shevchenko Acked-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index 619c257e8773..099936771e69 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -129,9 +129,8 @@ PKnownBSS BSSpSearchBSSList(void *hDeviceContext, unsigned int ii = 0; unsigned int jj = 0; if (pbyDesireBSSID != NULL) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList BSSID[%02X %02X %02X-%02X %02X %02X]\n", - *pbyDesireBSSID,*(pbyDesireBSSID+1),*(pbyDesireBSSID+2), - *(pbyDesireBSSID+3),*(pbyDesireBSSID+4),*(pbyDesireBSSID+5)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "BSSpSearchBSSList BSSID[%pM]\n", pbyDesireBSSID); if ((!is_broadcast_ether_addr(pbyDesireBSSID)) && (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)){ pbyBSSID = pbyDesireBSSID; @@ -218,7 +217,9 @@ PKnownBSS BSSpSearchBSSList(void *hDeviceContext, } pMgmt->pSameBSS[jj].uChannel = pCurrBSS->uChannel; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList pSelect1[%02X %02X %02X-%02X %02X %02X]\n",*pCurrBSS->abyBSSID,*(pCurrBSS->abyBSSID+1),*(pCurrBSS->abyBSSID+2),*(pCurrBSS->abyBSSID+3),*(pCurrBSS->abyBSSID+4),*(pCurrBSS->abyBSSID+5)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "BSSpSearchBSSList pSelect1[%pM]\n", + pCurrBSS->abyBSSID); jj++; -- GitLab From 075fb4b7243c90f936049d07761f1cffd2577928 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:28:16 +0300 Subject: [PATCH 2139/5711] staging: vt6655: use %pM for BSSID Signed-off-by: Andy Shevchenko Cc: Forest Bond Cc: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 1368e8cc9add..f4f108f72afd 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -142,9 +142,8 @@ BSSpSearchBSSList( unsigned int ii = 0; if (pbyDesireBSSID != NULL) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList BSSID[%02X %02X %02X-%02X %02X %02X]\n", - *pbyDesireBSSID,*(pbyDesireBSSID+1),*(pbyDesireBSSID+2), - *(pbyDesireBSSID+3),*(pbyDesireBSSID+4),*(pbyDesireBSSID+5)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "BSSpSearchBSSList BSSID[%pM]\n", pbyDesireBSSID); if ((!is_broadcast_ether_addr(pbyDesireBSSID)) && (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)){ pbyBSSID = pbyDesireBSSID; -- GitLab From e7ecb0fb40a5358646888720848787da34cfa33d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:28:15 +0300 Subject: [PATCH 2140/5711] staging: gdm72xx: use %pM for MAC Signed-off-by: Andy Shevchenko Cc: Ben Chan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/gdm_wimax.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c index 110bdbc9c899..e616de13b623 100644 --- a/drivers/staging/gdm72xx/gdm_wimax.c +++ b/drivers/staging/gdm72xx/gdm_wimax.c @@ -744,13 +744,8 @@ static int gdm_wimax_get_prepared_info(struct net_device *dev, char *buf, "[%x/%d]\n", __func__, T, L); return -1; } - printk(KERN_INFO - "MAC change [%02x:%02x:%02x:%02x:%02x:%02x]" - "->[%02x:%02x:%02x:%02x:%02x:%02x]\n", - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - V[0], V[1], V[2], V[3], V[4], V[5]); + printk(KERN_INFO "MAC change [%pM]->[%pM]\n", + dev->dev_addr, V); memcpy(dev->dev_addr, V, dev->addr_len); return 1; } -- GitLab From 0932966b1ca03217c6e0c18375867b1a99ee5af0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:39:47 +0300 Subject: [PATCH 2141/5711] staging: ccg: print MAC addresses via %pM Signed-off-by: Andy Shevchenko Acked-by: Kyungmin Park Cc: Andrzej Pietrasiewicz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccg/ccg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c index c50fa020e5c8..6a7aab8d9bf5 100644 --- a/drivers/staging/ccg/ccg.c +++ b/drivers/staging/ccg/ccg.c @@ -564,9 +564,7 @@ static int rndis_function_bind_config(struct ccg_usb_function *f, return -1; } - pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, - rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], - rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); + pr_info("%s MAC: %pM\n", __func__, rndis->ethaddr); ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis"); if (ret) { @@ -654,9 +652,7 @@ static ssize_t rndis_ethaddr_show(struct device *dev, { struct ccg_usb_function *f = dev_get_drvdata(dev); struct rndis_function_config *rndis = f->config; - return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", - rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], - rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); + return sprintf(buf, "%pM\n", rndis->ethaddr); } static ssize_t rndis_ethaddr_store(struct device *dev, -- GitLab From 6889d5ced744cb8a5a96d359e8c3bc4e62bdc36b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 25 Jun 2012 16:14:41 -0300 Subject: [PATCH 2142/5711] [media] Feature removal: V4L2 selections API target and flag definitions After unification of the V4L2 and V4L2 subdev selection targets and flags the old flags are no longer required. Thus they can be removed. However, as the API is present in a kernel release, this must go through the feature removal process. Signed-off-by: Sylwester Nawrocki Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 09701afc031a..b99803066b7b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -558,3 +558,21 @@ Why: The V4L2_CID_VCENTER, V4L2_CID_HCENTER controls have been deprecated There are newer controls (V4L2_CID_PAN*, V4L2_CID_TILT*) that provide similar functionality. Who: Sylwester Nawrocki + +---------------------------- + +What: V4L2 selections API target rectangle and flags unification, the + following definitions will be removed: V4L2_SEL_TGT_CROP_ACTIVE, + V4L2_SEL_TGT_COMPOSE_ACTIVE, V4L2_SUBDEV_SEL_*, V4L2_SUBDEV_SEL_FLAG_* + in favor of common V4L2_SEL_TGT_* and V4L2_SEL_FLAG_* definitions. + For more details see include/linux/v4l2-common.h. +When: 3.8 +Why: The regular V4L2 selections and the subdev selection API originally + defined distinct names for the target rectangles and flags - V4L2_SEL_* + and V4L2_SUBDEV_SEL_*. Although, it turned out that the meaning of these + target rectangles is virtually identical and the APIs were consolidated + to use single set of names - V4L2_SEL_*. This didn't involve any ABI + changes. Alias definitions were created for the original ones to avoid + any instabilities in the user space interface. After few cycles these + backward compatibility definitions will be removed. +Who: Sylwester Nawrocki -- GitLab From 9a70d980d038e27828db92cef235fabfb618c77d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 15 Jun 2012 10:22:25 -0300 Subject: [PATCH 2143/5711] [media] v4l: Correct conflicting V4L2 subdev selection API documentation The API reference documents that the KEEP_CONFIG flag tells the configuration should not be propagated by the driver whereas the interface documentation (dev-subdev.xml) prohibited any changes to the rest of the pipeline. Resolve the conflict by changing the API reference to disallow changes. Signed-off-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/selections-common.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/selections-common.xml b/Documentation/DocBook/media/v4l/selections-common.xml index b6618709ee7a..7502f784b8cc 100644 --- a/Documentation/DocBook/media/v4l/selections-common.xml +++ b/Documentation/DocBook/media/v4l/selections-common.xml @@ -148,7 +148,7 @@ V4L2_SEL_FLAG_KEEP_CONFIG (1 << 2) - The configuration should not be propagated to any + The configuration must not be propagated to any further processing steps. If this flag is not given, the configuration is propagated inside the subdevice to all further processing steps. -- GitLab From 03228792df67a6ae231960151b8a5c87e17a73e2 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 8 May 2012 12:28:47 -0300 Subject: [PATCH 2144/5711] [media] Terratec Cinergy S2 USB HD Rev.2 Terratec Cinergy S2 USB HD Rev.2 support. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 9382895b1b88..7c37a566c55d 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -1178,6 +1178,13 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d) u8 obuf[3] = { 0xe, 0x80, 0 }; u8 ibuf[] = { 0 }; + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) + err("command 0x0e transfer failed."); + + obuf[0] = 0xe; + obuf[1] = 0x02; + obuf[2] = 1; + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) err("command 0x0e transfer failed."); @@ -1447,6 +1454,9 @@ enum dw2102_table_entry { TEVII_S480_1, TEVII_S480_2, X3M_SPC1400HD, + TEVII_S421, + TEVII_S632, + TERRATEC_CINERGY_S2_R2, }; static struct usb_device_id dw2102_table[] = { @@ -1465,6 +1475,9 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, + [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, + [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, + [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, { } }; @@ -1853,7 +1866,7 @@ static struct dvb_usb_device_properties su3000_properties = { }}, } }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "SU3000HD DVB-S USB2.0", { &dw2102_table[GENIATECH_SU3000], NULL }, @@ -1867,6 +1880,10 @@ static struct dvb_usb_device_properties su3000_properties = { { &dw2102_table[X3M_SPC1400HD], NULL }, { NULL }, }, + { "Terratec Cinergy S2 USB HD Rev.2", + { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, + { NULL }, + }, } }; -- GitLab From 563cd5cec48b1cad04397a13dec0a2ab666ea95c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 20 May 2012 18:45:15 -0300 Subject: [PATCH 2145/5711] [media] media: Use pr_info not homegrown pr_reg macro No need to duplicate normal kernel logging capabilities. Add pr_fmt and convert pr_reg to pr_info. Remove pr_reg macros. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/fintek-cir.c | 32 ++++---- drivers/media/rc/nuvoton-cir.c | 145 ++++++++++++++++----------------- 2 files changed, 90 insertions(+), 87 deletions(-) diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index 6aabf7ae3a31..ab30c64f8124 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -23,6 +23,8 @@ * USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -110,30 +112,32 @@ static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset) return val; } -#define pr_reg(text, ...) \ - printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) - /* dump current cir register contents */ static void cir_dump_regs(struct fintek_dev *fintek) { fintek_config_mode_enable(fintek); fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); - pr_reg(" * CR CIR BASE ADDR: 0x%x\n", - (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | + pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); + pr_info(" * CR CIR BASE ADDR: 0x%x\n", + (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); - pr_reg(" * CR CIR IRQ NUM: 0x%x\n", - fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); + pr_info(" * CR CIR IRQ NUM: 0x%x\n", + fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); fintek_config_mode_disable(fintek); - pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); - pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); - pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); - pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); - pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); - pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); + pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); + pr_info(" * STATUS: 0x%x\n", + fintek_cir_reg_read(fintek, CIR_STATUS)); + pr_info(" * CONTROL: 0x%x\n", + fintek_cir_reg_read(fintek, CIR_CONTROL)); + pr_info(" * RX_DATA: 0x%x\n", + fintek_cir_reg_read(fintek, CIR_RX_DATA)); + pr_info(" * TX_CONTROL: 0x%x\n", + fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); + pr_info(" * TX_DATA: 0x%x\n", + fintek_cir_reg_read(fintek, CIR_TX_DATA)); } /* detect hardware features */ diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index dc8a7dddccd4..699eef39128b 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -25,6 +25,8 @@ * USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -123,43 +125,40 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) return val; } -#define pr_reg(text, ...) \ - printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) - /* dump current cir register contents */ static void cir_dump_regs(struct nvt_dev *nvt) { nvt_efm_enable(nvt); nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); - pr_reg(" * CR CIR ACTIVE : 0x%x\n", - nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); - pr_reg(" * CR CIR BASE ADDR: 0x%x\n", - (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | + pr_info("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); + pr_info(" * CR CIR ACTIVE : 0x%x\n", + nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); + pr_info(" * CR CIR BASE ADDR: 0x%x\n", + (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); - pr_reg(" * CR CIR IRQ NUM: 0x%x\n", - nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); + pr_info(" * CR CIR IRQ NUM: 0x%x\n", + nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); nvt_efm_disable(nvt); - pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); - pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); - pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); - pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); - pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); - pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); - pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); - pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); - pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); - pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); - pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); - pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); - pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); - pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); - pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); - pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); - pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); + pr_info("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); + pr_info(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); + pr_info(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); + pr_info(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); + pr_info(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); + pr_info(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); + pr_info(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); + pr_info(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); + pr_info(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); + pr_info(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); + pr_info(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); + pr_info(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); + pr_info(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); + pr_info(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); + pr_info(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); + pr_info(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); + pr_info(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); } /* dump current cir wake register contents */ @@ -170,59 +169,59 @@ static void cir_wake_dump_regs(struct nvt_dev *nvt) nvt_efm_enable(nvt); nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - pr_reg("%s: Dump CIR WAKE logical device registers:\n", - NVT_DRIVER_NAME); - pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n", - nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); - pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n", - (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | + pr_info("%s: Dump CIR WAKE logical device registers:\n", + NVT_DRIVER_NAME); + pr_info(" * CR CIR WAKE ACTIVE : 0x%x\n", + nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); + pr_info(" * CR CIR WAKE BASE ADDR: 0x%x\n", + (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); - pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n", - nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); + pr_info(" * CR CIR WAKE IRQ NUM: 0x%x\n", + nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); nvt_efm_disable(nvt); - pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); - pr_reg(" * IRCON: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); - pr_reg(" * IRSTS: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); - pr_reg(" * IREN: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); - pr_reg(" * FIFO CMP DEEP: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); - pr_reg(" * FIFO CMP TOL: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); - pr_reg(" * FIFO COUNT: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); - pr_reg(" * SLCH: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); - pr_reg(" * SLCL: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); - pr_reg(" * FIFOCON: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); - pr_reg(" * SRXFSTS: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); - pr_reg(" * SAMPLE RX FIFO: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); - pr_reg(" * WR FIFO DATA: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); - pr_reg(" * RD FIFO ONLY: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); - pr_reg(" * RD FIFO ONLY IDX: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); - pr_reg(" * FIFO IGNORE: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); - pr_reg(" * IRFSM: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); + pr_info("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); + pr_info(" * IRCON: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); + pr_info(" * IRSTS: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); + pr_info(" * IREN: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); + pr_info(" * FIFO CMP DEEP: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); + pr_info(" * FIFO CMP TOL: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); + pr_info(" * FIFO COUNT: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); + pr_info(" * SLCH: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); + pr_info(" * SLCL: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); + pr_info(" * FIFOCON: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); + pr_info(" * SRXFSTS: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); + pr_info(" * SAMPLE RX FIFO: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); + pr_info(" * WR FIFO DATA: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); + pr_info(" * RD FIFO ONLY: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); + pr_info(" * RD FIFO ONLY IDX: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); + pr_info(" * FIFO IGNORE: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); + pr_info(" * IRFSM: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); - pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); - pr_reg("* Contents = "); + pr_info("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); + pr_info("* Contents ="); for (i = 0; i < fifo_len; i++) - printk(KERN_CONT "%02x ", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); - printk(KERN_CONT "\n"); + pr_cont(" %02x", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); + pr_cont("\n"); } /* detect hardware features */ -- GitLab From f2bb26b9b7652287719f08f080c09c2d7ddcf6b5 Mon Sep 17 00:00:00 2001 From: Bob Ross Date: Fri, 6 Jul 2012 11:34:47 -0700 Subject: [PATCH 2146/5711] Input: synaptics_usb - Remove TrackPoint name trailing whitespace The USB TrackPoint name string contains a space at the trailing end that can cause confusion/difficulty when creating udev rules. Example: "Synaptics Inc. Composite TouchPad / TrackPoint (Stick) " This patch removes the trailing space. Signed-off-by: Bob Ross Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index 3c5eaaa5d154..64cf34ea7604 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c @@ -364,7 +364,7 @@ static int synusb_probe(struct usb_interface *intf, le16_to_cpu(udev->descriptor.idProduct)); if (synusb->flags & SYNUSB_STICK) - strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); + strlcat(synusb->name, " (Stick)", sizeof(synusb->name)); usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); -- GitLab From 6680884a44207efe8ef6bc56b1c932cce2b89994 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Jul 2012 10:44:19 -0700 Subject: [PATCH 2147/5711] Input: ad7879 - add option to correct xy axis Sebastian Zenker reported that driver swaps x and y samples when the touchscreen leads are connected in accordance with the datasheet specification. Transposed axis can be typically corrected by touch screen calibration however this bug also negatively influences touch pressure measurements. Add an option to correct x and y axis. Signed-off-by: Michael Hennerich Reported-and-tested-by: Sebastian Zenker Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7879.c | 5 +++++ include/linux/spi/ad7879.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index e2482b40da51..e60709261951 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -118,6 +118,7 @@ struct ad7879 { unsigned int irq; bool disabled; /* P: input->mutex */ bool suspended; /* P: input->mutex */ + bool swap_xy; u16 conversion_data[AD7879_NR_SENSE]; char phys[32]; u8 first_conversion_delay; @@ -161,6 +162,9 @@ static int ad7879_report(struct ad7879 *ts) z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT; z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT; + if (ts->swap_xy) + swap(x, y); + /* * The samples processed here are already preprocessed by the AD7879. * The preprocessing function consists of a median and an averaging @@ -520,6 +524,7 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, ts->dev = dev; ts->input = input_dev; ts->irq = irq; + ts->swap_xy = pdata->swap_xy; setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); diff --git a/include/linux/spi/ad7879.h b/include/linux/spi/ad7879.h index 6334cee1a3be..58368be0b4c0 100644 --- a/include/linux/spi/ad7879.h +++ b/include/linux/spi/ad7879.h @@ -12,6 +12,8 @@ struct ad7879_platform_data { u16 y_min, y_max; u16 pressure_min, pressure_max; + bool swap_xy; /* swap x and y axes */ + /* [0..255] 0=OFF Starts at 1=550us and goes * all the way to 9.440ms in steps of 35us. */ -- GitLab From a1e636e6d35944a2b970481b78a621774276acfd Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 6 Jul 2012 11:26:05 -0700 Subject: [PATCH 2148/5711] Input: imx_keypad - use clk_prepare_enable/clk_disable_unprepare() Adapt clock handling to the new i.mx clock framework and fix the following warning: input: imx-keypad as /devices/platform/imx-keypad/input/input0 ------------[ cut here ]------------ WARNING: at drivers/clk/clk.c:511 __clk_enable+0x98/0xa8() Modules linked in: [] (unwind_backtrace+0x0/0xf4) from [] (warn_slowpath_commo) [] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_) [] (warn_slowpath_null+0x1c/0x24) from [] (__clk_enable+0x9) [] (__clk_enable+0x98/0xa8) from [] (clk_enable+0x24/0x5c) [] (clk_enable+0x24/0x5c) from [] (imx_keypad_open+0x28/0xc) [] (imx_keypad_open+0x28/0xc8) from [] (input_open_device+0) [] (input_open_device+0x78/0xa8) from [] (kbd_connect+0x60/) [] (kbd_connect+0x60/0x80) from [] (input_attach_handler+0x) [] (input_attach_handler+0x220/0x258) from [] (input_regist) [] (input_register_device+0x31c/0x390) from [] (imx_keypad_) [] (imx_keypad_probe+0x2e4/0x3b8) from [] (platform_drv_pro) [] (platform_drv_probe+0x18/0x1c) from [] (driver_probe_dev) [] (driver_probe_device+0x84/0x210) from [] (__driver_attac) [] (__driver_attach+0x8c/0x90) from [] (bus_for_each_dev+0x) [] (bus_for_each_dev+0x68/0x90) from [] (bus_add_driver+0xa) [] (bus_add_driver+0xa4/0x23c) from [] (driver_register+0x7) [] (driver_register+0x78/0x12c) from [] (do_one_initcall+0x) [] (do_one_initcall+0x34/0x188) from [] (kernel_init+0xe4/0) [] (kernel_init+0xe4/0x1a8) from [] (kernel_thread_exit+0x0) ---[ end trace 1d550e891d03d7ce ]--- Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_keypad.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 6ee7421e2321..9d57945db53d 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -378,7 +378,7 @@ static void imx_keypad_close(struct input_dev *dev) imx_keypad_inhibit(keypad); /* Disable clock unit */ - clk_disable(keypad->clk); + clk_disable_unprepare(keypad->clk); } static int imx_keypad_open(struct input_dev *dev) @@ -391,7 +391,7 @@ static int imx_keypad_open(struct input_dev *dev) keypad->enabled = true; /* Enable the kpp clock */ - clk_enable(keypad->clk); + clk_prepare_enable(keypad->clk); imx_keypad_config(keypad); /* Sanity control, not all the rows must be actived now. */ @@ -581,7 +581,7 @@ static int imx_kbd_suspend(struct device *dev) mutex_lock(&input_dev->mutex); if (input_dev->users) - clk_disable(kbd->clk); + clk_disable_unprepare(kbd->clk); mutex_unlock(&input_dev->mutex); @@ -603,7 +603,7 @@ static int imx_kbd_resume(struct device *dev) mutex_lock(&input_dev->mutex); if (input_dev->users) - clk_enable(kbd->clk); + clk_prepare_enable(kbd->clk); mutex_unlock(&input_dev->mutex); -- GitLab From a40ec72d540553fc0e1d1fea94c1d7629b7f35f4 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 6 Jul 2012 11:26:37 -0700 Subject: [PATCH 2149/5711] Input: imx_keypad - adapt the new kpp clock name With the new i.mx clock framework we should pass NULL as the keypad clock name. Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 9d57945db53d..4830615ed2ec 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -467,7 +467,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) goto failed_free_priv; } - keypad->clk = clk_get(&pdev->dev, "kpp"); + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get keypad clock\n"); error = PTR_ERR(keypad->clk); -- GitLab From 333fbe8409dfabd3d3581af5cdbd30f666857437 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 6 Jul 2012 11:31:14 -0700 Subject: [PATCH 2150/5711] Input: imx_keypad - check error returned by clk_prepare_enable() Check error returned by clk_prepare_enable(). Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_keypad.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 4830615ed2ec..ff4c0a87a25f 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -384,14 +384,18 @@ static void imx_keypad_close(struct input_dev *dev) static int imx_keypad_open(struct input_dev *dev) { struct imx_keypad *keypad = input_get_drvdata(dev); + int error; dev_dbg(&dev->dev, ">%s\n", __func__); + /* Enable the kpp clock */ + error = clk_prepare_enable(keypad->clk); + if (error) + return error; + /* We became active from now */ keypad->enabled = true; - /* Enable the kpp clock */ - clk_prepare_enable(keypad->clk); imx_keypad_config(keypad); /* Sanity control, not all the rows must be actived now. */ @@ -596,18 +600,23 @@ static int imx_kbd_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; + int ret = 0; if (device_may_wakeup(&pdev->dev)) disable_irq_wake(kbd->irq); mutex_lock(&input_dev->mutex); - if (input_dev->users) - clk_prepare_enable(kbd->clk); + if (input_dev->users) { + ret = clk_prepare_enable(kbd->clk); + if (ret) + goto err_clk; + } +err_clk: mutex_unlock(&input_dev->mutex); - return 0; + return ret; } #endif -- GitLab From b7e386360922a15f943b2fbe8d77a19bb86f2e6f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Jul 2012 00:19:20 -0300 Subject: [PATCH 2151/5711] media: Revert "[media] Terratec Cinergy S2 USB HD Rev.2" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 03228792df67a6ae231960151b8a5c87e17a73e2. drivers/media/dvb/dvb-usb/dw2102.c:1478:18: error: ‘USB_PID_TEVII_S421’ undeclared here (not in a function) drivers/media/dvb/dvb-usb/dw2102.c:1479:18: error: ‘USB_PID_TEVII_S632’ undeclared here (not in a function) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 7c37a566c55d..9382895b1b88 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -1178,13 +1178,6 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d) u8 obuf[3] = { 0xe, 0x80, 0 }; u8 ibuf[] = { 0 }; - if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) - err("command 0x0e transfer failed."); - - obuf[0] = 0xe; - obuf[1] = 0x02; - obuf[2] = 1; - if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) err("command 0x0e transfer failed."); @@ -1454,9 +1447,6 @@ enum dw2102_table_entry { TEVII_S480_1, TEVII_S480_2, X3M_SPC1400HD, - TEVII_S421, - TEVII_S632, - TERRATEC_CINERGY_S2_R2, }; static struct usb_device_id dw2102_table[] = { @@ -1475,9 +1465,6 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, - [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, - [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, { } }; @@ -1866,7 +1853,7 @@ static struct dvb_usb_device_properties su3000_properties = { }}, } }, - .num_device_descs = 4, + .num_device_descs = 3, .devices = { { "SU3000HD DVB-S USB2.0", { &dw2102_table[GENIATECH_SU3000], NULL }, @@ -1880,10 +1867,6 @@ static struct dvb_usb_device_properties su3000_properties = { { &dw2102_table[X3M_SPC1400HD], NULL }, { NULL }, }, - { "Terratec Cinergy S2 USB HD Rev.2", - { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, - { NULL }, - }, } }; -- GitLab From c866ffc72541296b8d31c109fbdb69643d2d18a6 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 1 Jul 2012 00:47:41 +0200 Subject: [PATCH 2152/5711] iio staging: missing newline in printf Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/Documentation/iio_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 5244fa0dfd2f..cf32ae099cd6 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -453,7 +453,7 @@ inline int find_type_by_name(const char *name, const char *type) dp = opendir(iio_dir); if (dp == NULL) { - printf("No industrialio devices available"); + printf("No industrialio devices available\n"); return -ENODEV; } -- GitLab From 3bdff937827da04b487f0a0ac6e1f3a9a1296878 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 1 Jul 2012 00:47:43 +0200 Subject: [PATCH 2153/5711] iio: cleanup buffer.h comments Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- include/linux/iio/buffer.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index ad4fb1af0f7d..2a2b6b4d8d05 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -85,7 +85,7 @@ struct iio_buffer { /** * iio_buffer_init() - Initialize the buffer structure - * @buffer: buffer to be initialized + * @buffer: buffer to be initialized **/ void iio_buffer_init(struct iio_buffer *buffer); @@ -107,8 +107,9 @@ int iio_scan_mask_query(struct iio_dev *indio_dev, /** * iio_scan_mask_set() - set particular bit in the scan mask - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. + * @indio_dev IIO device structure + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. **/ int iio_scan_mask_set(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit); @@ -116,8 +117,8 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, /** * iio_push_to_buffer() - push to a registered buffer. * @buffer: IIO buffer structure for device - * @scan: Full scan. - * @timestamp: + * @data: the data to push to the buffer + * @timestamp: timestamp to associate with the data */ int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, s64 timestamp); @@ -126,7 +127,9 @@ int iio_update_demux(struct iio_dev *indio_dev); /** * iio_buffer_register() - register the buffer with IIO core - * @indio_dev: device with the buffer to be registered + * @indio_dev: device with the buffer to be registered + * @channels: the channel descriptions used to construct buffer + * @num_channels: the number of channels **/ int iio_buffer_register(struct iio_dev *indio_dev, const struct iio_chan_spec *channels, @@ -134,7 +137,7 @@ int iio_buffer_register(struct iio_dev *indio_dev, /** * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered + * @indio_dev: the device with the buffer to be unregistered **/ void iio_buffer_unregister(struct iio_dev *indio_dev); -- GitLab From 034bd7b5d926816285deb71c41a230b912524f8b Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Mon, 2 Jul 2012 23:43:47 +0200 Subject: [PATCH 2154/5711] iio: fix spelling of detach in static func Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ec653fb51d0b..2ef36d15ccc5 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -234,7 +234,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, return ret; } -static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, +static int iio_trigger_detach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf) { int ret = 0; @@ -502,7 +502,7 @@ EXPORT_SYMBOL(iio_triggered_buffer_postenable); int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) { - return iio_trigger_dettach_poll_func(indio_dev->trig, + return iio_trigger_detach_poll_func(indio_dev->trig, indio_dev->pollfunc); } EXPORT_SYMBOL(iio_triggered_buffer_predisable); -- GitLab From 5369f55021feb27a1481267e7afefe14128d669f Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Sat, 7 Jul 2012 23:04:40 +0200 Subject: [PATCH 2155/5711] kbuild: Print errors to stderr ... at least in the top-level Makefile and scripts/link-vmlinux.sh. There are some more instances of the 'echo ; exit 1' pattern in some arch Makefiles and kconfig. Reported-by: Linus Torvalds Signed-off-by: Michal Marek --- Makefile | 24 ++++++++++++------------ scripts/link-vmlinux.sh | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 0d718ede9ea5..d7d79491fe26 100644 --- a/Makefile +++ b/Makefile @@ -535,11 +535,11 @@ PHONY += include/config/auto.conf include/config/auto.conf: $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \ - echo; \ - echo " ERROR: Kernel configuration is invalid."; \ - echo " include/generated/autoconf.h or $@ are missing.";\ - echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ - echo; \ + echo >&2; \ + echo >&2 " ERROR: Kernel configuration is invalid."; \ + echo >&2 " include/generated/autoconf.h or $@ are missing.";\ + echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ + echo >&2 ; \ /bin/false) endif # KBUILD_EXTMOD @@ -796,8 +796,8 @@ prepare3: include/config/kernel.release ifneq ($(KBUILD_SRC),) @$(kecho) ' Using $(srctree) as source for kernel' $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ - echo " $(srctree) is not clean, please run 'make mrproper'"; \ - echo " in the '$(srctree)' directory.";\ + echo >&2 " $(srctree) is not clean, please run 'make mrproper'"; \ + echo >&2 " in the '$(srctree)' directory.";\ /bin/false; \ fi; endif @@ -971,11 +971,11 @@ else # CONFIG_MODULES # --------------------------------------------------------------------------- modules modules_install: FORCE - @echo - @echo "The present kernel configuration has modules disabled." - @echo "Type 'make config' and enable loadable module support." - @echo "Then build a kernel with module support enabled." - @echo + @echo >&2 + @echo >&2 "The present kernel configuration has modules disabled." + @echo >&2 "Type 'make config' and enable loadable module support." + @echo >&2 "Then build a kernel with module support enabled." + @echo >&2 @exit 1 endif # CONFIG_MODULES diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index cd9c6c6bb4c9..4629038c9e5a 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -210,8 +210,8 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then mksysmap ${kallsyms_vmlinux} .tmp_System.map if ! cmp -s System.map .tmp_System.map; then - echo Inconsistent kallsyms data - echo echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround + echo >&2 Inconsistent kallsyms data + echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround cleanup exit 1 fi -- GitLab From d1e09ebf426ff34b4b6bbd6212b820edeb992bd4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sat, 7 Jul 2012 15:13:47 -0700 Subject: [PATCH 2156/5711] RDMA/ocrdma: Fix assignment of max_srq_sge in device query We want to set attr->max_srq_sge to dev->attr.max_srq_sge, not to itself. This was detected by Coverity (CID 709210). Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 2e2e7aecc990..b2f9784beb4a 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -97,7 +97,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr) min(dev->attr.max_ord_per_qp, dev->attr.max_ird_per_qp); attr->max_qp_init_rd_atom = dev->attr.max_ord_per_qp; attr->max_srq = (dev->attr.max_qp - 1); - attr->max_srq_sge = attr->max_srq_sge; + attr->max_srq_sge = dev->attr.max_srq_sge; attr->max_srq_wr = dev->attr.max_rqe; attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay; attr->max_fast_reg_page_list_len = 0; -- GitLab From 8830cb88dd6d60c3bb4cb46d8a855628e4875b18 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 7 Jul 2012 16:40:16 -0700 Subject: [PATCH 2157/5711] Input: wacom_i2c - fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently GCC can't figure out that we bail if we fail to query device and will not try to use 'features': drivers/input/touchscreen/wacom_i2c.c: In function ‘wacom_i2c_probe’: drivers/input/touchscreen/wacom_i2c.c:177:20: warning: ‘features.fw_version’ may be used uninitialized in this function [-Wmaybe-uninitialized] Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index 35572575d34a..0c01657132fd 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -149,7 +149,7 @@ static int __devinit wacom_i2c_probe(struct i2c_client *client, { struct wacom_i2c *wac_i2c; struct input_dev *input; - struct wacom_features features; + struct wacom_features features = { 0 }; int error; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { -- GitLab From 5bdea83565e8b290410521d0dd64b7d3cc41603b Mon Sep 17 00:00:00 2001 From: Vipul Kumar Samar Date: Sat, 7 Jul 2012 18:00:10 -0700 Subject: [PATCH 2158/5711] Input: spear-keyboard - fix disable device_init_wakeup in remove This patch is to disable device wakeup while removing keyboard. Signed-off-by: Vipul Kumar Samar Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/spear-keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 6f287f7e1538..45dd02cbcaa0 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -302,7 +302,7 @@ static int __devexit spear_kbd_remove(struct platform_device *pdev) release_mem_region(kbd->res->start, resource_size(kbd->res)); kfree(kbd); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); return 0; -- GitLab From e99191f0391973326dd4de5cee5a72bf5aeb7040 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sat, 7 Jul 2012 18:00:36 -0700 Subject: [PATCH 2159/5711] Input: spear_keyboard - use correct io accessors All SPEAr keyboard registers are 32 bit wide and are word aligned. This patch aligns all io access to be word size using relaxed version of readl/writel. Signed-off-by: Shiraz Hashim Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/spear-keyboard.c | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 45dd02cbcaa0..10dda9f8e706 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -27,9 +27,9 @@ #include /* Keyboard Registers */ -#define MODE_REG 0x00 /* 16 bit reg */ -#define STATUS_REG 0x0C /* 2 bit reg */ -#define DATA_REG 0x10 /* 8 bit reg */ +#define MODE_REG 0x00 +#define STATUS_REG 0x0C +#define DATA_REG 0x10 #define INTR_MASK 0x54 /* Register Values */ @@ -72,9 +72,9 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) struct spear_kbd *kbd = dev_id; struct input_dev *input = kbd->input; unsigned int key; - u8 sts, val; + u32 sts, val; - sts = readb(kbd->io_base + STATUS_REG); + sts = readl_relaxed(kbd->io_base + STATUS_REG); if (!(sts & DATA_AVAIL)) return IRQ_NONE; @@ -84,7 +84,7 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) } /* following reads active (row, col) pair */ - val = readb(kbd->io_base + DATA_REG); + val = readl_relaxed(kbd->io_base + DATA_REG); key = kbd->keycodes[val]; input_event(input, EV_MSC, MSC_SCAN, val); @@ -94,7 +94,7 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) kbd->last_key = key; /* clear interrupt */ - writeb(0, kbd->io_base + STATUS_REG); + writel_relaxed(0, kbd->io_base + STATUS_REG); return IRQ_HANDLED; } @@ -103,7 +103,7 @@ static int spear_kbd_open(struct input_dev *dev) { struct spear_kbd *kbd = input_get_drvdata(dev); int error; - u16 val; + u32 val; kbd->last_key = KEY_RESERVED; @@ -114,13 +114,13 @@ static int spear_kbd_open(struct input_dev *dev) /* program keyboard */ val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK | (kbd->mode << KEY_MATRIX_SHIFT); - writew(val, kbd->io_base + MODE_REG); - writeb(1, kbd->io_base + STATUS_REG); + writel_relaxed(val, kbd->io_base + MODE_REG); + writel_relaxed(1, kbd->io_base + STATUS_REG); /* start key scan */ - val = readw(kbd->io_base + MODE_REG); + val = readl_relaxed(kbd->io_base + MODE_REG); val |= START_SCAN; - writew(val, kbd->io_base + MODE_REG); + writel_relaxed(val, kbd->io_base + MODE_REG); return 0; } @@ -128,12 +128,12 @@ static int spear_kbd_open(struct input_dev *dev) static void spear_kbd_close(struct input_dev *dev) { struct spear_kbd *kbd = input_get_drvdata(dev); - u16 val; + u32 val; /* stop key scan */ - val = readw(kbd->io_base + MODE_REG); + val = readl_relaxed(kbd->io_base + MODE_REG); val &= ~START_SCAN; - writew(val, kbd->io_base + MODE_REG); + writel_relaxed(val, kbd->io_base + MODE_REG); clk_disable(kbd->clk); -- GitLab From f6f2efa35f6b76034e5a31a075218feaa10f1812 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sat, 7 Jul 2012 18:00:54 -0700 Subject: [PATCH 2160/5711] Input: spear_keyboard - rename bit definitions to reflect register Rename bit definition macros to reflect keyboard registers clearly thus being more readable. Signed-off-by: Shiraz Hashim Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/spear-keyboard.c | 52 +++++++++++++------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 10dda9f8e706..a51cdc75466a 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -27,7 +27,7 @@ #include /* Keyboard Registers */ -#define MODE_REG 0x00 +#define MODE_CTL_REG 0x00 #define STATUS_REG 0x0C #define DATA_REG 0x10 #define INTR_MASK 0x54 @@ -38,22 +38,23 @@ * control register as 1010010(82MHZ) */ #define PCLK_FREQ_MSK 0xA400 /* 82 MHz */ -#define START_SCAN 0x0100 -#define SCAN_RATE_10 0x0000 -#define SCAN_RATE_20 0x0004 -#define SCAN_RATE_40 0x0008 -#define SCAN_RATE_80 0x000C -#define MODE_KEYBOARD 0x0002 -#define DATA_AVAIL 0x2 - -#define KEY_MASK 0xFF000000 -#define KEY_VALUE 0x00FFFFFF -#define ROW_MASK 0xF0 -#define COLUMN_MASK 0x0F #define NUM_ROWS 16 #define NUM_COLS 16 -#define KEY_MATRIX_SHIFT 6 +#define MODE_CTL_KEYBOARD (0x2 << 0) +#define MODE_CTL_SCAN_RATE_10 (0x0 << 2) +#define MODE_CTL_SCAN_RATE_20 (0x1 << 2) +#define MODE_CTL_SCAN_RATE_40 (0x2 << 2) +#define MODE_CTL_SCAN_RATE_80 (0x3 << 2) +#define MODE_CTL_KEYNUM_SHIFT 6 +#define MODE_CTL_START_SCAN (0x1 << 8) + +#define STATUS_DATA_AVAIL (0x1 << 1) + +#define DATA_ROW_MASK 0xF0 +#define DATA_COLUMN_MASK 0x0F + +#define ROW_SHIFT 4 struct spear_kbd { struct input_dev *input; @@ -75,7 +76,7 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) u32 sts, val; sts = readl_relaxed(kbd->io_base + STATUS_REG); - if (!(sts & DATA_AVAIL)) + if (!(sts & STATUS_DATA_AVAIL)) return IRQ_NONE; if (kbd->last_key != KEY_RESERVED) { @@ -84,7 +85,8 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) } /* following reads active (row, col) pair */ - val = readl_relaxed(kbd->io_base + DATA_REG); + val = readl_relaxed(kbd->io_base + DATA_REG) & + (DATA_ROW_MASK | DATA_COLUMN_MASK); key = kbd->keycodes[val]; input_event(input, EV_MSC, MSC_SCAN, val); @@ -112,15 +114,15 @@ static int spear_kbd_open(struct input_dev *dev) return error; /* program keyboard */ - val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK | - (kbd->mode << KEY_MATRIX_SHIFT); - writel_relaxed(val, kbd->io_base + MODE_REG); + val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | PCLK_FREQ_MSK | + (kbd->mode << MODE_CTL_KEYNUM_SHIFT); + writel_relaxed(val, kbd->io_base + MODE_CTL_REG); writel_relaxed(1, kbd->io_base + STATUS_REG); /* start key scan */ - val = readl_relaxed(kbd->io_base + MODE_REG); - val |= START_SCAN; - writel_relaxed(val, kbd->io_base + MODE_REG); + val = readl_relaxed(kbd->io_base + MODE_CTL_REG); + val |= MODE_CTL_START_SCAN; + writel_relaxed(val, kbd->io_base + MODE_CTL_REG); return 0; } @@ -131,9 +133,9 @@ static void spear_kbd_close(struct input_dev *dev) u32 val; /* stop key scan */ - val = readl_relaxed(kbd->io_base + MODE_REG); - val &= ~START_SCAN; - writel_relaxed(val, kbd->io_base + MODE_REG); + val = readl_relaxed(kbd->io_base + MODE_CTL_REG); + val &= ~MODE_CTL_START_SCAN; + writel_relaxed(val, kbd->io_base + MODE_CTL_REG); clk_disable(kbd->clk); -- GitLab From 98e4d4d6bcf130cbf5a684c4f98c345f13e2f28c Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sat, 7 Jul 2012 18:01:07 -0700 Subject: [PATCH 2161/5711] Input: spear_keyboard - generalize keyboard frequency configuration Current implementation hard coded keyboard frequency configuration assuming input clock as fixed APB (83 MHz). Generalize the configuration using clock framework APIs. Signed-off-by: Shiraz Hashim Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/spear-keyboard.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index a51cdc75466a..c499387d8735 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -33,13 +33,10 @@ #define INTR_MASK 0x54 /* Register Values */ -/* - * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode - * control register as 1010010(82MHZ) - */ -#define PCLK_FREQ_MSK 0xA400 /* 82 MHz */ #define NUM_ROWS 16 #define NUM_COLS 16 +#define MODE_CTL_PCLK_FREQ_SHIFT 9 +#define MODE_CTL_PCLK_FREQ_MSK 0x7F #define MODE_CTL_KEYBOARD (0x2 << 0) #define MODE_CTL_SCAN_RATE_10 (0x0 << 2) @@ -113,8 +110,12 @@ static int spear_kbd_open(struct input_dev *dev) if (error) return error; + /* keyboard rate to be programmed is input clock (in MHz) - 1 */ + val = clk_get_rate(kbd->clk) / 1000000 - 1; + val = (val & MODE_CTL_PCLK_FREQ_MSK) << MODE_CTL_PCLK_FREQ_SHIFT; + /* program keyboard */ - val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | PCLK_FREQ_MSK | + val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | val | (kbd->mode << MODE_CTL_KEYNUM_SHIFT); writel_relaxed(val, kbd->io_base + MODE_CTL_REG); writel_relaxed(1, kbd->io_base + STATUS_REG); -- GitLab From c6bd9d465500effa710634876fa9e35581da522d Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Sat, 7 Jul 2012 18:08:51 -0700 Subject: [PATCH 2162/5711] Input: synaptics - print firmware ID and board number at init Read the Firmware ID and Board Number from a synaptics device at init and display them in the system log. Device behavior is very board and firmware dependent. It may prove useful for users to include this information when providing bug reports or other feedback. Signed-off-by: Daniel Kurtz Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 38 +++++++++++++++++++++++++++++++-- drivers/input/mouse/synaptics.h | 3 +++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index c703d53be3a0..d5b390f75c9a 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -138,6 +138,35 @@ static int synaptics_model_id(struct psmouse *psmouse) return 0; } +/* + * Read the board id from the touchpad + * The board id is encoded in the "QUERY MODES" response + */ +static int synaptics_board_id(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + unsigned char bid[3]; + + if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) + return -1; + priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; + return 0; +} + +/* + * Read the firmware id from the touchpad + */ +static int synaptics_firmware_id(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + unsigned char fwid[3]; + + if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid)) + return -1; + priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2]; + return 0; +} + /* * Read the capability-bits from the touchpad * see also the SYN_CAP_* macros @@ -261,6 +290,10 @@ static int synaptics_query_hardware(struct psmouse *psmouse) return -1; if (synaptics_model_id(psmouse)) return -1; + if (synaptics_firmware_id(psmouse)) + return -1; + if (synaptics_board_id(psmouse)) + return -1; if (synaptics_capability(psmouse)) return -1; if (synaptics_resolution(psmouse)) @@ -1435,11 +1468,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; psmouse_info(psmouse, - "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", + "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n", SYN_ID_MODEL(priv->identity), SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), priv->model_id, - priv->capabilities, priv->ext_cap, priv->ext_cap_0c); + priv->capabilities, priv->ext_cap, priv->ext_cap_0c, + priv->board_id, priv->firmware_id); set_input_params(psmouse->dev, priv); diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index fd26ccca13d7..e594af0b264b 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -18,6 +18,7 @@ #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_EXT_CAPAB 0x09 +#define SYN_QUE_FIRMWARE_ID 0x0a #define SYN_QUE_EXT_CAPAB_0C 0x0c #define SYN_QUE_EXT_MAX_COORDS 0x0d #define SYN_QUE_EXT_MIN_COORDS 0x0f @@ -148,6 +149,8 @@ struct synaptics_hw_state { struct synaptics_data { /* Data read from the touchpad */ unsigned long int model_id; /* Model-ID */ + unsigned long int firmware_id; /* Firmware-ID */ + unsigned long int board_id; /* Board-ID */ unsigned long int capabilities; /* Capabilities */ unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ -- GitLab From 9a932145f2d57bad1092ba006dee9065adc5eb39 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 7 Jul 2012 18:17:54 -0700 Subject: [PATCH 2163/5711] Input: ff-memless - fix a couple min_t() casts envelope->attack_level is a u16 type. We're trying to clamp it here so it's between 0 and 0x7fff. Unfortunately, the cast to __s16 turns all the values larger than 0x7fff into negative numbers and min_t() thinks they are less than 0x7fff. envelope_level is an int so now we've got negative values stored there. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 5f558851d646..b107922514fb 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -176,7 +176,7 @@ static int apply_envelope(struct ml_effect_state *state, int value, value, envelope->attack_level); time_from_level = jiffies_to_msecs(now - state->play_at); time_of_envelope = envelope->attack_length; - envelope_level = min_t(__s16, envelope->attack_level, 0x7fff); + envelope_level = min_t(u16, envelope->attack_level, 0x7fff); } else if (envelope->fade_length && effect->replay.length && time_after(now, @@ -184,7 +184,7 @@ static int apply_envelope(struct ml_effect_state *state, int value, time_before(now, state->stop_at)) { time_from_level = jiffies_to_msecs(state->stop_at - now); time_of_envelope = envelope->fade_length; - envelope_level = min_t(__s16, envelope->fade_level, 0x7fff); + envelope_level = min_t(u16, envelope->fade_level, 0x7fff); } else return value; -- GitLab From da4db94080f0c54929a031f37e550001d0068930 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 1 Jul 2012 12:20:13 +0200 Subject: [PATCH 2164/5711] iio staging: add recently added modifiers to iio_event_monitor maybe iio_modifier_names and iio_chan_type_name_spec should be exported from industrialio-core instead? Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- .../staging/iio/Documentation/iio_event_monitor.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 4326e9e764c9..3a9b00087403 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -68,6 +68,12 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_Z] = "z", [IIO_MOD_LIGHT_BOTH] = "both", [IIO_MOD_LIGHT_IR] = "ir", + [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", + [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", + [IIO_MOD_LIGHT_CLEAR] = "clear", + [IIO_MOD_LIGHT_RED] = "red", + [IIO_MOD_LIGHT_GREEN] = "green", + [IIO_MOD_LIGHT_BLUE] = "blue", }; static bool event_is_known(struct iio_event_data *event) @@ -106,6 +112,12 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_Z: case IIO_MOD_LIGHT_BOTH: case IIO_MOD_LIGHT_IR: + case IIO_MOD_ROOT_SUM_SQUARED_X_Y: + case IIO_MOD_SUM_SQUARED_X_Y_Z: + case IIO_MOD_LIGHT_CLEAR: + case IIO_MOD_LIGHT_RED: + case IIO_MOD_LIGHT_GREEN: + case IIO_MOD_LIGHT_BLUE: break; default: return false; -- GitLab From cf09fe9c873ca0f4e2ca83e7bea03e2599a62d58 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 1 Jul 2012 12:20:11 +0200 Subject: [PATCH 2165/5711] iio: kernel version typo in sysfs-bus-iio Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index a3774a71ec26..2f06d40fe07d 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -275,7 +275,7 @@ What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available What: /sys/.../iio:deviceX/out_voltageX_scale_available What: /sys/.../iio:deviceX/out_altvoltageX_scale_available What: /sys/.../iio:deviceX/in_capacitance_scale_available -KernelVersion: 2.635 +KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: If a discrete set of scale values is available, they -- GitLab From 6d459aa011cb087ed1f5c17836b032fcc670e306 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 5 Jul 2012 10:57:06 +0200 Subject: [PATCH 2166/5711] iio:trigger: Register sysfs file statically The name sysfs attribute is the same for all triggers, so there is no need to register them dynamically at runtime. Create a attribute group for it and set it up for the bus attribute group. This also avoids a possible race condition where the uevent for the device is sent before the name sysfs attribute has been added. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 38 ++++++++++-------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 2ef36d15ccc5..4fe0ead84213 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -51,25 +51,19 @@ static ssize_t iio_trigger_read_name(struct device *dev, static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); -/** - * iio_trigger_register_sysfs() - create a device for this trigger - * @trig_info: the trigger - * - * Also adds any control attribute registered by the trigger driver - **/ -static int iio_trigger_register_sysfs(struct iio_trigger *trig_info) -{ - return sysfs_add_file_to_group(&trig_info->dev.kobj, - &dev_attr_name.attr, - NULL); -} +static struct attribute *iio_trig_dev_attrs[] = { + &dev_attr_name.attr, + NULL, +}; -static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info) -{ - sysfs_remove_file_from_group(&trig_info->dev.kobj, - &dev_attr_name.attr, - NULL); -} +static struct attribute_group iio_trig_attr_group = { + .attrs = iio_trig_dev_attrs, +}; + +static const struct attribute_group *iio_trig_attr_groups[] = { + &iio_trig_attr_group, + NULL +}; int iio_trigger_register(struct iio_trigger *trig_info) { @@ -88,10 +82,6 @@ int iio_trigger_register(struct iio_trigger *trig_info) if (ret) goto error_unregister_id; - ret = iio_trigger_register_sysfs(trig_info); - if (ret) - goto error_device_del; - /* Add to list of available triggers held by the IIO core */ mutex_lock(&iio_trigger_list_lock); list_add_tail(&trig_info->list, &iio_trigger_list); @@ -99,8 +89,6 @@ int iio_trigger_register(struct iio_trigger *trig_info) return 0; -error_device_del: - device_del(&trig_info->dev); error_unregister_id: ida_simple_remove(&iio_trigger_ida, trig_info->id); error_ret: @@ -114,7 +102,6 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) list_del(&trig_info->list); mutex_unlock(&iio_trigger_list_lock); - iio_trigger_unregister_sysfs(trig_info); ida_simple_remove(&iio_trigger_ida, trig_info->id); /* Possible issue in here */ device_unregister(&trig_info->dev); @@ -406,6 +393,7 @@ static void iio_trig_release(struct device *device) static struct device_type iio_trig_type = { .release = iio_trig_release, + .groups = iio_trig_attr_groups, }; static void iio_trig_subirqmask(struct irq_data *d) -- GitLab From d297b9bdad044a732223b44c19e8223d93fd3aa0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 3 Jul 2012 11:21:28 +0200 Subject: [PATCH 2167/5711] staging iio adt7410: make 16bit mode default In 13bit mode the lower three bits of the adc value contain flags. The driver does not use these flags at all, so make 16bit mode the default. Signed-off-by: Sascha Hauer Acked-by: Sonic Zhang Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/adt7410.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index 917b6921e24d..1a4197013e9b 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -761,13 +761,15 @@ static int __devinit adt7410_probe(struct i2c_client *client, goto error_unreg_ct_irq; } - if (client->irq && adt7410_platform_data[0]) { + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; + } - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } + chip->config |= ADT7410_RESOLUTION; + + if (client->irq && adt7410_platform_data[0]) { /* set irq polarity low level */ chip->config &= ~ADT7410_CT_POLARITY; @@ -776,12 +778,12 @@ static int __devinit adt7410_probe(struct i2c_client *client, chip->config |= ADT7410_INT_POLARITY; else chip->config &= ~ADT7410_INT_POLARITY; + } - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; } ret = iio_device_register(indio_dev); if (ret) -- GitLab From c732a24c5a9392cf3738f5957e0d97d37c09e6e1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 3 Jul 2012 11:27:53 +0200 Subject: [PATCH 2168/5711] staging:iio:adt7410: use local platformdata if none is specified The adt7410 expects information about an irq in platform_data. The driver can work without an irq, so make platform_data optional by specifying a dummy platform_data if the device has none. Signed-off-by: Sascha Hauer Acked-by: Sonic Zhang Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/adt7410.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index 1a4197013e9b..42fe2c8c49f3 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -720,6 +720,7 @@ static int __devinit adt7410_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret = 0; unsigned long *adt7410_platform_data = client->dev.platform_data; + unsigned long local_pdata[] = {0, 0}; indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { @@ -737,6 +738,9 @@ static int __devinit adt7410_probe(struct i2c_client *client, indio_dev->info = &adt7410_info; indio_dev->modes = INDIO_DIRECT_MODE; + if (!adt7410_platform_data) + adt7410_platform_data = local_pdata; + /* CT critcal temperature event. line 0 */ if (client->irq) { ret = request_threaded_irq(client->irq, -- GitLab From f14cf2fb8d30f9dad2e532a4e3f1ed4ca82fbc3b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 20 Apr 2012 17:08:02 +0200 Subject: [PATCH 2169/5711] devicetree: bindings: gpio-i2c belongs to i2c not gpio gpio-i2c describes an I2C controller (using gpios for data and clock), so it must be described in i2c, not gpio. Signed-off-by: Wolfram Sang Acked-by: Rob Herring --- .../devicetree/bindings/{gpio/gpio_i2c.txt => i2c/gpio-i2c.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/{gpio/gpio_i2c.txt => i2c/gpio-i2c.txt} (100%) diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt b/Documentation/devicetree/bindings/i2c/gpio-i2c.txt similarity index 100% rename from Documentation/devicetree/bindings/gpio/gpio_i2c.txt rename to Documentation/devicetree/bindings/i2c/gpio-i2c.txt -- GitLab From 3dae3efb123f8b21df57f426c9c72d6ebcd83f8d Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:13 +0530 Subject: [PATCH 2170/5711] I2C: OMAP: make omap_i2c_unidle/idle functions depend on CONFIG_PM_RUNTIME The functions omap_i2c_unidle/idle are called from omap_i2c_runtime_resume and omap_i2c_runtime_suspend which is compiled for CONFIG_PM_RUNTIME. This patch removes the omap_i2c_unidle/idle functions and folds them into the runtime callbacks. This fixes the below warn when CONFIG_PM_RUNTIME is not defined CC arch/arm/mach-omap2/board-ti8168evm.o drivers/i2c/busses/i2c-omap.c:272: warning: 'omap_i2c_unidle' defined but not used drivers/i2c/busses/i2c-omap.c:293: warning: 'omap_i2c_idle' defined but not used CC net/ipv4/ip_forward.o Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 75 +++++++++++++++-------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 801df6000e9b..4f4188de3251 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -269,47 +269,6 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } -static void omap_i2c_unidle(struct omap_i2c_dev *dev) -{ - if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); - omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate); - omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate); - omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate); - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate); - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - } - - /* - * Don't write to this register if the IE state is 0 as it can - * cause deadlock. - */ - if (dev->iestate) - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); -} - -static void omap_i2c_idle(struct omap_i2c_dev *dev) -{ - u16 iv; - - dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - if (dev->dtrev == OMAP_I2C_IP_VERSION_2) - omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1); - else - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); - - if (dev->rev < OMAP_I2C_OMAP1_REV_2) { - iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ - } else { - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); - - /* Flush posted write */ - omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); - } -} - static int omap_i2c_init(struct omap_i2c_dev *dev) { u16 psc = 0, scll = 0, sclh = 0, buf = 0; @@ -1163,8 +1122,22 @@ static int omap_i2c_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + u16 iv; + + _dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG); + if (_dev->dtrev == OMAP_I2C_IP_VERSION_2) + omap_i2c_write_reg(_dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1); + else + omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0); + + if (_dev->rev < OMAP_I2C_OMAP1_REV_2) { + iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ + } else { + omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate); - omap_i2c_idle(_dev); + /* Flush posted write */ + omap_i2c_read_reg(_dev, OMAP_I2C_STAT_REG); + } return 0; } @@ -1174,7 +1147,23 @@ static int omap_i2c_runtime_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); - omap_i2c_unidle(_dev); + if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { + omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); + omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate); + omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate); + omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate); + omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate); + omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate); + omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate); + omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); + } + + /* + * Don't write to this register if the IE state is 0 as it can + * cause deadlock. + */ + if (_dev->iestate) + omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate); return 0; } -- GitLab From 247405160093cf88cb59242f877543dd28e93df1 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:14 +0530 Subject: [PATCH 2171/5711] I2C: OMAP: Fix the mismatch of pm_runtime enable and disable Currently the i2c driver calls the pm_runtime_enable and never the disable. This may cause a warning when pm_runtime_enable checks for the count match.Fix the same by calling pm_runtime_disable in the error and the remove path. Cc: Rajendra Nayak Acked-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 4f4188de3251..c851672eb6a8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1090,6 +1090,7 @@ err_unuse_clocks: omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); pm_runtime_put(dev->dev); iounmap(dev->base); + pm_runtime_disable(&pdev->dev); err_free_mem: platform_set_drvdata(pdev, NULL); kfree(dev); @@ -1110,6 +1111,7 @@ omap_i2c_remove(struct platform_device *pdev) free_irq(dev->irq, dev); i2c_del_adapter(&dev->adapter); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); + pm_runtime_disable(&pdev->dev); iounmap(dev->base); kfree(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- GitLab From bd16c82f67a267b533e747c74c2fcd23578d4601 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:15 +0530 Subject: [PATCH 2172/5711] I2C: OMAP: Fix the interrupt clearing in OMAP4 On OMAP4 we were writing 1 to IRQENABLE_CLR which cleared only the arbitration lost interrupt. The patch intends to fix the same by writing 0 to the IE register clearing all interrupts. This is based on the work done by Vikram Pandita . The changes from the original patch ... - Does not use the IRQENABLE_CLR register to clear as it is not mentioned to be legacy register IRQENABLE_CLR helps in atomically setting/clearing specific interrupts, instead use the OMAP_I2C_IE_REG as we are clearing all interrupts. Cc: Vikram Pandita Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index c851672eb6a8..bf07ffd83c1e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1127,10 +1127,8 @@ static int omap_i2c_runtime_suspend(struct device *dev) u16 iv; _dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG); - if (_dev->dtrev == OMAP_I2C_IP_VERSION_2) - omap_i2c_write_reg(_dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1); - else - omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0); + + omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0); if (_dev->rev < OMAP_I2C_OMAP1_REV_2) { iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ -- GitLab From 62ff2c2b1a36de9dd98e9b8a575da6e6b2365740 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:16 +0530 Subject: [PATCH 2173/5711] I2C: OMAP: Prevent the register access after pm_runtime_put in probe Currently in probe pm_runtime_put(dev->dev); ... /* i2c device drivers may be active on return from add_adapter() */ adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); if (r) { dev_err(dev->dev, "failure adding adapter\n"); goto err_free_irq; } ... return 0; err_free_irq: free_irq(dev->irq, dev); err_unuse_clocks: omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); pm_runtime_put(dev->dev); This may access the i2c registers without the clocks in the error cases. Fix the same by moving the pm_runtime_put after the error check. Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index bf07ffd83c1e..1777d799ee9e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1061,8 +1061,6 @@ omap_i2c_probe(struct platform_device *pdev) dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id, dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); - pm_runtime_put(dev->dev); - adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; @@ -1082,6 +1080,8 @@ omap_i2c_probe(struct platform_device *pdev) of_i2c_register_devices(adap); + pm_runtime_put(dev->dev); + return 0; err_free_irq: -- GitLab From 33d549851d2fcb6492429ebfebc344a8988b259d Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:17 +0530 Subject: [PATCH 2174/5711] I2C: OMAP: Don't check if wait_for_completion_timeout() returns less than zero By definition, wait_for_completion_timeout() returns an unsigned value and therefore, it is not necessary to check if the return value is less than zero as this is not possible. This is based on a patch from Jon Hunter Changes from his patch - Declare a long as the wait_for_completion_timeout returns long. Original patch is http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=ea02cece7b0000bc736e60c4188a11aaa74bc6e6 Reviewed-by: Kevin Hilman Signed-off-by: Jon Hunter Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 1777d799ee9e..fec8d5c6f0e5 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -473,7 +473,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { struct omap_i2c_dev *dev = i2c_get_adapdata(adap); - int r; + unsigned long timeout; u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", @@ -541,12 +541,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ - r = wait_for_completion_timeout(&dev->cmd_complete, - OMAP_I2C_TIMEOUT); + timeout = wait_for_completion_timeout(&dev->cmd_complete, + OMAP_I2C_TIMEOUT); dev->buf_len = 0; - if (r < 0) - return r; - if (r == 0) { + if (timeout == 0) { dev_err(dev->dev, "controller timed out\n"); omap_i2c_init(dev); return -ETIMEDOUT; -- GitLab From 0861f430893e0b6fe980a71cdc5fb444b952b8e1 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:18 +0530 Subject: [PATCH 2175/5711] I2C: OMAP: Fix the crash in i2c remove In omap_i2c_remove we are accessing the I2C_CON register without enabling the clocks. Fix the same by ensure device is accessible by calling pm_runtime_get_sync before accessing the registers and calling pm_runtime_put after accessing. This fixes the following crash. [ 154.723022] ------------[ cut here ]------------ [ 154.725677] WARNING: at arch/arm/mach-omap2/omap_l3_noc.c:112 l3_interrupt_handler+0x1b4/0x1c4() [ 154.725677] L3 custom error: MASTER:MPU TARGET:L4 PER2 [ 154.742614] Modules linked in: i2c_omap(-) [ 154.746948] Backtrace: [ 154.746948] [] (dump_backtrace+0x0/0x110) from [] (dump_stack+0x18/0x1c) [ 154.752716] r6:00000070 r5:c002c43c r4:df9b9e98 r3:df9b8000 [ 154.764465] [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x5c/0x6c) [ 154.768341] [] (warn_slowpath_common+0x0/0x6c) from [] (warn_slowpath_fmt+0x38/0x40) [ 154.776153] r8:00000180 r7:c0361594 r6:c0379b48 r5:00080003 r4:e0838b00 [ 154.790771] r3:00000009 [ 154.791778] [] (warn_slowpath_fmt+0x0/0x40) from [] (l3_interrupt_handler+0x1b4/0x1c4) [ 154.803710] r3:c0361598 r2:c02ef74c [ 154.807403] [] (l3_interrupt_handler+0x0/0x1c4) from [] (handle_irq_event_percpu+0x58/0 [ 154.818237] r8:0000002a r7:00000000 r6:00000000 r5:df808054 r4:df8893c0 [ 154.825378] [] (handle_irq_event_percpu+0x0/0x188) from [] (handle_irq_event+0x44/0x64) [ 154.835662] [] (handle_irq_event+0x0/0x64) from [] (handle_fasteoi_irq+0xa4/0x10c) [ 154.845458] r6:0000002a r5:df808054 r4:df808000 r3:c034a150 [ 154.846466] [] (handle_fasteoi_irq+0x0/0x10c) from [] (generic_handle_irq+0x30/0x38) [ 154.854278] r5:c034aa48 r4:0000002a [ 154.862091] [] (generic_handle_irq+0x0/0x38) from [] (handle_IRQ+0x60/0xc0) [ 154.874450] r4:c034ea70 r3:000001f8 [ 154.878234] [] (handle_IRQ+0x0/0xc0) from [] (gic_handle_irq+0x20/0x5c) [ 154.887023] r7:ffffff40 r6:df9b9fb0 r5:c034e2b4 r4:0000001a [ 154.887054] [] (gic_handle_irq+0x0/0x5c) from [] (__irq_usr+0x40/0x60) [ 154.901153] Exception stack(0xdf9b9fb0 to 0xdf9b9ff8) [ 154.907104] 9fa0: beaf1f04 4006be00 0000000f 0000000c [ 154.915710] 9fc0: 4006c000 00000000 00008034 ffffff40 00000007 00000000 00000000 0007b8d7 [ 154.916778] 9fe0: 00000000 beaf1b68 0000d23c 4005baf0 80000010 ffffffff [ 154.931335] r6:ffffffff r5:80000010 r4:4005baf0 r3:beaf1f04 [ 154.937316] ---[ end trace 1b75b31a2719ed21 ]-- Cc: Rajendra Nayak Cc: Linux PM list Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index fec8d5c6f0e5..44e8cfa84dfe 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1108,7 +1108,9 @@ omap_i2c_remove(struct platform_device *pdev) free_irq(dev->irq, dev); i2c_del_adapter(&dev->adapter); + pm_runtime_get_sync(&pdev->dev); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); + pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(dev->base); kfree(dev); -- GitLab From 3b0fb97c8dc476935670706873c27a474191ccce Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:19 +0530 Subject: [PATCH 2176/5711] I2C: OMAP: Handle error check for pm runtime If PM runtime get_sync fails return with the error so that no further reads/writes goes through the interface. This will avoid possible abort. Add a error message in case of failure with the cause of the failure. Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 44e8cfa84dfe..c39b72f4a278 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -585,7 +585,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) int i; int r; - pm_runtime_get_sync(dev->dev); + r = pm_runtime_get_sync(dev->dev); + if (IS_ERR_VALUE(r)) + return r; r = omap_i2c_wait_for_bb(dev); if (r < 0) @@ -1011,7 +1013,9 @@ omap_i2c_probe(struct platform_device *pdev) dev->regs = (u8 *)reg_map_ip_v1; pm_runtime_enable(dev->dev); - pm_runtime_get_sync(dev->dev); + r = pm_runtime_get_sync(dev->dev); + if (IS_ERR_VALUE(r)) + goto err_free_mem; dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; @@ -1103,12 +1107,16 @@ omap_i2c_remove(struct platform_device *pdev) { struct omap_i2c_dev *dev = platform_get_drvdata(pdev); struct resource *mem; + int ret; platform_set_drvdata(pdev, NULL); free_irq(dev->irq, dev); i2c_del_adapter(&dev->adapter); - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (IS_ERR_VALUE(ret)) + return ret; + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); -- GitLab From 9aa8ec676b6ef151ab11868d16a928d92410d25e Mon Sep 17 00:00:00 2001 From: Tasslehoff Kjappfot Date: Tue, 29 May 2012 16:26:20 +0530 Subject: [PATCH 2177/5711] I2C: OMAP: prevent the overwrite of the errata flags i2c_probe set the dev->errata flag, but omap_i2c_init cleared the flag again. Prevent the overwrite of the errata flags.Move the errata handling to a unified place in probe to prevent such errors. Reviewed-by: Kevin Hilman Signed-off-by: Tasslehoff Kjappfot Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index c39b72f4a278..6129cb870573 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -427,11 +427,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) /* Take the I2C module out of reset: */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - dev->errata = 0; - - if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) - dev->errata |= I2C_OMAP_ERRATA_I207; - /* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | @@ -1019,6 +1014,11 @@ omap_i2c_probe(struct platform_device *pdev) dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; + dev->errata = 0; + + if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) + dev->errata |= I2C_OMAP_ERRATA_I207; + if (dev->rev <= OMAP_I2C_REV_ON_3430) dev->errata |= I2C_OMAP3_1P153; -- GitLab From e7e62df09d9be4288c1b33aff6eef078f61c97aa Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:21 +0530 Subject: [PATCH 2178/5711] I2C: OMAP: Do not set the XUDF(Transmit underflow) if the underflow is not reached Currently in the 1.153 errata handling, while waiting for transmitter underflow, if NACK is got the XUDF(Transmit underflow) flag is also set. Fix this by setting the XUDF(Transmit underflow) flag after wait for the condition is over. Cc: Alexander Shishkin Acked-by: Moiz Sonasath Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6129cb870573..cd6feead9de2 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -730,7 +730,6 @@ static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); - *err |= OMAP_I2C_STAT_XUDF; return -ETIMEDOUT; } @@ -743,6 +742,7 @@ static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) return 0; } + *err |= OMAP_I2C_STAT_XUDF; return 0; } -- GitLab From c8db38f0e15c1fd5fec765081eb41180c3acaf60 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 29 May 2012 16:26:22 +0530 Subject: [PATCH 2179/5711] I2C: OMAP: Rename the 1p153 to the erratum id i462 The section number in the recent errata document has changed. Rename the erratum 1p153 to the unique id i462 instead, so that it is easier to reference. Also change the function name and comments to reflect the same. Cc: Jon Hunter Reviewed-by: Kevin Hilman Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index cd6feead9de2..dc3bd40b9e47 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -173,7 +173,7 @@ enum { /* Errata definitions */ #define I2C_OMAP_ERRATA_I207 (1 << 0) -#define I2C_OMAP3_1P153 (1 << 1) +#define I2C_OMAP_ERRATA_I462 (1 << 1) struct omap_i2c_dev { struct device *dev; @@ -718,11 +718,11 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id) #endif /* - * OMAP3430 Errata 1.153: When an XRDY/XDR is hit, wait for XUDF before writing + * OMAP3430 Errata i462: When an XRDY/XDR is hit, wait for XUDF before writing * data to DATA_REG. Otherwise some data bytes can be lost while transferring * them from the memory to the I2C interface. */ -static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) +static int errata_omap3_i462(struct omap_i2c_dev *dev, u16 *stat, int *err) { unsigned long timeout = 10000; @@ -881,8 +881,8 @@ complete: break; } - if ((dev->errata & I2C_OMAP3_1P153) && - errata_omap3_1p153(dev, &stat, &err)) + if ((dev->errata & I2C_OMAP_ERRATA_I462) && + errata_omap3_i462(dev, &stat, &err)) goto complete; omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); @@ -1020,7 +1020,7 @@ omap_i2c_probe(struct platform_device *pdev) dev->errata |= I2C_OMAP_ERRATA_I207; if (dev->rev <= OMAP_I2C_REV_ON_3430) - dev->errata |= I2C_OMAP3_1P153; + dev->errata |= I2C_OMAP_ERRATA_I462; if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) { u16 s; -- GitLab From b4fde5e7ed1c275986f45fe411ef7a2df58f9652 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 29 May 2012 16:26:23 +0530 Subject: [PATCH 2180/5711] I2C: OMAP: Fix timeout problem during suspend. On a board with OMAP3 processor and TWL4030 Power management, we need to talk to the TWL4030 during late suspend but cannot because the I2C interrupt is disabled (as late suspend disables interrupt). e.g. I get messages like: [ 62.161102] musb-omap2430 musb-omap2430: LATE power domain suspend [ 63.167205] omap_i2c omap_i2c.1: controller timed out [ 63.183044] twl: i2c_read failed to transfer all messages [ 64.182861] omap_i2c omap_i2c.1: controller timed out [ 64.198455] twl: i2c_write failed to transfer all messages [ 65.198455] omap_i2c omap_i2c.1: controller timed out [ 65.203765] twl: i2c_write failed to transfer all messages The stack shows omap2430_runtime_suspend calling twl4030_set_suspend which tries to power-down the USB PHY (twl4030_phy_suspend -> twl4030_phy_power -> __twl4030_phy_power which as a nice WARN_ON that helps). Then we get the same in resume: [ 69.603912] musb-omap2430 musb-omap2430: EARLY power domain resume [ 70.610473] omap_i2c omap_i2c.1: controller timed out [ 70.626129] twl: i2c_write failed to transfer all messages etc. So don't disable interrupts for I2C. Acked-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: NeilBrown Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index dc3bd40b9e47..9895fa7e486e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1053,7 +1053,7 @@ omap_i2c_probe(struct platform_device *pdev) isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr : omap_i2c_isr; - r = request_irq(dev->irq, isr, 0, pdev->name, dev); + r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev); if (r) { dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); -- GitLab From ec7aaca2f64f509f45d463d784b41d0b3d2be083 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Jun 2012 15:42:36 +0530 Subject: [PATCH 2181/5711] i2c: tegra: make sure register writes completes The Tegra PPSB (an peripheral bus) queues writes transactions. In order to guarantee that writes have completed before a certain time, a read transaction to a register on the same bus must be executed. This is necessary in situations such as when clearing an interrupt status or enable, so that when returning from an interrupt handler, the HW has already de-asserted its interrupt status output, which will avoid spurious interrupts. Signed-off-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 8b2e555a9563..785f7f7a344a 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -165,6 +165,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) { writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); + + /* Read back register to make sure that register writes completed */ + if (reg != I2C_TX_FIFO) + readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); } static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) -- GitLab From a70181049fc7b619ddc10cc1b956e7ee04b5bddd Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Jun 2012 15:42:37 +0530 Subject: [PATCH 2182/5711] i2c: tegra: add PROTOCOL_MANGLING as supported functionality. The Tegra i2c driver supports the I2C_M_IGNORE_NAK and hence returning I2C_FUNC_PROTOCOL_MANGLING as supported functionality. Signed-off-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 785f7f7a344a..68433aeaa2e8 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -563,7 +563,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; } static const struct i2c_algorithm tegra_i2c_algo = { -- GitLab From c8f5af2f507d7f97a11065b98ec9f6c22aad8af0 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Jun 2012 15:42:38 +0530 Subject: [PATCH 2183/5711] i2c: tegra: support for I2C_M_NOSTART functionality Adding support for functionality I2C_M_NOSTART. When multiple message transfer request made through i2c and if any message is flagged with I2C_M_NOSTART then it will not send the start/repeat-start and address of that message i.e. sends data directly. Signed-off-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 68433aeaa2e8..c4593a24331c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -97,8 +97,21 @@ #define I2C_HEADER_10BIT_ADDR (1<<18) #define I2C_HEADER_IE_ENABLE (1<<17) #define I2C_HEADER_REPEAT_START (1<<16) +#define I2C_HEADER_CONTINUE_XFER (1<<15) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1 +/* + * msg_end_type: The bus control which need to be send at end of transfer. + * @MSG_END_STOP: Send stop pulse at end of transfer. + * @MSG_END_REPEAT_START: Send repeat start at end of transfer. + * @MSG_END_CONTINUE: The following on message is coming and so do not send + * stop or repeat start. + */ +enum msg_end_type { + MSG_END_STOP, + MSG_END_REPEAT_START, + MSG_END_CONTINUE, +}; /** * struct tegra_i2c_dev - per device i2c context @@ -453,7 +466,7 @@ err: } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) + struct i2c_msg *msg, enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -480,7 +493,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); packet_header = I2C_HEADER_IE_ENABLE; - if (!stop) + if (end_state == MSG_END_CONTINUE) + packet_header |= I2C_HEADER_CONTINUE_XFER; + else if (end_state == MSG_END_REPEAT_START) packet_header |= I2C_HEADER_REPEAT_START; if (msg->flags & I2C_M_TEN) { packet_header |= msg->addr; @@ -552,8 +567,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], clk_enable(i2c_dev->clk); for (i = 0; i < num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop); + enum msg_end_type end_type = MSG_END_STOP; + if (i < (num - 1)) { + if (msgs[i + 1].flags & I2C_M_NOSTART) + end_type = MSG_END_CONTINUE; + else + end_type = MSG_END_REPEAT_START; + } + ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], end_type); if (ret) break; } @@ -564,7 +585,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; } static const struct i2c_algorithm tegra_i2c_algo = { -- GitLab From 9cbb6b2b92d0fdade0fe00cc00e3658b44c86676 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Jun 2012 15:42:39 +0530 Subject: [PATCH 2184/5711] i2c: tegra: make all resource allocation through devm_* Use the devm_* for the memory region allocation, interrupt request, clock handler request. By doing this, it does not require to explicitly free it and hence saving some code. Signed-off-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 62 ++++++++++------------------------ 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c4593a24331c..9f4e22cdf82c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -598,7 +598,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; struct resource *res; - struct resource *iomem; struct clk *clk; struct clk *i2c_clk; const unsigned int *prop; @@ -611,50 +610,41 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no mem resource\n"); return -EINVAL; } - iomem = request_mem_region(res->start, resource_size(res), pdev->name); - if (!iomem) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } - base = ioremap(iomem->start, resource_size(iomem)); + base = devm_request_and_ioremap(&pdev->dev, res); if (!base) { - dev_err(&pdev->dev, "Cannot ioremap I2C region\n"); - return -ENOMEM; + dev_err(&pdev->dev, "Cannot request/ioremap I2C registers\n"); + return -EADDRNOTAVAIL; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(&pdev->dev, "no irq resource\n"); - ret = -EINVAL; - goto err_iounmap; + return -EINVAL; } irq = res->start; - clk = clk_get(&pdev->dev, NULL); + clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "missing controller clock"); - ret = PTR_ERR(clk); - goto err_release_region; + return PTR_ERR(clk); } - i2c_clk = clk_get(&pdev->dev, "i2c"); + i2c_clk = devm_clk_get(&pdev->dev, "i2c"); if (IS_ERR(i2c_clk)) { dev_err(&pdev->dev, "missing bus clock"); - ret = PTR_ERR(i2c_clk); - goto err_clk_put; + return PTR_ERR(i2c_clk); } - i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); + i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) { - ret = -ENOMEM; - goto err_i2c_clk_put; + dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev"); + return -ENOMEM; } i2c_dev->base = base; i2c_dev->clk = clk; i2c_dev->i2c_clk = i2c_clk; - i2c_dev->iomem = iomem; i2c_dev->adapter.algo = &tegra_i2c_algo; i2c_dev->irq = irq; i2c_dev->cont_id = pdev->id; @@ -683,13 +673,14 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = tegra_i2c_init(i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to initialize i2c controller"); - goto err_free; + return ret; } - ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev); + ret = devm_request_irq(&pdev->dev, i2c_dev->irq, + tegra_i2c_isr, 0, pdev->name, i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); - goto err_free; + return ret; } clk_enable(i2c_dev->i2c_clk); @@ -707,38 +698,19 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(&i2c_dev->adapter); if (ret) { dev_err(&pdev->dev, "Failed to add I2C adapter\n"); - goto err_free_irq; + clk_disable(i2c_dev->i2c_clk); + return ret; } of_i2c_register_devices(&i2c_dev->adapter); return 0; -err_free_irq: - free_irq(i2c_dev->irq, i2c_dev); -err_free: - kfree(i2c_dev); -err_i2c_clk_put: - clk_put(i2c_clk); -err_clk_put: - clk_put(clk); -err_release_region: - release_mem_region(iomem->start, resource_size(iomem)); -err_iounmap: - iounmap(base); - return ret; } static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); - free_irq(i2c_dev->irq, i2c_dev); - clk_put(i2c_dev->i2c_clk); - clk_put(i2c_dev->clk); - release_mem_region(i2c_dev->iomem->start, - resource_size(i2c_dev->iomem)); - iounmap(i2c_dev->base); - kfree(i2c_dev); return 0; } -- GitLab From 9f8a3e7fd5bd08e3fd9847c04a5a445e2994f6b3 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 4 Jun 2012 19:04:25 +0800 Subject: [PATCH 2185/5711] i2c: imx: convert to use managed functions - convert to use devm_request_and_ioremap, devm_kzalloc, devm_clk_get, devm_request_irq. - clean up unused variables. Signed-off-by: Richard Zhao Reviewed-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 71 +++++++++--------------------------- 1 file changed, 18 insertions(+), 53 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 8d6b504d65c4..a93e84650f99 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -118,10 +118,8 @@ static u16 __initdata i2c_clk_div[50][2] = { struct imx_i2c_struct { struct i2c_adapter adapter; - struct resource *res; struct clk *clk; void __iomem *base; - int irq; wait_queue_head_t queue; unsigned long i2csr; unsigned int disable_delay; @@ -473,7 +471,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imxi2c_platform_data *pdata = pdev->dev.platform_data; struct pinctrl *pinctrl; void __iomem *base; - resource_size_t res_size; int irq, bitrate; int ret; @@ -490,25 +487,15 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return -ENOENT; } - res_size = resource_size(res); - - if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); + base = devm_request_and_ioremap(&pdev->dev, res); + if (!base) return -EBUSY; - } - - base = ioremap(res->start, res_size); - if (!base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -EIO; - goto fail1; - } - i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); + i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct), + GFP_KERNEL); if (!i2c_imx) { dev_err(&pdev->dev, "can't allocate interface\n"); - ret = -ENOMEM; - goto fail2; + return -ENOMEM; } /* Setup i2c_imx driver structure */ @@ -518,29 +505,27 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx->adapter.dev.parent = &pdev->dev; i2c_imx->adapter.nr = pdev->id; i2c_imx->adapter.dev.of_node = pdev->dev.of_node; - i2c_imx->irq = irq; i2c_imx->base = base; - i2c_imx->res = res; pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto fail3; + dev_err(&pdev->dev, "can't get/select pinctrl\n"); + return PTR_ERR(pinctrl); } /* Get I2C clock */ - i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); + i2c_imx->clk = devm_clk_get(&pdev->dev, "i2c_clk"); if (IS_ERR(i2c_imx->clk)) { - ret = PTR_ERR(i2c_imx->clk); dev_err(&pdev->dev, "can't get I2C clock\n"); - goto fail3; + return PTR_ERR(i2c_imx->clk); } /* Request IRQ */ - ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); + ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, + pdev->name, i2c_imx); if (ret) { - dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); - goto fail4; + dev_err(&pdev->dev, "can't claim irq %d\n", irq); + return ret; } /* Init queue */ @@ -565,7 +550,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(&i2c_imx->adapter); if (ret < 0) { dev_err(&pdev->dev, "registration failed\n"); - goto fail5; + return ret; } of_i2c_register_devices(&i2c_imx->adapter); @@ -573,28 +558,16 @@ static int __init i2c_imx_probe(struct platform_device *pdev) /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); - dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); + dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq); dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", - i2c_imx->res->start, i2c_imx->res->end); - dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", - res_size, i2c_imx->res->start); + res->start, res->end); + dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n", + resource_size(res), res->start); dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", i2c_imx->adapter.name); dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); return 0; /* Return OK */ - -fail5: - free_irq(i2c_imx->irq, i2c_imx); -fail4: - clk_put(i2c_imx->clk); -fail3: - kfree(i2c_imx); -fail2: - iounmap(base); -fail1: - release_mem_region(res->start, resource_size(res)); - return ret; /* Return error number */ } static int __exit i2c_imx_remove(struct platform_device *pdev) @@ -606,20 +579,12 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) i2c_del_adapter(&i2c_imx->adapter); platform_set_drvdata(pdev, NULL); - /* free interrupt */ - free_irq(i2c_imx->irq, i2c_imx); - /* setup chip registers to defaults */ writeb(0, i2c_imx->base + IMX_I2C_IADR); writeb(0, i2c_imx->base + IMX_I2C_IFDR); writeb(0, i2c_imx->base + IMX_I2C_I2CR); writeb(0, i2c_imx->base + IMX_I2C_I2SR); - clk_put(i2c_imx->clk); - - iounmap(i2c_imx->base); - release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); - kfree(i2c_imx); return 0; } -- GitLab From fb18155925139caef33f5c2d0e60316c3c9c1aac Mon Sep 17 00:00:00 2001 From: Paul Parsons Date: Sun, 3 Jun 2012 11:33:52 +0100 Subject: [PATCH 2186/5711] video: w100fb: Reduce sleep mode battery discharge In 2006 and 2007 the handhelds.org kernel w100fb driver was patched to reduce sleep mode battery discharge. Unfortunately those two patches never migrated to the mainline kernel. Fortunately the function affected - w100_suspend() - has not changed since; thus those patches still apply cleanly. Applying those patches to linux-3.4-rc3 running on an HP iPAQ hx4700 reduces the sleep mode battery discharge from approximately 26 mA to approximately 11 mA. This patch combines those two patches into a single unified patch. Signed-off-by: Paul Parsons Cc: Matt Reimer Cc: Philipp Zabel Signed-off-by: Florian Tobias Schandinat --- drivers/video/w100fb.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 90a2e30272ad..2f6b2b835f88 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -1567,6 +1567,18 @@ static void w100_suspend(u32 mode) val = readl(remapped_regs + mmPLL_CNTL); val |= 0x00000004; /* bit2=1 */ writel(val, remapped_regs + mmPLL_CNTL); + + writel(0x00000000, remapped_regs + mmLCDD_CNTL1); + writel(0x00000000, remapped_regs + mmLCDD_CNTL2); + writel(0x00000000, remapped_regs + mmGENLCD_CNTL1); + writel(0x00000000, remapped_regs + mmGENLCD_CNTL2); + writel(0x00000000, remapped_regs + mmGENLCD_CNTL3); + + val = readl(remapped_regs + mmMEM_EXT_CNTL); + val |= 0xF0000000; + val &= ~(0x00000001); + writel(val, remapped_regs + mmMEM_EXT_CNTL); + writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL); } } -- GitLab From 42eb317f7d089f878a06aa358d1f168eac3e5afd Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Tue, 26 Jun 2012 00:37:32 +0200 Subject: [PATCH 2187/5711] grvga: Fix error handling issues This patch fixes two problems with the error handling in the grvga_probe function and simplifies it making the code easier to read. - If the call to grvga_parse_custom on line 370 fails we use the wrong label so that release_mem_region will be called without a call to request_mem_region being made. - If the call to ioremap on line 436 fails we should not try to call iounmap in the error handling code. This patch introduces the following changes: - Converts request_mem_region into its devm_ equivalent which simplifies the otherwise messy clean up code. - Changes the labels for correct error handling and their names to make the code easier to read. Signed-off-by: Emil Goode Signed-off-by: Florian Tobias Schandinat --- drivers/video/grvga.c | 47 ++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c index da066c210923..5245f9a71892 100644 --- a/drivers/video/grvga.c +++ b/drivers/video/grvga.c @@ -354,7 +354,7 @@ static int __devinit grvga_probe(struct platform_device *dev) */ if (fb_get_options("grvga", &options)) { retval = -ENODEV; - goto err; + goto free_fb; } if (!options || !*options) @@ -370,7 +370,7 @@ static int __devinit grvga_probe(struct platform_device *dev) if (grvga_parse_custom(this_opt, &info->var) < 0) { dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt); retval = -EINVAL; - goto err1; + goto free_fb; } } else if (!strncmp(this_opt, "addr", 4)) grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16); @@ -387,10 +387,11 @@ static int __devinit grvga_probe(struct platform_device *dev) info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; info->fix.smem_len = grvga_mem_size; - if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { + if (!devm_request_mem_region(&dev->dev, dev->resource[0].start, + resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { dev_err(&dev->dev, "registers already mapped\n"); retval = -EBUSY; - goto err; + goto free_fb; } par->regs = of_ioremap(&dev->resource[0], 0, @@ -400,14 +401,14 @@ static int __devinit grvga_probe(struct platform_device *dev) if (!par->regs) { dev_err(&dev->dev, "failed to map registers\n"); retval = -ENOMEM; - goto err1; + goto free_fb; } retval = fb_alloc_cmap(&info->cmap, 256, 0); if (retval < 0) { dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n"); retval = -ENOMEM; - goto err2; + goto unmap_regs; } if (mode_opt) { @@ -415,7 +416,7 @@ static int __devinit grvga_probe(struct platform_device *dev) grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8); if (!retval || retval == 4) { retval = -EINVAL; - goto err3; + goto dealloc_cmap; } } @@ -427,10 +428,11 @@ static int __devinit grvga_probe(struct platform_device *dev) physical_start = grvga_fix_addr; - if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) { + if (!devm_request_mem_region(&dev->dev, physical_start, + grvga_mem_size, dev->name)) { dev_err(&dev->dev, "failed to request memory region\n"); retval = -ENOMEM; - goto err3; + goto dealloc_cmap; } virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size); @@ -438,7 +440,7 @@ static int __devinit grvga_probe(struct platform_device *dev) if (!virtual_start) { dev_err(&dev->dev, "error mapping framebuffer memory\n"); retval = -ENOMEM; - goto err4; + goto dealloc_cmap; } } else { /* Allocate frambuffer memory */ @@ -451,7 +453,7 @@ static int __devinit grvga_probe(struct platform_device *dev) "unable to allocate framebuffer memory (%lu bytes)\n", grvga_mem_size); retval = -ENOMEM; - goto err3; + goto dealloc_cmap; } physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE); @@ -484,7 +486,7 @@ static int __devinit grvga_probe(struct platform_device *dev) retval = register_framebuffer(info); if (retval < 0) { dev_err(&dev->dev, "failed to register framebuffer\n"); - goto err4; + goto free_mem; } __raw_writel(physical_start, &par->regs->fb_pos); @@ -493,21 +495,18 @@ static int __devinit grvga_probe(struct platform_device *dev) return 0; -err4: +free_mem: dev_set_drvdata(&dev->dev, NULL); - if (grvga_fix_addr) { - release_mem_region(physical_start, grvga_mem_size); + if (grvga_fix_addr) iounmap((void *)virtual_start); - } else + else kfree((void *)virtual_start); -err3: +dealloc_cmap: fb_dealloc_cmap(&info->cmap); -err2: +unmap_regs: of_iounmap(&dev->resource[0], par->regs, resource_size(&dev->resource[0])); -err1: - release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0])); -err: +free_fb: framebuffer_release(info); return retval; @@ -524,12 +523,10 @@ static int __devexit grvga_remove(struct platform_device *device) of_iounmap(&device->resource[0], par->regs, resource_size(&device->resource[0])); - release_mem_region(device->resource[0].start, resource_size(&device->resource[0])); - if (!par->fb_alloced) { - release_mem_region(info->fix.smem_start, info->fix.smem_len); + if (!par->fb_alloced) iounmap(info->screen_base); - } else + else kfree((void *)info->screen_base); framebuffer_release(info); -- GitLab From 6fcdbc0c3a683003a00f383fceac80da1b7852ff Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 6 Jul 2012 15:12:11 +0200 Subject: [PATCH 2188/5711] s3fb: Add Virge/MX (86C260) Add support for Virge/MX (86C260) chip. Although this is a laptop chip, there's an AGP card with this chip too. Tested with AGP card, will probably not work correctly with laptops. DDC does not work on this card (even in DOS or Windows). Signed-off-by: Ondrej Zary Signed-off-by: Florian Tobias Schandinat --- drivers/video/s3fb.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 2c80246b18b8..1d007366b917 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -84,7 +84,7 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", "S3 Virge/GX2", "S3 Virge/GX2+", "", "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", - "S3 Trio3D"}; + "S3 Trio3D", "S3 Virge/MX"}; #define CHIP_UNKNOWN 0x00 #define CHIP_732_TRIO32 0x01 @@ -105,6 +105,7 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", #define CHIP_362_TRIO3D_2X 0x11 #define CHIP_368_TRIO3D_2X 0x12 #define CHIP_365_TRIO3D 0x13 +#define CHIP_260_VIRGE_MX 0x14 #define CHIP_XXX_TRIO 0x80 #define CHIP_XXX_TRIO64V2_DXGX 0x81 @@ -280,7 +281,8 @@ static int __devinit s3fb_setup_ddc_bus(struct fb_info *info) */ /* vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */ if (par->chip == CHIP_357_VIRGE_GX2 || - par->chip == CHIP_359_VIRGE_GX2P) + par->chip == CHIP_359_VIRGE_GX2P || + par->chip == CHIP_260_VIRGE_MX) svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03); else svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03); @@ -487,7 +489,8 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || - par->chip == CHIP_368_TRIO3D_2X) { + par->chip == CHIP_368_TRIO3D_2X || + par->chip == CHIP_260_VIRGE_MX) { vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */ } else @@ -690,7 +693,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip != CHIP_359_VIRGE_GX2P && par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && - par->chip != CHIP_368_TRIO3D_2X) { + par->chip != CHIP_368_TRIO3D_2X && + par->chip != CHIP_260_VIRGE_MX) { vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */ vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */ @@ -739,7 +743,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip == CHIP_368_TRIO3D_2X || par->chip == CHIP_365_TRIO3D || par->chip == CHIP_375_VIRGE_DX || - par->chip == CHIP_385_VIRGE_GX) { + par->chip == CHIP_385_VIRGE_GX || + par->chip == CHIP_260_VIRGE_MX) { dbytes = info->var.xres * ((bpp+7)/8); vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8); vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); @@ -751,7 +756,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || - par->chip == CHIP_368_TRIO3D_2X) + par->chip == CHIP_368_TRIO3D_2X || + par->chip == CHIP_260_VIRGE_MX) vga_wcrt(par->state.vgabase, 0x34, 0x00); else /* enable Data Transfer Position Control (DTPC) */ vga_wcrt(par->state.vgabase, 0x34, 0x10); @@ -807,7 +813,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || - par->chip == CHIP_368_TRIO3D_2X) + par->chip == CHIP_368_TRIO3D_2X || + par->chip == CHIP_260_VIRGE_MX) svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); else { svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0); @@ -837,7 +844,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip != CHIP_359_VIRGE_GX2P && par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && - par->chip != CHIP_368_TRIO3D_2X) + par->chip != CHIP_368_TRIO3D_2X && + par->chip != CHIP_260_VIRGE_MX) hmul = 2; } break; @@ -864,7 +872,8 @@ static int s3fb_set_par(struct fb_info *info) par->chip != CHIP_359_VIRGE_GX2P && par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && - par->chip != CHIP_368_TRIO3D_2X) + par->chip != CHIP_368_TRIO3D_2X && + par->chip != CHIP_260_VIRGE_MX) hmul = 2; } break; @@ -1208,7 +1217,8 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i break; } } else if (par->chip == CHIP_357_VIRGE_GX2 || - par->chip == CHIP_359_VIRGE_GX2P) { + par->chip == CHIP_359_VIRGE_GX2P || + par->chip == CHIP_260_VIRGE_MX) { switch ((regval & 0xC0) >> 6) { case 1: /* 4MB */ info->screen_size = 4 << 20; @@ -1515,6 +1525,7 @@ static struct pci_device_id s3_devices[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, + {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8C01), .driver_data = CHIP_260_VIRGE_MX}, {0, 0, 0, 0, 0, 0, 0} }; -- GitLab From 069ddcda37b2cf5bb4b6031a944c0e9359213262 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 11 Jun 2012 15:42:32 -0700 Subject: [PATCH 2189/5711] eCryptfs: Copy up POSIX ACL and read-only flags from lower mount When the eCryptfs mount options do not include '-o acl', but the lower filesystem's mount options do include 'acl', the MS_POSIXACL flag is not flipped on in the eCryptfs super block flags. This flag is what the VFS checks in do_last() when deciding if the current umask should be applied to a newly created inode's mode or not. When a default POSIX ACL mask is set on a directory, the current umask is incorrectly applied to new inodes created in the directory. This patch ignores the MS_POSIXACL flag passed into ecryptfs_mount() and sets the flag on the eCryptfs super block depending on the flag's presence on the lower super block. Additionally, it is incorrect to allow a writeable eCryptfs mount on top of a read-only lower mount. This missing check did not allow writes to the read-only lower mount because permissions checks are still performed on the lower filesystem's objects but it is best to simply not allow a rw mount on top of ro mount. However, a ro eCryptfs mount on top of a rw mount is valid and still allowed. https://launchpad.net/bugs/1009207 Signed-off-by: Tyler Hicks Reported-by: Stefan Beller Cc: John Johansen --- fs/ecryptfs/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 68954937a071..df217dc9f1d9 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -505,7 +505,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags goto out; } - s->s_flags = flags; rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); if (rc) goto out1; @@ -541,6 +540,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags } ecryptfs_set_superblock_lower(s, path.dentry->d_sb); + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower + * mount. Force a read-only eCryptfs mount if the lower mount is ro. + * Allow a ro eCryptfs mount even when the lower mount is rw. + */ + s->s_flags = flags & ~MS_POSIXACL; + s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; s->s_blocksize = path.dentry->d_sb->s_blocksize; s->s_magic = ECRYPTFS_SUPER_MAGIC; -- GitLab From 566968866555a19d0a78e0bfa845cd249a7eeae2 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 11 Jun 2012 09:39:54 -0700 Subject: [PATCH 2190/5711] eCryptfs: Remove unused messaging declarations and function These are no longer needed. Signed-off-by: Tyler Hicks Cc: Sasha Levin --- fs/ecryptfs/ecryptfs_kernel.h | 6 ------ fs/ecryptfs/messaging.c | 31 ------------------------------- 2 files changed, 37 deletions(-) diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 867b64c5d84f..01a1f8575950 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -385,8 +385,6 @@ struct ecryptfs_msg_ctx { struct mutex mux; }; -struct ecryptfs_daemon; - struct ecryptfs_daemon { #define ECRYPTFS_DAEMON_IN_READ 0x00000001 #define ECRYPTFS_DAEMON_IN_POLL 0x00000002 @@ -621,10 +619,6 @@ int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); -int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns, - struct pid *pid); -int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, - struct pid *pid); int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, struct user_namespace *user_ns, struct pid *pid, u32 seq); diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index a750f957b145..c11911decdc1 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -215,37 +215,6 @@ out: return rc; } -/** - * ecryptfs_process_quit - * @euid: The user ID owner of the message - * @user_ns: The namespace in which @euid applies - * @pid: The process ID for the userspace program that sent the - * message - * - * Deletes the corresponding daemon for the given euid and pid, if - * it is the registered that is requesting the deletion. Returns zero - * after deleting the desired daemon; non-zero otherwise. - */ -int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, - struct pid *pid) -{ - struct ecryptfs_daemon *daemon; - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns); - if (rc || !daemon) { - rc = -EINVAL; - printk(KERN_ERR "Received request from user [%d] to " - "unregister unrecognized daemon [0x%p]\n", euid, pid); - goto out_unlock; - } - rc = ecryptfs_exorcise_daemon(daemon); -out_unlock: - mutex_unlock(&ecryptfs_daemon_hash_mux); - return rc; -} - /** * ecryptfs_process_reponse * @msg: The ecryptfs message received; the caller should sanity check -- GitLab From 2ecaf55db6dcf4dd25e1ef8d5eb6068e3286a20f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 11 Jun 2012 09:47:47 -0700 Subject: [PATCH 2191/5711] eCryptfs: Make all miscdev functions use daemon ptr in file private_data Now that a pointer to a valid struct ecryptfs_daemon is stored in the private_data of an opened /dev/ecryptfs file, the remaining miscdev functions can utilize the pointer rather than looking up the ecryptfs_daemon at the beginning of each operation. The security model of /dev/ecryptfs is simplified a little bit with this patch. Upon opening /dev/ecryptfs, a per-user ecryptfs_daemon is registered. Another daemon cannot be registered for that user until the last file reference is released. During the lifetime of the ecryptfs_daemon, access checks are not performed on the /dev/ecryptfs operations because it is assumed that the application securely handles the opened file descriptor and does not unintentionally leak it to processes that are not trusted. Signed-off-by: Tyler Hicks Cc: Sasha Levin --- fs/ecryptfs/ecryptfs_kernel.h | 16 ++---- fs/ecryptfs/messaging.c | 105 ++++++---------------------------- fs/ecryptfs/miscdev.c | 98 +++++++++---------------------- 3 files changed, 47 insertions(+), 172 deletions(-) diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 01a1f8575950..0deb4f24957a 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -392,10 +392,7 @@ struct ecryptfs_daemon { #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 u32 flags; u32 num_queued_msg_ctx; - struct pid *pid; - uid_t euid; - struct user_namespace *user_ns; - struct task_struct *task; + struct file *file; struct mutex mux; struct list_head msg_ctx_out_queue; wait_queue_head_t wait; @@ -619,9 +616,8 @@ int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); -int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, - struct user_namespace *user_ns, struct pid *pid, - u32 seq); +int ecryptfs_process_response(struct ecryptfs_daemon *daemon, + struct ecryptfs_message *msg, u32 seq); int ecryptfs_send_message(char *data, int data_len, struct ecryptfs_msg_ctx **msg_ctx); int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, @@ -666,8 +662,7 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, struct inode *ecryptfs_inode); struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); -int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns); +int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon); int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, size_t *length_size); int ecryptfs_write_packet_length(char *dest, size_t size, @@ -679,8 +674,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, u16 msg_flags, struct ecryptfs_daemon *daemon); void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); int -ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns, struct pid *pid); +ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file); int ecryptfs_init_kthread(void); void ecryptfs_destroy_kthread(void); int ecryptfs_privileged_open(struct file **lower_file, diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index c11911decdc1..b29bb8bfa8d9 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -32,8 +32,8 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; static struct hlist_head *ecryptfs_daemon_hash; struct mutex ecryptfs_daemon_hash_mux; static int ecryptfs_hash_bits; -#define ecryptfs_uid_hash(uid) \ - hash_long((unsigned long)uid, ecryptfs_hash_bits) +#define ecryptfs_current_euid_hash(uid) \ + hash_long((unsigned long)current_euid(), ecryptfs_hash_bits) static u32 ecryptfs_msg_counter; static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; @@ -105,26 +105,24 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) /** * ecryptfs_find_daemon_by_euid - * @euid: The effective user id which maps to the desired daemon id - * @user_ns: The namespace in which @euid applies * @daemon: If return value is zero, points to the desired daemon pointer * * Must be called with ecryptfs_daemon_hash_mux held. * - * Search the hash list for the given user id. + * Search the hash list for the current effective user id. * * Returns zero if the user id exists in the list; non-zero otherwise. */ -int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns) +int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon) { struct hlist_node *elem; int rc; hlist_for_each_entry(*daemon, elem, - &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], - euid_chain) { - if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { + &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], + euid_chain) { + if ((*daemon)->file->f_cred->euid == current_euid() && + (*daemon)->file->f_cred->user_ns == current_user_ns()) { rc = 0; goto out; } @@ -137,9 +135,7 @@ out: /** * ecryptfs_spawn_daemon - Create and initialize a new daemon struct * @daemon: Pointer to set to newly allocated daemon struct - * @euid: Effective user id for the daemon - * @user_ns: The namespace in which @euid applies - * @pid: Process id for the daemon + * @file: File used when opening /dev/ecryptfs * * Must be called ceremoniously while in possession of * ecryptfs_sacred_daemon_hash_mux @@ -147,8 +143,7 @@ out: * Returns zero on success; non-zero otherwise */ int -ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns, struct pid *pid) +ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) { int rc = 0; @@ -159,16 +154,13 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); goto out; } - (*daemon)->euid = euid; - (*daemon)->user_ns = get_user_ns(user_ns); - (*daemon)->pid = get_pid(pid); - (*daemon)->task = current; + (*daemon)->file = file; mutex_init(&(*daemon)->mux); INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); init_waitqueue_head(&(*daemon)->wait); (*daemon)->num_queued_msg_ctx = 0; hlist_add_head(&(*daemon)->euid_chain, - &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); + &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]); out: return rc; } @@ -188,9 +180,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { rc = -EBUSY; - printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " - "[0x%p], but it is in the midst of a read or a poll\n", - __func__, daemon->pid); mutex_unlock(&daemon->mux); goto out; } @@ -203,12 +192,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) ecryptfs_msg_ctx_alloc_to_free(msg_ctx); } hlist_del(&daemon->euid_chain); - if (daemon->task) - wake_up_process(daemon->task); - if (daemon->pid) - put_pid(daemon->pid); - if (daemon->user_ns) - put_user_ns(daemon->user_ns); mutex_unlock(&daemon->mux); kzfree(daemon); out: @@ -219,8 +202,6 @@ out: * ecryptfs_process_reponse * @msg: The ecryptfs message received; the caller should sanity check * msg->data_len and free the memory - * @pid: The process ID of the userspace application that sent the - * message * @seq: The sequence number of the message; must match the sequence * number for the existing message context waiting for this * response @@ -239,16 +220,11 @@ out: * * Returns zero on success; non-zero otherwise */ -int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, - struct user_namespace *user_ns, struct pid *pid, - u32 seq) +int ecryptfs_process_response(struct ecryptfs_daemon *daemon, + struct ecryptfs_message *msg, u32 seq) { - struct ecryptfs_daemon *uninitialized_var(daemon); struct ecryptfs_msg_ctx *msg_ctx; size_t msg_size; - struct nsproxy *nsproxy; - struct user_namespace *tsk_user_ns; - uid_t ctx_euid; int rc; if (msg->index >= ecryptfs_message_buf_len) { @@ -261,51 +237,6 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, } msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; mutex_lock(&msg_ctx->mux); - mutex_lock(&ecryptfs_daemon_hash_mux); - rcu_read_lock(); - nsproxy = task_nsproxy(msg_ctx->task); - if (nsproxy == NULL) { - rc = -EBADMSG; - printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " - "message.\n", __func__); - rcu_read_unlock(); - mutex_unlock(&ecryptfs_daemon_hash_mux); - goto wake_up; - } - tsk_user_ns = __task_cred(msg_ctx->task)->user_ns; - ctx_euid = task_euid(msg_ctx->task); - rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); - rcu_read_unlock(); - mutex_unlock(&ecryptfs_daemon_hash_mux); - if (rc) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: User [%d] received a " - "message response from process [0x%p] but does " - "not have a registered daemon\n", __func__, - ctx_euid, pid); - goto wake_up; - } - if (ctx_euid != euid) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: Received message from user " - "[%d]; expected message from user [%d]\n", __func__, - euid, ctx_euid); - goto unlock; - } - if (tsk_user_ns != user_ns) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: Received message from user_ns " - "[0x%p]; expected message from user_ns [0x%p]\n", - __func__, user_ns, tsk_user_ns); - goto unlock; - } - if (daemon->pid != pid) { - rc = -EBADMSG; - printk(KERN_ERR "%s: User [%d] sent a message response " - "from an unrecognized process [0x%p]\n", - __func__, ctx_euid, pid); - goto unlock; - } if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { rc = -EINVAL; printk(KERN_WARNING "%s: Desired context element is not " @@ -328,9 +259,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, } memcpy(msg_ctx->msg, msg, msg_size); msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; - rc = 0; -wake_up: wake_up_process(msg_ctx->task); + rc = 0; unlock: mutex_unlock(&msg_ctx->mux); out: @@ -352,14 +282,11 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx) { struct ecryptfs_daemon *daemon; - uid_t euid = current_euid(); int rc; - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); + rc = ecryptfs_find_daemon_by_euid(&daemon); if (rc || !daemon) { rc = -ENOTCONN; - printk(KERN_ERR "%s: User [%d] does not have a daemon " - "registered\n", __func__, euid); goto out; } mutex_lock(&ecryptfs_msg_ctx_lists_mux); diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index c0038f6566d4..412e6eda25f8 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -33,7 +33,7 @@ static atomic_t ecryptfs_num_miscdev_opens; /** * ecryptfs_miscdev_poll - * @file: dev file (ignored) + * @file: dev file * @pt: dev poll table (ignored) * * Returns the poll mask @@ -41,20 +41,10 @@ static atomic_t ecryptfs_num_miscdev_opens; static unsigned int ecryptfs_miscdev_poll(struct file *file, poll_table *pt) { - struct ecryptfs_daemon *daemon; + struct ecryptfs_daemon *daemon = file->private_data; unsigned int mask = 0; - uid_t euid = current_euid(); - int rc; - mutex_lock(&ecryptfs_daemon_hash_mux); - /* TODO: Just use file->private_data? */ - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EINVAL; - } mutex_lock(&daemon->mux); - mutex_unlock(&ecryptfs_daemon_hash_mux); if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { printk(KERN_WARNING "%s: Attempt to poll on zombified " "daemon\n", __func__); @@ -79,7 +69,7 @@ out_unlock_daemon: /** * ecryptfs_miscdev_open * @inode: inode of miscdev handle (ignored) - * @file: file for miscdev handle (ignored) + * @file: file for miscdev handle * * Returns zero on success; non-zero otherwise */ @@ -87,7 +77,6 @@ static int ecryptfs_miscdev_open(struct inode *inode, struct file *file) { struct ecryptfs_daemon *daemon = NULL; - uid_t euid = current_euid(); int rc; mutex_lock(&ecryptfs_daemon_hash_mux); @@ -98,30 +87,20 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) "count; rc = [%d]\n", __func__, rc); goto out_unlock_daemon_list; } - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), - task_pid(current)); - if (rc) { - printk(KERN_ERR "%s: Error attempting to spawn daemon; " - "rc = [%d]\n", __func__, rc); - goto out_module_put_unlock_daemon_list; - } - } - mutex_lock(&daemon->mux); - if (daemon->pid != task_pid(current)) { + rc = ecryptfs_find_daemon_by_euid(&daemon); + if (!rc) { rc = -EINVAL; - printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " - "but pid [0x%p] has attempted to open the handle " - "instead\n", __func__, daemon->pid, daemon->euid, - task_pid(current)); - goto out_unlock_daemon; + goto out_unlock_daemon_list; + } + rc = ecryptfs_spawn_daemon(&daemon, file); + if (rc) { + printk(KERN_ERR "%s: Error attempting to spawn daemon; " + "rc = [%d]\n", __func__, rc); + goto out_module_put_unlock_daemon_list; } + mutex_lock(&daemon->mux); if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { rc = -EBUSY; - printk(KERN_ERR "%s: Miscellaneous device handle may only be " - "opened once per daemon; pid [0x%p] already has this " - "handle open\n", __func__, daemon->pid); goto out_unlock_daemon; } daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; @@ -140,7 +119,7 @@ out_unlock_daemon_list: /** * ecryptfs_miscdev_release * @inode: inode of fs/ecryptfs/euid handle (ignored) - * @file: file for fs/ecryptfs/euid handle (ignored) + * @file: file for fs/ecryptfs/euid handle * * This keeps the daemon registered until the daemon sends another * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. @@ -150,20 +129,18 @@ out_unlock_daemon_list: static int ecryptfs_miscdev_release(struct inode *inode, struct file *file) { - struct ecryptfs_daemon *daemon = NULL; - uid_t euid = current_euid(); + struct ecryptfs_daemon *daemon = file->private_data; int rc; - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) - daemon = file->private_data; mutex_lock(&daemon->mux); BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; atomic_dec(&ecryptfs_num_miscdev_opens); mutex_unlock(&daemon->mux); + + mutex_lock(&ecryptfs_daemon_hash_mux); rc = ecryptfs_exorcise_daemon(daemon); + mutex_unlock(&ecryptfs_daemon_hash_mux); if (rc) { printk(KERN_CRIT "%s: Fatal error whilst attempting to " "shut down daemon; rc = [%d]. Please report this " @@ -171,7 +148,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) BUG(); } module_put(THIS_MODULE); - mutex_unlock(&ecryptfs_daemon_hash_mux); return rc; } @@ -248,7 +224,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, /** * ecryptfs_miscdev_read - format and send message from queue - * @file: fs/ecryptfs/euid miscdevfs handle (ignored) + * @file: miscdevfs handle * @buf: User buffer into which to copy the next message on the daemon queue * @count: Amount of space available in @buf * @ppos: Offset in file (ignored) @@ -262,43 +238,27 @@ static ssize_t ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct ecryptfs_daemon *daemon; + struct ecryptfs_daemon *daemon = file->private_data; struct ecryptfs_msg_ctx *msg_ctx; size_t packet_length_size; char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; size_t i; size_t total_length; - uid_t euid = current_euid(); int rc; - mutex_lock(&ecryptfs_daemon_hash_mux); - /* TODO: Just use file->private_data? */ - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EINVAL; - } mutex_lock(&daemon->mux); - if (task_pid(current) != daemon->pid) { - mutex_unlock(&daemon->mux); - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EPERM; - } if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { rc = 0; - mutex_unlock(&ecryptfs_daemon_hash_mux); printk(KERN_WARNING "%s: Attempt to read from zombified " "daemon\n", __func__); goto out_unlock_daemon; } if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { rc = 0; - mutex_unlock(&ecryptfs_daemon_hash_mux); goto out_unlock_daemon; } /* This daemon will not go away so long as this flag is set */ daemon->flags |= ECRYPTFS_DAEMON_IN_READ; - mutex_unlock(&ecryptfs_daemon_hash_mux); check_list: if (list_empty(&daemon->msg_ctx_out_queue)) { mutex_unlock(&daemon->mux); @@ -382,16 +342,12 @@ out_unlock_daemon: * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon * @data: Bytes comprising struct ecryptfs_message * @data_size: sizeof(struct ecryptfs_message) + data len - * @euid: Effective user id of miscdevess sending the miscdev response - * @user_ns: The namespace in which @euid applies - * @pid: Miscdevess id of miscdevess sending the miscdev response * @seq: Sequence number for miscdev response packet * * Returns zero on success; non-zero otherwise */ -static int ecryptfs_miscdev_response(char *data, size_t data_size, - uid_t euid, struct user_namespace *user_ns, - struct pid *pid, u32 seq) +static int ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data, + size_t data_size, u32 seq) { struct ecryptfs_message *msg = (struct ecryptfs_message *)data; int rc; @@ -403,7 +359,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size, rc = -EINVAL; goto out; } - rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); + rc = ecryptfs_process_response(daemon, msg, seq); if (rc) printk(KERN_ERR "Error processing response message; rc = [%d]\n", rc); @@ -413,7 +369,7 @@ out: /** * ecryptfs_miscdev_write - handle write to daemon miscdev handle - * @file: File for misc dev handle (ignored) + * @file: File for misc dev handle * @buf: Buffer containing user data * @count: Amount of data in @buf * @ppos: Pointer to offset in file (ignored) @@ -428,7 +384,6 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, u32 seq; size_t packet_size, packet_size_length; char *data; - uid_t euid = current_euid(); unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; ssize_t rc; @@ -488,10 +443,9 @@ memdup: } memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); seq = be32_to_cpu(counter_nbo); - rc = ecryptfs_miscdev_response( + rc = ecryptfs_miscdev_response(file->private_data, &data[PKT_LEN_OFFSET + packet_size_length], - packet_size, euid, current_user_ns(), - task_pid(current), seq); + packet_size, seq); if (rc) { printk(KERN_WARNING "%s: Failed to deliver miscdev " "response to requesting operation; rc = [%zd]\n", -- GitLab From 8bc2d3cf612994a960c2e8eaea37f6676f67082a Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 22 May 2012 15:09:50 -0500 Subject: [PATCH 2192/5711] eCryptfs: Unlink lower inode when ecryptfs_create() fails ecryptfs_create() creates a lower inode, allocates an eCryptfs inode, initializes the eCryptfs inode and cryptographic metadata attached to the inode, and then writes the metadata to the header of the file. If an error was to occur after the lower inode was created, an empty lower file would be left in the lower filesystem. This is a problem because ecryptfs_open() refuses to open any lower files which do not have the appropriate metadata in the file header. This patch properly unlinks the lower inode when an error occurs in the later stages of ecryptfs_create(), reducing the chance that an empty lower file will be left in the lower filesystem. https://launchpad.net/bugs/872905 Signed-off-by: Tyler Hicks Cc: John Johansen Cc: Colin Ian King --- fs/ecryptfs/inode.c | 55 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index a07441a0a878..65efe5fa687c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -143,6 +143,31 @@ static int ecryptfs_interpose(struct dentry *lower_dentry, return 0; } +static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, + struct inode *inode) +{ + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); + struct dentry *lower_dir_dentry; + int rc; + + dget(lower_dentry); + lower_dir_dentry = lock_parent(lower_dentry); + rc = vfs_unlink(lower_dir_inode, lower_dentry); + if (rc) { + printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); + goto out_unlock; + } + fsstack_copy_attr_times(dir, lower_dir_inode); + set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink); + inode->i_ctime = dir->i_ctime; + d_drop(dentry); +out_unlock: + unlock_dir(lower_dir_dentry); + dput(lower_dentry); + return rc; +} + /** * ecryptfs_do_create * @directory_inode: inode of the new file's dentry's parent in ecryptfs @@ -182,8 +207,10 @@ ecryptfs_do_create(struct inode *directory_inode, } inode = __ecryptfs_get_inode(lower_dentry->d_inode, directory_inode->i_sb); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); goto out_lock; + } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: @@ -265,7 +292,9 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, * that this on disk file is prepared to be an ecryptfs file */ rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); if (rc) { - drop_nlink(ecryptfs_inode); + ecryptfs_do_unlink(directory_inode, ecryptfs_dentry, + ecryptfs_inode); + make_bad_inode(ecryptfs_inode); unlock_new_inode(ecryptfs_inode); iput(ecryptfs_inode); goto out; @@ -477,27 +506,7 @@ out_lock: static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) { - int rc = 0; - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); - struct dentry *lower_dir_dentry; - - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry); - if (rc) { - printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); - goto out_unlock; - } - fsstack_copy_attr_times(dir, lower_dir_inode); - set_nlink(dentry->d_inode, - ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink); - dentry->d_inode->i_ctime = dir->i_ctime; - d_drop(dentry); -out_unlock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - return rc; + return ecryptfs_do_unlink(dir, dentry, dentry->d_inode); } static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, -- GitLab From e3ccaa9761200952cc269b1f4b7d7bb77a5e071b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 20 Jun 2012 23:50:59 -0700 Subject: [PATCH 2193/5711] eCryptfs: Initialize empty lower files when opening them Historically, eCryptfs has only initialized lower files in the ecryptfs_create() path. Lower file initialization is the act of writing the cryptographic metadata from the inode's crypt_stat to the header of the file. The ecryptfs_open() path already expects that metadata to be in the header of the file. A number of users have reported empty lower files in beneath their eCryptfs mounts. Most of the causes for those empty files being left around have been addressed, but the presence of empty files causes problems due to the lack of proper cryptographic metadata. To transparently solve this problem, this patch initializes empty lower files in the ecryptfs_open() error path. If the metadata is unreadable due to the lower inode size being 0, plaintext passthrough support is not in use, and the metadata is stored in the header of the file (as opposed to the user.ecryptfs extended attribute), the lower file will be initialized. The number of nested conditionals in ecryptfs_open() was getting out of hand, so a helper function was created. To avoid the same nested conditional problem, the conditional logic was reversed inside of the helper function. https://launchpad.net/bugs/911507 Signed-off-by: Tyler Hicks Cc: John Johansen Cc: Colin Ian King --- fs/ecryptfs/ecryptfs_kernel.h | 2 + fs/ecryptfs/file.c | 71 ++++++++++++++++++++++------------- fs/ecryptfs/inode.c | 4 +- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 0deb4f24957a..9f77ff818173 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -563,6 +563,8 @@ struct ecryptfs_open_req { struct inode *ecryptfs_get_inode(struct inode *lower_inode, struct super_block *sb); void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode); int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, size_t *decrypted_name_size, struct dentry *ecryptfs_dentry, diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 2b17f2f9b121..baf8b0550391 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -161,6 +161,48 @@ static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) struct kmem_cache *ecryptfs_file_info_cache; +static int read_or_initialize_metadata(struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; + int rc; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + mount_crypt_stat = &ecryptfs_superblock_to_private( + inode->i_sb)->mount_crypt_stat; + mutex_lock(&crypt_stat->cs_mutex); + + if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED && + crypt_stat->flags & ECRYPTFS_KEY_VALID) { + rc = 0; + goto out; + } + + rc = ecryptfs_read_metadata(dentry); + if (!rc) + goto out; + + if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) { + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); + rc = 0; + goto out; + } + + if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) && + !i_size_read(ecryptfs_inode_to_lower(inode))) { + rc = ecryptfs_initialize_file(dentry, inode); + if (!rc) + goto out; + } + + rc = -EIO; +out: + mutex_unlock(&crypt_stat->cs_mutex); + return rc; +} + /** * ecryptfs_open * @inode: inode speciying file to open @@ -236,32 +278,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) rc = 0; goto out; } - mutex_lock(&crypt_stat->cs_mutex); - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - rc = ecryptfs_read_metadata(ecryptfs_dentry); - if (rc) { - ecryptfs_printk(KERN_DEBUG, - "Valid headers not found\n"); - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; - printk(KERN_WARNING "Either the lower file " - "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " - "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out_put; - } - rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED - | ECRYPTFS_ENCRYPTED); - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - } - mutex_unlock(&crypt_stat->cs_mutex); + rc = read_or_initialize_metadata(ecryptfs_dentry); + if (rc) + goto out_put; ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, (unsigned long long)i_size_read(inode)); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 65efe5fa687c..2d4143f8f5c9 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -227,8 +227,8 @@ out: * * Returns zero on success */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode) +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; -- GitLab From e1dc7bee745f74b42685b4b0b0a24895966e545e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Jul 2012 14:52:56 +0200 Subject: [PATCH 2194/5711] iio: iio_buffer_register: Use correct channel when calculating masklength The channel set assigned to the iio device is not necessarily the same has the channel set passed to iio_buffer_register. So to avoid possible complications always work with the channel set pass to iio_buffer_register and ignore the channel set assigned to the iio device. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 3d8d187eef2a..096a6bfe0cdf 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -292,7 +292,7 @@ int iio_buffer_register(struct iio_dev *indio_dev, if (channels[i].scan_index > (int)indio_dev->masklength - 1) indio_dev->masklength - = indio_dev->channels[i].scan_index + 1; + = channels[i].scan_index + 1; ret = iio_buffer_add_channel_sysfs(indio_dev, &channels[i]); -- GitLab From a91aff1c09fc41a55ccaa115763ff77e36b527d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Jul 2012 10:54:45 +0200 Subject: [PATCH 2195/5711] staging:iio: Request threaded-only IRQs with IRQF_ONESHOT Since commit 1c6c69525b ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. This patch adds the IRQF_ONESHOT to IIO drivers where it is missing. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/sca3000_core.c | 2 +- drivers/staging/iio/adc/ad7816.c | 2 +- drivers/staging/iio/adc/adt7310.c | 5 +++-- drivers/staging/iio/adc/adt7410.c | 5 +++-- drivers/staging/iio/cdc/ad7150.c | 6 ++++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 6ec5c204ff1d..c218d71abf1f 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1189,7 +1189,7 @@ static int __devinit sca3000_probe(struct spi_device *spi) ret = request_threaded_irq(spi->irq, NULL, &sca3000_event_handler, - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "sca3000", indio_dev); if (ret) diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 5356b091b08f..c5fb9476a2d1 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -402,7 +402,7 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) ret = request_threaded_irq(spi_dev->irq, NULL, &ad7816_event_handler, - IRQF_TRIGGER_LOW, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, indio_dev->name, indio_dev); if (ret) diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index e5f1ed7f8696..44dcf632f54d 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -778,7 +778,7 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) ret = request_threaded_irq(spi_dev->irq, NULL, &adt7310_event_handler, - irq_flags, + irq_flags | IRQF_ONESHOT, indio_dev->name, indio_dev); if (ret) @@ -790,7 +790,8 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) ret = request_threaded_irq(adt7310_platform_data[0], NULL, &adt7310_event_handler, - adt7310_platform_data[1], + adt7310_platform_data[1] | + IRQF_ONESHOT, indio_dev->name, indio_dev); if (ret) diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index 917b6921e24d..a2defe64d10b 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -742,7 +742,7 @@ static int __devinit adt7410_probe(struct i2c_client *client, ret = request_threaded_irq(client->irq, NULL, &adt7410_event_handler, - IRQF_TRIGGER_LOW, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, id->name, indio_dev); if (ret) @@ -754,7 +754,8 @@ static int __devinit adt7410_probe(struct i2c_client *client, ret = request_threaded_irq(adt7410_platform_data[0], NULL, &adt7410_event_handler, - adt7410_platform_data[1], + adt7410_platform_data[1] | + IRQF_ONESHOT, id->name, indio_dev); if (ret) diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index a16d1a22db0a..6a4041417d4e 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -585,7 +585,8 @@ static int __devinit ad7150_probe(struct i2c_client *client, NULL, &ad7150_event_handler, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "ad7150_irq1", indio_dev); if (ret) @@ -598,7 +599,8 @@ static int __devinit ad7150_probe(struct i2c_client *client, NULL, &ad7150_event_handler, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "ad7150_irq2", indio_dev); if (ret) -- GitLab From 46b24311ccc8b37da9e6e006c6158229a5354268 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 3 Jul 2012 10:55:40 +0200 Subject: [PATCH 2196/5711] iio: Fix unitialized use of list The dev_attr list is initialized in __iio_add_event_config_attrs which is called only when indio_dev->channels is true. Nevertheless the list is used unconditionally later in iio_device_register_eventset which results in a NULL pointer exception. To fix this unconditionally initialize the list in iio_device_register_eventset. Signed-off-by: Sascha Hauer Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index b49059de5d02..fa6543bf6731 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -345,7 +345,6 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) { int j, ret, attrcount = 0; - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); /* Dynically created from the channels array */ for (j = 0; j < indio_dev->num_channels; j++) { ret = iio_device_add_event_sysfs(indio_dev, @@ -396,6 +395,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) goto error_ret; } + INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); + iio_setup_ev_int(indio_dev->event_interface); if (indio_dev->info->event_attrs != NULL) { attr = indio_dev->info->event_attrs->attrs; -- GitLab From 3a427d184f22e0ebfbed1eb82114ece8fb58bd95 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 3 Jul 2012 11:21:26 +0200 Subject: [PATCH 2197/5711] staging iio adt7410: sysfs store function must return length Otherwise a write to the resolution entry never returns. Signed-off-by: Sascha Hauer Acked-by: Sonic Zhang Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/adt7410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index a2defe64d10b..9025161dfe0e 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -257,7 +257,7 @@ static ssize_t adt7410_store_resolution(struct device *dev, chip->config = config; - return ret; + return len; } static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, -- GitLab From 1764eff7d5d644310b87d7040c83fe5208c155f7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 3 Jul 2012 11:21:27 +0200 Subject: [PATCH 2198/5711] staging iio adt7410: fix 13bit mode The driver assumes that in 13bit mode the 16bit value has to be shifted to the right by 3 bits. This is not true, in both 16bit and 13bit mode the MSB is at the same position. Currently the driver returns a temperature of 194 degrees Celsius in 13bit mode and 24 degrees Celsius in 16bit mode. Fix this by using the same algorithm for 16bit and 13bit mode and by just masking out the lower three bits in 13bit mode. Signed-off-by: Sascha Hauer Acked-by: Sonic Zhang Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/adt7410.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index 9025161dfe0e..f87992cd1acc 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -293,26 +293,17 @@ static ssize_t adt7410_convert_temperature(struct adt7410_chip_info *chip, { char sign = ' '; - if (chip->config & ADT7410_RESOLUTION) { - if (data & ADT7410_T16_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); - sign = '-'; - } - return sprintf(buf, "%c%d.%.7d\n", sign, - (data >> ADT7410_T16_VALUE_FLOAT_OFFSET), - (data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125); - } else { - if (data & ADT7410_T13_VALUE_SIGN) { - /* convert supplement to positive value */ - data >>= ADT7410_T13_VALUE_OFFSET; - data = (ADT7410_T13_VALUE_SIGN << 1) - data; - sign = '-'; - } - return sprintf(buf, "%c%d.%.4d\n", sign, - (data >> ADT7410_T13_VALUE_FLOAT_OFFSET), - (data & ADT7410_T13_VALUE_FLOAT_MASK) * 625); + if (!(chip->config & ADT7410_RESOLUTION)) + data &= ~0x7; + + if (data & ADT7410_T16_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); + sign = '-'; } + return sprintf(buf, "%c%d.%.7d\n", sign, + (data >> ADT7410_T16_VALUE_FLOAT_OFFSET), + (data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125); } static ssize_t adt7410_show_value(struct device *dev, -- GitLab From abad65cbb2b53be39e8f55f9511cc53756860b1c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2199/5711] staging:iio:ad7298: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7298_ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index cd3e9cb47a64..fd1d855ff57a 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -82,7 +82,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) b_sent = spi_sync(st->spi, &st->ring_msg); if (b_sent) - return b_sent; + goto done; if (indio_dev->scan_timestamp) { time_ns = iio_get_time_ns(); @@ -95,6 +95,8 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) buf[i] = be16_to_cpu(st->rx_buf[i]); indio_dev->buffer->access->store_to(ring, (u8 *)buf, time_ns); + +done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; -- GitLab From a4eef3057dff597099673c42f8e3d0455deb9fe1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2200/5711] staging:iio:adt7310: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/adt7310.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index 44dcf632f54d..72460b6dc2f4 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -397,7 +397,7 @@ static irqreturn_t adt7310_event_handler(int irq, void *private) ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); if (ret) - return ret; + goto done; if (status & ADT7310_STAT_T_HIGH) iio_push_event(indio_dev, @@ -417,6 +417,8 @@ static irqreturn_t adt7310_event_handler(int irq, void *private) IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); + +done: return IRQ_HANDLED; } -- GitLab From a1bdeefd7bccabb265fa9c74811008a8582c1c7d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2201/5711] staging:iio:dummy driver: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/iio_simple_dummy_buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index b9e6093f6543..c0951f9f8a2f 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -52,7 +52,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) - return -ENOMEM; + goto done; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { /* @@ -91,6 +91,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) kfree(data); +done: /* * Tell the core we are done with this trigger and ready for the * next one. -- GitLab From f654a7e2b2106aec324f931fb802ffe191a460dd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2202/5711] staging:iio:ad799x: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad799x_core.c | 5 +++-- drivers/staging/iio/adc/ad799x_ring.c | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 2d4bda99eff7..990050700afc 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -350,10 +350,10 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status); if (ret) - return ret; + goto done; if (!status) - return -EIO; + goto done; ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR); @@ -372,6 +372,7 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) iio_get_time_ns()); } +done: return IRQ_HANDLED; } diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 0882c9ef6572..858a685e3889 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -81,8 +81,6 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) ring->access->store_to(indio_dev->buffer, rxbuf, time_ns); done: kfree(rxbuf); - if (b_sent < 0) - return b_sent; out: iio_trigger_notify_done(indio_dev->trig); -- GitLab From 9c586a4ce57b0ac1fbfbc378cd61c7274b703393 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2203/5711] staging:iio:ad7476: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7476_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 10f8b8dd1fa4..d087b21c51f6 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -31,7 +31,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) rxbuf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); if (rxbuf == NULL) - return -ENOMEM; + goto done; b_sent = spi_read(st->spi, rxbuf, st->chip_info->channel[0].scan_type.storagebits / 8); -- GitLab From 46b2495cc79484769e6c9364bf8f2e8b8e9de1aa Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2204/5711] staging:iio:ad7887: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 1c406dad0e67..c76fdb5081c2 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -82,7 +82,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); if (buf == NULL) - return -ENOMEM; + goto done; b_sent = spi_sync(st->spi, st->ring_msg); if (b_sent) -- GitLab From da0f01e1ed88b4ac650d884e4e2ee11c9cd4d83b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2205/5711] staging:iio:max1363: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/max1363_ring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index b30201300121..bf6b0c2eb9e9 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -64,11 +64,11 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) * no harm. */ if (numvals == 0) - return IRQ_HANDLED; + goto done; rxbuf = kmalloc(d_size, GFP_KERNEL); if (rxbuf == NULL) - return -ENOMEM; + goto done; if (st->chip_info->bits != 8) b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); else -- GitLab From 0b30246ef17c2e37819068aec3d5eac4ac06b562 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2206/5711] staging:iio:lis3l02dq: Do not return error code in interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq_ring.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 51b00dfc0465..d7f8af7678fd 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -143,7 +143,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) if (data == NULL) { dev_err(indio_dev->dev.parent, "memory alloc failed in buffer bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) @@ -156,8 +156,9 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) = pf->timestamp; buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } -- GitLab From 67bd5e26d44a5282d46719325b25deedebc39b2e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2207/5711] staging:iio:accel:adis16xxx: Do not return error code in the interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201_ring.c | 5 +++-- drivers/staging/iio/accel/adis16203_ring.c | 5 +++-- drivers/staging/iio/accel/adis16204_ring.c | 5 +++-- drivers/staging/iio/accel/adis16209_ring.c | 5 +++-- drivers/staging/iio/accel/adis16240_ring.c | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 247602a8e54c..03fcf6e319db 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -70,7 +70,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) @@ -85,8 +85,9 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) ring->access->store_to(ring, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index 7bbd2c2bbd19..c16b2b7323ac 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -69,7 +69,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && @@ -86,8 +86,9 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index f73518bc6587..1d2b31cc849e 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -66,7 +66,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && @@ -81,8 +81,9 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) ring->access->store_to(ring, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 090607504c93..1a4a55c27c7c 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -66,7 +66,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && @@ -81,8 +81,9 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) ring->access->store_to(ring, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index 86a2a4757ea7..360dfed6d4d1 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -64,7 +64,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && @@ -79,8 +79,9 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) ring->access->store_to(ring, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } -- GitLab From b82ed7d6805ef2a31503999edc80787083d4426f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2208/5711] staging:iio:adis16260: Do not return error code in the interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adis16260_ring.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index 0fe2d9dfb6cd..eeee8e760e6c 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -69,7 +69,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && @@ -84,8 +84,9 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) ring->access->store_to(ring, (u8 *)data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } -- GitLab From 462c8d27940d1d41f76091544245b0af11b64c81 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 4 Jul 2012 17:09:00 +0100 Subject: [PATCH 2209/5711] staging:iio:adis16400: Do not return error code in the interrupt handler The interrupt handler should only ever return one of the three irqreturn_t constants and not an error code. Also make sure to always call iio_trigger_notify_done before leaving the trigger handler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/adis16400_ring.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 809e2c4270d1..beec650ddbdb 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -125,20 +125,20 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) { dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; + goto done; } if (scan_count) { if (st->variant->flags & ADIS16400_NO_BURST) { ret = adis16350_spi_read_all(indio_dev, st->rx); if (ret < 0) - goto err; + goto done; for (; i < scan_count; i++) data[i] = *(s16 *)(st->rx + i*2); } else { ret = adis16400_spi_read_burst(indio_dev, st->rx); if (ret < 0) - goto err; + goto done; for (; i < scan_count; i++) { j = __ffs(mask); mask &= ~(1 << j); @@ -152,14 +152,11 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; ring->access->store_to(indio_dev->buffer, (u8 *) data, pf->timestamp); +done: + kfree(data); iio_trigger_notify_done(indio_dev->trig); - kfree(data); return IRQ_HANDLED; - -err: - kfree(data); - return ret; } void adis16400_unconfigure_ring(struct iio_dev *indio_dev) -- GitLab From 7b7627410e2c211f24787f61e6419e16d259aa13 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 30 Jun 2012 13:55:23 +0100 Subject: [PATCH 2210/5711] iio: Fix inkern remove incorrect put of device The device_get is after this point so on error we should not be removing it. Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 9a46ca61ef02..e2aded04996b 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -193,7 +193,6 @@ struct iio_channel *iio_channel_get_all(const char *name) c->map->adc_channel_label); if (chans[mapind].channel == NULL) { ret = -EINVAL; - iio_device_put(chans[mapind].indio_dev); goto error_free_chans; } iio_device_get(chans[mapind].indio_dev); -- GitLab From 70523b4e57cb6eeb1da7c8ebf19df855221825ad Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 6 Jul 2012 20:08:15 +0900 Subject: [PATCH 2211/5711] ARM: mach-shmobile: armadillo800eva: defconfig Allow use of armhf userspace This allows use a Debian armhf usespace as well as the existing ability to use a Debian armel userspace. Signed-off-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/configs/armadillo800eva_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig index 16bbb3f8f234..7d8718468e0d 100644 --- a/arch/arm/configs/armadillo800eva_defconfig +++ b/arch/arm/configs/armadillo800eva_defconfig @@ -18,7 +18,7 @@ CONFIG_ARCH_SHMOBILE=y CONFIG_ARCH_R8A7740=y CONFIG_MACH_ARMADILLO800EVA=y # CONFIG_SH_TIMER_TMU is not set -# CONFIG_ARM_THUMB is not set +CONFIG_ARM_THUMB=y CONFIG_CPU_BPREDICT_DISABLE=y # CONFIG_CACHE_L2X0 is not set CONFIG_ARM_ERRATA_430973=y @@ -36,6 +36,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" CONFIG_CMDLINE_FORCE=y CONFIG_KEXEC=y +CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SUSPEND is not set CONFIG_NET=y -- GitLab From dae8a969d512ee15e08fbec7837b9dab1777896d Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Mon, 25 Jun 2012 10:34:36 +0200 Subject: [PATCH 2212/5711] mfd: Add Maxim 77686 driver This patch is device driver for MAX77686 chip. MAX77686 is PMIC and includes regulator and rtc on it. This driver is core of MAX77686 chip, so provides common support for accessing on-chip devices. It uses irq_domain to manage irq and regmap to read/write data to its register with i2c bus. Signed-off-by: Chiwoong Byun Signed-off-by: Jonghwa Lee Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Reviewed-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 13 ++ drivers/mfd/Makefile | 1 + drivers/mfd/max77686-irq.c | 309 +++++++++++++++++++++++++++ drivers/mfd/max77686.c | 156 ++++++++++++++ include/linux/mfd/max77686-private.h | 247 +++++++++++++++++++++ include/linux/mfd/max77686.h | 117 ++++++++++ 6 files changed, 843 insertions(+) create mode 100644 drivers/mfd/max77686-irq.c create mode 100644 drivers/mfd/max77686.c create mode 100644 include/linux/mfd/max77686-private.h create mode 100644 include/linux/mfd/max77686.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index e129c820df7d..a7d0c851afc5 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -422,6 +422,19 @@ config PMIC_ADP5520 individual components like LCD backlight, LEDs, GPIOs and Kepad under the corresponding menus. +config MFD_MAX77686 + bool "Maxim Semiconductor MAX77686 PMIC Support" + depends on I2C=y && GENERIC_HARDIRQS + select MFD_CORE + select REGMAP_I2C + select IRQ_DOMAIN + help + Say yes here to support for Maxim Semiconductor MAX77686. + This is a Power Management IC with RTC on chip. + This driver provides common support for accessing the device; + additional drivers must be enabled in order to use the functionality + of the device. + config MFD_MAX77693 bool "Maxim Semiconductor MAX77693 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 75f6ed68a4b9..8ee7a3bf595b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o +obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o max8925-objs := max8925-core.o max8925-i2c.o obj-$(CONFIG_MFD_MAX8925) += max8925.o diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c new file mode 100644 index 000000000000..fc101220f990 --- /dev/null +++ b/drivers/mfd/max77686-irq.c @@ -0,0 +1,309 @@ +/* + * max77686-irq.c - Interrupt controller support for MAX77686 + * + * Copyright (C) 2012 Samsung Electronics Co.Ltd + * Chiwoong Byun + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This driver is based on max8997-irq.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + MAX77686_DEBUG_IRQ_INFO = 1 << 0, + MAX77686_DEBUG_IRQ_MASK = 1 << 1, + MAX77686_DEBUG_IRQ_INT = 1 << 2, +}; + +static int debug_mask = 0; +module_param(debug_mask, int, 0); +MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)"); + +static const u8 max77686_mask_reg[] = { + [PMIC_INT1] = MAX77686_REG_INT1MSK, + [PMIC_INT2] = MAX77686_REG_INT2MSK, + [RTC_INT] = MAX77686_RTC_INTM, +}; + +static struct regmap *max77686_get_regmap(struct max77686_dev *max77686, + enum max77686_irq_source src) +{ + switch (src) { + case PMIC_INT1 ... PMIC_INT2: + return max77686->regmap; + case RTC_INT: + return max77686->rtc_regmap; + default: + return ERR_PTR(-EINVAL); + } +} + +struct max77686_irq_data { + int mask; + enum max77686_irq_source group; +}; + +#define DECLARE_IRQ(idx, _group, _mask) \ + [(idx)] = { .group = (_group), .mask = (_mask) } +static const struct max77686_irq_data max77686_irqs[] = { + DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0), + DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1), + DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2), + DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3), + DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4), + DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5), + DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6), + DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7), + DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0), + DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1), + DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0), + DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1), + DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2), + DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3), + DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4), + DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5), +}; + +static void max77686_irq_lock(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s\n", __func__); + + mutex_lock(&max77686->irqlock); +} + +static void max77686_irq_sync_unlock(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + int i; + + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { + u8 mask_reg = max77686_mask_reg[i]; + struct regmap *map = max77686_get_regmap(max77686, i); + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n", + __func__, i, mask_reg, max77686->irq_masks_cur[i]); + + if (mask_reg == MAX77686_REG_INVALID || + IS_ERR_OR_NULL(map)) + continue; + + max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i]; + + regmap_write(map, max77686_mask_reg[i], + max77686->irq_masks_cur[i]); + } + + mutex_unlock(&max77686->irqlock); +} + +static const inline struct max77686_irq_data *to_max77686_irq(int irq) +{ + struct irq_data *data = irq_get_irq_data(irq); + return &max77686_irqs[data->hwirq]; +} + +static void max77686_irq_mask(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); + + max77686->irq_masks_cur[irq_data->group] |= irq_data->mask; + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s: group=%d, cur=0x%x\n", + __func__, irq_data->group, + max77686->irq_masks_cur[irq_data->group]); +} + +static void max77686_irq_unmask(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); + + max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask; + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s: group=%d, cur=0x%x\n", + __func__, irq_data->group, + max77686->irq_masks_cur[irq_data->group]); +} + +static struct irq_chip max77686_irq_chip = { + .name = "max77686", + .irq_bus_lock = max77686_irq_lock, + .irq_bus_sync_unlock = max77686_irq_sync_unlock, + .irq_mask = max77686_irq_mask, + .irq_unmask = max77686_irq_unmask, +}; + +static irqreturn_t max77686_irq_thread(int irq, void *data) +{ + struct max77686_dev *max77686 = data; + unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {}; + unsigned int irq_src; + int ret; + int i, cur_irq; + + ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: irq_src=0x%x\n", __func__, irq_src); + + if (irq_src == MAX77686_IRQSRC_PMIC) { + ret = regmap_bulk_read(max77686->rtc_regmap, + MAX77686_REG_INT1, irq_reg, 2); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: int1=0x%x, int2=0x%x\n", __func__, + irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]); + } + + if (irq_src & MAX77686_IRQSRC_RTC) { + ret = regmap_read(max77686->rtc_regmap, + MAX77686_RTC_INT, &irq_reg[RTC_INT]); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: rtc int=0x%x\n", __func__, + irq_reg[RTC_INT]); + + } + + for (i = 0; i < MAX77686_IRQ_NR; i++) { + if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) { + cur_irq = irq_find_mapping(max77686->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); + } + } + + return IRQ_HANDLED; +} + +static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max77686_dev *max77686 = d->host_data; + + irq_set_chip_data(irq, max77686); + irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + return 0; +} + +static struct irq_domain_ops max77686_irq_domain_ops = { + .map = max77686_irq_domain_map, +}; + +int max77686_irq_init(struct max77686_dev *max77686) +{ + struct irq_domain *domain; + int i; + int ret; + int val; + struct regmap *map; + + mutex_init(&max77686->irqlock); + + max77686->irq = gpio_to_irq(max77686->irq_gpio); + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) { + ret = gpio_request(max77686->irq_gpio, "pmic_irq"); + if (ret < 0) { + dev_err(max77686->dev, + "Failed to request gpio %d with ret: %d\n", + max77686->irq_gpio, ret); + return IRQ_NONE; + } + + gpio_direction_input(max77686->irq_gpio); + val = gpio_get_value(max77686->irq_gpio); + gpio_free(max77686->irq_gpio); + pr_info("%s: gpio_irq=%x\n", __func__, val); + } + + /* Mask individual interrupt sources */ + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { + max77686->irq_masks_cur[i] = 0xff; + max77686->irq_masks_cache[i] = 0xff; + map = max77686_get_regmap(max77686, i); + + if (IS_ERR_OR_NULL(map)) + continue; + if (max77686_mask_reg[i] == MAX77686_REG_INVALID) + continue; + + regmap_write(map, max77686_mask_reg[i], 0xff); + } + domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR, + &max77686_irq_domain_ops, max77686); + if (!domain) { + dev_err(max77686->dev, "could not create irq domain\n"); + return -ENODEV; + } + max77686->irq_domain = domain; + + ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "max77686-irq", max77686); + + if (ret) + dev_err(max77686->dev, "Failed to request IRQ %d: %d\n", + max77686->irq, ret); + + + if (debug_mask & MAX77686_DEBUG_IRQ_INFO) + pr_info("%s-\n", __func__); + + return 0; +} + +void max77686_irq_exit(struct max77686_dev *max77686) +{ + if (max77686->irq) + free_irq(max77686->irq, max77686); +} diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c new file mode 100644 index 000000000000..11e56017e0b0 --- /dev/null +++ b/drivers/mfd/max77686.c @@ -0,0 +1,156 @@ +/* + * max77686.c - mfd core driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun + * Jonghwa Lee + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This driver is based on max8997.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_ADDR_RTC (0x0C >> 1) + +static struct mfd_cell max77686_devs[] = { + { .name = "max77686-pmic", }, + { .name = "max77686-rtc", }, +}; + +static struct regmap_config max77686_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int max77686_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct max77686_dev *max77686; + struct max77686_platform_data *pdata = i2c->dev.platform_data; + unsigned int data; + int ret = 0; + + max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL); + if (max77686 == NULL) + return -ENOMEM; + + max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); + if (IS_ERR(max77686->regmap)) { + ret = PTR_ERR(max77686->regmap); + dev_err(max77686->dev, "Failed to allocate register map: %d\n", + ret); + kfree(max77686); + return ret; + } + + i2c_set_clientdata(i2c, max77686); + max77686->dev = &i2c->dev; + max77686->i2c = i2c; + max77686->type = id->driver_data; + + if (!pdata) { + ret = -EIO; + goto err; + } + + max77686->wakeup = pdata->wakeup; + max77686->irq_gpio = pdata->irq_gpio; + + mutex_init(&max77686->iolock); + + if (regmap_read(max77686->regmap, + MAX77686_REG_DEVICE_ID, &data) < 0) { + dev_err(max77686->dev, + "device not found on this channel (this is not an error)\n"); + ret = -ENODEV; + goto err; + } else + dev_info(max77686->dev, "device found\n"); + + max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); + i2c_set_clientdata(max77686->rtc, max77686); + + max77686_irq_init(max77686); + + ret = mfd_add_devices(max77686->dev, -1, max77686_devs, + ARRAY_SIZE(max77686_devs), NULL, 0); + + if (ret < 0) + goto err_mfd; + + return ret; + +err_mfd: + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); +err: + kfree(max77686); + return ret; +} + +static int max77686_i2c_remove(struct i2c_client *i2c) +{ + struct max77686_dev *max77686 = i2c_get_clientdata(i2c); + + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); + kfree(max77686); + + return 0; +} + +static const struct i2c_device_id max77686_i2c_id[] = { + { "max77686", TYPE_MAX77686 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max77686_i2c_id); + +static struct i2c_driver max77686_i2c_driver = { + .driver = { + .name = "max77686", + .owner = THIS_MODULE, + }, + .probe = max77686_i2c_probe, + .remove = max77686_i2c_remove, + .id_table = max77686_i2c_id, +}; + +static int __init max77686_i2c_init(void) +{ + return i2c_add_driver(&max77686_i2c_driver); +} +/* init early so consumer devices can complete system boot */ +subsys_initcall(max77686_i2c_init); + +static void __exit max77686_i2c_exit(void) +{ + i2c_del_driver(&max77686_i2c_driver); +} +module_exit(max77686_i2c_exit); + +MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver"); +MODULE_AUTHOR("Chiwoong Byun "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/max77686-private.h b/include/linux/mfd/max77686-private.h new file mode 100644 index 000000000000..962f65e72b71 --- /dev/null +++ b/include/linux/mfd/max77686-private.h @@ -0,0 +1,247 @@ +/* + * max77686.h - Voltage regulator driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electrnoics + * Chiwoong Byun + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_MFD_MAX77686_PRIV_H +#define __LINUX_MFD_MAX77686_PRIV_H + +#include +#include +#include + +#define MAX77686_REG_INVALID (0xff) + +enum max77686_pmic_reg { + MAX77686_REG_DEVICE_ID = 0x00, + MAX77686_REG_INTSRC = 0x01, + MAX77686_REG_INT1 = 0x02, + MAX77686_REG_INT2 = 0x03, + + MAX77686_REG_INT1MSK = 0x04, + MAX77686_REG_INT2MSK = 0x05, + + MAX77686_REG_STATUS1 = 0x06, + MAX77686_REG_STATUS2 = 0x07, + + MAX77686_REG_PWRON = 0x08, + MAX77686_REG_ONOFF_DELAY = 0x09, + MAX77686_REG_MRSTB = 0x0A, + /* Reserved: 0x0B-0x0F */ + + MAX77686_REG_BUCK1CTRL = 0x10, + MAX77686_REG_BUCK1OUT = 0x11, + MAX77686_REG_BUCK2CTRL1 = 0x12, + MAX77686_REG_BUCK234FREQ = 0x13, + MAX77686_REG_BUCK2DVS1 = 0x14, + MAX77686_REG_BUCK2DVS2 = 0x15, + MAX77686_REG_BUCK2DVS3 = 0x16, + MAX77686_REG_BUCK2DVS4 = 0x17, + MAX77686_REG_BUCK2DVS5 = 0x18, + MAX77686_REG_BUCK2DVS6 = 0x19, + MAX77686_REG_BUCK2DVS7 = 0x1A, + MAX77686_REG_BUCK2DVS8 = 0x1B, + MAX77686_REG_BUCK3CTRL1 = 0x1C, + /* Reserved: 0x1D */ + MAX77686_REG_BUCK3DVS1 = 0x1E, + MAX77686_REG_BUCK3DVS2 = 0x1F, + MAX77686_REG_BUCK3DVS3 = 0x20, + MAX77686_REG_BUCK3DVS4 = 0x21, + MAX77686_REG_BUCK3DVS5 = 0x22, + MAX77686_REG_BUCK3DVS6 = 0x23, + MAX77686_REG_BUCK3DVS7 = 0x24, + MAX77686_REG_BUCK3DVS8 = 0x25, + MAX77686_REG_BUCK4CTRL1 = 0x26, + /* Reserved: 0x27 */ + MAX77686_REG_BUCK4DVS1 = 0x28, + MAX77686_REG_BUCK4DVS2 = 0x29, + MAX77686_REG_BUCK4DVS3 = 0x2A, + MAX77686_REG_BUCK4DVS4 = 0x2B, + MAX77686_REG_BUCK4DVS5 = 0x2C, + MAX77686_REG_BUCK4DVS6 = 0x2D, + MAX77686_REG_BUCK4DVS7 = 0x2E, + MAX77686_REG_BUCK4DVS8 = 0x2F, + MAX77686_REG_BUCK5CTRL = 0x30, + MAX77686_REG_BUCK5OUT = 0x31, + MAX77686_REG_BUCK6CTRL = 0x32, + MAX77686_REG_BUCK6OUT = 0x33, + MAX77686_REG_BUCK7CTRL = 0x34, + MAX77686_REG_BUCK7OUT = 0x35, + MAX77686_REG_BUCK8CTRL = 0x36, + MAX77686_REG_BUCK8OUT = 0x37, + MAX77686_REG_BUCK9CTRL = 0x38, + MAX77686_REG_BUCK9OUT = 0x39, + /* Reserved: 0x3A-0x3F */ + + MAX77686_REG_LDO1CTRL1 = 0x40, + MAX77686_REG_LDO2CTRL1 = 0x41, + MAX77686_REG_LDO3CTRL1 = 0x42, + MAX77686_REG_LDO4CTRL1 = 0x43, + MAX77686_REG_LDO5CTRL1 = 0x44, + MAX77686_REG_LDO6CTRL1 = 0x45, + MAX77686_REG_LDO7CTRL1 = 0x46, + MAX77686_REG_LDO8CTRL1 = 0x47, + MAX77686_REG_LDO9CTRL1 = 0x48, + MAX77686_REG_LDO10CTRL1 = 0x49, + MAX77686_REG_LDO11CTRL1 = 0x4A, + MAX77686_REG_LDO12CTRL1 = 0x4B, + MAX77686_REG_LDO13CTRL1 = 0x4C, + MAX77686_REG_LDO14CTRL1 = 0x4D, + MAX77686_REG_LDO15CTRL1 = 0x4E, + MAX77686_REG_LDO16CTRL1 = 0x4F, + MAX77686_REG_LDO17CTRL1 = 0x50, + MAX77686_REG_LDO18CTRL1 = 0x51, + MAX77686_REG_LDO19CTRL1 = 0x52, + MAX77686_REG_LDO20CTRL1 = 0x53, + MAX77686_REG_LDO21CTRL1 = 0x54, + MAX77686_REG_LDO22CTRL1 = 0x55, + MAX77686_REG_LDO23CTRL1 = 0x56, + MAX77686_REG_LDO24CTRL1 = 0x57, + MAX77686_REG_LDO25CTRL1 = 0x58, + MAX77686_REG_LDO26CTRL1 = 0x59, + /* Reserved: 0x5A-0x5F */ + MAX77686_REG_LDO1CTRL2 = 0x60, + MAX77686_REG_LDO2CTRL2 = 0x61, + MAX77686_REG_LDO3CTRL2 = 0x62, + MAX77686_REG_LDO4CTRL2 = 0x63, + MAX77686_REG_LDO5CTRL2 = 0x64, + MAX77686_REG_LDO6CTRL2 = 0x65, + MAX77686_REG_LDO7CTRL2 = 0x66, + MAX77686_REG_LDO8CTRL2 = 0x67, + MAX77686_REG_LDO9CTRL2 = 0x68, + MAX77686_REG_LDO10CTRL2 = 0x69, + MAX77686_REG_LDO11CTRL2 = 0x6A, + MAX77686_REG_LDO12CTRL2 = 0x6B, + MAX77686_REG_LDO13CTRL2 = 0x6C, + MAX77686_REG_LDO14CTRL2 = 0x6D, + MAX77686_REG_LDO15CTRL2 = 0x6E, + MAX77686_REG_LDO16CTRL2 = 0x6F, + MAX77686_REG_LDO17CTRL2 = 0x70, + MAX77686_REG_LDO18CTRL2 = 0x71, + MAX77686_REG_LDO19CTRL2 = 0x72, + MAX77686_REG_LDO20CTRL2 = 0x73, + MAX77686_REG_LDO21CTRL2 = 0x74, + MAX77686_REG_LDO22CTRL2 = 0x75, + MAX77686_REG_LDO23CTRL2 = 0x76, + MAX77686_REG_LDO24CTRL2 = 0x77, + MAX77686_REG_LDO25CTRL2 = 0x78, + MAX77686_REG_LDO26CTRL2 = 0x79, + /* Reserved: 0x7A-0x7D */ + + MAX77686_REG_BBAT_CHG = 0x7E, + MAX77686_REG_32KHZ = 0x7F, + + MAX77686_REG_PMIC_END = 0x80, +}; + +enum max77686_rtc_reg { + MAX77686_RTC_INT = 0x00, + MAX77686_RTC_INTM = 0x01, + MAX77686_RTC_CONTROLM = 0x02, + MAX77686_RTC_CONTROL = 0x03, + MAX77686_RTC_UPDATE0 = 0x04, + /* Reserved: 0x5 */ + MAX77686_WTSR_SMPL_CNTL = 0x06, + MAX77686_RTC_SEC = 0x07, + MAX77686_RTC_MIN = 0x08, + MAX77686_RTC_HOUR = 0x09, + MAX77686_RTC_WEEKDAY = 0x0A, + MAX77686_RTC_MONTH = 0x0B, + MAX77686_RTC_YEAR = 0x0C, + MAX77686_RTC_DATE = 0x0D, + MAX77686_ALARM1_SEC = 0x0E, + MAX77686_ALARM1_MIN = 0x0F, + MAX77686_ALARM1_HOUR = 0x10, + MAX77686_ALARM1_WEEKDAY = 0x11, + MAX77686_ALARM1_MONTH = 0x12, + MAX77686_ALARM1_YEAR = 0x13, + MAX77686_ALARM1_DATE = 0x14, + MAX77686_ALARM2_SEC = 0x15, + MAX77686_ALARM2_MIN = 0x16, + MAX77686_ALARM2_HOUR = 0x17, + MAX77686_ALARM2_WEEKDAY = 0x18, + MAX77686_ALARM2_MONTH = 0x19, + MAX77686_ALARM2_YEAR = 0x1A, + MAX77686_ALARM2_DATE = 0x1B, +}; + +#define MAX77686_IRQSRC_PMIC (0) +#define MAX77686_IRQSRC_RTC (1 << 0) + +enum max77686_irq_source { + PMIC_INT1 = 0, + PMIC_INT2, + RTC_INT, + + MAX77686_IRQ_GROUP_NR, +}; + +enum max77686_irq { + MAX77686_PMICIRQ_PWRONF, + MAX77686_PMICIRQ_PWRONR, + MAX77686_PMICIRQ_JIGONBF, + MAX77686_PMICIRQ_JIGONBR, + MAX77686_PMICIRQ_ACOKBF, + MAX77686_PMICIRQ_ACOKBR, + MAX77686_PMICIRQ_ONKEY1S, + MAX77686_PMICIRQ_MRSTB, + + MAX77686_PMICIRQ_140C, + MAX77686_PMICIRQ_120C, + + MAX77686_RTCIRQ_RTC60S, + MAX77686_RTCIRQ_RTCA1, + MAX77686_RTCIRQ_RTCA2, + MAX77686_RTCIRQ_SMPL, + MAX77686_RTCIRQ_RTC1S, + MAX77686_RTCIRQ_WTSR, + + MAX77686_IRQ_NR, +}; + +struct max77686_dev { + struct device *dev; + struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */ + struct i2c_client *rtc; /* slave addr 0x0c */ + struct mutex iolock; + + int type; + + struct regmap *regmap; /* regmap for mfd */ + struct regmap *rtc_regmap; /* regmap for rtc */ + + struct irq_domain *irq_domain; + + int irq; + int irq_gpio; + bool wakeup; + struct mutex irqlock; + int irq_masks_cur[MAX77686_IRQ_GROUP_NR]; + int irq_masks_cache[MAX77686_IRQ_GROUP_NR]; +}; + +enum max77686_types { + TYPE_MAX77686, +}; + +extern int max77686_irq_init(struct max77686_dev *max77686); +extern void max77686_irq_exit(struct max77686_dev *max77686); +extern int max77686_irq_resume(struct max77686_dev *max77686); + +#endif /* __LINUX_MFD_MAX77686_PRIV_H */ diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h new file mode 100644 index 000000000000..fcf312678cac --- /dev/null +++ b/include/linux/mfd/max77686.h @@ -0,0 +1,117 @@ +/* + * max77686.h - Driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electrnoics + * Chiwoong Byun + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This driver is based on max8997.h + * + * MAX77686 has PMIC, RTC devices. + * The devices share the same I2C bus and included in + * this mfd driver. + */ + +#ifndef __LINUX_MFD_MAX77686_H +#define __LINUX_MFD_MAX77686_H + +#include + +/* MAX77686 regulator IDs */ +enum max77686_regulators { + MAX77686_LDO1 = 0, + MAX77686_LDO2, + MAX77686_LDO3, + MAX77686_LDO4, + MAX77686_LDO5, + MAX77686_LDO6, + MAX77686_LDO7, + MAX77686_LDO8, + MAX77686_LDO9, + MAX77686_LDO10, + MAX77686_LDO11, + MAX77686_LDO12, + MAX77686_LDO13, + MAX77686_LDO14, + MAX77686_LDO15, + MAX77686_LDO16, + MAX77686_LDO17, + MAX77686_LDO18, + MAX77686_LDO19, + MAX77686_LDO20, + MAX77686_LDO21, + MAX77686_LDO22, + MAX77686_LDO23, + MAX77686_LDO24, + MAX77686_LDO25, + MAX77686_LDO26, + MAX77686_BUCK1, + MAX77686_BUCK2, + MAX77686_BUCK3, + MAX77686_BUCK4, + MAX77686_BUCK5, + MAX77686_BUCK6, + MAX77686_BUCK7, + MAX77686_BUCK8, + MAX77686_BUCK9, + MAX77686_EN32KHZ_AP, + MAX77686_EN32KHZ_CP, + MAX77686_P32KH, + + MAX77686_REG_MAX, +}; + +struct max77686_regulator_data { + int id; + struct regulator_init_data *initdata; +}; + +enum max77686_opmode { + MAX77686_OPMODE_NORMAL, + MAX77686_OPMODE_LP, + MAX77686_OPMODE_STANDBY, +}; + +struct max77686_opmode_data { + int id; + int mode; +}; + +struct max77686_platform_data { + /* IRQ */ + int irq_gpio; + int ono; + int wakeup; + + /* ---- PMIC ---- */ + struct max77686_regulator_data *regulators; + int num_regulators; + + struct max77686_opmode_data *opmode_data; + + /* + * GPIO-DVS feature is not enabled with the current version of + * MAX77686 driver. Buck2/3/4_voltages[0] is used as the default + * voltage at probe. DVS/SELB gpios are set as OUTPUT-LOW. + */ + int buck234_gpio_dvs[3]; /* GPIO of [0]DVS1, [1]DVS2, [2]DVS3 */ + int buck234_gpio_selb[3]; /* [0]SELB2, [1]SELB3, [2]SELB4 */ + unsigned int buck2_voltage[8]; /* buckx_voltage in uV */ + unsigned int buck3_voltage[8]; + unsigned int buck4_voltage[8]; +}; + +#endif /* __LINUX_MFD_MAX77686_H */ -- GitLab From ae85f12c66dd9982486976fce08ab9475d1c5c4e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 May 2012 23:33:22 +0800 Subject: [PATCH 2213/5711] mfd: Add terminating entry for i2c_device_id palmas table The i2c_device_id table is supposed to be zero-terminated. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 00c0aba7eba0..5d896b352284 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -472,6 +472,7 @@ static const struct i2c_device_id palmas_i2c_id[] = { { "twl6035", }, { "twl6037", }, { "tps65913", }, + { /* end */ } }; MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); -- GitLab From 8517690f31a5d36cf1a55099cfb0bc1d96d0e6f2 Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Fri, 29 Jun 2012 13:14:15 +0200 Subject: [PATCH 2214/5711] mfd: Remove unused variable from da9052_device_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to address the following warning during compilation time: drivers/mfd/da9052-core.c: In function ‘da9052_device_init’: drivers/mfd/da9052-core.c:646: warning: unused variable ‘desc’ This variable is indeed no longer in use (change can be traced back to commit: 8614419451d88bf99fff7f5e468fe45f8450891e). Signed-off-by: Krzysztof Wilczynski Signed-off-by: Samuel Ortiz --- drivers/mfd/da9052-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 1f1313c90573..2544910e1fd6 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -772,7 +772,6 @@ EXPORT_SYMBOL_GPL(da9052_regmap_config); int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) { struct da9052_pdata *pdata = da9052->dev->platform_data; - struct irq_desc *desc; int ret; mutex_init(&da9052->auxadc_lock); -- GitLab From a7cc37a49876319b2f848290eefe3388dd82286b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 24 May 2012 16:57:46 +0800 Subject: [PATCH 2215/5711] mfd: Remove unused max77693 iolock mutex Now this driver is using regmap APIs, the iolock mutex is not used and can be removed. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693.c | 2 -- include/linux/mfd/max77693-private.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index e9e4278722f3..4055bc2d36fb 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -138,8 +138,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->wakeup = pdata->wakeup; - mutex_init(&max77693->iolock); - if (max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, ®_data) < 0) { dev_err(max77693->dev, "device not found on this channel\n"); diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index 68263c5fa53c..1eeae5c07915 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -190,7 +190,6 @@ struct max77693_dev { struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ struct i2c_client *muic; /* 0x4A , MUIC */ struct i2c_client *haptic; /* 0x90 , Haptic */ - struct mutex iolock; int type; -- GitLab From 77a5b3701832801619dc13d3e902fd8a216e531b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 29 May 2012 11:06:28 +0200 Subject: [PATCH 2216/5711] mfd: Fix mc13xxx SPI regmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix the SPI regmap configuration, the wrong write flag was used. Also, bits_per_word should not be set as the regmap spi implementation uses a 8bits transfert granularity. Signed-off-by: Philippe Rétornaz Tested-by: Fabio Estevam Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 3fcdab3eb8eb..5d1969f67d82 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -49,6 +49,7 @@ static struct regmap_config mc13xxx_regmap_spi_config = { .reg_bits = 7, .pad_bits = 1, .val_bits = 24, + .write_flag_mask = 0x80, .max_register = MC13XXX_NUMREGS, @@ -73,7 +74,6 @@ static int mc13xxx_spi_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, mc13xxx); spi->mode = SPI_MODE_0 | SPI_CS_HIGH; - spi->bits_per_word = 32; mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); -- GitLab From e4ecf6ea84d68aea5a9785e89f52672e1e126998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 29 May 2012 11:06:29 +0200 Subject: [PATCH 2217/5711] mfd: mc13xxx workaround SPI hardware bug on i.Mx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MC13xxx PMIC is mainly used on i.Mx SoC. On those SoC the SPI hardware will deassert CS line as soon as the SPI FIFO is empty. The MC13xxx hardware is very sensitive to CS line change as it corrupts the transfer if CS is deasserted in the middle of a register read or write. It is not possible to use the CS line as a GPIO on some SoC, so we need to workaround this by implementing a single SPI transfer to access the PMIC. Reviewed-by: Mark Brown Acked-by: Marc Reilly Signed-off-by: Philippe Rétornaz Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 65 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 5d1969f67d82..03df422feb76 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -54,6 +54,67 @@ static struct regmap_config mc13xxx_regmap_spi_config = { .max_register = MC13XXX_NUMREGS, .cache_type = REGCACHE_NONE, + .use_single_rw = 1, +}; + +static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0}; + unsigned char r[4]; + unsigned char *p = val; + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + struct spi_transfer t = { + .tx_buf = w, + .rx_buf = r, + .len = 4, + }; + + struct spi_message m; + int ret; + + if (val_size != 3 || reg_size != 1) + return -ENOTSUPP; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(spi, &m); + + memcpy(p, &r[1], 3); + + return ret; +} + +static int mc13xxx_spi_write(void *context, const void *data, size_t count) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + + if (count != 4) + return -ENOTSUPP; + + return spi_write(spi, data, count); +} + +/* + * We cannot use regmap-spi generic bus implementation here. + * The MC13783 chip will get corrupted if CS signal is deasserted + * and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller + * has the following errata (DSPhl22960): + * "The CSPI negates SS when the FIFO becomes empty with + * SSCTL= 0. Software cannot guarantee that the FIFO will not + * drain because of higher priority interrupts and the + * non-realtime characteristics of the operating system. As a + * result, the SS will negate before all of the data has been + * transferred to/from the peripheral." + * We workaround this by accessing the SPI controller with a + * single transfert. + */ + +static struct regmap_bus regmap_mc13xxx_bus = { + .write = mc13xxx_spi_write, + .read = mc13xxx_spi_read, }; static int mc13xxx_spi_probe(struct spi_device *spi) @@ -78,7 +139,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config); + mc13xxx->regmap = regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, + &mc13xxx_regmap_spi_config); + if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", -- GitLab From e7c706b1e5ccf28eaaf76c7a4613e80b0ca52863 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 29 Jun 2012 15:14:36 +0200 Subject: [PATCH 2218/5711] mfd: Use devm_* APIs for mc13xxx Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-core.c | 4 ---- drivers/mfd/mc13xxx-i2c.c | 6 +++--- drivers/mfd/mc13xxx-spi.c | 7 ++----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index f0ea3b8b3e4a..b801dc72f041 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -723,10 +723,6 @@ void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx) free_irq(mc13xxx->irq, mc13xxx); mfd_remove_devices(mc13xxx->dev); - - regmap_exit(mc13xxx->regmap); - - kfree(mc13xxx); } EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup); diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index d22501dad6a6..18d29f3ca67f 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -63,7 +63,7 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, if (of_id) idrv->id_table = (const struct i2c_device_id*) of_id->data; - mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); + mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; @@ -72,13 +72,13 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, mc13xxx->dev = &client->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init_i2c(client, &mc13xxx_regmap_i2c_config); + mc13xxx->regmap = devm_regmap_init_i2c(client, + &mc13xxx_regmap_i2c_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", ret); dev_set_drvdata(&client->dev, NULL); - kfree(mc13xxx); return ret; } diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 03df422feb76..234207f7a831 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -129,7 +129,7 @@ static int mc13xxx_spi_probe(struct spi_device *spi) if (of_id) sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data]; - mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); + mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; @@ -139,15 +139,12 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, - &mc13xxx_regmap_spi_config); - + mc13xxx->regmap = devm_regmap_init_spi(spi, &mc13xxx_regmap_spi_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", ret); dev_set_drvdata(&spi->dev, NULL); - kfree(mc13xxx); return ret; } -- GitLab From 6e19e837c8a731a7a54a195a3081c7f74657ced5 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 30 May 2012 12:47:34 +0800 Subject: [PATCH 2219/5711] mfd: Enable IRQF_ONESHOT when requesting a threaded IRQ for ab8500gpadc The kernel now forces IRQs to be ONESHOT if no IRQ handler is passed. Acked-by: Linus Walleij Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-gpadc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index b86fd8e1ec3f..b6cbc3ba2695 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -599,7 +599,8 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) /* Register interrupt - SwAdcComplete */ ret = request_threaded_irq(gpadc->irq, NULL, ab8500_bm_gpswadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc", gpadc); + IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, + "ab8500-gpadc", gpadc); if (ret < 0) { dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", gpadc->irq); -- GitLab From e2186b531fd33c2d3450e143c2c8d8387fccb15d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 30 May 2012 12:47:36 +0800 Subject: [PATCH 2220/5711] mfd: Remove redundant AB8500_I2C_CORE Kconfig entry During ab8500-core clean-up the Kconfig entry for AB8500_I2C_CORE was left remnant. This patch simply removes it. Acked-by: Linus Walleij Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a7d0c851afc5..ed488edb2dee 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -716,16 +716,6 @@ config AB8500_CORE the irq_chip parts for handling the Mixed Signal chip events. This chip embeds various other multimedia funtionalities as well. -config AB8500_I2C_CORE - bool "AB8500 register access via PRCMU I2C" - depends on AB8500_CORE && MFD_DB8500_PRCMU - default y - help - This enables register access to the AB8500 chip via PRCMU I2C. - The AB8500 chip can be accessed via SPI or I2C. On DB8500 hardware - the I2C bus is connected to the Power Reset - and Mangagement Unit, PRCMU. - config AB8500_DEBUG bool "Enable debug info via debugfs" depends on AB8500_CORE && DEBUG_FS -- GitLab From 3c1447620401294b81e34bec7195f803c749bb91 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 29 Jun 2012 15:41:38 +0200 Subject: [PATCH 2221/5711] mfd: Enable DT probing of the DB8500 PRCMU This patch adds the correct compatible string for use during Device Tree population. Without it the DB8500 PRCMU will not be probed. Acked-by: Linus Walleij Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/db8500-prcmu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 50e83dc5dc49..40204e1dbd29 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3004,11 +3004,16 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) no_irq_return: return err; } +static const struct of_device_id db8500_prcmu_match[] = { + { .compatible = "stericsson,db8500-prcmu"}, + { }, +}; static struct platform_driver db8500_prcmu_driver = { .driver = { .name = "db8500-prcmu", .owner = THIS_MODULE, + .of_match_table = db8500_prcmu_match, }, .probe = db8500_prcmu_probe, }; -- GitLab From 06e589efa5b75e6a38a8e8b9c6cd774b5f679cdc Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jun 2012 13:56:37 +0100 Subject: [PATCH 2222/5711] mfd: Add IRQ domain support for the AB8500 As the AB8500 is an IRQ controller in its own right, here we provide the AB8500 driver with IRQ domain support. This is required if we wish to reference any of its IRQs from a platform's Device Tree. Cc: Naga Radheshy Cc: Mattias Wallin Cc: Daniel Willerud Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + drivers/mfd/ab8500-core.c | 130 ++++++++++++++++-------------- include/linux/mfd/abx500/ab8500.h | 5 ++ 3 files changed, 76 insertions(+), 60 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ed488edb2dee..8b56c1998ab2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -709,6 +709,7 @@ config AB8500_CORE bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU select MFD_CORE + select IRQ_DOMAIN help Select this option to enable access to AB8500 power management chip. This connects to U8500 either on the SSP/SPI bus (deprecated diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index dac0e2998603..f3af34596439 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -361,7 +362,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) static void ab8500_irq_mask(struct irq_data *data) { struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); - int offset = data->irq - ab8500->irq_base; + int offset = data->hwirq; int index = offset / 8; int mask = 1 << (offset % 8); @@ -371,7 +372,7 @@ static void ab8500_irq_mask(struct irq_data *data) static void ab8500_irq_unmask(struct irq_data *data) { struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); - int offset = data->irq - ab8500->irq_base; + int offset = data->hwirq; int index = offset / 8; int mask = 1 << (offset % 8); @@ -510,38 +511,51 @@ static irqreturn_t ab8500_irq(int irq, void *dev) return IRQ_HANDLED; } -static int ab8500_irq_init(struct ab8500 *ab8500) +/** + * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ + * + * @ab8500: ab8500_irq controller to operate on. + * @irq: index of the interrupt requested in the chip IRQs + * + * Useful for drivers to request their own IRQs. + */ +int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) { - int base = ab8500->irq_base; - int irq; - int num_irqs; + if (!ab8500) + return -EINVAL; - if (is_ab9540(ab8500)) - num_irqs = AB9540_NR_IRQS; - else if (is_ab8505(ab8500)) - num_irqs = AB8505_NR_IRQS; - else - num_irqs = AB8500_NR_IRQS; + return irq_create_mapping(ab8500->domain, irq); +} +EXPORT_SYMBOL_GPL(ab8500_irq_get_virq); - for (irq = base; irq < base + num_irqs; irq++) { - irq_set_chip_data(irq, ab8500); - irq_set_chip_and_handler(irq, &ab8500_irq_chip, - handle_simple_irq); - irq_set_nested_thread(irq, 1); +static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hwirq) +{ + struct ab8500 *ab8500 = d->host_data; + + if (!ab8500) + return -EINVAL; + + irq_set_chip_data(virq, ab8500); + irq_set_chip_and_handler(virq, &ab8500_irq_chip, + handle_simple_irq); + irq_set_nested_thread(virq, 1); #ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); + set_irq_flags(virq, IRQF_VALID); #else - irq_set_noprobe(irq); + irq_set_noprobe(virq); #endif - } return 0; } -static void ab8500_irq_remove(struct ab8500 *ab8500) +static struct irq_domain_ops ab8500_irq_ops = { + .map = ab8500_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) { - int base = ab8500->irq_base; - int irq; int num_irqs; if (is_ab9540(ab8500)) @@ -551,13 +565,22 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) else num_irqs = AB8500_NR_IRQS; - for (irq = base; irq < base + num_irqs; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); + if (ab8500->irq_base) { + ab8500->domain = irq_domain_add_legacy( + NULL, num_irqs, ab8500->irq_base, + 0, &ab8500_irq_ops, ab8500); + } + else { + ab8500->domain = irq_domain_add_linear( + np, num_irqs, &ab8500_irq_ops, ab8500); } + + if (!ab8500->domain) { + dev_err(ab8500->dev, "Failed to create irqdomain\n"); + return -ENOSYS; + } + + return 0; } int ab8500_suspend(struct ab8500 *ab8500) @@ -1233,14 +1256,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev) if (plat) ab8500->irq_base = plat->irq_base; - else if (np) - ret = of_property_read_u32(np, "stericsson,irq-base", &ab8500->irq_base); - - if (!ab8500->irq_base) { - dev_info(&pdev->dev, "couldn't find irq-base\n"); - ret = -EINVAL; - goto out_free_ab8500; - } ab8500->dev = &pdev->dev; @@ -1323,7 +1338,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev) AB8500_SWITCH_OFF_STATUS, &value); if (ret < 0) return ret; - dev_info(ab8500->dev, "switch off status: %#x", value); + dev_info(ab8500->dev, "switch off status: %#x\n", value); if (plat && plat->init) plat->init(ab8500); @@ -1352,25 +1367,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev) for (i = 0; i < ab8500->mask_size; i++) ab8500->mask[i] = ab8500->oldmask[i] = 0xff; - if (ab8500->irq_base) { - ret = ab8500_irq_init(ab8500); - if (ret) - goto out_freeoldmask; + ret = ab8500_irq_init(ab8500, np); + if (ret) + goto out_freeoldmask; - /* Activate this feature only in ab9540 */ - /* till tests are done on ab8500 1p2 or later*/ - if (is_ab9540(ab8500)) - ret = request_threaded_irq(ab8500->irq, NULL, + /* Activate this feature only in ab9540 */ + /* till tests are done on ab8500 1p2 or later*/ + if (is_ab9540(ab8500)) { + ret = request_threaded_irq(ab8500->irq, NULL, ab8500_hierarchical_irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, "ab8500", ab8500); - else - ret = request_threaded_irq(ab8500->irq, NULL, + } + else { + ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, "ab8500", ab8500); if (ret) - goto out_removeirq; + goto out_freeoldmask; } if (!np) { @@ -1417,15 +1432,11 @@ static int __devinit ab8500_probe(struct platform_device *pdev) &ab8500_attr_group); if (ret) dev_err(ab8500->dev, "error creating sysfs entries\n"); - else - return ret; + + return ret; out_freeirq: - if (ab8500->irq_base) - free_irq(ab8500->irq, ab8500); -out_removeirq: - if (ab8500->irq_base) - ab8500_irq_remove(ab8500); + free_irq(ab8500->irq, ab8500); out_freeoldmask: kfree(ab8500->oldmask); out_freemask: @@ -1444,11 +1455,10 @@ static int __devexit ab8500_remove(struct platform_device *pdev) sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); else sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); + mfd_remove_devices(ab8500->dev); - if (ab8500->irq_base) { - free_irq(ab8500->irq, ab8500); - ab8500_irq_remove(ab8500); - } + free_irq(ab8500->irq, ab8500); + kfree(ab8500->oldmask); kfree(ab8500->mask); kfree(ab8500); diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 91dd3ef63e99..4ae2cd9584fb 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -9,6 +9,7 @@ #include #include +#include struct device; @@ -227,6 +228,7 @@ enum ab8500_version { * @irq_lock: genirq bus lock * @transfer_ongoing: 0 if no transfer ongoing * @irq: irq line + * @irq_domain: irq domain * @version: chip version id (e.g. ab8500 or ab9540) * @chip_id: chip revision id * @write: register write @@ -247,6 +249,7 @@ struct ab8500 { atomic_t transfer_ongoing; int irq_base; int irq; + struct irq_domain *domain; enum ab8500_version version; u8 chip_id; @@ -336,4 +339,6 @@ static inline int is_ab8500_2p0(struct ab8500 *ab) return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0)); } +int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq); + #endif /* MFD_AB8500_H */ -- GitLab From 822672a7b496e724f879af703693f342e2215163 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jun 2012 13:56:38 +0100 Subject: [PATCH 2223/5711] mfd: Generically describe interactions with the DB8500 PRCMU There is only one method used to communicate with the DB8500 PRCMU, via I2C. Now this can be assumed, there is no requirement to specify the protocol in the function name. This patch removes protocol specifics and uses a more generic naming convention. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-core.c | 12 ++++++------ drivers/mfd/ab8500-debugfs.c | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index f3af34596439..a19f520e2c72 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -141,7 +141,7 @@ static const char ab8500_version_str[][7] = { [AB8500_VERSION_AB8540] = "AB8540", }; -static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) +static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) { int ret; @@ -151,7 +151,7 @@ static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) return ret; } -static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, +static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data) { int ret; @@ -163,7 +163,7 @@ static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, return ret; } -static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) +static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) { int ret; u8 data; @@ -1267,9 +1267,9 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ab8500->irq = resource->start; - ab8500->read = ab8500_i2c_read; - ab8500->write = ab8500_i2c_write; - ab8500->write_masked = ab8500_i2c_write_masked; + ab8500->read = ab8500_prcmu_read; + ab8500->write = ab8500_prcmu_write; + ab8500->write_masked = ab8500_prcmu_write_masked; mutex_init(&ab8500->lock); mutex_init(&ab8500->irq_lock); diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 50c4c89ab220..361de52aefe5 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -31,12 +31,12 @@ struct ab8500_reg_range { }; /** - * struct ab8500_i2c_ranges + * struct ab8500_prcmu_ranges * @num_ranges: the number of ranges in the list * @bankid: bank identifier * @range: the list of register ranges */ -struct ab8500_i2c_ranges { +struct ab8500_prcmu_ranges { u8 num_ranges; u8 bankid; const struct ab8500_reg_range *range; @@ -47,7 +47,7 @@ struct ab8500_i2c_ranges { #define AB8500_REV_REG 0x80 -static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { +static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { [0x0] = { .num_ranges = 0, .range = 0, -- GitLab From c94bb233a9fee3314dc5d9c7de9fa702e91283f2 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 29 Jun 2012 19:01:03 +0200 Subject: [PATCH 2224/5711] mfd: Make MFD core code Device Tree and IRQ domain aware During Device Tree enablement of the ab8500 and db8500-prcmu drivers, a decision was made to omit registration through the MFD API and use Device Tree directly. However, because MFD devices have a different address space and the ab8500 and db8500 both use I2C to communicate, this causes issues with address translation during execution of of_platform_populate(). So the solution is to make the MFD core aware of Device Tree and have it assign the correct node pointers instead. To make this work the MFD core also needs to be awere of IRQ domains, as Device Tree insists on IRQ domain compatibility. So, instead of providing an irq-base via platform code, in the DT case we simply look up the IRQ domain and map to the correct virtual IRQ. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + drivers/mfd/mfd-core.c | 30 ++++++++++++++++++++++++++---- include/linux/mfd/core.h | 1 + 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8b56c1998ab2..d43876c6da23 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -7,6 +7,7 @@ menu "Multifunction device drivers" config MFD_CORE tristate + select IRQ_DOMAIN default n config MFD_88PM860X diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index ffc3d48676ae..0c3a01cde2f7 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include int mfd_cell_enable(struct platform_device *pdev) { @@ -76,6 +78,8 @@ static int mfd_add_device(struct device *parent, int id, { struct resource *res; struct platform_device *pdev; + struct device_node *np = NULL; + struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -89,6 +93,16 @@ static int mfd_add_device(struct device *parent, int id, pdev->dev.parent = parent; + if (parent->of_node && cell->of_compatible) { + for_each_child_of_node(parent->of_node, np) { + if (of_device_is_compatible(np, cell->of_compatible)) { + pdev->dev.of_node = np; + domain = irq_find_host(parent->of_node); + break; + } + } + } + if (cell->pdata_size) { ret = platform_device_add_data(pdev, cell->platform_data, cell->pdata_size); @@ -112,10 +126,18 @@ static int mfd_add_device(struct device *parent, int id, res[r].end = mem_base->start + cell->resources[r].end; } else if (cell->resources[r].flags & IORESOURCE_IRQ) { - res[r].start = irq_base + - cell->resources[r].start; - res[r].end = irq_base + - cell->resources[r].end; + if (domain) { + /* Unable to create mappings for IRQ ranges. */ + WARN_ON(cell->resources[r].start != + cell->resources[r].end); + res[r].start = res[r].end = irq_create_mapping( + domain, cell->resources[r].start); + } else { + res[r].start = irq_base + + cell->resources[r].start; + res[r].end = irq_base + + cell->resources[r].end; + } } else { res[r].parent = cell->resources[r].parent; res[r].start = cell->resources[r].start; diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 4e76163dd862..99b7eb1961b6 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -36,6 +36,7 @@ struct mfd_cell { /* platform data passed to the sub devices drivers */ void *platform_data; size_t pdata_size; + const char *of_compatible; /* * These resources can be specified relative to the parent device. -- GitLab From a661aca4ba602d81135ba5cfc2b208e1ad5fdead Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 11 Jun 2012 16:24:59 +0100 Subject: [PATCH 2225/5711] mfd: Initialise the DB8500 PRCMU driver at core_initcall time Now the AB8500 has its own IRQ domain it needs to be initialised earlier in the boot sequence. As the AB8500 relies on the DB8500 PRCMU we need to reflect this change for the PRCMU driver too. Cc: Samuel Ortiz Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/db8500-prcmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 40204e1dbd29..9effb710d4e0 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3023,7 +3023,7 @@ static int __init db8500_prcmu_init(void) return platform_driver_register(&db8500_prcmu_driver); } -arch_initcall(db8500_prcmu_init); +core_initcall(db8500_prcmu_init); MODULE_AUTHOR("Mattias Nilsson "); MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); -- GitLab From ba7cbc3e15df1eb34a3a986b52ac82db3a569ab9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 11 Jun 2012 16:25:00 +0100 Subject: [PATCH 2226/5711] mfd: Initialise the AB8500 driver at core_initcall time The AB8500 is soon to have its own IRQ domain. For this to be useful the driver needs to be initialised earlier in the boot sequence. Here we move initialisation forward from arch_initcall to core_initcall time. Cc: Samuel Ortiz Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index a19f520e2c72..8de3b659626e 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1494,7 +1494,7 @@ static void __exit ab8500_core_exit(void) { platform_driver_unregister(&ab8500_core_driver); } -arch_initcall(ab8500_core_init); +core_initcall(ab8500_core_init); module_exit(ab8500_core_exit); MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); -- GitLab From 5d90322bc85894105bbf738abc148135a619e01a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jun 2012 13:56:41 +0100 Subject: [PATCH 2227/5711] mfd: Register db8500-prcmu devices using the newly DT:ed MFD API Now the MFD API is Device Tree aware we can use it for platform registration again, even when booting with DT enabled. To aid in Device Node pointer allocation we provide each cell with the associative compatible string. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/db8500-prcmu.c | 14 +++++++------- drivers/regulator/db8500-prcmu.c | 6 ------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 9effb710d4e0..50b49d965f2b 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2948,11 +2948,13 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { static struct mfd_cell db8500_prcmu_devs[] = { { .name = "db8500-prcmu-regulators", + .of_compatible = "stericsson,db8500-prcmu-regulator", .platform_data = &db8500_regulators, .pdata_size = sizeof(db8500_regulators), }, { .name = "cpufreq-u8500", + .of_compatible = "stericsson,cpufreq-u8500", }, }; @@ -2990,13 +2992,11 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) if (cpu_is_u8500v20_or_later()) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); - if (!np) { - err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); - if (err) { - pr_err("prcmu: Failed to add subdevices\n"); - return err; - } + err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); + if (err) { + pr_err("prcmu: Failed to add subdevices\n"); + return err; } pr_info("DB8500 PRCMU initialized\n"); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 9dbb491b6efa..359f8d18fc3f 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -547,16 +547,10 @@ static int __exit db8500_regulator_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id db8500_prcmu_regulator_match[] = { - { .compatible = "stericsson,db8500-prcmu-regulator", }, - {} -}; - static struct platform_driver db8500_regulator_driver = { .driver = { .name = "db8500-prcmu-regulators", .owner = THIS_MODULE, - .of_match_table = db8500_prcmu_regulator_match, }, .probe = db8500_regulator_probe, .remove = __exit_p(db8500_regulator_remove), -- GitLab From 6d11d1356cb3b1c009a90b273350f6a88c0b90e0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 29 Jun 2012 17:13:35 +0200 Subject: [PATCH 2228/5711] mfd: Register the ab8500 from db8500-prcmu using the MFD API Hierarchically, the AB8500 is a child of the DB8500 PRCMU. So now that Device Tree is being used and MFD core code is Device Tree aware, we can simply register DB8500 PRCMU from Device Tree in the normal way then allow the DB8500 PRCMU driver to register the AB8500 as a simple MFD device at probe time. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- arch/arm/mach-ux500/board-mop500.c | 2 -- drivers/mfd/ab8500-core.c | 12 ------------ drivers/mfd/db8500-prcmu.c | 15 +++++++++++++++ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 1509a3cb5833..44d816ffaeb6 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -793,8 +793,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, { .compatible = "stericsson,db8500-prcmu", }, - { .compatible = "stericsson,db8500-prcmu-regulator", }, - { .compatible = "stericsson,ab8500", }, { .compatible = "stericsson,ab8500-regulator", }, { .compatible = "simple-bus"}, { }, diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 8de3b659626e..3eb15872c3a0 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1230,14 +1230,6 @@ static struct attribute_group ab9540_attr_group = { .attrs = ab9540_sysfs_entries, }; -static const struct of_device_id ab8500_match[] = { - { - .compatible = "stericsson,ab8500", - .data = (void *)AB8500_VERSION_AB8500, - }, - {}, -}; - static int __devinit ab8500_probe(struct platform_device *pdev) { struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); @@ -1279,9 +1271,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev) if (platid) version = platid->driver_data; - else if (np) - version = (unsigned int) - of_match_device(ab8500_match, &pdev->dev)->data; if (version != AB8500_VERSION_UNDEFINED) ab8500->version = version; @@ -1478,7 +1467,6 @@ static struct platform_driver ab8500_core_driver = { .driver = { .name = "ab8500-core", .owner = THIS_MODULE, - .of_match_table = ab8500_match, }, .probe = ab8500_probe, .remove = __devexit_p(ab8500_remove), diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 50b49d965f2b..bf5a054a2b91 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2945,6 +2945,14 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { }, }; +static struct resource ab8500_resources[] = { + [0] = { + .start = IRQ_DB8500_AB8500, + .end = IRQ_DB8500_AB8500, + .flags = IORESOURCE_IRQ + } +}; + static struct mfd_cell db8500_prcmu_devs[] = { { .name = "db8500-prcmu-regulators", @@ -2956,6 +2964,13 @@ static struct mfd_cell db8500_prcmu_devs[] = { .name = "cpufreq-u8500", .of_compatible = "stericsson,cpufreq-u8500", }, + { + .name = "ab8500-core", + .of_compatible = "stericsson,ab8500", + .num_resources = ARRAY_SIZE(ab8500_resources), + .resources = ab8500_resources, + .id = AB8500_VERSION_AB8500, + }, }; /** -- GitLab From b0ab907d325f99054eb2700a8f8c50776ebfeaf9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 1 Jun 2012 16:33:19 +0100 Subject: [PATCH 2229/5711] mfd: Support for user defined wm8994 irq flags Signed-off-by: Chris Rattray Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-irq.c | 10 +++++++++- include/linux/mfd/wm8994/pdata.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index f1837f669755..0aac4aff17a5 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -139,6 +140,8 @@ static struct regmap_irq_chip wm8994_irq_chip = { int wm8994_irq_init(struct wm8994 *wm8994) { int ret; + unsigned long irqflags; + struct wm8994_pdata *pdata = wm8994->dev->platform_data; if (!wm8994->irq) { dev_warn(wm8994->dev, @@ -147,8 +150,13 @@ int wm8994_irq_init(struct wm8994 *wm8994) return 0; } + /* select user or default irq flags */ + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; + if (pdata->irq_flags) + irqflags = pdata->irq_flags; + ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, wm8994->irq_base, &wm8994_irq_chip, &wm8994->irq_data); if (ret != 0) { diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 893267bb6229..f0361c031927 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -141,6 +141,7 @@ struct wm8994_pdata { struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO]; int irq_base; /** Base IRQ number for WM8994, required for IRQs */ + unsigned long irq_flags; /** user irq flags */ int num_drc_cfgs; struct wm8994_drc_cfg *drc_cfgs; -- GitLab From 52b461b86a9f6c7a86bdcb858e1bbef089fbe6a0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 3 Jun 2012 13:37:22 +0100 Subject: [PATCH 2230/5711] mfd: Add regmap cache support for wm8350 Use the most simple possible transformation on the existing code so keep the table sitting around, further patches in this series will delete the existing cache code - the main purpose of this patch is to ensure that we always have a cache for bisection. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-core.c | 29 ++++++++++------- drivers/mfd/wm8350-i2c.c | 5 --- drivers/mfd/wm8350-regmap.c | 56 +++++++++++++++++++++++++++++++++ include/linux/mfd/wm8350/core.h | 7 ++++- 4 files changed, 80 insertions(+), 17 deletions(-) diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 8a9b11ca076a..fadcbbe9e2ba 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -32,9 +32,6 @@ #include #include -#define WM8350_UNLOCK_KEY 0x0013 -#define WM8350_LOCK_KEY 0x0000 - #define WM8350_CLOCK_CONTROL_1 0x28 #define WM8350_AIF_TEST 0x74 @@ -295,15 +292,20 @@ EXPORT_SYMBOL_GPL(wm8350_block_write); */ int wm8350_reg_lock(struct wm8350 *wm8350) { - u16 key = WM8350_LOCK_KEY; int ret; + mutex_lock(®_lock_mutex); + ldbg(__func__); - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); + + ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_LOCK_KEY); if (ret) dev_err(wm8350->dev, "lock failed\n"); - mutex_unlock(&io_mutex); + + wm8350->unlocked = false; + + mutex_unlock(®_lock_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_lock); @@ -319,15 +321,20 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock); */ int wm8350_reg_unlock(struct wm8350 *wm8350) { - u16 key = WM8350_UNLOCK_KEY; int ret; + mutex_lock(®_lock_mutex); + ldbg(__func__); - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); + + ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_UNLOCK_KEY); if (ret) dev_err(wm8350->dev, "unlock failed\n"); - mutex_unlock(&io_mutex); + + wm8350->unlocked = true; + + mutex_unlock(®_lock_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_unlock); diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index a68aceb4e48c..2e57101c8d3d 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c @@ -23,11 +23,6 @@ #include #include -static const struct regmap_config wm8350_regmap = { - .reg_bits = 8, - .val_bits = 16, -}; - static int wm8350_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index e965139e5cd5..7974cadaa422 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c @@ -3433,3 +3433,59 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = { { 0x0000, 0x0000, 0x0000 }, /* R254 */ { 0x0000, 0x0000, 0x0000 }, /* R255 */ }; + +static bool wm8350_readable(struct device *dev, unsigned int reg) +{ + return wm8350_reg_io_map[reg].readable; +} + +static bool wm8350_writeable(struct device *dev, unsigned int reg) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + + if (!wm8350->unlocked) { + if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && + reg <= WM8350_GPIO_FUNCTION_SELECT_4) || + (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && + reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) + return false; + } + + return wm8350_reg_io_map[reg].writable; +} + +static bool wm8350_volatile(struct device *dev, unsigned int reg) +{ + return wm8350_reg_io_map[reg].vol; +} + +static bool wm8350_precious(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8350_SYSTEM_INTERRUPTS: + case WM8350_INT_STATUS_1: + case WM8350_INT_STATUS_2: + case WM8350_POWER_UP_INT_STATUS: + case WM8350_UNDER_VOLTAGE_INT_STATUS: + case WM8350_OVER_CURRENT_INT_STATUS: + case WM8350_GPIO_INT_STATUS: + case WM8350_COMPARATOR_INT_STATUS: + return true; + + default: + return false; + } +} + +const struct regmap_config wm8350_regmap = { + .reg_bits = 8, + .val_bits = 16, + + .cache_type = REGCACHE_RBTREE, + + .max_register = WM8350_MAX_REGISTER, + .readable_reg = wm8350_readable, + .writeable_reg = wm8350_writeable, + .volatile_reg = wm8350_volatile, + .precious_reg = wm8350_precious, +}; diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index 9192b6404a73..cba9bc8f947b 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,9 @@ #define WM8350_MAX_REGISTER 0xFF +#define WM8350_UNLOCK_KEY 0x0013 +#define WM8350_LOCK_KEY 0x0000 + /* * Field Definitions. */ @@ -582,6 +586,7 @@ #define WM8350_NUM_IRQ_REGS 7 +extern const struct regmap_config wm8350_regmap; struct wm8350_reg_access { u16 readable; /* Mask of readable bits */ u16 writable; /* Mask of writable bits */ @@ -602,7 +607,6 @@ extern const u16 wm8352_mode2_defaults[]; extern const u16 wm8352_mode3_defaults[]; struct wm8350; -struct regmap; struct wm8350_hwmon { struct platform_device *pdev; @@ -615,6 +619,7 @@ struct wm8350 { /* device IO */ struct regmap *regmap; u16 *reg_cache; + bool unlocked; struct mutex auxadc_mutex; struct completion auxadc_done; -- GitLab From 7fdb5d32614f7784fc7c2b8e883eb4da26358a94 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 3 Jun 2012 13:37:23 +0100 Subject: [PATCH 2231/5711] mfd: Rely on regmap cache in wm8350 interrupt controller We can just use regmap_update_bits() to achieve the same effect - it will do the read/modify/update cycle for us. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-irq.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c index 9fd01bf63c51..624ff90501cd 100644 --- a/drivers/mfd/wm8350-irq.c +++ b/drivers/mfd/wm8350-irq.c @@ -432,11 +432,9 @@ static void wm8350_irq_sync_unlock(struct irq_data *data) for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) { /* If there's been a change in the mask write it back * to the hardware. */ - if (wm8350->irq_masks[i] != - wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i]) - WARN_ON(wm8350_reg_write(wm8350, - WM8350_INT_STATUS_1_MASK + i, - wm8350->irq_masks[i])); + WARN_ON(regmap_update_bits(wm8350->regmap, + WM8350_INT_STATUS_1_MASK + i, + 0xffff, wm8350->irq_masks[i])); } mutex_unlock(&wm8350->irq_lock); -- GitLab From 19d57ed5a308472a02e773f33c03ad4cb2ec6a9d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 3 Jun 2012 13:37:24 +0100 Subject: [PATCH 2232/5711] mfd: Remove custom wm8350 cache implementation Since none of the users now reference the cache directly we can happily remove the custom cache code and rely on the regmap cache. For simplicity we don't bother with the register defaults tables but instead read the defaults from the device - regmap is capable of doing this, unlike our old cache infrastructure. This saves a lot of code and allows us to cache the device revision information too. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-core.c | 325 +--- drivers/mfd/wm8350-regmap.c | 3166 +------------------------------ include/linux/mfd/wm8350/core.h | 19 - 3 files changed, 18 insertions(+), 3492 deletions(-) diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index fadcbbe9e2ba..7c1ae24605d9 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -60,181 +60,32 @@ /* * WM8350 Device IO */ -static DEFINE_MUTEX(io_mutex); static DEFINE_MUTEX(reg_lock_mutex); -/* Perform a physical read from the device. - */ -static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, - u16 *dest) -{ - int i, ret; - int bytes = num_regs * 2; - - dev_dbg(wm8350->dev, "volatile read\n"); - ret = regmap_raw_read(wm8350->regmap, reg, dest, bytes); - - for (i = reg; i < reg + num_regs; i++) { - /* Cache is CPU endian */ - dest[i - reg] = be16_to_cpu(dest[i - reg]); - - /* Mask out non-readable bits */ - dest[i - reg] &= wm8350_reg_io_map[i].readable; - } - - dump(num_regs, dest); - - return ret; -} - -static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) -{ - int i; - int end = reg + num_regs; - int ret = 0; - int bytes = num_regs * 2; - - if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { - dev_err(wm8350->dev, "invalid reg %x\n", - reg + num_regs - 1); - return -EINVAL; - } - - dev_dbg(wm8350->dev, - "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); - -#if WM8350_BUS_DEBUG - /* we can _safely_ read any register, but warn if read not supported */ - for (i = reg; i < end; i++) { - if (!wm8350_reg_io_map[i].readable) - dev_warn(wm8350->dev, - "reg R%d is not readable\n", i); - } -#endif - - /* if any volatile registers are required, then read back all */ - for (i = reg; i < end; i++) - if (wm8350_reg_io_map[i].vol) - return wm8350_phys_read(wm8350, reg, num_regs, dest); - - /* no volatiles, then cache is good */ - dev_dbg(wm8350->dev, "cache read\n"); - memcpy(dest, &wm8350->reg_cache[reg], bytes); - dump(num_regs, dest); - return ret; -} - -static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) -{ - if (reg == WM8350_SECURITY || - wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) - return 0; - - if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && - reg <= WM8350_GPIO_FUNCTION_SELECT_4) || - (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && - reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) - return 1; - return 0; -} - -static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) -{ - int i; - int end = reg + num_regs; - int bytes = num_regs * 2; - - if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { - dev_err(wm8350->dev, "invalid reg %x\n", - reg + num_regs - 1); - return -EINVAL; - } - - /* it's generally not a good idea to write to RO or locked registers */ - for (i = reg; i < end; i++) { - if (!wm8350_reg_io_map[i].writable) { - dev_err(wm8350->dev, - "attempted write to read only reg R%d\n", i); - return -EINVAL; - } - - if (is_reg_locked(wm8350, i)) { - dev_err(wm8350->dev, - "attempted write to locked reg R%d\n", i); - return -EINVAL; - } - - src[i - reg] &= wm8350_reg_io_map[i].writable; - - wm8350->reg_cache[i] = - (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) - | src[i - reg]; - - src[i - reg] = cpu_to_be16(src[i - reg]); - } - - /* Actually write it out */ - return regmap_raw_write(wm8350->regmap, reg, src, bytes); -} - /* * Safe read, modify, write methods */ int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) { - u16 data; - int err; - - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); - if (err) { - dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - goto out; - } - - data &= ~mask; - err = wm8350_write(wm8350, reg, 1, &data); - if (err) - dev_err(wm8350->dev, "write to reg R%d failed\n", reg); -out: - mutex_unlock(&io_mutex); - return err; + return regmap_update_bits(wm8350->regmap, reg, mask, 0); } EXPORT_SYMBOL_GPL(wm8350_clear_bits); int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) { - u16 data; - int err; - - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); - if (err) { - dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - goto out; - } - - data |= mask; - err = wm8350_write(wm8350, reg, 1, &data); - if (err) - dev_err(wm8350->dev, "write to reg R%d failed\n", reg); -out: - mutex_unlock(&io_mutex); - return err; + return regmap_update_bits(wm8350->regmap, reg, mask, mask); } EXPORT_SYMBOL_GPL(wm8350_set_bits); u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) { - u16 data; + unsigned int data; int err; - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); + err = regmap_read(wm8350->regmap, reg, &data); if (err) dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - mutex_unlock(&io_mutex); return data; } EXPORT_SYMBOL_GPL(wm8350_reg_read); @@ -242,13 +93,11 @@ EXPORT_SYMBOL_GPL(wm8350_reg_read); int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) { int ret; - u16 data = val; - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, reg, 1, &data); + ret = regmap_write(wm8350->regmap, reg, val); + if (ret) dev_err(wm8350->dev, "write to reg R%d failed\n", reg); - mutex_unlock(&io_mutex); return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_write); @@ -258,12 +107,11 @@ int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, { int err = 0; - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, start_reg, regs, dest); + err = regmap_bulk_read(wm8350->regmap, start_reg, dest, regs); if (err) dev_err(wm8350->dev, "block read starting from R%d failed\n", start_reg); - mutex_unlock(&io_mutex); + return err; } EXPORT_SYMBOL_GPL(wm8350_block_read); @@ -273,12 +121,11 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, { int ret = 0; - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, start_reg, regs, src); + ret = regmap_bulk_write(wm8350->regmap, start_reg, src, regs); if (ret) dev_err(wm8350->dev, "block write starting at R%d failed\n", start_reg); - mutex_unlock(&io_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_block_write); @@ -401,146 +248,6 @@ static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) return IRQ_HANDLED; } -/* - * Cache is always host endian. - */ -static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) -{ - int i, ret = 0; - u16 value; - const u16 *reg_map; - - switch (type) { - case 0: - switch (mode) { -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 - case 0: - reg_map = wm8350_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 - case 1: - reg_map = wm8350_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 - case 2: - reg_map = wm8350_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 - case 3: - reg_map = wm8350_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8350 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - case 1: - switch (mode) { -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 - case 0: - reg_map = wm8351_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 - case 1: - reg_map = wm8351_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 - case 2: - reg_map = wm8351_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 - case 3: - reg_map = wm8351_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8351 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - case 2: - switch (mode) { -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 - case 0: - reg_map = wm8352_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 - case 1: - reg_map = wm8352_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 - case 2: - reg_map = wm8352_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 - case 3: - reg_map = wm8352_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8352 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - default: - dev_err(wm8350->dev, - "WM835x configuration mode %d not supported\n", - mode); - return -EINVAL; - } - - wm8350->reg_cache = - kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); - if (wm8350->reg_cache == NULL) - return -ENOMEM; - - /* Read the initial cache state back from the device - this is - * a PMIC so the device many not be in a virgin state and we - * can't rely on the silicon values. - */ - ret = regmap_raw_read(wm8350->regmap, 0, wm8350->reg_cache, - sizeof(u16) * (WM8350_MAX_REGISTER + 1)); - if (ret < 0) { - dev_err(wm8350->dev, - "failed to read initial cache values\n"); - goto out; - } - - /* Mask out uncacheable/unreadable bits and the audio. */ - for (i = 0; i < WM8350_MAX_REGISTER; i++) { - if (wm8350_reg_io_map[i].readable && - (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { - value = be16_to_cpu(wm8350->reg_cache[i]); - value &= wm8350_reg_io_map[i].readable; - wm8350->reg_cache[i] = value; - } else - wm8350->reg_cache[i] = reg_map[i]; - } - -out: - kfree(wm8350->reg_cache); - return ret; -} - /* * Register a client device. This is non-fatal since there is no need to * fail the entire device init due to a single platform device failing. @@ -688,18 +395,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, goto err; } - ret = wm8350_create_cache(wm8350, mask_rev, mode); - if (ret < 0) { - dev_err(wm8350->dev, "Failed to create register cache\n"); - return ret; - } - mutex_init(&wm8350->auxadc_mutex); init_completion(&wm8350->auxadc_done); ret = wm8350_irq_init(wm8350, irq, pdata); if (ret < 0) - goto err_free; + goto err; if (wm8350->irq_base) { ret = request_threaded_irq(wm8350->irq_base + @@ -737,8 +438,6 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, err_irq: wm8350_irq_exit(wm8350); -err_free: - kfree(wm8350->reg_cache); err: return ret; } @@ -765,8 +464,6 @@ void wm8350_device_exit(struct wm8350 *wm8350) free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); wm8350_irq_exit(wm8350); - - kfree(wm8350->reg_cache); } EXPORT_SYMBOL_GPL(wm8350_device_exit); diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index 7974cadaa422..9efc64750fb6 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c @@ -14,3170 +14,18 @@ #include -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode0_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0000, /* R195 - DCDC6 Control */ - 0x0000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode1_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0014, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x00FB, /* R134 - GPIO Configuration (i/o) */ - 0x04FE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0312, /* R140 - GPIO Function Select 1 */ - 0x1003, /* R141 - GPIO Function Select 2 */ - 0x1331, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0062, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0800, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0400, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0006, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode2_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0014, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x08FB, /* R134 - GPIO Configuration (i/o) */ - 0x0CFE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0312, /* R140 - GPIO Function Select 1 */ - 0x0003, /* R141 - GPIO Function Select 2 */ - 0x2331, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x002E, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x0800, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0C00, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001A, /* R200 - LDO1 Control */ - 0x0800, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0800, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x000A, /* R206 - LDO3 Control */ - 0x0C00, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0800, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode3_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1000, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0A7B, /* R134 - GPIO Configuration (i/o) */ - 0x06FE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1312, /* R140 - GPIO Function Select 1 */ - 0x1030, /* R141 - GPIO Function Select 2 */ - 0x2231, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x000E, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0026, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0400, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001C, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001C, /* R206 - LDO3 Control */ - 0x0400, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001F, /* R209 - LDO4 Control */ - 0x0400, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode0_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0000, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode1_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0CFB, /* R134 - GPIO Configuration (i/o) */ - 0x0C1F, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0300, /* R140 - GPIO Function Select 1 */ - 0x1110, /* R141 - GPIO Function Select 2 */ - 0x0013, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0C00, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x0800, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x000A, /* R195 */ - 0x1000, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0C00, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001F, /* R206 - LDO3 Control */ - 0x0800, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x000A, /* R209 - LDO4 Control */ - 0x0800, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x1000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode2_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0214, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0110, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x09FA, /* R134 - GPIO Configuration (i/o) */ - 0x0DF6, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1310, /* R140 - GPIO Function Select 1 */ - 0x0003, /* R141 - GPIO Function Select 2 */ - 0x2000, /* R142 - GPIO Function Select 3 */ - 0x0000, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x001A, /* R180 - DCDC1 Control */ - 0x0800, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0056, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0026, /* R189 - DCDC4 Control */ - 0x0C00, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0026, /* R195 */ - 0x0C00, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0400, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0C00, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0015, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode3_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0010, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0310, /* R140 - GPIO Function Select 1 */ - 0x0001, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x1400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0026, /* R195 */ - 0x0400, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0C00, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0016, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0019, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x1000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode0_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0000, /* R195 - DCDC6 Control */ - 0x0000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode1_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFF, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0300, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0062, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0006, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0006, /* R189 - DCDC4 Control */ - 0x0C00, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x1000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0002, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001A, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001F, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001F, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode2_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0110, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x09DA, /* R134 - GPIO Configuration (i/o) */ - 0x0DD6, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1310, /* R140 - GPIO Function Select 1 */ - 0x0033, /* R141 - GPIO Function Select 2 */ - 0x2000, /* R142 - GPIO Function Select 3 */ - 0x0000, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0800, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0056, /* R186 - DCDC3 Control */ - 0x1800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x1000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0C00, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0006, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001C, /* R206 - LDO3 Control */ - 0x1400, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode3_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0010, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0310, /* R140 - GPIO Function Select 1 */ - 0x0001, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0006, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0050, /* R186 - DCDC3 Control */ - 0x0C00, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0029, /* R195 - DCDC6 Control */ - 0x0800, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001D, /* R200 - LDO1 Control */ - 0x1000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0017, /* R203 - LDO2 Control */ - 0x1000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0006, /* R206 - LDO3 Control */ - 0x1000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x0010, /* R209 - LDO4 Control */ - 0x1000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - /* * Access masks. */ -const struct wm8350_reg_access wm8350_reg_io_map[] = { +static const struct wm8350_reg_access { + u16 readable; /* Mask of readable bits */ + u16 writable; /* Mask of writable bits */ + u16 vol; /* Mask of volatile bits */ +} wm8350_reg_io_map[] = { /* read write volatile */ - { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */ - { 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R0 - Reset/ID */ + { 0x7CFF, 0x0C00, 0x0000 }, /* R1 - ID */ { 0x007F, 0x0000, 0x0000 }, /* R2 - ROM Mask ID */ { 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */ { 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */ diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index cba9bc8f947b..509481d9cf19 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h @@ -587,24 +587,6 @@ #define WM8350_NUM_IRQ_REGS 7 extern const struct regmap_config wm8350_regmap; -struct wm8350_reg_access { - u16 readable; /* Mask of readable bits */ - u16 writable; /* Mask of writable bits */ - u16 vol; /* Mask of volatile bits */ -}; -extern const struct wm8350_reg_access wm8350_reg_io_map[]; -extern const u16 wm8350_mode0_defaults[]; -extern const u16 wm8350_mode1_defaults[]; -extern const u16 wm8350_mode2_defaults[]; -extern const u16 wm8350_mode3_defaults[]; -extern const u16 wm8351_mode0_defaults[]; -extern const u16 wm8351_mode1_defaults[]; -extern const u16 wm8351_mode2_defaults[]; -extern const u16 wm8351_mode3_defaults[]; -extern const u16 wm8352_mode0_defaults[]; -extern const u16 wm8352_mode1_defaults[]; -extern const u16 wm8352_mode2_defaults[]; -extern const u16 wm8352_mode3_defaults[]; struct wm8350; @@ -618,7 +600,6 @@ struct wm8350 { /* device IO */ struct regmap *regmap; - u16 *reg_cache; bool unlocked; struct mutex auxadc_mutex; -- GitLab From 5261e101198e7ef31a60d3aa97815a49c8b8fa20 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Mon, 21 May 2012 14:28:21 +0530 Subject: [PATCH 2233/5711] mfd: Update db8500-prmcu hostport_access enable Force the Modem wakeup by asserting the CaWakeReq signal before the hostaccess_req/ack ping-pong sequence. The Awake_req signal is de-asserted asserted at the same time than the hostaccess_req. Return error on failure case so that the client using this can take appropiate steps. Signed-off-by: Arun Murthy Acked-by: Linus Walleij Signed-off-by: Samuel Ortiz --- drivers/mfd/db8500-prcmu.c | 45 ++++++++++++++------------------ drivers/mfd/dbx500-prcmu-regs.h | 1 + include/linux/mfd/db8500-prcmu.h | 7 +++-- include/linux/mfd/dbx500-prcmu.h | 7 +++-- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index bf5a054a2b91..f4adcabb2a51 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2269,10 +2269,10 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) /** * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem */ -void prcmu_ac_wake_req(void) +int prcmu_ac_wake_req(void) { u32 val; - u32 status; + int ret = 0; mutex_lock(&mb0_transfer.ac_wake_lock); @@ -2282,39 +2282,32 @@ void prcmu_ac_wake_req(void) atomic_set(&ac_wake_req_state, 1); -retry: - writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ); + /* + * Force Modem Wake-up before hostaccess_req ping-pong. + * It prevents Modem to enter in Sleep while acking the hostaccess + * request. The 31us delay has been calculated by HWI. + */ + val |= PRCM_HOSTACCESS_REQ_WAKE_REQ; + writel(val, PRCM_HOSTACCESS_REQ); + + udelay(31); + + val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ; + writel(val, PRCM_HOSTACCESS_REQ); if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, msecs_to_jiffies(5000))) { +#if defined(CONFIG_DBX500_PRCMU_DEBUG) + db8500_prcmu_debug_dump(__func__, true, true); +#endif pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n", __func__); - goto unlock_and_return; - } - - /* - * The modem can generate an AC_WAKE_ACK, and then still go to sleep. - * As a workaround, we wait, and then check that the modem is indeed - * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS - * register, which may not be the whole truth). - */ - udelay(400); - status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2)); - if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE | - PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) { - pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n", - __func__, status); - udelay(1200); - writel(val, PRCM_HOSTACCESS_REQ); - if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work, - msecs_to_jiffies(5000))) - goto retry; - pr_crit("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n", - __func__); + ret = -EFAULT; } unlock_and_return: mutex_unlock(&mb0_transfer.ac_wake_lock); + return ret; } /** diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index 3a0bf91d7780..23108a6e3167 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -106,6 +106,7 @@ #define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) #define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1 +#define PRCM_HOSTACCESS_REQ_WAKE_REQ BIT(16) #define ARM_WAKEUP_MODEM 0x1 #define PRCM_ARM_IT1_CLR (_PRCMU_BASE + 0x48C) diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index b3a43b1263fe..b82f6ee66a0b 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -530,7 +530,7 @@ int db8500_prcmu_stop_temp_sense(void); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); -void prcmu_ac_wake_req(void); +int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); void db8500_prcmu_modem_reset(void); @@ -680,7 +680,10 @@ static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) return -ENOSYS; } -static inline void prcmu_ac_wake_req(void) {} +static inline int prcmu_ac_wake_req(void) +{ + return 0; +} static inline void prcmu_ac_sleep_req(void) {} diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 5a13f93d8f1c..5b90e94399e1 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -345,7 +345,7 @@ static inline u16 prcmu_get_reset_code(void) return db8500_prcmu_get_reset_code(); } -void prcmu_ac_wake_req(void); +int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); static inline void prcmu_modem_reset(void) { @@ -533,7 +533,10 @@ static inline u16 prcmu_get_reset_code(void) return 0; } -static inline void prcmu_ac_wake_req(void) {} +static inline int prcmu_ac_wake_req(void) +{ + return 0; +} static inline void prcmu_ac_sleep_req(void) {} -- GitLab From b04c530c78464a02963adeed6b6e458535d7cd8f Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Fri, 29 Jun 2012 17:46:12 +0200 Subject: [PATCH 2234/5711] mfd: Print ab8500 switch off cause Instead of just printing the register value, also output some description of the value. Signed-off-by: Jonas Aaberg Reviewed-by: Mattias Wallin Signed-off-by: Linus Walleij Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-core.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 3eb15872c3a0..e580c5d535fb 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1232,6 +1232,15 @@ static struct attribute_group ab9540_attr_group = { static int __devinit ab8500_probe(struct platform_device *pdev) { + static char *switch_off_status[] = { + "Swoff bit programming", + "Thermal protection activation", + "Vbat lower then BattOk falling threshold", + "Watchdog expired", + "Non presence of 32kHz clock", + "Battery level lower than power on reset threshold", + "Power on key 1 pressed longer than 10 seconds", + "DB8500 thermal shutdown"}; struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); const struct platform_device_id *platid = platform_get_device_id(pdev); enum ab8500_version version = AB8500_VERSION_UNDEFINED; @@ -1327,7 +1336,20 @@ static int __devinit ab8500_probe(struct platform_device *pdev) AB8500_SWITCH_OFF_STATUS, &value); if (ret < 0) return ret; - dev_info(ab8500->dev, "switch off status: %#x\n", value); + dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); + + if (value) { + for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { + if (value & 1) + printk(KERN_CONT " \"%s\"", + switch_off_status[i]); + value = value >> 1; + + } + printk(KERN_CONT "\n"); + } else { + printk(KERN_CONT " None\n"); + } if (plat && plat->init) plat->init(ab8500); -- GitLab From b673e24c0ae041d02b51b13917ba89aafdd454ed Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Jun 2012 16:39:07 +0530 Subject: [PATCH 2235/5711] mfd: Add missing max8997 static storage class specifier Fixes the following sparse warnings: drivers/mfd/max8997.c:209:4: warning: symbol 'max8997_dumpaddr_pmic' was not declared. Should it be static? drivers/mfd/max8997.c:334:4: warning: symbol 'max8997_dumpaddr_muic' was not declared. Should it be static? drivers/mfd/max8997.c:344:4: warning: symbol 'max8997_dumpaddr_haptic' was not declared. Should it be static? drivers/mfd/max8997.c:426:25: warning: symbol 'max8997_pm' was not declared. Should it be static? Signed-off-by: Sachin Kamat Acked-by: MyungJoo Ham Signed-off-by: Samuel Ortiz --- drivers/mfd/max8997.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index cb83a7ab53e7..454f4992cfc3 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -206,7 +206,7 @@ static const struct i2c_device_id max8997_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); -u8 max8997_dumpaddr_pmic[] = { +static u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_INT1MSK, MAX8997_REG_INT2MSK, MAX8997_REG_INT3MSK, @@ -331,7 +331,7 @@ u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_DVSOKTIMER5, }; -u8 max8997_dumpaddr_muic[] = { +static u8 max8997_dumpaddr_muic[] = { MAX8997_MUIC_REG_INTMASK1, MAX8997_MUIC_REG_INTMASK2, MAX8997_MUIC_REG_INTMASK3, @@ -341,7 +341,7 @@ u8 max8997_dumpaddr_muic[] = { MAX8997_MUIC_REG_CONTROL3, }; -u8 max8997_dumpaddr_haptic[] = { +static u8 max8997_dumpaddr_haptic[] = { MAX8997_HAPTIC_REG_CONF1, MAX8997_HAPTIC_REG_CONF2, MAX8997_HAPTIC_REG_DRVCONF, @@ -423,7 +423,7 @@ static int max8997_resume(struct device *dev) return max8997_irq_resume(max8997); } -const struct dev_pm_ops max8997_pm = { +static const struct dev_pm_ops max8997_pm = { .suspend = max8997_suspend, .resume = max8997_resume, .freeze = max8997_freeze, -- GitLab From c1a2f31dfeb09c0c767fc178daa4a1e2855808a7 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 5 Jun 2012 18:08:50 +0800 Subject: [PATCH 2236/5711] mfd: Transfer rtc max8925 irq from MFD defined resources MAX8925 rtc irq is transfered from mfd resources now. Signed-off-by: Haojian Zhuang Signed-off-by: Samuel Ortiz --- drivers/mfd/max8925-core.c | 8 ++++---- drivers/rtc/rtc-max8925.c | 13 +++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index ca881efedf75..825a7f06d9ba 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -75,9 +75,9 @@ static struct mfd_cell power_devs[] = { static struct resource rtc_resources[] = { { .name = "max8925-rtc", - .start = MAX8925_RTC_IRQ, - .end = MAX8925_RTC_IRQ_MASK, - .flags = IORESOURCE_IO, + .start = MAX8925_IRQ_RTC_ALARM0, + .end = MAX8925_IRQ_RTC_ALARM0, + .flags = IORESOURCE_IRQ, }, }; @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], 0); + &rtc_resources[0], chip->irq_base); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 1459055a83aa..34e4349611db 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -69,6 +69,7 @@ struct max8925_rtc_info { struct max8925_chip *chip; struct i2c_client *rtc; struct device *dev; + int irq; }; static irqreturn_t rtc_update_handler(int irq, void *data) @@ -250,7 +251,7 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max8925_rtc_info *info; - int irq, ret; + int ret; info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL); if (!info) @@ -258,13 +259,13 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) info->chip = chip; info->rtc = chip->rtc; info->dev = &pdev->dev; - irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0; + info->irq = platform_get_irq(pdev, 0); - ret = request_threaded_irq(irq, NULL, rtc_update_handler, + ret = request_threaded_irq(info->irq, NULL, rtc_update_handler, IRQF_ONESHOT, "rtc-alarm0", info); if (ret < 0) { dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", - irq, ret); + info->irq, ret); goto out_irq; } @@ -285,7 +286,7 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) return 0; out_rtc: platform_set_drvdata(pdev, NULL); - free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); + free_irq(info->irq, info); out_irq: kfree(info); return ret; @@ -296,7 +297,7 @@ static int __devexit max8925_rtc_remove(struct platform_device *pdev) struct max8925_rtc_info *info = platform_get_drvdata(pdev); if (info) { - free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); + free_irq(info->irq, info); rtc_device_unregister(info->rtc_dev); kfree(info); } -- GitLab From 12477a32ff4265d4188442ff892c94871e81d6f7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 16:15:59 +0100 Subject: [PATCH 2237/5711] mfd: Staticise max77693 pm_ops They're not referenced outside this file. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 4055bc2d36fb..8eed0c47ade6 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -213,7 +213,7 @@ static int max77693_resume(struct device *dev) return max77693_irq_resume(max77693); } -const struct dev_pm_ops max77693_pm = { +static const struct dev_pm_ops max77693_pm = { .suspend = max77693_suspend, .resume = max77693_resume, }; -- GitLab From 8b7353d17542b2a513aa62a9856215e99ddb8403 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 6 Jun 2012 23:25:11 +0200 Subject: [PATCH 2238/5711] mfd: Delete ab5500-core.h Commit 72fb92200d6c31b9982c06784e4bcff2f5b7d8b6 ("mfd/ab5500: delete AB5500 support") deleted all files that used ab5500-core.h. That file apparently was simply overlooked. Delete it too. Acked-by: Linus Walleij Signed-off-by: Paul Bolle Signed-off-by: Samuel Ortiz --- drivers/mfd/ab5500-core.h | 87 --------------------------------------- 1 file changed, 87 deletions(-) delete mode 100644 drivers/mfd/ab5500-core.h diff --git a/drivers/mfd/ab5500-core.h b/drivers/mfd/ab5500-core.h deleted file mode 100644 index 63b30b17e4f3..000000000000 --- a/drivers/mfd/ab5500-core.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2011 ST-Ericsson - * License terms: GNU General Public License (GPL) version 2 - * Shared definitions and data structures for the AB5500 MFD driver - */ - -/* Read/write operation values. */ -#define AB5500_PERM_RD (0x01) -#define AB5500_PERM_WR (0x02) - -/* Read/write permissions. */ -#define AB5500_PERM_RO (AB5500_PERM_RD) -#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR) - -#define AB5500_MASK_BASE (0x60) -#define AB5500_MASK_END (0x79) -#define AB5500_CHIP_ID (0x20) - -/** - * struct ab5500_reg_range - * @first: the first address of the range - * @last: the last address of the range - * @perm: access permissions for the range - */ -struct ab5500_reg_range { - u8 first; - u8 last; - u8 perm; -}; - -/** - * struct ab5500_i2c_ranges - * @count: the number of ranges in the list - * @range: the list of register ranges - */ -struct ab5500_i2c_ranges { - u8 nranges; - u8 bankid; - const struct ab5500_reg_range *range; -}; - -/** - * struct ab5500_i2c_banks - * @count: the number of ranges in the list - * @range: the list of register ranges - */ -struct ab5500_i2c_banks { - u8 nbanks; - const struct ab5500_i2c_ranges *bank; -}; - -/** - * struct ab5500_bank - * @slave_addr: I2C slave_addr found in AB5500 specification - * @name: Documentation name of the bank. For reference - */ -struct ab5500_bank { - u8 slave_addr; - const char *name; -}; - -static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = { - [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = { - AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"}, - [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = { - AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"}, - [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"}, - [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"}, - [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"}, - [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"}, - [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"}, - [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"}, - [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"}, - [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"}, - [AB5500_BANK_FG_BATTCOM_ACC] = { - AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"}, - [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"}, - [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"}, - [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"}, - [AB5500_BANK_AUDIO_HEADSETUSB] = { - AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"}, -}; - -int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg, - u8 *value); -int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank, - u8 reg, u8 bitmask, u8 bitvalues); -- GitLab From ff2b7ac6f6c58b0011d9d73004fb6e396f514018 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 08:35:37 +0800 Subject: [PATCH 2239/5711] mfd: Fix max77693 irq leak and wrong kfree call We need to call max77693_irq_exit() in max77693_i2c_probe error patch and max77693_i2c_remove. Current code already uses devm_kzalloc() to allocate memory for max77693. Thus we should not call kfree(max77693), otherwise we got double free. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 8eed0c47ade6..a1811cb50ec7 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -154,7 +154,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, ret = max77693_irq_init(max77693); if (ret < 0) - goto err_mfd; + goto err_irq; pm_runtime_set_active(max77693->dev); @@ -168,11 +168,11 @@ static int max77693_i2c_probe(struct i2c_client *i2c, return ret; err_mfd: + max77693_irq_exit(max77693); +err_irq: i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); err_regmap: - kfree(max77693); - return ret; } @@ -181,6 +181,7 @@ static int max77693_i2c_remove(struct i2c_client *i2c) struct max77693_dev *max77693 = i2c_get_clientdata(i2c); mfd_remove_devices(max77693->dev); + max77693_irq_exit(max77693); i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); -- GitLab From a834e81051fd51890bd9a64e109b587f8e12199a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 8 Jun 2012 11:54:21 +0300 Subject: [PATCH 2240/5711] mfd: Update twl6040 Kconfig to avoid build breakage twl6040 needs CONFIG_IRQ_DOMAIN to compile, without this we have: drivers/mfd/twl6040-irq.c: In function 'twl6040_irq_init': drivers/mfd/twl6040-irq.c:164:2: error: implicit declaration of function 'irq_domain_add_legacy' drivers/mfd/twl6040-irq.c:165:11: error: 'irq_domain_simple_ops' undeclared (first use in this function) drivers/mfd/twl6040-irq.c:165:11: note: each undeclared identifier is reported only once for each function it appears in Reported-by: Randy Dunlap Signed-off-by: Peter Ujfalusi Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d43876c6da23..b3dee92fd3a8 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -287,6 +287,7 @@ config TWL6040_CORE depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C + select IRQ_DOMAIN default n help Say yes here if you want support for Texas Instruments TWL6040 audio -- GitLab From 78a27cd3e891e8da343942aec10c926eaffabd63 Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Tue, 12 Jun 2012 00:43:35 +0800 Subject: [PATCH 2241/5711] mfd: Restore wm8994 pin configuration after reset during suspend Ensure that we leave the device with the pins in the expected configuration if we leave it in reset over suspend, avoiding any interoperation problems with other devices in the system. Signed-off-by: Chris Rattray Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 1e321d349777..f75cdccd1043 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -196,6 +196,7 @@ static int wm8994_suspend(struct device *dev) { struct wm8994 *wm8994 = dev_get_drvdata(dev); int ret; + int gpio_regs[WM8994_NUM_GPIO_REGS]; /* Don't actually go through with the suspend if the CODEC is * still active (eg, for audio passthrough from CP. */ @@ -277,12 +278,24 @@ static int wm8994_suspend(struct device *dev) WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD); + /* Save GPIO registers before reset */ + regmap_bulk_read(wm8994->regmap, WM8994_GPIO_1, gpio_regs, + WM8994_NUM_GPIO_REGS); + /* Explicitly put the device into reset in case regulators * don't get disabled in order to ensure consistent restart. */ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET)); + /* Restore GPIO registers to prevent problems with mismatched + * pin configurations. + */ + ret = regmap_bulk_write(wm8994->regmap, WM8994_GPIO_1, gpio_regs, + WM8994_NUM_GPIO_REGS); + if (ret != 0) + dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); + regcache_cache_only(wm8994->regmap, true); regcache_mark_dirty(wm8994->regmap); -- GitLab From 7f0f07ce25b62be9234998134f19e1511a9ad6c7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Jun 2012 20:26:58 +0200 Subject: [PATCH 2242/5711] mfd: Use devm allocation for ab3100-core Allocate memory and irq for device state using devm_* helpers to simplify memory accounting. Signed-off-by: Linus Walleij Signed-off-by: Samuel Ortiz --- drivers/mfd/ab3100-core.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 1efad20fb175..4276aab4f196 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -867,7 +867,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, int err; int i; - ab3100 = kzalloc(sizeof(struct ab3100), GFP_KERNEL); + ab3100 = devm_kzalloc(&client->dev, sizeof(struct ab3100), GFP_KERNEL); if (!ab3100) { dev_err(&client->dev, "could not allocate AB3100 device\n"); return -ENOMEM; @@ -921,7 +921,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, /* Attach a second dummy i2c_client to the test register address */ ab3100->testreg_client = i2c_new_dummy(client->adapter, - client->addr + 1); + client->addr + 1); if (!ab3100->testreg_client) { err = -ENOMEM; goto exit_no_testreg_client; @@ -931,13 +931,13 @@ static int __devinit ab3100_probe(struct i2c_client *client, if (err) goto exit_no_setup; - err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, - IRQF_ONESHOT, "ab3100-core", ab3100); - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); - + err = devm_request_threaded_irq(&client->dev, + client->irq, NULL, ab3100_irq_handler, + IRQF_ONESHOT, "ab3100-core", ab3100); if (err) goto exit_no_irq; + /* This real unpredictable IRQ is of course sampled for entropy */ + rand_initialize_irq(client->irq); err = abx500_register_ops(&client->dev, &ab3100_ops); if (err) @@ -962,7 +962,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, i2c_unregister_device(ab3100->testreg_client); exit_no_testreg_client: exit_no_detect: - kfree(ab3100); return err; } @@ -972,16 +971,8 @@ static int __devexit ab3100_remove(struct i2c_client *client) /* Unregister subdevices */ mfd_remove_devices(&client->dev); - ab3100_remove_debugfs(); i2c_unregister_device(ab3100->testreg_client); - - /* - * At this point, all subscribers should have unregistered - * their notifiers so deactivate IRQ - */ - free_irq(client->irq, ab3100); - kfree(ab3100); return 0; } -- GitLab From 2761a63945164ef111062828858a80225222ecd7 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Thu, 14 Jun 2012 09:24:21 -0700 Subject: [PATCH 2243/5711] mfd: USB: Fix the omap-usb EHCI ULPI PHY reset fix issues. 'ARM: OMAP3: USB: Fix the EHCI ULPI PHY reset issue' (1fcb57d0) fixes an issue where the ULPI PHYs were not held in reset while initializing the EHCI controller. However, it also changes behavior in omap-usb-host.c omap_usbhs_init by releasing reset while the configuration in that function was done. This change caused a regression on BB-xM where USB would not function if 'usb start' had been run from u-boot before booting. A change was made to release reset a little bit earlier which fixed the issue on BB-xM and did not cause any regressions on 3430 sdp, the board for which the fix was originally made. This new fix, 'USB: EHCI: OMAP: Finish ehci omap phy reset cycle before adding hcd.', (3aa2ae74) caused a regression on OMAP5. The original fix to hold the EHCI controller in reset during initialization was correct, however it appears that changing omap_usbhs_init to not hold the PHYs in reset during it's configuration was incorrect. This patch first reverts both fixes, and then changes ehci_hcd_omap_probe in ehci-omap.c to hold the PHYs in reset as the original patch had done. It also is sure to incorporate the _cansleep change that has been made in the meantime. I've tested this on Beagleboard xM, I'd really like to get an ack from the 3430 sdp and OMAP5 guys before getting this merged. v3 - Brown paper bag its too early in the morning actually run git commit amend fix v2 - Put cansleep gpiolib call outside of spinlock Acked-by: Mantesh Sarashetti Tested-by: Mantesh Sarashetti Acked-by: Keshava Munegowda Tested-by: Keshava Munegowda Signed-off-by: Russ Dill Signed-off-by: Samuel Ortiz --- drivers/mfd/omap-usb-host.c | 48 +++++++++++++++++++++++++++++++++++- drivers/usb/host/ehci-omap.c | 18 ++++++-------- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 7e96bb229724..41088ecbb2a9 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -500,8 +501,21 @@ static void omap_usbhs_init(struct device *dev) dev_dbg(dev, "starting TI HSUSB Controller\n"); pm_runtime_get_sync(dev); - spin_lock_irqsave(&omap->lock, flags); + if (pdata->ehci_data->phy_reset) { + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) + gpio_request_one(pdata->ehci_data->reset_gpio_port[0], + GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) + gpio_request_one(pdata->ehci_data->reset_gpio_port[1], + GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + + /* Hold the PHY in RESET for enough time till DIR is high */ + udelay(10); + } + + spin_lock_irqsave(&omap->lock, flags); omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); @@ -581,9 +595,39 @@ static void omap_usbhs_init(struct device *dev) } spin_unlock_irqrestore(&omap->lock, flags); + + if (pdata->ehci_data->phy_reset) { + /* Hold the PHY in RESET for enough time till + * PHY is settled and ready + */ + udelay(10); + + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) + gpio_set_value_cansleep + (pdata->ehci_data->reset_gpio_port[0], 1); + + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) + gpio_set_value_cansleep + (pdata->ehci_data->reset_gpio_port[1], 1); + } + pm_runtime_put_sync(dev); } +static void omap_usbhs_deinit(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; + + if (pdata->ehci_data->phy_reset) { + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) + gpio_free(pdata->ehci_data->reset_gpio_port[0]); + + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) + gpio_free(pdata->ehci_data->reset_gpio_port[1]); + } +} + /** * usbhs_omap_probe - initialize TI-based HCDs @@ -767,6 +811,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) goto end_probe; err_alloc: + omap_usbhs_deinit(&pdev->dev); iounmap(omap->tll_base); err_tll: @@ -818,6 +863,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) { struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); + omap_usbhs_deinit(&pdev->dev); iounmap(omap->tll_base); iounmap(omap->uhh_base); clk_put(omap->init_60m_fclk); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 17cfb8a1131c..c30435499a02 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -281,14 +281,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } } + /* Hold PHYs in reset while initializing EHCI controller */ if (pdata->phy_reset) { if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_request_one(pdata->reset_gpio_port[0], - GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_request_one(pdata->reset_gpio_port[1], - GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); /* Hold the PHY in RESET for enough time till DIR is high */ udelay(10); @@ -330,6 +329,11 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); ehci_reset(omap_ehci); + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) { + dev_err(dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } if (pdata->phy_reset) { /* Hold the PHY in RESET for enough time till @@ -344,12 +348,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret) { - dev_err(dev, "failed to add hcd with err %d\n", ret); - goto err_add_hcd; - } - /* root ports should always stay powered */ ehci_port_power(omap_ehci, 1); -- GitLab From e03088972f6e38e90077eaf09acf7b8a327a2da2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Jul 2012 16:03:00 +0800 Subject: [PATCH 2244/5711] mfd: Fix mc13xxx-spi merge conflict This patch fixes conflict between commit 8ae3559 "mfd: mc13xxx workaround SPI hardware bug on i.Mx" and commit 10c7a5d "mfd: Use devm_* APIs for mc13xxx". commit 8ae3559 changes regmap_init_spi to regmap_init. So now we need to use devm_regmap_init rather than devm_regmap_init_spi. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 234207f7a831..35636261da6c 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -139,7 +139,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = devm_regmap_init_spi(spi, &mc13xxx_regmap_spi_config); + mc13xxx->regmap = devm_regmap_init(&spi->dev, ®map_mc13xxx_bus, + &spi->dev, + &mc13xxx_regmap_spi_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", -- GitLab From 938848e7a5550ce28036ab30e2900b4672a540ee Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Jul 2012 16:53:52 +0800 Subject: [PATCH 2245/5711] mfd: Guard adp5520 PM methods with CONFIG_PM_SLEEP This fixes below build warnings: CC drivers/mfd/adp5520.o drivers/mfd/adp5520.c:324:12: warning: 'adp5520_suspend' defined but not used [-Wunused-function] drivers/mfd/adp5520.c:333:12: warning: 'adp5520_resume' defined but not used [-Wunused-function] Signed-off-by: Axel Lin Acked-by: Michael Hennerich Signed-off-by: Samuel Ortiz --- drivers/mfd/adp5520.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 8d816cce8322..ea8b9475731d 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -320,7 +320,7 @@ static int __devexit adp5520_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int adp5520_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); -- GitLab From 930bf02299943c67a52919a23a3eaf5ee9abbbe1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Jul 2012 17:19:52 +0800 Subject: [PATCH 2246/5711] mfd: Guard tc3589x PM methods with CONFIG_PM_SLEEP Guard PM methods with CONFIG_PM_SLEEP and get rid of some unneeded #ifdefs. This fixes below build warnings: CC drivers/mfd/tc3589x.o drivers/mfd/tc3589x.c:361:12: warning: 'tc3589x_suspend' defined but not used [-Wunused-function] drivers/mfd/tc3589x.c:375:12: warning: 'tc3589x_resume' defined but not used [-Wunused-function] SIMPLE_DEV_PM_OPS already defines constant dev_pm_ops, thus also fix 'duplicate const' sparse warning. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/tc3589x.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index de979742c6fc..048bf0532a09 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -357,7 +357,7 @@ static int __devexit tc3589x_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tc3589x_suspend(struct device *dev) { struct tc3589x *tc3589x = dev_get_drvdata(dev); @@ -385,11 +385,10 @@ static int tc3589x_resume(struct device *dev) return ret; } - -static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, - tc3589x_resume); #endif +static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume); + static const struct i2c_device_id tc3589x_id[] = { { "tc3589x", 24 }, { } @@ -399,9 +398,7 @@ MODULE_DEVICE_TABLE(i2c, tc3589x_id); static struct i2c_driver tc3589x_driver = { .driver.name = "tc3589x", .driver.owner = THIS_MODULE, -#ifdef CONFIG_PM .driver.pm = &tc3589x_dev_pm_ops, -#endif .probe = tc3589x_probe, .remove = __devexit_p(tc3589x_remove), .id_table = tc3589x_id, -- GitLab From 2968ab133ec790134d4347aa4264c2eb064b42e7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Jul 2012 10:50:19 +0100 Subject: [PATCH 2247/5711] mfd: Attaching a node to new 'struct mfd_cell' of_compatible variable Applying a succinct description to the of_compatible variable recently added to the mfd_cell struct. Also link to the documentation page where more information can be found about compatible properties. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- include/linux/mfd/core.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 99b7eb1961b6..3a8435a8058f 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -36,6 +36,10 @@ struct mfd_cell { /* platform data passed to the sub devices drivers */ void *platform_data; size_t pdata_size; + /* + * Device Tree compatible string + * See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details + */ const char *of_compatible; /* -- GitLab From bad76991d7847b7877ae797cc79745d82ffd9120 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Jul 2012 17:10:56 +0200 Subject: [PATCH 2248/5711] mfd: Register ab8500 devices using the newly DT:ed MFD API Now the MFD API is Device Tree aware we can use it for platform registration again, even when booting with DT enabled. To aid in Device Node pointer allocation we provide each cell with the associative compatible string. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- arch/arm/mach-ux500/board-mop500.c | 1 - drivers/mfd/ab8500-core.c | 64 ++++++++++++++++++------------ drivers/mfd/ab8500-debugfs.c | 6 --- drivers/mfd/ab8500-gpadc.c | 6 --- drivers/mfd/ab8500-sysctrl.c | 6 --- drivers/misc/ab8500-pwm.c | 6 --- drivers/regulator/ab8500.c | 6 --- 7 files changed, 39 insertions(+), 56 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 44d816ffaeb6..6224400a9d47 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -793,7 +793,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, { .compatible = "stericsson,db8500-prcmu", }, - { .compatible = "stericsson,ab8500-regulator", }, { .compatible = "simple-bus"}, { }, }; diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index e580c5d535fb..626b4ecaf647 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -970,54 +970,69 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", + .of_compatible = "stericsson,ab8500-debug", .num_resources = ARRAY_SIZE(ab8500_debug_resources), .resources = ab8500_debug_resources, }, #endif { .name = "ab8500-sysctrl", + .of_compatible = "stericsson,ab8500-sysctrl", }, { .name = "ab8500-regulator", + .of_compatible = "stericsson,ab8500-regulator", }, { .name = "ab8500-gpadc", + .of_compatible = "stericsson,ab8500-gpadc", .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), .resources = ab8500_gpadc_resources, }, { .name = "ab8500-rtc", + .of_compatible = "stericsson,ab8500-rtc", .num_resources = ARRAY_SIZE(ab8500_rtc_resources), .resources = ab8500_rtc_resources, }, { .name = "ab8500-acc-det", + .of_compatible = "stericsson,ab8500-acc-det", .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), .resources = ab8500_av_acc_detect_resources, }, { .name = "ab8500-poweron-key", + .of_compatible = "stericsson,ab8500-poweron-key", .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), .resources = ab8500_poweronkey_db_resources, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 1, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 2, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 3, }, - { .name = "ab8500-leds", }, + { + .name = "ab8500-leds", + .of_compatible = "stericsson,ab8500-leds", + }, { .name = "ab8500-denc", + .of_compatible = "stericsson,ab8500-denc", }, { .name = "ab8500-temp", + .of_compatible = "stericsson,ab8500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, }, @@ -1049,11 +1064,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { static struct mfd_cell __devinitdata ab8500_devs[] = { { .name = "ab8500-gpio", + .of_compatible = "stericsson,ab8500-gpio", .num_resources = ARRAY_SIZE(ab8500_gpio_resources), .resources = ab8500_gpio_resources, }, { .name = "ab8500-usb", + .of_compatible = "stericsson,ab8500-usb", .num_resources = ARRAY_SIZE(ab8500_usb_resources), .resources = ab8500_usb_resources, }, @@ -1399,32 +1416,29 @@ static int __devinit ab8500_probe(struct platform_device *pdev) goto out_freeoldmask; } - if (!np) { - ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, - ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base); + ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, + ARRAY_SIZE(abx500_common_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; - if (ret) - goto out_freeirq; - - if (is_ab9540(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, - ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base); - else - ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, - ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base); - if (ret) - goto out_freeirq; + if (is_ab9540(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, + ARRAY_SIZE(ab9540_devs), NULL, + ab8500->irq_base); + else + ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, + ARRAY_SIZE(ab8500_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; - if (is_ab9540(ab8500) || is_ab8505(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, - ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base); - if (ret) - goto out_freeirq; - } + if (is_ab9540(ab8500) || is_ab8505(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, + ARRAY_SIZE(ab9540_ab8505_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; if (!no_bm) { /* Add battery management devices */ diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 361de52aefe5..c4cb806978ac 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -608,16 +608,10 @@ static int __devexit ab8500_debug_remove(struct platform_device *plf) return 0; } -static const struct of_device_id ab8500_debug_match[] = { - { .compatible = "stericsson,ab8500-debug", }, - {} -}; - static struct platform_driver ab8500_debug_driver = { .driver = { .name = "ab8500-debug", .owner = THIS_MODULE, - .of_match_table = ab8500_debug_match, }, .probe = ab8500_debug_probe, .remove = __devexit_p(ab8500_debug_remove) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index b6cbc3ba2695..866f95960b4b 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -649,18 +649,12 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_gpadc_match[] = { - { .compatible = "stericsson,ab8500-gpadc", }, - {} -}; - static struct platform_driver ab8500_gpadc_driver = { .probe = ab8500_gpadc_probe, .remove = __devexit_p(ab8500_gpadc_remove), .driver = { .name = "ab8500-gpadc", .owner = THIS_MODULE, - .of_match_table = ab8500_gpadc_match, }, }; diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 5a3e51ccf258..c28d4eb1eff0 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -61,16 +61,10 @@ static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_sysctrl_match[] = { - { .compatible = "stericsson,ab8500-sysctrl", }, - {} -}; - static struct platform_driver ab8500_sysctrl_driver = { .driver = { .name = "ab8500-sysctrl", .owner = THIS_MODULE, - .of_match_table = ab8500_sysctrl_match, }, .probe = ab8500_sysctrl_probe, .remove = __devexit_p(ab8500_sysctrl_remove), diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 042a8fe4efaa..d7a9aa14e5d5 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -142,16 +142,10 @@ static int __devexit ab8500_pwm_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_pwm_match[] = { - { .compatible = "stericsson,ab8500-pwm", }, - {} -}; - static struct platform_driver ab8500_pwm_driver = { .driver = { .name = "ab8500-pwm", .owner = THIS_MODULE, - .of_match_table = ab8500_pwm_match, }, .probe = ab8500_pwm_probe, .remove = __devexit_p(ab8500_pwm_remove), diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index a739f5ca936a..6745bd248da4 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -906,18 +906,12 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_regulator_match[] = { - { .compatible = "stericsson,ab8500-regulator", }, - {} -}; - static struct platform_driver ab8500_regulator_driver = { .probe = ab8500_regulator_probe, .remove = __devexit_p(ab8500_regulator_remove), .driver = { .name = "ab8500-regulator", .owner = THIS_MODULE, - .of_match_table = ab8500_regulator_match, }, }; -- GitLab From b41511f713ccaef666e450fae8cb18909897fe4e Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 2 Jul 2012 09:02:55 +0900 Subject: [PATCH 2249/5711] mfd: Add irq domain support for max8997 interrupts Add irq domain support for max8997 interrupts. The reverse mapping method used is linear mapping since the sub-drivers of max8997 such as regulator and charger drivers can use the max8997 irq_domain to get the linux irq number for max8997 interrupts. All uses of irq_base in platform data and max8997 driver private data are removed. Reviwed-by: Mark Brown Acked-by: MyungJoo Ham Acked-by: Grant Likely Signed-off-by: Thomas Abraham Signed-off-by: Chanwoo Choi Signed-off-by: Kyungmin Park Signed-off-by: Samuel Ortiz --- arch/arm/mach-exynos/mach-nuri.c | 4 -- arch/arm/mach-exynos/mach-origen.c | 1 - drivers/mfd/Kconfig | 1 + drivers/mfd/max8997-irq.c | 62 +++++++++++++++++------------ drivers/mfd/max8997.c | 1 - include/linux/mfd/max8997-private.h | 4 +- include/linux/mfd/max8997.h | 1 - 7 files changed, 41 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 656f8fc9addd..acb58f5cee8d 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -1067,12 +1067,8 @@ static struct platform_device nuri_max8903_device = { static void __init nuri_power_init(void) { int gpio; - int irq_base = IRQ_GPIO_END + 1; int ta_en = 0; - nuri_max8997_pdata.irq_base = irq_base; - irq_base += MAX8997_IRQ_NR; - gpio = EXYNOS4_GPX0(7); gpio_request(gpio, "AP_PMIC_IRQ"); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index f5572be9d7bf..3ce403d7cf1c 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -425,7 +425,6 @@ static struct max8997_platform_data __initdata origen_max8997_pdata = { .buck1_gpiodvs = false, .buck2_gpiodvs = false, .buck5_gpiodvs = false, - .irq_base = IRQ_GPIO_END + 1, .ignore_gpiodvs_side_effect = true, .buck125_default_idx = 0x0, diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b3dee92fd3a8..aaa048a437c0 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -464,6 +464,7 @@ config MFD_MAX8997 bool "Maxim Semiconductor MAX8997/8966 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select IRQ_DOMAIN help Say yes here to support for Maxim Semiconductor MAX8997/8966. This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic, diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index 09274cf7c33b..43fa61413e93 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c @@ -142,7 +142,8 @@ static void max8997_irq_sync_unlock(struct irq_data *data) static const inline struct max8997_irq_data * irq_to_max8997_irq(struct max8997_dev *max8997, int irq) { - return &max8997_irqs[irq - max8997->irq_base]; + struct irq_data *data = irq_get_irq_data(irq); + return &max8997_irqs[data->hwirq]; } static void max8997_irq_mask(struct irq_data *data) @@ -182,7 +183,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {}; u8 irq_src; int ret; - int i; + int i, cur_irq; ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src); if (ret < 0) { @@ -269,8 +270,11 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8997_IRQ_NR; i++) { - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) - handle_nested_irq(max8997->irq_base + i); + if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) { + cur_irq = irq_find_mapping(max8997->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); + } } return IRQ_HANDLED; @@ -278,26 +282,40 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) int max8997_irq_resume(struct max8997_dev *max8997) { - if (max8997->irq && max8997->irq_base) - max8997_irq_thread(max8997->irq_base, max8997); + if (max8997->irq && max8997->irq_domain) + max8997_irq_thread(0, max8997); + return 0; +} + +static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max8997_dev *max8997 = d->host_data; + + irq_set_chip_data(irq, max8997); + irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif return 0; } +static struct irq_domain_ops max8997_irq_domain_ops = { + .map = max8997_irq_domain_map, +}; + int max8997_irq_init(struct max8997_dev *max8997) { + struct irq_domain *domain; int i; - int cur_irq; int ret; u8 val; if (!max8997->irq) { dev_warn(max8997->dev, "No interrupt specified.\n"); - max8997->irq_base = 0; - return 0; - } - - if (!max8997->irq_base) { - dev_err(max8997->dev, "No interrupt base specified.\n"); return 0; } @@ -327,19 +345,13 @@ int max8997_irq_init(struct max8997_dev *max8997) true : false; } - /* Register with genirq */ - for (i = 0; i < MAX8997_IRQ_NR; i++) { - cur_irq = i + max8997->irq_base; - irq_set_chip_data(cur_irq, max8997); - irq_set_chip_and_handler(cur_irq, &max8997_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif + domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR, + &max8997_irq_domain_ops, max8997); + if (!domain) { + dev_err(max8997->dev, "could not create irq domain\n"); + return -ENODEV; } + max8997->irq_domain = domain; ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 454f4992cfc3..10b629c245b6 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -143,7 +143,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c, if (!pdata) goto err; - max8997->irq_base = pdata->irq_base; max8997->ono = pdata->ono; mutex_init(&max8997->iolock); diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index 3f4deb62d6b0..830152cfae33 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -23,6 +23,8 @@ #define __LINUX_MFD_MAX8997_PRIV_H #include +#include +#include #define MAX8997_REG_INVALID (0xff) @@ -325,7 +327,7 @@ struct max8997_dev { int irq; int ono; - int irq_base; + struct irq_domain *irq_domain; struct mutex irqlock; int irq_masks_cur[MAX8997_IRQ_GROUP_NR]; int irq_masks_cache[MAX8997_IRQ_GROUP_NR]; diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h index b40c08cd30bc..328d8e24b533 100644 --- a/include/linux/mfd/max8997.h +++ b/include/linux/mfd/max8997.h @@ -181,7 +181,6 @@ struct max8997_led_platform_data { struct max8997_platform_data { /* IRQ */ - int irq_base; int ono; int wakeup; -- GitLab From dca1a71e4108a0a9051a653d885297e9d1cc656c Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 2 Jul 2012 09:03:00 +0900 Subject: [PATCH 2250/5711] extcon: Add support irq domain for MAX8997 muic This patch add support irq domain for Maxim MAX8997 muic instead of irq_base in platform data and max8997 driver private data are instead. It is tested on TRATS board. Cc: Greg Kroah-Hartman Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Samuel Ortiz --- drivers/extcon/Kconfig | 2 +- drivers/extcon/extcon-max8997.c | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 29c5cf852efc..bf6b2eae5751 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -23,7 +23,7 @@ config EXTCON_GPIO config EXTCON_MAX8997 tristate "MAX8997 EXTCON Support" - depends on MFD_MAX8997 + depends on MFD_MAX8997 && IRQ_DOMAIN help If you say yes here you get support for the MUIC device of Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index a4ed30bd9a41..ef9090a4271d 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -26,6 +26,7 @@ #include #include #include +#include #define DEV_NAME "max8997-muic" @@ -77,6 +78,7 @@ struct max8997_muic_irq { unsigned int irq; const char *name; + unsigned int virq; }; static struct max8997_muic_irq muic_irqs[] = { @@ -343,12 +345,10 @@ static void max8997_muic_irq_work(struct work_struct *work) { struct max8997_muic_info *info = container_of(work, struct max8997_muic_info, irq_work); - struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); u8 status[2]; u8 adc, chg_type; - - int irq_type = info->irq - max8997->irq_base; - int ret; + int irq_type = 0; + int i, ret; mutex_lock(&info->mutex); @@ -363,6 +363,10 @@ static void max8997_muic_irq_work(struct work_struct *work) dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__, status[0], status[1]); + for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++) + if (info->irq == muic_irqs[i].virq) + irq_type = muic_irqs[i].irq; + switch (irq_type) { case MAX8997_MUICIRQ_ADC: adc = status[0] & STATUS1_ADC_MASK; @@ -448,11 +452,15 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max8997_muic_irq *muic_irq = &muic_irqs[i]; + int virq = 0; + + virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq); + if (!virq) + goto err_irq; + muic_irq->virq = virq; - ret = request_threaded_irq(pdata->irq_base + muic_irq->irq, - NULL, max8997_muic_irq_handler, - 0, muic_irq->name, - info); + ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler, + 0, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d," @@ -496,7 +504,7 @@ err_extcon: kfree(info->edev); err_irq: while (--i >= 0) - free_irq(pdata->irq_base + muic_irqs[i].irq, info); + free_irq(muic_irqs[i].virq, info); kfree(info); err_kfree: return ret; @@ -505,11 +513,10 @@ err_kfree: static int __devexit max8997_muic_remove(struct platform_device *pdev) { struct max8997_muic_info *info = platform_get_drvdata(pdev); - struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); int i; for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) - free_irq(max8997->irq_base + muic_irqs[i].irq, info); + free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); -- GitLab From 56dbd61f297d8d645856f604536bcd856ab9060a Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Fri, 22 Jun 2012 13:36:18 +0100 Subject: [PATCH 2251/5711] mfd: Fix palmas regulator pdata missing Due to a merge error the section of code passing the pdata for the regulator driver to the mfd_add_devices via the children structure was missing. This corrects this problem. Signed-off-by: Graeme Gregory Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 5d896b352284..98fdcdbbd610 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -441,6 +441,9 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, goto err; } + children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata; + children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata); + ret = mfd_add_devices(palmas->dev, -1, children, ARRAY_SIZE(palmas_children), NULL, regmap_irq_chip_get_base(palmas->irq_data)); -- GitLab From 54210c97c8bfff67a4c5ec09ff797543bf291d6b Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Fri, 22 Jun 2012 13:36:19 +0100 Subject: [PATCH 2252/5711] mfd: Add missing hunk to change palmas irq to clear on read During conversion to regmap_irq this hunk was missing being moved to MFD driver to put the chip into clear on read mode. Also as slave is now set use it to determine which slave for the register call. Signed-off-by: Graeme Gregory Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 98fdcdbbd610..c4a69f193a1d 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -356,7 +356,14 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, } } - ret = regmap_add_irq_chip(palmas->regmap[1], palmas->irq, + /* Change IRQ into clear on read mode for efficiency */ + slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); + addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); + reg = PALMAS_INT_CTRL_INT_CLEAR; + + regmap_write(palmas->regmap[slave], addr, reg); + + ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip, &palmas->irq_data); if (ret < 0) -- GitLab From 712db99df155eeef7bbab8677d8a02d0eff50d11 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 28 Jun 2012 12:20:21 +0200 Subject: [PATCH 2253/5711] mfd: Add support for enabling tps65910 external 32-kHz oscillator Add flag to platform data to enable external 32-kHz crystal oscillator (or square wave) input. The tps6591x can use either an internal 32-kHz RC oscillator or an external crystal (or square wave) to generate the 32-kHz clock. The default setting depends on the selected boot mode. In boot mode 00 the internal RC oscillator is used at power-on, but the external crystal oscillator (or square wave) can be enabled by clearing the ck32k_ctrl flag in the device control register. Note that there is no way to switch from the external crystal oscillator to the internal RC oscillator. Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz --- drivers/mfd/tps65910.c | 21 ++++++++++++++++++++- include/linux/mfd/tps65910.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index be9e07b77325..b0526b7d6550 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -68,6 +68,25 @@ static const struct regmap_config tps65910_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static int __devinit tps65910_misc_init(struct tps65910 *tps65910, + struct tps65910_board *pmic_pdata) +{ + struct device *dev = tps65910->dev; + int ret; + + if (pmic_pdata->en_ck32k_xtal) { + ret = tps65910_reg_clear_bits(tps65910, + TPS65910_DEVCTRL, + DEVCTRL_CK32K_CTRL_MASK); + if (ret < 0) { + dev_err(dev, "clear ck32k_ctrl failed: %d\n", ret); + return ret; + } + } + + return 0; +} + static int __devinit tps65910_sleepinit(struct tps65910 *tps65910, struct tps65910_board *pmic_pdata) { @@ -243,7 +262,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, init_data->irq_base = pmic_plat_data->irq_base; tps65910_irq_init(tps65910, init_data->irq, init_data); - + tps65910_misc_init(tps65910, pmic_plat_data); tps65910_sleepinit(tps65910, pmic_plat_data); return ret; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index dd8dc0a6c462..a989d2b066be 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -807,6 +807,7 @@ struct tps65910_board { int irq_base; int vmbch_threshold; int vmbch2_threshold; + bool en_ck32k_xtal; bool en_dev_slp; struct tps65910_sleep_keepon_data *slp_keepon; bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; -- GitLab From bcc1dd4cd77ec168894ea325b4e89b15a8b5b4f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 28 Jun 2012 12:20:22 +0200 Subject: [PATCH 2254/5711] mfd: Add device-tree entry to enable tps65910 external 32-kHz oscillator Add device-tree entry to enable external 32-kHz crystal oscillator input. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz --- Documentation/devicetree/bindings/mfd/tps65910.txt | 4 +++- drivers/mfd/tps65910.c | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index 645f5eaadb3f..0f5d9b74f4b9 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -29,6 +29,8 @@ Optional properties: comparator. (see VMBCH_VSEL in TPS65910 datasheet) - ti,vmbch2-threshold: (tps65911) main battery discharged threshold comparator. (see VMBCH_VSEL in TPS65910 datasheet) +- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL + in TPS6591X datasheet) - ti,en-gpio-sleep: enable sleep control for gpios There should be 9 entries here, one for each gpio. @@ -53,7 +55,7 @@ Example: ti,vmbch-threshold = 0; ti,vmbch2-threshold = 0; - + ti,en-ck32k-xtal; ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; regulators { diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index b0526b7d6550..3f27ea1f1ba6 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -194,6 +194,9 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, else if (*chip_id == TPS65911) dev_warn(&client->dev, "VMBCH2-Threshold not specified"); + prop = of_property_read_bool(np, "ti,en-ck32k-xtal"); + board_info->en_ck32k_xtal = prop; + board_info->irq = client->irq; board_info->irq_base = -1; -- GitLab From 2573f6d36e73e080fc1d9d9ac7dfaf2253a61434 Mon Sep 17 00:00:00 2001 From: "Jett.Zhou" Date: Fri, 6 Jul 2012 10:59:58 +0800 Subject: [PATCH 2255/5711] mfd: Add pre-regulator device for 88pm860x Pre-regulator of 88pm8606 is mainly for support charging based on vbus, it needs to be enabled for charging battery, and will be disabled in some exception condition like over-temp. Add the pre-regulator device init data and resource for mfd subdev. Signed-off-by: Jett.Zhou Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm860x-core.c | 23 +++++++++++++++++++++++ include/linux/mfd/88pm860x.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 87bd5ba38d5b..d09918cf1b15 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -90,6 +90,10 @@ static struct resource charger_resources[] __devinitdata = { {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, }; +static struct resource preg_resources[] __devinitdata = { + {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO,}, +}; + static struct resource rtc_resources[] __devinitdata = { {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, }; @@ -142,9 +146,19 @@ static struct mfd_cell codec_devs[] = { {"88pm860x-codec", -1,}, }; +static struct regulator_consumer_supply preg_supply[] = { + REGULATOR_SUPPLY("preg", "charger-manager"), +}; + +static struct regulator_init_data preg_init_data = { + .num_consumer_supplies = ARRAY_SIZE(preg_supply), + .consumer_supplies = &preg_supply[0], +}; + static struct mfd_cell power_devs[] = { {"88pm860x-battery", -1,}, {"88pm860x-charger", -1,}, + {"88pm860x-preg", -1,}, }; static struct mfd_cell rtc_devs[] = { @@ -768,6 +782,15 @@ static void __devinit device_power_init(struct pm860x_chip *chip, &charger_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); + + power_devs[2].platform_data = &preg_init_data; + power_devs[2].pdata_size = sizeof(struct regulator_init_data); + power_devs[2].num_resources = ARRAY_SIZE(preg_resources); + power_devs[2].resources = &preg_resources[0], + ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, + &preg_resources[0], chip->irq_base); + if (ret < 0) + dev_err(chip->dev, "Failed to add preg subdev\n"); } static void __devinit device_onkey_init(struct pm860x_chip *chip, diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 84d071ade1d8..7b24943779fa 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h @@ -136,6 +136,7 @@ enum { PM8607_ID_LDO13, PM8607_ID_LDO14, PM8607_ID_LDO15, + PM8606_ID_PREG, PM8607_ID_RG_MAX, }; -- GitLab From b8748096111b483de8a544cc220510dff17bbff9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Jul 2012 15:32:20 +0800 Subject: [PATCH 2256/5711] mfd: Remove unused max77686 iolock mutex Now this driver is using regmap API, the iolock mutex is not used and can be removed. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686.c | 3 --- include/linux/mfd/max77686-private.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 11e56017e0b0..9e7e1d30f25f 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -79,8 +78,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->wakeup = pdata->wakeup; max77686->irq_gpio = pdata->irq_gpio; - mutex_init(&max77686->iolock); - if (regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data) < 0) { dev_err(max77686->dev, diff --git a/include/linux/mfd/max77686-private.h b/include/linux/mfd/max77686-private.h index 962f65e72b71..d327d4971e4f 100644 --- a/include/linux/mfd/max77686-private.h +++ b/include/linux/mfd/max77686-private.h @@ -219,7 +219,6 @@ struct max77686_dev { struct device *dev; struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */ struct i2c_client *rtc; /* slave addr 0x0c */ - struct mutex iolock; int type; -- GitLab From 3a8e39c9f475dd061d1bbb7bf3b819f601df33e5 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 6 Jul 2012 12:46:23 +0200 Subject: [PATCH 2257/5711] ARM: ux500: Register the AB8500 from DB8500 MFD As the AB8500 is a subordinate MFD device to the DB8500-PRCMU, for consistency and a better 1:1 depiction of how the hardware is laid out, it is a good idea to register it in the same way as we do for the other MFD child devices. In order for us to do this successfully we have to pass AB8500's platform data when registering the DB8500-PRCMU from platform code. Also solves this issue: WARNING: at fs/sysfs/dir.c:526 sysfs_add_one+0x88/0xb0() sysfs: cannot create duplicate filename '/bus/platform/devices/ab8500-core.0' Reported-by: Linus Walleij Suggested-by: Arnd Bergmann Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- arch/arm/mach-ux500/board-mop500.c | 27 +++--------------------- arch/arm/mach-ux500/cpu-db8500.c | 7 ++++-- arch/arm/mach-ux500/include/mach/setup.h | 3 ++- drivers/mfd/db8500-prcmu.c | 10 ++++++++- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 6224400a9d47..833903e428a8 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -197,24 +197,6 @@ static struct ab8500_platform_data ab8500_platdata = { .gpio = &ab8500_gpio_pdata, }; -static struct resource ab8500_resources[] = { - [0] = { - .start = IRQ_DB8500_AB8500, - .end = IRQ_DB8500_AB8500, - .flags = IORESOURCE_IRQ - } -}; - -struct platform_device ab8500_device = { - .name = "ab8500-core", - .id = 0, - .dev = { - .platform_data = &ab8500_platdata, - }, - .num_resources = 1, - .resource = ab8500_resources, -}; - /* * TPS61052 */ @@ -460,7 +442,6 @@ static struct hash_platform_data u8500_hash1_platform_data = { /* add any platform devices here - TODO */ static struct platform_device *mop500_platform_devs[] __initdata = { &mop500_gpio_keys_device, - &ab8500_device, }; #ifdef CONFIG_STE_DMA40 @@ -622,7 +603,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = { &snowball_led_dev, &snowball_key_dev, &snowball_sbnet_dev, - &ab8500_device, }; static struct platform_device *snowball_of_platform_devs[] __initdata = { @@ -639,9 +619,8 @@ static void __init mop500_init_machine(void) mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; mop500_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); - /* FIXME: parent of ab8500 should be prcmu */ for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -674,7 +653,7 @@ static void __init snowball_init_machine(void) int i; snowball_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) snowball_platform_devs[i]->dev.parent = parent; @@ -706,7 +685,7 @@ static void __init hrefv60_init_machine(void) mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; hrefv60_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 33275eb4c689..1fcdc2da33ba 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -115,7 +116,7 @@ static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) return ret; } -static struct arm_pmu_platdata db8500_pmu_platdata = { +struct arm_pmu_platdata db8500_pmu_platdata = { .handle_irq = db8500_pmu_handler, }; @@ -207,7 +208,7 @@ static struct device * __init db8500_soc_device_init(void) /* * This function is called from the board init */ -struct device * __init u8500_init_devices(void) +struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500) { struct device *parent; int i; @@ -224,6 +225,8 @@ struct device * __init u8500_init_devices(void) for (i = 0; i < ARRAY_SIZE(platform_devs); i++) platform_devs[i]->dev.parent = parent; + db8500_prcmu_device.dev.platform_data = ab8500; + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return parent; diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 8b7ed82a2866..7914e5eaa9c7 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -13,11 +13,12 @@ #include #include +#include void __init ux500_map_io(void); extern void __init u8500_map_io(void); -extern struct device * __init u8500_init_devices(void); +extern struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500); extern void __init ux500_init_irq(void); extern void __init ux500_init_late(void); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index f4adcabb2a51..4050a1e1872b 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2972,8 +2973,9 @@ static struct mfd_cell db8500_prcmu_devs[] = { */ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) { + struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data; struct device_node *np = pdev->dev.of_node; - int irq = 0, err = 0; + int irq = 0, err = 0, i; if (ux500_is_svp()) return -ENODEV; @@ -2997,6 +2999,12 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) goto no_irq_return; } + for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { + if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { + db8500_prcmu_devs[i].platform_data = ab8500_platdata; + } + } + if (cpu_is_u8500v20_or_later()) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); -- GitLab From 14b5bd5cf5605555a746c10404e442c6a95567c1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Jul 2012 12:45:39 +0100 Subject: [PATCH 2258/5711] mfd: Force on REGMAP for the arizona core While the core isn't useful by itself it does depend on regmap so try to force that on. Reported-by: MyungJoo Ham Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 11ee6ec76011..53cbd16c7a4a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -496,6 +496,7 @@ config MFD_S5M_CORE of the device config MFD_ARIZONA + select REGMAP tristate config MFD_ARIZONA_I2C -- GitLab From 59db96913c9d94fe74002df494eb80e4a5ca4087 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 00:31:36 +0200 Subject: [PATCH 2259/5711] mfd: Move arizona digital core supply management to the regulator API Rather than open coding the enable GPIO control in the MFD core use the API to push the management on to the regulator driver. The immediate advantage is slight for most systems but this will in future allow device configurations where an external regulator is used for DCVDD. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 65 +++++++++++++++++--------------- include/linux/mfd/arizona/core.h | 1 + 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 42cb28b2b5c8..c8946a889a78 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -28,7 +29,6 @@ static const char *wm5102_core_supplies[] = { "AVDD", "DBVDD1", - "DCVDD", }; int arizona_clk32k_enable(struct arizona *arizona) @@ -223,8 +223,11 @@ static int arizona_runtime_resume(struct device *dev) struct arizona *arizona = dev_get_drvdata(dev); int ret; - if (arizona->pdata.ldoena) - gpio_set_value_cansleep(arizona->pdata.ldoena, 1); + ret = regulator_enable(arizona->dcvdd); + if (ret != 0) { + dev_err(arizona->dev, "Failed to enable DCVDD: %d\n", ret); + return ret; + } regcache_cache_only(arizona->regmap, false); @@ -241,11 +244,9 @@ static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); - if (arizona->pdata.ldoena) { - gpio_set_value_cansleep(arizona->pdata.ldoena, 0); - regcache_cache_only(arizona->regmap, true); - regcache_mark_dirty(arizona->regmap); - } + regulator_disable(arizona->dcvdd); + regcache_cache_only(arizona->regmap, true); + regcache_mark_dirty(arizona->regmap); return 0; } @@ -314,6 +315,13 @@ int __devinit arizona_dev_init(struct arizona *arizona) goto err_early; } + arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD"); + if (IS_ERR(arizona->dcvdd)) { + ret = PTR_ERR(arizona->dcvdd); + dev_err(dev, "Failed to request DCVDD: %d\n", ret); + goto err_early; + } + ret = regulator_bulk_enable(arizona->num_core_supplies, arizona->core_supplies); if (ret != 0) { @@ -322,6 +330,12 @@ int __devinit arizona_dev_init(struct arizona *arizona) goto err_early; } + ret = regulator_enable(arizona->dcvdd); + if (ret != 0) { + dev_err(dev, "Failed to enable DCVDD: %d\n", ret); + goto err_enable; + } + if (arizona->pdata.reset) { /* Start out with /RESET low to put the chip into reset */ ret = gpio_request_one(arizona->pdata.reset, @@ -329,35 +343,25 @@ int __devinit arizona_dev_init(struct arizona *arizona) "arizona /RESET"); if (ret != 0) { dev_err(dev, "Failed to request /RESET: %d\n", ret); - goto err_enable; + goto err_dcvdd; } gpio_set_value_cansleep(arizona->pdata.reset, 1); } - if (arizona->pdata.ldoena) { - ret = gpio_request_one(arizona->pdata.ldoena, - GPIOF_DIR_OUT | GPIOF_INIT_HIGH, - "arizona LDOENA"); - if (ret != 0) { - dev_err(dev, "Failed to request LDOENA: %d\n", ret); - goto err_reset; - } - } - regcache_cache_only(arizona->regmap, false); ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); if (ret != 0) { dev_err(dev, "Failed to read ID register: %d\n", ret); - goto err_ldoena; + goto err_reset; } ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, &arizona->rev); if (ret != 0) { dev_err(dev, "Failed to read revision register: %d\n", ret); - goto err_ldoena; + goto err_reset; } arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; @@ -374,7 +378,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); - goto err_ldoena; + goto err_reset; } dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); @@ -387,7 +391,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0); if (ret != 0) { dev_err(dev, "Failed to reset device: %d\n", ret); - goto err_ldoena; + goto err_reset; } } @@ -424,7 +428,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) dev_err(arizona->dev, "Invalid 32kHz clock source: %d\n", arizona->pdata.clk32k_src); ret = -EINVAL; - goto err_ldoena; + goto err_reset; } for (i = 0; i < ARIZONA_MAX_INPUT; i++) { @@ -470,7 +474,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) /* Set up for interrupts */ ret = arizona_irq_init(arizona); if (ret != 0) - goto err_ldoena; + goto err_reset; arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, "CLKGEN error", arizona_clkgen_err, arizona); @@ -491,20 +495,21 @@ int __devinit arizona_dev_init(struct arizona *arizona) goto err_irq; } +#ifdef CONFIG_PM_RUNTIME + regulator_disable(arizona->dcvdd); +#endif + return 0; err_irq: arizona_irq_exit(arizona); -err_ldoena: - if (arizona->pdata.ldoena) { - gpio_set_value_cansleep(arizona->pdata.ldoena, 0); - gpio_free(arizona->pdata.ldoena); - } err_reset: if (arizona->pdata.reset) { gpio_set_value_cansleep(arizona->pdata.reset, 1); gpio_free(arizona->pdata.reset); } +err_dcvdd: + regulator_disable(arizona->dcvdd); err_enable: regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies), arizona->core_supplies); diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index 0157d845c2ff..3ef32b4c1136 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h @@ -77,6 +77,7 @@ struct arizona { int num_core_supplies; struct regulator_bulk_data core_supplies[ARIZONA_MAX_CORE_SUPPLIES]; + struct regulator *dcvdd; struct arizona_pdata pdata; -- GitLab From ed393dcd419fd2a00d33cd169dded7303e1c0968 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Jun 2012 14:55:39 +0100 Subject: [PATCH 2260/5711] mfd: Use regcache_sync_region() to sync wm8994 GPIO registers on suspend Now we have regcache sync region we can use it to do a more efficient sync of the pin configuration after we reset the device during suspend. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index f75cdccd1043..53293c742a19 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -196,7 +196,6 @@ static int wm8994_suspend(struct device *dev) { struct wm8994 *wm8994 = dev_get_drvdata(dev); int ret; - int gpio_regs[WM8994_NUM_GPIO_REGS]; /* Don't actually go through with the suspend if the CODEC is * still active (eg, for audio passthrough from CP. */ @@ -278,27 +277,23 @@ static int wm8994_suspend(struct device *dev) WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD); - /* Save GPIO registers before reset */ - regmap_bulk_read(wm8994->regmap, WM8994_GPIO_1, gpio_regs, - WM8994_NUM_GPIO_REGS); - /* Explicitly put the device into reset in case regulators * don't get disabled in order to ensure consistent restart. */ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET)); + regcache_mark_dirty(wm8994->regmap); + /* Restore GPIO registers to prevent problems with mismatched * pin configurations. */ - ret = regmap_bulk_write(wm8994->regmap, WM8994_GPIO_1, gpio_regs, - WM8994_NUM_GPIO_REGS); + ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1, + WM8994_GPIO_11); if (ret != 0) dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); regcache_cache_only(wm8994->regmap, true); - regcache_mark_dirty(wm8994->regmap); - wm8994->suspended = true; ret = regulator_bulk_disable(wm8994->num_supplies, -- GitLab From 1a2017b7143d9d0ec1b75078e76c6f55a2e55d17 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Jun 2012 14:55:40 +0100 Subject: [PATCH 2261/5711] mfd: Also restore wm8994 GPIO IRQ masks after reset This ensures that if we are using a GPIO as a wake source it continues to function while we're suspended. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 53293c742a19..eec74aa55fdf 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -293,6 +293,13 @@ static int wm8994_suspend(struct device *dev) if (ret != 0) dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); + /* In case one of the GPIOs is used as a wake input. */ + ret = regcache_sync_region(wm8994->regmap, + WM8994_INTERRUPT_STATUS_1_MASK, + WM8994_INTERRUPT_STATUS_1_MASK); + if (ret != 0) + dev_err(dev, "Failed to restore interrupt mask: %d\n", ret); + regcache_cache_only(wm8994->regmap, true); wm8994->suspended = true; -- GitLab From de2233365d5abc94993378330768786de2c606f6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:35:28 +0100 Subject: [PATCH 2262/5711] mfd: Add more arizona register definitions These registers will be used in future devices. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- include/linux/mfd/arizona/registers.h | 163 ++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index 989c47d681e0..8f49106d7bda 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -20,6 +20,9 @@ #define ARIZONA_DEVICE_REVISION 0x01 #define ARIZONA_CTRL_IF_SPI_CFG_1 0x08 #define ARIZONA_CTRL_IF_I2C1_CFG_1 0x09 +#define ARIZONA_CTRL_IF_I2C2_CFG_1 0x0A +#define ARIZONA_CTRL_IF_I2C1_CFG_2 0x0B +#define ARIZONA_CTRL_IF_I2C2_CFG_2 0x0C #define ARIZONA_CTRL_IF_STATUS_1 0x0D #define ARIZONA_WRITE_SEQUENCER_CTRL_0 0x16 #define ARIZONA_WRITE_SEQUENCER_CTRL_1 0x17 @@ -80,6 +83,7 @@ #define ARIZONA_FLL1_CONTROL_5 0x175 #define ARIZONA_FLL1_CONTROL_6 0x176 #define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177 +#define ARIZONA_FLL1_NCO_TEST_0 0x178 #define ARIZONA_FLL1_SYNCHRONISER_1 0x181 #define ARIZONA_FLL1_SYNCHRONISER_2 0x182 #define ARIZONA_FLL1_SYNCHRONISER_3 0x183 @@ -95,6 +99,7 @@ #define ARIZONA_FLL2_CONTROL_5 0x195 #define ARIZONA_FLL2_CONTROL_6 0x196 #define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197 +#define ARIZONA_FLL2_NCO_TEST_0 0x198 #define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1 #define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2 #define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3 @@ -119,6 +124,7 @@ #define ARIZONA_ISOLATION_CONTROL 0x2CB #define ARIZONA_JACK_DETECT_ANALOGUE 0x2D3 #define ARIZONA_INPUT_ENABLES 0x300 +#define ARIZONA_INPUT_ENABLES_STATUS 0x301 #define ARIZONA_INPUT_RATE 0x308 #define ARIZONA_INPUT_VOLUME_RAMP 0x309 #define ARIZONA_IN1L_CONTROL 0x310 @@ -139,8 +145,14 @@ #define ARIZONA_IN3R_CONTROL 0x324 #define ARIZONA_ADC_DIGITAL_VOLUME_3R 0x325 #define ARIZONA_DMIC3R_CONTROL 0x326 +#define ARIZONA_IN4_CONTROL 0x328 +#define ARIZONA_ADC_DIGITAL_VOLUME_4L 0x329 +#define ARIZONA_DMIC4L_CONTROL 0x32A +#define ARIZONA_ADC_DIGITAL_VOLUME_4R 0x32D +#define ARIZONA_DMIC4R_CONTROL 0x32E #define ARIZONA_OUTPUT_ENABLES_1 0x400 #define ARIZONA_OUTPUT_STATUS_1 0x401 +#define ARIZONA_RAW_OUTPUT_STATUS_1 0x406 #define ARIZONA_OUTPUT_RATE_1 0x408 #define ARIZONA_OUTPUT_VOLUME_RAMP 0x409 #define ARIZONA_OUTPUT_PATH_CONFIG_1L 0x410 @@ -166,6 +178,7 @@ #define ARIZONA_OUTPUT_PATH_CONFIG_3R 0x424 #define ARIZONA_DAC_DIGITAL_VOLUME_3R 0x425 #define ARIZONA_DAC_VOLUME_LIMIT_3R 0x426 +#define ARIZONA_NOISE_GATE_SELECT_3R 0x427 #define ARIZONA_OUTPUT_PATH_CONFIG_4L 0x428 #define ARIZONA_DAC_DIGITAL_VOLUME_4L 0x429 #define ARIZONA_OUT_VOLUME_4L 0x42A @@ -182,10 +195,20 @@ #define ARIZONA_DAC_DIGITAL_VOLUME_5R 0x435 #define ARIZONA_DAC_VOLUME_LIMIT_5R 0x436 #define ARIZONA_NOISE_GATE_SELECT_5R 0x437 +#define ARIZONA_OUTPUT_PATH_CONFIG_6L 0x438 +#define ARIZONA_DAC_DIGITAL_VOLUME_6L 0x439 +#define ARIZONA_DAC_VOLUME_LIMIT_6L 0x43A +#define ARIZONA_NOISE_GATE_SELECT_6L 0x43B +#define ARIZONA_OUTPUT_PATH_CONFIG_6R 0x43C +#define ARIZONA_DAC_DIGITAL_VOLUME_6R 0x43D +#define ARIZONA_DAC_VOLUME_LIMIT_6R 0x43E +#define ARIZONA_NOISE_GATE_SELECT_6R 0x43F #define ARIZONA_DAC_AEC_CONTROL_1 0x450 #define ARIZONA_NOISE_GATE_CONTROL 0x458 #define ARIZONA_PDM_SPK1_CTRL_1 0x490 #define ARIZONA_PDM_SPK1_CTRL_2 0x491 +#define ARIZONA_PDM_SPK2_CTRL_1 0x492 +#define ARIZONA_PDM_SPK2_CTRL_2 0x493 #define ARIZONA_DAC_COMP_1 0x4DC #define ARIZONA_DAC_COMP_2 0x4DD #define ARIZONA_DAC_COMP_3 0x4DE @@ -335,6 +358,14 @@ #define ARIZONA_OUT3LMIX_INPUT_3_VOLUME 0x6A5 #define ARIZONA_OUT3LMIX_INPUT_4_SOURCE 0x6A6 #define ARIZONA_OUT3LMIX_INPUT_4_VOLUME 0x6A7 +#define ARIZONA_OUT3RMIX_INPUT_1_SOURCE 0x6A8 +#define ARIZONA_OUT3RMIX_INPUT_1_VOLUME 0x6A9 +#define ARIZONA_OUT3RMIX_INPUT_2_SOURCE 0x6AA +#define ARIZONA_OUT3RMIX_INPUT_2_VOLUME 0x6AB +#define ARIZONA_OUT3RMIX_INPUT_3_SOURCE 0x6AC +#define ARIZONA_OUT3RMIX_INPUT_3_VOLUME 0x6AD +#define ARIZONA_OUT3RMIX_INPUT_4_SOURCE 0x6AE +#define ARIZONA_OUT3RMIX_INPUT_4_VOLUME 0x6AF #define ARIZONA_OUT4LMIX_INPUT_1_SOURCE 0x6B0 #define ARIZONA_OUT4LMIX_INPUT_1_VOLUME 0x6B1 #define ARIZONA_OUT4LMIX_INPUT_2_SOURCE 0x6B2 @@ -367,6 +398,22 @@ #define ARIZONA_OUT5RMIX_INPUT_3_VOLUME 0x6CD #define ARIZONA_OUT5RMIX_INPUT_4_SOURCE 0x6CE #define ARIZONA_OUT5RMIX_INPUT_4_VOLUME 0x6CF +#define ARIZONA_OUT6LMIX_INPUT_1_SOURCE 0x6D0 +#define ARIZONA_OUT6LMIX_INPUT_1_VOLUME 0x6D1 +#define ARIZONA_OUT6LMIX_INPUT_2_SOURCE 0x6D2 +#define ARIZONA_OUT6LMIX_INPUT_2_VOLUME 0x6D3 +#define ARIZONA_OUT6LMIX_INPUT_3_SOURCE 0x6D4 +#define ARIZONA_OUT6LMIX_INPUT_3_VOLUME 0x6D5 +#define ARIZONA_OUT6LMIX_INPUT_4_SOURCE 0x6D6 +#define ARIZONA_OUT6LMIX_INPUT_4_VOLUME 0x6D7 +#define ARIZONA_OUT6RMIX_INPUT_1_SOURCE 0x6D8 +#define ARIZONA_OUT6RMIX_INPUT_1_VOLUME 0x6D9 +#define ARIZONA_OUT6RMIX_INPUT_2_SOURCE 0x6DA +#define ARIZONA_OUT6RMIX_INPUT_2_VOLUME 0x6DB +#define ARIZONA_OUT6RMIX_INPUT_3_SOURCE 0x6DC +#define ARIZONA_OUT6RMIX_INPUT_3_VOLUME 0x6DD +#define ARIZONA_OUT6RMIX_INPUT_4_SOURCE 0x6DE +#define ARIZONA_OUT6RMIX_INPUT_4_VOLUME 0x6DF #define ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE 0x700 #define ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME 0x701 #define ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE 0x702 @@ -645,18 +692,106 @@ #define ARIZONA_DSP1AUX4MIX_INPUT_1_SOURCE 0x968 #define ARIZONA_DSP1AUX5MIX_INPUT_1_SOURCE 0x970 #define ARIZONA_DSP1AUX6MIX_INPUT_1_SOURCE 0x978 +#define ARIZONA_DSP2LMIX_INPUT_1_SOURCE 0x980 +#define ARIZONA_DSP2LMIX_INPUT_1_VOLUME 0x981 +#define ARIZONA_DSP2LMIX_INPUT_2_SOURCE 0x982 +#define ARIZONA_DSP2LMIX_INPUT_2_VOLUME 0x983 +#define ARIZONA_DSP2LMIX_INPUT_3_SOURCE 0x984 +#define ARIZONA_DSP2LMIX_INPUT_3_VOLUME 0x985 +#define ARIZONA_DSP2LMIX_INPUT_4_SOURCE 0x986 +#define ARIZONA_DSP2LMIX_INPUT_4_VOLUME 0x987 +#define ARIZONA_DSP2RMIX_INPUT_1_SOURCE 0x988 +#define ARIZONA_DSP2RMIX_INPUT_1_VOLUME 0x989 +#define ARIZONA_DSP2RMIX_INPUT_2_SOURCE 0x98A +#define ARIZONA_DSP2RMIX_INPUT_2_VOLUME 0x98B +#define ARIZONA_DSP2RMIX_INPUT_3_SOURCE 0x98C +#define ARIZONA_DSP2RMIX_INPUT_3_VOLUME 0x98D +#define ARIZONA_DSP2RMIX_INPUT_4_SOURCE 0x98E +#define ARIZONA_DSP2RMIX_INPUT_4_VOLUME 0x98F +#define ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE 0x990 +#define ARIZONA_DSP2AUX2MIX_INPUT_1_SOURCE 0x998 +#define ARIZONA_DSP2AUX3MIX_INPUT_1_SOURCE 0x9A0 +#define ARIZONA_DSP2AUX4MIX_INPUT_1_SOURCE 0x9A8 +#define ARIZONA_DSP2AUX5MIX_INPUT_1_SOURCE 0x9B0 +#define ARIZONA_DSP2AUX6MIX_INPUT_1_SOURCE 0x9B8 +#define ARIZONA_DSP3LMIX_INPUT_1_SOURCE 0x9C0 +#define ARIZONA_DSP3LMIX_INPUT_1_VOLUME 0x9C1 +#define ARIZONA_DSP3LMIX_INPUT_2_SOURCE 0x9C2 +#define ARIZONA_DSP3LMIX_INPUT_2_VOLUME 0x9C3 +#define ARIZONA_DSP3LMIX_INPUT_3_SOURCE 0x9C4 +#define ARIZONA_DSP3LMIX_INPUT_3_VOLUME 0x9C5 +#define ARIZONA_DSP3LMIX_INPUT_4_SOURCE 0x9C6 +#define ARIZONA_DSP3LMIX_INPUT_4_VOLUME 0x9C7 +#define ARIZONA_DSP3RMIX_INPUT_1_SOURCE 0x9C8 +#define ARIZONA_DSP3RMIX_INPUT_1_VOLUME 0x9C9 +#define ARIZONA_DSP3RMIX_INPUT_2_SOURCE 0x9CA +#define ARIZONA_DSP3RMIX_INPUT_2_VOLUME 0x9CB +#define ARIZONA_DSP3RMIX_INPUT_3_SOURCE 0x9CC +#define ARIZONA_DSP3RMIX_INPUT_3_VOLUME 0x9CD +#define ARIZONA_DSP3RMIX_INPUT_4_SOURCE 0x9CE +#define ARIZONA_DSP3RMIX_INPUT_4_VOLUME 0x9CF +#define ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE 0x9D0 +#define ARIZONA_DSP3AUX2MIX_INPUT_1_SOURCE 0x9D8 +#define ARIZONA_DSP3AUX3MIX_INPUT_1_SOURCE 0x9E0 +#define ARIZONA_DSP3AUX4MIX_INPUT_1_SOURCE 0x9E8 +#define ARIZONA_DSP3AUX5MIX_INPUT_1_SOURCE 0x9F0 +#define ARIZONA_DSP3AUX6MIX_INPUT_1_SOURCE 0x9F8 +#define ARIZONA_DSP4LMIX_INPUT_1_SOURCE 0xA00 +#define ARIZONA_DSP4LMIX_INPUT_1_VOLUME 0xA01 +#define ARIZONA_DSP4LMIX_INPUT_2_SOURCE 0xA02 +#define ARIZONA_DSP4LMIX_INPUT_2_VOLUME 0xA03 +#define ARIZONA_DSP4LMIX_INPUT_3_SOURCE 0xA04 +#define ARIZONA_DSP4LMIX_INPUT_3_VOLUME 0xA05 +#define ARIZONA_DSP4LMIX_INPUT_4_SOURCE 0xA06 +#define ARIZONA_DSP4LMIX_INPUT_4_VOLUME 0xA07 +#define ARIZONA_DSP4RMIX_INPUT_1_SOURCE 0xA08 +#define ARIZONA_DSP4RMIX_INPUT_1_VOLUME 0xA09 +#define ARIZONA_DSP4RMIX_INPUT_2_SOURCE 0xA0A +#define ARIZONA_DSP4RMIX_INPUT_2_VOLUME 0xA0B +#define ARIZONA_DSP4RMIX_INPUT_3_SOURCE 0xA0C +#define ARIZONA_DSP4RMIX_INPUT_3_VOLUME 0xA0D +#define ARIZONA_DSP4RMIX_INPUT_4_SOURCE 0xA0E +#define ARIZONA_DSP4RMIX_INPUT_4_VOLUME 0xA0F +#define ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE 0xA10 +#define ARIZONA_DSP4AUX2MIX_INPUT_1_SOURCE 0xA18 +#define ARIZONA_DSP4AUX3MIX_INPUT_1_SOURCE 0xA20 +#define ARIZONA_DSP4AUX4MIX_INPUT_1_SOURCE 0xA28 +#define ARIZONA_DSP4AUX5MIX_INPUT_1_SOURCE 0xA30 +#define ARIZONA_DSP4AUX6MIX_INPUT_1_SOURCE 0xA38 #define ARIZONA_ASRC1LMIX_INPUT_1_SOURCE 0xA80 #define ARIZONA_ASRC1RMIX_INPUT_1_SOURCE 0xA88 #define ARIZONA_ASRC2LMIX_INPUT_1_SOURCE 0xA90 #define ARIZONA_ASRC2RMIX_INPUT_1_SOURCE 0xA98 #define ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE 0xB00 #define ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE 0xB08 +#define ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE 0xB10 +#define ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE 0xB18 #define ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE 0xB20 #define ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE 0xB28 +#define ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 +#define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 #define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 #define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 #define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 #define ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 +#define ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 +#define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 +#define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 +#define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 +#define ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50 +#define ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58 +#define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 +#define ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 +#define ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE 0xB70 +#define ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE 0xB78 +#define ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE 0xB80 +#define ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE 0xB88 +#define ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE 0xB90 +#define ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE 0xB98 +#define ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE 0xBA0 +#define ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE 0xBA8 +#define ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE 0xBB0 +#define ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE 0xBB8 #define ARIZONA_GPIO1_CTRL 0xC00 #define ARIZONA_GPIO2_CTRL 0xC01 #define ARIZONA_GPIO3_CTRL 0xC02 @@ -670,6 +805,18 @@ #define ARIZONA_MISC_PAD_CTRL_4 0xC23 #define ARIZONA_MISC_PAD_CTRL_5 0xC24 #define ARIZONA_MISC_PAD_CTRL_6 0xC25 +#define ARIZONA_MISC_PAD_CTRL_7 0xC30 +#define ARIZONA_MISC_PAD_CTRL_8 0xC31 +#define ARIZONA_MISC_PAD_CTRL_9 0xC32 +#define ARIZONA_MISC_PAD_CTRL_10 0xC33 +#define ARIZONA_MISC_PAD_CTRL_11 0xC34 +#define ARIZONA_MISC_PAD_CTRL_12 0xC35 +#define ARIZONA_MISC_PAD_CTRL_13 0xC36 +#define ARIZONA_MISC_PAD_CTRL_14 0xC37 +#define ARIZONA_MISC_PAD_CTRL_15 0xC38 +#define ARIZONA_MISC_PAD_CTRL_16 0xC39 +#define ARIZONA_MISC_PAD_CTRL_17 0xC3A +#define ARIZONA_MISC_PAD_CTRL_18 0xC3B #define ARIZONA_INTERRUPT_STATUS_1 0xD00 #define ARIZONA_INTERRUPT_STATUS_2 0xD01 #define ARIZONA_INTERRUPT_STATUS_3 0xD02 @@ -813,6 +960,7 @@ #define ARIZONA_HPLPF4_1 0xECC #define ARIZONA_HPLPF4_2 0xECD #define ARIZONA_ASRC_ENABLE 0xEE0 +#define ARIZONA_ASRC_STATUS 0xEE1 #define ARIZONA_ASRC_RATE1 0xEE2 #define ARIZONA_ASRC_RATE2 0xEE3 #define ARIZONA_ISRC_1_CTRL_1 0xEF0 @@ -824,10 +972,25 @@ #define ARIZONA_ISRC_3_CTRL_1 0xEF6 #define ARIZONA_ISRC_3_CTRL_2 0xEF7 #define ARIZONA_ISRC_3_CTRL_3 0xEF8 +#define ARIZONA_CLOCK_CONTROL 0xF00 +#define ARIZONA_ANC_SRC 0xF01 +#define ARIZONA_DSP_STATUS 0xF02 #define ARIZONA_DSP1_CONTROL_1 0x1100 #define ARIZONA_DSP1_CLOCKING_1 0x1101 #define ARIZONA_DSP1_STATUS_1 0x1104 #define ARIZONA_DSP1_STATUS_2 0x1105 +#define ARIZONA_DSP2_CONTROL_1 0x1200 +#define ARIZONA_DSP2_CLOCKING_1 0x1201 +#define ARIZONA_DSP2_STATUS_1 0x1204 +#define ARIZONA_DSP2_STATUS_2 0x1205 +#define ARIZONA_DSP3_CONTROL_1 0x1300 +#define ARIZONA_DSP3_CLOCKING_1 0x1301 +#define ARIZONA_DSP3_STATUS_1 0x1304 +#define ARIZONA_DSP3_STATUS_2 0x1305 +#define ARIZONA_DSP4_CONTROL_1 0x1400 +#define ARIZONA_DSP4_CLOCKING_1 0x1401 +#define ARIZONA_DSP4_STATUS_1 0x1404 +#define ARIZONA_DSP4_STATUS_2 0x1405 /* * Field Definitions. -- GitLab From 5879f5710e684af662635770561112ce3f25ea8c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:35:29 +0100 Subject: [PATCH 2263/5711] mfd: Release arizona DCVDD if we fail to resume the device Ensures we don't leak the enable we just did. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c8946a889a78..e1308b5214ba 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -232,8 +232,10 @@ static int arizona_runtime_resume(struct device *dev) regcache_cache_only(arizona->regmap, false); ret = arizona_wait_for_boot(arizona); - if (ret != 0) + if (ret != 0) { + regulator_disable(arizona->dcvdd); return ret; + } regcache_sync(arizona->regmap); -- GitLab From cfe775ce62d83168125299714739aebc1018211e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:35:30 +0100 Subject: [PATCH 2264/5711] mfd: Treat arizona register read errors as non-fatal during resume We're testing for a specific value and while SPI does not detect I/O errors I2C can. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index e1308b5214ba..03aef6750a9d 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -197,7 +197,7 @@ static int arizona_wait_for_boot(struct arizona *arizona) if (ret != 0) { dev_err(arizona->dev, "Failed to read boot state: %d\n", ret); - return ret; + continue; } if (reg & ARIZONA_BOOT_DONE_STS) -- GitLab From 863df8d5f1a1a92016e24c80947cb3509b8aaa48 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:35:31 +0100 Subject: [PATCH 2265/5711] mfd: Add missing WM5102 ifdefs References to the WM5102 tables need to be guarded. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 3 ++- drivers/mfd/arizona-i2c.c | 2 ++ drivers/mfd/arizona-irq.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 03aef6750a9d..7f837edfbfb7 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -368,6 +368,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { +#ifdef CONFIG_MFD_WM5102 case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { @@ -377,7 +378,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) } ret = wm5102_patch(arizona); break; - +#endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); goto err_reset; diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 75fb110105e1..fe19d11b92f0 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -30,9 +30,11 @@ static __devinit int arizona_i2c_probe(struct i2c_client *i2c, int ret; switch (id->driver_data) { +#ifdef CONFIG_MFD_WM5102 case WM5102: regmap_config = &wm5102_i2c_regmap; break; +#endif default: dev_err(&i2c->dev, "Unknown device type %ld\n", id->driver_data); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 4c7894046a39..17d20c0fba1e 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -158,10 +158,12 @@ int arizona_irq_init(struct arizona *arizona) const struct regmap_irq_chip *aod, *irq; switch (arizona->type) { +#ifdef CONFIG_MFD_WM5102 case WM5102: aod = &wm5102_aod; irq = &wm5102_irq; break; +#endif default: BUG_ON("Unknown Arizona class device" == NULL); return -EINVAL; -- GitLab From 3a36a0db5b0f77ff71a9df23db9f4044e04590d8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 00:45:53 +0200 Subject: [PATCH 2266/5711] mfd: Don't free unallocated arizona supplies on error ARRAY_SIZE() may be larger than the number of supplies actually used. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 7f837edfbfb7..5cbacf6e2bf7 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -514,7 +514,7 @@ err_reset: err_dcvdd: regulator_disable(arizona->dcvdd); err_enable: - regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies), + regulator_bulk_disable(arizona->num_core_supplies, arizona->core_supplies); err_early: mfd_remove_devices(dev); -- GitLab From c6a5d9ff6f96128161126c0a01f0a28edf8010da Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:35:33 +0100 Subject: [PATCH 2267/5711] mfd: Mark headphone detect readback wm5102 register volatile Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm5102-tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 9b38b6b412dc..01b9255ed631 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -813,7 +813,6 @@ static const struct reg_default wm5102_reg_default[] = { { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ - { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ @@ -2362,6 +2361,7 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_AOD_IRQ_RAW_STATUS: case ARIZONA_DSP1_STATUS_1: case ARIZONA_DSP1_STATUS_2: + case ARIZONA_HEADPHONE_DETECT_2: case ARIZONA_MIC_DETECT_3: return true; default: -- GitLab From 5b0ec991c0576c54db75803fbcb0ef5bebfa0828 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Thu, 14 Jun 2012 20:31:39 +0000 Subject: [PATCH 2268/5711] RDMA/cma: Bind to a specific address family The RDMA CM uses a single port space for all associated (tcp, udp, etc.) port bindings, regardless of the address family that the user binds to. The result is that if a user binds to AF_INET, but does not specify an IP address, the bind will occur for AF_INET6. This causes an attempt to bind to the same port using AF_INET6 to fail, and connection requests to AF_INET6 will match with the AF_INET listener. Align the behavior with sockets and restrict the bind to AF_INET only. If a user binds to AF_INET6, we bind the port to AF_INET6 and AF_INET depending on the value of bindv6only. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 2e826f9702c6..c10c45a07162 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -140,6 +140,7 @@ struct rdma_id_private { u8 srq; u8 tos; u8 reuseaddr; + u8 afonly; }; struct cma_multicast { @@ -1573,6 +1574,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); atomic_inc(&id_priv->refcount); dev_id_priv->internal_id = 1; + dev_id_priv->afonly = id_priv->afonly; ret = rdma_listen(id, id_priv->backlog); if (ret) @@ -2187,22 +2189,24 @@ static int cma_check_port(struct rdma_bind_list *bind_list, struct hlist_node *node; addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; - if (cma_any_addr(addr) && !reuseaddr) - return -EADDRNOTAVAIL; - hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { if (id_priv == cur_id) continue; - if ((cur_id->state == RDMA_CM_LISTEN) || - !reuseaddr || !cur_id->reuseaddr) { - cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr; - if (cma_any_addr(cur_addr)) - return -EADDRNOTAVAIL; + if ((cur_id->state != RDMA_CM_LISTEN) && reuseaddr && + cur_id->reuseaddr) + continue; - if (!cma_addr_cmp(addr, cur_addr)) - return -EADDRINUSE; - } + cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr; + if (id_priv->afonly && cur_id->afonly && + (addr->sa_family != cur_addr->sa_family)) + continue; + + if (cma_any_addr(addr) || cma_any_addr(cur_addr)) + return -EADDRNOTAVAIL; + + if (!cma_addr_cmp(addr, cur_addr)) + return -EADDRINUSE; } return 0; } @@ -2371,6 +2375,12 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) } memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); + if (addr->sa_family == AF_INET) + id_priv->afonly = 1; +#if IS_ENABLED(CONFIG_IPV6) + else if (addr->sa_family == AF_INET6) + id_priv->afonly = init_net.ipv6.sysctl.bindv6only; +#endif ret = cma_get_port(id_priv); if (ret) goto err2; -- GitLab From 406b6a25f85271397739a7e9f5af1df665b8a0d0 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Thu, 14 Jun 2012 20:31:39 +0000 Subject: [PATCH 2269/5711] RDMA/cma: Listen on specific address family The rdma_cm maps IPv4 and IPv6 addresses to the same service ID. This prevents apps from listening only for IPv4 or IPv6 addresses. It also results in an app binding to an IPv4 address receiving connection requests for an IPv6 address. Change this to match socket behavior: restrict listens on IPv4 addresses to only IPv4 addresses, and if a listen is on an IPv6 address, allow it to receive either IPv4 or IPv6 addresses, based on its address family binding. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index c10c45a07162..454e7ea111e6 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1298,8 +1298,10 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, } else { cma_set_ip_ver(cma_data, 4); cma_set_ip_ver(cma_mask, 0xF); - cma_data->dst_addr.ip4.addr = ip4_addr; - cma_mask->dst_addr.ip4.addr = htonl(~0); + if (!cma_any_addr(addr)) { + cma_data->dst_addr.ip4.addr = ip4_addr; + cma_mask->dst_addr.ip4.addr = htonl(~0); + } } break; case AF_INET6: @@ -1313,9 +1315,11 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, } else { cma_set_ip_ver(cma_data, 6); cma_set_ip_ver(cma_mask, 0xF); - cma_data->dst_addr.ip6 = ip6_addr; - memset(&cma_mask->dst_addr.ip6, 0xFF, - sizeof cma_mask->dst_addr.ip6); + if (!cma_any_addr(addr)) { + cma_data->dst_addr.ip6 = ip6_addr; + memset(&cma_mask->dst_addr.ip6, 0xFF, + sizeof cma_mask->dst_addr.ip6); + } } break; default: @@ -1500,7 +1504,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv) addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; svc_id = cma_get_service_id(id_priv->id.ps, addr); - if (cma_any_addr(addr)) + if (cma_any_addr(addr) && !id_priv->afonly) ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); else { cma_set_compare_data(id_priv->id.ps, addr, &compare_data); -- GitLab From 68602120e496a31d8e3b36d0bfc7d9d2456fb05c Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Thu, 14 Jun 2012 20:31:39 +0000 Subject: [PATCH 2270/5711] RDMA/cma: Allow user to restrict listens to bound address family Provide an option for the user to specify that listens should only accept connections where the incoming address family matches that of the locally bound address. This is used to support the equivalent of IPV6_V6ONLY socket option, which allows an app to only accept connection requests directed to IPv6 addresses. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 35 ++++++++++++++++++++++++++++++---- drivers/infiniband/core/ucma.c | 7 +++++++ include/rdma/rdma_cm.h | 10 ++++++++++ include/rdma/rdma_user_cm.h | 1 + 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 454e7ea111e6..8734a6af35d7 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -99,6 +99,10 @@ struct rdma_bind_list { unsigned short port; }; +enum { + CMA_OPTION_AFONLY, +}; + /* * Device removal can occur at anytime, so we need extra handling to * serialize notifying the user of device removal with other callbacks. @@ -137,6 +141,7 @@ struct rdma_id_private { u32 qkey; u32 qp_num; pid_t owner; + u32 options; u8 srq; u8 tos; u8 reuseaddr; @@ -2104,6 +2109,26 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse) } EXPORT_SYMBOL(rdma_set_reuseaddr); +int rdma_set_afonly(struct rdma_cm_id *id, int afonly) +{ + struct rdma_id_private *id_priv; + unsigned long flags; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + spin_lock_irqsave(&id_priv->lock, flags); + if (id_priv->state == RDMA_CM_IDLE || id_priv->state == RDMA_CM_ADDR_BOUND) { + id_priv->options |= (1 << CMA_OPTION_AFONLY); + id_priv->afonly = afonly; + ret = 0; + } else { + ret = -EINVAL; + } + spin_unlock_irqrestore(&id_priv->lock, flags); + return ret; +} +EXPORT_SYMBOL(rdma_set_afonly); + static void cma_bind_port(struct rdma_bind_list *bind_list, struct rdma_id_private *id_priv) { @@ -2379,12 +2404,14 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) } memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); - if (addr->sa_family == AF_INET) - id_priv->afonly = 1; + if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) { + if (addr->sa_family == AF_INET) + id_priv->afonly = 1; #if IS_ENABLED(CONFIG_IPV6) - else if (addr->sa_family == AF_INET6) - id_priv->afonly = init_net.ipv6.sysctl.bindv6only; + else if (addr->sa_family == AF_INET6) + id_priv->afonly = init_net.ipv6.sysctl.bindv6only; #endif + } ret = cma_get_port(id_priv); if (ret) goto err2; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 8002ae642cfe..893cb879462c 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -909,6 +909,13 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname, } ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0); break; + case RDMA_OPTION_ID_AFONLY: + if (optlen != sizeof(int)) { + ret = -EINVAL; + break; + } + ret = rdma_set_afonly(ctx->cm_id, *((int *) optval) ? 1 : 0); + break; default: ret = -ENOSYS; } diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index 51988f808181..ad3a3142383a 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -357,4 +357,14 @@ void rdma_set_service_type(struct rdma_cm_id *id, int tos); */ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse); +/** + * rdma_set_afonly - Specify that listens are restricted to the + * bound address family only. + * @id: Communication identifer to configure. + * @afonly: Value indicating if listens are restricted. + * + * Must be set before identifier is in the listening state. + */ +int rdma_set_afonly(struct rdma_cm_id *id, int afonly); + #endif /* RDMA_CM_H */ diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h index 5348a000c8f3..1ee9239ff8c2 100644 --- a/include/rdma/rdma_user_cm.h +++ b/include/rdma/rdma_user_cm.h @@ -224,6 +224,7 @@ enum { enum { RDMA_OPTION_ID_TOS = 0, RDMA_OPTION_ID_REUSEADDR = 1, + RDMA_OPTION_ID_AFONLY = 2, RDMA_OPTION_IB_PATH = 1 }; -- GitLab From f747c34af4f56cc239e04505bd583dd3bdcfe49d Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 5 Jul 2012 14:16:54 -0700 Subject: [PATCH 2271/5711] RDMA/cxgb4: Fix endianness of addition to mpa->private_data_size sparse correctly warns that if mpa->private_data_size is __be16, then doing += on it is wrong, even if we do += htons() -- on a little endian system, carries will go the wrong way. Fix this up by doing the addition in native byte order. Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index b18870c455ad..51f42061dae9 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -548,8 +548,8 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, } if (mpa_rev_to_use == 2) { - mpa->private_data_size += - htons(sizeof(struct mpa_v2_conn_params)); + mpa->private_data_size = htons(ntohs(mpa->private_data_size) + + sizeof (struct mpa_v2_conn_params)); mpa_v2_params.ird = htons((u16)ep->ird); mpa_v2_params.ord = htons((u16)ep->ord); @@ -635,8 +635,8 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { mpa->flags |= MPA_ENHANCED_RDMA_CONN; - mpa->private_data_size += - htons(sizeof(struct mpa_v2_conn_params)); + mpa->private_data_size = htons(ntohs(mpa->private_data_size) + + sizeof (struct mpa_v2_conn_params)); mpa_v2_params.ird = htons(((u16)ep->ird) | (peer2peer ? MPA_V2_PEER2PEER_MODEL : 0)); @@ -715,8 +715,8 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { mpa->flags |= MPA_ENHANCED_RDMA_CONN; - mpa->private_data_size += - htons(sizeof(struct mpa_v2_conn_params)); + mpa->private_data_size = htons(ntohs(mpa->private_data_size) + + sizeof (struct mpa_v2_conn_params)); mpa_v2_params.ird = htons((u16)ep->ird); mpa_v2_params.ord = htons((u16)ep->ord); if (peer2peer && (ep->mpa_attr.p2p_type != -- GitLab From d90f9b3591b3b5fa86178e318008fc1c531a84dc Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 5 Jul 2012 22:39:34 -0700 Subject: [PATCH 2272/5711] IB: Use IS_ENABLED(CONFIG_IPV6) Instead of testing defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 4 ++-- drivers/infiniband/core/cma.c | 2 +- drivers/infiniband/hw/ocrdma/ocrdma_main.c | 7 +++---- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 6ef660c1332f..28058ae33d38 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -129,7 +129,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) dev_put(dev); break; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) case AF_INET6: rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { @@ -243,7 +243,7 @@ out: return ret; } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) static int addr6_resolve(struct sockaddr_in6 *src_in, struct sockaddr_in6 *dst_in, struct rdma_dev_addr *addr) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 2e826f9702c6..4d8f592b1e51 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2278,7 +2278,7 @@ static int cma_get_port(struct rdma_id_private *id_priv) static int cma_check_linklocal(struct rdma_dev_addr *dev_addr, struct sockaddr *addr) { -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct sockaddr_in6 *sin6; if (addr->sa_family != AF_INET6) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index b050e629e9c3..5a044526e4f4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -202,8 +202,7 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev) return 0; } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) || \ -defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_VLAN_8021Q) static int ocrdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, void *ptr) @@ -549,7 +548,7 @@ static struct ocrdma_driver ocrdma_drv = { static void ocrdma_unregister_inet6addr_notifier(void) { -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) unregister_inet6addr_notifier(&ocrdma_inet6addr_notifier); #endif } @@ -558,7 +557,7 @@ static int __init ocrdma_init_module(void) { int status; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) status = register_inet6addr_notifier(&ocrdma_inet6addr_notifier); if (status) return status; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 014504d8e43c..fd3871e3f65b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1376,7 +1376,7 @@ static void ipoib_cm_skb_reap(struct work_struct *work) if (skb->protocol == htons(ETH_P_IP)) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) else if (skb->protocol == htons(ETH_P_IPV6)) icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); #endif -- GitLab From 752a50cab600c6d46c5a1921c6a6d2fb116c8a4b Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:33 +0300 Subject: [PATCH 2273/5711] mlx4_core: Pass an invalid PCI id number to VFs Currently, VFs have 0 in their dev->caps.function field. This is a valid pci id (usually of the PF). Instead, pass an invalid PCI id to the VF via QUERY_FW, so that if the value gets accessed in the VF driver, we'll catch the problem. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/fw.c | 10 +++++++--- include/linux/mlx4/device.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 9c83bb8151ea..4281ce09add8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -881,11 +881,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ((fw_ver & 0xffff0000ull) >> 16) | ((fw_ver & 0x0000ffffull) << 16); + MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); + dev->caps.function = lg; + if (mlx4_is_slave(dev)) goto out; - MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); - dev->caps.function = lg; MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || @@ -966,9 +967,12 @@ int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave, if (err) return err; - /* for slaves, zero out everything except FW version */ + /* for slaves, set pci PPF ID to invalid and zero out everything + * else except FW version */ outbuf[0] = outbuf[1] = 0; memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8); + outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID; + return 0; } diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 6a8f002b8ed3..8eadf0f14cc5 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -534,6 +534,8 @@ struct mlx4_init_port_param { if (((dev)->caps.port_mask[port] == MLX4_PORT_TYPE_IB) || \ ((dev)->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) +#define MLX4_INVALID_SLAVE_ID 0xFF + static inline int mlx4_is_master(struct mlx4_dev *dev) { return dev->flags & MLX4_FLAG_MASTER; -- GitLab From b1d8eb5a213640f1be98a90e73a241d15b70045c Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:35 +0300 Subject: [PATCH 2274/5711] IB/mlx4: Add debug prints Define pr_fmt and add some pr_debug prints. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 19 +++++++++++++++++++ drivers/infiniband/hw/mlx4/main.c | 2 +- drivers/infiniband/hw/mlx4/mlx4_ib.h | 10 ++++++++++ drivers/infiniband/hw/mlx4/qp.c | 27 +++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 259b0670b51c..84786a9fb64f 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -242,6 +242,25 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int err; struct ib_port_attr pattr; + if (in_wc && in_wc->qp->qp_num) { + pr_debug("received MAD: slid:%d sqpn:%d " + "dlid_bits:%d dqpn:%d wc_flags:0x%x, cls %x, mtd %x, atr %x\n", + in_wc->slid, in_wc->src_qp, + in_wc->dlid_path_bits, + in_wc->qp->qp_num, + in_wc->wc_flags, + in_mad->mad_hdr.mgmt_class, in_mad->mad_hdr.method, + be16_to_cpu(in_mad->mad_hdr.attr_id)); + if (in_wc->wc_flags & IB_WC_GRH) { + pr_debug("sgid_hi:0x%016llx sgid_lo:0x%016llx\n", + be64_to_cpu(in_grh->sgid.global.subnet_prefix), + be64_to_cpu(in_grh->sgid.global.interface_id)); + pr_debug("dgid_hi:0x%016llx dgid_lo:0x%016llx\n", + be64_to_cpu(in_grh->dgid.global.subnet_prefix), + be64_to_cpu(in_grh->dgid.global.interface_id)); + } + } + slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0) { diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 3530c41fcd1f..5266b49c46ee 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -50,7 +50,7 @@ #include "mlx4_ib.h" #include "user.h" -#define DRV_NAME "mlx4_ib" +#define DRV_NAME MLX4_IB_DRV_NAME #define DRV_VERSION "1.0" #define DRV_RELDATE "April 4, 2008" diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index ff36655d23d3..5f298afaa81f 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -44,6 +44,16 @@ #include #include +#define MLX4_IB_DRV_NAME "mlx4_ib" + +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) "<" MLX4_IB_DRV_NAME "> %s: " fmt, __func__ + +#define mlx4_ib_warn(ibdev, format, arg...) \ + dev_warn((ibdev)->dma_device, MLX4_IB_DRV_NAME ": " format, ## arg) + enum { MLX4_IB_SQ_MIN_WQE_SHIFT = 6, MLX4_IB_MAX_HEADROOM = 2048 diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 8d4ed24aef93..84b26963c8d4 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1335,11 +1335,21 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; - if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) + if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) { + pr_debug("qpn 0x%x: invalid attribute mask specified " + "for transition %d to %d. qp_type %d," + " attr_mask 0x%x\n", + ibqp->qp_num, cur_state, new_state, + ibqp->qp_type, attr_mask); goto out; + } if ((attr_mask & IB_QP_PORT) && (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) { + pr_debug("qpn 0x%x: invalid port number (%d) specified " + "for transition %d to %d. qp_type %d\n", + ibqp->qp_num, attr->port_num, cur_state, + new_state, ibqp->qp_type); goto out; } @@ -1350,17 +1360,30 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (attr_mask & IB_QP_PKEY_INDEX) { int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; - if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p]) + if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p]) { + pr_debug("qpn 0x%x: invalid pkey index (%d) specified " + "for transition %d to %d. qp_type %d\n", + ibqp->qp_num, attr->pkey_index, cur_state, + new_state, ibqp->qp_type); goto out; + } } if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) { + pr_debug("qpn 0x%x: max_rd_atomic (%d) too large. " + "Transition %d to %d. qp_type %d\n", + ibqp->qp_num, attr->max_rd_atomic, cur_state, + new_state, ibqp->qp_type); goto out; } if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && attr->max_dest_rd_atomic > dev->dev->caps.max_qp_dest_rdma) { + pr_debug("qpn 0x%x: max_dest_rd_atomic (%d) too large. " + "Transition %d to %d. qp_type %d\n", + ibqp->qp_num, attr->max_dest_rd_atomic, cur_state, + new_state, ibqp->qp_type); goto out; } -- GitLab From aeab97ed1503bedbe14d1e1c5ab7b90253a67664 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Tue, 19 Jun 2012 11:21:38 +0300 Subject: [PATCH 2275/5711] IB/sa: Add GuidInfoRecord query support This query is needed for SRIOV alias GUID support. The query is implemented per the IB Spec definition in section 15.2.5.18 (GuidInfoRecord). Signed-off-by: Erez Shitrit Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/sa_query.c | 133 +++++++++++++++++++++++++++++ include/rdma/ib_sa.h | 33 +++++++ 2 files changed, 166 insertions(+) diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index fbbfa24cf572..a8905abc56e4 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -94,6 +94,12 @@ struct ib_sa_path_query { struct ib_sa_query sa_query; }; +struct ib_sa_guidinfo_query { + void (*callback)(int, struct ib_sa_guidinfo_rec *, void *); + void *context; + struct ib_sa_query sa_query; +}; + struct ib_sa_mcmember_query { void (*callback)(int, struct ib_sa_mcmember_rec *, void *); void *context; @@ -347,6 +353,34 @@ static const struct ib_field service_rec_table[] = { .size_bits = 2*64 }, }; +#define GUIDINFO_REC_FIELD(field) \ + .struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \ + .struct_size_bytes = sizeof((struct ib_sa_guidinfo_rec *) 0)->field, \ + .field_name = "sa_guidinfo_rec:" #field + +static const struct ib_field guidinfo_rec_table[] = { + { GUIDINFO_REC_FIELD(lid), + .offset_words = 0, + .offset_bits = 0, + .size_bits = 16 }, + { GUIDINFO_REC_FIELD(block_num), + .offset_words = 0, + .offset_bits = 16, + .size_bits = 8 }, + { GUIDINFO_REC_FIELD(res1), + .offset_words = 0, + .offset_bits = 24, + .size_bits = 8 }, + { GUIDINFO_REC_FIELD(res2), + .offset_words = 1, + .offset_bits = 0, + .size_bits = 32 }, + { GUIDINFO_REC_FIELD(guid_info_list), + .offset_words = 2, + .offset_bits = 0, + .size_bits = 512 }, +}; + static void free_sm_ah(struct kref *kref) { struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref); @@ -945,6 +979,105 @@ err1: return ret; } +/* Support GuidInfoRecord */ +static void ib_sa_guidinfo_rec_callback(struct ib_sa_query *sa_query, + int status, + struct ib_sa_mad *mad) +{ + struct ib_sa_guidinfo_query *query = + container_of(sa_query, struct ib_sa_guidinfo_query, sa_query); + + if (mad) { + struct ib_sa_guidinfo_rec rec; + + ib_unpack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), + mad->data, &rec); + query->callback(status, &rec, query->context); + } else + query->callback(status, NULL, query->context); +} + +static void ib_sa_guidinfo_rec_release(struct ib_sa_query *sa_query) +{ + kfree(container_of(sa_query, struct ib_sa_guidinfo_query, sa_query)); +} + +int ib_sa_guid_info_rec_query(struct ib_sa_client *client, + struct ib_device *device, u8 port_num, + struct ib_sa_guidinfo_rec *rec, + ib_sa_comp_mask comp_mask, u8 method, + int timeout_ms, gfp_t gfp_mask, + void (*callback)(int status, + struct ib_sa_guidinfo_rec *resp, + void *context), + void *context, + struct ib_sa_query **sa_query) +{ + struct ib_sa_guidinfo_query *query; + struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); + struct ib_sa_port *port; + struct ib_mad_agent *agent; + struct ib_sa_mad *mad; + int ret; + + if (!sa_dev) + return -ENODEV; + + if (method != IB_MGMT_METHOD_GET && + method != IB_MGMT_METHOD_SET && + method != IB_SA_METHOD_DELETE) { + return -EINVAL; + } + + port = &sa_dev->port[port_num - sa_dev->start_port]; + agent = port->agent; + + query = kmalloc(sizeof *query, gfp_mask); + if (!query) + return -ENOMEM; + + query->sa_query.port = port; + ret = alloc_mad(&query->sa_query, gfp_mask); + if (ret) + goto err1; + + ib_sa_client_get(client); + query->sa_query.client = client; + query->callback = callback; + query->context = context; + + mad = query->sa_query.mad_buf->mad; + init_mad(mad, agent); + + query->sa_query.callback = callback ? ib_sa_guidinfo_rec_callback : NULL; + query->sa_query.release = ib_sa_guidinfo_rec_release; + + mad->mad_hdr.method = method; + mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_GUID_INFO_REC); + mad->sa_hdr.comp_mask = comp_mask; + + ib_pack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), rec, + mad->data); + + *sa_query = &query->sa_query; + + ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); + if (ret < 0) + goto err2; + + return ret; + +err2: + *sa_query = NULL; + ib_sa_client_put(query->sa_query.client); + free_mad(&query->sa_query); + +err1: + kfree(query); + return ret; +} +EXPORT_SYMBOL(ib_sa_guid_info_rec_query); + static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *mad_send_wc) { diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index d44a56388a3e..8275e539bace 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -251,6 +251,28 @@ struct ib_sa_service_rec { u64 data64[2]; }; +#define IB_SA_GUIDINFO_REC_LID IB_SA_COMP_MASK(0) +#define IB_SA_GUIDINFO_REC_BLOCK_NUM IB_SA_COMP_MASK(1) +#define IB_SA_GUIDINFO_REC_RES1 IB_SA_COMP_MASK(2) +#define IB_SA_GUIDINFO_REC_RES2 IB_SA_COMP_MASK(3) +#define IB_SA_GUIDINFO_REC_GID0 IB_SA_COMP_MASK(4) +#define IB_SA_GUIDINFO_REC_GID1 IB_SA_COMP_MASK(5) +#define IB_SA_GUIDINFO_REC_GID2 IB_SA_COMP_MASK(6) +#define IB_SA_GUIDINFO_REC_GID3 IB_SA_COMP_MASK(7) +#define IB_SA_GUIDINFO_REC_GID4 IB_SA_COMP_MASK(8) +#define IB_SA_GUIDINFO_REC_GID5 IB_SA_COMP_MASK(9) +#define IB_SA_GUIDINFO_REC_GID6 IB_SA_COMP_MASK(10) +#define IB_SA_GUIDINFO_REC_GID7 IB_SA_COMP_MASK(11) + +struct ib_sa_guidinfo_rec { + __be16 lid; + u8 block_num; + /* reserved */ + u8 res1; + __be32 res2; + u8 guid_info_list[64]; +}; + struct ib_sa_client { atomic_t users; struct completion comp; @@ -385,4 +407,15 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, */ void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec); +/* Support GuidInfoRecord */ +int ib_sa_guid_info_rec_query(struct ib_sa_client *client, + struct ib_device *device, u8 port_num, + struct ib_sa_guidinfo_rec *rec, + ib_sa_comp_mask comp_mask, u8 method, + int timeout_ms, gfp_t gfp_mask, + void (*callback)(int status, + struct ib_sa_guidinfo_rec *resp, + void *context), + void *context, + struct ib_sa_query **sa_query); #endif /* IB_SA_H */ -- GitLab From 3045f0920367e625bbec7d66fadb444e673515af Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:39 +0300 Subject: [PATCH 2276/5711] IB/core: Move CM_xxx_ATTR_ID macros from cm_msgs.h to ib_cm.h These macros will be reused by the mlx4 SRIOV-IB CM paravirtualization code, and there is no reason to have them declared both in the IB core in the mlx4 IB driver. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm_msgs.h | 12 ------------ include/rdma/ib_cm.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h index 7da9b2102341..be068f47e47e 100644 --- a/drivers/infiniband/core/cm_msgs.h +++ b/drivers/infiniband/core/cm_msgs.h @@ -44,18 +44,6 @@ #define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */ -#define CM_REQ_ATTR_ID cpu_to_be16(0x0010) -#define CM_MRA_ATTR_ID cpu_to_be16(0x0011) -#define CM_REJ_ATTR_ID cpu_to_be16(0x0012) -#define CM_REP_ATTR_ID cpu_to_be16(0x0013) -#define CM_RTU_ATTR_ID cpu_to_be16(0x0014) -#define CM_DREQ_ATTR_ID cpu_to_be16(0x0015) -#define CM_DREP_ATTR_ID cpu_to_be16(0x0016) -#define CM_SIDR_REQ_ATTR_ID cpu_to_be16(0x0017) -#define CM_SIDR_REP_ATTR_ID cpu_to_be16(0x0018) -#define CM_LAP_ATTR_ID cpu_to_be16(0x0019) -#define CM_APR_ATTR_ID cpu_to_be16(0x001A) - enum cm_msg_sequence { CM_MSG_SEQUENCE_REQ, CM_MSG_SEQUENCE_LAP, diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index 83f77ac33957..0e3ff30647d5 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h @@ -262,6 +262,18 @@ struct ib_cm_event { void *private_data; }; +#define CM_REQ_ATTR_ID cpu_to_be16(0x0010) +#define CM_MRA_ATTR_ID cpu_to_be16(0x0011) +#define CM_REJ_ATTR_ID cpu_to_be16(0x0012) +#define CM_REP_ATTR_ID cpu_to_be16(0x0013) +#define CM_RTU_ATTR_ID cpu_to_be16(0x0014) +#define CM_DREQ_ATTR_ID cpu_to_be16(0x0015) +#define CM_DREP_ATTR_ID cpu_to_be16(0x0016) +#define CM_SIDR_REQ_ATTR_ID cpu_to_be16(0x0017) +#define CM_SIDR_REP_ATTR_ID cpu_to_be16(0x0018) +#define CM_LAP_ATTR_ID cpu_to_be16(0x0019) +#define CM_APR_ATTR_ID cpu_to_be16(0x001A) + /** * ib_cm_handler - User-defined callback to process communication events. * @cm_id: Communication identifier associated with the reported event. -- GitLab From 354dff1bd8ccd41b6e8421226d586d35e7fb8920 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 27 Jun 2012 18:33:05 -0400 Subject: [PATCH 2277/5711] IB/qib: Fix UC MR refs for immediate operations An MR reference leak exists when handling UC RDMA writes with immediate data because we manipulate the reference counts as if the operation had been a send. This patch moves the last_imm label so that the RDMA write operations with immediate data converge at the cq building code. The copy/mr deref code is now done correctly prior to the branch to last_imm. Reviewed-by: Edward Mascarenhas Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_uc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c index ce7387ff5d91..70b4cb710f9a 100644 --- a/drivers/infiniband/hw/qib/qib_uc.c +++ b/drivers/infiniband/hw/qib/qib_uc.c @@ -403,7 +403,6 @@ send_last: if (unlikely(wc.byte_len > qp->r_len)) goto rewind; wc.opcode = IB_WC_RECV; -last_imm: qib_copy_sge(&qp->r_sge, data, tlen, 0); while (qp->s_rdma_read_sge.num_sge) { atomic_dec(&qp->s_rdma_read_sge.sge.mr->refcount); @@ -411,6 +410,7 @@ last_imm: qp->s_rdma_read_sge.sge = *qp->s_rdma_read_sge.sg_list++; } +last_imm: wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; wc.qp = &qp->ibqp; @@ -509,6 +509,12 @@ rdma_last_imm: } wc.byte_len = qp->r_len; wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; + qib_copy_sge(&qp->r_sge, data, tlen, 1); + while (qp->r_sge.num_sge) { + atomic_dec(&qp->r_sge.sge.mr->refcount); + if (--qp->r_sge.num_sge) + qp->r_sge.sge = *qp->r_sge.sg_list++; + } goto last_imm; case OP(RDMA_WRITE_LAST): -- GitLab From 6a82649f217023863d6b1740017e6c3dd6685327 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 27 Jun 2012 18:33:12 -0400 Subject: [PATCH 2278/5711] IB/qib: Avoid returning EBUSY from MR deregister A timing issue can occur where qib_mr_dereg can return -EBUSY if the MR use count is not zero. This can occur if the MR is de-registered while RDMA read response packets are being progressed from the SDMA ring. The suspicion is that the peer sent an RDMA read request, which has already been copied across to the peer. The peer sees the completion of his request and then communicates to the responder that the MR is not needed any longer. The responder tries to de-register the MR, catching some responses remaining in the SDMA ring holding the MR use count. The code now uses a get/put paradigm to track MR use counts and coordinates with the MR de-registration process using a completion when the count has reached zero. A timeout on the delay is in place to catch other EBUSY issues. The reference count protocol is as follows: - The return to the user counts as 1 - A reference from the lk_table or the qib_ibdev counts as 1. - Transient I/O operations increase/decrease as necessary A lot of code duplication has been folded into the new routines init_qib_mregion() and deinit_qib_mregion(). Additionally, explicit initialization of fields to zero is now handled by kzalloc(). Also, duplicated code 'while.*num_sge' that decrements reference counts have been consolidated in qib_put_ss(). Reviewed-by: Ramkrishna Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_keys.c | 84 +++++---- drivers/infiniband/hw/qib/qib_mr.c | 242 ++++++++++++++------------ drivers/infiniband/hw/qib/qib_qp.c | 21 +-- drivers/infiniband/hw/qib/qib_rc.c | 24 ++- drivers/infiniband/hw/qib/qib_ruc.c | 14 +- drivers/infiniband/hw/qib/qib_uc.c | 33 +--- drivers/infiniband/hw/qib/qib_ud.c | 12 +- drivers/infiniband/hw/qib/qib_verbs.c | 10 +- drivers/infiniband/hw/qib/qib_verbs.h | 28 ++- 9 files changed, 244 insertions(+), 224 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c index 8fd19a47df0c..8b5ee3aa8e3d 100644 --- a/drivers/infiniband/hw/qib/qib_keys.c +++ b/drivers/infiniband/hw/qib/qib_keys.c @@ -35,21 +35,40 @@ /** * qib_alloc_lkey - allocate an lkey - * @rkt: lkey table in which to allocate the lkey * @mr: memory region that this lkey protects + * @dma_region: 0->normal key, 1->restricted DMA key + * + * Returns 0 if successful, otherwise returns -errno. + * + * Increments mr reference count and sets published + * as required. + * + * Sets the lkey field mr for non-dma regions. * - * Returns 1 if successful, otherwise returns 0. */ -int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr) +int qib_alloc_lkey(struct qib_mregion *mr, int dma_region) { unsigned long flags; u32 r; u32 n; - int ret; + int ret = 0; + struct qib_ibdev *dev = to_idev(mr->pd->device); + struct qib_lkey_table *rkt = &dev->lk_table; spin_lock_irqsave(&rkt->lock, flags); + /* special case for dma_mr lkey == 0 */ + if (dma_region) { + /* should the dma_mr be relative to the pd? */ + if (!dev->dma_mr) { + qib_get_mr(mr); + dev->dma_mr = mr; + mr->lkey_published = 1; + } + goto success; + } + /* Find the next available LKEY */ r = rkt->next; n = r; @@ -57,11 +76,8 @@ int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr) if (rkt->table[r] == NULL) break; r = (r + 1) & (rkt->max - 1); - if (r == n) { - spin_unlock_irqrestore(&rkt->lock, flags); - ret = 0; + if (r == n) goto bail; - } } rkt->next = (r + 1) & (rkt->max - 1); /* @@ -76,46 +92,50 @@ int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr) mr->lkey |= 1 << 8; rkt->gen++; } + qib_get_mr(mr); rkt->table[r] = mr; + mr->lkey_published = 1; +success: spin_unlock_irqrestore(&rkt->lock, flags); - - ret = 1; - -bail: +out: return ret; +bail: + spin_unlock_irqrestore(&rkt->lock, flags); + ret = -ENOMEM; + goto out; } /** * qib_free_lkey - free an lkey - * @rkt: table from which to free the lkey - * @lkey: lkey id to free + * @mr: mr to free from tables */ -int qib_free_lkey(struct qib_ibdev *dev, struct qib_mregion *mr) +void qib_free_lkey(struct qib_mregion *mr) { unsigned long flags; u32 lkey = mr->lkey; u32 r; - int ret; + struct qib_ibdev *dev = to_idev(mr->pd->device); + struct qib_lkey_table *rkt = &dev->lk_table; + + spin_lock_irqsave(&rkt->lock, flags); + if (!mr->lkey_published) + goto out; + mr->lkey_published = 0; + spin_lock_irqsave(&dev->lk_table.lock, flags); if (lkey == 0) { if (dev->dma_mr && dev->dma_mr == mr) { - ret = atomic_read(&dev->dma_mr->refcount); - if (!ret) - dev->dma_mr = NULL; - } else - ret = 0; + qib_put_mr(dev->dma_mr); + dev->dma_mr = NULL; + } } else { r = lkey >> (32 - ib_qib_lkey_table_size); - ret = atomic_read(&dev->lk_table.table[r]->refcount); - if (!ret) - dev->lk_table.table[r] = NULL; + qib_put_mr(dev->dma_mr); + rkt->table[r] = NULL; } +out: spin_unlock_irqrestore(&dev->lk_table.lock, flags); - - if (ret) - ret = -EBUSY; - return ret; } /** @@ -150,7 +170,7 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, goto bail; if (!dev->dma_mr) goto bail; - atomic_inc(&dev->dma_mr->refcount); + qib_get_mr(dev->dma_mr); spin_unlock_irqrestore(&rkt->lock, flags); isge->mr = dev->dma_mr; @@ -171,7 +191,7 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, off + sge->length > mr->length || (mr->access_flags & acc) != acc)) goto bail; - atomic_inc(&mr->refcount); + qib_get_mr(mr); spin_unlock_irqrestore(&rkt->lock, flags); off += mr->offset; @@ -245,7 +265,7 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, goto bail; if (!dev->dma_mr) goto bail; - atomic_inc(&dev->dma_mr->refcount); + qib_get_mr(dev->dma_mr); spin_unlock_irqrestore(&rkt->lock, flags); sge->mr = dev->dma_mr; @@ -265,7 +285,7 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, if (unlikely(vaddr < mr->iova || off + len > mr->length || (mr->access_flags & acc) == 0)) goto bail; - atomic_inc(&mr->refcount); + qib_get_mr(mr); spin_unlock_irqrestore(&rkt->lock, flags); off += mr->offset; diff --git a/drivers/infiniband/hw/qib/qib_mr.c b/drivers/infiniband/hw/qib/qib_mr.c index 08944e2ee334..6a2028a56e3d 100644 --- a/drivers/infiniband/hw/qib/qib_mr.c +++ b/drivers/infiniband/hw/qib/qib_mr.c @@ -47,6 +47,43 @@ static inline struct qib_fmr *to_ifmr(struct ib_fmr *ibfmr) return container_of(ibfmr, struct qib_fmr, ibfmr); } +static int init_qib_mregion(struct qib_mregion *mr, struct ib_pd *pd, + int count) +{ + int m, i = 0; + int rval = 0; + + m = (count + QIB_SEGSZ - 1) / QIB_SEGSZ; + for (; i < m; i++) { + mr->map[i] = kzalloc(sizeof *mr->map[0], GFP_KERNEL); + if (!mr->map[i]) + goto bail; + } + mr->mapsz = m; + init_completion(&mr->comp); + /* count returning the ptr to user */ + atomic_set(&mr->refcount, 1); + mr->pd = pd; + mr->max_segs = count; +out: + return rval; +bail: + while (i) + kfree(mr->map[--i]); + rval = -ENOMEM; + goto out; +} + +static void deinit_qib_mregion(struct qib_mregion *mr) +{ + int i = mr->mapsz; + + mr->mapsz = 0; + while (i) + kfree(mr->map[--i]); +} + + /** * qib_get_dma_mr - get a DMA memory region * @pd: protection domain for this memory region @@ -58,10 +95,9 @@ static inline struct qib_fmr *to_ifmr(struct ib_fmr *ibfmr) */ struct ib_mr *qib_get_dma_mr(struct ib_pd *pd, int acc) { - struct qib_ibdev *dev = to_idev(pd->device); - struct qib_mr *mr; + struct qib_mr *mr = NULL; struct ib_mr *ret; - unsigned long flags; + int rval; if (to_ipd(pd)->user) { ret = ERR_PTR(-EPERM); @@ -74,61 +110,64 @@ struct ib_mr *qib_get_dma_mr(struct ib_pd *pd, int acc) goto bail; } - mr->mr.access_flags = acc; - atomic_set(&mr->mr.refcount, 0); + rval = init_qib_mregion(&mr->mr, pd, 0); + if (rval) { + ret = ERR_PTR(rval); + goto bail; + } - spin_lock_irqsave(&dev->lk_table.lock, flags); - if (!dev->dma_mr) - dev->dma_mr = &mr->mr; - spin_unlock_irqrestore(&dev->lk_table.lock, flags); + rval = qib_alloc_lkey(&mr->mr, 1); + if (rval) { + ret = ERR_PTR(rval); + goto bail_mregion; + } + + mr->mr.access_flags = acc; ret = &mr->ibmr; +done: + return ret; +bail_mregion: + deinit_qib_mregion(&mr->mr); bail: - return ret; + kfree(mr); + goto done; } -static struct qib_mr *alloc_mr(int count, struct qib_lkey_table *lk_table) +static struct qib_mr *alloc_mr(int count, struct ib_pd *pd) { struct qib_mr *mr; - int m, i = 0; + int rval = -ENOMEM; + int m; /* Allocate struct plus pointers to first level page tables. */ m = (count + QIB_SEGSZ - 1) / QIB_SEGSZ; - mr = kmalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL); + mr = kzalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL); if (!mr) - goto done; - - /* Allocate first level page tables. */ - for (; i < m; i++) { - mr->mr.map[i] = kmalloc(sizeof *mr->mr.map[0], GFP_KERNEL); - if (!mr->mr.map[i]) - goto bail; - } - mr->mr.mapsz = m; - mr->mr.page_shift = 0; - mr->mr.max_segs = count; + goto bail; + rval = init_qib_mregion(&mr->mr, pd, count); + if (rval) + goto bail; /* * ib_reg_phys_mr() will initialize mr->ibmr except for * lkey and rkey. */ - if (!qib_alloc_lkey(lk_table, &mr->mr)) - goto bail; + rval = qib_alloc_lkey(&mr->mr, 0); + if (rval) + goto bail_mregion; mr->ibmr.lkey = mr->mr.lkey; mr->ibmr.rkey = mr->mr.lkey; +done: + return mr; - atomic_set(&mr->mr.refcount, 0); - goto done; - +bail_mregion: + deinit_qib_mregion(&mr->mr); bail: - while (i) - kfree(mr->mr.map[--i]); kfree(mr); - mr = NULL; - -done: - return mr; + mr = ERR_PTR(rval); + goto done; } /** @@ -148,19 +187,15 @@ struct ib_mr *qib_reg_phys_mr(struct ib_pd *pd, int n, m, i; struct ib_mr *ret; - mr = alloc_mr(num_phys_buf, &to_idev(pd->device)->lk_table); - if (mr == NULL) { - ret = ERR_PTR(-ENOMEM); + mr = alloc_mr(num_phys_buf, pd); + if (IS_ERR(mr)) { + ret = (struct ib_mr *)mr; goto bail; } - mr->mr.pd = pd; mr->mr.user_base = *iova_start; mr->mr.iova = *iova_start; - mr->mr.length = 0; - mr->mr.offset = 0; mr->mr.access_flags = acc; - mr->umem = NULL; m = 0; n = 0; @@ -186,7 +221,6 @@ bail: * @pd: protection domain for this memory region * @start: starting userspace address * @length: length of region to register - * @virt_addr: virtual address to use (from HCA's point of view) * @mr_access_flags: access flags for this memory region * @udata: unused by the QLogic_IB driver * @@ -216,14 +250,13 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, list_for_each_entry(chunk, &umem->chunk_list, list) n += chunk->nents; - mr = alloc_mr(n, &to_idev(pd->device)->lk_table); - if (!mr) { - ret = ERR_PTR(-ENOMEM); + mr = alloc_mr(n, pd); + if (IS_ERR(mr)) { + ret = (struct ib_mr *)mr; ib_umem_release(umem); goto bail; } - mr->mr.pd = pd; mr->mr.user_base = start; mr->mr.iova = virt_addr; mr->mr.length = length; @@ -271,21 +304,25 @@ bail: int qib_dereg_mr(struct ib_mr *ibmr) { struct qib_mr *mr = to_imr(ibmr); - struct qib_ibdev *dev = to_idev(ibmr->device); - int ret; - int i; - - ret = qib_free_lkey(dev, &mr->mr); - if (ret) - return ret; - - i = mr->mr.mapsz; - while (i) - kfree(mr->mr.map[--i]); + int ret = 0; + unsigned long timeout; + + qib_free_lkey(&mr->mr); + + qib_put_mr(&mr->mr); /* will set completion if last */ + timeout = wait_for_completion_timeout(&mr->mr.comp, + 5 * HZ); + if (!timeout) { + qib_get_mr(&mr->mr); + ret = -EBUSY; + goto out; + } + deinit_qib_mregion(&mr->mr); if (mr->umem) ib_umem_release(mr->umem); kfree(mr); - return 0; +out: + return ret; } /* @@ -298,17 +335,9 @@ struct ib_mr *qib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len) { struct qib_mr *mr; - mr = alloc_mr(max_page_list_len, &to_idev(pd->device)->lk_table); - if (mr == NULL) - return ERR_PTR(-ENOMEM); - - mr->mr.pd = pd; - mr->mr.user_base = 0; - mr->mr.iova = 0; - mr->mr.length = 0; - mr->mr.offset = 0; - mr->mr.access_flags = 0; - mr->umem = NULL; + mr = alloc_mr(max_page_list_len, pd); + if (IS_ERR(mr)) + return (struct ib_mr *)mr; return &mr->ibmr; } @@ -322,11 +351,11 @@ qib_alloc_fast_reg_page_list(struct ib_device *ibdev, int page_list_len) if (size > PAGE_SIZE) return ERR_PTR(-EINVAL); - pl = kmalloc(sizeof *pl, GFP_KERNEL); + pl = kzalloc(sizeof *pl, GFP_KERNEL); if (!pl) return ERR_PTR(-ENOMEM); - pl->page_list = kmalloc(size, GFP_KERNEL); + pl->page_list = kzalloc(size, GFP_KERNEL); if (!pl->page_list) goto err_free; @@ -355,57 +384,47 @@ struct ib_fmr *qib_alloc_fmr(struct ib_pd *pd, int mr_access_flags, struct ib_fmr_attr *fmr_attr) { struct qib_fmr *fmr; - int m, i = 0; + int m; struct ib_fmr *ret; + int rval = -ENOMEM; /* Allocate struct plus pointers to first level page tables. */ m = (fmr_attr->max_pages + QIB_SEGSZ - 1) / QIB_SEGSZ; - fmr = kmalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL); + fmr = kzalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL); if (!fmr) goto bail; - /* Allocate first level page tables. */ - for (; i < m; i++) { - fmr->mr.map[i] = kmalloc(sizeof *fmr->mr.map[0], - GFP_KERNEL); - if (!fmr->mr.map[i]) - goto bail; - } - fmr->mr.mapsz = m; + rval = init_qib_mregion(&fmr->mr, pd, fmr_attr->max_pages); + if (rval) + goto bail; /* * ib_alloc_fmr() will initialize fmr->ibfmr except for lkey & * rkey. */ - if (!qib_alloc_lkey(&to_idev(pd->device)->lk_table, &fmr->mr)) - goto bail; + rval = qib_alloc_lkey(&fmr->mr, 0); + if (rval) + goto bail_mregion; fmr->ibfmr.rkey = fmr->mr.lkey; fmr->ibfmr.lkey = fmr->mr.lkey; /* * Resources are allocated but no valid mapping (RKEY can't be * used). */ - fmr->mr.pd = pd; - fmr->mr.user_base = 0; - fmr->mr.iova = 0; - fmr->mr.length = 0; - fmr->mr.offset = 0; fmr->mr.access_flags = mr_access_flags; fmr->mr.max_segs = fmr_attr->max_pages; fmr->mr.page_shift = fmr_attr->page_shift; - atomic_set(&fmr->mr.refcount, 0); ret = &fmr->ibfmr; - goto done; +done: + return ret; +bail_mregion: + deinit_qib_mregion(&fmr->mr); bail: - while (i) - kfree(fmr->mr.map[--i]); kfree(fmr); - ret = ERR_PTR(-ENOMEM); - -done: - return ret; + ret = ERR_PTR(rval); + goto done; } /** @@ -428,7 +447,8 @@ int qib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, u32 ps; int ret; - if (atomic_read(&fmr->mr.refcount)) + i = atomic_read(&fmr->mr.refcount); + if (i > 2) return -EBUSY; if (list_len > fmr->mr.max_segs) { @@ -490,16 +510,20 @@ int qib_unmap_fmr(struct list_head *fmr_list) int qib_dealloc_fmr(struct ib_fmr *ibfmr) { struct qib_fmr *fmr = to_ifmr(ibfmr); - int ret; - int i; - - ret = qib_free_lkey(to_idev(ibfmr->device), &fmr->mr); - if (ret) - return ret; - - i = fmr->mr.mapsz; - while (i) - kfree(fmr->mr.map[--i]); + int ret = 0; + unsigned long timeout; + + qib_free_lkey(&fmr->mr); + qib_put_mr(&fmr->mr); /* will set completion if last */ + timeout = wait_for_completion_timeout(&fmr->mr.comp, + 5 * HZ); + if (!timeout) { + qib_get_mr(&fmr->mr); + ret = -EBUSY; + goto out; + } + deinit_qib_mregion(&fmr->mr); kfree(fmr); - return 0; +out: + return ret; } diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 1ce56b51ab1a..693041b076f0 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -406,18 +406,9 @@ static void clear_mr_refs(struct qib_qp *qp, int clr_sends) unsigned n; if (test_and_clear_bit(QIB_R_REWIND_SGE, &qp->r_aflags)) - while (qp->s_rdma_read_sge.num_sge) { - atomic_dec(&qp->s_rdma_read_sge.sge.mr->refcount); - if (--qp->s_rdma_read_sge.num_sge) - qp->s_rdma_read_sge.sge = - *qp->s_rdma_read_sge.sg_list++; - } + qib_put_ss(&qp->s_rdma_read_sge); - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); if (clr_sends) { while (qp->s_last != qp->s_head) { @@ -427,7 +418,7 @@ static void clear_mr_refs(struct qib_qp *qp, int clr_sends) for (i = 0; i < wqe->wr.num_sge; i++) { struct qib_sge *sge = &wqe->sg_list[i]; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } if (qp->ibqp.qp_type == IB_QPT_UD || qp->ibqp.qp_type == IB_QPT_SMI || @@ -437,7 +428,7 @@ static void clear_mr_refs(struct qib_qp *qp, int clr_sends) qp->s_last = 0; } if (qp->s_rdma_mr) { - atomic_dec(&qp->s_rdma_mr->refcount); + qib_put_mr(qp->s_rdma_mr); qp->s_rdma_mr = NULL; } } @@ -450,7 +441,7 @@ static void clear_mr_refs(struct qib_qp *qp, int clr_sends) if (e->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST && e->rdma_sge.mr) { - atomic_dec(&e->rdma_sge.mr->refcount); + qib_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } } @@ -495,7 +486,7 @@ int qib_error_qp(struct qib_qp *qp, enum ib_wc_status err) if (!(qp->s_flags & QIB_S_BUSY)) { qp->s_hdrwords = 0; if (qp->s_rdma_mr) { - atomic_dec(&qp->s_rdma_mr->refcount); + qib_put_mr(qp->s_rdma_mr); qp->s_rdma_mr = NULL; } if (qp->s_tx) { diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c index b641416148eb..3ab341320ead 100644 --- a/drivers/infiniband/hw/qib/qib_rc.c +++ b/drivers/infiniband/hw/qib/qib_rc.c @@ -95,7 +95,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct qib_qp *qp, case OP(RDMA_READ_RESPONSE_ONLY): e = &qp->s_ack_queue[qp->s_tail_ack_queue]; if (e->rdma_sge.mr) { - atomic_dec(&e->rdma_sge.mr->refcount); + qib_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } /* FALLTHROUGH */ @@ -133,7 +133,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct qib_qp *qp, /* Copy SGE state in case we need to resend */ qp->s_rdma_mr = e->rdma_sge.mr; if (qp->s_rdma_mr) - atomic_inc(&qp->s_rdma_mr->refcount); + qib_get_mr(qp->s_rdma_mr); qp->s_ack_rdma_sge.sge = e->rdma_sge; qp->s_ack_rdma_sge.num_sge = 1; qp->s_cur_sge = &qp->s_ack_rdma_sge; @@ -172,7 +172,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct qib_qp *qp, qp->s_cur_sge = &qp->s_ack_rdma_sge; qp->s_rdma_mr = qp->s_ack_rdma_sge.sge.mr; if (qp->s_rdma_mr) - atomic_inc(&qp->s_rdma_mr->refcount); + qib_get_mr(qp->s_rdma_mr); len = qp->s_ack_rdma_sge.sge.sge_length; if (len > pmtu) len = pmtu; @@ -1012,7 +1012,7 @@ void qib_rc_send_complete(struct qib_qp *qp, struct qib_ib_header *hdr) for (i = 0; i < wqe->wr.num_sge; i++) { struct qib_sge *sge = &wqe->sg_list[i]; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } /* Post a send completion queue entry if requested. */ if (!(qp->s_flags & QIB_S_SIGNAL_REQ_WR) || @@ -1068,7 +1068,7 @@ static struct qib_swqe *do_rc_completion(struct qib_qp *qp, for (i = 0; i < wqe->wr.num_sge; i++) { struct qib_sge *sge = &wqe->sg_list[i]; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } /* Post a send completion queue entry if requested. */ if (!(qp->s_flags & QIB_S_SIGNAL_REQ_WR) || @@ -1730,7 +1730,7 @@ static int qib_rc_rcv_error(struct qib_other_headers *ohdr, if (unlikely(offset + len != e->rdma_sge.sge_length)) goto unlock_done; if (e->rdma_sge.mr) { - atomic_dec(&e->rdma_sge.mr->refcount); + qib_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } if (len != 0) { @@ -2024,11 +2024,7 @@ send_last: if (unlikely(wc.byte_len > qp->r_len)) goto nack_inv; qib_copy_sge(&qp->r_sge, data, tlen, 1); - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); qp->r_msn++; if (!test_and_clear_bit(QIB_R_WRID_VALID, &qp->r_aflags)) break; @@ -2116,7 +2112,7 @@ send_last: } e = &qp->s_ack_queue[qp->r_head_ack_queue]; if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { - atomic_dec(&e->rdma_sge.mr->refcount); + qib_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } reth = &ohdr->u.rc.reth; @@ -2188,7 +2184,7 @@ send_last: } e = &qp->s_ack_queue[qp->r_head_ack_queue]; if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { - atomic_dec(&e->rdma_sge.mr->refcount); + qib_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } ateth = &ohdr->u.atomic_eth; @@ -2210,7 +2206,7 @@ send_last: (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, be64_to_cpu(ateth->compare_data), sdata); - atomic_dec(&qp->r_sge.sge.mr->refcount); + qib_put_mr(qp->r_sge.sge.mr); qp->r_sge.num_sge = 0; e->opcode = opcode; e->sent = 0; diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c index c0ee7e095d81..357b6cfcd46c 100644 --- a/drivers/infiniband/hw/qib/qib_ruc.c +++ b/drivers/infiniband/hw/qib/qib_ruc.c @@ -110,7 +110,7 @@ bad_lkey: while (j) { struct qib_sge *sge = --j ? &ss->sg_list[j - 1] : &ss->sge; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } ss->num_sge = 0; memset(&wc, 0, sizeof(wc)); @@ -501,7 +501,7 @@ again: (u64) atomic64_add_return(sdata, maddr) - sdata : (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, sdata, wqe->wr.wr.atomic.swap); - atomic_dec(&qp->r_sge.sge.mr->refcount); + qib_put_mr(qp->r_sge.sge.mr); qp->r_sge.num_sge = 0; goto send_comp; @@ -525,7 +525,7 @@ again: sge->sge_length -= len; if (sge->sge_length == 0) { if (!release) - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); if (--sqp->s_sge.num_sge) *sge = *sqp->s_sge.sg_list++; } else if (sge->length == 0 && sge->mr->lkey) { @@ -542,11 +542,7 @@ again: sqp->s_len -= len; } if (release) - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); if (!test_and_clear_bit(QIB_R_WRID_VALID, &qp->r_aflags)) goto send_comp; @@ -782,7 +778,7 @@ void qib_send_complete(struct qib_qp *qp, struct qib_swqe *wqe, for (i = 0; i < wqe->wr.num_sge; i++) { struct qib_sge *sge = &wqe->sg_list[i]; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } if (qp->ibqp.qp_type == IB_QPT_UD || qp->ibqp.qp_type == IB_QPT_SMI || diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c index 70b4cb710f9a..aa3a8035bb68 100644 --- a/drivers/infiniband/hw/qib/qib_uc.c +++ b/drivers/infiniband/hw/qib/qib_uc.c @@ -281,11 +281,7 @@ inv: set_bit(QIB_R_REWIND_SGE, &qp->r_aflags); qp->r_sge.num_sge = 0; } else - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); qp->r_state = OP(SEND_LAST); switch (opcode) { case OP(SEND_FIRST): @@ -404,12 +400,7 @@ send_last: goto rewind; wc.opcode = IB_WC_RECV; qib_copy_sge(&qp->r_sge, data, tlen, 0); - while (qp->s_rdma_read_sge.num_sge) { - atomic_dec(&qp->s_rdma_read_sge.sge.mr->refcount); - if (--qp->s_rdma_read_sge.num_sge) - qp->s_rdma_read_sge.sge = - *qp->s_rdma_read_sge.sg_list++; - } + qib_put_ss(&qp->s_rdma_read_sge); last_imm: wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; @@ -493,13 +484,7 @@ rdma_last_imm: if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) goto drop; if (test_and_clear_bit(QIB_R_REWIND_SGE, &qp->r_aflags)) - while (qp->s_rdma_read_sge.num_sge) { - atomic_dec(&qp->s_rdma_read_sge.sge.mr-> - refcount); - if (--qp->s_rdma_read_sge.num_sge) - qp->s_rdma_read_sge.sge = - *qp->s_rdma_read_sge.sg_list++; - } + qib_put_ss(&qp->s_rdma_read_sge); else { ret = qib_get_rwqe(qp, 1); if (ret < 0) @@ -510,11 +495,7 @@ rdma_last_imm: wc.byte_len = qp->r_len; wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; qib_copy_sge(&qp->r_sge, data, tlen, 1); - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); goto last_imm; case OP(RDMA_WRITE_LAST): @@ -530,11 +511,7 @@ rdma_last: if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) goto drop; qib_copy_sge(&qp->r_sge, data, tlen, 1); - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); break; default: diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index a468bf2d4465..d6c7fe7f88d5 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -194,11 +194,7 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe) } length -= len; } - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); if (!test_and_clear_bit(QIB_R_WRID_VALID, &qp->r_aflags)) goto bail_unlock; wc.wr_id = qp->r_wr_id; @@ -556,11 +552,7 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, } else qib_skip_sge(&qp->r_sge, sizeof(struct ib_grh), 1); qib_copy_sge(&qp->r_sge, data, wc.byte_len - sizeof(struct ib_grh), 1); - while (qp->r_sge.num_sge) { - atomic_dec(&qp->r_sge.sge.mr->refcount); - if (--qp->r_sge.num_sge) - qp->r_sge.sge = *qp->r_sge.sg_list++; - } + qib_put_ss(&qp->r_sge); if (!test_and_clear_bit(QIB_R_WRID_VALID, &qp->r_aflags)) return; wc.wr_id = qp->r_wr_id; diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 7b6c3bffa9d9..76d7ce8a8c6e 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -183,7 +183,7 @@ void qib_copy_sge(struct qib_sge_state *ss, void *data, u32 length, int release) sge->sge_length -= len; if (sge->sge_length == 0) { if (release) - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); if (--ss->num_sge) *sge = *ss->sg_list++; } else if (sge->length == 0 && sge->mr->lkey) { @@ -224,7 +224,7 @@ void qib_skip_sge(struct qib_sge_state *ss, u32 length, int release) sge->sge_length -= len; if (sge->sge_length == 0) { if (release) - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); if (--ss->num_sge) *sge = *ss->sg_list++; } else if (sge->length == 0 && sge->mr->lkey) { @@ -435,7 +435,7 @@ bail_inval_free: while (j) { struct qib_sge *sge = &wqe->sg_list[--j]; - atomic_dec(&sge->mr->refcount); + qib_put_mr(sge->mr); } bail_inval: ret = -EINVAL; @@ -978,7 +978,7 @@ void qib_put_txreq(struct qib_verbs_txreq *tx) if (atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); if (tx->mr) { - atomic_dec(&tx->mr->refcount); + qib_put_mr(tx->mr); tx->mr = NULL; } if (tx->txreq.flags & QIB_SDMA_TXREQ_F_FREEBUF) { @@ -1336,7 +1336,7 @@ done: } qib_sendbuf_done(dd, pbufn); if (qp->s_rdma_mr) { - atomic_dec(&qp->s_rdma_mr->refcount); + qib_put_mr(qp->s_rdma_mr); qp->s_rdma_mr = NULL; } if (qp->s_wqe) { diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 487606024659..4a2277bc059e 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -302,6 +303,8 @@ struct qib_mregion { u32 max_segs; /* number of qib_segs in all the arrays */ u32 mapsz; /* size of the map array */ u8 page_shift; /* 0 - non unform/non powerof2 sizes */ + u8 lkey_published; /* in global table */ + struct completion comp; /* complete when refcount goes to zero */ atomic_t refcount; struct qib_segarray *map[0]; /* the segments */ }; @@ -944,9 +947,9 @@ int qib_post_ud_send(struct qib_qp *qp, struct ib_send_wr *wr); void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, int has_grh, void *data, u32 tlen, struct qib_qp *qp); -int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr); +int qib_alloc_lkey(struct qib_mregion *mr, int dma_region); -int qib_free_lkey(struct qib_ibdev *dev, struct qib_mregion *mr); +void qib_free_lkey(struct qib_mregion *mr); int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, struct qib_sge *isge, struct ib_sge *sge, int acc); @@ -1014,6 +1017,27 @@ int qib_unmap_fmr(struct list_head *fmr_list); int qib_dealloc_fmr(struct ib_fmr *ibfmr); +static inline void qib_get_mr(struct qib_mregion *mr) +{ + atomic_inc(&mr->refcount); +} + +static inline void qib_put_mr(struct qib_mregion *mr) +{ + if (unlikely(atomic_dec_and_test(&mr->refcount))) + complete(&mr->comp); +} + +static inline void qib_put_ss(struct qib_sge_state *ss) +{ + while (ss->num_sge) { + qib_put_mr(ss->sge.mr); + if (--ss->num_sge) + ss->sge = *ss->sg_list++; + } +} + + void qib_release_mmap_info(struct kref *ref); struct qib_mmap_info *qib_create_mmap_info(struct qib_ibdev *dev, u32 size, -- GitLab From 8aac4cc3a9d7d7c2f203b7a8db521b604cfb5dc9 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 27 Jun 2012 18:33:19 -0400 Subject: [PATCH 2279/5711] IB/qib: RCU locking for MR validation Profiling indicates that MR validation locking is expensive. The MR table is largely read-only and is a suitable candidate for RCU locking. The patch uses RCU locking during validation to eliminate one lock/unlock during that validation. Reviewed-by: Mike Heinz Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_keys.c | 98 ++++++++++++++------------- drivers/infiniband/hw/qib/qib_mr.c | 7 ++ drivers/infiniband/hw/qib/qib_verbs.c | 4 +- drivers/infiniband/hw/qib/qib_verbs.h | 7 +- 4 files changed, 66 insertions(+), 50 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c index 8b5ee3aa8e3d..970165b027f7 100644 --- a/drivers/infiniband/hw/qib/qib_keys.c +++ b/drivers/infiniband/hw/qib/qib_keys.c @@ -40,8 +40,7 @@ * * Returns 0 if successful, otherwise returns -errno. * - * Increments mr reference count and sets published - * as required. + * Increments mr reference count as required. * * Sets the lkey field mr for non-dma regions. * @@ -60,10 +59,12 @@ int qib_alloc_lkey(struct qib_mregion *mr, int dma_region) /* special case for dma_mr lkey == 0 */ if (dma_region) { - /* should the dma_mr be relative to the pd? */ - if (!dev->dma_mr) { + struct qib_mregion *tmr; + + tmr = rcu_dereference(dev->dma_mr); + if (!tmr) { qib_get_mr(mr); - dev->dma_mr = mr; + rcu_assign_pointer(dev->dma_mr, mr); mr->lkey_published = 1; } goto success; @@ -93,7 +94,7 @@ int qib_alloc_lkey(struct qib_mregion *mr, int dma_region) rkt->gen++; } qib_get_mr(mr); - rkt->table[r] = mr; + rcu_assign_pointer(rkt->table[r], mr); mr->lkey_published = 1; success: spin_unlock_irqrestore(&rkt->lock, flags); @@ -120,33 +121,30 @@ void qib_free_lkey(struct qib_mregion *mr) spin_lock_irqsave(&rkt->lock, flags); if (!mr->lkey_published) goto out; - mr->lkey_published = 0; - - - spin_lock_irqsave(&dev->lk_table.lock, flags); - if (lkey == 0) { - if (dev->dma_mr && dev->dma_mr == mr) { - qib_put_mr(dev->dma_mr); - dev->dma_mr = NULL; - } - } else { + if (lkey == 0) + rcu_assign_pointer(dev->dma_mr, NULL); + else { r = lkey >> (32 - ib_qib_lkey_table_size); - qib_put_mr(dev->dma_mr); - rkt->table[r] = NULL; + rcu_assign_pointer(rkt->table[r], NULL); } + qib_put_mr(mr); + mr->lkey_published = 0; out: - spin_unlock_irqrestore(&dev->lk_table.lock, flags); + spin_unlock_irqrestore(&rkt->lock, flags); } /** * qib_lkey_ok - check IB SGE for validity and initialize * @rkt: table containing lkey to check SGE against + * @pd: protection domain * @isge: outgoing internal SGE * @sge: SGE to check * @acc: access flags * * Return 1 if valid and successful, otherwise returns 0. * + * increments the reference count upon success + * * Check the IB SGE for validity and initialize our internal version * of it. */ @@ -156,24 +154,25 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, struct qib_mregion *mr; unsigned n, m; size_t off; - unsigned long flags; /* * We use LKEY == zero for kernel virtual addresses * (see qib_get_dma_mr and qib_dma.c). */ - spin_lock_irqsave(&rkt->lock, flags); + rcu_read_lock(); if (sge->lkey == 0) { struct qib_ibdev *dev = to_idev(pd->ibpd.device); if (pd->user) goto bail; - if (!dev->dma_mr) + mr = rcu_dereference(dev->dma_mr); + if (!mr) + goto bail; + if (unlikely(!atomic_inc_not_zero(&mr->refcount))) goto bail; - qib_get_mr(dev->dma_mr); - spin_unlock_irqrestore(&rkt->lock, flags); + rcu_read_unlock(); - isge->mr = dev->dma_mr; + isge->mr = mr; isge->vaddr = (void *) sge->addr; isge->length = sge->length; isge->sge_length = sge->length; @@ -181,18 +180,18 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, isge->n = 0; goto ok; } - mr = rkt->table[(sge->lkey >> (32 - ib_qib_lkey_table_size))]; - if (unlikely(mr == NULL || mr->lkey != sge->lkey || - mr->pd != &pd->ibpd)) + mr = rcu_dereference( + rkt->table[(sge->lkey >> (32 - ib_qib_lkey_table_size))]); + if (unlikely(!mr || mr->lkey != sge->lkey || mr->pd != &pd->ibpd)) goto bail; off = sge->addr - mr->user_base; - if (unlikely(sge->addr < mr->user_base || - off + sge->length > mr->length || - (mr->access_flags & acc) != acc)) + if (unlikely(sge->addr < mr->iova || off + sge->length > mr->length || + (mr->access_flags & acc) == 0)) goto bail; - qib_get_mr(mr); - spin_unlock_irqrestore(&rkt->lock, flags); + if (unlikely(!atomic_inc_not_zero(&mr->refcount))) + goto bail; + rcu_read_unlock(); off += mr->offset; if (mr->page_shift) { @@ -228,20 +227,22 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, ok: return 1; bail: - spin_unlock_irqrestore(&rkt->lock, flags); + rcu_read_unlock(); return 0; } /** * qib_rkey_ok - check the IB virtual address, length, and RKEY - * @dev: infiniband device - * @ss: SGE state + * @qp: qp for validation + * @sge: SGE state * @len: length of data * @vaddr: virtual address to place data * @rkey: rkey to check * @acc: access flags * * Return 1 if successful, otherwise 0. + * + * increments the reference count upon success */ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, u32 len, u64 vaddr, u32 rkey, int acc) @@ -250,25 +251,26 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, struct qib_mregion *mr; unsigned n, m; size_t off; - unsigned long flags; /* * We use RKEY == zero for kernel virtual addresses * (see qib_get_dma_mr and qib_dma.c). */ - spin_lock_irqsave(&rkt->lock, flags); + rcu_read_lock(); if (rkey == 0) { struct qib_pd *pd = to_ipd(qp->ibqp.pd); struct qib_ibdev *dev = to_idev(pd->ibpd.device); if (pd->user) goto bail; - if (!dev->dma_mr) + mr = rcu_dereference(dev->dma_mr); + if (!mr) goto bail; - qib_get_mr(dev->dma_mr); - spin_unlock_irqrestore(&rkt->lock, flags); + if (unlikely(!atomic_inc_not_zero(&mr->refcount))) + goto bail; + rcu_read_unlock(); - sge->mr = dev->dma_mr; + sge->mr = mr; sge->vaddr = (void *) vaddr; sge->length = len; sge->sge_length = len; @@ -277,16 +279,18 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, goto ok; } - mr = rkt->table[(rkey >> (32 - ib_qib_lkey_table_size))]; - if (unlikely(mr == NULL || mr->lkey != rkey || qp->ibqp.pd != mr->pd)) + mr = rcu_dereference( + rkt->table[(rkey >> (32 - ib_qib_lkey_table_size))]); + if (unlikely(!mr || mr->lkey != rkey || qp->ibqp.pd != mr->pd)) goto bail; off = vaddr - mr->iova; if (unlikely(vaddr < mr->iova || off + len > mr->length || (mr->access_flags & acc) == 0)) goto bail; - qib_get_mr(mr); - spin_unlock_irqrestore(&rkt->lock, flags); + if (unlikely(!atomic_inc_not_zero(&mr->refcount))) + goto bail; + rcu_read_unlock(); off += mr->offset; if (mr->page_shift) { @@ -322,7 +326,7 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, ok: return 1; bail: - spin_unlock_irqrestore(&rkt->lock, flags); + rcu_read_unlock(); return 0; } diff --git a/drivers/infiniband/hw/qib/qib_mr.c b/drivers/infiniband/hw/qib/qib_mr.c index 6a2028a56e3d..e6687ded8210 100644 --- a/drivers/infiniband/hw/qib/qib_mr.c +++ b/drivers/infiniband/hw/qib/qib_mr.c @@ -527,3 +527,10 @@ int qib_dealloc_fmr(struct ib_fmr *ibfmr) out: return ret; } + +void mr_rcu_callback(struct rcu_head *list) +{ + struct qib_mregion *mr = container_of(list, struct qib_mregion, list); + + complete(&mr->comp); +} diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 76d7ce8a8c6e..59cdea345a82 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -2066,7 +2066,9 @@ int qib_register_ib_device(struct qib_devdata *dd) ret = -ENOMEM; goto err_lk; } - memset(dev->lk_table.table, 0, lk_tab_size); + RCU_INIT_POINTER(dev->dma_mr, NULL); + for (i = 0; i < dev->lk_table.max; i++) + RCU_INIT_POINTER(dev->lk_table.table[i], NULL); INIT_LIST_HEAD(&dev->pending_mmaps); spin_lock_init(&dev->pending_lock); dev->mmap_offset = PAGE_SIZE; diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 4a2277bc059e..85751fd74371 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -303,8 +303,9 @@ struct qib_mregion { u32 max_segs; /* number of qib_segs in all the arrays */ u32 mapsz; /* size of the map array */ u8 page_shift; /* 0 - non unform/non powerof2 sizes */ - u8 lkey_published; /* in global table */ + u8 lkey_published; /* in global table */ struct completion comp; /* complete when refcount goes to zero */ + struct rcu_head list; atomic_t refcount; struct qib_segarray *map[0]; /* the segments */ }; @@ -1022,10 +1023,12 @@ static inline void qib_get_mr(struct qib_mregion *mr) atomic_inc(&mr->refcount); } +void mr_rcu_callback(struct rcu_head *list); + static inline void qib_put_mr(struct qib_mregion *mr) { if (unlikely(atomic_dec_and_test(&mr->refcount))) - complete(&mr->comp); + call_rcu(&mr->list, mr_rcu_callback); } static inline void qib_put_ss(struct qib_sge_state *ss) -- GitLab From 068ce415bea9e2b96bde76dc1bf6e672a89903ee Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 8 Jul 2012 13:37:40 +0200 Subject: [PATCH 2280/5711] slub: remove invalid reference to list iterator variable If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. The patch replaces s->name by al->name, which is referenced nearby. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Signed-off-by: Pekka Enberg --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index f96d8bcec54f..79fe9c6b93cf 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5405,7 +5405,7 @@ static int __init slab_sysfs_init(void) err = sysfs_slab_alias(al->s, al->name); if (err) printk(KERN_ERR "SLUB: Unable to add boot slab alias" - " %s to sysfs\n", s->name); + " %s to sysfs\n", al->name); kfree(al); } -- GitLab From 039363f38bfe5f6281e9eae5e0518b11577d9d50 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 6 Jul 2012 15:25:10 -0500 Subject: [PATCH 2281/5711] mm, sl[aou]b: Extract common code for kmem_cache_create() Kmem_cache_create() does a variety of sanity checks but those vary depending on the allocator. Use the strictest tests and put them into a slab_common file. Make the tests conditional on CONFIG_DEBUG_VM. This patch has the effect of adding sanity checks for SLUB and SLOB under CONFIG_DEBUG_VM and removes the checks in SLAB for !CONFIG_DEBUG_VM. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slab.h | 4 +++ mm/Makefile | 3 +- mm/slab.c | 24 ++++++---------- mm/slab_common.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ mm/slob.c | 8 ++---- mm/slub.c | 11 +------ 6 files changed, 87 insertions(+), 31 deletions(-) create mode 100644 mm/slab_common.c diff --git a/include/linux/slab.h b/include/linux/slab.h index 0dd2dfa7beca..0cb7c7eb0416 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -130,6 +130,10 @@ int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); unsigned int kmem_cache_size(struct kmem_cache *); +/* Slab internal function */ +struct kmem_cache *__kmem_cache_create(const char *, size_t, size_t, + unsigned long, + void (*)(void *)); /* * Please use this macro to create slab caches. Simply specify the * name of the structure and maybe some flags that are listed above. diff --git a/mm/Makefile b/mm/Makefile index a156285ce88d..ae370783612d 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -16,7 +16,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ page_isolation.o mm_init.o mmu_context.o percpu.o \ - compaction.o $(mmu-y) + compaction.o slab_common.o $(mmu-y) + obj-y += init-mm.o ifdef CONFIG_NO_BOOTMEM diff --git a/mm/slab.c b/mm/slab.c index 105f188d14a3..10c821e492bf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1558,7 +1558,7 @@ void __init kmem_cache_init(void) * bug. */ - sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name, + sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name, sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, @@ -1566,7 +1566,7 @@ void __init kmem_cache_init(void) if (INDEX_AC != INDEX_L3) { sizes[INDEX_L3].cs_cachep = - kmem_cache_create(names[INDEX_L3].name, + __kmem_cache_create(names[INDEX_L3].name, sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, @@ -1584,14 +1584,14 @@ void __init kmem_cache_init(void) * allow tighter packing of the smaller caches. */ if (!sizes->cs_cachep) { - sizes->cs_cachep = kmem_cache_create(names->name, + sizes->cs_cachep = __kmem_cache_create(names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, NULL); } #ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = kmem_cache_create( + sizes->cs_dmacachep = __kmem_cache_create( names->name_dma, sizes->cs_size, ARCH_KMALLOC_MINALIGN, @@ -2220,7 +2220,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) } /** - * kmem_cache_create - Create a cache. + * __kmem_cache_create - Create a cache. * @name: A string which is used in /proc/slabinfo to identify this cache. * @size: The size of objects to be created in this cache. * @align: The required alignment for the objects. @@ -2247,7 +2247,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) * as davem. */ struct kmem_cache * -kmem_cache_create (const char *name, size_t size, size_t align, +__kmem_cache_create (const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { size_t left_over, slab_size, ralign; @@ -2388,7 +2388,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, /* Get cache's description obj. */ cachep = kmem_cache_zalloc(&cache_cache, gfp); if (!cachep) - goto oops; + return NULL; cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; cachep->object_size = size; @@ -2445,8 +2445,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, printk(KERN_ERR "kmem_cache_create: couldn't create cache %s.\n", name); kmem_cache_free(&cache_cache, cachep); - cachep = NULL; - goto oops; + return NULL; } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab), align); @@ -2504,8 +2503,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (setup_cpu_cache(cachep, gfp)) { __kmem_cache_destroy(cachep); - cachep = NULL; - goto oops; + return NULL; } if (flags & SLAB_DEBUG_OBJECTS) { @@ -2521,16 +2519,12 @@ kmem_cache_create (const char *name, size_t size, size_t align, /* cache setup completed, link it into the list */ list_add(&cachep->list, &cache_chain); oops: - if (!cachep && (flags & SLAB_PANIC)) - panic("kmem_cache_create(): failed to create slab `%s'\n", - name); if (slab_is_available()) { mutex_unlock(&cache_chain_mutex); put_online_cpus(); } return cachep; } -EXPORT_SYMBOL(kmem_cache_create); #if DEBUG static void check_irq_off(void) diff --git a/mm/slab_common.c b/mm/slab_common.c new file mode 100644 index 000000000000..80412beb67cc --- /dev/null +++ b/mm/slab_common.c @@ -0,0 +1,68 @@ +/* + * Slab allocator functions that are independent of the allocator strategy + * + * (C) 2012 Christoph Lameter + */ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * kmem_cache_create - Create a cache. + * @name: A string which is used in /proc/slabinfo to identify this cache. + * @size: The size of objects to be created in this cache. + * @align: The required alignment for the objects. + * @flags: SLAB flags + * @ctor: A constructor for the objects. + * + * Returns a ptr to the cache on success, NULL on failure. + * Cannot be called within a interrupt, but can be interrupted. + * The @ctor is run when new pages are allocated by the cache. + * + * The flags are + * + * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) + * to catch references to uninitialised memory. + * + * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check + * for buffer overruns. + * + * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware + * cacheline. This can be beneficial if you're counting cycles as closely + * as davem. + */ + +struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, + unsigned long flags, void (*ctor)(void *)) +{ + struct kmem_cache *s = NULL; + +#ifdef CONFIG_DEBUG_VM + if (!name || in_interrupt() || size < sizeof(void *) || + size > KMALLOC_MAX_SIZE) { + printk(KERN_ERR "kmem_cache_create(%s) integrity check" + " failed\n", name); + goto out; + } +#endif + + s = __kmem_cache_create(name, size, align, flags, ctor); + +#ifdef CONFIG_DEBUG_VM +out: +#endif + if (!s && (flags & SLAB_PANIC)) + panic("kmem_cache_create: Failed to create slab '%s'\n", name); + + return s; +} +EXPORT_SYMBOL(kmem_cache_create); diff --git a/mm/slob.c b/mm/slob.c index 95d1c7dd88e0..d63923d549ec 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -506,7 +506,7 @@ size_t ksize(const void *block) } EXPORT_SYMBOL(ksize); -struct kmem_cache *kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *c; @@ -529,13 +529,11 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, c->align = ARCH_SLAB_MINALIGN; if (c->align < align) c->align = align; - } else if (flags & SLAB_PANIC) - panic("Cannot create slab cache %s\n", name); - kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + } return c; } -EXPORT_SYMBOL(kmem_cache_create); void kmem_cache_destroy(struct kmem_cache *c) { diff --git a/mm/slub.c b/mm/slub.c index 79fe9c6b93cf..6551cc9a51f8 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3920,15 +3920,12 @@ static struct kmem_cache *find_mergeable(size_t size, return NULL; } -struct kmem_cache *kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s; char *n; - if (WARN_ON(!name)) - return NULL; - down_write(&slub_lock); s = find_mergeable(size, align, flags, name, ctor); if (s) { @@ -3972,14 +3969,8 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, kfree(n); err: up_write(&slub_lock); - - if (flags & SLAB_PANIC) - panic("Cannot create slabcache %s\n", name); - else - s = NULL; return s; } -EXPORT_SYMBOL(kmem_cache_create); #ifdef CONFIG_SMP /* -- GitLab From 97d06609158e61f6bdf538c4a6788e2de492236f Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 6 Jul 2012 15:25:11 -0500 Subject: [PATCH 2282/5711] mm, sl[aou]b: Common definition for boot state of the slab allocators All allocators have some sort of support for the bootstrap status. Setup a common definition for the boot states and make all slab allocators use that definition. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slab.h | 4 ---- mm/slab.c | 45 ++++++++++++++------------------------------ mm/slab.h | 29 ++++++++++++++++++++++++++++ mm/slab_common.c | 9 +++++++++ mm/slob.c | 14 +++++--------- mm/slub.c | 21 +++++---------------- 6 files changed, 62 insertions(+), 60 deletions(-) create mode 100644 mm/slab.h diff --git a/include/linux/slab.h b/include/linux/slab.h index 0cb7c7eb0416..0dd2dfa7beca 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -130,10 +130,6 @@ int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); unsigned int kmem_cache_size(struct kmem_cache *); -/* Slab internal function */ -struct kmem_cache *__kmem_cache_create(const char *, size_t, size_t, - unsigned long, - void (*)(void *)); /* * Please use this macro to create slab caches. Simply specify the * name of the structure and maybe some flags that are listed above. diff --git a/mm/slab.c b/mm/slab.c index 10c821e492bf..59a466b85b0f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -87,6 +87,7 @@ */ #include +#include "slab.h" #include #include #include @@ -565,27 +566,6 @@ static struct kmem_cache cache_cache = { #define BAD_ALIEN_MAGIC 0x01020304ul -/* - * chicken and egg problem: delay the per-cpu array allocation - * until the general caches are up. - */ -static enum { - NONE, - PARTIAL_AC, - PARTIAL_L3, - EARLY, - LATE, - FULL -} g_cpucache_up; - -/* - * used by boot code to determine if it can use slab based allocator - */ -int slab_is_available(void) -{ - return g_cpucache_up >= EARLY; -} - #ifdef CONFIG_LOCKDEP /* @@ -651,7 +631,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up < LATE) + if (slab_state < UP) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -1649,14 +1629,14 @@ void __init kmem_cache_init(void) } } - g_cpucache_up = EARLY; + slab_state = UP; } void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; - g_cpucache_up = LATE; + slab_state = UP; /* Annotate slab for lockdep -- annotate the malloc caches */ init_lock_keys(); @@ -1668,6 +1648,9 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&cache_chain_mutex); + /* Done! */ + slab_state = FULL; + /* * Register a cpu startup notifier callback that initializes * cpu_cache_get for all new cpus @@ -1699,7 +1682,7 @@ static int __init cpucache_init(void) start_cpu_timer(cpu); /* Done! */ - g_cpucache_up = FULL; + slab_state = FULL; return 0; } __initcall(cpucache_init); @@ -2167,10 +2150,10 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) { - if (g_cpucache_up >= LATE) + if (slab_state >= FULL) return enable_cpucache(cachep, gfp); - if (g_cpucache_up == NONE) { + if (slab_state == DOWN) { /* * Note: the first kmem_cache_create must create the cache * that's used by kmalloc(24), otherwise the creation of @@ -2185,16 +2168,16 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) */ set_up_list3s(cachep, SIZE_AC); if (INDEX_AC == INDEX_L3) - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; else - g_cpucache_up = PARTIAL_AC; + slab_state = PARTIAL_ARRAYCACHE; } else { cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init), gfp); - if (g_cpucache_up == PARTIAL_AC) { + if (slab_state == PARTIAL_ARRAYCACHE) { set_up_list3s(cachep, SIZE_L3); - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; } else { int node; for_each_online_node(node) { diff --git a/mm/slab.h b/mm/slab.h new file mode 100644 index 000000000000..f9a9815cdc82 --- /dev/null +++ b/mm/slab.h @@ -0,0 +1,29 @@ +#ifndef MM_SLAB_H +#define MM_SLAB_H +/* + * Internal slab definitions + */ + +/* + * State of the slab allocator. + * + * This is used to describe the states of the allocator during bootup. + * Allocators use this to gradually bootstrap themselves. Most allocators + * have the problem that the structures used for managing slab caches are + * allocated from slab caches themselves. + */ +enum slab_state { + DOWN, /* No slab functionality yet */ + PARTIAL, /* SLUB: kmem_cache_node available */ + PARTIAL_ARRAYCACHE, /* SLAB: kmalloc size for arraycache available */ + PARTIAL_L3, /* SLAB: kmalloc size for l3 struct available */ + UP, /* Slab caches usable but not all extras yet */ + FULL /* Everything is working */ +}; + +extern enum slab_state slab_state; + +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)); + +#endif diff --git a/mm/slab_common.c b/mm/slab_common.c index 80412beb67cc..ca1aaf69a1f5 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -16,6 +16,10 @@ #include #include +#include "slab.h" + +enum slab_state slab_state; + /* * kmem_cache_create - Create a cache. * @name: A string which is used in /proc/slabinfo to identify this cache. @@ -66,3 +70,8 @@ out: return s; } EXPORT_SYMBOL(kmem_cache_create); + +int slab_is_available(void) +{ + return slab_state >= UP; +} diff --git a/mm/slob.c b/mm/slob.c index d63923d549ec..0111e0dece93 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -59,6 +59,8 @@ #include #include +#include "slab.h" + #include #include /* struct reclaim_state */ #include @@ -531,6 +533,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, c->align = align; kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + c->refcount = 1; } return c; } @@ -616,19 +619,12 @@ int kmem_cache_shrink(struct kmem_cache *d) } EXPORT_SYMBOL(kmem_cache_shrink); -static unsigned int slob_ready __read_mostly; - -int slab_is_available(void) -{ - return slob_ready; -} - void __init kmem_cache_init(void) { - slob_ready = 1; + slab_state = UP; } void __init kmem_cache_init_late(void) { - /* Nothing to do */ + slab_state = FULL; } diff --git a/mm/slub.c b/mm/slub.c index 6551cc9a51f8..4c385164d9f7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -16,6 +16,7 @@ #include #include #include +#include "slab.h" #include #include #include @@ -182,13 +183,6 @@ static int kmem_size = sizeof(struct kmem_cache); static struct notifier_block slab_notifier; #endif -static enum { - DOWN, /* No slab functionality available */ - PARTIAL, /* Kmem_cache_node works */ - UP, /* Everything works but does not show up in sysfs */ - SYSFS /* Sysfs up */ -} slab_state = DOWN; - /* A list of all slab caches on the system */ static DECLARE_RWSEM(slub_lock); static LIST_HEAD(slab_caches); @@ -237,11 +231,6 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si) * Core slab cache functions *******************************************************************/ -int slab_is_available(void) -{ - return slab_state >= UP; -} - static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node) { return s->node[node]; @@ -5274,7 +5263,7 @@ static int sysfs_slab_add(struct kmem_cache *s) const char *name; int unmergeable; - if (slab_state < SYSFS) + if (slab_state < FULL) /* Defer until later */ return 0; @@ -5319,7 +5308,7 @@ static int sysfs_slab_add(struct kmem_cache *s) static void sysfs_slab_remove(struct kmem_cache *s) { - if (slab_state < SYSFS) + if (slab_state < FULL) /* * Sysfs has not been setup yet so no need to remove the * cache from sysfs. @@ -5347,7 +5336,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; - if (slab_state == SYSFS) { + if (slab_state == FULL) { /* * If we have a leftover link then remove it. */ @@ -5380,7 +5369,7 @@ static int __init slab_sysfs_init(void) return -ENOSYS; } - slab_state = SYSFS; + slab_state = FULL; list_for_each_entry(s, &slab_caches, list) { err = sysfs_slab_add(s); -- GitLab From 18004c5d4084d965aa1396392706b8688306427a Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 6 Jul 2012 15:25:12 -0500 Subject: [PATCH 2283/5711] mm, sl[aou]b: Use a common mutex definition Use the mutex definition from SLAB and make it the common way to take a sleeping lock. This has the effect of using a mutex instead of a rw semaphore for SLUB. SLOB gains the use of a mutex for kmem_cache_create serialization. Not needed now but SLOB may acquire some more features later (like slabinfo / sysfs support) through the expansion of the common code that will need this. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slab.c | 108 ++++++++++++++++++++++------------------------- mm/slab.h | 4 ++ mm/slab_common.c | 2 + mm/slub.c | 54 +++++++++++------------- 4 files changed, 82 insertions(+), 86 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 59a466b85b0f..fd7dac67c26e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -68,7 +68,7 @@ * Further notes from the original documentation: * * 11 April '97. Started multi-threading - markhe - * The global cache-chain is protected by the mutex 'cache_chain_mutex'. + * The global cache-chain is protected by the mutex 'slab_mutex'. * The sem is only needed when accessing/extending the cache-chain, which * can never happen inside an interrupt (kmem_cache_create(), * kmem_cache_shrink() and kmem_cache_reap()). @@ -671,12 +671,6 @@ static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep) } #endif -/* - * Guard access to the cache-chain. - */ -static DEFINE_MUTEX(cache_chain_mutex); -static struct list_head cache_chain; - static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -1100,7 +1094,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) * When hotplugging memory or a cpu, existing nodelists are not replaced if * already in use. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int init_cache_nodelists_node(int node) { @@ -1108,7 +1102,7 @@ static int init_cache_nodelists_node(int node) struct kmem_list3 *l3; const int memsize = sizeof(struct kmem_list3); - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { /* * Set up the size64 kmemlist for cpu before we can * begin anything. Make sure some other cpu on this @@ -1124,7 +1118,7 @@ static int init_cache_nodelists_node(int node) /* * The l3s don't come and go as CPUs come and - * go. cache_chain_mutex is sufficient + * go. slab_mutex is sufficient * protection here. */ cachep->nodelists[node] = l3; @@ -1146,7 +1140,7 @@ static void __cpuinit cpuup_canceled(long cpu) int node = cpu_to_mem(cpu); const struct cpumask *mask = cpumask_of_node(node); - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared; struct array_cache **alien; @@ -1196,7 +1190,7 @@ free_array_cache: * the respective cache's slabs, now we can go ahead and * shrink each nodelist to its limit. */ - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { l3 = cachep->nodelists[node]; if (!l3) continue; @@ -1225,7 +1219,7 @@ static int __cpuinit cpuup_prepare(long cpu) * Now we can go ahead with allocating the shared arrays and * array caches */ - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared = NULL; struct array_cache **alien = NULL; @@ -1293,9 +1287,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); err = cpuup_prepare(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: @@ -1305,7 +1299,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: /* - * Shutdown cache reaper. Note that the cache_chain_mutex is + * Shutdown cache reaper. Note that the slab_mutex is * held so that if cache_reap() is invoked it cannot do * anything expensive but will only modify reap_work * and reschedule the timer. @@ -1332,9 +1326,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, #endif case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); cpuup_canceled(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; } return notifier_from_errno(err); @@ -1350,14 +1344,14 @@ static struct notifier_block __cpuinitdata cpucache_notifier = { * Returns -EBUSY if all objects cannot be drained so that the node is not * removed. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int __meminit drain_cache_nodelists_node(int node) { struct kmem_cache *cachep; int ret = 0; - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { struct kmem_list3 *l3; l3 = cachep->nodelists[node]; @@ -1388,14 +1382,14 @@ static int __meminit slab_memory_callback(struct notifier_block *self, switch (action) { case MEM_GOING_ONLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = init_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_GOING_OFFLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = drain_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_ONLINE: case MEM_OFFLINE: @@ -1499,8 +1493,8 @@ void __init kmem_cache_init(void) node = numa_mem_id(); /* 1) create the cache_cache */ - INIT_LIST_HEAD(&cache_chain); - list_add(&cache_cache.list, &cache_chain); + INIT_LIST_HEAD(&slab_caches); + list_add(&cache_cache.list, &slab_caches); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; @@ -1642,11 +1636,11 @@ void __init kmem_cache_init_late(void) init_lock_keys(); /* 6) resize the head arrays to their final sizes */ - mutex_lock(&cache_chain_mutex); - list_for_each_entry(cachep, &cache_chain, list) + mutex_lock(&slab_mutex); + list_for_each_entry(cachep, &slab_caches, list) if (enable_cpucache(cachep, GFP_NOWAIT)) BUG(); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); /* Done! */ slab_state = FULL; @@ -2253,10 +2247,10 @@ __kmem_cache_create (const char *name, size_t size, size_t align, */ if (slab_is_available()) { get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); } - list_for_each_entry(pc, &cache_chain, list) { + list_for_each_entry(pc, &slab_caches, list) { char tmp; int res; @@ -2500,10 +2494,10 @@ __kmem_cache_create (const char *name, size_t size, size_t align, } /* cache setup completed, link it into the list */ - list_add(&cachep->list, &cache_chain); + list_add(&cachep->list, &slab_caches); oops: if (slab_is_available()) { - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); } return cachep; @@ -2622,7 +2616,7 @@ out: return nr_freed; } -/* Called with cache_chain_mutex held to protect against cpu hotplug */ +/* Called with slab_mutex held to protect against cpu hotplug */ static int __cache_shrink(struct kmem_cache *cachep) { int ret = 0, i = 0; @@ -2657,9 +2651,9 @@ int kmem_cache_shrink(struct kmem_cache *cachep) BUG_ON(!cachep || in_interrupt()); get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = __cache_shrink(cachep); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); return ret; } @@ -2687,15 +2681,15 @@ void kmem_cache_destroy(struct kmem_cache *cachep) /* Find the cache in the chain of caches. */ get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); /* * the chain is never empty, cache_cache is never destroyed */ list_del(&cachep->list); if (__cache_shrink(cachep)) { slab_error(cachep, "Can't free all objects"); - list_add(&cachep->list, &cache_chain); - mutex_unlock(&cache_chain_mutex); + list_add(&cachep->list, &slab_caches); + mutex_unlock(&slab_mutex); put_online_cpus(); return; } @@ -2704,7 +2698,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep) rcu_barrier(); __kmem_cache_destroy(cachep); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); } EXPORT_SYMBOL(kmem_cache_destroy); @@ -4017,7 +4011,7 @@ static void do_ccupdate_local(void *info) new->new[smp_processor_id()] = old; } -/* Always called with the cache_chain_mutex held */ +/* Always called with the slab_mutex held */ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared, gfp_t gfp) { @@ -4061,7 +4055,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, return alloc_kmemlist(cachep, gfp); } -/* Called with cache_chain_mutex held always */ +/* Called with slab_mutex held always */ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) { int err; @@ -4163,11 +4157,11 @@ static void cache_reap(struct work_struct *w) int node = numa_mem_id(); struct delayed_work *work = to_delayed_work(w); - if (!mutex_trylock(&cache_chain_mutex)) + if (!mutex_trylock(&slab_mutex)) /* Give up. Setup the next iteration. */ goto out; - list_for_each_entry(searchp, &cache_chain, list) { + list_for_each_entry(searchp, &slab_caches, list) { check_irq_on(); /* @@ -4205,7 +4199,7 @@ next: cond_resched(); } check_irq_on(); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); next_reap_node(); out: /* Set up the next iteration */ @@ -4241,21 +4235,21 @@ static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); - return seq_list_start(&cache_chain, *pos); + return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { - return seq_list_next(p, &cache_chain, pos); + return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) @@ -4406,9 +4400,9 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, return -EINVAL; /* Find the cache in the chain of caches. */ - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); res = -EINVAL; - list_for_each_entry(cachep, &cache_chain, list) { + list_for_each_entry(cachep, &slab_caches, list) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4421,7 +4415,7 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, break; } } - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); if (res >= 0) res = count; return res; @@ -4444,8 +4438,8 @@ static const struct file_operations proc_slabinfo_operations = { static void *leaks_start(struct seq_file *m, loff_t *pos) { - mutex_lock(&cache_chain_mutex); - return seq_list_start(&cache_chain, *pos); + mutex_lock(&slab_mutex); + return seq_list_start(&slab_caches, *pos); } static inline int add_caller(unsigned long *n, unsigned long v) @@ -4544,17 +4538,17 @@ static int leaks_show(struct seq_file *m, void *p) name = cachep->name; if (n[0] == n[1]) { /* Increase the buffer size */ - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL); if (!m->private) { /* Too bad, we are really out */ m->private = n; - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); return -ENOMEM; } *(unsigned long *)m->private = n[0] * 2; kfree(n); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); /* Now make sure this entry will be retried */ m->count = m->size; return 0; diff --git a/mm/slab.h b/mm/slab.h index f9a9815cdc82..db7848caaa25 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -23,6 +23,10 @@ enum slab_state { extern enum slab_state slab_state; +/* The slab cache mutex protects the management structures during changes */ +extern struct mutex slab_mutex; +extern struct list_head slab_caches; + struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)); diff --git a/mm/slab_common.c b/mm/slab_common.c index ca1aaf69a1f5..50e1ff10bff9 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -19,6 +19,8 @@ #include "slab.h" enum slab_state slab_state; +LIST_HEAD(slab_caches); +DEFINE_MUTEX(slab_mutex); /* * kmem_cache_create - Create a cache. diff --git a/mm/slub.c b/mm/slub.c index 4c385164d9f7..8c4fd37541d7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -36,13 +36,13 @@ /* * Lock order: - * 1. slub_lock (Global Semaphore) + * 1. slab_mutex (Global Mutex) * 2. node->list_lock * 3. slab_lock(page) (Only on some arches and for debugging) * - * slub_lock + * slab_mutex * - * The role of the slub_lock is to protect the list of all the slabs + * The role of the slab_mutex is to protect the list of all the slabs * and to synchronize major metadata changes to slab cache structures. * * The slab_lock is only used for debugging and on arches that do not @@ -183,10 +183,6 @@ static int kmem_size = sizeof(struct kmem_cache); static struct notifier_block slab_notifier; #endif -/* A list of all slab caches on the system */ -static DECLARE_RWSEM(slub_lock); -static LIST_HEAD(slab_caches); - /* * Tracking user of a slab. */ @@ -3177,11 +3173,11 @@ static inline int kmem_cache_close(struct kmem_cache *s) */ void kmem_cache_destroy(struct kmem_cache *s) { - down_write(&slub_lock); + mutex_lock(&slab_mutex); s->refcount--; if (!s->refcount) { list_del(&s->list); - up_write(&slub_lock); + mutex_unlock(&slab_mutex); if (kmem_cache_close(s)) { printk(KERN_ERR "SLUB %s: %s called for cache that " "still has objects.\n", s->name, __func__); @@ -3191,7 +3187,7 @@ void kmem_cache_destroy(struct kmem_cache *s) rcu_barrier(); sysfs_slab_remove(s); } else - up_write(&slub_lock); + mutex_unlock(&slab_mutex); } EXPORT_SYMBOL(kmem_cache_destroy); @@ -3253,7 +3249,7 @@ static struct kmem_cache *__init create_kmalloc_cache(const char *name, /* * This function is called with IRQs disabled during early-boot on - * single CPU so there's no need to take slub_lock here. + * single CPU so there's no need to take slab_mutex here. */ if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, flags, NULL)) @@ -3538,10 +3534,10 @@ static int slab_mem_going_offline_callback(void *arg) { struct kmem_cache *s; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) kmem_cache_shrink(s); - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return 0; } @@ -3562,7 +3558,7 @@ static void slab_mem_offline_callback(void *arg) if (offline_node < 0) return; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { n = get_node(s, offline_node); if (n) { @@ -3578,7 +3574,7 @@ static void slab_mem_offline_callback(void *arg) kmem_cache_free(kmem_cache_node, n); } } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); } static int slab_mem_going_online_callback(void *arg) @@ -3601,7 +3597,7 @@ static int slab_mem_going_online_callback(void *arg) * allocate a kmem_cache_node structure in order to bring the node * online. */ - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { /* * XXX: kmem_cache_alloc_node will fallback to other nodes @@ -3617,7 +3613,7 @@ static int slab_mem_going_online_callback(void *arg) s->node[nid] = n; } out: - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return ret; } @@ -3915,7 +3911,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, struct kmem_cache *s; char *n; - down_write(&slub_lock); + mutex_lock(&slab_mutex); s = find_mergeable(size, align, flags, name, ctor); if (s) { s->refcount++; @@ -3930,7 +3926,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, s->refcount--; goto err; } - up_write(&slub_lock); + mutex_unlock(&slab_mutex); return s; } @@ -3943,9 +3939,9 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, if (kmem_cache_open(s, n, size, align, flags, ctor)) { list_add(&s->list, &slab_caches); - up_write(&slub_lock); + mutex_unlock(&slab_mutex); if (sysfs_slab_add(s)) { - down_write(&slub_lock); + mutex_lock(&slab_mutex); list_del(&s->list); kfree(n); kfree(s); @@ -3957,7 +3953,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, } kfree(n); err: - up_write(&slub_lock); + mutex_unlock(&slab_mutex); return s; } @@ -3978,13 +3974,13 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { local_irq_save(flags); __flush_cpu_slab(s, cpu); local_irq_restore(flags); } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); break; default: break; @@ -5360,11 +5356,11 @@ static int __init slab_sysfs_init(void) struct kmem_cache *s; int err; - down_write(&slub_lock); + mutex_lock(&slab_mutex); slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); if (!slab_kset) { - up_write(&slub_lock); + mutex_unlock(&slab_mutex); printk(KERN_ERR "Cannot register slab subsystem.\n"); return -ENOSYS; } @@ -5389,7 +5385,7 @@ static int __init slab_sysfs_init(void) kfree(al); } - up_write(&slub_lock); + mutex_unlock(&slab_mutex); resiliency_test(); return 0; } @@ -5415,7 +5411,7 @@ static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; - down_read(&slub_lock); + mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); @@ -5429,7 +5425,7 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos) static void s_stop(struct seq_file *m, void *p) { - up_read(&slub_lock); + mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) -- GitLab From 20cea9683ecc6dd75a80c0dd02dc69c64e95be75 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 6 Jul 2012 15:25:13 -0500 Subject: [PATCH 2284/5711] mm, sl[aou]b: Move kmem_cache_create mutex handling to common code Move the mutex handling into the common kmem_cache_create() function. Then we can also move more checks out of SLAB's kmem_cache_create() into the common code. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slab.c | 52 +----------------------------------------------- mm/slab_common.c | 41 +++++++++++++++++++++++++++++++++++++- mm/slub.c | 28 ++++++++++++-------------- 3 files changed, 54 insertions(+), 67 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index fd7dac67c26e..1fcf3ac94b6c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2228,55 +2228,10 @@ __kmem_cache_create (const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { size_t left_over, slab_size, ralign; - struct kmem_cache *cachep = NULL, *pc; + struct kmem_cache *cachep = NULL; gfp_t gfp; - /* - * Sanity checks... these are all serious usage bugs. - */ - if (!name || in_interrupt() || (size < BYTES_PER_WORD) || - size > KMALLOC_MAX_SIZE) { - printk(KERN_ERR "%s: Early error in slab %s\n", __func__, - name); - BUG(); - } - - /* - * We use cache_chain_mutex to ensure a consistent view of - * cpu_online_mask as well. Please see cpuup_callback - */ - if (slab_is_available()) { - get_online_cpus(); - mutex_lock(&slab_mutex); - } - - list_for_each_entry(pc, &slab_caches, list) { - char tmp; - int res; - - /* - * This happens when the module gets unloaded and doesn't - * destroy its slab cache and no-one else reuses the vmalloc - * area of the module. Print a warning. - */ - res = probe_kernel_address(pc->name, tmp); - if (res) { - printk(KERN_ERR - "SLAB: cache with size %d has lost its name\n", - pc->size); - continue; - } - - if (!strcmp(pc->name, name)) { - printk(KERN_ERR - "kmem_cache_create: duplicate cache %s\n", name); - dump_stack(); - goto oops; - } - } - #if DEBUG - WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #if FORCED_DEBUG /* * Enable redzoning and last user accounting, except for caches with @@ -2495,11 +2450,6 @@ __kmem_cache_create (const char *name, size_t size, size_t align, /* cache setup completed, link it into the list */ list_add(&cachep->list, &slab_caches); -oops: - if (slab_is_available()) { - mutex_unlock(&slab_mutex); - put_online_cpus(); - } return cachep; } diff --git a/mm/slab_common.c b/mm/slab_common.c index 50e1ff10bff9..12637cee1f95 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -11,7 +11,8 @@ #include #include #include - +#include +#include #include #include #include @@ -61,8 +62,46 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align } #endif + get_online_cpus(); + mutex_lock(&slab_mutex); + +#ifdef CONFIG_DEBUG_VM + list_for_each_entry(s, &slab_caches, list) { + char tmp; + int res; + + /* + * This happens when the module gets unloaded and doesn't + * destroy its slab cache and no-one else reuses the vmalloc + * area of the module. Print a warning. + */ + res = probe_kernel_address(s->name, tmp); + if (res) { + printk(KERN_ERR + "Slab cache with size %d has lost its name\n", + s->object_size); + continue; + } + + if (!strcmp(s->name, name)) { + printk(KERN_ERR "kmem_cache_create(%s): Cache name" + " already exists.\n", + name); + dump_stack(); + s = NULL; + goto oops; + } + } + + WARN_ON(strchr(name, ' ')); /* It confuses parsers */ +#endif + s = __kmem_cache_create(name, size, align, flags, ctor); +oops: + mutex_unlock(&slab_mutex); + put_online_cpus(); + #ifdef CONFIG_DEBUG_VM out: #endif diff --git a/mm/slub.c b/mm/slub.c index 8c4fd37541d7..0e0504ed6ff1 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3911,7 +3911,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, struct kmem_cache *s; char *n; - mutex_lock(&slab_mutex); s = find_mergeable(size, align, flags, name, ctor); if (s) { s->refcount++; @@ -3924,37 +3923,36 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, if (sysfs_slab_alias(s, name)) { s->refcount--; - goto err; + return NULL; } - mutex_unlock(&slab_mutex); return s; } n = kstrdup(name, GFP_KERNEL); if (!n) - goto err; + return NULL; s = kmalloc(kmem_size, GFP_KERNEL); if (s) { if (kmem_cache_open(s, n, size, align, flags, ctor)) { + int r; + list_add(&s->list, &slab_caches); mutex_unlock(&slab_mutex); - if (sysfs_slab_add(s)) { - mutex_lock(&slab_mutex); - list_del(&s->list); - kfree(n); - kfree(s); - goto err; - } - return s; + r = sysfs_slab_add(s); + mutex_lock(&slab_mutex); + + if (!r) + return s; + + list_del(&s->list); + kmem_cache_close(s); } kfree(s); } kfree(n); -err: - mutex_unlock(&slab_mutex); - return s; + return NULL; } #ifdef CONFIG_SMP -- GitLab From af97bace2cca58ee7c94bf4d31e820f29688d7a5 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Mon, 11 Jun 2012 22:56:26 +0200 Subject: [PATCH 2285/5711] i2c-nomadik: move header to The header and driver are only used by arm/mach-u8500 (and potentially arm/mach-nomadik), but the STA2X11 I/O Hub exports on PCIe a number of devices, including i2c-nomadik. This patch allows compilation of the driver under x86. Signed-off-by: Alessandro Rubini Acked-by: Giancarlo Asnaghi Tested-by: Linus Walleij Signed-off-by: Wolfram Sang --- arch/arm/mach-ux500/board-mop500.c | 2 +- arch/arm/mach-ux500/devices-common.h | 2 +- drivers/i2c/busses/i2c-nomadik.c | 3 +-- .../plat/i2c.h => include/linux/platform_data/i2c-nomadik.h | 6 +++--- 4 files changed, 6 insertions(+), 7 deletions(-) rename arch/arm/plat-nomadik/include/plat/i2c.h => include/linux/platform_data/i2c-nomadik.h (91%) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 1509a3cb5833..f9a964836d3a 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include -#include #include #include diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 6e4706560266..23cf734b5384 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include struct spi_master_cntlr; diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5267ab93d550..752f1fda371f 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -23,8 +23,7 @@ #include #include #include - -#include +#include #define DRIVER_NAME "nmk-i2c" diff --git a/arch/arm/plat-nomadik/include/plat/i2c.h b/include/linux/platform_data/i2c-nomadik.h similarity index 91% rename from arch/arm/plat-nomadik/include/plat/i2c.h rename to include/linux/platform_data/i2c-nomadik.h index 8ba70ffc31ec..c2303c3e4803 100644 --- a/arch/arm/plat-nomadik/include/plat/i2c.h +++ b/include/linux/platform_data/i2c-nomadik.h @@ -5,8 +5,8 @@ * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. */ -#ifndef __PLAT_I2C_H -#define __PLAT_I2C_H +#ifndef __PDATA_I2C_NOMADIK_H +#define __PDATA_I2C_NOMADIK_H enum i2c_freq_mode { I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ @@ -36,4 +36,4 @@ struct nmk_i2c_controller { enum i2c_freq_mode sm; }; -#endif /* __PLAT_I2C_H */ +#endif /* __PDATA_I2C_NOMADIK_H */ -- GitLab From 235602146ec9c1882edf1ccc68389c1176be8198 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Mon, 11 Jun 2012 22:56:38 +0200 Subject: [PATCH 2286/5711] i2c-nomadik: turn the platform driver to an amba driver The i2c-nomadik gateware is really a PrimeCell APB device. By hosting the driver under the amba bus we can access it more easily, for example using the generic pci-amba driver. The patch also fixes the mach-ux500 users, so they register an amba device instead than a platform device. Signed-off-by: Alessandro Rubini Acked-by: Giancarlo Asnaghi Tested-by: Linus Walleij Signed-off-by: Wolfram Sang --- arch/arm/mach-ux500/devices-common.h | 22 +---- drivers/i2c/busses/i2c-nomadik.c | 142 ++++++++++++++------------- 2 files changed, 78 insertions(+), 86 deletions(-) diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 23cf734b5384..ecdd8386cffb 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -56,27 +56,15 @@ dbx500_add_uart(struct device *parent, const char *name, resource_size_t base, struct nmk_i2c_controller; -static inline struct platform_device * +static inline struct amba_device * dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, struct nmk_i2c_controller *data) { - struct resource res[] = { - DEFINE_RES_MEM(base, SZ_4K), - DEFINE_RES_IRQ(irq), - }; + /* Conjure a name similar to what the platform device used to have */ + char name[16]; - struct platform_device_info pdevinfo = { - .parent = parent, - .name = "nmk-i2c", - .id = id, - .res = res, - .num_res = ARRAY_SIZE(res), - .data = data, - .size_data = sizeof(*data), - .dma_mask = DMA_BIT_MASK(32), - }; - - return platform_device_register_full(&pdevinfo); + snprintf(name, sizeof(name), "nmk-i2c.%d", id); + return amba_apb_device_add(parent, name, base, SZ_4K, irq, 0, data, 0); } static inline struct amba_device * diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 752f1fda371f..6db453fe68e6 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -14,7 +14,8 @@ */ #include #include -#include +#include +#include #include #include #include @@ -135,7 +136,7 @@ struct i2c_nmk_client { /** * struct nmk_i2c_dev - private data structure of the controller. - * @pdev: parent platform device. + * @adev: parent amba device. * @adap: corresponding I2C adapter. * @irq: interrupt line for the controller. * @virtbase: virtual io memory area. @@ -149,7 +150,7 @@ struct i2c_nmk_client { * @busy: Busy doing transfer. */ struct nmk_i2c_dev { - struct platform_device *pdev; + struct amba_device *adev; struct i2c_adapter adap; int irq; void __iomem *virtbase; @@ -216,7 +217,7 @@ static int flush_i2c_fifo(struct nmk_i2c_dev *dev) } } - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "flushing operation timed out giving up after %d attempts", LOOP_ATTEMPTS); @@ -363,7 +364,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) * and high speed (up to 3.4 Mb/s) */ if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "do not support this mode defaulting to std. mode\n"); brcr2 = i2c_clk/(100000 * 2) & 0xffff; writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); @@ -422,7 +423,7 @@ static int read_i2c(struct nmk_i2c_dev *dev) &dev->xfer_complete, dev->adap.timeout); if (timeout < 0) { - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "wait_for_completion_timeout " "returned %d waiting for event\n", timeout); status = timeout; @@ -430,7 +431,7 @@ static int read_i2c(struct nmk_i2c_dev *dev) if (timeout == 0) { /* Controller timed out */ - dev_err(&dev->pdev->dev, "read from slave 0x%x timed out\n", + dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n", dev->cli.slave_adr); status = -ETIMEDOUT; } @@ -509,7 +510,7 @@ static int write_i2c(struct nmk_i2c_dev *dev) &dev->xfer_complete, dev->adap.timeout); if (timeout < 0) { - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "wait_for_completion_timeout " "returned %d waiting for event\n", timeout); status = timeout; @@ -517,7 +518,7 @@ static int write_i2c(struct nmk_i2c_dev *dev) if (timeout == 0) { /* Controller timed out */ - dev_err(&dev->pdev->dev, "write to slave 0x%x timed out\n", + dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n", dev->cli.slave_adr); status = -ETIMEDOUT; } @@ -556,7 +557,7 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) if (((i2c_sr >> 2) & 0x3) == 0x3) { /* get the abort cause */ cause = (i2c_sr >> 4) & 0x7; - dev_err(&dev->pdev->dev, "%s\n", + dev_err(&dev->adev->dev, "%s\n", cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" : abort_causes[cause]); @@ -629,7 +630,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, if (dev->regulator) regulator_enable(dev->regulator); - pm_runtime_get_sync(&dev->pdev->dev); + pm_runtime_get_sync(&dev->adev->dev); clk_enable(dev->clk); @@ -644,7 +645,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, for (i = 0; i < num_msgs; i++) { if (unlikely(msgs[i].flags & I2C_M_TEN)) { - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "10 bit addressing not supported\n"); status = -EINVAL; @@ -666,7 +667,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, out: clk_disable(dev->clk); - pm_runtime_put_sync(&dev->pdev->dev); + pm_runtime_put_sync(&dev->adev->dev); if (dev->regulator) regulator_disable(dev->regulator); @@ -789,7 +790,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) if (dev->cli.count) { dev->result = -EIO; - dev_err(&dev->pdev->dev, + dev_err(&dev->adev->dev, "%lu bytes still remain to be xfered\n", dev->cli.count); (void) init_hw(dev); @@ -833,7 +834,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) dev->result = -EIO; (void) init_hw(dev); - dev_err(&dev->pdev->dev, "Tx Fifo Over run\n"); + dev_err(&dev->adev->dev, "Tx Fifo Over run\n"); complete(&dev->xfer_complete); break; @@ -846,10 +847,10 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) case I2C_IT_RFSE: case I2C_IT_WTSR: case I2C_IT_STD: - dev_err(&dev->pdev->dev, "unhandled Interrupt\n"); + dev_err(&dev->adev->dev, "unhandled Interrupt\n"); break; default: - dev_err(&dev->pdev->dev, "spurious Interrupt..\n"); + dev_err(&dev->adev->dev, "spurious Interrupt..\n"); break; } @@ -860,8 +861,8 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) #ifdef CONFIG_PM static int nmk_i2c_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); + struct amba_device *adev = to_amba_device(dev); + struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); if (nmk_i2c->busy) return -EBUSY; @@ -898,79 +899,70 @@ static const struct i2c_algorithm nmk_i2c_algo = { .functionality = nmk_i2c_functionality }; -static int __devinit nmk_i2c_probe(struct platform_device *pdev) +static atomic_t adapter_id = ATOMIC_INIT(0); + +static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - struct resource *res; struct nmk_i2c_controller *pdata = - pdev->dev.platform_data; + adev->dev.platform_data; struct nmk_i2c_dev *dev; struct i2c_adapter *adap; + if (!pdata) { + dev_warn(&adev->dev, "no platform data\n"); + return -ENODEV; + } dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); if (!dev) { - dev_err(&pdev->dev, "cannot allocate memory\n"); + dev_err(&adev->dev, "cannot allocate memory\n"); ret = -ENOMEM; goto err_no_mem; } dev->busy = false; - dev->pdev = pdev; - platform_set_drvdata(pdev, dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto err_no_resource; - } + dev->adev = adev; + amba_set_drvdata(adev, dev); - if (request_mem_region(res->start, resource_size(res), - DRIVER_NAME "I/O region") == NULL) { - ret = -EBUSY; - goto err_no_region; - } - - dev->virtbase = ioremap(res->start, resource_size(res)); + dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); if (!dev->virtbase) { ret = -ENOMEM; goto err_no_ioremap; } - dev->irq = platform_get_irq(pdev, 0); + dev->irq = adev->irq[0]; ret = request_irq(dev->irq, i2c_irq_handler, 0, DRIVER_NAME, dev); if (ret) { - dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq); + dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); goto err_irq; } - dev->regulator = regulator_get(&pdev->dev, "v-i2c"); + dev->regulator = regulator_get(&adev->dev, "v-i2c"); if (IS_ERR(dev->regulator)) { - dev_warn(&pdev->dev, "could not get i2c regulator\n"); + dev_warn(&adev->dev, "could not get i2c regulator\n"); dev->regulator = NULL; } - pm_suspend_ignore_children(&pdev->dev, true); - pm_runtime_enable(&pdev->dev); + pm_suspend_ignore_children(&adev->dev, true); - dev->clk = clk_get(&pdev->dev, NULL); + dev->clk = clk_get(&adev->dev, NULL); if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "could not get i2c clock\n"); + dev_err(&adev->dev, "could not get i2c clock\n"); ret = PTR_ERR(dev->clk); goto err_no_clk; } adap = &dev->adap; - adap->dev.parent = &pdev->dev; + adap->dev.parent = &adev->dev; adap->owner = THIS_MODULE; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->algo = &nmk_i2c_algo; adap->timeout = pdata->timeout ? msecs_to_jiffies(pdata->timeout) : msecs_to_jiffies(20000); + adap->nr = atomic_read(&adapter_id); snprintf(adap->name, sizeof(adap->name), - "Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start); - - /* fetch the controller id */ - adap->nr = pdev->id; + "Nomadik I2C%d at %pR", adap->nr, &adev->res); + atomic_inc(&adapter_id); /* fetch the controller configuration from machine */ dev->cfg.clk_freq = pdata->clk_freq; @@ -981,16 +973,18 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, dev); - dev_info(&pdev->dev, + dev_info(&adev->dev, "initialize %s on virtual base %p\n", adap->name, dev->virtbase); ret = i2c_add_numbered_adapter(adap); if (ret) { - dev_err(&pdev->dev, "failed to add adapter\n"); + dev_err(&adev->dev, "failed to add adapter\n"); goto err_add_adap; } + pm_runtime_put(&adev->dev); + return 0; err_add_adap: @@ -998,25 +992,21 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) err_no_clk: if (dev->regulator) regulator_put(dev->regulator); - pm_runtime_disable(&pdev->dev); free_irq(dev->irq, dev); err_irq: iounmap(dev->virtbase); err_no_ioremap: - release_mem_region(res->start, resource_size(res)); - err_no_region: - platform_set_drvdata(pdev, NULL); - err_no_resource: + amba_set_drvdata(adev, NULL); kfree(dev); err_no_mem: return ret; } -static int __devexit nmk_i2c_remove(struct platform_device *pdev) +static int nmk_i2c_remove(struct amba_device *adev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); + struct resource *res = &adev->res; + struct nmk_i2c_dev *dev = amba_get_drvdata(adev); i2c_del_adapter(&dev->adap); flush_i2c_fifo(dev); @@ -1031,31 +1021,46 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) clk_put(dev->clk); if (dev->regulator) regulator_put(dev->regulator); - pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); + pm_runtime_disable(&adev->dev); + amba_set_drvdata(adev, NULL); kfree(dev); return 0; } -static struct platform_driver nmk_i2c_driver = { - .driver = { +static struct amba_id nmk_i2c_ids[] = { + { + .id = 0x00180024, + .mask = 0x00ffffff, + }, + { + .id = 0x00380024, + .mask = 0x00ffffff, + }, + {}, +}; + +MODULE_DEVICE_TABLE(amba, nmk_i2c_ids); + +static struct amba_driver nmk_i2c_driver = { + .drv = { .owner = THIS_MODULE, .name = DRIVER_NAME, .pm = &nmk_i2c_pm, }, + .id_table = nmk_i2c_ids, .probe = nmk_i2c_probe, - .remove = __devexit_p(nmk_i2c_remove), + .remove = nmk_i2c_remove, }; static int __init nmk_i2c_init(void) { - return platform_driver_register(&nmk_i2c_driver); + return amba_driver_register(&nmk_i2c_driver); } static void __exit nmk_i2c_exit(void) { - platform_driver_unregister(&nmk_i2c_driver); + amba_driver_unregister(&nmk_i2c_driver); } subsys_initcall(nmk_i2c_init); @@ -1064,4 +1069,3 @@ module_exit(nmk_i2c_exit); MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); -- GitLab From 419408edc90ee50d50323227d4dd73d6d22dc744 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Mon, 11 Jun 2012 22:56:49 +0200 Subject: [PATCH 2287/5711] i2c-nomadik: depend on ARM_AMBA, not PLAT_NOMADIK The gateware device has been used outside of the Nomadik world, using the pci-amba bridge driver, so loosen the dependencies. Signed-off-by: Alessandro Rubini Acked-by: Giancarlo Asnaghi Tested-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7244c8be6063..e9f9c5dc87ce 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -479,10 +479,11 @@ config I2C_MXS config I2C_NOMADIK tristate "ST-Ericsson Nomadik/Ux500 I2C Controller" - depends on PLAT_NOMADIK + depends on ARM_AMBA help If you say yes to this option, support will be included for the - I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. + I2C interface from ST-Ericsson's Nomadik and Ux500 architectures, + as well as the STA2X11 PCIe I/O HUB. config I2C_NUC900 tristate "NUC900 I2C Driver" -- GitLab From 51a0c8d0b8a877f41e9be62fb1e946ec682611c1 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Mon, 25 Jun 2012 17:56:07 +0530 Subject: [PATCH 2288/5711] i2c-nomadik: Add 10-bit addressing support Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Srinidhi KASAGAR Acked-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 46 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 6db453fe68e6..e6b93f3ca867 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -276,15 +276,32 @@ exit: /** * load_i2c_mcr_reg() - load the MCR register * @dev: private data of controller + * @flags: message flags */ -static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev) +static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev, u16 flags) { u32 mcr = 0; + unsigned short slave_adr_3msb_bits; - /* 7-bit address transaction */ - mcr |= GEN_MASK(1, I2C_MCR_AM, 12); mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1); + if (unlikely(flags & I2C_M_TEN)) { + /* 10-bit address transaction */ + mcr |= GEN_MASK(2, I2C_MCR_AM, 12); + /* + * Get the top 3 bits. + * EA10 represents extended address in MCR. This includes + * the extension (MSB bits) of the 7 bit address loaded + * in A7 + */ + slave_adr_3msb_bits = (dev->cli.slave_adr >> 7) & 0x7; + + mcr |= GEN_MASK(slave_adr_3msb_bits, I2C_MCR_EA10, 8); + } else { + /* 7-bit address transaction */ + mcr |= GEN_MASK(1, I2C_MCR_AM, 12); + } + /* start byte procedure not applied */ mcr |= GEN_MASK(0, I2C_MCR_SB, 11); @@ -381,19 +398,20 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) /** * read_i2c() - Read from I2C client device * @dev: private data of I2C Driver + * @flags: message flags * * This function reads from i2c client device when controller is in * master mode. There is a completion timeout. If there is no transfer * before timeout error is returned. */ -static int read_i2c(struct nmk_i2c_dev *dev) +static int read_i2c(struct nmk_i2c_dev *dev, u16 flags) { u32 status = 0; u32 mcr; u32 irq_mask = 0; int timeout; - mcr = load_i2c_mcr_reg(dev); + mcr = load_i2c_mcr_reg(dev, flags); writel(mcr, dev->virtbase + I2C_MCR); /* load the current CR value */ @@ -459,17 +477,18 @@ static void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes) /** * write_i2c() - Write data to I2C client. * @dev: private data of I2C Driver + * @flags: message flags * * This function writes data to I2C client */ -static int write_i2c(struct nmk_i2c_dev *dev) +static int write_i2c(struct nmk_i2c_dev *dev, u16 flags) { u32 status = 0; u32 mcr; u32 irq_mask = 0; int timeout; - mcr = load_i2c_mcr_reg(dev); + mcr = load_i2c_mcr_reg(dev, flags); writel(mcr, dev->virtbase + I2C_MCR); @@ -538,11 +557,11 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) if (flags & I2C_M_RD) { /* read operation */ dev->cli.operation = I2C_READ; - status = read_i2c(dev); + status = read_i2c(dev, flags); } else { /* write operation */ dev->cli.operation = I2C_WRITE; - status = write_i2c(dev); + status = write_i2c(dev, flags); } if (status || (dev->result)) { @@ -644,13 +663,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, setup_i2c_controller(dev); for (i = 0; i < num_msgs; i++) { - if (unlikely(msgs[i].flags & I2C_M_TEN)) { - dev_err(&dev->adev->dev, - "10 bit addressing not supported\n"); - - status = -EINVAL; - goto out; - } dev->cli.slave_adr = msgs[i].addr; dev->cli.buffer = msgs[i].buf; dev->cli.count = msgs[i].len; @@ -891,7 +903,7 @@ static const struct dev_pm_ops nmk_i2c_pm = { static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; } static const struct i2c_algorithm nmk_i2c_algo = { -- GitLab From f3da93105b6963a2be2a56dee27fdc88ac4ad769 Mon Sep 17 00:00:00 2001 From: Jeff Liu Date: Mon, 28 May 2012 23:40:17 +0800 Subject: [PATCH 2289/5711] quota: fix checkpatch.pl warning by replacing with checkpatch.pl warns: "WARNING: Use #include instead of " Below patch fixes it. Signed-off-by: Jie Liu Signed-off-by: Jan Kara --- fs/quota/dquot.c | 2 +- fs/quota/quota.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 10cbe841cb7e..0c541dcbdf07 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -78,7 +78,7 @@ #include #include "../internal.h" /* ugh */ -#include +#include /* * There are three quota SMP locks. dq_list_lock protects all lists with quotas diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 9a391204ca27..639782d5a76f 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include -- GitLab From f007dbf8e51f4a0910194eebc2aa119eb861893e Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 24 May 2012 12:00:37 -0500 Subject: [PATCH 2290/5711] ext3: force ro mount if ext3_setup_super() fails If ext3_setup_super() fails i.e. due to a too-high revision, the error is logged in dmesg but the fs is not mounted RO as indicated. Tested by: [164152.114551] EXT3-fs (sdb6): error: revision level too high, forcing read-only mode /dev/sdb6 /mnt/test2 ext3 rw,seclabel,relatime,errors=continue,user_xattr,acl,barrier=1,data=ordered 0 0 ^^ Signed-off-by: Eric Sandeen Reviewed-by: Andreas Dilger Signed-off-by: Jan Kara --- fs/ext3/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 8c3a44b7c375..b4e19926f46f 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2058,7 +2058,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) goto failed_mount3; } - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); + if (ext3_setup_super(sb, es, sb->s_flags & MS_RDONLY)) + sb->s_flags |= MS_RDONLY; EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS; ext3_orphan_cleanup(sb, es); -- GitLab From db8109ef98b5fb7e26e0d265c02f7164b13009d4 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 4 Jun 2012 14:46:24 +0300 Subject: [PATCH 2291/5711] udf: stop using s_dirt The UDF file-system does not need the 's_dirt' superblock flag because it does not define the 'write_super()' method. This flag was set to 1 in few places and set to 0 in '->sync_fs()' and was basically useless. Stop using it because it is on its way out. Signed-off-by: Artem Bityutskiy Signed-off-by: Jan Kara --- fs/udf/super.c | 6 ------ fs/udf/udfdecl.h | 1 - 2 files changed, 7 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 8d86a8706c0e..e7534fb84c2d 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1974,7 +1974,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sb->s_op = &udf_sb_ops; sb->s_export_op = &udf_export_ops; - sb->s_dirt = 0; sb->s_magic = UDF_SUPER_MAGIC; sb->s_time_gran = 1000; @@ -2096,10 +2095,6 @@ void _udf_err(struct super_block *sb, const char *function, struct va_format vaf; va_list args; - /* mark sb error */ - if (!(sb->s_flags & MS_RDONLY)) - sb->s_dirt = 1; - va_start(args, fmt); vaf.fmt = fmt; @@ -2161,7 +2156,6 @@ static int udf_sync_fs(struct super_block *sb, int wait) * the buffer for IO */ mark_buffer_dirty(sbi->s_lvid_bh); - sb->s_dirt = 0; sbi->s_lvid_dirty = 0; } mutex_unlock(&sbi->s_alloc_mutex); diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index ebe10314e512..de038da6f6bd 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -129,7 +129,6 @@ static inline void udf_updated_lvid(struct super_block *sb) WARN_ON_ONCE(((struct logicalVolIntegrityDesc *) bh->b_data)->integrityType != cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN)); - sb->s_dirt = 1; UDF_SB(sb)->s_lvid_dirty = 1; } extern u64 lvid_get_unique_id(struct super_block *sb); -- GitLab From a0e589b485cd5e6a74d40d195b3d7de212b4227d Mon Sep 17 00:00:00 2001 From: Ashish Sangwan Date: Tue, 26 Jun 2012 19:33:11 +0530 Subject: [PATCH 2292/5711] UDF: Remove unnecessary variable "offset" from udf_fill_inode The variable "offset" is not needed. Remove it. Signed-off-by: Ashish Sangwan Signed-off-by: Namjae Jeon Signed-off-by: Jan Kara --- fs/udf/inode.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 873e1bab9c4c..fafaad795cd6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1247,7 +1247,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) { struct fileEntry *fe; struct extendedFileEntry *efe; - int offset; struct udf_sb_info *sbi = UDF_SB(inode->i_sb); struct udf_inode_info *iinfo = UDF_I(inode); unsigned int link_count; @@ -1359,7 +1358,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); - offset = sizeof(struct fileEntry) + iinfo->i_lenEAttr; } else { inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); @@ -1381,8 +1379,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); - offset = sizeof(struct extendedFileEntry) + - iinfo->i_lenEAttr; } switch (fe->icbTag.fileType) { -- GitLab From e124a32043416ddefaec3c54cc945b7667c00628 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Thu, 28 Jun 2012 00:49:44 +0800 Subject: [PATCH 2293/5711] ext2: cleanup the confused goto label Cleanup the confused goto label, since the big lock has been removed. Signed-off-by: Wanlong Gao Signed-off-by: Jan Kara --- fs/ext2/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index b3621cb7ea31..c8e49794ab5d 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -771,13 +771,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) err = -ENOMEM; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) - goto failed_unlock; + goto failed; sbi->s_blockgroup_lock = kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); if (!sbi->s_blockgroup_lock) { kfree(sbi); - goto failed_unlock; + goto failed; } sb->s_fs_info = sbi; sbi->s_sb_block = sb_block; @@ -1130,7 +1130,7 @@ failed_sbi: sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); kfree(sbi); -failed_unlock: +failed: return ret; } -- GitLab From bff943af6fe3af022c1c7a22cdb2e18a242eaf35 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Jun 2012 22:27:05 +0200 Subject: [PATCH 2294/5711] udf: Fix memory leak when mounting When we are mounting filesystem, we can load one partition table before finding out that we cannot complete processing of logical volume descriptor and trying the reserve descriptor. Free the table properly before trying the reserve descriptor. Signed-off-by: Jan Kara --- fs/udf/super.c | 122 ++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index e7534fb84c2d..8a7583867811 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -252,6 +252,63 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count) return 0; } +static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) +{ + int i; + int nr_groups = bitmap->s_nr_groups; + int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * + nr_groups); + + for (i = 0; i < nr_groups; i++) + if (bitmap->s_block_bitmap[i]) + brelse(bitmap->s_block_bitmap[i]); + + if (size <= PAGE_SIZE) + kfree(bitmap); + else + vfree(bitmap); +} + +static void udf_free_partition(struct udf_part_map *map) +{ + int i; + struct udf_meta_data *mdata; + + if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) + iput(map->s_uspace.s_table); + if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) + iput(map->s_fspace.s_table); + if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) + udf_sb_free_bitmap(map->s_uspace.s_bitmap); + if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) + udf_sb_free_bitmap(map->s_fspace.s_bitmap); + if (map->s_partition_type == UDF_SPARABLE_MAP15) + for (i = 0; i < 4; i++) + brelse(map->s_type_specific.s_sparing.s_spar_map[i]); + else if (map->s_partition_type == UDF_METADATA_MAP25) { + mdata = &map->s_type_specific.s_metadata; + iput(mdata->s_metadata_fe); + mdata->s_metadata_fe = NULL; + + iput(mdata->s_mirror_fe); + mdata->s_mirror_fe = NULL; + + iput(mdata->s_bitmap_fe); + mdata->s_bitmap_fe = NULL; + } +} + +static void udf_sb_free_partitions(struct super_block *sb) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + int i; + + for (i = 0; i < sbi->s_partitions; i++) + udf_free_partition(&sbi->s_partmaps[i]); + kfree(sbi->s_partmaps); + sbi->s_partmaps = NULL; +} + static int udf_show_options(struct seq_file *seq, struct dentry *root) { struct super_block *sb = root->d_sb; @@ -1596,7 +1653,11 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, /* responsible for finding the PartitionDesc(s) */ if (!udf_process_sequence(sb, main_s, main_e, fileset)) return 1; - return !udf_process_sequence(sb, reserve_s, reserve_e, fileset); + udf_sb_free_partitions(sb); + if (!udf_process_sequence(sb, reserve_s, reserve_e, fileset)) + return 1; + udf_sb_free_partitions(sb); + return 0; } /* @@ -1861,55 +1922,8 @@ u64 lvid_get_unique_id(struct super_block *sb) return ret; } -static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) -{ - int i; - int nr_groups = bitmap->s_nr_groups; - int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * - nr_groups); - - for (i = 0; i < nr_groups; i++) - if (bitmap->s_block_bitmap[i]) - brelse(bitmap->s_block_bitmap[i]); - - if (size <= PAGE_SIZE) - kfree(bitmap); - else - vfree(bitmap); -} - -static void udf_free_partition(struct udf_part_map *map) -{ - int i; - struct udf_meta_data *mdata; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) - iput(map->s_uspace.s_table); - if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) - iput(map->s_fspace.s_table); - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) - udf_sb_free_bitmap(map->s_uspace.s_bitmap); - if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) - udf_sb_free_bitmap(map->s_fspace.s_bitmap); - if (map->s_partition_type == UDF_SPARABLE_MAP15) - for (i = 0; i < 4; i++) - brelse(map->s_type_specific.s_sparing.s_spar_map[i]); - else if (map->s_partition_type == UDF_METADATA_MAP25) { - mdata = &map->s_type_specific.s_metadata; - iput(mdata->s_metadata_fe); - mdata->s_metadata_fe = NULL; - - iput(mdata->s_mirror_fe); - mdata->s_mirror_fe = NULL; - - iput(mdata->s_bitmap_fe); - mdata->s_bitmap_fe = NULL; - } -} - static int udf_fill_super(struct super_block *sb, void *options, int silent) { - int i; int ret; struct inode *inode = NULL; struct udf_options uopt; @@ -2071,9 +2085,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) error_out: if (sbi->s_vat_inode) iput(sbi->s_vat_inode); - if (sbi->s_partitions) - for (i = 0; i < sbi->s_partitions; i++) - udf_free_partition(&sbi->s_partmaps[i]); #ifdef CONFIG_UDF_NLS if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) unload_nls(sbi->s_nls_map); @@ -2081,8 +2092,7 @@ error_out: if (!(sb->s_flags & MS_RDONLY)) udf_close_lvid(sb); brelse(sbi->s_lvid_bh); - - kfree(sbi->s_partmaps); + udf_sb_free_partitions(sb); kfree(sbi); sb->s_fs_info = NULL; @@ -2123,16 +2133,12 @@ void _udf_warn(struct super_block *sb, const char *function, static void udf_put_super(struct super_block *sb) { - int i; struct udf_sb_info *sbi; sbi = UDF_SB(sb); if (sbi->s_vat_inode) iput(sbi->s_vat_inode); - if (sbi->s_partitions) - for (i = 0; i < sbi->s_partitions; i++) - udf_free_partition(&sbi->s_partmaps[i]); #ifdef CONFIG_UDF_NLS if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) unload_nls(sbi->s_nls_map); @@ -2140,7 +2146,7 @@ static void udf_put_super(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) udf_close_lvid(sb); brelse(sbi->s_lvid_bh); - kfree(sbi->s_partmaps); + udf_sb_free_partitions(sb); kfree(sb->s_fs_info); sb->s_fs_info = NULL; } -- GitLab From 49003a68926e073fc71062d210c6f9febc8665a2 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 9 Jul 2012 12:36:11 +0200 Subject: [PATCH 2295/5711] mfd: Fix Arizona Kconfig entry The core and irq Arizona parts should be boolean as they depend on non exported symbols. This fixes the following build errors: ERROR: "wm5102_aod" [drivers/mfd/arizona-irq.ko] undefined! ERROR: "wm5102_irq" [drivers/mfd/arizona-irq.ko] undefined! ERROR: "irq_set_chip_and_handler_name" [drivers/mfd/arizona-irq.ko] undefined! ERROR: "wm5102_patch" [drivers/mfd/arizona-core.ko] undefined! ERROR: "arizona_irq_init" [drivers/mfd/arizona-core.ko] undefined! ERROR: "arizona_irq_exit" [drivers/mfd/arizona-core.ko] undefined! Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 53cbd16c7a4a..5c043693f52c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -497,7 +497,7 @@ config MFD_S5M_CORE config MFD_ARIZONA select REGMAP - tristate + bool config MFD_ARIZONA_I2C tristate "Support Wolfson Microelectronics Arizona platform with I2C" -- GitLab From a55b44ac3fe07d4e89486817732b596fce6ab9f6 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 1 Jul 2012 23:34:30 +0200 Subject: [PATCH 2296/5711] i2c: mxs: mxs_i2c_finish_read: mute flase positive uninitialized var This patch mutes the false positive compiler warning: drivers/i2c/busses/i2c-mxs.c: In function 'mxs_i2c_xfer_msg': drivers/i2c/busses/i2c-mxs.c:206:8: warning: 'data' may be used uninitialized in this function [-Wuninitialized] drivers/i2c/busses/i2c-mxs.c:196:6: note: 'data' was declared here Signed-off-by: Marc Kleine-Budde Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mxs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 04eb441b6ce1..02ce1faeeeef 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -193,7 +193,7 @@ static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) { - u32 data; + u32 uninitialized_var(data); int i; for (i = 0; i < len; i++) { -- GitLab From a837987e7b36a9056cd17c0967efe1ce73a102ff Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 12:16:41 +0100 Subject: [PATCH 2297/5711] ASoC: arizona: Export dai_ops Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 901b53e1d7bc..0be04b526588 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -646,6 +646,7 @@ const struct snd_soc_dai_ops arizona_dai_ops = { .hw_params = arizona_hw_params, .set_sysclk = arizona_dai_set_sysclk, }; +EXPORT_SYMBOL_GPL(arizona_dai_ops); int arizona_init_dai(struct arizona_priv *priv, int id) { -- GitLab From 17dc59ba418c3d6b0675d5b74d280acab2d4e369 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 9 Jul 2012 13:24:21 +0200 Subject: [PATCH 2298/5711] udf: Do not decrement i_blocks when freeing indirect extent block Indirect extent block is not accounted in i_blocks during allocation thus we should not decrement i_blocks when we are freeing such block during truncation. Reported-by: Steve Nickel Signed-off-by: Jan Kara --- fs/udf/truncate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 4b98fee8e161..8a9657d7f7c6 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -248,7 +248,7 @@ void udf_truncate_extents(struct inode *inode) /* We managed to free all extents in the * indirect extent - free it too */ BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, &epos.block, + udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len); } else if (!epos.bh) { iinfo->i_lenAlloc = lenalloc; @@ -275,7 +275,7 @@ void udf_truncate_extents(struct inode *inode) if (indirect_ext_len) { BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len); + udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len); } else if (!epos.bh) { iinfo->i_lenAlloc = lenalloc; mark_inode_dirty(inode); -- GitLab From 2a8ac745e3171889d364235b8203342e28526d2c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 6 Jul 2012 16:08:25 +0200 Subject: [PATCH 2299/5711] x86: CONFIG_CC_STACKPROTECTOR=y is no longer experimental This feature has been around for over 5 years now, and has no CONFIG_EXPERIMENTAL dependency anymore, so remove the '(EXPERIMENTAL)' tag from the help text as well. Signed-off-by: Jean Delvare Acked-by: Arjan van de Ven Link: http://lkml.kernel.org/r/1341583705.4655.18.camel@amber.site Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c70684f859e1..b03fe17042e4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1525,7 +1525,7 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. config CC_STACKPROTECTOR - bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" + bool "Enable -fstack-protector buffer overflow detection" ---help--- This option turns on the -fstack-protector GCC feature. This feature puts, at the beginning of functions, a canary value on -- GitLab From a3f24c0dbd0b9a7624d077b3c1841dde267aaa6c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Jun 2012 19:33:30 +0200 Subject: [PATCH 2300/5711] i2c: stu300: use clk_prepare/unprepare Make sure we prepare/unprepare the clock for the ST U300 I2C driver as is required by the clk API especially if you use common clock. Signed-off-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stu300.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 4d44af181f37..79b785150c15 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -924,7 +924,7 @@ stu300_probe(struct platform_device *pdev) dev->speed = scl_frequency; - clk_enable(dev->clk); + clk_prepare_enable(dev->clk); ret = stu300_init_hw(dev); clk_disable(dev->clk); @@ -960,6 +960,7 @@ stu300_probe(struct platform_device *pdev) err_add_adapter: err_init_hw: + clk_unprepare(dev->clk); free_irq(dev->irq, dev); err_no_irq: iounmap(dev->virtbase); @@ -1016,6 +1017,7 @@ stu300_remove(struct platform_device *pdev) free_irq(dev->irq, dev); iounmap(dev->virtbase); release_mem_region(dev->phybase, dev->physize); + clk_unprepare(dev->clk); clk_put(dev->clk); platform_set_drvdata(pdev, NULL); kfree(dev); -- GitLab From 1f09c672314f8180113429ff36cad09296c40a9f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 6 Jul 2012 15:31:32 -0300 Subject: [PATCH 2301/5711] i2c: i2c-imx: Adapt the clock name to the new clock framework With the new i.mx clock framework the i2c clock is registered as: clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx-i2c.0") So we do not need to pass "i2c_clk" string and can use NULL instead. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer [wsa: rebased on top of the devm-conversion] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a93e84650f99..dd2a0839b266 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -514,7 +514,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) } /* Get I2C clock */ - i2c_imx->clk = devm_clk_get(&pdev->dev, "i2c_clk"); + i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_imx->clk)) { dev_err(&pdev->dev, "can't get I2C clock\n"); return PTR_ERR(i2c_imx->clk); -- GitLab From 70c6cce040661204986ebbf22224cb24bd77ea71 Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Mon, 9 Jul 2012 14:37:32 +0800 Subject: [PATCH 2302/5711] mfd: Support 88pm80x in 80x driver 88PM800 and 88PM805 are two discrete chips used for power management. Hardware designer can use them together or only one of them according to requirement. 88pm80x.c provides common i2c driver handling for both 800 and 805, such as i2c_driver init, regmap init, read/write api etc. 88pm800.c handles specifically for 800, such as chip init, irq init/handle, mfd device register, including rtc, onkey, regulator( to be add later) etc. besides that, 800 has three i2c device, one regular i2c client, two other i2c dummy for gpadc and power purpose. 88pm805.c handles specifically for 805, such as chip init, irq init/handle, mfd device register, including codec, headset/mic detect etc. the i2c operation of both 800 and 805 are via regmap, and 88pm80x-i2c exported a group of r/w bulk r/w and bits set API for facility. Signed-off-by: Qiao Zhou Reviewed-by: Arnd Bergmann Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 593 ++++++++++++++++++++++++++++++++++++ drivers/mfd/88pm805.c | 299 ++++++++++++++++++ drivers/mfd/88pm80x.c | 116 +++++++ drivers/mfd/Kconfig | 24 ++ drivers/mfd/Makefile | 2 + include/linux/mfd/88pm80x.h | 368 ++++++++++++++++++++++ 6 files changed, 1402 insertions(+) create mode 100644 drivers/mfd/88pm800.c create mode 100644 drivers/mfd/88pm805.c create mode 100644 drivers/mfd/88pm80x.c create mode 100644 include/linux/mfd/88pm80x.h diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c new file mode 100644 index 000000000000..fe479ccfaa19 --- /dev/null +++ b/drivers/mfd/88pm800.c @@ -0,0 +1,593 @@ +/* + * Base driver for Marvell 88PM800 + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang + * Joseph(Yossi) Hanin + * Qiao Zhou + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#define PM800_CHIP_ID (0x00) + +/* Interrupt Registers */ +#define PM800_INT_STATUS1 (0x05) +#define PM800_ONKEY_INT_STS1 (1 << 0) +#define PM800_EXTON_INT_STS1 (1 << 1) +#define PM800_CHG_INT_STS1 (1 << 2) +#define PM800_BAT_INT_STS1 (1 << 3) +#define PM800_RTC_INT_STS1 (1 << 4) +#define PM800_CLASSD_OC_INT_STS1 (1 << 5) + +#define PM800_INT_STATUS2 (0x06) +#define PM800_VBAT_INT_STS2 (1 << 0) +#define PM800_VSYS_INT_STS2 (1 << 1) +#define PM800_VCHG_INT_STS2 (1 << 2) +#define PM800_TINT_INT_STS2 (1 << 3) +#define PM800_GPADC0_INT_STS2 (1 << 4) +#define PM800_TBAT_INT_STS2 (1 << 5) +#define PM800_GPADC2_INT_STS2 (1 << 6) +#define PM800_GPADC3_INT_STS2 (1 << 7) + +#define PM800_INT_STATUS3 (0x07) + +#define PM800_INT_STATUS4 (0x08) +#define PM800_GPIO0_INT_STS4 (1 << 0) +#define PM800_GPIO1_INT_STS4 (1 << 1) +#define PM800_GPIO2_INT_STS4 (1 << 2) +#define PM800_GPIO3_INT_STS4 (1 << 3) +#define PM800_GPIO4_INT_STS4 (1 << 4) + +#define PM800_INT_ENA_1 (0x09) +#define PM800_ONKEY_INT_ENA1 (1 << 0) +#define PM800_EXTON_INT_ENA1 (1 << 1) +#define PM800_CHG_INT_ENA1 (1 << 2) +#define PM800_BAT_INT_ENA1 (1 << 3) +#define PM800_RTC_INT_ENA1 (1 << 4) +#define PM800_CLASSD_OC_INT_ENA1 (1 << 5) + +#define PM800_INT_ENA_2 (0x0A) +#define PM800_VBAT_INT_ENA2 (1 << 0) +#define PM800_VSYS_INT_ENA2 (1 << 1) +#define PM800_VCHG_INT_ENA2 (1 << 2) +#define PM800_TINT_INT_ENA2 (1 << 3) + +#define PM800_INT_ENA_3 (0x0B) +#define PM800_GPADC0_INT_ENA3 (1 << 0) +#define PM800_GPADC1_INT_ENA3 (1 << 1) +#define PM800_GPADC2_INT_ENA3 (1 << 2) +#define PM800_GPADC3_INT_ENA3 (1 << 3) +#define PM800_GPADC4_INT_ENA3 (1 << 4) + +#define PM800_INT_ENA_4 (0x0C) +#define PM800_GPIO0_INT_ENA4 (1 << 0) +#define PM800_GPIO1_INT_ENA4 (1 << 1) +#define PM800_GPIO2_INT_ENA4 (1 << 2) +#define PM800_GPIO3_INT_ENA4 (1 << 3) +#define PM800_GPIO4_INT_ENA4 (1 << 4) + +/* number of INT_ENA & INT_STATUS regs */ +#define PM800_INT_REG_NUM (4) + +/* Interrupt Number in 88PM800 */ +enum { + PM800_IRQ_ONKEY, /*EN1b0 *//*0 */ + PM800_IRQ_EXTON, /*EN1b1 */ + PM800_IRQ_CHG, /*EN1b2 */ + PM800_IRQ_BAT, /*EN1b3 */ + PM800_IRQ_RTC, /*EN1b4 */ + PM800_IRQ_CLASSD, /*EN1b5 *//*5 */ + PM800_IRQ_VBAT, /*EN2b0 */ + PM800_IRQ_VSYS, /*EN2b1 */ + PM800_IRQ_VCHG, /*EN2b2 */ + PM800_IRQ_TINT, /*EN2b3 */ + PM800_IRQ_GPADC0, /*EN3b0 *//*10 */ + PM800_IRQ_GPADC1, /*EN3b1 */ + PM800_IRQ_GPADC2, /*EN3b2 */ + PM800_IRQ_GPADC3, /*EN3b3 */ + PM800_IRQ_GPADC4, /*EN3b4 */ + PM800_IRQ_GPIO0, /*EN4b0 *//*15 */ + PM800_IRQ_GPIO1, /*EN4b1 */ + PM800_IRQ_GPIO2, /*EN4b2 */ + PM800_IRQ_GPIO3, /*EN4b3 */ + PM800_IRQ_GPIO4, /*EN4b4 *//*19 */ + PM800_MAX_IRQ, +}; + +enum { + /* Procida */ + PM800_CHIP_A0 = 0x60, + PM800_CHIP_A1 = 0x61, + PM800_CHIP_B0 = 0x62, + PM800_CHIP_C0 = 0x63, + PM800_CHIP_END = PM800_CHIP_C0, + + /* Make sure to update this to the last stepping */ + PM8XXX_CHIP_END = PM800_CHIP_END +}; + +static const struct i2c_device_id pm80x_id_table[] = { + {"88PM800", CHIP_PM800}, +}; +MODULE_DEVICE_TABLE(i2c, pm80x_id_table); + +static struct resource rtc_resources[] = { + { + .name = "88pm80x-rtc", + .start = PM800_IRQ_RTC, + .end = PM800_IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell rtc_devs[] = { + { + .name = "88pm80x-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + .id = -1, + }, +}; + +static struct resource onkey_resources[] = { + { + .name = "88pm80x-onkey", + .start = PM800_IRQ_ONKEY, + .end = PM800_IRQ_ONKEY, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell onkey_devs[] = { + { + .name = "88pm80x-onkey", + .num_resources = 1, + .resources = &onkey_resources[0], + .id = -1, + }, +}; + +static const struct regmap_irq pm800_irqs[] = { + /* INT0 */ + [PM800_IRQ_ONKEY] = { + .mask = PM800_ONKEY_INT_ENA1, + }, + [PM800_IRQ_EXTON] = { + .mask = PM800_EXTON_INT_ENA1, + }, + [PM800_IRQ_CHG] = { + .mask = PM800_CHG_INT_ENA1, + }, + [PM800_IRQ_BAT] = { + .mask = PM800_BAT_INT_ENA1, + }, + [PM800_IRQ_RTC] = { + .mask = PM800_RTC_INT_ENA1, + }, + [PM800_IRQ_CLASSD] = { + .mask = PM800_CLASSD_OC_INT_ENA1, + }, + /* INT1 */ + [PM800_IRQ_VBAT] = { + .reg_offset = 1, + .mask = PM800_VBAT_INT_ENA2, + }, + [PM800_IRQ_VSYS] = { + .reg_offset = 1, + .mask = PM800_VSYS_INT_ENA2, + }, + [PM800_IRQ_VCHG] = { + .reg_offset = 1, + .mask = PM800_VCHG_INT_ENA2, + }, + [PM800_IRQ_TINT] = { + .reg_offset = 1, + .mask = PM800_TINT_INT_ENA2, + }, + /* INT2 */ + [PM800_IRQ_GPADC0] = { + .reg_offset = 2, + .mask = PM800_GPADC0_INT_ENA3, + }, + [PM800_IRQ_GPADC1] = { + .reg_offset = 2, + .mask = PM800_GPADC1_INT_ENA3, + }, + [PM800_IRQ_GPADC2] = { + .reg_offset = 2, + .mask = PM800_GPADC2_INT_ENA3, + }, + [PM800_IRQ_GPADC3] = { + .reg_offset = 2, + .mask = PM800_GPADC3_INT_ENA3, + }, + [PM800_IRQ_GPADC4] = { + .reg_offset = 2, + .mask = PM800_GPADC4_INT_ENA3, + }, + /* INT3 */ + [PM800_IRQ_GPIO0] = { + .reg_offset = 3, + .mask = PM800_GPIO0_INT_ENA4, + }, + [PM800_IRQ_GPIO1] = { + .reg_offset = 3, + .mask = PM800_GPIO1_INT_ENA4, + }, + [PM800_IRQ_GPIO2] = { + .reg_offset = 3, + .mask = PM800_GPIO2_INT_ENA4, + }, + [PM800_IRQ_GPIO3] = { + .reg_offset = 3, + .mask = PM800_GPIO3_INT_ENA4, + }, + [PM800_IRQ_GPIO4] = { + .reg_offset = 3, + .mask = PM800_GPIO4_INT_ENA4, + }, +}; + +static int __devinit device_gpadc_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + struct pm80x_subchip *subchip = chip->subchip; + struct regmap *map = subchip->regmap_gpadc; + int data = 0, mask = 0, ret = 0; + + if (!map) { + dev_warn(chip->dev, + "Warning: gpadc regmap is not available!\n"); + return -EINVAL; + } + /* + * initialize GPADC without activating it turn on GPADC + * measurments + */ + ret = regmap_update_bits(map, + PM800_GPADC_MISC_CONFIG2, + PM800_GPADC_MISC_GPFSM_EN, + PM800_GPADC_MISC_GPFSM_EN); + if (ret < 0) + goto out; + /* + * This function configures the ADC as requires for + * CP implementation.CP does not "own" the ADC configuration + * registers and relies on AP. + * Reason: enable automatic ADC measurements needed + * for CP to get VBAT and RF temperature readings. + */ + ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN1, + PM800_MEAS_EN1_VBAT, PM800_MEAS_EN1_VBAT); + if (ret < 0) + goto out; + ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN2, + (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN), + (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN)); + if (ret < 0) + goto out; + + /* + * the defult of PM800 is GPADC operates at 100Ks/s rate + * and Number of GPADC slots with active current bias prior + * to GPADC sampling = 1 slot for all GPADCs set for + * Temprature mesurmants + */ + mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 | + PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3); + + if (pdata && (pdata->batt_det == 0)) + data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 | + PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3); + else + data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN2 | + PM800_GPADC_GP_BIAS_EN3); + + ret = regmap_update_bits(map, PM800_GP_BIAS_ENA1, mask, data); + if (ret < 0) + goto out; + + dev_info(chip->dev, "pm800 device_gpadc_init: Done\n"); + return 0; + +out: + dev_info(chip->dev, "pm800 device_gpadc_init: Failed!\n"); + return ret; +} + +static int __devinit device_irq_init_800(struct pm80x_chip *chip) +{ + struct regmap *map = chip->regmap; + unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + int data, mask, ret = -EINVAL; + + if (!map || !chip->irq) { + dev_err(chip->dev, "incorrect parameters\n"); + return -EINVAL; + } + + /* + * irq_mode defines the way of clearing interrupt. it's read-clear by + * default. + */ + mask = + PM800_WAKEUP2_INV_INT | PM800_WAKEUP2_INT_CLEAR | + PM800_WAKEUP2_INT_MASK; + + data = PM800_WAKEUP2_INT_CLEAR; + ret = regmap_update_bits(map, PM800_WAKEUP2, mask, data); + + if (ret < 0) + goto out; + + ret = + regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1, + chip->regmap_irq_chip, &chip->irq_data); + +out: + return ret; +} + +static void device_irq_exit_800(struct pm80x_chip *chip) +{ + regmap_del_irq_chip(chip->irq, chip->irq_data); +} + +static struct regmap_irq_chip pm800_irq_chip = { + .name = "88pm800", + .irqs = pm800_irqs, + .num_irqs = ARRAY_SIZE(pm800_irqs), + + .num_regs = 4, + .status_base = PM800_INT_STATUS1, + .mask_base = PM800_INT_ENA_1, + .ack_base = PM800_INT_STATUS1, +}; + +static int pm800_pages_init(struct pm80x_chip *chip) +{ + struct pm80x_subchip *subchip; + struct i2c_client *client = chip->client; + + subchip = chip->subchip; + /* PM800 block power: i2c addr 0x31 */ + if (subchip->power_page_addr) { + subchip->power_page = + i2c_new_dummy(client->adapter, subchip->power_page_addr); + subchip->regmap_power = + devm_regmap_init_i2c(subchip->power_page, + &pm80x_regmap_config); + i2c_set_clientdata(subchip->power_page, chip); + } else + dev_info(chip->dev, + "PM800 block power 0x31: No power_page_addr\n"); + + /* PM800 block GPADC: i2c addr 0x32 */ + if (subchip->gpadc_page_addr) { + subchip->gpadc_page = i2c_new_dummy(client->adapter, + subchip->gpadc_page_addr); + subchip->regmap_gpadc = + devm_regmap_init_i2c(subchip->gpadc_page, + &pm80x_regmap_config); + i2c_set_clientdata(subchip->gpadc_page, chip); + } else + dev_info(chip->dev, + "PM800 block GPADC 0x32: No gpadc_page_addr\n"); + + return 0; +} + +static void pm800_pages_exit(struct pm80x_chip *chip) +{ + struct pm80x_subchip *subchip; + + regmap_exit(chip->regmap); + i2c_unregister_device(chip->client); + + subchip = chip->subchip; + if (subchip->power_page) { + regmap_exit(subchip->regmap_power); + i2c_unregister_device(subchip->power_page); + } + if (subchip->gpadc_page) { + regmap_exit(subchip->regmap_gpadc); + i2c_unregister_device(subchip->gpadc_page); + } +} + +static int __devinit device_800_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret, pmic_id; + + regmap_read(chip->regmap, PM800_CHIP_ID, &ret); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + goto out; + } + + pmic_id = ret & PM80X_VERSION_MASK; + + if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) { + chip->version = ret; + dev_info(chip->dev, + "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", ret); + } else { + dev_err(chip->dev, + "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", ret); + goto out; + } + + /* + * alarm wake up bit will be clear in device_irq_init(), + * read before that + */ + regmap_read(chip->regmap, PM800_RTC_CONTROL, &ret); + if (ret < 0) { + dev_err(chip->dev, "Failed to read RTC register: %d\n", ret); + goto out; + } + if (ret & PM800_ALARM_WAKEUP) { + if (pdata && pdata->rtc) + pdata->rtc->rtc_wakeup = 1; + } + + ret = device_gpadc_init(chip, pdata); + if (ret < 0) { + dev_err(chip->dev, "[%s]Failed to init gpadc\n", __func__); + goto out; + } + + chip->regmap_irq_chip = &pm800_irq_chip; + + ret = device_irq_init_800(chip); + if (ret < 0) { + dev_err(chip->dev, "[%s]Failed to init pm800 irq\n", __func__); + goto out; + } + + ret = + mfd_add_devices(chip->dev, 0, &onkey_devs[0], + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add onkey subdev\n"); + goto out_dev; + } else + dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__); + + if (pdata && pdata->rtc) { + rtc_devs[0].platform_data = pdata->rtc; + rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); + ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], + ARRAY_SIZE(rtc_devs), NULL, 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + goto out_dev; + } else + dev_info(chip->dev, + "[%s]:Added mfd rtc_devs\n", __func__); + } + + return 0; +out_dev: + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); +out: + return ret; +} + +static int __devinit pm800_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct pm80x_chip *chip; + struct pm80x_platform_data *pdata = client->dev.platform_data; + struct pm80x_subchip *subchip; + + ret = pm80x_init(client, id); + if (ret) { + dev_err(&client->dev, "pm800_init fail\n"); + goto out_init; + } + + chip = i2c_get_clientdata(client); + + /* init subchip for PM800 */ + subchip = + devm_kzalloc(&client->dev, sizeof(struct pm80x_subchip), + GFP_KERNEL); + if (!subchip) { + ret = -ENOMEM; + goto err_subchip_alloc; + } + + subchip->power_page_addr = pdata->power_page_addr; + subchip->gpadc_page_addr = pdata->gpadc_page_addr; + chip->subchip = subchip; + + ret = device_800_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + goto err_800_init; + } + + ret = pm800_pages_init(chip); + if (ret) { + dev_err(&client->dev, "pm800_pages_init failed!\n"); + goto err_page_init; + } + + if (pdata->plat_config) + pdata->plat_config(chip, pdata); + +err_page_init: + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); +err_800_init: + devm_kfree(&client->dev, subchip); +err_subchip_alloc: + pm80x_deinit(client); +out_init: + return ret; +} + +static int __devexit pm800_remove(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); + + pm800_pages_exit(chip); + devm_kfree(&client->dev, chip->subchip); + + pm80x_deinit(client); + + return 0; +} + +static struct i2c_driver pm800_driver = { + .driver = { + .name = "88PM80X", + .owner = THIS_MODULE, + .pm = &pm80x_pm_ops, + }, + .probe = pm800_probe, + .remove = __devexit_p(pm800_remove), + .id_table = pm80x_id_table, +}; + +static int __init pm800_i2c_init(void) +{ + return i2c_add_driver(&pm800_driver); +} +subsys_initcall(pm800_i2c_init); + +static void __exit pm800_i2c_exit(void) +{ + i2c_del_driver(&pm800_driver); +} +module_exit(pm800_i2c_exit); + +MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM800"); +MODULE_AUTHOR("Qiao Zhou "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c new file mode 100644 index 000000000000..d93c3091cb9f --- /dev/null +++ b/drivers/mfd/88pm805.c @@ -0,0 +1,299 @@ +/* + * Base driver for Marvell 88PM805 + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang + * Joseph(Yossi) Hanin + * Qiao Zhou + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PM805_CHIP_ID (0x00) + +static const struct i2c_device_id pm80x_id_table[] = { + {"88PM805", CHIP_PM805}, +}; +MODULE_DEVICE_TABLE(i2c, pm80x_id_table); + +/* Interrupt Number in 88PM805 */ +enum { + PM805_IRQ_LDO_OFF, /*0 */ + PM805_IRQ_SRC_DPLL_LOCK, /*1 */ + PM805_IRQ_CLIP_FAULT, + PM805_IRQ_MIC_CONFLICT, + PM805_IRQ_HP2_SHRT, + PM805_IRQ_HP1_SHRT, /*5 */ + PM805_IRQ_FINE_PLL_FAULT, + PM805_IRQ_RAW_PLL_FAULT, + PM805_IRQ_VOLP_BTN_DET, + PM805_IRQ_VOLM_BTN_DET, + PM805_IRQ_SHRT_BTN_DET, /*10 */ + PM805_IRQ_MIC_DET, /*11 */ + + PM805_MAX_IRQ, +}; + +static struct resource codec_resources[] = { + { + /* Headset microphone insertion or removal */ + .name = "micin", + .start = PM805_IRQ_MIC_DET, + .end = PM805_IRQ_MIC_DET, + .flags = IORESOURCE_IRQ, + }, + { + /* Audio short HP1 */ + .name = "audio-short1", + .start = PM805_IRQ_HP1_SHRT, + .end = PM805_IRQ_HP1_SHRT, + .flags = IORESOURCE_IRQ, + }, + { + /* Audio short HP2 */ + .name = "audio-short2", + .start = PM805_IRQ_HP2_SHRT, + .end = PM805_IRQ_HP2_SHRT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell codec_devs[] = { + { + .name = "88pm80x-codec", + .num_resources = ARRAY_SIZE(codec_resources), + .resources = &codec_resources[0], + .id = -1, + }, +}; + +static struct regmap_irq pm805_irqs[] = { + /* INT0 */ + [PM805_IRQ_LDO_OFF] = { + .mask = PM805_INT1_HP1_SHRT, + }, + [PM805_IRQ_SRC_DPLL_LOCK] = { + .mask = PM805_INT1_HP2_SHRT, + }, + [PM805_IRQ_CLIP_FAULT] = { + .mask = PM805_INT1_MIC_CONFLICT, + }, + [PM805_IRQ_MIC_CONFLICT] = { + .mask = PM805_INT1_CLIP_FAULT, + }, + [PM805_IRQ_HP2_SHRT] = { + .mask = PM805_INT1_LDO_OFF, + }, + [PM805_IRQ_HP1_SHRT] = { + .mask = PM805_INT1_SRC_DPLL_LOCK, + }, + /* INT1 */ + [PM805_IRQ_FINE_PLL_FAULT] = { + .reg_offset = 1, + .mask = PM805_INT2_MIC_DET, + }, + [PM805_IRQ_RAW_PLL_FAULT] = { + .reg_offset = 1, + .mask = PM805_INT2_SHRT_BTN_DET, + }, + [PM805_IRQ_VOLP_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_VOLM_BTN_DET, + }, + [PM805_IRQ_VOLM_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_VOLP_BTN_DET, + }, + [PM805_IRQ_SHRT_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_RAW_PLL_FAULT, + }, + [PM805_IRQ_MIC_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_FINE_PLL_FAULT, + }, +}; + +static int __devinit device_irq_init_805(struct pm80x_chip *chip) +{ + struct regmap *map = chip->regmap; + unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + int data, mask, ret = -EINVAL; + + if (!map || !chip->irq) { + dev_err(chip->dev, "incorrect parameters\n"); + return -EINVAL; + } + + /* + * irq_mode defines the way of clearing interrupt. it's read-clear by + * default. + */ + mask = + PM805_STATUS0_INT_CLEAR | PM805_STATUS0_INV_INT | + PM800_STATUS0_INT_MASK; + + data = PM805_STATUS0_INT_CLEAR; + ret = regmap_update_bits(map, PM805_INT_STATUS0, mask, data); + /* + * PM805_INT_STATUS is under 32K clock domain, so need to + * add proper delay before the next I2C register access. + */ + msleep(1); + + if (ret < 0) + goto out; + + ret = + regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1, + chip->regmap_irq_chip, &chip->irq_data); + +out: + return ret; +} + +static void device_irq_exit_805(struct pm80x_chip *chip) +{ + regmap_del_irq_chip(chip->irq, chip->irq_data); +} + +static struct regmap_irq_chip pm805_irq_chip = { + .name = "88pm805", + .irqs = pm805_irqs, + .num_irqs = ARRAY_SIZE(pm805_irqs), + + .num_regs = 2, + .status_base = PM805_INT_STATUS1, + .mask_base = PM805_INT_MASK1, + .ack_base = PM805_INT_STATUS1, +}; + +static int __devinit device_805_init(struct pm80x_chip *chip) +{ + int ret = 0; + struct regmap *map = chip->regmap; + + if (!map) { + dev_err(chip->dev, "regmap is invalid\n"); + return -EINVAL; + } + + regmap_read(map, PM805_CHIP_ID, &ret); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + goto out_irq_init; + } + chip->version = ret; + + chip->regmap_irq_chip = &pm805_irq_chip; + + ret = device_irq_init_805(chip); + if (ret < 0) { + dev_err(chip->dev, "Failed to init pm805 irq!\n"); + goto out_irq_init; + } + + ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add codec subdev\n"); + goto out_codec; + } else + dev_info(chip->dev, "[%s]:Added mfd codec_devs\n", __func__); + + return 0; + +out_codec: + device_irq_exit_805(chip); +out_irq_init: + return ret; +} + +static int __devinit pm805_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct pm80x_chip *chip; + struct pm80x_platform_data *pdata = client->dev.platform_data; + + ret = pm80x_init(client, id); + if (ret) { + dev_err(&client->dev, "pm805_init fail!\n"); + goto out_init; + } + + chip = i2c_get_clientdata(client); + + ret = device_805_init(chip); + if (ret) { + dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + goto err_805_init; + } + + if (pdata->plat_config) + pdata->plat_config(chip, pdata); + +err_805_init: + pm80x_deinit(client); +out_init: + return ret; +} + +static int __devexit pm805_remove(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + mfd_remove_devices(chip->dev); + device_irq_exit_805(chip); + + pm80x_deinit(client); + + return 0; +} + +static struct i2c_driver pm805_driver = { + .driver = { + .name = "88PM80X", + .owner = THIS_MODULE, + .pm = &pm80x_pm_ops, + }, + .probe = pm805_probe, + .remove = __devexit_p(pm805_remove), + .id_table = pm80x_id_table, +}; + +static int __init pm805_i2c_init(void) +{ + return i2c_add_driver(&pm805_driver); +} +subsys_initcall(pm805_i2c_init); + +static void __exit pm805_i2c_exit(void) +{ + i2c_del_driver(&pm805_driver); +} +module_exit(pm805_i2c_exit); + +MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM805"); +MODULE_AUTHOR("Qiao Zhou "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c new file mode 100644 index 000000000000..90aa18a37f79 --- /dev/null +++ b/drivers/mfd/88pm80x.c @@ -0,0 +1,116 @@ +/* + * I2C driver for Marvell 88PM80x + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang + * Joseph(Yossi) Hanin + * Qiao Zhou + * + * 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 + + +const struct regmap_config pm80x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +int __devinit pm80x_init(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pm80x_chip *chip; + struct regmap *map; + int ret = 0; + + chip = + devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + map = devm_regmap_init_i2c(client, &pm80x_regmap_config); + if (IS_ERR(map)) { + ret = PTR_ERR(map); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + ret); + goto err_regmap_init; + } + + chip->id = id->driver_data; + if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) { + ret = -EINVAL; + goto err_chip_id; + } + + chip->client = client; + chip->regmap = map; + + chip->irq = client->irq; + + chip->dev = &client->dev; + dev_set_drvdata(chip->dev, chip); + i2c_set_clientdata(chip->client, chip); + + device_init_wakeup(&client->dev, 1); + + return 0; + +err_chip_id: + regmap_exit(map); +err_regmap_init: + devm_kfree(&client->dev, chip); + return ret; +} +EXPORT_SYMBOL_GPL(pm80x_init); + +int __devexit pm80x_deinit(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + regmap_exit(chip->regmap); + devm_kfree(&client->dev, chip); + + return 0; +} +EXPORT_SYMBOL_GPL(pm80x_deinit); + +#ifdef CONFIG_PM_SLEEP +static int pm80x_suspend(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct pm80x_chip *chip = i2c_get_clientdata(client); + + if (chip && chip->wu_flag) + if (device_may_wakeup(chip->dev)) + enable_irq_wake(chip->irq); + + return 0; +} + +static int pm80x_resume(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct pm80x_chip *chip = i2c_get_clientdata(client); + + if (chip && chip->wu_flag) + if (device_may_wakeup(chip->dev)) + disable_irq_wake(chip->irq); + + return 0; +} +#endif + +SIMPLE_DEV_PM_OPS(pm80x_pm_ops, pm80x_suspend, pm80x_resume); +EXPORT_SYMBOL_GPL(pm80x_pm_ops); + +MODULE_DESCRIPTION("I2C Driver for Marvell 88PM80x"); +MODULE_AUTHOR("Qiao Zhou "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 5c043693f52c..9c3ab2ab7dc7 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -21,6 +21,30 @@ config MFD_88PM860X select individual components like voltage regulators, RTC and battery-charger under the corresponding menus. +config MFD_88PM800 + tristate "Support Marvell 88PM800" + depends on I2C=y && GENERIC_HARDIRQS + select REGMAP_I2C + select REGMAP_IRQ + select MFD_CORE + help + This supports for Marvell 88PM800 Power Management IC. + This includes the I2C driver and the core APIs _only_, you have to + select individual components like voltage regulators, RTC and + battery-charger under the corresponding menus. + +config MFD_88PM805 + tristate "Support Marvell 88PM805" + depends on I2C=y && GENERIC_HARDIRQS + select REGMAP_I2C + select REGMAP_IRQ + select MFD_CORE + help + This supports for Marvell 88PM805 Power Management IC. This includes + the I2C driver and the core APIs _only_, you have to select individual + components like codec device, headset/Mic device under the + corresponding menus. + config MFD_SM501 tristate "Support for Silicon Motion SM501" ---help--- diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f28885bb103c..09674a99eb60 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -4,6 +4,8 @@ 88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o +obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o +obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h new file mode 100644 index 000000000000..6c126e9714a3 --- /dev/null +++ b/include/linux/mfd/88pm80x.h @@ -0,0 +1,368 @@ +/* + * Marvell 88PM80x Interface + * + * Copyright (C) 2012 Marvell International Ltd. + * Qiao Zhou + * + * 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 __LINUX_MFD_88PM80X_H +#define __LINUX_MFD_88PM80X_H + +#include +#include +#include +#include + +#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */ +enum { + CHIP_INVALID = 0, + CHIP_PM800, + CHIP_PM805, + CHIP_MAX, +}; + +enum { + PM800_ID_BUCK1 = 0, + PM800_ID_BUCK2, + PM800_ID_BUCK3, + PM800_ID_BUCK4, + PM800_ID_BUCK5, + + PM800_ID_LDO1, + PM800_ID_LDO2, + PM800_ID_LDO3, + PM800_ID_LDO4, + PM800_ID_LDO5, + PM800_ID_LDO6, + PM800_ID_LDO7, + PM800_ID_LDO8, + PM800_ID_LDO9, + PM800_ID_LDO10, + PM800_ID_LDO11, + PM800_ID_LDO12, + PM800_ID_LDO13, + PM800_ID_LDO14, + PM800_ID_LDO15, + PM800_ID_LDO16, + PM800_ID_LDO17, + PM800_ID_LDO18, + PM800_ID_LDO19, + + PM800_ID_RG_MAX, +}; +#define PM800_MAX_REGULATOR PM800_ID_RG_MAX /* 5 Bucks, 19 LDOs */ +#define PM800_NUM_BUCK (5) /*5 Bucks */ +#define PM800_NUM_LDO (19) /*19 Bucks */ + +/* page 0 basic: slave adder 0x60 */ + +#define PM800_STATUS_1 (0x01) +#define PM800_ONKEY_STS1 (1 << 0) +#define PM800_EXTON_STS1 (1 << 1) +#define PM800_CHG_STS1 (1 << 2) +#define PM800_BAT_STS1 (1 << 3) +#define PM800_VBUS_STS1 (1 << 4) +#define PM800_LDO_PGOOD_STS1 (1 << 5) +#define PM800_BUCK_PGOOD_STS1 (1 << 6) + +#define PM800_STATUS_2 (0x02) +#define PM800_RTC_ALARM_STS2 (1 << 0) + +/* Wakeup Registers */ +#define PM800_WAKEUP1 (0x0D) + +#define PM800_WAKEUP2 (0x0E) +#define PM800_WAKEUP2_INV_INT (1 << 0) +#define PM800_WAKEUP2_INT_CLEAR (1 << 1) +#define PM800_WAKEUP2_INT_MASK (1 << 2) + +#define PM800_POWER_UP_LOG (0x10) + +/* Referance and low power registers */ +#define PM800_LOW_POWER1 (0x20) +#define PM800_LOW_POWER2 (0x21) +#define PM800_LOW_POWER_CONFIG3 (0x22) +#define PM800_LOW_POWER_CONFIG4 (0x23) + +/* GPIO register */ +#define PM800_GPIO_0_1_CNTRL (0x30) +#define PM800_GPIO0_VAL (1 << 0) +#define PM800_GPIO0_GPIO_MODE(x) (x << 1) +#define PM800_GPIO1_VAL (1 << 4) +#define PM800_GPIO1_GPIO_MODE(x) (x << 5) + +#define PM800_GPIO_2_3_CNTRL (0x31) +#define PM800_GPIO2_VAL (1 << 0) +#define PM800_GPIO2_GPIO_MODE(x) (x << 1) +#define PM800_GPIO3_VAL (1 << 4) +#define PM800_GPIO3_GPIO_MODE(x) (x << 5) +#define PM800_GPIO3_MODE_MASK 0x1F +#define PM800_GPIO3_HEADSET_MODE PM800_GPIO3_GPIO_MODE(6) + +#define PM800_GPIO_4_CNTRL (0x32) +#define PM800_GPIO4_VAL (1 << 0) +#define PM800_GPIO4_GPIO_MODE(x) (x << 1) + +#define PM800_HEADSET_CNTRL (0x38) +#define PM800_HEADSET_DET_EN (1 << 7) +#define PM800_HSDET_SLP (1 << 1) +/* PWM register */ +#define PM800_PWM1 (0x40) +#define PM800_PWM2 (0x41) +#define PM800_PWM3 (0x42) +#define PM800_PWM4 (0x43) + +/* RTC Registers */ +#define PM800_RTC_CONTROL (0xD0) +#define PM800_RTC_MISC1 (0xE1) +#define PM800_RTC_MISC2 (0xE2) +#define PM800_RTC_MISC3 (0xE3) +#define PM800_RTC_MISC4 (0xE4) +#define PM800_RTC_MISC5 (0xE7) +/* bit definitions of RTC Register 1 (0xD0) */ +#define PM800_ALARM1_EN (1 << 0) +#define PM800_ALARM_WAKEUP (1 << 4) +#define PM800_ALARM (1 << 5) +#define PM800_RTC1_USE_XO (1 << 7) + +/* Regulator Control Registers: BUCK1,BUCK5,LDO1 have DVC */ + +/* buck registers */ +#define PM800_SLEEP_BUCK1 (0x30) + +/* BUCK Sleep Mode Register 1: BUCK[1..4] */ +#define PM800_BUCK_SLP1 (0x5A) +#define PM800_BUCK1_SLP1_SHIFT 0 +#define PM800_BUCK1_SLP1_MASK (0x3 << PM800_BUCK1_SLP1_SHIFT) + +/* page 2 GPADC: slave adder 0x02 */ +#define PM800_GPADC_MEAS_EN1 (0x01) +#define PM800_MEAS_EN1_VBAT (1 << 2) +#define PM800_GPADC_MEAS_EN2 (0x02) +#define PM800_MEAS_EN2_RFTMP (1 << 0) +#define PM800_MEAS_GP0_EN (1 << 2) +#define PM800_MEAS_GP1_EN (1 << 3) +#define PM800_MEAS_GP2_EN (1 << 4) +#define PM800_MEAS_GP3_EN (1 << 5) +#define PM800_MEAS_GP4_EN (1 << 6) + +#define PM800_GPADC_MISC_CONFIG1 (0x05) +#define PM800_GPADC_MISC_CONFIG2 (0x06) +#define PM800_GPADC_MISC_GPFSM_EN (1 << 0) +#define PM800_GPADC_SLOW_MODE(x) (x << 3) + +#define PM800_GPADC_MISC_CONFIG3 (0x09) +#define PM800_GPADC_MISC_CONFIG4 (0x0A) + +#define PM800_GPADC_PREBIAS1 (0x0F) +#define PM800_GPADC0_GP_PREBIAS_TIME(x) (x << 0) +#define PM800_GPADC_PREBIAS2 (0x10) + +#define PM800_GP_BIAS_ENA1 (0x14) +#define PM800_GPADC_GP_BIAS_EN0 (1 << 0) +#define PM800_GPADC_GP_BIAS_EN1 (1 << 1) +#define PM800_GPADC_GP_BIAS_EN2 (1 << 2) +#define PM800_GPADC_GP_BIAS_EN3 (1 << 3) + +#define PM800_GP_BIAS_OUT1 (0x15) +#define PM800_BIAS_OUT_GP0 (1 << 0) +#define PM800_BIAS_OUT_GP1 (1 << 1) +#define PM800_BIAS_OUT_GP2 (1 << 2) +#define PM800_BIAS_OUT_GP3 (1 << 3) + +#define PM800_GPADC0_LOW_TH 0x20 +#define PM800_GPADC1_LOW_TH 0x21 +#define PM800_GPADC2_LOW_TH 0x22 +#define PM800_GPADC3_LOW_TH 0x23 +#define PM800_GPADC4_LOW_TH 0x24 + +#define PM800_GPADC0_UPP_TH 0x30 +#define PM800_GPADC1_UPP_TH 0x31 +#define PM800_GPADC2_UPP_TH 0x32 +#define PM800_GPADC3_UPP_TH 0x33 +#define PM800_GPADC4_UPP_TH 0x34 + +#define PM800_VBBAT_MEAS1 0x40 +#define PM800_VBBAT_MEAS2 0x41 +#define PM800_VBAT_MEAS1 0x42 +#define PM800_VBAT_MEAS2 0x43 +#define PM800_VSYS_MEAS1 0x44 +#define PM800_VSYS_MEAS2 0x45 +#define PM800_VCHG_MEAS1 0x46 +#define PM800_VCHG_MEAS2 0x47 +#define PM800_TINT_MEAS1 0x50 +#define PM800_TINT_MEAS2 0x51 +#define PM800_PMOD_MEAS1 0x52 +#define PM800_PMOD_MEAS2 0x53 + +#define PM800_GPADC0_MEAS1 0x54 +#define PM800_GPADC0_MEAS2 0x55 +#define PM800_GPADC1_MEAS1 0x56 +#define PM800_GPADC1_MEAS2 0x57 +#define PM800_GPADC2_MEAS1 0x58 +#define PM800_GPADC2_MEAS2 0x59 +#define PM800_GPADC3_MEAS1 0x5A +#define PM800_GPADC3_MEAS2 0x5B +#define PM800_GPADC4_MEAS1 0x5C +#define PM800_GPADC4_MEAS2 0x5D + +#define PM800_GPADC4_AVG1 0xA8 +#define PM800_GPADC4_AVG2 0xA9 + +/* 88PM805 Registers */ +#define PM805_MAIN_POWERUP (0x01) +#define PM805_INT_STATUS0 (0x02) /* for ena/dis all interrupts */ + +#define PM805_STATUS0_INT_CLEAR (1 << 0) +#define PM805_STATUS0_INV_INT (1 << 1) +#define PM800_STATUS0_INT_MASK (1 << 2) + +#define PM805_INT_STATUS1 (0x03) + +#define PM805_INT1_HP1_SHRT (1 << 0) +#define PM805_INT1_HP2_SHRT (1 << 1) +#define PM805_INT1_MIC_CONFLICT (1 << 2) +#define PM805_INT1_CLIP_FAULT (1 << 3) +#define PM805_INT1_LDO_OFF (1 << 4) +#define PM805_INT1_SRC_DPLL_LOCK (1 << 5) + +#define PM805_INT_STATUS2 (0x04) + +#define PM805_INT2_MIC_DET (1 << 0) +#define PM805_INT2_SHRT_BTN_DET (1 << 1) +#define PM805_INT2_VOLM_BTN_DET (1 << 2) +#define PM805_INT2_VOLP_BTN_DET (1 << 3) +#define PM805_INT2_RAW_PLL_FAULT (1 << 4) +#define PM805_INT2_FINE_PLL_FAULT (1 << 5) + +#define PM805_INT_MASK1 (0x05) +#define PM805_INT_MASK2 (0x06) +#define PM805_SHRT_BTN_DET (1 << 1) + +/* number of status and int reg in a row */ +#define PM805_INT_REG_NUM (2) + +#define PM805_MIC_DET1 (0x07) +#define PM805_MIC_DET_EN_MIC_DET (1 << 0) +#define PM805_MIC_DET2 (0x08) +#define PM805_MIC_DET_STATUS1 (0x09) + +#define PM805_MIC_DET_STATUS3 (0x0A) +#define PM805_AUTO_SEQ_STATUS1 (0x0B) +#define PM805_AUTO_SEQ_STATUS2 (0x0C) + +#define PM805_ADC_SETTING1 (0x10) +#define PM805_ADC_SETTING2 (0x11) +#define PM805_ADC_SETTING3 (0x11) +#define PM805_ADC_GAIN1 (0x12) +#define PM805_ADC_GAIN2 (0x13) +#define PM805_DMIC_SETTING (0x15) +#define PM805_DWS_SETTING (0x16) +#define PM805_MIC_CONFLICT_STS (0x17) + +#define PM805_PDM_SETTING1 (0x20) +#define PM805_PDM_SETTING2 (0x21) +#define PM805_PDM_SETTING3 (0x22) +#define PM805_PDM_CONTROL1 (0x23) +#define PM805_PDM_CONTROL2 (0x24) +#define PM805_PDM_CONTROL3 (0x25) + +#define PM805_HEADPHONE_SETTING (0x26) +#define PM805_HEADPHONE_GAIN_A2A (0x27) +#define PM805_HEADPHONE_SHORT_STATE (0x28) +#define PM805_EARPHONE_SETTING (0x29) +#define PM805_AUTO_SEQ_SETTING (0x2A) + +struct pm80x_rtc_pdata { + int vrtc; + int rtc_wakeup; +}; + +struct pm80x_subchip { + struct i2c_client *power_page; /* chip client for power page */ + struct i2c_client *gpadc_page; /* chip client for gpadc page */ + struct regmap *regmap_power; + struct regmap *regmap_gpadc; + unsigned short power_page_addr; /* power page I2C address */ + unsigned short gpadc_page_addr; /* gpadc page I2C address */ +}; + +struct pm80x_chip { + struct pm80x_subchip *subchip; + struct device *dev; + struct i2c_client *client; + struct regmap *regmap; + struct regmap_irq_chip *regmap_irq_chip; + struct regmap_irq_chip_data *irq_data; + unsigned char version; + int id; + int irq; + int irq_mode; + unsigned long wu_flag; + spinlock_t lock; +}; + +struct pm80x_platform_data { + struct pm80x_rtc_pdata *rtc; + unsigned short power_page_addr; /* power page I2C address */ + unsigned short gpadc_page_addr; /* gpadc page I2C address */ + int irq_mode; /* Clear interrupt by read/write(0/1) */ + int batt_det; /* enable/disable */ + int (*plat_config)(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata); +}; + +extern const struct dev_pm_ops pm80x_pm_ops; +extern const struct regmap_config pm80x_regmap_config; + +static inline int pm80x_request_irq(struct pm80x_chip *pm80x, int irq, + irq_handler_t handler, unsigned long flags, + const char *name, void *data) +{ + if (!pm80x->irq_data) + return -EINVAL; + return request_threaded_irq(regmap_irq_get_virq(pm80x->irq_data, irq), + NULL, handler, flags, name, data); +} + +static inline void pm80x_free_irq(struct pm80x_chip *pm80x, int irq, void *data) +{ + if (!pm80x->irq_data) + return; + free_irq(regmap_irq_get_virq(pm80x->irq_data, irq), data); +} + +#ifdef CONFIG_PM +static inline int pm80x_dev_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + int irq = platform_get_irq(pdev, 0); + + if (device_may_wakeup(dev)) + set_bit((1 << irq), &chip->wu_flag); + + return 0; +} + +static inline int pm80x_dev_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + int irq = platform_get_irq(pdev, 0); + + if (device_may_wakeup(dev)) + clear_bit((1 << irq), &chip->wu_flag); + + return 0; +} +#endif + +extern int pm80x_init(struct i2c_client *client, + const struct i2c_device_id *id) __devinit; +extern int pm80x_deinit(struct i2c_client *client) __devexit; +#endif /* __LINUX_MFD_88PM80X_H */ -- GitLab From 5500e3964b8c154dc5af51ebcd7cd4df5d4abfee Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Mon, 9 Jul 2012 14:37:33 +0800 Subject: [PATCH 2303/5711] mfd: Add companion chip in 88pm80x in hw design, 800 is mainly for pmic control, while 805 for audio. but there are 3 registers which controls class D speaker property, and they are defined in 800 i2c client domain. so 805 codec driver needs to use 800 i2c client to access class D speaker reg for audio path management. so add this workaround for the purpose to let 805 access 800 i2c in some scenario. Signed-off-by: Qiao Zhou Reviewed-by: Arnd Bergmann Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm80x.c | 28 ++++++++++++++++++++++++++++ include/linux/mfd/88pm80x.h | 1 + 2 files changed, 29 insertions(+) diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index 90aa18a37f79..77b865594c29 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -18,6 +18,12 @@ #include #include +/* + * workaround: some registers needed by pm805 are defined in pm800, so + * need to use this global variable to maintain the relation between + * pm800 and pm805. would remove it after HW chip fixes the issue. + */ +static struct pm80x_chip *g_pm80x_chip; const struct regmap_config pm80x_regmap_config = { .reg_bits = 8, @@ -61,6 +67,19 @@ int __devinit pm80x_init(struct i2c_client *client, device_init_wakeup(&client->dev, 1); + /* + * workaround: set g_pm80x_chip to the first probed chip. if the + * second chip is probed, just point to the companion to each + * other so that pm805 can access those specific register. would + * remove it after HW chip fixes the issue. + */ + if (!g_pm80x_chip) + g_pm80x_chip = chip; + else { + chip->companion = g_pm80x_chip->client; + g_pm80x_chip->companion = chip->client; + } + return 0; err_chip_id: @@ -75,6 +94,15 @@ int __devexit pm80x_deinit(struct i2c_client *client) { struct pm80x_chip *chip = i2c_get_clientdata(client); + /* + * workaround: clear the dependency between pm800 and pm805. + * would remove it after HW chip fixes the issue. + */ + if (g_pm80x_chip->companion) + g_pm80x_chip->companion = NULL; + else + g_pm80x_chip = NULL; + regmap_exit(chip->regmap); devm_kfree(&client->dev, chip); diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 6c126e9714a3..103f06d1892d 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -295,6 +295,7 @@ struct pm80x_chip { struct pm80x_subchip *subchip; struct device *dev; struct i2c_client *client; + struct i2c_client *companion; struct regmap *regmap; struct regmap_irq_chip *regmap_irq_chip; struct regmap_irq_chip_data *irq_data; -- GitLab From 17ffba6ad235cf9c21937ee1343df0d0fb2371fa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 7 Jul 2012 08:51:03 +1000 Subject: [PATCH 2304/5711] mfd: Move twl-core device_init_wakeup to after platform_device_add device_init_wakeup uses the dev_name() of the device to set the name of the wakeup_source which appears in /sys/kernel/debug/wakeup_sources. For a platform device, that name is not set until platform_device_add calls dev_set_name. So the call to device_init_wakeup() must be after the call to platform_device_add(). Making this change causes correct names to appear in the wakeup_sources file. Signed-off-by: NeilBrown Acked-by: Rafael J. Wysocki Signed-off-by: Samuel Ortiz --- drivers/mfd/twl-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 6fc90befa79e..b012efd29e01 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -568,7 +568,6 @@ add_numbered_child(unsigned chip, const char *name, int num, goto err; } - device_init_wakeup(&pdev->dev, can_wakeup); pdev->dev.parent = &twl->client->dev; if (pdata) { @@ -593,6 +592,8 @@ add_numbered_child(unsigned chip, const char *name, int num, } status = platform_device_add(pdev); + if (status == 0) + device_init_wakeup(&pdev->dev, can_wakeup); err: if (status < 0) { -- GitLab From 84d70ee78bb0c3d8d1d8df74565d010e2e3c31a9 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Thu, 5 Jul 2012 09:28:20 +0530 Subject: [PATCH 2305/5711] mfd: Use pmic regmap to read max77686 pmic interrupt register PMIC's regmap should be used to read pmic interrupt registers. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c index fc101220f990..09e593ad07b5 100644 --- a/drivers/mfd/max77686-irq.c +++ b/drivers/mfd/max77686-irq.c @@ -180,7 +180,7 @@ static irqreturn_t max77686_irq_thread(int irq, void *data) pr_info("%s: irq_src=0x%x\n", __func__, irq_src); if (irq_src == MAX77686_IRQSRC_PMIC) { - ret = regmap_bulk_read(max77686->rtc_regmap, + ret = regmap_bulk_read(max77686->regmap, MAX77686_REG_INT1, irq_reg, 2); if (ret < 0) { dev_err(max77686->dev, "Failed to read interrupt source: %d\n", -- GitLab From 9bdf9b4ec7c8b707cd0d9109d576c4eb69cd84bb Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Thu, 5 Jul 2012 09:28:21 +0530 Subject: [PATCH 2306/5711] mfd: Apply irq_mask_cur before handling max77686 interrupts According to TRM, though we mask the interrupts in interrupt-mask register, interrupt source-register still provide the status of the masked interrupts. So we should apply irq_mask_cur to read interrupt source-register value before handling. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686-irq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c index 09e593ad07b5..0758fac0c447 100644 --- a/drivers/mfd/max77686-irq.c +++ b/drivers/mfd/max77686-irq.c @@ -208,6 +208,9 @@ static irqreturn_t max77686_irq_thread(int irq, void *data) } + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) + irq_reg[i] &= ~max77686->irq_masks_cur[i]; + for (i = 0; i < MAX77686_IRQ_NR; i++) { if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) { cur_irq = irq_find_mapping(max77686->irq_domain, i); -- GitLab From 2b40459b7ee502c970d9f1dcf94dfa4d58ec1d85 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Mon, 9 Jul 2012 13:21:45 +0200 Subject: [PATCH 2307/5711] mfd: Allow to specify max77686 interrupt through DT or platform file also Presently driver expects irq_gpio pin in platform data and maps it to irq itself. But we can also directly specify the interrupt in DT or platform file. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686-irq.c | 33 ++++++++++++++++++++------------- drivers/mfd/max77686.c | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c index 0758fac0c447..cdc3280e2ec7 100644 --- a/drivers/mfd/max77686-irq.c +++ b/drivers/mfd/max77686-irq.c @@ -252,21 +252,28 @@ int max77686_irq_init(struct max77686_dev *max77686) mutex_init(&max77686->irqlock); - max77686->irq = gpio_to_irq(max77686->irq_gpio); - - if (debug_mask & MAX77686_DEBUG_IRQ_INT) { - ret = gpio_request(max77686->irq_gpio, "pmic_irq"); - if (ret < 0) { - dev_err(max77686->dev, - "Failed to request gpio %d with ret: %d\n", - max77686->irq_gpio, ret); - return IRQ_NONE; + if (max77686->irq_gpio && !max77686->irq) { + max77686->irq = gpio_to_irq(max77686->irq_gpio); + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) { + ret = gpio_request(max77686->irq_gpio, "pmic_irq"); + if (ret < 0) { + dev_err(max77686->dev, + "Failed to request gpio %d with ret:" + "%d\n", max77686->irq_gpio, ret); + return IRQ_NONE; + } + + gpio_direction_input(max77686->irq_gpio); + val = gpio_get_value(max77686->irq_gpio); + gpio_free(max77686->irq_gpio); + pr_info("%s: gpio_irq=%x\n", __func__, val); } + } - gpio_direction_input(max77686->irq_gpio); - val = gpio_get_value(max77686->irq_gpio); - gpio_free(max77686->irq_gpio); - pr_info("%s: gpio_irq=%x\n", __func__, val); + if (!max77686->irq) { + dev_err(max77686->dev, "irq is not specified\n"); + return -ENODEV; } /* Mask individual interrupt sources */ diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 9e7e1d30f25f..c66639d681e9 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -77,6 +77,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->wakeup = pdata->wakeup; max77686->irq_gpio = pdata->irq_gpio; + max77686->irq = i2c->irq; if (regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data) < 0) { -- GitLab From c1516f840dcd91e76712a047993e09d95034a66d Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Fri, 6 Jul 2012 17:02:55 +0530 Subject: [PATCH 2308/5711] mfd: Add device tree support for max77686 This patch adds device tree support for mfd driver and adds Documentation/devicetree/bindings/mfd/max77686.txt. This patch also intialize max77686 pointer to NULL in max77686_i2c_probe to silent a compile time warning. Signed-off-by: Yadwinder Singh Brar Reviwed-by: Mark Brown Signed-off-by: Samuel Ortiz --- .../devicetree/bindings/mfd/max77686.txt | 59 +++++++++++++++++++ drivers/mfd/max77686.c | 45 ++++++++++++-- 2 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/max77686.txt diff --git a/Documentation/devicetree/bindings/mfd/max77686.txt b/Documentation/devicetree/bindings/mfd/max77686.txt new file mode 100644 index 000000000000..c6a3469d3436 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max77686.txt @@ -0,0 +1,59 @@ +Maxim MAX77686 multi-function device + +MAX77686 is a Mulitifunction device with PMIC, RTC and Charger on chip. It is +interfaced to host controller using i2c interface. PMIC and Charger submodules +are addressed using same i2c slave address whereas RTC submodule uses +different i2c slave address,presently for which we are statically creating i2c +client while probing.This document describes the binding for mfd device and +PMIC submodule. + +Required properties: +- compatible : Must be "maxim,max77686"; +- reg : Specifies the i2c slave address of PMIC block. +- interrupts : This i2c device has an IRQ line connected to the main SoC. +- interrupt-parent : The parent interrupt controller. + +Optional node: +- voltage-regulators : The regulators of max77686 have to be instantiated + under subnode named "voltage-regulators" using the following format. + + regulator_name { + regulator-compatible = LDOn/BUCKn + standard regulator constraints.... + }; + refer Documentation/devicetree/bindings/regulator/regulator.txt + + The regulator-compatible property of regulator should initialized with string +to get matched with their hardware counterparts as follow: + + -LDOn : for LDOs, where n can lie in range 1 to 26. + example: LDO1, LDO2, LDO26. + -BUCKn : for BUCKs, where n can lie in range 1 to 9. + example: BUCK1, BUCK5, BUCK9. + +Example: + + max77686@09 { + compatible = "maxim,max77686"; + interrupt-parent = <&wakeup_eint>; + interrupts = <26 0>; + reg = <0x09>; + + voltage-regulators { + ldo11_reg { + regulator-compatible = "LDO11"; + regulator-name = "vdd_ldo11"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + regulator-always-on; + }; + + buck1_reg { + regulator-compatible = "BUCK1"; + regulator-name = "vdd_mif"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + } diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c66639d681e9..3e31d05906b2 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -34,6 +34,11 @@ #define I2C_ADDR_RTC (0x0C >> 1) +static struct of_device_id __devinitdata max77686_pmic_dt_match[] = { + {.compatible = "maxim,max77686", .data = 0}, + {}, +}; + static struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, { .name = "max77686-rtc", }, @@ -44,14 +49,46 @@ static struct regmap_config max77686_regmap_config = { .val_bits = 8, }; +#ifdef CONFIG_OF +static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device + *dev) +{ + struct max77686_platform_data *pd; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + dev_err(dev, "could not allocate memory for pdata\n"); + return NULL; + } + + dev->platform_data = pd; + return pd; +} +#else +static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device + *dev) +{ + return 0; +} +#endif + static int max77686_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct max77686_dev *max77686; + struct max77686_dev *max77686 = NULL; struct max77686_platform_data *pdata = i2c->dev.platform_data; unsigned int data; int ret = 0; + if (i2c->dev.of_node) + pdata = max77686_i2c_parse_dt_pdata(&i2c->dev); + + if (!pdata) { + ret = -EIO; + dev_err(&i2c->dev, "No platform data found.\n"); + goto err; + } + max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL); if (max77686 == NULL) return -ENOMEM; @@ -70,11 +107,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->i2c = i2c; max77686->type = id->driver_data; - if (!pdata) { - ret = -EIO; - goto err; - } - max77686->wakeup = pdata->wakeup; max77686->irq_gpio = pdata->irq_gpio; max77686->irq = i2c->irq; @@ -130,6 +162,7 @@ static struct i2c_driver max77686_i2c_driver = { .driver = { .name = "max77686", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max77686_pmic_dt_match), }, .probe = max77686_i2c_probe, .remove = max77686_i2c_remove, -- GitLab From a232d56e48024c41c87ba884cc0a0fc98e37f5c6 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Thu, 5 Jul 2012 09:28:24 +0530 Subject: [PATCH 2309/5711] mfd: Remove the clocks from the list of max77686 regulators Remove the clocks from the list of regulators to correct the value of MAX77686_REG_MAX which is used in the regulator driver to represent the no. of regulators present in max77686. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Samuel Ortiz --- include/linux/mfd/max77686.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h index fcf312678cac..3d7ae4d7fd36 100644 --- a/include/linux/mfd/max77686.h +++ b/include/linux/mfd/max77686.h @@ -67,9 +67,6 @@ enum max77686_regulators { MAX77686_BUCK7, MAX77686_BUCK8, MAX77686_BUCK9, - MAX77686_EN32KHZ_AP, - MAX77686_EN32KHZ_CP, - MAX77686_P32KH, MAX77686_REG_MAX, }; -- GitLab From 31b3ffbdfb4e4d2d2416c30fe02da3e58e37d798 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 9 Jul 2012 15:11:46 +0200 Subject: [PATCH 2310/5711] mfd: 88pm80[05] i2c device_id arrays should be NULL terminated Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 1 + drivers/mfd/88pm805.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index fe479ccfaa19..ec7d9b8c7844 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -127,6 +127,7 @@ enum { static const struct i2c_device_id pm80x_id_table[] = { {"88PM800", CHIP_PM800}, + {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index d93c3091cb9f..d59ca6bae096 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -33,6 +33,7 @@ static const struct i2c_device_id pm80x_id_table[] = { {"88PM805", CHIP_PM805}, + {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); -- GitLab From af65a361d543100962c03cc4cdb7333b14c9d119 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 11:56:43 +0100 Subject: [PATCH 2311/5711] mfd: Error out if initial arizona boot fails Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 5cbacf6e2bf7..ffa011f4677e 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -398,7 +398,11 @@ int __devinit arizona_dev_init(struct arizona *arizona) } } - arizona_wait_for_boot(arizona); + ret = arizona_wait_for_boot(arizona); + if (ret != 0) { + dev_err(arizona->dev, "Device failed initial boot: %d\n", ret); + goto err_reset; + } for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { if (!arizona->pdata.gpio_defaults[i]) -- GitLab From 2985c29c196418b8f666bc9240c922aa56bff599 Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Mon, 9 Jul 2012 14:37:34 +0800 Subject: [PATCH 2312/5711] rtc: Add rtc support to 88PM80X PMIC add rtc driver for MARVELL 88PM80X PMIC and enable rtc function. Cc: Alessandro Zummo Signed-off-by: Qiao Zhou Signed-off-by: Samuel Ortiz --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-88pm80x.c | 371 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 drivers/rtc/rtc-88pm80x.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 08cbdb900a18..f049c02413ce 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -135,6 +135,16 @@ config RTC_DRV_88PM860X This driver can also be built as a module. If so, the module will be called rtc-88pm860x. +config RTC_DRV_88PM80X + tristate "Marvell 88PM80x" + depends on RTC_CLASS && I2C && MFD_88PM800 + help + If you say yes here you get support for RTC function in Marvell + 88PM80x chips. + + This driver can also be built as a module. If so, the module + will be called rtc-88pm80x. + config RTC_DRV_DS1307 tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 2973921c30d8..0d5b2b66f90d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,6 +16,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o # Keep the list ordered. obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o +obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c new file mode 100644 index 000000000000..a2f956d90de0 --- /dev/null +++ b/drivers/rtc/rtc-88pm80x.c @@ -0,0 +1,371 @@ +/* + * Real Time Clock driver for Marvell 88PM80x PMIC + * + * Copyright (c) 2012 Marvell International Ltd. + * Wenzeng Chen + * Qiao Zhou + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PM800_RTC_COUNTER1 (0xD1) +#define PM800_RTC_COUNTER2 (0xD2) +#define PM800_RTC_COUNTER3 (0xD3) +#define PM800_RTC_COUNTER4 (0xD4) +#define PM800_RTC_EXPIRE1_1 (0xD5) +#define PM800_RTC_EXPIRE1_2 (0xD6) +#define PM800_RTC_EXPIRE1_3 (0xD7) +#define PM800_RTC_EXPIRE1_4 (0xD8) +#define PM800_RTC_TRIM1 (0xD9) +#define PM800_RTC_TRIM2 (0xDA) +#define PM800_RTC_TRIM3 (0xDB) +#define PM800_RTC_TRIM4 (0xDC) +#define PM800_RTC_EXPIRE2_1 (0xDD) +#define PM800_RTC_EXPIRE2_2 (0xDE) +#define PM800_RTC_EXPIRE2_3 (0xDF) +#define PM800_RTC_EXPIRE2_4 (0xE0) + +#define PM800_POWER_DOWN_LOG1 (0xE5) +#define PM800_POWER_DOWN_LOG2 (0xE6) + +struct pm80x_rtc_info { + struct pm80x_chip *chip; + struct regmap *map; + struct rtc_device *rtc_dev; + struct device *dev; + struct delayed_work calib_work; + + int irq; + int vrtc; +}; + +static irqreturn_t rtc_update_handler(int irq, void *data) +{ + struct pm80x_rtc_info *info = (struct pm80x_rtc_info *)data; + int mask; + + mask = PM800_ALARM | PM800_ALARM_WAKEUP; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask | PM800_ALARM1_EN, + mask); + rtc_update_irq(info->rtc_dev, 1, RTC_AF); + return IRQ_HANDLED; +} + +static int pm80x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + + if (enabled) + regmap_update_bits(info->map, PM800_RTC_CONTROL, + PM800_ALARM1_EN, PM800_ALARM1_EN); + else + regmap_update_bits(info->map, PM800_RTC_CONTROL, + PM800_ALARM1_EN, 0); + return 0; +} + +/* + * Calculate the next alarm time given the requested alarm time mask + * and the current time. + */ +static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, + struct rtc_time *alrm) +{ + unsigned long next_time; + unsigned long now_time; + + next->tm_year = now->tm_year; + next->tm_mon = now->tm_mon; + next->tm_mday = now->tm_mday; + next->tm_hour = alrm->tm_hour; + next->tm_min = alrm->tm_min; + next->tm_sec = alrm->tm_sec; + + rtc_tm_to_time(now, &now_time); + rtc_tm_to_time(next, &next_time); + + if (next_time < now_time) { + /* Advance one day */ + next_time += 60 * 60 * 24; + rtc_time_to_tm(next_time, next); + } +} + +static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + rtc_time_to_tm(ticks, tm); + return 0; +} + +static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + if ((tm->tm_year < 70) || (tm->tm_year > 138)) { + dev_dbg(info->dev, + "Set time %d out of range. Please set time between 1970 to 2038.\n", + 1900 + tm->tm_year); + return -EINVAL; + } + rtc_tm_to_time(tm, &ticks); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + base = ticks - data; + dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + buf[0] = base & 0xFF; + buf[1] = (base >> 8) & 0xFF; + buf[2] = (base >> 16) & 0xFF; + buf[3] = (base >> 24) & 0xFF; + regmap_raw_write(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + + return 0; +} + +static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + int ret; + + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + regmap_raw_read(info->map, PM800_RTC_EXPIRE1_1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + + rtc_time_to_tm(ticks, &alrm->time); + regmap_read(info->map, PM800_RTC_CONTROL, &ret); + alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0; + alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0; + return 0; +} + +static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + struct rtc_time now_tm, alarm_tm; + unsigned long ticks, base, data; + unsigned char buf[4]; + int mask; + + regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_ALARM1_EN, 0); + + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + + rtc_time_to_tm(ticks, &now_tm); + dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks); + rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); + /* get new ticks for alarm in 24 hours */ + rtc_tm_to_time(&alarm_tm, &ticks); + dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks); + data = ticks - base; + + buf[0] = data & 0xff; + buf[1] = (data >> 8) & 0xff; + buf[2] = (data >> 16) & 0xff; + buf[3] = (data >> 24) & 0xff; + regmap_raw_write(info->map, PM800_RTC_EXPIRE1_1, buf, 4); + if (alrm->enabled) { + mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask, mask); + } else { + mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask, + PM800_ALARM | PM800_ALARM_WAKEUP); + } + return 0; +} + +static const struct rtc_class_ops pm80x_rtc_ops = { + .read_time = pm80x_rtc_read_time, + .set_time = pm80x_rtc_set_time, + .read_alarm = pm80x_rtc_read_alarm, + .set_alarm = pm80x_rtc_set_alarm, + .alarm_irq_enable = pm80x_rtc_alarm_irq_enable, +}; + +#ifdef CONFIG_PM +static int pm80x_rtc_suspend(struct device *dev) +{ + return pm80x_dev_suspend(dev); +} + +static int pm80x_rtc_resume(struct device *dev) +{ + return pm80x_dev_resume(dev); +} +#endif + +static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); + +static int __devinit pm80x_rtc_probe(struct platform_device *pdev) +{ + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm80x_platform_data *pm80x_pdata; + struct pm80x_rtc_pdata *pdata = NULL; + struct pm80x_rtc_info *info; + struct rtc_time tm; + unsigned long ticks = 0; + int ret; + + pdata = pdev->dev.platform_data; + if (pdata == NULL) + dev_warn(&pdev->dev, "No platform data!\n"); + + info = + devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->irq = platform_get_irq(pdev, 0); + if (info->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource!\n"); + ret = -EINVAL; + goto out; + } + + info->chip = chip; + info->map = chip->regmap; + if (!info->map) { + dev_err(&pdev->dev, "no regmap!\n"); + ret = -EINVAL; + goto out; + } + + info->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, info); + + ret = pm80x_request_irq(chip, info->irq, rtc_update_handler, + IRQF_ONESHOT, "rtc", info); + if (ret < 0) { + dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", + info->irq, ret); + goto out; + } + + ret = pm80x_rtc_read_time(&pdev->dev, &tm); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to read initial time.\n"); + goto out_rtc; + } + if ((tm.tm_year < 70) || (tm.tm_year > 138)) { + tm.tm_year = 70; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + ret = pm80x_rtc_set_time(&pdev->dev, &tm); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to set initial time.\n"); + goto out_rtc; + } + } + rtc_tm_to_time(&tm, &ticks); + + info->rtc_dev = rtc_device_register("88pm80x-rtc", &pdev->dev, + &pm80x_rtc_ops, THIS_MODULE); + ret = PTR_ERR(info->rtc_dev); + if (IS_ERR(info->rtc_dev)) { + dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + goto out_rtc; + } + /* + * enable internal XO instead of internal 3.25MHz clock since it can + * free running in PMIC power-down state. + */ + regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO, + PM800_RTC1_USE_XO); + + if (pdev->dev.parent->platform_data) { + pm80x_pdata = pdev->dev.parent->platform_data; + pdata = pm80x_pdata->rtc; + if (pdata) + info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup; + } + + device_init_wakeup(&pdev->dev, 1); + + return 0; +out_rtc: + pm80x_free_irq(chip, info->irq, info); +out: + devm_kfree(&pdev->dev, info); + return ret; +} + +static int __devexit pm80x_rtc_remove(struct platform_device *pdev) +{ + struct pm80x_rtc_info *info = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + rtc_device_unregister(info->rtc_dev); + pm80x_free_irq(info->chip, info->irq, info); + devm_kfree(&pdev->dev, info); + return 0; +} + +static struct platform_driver pm80x_rtc_driver = { + .driver = { + .name = "88pm80x-rtc", + .owner = THIS_MODULE, + .pm = &pm80x_rtc_pm_ops, + }, + .probe = pm80x_rtc_probe, + .remove = __devexit_p(pm80x_rtc_remove), +}; + +module_platform_driver(pm80x_rtc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Marvell 88PM80x RTC driver"); +MODULE_AUTHOR("Qiao Zhou "); +MODULE_ALIAS("platform:88pm80x-rtc"); -- GitLab From 9ea3c498962bc63748e92c31c874169ab0726324 Mon Sep 17 00:00:00 2001 From: Martlin Ettl Date: Thu, 5 Jul 2012 17:58:46 +0100 Subject: [PATCH 2313/5711] backlight: fix memory leak on obscure error path Dredged out of bugzilla Reported-by: Martlin Ettl Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=15492 Signed-off-by: Alan Cox Signed-off-by: Jiri Kosina --- drivers/video/backlight/88pm860x_bl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index f49181c73113..f75da8758adc 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -228,6 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) data->port = pdata->flags; if (data->port < 0) { dev_err(&pdev->dev, "wrong platform data is assigned"); + kfree(data); return -EINVAL; } -- GitLab From c5cf9212a368d88fe1e25797699b167f6daa64a5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 28 Jun 2012 11:19:02 -0400 Subject: [PATCH 2314/5711] EHCI: centralize controller suspend/resume This patch (as1563) removes a lot of duplicated code by moving the EHCI controller suspend/resume routines into the core driver, where the various platform drivers can invoke them as needed. Not only does this simplify these platform drivers, this also makes it easier for other platform drivers to add suspend/resume support in the future. Note: The patch does not touch the ehci-fsl.c file, because its approach to suspend and resume is so different from all the others. It will have to be handled specially by its maintainer. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-au1xxx.c | 73 ++------------------------ drivers/usb/host/ehci-hcd.c | 89 ++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-hub.c | 4 +- drivers/usb/host/ehci-msm.c | 19 ++----- drivers/usb/host/ehci-pci.c | 74 ++------------------------ drivers/usb/host/ehci-platform.c | 7 ++- drivers/usb/host/ehci-s5p.c | 61 ++-------------------- drivers/usb/host/ehci-sead3.c | 74 ++------------------------ drivers/usb/host/ehci-spear.c | 61 ++-------------------- 9 files changed, 114 insertions(+), 348 deletions(-) diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index bf7441afed16..182d39565906 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -158,28 +158,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - unsigned long flags; - int rc = 0; - - if (time_before(jiffies, ehci->next_statechange)) - msleep(10); - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); - spin_lock_irqsave(&ehci->lock, flags); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void)ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irqrestore(&ehci->lock, flags); - - // could save FLADJ in case of Vaux power loss - // ... we'd only use it to handle clock skew + bool do_wakeup = device_may_wakeup(dev); + int rc; + rc = ehci_suspend(hcd, do_wakeup); alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); return rc; @@ -188,56 +170,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) static int ehci_hcd_au1xxx_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); - - // maybe restore FLADJ - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* If CF is still set, we maintained PCI Vaux power. - * Just undo the effect of ehci_pci_suspend(). - */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - return 0; - } - - ehci_dbg(ehci, "lost power, restarting\n"); - usb_root_hub_lost_power(hcd->self.root_hub); - - /* Else reset, to cope with power loss or flush-to-storage - * style "resume" having let BIOS kick in during reboot. - */ - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq(&ehci->lock); - if (ehci->reclaim) - end_unlink_async(ehci); - ehci_work(ehci); - spin_unlock_irq(&ehci->lock); - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - - ehci->rh_state = EHCI_RH_SUSPENDED; + ehci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c49fc1e7895d..e6823a0cf642 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1242,6 +1242,95 @@ static int ehci_get_frame (struct usb_hcd *hcd) } /*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +/* suspend/resume, section 4.3 */ + +/* These routines handle the generic parts of controller suspend/resume */ + +static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); + + /* + * Root hub was already suspended. Disable IRQ emission and + * mark HW unaccessible. The PM and USB cores make sure that + * the root hub is either suspended or stopped. + */ + ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); + + spin_lock_irq(&ehci->lock); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void) ehci_readl(ehci, &ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + spin_unlock_irq(&ehci->lock); + + return 0; +} + +/* Returns 0 if power was preserved, 1 if power was lost */ +static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); + + /* Mark hardware accessible again as we are back to full power by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* + * If CF is still set and we aren't resuming from hibernation + * then we maintained suspend power. + * Just undo the effect of ehci_suspend(). + */ + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && + !hibernated) { + int mask = INTR_MASK; + + ehci_prepare_ports_for_controller_resume(ehci); + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + return 0; + } + + /* + * Else reset, to cope with power loss or resume from hibernation + * having let the firmware kick in during reboot. + */ + usb_root_hub_lost_power(hcd->self.root_hub); + (void) ehci_halt(ehci); + (void) ehci_reset(ehci); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq(&ehci->lock); + if (ehci->reclaim) + end_unlink_async(ehci); + ehci_work(ehci); + spin_unlock_irq(&ehci->lock); + + ehci_writel(ehci, ehci->command, &ehci->regs->command); + ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + + /* here we "know" root ports should always stay powered */ + ehci_port_power(ehci, 1); + + ehci->rh_state = EHCI_RH_SUSPENDED; + return 1; +} + +#endif + +/*-------------------------------------------------------------------------*/ + /* * The EHCI in ChipIdea HDRC cannot be a separate module or device, * because its registers (and irq) are shared between host/gadget/otg diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index db05e358677a..b3e2d66e95bb 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) ehci->owned_ports = 0; } -static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) +static int ehci_port_change(struct ehci_hcd *ehci) { int i = HCS_N_PORTS(ehci->hcs_params); @@ -128,7 +128,7 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) return 0; } -static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, +static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, bool suspending, bool do_wakeup) { int port; diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 6b4ffb598db1..17dd9e94001e 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -198,24 +198,11 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) static int ehci_msm_pm_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - bool wakeup = device_may_wakeup(dev); + bool do_wakeup = device_may_wakeup(dev); dev_dbg(dev, "ehci-msm PM suspend\n"); - /* - * EHCI helper function has also the same check before manipulating - * port wakeup flags. We do check here the same condition before - * calling the same helper function to avoid bringing hardware - * from Low power mode when there is no need for adjusting port - * wakeup flags. - */ - if (hcd->self.root_hub->do_remote_wakeup && !wakeup) { - pm_runtime_resume(dev); - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), - wakeup); - } - - return 0; + return ehci_suspend(hcd, do_wakeup); } static int ehci_msm_pm_resume(struct device *dev) @@ -223,7 +210,7 @@ static int ehci_msm_pm_resume(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); dev_dbg(dev, "ehci-msm PM resume\n"); - ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); + ehci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 123481793a47..6e767bce0605 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -331,29 +331,7 @@ done: static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - unsigned long flags; - int rc = 0; - - if (time_before(jiffies, ehci->next_statechange)) - msleep(10); - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); - spin_lock_irqsave (&ehci->lock, flags); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void)ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irqrestore (&ehci->lock, flags); - - // could save FLADJ in case of Vaux power loss - // ... we'd only use it to handle clock skew - - return rc; + return ehci_suspend(hcd, do_wakeup); } static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) @@ -402,54 +380,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) if (usb_is_intel_switchable_ehci(pdev)) ehci_enable_xhci_companion(); - // maybe restore FLADJ - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* If CF is still set and we aren't resuming from hibernation - * then we maintained PCI Vaux power. - * Just undo the effect of ehci_pci_suspend(). - */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && - !hibernated) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - return 0; - } - - usb_root_hub_lost_power(hcd->self.root_hub); - - /* Else reset, to cope with power loss or flush-to-storage - * style "resume" having let BIOS kick in during reboot. - */ - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - (void) ehci_pci_reinit(ehci, pdev); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq(&ehci->lock); - if (ehci->reclaim) - end_unlink_async(ehci); - ehci_work(ehci); - spin_unlock_irq(&ehci->lock); - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - - ehci->rh_state = EHCI_RH_SUSPENDED; + if (ehci_resume(hcd, hibernated) != 0) + (void) ehci_pci_reinit(ehci, pdev); return 0; } #endif diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index dfe881a34ae2..4b1d896d5a22 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - bool wakeup = device_may_wakeup(dev); + bool do_wakeup = device_may_wakeup(dev); - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup); - return 0; + return ehci_suspend(hcd, do_wakeup); } static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); + ehci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 1e483f052ff7..c7e0936d4a7c 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -200,27 +200,12 @@ static int s5p_ehci_suspend(struct device *dev) { struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); + bool do_wakeup = device_may_wakeup(dev); struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; - unsigned long flags; - int rc = 0; + int rc; - if (time_before(jiffies, ehci->next_statechange)) - msleep(20); - - /* - * Root hub was already suspended. Disable irq emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); - spin_lock_irqsave(&ehci->lock, flags); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void)ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irqrestore(&ehci->lock, flags); + rc = ehci_suspend(hcd, do_wakeup); if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); @@ -234,7 +219,6 @@ static int s5p_ehci_resume(struct device *dev) { struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; @@ -246,44 +230,7 @@ static int s5p_ehci_resume(struct device *dev) /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - return 0; - } - - usb_root_hub_lost_power(hcd->self.root_hub); - - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq(&ehci->lock); - if (ehci->reclaim) - end_unlink_async(ehci); - ehci_work(ehci); - spin_unlock_irq(&ehci->lock); - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - - ehci->rh_state = EHCI_RH_SUSPENDED; - + ehci_resume(hcd, false); return 0; } #else diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index cc199e87a7a9..58c96bd50d22 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -160,84 +160,16 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev) static int ehci_hcd_sead3_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - unsigned long flags; - int rc = 0; - - if (time_before(jiffies, ehci->next_statechange)) - msleep(20); - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); - spin_lock_irqsave(&ehci->lock, flags); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void)ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irqrestore(&ehci->lock, flags); + bool do_wakeup = device_may_wakeup(dev); - /* could save FLADJ in case of Vaux power loss - * ... we'd only use it to handle clock skew - */ - - return rc; + return ehci_suspend(hcd, do_wakeup); } static int ehci_hcd_sead3_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - /* maybe restore FLADJ. */ - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* If CF is still set, we maintained PCI Vaux power. - * Just undo the effect of ehci_pci_suspend(). - */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - return 0; - } - - ehci_dbg(ehci, "lost power, restarting\n"); - usb_root_hub_lost_power(hcd->self.root_hub); - - /* Else reset, to cope with power loss or flush-to-storage - * style "resume" having let BIOS kick in during reboot. - */ - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq(&ehci->lock); - if (ehci->reclaim) - end_unlink_async(ehci); - ehci_work(ehci); - spin_unlock_irq(&ehci->lock); - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - - ehci->rh_state = EHCI_RH_SUSPENDED; + ehci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 37ba8c8d2fd0..7ed533e6cca8 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -97,71 +97,16 @@ static const struct hc_driver ehci_spear_hc_driver = { static int ehci_spear_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - unsigned long flags; - int rc = 0; - - if (time_before(jiffies, ehci->next_statechange)) - msleep(10); - - /* - * Root hub was already suspended. Disable irq emission and mark HW - * unaccessible. The PM and USB cores make sure that the root hub is - * either suspended or stopped. - */ - spin_lock_irqsave(&ehci->lock, flags); - ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - spin_unlock_irqrestore(&ehci->lock, flags); + bool do_wakeup = device_may_wakeup(dev); - return rc; + return ehci_suspend(hcd, do_wakeup); } static int ehci_spear_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - return 0; - } - - usb_root_hub_lost_power(hcd->self.root_hub); - - /* - * Else reset, to cope with power loss or flush-to-storage style - * "resume" having let BIOS kick in during reboot. - */ - ehci_halt(ehci); - ehci_reset(ehci); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq(&ehci->lock); - if (ehci->reclaim) - end_unlink_async(ehci); - - ehci_work(ehci); - spin_unlock_irq(&ehci->lock); - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); + ehci_resume(hcd, false); return 0; } #endif /* CONFIG_PM */ -- GitLab From ff081e05bfba3461119cd280201d163b6858eda2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 6 Jul 2012 22:03:42 +0100 Subject: [PATCH 2315/5711] ARM: 7457/1: smp: Fix suspicious RCU originating from cpu_die() While running hotplug tests I ran into this RCU splat =============================== [ INFO: suspicious RCU usage. ] 3.4.0 #3275 Tainted: G W ------------------------------- include/linux/rcupdate.h:729 rcu_read_lock() used illegally while idle! other info that might help us debug this: RCU used illegally from idle CPU! rcu_scheduler_active = 1, debug_locks = 0 RCU used illegally from extended quiescent state! 4 locks held by swapper/2/0: #0: ((cpu_died).wait.lock){......}, at: [] complete+0x1c/0x5c #1: (&p->pi_lock){-.-.-.}, at: [] try_to_wake_up+0x2c/0x388 #2: (&rq->lock){-.-.-.}, at: [] try_to_wake_up+0x130/0x388 #3: (rcu_read_lock){.+.+..}, at: [] cpuacct_charge+0x28/0x1f4 stack backtrace: [] (unwind_backtrace+0x0/0x12c) from [] (cpuacct_charge+0x94/0x1f4) [] (cpuacct_charge+0x94/0x1f4) from [] (update_curr+0x24c/0x2c8) [] (update_curr+0x24c/0x2c8) from [] (enqueue_task_fair+0x50/0x194) [] (enqueue_task_fair+0x50/0x194) from [] (enqueue_task+0x30/0x34) [] (enqueue_task+0x30/0x34) from [] (ttwu_activate+0x14/0x38) [] (ttwu_activate+0x14/0x38) from [] (try_to_wake_up+0x178/0x388) [] (try_to_wake_up+0x178/0x388) from [] (__wake_up_common+0x34/0x78) [] (__wake_up_common+0x34/0x78) from [] (complete+0x48/0x5c) [] (complete+0x48/0x5c) from [] (cpu_die+0x2c/0x58) [] (cpu_die+0x2c/0x58) from [] (cpu_idle+0x64/0xfc) [] (cpu_idle+0x64/0xfc) from [<80208160>] (0x80208160) When a cpu is marked offline during its idle thread it calls cpu_die() during an RCU idle period. cpu_die() calls complete() to notify the killing process that the cpu has died. complete() calls into the scheduler code and eventually grabs an RCU read lock in cpuacct_charge(). Mark complete() as RCU_NONIDLE so that RCU pays attention to this CPU for the duration of the complete() function even though it's in idle. Suggested-by: "Paul E. McKenney" Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 2c7217d971db..aea74f5bc34a 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -179,7 +179,7 @@ void __ref cpu_die(void) mb(); /* Tell __cpu_die() that this CPU is now safe to dispose of */ - complete(&cpu_died); + RCU_NONIDLE(complete(&cpu_died)); /* * actual CPU shutdown procedure is at least platform (if not -- GitLab From 3169663ac5902f2228ea0eb8cc34eb52cbd4b283 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Jun 2012 11:42:36 +0100 Subject: [PATCH 2316/5711] ARM: sa11x0/pxa: convert OS timer registers to IOMEM Make the OS timer registers have IOMEM like properities so they can be passed to readl_relaxed/writel_relaxed() et.al. rather than being straight volatile dereferences. Add linux/io.h includes where required. linux/io.h includes added to arch/arm/mach-sa1100/cpu-sa1100.c, arch/arm/mach-sa1100/jornada720_ssp.c, arch/arm/mach-sa1100/leds-lart.c drivers/input/touchscreen/jornada720_ts.c, drivers/pcmcia/sa1100_shannon.c from Arnd. This fixes these warnings: arch/arm/mach-sa1100/time.c: In function 'sa1100_timer_init': arch/arm/mach-sa1100/time.c:104: warning: passing argument 1 of 'clocksource_mmio_init' discards qualifiers from pointer target type arch/arm/mach-pxa/time.c: In function 'pxa_timer_init': arch/arm/mach-pxa/time.c:126: warning: passing argument 1 of 'clocksource_mmio_init' discards qualifiers from pointer target type Signed-off-by: Arnd Bergmann Signed-off-by: Russell King --- arch/arm/mach-pxa/include/mach/regs-ost.h | 22 ++++---- arch/arm/mach-pxa/reset.c | 7 +-- arch/arm/mach-pxa/time.c | 52 +++++++++---------- arch/arm/mach-sa1100/assabet.c | 2 +- arch/arm/mach-sa1100/cpu-sa1100.c | 1 + arch/arm/mach-sa1100/cpu-sa1110.c | 1 + arch/arm/mach-sa1100/include/mach/SA-1100.h | 16 +++--- arch/arm/mach-sa1100/include/mach/gpio.h | 1 + arch/arm/mach-sa1100/include/mach/hardware.h | 6 ++- .../arm/mach-sa1100/include/mach/uncompress.h | 2 + arch/arm/mach-sa1100/irq.c | 1 + arch/arm/mach-sa1100/jornada720_ssp.c | 1 + arch/arm/mach-sa1100/leds-cerf.c | 1 + arch/arm/mach-sa1100/leds-lart.c | 1 + arch/arm/mach-sa1100/pm.c | 1 + arch/arm/mach-sa1100/time.c | 48 ++++++++--------- drivers/input/touchscreen/jornada720_ts.c | 1 + drivers/pcmcia/sa1100_shannon.c | 1 + drivers/watchdog/sa1100_wdt.c | 14 ++--- 19 files changed, 97 insertions(+), 82 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/regs-ost.h b/arch/arm/mach-pxa/include/mach/regs-ost.h index a3e5f86ef67e..628819995c52 100644 --- a/arch/arm/mach-pxa/include/mach/regs-ost.h +++ b/arch/arm/mach-pxa/include/mach/regs-ost.h @@ -7,17 +7,17 @@ * OS Timer & Match Registers */ -#define OSMR0 __REG(0x40A00000) /* */ -#define OSMR1 __REG(0x40A00004) /* */ -#define OSMR2 __REG(0x40A00008) /* */ -#define OSMR3 __REG(0x40A0000C) /* */ -#define OSMR4 __REG(0x40A00080) /* */ -#define OSCR __REG(0x40A00010) /* OS Timer Counter Register */ -#define OSCR4 __REG(0x40A00040) /* OS Timer Counter Register */ -#define OMCR4 __REG(0x40A000C0) /* */ -#define OSSR __REG(0x40A00014) /* OS Timer Status Register */ -#define OWER __REG(0x40A00018) /* OS Timer Watchdog Enable Register */ -#define OIER __REG(0x40A0001C) /* OS Timer Interrupt Enable Register */ +#define OSMR0 io_p2v(0x40A00000) /* */ +#define OSMR1 io_p2v(0x40A00004) /* */ +#define OSMR2 io_p2v(0x40A00008) /* */ +#define OSMR3 io_p2v(0x40A0000C) /* */ +#define OSMR4 io_p2v(0x40A00080) /* */ +#define OSCR io_p2v(0x40A00010) /* OS Timer Counter Register */ +#define OSCR4 io_p2v(0x40A00040) /* OS Timer Counter Register */ +#define OMCR4 io_p2v(0x40A000C0) /* */ +#define OSSR io_p2v(0x40A00014) /* OS Timer Status Register */ +#define OWER io_p2v(0x40A00018) /* OS Timer Watchdog Enable Register */ +#define OIER io_p2v(0x40A0001C) /* OS Timer Interrupt Enable Register */ #define OSSR_M3 (1 << 3) /* Match status channel 3 */ #define OSSR_M2 (1 << 2) /* Match status channel 2 */ diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index b4528899ef08..3fab583755d4 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -77,9 +77,10 @@ static void do_gpio_reset(void) static void do_hw_reset(void) { /* Initialize the watchdog and let it fire */ - OWER = OWER_WME; - OSSR = OSSR_M3; - OSMR3 = OSCR + 368640; /* ... in 100 ms */ + writel_relaxed(OWER_WME, OWER); + writel_relaxed(OSSR_M3, OSSR); + /* ... in 100 ms */ + writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3); } void pxa_restart(char mode, const char *cmd) diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 3d6c9bd90de6..4bc47d63698b 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -35,7 +35,7 @@ static u32 notrace pxa_read_sched_clock(void) { - return OSCR; + return readl_relaxed(OSCR); } @@ -47,8 +47,8 @@ pxa_ost0_interrupt(int irq, void *dev_id) struct clock_event_device *c = dev_id; /* Disarm the compare/match, signal the event. */ - OIER &= ~OIER_E0; - OSSR = OSSR_M0; + writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); + writel_relaxed(OSSR_M0, OSSR); c->event_handler(c); return IRQ_HANDLED; @@ -59,10 +59,10 @@ pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) { unsigned long next, oscr; - OIER |= OIER_E0; - next = OSCR + delta; - OSMR0 = next; - oscr = OSCR; + writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER); + next = readl_relaxed(OSCR) + delta; + writel_relaxed(next, OSMR0); + oscr = readl_relaxed(OSCR); return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } @@ -72,15 +72,15 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { case CLOCK_EVT_MODE_ONESHOT: - OIER &= ~OIER_E0; - OSSR = OSSR_M0; + writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); + writel_relaxed(OSSR_M0, OSSR); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: /* initializing, released, or preparing for suspend */ - OIER &= ~OIER_E0; - OSSR = OSSR_M0; + writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); + writel_relaxed(OSSR_M0, OSSR); break; case CLOCK_EVT_MODE_RESUME: @@ -108,8 +108,8 @@ static void __init pxa_timer_init(void) { unsigned long clock_tick_rate = get_clock_tick_rate(); - OIER = 0; - OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; + writel_relaxed(0, OIER); + writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); @@ -122,7 +122,7 @@ static void __init pxa_timer_init(void) setup_irq(IRQ_OST0, &pxa_ost0_irq); - clocksource_mmio_init(&OSCR, "oscr0", clock_tick_rate, 200, 32, + clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32, clocksource_mmio_readl_up); clockevents_register_device(&ckevt_pxa_osmr0); } @@ -132,12 +132,12 @@ static unsigned long osmr[4], oier, oscr; static void pxa_timer_suspend(void) { - osmr[0] = OSMR0; - osmr[1] = OSMR1; - osmr[2] = OSMR2; - osmr[3] = OSMR3; - oier = OIER; - oscr = OSCR; + osmr[0] = readl_relaxed(OSMR0); + osmr[1] = readl_relaxed(OSMR1); + osmr[2] = readl_relaxed(OSMR2); + osmr[3] = readl_relaxed(OSMR3); + oier = readl_relaxed(OIER); + oscr = readl_relaxed(OSCR); } static void pxa_timer_resume(void) @@ -151,12 +151,12 @@ static void pxa_timer_resume(void) if (osmr[0] - oscr < MIN_OSCR_DELTA) osmr[0] += MIN_OSCR_DELTA; - OSMR0 = osmr[0]; - OSMR1 = osmr[1]; - OSMR2 = osmr[2]; - OSMR3 = osmr[3]; - OIER = oier; - OSCR = oscr; + writel_relaxed(osmr[0], OSMR0); + writel_relaxed(osmr[1], OSMR1); + writel_relaxed(osmr[2], OSMR2); + writel_relaxed(osmr[3], OSMR3); + writel_relaxed(oier, OIER); + writel_relaxed(oscr, OSCR); } #else #define pxa_timer_suspend NULL diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d1dc7f1a239c..d673211f121c 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -362,7 +362,7 @@ static void __init assabet_init(void) static void __init map_sa1100_gpio_regs( void ) { unsigned long phys = __PREG(GPLR) & PMD_MASK; - unsigned long virt = io_p2v(phys); + unsigned long virt = (unsigned long)io_p2v(phys); int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO); pmd_t *pmd; diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index 19b2053f5af4..e8f4d1e19233 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -87,6 +87,7 @@ #include #include #include +#include #include diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 675bf8ef97e8..48c45b0c92bb 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-sa1100/include/mach/SA-1100.h b/arch/arm/mach-sa1100/include/mach/SA-1100.h index 3f2d1b60188c..0ac6cc08a19c 100644 --- a/arch/arm/mach-sa1100/include/mach/SA-1100.h +++ b/arch/arm/mach-sa1100/include/mach/SA-1100.h @@ -830,14 +830,14 @@ * (read/write). */ -#define OSMR0 __REG(0x90000000) /* OS timer Match Reg. 0 */ -#define OSMR1 __REG(0x90000004) /* OS timer Match Reg. 1 */ -#define OSMR2 __REG(0x90000008) /* OS timer Match Reg. 2 */ -#define OSMR3 __REG(0x9000000c) /* OS timer Match Reg. 3 */ -#define OSCR __REG(0x90000010) /* OS timer Counter Reg. */ -#define OSSR __REG(0x90000014 ) /* OS timer Status Reg. */ -#define OWER __REG(0x90000018 ) /* OS timer Watch-dog Enable Reg. */ -#define OIER __REG(0x9000001C ) /* OS timer Interrupt Enable Reg. */ +#define OSMR0 io_p2v(0x90000000) /* OS timer Match Reg. 0 */ +#define OSMR1 io_p2v(0x90000004) /* OS timer Match Reg. 1 */ +#define OSMR2 io_p2v(0x90000008) /* OS timer Match Reg. 2 */ +#define OSMR3 io_p2v(0x9000000c) /* OS timer Match Reg. 3 */ +#define OSCR io_p2v(0x90000010) /* OS timer Counter Reg. */ +#define OSSR io_p2v(0x90000014) /* OS timer Status Reg. */ +#define OWER io_p2v(0x90000018) /* OS timer Watch-dog Enable Reg. */ +#define OIER io_p2v(0x9000001C) /* OS timer Interrupt Enable Reg. */ #define OSSR_M(Nb) /* Match detected [0..3] */ \ (0x00000001 << (Nb)) diff --git a/arch/arm/mach-sa1100/include/mach/gpio.h b/arch/arm/mach-sa1100/include/mach/gpio.h index a38fc4f54241..6a9eecf3137e 100644 --- a/arch/arm/mach-sa1100/include/mach/gpio.h +++ b/arch/arm/mach-sa1100/include/mach/gpio.h @@ -24,6 +24,7 @@ #ifndef __ASM_ARCH_SA1100_GPIO_H #define __ASM_ARCH_SA1100_GPIO_H +#include #include #include #include diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h index 99f5856d8de4..cbedd75a9d65 100644 --- a/arch/arm/mach-sa1100/include/mach/hardware.h +++ b/arch/arm/mach-sa1100/include/mach/hardware.h @@ -32,7 +32,7 @@ #define PIO_START 0x80000000 /* physical start of IO space */ #define io_p2v( x ) \ - ( (((x)&0x00ffffff) | (((x)&0x30000000)>>VIO_SHIFT)) + VIO_BASE ) + IOMEM( (((x)&0x00ffffff) | (((x)&0x30000000)>>VIO_SHIFT)) + VIO_BASE ) #define io_v2p( x ) \ ( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))< @@ -56,7 +58,7 @@ #define cpu_is_sa1100() ((read_cpuid_id() & CPU_SA1100_MASK) == CPU_SA1100_ID) #define cpu_is_sa1110() ((read_cpuid_id() & CPU_SA1110_MASK) == CPU_SA1110_ID) -# define __REG(x) (*((volatile unsigned long *)io_p2v(x))) +# define __REG(x) (*((volatile unsigned long __iomem *)io_p2v(x))) # define __PREG(x) (io_v2p((unsigned long)&(x))) static inline unsigned long get_clock_tick_rate(void) diff --git a/arch/arm/mach-sa1100/include/mach/uncompress.h b/arch/arm/mach-sa1100/include/mach/uncompress.h index 6cb39ddde656..5cf71da60e42 100644 --- a/arch/arm/mach-sa1100/include/mach/uncompress.h +++ b/arch/arm/mach-sa1100/include/mach/uncompress.h @@ -8,6 +8,8 @@ #include "hardware.h" +#define IOMEM(x) (x) + /* * The following code assumes the serial port has already been * initialized by the bootloader. We search for the first enabled diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index 516ccc25d7fd..2124f1fc2fbe 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index b412fc09c80c..7f07f08d8968 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-sa1100/leds-cerf.c b/arch/arm/mach-sa1100/leds-cerf.c index 040540fb7d8a..30fc3b2bf555 100644 --- a/arch/arm/mach-sa1100/leds-cerf.c +++ b/arch/arm/mach-sa1100/leds-cerf.c @@ -4,6 +4,7 @@ * Author: ??? */ #include +#include #include #include diff --git a/arch/arm/mach-sa1100/leds-lart.c b/arch/arm/mach-sa1100/leds-lart.c index a51830c60e53..50a5b143b460 100644 --- a/arch/arm/mach-sa1100/leds-lart.c +++ b/arch/arm/mach-sa1100/leds-lart.c @@ -10,6 +10,7 @@ * pace of the LED. */ #include +#include #include #include diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 690cf0ce5c0c..6645d1e31f14 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -23,6 +23,7 @@ * Storage is local on the stack now. */ #include +#include #include #include #include diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 6af26e8d55e6..80702c9ecc77 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -22,7 +22,7 @@ static u32 notrace sa1100_read_sched_clock(void) { - return OSCR; + return readl_relaxed(OSCR); } #define MIN_OSCR_DELTA 2 @@ -32,8 +32,8 @@ static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id) struct clock_event_device *c = dev_id; /* Disarm the compare/match, signal the event. */ - OIER &= ~OIER_E0; - OSSR = OSSR_M0; + writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); + writel_relaxed(OSSR_M0, OSSR); c->event_handler(c); return IRQ_HANDLED; @@ -44,10 +44,10 @@ sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) { unsigned long next, oscr; - OIER |= OIER_E0; - next = OSCR + delta; - OSMR0 = next; - oscr = OSCR; + writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER); + next = readl_relaxed(OSCR) + delta; + writel_relaxed(next, OSMR0); + oscr = readl_relaxed(OSCR); return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } @@ -59,8 +59,8 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - OIER &= ~OIER_E0; - OSSR = OSSR_M0; + writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); + writel_relaxed(OSSR_M0, OSSR); break; case CLOCK_EVT_MODE_RESUME: @@ -86,8 +86,8 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { - OIER = 0; - OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; + writel_relaxed(0, OIER); + writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); @@ -100,7 +100,7 @@ static void __init sa1100_timer_init(void) setup_irq(IRQ_OST0, &sa1100_timer_irq); - clocksource_mmio_init(&OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, + clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); clockevents_register_device(&ckevt_sa1100_osmr0); } @@ -110,26 +110,26 @@ unsigned long osmr[4], oier; static void sa1100_timer_suspend(void) { - osmr[0] = OSMR0; - osmr[1] = OSMR1; - osmr[2] = OSMR2; - osmr[3] = OSMR3; - oier = OIER; + osmr[0] = readl_relaxed(OSMR0); + osmr[1] = readl_relaxed(OSMR1); + osmr[2] = readl_relaxed(OSMR2); + osmr[3] = readl_relaxed(OSMR3); + oier = readl_relaxed(OIER); } static void sa1100_timer_resume(void) { - OSSR = 0x0f; - OSMR0 = osmr[0]; - OSMR1 = osmr[1]; - OSMR2 = osmr[2]; - OSMR3 = osmr[3]; - OIER = oier; + writel_relaxed(0x0f, OSSR); + writel_relaxed(osmr[0], OSMR0); + writel_relaxed(osmr[1], OSMR1); + writel_relaxed(osmr[2], OSMR2); + writel_relaxed(osmr[3], OSMR3); + writel_relaxed(oier, OIER); /* * OSMR0 is the system timer: make sure OSCR is sufficiently behind */ - OSCR = OSMR0 - LATCH; + writel_relaxed(OSMR0 - LATCH, OSCR); } #else #define sa1100_timer_suspend NULL diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index d9be6eac99b1..7f03d1bd916e 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c index decb34730bcf..56ab73915602 100644 --- a/drivers/pcmcia/sa1100_shannon.c +++ b/drivers/pcmcia/sa1100_shannon.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index 54984deb8561..ccd6b29e21bf 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -54,10 +54,10 @@ static int sa1100dog_open(struct inode *inode, struct file *file) return -EBUSY; /* Activate SA1100 Watchdog timer */ - OSMR3 = OSCR + pre_margin; - OSSR = OSSR_M3; - OWER = OWER_WME; - OIER |= OIER_E3; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + writel_relaxed(OSSR_M3, OSSR); + writel_relaxed(OWER_WME, OWER); + writel_relaxed(readl_relaxed(OIER) | OIER_E3, OIER); return nonseekable_open(inode, file); } @@ -80,7 +80,7 @@ static ssize_t sa1100dog_write(struct file *file, const char __user *data, { if (len) /* Refresh OSMR3 timer. */ - OSMR3 = OSCR + pre_margin; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); return len; } @@ -114,7 +114,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, break; case WDIOC_KEEPALIVE: - OSMR3 = OSCR + pre_margin; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); ret = 0; break; @@ -129,7 +129,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, } pre_margin = oscr_freq * time; - OSMR3 = OSCR + pre_margin; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); /*fall through*/ case WDIOC_GETTIMEOUT: -- GitLab From 929678005ce947d521b0f8f3a76d48d7b394562b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 7 Jul 2012 20:00:18 +0100 Subject: [PATCH 2317/5711] ARM: 7459/1: irda/pxa: use readl_relaxed() to access OSCR register After c00184f9ab4 "ARM: sa11x0/pxa: convert OS timer registers to IOMEM", magician_defconfig and a few others fail to build because the OSCR register is accessed by the drivers/net/irda/pxaficp_ir.c but has turned into a pointer that needs to be read using readl. There are other registers in the same driver that eventually should be converted, and it's unclear whether we would want a better interface to access the OSCR from a device driver. Signed-off-by: Arnd Bergmann Acked-by: David S. Miller Signed-off-by: Russell King --- drivers/net/irda/pxaficp_ir.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index ff16daf33ae1..8d5476707912 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -289,7 +289,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) } lsr = STLSR; } - si->last_oscr = OSCR; + si->last_oscr = readl_relaxed(OSCR); break; case 0x04: /* Received Data Available */ @@ -300,7 +300,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) dev->stats.rx_bytes++; async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR); } while (STLSR & LSR_DR); - si->last_oscr = OSCR; + si->last_oscr = readl_relaxed(OSCR); break; case 0x02: /* Transmit FIFO Data Request */ @@ -316,7 +316,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) /* We need to ensure that the transmitter has finished. */ while ((STLSR & LSR_TEMT) == 0) cpu_relax(); - si->last_oscr = OSCR; + si->last_oscr = readl_relaxed(OSCR); /* * Ok, we've finished transmitting. Now enable @@ -370,7 +370,7 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) while (ICSR1 & ICSR1_TBY) cpu_relax(); - si->last_oscr = OSCR; + si->last_oscr = readl_relaxed(OSCR); /* * HACK: It looks like the TBY bit is dropped too soon. @@ -470,7 +470,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; - si->last_oscr = OSCR; + si->last_oscr = readl_relaxed(OSCR); icsr0 = ICSR0; if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { @@ -546,7 +546,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len); if (mtt) - while ((unsigned)(OSCR - si->last_oscr)/4 < mtt) + while ((unsigned)(readl_relaxed(OSCR) - si->last_oscr)/4 < mtt) cpu_relax(); /* stop RX DMA, disable FICP */ -- GitLab From 98437b83ee9e8c4adc84efa7f5a02647041f675b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Jun 2012 20:23:20 +0100 Subject: [PATCH 2318/5711] ARM: Realview: use SGI0 to wake secondary CPUs Signed-off-by: Russell King --- arch/arm/plat-versatile/platsmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 49c7db48c7f1..d7c5c171f5aa 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -85,7 +85,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 0); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { -- GitLab From 79d15ce999e7ae3e4b6cd71a720915e5d1c6c9c6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Jun 2012 20:24:07 +0100 Subject: [PATCH 2319/5711] ARM: OMAP: use SGI0 to wake secondary CPUs Signed-off-by: Russell King --- arch/arm/mach-omap2/omap-smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index deffbf1c9627..596eb70d37be 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -111,7 +111,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) booted = true; } - gic_raise_softirq(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 0); /* * Now the secondary core is starting up let it run its -- GitLab From ffae894035a1e0c46869eb81d53ea88ca4eaf2f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Jun 2012 20:24:44 +0100 Subject: [PATCH 2320/5711] ARM: MSM: use SGI0 to wake secondary CPUs Signed-off-by: Russell King --- arch/arm/mach-msm/platsmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index db0117ec55f4..e012dc8391cf 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -127,7 +127,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 0); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { -- GitLab From 02df19b4227e5b799e4642e88b568f9474fa78d0 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 15 Jun 2012 10:23:32 +0100 Subject: [PATCH 2321/5711] ARM: 7424/1: update die handler from x86 Robustify ARM's die() handling with improvements from x86: - Fix for a deadlock (before panic in the case of panic_on_oops) if we oops under a spinlock which is also used from interrupt handler, since the old code was unconditionally enabling interrupts. - Usage of arch spinlock so lockdep etc doesn't get involved while we're trying to dump out oopses. - Deadlock prevention in the unlikely event that die() recurses. The changes all touch the same few lines of code, so they're done together in one patch. Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 78 +++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4928d89758f4..2df8715c36c0 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -233,9 +233,9 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) #define S_ISA " ARM" #endif -static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) +static int __die(const char *str, int err, struct pt_regs *regs) { - struct task_struct *tsk = thread->task; + struct task_struct *tsk = current; static int die_counter; int ret; @@ -245,12 +245,12 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); if (ret == NOTIFY_STOP) - return ret; + return 1; print_modules(); __show_regs(regs); printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); + TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, @@ -259,45 +259,77 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt dump_instr(KERN_EMERG, regs); } - return ret; + return 0; } -static DEFINE_RAW_SPINLOCK(die_lock); +static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; +static int die_owner = -1; +static unsigned int die_nest_count; -/* - * This function is protected against re-entrancy. - */ -void die(const char *str, struct pt_regs *regs, int err) +static unsigned long oops_begin(void) { - struct thread_info *thread = current_thread_info(); - int ret; - enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; + int cpu; + unsigned long flags; oops_enter(); - raw_spin_lock_irq(&die_lock); + /* racy, but better than risking deadlock. */ + raw_local_irq_save(flags); + cpu = smp_processor_id(); + if (!arch_spin_trylock(&die_lock)) { + if (cpu == die_owner) + /* nested oops. should stop eventually */; + else + arch_spin_lock(&die_lock); + } + die_nest_count++; + die_owner = cpu; console_verbose(); bust_spinlocks(1); - if (!user_mode(regs)) - bug_type = report_bug(regs->ARM_pc, regs); - if (bug_type != BUG_TRAP_TYPE_NONE) - str = "Oops - BUG"; - ret = __die(str, err, thread, regs); + return flags; +} - if (regs && kexec_should_crash(thread->task)) +static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) +{ + if (regs && kexec_should_crash(current)) crash_kexec(regs); bust_spinlocks(0); + die_owner = -1; add_taint(TAINT_DIE); - raw_spin_unlock_irq(&die_lock); + die_nest_count--; + if (!die_nest_count) + /* Nest count reaches zero, release the lock. */ + arch_spin_unlock(&die_lock); + raw_local_irq_restore(flags); oops_exit(); if (in_interrupt()) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); - if (ret != NOTIFY_STOP) - do_exit(SIGSEGV); + if (signr) + do_exit(signr); +} + +/* + * This function is protected against re-entrancy. + */ +void die(const char *str, struct pt_regs *regs, int err) +{ + enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; + unsigned long flags = oops_begin(); + int sig = SIGSEGV; + + if (!user_mode(regs)) + bug_type = report_bug(regs->ARM_pc, regs); + if (bug_type != BUG_TRAP_TYPE_NONE) + str = "Oops - BUG"; + + if (__die(str, err, regs)) + sig = 0; + + oops_end(flags, regs, sig); } void arm_notify_die(const char *str, struct pt_regs *regs, -- GitLab From 9ad86ddde0345e903eb74837e52cf19fe0c7f825 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 25 Jun 2012 14:59:38 +0100 Subject: [PATCH 2322/5711] ARM: 7436/1: Do not map the vectors page as write-through on UP systems The vectors page has been traditionally mapped as WT on UP systems but this creates a mismatched alias with the directly mapped RAM that is using WB attributes. On newer processors like Cortex-A15 this has implications on the data/instructions coherency at the point of unification (usually L2). This patch removes such restriction. Signed-off-by: Catalin Marinas Tested-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e5dad60b558b..f37dc1856a69 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -421,12 +421,6 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; - /* - * Only use write-through for non-SMP systems - */ - if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH) - vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte; - /* * Enable CPU-specific coherency if supported. * (Only available on XSC3 at the moment.) -- GitLab From d0f34a11ddab9b456e4caf9fc48d8d7e832e0e50 Mon Sep 17 00:00:00 2001 From: Genoud Richard Date: Tue, 26 Jun 2012 16:37:59 +0100 Subject: [PATCH 2323/5711] ARM: 7437/1: zImage: Allow DTB command line concatenation with ATAG_CMDLINE This patch allows the ATAG_CMDLINE provided by the bootloader to be concatenated to the bootargs property of the device tree. This is useful to merge static values defined in the device tree with the boot loader's (possibly) more dynamic values, such as startup reasons and more. The bootloader should use the device tree to pass those values to the kernel, but that's not always simple (old bootloader or very small one). The behaviour is the same as the one introduced by Victor Boivie in 4394c1244249198c6b85093d46935b761b36ae05 by extending the CONFIG_CMDLINE. Signed-off-by: Richard Genoud Tested-by: Gregory CLEMENT Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 19 ++++++++ arch/arm/boot/compressed/atags_to_fdt.c | 62 ++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b649c5904a4f..8c9d264f2108 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1960,6 +1960,25 @@ config ARM_ATAG_DTB_COMPAT bootloaders, this option allows zImage to extract the information from the ATAG list and store it at run time into the appended DTB. +choice + prompt "Kernel command line type" if ARM_ATAG_DTB_COMPAT + default ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER + +config ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER + bool "Use bootloader kernel arguments if available" + help + Uses the command-line options passed by the boot loader instead of + the device tree bootargs property. If the boot loader doesn't provide + any, the device tree bootargs property will be used. + +config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND + bool "Extend with bootloader kernel arguments" + help + The command-line arguments provided by the boot loader will be + appended to the the device tree bootargs property. + +endchoice + config CMDLINE string "Default kernel command string" default "" diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index 797f04bedb47..aabc02a68482 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -1,6 +1,12 @@ #include #include +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) +#define do_extend_cmdline 1 +#else +#define do_extend_cmdline 0 +#endif + static int node_offset(void *fdt, const char *node_path) { int offset = fdt_path_offset(fdt, node_path); @@ -36,6 +42,48 @@ static int setprop_cell(void *fdt, const char *node_path, return fdt_setprop_cell(fdt, offset, property, val); } +static const void *getprop(const void *fdt, const char *node_path, + const char *property, int *len) +{ + int offset = fdt_path_offset(fdt, node_path); + + if (offset == -FDT_ERR_NOTFOUND) + return NULL; + + return fdt_getprop(fdt, offset, property, len); +} + +static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) +{ + char cmdline[COMMAND_LINE_SIZE]; + const char *fdt_bootargs; + char *ptr = cmdline; + int len = 0; + + /* copy the fdt command line into the buffer */ + fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len); + if (fdt_bootargs) + if (len < COMMAND_LINE_SIZE) { + memcpy(ptr, fdt_bootargs, len); + /* len is the length of the string + * including the NULL terminator */ + ptr += len - 1; + } + + /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { + len = strlen(fdt_cmdline); + if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { + *ptr++ = ' '; + memcpy(ptr, fdt_cmdline, len); + ptr += len; + } + } + *ptr = '\0'; + + setprop_string(fdt, "/chosen", "bootargs", cmdline); +} + /* * Convert and fold provided ATAGs into the provided FDT. * @@ -72,8 +120,18 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) for_each_tag(atag, atag_list) { if (atag->hdr.tag == ATAG_CMDLINE) { - setprop_string(fdt, "/chosen", "bootargs", - atag->u.cmdline.cmdline); + /* Append the ATAGS command line to the device tree + * command line. + * NB: This means that if the same parameter is set in + * the device tree and in the tags, the one from the + * tags will be chosen. + */ + if (do_extend_cmdline) + merge_fdt_bootargs(fdt, + atag->u.cmdline.cmdline); + else + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); } else if (atag->hdr.tag == ATAG_MEM) { if (memcount >= sizeof(mem_reg_property)/4) continue; -- GitLab From 9fa16b7755967b1b4dc704de71a3d639d13e21fc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 4 Jul 2012 04:58:12 +0100 Subject: [PATCH 2324/5711] ARM: 7439/1: head.S: simplify initial page table mapping Let's map the initial RAM up to the end of the kernel .bss instead of the strict kernel image area. This simplifies the code as the kernel image only needs to be handled specially in the XIP case. That covers the legacy ATAG location as well. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/head.S | 59 ++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 835898e7d704..3db960e20cb8 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -55,14 +55,6 @@ add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE .endm -#ifdef CONFIG_XIP_KERNEL -#define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) -#define KERNEL_END _edata_loc -#else -#define KERNEL_START KERNEL_RAM_VADDR -#define KERNEL_END _end -#endif - /* * Kernel startup entry point. * --------------------------- @@ -218,51 +210,46 @@ __create_page_tables: blo 1b /* - * Now setup the pagetables for our kernel direct - * mapped region. + * Map our RAM from the start to the end of the kernel .bss section. */ - mov r3, pc - mov r3, r3, lsr #SECTION_SHIFT - orr r3, r7, r3, lsl #SECTION_SHIFT - add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! - ldr r6, =(KERNEL_END - 1) - add r0, r0, #1 << PMD_ORDER + add r0, r4, #PAGE_OFFSET >> (SECTION_SHIFT - PMD_ORDER) + ldr r6, =(_end - 1) + orr r3, r8, r7 add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) -1: cmp r0, r6 +1: str r3, [r0], #1 << PMD_ORDER add r3, r3, #1 << SECTION_SHIFT - strls r3, [r0], #1 << PMD_ORDER + cmp r0, r6 bls 1b #ifdef CONFIG_XIP_KERNEL /* - * Map some ram to cover our .data and .bss areas. + * Map the kernel image separately as it is not located in RAM. */ - add r3, r8, #TEXT_OFFSET - orr r3, r3, r7 - add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! - ldr r6, =(_end - 1) - add r0, r0, #4 +#define XIP_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + mov r3, pc + mov r3, r3, lsr #SECTION_SHIFT + orr r3, r7, r3, lsl #SECTION_SHIFT + add r0, r4, #(XIP_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #((XIP_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! + ldr r6, =(_edata_loc - 1) + add r0, r0, #1 << PMD_ORDER add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 - add r3, r3, #1 << 20 - strls r3, [r0], #4 + add r3, r3, #1 << SECTION_SHIFT + strls r3, [r0], #1 << PMD_ORDER bls 1b #endif /* - * Then map boot params address in r2 or the first 1MB (2MB with LPAE) - * of ram if boot params address is not specified. + * Then map boot params address in r2 if specified. */ mov r0, r2, lsr #SECTION_SHIFT movs r0, r0, lsl #SECTION_SHIFT - moveq r0, r8 - sub r3, r0, r8 - add r3, r3, #PAGE_OFFSET - add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) - orr r6, r7, r0 - str r6, [r3] + subne r3, r0, r8 + addne r3, r3, #PAGE_OFFSET + addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) + orrne r6, r7, r0 + strne r6, [r3] #ifdef CONFIG_DEBUG_LL #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) -- GitLab From a5203c4ce6750730b1d95a8bc1e8214765450f7e Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 8 Jul 2012 22:51:44 +0100 Subject: [PATCH 2325/5711] ARM: 7460/1: remove asm/locks.h Commit 64ac24e738823161693bf791f87adc802cf529ff ("Generic semaphore implementation") removed the last include of this header. Apparently it was just an oversight to keep this header. It can safely be removed now. Acked-by: Will Deacon Signed-off-by: Paul Bolle Signed-off-by: Russell King --- arch/arm/include/asm/locks.h | 274 ----------------------------------- 1 file changed, 274 deletions(-) delete mode 100644 arch/arm/include/asm/locks.h diff --git a/arch/arm/include/asm/locks.h b/arch/arm/include/asm/locks.h deleted file mode 100644 index ef4c897772d1..000000000000 --- a/arch/arm/include/asm/locks.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * arch/arm/include/asm/locks.h - * - * Copyright (C) 2000 Russell King - * - * 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. - * - * Interrupt safe locking assembler. - */ -#ifndef __ASM_PROC_LOCKS_H -#define __ASM_PROC_LOCKS_H - -#if __LINUX_ARM_ARCH__ >= 6 - -#define __down_op(ptr,fail) \ - ({ \ - __asm__ __volatile__( \ - "@ down_op\n" \ -"1: ldrex lr, [%0]\n" \ -" sub lr, lr, %1\n" \ -" strex ip, lr, [%0]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" teq lr, #0\n" \ -" movmi ip, %0\n" \ -" blmi " #fail \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - }) - -#define __down_op_ret(ptr,fail) \ - ({ \ - unsigned int ret; \ - __asm__ __volatile__( \ - "@ down_op_ret\n" \ -"1: ldrex lr, [%1]\n" \ -" sub lr, lr, %2\n" \ -" strex ip, lr, [%1]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" teq lr, #0\n" \ -" movmi ip, %1\n" \ -" movpl ip, #0\n" \ -" blmi " #fail "\n" \ -" mov %0, ip" \ - : "=&r" (ret) \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - ret; \ - }) - -#define __up_op(ptr,wake) \ - ({ \ - smp_mb(); \ - __asm__ __volatile__( \ - "@ up_op\n" \ -"1: ldrex lr, [%0]\n" \ -" add lr, lr, %1\n" \ -" strex ip, lr, [%0]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" cmp lr, #0\n" \ -" movle ip, %0\n" \ -" blle " #wake \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - }) - -/* - * The value 0x01000000 supports up to 128 processors and - * lots of processes. BIAS must be chosen such that sub'ing - * BIAS once per CPU will result in the long remaining - * negative. - */ -#define RW_LOCK_BIAS 0x01000000 -#define RW_LOCK_BIAS_STR "0x01000000" - -#define __down_op_write(ptr,fail) \ - ({ \ - __asm__ __volatile__( \ - "@ down_op_write\n" \ -"1: ldrex lr, [%0]\n" \ -" sub lr, lr, %1\n" \ -" strex ip, lr, [%0]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" teq lr, #0\n" \ -" movne ip, %0\n" \ -" blne " #fail \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - }) - -#define __up_op_write(ptr,wake) \ - ({ \ - smp_mb(); \ - __asm__ __volatile__( \ - "@ up_op_write\n" \ -"1: ldrex lr, [%0]\n" \ -" adds lr, lr, %1\n" \ -" strex ip, lr, [%0]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" movcs ip, %0\n" \ -" blcs " #wake \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - }) - -#define __down_op_read(ptr,fail) \ - __down_op(ptr, fail) - -#define __up_op_read(ptr,wake) \ - ({ \ - smp_mb(); \ - __asm__ __volatile__( \ - "@ up_op_read\n" \ -"1: ldrex lr, [%0]\n" \ -" add lr, lr, %1\n" \ -" strex ip, lr, [%0]\n" \ -" teq ip, #0\n" \ -" bne 1b\n" \ -" teq lr, #0\n" \ -" moveq ip, %0\n" \ -" bleq " #wake \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - }) - -#else - -#define __down_op(ptr,fail) \ - ({ \ - __asm__ __volatile__( \ - "@ down_op\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%0]\n" \ -" subs lr, lr, %1\n" \ -" str lr, [%0]\n" \ -" msr cpsr_c, ip\n" \ -" movmi ip, %0\n" \ -" blmi " #fail \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - }) - -#define __down_op_ret(ptr,fail) \ - ({ \ - unsigned int ret; \ - __asm__ __volatile__( \ - "@ down_op_ret\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%1]\n" \ -" subs lr, lr, %2\n" \ -" str lr, [%1]\n" \ -" msr cpsr_c, ip\n" \ -" movmi ip, %1\n" \ -" movpl ip, #0\n" \ -" blmi " #fail "\n" \ -" mov %0, ip" \ - : "=&r" (ret) \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - ret; \ - }) - -#define __up_op(ptr,wake) \ - ({ \ - smp_mb(); \ - __asm__ __volatile__( \ - "@ up_op\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%0]\n" \ -" adds lr, lr, %1\n" \ -" str lr, [%0]\n" \ -" msr cpsr_c, ip\n" \ -" movle ip, %0\n" \ -" blle " #wake \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - }) - -/* - * The value 0x01000000 supports up to 128 processors and - * lots of processes. BIAS must be chosen such that sub'ing - * BIAS once per CPU will result in the long remaining - * negative. - */ -#define RW_LOCK_BIAS 0x01000000 -#define RW_LOCK_BIAS_STR "0x01000000" - -#define __down_op_write(ptr,fail) \ - ({ \ - __asm__ __volatile__( \ - "@ down_op_write\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%0]\n" \ -" subs lr, lr, %1\n" \ -" str lr, [%0]\n" \ -" msr cpsr_c, ip\n" \ -" movne ip, %0\n" \ -" blne " #fail \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - }) - -#define __up_op_write(ptr,wake) \ - ({ \ - __asm__ __volatile__( \ - "@ up_op_write\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%0]\n" \ -" adds lr, lr, %1\n" \ -" str lr, [%0]\n" \ -" msr cpsr_c, ip\n" \ -" movcs ip, %0\n" \ -" blcs " #wake \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - smp_mb(); \ - }) - -#define __down_op_read(ptr,fail) \ - __down_op(ptr, fail) - -#define __up_op_read(ptr,wake) \ - ({ \ - smp_mb(); \ - __asm__ __volatile__( \ - "@ up_op_read\n" \ -" mrs ip, cpsr\n" \ -" orr lr, ip, #128\n" \ -" msr cpsr_c, lr\n" \ -" ldr lr, [%0]\n" \ -" adds lr, lr, %1\n" \ -" str lr, [%0]\n" \ -" msr cpsr_c, ip\n" \ -" moveq ip, %0\n" \ -" bleq " #wake \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - }) - -#endif - -#endif -- GitLab From 27a5569dc66ecce06cb532542ddcd0b6da8783f6 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 6 Jul 2012 11:06:49 +0100 Subject: [PATCH 2326/5711] ARM: 7444/1: kernel: add arch-timer C3STOP feature When a CPU is shutdown its architected timer comparators registers are lost. Within CPU idle, before processors enter shutdown they enter clock events broadcast mode through the clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, cpuid); function where the local timers are emulated by a global always-on timer. On CPU resume, the per-CPU tick device normal mode is restored by exiting broadcast mode through clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, cpuid); In order for this mechanism to function, architected timers should add to their feature C3STOP, which means that they are not able to function when the CPU is in off-mode. Signed-off-by: Lorenzo Pieralisi Signed-off-by: Marc Zyngier Signed-off-by: Russell King --- arch/arm/kernel/arch_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dd58035621f7..df44c8cf9e2e 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -137,7 +137,7 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk) /* Be safe... */ arch_timer_disable(); - clk->features = CLOCK_EVT_FEAT_ONESHOT; + clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->name = "arch_sys_timer"; clk->rating = 450; clk->set_mode = arch_timer_set_mode; -- GitLab From 575320d625d5b5eb115575a1f5e17af456e69577 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:43:03 +0100 Subject: [PATCH 2327/5711] ARM: 7445/1: mm: update CONTEXTIDR register to contain PID of current process This patch introduces a new Kconfig option which, when enabled, causes the kernel to write the PID of the current task into the PROCID field of the CONTEXTIDR on context switch. This is useful when analysing hardware trace, since writes to this register can be configured to emit an event into the trace stream. The thread notifier for writing the PID is deliberately kept separate from the ASID-writing code so that we can support newer processors using LPAE, where the ASID is stored in TTBR0. As such, the switch_mm code is updated to perform a read-modify-write sequence to ensure that we don't clobber the PID on CPUs using the classic 2-level page tables. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 9 +++++++++ arch/arm/mm/context.c | 35 +++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v6.S | 6 ++++++ arch/arm/mm/proc-v7-2level.S | 5 +++++ 4 files changed, 55 insertions(+) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 01a134141216..521e15bc6401 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -369,4 +369,13 @@ config ARM_KPROBES_TEST help Perform tests of kprobes API and instruction set simulation. +config PID_IN_CONTEXTIDR + bool "Write the current PID to the CONTEXTIDR register" + depends on CPU_COPY_V6 + help + Enabling this option causes the kernel to write the current PID to + the PROCID field of the CONTEXTIDR register, at the expense of some + additional instructions during context switch. Say Y here only if you + are planning to use hardware trace tools with this kernel. + endmenu diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 806cc4f63516..119bc52ab93e 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -14,6 +14,7 @@ #include #include +#include #include static DEFINE_RAW_SPINLOCK(cpu_asid_lock); @@ -48,6 +49,40 @@ void cpu_set_reserved_ttbr0(void) } #endif +#ifdef CONFIG_PID_IN_CONTEXTIDR +static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd, + void *t) +{ + u32 contextidr; + pid_t pid; + struct thread_info *thread = t; + + if (cmd != THREAD_NOTIFY_SWITCH) + return NOTIFY_DONE; + + pid = task_pid_nr(thread->task) << ASID_BITS; + asm volatile( + " mrc p15, 0, %0, c13, c0, 1\n" + " bfi %1, %0, #0, %2\n" + " mcr p15, 0, %1, c13, c0, 1\n" + : "=r" (contextidr), "+r" (pid) + : "I" (ASID_BITS)); + isb(); + + return NOTIFY_OK; +} + +static struct notifier_block contextidr_notifier_block = { + .notifier_call = contextidr_notifier, +}; + +static int __init contextidr_notifier_init(void) +{ + return thread_register_notifier(&contextidr_notifier_block); +} +arch_initcall(contextidr_notifier_init); +#endif + /* * We fork()ed a process, and we need a new context for the child * to run in. diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 5900cd520e84..86b8b480634f 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -107,6 +107,12 @@ ENTRY(cpu_v6_switch_mm) mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 +#ifdef CONFIG_PID_IN_CONTEXTIDR + mrc p15, 0, r2, c13, c0, 1 @ read current context ID + bic r2, r2, #0xff @ extract the PID + and r1, r1, #0xff + orr r1, r1, r2 @ insert into new context ID +#endif mcr p15, 0, r1, c13, c0, 1 @ set context ID #endif mov pc, lr diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S index 42ac069c8012..fd045e706390 100644 --- a/arch/arm/mm/proc-v7-2level.S +++ b/arch/arm/mm/proc-v7-2level.S @@ -46,6 +46,11 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif +#ifdef CONFIG_PID_IN_CONTEXTIDR + mrc p15, 0, r2, c13, c0, 1 @ read current context ID + lsr r2, r2, #8 @ extract the PID + bfi r1, r2, #8, #24 @ insert into new context ID +#endif #ifdef CONFIG_ARM_ERRATA_754322 dsb #endif -- GitLab From 546c2896a42202dbc7d02f7c6ec9948ac1bf511b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:43:41 +0100 Subject: [PATCH 2328/5711] ARM: 7446/1: spinlock: use ticket algorithm for ARMv6+ locking implementation Ticket spinlocks ensure locking fairness by introducing a FIFO-like nature to the granting of lock acquisitions and also reducing the thundering herd effect when spinning on a lock by allowing the cacheline to remain in a shared state amongst the waiting CPUs. This is especially important on systems where memory-access times are not necessarily uniform when accessing the lock structure (for example, on a multi-cluster platform where the lock is allocated into L1 when a CPU releases it). This patch implements the ticket spinlock algorithm for ARM, replacing the simpler implementation for ARMv6+ processors. Reviewed-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/spinlock.h | 72 ++++++++++++++++++--------- arch/arm/include/asm/spinlock_types.h | 17 ++++++- 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index 65fa3c88095c..0da2effd4b37 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -59,18 +59,13 @@ static inline void dsb_sev(void) } /* - * ARMv6 Spin-locking. + * ARMv6 ticket-based spin-locking. * - * We exclusively read the old value. If it is zero, we may have - * won the lock, so we try exclusively storing it. A memory barrier - * is required after we get a lock, and before we release it, because - * V6 CPUs are assumed to have weakly ordered memory. - * - * Unlocked value: 0 - * Locked value: 1 + * A memory barrier is required after we get a lock, and before we + * release it, because V6 CPUs are assumed to have weakly ordered + * memory. */ -#define arch_spin_is_locked(x) ((x)->lock != 0) #define arch_spin_unlock_wait(lock) \ do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) @@ -79,31 +74,39 @@ static inline void dsb_sev(void) static inline void arch_spin_lock(arch_spinlock_t *lock) { unsigned long tmp; + u32 newval; + arch_spinlock_t lockval; __asm__ __volatile__( -"1: ldrex %0, [%1]\n" -" teq %0, #0\n" - WFE("ne") -" strexeq %0, %2, [%1]\n" -" teqeq %0, #0\n" +"1: ldrex %0, [%3]\n" +" add %1, %0, %4\n" +" strex %2, %1, [%3]\n" +" teq %2, #0\n" " bne 1b" - : "=&r" (tmp) - : "r" (&lock->lock), "r" (1) + : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) : "cc"); + while (lockval.tickets.next != lockval.tickets.owner) { + wfe(); + lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner); + } + smp_mb(); } static inline int arch_spin_trylock(arch_spinlock_t *lock) { unsigned long tmp; + u32 slock; __asm__ __volatile__( -" ldrex %0, [%1]\n" -" teq %0, #0\n" -" strexeq %0, %2, [%1]" - : "=&r" (tmp) - : "r" (&lock->lock), "r" (1) +" ldrex %0, [%2]\n" +" subs %1, %0, %0, ror #16\n" +" addeq %0, %0, %3\n" +" strexeq %1, %0, [%2]" + : "=&r" (slock), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) : "cc"); if (tmp == 0) { @@ -116,17 +119,38 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) static inline void arch_spin_unlock(arch_spinlock_t *lock) { + unsigned long tmp; + u32 slock; + smp_mb(); __asm__ __volatile__( -" str %1, [%0]\n" - : - : "r" (&lock->lock), "r" (0) +" mov %1, #1\n" +"1: ldrex %0, [%2]\n" +" uadd16 %0, %0, %1\n" +" strex %1, %0, [%2]\n" +" teq %1, #0\n" +" bne 1b" + : "=&r" (slock), "=&r" (tmp) + : "r" (&lock->slock) : "cc"); dsb_sev(); } +static inline int arch_spin_is_locked(arch_spinlock_t *lock) +{ + struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets); + return tickets.owner != tickets.next; +} + +static inline int arch_spin_is_contended(arch_spinlock_t *lock) +{ + struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets); + return (tickets.next - tickets.owner) > 1; +} +#define arch_spin_is_contended arch_spin_is_contended + /* * RWLOCKS * diff --git a/arch/arm/include/asm/spinlock_types.h b/arch/arm/include/asm/spinlock_types.h index d14d197ae04a..b262d2f8b478 100644 --- a/arch/arm/include/asm/spinlock_types.h +++ b/arch/arm/include/asm/spinlock_types.h @@ -5,11 +5,24 @@ # error "please don't include this file directly" #endif +#define TICKET_SHIFT 16 + typedef struct { - volatile unsigned int lock; + union { + u32 slock; + struct __raw_tickets { +#ifdef __ARMEB__ + u16 next; + u16 owner; +#else + u16 owner; + u16 next; +#endif + } tickets; + }; } arch_spinlock_t; -#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } +#define __ARCH_SPIN_LOCK_UNLOCKED { { 0 } } typedef struct { volatile unsigned int lock; -- GitLab From 881ccccb6bd3f0e1fff8b9addbe0de90e0b16166 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:44:13 +0100 Subject: [PATCH 2329/5711] ARM: 7447/1: rwlocks: remove unused branch labels from trylock routines The ARM arch_{read,write}_trylock implementations include unused backwards branch labels, since we don't retry the locking operation if the exclusive store fails. This patch removes the labels. Acked-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/spinlock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index 0da2effd4b37..b4ca707d0a69 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -182,7 +182,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) unsigned long tmp; __asm__ __volatile__( -"1: ldrex %0, [%1]\n" +" ldrex %0, [%1]\n" " teq %0, #0\n" " strexeq %0, %2, [%1]" : "=&r" (tmp) @@ -268,7 +268,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) unsigned long tmp, tmp2 = 1; __asm__ __volatile__( -"1: ldrex %0, [%2]\n" +" ldrex %0, [%2]\n" " adds %0, %0, #1\n" " strexpl %1, %0, [%2]\n" : "=&r" (tmp), "+r" (tmp2) -- GitLab From 4295b898f5a5c7e62ae68e7a4ecc4b414622ffe6 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:45:00 +0100 Subject: [PATCH 2330/5711] ARM: 7448/1: perf: remove arm_perf_pmu_ids global enumeration In order to provide PMU name strings compatible with the OProfile user ABI, an enumeration of all PMUs is currently used by perf to identify each PMU uniquely. Unfortunately, this does not scale well in the presence of multiple PMUs and creates a single, global namespace across all PMUs in the system. This patch removes the enumeration and instead uses the name string for the PMU to map onto the OProfile variant. perf_pmu_name is implemented for CPU PMUs, which is all that OProfile cares about anyway. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/perf_event.h | 17 +---------- arch/arm/include/asm/pmu.h | 3 +- arch/arm/kernel/perf_event.c | 15 ++++------ arch/arm/kernel/perf_event_v6.c | 2 -- arch/arm/kernel/perf_event_v7.c | 5 ---- arch/arm/kernel/perf_event_xscale.c | 2 -- arch/arm/oprofile/common.c | 45 ++++++++++++++++++----------- 7 files changed, 36 insertions(+), 53 deletions(-) diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 00cbe10a50e3..e074948d8143 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -12,21 +12,6 @@ #ifndef __ARM_PERF_EVENT_H__ #define __ARM_PERF_EVENT_H__ -/* ARM perf PMU IDs for use by internal perf clients. */ -enum arm_perf_pmu_ids { - ARM_PERF_PMU_ID_XSCALE1 = 0, - ARM_PERF_PMU_ID_XSCALE2, - ARM_PERF_PMU_ID_V6, - ARM_PERF_PMU_ID_V6MP, - ARM_PERF_PMU_ID_CA8, - ARM_PERF_PMU_ID_CA9, - ARM_PERF_PMU_ID_CA5, - ARM_PERF_PMU_ID_CA15, - ARM_PERF_PMU_ID_CA7, - ARM_NUM_PMU_IDS, -}; - -extern enum arm_perf_pmu_ids -armpmu_get_pmu_id(void); +/* Nothing to see here... */ #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 90114faa9f3c..4432305f4a2a 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -103,10 +103,9 @@ struct pmu_hw_events { struct arm_pmu { struct pmu pmu; - enum arm_perf_pmu_ids id; enum arm_pmu_type type; cpumask_t active_irqs; - const char *name; + char *name; irqreturn_t (*handle_irq)(int irq_num, void *dev); void (*enable)(struct hw_perf_event *evt, int idx); void (*disable)(struct hw_perf_event *evt, int idx); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 186c8cb982c5..df85eda3add3 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -47,17 +47,14 @@ static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); /* Set at runtime when we know what CPU type we are. */ static struct arm_pmu *cpu_pmu; -enum arm_perf_pmu_ids -armpmu_get_pmu_id(void) +const char *perf_pmu_name(void) { - int id = -ENODEV; - - if (cpu_pmu != NULL) - id = cpu_pmu->id; + if (!cpu_pmu) + return NULL; - return id; + return cpu_pmu->pmu.name; } -EXPORT_SYMBOL_GPL(armpmu_get_pmu_id); +EXPORT_SYMBOL_GPL(perf_pmu_name); int perf_num_counters(void) { @@ -760,7 +757,7 @@ init_hw_perf_events(void) cpu_pmu->name, cpu_pmu->num_events); cpu_pmu_init(cpu_pmu); register_cpu_notifier(&pmu_cpu_notifier); - armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); + armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); } else { pr_info("no hardware support available\n"); } diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index ab627a740fa3..c90fcb2b6967 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -650,7 +650,6 @@ static int armv6_map_event(struct perf_event *event) } static struct arm_pmu armv6pmu = { - .id = ARM_PERF_PMU_ID_V6, .name = "v6", .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, @@ -685,7 +684,6 @@ static int armv6mpcore_map_event(struct perf_event *event) } static struct arm_pmu armv6mpcore_pmu = { - .id = ARM_PERF_PMU_ID_V6MP, .name = "v6mpcore", .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index d3c536068162..f04070bd2183 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -1258,7 +1258,6 @@ static u32 __init armv7_read_num_pmnc_events(void) static struct arm_pmu *__init armv7_a8_pmu_init(void) { - armv7pmu.id = ARM_PERF_PMU_ID_CA8; armv7pmu.name = "ARMv7 Cortex-A8"; armv7pmu.map_event = armv7_a8_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1267,7 +1266,6 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void) static struct arm_pmu *__init armv7_a9_pmu_init(void) { - armv7pmu.id = ARM_PERF_PMU_ID_CA9; armv7pmu.name = "ARMv7 Cortex-A9"; armv7pmu.map_event = armv7_a9_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1276,7 +1274,6 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void) static struct arm_pmu *__init armv7_a5_pmu_init(void) { - armv7pmu.id = ARM_PERF_PMU_ID_CA5; armv7pmu.name = "ARMv7 Cortex-A5"; armv7pmu.map_event = armv7_a5_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1285,7 +1282,6 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void) static struct arm_pmu *__init armv7_a15_pmu_init(void) { - armv7pmu.id = ARM_PERF_PMU_ID_CA15; armv7pmu.name = "ARMv7 Cortex-A15"; armv7pmu.map_event = armv7_a15_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1295,7 +1291,6 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void) static struct arm_pmu *__init armv7_a7_pmu_init(void) { - armv7pmu.id = ARM_PERF_PMU_ID_CA7; armv7pmu.name = "ARMv7 Cortex-A7"; armv7pmu.map_event = armv7_a7_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index e34e7254e652..f759fe0bab63 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -435,7 +435,6 @@ static int xscale_map_event(struct perf_event *event) } static struct arm_pmu xscale1pmu = { - .id = ARM_PERF_PMU_ID_XSCALE1, .name = "xscale1", .handle_irq = xscale1pmu_handle_irq, .enable = xscale1pmu_enable_event, @@ -803,7 +802,6 @@ xscale2pmu_write_counter(int counter, u32 val) } static struct arm_pmu xscale2pmu = { - .id = ARM_PERF_PMU_ID_XSCALE2, .name = "xscale2", .handle_irq = xscale2pmu_handle_irq, .enable = xscale2pmu_enable_event, diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 4e0a371630b3..99c63d4b6af8 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -23,26 +23,37 @@ #include #ifdef CONFIG_HW_PERF_EVENTS + +/* + * OProfile has a curious naming scheme for the ARM PMUs, but they are + * part of the user ABI so we need to map from the perf PMU name for + * supported PMUs. + */ +static struct op_perf_name { + char *perf_name; + char *op_name; +} op_perf_name_map[] = { + { "xscale1", "arm/xscale1" }, + { "xscale1", "arm/xscale2" }, + { "v6", "arm/armv6" }, + { "v6mpcore", "arm/mpcore" }, + { "ARMv7 Cortex-A8", "arm/armv7" }, + { "ARMv7 Cortex-A9", "arm/armv7-ca9" }, +}; + char *op_name_from_perf_id(void) { - enum arm_perf_pmu_ids id = armpmu_get_pmu_id(); - - switch (id) { - case ARM_PERF_PMU_ID_XSCALE1: - return "arm/xscale1"; - case ARM_PERF_PMU_ID_XSCALE2: - return "arm/xscale2"; - case ARM_PERF_PMU_ID_V6: - return "arm/armv6"; - case ARM_PERF_PMU_ID_V6MP: - return "arm/mpcore"; - case ARM_PERF_PMU_ID_CA8: - return "arm/armv7"; - case ARM_PERF_PMU_ID_CA9: - return "arm/armv7-ca9"; - default: - return NULL; + int i; + struct op_perf_name names; + const char *perf_name = perf_pmu_name(); + + for (i = 0; i < ARRAY_SIZE(op_perf_name_map); ++i) { + names = op_perf_name_map[i]; + if (!strcmp(names.perf_name, perf_name)) + return names.op_name; } + + return NULL; } #endif -- GitLab From 8c56cc8be5b38e3684eba96dc9b3f7ca7e495755 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:45:39 +0100 Subject: [PATCH 2331/5711] ARM: 7449/1: use generic strnlen_user and strncpy_from_user functions This patch implements the word-at-a-time interface for ARM using the same algorithm as x86. We use the fls macro from ARMv5 onwards, where we have a clz instruction available which saves us a mov instruction when targetting Thumb-2. For older CPUs, we use the magic 0x0ff0001 constant. Big-endian configurations make use of the implementation from asm-generic. With this implemented, we can replace our byte-at-a-time strnlen_user and strncpy_from_user functions with the optimised generic versions. Reviewed-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 2 + arch/arm/include/asm/uaccess.h | 27 +++---------- arch/arm/include/asm/word-at-a-time.h | 55 +++++++++++++++++++++++++++ arch/arm/kernel/armksyms.c | 4 -- arch/arm/lib/Makefile | 1 - arch/arm/lib/strncpy_from_user.S | 43 --------------------- arch/arm/lib/strnlen_user.S | 40 ------------------- 7 files changed, 63 insertions(+), 109 deletions(-) create mode 100644 arch/arm/include/asm/word-at-a-time.h delete mode 100644 arch/arm/lib/strncpy_from_user.S delete mode 100644 arch/arm/lib/strnlen_user.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8c9d264f2108..574561a66d75 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -46,6 +46,8 @@ config ARM select GENERIC_SMP_IDLE_THREAD select KTIME_SCALAR select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 71f6536d17ac..479a6352e0b5 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -189,6 +189,9 @@ static inline void set_fs(mm_segment_t fs) #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#define user_addr_max() \ + (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) + /* * The "__xxx" versions of the user access functions do not verify the * address space - it must have been done previously with a separate @@ -398,9 +401,6 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l #define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) #endif -extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count); -extern unsigned long __must_check __strnlen_user(const char __user *s, long n); - static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) @@ -427,24 +427,9 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo return n; } -static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res = -EFAULT; - if (access_ok(VERIFY_READ, src, 1)) - res = __strncpy_from_user(dst, src, count); - return res; -} - -#define strlen_user(s) strnlen_user(s, ~0UL >> 1) +extern long strncpy_from_user(char *dest, const char __user *src, long count); -static inline long __must_check strnlen_user(const char __user *s, long n) -{ - unsigned long res = 0; - - if (__addr_ok(s)) - res = __strnlen_user(s, n); - - return res; -} +extern __must_check long strlen_user(const char __user *str); +extern __must_check long strnlen_user(const char __user *str, long n); #endif /* _ASMARM_UACCESS_H */ diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h new file mode 100644 index 000000000000..74b2d4578577 --- /dev/null +++ b/arch/arm/include/asm/word-at-a-time.h @@ -0,0 +1,55 @@ +#ifndef __ASM_ARM_WORD_AT_A_TIME_H +#define __ASM_ARM_WORD_AT_A_TIME_H + +#ifndef __ARMEB__ + +/* + * Little-endian word-at-a-time zero byte handling. + * Heavily based on the x86 algorithm. + */ +#include + +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, + const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +#define prep_zero_mask(a, bits, c) (bits) + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +static inline unsigned long find_zero(unsigned long mask) +{ + unsigned long ret; + +#if __LINUX_ARM_ARCH__ >= 5 + /* We have clz available. */ + ret = fls(mask) >> 3; +#else + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + ret = (0x0ff0001 + mask) >> 23; + /* Fix the 1 for 00 case */ + ret &= mask; +#endif + + return ret; +} + +#else /* __ARMEB__ */ +#include +#endif + +#endif /* __ASM_ARM_WORD_AT_A_TIME_H */ diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index b57c75e0b01f..c3dff6abc89d 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -87,10 +87,6 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(__memzero); - /* user mem (segment) */ -EXPORT_SYMBOL(__strnlen_user); -EXPORT_SYMBOL(__strncpy_from_user); - #ifdef CONFIG_MMU EXPORT_SYMBOL(copy_page); diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 992769ae2599..d5060dab6e52 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -8,7 +8,6 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ delay.o findbit.o memchr.o memcpy.o \ memmove.o memset.o memzero.o setbit.o \ - strncpy_from_user.o strnlen_user.o \ strchr.o strrchr.o \ testchangebit.o testclearbit.o testsetbit.o \ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S deleted file mode 100644 index f202d7bd1647..000000000000 --- a/arch/arm/lib/strncpy_from_user.S +++ /dev/null @@ -1,43 +0,0 @@ -/* - * linux/arch/arm/lib/strncpy_from_user.S - * - * Copyright (C) 1995-2000 Russell King - * - * 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 - - .text - .align 5 - -/* - * Copy a string from user space to kernel space. - * r0 = dst, r1 = src, r2 = byte length - * returns the number of characters copied (strlen of copied string), - * -EFAULT on exception, or "len" if we fill the whole buffer - */ -ENTRY(__strncpy_from_user) - mov ip, r1 -1: subs r2, r2, #1 - ldrusr r3, r1, 1, pl - bmi 2f - strb r3, [r0], #1 - teq r3, #0 - bne 1b - sub r1, r1, #1 @ take NUL character out of count -2: sub r0, r1, ip - mov pc, lr -ENDPROC(__strncpy_from_user) - - .pushsection .fixup,"ax" - .align 0 -9001: mov r3, #0 - strb r3, [r0, #0] @ null terminate - mov r0, #-EFAULT - mov pc, lr - .popsection - diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S deleted file mode 100644 index 0ecbb459c4f1..000000000000 --- a/arch/arm/lib/strnlen_user.S +++ /dev/null @@ -1,40 +0,0 @@ -/* - * linux/arch/arm/lib/strnlen_user.S - * - * Copyright (C) 1995-2000 Russell King - * - * 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 - - .text - .align 5 - -/* Prototype: unsigned long __strnlen_user(const char *str, long n) - * Purpose : get length of a string in user memory - * Params : str - address of string in user memory - * Returns : length of string *including terminator* - * or zero on exception, or n + 1 if too long - */ -ENTRY(__strnlen_user) - mov r2, r0 -1: - ldrusr r3, r0, 1 - teq r3, #0 - beq 2f - subs r1, r1, #1 - bne 1b - add r0, r0, #1 -2: sub r0, r0, r2 - mov pc, lr -ENDPROC(__strnlen_user) - - .pushsection .fixup,"ax" - .align 0 -9001: mov r0, #0 - mov pc, lr - .popsection -- GitLab From b9a50f74905ad9126c91b495ece8a5f45434c643 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:46:08 +0100 Subject: [PATCH 2332/5711] ARM: 7450/1: dcache: select DCACHE_WORD_ACCESS for little-endian ARMv6+ CPUs DCACHE_WORD_ACCESS uses the word-at-a-time API for optimised string comparisons in the vfs layer. This patch implements support for load_unaligned_zeropad for ARM CPUs with native support for unaligned memory accesses (v6+) when running little-endian. Reviewed-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/include/asm/word-at-a-time.h | 41 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 574561a66d75..acd12efe6f3e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -48,6 +48,7 @@ config ARM select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER + select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h index 74b2d4578577..4d52f92967a6 100644 --- a/arch/arm/include/asm/word-at-a-time.h +++ b/arch/arm/include/asm/word-at-a-time.h @@ -48,6 +48,47 @@ static inline unsigned long find_zero(unsigned long mask) return ret; } +#ifdef CONFIG_DCACHE_WORD_ACCESS + +#define zero_bytemask(mask) (mask) + +/* + * Load an unaligned word from kernel space. + * + * In the (very unlikely) case of the word being a page-crosser + * and the next page not being mapped, take the exception and + * return zeroes in the non-existing part. + */ +static inline unsigned long load_unaligned_zeropad(const void *addr) +{ + unsigned long ret, offset; + + /* Load word from unaligned pointer addr */ + asm( + "1: ldr %0, [%2]\n" + "2:\n" + " .pushsection .fixup,\"ax\"\n" + " .align 2\n" + "3: and %1, %2, #0x3\n" + " bic %2, %2, #0x3\n" + " ldr %0, [%2]\n" + " lsl %1, %1, #0x3\n" + " lsr %0, %0, %1\n" + " b 2b\n" + " .popsection\n" + " .pushsection __ex_table,\"a\"\n" + " .align 3\n" + " .long 1b, 3b\n" + " .popsection" + : "=&r" (ret), "=&r" (offset) + : "r" (addr), "Qo" (*(unsigned long *)addr)); + + return ret; +} + + +#endif /* DCACHE_WORD_ACCESS */ + #else /* __ARMEB__ */ #include #endif -- GitLab From 923df96b9f31b7d08d8438ff9677326d9537accf Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:46:45 +0100 Subject: [PATCH 2333/5711] ARM: 7451/1: arch timer: implement read_current_timer and get_cycles This patch implements read_current_timer using the architected timers when they are selected via CONFIG_ARM_ARCH_TIMER. If they are detected not to be usable at runtime, we return -ENXIO to the caller. Furthermore, if read_current_timer is exported then we can implement get_cycles in terms of it for use as both an entropy source and for implementing __udelay and friends. Tested-by: Shinya Kuribayashi Reviewed-by: Stephen Boyd Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/arch_timer.h | 3 +++ arch/arm/include/asm/timex.h | 10 ++++++---- arch/arm/kernel/arch_timer.c | 8 ++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index ed2e95d46e29..62e75475e57e 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -1,7 +1,10 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H +#include + #ifdef CONFIG_ARM_ARCH_TIMER +#define ARCH_HAS_READ_CURRENT_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); #else diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h index 3be8de3adaba..ce119442277c 100644 --- a/arch/arm/include/asm/timex.h +++ b/arch/arm/include/asm/timex.h @@ -12,13 +12,15 @@ #ifndef _ASMARM_TIMEX_H #define _ASMARM_TIMEX_H +#include #include typedef unsigned long cycles_t; -static inline cycles_t get_cycles (void) -{ - return 0; -} +#ifdef ARCH_HAS_READ_CURRENT_TIMER +#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; }) +#else +#define get_cycles() (0) +#endif #endif diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dd58035621f7..dbbeec4f06e2 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -223,6 +223,14 @@ static cycle_t arch_counter_read(struct clocksource *cs) return arch_counter_get_cntpct(); } +int read_current_timer(unsigned long *timer_val) +{ + if (!arch_timer_rate) + return -ENXIO; + *timer_val = arch_counter_get_cntpct(); + return 0; +} + static struct clocksource clocksource_counter = { .name = "arch_sys_counter", .rating = 400, -- GitLab From d0a533b18235d36206b9b422efadb7cee444dfdb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:47:17 +0100 Subject: [PATCH 2334/5711] ARM: 7452/1: delay: allow timer-based delay implementation to be selected This patch allows a timer-based delay implementation to be selected by switching the delay routines over to use get_cycles, which is implemented in terms of read_current_timer. This further allows us to skip the loop calibration and have a consistent delay function in the face of core frequency scaling. To avoid the pain of dealing with memory-mapped counters, this implementation uses the co-processor interface to the architected timers when they are available. The previous loop-based implementation is kept around for CPUs without the architected timers and we retain both the maximum delay (2ms) and the corresponding conversion factors for determining the number of loops required for a given interval. Since the indirection of the timer routines will only work when called from C, the sa1100 sleep routines are modified to branch to the loop-based delay functions directly. Tested-by: Shinya Kuribayashi Reviewed-by: Stephen Boyd Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/delay.h | 32 +++++++++--- arch/arm/kernel/arch_timer.c | 3 ++ arch/arm/kernel/armksyms.c | 3 +- arch/arm/lib/Makefile | 2 +- arch/arm/lib/{delay.S => delay-loop.S} | 20 ++++---- arch/arm/lib/delay.c | 71 ++++++++++++++++++++++++++ arch/arm/mach-sa1100/sleep.S | 8 +-- 7 files changed, 114 insertions(+), 25 deletions(-) rename arch/arm/lib/{delay.S => delay-loop.S} (81%) create mode 100644 arch/arm/lib/delay.c diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index b2deda181549..dc6145120de3 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -6,9 +6,22 @@ #ifndef __ASM_ARM_DELAY_H #define __ASM_ARM_DELAY_H +#include #include /* HZ */ -extern void __delay(int loops); +#define MAX_UDELAY_MS 2 +#define UDELAY_MULT ((UL(2199023) * HZ) >> 11) +#define UDELAY_SHIFT 30 + +#ifndef __ASSEMBLY__ + +extern struct arm_delay_ops { + void (*delay)(unsigned long); + void (*const_udelay)(unsigned long); + void (*udelay)(unsigned long); +} arm_delay_ops; + +#define __delay(n) arm_delay_ops.delay(n) /* * This function intentionally does not exist; if you see references to @@ -23,22 +36,27 @@ extern void __bad_udelay(void); * division by multiplication: you don't have to worry about * loss of precision. * - * Use only for very small delays ( < 1 msec). Should probably use a + * Use only for very small delays ( < 2 msec). Should probably use a * lookup table, really, as the multiplications take much too long with * short delays. This is a "reasonable" implementation, though (and the * first constant multiplications gets optimized away if the delay is * a constant) */ -extern void __udelay(unsigned long usecs); -extern void __const_udelay(unsigned long); - -#define MAX_UDELAY_MS 2 +#define __udelay(n) arm_delay_ops.udelay(n) +#define __const_udelay(n) arm_delay_ops.const_udelay(n) #define udelay(n) \ (__builtin_constant_p(n) ? \ ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \ - __const_udelay((n) * ((2199023U*HZ)>>11))) : \ + __const_udelay((n) * UDELAY_MULT)) : \ __udelay(n)) +/* Loop-based definitions for assembly code. */ +extern void __loop_delay(unsigned long loops); +extern void __loop_udelay(unsigned long usecs); +extern void __loop_const_udelay(unsigned long); + +#endif /* __ASSEMBLY__ */ + #endif /* defined(_ARM_DELAY_H) */ diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dbbeec4f06e2..675cee09c014 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -32,6 +32,8 @@ static int arch_timer_ppi2; static struct clock_event_device __percpu **arch_timer_evt; +extern void init_current_timer_delay(unsigned long freq); + /* * Architected system timer support. */ @@ -304,6 +306,7 @@ static int __init arch_timer_register(void) if (err) goto out_free_irq; + init_current_timer_delay(arch_timer_rate); return 0; out_free_irq: diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index b57c75e0b01f..71962284d288 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -49,8 +49,7 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); /* platform dependent support */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(arm_delay_ops); /* networking */ EXPORT_SYMBOL(csum_partial); diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 992769ae2599..b621114644fd 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -6,7 +6,7 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ - delay.o findbit.o memchr.o memcpy.o \ + delay.o delay-loop.o findbit.o memchr.o memcpy.o \ memmove.o memset.o memzero.o setbit.o \ strncpy_from_user.o strnlen_user.o \ strchr.o strrchr.o \ diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay-loop.S similarity index 81% rename from arch/arm/lib/delay.S rename to arch/arm/lib/delay-loop.S index 3c9a05c8d20b..36b668d8e121 100644 --- a/arch/arm/lib/delay.S +++ b/arch/arm/lib/delay-loop.S @@ -9,11 +9,11 @@ */ #include #include -#include +#include .text .LC0: .word loops_per_jiffy -.LC1: .word (2199023*HZ)>>11 +.LC1: .word UDELAY_MULT /* * r0 <= 2000 @@ -21,10 +21,10 @@ * HZ <= 1000 */ -ENTRY(__udelay) +ENTRY(__loop_udelay) ldr r2, .LC1 mul r0, r2, r0 -ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 +ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06 mov r1, #-1 ldr r2, .LC0 ldr r2, [r2] @ max = 0x01ffffff @@ -39,12 +39,10 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 /* * loops = r0 * HZ * loops_per_jiffy / 1000000 - * - * Oh, if only we had a cycle counter... */ @ Delay routine -ENTRY(__delay) +ENTRY(__loop_delay) subs r0, r0, #1 #if 0 movls pc, lr @@ -62,8 +60,8 @@ ENTRY(__delay) movls pc, lr subs r0, r0, #1 #endif - bhi __delay + bhi __loop_delay mov pc, lr -ENDPROC(__udelay) -ENDPROC(__const_udelay) -ENDPROC(__delay) +ENDPROC(__loop_udelay) +ENDPROC(__loop_const_udelay) +ENDPROC(__loop_delay) diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c new file mode 100644 index 000000000000..d6dacc69254e --- /dev/null +++ b/arch/arm/lib/delay.c @@ -0,0 +1,71 @@ +/* + * Delay loops based on the OpenRISC implementation. + * + * Copyright (C) 2012 ARM Limited + * + * 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; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Will Deacon + */ + +#include +#include +#include +#include +#include + +/* + * Default to the loop-based delay implementation. + */ +struct arm_delay_ops arm_delay_ops = { + .delay = __loop_delay, + .const_udelay = __loop_const_udelay, + .udelay = __loop_udelay, +}; + +#ifdef ARCH_HAS_READ_CURRENT_TIMER +static void __timer_delay(unsigned long cycles) +{ + cycles_t start = get_cycles(); + + while ((get_cycles() - start) < cycles) + cpu_relax(); +} + +static void __timer_const_udelay(unsigned long xloops) +{ + unsigned long long loops = xloops; + loops *= loops_per_jiffy; + __timer_delay(loops >> UDELAY_SHIFT); +} + +static void __timer_udelay(unsigned long usecs) +{ + __timer_const_udelay(usecs * UDELAY_MULT); +} + +void __init init_current_timer_delay(unsigned long freq) +{ + pr_info("Switching to timer-based delay loop\n"); + lpj_fine = freq / HZ; + arm_delay_ops.delay = __timer_delay; + arm_delay_ops.const_udelay = __timer_const_udelay; + arm_delay_ops.udelay = __timer_udelay; +} + +unsigned long __cpuinit calibrate_delay_is_known(void) +{ + return lpj_fine; +} +#endif diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 30cc6721665b..85863741ef8b 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -38,9 +38,9 @@ ENTRY(sa1100_finish_suspend) orr r4, r4, #MDREFR_K1DB2 ldr r5, =PPCR - @ Pre-load __udelay into the I-cache + @ Pre-load __loop_udelay into the I-cache mov r0, #1 - bl __udelay + bl __loop_udelay mov r0, r0 @ The following must all exist in a single cache line to @@ -53,11 +53,11 @@ ENTRY(sa1100_finish_suspend) @ delay 90us and set CPU PLL to lowest speed @ fixes resume problem on high speed SA1110 mov r0, #90 - bl __udelay + bl __loop_udelay mov r1, #0 str r1, [r5] mov r0, #90 - bl __udelay + bl __loop_udelay /* * SA1110 SDRAM controller workaround. register values: -- GitLab From 8f827a1468c51c82443a78d15e67fe92022cd5b9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:48:16 +0100 Subject: [PATCH 2335/5711] ARM: 7453/1: audit: only allow syscall auditing for pure EABI userspace The audit tools support only EABI userspace and, since there are no AUDIT_ARCH_* defines for the ARM OABI, it makes sense to allow syscall auditing on ARM only for EABI at the moment. Cc: Eric Paris Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index d07dcf9fc8a9..b3f55f15e107 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -357,7 +357,7 @@ config AUDIT config AUDITSYSCALL bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || ARM) + depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT)) default y if SECURITY_SELINUX help Enable low-overhead system-call auditing infrastructure that -- GitLab From 64284a9f8a91b2f1af577f78fabe05d8072cb6e6 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:48:50 +0100 Subject: [PATCH 2336/5711] ARM: 7454/1: entry: don't bother with syscall tracing on ret_from_fork path ret_from_fork is setup for a freshly spawned child task via copy_thread, called from copy_process. The latter function clears TIF_SYSCALL_TRACE and also resets the child task's audit_context to NULL, meaning that there is little point invoking the system call tracing routines. Furthermore, getting hold of the syscall number is a complete pain and it looks like the current code doesn't even bother. This patch removes the syscall tracing checks from ret_from_fork. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 4afed88d250a..10911c93fbf1 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -95,13 +95,7 @@ ENDPROC(ret_to_user) ENTRY(ret_from_fork) bl schedule_tail get_thread_info tsk - ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing mov why, #1 - tst r1, #_TIF_SYSCALL_WORK @ are we tracing syscalls? - beq ret_slow_syscall - mov r1, sp - mov r0, #1 @ trace exit [IP = 1] - bl syscall_trace b ret_slow_syscall ENDPROC(ret_from_fork) -- GitLab From 5125430cccc41f67bfe024394a302901034f6d39 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:49:27 +0100 Subject: [PATCH 2337/5711] ARM: 7455/1: audit: move syscall auditing until after ptrace SIGTRAP handling When auditing system calls on ARM, the audit code is called before notifying the parent process in the case that the current task is being ptraced. At this point, the parent (debugger) may choose to change the system call being issued via the SET_SYSCALL ptrace request, causing the wrong system call to be reported to the audit tools. This patch moves the audit calls after the ptrace SIGTRAP handling code in the syscall tracing implementation. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/ptrace.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 14e38261cd31..592a39d0ef31 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -911,14 +911,8 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) { unsigned long ip; - if (why) - audit_syscall_exit(regs); - else - audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, - regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return scno; + goto out_no_trace; current_thread_info()->syscall = scno; @@ -935,6 +929,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) current_thread_info()->syscall = -1; regs->ARM_ip = ip; + scno = current_thread_info()->syscall; - return current_thread_info()->syscall; +out_no_trace: + if (why) + audit_syscall_exit(regs); + else + audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, + regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); + return scno; } -- GitLab From ad722541147e6e517a2077e3d944105e7bc4fa8e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 6 Jul 2012 15:50:14 +0100 Subject: [PATCH 2338/5711] ARM: 7456/1: ptrace: provide separate functions for tracing syscall {entry,exit} The syscall_trace on ARM takes a `why' parameter to indicate whether or not we are entering or exiting a system call. This can be confusing for people looking at the code since (a) it conflicts with the why register alias in the entry assembly code and (b) it is not immediately clear what it represents. This patch splits up the syscall_trace function into separate wrappers for syscall entry and exit, allowing the low-level syscall handling code to branch to the appropriate function. Reported-by: Al Viro Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 14 ++++++------- arch/arm/kernel/ptrace.c | 37 +++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 10911c93fbf1..49d9f9305247 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -442,10 +442,9 @@ ENDPROC(vector_swi) * context switches, and waiting for our parent to respond. */ __sys_trace: - mov r2, scno - add r1, sp, #S_OFF - mov r0, #0 @ trace entry [IP = 0] - bl syscall_trace + mov r1, scno + add r0, sp, #S_OFF + bl syscall_trace_enter adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) @@ -457,10 +456,9 @@ __sys_trace: __sys_trace_return: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 - mov r2, scno - mov r1, sp - mov r0, #1 @ trace exit [IP = 1] - bl syscall_trace + mov r1, scno + mov r0, sp + bl syscall_trace_exit b ret_slow_syscall .align 5 diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 592a39d0ef31..dab711e6e1ca 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -907,12 +907,18 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) +enum ptrace_syscall_dir { + PTRACE_SYSCALL_ENTER = 0, + PTRACE_SYSCALL_EXIT, +}; + +static int ptrace_syscall_trace(struct pt_regs *regs, int scno, + enum ptrace_syscall_dir dir) { unsigned long ip; if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out_no_trace; + return scno; current_thread_info()->syscall = scno; @@ -921,21 +927,28 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) * IP = 0 -> entry, =1 -> exit */ ip = regs->ARM_ip; - regs->ARM_ip = why; + regs->ARM_ip = dir; - if (why) + if (dir == PTRACE_SYSCALL_EXIT) tracehook_report_syscall_exit(regs, 0); else if (tracehook_report_syscall_entry(regs)) current_thread_info()->syscall = -1; regs->ARM_ip = ip; - scno = current_thread_info()->syscall; + return current_thread_info()->syscall; +} -out_no_trace: - if (why) - audit_syscall_exit(regs); - else - audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, - regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); - return scno; +asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) +{ + int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); + audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, + regs->ARM_r2, regs->ARM_r3); + return ret; +} + +asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) +{ + int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); + audit_syscall_exit(regs); + return ret; } -- GitLab From fe2072cc1768b0f979195acf19b8ccd381e541c3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 9 Jul 2012 15:57:00 +0200 Subject: [PATCH 2339/5711] usb/hcd: Ensure scatter-gather is not used for isoc transfers We don't support sg for isoc transfers, enforce this. Signed-off-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 190b1ec7bdcb..bc84106ac057 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1398,7 +1398,15 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { if (hcd->self.uses_dma) { if (urb->num_sgs) { - int n = dma_map_sg( + int n; + + /* We don't support sg for isoc transfers ! */ + if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { + WARN_ON(1); + return -EINVAL; + } + + n = dma_map_sg( hcd->self.controller, urb->sg, urb->num_sgs, -- GitLab From 277bd8746bb8d23c00ff8343e58df783544e961e Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 9 Jul 2012 12:04:40 +0530 Subject: [PATCH 2340/5711] drivers: usb: otg: fix build break in twl6030-usb.c Fixed a mistake in the merge conflict resoultion commit(ff9cce) in file twl6030-usb.c Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/twl6030-usb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index a3d0c0405cca..6907d8df7a27 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -302,8 +302,6 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); status = OMAP_MUSB_ID_GROUND; - otg->default_a = true; - twl->phy.state = OTG_STATE_A_IDLE; twl->linkstat = status; omap_musb_mailbox(status); } else { -- GitLab From 2f0de9d844d6c08a8e9059ed0b8d3d5ab6b7911b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 8 Jul 2012 23:10:28 -0700 Subject: [PATCH 2341/5711] usb: renesas_usbhs: use dmaengine helper functions This patch used dmaengine helper functions instead of using hand setting. Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/fifo.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 6ec7f838d7fa..d5272d4714ce 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -771,22 +771,15 @@ static void xfer_work(struct work_struct *work) struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); - struct scatterlist sg; struct dma_async_tx_descriptor *desc; struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); struct device *dev = usbhs_priv_to_dev(priv); enum dma_transfer_direction dir; - dma_cookie_t cookie; dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; - sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(pkt->dma), - pkt->length, offset_in_page(pkt->dma)); - sg_dma_address(&sg) = pkt->dma + pkt->actual; - sg_dma_len(&sg) = pkt->trans; - - desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, + desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual, + pkt->trans, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) return; @@ -794,8 +787,7 @@ static void xfer_work(struct work_struct *work) desc->callback = usbhsf_dma_complete; desc->callback_param = pipe; - cookie = desc->tx_submit(desc); - if (cookie < 0) { + if (dmaengine_submit(desc) < 0) { dev_err(dev, "Failed to submit dma descriptor\n"); return; } -- GitLab From 26c696c678c4ce180599330999e895cded0f625b Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:40 +0800 Subject: [PATCH 2342/5711] USB: Chipidea: rename struct ci13xxx variables from udc to ci struct ci13xxx represent the controller, which may be device or host, so name its variables as ci. Signed-off-by: Richard Zhao Reviewed-by: Felipe Balbi Signed-off-by: Alexander Shishkin Reviewed-by: Marek Vasut Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci.h | 26 +- drivers/usb/chipidea/ci13xxx_msm.c | 12 +- drivers/usb/chipidea/debug.c | 146 +++---- drivers/usb/chipidea/udc.c | 628 ++++++++++++++--------------- include/linux/usb/chipidea.h | 2 +- 5 files changed, 407 insertions(+), 407 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 0b093308548d..9655e3569d4c 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -36,7 +36,7 @@ * @name: string description of the endpoint * @qh: queue head for this endpoint * @wedge: is the endpoint wedged - * @udc: pointer to the controller + * @ci: pointer to the controller * @lock: pointer to controller's spinlock * @td_pool: pointer to controller's TD pool */ @@ -54,7 +54,7 @@ struct ci13xxx_ep { int wedge; /* global resources */ - struct ci13xxx *udc; + struct ci13xxx *ci; spinlock_t *lock; struct dma_pool *td_pool; }; @@ -250,9 +250,9 @@ static inline int ffs_nr(u32 x) * * This function returns register contents */ -static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask) +static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) { - return ioread32(udc->hw_bank.regmap[reg]) & mask; + return ioread32(ci->hw_bank.regmap[reg]) & mask; } /** @@ -261,14 +261,14 @@ static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask) * @mask: bitfield mask * @data: new value */ -static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, +static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask, u32 data) { if (~mask) - data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask) + data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask) | (data & mask); - iowrite32(data, udc->hw_bank.regmap[reg]); + iowrite32(data, ci->hw_bank.regmap[reg]); } /** @@ -278,12 +278,12 @@ static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, * * This function returns register contents */ -static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg, +static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) { - u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask; + u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; - iowrite32(val, udc->hw_bank.regmap[reg]); + iowrite32(val, ci->hw_bank.regmap[reg]); return val; } @@ -295,12 +295,12 @@ static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg, * * This function returns register contents */ -static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg, +static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask, u32 data) { - u32 val = hw_read(udc, reg, ~0); + u32 val = hw_read(ci, reg, ~0); - hw_write(udc, reg, mask, data); + hw_write(ci, reg, mask, data); return (val & mask) >> ffs_nr(mask); } diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index 12c0dd6a300c..5a2fe5f9b6c3 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -15,11 +15,11 @@ #include "ci.h" -#define MSM_USB_BASE (udc->hw_bank.abs) +#define MSM_USB_BASE (ci->hw_bank.abs) -static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) +static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) { - struct device *dev = udc->gadget.dev.parent; + struct device *dev = ci->gadget.dev.parent; int val; switch (event) { @@ -34,13 +34,13 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. */ - val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL); + val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); + usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); break; default: - dev_dbg(dev, "unknown ci13xxx_udc event\n"); + dev_dbg(dev, "unknown ci13xxx event\n"); break; } } diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index c4b3e15532db..c6f50a257565 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -68,15 +68,15 @@ void dbg_interrupt(u32 intmask) * * This function returns number of registers read */ -static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size) +static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size) { unsigned i; - if (size > udc->hw_bank.size) - size = udc->hw_bank.size; + if (size > ci->hw_bank.size) + size = ci->hw_bank.size; for (i = 0; i < size; i++) - buf[i] = hw_read(udc, i * sizeof(u32), ~0); + buf[i] = hw_read(ci, i * sizeof(u32), ~0); return size; } @@ -88,18 +88,18 @@ static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size) * * This function returns an error code */ -static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data) +static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data) { /* align */ addr /= sizeof(u32); - if (addr >= udc->hw_bank.size) + if (addr >= ci->hw_bank.size) return -EINVAL; /* align */ addr *= sizeof(u32); - hw_write(udc, addr, ~0, data); + hw_write(ci, addr, ~0, data); return 0; } @@ -110,13 +110,13 @@ static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data) * * This function returns an error code */ -static int hw_intr_clear(struct ci13xxx *udc, int n) +static int hw_intr_clear(struct ci13xxx *ci, int n) { if (n >= REG_BITS) return -EINVAL; - hw_write(udc, OP_USBINTR, BIT(n), 0); - hw_write(udc, OP_USBSTS, BIT(n), BIT(n)); + hw_write(ci, OP_USBINTR, BIT(n), 0); + hw_write(ci, OP_USBSTS, BIT(n), BIT(n)); return 0; } @@ -127,15 +127,15 @@ static int hw_intr_clear(struct ci13xxx *udc, int n) * * This function returns an error code */ -static int hw_intr_force(struct ci13xxx *udc, int n) +static int hw_intr_force(struct ci13xxx *ci, int n) { if (n >= REG_BITS) return -EINVAL; - hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); - hw_write(udc, OP_USBINTR, BIT(n), BIT(n)); - hw_write(udc, OP_USBSTS, BIT(n), BIT(n)); - hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0); + hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); + hw_write(ci, OP_USBINTR, BIT(n), BIT(n)); + hw_write(ci, OP_USBSTS, BIT(n), BIT(n)); + hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0); return 0; } @@ -147,12 +147,12 @@ static int hw_intr_force(struct ci13xxx *udc, int n) static ssize_t show_device(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); - struct usb_gadget *gadget = &udc->gadget; + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); + struct usb_gadget *gadget = &ci->gadget; int n = 0; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); return 0; } @@ -188,8 +188,8 @@ static DEVICE_ATTR(device, S_IRUSR, show_device, NULL); static ssize_t show_driver(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); - struct usb_gadget_driver *driver = udc->driver; + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); + struct usb_gadget_driver *driver = ci->driver; int n = 0; if (attr == NULL || buf == NULL) { @@ -412,22 +412,22 @@ static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events); static ssize_t show_inters(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; u32 intr; unsigned i, j, n = 0; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); return 0; } - spin_lock_irqsave(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); /*n += scnprintf(buf + n, PAGE_SIZE - n, - "status = %08x\n", hw_read_intr_status(udc)); + "status = %08x\n", hw_read_intr_status(ci)); n += scnprintf(buf + n, PAGE_SIZE - n, - "enable = %08x\n", hw_read_intr_enable(udc));*/ + "enable = %08x\n", hw_read_intr_enable(ci));*/ n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n", isr_statistics.test); @@ -471,7 +471,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr, n += scnprintf(buf + n, PAGE_SIZE - n, "\n"); } - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return n; } @@ -485,31 +485,31 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr, static ssize_t store_inters(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; unsigned en, bit; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "EINVAL\n"); + dev_err(ci->dev, "EINVAL\n"); goto done; } if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) { - dev_err(udc->dev, "<1|0> : enable|disable interrupt\n"); + dev_err(ci->dev, "<1|0> : enable|disable interrupt\n"); goto done; } - spin_lock_irqsave(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); if (en) { - if (hw_intr_force(udc, bit)) + if (hw_intr_force(ci, bit)) dev_err(dev, "invalid bit number\n"); else isr_statistics.test++; } else { - if (hw_intr_clear(udc, bit)) + if (hw_intr_clear(ci, bit)) dev_err(dev, "invalid bit number\n"); } - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); done: return count; @@ -524,18 +524,18 @@ static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters); static ssize_t show_port_test(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; unsigned mode; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "EINVAL\n"); + dev_err(ci->dev, "EINVAL\n"); return 0; } - spin_lock_irqsave(&udc->lock, flags); - mode = hw_port_test_get(udc); - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + mode = hw_port_test_get(ci); + spin_unlock_irqrestore(&ci->lock, flags); return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode); } @@ -549,24 +549,24 @@ static ssize_t store_port_test(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; unsigned mode; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); goto done; } if (sscanf(buf, "%u", &mode) != 1) { - dev_err(udc->dev, ": set port test mode"); + dev_err(ci->dev, ": set port test mode"); goto done; } - spin_lock_irqsave(&udc->lock, flags); - if (hw_port_test_set(udc, mode)) - dev_err(udc->dev, "invalid mode\n"); - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + if (hw_port_test_set(ci, mode)) + dev_err(ci->dev, "invalid mode\n"); + spin_unlock_irqrestore(&ci->lock, flags); done: return count; @@ -582,20 +582,20 @@ static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR, static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; unsigned i, j, n = 0; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); return 0; } - spin_lock_irqsave(&udc->lock, flags); - for (i = 0; i < udc->hw_ep_max/2; i++) { - struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i]; + spin_lock_irqsave(&ci->lock, flags); + for (i = 0; i < ci->hw_ep_max/2; i++) { + struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; struct ci13xxx_ep *mEpTx = - &udc->ci13xxx_ep[i + udc->hw_ep_max/2]; + &ci->ci13xxx_ep[i + ci->hw_ep_max/2]; n += scnprintf(buf + n, PAGE_SIZE - n, "EP=%02i: RX=%08X TX=%08X\n", i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); @@ -606,7 +606,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, *((u32 *)mEpTx->qh.ptr + j)); } } - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return n; } @@ -621,25 +621,25 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); static ssize_t show_registers(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; u32 *dump; unsigned i, k, n = 0; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); return 0; } dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); if (!dump) { - dev_err(udc->dev, "%s: out of memory\n", __func__); + dev_err(ci->dev, "%s: out of memory\n", __func__); return 0; } - spin_lock_irqsave(&udc->lock, flags); - k = hw_register_read(udc, dump, DUMP_ENTRIES); - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + k = hw_register_read(ci, dump, DUMP_ENTRIES); + spin_unlock_irqrestore(&ci->lock, flags); for (i = 0; i < k; i++) { n += scnprintf(buf + n, PAGE_SIZE - n, @@ -660,24 +660,24 @@ static ssize_t store_registers(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long addr, data, flags; if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); goto done; } if (sscanf(buf, "%li %li", &addr, &data) != 2) { - dev_err(udc->dev, + dev_err(ci->dev, " : write data to register address\n"); goto done; } - spin_lock_irqsave(&udc->lock, flags); - if (hw_register_write(udc, addr, data)) - dev_err(udc->dev, "invalid address range\n"); - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + if (hw_register_write(ci, addr, data)) + dev_err(ci->dev, "invalid address range\n"); + spin_unlock_irqrestore(&ci->lock, flags); done: return count; @@ -693,34 +693,34 @@ static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR, static ssize_t show_requests(struct device *dev, struct device_attribute *attr, char *buf) { - struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); + struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; struct list_head *ptr = NULL; struct ci13xxx_req *req = NULL; unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); if (attr == NULL || buf == NULL) { - dev_err(udc->dev, "[%s] EINVAL\n", __func__); + dev_err(ci->dev, "[%s] EINVAL\n", __func__); return 0; } - spin_lock_irqsave(&udc->lock, flags); - for (i = 0; i < udc->hw_ep_max; i++) - list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) + spin_lock_irqsave(&ci->lock, flags); + for (i = 0; i < ci->hw_ep_max; i++) + list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) { req = list_entry(ptr, struct ci13xxx_req, queue); n += scnprintf(buf + n, PAGE_SIZE - n, "EP=%02i: TD=%08X %s\n", - i % udc->hw_ep_max/2, (u32)req->dma, - ((i < udc->hw_ep_max/2) ? "RX" : "TX")); + i % ci->hw_ep_max/2, (u32)req->dma, + ((i < ci->hw_ep_max/2) ? "RX" : "TX")); for (j = 0; j < qSize; j++) n += scnprintf(buf + n, PAGE_SIZE - n, " %04X: %08X\n", j, *((u32 *)req->ptr + j)); } - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return n; } diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 3094c85dc0b5..ba8284e2a237 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -67,11 +67,11 @@ static inline int hw_ep_bit(int num, int dir) return num + (dir ? 16 : 0); } -static inline int ep_to_bit(struct ci13xxx *udc, int n) +static inline int ep_to_bit(struct ci13xxx *ci, int n) { - int fill = 16 - udc->hw_ep_max / 2; + int fill = 16 - ci->hw_ep_max / 2; - if (n >= udc->hw_ep_max / 2) + if (n >= ci->hw_ep_max / 2) n += fill; return n; @@ -84,17 +84,17 @@ static inline int ep_to_bit(struct ci13xxx *udc, int n) * * This function returns an error code */ -static int hw_device_state(struct ci13xxx *udc, u32 dma) +static int hw_device_state(struct ci13xxx *ci, u32 dma) { if (dma) { - hw_write(udc, OP_ENDPTLISTADDR, ~0, dma); + hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); /* interrupt, error, port change, reset, sleep/suspend */ - hw_write(udc, OP_USBINTR, ~0, + hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); - hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS); + hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); } else { - hw_write(udc, OP_USBCMD, USBCMD_RS, 0); - hw_write(udc, OP_USBINTR, ~0, 0); + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); + hw_write(ci, OP_USBINTR, ~0, 0); } return 0; } @@ -106,16 +106,16 @@ static int hw_device_state(struct ci13xxx *udc, u32 dma) * * This function returns an error code */ -static int hw_ep_flush(struct ci13xxx *udc, int num, int dir) +static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) { int n = hw_ep_bit(num, dir); do { /* flush any pending transfer */ - hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n)); - while (hw_read(udc, OP_ENDPTFLUSH, BIT(n))) + hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); + while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) cpu_relax(); - } while (hw_read(udc, OP_ENDPTSTAT, BIT(n))); + } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); return 0; } @@ -127,10 +127,10 @@ static int hw_ep_flush(struct ci13xxx *udc, int num, int dir) * * This function returns an error code */ -static int hw_ep_disable(struct ci13xxx *udc, int num, int dir) +static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) { - hw_ep_flush(udc, num, dir); - hw_write(udc, OP_ENDPTCTRL + num, + hw_ep_flush(ci, num, dir); + hw_write(ci, OP_ENDPTCTRL + num, dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); return 0; } @@ -143,7 +143,7 @@ static int hw_ep_disable(struct ci13xxx *udc, int num, int dir) * * This function returns an error code */ -static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) +static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) { u32 mask, data; @@ -166,7 +166,7 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) mask |= ENDPTCTRL_RXE; /* enable */ data |= ENDPTCTRL_RXE; } - hw_write(udc, OP_ENDPTCTRL + num, mask, data); + hw_write(ci, OP_ENDPTCTRL + num, mask, data); return 0; } @@ -177,11 +177,11 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type) * * This function returns 1 if endpoint halted */ -static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir) +static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) { u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; - return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0; + return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; } /** @@ -191,10 +191,10 @@ static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir) * * This function returns setup status */ -static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n) +static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) { - n = ep_to_bit(udc, n); - return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n)); + n = ep_to_bit(ci, n); + return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); } /** @@ -205,18 +205,18 @@ static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n) * * This function returns an error code */ -static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl) +static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) { int n = hw_ep_bit(num, dir); - if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num))) + if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; - hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n)); + hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); - while (hw_read(udc, OP_ENDPTPRIME, BIT(n))) + while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) cpu_relax(); - if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num))) + if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; /* status shoult be tested according with manual but it doesn't work */ @@ -232,7 +232,7 @@ static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl) * * This function returns an error code */ -static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) +static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) { if (value != 0 && value != 1) return -EINVAL; @@ -243,9 +243,9 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; /* data toggle - reserved for EP0 but it's in ESS */ - hw_write(udc, reg, mask_xs|mask_xr, + hw_write(ci, reg, mask_xs|mask_xr, value ? mask_xs : mask_xr); - } while (value != hw_ep_get_halt(udc, num, dir)); + } while (value != hw_ep_get_halt(ci, num, dir)); return 0; } @@ -255,10 +255,10 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value) * * This function returns true if high speed port */ -static int hw_port_is_high_speed(struct ci13xxx *udc) +static int hw_port_is_high_speed(struct ci13xxx *ci) { - return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) : - hw_read(udc, OP_PORTSC, PORTSC_HSP); + return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : + hw_read(ci, OP_PORTSC, PORTSC_HSP); } /** @@ -266,9 +266,9 @@ static int hw_port_is_high_speed(struct ci13xxx *udc) * * This function returns register data */ -static u32 hw_read_intr_enable(struct ci13xxx *udc) +static u32 hw_read_intr_enable(struct ci13xxx *ci) { - return hw_read(udc, OP_USBINTR, ~0); + return hw_read(ci, OP_USBINTR, ~0); } /** @@ -276,9 +276,9 @@ static u32 hw_read_intr_enable(struct ci13xxx *udc) * * This function returns register data */ -static u32 hw_read_intr_status(struct ci13xxx *udc) +static u32 hw_read_intr_status(struct ci13xxx *ci) { - return hw_read(udc, OP_USBSTS, ~0); + return hw_read(ci, OP_USBSTS, ~0); } /** @@ -288,10 +288,10 @@ static u32 hw_read_intr_status(struct ci13xxx *udc) * * This function returns complete status */ -static int hw_test_and_clear_complete(struct ci13xxx *udc, int n) +static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) { - n = ep_to_bit(udc, n); - return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n)); + n = ep_to_bit(ci, n); + return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); } /** @@ -300,11 +300,11 @@ static int hw_test_and_clear_complete(struct ci13xxx *udc, int n) * * This function returns active interrutps */ -static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc) +static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) { - u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc); + u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); - hw_write(udc, OP_USBSTS, ~0, reg); + hw_write(ci, OP_USBSTS, ~0, reg); return reg; } @@ -314,9 +314,9 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc) * * This function returns guard value */ -static int hw_test_and_clear_setup_guard(struct ci13xxx *udc) +static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) { - return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0); + return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); } /** @@ -325,9 +325,9 @@ static int hw_test_and_clear_setup_guard(struct ci13xxx *udc) * * This function returns guard value */ -static int hw_test_and_set_setup_guard(struct ci13xxx *udc) +static int hw_test_and_set_setup_guard(struct ci13xxx *ci) { - return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); + return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); } /** @@ -337,9 +337,9 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *udc) * This function explicitly sets the address, without the "USBADRA" (advance) * feature, which is not supported by older versions of the controller. */ -static void hw_usb_set_address(struct ci13xxx *udc, u8 value) +static void hw_usb_set_address(struct ci13xxx *ci, u8 value) { - hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR, + hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, value << ffs_nr(DEVICEADDR_USBADR)); } @@ -349,21 +349,21 @@ static void hw_usb_set_address(struct ci13xxx *udc, u8 value) * * This function returns an error code */ -static int hw_usb_reset(struct ci13xxx *udc) +static int hw_usb_reset(struct ci13xxx *ci) { - hw_usb_set_address(udc, 0); + hw_usb_set_address(ci, 0); /* ESS flushes only at end?!? */ - hw_write(udc, OP_ENDPTFLUSH, ~0, ~0); + hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); /* clear setup token semaphores */ - hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0); + hw_write(ci, OP_ENDPTSETUPSTAT, 0, 0); /* clear complete status */ - hw_write(udc, OP_ENDPTCOMPLETE, 0, 0); + hw_write(ci, OP_ENDPTCOMPLETE, 0, 0); /* wait until all bits cleared */ - while (hw_read(udc, OP_ENDPTPRIME, ~0)) + while (hw_read(ci, OP_ENDPTPRIME, ~0)) udelay(10); /* not RTOS friendly */ /* reset all endpoints ? */ @@ -395,7 +395,7 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep) */ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) { - struct ci13xxx *udc = mEp->udc; + struct ci13xxx *ci = mEp->ci; unsigned i; int ret = 0; unsigned length = mReq->req.length; @@ -418,7 +418,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) if (!mReq->req.no_interrupt) mReq->zptr->token |= TD_IOC; } - ret = usb_gadget_map_request(&udc->gadget, &mReq->req, mEp->dir); + ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir); if (ret) return ret; @@ -454,13 +454,13 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) else mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK; wmb(); - if (hw_read(udc, OP_ENDPTPRIME, BIT(n))) + if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) goto done; do { - hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); - tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n)); - } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW)); - hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0); + hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); + tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); + } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); + hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); if (tmp_stat) goto done; } @@ -472,7 +472,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) wmb(); /* synchronize before ep prime */ - ret = hw_ep_prime(udc, mEp->num, mEp->dir, + ret = hw_ep_prime(ci, mEp->num, mEp->dir, mEp->type == USB_ENDPOINT_XFER_CONTROL); done: return ret; @@ -502,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) mReq->req.status = 0; - usb_gadget_unmap_request(&mEp->udc->gadget, &mReq->req, mEp->dir); + usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir); mReq->req.status = mReq->ptr->token & TD_STATUS; if ((TD_STATUS_HALTED & mReq->req.status) != 0) @@ -534,7 +534,7 @@ __acquires(mEp->lock) if (mEp == NULL) return -EINVAL; - hw_ep_flush(mEp->udc, mEp->num, mEp->dir); + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); while (!list_empty(&mEp->qh.queue)) { @@ -563,33 +563,33 @@ __acquires(mEp->lock) static int _gadget_stop_activity(struct usb_gadget *gadget) { struct usb_ep *ep; - struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); unsigned long flags; - spin_lock_irqsave(&udc->lock, flags); - udc->gadget.speed = USB_SPEED_UNKNOWN; - udc->remote_wakeup = 0; - udc->suspended = 0; - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + ci->gadget.speed = USB_SPEED_UNKNOWN; + ci->remote_wakeup = 0; + ci->suspended = 0; + spin_unlock_irqrestore(&ci->lock, flags); /* flush all endpoints */ gadget_for_each_ep(ep, gadget) { usb_ep_fifo_flush(ep); } - usb_ep_fifo_flush(&udc->ep0out->ep); - usb_ep_fifo_flush(&udc->ep0in->ep); + usb_ep_fifo_flush(&ci->ep0out->ep); + usb_ep_fifo_flush(&ci->ep0in->ep); - if (udc->driver) - udc->driver->disconnect(gadget); + if (ci->driver) + ci->driver->disconnect(gadget); /* make sure to disable all endpoints */ gadget_for_each_ep(ep, gadget) { usb_ep_disable(ep); } - if (udc->status != NULL) { - usb_ep_free_request(&udc->ep0in->ep, udc->status); - udc->status = NULL; + if (ci->status != NULL) { + usb_ep_free_request(&ci->ep0in->ep, ci->status); + ci->status = NULL; } return 0; @@ -600,36 +600,36 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) *****************************************************************************/ /** * isr_reset_handler: USB reset interrupt handler - * @udc: UDC device + * @ci: UDC device * * This function resets USB engine after a bus reset occurred */ -static void isr_reset_handler(struct ci13xxx *udc) -__releases(udc->lock) -__acquires(udc->lock) +static void isr_reset_handler(struct ci13xxx *ci) +__releases(ci->lock) +__acquires(ci->lock) { int retval; dbg_event(0xFF, "BUS RST", 0); - spin_unlock(&udc->lock); - retval = _gadget_stop_activity(&udc->gadget); + spin_unlock(&ci->lock); + retval = _gadget_stop_activity(&ci->gadget); if (retval) goto done; - retval = hw_usb_reset(udc); + retval = hw_usb_reset(ci); if (retval) goto done; - udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC); - if (udc->status == NULL) + ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC); + if (ci->status == NULL) retval = -ENOMEM; done: - spin_lock(&udc->lock); + spin_lock(&ci->lock); if (retval) - dev_err(udc->dev, "error: %i\n", retval); + dev_err(ci->dev, "error: %i\n", retval); } /** @@ -650,17 +650,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) /** * isr_get_status_response: get_status request response - * @udc: udc struct + * @ci: ci struct * @setup: setup request packet * * This function returns an error code */ -static int isr_get_status_response(struct ci13xxx *udc, +static int isr_get_status_response(struct ci13xxx *ci, struct usb_ctrlrequest *setup) __releases(mEp->lock) __acquires(mEp->lock) { - struct ci13xxx_ep *mEp = udc->ep0in; + struct ci13xxx_ep *mEp = ci->ep0in; struct usb_request *req = NULL; gfp_t gfp_flags = GFP_ATOMIC; int dir, num, retval; @@ -684,14 +684,14 @@ __acquires(mEp->lock) if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { /* Assume that device is bus powered for now. */ - *(u16 *)req->buf = udc->remote_wakeup << 1; + *(u16 *)req->buf = ci->remote_wakeup << 1; retval = 0; } else if ((setup->bRequestType & USB_RECIP_MASK) \ == USB_RECIP_ENDPOINT) { dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? TX : RX; num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; - *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir); + *(u16 *)req->buf = hw_ep_get_halt(ci, num, dir); } /* else do nothing; reserved for future use */ @@ -723,39 +723,39 @@ __acquires(mEp->lock) static void isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) { - struct ci13xxx *udc = req->context; + struct ci13xxx *ci = req->context; unsigned long flags; - if (udc->setaddr) { - hw_usb_set_address(udc, udc->address); - udc->setaddr = false; + if (ci->setaddr) { + hw_usb_set_address(ci, ci->address); + ci->setaddr = false; } - spin_lock_irqsave(&udc->lock, flags); - if (udc->test_mode) - hw_port_test_set(udc, udc->test_mode); - spin_unlock_irqrestore(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); + if (ci->test_mode) + hw_port_test_set(ci, ci->test_mode); + spin_unlock_irqrestore(&ci->lock, flags); } /** * isr_setup_status_phase: queues the status phase of a setup transation - * @udc: udc struct + * @ci: ci struct * * This function returns an error code */ -static int isr_setup_status_phase(struct ci13xxx *udc) +static int isr_setup_status_phase(struct ci13xxx *ci) __releases(mEp->lock) __acquires(mEp->lock) { int retval; struct ci13xxx_ep *mEp; - mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in; - udc->status->context = udc; - udc->status->complete = isr_setup_status_complete; + mEp = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; + ci->status->context = ci; + ci->status->complete = isr_setup_status_complete; spin_unlock(mEp->lock); - retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC); + retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC); spin_lock(mEp->lock); return retval; @@ -790,7 +790,7 @@ __acquires(mEp->lock) spin_unlock(mEp->lock); if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && mReq->req.length) - mEpTemp = mEp->udc->ep0in; + mEpTemp = mEp->ci->ep0in; mReq->req.complete(&mEpTemp->ep, &mReq->req); spin_lock(mEp->lock); } @@ -806,48 +806,48 @@ __acquires(mEp->lock) /** * isr_tr_complete_handler: transaction complete interrupt handler - * @udc: UDC descriptor + * @ci: UDC descriptor * * This function handles traffic events */ -static void isr_tr_complete_handler(struct ci13xxx *udc) -__releases(udc->lock) -__acquires(udc->lock) +static void isr_tr_complete_handler(struct ci13xxx *ci) +__releases(ci->lock) +__acquires(ci->lock) { unsigned i; u8 tmode = 0; - for (i = 0; i < udc->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < ci->hw_ep_max; i++) { + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; int type, num, dir, err = -EINVAL; struct usb_ctrlrequest req; if (mEp->ep.desc == NULL) continue; /* not configured */ - if (hw_test_and_clear_complete(udc, i)) { + if (hw_test_and_clear_complete(ci, i)) { err = isr_tr_complete_low(mEp); if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { if (err > 0) /* needs status phase */ - err = isr_setup_status_phase(udc); + err = isr_setup_status_phase(ci); if (err < 0) { dbg_event(_usb_addr(mEp), "ERROR", err); - spin_unlock(&udc->lock); + spin_unlock(&ci->lock); if (usb_ep_set_halt(&mEp->ep)) - dev_err(udc->dev, + dev_err(ci->dev, "error: ep_set_halt\n"); - spin_lock(&udc->lock); + spin_lock(&ci->lock); } } } if (mEp->type != USB_ENDPOINT_XFER_CONTROL || - !hw_test_and_clear_setup_status(udc, i)) + !hw_test_and_clear_setup_status(ci, i)) continue; if (i != 0) { - dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i); + dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i); continue; } @@ -855,18 +855,18 @@ __acquires(udc->lock) * Flush data and handshake transactions of previous * setup packet. */ - _ep_nuke(udc->ep0out); - _ep_nuke(udc->ep0in); + _ep_nuke(ci->ep0out); + _ep_nuke(ci->ep0in); /* read_setup_packet */ do { - hw_test_and_set_setup_guard(udc); + hw_test_and_set_setup_guard(ci); memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); - } while (!hw_test_and_clear_setup_guard(udc)); + } while (!hw_test_and_clear_setup_guard(ci)); type = req.bRequestType; - udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX; + ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; dbg_setup(_usb_addr(mEp), &req); @@ -881,23 +881,23 @@ __acquires(udc->lock) dir = num & USB_ENDPOINT_DIR_MASK; num &= USB_ENDPOINT_NUMBER_MASK; if (dir) /* TX */ - num += udc->hw_ep_max/2; - if (!udc->ci13xxx_ep[num].wedge) { - spin_unlock(&udc->lock); + num += ci->hw_ep_max/2; + if (!ci->ci13xxx_ep[num].wedge) { + spin_unlock(&ci->lock); err = usb_ep_clear_halt( - &udc->ci13xxx_ep[num].ep); - spin_lock(&udc->lock); + &ci->ci13xxx_ep[num].ep); + spin_lock(&ci->lock); if (err) break; } - err = isr_setup_status_phase(udc); + err = isr_setup_status_phase(ci); } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && le16_to_cpu(req.wValue) == USB_DEVICE_REMOTE_WAKEUP) { if (req.wLength != 0) break; - udc->remote_wakeup = 0; - err = isr_setup_status_phase(udc); + ci->remote_wakeup = 0; + err = isr_setup_status_phase(ci); } else { goto delegate; } @@ -910,7 +910,7 @@ __acquires(udc->lock) if (le16_to_cpu(req.wLength) != 2 || le16_to_cpu(req.wValue) != 0) break; - err = isr_get_status_response(udc, &req); + err = isr_get_status_response(ci, &req); break; case USB_REQ_SET_ADDRESS: if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) @@ -918,9 +918,9 @@ __acquires(udc->lock) if (le16_to_cpu(req.wLength) != 0 || le16_to_cpu(req.wIndex) != 0) break; - udc->address = (u8)le16_to_cpu(req.wValue); - udc->setaddr = true; - err = isr_setup_status_phase(udc); + ci->address = (u8)le16_to_cpu(req.wValue); + ci->setaddr = true; + err = isr_setup_status_phase(ci); break; case USB_REQ_SET_FEATURE: if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && @@ -932,20 +932,20 @@ __acquires(udc->lock) dir = num & USB_ENDPOINT_DIR_MASK; num &= USB_ENDPOINT_NUMBER_MASK; if (dir) /* TX */ - num += udc->hw_ep_max/2; + num += ci->hw_ep_max/2; - spin_unlock(&udc->lock); - err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep); - spin_lock(&udc->lock); + spin_unlock(&ci->lock); + err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep); + spin_lock(&ci->lock); if (!err) - isr_setup_status_phase(udc); + isr_setup_status_phase(ci); } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { if (req.wLength != 0) break; switch (le16_to_cpu(req.wValue)) { case USB_DEVICE_REMOTE_WAKEUP: - udc->remote_wakeup = 1; - err = isr_setup_status_phase(udc); + ci->remote_wakeup = 1; + err = isr_setup_status_phase(ci); break; case USB_DEVICE_TEST_MODE: tmode = le16_to_cpu(req.wIndex) >> 8; @@ -955,9 +955,9 @@ __acquires(udc->lock) case TEST_SE0_NAK: case TEST_PACKET: case TEST_FORCE_EN: - udc->test_mode = tmode; + ci->test_mode = tmode; err = isr_setup_status_phase( - udc); + ci); break; default: break; @@ -972,21 +972,21 @@ __acquires(udc->lock) default: delegate: if (req.wLength == 0) /* no data phase */ - udc->ep0_dir = TX; + ci->ep0_dir = TX; - spin_unlock(&udc->lock); - err = udc->driver->setup(&udc->gadget, &req); - spin_lock(&udc->lock); + spin_unlock(&ci->lock); + err = ci->driver->setup(&ci->gadget, &req); + spin_lock(&ci->lock); break; } if (err < 0) { dbg_event(_usb_addr(mEp), "ERROR", err); - spin_unlock(&udc->lock); + spin_unlock(&ci->lock); if (usb_ep_set_halt(&mEp->ep)) - dev_err(udc->dev, "error: ep_set_halt\n"); - spin_lock(&udc->lock); + dev_err(ci->dev, "error: ep_set_halt\n"); + spin_lock(&ci->lock); } } } @@ -1016,7 +1016,7 @@ static int ep_enable(struct usb_ep *ep, mEp->ep.desc = desc; if (!list_empty(&mEp->qh.queue)) - dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n"); + dev_warn(mEp->ci->dev, "enabling a non-empty endpoint!\n"); mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; mEp->num = usb_endpoint_num(desc); @@ -1044,7 +1044,7 @@ static int ep_enable(struct usb_ep *ep, * is always enabled */ if (mEp->num) - retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type); + retval |= hw_ep_enable(mEp->ci, mEp->num, mEp->dir, mEp->type); spin_unlock_irqrestore(mEp->lock, flags); return retval; @@ -1075,7 +1075,7 @@ static int ep_disable(struct usb_ep *ep) dbg_event(_usb_addr(mEp), "DISABLE", 0); retval |= _ep_nuke(mEp); - retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir); + retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir); if (mEp->type == USB_ENDPOINT_XFER_CONTROL) mEp->dir = (mEp->dir == TX) ? RX : TX; @@ -1132,7 +1132,7 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) if (ep == NULL || req == NULL) { return; } else if (!list_empty(&mReq->queue)) { - dev_err(mEp->udc->dev, "freeing queued request\n"); + dev_err(mEp->ci->dev, "freeing queued request\n"); return; } @@ -1157,7 +1157,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, { struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); - struct ci13xxx *udc = mEp->udc; + struct ci13xxx *ci = mEp->ci; int retval = 0; unsigned long flags; @@ -1168,12 +1168,12 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { if (req->length) - mEp = (udc->ep0_dir == RX) ? - udc->ep0out : udc->ep0in; + mEp = (ci->ep0_dir == RX) ? + ci->ep0out : ci->ep0in; if (!list_empty(&mEp->qh.queue)) { _ep_nuke(mEp); retval = -EOVERFLOW; - dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n", + dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", _usb_addr(mEp)); } } @@ -1181,14 +1181,14 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, /* first nuke then test link, e.g. previous status has not sent */ if (!list_empty(&mReq->queue)) { retval = -EBUSY; - dev_err(mEp->udc->dev, "request already in queue\n"); + dev_err(mEp->ci->dev, "request already in queue\n"); goto done; } if (req->length > 4 * CI13XXX_PAGE_SIZE) { req->length = 4 * CI13XXX_PAGE_SIZE; retval = -EMSGSIZE; - dev_warn(mEp->udc->dev, "request length truncated\n"); + dev_warn(mEp->ci->dev, "request length truncated\n"); } dbg_queue(_usb_addr(mEp), req, retval); @@ -1231,12 +1231,12 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) dbg_event(_usb_addr(mEp), "DEQUEUE", 0); - hw_ep_flush(mEp->udc, mEp->num, mEp->dir); + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); /* pop request */ list_del_init(&mReq->queue); - usb_gadget_unmap_request(&mEp->udc->gadget, req, mEp->dir); + usb_gadget_unmap_request(&mEp->ci->gadget, req, mEp->dir); req->status = -ECONNRESET; @@ -1278,7 +1278,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) direction = mEp->dir; do { dbg_event(_usb_addr(mEp), "HALT", value); - retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value); + retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value); if (!value) mEp->wedge = 0; @@ -1326,14 +1326,14 @@ static void ep_fifo_flush(struct usb_ep *ep) unsigned long flags; if (ep == NULL) { - dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); + dev_err(mEp->ci->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); return; } spin_lock_irqsave(mEp->lock, flags); dbg_event(_usb_addr(mEp), "FFLUSH", 0); - hw_ep_flush(mEp->udc, mEp->num, mEp->dir); + hw_ep_flush(mEp->ci, mEp->num, mEp->dir); spin_unlock_irqrestore(mEp->lock, flags); } @@ -1359,30 +1359,30 @@ static const struct usb_ep_ops usb_ep_ops = { *****************************************************************************/ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) { - struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); unsigned long flags; int gadget_ready = 0; - if (!(udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) + if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) return -EOPNOTSUPP; - spin_lock_irqsave(&udc->lock, flags); - udc->vbus_active = is_active; - if (udc->driver) + spin_lock_irqsave(&ci->lock, flags); + ci->vbus_active = is_active; + if (ci->driver) gadget_ready = 1; - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); if (gadget_ready) { if (is_active) { pm_runtime_get_sync(&_gadget->dev); - hw_device_reset(udc, USBMODE_CM_DC); - hw_device_state(udc, udc->ep0out->qh.dma); + hw_device_reset(ci, USBMODE_CM_DC); + hw_device_state(ci, ci->ep0out->qh.dma); } else { - hw_device_state(udc, 0); - if (udc->platdata->notify_event) - udc->platdata->notify_event(udc, + hw_device_state(ci, 0); + if (ci->platdata->notify_event) + ci->platdata->notify_event(ci, CI13XXX_CONTROLLER_STOPPED_EVENT); - _gadget_stop_activity(&udc->gadget); + _gadget_stop_activity(&ci->gadget); pm_runtime_put_sync(&_gadget->dev); } } @@ -1392,31 +1392,31 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) static int ci13xxx_wakeup(struct usb_gadget *_gadget) { - struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); unsigned long flags; int ret = 0; - spin_lock_irqsave(&udc->lock, flags); - if (!udc->remote_wakeup) { + spin_lock_irqsave(&ci->lock, flags); + if (!ci->remote_wakeup) { ret = -EOPNOTSUPP; goto out; } - if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) { + if (!hw_read(ci, OP_PORTSC, PORTSC_SUSP)) { ret = -EINVAL; goto out; } - hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); + hw_write(ci, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); out: - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return ret; } static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) { - struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); - if (udc->transceiver) - return usb_phy_set_power(udc->transceiver, mA); + if (ci->transceiver) + return usb_phy_set_power(ci->transceiver, mA); return -ENOTSUPP; } @@ -1437,28 +1437,28 @@ static const struct usb_gadget_ops usb_gadget_ops = { .udc_stop = ci13xxx_stop, }; -static int init_eps(struct ci13xxx *udc) +static int init_eps(struct ci13xxx *ci) { int retval = 0, i, j; - for (i = 0; i < udc->hw_ep_max/2; i++) + for (i = 0; i < ci->hw_ep_max/2; i++) for (j = RX; j <= TX; j++) { - int k = i + j * udc->hw_ep_max/2; - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; + int k = i + j * ci->hw_ep_max/2; + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[k]; scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, (j == TX) ? "in" : "out"); - mEp->udc = udc; - mEp->lock = &udc->lock; - mEp->td_pool = udc->td_pool; + mEp->ci = ci; + mEp->lock = &ci->lock; + mEp->td_pool = ci->td_pool; mEp->ep.name = mEp->name; mEp->ep.ops = &usb_ep_ops; mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; INIT_LIST_HEAD(&mEp->qh.queue); - mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, + mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, &mEp->qh.dma); if (mEp->qh.ptr == NULL) retval = -ENOMEM; @@ -1471,14 +1471,14 @@ static int init_eps(struct ci13xxx *udc) */ if (i == 0) { if (j == RX) - udc->ep0out = mEp; + ci->ep0out = mEp; else - udc->ep0in = mEp; + ci->ep0in = mEp; continue; } - list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); + list_add_tail(&mEp->ep.ep_list, &ci->gadget.ep_list); } return retval; @@ -1494,7 +1494,7 @@ static int init_eps(struct ci13xxx *udc) static int ci13xxx_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { - struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); unsigned long flags; int retval = -ENOMEM; @@ -1502,35 +1502,35 @@ static int ci13xxx_start(struct usb_gadget *gadget, return -EINVAL; - udc->ep0out->ep.desc = &ctrl_endpt_out_desc; - retval = usb_ep_enable(&udc->ep0out->ep); + ci->ep0out->ep.desc = &ctrl_endpt_out_desc; + retval = usb_ep_enable(&ci->ep0out->ep); if (retval) return retval; - udc->ep0in->ep.desc = &ctrl_endpt_in_desc; - retval = usb_ep_enable(&udc->ep0in->ep); + ci->ep0in->ep.desc = &ctrl_endpt_in_desc; + retval = usb_ep_enable(&ci->ep0in->ep); if (retval) return retval; - spin_lock_irqsave(&udc->lock, flags); - - udc->driver = driver; - pm_runtime_get_sync(&udc->gadget.dev); - if (udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { - if (udc->vbus_active) { - if (udc->platdata->flags & CI13XXX_REGS_SHARED) - hw_device_reset(udc, USBMODE_CM_DC); + spin_lock_irqsave(&ci->lock, flags); + + ci->driver = driver; + pm_runtime_get_sync(&ci->gadget.dev); + if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { + if (ci->vbus_active) { + if (ci->platdata->flags & CI13XXX_REGS_SHARED) + hw_device_reset(ci, USBMODE_CM_DC); } else { - pm_runtime_put_sync(&udc->gadget.dev); + pm_runtime_put_sync(&ci->gadget.dev); goto done; } } - retval = hw_device_state(udc, udc->ep0out->qh.dma); + retval = hw_device_state(ci, ci->ep0out->qh.dma); if (retval) - pm_runtime_put_sync(&udc->gadget.dev); + pm_runtime_put_sync(&ci->gadget.dev); done: - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return retval; } @@ -1540,25 +1540,25 @@ static int ci13xxx_start(struct usb_gadget *gadget, static int ci13xxx_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { - struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); + struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); unsigned long flags; - spin_lock_irqsave(&udc->lock, flags); + spin_lock_irqsave(&ci->lock, flags); - if (!(udc->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || - udc->vbus_active) { - hw_device_state(udc, 0); - if (udc->platdata->notify_event) - udc->platdata->notify_event(udc, + if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || + ci->vbus_active) { + hw_device_state(ci, 0); + if (ci->platdata->notify_event) + ci->platdata->notify_event(ci, CI13XXX_CONTROLLER_STOPPED_EVENT); - udc->driver = NULL; - spin_unlock_irqrestore(&udc->lock, flags); - _gadget_stop_activity(&udc->gadget); - spin_lock_irqsave(&udc->lock, flags); - pm_runtime_put(&udc->gadget.dev); + ci->driver = NULL; + spin_unlock_irqrestore(&ci->lock, flags); + _gadget_stop_activity(&ci->gadget); + spin_lock_irqsave(&ci->lock, flags); + pm_runtime_put(&ci->gadget.dev); } - spin_unlock_irqrestore(&udc->lock, flags); + spin_unlock_irqrestore(&ci->lock, flags); return 0; } @@ -1567,64 +1567,64 @@ static int ci13xxx_stop(struct usb_gadget *gadget, * BUS block *****************************************************************************/ /** - * udc_irq: udc interrupt handler + * udc_irq: ci interrupt handler * * This function returns IRQ_HANDLED if the IRQ has been handled * It locks access to registers */ -static irqreturn_t udc_irq(struct ci13xxx *udc) +static irqreturn_t udc_irq(struct ci13xxx *ci) { irqreturn_t retval; u32 intr; - if (udc == NULL) + if (ci == NULL) return IRQ_HANDLED; - spin_lock(&udc->lock); + spin_lock(&ci->lock); - if (udc->platdata->flags & CI13XXX_REGS_SHARED) { - if (hw_read(udc, OP_USBMODE, USBMODE_CM) != + if (ci->platdata->flags & CI13XXX_REGS_SHARED) { + if (hw_read(ci, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DC) { - spin_unlock(&udc->lock); + spin_unlock(&ci->lock); return IRQ_NONE; } } - intr = hw_test_and_clear_intr_active(udc); + intr = hw_test_and_clear_intr_active(ci); dbg_interrupt(intr); if (intr) { /* order defines priority - do NOT change it */ if (USBi_URI & intr) - isr_reset_handler(udc); + isr_reset_handler(ci); if (USBi_PCI & intr) { - udc->gadget.speed = hw_port_is_high_speed(udc) ? + ci->gadget.speed = hw_port_is_high_speed(ci) ? USB_SPEED_HIGH : USB_SPEED_FULL; - if (udc->suspended && udc->driver->resume) { - spin_unlock(&udc->lock); - udc->driver->resume(&udc->gadget); - spin_lock(&udc->lock); - udc->suspended = 0; + if (ci->suspended && ci->driver->resume) { + spin_unlock(&ci->lock); + ci->driver->resume(&ci->gadget); + spin_lock(&ci->lock); + ci->suspended = 0; } } if (USBi_UI & intr) - isr_tr_complete_handler(udc); + isr_tr_complete_handler(ci); if (USBi_SLI & intr) { - if (udc->gadget.speed != USB_SPEED_UNKNOWN && - udc->driver->suspend) { - udc->suspended = 1; - spin_unlock(&udc->lock); - udc->driver->suspend(&udc->gadget); - spin_lock(&udc->lock); + if (ci->gadget.speed != USB_SPEED_UNKNOWN && + ci->driver->suspend) { + ci->suspended = 1; + spin_unlock(&ci->lock); + ci->driver->suspend(&ci->gadget); + spin_lock(&ci->lock); } } retval = IRQ_HANDLED; } else { retval = IRQ_NONE; } - spin_unlock(&udc->lock); + spin_unlock(&ci->lock); return retval; } @@ -1641,109 +1641,109 @@ static void udc_release(struct device *dev) /** * udc_start: initialize gadget role - * @udc: chipidea controller + * @ci: chipidea controller */ -static int udc_start(struct ci13xxx *udc) +static int udc_start(struct ci13xxx *ci) { - struct device *dev = udc->dev; + struct device *dev = ci->dev; int retval = 0; - spin_lock_init(&udc->lock); + spin_lock_init(&ci->lock); - udc->gadget.ops = &usb_gadget_ops; - udc->gadget.speed = USB_SPEED_UNKNOWN; - udc->gadget.max_speed = USB_SPEED_HIGH; - udc->gadget.is_otg = 0; - udc->gadget.name = udc->platdata->name; + ci->gadget.ops = &usb_gadget_ops; + ci->gadget.speed = USB_SPEED_UNKNOWN; + ci->gadget.max_speed = USB_SPEED_HIGH; + ci->gadget.is_otg = 0; + ci->gadget.name = ci->platdata->name; - INIT_LIST_HEAD(&udc->gadget.ep_list); + INIT_LIST_HEAD(&ci->gadget.ep_list); - dev_set_name(&udc->gadget.dev, "gadget"); - udc->gadget.dev.dma_mask = dev->dma_mask; - udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; - udc->gadget.dev.parent = dev; - udc->gadget.dev.release = udc_release; + dev_set_name(&ci->gadget.dev, "gadget"); + ci->gadget.dev.dma_mask = dev->dma_mask; + ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; + ci->gadget.dev.parent = dev; + ci->gadget.dev.release = udc_release; /* alloc resources */ - udc->qh_pool = dma_pool_create("ci13xxx_qh", dev, + ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, sizeof(struct ci13xxx_qh), 64, CI13XXX_PAGE_SIZE); - if (udc->qh_pool == NULL) + if (ci->qh_pool == NULL) return -ENOMEM; - udc->td_pool = dma_pool_create("ci13xxx_td", dev, + ci->td_pool = dma_pool_create("ci13xxx_td", dev, sizeof(struct ci13xxx_td), 64, CI13XXX_PAGE_SIZE); - if (udc->td_pool == NULL) { + if (ci->td_pool == NULL) { retval = -ENOMEM; goto free_qh_pool; } - retval = init_eps(udc); + retval = init_eps(ci); if (retval) goto free_pools; - udc->gadget.ep0 = &udc->ep0in->ep; + ci->gadget.ep0 = &ci->ep0in->ep; - udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); + ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); - if (udc->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { - if (udc->transceiver == NULL) { + if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { + if (ci->transceiver == NULL) { retval = -ENODEV; goto free_pools; } } - if (!(udc->platdata->flags & CI13XXX_REGS_SHARED)) { - retval = hw_device_reset(udc, USBMODE_CM_DC); + if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) { + retval = hw_device_reset(ci, USBMODE_CM_DC); if (retval) goto put_transceiver; } - retval = device_register(&udc->gadget.dev); + retval = device_register(&ci->gadget.dev); if (retval) { - put_device(&udc->gadget.dev); + put_device(&ci->gadget.dev); goto put_transceiver; } - retval = dbg_create_files(&udc->gadget.dev); + retval = dbg_create_files(&ci->gadget.dev); if (retval) goto unreg_device; - if (!IS_ERR_OR_NULL(udc->transceiver)) { - retval = otg_set_peripheral(udc->transceiver->otg, - &udc->gadget); + if (!IS_ERR_OR_NULL(ci->transceiver)) { + retval = otg_set_peripheral(ci->transceiver->otg, + &ci->gadget); if (retval) goto remove_dbg; } - retval = usb_add_gadget_udc(dev, &udc->gadget); + retval = usb_add_gadget_udc(dev, &ci->gadget); if (retval) goto remove_trans; - pm_runtime_no_callbacks(&udc->gadget.dev); - pm_runtime_enable(&udc->gadget.dev); + pm_runtime_no_callbacks(&ci->gadget.dev); + pm_runtime_enable(&ci->gadget.dev); return retval; remove_trans: - if (!IS_ERR_OR_NULL(udc->transceiver)) { - otg_set_peripheral(udc->transceiver->otg, &udc->gadget); - usb_put_phy(udc->transceiver); + if (!IS_ERR_OR_NULL(ci->transceiver)) { + otg_set_peripheral(ci->transceiver->otg, &ci->gadget); + usb_put_phy(ci->transceiver); } dev_err(dev, "error = %i\n", retval); remove_dbg: - dbg_remove_files(&udc->gadget.dev); + dbg_remove_files(&ci->gadget.dev); unreg_device: - device_unregister(&udc->gadget.dev); + device_unregister(&ci->gadget.dev); put_transceiver: - if (!IS_ERR_OR_NULL(udc->transceiver)) - usb_put_phy(udc->transceiver); + if (!IS_ERR_OR_NULL(ci->transceiver)) + usb_put_phy(ci->transceiver); free_pools: - dma_pool_destroy(udc->td_pool); + dma_pool_destroy(ci->td_pool); free_qh_pool: - dma_pool_destroy(udc->qh_pool); + dma_pool_destroy(ci->qh_pool); return retval; } @@ -1752,32 +1752,32 @@ free_qh_pool: * * No interrupts active, the IRQ has been released */ -static void udc_stop(struct ci13xxx *udc) +static void udc_stop(struct ci13xxx *ci) { int i; - if (udc == NULL) + if (ci == NULL) return; - usb_del_gadget_udc(&udc->gadget); + usb_del_gadget_udc(&ci->gadget); - for (i = 0; i < udc->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < ci->hw_ep_max; i++) { + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; - dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); + dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); } - dma_pool_destroy(udc->td_pool); - dma_pool_destroy(udc->qh_pool); + dma_pool_destroy(ci->td_pool); + dma_pool_destroy(ci->qh_pool); - if (!IS_ERR_OR_NULL(udc->transceiver)) { - otg_set_peripheral(udc->transceiver->otg, NULL); - usb_put_phy(udc->transceiver); + if (!IS_ERR_OR_NULL(ci->transceiver)) { + otg_set_peripheral(ci->transceiver->otg, NULL); + usb_put_phy(ci->transceiver); } - dbg_remove_files(&udc->gadget.dev); - device_unregister(&udc->gadget.dev); + dbg_remove_files(&ci->gadget.dev); + device_unregister(&ci->gadget.dev); /* my kobject is dynamic, I swear! */ - memset(&udc->gadget, 0, sizeof(udc->gadget)); + memset(&ci->gadget, 0, sizeof(ci->gadget)); } /** diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index d4cf970656fb..d2f7e494f5c0 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -19,7 +19,7 @@ struct ci13xxx_platform_data { #define CI13XXX_CONTROLLER_RESET_EVENT 0 #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 - void (*notify_event) (struct ci13xxx *udc, unsigned event); + void (*notify_event) (struct ci13xxx *ci, unsigned event); }; /* Default offset of capability registers */ -- GitLab From cbc6dc2af39e1395564445fd71cfcc1c70a96277 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:41 +0800 Subject: [PATCH 2343/5711] USB: Chipidea: add unified ci13xxx_{add,remove}_device for platform drivers Platform drivers do the similar things to add/remove ci13xxx device, so create a unified one. Signed-off-by: Richard Zhao Reviewed-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci13xxx_msm.c | 34 +++++------------------ drivers/usb/chipidea/ci13xxx_pci.c | 34 +++++------------------ drivers/usb/chipidea/core.c | 43 ++++++++++++++++++++++++++++++ include/linux/usb/chipidea.h | 7 +++++ 4 files changed, 63 insertions(+), 55 deletions(-) diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index 5a2fe5f9b6c3..b01feb3be92e 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -58,43 +58,23 @@ static struct ci13xxx_platform_data ci13xxx_msm_platdata = { static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) { struct platform_device *plat_ci; - int ret; dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); - plat_ci = platform_device_alloc("ci_hdrc", -1); - if (!plat_ci) { - dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n"); - return -ENOMEM; + plat_ci = ci13xxx_add_device(&pdev->dev, + pdev->resource, pdev->num_resources, + &ci13xxx_msm_platdata); + if (IS_ERR(plat_ci)) { + dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); + return PTR_ERR(plat_ci); } - ret = platform_device_add_resources(plat_ci, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "can't add resources to platform device\n"); - goto put_platform; - } - - ret = platform_device_add_data(plat_ci, &ci13xxx_msm_platdata, - sizeof(ci13xxx_msm_platdata)); - if (ret) - goto put_platform; - - ret = platform_device_add(plat_ci); - if (ret) - goto put_platform; - platform_set_drvdata(pdev, plat_ci); pm_runtime_no_callbacks(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; - -put_platform: - platform_device_put(plat_ci); - - return ret; } static int __devexit ci13xxx_msm_remove(struct platform_device *pdev) @@ -102,7 +82,7 @@ static int __devexit ci13xxx_msm_remove(struct platform_device *pdev) struct platform_device *plat_ci = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); - platform_device_unregister(plat_ci); + ci13xxx_remove_device(plat_ci); return 0; } diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c index cdcac3a0e94d..918e14971f2b 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci13xxx_pci.c @@ -75,13 +75,6 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, pci_set_master(pdev); pci_try_set_mwi(pdev); - plat_ci = platform_device_alloc("ci_hdrc", -1); - if (!plat_ci) { - dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n"); - retval = -ENOMEM; - goto disable_device; - } - memset(res, 0, sizeof(res)); res[0].start = pci_resource_start(pdev, 0); res[0].end = pci_resource_end(pdev, 0); @@ -89,32 +82,17 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, res[1].start = pdev->irq; res[1].flags = IORESOURCE_IRQ; - retval = platform_device_add_resources(plat_ci, res, nres); - if (retval) { - dev_err(&pdev->dev, "can't add resources to platform device\n"); - goto put_platform; + plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata); + if (IS_ERR(plat_ci)) { + dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); + retval = PTR_ERR(plat_ci); + goto disable_device; } - retval = platform_device_add_data(plat_ci, platdata, sizeof(*platdata)); - if (retval) - goto put_platform; - - dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask); - plat_ci->dev.dma_mask = pdev->dev.dma_mask; - plat_ci->dev.dma_parms = pdev->dev.dma_parms; - plat_ci->dev.parent = &pdev->dev; - pci_set_drvdata(pdev, plat_ci); - retval = platform_device_add(plat_ci); - if (retval) - goto put_platform; - return 0; - put_platform: - pci_set_drvdata(pdev, NULL); - platform_device_put(plat_ci); disable_device: pci_disable_device(pdev); done: @@ -133,7 +111,7 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) { struct platform_device *plat_ci = pci_get_drvdata(pdev); - platform_device_unregister(plat_ci); + ci13xxx_remove_device(plat_ci); pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); } diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 9a883bd5e113..8b9d06fd0325 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -332,6 +332,49 @@ static irqreturn_t ci_irq(int irq, void *data) return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); } +struct platform_device *ci13xxx_add_device(struct device *dev, + struct resource *res, int nres, + struct ci13xxx_platform_data *platdata) +{ + struct platform_device *pdev; + int ret; + + /* FIXME: find a way to choose id */ + pdev = platform_device_alloc("ci_hdrc", -1); + if (!pdev) + return ERR_PTR(-ENOMEM); + + pdev->dev.parent = dev; + pdev->dev.dma_mask = dev->dma_mask; + pdev->dev.dma_parms = dev->dma_parms; + dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); + + ret = platform_device_add_resources(pdev, res, nres); + if (ret) + goto err; + + ret = platform_device_add_data(pdev, platdata, sizeof(*platdata)); + if (ret) + goto err; + + ret = platform_device_add(pdev); + if (ret) + goto err; + + return pdev; + +err: + platform_device_put(pdev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(ci13xxx_add_device); + +void ci13xxx_remove_device(struct platform_device *pdev) +{ + platform_device_unregister(pdev); +} +EXPORT_SYMBOL_GPL(ci13xxx_remove_device); + static int __devinit ci_hdrc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index d2f7e494f5c0..be078f0bfde2 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -25,4 +25,11 @@ struct ci13xxx_platform_data { /* Default offset of capability registers */ #define DEF_CAPOFFSET 0x100 +/* Add ci13xxx device */ +struct platform_device *ci13xxx_add_device(struct device *dev, + struct resource *res, int nres, + struct ci13xxx_platform_data *platdata); +/* Remove ci13xxx device */ +void ci13xxx_remove_device(struct platform_device *pdev); + #endif -- GitLab From fe6e125e30fb9d93fdfc5e3e3702b9c7c3076194 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:42 +0800 Subject: [PATCH 2344/5711] USB: Chipidea: add ci13xxx device id management We use ida_simple_get and ida_simple_remove to manage the ids. Signed-off-by: Richard Zhao Reviewed-by: Felipe Balbi Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/core.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 8b9d06fd0325..39603d7b7916 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -332,17 +333,24 @@ static irqreturn_t ci_irq(int irq, void *data) return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); } +static DEFINE_IDA(ci_ida); + struct platform_device *ci13xxx_add_device(struct device *dev, struct resource *res, int nres, struct ci13xxx_platform_data *platdata) { struct platform_device *pdev; - int ret; + int id, ret; - /* FIXME: find a way to choose id */ - pdev = platform_device_alloc("ci_hdrc", -1); - if (!pdev) - return ERR_PTR(-ENOMEM); + id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); + if (id < 0) + return ERR_PTR(id); + + pdev = platform_device_alloc("ci_hdrc", id); + if (!pdev) { + ret = -ENOMEM; + goto put_id; + } pdev->dev.parent = dev; pdev->dev.dma_mask = dev->dma_mask; @@ -365,6 +373,8 @@ struct platform_device *ci13xxx_add_device(struct device *dev, err: platform_device_put(pdev); +put_id: + ida_simple_remove(&ci_ida, id); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(ci13xxx_add_device); @@ -372,6 +382,7 @@ EXPORT_SYMBOL_GPL(ci13xxx_add_device); void ci13xxx_remove_device(struct platform_device *pdev) { platform_device_unregister(pdev); + ida_simple_remove(&ci_ida, pdev->id); } EXPORT_SYMBOL_GPL(ci13xxx_remove_device); -- GitLab From ca72ae9bf6b599519576142b4cb209aa79bbf867 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:43 +0800 Subject: [PATCH 2345/5711] usb: chipidea: select USB_EHCI_ROOT_HUB_TT in USB_CHIPIDEA_HOST of Kconfig ci13xxx host needs Root Hub Transaction Translators. Reported-by: Shawn Guo Signed-off-by: Richard Zhao Acked-by: Felipe Balbi Signed-off-by: Alexander Shishkin Acked-by: Marek Vasut Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index fd36dc8b889b..8337fb5d988d 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC config USB_CHIPIDEA_HOST bool "ChipIdea host controller" + select USB_EHCI_ROOT_HUB_TT help Say Y here to enable host controller functionality of the ChipIdea driver. -- GitLab From 526c51382d59144a3704970ab111d668e604a10f Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:44 +0800 Subject: [PATCH 2346/5711] usb: otg: add notify_connect/notify_disconnect callback This let usb phy driver has a chance to change hw settings when connect status change. Signed-off-by: Richard Zhao Acked-by: Felipe Balbi Tested-by: Subodh Nijsure Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/otg.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 0cb2ec2e50c0..45824be0a2f9 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -128,6 +128,9 @@ struct usb_phy { int (*set_suspend)(struct usb_phy *x, int suspend); + /* notify phy connect status change */ + int (*notify_connect)(struct usb_phy *x, int port); + int (*notify_disconnect)(struct usb_phy *x, int port); }; @@ -276,6 +279,24 @@ usb_phy_set_suspend(struct usb_phy *x, int suspend) return 0; } +static inline int +usb_phy_notify_connect(struct usb_phy *x, int port) +{ + if (x->notify_connect) + return x->notify_connect(x, port); + else + return 0; +} + +static inline int +usb_phy_notify_disconnect(struct usb_phy *x, int port) +{ + if (x->notify_disconnect) + return x->notify_disconnect(x, port); + else + return 0; +} + static inline int otg_start_srp(struct usb_otg *otg) { -- GitLab From 496f1314f9cac3b59016b5af71ddf47e7a4eb2fb Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 9 Jul 2012 15:54:08 +0200 Subject: [PATCH 2347/5711] cgroup: Remove populate() documentation This function was removed by 86f82d561864e902c70282b6f17cf590c0f34691. Signed-off-by: Daniel Wagner Signed-off-by: Tejun Heo Cc: Rob Landley Cc: Paul Menage Cc: Li Zefan Cc: Frederic Weisbecker Cc: KAMEZAWA Hiroyuki --- Documentation/cgroups/cgroups.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index e86faaea7d66..97a0d1a6a5ae 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -637,16 +637,6 @@ void exit(struct task_struct *task) Called during task exit. -int populate(struct cgroup *cgrp) -(cgroup_mutex held by caller) - -Called after creation of a cgroup to allow a subsystem to populate -the cgroup directory with file entries. The subsystem should make -calls to cgroup_add_file() with objects of type cftype (see -include/linux/cgroup.h for details). Note that although this -method can return an error code, the error code is currently not -always handled well. - void post_clone(struct cgroup *cgrp) (cgroup_mutex held by caller) -- GitLab From a2c3d6902f6f9916b5376c44baa8c1d08bf92a27 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:46 +0800 Subject: [PATCH 2348/5711] usb: chipidea: permit driver bindings pass phy pointer Sometimes, the driver bindings may know what phy they use. For example, when using device tree, the usb controller may have a phandler pointing to usb phy. Signed-off-by: Richard Zhao Reviewed-by: Marek Vasut Acked-by: Felipe Balbi Tested-by: Subodh Nijsure Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci.h | 2 ++ drivers/usb/chipidea/core.c | 4 ++++ drivers/usb/chipidea/host.c | 1 + drivers/usb/chipidea/udc.c | 11 +++++++---- include/linux/usb/chipidea.h | 3 +++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 9655e3569d4c..d738603a2757 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -160,6 +160,8 @@ struct ci13xxx { struct ci13xxx_platform_data *platdata; int vbus_active; + /* FIXME: some day, we'll not use global phy */ + bool global_phy; struct usb_phy *transceiver; struct usb_hcd *hcd; }; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 39603d7b7916..1083585fad00 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -419,6 +419,10 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) ci->dev = dev; ci->platdata = dev->platform_data; + if (ci->platdata->phy) + ci->transceiver = ci->platdata->phy; + else + ci->global_phy = true; ret = hw_device_init(ci, base); if (ret < 0) { diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 4a4fdb8c65f8..ebff9f4f56ec 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -117,6 +117,7 @@ static int host_start(struct ci13xxx *ci) hcd->has_tt = 1; hcd->power_budget = ci->platdata->power_budget; + hcd->phy = ci->transceiver; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index ba8284e2a237..c7a032a4f0c5 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1685,7 +1685,8 @@ static int udc_start(struct ci13xxx *ci) ci->gadget.ep0 = &ci->ep0in->ep; - ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); + if (ci->global_phy) + ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (ci->transceiver == NULL) { @@ -1729,7 +1730,8 @@ static int udc_start(struct ci13xxx *ci) remove_trans: if (!IS_ERR_OR_NULL(ci->transceiver)) { otg_set_peripheral(ci->transceiver->otg, &ci->gadget); - usb_put_phy(ci->transceiver); + if (ci->global_phy) + usb_put_phy(ci->transceiver); } dev_err(dev, "error = %i\n", retval); @@ -1738,7 +1740,7 @@ remove_dbg: unreg_device: device_unregister(&ci->gadget.dev); put_transceiver: - if (!IS_ERR_OR_NULL(ci->transceiver)) + if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) usb_put_phy(ci->transceiver); free_pools: dma_pool_destroy(ci->td_pool); @@ -1772,7 +1774,8 @@ static void udc_stop(struct ci13xxx *ci) if (!IS_ERR_OR_NULL(ci->transceiver)) { otg_set_peripheral(ci->transceiver->otg, NULL); - usb_put_phy(ci->transceiver); + if (ci->global_phy) + usb_put_phy(ci->transceiver); } dbg_remove_files(&ci->gadget.dev); device_unregister(&ci->gadget.dev); diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index be078f0bfde2..544825dde823 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -5,12 +5,15 @@ #ifndef __LINUX_USB_CHIPIDEA_H #define __LINUX_USB_CHIPIDEA_H +#include + struct ci13xxx; struct ci13xxx_platform_data { const char *name; /* offset of the capability registers */ uintptr_t capoffset; unsigned power_budget; + struct usb_phy *phy; unsigned long flags; #define CI13XXX_REGS_SHARED BIT(0) #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) -- GitLab From b3d99681227a8c5e1f50bccae0f55930aad2ca77 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:47 +0800 Subject: [PATCH 2349/5711] usb: otg: add basic mxs phy driver support mxs phy is used in Freescale i.MX SoCs, for example imx23, imx28, imx6Q. This patch adds the basic host support. Signed-off-by: Richard Zhao Signed-off-by: Marek Vasut Cc: Peter Chen Acked-by: Felipe Balbi Tested-by: Subodh Nijsure Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/usb/mxs-phy.txt | 13 ++ drivers/usb/otg/Kconfig | 10 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/mxs-phy.c | 186 ++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/mxs-phy.txt create mode 100644 drivers/usb/otg/mxs-phy.c diff --git a/Documentation/devicetree/bindings/usb/mxs-phy.txt b/Documentation/devicetree/bindings/usb/mxs-phy.txt new file mode 100644 index 000000000000..5835b27146ea --- /dev/null +++ b/Documentation/devicetree/bindings/usb/mxs-phy.txt @@ -0,0 +1,13 @@ +* Freescale MXS USB Phy Device + +Required properties: +- compatible: Should be "fsl,imx23-usbphy" +- reg: Should contain registers location and length +- interrupts: Should contain phy interrupt + +Example: +usbphy1: usbphy@020c9000 { + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; + reg = <0x020c9000 0x1000>; + interrupts = <0 44 0x04>; +}; diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db06b598..13fd1ddf742f 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -116,6 +116,16 @@ config FSL_USB2_OTG help Enable this to support Freescale USB OTG transceiver. +config USB_MXS_PHY + tristate "Freescale MXS USB PHY support" + depends on ARCH_MXC || ARCH_MXS + select STMP_DEVICE + select USB_OTG_UTILS + help + Enable this to support the Freescale MXS USB PHY. + + MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa5098b139..a844b8d35d14 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c new file mode 100644 index 000000000000..c1a67cb8e244 --- /dev/null +++ b/drivers/usb/otg/mxs-phy.c @@ -0,0 +1,186 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Marek Vasut + * on behalf of DENX Software Engineering GmbH + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "mxs_phy" + +#define HW_USBPHY_PWD 0x00 +#define HW_USBPHY_CTRL 0x30 +#define HW_USBPHY_CTRL_SET 0x34 +#define HW_USBPHY_CTRL_CLR 0x38 + +#define BM_USBPHY_CTRL_SFTRST BIT(31) +#define BM_USBPHY_CTRL_CLKGATE BIT(30) +#define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15) +#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) +#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) + +struct mxs_phy { + struct usb_phy phy; + struct clk *clk; +}; + +#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) + +static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) +{ + void __iomem *base = mxs_phy->phy.io_priv; + + stmp_reset_block(base + HW_USBPHY_CTRL); + + /* Power up the PHY */ + writel_relaxed(0, base + HW_USBPHY_PWD); + + /* enable FS/LS device */ + writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 | + BM_USBPHY_CTRL_ENUTMILEVEL3, + base + HW_USBPHY_CTRL_SET); +} + +static int mxs_phy_init(struct usb_phy *phy) +{ + struct mxs_phy *mxs_phy = to_mxs_phy(phy); + + clk_prepare_enable(mxs_phy->clk); + mxs_phy_hw_init(mxs_phy); + + return 0; +} + +static void mxs_phy_shutdown(struct usb_phy *phy) +{ + struct mxs_phy *mxs_phy = to_mxs_phy(phy); + + writel_relaxed(BM_USBPHY_CTRL_CLKGATE, + phy->io_priv + HW_USBPHY_CTRL_SET); + + clk_disable_unprepare(mxs_phy->clk); +} + +static int mxs_phy_on_connect(struct usb_phy *phy, int port) +{ + dev_dbg(phy->dev, "Connect on port %d\n", port); + + mxs_phy_hw_init(to_mxs_phy(phy)); + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + phy->io_priv + HW_USBPHY_CTRL_SET); + + return 0; +} + +static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) +{ + dev_dbg(phy->dev, "Disconnect on port %d\n", port); + + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + phy->io_priv + HW_USBPHY_CTRL_CLR); + + return 0; +} + +static int mxs_phy_probe(struct platform_device *pdev) +{ + struct resource *res; + void __iomem *base; + struct clk *clk; + struct mxs_phy *mxs_phy; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "can't get device resources\n"); + return -ENOENT; + } + + base = devm_request_and_ioremap(&pdev->dev, res); + if (!base) + return -EBUSY; + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, + "can't get the clock, err=%ld", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL); + if (!mxs_phy) { + dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n"); + return -ENOMEM; + } + + mxs_phy->phy.io_priv = base; + mxs_phy->phy.dev = &pdev->dev; + mxs_phy->phy.label = DRIVER_NAME; + mxs_phy->phy.init = mxs_phy_init; + mxs_phy->phy.shutdown = mxs_phy_shutdown; + mxs_phy->phy.notify_connect = mxs_phy_on_connect; + mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect; + + ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier); + + mxs_phy->clk = clk; + + platform_set_drvdata(pdev, &mxs_phy->phy); + + return 0; +} + +static int __devexit mxs_phy_remove(struct platform_device *pdev) +{ + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id mxs_phy_dt_ids[] = { + { .compatible = "fsl,imx23-usbphy", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); + +static struct platform_driver mxs_phy_driver = { + .probe = mxs_phy_probe, + .remove = __devexit_p(mxs_phy_remove), + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = mxs_phy_dt_ids, + }, +}; + +static int __init mxs_phy_module_init(void) +{ + return platform_driver_register(&mxs_phy_driver); +} +postcore_initcall(mxs_phy_module_init); + +static void __exit mxs_phy_module_exit(void) +{ + platform_driver_unregister(&mxs_phy_driver); +} +module_exit(mxs_phy_module_exit); + +MODULE_ALIAS("platform:mxs-usb-phy"); +MODULE_AUTHOR("Marek Vasut "); +MODULE_AUTHOR("Richard Zhao "); +MODULE_DESCRIPTION("Freescale MXS USB PHY driver"); +MODULE_LICENSE("GPL"); -- GitLab From 1530280084c3905be6fce802cbfa83fb3bbb8839 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 7 Jul 2012 22:56:48 +0800 Subject: [PATCH 2350/5711] usb: chipidea: add imx platform driver This patch supports only the host-mode functionality so far. Signed-off-by: Richard Zhao Signed-off-by: Marek Vasut Cc: Peter Chen Cc: Alexander Shishkin Cc: Felipe Balbi Tested-by: Subodh Nijsure Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/usb/ci13xxx-imx.txt | 18 ++ drivers/usb/chipidea/Makefile | 3 + drivers/usb/chipidea/ci13xxx_imx.c | 198 ++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/ci13xxx-imx.txt create mode 100644 drivers/usb/chipidea/ci13xxx_imx.c diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt new file mode 100644 index 000000000000..2c290418bb2d --- /dev/null +++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt @@ -0,0 +1,18 @@ +* Freescale i.MX ci13xxx usb controllers + +Required properties: +- compatible: Should be "fsl,imx27-usb" +- reg: Should contain registers location and length +- interrupts: Should contain controller interrupt + +Optional properties: +- fsl,usbphy: phandler of usb phy that connects to the only one port +- vbus-supply: regulator for vbus + +Examples: +usb@02184000 { /* USB OTG */ + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; + reg = <0x02184000 0x200>; + interrupts = <0 43 0x04>; + fsl,usbphy = <&usbphy1>; +}; diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index b69900a62a4d..5c66d9c330ca 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -14,3 +14,6 @@ ifneq ($(CONFIG_PCI),) obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o endif +ifneq ($(CONFIG_OF_DEVICE),) + obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o +endif diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c new file mode 100644 index 000000000000..ef60d06835d0 --- /dev/null +++ b/drivers/usb/chipidea/ci13xxx_imx.c @@ -0,0 +1,198 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Marek Vasut + * on behalf of DENX Software Engineering GmbH + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ci.h" + +#define pdev_to_phy(pdev) \ + ((struct usb_phy *)platform_get_drvdata(pdev)) + +struct ci13xxx_imx_data { + struct device_node *phy_np; + struct usb_phy *phy; + struct platform_device *ci_pdev; + struct clk *clk; + struct regulator *reg_vbus; +}; + +static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = { + .name = "ci13xxx_imx", + .flags = CI13XXX_REQUIRE_TRANSCEIVER | + CI13XXX_PULLUP_ON_VBUS | + CI13XXX_DISABLE_STREAMING, + .capoffset = DEF_CAPOFFSET, +}; + +static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) +{ + struct ci13xxx_imx_data *data; + struct platform_device *plat_ci, *phy_pdev; + struct device_node *phy_np; + struct resource *res; + struct regulator *reg_vbus; + int ret; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Can't get device resources!\n"); + return -ENOENT; + } + + data->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, + "Failed to get clock, err=%ld\n", PTR_ERR(data->clk)); + return PTR_ERR(data->clk); + } + + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, + "Failed to prepare or enable clock, err=%d\n", ret); + return ret; + } + + phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0); + if (phy_np) { + data->phy_np = phy_np; + phy_pdev = of_find_device_by_node(phy_np); + if (phy_pdev) { + struct usb_phy *phy; + phy = pdev_to_phy(phy_pdev); + if (phy && + try_module_get(phy_pdev->dev.driver->owner)) { + usb_phy_init(phy); + data->phy = phy; + } + } + } + + /* we only support host now, so enable vbus here */ + reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (!IS_ERR(reg_vbus)) { + ret = regulator_enable(reg_vbus); + if (ret) { + dev_err(&pdev->dev, + "Failed to enable vbus regulator, err=%d\n", + ret); + goto put_np; + } + data->reg_vbus = reg_vbus; + } else { + reg_vbus = NULL; + } + + ci13xxx_imx_platdata.phy = data->phy; + + if (!pdev->dev.dma_mask) { + pdev->dev.dma_mask = devm_kzalloc(&pdev->dev, + sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) { + ret = -ENOMEM; + dev_err(&pdev->dev, "Failed to alloc dma_mask!\n"); + goto err; + } + *pdev->dev.dma_mask = DMA_BIT_MASK(32); + dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask); + } + plat_ci = ci13xxx_add_device(&pdev->dev, + pdev->resource, pdev->num_resources, + &ci13xxx_imx_platdata); + if (IS_ERR(plat_ci)) { + ret = PTR_ERR(plat_ci); + dev_err(&pdev->dev, + "Can't register ci_hdrc platform device, err=%d\n", + ret); + goto err; + } + + data->ci_pdev = plat_ci; + platform_set_drvdata(pdev, data); + + pm_runtime_no_callbacks(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + return 0; + +err: + if (reg_vbus) + regulator_disable(reg_vbus); +put_np: + if (phy_np) + of_node_put(phy_np); + clk_disable_unprepare(data->clk); + return ret; +} + +static int __devexit ci13xxx_imx_remove(struct platform_device *pdev) +{ + struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + ci13xxx_remove_device(data->ci_pdev); + + if (data->reg_vbus) + regulator_disable(data->reg_vbus); + + if (data->phy) { + usb_phy_shutdown(data->phy); + module_put(data->phy->dev->driver->owner); + } + + of_node_put(data->phy_np); + + clk_disable_unprepare(data->clk); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id ci13xxx_imx_dt_ids[] = { + { .compatible = "fsl,imx27-usb", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids); + +static struct platform_driver ci13xxx_imx_driver = { + .probe = ci13xxx_imx_probe, + .remove = __devexit_p(ci13xxx_imx_remove), + .driver = { + .name = "imx_usb", + .owner = THIS_MODULE, + .of_match_table = ci13xxx_imx_dt_ids, + }, +}; + +module_platform_driver(ci13xxx_imx_driver); + +MODULE_ALIAS("platform:imx-usb"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CI13xxx i.MX USB binding"); +MODULE_AUTHOR("Marek Vasut "); +MODULE_AUTHOR("Richard Zhao "); -- GitLab From ce27e317ba22b359bde02216afab934dac3af095 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 3 Jul 2012 10:38:06 -0700 Subject: [PATCH 2351/5711] cgroup: cgroup_rm_files() was calling simple_unlink() with the wrong inode While refactoring cgroup file removal path, 05ef1d7c4a "cgroup: introduce struct cfent" incorrectly changed the @dir argument of simple_unlink() to the inode of the file being deleted instead of that of the containing directory. The effect of this bug is minor - ctime and mtime of the parent weren't properly updated on file deletion. Fix it by using @cgrp->dentry->d_inode instead. Signed-off-by: Tejun Heo Reported-by: Al Viro Acked-by: Li Zefan Cc: stable@vger.kernel.org --- kernel/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index dec62f5936ef..a56805aa0f1b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -959,7 +959,7 @@ static int cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) dget(d); d_delete(d); - simple_unlink(d->d_inode, d); + simple_unlink(cgrp->dentry->d_inode, d); list_del_init(&cfe->node); dput(d); -- GitLab From 939546d1a9f47ed169554c711e1e05965b84ffe1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 9 Jul 2012 10:00:00 +0100 Subject: [PATCH 2352/5711] iio: Add callback to check whether a scan mask is valid This is useful for cases where the number of valid scan masks grows exponentially, but it is rather easy to check whether a mask is valid or not programmatically. An example of such a case is a device with multiple ADCs where each ADC has a upstream MUX, which allows to select from a number of physical channels. +-------+ +-------+ | | | | --- Channel 1 | ADC 1 |---| MUX 1 | --- ... | | | | --- Channel M +-------+ +-------+ . . . . . . . . . +-------+ +-------+ | | | | --- Channel M * N + 1 | ADC N |---| MUX N | --- ... | | | | --- Channel M * N + M +-------+ +-------+ The number of necessary scan masks for this case is (M+1)**N - 1, on the other hand it is easy to check whether subsets for each ADC of the scanmask have only one bit set. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 27 ++++++++++++++++++++------- include/linux/iio/iio.h | 4 ++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 3d8d187eef2a..cc5db36fb75a 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -570,6 +570,15 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_sw_buffer_preenable); +static bool iio_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *mask) +{ + if (!indio_dev->setup_ops->validate_scan_mask) + return true; + + return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); +} + /** * iio_scan_mask_set() - set particular bit in the scan mask * @buffer: the buffer whose scan mask we are interested in @@ -589,27 +598,31 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, return -ENOMEM; if (!indio_dev->masklength) { WARN_ON("trying to set scanmask prior to registering buffer\n"); - kfree(trialmask); - return -EINVAL; + goto err_invalid_mask; } bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); set_bit(bit, trialmask); + if (!iio_validate_scan_mask(indio_dev, trialmask)) + goto err_invalid_mask; + if (indio_dev->available_scan_masks) { mask = iio_scan_mask_match(indio_dev->available_scan_masks, indio_dev->masklength, trialmask); - if (!mask) { - kfree(trialmask); - return -EINVAL; - } + if (!mask) + goto err_invalid_mask; } bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); kfree(trialmask); return 0; -}; + +err_invalid_mask: + kfree(trialmask); + return -EINVAL; +} EXPORT_SYMBOL_GPL(iio_scan_mask_set); int iio_scan_mask_query(struct iio_dev *indio_dev, diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 2afbb6f01afc..be82936c4089 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -363,12 +363,16 @@ struct iio_info { * @predisable: [DRIVER] function to run prior to marking buffer * disabled * @postdisable: [DRIVER] function to run after marking buffer disabled + * @validate_scan_mask: [DRIVER] function callback to check whether a given + * scan mask is valid for the device. */ struct iio_buffer_setup_ops { int (*preenable)(struct iio_dev *); int (*postenable)(struct iio_dev *); int (*predisable)(struct iio_dev *); int (*postdisable)(struct iio_dev *); + bool (*validate_scan_mask)(struct iio_dev *indio_dev, + const unsigned long *scan_mask); }; /** -- GitLab From 81636632057cc1bece2531220dd5803036f95ea9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 9 Jul 2012 10:00:00 +0100 Subject: [PATCH 2353/5711] iio: Introduce iio_validate_scan_mask_onehot Add a helper function for validating a scan mask for devices where exactly one channel must be selected during sampling. This is a common case among devices which have scan mask restrictions so it makes sense to provide this function in the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 16 ++++++++++++++++ include/linux/iio/buffer.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index cc5db36fb75a..8c1dc9a683fb 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -570,6 +570,22 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_sw_buffer_preenable); +/** + * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected + * @indio_dev: the iio device + * @mask: scan mask to be checked + * + * Return true if exactly one bit is set in the scan mask, false otherwise. It + * can be used for devices where only one channel can be active for sampling at + * a time. + */ +bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, + const unsigned long *mask) +{ + return bitmap_weight(mask, indio_dev->masklength) == 1; +} +EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); + static bool iio_validate_scan_mask(struct iio_dev *indio_dev, const unsigned long *mask) { diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 2a2b6b4d8d05..8ba516fc2ec6 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -177,6 +177,9 @@ ssize_t iio_buffer_show_enable(struct device *dev, int iio_sw_buffer_preenable(struct iio_dev *indio_dev); +bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, + const unsigned long *mask); + #else /* CONFIG_IIO_BUFFER */ static inline int iio_buffer_register(struct iio_dev *indio_dev, -- GitLab From f6aea5543021c341f0397b191243fecca98ac595 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 9 Jul 2012 10:00:00 +0100 Subject: [PATCH 2354/5711] staging:iio:ad7192: Use iio_validate_scan_mask_onehot Only one of the channels of the ad7192 may be sampled at a time. Use the new validate_scan_mask callback and the iio_validate_scan_mask_onehot function to implement this restriction. Previously this was implemented using available_scan_masks, but this requires a individual scan mask for each channel. Also the previous code was adding the scan index of the timestamp channel to each available scan mask, this is not required though since the timestamp channel is not restricted by the available scan masks and can be enabled or disabled independently. So the new code does not have to take care of this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 839f17c4e33d..22c3923d55eb 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -146,7 +146,6 @@ struct ad7192_state { u32 mode; u32 conf; u32 scale_avail[8][2]; - long available_scan_masks[9]; u8 gpocon; u8 devid; /* @@ -538,6 +537,7 @@ static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = { .postenable = &iio_triggered_buffer_postenable, .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7192_ring_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, }; static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) @@ -984,7 +984,7 @@ static int __devinit ad7192_probe(struct spi_device *spi) struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret, i , voltage_uv = 0; + int ret , voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); @@ -1028,17 +1028,11 @@ static int __devinit ad7192_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad7192_channels; indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); - indio_dev->available_scan_masks = st->available_scan_masks; if (st->devid == ID_AD7195) indio_dev->info = &ad7195_info; else indio_dev->info = &ad7192_info; - for (i = 0; i < indio_dev->num_channels; i++) - st->available_scan_masks[i] = (1 << i) | (1 << - indio_dev->channels[indio_dev->num_channels - 1]. - scan_index); - init_waitqueue_head(&st->wq_data_avail); ret = ad7192_register_ring_funcs_and_init(indio_dev); -- GitLab From 8c2c6ba6aa8f187b465fab13627566311a0c03fb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 9 Jul 2012 10:00:00 +0100 Subject: [PATCH 2355/5711] staging:iio:ad7793: Use iio_validate_scan_mask_onehot Only one of the channels of the ad7793 may be sampled at a time. Use the new validate_scan_mask callback and the iio_validate_scan_mask_onehot function to implement this restriction. Previously this was implemented using available_scan_masks, but this requires a individual scan mask for each channel. Also the previous code was adding the scan index of the timestamp channel to each available scan mask, this is not required though since the timestamp channel is not restricted by the available scan masks and can be enabled or disabled independently. So the new code does not have to take care of this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index eaa0cc939165..76fdd7145fc5 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -52,8 +52,7 @@ struct ad7793_state { u16 mode; u16 conf; u32 scale_avail[8][2]; - /* Note this uses fact that 8 the mask always fits in a long */ - unsigned long available_scan_masks[7]; + /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -403,6 +402,7 @@ static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = { .postenable = &iio_triggered_buffer_postenable, .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7793_ring_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, }; static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) @@ -864,7 +864,7 @@ static int __devinit ad7793_probe(struct spi_device *spi) struct ad7793_platform_data *pdata = spi->dev.platform_data; struct ad7793_state *st; struct iio_dev *indio_dev; - int ret, i, voltage_uv = 0; + int ret, voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); @@ -910,17 +910,9 @@ static int __devinit ad7793_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channel; - indio_dev->available_scan_masks = st->available_scan_masks; indio_dev->num_channels = 7; indio_dev->info = &ad7793_info; - for (i = 0; i < indio_dev->num_channels; i++) { - set_bit(i, &st->available_scan_masks[i]); - set_bit(indio_dev-> - channels[indio_dev->num_channels - 1].scan_index, - &st->available_scan_masks[i]); - } - init_waitqueue_head(&st->wq_data_avail); ret = ad7793_register_ring_funcs_and_init(indio_dev); -- GitLab From ee0312a05ddceb0fc871f39b8f56b4cabc5176aa Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 9 Jul 2012 10:00:00 +0100 Subject: [PATCH 2356/5711] staging:iio:ade7758: Use iio_validate_scan_mask_onehot Only one of the channels of the ade7758 may be sampled at a time. Use the new validate_scan_mask callback and the iio_validate_scan_mask_onehot function to implement this restriction. Previously this was implemented using available_scan_masks, but this requires a individual scan mask for each channel. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/meter/ade7758.h | 1 - drivers/staging/iio/meter/ade7758_core.c | 7 +------ drivers/staging/iio/meter/ade7758_ring.c | 1 + 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index bdd1b05bf7a5..ec202b4ecfb2 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -122,7 +122,6 @@ struct ade7758_state { u8 *tx; u8 *rx; struct mutex buf_lock; - unsigned long available_scan_masks[AD7758_NUM_WAVESRC]; struct iio_chan_spec *ade7758_ring_channels; struct spi_transfer ring_xfer[4]; struct spi_message ring_msg; diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 96d6114a31aa..7014a0078446 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -883,7 +883,7 @@ static const struct iio_info ade7758_info = { static int __devinit ade7758_probe(struct spi_device *spi) { - int i, ret; + int ret; struct ade7758_state *st; struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); @@ -916,11 +916,6 @@ static int __devinit ade7758_probe(struct spi_device *spi) indio_dev->info = &ade7758_info; indio_dev->modes = INDIO_DIRECT_MODE; - for (i = 0; i < AD7758_NUM_WAVESRC; i++) - set_bit(i, &st->available_scan_masks[i]); - - indio_dev->available_scan_masks = st->available_scan_masks; - ret = ade7758_configure_ring(indio_dev); if (ret) goto error_free_tx; diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 92159f208d14..1ce10b21f4d6 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -114,6 +114,7 @@ static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = { .preenable = &ade7758_ring_preenable, .postenable = &iio_triggered_buffer_postenable, .predisable = &iio_triggered_buffer_predisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, }; void ade7758_unconfigure_ring(struct iio_dev *indio_dev) -- GitLab From 47ec4ed2d23ff3a93f9f575295f17bdaf3d2cec9 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Sat, 7 Jul 2012 20:44:49 +0200 Subject: [PATCH 2357/5711] staging: CSR: fix function declaration warnings Sparse is warning about non-ANSI function declaration. Add void to the parameterless function. drivers/staging/csr/csr_wifi_hip_chiphelper.c:633:31: warning: non-ANSI function declaration of function 'ChipHelper_Null' I also fixed this checkpatch error: ERROR: "foo* bar" should be "foo *bar" Signed-off-by: Emil Goode Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/csr_wifi_hip_chiphelper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.c b/drivers/staging/csr/csr_wifi_hip_chiphelper.c index 0e2477ff4dd0..a3148d87609a 100644 --- a/drivers/staging/csr/csr_wifi_hip_chiphelper.c +++ b/drivers/staging/csr/csr_wifi_hip_chiphelper.c @@ -630,7 +630,7 @@ ChipDescript* ChipHelper_GetVersionUniFi(CsrUint16 ver) } -ChipDescript* ChipHelper_Null() +ChipDescript *ChipHelper_Null(void) { return &chip_device_desc_null; } -- GitLab From 30453529bc17161fd863093ebf7a4bfce9820159 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:49:46 +0800 Subject: [PATCH 2358/5711] staging: zcache: fix refcount leak In zcache_get_pool_by_id, the refcount of zcache_host is not increased, but it is always decreased in zcache_put_pool Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index c9e08bbeb519..55fbe3db7d53 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -946,8 +946,9 @@ static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) cli = &zcache_clients[cli_id]; if (cli == NULL) goto out; - atomic_inc(&cli->refcount); } + + atomic_inc(&cli->refcount); pool = idr_find(&cli->tmem_pools, poolid); if (pool != NULL) atomic_inc(&pool->refcount); -- GitLab From a16554474f772ea857bf193608231a735e01cccc Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:50:10 +0800 Subject: [PATCH 2359/5711] staging: zcache: fix a compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: drivers/staging/zcache/zcache-main.c: In function ‘zcache_comp_op’: drivers/staging/zcache/zcache-main.c:112:2: warning: ‘ret’ may be used uninitial Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 55fbe3db7d53..58e7bd432508 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -109,6 +109,8 @@ static inline int zcache_comp_op(enum comp_op op, case ZCACHE_COMPOP_DECOMPRESS: ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); break; + default: + ret = -EINVAL; } put_cpu(); return ret; -- GitLab From f64d94f9f7536842a120f6eef4cfd4cfcd516f5e Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:50:31 +0800 Subject: [PATCH 2360/5711] staging: zcache: remove unnecessary config option dependence zcache is enabled only if one of CONFIG_CLEANCACHE and CONFIG_FRONTSWAP is enabled, see the Kconfig: depends on (CLEANCACHE || FRONTSWAP) && CRYPTO=y && X86 So, we can remove the check in the source code Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 58e7bd432508..36c3b05926e3 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -36,9 +36,6 @@ #include "../zsmalloc/zsmalloc.h" -#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) -#error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" -#endif #ifdef CONFIG_CLEANCACHE #include #endif @@ -2028,7 +2025,7 @@ static int __init zcache_init(void) goto out; } #endif /* CONFIG_SYSFS */ -#if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP) + if (zcache_enabled) { unsigned int cpu; @@ -2059,7 +2056,7 @@ static int __init zcache_init(void) pr_err("zcache: can't create client\n"); goto out; } -#endif + #ifdef CONFIG_CLEANCACHE if (zcache_enabled && use_cleancache) { struct cleancache_ops old_ops; -- GitLab From 2ad0f81c588a7a4e0fb685cbd2246b4907401784 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:50:50 +0800 Subject: [PATCH 2361/5711] staging: zcache: mark zbud_init/zcache_comp_init as __init These functions are called only when system is initializing, so mark __init for them to free memory Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 36c3b05926e3..a77cacbbe7cd 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -600,7 +600,7 @@ out: return; } -static void zbud_init(void) +static void __init zbud_init(void) { int i; @@ -1985,7 +1985,7 @@ static int __init enable_zcache_compressor(char *s) __setup("zcache=", enable_zcache_compressor); -static int zcache_comp_init(void) +static int __init zcache_comp_init(void) { int ret = 0; -- GitLab From dc2f9a5d3d0a7a6c0e1a891c70ed2171869dd78d Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:51:10 +0800 Subject: [PATCH 2362/5711] staging: zcache: cleanup zbud_init Need not set global parameters to 0 Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index a77cacbbe7cd..0529b4685161 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -605,11 +605,9 @@ static void __init zbud_init(void) int i; INIT_LIST_HEAD(&zbud_buddied_list); - zcache_zbud_buddied_count = 0; - for (i = 0; i < NCHUNKS; i++) { + + for (i = 0; i < NCHUNKS; i++) INIT_LIST_HEAD(&zbud_unbuddied[i].list); - zbud_unbuddied[i].count = 0; - } } #ifdef CONFIG_SYSFS -- GitLab From 79c0d92c5b6175c1462fbe38bf44180f325aa478 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:51:34 +0800 Subject: [PATCH 2363/5711] staging: zcache: optimize zcache_do_preload zcache_do_preload is called in zcache_put_page where IRQ is disabled, so, need not care preempt Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 0529b4685161..57e25fc67453 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1031,45 +1031,43 @@ static int zcache_do_preload(struct tmem_pool *pool) goto out; if (unlikely(zcache_obj_cache == NULL)) goto out; - preempt_disable(); + + /* IRQ has already been disabled. */ kp = &__get_cpu_var(zcache_preloads); while (kp->nr < ARRAY_SIZE(kp->objnodes)) { - preempt_enable_no_resched(); objnode = kmem_cache_alloc(zcache_objnode_cache, ZCACHE_GFP_MASK); if (unlikely(objnode == NULL)) { zcache_failed_alloc++; goto out; } - preempt_disable(); - kp = &__get_cpu_var(zcache_preloads); - if (kp->nr < ARRAY_SIZE(kp->objnodes)) - kp->objnodes[kp->nr++] = objnode; - else - kmem_cache_free(zcache_objnode_cache, objnode); + + kp->objnodes[kp->nr++] = objnode; } - preempt_enable_no_resched(); + obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); if (unlikely(obj == NULL)) { zcache_failed_alloc++; goto out; } + page = (void *)__get_free_page(ZCACHE_GFP_MASK); if (unlikely(page == NULL)) { zcache_failed_get_free_pages++; kmem_cache_free(zcache_obj_cache, obj); goto out; } - preempt_disable(); - kp = &__get_cpu_var(zcache_preloads); + if (kp->obj == NULL) kp->obj = obj; else kmem_cache_free(zcache_obj_cache, obj); + if (kp->page == NULL) kp->page = page; else free_page((unsigned long)page); + ret = 0; out: return ret; @@ -1580,7 +1578,6 @@ static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, zcache_failed_pers_puts++; } zcache_put_pool(pool); - preempt_enable_no_resched(); } else { zcache_put_to_flush++; if (atomic_read(&pool->obj_count) > 0) -- GitLab From b71f3bcc5ab5e76a22d7ad82b3795602fcf0e0af Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:51:55 +0800 Subject: [PATCH 2364/5711] staging: zcache: cleanup zcache_do_preload and zcache_put_page Cleanup the code for zcache_do_preload and zcache_put_page Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 37 ++++++++++++---------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 57e25fc67453..fbd9bcfa9d9a 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1045,29 +1045,24 @@ static int zcache_do_preload(struct tmem_pool *pool) kp->objnodes[kp->nr++] = objnode; } - obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); - if (unlikely(obj == NULL)) { - zcache_failed_alloc++; - goto out; + if (!kp->obj) { + obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); + if (unlikely(obj == NULL)) { + zcache_failed_alloc++; + goto out; + } + kp->obj = obj; } - page = (void *)__get_free_page(ZCACHE_GFP_MASK); - if (unlikely(page == NULL)) { - zcache_failed_get_free_pages++; - kmem_cache_free(zcache_obj_cache, obj); - goto out; + if (!kp->page) { + page = (void *)__get_free_page(ZCACHE_GFP_MASK); + if (unlikely(page == NULL)) { + zcache_failed_get_free_pages++; + goto out; + } + kp->page = page; } - if (kp->obj == NULL) - kp->obj = obj; - else - kmem_cache_free(zcache_obj_cache, obj); - - if (kp->page == NULL) - kp->page = page; - else - free_page((unsigned long)page); - ret = 0; out: return ret; @@ -1577,14 +1572,14 @@ static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, else zcache_failed_pers_puts++; } - zcache_put_pool(pool); } else { zcache_put_to_flush++; if (atomic_read(&pool->obj_count) > 0) /* the put fails whether the flush succeeds or not */ (void)tmem_flush_page(pool, oidp, index); - zcache_put_pool(pool); } + + zcache_put_pool(pool); out: return ret; } -- GitLab From 08b0b50048cea27437e06a5544b4ecc443a32f7d Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:52:17 +0800 Subject: [PATCH 2365/5711] staging: zcache: introduce get_zcache_client Introduce get_zcache_client to remove the common code Acked-by: Seth Jennings Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 46 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index fbd9bcfa9d9a..2b5c73c89c33 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -74,6 +74,17 @@ static inline uint16_t get_client_id_from_client(struct zcache_client *cli) return cli - &zcache_clients[0]; } +static struct zcache_client *get_zcache_client(uint16_t cli_id) +{ + if (cli_id == LOCAL_CLIENT) + return &zcache_host; + + if ((unsigned int)cli_id < MAX_CLIENTS) + return &zcache_clients[cli_id]; + + return NULL; +} + static inline bool is_local_client(struct zcache_client *cli) { return cli == &zcache_host; @@ -935,15 +946,9 @@ static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) struct tmem_pool *pool = NULL; struct zcache_client *cli = NULL; - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else { - if (cli_id >= MAX_CLIENTS) - goto out; - cli = &zcache_clients[cli_id]; - if (cli == NULL) - goto out; - } + cli = get_zcache_client(cli_id); + if (!cli) + goto out; atomic_inc(&cli->refcount); pool = idr_find(&cli->tmem_pools, poolid); @@ -966,13 +971,11 @@ static void zcache_put_pool(struct tmem_pool *pool) int zcache_new_client(uint16_t cli_id) { - struct zcache_client *cli = NULL; + struct zcache_client *cli; int ret = -1; - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; + cli = get_zcache_client(cli_id); + if (cli == NULL) goto out; if (cli->allocated) @@ -1649,17 +1652,16 @@ static int zcache_flush_object(int cli_id, int pool_id, static int zcache_destroy_pool(int cli_id, int pool_id) { struct tmem_pool *pool = NULL; - struct zcache_client *cli = NULL; + struct zcache_client *cli; int ret = -1; if (pool_id < 0) goto out; - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; + + cli = get_zcache_client(cli_id); if (cli == NULL) goto out; + atomic_inc(&cli->refcount); pool = idr_find(&cli->tmem_pools, pool_id); if (pool == NULL) @@ -1686,12 +1688,10 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) struct zcache_client *cli = NULL; int r; - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; + cli = get_zcache_client(cli_id); if (cli == NULL) goto out; + atomic_inc(&cli->refcount); pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); if (pool == NULL) { -- GitLab From c666e636ac9915f33fe175c75bc01ab994e5afa6 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 26 Jun 2012 16:52:50 +0800 Subject: [PATCH 2366/5711] staging: zcache: cleanup the code between tmem_obj_init and tmem_obj_find tmem_obj_find and insertion tmem-obj have the some logic, we can integrate the code Signed-off-by: Xiao Guangrong Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/tmem.c | 63 ++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c index 1ca66ea9b281..eaa90213457b 100644 --- a/drivers/staging/zcache/tmem.c +++ b/drivers/staging/zcache/tmem.c @@ -72,33 +72,49 @@ void tmem_register_pamops(struct tmem_pamops *m) * the hashbucket lock must be held. */ -/* searches for object==oid in pool, returns locked object if found */ -static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, - struct tmem_oid *oidp) +static struct tmem_obj +*__tmem_obj_find(struct tmem_hashbucket*hb, struct tmem_oid *oidp, + struct rb_node **parent, struct rb_node ***link) { - struct rb_node *rbnode; - struct tmem_obj *obj; - - rbnode = hb->obj_rb_root.rb_node; - while (rbnode) { - BUG_ON(RB_EMPTY_NODE(rbnode)); - obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); + struct rb_node *_parent = NULL, **rbnode; + struct tmem_obj *obj = NULL; + + rbnode = &hb->obj_rb_root.rb_node; + while (*rbnode) { + BUG_ON(RB_EMPTY_NODE(*rbnode)); + _parent = *rbnode; + obj = rb_entry(*rbnode, struct tmem_obj, + rb_tree_node); switch (tmem_oid_compare(oidp, &obj->oid)) { case 0: /* equal */ goto out; case -1: - rbnode = rbnode->rb_left; + rbnode = &(*rbnode)->rb_left; break; case 1: - rbnode = rbnode->rb_right; + rbnode = &(*rbnode)->rb_right; break; } } + + if (parent) + *parent = _parent; + if (link) + *link = rbnode; + obj = NULL; out: return obj; } + +/* searches for object==oid in pool, returns locked object if found */ +static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, + struct tmem_oid *oidp) +{ + return __tmem_obj_find(hb, oidp, NULL, NULL); +} + static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *); /* free an object that has no more pampds in it */ @@ -131,8 +147,7 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, struct tmem_oid *oidp) { struct rb_root *root = &hb->obj_rb_root; - struct rb_node **new = &(root->rb_node), *parent = NULL; - struct tmem_obj *this; + struct rb_node **new = NULL, *parent = NULL; BUG_ON(pool == NULL); atomic_inc(&pool->obj_count); @@ -144,22 +159,10 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, obj->pampd_count = 0; (*tmem_pamops.new_obj)(obj); SET_SENTINEL(obj, OBJ); - while (*new) { - BUG_ON(RB_EMPTY_NODE(*new)); - this = rb_entry(*new, struct tmem_obj, rb_tree_node); - parent = *new; - switch (tmem_oid_compare(oidp, &this->oid)) { - case 0: - BUG(); /* already present; should never happen! */ - break; - case -1: - new = &(*new)->rb_left; - break; - case 1: - new = &(*new)->rb_right; - break; - } - } + + if (__tmem_obj_find(hb, oidp, &parent, &new)) + BUG(); + rb_link_node(&obj->rb_tree_node, parent, new); rb_insert_color(&obj->rb_tree_node, root); } -- GitLab From 5f601902c61e6cda627ec71c10609021067ed0fa Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 2 Jul 2012 16:15:49 -0500 Subject: [PATCH 2367/5711] staging: zsmalloc: remove x86 dependency This patch replaces the page table assisted object mapping method, which has x86 dependencies, with a arch-independent method that does a simple copy into a temporary per-cpu buffer. While a copy seems like it would be worse than mapping the pages, tests demonstrate the copying is always faster and, in the case of running inside a KVM guest, roughly 4x faster. Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/Kconfig | 4 - drivers/staging/zsmalloc/zsmalloc-main.c | 99 +++++++++++++++++------- drivers/staging/zsmalloc/zsmalloc_int.h | 5 +- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig index a5ab7200626f..908456565796 100644 --- a/drivers/staging/zsmalloc/Kconfig +++ b/drivers/staging/zsmalloc/Kconfig @@ -1,9 +1,5 @@ config ZSMALLOC tristate "Memory allocator for compressed pages" - # X86 dependency is because of the use of __flush_tlb_one and set_pte - # in zsmalloc-main.c. - # TODO: convert these to portable functions - depends on X86 default n help zsmalloc is a slab-based memory allocator designed to store diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 10b0d6000260..a7a6f225bbff 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -470,6 +470,57 @@ static struct page *find_get_zspage(struct size_class *class) return page; } +static void zs_copy_map_object(char *buf, struct page *firstpage, + int off, int size) +{ + struct page *pages[2]; + int sizes[2]; + void *addr; + + pages[0] = firstpage; + pages[1] = get_next_page(firstpage); + BUG_ON(!pages[1]); + + sizes[0] = PAGE_SIZE - off; + sizes[1] = size - sizes[0]; + + /* disable page faults to match kmap_atomic() return conditions */ + pagefault_disable(); + + /* copy object to per-cpu buffer */ + addr = kmap_atomic(pages[0]); + memcpy(buf, addr + off, sizes[0]); + kunmap_atomic(addr); + addr = kmap_atomic(pages[1]); + memcpy(buf + sizes[0], addr, sizes[1]); + kunmap_atomic(addr); +} + +static void zs_copy_unmap_object(char *buf, struct page *firstpage, + int off, int size) +{ + struct page *pages[2]; + int sizes[2]; + void *addr; + + pages[0] = firstpage; + pages[1] = get_next_page(firstpage); + BUG_ON(!pages[1]); + + sizes[0] = PAGE_SIZE - off; + sizes[1] = size - sizes[0]; + + /* copy per-cpu buffer to object */ + addr = kmap_atomic(pages[0]); + memcpy(addr + off, buf, sizes[0]); + kunmap_atomic(addr); + addr = kmap_atomic(pages[1]); + memcpy(addr, buf + sizes[0], sizes[1]); + kunmap_atomic(addr); + + /* enable page faults to match kunmap_atomic() return conditions */ + pagefault_enable(); +} static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) @@ -480,18 +531,23 @@ static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, switch (action) { case CPU_UP_PREPARE: area = &per_cpu(zs_map_area, cpu); - if (area->vm) - break; - area->vm = alloc_vm_area(2 * PAGE_SIZE, area->vm_ptes); - if (!area->vm) - return notifier_from_errno(-ENOMEM); + /* + * Make sure we don't leak memory if a cpu UP notification + * and zs_init() race and both call zs_cpu_up() on the same cpu + */ + if (area->vm_buf) + return 0; + area->vm_buf = (char *)__get_free_page(GFP_KERNEL); + if (!area->vm_buf) + return -ENOMEM; + return 0; break; case CPU_DEAD: case CPU_UP_CANCELED: area = &per_cpu(zs_map_area, cpu); - if (area->vm) - free_vm_area(area->vm); - area->vm = NULL; + if (area->vm_buf) + free_page((unsigned long)area->vm_buf); + area->vm_buf = NULL; break; } @@ -714,22 +770,11 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle) if (off + class->size <= PAGE_SIZE) { /* this object is contained entirely within a page */ area->vm_addr = kmap_atomic(page); - } else { - /* this object spans two pages */ - struct page *nextp; - - nextp = get_next_page(page); - BUG_ON(!nextp); - - - set_pte(area->vm_ptes[0], mk_pte(page, PAGE_KERNEL)); - set_pte(area->vm_ptes[1], mk_pte(nextp, PAGE_KERNEL)); - - /* We pre-allocated VM area so mapping can never fail */ - area->vm_addr = area->vm->addr; + return area->vm_addr + off; } - return area->vm_addr + off; + zs_copy_map_object(area->vm_buf, page, off, class->size); + return area->vm_buf; } EXPORT_SYMBOL_GPL(zs_map_object); @@ -751,14 +796,10 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) off = obj_idx_to_offset(page, obj_idx, class->size); area = &__get_cpu_var(zs_map_area); - if (off + class->size <= PAGE_SIZE) { + if (off + class->size <= PAGE_SIZE) kunmap_atomic(area->vm_addr); - } else { - set_pte(area->vm_ptes[0], __pte(0)); - set_pte(area->vm_ptes[1], __pte(0)); - __flush_tlb_one((unsigned long)area->vm_addr); - __flush_tlb_one((unsigned long)area->vm_addr + PAGE_SIZE); - } + else + zs_copy_unmap_object(area->vm_buf, page, off, class->size); put_cpu_var(zs_map_area); } EXPORT_SYMBOL_GPL(zs_unmap_object); diff --git a/drivers/staging/zsmalloc/zsmalloc_int.h b/drivers/staging/zsmalloc/zsmalloc_int.h index 6fd32a9e0315..f760dae54f28 100644 --- a/drivers/staging/zsmalloc/zsmalloc_int.h +++ b/drivers/staging/zsmalloc/zsmalloc_int.h @@ -110,9 +110,8 @@ enum fullness_group { static const int fullness_threshold_frac = 4; struct mapping_area { - struct vm_struct *vm; - pte_t *vm_ptes[2]; - char *vm_addr; + char *vm_buf; /* copy buffer for objects that span pages */ + char *vm_addr; /* address of kmap_atomic()'ed pages */ }; struct size_class { -- GitLab From 103123305c4f695cbb11555d51a32ea14d6bed05 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 2 Jul 2012 16:15:50 -0500 Subject: [PATCH 2368/5711] staging: zsmalloc: add single-page object fastpath in unmap Improve zs_unmap_object() performance by adding a fast path for objects that don't span pages. Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index a7a6f225bbff..4942d419074b 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -774,6 +774,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle) } zs_copy_map_object(area->vm_buf, page, off, class->size); + area->vm_addr = NULL; return area->vm_buf; } EXPORT_SYMBOL_GPL(zs_map_object); @@ -788,6 +789,14 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) struct size_class *class; struct mapping_area *area; + area = &__get_cpu_var(zs_map_area); + if (area->vm_addr) { + /* single-page object fastpath */ + kunmap_atomic(area->vm_addr); + put_cpu_var(zs_map_area); + return; + } + BUG_ON(!handle); obj_handle_to_location(handle, &page, &obj_idx); @@ -795,11 +804,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) class = &pool->size_class[class_idx]; off = obj_idx_to_offset(page, obj_idx, class->size); - area = &__get_cpu_var(zs_map_area); - if (off + class->size <= PAGE_SIZE) - kunmap_atomic(area->vm_addr); - else - zs_copy_unmap_object(area->vm_buf, page, off, class->size); + zs_copy_unmap_object(area->vm_buf, page, off, class->size); put_cpu_var(zs_map_area); } EXPORT_SYMBOL_GPL(zs_unmap_object); -- GitLab From 166cfda752ca22eb6912614993b85f9a997dbd8f Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 2 Jul 2012 16:15:51 -0500 Subject: [PATCH 2369/5711] staging: zsmalloc: add details to zs_map_object boiler plate Add information on the usage limits of zs_map_object() Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 4942d419074b..abf7c13c89c8 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -747,7 +747,12 @@ EXPORT_SYMBOL_GPL(zs_free); * * Before using an object allocated from zs_malloc, it must be mapped using * this function. When done with the object, it must be unmapped using - * zs_unmap_object + * zs_unmap_object. + * + * Only one object can be mapped per cpu at a time. There is no protection + * against nested mappings. + * + * This function returns with preemption and page faults disabled. */ void *zs_map_object(struct zs_pool *pool, unsigned long handle) { -- GitLab From b74185108668ef966e663878adbad65e03bfcb43 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 2 Jul 2012 16:15:52 -0500 Subject: [PATCH 2370/5711] staging: zsmalloc: add mapping modes This patch improves mapping performance in zsmalloc by getting usage information from the user in the form of a "mapping mode" and using it to avoid unnecessary copying for objects that span pages. Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 6 ++--- drivers/staging/zram/zram_drv.c | 7 +++--- drivers/staging/zsmalloc/zsmalloc-main.c | 29 +++++++++++++++--------- drivers/staging/zsmalloc/zsmalloc.h | 14 +++++++++++- drivers/staging/zsmalloc/zsmalloc_int.h | 1 + 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 2b5c73c89c33..c214977b4ab4 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -716,7 +716,7 @@ static unsigned long zv_create(struct zs_pool *pool, uint32_t pool_id, goto out; atomic_inc(&zv_curr_dist_counts[chunks]); atomic_inc(&zv_cumul_dist_counts[chunks]); - zv = zs_map_object(pool, handle); + zv = zs_map_object(pool, handle, ZS_MM_WO); zv->index = index; zv->oid = *oid; zv->pool_id = pool_id; @@ -735,7 +735,7 @@ static void zv_free(struct zs_pool *pool, unsigned long handle) uint16_t size; int chunks; - zv = zs_map_object(pool, handle); + zv = zs_map_object(pool, handle, ZS_MM_RW); ASSERT_SENTINEL(zv, ZVH); size = zv->size + sizeof(struct zv_hdr); INVERT_SENTINEL(zv, ZVH); @@ -757,7 +757,7 @@ static void zv_decompress(struct page *page, unsigned long handle) int ret; struct zv_hdr *zv; - zv = zs_map_object(zcache_host.zspool, handle); + zv = zs_map_object(zcache_host.zspool, handle, ZS_MM_RO); BUG_ON(zv->size == 0); ASSERT_SENTINEL(zv, ZVH); to_va = kmap_atomic(page); diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 706cb625aae9..653b074035f7 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -220,7 +220,8 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, uncmem = user_mem; clen = PAGE_SIZE; - cmem = zs_map_object(zram->mem_pool, zram->table[index].handle); + cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, + ZS_MM_RO); ret = lzo1x_decompress_safe(cmem, zram->table[index].size, uncmem, &clen); @@ -258,7 +259,7 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) return 0; } - cmem = zs_map_object(zram->mem_pool, handle); + cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); ret = lzo1x_decompress_safe(cmem, zram->table[index].size, mem, &clen); zs_unmap_object(zram->mem_pool, handle); @@ -351,7 +352,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, ret = -ENOMEM; goto out; } - cmem = zs_map_object(zram->mem_pool, handle); + cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); memcpy(cmem, src, clen); diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index abf7c13c89c8..8b0bcb626a7f 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -484,9 +484,6 @@ static void zs_copy_map_object(char *buf, struct page *firstpage, sizes[0] = PAGE_SIZE - off; sizes[1] = size - sizes[0]; - /* disable page faults to match kmap_atomic() return conditions */ - pagefault_disable(); - /* copy object to per-cpu buffer */ addr = kmap_atomic(pages[0]); memcpy(buf, addr + off, sizes[0]); @@ -517,9 +514,6 @@ static void zs_copy_unmap_object(char *buf, struct page *firstpage, addr = kmap_atomic(pages[1]); memcpy(addr, buf + sizes[0], sizes[1]); kunmap_atomic(addr); - - /* enable page faults to match kunmap_atomic() return conditions */ - pagefault_enable(); } static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, @@ -754,7 +748,8 @@ EXPORT_SYMBOL_GPL(zs_free); * * This function returns with preemption and page faults disabled. */ -void *zs_map_object(struct zs_pool *pool, unsigned long handle) +void *zs_map_object(struct zs_pool *pool, unsigned long handle, + enum zs_mapmode mm) { struct page *page; unsigned long obj_idx, off; @@ -778,7 +773,11 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle) return area->vm_addr + off; } - zs_copy_map_object(area->vm_buf, page, off, class->size); + /* disable page faults to match kmap_atomic() return conditions */ + pagefault_disable(); + + if (mm != ZS_MM_WO) + zs_copy_map_object(area->vm_buf, page, off, class->size); area->vm_addr = NULL; return area->vm_buf; } @@ -795,13 +794,16 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) struct mapping_area *area; area = &__get_cpu_var(zs_map_area); + /* single-page object fastpath */ if (area->vm_addr) { - /* single-page object fastpath */ kunmap_atomic(area->vm_addr); - put_cpu_var(zs_map_area); - return; + goto out; } + /* no write fastpath */ + if (area->vm_mm == ZS_MM_RO) + goto pfenable; + BUG_ON(!handle); obj_handle_to_location(handle, &page, &obj_idx); @@ -810,6 +812,11 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) off = obj_idx_to_offset(page, obj_idx, class->size); zs_copy_unmap_object(area->vm_buf, page, off, class->size); + +pfenable: + /* enable page faults to match kunmap_atomic() return conditions */ + pagefault_enable(); +out: put_cpu_var(zs_map_area); } EXPORT_SYMBOL_GPL(zs_unmap_object); diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/drivers/staging/zsmalloc/zsmalloc.h index 485cbb1a5ac8..de2e8bfbcc06 100644 --- a/drivers/staging/zsmalloc/zsmalloc.h +++ b/drivers/staging/zsmalloc/zsmalloc.h @@ -15,6 +15,17 @@ #include +/* + * zsmalloc mapping modes + * + * NOTE: These only make a difference when a mapped object spans pages +*/ +enum zs_mapmode { + ZS_MM_RW, /* normal read-write mapping */ + ZS_MM_RO, /* read-only (no copy-out at unmap time) */ + ZS_MM_WO /* write-only (no copy-in at map time) */ +}; + struct zs_pool; struct zs_pool *zs_create_pool(const char *name, gfp_t flags); @@ -23,7 +34,8 @@ void zs_destroy_pool(struct zs_pool *pool); unsigned long zs_malloc(struct zs_pool *pool, size_t size); void zs_free(struct zs_pool *pool, unsigned long obj); -void *zs_map_object(struct zs_pool *pool, unsigned long handle); +void *zs_map_object(struct zs_pool *pool, unsigned long handle, + enum zs_mapmode mm); void zs_unmap_object(struct zs_pool *pool, unsigned long handle); u64 zs_get_total_size_bytes(struct zs_pool *pool); diff --git a/drivers/staging/zsmalloc/zsmalloc_int.h b/drivers/staging/zsmalloc/zsmalloc_int.h index f760dae54f28..528051767733 100644 --- a/drivers/staging/zsmalloc/zsmalloc_int.h +++ b/drivers/staging/zsmalloc/zsmalloc_int.h @@ -112,6 +112,7 @@ static const int fullness_threshold_frac = 4; struct mapping_area { char *vm_buf; /* copy buffer for objects that span pages */ char *vm_addr; /* address of kmap_atomic()'ed pages */ + enum zs_mapmode vm_mm; /* mapping mode */ }; struct size_class { -- GitLab From c9c56fd0b766f6f3cd19c83945954ff5b06afc5f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 19:09:01 +0100 Subject: [PATCH 2371/5711] ASoC: arizona: Add IN4 to the mixer tables Some devices have four input structures rather than three. Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 4 ++++ sound/soc/codecs/arizona.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 0be04b526588..f3680c374347 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -79,6 +79,8 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { "IN2R", "IN3L", "IN3R", + "IN4L", + "IN4R", "AIF1RX1", "AIF1RX2", "AIF1RX3", @@ -138,6 +140,8 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { 0x13, 0x14, 0x15, + 0x16, + 0x17, 0x20, /* AIF1RX1 */ 0x21, 0x22, diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 896711e19baa..b894b64e8f5c 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -59,7 +59,7 @@ struct arizona_priv { struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; }; -#define ARIZONA_NUM_MIXER_INPUTS 55 +#define ARIZONA_NUM_MIXER_INPUTS 57 extern const unsigned int arizona_mixer_tlv[]; extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; -- GitLab From bc9dce5853ced3b7a5bc79f1101a4c4b0a752f3e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 19:08:23 +0100 Subject: [PATCH 2372/5711] ASoC: wm5102: Fix cut'n'paste for digital volume registers The analogue PGA shifts were used; this makes no practical difference as the values are the same. Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 3827fa2af70a..7a6a11a323ff 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -68,13 +68,13 @@ SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, - ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_PGA_VOL_SHIFT, + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, - ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_PGA_VOL_SHIFT, + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, - ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_PGA_VOL_SHIFT, + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), -- GitLab From 774441915de8402103ffe5bf68656f160fefc86f Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Mon, 9 Jul 2012 09:48:44 +0200 Subject: [PATCH 2373/5711] ASoC: tlv320aic3x: add deemphasis switch This patch adds missing deemphasis switch. Signed-off-by: Jiri Prchal Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 174de6650563..7933b8c720af 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -356,6 +356,9 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { */ SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), + /* De-emphasis */ + SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), + /* Input */ SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 119, 0, adc_tlv), -- GitLab From 4063d060431b11da3ac2e255e0d8b3c62a0b5f9f Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 9 Jul 2012 00:58:36 +0200 Subject: [PATCH 2374/5711] staging: vt6656: iwctl: fix up spacing around operators A few cases were missed in my previous cleanup, this takes care of the last cases of missing space (or too much space (as in a newline)) around operators ('=', '==', ',', '<'). Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/iwctl.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index dc240962c59c..f8ea66258257 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -104,7 +104,7 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info, PSMgmtObject pMgmt = &(pDevice->sMgmtObj); struct iw_scan_req *req = (struct iw_scan_req *)extra; BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; - PWLAN_IE_SSID pItemSSID=NULL; + PWLAN_IE_SSID pItemSSID = NULL; if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) return -EINVAL; @@ -203,7 +203,7 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN); - current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); // ADD ssid memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWESSID; @@ -244,7 +244,7 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, iwe.u.qual.level = ldBm; iwe.u.qual.noise = 0; - if (-ldBm<50) + if (-ldBm < 50) iwe.u.qual.qual = 100; else if (-ldBm > 90) iwe.u.qual.qual = 0; @@ -1099,9 +1099,9 @@ int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info, // Send the key to the card if (wrq->length > 0) { - if (wrq->length == WLAN_WEP232_KEYLEN) { + if (wrq->length == WLAN_WEP232_KEYLEN) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n"); - } else if (wrq->length == WLAN_WEP104_KEYLEN) { + } else if (wrq->length == WLAN_WEP104_KEYLEN) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n"); } else if (wrq->length == WLAN_WEP40_KEYLEN) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex); @@ -1624,8 +1624,7 @@ int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info, case IW_MLME_DISASSOC: if (pDevice->bLinkPass == TRUE) { PRINT_K("iwctl_siwmlme--->send DISASSOCIATE\n"); - bScheduleCommand((void *)pDevice, - WLAN_CMD_DISASSOCIATE, + bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL); } break; -- GitLab From 0c5c79010950afee602436f85864d0ad3f195029 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 9 Jul 2012 00:58:52 +0200 Subject: [PATCH 2375/5711] staging: vt6656: iwctl: Fix up a few remaining brace issues My previous cleanup patches missed a few cases of redundant/missing/replaced curly braces. This should fix up the last ones. Signed-off-by: Jesper Juhl Acked-by : Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/iwctl.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index f8ea66258257..13ad62cb28e8 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -140,9 +140,9 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info, if (pItemSSID->abySSID[req->essid_len - 1] == '\0') { if (req->essid_len > 0) pItemSSID->len = req->essid_len - 1; - } - else + } else { pItemSSID->len = req->essid_len; + } pMgmt->eScanType = WMAC_SCAN_PASSIVE; PRINT_K("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n", ((PWLAN_IE_SSID)abyScanSSID)->abySSID, ((PWLAN_IE_SSID)abyScanSSID)->len); @@ -577,9 +577,9 @@ int iwctl_siwap(struct net_device *dev, struct iw_request_info *info, PRINT_K(" SIOCSIWAP \n"); - if (wrq->sa_family != ARPHRD_ETHER) + if (wrq->sa_family != ARPHRD_ETHER) { rc = -EINVAL; - else { + } else { memcpy(pMgmt->abyDesireBSSID, wrq->sa_data, 6); // mike: add if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) || @@ -882,8 +882,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, pDevice->uConnectionRate = brate; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate); } - } - else { + } else { pDevice->bFixRate = FALSE; pDevice->uConnectionRate = 13; } @@ -1205,7 +1204,7 @@ int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info, wrq->length = 0; if ((index == 0) && (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled || - pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)){ // get wpa pairwise key + pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)) { // get wpa pairwise key if (KeybGetKey(&(pDevice->sKey), pMgmt->abyCurrBSSID, 0xffffffff, &pKey)) { wrq->length = pKey->uKeyLength; memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); @@ -1360,11 +1359,10 @@ int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info, if (wpa_version == IW_AUTH_WPA_VERSION_DISABLED) break; if (pairwise == IW_AUTH_CIPHER_NONE) { - if (wrq->value == IW_AUTH_CIPHER_CCMP) { + if (wrq->value == IW_AUTH_CIPHER_CCMP) pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; - }else { + else pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; - } } break; case IW_AUTH_KEY_MGMT: @@ -1446,7 +1444,7 @@ int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info, goto out; } pMgmt->wWPAIELen = wrq->length; - }else { + } else { memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); pMgmt->wWPAIELen = 0; } @@ -1470,8 +1468,9 @@ int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info, if (copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)) { ret = -EFAULT; } - } else + } else { ret = -E2BIG; + } } return ret; } -- GitLab From 9a671f886f156e67d984057074c6241621961a21 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 9 Jul 2012 00:59:30 +0200 Subject: [PATCH 2376/5711] staging: vt6656: iwctl: remove a few remaining redundant newlines I missed a few redundant newlines the first time. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/iwctl.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 13ad62cb28e8..8b9894b1146a 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -964,7 +964,6 @@ int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info, wrq->value = pDevice->wRTSThreshold; wrq->disabled = (wrq->value >= 2312); wrq->fixed = 1; - return 0; } @@ -1003,7 +1002,6 @@ int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info, wrq->value = pDevice->wFragmentationThreshold; wrq->disabled = (wrq->value >= 2312); wrq->fixed = 1; - return 0; } @@ -1097,7 +1095,6 @@ int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info, // Send the key to the card if (wrq->length > 0) { - if (wrq->length == WLAN_WEP232_KEYLEN) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n"); } else if (wrq->length == WLAN_WEP104_KEYLEN) { @@ -1119,8 +1116,7 @@ int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info, dwKeyIndex | (1 << 31), wrq->length, NULL, pDevice->abyKey, - KEY_CTL_WEP - ); + KEY_CTL_WEP); spin_unlock_irq(&pDevice->lock); } pDevice->byKeyIndex = (BYTE)dwKeyIndex; -- GitLab From 0d3de9b01419ff1f2c776b2683586c2f269d3607 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 11:32:15 +0530 Subject: [PATCH 2377/5711] staging/rts_pstor: fix the no brace needed warning for if else statements having single block no braces are needed fixed the following checkpatch warning drivers/staging/rts_pstor/sd.c:140: WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/sd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c index b9474a8aefc0..ff9bf0fa17d1 100644 --- a/drivers/staging/rts_pstor/sd.c +++ b/drivers/staging/rts_pstor/sd.c @@ -137,11 +137,10 @@ static int sd_check_data0_status(struct rtsx_chip *chip) { u8 stat; - if (CHECK_PID(chip, 0x5209)) { + if (CHECK_PID(chip, 0x5209)) RTSX_READ_REG(chip, REG_SD_BUS_STAT, &stat); - } else { + else RTSX_READ_REG(chip, REG_SD_STAT1, &stat); - } if (!(stat & SD_DAT0_STATUS)) { sd_set_err_code(chip, SD_BUSY); -- GitLab From 9e76b9dfa383894d4807947bed282f024b519565 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 11:33:04 +0530 Subject: [PATCH 2378/5711] staging/rts_pstor: fix single statements block warning The following warning is fixed up. drivers/staging/rts_pstor/sd.c:190: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/sd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c index ff9bf0fa17d1..3cc9a489e4e8 100644 --- a/drivers/staging/rts_pstor/sd.c +++ b/drivers/staging/rts_pstor/sd.c @@ -187,9 +187,9 @@ RTY_SEND_CMD: 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; reg_addr++) { + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - } + stat_idx = 16; } else if (rsp_type != SD_RSP_TYPE_R0) { for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) { -- GitLab From 64cab4e27648d358842fbf16e0f0c6572458eb20 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:12 +0530 Subject: [PATCH 2379/5711] staging/ft1000: fix the no brace needed warning in ft1000_interrupt as the if statement encloses only one line braces around it are not needed. The following warn fixed, WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index c4a8a0a26eb5..0bd080c4f1f7 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -1998,9 +1998,8 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id) // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type while (inttype) { - if (inttype & ISR_DOORBELL_PEND) { - ft1000_parse_dpram_msg(dev); - } + if (inttype & ISR_DOORBELL_PEND) + ft1000_parse_dpram_msg(dev); if (inttype & ISR_RCV) { DEBUG(1, "Data in FIFO\n"); -- GitLab From 3a0ccb0db9a113a1ab6a8d60213ea86e9a53ec57 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:14 +0530 Subject: [PATCH 2380/5711] staging/ft1000: fix sparse warning sparse warns about having 0 assigned to a pointer, fix it up by using NULL. The following sparse warning is fixed drivers/staging/ft1000/ft1000-usb/ft1000_debug.c:170:52: warning: Using plain integer as NULL pointer Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c index 19db23fe73ca..6d911fda47fb 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c @@ -167,7 +167,7 @@ int ft1000_create_dev(struct ft1000_device *dev) goto fail; } - dir = debugfs_create_dir(info->DeviceName, 0); + dir = debugfs_create_dir(info->DeviceName, NULL); if (IS_ERR(dir)) { result = PTR_ERR(dir); goto debug_dir_fail; -- GitLab From 3bc2311e32daef1b62f45bc5d1da936f4cb31111 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:15 +0530 Subject: [PATCH 2381/5711] staging/ft1000: fix sparse warning about the kernel thread handler function sparse throws warning about the ft1000_poll_thread as drivers/staging/ft1000/ft1000-usb/ft1000_usb.c:40:5: warning: symbol 'ft1000_poll_thread' was not declared. Should it be static? Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index bfead67436fe..e434d33454a8 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -37,7 +37,7 @@ static struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); static bool gPollingfailed = FALSE; -int ft1000_poll_thread(void *arg) +static int ft1000_poll_thread(void *arg) { int ret = STATUS_SUCCESS; -- GitLab From b3a87c3767b476a2115a8d9c7aa5496c153d1dc5 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:16 +0530 Subject: [PATCH 2382/5711] staging/ft1000: fix the no brace needed warning in ft1000_read_fifo_len as the if else statements enclose only one line, so braces around them are not needed. The following warning is fixed drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c:100: WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 0bd080c4f1f7..4a8d6426641e 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -97,11 +97,10 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16); - } else { + else return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16); - } } //--------------------------------------------------------------------------- -- GitLab From cfe116c2c03d2c09b86edb5b5870bd169caec5cd Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:17 +0530 Subject: [PATCH 2383/5711] staging/ft1000: fix the foo * bar warning Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 4a8d6426641e..0059cac10c36 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -115,7 +115,7 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev) // value - value of dpram // //--------------------------------------------------------------------------- -u16 ft1000_read_dpram(struct net_device * dev, int offset) +u16 ft1000_read_dpram(struct net_device *dev, int offset) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; -- GitLab From 95f2825d3b1b562f4a95ffe64f80f331eeeded6e Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:18 +0530 Subject: [PATCH 2384/5711] staging/ft1000-pcmcia: fix checkpatch warnings The below checkpatch warns fixed, drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c:38: ERROR: that open brace { should be on the previous line drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c:45: ERROR: that open brace { should be on the previous line drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c:57: ERROR: that open brace { should be on the previous line Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c index 71aaad31270b..72727c6b9e2e 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c @@ -34,16 +34,14 @@ #define PUTX_TO_PAGE(len, page, message, size, var) \ len += snprintf(page+len, PAGE_SIZE - len, message); \ - for(i = 0; i < (size - 1); i++) \ - { \ + for(i = 0; i < (size - 1); i++) { \ len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \ } \ len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i]) #define PUTD_TO_PAGE(len, page, message, size, var) \ len += snprintf(page+len, PAGE_SIZE - len, message); \ - for(i = 0; i < (size - 1); i++) \ - { \ + for(i = 0; i < (size - 1); i++) { \ len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \ } \ len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i]) @@ -55,8 +53,8 @@ static int ft1000ReadProc(char *page, char **start, off_t off, int len; int i; struct ft1000_info *info; - char *status[] = - { "Idle (Disconnect)", "Searching", "Active (Connected)", + char *status[] = { + "Idle (Disconnect)", "Searching", "Active (Connected)", "Waiting for L2", "Sleep", "No Coverage", "", "" }; char *signal[] = { "", "*", "**", "***", "****" }; -- GitLab From b7c5a774b0f516fed3a38367eb2aeb5ad4d6e234 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 7 Jul 2012 17:35:19 +0530 Subject: [PATCH 2385/5711] staging/ft1000: remove unnecessary assignment of ret with STATUS_SUCCESS as ret is assigned to the return of ft1000_poll, we dont need to initialise ret with STATUS_SUCCESS. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index e434d33454a8..7bd7fb2f3b15 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -39,7 +39,7 @@ MODULE_DEVICE_TABLE(usb, id_table); static bool gPollingfailed = FALSE; static int ft1000_poll_thread(void *arg) { - int ret = STATUS_SUCCESS; + int ret; while (!kthread_should_stop()) { msleep(10); -- GitLab From 485b34c2dfb933592f211aa416ad4c1d2bed895a Mon Sep 17 00:00:00 2001 From: Cruz Julian Bishop Date: Sun, 8 Jul 2012 17:00:56 +1000 Subject: [PATCH 2386/5711] staging: Fixes some checkpatch warnings in asus_oled/asus_oled.c This fixes the following warnings: 1: Changes a printk(KERN_ERR) call to a pr_err call in line 785 2: Changes a printk(KERN_ERR) call to a pr_err call in line 791 3: Changes a printk(KERN_ERR) call to a pr_err call in line 798 4: Reduces line length below 80 at line 785 (Not intended) 5: Reduces line length below 80 at line 798 (Not intended) Signed-off-by: Cruz Julian Bishop Signed-off-by: Greg Kroah-Hartman --- drivers/staging/asus_oled/asus_oled.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index 510d79639217..f63c1d3aeb64 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -782,20 +782,20 @@ static int __init asus_oled_init(void) oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME); if (IS_ERR(oled_class)) { - printk(KERN_ERR "Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n"); + pr_err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n"); return PTR_ERR(oled_class); } retval = class_create_file(oled_class, &class_attr_version.attr); if (retval) { - printk(KERN_ERR "Error creating class version file\n"); + pr_err("Error creating class version file\n"); goto error; } retval = usb_register(&oled_driver); if (retval) { - printk(KERN_ERR "usb_register failed. Error number %d\n", retval); + pr_err("usb_register failed. Error number %d\n", retval); goto error; } -- GitLab From 5dde383e2ef5e22fe7db689dc38c1aabfb801449 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 9 Jul 2012 13:38:41 -0600 Subject: [PATCH 2387/5711] PCI: allow P2P bridge windows starting at PCI bus address zero cd81e1ea1a4c added checks that prevent us from using P2P bridge windows that start at PCI bus address zero. The reason was to "prevent us from overwriting resources that are unassigned." But generic code should allow address zero in both BARs and bridge windows, so I think that commit was a mistake. Windows at bus address zero are legal and likely to exist on machines with an offset between bus addresses and CPU addresses. For example, in the following hypothetical scenario, the bridge at 00:01.0 has a window at bus address zero and the device at 01:00.0 has a BAR at bus address zero, and I think both are perfectly valid: PCI host bridge to bus 0000:00 pci_bus 0000:00: root bus resource [mem 0x100000000-0x1ffffffff] (bus address [0x00000000-0xffffffff]) pci 0000:00:01.0: PCI bridge to [bus 01] pci 0000:00:01.0: bridge window [mem 0x100000000-0x100ffffff] pci 0000:01:00.0: reg 10: [mem 0x100000000-0x100ffffff] Acked-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 658ac977cb56..9c5d2a992999 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -287,7 +287,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) limit |= (io_limit_hi << 16); } - if (base && base <= limit) { + if (base <= limit) { res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; res2.flags = res->flags; region.start = base; @@ -314,7 +314,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; - if (base && base <= limit) { + if (base <= limit) { res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; region.start = base; region.end = limit + 0xfffff; @@ -360,7 +360,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) #endif } } - if (base && base <= limit) { + if (base <= limit) { res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; if (res->flags & PCI_PREF_RANGE_TYPE_64) -- GitLab From 728a9ca3cb390bc7d4aca53328fe272140025864 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 22:55:46 -0300 Subject: [PATCH 2388/5711] staging: vt6656: desc.h: Remove commented macros and useless comments The commented macros are reported by forgotten-macros tool(https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/desc.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index 767112b3c4a9..b68b2ec96eaa 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -36,8 +36,6 @@ #include "ttype.h" #include "tether.h" -/*--------------------- Export Definitions -------------------------*/ - // max transmit or receive buffer size #define CB_MAX_BUF_SIZE 2900U // max buffer size // NOTE: must be multiple of 4 @@ -120,17 +118,11 @@ #define FRAGCTL_TKIP 0x0200 // 0000 0010 0000 0000 #define FRAGCTL_LEGACY 0x0100 // 0000 0001 0000 0000 #define FRAGCTL_NONENCRYPT 0x0000 // 0000 0000 0000 0000 -//#define FRAGCTL_AC3 0x000C // 0000 0000 0000 1100 -//#define FRAGCTL_AC2 0x0008 // 0000 0000 0000 1000 -//#define FRAGCTL_AC1 0x0004 // 0000 0000 0000 0100 -//#define FRAGCTL_AC0 0x0000 // 0000 0000 0000 0000 #define FRAGCTL_ENDFRAG 0x0003 // 0000 0000 0000 0011 #define FRAGCTL_MIDFRAG 0x0002 // 0000 0000 0000 0010 #define FRAGCTL_STAFRAG 0x0001 // 0000 0000 0000 0001 #define FRAGCTL_NONFRAG 0x0000 // 0000 0000 0000 0000 -//#define TYPE_AC0DMA 0 -//#define TYPE_TXDMA0 1 #define TYPE_TXDMA0 0 #define TYPE_AC0DMA 1 #define TYPE_ATIMDMA 2 @@ -147,9 +139,6 @@ #define TD_FLAGS_NETIF_SKB 0x01 // check if need release skb #define TD_FLAGS_PRIV_SKB 0x02 // check if called from private skb(hostap) #define TD_FLAGS_PS_RETRY 0x04 // check if PS STA frame re-transmit -//#define TD_FLAGS_NETIF_SKB 0x04 - -/*--------------------- Export Types ------------------------------*/ // // RsvTime buffer header @@ -268,7 +257,6 @@ SRTS_a_FB, *PSRTS_a_FB; typedef const SRTS_a_FB *PCSRTS_a_FB; - // // CTS buffer header // @@ -421,12 +409,5 @@ typedef struct tagSKeyEntry { DWORD dwKey4[4]; } __attribute__ ((__packed__)) SKeyEntry; -/*--------------------- Export Macros ------------------------------*/ - -/*--------------------- Export Classes ----------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ #endif /* __DESC_H__ */ -- GitLab From 7f289dae41f45d163b8d82edb549083caf023e6a Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 22:55:47 -0300 Subject: [PATCH 2389/5711] staging: vt6656: hostap.c: Remove unused macros and some useless comments The unused macros were reporteds by forgotten-macros tool(https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/hostap.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c index 51b5adf36577..f5780950b471 100644 --- a/drivers/staging/vt6656/hostap.c +++ b/drivers/staging/vt6656/hostap.c @@ -41,31 +41,11 @@ #define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 #define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0 -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT1 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 #define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 #define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -/*--------------------- Static Definitions -------------------------*/ - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Variables --------------------------*/ -//static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; -/*--------------------- Static Functions --------------------------*/ - - - - -/*--------------------- Export Variables --------------------------*/ - - /* * Description: * register net_device (AP) for hostap deamon -- GitLab From a6fadf5c53c0d31e23e1800fd2d2cd14e2fff744 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 22:55:48 -0300 Subject: [PATCH 2390/5711] staging: vt6656: hostap.c: Remove commented code Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/hostap.c | 43 --------------------------------- 1 file changed, 43 deletions(-) diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c index f5780950b471..682002a5b8d7 100644 --- a/drivers/staging/vt6656/hostap.c +++ b/drivers/staging/vt6656/hostap.c @@ -294,37 +294,6 @@ static int hostap_get_info_sta(PSDevice pDevice, return 0; } -/* - * Description: - * reset txexec - * - * Parameters: - * In: - * pDevice - - * param - - * Out: - * TURE, FALSE - * - * Return Value: - * - */ -/* -static int hostap_reset_txexc_sta(PSDevice pDevice, - struct viawget_hostapd_param *param) -{ - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - unsigned int uNodeIndex; - - if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) { - pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0; - } - else { - return -ENOENT; - } - - return 0; -} -*/ /* * Description: @@ -459,12 +428,6 @@ static int hostap_set_encryption(PSDevice pDevice, param->u.crypt.err = 0; -/* - if (param_len != - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len) - return -EINVAL; -*/ if (param->u.crypt.alg > WPA_ALG_CCMP) return -EINVAL; @@ -794,12 +757,6 @@ int vt6656_hostap_ioctl(PSDevice pDevice, struct iw_point *p) ret = hostap_get_info_sta(pDevice, param); ap_ioctl = 1; break; -/* - case VIAWGET_HOSTAPD_RESET_TXEXC_STA: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n"); - ret = hostap_reset_txexc_sta(pDevice, param); - break; -*/ case VIAWGET_HOSTAPD_SET_FLAGS_STA: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n"); ret = hostap_set_flags_sta(pDevice, param); -- GitLab From 1acc0d62d0e9607a35f1e7a7500c22bb49d8fab3 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 22:55:49 -0300 Subject: [PATCH 2391/5711] staging: vt6656: Remove all commented macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/80211hdr.h | 2 -- drivers/staging/vt6656/bssdb.h | 2 -- drivers/staging/vt6656/card.h | 1 - drivers/staging/vt6656/device.h | 4 ---- drivers/staging/vt6656/main_usb.c | 5 ----- drivers/staging/vt6656/mib.h | 1 - drivers/staging/vt6656/tether.h | 2 -- drivers/staging/vt6656/usbpipe.c | 3 --- 8 files changed, 20 deletions(-) diff --git a/drivers/staging/vt6656/80211hdr.h b/drivers/staging/vt6656/80211hdr.h index 15c6ef1a635c..b87d5434077a 100644 --- a/drivers/staging/vt6656/80211hdr.h +++ b/drivers/staging/vt6656/80211hdr.h @@ -78,7 +78,6 @@ #define WLAN_HDR_ADDR4_LEN 30 #define WLAN_IEHDR_LEN 2 #define WLAN_SSID_MAXLEN 32 -/* #define WLAN_RATES_MAXLEN 255 */ #define WLAN_RATES_MAXLEN 16 #define WLAN_RATES_MAXLEN_11B 4 #define WLAN_RSN_MAXLEN 32 @@ -104,7 +103,6 @@ #define WLAN_WEP40_KEYLEN 5 #define WLAN_WEP104_KEYLEN 13 #define WLAN_WEP232_KEYLEN 29 -/* #define WLAN_WEPMAX_KEYLEN 29 */ #define WLAN_WEPMAX_KEYLEN 32 #define WLAN_CHALLENGE_IE_MAXLEN 255 #define WLAN_CHALLENGE_IE_LEN 130 diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index a8f97ebb659b..6b2ec390e775 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -64,8 +64,6 @@ // send and receive non-IEEE 802.1X frames #define WLAN_STA_AUTHORIZED BIT5 -//#define MAX_RATE 12 - #define MAX_WPA_IE_LEN 64 diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h index 9cf71a3d8801..55962b198831 100644 --- a/drivers/staging/vt6656/card.h +++ b/drivers/staging/vt6656/card.h @@ -52,7 +52,6 @@ typedef enum _CARD_OP_MODE { } CARD_OP_MODE, *PCARD_OP_MODE; #define CB_MAX_CHANNEL_24G 14 -/* #define CB_MAX_CHANNEL_5G 24 */ #define CB_MAX_CHANNEL_5G 42 /* add channel9(5045MHz), 41==>42 */ #define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index f1496ec5dc72..171dd68cf5b2 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -106,10 +106,6 @@ #define MAX_MULTICAST_ADDRESS_NUM 32 #define MULTICAST_ADDRESS_LIST_SIZE (MAX_MULTICAST_ADDRESS_NUM * ETH_ALEN) -//#define OP_MODE_INFRASTRUCTURE 0 -//#define OP_MODE_ADHOC 1 -//#define OP_MODE_AP 2 - #define DUPLICATE_RX_CACHE_LENGTH 5 #define NUM_KEY_ENTRY 11 diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 5048341518c3..b06fd5b723fa 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -205,11 +205,6 @@ static const long frequency_list[] = { }; -#ifndef IW_ENCODE_NOKEY -#define IW_ENCODE_NOKEY 0x0800 -#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) -#endif - static const struct iw_handler_def iwctl_handler_def; */ diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h index a89cca0c5ecf..82d69a9cc209 100644 --- a/drivers/staging/vt6656/mib.h +++ b/drivers/staging/vt6656/mib.h @@ -113,7 +113,6 @@ typedef struct tagSMib2Counter { } SMib2Counter, *PSMib2Counter; // Value in the ifType entry -//#define ETHERNETCSMACD 6 // #define WIRELESSLANIEEE80211b 6 // // Value in the ifAdminStatus/ifOperStatus entry diff --git a/drivers/staging/vt6656/tether.h b/drivers/staging/vt6656/tether.h index 4ec05237469b..8c1f5d253f88 100644 --- a/drivers/staging/vt6656/tether.h +++ b/drivers/staging/vt6656/tether.h @@ -72,7 +72,6 @@ #define TYPE_CTL_ACK 0xd400 -//#define WEP_IV_MASK 0xFFFFFF00 #else //if LITTLE_ENDIAN // @@ -111,7 +110,6 @@ #define TYPE_CTL_ACK 0x00d4 -//#define WEP_IV_MASK 0x00FFFFFF #endif //#ifdef __BIG_ENDIAN diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index c612ab58f389..609e8fa10b98 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -52,9 +52,6 @@ //endpoint 2: read bulk //endpoint 3: write bulk -//RequestType: -//#define REQUEST_OUT (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) // 0x40 -//#define REQUEST_IN (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE ) //0xc0 //static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; -- GitLab From 5328b9ccfc4db5c03aeb05bf0d205625d67dd911 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 22:55:50 -0300 Subject: [PATCH 2392/5711] staging: vt6656: Remove unsed macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/card.c | 1 - drivers/staging/vt6656/channel.c | 2 -- drivers/staging/vt6656/rxtx.c | 2 -- 3 files changed, 5 deletions(-) diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 9d09e9fd8e18..e3ddc0b55317 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -66,7 +66,6 @@ static int msglevel =MSG_LEVEL_INFO; /*--------------------- Static Definitions -------------------------*/ -#define CB_TXPOWER_LEVEL 6 /*--------------------- Static Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index 99e054d2d601..650217607858 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -368,8 +368,6 @@ static struct /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 */ }; -#define NUM_RULES ARRAY_SIZE(ChannelRuleTab) - /*--------------------- Export function -------------------------*/ /************************************************************************ * Country Channel Valid diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9b64b102f55c..bb464527fc1b 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -73,8 +73,6 @@ static int msglevel = MSG_LEVEL_INFO; /*--------------------- Static Functions --------------------------*/ /*--------------------- Static Definitions -------------------------*/ -#define CRITICAL_PACKET_LEN 256 // if packet size < 256 -> in-direct send - // packet size >= 256 -> direct send const WORD wTimeStampOff[2][MAX_RATE] = { {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble -- GitLab From 2478ef577c1d6b39863a51d2622e74f912d9b3f8 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:21 -0300 Subject: [PATCH 2393/5711] staging: vt6655: Remove all "if 0" blocks from driver This commit removes code that will never be executed by vt6655 driver. Was the forgotten-macros tool(https://github.com/marcosps/forgotten_macros) who reported these blocks for us. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 33 ---------------------- drivers/staging/vt6655/iwctl.c | 36 ------------------------ drivers/staging/vt6655/rf.c | 42 ---------------------------- drivers/staging/vt6655/wcmd.c | 24 ---------------- 4 files changed, 135 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 3e8283c2dc73..d0fefb1eae94 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1086,15 +1086,6 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) device_free_info(pDevice); return -ENODEV; } -//2008-07-21-01by MikeLiu -//register wpadev -#if 0 - if(wpa_set_wpadev(pDevice, 1)!=0) { - printk("Fail to Register WPADEV?\n"); - unregister_netdev(pDevice->dev); - free_netdev(dev); - } -#endif device_print_info(pDevice); pci_set_drvdata(pcid, pDevice); return 0; @@ -1948,15 +1939,6 @@ device_init_rd0_ring(pDevice); -#if 0 - pDevice->MLMEThr_pid = kernel_thread(MlmeThread, pDevice, CLONE_VM); - if (pDevice->MLMEThr_pid <0 ) - { - printk("unable start thread MlmeThread\n"); - return -1; - } -#endif - //printk("thread id is %d\n",pDevice->MLMEThr_pid); //printk("Create thread time is %x\n",jiffies); //wait_for_completion(&pDevice->notify); @@ -2493,21 +2475,6 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { &(pDevice->byTopCCKBasicRate), &(pDevice->byTopOFDMBasicRate)); -#if 0 -printk("auto rate:Rate : %d,AckRate:%d,TopCCKRate:%d,TopOFDMRate:%d\n", -pDevice->wCurrentRate,pDevice->byACKRate, -pDevice->byTopCCKBasicRate,pDevice->byTopOFDMBasicRate); - -#endif - -#if 0 - - pDevice->wCurrentRate = 11; - pDevice->byACKRate = 8; - pDevice->byTopCCKBasicRate = 3; - pDevice->byTopOFDMBasicRate = 8; -#endif - } } diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index 87288db21785..77aad7f5ae76 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -84,24 +84,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.status = pDevice->eOPMode; #ifdef Calcu_LinkQual - #if 0 - if(pDevice->byBBType == BB_TYPE_11B) { - if(pDevice->byCurrSQ > 120) - pDevice->scStatistic.LinkQuality = 100; - else - pDevice->scStatistic.LinkQuality = pDevice->byCurrSQ*100/120; - } - else if(pDevice->byBBType == BB_TYPE_11G) { - if(pDevice->byCurrSQ < 20) - pDevice->scStatistic.LinkQuality = 100; - else if(pDevice->byCurrSQ >96) - pDevice->scStatistic.LinkQuality = 0; - else - pDevice->scStatistic.LinkQuality = (96-pDevice->byCurrSQ)*100/76; - } - if(pDevice->bLinkPass !=true) - pDevice->scStatistic.LinkQuality = 0; - #endif if(pDevice->scStatistic.LinkQuality > 100) pDevice->scStatistic.LinkQuality = 100; pDevice->wstats.qual.qual =(unsigned char) pDevice->scStatistic.LinkQuality; @@ -2004,24 +1986,6 @@ param->u.wpa_key.key = (u8 *)key_array; param->u.wpa_key.seq = (u8 *)seq; param->u.wpa_key.seq_len = seq_len; -#if 0 -printk("param->u.wpa_key.alg_name =%d\n",param->u.wpa_key.alg_name); -printk(KERN_DEBUG "param->addr=%pM\n", param->addr); -printk("param->u.wpa_key.set_tx =%d\n",param->u.wpa_key.set_tx); -printk("param->u.wpa_key.key_index =%d\n",param->u.wpa_key.key_index); -printk("param->u.wpa_key.key_len =%d\n",param->u.wpa_key.key_len); -printk("param->u.wpa_key.key ="); -for(ii=0;iiu.wpa_key.key_len;ii++) - printk("%02x:",param->u.wpa_key.key[ii]); - printk("\n"); -printk("param->u.wpa_key.seq_len =%d\n",param->u.wpa_key.seq_len); -printk("param->u.wpa_key.seq ="); -for(ii=0;iiu.wpa_key.seq_len;ii++) - printk("%02x:",param->u.wpa_key.seq[ii]); - printk("\n"); - -printk("...........\n"); -#endif //****set if current action is Network Manager count?? //****this method is so foolish,but there is no other way??? if(param->u.wpa_key.alg_name == WPA_ALG_NONE) { diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index b8ec783e55e0..a2db0ffbb94e 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -1067,48 +1067,6 @@ unsigned char byPwrdBm = 0; break; } -#if 0 - - // 802.11h TPC - if (pDevice->bLinkPass == true) { - // do not over local constraint - if (byPwrdBm > pDevice->abyLocalPwr[uCH]) { - pDevice->byCurPwrdBm = pDevice->abyLocalPwr[uCH]; - byDec = byPwrdBm - pDevice->abyLocalPwr[uCH]; - if (pDevice->byRFType == RF_UW2452) { - byDec *= 3; - } else { - byDec <<= 1; - } - if (byPwr > byDec) { - byPwr -= byDec; - } else { - byPwr = 0; - } - } else { - pDevice->byCurPwrdBm = byPwrdBm; - } - } else { - // do not over regulatory constraint - if (byPwrdBm > pDevice->abyRegPwr[uCH]) { - pDevice->byCurPwrdBm = pDevice->abyRegPwr[uCH]; - byDec = byPwrdBm - pDevice->abyRegPwr[uCH]; - if (pDevice->byRFType == RF_UW2452) { - byDec *= 3; - } else { - byDec <<= 1; - } - if (byPwr > byDec) { - byPwr -= byDec; - } else { - byPwr = 0; - } - } else { - pDevice->byCurPwrdBm = byPwrdBm; - } - } -#endif - // if (pDevice->byLocalID <= REV_ID_VT3253_B1) { if (pDevice->byCurPwr == byPwr) { return true; diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index bab3b0116ccc..7b5b99c8cf14 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -684,18 +684,6 @@ printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySS return; } pDevice->byLinkWaitCount = 0; - #if 0 - #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT - // if(pDevice->bWPASuppWextEnabled == true) - { - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof (wrqu)); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - printk("wireless_send_event--->SIOCGIWAP(disassociated:AUTHENTICATE_WAIT_timeout)\n"); - wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); - } - #endif - #endif s_bCommandComplete(pDevice); break; @@ -748,18 +736,6 @@ printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySS return; } pDevice->byLinkWaitCount = 0; - #if 0 - #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT - // if(pDevice->bWPASuppWextEnabled == true) - { - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof (wrqu)); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - printk("wireless_send_event--->SIOCGIWAP(disassociated:ASSOCIATE_WAIT_timeout)\n"); - wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); - } - #endif - #endif s_bCommandComplete(pDevice); break; -- GitLab From 9deff1d7975f79dd4564980e9a563bb86c6a64b4 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:22 -0300 Subject: [PATCH 2394/5711] staging: vt6655: mac.h: Remove all commented macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/mac.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index b96d27ee2540..e3ccfee90268 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -292,19 +292,11 @@ // #define EnCFG_BarkerPream 0x00020000 #define EnCFG_NXTBTTCFPSTR 0x00010000 -//#define EnCFG_TXLMT3UPDATE 0x00008000 -//#define EnCFG_TXLMT2UPDATE 0x00004000 -//#define EnCFG_TXLMT1UPDATE 0x00002000 -//#define EnCFG_TXLMT3EN 0x00001000 -//#define EnCFG_TXLMT2EN 0x00000800 -//#define EnCFG_TXLMT1EN 0x00000400 #define EnCFG_BcnSusClr 0x00000200 #define EnCFG_BcnSusInd 0x00000100 -//#define EnCFG_CWOFF1 0x00000080 #define EnCFG_CFP_ProtectEn 0x00000040 #define EnCFG_ProtectMd 0x00000020 #define EnCFG_HwParCFP 0x00000010 -//#define EnCFG_QOS 0x00000008 #define EnCFG_CFNULRSP 0x00000004 #define EnCFG_BBType_MASK 0x00000003 #define EnCFG_BBType_g 0x00000002 @@ -392,14 +384,6 @@ #define IMR_RADARDETECT 0x10000000 // #define IMR_MEASUREEND 0x08000000 // #define IMR_SOFTTIMER1 0x00200000 // -//#define IMR_SYNCFLUSHOK 0x00100000 // -//#define IMR_ATIMEND 0x00080000 //0000 1000 0000 0000 0000 0000 -//#define IMR_CFPEND 0x00040000 //0000 0100 0000 0000 0000 0000 -//#define IMR_AC3DMA 0x00020000 //0000 0010 0000 0000 0000 0000 -//#define IMR_AC2DMA 0x00010000 //0000 0001 0000 0000 0000 0000 -//#define IMR_AC1DMA 0x00008000 //0000 0000 1000 0000 0000 0000 -//#define IMR_SYNCTX 0x00004000 //0000 0000 0100 0000 0000 0000 -//#define IMR_ATIMTX 0x00002000 //0000 0000 0010 0000 0000 0000 #define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 #define IMR_RXNOBUF 0x00000800 // #define IMR_MIBNEARFULL 0x00000400 // @@ -424,14 +408,6 @@ #define ISR_RADARDETECT 0x10000000 // #define ISR_MEASUREEND 0x08000000 // #define ISR_SOFTTIMER1 0x00200000 // -//#define ISR_SYNCFLUSHOK 0x00100000 //0001 0000 0000 0000 0000 0000 -//#define ISR_ATIMEND 0x00080000 //0000 1000 0000 0000 0000 0000 -//#define ISR_CFPEND 0x00040000 //0000 0100 0000 0000 0000 0000 -//#define ISR_AC3DMA 0x00020000 //0000 0010 0000 0000 0000 0000 -//#define ISR_AC2DMA 0x00010000 //0000 0001 0000 0000 0000 0000 -//#define ISR_AC1DMA 0x00008000 //0000 0000 1000 0000 0000 0000 -//#define ISR_SYNCTX 0x00004000 //0000 0000 0100 0000 0000 0000 -//#define ISR_ATIMTX 0x00002000 //0000 0000 0010 0000 0000 0000 #define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 #define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 #define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 -- GitLab From f4621f2cededa3f7679d9d689bb918111c7b5a9c Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:23 -0300 Subject: [PATCH 2395/5711] staging: vt6655: rf.c: Remove all unused macros These macros were reported by forgotte-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index a2db0ffbb94e..aa696650b86c 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -41,52 +41,16 @@ //static int msglevel =MSG_LEVEL_INFO; -#define BY_RF2959_REG_LEN 23 //24bits -#define CB_RF2959_INIT_SEQ 15 -#define SWITCH_CHANNEL_DELAY_RF2959 200 //us -#define RF2959_PWR_IDX_LEN 32 - -#define BY_MA2825_REG_LEN 23 //24bit -#define CB_MA2825_INIT_SEQ 13 -#define SWITCH_CHANNEL_DELAY_MA2825 200 //us -#define MA2825_PWR_IDX_LEN 31 - #define BY_AL2230_REG_LEN 23 //24bit #define CB_AL2230_INIT_SEQ 15 #define SWITCH_CHANNEL_DELAY_AL2230 200 //us #define AL2230_PWR_IDX_LEN 64 -#define BY_UW2451_REG_LEN 23 -#define CB_UW2451_INIT_SEQ 6 -#define SWITCH_CHANNEL_DELAY_UW2451 200 //us -#define UW2451_PWR_IDX_LEN 25 - -//{{ RobertYu: 20041118 -#define BY_MA2829_REG_LEN 23 //24bit -#define CB_MA2829_INIT_SEQ 13 -#define SWITCH_CHANNEL_DELAY_MA2829 200 //us -#define MA2829_PWR_IDX_LEN 64 -//}} RobertYu - -//{{ RobertYu:20050103 #define BY_AL7230_REG_LEN 23 //24bit #define CB_AL7230_INIT_SEQ 16 #define SWITCH_CHANNEL_DELAY_AL7230 200 //us #define AL7230_PWR_IDX_LEN 64 -//}} RobertYu - -//{{ RobertYu: 20041210 -#define BY_UW2452_REG_LEN 23 -#define CB_UW2452_INIT_SEQ 5 //RoberYu:20050113, Rev0.2 Programming Guide(remove R3, so 6-->5) -#define SWITCH_CHANNEL_DELAY_UW2452 100 //us -#define UW2452_PWR_IDX_LEN 64 -//}} RobertYu - -#define BY_VT3226_REG_LEN 23 -#define CB_VT3226_INIT_SEQ 12 -#define SWITCH_CHANNEL_DELAY_VT3226 200 //us -#define VT3226_PWR_IDX_LEN 16 /*--------------------- Static Classes ----------------------------*/ -- GitLab From 3abe0584122fff0db84d584238972e678e4d7c33 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:24 -0300 Subject: [PATCH 2396/5711] staging: vt6655: baseband.h: Remove all unused macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.h | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 8294bdbb7b51..be2d68909490 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -46,36 +46,6 @@ // Baseband RF pair definition in eeprom (Bits 6..0) // -/* -#define RATE_1M 0 -#define RATE_2M 1 -#define RATE_5M 2 -#define RATE_11M 3 -#define RATE_6M 4 -#define RATE_9M 5 -#define RATE_12M 6 -#define RATE_18M 7 -#define RATE_24M 8 -#define RATE_36M 9 -#define RATE_48M 10 -#define RATE_54M 11 -#define RATE_AUTO 12 -#define MAX_RATE 12 - - -//0:11A 1:11B 2:11G -#define BB_TYPE_11A 0 -#define BB_TYPE_11B 1 -#define BB_TYPE_11G 2 - -//0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate) -#define PK_TYPE_11A 0 -#define PK_TYPE_11B 1 -#define PK_TYPE_11GB 2 -#define PK_TYPE_11GA 3 -*/ - - #define PREAMBLE_LONG 0 #define PREAMBLE_SHORT 1 -- GitLab From 27e3b90153c52f79beede1dd5eb51db326a5d8a9 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:25 -0300 Subject: [PATCH 2397/5711] staging: vt6655: Remove all commented macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/80211hdr.h | 2 -- drivers/staging/vt6655/baseband.c | 2 -- drivers/staging/vt6655/bssdb.c | 1 - drivers/staging/vt6655/desc.h | 11 ----------- drivers/staging/vt6655/device.h | 15 --------------- drivers/staging/vt6655/device_main.c | 4 ---- drivers/staging/vt6655/dpc.c | 1 - drivers/staging/vt6655/mib.h | 2 -- drivers/staging/vt6655/rf.h | 1 - drivers/staging/vt6655/tether.h | 3 --- drivers/staging/vt6655/vntwifi.c | 2 -- 11 files changed, 44 deletions(-) diff --git a/drivers/staging/vt6655/80211hdr.h b/drivers/staging/vt6655/80211hdr.h index f55283b86410..c4d2349260ea 100644 --- a/drivers/staging/vt6655/80211hdr.h +++ b/drivers/staging/vt6655/80211hdr.h @@ -80,7 +80,6 @@ #define WLAN_HDR_ADDR4_LEN 30 #define WLAN_IEHDR_LEN 2 #define WLAN_SSID_MAXLEN 32 -/*#define WLAN_RATES_MAXLEN 255*/ #define WLAN_RATES_MAXLEN 16 #define WLAN_RATES_MAXLEN_11B 4 #define WLAN_RSN_MAXLEN 32 @@ -106,7 +105,6 @@ #define WLAN_WEP40_KEYLEN 5 #define WLAN_WEP104_KEYLEN 13 #define WLAN_WEP232_KEYLEN 29 -/*#define WLAN_WEPMAX_KEYLEN 29*/ #define WLAN_WEPMAX_KEYLEN 32 #define WLAN_CHALLENGE_IE_MAXLEN 255 #define WLAN_CHALLENGE_IE_LEN 130 diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 1e1c6e34f786..e7b93a21e3b2 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -60,8 +60,6 @@ //static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; -//#define PLICE_DEBUG - /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index f4f108f72afd..fcffa4f0f4e3 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -58,7 +58,6 @@ #include "wpa2.h" #include "iowpa.h" -//#define PLICE_DEBUG /*--------------------- Static Definitions -------------------------*/ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 138897a79325..084a1a5566ad 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -152,10 +152,6 @@ #define FRAGCTL_TKIP 0x0002 // 0000 0010 0000 0000 #define FRAGCTL_LEGACY 0x0001 // 0000 0001 0000 0000 #define FRAGCTL_NONENCRYPT 0x0000 // 0000 0000 0000 0000 -//#define FRAGCTL_AC3 0x0C00 // 0000 0000 0000 1100 -//#define FRAGCTL_AC2 0x0800 // 0000 0000 0000 1000 -//#define FRAGCTL_AC1 0x0400 // 0000 0000 0000 0100 -//#define FRAGCTL_AC0 0x0000 // 0000 0000 0000 0000 #define FRAGCTL_ENDFRAG 0x0300 // 0000 0000 0000 0011 #define FRAGCTL_MIDFRAG 0x0200 // 0000 0000 0000 0010 #define FRAGCTL_STAFRAG 0x0100 // 0000 0000 0000 0001 @@ -184,10 +180,6 @@ #define FRAGCTL_TKIP 0x0200 // 0000 0010 0000 0000 #define FRAGCTL_LEGACY 0x0100 // 0000 0001 0000 0000 #define FRAGCTL_NONENCRYPT 0x0000 // 0000 0000 0000 0000 -//#define FRAGCTL_AC3 0x000C // 0000 0000 0000 1100 -//#define FRAGCTL_AC2 0x0008 // 0000 0000 0000 1000 -//#define FRAGCTL_AC1 0x0004 // 0000 0000 0000 0100 -//#define FRAGCTL_AC0 0x0000 // 0000 0000 0000 0000 #define FRAGCTL_ENDFRAG 0x0003 // 0000 0000 0000 0011 #define FRAGCTL_MIDFRAG 0x0002 // 0000 0000 0000 0010 #define FRAGCTL_STAFRAG 0x0001 // 0000 0000 0000 0001 @@ -195,8 +187,6 @@ #endif // #ifdef __BIG_ENDIAN -//#define TYPE_AC0DMA 0 -//#define TYPE_TXDMA0 1 #define TYPE_TXDMA0 0 #define TYPE_AC0DMA 1 #define TYPE_ATIMDMA 2 @@ -215,7 +205,6 @@ #define TD_FLAGS_NETIF_SKB 0x01 // check if need release skb #define TD_FLAGS_PRIV_SKB 0x02 // check if called from private skb(hostap) #define TD_FLAGS_PS_RETRY 0x04 // check if PS STA frame re-transmit -//#define TD_FLAGS_NETIF_SKB 0x04 /*--------------------- Export Types ------------------------------*/ diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 780205c0a88b..c5e6b98d3e4e 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -69,10 +69,6 @@ #ifndef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT #define WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT #endif -//2008-4-14 by chester for led issue -//#define FOR_LED_ON_NOTEBOOK -// - // // device specific @@ -91,12 +87,6 @@ #include "key.h" #include "mac.h" -//PLICE_DEBUG-> -//#define THREAD - -//#define TASK_LET -//PLICE_DEBUG<- - /*--------------------- Export Definitions -------------------------*/ @@ -105,11 +95,6 @@ #define MAX_MULTICAST_ADDRESS_NUM 32 #define MULTICAST_ADDRESS_LIST_SIZE (MAX_MULTICAST_ADDRESS_NUM * ETH_ALEN) - -//#define OP_MODE_INFRASTRUCTURE 0 -//#define OP_MODE_ADHOC 1 -//#define OP_MODE_AP 2 - #define DUPLICATE_RX_CACHE_LENGTH 5 #define NUM_KEY_ENTRY 11 diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index d0fefb1eae94..89d1c22695a0 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -87,12 +87,10 @@ #include #include -//#define DEBUG /*--------------------- Static Definitions -------------------------*/ //static int msglevel =MSG_LEVEL_DEBUG; static int msglevel = MSG_LEVEL_INFO; -//#define PLICE_DEBUG // // Define module options // @@ -100,10 +98,8 @@ MODULE_AUTHOR("VIA Networking Technologies, Inc., "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); -//PLICE_DEBUG -> static int mlme_kill; //static struct task_struct * mlme_task; -//PLICE_DEBUG <- #define DEVICE_PARAM(N,D) /* diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index c0fab4bc8702..e8a71ba4b92c 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -55,7 +55,6 @@ #include "iowpa.h" #include "aes_ccmp.h" -//#define PLICE_DEBUG /*--------------------- Static Definitions -------------------------*/ diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 009f3a4d29f6..5cd697a2bc77 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -98,7 +98,6 @@ typedef struct tagSMib2Counter { } SMib2Counter, *PSMib2Counter; // Value in the ifType entry -//#define ETHERNETCSMACD 6 // #define WIRELESSLANIEEE80211b 6 // // Value in the ifAdminStatus/ifOperStatus entry @@ -210,7 +209,6 @@ typedef struct tagSISRCounters { #define UNDER_CREATION 3 // #define INVALID 4 // -//#define MAX_RATE 12 // // statistic counter // diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index 1f8d82e13041..73f09693ee7a 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -41,7 +41,6 @@ #define RF_MAXIMAG 0x02 #define RF_AIROHA 0x03 -//#define RF_GCT5103 0x04 #define RF_UW2451 0x05 #define RF_MAXIMG 0x06 #define RF_MAXIM2829 0x07 // RobertYu: 20041118 diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 787d885deee9..6a68f97d9a32 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -90,8 +90,6 @@ #define TYPE_CTL_ACK 0xd400 -//#define WEP_IV_MASK 0xFFFFFF00 - #else //if LITTLE_ENDIAN // // wType field in the SEthernetHeader @@ -143,7 +141,6 @@ #define TYPE_CTL_ACK 0x00d4 -//#define WEP_IV_MASK 0x00FFFFFF #endif //#ifdef __BIG_ENDIAN diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index 0491d0b52c85..d645ecd89417 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -38,8 +38,6 @@ #include "wmgr.h" #include "datarate.h" -//#define PLICE_DEBUG - /*--------------------- Static Definitions -------------------------*/ //static int msglevel =MSG_LEVEL_DEBUG; //static int msglevel =MSG_LEVEL_INFO; -- GitLab From 4b733a1b0f7b83caef204b1d3cbee2c85b00a055 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Sun, 8 Jul 2012 23:51:26 -0300 Subject: [PATCH 2398/5711] staging: vt6655: hostap.c: Remove all unused macros All these macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/hostap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index 773502702203..6ac6f452b261 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -40,14 +40,8 @@ #define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 #define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0 -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT1 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 #define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 #define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - /*--------------------- Static Definitions -------------------------*/ -- GitLab From 83414d528d2f97d6574c14afb892879c11bbcc7c Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Mon, 9 Jul 2012 07:30:27 -0700 Subject: [PATCH 2399/5711] staging "speakup" Fix typos. Signed-off-by: Justin P. Mattock Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/i18n.c | 2 +- drivers/staging/speakup/speakup_acnt.h | 2 +- drivers/staging/speakup/speakup_decpc.c | 2 +- drivers/staging/speakup/synth.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/speakup/i18n.c b/drivers/staging/speakup/i18n.c index c2119433f333..ca01734d13c5 100644 --- a/drivers/staging/speakup/i18n.c +++ b/drivers/staging/speakup/i18n.c @@ -71,7 +71,7 @@ static char *speakup_default_msgs[MSG_LAST_INDEX] = { [MSG_CTL_SHIFT] = "shift", [MSG_CTL_ALTGR] = "altgr", [MSG_CTL_CONTROL] = "control", - [MSG_CTL_ALT] = "ault", + [MSG_CTL_ALT] = "alt", [MSG_CTL_LSHIFT] = "l shift", [MSG_CTL_SPEAKUP] = "speakup", [MSG_CTL_LCONTROL] = "l control", diff --git a/drivers/staging/speakup/speakup_acnt.h b/drivers/staging/speakup/speakup_acnt.h index 2d883654ffcc..6376fca9e0e1 100644 --- a/drivers/staging/speakup/speakup_acnt.h +++ b/drivers/staging/speakup/speakup_acnt.h @@ -12,5 +12,5 @@ to accept a byte of data. */ #define SYNTH_QUIET 'S' /* synth is not speaking */ #define SYNTH_FULL 'F' /* synth is full. */ -#define SYNTH_ALMOST_EMPTY 'M' /* synth has les than 2 seconds of text left */ +#define SYNTH_ALMOST_EMPTY 'M' /* synth has less than 2 seconds of text left */ #define SYNTH_SPEAKING 's' /* synth is speaking and has a fare way to go */ diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c index de25527decf6..a09a0c9975df 100644 --- a/drivers/staging/speakup/speakup_decpc.c +++ b/drivers/staging/speakup/speakup_decpc.c @@ -66,7 +66,7 @@ #define CMD_null 0x0000 /* post status */ #define CMD_control 0x1000 /* hard control command */ #define CTRL_mask 0x0F00 /* mask off control nibble */ -#define CTRL_data 0x00FF /* madk to get data byte */ +#define CTRL_data 0x00FF /* mask to get data byte */ #define CTRL_null 0x0000 /* null control */ #define CTRL_vol_up 0x0100 /* increase volume */ #define CTRL_vol_down 0x0200 /* decrease volume */ diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 331eae788700..df9533798095 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -64,7 +64,7 @@ EXPORT_SYMBOL_GPL(serial_synth_probe); /* Main loop of the progression thread: keep eating from the buffer * and push to the serial port, waiting as needed * - * For devices that have a "full" notification mecanism, the driver can + * For devices that have a "full" notification mechanism, the driver can * adapt the loop the way they prefer. */ void spk_do_catch_up(struct spk_synth *synth) -- GitLab From 2add5f4661ce822fe16afabf925a0133d6b274fb Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Mon, 9 Jul 2012 23:04:18 +0530 Subject: [PATCH 2400/5711] staging/slicoss: remove not-needed ASSERT As the private pointer is valid at the remove of driver, and remove wont' be called if probe fails, so no point for checking of ASSERT Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index d2b82a78d2af..a511a2be9c70 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -3196,7 +3196,6 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev) struct sliccard *card; struct mcast_address *mcaddr, *mlist; - ASSERT(adapter); slic_adapter_freeresources(adapter); slic_unmap_mmio_space(adapter); unregister_netdev(dev); -- GitLab From 0ab1900539d46a3a8b7a006819ef5ec0e3288e5b Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Mon, 9 Jul 2012 23:04:20 +0530 Subject: [PATCH 2401/5711] staging/slicoss: return -ENODEV if no devid matches if no case matches we are simply asserting and doing break. and i think we may need to return that -ENODEV , no device is present, rather assert'ing. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index a511a2be9c70..785e4c5f269e 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -3745,8 +3745,7 @@ static u32 slic_card_locate(struct adapter *adapter) rdhostid_offset = SLIC_RDHOSTID_1GB; break; default: - ASSERT(0); - break; + return -ENODEV; } hostid_reg = -- GitLab From 952fc18ef9ec707ebdc16c0786ec360295e5ff15 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 9 Jul 2012 16:27:05 -0400 Subject: [PATCH 2402/5711] ext4: fix overhead calculation used by ext4_statfs() Commit f975d6bcc7a introduced bug which caused ext4_statfs() to miscalculate the number of file system overhead blocks. This causes the f_blocks field in the statfs structure to be larger than it should be. This would in turn cause the "df" output to show the number of data blocks in the file system and the number of data blocks used to be larger than they should be. Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/bitmap.c | 4 -- fs/ext4/ext4.h | 4 +- fs/ext4/resize.c | 7 +- fs/ext4/super.c | 174 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 132 insertions(+), 57 deletions(-) diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 7e86a6d28c64..a94b9c63ee5c 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -11,8 +11,6 @@ #include #include "ext4.h" -#ifdef EXT4FS_DEBUG - static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; unsigned int ext4_count_free(char *bitmap, unsigned int numchars) @@ -25,8 +23,6 @@ unsigned int ext4_count_free(char *bitmap, unsigned int numchars) return sum; } -#endif /* EXT4FS_DEBUG */ - int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, struct buffer_head *bh, int sz) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 293fa1ced21b..01434f25917d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1161,8 +1161,7 @@ struct ext4_sb_info { unsigned long s_desc_per_block; /* Number of group descriptors per block */ ext4_group_t s_groups_count; /* Number of groups in the fs */ ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ - unsigned long s_overhead_last; /* Last calculated overhead */ - unsigned long s_blocks_last; /* Last seen block count */ + unsigned long s_overhead; /* # of fs overhead clusters */ unsigned int s_cluster_ratio; /* Number of blocks per cluster */ unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ @@ -2037,6 +2036,7 @@ extern int ext4_group_extend(struct super_block *sb, extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); /* super.c */ +extern int ext4_calculate_overhead(struct super_block *sb); extern int ext4_superblock_csum_verify(struct super_block *sb, struct ext4_super_block *es); extern void ext4_superblock_csum_set(struct super_block *sb, diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 7ea6cbb44121..17d38de4068c 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1197,7 +1197,7 @@ static void ext4_update_super(struct super_block *sb, struct ext4_new_group_data *group_data = flex_gd->groups; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - int i; + int i, ret; BUG_ON(flex_gd->count == 0 || group_data == NULL); /* @@ -1272,6 +1272,11 @@ static void ext4_update_super(struct super_block *sb, &sbi->s_flex_groups[flex_group].free_inodes); } + /* + * Update the fs overhead information + */ + ext4_calculate_overhead(sb); + if (test_opt(sb, DEBUG)) printk(KERN_DEBUG "EXT4-fs: added group %u:" "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index eb7aa3e4ef05..78b7ede2efa0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3085,6 +3085,114 @@ static int set_journal_csum_feature_set(struct super_block *sb) return ret; } +/* + * Note: calculating the overhead so we can be compatible with + * historical BSD practice is quite difficult in the face of + * clusters/bigalloc. This is because multiple metadata blocks from + * different block group can end up in the same allocation cluster. + * Calculating the exact overhead in the face of clustered allocation + * requires either O(all block bitmaps) in memory or O(number of block + * groups**2) in time. We will still calculate the superblock for + * older file systems --- and if we come across with a bigalloc file + * system with zero in s_overhead_clusters the estimate will be close to + * correct especially for very large cluster sizes --- but for newer + * file systems, it's better to calculate this figure once at mkfs + * time, and store it in the superblock. If the superblock value is + * present (even for non-bigalloc file systems), we will use it. + */ +static int count_overhead(struct super_block *sb, ext4_group_t grp, + char *buf) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_group_desc *gdp; + ext4_fsblk_t first_block, last_block, b; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int s, j, count = 0; + + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + + (grp * EXT4_BLOCKS_PER_GROUP(sb)); + last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; + for (i = 0; i < ngroups; i++) { + gdp = ext4_get_group_desc(sb, i, NULL); + b = ext4_block_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_table(sb, gdp); + if (b >= first_block && b + sbi->s_itb_per_group <= last_block) + for (j = 0; j < sbi->s_itb_per_group; j++, b++) { + int c = EXT4_B2C(sbi, b - first_block); + ext4_set_bit(c, buf); + count++; + } + if (i != grp) + continue; + s = 0; + if (ext4_bg_has_super(sb, grp)) { + ext4_set_bit(s++, buf); + count++; + } + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { + ext4_set_bit(EXT4_B2C(sbi, s++), buf); + count++; + } + } + if (!count) + return 0; + return EXT4_CLUSTERS_PER_GROUP(sb) - + ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8); +} + +/* + * Compute the overhead and stash it in sbi->s_overhead + */ +int ext4_calculate_overhead(struct super_block *sb) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + ext4_fsblk_t overhead = 0; + char *buf = (char *) get_zeroed_page(GFP_KERNEL); + + memset(buf, 0, PAGE_SIZE); + if (!buf) + return -ENOMEM; + + /* + * Compute the overhead (FS structures). This is constant + * for a given filesystem unless the number of block groups + * changes so we cache the previous value until it does. + */ + + /* + * All of the blocks before first_data_block are overhead + */ + overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); + + /* + * Add the overhead found in each block group + */ + for (i = 0; i < ngroups; i++) { + int blks; + + blks = count_overhead(sb, i, buf); + overhead += blks; + if (blks) + memset(buf, 0, PAGE_SIZE); + cond_resched(); + } + sbi->s_overhead = overhead; + smp_wmb(); + free_page((unsigned long) buf); + return 0; +} + static int ext4_fill_super(struct super_block *sb, void *data, int silent) { char *orig_data = kstrdup(data, GFP_KERNEL); @@ -3734,6 +3842,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); no_journal: + /* + * Get the # of file system overhead blocks from the + * superblock if present. + */ + if (es->s_overhead_clusters) + sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); + else { + ret = ext4_calculate_overhead(sb); + if (ret) + goto failed_mount_wq; + } + /* * The maximum number of concurrent works can be high and * concurrency isn't really necessary. Limit it to 1. @@ -4600,67 +4720,21 @@ restore_opts: return err; } -/* - * Note: calculating the overhead so we can be compatible with - * historical BSD practice is quite difficult in the face of - * clusters/bigalloc. This is because multiple metadata blocks from - * different block group can end up in the same allocation cluster. - * Calculating the exact overhead in the face of clustered allocation - * requires either O(all block bitmaps) in memory or O(number of block - * groups**2) in time. We will still calculate the superblock for - * older file systems --- and if we come across with a bigalloc file - * system with zero in s_overhead_clusters the estimate will be close to - * correct especially for very large cluster sizes --- but for newer - * file systems, it's better to calculate this figure once at mkfs - * time, and store it in the superblock. If the superblock value is - * present (even for non-bigalloc file systems), we will use it. - */ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - struct ext4_group_desc *gdp; + ext4_fsblk_t overhead = 0; u64 fsid; s64 bfree; - if (test_opt(sb, MINIX_DF)) { - sbi->s_overhead_last = 0; - } else if (es->s_overhead_clusters) { - sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters); - } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - ext4_fsblk_t overhead = 0; - - /* - * Compute the overhead (FS structures). This is constant - * for a given filesystem unless the number of block groups - * changes so we cache the previous value until it does. - */ - - /* - * All of the blocks before first_data_block are - * overhead - */ - overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); - - /* - * Add the overhead found in each block group - */ - for (i = 0; i < ngroups; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - overhead += ext4_num_overhead_clusters(sb, i, gdp); - cond_resched(); - } - sbi->s_overhead_last = overhead; - smp_wmb(); - sbi->s_blocks_last = ext4_blocks_count(es); - } + if (!test_opt(sb, MINIX_DF)) + overhead = sbi->s_overhead; buf->f_type = EXT4_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; - buf->f_blocks = (ext4_blocks_count(es) - - EXT4_C2B(sbi, sbi->s_overhead_last)); + buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead); bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); /* prevent underflow in case that few free space is available */ -- GitLab From ef58f69c3c34f6377f1e21d3533c806dbd980ad0 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 9 Jul 2012 16:29:05 -0400 Subject: [PATCH 2403/5711] ext4: use proper csum calculation in ext4_rename In ext4_rename, when the old name is a dir, we need to change ".." to its new parent and journal the change, so with metadata_csum enabled, we have to re-calc the csum. As the first block of the dir can be either a htree root or a normal directory block and we have different csum calculation for these 2 types, we have to choose the right one in ext4_rename. btw, it is found by xfstests 013. Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" Acked-by: Darrick J. Wong --- fs/ext4/namei.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5845cd97bf8b..0edaf18d843e 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2918,8 +2918,15 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); - retval = ext4_handle_dirty_dirent_node(handle, old_inode, - dir_bh); + if (is_dx(old_inode)) { + retval = ext4_handle_dirty_dx_node(handle, + old_inode, + dir_bh); + } else { + retval = ext4_handle_dirty_dirent_node(handle, + old_inode, + dir_bh); + } if (retval) { ext4_std_error(old_dir->i_sb, retval); goto end_rename; -- GitLab From 41eb70dde42b2360074a559a6f1fc49860a50179 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 9 Jul 2012 16:29:27 -0400 Subject: [PATCH 2404/5711] ext4: use s_csum_seed instead of i_csum_seed for xattr block In xattr block operation, we use h_refcount to indicate whether the xattr block is shared among many inodes. And xattr block csum uses s_csum_seed if it is shared and i_csum_seed if it belongs to one inode. But this has a problem. So consider the block is shared first bewteen inode A and B, and B has some xattr update and CoW the xattr block. When it updates the *old* xattr block(because of the h_refcount change) and calls ext4_xattr_release_block, we has no idea that inode A is the real owner of the *old* xattr block and we can't use the i_csum_seed of inode A either in xattr block csum calculation. And I don't think we have an easy way to find inode A. So this patch just removes the tricky i_csum_seed and we now uses s_csum_seed every time for the xattr block csum. The corresponding patch for the e2fsprogs will be sent in another patch. This is spotted by xfstests 117. Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" Acked-by: Darrick J. Wong --- fs/ext4/xattr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e56c9ed7d6e3..2cdb98d62980 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -127,19 +127,16 @@ static __le32 ext4_xattr_block_csum(struct inode *inode, struct ext4_xattr_header *hdr) { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); - struct ext4_inode_info *ei = EXT4_I(inode); __u32 csum, old; old = hdr->h_checksum; hdr->h_checksum = 0; - if (le32_to_cpu(hdr->h_refcount) != 1) { - block_nr = cpu_to_le64(block_nr); - csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr, - sizeof(block_nr)); - } else - csum = ei->i_csum_seed; + block_nr = cpu_to_le64(block_nr); + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr, + sizeof(block_nr)); csum = ext4_chksum(sbi, csum, (__u8 *)hdr, EXT4_BLOCK_SIZE(inode->i_sb)); + hdr->h_checksum = old; return cpu_to_le32(csum); } -- GitLab From e7bcf8230498b9568e09d74e296e71a01e024006 Mon Sep 17 00:00:00 2001 From: HaiboLiu Date: Mon, 9 Jul 2012 16:29:28 -0400 Subject: [PATCH 2405/5711] ext4: fix out-of-date comments in extents.c In this patch, ext4_ext_try_to_merge has been change to merge an extent both left and right. So we need to update the comment in here. Signed-off-by: HaiboLiu Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f1089cba913a..46b5c9fdc96a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1891,11 +1891,10 @@ has_space: nearex->ee_len = newext->ee_len; merge: - /* try to merge extents to the right */ + /* try to merge extents */ if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) ext4_ext_try_to_merge(inode, path, nearex); - /* try to merge extents to the left */ /* time to correct all indexes above */ err = ext4_ext_correct_indexes(handle, inode, path); -- GitLab From 62a1391ddd6fbe82fc02154dc760bcc5cbc9ef68 Mon Sep 17 00:00:00 2001 From: Haibo Liu Date: Mon, 9 Jul 2012 16:29:28 -0400 Subject: [PATCH 2406/5711] ext4: remove an unused statement in ext4_mb_get_buddy_page_lock() In this patch, the statement "poff = block % blocks_per_page" in ext4_mb_get_buddy_page_lock has no effect. It will be optimized out by the compiler, but it's better to remove it. Signed-off-by: Haibo Liu Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 9f1e655979b9..ca376e7d716a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -969,7 +969,6 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb, block++; pnum = block / blocks_per_page; - poff = block % blocks_per_page; page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); if (!page) return -EIO; -- GitLab From fbe104942d3ff44f6802e8e4a3fbf267c1fb9ac4 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Mon, 9 Jul 2012 16:29:29 -0400 Subject: [PATCH 2407/5711] ext4: split ext4_file_write into buffered IO and direct IO ext4_file_dio_write is defined in order to split buffered IO and direct IO in ext4. This patch just refactor some stuff in write path. CC: Tao Ma CC: Eric Sandeen CC: Robin Dong Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" --- fs/ext4/file.c | 60 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 8c7642a00054..a10dc7742aec 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -90,34 +90,16 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, } static ssize_t -ext4_file_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) { struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; int unaligned_aio = 0; ssize_t ret; - /* - * If we have encountered a bitmap-format file, the size limit - * is smaller than s_maxbytes, which is for extent-mapped files. - */ - - if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); - size_t length = iov_length(iov, nr_segs); - - if ((pos > sbi->s_bitmap_maxbytes || - (pos == sbi->s_bitmap_maxbytes && length > 0))) - return -EFBIG; - - if (pos + length > sbi->s_bitmap_maxbytes) { - nr_segs = iov_shorten((struct iovec *)iov, nr_segs, - sbi->s_bitmap_maxbytes - pos); - } - } else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) && - !is_sync_kiocb(iocb))) { + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && + !is_sync_kiocb(iocb)) unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); - } /* Unaligned direct AIO must be serialized; see comment above */ if (unaligned_aio) { @@ -141,6 +123,40 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, return ret; } +static ssize_t +ext4_file_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; + ssize_t ret; + + /* + * If we have encountered a bitmap-format file, the size limit + * is smaller than s_maxbytes, which is for extent-mapped files. + */ + + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + size_t length = iov_length(iov, nr_segs); + + if ((pos > sbi->s_bitmap_maxbytes || + (pos == sbi->s_bitmap_maxbytes && length > 0))) + return -EFBIG; + + if (pos + length > sbi->s_bitmap_maxbytes) { + nr_segs = iov_shorten((struct iovec *)iov, nr_segs, + sbi->s_bitmap_maxbytes - pos); + } + } + + if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) + ret = ext4_file_dio_write(iocb, iov, nr_segs, pos); + else + ret = generic_file_aio_write(iocb, iov, nr_segs, pos); + + return ret; +} + static const struct vm_operations_struct ext4_file_vm_ops = { .fault = filemap_fault, .page_mkwrite = ext4_page_mkwrite, -- GitLab From 729f52c6be51013c9268e5fc85acbc1091286fdb Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Mon, 9 Jul 2012 16:29:29 -0400 Subject: [PATCH 2408/5711] ext4: add a new nolock flag in ext4_map_blocks EXT4_GET_BLOCKS_NO_LOCK flag is added to indicate that we don't need to acquire i_data_sem lock in ext4_map_blocks. Meanwhile, it changes ext4_get_block() to not start a new journal because when we do a overwrite dio, there is no any metadata that needs to be modified. We define a new function called ext4_get_block_write_nolock, which is used in dio overwrite nolock. In this function, it doesn't try to acquire i_data_sem lock and doesn't start a new journal as it does a lookup. CC: Tao Ma CC: Eric Sandeen CC: Robin Dong Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4.h | 2 ++ fs/ext4/inode.c | 59 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 01434f25917d..4a49f8225d0b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -571,6 +571,8 @@ enum { #define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040 /* Request will not result in inode size update (user for fallocate) */ #define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080 + /* Do not take i_data_sem locking in ext4_map_blocks */ +#define EXT4_GET_BLOCKS_NO_LOCK 0x0100 /* * Flags used by ext4_free_blocks diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 02bc8cbe7281..76cb3b1ad78a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -544,7 +544,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, * Try to see if we can get the block without requesting a new * file system block. */ - down_read((&EXT4_I(inode)->i_data_sem)); + if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) + down_read((&EXT4_I(inode)->i_data_sem)); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { retval = ext4_ext_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE); @@ -552,7 +553,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, retval = ext4_ind_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE); } - up_read((&EXT4_I(inode)->i_data_sem)); + if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) + up_read((&EXT4_I(inode)->i_data_sem)); if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { int ret = check_block_validity(inode, map); @@ -2818,6 +2820,32 @@ static int ext4_get_block_write(struct inode *inode, sector_t iblock, EXT4_GET_BLOCKS_IO_CREATE_EXT); } +static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int flags) +{ + handle_t *handle = ext4_journal_current_handle(); + struct ext4_map_blocks map; + int ret = 0; + + ext4_debug("ext4_get_block_write_nolock: inode %lu, flag %d\n", + inode->i_ino, flags); + + flags = EXT4_GET_BLOCKS_NO_LOCK; + + map.m_lblk = iblock; + map.m_len = bh_result->b_size >> inode->i_blkbits; + + ret = ext4_map_blocks(handle, inode, &map, flags); + if (ret > 0) { + map_bh(bh_result, inode->i_sb, map.m_pblk); + bh_result->b_state = (bh_result->b_state & ~EXT4_MAP_FLAGS) | + map.m_flags; + bh_result->b_size = inode->i_sb->s_blocksize * map.m_len; + ret = 0; + } + return ret; +} + static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, ssize_t size, void *private, int ret, bool is_async) @@ -2966,6 +2994,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, loff_t final_size = offset + count; if (rw == WRITE && final_size <= inode->i_size) { + int overwrite = 0; + /* * We could direct write to holes and fallocate. * @@ -3005,13 +3035,22 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, EXT4_I(inode)->cur_aio_dio = iocb->private; } - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, - ext4_get_block_write, - ext4_end_io_dio, - NULL, - DIO_LOCKING); + if (overwrite) + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, + ext4_get_block_write_nolock, + ext4_end_io_dio, + NULL, + 0); + else + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, + ext4_get_block_write, + ext4_end_io_dio, + NULL, + DIO_LOCKING); if (iocb->private) EXT4_I(inode)->cur_aio_dio = NULL; /* @@ -3031,7 +3070,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) { ext4_free_io_end(iocb->private); iocb->private = NULL; - } else if (ret > 0 && ext4_test_inode_state(inode, + } else if (ret > 0 && !overwrite && ext4_test_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN)) { int err; /* -- GitLab From 1a49e2ac9651df7349867a5cf44e2c83de1046af Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Jul 2012 15:55:14 -0400 Subject: [PATCH 2409/5711] EHCI: centralize controller initialization This patch (as1564c) converts the EHCI platform drivers to use the central ehci_setup() routine for generic controller initialization rather than each having its own idiosyncratic approach. The major point of difficulty lies in ehci-pci's many vendor- and device-specific workarounds. Some of them have to be applied before calling ehci_setup() and some after, which necessitates a fair amount of code motion. The other platform drivers require much smaller changes. One point not addressed by the patch is whether ports should be powered on or off following initialization. The different drivers appear to handle this pretty much at random. In fact it shouldn't matter, because the hub driver turns on power to all ports when it binds to the root hub. Straightening that out will be left for another day. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-atmel.c | 19 +--- drivers/usb/host/ehci-au1xxx.c | 14 +-- drivers/usb/host/ehci-cns3xxx.c | 6 +- drivers/usb/host/ehci-fsl.c | 18 +--- drivers/usb/host/ehci-grlib.c | 15 +-- drivers/usb/host/ehci-hcd.c | 5 +- drivers/usb/host/ehci-ixp4xx.c | 6 +- drivers/usb/host/ehci-mv.c | 23 +---- drivers/usb/host/ehci-mxc.c | 17 +--- drivers/usb/host/ehci-octeon.c | 8 +- drivers/usb/host/ehci-omap.c | 104 ++++++++++--------- drivers/usb/host/ehci-orion.c | 17 +--- drivers/usb/host/ehci-pci.c | 160 +++++++++++++++--------------- drivers/usb/host/ehci-pmcmsp.c | 17 +--- drivers/usb/host/ehci-ppc-of.c | 25 +---- drivers/usb/host/ehci-ps3.c | 18 +--- drivers/usb/host/ehci-s5p.c | 12 +-- drivers/usb/host/ehci-sh.c | 16 +-- drivers/usb/host/ehci-spear.c | 10 +- drivers/usb/host/ehci-tegra.c | 18 +--- drivers/usb/host/ehci-vt8500.c | 14 +-- drivers/usb/host/ehci-w90x900.c | 9 +- drivers/usb/host/ehci-xilinx-of.c | 31 +----- drivers/usb/host/ehci-xls.c | 21 +--- 24 files changed, 164 insertions(+), 439 deletions(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index cf14c95a6700..a47e2cffaaf8 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev) static int ehci_atmel_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval = 0; + int retval; /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - retval = ehci_halt(ehci); - if (retval) - return retval; - /* data structure init */ - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; - ehci->sbrn = 0x20; - - ehci_reset(ehci); ehci_port_power(ehci, 0); return retval; diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 182d39565906..cba10d625a5d 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -20,10 +20,12 @@ extern int usb_disabled(void); static int au1xxx_ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret = ehci_init(hcd); + int ret; + + ehci->caps = hcd->regs; + ret = ehci_setup(hcd); ehci->need_io_watchdog = 0; - ehci_reset(ehci); return ret; } @@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; - struct ehci_hcd *ehci; struct resource *res; int ret; @@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) goto err3; } - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl(&ehci->caps->hcs_params); - ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); if (ret == 0) { diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c index 6536abdea6e6..caaa3e5be334 100644 --- a/drivers/usb/host/ehci-cns3xxx.c +++ b/drivers/usb/host/ehci-cns3xxx.c @@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd) } ehci->caps = hcd->regs; - ehci->regs = hcd->regs - + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 0; - ehci_reset(ehci); - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 74914de8b9bf..ab52db684b63 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -348,29 +348,13 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* data structure init */ - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; - ehci->sbrn = 0x20; - - ehci_reset(ehci); - if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { /* diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index fdfd8c5b639b..22ca45c079a4 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; - retval = ehci_halt(ehci); + retval = ehci_setup(hcd); if (retval) return retval; - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; ehci_port_power(ehci, 1); - return ehci_reset(ehci); + return retval; } @@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) ehci->big_endian_capbase = 1; } - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - rv = usb_add_hcd(hcd, irq, 0); if (rv) goto err_ehci; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e6823a0cf642..f9a783bfa1fe 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -808,7 +808,7 @@ static int ehci_run (struct usb_hcd *hcd) return 0; } -static int __maybe_unused ehci_setup (struct usb_hcd *hcd) +static int ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; @@ -832,6 +832,9 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd) if (retval) return retval; + if (ehci_is_TDI(ehci)) + tdi_reset(ehci); + ehci_reset(ehci); return 0; diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index c4460f3d009f..488d401942e9 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd) ehci->big_endian_mmio = 1; ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 - + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; - ehci_reset(ehci); - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 0e8c168ca24c..f6df1ccc9617 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -77,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) static int mv_ehci_reset(struct usb_hcd *hcd) { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct device *dev = hcd->self.controller; struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev); int retval; @@ -87,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd) return -ENODEV; } - /* - * data structure init - */ - retval = ehci_init(hcd); - if (retval) { - dev_err(dev, "ehci_init failed %d\n", retval); - return retval; - } - hcd->has_tt = 1; - ehci->sbrn = 0x20; - retval = ehci_reset(ehci); - if (retval) { - dev_err(dev, "ehci_reset failed %d\n", retval); - return retval; - } + retval = ehci_setup(hcd); + if (retval) + dev_err(dev, "ehci_setup failed %d\n", retval); - return 0; + return retval; } static const struct hc_driver mv_ehci_hc_driver = { @@ -248,8 +235,6 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; - ehci->regs = (struct ehci_regs *) ehci_mv->op_regs; - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index c778ffe4e4e5..34201372c85f 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - hcd->has_tt = 1; - retval = ehci_halt(ehci); + retval = ehci_setup(hcd); if (retval) return retval; - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - - ehci_reset(ehci); - ehci_port_power(ehci, 0); return 0; } diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index c0104882c72d..ba26957abf46 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_init, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) #endif ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ehci_reset(ehci); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) { diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 6e15fc87cf60..6133d93808dc 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -145,6 +145,56 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) } } +static int omap_ehci_init(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int rc; + struct ehci_hcd_omap_platform_data *pdata; + + pdata = hcd->self.controller->platform_data; + if (pdata->phy_reset) { + if (gpio_is_valid(pdata->reset_gpio_port[0])) + gpio_request_one(pdata->reset_gpio_port[0], + GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + + if (gpio_is_valid(pdata->reset_gpio_port[1])) + gpio_request_one(pdata->reset_gpio_port[1], + GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + + /* Hold the PHY in RESET for enough time till DIR is high */ + udelay(10); + } + + /* Soft reset the PHY using PHY reset command over ULPI */ + if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) + omap_ehci_soft_phy_reset(pdev, 0); + if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) + omap_ehci_soft_phy_reset(pdev, 1); + + /* we know this is the memory we want, no need to ioremap again */ + ehci->caps = hcd->regs; + + rc = ehci_setup(hcd); + + if (pdata->phy_reset) { + /* Hold the PHY in RESET for enough time till + * PHY is settled and ready + */ + udelay(10); + + if (gpio_is_valid(pdata->reset_gpio_port[0])) + gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); + + if (gpio_is_valid(pdata->reset_gpio_port[1])) + gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); + } + + /* root ports should always stay powered */ + ehci_port_power(ehci, 1); + + return rc; +} + static int omap_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, @@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) struct resource *res; struct usb_hcd *hcd; void __iomem *regs; - struct ehci_hcd *omap_ehci; int ret = -ENODEV; int irq; int i; @@ -281,19 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } } - if (pdata->phy_reset) { - if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_request_one(pdata->reset_gpio_port[0], - GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); - - if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_request_one(pdata->reset_gpio_port[1], - GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); - - /* Hold the PHY in RESET for enough time till DIR is high */ - udelay(10); - } - pm_runtime_enable(dev); pm_runtime_get_sync(dev); @@ -309,50 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) ehci_write(regs, EHCI_INSNREG04, EHCI_INSNREG04_DISABLE_UNSUSPEND); - /* Soft reset the PHY using PHY reset command over ULPI */ - if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) - omap_ehci_soft_phy_reset(pdev, 0); - if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) - omap_ehci_soft_phy_reset(pdev, 1); - - omap_ehci = hcd_to_ehci(hcd); - omap_ehci->sbrn = 0x20; - - /* we know this is the memory we want, no need to ioremap again */ - omap_ehci->caps = hcd->regs; - omap_ehci->regs = hcd->regs - + HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase)); - - dbg_hcs_params(omap_ehci, "reset"); - dbg_hcc_params(omap_ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); - - ehci_reset(omap_ehci); - - if (pdata->phy_reset) { - /* Hold the PHY in RESET for enough time till - * PHY is settled and ready - */ - udelay(10); - - if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); - - if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); - } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) { dev_err(dev, "failed to add hcd with err %d\n", ret); goto err_pm_runtime; } - /* root ports should always stay powered */ - ehci_port_power(omap_ehci, 1); - /* get clocks */ utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); if (IS_ERR(utmi_p1_fck)) { @@ -512,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_init, + .reset = omap_ehci_init, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 82de1073aa52..3e411230953b 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; - hcd->has_tt = 1; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* - * data structure init - */ - retval = ehci_init(hcd); + retval = ehci_setup(ehci); if (retval) return retval; - ehci_reset(ehci); - ehci_port_power(ehci, 0); return retval; @@ -261,11 +250,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; - ehci->sbrn = 0x20; /* * (Re-)program MBUS remapping windows if we are asked to. diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 6e767bce0605..21e5f963f331 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) u32 temp; int retval; + ehci->caps = hcd->regs; + + /* + * ehci_init() causes memory for DMA transfers to be + * allocated. Thus, any vendor-specific workarounds based on + * limiting the type of memory used for DMA transfers must + * happen before ehci_setup() is called. + * + * Most other workarounds can be done either before or after + * init and reset; they are located here too. + */ switch (pdev->vendor) { case PCI_VENDOR_ID_TOSHIBA_2: /* celleb's companion chip */ @@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) #endif } break; - } - - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* ehci_init() causes memory for DMA transfers to be - * allocated. Thus, any vendor-specific workarounds based on - * limiting the type of memory used for DMA transfers must - * happen before ehci_init() is called. */ - switch (pdev->vendor) { case PCI_VENDOR_ID_NVIDIA: /* NVidia reports that certain chips don't handle * QH, ITD, or SITD addresses above 2GB. (But TD, @@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; - } - break; - } - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - retval = ehci_halt(ehci); - if (retval) - return retval; - - if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) || - (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) { - /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. + /* Some NForce2 chips have problems with selective suspend; + * fixed in newer silicon. */ - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI " - "dummy qh workaround\n"); - } - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - switch (pdev->vendor) { - case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; + case 0x0068: + if (pdev->revision < 0xa4) + ehci->no_selective_suspend = 1; + break; + } break; case PCI_VENDOR_ID_INTEL: - ehci->need_io_watchdog = 0; ehci->fs_i_thresh = 1; if (pdev->device == 0x27cc) { ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); } - if (pdev->device == 0x0806 || pdev->device == 0x0811 - || pdev->device == 0x0829) { - ehci_info(ehci, "disable lpm for langwell/penwell\n"); - ehci->has_lpm = 0; - } - if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) { + if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) hcd->has_tt = 1; - tdi_reset(ehci); - } break; case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) hcd->has_tt = 1; - tdi_reset(ehci); - } break; case PCI_VENDOR_ID_AMD: /* AMD PLL quirk */ @@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) retval = -EIO; goto done; } - break; - case PCI_VENDOR_ID_NVIDIA: - switch (pdev->device) { - /* Some NForce2 chips have problems with selective suspend; - * fixed in newer silicon. - */ - case 0x0068: - if (pdev->revision < 0xa4) - ehci->no_selective_suspend = 1; - break; - /* MCP89 chips on the MacBookAir3,1 give EPROTO when - * fetching device descriptors unless LPM is disabled. - * There are also intermittent problems enumerating - * devices with PPCD enabled. + /* + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may + * read/write memory space which does not belong to it when + * there is NULL pointer with T-bit set to 1 in the frame list + * table. To avoid the issue, the frame list link pointer + * should always contain a valid pointer to a inactive qh. */ - case 0x0d9d: - ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); - ehci->has_lpm = 0; - ehci->has_ppcd = 0; - ehci->command &= ~CMD_PPCEE; - break; + if (pdev->device == 0x7808) { + ehci->use_dummy_qh = 1; + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); } break; case PCI_VENDOR_ID_VIA: @@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* AMD PLL quirk */ if (usb_amd_find_chipset_info()) ehci->amd_pll_fix = 1; + + /* + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may + * read/write memory space which does not belong to it when + * there is NULL pointer with T-bit set to 1 in the frame list + * table. To avoid the issue, the frame list link pointer + * should always contain a valid pointer to a inactive qh. + */ + if (pdev->device == 0x4396) { + ehci->use_dummy_qh = 1; + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); + } /* SB600 and old version of SB700 have a bug in EHCI controller, * which causes usb devices lose response in some cases. */ @@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } + retval = ehci_setup(hcd); + if (retval) + return retval; + + /* 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: + ehci->need_io_watchdog = 0; + if (pdev->device == 0x0806 || pdev->device == 0x0811 + || pdev->device == 0x0829) { + ehci_info(ehci, "disable lpm for langwell/penwell\n"); + ehci->has_lpm = 0; + } + break; + case PCI_VENDOR_ID_NVIDIA: + switch (pdev->device) { + /* MCP89 chips on the MacBookAir3,1 give EPROTO when + * fetching device descriptors unless LPM is disabled. + * There are also intermittent problems enumerating + * devices with PPCD enabled. + */ + case 0x0d9d: + ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); + ehci->has_lpm = 0; + ehci->has_ppcd = 0; + ehci->command &= ~CMD_PPCEE; + break; + } + break; + } + /* optional debug port, normally in the first BAR */ temp = pci_find_capability(pdev, 0x0a); if (temp) { @@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) temp >>= 16; if ((temp & (3 << 13)) == (1 << 13)) { temp &= 0x1fff; - ehci->debug = ehci_to_hcd(ehci)->regs + temp; + ehci->debug = hcd->regs + temp; temp = ehci_readl(ehci, &ehci->debug->control); ehci_info(ehci, "debug port %d%s\n", HCS_DEBUG_PORT(ehci->hcs_params), @@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } } - ehci_reset(ehci); - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; @@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } /* Serial Bus Release Number is at PCI 0x60 offset */ - pci_read_config_byte(pdev, 0x60, &ehci->sbrn); if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) - ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ + ; /* ConneXT has no sbrn register */ + else + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index e8d54de44acc..087aee2a904f 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; + ehci->big_endian_mmio = 1; ehci->big_endian_desc = 1; ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; - retval = ehci_halt(ehci); - if (retval) - return retval; - - ehci_reset(ehci); - - /* data structure init */ - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 41d11fe14252..bbbe89dfd886 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -17,24 +17,6 @@ #include #include -/* called during probe() after chip reset completes */ -static int ehci_ppc_of_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - return ehci_reset(ehci); -} - static const struct hc_driver ehci_ppc_of_hc_driver = { .description = hcd_name, @@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_ppc_of_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) ehci->big_endian_desc = 1; ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) { rv = ppc44x_enable_bmt(dn); diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index a20e496eb479..45a356e9f138 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); ehci->big_endian_mmio = 1; - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, - &ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - result = ehci_halt(ehci); + result = ehci_setup(hcd); if (result) return result; - result = ehci_init(hcd); - - if (result) - return result; - - ehci_reset(ehci); - ps3_ehci_setup_insnreg(ehci); return result; diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index c7e0936d4a7c..13c179fb2ee2 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -40,7 +40,7 @@ static const struct hc_driver s5p_ehci_hc_driver = { .irq = ehci_irq, .flags = HCD_MEMORY | HCD_USB2, - .reset = ehci_init, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -134,20 +134,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl(&ehci->caps->hcs_params); - - ehci_reset(ehci); - err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index e7cb3925abf8..b3f1e3650da0 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd) int ret; ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, - &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ret = ehci_halt(ehci); - if (unlikely(ret)) - return ret; - - ret = ehci_init(hcd); + ret = ehci_setup(hcd); if (unlikely(ret)) return ret; - ehci->sbrn = 0x20; - - ehci_reset(ehci); ehci_port_power(ehci, 0); return ret; diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 7ed533e6cca8..c718a065e154 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd) /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, - &ehci->caps->hc_capbase)); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - retval = ehci_halt(ehci); - if (retval) - return retval; - retval = ehci_init(hcd); + retval = ehci_setup(hcd); if (retval) return retval; - ehci_reset(ehci); ehci_port_power(ehci, 0); return retval; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 477ecfa05154..f7f3ce3275b8 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -281,30 +281,14 @@ static int tegra_ehci_setup(struct usb_hcd *hcd) /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl(&ehci->caps->hcs_params); /* switch to host mode */ hcd->has_tt = 1; - ehci_reset(ehci); - retval = ehci_halt(ehci); + retval = ehci_setup(ehci); if (retval) return retval; - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - ehci_port_power(ehci, 1); return retval; } diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index c1eda73916cd..4d147c4e33f5 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_init, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -121,18 +121,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl(&ehci->caps->hcs_params); - - ehci_port_power(ehci, 1); - - ehci_reset(ehci); ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index 3d2e26cbb34c..ec598082c14b 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver, val |= ENPHY; __raw_writel(val, ehci->regs+PHY1_CTR); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->sbrn = 0x20; - irq = platform_get_irq(pdev, 0); if (irq < 0) goto err4; - ehci_reset(ehci); - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval != 0) goto err4; - ehci_writel(ehci, 1, &ehci->regs->configured_flag); - return retval; err4: iounmap(hcd->regs); @@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_init, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index e9713d589e30..39f24fa37ebe 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -31,30 +31,6 @@ #include #include -/** - * ehci_xilinx_of_setup - Initialize the device for ehci_reset() - * @hcd: Pointer to the usb_hcd device to which the host controller bound - * - * called during probe() after chip reset completes. - */ -static int ehci_xilinx_of_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - - return ehci_reset(ehci); -} - /** * ehci_xilinx_port_handed_over - hand the port out if failed to enable it * @hcd: Pointer to the usb_hcd device to which the host controller bound @@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_xilinx_of_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) /* Debug registers are at the first 0x100 region */ ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); rv = usb_add_hcd(hcd, irq, 0); if (rv == 0) diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c index 72f08196f8cd..99c353a85ae4 100644 --- a/drivers/usb/host/ehci-xls.c +++ b/drivers/usb/host/ehci-xls.c @@ -14,30 +14,11 @@ static int ehci_xls_setup(struct usb_hcd *hcd) { - int retval; struct ehci_hcd *ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci_reset(ehci); - - return retval; + return ehci_setup(ehci); } int ehci_xls_probe_internal(const struct hc_driver *driver, -- GitLab From d55de60564c90cfd5a55122772c9af7d34e4f665 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 9 Jul 2012 18:22:11 +0400 Subject: [PATCH 2410/5711] sparc64: remove unused function straddles_64bit_va_hole() Nobody uses straddles_64bit_va_hole(). Remove it Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc_64.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 275f74fd6f6a..c38e5aaae56f 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -66,23 +66,6 @@ static inline int invalid_64bit_range(unsigned long addr, unsigned long len) return 0; } -/* Does start,end straddle the VA-space hole? */ -static inline int straddles_64bit_va_hole(unsigned long start, unsigned long end) -{ - unsigned long va_exclude_start, va_exclude_end; - - va_exclude_start = VA_EXCLUDE_START; - va_exclude_end = VA_EXCLUDE_END; - - if (likely(start < va_exclude_start && end < va_exclude_start)) - return 0; - - if (likely(start >= va_exclude_end && end >= va_exclude_end)) - return 0; - - return 1; -} - /* These functions differ from the default implementations in * mm/mmap.c in two ways: * -- GitLab From 349ecd6a3c0e4f97fa4dc6bd3917455ccc106d23 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 9 Jul 2012 23:38:36 +0200 Subject: [PATCH 2411/5711] jbd: Check return value of blkdev_issue_flush() blkdev_issue_flush() can fail. Make sure the error gets properly propagated. Signed-off-by: Jan Kara --- fs/jbd/recovery.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 008bf062fd26..a748fe21465a 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -265,8 +265,11 @@ int journal_recover(journal_t *journal) if (!err) err = err2; /* Flush disk caches to get replayed data on the permanent storage */ - if (journal->j_flags & JFS_BARRIER) - blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); + if (journal->j_flags & JFS_BARRIER) { + err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); + if (!err) + err = err2; + } return err; } -- GitLab From 44f4f729e7a143b08bd63c33cb78b3181d9f4716 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 9 Jul 2012 23:40:46 +0200 Subject: [PATCH 2412/5711] ext3: Check return value of blkdev_issue_flush() blkdev_issue_flush() can fail. Make sure the error gets properly propagated. Signed-off-by: Jan Kara --- fs/ext3/fsync.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c index d4dff278cbd8..b31dbd4c46ad 100644 --- a/fs/ext3/fsync.c +++ b/fs/ext3/fsync.c @@ -92,8 +92,13 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync) * disk caches manually so that data really is on persistent * storage */ - if (needs_barrier) - blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + if (needs_barrier) { + int err; + + err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + if (!ret) + ret = err; + } out: trace_ext3_sync_file_exit(inode, ret); return ret; -- GitLab From 2729d5b18df363167d0c0be428876f3c07d2617b Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:02 -0600 Subject: [PATCH 2413/5711] PCI: restructure 'pci_do_fixups()' This patch restructures pci_do_fixups()'s quirk invocations in the style of initcall_debug_start() and initcall_debug_report(), so we have only one call site for the quirk. [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a7521677541..51c4a4409e8c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2879,20 +2879,34 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); -static void do_one_fixup_debug(void (*fn)(struct pci_dev *dev), struct pci_dev *dev) +static ktime_t fixup_debug_start(struct pci_dev *dev, + void (*fn)(struct pci_dev *dev)) { - ktime_t calltime, delta, rettime; + ktime_t calltime = ktime_set(0, 0); + + dev_dbg(&dev->dev, "calling %pF\n", fn); + if (initcall_debug) { + pr_debug("calling %pF @ %i for %s\n", + fn, task_pid_nr(current), dev_name(&dev->dev)); + calltime = ktime_get(); + } + + return calltime; +} + +static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime, + void (*fn)(struct pci_dev *dev)) +{ + ktime_t delta, rettime; unsigned long long duration; - printk(KERN_DEBUG "calling %pF @ %i for %s\n", - fn, task_pid_nr(current), dev_name(&dev->dev)); - calltime = ktime_get(); - fn(dev); - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - duration = (unsigned long long) ktime_to_ns(delta) >> 10; - printk(KERN_DEBUG "pci fixup %pF returned after %lld usecs for %s\n", - fn, duration, dev_name(&dev->dev)); + if (initcall_debug) { + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long) ktime_to_ns(delta) >> 10; + pr_debug("pci fixup %pF returned after %lld usecs for %s\n", + fn, duration, dev_name(&dev->dev)); + } } /* @@ -2932,6 +2946,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { + ktime_t calltime; + for (; f < end; f++) if ((f->class == (u32) (dev->class >> f->class_shift) || f->class == (u32) PCI_ANY_ID) && @@ -2939,11 +2955,9 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, f->vendor == (u16) PCI_ANY_ID) && (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { - dev_dbg(&dev->dev, "calling %pF\n", f->hook); - if (initcall_debug) - do_one_fixup_debug(f->hook, dev); - else - f->hook(dev); + calltime = fixup_debug_start(dev, f->hook); + f->hook(dev); + fixup_debug_report(dev, calltime, f->hook); } } -- GitLab From dff3aef7139ce1be190be6d13505a35d5c7c0c3c Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:08 -0600 Subject: [PATCH 2414/5711] PCI: release temporary reference in __nv_msi_ht_cap_quirk() __nv_msi_ht_cap_quirk() acquires a temporary reference via 'pci_get_bus_and_slot()' that is never released. This patch releases the temporary reference. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 51c4a4409e8c..50448c291a8f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2541,15 +2541,18 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) else nv_ht_enable_msi_mapping(dev); } - return; + goto out; } /* HT MSI is not enabled */ if (found == 1) - return; + goto out; /* Host bridge is not to HT, disable HT MSI mapping on this device */ ht_disable_msi_mapping(dev); + +out: + pci_dev_put(host_bridge); } static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev) -- GitLab From 25e742b27018abce3bad42e6b6732f91d71cc655 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:14 -0600 Subject: [PATCH 2415/5711] PCI: never discard enable/suspend/resume_early/resume fixups The enable/suspend/resume_early/resume fixups can be called at any time, so they can't be __init or __devinit. [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 50448c291a8f..5b8b840f1a99 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1039,7 +1039,7 @@ static void quirk_disable_pxb(struct pci_dev *pdev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb); -static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev) +static void quirk_amd_ide_mode(struct pci_dev *pdev) { /* set SBX00/Hudson-2 SATA in IDE mode to AHCI mode */ u8 tmp; @@ -2104,7 +2104,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S, quirk_brcm_570x_limit_vpd); -static void __devinit quirk_brcm_5719_limit_mrrs(struct pci_dev *dev) +static void quirk_brcm_5719_limit_mrrs(struct pci_dev *dev) { u32 rev; @@ -2217,7 +2217,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi); /* Go through the list of Hypertransport capabilities and * return 1 if a HT MSI capability is found and enabled */ -static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) +static int msi_ht_cap_enabled(struct pci_dev *dev) { int pos, ttl = 48; @@ -2241,7 +2241,7 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) } /* Check the hypertransport MSI mapping to know whether MSI is enabled or not */ -static void __devinit quirk_msi_ht_cap(struct pci_dev *dev) +static void quirk_msi_ht_cap(struct pci_dev *dev) { if (dev->subordinate && !msi_ht_cap_enabled(dev)) { dev_warn(&dev->dev, "MSI quirk detected; " @@ -2255,7 +2255,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2 /* The nVidia CK804 chipset may have 2 HT MSI mappings. * MSI are supported if the MSI capability set in any of these mappings. */ -static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) +static void quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) { struct pci_dev *pdev; @@ -2279,7 +2279,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_msi_ht_cap); /* Force enable MSI mapping capability on HT bridges */ -static void __devinit ht_enable_msi_mapping(struct pci_dev *dev) +static void ht_enable_msi_mapping(struct pci_dev *dev) { int pos, ttl = 48; @@ -2359,7 +2359,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4, nvbridge_check_legacy_irq_routing); -static int __devinit ht_check_msi_mapping(struct pci_dev *dev) +static int ht_check_msi_mapping(struct pci_dev *dev) { int pos, ttl = 48; int found = 0; @@ -2387,7 +2387,7 @@ static int __devinit ht_check_msi_mapping(struct pci_dev *dev) return found; } -static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge) +static int host_bridge_with_leaf(struct pci_dev *host_bridge) { struct pci_dev *dev; int pos; @@ -2421,7 +2421,7 @@ static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge) #define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */ #define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */ -static int __devinit is_end_of_ht_chain(struct pci_dev *dev) +static int is_end_of_ht_chain(struct pci_dev *dev) { int pos, ctrl_off; int end = 0; @@ -2445,7 +2445,7 @@ out: return end; } -static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) +static void nv_ht_enable_msi_mapping(struct pci_dev *dev) { struct pci_dev *host_bridge; int pos; @@ -2484,7 +2484,7 @@ out: pci_dev_put(host_bridge); } -static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) +static void ht_disable_msi_mapping(struct pci_dev *dev) { int pos, ttl = 48; @@ -2504,7 +2504,7 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) } } -static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) +static void __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) { struct pci_dev *host_bridge; int pos; @@ -2555,12 +2555,12 @@ out: pci_dev_put(host_bridge); } -static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev) +static void nv_msi_ht_cap_quirk_all(struct pci_dev *dev) { return __nv_msi_ht_cap_quirk(dev, 1); } -static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev) +static void nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev) { return __nv_msi_ht_cap_quirk(dev, 0); } -- GitLab From bbffe435248444065bd76141c41bbe65db950cc9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 6 Jul 2012 12:08:18 -0600 Subject: [PATCH 2416/5711] PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too After 253d2e5498, we disable MEM and IO decoding for most devices while we size 32-bit BARs. However, we restore the original COMMAND register before we size the upper 32 bits of 64-bit BARs, so we can still cause a conflict. This patch waits to restore the original COMMAND register until we're completely finished sizing the BAR. Reference: https://lkml.org/lkml/2007/8/25/154 Acked-by: Jacob Pan Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 658ac977cb56..66b3a6ffe5a0 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -152,9 +152,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, pci_read_config_dword(dev, pos, &sz); pci_write_config_dword(dev, pos, l); - if (!dev->mmio_always_on) - pci_write_config_word(dev, PCI_COMMAND, orig_cmd); - /* * All bits set in sz means the device isn't working properly. * If the BAR isn't implemented, all bits must be 0. If it's a @@ -239,6 +236,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } out: + if (!dev->mmio_always_on) + pci_write_config_word(dev, PCI_COMMAND, orig_cmd); + return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; fail: res->flags = 0; -- GitLab From 9aac537e0e33f4e4f28b8e7472c283fb6460c650 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 9 Jul 2012 19:49:37 -0600 Subject: [PATCH 2417/5711] PCI: disable MEM decoding while updating 64-bit MEM BARs When we update 64-bit BARs, we have to perform two config writes. Between the writes, the half-written BAR value could match a MEM access intended for another device. This could result in corruption of this device (for writes) or an unexpected response machine check (for reads). To prevent this, disable MEM decoding while updating such BARs. This uses the same safety test as 253d2e5498, which disables both MEM and IO while sizing BARs, namely, we don't disable decoding for host bridge devices. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index eea85dafc763..1a0e60e265ea 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -30,6 +30,8 @@ void pci_update_resource(struct pci_dev *dev, int resno) { struct pci_bus_region region; + bool disable; + u16 cmd; u32 new, check, mask; int reg; enum pci_bar_type type; @@ -67,6 +69,18 @@ void pci_update_resource(struct pci_dev *dev, int resno) new |= PCI_ROM_ADDRESS_ENABLE; } + /* + * We can't update a 64-bit BAR atomically, so when possible, + * disable decoding so that a half-updated BAR won't conflict + * with another device. + */ + disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on; + if (disable) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_write_config_word(dev, PCI_COMMAND, + cmd & ~PCI_COMMAND_MEMORY); + } + pci_write_config_dword(dev, reg, new); pci_read_config_dword(dev, reg, &check); @@ -84,6 +98,10 @@ void pci_update_resource(struct pci_dev *dev, int resno) "(high %#08x != %#08x)\n", resno, new, check); } } + + if (disable) + pci_write_config_word(dev, PCI_COMMAND, cmd); + res->flags &= ~IORESOURCE_UNSET; dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", resno, res, (unsigned long long)region.start, -- GitLab From 2b28ae1912e5ce5bb0527e352ae6ff04e76183d1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 9 Jul 2012 13:38:57 -0600 Subject: [PATCH 2418/5711] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) 9d265124d051 and 15a260d53f7c added quirks for P2P bridges that support I/O windows that start/end at 1K boundaries, not just the 4K boundaries defined by the PCI spec. For details, see the IOBL_ADR register and the EN1K bit in the CNF register in the Intel 82870P2 (P64H2). These quirks complicate the code that reads P2P bridge windows (pci_read_bridge_io() and pci_cfg_fake_ranges()) because the bridge I/O resource is updated in the HEADER quirk, in pci_read_bridge_io(), in pci_setup_bridge(), and again in the FINAL quirk. This is confusing and makes it impossible to reassign the bridge windows after FINAL quirks are run. This patch adds support for 1K windows in the generic paths, so the HEADER quirk only has to enable this support. The FINAL quirk, which used to undo damage done by pci_setup_bridge(), is no longer needed. This removes "if (!res->start) res->start = ..." from pci_read_bridge_io(); that was part of 9d265124d051 to avoid overwriting the resource filled in by the quirk. Since pci_read_bridge_io() itself now knows about granularity, the quirk no longer updates the resource and this test is no longer needed. Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 25 ++++++++++++++----------- drivers/pci/quirks.c | 39 +-------------------------------------- drivers/pci/setup-bus.c | 11 +++++++++-- include/linux/pci.h | 1 + include/linux/pci_regs.h | 3 ++- 5 files changed, 27 insertions(+), 52 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9c5d2a992999..ef24cf765b2f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -269,15 +269,23 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) { struct pci_dev *dev = child->self; u8 io_base_lo, io_limit_lo; - unsigned long base, limit; + unsigned long io_mask, io_granularity, base, limit; struct pci_bus_region region; - struct resource *res, res2; + struct resource *res; + + io_mask = PCI_IO_RANGE_MASK; + io_granularity = 0x1000; + if (dev->io_window_1k) { + /* Support 1K I/O space granularity */ + io_mask = PCI_IO_1K_RANGE_MASK; + io_granularity = 0x400; + } res = child->resource[0]; pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); - base = (io_base_lo & PCI_IO_RANGE_MASK) << 8; - limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8; + base = (io_base_lo & io_mask) << 8; + limit = (io_limit_lo & io_mask) << 8; if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { u16 io_base_hi, io_limit_hi; @@ -289,14 +297,9 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) if (base <= limit) { res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; - res2.flags = res->flags; region.start = base; - region.end = limit + 0xfff; - pcibios_bus_to_resource(dev, &res2, ®ion); - if (!res->start) - res->start = res2.start; - if (!res->end) - res->end = res2.end; + region.end = limit + io_granularity - 1; + pcibios_bus_to_resource(dev, res, ®ion); dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); } } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a7521677541..356846bd7ffb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1938,53 +1938,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1 static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) { u16 en1k; - u8 io_base_lo, io_limit_lo; - unsigned long base, limit; - struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; pci_read_config_word(dev, 0x40, &en1k); if (en1k & 0x200) { dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n"); - - pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); - pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); - base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; - limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; - - if (base <= limit) { - res->start = base; - res->end = limit + 0x3ff; - } + dev->io_window_1k = 1; } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); -/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2 - * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge() - * in drivers/pci/setup-bus.c - */ -static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev) -{ - u16 en1k, iobl_adr, iobl_adr_1k; - struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; - - pci_read_config_word(dev, 0x40, &en1k); - - if (en1k & 0x200) { - pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr); - - iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00); - - if (iobl_adr != iobl_adr_1k) { - dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n", - iobl_adr,iobl_adr_1k); - pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k); - } - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl); - /* Under some circumstances, AER is not linked with extended capabilities. * Force it to be linked by setting the corresponding control bit in the * config space. diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8fa2d4be88de..dad5425f1f09 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -469,16 +469,23 @@ static void pci_setup_bridge_io(struct pci_bus *bus) struct pci_dev *bridge = bus->self; struct resource *res; struct pci_bus_region region; + unsigned long io_mask; + u8 io_base_lo, io_limit_lo; u32 l, io_upper16; + io_mask = PCI_IO_RANGE_MASK; + if (bridge->io_window_1k) + io_mask = PCI_IO_1K_RANGE_MASK; + /* Set up the top and bottom of the PCI I/O segment for this bus. */ res = bus->resource[0]; pcibios_resource_to_bus(bridge, ®ion, res); if (res->flags & IORESOURCE_IO) { pci_read_config_dword(bridge, PCI_IO_BASE, &l); l &= 0xffff0000; - l |= (region.start >> 8) & 0x00f0; - l |= region.end & 0xf000; + io_base_lo = (region.start >> 8) & io_mask; + io_limit_lo = (region.end >> 8) & io_mask; + l |= ((u32) io_limit_lo << 8) | io_base_lo; /* Set up upper 16 bits of I/O base/limit. */ io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); dev_info(&bridge->dev, " bridge window %pR\n", res); diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..89b46fd245c6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -324,6 +324,7 @@ struct pci_dev { unsigned int is_hotplug_bridge:1; unsigned int __aer_firmware_first_valid:1; unsigned int __aer_firmware_first:1; + unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */ pci_dev_flags_t dev_flags; atomic_t enable_cnt; /* pci_enable_device has been called */ diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 4b608f543412..88c9ea56e252 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -125,7 +125,8 @@ #define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */ #define PCI_IO_RANGE_TYPE_16 0x00 #define PCI_IO_RANGE_TYPE_32 0x01 -#define PCI_IO_RANGE_MASK (~0x0fUL) +#define PCI_IO_RANGE_MASK (~0x0fUL) /* Standard 4K I/O windows */ +#define PCI_IO_1K_RANGE_MASK (~0x03UL) /* Intel 1K I/O windows */ #define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ #define PCI_MEMORY_BASE 0x20 /* Memory range behind */ #define PCI_MEMORY_LIMIT 0x22 -- GitLab From fd591341102ba5eb9e517d3889e7566fa45e021e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 9 Jul 2012 19:55:29 -0600 Subject: [PATCH 2419/5711] PCI: support sizing P2P bridge I/O windows with 1K granularity Some bridges support I/O windows with 1K alignment, not just the 4K alignment defined by the PCI spec. For example, see the IOBL_ADR register and the EN1K bit in the CNF register in the Intel 82870P2 (P64H2). This patch adds support for sizing the window in 1K increments based on the requirements of downstream devices. [bhelgaas: changelog, comment] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index dad5425f1f09..eb0293e23e48 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -706,7 +706,7 @@ static resource_size_t calculate_memsize(resource_size_t size, * @realloc_head : track the additional io window on this list * * Sizing the IO windows of the PCI-PCI bridge is trivial, - * since these windows have 4K granularity and the IO ranges + * since these windows have 1K or 4K granularity and the IO ranges * of non-bridge PCI devices are limited to 256 bytes. * We must be careful with the ISA aliasing though. */ @@ -717,10 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); unsigned long size = 0, size0 = 0, size1 = 0; resource_size_t children_add_size = 0; + resource_size_t min_align = 4096, align; if (!b_res) return; + /* + * Per spec, I/O windows are 4K-aligned, but some bridges have an + * extension to support 1K alignment. + */ + if (bus->self->io_window_1k) + min_align = 1024; list_for_each_entry(dev, &bus->devices, bus_list) { int i; @@ -738,17 +745,25 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, else size1 += r_size; + align = pci_resource_alignment(dev, r); + if (align > min_align) + min_align = align; + if (realloc_head) children_add_size += get_res_add_size(realloc_head, r); } } + + if (min_align > 4096) + min_align = 4096; + size0 = calculate_iosize(size, min_size, size1, - resource_size(b_res), 4096); + resource_size(b_res), min_align); if (children_add_size > add_size) add_size = children_add_size; size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 : calculate_iosize(size, min_size, add_size + size1, - resource_size(b_res), 4096); + resource_size(b_res), min_align); if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window " @@ -757,12 +772,13 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, b_res->flags = 0; return; } - /* Alignment of the IO window is always 4K */ - b_res->start = 4096; + + b_res->start = min_align; b_res->end = b_res->start + size0 - 1; b_res->flags |= IORESOURCE_STARTALIGN; if (size1 > size0 && realloc_head) { - add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); + add_to_list(realloc_head, bus->self, b_res, size1-size0, + min_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " "%pR to [bus %02x-%02x] add_size %lx\n", b_res, bus->secondary, bus->subordinate, size1-size0); -- GitLab From 02d4b36bf0022a17f20c3a79b3d94a14dbd6da3a Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:27 -0600 Subject: [PATCH 2420/5711] MIPS/PCI: move final fixups from __init to __devinit Final fixups are executed during device enumeration. If we support hotplug, this may be after boot, so final fixups cannot be __init. [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/mips/mti-malta/malta-pci.c | 2 +- arch/mips/pci/ops-tx4927.c | 2 +- arch/mips/txx9/generic/pci.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/mti-malta/malta-pci.c b/arch/mips/mti-malta/malta-pci.c index bf80921f2f56..b6634025d67c 100644 --- a/arch/mips/mti-malta/malta-pci.c +++ b/arch/mips/mti-malta/malta-pci.c @@ -253,7 +253,7 @@ void __init mips_pcibios_init(void) } /* Enable PCI 2.1 compatibility in PIIX4 */ -static void __init quirk_dlcsetup(struct pci_dev *dev) +static void __devinit quirk_dlcsetup(struct pci_dev *dev) { u8 odlc, ndlc; (void) pci_read_config_byte(dev, 0x82, &odlc); diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index a1e7e6d80c8c..bc13e29d2bb3 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -495,7 +495,7 @@ irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id) } #ifdef CONFIG_TOSHIBA_FPCIB0 -static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) +static void __devinit tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) { struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus); diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index 682efb0c108d..ce1ee5088a03 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -256,7 +256,7 @@ static irqreturn_t i8259_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init +static int __devinit txx9_i8259_irq_setup(int irq) { int err; @@ -269,7 +269,7 @@ txx9_i8259_irq_setup(int irq) return err; } -static void __init quirk_slc90e66_bridge(struct pci_dev *dev) +static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev) { int irq; /* PCI/ISA Bridge interrupt */ u8 reg_64; -- GitLab From ce6ed7e7f7e12af1a08cc32ad33d1b3202fede64 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:33 -0600 Subject: [PATCH 2421/5711] x86/PCI: move final fixups from __init to __devinit Final fixups are executed during device enumeration. If we support hotplug, this may be after boot, so final fixups cannot be __init. [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/x86/kernel/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 03920a15a632..1b27de563561 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -512,7 +512,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) /* Set correct numa_node information for AMD NB functions */ -static void __init quirk_amd_nb_node(struct pci_dev *dev) +static void __devinit quirk_amd_nb_node(struct pci_dev *dev) { struct pci_dev *nb_ht; unsigned int devfn; -- GitLab From 3274c8eb26896fc4cae3b199de71e985e20771a9 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:39 -0600 Subject: [PATCH 2422/5711] PCI: move final fixups from __init to __devinit Final fixups are executed during device enumeration. If we support hotplug, this may be after boot, so final fixups cannot be __init. [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5b8b840f1a99..4565f4ff8ae3 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx) * workaround applied too * [Info kindly provided by ALi] */ -static void __init quirk_alimagik(struct pci_dev *dev) +static void __devinit quirk_alimagik(struct pci_dev *dev) { if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) { dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n"); @@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic); -static void __init quirk_ioapic_rmw(struct pci_dev *dev) +static void __devinit quirk_ioapic_rmw(struct pci_dev *dev) { if (dev->devfn == 0 && dev->bus->number == 0) sis_apic_bug = 1; @@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw); * Some settings of MMRBC can lead to data corruption so block changes. * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide */ -static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev) +static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev) { if (dev->subordinate && dev->revision <= 0x12) { dev_info(&dev->dev, "AMD8131 rev %x detected; " @@ -2169,7 +2169,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); * aware of it. Instead of setting the flag on all busses in the * machine, simply disable MSI globally. */ -static void __init quirk_disable_all_msi(struct pci_dev *dev) +static void __devinit quirk_disable_all_msi(struct pci_dev *dev) { pci_no_msi(); dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n"); -- GitLab From 735bff10c157fdbba2291e10ca3e28a59c7acc1c Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 9 Jul 2012 15:36:46 -0600 Subject: [PATCH 2423/5711] PCI: call final fixups hot-added devices Final fixups are currently applied only at boot-time by pci_apply_final_quirks(), which is an fs_initcall(). Hot-added devices don't get these fixups, so they may not be completely initialized. This patch makes us run final fixups for hot-added devices in pci_bus_add_device() just before the new device becomes eligible for driver binding. This patch keeps the fs_initcall() for devices present at boot because we do resource assignment between pci_bus_add_device and the fs_initcall(), and we don't want to break any fixups that depend on that assignment. This is a design issue that may be addressed in the future -- any resource assignment should be done *before* device_add(). [bhelgaas: changelog] Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- drivers/pci/bus.c | 4 ++++ drivers/pci/quirks.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 4ce5ef2f2826..b511bd4e3f7c 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -164,6 +164,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, int pci_bus_add_device(struct pci_dev *dev) { int retval; + extern bool pci_fixup_final_inited; + + if (pci_fixup_final_inited) + pci_fixup_device(pci_fixup_final, dev); retval = device_add(&dev->dev); if (retval) return retval; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4565f4ff8ae3..d8e9a0edf93c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3028,6 +3028,22 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) } EXPORT_SYMBOL(pci_fixup_device); + +/* + * The global variable 'pci_fixup_final_inited' is being used as a interim + * solution for calling the final quirks only during hot-plug events (not + * during boot processing). + * + * When the boot path's PCI device setup sequencing is addressed, we can + * remove the instance, and usages of, 'pci_fixup_final_inited' along with + * removing 'fs_initcall_sync(pci_apply_final_quirks);' and end up with a + * single, uniform, solution that satisfies both the boot path and the + * various hot-plug event paths. + * + * ToDo: Remove 'pci_fixup_final_inited' + */ +bool pci_fixup_final_inited; + static int __init pci_apply_final_quirks(void) { struct pci_dev *dev = NULL; @@ -3058,6 +3074,8 @@ static int __init pci_apply_final_quirks(void) pci_cache_line_size = pci_dfl_cache_line_size; } } + pci_fixup_final_inited = 1; + if (!pci_cache_line_size) { printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", cls << 2, pci_dfl_cache_line_size << 2); -- GitLab From 8c88ab040115430fc146df7aa5a57538bf6d0e2d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 8 Jul 2012 13:11:43 +0200 Subject: [PATCH 2424/5711] i2c: imx: make bitrate an u32 type sparse found this assignment of u32 to an int. Fix it: drivers/i2c/busses/i2c-imx.c:540:56: warning: incorrect type in argument 3 (different signedness) and also fix the type in platform_data. All current users use values which fit into the old and new type, so it is a safe change. Signed-off-by: Wolfram Sang Reviewed-by: Richard Zhao Acked-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/i2c.h | 2 +- drivers/i2c/busses/i2c-imx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/i2c.h b/arch/arm/plat-mxc/include/mach/i2c.h index 375cdd0cf876..8289d915e615 100644 --- a/arch/arm/plat-mxc/include/mach/i2c.h +++ b/arch/arm/plat-mxc/include/mach/i2c.h @@ -15,7 +15,7 @@ * **/ struct imxi2c_platform_data { - int bitrate; + u32 bitrate; }; #endif /* __ASM_ARCH_I2C_H_ */ diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dd2a0839b266..90460dd5e5ab 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -471,8 +471,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imxi2c_platform_data *pdata = pdev->dev.platform_data; struct pinctrl *pinctrl; void __iomem *base; - int irq, bitrate; - int ret; + int irq, ret; + u32 bitrate; dev_dbg(&pdev->dev, "<%s>\n", __func__); -- GitLab From 2984fc0093268cfffd39725a70078396c5fdef2a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Jul 2012 22:29:00 +0800 Subject: [PATCH 2425/5711] mfd: Guard max77686_pmic_dt_match with CONFIG_OF This fixes below build warning if CONFIG_OF is not set. CC drivers/mfd/max77686.o drivers/mfd/max77686.c:37:42: warning: 'max77686_pmic_dt_match' defined but not used [-Wunused-variable] Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 3e31d05906b2..c03e12b51924 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -34,11 +34,6 @@ #define I2C_ADDR_RTC (0x0C >> 1) -static struct of_device_id __devinitdata max77686_pmic_dt_match[] = { - {.compatible = "maxim,max77686", .data = 0}, - {}, -}; - static struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, { .name = "max77686-rtc", }, @@ -50,6 +45,11 @@ static struct regmap_config max77686_regmap_config = { }; #ifdef CONFIG_OF +static struct of_device_id __devinitdata max77686_pmic_dt_match[] = { + {.compatible = "maxim,max77686", .data = 0}, + {}, +}; + static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device *dev) { -- GitLab From 78a73e59db21b465fe60e795a0b7eadb0451370b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Jul 2012 22:44:21 +0800 Subject: [PATCH 2426/5711] mfd: Export pm80x_regmap_config This fixes below build error when CONFIG_MFD_88PM800=m. ERROR: "pm80x_regmap_config" [drivers/mfd/88pm800.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm80x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index 77b865594c29..62da342553bd 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -29,6 +29,7 @@ const struct regmap_config pm80x_regmap_config = { .reg_bits = 8, .val_bits = 8, }; +EXPORT_SYMBOL_GPL(pm80x_regmap_config); int __devinit pm80x_init(struct i2c_client *client, const struct i2c_device_id *id) -- GitLab From 2a51da04fef56ec83f790bf0746e90fe40215a92 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 19:33:14 +0100 Subject: [PATCH 2427/5711] mfd: Add support for multiple arizona PDM speaker outputs The registers have stride 2 so we can write the loop properly now. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/arizona-core.c | 5 ++--- include/linux/mfd/arizona/pdata.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index ffa011f4677e..b35680dcd8c1 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -462,18 +462,17 @@ int __devinit arizona_dev_init(struct arizona *arizona) ARIZONA_OUT1_MONO, val); } - BUILD_BUG_ON(ARIZONA_MAX_PDM_SPK > 1); for (i = 0; i < ARIZONA_MAX_PDM_SPK; i++) { if (arizona->pdata.spk_mute[i]) regmap_update_bits(arizona->regmap, - ARIZONA_PDM_SPK1_CTRL_1, + ARIZONA_PDM_SPK1_CTRL_1 + (i * 2), ARIZONA_SPK1_MUTE_ENDIAN_MASK | ARIZONA_SPK1_MUTE_SEQ1_MASK, arizona->pdata.spk_mute[i]); if (arizona->pdata.spk_fmt[i]) regmap_update_bits(arizona->regmap, - ARIZONA_PDM_SPK1_CTRL_2, + ARIZONA_PDM_SPK1_CTRL_2 + (i * 2), ARIZONA_SPK1_FMT_MASK, arizona->pdata.spk_fmt[i]); } diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index fa2cb9885d62..68ff91aa3888 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h @@ -62,7 +62,7 @@ #define ARIZONA_MAX_OUTPUT 5 -#define ARIZONA_MAX_PDM_SPK 1 +#define ARIZONA_MAX_PDM_SPK 2 struct regulator_init_data; -- GitLab From 1faedca9c7bfd3055204b9d10017ce77ad03fc72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 19:33:15 +0100 Subject: [PATCH 2428/5711] mfd: Add even more arizona register definitions A few more registers used on newer devices. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- include/linux/mfd/arizona/registers.h | 211 +++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 1 deletion(-) diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index 8f49106d7bda..7671a287dfee 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -145,7 +145,7 @@ #define ARIZONA_IN3R_CONTROL 0x324 #define ARIZONA_ADC_DIGITAL_VOLUME_3R 0x325 #define ARIZONA_DMIC3R_CONTROL 0x326 -#define ARIZONA_IN4_CONTROL 0x328 +#define ARIZONA_IN4L_CONTROL 0x328 #define ARIZONA_ADC_DIGITAL_VOLUME_4L 0x329 #define ARIZONA_DMIC4L_CONTROL 0x32A #define ARIZONA_ADC_DIGITAL_VOLUME_4R 0x32D @@ -2129,6 +2129,14 @@ /* * R768 (0x300) - Input Enables */ +#define ARIZONA_IN4L_ENA 0x0080 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_MASK 0x0080 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_SHIFT 7 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_WIDTH 1 /* IN4L_ENA */ +#define ARIZONA_IN4R_ENA 0x0040 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_MASK 0x0040 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_SHIFT 6 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_WIDTH 1 /* IN4R_ENA */ #define ARIZONA_IN3L_ENA 0x0020 /* IN3L_ENA */ #define ARIZONA_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */ #define ARIZONA_IN3L_ENA_SHIFT 5 /* IN3L_ENA */ @@ -2372,9 +2380,71 @@ #define ARIZONA_IN3_DMICR_DLY_SHIFT 0 /* IN3_DMICR_DLY - [5:0] */ #define ARIZONA_IN3_DMICR_DLY_WIDTH 6 /* IN3_DMICR_DLY - [5:0] */ +/* + * R808 (0x328) - IN4 Control + */ +#define ARIZONA_IN4_OSR_MASK 0x6000 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_OSR_SHIFT 13 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_OSR_WIDTH 2 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_DMIC_SUP_MASK 0x1800 /* IN4_DMIC_SUP - [12:11] */ +#define ARIZONA_IN4_DMIC_SUP_SHIFT 11 /* IN4_DMIC_SUP - [12:11] */ +#define ARIZONA_IN4_DMIC_SUP_WIDTH 2 /* IN4_DMIC_SUP - [12:11] */ + +/* + * R809 (0x329) - ADC Digital Volume 4L + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN4L_MUTE 0x0100 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_MASK 0x0100 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_SHIFT 8 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_WIDTH 1 /* IN4L_MUTE */ +#define ARIZONA_IN4L_DIG_VOL_MASK 0x00FF /* IN4L_DIG_VOL - [7:0] */ +#define ARIZONA_IN4L_DIG_VOL_SHIFT 0 /* IN4L_DIG_VOL - [7:0] */ +#define ARIZONA_IN4L_DIG_VOL_WIDTH 8 /* IN4L_DIG_VOL - [7:0] */ + +/* + * R810 (0x32A) - DMIC4L Control + */ +#define ARIZONA_IN4L_DMIC_DLY_MASK 0x003F /* IN4L_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4L_DMIC_DLY_SHIFT 0 /* IN4L_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4L_DMIC_DLY_WIDTH 6 /* IN4L_DMIC_DLY - [5:0] */ + +/* + * R813 (0x32D) - ADC Digital Volume 4R + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN4R_MUTE 0x0100 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_MASK 0x0100 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_SHIFT 8 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_WIDTH 1 /* IN4R_MUTE */ +#define ARIZONA_IN4R_DIG_VOL_MASK 0x00FF /* IN4R_DIG_VOL - [7:0] */ +#define ARIZONA_IN4R_DIG_VOL_SHIFT 0 /* IN4R_DIG_VOL - [7:0] */ +#define ARIZONA_IN4R_DIG_VOL_WIDTH 8 /* IN4R_DIG_VOL - [7:0] */ + +/* + * R814 (0x32E) - DMIC4R Control + */ +#define ARIZONA_IN4R_DMIC_DLY_MASK 0x003F /* IN4R_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4R_DMIC_DLY_SHIFT 0 /* IN4R_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4R_DMIC_DLY_WIDTH 6 /* IN4R_DMIC_DLY - [5:0] */ + /* * R1024 (0x400) - Output Enables 1 */ +#define ARIZONA_OUT6L_ENA 0x0800 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_MASK 0x0800 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_SHIFT 11 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_WIDTH 1 /* OUT6L_ENA */ +#define ARIZONA_OUT6R_ENA 0x0400 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_MASK 0x0400 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_SHIFT 10 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_WIDTH 1 /* OUT6R_ENA */ #define ARIZONA_OUT5L_ENA 0x0200 /* OUT5L_ENA */ #define ARIZONA_OUT5L_ENA_MASK 0x0200 /* OUT5L_ENA */ #define ARIZONA_OUT5L_ENA_SHIFT 9 /* OUT5L_ENA */ @@ -2876,6 +2946,82 @@ #define ARIZONA_OUT5R_NGATE_SRC_SHIFT 0 /* OUT5R_NGATE_SRC - [11:0] */ #define ARIZONA_OUT5R_NGATE_SRC_WIDTH 12 /* OUT5R_NGATE_SRC - [11:0] */ +/* + * R1080 (0x438) - Output Path Config 6L + */ +#define ARIZONA_OUT6_OSR 0x2000 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_MASK 0x2000 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_SHIFT 13 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_WIDTH 1 /* OUT6_OSR */ +#define ARIZONA_OUT6L_ANC_SRC_MASK 0x0C00 /* OUT6L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6L_ANC_SRC_SHIFT 10 /* OUT6L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6L_ANC_SRC_WIDTH 2 /* OUT6L_ANC_SRC - [11:10] */ + +/* + * R1081 (0x439) - DAC Digital Volume 6L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT6L_MUTE 0x0100 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_MASK 0x0100 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_SHIFT 8 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_WIDTH 1 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_VOL_MASK 0x00FF /* OUT6L_VOL - [7:0] */ +#define ARIZONA_OUT6L_VOL_SHIFT 0 /* OUT6L_VOL - [7:0] */ +#define ARIZONA_OUT6L_VOL_WIDTH 8 /* OUT6L_VOL - [7:0] */ + +/* + * R1082 (0x43A) - DAC Volume Limit 6L + */ +#define ARIZONA_OUT6L_VOL_LIM_MASK 0x00FF /* OUT6L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6L_VOL_LIM_SHIFT 0 /* OUT6L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6L_VOL_LIM_WIDTH 8 /* OUT6L_VOL_LIM - [7:0] */ + +/* + * R1083 (0x43B) - Noise Gate Select 6L + */ +#define ARIZONA_OUT6L_NGATE_SRC_MASK 0x0FFF /* OUT6L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6L_NGATE_SRC_SHIFT 0 /* OUT6L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6L_NGATE_SRC_WIDTH 12 /* OUT6L_NGATE_SRC - [11:0] */ + +/* + * R1084 (0x43C) - Output Path Config 6R + */ +#define ARIZONA_OUT6R_ANC_SRC_MASK 0x0C00 /* OUT6R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6R_ANC_SRC_SHIFT 10 /* OUT6R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6R_ANC_SRC_WIDTH 2 /* OUT6R_ANC_SRC - [11:10] */ + +/* + * R1085 (0x43D) - DAC Digital Volume 6R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT6R_MUTE 0x0100 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_MASK 0x0100 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_SHIFT 8 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_WIDTH 1 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_VOL_MASK 0x00FF /* OUT6R_VOL - [7:0] */ +#define ARIZONA_OUT6R_VOL_SHIFT 0 /* OUT6R_VOL - [7:0] */ +#define ARIZONA_OUT6R_VOL_WIDTH 8 /* OUT6R_VOL - [7:0] */ + +/* + * R1086 (0x43E) - DAC Volume Limit 6R + */ +#define ARIZONA_OUT6R_VOL_LIM_MASK 0x00FF /* OUT6R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6R_VOL_LIM_SHIFT 0 /* OUT6R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6R_VOL_LIM_WIDTH 8 /* OUT6R_VOL_LIM - [7:0] */ + +/* + * R1087 (0x43F) - Noise Gate Select 6R + */ +#define ARIZONA_OUT6R_NGATE_SRC_MASK 0x0FFF /* OUT6R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6R_NGATE_SRC_SHIFT 0 /* OUT6R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6R_NGATE_SRC_WIDTH 12 /* OUT6R_NGATE_SRC - [11:0] */ + /* * R1104 (0x450) - DAC AEC Control 1 */ @@ -2932,6 +3078,33 @@ #define ARIZONA_SPK1_FMT_SHIFT 0 /* SPK1_FMT */ #define ARIZONA_SPK1_FMT_WIDTH 1 /* SPK1_FMT */ +/* + * R1170 (0x492) - PDM SPK2 CTRL 1 + */ +#define ARIZONA_SPK2R_MUTE 0x2000 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_MASK 0x2000 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_SHIFT 13 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */ +#define ARIZONA_SPK2L_MUTE 0x1000 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_MASK 0x1000 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_SHIFT 12 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */ +#define ARIZONA_SPK2_MUTE_ENDIAN 0x0100 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_MASK 0x0100 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_SHIFT 8 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_WIDTH 1 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_SEQ_MASK 0x00FF /* SPK2_MUTE_SEQ - [7:0] */ +#define ARIZONA_SPK2_MUTE_SEQ_SHIFT 0 /* SPK2_MUTE_SEQ - [7:0] */ +#define ARIZONA_SPK2_MUTE_SEQ_WIDTH 8 /* SPK2_MUTE_SEQ - [7:0] */ + +/* + * R1171 (0x493) - PDM SPK2 CTRL 2 + */ +#define ARIZONA_SPK2_FMT 0x0001 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_MASK 0x0001 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_SHIFT 0 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_WIDTH 1 /* SPK2_FMT */ + /* * R1244 (0x4DC) - DAC comp 1 */ @@ -4028,10 +4201,46 @@ /* * R3329 (0xD01) - Interrupt Status 2 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1 0x0800 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_MASK 0x0800 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_SHIFT 11 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_WIDTH 1 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1 0x0400 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_MASK 0x0400 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_SHIFT 10 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_WIDTH 1 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1 0x0200 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_MASK 0x0200 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_SHIFT 9 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_WIDTH 1 /* DSP2_RAM_RDY_EINT1 */ #define ARIZONA_DSP1_RAM_RDY_EINT1 0x0100 /* DSP1_RAM_RDY_EINT1 */ #define ARIZONA_DSP1_RAM_RDY_EINT1_MASK 0x0100 /* DSP1_RAM_RDY_EINT1 */ #define ARIZONA_DSP1_RAM_RDY_EINT1_SHIFT 8 /* DSP1_RAM_RDY_EINT1 */ #define ARIZONA_DSP1_RAM_RDY_EINT1_WIDTH 1 /* DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1 0x0080 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_MASK 0x0080 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_SHIFT 7 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_WIDTH 1 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1 0x0040 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_MASK 0x0040 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_SHIFT 6 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_WIDTH 1 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1 0x0020 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_MASK 0x0020 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_SHIFT 5 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_WIDTH 1 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1 0x0010 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_MASK 0x0010 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_SHIFT 4 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_WIDTH 1 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1 0x0008 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_MASK 0x0008 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_SHIFT 3 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_WIDTH 1 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1 0x0004 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_MASK 0x0004 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_SHIFT 2 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_WIDTH 1 /* DSP_IRQ3_EINT1 */ #define ARIZONA_DSP_IRQ2_EINT1 0x0002 /* DSP_IRQ2_EINT1 */ #define ARIZONA_DSP_IRQ2_EINT1_MASK 0x0002 /* DSP_IRQ2_EINT1 */ #define ARIZONA_DSP_IRQ2_EINT1_SHIFT 1 /* DSP_IRQ2_EINT1 */ -- GitLab From 0f307323a48e47f064aa38e87f6fa03c88b551fc Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Sat, 7 Jul 2012 10:51:56 +0800 Subject: [PATCH 2429/5711] netprio_cgroup.c: fix comment typo poitner -> pointer. Signed-off-by: Liu Bo Signed-off-by: Jiri Kosina --- net/core/netprio_cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 5b8aa2fae48b..e13ad4946565 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -198,7 +198,7 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, /* *Separate the devname from the associated priority - *and advance the priostr poitner to the priority value + *and advance the priostr pointer to the priority value */ *priostr = '\0'; priostr++; -- GitLab From cf5388307a2b4faab4b11d732b61c85741be6169 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 4 Jul 2012 15:42:48 +0200 Subject: [PATCH 2430/5711] Btrfs: fix buffer leak in btrfs_next_old_leaf When calling btrfs_next_old_leaf, we were leaking an extent buffer in the rare case of using the deadlock avoidance code needed for the tree mod log. Signed-off-by: Jan Schmidt --- fs/btrfs/ctree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 8206b3900587..67fe46fdee6f 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -5127,6 +5127,7 @@ again: * locked. To solve this situation, we give up * on our lock and cycle. */ + free_extent_buffer(next); btrfs_release_path(path); cond_resched(); goto again; -- GitLab From 097b8a7c9e48e2cb50fd0eb9315791921beaf484 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 21 Jun 2012 11:08:04 +0200 Subject: [PATCH 2431/5711] Btrfs: join tree mod log code with the code holding back delayed refs We've got two mechanisms both required for reliable backref resolving (tree mod log and holding back delayed refs). You cannot make use of one without the other. So instead of requiring the user of this mechanism to setup both correctly, we join them into a single interface. Additionally, we stop inserting non-blockers into fs_info->tree_mod_seq_list as we did before, which was of no value. Signed-off-by: Jan Schmidt --- fs/btrfs/backref.c | 30 ++--- fs/btrfs/backref.h | 3 +- fs/btrfs/ctree.c | 275 +++++++++++++++++++++++++---------------- fs/btrfs/ctree.h | 31 +++-- fs/btrfs/delayed-ref.c | 44 ++++--- fs/btrfs/delayed-ref.h | 49 +------- fs/btrfs/disk-io.c | 2 + fs/btrfs/extent-tree.c | 21 ++-- fs/btrfs/transaction.c | 4 - 9 files changed, 240 insertions(+), 219 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index a383c18e74e8..7d80ddd8f544 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -773,9 +773,8 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, */ static int find_parent_nodes(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 bytenr, - u64 delayed_ref_seq, u64 time_seq, - struct ulist *refs, struct ulist *roots, - const u64 *extent_item_pos) + u64 time_seq, struct ulist *refs, + struct ulist *roots, const u64 *extent_item_pos) { struct btrfs_key key; struct btrfs_path *path; @@ -837,7 +836,7 @@ again: btrfs_put_delayed_ref(&head->node); goto again; } - ret = __add_delayed_refs(head, delayed_ref_seq, + ret = __add_delayed_refs(head, time_seq, &prefs_delayed); mutex_unlock(&head->mutex); if (ret) { @@ -981,8 +980,7 @@ static void free_leaf_list(struct ulist *blocks) */ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 bytenr, - u64 delayed_ref_seq, u64 time_seq, - struct ulist **leafs, + u64 time_seq, struct ulist **leafs, const u64 *extent_item_pos) { struct ulist *tmp; @@ -997,7 +995,7 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, return -ENOMEM; } - ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, + ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, *leafs, tmp, extent_item_pos); ulist_free(tmp); @@ -1024,8 +1022,7 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, */ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 bytenr, - u64 delayed_ref_seq, u64 time_seq, - struct ulist **roots) + u64 time_seq, struct ulist **roots) { struct ulist *tmp; struct ulist_node *node = NULL; @@ -1043,7 +1040,7 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, ULIST_ITER_INIT(&uiter); while (1) { - ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, + ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, tmp, *roots, NULL); if (ret < 0 && ret != -ENOENT) { ulist_free(tmp); @@ -1376,11 +1373,9 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, struct ulist *roots = NULL; struct ulist_node *ref_node = NULL; struct ulist_node *root_node = NULL; - struct seq_list seq_elem = {}; struct seq_list tree_mod_seq_elem = {}; struct ulist_iterator ref_uiter; struct ulist_iterator root_uiter; - struct btrfs_delayed_ref_root *delayed_refs = NULL; pr_debug("resolving all inodes for extent %llu\n", extent_item_objectid); @@ -1391,16 +1386,11 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, trans = btrfs_join_transaction(fs_info->extent_root); if (IS_ERR(trans)) return PTR_ERR(trans); - - delayed_refs = &trans->transaction->delayed_refs; - spin_lock(&delayed_refs->lock); - btrfs_get_delayed_seq(delayed_refs, &seq_elem); - spin_unlock(&delayed_refs->lock); btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); } ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, - seq_elem.seq, tree_mod_seq_elem.seq, &refs, + tree_mod_seq_elem.seq, &refs, &extent_item_pos); if (ret) goto out; @@ -1408,8 +1398,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, ULIST_ITER_INIT(&ref_uiter); while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, - seq_elem.seq, - tree_mod_seq_elem.seq, &roots); + tree_mod_seq_elem.seq, &roots); if (ret) break; ULIST_ITER_INIT(&root_uiter); @@ -1431,7 +1420,6 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, out: if (!search_commit_root) { btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); - btrfs_put_delayed_seq(delayed_refs, &seq_elem); btrfs_end_transaction(trans, fs_info->extent_root); } diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index c18d8ac7b795..3a1ad3e2dcb0 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -58,8 +58,7 @@ int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); int btrfs_find_all_roots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 bytenr, - u64 delayed_ref_seq, u64 time_seq, - struct ulist **roots); + u64 time_seq, struct ulist **roots); struct btrfs_data_container *init_data_container(u32 total_bytes); struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 67fe46fdee6f..bef68ab32204 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -321,7 +321,7 @@ struct tree_mod_root { struct tree_mod_elem { struct rb_node node; u64 index; /* shifted logical */ - struct seq_list elem; + u64 seq; enum mod_log_op op; /* this is used for MOD_LOG_KEY_* and MOD_LOG_MOVE_KEYS operations */ @@ -341,20 +341,50 @@ struct tree_mod_elem { struct tree_mod_root old_root; }; -static inline void -__get_tree_mod_seq(struct btrfs_fs_info *fs_info, struct seq_list *elem) +static inline void tree_mod_log_read_lock(struct btrfs_fs_info *fs_info) { - elem->seq = atomic_inc_return(&fs_info->tree_mod_seq); - list_add_tail(&elem->list, &fs_info->tree_mod_seq_list); + read_lock(&fs_info->tree_mod_log_lock); } -void btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, - struct seq_list *elem) +static inline void tree_mod_log_read_unlock(struct btrfs_fs_info *fs_info) +{ + read_unlock(&fs_info->tree_mod_log_lock); +} + +static inline void tree_mod_log_write_lock(struct btrfs_fs_info *fs_info) +{ + write_lock(&fs_info->tree_mod_log_lock); +} + +static inline void tree_mod_log_write_unlock(struct btrfs_fs_info *fs_info) { - elem->flags = 1; + write_unlock(&fs_info->tree_mod_log_lock); +} + +/* + * This adds a new blocker to the tree mod log's blocker list if the @elem + * passed does not already have a sequence number set. So when a caller expects + * to record tree modifications, it should ensure to set elem->seq to zero + * before calling btrfs_get_tree_mod_seq. + * Returns a fresh, unused tree log modification sequence number, even if no new + * blocker was added. + */ +u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, + struct seq_list *elem) +{ + u64 seq; + + tree_mod_log_write_lock(fs_info); spin_lock(&fs_info->tree_mod_seq_lock); - __get_tree_mod_seq(fs_info, elem); + if (!elem->seq) { + elem->seq = btrfs_inc_tree_mod_seq(fs_info); + list_add_tail(&elem->list, &fs_info->tree_mod_seq_list); + } + seq = btrfs_inc_tree_mod_seq(fs_info); spin_unlock(&fs_info->tree_mod_seq_lock); + tree_mod_log_write_unlock(fs_info); + + return seq; } void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, @@ -371,41 +401,46 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, if (!seq_putting) return; - BUG_ON(!(elem->flags & 1)); spin_lock(&fs_info->tree_mod_seq_lock); list_del(&elem->list); + elem->seq = 0; list_for_each_entry(cur_elem, &fs_info->tree_mod_seq_list, list) { - if ((cur_elem->flags & 1) && cur_elem->seq < min_seq) { + if (cur_elem->seq < min_seq) { if (seq_putting > cur_elem->seq) { /* * blocker with lower sequence number exists, we * cannot remove anything from the log */ - goto out; + spin_unlock(&fs_info->tree_mod_seq_lock); + return; } min_seq = cur_elem->seq; } } + spin_unlock(&fs_info->tree_mod_seq_lock); + + /* + * we removed the lowest blocker from the blocker list, so there may be + * more processible delayed refs. + */ + wake_up(&fs_info->tree_mod_seq_wait); /* * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. */ - write_lock(&fs_info->tree_mod_log_lock); + tree_mod_log_write_lock(fs_info); tm_root = &fs_info->tree_mod_log; for (node = rb_first(tm_root); node; node = next) { next = rb_next(node); tm = container_of(node, struct tree_mod_elem, node); - if (tm->elem.seq > min_seq) + if (tm->seq > min_seq) continue; rb_erase(node, tm_root); - list_del(&tm->elem.list); kfree(tm); } - write_unlock(&fs_info->tree_mod_log_lock); -out: - spin_unlock(&fs_info->tree_mod_seq_lock); + tree_mod_log_write_unlock(fs_info); } /* @@ -423,11 +458,9 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) struct rb_node **new; struct rb_node *parent = NULL; struct tree_mod_elem *cur; - int ret = 0; - BUG_ON(!tm || !tm->elem.seq); + BUG_ON(!tm || !tm->seq); - write_lock(&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log; new = &tm_root->rb_node; while (*new) { @@ -437,88 +470,81 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) new = &((*new)->rb_left); else if (cur->index > tm->index) new = &((*new)->rb_right); - else if (cur->elem.seq < tm->elem.seq) + else if (cur->seq < tm->seq) new = &((*new)->rb_left); - else if (cur->elem.seq > tm->elem.seq) + else if (cur->seq > tm->seq) new = &((*new)->rb_right); else { kfree(tm); - ret = -EEXIST; - goto unlock; + return -EEXIST; } } rb_link_node(&tm->node, parent, new); rb_insert_color(&tm->node, tm_root); -unlock: - write_unlock(&fs_info->tree_mod_log_lock); - return ret; + return 0; } +/* + * Determines if logging can be omitted. Returns 1 if it can. Otherwise, it + * returns zero with the tree_mod_log_lock acquired. The caller must hold + * this until all tree mod log insertions are recorded in the rb tree and then + * call tree_mod_log_write_unlock() to release. + */ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) { smp_mb(); if (list_empty(&(fs_info)->tree_mod_seq_list)) return 1; - if (!eb) - return 0; - if (btrfs_header_level(eb) == 0) + if (eb && btrfs_header_level(eb) == 0) return 1; + + tree_mod_log_write_lock(fs_info); + if (list_empty(&fs_info->tree_mod_seq_list)) { + /* + * someone emptied the list while we were waiting for the lock. + * we must not add to the list when no blocker exists. + */ + tree_mod_log_write_unlock(fs_info); + return 1; + } + return 0; } /* - * This allocates memory and gets a tree modification sequence number when - * needed. + * This allocates memory and gets a tree modification sequence number. * - * Returns 0 when no sequence number is needed, < 0 on error. - * Returns 1 when a sequence number was added. In this case, - * fs_info->tree_mod_seq_lock was acquired and must be released by the caller - * after inserting into the rb tree. + * Returns <0 on error. + * Returns >0 (the added sequence number) on success. */ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, struct tree_mod_elem **tm_ret) { struct tree_mod_elem *tm; - int seq; - if (tree_mod_dont_log(fs_info, NULL)) - return 0; - - tm = *tm_ret = kzalloc(sizeof(*tm), flags); + /* + * once we switch from spin locks to something different, we should + * honor the flags parameter here. + */ + tm = *tm_ret = kzalloc(sizeof(*tm), GFP_ATOMIC); if (!tm) return -ENOMEM; - tm->elem.flags = 0; - spin_lock(&fs_info->tree_mod_seq_lock); - if (list_empty(&fs_info->tree_mod_seq_list)) { - /* - * someone emptied the list while we were waiting for the lock. - * we must not add to the list, because no blocker exists. items - * are removed from the list only when the existing blocker is - * removed from the list. - */ - kfree(tm); - seq = 0; - spin_unlock(&fs_info->tree_mod_seq_lock); - } else { - __get_tree_mod_seq(fs_info, &tm->elem); - seq = tm->elem.seq; - } - - return seq; + tm->seq = btrfs_inc_tree_mod_seq(fs_info); + return tm->seq; } -static noinline int -tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb, int slot, - enum mod_log_op op, gfp_t flags) +static inline int +__tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, + struct extent_buffer *eb, int slot, + enum mod_log_op op, gfp_t flags) { - struct tree_mod_elem *tm; int ret; + struct tree_mod_elem *tm; ret = tree_mod_alloc(fs_info, flags, &tm); - if (ret <= 0) + if (ret < 0) return ret; tm->index = eb->start >> PAGE_CACHE_SHIFT; @@ -530,8 +556,22 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, tm->slot = slot; tm->generation = btrfs_node_ptr_generation(eb, slot); - ret = __tree_mod_log_insert(fs_info, tm); - spin_unlock(&fs_info->tree_mod_seq_lock); + return __tree_mod_log_insert(fs_info, tm); +} + +static noinline int +tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, + struct extent_buffer *eb, int slot, + enum mod_log_op op, gfp_t flags) +{ + int ret; + + if (tree_mod_dont_log(fs_info, eb)) + return 0; + + ret = __tree_mod_log_insert_key(fs_info, eb, slot, op, flags); + + tree_mod_log_write_unlock(fs_info); return ret; } @@ -542,6 +582,14 @@ tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, return tree_mod_log_insert_key_mask(fs_info, eb, slot, op, GFP_NOFS); } +static noinline int +tree_mod_log_insert_key_locked(struct btrfs_fs_info *fs_info, + struct extent_buffer *eb, int slot, + enum mod_log_op op) +{ + return __tree_mod_log_insert_key(fs_info, eb, slot, op, GFP_NOFS); +} + static noinline int tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, int dst_slot, int src_slot, @@ -555,14 +603,14 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, return 0; for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { - ret = tree_mod_log_insert_key(fs_info, eb, i + dst_slot, + ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, MOD_LOG_KEY_REMOVE_WHILE_MOVING); BUG_ON(ret < 0); } ret = tree_mod_alloc(fs_info, flags, &tm); - if (ret <= 0) - return ret; + if (ret < 0) + goto out; tm->index = eb->start >> PAGE_CACHE_SHIFT; tm->slot = src_slot; @@ -571,10 +619,26 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, tm->op = MOD_LOG_MOVE_KEYS; ret = __tree_mod_log_insert(fs_info, tm); - spin_unlock(&fs_info->tree_mod_seq_lock); +out: + tree_mod_log_write_unlock(fs_info); return ret; } +static inline void +__tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) +{ + int i; + u32 nritems; + int ret; + + nritems = btrfs_header_nritems(eb); + for (i = nritems - 1; i >= 0; i--) { + ret = tree_mod_log_insert_key_locked(fs_info, eb, i, + MOD_LOG_KEY_REMOVE_WHILE_FREEING); + BUG_ON(ret < 0); + } +} + static noinline int tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, struct extent_buffer *old_root, @@ -583,9 +647,14 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm; int ret; + if (tree_mod_dont_log(fs_info, NULL)) + return 0; + + __tree_mod_log_free_eb(fs_info, old_root); + ret = tree_mod_alloc(fs_info, flags, &tm); - if (ret <= 0) - return ret; + if (ret < 0) + goto out; tm->index = new_root->start >> PAGE_CACHE_SHIFT; tm->old_root.logical = old_root->start; @@ -594,7 +663,8 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, tm->op = MOD_LOG_ROOT_REPLACE; ret = __tree_mod_log_insert(fs_info, tm); - spin_unlock(&fs_info->tree_mod_seq_lock); +out: + tree_mod_log_write_unlock(fs_info); return ret; } @@ -608,7 +678,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, struct tree_mod_elem *found = NULL; u64 index = start >> PAGE_CACHE_SHIFT; - read_lock(&fs_info->tree_mod_log_lock); + tree_mod_log_read_lock(fs_info); tm_root = &fs_info->tree_mod_log; node = tm_root->rb_node; while (node) { @@ -617,18 +687,18 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, node = node->rb_left; } else if (cur->index > index) { node = node->rb_right; - } else if (cur->elem.seq < min_seq) { + } else if (cur->seq < min_seq) { node = node->rb_left; } else if (!smallest) { /* we want the node with the highest seq */ if (found) - BUG_ON(found->elem.seq > cur->elem.seq); + BUG_ON(found->seq > cur->seq); found = cur; node = node->rb_left; - } else if (cur->elem.seq > min_seq) { + } else if (cur->seq > min_seq) { /* we want the node with the smallest seq */ if (found) - BUG_ON(found->elem.seq < cur->elem.seq); + BUG_ON(found->seq < cur->seq); found = cur; node = node->rb_right; } else { @@ -636,7 +706,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, break; } } - read_unlock(&fs_info->tree_mod_log_lock); + tree_mod_log_read_unlock(fs_info); return found; } @@ -664,7 +734,7 @@ tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq) return __tree_mod_log_search(fs_info, start, min_seq, 0); } -static inline void +static noinline void tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, struct extent_buffer *src, unsigned long dst_offset, unsigned long src_offset, int nr_items) @@ -675,18 +745,23 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, if (tree_mod_dont_log(fs_info, NULL)) return; - if (btrfs_header_level(dst) == 0 && btrfs_header_level(src) == 0) + if (btrfs_header_level(dst) == 0 && btrfs_header_level(src) == 0) { + tree_mod_log_write_unlock(fs_info); return; + } - /* speed this up by single seq for all operations? */ for (i = 0; i < nr_items; i++) { - ret = tree_mod_log_insert_key(fs_info, src, i + src_offset, - MOD_LOG_KEY_REMOVE); + ret = tree_mod_log_insert_key_locked(fs_info, src, + i + src_offset, + MOD_LOG_KEY_REMOVE); BUG_ON(ret < 0); - ret = tree_mod_log_insert_key(fs_info, dst, i + dst_offset, - MOD_LOG_KEY_ADD); + ret = tree_mod_log_insert_key_locked(fs_info, dst, + i + dst_offset, + MOD_LOG_KEY_ADD); BUG_ON(ret < 0); } + + tree_mod_log_write_unlock(fs_info); } static inline void @@ -699,7 +774,7 @@ tree_mod_log_eb_move(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, BUG_ON(ret < 0); } -static inline void +static noinline void tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, struct btrfs_disk_key *disk_key, int slot, int atomic) @@ -712,30 +787,22 @@ tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, BUG_ON(ret < 0); } -static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb) +static noinline void +tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) { - int i; - int ret; - u32 nritems; - if (tree_mod_dont_log(fs_info, eb)) return; - nritems = btrfs_header_nritems(eb); - for (i = nritems - 1; i >= 0; i--) { - ret = tree_mod_log_insert_key(fs_info, eb, i, - MOD_LOG_KEY_REMOVE_WHILE_FREEING); - BUG_ON(ret < 0); - } + __tree_mod_log_free_eb(fs_info, eb); + + tree_mod_log_write_unlock(fs_info); } -static inline void +static noinline void tree_mod_log_set_root_pointer(struct btrfs_root *root, struct extent_buffer *new_root_node) { int ret; - tree_mod_log_free_eb(root->fs_info, root->node); ret = tree_mod_log_insert_root(root->fs_info, root->node, new_root_node, GFP_NOFS); BUG_ON(ret < 0); @@ -1069,7 +1136,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, unsigned long p_size = sizeof(struct btrfs_key_ptr); n = btrfs_header_nritems(eb); - while (tm && tm->elem.seq >= time_seq) { + while (tm && tm->seq >= time_seq) { /* * all the operations are recorded with the operator used for * the modification. as we're going backwards, we do the diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 84ac723f58f8..8f8dc46f44e7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1030,6 +1030,13 @@ struct btrfs_block_group_cache { struct list_head cluster_list; }; +/* delayed seq elem */ +struct seq_list { + struct list_head list; + u64 seq; +}; + +/* fs_info */ struct reloc_control; struct btrfs_device; struct btrfs_fs_devices; @@ -1144,6 +1151,8 @@ struct btrfs_fs_info { spinlock_t tree_mod_seq_lock; atomic_t tree_mod_seq; struct list_head tree_mod_seq_list; + struct seq_list tree_mod_seq_elem; + wait_queue_head_t tree_mod_seq_wait; /* this protects tree_mod_log */ rwlock_t tree_mod_log_lock; @@ -2798,6 +2807,16 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info) kfree(fs_info); } +/* tree mod log functions from ctree.c */ +u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, + struct seq_list *elem); +void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, + struct seq_list *elem); +static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) +{ + return atomic_inc_return(&fs_info->tree_mod_seq); +} + /* root-item.c */ int btrfs_find_root_ref(struct btrfs_root *tree_root, struct btrfs_path *path, @@ -3157,18 +3176,6 @@ void btrfs_reada_detach(void *handle); int btree_readahead_hook(struct btrfs_root *root, struct extent_buffer *eb, u64 start, int err); -/* delayed seq elem */ -struct seq_list { - struct list_head list; - u64 seq; - u32 flags; -}; - -void btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, - struct seq_list *elem); -void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, - struct seq_list *elem); - static inline int is_fstree(u64 rootid) { if (rootid == BTRFS_FS_TREE_OBJECTID || diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 13ae7b04790e..21a757717637 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -233,22 +233,26 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, return 0; } -int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, +int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, + struct btrfs_delayed_ref_root *delayed_refs, u64 seq) { struct seq_list *elem; - - assert_spin_locked(&delayed_refs->lock); - if (list_empty(&delayed_refs->seq_head)) - return 0; - - elem = list_first_entry(&delayed_refs->seq_head, struct seq_list, list); - if (seq >= elem->seq) { - pr_debug("holding back delayed_ref %llu, lowest is %llu (%p)\n", - seq, elem->seq, delayed_refs); - return 1; + int ret = 0; + + spin_lock(&fs_info->tree_mod_seq_lock); + if (!list_empty(&fs_info->tree_mod_seq_list)) { + elem = list_first_entry(&fs_info->tree_mod_seq_list, + struct seq_list, list); + if (seq >= elem->seq) { + pr_debug("holding back delayed_ref %llu, lowest is " + "%llu (%p)\n", seq, elem->seq, delayed_refs); + ret = 1; + } } - return 0; + + spin_unlock(&fs_info->tree_mod_seq_lock); + return ret; } int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, @@ -526,7 +530,7 @@ static noinline void add_delayed_tree_ref(struct btrfs_fs_info *fs_info, ref->in_tree = 1; if (is_fstree(ref_root)) - seq = inc_delayed_seq(delayed_refs); + seq = btrfs_inc_tree_mod_seq(fs_info); ref->seq = seq; full_ref = btrfs_delayed_node_to_tree_ref(ref); @@ -585,7 +589,7 @@ static noinline void add_delayed_data_ref(struct btrfs_fs_info *fs_info, ref->in_tree = 1; if (is_fstree(ref_root)) - seq = inc_delayed_seq(delayed_refs); + seq = btrfs_inc_tree_mod_seq(fs_info); ref->seq = seq; full_ref = btrfs_delayed_node_to_data_ref(ref); @@ -659,8 +663,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, num_bytes, parent, ref_root, level, action, for_cow); if (!is_fstree(ref_root) && - waitqueue_active(&delayed_refs->seq_wait)) - wake_up(&delayed_refs->seq_wait); + waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); return 0; @@ -708,8 +712,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, num_bytes, parent, ref_root, owner, offset, action, for_cow); if (!is_fstree(ref_root) && - waitqueue_active(&delayed_refs->seq_wait)) - wake_up(&delayed_refs->seq_wait); + waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); return 0; @@ -736,8 +740,8 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, num_bytes, BTRFS_UPDATE_DELAYED_HEAD, extent_op->is_data); - if (waitqueue_active(&delayed_refs->seq_wait)) - wake_up(&delayed_refs->seq_wait); + if (waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); return 0; } diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index 413927fb9957..2b5cb27f9861 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h @@ -139,26 +139,6 @@ struct btrfs_delayed_ref_root { int flushing; u64 run_delayed_start; - - /* - * seq number of delayed refs. We need to know if a backref was being - * added before the currently processed ref or afterwards. - */ - u64 seq; - - /* - * seq_list holds a list of all seq numbers that are currently being - * added to the list. While walking backrefs (btrfs_find_all_roots, - * qgroups), which might take some time, no newer ref must be processed, - * as it might influence the outcome of the walk. - */ - struct list_head seq_head; - - /* - * when the only refs we have in the list must not be processed, we want - * to wait for more refs to show up or for the end of backref walking. - */ - wait_queue_head_t seq_wait; }; static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) @@ -195,33 +175,8 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, struct list_head *cluster, u64 search_start); -static inline u64 inc_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs) -{ - assert_spin_locked(&delayed_refs->lock); - ++delayed_refs->seq; - return delayed_refs->seq; -} - -static inline void -btrfs_get_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, - struct seq_list *elem) -{ - assert_spin_locked(&delayed_refs->lock); - elem->seq = delayed_refs->seq; - list_add_tail(&elem->list, &delayed_refs->seq_head); -} - -static inline void -btrfs_put_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, - struct seq_list *elem) -{ - spin_lock(&delayed_refs->lock); - list_del(&elem->list); - wake_up(&delayed_refs->seq_wait); - spin_unlock(&delayed_refs->lock); -} - -int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, +int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, + struct btrfs_delayed_ref_root *delayed_refs, u64 seq); /* diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8cc47103a32e..19a39e10d6f5 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1944,6 +1944,8 @@ int open_ctree(struct super_block *sb, fs_info->free_chunk_space = 0; fs_info->tree_mod_log = RB_ROOT; + init_waitqueue_head(&fs_info->tree_mod_seq_wait); + /* readahead state */ INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); spin_lock_init(&fs_info->reada_lock); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 6e1d36702ff7..94ce79f76e5f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2217,6 +2217,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_node *ref; struct btrfs_delayed_ref_head *locked_ref = NULL; struct btrfs_delayed_extent_op *extent_op; + struct btrfs_fs_info *fs_info = root->fs_info; int ret; int count = 0; int must_insert_reserved = 0; @@ -2255,7 +2256,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, ref = select_delayed_ref(locked_ref); if (ref && ref->seq && - btrfs_check_delayed_seq(delayed_refs, ref->seq)) { + btrfs_check_delayed_seq(fs_info, delayed_refs, ref->seq)) { /* * there are still refs with lower seq numbers in the * process of being added. Don't run this ref yet. @@ -2337,7 +2338,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, } next: - do_chunk_alloc(trans, root->fs_info->extent_root, + do_chunk_alloc(trans, fs_info->extent_root, 2 * 1024 * 1024, btrfs_get_alloc_profile(root, 0), CHUNK_ALLOC_NO_FORCE); @@ -2347,18 +2348,19 @@ next: return count; } -static void wait_for_more_refs(struct btrfs_delayed_ref_root *delayed_refs, +static void wait_for_more_refs(struct btrfs_fs_info *fs_info, + struct btrfs_delayed_ref_root *delayed_refs, unsigned long num_refs, struct list_head *first_seq) { spin_unlock(&delayed_refs->lock); pr_debug("waiting for more refs (num %ld, first %p)\n", num_refs, first_seq); - wait_event(delayed_refs->seq_wait, + wait_event(fs_info->tree_mod_seq_wait, num_refs != delayed_refs->num_entries || - delayed_refs->seq_head.next != first_seq); + fs_info->tree_mod_seq_list.next != first_seq); pr_debug("done waiting for more refs (num %ld, first %p)\n", - delayed_refs->num_entries, delayed_refs->seq_head.next); + delayed_refs->num_entries, fs_info->tree_mod_seq_list.next); spin_lock(&delayed_refs->lock); } @@ -2403,6 +2405,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, again: consider_waiting = 0; spin_lock(&delayed_refs->lock); + if (count == 0) { count = delayed_refs->num_entries * 2; run_most = 1; @@ -2437,7 +2440,7 @@ again: num_refs = delayed_refs->num_entries; first_seq = root->fs_info->tree_mod_seq_list.next; } else { - wait_for_more_refs(delayed_refs, + wait_for_more_refs(root->fs_info, delayed_refs, num_refs, first_seq); /* * after waiting, things have changed. we @@ -5190,8 +5193,8 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, rb_erase(&head->node.rb_node, &delayed_refs->root); delayed_refs->num_entries--; - if (waitqueue_active(&delayed_refs->seq_wait)) - wake_up(&delayed_refs->seq_wait); + if (waitqueue_active(&root->fs_info->tree_mod_seq_wait)) + wake_up(&root->fs_info->tree_mod_seq_wait); /* * we don't take a ref on the node because we're removing it from the diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b72b068183ec..621c8dc48fb6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -38,7 +38,6 @@ void put_transaction(struct btrfs_transaction *transaction) if (atomic_dec_and_test(&transaction->use_count)) { BUG_ON(!list_empty(&transaction->list)); WARN_ON(transaction->delayed_refs.root.rb_node); - WARN_ON(!list_empty(&transaction->delayed_refs.seq_head)); memset(transaction, 0, sizeof(*transaction)); kmem_cache_free(btrfs_transaction_cachep, transaction); } @@ -126,7 +125,6 @@ loop: cur_trans->delayed_refs.num_heads = 0; cur_trans->delayed_refs.flushing = 0; cur_trans->delayed_refs.run_delayed_start = 0; - cur_trans->delayed_refs.seq = 1; /* * although the tree mod log is per file system and not per transaction, @@ -145,10 +143,8 @@ loop: } atomic_set(&fs_info->tree_mod_seq, 0); - init_waitqueue_head(&cur_trans->delayed_refs.seq_wait); spin_lock_init(&cur_trans->commit_lock); spin_lock_init(&cur_trans->delayed_refs.lock); - INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head); INIT_LIST_HEAD(&cur_trans->pending_snapshots); list_add_tail(&cur_trans->list, &fs_info->trans_list); -- GitLab From 630dc772ea51bca3ec6fac609f450cbe0cafd1d6 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 13 Sep 2011 11:06:07 +0200 Subject: [PATCH 2432/5711] Btrfs: qgroup on-disk format Not all features are in use by the current version and thus may change in the future. Signed-off-by: Arne Jansen --- fs/btrfs/ctree.h | 136 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8f8dc46f44e7..33088b0dbf3f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -91,6 +91,9 @@ struct btrfs_ordered_sum; /* for storing balance parameters in the root tree */ #define BTRFS_BALANCE_OBJECTID -4ULL +/* holds quota configuration and tracking */ +#define BTRFS_QUOTA_TREE_OBJECTID 8ULL + /* orhpan objectid for tracking unlinked/truncated files */ #define BTRFS_ORPHAN_OBJECTID -5ULL @@ -883,6 +886,72 @@ struct btrfs_block_group_item { __le64 flags; } __attribute__ ((__packed__)); +/* + * is subvolume quota turned on? + */ +#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0) +/* + * SCANNING is set during the initialization phase + */ +#define BTRFS_QGROUP_STATUS_FLAG_SCANNING (1ULL << 1) +/* + * Some qgroup entries are known to be out of date, + * either because the configuration has changed in a way that + * makes a rescan necessary, or because the fs has been mounted + * with a non-qgroup-aware version. + * Turning qouta off and on again makes it inconsistent, too. + */ +#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) + +#define BTRFS_QGROUP_STATUS_VERSION 1 + +struct btrfs_qgroup_status_item { + __le64 version; + /* + * the generation is updated during every commit. As older + * versions of btrfs are not aware of qgroups, it will be + * possible to detect inconsistencies by checking the + * generation on mount time + */ + __le64 generation; + + /* flag definitions see above */ + __le64 flags; + + /* + * only used during scanning to record the progress + * of the scan. It contains a logical address + */ + __le64 scan; +} __attribute__ ((__packed__)); + +struct btrfs_qgroup_info_item { + __le64 generation; + __le64 rfer; + __le64 rfer_cmpr; + __le64 excl; + __le64 excl_cmpr; +} __attribute__ ((__packed__)); + +/* flags definition for qgroup limits */ +#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) +#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) +#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) +#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) +#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) +#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) + +struct btrfs_qgroup_limit_item { + /* + * only updated when any of the other values change + */ + __le64 flags; + __le64 max_rfer; + __le64 max_excl; + __le64 rsv_rfer; + __le64 rsv_excl; +} __attribute__ ((__packed__)); + struct btrfs_space_info { u64 flags; @@ -1534,6 +1603,30 @@ struct btrfs_ioctl_defrag_range_args { #define BTRFS_DEV_ITEM_KEY 216 #define BTRFS_CHUNK_ITEM_KEY 228 +/* + * Records the overall state of the qgroups. + * There's only one instance of this key present, + * (0, BTRFS_QGROUP_STATUS_KEY, 0) + */ +#define BTRFS_QGROUP_STATUS_KEY 240 +/* + * Records the currently used space of the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid). + */ +#define BTRFS_QGROUP_INFO_KEY 242 +/* + * Contains the user configured limits for the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid). + */ +#define BTRFS_QGROUP_LIMIT_KEY 244 +/* + * Records the child-parent relationship of qgroups. For + * each relation, 2 keys are present: + * (childid, BTRFS_QGROUP_RELATION_KEY, parentid) + * (parentid, BTRFS_QGROUP_RELATION_KEY, childid) + */ +#define BTRFS_QGROUP_RELATION_KEY 246 + #define BTRFS_BALANCE_ITEM_KEY 248 /* @@ -2474,6 +2567,49 @@ static inline void btrfs_set_dev_stats_value(struct extent_buffer *eb, sizeof(val)); } +/* btrfs_qgroup_status_item */ +BTRFS_SETGET_FUNCS(qgroup_status_generation, struct btrfs_qgroup_status_item, + generation, 64); +BTRFS_SETGET_FUNCS(qgroup_status_version, struct btrfs_qgroup_status_item, + version, 64); +BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item, + flags, 64); +BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item, + scan, 64); + +/* btrfs_qgroup_info_item */ +BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item, + generation, 64); +BTRFS_SETGET_FUNCS(qgroup_info_rfer, struct btrfs_qgroup_info_item, rfer, 64); +BTRFS_SETGET_FUNCS(qgroup_info_rfer_cmpr, struct btrfs_qgroup_info_item, + rfer_cmpr, 64); +BTRFS_SETGET_FUNCS(qgroup_info_excl, struct btrfs_qgroup_info_item, excl, 64); +BTRFS_SETGET_FUNCS(qgroup_info_excl_cmpr, struct btrfs_qgroup_info_item, + excl_cmpr, 64); + +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_info_generation, + struct btrfs_qgroup_info_item, generation, 64); +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_info_rfer, struct btrfs_qgroup_info_item, + rfer, 64); +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_info_rfer_cmpr, + struct btrfs_qgroup_info_item, rfer_cmpr, 64); +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_info_excl, struct btrfs_qgroup_info_item, + excl, 64); +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_info_excl_cmpr, + struct btrfs_qgroup_info_item, excl_cmpr, 64); + +/* btrfs_qgroup_limit_item */ +BTRFS_SETGET_FUNCS(qgroup_limit_flags, struct btrfs_qgroup_limit_item, + flags, 64); +BTRFS_SETGET_FUNCS(qgroup_limit_max_rfer, struct btrfs_qgroup_limit_item, + max_rfer, 64); +BTRFS_SETGET_FUNCS(qgroup_limit_max_excl, struct btrfs_qgroup_limit_item, + max_excl, 64); +BTRFS_SETGET_FUNCS(qgroup_limit_rsv_rfer, struct btrfs_qgroup_limit_item, + rsv_rfer, 64); +BTRFS_SETGET_FUNCS(qgroup_limit_rsv_excl, struct btrfs_qgroup_limit_item, + rsv_excl, 64); + static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb) { return sb->s_fs_info; -- GitLab From 2f38b3e1900634e64a186873b3388b1bf85dabc0 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 13 Sep 2011 11:18:10 +0200 Subject: [PATCH 2433/5711] Btrfs: add helper for tree enumeration Often no exact match is wanted but just the next lower or higher item. There's a lot of duplicated code throughout btrfs to deal with the corner cases. This patch adds a helper function that can facilitate searching. Signed-off-by: Arne Jansen --- fs/btrfs/ctree.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/ctree.h | 3 ++ 2 files changed, 75 insertions(+) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index bef68ab32204..fb21431fe4e0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -2788,6 +2788,78 @@ done: return ret; } +/* + * helper to use instead of search slot if no exact match is needed but + * instead the next or previous item should be returned. + * When find_higher is true, the next higher item is returned, the next lower + * otherwise. + * When return_any and find_higher are both true, and no higher item is found, + * return the next lower instead. + * When return_any is true and find_higher is false, and no lower item is found, + * return the next higher instead. + * It returns 0 if any item is found, 1 if none is found (tree empty), and + * < 0 on error + */ +int btrfs_search_slot_for_read(struct btrfs_root *root, + struct btrfs_key *key, struct btrfs_path *p, + int find_higher, int return_any) +{ + int ret; + struct extent_buffer *leaf; + +again: + ret = btrfs_search_slot(NULL, root, key, p, 0, 0); + if (ret <= 0) + return ret; + /* + * a return value of 1 means the path is at the position where the + * item should be inserted. Normally this is the next bigger item, + * but in case the previous item is the last in a leaf, path points + * to the first free slot in the previous leaf, i.e. at an invalid + * item. + */ + leaf = p->nodes[0]; + + if (find_higher) { + if (p->slots[0] >= btrfs_header_nritems(leaf)) { + ret = btrfs_next_leaf(root, p); + if (ret <= 0) + return ret; + if (!return_any) + return 1; + /* + * no higher item found, return the next + * lower instead + */ + return_any = 0; + find_higher = 0; + btrfs_release_path(p); + goto again; + } + } else { + if (p->slots[0] >= btrfs_header_nritems(leaf)) { + /* we're sitting on an invalid slot */ + if (p->slots[0] == 0) { + ret = btrfs_prev_leaf(root, p); + if (ret <= 0) + return ret; + if (!return_any) + return 1; + /* + * no lower item found, return the next + * higher instead + */ + return_any = 0; + find_higher = 1; + btrfs_release_path(p); + goto again; + } + --p->slots[0]; + } + } + return 0; +} + /* * adjust the pointers going up the tree, starting at level * making sure the right key of each node is points to 'key'. diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 33088b0dbf3f..27cf995564ed 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2856,6 +2856,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ins_len, int cow); int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, u64 time_seq); +int btrfs_search_slot_for_read(struct btrfs_root *root, + struct btrfs_key *key, struct btrfs_path *p, + int find_higher, int return_any); int btrfs_realloc_node(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *parent, int start_slot, int cache_only, u64 *last_ret, -- GitLab From d13603ef6e14a12cd65a6975e8117c0fea7c7ddf Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 13 Sep 2011 11:40:09 +0200 Subject: [PATCH 2434/5711] Btrfs: check the root passed to btrfs_end_transaction This patch only add a consistancy check to validate that the same root is passed to start_transaction and end_transaction. Subvolume quota depends on this. Signed-off-by: Arne Jansen --- fs/btrfs/transaction.c | 6 ++++++ fs/btrfs/transaction.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 621c8dc48fb6..23cbda0685b8 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -345,6 +345,7 @@ again: h->transaction = cur_trans; h->blocks_used = 0; h->bytes_reserved = 0; + h->root = root; h->delayed_ref_updates = 0; h->use_count = 1; h->block_rsv = NULL; @@ -511,6 +512,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, btrfs_trans_release_metadata(trans, root); trans->block_rsv = NULL; + /* + * the same root has to be passed to start_transaction and + * end_transaction. Subvolume quota depends on this. + */ + WARN_ON(trans->root != root); while (count < 2) { unsigned long cur = trans->delayed_ref_updates; trans->delayed_ref_updates = 0; diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index fe27379e368b..010729446e13 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h @@ -57,6 +57,12 @@ struct btrfs_trans_handle { struct btrfs_block_rsv *block_rsv; struct btrfs_block_rsv *orig_rsv; int aborted; + /* + * this root is only needed to validate that the root passed to + * start_transaction is the same as the one passed to end_transaction. + * Subvolume quota depends on this + */ + struct btrfs_root *root; }; struct btrfs_pending_snapshot { -- GitLab From 20897f5c86b9d2b77baea1d48eda7fa4ac217279 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 13 Sep 2011 12:44:20 +0200 Subject: [PATCH 2435/5711] Btrfs: added helper to create new trees This creates a brand new tree. Will be used to create the quota tree. Signed-off-by: Arne Jansen --- fs/btrfs/disk-io.c | 78 +++++++++++++++++++++++++++++++++++++++++++++- fs/btrfs/disk-io.h | 6 ++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 19a39e10d6f5..6fc243eccffa 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1225,6 +1225,82 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info) return root; } +struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + u64 objectid) +{ + struct extent_buffer *leaf; + struct btrfs_root *tree_root = fs_info->tree_root; + struct btrfs_root *root; + struct btrfs_key key; + int ret = 0; + u64 bytenr; + + root = btrfs_alloc_root(fs_info); + if (!root) + return ERR_PTR(-ENOMEM); + + __setup_root(tree_root->nodesize, tree_root->leafsize, + tree_root->sectorsize, tree_root->stripesize, + root, fs_info, objectid); + root->root_key.objectid = objectid; + root->root_key.type = BTRFS_ROOT_ITEM_KEY; + root->root_key.offset = 0; + + leaf = btrfs_alloc_free_block(trans, root, root->leafsize, + 0, objectid, NULL, 0, 0, 0); + if (IS_ERR(leaf)) { + ret = PTR_ERR(leaf); + goto fail; + } + + bytenr = leaf->start; + memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header)); + btrfs_set_header_bytenr(leaf, leaf->start); + btrfs_set_header_generation(leaf, trans->transid); + btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); + btrfs_set_header_owner(leaf, objectid); + root->node = leaf; + + write_extent_buffer(leaf, fs_info->fsid, + (unsigned long)btrfs_header_fsid(leaf), + BTRFS_FSID_SIZE); + write_extent_buffer(leaf, fs_info->chunk_tree_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(leaf), + BTRFS_UUID_SIZE); + btrfs_mark_buffer_dirty(leaf); + + root->commit_root = btrfs_root_node(root); + root->track_dirty = 1; + + + root->root_item.flags = 0; + root->root_item.byte_limit = 0; + btrfs_set_root_bytenr(&root->root_item, leaf->start); + btrfs_set_root_generation(&root->root_item, trans->transid); + btrfs_set_root_level(&root->root_item, 0); + btrfs_set_root_refs(&root->root_item, 1); + btrfs_set_root_used(&root->root_item, leaf->len); + btrfs_set_root_last_snapshot(&root->root_item, 0); + btrfs_set_root_dirid(&root->root_item, 0); + root->root_item.drop_level = 0; + + key.objectid = objectid; + key.type = BTRFS_ROOT_ITEM_KEY; + key.offset = 0; + ret = btrfs_insert_root(trans, tree_root, &key, &root->root_item); + if (ret) + goto fail; + + btrfs_tree_unlock(leaf); + +fail: + if (ret) + return ERR_PTR(ret); + + return root; +} + static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info) { @@ -3260,7 +3336,7 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) return btree_read_extent_buffer_pages(root, buf, 0, parent_transid); } -static int btree_lock_page_hook(struct page *page, void *data, +int btree_lock_page_hook(struct page *page, void *data, void (*flush_fn)(void *)) { struct inode *inode = page->mapping->host; diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 05b3fab39f7e..95e147eea239 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -89,6 +89,12 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans, int btrfs_cleanup_transaction(struct btrfs_root *root); void btrfs_cleanup_one_transaction(struct btrfs_transaction *trans, struct btrfs_root *root); +void btrfs_abort_devices(struct btrfs_root *root); +struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + u64 objectid); +int btree_lock_page_hook(struct page *page, void *data, + void (*flush_fn)(void *)); #ifdef CONFIG_DEBUG_LOCK_ALLOC void btrfs_init_lockdep(void); -- GitLab From 416ac51da90e98daaac17e1f359a6c5591f7f5bd Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 13 Sep 2011 12:56:09 +0200 Subject: [PATCH 2436/5711] Btrfs: qgroup state and initialization Add state to fs_info. Signed-off-by: Arne Jansen --- fs/btrfs/ctree.h | 24 ++++++++++++++++++++++++ fs/btrfs/disk-io.c | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 27cf995564ed..a5269d4a164f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1120,6 +1120,7 @@ struct btrfs_fs_info { struct btrfs_root *dev_root; struct btrfs_root *fs_root; struct btrfs_root *csum_root; + struct btrfs_root *quota_root; /* the log root tree is a directory of all the other log roots */ struct btrfs_root *log_root_tree; @@ -1374,6 +1375,29 @@ struct btrfs_fs_info { #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY u32 check_integrity_print_mask; #endif + /* + * quota information + */ + unsigned int quota_enabled:1; + + /* + * quota_enabled only changes state after a commit. This holds the + * next state. + */ + unsigned int pending_quota_state:1; + + /* is qgroup tracking in a consistent state? */ + u64 qgroup_flags; + + /* holds configuration and tracking. Protected by qgroup_lock */ + struct rb_root qgroup_tree; + spinlock_t qgroup_lock; + + /* list of dirty qgroups to be written at next commit */ + struct list_head dirty_qgroups; + + /* used by btrfs_qgroup_record_ref for an efficient tree traversal */ + u64 qgroup_seq; /* filesystem state */ u64 fs_state; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6fc243eccffa..eca054974425 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2110,6 +2110,13 @@ int open_ctree(struct super_block *sb, init_rwsem(&fs_info->cleanup_work_sem); init_rwsem(&fs_info->subvol_sem); + spin_lock_init(&fs_info->qgroup_lock); + fs_info->qgroup_tree = RB_ROOT; + INIT_LIST_HEAD(&fs_info->dirty_qgroups); + fs_info->qgroup_seq = 1; + fs_info->quota_enabled = 0; + fs_info->pending_quota_state = 0; + btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); btrfs_init_free_cluster(&fs_info->data_alloc_cluster); -- GitLab From 709c0486b9fe9586736b108b7233bbce0300cfa5 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Mon, 12 Sep 2011 12:22:57 +0200 Subject: [PATCH 2437/5711] Btrfs: Test code to change the order of delayed-ref processing Normally delayed refs get processed in ascending bytenr order. This correlates in most cases to the order added. To expose dependencies on this order, we start to process the tree in the middle instead of the beginning. This code is only effective when SCRAMBLE_DELAYED_REFS is defined. Signed-off-by: Arne Jansen --- fs/btrfs/extent-tree.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 94ce79f76e5f..b13f1fbc3733 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -34,6 +34,8 @@ #include "locking.h" #include "free-space-cache.h" +#undef SCRAMBLE_DELAYED_REFS + /* * control flags for do_chunk_alloc's force field * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk @@ -2364,6 +2366,49 @@ static void wait_for_more_refs(struct btrfs_fs_info *fs_info, spin_lock(&delayed_refs->lock); } +#ifdef SCRAMBLE_DELAYED_REFS +/* + * Normally delayed refs get processed in ascending bytenr order. This + * correlates in most cases to the order added. To expose dependencies on this + * order, we start to process the tree in the middle instead of the beginning + */ +static u64 find_middle(struct rb_root *root) +{ + struct rb_node *n = root->rb_node; + struct btrfs_delayed_ref_node *entry; + int alt = 1; + u64 middle; + u64 first = 0, last = 0; + + n = rb_first(root); + if (n) { + entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); + first = entry->bytenr; + } + n = rb_last(root); + if (n) { + entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); + last = entry->bytenr; + } + n = root->rb_node; + + while (n) { + entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); + WARN_ON(!entry->in_tree); + + middle = entry->bytenr; + + if (alt) + n = n->rb_left; + else + n = n->rb_right; + + alt = 1 - alt; + } + return middle; +} +#endif + /* * this starts processing the delayed reference count updates and * extent insertions we have queued up so far. count can be @@ -2406,6 +2451,10 @@ again: consider_waiting = 0; spin_lock(&delayed_refs->lock); +#ifdef SCRAMBLE_DELAYED_REFS + delayed_refs->run_delayed_start = find_middle(&delayed_refs->root); +#endif + if (count == 0) { count = delayed_refs->num_entries * 2; run_most = 1; -- GitLab From bb1daa803c733462248421dd9beed84fecf1745e Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 10 Jul 2012 14:35:11 +0200 Subject: [PATCH 2438/5711] ASoC: tlv320aic3x: add AGC settings This patch adds AGC target level and times settings for TLV320AIC3x. Enums uses small arrays of two channels left and right since it uses different registers. Signed-off-by: Jiri Prchal Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 7933b8c720af..0d2f8c44999d 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -231,6 +231,25 @@ static const struct soc_enum aic3x_enum[] = { SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), }; +static const char *aic3x_agc_level[] = + { "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" }; +static const struct soc_enum aic3x_agc_level_enum[] = { + SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level), + SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level), +}; + +static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" }; +static const struct soc_enum aic3x_agc_attack_enum[] = { + SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack), + SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack), +}; + +static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" }; +static const struct soc_enum aic3x_agc_decay_enum[] = { + SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay), + SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay), +}; + /* * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps */ @@ -355,6 +374,12 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { * adjust PGA to max value when ADC is on and will never go back. */ SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), + SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]), + SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]), + SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]), + SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]), + SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]), + SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]), /* De-emphasis */ SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), -- GitLab From a1f34af0ec35e3131d65e0ae4cec6b048cba3e88 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 10 Jul 2012 14:36:58 +0200 Subject: [PATCH 2439/5711] ASoC: tlv320aic3x: add input clock selection This patch adds input selection of main codec clock - from what pin. Both registers set same value since codec uses clock divider or pll at one time. Signed-off-by: Jiri Prchal Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 6 ++++++ sound/soc/codecs/tlv320aic3x.h | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 0d2f8c44999d..b94f81ffed34 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1002,6 +1002,12 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); + /* set clock on MCLK or GPIO2 or BCLK */ + snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK, + clk_id << PLLCLK_IN_SHIFT); + snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK, + clk_id << CLKDIV_IN_SHIFT); + aic3x->sysclk = freq; return 0; } diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 5da5eb3f4cc0..149338b254f6 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -195,6 +195,14 @@ #define PLL_CLKIN_SHIFT 4 #define MCLK_SOURCE 0x0 #define PLL_CLKDIV_SHIFT 0 +#define PLLCLK_IN_MASK 0x30 +#define PLLCLK_IN_SHIFT 4 +#define CLKDIV_IN_MASK 0xc0 +#define CLKDIV_IN_SHIFT 6 +/* clock in source */ +#define CLKIN_MCLK 0 +#define CLKIN_GPIO2 1 +#define CLKIN_BCLK 2 /* Software reset register bits */ #define SOFT_RESET 0x80 -- GitLab From 619ac8d3e582ccd806f24dcfc369c4c250ca9814 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 10 Jul 2012 19:08:37 +0530 Subject: [PATCH 2440/5711] spi: tegra: use dmaengine based dma driver Use the dmaengine based Tegra APB DMA driver for data transfer between SPI FIFO and memory in place of legacy Tegra APB DMA. The new driver is selected if legacy driver is not selected and new DMA driver is enabled through config file. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- drivers/spi/spi-tegra.c | 89 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 00c024039c97..6eeb8a286a20 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -357,7 +357,7 @@ config SPI_STMP3XXX config SPI_TEGRA tristate "Nvidia Tegra SPI controller" - depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA + depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA) help SPI driver for NVidia Tegra SoCs diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c index ae6d78a3e912..956ff4a0827b 100644 --- a/drivers/spi/spi-tegra.c +++ b/drivers/spi/spi-tegra.c @@ -30,6 +30,7 @@ #include #include +#include #include @@ -162,12 +163,23 @@ struct spi_tegra_data { * require transfers to be 4 byte aligned we need a bounce buffer * for the generic case. */ + int dma_req_len; +#if defined(CONFIG_TEGRA_SYSTEM_DMA) struct tegra_dma_req rx_dma_req; struct tegra_dma_channel *rx_dma; +#else + struct dma_chan *rx_dma; + struct dma_slave_config sconfig; + struct dma_async_tx_descriptor *rx_dma_desc; + dma_cookie_t rx_cookie; +#endif u32 *rx_bb; dma_addr_t rx_bb_phys; }; +#if !defined(CONFIG_TEGRA_SYSTEM_DMA) +static void tegra_spi_rx_dma_complete(void *args); +#endif static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, unsigned long reg) @@ -190,10 +202,24 @@ static void spi_tegra_go(struct spi_tegra_data *tspi) val = spi_tegra_readl(tspi, SLINK_DMA_CTL); val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN; - val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1); + val |= SLINK_DMA_BLOCK_SIZE(tspi->dma_req_len / 4 - 1); spi_tegra_writel(tspi, val, SLINK_DMA_CTL); - +#if defined(CONFIG_TEGRA_SYSTEM_DMA) + tspi->rx_dma_req.size = tspi->dma_req_len; tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req); +#else + tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma, + tspi->rx_bb_phys, tspi->dma_req_len, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); + if (!tspi->rx_dma_desc) { + dev_err(&tspi->pdev->dev, "dmaengine slave prep failed\n"); + return; + } + tspi->rx_dma_desc->callback = tegra_spi_rx_dma_complete; + tspi->rx_dma_desc->callback_param = tspi; + tspi->rx_cookie = dmaengine_submit(tspi->rx_dma_desc); + dma_async_issue_pending(tspi->rx_dma); +#endif val |= SLINK_DMA_EN; spi_tegra_writel(tspi, val, SLINK_DMA_CTL); @@ -221,7 +247,7 @@ static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi, spi_tegra_writel(tspi, val, SLINK_TX_FIFO); } - tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4; + tspi->dma_req_len = len / tspi->cur_bytes_per_word * 4; return len; } @@ -318,9 +344,8 @@ static void spi_tegra_start_message(struct spi_device *spi, spi_tegra_start_transfer(spi, t); } -static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) +static void handle_spi_rx_dma_complete(struct spi_tegra_data *tspi) { - struct spi_tegra_data *tspi = req->dev; unsigned long flags; struct spi_message *m; struct spi_device *spi; @@ -380,6 +405,19 @@ static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) spin_unlock_irqrestore(&tspi->lock, flags); } +#if defined(CONFIG_TEGRA_SYSTEM_DMA) +static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) +{ + struct spi_tegra_data *tspi = req->dev; + handle_spi_rx_dma_complete(tspi); +} +#else +static void tegra_spi_rx_dma_complete(void *args) +{ + struct spi_tegra_data *tspi = args; + handle_spi_rx_dma_complete(tspi); +} +#endif static int spi_tegra_setup(struct spi_device *spi) { @@ -471,6 +509,9 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) struct spi_tegra_data *tspi; struct resource *r; int ret; +#if !defined(CONFIG_TEGRA_SYSTEM_DMA) + dma_cap_mask_t mask; +#endif master = spi_alloc_master(&pdev->dev, sizeof *tspi); if (master == NULL) { @@ -522,12 +563,24 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) INIT_LIST_HEAD(&tspi->queue); +#if defined(CONFIG_TEGRA_SYSTEM_DMA) tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); if (!tspi->rx_dma) { dev_err(&pdev->dev, "can not allocate rx dma channel\n"); ret = -ENODEV; goto err3; } +#else + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + tspi->rx_dma = dma_request_channel(mask, NULL, NULL); + if (!tspi->rx_dma) { + dev_err(&pdev->dev, "can not allocate rx dma channel\n"); + ret = -ENODEV; + goto err3; + } + +#endif tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN, &tspi->rx_bb_phys, GFP_KERNEL); @@ -537,6 +590,7 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) goto err4; } +#if defined(CONFIG_TEGRA_SYSTEM_DMA) tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete; tspi->rx_dma_req.to_memory = 1; tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys; @@ -546,6 +600,23 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) tspi->rx_dma_req.source_wrap = 4; tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id]; tspi->rx_dma_req.dev = tspi; +#else + /* Dmaengine Dma slave config */ + tspi->sconfig.src_addr = tspi->phys + SLINK_RX_FIFO; + tspi->sconfig.dst_addr = tspi->phys + SLINK_RX_FIFO; + tspi->sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + tspi->sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + tspi->sconfig.slave_id = spi_tegra_req_sels[pdev->id]; + tspi->sconfig.src_maxburst = 1; + tspi->sconfig.dst_maxburst = 1; + ret = dmaengine_device_control(tspi->rx_dma, + DMA_SLAVE_CONFIG, (unsigned long) &tspi->sconfig); + if (ret < 0) { + dev_err(&pdev->dev, "can not do slave configure for dma %d\n", + ret); + goto err4; + } +#endif master->dev.of_node = pdev->dev.of_node; ret = spi_register_master(master); @@ -559,7 +630,11 @@ err5: dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, tspi->rx_bb, tspi->rx_bb_phys); err4: +#if defined(CONFIG_TEGRA_SYSTEM_DMA) tegra_dma_free_channel(tspi->rx_dma); +#else + dma_release_channel(tspi->rx_dma); +#endif err3: clk_put(tspi->clk); err2: @@ -581,7 +656,11 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) tspi = spi_master_get_devdata(master); spi_unregister_master(master); +#if defined(CONFIG_TEGRA_SYSTEM_DMA) tegra_dma_free_channel(tspi->rx_dma); +#else + dma_release_channel(tspi->rx_dma); +#endif dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, tspi->rx_bb, tspi->rx_bb_phys); -- GitLab From 05644147064acabb8587c4cbd690047494f7b3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 9 Feb 2012 22:21:45 +0100 Subject: [PATCH 2441/5711] spi/gpio: start with CS non-active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chip select line was configured as output with the initial value being active explicitly. It was later deasserted during spi_bitbang_setup() without any clock activity in between. So it makes no sense to activate the device at all and the chip select line can better start non-active. Signed-off-by: Uwe Kleine-König Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0094c645ff0d..0b56cfc71fab 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -235,7 +235,8 @@ static int spi_gpio_setup(struct spi_device *spi) status = gpio_request(cs, dev_name(&spi->dev)); if (status) return status; - status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); + status = gpio_direction_output(cs, + !(spi->mode & SPI_CS_HIGH)); } } if (!status) -- GitLab From 1c975931128c1128892981095a64fb8eabf240eb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 9 Jul 2012 13:39:52 -0600 Subject: [PATCH 2442/5711] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases() The generic code to read P2P bridge windows is functionally equivalent to the sparc-specific pci_cfg_fake_ranges(), so use the generic code. The "if (!res->start) res->start = ..." removed from the I/O window code here was an artifact of the Intel 1K window support from 9d265124d051 and is no longer necessary (it probably was just cloned from x86 and was never useful on sparc). Acked-by: David S. Miller Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pci.c | 89 +---------------------------------------- 1 file changed, 1 insertion(+), 88 deletions(-) diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index fdaf21811670..fa53d552875f 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -375,93 +375,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) *last_p = last; } -/* For PCI bus devices which lack a 'ranges' property we interrogate - * the config space values to set the resources, just like the generic - * Linux PCI probing code does. - */ -static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev, - struct pci_bus *bus, - struct pci_pbm_info *pbm) -{ - struct pci_bus_region region; - struct resource *res, res2; - u8 io_base_lo, io_limit_lo; - u16 mem_base_lo, mem_limit_lo; - unsigned long base, limit; - - pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); - pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); - base = (io_base_lo & PCI_IO_RANGE_MASK) << 8; - limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8; - - if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { - u16 io_base_hi, io_limit_hi; - - pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi); - pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi); - base |= (io_base_hi << 16); - limit |= (io_limit_hi << 16); - } - - res = bus->resource[0]; - if (base <= limit) { - res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; - res2.flags = res->flags; - region.start = base; - region.end = limit + 0xfff; - pcibios_bus_to_resource(dev, &res2, ®ion); - if (!res->start) - res->start = res2.start; - if (!res->end) - res->end = res2.end; - } - - pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); - pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); - base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; - limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; - - res = bus->resource[1]; - if (base <= limit) { - res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | - IORESOURCE_MEM); - region.start = base; - region.end = limit + 0xfffff; - pcibios_bus_to_resource(dev, res, ®ion); - } - - pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); - pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); - base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; - limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; - - if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { - u32 mem_base_hi, mem_limit_hi; - - pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi); - pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi); - - /* - * Some bridges set the base > limit by default, and some - * (broken) BIOSes do not initialize them. If we find - * this, just assume they are not being used. - */ - if (mem_base_hi <= mem_limit_hi) { - base |= ((long) mem_base_hi) << 32; - limit |= ((long) mem_limit_hi) << 32; - } - } - - res = bus->resource[2]; - if (base <= limit) { - res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | - IORESOURCE_MEM | IORESOURCE_PREFETCH); - region.start = base; - region.end = limit + 0xfffff; - pcibios_bus_to_resource(dev, res, ®ion); - } -} - /* Cook up fake bus resources for SUNW,simba PCI bridges which lack * a proper 'ranges' property. */ @@ -550,7 +463,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, apb_fake_ranges(dev, bus, pbm); goto after_ranges; } else if (ranges == NULL) { - pci_cfg_fake_ranges(dev, bus, pbm); + pci_read_bridge_bases(bus); goto after_ranges; } i = 1; -- GitLab From e95d8aafa5d911bf523bc47fe89f3336eb8a1b51 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 10 Jul 2012 13:35:50 +0000 Subject: [PATCH 2443/5711] of: mtd: nuke useless const qualifier This patch does the following: -const int of_get_nand_ecc_mode(struct device_node *np) +int of_get_nand_ecc_mode(struct device_node *np) because: 1. it is probably just a typo? 2. it causes warnings like this when people assing the returned value to an 'int' variable: include/linux/of_mtd.h:14:18: warning: type qualifiers ignored on functi= on return type [-Wignored-qualifiers] Remove also the unnecessary "extern" qualifier to be consistent with other declarations in this file. Signed-off-by: Artem Bityutskiy Signed-off-by: Rob Herring --- drivers/of/of_mtd.c | 2 +- include/linux/of_mtd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c index e7cad627a5d1..a27ec94877e4 100644 --- a/drivers/of/of_mtd.c +++ b/drivers/of/of_mtd.c @@ -32,7 +32,7 @@ static const char *nand_ecc_modes[] = { * The function gets ecc mode string from property 'nand-ecc-mode', * and return its index in nand_ecc_modes table, or errno in error case. */ -const int of_get_nand_ecc_mode(struct device_node *np) +int of_get_nand_ecc_mode(struct device_node *np) { const char *pm; int err, i; diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h index bae1b6094c63..ed7f267e6389 100644 --- a/include/linux/of_mtd.h +++ b/include/linux/of_mtd.h @@ -11,7 +11,7 @@ #ifdef CONFIG_OF_MTD #include -extern const int of_get_nand_ecc_mode(struct device_node *np); +int of_get_nand_ecc_mode(struct device_node *np); int of_get_nand_bus_width(struct device_node *np); bool of_get_nand_on_flash_bbt(struct device_node *np); #endif -- GitLab From 57b9655d01ef057a523e810d29c37ac09b80eead Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 10 Jul 2012 17:58:04 +0200 Subject: [PATCH 2444/5711] udf: Improve table length check to avoid possible overflow When a partition table length is corrupted to be close to 1 << 32, the check for its length may overflow on 32-bit systems and we will think the length is valid. Later on the kernel can crash trying to read beyond end of buffer. Fix the check to avoid possible overflow. CC: stable@vger.kernel.org Reported-by: Ben Hutchings Signed-off-by: Jan Kara --- fs/udf/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 8a7583867811..dcbf98722afc 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1340,7 +1340,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; table_len = le32_to_cpu(lvd->mapTableLength); - if (sizeof(*lvd) + table_len > sb->s_blocksize) { + if (table_len > sb->s_blocksize - sizeof(*lvd)) { udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); -- GitLab From 2b4d39fc2a80e271ac8d44fccd02277a4b63c557 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Jul 2012 17:03:46 +0100 Subject: [PATCH 2445/5711] ASoC: arizona: Support variable FLL VCO multipliers Some Arizona chips have a higher frequency for the FLL VCO, support this in the common code. Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 6 +++--- sound/soc/codecs/arizona.h | 1 + sound/soc/codecs/wm5102.c | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index f3680c374347..5c9cacaf2d52 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -734,9 +734,9 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Apply the division for our remaining calculations */ Fref /= div; - /* Fvco should be 90-100MHz; don't check the upper bound */ + /* Fvco should be over the targt; don't check the upper bound */ div = 1; - while (Fout * div < 90000000) { + while (Fout * div < 90000000 * fll->vco_mult) { div++; if (div > 7) { arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", @@ -744,7 +744,7 @@ static int arizona_calc_fll(struct arizona_fll *fll, return -EINVAL; } } - target = Fout * div; + target = Fout * div / fll->vco_mult; cfg->outdiv = div; arizona_fll_dbg(fll, "Fvco=%dHz\n", target); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index b894b64e8f5c..59caca8865e8 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -141,6 +141,7 @@ struct arizona_fll { struct arizona *arizona; int id; unsigned int base; + unsigned int vco_mult; struct completion lock; struct completion ok; diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 7a6a11a323ff..6537f16d383e 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -853,6 +853,9 @@ static int __devinit wm5102_probe(struct platform_device *pdev) wm5102->core.arizona = arizona; + for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) + wm5102->fll[i].vco_mult = 1; + arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, &wm5102->fll[0]); -- GitLab From 00f5ce99dc6ee46c3113393cc8fa12173f9bbcd7 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:40 +0300 Subject: [PATCH 2446/5711] mlx4: Use port management change event instead of smp_snoop The port management change event can replace smp_snoop. If the capability bit for this event is set in dev-caps, the event is used (by the driver setting the PORT_MNG_CHG_EVENT bit in the async event mask in the MAP_EQ fw command). In this case, when the driver passes incoming SMP PORT_INFO SET mads to the FW, the FW generates port management change events to signal any changes to the driver. If the FW generates these events, smp_snoop shouldn't be invoked in ib_process_mad(), or duplicate events will occur (once from the FW-generated event, and once from smp_snoop). In the case where the FW does not generate port management change events smp_snoop needs to be invoked to create these events. The flow in smp_snoop has been modified to make use of the same procedures as in the fw-generated-event event case to generate the port management events (LID change, Client-rereg, Pkey change, and/or GID change). Port management change event handling required changing the mlx4_ib_event and mlx4_dispatch_event prototypes; the "param" argument (last argument) had to be changed to unsigned long in order to accomodate passing the EQE pointer. We also needed to move the definition of struct mlx4_eqe from net/mlx4.h to file device.h -- to make it available to the IB driver, to handle port management change events. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 118 ++++++++++++++----- drivers/infiniband/hw/mlx4/main.c | 29 ++++- drivers/infiniband/hw/mlx4/mlx4_ib.h | 9 ++ drivers/net/ethernet/mellanox/mlx4/en_main.c | 5 +- drivers/net/ethernet/mellanox/mlx4/eq.c | 22 +++- drivers/net/ethernet/mellanox/mlx4/fw.c | 1 + drivers/net/ethernet/mellanox/mlx4/intf.c | 5 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 63 +--------- include/linux/mlx4/device.h | 99 +++++++++++++++- include/linux/mlx4/driver.h | 3 +- 10 files changed, 249 insertions(+), 105 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 84786a9fb64f..58c45fb5bd31 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -147,47 +147,49 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) } /* - * Snoop SM MADs for port info and P_Key table sets, so we can - * synthesize LID change and P_Key change events. + * Snoop SM MADs for port info, GUID info, and P_Key table sets, so we can + * synthesize LID change, Client-Rereg, GID change, and P_Key change events. */ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, - u16 prev_lid) + u16 prev_lid) { - struct ib_event event; + struct ib_port_info *pinfo; + u16 lid; + struct mlx4_ib_dev *dev = to_mdev(ibdev); if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && - mad->mad_hdr.method == IB_MGMT_METHOD_SET) { - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { - struct ib_port_info *pinfo = - (struct ib_port_info *) ((struct ib_smp *) mad)->data; - u16 lid = be16_to_cpu(pinfo->lid); + mad->mad_hdr.method == IB_MGMT_METHOD_SET) + switch (mad->mad_hdr.attr_id) { + case IB_SMP_ATTR_PORT_INFO: + pinfo = (struct ib_port_info *) ((struct ib_smp *) mad)->data; + lid = be16_to_cpu(pinfo->lid); - update_sm_ah(to_mdev(ibdev), port_num, + update_sm_ah(dev, port_num, be16_to_cpu(pinfo->sm_lid), pinfo->neighbormtu_mastersmsl & 0xf); - event.device = ibdev; - event.element.port_num = port_num; + if (pinfo->clientrereg_resv_subnetto & 0x80) + mlx4_ib_dispatch_event(dev, port_num, + IB_EVENT_CLIENT_REREGISTER); - if (pinfo->clientrereg_resv_subnetto & 0x80) { - event.event = IB_EVENT_CLIENT_REREGISTER; - ib_dispatch_event(&event); - } + if (prev_lid != lid) + mlx4_ib_dispatch_event(dev, port_num, + IB_EVENT_LID_CHANGE); + break; - if (prev_lid != lid) { - event.event = IB_EVENT_LID_CHANGE; - ib_dispatch_event(&event); - } - } + case IB_SMP_ATTR_PKEY_TABLE: + mlx4_ib_dispatch_event(dev, port_num, + IB_EVENT_PKEY_CHANGE); + break; - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { - event.device = ibdev; - event.event = IB_EVENT_PKEY_CHANGE; - event.element.port_num = port_num; - ib_dispatch_event(&event); + case IB_SMP_ATTR_GUID_INFO: + mlx4_ib_dispatch_event(dev, port_num, + IB_EVENT_GID_CHANGE); + break; + default: + break; } - } } static void node_desc_override(struct ib_device *dev, @@ -305,7 +307,8 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_FAILURE; if (!out_mad->mad_hdr.status) { - smp_snoop(ibdev, port_num, in_mad, prev_lid); + if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV)) + smp_snoop(ibdev, port_num, in_mad, prev_lid); node_desc_override(ibdev, out_mad); } @@ -446,3 +449,62 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev) ib_destroy_ah(dev->sm_ah[p]); } } + +void handle_port_mgmt_change_event(struct work_struct *work) +{ + struct ib_event_work *ew = container_of(work, struct ib_event_work, work); + struct mlx4_ib_dev *dev = ew->ib_dev; + struct mlx4_eqe *eqe = &(ew->ib_eqe); + u8 port = eqe->event.port_mgmt_change.port; + u32 changed_attr; + + switch (eqe->subtype) { + case MLX4_DEV_PMC_SUBTYPE_PORT_INFO: + changed_attr = be32_to_cpu(eqe->event.port_mgmt_change.params.port_info.changed_attr); + + /* Update the SM ah - This should be done before handling + the other changed attributes so that MADs can be sent to the SM */ + if (changed_attr & MSTR_SM_CHANGE_MASK) { + u16 lid = be16_to_cpu(eqe->event.port_mgmt_change.params.port_info.mstr_sm_lid); + u8 sl = eqe->event.port_mgmt_change.params.port_info.mstr_sm_sl & 0xf; + update_sm_ah(dev, port, lid, sl); + } + + /* Check if it is a lid change event */ + if (changed_attr & MLX4_EQ_PORT_INFO_LID_CHANGE_MASK) + mlx4_ib_dispatch_event(dev, port, IB_EVENT_LID_CHANGE); + + /* Generate GUID changed event */ + if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) + mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); + + if (changed_attr & MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK) + mlx4_ib_dispatch_event(dev, port, + IB_EVENT_CLIENT_REREGISTER); + break; + + case MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE: + mlx4_ib_dispatch_event(dev, port, IB_EVENT_PKEY_CHANGE); + break; + case MLX4_DEV_PMC_SUBTYPE_GUID_INFO: + mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); + break; + default: + pr_warn("Unsupported subtype 0x%x for " + "Port Management Change event\n", eqe->subtype); + } + + kfree(ew); +} + +void mlx4_ib_dispatch_event(struct mlx4_ib_dev *dev, u8 port_num, + enum ib_event_type type) +{ + struct ib_event event; + + event.device = &dev->ib_dev; + event.element.port_num = port_num; + event.event = type; + + ib_dispatch_event(&event); +} diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 5266b49c46ee..4f230c26622d 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -898,7 +898,6 @@ static void update_gids_task(struct work_struct *work) union ib_gid *gids; int err; struct mlx4_dev *dev = gw->dev->dev; - struct ib_event event; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) { @@ -916,10 +915,7 @@ static void update_gids_task(struct work_struct *work) pr_warn("set port command failed\n"); else { memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids); - event.device = &gw->dev->ib_dev; - event.element.port_num = gw->port; - event.event = IB_EVENT_GID_CHANGE; - ib_dispatch_event(&event); + mlx4_ib_dispatch_event(gw->dev, gw->port, IB_EVENT_GID_CHANGE); } mlx4_free_cmd_mailbox(dev, mailbox); @@ -1383,10 +1379,18 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) } static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, - enum mlx4_dev_event event, int port) + enum mlx4_dev_event event, unsigned long param) { struct ib_event ibev; struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr); + struct mlx4_eqe *eqe = NULL; + struct ib_event_work *ew; + int port = 0; + + if (event == MLX4_DEV_EVENT_PORT_MGMT_CHANGE) + eqe = (struct mlx4_eqe *)param; + else + port = (u8)param; if (port > ibdev->num_ports) return; @@ -1405,6 +1409,19 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, ibev.event = IB_EVENT_DEVICE_FATAL; break; + case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: + ew = kmalloc(sizeof *ew, GFP_ATOMIC); + if (!ew) { + pr_err("failed to allocate memory for events work\n"); + break; + } + + INIT_WORK(&ew->work, handle_port_mgmt_change_event); + memcpy(&ew->ib_eqe, eqe, sizeof *eqe); + ew->ib_dev = ibdev; + handle_port_mgmt_change_event(&ew->work); + return; + default: return; } diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 5f298afaa81f..23bfbf9ee0e0 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -224,6 +224,12 @@ struct mlx4_ib_dev { int eq_added; }; +struct ib_event_work { + struct work_struct work; + struct mlx4_ib_dev *ib_dev; + struct mlx4_eqe ib_eqe; +}; + static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) { return container_of(ibdev, struct mlx4_ib_dev, ib_dev); @@ -381,4 +387,7 @@ static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah) int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, union ib_gid *gid); +void mlx4_ib_dispatch_event(struct mlx4_ib_dev *dev, u8 port_num, + enum ib_event_type type); + #endif /* MLX4_IB_H */ diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 69ba57270481..a52922ed85c1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -131,7 +131,7 @@ static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port) } static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, - enum mlx4_dev_event event, int port) + enum mlx4_dev_event event, unsigned long port) { struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; struct mlx4_en_priv *priv; @@ -156,7 +156,8 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, if (port < 1 || port > dev->caps.num_ports || !mdev->pndev[port]) return; - mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, port); + mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, + (int) port); } } diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index bce98d9c0039..9b15d0219950 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -82,6 +82,15 @@ enum { (1ull << MLX4_EVENT_TYPE_FLR_EVENT) | \ (1ull << MLX4_EVENT_TYPE_FATAL_WARNING)) +static u64 get_async_ev_mask(struct mlx4_dev *dev) +{ + u64 async_ev_mask = MLX4_ASYNC_EVENT_MASK; + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV) + async_ev_mask |= (1ull << MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT); + + return async_ev_mask; +} + static void eq_set_ci(struct mlx4_eq *eq, int req_not) { __raw_writel((__force u32) cpu_to_be32((eq->cons_index & 0xffffff) | @@ -473,6 +482,11 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) break; + case MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT: + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_MGMT_CHANGE, + (unsigned long) eqe); + break; + case MLX4_EVENT_TYPE_EEC_CATAS_ERROR: case MLX4_EVENT_TYPE_ECC_DETECT: default: @@ -956,7 +970,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) priv->eq_table.have_irq = 1; } - err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, + err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0, priv->eq_table.eq[dev->caps.num_comp_vectors].eqn); if (err) mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n", @@ -996,7 +1010,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int i; - mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1, + mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 1, priv->eq_table.eq[dev->caps.num_comp_vectors].eqn); mlx4_free_irqs(dev); @@ -1040,7 +1054,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev) mlx4_cmd_use_polling(dev); /* Map the new eq to handle all asyncronous events */ - err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, + err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0, priv->eq_table.eq[i].eqn); if (err) { mlx4_warn(dev, "Failed mapping eq for interrupt test\n"); @@ -1054,7 +1068,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev) } /* Return to default */ - mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, + mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0, priv->eq_table.eq[dev->caps.num_comp_vectors].eqn); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 4281ce09add8..ee9d6b0b4d20 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -109,6 +109,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags) [41] = "Unicast VEP steering support", [42] = "Multicast VEP steering support", [48] = "Counters support", + [59] = "Port management change event support", }; int i; diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index b4e9f6f5cc04..116895ac8b35 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -115,7 +115,8 @@ void mlx4_unregister_interface(struct mlx4_interface *intf) } EXPORT_SYMBOL_GPL(mlx4_unregister_interface); -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port) +void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, + unsigned long param) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_device_context *dev_ctx; @@ -125,7 +126,7 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int por list_for_each_entry(dev_ctx, &priv->ctx_list, list) if (dev_ctx->intf->event) - dev_ctx->intf->event(dev, dev_ctx->context, type, port); + dev_ctx->intf->event(dev, dev_ctx->context, type, param); spin_unlock_irqrestore(&priv->ctx_lock, flags); } diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index e5d20220762c..4d11d12b9db4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -338,66 +338,6 @@ struct mlx4_srq_context { __be64 db_rec_addr; }; -struct mlx4_eqe { - u8 reserved1; - u8 type; - u8 reserved2; - u8 subtype; - union { - u32 raw[6]; - struct { - __be32 cqn; - } __packed comp; - struct { - u16 reserved1; - __be16 token; - u32 reserved2; - u8 reserved3[3]; - u8 status; - __be64 out_param; - } __packed cmd; - struct { - __be32 qpn; - } __packed qp; - struct { - __be32 srqn; - } __packed srq; - struct { - __be32 cqn; - u32 reserved1; - u8 reserved2[3]; - u8 syndrome; - } __packed cq_err; - struct { - u32 reserved1[2]; - __be32 port; - } __packed port_change; - struct { - #define COMM_CHANNEL_BIT_ARRAY_SIZE 4 - u32 reserved; - u32 bit_vec[COMM_CHANNEL_BIT_ARRAY_SIZE]; - } __packed comm_channel_arm; - struct { - u8 port; - u8 reserved[3]; - __be64 mac; - } __packed mac_update; - struct { - u8 port; - } __packed sw_event; - struct { - __be32 slave_id; - } __packed flr_event; - struct { - __be16 current_temperature; - __be16 warning_threshold; - } __packed warming; - } event; - u8 slave_id; - u8 reserved3[2]; - u8 owner; -} __packed; - struct mlx4_eq { struct mlx4_dev *dev; void __iomem *doorbell; @@ -887,7 +827,8 @@ void mlx4_catas_init(void); int mlx4_restart_one(struct pci_dev *pdev); int mlx4_register_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev); -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port); +void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, + unsigned long param); struct mlx4_dev_cap; struct mlx4_init_hca_param; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 8eadf0f14cc5..560b2201519f 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -96,7 +96,8 @@ enum { MLX4_DEV_CAP_FLAG_VEP_UC_STEER = 1LL << 41, MLX4_DEV_CAP_FLAG_VEP_MC_STEER = 1LL << 42, MLX4_DEV_CAP_FLAG_COUNTERS = 1LL << 48, - MLX4_DEV_CAP_FLAG_SENSE_SUPPORT = 1LL << 55 + MLX4_DEV_CAP_FLAG_SENSE_SUPPORT = 1LL << 55, + MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV = 1LL << 59, }; enum { @@ -138,6 +139,7 @@ enum mlx4_event { MLX4_EVENT_TYPE_COMM_CHANNEL = 0x18, MLX4_EVENT_TYPE_FATAL_WARNING = 0x1b, MLX4_EVENT_TYPE_FLR_EVENT = 0x1c, + MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT = 0x1d, MLX4_EVENT_TYPE_NONE = 0xff, }; @@ -235,6 +237,24 @@ enum { MLX4_MAX_FAST_REG_PAGES = 511, }; +enum { + MLX4_DEV_PMC_SUBTYPE_GUID_INFO = 0x14, + MLX4_DEV_PMC_SUBTYPE_PORT_INFO = 0x15, + MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE = 0x16, +}; + +/* Port mgmt change event handling */ +enum { + MLX4_EQ_PORT_INFO_MSTR_SM_LID_CHANGE_MASK = 1 << 0, + MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK = 1 << 1, + MLX4_EQ_PORT_INFO_LID_CHANGE_MASK = 1 << 2, + MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK = 1 << 3, + MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK = 1 << 4, +}; + +#define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \ + MLX4_EQ_PORT_INFO_MSTR_SM_LID_CHANGE_MASK) + static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) { return (major << 32) | (minor << 16) | subminor; @@ -511,6 +531,81 @@ struct mlx4_dev { int num_vfs; }; +struct mlx4_eqe { + u8 reserved1; + u8 type; + u8 reserved2; + u8 subtype; + union { + u32 raw[6]; + struct { + __be32 cqn; + } __packed comp; + struct { + u16 reserved1; + __be16 token; + u32 reserved2; + u8 reserved3[3]; + u8 status; + __be64 out_param; + } __packed cmd; + struct { + __be32 qpn; + } __packed qp; + struct { + __be32 srqn; + } __packed srq; + struct { + __be32 cqn; + u32 reserved1; + u8 reserved2[3]; + u8 syndrome; + } __packed cq_err; + struct { + u32 reserved1[2]; + __be32 port; + } __packed port_change; + struct { + #define COMM_CHANNEL_BIT_ARRAY_SIZE 4 + u32 reserved; + u32 bit_vec[COMM_CHANNEL_BIT_ARRAY_SIZE]; + } __packed comm_channel_arm; + struct { + u8 port; + u8 reserved[3]; + __be64 mac; + } __packed mac_update; + struct { + __be32 slave_id; + } __packed flr_event; + struct { + __be16 current_temperature; + __be16 warning_threshold; + } __packed warming; + struct { + u8 reserved[3]; + u8 port; + union { + struct { + __be16 mstr_sm_lid; + __be16 port_lid; + __be32 changed_attr; + u8 reserved[3]; + u8 mstr_sm_sl; + __be64 gid_prefix; + } __packed port_info; + struct { + __be32 block_ptr; + __be32 tbl_entries_mask; + } __packed tbl_change_info; + } params; + } __packed port_mgmt_change; + } event; + u8 slave_id; + u8 reserved3[2]; + u8 owner; +} __packed; + struct mlx4_init_port_param { int set_guid0; int set_node_guid; @@ -536,6 +631,8 @@ struct mlx4_init_port_param { #define MLX4_INVALID_SLAVE_ID 0xFF +void handle_port_mgmt_change_event(struct work_struct *work); + static inline int mlx4_is_master(struct mlx4_dev *dev) { return dev->flags & MLX4_FLAG_MASTER; diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h index 5f1298b1b5ef..0f509229fb3d 100644 --- a/include/linux/mlx4/driver.h +++ b/include/linux/mlx4/driver.h @@ -42,13 +42,14 @@ enum mlx4_dev_event { MLX4_DEV_EVENT_PORT_UP, MLX4_DEV_EVENT_PORT_DOWN, MLX4_DEV_EVENT_PORT_REINIT, + MLX4_DEV_EVENT_PORT_MGMT_CHANGE, }; struct mlx4_interface { void * (*add) (struct mlx4_dev *dev); void (*remove)(struct mlx4_dev *dev, void *context); void (*event) (struct mlx4_dev *dev, void *context, - enum mlx4_dev_event event, int port); + enum mlx4_dev_event event, unsigned long param); void * (*get_dev)(struct mlx4_dev *dev, void *context, u8 port); struct list_head list; enum mlx4_protocol protocol; -- GitLab From 2aca1172c2f5b27fbc37297574f716c1c15f4153 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:41 +0300 Subject: [PATCH 2447/5711] net/mlx4_core: Initialize IB port capabilities for all slaves With IB SR-IOV, each slave has its own separate copy of the port capabilities flags. For example, the master can run a subnet manager (which causes the IsSM bit to be set in the master's port capabilities) without affecting the port capabilities seen by the slaves (the IsSM bit will be seen as cleared in the slaves). Also add a static inline mlx4_master_func_num() to enhance readability of the code. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/main.c | 11 +++++++++++ include/linux/mlx4/device.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index a0313de122de..83afb1541a74 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1477,6 +1477,17 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) "with caps = 0\n", port, err); dev->caps.ib_port_def_cap[port] = ib_port_default_caps; + /* initialize per-slave default ib port capabilities */ + if (mlx4_is_master(dev)) { + int i; + for (i = 0; i < dev->num_slaves; i++) { + if (i == mlx4_master_func_num(dev)) + continue; + priv->mfunc.master.slave_state[i].ib_cap_mask[port] = + ib_port_default_caps; + } + } + if (mlx4_is_mfunc(dev)) dev->caps.port_ib_mtu[port] = IB_MTU_2048; else diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 560b2201519f..7fbdc89de495 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -633,6 +633,11 @@ struct mlx4_init_port_param { void handle_port_mgmt_change_event(struct work_struct *work); +static inline int mlx4_master_func_num(struct mlx4_dev *dev) +{ + return dev->caps.function; +} + static inline int mlx4_is_master(struct mlx4_dev *dev) { return dev->flags & MLX4_FLAG_MASTER; -- GitLab From 7e23017704172cb6508cb365eb2cae7335e5da71 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 6 Jul 2012 18:29:45 +0000 Subject: [PATCH 2448/5711] IB/qib: Fix sparse RCU warnings in qib_keys.c Commit 8aac4cc3a9d7 ("IB/qib: RCU locking for MR validation") introduced new sparse warnings in qib_keys.c. Acked-by: Fengguang Wu Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_keys.c | 4 +++- drivers/infiniband/hw/qib/qib_verbs.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c index 970165b027f7..e9486c74c226 100644 --- a/drivers/infiniband/hw/qib/qib_keys.c +++ b/drivers/infiniband/hw/qib/qib_keys.c @@ -349,7 +349,9 @@ int qib_fast_reg_mr(struct qib_qp *qp, struct ib_send_wr *wr) if (pd->user || rkey == 0) goto bail; - mr = rkt->table[(rkey >> (32 - ib_qib_lkey_table_size))]; + mr = rcu_dereference_protected( + rkt->table[(rkey >> (32 - ib_qib_lkey_table_size))], + lockdep_is_held(&rkt->lock)); if (unlikely(mr == NULL || qp->ibqp.pd != mr->pd)) goto bail; diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 85751fd74371..1293133f28cb 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -650,7 +650,7 @@ struct qib_lkey_table { u32 next; /* next unused index (speeds search) */ u32 gen; /* generation count */ u32 max; /* size of the table */ - struct qib_mregion **table; + struct qib_mregion __rcu **table; }; struct qib_opcode_stats { @@ -732,7 +732,7 @@ struct qib_ibdev { struct list_head pending_mmaps; spinlock_t mmap_offset_lock; /* protect mmap_offset */ u32 mmap_offset; - struct qib_mregion *dma_mr; + struct qib_mregion __rcu *dma_mr; /* QP numbers are shared by all IB ports */ struct qib_qpn_table qpn_table; -- GitLab From 21cd1fab058671313f7c178b640999fcd0d8de21 Mon Sep 17 00:00:00 2001 From: Jon Brenner Date: Wed, 16 May 2012 10:46:42 -0500 Subject: [PATCH 2449/5711] IIO channel type and modifiers for CCT and RGBC data Add iio channel type and modifiers for Correlated Color Temperature (CCT) and RGBC (red/green/blue/clear) data. Add CCT and RGBC descriptions to documentation. Changes: Revised/condensed RGBC descriptions. Merge and trivial fix done by Jonathan Cameron. Signed-off-by: Jon Brenner Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 5 ++++ .../iio/Documentation/sysfs-bus-iio-light | 23 +++++++++++++++++++ include/linux/iio/types.h | 5 ++++ 3 files changed, 33 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index bb3c692e49b8..2ec266ef41a3 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -64,6 +64,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_TIMESTAMP] = "timestamp", [IIO_CAPACITANCE] = "capacitance", [IIO_ALTVOLTAGE] = "altvoltage", + [IIO_CCT] = "cct", }; static const char * const iio_modifier_names[] = { @@ -74,6 +75,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", [IIO_MOD_LIGHT_BOTH] = "both", [IIO_MOD_LIGHT_IR] = "ir", + [IIO_MOD_LIGHT_CLEAR] = "clear", + [IIO_MOD_LIGHT_RED] = "red", + [IIO_MOD_LIGHT_GREEN] = "green", + [IIO_MOD_LIGHT_BLUE] = "blue", }; /* relies on pairs of these shared then separate */ diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index d52be0385dc4..a28919da13e3 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -82,3 +82,26 @@ Contact: linux-iio@vger.kernel.org Description: This property gets/sets the table of coefficients used in calculating illuminance in lux. + +What: /sys/bus/iio/devices/device[n]/in_intensity_clear[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_red[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_green[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_blue[_input|_raw] +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + This property is supported by sensors that have a RGBC + sensing mode. This value should be the output from a reading + and if expressed in SI units, should include _input. If this + value is not in SI units (irradiance, uW/mm^2), then it should + include _raw. + +What: /sys/bus/iio/devices/device[n]/in_cct0[_input|_raw] +KernelVersion: 3.4.0 +Contact: linux-iio@vger.kernel.org +Description: + This should return the correlated color temperature from the + light sensor. If it comes back in SI units, it should also + include _input else it should include _raw to signify it is not + in SI units. + diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index e25040173346..44e397705d7f 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -27,6 +27,7 @@ enum iio_chan_type { IIO_TIMESTAMP, IIO_CAPACITANCE, IIO_ALTVOLTAGE, + IIO_CCT, }; enum iio_modifier { @@ -46,6 +47,10 @@ enum iio_modifier { IIO_MOD_LIGHT_IR, IIO_MOD_ROOT_SUM_SQUARED_X_Y, IIO_MOD_SUM_SQUARED_X_Y_Z, + IIO_MOD_LIGHT_CLEAR, + IIO_MOD_LIGHT_RED, + IIO_MOD_LIGHT_GREEN, + IIO_MOD_LIGHT_BLUE, }; #define IIO_VAL_INT 1 -- GitLab From 2930d381d22b9c56f40dd4c63a8fa59719ca2c3c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 5 Jun 2012 16:52:06 -0400 Subject: [PATCH 2450/5711] nfsd4: our filesystems are normally case sensitive Actually, xfs and jfs can optionally be case insensitive; we'll handle that case in later patches. Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 4949667c84ea..6322df36031f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2259,7 +2259,7 @@ out_acl: if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { if ((buflen -= 4) < 0) goto out_resource; - WRITE32(1); + WRITE32(0); } if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { if ((buflen -= 4) < 0) -- GitLab From d05b2fe037d0a6996a357af85b8e18229e534568 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 10 Jul 2012 20:30:55 +0100 Subject: [PATCH 2451/5711] iio: Trivial documentation fix to correct kernel version info in 21cd1fab058671313f7c178b640999fcd0d8de21 Signed-off-by: Jonathan Cameron Reported-by: Peter Meerwald --- drivers/staging/iio/Documentation/sysfs-bus-iio-light | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index a28919da13e3..17e5c9c515d4 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -87,7 +87,7 @@ What: /sys/bus/iio/devices/device[n]/in_intensity_clear[_input|_raw] What: /sys/bus/iio/devices/device[n]/in_intensity_red[_input|_raw] What: /sys/bus/iio/devices/device[n]/in_intensity_green[_input|_raw] What: /sys/bus/iio/devices/device[n]/in_intensity_blue[_input|_raw] -KernelVersion: 3.4.0 +KernelVersion: 3.6.0 Contact: linux-iio@vger.kernel.org Description: This property is supported by sensors that have a RGBC @@ -97,7 +97,7 @@ Description: include _raw. What: /sys/bus/iio/devices/device[n]/in_cct0[_input|_raw] -KernelVersion: 3.4.0 +KernelVersion: 3.6.0 Contact: linux-iio@vger.kernel.org Description: This should return the correlated color temperature from the -- GitLab From 737b719ed6569ffcd015fcdf3039dc7af47af877 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 9 Jul 2012 14:00:38 -0700 Subject: [PATCH 2452/5711] mm, slub: ensure irqs are enabled for kmemcheck kmemcheck_alloc_shadow() requires irqs to be enabled, so wait to disable them until after its called for __GFP_WAIT allocations. This fixes a warning for such allocations: WARNING: at kernel/lockdep.c:2739 lockdep_trace_alloc+0x14e/0x1c0() Acked-by: Fengguang Wu Acked-by: Steven Rostedt Tested-by: Fengguang Wu Signed-off-by: David Rientjes Signed-off-by: Pekka Enberg --- mm/slub.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 0e0504ed6ff1..e517d435e5dc 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1299,13 +1299,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) stat(s, ORDER_FALLBACK); } - if (flags & __GFP_WAIT) - local_irq_disable(); - - if (!page) - return NULL; - - if (kmemcheck_enabled + if (kmemcheck_enabled && page && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) { int pages = 1 << oo_order(oo); @@ -1321,6 +1315,11 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) kmemcheck_mark_unallocated_pages(page, pages); } + if (flags & __GFP_WAIT) + local_irq_disable(); + if (!page) + return NULL; + page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? -- GitLab From 74dbafaf5d84b5187e50dbe82442ec8df66d55b3 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 6 Jun 2012 12:53:48 -0400 Subject: [PATCH 2453/5711] nfsd4: release openowners on free in >=4.1 case We don't need to keep openowners around in the >=4.1 case, because they aren't needed to handle CLOSE replays any more (that's a problem for sessions). And doing so causes unexpected failures on a subsequent destroy_clientid to fail. We probably also need something comparable for lock owners on last unlock. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9efa4055b5a8..e404fca08260 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3763,12 +3763,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfsd4_close_open_stateid(stp); oo->oo_last_closed_stid = stp; - /* place unused nfs4_stateowners on so_close_lru list to be - * released by the laundromat service after the lease period - * to enable us to handle CLOSE replay - */ - if (list_empty(&oo->oo_owner.so_stateids)) - move_to_close_lru(oo); + if (list_empty(&oo->oo_owner.so_stateids)) { + if (cstate->minorversion) { + release_openowner(oo); + cstate->replay_owner = NULL; + } else { + /* + * In the 4.0 case we need to keep the owners around a + * little while to handle CLOSE replay. + */ + if (list_empty(&oo->oo_owner.so_stateids)) + move_to_close_lru(oo); + } + } out: if (!cstate->replay_owner) nfs4_unlock_state(); -- GitLab From d91d0b569044ab366895d587d4811b154dd7d7f5 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 6 Jun 2012 12:12:57 -0400 Subject: [PATCH 2454/5711] nfsd: allow owner_override only for regular files We normally allow the owner of a file to override permissions checks on IO operations, since: - the client will take responsibility for doing an access check on open; - the permission checks offer no protection against malicious clients--if they can authenticate as the file's owner then they can always just change its permissions; - checking permission on each IO operation breaks the usual posix rule that permission is checked only on open. However, we've never allowed the owner to override permissions on readdir operations, even though the above logic would also apply to directories. I've never heard of this causing a problem, probably because a) simultaneously opening and creating a directory (with restricted mode) isn't possible, and b) opening a directory, then chmod'ing it, is rare. Our disallowal of owner-override on directories appears to be an accident, though--the readdir itself succeeds, and then we fail just because lookup_one_len() calls in our filldir methods fail. I'm not sure what the easiest fix for that would be. For now, just make this behavior obvious by denying the override right at the start. This also fixes some odd v4 behavior: with the rdattr_error attribute requested, it would perform the readdir but return an ACCES error with each entry. Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index c8bd9c3be7f7..3256b5c324bc 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -757,8 +757,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, * If we get here, then the client has already done an "open", * and (hopefully) checked permission - so allow OWNER_OVERRIDE * in case a chmod has now revoked permission. + * + * Arguably we should also allow the owner override for + * directories, but we never have and it doesn't seem to have + * caused anyone a problem. If we were to change this, note + * also that our filldir callbacks would need a variant of + * lookup_one_len that doesn't check permissions. */ - err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE); + if (type == S_IFREG) + may_flags |= NFSD_MAY_OWNER_OVERRIDE; + err = fh_verify(rqstp, fhp, type, may_flags); if (err) goto out; -- GitLab From 7f2e7dc0fdd9f124da43d1bd12adcebf92bedf16 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 12 Jun 2012 16:06:29 -0400 Subject: [PATCH 2455/5711] nfsd: share some function prototypes Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 1671429ffa66..6d425c2f9fcd 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -72,6 +72,8 @@ int nfsd_nrthreads(void); int nfsd_nrpools(void); int nfsd_get_nrthreads(int n, int *); int nfsd_set_nrthreads(int n, int *); +int nfsd_pool_stats_open(struct inode *, struct file *); +int nfsd_pool_stats_release(struct inode *, struct file *); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL -- GitLab From e735a80bd57d6b04e1c8f30da762ed0c6af5ee6a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 23 Jun 2012 00:42:01 -0700 Subject: [PATCH 2456/5711] PCI: acpiphp: remove unused res_lock res_lock is never used, so remove it. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp.h | 2 -- drivers/pci/hotplug/acpiphp_glue.c | 3 --- 2 files changed, 5 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7722108e78df..6b58ed0432e9 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -89,8 +89,6 @@ struct acpiphp_bridge { /* PCI-to-PCI bridge device */ struct pci_dev *pci_dev; - - spinlock_t res_lock; }; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645a..7dc8dd00135a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -391,8 +391,6 @@ static void add_host_bridge(acpi_handle *handle) bridge->pci_bus = root->bus; - spin_lock_init(&bridge->res_lock); - init_bridge_misc(bridge); } @@ -425,7 +423,6 @@ static void add_p2p_bridge(acpi_handle *handle) * (which we access during module unload). */ get_device(&bridge->pci_bus->dev); - spin_lock_init(&bridge->res_lock); init_bridge_misc(bridge); return; -- GitLab From 4a0d6a74638f44055ea536abdd428007e5f2f89e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:49 +0300 Subject: [PATCH 2457/5711] mei: mei_device can be const for mei register access functions Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei_dev.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index d60250d663c6..772f74dcd2ad 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -363,7 +363,8 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid); * * returns register value (u32) */ -static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset) +static inline u32 mei_reg_read(const struct mei_device *dev, + unsigned long offset) { return ioread32(dev->mem_addr + offset); } @@ -375,8 +376,8 @@ static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset) * @offset: offset from which to write the data * @value: register value to write (u32) */ -static inline void mei_reg_write(struct mei_device *dev, - unsigned long offset, u32 value) +static inline void mei_reg_write(const struct mei_device *dev, + unsigned long offset, u32 value) { iowrite32(value, dev->mem_addr + offset); } @@ -388,7 +389,7 @@ static inline void mei_reg_write(struct mei_device *dev, * * returns the byte read. */ -static inline u32 mei_hcsr_read(struct mei_device *dev) +static inline u32 mei_hcsr_read(const struct mei_device *dev) { return mei_reg_read(dev, H_CSR); } @@ -400,7 +401,7 @@ static inline u32 mei_hcsr_read(struct mei_device *dev) * * returns ME_CSR_HA register value (u32) */ -static inline u32 mei_mecsr_read(struct mei_device *dev) +static inline u32 mei_mecsr_read(const struct mei_device *dev) { return mei_reg_read(dev, ME_CSR_HA); } @@ -412,7 +413,7 @@ static inline u32 mei_mecsr_read(struct mei_device *dev) * * returns ME_CB_RW register value (u32) */ -static inline u32 mei_mecbrw_read(struct mei_device *dev) +static inline u32 mei_mecbrw_read(const struct mei_device *dev) { return mei_reg_read(dev, ME_CB_RW); } -- GitLab From d242a0afb2e5bf1db83c6a0504e55addef425e61 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:50 +0300 Subject: [PATCH 2458/5711] mei: remove write only wariable wd_due_counter Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 1 - drivers/misc/mei/interrupt.c | 12 ++++-------- drivers/misc/mei/mei_dev.h | 1 - drivers/misc/mei/wd.c | 3 --- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index d39b2774535b..e77f86e69fb5 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -306,7 +306,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->iamthif_cl.host_client_id); mei_reset_iamthif_params(dev); - dev->wd_due_counter = 0; dev->extra_write_index = 0; } diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 1872a2a760e5..4c1afcf6f4e9 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -575,10 +575,9 @@ static void mei_client_disconnect_request(struct mei_device *dev, disconnect_req->me_addr); cl_pos->state = MEI_FILE_DISCONNECTED; cl_pos->timer_count = 0; - if (cl_pos == &dev->wd_cl) { - dev->wd_due_counter = 0; + if (cl_pos == &dev->wd_cl) dev->wd_pending = false; - } else if (cl_pos == &dev->iamthif_cl) + else if (cl_pos == &dev->iamthif_cl) dev->iamthif_timer = 0; /* prepare disconnect response */ @@ -1266,15 +1265,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; - if (dev->wd_timeout) { + if (dev->wd_timeout) *slots -= (sizeof(struct mei_msg_hdr) + MEI_START_WD_DATA_SIZE + 3) / 4; - dev->wd_due_counter = 2; - } else { + else *slots -= (sizeof(struct mei_msg_hdr) + MEI_WD_PARAMS_SIZE + 3) / 4; - dev->wd_due_counter = 0; - } } } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 772f74dcd2ad..d61c4ddfc80c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -246,7 +246,6 @@ struct mei_device { bool wd_stopped; bool wd_bypass; /* if false, don't refresh watchdog ME client */ u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ - u16 wd_due_counter; unsigned char wd_data[MEI_START_WD_DATA_SIZE]; diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 6be5605707b4..325d26f29746 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -137,7 +137,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) return 0; dev->wd_timeout = 0; - dev->wd_due_counter = 0; memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE); dev->stop = true; @@ -357,8 +356,6 @@ void mei_watchdog_register(struct mei_device *dev) { dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout); - dev->wd_due_counter = !!dev->wd_timeout; - if (watchdog_register_device(&amt_wd_dev)) { dev_err(&dev->pdev->dev, "wd: unable to register watchdog device.\n"); -- GitLab From 7cb1ba9b679afe5fc335205fd6fb25fd3e51e33a Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:51 +0300 Subject: [PATCH 2459/5711] mei: mei_wd_host_init: update the comment Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/wd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 325d26f29746..0a893389f6cb 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -53,11 +53,12 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) } /** - * host_init_wd - mei initialization wd. + * mei_wd_host_init - connect to the watchdog client * * @dev: the device structure * returns -ENENT if wd client cannot be found * -EIO if write has failed + * 0 on success */ int mei_wd_host_init(struct mei_device *dev) { -- GitLab From 7bdf72d3d8059a50214069ea4b87c2174645f40f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:52 +0300 Subject: [PATCH 2460/5711] mei: introduce mei_data2slots wrapper Introduce mei_data2slots wrapper for sake of readability. This wrapper close up the open code for computing slots from a message length: rond up dwords count from payload and header byte size Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interface.c | 2 +- drivers/misc/mei/interface.h | 6 ++++++ drivers/misc/mei/interrupt.c | 33 +++++++++++---------------------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 88ada64c0b54..509c3957ff45 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c @@ -135,7 +135,7 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, empty_slots = mei_hbuf_empty_slots(dev); dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); - dw_cnt = (length + sizeof(*header) + 3) / 4; + dw_cnt = mei_data2slots(length); if (empty_slots < 0 || dw_cnt > empty_slots) return -EIO; diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index cd9b778e8dc5..fb5c7db4723b 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -50,6 +50,12 @@ static inline size_t mei_hbuf_max_data(const struct mei_device *dev) return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); } +/* get slots (dwords) from a message length + header (bytes) */ +static inline unsigned char mei_data2slots(size_t length) +{ + return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); +} + int mei_count_full_read_slots(struct mei_device *dev); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 4c1afcf6f4e9..92d762100268 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -267,8 +267,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) + sizeof(struct hbm_flow_control))) { return -EMSGSIZE; } - *slots -= (sizeof(struct mei_msg_hdr) + - sizeof(struct hbm_flow_control) + 3) / 4; + *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); if (mei_send_flow_control(dev, &dev->iamthif_cl)) { dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); return -EIO; @@ -302,8 +301,7 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, { if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + sizeof(struct hbm_client_disconnect_request))) { - *slots -= (sizeof(struct mei_msg_hdr) + - sizeof(struct hbm_client_disconnect_request) + 3) / 4; + *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request)); if (mei_disconnect(dev, cl)) { cl->status = 0; @@ -841,8 +839,8 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, return -EBADMSG; } - *slots -= (sizeof(struct mei_msg_hdr) + - sizeof(struct hbm_flow_control) + 3) / 4; + *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); + if (mei_send_flow_control(dev, cl)) { cl->status = -ENODEV; cb_pos->information = 0; @@ -874,8 +872,7 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + sizeof(struct hbm_client_connect_request))) { cl->state = MEI_FILE_CONNECTING; - *slots -= (sizeof(struct mei_msg_hdr) + - sizeof(struct hbm_client_connect_request) + 3) / 4; + *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); if (mei_connect(dev, cl)) { cl->status = -ENODEV; cb_pos->information = 0; @@ -931,8 +928,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, cb_pos->information); dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length); - *slots -= (sizeof(struct mei_msg_hdr) + - mei_hdr->length + 3) / 4; + *slots -= mei_data2slots(mei_hdr->length); if (mei_write_message(dev, mei_hdr, (unsigned char *) (cb_pos->request_buffer.data + @@ -959,9 +955,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); mei_hdr->msg_complete = 0; mei_hdr->reserved = 0; - - (*slots) -= (sizeof(struct mei_msg_hdr) + - mei_hdr->length + 3) / 4; + *slots -= mei_data2slots(mei_hdr->length); if (mei_write_message(dev, mei_hdr, (unsigned char *) (cb_pos->request_buffer.data + @@ -1020,8 +1014,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, mei_hdr->msg_complete = 1; mei_hdr->reserved = 0; - *slots -= (sizeof(struct mei_msg_hdr) + - mei_hdr->length + 3) / 4; + *slots -= mei_data2slots(mei_hdr->length); if (mei_write_message(dev, mei_hdr, (dev->iamthif_msg_buf + @@ -1055,8 +1048,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, mei_hdr->msg_complete = 0; mei_hdr->reserved = 0; - *slots -= (sizeof(struct mei_msg_hdr) + - mei_hdr->length + 3) / 4; + *slots -= mei_data2slots(mei_hdr->length); if (mei_write_message(dev, mei_hdr, (dev->iamthif_msg_buf + @@ -1266,12 +1258,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; if (dev->wd_timeout) - *slots -= (sizeof(struct mei_msg_hdr) + - MEI_START_WD_DATA_SIZE + 3) / 4; + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); else - *slots -= (sizeof(struct mei_msg_hdr) + - MEI_WD_PARAMS_SIZE + 3) / 4; - + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); } } if (dev->stop) -- GitLab From b45f3ccf80fb3e9e86bba2ad3640880d6fe85bfc Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:53 +0300 Subject: [PATCH 2461/5711] mei: streamline the _mei_irq_thread_close/ioctol functions change statements of types if (ok) do something else return err into if (err) return err do something Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 63 +++++++++++++++++------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 92d762100268..b4afc1211fd2 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -299,27 +299,25 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, struct mei_cl *cl, struct mei_io_list *cmpl_list) { - if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + - sizeof(struct hbm_client_disconnect_request))) { - *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request)); + if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + + sizeof(struct hbm_client_disconnect_request))) + return -EBADMSG; - if (mei_disconnect(dev, cl)) { - cl->status = 0; - cb_pos->information = 0; - list_move_tail(&cb_pos->cb_list, - &cmpl_list->mei_cb.cb_list); - return -EMSGSIZE; - } else { - cl->state = MEI_FILE_DISCONNECTING; - cl->status = 0; - cb_pos->information = 0; - list_move_tail(&cb_pos->cb_list, - &dev->ctrl_rd_list.mei_cb.cb_list); - cl->timer_count = MEI_CONNECT_TIMEOUT; - } + *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request)); + + if (mei_disconnect(dev, cl)) { + cl->status = 0; + cb_pos->information = 0; + list_move_tail(&cb_pos->cb_list, + &cmpl_list->mei_cb.cb_list); + return -EMSGSIZE; } else { - /* return the cancel routine */ - return -EBADMSG; + cl->state = MEI_FILE_DISCONNECTING; + cl->status = 0; + cb_pos->information = 0; + list_move_tail(&cb_pos->cb_list, + &dev->ctrl_rd_list.mei_cb.cb_list); + cl->timer_count = MEI_CONNECT_TIMEOUT; } return 0; @@ -869,26 +867,25 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, struct mei_cl *cl, struct mei_io_list *cmpl_list) { - if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + + if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + sizeof(struct hbm_client_connect_request))) { - cl->state = MEI_FILE_CONNECTING; - *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); - if (mei_connect(dev, cl)) { - cl->status = -ENODEV; - cb_pos->information = 0; - list_del(&cb_pos->cb_list); - return -ENODEV; - } else { - list_move_tail(&cb_pos->cb_list, - &dev->ctrl_rd_list.mei_cb.cb_list); - cl->timer_count = MEI_CONNECT_TIMEOUT; - } - } else { /* return the cancel routine */ list_del(&cb_pos->cb_list); return -EBADMSG; } + cl->state = MEI_FILE_CONNECTING; + *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); + if (mei_connect(dev, cl)) { + cl->status = -ENODEV; + cb_pos->information = 0; + list_del(&cb_pos->cb_list); + return -ENODEV; + } else { + list_move_tail(&cb_pos->cb_list, + &dev->ctrl_rd_list.mei_cb.cb_list); + cl->timer_count = MEI_CONNECT_TIMEOUT; + } return 0; } -- GitLab From 483136ea0e2b23f2aebf57e1a36a06dec4223a92 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:54 +0300 Subject: [PATCH 2462/5711] mei: mei_irq_thread_write_handler - line break fix 1. straight up lines that doesn't cross 80 characters 2. don't break strings Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 44 +++++++++++++----------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index b4afc1211fd2..b428b3fe4092 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1199,8 +1199,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); list = &dev->write_waiting_list; - list_for_each_entry_safe(pos, next, - &list->mei_cb.cb_list, cb_list) { + list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) { cl = (struct mei_cl *)pos->file_private; if (cl == NULL) continue; @@ -1210,17 +1209,15 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, if (MEI_WRITING == cl->writing_state && (pos->major_file_operations == MEI_WRITE) && (cl != &dev->iamthif_cl)) { - dev_dbg(&dev->pdev->dev, - "MEI WRITE COMPLETE\n"); + dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); cl->writing_state = MEI_WRITE_COMPLETE; list_add_tail(&pos->cb_list, - &cmpl_list->mei_cb.cb_list); + &cmpl_list->mei_cb.cb_list); } if (cl == &dev->iamthif_cl) { dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); if (dev->iamthif_flow_control_pending) { - ret = _mei_irq_thread_iamthif_read( - dev, slots); + ret = _mei_irq_thread_iamthif_read(dev, slots); if (ret) return ret; } @@ -1245,12 +1242,11 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, } if (dev->mei_state == MEI_ENABLED) { if (dev->wd_pending && - mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { + mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { if (mei_wd_send(dev)) dev_dbg(&dev->pdev->dev, "wd send failed.\n"); - else - if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) - return -ENODEV; + else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) + return -ENODEV; dev->wd_pending = false; @@ -1305,7 +1301,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, /* complete write list CB */ dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); list_for_each_entry_safe(pos, next, - &dev->write_list.mei_cb.cb_list, cb_list) { + &dev->write_list.mei_cb.cb_list, cb_list) { cl = (struct mei_cl *)pos->file_private; if (cl == NULL) continue; @@ -1313,15 +1309,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, if (cl != &dev->iamthif_cl) { if (mei_flow_ctrl_creds(dev, cl) <= 0) { dev_dbg(&dev->pdev->dev, - "No flow control" - " credentials for client" - " %d, not sending.\n", - cl->host_client_id); + "No flow control credentials for client %d, not sending.\n", + cl->host_client_id); continue; } - ret = _mei_irq_thread_cmpl(dev, slots, - pos, - cl, cmpl_list); + ret = _mei_irq_thread_cmpl(dev, slots, pos, + cl, cmpl_list); if (ret) return ret; @@ -1330,17 +1323,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n"); if (mei_flow_ctrl_creds(dev, cl) <= 0) { dev_dbg(&dev->pdev->dev, - "No flow control" - " credentials for amthi" - " client %d.\n", - cl->host_client_id); + "No flow control credentials for amthi client %d.\n", + cl->host_client_id); continue; } - ret = _mei_irq_thread_cmpl_iamthif(dev, - slots, - pos, - cl, - cmpl_list); + ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos, + cl, cmpl_list); if (ret) return ret; -- GitLab From 2ac45f28b8eeef576c48579833b40b572f3f9790 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 23 Jun 2012 00:42:03 -0700 Subject: [PATCH 2463/5711] PCI: acpiphp: merge acpiphp_debug and debug Should not have two, just remove debug, and use module_param_named instead. Also change acpiphp_debug to bool. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp.h | 2 +- drivers/pci/hotplug/acpiphp_core.c | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6b58ed0432e9..a1afb5b39ad4 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -205,6 +205,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); /* variables */ -extern int acpiphp_debug; +extern bool acpiphp_debug; #endif /* _ACPIPHP_H */ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index aa41631e9e02..96316b74969f 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -47,8 +47,7 @@ /* name size which is used for entries in pcihpfs */ #define SLOT_NAME_SIZE 21 /* {_SUN} */ -static bool debug; -int acpiphp_debug; +bool acpiphp_debug; /* local variables */ static int num_slots; @@ -62,7 +61,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(debug, bool, 0644); +module_param_named(debug, acpiphp_debug, bool, 0644); /* export the attention callback registration methods */ EXPORT_SYMBOL_GPL(acpiphp_register_attention); @@ -379,8 +378,6 @@ static int __init acpiphp_init(void) if (acpi_pci_disabled) return 0; - acpiphp_debug = debug; - /* read all the ACPI info from the system */ return init_acpi(); } -- GitLab From 1af8ea862c9a9a6d5dc100850036cc7a641bb242 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Wed, 11 Jul 2012 11:06:10 +0800 Subject: [PATCH 2464/5711] crypto: caam - Using alloc_coherent for caam job rings The caam job rings (input/output job ring) are allocated using dma_map_single(). These job rings can be visualized as the ring buffers in which the jobs are en-queued/de-queued. The s/w enqueues the jobs in input job ring which h/w dequeues and after processing it copies the jobs in output job ring. Software then de-queues the job from output ring. Using dma_map/unmap_single() is not preferred way to allocate memory for this type of requirements because this adds un-necessary complexity. Example, if bounce buffer (SWIOTLB) will get used then to make any change visible in this memory to other processing unit requires dmap_unmap_single() or dma_sync_single_for_cpu/device(). The dma_unmap_single() can not be used as this will free the bounce buffer, this will require changing the job rings on running system and I seriously doubt that it will be not possible or very complex to implement. Also using dma_sync_single_for_cpu/device() will also add unnecessary complexity. The simple and preferred way is using dma_alloc_coherent() for these type of memory requirements. This resolves the Linux boot crash issue when "swiotlb=force" is set in bootargs on systems which have memory more than 4G. Signed-off-by: Bharat Bhushan Acked-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/jr.c | 45 ++++++++-------------------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 7074a1a29e8b..53c8c51d5881 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -339,10 +339,11 @@ static int caam_jr_init(struct device *dev) if (error) return error; - jrp->inpring = kzalloc(sizeof(dma_addr_t) * JOBR_DEPTH, - GFP_KERNEL | GFP_DMA); - jrp->outring = kzalloc(sizeof(struct jr_outentry) * - JOBR_DEPTH, GFP_KERNEL | GFP_DMA); + jrp->inpring = dma_alloc_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH, + &inpbusaddr, GFP_KERNEL); + + jrp->outring = dma_alloc_coherent(dev, sizeof(struct jr_outentry) * + JOBR_DEPTH, &outbusaddr, GFP_KERNEL); jrp->entinfo = kzalloc(sizeof(struct caam_jrentry_info) * JOBR_DEPTH, GFP_KERNEL); @@ -358,31 +359,6 @@ static int caam_jr_init(struct device *dev) jrp->entinfo[i].desc_addr_dma = !0; /* Setup rings */ - inpbusaddr = dma_map_single(dev, jrp->inpring, - sizeof(dma_addr_t) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - if (dma_mapping_error(dev, inpbusaddr)) { - dev_err(dev, "caam_jr_init(): can't map input ring\n"); - kfree(jrp->inpring); - kfree(jrp->outring); - kfree(jrp->entinfo); - return -EIO; - } - - outbusaddr = dma_map_single(dev, jrp->outring, - sizeof(struct jr_outentry) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - if (dma_mapping_error(dev, outbusaddr)) { - dev_err(dev, "caam_jr_init(): can't map output ring\n"); - dma_unmap_single(dev, inpbusaddr, - sizeof(dma_addr_t) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - kfree(jrp->inpring); - kfree(jrp->outring); - kfree(jrp->entinfo); - return -EIO; - } - jrp->inp_ring_write_index = 0; jrp->out_ring_read_index = 0; jrp->head = 0; @@ -426,13 +402,10 @@ int caam_jr_shutdown(struct device *dev) /* Free rings */ inpbusaddr = rd_reg64(&jrp->rregs->inpring_base); outbusaddr = rd_reg64(&jrp->rregs->outring_base); - dma_unmap_single(dev, outbusaddr, - sizeof(struct jr_outentry) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - dma_unmap_single(dev, inpbusaddr, sizeof(dma_addr_t) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - kfree(jrp->outring); - kfree(jrp->inpring); + dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH, + jrp->inpring, inpbusaddr); + dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH, + jrp->outring, outbusaddr); kfree(jrp->entinfo); return ret; -- GitLab From 82c2f9607b8a4667e9d89613478748f4e2b7288b Mon Sep 17 00:00:00 2001 From: Alex Porosanu Date: Wed, 11 Jul 2012 11:06:11 +0800 Subject: [PATCH 2465/5711] crypto: caam - ERA retrieval and printing for SEC device This patch adds support for retrieving and printing of SEC ERA information. It is useful for knowing beforehand what features exist from the SEC point of view on a certain SoC. Only era-s 1 to 4 are currently supported; other eras will appear as unknown. Signed-off-by: Alex Porosanu - rebased onto current cryptodev master - made caam_eras static Signed-off-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/ctrl.c | 41 ++++++++++++++++++++++++++++++++++++-- drivers/crypto/caam/ctrl.h | 13 ++++++++++++ drivers/crypto/caam/regs.h | 6 ++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 drivers/crypto/caam/ctrl.h diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index ac6abb375c8d..414ba20c05a1 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -11,6 +11,7 @@ #include "jr.h" #include "desc_constr.h" #include "error.h" +#include "ctrl.h" static int caam_remove(struct platform_device *pdev) { @@ -155,10 +156,44 @@ static void kick_trng(struct platform_device *pdev) clrbits32(&r4tst->rtmctl, RTMCTL_PRGM); } +/** + * caam_get_era() - Return the ERA of the SEC on SoC, based + * on the SEC_VID register. + * Returns the ERA number (1..4) or -ENOTSUPP if the ERA is unknown. + * @caam_id - the value of the SEC_VID register + **/ +int caam_get_era(u64 caam_id) +{ + struct sec_vid *sec_vid = (struct sec_vid *)&caam_id; + static const struct { + u16 ip_id; + u8 maj_rev; + u8 era; + } caam_eras[] = { + {0x0A10, 1, 1}, + {0x0A10, 2, 2}, + {0x0A12, 1, 3}, + {0x0A14, 1, 3}, + {0x0A14, 2, 4}, + {0x0A16, 1, 4}, + {0x0A11, 1, 4} + }; + int i; + + for (i = 0; i < ARRAY_SIZE(caam_eras); i++) + if (caam_eras[i].ip_id == sec_vid->ip_id && + caam_eras[i].maj_rev == sec_vid->maj_rev) + return caam_eras[i].era; + + return -ENOTSUPP; +} +EXPORT_SYMBOL(caam_get_era); + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { int ret, ring, rspec; + u64 caam_id; struct device *dev; struct device_node *nprop, *np; struct caam_ctrl __iomem *ctrl; @@ -276,9 +311,11 @@ static int caam_probe(struct platform_device *pdev) /* Initialize queue allocator lock */ spin_lock_init(&ctrlpriv->jr_alloc_lock); + caam_id = rd_reg64(&topregs->ctrl.perfmon.caam_id); + /* Report "alive" for developer to see */ - dev_info(dev, "device ID = 0x%016llx\n", - rd_reg64(&topregs->ctrl.perfmon.caam_id)); + dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id, + caam_get_era(caam_id)); dev_info(dev, "job rings = %d, qi = %d\n", ctrlpriv->total_jobrs, ctrlpriv->qi_present); diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h new file mode 100644 index 000000000000..980d44eaaf40 --- /dev/null +++ b/drivers/crypto/caam/ctrl.h @@ -0,0 +1,13 @@ +/* + * CAAM control-plane driver backend public-level include definitions + * + * Copyright 2012 Freescale Semiconductor, Inc. + */ + +#ifndef CTRL_H +#define CTRL_H + +/* Prototypes for backend-level services exposed to APIs */ +int caam_get_era(u64 caam_id); + +#endif /* CTRL_H */ diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 6d9f1d982970..3223fc6d647c 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -117,6 +117,12 @@ struct jr_outentry { #define CHA_NUM_DECONUM_SHIFT 56 #define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT) +struct sec_vid { + u16 ip_id; + u8 maj_rev; + u8 min_rev; +}; + struct caam_perfmon { /* Performance Monitor Registers f00-f9f */ u64 req_dequeued; /* PC_REQ_DEQ - Dequeued Requests */ -- GitLab From bf084d8f6eb4ded3f90a6ab79bb682db00ebfbd4 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 28 Jun 2012 17:26:02 +0200 Subject: [PATCH 2466/5711] crypto: aesni-intel - fix wrong kfree pointer kfree(new_key_mem) in rfc4106_set_key() should be called on malloced pointer, not on aligned one, otherwise it can cause invalid pointer on free. (Seen at least once when running tcrypt tests with debug kernel.) Signed-off-by: Milan Broz Signed-off-by: Herbert Xu --- arch/x86/crypto/aesni-intel_glue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index d6626152067d..34fdcff4d2c8 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -529,7 +529,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); struct aesni_rfc4106_gcm_ctx *child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); - u8 *new_key_mem = NULL; + u8 *new_key_align, *new_key_mem = NULL; if (key_len < 4) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); @@ -553,9 +553,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, if (!new_key_mem) return -ENOMEM; - new_key_mem = PTR_ALIGN(new_key_mem, AESNI_ALIGN); - memcpy(new_key_mem, key, key_len); - key = new_key_mem; + new_key_align = PTR_ALIGN(new_key_mem, AESNI_ALIGN); + memcpy(new_key_align, key, key_len); + key = new_key_align; } if (!irq_fpu_usable()) -- GitLab From b329669ea0b5b02efd41f94372bcf0e988814af4 Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Fri, 29 Jun 2012 09:43:26 +0900 Subject: [PATCH 2467/5711] hwrng: exynos - Add support for Exynos random number generator This patch supports Exynos SOC's PRNG driver. Exynos's PRNG has 5 seeds and 5 random number outputs. Module is excuted under runtime power management control, so it activates only while it's in use. Otherwise it will be suspended generally. It was tested on PQ board by rngtest program. Signed-off-by: Jonghwa Lee Signed-off-by: Kyungmin Park Reviewed-by: Stephen Boyd Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 12 ++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/exynos-rng.c | 182 ++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 drivers/char/hw_random/exynos-rng.c diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index f45dad39a18b..b01d67328243 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -263,3 +263,15 @@ config HW_RANDOM_PSERIES module will be called pseries-rng. If unsure, say Y. + +config HW_RANDOM_EXYNOS + tristate "EXYNOS HW random number generator support" + depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on EXYNOS SOCs. + + To compile this driver as a module, choose M here: the + module will be called exynos-rng. + + If unsure, say Y. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index d901dfa30321..8d6d173b65e6 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o +obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c new file mode 100644 index 000000000000..232ba9ce579c --- /dev/null +++ b/drivers/char/hw_random/exynos-rng.c @@ -0,0 +1,182 @@ +/* + * exynos-rng.c - Random Number Generator driver for the exynos + * + * Copyright (C) 2012 Samsung Electronics + * Jonghwa Lee + * + * 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; + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EXYNOS_PRNG_STATUS_OFFSET 0x10 +#define EXYNOS_PRNG_SEED_OFFSET 0x140 +#define EXYNOS_PRNG_OUT1_OFFSET 0x160 +#define SEED_SETTING_DONE BIT(1) +#define PRNG_START 0x18 +#define PRNG_DONE BIT(5) +#define EXYNOS_AUTOSUSPEND_DELAY 100 + +struct exynos_rng { + struct device *dev; + struct hwrng rng; + void __iomem *mem; + struct clk *clk; +}; + +static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset) +{ + return __raw_readl(rng->mem + offset); +} + +static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset) +{ + __raw_writel(val, rng->mem + offset); +} + +static int exynos_init(struct hwrng *rng) +{ + struct exynos_rng *exynos_rng = container_of(rng, + struct exynos_rng, rng); + int i; + int ret = 0; + + pm_runtime_get_sync(exynos_rng->dev); + + for (i = 0 ; i < 5 ; i++) + exynos_rng_writel(exynos_rng, jiffies, + EXYNOS_PRNG_SEED_OFFSET + 4*i); + + if (!(exynos_rng_readl(exynos_rng, EXYNOS_PRNG_STATUS_OFFSET) + & SEED_SETTING_DONE)) + ret = -EIO; + + pm_runtime_put_noidle(exynos_rng->dev); + + return ret; +} + +static int exynos_read(struct hwrng *rng, void *buf, + size_t max, bool wait) +{ + struct exynos_rng *exynos_rng = container_of(rng, + struct exynos_rng, rng); + u32 *data = buf; + + pm_runtime_get_sync(exynos_rng->dev); + + exynos_rng_writel(exynos_rng, PRNG_START, 0); + + while (!(exynos_rng_readl(exynos_rng, + EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE)) + cpu_relax(); + + exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET); + + *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET); + + pm_runtime_mark_last_busy(exynos_rng->dev); + pm_runtime_autosuspend(exynos_rng->dev); + + return 4; +} + +static int __devinit exynos_rng_probe(struct platform_device *pdev) +{ + struct exynos_rng *exynos_rng; + + exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng), + GFP_KERNEL); + if (!exynos_rng) + return -ENOMEM; + + exynos_rng->dev = &pdev->dev; + exynos_rng->rng.name = "exynos"; + exynos_rng->rng.init = exynos_init; + exynos_rng->rng.read = exynos_read; + exynos_rng->clk = devm_clk_get(&pdev->dev, "secss"); + if (IS_ERR(exynos_rng->clk)) { + dev_err(&pdev->dev, "Couldn't get clock.\n"); + return -ENOENT; + } + + exynos_rng->mem = devm_request_and_ioremap(&pdev->dev, + platform_get_resource(pdev, IORESOURCE_MEM, 0)); + if (!exynos_rng->mem) + return -EBUSY; + + platform_set_drvdata(pdev, exynos_rng); + + pm_runtime_set_autosuspend_delay(&pdev->dev, EXYNOS_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + return hwrng_register(&exynos_rng->rng); +} + +static int __devexit exynos_rng_remove(struct platform_device *pdev) +{ + struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); + + hwrng_unregister(&exynos_rng->rng); + + return 0; +} + +static int exynos_rng_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); + + clk_disable_unprepare(exynos_rng->clk); + + return 0; +} + +static int exynos_rng_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); + + return clk_prepare_enable(exynos_rng->clk); +} + + +UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend, + exynos_rng_runtime_resume, NULL); + +static struct platform_driver exynos_rng_driver = { + .driver = { + .name = "exynos-rng", + .owner = THIS_MODULE, + .pm = &exynos_rng_pm_ops, + }, + .probe = exynos_rng_probe, + .remove = __devexit_p(exynos_rng_remove), +}; + +module_platform_driver(exynos_rng_driver); + +MODULE_DESCRIPTION("EXYNOS 4 H/W Random Number Generator driver"); +MODULE_AUTHOR("Jonghwa Lee "); +MODULE_LICENSE("GPL"); -- GitLab From 6c79294f44fd7d1122cbaabff3b9815b074c0dd0 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 29 Jun 2012 22:08:09 +0200 Subject: [PATCH 2468/5711] crypto: testmgr - allow aesni-intel and ghash_clmulni-intel in fips mode Patch 863b557a88f8c033f7419fabafef4712a5055f85 added NULL entries for intel accelerated drivers but did not marked these fips allowed. This cause panic if running tests with fips=1. For ghash, fips_allowed flag was added in patch 18c0ebd2d8194cce4b3f67e2903fa01bea892cbc. Without patch, "modprobe tcrypt" fails with alg: skcipher: Failed to load transform for cbc-aes-aesni: -2 cbc-aes-aesni: cbc(aes) alg self test failed in fips mode! (panic) Also add missing cryptd(__driver-cbc-aes-aesni) and cryptd(__driver-gcm-aes-aesni) test to complement null tests above, otherwise system complains with alg: No test for __cbc-aes-aesni (cryptd(__driver-cbc-aes-aesni)) alg: No test for __gcm-aes-aesni (cryptd(__driver-gcm-aes-aesni)) Signed-off-by: Milan Broz Signed-off-by: Paul Wouters Signed-off-by: Herbert Xu --- crypto/testmgr.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 36748a5996e2..4308a11f129c 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1581,6 +1581,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "__driver-cbc-aes-aesni", .test = alg_test_null, + .fips_allowed = 1, .suite = { .cipher = { .enc = { @@ -1641,6 +1642,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "__driver-ecb-aes-aesni", .test = alg_test_null, + .fips_allowed = 1, .suite = { .cipher = { .enc = { @@ -1701,6 +1703,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "__ghash-pclmulqdqni", .test = alg_test_null, + .fips_allowed = 1, .suite = { .hash = { .vecs = NULL, @@ -1865,9 +1868,26 @@ static const struct alg_test_desc alg_test_descs[] = { .count = CRC32C_TEST_VECTORS } } + }, { + .alg = "cryptd(__driver-cbc-aes-aesni)", + .test = alg_test_null, + .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__driver-ecb-aes-aesni)", .test = alg_test_null, + .fips_allowed = 1, .suite = { .cipher = { .enc = { @@ -1925,9 +1945,26 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "cryptd(__driver-gcm-aes-aesni)", + .test = alg_test_null, + .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__ghash-pclmulqdqni)", .test = alg_test_null, + .fips_allowed = 1, .suite = { .hash = { .vecs = NULL, @@ -2043,6 +2080,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "ecb(__aes-aesni)", .test = alg_test_null, + .fips_allowed = 1, .suite = { .cipher = { .enc = { -- GitLab From 815e972110052e8da68b5b5298ca2cd69cb7c3c0 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 1 Jul 2012 19:19:43 +0200 Subject: [PATCH 2469/5711] ARM: AT91SAM9G45: add crypto peripherals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Herbert Xu --- arch/arm/mach-at91/at91sam9g45.c | 13 +- arch/arm/mach-at91/at91sam9g45_devices.c | 128 ++++++++++++++++++ arch/arm/mach-at91/include/mach/at91sam9g45.h | 2 + include/linux/platform_data/atmel-aes.h | 22 +++ 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 include/linux/platform_data/atmel-aes.h diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 4792682d52b9..da6dc0f29657 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -182,6 +182,13 @@ static struct clk adc_op_clk = { .rate_hz = 13200000, }; +/* AES/TDES/SHA clock - Only for sam9m11/sam9g56 */ +static struct clk aestdessha_clk = { + .name = "aestdessha_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_AESTDESSHA, + .type = CLK_TYPE_PERIPHERAL, +}; + static struct clk *periph_clocks[] __initdata = { &pioA_clk, &pioB_clk, @@ -211,6 +218,7 @@ static struct clk *periph_clocks[] __initdata = { &udphs_clk, &mmc1_clk, &adc_op_clk, + &aestdessha_clk, // irq0 }; @@ -231,6 +239,9 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk), + CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk), + CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk), + CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk), /* more usart lookup table for DT entries */ CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck), CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk), @@ -387,7 +398,7 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = { 3, /* Ethernet */ 0, /* Image Sensor Interface */ 2, /* USB Device High speed port */ - 0, + 0, /* AESTDESSHA Crypto HW Accelerators */ 0, /* Multimedia Card Interface 1 */ 0, 0, /* Advanced Interrupt Controller (IRQ0) */ diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 933fc9afe7d0..7102f62b64ef 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -1830,6 +1831,130 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} void __init at91_add_device_serial(void) {} #endif +/* -------------------------------------------------------------------- + * SHA1/SHA256 + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_CRYPTO_DEV_ATMEL_SHA) || defined(CONFIG_CRYPTO_DEV_ATMEL_SHA_MODULE) +static struct resource sha_resources[] = { + { + .start = AT91SAM9G45_BASE_SHA, + .end = AT91SAM9G45_BASE_SHA + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_AESTDESSHA, + .end = AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_sha_device = { + .name = "atmel_sha", + .id = -1, + .resource = sha_resources, + .num_resources = ARRAY_SIZE(sha_resources), +}; + +static void __init at91_add_device_sha(void) +{ + platform_device_register(&at91sam9g45_sha_device); +} +#else +static void __init at91_add_device_sha(void) {} +#endif + +/* -------------------------------------------------------------------- + * DES/TDES + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_CRYPTO_DEV_ATMEL_TDES) || defined(CONFIG_CRYPTO_DEV_ATMEL_TDES_MODULE) +static struct resource tdes_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TDES, + .end = AT91SAM9G45_BASE_TDES + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_AESTDESSHA, + .end = AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_tdes_device = { + .name = "atmel_tdes", + .id = -1, + .resource = tdes_resources, + .num_resources = ARRAY_SIZE(tdes_resources), +}; + +static void __init at91_add_device_tdes(void) +{ + platform_device_register(&at91sam9g45_tdes_device); +} +#else +static void __init at91_add_device_tdes(void) {} +#endif + +/* -------------------------------------------------------------------- + * AES + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_CRYPTO_DEV_ATMEL_AES) || defined(CONFIG_CRYPTO_DEV_ATMEL_AES_MODULE) +static struct aes_platform_data aes_data; +static u64 aes_dmamask = DMA_BIT_MASK(32); + +static struct resource aes_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_AES, + .end = AT91SAM9G45_BASE_AES + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_AESTDESSHA, + .end = AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_aes_device = { + .name = "atmel_aes", + .id = -1, + .dev = { + .dma_mask = &aes_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &aes_data, + }, + .resource = aes_resources, + .num_resources = ARRAY_SIZE(aes_resources), +}; + +static void __init at91_add_device_aes(void) +{ + struct at_dma_slave *atslave; + struct aes_dma_data *alt_atslave; + + alt_atslave = kzalloc(sizeof(struct aes_dma_data), GFP_KERNEL); + + /* DMA TX slave channel configuration */ + atslave = &alt_atslave->txdata; + atslave->dma_dev = &at_hdmac_device.dev; + atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE | ATC_SRC_H2SEL_HW | + ATC_SRC_PER(AT_DMA_ID_AES_RX); + + /* DMA RX slave channel configuration */ + atslave = &alt_atslave->rxdata; + atslave->dma_dev = &at_hdmac_device.dev; + atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE | ATC_DST_H2SEL_HW | + ATC_DST_PER(AT_DMA_ID_AES_TX); + + aes_data.dma_slave = alt_atslave; + platform_device_register(&at91sam9g45_aes_device); +} +#else +static void __init at91_add_device_aes(void) {} +#endif /* -------------------------------------------------------------------- */ /* @@ -1847,6 +1972,9 @@ static int __init at91_add_standard_devices(void) at91_add_device_trng(); at91_add_device_watchdog(); at91_add_device_tc(); + at91_add_device_sha(); + at91_add_device_tdes(); + at91_add_device_aes(); return 0; } diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h index 3a4da24d5911..8eba1021f533 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9g45.h +++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h @@ -136,6 +136,8 @@ #define AT_DMA_ID_SSC1_RX 8 #define AT_DMA_ID_AC97_TX 9 #define AT_DMA_ID_AC97_RX 10 +#define AT_DMA_ID_AES_TX 11 +#define AT_DMA_ID_AES_RX 12 #define AT_DMA_ID_MCI1 13 #endif diff --git a/include/linux/platform_data/atmel-aes.h b/include/linux/platform_data/atmel-aes.h new file mode 100644 index 000000000000..e7a1949bad26 --- /dev/null +++ b/include/linux/platform_data/atmel-aes.h @@ -0,0 +1,22 @@ +#ifndef __LINUX_ATMEL_AES_H +#define __LINUX_ATMEL_AES_H + +#include + +/** + * struct aes_dma_data - DMA data for AES + */ +struct aes_dma_data { + struct at_dma_slave txdata; + struct at_dma_slave rxdata; +}; + +/** + * struct aes_platform_data - board-specific AES configuration + * @dma_slave: DMA slave interface to use in data transfers. + */ +struct aes_platform_data { + struct aes_dma_data *dma_slave; +}; + +#endif /* __LINUX_ATMEL_AES_H */ -- GitLab From bd3c7b5c2aba0d806285700848f588ca482094d8 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 1 Jul 2012 19:19:44 +0200 Subject: [PATCH 2470/5711] crypto: atmel - add Atmel AES driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 17 + drivers/crypto/Makefile | 1 + drivers/crypto/atmel-aes-regs.h | 62 ++ drivers/crypto/atmel-aes.c | 1206 +++++++++++++++++++++++++++++++ 4 files changed, 1286 insertions(+) create mode 100644 drivers/crypto/atmel-aes-regs.h create mode 100644 drivers/crypto/atmel-aes.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index be6b2ba11fb1..d04eabef1e8c 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -332,4 +332,21 @@ config CRYPTO_DEV_BFIN_CRC Newer Blackfin processors have CRC hardware. Select this if you want to use the Blackfin CRC module. +config CRYPTO_DEV_ATMEL_AES + tristate "Support for Atmel AES hw accelerator" + depends on ARCH_AT91 + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_AES + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + select CONFIG_AT_HDMAC + help + Some Atmel processors have AES hw accelerator. + Select this if you want to use the Atmel module for + AES algorithms. + + To compile this driver as a module, choose M here: the module + will be called atmel-aes. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 1c5a145cc268..44a8147c630e 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ +obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h new file mode 100644 index 000000000000..2786bb1a5aa0 --- /dev/null +++ b/drivers/crypto/atmel-aes-regs.h @@ -0,0 +1,62 @@ +#ifndef __ATMEL_AES_REGS_H__ +#define __ATMEL_AES_REGS_H__ + +#define AES_CR 0x00 +#define AES_CR_START (1 << 0) +#define AES_CR_SWRST (1 << 8) +#define AES_CR_LOADSEED (1 << 16) + +#define AES_MR 0x04 +#define AES_MR_CYPHER_DEC (0 << 0) +#define AES_MR_CYPHER_ENC (1 << 0) +#define AES_MR_DUALBUFF (1 << 3) +#define AES_MR_PROCDLY_MASK (0xF << 4) +#define AES_MR_PROCDLY_OFFSET 4 +#define AES_MR_SMOD_MASK (0x3 << 8) +#define AES_MR_SMOD_MANUAL (0x0 << 8) +#define AES_MR_SMOD_AUTO (0x1 << 8) +#define AES_MR_SMOD_IDATAR0 (0x2 << 8) +#define AES_MR_KEYSIZE_MASK (0x3 << 10) +#define AES_MR_KEYSIZE_128 (0x0 << 10) +#define AES_MR_KEYSIZE_192 (0x1 << 10) +#define AES_MR_KEYSIZE_256 (0x2 << 10) +#define AES_MR_OPMOD_MASK (0x7 << 12) +#define AES_MR_OPMOD_ECB (0x0 << 12) +#define AES_MR_OPMOD_CBC (0x1 << 12) +#define AES_MR_OPMOD_OFB (0x2 << 12) +#define AES_MR_OPMOD_CFB (0x3 << 12) +#define AES_MR_OPMOD_CTR (0x4 << 12) +#define AES_MR_LOD (0x1 << 15) +#define AES_MR_CFBS_MASK (0x7 << 16) +#define AES_MR_CFBS_128b (0x0 << 16) +#define AES_MR_CFBS_64b (0x1 << 16) +#define AES_MR_CFBS_32b (0x2 << 16) +#define AES_MR_CFBS_16b (0x3 << 16) +#define AES_MR_CFBS_8b (0x4 << 16) +#define AES_MR_CKEY_MASK (0xF << 20) +#define AES_MR_CKEY_OFFSET 20 +#define AES_MR_CMTYP_MASK (0x1F << 24) +#define AES_MR_CMTYP_OFFSET 24 + +#define AES_IER 0x10 +#define AES_IDR 0x14 +#define AES_IMR 0x18 +#define AES_ISR 0x1C +#define AES_INT_DATARDY (1 << 0) +#define AES_INT_URAD (1 << 8) +#define AES_ISR_URAT_MASK (0xF << 12) +#define AES_ISR_URAT_IDR_WR_PROC (0x0 << 12) +#define AES_ISR_URAT_ODR_RD_PROC (0x1 << 12) +#define AES_ISR_URAT_MR_WR_PROC (0x2 << 12) +#define AES_ISR_URAT_ODR_RD_SUBK (0x3 << 12) +#define AES_ISR_URAT_MR_WR_SUBK (0x4 << 12) +#define AES_ISR_URAT_WOR_RD (0x5 << 12) + +#define AES_KEYWR(x) (0x20 + ((x) * 0x04)) +#define AES_IDATAR(x) (0x40 + ((x) * 0x04)) +#define AES_ODATAR(x) (0x50 + ((x) * 0x04)) +#define AES_IVR(x) (0x60 + ((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 new file mode 100644 index 000000000000..6bb20fffbf49 --- /dev/null +++ b/drivers/crypto/atmel-aes.c @@ -0,0 +1,1206 @@ +/* + * Cryptographic API. + * + * Support for ATMEL AES HW acceleration. + * + * Copyright (c) 2012 Eukréa Electromatique - ATMEL + * Author: Nicolas Royer + * + * 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. + * + * Some ideas are from omap-aes.c driver. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atmel-aes-regs.h" + +#define CFB8_BLOCK_SIZE 1 +#define CFB16_BLOCK_SIZE 2 +#define CFB32_BLOCK_SIZE 4 +#define CFB64_BLOCK_SIZE 8 + +/* AES flags */ +#define AES_FLAGS_MODE_MASK 0x01ff +#define AES_FLAGS_ENCRYPT BIT(0) +#define AES_FLAGS_CBC BIT(1) +#define AES_FLAGS_CFB BIT(2) +#define AES_FLAGS_CFB8 BIT(3) +#define AES_FLAGS_CFB16 BIT(4) +#define AES_FLAGS_CFB32 BIT(5) +#define AES_FLAGS_CFB64 BIT(6) +#define AES_FLAGS_OFB BIT(7) +#define AES_FLAGS_CTR BIT(8) + +#define AES_FLAGS_INIT BIT(16) +#define AES_FLAGS_DMA BIT(17) +#define AES_FLAGS_BUSY BIT(18) + +#define AES_FLAGS_DUALBUFF BIT(24) + +#define ATMEL_AES_QUEUE_LENGTH 1 +#define ATMEL_AES_CACHE_SIZE 0 + +#define ATMEL_AES_DMA_THRESHOLD 16 + + +struct atmel_aes_dev; + +struct atmel_aes_ctx { + struct atmel_aes_dev *dd; + + int keylen; + u32 key[AES_KEYSIZE_256 / sizeof(u32)]; +}; + +struct atmel_aes_reqctx { + unsigned long mode; +}; + +struct atmel_aes_dma { + struct dma_chan *chan; + struct dma_slave_config dma_conf; +}; + +struct atmel_aes_dev { + struct list_head list; + unsigned long phys_base; + void __iomem *io_base; + + struct atmel_aes_ctx *ctx; + struct device *dev; + struct clk *iclk; + int irq; + + unsigned long flags; + int err; + + spinlock_t lock; + struct crypto_queue queue; + + struct tasklet_struct done_task; + struct tasklet_struct queue_task; + + struct ablkcipher_request *req; + size_t total; + + struct scatterlist *in_sg; + unsigned int nb_in_sg; + + struct scatterlist *out_sg; + unsigned int nb_out_sg; + + size_t bufcnt; + + u8 buf_in[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32)); + int dma_in; + struct atmel_aes_dma dma_lch_in; + + u8 buf_out[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32)); + int dma_out; + struct atmel_aes_dma dma_lch_out; + + u32 hw_version; +}; + +struct atmel_aes_drv { + struct list_head dev_list; + spinlock_t lock; +}; + +static struct atmel_aes_drv atmel_aes = { + .dev_list = LIST_HEAD_INIT(atmel_aes.dev_list), + .lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock), +}; + +static int atmel_aes_sg_length(struct ablkcipher_request *req, + struct scatterlist *sg) +{ + unsigned int total = req->nbytes; + int sg_nb; + unsigned int len; + struct scatterlist *sg_list; + + sg_nb = 0; + sg_list = sg; + total = req->nbytes; + + while (total) { + len = min(sg_list->length, total); + + sg_nb++; + total -= len; + + sg_list = sg_next(sg_list); + if (!sg_list) + total = 0; + } + + return sg_nb; +} + +static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset) +{ + return readl_relaxed(dd->io_base + offset); +} + +static inline void atmel_aes_write(struct atmel_aes_dev *dd, + u32 offset, u32 value) +{ + writel_relaxed(value, dd->io_base + offset); +} + +static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 offset, + u32 *value, int count) +{ + for (; count--; value++, offset += 4) + *value = atmel_aes_read(dd, offset); +} + +static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset, + u32 *value, int count) +{ + for (; count--; value++, offset += 4) + atmel_aes_write(dd, offset, *value); +} + +static void atmel_aes_dualbuff_test(struct atmel_aes_dev *dd) +{ + atmel_aes_write(dd, AES_MR, AES_MR_DUALBUFF); + + if (atmel_aes_read(dd, AES_MR) & AES_MR_DUALBUFF) + dd->flags |= AES_FLAGS_DUALBUFF; +} + +static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx) +{ + struct atmel_aes_dev *aes_dd = NULL; + struct atmel_aes_dev *tmp; + + spin_lock_bh(&atmel_aes.lock); + if (!ctx->dd) { + list_for_each_entry(tmp, &atmel_aes.dev_list, list) { + aes_dd = tmp; + break; + } + ctx->dd = aes_dd; + } else { + aes_dd = ctx->dd; + } + + spin_unlock_bh(&atmel_aes.lock); + + return aes_dd; +} + +static int atmel_aes_hw_init(struct atmel_aes_dev *dd) +{ + clk_prepare_enable(dd->iclk); + + if (!(dd->flags & AES_FLAGS_INIT)) { + atmel_aes_write(dd, AES_CR, AES_CR_SWRST); + atmel_aes_dualbuff_test(dd); + dd->flags |= AES_FLAGS_INIT; + dd->err = 0; + } + + return 0; +} + +static void atmel_aes_hw_version_init(struct atmel_aes_dev *dd) +{ + atmel_aes_hw_init(dd); + + dd->hw_version = atmel_aes_read(dd, AES_HW_VERSION); + + clk_disable_unprepare(dd->iclk); +} + +static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err) +{ + struct ablkcipher_request *req = dd->req; + + clk_disable_unprepare(dd->iclk); + dd->flags &= ~AES_FLAGS_BUSY; + + req->base.complete(&req->base, err); +} + +static void atmel_aes_dma_callback(void *data) +{ + struct atmel_aes_dev *dd = data; + + /* dma_lch_out - completed */ + tasklet_schedule(&dd->done_task); +} + +static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd) +{ + struct dma_async_tx_descriptor *in_desc, *out_desc; + int nb_dma_sg_in, nb_dma_sg_out; + + dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg); + if (!dd->nb_in_sg) + goto exit_err; + + nb_dma_sg_in = dma_map_sg(dd->dev, dd->in_sg, dd->nb_in_sg, + DMA_TO_DEVICE); + if (!nb_dma_sg_in) + goto exit_err; + + in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, dd->in_sg, + nb_dma_sg_in, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!in_desc) + goto unmap_in; + + /* callback not needed */ + + dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg); + if (!dd->nb_out_sg) + goto unmap_in; + + nb_dma_sg_out = dma_map_sg(dd->dev, dd->out_sg, dd->nb_out_sg, + DMA_FROM_DEVICE); + if (!nb_dma_sg_out) + goto unmap_out; + + out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, dd->out_sg, + nb_dma_sg_out, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!out_desc) + goto unmap_out; + + out_desc->callback = atmel_aes_dma_callback; + out_desc->callback_param = dd; + + dd->total -= dd->req->nbytes; + + dmaengine_submit(out_desc); + dma_async_issue_pending(dd->dma_lch_out.chan); + + dmaengine_submit(in_desc); + dma_async_issue_pending(dd->dma_lch_in.chan); + + return 0; + +unmap_out: + dma_unmap_sg(dd->dev, dd->out_sg, dd->nb_out_sg, + DMA_FROM_DEVICE); +unmap_in: + dma_unmap_sg(dd->dev, dd->in_sg, dd->nb_in_sg, + DMA_TO_DEVICE); +exit_err: + return -EINVAL; +} + +static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd) +{ + dd->flags &= ~AES_FLAGS_DMA; + + /* use cache buffers */ + dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg); + if (!dd->nb_in_sg) + return -EINVAL; + + dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg); + if (!dd->nb_in_sg) + return -EINVAL; + + dd->bufcnt = sg_copy_to_buffer(dd->in_sg, dd->nb_in_sg, + dd->buf_in, dd->total); + + if (!dd->bufcnt) + return -EINVAL; + + dd->total -= dd->bufcnt; + + atmel_aes_write(dd, AES_IER, AES_INT_DATARDY); + atmel_aes_write_n(dd, AES_IDATAR(0), (u32 *) dd->buf_in, + dd->bufcnt >> 2); + + return 0; +} + +static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd) +{ + int err; + + if (dd->flags & AES_FLAGS_CFB8) { + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_1_BYTE; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_1_BYTE; + } else if (dd->flags & AES_FLAGS_CFB16) { + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_2_BYTES; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_2_BYTES; + } else { + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + } + + dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf); + dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf); + + dd->flags |= AES_FLAGS_DMA; + err = atmel_aes_crypt_dma(dd); + + return err; +} + +static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd) +{ + int err; + u32 valcr = 0, valmr = 0; + + err = atmel_aes_hw_init(dd); + + if (err) + return err; + + /* MR register must be set before IV registers */ + if (dd->ctx->keylen == AES_KEYSIZE_128) + valmr |= AES_MR_KEYSIZE_128; + else if (dd->ctx->keylen == AES_KEYSIZE_192) + valmr |= AES_MR_KEYSIZE_192; + else + valmr |= AES_MR_KEYSIZE_256; + + if (dd->flags & AES_FLAGS_CBC) { + valmr |= AES_MR_OPMOD_CBC; + } else if (dd->flags & AES_FLAGS_CFB) { + valmr |= AES_MR_OPMOD_CFB; + if (dd->flags & AES_FLAGS_CFB8) + valmr |= AES_MR_CFBS_8b; + else if (dd->flags & AES_FLAGS_CFB16) + valmr |= AES_MR_CFBS_16b; + else if (dd->flags & AES_FLAGS_CFB32) + valmr |= AES_MR_CFBS_32b; + else if (dd->flags & AES_FLAGS_CFB64) + valmr |= AES_MR_CFBS_64b; + } else if (dd->flags & AES_FLAGS_OFB) { + valmr |= AES_MR_OPMOD_OFB; + } else if (dd->flags & AES_FLAGS_CTR) { + valmr |= AES_MR_OPMOD_CTR; + } else { + valmr |= AES_MR_OPMOD_ECB; + } + + if (dd->flags & AES_FLAGS_ENCRYPT) + valmr |= AES_MR_CYPHER_ENC; + + if (dd->total > ATMEL_AES_DMA_THRESHOLD) { + valmr |= AES_MR_SMOD_IDATAR0; + if (dd->flags & AES_FLAGS_DUALBUFF) + valmr |= AES_MR_DUALBUFF; + } else { + valmr |= AES_MR_SMOD_AUTO; + } + + atmel_aes_write(dd, AES_CR, valcr); + atmel_aes_write(dd, AES_MR, valmr); + + atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key, + dd->ctx->keylen >> 2); + + if (((dd->flags & AES_FLAGS_CBC) || (dd->flags & AES_FLAGS_CFB) || + (dd->flags & AES_FLAGS_OFB) || (dd->flags & AES_FLAGS_CTR)) && + dd->req->info) { + atmel_aes_write_n(dd, AES_IVR(0), dd->req->info, 4); + } + + return 0; +} + +static int atmel_aes_handle_queue(struct atmel_aes_dev *dd, + struct ablkcipher_request *req) +{ + struct crypto_async_request *async_req, *backlog; + struct atmel_aes_ctx *ctx; + struct atmel_aes_reqctx *rctx; + unsigned long flags; + int err, ret = 0; + + spin_lock_irqsave(&dd->lock, flags); + if (req) + ret = ablkcipher_enqueue_request(&dd->queue, req); + if (dd->flags & AES_FLAGS_BUSY) { + spin_unlock_irqrestore(&dd->lock, flags); + return ret; + } + backlog = crypto_get_backlog(&dd->queue); + async_req = crypto_dequeue_request(&dd->queue); + if (async_req) + dd->flags |= AES_FLAGS_BUSY; + spin_unlock_irqrestore(&dd->lock, flags); + + if (!async_req) + return ret; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + req = ablkcipher_request_cast(async_req); + + /* assign new request to device */ + dd->req = req; + dd->total = req->nbytes; + dd->in_sg = req->src; + dd->out_sg = req->dst; + + rctx = ablkcipher_request_ctx(req); + ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); + rctx->mode &= AES_FLAGS_MODE_MASK; + dd->flags = (dd->flags & ~AES_FLAGS_MODE_MASK) | rctx->mode; + dd->ctx = ctx; + ctx->dd = dd; + + err = atmel_aes_write_ctrl(dd); + if (!err) { + if (dd->total > ATMEL_AES_DMA_THRESHOLD) + err = atmel_aes_crypt_dma_start(dd); + else + err = atmel_aes_crypt_cpu_start(dd); + } + if (err) { + /* aes_task will not finish it, so do it here */ + atmel_aes_finish_req(dd, err); + tasklet_schedule(&dd->queue_task); + } + + return ret; +} + +static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd) +{ + int err = -EINVAL; + + if (dd->flags & AES_FLAGS_DMA) { + dma_unmap_sg(dd->dev, dd->out_sg, + dd->nb_out_sg, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, dd->in_sg, + dd->nb_in_sg, DMA_TO_DEVICE); + err = 0; + } + + return err; +} + +static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode) +{ + struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); + struct atmel_aes_dev *dd; + + if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { + pr_err("request size is not exact amount of AES blocks\n"); + return -EINVAL; + } + + dd = atmel_aes_find_dev(ctx); + if (!dd) + return -ENODEV; + + rctx->mode = mode; + + return atmel_aes_handle_queue(dd, req); +} + +static bool atmel_aes_filter(struct dma_chan *chan, void *slave) +{ + struct at_dma_slave *sl = slave; + + if (sl && sl->dma_dev == chan->device->dev) { + chan->private = sl; + return true; + } else { + return false; + } +} + +static int atmel_aes_dma_init(struct atmel_aes_dev *dd) +{ + int err = -ENOMEM; + struct aes_platform_data *pdata; + dma_cap_mask_t mask_in, mask_out; + + pdata = dd->dev->platform_data; + + if (pdata && pdata->dma_slave->txdata.dma_dev && + pdata->dma_slave->rxdata.dma_dev) { + + /* Try to grab 2 DMA channels */ + dma_cap_zero(mask_in); + dma_cap_set(DMA_SLAVE, mask_in); + + dd->dma_lch_in.chan = dma_request_channel(mask_in, + atmel_aes_filter, &pdata->dma_slave->rxdata); + if (!dd->dma_lch_in.chan) + goto err_dma_in; + + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + AES_IDATAR(0); + dd->dma_lch_in.dma_conf.src_maxburst = 1; + dd->dma_lch_in.dma_conf.dst_maxburst = 1; + dd->dma_lch_in.dma_conf.device_fc = false; + + dma_cap_zero(mask_out); + dma_cap_set(DMA_SLAVE, mask_out); + dd->dma_lch_out.chan = dma_request_channel(mask_out, + atmel_aes_filter, &pdata->dma_slave->txdata); + if (!dd->dma_lch_out.chan) + goto err_dma_out; + + dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; + dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + + AES_ODATAR(0); + dd->dma_lch_out.dma_conf.src_maxburst = 1; + dd->dma_lch_out.dma_conf.dst_maxburst = 1; + dd->dma_lch_out.dma_conf.device_fc = false; + + return 0; + } else { + return -ENODEV; + } + +err_dma_out: + dma_release_channel(dd->dma_lch_in.chan); +err_dma_in: + return err; +} + +static void atmel_aes_dma_cleanup(struct atmel_aes_dev *dd) +{ + dma_release_channel(dd->dma_lch_in.chan); + dma_release_channel(dd->dma_lch_out.chan); +} + +static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && + keylen != AES_KEYSIZE_256) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + return 0; +} + +static int atmel_aes_ecb_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT); +} + +static int atmel_aes_ecb_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + 0); +} + +static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CBC); +} + +static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CBC); +} + +static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_OFB); +} + +static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_OFB); +} + +static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CFB); +} + +static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CFB); +} + +static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB64); +} + +static int atmel_aes_cfb64_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CFB | AES_FLAGS_CFB64); +} + +static int atmel_aes_cfb32_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB32); +} + +static int atmel_aes_cfb32_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CFB | AES_FLAGS_CFB32); +} + +static int atmel_aes_cfb16_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB16); +} + +static int atmel_aes_cfb16_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CFB | AES_FLAGS_CFB16); +} + +static int atmel_aes_cfb8_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB8); +} + +static int atmel_aes_cfb8_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CFB | AES_FLAGS_CFB8); +} + +static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_ENCRYPT | AES_FLAGS_CTR); +} + +static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req) +{ + return atmel_aes_crypt(req, + AES_FLAGS_CTR); +} + +static int atmel_aes_cra_init(struct crypto_tfm *tfm) +{ + tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx); + + return 0; +} + +static void atmel_aes_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct crypto_alg aes_algs[] = { +{ + .cra_name = "ecb(aes)", + .cra_driver_name = "atmel-ecb-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_ecb_encrypt, + .decrypt = atmel_aes_ecb_decrypt, + } +}, +{ + .cra_name = "cbc(aes)", + .cra_driver_name = "atmel-cbc-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cbc_encrypt, + .decrypt = atmel_aes_cbc_decrypt, + } +}, +{ + .cra_name = "ofb(aes)", + .cra_driver_name = "atmel-ofb-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_ofb_encrypt, + .decrypt = atmel_aes_ofb_decrypt, + } +}, +{ + .cra_name = "cfb(aes)", + .cra_driver_name = "atmel-cfb-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cfb_encrypt, + .decrypt = atmel_aes_cfb_decrypt, + } +}, +{ + .cra_name = "cfb32(aes)", + .cra_driver_name = "atmel-cfb32-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cfb32_encrypt, + .decrypt = atmel_aes_cfb32_decrypt, + } +}, +{ + .cra_name = "cfb16(aes)", + .cra_driver_name = "atmel-cfb16-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB16_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cfb16_encrypt, + .decrypt = atmel_aes_cfb16_decrypt, + } +}, +{ + .cra_name = "cfb8(aes)", + .cra_driver_name = "atmel-cfb8-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB64_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cfb8_encrypt, + .decrypt = atmel_aes_cfb8_decrypt, + } +}, +{ + .cra_name = "ctr(aes)", + .cra_driver_name = "atmel-ctr-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_ctr_encrypt, + .decrypt = atmel_aes_ctr_decrypt, + } +}, +}; + +static struct crypto_alg aes_cfb64_alg[] = { +{ + .cra_name = "cfb64(aes)", + .cra_driver_name = "atmel-cfb64-aes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB64_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_aes_ctx), + .cra_alignmask = 0x0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_aes_cra_init, + .cra_exit = atmel_aes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = atmel_aes_setkey, + .encrypt = atmel_aes_cfb64_encrypt, + .decrypt = atmel_aes_cfb64_decrypt, + } +}, +}; + +static void atmel_aes_queue_task(unsigned long data) +{ + struct atmel_aes_dev *dd = (struct atmel_aes_dev *)data; + + atmel_aes_handle_queue(dd, NULL); +} + +static void atmel_aes_done_task(unsigned long data) +{ + struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data; + int err; + + if (!(dd->flags & AES_FLAGS_DMA)) { + atmel_aes_read_n(dd, AES_ODATAR(0), (u32 *) dd->buf_out, + dd->bufcnt >> 2); + + if (sg_copy_from_buffer(dd->out_sg, dd->nb_out_sg, + dd->buf_out, dd->bufcnt)) + err = 0; + else + err = -EINVAL; + + goto cpu_end; + } + + err = atmel_aes_crypt_dma_stop(dd); + + err = dd->err ? : err; + + if (dd->total && !err) { + err = atmel_aes_crypt_dma_start(dd); + if (!err) + return; /* DMA started. Not fininishing. */ + } + +cpu_end: + atmel_aes_finish_req(dd, err); + atmel_aes_handle_queue(dd, NULL); +} + +static irqreturn_t atmel_aes_irq(int irq, void *dev_id) +{ + struct atmel_aes_dev *aes_dd = dev_id; + u32 reg; + + reg = atmel_aes_read(aes_dd, AES_ISR); + if (reg & atmel_aes_read(aes_dd, AES_IMR)) { + atmel_aes_write(aes_dd, AES_IDR, reg); + if (AES_FLAGS_BUSY & aes_dd->flags) + tasklet_schedule(&aes_dd->done_task); + else + dev_warn(aes_dd->dev, "AES interrupt when no active requests.\n"); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(aes_algs); i++) + crypto_unregister_alg(&aes_algs[i]); + if (dd->hw_version >= 0x130) + crypto_unregister_alg(&aes_cfb64_alg[0]); +} + +static int atmel_aes_register_algs(struct atmel_aes_dev *dd) +{ + int err, i, j; + + for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { + INIT_LIST_HEAD(&aes_algs[i].cra_list); + err = crypto_register_alg(&aes_algs[i]); + if (err) + goto err_aes_algs; + } + + atmel_aes_hw_version_init(dd); + + if (dd->hw_version >= 0x130) { + INIT_LIST_HEAD(&aes_cfb64_alg[0].cra_list); + err = crypto_register_alg(&aes_cfb64_alg[0]); + if (err) + goto err_aes_cfb64_alg; + } + + return 0; + +err_aes_cfb64_alg: + i = ARRAY_SIZE(aes_algs); +err_aes_algs: + for (j = 0; j < i; j++) + crypto_unregister_alg(&aes_algs[j]); + + return err; +} + +static int __devinit atmel_aes_probe(struct platform_device *pdev) +{ + struct atmel_aes_dev *aes_dd; + struct aes_platform_data *pdata; + struct device *dev = &pdev->dev; + struct resource *aes_res; + unsigned long aes_phys_size; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + err = -ENXIO; + goto aes_dd_err; + } + + aes_dd = kzalloc(sizeof(struct atmel_aes_dev), GFP_KERNEL); + if (aes_dd == NULL) { + dev_err(dev, "unable to alloc data struct.\n"); + err = -ENOMEM; + goto aes_dd_err; + } + + aes_dd->dev = dev; + + platform_set_drvdata(pdev, aes_dd); + + INIT_LIST_HEAD(&aes_dd->list); + + tasklet_init(&aes_dd->done_task, atmel_aes_done_task, + (unsigned long)aes_dd); + tasklet_init(&aes_dd->queue_task, atmel_aes_queue_task, + (unsigned long)aes_dd); + + crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH); + + aes_dd->irq = -1; + + /* Get the base address */ + aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!aes_res) { + dev_err(dev, "no MEM resource info\n"); + err = -ENODEV; + goto res_err; + } + aes_dd->phys_base = aes_res->start; + aes_phys_size = resource_size(aes_res); + + /* Get the IRQ */ + aes_dd->irq = platform_get_irq(pdev, 0); + if (aes_dd->irq < 0) { + dev_err(dev, "no IRQ resource info\n"); + err = aes_dd->irq; + goto aes_irq_err; + } + + err = request_irq(aes_dd->irq, atmel_aes_irq, IRQF_SHARED, "atmel-aes", + aes_dd); + if (err) { + dev_err(dev, "unable to request aes irq.\n"); + goto aes_irq_err; + } + + /* Initializing the clock */ + aes_dd->iclk = clk_get(&pdev->dev, NULL); + if (IS_ERR(aes_dd->iclk)) { + dev_err(dev, "clock intialization failed.\n"); + err = PTR_ERR(aes_dd->iclk); + goto clk_err; + } + + aes_dd->io_base = ioremap(aes_dd->phys_base, aes_phys_size); + if (!aes_dd->io_base) { + dev_err(dev, "can't ioremap\n"); + err = -ENOMEM; + goto aes_io_err; + } + + err = atmel_aes_dma_init(aes_dd); + if (err) + goto err_aes_dma; + + spin_lock(&atmel_aes.lock); + list_add_tail(&aes_dd->list, &atmel_aes.dev_list); + spin_unlock(&atmel_aes.lock); + + err = atmel_aes_register_algs(aes_dd); + if (err) + goto err_algs; + + dev_info(dev, "Atmel AES\n"); + + return 0; + +err_algs: + spin_lock(&atmel_aes.lock); + list_del(&aes_dd->list); + spin_unlock(&atmel_aes.lock); + atmel_aes_dma_cleanup(aes_dd); +err_aes_dma: + iounmap(aes_dd->io_base); +aes_io_err: + clk_put(aes_dd->iclk); +clk_err: + free_irq(aes_dd->irq, aes_dd); +aes_irq_err: +res_err: + tasklet_kill(&aes_dd->done_task); + tasklet_kill(&aes_dd->queue_task); + kfree(aes_dd); + aes_dd = NULL; +aes_dd_err: + dev_err(dev, "initialization failed.\n"); + + return err; +} + +static int __devexit atmel_aes_remove(struct platform_device *pdev) +{ + static struct atmel_aes_dev *aes_dd; + + aes_dd = platform_get_drvdata(pdev); + if (!aes_dd) + return -ENODEV; + spin_lock(&atmel_aes.lock); + list_del(&aes_dd->list); + spin_unlock(&atmel_aes.lock); + + atmel_aes_unregister_algs(aes_dd); + + tasklet_kill(&aes_dd->done_task); + tasklet_kill(&aes_dd->queue_task); + + atmel_aes_dma_cleanup(aes_dd); + + iounmap(aes_dd->io_base); + + clk_put(aes_dd->iclk); + + if (aes_dd->irq > 0) + free_irq(aes_dd->irq, aes_dd); + + kfree(aes_dd); + aes_dd = NULL; + + return 0; +} + +static struct platform_driver atmel_aes_driver = { + .probe = atmel_aes_probe, + .remove = __devexit_p(atmel_aes_remove), + .driver = { + .name = "atmel_aes", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(atmel_aes_driver); + +MODULE_DESCRIPTION("Atmel AES hw acceleration support."); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique"); -- GitLab From 13802005d8f2db244ec1f5d7f6923de8f7a463db Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 1 Jul 2012 19:19:45 +0200 Subject: [PATCH 2471/5711] crypto: atmel - add Atmel DES/TDES driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 16 + drivers/crypto/Makefile | 1 + drivers/crypto/atmel-tdes-regs.h | 89 +++ drivers/crypto/atmel-tdes.c | 1215 ++++++++++++++++++++++++++++++ 4 files changed, 1321 insertions(+) create mode 100644 drivers/crypto/atmel-tdes-regs.h create mode 100644 drivers/crypto/atmel-tdes.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index d04eabef1e8c..76d489b8890f 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -349,4 +349,20 @@ config CRYPTO_DEV_ATMEL_AES To compile this driver as a module, choose M here: the module will be called atmel-aes. +config CRYPTO_DEV_ATMEL_TDES + tristate "Support for Atmel DES/TDES hw accelerator" + depends on ARCH_AT91 + select CRYPTO_DES + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + help + Some Atmel processors have DES/TDES hw accelerator. + Select this if you want to use the Atmel module for + DES/TDES algorithms. + + To compile this driver as a module, choose M here: the module + will be called atmel-tdes. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 44a8147c630e..6b8b75f2b8c0 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o +obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o diff --git a/drivers/crypto/atmel-tdes-regs.h b/drivers/crypto/atmel-tdes-regs.h new file mode 100644 index 000000000000..5ac2a900d80c --- /dev/null +++ b/drivers/crypto/atmel-tdes-regs.h @@ -0,0 +1,89 @@ +#ifndef __ATMEL_TDES_REGS_H__ +#define __ATMEL_TDES_REGS_H__ + +#define TDES_CR 0x00 +#define TDES_CR_START (1 << 0) +#define TDES_CR_SWRST (1 << 8) +#define TDES_CR_LOADSEED (1 << 16) + +#define TDES_MR 0x04 +#define TDES_MR_CYPHER_DEC (0 << 0) +#define TDES_MR_CYPHER_ENC (1 << 0) +#define TDES_MR_TDESMOD_MASK (0x3 << 1) +#define TDES_MR_TDESMOD_DES (0x0 << 1) +#define TDES_MR_TDESMOD_TDES (0x1 << 1) +#define TDES_MR_TDESMOD_XTEA (0x2 << 1) +#define TDES_MR_KEYMOD_3KEY (0 << 4) +#define TDES_MR_KEYMOD_2KEY (1 << 4) +#define TDES_MR_SMOD_MASK (0x3 << 8) +#define TDES_MR_SMOD_MANUAL (0x0 << 8) +#define TDES_MR_SMOD_AUTO (0x1 << 8) +#define TDES_MR_SMOD_PDC (0x2 << 8) +#define TDES_MR_OPMOD_MASK (0x3 << 12) +#define TDES_MR_OPMOD_ECB (0x0 << 12) +#define TDES_MR_OPMOD_CBC (0x1 << 12) +#define TDES_MR_OPMOD_OFB (0x2 << 12) +#define TDES_MR_OPMOD_CFB (0x3 << 12) +#define TDES_MR_LOD (0x1 << 15) +#define TDES_MR_CFBS_MASK (0x3 << 16) +#define TDES_MR_CFBS_64b (0x0 << 16) +#define TDES_MR_CFBS_32b (0x1 << 16) +#define TDES_MR_CFBS_16b (0x2 << 16) +#define TDES_MR_CFBS_8b (0x3 << 16) +#define TDES_MR_CKEY_MASK (0xF << 20) +#define TDES_MR_CKEY_OFFSET 20 +#define TDES_MR_CTYPE_MASK (0x3F << 24) +#define TDES_MR_CTYPE_OFFSET 24 + +#define TDES_IER 0x10 +#define TDES_IDR 0x14 +#define TDES_IMR 0x18 +#define TDES_ISR 0x1C +#define TDES_INT_DATARDY (1 << 0) +#define TDES_INT_ENDRX (1 << 1) +#define TDES_INT_ENDTX (1 << 2) +#define TDES_INT_RXBUFF (1 << 3) +#define TDES_INT_TXBUFE (1 << 4) +#define TDES_INT_URAD (1 << 8) +#define TDES_ISR_URAT_MASK (0x3 << 12) +#define TDES_ISR_URAT_IDR (0x0 << 12) +#define TDES_ISR_URAT_ODR (0x1 << 12) +#define TDES_ISR_URAT_MR (0x2 << 12) +#define TDES_ISR_URAT_WO (0x3 << 12) + + +#define TDES_KEY1W1R 0x20 +#define TDES_KEY1W2R 0x24 +#define TDES_KEY2W1R 0x28 +#define TDES_KEY2W2R 0x2C +#define TDES_KEY3W1R 0x30 +#define TDES_KEY3W2R 0x34 +#define TDES_IDATA1R 0x40 +#define TDES_IDATA2R 0x44 +#define TDES_ODATA1R 0x50 +#define TDES_ODATA2R 0x54 +#define TDES_IV1R 0x60 +#define TDES_IV2R 0x64 + +#define TDES_XTEARNDR 0x70 +#define TDES_XTEARNDR_XTEA_RNDS_MASK (0x3F << 0) +#define TDES_XTEARNDR_XTEA_RNDS_OFFSET 0 + +#define TDES_RPR 0x100 +#define TDES_RCR 0x104 +#define TDES_TPR 0x108 +#define TDES_TCR 0x10C +#define TDES_RNPR 0x118 +#define TDES_RNCR 0x11C +#define TDES_TNPR 0x118 +#define TDES_TNCR 0x11C +#define TDES_PTCR 0x120 +#define TDES_PTCR_RXTEN (1 << 0) +#define TDES_PTCR_RXTDIS (1 << 1) +#define TDES_PTCR_TXTEN (1 << 8) +#define TDES_PTCR_TXTDIS (1 << 9) +#define TDES_PTSR 0x124 +#define TDES_PTSR_RXTEN (1 << 0) +#define TDES_PTSR_TXTEN (1 << 8) + +#endif /* __ATMEL_TDES_REGS_H__ */ diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c new file mode 100644 index 000000000000..eb2b61e57e2d --- /dev/null +++ b/drivers/crypto/atmel-tdes.c @@ -0,0 +1,1215 @@ +/* + * Cryptographic API. + * + * Support for ATMEL DES/TDES HW acceleration. + * + * Copyright (c) 2012 Eukréa Electromatique - ATMEL + * Author: Nicolas Royer + * + * 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. + * + * Some ideas are from omap-aes.c drivers. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atmel-tdes-regs.h" + +/* TDES flags */ +#define TDES_FLAGS_MODE_MASK 0x007f +#define TDES_FLAGS_ENCRYPT BIT(0) +#define TDES_FLAGS_CBC BIT(1) +#define TDES_FLAGS_CFB BIT(2) +#define TDES_FLAGS_CFB8 BIT(3) +#define TDES_FLAGS_CFB16 BIT(4) +#define TDES_FLAGS_CFB32 BIT(5) +#define TDES_FLAGS_OFB BIT(6) + +#define TDES_FLAGS_INIT BIT(16) +#define TDES_FLAGS_FAST BIT(17) +#define TDES_FLAGS_BUSY BIT(18) + +#define ATMEL_TDES_QUEUE_LENGTH 1 + +#define CFB8_BLOCK_SIZE 1 +#define CFB16_BLOCK_SIZE 2 +#define CFB32_BLOCK_SIZE 4 +#define CFB64_BLOCK_SIZE 8 + + +struct atmel_tdes_dev; + +struct atmel_tdes_ctx { + struct atmel_tdes_dev *dd; + + int keylen; + u32 key[3*DES_KEY_SIZE / sizeof(u32)]; + unsigned long flags; +}; + +struct atmel_tdes_reqctx { + unsigned long mode; +}; + +struct atmel_tdes_dev { + struct list_head list; + unsigned long phys_base; + void __iomem *io_base; + + struct atmel_tdes_ctx *ctx; + struct device *dev; + struct clk *iclk; + int irq; + + unsigned long flags; + int err; + + spinlock_t lock; + struct crypto_queue queue; + + struct tasklet_struct done_task; + struct tasklet_struct queue_task; + + struct ablkcipher_request *req; + size_t total; + + struct scatterlist *in_sg; + size_t in_offset; + struct scatterlist *out_sg; + size_t out_offset; + + size_t buflen; + size_t dma_size; + + void *buf_in; + int dma_in; + dma_addr_t dma_addr_in; + + void *buf_out; + int dma_out; + dma_addr_t dma_addr_out; +}; + +struct atmel_tdes_drv { + struct list_head dev_list; + spinlock_t lock; +}; + +static struct atmel_tdes_drv atmel_tdes = { + .dev_list = LIST_HEAD_INIT(atmel_tdes.dev_list), + .lock = __SPIN_LOCK_UNLOCKED(atmel_tdes.lock), +}; + +static int atmel_tdes_sg_copy(struct scatterlist **sg, size_t *offset, + void *buf, size_t buflen, size_t total, int out) +{ + unsigned int count, off = 0; + + while (buflen && total) { + count = min((*sg)->length - *offset, total); + count = min(count, buflen); + + if (!count) + return off; + + scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out); + + off += count; + buflen -= count; + *offset += count; + total -= count; + + if (*offset == (*sg)->length) { + *sg = sg_next(*sg); + if (*sg) + *offset = 0; + else + total = 0; + } + } + + return off; +} + +static inline u32 atmel_tdes_read(struct atmel_tdes_dev *dd, u32 offset) +{ + return readl_relaxed(dd->io_base + offset); +} + +static inline void atmel_tdes_write(struct atmel_tdes_dev *dd, + u32 offset, u32 value) +{ + writel_relaxed(value, dd->io_base + offset); +} + +static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset, + u32 *value, int count) +{ + for (; count--; value++, offset += 4) + atmel_tdes_write(dd, offset, *value); +} + +static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx) +{ + struct atmel_tdes_dev *tdes_dd = NULL; + struct atmel_tdes_dev *tmp; + + spin_lock_bh(&atmel_tdes.lock); + if (!ctx->dd) { + list_for_each_entry(tmp, &atmel_tdes.dev_list, list) { + tdes_dd = tmp; + break; + } + ctx->dd = tdes_dd; + } else { + tdes_dd = ctx->dd; + } + spin_unlock_bh(&atmel_tdes.lock); + + return tdes_dd; +} + +static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd) +{ + clk_prepare_enable(dd->iclk); + + if (!(dd->flags & TDES_FLAGS_INIT)) { + atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST); + dd->flags |= TDES_FLAGS_INIT; + dd->err = 0; + } + + return 0; +} + +static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd) +{ + int err; + u32 valcr = 0, valmr = TDES_MR_SMOD_PDC; + + err = atmel_tdes_hw_init(dd); + + if (err) + return err; + + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS); + + /* MR register must be set before IV registers */ + if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) { + valmr |= TDES_MR_KEYMOD_3KEY; + valmr |= TDES_MR_TDESMOD_TDES; + } else if (dd->ctx->keylen > DES_KEY_SIZE) { + valmr |= TDES_MR_KEYMOD_2KEY; + valmr |= TDES_MR_TDESMOD_TDES; + } else { + valmr |= TDES_MR_TDESMOD_DES; + } + + if (dd->flags & TDES_FLAGS_CBC) { + valmr |= TDES_MR_OPMOD_CBC; + } else if (dd->flags & TDES_FLAGS_CFB) { + valmr |= TDES_MR_OPMOD_CFB; + + if (dd->flags & TDES_FLAGS_CFB8) + valmr |= TDES_MR_CFBS_8b; + else if (dd->flags & TDES_FLAGS_CFB16) + valmr |= TDES_MR_CFBS_16b; + else if (dd->flags & TDES_FLAGS_CFB32) + valmr |= TDES_MR_CFBS_32b; + } else if (dd->flags & TDES_FLAGS_OFB) { + valmr |= TDES_MR_OPMOD_OFB; + } + + if ((dd->flags & TDES_FLAGS_ENCRYPT) || (dd->flags & TDES_FLAGS_OFB)) + valmr |= TDES_MR_CYPHER_ENC; + + atmel_tdes_write(dd, TDES_CR, valcr); + atmel_tdes_write(dd, TDES_MR, valmr); + + atmel_tdes_write_n(dd, TDES_KEY1W1R, dd->ctx->key, + dd->ctx->keylen >> 2); + + if (((dd->flags & TDES_FLAGS_CBC) || (dd->flags & TDES_FLAGS_CFB) || + (dd->flags & TDES_FLAGS_OFB)) && dd->req->info) { + atmel_tdes_write_n(dd, TDES_IV1R, dd->req->info, 2); + } + + return 0; +} + +static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd) +{ + int err = 0; + size_t count; + + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS); + + if (dd->flags & TDES_FLAGS_FAST) { + dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); + } else { + dma_sync_single_for_device(dd->dev, dd->dma_addr_out, + dd->dma_size, DMA_FROM_DEVICE); + + /* copy data */ + count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset, + dd->buf_out, dd->buflen, dd->dma_size, 1); + if (count != dd->dma_size) { + err = -EINVAL; + pr_err("not all data converted: %u\n", count); + } + } + + return err; +} + +static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd) +{ + int err = -ENOMEM; + + dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); + dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0); + dd->buflen = PAGE_SIZE; + dd->buflen &= ~(DES_BLOCK_SIZE - 1); + + if (!dd->buf_in || !dd->buf_out) { + dev_err(dd->dev, "unable to alloc pages.\n"); + goto err_alloc; + } + + /* MAP here */ + dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, + dd->buflen, DMA_TO_DEVICE); + if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { + dev_err(dd->dev, "dma %d bytes error\n", dd->buflen); + err = -EINVAL; + goto err_map_in; + } + + dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, + dd->buflen, DMA_FROM_DEVICE); + if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { + dev_err(dd->dev, "dma %d bytes error\n", dd->buflen); + err = -EINVAL; + goto err_map_out; + } + + return 0; + +err_map_out: + dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, + DMA_TO_DEVICE); +err_map_in: + free_page((unsigned long)dd->buf_out); + free_page((unsigned long)dd->buf_in); +err_alloc: + if (err) + pr_err("error: %d\n", err); + return err; +} + +static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd) +{ + dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen, + DMA_FROM_DEVICE); + dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, + DMA_TO_DEVICE); + free_page((unsigned long)dd->buf_out); + free_page((unsigned long)dd->buf_in); +} + +static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in, + dma_addr_t dma_addr_out, int length) +{ + struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + struct atmel_tdes_dev *dd = ctx->dd; + int len32; + + dd->dma_size = length; + + if (!(dd->flags & TDES_FLAGS_FAST)) { + dma_sync_single_for_device(dd->dev, dma_addr_in, length, + DMA_TO_DEVICE); + } + + if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB8)) + len32 = DIV_ROUND_UP(length, sizeof(u8)); + else if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB16)) + len32 = DIV_ROUND_UP(length, sizeof(u16)); + else + len32 = DIV_ROUND_UP(length, sizeof(u32)); + + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS); + atmel_tdes_write(dd, TDES_TPR, dma_addr_in); + atmel_tdes_write(dd, TDES_TCR, len32); + atmel_tdes_write(dd, TDES_RPR, dma_addr_out); + atmel_tdes_write(dd, TDES_RCR, len32); + + /* Enable Interrupt */ + atmel_tdes_write(dd, TDES_IER, TDES_INT_ENDRX); + + /* Start DMA transfer */ + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTEN | TDES_PTCR_RXTEN); + + return 0; +} + +static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd) +{ + struct crypto_tfm *tfm = crypto_ablkcipher_tfm( + crypto_ablkcipher_reqtfm(dd->req)); + int err, fast = 0, in, out; + size_t count; + dma_addr_t addr_in, addr_out; + + if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) { + /* check for alignment */ + in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)); + out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)); + + fast = in && out; + } + + if (fast) { + count = min(dd->total, sg_dma_len(dd->in_sg)); + count = min(count, sg_dma_len(dd->out_sg)); + + if (count != dd->total) { + pr_err("request length != buffer length\n"); + return -EINVAL; + } + + err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); + if (!err) { + dev_err(dd->dev, "dma_map_sg() error\n"); + return -EINVAL; + } + + err = dma_map_sg(dd->dev, dd->out_sg, 1, + DMA_FROM_DEVICE); + if (!err) { + dev_err(dd->dev, "dma_map_sg() error\n"); + dma_unmap_sg(dd->dev, dd->in_sg, 1, + DMA_TO_DEVICE); + return -EINVAL; + } + + addr_in = sg_dma_address(dd->in_sg); + addr_out = sg_dma_address(dd->out_sg); + + dd->flags |= TDES_FLAGS_FAST; + + } else { + /* use cache buffers */ + count = atmel_tdes_sg_copy(&dd->in_sg, &dd->in_offset, + dd->buf_in, dd->buflen, dd->total, 0); + + addr_in = dd->dma_addr_in; + addr_out = dd->dma_addr_out; + + dd->flags &= ~TDES_FLAGS_FAST; + + } + + dd->total -= count; + + err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count); + if (err) { + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); + dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE); + } + + return err; +} + + +static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err) +{ + struct ablkcipher_request *req = dd->req; + + clk_disable_unprepare(dd->iclk); + + dd->flags &= ~TDES_FLAGS_BUSY; + + req->base.complete(&req->base, err); +} + +static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd, + struct ablkcipher_request *req) +{ + struct crypto_async_request *async_req, *backlog; + struct atmel_tdes_ctx *ctx; + struct atmel_tdes_reqctx *rctx; + unsigned long flags; + int err, ret = 0; + + spin_lock_irqsave(&dd->lock, flags); + if (req) + ret = ablkcipher_enqueue_request(&dd->queue, req); + if (dd->flags & TDES_FLAGS_BUSY) { + spin_unlock_irqrestore(&dd->lock, flags); + return ret; + } + backlog = crypto_get_backlog(&dd->queue); + async_req = crypto_dequeue_request(&dd->queue); + if (async_req) + dd->flags |= TDES_FLAGS_BUSY; + spin_unlock_irqrestore(&dd->lock, flags); + + if (!async_req) + return ret; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + req = ablkcipher_request_cast(async_req); + + /* assign new request to device */ + dd->req = req; + dd->total = req->nbytes; + dd->in_offset = 0; + dd->in_sg = req->src; + dd->out_offset = 0; + dd->out_sg = req->dst; + + rctx = ablkcipher_request_ctx(req); + ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); + rctx->mode &= TDES_FLAGS_MODE_MASK; + dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode; + dd->ctx = ctx; + ctx->dd = dd; + + err = atmel_tdes_write_ctrl(dd); + if (!err) + err = atmel_tdes_crypt_dma_start(dd); + if (err) { + /* des_task will not finish it, so do it here */ + atmel_tdes_finish_req(dd, err); + tasklet_schedule(&dd->queue_task); + } + + return ret; +} + + +static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode) +{ + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req); + struct atmel_tdes_dev *dd; + + if (mode & TDES_FLAGS_CFB8) { + if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) { + pr_err("request size is not exact amount of CFB8 blocks\n"); + return -EINVAL; + } + } else if (mode & TDES_FLAGS_CFB16) { + if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) { + pr_err("request size is not exact amount of CFB16 blocks\n"); + return -EINVAL; + } + } else if (mode & TDES_FLAGS_CFB32) { + if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) { + pr_err("request size is not exact amount of CFB32 blocks\n"); + return -EINVAL; + } + } else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) { + pr_err("request size is not exact amount of DES blocks\n"); + return -EINVAL; + } + + dd = atmel_tdes_find_dev(ctx); + if (!dd) + return -ENODEV; + + rctx->mode = mode; + + return atmel_tdes_handle_queue(dd, req); +} + +static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + u32 tmp[DES_EXPKEY_WORDS]; + int err; + struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); + + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (keylen != DES_KEY_SIZE) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + err = des_ekey(tmp, key); + if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) { + ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; + return -EINVAL; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + return 0; +} + +static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + const char *alg_name; + + alg_name = crypto_tfm_alg_name(crypto_ablkcipher_tfm(tfm)); + + /* + * HW bug in cfb 3-keys mode. + */ + if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + return 0; +} + +static int atmel_tdes_ecb_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT); +} + +static int atmel_tdes_ecb_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, 0); +} + +static int atmel_tdes_cbc_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CBC); +} + +static int atmel_tdes_cbc_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_CBC); +} +static int atmel_tdes_cfb_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB); +} + +static int atmel_tdes_cfb_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_CFB); +} + +static int atmel_tdes_cfb8_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB | + TDES_FLAGS_CFB8); +} + +static int atmel_tdes_cfb8_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB8); +} + +static int atmel_tdes_cfb16_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB | + TDES_FLAGS_CFB16); +} + +static int atmel_tdes_cfb16_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB16); +} + +static int atmel_tdes_cfb32_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB | + TDES_FLAGS_CFB32); +} + +static int atmel_tdes_cfb32_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB32); +} + +static int atmel_tdes_ofb_encrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_OFB); +} + +static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req) +{ + return atmel_tdes_crypt(req, TDES_FLAGS_OFB); +} + +static int atmel_tdes_cra_init(struct crypto_tfm *tfm) +{ + tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx); + + return 0; +} + +static void atmel_tdes_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct crypto_alg tdes_algs[] = { +{ + .cra_name = "ecb(des)", + .cra_driver_name = "atmel-ecb-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_ecb_encrypt, + .decrypt = atmel_tdes_ecb_decrypt, + } +}, +{ + .cra_name = "cbc(des)", + .cra_driver_name = "atmel-cbc-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_cbc_encrypt, + .decrypt = atmel_tdes_cbc_decrypt, + } +}, +{ + .cra_name = "cfb(des)", + .cra_driver_name = "atmel-cfb-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_cfb_encrypt, + .decrypt = atmel_tdes_cfb_decrypt, + } +}, +{ + .cra_name = "cfb8(des)", + .cra_driver_name = "atmel-cfb8-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB8_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_cfb8_encrypt, + .decrypt = atmel_tdes_cfb8_decrypt, + } +}, +{ + .cra_name = "cfb16(des)", + .cra_driver_name = "atmel-cfb16-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB16_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_cfb16_encrypt, + .decrypt = atmel_tdes_cfb16_decrypt, + } +}, +{ + .cra_name = "cfb32(des)", + .cra_driver_name = "atmel-cfb32-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_cfb32_encrypt, + .decrypt = atmel_tdes_cfb32_decrypt, + } +}, +{ + .cra_name = "ofb(des)", + .cra_driver_name = "atmel-ofb-des", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_des_setkey, + .encrypt = atmel_tdes_ofb_encrypt, + .decrypt = atmel_tdes_ofb_decrypt, + } +}, +{ + .cra_name = "ecb(des3_ede)", + .cra_driver_name = "atmel-ecb-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * DES_KEY_SIZE, + .max_keysize = 3 * DES_KEY_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_ecb_encrypt, + .decrypt = atmel_tdes_ecb_decrypt, + } +}, +{ + .cra_name = "cbc(des3_ede)", + .cra_driver_name = "atmel-cbc-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 3*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_cbc_encrypt, + .decrypt = atmel_tdes_cbc_decrypt, + } +}, +{ + .cra_name = "cfb(des3_ede)", + .cra_driver_name = "atmel-cfb-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 2*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_cfb_encrypt, + .decrypt = atmel_tdes_cfb_decrypt, + } +}, +{ + .cra_name = "cfb8(des3_ede)", + .cra_driver_name = "atmel-cfb8-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB8_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 2*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_cfb8_encrypt, + .decrypt = atmel_tdes_cfb8_decrypt, + } +}, +{ + .cra_name = "cfb16(des3_ede)", + .cra_driver_name = "atmel-cfb16-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB16_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 2*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_cfb16_encrypt, + .decrypt = atmel_tdes_cfb16_decrypt, + } +}, +{ + .cra_name = "cfb32(des3_ede)", + .cra_driver_name = "atmel-cfb32-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = CFB32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 2*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_cfb32_encrypt, + .decrypt = atmel_tdes_cfb32_decrypt, + } +}, +{ + .cra_name = "ofb(des3_ede)", + .cra_driver_name = "atmel-ofb-tdes", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = atmel_tdes_cra_init, + .cra_exit = atmel_tdes_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2*DES_KEY_SIZE, + .max_keysize = 3*DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = atmel_tdes_setkey, + .encrypt = atmel_tdes_ofb_encrypt, + .decrypt = atmel_tdes_ofb_decrypt, + } +}, +}; + +static void atmel_tdes_queue_task(unsigned long data) +{ + struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *)data; + + atmel_tdes_handle_queue(dd, NULL); +} + +static void atmel_tdes_done_task(unsigned long data) +{ + struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data; + int err; + + err = atmel_tdes_crypt_dma_stop(dd); + + err = dd->err ? : err; + + if (dd->total && !err) { + err = atmel_tdes_crypt_dma_start(dd); + if (!err) + return; + } + + atmel_tdes_finish_req(dd, err); + atmel_tdes_handle_queue(dd, NULL); +} + +static irqreturn_t atmel_tdes_irq(int irq, void *dev_id) +{ + struct atmel_tdes_dev *tdes_dd = dev_id; + u32 reg; + + reg = atmel_tdes_read(tdes_dd, TDES_ISR); + if (reg & atmel_tdes_read(tdes_dd, TDES_IMR)) { + atmel_tdes_write(tdes_dd, TDES_IDR, reg); + if (TDES_FLAGS_BUSY & tdes_dd->flags) + tasklet_schedule(&tdes_dd->done_task); + else + dev_warn(tdes_dd->dev, "TDES interrupt when no active requests.\n"); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void atmel_tdes_unregister_algs(struct atmel_tdes_dev *dd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) + crypto_unregister_alg(&tdes_algs[i]); +} + +static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd) +{ + int err, i, j; + + for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) { + INIT_LIST_HEAD(&tdes_algs[i].cra_list); + err = crypto_register_alg(&tdes_algs[i]); + if (err) + goto err_tdes_algs; + } + + return 0; + +err_tdes_algs: + for (j = 0; j < i; j++) + crypto_unregister_alg(&tdes_algs[j]); + + return err; +} + +static int __devinit atmel_tdes_probe(struct platform_device *pdev) +{ + struct atmel_tdes_dev *tdes_dd; + struct device *dev = &pdev->dev; + struct resource *tdes_res; + unsigned long tdes_phys_size; + int err; + + tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL); + if (tdes_dd == NULL) { + dev_err(dev, "unable to alloc data struct.\n"); + err = -ENOMEM; + goto tdes_dd_err; + } + + tdes_dd->dev = dev; + + platform_set_drvdata(pdev, tdes_dd); + + INIT_LIST_HEAD(&tdes_dd->list); + + tasklet_init(&tdes_dd->done_task, atmel_tdes_done_task, + (unsigned long)tdes_dd); + tasklet_init(&tdes_dd->queue_task, atmel_tdes_queue_task, + (unsigned long)tdes_dd); + + crypto_init_queue(&tdes_dd->queue, ATMEL_TDES_QUEUE_LENGTH); + + tdes_dd->irq = -1; + + /* Get the base address */ + tdes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!tdes_res) { + dev_err(dev, "no MEM resource info\n"); + err = -ENODEV; + goto res_err; + } + tdes_dd->phys_base = tdes_res->start; + tdes_phys_size = resource_size(tdes_res); + + /* Get the IRQ */ + tdes_dd->irq = platform_get_irq(pdev, 0); + if (tdes_dd->irq < 0) { + dev_err(dev, "no IRQ resource info\n"); + err = tdes_dd->irq; + goto res_err; + } + + err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED, + "atmel-tdes", tdes_dd); + if (err) { + dev_err(dev, "unable to request tdes irq.\n"); + goto tdes_irq_err; + } + + /* Initializing the clock */ + tdes_dd->iclk = clk_get(&pdev->dev, NULL); + if (IS_ERR(tdes_dd->iclk)) { + dev_err(dev, "clock intialization failed.\n"); + err = PTR_ERR(tdes_dd->iclk); + goto clk_err; + } + + tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size); + if (!tdes_dd->io_base) { + dev_err(dev, "can't ioremap\n"); + err = -ENOMEM; + goto tdes_io_err; + } + + err = atmel_tdes_dma_init(tdes_dd); + if (err) + goto err_tdes_dma; + + spin_lock(&atmel_tdes.lock); + list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list); + spin_unlock(&atmel_tdes.lock); + + err = atmel_tdes_register_algs(tdes_dd); + if (err) + goto err_algs; + + dev_info(dev, "Atmel DES/TDES\n"); + + return 0; + +err_algs: + spin_lock(&atmel_tdes.lock); + list_del(&tdes_dd->list); + spin_unlock(&atmel_tdes.lock); + atmel_tdes_dma_cleanup(tdes_dd); +err_tdes_dma: + iounmap(tdes_dd->io_base); +tdes_io_err: + clk_put(tdes_dd->iclk); +clk_err: + free_irq(tdes_dd->irq, tdes_dd); +tdes_irq_err: +res_err: + tasklet_kill(&tdes_dd->done_task); + tasklet_kill(&tdes_dd->queue_task); + kfree(tdes_dd); + tdes_dd = NULL; +tdes_dd_err: + dev_err(dev, "initialization failed.\n"); + + return err; +} + +static int __devexit atmel_tdes_remove(struct platform_device *pdev) +{ + static struct atmel_tdes_dev *tdes_dd; + + tdes_dd = platform_get_drvdata(pdev); + if (!tdes_dd) + return -ENODEV; + spin_lock(&atmel_tdes.lock); + list_del(&tdes_dd->list); + spin_unlock(&atmel_tdes.lock); + + atmel_tdes_unregister_algs(tdes_dd); + + tasklet_kill(&tdes_dd->done_task); + tasklet_kill(&tdes_dd->queue_task); + + atmel_tdes_dma_cleanup(tdes_dd); + + iounmap(tdes_dd->io_base); + + clk_put(tdes_dd->iclk); + + if (tdes_dd->irq >= 0) + free_irq(tdes_dd->irq, tdes_dd); + + kfree(tdes_dd); + tdes_dd = NULL; + + return 0; +} + +static struct platform_driver atmel_tdes_driver = { + .probe = atmel_tdes_probe, + .remove = __devexit_p(atmel_tdes_remove), + .driver = { + .name = "atmel_tdes", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(atmel_tdes_driver); + +MODULE_DESCRIPTION("Atmel DES/TDES hw acceleration support."); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique"); -- GitLab From ebc82efa1cd64efba0f41455460411b852b5b89c Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 1 Jul 2012 19:19:46 +0200 Subject: [PATCH 2472/5711] crypto: atmel - add Atmel SHA1/SHA256 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 14 + drivers/crypto/Makefile | 1 + drivers/crypto/atmel-sha-regs.h | 46 ++ drivers/crypto/atmel-sha.c | 1112 +++++++++++++++++++++++++++++++ 4 files changed, 1173 insertions(+) create mode 100644 drivers/crypto/atmel-sha-regs.h create mode 100644 drivers/crypto/atmel-sha.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 76d489b8890f..7d74d092aa8f 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -365,4 +365,18 @@ config CRYPTO_DEV_ATMEL_TDES To compile this driver as a module, choose M here: the module will be called atmel-tdes. +config CRYPTO_DEV_ATMEL_SHA + tristate "Support for Atmel SHA1/SHA256 hw accelerator" + depends on ARCH_AT91 + select CRYPTO_SHA1 + select CRYPTO_SHA256 + select CRYPTO_ALGAPI + help + Some Atmel processors have SHA1/SHA256 hw accelerator. + Select this if you want to use the Atmel module for + SHA1/SHA256 algorithms. + + To compile this driver as a module, choose M here: the module + will be called atmel-sha. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 6b8b75f2b8c0..880a47b0b023 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o +obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h new file mode 100644 index 000000000000..dc53a20d7da1 --- /dev/null +++ b/drivers/crypto/atmel-sha-regs.h @@ -0,0 +1,46 @@ +#ifndef __ATMEL_SHA_REGS_H__ +#define __ATMEL_SHA_REGS_H__ + +#define SHA_REG_DIGEST(x) (0x80 + ((x) * 0x04)) +#define SHA_REG_DIN(x) (0x40 + ((x) * 0x04)) + +#define SHA_CR 0x00 +#define SHA_CR_START (1 << 0) +#define SHA_CR_FIRST (1 << 4) +#define SHA_CR_SWRST (1 << 8) + +#define SHA_MR 0x04 +#define SHA_MR_MODE_MASK (0x3 << 0) +#define SHA_MR_MODE_MANUAL 0x0 +#define SHA_MR_MODE_AUTO 0x1 +#define SHA_MR_MODE_PDC 0x2 +#define SHA_MR_DUALBUFF (1 << 3) +#define SHA_MR_PROCDLY (1 << 4) +#define SHA_MR_ALGO_SHA1 (0 << 8) +#define SHA_MR_ALGO_SHA256 (1 << 8) + +#define SHA_IER 0x10 +#define SHA_IDR 0x14 +#define SHA_IMR 0x18 +#define SHA_ISR 0x1C +#define SHA_INT_DATARDY (1 << 0) +#define SHA_INT_ENDTX (1 << 1) +#define SHA_INT_TXBUFE (1 << 2) +#define SHA_INT_URAD (1 << 8) +#define SHA_ISR_URAT_MASK (0x7 << 12) +#define SHA_ISR_URAT_IDR (0x0 << 12) +#define SHA_ISR_URAT_ODR (0x1 << 12) +#define SHA_ISR_URAT_MR (0x2 << 12) +#define SHA_ISR_URAT_WO (0x5 << 12) + +#define SHA_TPR 0x108 +#define SHA_TCR 0x10C +#define SHA_TNPR 0x118 +#define SHA_TNCR 0x11C +#define SHA_PTCR 0x120 +#define SHA_PTCR_TXTEN (1 << 8) +#define SHA_PTCR_TXTDIS (1 << 9) +#define SHA_PTSR 0x124 +#define SHA_PTSR_TXTEN (1 << 8) + +#endif /* __ATMEL_SHA_REGS_H__ */ diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c new file mode 100644 index 000000000000..f938b9d79b66 --- /dev/null +++ b/drivers/crypto/atmel-sha.c @@ -0,0 +1,1112 @@ +/* + * Cryptographic API. + * + * Support for ATMEL SHA1/SHA256 HW acceleration. + * + * Copyright (c) 2012 Eukréa Electromatique - ATMEL + * Author: Nicolas Royer + * + * 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. + * + * Some ideas are from omap-sham.c drivers. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atmel-sha-regs.h" + +/* SHA flags */ +#define SHA_FLAGS_BUSY BIT(0) +#define SHA_FLAGS_FINAL BIT(1) +#define SHA_FLAGS_DMA_ACTIVE BIT(2) +#define SHA_FLAGS_OUTPUT_READY BIT(3) +#define SHA_FLAGS_INIT BIT(4) +#define SHA_FLAGS_CPU BIT(5) +#define SHA_FLAGS_DMA_READY BIT(6) + +#define SHA_FLAGS_FINUP BIT(16) +#define SHA_FLAGS_SG BIT(17) +#define SHA_FLAGS_SHA1 BIT(18) +#define SHA_FLAGS_SHA256 BIT(19) +#define SHA_FLAGS_ERROR BIT(20) +#define SHA_FLAGS_PAD BIT(21) + +#define SHA_FLAGS_DUALBUFF BIT(24) + +#define SHA_OP_UPDATE 1 +#define SHA_OP_FINAL 2 + +#define SHA_BUFFER_LEN PAGE_SIZE + +#define ATMEL_SHA_DMA_THRESHOLD 56 + + +struct atmel_sha_dev; + +struct atmel_sha_reqctx { + struct atmel_sha_dev *dd; + unsigned long flags; + unsigned long op; + + u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32)); + size_t digcnt; + size_t bufcnt; + size_t buflen; + dma_addr_t dma_addr; + + /* walk state */ + struct scatterlist *sg; + unsigned int offset; /* offset in current sg */ + unsigned int total; /* total request */ + + u8 buffer[0] __aligned(sizeof(u32)); +}; + +struct atmel_sha_ctx { + struct atmel_sha_dev *dd; + + unsigned long flags; + + /* fallback stuff */ + struct crypto_shash *fallback; + +}; + +#define ATMEL_SHA_QUEUE_LENGTH 1 + +struct atmel_sha_dev { + struct list_head list; + unsigned long phys_base; + struct device *dev; + struct clk *iclk; + int irq; + void __iomem *io_base; + + spinlock_t lock; + int err; + struct tasklet_struct done_task; + + unsigned long flags; + struct crypto_queue queue; + struct ahash_request *req; +}; + +struct atmel_sha_drv { + struct list_head dev_list; + spinlock_t lock; +}; + +static struct atmel_sha_drv atmel_sha = { + .dev_list = LIST_HEAD_INIT(atmel_sha.dev_list), + .lock = __SPIN_LOCK_UNLOCKED(atmel_sha.lock), +}; + +static inline u32 atmel_sha_read(struct atmel_sha_dev *dd, u32 offset) +{ + return readl_relaxed(dd->io_base + offset); +} + +static inline void atmel_sha_write(struct atmel_sha_dev *dd, + u32 offset, u32 value) +{ + writel_relaxed(value, dd->io_base + offset); +} + +static void atmel_sha_dualbuff_test(struct atmel_sha_dev *dd) +{ + atmel_sha_write(dd, SHA_MR, SHA_MR_DUALBUFF); + + if (atmel_sha_read(dd, SHA_MR) & SHA_MR_DUALBUFF) + dd->flags |= SHA_FLAGS_DUALBUFF; +} + +static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx) +{ + size_t count; + + while ((ctx->bufcnt < ctx->buflen) && ctx->total) { + count = min(ctx->sg->length - ctx->offset, ctx->total); + count = min(count, ctx->buflen - ctx->bufcnt); + + if (count <= 0) + break; + + scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, ctx->sg, + ctx->offset, count, 0); + + ctx->bufcnt += count; + ctx->offset += count; + ctx->total -= count; + + if (ctx->offset == ctx->sg->length) { + ctx->sg = sg_next(ctx->sg); + if (ctx->sg) + ctx->offset = 0; + else + ctx->total = 0; + } + } + + return 0; +} + +/* + * The purpose of this padding is to ensure that the padded message + * is a multiple of 512 bits. The bit "1" is appended at the end of + * the message followed by "padlen-1" zero bits. Then a 64 bits block + * equals to the message length in bits is appended. + * + * padlen is calculated as followed: + * - if message length < 56 bytes then padlen = 56 - message length + * - else padlen = 64 + 56 - message length + */ +static void atmel_sha_fill_padding(struct atmel_sha_reqctx *ctx, int length) +{ + unsigned int index, padlen; + u64 bits; + u64 size; + + bits = (ctx->bufcnt + ctx->digcnt + length) << 3; + size = cpu_to_be64(bits); + + index = ctx->bufcnt & 0x3f; + padlen = (index < 56) ? (56 - index) : ((64+56) - index); + *(ctx->buffer + ctx->bufcnt) = 0x80; + memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1); + memcpy(ctx->buffer + ctx->bufcnt + padlen, &size, 8); + ctx->bufcnt += padlen + 8; + ctx->flags |= SHA_FLAGS_PAD; +} + +static int atmel_sha_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm); + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_dev *dd = NULL; + struct atmel_sha_dev *tmp; + + spin_lock_bh(&atmel_sha.lock); + if (!tctx->dd) { + list_for_each_entry(tmp, &atmel_sha.dev_list, list) { + dd = tmp; + break; + } + tctx->dd = dd; + } else { + dd = tctx->dd; + } + + spin_unlock_bh(&atmel_sha.lock); + + ctx->dd = dd; + + ctx->flags = 0; + + dev_dbg(dd->dev, "init: digest size: %d\n", + crypto_ahash_digestsize(tfm)); + + if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE) + ctx->flags |= SHA_FLAGS_SHA1; + else if (crypto_ahash_digestsize(tfm) == SHA256_DIGEST_SIZE) + ctx->flags |= SHA_FLAGS_SHA256; + + ctx->bufcnt = 0; + ctx->digcnt = 0; + ctx->buflen = SHA_BUFFER_LEN; + + return 0; +} + +static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + u32 valcr = 0, valmr = SHA_MR_MODE_AUTO; + + if (likely(dma)) { + atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE); + valmr = SHA_MR_MODE_PDC; + if (dd->flags & SHA_FLAGS_DUALBUFF) + valmr = SHA_MR_DUALBUFF; + } else { + atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY); + } + + if (ctx->flags & SHA_FLAGS_SHA256) + valmr |= SHA_MR_ALGO_SHA256; + + /* Setting CR_FIRST only for the first iteration */ + if (!ctx->digcnt) + valcr = SHA_CR_FIRST; + + atmel_sha_write(dd, SHA_CR, valcr); + atmel_sha_write(dd, SHA_MR, valmr); +} + +static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf, + size_t length, int final) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + int count, len32; + const u32 *buffer = (const u32 *)buf; + + dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n", + ctx->digcnt, length, final); + + atmel_sha_write_ctrl(dd, 0); + + /* should be non-zero before next lines to disable clocks later */ + ctx->digcnt += length; + + if (final) + dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */ + + len32 = DIV_ROUND_UP(length, sizeof(u32)); + + dd->flags |= SHA_FLAGS_CPU; + + for (count = 0; count < len32; count++) + atmel_sha_write(dd, SHA_REG_DIN(count), buffer[count]); + + return -EINPROGRESS; +} + +static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1, + size_t length1, dma_addr_t dma_addr2, size_t length2, int final) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + int len32; + + dev_dbg(dd->dev, "xmit_pdc: digcnt: %d, length: %d, final: %d\n", + ctx->digcnt, length1, final); + + len32 = DIV_ROUND_UP(length1, sizeof(u32)); + atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTDIS); + atmel_sha_write(dd, SHA_TPR, dma_addr1); + atmel_sha_write(dd, SHA_TCR, len32); + + len32 = DIV_ROUND_UP(length2, sizeof(u32)); + atmel_sha_write(dd, SHA_TNPR, dma_addr2); + atmel_sha_write(dd, SHA_TNCR, len32); + + atmel_sha_write_ctrl(dd, 1); + + /* should be non-zero before next lines to disable clocks later */ + ctx->digcnt += length1; + + if (final) + dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */ + + dd->flags |= SHA_FLAGS_DMA_ACTIVE; + + /* Start DMA transfer */ + atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTEN); + + return -EINPROGRESS; +} + +static int atmel_sha_update_cpu(struct atmel_sha_dev *dd) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + int bufcnt; + + atmel_sha_append_sg(ctx); + atmel_sha_fill_padding(ctx, 0); + + bufcnt = ctx->bufcnt; + ctx->bufcnt = 0; + + return atmel_sha_xmit_cpu(dd, ctx->buffer, bufcnt, 1); +} + +static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd, + struct atmel_sha_reqctx *ctx, + size_t length, int final) +{ + ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, + ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dd->dev, ctx->dma_addr)) { + dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen + + SHA1_BLOCK_SIZE); + return -EINVAL; + } + + ctx->flags &= ~SHA_FLAGS_SG; + + /* next call does not fail... so no unmap in the case of error */ + return atmel_sha_xmit_pdc(dd, ctx->dma_addr, length, 0, 0, final); +} + +static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + unsigned int final; + size_t count; + + atmel_sha_append_sg(ctx); + + final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total; + + dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n", + ctx->bufcnt, ctx->digcnt, final); + + if (final) + atmel_sha_fill_padding(ctx, 0); + + if (final || (ctx->bufcnt == ctx->buflen && ctx->total)) { + count = ctx->bufcnt; + ctx->bufcnt = 0; + return atmel_sha_xmit_dma_map(dd, ctx, count, final); + } + + return 0; +} + +static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + unsigned int length, final, tail; + struct scatterlist *sg; + unsigned int count; + + if (!ctx->total) + return 0; + + if (ctx->bufcnt || ctx->offset) + return atmel_sha_update_dma_slow(dd); + + dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n", + ctx->digcnt, ctx->bufcnt, ctx->total); + + sg = ctx->sg; + + if (!IS_ALIGNED(sg->offset, sizeof(u32))) + return atmel_sha_update_dma_slow(dd); + + if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, SHA1_BLOCK_SIZE)) + /* size is not SHA1_BLOCK_SIZE aligned */ + return atmel_sha_update_dma_slow(dd); + + length = min(ctx->total, sg->length); + + if (sg_is_last(sg)) { + if (!(ctx->flags & SHA_FLAGS_FINUP)) { + /* not last sg must be SHA1_BLOCK_SIZE aligned */ + tail = length & (SHA1_BLOCK_SIZE - 1); + length -= tail; + if (length == 0) { + /* offset where to start slow */ + ctx->offset = length; + return atmel_sha_update_dma_slow(dd); + } + } + } + + ctx->total -= length; + ctx->offset = length; /* offset where to start slow */ + + final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total; + + /* Add padding */ + if (final) { + tail = length & (SHA1_BLOCK_SIZE - 1); + length -= tail; + ctx->total += tail; + ctx->offset = length; /* offset where to start slow */ + + sg = ctx->sg; + atmel_sha_append_sg(ctx); + + atmel_sha_fill_padding(ctx, length); + + ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, + ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dd->dev, ctx->dma_addr)) { + dev_err(dd->dev, "dma %u bytes error\n", + ctx->buflen + SHA1_BLOCK_SIZE); + return -EINVAL; + } + + if (length == 0) { + ctx->flags &= ~SHA_FLAGS_SG; + count = ctx->bufcnt; + ctx->bufcnt = 0; + return atmel_sha_xmit_pdc(dd, ctx->dma_addr, count, 0, + 0, final); + } else { + ctx->sg = sg; + if (!dma_map_sg(dd->dev, ctx->sg, 1, + DMA_TO_DEVICE)) { + dev_err(dd->dev, "dma_map_sg error\n"); + return -EINVAL; + } + + ctx->flags |= SHA_FLAGS_SG; + + count = ctx->bufcnt; + ctx->bufcnt = 0; + return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg), + length, ctx->dma_addr, count, final); + } + } + + if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) { + dev_err(dd->dev, "dma_map_sg error\n"); + return -EINVAL; + } + + ctx->flags |= SHA_FLAGS_SG; + + /* next call does not fail... so no unmap in the case of error */ + return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg), length, 0, + 0, final); +} + +static int atmel_sha_update_dma_stop(struct atmel_sha_dev *dd) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); + + if (ctx->flags & SHA_FLAGS_SG) { + dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE); + if (ctx->sg->length == ctx->offset) { + ctx->sg = sg_next(ctx->sg); + if (ctx->sg) + ctx->offset = 0; + } + if (ctx->flags & SHA_FLAGS_PAD) + dma_unmap_single(dd->dev, ctx->dma_addr, + ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE); + } else { + dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen + + SHA1_BLOCK_SIZE, DMA_TO_DEVICE); + } + + return 0; +} + +static int atmel_sha_update_req(struct atmel_sha_dev *dd) +{ + struct ahash_request *req = dd->req; + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + int err; + + dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n", + ctx->total, ctx->digcnt, (ctx->flags & SHA_FLAGS_FINUP) != 0); + + if (ctx->flags & SHA_FLAGS_CPU) + err = atmel_sha_update_cpu(dd); + else + err = atmel_sha_update_dma_start(dd); + + /* wait for dma completion before can take more data */ + dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n", + err, ctx->digcnt); + + return err; +} + +static int atmel_sha_final_req(struct atmel_sha_dev *dd) +{ + struct ahash_request *req = dd->req; + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + int err = 0; + int count; + + if (ctx->bufcnt >= ATMEL_SHA_DMA_THRESHOLD) { + atmel_sha_fill_padding(ctx, 0); + count = ctx->bufcnt; + ctx->bufcnt = 0; + err = atmel_sha_xmit_dma_map(dd, ctx, count, 1); + } + /* faster to handle last block with cpu */ + else { + atmel_sha_fill_padding(ctx, 0); + count = ctx->bufcnt; + ctx->bufcnt = 0; + err = atmel_sha_xmit_cpu(dd, ctx->buffer, count, 1); + } + + dev_dbg(dd->dev, "final_req: err: %d\n", err); + + return err; +} + +static void atmel_sha_copy_hash(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + u32 *hash = (u32 *)ctx->digest; + int i; + + if (likely(ctx->flags & SHA_FLAGS_SHA1)) + for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) + hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); + else + for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) + hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); +} + +static void atmel_sha_copy_ready_hash(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + + if (!req->result) + return; + + if (likely(ctx->flags & SHA_FLAGS_SHA1)) + memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE); + else + memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE); +} + +static int atmel_sha_finish(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_dev *dd = ctx->dd; + int err = 0; + + if (ctx->digcnt) + atmel_sha_copy_ready_hash(req); + + dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, + ctx->bufcnt); + + return err; +} + +static void atmel_sha_finish_req(struct ahash_request *req, int err) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_dev *dd = ctx->dd; + + if (!err) { + atmel_sha_copy_hash(req); + if (SHA_FLAGS_FINAL & dd->flags) + err = atmel_sha_finish(req); + } else { + ctx->flags |= SHA_FLAGS_ERROR; + } + + /* atomic operation is not needed here */ + dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU | + SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY); + + clk_disable_unprepare(dd->iclk); + + if (req->base.complete) + req->base.complete(&req->base, err); + + /* handle new request */ + tasklet_schedule(&dd->done_task); +} + +static int atmel_sha_hw_init(struct atmel_sha_dev *dd) +{ + clk_prepare_enable(dd->iclk); + + if (SHA_FLAGS_INIT & dd->flags) { + atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST); + atmel_sha_dualbuff_test(dd); + dd->flags |= SHA_FLAGS_INIT; + dd->err = 0; + } + + return 0; +} + +static int atmel_sha_handle_queue(struct atmel_sha_dev *dd, + struct ahash_request *req) +{ + struct crypto_async_request *async_req, *backlog; + struct atmel_sha_reqctx *ctx; + unsigned long flags; + int err = 0, ret = 0; + + spin_lock_irqsave(&dd->lock, flags); + if (req) + ret = ahash_enqueue_request(&dd->queue, req); + + if (SHA_FLAGS_BUSY & dd->flags) { + spin_unlock_irqrestore(&dd->lock, flags); + return ret; + } + + backlog = crypto_get_backlog(&dd->queue); + async_req = crypto_dequeue_request(&dd->queue); + if (async_req) + dd->flags |= SHA_FLAGS_BUSY; + + spin_unlock_irqrestore(&dd->lock, flags); + + if (!async_req) + return ret; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + req = ahash_request_cast(async_req); + dd->req = req; + ctx = ahash_request_ctx(req); + + dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n", + ctx->op, req->nbytes); + + err = atmel_sha_hw_init(dd); + + if (err) + goto err1; + + if (ctx->op == SHA_OP_UPDATE) { + err = atmel_sha_update_req(dd); + if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP)) { + /* no final() after finup() */ + err = atmel_sha_final_req(dd); + } + } else if (ctx->op == SHA_OP_FINAL) { + err = atmel_sha_final_req(dd); + } + +err1: + if (err != -EINPROGRESS) + /* done_task will not finish it, so do it here */ + atmel_sha_finish_req(req, err); + + dev_dbg(dd->dev, "exit, err: %d\n", err); + + return ret; +} + +static int atmel_sha_enqueue(struct ahash_request *req, unsigned int op) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm); + struct atmel_sha_dev *dd = tctx->dd; + + ctx->op = op; + + return atmel_sha_handle_queue(dd, req); +} + +static int atmel_sha_update(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + + if (!req->nbytes) + return 0; + + ctx->total = req->nbytes; + ctx->sg = req->src; + ctx->offset = 0; + + if (ctx->flags & SHA_FLAGS_FINUP) { + if (ctx->bufcnt + ctx->total < ATMEL_SHA_DMA_THRESHOLD) + /* faster to use CPU for short transfers */ + ctx->flags |= SHA_FLAGS_CPU; + } else if (ctx->bufcnt + ctx->total < ctx->buflen) { + atmel_sha_append_sg(ctx); + return 0; + } + return atmel_sha_enqueue(req, SHA_OP_UPDATE); +} + +static int atmel_sha_final(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm); + struct atmel_sha_dev *dd = tctx->dd; + + int err = 0; + + ctx->flags |= SHA_FLAGS_FINUP; + + if (ctx->flags & SHA_FLAGS_ERROR) + return 0; /* uncompleted hash is not needed */ + + if (ctx->bufcnt) { + return atmel_sha_enqueue(req, SHA_OP_FINAL); + } else if (!(ctx->flags & SHA_FLAGS_PAD)) { /* add padding */ + err = atmel_sha_hw_init(dd); + if (err) + goto err1; + + dd->flags |= SHA_FLAGS_BUSY; + err = atmel_sha_final_req(dd); + } else { + /* copy ready hash (+ finalize hmac) */ + return atmel_sha_finish(req); + } + +err1: + if (err != -EINPROGRESS) + /* done_task will not finish it, so do it here */ + atmel_sha_finish_req(req, err); + + return err; +} + +static int atmel_sha_finup(struct ahash_request *req) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + int err1, err2; + + ctx->flags |= SHA_FLAGS_FINUP; + + err1 = atmel_sha_update(req); + if (err1 == -EINPROGRESS || err1 == -EBUSY) + return err1; + + /* + * final() has to be always called to cleanup resources + * even if udpate() failed, except EINPROGRESS + */ + err2 = atmel_sha_final(req); + + return err1 ?: err2; +} + +static int atmel_sha_digest(struct ahash_request *req) +{ + return atmel_sha_init(req) ?: atmel_sha_finup(req); +} + +static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) +{ + struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); + + /* Allocate a fallback and abort if it failed. */ + tctx->fallback = crypto_alloc_shash(alg_name, 0, + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(tctx->fallback)) { + pr_err("atmel-sha: fallback driver '%s' could not be loaded.\n", + alg_name); + return PTR_ERR(tctx->fallback); + } + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct atmel_sha_reqctx) + + SHA_BUFFER_LEN + SHA256_BLOCK_SIZE); + + return 0; +} + +static int atmel_sha_cra_init(struct crypto_tfm *tfm) +{ + return atmel_sha_cra_init_alg(tfm, NULL); +} + +static void atmel_sha_cra_exit(struct crypto_tfm *tfm) +{ + struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm); + + crypto_free_shash(tctx->fallback); + tctx->fallback = NULL; +} + +static struct ahash_alg sha_algs[] = { +{ + .init = atmel_sha_init, + .update = atmel_sha_update, + .final = atmel_sha_final, + .finup = atmel_sha_finup, + .digest = atmel_sha_digest, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, + .base = { + .cra_name = "sha1", + .cra_driver_name = "atmel-sha1", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_sha_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = atmel_sha_cra_init, + .cra_exit = atmel_sha_cra_exit, + } + } +}, +{ + .init = atmel_sha_init, + .update = atmel_sha_update, + .final = atmel_sha_final, + .finup = atmel_sha_finup, + .digest = atmel_sha_digest, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .base = { + .cra_name = "sha256", + .cra_driver_name = "atmel-sha256", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct atmel_sha_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = atmel_sha_cra_init, + .cra_exit = atmel_sha_cra_exit, + } + } +}, +}; + +static void atmel_sha_done_task(unsigned long data) +{ + struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data; + int err = 0; + + if (!(SHA_FLAGS_BUSY & dd->flags)) { + atmel_sha_handle_queue(dd, NULL); + return; + } + + if (SHA_FLAGS_CPU & dd->flags) { + if (SHA_FLAGS_OUTPUT_READY & dd->flags) { + dd->flags &= ~SHA_FLAGS_OUTPUT_READY; + goto finish; + } + } else if (SHA_FLAGS_DMA_READY & dd->flags) { + if (SHA_FLAGS_DMA_ACTIVE & dd->flags) { + dd->flags &= ~SHA_FLAGS_DMA_ACTIVE; + atmel_sha_update_dma_stop(dd); + if (dd->err) { + err = dd->err; + goto finish; + } + } + if (SHA_FLAGS_OUTPUT_READY & dd->flags) { + /* hash or semi-hash ready */ + dd->flags &= ~(SHA_FLAGS_DMA_READY | + SHA_FLAGS_OUTPUT_READY); + err = atmel_sha_update_dma_start(dd); + if (err != -EINPROGRESS) + goto finish; + } + } + return; + +finish: + /* finish curent request */ + atmel_sha_finish_req(dd->req, err); +} + +static irqreturn_t atmel_sha_irq(int irq, void *dev_id) +{ + struct atmel_sha_dev *sha_dd = dev_id; + u32 reg; + + reg = atmel_sha_read(sha_dd, SHA_ISR); + if (reg & atmel_sha_read(sha_dd, SHA_IMR)) { + atmel_sha_write(sha_dd, SHA_IDR, reg); + if (SHA_FLAGS_BUSY & sha_dd->flags) { + sha_dd->flags |= SHA_FLAGS_OUTPUT_READY; + if (!(SHA_FLAGS_CPU & sha_dd->flags)) + sha_dd->flags |= SHA_FLAGS_DMA_READY; + tasklet_schedule(&sha_dd->done_task); + } else { + dev_warn(sha_dd->dev, "SHA interrupt when no active requests.\n"); + } + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sha_algs); i++) + crypto_unregister_ahash(&sha_algs[i]); +} + +static int atmel_sha_register_algs(struct atmel_sha_dev *dd) +{ + int err, i, j; + + for (i = 0; i < ARRAY_SIZE(sha_algs); i++) { + err = crypto_register_ahash(&sha_algs[i]); + if (err) + goto err_sha_algs; + } + + return 0; + +err_sha_algs: + for (j = 0; j < i; j++) + crypto_unregister_ahash(&sha_algs[j]); + + return err; +} + +static int __devinit atmel_sha_probe(struct platform_device *pdev) +{ + struct atmel_sha_dev *sha_dd; + struct device *dev = &pdev->dev; + struct resource *sha_res; + unsigned long sha_phys_size; + int err; + + sha_dd = kzalloc(sizeof(struct atmel_sha_dev), GFP_KERNEL); + if (sha_dd == NULL) { + dev_err(dev, "unable to alloc data struct.\n"); + err = -ENOMEM; + goto sha_dd_err; + } + + sha_dd->dev = dev; + + platform_set_drvdata(pdev, sha_dd); + + INIT_LIST_HEAD(&sha_dd->list); + + tasklet_init(&sha_dd->done_task, atmel_sha_done_task, + (unsigned long)sha_dd); + + crypto_init_queue(&sha_dd->queue, ATMEL_SHA_QUEUE_LENGTH); + + sha_dd->irq = -1; + + /* Get the base address */ + sha_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!sha_res) { + dev_err(dev, "no MEM resource info\n"); + err = -ENODEV; + goto res_err; + } + sha_dd->phys_base = sha_res->start; + sha_phys_size = resource_size(sha_res); + + /* Get the IRQ */ + sha_dd->irq = platform_get_irq(pdev, 0); + if (sha_dd->irq < 0) { + dev_err(dev, "no IRQ resource info\n"); + err = sha_dd->irq; + goto res_err; + } + + err = request_irq(sha_dd->irq, atmel_sha_irq, IRQF_SHARED, "atmel-sha", + sha_dd); + if (err) { + dev_err(dev, "unable to request sha irq.\n"); + goto res_err; + } + + /* Initializing the clock */ + sha_dd->iclk = clk_get(&pdev->dev, NULL); + if (IS_ERR(sha_dd->iclk)) { + dev_err(dev, "clock intialization failed.\n"); + err = PTR_ERR(sha_dd->iclk); + goto clk_err; + } + + sha_dd->io_base = ioremap(sha_dd->phys_base, sha_phys_size); + if (!sha_dd->io_base) { + dev_err(dev, "can't ioremap\n"); + err = -ENOMEM; + goto sha_io_err; + } + + spin_lock(&atmel_sha.lock); + list_add_tail(&sha_dd->list, &atmel_sha.dev_list); + spin_unlock(&atmel_sha.lock); + + err = atmel_sha_register_algs(sha_dd); + if (err) + goto err_algs; + + dev_info(dev, "Atmel SHA1/SHA256\n"); + + return 0; + +err_algs: + spin_lock(&atmel_sha.lock); + list_del(&sha_dd->list); + spin_unlock(&atmel_sha.lock); + iounmap(sha_dd->io_base); +sha_io_err: + clk_put(sha_dd->iclk); +clk_err: + free_irq(sha_dd->irq, sha_dd); +res_err: + tasklet_kill(&sha_dd->done_task); + kfree(sha_dd); + sha_dd = NULL; +sha_dd_err: + dev_err(dev, "initialization failed.\n"); + + return err; +} + +static int __devexit atmel_sha_remove(struct platform_device *pdev) +{ + static struct atmel_sha_dev *sha_dd; + + sha_dd = platform_get_drvdata(pdev); + if (!sha_dd) + return -ENODEV; + spin_lock(&atmel_sha.lock); + list_del(&sha_dd->list); + spin_unlock(&atmel_sha.lock); + + atmel_sha_unregister_algs(sha_dd); + + tasklet_kill(&sha_dd->done_task); + + iounmap(sha_dd->io_base); + + clk_put(sha_dd->iclk); + + if (sha_dd->irq >= 0) + free_irq(sha_dd->irq, sha_dd); + + kfree(sha_dd); + sha_dd = NULL; + + return 0; +} + +static struct platform_driver atmel_sha_driver = { + .probe = atmel_sha_probe, + .remove = __devexit_p(atmel_sha_remove), + .driver = { + .name = "atmel_sha", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(atmel_sha_driver); + +MODULE_DESCRIPTION("Atmel SHA1/SHA256 hw acceleration support."); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique"); -- GitLab From de197533485c09598215802b0e401a688e172573 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 1 Jul 2012 19:19:47 +0200 Subject: [PATCH 2473/5711] crypto: atmel - add new tests to tcrypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - set sg buffers size equals to message size - add cfb & ofb tests for AES, DES & TDES Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 58ad4fe5d208..5cf2ccb1540c 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -809,7 +809,7 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec, struct cipher_speed_template *template, unsigned int tcount, u8 *keysize) { - unsigned int ret, i, j, iv_len; + unsigned int ret, i, j, k, iv_len; struct tcrypt_result tresult; const char *key; char iv[128]; @@ -883,11 +883,23 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec, } sg_init_table(sg, TVMEMSIZE); - sg_set_buf(sg, tvmem[0] + *keysize, + + k = *keysize + *b_size; + if (k > PAGE_SIZE) { + sg_set_buf(sg, tvmem[0] + *keysize, PAGE_SIZE - *keysize); - for (j = 1; j < TVMEMSIZE; j++) { - sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); - memset(tvmem[j], 0xff, PAGE_SIZE); + k -= PAGE_SIZE; + j = 1; + while (k > PAGE_SIZE) { + sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); + memset(tvmem[j], 0xff, PAGE_SIZE); + j++; + k -= PAGE_SIZE; + } + sg_set_buf(sg + j, tvmem[j], k); + memset(tvmem[j], 0xff, k); + } else { + sg_set_buf(sg, tvmem[0] + *keysize, *b_size); } iv_len = crypto_ablkcipher_ivsize(tfm); @@ -1520,6 +1532,14 @@ static int do_test(int m) speed_template_16_24_32); test_acipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0, speed_template_16_24_32); + test_acipher_speed("cfb(aes)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("cfb(aes)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ofb(aes)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); break; case 501: @@ -1535,6 +1555,18 @@ static int do_test(int m) test_acipher_speed("cbc(des3_ede)", DECRYPT, sec, des3_speed_template, DES3_SPEED_VECTORS, speed_template_24); + test_acipher_speed("cfb(des3_ede)", ENCRYPT, sec, + des3_speed_template, DES3_SPEED_VECTORS, + speed_template_24); + test_acipher_speed("cfb(des3_ede)", DECRYPT, sec, + des3_speed_template, DES3_SPEED_VECTORS, + speed_template_24); + test_acipher_speed("ofb(des3_ede)", ENCRYPT, sec, + des3_speed_template, DES3_SPEED_VECTORS, + speed_template_24); + test_acipher_speed("ofb(des3_ede)", DECRYPT, sec, + des3_speed_template, DES3_SPEED_VECTORS, + speed_template_24); break; case 502: @@ -1546,6 +1578,14 @@ static int do_test(int m) speed_template_8); test_acipher_speed("cbc(des)", DECRYPT, sec, NULL, 0, speed_template_8); + test_acipher_speed("cfb(des)", ENCRYPT, sec, NULL, 0, + speed_template_8); + test_acipher_speed("cfb(des)", DECRYPT, sec, NULL, 0, + speed_template_8); + test_acipher_speed("ofb(des)", ENCRYPT, sec, NULL, 0, + speed_template_8); + test_acipher_speed("ofb(des)", DECRYPT, sec, NULL, 0, + speed_template_8); break; case 503: -- GitLab From d1a0eb98e7a8b7e244e31430fdb1a752243e2698 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Tue, 3 Jul 2012 19:16:51 +0300 Subject: [PATCH 2474/5711] crypto: talitos - move talitos structures to header file This patch moves the talitos structure definitions from c file to its header file so that the same can be shared on need basis. Signed-off-by: Sandeep Malik Signed-off-by: Kim Phillips Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 111 --------------------------------------- drivers/crypto/talitos.h | 111 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 111 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 921039e56f87..bb3e63f5596b 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -53,117 +53,6 @@ #include "talitos.h" -#define TALITOS_TIMEOUT 100000 -#define TALITOS_MAX_DATA_LEN 65535 - -#define DESC_TYPE(desc_hdr) ((be32_to_cpu(desc_hdr) >> 3) & 0x1f) -#define PRIMARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 28) & 0xf) -#define SECONDARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 16) & 0xf) - -/* descriptor pointer entry */ -struct talitos_ptr { - __be16 len; /* length */ - u8 j_extent; /* jump to sg link table and/or extent */ - u8 eptr; /* extended address */ - __be32 ptr; /* address */ -}; - -static const struct talitos_ptr zero_entry = { - .len = 0, - .j_extent = 0, - .eptr = 0, - .ptr = 0 -}; - -/* descriptor */ -struct talitos_desc { - __be32 hdr; /* header high bits */ - __be32 hdr_lo; /* header low bits */ - struct talitos_ptr ptr[7]; /* ptr/len pair array */ -}; - -/** - * talitos_request - descriptor submission request - * @desc: descriptor pointer (kernel virtual) - * @dma_desc: descriptor's physical bus address - * @callback: whom to call when descriptor processing is done - * @context: caller context (optional) - */ -struct talitos_request { - struct talitos_desc *desc; - dma_addr_t dma_desc; - void (*callback) (struct device *dev, struct talitos_desc *desc, - void *context, int error); - void *context; -}; - -/* per-channel fifo management */ -struct talitos_channel { - void __iomem *reg; - - /* request fifo */ - struct talitos_request *fifo; - - /* number of requests pending in channel h/w fifo */ - atomic_t submit_count ____cacheline_aligned; - - /* request submission (head) lock */ - spinlock_t head_lock ____cacheline_aligned; - /* index to next free descriptor request */ - int head; - - /* request release (tail) lock */ - spinlock_t tail_lock ____cacheline_aligned; - /* index to next in-progress/done descriptor request */ - int tail; -}; - -struct talitos_private { - struct device *dev; - struct platform_device *ofdev; - void __iomem *reg; - int irq[2]; - - /* SEC global registers lock */ - spinlock_t reg_lock ____cacheline_aligned; - - /* SEC version geometry (from device tree node) */ - unsigned int num_channels; - unsigned int chfifo_len; - unsigned int exec_units; - unsigned int desc_types; - - /* SEC Compatibility info */ - unsigned long features; - - /* - * length of the request fifo - * fifo_len is chfifo_len rounded up to next power of 2 - * so we can use bitwise ops to wrap - */ - unsigned int fifo_len; - - struct talitos_channel *chan; - - /* next channel to be assigned next incoming descriptor */ - atomic_t last_chan ____cacheline_aligned; - - /* request callback tasklet */ - struct tasklet_struct done_task[2]; - - /* list of registered algorithms */ - struct list_head alg_list; - - /* hwrng device */ - struct hwrng rng; -}; - -/* .features flag */ -#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 -#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 -#define TALITOS_FTR_SHA224_HWINIT 0x00000004 -#define TALITOS_FTR_HMAC_OK 0x00000008 - static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr) { talitos_ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr)); diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 3c173954ef29..9835e3abd89f 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -28,6 +28,117 @@ * */ +#define TALITOS_TIMEOUT 100000 +#define TALITOS_MAX_DATA_LEN 65535 + +#define DESC_TYPE(desc_hdr) ((be32_to_cpu(desc_hdr) >> 3) & 0x1f) +#define PRIMARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 28) & 0xf) +#define SECONDARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 16) & 0xf) + +/* descriptor pointer entry */ +struct talitos_ptr { + __be16 len; /* length */ + u8 j_extent; /* jump to sg link table and/or extent */ + u8 eptr; /* extended address */ + __be32 ptr; /* address */ +}; + +static const struct talitos_ptr zero_entry = { + .len = 0, + .j_extent = 0, + .eptr = 0, + .ptr = 0 +}; + +/* descriptor */ +struct talitos_desc { + __be32 hdr; /* header high bits */ + __be32 hdr_lo; /* header low bits */ + struct talitos_ptr ptr[7]; /* ptr/len pair array */ +}; + +/** + * talitos_request - descriptor submission request + * @desc: descriptor pointer (kernel virtual) + * @dma_desc: descriptor's physical bus address + * @callback: whom to call when descriptor processing is done + * @context: caller context (optional) + */ +struct talitos_request { + struct talitos_desc *desc; + dma_addr_t dma_desc; + void (*callback) (struct device *dev, struct talitos_desc *desc, + void *context, int error); + void *context; +}; + +/* per-channel fifo management */ +struct talitos_channel { + void __iomem *reg; + + /* request fifo */ + struct talitos_request *fifo; + + /* number of requests pending in channel h/w fifo */ + atomic_t submit_count ____cacheline_aligned; + + /* request submission (head) lock */ + spinlock_t head_lock ____cacheline_aligned; + /* index to next free descriptor request */ + int head; + + /* request release (tail) lock */ + spinlock_t tail_lock ____cacheline_aligned; + /* index to next in-progress/done descriptor request */ + int tail; +}; + +struct talitos_private { + struct device *dev; + struct platform_device *ofdev; + void __iomem *reg; + int irq[2]; + + /* SEC global registers lock */ + spinlock_t reg_lock ____cacheline_aligned; + + /* SEC version geometry (from device tree node) */ + unsigned int num_channels; + unsigned int chfifo_len; + unsigned int exec_units; + unsigned int desc_types; + + /* SEC Compatibility info */ + unsigned long features; + + /* + * length of the request fifo + * fifo_len is chfifo_len rounded up to next power of 2 + * so we can use bitwise ops to wrap + */ + unsigned int fifo_len; + + struct talitos_channel *chan; + + /* next channel to be assigned next incoming descriptor */ + atomic_t last_chan ____cacheline_aligned; + + /* request callback tasklet */ + struct tasklet_struct done_task[2]; + + /* list of registered algorithms */ + struct list_head alg_list; + + /* hwrng device */ + struct hwrng rng; +}; + +/* .features flag */ +#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 +#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 +#define TALITOS_FTR_SHA224_HWINIT 0x00000004 +#define TALITOS_FTR_HMAC_OK 0x00000008 + /* * TALITOS_xxx_LO addresses point to the low data bits (32-63) of the register */ -- GitLab From 865d506155b117edc7e668ced373030ce7108ce9 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Tue, 3 Jul 2012 19:16:52 +0300 Subject: [PATCH 2475/5711] crypto: talitos - export the talitos_submit function This patch exports the talitos_submit function so that on need basis same can be used by other entities. Signed-off-by: Sandeep Malik Signed-off-by: Kim Phillips Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 11 ++++++----- drivers/crypto/talitos.h | 6 ++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index bb3e63f5596b..2561aea52b62 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -192,11 +192,11 @@ static int init_device(struct device *dev) * callback must check err and feedback in descriptor header * for device processing status. */ -static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, - void (*callback)(struct device *dev, - struct talitos_desc *desc, - void *context, int error), - void *context) +int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, + void (*callback)(struct device *dev, + struct talitos_desc *desc, + void *context, int error), + void *context) { struct talitos_private *priv = dev_get_drvdata(dev); struct talitos_request *request; @@ -237,6 +237,7 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, return -EINPROGRESS; } +EXPORT_SYMBOL(talitos_submit); /* * process what was done, notify callback of error if not diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 9835e3abd89f..41b80f6295ce 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -133,6 +133,12 @@ struct talitos_private { struct hwrng rng; }; +extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, + void (*callback)(struct device *dev, + struct talitos_desc *desc, + void *context, int error), + void *context); + /* .features flag */ #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 #define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 -- GitLab From 357fb60502ede168fa1b76b996298e0045e24b59 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Tue, 3 Jul 2012 19:16:53 +0300 Subject: [PATCH 2476/5711] crypto: talitos - add sha224, sha384 and sha512 to existing AEAD algorithms With this, now all combinations of CBC: AES, 3DES-EDE with HMAC: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 are supported. Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 161 ++++++++++++++++++++++++++++++++++++++- drivers/crypto/talitos.h | 6 ++ 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 2561aea52b62..efff788d2f1d 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -623,7 +623,7 @@ static void talitos_unregister_rng(struct device *dev) * crypto alg */ #define TALITOS_CRA_PRIORITY 3000 -#define TALITOS_MAX_KEY_SIZE 64 +#define TALITOS_MAX_KEY_SIZE 96 #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ #define MD5_BLOCK_SIZE 64 @@ -1956,6 +1956,59 @@ static struct talitos_alg_template driver_algs[] = { DESC_HDR_MODE1_MDEU_PAD | DESC_HDR_MODE1_MDEU_SHA1_HMAC, }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha224),cbc(aes))", + .cra_driver_name = "authenc-hmac-sha224-cbc-aes-talitos", + .cra_blocksize = AES_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_AESU | + DESC_HDR_MODE0_AESU_CBC | + DESC_HDR_SEL1_MDEUA | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEU_SHA224_HMAC, + }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", + .cra_driver_name = "authenc-hmac-sha224-cbc-3des-talitos", + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_DEU | + DESC_HDR_MODE0_DEU_CBC | + DESC_HDR_MODE0_DEU_3DES | + DESC_HDR_SEL1_MDEUA | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEU_SHA224_HMAC, + }, { .type = CRYPTO_ALG_TYPE_AEAD, .alg.crypto = { .cra_name = "authenc(hmac(sha256),cbc(aes))", @@ -2009,6 +2062,112 @@ static struct talitos_alg_template driver_algs[] = { DESC_HDR_MODE1_MDEU_PAD | DESC_HDR_MODE1_MDEU_SHA256_HMAC, }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha384),cbc(aes))", + .cra_driver_name = "authenc-hmac-sha384-cbc-aes-talitos", + .cra_blocksize = AES_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_AESU | + DESC_HDR_MODE0_AESU_CBC | + DESC_HDR_SEL1_MDEUB | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEUB_SHA384_HMAC, + }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha384),cbc(des3_ede))", + .cra_driver_name = "authenc-hmac-sha384-cbc-3des-talitos", + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_DEU | + DESC_HDR_MODE0_DEU_CBC | + DESC_HDR_MODE0_DEU_3DES | + DESC_HDR_SEL1_MDEUB | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEUB_SHA384_HMAC, + }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha512),cbc(aes))", + .cra_driver_name = "authenc-hmac-sha512-cbc-aes-talitos", + .cra_blocksize = AES_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_AESU | + DESC_HDR_MODE0_AESU_CBC | + DESC_HDR_SEL1_MDEUB | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEUB_SHA512_HMAC, + }, + { .type = CRYPTO_ALG_TYPE_AEAD, + .alg.crypto = { + .cra_name = "authenc(hmac(sha512),cbc(des3_ede))", + .cra_driver_name = "authenc-hmac-sha512-cbc-3des-talitos", + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_type = &crypto_aead_type, + .cra_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + } + }, + .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | + DESC_HDR_SEL0_DEU | + DESC_HDR_MODE0_DEU_CBC | + DESC_HDR_MODE0_DEU_3DES | + DESC_HDR_SEL1_MDEUB | + DESC_HDR_MODE1_MDEU_INIT | + DESC_HDR_MODE1_MDEU_PAD | + DESC_HDR_MODE1_MDEUB_SHA512_HMAC, + }, { .type = CRYPTO_ALG_TYPE_AEAD, .alg.crypto = { .cra_name = "authenc(hmac(md5),cbc(aes))", diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 41b80f6295ce..61a14054aa39 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -326,6 +326,12 @@ extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, DESC_HDR_MODE1_MDEU_HMAC) #define DESC_HDR_MODE1_MDEU_SHA1_HMAC (DESC_HDR_MODE1_MDEU_SHA1 | \ DESC_HDR_MODE1_MDEU_HMAC) +#define DESC_HDR_MODE1_MDEU_SHA224_HMAC (DESC_HDR_MODE1_MDEU_SHA224 | \ + DESC_HDR_MODE1_MDEU_HMAC) +#define DESC_HDR_MODE1_MDEUB_SHA384_HMAC (DESC_HDR_MODE1_MDEUB_SHA384 | \ + DESC_HDR_MODE1_MDEU_HMAC) +#define DESC_HDR_MODE1_MDEUB_SHA512_HMAC (DESC_HDR_MODE1_MDEUB_SHA512 | \ + DESC_HDR_MODE1_MDEU_HMAC) /* direction of overall data flow (DIR) */ #define DESC_HDR_DIR_INBOUND cpu_to_be32(0x00000002) -- GitLab From e46e9a46386bca8e80a6467b5c643dc494861896 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Tue, 3 Jul 2012 19:16:54 +0300 Subject: [PATCH 2477/5711] crypto: testmgr - add aead cbc aes hmac sha1,256,512 test vectors Test vectors were generated starting from existing CBC(AES) test vectors (RFC3602, NIST SP800-38A) and adding HMAC(SHA*) computed with Crypto++ and double-checked with HashCalc. Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu --- crypto/testmgr.c | 36 ++ crypto/testmgr.h | 834 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 870 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4308a11f129c..a2ca7431760a 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1720,6 +1720,42 @@ static const struct alg_test_desc alg_test_descs[] = { .count = ANSI_CPRNG_AES_TEST_VECTORS } } + }, { + .alg = "authenc(hmac(sha1),cbc(aes))", + .test = alg_test_aead, + .fips_allowed = 1, + .suite = { + .aead = { + .enc = { + .vecs = hmac_sha1_aes_cbc_enc_tv_template, + .count = HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS + } + } + } + }, { + .alg = "authenc(hmac(sha256),cbc(aes))", + .test = alg_test_aead, + .fips_allowed = 1, + .suite = { + .aead = { + .enc = { + .vecs = hmac_sha256_aes_cbc_enc_tv_template, + .count = HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS + } + } + } + }, { + .alg = "authenc(hmac(sha512),cbc(aes))", + .test = alg_test_aead, + .fips_allowed = 1, + .suite = { + .aead = { + .enc = { + .vecs = hmac_sha512_aes_cbc_enc_tv_template, + .count = HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS + } + } + } }, { .alg = "cbc(aes)", .test = alg_test_skcipher, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 4d84fe48df08..f8179e0344ed 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -6975,6 +6975,9 @@ static struct cipher_testvec cast6_dec_tv_template[] = { #define AES_DEC_TEST_VECTORS 3 #define AES_CBC_ENC_TEST_VECTORS 4 #define AES_CBC_DEC_TEST_VECTORS 4 +#define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7 +#define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7 +#define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7 #define AES_LRW_ENC_TEST_VECTORS 8 #define AES_LRW_DEC_TEST_VECTORS 8 #define AES_XTS_ENC_TEST_VECTORS 5 @@ -7232,6 +7235,837 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = { }, }; +static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_template[] = { + { /* RFC 3602 Case 1 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 8 + 20 + 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "Single block msg", + .ilen = 16, + .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a" + "\x1b\x13\xcb\xaf\x89\x5e\xe1\x2c" + "\x13\xc5\x2e\xa3\xcc\xed\xdc\xb5" + "\x03\x71\xa2\x06", + .rlen = 16 + 20, + }, { /* RFC 3602 Case 2 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 20 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xad\x9b\x4c\x5c\x85\xe1\xda\xae" + "\xee\x81\x4e\xd7\xdb\x74\xcf\x58" + "\x65\x39\xf8\xde", + .rlen = 32 + 20, + }, { /* RFC 3602 Case 3 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55" + "\x6c\x3e\xa0\x47\x76\x30\xce\x21" + "\xa2\xce\x33\x4a\xa7\x46\xc2\xcd", + .klen = 8 + 20 + 16, + .iv = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb" + "\xd9\xcd\x27\xd8\x25\x68\x2c\x81", + .input = "This is a 48-byte message (exactly 3 AES blocks)", + .ilen = 48, + .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53" + "\xd4\x93\x66\x5d\x33\xf0\xe8\x86" + "\x2d\xea\x54\xcd\xb2\x93\xab\xc7" + "\x50\x69\x39\x27\x67\x72\xf8\xd5" + "\x02\x1c\x19\x21\x6b\xad\x52\x5c" + "\x85\x79\x69\x5d\x83\xba\x26\x84" + "\xc2\xec\x0c\xf8\x7f\x05\xba\xca" + "\xff\xee\x4c\xd0\x93\xe6\x36\x7f" + "\x8d\x62\xf2\x1e", + .rlen = 48 + 20, + }, { /* RFC 3602 Case 4 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55" + "\x56\xe4\x7a\x38\xc5\x59\x89\x74" + "\xbc\x46\x90\x3d\xba\x29\x03\x49", + .klen = 8 + 20 + 16, + .iv = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c" + "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9", + .input = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", + .ilen = 64, + .result = "\xc3\x0e\x32\xff\xed\xc0\x77\x4e" + "\x6a\xff\x6a\xf0\x86\x9f\x71\xaa" + "\x0f\x3a\xf0\x7a\x9a\x31\xa9\xc6" + "\x84\xdb\x20\x7e\xb0\xef\x8e\x4e" + "\x35\x90\x7a\xa6\x32\xc3\xff\xdf" + "\x86\x8b\xb7\xb2\x9d\x3d\x46\xad" + "\x83\xce\x9f\x9a\x10\x2e\xe9\x9d" + "\x49\xa5\x3e\x87\xf4\xc3\xda\x55" + "\x1c\x45\x57\xa9\x56\xcb\xa9\x2d" + "\x18\xac\xf1\xc7\x5d\xd1\xcd\x0d" + "\x1d\xbe\xc6\xe9", + .rlen = 64 + 20, + }, { /* RFC 3602 Case 5 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55" + "\x90\xd3\x82\xb4\x10\xee\xba\x7a" + "\xd9\x38\xc4\x6c\xec\x1a\x82\xbf", + .klen = 8 + 20 + 16, + .iv = "\xe9\x6e\x8c\x08\xab\x46\x57\x63" + "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93", + .assoc = "\x00\x00\x43\x21\x00\x00\x00\x01", + .alen = 8, + .input = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00" + "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0e\x01", + .ilen = 80, + .result = "\xf6\x63\xc2\x5d\x32\x5c\x18\xc6" + "\xa9\x45\x3e\x19\x4e\x12\x08\x49" + "\xa4\x87\x0b\x66\xcc\x6b\x99\x65" + "\x33\x00\x13\xb4\x89\x8d\xc8\x56" + "\xa4\x69\x9e\x52\x3a\x55\xdb\x08" + "\x0b\x59\xec\x3a\x8e\x4b\x7e\x52" + "\x77\x5b\x07\xd1\xdb\x34\xed\x9c" + "\x53\x8a\xb5\x0c\x55\x1b\x87\x4a" + "\xa2\x69\xad\xd0\x47\xad\x2d\x59" + "\x13\xac\x19\xb7\xcf\xba\xd4\xa6" + "\x58\xc6\x84\x75\xe4\xe9\x6b\x0c" + "\xe1\xc5\x0b\x73\x4d\x82\x55\xa8" + "\x85\xe1\x59\xf7", + .rlen = 80 + 20, + }, { /* NIST SP800-38A F.2.3 CBC-AES192.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x18" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55" + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 8 + 20 + 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd" + "\x73\xe3\x19\x3f\x8b\xc9\xc6\xf4" + "\x5a\xf1\x5b\xa8\x98\x07\xc5\x36" + "\x47\x4c\xfc\x36", + .rlen = 64 + 20, + }, { /* NIST SP800-38A F.2.5 CBC-AES256.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x20" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55" + "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 8 + 20 + 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b" + "\xa3\xe8\x9b\x17\xe3\xf4\x7f\xde" + "\x1b\x9f\xc6\x81\x26\x43\x4a\x87" + "\x51\xee\xd6\x4e", + .rlen = 64 + 20, + }, +}; + +static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_template[] = { + { /* RFC 3602 Case 1 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 8 + 32 + 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "Single block msg", + .ilen = 16, + .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a" + "\xcc\xde\x2d\x6a\xae\xf1\x0b\xcc" + "\x38\x06\x38\x51\xb4\xb8\xf3\x5b" + "\x5c\x34\xa6\xa3\x6e\x0b\x05\xe5" + "\x6a\x6d\x44\xaa\x26\xa8\x44\xa5", + .rlen = 16 + 32, + }, { /* RFC 3602 Case 2 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 32 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xf5\x33\x53\xf3\x68\x85\x2a\x99" + "\x0e\x06\x58\x8f\xba\xf6\x06\xda" + "\x49\x69\x0d\x5b\xd4\x36\x06\x62" + "\x35\x5e\x54\x58\x53\x4d\xdf\xbf", + .rlen = 32 + 32, + }, { /* RFC 3602 Case 3 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x6c\x3e\xa0\x47\x76\x30\xce\x21" + "\xa2\xce\x33\x4a\xa7\x46\xc2\xcd", + .klen = 8 + 32 + 16, + .iv = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb" + "\xd9\xcd\x27\xd8\x25\x68\x2c\x81", + .input = "This is a 48-byte message (exactly 3 AES blocks)", + .ilen = 48, + .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53" + "\xd4\x93\x66\x5d\x33\xf0\xe8\x86" + "\x2d\xea\x54\xcd\xb2\x93\xab\xc7" + "\x50\x69\x39\x27\x67\x72\xf8\xd5" + "\x02\x1c\x19\x21\x6b\xad\x52\x5c" + "\x85\x79\x69\x5d\x83\xba\x26\x84" + "\x68\xb9\x3e\x90\x38\xa0\x88\x01" + "\xe7\xc6\xce\x10\x31\x2f\x9b\x1d" + "\x24\x78\xfb\xbe\x02\xe0\x4f\x40" + "\x10\xbd\xaa\xc6\xa7\x79\xe0\x1a", + .rlen = 48 + 32, + }, { /* RFC 3602 Case 4 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x56\xe4\x7a\x38\xc5\x59\x89\x74" + "\xbc\x46\x90\x3d\xba\x29\x03\x49", + .klen = 8 + 32 + 16, + .iv = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c" + "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9", + .input = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", + .ilen = 64, + .result = "\xc3\x0e\x32\xff\xed\xc0\x77\x4e" + "\x6a\xff\x6a\xf0\x86\x9f\x71\xaa" + "\x0f\x3a\xf0\x7a\x9a\x31\xa9\xc6" + "\x84\xdb\x20\x7e\xb0\xef\x8e\x4e" + "\x35\x90\x7a\xa6\x32\xc3\xff\xdf" + "\x86\x8b\xb7\xb2\x9d\x3d\x46\xad" + "\x83\xce\x9f\x9a\x10\x2e\xe9\x9d" + "\x49\xa5\x3e\x87\xf4\xc3\xda\x55" + "\x7a\x1b\xd4\x3c\xdb\x17\x95\xe2" + "\xe0\x93\xec\xc9\x9f\xf7\xce\xd8" + "\x3f\x54\xe2\x49\x39\xe3\x71\x25" + "\x2b\x6c\xe9\x5d\xec\xec\x2b\x64", + .rlen = 64 + 32, + }, { /* RFC 3602 Case 5 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x90\xd3\x82\xb4\x10\xee\xba\x7a" + "\xd9\x38\xc4\x6c\xec\x1a\x82\xbf", + .klen = 8 + 32 + 16, + .iv = "\xe9\x6e\x8c\x08\xab\x46\x57\x63" + "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93", + .assoc = "\x00\x00\x43\x21\x00\x00\x00\x01", + .alen = 8, + .input = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00" + "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0e\x01", + .ilen = 80, + .result = "\xf6\x63\xc2\x5d\x32\x5c\x18\xc6" + "\xa9\x45\x3e\x19\x4e\x12\x08\x49" + "\xa4\x87\x0b\x66\xcc\x6b\x99\x65" + "\x33\x00\x13\xb4\x89\x8d\xc8\x56" + "\xa4\x69\x9e\x52\x3a\x55\xdb\x08" + "\x0b\x59\xec\x3a\x8e\x4b\x7e\x52" + "\x77\x5b\x07\xd1\xdb\x34\xed\x9c" + "\x53\x8a\xb5\x0c\x55\x1b\x87\x4a" + "\xa2\x69\xad\xd0\x47\xad\x2d\x59" + "\x13\xac\x19\xb7\xcf\xba\xd4\xa6" + "\xbb\xd4\x0f\xbe\xa3\x3b\x4c\xb8" + "\x3a\xd2\xe1\x03\x86\xa5\x59\xb7" + "\x73\xc3\x46\x20\x2c\xb1\xef\x68" + "\xbb\x8a\x32\x7e\x12\x8c\x69\xcf", + .rlen = 80 + 32, + }, { /* NIST SP800-38A F.2.3 CBC-AES192.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x18" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 8 + 32 + 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd" + "\x2f\xee\x5f\xdb\x66\xfe\x79\x09" + "\x61\x81\x31\xea\x5b\x3d\x8e\xfb" + "\xca\x71\x85\x93\xf7\x85\x55\x8b" + "\x7a\xe4\x94\xca\x8b\xba\x19\x33", + .rlen = 64 + 32, + }, { /* NIST SP800-38A F.2.5 CBC-AES256.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x20" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 8 + 32 + 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b" + "\x24\x29\xed\xc2\x31\x49\xdb\xb1" + "\x8f\x74\xbd\x17\x92\x03\xbe\x8f" + "\xf3\x61\xde\x1c\xe9\xdb\xcd\xd0" + "\xcc\xce\xe9\x85\x57\xcf\x6f\x5f", + .rlen = 64 + 32, + }, +}; + +static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_template[] = { + { /* RFC 3602 Case 1 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 8 + 64 + 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "Single block msg", + .ilen = 16, + .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a" + "\x3f\xdc\xad\x90\x03\x63\x5e\x68" + "\xc3\x13\xdd\xa4\x5c\x4d\x54\xa7" + "\x19\x6e\x03\x75\x2b\xa1\x62\xce" + "\xe0\xc6\x96\x75\xb2\x14\xca\x96" + "\xec\xbd\x50\x08\x07\x64\x1a\x49" + "\xe8\x9a\x7c\x06\x3d\xcb\xff\xb2" + "\xfa\x20\x89\xdd\x9c\xac\x9e\x16" + "\x18\x8a\xa0\x6d\x01\x6c\xa3\x3a", + .rlen = 16 + 64, + }, { /* RFC 3602 Case 2 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 64 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xda\xb2\x0c\xb2\x26\xc4\xd5\xef" + "\x60\x38\xa4\x5e\x9a\x8c\x1b\x41" + "\x03\x9f\xc4\x64\x7f\x01\x42\x9b" + "\x0e\x1b\xea\xef\xbc\x88\x19\x5e" + "\x31\x7e\xc2\x95\xfc\x09\x32\x0a" + "\x46\x32\x7c\x41\x9c\x59\x3e\xe9" + "\x8f\x9f\xd4\x31\xd6\x22\xbd\xf8" + "\xf7\x0a\x94\xe5\xa9\xc3\xf6\x9d", + .rlen = 32 + 64, + }, { /* RFC 3602 Case 3 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x33\x44\x55\x66\x77\x88\x99\xaa" + "\xbb\xcc\xdd\xee\xff\x11\x22\x33" + "\x44\x55\x66\x77\x88\x99\xaa\xbb" + "\xcc\xdd\xee\xff\x11\x22\x33\x44" + "\x6c\x3e\xa0\x47\x76\x30\xce\x21" + "\xa2\xce\x33\x4a\xa7\x46\xc2\xcd", + .klen = 8 + 64 + 16, + .iv = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb" + "\xd9\xcd\x27\xd8\x25\x68\x2c\x81", + .input = "This is a 48-byte message (exactly 3 AES blocks)", + .ilen = 48, + .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53" + "\xd4\x93\x66\x5d\x33\xf0\xe8\x86" + "\x2d\xea\x54\xcd\xb2\x93\xab\xc7" + "\x50\x69\x39\x27\x67\x72\xf8\xd5" + "\x02\x1c\x19\x21\x6b\xad\x52\x5c" + "\x85\x79\x69\x5d\x83\xba\x26\x84" + "\x64\x19\x17\x5b\x57\xe0\x21\x0f" + "\xca\xdb\xa1\x26\x38\x14\xa2\x69" + "\xdb\x54\x67\x80\xc0\x54\xe0\xfd" + "\x3e\x91\xe7\x91\x7f\x13\x38\x44" + "\xb7\xb1\xd6\xc8\x7d\x48\x8d\x41" + "\x08\xea\x29\x6c\x74\x67\x3f\xb0" + "\xac\x7f\x5c\x1d\xf5\xee\x22\x66" + "\x27\xa6\xb6\x13\xba\xba\xf0\xc2", + .rlen = 48 + 64, + }, { /* RFC 3602 Case 4 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x33\x44\x55\x66\x77\x88\x99\xaa" + "\xbb\xcc\xdd\xee\xff\x11\x22\x33" + "\x44\x55\x66\x77\x88\x99\xaa\xbb" + "\xcc\xdd\xee\xff\x11\x22\x33\x44" + "\x56\xe4\x7a\x38\xc5\x59\x89\x74" + "\xbc\x46\x90\x3d\xba\x29\x03\x49", + .klen = 8 + 64 + 16, + .iv = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c" + "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9", + .input = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", + .ilen = 64, + .result = "\xc3\x0e\x32\xff\xed\xc0\x77\x4e" + "\x6a\xff\x6a\xf0\x86\x9f\x71\xaa" + "\x0f\x3a\xf0\x7a\x9a\x31\xa9\xc6" + "\x84\xdb\x20\x7e\xb0\xef\x8e\x4e" + "\x35\x90\x7a\xa6\x32\xc3\xff\xdf" + "\x86\x8b\xb7\xb2\x9d\x3d\x46\xad" + "\x83\xce\x9f\x9a\x10\x2e\xe9\x9d" + "\x49\xa5\x3e\x87\xf4\xc3\xda\x55" + "\x82\xcd\x42\x28\x21\x20\x15\xcc" + "\xb7\xb2\x48\x40\xc7\x64\x41\x3a" + "\x61\x32\x82\x85\xcf\x27\xed\xb4" + "\xe4\x68\xa2\xf5\x79\x26\x27\xb2" + "\x51\x67\x6a\xc4\xf0\x66\x55\x50" + "\xbc\x6f\xed\xd5\x8d\xde\x23\x7c" + "\x62\x98\x14\xd7\x2f\x37\x8d\xdf" + "\xf4\x33\x80\xeb\x8e\xb4\xa4\xda", + .rlen = 64 + 64, + }, { /* RFC 3602 Case 5 */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x33\x44\x55\x66\x77\x88\x99\xaa" + "\xbb\xcc\xdd\xee\xff\x11\x22\x33" + "\x44\x55\x66\x77\x88\x99\xaa\xbb" + "\xcc\xdd\xee\xff\x11\x22\x33\x44" + "\x90\xd3\x82\xb4\x10\xee\xba\x7a" + "\xd9\x38\xc4\x6c\xec\x1a\x82\xbf", + .klen = 8 + 64 + 16, + .iv = "\xe9\x6e\x8c\x08\xab\x46\x57\x63" + "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93", + .assoc = "\x00\x00\x43\x21\x00\x00\x00\x01", + .alen = 8, + .input = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00" + "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0e\x01", + .ilen = 80, + .result = "\xf6\x63\xc2\x5d\x32\x5c\x18\xc6" + "\xa9\x45\x3e\x19\x4e\x12\x08\x49" + "\xa4\x87\x0b\x66\xcc\x6b\x99\x65" + "\x33\x00\x13\xb4\x89\x8d\xc8\x56" + "\xa4\x69\x9e\x52\x3a\x55\xdb\x08" + "\x0b\x59\xec\x3a\x8e\x4b\x7e\x52" + "\x77\x5b\x07\xd1\xdb\x34\xed\x9c" + "\x53\x8a\xb5\x0c\x55\x1b\x87\x4a" + "\xa2\x69\xad\xd0\x47\xad\x2d\x59" + "\x13\xac\x19\xb7\xcf\xba\xd4\xa6" + "\x74\x84\x94\xe2\xd7\x7a\xf9\xbf" + "\x00\x8a\xa2\xd5\xb7\xf3\x60\xcf" + "\xa0\x47\xdf\x4e\x09\xf4\xb1\x7f" + "\x14\xd9\x3d\x53\x8e\x12\xb3\x00" + "\x4c\x0a\x4e\x32\x40\x43\x88\xce" + "\x92\x26\xc1\x76\x20\x11\xeb\xba" + "\x62\x4f\x9a\x62\x25\xc3\x75\x80" + "\xb7\x0a\x17\xf5\xd7\x94\xb4\x14", + .rlen = 80 + 64, + }, { /* NIST SP800-38A F.2.3 CBC-AES192.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x18" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x33\x44\x55\x66\x77\x88\x99\xaa" + "\xbb\xcc\xdd\xee\xff\x11\x22\x33" + "\x44\x55\x66\x77\x88\x99\xaa\xbb" + "\xcc\xdd\xee\xff\x11\x22\x33\x44" + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 8 + 64 + 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd" + "\x77\x4b\x69\x9d\x3a\x0d\xb4\x99" + "\x8f\xc6\x8e\x0e\x72\x58\xe3\x56" + "\xbb\x21\xd2\x7d\x93\x11\x17\x91" + "\xc4\x83\xfd\x0a\xea\x71\xfe\x77" + "\xae\x6f\x0a\xa5\xf0\xcf\xe1\x35" + "\xba\x03\xd5\x32\xfa\x5f\x41\x58" + "\x8d\x43\x98\xa7\x94\x16\x07\x02" + "\x0f\xb6\x81\x50\x28\x95\x2e\x75", + .rlen = 64 + 64, + }, { /* NIST SP800-38A F.2.5 CBC-AES256.Encrypt */ +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x20" /* enc key length */ + "\x11\x22\x33\x44\x55\x66\x77\x88" + "\x99\xaa\xbb\xcc\xdd\xee\xff\x11" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xaa\xbb\xcc\xdd\xee\xff\x11\x22" + "\x33\x44\x55\x66\x77\x88\x99\xaa" + "\xbb\xcc\xdd\xee\xff\x11\x22\x33" + "\x44\x55\x66\x77\x88\x99\xaa\xbb" + "\xcc\xdd\xee\xff\x11\x22\x33\x44" + "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 8 + 64 + 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b" + "\xb2\x27\x69\x7f\x45\x64\x79\x2b" + "\xb7\xb8\x4c\xd4\x75\x94\x68\x40" + "\x2a\xea\x91\xc7\x3f\x7c\xed\x7b" + "\x95\x2c\x9b\xa8\xf5\xe5\x52\x8d" + "\x6b\xe1\xae\xf1\x74\xfa\x0d\x0c" + "\xe3\x8d\x64\xc3\x8d\xff\x7c\x8c" + "\xdb\xbf\xa0\xb4\x01\xa2\xa8\xa2" + "\x2c\xb1\x62\x2c\x10\xca\xf1\x21", + .rlen = 64 + 64, + }, +}; + static struct cipher_testvec aes_lrw_enc_tv_template[] = { /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ { /* LRW-32-AES 1 */ -- GitLab From a43478863b16cb0986fd2ec9d1f1b9ebaaec5922 Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Thu, 5 Jul 2012 20:43:58 +0200 Subject: [PATCH 2478/5711] crypto: twofish-avx - remove useless instruction The register %rdx is written, but never read till the end of the encryption routine. Therefore let's delete the useless instruction. Signed-off-by: Johannes Goetzfried Signed-off-by: Herbert Xu --- arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S index fc31b89ba4c3..35f45574390d 100644 --- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S @@ -243,7 +243,6 @@ __twofish_enc_blk_8way: popq %rbx; leaq (4*4*4)(%rsi), %rax; - leaq (4*4*4)(%rax), %rdx; testb %cl, %cl; jnz __enc_xor8; -- GitLab From f96985e3b3cfcd2d21faca79863fb34533d575aa Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 11 Jul 2012 09:41:23 +0300 Subject: [PATCH 2479/5711] ASoC: STA529: fix an error message GCC complains that "ret" is uninitialized here. Signed-off-by: Dan Carpenter Acked-By: Rajeev Kumar Signed-off-by: Mark Brown --- sound/soc/codecs/sta529.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index a9f34c736bfa..0c225cd569d2 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -397,8 +397,9 @@ static __devinit int sta529_i2c_probe(struct i2c_client *i2c, sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); if (IS_ERR(sta529->regmap)) { + ret = PTR_ERR(sta529->regmap); dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); - return PTR_ERR(sta529->regmap); + return ret; } i2c_set_clientdata(i2c, sta529); -- GitLab From 5c6af635fd77251b753cb1c07a6a6f306ba4e287 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Jul 2012 19:09:41 +0100 Subject: [PATCH 2480/5711] ASoC: wm5110: Add audio CODEC driver The WM5110 is a highly integrated low power audio subsystem for smartphones, tablets and other portable audio devices. It combines an advanced DSP feature set with a flexible, high performance audio hub CODEC. This patch adds the audio CODEC driver for the device. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm5110.c | 950 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm5110.h | 21 + 4 files changed, 979 insertions(+) create mode 100644 sound/soc/codecs/wm5110.c create mode 100644 sound/soc/codecs/wm5110.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index bbcb03863503..9f8e8594aeb9 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM2200 if I2C select SND_SOC_WM5100 if I2C select SND_SOC_WM5102 if MFD_WM5102 + select SND_SOC_WM5110 if MFD_WM5110 select SND_SOC_WM8350 if MFD_WM8350 select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI @@ -134,7 +135,9 @@ config SND_SOC_88PM860X config SND_SOC_ARIZONA tristate default y if SND_SOC_WM5102=y + default y if SND_SOC_WM5110=y default m if SND_SOC_WM5102=m + default m if SND_SOC_WM5110=m config SND_SOC_WM_HUBS tristate @@ -338,6 +341,9 @@ config SND_SOC_WM5100 config SND_SOC_WM5102 tristate +config SND_SOC_WM5110 + tristate + config SND_SOC_WM8350 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 8da3d22a7d1c..34148bb59c68 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -66,6 +66,7 @@ snd-soc-wm2000-objs := wm2000.o snd-soc-wm2200-objs := wm2200.o snd-soc-wm5100-objs := wm5100.o wm5100-tables.o snd-soc-wm5102-objs := wm5102.o +snd-soc-wm5110-objs := wm5110.o snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o @@ -181,6 +182,7 @@ obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o obj-$(CONFIG_SND_SOC_WM5102) += snd-soc-wm5102.o +obj-$(CONFIG_SND_SOC_WM5110) += snd-soc-wm5110.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c new file mode 100644 index 000000000000..8033f7065189 --- /dev/null +++ b/sound/soc/codecs/wm5110.c @@ -0,0 +1,950 @@ +/* + * wm5110.c -- WM5110 ALSA SoC Audio driver + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown + * + * 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 +#include + +#include "arizona.h" +#include "wm5110.h" + +struct wm5110_priv { + struct arizona_priv core; + struct arizona_fll fll[2]; +}; + +static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); +static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); + +static const struct snd_kcontrol_new wm5110_snd_controls[] = { +SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, + ARIZONA_IN1_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, + ARIZONA_IN2_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, + ARIZONA_IN3_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL, + ARIZONA_IN4_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL, + ARIZONA_IN1R_CONTROL, + ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, + ARIZONA_IN2R_CONTROL, + ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL, + ARIZONA_IN3R_CONTROL, + ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), + +SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L, + ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L, + ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT, + 0xbf, 0, digital_tlv), + +ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, + ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, + ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), + +ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), + +SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), + +ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, + ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), + +ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, + ARIZONA_OUT1_OSR_SHIFT, 1, 0), +SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, + ARIZONA_OUT2_OSR_SHIFT, 1, 0), +SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, + ARIZONA_OUT3_OSR_SHIFT, 1, 0), +SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, + ARIZONA_OUT4_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, + ARIZONA_OUT5_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L, + ARIZONA_OUT6_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), +SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L, + ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, + 0xbf, 0, digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L, + ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT, + 0xbf, 0, digital_tlv), + +SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, + ARIZONA_OUTPUT_PATH_CONFIG_1R, + ARIZONA_OUT1L_PGA_VOL_SHIFT, + 0x34, 0x40, 0, ana_tlv), +SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, + ARIZONA_OUTPUT_PATH_CONFIG_2R, + ARIZONA_OUT2L_PGA_VOL_SHIFT, + 0x34, 0x40, 0, ana_tlv), +SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, + ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, + ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), +SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, + ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), + +ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), + +ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), + +ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), +}; + +ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDAT2L, ARIZONA_OUT6LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(SPKDAT2R, ARIZONA_OUT6RMIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); + +ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); + +static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, + ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1L"), +SND_SOC_DAPM_INPUT("IN1R"), +SND_SOC_DAPM_INPUT("IN2L"), +SND_SOC_DAPM_INPUT("IN2R"), +SND_SOC_DAPM_INPUT("IN3L"), +SND_SOC_DAPM_INPUT("IN3R"), +SND_SOC_DAPM_INPUT("IN4L"), +SND_SOC_DAPM_INPUT("IN4R"), + +SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, + 0, NULL, 0, arizona_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, + ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, + ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, + ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, + ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT6L", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT6L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT6R", ARIZONA_OUTPUT_ENABLES_1, + ARIZONA_OUT6R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), +ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), +ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), +ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), + +ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), +ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), +ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), +ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), +ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), +ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), +ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +ARIZONA_MIXER_WIDGETS(Mic, "Mic"), +ARIZONA_MIXER_WIDGETS(Noise, "Noise"), + +ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), +ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), + +ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), +ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), +ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), +ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), +ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), +ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), +ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), +ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), + +ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), +ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), +ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), + +ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), + +ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), +ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), +ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), +ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), + +SND_SOC_DAPM_OUTPUT("HPOUT1L"), +SND_SOC_DAPM_OUTPUT("HPOUT1R"), +SND_SOC_DAPM_OUTPUT("HPOUT2L"), +SND_SOC_DAPM_OUTPUT("HPOUT2R"), +SND_SOC_DAPM_OUTPUT("EPOUTN"), +SND_SOC_DAPM_OUTPUT("EPOUTP"), +SND_SOC_DAPM_OUTPUT("SPKOUTLN"), +SND_SOC_DAPM_OUTPUT("SPKOUTLP"), +SND_SOC_DAPM_OUTPUT("SPKOUTRN"), +SND_SOC_DAPM_OUTPUT("SPKOUTRP"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPKDAT2L"), +SND_SOC_DAPM_OUTPUT("SPKDAT2R"), +}; + +#define ARIZONA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "IN1L", "IN1L PGA" }, \ + { name, "IN1R", "IN1R PGA" }, \ + { name, "IN2L", "IN2L PGA" }, \ + { name, "IN2R", "IN2R PGA" }, \ + { name, "IN3L", "IN3L PGA" }, \ + { name, "IN3R", "IN3R PGA" }, \ + { name, "IN4L", "IN4L PGA" }, \ + { name, "IN4R", "IN4R PGA" }, \ + { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF1RX7", "AIF1RX7" }, \ + { name, "AIF1RX8", "AIF1RX8" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ASRC1L", "ASRC1L" }, \ + { name, "ASRC1R", "ASRC1R" }, \ + { name, "ASRC2L", "ASRC2L" }, \ + { name, "ASRC2R", "ASRC2R" } + +static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { + { "AIF2 Capture", NULL, "DBVDD2" }, + { "AIF2 Playback", NULL, "DBVDD2" }, + + { "AIF3 Capture", NULL, "DBVDD3" }, + { "AIF3 Playback", NULL, "DBVDD3" }, + + { "OUT1L", NULL, "CPVDD" }, + { "OUT1R", NULL, "CPVDD" }, + { "OUT2L", NULL, "CPVDD" }, + { "OUT2R", NULL, "CPVDD" }, + { "OUT3L", NULL, "CPVDD" }, + + { "OUT4L", NULL, "SPKVDDL" }, + { "OUT4R", NULL, "SPKVDDR" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3L", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT4R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + { "OUT6L", NULL, "SYSCLK" }, + { "OUT6R", NULL, "SYSCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + { "MICBIAS3", NULL, "MICVDD" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "Mic Mute Mixer", NULL, "Noise Mixer" }, + { "Mic Mute Mixer", NULL, "Mic Mixer" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + { "AIF1 Capture", NULL, "AIF1TX7" }, + { "AIF1 Capture", NULL, "AIF1TX8" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + { "AIF1RX7", NULL, "AIF1 Playback" }, + { "AIF1RX8", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), + ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), + ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), + + ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), + ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), + ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"), + ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"), + + ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), + ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), + + ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + + ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), + ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), + ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), + ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), + + ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), + ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), + ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), + ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), + + ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), + ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), + ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), + ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), + + ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), + ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), + ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), + ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), + + { "HPOUT1L", NULL, "OUT1L" }, + { "HPOUT1R", NULL, "OUT1R" }, + + { "HPOUT2L", NULL, "OUT2L" }, + { "HPOUT2R", NULL, "OUT2R" }, + + { "EPOUTN", NULL, "OUT3L" }, + { "EPOUTP", NULL, "OUT3L" }, + + { "SPKOUTLN", NULL, "OUT4L" }, + { "SPKOUTLP", NULL, "OUT4L" }, + + { "SPKOUTRN", NULL, "OUT4R" }, + { "SPKOUTRP", NULL, "OUT4R" }, + + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + { "SPKDAT2L", NULL, "OUT6L" }, + { "SPKDAT2R", NULL, "OUT6R" }, +}; + +static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, + unsigned int Fref, unsigned int Fout) +{ + struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec); + + switch (fll_id) { + case WM5110_FLL1: + return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); + case WM5110_FLL2: + return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); + default: + return -EINVAL; + } +} + +#define WM5110_RATES SNDRV_PCM_RATE_8000_192000 + +#define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver wm5110_dai[] = { + { + .name = "wm5110-aif1", + .id = 1, + .base = ARIZONA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + }, + { + .name = "wm5110-aif2", + .id = 2, + .base = ARIZONA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + }, + { + .name = "wm5110-aif3", + .id = 3, + .base = ARIZONA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .ops = &arizona_dai_ops, + .symmetric_rates = 1, + }, +}; + +static int wm5110_codec_probe(struct snd_soc_codec *codec) +{ + struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); + + codec->control_data = priv->core.arizona->regmap; + return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); +} + +#define WM5110_DIG_VU 0x0200 + +static unsigned int wm5110_digital_vu[] = { + ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_ADC_DIGITAL_VOLUME_1R, + ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_ADC_DIGITAL_VOLUME_2R, + ARIZONA_ADC_DIGITAL_VOLUME_3L, + ARIZONA_ADC_DIGITAL_VOLUME_3R, + + ARIZONA_DAC_DIGITAL_VOLUME_1L, + ARIZONA_DAC_DIGITAL_VOLUME_1R, + ARIZONA_DAC_DIGITAL_VOLUME_2L, + ARIZONA_DAC_DIGITAL_VOLUME_2R, + ARIZONA_DAC_DIGITAL_VOLUME_3L, + ARIZONA_DAC_DIGITAL_VOLUME_3R, + ARIZONA_DAC_DIGITAL_VOLUME_4L, + ARIZONA_DAC_DIGITAL_VOLUME_4R, + ARIZONA_DAC_DIGITAL_VOLUME_5L, + ARIZONA_DAC_DIGITAL_VOLUME_5R, +}; + +static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { + .probe = wm5110_codec_probe, + + .idle_bias_off = true, + + .set_sysclk = arizona_set_sysclk, + .set_pll = wm5110_set_fll, + + .controls = wm5110_snd_controls, + .num_controls = ARRAY_SIZE(wm5110_snd_controls), + .dapm_widgets = wm5110_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), + .dapm_routes = wm5110_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), +}; + +static int __devinit wm5110_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct wm5110_priv *wm5110; + int i; + + wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), + GFP_KERNEL); + if (wm5110 == NULL) + return -ENOMEM; + platform_set_drvdata(pdev, wm5110); + + wm5110->core.arizona = arizona; + + for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) + wm5110->fll[i].vco_mult = 3; + + arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, + ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, + &wm5110->fll[0]); + arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, + ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, + &wm5110->fll[1]); + + for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) + arizona_init_dai(&wm5110->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++) + regmap_update_bits(arizona->regmap, wm5110_digital_vu[i], + WM5110_DIG_VU, WM5110_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110, + wm5110_dai, ARRAY_SIZE(wm5110_dai)); +} + +static int __devexit wm5110_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static struct platform_driver wm5110_codec_driver = { + .driver = { + .name = "wm5110-codec", + .owner = THIS_MODULE, + }, + .probe = wm5110_probe, + .remove = __devexit_p(wm5110_remove), +}; + +module_platform_driver(wm5110_codec_driver); + +MODULE_DESCRIPTION("ASoC WM5110 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm5110-codec"); diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h new file mode 100644 index 000000000000..75e9351ccab0 --- /dev/null +++ b/sound/soc/codecs/wm5110.h @@ -0,0 +1,21 @@ +/* + * wm5110.h -- WM5110 ALSA SoC Audio driver + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown + * + * 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 _WM5110_H +#define _WM5110_H + +#include "arizona.h" + +#define WM5110_FLL1 1 +#define WM5110_FLL2 2 + +#endif -- GitLab From 0cd76dd13bdd2f7f02a2dc931e808e92b191082f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 19:40:52 +0100 Subject: [PATCH 2481/5711] iommu: Add domain-attribute handlers This patch introduces an extension to the iommu-api to get and set attributes for an iommu_domain. Two functions are introduced for this: * iommu_domain_get_attr() * iommu_domain_set_attr() These functions will be used to make the iommu-api suitable for GART-like IOMMUs and to implement hardware-specifc api-extensions. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 20 ++++++++++++++++++++ include/linux/iommu.h | 28 +++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 8b9ded88e6f5..c39972d8ded3 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -344,3 +344,23 @@ int iommu_device_group(struct device *dev, unsigned int *groupid) return -ENODEV; } EXPORT_SYMBOL_GPL(iommu_device_group); + +int iommu_domain_get_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + if (!domain->ops->domain_get_attr) + return -EINVAL; + + return domain->ops->domain_get_attr(domain, attr, data); +} +EXPORT_SYMBOL_GPL(iommu_domain_get_attr); + +int iommu_domain_set_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + if (!domain->ops->domain_set_attr) + return -EINVAL; + + return domain->ops->domain_set_attr(domain, attr, data); +} +EXPORT_SYMBOL_GPL(iommu_domain_set_attr); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 450293f6d68b..0eef096183e8 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -47,6 +47,10 @@ struct iommu_domain { #define IOMMU_CAP_CACHE_COHERENCY 0x1 #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ +enum iommu_attr { + DOMAIN_ATTR_MAX, +}; + #ifdef CONFIG_IOMMU_API /** @@ -59,7 +63,8 @@ struct iommu_domain { * @unmap: unmap a physically contiguous memory region from an iommu domain * @iova_to_phys: translate iova to physical address * @domain_has_cap: domain capabilities query - * @commit: commit iommu domain + * @domain_get_attr: Query domain attributes + * @domain_set_attr: Change domain attributes * @pgsize_bitmap: bitmap of supported page sizes */ struct iommu_ops { @@ -76,6 +81,10 @@ struct iommu_ops { int (*domain_has_cap)(struct iommu_domain *domain, unsigned long cap); int (*device_group)(struct device *dev, unsigned int *groupid); + int (*domain_get_attr)(struct iommu_domain *domain, + enum iommu_attr attr, void *data); + int (*domain_set_attr)(struct iommu_domain *domain, + enum iommu_attr attr, void *data); unsigned long pgsize_bitmap; }; @@ -99,6 +108,11 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); extern int iommu_device_group(struct device *dev, unsigned int *groupid); +extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, + void *data); +extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, + void *data); + /** * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework * @domain: the iommu domain where the fault has happened @@ -202,6 +216,18 @@ static inline int iommu_device_group(struct device *dev, unsigned int *groupid) return -ENODEV; } +static inline int iommu_domain_get_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + return -EINVAL; +} + +static inline int iommu_domain_set_attr(struct iommu_domain *domain, + enum iommu_attr attr, void *data) +{ + return -EINVAL; +} + #endif /* CONFIG_IOMMU_API */ #endif /* __LINUX_IOMMU_H */ -- GitLab From 0ff64f80e075ae036a4c80c7d7752b1e07fed792 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 19:40:53 +0100 Subject: [PATCH 2482/5711] iommu/amd: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute itself and add the code for the AMD IOMMU driver. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 4 ++++ drivers/iommu/iommu.c | 19 ++++++++++++++++--- include/linux/iommu.h | 8 ++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a2e418cba0ff..259a6beddece 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3069,6 +3069,10 @@ static int amd_iommu_domain_init(struct iommu_domain *dom) dom->priv = domain; + dom->geometry.aperture_start = 0; + dom->geometry.aperture_end = ~0ULL; + dom->geometry.force_aperture = true; + return 0; out_free: diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index c39972d8ded3..ed5e0a553ca7 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -348,10 +348,23 @@ EXPORT_SYMBOL_GPL(iommu_device_group); int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr attr, void *data) { - if (!domain->ops->domain_get_attr) - return -EINVAL; + struct iommu_domain_geometry *geometry; + int ret = 0; + + switch (attr) { + case DOMAIN_ATTR_GEOMETRY: + geometry = data; + *geometry = domain->geometry; + + break; + default: + if (!domain->ops->domain_get_attr) + return -EINVAL; - return domain->ops->domain_get_attr(domain, attr, data); + ret = domain->ops->domain_get_attr(domain, attr, data); + } + + return ret; } EXPORT_SYMBOL_GPL(iommu_domain_get_attr); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0eef096183e8..f7df4aa527f3 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -37,11 +37,18 @@ struct iommu_domain; typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); +struct iommu_domain_geometry { + dma_addr_t aperture_start; /* First address that can be mapped */ + dma_addr_t aperture_end; /* Last address that can be mapped */ + bool force_aperture; /* DMA only allowed in mappable range? */ +}; + struct iommu_domain { struct iommu_ops *ops; void *priv; iommu_fault_handler_t handler; void *handler_token; + struct iommu_domain_geometry geometry; }; #define IOMMU_CAP_CACHE_COHERENCY 0x1 @@ -49,6 +56,7 @@ struct iommu_domain { enum iommu_attr { DOMAIN_ATTR_MAX, + DOMAIN_ATTR_GEOMETRY, }; #ifdef CONFIG_IOMMU_API -- GitLab From 8a0e715b73c4a54d6ef294ce314dab22c6b62a10 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 19:40:54 +0100 Subject: [PATCH 2483/5711] iommu/vt-d: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute for the Intel IOMMU driver. Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b12af2ff8c54..6cb0791b3264 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3932,6 +3932,10 @@ static int intel_iommu_domain_init(struct iommu_domain *domain) domain_update_iommu_cap(dmar_domain); domain->priv = dmar_domain; + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw); + domain->geometry.force_aperture = true; + return 0; } -- GitLab From 2c6edb0cc43688a12571a35728a06e2748d55af3 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 19:40:55 +0100 Subject: [PATCH 2484/5711] iommu/omap: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute for the OMAP IOMMU driver. Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index e70ee2b59df9..d0b1234581be 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1148,6 +1148,10 @@ static int omap_iommu_domain_init(struct iommu_domain *domain) domain->priv = omap_domain; + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = (1ULL << 32) - 1; + domain->geometry.force_aperture = true; + return 0; fail_nomem: -- GitLab From 4be6a290b87af9136b482d5c22574f070ffdbdb8 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 19:40:56 +0100 Subject: [PATCH 2485/5711] iommu/msm: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute for the MSM IOMMU driver. Acked-by: David Brown Signed-off-by: Joerg Roedel --- drivers/iommu/msm_iommu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index cee307e86606..6a8870a31668 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -226,6 +226,11 @@ static int msm_iommu_domain_init(struct iommu_domain *domain) memset(priv->pgtable, 0, SZ_16K); domain->priv = priv; + + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = (1ULL << 32) - 1; + domain->geometry.force_aperture = true; + return 0; fail_nomem: -- GitLab From 23349902edec4d3d932bca1bb99261477139a36a Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Thu, 26 Jan 2012 19:40:57 +0100 Subject: [PATCH 2486/5711] iommu/tegra: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute for the Tegra IOMMU drivers. Signed-off-by: Hiroshi DOYU Signed-off-by: Joerg Roedel --- drivers/iommu/tegra-gart.c | 5 +++++ drivers/iommu/tegra-smmu.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 0c0a37792218..c16e8fc8a4bd 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -165,6 +165,11 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, return -EINVAL; domain->priv = gart; + domain->geometry.aperture_start = gart->iovmm_base; + domain->geometry.aperture_end = gart->iovmm_base + + gart->page_count * GART_PAGE_SIZE - 1; + domain->geometry.force_aperture = true; + client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); if (!client) return -ENOMEM; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index ecd679043d77..96e73d56451a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -807,6 +807,11 @@ found: spin_unlock_irqrestore(&as->lock, flags); domain->priv = as; + domain->geometry.aperture_start = smmu->iovmm_base; + domain->geometry.aperture_end = smmu->iovmm_base + + smmu->page_count * SMMU_PAGE_SIZE - 1; + domain->geometry.force_aperture = true; + dev_dbg(smmu->dev, "smmu_as@%p\n", as); return 0; -- GitLab From 3177bb76a8c510cbc737425a74e777a9aa253065 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 11 Jul 2012 12:41:10 +0200 Subject: [PATCH 2487/5711] iommu/exynos: Implement DOMAIN_ATTR_GEOMETRY attribute Implement the attribute for the Samsung Exynos IOMMU driver. Signed-off-by: Joerg Roedel --- drivers/iommu/exynos-iommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 9a114b9ff170..5c40937e9988 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -732,6 +732,10 @@ static int exynos_iommu_domain_init(struct iommu_domain *domain) spin_lock_init(&priv->pgtablelock); INIT_LIST_HEAD(&priv->clients); + dom->geometry.aperture_start = 0; + dom->geometry.aperture_end = ~0UL; + dom->geometry.force_aperture = true; + domain->priv = priv; return 0; -- GitLab From 6d1d051330ee096f575523647fbd8ffe703600b5 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 3 Jul 2012 22:49:04 -0700 Subject: [PATCH 2488/5711] USB: Fix LPM disable/enable during device reset. The USB 3.0 specification says that sending a Set Feature or Clear Feature for U1/U2 Enable is not a valid request when the device is in the Default or Addressed state. It is only valid when the device is in the Configured state. The original LPM patch attempted to disable LPM after the device had been reset by hub_port_init(), before it had the configuration reinstalled. The TI hub I tested with did not fail the Clear Feature U1/U2 Enable request that khubd sent while it was in the addressed state, which is why I didn't catch it. Move the LPM disable before the device reset, so that we can send the Clear Feature U1/U2 Enable successfully, and balance the LPM disable count. Also delete any calls to usb_enable_lpm() on error paths that lead to re-enumeration. The calls will fail because the device isn't configured, and it's not useful to balance the LPM disable count because the usb_device is about to be destroyed before re-enumeration. Fix the early exit path ("done" label) to call usb_enable_lpm() to balance the LPM disable count. Note that calling usb_reset_and_verify_device() with an unconfigured device may fail on the first call to usb_disable_lpm(). That's because the LPM disable count is initialized to 0 (LPM enabled), and usb_disable_lpm() will attempt to send a Clear Feature U1/U2 request to a device in the Addressed state. The next patch will fix that. This commit should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/hub.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4cc8dc96940e..5c31d2c2f95a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4673,6 +4673,16 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } parent_hub = hdev_to_hub(parent_hdev); + /* Disable LPM while we reset the device and reinstall the alt settings. + * Device-initiated LPM settings, and system exit latency settings are + * cleared when the device is reset, so we have to set them up again. + */ + ret = usb_unlocked_disable_lpm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); + goto re_enumerate; + } + set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -4700,22 +4710,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev) goto done; mutex_lock(hcd->bandwidth_mutex); - /* Disable LPM while we reset the device and reinstall the alt settings. - * Device-initiated LPM settings, and system exit latency settings are - * cleared when the device is reset, so we have to set them up again. - */ - ret = usb_disable_lpm(udev); - if (ret) { - dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); - mutex_unlock(hcd->bandwidth_mutex); - goto done; - } ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); if (ret < 0) { dev_warn(&udev->dev, "Busted HC? Not enough HCD resources for " "old configuration.\n"); - usb_enable_lpm(udev); mutex_unlock(hcd->bandwidth_mutex); goto re_enumerate; } @@ -4727,7 +4726,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) dev_err(&udev->dev, "can't restore configuration #%d (error=%d)\n", udev->actconfig->desc.bConfigurationValue, ret); - usb_enable_lpm(udev); mutex_unlock(hcd->bandwidth_mutex); goto re_enumerate; } @@ -4766,17 +4764,17 @@ static int usb_reset_and_verify_device(struct usb_device *udev) desc->bInterfaceNumber, desc->bAlternateSetting, ret); - usb_unlocked_enable_lpm(udev); goto re_enumerate; } } +done: /* Now that the alt settings are re-installed, enable LPM. */ usb_unlocked_enable_lpm(udev); -done: return 0; re_enumerate: + /* LPM state doesn't matter when we're about to destroy the device. */ hub_port_logical_disconnect(parent_hub, port1); return -ENODEV; } -- GitLab From 9cf65991dd93ac3d5f97f536171c388918b7c1a9 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 3 Jul 2012 23:22:38 -0700 Subject: [PATCH 2489/5711] USB: Disable LPM while the device is unconfigured. The USB 3.0 Set/Clear Feature U1/U2 Enable cannot be sent to a device in the Default or Addressed state. It can only be sent to a configured device. Change the USB core to initialize the LPM disable count to 1 (disabled), which reflects this limitation. Change usb_set_configuration() to ensure that if the device is unconfigured on entry, usb_lpm_disable() is not called. This avoids sending the Clear Feature U1/U2 when the device is in the Addressed state. When usb_set_configuration() exits with a successfully installed configuration, usb_lpm_enable() will be called. Once the new configuration is installed, make sure usb_set_configuration() only calls usb_enable_lpm() if the device moved to the Configured state. If we have unconfigured the device by sending it a Set Configuration for config 0, don't enable LPM. This commit should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/message.c | 7 ++++--- drivers/usb/core/usb.c | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 8b9d669e3784..37239048be14 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1792,14 +1792,15 @@ free_interfaces: * installed, so that the xHCI driver can recalculate the U1/U2 * timeouts. */ - if (usb_disable_lpm(dev)) { + if (dev->actconfig && usb_disable_lpm(dev)) { dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__); mutex_unlock(hcd->bandwidth_mutex); return -ENOMEM; } ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { - usb_enable_lpm(dev); + if (dev->actconfig) + usb_enable_lpm(dev); mutex_unlock(hcd->bandwidth_mutex); usb_autosuspend_device(dev); goto free_interfaces; @@ -1819,7 +1820,7 @@ free_interfaces: if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - usb_enable_lpm(dev); + /* Leave LPM disabled while the device is unconfigured. */ mutex_unlock(hcd->bandwidth_mutex); usb_autosuspend_device(dev); goto free_interfaces; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 25d0c61c3f8a..cd8fb44a3e16 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -396,6 +396,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->dev.dma_mask = bus->controller->dma_mask; set_dev_node(&dev->dev, dev_to_node(bus->controller)); dev->state = USB_STATE_ATTACHED; + dev->lpm_disable_count = 1; atomic_set(&dev->urbnum, 0); INIT_LIST_HEAD(&dev->ep0.urb_list); -- GitLab From 249719121bc2b841bdfcab5eb21b10d8b871743b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 5 Jul 2012 14:09:30 -0700 Subject: [PATCH 2490/5711] USB: Fix LPM disable count mismatch on driver unbind. When a user runs `echo 0 > bConfigurationValue` for a USB 3.0 device, usb_disable_device() is called. This function disables all drivers, deallocates interfaces, and sets the device configuration value to 0 (unconfigured). With the new scheme to ensure that unconfigured devices have LPM disabled, usb_disable_device() must call usb_unlocked_disable_lpm() once it unconfigures the device. This commit should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/message.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 37239048be14..c0877b7f505a 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1174,6 +1174,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) put_device(&dev->actconfig->interface[i]->dev); dev->actconfig->interface[i] = NULL; } + usb_unlocked_disable_lpm(dev); dev->actconfig = NULL; if (dev->state == USB_STATE_CONFIGURED) usb_set_device_state(dev, USB_STATE_ADDRESS); -- GitLab From c5c4bdf02e518a281b229ae0891b346919e2d291 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 5 Jul 2012 09:41:22 -0700 Subject: [PATCH 2491/5711] USB: Remove unused LPM variable. hub_initiated_lpm_disable_count is not used by any code, so remove it. This commit should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- include/linux/usb.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index d4f9de1acd45..dea2f0de063e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -561,7 +561,6 @@ struct usb_device { struct usb3_lpm_parameters u1_params; struct usb3_lpm_parameters u2_params; unsigned lpm_disable_count; - unsigned hub_initiated_lpm_disable_count; }; #define to_usb_device(d) container_of(d, struct usb_device, dev) -- GitLab From af3a23ef4e5fbaf33f0afdda7d26442f036ba795 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 25 Jun 2012 08:24:30 -0700 Subject: [PATCH 2492/5711] xhci: Export Latency Tolerance Messaging capabilities. Some xHCI host controllers may have optional support for Latency Tolerance Messaging (LTM). This allows USB 3.0 devices that support LTM to pass information about how much latency they can tolerate to the xHC. A PCI xHCI host will use this information to update the PCI Latency Tolerance Request (LTR) info. The goal of this is to gather latency information for the system, to enable hardware-driven C states, and the shutting down of PLLs. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 2732ef660c5c..6d21030e2b7b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -508,12 +508,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if (hcd->speed != HCD_USB3) goto error; + /* Set the U1 and U2 exit latencies. */ memcpy(buf, &usb_bos_descriptor, USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); buf[12] = HCS_U1_LATENCY(temp); put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); + /* Indicate whether the host has LTM support. */ + temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); + if (HCC_LTC(temp)) + buf[8] |= USB_LTM_SUPPORT; + spin_unlock_irqrestore(&xhci->lock, flags); return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; case GetPortStatus: -- GitLab From f74631e3426474183389e55f703797bd965cd356 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 25 Jun 2012 12:08:08 -0700 Subject: [PATCH 2493/5711] USB: Enable Latency Tolerance Messaging (LTM). USB 3.0 devices may optionally support a new feature called Latency Tolerance Messaging. If both the xHCI host controller and the device support LTM, it should be turned on in order to give the system hardware a better clue about the latency tolerance values of its PCI devices. Once a Set Feature request to enable LTM is received, the USB 3.0 device will begin to send LTM updates as its buffers fill or empty, and it can tolerate more or less latency. The USB 3.0 spec, section C.4.2 says that LTM should be disabled just before the device is placed into suspend. Then the device will send an updated LTM notification, so that the system doesn't think it should remain in an active state in order to satisfy the latency requirements of the suspended device. The Set and Clear Feature LTM enable command can only be sent to a configured device. The device will respond with an error if that command is sent while it is in the Default or Addressed state. Make sure to check udev->actconfig in usb_enable_ltm() and usb_disable_ltm(), and don't send those commands when the device is unconfigured. LTM should be enabled once a new configuration is installed in usb_set_configuration(). If we end up sending duplicate Set Feature LTM Enable commands on a switch from one installed configuration to another configuration, that should be harmless. Make sure that LTM is disabled before the device is unconfigured in usb_disable_device(). If no drivers are bound to the device, it doesn't make sense to allow the device to control the latency tolerance of the xHCI host controller. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 87 +++++++++++++++++++++++++++++++++++--- drivers/usb/core/message.c | 3 ++ include/linux/usb.h | 3 ++ 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5c31d2c2f95a..b5bd6bd8fd12 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2610,6 +2610,57 @@ static int check_port_resume_type(struct usb_device *udev, return status; } +static bool usb_device_supports_ltm(struct usb_device *udev) +{ + if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap) + return false; + return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT; +} + +int usb_disable_ltm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + /* Check if the roothub and device supports LTM. */ + if (!usb_device_supports_ltm(hcd->self.root_hub) || + !usb_device_supports_ltm(udev)) + return 0; + + /* Clear Feature LTM Enable can only be sent if the device is + * configured. + */ + if (!udev->actconfig) + return 0; + + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} +EXPORT_SYMBOL_GPL(usb_disable_ltm); + +void usb_enable_ltm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + /* Check if the roothub and device supports LTM. */ + if (!usb_device_supports_ltm(hcd->self.root_hub) || + !usb_device_supports_ltm(udev)) + return; + + /* Set Feature LTM Enable can only be sent if the device is + * configured. + */ + if (!udev->actconfig) + return; + + usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} +EXPORT_SYMBOL_GPL(usb_enable_ltm); + #ifdef CONFIG_USB_SUSPEND /* @@ -2705,6 +2756,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (udev->usb2_hw_lpm_enabled == 1) usb_set_usb2_hardware_lpm(udev, 0); + if (usb_disable_ltm(udev)) { + dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.", + __func__); + return -ENOMEM; + } if (usb_unlocked_disable_lpm(udev)) { dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", __func__); @@ -2734,7 +2790,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (udev->usb2_hw_lpm_capable == 1) usb_set_usb2_hardware_lpm(udev, 1); - /* Try to enable USB3 LPM again */ + /* Try to enable USB3 LTM and LPM again */ + usb_enable_ltm(udev); usb_unlocked_enable_lpm(udev); /* System sleep transitions should never fail */ @@ -2935,7 +2992,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) if (udev->usb2_hw_lpm_capable == 1) usb_set_usb2_hardware_lpm(udev, 1); - /* Try to enable USB3 LPM */ + /* Try to enable USB3 LTM and LPM */ + usb_enable_ltm(udev); usb_unlocked_enable_lpm(udev); } @@ -3488,6 +3546,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); void usb_unlocked_enable_lpm(struct usb_device *udev) { } EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); + +int usb_disable_ltm(struct usb_device *udev) +{ + return 0; +} +EXPORT_SYMBOL_GPL(usb_disable_ltm); + +void usb_enable_ltm(struct usb_device *udev) { } +EXPORT_SYMBOL_GPL(usb_enable_ltm); #endif @@ -4673,15 +4740,22 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } parent_hub = hdev_to_hub(parent_hdev); - /* Disable LPM while we reset the device and reinstall the alt settings. - * Device-initiated LPM settings, and system exit latency settings are - * cleared when the device is reset, so we have to set them up again. + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency + * settings are cleared when the device is reset, so we have to set + * them up again. */ ret = usb_unlocked_disable_lpm(udev); if (ret) { dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); goto re_enumerate; } + ret = usb_disable_ltm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LTM\n.", + __func__); + goto re_enumerate; + } set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -4769,8 +4843,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } done: - /* Now that the alt settings are re-installed, enable LPM. */ + /* Now that the alt settings are re-installed, enable LTM and LPM. */ usb_unlocked_enable_lpm(udev); + usb_enable_ltm(udev); return 0; re_enumerate: diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c0877b7f505a..0ab7da2283e3 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1175,6 +1175,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) dev->actconfig->interface[i] = NULL; } usb_unlocked_disable_lpm(dev); + usb_disable_ltm(dev); dev->actconfig = NULL; if (dev->state == USB_STATE_CONFIGURED) usb_set_device_state(dev, USB_STATE_ADDRESS); @@ -1879,6 +1880,8 @@ free_interfaces: /* Now that the interfaces are installed, re-enable LPM. */ usb_unlocked_enable_lpm(dev); + /* Enable LTM if it was turned off by usb_disable_device. */ + usb_enable_ltm(dev); /* Now that all the interfaces are set up, register them * to trigger binding of drivers to interfaces. probe() diff --git a/include/linux/usb.h b/include/linux/usb.h index dea2f0de063e..f29831bad235 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -633,6 +633,9 @@ extern void usb_enable_lpm(struct usb_device *udev); extern int usb_unlocked_disable_lpm(struct usb_device *udev); extern void usb_unlocked_enable_lpm(struct usb_device *udev); +extern int usb_disable_ltm(struct usb_device *udev); +extern void usb_enable_ltm(struct usb_device *udev); + /*-------------------------------------------------------------------------*/ /* for drivers using iso endpoints */ -- GitLab From 024f117c2f3c4bb5df6e6696b709e0f3ed7e5dbb Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 5 Jul 2012 17:17:24 -0700 Subject: [PATCH 2494/5711] USB: Add a sysfs file to show LTM capabilities. USB 3.0 devices can optionally support Latency Tolerance Messaging (LTM). Add a new sysfs file in the device directory to show whether a device is LTM capable. This file will be present for both USB 2.0 and USB 3.0 devices. Signed-off-by: Sarah Sharp --- Documentation/ABI/testing/sysfs-bus-usb | 12 ++++++++++++ drivers/usb/core/hub.c | 7 ------- drivers/usb/core/sysfs.c | 10 ++++++++++ include/linux/usb.h | 8 ++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 6df4e6f57560..5f75f8f7df34 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -208,3 +208,15 @@ Description: such as ACPI. This file will read either "removable" or "fixed" if the information is available, and "unknown" otherwise. + +What: /sys/bus/usb/devices/.../ltm_capable +Date: July 2012 +Contact: Sarah Sharp +Description: + USB 3.0 devices may optionally support Latency Tolerance + Messaging (LTM). They indicate their support by setting a bit + in the bmAttributes field of their SuperSpeed BOS descriptors. + If that bit is set for the device, ltm_capable will read "yes". + If the device doesn't support LTM, the file will read "no". + The file will be present for all speeds of USB devices, and will + always read "no" for USB 1.1 and USB 2.0 devices. diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b5bd6bd8fd12..d739f966b5a8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2610,13 +2610,6 @@ static int check_port_resume_type(struct usb_device *udev, return status; } -static bool usb_device_supports_ltm(struct usb_device *udev) -{ - if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap) - return false; - return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT; -} - int usb_disable_ltm(struct usb_device *udev) { struct usb_hcd *hcd = bus_to_hcd(udev->bus); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 777f03c37725..682e8256b95d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -253,6 +253,15 @@ show_removable(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); +static ssize_t +show_ltm_capable(struct device *dev, struct device_attribute *attr, char *buf) +{ + if (usb_device_supports_ltm(to_usb_device(dev))) + return sprintf(buf, "%s\n", "yes"); + return sprintf(buf, "%s\n", "no"); +} +static DEVICE_ATTR(ltm_capable, S_IRUGO, show_ltm_capable, NULL); + #ifdef CONFIG_PM static ssize_t @@ -649,6 +658,7 @@ static struct attribute *dev_attrs[] = { &dev_attr_authorized.attr, &dev_attr_remove.attr, &dev_attr_removable.attr, + &dev_attr_ltm_capable.attr, NULL, }; static struct attribute_group dev_attr_grp = { diff --git a/include/linux/usb.h b/include/linux/usb.h index f29831bad235..f8506ed0f97b 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -636,6 +636,14 @@ extern void usb_unlocked_enable_lpm(struct usb_device *udev); extern int usb_disable_ltm(struct usb_device *udev); extern void usb_enable_ltm(struct usb_device *udev); +static inline bool usb_device_supports_ltm(struct usb_device *udev) +{ + if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap) + return false; + return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT; +} + + /*-------------------------------------------------------------------------*/ /* for drivers using iso endpoints */ -- GitLab From 781d0f46d81e2c26c70649903b503bcfe817efc8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 12:19:19 +0100 Subject: [PATCH 2495/5711] irq_domain: Standardise legacy/linear domain selection A large proportion of interrupt controllers that support legacy mappings do so because non-DT systems need to use fixed IRQ numbers when registering devices via buses but can otherwise use a linear mapping. The interrupt controller itself typically is not affected by the mapping used and best practice is to use a linear mapping where possible so drivers frequently select at runtime depending on if a legacy range has been allocated to them. Standardise this behaviour by providing irq_domain_register_simple() which will allocate a linear mapping unless a positive first_irq is provided in which case it will fall back to a legacy mapping. This helps make best practice for irq_domain adoption clearer. Signed-off-by: Mark Brown Signed-off-by: Grant Likely --- Documentation/IRQ-domain.txt | 5 +++++ include/linux/irqdomain.h | 5 +++++ kernel/irq/irqdomain.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 27dcaabfb4db..1401cece745a 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -93,6 +93,7 @@ Linux IRQ number into the hardware. Most drivers cannot use this mapping. ==== Legacy ==== +irq_domain_add_simple() irq_domain_add_legacy() irq_domain_add_legacy_isa() @@ -115,3 +116,7 @@ The legacy map should only be used if fixed IRQ mappings must be supported. For example, ISA controllers would use the legacy map for mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ numbers. + +Most users of legacy mappings should use irq_domain_add_simple() which +will use a legacy domain only if an IRQ range is supplied by the +system and will otherwise use a linear domain mapping. diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 5abb533eb8eb..17b60be30fff 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -112,6 +112,11 @@ struct irq_domain { }; #ifdef CONFIG_IRQ_DOMAIN +struct irq_domain *irq_domain_add_simple(struct device_node *of_node, + unsigned int size, + unsigned int first_irq, + const struct irq_domain_ops *ops, + void *host_data); struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, unsigned int size, unsigned int first_irq, diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index d3968e91bfd2..0c51958c6335 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -139,6 +139,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, return hwirq - first_hwirq + domain->revmap_data.legacy.first_irq; } +/** + * irq_domain_add_simple() - Allocate and register a simple irq_domain. + * @of_node: pointer to interrupt controller's device tree node. + * @size: total number of irqs in mapping + * @first_irq: first number of irq block assigned to the domain + * @ops: map/unmap domain callbacks + * @host_data: Controller private data pointer + * + * Allocates a legacy irq_domain if irq_base is positive or a linear + * domain otherwise. + * + * This is intended to implement the expected behaviour for most + * interrupt controllers which is that a linear mapping should + * normally be used unless the system requires a legacy mapping in + * order to support supplying interrupt numbers during non-DT + * registration of devices. + */ +struct irq_domain *irq_domain_add_simple(struct device_node *of_node, + unsigned int size, + unsigned int first_irq, + const struct irq_domain_ops *ops, + void *host_data) +{ + if (first_irq > 0) + return irq_domain_add_legacy(of_node, size, first_irq, 0, + ops, host_data); + else + return irq_domain_add_linear(of_node, size, ops, host_data); +} + /** * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain. * @of_node: pointer to interrupt controller's device tree node. -- GitLab From 22076c7712be29a602de45b1c573f31adbd428a9 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 20 Jun 2012 17:00:30 +0800 Subject: [PATCH 2496/5711] irq_domain: correct a minor wrong comment for linear revmap The revmap type should be linear for irq_domain_add_linear function. Signed-off-by: Dong Aisheng Signed-off-by: Grant Likely --- kernel/irq/irqdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 0c51958c6335..622fdf4b82b6 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -248,7 +248,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, EXPORT_SYMBOL_GPL(irq_domain_add_legacy); /** - * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain. + * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. * @of_node: pointer to interrupt controller's device tree node. * @size: Number of interrupts in the domain. * @ops: map/unmap domain callbacks -- GitLab From 913af2070731bfc1bd39bb35c5cd2fd66f5eff12 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:35 -0700 Subject: [PATCH 2497/5711] irqdomain: Split disassociating code into separate function This patch moves the irq disassociation code out into a separate function in preparation to extend irq_setup_virq to handle multiple irqs and rename it for use by interrupt controller drivers. The new function will be used by irq_setup_virq() in its error path. Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Cc: Paul Mundt Cc: Thomas Gleixner Cc: Rob Herring --- kernel/irq/irqdomain.c | 75 ++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 622fdf4b82b6..17634f2c9f6c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -364,6 +364,52 @@ void irq_set_default_host(struct irq_domain *domain) } EXPORT_SYMBOL_GPL(irq_set_default_host); +static void irq_domain_disassociate_many(struct irq_domain *domain, + unsigned int irq_base, int count) +{ + /* + * disassociate in reverse order; + * not strictly necessary, but nice for unwinding + */ + while (count--) { + int irq = irq_base + count; + struct irq_data *irq_data = irq_get_irq_data(irq); + irq_hw_number_t hwirq = irq_data->hwirq; + + if (WARN_ON(!irq_data || irq_data->domain != domain)) + continue; + + irq_set_status_flags(irq, IRQ_NOREQUEST); + + /* remove chip and handler */ + irq_set_chip_and_handler(irq, NULL, NULL); + + /* Make sure it's completed */ + synchronize_irq(irq); + + /* Tell the PIC about it */ + if (domain->ops->unmap) + domain->ops->unmap(domain, irq); + smp_mb(); + + irq_data->domain = NULL; + irq_data->hwirq = 0; + + /* Clear reverse map */ + switch(domain->revmap_type) { + case IRQ_DOMAIN_MAP_LINEAR: + if (hwirq < domain->revmap_data.linear.size) + domain->revmap_data.linear.revmap[hwirq] = 0; + break; + case IRQ_DOMAIN_MAP_TREE: + mutex_lock(&revmap_trees_mutex); + radix_tree_delete(&domain->revmap_data.tree, hwirq); + mutex_unlock(&revmap_trees_mutex); + break; + } + } +} + static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq) { @@ -544,7 +590,6 @@ void irq_dispose_mapping(unsigned int virq) { struct irq_data *irq_data = irq_get_irq_data(virq); struct irq_domain *domain; - irq_hw_number_t hwirq; if (!virq || !irq_data) return; @@ -557,33 +602,7 @@ void irq_dispose_mapping(unsigned int virq) if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) return; - irq_set_status_flags(virq, IRQ_NOREQUEST); - - /* remove chip and handler */ - irq_set_chip_and_handler(virq, NULL, NULL); - - /* Make sure it's completed */ - synchronize_irq(virq); - - /* Tell the PIC about it */ - if (domain->ops->unmap) - domain->ops->unmap(domain, virq); - smp_mb(); - - /* Clear reverse map */ - hwirq = irq_data->hwirq; - switch(domain->revmap_type) { - case IRQ_DOMAIN_MAP_LINEAR: - if (hwirq < domain->revmap_data.linear.size) - domain->revmap_data.linear.revmap[hwirq] = 0; - break; - case IRQ_DOMAIN_MAP_TREE: - mutex_lock(&revmap_trees_mutex); - radix_tree_delete(&domain->revmap_data.tree, hwirq); - mutex_unlock(&revmap_trees_mutex); - break; - } - + irq_domain_disassociate_many(domain, virq, 1); irq_free_desc(virq); } EXPORT_SYMBOL_GPL(irq_dispose_mapping); -- GitLab From 2a71a1a9da40dfbd5b23d4312aa1641385581f4a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:36 -0700 Subject: [PATCH 2498/5711] irqdomain: Always update revmap when setting up a virq At irq_setup_virq() time all of the data needed to update the reverse map is available, but the current code ignores it and relies upon the slow path to insert revmap records. This patch adds revmap updating to the setup path so the slow path will no longer be necessary. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring --- arch/powerpc/sysdev/xics/xics-common.c | 3 --- kernel/irq/irqdomain.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index cd1d18db92c6..9049d9f44485 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -329,9 +329,6 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq, pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); - /* Insert the interrupt mapping into the radix tree for fast lookup */ - irq_radix_revmap_insert(xics_host, virq, hw); - /* They aren't all level sensitive but we just don't really know */ irq_set_status_flags(virq, IRQ_LEVEL); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 17634f2c9f6c..091732c9dbdc 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -424,6 +424,18 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, return -1; } + switch (domain->revmap_type) { + case IRQ_DOMAIN_MAP_LINEAR: + if (hwirq < domain->revmap_data.linear.size) + domain->revmap_data.linear.revmap[hwirq] = virq; + break; + case IRQ_DOMAIN_MAP_TREE: + mutex_lock(&revmap_trees_mutex); + irq_radix_revmap_insert(domain, virq, hwirq); + mutex_unlock(&revmap_trees_mutex); + break; + } + irq_clear_status_flags(virq, IRQ_NOREQUEST); return 0; -- GitLab From 98aa468e045a0091a7c34d9f5205a629634fabf4 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 17 Jun 2012 16:17:04 -0600 Subject: [PATCH 2499/5711] irqdomain: Support for static IRQ mapping and association. This adds a new strict mapping API for supporting creation of linux IRQs at existing positions within the domain. The new routines are as follows: For dynamic allocation and insertion to specified ranges: - irq_create_identity_mapping() - irq_create_strict_mappings() These will allocate and associate a range of linux IRQs at the specified location. This can be used by controllers that have their own static linux IRQ definitions to map a hwirq range to, as well as for platforms that wish to establish 1:1 identity mapping between linux and hwirq space. For insertion to specified ranges by platforms that do their own irq_desc management: - irq_domain_associate() - irq_domain_associate_many() These in turn call back in to the domain's ->map() routine, for further processing by the platform. Disassociation of IRQs get handled through irq_dispose_mapping() as normal. With these in place it should be possible to begin migration of legacy IRQ domains to linear ones, without requiring special handling for static vs dynamic IRQ definitions in DT vs non-DT paths. This also makes it possible for domains with static mappings to adopt whichever tree model best fits their needs, rather than simply restricting them to linear revmaps. Signed-off-by: Paul Mundt [grant.likely: Reorganized irq_domain_associate{,_many} to have all logic in one place] [grant.likely: Add error checking for unallocated irq_descs at associate time] Signed-off-by: Grant Likely Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring --- include/linux/irqdomain.h | 19 +++++++ kernel/irq/irqdomain.c | 113 +++++++++++++++++++++++++++++--------- 2 files changed, 107 insertions(+), 25 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 17b60be30fff..eab8a0e60b8e 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -149,12 +149,31 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( extern void irq_domain_remove(struct irq_domain *host); +extern int irq_domain_associate_many(struct irq_domain *domain, + unsigned int irq_base, + irq_hw_number_t hwirq_base, int count); +static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + return irq_domain_associate_many(domain, irq, hwirq, 1); +} + extern unsigned int irq_create_mapping(struct irq_domain *host, irq_hw_number_t hwirq); extern void irq_dispose_mapping(unsigned int virq); extern unsigned int irq_find_mapping(struct irq_domain *host, irq_hw_number_t hwirq); extern unsigned int irq_create_direct_mapping(struct irq_domain *host); +extern int irq_create_strict_mappings(struct irq_domain *domain, + unsigned int irq_base, + irq_hw_number_t hwirq_base, int count); + +static inline int irq_create_identity_mapping(struct irq_domain *host, + irq_hw_number_t hwirq) +{ + return irq_create_strict_mappings(host, hwirq, hwirq, 1); +} + extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq, irq_hw_number_t hwirq); extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 091732c9dbdc..a07d92446b66 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -410,36 +410,61 @@ static void irq_domain_disassociate_many(struct irq_domain *domain, } } -static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, - irq_hw_number_t hwirq) +int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, + irq_hw_number_t hwirq_base, int count) { - struct irq_data *irq_data = irq_get_irq_data(virq); + unsigned int virq = irq_base; + irq_hw_number_t hwirq = hwirq_base; + int i; - irq_data->hwirq = hwirq; - irq_data->domain = domain; - if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { - pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); - irq_data->domain = NULL; - irq_data->hwirq = 0; - return -1; - } + pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, + of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count); - switch (domain->revmap_type) { - case IRQ_DOMAIN_MAP_LINEAR: - if (hwirq < domain->revmap_data.linear.size) - domain->revmap_data.linear.revmap[hwirq] = virq; - break; - case IRQ_DOMAIN_MAP_TREE: - mutex_lock(&revmap_trees_mutex); - irq_radix_revmap_insert(domain, virq, hwirq); - mutex_unlock(&revmap_trees_mutex); - break; - } + for (i = 0; i < count; i++) { + struct irq_data *irq_data = irq_get_irq_data(virq + i); + + if (WARN(!irq_data, "error: irq_desc not allocated; " + "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) + return -EINVAL; + if (WARN(irq_data->domain, "error: irq_desc already associated; " + "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) + return -EINVAL; + }; + + for (i = 0; i < count; i++, virq++, hwirq++) { + struct irq_data *irq_data = irq_get_irq_data(virq); + + irq_data->hwirq = hwirq; + irq_data->domain = domain; + if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { + pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); + irq_data->domain = NULL; + irq_data->hwirq = 0; + goto err_unmap; + } + + switch (domain->revmap_type) { + case IRQ_DOMAIN_MAP_LINEAR: + if (hwirq < domain->revmap_data.linear.size) + domain->revmap_data.linear.revmap[hwirq] = virq; + break; + case IRQ_DOMAIN_MAP_TREE: + mutex_lock(&revmap_trees_mutex); + irq_radix_revmap_insert(domain, virq, hwirq); + mutex_unlock(&revmap_trees_mutex); + break; + } - irq_clear_status_flags(virq, IRQ_NOREQUEST); + irq_clear_status_flags(virq, IRQ_NOREQUEST); + } return 0; + + err_unmap: + irq_domain_disassociate_many(domain, irq_base, i); + return -EINVAL; } +EXPORT_SYMBOL_GPL(irq_domain_associate_many); /** * irq_create_direct_mapping() - Allocate an irq for direct mapping @@ -472,7 +497,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) } pr_debug("create_direct obtained virq %d\n", virq); - if (irq_setup_virq(domain, virq, virq)) { + if (irq_domain_associate(domain, virq, virq)) { irq_free_desc(virq); return 0; } @@ -533,7 +558,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, return 0; } - if (irq_setup_virq(domain, virq, hwirq)) { + if (irq_domain_associate(domain, virq, hwirq)) { irq_free_desc(virq); return 0; } @@ -545,6 +570,44 @@ unsigned int irq_create_mapping(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(irq_create_mapping); +/** + * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs + * @domain: domain owning the interrupt range + * @irq_base: beginning of linux IRQ range + * @hwirq_base: beginning of hardware IRQ range + * @count: Number of interrupts to map + * + * This routine is used for allocating and mapping a range of hardware + * irqs to linux irqs where the linux irq numbers are at pre-defined + * locations. For use by controllers that already have static mappings + * to insert in to the domain. + * + * Non-linear users can use irq_create_identity_mapping() for IRQ-at-a-time + * domain insertion. + * + * 0 is returned upon success, while any failure to establish a static + * mapping is treated as an error. + */ +int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base, + irq_hw_number_t hwirq_base, int count) +{ + int ret; + + ret = irq_alloc_descs(irq_base, irq_base, count, + of_node_to_nid(domain->of_node)); + if (unlikely(ret < 0)) + return ret; + + ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count); + if (unlikely(ret < 0)) { + irq_free_descs(irq_base, count); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(irq_create_strict_mappings); + unsigned int irq_create_of_mapping(struct device_node *controller, const u32 *intspec, unsigned int intsize) { -- GitLab From d6b0d1f7058f7cf818138cd7fd116dca3f3576d9 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:37 -0700 Subject: [PATCH 2500/5711] irqdomain: Eliminate dedicated radix lookup functions In preparation to remove the slow revmap path, eliminate the public radix revmap lookup functions. This simplifies the code and makes the slowpath removal patch a lot simpler. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring --- arch/powerpc/sysdev/xics/icp-hv.c | 2 +- arch/powerpc/sysdev/xics/icp-native.c | 2 +- include/linux/irqdomain.h | 4 -- kernel/irq/irqdomain.c | 60 +-------------------------- 4 files changed, 3 insertions(+), 65 deletions(-) diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 253dce98c16e..14469cf9df68 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c @@ -111,7 +111,7 @@ static unsigned int icp_hv_get_irq(void) if (vec == XICS_IRQ_SPURIOUS) return NO_IRQ; - irq = irq_radix_revmap_lookup(xics_host, vec); + irq = irq_find_mapping(xics_host, vec); if (likely(irq != NO_IRQ)) { xics_push_cppr(vec); return irq; diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 4c79b6fbee1c..48861d3fcd07 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c @@ -119,7 +119,7 @@ static unsigned int icp_native_get_irq(void) if (vec == XICS_IRQ_SPURIOUS) return NO_IRQ; - irq = irq_radix_revmap_lookup(xics_host, vec); + irq = irq_find_mapping(xics_host, vec); if (likely(irq != NO_IRQ)) { xics_push_cppr(vec); return irq; diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index eab8a0e60b8e..0d5b17bf5e51 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -174,10 +174,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host, return irq_create_strict_mappings(host, hwirq, hwirq, 1); } -extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq, - irq_hw_number_t hwirq); -extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, - irq_hw_number_t hwirq); extern unsigned int irq_linear_revmap(struct irq_domain *host, irq_hw_number_t hwirq); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index a07d92446b66..f540bb1eff84 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -450,7 +450,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, break; case IRQ_DOMAIN_MAP_TREE: mutex_lock(&revmap_trees_mutex); - irq_radix_revmap_insert(domain, virq, hwirq); + radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); mutex_unlock(&revmap_trees_mutex); break; } @@ -723,64 +723,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(irq_find_mapping); -/** - * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number. - * @domain: domain owning this hardware interrupt - * @hwirq: hardware irq number in that domain space - * - * This is a fast path, for use by irq controller code that uses radix tree - * revmaps - */ -unsigned int irq_radix_revmap_lookup(struct irq_domain *domain, - irq_hw_number_t hwirq) -{ - struct irq_data *irq_data; - - if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) - return irq_find_mapping(domain, hwirq); - - /* - * Freeing an irq can delete nodes along the path to - * do the lookup via call_rcu. - */ - rcu_read_lock(); - irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq); - rcu_read_unlock(); - - /* - * If found in radix tree, then fine. - * Else fallback to linear lookup - this should not happen in practice - * as it means that we failed to insert the node in the radix tree. - */ - return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq); -} -EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup); - -/** - * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping. - * @domain: domain owning this hardware interrupt - * @virq: linux irq number - * @hwirq: hardware irq number in that domain space - * - * This is for use by irq controllers that use a radix tree reverse - * mapping for fast lookup. - */ -void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq, - irq_hw_number_t hwirq) -{ - struct irq_data *irq_data = irq_get_irq_data(virq); - - if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) - return; - - if (virq) { - mutex_lock(&revmap_trees_mutex); - radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); - mutex_unlock(&revmap_trees_mutex); - } -} -EXPORT_SYMBOL_GPL(irq_radix_revmap_insert); - /** * irq_linear_revmap() - Find a linux irq from a hw irq number. * @domain: domain owning this hardware interrupt -- GitLab From 9844a5524ec532aee826c35e3031637c7fc8287b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 3 Jun 2012 22:04:38 -0700 Subject: [PATCH 2501/5711] irqdomain: Fix irq_create_direct_mapping() to test irq_domain type. irq_create_direct_mapping can only be used with the NOMAP type. Make the function test to ensure it is passed the correct type of irq_domain. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Cc: Rob Herring --- kernel/irq/irqdomain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index f540bb1eff84..c0e638ba9c2a 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -481,8 +481,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) if (domain == NULL) domain = irq_default_domain; - BUG_ON(domain == NULL); - WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); + if (WARN_ON(!domain || domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP)) + return 0; virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); if (!virq) { -- GitLab From 39012f68058e845b63b98fc07f37cf631dddbed3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 11 Jul 2012 14:22:56 +0100 Subject: [PATCH 2502/5711] via: Remove bogus if check Reported-by: Signed-off-by: Alan Cox Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44331 Signed-off-by: Jiri Kosina --- drivers/video/sis/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c index 66de832361cc..f082ae55c0c9 100644 --- a/drivers/video/sis/init.c +++ b/drivers/video/sis/init.c @@ -2628,7 +2628,8 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, else if(VCLK >= 135) data = 0x02; if(SiS_Pr->ChipType == SIS_540) { - if((VCLK == 203) || (VCLK < 234)) data = 0x02; + /* Was == 203 or < 234 which made no sense */ + if (VCLK < 234) data = 0x02; } if(SiS_Pr->ChipType < SIS_315H) { -- GitLab From 9bbeb6663ea2f069bd3bb6387fe7a824def21064 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:27 +0000 Subject: [PATCH 2503/5711] IB/mthca: Warning about event for non-existent QPs should show event type Events received for non-existent QPs should generate a warning that includes the event type that was received. Signed-off-by: Dotan Barak Reviewed-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 9601049e14d0..c3074a1d34ed 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -247,7 +247,8 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn, spin_unlock(&dev->qp_table.lock); if (!qp) { - mthca_warn(dev, "Async event for bogus QP %08x\n", qpn); + mthca_warn(dev, "Async event %d for bogus QP %08x\n", + event_type, qpn); return; } -- GitLab From 16551d450146eeba29ae3933560a2ed4968b23ce Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:28 +0000 Subject: [PATCH 2504/5711] IB/mthca: Fill in sq_sig_type in query QP The query QP code was didn't fill that attribute, do that. Signed-off-by: Dotan Barak Reviewed-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index c3074a1d34ed..26a684536109 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -502,6 +502,7 @@ done: qp_attr->cap.max_inline_data = qp->max_inline_data; qp_init_attr->cap = qp_attr->cap; + qp_init_attr->sq_sig_type = qp->sq_policy; out_mailbox: mthca_free_mailbox(dev, mailbox); -- GitLab From 47e956b2a6a4539f948ff2b85dfd259704dc5021 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:29 +0000 Subject: [PATCH 2505/5711] IB/mlx4: Fill the masked_atomic_cap attribute in query device When the user queries for device capabilities, fill in the masked_atomic_cap attribute with the real support level of atomic capabilities instead of using a hard coded value. Signed-off-by: Dotan Barak Reviewed-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 3530c41fcd1f..07efe4b84a74 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -157,7 +157,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay; props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ? IB_ATOMIC_HCA : IB_ATOMIC_NONE; - props->masked_atomic_cap = IB_ATOMIC_HCA; + props->masked_atomic_cap = props->atomic_cap; props->max_pkeys = dev->dev->caps.pkey_table_len[1]; props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms; props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm; -- GitLab From f457ce471c522cadf697b873e2cf46e458e90bef Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:30 +0000 Subject: [PATCH 2506/5711] mlx4_core: Remove double function declarations Spotted four duplicate declarations in icm.h, remove them. Signed-off-by: Dotan Barak Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/icm.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index b10c07a1dc1a..19e4efc0b342 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -81,13 +81,7 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, u64 virt, int obj_size, int nobj, int reserved, int use_lowmem, int use_coherent); void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); static inline void mlx4_icm_first(struct mlx4_icm *icm, struct mlx4_icm_iter *iter) -- GitLab From 87d4abda83a125dec65181a6ecce3035db76d46a Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:31 +0000 Subject: [PATCH 2507/5711] IB/cm: Destroy idr as part of the module init error flow Clean the idr as part of the error flow since it is a resource too. Signed-off-by: Dotan Barak Reviewed-by: Sean Hefty Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index c889aaef3416..d67999f6e34a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3848,24 +3848,28 @@ static int __init ib_cm_init(void) INIT_LIST_HEAD(&cm.timewait_list); ret = class_register(&cm_class); - if (ret) - return -ENOMEM; + if (ret) { + ret = -ENOMEM; + goto error1; + } cm.wq = create_workqueue("ib_cm"); if (!cm.wq) { ret = -ENOMEM; - goto error1; + goto error2; } ret = ib_register_client(&cm_client); if (ret) - goto error2; + goto error3; return 0; -error2: +error3: destroy_workqueue(cm.wq); -error1: +error2: class_unregister(&cm_class); +error1: + idr_destroy(&cm.local_id_table); return ret; } -- GitLab From 240a9207aae24916dba7070aa7047c3732102cb8 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 11 Jul 2012 15:39:32 +0000 Subject: [PATCH 2508/5711] net/mlx4_core: Free ICM table in case of error In mlx4_init_icm_table(), free the allocated table if we failed to allocate memory to its entries. Signed-off-by: Dotan Barak Reviewed-by: Yevgeny Petrilin Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/icm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index a9ade1c3cad5..88b7b3e75ab1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -413,6 +413,8 @@ err: mlx4_free_icm(dev, table->icm[i], use_coherent); } + kfree(table->icm); + return -ENOMEM; } -- GitLab From b761c0ca2e964a240d74e50da9e27dc0b3be0649 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 11 Jul 2012 17:36:34 +0200 Subject: [PATCH 2509/5711] ASoC: Free memory in the error paths of soc_of_parse_audio_routing() Release the memory of the routing table before leaving the function upon errors in the device tree Signed-off-by: Matthias Kaehlcke Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 64b464ca3bc5..f219b2f7ee68 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4136,6 +4136,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, dev_err(card->dev, "Property '%s' index %d could not be read: %d\n", propname, 2 * i, ret); + kfree(routes); return -EINVAL; } ret = of_property_read_string_index(np, propname, @@ -4144,6 +4145,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, dev_err(card->dev, "Property '%s' index %d could not be read: %d\n", propname, (2 * i) + 1, ret); + kfree(routes); return -EINVAL; } } -- GitLab From 396f2feb05d7cc5549c611c05abfb4108cd1c6d6 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:42 +0300 Subject: [PATCH 2510/5711] mlx4_core: Implement mechanism for reserved Q_Keys The SR-IOV special QP tunneling mechanism uses proxy special QPs (instead of the real special QPs) for MADs on guests. These proxy QPs send their packets to a "tunnel" QP owned by the master. The master then forwards the MAD (after any required paravirtualization) to the real special QP, which sends out the MAD. For security reasons (i.e., to prevent guests from sending MADs to tunnel QPs belonging to other guests), each proxy-tunnel QP pair is assigned a unique, reserved, Q_Key. These Q_Keys are available only for proxy and tunnel QPs -- if the guest tries to use these Q_Keys with other QPs, it will fail. This patch introduces a mechanism for reserving a block of 64K Q_Keys for proxy/tunneling use. The patch introduces also two new fields into mlx4_dev: base_sqpn and base_tunnel_sqpn. In SR-IOV mode, the QP numbers for the "real," proxy, and tunnel sqps are added to the reserved QPN area (so that they will not change). There are 8 special QPs per port in the HCA, and each of them is assigned both a proxy and a tunnel QP, for each VF and for the PF as well in SR-IOV mode. The QPNs for these QPs are arranged as follows: 1. The real SQP numbers (8) 2. The proxy SQPs (8 * (max number of VFs + max number of PFs) 3. The tunnel SQPs (8 * (max number of VFs + max number of PFs) To support these QPs, two new fields are added to struct mlx4_dev: base_sqp: this is the QP number of the first of the real SQPs base_tunnel_sqp: this is the qp number of the first qp in the tunnel sqp region. (On guests, this is the first tunnel sqp of the 8 which are assigned to that guest). In addition, in SR-IOV mode, sqp_start is the number of the first proxy SQP in the proxy SQP region. (In guests, this is the first proxy SQP of the 8 which are assigned to that guest) Note that in non-SR-IOV mode, there are no proxies and no tunnels. In this case, sqp_start is set to sqp_base -- which minimizes code changes. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/main.c | 17 +++++++++++++++++ include/linux/mlx4/device.h | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 83afb1541a74..81154a16d6b8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -391,6 +391,23 @@ static int mlx4_how_many_lives_vf(struct mlx4_dev *dev) return ret; } +int mlx4_get_parav_qkey(struct mlx4_dev *dev, u32 qpn, u32 *qkey) +{ + u32 qk = MLX4_RESERVED_QKEY_BASE; + if (qpn >= dev->caps.base_tunnel_sqpn + 8 * MLX4_MFUNC_MAX || + qpn < dev->caps.sqp_start) + return -EINVAL; + + if (qpn >= dev->caps.base_tunnel_sqpn) + /* tunnel qp */ + qk += qpn - dev->caps.base_tunnel_sqpn; + else + qk += qpn - dev->caps.sqp_start; + *qkey = qk; + return 0; +} +EXPORT_SYMBOL(mlx4_get_parav_qkey); + int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) { struct mlx4_priv *priv = mlx4_priv(dev); diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 7fbdc89de495..c30a314e095c 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -56,6 +56,13 @@ enum { MLX4_MAX_PORTS = 2 }; +/* base qkey for use in sriov tunnel-qp/proxy-qp communication. + * These qkeys must not be allowed for general use. This is a 64k range, + * and to test for violation, we use the mask (protect against future chg). + */ +#define MLX4_RESERVED_QKEY_BASE (0xFFFF0000) +#define MLX4_RESERVED_QKEY_MASK (0xFFFF0000) + enum { MLX4_BOARD_ID_LEN = 64 }; @@ -293,6 +300,8 @@ struct mlx4_caps { int max_qp_init_rdma; int max_qp_dest_rdma; int sqp_start; + u32 base_sqpn; + u32 base_tunnel_sqpn; int num_srqs; int max_srq_wqes; int max_srq_sge; @@ -772,4 +781,6 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port); int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx); void mlx4_counter_free(struct mlx4_dev *dev, u32 idx); +int mlx4_get_parav_qkey(struct mlx4_dev *dev, u32 qpn, u32 *qkey); + #endif /* MLX4_DEVICE_H */ -- GitLab From 105c320f6ac37af30252577d419e47b39edb5843 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:43 +0300 Subject: [PATCH 2511/5711] mlx4_core: Allow guests to have IB ports Modify mlx4_dev_cap to allow IB support when SR-IOV is active. Modify mlx4_slave_cap to set the "rdma-supported" bit in its flags area, and pass that to the guests (this is done in QUERY_FUNC_CAP and its wrapper). However, we don't activate IB support quite yet -- we leave the error return at the start of mlx4_ib_add in the mlx4_ib driver. In addition, set "protected fmr supported" bit to zero in the QUERY_FUNC_CAP wrapper. Finally, in the QUERY_FUNC_CAP wrapper, we needed to add code which checks for the port type (IB or Ethernet). Previously, this was not an issue, since only Ethernet ports were supported. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/fw.c | 78 +++++++++++++++-------- drivers/net/ethernet/mellanox/mlx4/main.c | 26 +++----- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index ee9d6b0b4d20..5549f6b3bb67 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -174,6 +174,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, #define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 +#define QUERY_FUNC_CAP_FMR_OFFSET 0x8 #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10 #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14 #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x18 @@ -183,25 +184,44 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, #define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0X30 +#define QUERY_FUNC_CAP_FMR_FLAG 0x80 +#define QUERY_FUNC_CAP_FLAG_RDMA 0x40 +#define QUERY_FUNC_CAP_FLAG_ETH 0x80 + +/* when opcode modifier = 1 */ #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 +#define QUERY_FUNC_CAP_RDMA_PROPS_OFFSET 0x8 #define QUERY_FUNC_CAP_ETH_PROPS_OFFSET 0xc +#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_MAC 0x40 +#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN 0x80 + +#define QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID 0x80 + if (vhcr->op_modifier == 1) { field = vhcr->in_modifier; MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); - field = 0; /* ensure fvl bit is not set */ + field = 0; + /* ensure force vlan and force mac bits are not set */ MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_ETH_PROPS_OFFSET); + /* ensure that phy_wqe_gid bit is not set */ + MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_RDMA_PROPS_OFFSET); + } else if (vhcr->op_modifier == 0) { - field = 1 << 7; /* enable only ethernet interface */ + /* enable rdma and ethernet interfaces */ + field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA); MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); field = dev->caps.num_ports; MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); - size = 0; /* no PF behavious is set for now */ + size = 0; /* no PF behaviour is set for now */ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET); + field = 0; /* protected FMR support not available as yet */ + MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); + size = dev->caps.num_qps; MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); @@ -254,11 +274,12 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap) outbox = mailbox->buf; MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET); - if (!(field & (1 << 7))) { - mlx4_err(dev, "The host doesn't support eth interface\n"); + if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) { + mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n"); err = -EPROTONOSUPPORT; goto out; } + func_cap->flags = field; MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); func_cap->num_ports = field; @@ -297,17 +318,27 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap) if (err) goto out; - MLX4_GET(field, outbox, QUERY_FUNC_CAP_ETH_PROPS_OFFSET); - if (field & (1 << 7)) { - mlx4_err(dev, "VLAN is enforced on this port\n"); - err = -EPROTONOSUPPORT; - goto out; - } + if (dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) { + MLX4_GET(field, outbox, QUERY_FUNC_CAP_ETH_PROPS_OFFSET); + if (field & QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN) { + mlx4_err(dev, "VLAN is enforced on this port\n"); + err = -EPROTONOSUPPORT; + goto out; + } - if (field & (1 << 6)) { - mlx4_err(dev, "Force mac is enabled on this port\n"); - err = -EPROTONOSUPPORT; - goto out; + if (field & QUERY_FUNC_CAP_ETH_PROPS_FORCE_MAC) { + mlx4_err(dev, "Force mac is enabled on this port\n"); + err = -EPROTONOSUPPORT; + goto out; + } + } else if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB) { + MLX4_GET(field, outbox, QUERY_FUNC_CAP_RDMA_PROPS_OFFSET); + if (field & QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID) { + mlx4_err(dev, "phy_wqe_gid is " + "enforced on this ib port\n"); + err = -EPROTONOSUPPORT; + goto out; + } } MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); @@ -701,12 +732,7 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, u8 port_type; int err; -#define MLX4_PORT_SUPPORT_IB (1 << 0) -#define MLX4_PORT_SUGGEST_TYPE (1 << 3) -#define MLX4_PORT_DEFAULT_SENSE (1 << 4) -#define MLX4_VF_PORT_ETH_ONLY_MASK (0xff & ~MLX4_PORT_SUPPORT_IB & \ - ~MLX4_PORT_SUGGEST_TYPE & \ - ~MLX4_PORT_DEFAULT_SENSE) +#define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, @@ -722,12 +748,10 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, MLX4_GET(port_type, outbox->buf, QUERY_PORT_SUPPORTED_TYPE_OFFSET); - /* Allow only Eth port, no link sensing allowed */ - port_type &= MLX4_VF_PORT_ETH_ONLY_MASK; - - /* check eth is enabled for this port */ - if (!(port_type & 2)) - mlx4_dbg(dev, "QUERY PORT: eth not supported by host"); + /* No link sensing allowed */ + port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK; + /* set port type to currently operating port type */ + port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3); MLX4_PUT(outbox->buf, port_type, QUERY_PORT_SUPPORTED_TYPE_OFFSET); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 81154a16d6b8..58544b72bacb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -288,29 +288,19 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) /* if only ETH is supported - assign ETH */ if (dev->caps.supported_type[i] == MLX4_PORT_TYPE_ETH) dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; - /* if only IB is supported, - * assign IB only if SRIOV is off*/ + /* if only IB is supported, assign IB */ else if (dev->caps.supported_type[i] == - MLX4_PORT_TYPE_IB) { - if (dev->flags & MLX4_FLAG_SRIOV) - dev->caps.port_type[i] = - MLX4_PORT_TYPE_NONE; - else - dev->caps.port_type[i] = - MLX4_PORT_TYPE_IB; - /* if IB and ETH are supported, - * first of all check if SRIOV is on */ - } else if (dev->flags & MLX4_FLAG_SRIOV) - dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; + MLX4_PORT_TYPE_IB) + dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; else { - /* In non-SRIOV mode, we set the port type - * according to user selection of port type, - * if usere selected none, take the FW hint */ - if (port_type_array[i-1] == MLX4_PORT_TYPE_NONE) + /* if IB and ETH are supported, we set the port + * type according to user selection of port type; + * if user selected none, take the FW hint */ + if (port_type_array[i - 1] == MLX4_PORT_TYPE_NONE) dev->caps.port_type[i] = dev->caps.suggested_type[i] ? MLX4_PORT_TYPE_ETH : MLX4_PORT_TYPE_IB; else - dev->caps.port_type[i] = port_type_array[i-1]; + dev->caps.port_type[i] = port_type_array[i - 1]; } } /* -- GitLab From 6634961c14d38ef64ec284c07aecb03d3dd03b4a Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 19 Jun 2012 11:21:44 +0300 Subject: [PATCH 2512/5711] mlx4: Put physical GID and P_Key table sizes in mlx4_phys_caps struct and paravirtualize them To allow easy paravirtualization of P_Key and GID table sizes, keep paravirtualized sizes in mlx4_dev->caps, but save the actual physical sizes from FW in struct: mlx4_dev->phys_cap. In addition, in SR-IOV mode, do the following: 1. Reduce reported P_Key table size by 1. This is done to reserve the highest P_Key index for internal use, for declaring an invalid P_Key in P_Key paravirtualization. We require a P_Key index which always contain an invalid P_Key value for this purpose (i.e., one which cannot be modified by the subnet manager). The way to do this is to reduce the P_Key table size reported to the subnet manager by 1, so that it will not attempt to access the P_Key at index #127. 2. Paravirtualize the GID table size to 1. Thus, each guest sees only a single GID (at its paravirtualized index 0). In addition, since we are paravirtualizing the GID table size to 1, we add paravirtualization of the master GID event here (i.e., we do not do ib_dispatch_event() for the GUID change event on the master, since its (only) GUID never changes). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 10 ++++-- drivers/net/ethernet/mellanox/mlx4/fw.c | 43 +++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/main.c | 32 ++++++++++++++--- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 4 ++- drivers/net/ethernet/mellanox/mlx4/port.c | 11 ++++-- include/linux/mlx4/device.h | 2 ++ 6 files changed, 92 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 58c45fb5bd31..c27141fef1ab 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -184,8 +184,10 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, break; case IB_SMP_ATTR_GUID_INFO: - mlx4_ib_dispatch_event(dev, port_num, - IB_EVENT_GID_CHANGE); + /* paravirtualized master's guid is guid 0 -- does not change */ + if (!mlx4_is_master(dev->dev)) + mlx4_ib_dispatch_event(dev, port_num, + IB_EVENT_GID_CHANGE); break; default: break; @@ -487,7 +489,9 @@ void handle_port_mgmt_change_event(struct work_struct *work) mlx4_ib_dispatch_event(dev, port, IB_EVENT_PKEY_CHANGE); break; case MLX4_DEV_PMC_SUBTYPE_GUID_INFO: - mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); + /* paravirtualized master's guid is guid 0 -- does not change */ + if (!mlx4_is_master(dev->dev)) + mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); break; default: pr_warn("Unsupported subtype 0x%x for " diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 5549f6b3bb67..473d63b63b4e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -730,9 +730,12 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, { u64 def_mac; u8 port_type; + u16 short_field; int err; #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 +#define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c +#define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, @@ -755,11 +758,51 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, MLX4_PUT(outbox->buf, port_type, QUERY_PORT_SUPPORTED_TYPE_OFFSET); + + short_field = 1; /* slave max gids */ + MLX4_PUT(outbox->buf, short_field, + QUERY_PORT_CUR_MAX_GID_OFFSET); + + short_field = dev->caps.pkey_table_len[vhcr->in_modifier]; + MLX4_PUT(outbox->buf, short_field, + QUERY_PORT_CUR_MAX_PKEY_OFFSET); } return err; } +int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port, + int *gid_tbl_len, int *pkey_tbl_len) +{ + struct mlx4_cmd_mailbox *mailbox; + u32 *outbox; + u16 field; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, + MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, + MLX4_CMD_WRAPPED); + if (err) + goto out; + + outbox = mailbox->buf; + + MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET); + *gid_tbl_len = field; + + MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET); + *pkey_tbl_len = field; + +out: + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len); + int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) { struct mlx4_cmd_mailbox *mailbox; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 58544b72bacb..5df3ac40a490 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -215,6 +215,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) for (i = 1; i <= dev->caps.num_ports; ++i) { dev->caps.vl_cap[i] = dev_cap->max_vl[i]; dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; + dev->phys_caps.gid_phys_table_len[i] = dev_cap->max_gids[i]; + dev->phys_caps.pkey_phys_table_len[i] = dev_cap->max_pkeys[i]; + /* set gid and pkey table operating lengths by default + * to non-sriov values */ dev->caps.gid_table_len[i] = dev_cap->max_gids[i]; dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i]; dev->caps.port_width_cap[i] = dev_cap->max_port_width[i]; @@ -498,8 +502,13 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENODEV; } - for (i = 1; i <= dev->caps.num_ports; ++i) + for (i = 1; i <= dev->caps.num_ports; ++i) { dev->caps.port_mask[i] = dev->caps.port_type[i]; + if (mlx4_get_slave_pkey_gid_tbl_len(dev, i, + &dev->caps.gid_table_len[i], + &dev->caps.pkey_table_len[i])) + return -ENODEV; + } if (dev->caps.uar_page_size * (dev->caps.num_uars - dev->caps.reserved_uars) > @@ -536,7 +545,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev, for (port = 1; port <= dev->caps.num_ports; port++) { mlx4_CLOSE_PORT(dev, port); dev->caps.port_type[port] = port_types[port - 1]; - err = mlx4_SET_PORT(dev, port); + err = mlx4_SET_PORT(dev, port, -1); if (err) { mlx4_err(dev, "Failed to set port %d, " "aborting\n", port); @@ -722,7 +731,7 @@ static ssize_t set_port_ib_mtu(struct device *dev, mlx4_unregister_device(mdev); for (port = 1; port <= mdev->caps.num_ports; port++) { mlx4_CLOSE_PORT(mdev, port); - err = mlx4_SET_PORT(mdev, port); + err = mlx4_SET_PORT(mdev, port, -1); if (err) { mlx4_err(mdev, "Failed to set port %d, " "aborting\n", port); @@ -1173,6 +1182,17 @@ err: return -EIO; } +static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev) +{ + int i; + + for (i = 1; i <= dev->caps.num_ports; i++) { + dev->caps.gid_table_len[i] = 1; + dev->caps.pkey_table_len[i] = + dev->phys_caps.pkey_phys_table_len[i] - 1; + } +} + static int mlx4_init_hca(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -1212,6 +1232,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev) goto err_stop_fw; } + if (mlx4_is_master(dev)) + mlx4_parav_master_pf_caps(dev); + profile = default_profile; icm_size = mlx4_make_profile(dev, &profile, &dev_cap, @@ -1500,7 +1523,8 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) else dev->caps.port_ib_mtu[port] = IB_MTU_4096; - err = mlx4_SET_PORT(dev, port); + err = mlx4_SET_PORT(dev, port, mlx4_is_master(dev) ? + dev->caps.pkey_table_len[port] : -1); if (err) { mlx4_err(dev, "Failed to set port %d, aborting\n", port); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d11d12b9db4..cde6e511899f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -969,7 +969,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev, void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); -int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); +int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz); /* resource tracker functions*/ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, enum mlx4_resource resource_type, @@ -1012,6 +1012,8 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_info *cmd); int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); +int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port, + int *gid_tbl_len, int *pkey_tbl_len); int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index a8fb52992c64..90dc47542b8b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -726,14 +726,15 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, enum { MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */ MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */ + MLX4_CHANGE_PORT_PKEY_TBL_SZ = 20, MLX4_CHANGE_PORT_VL_CAP = 21, MLX4_CHANGE_PORT_MTU_CAP = 22, }; -int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) +int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz) { struct mlx4_cmd_mailbox *mailbox; - int err, vl_cap; + int err, vl_cap, pkey_tbl_flag = 0; if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) return 0; @@ -746,11 +747,17 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; + if (pkey_tbl_sz >= 0 && mlx4_is_master(dev)) { + pkey_tbl_flag = 1; + ((__be16 *) mailbox->buf)[20] = cpu_to_be16(pkey_tbl_sz); + } + /* IB VL CAP enum isn't used by the firmware, just numerical values */ for (vl_cap = 8; vl_cap >= 1; vl_cap >>= 1) { ((__be32 *) mailbox->buf)[0] = cpu_to_be32( (1 << MLX4_CHANGE_PORT_MTU_CAP) | (1 << MLX4_CHANGE_PORT_VL_CAP) | + (pkey_tbl_flag << MLX4_CHANGE_PORT_PKEY_TBL_SZ) | (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) | (vl_cap << MLX4_SET_PORT_VL_CAP)); err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index c30a314e095c..441caf1a497d 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -268,6 +268,8 @@ static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) } struct mlx4_phys_caps { + u32 gid_phys_table_len[MLX4_MAX_PORTS + 1]; + u32 pkey_phys_table_len[MLX4_MAX_PORTS + 1]; u32 num_phys_eqs; }; -- GitLab From d9c2ede63c74048dfddbb129c59ac01176b0ab71 Mon Sep 17 00:00:00 2001 From: Eldad Zack Date: Fri, 6 Jul 2012 21:31:56 +0200 Subject: [PATCH 2513/5711] sunrpc/cache.h: fix coding style Neaten code style in get_int(). Also use sizeof() instead of hard coded number as suggested by Joe Perches . Cc: Joe Perches Signed-off-by: Eldad Zack Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/cache.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f5fd6160dbca..6def1f6cc269 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -219,11 +219,17 @@ static inline int get_int(char **bpp, int *anint) char buf[50]; char *ep; int rv; - int len = qword_get(bpp, buf, 50); - if (len < 0) return -EINVAL; - if (len ==0) return -ENOENT; + int len = qword_get(bpp, buf, sizeof(buf)); + + if (len < 0) + return -EINVAL; + if (len == 0) + return -ENOENT; + rv = simple_strtol(buf, &ep, 0); - if (*ep) return -EINVAL; + if (*ep) + return -EINVAL; + *anint = rv; return 0; } -- GitLab From bbf43dc888833ac0539e437dbaeb28bfd4fbab9f Mon Sep 17 00:00:00 2001 From: Eldad Zack Date: Fri, 6 Jul 2012 21:31:57 +0200 Subject: [PATCH 2514/5711] sunrpc/cache.h: replace simple_strtoul This patch replaces the usage of simple_strtoul with kstrtoint in get_int(), since the simple_str* family doesn't account for overflow and is deprecated. Also, in this specific case, the long from strtol is silently converted to an int by the caller. As Joe Perches suggested, this patch also removes the redundant temporary variable rv, since kstrtoint() will not write to anint unless it's successful. Cc: Joe Perches Signed-off-by: Eldad Zack Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/cache.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 6def1f6cc269..af42596a82f9 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -217,8 +217,6 @@ extern int qword_get(char **bpp, char *dest, int bufsize); static inline int get_int(char **bpp, int *anint) { char buf[50]; - char *ep; - int rv; int len = qword_get(bpp, buf, sizeof(buf)); if (len < 0) @@ -226,11 +224,9 @@ static inline int get_int(char **bpp, int *anint) if (len == 0) return -ENOENT; - rv = simple_strtol(buf, &ep, 0); - if (*ep) + if (kstrtoint(buf, 0, anint)) return -EINVAL; - *anint = rv; return 0; } -- GitLab From a1ee61b8f4b56e5e6ced16b83d5098e0f4238a45 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 11 Jul 2012 22:54:05 +0200 Subject: [PATCH 2515/5711] ARM: shmobile: Take cpuidle dependencies into account correctly The sh7372's cpuidle code uses cpu_suspend() and cpu_resume() in its implementation of the .enter() callback for deeper C-states, so make ARCH_SH7372 select ARM_CPU_SUSPEND if CPU_IDLE is set to satisfy all of the build dependencies (it has to be selected for CONFIG_PM as well for the system suspend handling). [rjw: Added the subject and changelog.] Signed-off-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index df33909205e2..eedb0d1888c3 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -19,6 +19,7 @@ config ARCH_SH7372 select CPU_V7 select SH_CLK_CPG select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_CPU_SUSPEND if PM || CPU_IDLE config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" -- GitLab From 911a472aca3dac8aede558760a85ae051966dda0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 11 Jul 2012 22:55:12 +0200 Subject: [PATCH 2516/5711] ARM: shmobile: Fix build problem in pm-sh7372.c for unusual .config If neither CONFIG_SUSPEND nor CONFIG_CPU_IDLE is set in the kernel configuration file, build error occurs in arch/arm/mach-shmobile/pm-sh7372.c. Fix it by rearranging #ifdefs in that file to make the definition of sh7372_suspend_init() depend only on CONFIG_SUSPEND and the definition of sh7372_cpuidle_init() depend only on CONFIG_CPU_IDLE. Signed-off-by: Rafael J. Wysocki Acked-by: Magnus Damm --- arch/arm/mach-shmobile/pm-sh7372.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 6a23e7c449ea..792037069226 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -303,6 +303,7 @@ static void sh7372_enter_a3sm_common(int pllc0_on) sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); sh7372_enter_sysc(pllc0_on, 1 << 12); } +#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ #ifdef CONFIG_CPU_IDLE static int sh7372_do_idle_core_standby(unsigned long unused) @@ -442,7 +443,6 @@ static void sh7372_suspend_init(void) #else static void sh7372_suspend_init(void) {} #endif -#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ void __init sh7372_pm_init(void) { -- GitLab From ec29174ad2069d6768a7229eab0453e7b7343abe Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 11 Jul 2012 22:59:20 +0200 Subject: [PATCH 2517/5711] ARM: shmobile: kzm9g: defconfig enable INOTIFY_USER This is required for udev to run which is common to many user-spaces. It is my understanding that this is a requirement for automated testing conducted by Iwamatsu-san. Signed-off-by: Simon Horman Acked-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/configs/kzm9g_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index 7b2eecd6dcc5..2388c8610627 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig @@ -119,7 +119,7 @@ CONFIG_SH_DMAE=y CONFIG_ASYNC_TX_DMA=y CONFIG_STAGING=y # CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set +CONFIG_INOTIFY_USER=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set -- GitLab From 6d9252bd9a4bb1dadc1f199fd276e3464a251085 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 17 May 2012 15:52:13 +0530 Subject: [PATCH 2518/5711] clk: Add support for power of two type dividers Quite often dividers and the value programmed in the register have a relation of 'power of two', something like value div 0 1 1 2 2 4 3 8... Add support for such dividers as part of clk-divider. The clk-divider flag 'CLK_DIVIDER_POWER_OF_TWO' should be used to define such clocks. Signed-off-by: Rajendra Nayak Signed-off-by: Mike Turquette --- drivers/clk/clk-divider.c | 66 ++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 8ea11b444528..e548c4328f3c 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -30,18 +30,50 @@ #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) #define div_mask(d) ((1 << (d->width)) - 1) +#define is_power_of_two(i) !(i & ~i) + +static unsigned int _get_maxdiv(struct clk_divider *divider) +{ + if (divider->flags & CLK_DIVIDER_ONE_BASED) + return div_mask(divider); + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << div_mask(divider); + return div_mask(divider) + 1; +} + +static unsigned int _get_div(struct clk_divider *divider, unsigned int val) +{ + if (divider->flags & CLK_DIVIDER_ONE_BASED) + return val; + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << val; + return val + 1; +} + +static unsigned int _get_val(struct clk_divider *divider, u8 div) +{ + if (divider->flags & CLK_DIVIDER_ONE_BASED) + return div; + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return __ffs(div); + return div - 1; +} static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_divider *divider = to_clk_divider(hw); - unsigned int div; + unsigned int div, val; - div = readl(divider->reg) >> divider->shift; - div &= div_mask(divider); + val = readl(divider->reg) >> divider->shift; + val &= div_mask(divider); - if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) - div++; + div = _get_div(divider, val); + if (!div) { + WARN(1, "%s: Invalid divisor for clock %s\n", __func__, + __clk_get_name(hw->clk)); + return parent_rate; + } return parent_rate / div; } @@ -62,10 +94,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!rate) rate = 1; - maxdiv = (1 << divider->width); - - if (divider->flags & CLK_DIVIDER_ONE_BASED) - maxdiv--; + maxdiv = _get_maxdiv(divider); if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { parent_rate = *best_parent_rate; @@ -82,6 +111,9 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, maxdiv = min(ULONG_MAX / rate, maxdiv); for (i = 1; i <= maxdiv; i++) { + if ((divider->flags & CLK_DIVIDER_POWER_OF_TWO) + && (!is_power_of_two(i))) + continue; parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), MULT_ROUND_UP(rate, i)); now = parent_rate / i; @@ -93,9 +125,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, } if (!bestdiv) { - bestdiv = (1 << divider->width); - if (divider->flags & CLK_DIVIDER_ONE_BASED) - bestdiv--; + bestdiv = _get_maxdiv(divider); *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); } @@ -115,24 +145,22 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_divider *divider = to_clk_divider(hw); - unsigned int div; + unsigned int div, value; unsigned long flags = 0; u32 val; div = parent_rate / rate; + value = _get_val(divider, div); - if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) - div--; - - if (div > div_mask(divider)) - div = div_mask(divider); + if (value > div_mask(divider)) + value = div_mask(divider); if (divider->lock) spin_lock_irqsave(divider->lock, flags); val = readl(divider->reg); val &= ~(div_mask(divider) << divider->shift); - val |= div << divider->shift; + val |= value << divider->shift; writel(val, divider->reg); if (divider->lock) -- GitLab From 357c3f0a6c7613f7230fcaf1eb16190ed2a4b0af Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 29 Jun 2012 19:06:32 +0530 Subject: [PATCH 2519/5711] clk: Add support for rate table based dividers Some divider clks do not have any obvious relationship between the divider and the value programmed in the register. For instance, say a value of 1 could signify divide by 6 and a value of 2 could signify divide by 4 etc. Also there are dividers where not all values possible based on the bitfield width are valid. For instance a 3 bit wide bitfield can be used to program a value from 0 to 7. However its possible that only 0 to 4 are valid values. All these cases need the platform code to pass a simple table of divider/value tuple, so the framework knows the exact value to be written based on the divider calculation and can also do better error checking. This patch adds support for such rate table based dividers and as part of the support adds a new registration function 'clk_register_divider_table()' and a new macro for static definition 'DEFINE_CLK_DIVIDER_TABLE'. Signed-off-by: Rajendra Nayak Signed-off-by: Mike Turquette --- drivers/clk/clk-divider.c | 125 ++++++++++++++++++++++++++++++----- include/linux/clk-private.h | 20 +++++- include/linux/clk-provider.h | 12 ++++ 3 files changed, 139 insertions(+), 18 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index e548c4328f3c..02a4da98176b 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -32,30 +32,69 @@ #define div_mask(d) ((1 << (d->width)) - 1) #define is_power_of_two(i) !(i & ~i) +static unsigned int _get_table_maxdiv(const struct clk_div_table *table) +{ + unsigned int maxdiv = 0; + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div > maxdiv) + maxdiv = clkt->div; + return maxdiv; +} + static unsigned int _get_maxdiv(struct clk_divider *divider) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div_mask(divider); if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << div_mask(divider); + if (divider->table) + return _get_table_maxdiv(divider->table); return div_mask(divider) + 1; } +static unsigned int _get_table_div(const struct clk_div_table *table, + unsigned int val) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->val == val) + return clkt->div; + return 0; +} + static unsigned int _get_div(struct clk_divider *divider, unsigned int val) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return val; if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << val; + if (divider->table) + return _get_table_div(divider->table, val); return val + 1; } +static unsigned int _get_table_val(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return clkt->val; + return 0; +} + static unsigned int _get_val(struct clk_divider *divider, u8 div) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div; if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) return __ffs(div); + if (divider->table) + return _get_table_val(divider->table, div); return div - 1; } @@ -84,6 +123,26 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, */ #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) +static bool _is_valid_table_div(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return true; + return false; +} + +static bool _is_valid_div(struct clk_divider *divider, unsigned int div) +{ + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return is_power_of_two(div); + if (divider->table) + return _is_valid_table_div(divider->table, div); + return true; +} + static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate) { @@ -111,8 +170,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, maxdiv = min(ULONG_MAX / rate, maxdiv); for (i = 1; i <= maxdiv; i++) { - if ((divider->flags & CLK_DIVIDER_POWER_OF_TWO) - && (!is_power_of_two(i))) + if (!_is_valid_div(divider, i)) continue; parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), MULT_ROUND_UP(rate, i)); @@ -176,22 +234,11 @@ const struct clk_ops clk_divider_ops = { }; EXPORT_SYMBOL_GPL(clk_divider_ops); -/** - * clk_register_divider - register a divider clock with the clock framework - * @dev: device registering this clock - * @name: name of this clock - * @parent_name: name of clock's parent - * @flags: framework-specific flags - * @reg: register address to adjust divider - * @shift: number of bits to shift the bitfield - * @width: width of the bitfield - * @clk_divider_flags: divider-specific flags for this clock - * @lock: shared register lock for this clock - */ -struct clk *clk_register_divider(struct device *dev, const char *name, +static struct clk *_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, spinlock_t *lock) + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock) { struct clk_divider *div; struct clk *clk; @@ -217,6 +264,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name, div->flags = clk_divider_flags; div->lock = lock; div->hw.init = &init; + div->table = table; /* register the clock */ clk = clk_register(dev, &div->hw); @@ -226,3 +274,48 @@ struct clk *clk_register_divider(struct device *dev, const char *name, return clk; } + +/** + * clk_register_divider - register a divider clock with the clock framework + * @dev: device registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @reg: register address to adjust divider + * @shift: number of bits to shift the bitfield + * @width: width of the bitfield + * @clk_divider_flags: divider-specific flags for this clock + * @lock: shared register lock for this clock + */ +struct clk *clk_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock) +{ + return _register_divider(dev, name, parent_name, flags, reg, shift, + width, clk_divider_flags, NULL, lock); +} + +/** + * clk_register_divider_table - register a table based divider clock with + * the clock framework + * @dev: device registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @reg: register address to adjust divider + * @shift: number of bits to shift the bitfield + * @width: width of the bitfield + * @clk_divider_flags: divider-specific flags for this clock + * @table: array of divider/value pairs ending with a div set to 0 + * @lock: shared register lock for this clock + */ +struct clk *clk_register_divider_table(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock) +{ + return _register_divider(dev, name, parent_name, flags, reg, shift, + width, clk_divider_flags, table, lock); +} diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index eb3f84bc5325..cc9972d1429c 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -103,9 +103,9 @@ struct clk { DEFINE_CLK(_name, clk_gate_ops, _flags, \ _name##_parent_names, _name##_parents); -#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ +#define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ _flags, _reg, _shift, _width, \ - _divider_flags, _lock) \ + _divider_flags, _table, _lock) \ static struct clk _name; \ static const char *_name##_parent_names[] = { \ _parent_name, \ @@ -121,11 +121,27 @@ struct clk { .shift = _shift, \ .width = _width, \ .flags = _divider_flags, \ + .table = _table, \ .lock = _lock, \ }; \ DEFINE_CLK(_name, clk_divider_ops, _flags, \ _name##_parent_names, _name##_parents); +#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ + _flags, _reg, _shift, _width, \ + _divider_flags, _lock) \ + _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ + _flags, _reg, _shift, _width, \ + _divider_flags, NULL, _lock) + +#define DEFINE_CLK_DIVIDER_TABLE(_name, _parent_name, \ + _parent_ptr, _flags, _reg, \ + _shift, _width, _divider_flags, \ + _table, _lock) \ + _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ + _flags, _reg, _shift, _width, \ + _divider_flags, _table, _lock) \ + #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \ _reg, _shift, _width, \ _mux_flags, _lock) \ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4a0b483986c3..79caee9f1489 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -203,6 +203,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +struct clk_div_table { + unsigned int val; + unsigned int div; +}; + /** * struct clk_divider - adjustable divider clock * @@ -210,6 +215,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, * @reg: register containing the divider * @shift: shift to the divider bit field * @width: width of the divider bit field + * @table: array of value/divider pairs, last entry should have div = 0 * @lock: register lock * * Clock with an adjustable divider affecting its output frequency. Implements @@ -229,6 +235,7 @@ struct clk_divider { u8 shift; u8 width; u8 flags; + const struct clk_div_table *table; spinlock_t *lock; }; @@ -240,6 +247,11 @@ struct clk *clk_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, spinlock_t *lock); +struct clk *clk_register_divider_table(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock); /** * struct clk_mux - multiplexer clock -- GitLab From f7d8caadfd2813cbada82ce9041b13c38e8e5282 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 1 Jun 2012 14:02:47 +0530 Subject: [PATCH 2520/5711] clk: Add CLK_IS_BASIC flag to identify basic clocks Most platforms end up using a mix of basic clock types and some which use clk_hw_foo struct for filling in custom platform information when the clocks don't fit into basic types supported. In platform code, its useful to know if a clock is using a basic type or clk_hw_foo, which helps platforms know if they can safely use to_clk_hw_foo to derive the clk_hw_foo pointer from clk_hw. Mark all basic clocks with a CLK_IS_BASIC flag. Signed-off-by: Rajendra Nayak Signed-off-by: Mike Turquette --- drivers/clk/clk-divider.c | 2 +- drivers/clk/clk-fixed-factor.c | 2 +- drivers/clk/clk-fixed-rate.c | 2 +- drivers/clk/clk-gate.c | 2 +- drivers/clk/clk-mux.c | 2 +- include/linux/clk-private.h | 2 +- include/linux/clk-provider.h | 1 + 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 02a4da98176b..a9204c69148d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -253,7 +253,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, init.name = name; init.ops = &clk_divider_ops; - init.flags = flags; + init.flags = flags | CLK_IS_BASIC; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index c8c003e217ad..a4899855c0f6 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -82,7 +82,7 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, init.name = name; init.ops = &clk_fixed_factor_ops; - init.flags = flags; + init.flags = flags | CLK_IS_BASIC; init.parent_names = &parent_name; init.num_parents = 1; diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index cbd246229786..7e1464569727 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -63,7 +63,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, init.name = name; init.ops = &clk_fixed_rate_ops; - init.flags = flags; + init.flags = flags | CLK_IS_BASIC; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 578465e04be6..15114febfd92 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -130,7 +130,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, init.name = name; init.ops = &clk_gate_ops; - init.flags = flags; + init.flags = flags | CLK_IS_BASIC; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index fd36a8ea73d9..508c032edce4 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -106,7 +106,7 @@ struct clk *clk_register_mux(struct device *dev, const char *name, init.name = name; init.ops = &clk_mux_ops; - init.flags = flags; + init.flags = flags | CLK_IS_BASIC; init.parent_names = parent_names; init.num_parents = num_parents; diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index cc9972d1429c..9c7f5807824b 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -64,7 +64,7 @@ struct clk { .parent_names = _parent_names, \ .num_parents = ARRAY_SIZE(_parent_names), \ .parents = _parents, \ - .flags = _flags, \ + .flags = _flags | CLK_IS_BASIC, \ } #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 79caee9f1489..0236f58f3e65 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -25,6 +25,7 @@ #define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ #define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ #define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ +#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ struct clk_hw; -- GitLab From dc4cd941c900fda27f0146ab615122426229de73 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 15:12:42 +0100 Subject: [PATCH 2521/5711] clk: Constify struct clk_init_data Allow drivers to declare their clk_init_data const, the framework really shouldn't be modifying the data. Signed-off-by: Mark Brown Signed-off-by: Mike Turquette --- include/linux/clk-provider.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 0236f58f3e65..06ad617664a2 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -144,7 +144,7 @@ struct clk_init_data { */ struct clk_hw { struct clk *clk; - struct clk_init_data *init; + const struct clk_init_data *init; }; /* -- GitLab From f05259a6ffa40097b5565f25c3fcf833a9d3ecf5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 17 May 2012 10:04:57 +0100 Subject: [PATCH 2522/5711] clk: wm831x: Add initial WM831x clock driver The WM831x and WM832x series of PMICs contain a flexible clocking subsystem intended to provide always on and system core clocks. It features: - A 32.768kHz crystal oscillator which can optionally be used to pass through an externally generated clock. - A FLL which can be clocked from either the 32.768kHz oscillator or the CLKIN pin. - A CLKOUT pin which can bring out either the oscillator or the FLL output. - The 32.768kHz clock can also optionally be brought out on the GPIO pins of the device. This driver fully supports the 32.768kHz oscillator and CLKOUT. The FLL is supported only in AUTO mode, the full flexibility of the FLL cannot currently be used. Due to a lack of access to systems where the core SoC has been converted to use the generic clock API this driver has been compile tested only. Signed-off-by: Mark Brown Signed-off-by: Mike Turquette --- MAINTAINERS | 1 + drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 3 + drivers/clk/clk-wm831x.c | 428 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 439 insertions(+) create mode 100644 drivers/clk/clk-wm831x.c diff --git a/MAINTAINERS b/MAINTAINERS index 03df1d15ebf3..51b2e1c1585b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7577,6 +7577,7 @@ W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* +F: drivers/clk/clk-wm83*.c F: drivers/leds/leds-wm83*.c F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4864407e3fc4..3f99b9099658 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -34,4 +34,11 @@ config COMMON_CLK_DEBUG clk_flags, clk_prepare_count, clk_enable_count & clk_notifier_count. +config COMMON_CLK_WM831X + tristate "Clock driver for WM831x/2x PMICs" + depends on MFD_WM831X + ---help--- + Supports the clocking subsystem of the WM831x/2x series of + PMICs from Wolfson Microlectronics. + endmenu diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b9a5158a30b1..b679f117f3cc 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ # SoCs specific obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_PLAT_SPEAR) += spear/ + +# Chip specific +obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c new file mode 100644 index 000000000000..e7b7765e85f3 --- /dev/null +++ b/drivers/clk/clk-wm831x.c @@ -0,0 +1,428 @@ +/* + * WM831x clock control + * + * Copyright 2011-2 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * 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 + +struct wm831x_clk { + struct wm831x *wm831x; + struct clk_hw xtal_hw; + struct clk_hw fll_hw; + struct clk_hw clkout_hw; + struct clk *xtal; + struct clk *fll; + struct clk *clkout; + bool xtal_ena; +}; + +static int wm831x_xtal_is_enabled(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + xtal_hw); + + return clkdata->xtal_ena; +} + +static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + xtal_hw); + + if (clkdata->xtal_ena) + return 32768; + else + return 0; +} + +static const struct clk_ops wm831x_xtal_ops = { + .is_enabled = wm831x_xtal_is_enabled, + .recalc_rate = wm831x_xtal_recalc_rate, +}; + +static struct clk_init_data wm831x_xtal_init = { + .name = "xtal", + .ops = &wm831x_xtal_ops, + .flags = CLK_IS_ROOT, +}; + +static const unsigned long wm831x_fll_auto_rates[] = { + 2048000, + 11289600, + 12000000, + 12288000, + 19200000, + 22579600, + 24000000, + 24576000, +}; + +static int wm831x_fll_is_enabled(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n", + ret); + return true; + } + + return (ret & WM831X_FLL_ENA) != 0; +} + +static int wm831x_fll_prepare(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, + WM831X_FLL_ENA, WM831X_FLL_ENA); + if (ret != 0) + dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret); + + usleep_range(2000, 2000); + + return ret; +} + +static void wm831x_fll_unprepare(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0); + if (ret != 0) + dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret); +} + +static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n", + ret); + return 0; + } + + if (ret & WM831X_FLL_AUTO) + return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK]; + + dev_err(wm831x->dev, "FLL only supported in AUTO mode\n"); + + return 0; +} + +static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *unused) +{ + int best = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++) + if (abs(wm831x_fll_auto_rates[i] - rate) < + abs(wm831x_fll_auto_rates[best] - rate)) + best = i; + + return wm831x_fll_auto_rates[best]; +} + +static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int i; + + for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++) + if (wm831x_fll_auto_rates[i] == rate) + break; + if (i == ARRAY_SIZE(wm831x_fll_auto_rates)) + return -EINVAL; + + if (wm831x_fll_is_enabled(hw)) + return -EPERM; + + return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2, + WM831X_FLL_AUTO_FREQ_MASK, i); +} + +static const char *wm831x_fll_parents[] = { + "xtal", + "clkin", +}; + +static u8 wm831x_fll_get_parent(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + fll_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + /* AUTO mode is always clocked from the crystal */ + ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n", + ret); + return 0; + } + + if (ret & WM831X_FLL_AUTO) + return 0; + + ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n", + ret); + return 0; + } + + switch (ret & WM831X_FLL_CLK_SRC_MASK) { + case 0: + return 0; + case 1: + return 1; + default: + dev_err(wm831x->dev, "Unsupported FLL clock source %d\n", + ret & WM831X_FLL_CLK_SRC_MASK); + return 0; + } +} + +static const struct clk_ops wm831x_fll_ops = { + .is_enabled = wm831x_fll_is_enabled, + .prepare = wm831x_fll_prepare, + .unprepare = wm831x_fll_unprepare, + .round_rate = wm831x_fll_round_rate, + .recalc_rate = wm831x_fll_recalc_rate, + .set_rate = wm831x_fll_set_rate, + .get_parent = wm831x_fll_get_parent, +}; + +static struct clk_init_data wm831x_fll_init = { + .name = "fll", + .ops = &wm831x_fll_ops, + .parent_names = wm831x_fll_parents, + .num_parents = ARRAY_SIZE(wm831x_fll_parents), + .flags = CLK_SET_RATE_GATE, +}; + +static int wm831x_clkout_is_enabled(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + clkout_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n", + ret); + return true; + } + + return (ret & WM831X_CLKOUT_ENA) != 0; +} + +static int wm831x_clkout_prepare(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + clkout_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_unlock(wm831x); + if (ret != 0) { + dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret); + return ret; + } + + ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1, + WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA); + if (ret != 0) + dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret); + + wm831x_reg_lock(wm831x); + + return ret; +} + +static void wm831x_clkout_unprepare(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + clkout_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_unlock(wm831x); + if (ret != 0) { + dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret); + return; + } + + ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1, + WM831X_CLKOUT_ENA, 0); + if (ret != 0) + dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret); + + wm831x_reg_lock(wm831x); +} + +static const char *wm831x_clkout_parents[] = { + "xtal", + "fll", +}; + +static u8 wm831x_clkout_get_parent(struct clk_hw *hw) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + clkout_hw); + struct wm831x *wm831x = clkdata->wm831x; + int ret; + + ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n", + ret); + return 0; + } + + if (ret & WM831X_CLKOUT_SRC) + return 0; + else + return 1; +} + +static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent) +{ + struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, + clkout_hw); + struct wm831x *wm831x = clkdata->wm831x; + + return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1, + WM831X_CLKOUT_SRC, + parent << WM831X_CLKOUT_SRC_SHIFT); +} + +static const struct clk_ops wm831x_clkout_ops = { + .is_enabled = wm831x_clkout_is_enabled, + .prepare = wm831x_clkout_prepare, + .unprepare = wm831x_clkout_unprepare, + .get_parent = wm831x_clkout_get_parent, + .set_parent = wm831x_clkout_set_parent, +}; + +static struct clk_init_data wm831x_clkout_init = { + .name = "clkout", + .ops = &wm831x_clkout_ops, + .parent_names = wm831x_clkout_parents, + .num_parents = ARRAY_SIZE(wm831x_clkout_parents), + .flags = CLK_SET_RATE_PARENT, +}; + +static __devinit int wm831x_clk_probe(struct platform_device *pdev) +{ + struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); + struct wm831x_clk *clkdata; + int ret; + + clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL); + if (!clkdata) + return -ENOMEM; + + /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */ + ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2); + if (ret < 0) { + dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n", + ret); + return ret; + } + clkdata->xtal_ena = ret & WM831X_XTAL_ENA; + + clkdata->xtal_hw.init = &wm831x_xtal_init; + clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw); + if (!clkdata->xtal) + return -EINVAL; + + clkdata->fll_hw.init = &wm831x_fll_init; + clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw); + if (!clkdata->fll) { + ret = -EINVAL; + goto err_xtal; + } + + clkdata->clkout_hw.init = &wm831x_clkout_init; + clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw); + if (!clkdata->clkout) { + ret = -EINVAL; + goto err_fll; + } + + dev_set_drvdata(&pdev->dev, clkdata); + + return 0; + +err_fll: + clk_unregister(clkdata->fll); +err_xtal: + clk_unregister(clkdata->xtal); + return ret; +} + +static int __devexit wm831x_clk_remove(struct platform_device *pdev) +{ + struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev); + + clk_unregister(clkdata->clkout); + clk_unregister(clkdata->fll); + clk_unregister(clkdata->xtal); + + return 0; +} + +static struct platform_driver wm831x_clk_driver = { + .probe = wm831x_clk_probe, + .remove = __devexit_p(wm831x_clk_remove), + .driver = { + .name = "wm831x-clk", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(wm831x_clk_driver); + +/* Module information */ +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("WM831x clock driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm831x-clk"); -- GitLab From 9ca1c5a4bf4105d6f2f2a46892495953dd3e2fec Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 6 Jun 2012 14:41:30 +0530 Subject: [PATCH 2523/5711] clk: cache parent clocks only for muxes caching parent clocks makes sense only when a clock has more than one parent (mux clocks). Avoid doing this for every other clock. Signed-off-by: Rajendra Nayak [mturquette@linaro.org: removed extra parentheses] Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9a1eb0cfa95f..46317cbc088f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1235,8 +1235,8 @@ int __clk_init(struct device *dev, struct clk *clk) * If clk->parents is not NULL we skip this entire block. This allows * for clock drivers to statically initialize clk->parents. */ - if (clk->num_parents && !clk->parents) { - clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents), + if (clk->num_parents > 1 && !clk->parents) { + clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), GFP_KERNEL); /* * __clk_lookup returns NULL for parents that have not been -- GitLab From 50667d63085af108f625c83102430c1d74931d78 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Jun 2012 23:44:25 +0200 Subject: [PATCH 2524/5711] ARM: u300: convert to common clock This converts the U300 clock implementation over to use the common struct clk and moves the implementation down into drivers/clk. Since VCO isn't used in tree it was removed, it's not hard to put it back in if need be. Signed-off-by: Linus Walleij [mturquette@linaro.org: trivial Makefile conflict] Signed-off-by: Mike Turquette --- arch/arm/Kconfig | 2 +- arch/arm/mach-u300/Makefile | 2 +- arch/arm/mach-u300/clock.c | 1504 ------------------------ arch/arm/mach-u300/clock.h | 50 - arch/arm/mach-u300/core.c | 21 +- arch/arm/mach-u300/timer.c | 2 +- drivers/clk/Makefile | 3 +- drivers/clk/clk-u300.c | 746 ++++++++++++ include/linux/platform_data/clk-u300.h | 1 + 9 files changed, 763 insertions(+), 1568 deletions(-) delete mode 100644 arch/arm/mach-u300/clock.c delete mode 100644 arch/arm/mach-u300/clock.h create mode 100644 drivers/clk/clk-u300.c create mode 100644 include/linux/platform_data/clk-u300.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a91009c61870..c59853738967 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -888,7 +888,7 @@ config ARCH_U300 select ARM_VIC select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP - select HAVE_MACH_CLKDEV + select COMMON_CLK select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index fd3a5c382f47..7e47d37aeb0e 100644 --- a/arch/arm/mach-u300/Makefile +++ b/arch/arm/mach-u300/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U300 machine. # -obj-y := core.o clock.o timer.o +obj-y := core.o timer.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c deleted file mode 100644 index 5535dd0a78c9..000000000000 --- a/arch/arm/mach-u300/clock.c +++ /dev/null @@ -1,1504 +0,0 @@ -/* - * - * arch/arm/mach-u300/clock.c - * - * - * Copyright (C) 2007-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * Define clocks in the app platform. - * Author: Linus Walleij - * Author: Jonas Aaberg - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "clock.h" - -/* - * TODO: - * - move all handling of the CCR register into this file and create - * a spinlock for the CCR register - * - switch to the clkdevice lookup mechanism that maps clocks to - * device ID:s instead when it becomes available in kernel 2.6.29. - * - implement rate get/set for all clocks that need it. - */ - -/* - * Syscon clock I/O registers lock so clock requests don't collide - * NOTE: this is a local lock only used to lock access to clock and - * reset registers in syscon. - */ -static DEFINE_SPINLOCK(syscon_clkreg_lock); -static DEFINE_SPINLOCK(syscon_resetreg_lock); - -/* - * The clocking hierarchy currently looks like this. - * NOTE: the idea is NOT to show how the clocks are routed on the chip! - * The ideas is to show dependencies, so a clock higher up in the - * hierarchy has to be on in order for another clock to be on. Now, - * both CPU and DMA can actually be on top of the hierarchy, and that - * is not modeled currently. Instead we have the backbone AMBA bus on - * top. This bus cannot be programmed in any way but conceptually it - * needs to be active for the bridges and devices to transport data. - * - * Please be aware that a few clocks are hw controlled, which mean that - * the hw itself can turn on/off or change the rate of the clock when - * needed! - * - * AMBA bus - * | - * +- CPU - * +- FSMC NANDIF NAND Flash interface - * +- SEMI Shared Memory interface - * +- ISP Image Signal Processor (U335 only) - * +- CDS (U335 only) - * +- DMA Direct Memory Access Controller - * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL) - * +- APEX - * +- VIDEO_ENC AVE2/3 Video Encoder - * +- XGAM Graphics Accelerator Controller - * +- AHB - * | - * +- ahb:0 AHB Bridge - * | | - * | +- ahb:1 INTCON Interrupt controller - * | +- ahb:3 MSPRO Memory Stick Pro controller - * | +- ahb:4 EMIF External Memory interface - * | - * +- fast:0 FAST bridge - * | | - * | +- fast:1 MMCSD MMC/SD card reader controller - * | +- fast:2 I2S0 PCM I2S channel 0 controller - * | +- fast:3 I2S1 PCM I2S channel 1 controller - * | +- fast:4 I2C0 I2C channel 0 controller - * | +- fast:5 I2C1 I2C channel 1 controller - * | +- fast:6 SPI SPI controller - * | +- fast:7 UART1 Secondary UART (U335 only) - * | - * +- slow:0 SLOW bridge - * | - * +- slow:1 SYSCON (not possible to control) - * +- slow:2 WDOG Watchdog - * +- slow:3 UART0 primary UART - * +- slow:4 TIMER_APP Application timer - used in Linux - * +- slow:5 KEYPAD controller - * +- slow:6 GPIO controller - * +- slow:7 RTC controller - * +- slow:8 BT Bus Tracer (not used currently) - * +- slow:9 EH Event Handler (not used currently) - * +- slow:a TIMER_ACC Access style timer (not used currently) - * +- slow:b PPM (U335 only, what is that?) - */ - -/* - * Reset control functions. We remember if a block has been - * taken out of reset and don't remove the reset assertion again - * and vice versa. Currently we only remove resets so the - * enablement function is defined out. - */ -static void syscon_block_reset_enable(struct clk *clk) -{ - u16 val; - unsigned long iflags; - - /* Not all blocks support resetting */ - if (!clk->res_reg || !clk->res_mask) - return; - spin_lock_irqsave(&syscon_resetreg_lock, iflags); - val = readw(clk->res_reg); - val |= clk->res_mask; - writew(val, clk->res_reg); - spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); - clk->reset = true; -} - -static void syscon_block_reset_disable(struct clk *clk) -{ - u16 val; - unsigned long iflags; - - /* Not all blocks support resetting */ - if (!clk->res_reg || !clk->res_mask) - return; - spin_lock_irqsave(&syscon_resetreg_lock, iflags); - val = readw(clk->res_reg); - val &= ~clk->res_mask; - writew(val, clk->res_reg); - spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); - clk->reset = false; -} - -int __clk_get(struct clk *clk) -{ - u16 val; - - /* The MMC and MSPRO clocks need some special set-up */ - if (!strcmp(clk->name, "MCLK")) { - /* Set default MMC clock divisor to 18.9 MHz */ - writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); - /* Disable the MMC feedback clock */ - val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; - /* Disable MSPRO frequency */ - val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); - } - if (!strcmp(clk->name, "MSPRO")) { - val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); - /* Disable the MMC feedback clock */ - val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; - /* Enable MSPRO frequency */ - val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); - } - return 1; -} -EXPORT_SYMBOL(__clk_get); - -void __clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(__clk_put); - -static void syscon_clk_disable(struct clk *clk) -{ - unsigned long iflags; - - /* Don't touch the hardware controlled clocks */ - if (clk->hw_ctrld) - return; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -static void syscon_clk_enable(struct clk *clk) -{ - unsigned long iflags; - - /* Don't touch the hardware controlled clocks */ - if (clk->hw_ctrld) - return; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -static u16 syscon_clk_get_rate(void) -{ - u16 val; - unsigned long iflags; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); - return val; -} - -#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER -static void enable_i2s0_vcxo(void) -{ - u16 val; - unsigned long iflags; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - /* Set I2S0 to use the VCXO 26 MHz clock */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val |= U300_SYSCON_CCR_TURN_VCXO_ON; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val |= U300_SYSCON_CCR_I2S0_USE_VCXO; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); - val |= U300_SYSCON_CEFR_I2S0_CLK_EN; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -static void enable_i2s1_vcxo(void) -{ - u16 val; - unsigned long iflags; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - /* Set I2S1 to use the VCXO 26 MHz clock */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val |= U300_SYSCON_CCR_TURN_VCXO_ON; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val |= U300_SYSCON_CCR_I2S1_USE_VCXO; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); - val |= U300_SYSCON_CEFR_I2S1_CLK_EN; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -static void disable_i2s0_vcxo(void) -{ - u16 val; - unsigned long iflags; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - /* Disable I2S0 use of the VCXO 26 MHz clock */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Deactivate VCXO if no one else is using VCXO */ - if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO)) - val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); - val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -static void disable_i2s1_vcxo(void) -{ - u16 val; - unsigned long iflags; - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - /* Disable I2S1 use of the VCXO 26 MHz clock */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Deactivate VCXO if no one else is using VCXO */ - if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO)) - val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); - val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} -#endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */ - - -static void syscon_clk_rate_set_mclk(unsigned long rate) -{ - u16 val; - u32 reg; - unsigned long iflags; - - switch (rate) { - case 18900000: - val = 0x0054; - break; - case 20800000: - val = 0x0044; - break; - case 23100000: - val = 0x0043; - break; - case 26000000: - val = 0x0033; - break; - case 29700000: - val = 0x0032; - break; - case 34700000: - val = 0x0022; - break; - case 41600000: - val = 0x0021; - break; - case 52000000: - val = 0x0011; - break; - case 104000000: - val = 0x0000; - break; - default: - printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n", - rate); - return; - } - - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & - ~U300_SYSCON_MMF0R_MASK; - writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} - -void syscon_clk_rate_set_cpuclk(unsigned long rate) -{ - u16 val; - unsigned long iflags; - - switch (rate) { - case 13000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER; - break; - case 52000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE; - break; - case 104000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH; - break; - case 208000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST; - break; - default: - return; - } - spin_lock_irqsave(&syscon_clkreg_lock, iflags); - val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) & - ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); -} -EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk); - -void clk_disable(struct clk *clk) -{ - unsigned long iflags; - - spin_lock_irqsave(&clk->lock, iflags); - if (clk->usecount > 0 && !(--clk->usecount)) { - /* some blocks lack clocking registers and cannot be disabled */ - if (clk->disable) - clk->disable(clk); - if (likely((u32)clk->parent)) - clk_disable(clk->parent); - } -#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER - if (unlikely(!strcmp(clk->name, "I2S0"))) - disable_i2s0_vcxo(); - if (unlikely(!strcmp(clk->name, "I2S1"))) - disable_i2s1_vcxo(); -#endif - spin_unlock_irqrestore(&clk->lock, iflags); -} -EXPORT_SYMBOL(clk_disable); - -int clk_enable(struct clk *clk) -{ - int ret = 0; - unsigned long iflags; - - spin_lock_irqsave(&clk->lock, iflags); - if (clk->usecount++ == 0) { - if (likely((u32)clk->parent)) - ret = clk_enable(clk->parent); - - if (unlikely(ret != 0)) - clk->usecount--; - else { - /* remove reset line (we never enable reset again) */ - syscon_block_reset_disable(clk); - /* clocks without enable function are always on */ - if (clk->enable) - clk->enable(clk); -#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER - if (unlikely(!strcmp(clk->name, "I2S0"))) - enable_i2s0_vcxo(); - if (unlikely(!strcmp(clk->name, "I2S1"))) - enable_i2s1_vcxo(); -#endif - } - } - spin_unlock_irqrestore(&clk->lock, iflags); - return ret; - -} -EXPORT_SYMBOL(clk_enable); - -/* Returns the clock rate in Hz */ -static unsigned long clk_get_rate_cpuclk(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 52000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - return 104000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - return 208000000; - default: - break; - } - return clk->rate; -} - -static unsigned long clk_get_rate_ahb_clk(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 6500000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 26000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - return 52000000; - default: - break; - } - return clk->rate; - -} - -static unsigned long clk_get_rate_emif_clk(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 52000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - return 104000000; - default: - break; - } - return clk->rate; - -} - -static unsigned long clk_get_rate_xgamclk(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 6500000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 26000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - return 52000000; - default: - break; - } - - return clk->rate; -} - -static unsigned long clk_get_rate_mclk(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - /* - * Here, the 208 MHz PLL gets shut down and the always - * on 13 MHz PLL used for RTC etc kicks into use - * instead. - */ - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - { - /* - * This clock is under program control. The register is - * divided in two nybbles, bit 7-4 gives cycles-1 to count - * high, bit 3-0 gives cycles-1 to count low. Distribute - * these with no more than 1 cycle difference between - * low and high and add low and high to get the actual - * divisor. The base PLL is 208 MHz. Writing 0x00 will - * divide by 1 and 1 so the highest frequency possible - * is 104 MHz. - * - * e.g. 0x54 => - * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz - */ - u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & - U300_SYSCON_MMF0R_MASK; - switch (val) { - case 0x0054: - return 18900000; - case 0x0044: - return 20800000; - case 0x0043: - return 23100000; - case 0x0033: - return 26000000; - case 0x0032: - return 29700000; - case 0x0022: - return 34700000; - case 0x0021: - return 41600000; - case 0x0011: - return 52000000; - case 0x0000: - return 104000000; - default: - break; - } - } - default: - break; - } - - return clk->rate; -} - -static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk) -{ - u16 val; - - val = syscon_clk_get_rate(); - - switch (val) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - return 26000000; - default: - break; - } - - return clk->rate; -} - -unsigned long clk_get_rate(struct clk *clk) -{ - if (clk->get_rate) - return clk->get_rate(clk); - else - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate) -{ - if (rate <= 18900000) - return 18900000; - if (rate <= 20800000) - return 20800000; - if (rate <= 23100000) - return 23100000; - if (rate <= 26000000) - return 26000000; - if (rate <= 29700000) - return 29700000; - if (rate <= 34700000) - return 34700000; - if (rate <= 41600000) - return 41600000; - if (rate <= 52000000) - return 52000000; - return -EINVAL; -} - -static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate) -{ - if (rate <= 13000000) - return 13000000; - if (rate <= 52000000) - return 52000000; - if (rate <= 104000000) - return 104000000; - if (rate <= 208000000) - return 208000000; - return -EINVAL; -} - -/* - * This adjusts a requested rate to the closest exact rate - * a certain clock can provide. For a fixed clock it's - * mostly clk->rate. - */ -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - /* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */ - /* Else default to fixed value */ - - if (clk->round_rate) { - return (long) clk->round_rate(clk, rate); - } else { - printk(KERN_ERR "clock: Failed to round rate of %s\n", - clk->name); - } - return (long) clk->rate; -} -EXPORT_SYMBOL(clk_round_rate); - -static int clk_set_rate_mclk(struct clk *clk, unsigned long rate) -{ - syscon_clk_rate_set_mclk(clk_round_rate(clk, rate)); - return 0; -} - -static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate) -{ - syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate)); - return 0; -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - /* TODO: set for EMIFCLK and AHBCLK */ - /* Else assume the clock is fixed and fail */ - if (clk->set_rate) { - return clk->set_rate(clk, rate); - } else { - printk(KERN_ERR "clock: Failed to set %s to %ld hz\n", - clk->name, rate); - return -EINVAL; - } -} -EXPORT_SYMBOL(clk_set_rate); - -/* - * Clock definitions. The clock parents are set to respective - * bridge and the clock framework makes sure that the clocks have - * parents activated and are brought out of reset when in use. - * - * Clocks that have hw_ctrld = true are hw controlled, and the hw - * can by itself turn these clocks on and off. - * So in other words, we don't really have to care about them. - */ - -static struct clk amba_clk = { - .name = "AMBA", - .rate = 52000000, /* this varies! */ - .hw_ctrld = true, - .reset = false, - .lock = __SPIN_LOCK_UNLOCKED(amba_clk.lock), -}; - -/* - * These blocks are connected directly to the AMBA bus - * with no bridge. - */ - -static struct clk cpu_clk = { - .name = "CPU", - .parent = &amba_clk, - .rate = 208000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_CPU_RESET_EN, - .set_rate = clk_set_rate_cpuclk, - .get_rate = clk_get_rate_cpuclk, - .round_rate = clk_round_rate_cpuclk, - .lock = __SPIN_LOCK_UNLOCKED(cpu_clk.lock), -}; - -static struct clk nandif_clk = { - .name = "FSMC", - .parent = &amba_clk, - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_NANDIF_RESET_EN, - .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(nandif_clk.lock), -}; - -static struct clk semi_clk = { - .name = "SEMI", - .parent = &amba_clk, - .rate = 0, /* FIXME */ - /* It is not possible to reset SEMI */ - .hw_ctrld = false, - .reset = false, - .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(semi_clk.lock), -}; - -#ifdef CONFIG_MACH_U300_BS335 -static struct clk isp_clk = { - .name = "ISP", - .parent = &amba_clk, - .rate = 0, /* FIXME */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_ISP_RESET_EN, - .clk_val = U300_SYSCON_SBCER_ISP_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(isp_clk.lock), -}; - -static struct clk cds_clk = { - .name = "CDS", - .parent = &amba_clk, - .rate = 0, /* FIXME */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_CDS_RESET_EN, - .clk_val = U300_SYSCON_SBCER_CDS_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(cds_clk.lock), -}; -#endif - -static struct clk dma_clk = { - .name = "DMA", - .parent = &amba_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_DMAC_RESET_EN, - .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(dma_clk.lock), -}; - -static struct clk aaif_clk = { - .name = "AAIF", - .parent = &amba_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_AAIF_RESET_EN, - .clk_val = U300_SYSCON_SBCER_AAIF_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(aaif_clk.lock), -}; - -static struct clk apex_clk = { - .name = "APEX", - .parent = &amba_clk, - .rate = 0, /* FIXME */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_APEX_RESET_EN, - .clk_val = U300_SYSCON_SBCER_APEX_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(apex_clk.lock), -}; - -static struct clk video_enc_clk = { - .name = "VIDEO_ENC", - .parent = &amba_clk, - .rate = 208000000, /* this varies! */ - .hw_ctrld = false, - .reset = false, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - /* This has XGAM in the name but refers to the video encoder */ - .res_mask = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN, - .clk_val = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock), -}; - -static struct clk xgam_clk = { - .name = "XGAMCLK", - .parent = &amba_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_XGAM_RESET_EN, - .clk_val = U300_SYSCON_SBCER_XGAM_CLK_EN, - .get_rate = clk_get_rate_xgamclk, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(xgam_clk.lock), -}; - -/* This clock is used to activate the video encoder */ -static struct clk ahb_clk = { - .name = "AHB", - .parent = &amba_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = false, /* This one is set to false due to HW bug */ - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_AHB_RESET_EN, - .clk_val = U300_SYSCON_SBCER_AHB_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_ahb_clk, - .lock = __SPIN_LOCK_UNLOCKED(ahb_clk.lock), -}; - - -/* - * Clocks on the AHB bridge - */ - -static struct clk ahb_subsys_clk = { - .name = "AHB_SUBSYS", - .parent = &amba_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = true, - .reset = false, - .clk_val = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_ahb_clk, - .lock = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock), -}; - -static struct clk intcon_clk = { - .name = "INTCON", - .parent = &ahb_subsys_clk, - .rate = 52000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_INTCON_RESET_EN, - /* INTCON can be reset but not clock-gated */ - .lock = __SPIN_LOCK_UNLOCKED(intcon_clk.lock), - -}; - -static struct clk mspro_clk = { - .name = "MSPRO", - .parent = &ahb_subsys_clk, - .rate = 0, /* FIXME */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_MSPRO_RESET_EN, - .clk_val = U300_SYSCON_SBCER_MSPRO_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(mspro_clk.lock), -}; - -static struct clk emif_clk = { - .name = "EMIF", - .parent = &ahb_subsys_clk, - .rate = 104000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, - .res_mask = U300_SYSCON_RRR_EMIF_RESET_EN, - .clk_val = U300_SYSCON_SBCER_EMIF_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_emif_clk, - .lock = __SPIN_LOCK_UNLOCKED(emif_clk.lock), -}; - - -/* - * Clocks on the FAST bridge - */ -static struct clk fast_clk = { - .name = "FAST_BRIDGE", - .parent = &amba_clk, - .rate = 13000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(fast_clk.lock), -}; - -/* - * The MMCI apb_pclk is hardwired to the same terminal as the - * external MCI clock. Thus this will be referenced twice. - */ -static struct clk mmcsd_clk = { - .name = "MCLK", - .parent = &fast_clk, - .rate = 18900000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_MMC_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_MMC_CLK_EN, - .get_rate = clk_get_rate_mclk, - .set_rate = clk_set_rate_mclk, - .round_rate = clk_round_rate_mclk, - .disable = syscon_clk_disable, - .enable = syscon_clk_enable, - .lock = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock), -}; - -static struct clk i2s0_clk = { - .name = "i2s0", - .parent = &fast_clk, - .rate = 26000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_i2s_i2c_spi, - .lock = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock), -}; - -static struct clk i2s1_clk = { - .name = "i2s1", - .parent = &fast_clk, - .rate = 26000000, /* this varies! */ - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_i2s_i2c_spi, - .lock = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock), -}; - -static struct clk i2c0_clk = { - .name = "I2C0", - .parent = &fast_clk, - .rate = 26000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_I2C0_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_I2C0_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_i2s_i2c_spi, - .lock = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock), -}; - -static struct clk i2c1_clk = { - .name = "I2C1", - .parent = &fast_clk, - .rate = 26000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_I2C1_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_I2C1_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_i2s_i2c_spi, - .lock = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock), -}; - -/* - * The SPI apb_pclk is hardwired to the same terminal as the - * external SPI clock. Thus this will be referenced twice. - */ -static struct clk spi_clk = { - .name = "SPI", - .parent = &fast_clk, - .rate = 26000000, /* this varies! */ - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_SPI_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_SPI_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .get_rate = clk_get_rate_i2s_i2c_spi, - .lock = __SPIN_LOCK_UNLOCKED(spi_clk.lock), -}; - -#ifdef CONFIG_MACH_U300_BS335 -static struct clk uart1_pclk = { - .name = "UART1_PCLK", - .parent = &fast_clk, - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, - .res_mask = U300_SYSCON_RFR_UART1_RESET_ENABLE, - .clk_val = U300_SYSCON_SBCER_UART1_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(uart1_pclk.lock), -}; - -/* This one is hardwired to PLL13 */ -static struct clk uart1_clk = { - .name = "UART1_CLK", - .rate = 13000000, - .hw_ctrld = true, - .lock = __SPIN_LOCK_UNLOCKED(uart1_clk.lock), -}; -#endif - - -/* - * Clocks on the SLOW bridge - */ -static struct clk slow_clk = { - .name = "SLOW_BRIDGE", - .parent = &amba_clk, - .rate = 13000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN, - .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(slow_clk.lock), -}; - -/* TODO: implement SYSCON clock? */ - -static struct clk wdog_clk = { - .name = "WDOG", - .parent = &slow_clk, - .hw_ctrld = false, - .rate = 32768, - .reset = false, - /* This is always on, cannot be enabled/disabled or reset */ - .lock = __SPIN_LOCK_UNLOCKED(wdog_clk.lock), -}; - -static struct clk uart0_pclk = { - .name = "UART0_PCLK", - .parent = &slow_clk, - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_UART_RESET_EN, - .clk_val = U300_SYSCON_SBCER_UART_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(uart0_pclk.lock), -}; - -/* This one is hardwired to PLL13 */ -static struct clk uart0_clk = { - .name = "UART0_CLK", - .parent = &slow_clk, - .rate = 13000000, - .hw_ctrld = true, - .lock = __SPIN_LOCK_UNLOCKED(uart0_clk.lock), -}; - -static struct clk keypad_clk = { - .name = "KEYPAD", - .parent = &slow_clk, - .rate = 32768, - .hw_ctrld = false, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_KEYPAD_RESET_EN, - .clk_val = U300_SYSCON_SBCER_KEYPAD_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(keypad_clk.lock), -}; - -static struct clk gpio_clk = { - .name = "GPIO", - .parent = &slow_clk, - .rate = 13000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_GPIO_RESET_EN, - .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(gpio_clk.lock), -}; - -static struct clk rtc_clk = { - .name = "RTC", - .parent = &slow_clk, - .rate = 32768, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_RTC_RESET_EN, - /* This clock is always on, cannot be enabled/disabled */ - .lock = __SPIN_LOCK_UNLOCKED(rtc_clk.lock), -}; - -static struct clk bustr_clk = { - .name = "BUSTR", - .parent = &slow_clk, - .rate = 13000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_BTR_RESET_EN, - .clk_val = U300_SYSCON_SBCER_BTR_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(bustr_clk.lock), -}; - -static struct clk evhist_clk = { - .name = "EVHIST", - .parent = &slow_clk, - .rate = 13000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_EH_RESET_EN, - .clk_val = U300_SYSCON_SBCER_EH_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(evhist_clk.lock), -}; - -static struct clk timer_clk = { - .name = "TIMER", - .parent = &slow_clk, - .rate = 13000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_ACC_TMR_RESET_EN, - .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(timer_clk.lock), -}; - -/* - * There is a binary divider in the hardware that divides - * the 13MHz PLL by 13 down to 1 MHz. - */ -static struct clk app_timer_clk = { - .name = "TIMER_APP", - .parent = &slow_clk, - .rate = 1000000, - .hw_ctrld = true, - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_APP_TMR_RESET_EN, - .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock), -}; - -#ifdef CONFIG_MACH_U300_BS335 -static struct clk ppm_clk = { - .name = "PPM", - .parent = &slow_clk, - .rate = 0, /* FIXME */ - .hw_ctrld = true, /* TODO: Look up if it is hw ctrld or not */ - .reset = true, - .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, - .res_mask = U300_SYSCON_RSR_PPM_RESET_EN, - .clk_val = U300_SYSCON_SBCER_PPM_CLK_EN, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .lock = __SPIN_LOCK_UNLOCKED(ppm_clk.lock), -}; -#endif - -#define DEF_LOOKUP(devid, clkref) \ - { \ - .dev_id = devid, \ - .clk = clkref, \ - } - -#define DEF_LOOKUP_CON(devid, conid, clkref) \ - { \ - .dev_id = devid, \ - .con_id = conid, \ - .clk = clkref, \ - } - -/* - * Here we only define clocks that are meaningful to - * look up through clockdevice. - */ -static struct clk_lookup lookups[] = { - /* Connected directly to the AMBA bus */ - DEF_LOOKUP("amba", &amba_clk), - DEF_LOOKUP("cpu", &cpu_clk), - DEF_LOOKUP("fsmc-nand", &nandif_clk), - DEF_LOOKUP("semi", &semi_clk), -#ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("isp", &isp_clk), - DEF_LOOKUP("cds", &cds_clk), -#endif - DEF_LOOKUP("dma", &dma_clk), - DEF_LOOKUP("msl", &aaif_clk), - DEF_LOOKUP("apex", &apex_clk), - DEF_LOOKUP("video_enc", &video_enc_clk), - DEF_LOOKUP("xgam", &xgam_clk), - DEF_LOOKUP("ahb", &ahb_clk), - /* AHB bridge clocks */ - DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk), - DEF_LOOKUP("intcon", &intcon_clk), - DEF_LOOKUP_CON("intcon", "apb_pclk", &intcon_clk), - DEF_LOOKUP("mspro", &mspro_clk), - DEF_LOOKUP("pl172", &emif_clk), - DEF_LOOKUP_CON("pl172", "apb_pclk", &emif_clk), - /* FAST bridge clocks */ - DEF_LOOKUP("fast", &fast_clk), - DEF_LOOKUP("mmci", &mmcsd_clk), - DEF_LOOKUP_CON("mmci", "apb_pclk", &mmcsd_clk), - /* - * The .0 and .1 identifiers on these comes from the platform device - * .id field and are assigned when the platform devices are registered. - */ - DEF_LOOKUP("i2s.0", &i2s0_clk), - DEF_LOOKUP("i2s.1", &i2s1_clk), - DEF_LOOKUP("stu300.0", &i2c0_clk), - DEF_LOOKUP("stu300.1", &i2c1_clk), - DEF_LOOKUP("pl022", &spi_clk), - DEF_LOOKUP_CON("pl022", "apb_pclk", &spi_clk), -#ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("uart1", &uart1_clk), - DEF_LOOKUP_CON("uart1", "apb_pclk", &uart1_pclk), -#endif - /* SLOW bridge clocks */ - DEF_LOOKUP("slow", &slow_clk), - DEF_LOOKUP("coh901327_wdog", &wdog_clk), - DEF_LOOKUP("uart0", &uart0_clk), - DEF_LOOKUP_CON("uart0", "apb_pclk", &uart0_pclk), - DEF_LOOKUP("apptimer", &app_timer_clk), - DEF_LOOKUP("coh901461-keypad", &keypad_clk), - DEF_LOOKUP("u300-gpio", &gpio_clk), - DEF_LOOKUP("rtc-coh901331", &rtc_clk), - DEF_LOOKUP("bustr", &bustr_clk), - DEF_LOOKUP("evhist", &evhist_clk), - DEF_LOOKUP("timer", &timer_clk), -#ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("ppm", &ppm_clk), -#endif -}; - -static void __init clk_register(void) -{ - /* Register the lookups */ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -} - -#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) -/* - * The following makes it possible to view the status (especially - * reference count and reset status) for the clocks in the platform - * by looking into the special file /u300_clocks - */ - -/* A list of all clocks in the platform */ -static struct clk *clks[] = { - /* Top node clock for the AMBA bus */ - &amba_clk, - /* Connected directly to the AMBA bus */ - &cpu_clk, - &nandif_clk, - &semi_clk, -#ifdef CONFIG_MACH_U300_BS335 - &isp_clk, - &cds_clk, -#endif - &dma_clk, - &aaif_clk, - &apex_clk, - &video_enc_clk, - &xgam_clk, - &ahb_clk, - - /* AHB bridge clocks */ - &ahb_subsys_clk, - &intcon_clk, - &mspro_clk, - &emif_clk, - /* FAST bridge clocks */ - &fast_clk, - &mmcsd_clk, - &i2s0_clk, - &i2s1_clk, - &i2c0_clk, - &i2c1_clk, - &spi_clk, -#ifdef CONFIG_MACH_U300_BS335 - &uart1_clk, - &uart1_pclk, -#endif - /* SLOW bridge clocks */ - &slow_clk, - &wdog_clk, - &uart0_clk, - &uart0_pclk, - &app_timer_clk, - &keypad_clk, - &gpio_clk, - &rtc_clk, - &bustr_clk, - &evhist_clk, - &timer_clk, -#ifdef CONFIG_MACH_U300_BS335 - &ppm_clk, -#endif -}; - -static int u300_clocks_show(struct seq_file *s, void *data) -{ - struct clk *clk; - int i; - - seq_printf(s, "CLOCK DEVICE RESET STATE\t" \ - "ACTIVE\tUSERS\tHW CTRL FREQ\n"); - seq_printf(s, "---------------------------------------------" \ - "-----------------------------------------\n"); - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk = clks[i]; - if (clk != ERR_PTR(-ENOENT)) { - /* Format clock and device name nicely */ - char cdp[33]; - int chars; - - chars = snprintf(&cdp[0], 17, "%s", clk->name); - while (chars < 16) { - cdp[chars] = ' '; - chars++; - } - chars = snprintf(&cdp[16], 17, "%s", clk->dev ? - dev_name(clk->dev) : "N/A"); - while (chars < 16) { - cdp[chars+16] = ' '; - chars++; - } - cdp[32] = '\0'; - if (clk->get_rate || clk->rate != 0) - seq_printf(s, - "%s%s\t%s\t%d\t%s\t%lu Hz\n", - &cdp[0], - clk->reset ? - "ASSERTED" : "RELEASED", - clk->usecount ? "ON" : "OFF", - clk->usecount, - clk->hw_ctrld ? "YES" : "NO ", - clk_get_rate(clk)); - else - seq_printf(s, - "%s%s\t%s\t%d\t%s\t" \ - "(unknown rate)\n", - &cdp[0], - clk->reset ? - "ASSERTED" : "RELEASED", - clk->usecount ? "ON" : "OFF", - clk->usecount, - clk->hw_ctrld ? "YES" : "NO "); - } - } - return 0; -} - -static int u300_clocks_open(struct inode *inode, struct file *file) -{ - return single_open(file, u300_clocks_show, NULL); -} - -static const struct file_operations u300_clocks_operations = { - .open = u300_clocks_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init init_clk_read_debugfs(void) -{ - /* Expose a simple debugfs interface to view all clocks */ - (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO, - NULL, NULL, - &u300_clocks_operations); - return 0; -} -/* - * This needs to come in after the core_initcall() for the - * overall clocks, because debugfs is not available until - * the subsystems come up. - */ -module_init(init_clk_read_debugfs); -#endif - -int __init u300_clock_init(void) -{ - u16 val; - - /* - * FIXME: shall all this powermanagement stuff really live here??? - */ - - /* Set system to run at PLL208, max performance, a known state. */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Wait for the PLL208 to lock if not locked in yet */ - while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & - U300_SYSCON_CSR_PLL208_LOCK_IND)); - - /* Power management enable */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR); - val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR); - - clk_register(); - - /* - * Some of these may be on when we boot the system so make sure they - * are turned OFF. - */ - syscon_block_reset_enable(&timer_clk); - timer_clk.disable(&timer_clk); - - /* - * These shall be turned on by default when we boot the system - * so make sure they are ON. (Adding CPU here is a bit too much.) - * These clocks will be claimed by drivers later. - */ - syscon_block_reset_disable(&semi_clk); - syscon_block_reset_disable(&emif_clk); - clk_enable(&semi_clk); - clk_enable(&emif_clk); - - return 0; -} diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h deleted file mode 100644 index 4f50ca8f901e..000000000000 --- a/arch/arm/mach-u300/clock.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * arch/arm/mach-u300/include/mach/clock.h - * - * Copyright (C) 2004 - 2005 Nokia corporation - * Written by Tuukka Tikkanen - * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc - * Copyright (C) 2007-2009 ST-Ericsson AB - * Adopted to ST-Ericsson U300 platforms by - * Jonas Aaberg - * - * 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 __MACH_CLOCK_H -#define __MACH_CLOCK_H - -#include - -struct clk { - struct list_head node; - struct module *owner; - struct device *dev; - const char *name; - struct clk *parent; - - spinlock_t lock; - unsigned long rate; - bool reset; - __u16 clk_val; - __s8 usecount; - void __iomem * res_reg; - __u16 res_mask; - - bool hw_ctrld; - - void (*recalc) (struct clk *); - int (*set_rate) (struct clk *, unsigned long); - unsigned long (*get_rate) (struct clk *); - unsigned long (*round_rate) (struct clk *, unsigned long); - void (*init) (struct clk *); - void (*enable) (struct clk *); - void (*disable) (struct clk *); -}; - -int u300_clock_init(void); - -#endif diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 33339745d432..03acf1883ec7 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,6 @@ #include #include -#include "clock.h" #include "spi.h" #include "i2c.h" #include "u300-gpio.h" @@ -1658,12 +1658,20 @@ void __init u300_init_irq(void) int i; /* initialize clocking early, we want to clock the INTCON */ - u300_clock_init(); + u300_clk_init(U300_SYSCON_VBASE); + + /* Bootstrap EMIF and SEMI clocks */ + clk = clk_get_sys("pl172", NULL); + BUG_ON(IS_ERR(clk)); + clk_prepare_enable(clk); + clk = clk_get_sys("semi", NULL); + BUG_ON(IS_ERR(clk)); + clk_prepare_enable(clk); /* Clock the interrupt controller */ clk = clk_get_sys("intcon", NULL); BUG_ON(IS_ERR(clk)); - clk_enable(clk); + clk_prepare_enable(clk); for (i = 0; i < U300_VIC_IRQS_END; i++) set_bit(i, (unsigned long *) &mask[0]); @@ -1811,13 +1819,6 @@ void __init u300_init_devices(void) /* Check what platform we run and print some status information */ u300_init_check_chip(); - /* Set system to run at PLL208, max performance, a known state. */ - val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); - val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; - writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Wait for the PLL208 to lock if not locked in yet */ - while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & - U300_SYSCON_CSR_PLL208_LOCK_IND)); /* Initialize SPI device with some board specifics */ u300_spi_init(&pl022_device); diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index bc1c7897e82d..56ac06d38ec1 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -354,7 +354,7 @@ static void __init u300_timer_init(void) /* Clock the interrupt controller */ clk = clk_get_sys("apptimer", NULL); BUG_ON(IS_ERR(clk)); - clk_enable(clk); + clk_prepare_enable(clk); rate = clk_get_rate(clk); setup_sched_clock(u300_read_sched_clock, 32, rate); diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b679f117f3cc..35d9fb44c814 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,10 +1,11 @@ - +# common clock types obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ clk-mux.o clk-divider.o clk-fixed-factor.o # SoCs specific obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_PLAT_SPEAR) += spear/ +obj-$(CONFIG_ARCH_U300) += clk-u300.o # Chip specific obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c new file mode 100644 index 000000000000..a15f7928fb11 --- /dev/null +++ b/drivers/clk/clk-u300.c @@ -0,0 +1,746 @@ +/* + * U300 clock implementation + * Copyright (C) 2007-2012 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Author: Linus Walleij + * Author: Jonas Aaberg + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * The clocking hierarchy currently looks like this. + * NOTE: the idea is NOT to show how the clocks are routed on the chip! + * The ideas is to show dependencies, so a clock higher up in the + * hierarchy has to be on in order for another clock to be on. Now, + * both CPU and DMA can actually be on top of the hierarchy, and that + * is not modeled currently. Instead we have the backbone AMBA bus on + * top. This bus cannot be programmed in any way but conceptually it + * needs to be active for the bridges and devices to transport data. + * + * Please be aware that a few clocks are hw controlled, which mean that + * the hw itself can turn on/off or change the rate of the clock when + * needed! + * + * AMBA bus + * | + * +- CPU + * +- FSMC NANDIF NAND Flash interface + * +- SEMI Shared Memory interface + * +- ISP Image Signal Processor (U335 only) + * +- CDS (U335 only) + * +- DMA Direct Memory Access Controller + * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL) + * +- APEX + * +- VIDEO_ENC AVE2/3 Video Encoder + * +- XGAM Graphics Accelerator Controller + * +- AHB + * | + * +- ahb:0 AHB Bridge + * | | + * | +- ahb:1 INTCON Interrupt controller + * | +- ahb:3 MSPRO Memory Stick Pro controller + * | +- ahb:4 EMIF External Memory interface + * | + * +- fast:0 FAST bridge + * | | + * | +- fast:1 MMCSD MMC/SD card reader controller + * | +- fast:2 I2S0 PCM I2S channel 0 controller + * | +- fast:3 I2S1 PCM I2S channel 1 controller + * | +- fast:4 I2C0 I2C channel 0 controller + * | +- fast:5 I2C1 I2C channel 1 controller + * | +- fast:6 SPI SPI controller + * | +- fast:7 UART1 Secondary UART (U335 only) + * | + * +- slow:0 SLOW bridge + * | + * +- slow:1 SYSCON (not possible to control) + * +- slow:2 WDOG Watchdog + * +- slow:3 UART0 primary UART + * +- slow:4 TIMER_APP Application timer - used in Linux + * +- slow:5 KEYPAD controller + * +- slow:6 GPIO controller + * +- slow:7 RTC controller + * +- slow:8 BT Bus Tracer (not used currently) + * +- slow:9 EH Event Handler (not used currently) + * +- slow:a TIMER_ACC Access style timer (not used currently) + * +- slow:b PPM (U335 only, what is that?) + */ + +/* Global syscon virtual base */ +static void __iomem *syscon_vbase; + +/** + * struct clk_syscon - U300 syscon clock + * @hw: corresponding clock hardware entry + * @hw_ctrld: whether this clock is hardware controlled (for refcount etc) + * and does not need any magic pokes to be enabled/disabled + * @reset: state holder, whether this block's reset line is asserted or not + * @res_reg: reset line enable/disable flag register + * @res_bit: bit for resetting or taking this consumer out of reset + * @en_reg: clock line enable/disable flag register + * @en_bit: bit for enabling/disabling this consumer clock line + * @clk_val: magic value to poke in the register to enable/disable + * this one clock + */ +struct clk_syscon { + struct clk_hw hw; + bool hw_ctrld; + bool reset; + void __iomem *res_reg; + u8 res_bit; + void __iomem *en_reg; + u8 en_bit; + u16 clk_val; +}; + +#define to_syscon(_hw) container_of(_hw, struct clk_syscon, hw) + +static DEFINE_SPINLOCK(syscon_resetreg_lock); + +/* + * Reset control functions. We remember if a block has been + * taken out of reset and don't remove the reset assertion again + * and vice versa. Currently we only remove resets so the + * enablement function is defined out. + */ +static void syscon_block_reset_enable(struct clk_syscon *sclk) +{ + unsigned long iflags; + u16 val; + + /* Not all blocks support resetting */ + if (!sclk->res_reg) + return; + spin_lock_irqsave(&syscon_resetreg_lock, iflags); + val = readw(sclk->res_reg); + val |= BIT(sclk->res_bit); + writew(val, sclk->res_reg); + spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); + sclk->reset = true; +} + +static void syscon_block_reset_disable(struct clk_syscon *sclk) +{ + unsigned long iflags; + u16 val; + + /* Not all blocks support resetting */ + if (!sclk->res_reg) + return; + spin_lock_irqsave(&syscon_resetreg_lock, iflags); + val = readw(sclk->res_reg); + val &= ~BIT(sclk->res_bit); + writew(val, sclk->res_reg); + spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); + sclk->reset = false; +} + +static int syscon_clk_prepare(struct clk_hw *hw) +{ + struct clk_syscon *sclk = to_syscon(hw); + + /* If the block is in reset, bring it out */ + if (sclk->reset) + syscon_block_reset_disable(sclk); + return 0; +} + +static void syscon_clk_unprepare(struct clk_hw *hw) +{ + struct clk_syscon *sclk = to_syscon(hw); + + /* Please don't force the console into reset */ + if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN) + return; + /* When unpreparing, force block into reset */ + if (!sclk->reset) + syscon_block_reset_enable(sclk); +} + +static int syscon_clk_enable(struct clk_hw *hw) +{ + struct clk_syscon *sclk = to_syscon(hw); + + /* Don't touch the hardware controlled clocks */ + if (sclk->hw_ctrld) + return 0; + /* These cannot be controlled */ + if (sclk->clk_val == 0xFFFFU) + return 0; + + writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCER); + return 0; +} + +static void syscon_clk_disable(struct clk_hw *hw) +{ + struct clk_syscon *sclk = to_syscon(hw); + + /* Don't touch the hardware controlled clocks */ + if (sclk->hw_ctrld) + return; + if (sclk->clk_val == 0xFFFFU) + return; + /* Please don't disable the console port */ + if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN) + return; + + writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCDR); +} + +static int syscon_clk_is_enabled(struct clk_hw *hw) +{ + struct clk_syscon *sclk = to_syscon(hw); + u16 val; + + /* If no enable register defined, it's always-on */ + if (!sclk->en_reg) + return 1; + + val = readw(sclk->en_reg); + val &= BIT(sclk->en_bit); + + return val ? 1 : 0; +} + +static u16 syscon_get_perf(void) +{ + u16 val; + + val = readw(syscon_vbase + U300_SYSCON_CCR); + val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; + return val; +} + +static unsigned long +syscon_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_syscon *sclk = to_syscon(hw); + u16 perf = syscon_get_perf(); + + switch(sclk->clk_val) { + case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN: + case U300_SYSCON_SBCER_I2C0_CLK_EN: + case U300_SYSCON_SBCER_I2C1_CLK_EN: + case U300_SYSCON_SBCER_MMC_CLK_EN: + case U300_SYSCON_SBCER_SPI_CLK_EN: + /* The FAST clocks have one progression */ + switch(perf) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + default: + return parent_rate; /* 26 MHz */ + } + case U300_SYSCON_SBCER_DMAC_CLK_EN: + case U300_SYSCON_SBCER_NANDIF_CLK_EN: + case U300_SYSCON_SBCER_XGAM_CLK_EN: + /* AMBA interconnect peripherals */ + switch(perf) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 6500000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 26000000; + default: + return parent_rate; /* 52 MHz */ + } + case U300_SYSCON_SBCER_SEMI_CLK_EN: + case U300_SYSCON_SBCER_EMIF_CLK_EN: + /* EMIF speeds */ + switch(perf) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 52000000; + default: + return 104000000; + } + case U300_SYSCON_SBCER_CPU_CLK_EN: + /* And the fast CPU clock */ + switch(perf) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 52000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + return 104000000; + default: + return parent_rate; /* 208 MHz */ + } + default: + /* + * The SLOW clocks and default just inherit the rate of + * their parent (typically PLL13 13 MHz). + */ + return parent_rate; + } +} + +static long +syscon_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_syscon *sclk = to_syscon(hw); + + if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN) + return *prate; + /* We really only support setting the rate of the CPU clock */ + if (rate <= 13000000) + return 13000000; + if (rate <= 52000000) + return 52000000; + if (rate <= 104000000) + return 104000000; + return 208000000; +} + +static int syscon_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_syscon *sclk = to_syscon(hw); + u16 val; + + /* We only support setting the rate of the CPU clock */ + if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN) + return -EINVAL; + switch (rate) { + case 13000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER; + break; + case 52000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE; + break; + case 104000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH; + break; + case 208000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST; + break; + default: + return -EINVAL; + } + val |= readw(syscon_vbase + U300_SYSCON_CCR) & + ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ; + writew(val, syscon_vbase + U300_SYSCON_CCR); + return 0; +} + +static const struct clk_ops syscon_clk_ops = { + .prepare = syscon_clk_prepare, + .unprepare = syscon_clk_unprepare, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .is_enabled = syscon_clk_is_enabled, + .recalc_rate = syscon_clk_recalc_rate, + .round_rate = syscon_clk_round_rate, + .set_rate = syscon_clk_set_rate, +}; + +static struct clk * __init +syscon_clk_register(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + bool hw_ctrld, + void __iomem *res_reg, u8 res_bit, + void __iomem *en_reg, u8 en_bit, + u16 clk_val) +{ + struct clk *clk; + struct clk_syscon *sclk; + struct clk_init_data init; + + sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL); + if (!sclk) { + pr_err("could not allocate syscon clock %s\n", + name); + return ERR_PTR(-ENOMEM); + } + init.name = name; + init.ops = &syscon_clk_ops; + init.flags = flags; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + sclk->hw.init = &init; + sclk->hw_ctrld = hw_ctrld; + /* Assume the block is in reset at registration */ + sclk->reset = true; + sclk->res_reg = res_reg; + sclk->res_bit = res_bit; + sclk->en_reg = en_reg; + sclk->en_bit = en_bit; + sclk->clk_val = clk_val; + + clk = clk_register(dev, &sclk->hw); + if (IS_ERR(clk)) + kfree(sclk); + + return clk; +} + +/** + * struct clk_mclk - U300 MCLK clock (MMC/SD clock) + * @hw: corresponding clock hardware entry + * @is_mspro: if this is the memory stick clock rather than MMC/SD + */ +struct clk_mclk { + struct clk_hw hw; + bool is_mspro; +}; + +#define to_mclk(_hw) container_of(_hw, struct clk_mclk, hw) + +static int mclk_clk_prepare(struct clk_hw *hw) +{ + struct clk_mclk *mclk = to_mclk(hw); + u16 val; + + /* The MMC and MSPRO clocks need some special set-up */ + if (!mclk->is_mspro) { + /* Set default MMC clock divisor to 18.9 MHz */ + writew(0x0054U, syscon_vbase + U300_SYSCON_MMF0R); + val = readw(syscon_vbase + U300_SYSCON_MMCR); + /* Disable the MMC feedback clock */ + val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; + /* Disable MSPRO frequency */ + val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; + writew(val, syscon_vbase + U300_SYSCON_MMCR); + } else { + val = readw(syscon_vbase + U300_SYSCON_MMCR); + /* Disable the MMC feedback clock */ + val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; + /* Enable MSPRO frequency */ + val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; + writew(val, syscon_vbase + U300_SYSCON_MMCR); + } + + return 0; +} + +static unsigned long +mclk_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u16 perf = syscon_get_perf(); + + switch (perf) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + /* + * Here, the 208 MHz PLL gets shut down and the always + * on 13 MHz PLL used for RTC etc kicks into use + * instead. + */ + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + { + /* + * This clock is under program control. The register is + * divided in two nybbles, bit 7-4 gives cycles-1 to count + * high, bit 3-0 gives cycles-1 to count low. Distribute + * these with no more than 1 cycle difference between + * low and high and add low and high to get the actual + * divisor. The base PLL is 208 MHz. Writing 0x00 will + * divide by 1 and 1 so the highest frequency possible + * is 104 MHz. + * + * e.g. 0x54 => + * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz + */ + u16 val = readw(syscon_vbase + U300_SYSCON_MMF0R) & + U300_SYSCON_MMF0R_MASK; + switch (val) { + case 0x0054: + return 18900000; + case 0x0044: + return 20800000; + case 0x0043: + return 23100000; + case 0x0033: + return 26000000; + case 0x0032: + return 29700000; + case 0x0022: + return 34700000; + case 0x0021: + return 41600000; + case 0x0011: + return 52000000; + case 0x0000: + return 104000000; + default: + break; + } + } + default: + break; + } + return parent_rate; +} + +static long +mclk_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + if (rate <= 18900000) + return 18900000; + if (rate <= 20800000) + return 20800000; + if (rate <= 23100000) + return 23100000; + if (rate <= 26000000) + return 26000000; + if (rate <= 29700000) + return 29700000; + if (rate <= 34700000) + return 34700000; + if (rate <= 41600000) + return 41600000; + /* Highest rate */ + return 52000000; +} + +static int mclk_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u16 val; + u16 reg; + + switch (rate) { + case 18900000: + val = 0x0054; + break; + case 20800000: + val = 0x0044; + break; + case 23100000: + val = 0x0043; + break; + case 26000000: + val = 0x0033; + break; + case 29700000: + val = 0x0032; + break; + case 34700000: + val = 0x0022; + break; + case 41600000: + val = 0x0021; + break; + case 52000000: + val = 0x0011; + break; + case 104000000: + val = 0x0000; + break; + default: + return -EINVAL; + } + + reg = readw(syscon_vbase + U300_SYSCON_MMF0R) & + ~U300_SYSCON_MMF0R_MASK; + writew(reg | val, syscon_vbase + U300_SYSCON_MMF0R); + return 0; +} + +static const struct clk_ops mclk_ops = { + .prepare = mclk_clk_prepare, + .recalc_rate = mclk_clk_recalc_rate, + .round_rate = mclk_clk_round_rate, + .set_rate = mclk_clk_set_rate, +}; + +static struct clk * __init +mclk_clk_register(struct device *dev, const char *name, + const char *parent_name, bool is_mspro) +{ + struct clk *clk; + struct clk_mclk *mclk; + struct clk_init_data init; + + mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL); + if (!mclk) { + pr_err("could not allocate MMC/SD clock %s\n", + name); + return ERR_PTR(-ENOMEM); + } + init.name = "mclk"; + init.ops = &mclk_ops; + init.flags = 0; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + mclk->hw.init = &init; + mclk->is_mspro = is_mspro; + + clk = clk_register(dev, &mclk->hw); + if (IS_ERR(clk)) + kfree(mclk); + + return clk; +} + +void __init u300_clk_init(void __iomem *base) +{ + u16 val; + struct clk *clk; + + syscon_vbase = base; + + /* Set system to run at PLL208, max performance, a known state. */ + val = readw(syscon_vbase + U300_SYSCON_CCR); + val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; + writew(val, syscon_vbase + U300_SYSCON_CCR); + /* Wait for the PLL208 to lock if not locked in yet */ + while (!(readw(syscon_vbase + U300_SYSCON_CSR) & + U300_SYSCON_CSR_PLL208_LOCK_IND)); + + /* Power management enable */ + val = readw(syscon_vbase + U300_SYSCON_PMCR); + val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE; + writew(val, syscon_vbase + U300_SYSCON_PMCR); + + /* These are always available (RTC and PLL13) */ + clk = clk_register_fixed_rate(NULL, "app_32_clk", NULL, + CLK_IS_ROOT, 32768); + /* The watchdog sits directly on the 32 kHz clock */ + clk_register_clkdev(clk, NULL, "coh901327_wdog"); + clk = clk_register_fixed_rate(NULL, "pll13", NULL, + CLK_IS_ROOT, 13000000); + + /* These derive from PLL208 */ + clk = clk_register_fixed_rate(NULL, "pll208", NULL, + CLK_IS_ROOT, 208000000); + clk = clk_register_fixed_factor(NULL, "app_208_clk", "pll208", + 0, 1, 1); + clk = clk_register_fixed_factor(NULL, "app_104_clk", "pll208", + 0, 1, 2); + clk = clk_register_fixed_factor(NULL, "app_52_clk", "pll208", + 0, 1, 4); + /* The 52 MHz is divided down to 26 MHz */ + clk = clk_register_fixed_factor(NULL, "app_26_clk", "app_52_clk", + 0, 1, 2); + + /* Directly on the AMBA interconnect */ + clk = syscon_clk_register(NULL, "cpu_clk", "app_208_clk", 0, true, + syscon_vbase + U300_SYSCON_RRR, 3, + syscon_vbase + U300_SYSCON_CERR, 3, + U300_SYSCON_SBCER_CPU_CLK_EN); + clk = syscon_clk_register(NULL, "dmac_clk", "app_52_clk", 0, true, + syscon_vbase + U300_SYSCON_RRR, 4, + syscon_vbase + U300_SYSCON_CERR, 4, + U300_SYSCON_SBCER_DMAC_CLK_EN); + clk_register_clkdev(clk, NULL, "dma"); + clk = syscon_clk_register(NULL, "fsmc_clk", "app_52_clk", 0, false, + syscon_vbase + U300_SYSCON_RRR, 6, + syscon_vbase + U300_SYSCON_CERR, 6, + U300_SYSCON_SBCER_NANDIF_CLK_EN); + clk_register_clkdev(clk, NULL, "fsmc-nand"); + clk = syscon_clk_register(NULL, "xgam_clk", "app_52_clk", 0, true, + syscon_vbase + U300_SYSCON_RRR, 8, + syscon_vbase + U300_SYSCON_CERR, 8, + U300_SYSCON_SBCER_XGAM_CLK_EN); + clk_register_clkdev(clk, NULL, "xgam"); + clk = syscon_clk_register(NULL, "semi_clk", "app_104_clk", 0, false, + syscon_vbase + U300_SYSCON_RRR, 9, + syscon_vbase + U300_SYSCON_CERR, 9, + U300_SYSCON_SBCER_SEMI_CLK_EN); + clk_register_clkdev(clk, NULL, "semi"); + + /* AHB bridge clocks */ + clk = syscon_clk_register(NULL, "ahb_subsys_clk", "app_52_clk", 0, true, + syscon_vbase + U300_SYSCON_RRR, 10, + syscon_vbase + U300_SYSCON_CERR, 10, + U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN); + clk = syscon_clk_register(NULL, "intcon_clk", "ahb_subsys_clk", 0, false, + syscon_vbase + U300_SYSCON_RRR, 12, + syscon_vbase + U300_SYSCON_CERR, 12, + /* Cannot be enabled, just taken out of reset */ + 0xFFFFU); + clk_register_clkdev(clk, NULL, "intcon"); + clk = syscon_clk_register(NULL, "emif_clk", "ahb_subsys_clk", 0, false, + syscon_vbase + U300_SYSCON_RRR, 5, + syscon_vbase + U300_SYSCON_CERR, 5, + U300_SYSCON_SBCER_EMIF_CLK_EN); + clk_register_clkdev(clk, NULL, "pl172"); + + /* FAST bridge clocks */ + clk = syscon_clk_register(NULL, "fast_clk", "app_26_clk", 0, true, + syscon_vbase + U300_SYSCON_RFR, 0, + syscon_vbase + U300_SYSCON_CEFR, 0, + U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN); + clk = syscon_clk_register(NULL, "i2c0_p_clk", "fast_clk", 0, false, + syscon_vbase + U300_SYSCON_RFR, 1, + syscon_vbase + U300_SYSCON_CEFR, 1, + U300_SYSCON_SBCER_I2C0_CLK_EN); + clk_register_clkdev(clk, NULL, "stu300.0"); + clk = syscon_clk_register(NULL, "i2c1_p_clk", "fast_clk", 0, false, + syscon_vbase + U300_SYSCON_RFR, 2, + syscon_vbase + U300_SYSCON_CEFR, 2, + U300_SYSCON_SBCER_I2C1_CLK_EN); + clk_register_clkdev(clk, NULL, "stu300.1"); + clk = syscon_clk_register(NULL, "mmc_p_clk", "fast_clk", 0, false, + syscon_vbase + U300_SYSCON_RFR, 5, + syscon_vbase + U300_SYSCON_CEFR, 5, + U300_SYSCON_SBCER_MMC_CLK_EN); + clk_register_clkdev(clk, "apb_pclk", "mmci"); + clk = syscon_clk_register(NULL, "spi_p_clk", "fast_clk", 0, false, + syscon_vbase + U300_SYSCON_RFR, 6, + syscon_vbase + U300_SYSCON_CEFR, 6, + U300_SYSCON_SBCER_SPI_CLK_EN); + /* The SPI has no external clock for the outward bus, uses the pclk */ + clk_register_clkdev(clk, NULL, "pl022"); + clk_register_clkdev(clk, "apb_pclk", "pl022"); + + /* SLOW bridge clocks */ + clk = syscon_clk_register(NULL, "slow_clk", "pll13", 0, true, + syscon_vbase + U300_SYSCON_RSR, 0, + syscon_vbase + U300_SYSCON_CESR, 0, + U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN); + clk = syscon_clk_register(NULL, "uart0_clk", "slow_clk", 0, false, + syscon_vbase + U300_SYSCON_RSR, 1, + syscon_vbase + U300_SYSCON_CESR, 1, + U300_SYSCON_SBCER_UART_CLK_EN); + /* Same clock is used for APB and outward bus */ + clk_register_clkdev(clk, NULL, "uart0"); + clk_register_clkdev(clk, "apb_pclk", "uart0"); + clk = syscon_clk_register(NULL, "gpio_clk", "slow_clk", 0, false, + syscon_vbase + U300_SYSCON_RSR, 4, + syscon_vbase + U300_SYSCON_CESR, 4, + U300_SYSCON_SBCER_GPIO_CLK_EN); + clk_register_clkdev(clk, NULL, "u300-gpio"); + clk = syscon_clk_register(NULL, "keypad_clk", "slow_clk", 0, false, + syscon_vbase + U300_SYSCON_RSR, 5, + syscon_vbase + U300_SYSCON_CESR, 6, + U300_SYSCON_SBCER_KEYPAD_CLK_EN); + clk_register_clkdev(clk, NULL, "coh901461-keypad"); + clk = syscon_clk_register(NULL, "rtc_clk", "slow_clk", 0, true, + syscon_vbase + U300_SYSCON_RSR, 6, + /* No clock enable register bit */ + NULL, 0, 0xFFFFU); + clk_register_clkdev(clk, NULL, "rtc-coh901331"); + clk = syscon_clk_register(NULL, "app_tmr_clk", "slow_clk", 0, false, + syscon_vbase + U300_SYSCON_RSR, 7, + syscon_vbase + U300_SYSCON_CESR, 7, + U300_SYSCON_SBCER_APP_TMR_CLK_EN); + clk_register_clkdev(clk, NULL, "apptimer"); + clk = syscon_clk_register(NULL, "acc_tmr_clk", "slow_clk", 0, false, + syscon_vbase + U300_SYSCON_RSR, 8, + syscon_vbase + U300_SYSCON_CESR, 8, + U300_SYSCON_SBCER_ACC_TMR_CLK_EN); + clk_register_clkdev(clk, NULL, "timer"); + + /* Then this special MMC/SD clock */ + clk = mclk_clk_register(NULL, "mmc_clk", "mmc_p_clk", false); + clk_register_clkdev(clk, NULL, "mmci"); +} diff --git a/include/linux/platform_data/clk-u300.h b/include/linux/platform_data/clk-u300.h new file mode 100644 index 000000000000..8429e73911a1 --- /dev/null +++ b/include/linux/platform_data/clk-u300.h @@ -0,0 +1 @@ +void __init u300_clk_init(void __iomem *base); -- GitLab From d6776e6d5c2f8db0252f447b09736075e1bbe387 Mon Sep 17 00:00:00 2001 From: Nikhil P Rao Date: Wed, 20 Jun 2012 12:56:00 -0700 Subject: [PATCH 2525/5711] PCI: fix truncation of resource size to 32 bits _pci_assign_resource() took an int "size" argument, which meant that sizes larger than 4GB were truncated. Change type to resource_size_t. [bhelgaas: changelog] Signed-off-by: Nikhil P Rao Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index eea85dafc763..be76ebacf486 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -206,7 +206,8 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, return ret; } -static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align) +static int _pci_assign_resource(struct pci_dev *dev, int resno, + resource_size_t size, resource_size_t min_align) { struct resource *res = dev->resource + resno; struct pci_bus *bus; -- GitLab From fe6dacdb1a31957825c0876de7cdea4c356aca30 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 11 Jul 2012 17:05:43 -0600 Subject: [PATCH 2526/5711] PCI: reorder __pci_assign_resource() (no change) Reorder functions so __pci_assign_resource(), _pci_assign_resource(), and pci_assign_resource() are closer together. No code change. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 104 ++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index be76ebacf486..3ce9fa317d1d 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -127,33 +127,6 @@ void pci_disable_bridge_window(struct pci_dev *dev) pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff); } -static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, - int resno, resource_size_t size, resource_size_t align) -{ - struct resource *res = dev->resource + resno; - resource_size_t min; - int ret; - - min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - - /* First, try exact prefetching match.. */ - ret = pci_bus_alloc_resource(bus, res, size, align, min, - IORESOURCE_PREFETCH, - pcibios_align_resource, dev); - - if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { - /* - * That failed. - * - * But a prefetching area can handle a non-prefetching - * window (it will just not perform as well). - */ - ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, - pcibios_align_resource, dev); - } - return ret; -} - /* * Generic function that returns a value indicating that the device's * original BIOS BAR address was not saved and so is not available for @@ -206,6 +179,33 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, return ret; } +static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, + int resno, resource_size_t size, resource_size_t align) +{ + struct resource *res = dev->resource + resno; + resource_size_t min; + int ret; + + min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; + + /* First, try exact prefetching match.. */ + ret = pci_bus_alloc_resource(bus, res, size, align, min, + IORESOURCE_PREFETCH, + pcibios_align_resource, dev); + + if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { + /* + * That failed. + * + * But a prefetching area can handle a non-prefetching + * window (it will just not perform as well). + */ + ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, + pcibios_align_resource, dev); + } + return ret; +} + static int _pci_assign_resource(struct pci_dev *dev, int resno, resource_size_t size, resource_size_t min_align) { @@ -239,31 +239,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno, return ret; } -int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize, - resource_size_t min_align) -{ - struct resource *res = dev->resource + resno; - resource_size_t new_size; - int ret; - - if (!res->parent) { - dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR " - "\n", resno, res); - return -EINVAL; - } - - /* already aligned with min_align */ - new_size = resource_size(res) + addsize; - ret = _pci_assign_resource(dev, resno, new_size, min_align); - if (!ret) { - res->flags &= ~IORESOURCE_STARTALIGN; - dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); - if (resno < PCI_BRIDGE_RESOURCES) - pci_update_resource(dev, resno); - } - return ret; -} - int pci_assign_resource(struct pci_dev *dev, int resno) { struct resource *res = dev->resource + resno; @@ -299,6 +274,31 @@ int pci_assign_resource(struct pci_dev *dev, int resno) return ret; } +int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize, + resource_size_t min_align) +{ + struct resource *res = dev->resource + resno; + resource_size_t new_size; + int ret; + + if (!res->parent) { + dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR " + "\n", resno, res); + return -EINVAL; + } + + /* already aligned with min_align */ + new_size = resource_size(res) + addsize; + ret = _pci_assign_resource(dev, resno, new_size, min_align); + if (!ret) { + res->flags &= ~IORESOURCE_STARTALIGN; + dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); + if (resno < PCI_BRIDGE_RESOURCES) + pci_update_resource(dev, resno); + } + return ret; +} + int pci_enable_resources(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; -- GitLab From 949eb0aeb939f5c7022c02358f98ffd235b45ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:36 +0200 Subject: [PATCH 2527/5711] Staging: xgifb: Comment cleaning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove commented code and useless comments. Leave only those with relevant hints to the code. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main.h | 4 - drivers/staging/xgifb/XGI_main_26.c | 133 ++++-------------------- drivers/staging/xgifb/XGIfb.h | 8 +- drivers/staging/xgifb/vb_def.h | 3 - drivers/staging/xgifb/vb_init.c | 155 ++++------------------------ drivers/staging/xgifb/vb_setmode.c | 26 ++--- drivers/staging/xgifb/vb_struct.h | 3 - drivers/staging/xgifb/vb_table.h | 35 ++----- 8 files changed, 61 insertions(+), 306 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index be6bb7d0971e..1686c5acda13 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -68,9 +68,6 @@ static int XGIfb_crt2type = -1; /* PR: Tv plug type (for overriding autodetection) */ static int XGIfb_tvplug = -1; -/* TW: For ioctl XGIFB_GET_INFO */ -/* XGIfb_info XGIfbinfo; */ - #define MD_XGI315 1 /* mode table */ @@ -240,7 +237,6 @@ static const struct _chswtable { { 0, 0, "" , "" } }; -/* Eden Chen */ static const struct _XGI_TV_filter { u8 filter[9][4]; } XGI_TV_filter[] = { diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index fe9061d37ce8..b226458272a3 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -36,36 +36,6 @@ static void dumpVGAReg(void) u8 i, reg; xgifb_reg_set(XGISR, 0x05, 0x86); - /* - xgifb_reg_set(XGISR, 0x08, 0x4f); - xgifb_reg_set(XGISR, 0x0f, 0x20); - xgifb_reg_set(XGISR, 0x11, 0x4f); - xgifb_reg_set(XGISR, 0x13, 0x45); - xgifb_reg_set(XGISR, 0x14, 0x51); - xgifb_reg_set(XGISR, 0x1e, 0x41); - xgifb_reg_set(XGISR, 0x1f, 0x0); - xgifb_reg_set(XGISR, 0x20, 0xa1); - xgifb_reg_set(XGISR, 0x22, 0xfb); - xgifb_reg_set(XGISR, 0x26, 0x22); - xgifb_reg_set(XGISR, 0x3e, 0x07); - */ - - /* xgifb_reg_set(XGICR, 0x19, 0x00); */ - /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */ - /* xgifb_reg_set(XGICR, 0x22, 0xff); */ - /* xgifb_reg_set(XGICR, 0x3D, 0x10); */ - - /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */ - - /* xgifb_reg_set(XGICR, 0x57, 0x0); */ - /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */ - - /* xgifb_reg_set(XGICR, 0x82, 0xcc); */ - /* xgifb_reg_set(XGICR, 0x8c, 0x0); */ - /* - xgifb_reg_set(XGICR, 0x99, 0x1); - xgifb_reg_set(XGICR, 0x41, 0x40); - */ for (i = 0; i < 0x4f; i++) { reg = xgifb_reg_get(XGISR, i); @@ -78,30 +48,6 @@ static void dumpVGAReg(void) pr_debug("\no 3d4 %x", i); pr_debug("\ni 3d5 => %x", reg); } - /* - xgifb_reg_set(XGIPART1,0x2F,1); - for (i=1; i < 0x50; i++) { - reg = xgifb_reg_get(XGIPART1, i); - pr_debug("\no d004 %x", i); - pr_debug("\ni d005 => %x", reg); - } - - for (i=0; i < 0x50; i++) { - reg = xgifb_reg_get(XGIPART2, i); - pr_debug("\no d010 %x", i); - pr_debug("\ni d011 => %x", reg); - } - for (i=0; i < 0x50; i++) { - reg = xgifb_reg_get(XGIPART3, i); - pr_debug("\no d012 %x",i); - pr_debug("\ni d013 => %x",reg); - } - for (i=0; i < 0x50; i++) { - reg = xgifb_reg_get(XGIPART4, i); - pr_debug("\no d014 %x",i); - pr_debug("\ni d015 => %x",reg); - } - */ } #else static inline void dumpVGAReg(void) @@ -215,15 +161,6 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, | ((unsigned short) (sr_data & 0x01) << 10); A = VT + 2; - /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */ - - /* Vertical display enable end */ - /* - VDE = (cr_data & 0xff) | - ((unsigned short) (cr_data2 & 0x02) << 7) | - ((unsigned short) (cr_data2 & 0x40) << 3) | - ((unsigned short) (sr_data & 0x02) << 9); - */ VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1; E = VDE + 1; @@ -590,7 +527,7 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) if (XGIbios_mode[myindex].yres != 576) return -1; } - /* TW: LVDS/CHRONTEL does not support 720 */ + /* LVDS/CHRONTEL does not support 720 */ if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL || xgifb_info->hasVB == HASVB_CHRONTEL) { return -1; @@ -794,26 +731,25 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) { u8 reg; unsigned char doit = 1; - /* - xgifb_reg_set(XGISR,IND_SIS_PASSWORD,SIS_PASSWORD); - xgifb_reg_set(XGICR, 0x13, 0x00); - xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01); - *test* - */ + if (xgifb_info->video_bpp == 8) { - /* TW: We can't switch off CRT1 on LVDS/Chrontel - * in 8bpp Modes */ + /* + * We can't switch off CRT1 on LVDS/Chrontel + * in 8bpp Modes + */ if ((xgifb_info->hasVB == HASVB_LVDS) || (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) { doit = 0; } - /* TW: We can't switch off CRT1 on 301B-DH - * in 8bpp Modes if using LCD */ + /* + * We can't switch off CRT1 on 301B-DH + * in 8bpp Modes if using LCD + */ if (xgifb_info->display2 == XGIFB_DISP_LCD) doit = 0; } - /* TW: We can't switch off CRT1 if bridge is in slave mode */ + /* We can't switch off CRT1 if bridge is in slave mode */ if (xgifb_info->hasVB != HASVB_NONE) { reg = xgifb_reg_get(XGIPART1, 0x00); @@ -1038,7 +974,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, unsigned int drate = 0, hrate = 0; int found_mode = 0; int old_mode; - /* unsigned char reg, reg1; */ info->var.xres_virtual = var->xres_virtual; info->var.yres_virtual = var->yres_virtual; @@ -1049,8 +984,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) vtotal <<= 2; else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { - /* vtotal <<= 1; */ - /* var->yres <<= 1; */ } if (!htotal || !vtotal) { @@ -1388,16 +1321,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) xgifb_info->refresh_rate = 60; } - /* - if ((var->pixclock) && (htotal)) { - drate = 1E12 / var->pixclock; - hrate = drate / htotal; - refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5); - } else { - refresh_rate = 60; - } - */ - /* TW: Calculation wrong for 1024x600 - force it to 60Hz */ + /* Calculation wrong for 1024x600 - force it to 60Hz */ if ((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60; @@ -1446,8 +1370,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } } - /* TW: TODO: Check the refresh rate */ - /* Adapt RGB settings */ XGIfb_bpp_to_var(xgifb_info, var); @@ -1462,16 +1384,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->xres_virtual = var->xres; if (var->yres != var->yres_virtual) var->yres_virtual = var->yres; - } /* else { */ - /* TW: Now patch yres_virtual if we use panning */ - /* May I do this? */ - /* var->yres_virtual = xgifb_info->heapstart / - (var->xres * (var->bits_per_pixel >> 3)); */ - /* if (var->yres_virtual <= var->yres) { */ - /* TW: Paranoia check */ - /* var->yres_virtual = var->yres; */ - /* } */ - /* } */ + } /* Truncate offsets to maximum if too high */ if (var->xoffset > var->xres_virtual - var->xres) @@ -1553,7 +1466,6 @@ static struct fb_ops XGIfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - /* .fb_mmap = XGIfb_mmap, */ }; /* ---------------- Chip generation dependent routines ---------------- */ @@ -1630,9 +1542,6 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) } xgifb_info->video_size = xgifb_info->video_size * ChannelNum; - /* PLiad fixed for benchmarking and fb set */ - /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */ - /* xgifb_info->video_size = 0x1000000; */ /* benchmark */ pr_info("SR14=%x DramSzie %x ChannelNum %x\n", reg, @@ -1680,7 +1589,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) } if (XGIfb_tvplug != -1) - /* PR/TW: Override with option */ + /* Override with option */ xgifb_info->TV_plug = XGIfb_tvplug; else if (cr32 & SIS_VB_HIVISION) { xgifb_info->TV_type = TVMODE_HIVISION; @@ -1700,7 +1609,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) xgifb_info->TV_type = TVMODE_NTSC; } - /* TW: Copy forceCRT1 option to CRT1off if option is given */ + /* Copy forceCRT1 option to CRT1off if option is given */ if (XGIfb_forcecrt1 != -1) { if (XGIfb_forcecrt1) XGIfb_crt1off = 0; @@ -1794,7 +1703,7 @@ static int __init XGIfb_setup(char *options) XGIfb_search_tvstd(this_opt + 7); } else if (!strncmp(this_opt, "dstn", 4)) { enable_dstn = 1; - /* TW: DSTN overrules forcecrt2type */ + /* DSTN overrules forcecrt2type */ XGIfb_crt2type = XGIFB_DISP_LCD; } else if (!strncmp(this_opt, "noypan", 6)) { XGIfb_ypan = 0; @@ -1981,13 +1890,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "XGI301LV bridge detected (revision 0x%02x)\n", reg); - } - /* else if (reg >= 0xB0) { - hw_info->ujVBChipID = VB_CHIP_301B; - reg1 = xgifb_reg_get(XGIPART4, 0x23); - pr_debug("XGIfb: XGI301B bridge detected\n"); - } */ - else { + } else { hw_info->ujVBChipID = VB_CHIP_301; dev_info(&pdev->dev, "XGI301 bridge detected\n"); } @@ -2104,7 +2007,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, goto error_1; } - /* yilin set default refresh rate */ + /* set default refresh rate */ xgifb_info->refresh_rate = refresh_rate; if (xgifb_info->refresh_rate == 0) xgifb_info->refresh_rate = 60; diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h index 741bba351cff..80547983759b 100644 --- a/drivers/staging/xgifb/XGIfb.h +++ b/drivers/staging/xgifb/XGIfb.h @@ -30,13 +30,13 @@ enum xgi_tvtype { TVMODE_NTSC = 0, TVMODE_PAL, TVMODE_HIVISION, - TVTYPE_PALM, /* vicki@030226 */ - TVTYPE_PALN, /* vicki@030226 */ - TVTYPE_NTSCJ, /* vicki@030226 */ + TVTYPE_PALM, + TVTYPE_PALN, + TVTYPE_NTSCJ, TVMODE_TOTAL }; -enum xgi_tv_plug { /* vicki@030226 */ +enum xgi_tv_plug { TVPLUG_UNKNOWN = 0, TVPLUG_COMPOSITE = 1, TVPLUG_SVIDEO = 2, diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 5b987a68ee9f..69078d933a47 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -1,5 +1,3 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h - * ,v 1.4 2000/12/02 01:16:17 dawes Exp $*/ #ifndef _VB_DEF_ #define _VB_DEF_ #include "../../video/sis/initdef.h" @@ -12,7 +10,6 @@ #define SetCHTVOverScan 0x8000 #define Panel_320x480 0x07 /*fstn*/ -/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */ #define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */ #define Panel_1024x768x75 0x22 #define Panel_1280x1024x75 0x23 diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 7c555a7725fe..6bb020697a59 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1,4 +1,4 @@ -#include /* udelay */ +#include #include #include "XGIfb.h" @@ -132,10 +132,8 @@ static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, 0x30, pVBInfo->ECLKData[pVBInfo->ram_type].SR30); - /* [Vicent] 2004/07/07, - * When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */ - /* [Hsuan] 2004/08/20, - * Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, + /* When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */ + /* Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, * Set SR32 D[1:0] = 10b */ if (HwDeviceExtension->jChipType == XG42) { if ((pVBInfo->MCLKData[pVBInfo->ram_type].SR28 == 0x1C) && @@ -160,7 +158,6 @@ static void XGINew_DDRII_Bootup_XG27( XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo); /* Set Double Frequency */ - /* xgifb_reg_set(P3d4, 0x97, 0x11); *//* CR97 */ xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */ udelay(200); @@ -192,7 +189,6 @@ static void XGINew_DDRII_Bootup_XG27( udelay(30); xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */ xgifb_reg_set(P3c4, 0x16, 0x80); /* Set SR16 */ - /* udelay(15); */ xgifb_reg_set(P3c4, 0x1B, 0x04); /* Set SR1B */ udelay(60); @@ -252,7 +248,6 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension, xgifb_reg_set(P3c4, 0x16, 0x05); xgifb_reg_set(P3c4, 0x16, 0x85); - /* xgifb_reg_set(P3c4, 0x18, 0x52); */ /* MRS1 */ xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */ xgifb_reg_set(P3c4, 0x19, 0x02); xgifb_reg_set(P3c4, 0x16, 0x05); @@ -264,7 +259,6 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension, xgifb_reg_set(P3c4, 0x1B, 0x00); /* SR1B */ udelay(100); - /* xgifb_reg_set(P3c4 ,0x18, 0x52); */ /* MRS2 */ xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */ xgifb_reg_set(P3c4, 0x19, 0x00); xgifb_reg_set(P3c4, 0x16, 0x05); @@ -290,14 +284,12 @@ static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */ - /* xgifb_reg_set(P3c4, 0x18, 0x31); */ xgifb_reg_set(P3c4, 0x19, 0x01); xgifb_reg_set(P3c4, 0x16, 0x03); xgifb_reg_set(P3c4, 0x16, 0x83); mdelay(1); xgifb_reg_set(P3c4, 0x1B, 0x03); udelay(500); - /* xgifb_reg_set(P3c4, 0x18, 0x31); */ xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */ @@ -546,7 +538,6 @@ static void XGINew_SetDRAMDefaultRegister340( xgifb_reg_set(P3d4, 0x87, 0x00); /* CR87 */ xgifb_reg_set(P3d4, 0xCF, XG40_CRCF); /* CRCF */ if (pVBInfo->ram_type) { - /* xgifb_reg_set(P3c4, 0x17, 0xC0); */ /* SR17 DDRII */ xgifb_reg_set(P3c4, 0x17, 0x80); /* SR17 DDRII */ if (HwDeviceExtension->jChipType == XG27) xgifb_reg_set(P3c4, 0x17, 0x02); /* SR17 DDRII */ @@ -597,19 +588,12 @@ static unsigned short XGINew_SetDRAMSize20Reg( memsize = data >> 4; - /* [2004/03/25] Vicent, Fix DRAM Sizing Error */ + /* Fix DRAM Sizing Error */ xgifb_reg_set(pVBInfo->P3c4, 0x14, (xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) | (data & 0xF0)); udelay(15); - - /* data |= pVBInfo->ram_channel << 2; */ - /* data |= (pVBInfo->ram_bus / 64) << 1; */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */ - - /* should delay */ - /* XGINew_SetDRAMModeRegister340(pVBInfo); */ } return memsize; } @@ -628,8 +612,7 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr, writel(Position, fbaddr + Position); } - udelay(500); /* [Vicent] 2004/04/16. - Fix #1759 Memory Size error in Multi-Adapter. */ + udelay(500); /* Fix #1759 Memory Size error in Multi-Adapter. */ Position = 0; @@ -925,9 +908,6 @@ static void XGINew_SetDRAMSize_340(struct xgifb_video_info *xgifb_info, xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF)); XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo); - /* data = xgifb_reg_get(pVBInfo->P3c4, 0x1); */ - /* data |= 0x20 ; */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x01, data); *//* Turn OFF Display */ XGINew_DDRSizing340(HwDeviceExtension, pVBInfo); data = xgifb_reg_get(pVBInfo->P3c4, 0x21); /* enable read cache */ @@ -1308,16 +1288,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) struct vb_device_info VBINF; struct vb_device_info *pVBInfo = &VBINF; unsigned char i, temp = 0, temp1; - /* VBIOSVersion[5]; */ - - /* unsigned long j, k; */ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress; pVBInfo->BaseAddr = xgifb_info->vga_base; - /* Newdebugcode(0x99); */ - if (pVBInfo->FBAddr == NULL) { dev_dbg(&pdev->dev, "pVBInfo->FBAddr == 0\n"); return 0; @@ -1331,10 +1306,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->ISXPDOS = 0; - /* VBIOSVersion[4] = 0x0; */ - - /* 09/07/99 modify by domao */ - pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14; pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24; pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10; @@ -1353,7 +1324,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->Part4Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14; pVBInfo->Part5Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14 + 2; - if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) /* Run XGI_GetVBType before InitTo330Pointer */ XGI_GetVBType(pVBInfo); @@ -1361,7 +1332,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_read_vbios(pdev, pVBInfo); - /* 1.Openkey */ + /* Openkey */ xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86); /* GetXG21Sense (GPIO) */ @@ -1371,7 +1342,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) if (HwDeviceExtension->jChipType == XG27) XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo); - /* 2.Reset Extended register */ + /* Reset Extended register */ for (i = 0x06; i < 0x20; i++) xgifb_reg_set(pVBInfo->P3c4, i, 0); @@ -1379,31 +1350,20 @@ unsigned char XGIInitNew(struct pci_dev *pdev) for (i = 0x21; i <= 0x27; i++) xgifb_reg_set(pVBInfo->P3c4, i, 0); - /* for(i = 0x06; i <= 0x27; i++) */ - /* xgifb_reg_set(pVBInfo->P3c4, i, 0); */ - for (i = 0x31; i <= 0x3B; i++) xgifb_reg_set(pVBInfo->P3c4, i, 0); - /* [Hsuan] 2004/08/20 Auto over driver for XG42 */ + /* Auto over driver for XG42 */ if (HwDeviceExtension->jChipType == XG42) xgifb_reg_set(pVBInfo->P3c4, 0x3B, 0xC0); - /* for (i = 0x30; i <= 0x3F; i++) */ - /* xgifb_reg_set(pVBInfo->P3d4, i, 0); */ - for (i = 0x79; i <= 0x7C; i++) - xgifb_reg_set(pVBInfo->P3d4, i, 0); /* shampoo 0208 */ + xgifb_reg_set(pVBInfo->P3d4, i, 0); if (HwDeviceExtension->jChipType >= XG20) xgifb_reg_set(pVBInfo->P3d4, 0x97, pVBInfo->XGINew_CR97); - /* 3.SetMemoryClock - - pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo); - */ - - /* 4.SetDefExt1Regs begin */ + /* SetDefExt1Regs begin */ xgifb_reg_set(pVBInfo->P3c4, 0x07, XGI330_SR07); if (HwDeviceExtension->jChipType == XG27) { xgifb_reg_set(pVBInfo->P3c4, 0x40, XG27_SR40); @@ -1411,62 +1371,16 @@ unsigned char XGIInitNew(struct pci_dev *pdev) } xgifb_reg_set(pVBInfo->P3c4, 0x11, 0x0F); xgifb_reg_set(pVBInfo->P3c4, 0x1F, XGI330_SR1F); - /* xgifb_reg_set(pVBInfo->P3c4, 0x20, 0x20); */ - /* alan, 2001/6/26 Frame buffer can read/write SR20 */ + /* Frame buffer can read/write SR20 */ xgifb_reg_set(pVBInfo->P3c4, 0x20, 0xA0); - /* Hsuan, 2006/01/01 H/W request for slow corner chip */ + /* H/W request for slow corner chip */ xgifb_reg_set(pVBInfo->P3c4, 0x36, 0x70); - if (HwDeviceExtension->jChipType == XG27) /* Alan 12/07/2006 */ + if (HwDeviceExtension->jChipType == XG27) xgifb_reg_set(pVBInfo->P3c4, 0x36, XG27_SR36); - /* SR11 = 0x0F; */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x11, SR11); */ - - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) { u32 Temp; - /* Set AGP Rate */ - /* - temp1 = xgifb_reg_get(pVBInfo->P3c4, 0x3B); - temp1 &= 0x02; - if (temp1 == 0x02) { - outl(0x80000000, 0xcf8); - ChipsetID = inl(0x0cfc); - outl(0x8000002C, 0xcf8); - VendorID = inl(0x0cfc); - VendorID &= 0x0000FFFF; - outl(0x8001002C, 0xcf8); - GraphicVendorID = inl(0x0cfc); - GraphicVendorID &= 0x0000FFFF; - - if (ChipsetID == 0x7301039) - xgifb_reg_set(pVBInfo->P3d4, 0x5F, 0x09); - - ChipsetID &= 0x0000FFFF; - - if ((ChipsetID == 0x700E) || - (ChipsetID == 0x1022) || - (ChipsetID == 0x1106) || - (ChipsetID == 0x10DE)) { - if (ChipsetID == 0x1106) { - if ((VendorID == 0x1019) && - (GraphicVendorID == 0x1019)) - xgifb_reg_set(pVBInfo->P3d4, - 0x5F, - 0x0D); - else - xgifb_reg_set(pVBInfo->P3d4, - 0x5F, - 0x0B); - } else { - xgifb_reg_set(pVBInfo->P3d4, - 0x5F, - 0x0B); - } - } - } - */ - /* Set AGP customize registers (in SetDefAGPRegs) Start */ for (i = 0x47; i <= 0x4C; i++) xgifb_reg_set(pVBInfo->P3d4, @@ -1482,12 +1396,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->P3d4, i, pVBInfo->AGPReg[8 + i - 0x74]); - /* Set AGP customize registers (in SetDefAGPRegs) End */ - /* [Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */ - /* outl(0x80000000, 0xcf8); */ - /* ChipsetID = inl(0x0cfc); */ - /* if (ChipsetID == 0x25308086) */ - /* xgifb_reg_set(pVBInfo->P3d4, 0x77, 0xF0); */ pci_read_config_dword(pdev, 0x50, &Temp); Temp >>= 20; @@ -1502,10 +1410,10 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->P3c4, 0x24, XGI330_SR24); xgifb_reg_set(pVBInfo->P3c4, 0x25, XGI330_SR25); - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) { /* Set VB */ XGI_UnLockCRT2(HwDeviceExtension, pVBInfo); - /* alan, disable VideoCapture */ + /* disable VideoCapture */ xgifb_reg_and_or(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00); xgifb_reg_set(pVBInfo->Part1Port, 0x00, 0x00); /* chk if BCLK>=100MHz */ @@ -1535,10 +1443,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) } xgifb_reg_set(pVBInfo->P3c4, 0x33, XGI330_SR33); - /* - SetPowerConsume (HwDeviceExtension, pVBInfo->P3c4); */ - - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) { if (XGI_BridgeIsOn(pVBInfo) == 1) { if (pVBInfo->IF_DEF_LVDS == 0) { xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C); @@ -1557,7 +1462,6 @@ unsigned char XGIInitNew(struct pci_dev *pdev) XGI_SenseCRT1(pVBInfo); - /* XGINew_DetectMonitor(HwDeviceExtension); */ if (HwDeviceExtension->jChipType == XG21) { xgifb_reg_and_or(pVBInfo->P3d4, @@ -1585,32 +1489,9 @@ unsigned char XGIInitNew(struct pci_dev *pdev) XGINew_SetDRAMSize_340(xgifb_info, HwDeviceExtension, pVBInfo); - /* SetDefExt2Regs begin */ - /* - AGP = 1; - temp = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x3A); - temp &= 0x30; - if (temp == 0x30) - AGP = 0; - - if (AGP == 0) - pVBInfo->SR21 &= 0xEF; - - xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21); - if (AGP == 1) - pVBInfo->SR22 &= 0x20; - xgifb_reg_set(pVBInfo->P3c4, 0x22, pVBInfo->SR22); - */ - /* base = 0x80000000; */ - /* OutPortLong(0xcf8, base); */ - /* Temp = (InPortLong(0xcfc) & 0xFFFF); */ - /* if (Temp == 0x1039) { */ xgifb_reg_set(pVBInfo->P3c4, 0x22, (unsigned char) ((pVBInfo->SR22) & 0xFE)); - /* } else { */ - /* xgifb_reg_set(pVBInfo->P3c4, 0x22, pVBInfo->SR22); */ - /* } */ xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21); diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 479362eacb4f..3ba3c48a5696 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1859,7 +1859,6 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, i++; } - /* 07/05/22 */ if (table == 0x04) { switch (tempdi[i].DATAPTR) { case 0: @@ -2519,7 +2518,7 @@ static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, temp &= 0x0f; if (!(temp == 0x08)) { - /* Check ChannelA by Part1_13 [2003/10/03] */ + /* Check ChannelA */ tempax = xgifb_reg_get(pVBInfo->Part1Port, 0x13); if (tempax & 0x04) tempcl = tempcl | ActiveLCD; @@ -2675,7 +2674,6 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, } if (pVBInfo->IF_DEF_YPbPr == 1) { - /* [Billy] 07/05/04 */ if (((pVBInfo->IF_DEF_LVDS == 0) && ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV) || @@ -2927,7 +2925,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if (tempbx == 0) tempbx = Panel_1024x768; /* default */ - /* LCD75 [2003/8/22] Vicent */ + /* LCD75 */ if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) { if (pVBInfo->VBInfo & DriverMode) { tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33); @@ -4591,7 +4589,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, } } - /* [ycchen] 01/14/03 Modify for 301C PALM Support */ + /* Modify for 301C PALM Support */ if (pVBInfo->VBType & VB_XGI301C) { if (pVBInfo->TVInfo & TVSetPALM) xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08, @@ -6245,8 +6243,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 600)) { index++; } - /* Alan 10/19/2007; - * do the similar adjustment like XGISearchCRT1Rate() */ + /* do the similar adjustment like XGISearchCRT1Rate() */ if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1024) && (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 768)) { index++; @@ -6354,7 +6351,7 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo) int i; xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86); - /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */ + /* to fix XG42 single LCD sense to CRT+LCD */ xgifb_reg_set(pVBInfo->P3d4, 0x57, 0x4A); xgifb_reg_set(pVBInfo->P3d4, 0x53, (unsigned char) (xgifb_reg_get( pVBInfo->P3d4, 0x53) | 0x02)); @@ -6419,7 +6416,7 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo) else xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x00); - /* alan, avoid display something, set BLACK DAC if not restore DAC */ + /* avoid display something, set BLACK DAC if not restore DAC */ outb(0x00, pVBInfo->P3c8); for (i = 0; i < 256; i++) { @@ -6432,7 +6429,6 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo) xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63); xgifb_reg_set(pVBInfo->P3c4, 0x31, SR31); - /* [2004/05/11] Vicent */ xgifb_reg_set(pVBInfo->P3d4, 0x53, (unsigned char) (xgifb_reg_get( pVBInfo->P3d4, 0x53) & 0xFD)); xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F); @@ -6653,7 +6649,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, pVBInfo->IF_DEF_LVDS = 0; pVBInfo->IF_DEF_LCDA = 1; - if (HwDeviceExtension->jChipType >= XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType >= XG20) { pVBInfo->IF_DEF_YPbPr = 0; pVBInfo->IF_DEF_HiVision = 0; pVBInfo->IF_DEF_CRT2Monitor = 0; @@ -6695,7 +6691,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, } } - if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) XGI_GetVBType(pVBInfo); InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo); @@ -6703,12 +6699,12 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, ModeNo = ModeNo & 0x7F; xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86); - if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 1.Openkey */ + if (HwDeviceExtension->jChipType < XG20) XGI_UnLockCRT2(HwDeviceExtension, pVBInfo); XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo); - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) { XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo); XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo); XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo); @@ -6779,7 +6775,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo); - if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */ + if (HwDeviceExtension->jChipType < XG20) { XGI_LockCRT2(HwDeviceExtension, pVBInfo); } diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index aea760ad4ae2..22c8eb9810d6 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -28,7 +28,6 @@ struct XGI_Ext2Struct { unsigned char ModeID; unsigned short XRes; unsigned short YRes; - /* unsigned short ROM_OFFSET; */ }; struct XGI_ECLKDataStruct { @@ -167,7 +166,6 @@ struct vb_device_info { unsigned short LCDHRS, LCDVRS, LCDHDES, LCDVDES; unsigned short ModeType; - /* ,IF_DEF_FSTN; add for dstn */ unsigned short IF_DEF_LVDS, IF_DEF_TRUMPION, IF_DEF_DSTN; unsigned short IF_DEF_CRT2Monitor; unsigned short IF_DEF_LCDA, IF_DEF_YPbPr; @@ -225,7 +223,6 @@ struct vb_device_info { struct SiS_StandTable_S *StandTable; struct XGI_ExtStruct *EModeIDTable; struct XGI_Ext2Struct *RefIndex; - /* XGINew_CRT1TableStruct *CRT1Table; */ struct XGI_CRT1TableStruct *XGINEWUB_CRT1Table; struct SiS_VCLKData *VCLKData; struct SiS_VBVCLKData *VBVCLKData; diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 75da7c3e1baf..ca8c68d6fb16 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1,6 +1,5 @@ #ifndef _VB_TABLE_ #define _VB_TABLE_ -/* yilin modify for xgi20 */ static struct SiS_MCLKData XGI340New_MCLKData[] = { {0x16, 0x01, 0x01, 166}, {0x19, 0x02, 0x01, 124}, @@ -23,7 +22,6 @@ static struct SiS_MCLKData XGI27New_MCLKData[] = { {0x5c, 0x23, 0x01, 166} }; -/* yilin modify for xgi20 */ static struct XGI_ECLKDataStruct XGI340_ECLKData[] = { {0x5c, 0x23, 0x01, 166}, {0x55, 0x84, 0x01, 123}, @@ -424,13 +422,9 @@ static struct SiS_LCDData XGI_StLCD1024x768Data[] = { }; static struct SiS_LCDData XGI_ExtLCD1024x768Data[] = { - /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */ {42, 25, 1536, 419, 1344, 806}, - /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */ {48, 25, 1536, 369, 1344, 806}, - /* { 32, 15,1008, 505,1344, 806}, // alan 09/12/2003 */ {42, 25, 1536, 419, 1344, 806}, - /* { 32, 15,1008, 514,1344, 806}, // alan 09/12/2003 */ {48, 25, 1536, 369, 1344, 806}, {12, 5, 896, 500, 1344, 806}, {42, 25, 1024, 625, 1344, 806}, @@ -504,14 +498,10 @@ static struct SiS_LCDData xgifb_lcd_1400x1050[] = { }; static struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = { - {4, 1, 1620, 420, 2160, 1250}, /* { 3,1,2160,425,2160,1250 }, - // 00 (320x200,320x400, - // 640x200,640x400) - // // alan 10/14/2003 */ + {4, 1, 1620, 420, 2160, 1250}, /* 00 (320x200,320x400, + 640x200,640x400)*/ {27, 7, 1920, 375, 2160, 1250}, /* 01 (320x350,640x350) */ - {4, 1, 1620, 420, 2160, 1250}, /* { 3,1,2160,425,2160,1250 }, - // 02 (360x400,720x400) - // // alan 10/14/2003 */ + {4, 1, 1620, 420, 2160, 1250}, /* 02 (360x400,720x400)*/ {27, 7, 1920, 375, 2160, 1250}, /* 03 (720x350) */ {27, 4, 800, 500, 2160, 1250}, /* 04 (640x480x60Hz) */ {4, 1, 1080, 625, 2160, 1250}, /* 05 (800x600x60Hz) */ @@ -615,8 +605,7 @@ static struct SiS_LCDData XGI_NoScalingDatax75[] = { {1, 1, 1056, 625, 1056, 625}, /* ; 05 (800x600x75Hz) */ {1, 1, 1312, 800, 1312, 800}, /* ; 06 (1024x768x75Hz) */ {1, 1, 1688, 1066, 1688, 1066}, /* ; 07 (1280x1024x75Hz) */ - {1, 1, 1688, 1066, 1688, 1066}, /* ; 08 (1400x1050x75Hz) - ;;[ycchen] 12/19/02 */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 08 (1400x1050x75Hz)*/ {1, 1, 2160, 1250, 2160, 1250}, /* ; 09 (1600x1200x75Hz) */ {1, 1, 1688, 806, 1688, 806} /* ; 0A (1280x768x75Hz) */ }; @@ -823,8 +812,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[] = { {9, 849, 627, 600, 128, 4}, /* 05 (800x600x60Hz) */ {9, 1057, 805, 770, 0136, 6}, /* 06 (1024x768x60Hz) */ {9, 1337, 0, 1025, 112, 3}, /* 07 (1280x1024x60Hz) */ - {9, 1457, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz) }, - //;[ycchen] 12/19/02 */ + {9, 1457, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz)*/ {9, 1673, 0, 1201, 192, 3}, /* 09 (1600x1200x60Hz) */ {9, 1337, 0, 771, 112, 6} /* 0A (1280x768x60Hz) */ }; @@ -910,8 +898,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] = { {9, 825, 0, 601, 80, 3}, /* ; 05 (800x600x75Hz) */ {9, 1049, 0, 769, 96, 3}, /* ; 06 (1024x768x75Hz) */ {9, 1305, 0, 1025, 144, 3}, /* ; 07 (1280x1024x75Hz) */ - {9, 1457, 0, 1051, 112, 3}, /* ; 08 (1400x1050x60Hz) - ;;[ycchen] 12/19/02 */ + {9, 1457, 0, 1051, 112, 3}, /* ; 08 (1400x1050x60Hz)*/ {9, 1673, 0, 1201, 192, 3}, /* ; 09 (1600x1200x75Hz) */ {9, 1337, 0, 771, 112, 6} /* ; 0A (1280x768x60Hz) */ }; @@ -1308,7 +1295,7 @@ static struct SiS_LVDSData XGI_LVDSNoScalingData[] = { {1056, 628, 1056, 628}, /* 05 (800x600x60Hz) */ {1344, 806, 1344, 806}, /* 06 (1024x768x60Hz) */ {1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz) */ - {1688, 1066, 1688, 1066}, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */ + {1688, 1066, 1688, 1066}, /* 08 (1400x1050x60Hz) */ {2160, 1250, 2160, 1250}, /* 09 (1600x1200x60Hz) */ {1688, 806, 1688, 806} /* 0A (1280x768x60Hz) */ }; @@ -1469,8 +1456,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[] = { {0, 840, 627, 600, 128, 4}, /* 05 (800x600x60Hz) */ {0, 1048, 805, 770, 136, 6}, /* 06 (1024x768x60Hz) */ {0, 1328, 0, 1025, 112, 3}, /* 07 (1280x1024x60Hz) */ - {0, 1438, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz) - ;;[ycchen] 12/19/02 */ + {0, 1438, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz)*/ {0, 1664, 0, 1201, 192, 3}, /* 09 (1600x1200x60Hz) */ {0, 1328, 0, 0771, 112, 6} /* 0A (1280x768x60Hz) */ }; @@ -1518,7 +1504,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = { }; /* The Display setting for DE Mode Panel */ -/* [ycchen] 02/18/03 Set DE as default */ +/* Set DE as default */ static struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = { {1368, 976, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */ {1368, 976, 729, 688}, /* ; 01 (320x350,640x350) */ @@ -1541,8 +1527,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = { {0, 816, 0, 601, 80, 3}, /* ; 05 (800x600x75Hz) */ {0, 1040, 0, 769, 96, 3}, /* ; 06 (1024x768x75Hz) */ {0, 1296, 0, 1025, 144, 3}, /* ; 07 (1280x1024x75Hz) */ - {0, 1448, 0, 1051, 112, 3}, /* ; 08 (1400x1050x75Hz) - ;;[ycchen] 12/19/02 */ + {0, 1448, 0, 1051, 112, 3}, /* ; 08 (1400x1050x75Hz) */ {0, 1664, 0, 1201, 192, 3}, /* ; 09 (1600x1200x75Hz) */ {0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */ }; -- GitLab From c2dd691eed6356610a7ce9836d36d1aba3145b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:37 +0200 Subject: [PATCH 2528/5711] Staging: xgifb: Remove unneeded XGI_LCD_TYPE enumeration. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LCD_TYPEs are taken from drivers/video/sis/sis.h, so this enumeration is not needed. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vgatypes.h | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h index 7fc07194eea2..ddf7776c295b 100644 --- a/drivers/staging/xgifb/vgatypes.h +++ b/drivers/staging/xgifb/vgatypes.h @@ -21,40 +21,6 @@ enum XGI_VB_CHIP_TYPE { }; #endif - -#define XGI_LCD_TYPE -/* Since the merge with video/sis the LCD_TYPEs are used from - drivers/video/sis/sis.h . Nevertheless we keep this (for the moment) for - future reference until the code is merged completely and we are sure - nothing of this should be added to the sis.h header */ -#ifndef XGI_LCD_TYPE -enum XGI_LCD_TYPE { - LCD_INVALID = 0, - LCD_320x480, /* FSTN, DSTN */ - LCD_640x480, - LCD_640x480_2, /* FSTN, DSTN */ - LCD_640x480_3, /* FSTN, DSTN */ - LCD_800x600, - LCD_848x480, - LCD_1024x600, - LCD_1024x768, - LCD_1152x768, - LCD_1152x864, - LCD_1280x720, - LCD_1280x768, - LCD_1280x800, - LCD_1280x960, - LCD_1280x1024, - LCD_1400x1050, - LCD_1600x1200, - LCD_1680x1050, - LCD_1920x1440, - LCD_2048x1536, - LCD_CUSTOM, - LCD_UNKNOWN -}; -#endif - struct xgi_hw_device_info { unsigned long ulExternalChip; /* NO VB or other video bridge*/ /* if ujVBChipID = VB_CHIP_UNKNOWN, */ -- GitLab From 469b43c0a67d14c3c87fa87907999d1894156015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:38 +0200 Subject: [PATCH 2529/5711] Staging: xgifb: Remove LCDA detection in xgifb_probe(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The piece of code that checks for LCDA in xgifb_probe() just checks for some register values but doesn't really do anything in response to them (the actions that should be executed are commented). As nothing is really being done, the code can be safely removed. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index b226458272a3..0307ecac0ef8 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1952,36 +1952,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } } - if ((hw_info->ujVBChipID == VB_CHIP_302B) || - (hw_info->ujVBChipID == VB_CHIP_301LV) || - (hw_info->ujVBChipID == VB_CHIP_302LV)) { - int tmp; - tmp = xgifb_reg_get(XGICR, 0x34); - if (tmp <= 0x13) { - /* Currently on LCDA? - *(Some BIOSes leave CR38) */ - tmp = xgifb_reg_get(XGICR, 0x38); - if ((tmp & 0x03) == 0x03) { - /* XGI_Pr.XGI_UseLCDA = 1; */ - } else { - /* Currently on LCDA? - *(Some newer BIOSes set D0 in CR35) */ - tmp = xgifb_reg_get(XGICR, 0x35); - if (tmp & 0x01) { - /* XGI_Pr.XGI_UseLCDA = 1; */ - } else { - tmp = xgifb_reg_get(XGICR, - 0x30); - if (tmp & 0x20) { - tmp = xgifb_reg_get( - XGIPART1, 0x13); - } - } - } - } - - } - xgifb_info->mode_idx = -1; if (mode) -- GitLab From 61439fa873d98654a9f985854c634896384ee3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:39 +0200 Subject: [PATCH 2530/5711] Staging: xgifb: Remove unused struct _chswtable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Struct _chswtable and the variable mychswtable are not used anywhere, so remove them. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index 1686c5acda13..c033da408a58 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -227,16 +227,6 @@ static const struct _XGI_vrate { {0, 0, 0, 0} }; -static const struct _chswtable { - int subsysVendor; - int subsysCard; - char *vendorName; - char *cardName; -} mychswtable[] = { - { 0x1631, 0x1002, "Mitachi", "0x1002" }, - { 0, 0, "" , "" } -}; - static const struct _XGI_TV_filter { u8 filter[9][4]; } XGI_TV_filter[] = { -- GitLab From be25aef0ca638ea798fdb836291b2d5e5fe555ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:40 +0200 Subject: [PATCH 2531/5711] Staging: xgifb: Improve debug strings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 34 ++++++++++++++--------------- drivers/staging/xgifb/vb_init.c | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 0307ecac0ef8..d5c87eae5cf4 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -39,14 +39,14 @@ static void dumpVGAReg(void) for (i = 0; i < 0x4f; i++) { reg = xgifb_reg_get(XGISR, i); - pr_debug("\no 3c4 %x", i); - pr_debug("\ni 3c5 => %x", reg); + pr_debug("o 3c4 %x\n", i); + pr_debug("i 3c5 => %x\n", reg); } for (i = 0; i < 0xF0; i++) { reg = xgifb_reg_get(XGICR, i); - pr_debug("\no 3d4 %x", i); - pr_debug("\ni 3d5 => %x", reg); + pr_debug("o 3d4 %x\n", i); + pr_debug("i 3d5 => %x\n", reg); } } #else @@ -591,7 +591,7 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, break; } else if (XGIfb_vrate[i].refresh > rate) { if ((XGIfb_vrate[i].refresh - rate) <= 3) { - pr_debug("XGIfb: Adjusting rate from %d up to %d\n", + pr_debug("Adjusting rate from %d up to %d\n", rate, XGIfb_vrate[i].refresh); xgifb_info->rate_idx = XGIfb_vrate[i].idx; @@ -600,7 +600,7 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, } else if (((rate - XGIfb_vrate[i - 1].refresh) <= 2) && (XGIfb_vrate[i].idx != 1)) { - pr_debug("XGIfb: Adjusting rate from %d down to %d\n", + pr_debug("Adjusting rate from %d down to %d\n", rate, XGIfb_vrate[i-1].refresh); xgifb_info->rate_idx = XGIfb_vrate[i - 1].idx; @@ -609,7 +609,7 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, } break; } else if ((rate - XGIfb_vrate[i].refresh) <= 2) { - pr_debug("XGIfb: Adjusting rate from %d down to %d\n", + pr_debug("Adjusting rate from %d down to %d\n", rate, XGIfb_vrate[i].refresh); xgifb_info->rate_idx = XGIfb_vrate[i].idx; break; @@ -987,7 +987,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } if (!htotal || !vtotal) { - pr_debug("XGIfb: Invalid 'var' information\n"); + pr_debug("Invalid 'var' information\n"); return -EINVAL; } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n", var->pixclock, htotal, vtotal); @@ -1063,7 +1063,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, XGIfb_post_setmode(xgifb_info); - pr_debug("XGIfb: Set new mode: %dx%dx%d-%d\n", + pr_debug("Set new mode: %dx%dx%d-%d\n", XGIbios_mode[xgifb_info->mode_idx].xres, XGIbios_mode[xgifb_info->mode_idx].yres, XGIbios_mode[xgifb_info->mode_idx].bpp, @@ -1109,7 +1109,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, break; default: xgifb_info->video_cmap_len = 16; - pr_err("Unsupported depth %d", + pr_err("Unsupported depth %d\n", xgifb_info->video_bpp); break; } @@ -1303,7 +1303,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) + var->vsync_len; if (!(htotal) || !(vtotal)) { - pr_debug("XGIfb: no valid timing data\n"); + pr_debug("No valid timing data\n"); return -EINVAL; } @@ -1661,7 +1661,7 @@ static int __init xgifb_optval(char *fullopt, int validx) unsigned long lres; if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) { - pr_err("xgifb: invalid value for option: %s\n", fullopt); + pr_err("Invalid value for option: %s\n", fullopt); return 0; } return lres; @@ -1674,7 +1674,7 @@ static int __init XGIfb_setup(char *options) if (!options || !*options) return 0; - pr_info("xgifb: options: %s\n", options); + pr_info("Options: %s\n", options); while ((this_opt = strsep(&options, ",")) != NULL) { @@ -1767,7 +1767,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD); if (reg1 != 0xa1) { /*I/O error */ - dev_err(&pdev->dev, "I/O error!!!"); + dev_err(&pdev->dev, "I/O error\n"); ret = -EIO; goto error_disable; } @@ -1817,7 +1817,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (!request_mem_region(xgifb_info->video_base, xgifb_info->video_size, "XGIfb FB")) { - dev_err(&pdev->dev, "unable request memory size %x\n", + dev_err(&pdev->dev, "Unable request memory size %x\n", xgifb_info->video_size); dev_err(&pdev->dev, "Fatal error: Unable to reserve frame buffer memory. " @@ -1973,7 +1973,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } if (xgifb_info->mode_idx < 0) { - dev_err(&pdev->dev, "no supported video mode found\n"); + dev_err(&pdev->dev, "No supported video mode found\n"); goto error_1; } @@ -2085,7 +2085,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->mtrr = mtrr_add(xgifb_info->video_base, xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1); if (xgifb_info->mtrr >= 0) - dev_info(&pdev->dev, "added MTRR\n"); + dev_info(&pdev->dev, "Added MTRR\n"); #endif if (register_framebuffer(fb_info) < 0) { diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 6bb020697a59..64935fa0a6db 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -951,7 +951,7 @@ static void xgifb_read_vbios(struct pci_dev *pdev, pVBInfo->IF_DEF_LVDS = 0; vbios = xgifb_copy_rom(pdev, &vbios_size); if (vbios == NULL) { - dev_err(&pdev->dev, "video BIOS not available\n"); + dev_err(&pdev->dev, "Video BIOS not available\n"); return; } if (vbios_size <= 0x65) @@ -1006,7 +1006,7 @@ static void xgifb_read_vbios(struct pci_dev *pdev, pVBInfo->IF_DEF_LVDS = 1; return; error: - dev_err(&pdev->dev, "video BIOS corrupted\n"); + dev_err(&pdev->dev, "Video BIOS corrupted\n"); vfree(vbios); } -- GitLab From 1cd17030813007578e7b5eb0aa7dec13d6ed9a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:41 +0200 Subject: [PATCH 2532/5711] Staging: xgifb: Remove useless switch in XGIfb_detect_VB(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The switch performs no action so it can be removed. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index d5c87eae5cf4..788d141beca4 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1556,16 +1556,6 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) xgifb_info->TV_plug = xgifb_info->TV_type = 0; - switch (xgifb_info->hasVB) { - case HASVB_LVDS_CHRONTEL: - case HASVB_CHRONTEL: - break; - case HASVB_301: - case HASVB_302: - /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */ - break; - } - cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32); if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) -- GitLab From 791fef1b30861d1125222780d4eaae00cb3a4563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:42 +0200 Subject: [PATCH 2533/5711] Staging: xgifb: Simplify XGIfb_GetXG21DefaultLVDSModeIdx(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the code and make it more readable. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 788d141beca4..c1aa0375680f 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -262,28 +262,19 @@ static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr) static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info) { + int i = 0; - int found_mode = 0; - int XGIfb_mode_idx = 0; - - found_mode = 0; - while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0) - && (XGIbios_mode[XGIfb_mode_idx].xres - <= xgifb_info->lvds_data.LVDSHDE)) { - if ((XGIbios_mode[XGIfb_mode_idx].xres - == xgifb_info->lvds_data.LVDSHDE) - && (XGIbios_mode[XGIfb_mode_idx].yres - == xgifb_info->lvds_data.LVDSVDE) - && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) { - found_mode = 1; - break; + while ((XGIbios_mode[i].mode_no != 0) + && (XGIbios_mode[i].xres <= xgifb_info->lvds_data.LVDSHDE)) { + if ((XGIbios_mode[i].xres == xgifb_info->lvds_data.LVDSHDE) + && (XGIbios_mode[i].yres == xgifb_info->lvds_data.LVDSVDE) + && (XGIbios_mode[i].bpp == 8)) { + return i; } - XGIfb_mode_idx++; + i++; } - if (!found_mode) - XGIfb_mode_idx = -1; - return XGIfb_mode_idx; + return -1; } static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info, -- GitLab From 4362f5becde07b43ec9d57a6a713c955dd2703e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:43 +0200 Subject: [PATCH 2534/5711] Staging: xgifb: Remove unneeded var and condition in XGIfb_search_vesamode(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index c1aa0375680f..e5657ffa4cd0 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -305,7 +305,7 @@ invalid_mode: static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info, unsigned int vesamode) { - int i = 0, j = 0; + int i = 0; if (vesamode == 0) goto invalid; @@ -316,15 +316,13 @@ static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info, if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) || (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) { xgifb_info->mode_idx = i; - j = 1; - break; + return; } i++; } invalid: - if (!j) - pr_info("Invalid VESA mode 0x%x'\n", vesamode); + pr_info("Invalid VESA mode 0x%x'\n", vesamode); } static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) -- GitLab From 8afb7d3528444a8a6d6032ce04f7cc1a19b30ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:44 +0200 Subject: [PATCH 2535/5711] Staging: xgifb: Remove useless always true condition. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 64935fa0a6db..ae10153503d5 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1185,13 +1185,11 @@ static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, { unsigned char Temp; -#if 1 if (pVBInfo->IF_DEF_LVDS) { /* For XG21 LVDS */ xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense); /* LVDS on chip */ xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); } else { -#endif /* Enable GPIOA/B read */ xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03); Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0xC0; @@ -1214,9 +1212,7 @@ static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, /* Disable read GPIOF */ xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x20); } -#if 1 } -#endif } static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, -- GitLab From 661a6384f85fd2229b4e14229d5479ab1a1c1322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:45 +0200 Subject: [PATCH 2536/5711] Staging: xgifb: Rework conditions in XGI_SetATTRegs(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 3ba3c48a5696..4b49705c04c4 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -161,18 +161,15 @@ static void XGI_SetATTRegs(unsigned short ModeNo, for (i = 0; i <= 0x13; i++) { ARdata = pVBInfo->StandTable->ATTR[i]; - if (modeflag & Charx8Dot) { /* ifndef Dot9 */ - if (i == 0x13) { - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { + + if ((modeflag & Charx8Dot) && i == 0x13) { /* ifndef Dot9 */ + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { + ARdata = 0; + } else { + if ((pVBInfo->VBInfo & + (SetCRT2ToTV | SetCRT2ToLCD)) && + (pVBInfo->VBInfo & SetInSlaveMode)) ARdata = 0; - } else { - if (pVBInfo->VBInfo & (SetCRT2ToTV - | SetCRT2ToLCD)) { - if (pVBInfo->VBInfo & - SetInSlaveMode) - ARdata = 0; - } - } } } -- GitLab From 3b175621a217a354a0f38172381f8f88fe7a59be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:46 +0200 Subject: [PATCH 2537/5711] Staging: xgifb: Refactor XGI_AjustCRT2Rate(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 73 ++++++++++-------------------- 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 4b49705c04c4..03edf36e18df 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -250,48 +250,30 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempax |= SupportLCD; - if (pVBInfo->LCDResInfo != Panel_1280x1024) { - if (pVBInfo->LCDResInfo != Panel_1280x960) { - if (pVBInfo->LCDInfo & - LCDNonExpanding) { - if (resinfo >= 9) { - tempax = 0; - return 0; - } - } - } - } + if (pVBInfo->LCDResInfo != Panel_1280x1024 && + pVBInfo->LCDResInfo != Panel_1280x960 && + (pVBInfo->LCDInfo & LCDNonExpanding) && + resinfo >= 9) + return 0; } if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */ if ((pVBInfo->VBType & VB_SIS301LV) && (pVBInfo->VBExtInfo == VB_YPbPr1080i)) { tempax |= SupportYPbPr750p; - if (pVBInfo->VBInfo & SetInSlaveMode) { - if (resinfo == 4) - return 0; - - if (resinfo == 3) - return 0; - - if (resinfo > 7) - return 0; - } + if ((pVBInfo->VBInfo & SetInSlaveMode) && + ((resinfo == 3) || + (resinfo == 4) || + (resinfo > 7))) + return 0; } else { tempax |= SupportHiVision; - if (pVBInfo->VBInfo & SetInSlaveMode) { - if (resinfo == 4) + if ((pVBInfo->VBInfo & SetInSlaveMode) && + ((resinfo == 4) || + (resinfo == 3 && + (pVBInfo->SetFlag & TVSimuMode)) || + (resinfo > 7))) return 0; - - if (resinfo == 3) { - if (pVBInfo->SetFlag - & TVSimuMode) - return 0; - } - - if (resinfo > 7) - return 0; - } } } else { if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | @@ -301,23 +283,18 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, SetCRT2ToHiVision)) { tempax |= SupportTV; - if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B - | VB_SIS301LV | VB_SIS302LV - | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | + VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | + VB_XGI301C)) tempax |= SupportTV1024; - } - if (!(pVBInfo->VBInfo & TVSetPAL)) { - if (modeflag & NoSupportSimuTV) { - if (pVBInfo->VBInfo & - SetInSlaveMode) { - if (!(pVBInfo->VBInfo & - SetNotSimuMode)) { - return 0; - } - } - } - } + if (!(pVBInfo->VBInfo & TVSetPAL) && + (modeflag & NoSupportSimuTV) && + (pVBInfo->VBInfo & SetInSlaveMode) && + (!(pVBInfo->VBInfo & SetNotSimuMode))) + return 0; } } } else { /* for LVDS */ -- GitLab From 7eec23a7b3dd0bcb9b64c0627b317464765e2426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:47 +0200 Subject: [PATCH 2538/5711] Staging: xgifb: Refactor XGI_GetVBType(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor XGI_GetVBType() to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 69 ++++++++++++++++-------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 03edf36e18df..251145ea0f39 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -2559,42 +2559,45 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo) { unsigned short flag, tempbx, tempah; - if (pVBInfo->IF_DEF_LVDS == 0) { - tempbx = VB_SIS302B; - flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00); - if (flag != 0x02) { - tempbx = VB_SIS301; - flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01); - if (flag >= 0xB0) { - tempbx = VB_SIS301B; - if (flag >= 0xC0) { - tempbx = VB_XGI301C; - if (flag >= 0xD0) { - tempbx = VB_SIS301LV; - if (flag >= 0xE0) { - tempbx = VB_SIS302LV; - tempah = xgifb_reg_get( - pVBInfo->Part4Port, - 0x39); - if (tempah != 0xFF) - tempbx = - VB_XGI301C; - } - } - } + if (pVBInfo->IF_DEF_LVDS != 0) + return; - if (tempbx & (VB_SIS301B | VB_SIS302B)) { - flag = xgifb_reg_get( - pVBInfo->Part4Port, - 0x23); + tempbx = VB_SIS302B; + flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00); + if (flag == 0x02) + goto finish; - if (!(flag & 0x02)) - tempbx = tempbx | VB_NoLCD; - } - } - } - pVBInfo->VBType = tempbx; + tempbx = VB_SIS301; + flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01); + if (flag < 0xB0) + goto finish; + + tempbx = VB_SIS301B; + if (flag < 0xC0) + goto bigger_than_0xB0; + + tempbx = VB_XGI301C; + if (flag < 0xD0) + goto bigger_than_0xB0; + + tempbx = VB_SIS301LV; + if (flag < 0xE0) + goto bigger_than_0xB0; + + tempbx = VB_SIS302LV; + tempah = xgifb_reg_get(pVBInfo->Part4Port, 0x39); + if (tempah != 0xFF) + tempbx = VB_XGI301C; + +bigger_than_0xB0: + if (tempbx & (VB_SIS301B | VB_SIS302B)) { + flag = xgifb_reg_get(pVBInfo->Part4Port, 0x23); + if (!(flag & 0x02)) + tempbx = tempbx | VB_NoLCD; } + +finish: + pVBInfo->VBType = tempbx; } static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, -- GitLab From f93173515f809fbcf251a3b1742e8659cc75dd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:48 +0200 Subject: [PATCH 2539/5711] Staging: xgifb: Rework conditions in XGI_GetVBInfo(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 287 ++++++++++++++--------------- 1 file changed, 142 insertions(+), 145 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 251145ea0f39..9dfc2deacd0a 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -2611,186 +2611,183 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->ModeType = modeflag & ModeTypeMask; tempbx = 0; - if (pVBInfo->VBType & 0xFFFF) { - /* Check Display Device */ - temp = xgifb_reg_get(pVBInfo->P3d4, 0x30); - tempbx = tempbx | temp; - temp = xgifb_reg_get(pVBInfo->P3d4, 0x31); - push = temp; - push = push << 8; - tempax = temp << 8; - tempbx = tempbx | tempax; - temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA - | SetInSlaveMode | DisableCRT2Display); - temp = 0xFFFF ^ temp; - tempbx &= temp; - - temp = xgifb_reg_get(pVBInfo->P3d4, 0x38); + if (!(pVBInfo->VBType & 0xFFFF)) + return; - if (pVBInfo->IF_DEF_LCDA == 1) { - - if ((HwDeviceExtension->jChipType >= XG20) || - (HwDeviceExtension->jChipType >= XG40)) { - if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->VBType & - (VB_SIS302B | - VB_SIS301LV | - VB_SIS302LV | - VB_XGI301C)) { - if (temp & EnableDualEdge) { - tempbx |= - SetCRT2ToDualEdge; - - if (temp & SetToLCDA) - tempbx |= - XGI_SetCRT2ToLCDA; - } - } + /* Check Display Device */ + temp = xgifb_reg_get(pVBInfo->P3d4, 0x30); + tempbx = tempbx | temp; + temp = xgifb_reg_get(pVBInfo->P3d4, 0x31); + push = temp; + push = push << 8; + tempax = temp << 8; + tempbx = tempbx | tempax; + temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA + | SetInSlaveMode | DisableCRT2Display); + temp = 0xFFFF ^ temp; + tempbx &= temp; + + temp = xgifb_reg_get(pVBInfo->P3d4, 0x38); + + if (pVBInfo->IF_DEF_LCDA == 1) { + + if (((HwDeviceExtension->jChipType >= XG20) || + (HwDeviceExtension->jChipType >= XG40)) && + (pVBInfo->IF_DEF_LVDS == 0)) { + if (pVBInfo->VBType & + (VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | + VB_XGI301C)) { + if (temp & EnableDualEdge) { + tempbx |= SetCRT2ToDualEdge; + if (temp & SetToLCDA) + tempbx |= XGI_SetCRT2ToLCDA; } } } + } - if (pVBInfo->IF_DEF_YPbPr == 1) { - if (((pVBInfo->IF_DEF_LVDS == 0) && - ((pVBInfo->VBType & VB_SIS301LV) || - (pVBInfo->VBType & VB_SIS302LV) || - (pVBInfo->VBType & VB_XGI301C)))) { - if (temp & SetYPbPr) { - if (pVBInfo->IF_DEF_HiVision == 1) { - /* shampoo add for new - * scratch */ - temp = xgifb_reg_get( - pVBInfo->P3d4, - 0x35); - temp &= YPbPrMode; - tempbx |= SetCRT2ToHiVision; - - if (temp != YPbPrMode1080i) { - tempbx &= - (~SetCRT2ToHiVision); - tempbx |= - SetCRT2ToYPbPr525750; - } + if (pVBInfo->IF_DEF_YPbPr == 1) { + if (((pVBInfo->IF_DEF_LVDS == 0) && + ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV) || + (pVBInfo->VBType & VB_XGI301C)))) { + if (temp & SetYPbPr) { + if (pVBInfo->IF_DEF_HiVision == 1) { + /* shampoo add for new + * scratch */ + temp = xgifb_reg_get( + pVBInfo->P3d4, + 0x35); + temp &= YPbPrMode; + tempbx |= SetCRT2ToHiVision; + + if (temp != YPbPrMode1080i) { + tempbx &= + (~SetCRT2ToHiVision); + tempbx |= + SetCRT2ToYPbPr525750; } } } } + } - tempax = push; /* restore CR31 */ + tempax = push; /* restore CR31 */ - if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->IF_DEF_YPbPr == 1) { - if (pVBInfo->IF_DEF_HiVision == 1) - temp = 0x09FC; - else - temp = 0x097C; - } else { - if (pVBInfo->IF_DEF_HiVision == 1) - temp = 0x01FC; - else - temp = 0x017C; - } - } else { /* 3nd party chip */ - temp = SetCRT2ToLCD; - } - - if (!(tempbx & temp)) { - tempax |= DisableCRT2Display; - tempbx = 0; - } - - if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */ - if (!(pVBInfo->VBType & VB_NoLCD)) { - if (tempbx & XGI_SetCRT2ToLCDA) { - if (tempbx & SetSimuScanMode) - tempbx &= (~(SetCRT2ToLCD | - SetCRT2ToRAMDAC | - SwitchCRT2)); - else - tempbx &= (~(SetCRT2ToLCD | - SetCRT2ToRAMDAC | - SetCRT2ToTV | - SwitchCRT2)); - } - } + if (pVBInfo->IF_DEF_LVDS == 0) { + if (pVBInfo->IF_DEF_YPbPr == 1) { + if (pVBInfo->IF_DEF_HiVision == 1) + temp = 0x09FC; + else + temp = 0x097C; + } else { + if (pVBInfo->IF_DEF_HiVision == 1) + temp = 0x01FC; + else + temp = 0x017C; } + } else { /* 3nd party chip */ + temp = SetCRT2ToLCD; + } - /* shampoo add */ - /* for driver abnormal */ - if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) { - if (pVBInfo->IF_DEF_CRT2Monitor == 1) { - if (tempbx & SetCRT2ToRAMDAC) { - tempbx &= (0xFF00 | - SetCRT2ToRAMDAC | - SwitchCRT2 | - SetSimuScanMode); - tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); - } - } else { - tempbx &= (~(SetCRT2ToRAMDAC | - SetCRT2ToLCD | - SetCRT2ToTV)); + if (!(tempbx & temp)) { + tempax |= DisableCRT2Display; + tempbx = 0; + } + + if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */ + if (!(pVBInfo->VBType & VB_NoLCD)) { + if (tempbx & XGI_SetCRT2ToLCDA) { + if (tempbx & SetSimuScanMode) + tempbx &= (~(SetCRT2ToLCD | + SetCRT2ToRAMDAC | + SwitchCRT2)); + else + tempbx &= (~(SetCRT2ToLCD | + SetCRT2ToRAMDAC | + SetCRT2ToTV | + SwitchCRT2)); } } + } - if (!(pVBInfo->VBType & VB_NoLCD)) { - if (tempbx & SetCRT2ToLCD) { + /* shampoo add */ + /* for driver abnormal */ + if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) { + if (pVBInfo->IF_DEF_CRT2Monitor == 1) { + if (tempbx & SetCRT2ToRAMDAC) { tempbx &= (0xFF00 | - SetCRT2ToLCD | + SetCRT2ToRAMDAC | SwitchCRT2 | SetSimuScanMode); tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } + } else { + tempbx &= (~(SetCRT2ToRAMDAC | + SetCRT2ToLCD | + SetCRT2ToTV)); } + } - if (tempbx & SetCRT2ToSCART) { + if (!(pVBInfo->VBType & VB_NoLCD)) { + if (tempbx & SetCRT2ToLCD) { tempbx &= (0xFF00 | - SetCRT2ToSCART | + SetCRT2ToLCD | SwitchCRT2 | SetSimuScanMode); tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } + } - if (pVBInfo->IF_DEF_YPbPr == 1) { - if (tempbx & SetCRT2ToYPbPr525750) - tempbx &= (0xFF00 | - SwitchCRT2 | - SetSimuScanMode); - } + if (tempbx & SetCRT2ToSCART) { + tempbx &= (0xFF00 | + SetCRT2ToSCART | + SwitchCRT2 | + SetSimuScanMode); + tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); + } - if (pVBInfo->IF_DEF_HiVision == 1) { - if (tempbx & SetCRT2ToHiVision) - tempbx &= (0xFF00 | - SetCRT2ToHiVision | - SwitchCRT2 | - SetSimuScanMode); - } + if (pVBInfo->IF_DEF_YPbPr == 1) { + if (tempbx & SetCRT2ToYPbPr525750) + tempbx &= (0xFF00 | + SwitchCRT2 | + SetSimuScanMode); + } - if (tempax & DisableCRT2Display) { /* Set Display Device Info */ - if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) - tempbx = DisableCRT2Display; - } + if (pVBInfo->IF_DEF_HiVision == 1) { + if (tempbx & SetCRT2ToHiVision) + tempbx &= (0xFF00 | + SetCRT2ToHiVision | + SwitchCRT2 | + SetSimuScanMode); + } - if (!(tempbx & DisableCRT2Display)) { - if ((!(tempbx & DriverMode)) || - (!(modeflag & CRT2Mode))) { - if (pVBInfo->IF_DEF_LCDA == 1) { - if (!(tempbx & XGI_SetCRT2ToLCDA)) - tempbx |= (SetInSlaveMode | - SetSimuScanMode); - } - } + if (tempax & DisableCRT2Display) { /* Set Display Device Info */ + if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) + tempbx = DisableCRT2Display; + } - /* LCD+TV can't support in slave mode - * (Force LCDA+TV->LCDB) */ - if ((tempbx & SetInSlaveMode) && - (tempbx & XGI_SetCRT2ToLCDA)) { - tempbx ^= (SetCRT2ToLCD | - XGI_SetCRT2ToLCDA | - SetCRT2ToDualEdge); - pVBInfo->SetFlag |= ReserveTVOption; + if (!(tempbx & DisableCRT2Display)) { + if ((!(tempbx & DriverMode)) || + (!(modeflag & CRT2Mode))) { + if (pVBInfo->IF_DEF_LCDA == 1) { + if (!(tempbx & XGI_SetCRT2ToLCDA)) + tempbx |= (SetInSlaveMode | + SetSimuScanMode); } } + + /* LCD+TV can't support in slave mode + * (Force LCDA+TV->LCDB) */ + if ((tempbx & SetInSlaveMode) && + (tempbx & XGI_SetCRT2ToLCDA)) { + tempbx ^= (SetCRT2ToLCD | + XGI_SetCRT2ToLCDA | + SetCRT2ToDualEdge); + pVBInfo->SetFlag |= ReserveTVOption; + } } pVBInfo->VBInfo = tempbx; -- GitLab From 3339db8a0c0182b6be7dcece9647f2d4307576b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:49 +0200 Subject: [PATCH 2540/5711] Staging: xgifb: Refactor XGI_GetCRT2ResInfo(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a goto to remove one level of indentation, fixing style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 61 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 9dfc2deacd0a..a7ba99f42a68 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -3263,46 +3263,47 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, if (modeflag & DoubleScanMode) yres *= 2; - if (pVBInfo->VBInfo & SetCRT2ToLCD) { - if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->LCDResInfo == Panel_1600x1200) { - if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { - if (yres == 1024) - yres = 1056; - } + if (!(pVBInfo->VBInfo & SetCRT2ToLCD)) + goto exit; + + if (pVBInfo->IF_DEF_LVDS == 0) { + if (pVBInfo->LCDResInfo == Panel_1600x1200) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { + if (yres == 1024) + yres = 1056; } + } - if (pVBInfo->LCDResInfo == Panel_1280x1024) { - if (yres == 400) - yres = 405; - else if (yres == 350) - yres = 360; + if (pVBInfo->LCDResInfo == Panel_1280x1024) { + if (yres == 400) + yres = 405; + else if (yres == 350) + yres = 360; - if (pVBInfo->LCDInfo & XGI_LCDVESATiming) { - if (yres == 360) - yres = 375; - } + if (pVBInfo->LCDInfo & XGI_LCDVESATiming) { + if (yres == 360) + yres = 375; } + } - if (pVBInfo->LCDResInfo == Panel_1024x768) { - if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { - if (!(pVBInfo->LCDInfo - & LCDNonExpanding)) { - if (yres == 350) - yres = 357; - else if (yres == 400) - yres = 420; - else if (yres == 480) - yres = 525; - } + if (pVBInfo->LCDResInfo == Panel_1024x768) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & LCDNonExpanding)) { + if (yres == 350) + yres = 357; + else if (yres == 400) + yres = 420; + else if (yres == 480) + yres = 525; } } } - - if (xres == 720) - xres = 640; } + if (xres == 720) + xres = 640; + +exit: pVBInfo->VGAHDE = xres; pVBInfo->HDE = xres; pVBInfo->VGAVDE = yres; -- GitLab From 470c533896e540b2848d4e0a9d7a1cf56634f565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:50 +0200 Subject: [PATCH 2541/5711] Staging: xgifb: Rework conditions in XGI_SetLockRegs(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index a7ba99f42a68..5b2c35af4aa3 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -4039,24 +4039,16 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - if (pVBInfo->VBType & VB_SIS301LV) { - if (pVBInfo->TVInfo & TVSetHiVision) { - tempbx -= 10; - } else { - if (pVBInfo->TVInfo & TVSimuMode) { - if (pVBInfo->TVInfo & TVSetPAL) { - if (pVBInfo->VBType & - VB_SIS301LV) { - if (!(pVBInfo->TVInfo & - (TVSetYPbPr525p | - TVSetYPbPr750p | - TVSetHiVision))) - tempbx += 40; - } else { - tempbx += 40; - } - } - } + if ((pVBInfo->VBType & VB_SIS301LV) && + !(pVBInfo->TVInfo & TVSetHiVision)) { + if ((pVBInfo->TVInfo & TVSimuMode) && + (pVBInfo->TVInfo & TVSetPAL)) { + if (!(pVBInfo->VBType & VB_SIS301LV) || + !(pVBInfo->TVInfo & + (TVSetYPbPr525p | + TVSetYPbPr750p | + TVSetHiVision))) + tempbx += 40; } } else { tempbx -= 10; -- GitLab From b1bf998c67e37dba950293029bc2872e3cdb3b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:51 +0200 Subject: [PATCH 2542/5711] Staging: xgifb: Rework conditions in XGI_EnableBridge(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 44 ++++++++++++------------------ 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 5b2c35af4aa3..53135c545965 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -6472,32 +6472,24 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, if (!(pVBInfo->VBInfo & DisableCRT2Display)) { tempah = 0xc0; - if (!(pVBInfo->VBInfo & SetSimuScanMode)) { - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { - if (pVBInfo->VBInfo & - SetCRT2ToDualEdge) { - tempah = tempah & 0x40; - if (pVBInfo->VBInfo & - XGI_SetCRT2ToLCDA) - tempah = tempah ^ 0xC0; - - if (pVBInfo->SetFlag & - DisableChB) - tempah &= 0xBF; - - if (pVBInfo->SetFlag & - DisableChA) - tempah &= 0x7F; - - if (pVBInfo->SetFlag & - EnableChB) - tempah |= 0x40; - - if (pVBInfo->SetFlag & - EnableChA) - tempah |= 0x80; - } - } + if (!(pVBInfo->VBInfo & SetSimuScanMode) && + (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && + (pVBInfo->VBInfo & SetCRT2ToDualEdge)) { + tempah = tempah & 0x40; + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) + tempah = tempah ^ 0xC0; + + if (pVBInfo->SetFlag & DisableChB) + tempah &= 0xBF; + + if (pVBInfo->SetFlag & DisableChA) + tempah &= 0x7F; + + if (pVBInfo->SetFlag & EnableChB) + tempah |= 0x40; + + if (pVBInfo->SetFlag & EnableChA) + tempah |= 0x80; } } -- GitLab From e123e46630d0dec5d16d392bb83a8fa40d2e773d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:52 +0200 Subject: [PATCH 2543/5711] Staging: xgifb: Rework some conditions in XGI_SetCRT2ModeRegs(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework some conditions to reduce indentation and fix style warnings. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 83 +++++++++++++----------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 53135c545965..01a3ef394ba0 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -5990,60 +5990,49 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, tempah = 0x08; tempbl = 0xf0; - if (pVBInfo->VBInfo & DisableCRT2Display) { - xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah); - } else { - tempah = 0x00; - tempbl = 0xff; + if (pVBInfo->VBInfo & DisableCRT2Display) + goto reg_and_or; - if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV - | SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && - (!(pVBInfo->VBInfo & SetSimuScanMode))) { - tempbl &= 0xf7; - tempah |= 0x01; - xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, - tempbl, tempah); - } else { - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { - tempbl &= 0xf7; - tempah |= 0x01; - } + tempah = 0x00; + tempbl = 0xff; - if (pVBInfo->VBInfo & - (SetCRT2ToRAMDAC | - SetCRT2ToTV | - SetCRT2ToLCD)) { - tempbl &= 0xf8; - tempah = 0x01; + if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | + SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) + goto reg_and_or; - if (!(pVBInfo->VBInfo & SetInSlaveMode)) - tempah |= 0x02; + if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && + (!(pVBInfo->VBInfo & SetSimuScanMode))) { + tempbl &= 0xf7; + tempah |= 0x01; + goto reg_and_or; + } - if (!(pVBInfo->VBInfo & - SetCRT2ToRAMDAC)) { - tempah = tempah ^ 0x05; - if (!(pVBInfo->VBInfo & - SetCRT2ToLCD)) - tempah = tempah ^ 0x01; - } + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { + tempbl &= 0xf7; + tempah |= 0x01; + } - if (!(pVBInfo->VBInfo & - SetCRT2ToDualEdge)) - tempah |= 0x08; - xgifb_reg_and_or(pVBInfo->Part1Port, - 0x2e, tempbl, tempah); - } else { - xgifb_reg_and_or(pVBInfo->Part1Port, - 0x2e, tempbl, tempah); - } - } - } else { - xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, - tempah); - } + if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD))) + goto reg_and_or; + + tempbl &= 0xf8; + tempah = 0x01; + + if (!(pVBInfo->VBInfo & SetInSlaveMode)) + tempah |= 0x02; + + if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) { + tempah = tempah ^ 0x05; + if (!(pVBInfo->VBInfo & SetCRT2ToLCD)) + tempah = tempah ^ 0x01; } + if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge)) + tempah |= 0x08; + +reg_and_or: + xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah); + if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempah &= (~0x08); -- GitLab From 3bcc24601626a1e3e8a66577f735185141edd206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:53 +0200 Subject: [PATCH 2544/5711] Staging: xgifb: Fix coding style. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix small coding style warnings in several files. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 3 +- drivers/staging/xgifb/vb_init.c | 3 +- drivers/staging/xgifb/vb_setmode.c | 59 +++++++++++++++++------------ drivers/staging/xgifb/vb_table.h | 30 ++++++++++----- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index e5657ffa4cd0..0f49a2104d40 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -590,7 +590,8 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, <= 2) && (XGIfb_vrate[i].idx != 1)) { pr_debug("Adjusting rate from %d down to %d\n", - rate, XGIfb_vrate[i-1].refresh); + rate, + XGIfb_vrate[i-1].refresh); xgifb_info->rate_idx = XGIfb_vrate[i - 1].idx; xgifb_info->refresh_rate = diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index ae10153503d5..80dba6a425ba 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1042,9 +1042,8 @@ static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, if (tempbx & tempcx) { CR3CData = xgifb_reg_get(pVBInfo->P3d4, 0x3c); - if (!(CR3CData & DisplayDeviceFromCMOS)) { + if (!(CR3CData & DisplayDeviceFromCMOS)) tempcx = 0x1FF0; - } } else { tempcx = 0x1FF0; } diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 01a3ef394ba0..e81149fc66e3 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -945,23 +945,26 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { CRT2Index = CRT2Index >> 6; /* for LCD */ - if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /*301b*/ + if (pVBInfo->VBInfo & + (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /*301b*/ if (pVBInfo->LCDResInfo != Panel_1024x768) - VCLKIndex = VCLK108_2_315 + 5; /* LCDXlat2VCLK */ + /* LCDXlat2VCLK */ + VCLKIndex = VCLK108_2_315 + 5; else VCLKIndex = VCLK65_315 + 2; /* LCDXlat1VCLK */ } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - if (pVBInfo->SetFlag & RPLLDIV2XO) { + if (pVBInfo->SetFlag & RPLLDIV2XO) VCLKIndex = TVCLKBASE_315_25 + HiTVVCLKDIV2; - } else { + else VCLKIndex = TVCLKBASE_315_25 + HiTVVCLK; - } if (pVBInfo->SetFlag & TVSimuMode) { if (modeflag & Charx8Dot) { - VCLKIndex = TVCLKBASE_315_25 + HiTVSimuVCLK; + VCLKIndex = TVCLKBASE_315_25 + + HiTVSimuVCLK; } else { - VCLKIndex = TVCLKBASE_315_25 + HiTVTextVCLK; + VCLKIndex = TVCLKBASE_315_25 + + HiTVTextVCLK; } } @@ -978,11 +981,10 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = YPbPr525iVCLK; } } else if (pVBInfo->VBInfo & SetCRT2ToTV) { - if (pVBInfo->SetFlag & RPLLDIV2XO) { + if (pVBInfo->SetFlag & RPLLDIV2XO) VCLKIndex = TVCLKBASE_315_25 + TVVCLKDIV2; - } else { + else VCLKIndex = TVCLKBASE_315_25 + TVVCLK; - } } else { /* for CRT2 */ /* di+Ext_CRTVCLK */ VCLKIndex = pVBInfo->RefIndex[RefreshRateTableIndex]. @@ -994,7 +996,8 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, (pVBInfo->LCDResInfo == Panel_320x480)) VCLKIndex = VCLK40; /* LVDSXlat1VCLK */ else - VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK, LVDSXlat3VCLK */ + VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK, + LVDSXlat3VCLK */ } return VCLKIndex; @@ -1928,7 +1931,8 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->HDE = 1024; pVBInfo->VDE = 768; } else if ((pVBInfo->LCDResInfo == Panel_1280x1024) || - (pVBInfo->LCDResInfo == Panel_1280x1024x75)) { + (pVBInfo->LCDResInfo == + Panel_1280x1024x75)) { pVBInfo->HDE = 1280; pVBInfo->VDE = 1024; } else if (pVBInfo->LCDResInfo == Panel_1400x1050) { @@ -2385,7 +2389,8 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, if (pVBInfo->TVInfo & TVSimuMode) { tempal = TVCLKBASE_315 + HiTVSimuVCLK; if (!(modeflag & Charx8Dot)) - tempal = TVCLKBASE_315 + HiTVTextVCLK; + tempal = TVCLKBASE_315 + + HiTVTextVCLK; } return tempal; @@ -2431,8 +2436,8 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, { if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && (pVBInfo->SetFlag - & ProgrammingCRT2)) { + if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + (pVBInfo->SetFlag & ProgrammingCRT2)) { *di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B; *di_1 = XGI_VBVCLKData[tempal].SR2C; } @@ -2948,7 +2953,10 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if ((pVBInfo->LCDResInfo == Panel_1400x1050) && (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) && (!(tempbx & EnableScalingLCD))) - /* set to center in 1280x1024 LCDB for Panel_1400x1050 */ + /* + * set to center in 1280x1024 LCDB + * for Panel_1400x1050 + */ tempbx |= SetLCDtoNonExpanding; } @@ -5451,7 +5459,8 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { tempah = 0x7F; /* Disable Channel A */ - if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) + if (!(pVBInfo->VBInfo & + XGI_SetCRT2ToLCDA)) /* Disable Channel B */ tempah = 0xBF; @@ -5470,9 +5479,10 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah); if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { - if (((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) - || (XGI_DisableChISLCD(pVBInfo)) - || (XGI_IsLCDON(pVBInfo))) + if (((pVBInfo->VBInfo & + (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) + || (XGI_DisableChISLCD(pVBInfo)) + || (XGI_IsLCDON(pVBInfo))) /* LVDS Driver power down */ xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x80); } @@ -5638,7 +5648,8 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) if (pVBInfo->VBInfo & SetCRT2ToDualEdge) tempbl = tempbl >> 4; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & + (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempbh = XGI301LCDDelay; if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) @@ -5655,7 +5666,8 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) tempah |= tempbl; } - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { /* Channel A */ + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { + /* Channel A */ tempah &= 0x0F; tempah |= tempbh; } @@ -6723,9 +6735,8 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo); - if (HwDeviceExtension->jChipType < XG20) { + if (HwDeviceExtension->jChipType < XG20) XGI_LockCRT2(HwDeviceExtension, pVBInfo); - } return 1; } diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index ca8c68d6fb16..1c168461411d 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1838,9 +1838,12 @@ static struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = { {Panel_1024x768x75, 0x0019, 0x0001, 12}, /* XGI_ExtLCD1024x768x75Data */ {Panel_1024x768x75, 0x0019, 0x0000, 13}, /* XGI_StLCD1024x768x75Data */ {Panel_1024x768x75, 0x0018, 0x0010, 14}, /* XGI_CetLCD1024x768x75Data */ - {Panel_1280x1024x75, 0x0019, 0x0001, 15}, /* XGI_ExtLCD1280x1024x75Data*/ - {Panel_1280x1024x75, 0x0019, 0x0000, 16}, /* XGI_StLCD1280x1024x75Data */ - {Panel_1280x1024x75, 0x0018, 0x0010, 17}, /* XGI_CetLCD1280x1024x75Data*/ + /* XGI_ExtLCD1280x1024x75Data */ + {Panel_1280x1024x75, 0x0019, 0x0001, 15}, + /* XGI_StLCD1280x1024x75Data */ + {Panel_1280x1024x75, 0x0019, 0x0000, 16}, + /* XGI_CetLCD1280x1024x75Data */ + {Panel_1280x1024x75, 0x0018, 0x0010, 17}, {PanelRef75Hz, 0x0008, 0x0008, 18}, /* XGI_NoScalingDatax75 */ {0xFF, 0x0000, 0x0000, 0} /* End of table */ }; @@ -1859,9 +1862,12 @@ static struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = { {Panel_1600x1200, 0x0019, 0x0001, 10}, /* XGI_ExtLCDDes1600x1200Data */ {Panel_1600x1200, 0x0019, 0x0000, 11}, /* XGI_StLCDDes1600x1200Data */ {PanelRef60Hz, 0x0008, 0x0008, 12}, /* XGI_NoScalingDesData */ - {Panel_1024x768x75, 0x0019, 0x0001, 13}, /*XGI_ExtLCDDes1024x768x75Data*/ - {Panel_1024x768x75, 0x0019, 0x0000, 14}, /* XGI_StLCDDes1024x768x75Data*/ - {Panel_1024x768x75, 0x0018, 0x0010, 15}, /*XGI_CetLCDDes1024x768x75Data*/ + /* XGI_ExtLCDDes1024x768x75Data */ + {Panel_1024x768x75, 0x0019, 0x0001, 13}, + /* XGI_StLCDDes1024x768x75Data */ + {Panel_1024x768x75, 0x0019, 0x0000, 14}, + /* XGI_CetLCDDes1024x768x75Data */ + {Panel_1024x768x75, 0x0018, 0x0010, 15}, /* XGI_ExtLCDDes1280x1024x75Data */ {Panel_1280x1024x75, 0x0019, 0x0001, 16}, /* XGI_StLCDDes1280x1024x75Data */ @@ -1898,8 +1904,10 @@ static struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] = { {PanelRef60Hz, 0x0008, 0x0008, 7}, /* XGI_LVDSNoScalingData */ {Panel_1024x768x75, 0x0018, 0x0000, 8}, /* XGI_LVDS1024x768Data_1x75 */ {Panel_1024x768x75, 0x0018, 0x0010, 9}, /* XGI_LVDS1024x768Data_2x75 */ - {Panel_1280x1024x75, 0x0018, 0x0000, 10}, /* XGI_LVDS1280x1024Data_1x75*/ - {Panel_1280x1024x75, 0x0018, 0x0010, 11}, /*XGI_LVDS1280x1024Data_2x75*/ + /* XGI_LVDS1280x1024Data_1x75 */ + {Panel_1280x1024x75, 0x0018, 0x0000, 10}, + /* XGI_LVDS1280x1024Data_2x75 */ + {Panel_1280x1024x75, 0x0018, 0x0010, 11}, {PanelRef75Hz, 0x0008, 0x0008, 12}, /* XGI_LVDSNoScalingDatax75 */ {0xFF, 0x0000, 0x0000, 0} }; @@ -1917,8 +1925,10 @@ static struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = { {Panel_1024x768x75, 0x0018, 0x0000, 9}, /* XGI_LVDS1024x768Des_1x75 */ {Panel_1024x768x75, 0x0618, 0x0410, 10}, /* XGI_LVDS1024x768Des_3x75 */ {Panel_1024x768x75, 0x0018, 0x0010, 11}, /* XGI_LVDS1024x768Des_2x75 */ - {Panel_1280x1024x75, 0x0018, 0x0000, 12}, /* XGI_LVDS1280x1024Des_1x75 */ - {Panel_1280x1024x75, 0x0018, 0x0010, 13}, /* XGI_LVDS1280x1024Des_2x75 */ + /* XGI_LVDS1280x1024Des_1x75 */ + {Panel_1280x1024x75, 0x0018, 0x0000, 12}, + /* XGI_LVDS1280x1024Des_2x75 */ + {Panel_1280x1024x75, 0x0018, 0x0010, 13}, {PanelRef75Hz, 0x0008, 0x0008, 14}, /* XGI_LVDSNoScalingDesDatax75 */ {0xFF, 0x0000, 0x0000, 0} }; -- GitLab From f6002041af0bc95bc4951ddf94cda706605faf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20G=C3=B3mez?= Date: Fri, 6 Jul 2012 12:40:54 +0200 Subject: [PATCH 2545/5711] Staging: xgifb: Remove useless condition. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove last if branch in XGIfb_do_set_var(), as it has no action assigned. Signed-off-by: Miguel Gómez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 0f49a2104d40..64ffd70eb7dc 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -973,8 +973,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, vtotal <<= 1; else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) vtotal <<= 2; - else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { - } if (!htotal || !vtotal) { pr_debug("Invalid 'var' information\n"); -- GitLab From 9f433eac0b6f2af7642890ce7995dcc9d1d309ff Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 22:32:38 -0300 Subject: [PATCH 2546/5711] staging: bcm: Remove code that will never execute This patch removes all references of "if 0" blocks in the bcm drivers. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Misc.c | 63 -------------------------------------- 1 file changed, 63 deletions(-) diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index c36fd763310d..d7c662d5f914 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -402,30 +402,6 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) return Status; } -#if 0 -/***************************************************************** -* Function - SendStatisticsPointerRequest() -* -* Description - This function builds and forwards the Statistics -* Pointer Request control Packet. -* -* Parameters - Adapter : Pointer to Adapter structure. -* - pstStatisticsPtrRequest : Pointer to link request. -* -* Returns - None. -*****************************************************************/ -static VOID SendStatisticsPointerRequest(struct bcm_mini_adapter *Adapter, struct bcm_link_request *pstStatisticsPtrRequest) -{ - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); - pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; - pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG); /* minimum 4 bytes */ - pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ; - CopyBufferToControlPacket(Adapter, pstStatisticsPtrRequest); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<====="); - return; -} -#endif - /****************************************************************** * Function - LinkMessage() * @@ -1217,45 +1193,6 @@ static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter) } } -#if 0 -static unsigned char *ReadMacAddrEEPROM(struct bcm_mini_adapter *Adapter, ulong dwAddress) -{ - int status = 0, i = 0; - unsigned int temp = 0; - unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL); - int bytes; - - if (!pucmacaddr) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n"); - return NULL; - } - - dwAddress |= 0x5b000000; - status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, (PUINT)&dwAddress, sizeof(UINT)); - if (status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n"); - kfree(pucmacaddr); - pucmacaddr = NULL; - goto OUT; - } - - for (i = 0; i < MAC_ADDRESS_SIZE; i++) { - bytes = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp)); - if (bytes < 0) { - status = bytes; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n"); - kfree(pucmacaddr); - pucmacaddr = NULL; - goto OUT; - } - pucmacaddr[i] = temp & 0xff; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "%x\n", pucmacaddr[i]); - } -OUT: - return pucmacaddr; -} -#endif - static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) { UINT uiIndex = 0; -- GitLab From d5bd0ba64df5ac474090b82f958328e696ade458 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 22:32:39 -0300 Subject: [PATCH 2547/5711] staging: bcm: Remove all commented macros All these macros are commented, and can be removed. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/CmHost.c | 1 - drivers/staging/bcm/Debug.h | 5 ----- drivers/staging/bcm/Macros.h | 1 - drivers/staging/bcm/PHSDefines.h | 1 - 4 files changed, 8 deletions(-) diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 9c8c9b14e8d4..b54ec974477f 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -4,7 +4,6 @@ * Management. ************************************************************/ -/* #define CONN_MSG */ #include "headers.h" enum E_CLASSIFIER_ACTION { diff --git a/drivers/staging/bcm/Debug.h b/drivers/staging/bcm/Debug.h index 420382d1cacf..8018a189f817 100644 --- a/drivers/staging/bcm/Debug.h +++ b/drivers/staging/bcm/Debug.h @@ -42,10 +42,6 @@ #define ARP_REQ (TX<<5) #define ARP_RESP (TX<<6) -// dhcp.c -//#define DHCP TX -//#define DHCP_REQ (DHCP<<7) - // Leakybucket.c #define TOKEN_COUNTS (TX<<8) #define CHECK_TOKENS (TX<<9) @@ -147,7 +143,6 @@ DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c */ #define HOST_MIBS (OTHERS << 28) #define CONN_MSG (CMHOST << 29) -//#define OTHERS_MISC (OTHERS << 29) // ProcSupport.c /*-----------------END SUBTYPEs------------------------------------------*/ diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h index b5ca6f6a1cb2..46f5f0feea88 100644 --- a/drivers/staging/bcm/Macros.h +++ b/drivers/staging/bcm/Macros.h @@ -6,7 +6,6 @@ #define TX_TIMER_PERIOD 10 /*10 msec*/ #define MAX_CLASSIFIERS 100 -/* #define MAX_CLASSIFIERS_PER_SF 20 */ #define MAX_TARGET_DSX_BUFFERS 24 #define MAX_CNTRL_PKTS 100 diff --git a/drivers/staging/bcm/PHSDefines.h b/drivers/staging/bcm/PHSDefines.h index eed4cfc6e538..6016fc502d2d 100644 --- a/drivers/staging/bcm/PHSDefines.h +++ b/drivers/staging/bcm/PHSDefines.h @@ -27,7 +27,6 @@ #define PHS_BUFFER_SIZE 1532 -//#define MAX_PHS_LENGTHS 100 #define MAX_PHSRULE_PER_SF 20 #define MAX_SERVICEFLOWS 17 -- GitLab From 3a53ecbd5f7b1843232ed692c3ec3308b1f63ca7 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 22:32:40 -0300 Subject: [PATCH 2548/5711] staging: bcm: Misc.c: Remove unused macros These macros were reported by forgotten-macros tool (https://github.com/marcosps/forgotten_macros). Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Misc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index d7c662d5f914..9a60d4cd2184 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -1206,9 +1206,6 @@ static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) } } -#define CACHE_ADDRESS_MASK 0x80000000 -#define UNCACHE_ADDRESS_MASK 0xa0000000 - int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { return Adapter->interface_rdm(Adapter->pvInterfaceAdapter, -- GitLab From d69803b95580581bc7cf6cc901dec91e20f5d5a8 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:09 -0300 Subject: [PATCH 2549/5711] staging: csr: Remove dead code All this code is dead, so remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/monitor.c | 57 ------------------------------ drivers/staging/csr/unifi_native.h | 19 ---------- 2 files changed, 76 deletions(-) diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c index 7648d2bbad43..8c35b7e9fc96 100644 --- a/drivers/staging/csr/monitor.c +++ b/drivers/staging/csr/monitor.c @@ -51,13 +51,6 @@ uf_start_sniff(unifi_priv_t *priv) req->Channel = priv->wext_conf.channel; req->ChannelStartingFactor = 0; -#if 0 - printk("SniffJoin: Ifindex=%d, Channel=%d, ChannelStartingFactor=%d\n", - req->Ifindex, - req->Channel, - req->ChannelStartingFactor); -#endif - signal.SignalPrimitiveHeader.SignalId = CSR_MLME_SNIFFJOIN_REQUEST_ID; r = unifi_mlme_blocking_request(priv, pcli, &signal, NULL, timeout); @@ -198,11 +191,6 @@ netrx_radiotap(unifi_priv_t *priv, unifi_rt->rt_antenna = ind->AntennaId; -#if 0 - printk("skb datalen=%d\n", skb->len); - dump(skb->data, 48); -#endif - skb->dev = dev; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) skb->mac_header = skb->data; @@ -282,24 +270,6 @@ netrx_prism(unifi_priv_t *priv, return; } -#if 0 - printk("MA-SINFFDATA.ind: DataLen=%d bytes, TSF %02X %02X %02X %02X %02X %02X %02X %02X, Rate=%d, Antenna=%d\n", - ind->Data.DataLength, - ind->Timestamp.x[0], - ind->Timestamp.x[1], - ind->Timestamp.x[2], - ind->Timestamp.x[3], - ind->Timestamp.x[4], - ind->Timestamp.x[5], - ind->Timestamp.x[6], - ind->Timestamp.x[7], - ind->Rate, - ind->Antenna); - - printk("payload, len %d\n", length); - dump((unsigned char *)payload, 32); -#endif - /* * Allocate a SKB for the received data packet, including radiotap * header. @@ -341,11 +311,6 @@ netrx_prism(unifi_priv_t *priv, avs->encoding = htonl(0); /* unknown */ -#if 0 - printk("skb datalen=%d\n", skb->len); - dump(skb->data, 48); -#endif - skb->dev = dev; skb->mac.raw = skb->data; skb->pkt_type = PACKET_OTHERHOST; @@ -402,33 +367,11 @@ ma_sniffdata_ind(void *ospriv, } skb->len = bulkdata->d[0].data_length; -#if 0 - printk("MA-SNIFFDATA.ind: DataLen=%d bytes, TSF %02X %02X %02X %02X %02X %02X %02X %02X, Rate=%d, Antenna=%d\n", - ind->Data.DataLength, - ind->Timestamp.x[0], - ind->Timestamp.x[1], - ind->Timestamp.x[2], - ind->Timestamp.x[3], - ind->Timestamp.x[4], - ind->Timestamp.x[5], - ind->Timestamp.x[6], - ind->Timestamp.x[7], - ind->Rate, - ind->AntennaId); - - printk("payload, len %lu\n", bulkdata->d[0].data_length); - if (bulkdata->d[0].os_data_ptr && (bulkdata->d[0].data_length >= 32)) { - dump((unsigned char *)bulkdata->d[0].os_data_ptr, 32); - } -#endif /* We only process data packets if the interface is open */ if (unlikely(!netif_running(dev))) { priv->stats.rx_dropped++; priv->wext_conf.wireless_stats.discard.misc++; -#if 0 - printk("Dropping packet while interface is not up.\n"); -#endif dev_kfree_skb(skb); return; } diff --git a/drivers/staging/csr/unifi_native.h b/drivers/staging/csr/unifi_native.h index a480c9e2435b..a73b38e5e480 100644 --- a/drivers/staging/csr/unifi_native.h +++ b/drivers/staging/csr/unifi_native.h @@ -242,25 +242,6 @@ void uf_native_process_udi_signal(ul_client_t *pcli, const u8 *packed_signal, int packed_signal_len, const bulk_data_param_t *bulkdata, int dir); -#if 0 -/* - * Choose one of these if available in linux/if_arp.h: - * #define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_RADIOTAP - * #define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_PRISM - * - * Radiotap is the newer standard for softmac WLAN devices, it works with - * Wireshark but not Ethereal (due to a bug in the Ethereal dissector). - * Prism is an older (less desirable) format but it does work with Ethereal. - */ -#ifdef ARPHRD_IEEE80211_RADIOTAP -#define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_RADIOTAP -#else -#ifdef ARPHRD_IEEE80211_PRISM -#define UNIFI_SNIFF_ARPHRD ARPHRD_IEEE80211_PRISM -#endif -#endif -#endif - #ifdef UNIFI_SNIFF_ARPHRD /* * monitor.c -- GitLab From b433ed5bfec42f956887e50e5965941c14120f31 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:10 -0300 Subject: [PATCH 2550/5711] staging: csr: csr_util.h: Remove commented macros All these macros are commented, so we can removed it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/csr_util.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/csr/csr_util.h b/drivers/staging/csr/csr_util.h index ce39c7e8dab7..5cd6cb4f22ca 100644 --- a/drivers/staging/csr/csr_util.h +++ b/drivers/staging/csr/csr_util.h @@ -47,17 +47,10 @@ void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str); #define CsrMemCmp(s1, s2, n) ((CsrInt32) memcmp((s1), (s2), (n))) #define CsrStrCmp(s1, s2) ((CsrInt32) strcmp((s1), (s2))) #define CsrStrNCmp(s1, s2, n) ((CsrInt32) strncmp((s1), (s2), (n))) -/*#define CsrMemChr memchr*/ #define CsrStrChr strchr -/*#define CsrStrCSpn strcspn*/ -/*#define CsrStrPBrk strpbrk*/ -/*#define CsrStrRChr strrchr*/ -/*#define CsrStrSpn strspn*/ #define CsrStrStr strstr -/*#define CsrStrTok strtok*/ #define CsrMemSet memset #define CsrStrLen strlen -/*#define CsrVsnprintf(s, n, format, arg) ((CsrInt32) vsnprintf((s), (n), (format), (arg)))*/ #else /* !CSR_USE_STDC_LIB */ void *CsrMemCpy(void *dest, const void *src, CsrSize count); void *CsrMemMove(void *dest, const void *src, CsrSize count); -- GitLab From e3a90feadf00d7892a0b08fee97cf6aed5c4e624 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:11 -0300 Subject: [PATCH 2551/5711] staging: csr: netdev.c: Remove unused macros These macros are not used, so we can remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/netdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c index cf19f1116c2e..55149df5e347 100644 --- a/drivers/staging/csr/netdev.c +++ b/drivers/staging/csr/netdev.c @@ -70,11 +70,6 @@ */ #define ALLOW_Q_PAUSE -#define ieee2host16(n) __le16_to_cpu(n) -#define ieee2host32(n) __le32_to_cpu(n) -#define host2ieee16(n) __cpu_to_le16(n) -#define host2ieee32(n) __cpu_to_le32(n) - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) #ifdef UNIFI_NET_NAME #define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ -- GitLab From 6d6f64ae16a38b485b164b8089f357343077d230 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:12 -0300 Subject: [PATCH 2552/5711] staging: csr: unifi_sme.c: Remove unused macros These macros are not used, so remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/unifi_sme.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c index 6e7cbbf70c88..5ad1d5f8167e 100644 --- a/drivers/staging/csr/unifi_sme.c +++ b/drivers/staging/csr/unifi_sme.c @@ -78,12 +78,6 @@ sme_log_event(ul_client_t *pcli, CsrResult result = CSR_RESULT_SUCCESS; int r; - /* Following bits are encoded in hostTag These are there to ensure that hostTags are unique*/ -#define CSR_SME_DATA 0x00000000 /* Frames Sent by SME */ -#define CSR_PAL_DATA 0X10000000 /* Frames Sent by PAL-D*/ -#define CSR_NME_DATA 0x20000000 /* Frames Sent by NME*/ -#define APPLICATION_DATA 0x30000000 /* Frames Sent by Application*/ - func_enter(); /* Just a sanity check */ if ((signal == NULL) || (signal_len <= 0)) { -- GitLab From 69a7cd7dd54d4d7a129c209a9586f850b13721bb Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:13 -0300 Subject: [PATCH 2553/5711] staging: csr: Remove unused macros These macros are not used, so remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/csr_wifi_hip_card_sdio.c | 3 --- drivers/staging/csr/drv.c | 1 - drivers/staging/csr/firmware.c | 1 - drivers/staging/csr/mlme.c | 5 ----- drivers/staging/csr/monitor.c | 2 -- drivers/staging/csr/sme_sys.c | 1 - 6 files changed, 13 deletions(-) diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c index 91976b824a4e..5a86ff90253d 100644 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c @@ -36,9 +36,6 @@ #define MAILBOX2_TIMEOUT 5 /* in millisecs */ #define MAILBOX2_ATTEMPTS 10 /* 50ms */ -#define MAILBOX2_RESET_ATTEMPTS 10 -#define MAILBOX2_RESET_TIMEOUT 5 /* in millisecs */ - #define RESET_SETTLE_DELAY 25 /* in millisecs */ static CsrResult card_init_slots(card_t *card); diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c index fbe86301816c..4be6d9533cd0 100644 --- a/drivers/staging/csr/drv.c +++ b/drivers/staging/csr/drv.c @@ -63,7 +63,6 @@ int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ int bh_priority = -1; #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -#define UNIFI_LOG_HIP_SIGNALS_FILTER_SIGNAL (1 << 0) #define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1) #define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2) int log_hip_signals = 0; diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c index 03da0d5c247a..98e27d6f440e 100644 --- a/drivers/staging/csr/firmware.c +++ b/drivers/staging/csr/firmware.c @@ -220,7 +220,6 @@ unifi_fw_read(void *ospriv, void *arg, CsrUint32 offset, void *buf, CsrUint32 le -#define UNIFIHELPER_INIT_MODE_SMEEMB 0 #define UNIFIHELPER_INIT_MODE_SMEUSER 2 #define UNIFIHELPER_INIT_MODE_NATIVE 1 diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c index 790d5d77375f..ed767eccbb32 100644 --- a/drivers/staging/csr/mlme.c +++ b/drivers/staging/csr/mlme.c @@ -15,11 +15,6 @@ #include "csr_wifi_hip_unifi.h" #include "unifi_priv.h" - -/* The additional time taken by the UniFi to do a scan per channel */ -#define SCAN_STARTUP_TIME 300 /* in millisecs */ - - /* * --------------------------------------------------------------------------- * unifi_mlme_wait_for_reply diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c index 8c35b7e9fc96..628782ad641e 100644 --- a/drivers/staging/csr/monitor.c +++ b/drivers/staging/csr/monitor.c @@ -242,9 +242,7 @@ netrx_prism(unifi_priv_t *priv, unsigned char *ptr; unsigned char *base; int ind_data_len = skb_orig->len - 2 - ETH_HLEN; -#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001 -#define WLANCAP_MAGIC_COOKIE_V2 0x80211002 struct avs_header_v1 { uint32 version; uint32 length; diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c index 9c3aa7494604..5f38f9dbb986 100644 --- a/drivers/staging/csr/sme_sys.c +++ b/drivers/staging/csr/sme_sys.c @@ -1572,7 +1572,6 @@ void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) r = _sys_packet_req(priv, &signal, mareq->subscriptionHandle, mareq->frameLength, mareq->frame, snap_protocol); -#define MAX_RETRY 2 if (r && mareq->cfmRequested) { CsrWifiRouterMaPacketCfmSend(msg->source,interfaceTag, -- GitLab From 80145a579f167f090af3b2716f14a6b0a82b4e76 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 10:36:05 +0530 Subject: [PATCH 2554/5711] staging/ft1000: remove all spaces, tabs issue in while loop of ft1000_interrupt all spaces in the main while loop of ft1000_interrupt are converted to tabs. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- .../staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 0059cac10c36..86a680c09ba2 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -1996,41 +1996,43 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id) inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type - while (inttype) { + while (inttype) { if (inttype & ISR_DOORBELL_PEND) ft1000_parse_dpram_msg(dev); - if (inttype & ISR_RCV) { - DEBUG(1, "Data in FIFO\n"); + if (inttype & ISR_RCV) { + DEBUG(1, "Data in FIFO\n"); - cnt = 0; - do { - // Check if we have packets in the Downlink FIFO - if (info->AsicID == ELECTRABUZZ_ID) { - tempword = - ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT); - } else { - tempword = - ft1000_read_reg(dev, FT1000_REG_MAG_DFSR); - } - if (tempword & 0x1f) { - ft1000_copy_up_pkt(dev); - } else { - break; - } - cnt++; - } while (cnt < MAX_RCV_LOOP); + cnt = 0; + do { + // Check if we have packets in the Downlink FIFO + if (info->AsicID == ELECTRABUZZ_ID) { + tempword = + ft1000_read_reg(dev, + FT1000_REG_DFIFO_STAT); + } else { + tempword = + ft1000_read_reg(dev, + FT1000_REG_MAG_DFSR); + } + if (tempword & 0x1f) { + ft1000_copy_up_pkt(dev); + } else { + break; + } + cnt++; + } while (cnt < MAX_RCV_LOOP); + } + // clear interrupts + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); + DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); + ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); + + // Read interrupt type + inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR); + DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype); } - // clear interrupts - tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); - DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); - ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); - - // Read interrupt type - inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR); - DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype); - } ft1000_enable_interrupts(dev); return IRQ_HANDLED; } -- GitLab From aaf3ee4f80960eecccdd94a6b44b41c6af6c14d3 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 12 Jul 2012 00:41:44 +0900 Subject: [PATCH 2555/5711] staging: ft1000: Fix typo in ft1000_usb.c Correct spelling typo within debug message of ft1000_usb.c Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index 7bd7fb2f3b15..e8c4a4e5ac6d 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -237,7 +237,7 @@ static void ft1000_disconnect(struct usb_interface *interface) ft1000_destroy_dev(pft1000info->pFt1000Dev->net); unregister_netdev(pft1000info->pFt1000Dev->net); DEBUG - ("ft1000_disconnect: network device unregisterd\n"); + ("ft1000_disconnect: network device unregistered\n"); free_netdev(pft1000info->pFt1000Dev->net); } -- GitLab From e6345c81b4eb20850ae4078ed3a8ff6eae584283 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 11:19:14 +0530 Subject: [PATCH 2556/5711] staging/sm7xxfb: use module_pci_driver macro as the manual of module_pci_driver says that it can be used when the init and exit functions of the module does nothing but the pci_register_driver and pci_unregister_driver. use it for the sm7xxfb driver, as the driver does nothing in its _init and _exit functions but the register and unregister. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xxfb.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index e3511ecd0980..0c0b6035cb04 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -1058,18 +1058,7 @@ static struct pci_driver smtcfb_driver = { .driver.pm = SM7XX_PM_OPS, }; -static int __init smtcfb_init(void) -{ - return pci_register_driver(&smtcfb_driver); -} - -static void __exit smtcfb_exit(void) -{ - pci_unregister_driver(&smtcfb_driver); -} - -module_init(smtcfb_init); -module_exit(smtcfb_exit); +module_pci_driver(smtcfb_driver); MODULE_AUTHOR("Siliconmotion "); MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); -- GitLab From fd67859d380b4c2af160d4aa3d8041bf63d7bd36 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 11:19:15 +0530 Subject: [PATCH 2557/5711] staging/sm7xxfb: return a proper err for smtc_alloc_fb_info failure as smtc_alloc_fb_info can fail, but we are returning the 0, how? because the pci_enable_device succeeded, which makes the probe return 0, and may cause panics or some strange problems at remove when driver unloaded by modprobe -r. so return err properly as smtc_alloc_fb_info is doing kzallocs its good to do -ENOMEM Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xxfb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 0c0b6035cb04..73951963c018 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -808,8 +808,10 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, sfb = smtc_alloc_fb_info(pdev, name); - if (!sfb) + if (!sfb) { + err = -ENOMEM; goto failed_free; + } sfb->chip_id = ent->device; sprintf(name, "sm%Xfb", sfb->chip_id); -- GitLab From 8e4763f67fe7279822c131bde4eadf5f7e456b2c Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 12:11:48 +0530 Subject: [PATCH 2558/5711] staging/sep: use module_pci_driver macro this driver duplicates the module_pci_driver code, so remove the duplicated code and use module_pci_driver and also remove the obvious comments about _init and _exit. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_main.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 270fcb811b80..205d0df20e2e 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -4492,30 +4492,5 @@ static struct pci_driver sep_pci_driver = { .remove = sep_remove }; -/** - * sep_init - init function - * - * Module load time. Register the PCI device driver. - */ - -static int __init sep_init(void) -{ - return pci_register_driver(&sep_pci_driver); -} - - -/** - * sep_exit - called to unload driver - * - * Unregister the driver The device will perform all the cleanup required. - */ -static void __exit sep_exit(void) -{ - pci_unregister_driver(&sep_pci_driver); -} - - -module_init(sep_init); -module_exit(sep_exit); - +module_pci_driver(sep_pci_driver); MODULE_LICENSE("GPL"); -- GitLab From 89812b1f5af666e531e4840e867edf86ed047db8 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 12:11:03 +0530 Subject: [PATCH 2559/5711] staging/et131x: use module_pci_driver macro remove code duplicating module_pci_driver and also the obvious comments about the _init and _exit points. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 8f3fc5f85ec9..ac6897b593c9 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -5445,24 +5445,4 @@ static struct pci_driver et131x_driver = { .driver.pm = ET131X_PM_OPS, }; -/** - * et131x_init_module - The "main" entry point called on driver initialization - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ -static int __init et131x_init_module(void) -{ - return pci_register_driver(&et131x_driver); -} - -/** - * et131x_cleanup_module - The entry point called on driver cleanup - */ -static void __exit et131x_cleanup_module(void) -{ - pci_unregister_driver(&et131x_driver); -} - -module_init(et131x_init_module); -module_exit(et131x_cleanup_module); - +module_pci_driver(et131x_driver); -- GitLab From 1cdb9c7c1d4846e04c28dbb41c6cef3a5e5f2b56 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 12:10:04 +0530 Subject: [PATCH 2560/5711] staging/sbe-2t3e3: use module_pci_driver macro the _init and _exit functions do nothing but pci_register_driver, and pci_unregister_driver, so replace these and also the module _init and _exit macros with the module_pci_driver macro. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sbe-2t3e3/module.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c index e87fe81f6bb3..cd778b3a02b2 100644 --- a/drivers/staging/sbe-2t3e3/module.c +++ b/drivers/staging/sbe-2t3e3/module.c @@ -194,17 +194,6 @@ static struct pci_driver t3e3_pci_driver = { .remove = t3e3_remove_card, }; -static int __init t3e3_init_module(void) -{ - return pci_register_driver(&t3e3_pci_driver); -} - -static void __exit t3e3_cleanup_module(void) -{ - pci_unregister_driver(&t3e3_pci_driver); -} - -module_init(t3e3_init_module); -module_exit(t3e3_cleanup_module); +module_pci_driver(t3e3_pci_driver); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl); -- GitLab From d44858a9b4abc1fb94f0dae587fbd1807bb3c576 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 12:16:30 +0530 Subject: [PATCH 2561/5711] staging/phison: use module_pci_driver macro remove the duplication of module_pci_driver and use this macro instead module_pci_driver macro does the same things as the code below does static int __init pci_test_dev_init(void) { return pci_register_driver(&pci_test_driver_ops); } static void __exit pci_test_dev_exit(void) { pci_unregister_driver(&pci_test_driver_ops); } module_init(pci_test_dev_init); module_exit(pci_test_dev_exit); Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/phison/phison.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c index d77b21f1eb2d..919cb95236fc 100644 --- a/drivers/staging/phison/phison.c +++ b/drivers/staging/phison/phison.c @@ -87,18 +87,7 @@ static struct pci_driver phison_pci_driver = { #endif }; -static int __init phison_ide_init(void) -{ - return pci_register_driver(&phison_pci_driver); -} - -static void __exit phison_ide_exit(void) -{ - pci_unregister_driver(&phison_pci_driver); -} - -module_init(phison_ide_init); -module_exit(phison_ide_exit); +module_pci_driver(phison_pci_driver); MODULE_AUTHOR("Evan Ko"); MODULE_DESCRIPTION("PCIE driver module for PHISON PS5000 E-BOX"); -- GitLab From d99b5ac65e7827f10ba60b1ea44d7bd041d58d1d Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Wed, 11 Jul 2012 11:54:15 +0545 Subject: [PATCH 2562/5711] staging/slicoss: disable pci device at remove at probe we enabled the device, and we should disable it at remove. Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 785e4c5f269e..56829fc032ff 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -3234,6 +3234,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev) } free_netdev(dev); pci_release_regions(pcidev); + pci_disable_device(pcidev); } static int slic_entry_halt(struct net_device *dev) -- GitLab From d59fdcfc63a2d15b11dde10a85233b95cee0ad2e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Jun 2012 00:14:15 +0200 Subject: [PATCH 2563/5711] ARM: integrator: put symbolic bus names on devices All the Integrator devices have bus names like "mb:16" which I think means "memory base 0x16000000" which is where the UART0 is. So let's call it "uart0" because that's what most platforms do these days. Change this everywhere for the integrator as we prepare for some core clock code movement. Cc: Russell King Signed-off-by: Linus Walleij Signed-off-by: Mike Turquette --- arch/arm/mach-integrator/core.c | 20 ++++++++++---------- arch/arm/mach-integrator/integrator_cp.c | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index eaf6c6366ffa..2a20bba246fb 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -41,17 +41,17 @@ static struct amba_pl010_data integrator_uart_data; #define KMI0_IRQ { IRQ_KMIINT0 } #define KMI1_IRQ { IRQ_KMIINT1 } -static AMBA_APB_DEVICE(rtc, "mb:15", 0, +static AMBA_APB_DEVICE(rtc, "rtc", 0, INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL); -static AMBA_APB_DEVICE(uart0, "mb:16", 0, +static AMBA_APB_DEVICE(uart0, "uart0", 0, INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, &integrator_uart_data); -static AMBA_APB_DEVICE(uart1, "mb:17", 0, +static AMBA_APB_DEVICE(uart1, "uart1", 0, INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data); -static AMBA_APB_DEVICE(kmi0, "mb:18", 0, KMI0_BASE, KMI0_IRQ, NULL); -static AMBA_APB_DEVICE(kmi1, "mb:19", 0, KMI1_BASE, KMI1_IRQ, NULL); +static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL); +static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL); static struct amba_device *amba_devs[] __initdata = { &rtc_device, @@ -83,19 +83,19 @@ static struct clk_lookup lookups[] = { .dev_id = "ap_timer", .clk = &clk24mhz, }, { /* UART0 */ - .dev_id = "mb:16", + .dev_id = "uart0", .clk = &uartclk, }, { /* UART1 */ - .dev_id = "mb:17", + .dev_id = "uart1", .clk = &uartclk, }, { /* KMI0 */ - .dev_id = "mb:18", + .dev_id = "kmi0", .clk = &clk24mhz, }, { /* KMI1 */ - .dev_id = "mb:19", + .dev_id = "kmi1", .clk = &clk24mhz, }, { /* MMCI - IntegratorCP */ - .dev_id = "mb:1c", + .dev_id = "mmci", .clk = &uartclk, } }; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index a56c53608939..a8c6480babdd 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -221,7 +221,7 @@ static struct clk sp804_clk = { static struct clk_lookup cp_lookups[] = { { /* CLCD */ - .dev_id = "mb:c0", + .dev_id = "clcd", .clk = &cp_auxclk, }, { /* SP804 timers */ .dev_id = "sp804", @@ -336,10 +336,10 @@ static struct mmci_platform_data mmc_data = { #define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 } #define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT } -static AMBA_APB_DEVICE(mmc, "mb:1c", 0, INTEGRATOR_CP_MMC_BASE, +static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE, INTEGRATOR_CP_MMC_IRQS, &mmc_data); -static AMBA_APB_DEVICE(aaci, "mb:1d", 0, INTEGRATOR_CP_AACI_BASE, +static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE, INTEGRATOR_CP_AACI_IRQS, NULL); @@ -393,7 +393,7 @@ static struct clcd_board clcd_data = { .remove = versatile_clcd_remove_dma, }; -static AMBA_AHB_DEVICE(clcd, "mb:c0", 0, INTCP_PA_CLCD_BASE, +static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE, { IRQ_CP_CLCDCINT }, &clcd_data); static struct amba_device *amba_devs[] __initdata = { -- GitLab From 91b87a4795c42b97b8d18c3757eff352458ecef4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Jun 2012 17:29:54 +0200 Subject: [PATCH 2564/5711] clk: add versatile ICST307 driver The ICST307 VCO clock has a shared driver in the ARM architecture. This patch provides a wrapper into the common clock framework so we can use the implementation in the ARM architecture without duplicating the code until all ARM platforms using this VCO are moved over. At that point we can merge the driver from the ARM platform into the generic file altogether. Cc: Russell King Cc: Mike Turquette Signed-off-by: Linus Walleij [mturquette@linaro.org: removed versatile Kconfig] Signed-off-by: Mike Turquette --- drivers/clk/Makefile | 1 + drivers/clk/versatile/Makefile | 2 + drivers/clk/versatile/clk-icst.c | 100 +++++++++++++++++++++++++++++++ drivers/clk/versatile/clk-icst.h | 10 ++++ 4 files changed, 113 insertions(+) create mode 100644 drivers/clk/versatile/Makefile create mode 100644 drivers/clk/versatile/clk-icst.c create mode 100644 drivers/clk/versatile/clk-icst.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 35d9fb44c814..a4d67d7a7534 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_U300) += clk-u300.o +obj-$(CONFIG_ARCH_INTEGRATOR) += versatile/ # Chip specific obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile new file mode 100644 index 000000000000..a83539b41787 --- /dev/null +++ b/drivers/clk/versatile/Makefile @@ -0,0 +1,2 @@ +# Makefile for Versatile-specific clocks +obj-$(CONFIG_ICST) += clk-icst.o diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c new file mode 100644 index 000000000000..f555b50a5fa5 --- /dev/null +++ b/drivers/clk/versatile/clk-icst.c @@ -0,0 +1,100 @@ +/* + * Driver for the ICST307 VCO clock found in the ARM Reference designs. + * We wrap the custom interface from into the generic + * clock framework. + * + * TODO: when all ARM reference designs are migrated to generic clocks, the + * ICST clock code from the ARM tree should probably be merged into this + * file. + */ +#include +#include +#include +#include + +#include "clk-icst.h" + +/** + * struct clk_icst - ICST VCO clock wrapper + * @hw: corresponding clock hardware entry + * @params: parameters for this ICST instance + * @rate: current rate + * @setvco: function to commit ICST settings to hardware + */ +struct clk_icst { + struct clk_hw hw; + const struct icst_params *params; + unsigned long rate; + struct icst_vco (*getvco)(void); + void (*setvco)(struct icst_vco); +}; + +#define to_icst(_hw) container_of(_hw, struct clk_icst, hw) + +static unsigned long icst_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_icst *icst = to_icst(hw); + struct icst_vco vco; + + vco = icst->getvco(); + icst->rate = icst_hz(icst->params, vco); + return icst->rate; +} + +static long icst_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_icst *icst = to_icst(hw); + struct icst_vco vco; + + vco = icst_hz_to_vco(icst->params, rate); + return icst_hz(icst->params, vco); +} + +static int icst_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_icst *icst = to_icst(hw); + struct icst_vco vco; + + vco = icst_hz_to_vco(icst->params, rate); + icst->rate = icst_hz(icst->params, vco); + icst->setvco(vco); + return 0; +} + +static const struct clk_ops icst_ops = { + .recalc_rate = icst_recalc_rate, + .round_rate = icst_round_rate, + .set_rate = icst_set_rate, +}; + +struct clk * __init icst_clk_register(struct device *dev, + const struct clk_icst_desc *desc) +{ + struct clk *clk; + struct clk_icst *icst; + struct clk_init_data init; + + icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); + if (!icst) { + pr_err("could not allocate ICST clock!\n"); + return ERR_PTR(-ENOMEM); + } + init.name = "icst"; + init.ops = &icst_ops; + init.flags = CLK_IS_ROOT; + init.parent_names = NULL; + init.num_parents = 0; + icst->hw.init = &init; + icst->params = desc->params; + icst->getvco = desc->getvco; + icst->setvco = desc->setvco; + + clk = clk_register(dev, &icst->hw); + if (IS_ERR(clk)) + kfree(icst); + + return clk; +} diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h new file mode 100644 index 000000000000..71b4c56c1410 --- /dev/null +++ b/drivers/clk/versatile/clk-icst.h @@ -0,0 +1,10 @@ +#include + +struct clk_icst_desc { + const struct icst_params *params; + struct icst_vco (*getvco)(void); + void (*setvco)(struct icst_vco); +}; + +struct clk *icst_clk_register(struct device *dev, + const struct clk_icst_desc *desc); -- GitLab From a613163dff04cbfcb7d66b06ef4a5f65498ee59b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Jun 2012 17:33:12 +0200 Subject: [PATCH 2565/5711] ARM: integrator: convert to common clock This converts the Integrator platform to use common clock and the ICST driver. Since from this point not all ARM reference platforms use the clock, we define CONFIG_PLAT_VERSATILE_CLOCK and select it for all platforms except the Integrator. Open issue: I could not use the .init_early() field of the machine descriptor to initialize the clocks, but had to move them to .init_irq(), so presumably .init_early() is so early that common clock is not up, and .init_machine() is too late since it's needed for the clockevent/clocksource initialization. Any suggestions on how to solve this is very welcome. Cc: Russell King Signed-off-by: Linus Walleij [mturquette@linaro.org: use 'select' instead of versatile Kconfig] Signed-off-by: Mike Turquette --- arch/arm/Kconfig | 7 +- arch/arm/mach-integrator/core.c | 45 ------- .../arm/mach-integrator/include/mach/clkdev.h | 26 ---- arch/arm/mach-integrator/integrator_ap.c | 8 +- arch/arm/mach-integrator/integrator_cp.c | 63 +--------- arch/arm/plat-versatile/Kconfig | 3 + arch/arm/plat-versatile/Makefile | 2 +- drivers/clk/versatile/Makefile | 1 + drivers/clk/versatile/clk-integrator.c | 111 ++++++++++++++++++ include/linux/platform_data/clk-integrator.h | 1 + 10 files changed, 131 insertions(+), 136 deletions(-) delete mode 100644 arch/arm/mach-integrator/include/mach/clkdev.h create mode 100644 drivers/clk/versatile/clk-integrator.c create mode 100644 include/linux/platform_data/clk-integrator.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c59853738967..6f8cf405d3ec 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -254,8 +254,8 @@ config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select ARM_AMBA select ARCH_HAS_CPUFREQ - select CLKDEV_LOOKUP - select HAVE_MACH_CLKDEV + select COMMON_CLK + select CLK_VERSATILE select HAVE_TCM select ICST select GENERIC_CLOCKEVENTS @@ -277,6 +277,7 @@ config ARCH_REALVIEW select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 select GPIO_PL061 if GPIOLIB @@ -295,6 +296,7 @@ config ARCH_VERSATILE select ARCH_WANT_OPTIONAL_GPIOLIB select NEED_MACH_IO_H if PCI select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD select PLAT_VERSATILE_FPGA_IRQ select ARM_TIMER_SP804 @@ -314,6 +316,7 @@ config ARCH_VEXPRESS select ICST select NO_IOPORT select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD help This enables support for the ARM Ltd Versatile Express boards. diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 2a20bba246fb..ebf680bebdf2 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -61,50 +60,6 @@ static struct amba_device *amba_devs[] __initdata = { &kmi1_device, }; -/* - * These are fixed clocks. - */ -static struct clk clk24mhz = { - .rate = 24000000, -}; - -static struct clk uartclk = { - .rate = 14745600, -}; - -static struct clk dummy_apb_pclk; - -static struct clk_lookup lookups[] = { - { /* Bus clock */ - .con_id = "apb_pclk", - .clk = &dummy_apb_pclk, - }, { - /* Integrator/AP timer frequency */ - .dev_id = "ap_timer", - .clk = &clk24mhz, - }, { /* UART0 */ - .dev_id = "uart0", - .clk = &uartclk, - }, { /* UART1 */ - .dev_id = "uart1", - .clk = &uartclk, - }, { /* KMI0 */ - .dev_id = "kmi0", - .clk = &clk24mhz, - }, { /* KMI1 */ - .dev_id = "kmi1", - .clk = &clk24mhz, - }, { /* MMCI - IntegratorCP */ - .dev_id = "mmci", - .clk = &uartclk, - } -}; - -void __init integrator_init_early(void) -{ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -} - static int __init integrator_init(void) { int i; diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h deleted file mode 100644 index bfe07679faec..000000000000 --- a/arch/arm/mach-integrator/include/mach/clkdev.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ASM_MACH_CLKDEV_H -#define __ASM_MACH_CLKDEV_H - -#include -#include - -struct clk { - unsigned long rate; - const struct clk_ops *ops; - struct module *owner; - const struct icst_params *params; - void __iomem *vcoreg; - void *data; -}; - -static inline int __clk_get(struct clk *clk) -{ - return try_module_get(clk->owner); -} - -static inline void __clk_put(struct clk *clk) -{ - module_put(clk->owner); -} - -#endif diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index c857501c5783..7b1055c8e0b9 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -33,6 +33,7 @@ #include #include #include +#include #include Cr component, bits [15:8] as Cb component and bits [31:16] must be zero. + + V4L2_CID_AUTOBRIGHTNESS + boolean + Enable Automatic Brightness. + V4L2_CID_ROTATE integer diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 9abd9abd4502..babfb13dc7f2 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -755,6 +755,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_HUE_AUTO: case V4L2_CID_CHROMA_AGC: case V4L2_CID_COLOR_KILLER: + case V4L2_CID_AUTOBRIGHTNESS: case V4L2_CID_MPEG_AUDIO_MUTE: case V4L2_CID_MPEG_VIDEO_MUTE: case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: -- GitLab From 7a3ed2d95e9ef3032700c2e56f3369d8652a6e8b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Jul 2012 16:11:11 -0300 Subject: [PATCH 4451/5711] [media] v4l2-ioctl: Don't assume file->private_data always points to a v4l2_fh Commit efbceecd4522a41b8442c6b4f68b4508d57d1ccf, adds a number of helper functions for ctrl related ioctls to v4l2-ioctl.c, these helpers assume that if file->private_data != NULL, it points to a v4l2_fh, which is only the case for drivers which actually use v4l2_fh. This breaks for example bttv which use the "filedata" pointer for its own uses, and now all the ctrl ioctls try to use whatever its filedata points to as v4l2_fh and think it has a ctrl_handler, leading to: [ 142.499214] BUG: unable to handle kernel NULL pointer dereference at 0000000000000021 [ 142.499270] IP: [] v4l2_queryctrl+0x29/0x230 [videodev] [ 142.514649] [] v4l_queryctrl+0x47/0x90 [videodev] [ 142.517417] [] __video_do_ioctl+0x2c1/0x420 [videodev] [ 142.520116] [] video_usercopy+0x1a6/0x470 [videodev] ... This patch adds the missing test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) tests to the ctrl ioctl helpers v4l2_fh paths, fixing the issues with for example the bttv driver. Signed-off-by: Hans Verkuil Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 17dff312d76d..68d89eadf1ca 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1486,7 +1486,8 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_queryctrl *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; if (vfh && vfh->ctrl_handler) return v4l2_queryctrl(vfh->ctrl_handler, p); @@ -1502,7 +1503,8 @@ static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_querymenu *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; if (vfh && vfh->ctrl_handler) return v4l2_querymenu(vfh->ctrl_handler, p); @@ -1518,7 +1520,8 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_control *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; struct v4l2_ext_controls ctrls; struct v4l2_ext_control ctrl; @@ -1551,7 +1554,8 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_control *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; struct v4l2_ext_controls ctrls; struct v4l2_ext_control ctrl; @@ -1579,7 +1583,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; if (vfh && vfh->ctrl_handler) @@ -1597,7 +1602,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; if (vfh && vfh->ctrl_handler) @@ -1615,7 +1621,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = fh; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; if (vfh && vfh->ctrl_handler) -- GitLab From 4faba767c6243b43ad975406fe027be7394e4591 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 23 Jun 2012 04:39:58 -0300 Subject: [PATCH 4452/5711] [media] shark2: New driver for the Griffin radioSHARK v2 USB radio receiver This driver consists of 2 parts, a generic tea5777 driver and a driver for the Griffin radioSHARK v2 USB radio receiver, which is the only driver using the generic tea5777 for now. This first version only implements FM support, once the the new VIDIOC_ENUM_FREQ_BANDS API is upstream I'll also add AM support. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/Kconfig | 17 + drivers/media/radio/Makefile | 3 + drivers/media/radio/radio-shark2.c | 348 ++++++++++++++++++++ drivers/media/radio/radio-tea5777.c | 489 ++++++++++++++++++++++++++++ drivers/media/radio/radio-tea5777.h | 87 +++++ 5 files changed, 944 insertions(+) create mode 100644 drivers/media/radio/radio-shark2.c create mode 100644 drivers/media/radio/radio-tea5777.c create mode 100644 drivers/media/radio/radio-tea5777.h diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index e3c117122351..8090b87b3066 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -74,6 +74,23 @@ config RADIO_SHARK To compile this driver as a module, choose M here: the module will be called radio-shark. +config RADIO_SHARK2 + tristate "Griffin radioSHARK2 USB radio receiver" + depends on USB + ---help--- + Choose Y here if you have this radio receiver. + + There are 2 versions of this device, this driver is for version 2, + which is black. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux API. Information on + this API and pointers to "v4l" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-shark2. + config I2C_SI4713 tristate "I2C driver for Silicon Labs Si4713 device" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index e03b258e18d4..c03ce4fe74e9 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o obj-$(CONFIG_RADIO_SHARK) += radio-shark.o +obj-$(CONFIG_RADIO_SHARK2) += shark2.o obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o @@ -30,4 +31,6 @@ obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o obj-$(CONFIG_RADIO_WL128X) += wl128x/ +shark2-objs := radio-shark2.o radio-tea5777.o + ccflags-y += -Isound diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c new file mode 100644 index 000000000000..b9575de3e7e8 --- /dev/null +++ b/drivers/media/radio/radio-shark2.c @@ -0,0 +1,348 @@ +/* + * Linux V4L2 radio driver for the Griffin radioSHARK2 USB radio receiver + * + * Note the radioSHARK2 offers the audio through a regular USB audio device, + * this driver only handles the tuning. + * + * The info necessary to drive the shark2 was taken from the small userspace + * shark2.c program by Hisaaki Shibata, which he kindly placed in the Public + * Domain. + * + * Copyright (c) 2012 Hans de Goede + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "radio-tea5777.h" + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + + +#define SHARK_IN_EP 0x83 +#define SHARK_OUT_EP 0x05 + +#define TB_LEN 7 +#define DRV_NAME "radioshark2" + +#define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev) + +enum { BLUE_LED, RED_LED, NO_LEDS }; + +static void shark_led_set_blue(struct led_classdev *led_cdev, + enum led_brightness value); +static void shark_led_set_red(struct led_classdev *led_cdev, + enum led_brightness value); + +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + +struct shark_device { + struct usb_device *usbdev; + struct v4l2_device v4l2_dev; + struct radio_tea5777 tea; + + struct work_struct led_work; + struct led_classdev leds[NO_LEDS]; + char led_names[NO_LEDS][32]; + atomic_t brightness[NO_LEDS]; + unsigned long brightness_new; + + u8 *transfer_buffer; +}; + +static atomic_t shark_instance = ATOMIC_INIT(0); + +static int shark_write_reg(struct radio_tea5777 *tea, u64 reg) +{ + struct shark_device *shark = tea->private_data; + int i, res, actual_len; + + memset(shark->transfer_buffer, 0, TB_LEN); + shark->transfer_buffer[0] = 0x81; /* Write register command */ + for (i = 0; i < 6; i++) + shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff; + + v4l2_dbg(1, debug, tea->v4l2_dev, + "shark2-write: %02x %02x %02x %02x %02x %02x %02x\n", + shark->transfer_buffer[0], shark->transfer_buffer[1], + shark->transfer_buffer[2], shark->transfer_buffer[3], + shark->transfer_buffer[4], shark->transfer_buffer[5], + shark->transfer_buffer[6]); + + res = usb_interrupt_msg(shark->usbdev, + usb_sndintpipe(shark->usbdev, SHARK_OUT_EP), + shark->transfer_buffer, TB_LEN, + &actual_len, 1000); + if (res < 0) { + v4l2_err(tea->v4l2_dev, "write error: %d\n", res); + return res; + } + + return 0; +} + +static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret) +{ + struct shark_device *shark = tea->private_data; + int i, res, actual_len; + u32 reg = 0; + + memset(shark->transfer_buffer, 0, TB_LEN); + shark->transfer_buffer[0] = 0x82; + res = usb_interrupt_msg(shark->usbdev, + usb_sndintpipe(shark->usbdev, SHARK_OUT_EP), + shark->transfer_buffer, TB_LEN, + &actual_len, 1000); + if (res < 0) { + v4l2_err(tea->v4l2_dev, "request-read error: %d\n", res); + return res; + } + + res = usb_interrupt_msg(shark->usbdev, + usb_rcvintpipe(shark->usbdev, SHARK_IN_EP), + shark->transfer_buffer, TB_LEN, + &actual_len, 1000); + if (res < 0) { + v4l2_err(tea->v4l2_dev, "read error: %d\n", res); + return res; + } + + for (i = 0; i < 3; i++) + reg |= shark->transfer_buffer[i] << (16 - i * 8); + + v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %02x %02x %02x\n", + shark->transfer_buffer[0], shark->transfer_buffer[1], + shark->transfer_buffer[2]); + + *reg_ret = reg; + return 0; +} + +static struct radio_tea5777_ops shark_tea_ops = { + .write_reg = shark_write_reg, + .read_reg = shark_read_reg, +}; + +static void shark_led_work(struct work_struct *work) +{ + struct shark_device *shark = + container_of(work, struct shark_device, led_work); + int i, res, brightness, actual_len; + /* + * We use the v4l2_dev lock and registered bit to ensure the device + * does not get unplugged and unreffed while we're running. + */ + mutex_lock(&shark->tea.mutex); + if (!video_is_registered(&shark->tea.vd)) + goto leave; + + for (i = 0; i < 2; i++) { + if (!test_and_clear_bit(i, &shark->brightness_new)) + continue; + + brightness = atomic_read(&shark->brightness[i]); + memset(shark->transfer_buffer, 0, TB_LEN); + shark->transfer_buffer[0] = 0x83 + i; + shark->transfer_buffer[1] = brightness; + res = usb_interrupt_msg(shark->usbdev, + usb_sndintpipe(shark->usbdev, + SHARK_OUT_EP), + shark->transfer_buffer, TB_LEN, + &actual_len, 1000); + if (res < 0) + v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", + shark->led_names[i], res); + } +leave: + mutex_unlock(&shark->tea.mutex); +} + +static void shark_led_set_blue(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct shark_device *shark = + container_of(led_cdev, struct shark_device, leds[BLUE_LED]); + + atomic_set(&shark->brightness[BLUE_LED], value); + set_bit(BLUE_LED, &shark->brightness_new); + schedule_work(&shark->led_work); +} + +static void shark_led_set_red(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct shark_device *shark = + container_of(led_cdev, struct shark_device, leds[RED_LED]); + + atomic_set(&shark->brightness[RED_LED], value); + set_bit(RED_LED, &shark->brightness_new); + schedule_work(&shark->led_work); +} + +static void usb_shark_disconnect(struct usb_interface *intf) +{ + struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + int i; + + mutex_lock(&shark->tea.mutex); + v4l2_device_disconnect(&shark->v4l2_dev); + radio_tea5777_exit(&shark->tea); + mutex_unlock(&shark->tea.mutex); + + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); + + v4l2_device_put(&shark->v4l2_dev); +} + +static void usb_shark_release(struct v4l2_device *v4l2_dev) +{ + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + + cancel_work_sync(&shark->led_work); + v4l2_device_unregister(&shark->v4l2_dev); + kfree(shark->transfer_buffer); + kfree(shark); +} + +static int usb_shark_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct shark_device *shark; + int i, retval = -ENOMEM; + + shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); + if (!shark) + return retval; + + shark->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL); + if (!shark->transfer_buffer) + goto err_alloc_buffer; + + /* + * Work around a bug in usbhid/hid-core.c, where it leaves a dangling + * pointer in intfdata causing v4l2-device.c to not set it. Which + * results in usb_shark_disconnect() referencing the dangling pointer + * + * REMOVE (as soon as the above bug is fixed, patch submitted) + */ + usb_set_intfdata(intf, NULL); + + shark->v4l2_dev.release = usb_shark_release; + v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); + if (retval) { + v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); + goto err_reg_dev; + } + + shark->usbdev = interface_to_usbdev(intf); + shark->tea.v4l2_dev = &shark->v4l2_dev; + shark->tea.private_data = shark; + shark->tea.ops = &shark_tea_ops; + shark->tea.has_am = true; + shark->tea.write_before_read = true; + strlcpy(shark->tea.card, "Griffin radioSHARK2", + sizeof(shark->tea.card)); + usb_make_path(shark->usbdev, shark->tea.bus_info, + sizeof(shark->tea.bus_info)); + + retval = radio_tea5777_init(&shark->tea, THIS_MODULE); + if (retval) { + v4l2_err(&shark->v4l2_dev, "couldn't init tea5777\n"); + goto err_init_tea; + } + + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + /* + * We don't fail the probe if we fail to register the leds, + * because once we've called radio_tea5777_init, the /dev/radio0 + * node may be opened from userspace holding a reference to us! + * + * Note we cannot register the leds first instead as + * shark_led_work depends on the v4l2 mutex and registered bit. + */ + retval = led_classdev_register(&intf->dev, &shark->leds[i]); + if (retval) + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + } + + return 0; + +err_init_tea: + v4l2_device_unregister(&shark->v4l2_dev); +err_reg_dev: + kfree(shark->transfer_buffer); +err_alloc_buffer: + kfree(shark); + + return retval; +} + +/* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */ +static struct usb_device_id usb_shark_device_table[] = { + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | + USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = 0x077d, + .idProduct = 0x627a, + .bcdDevice_lo = 0x0010, + .bcdDevice_hi = 0x0010, + .bInterfaceClass = 3, + }, + { } +}; +MODULE_DEVICE_TABLE(usb, usb_shark_device_table); + +static struct usb_driver usb_shark_driver = { + .name = DRV_NAME, + .probe = usb_shark_probe, + .disconnect = usb_shark_disconnect, + .id_table = usb_shark_device_table, +}; +module_usb_driver(usb_shark_driver); diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c new file mode 100644 index 000000000000..3e12179364f8 --- /dev/null +++ b/drivers/media/radio/radio-tea5777.c @@ -0,0 +1,489 @@ +/* + * v4l2 driver for TEA5777 Philips AM/FM radio tuner chips + * + * Copyright (c) 2012 Hans de Goede + * + * Based on the ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips: + * + * Copyright (c) 2004 Jaroslav Kysela + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "radio-tea5777.h" + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Routines for control of TEA5777 Philips AM/FM radio tuner chips"); +MODULE_LICENSE("GPL"); + +/* Fixed FM only band for now, will implement multi-band support when the + VIDIOC_ENUM_FREQ_BANDS API is upstream */ +#define TEA5777_FM_RANGELOW (76000 * 16) +#define TEA5777_FM_RANGEHIGH (108000 * 16) + +#define TEA5777_FM_IF 150 /* kHz */ +#define TEA5777_FM_FREQ_STEP 50 /* kHz */ + +/* Write reg, common bits */ +#define TEA5777_W_MUTE_MASK (1LL << 47) +#define TEA5777_W_MUTE_SHIFT 47 +#define TEA5777_W_AM_FM_MASK (1LL << 46) +#define TEA5777_W_AM_FM_SHIFT 46 +#define TEA5777_W_STB_MASK (1LL << 45) +#define TEA5777_W_STB_SHIFT 45 + +#define TEA5777_W_IFCE_MASK (1LL << 29) +#define TEA5777_W_IFCE_SHIFT 29 +#define TEA5777_W_IFW_MASK (1LL << 28) +#define TEA5777_W_IFW_SHIFT 28 +#define TEA5777_W_HILO_MASK (1LL << 27) +#define TEA5777_W_HILO_SHIFT 27 +#define TEA5777_W_DBUS_MASK (1LL << 26) +#define TEA5777_W_DBUS_SHIFT 26 + +#define TEA5777_W_INTEXT_MASK (1LL << 24) +#define TEA5777_W_INTEXT_SHIFT 24 +#define TEA5777_W_P1_MASK (1LL << 23) +#define TEA5777_W_P1_SHIFT 23 +#define TEA5777_W_P0_MASK (1LL << 22) +#define TEA5777_W_P0_SHIFT 22 +#define TEA5777_W_PEN1_MASK (1LL << 21) +#define TEA5777_W_PEN1_SHIFT 21 +#define TEA5777_W_PEN0_MASK (1LL << 20) +#define TEA5777_W_PEN0_SHIFT 20 + +#define TEA5777_W_CHP0_MASK (1LL << 18) +#define TEA5777_W_CHP0_SHIFT 18 +#define TEA5777_W_DEEM_MASK (1LL << 17) +#define TEA5777_W_DEEM_SHIFT 17 + +#define TEA5777_W_SEARCH_MASK (1LL << 7) +#define TEA5777_W_SEARCH_SHIFT 7 +#define TEA5777_W_PROGBLIM_MASK (1LL << 6) +#define TEA5777_W_PROGBLIM_SHIFT 6 +#define TEA5777_W_UPDWN_MASK (1LL << 5) +#define TEA5777_W_UPDWN_SHIFT 5 +#define TEA5777_W_SLEV_MASK (3LL << 3) +#define TEA5777_W_SLEV_SHIFT 3 + +/* Write reg, FM specific bits */ +#define TEA5777_W_FM_PLL_MASK (0x1fffLL << 32) +#define TEA5777_W_FM_PLL_SHIFT 32 +#define TEA5777_W_FM_FREF_MASK (0x03LL << 30) +#define TEA5777_W_FM_FREF_SHIFT 30 +#define TEA5777_W_FM_FREF_VALUE 0 /* 50 kHz tune steps, 150 kHz IF */ + +#define TEA5777_W_FM_FORCEMONO_MASK (1LL << 15) +#define TEA5777_W_FM_FORCEMONO_SHIFT 15 +#define TEA5777_W_FM_SDSOFF_MASK (1LL << 14) +#define TEA5777_W_FM_SDSOFF_SHIFT 14 +#define TEA5777_W_FM_DOFF_MASK (1LL << 13) +#define TEA5777_W_FM_DOFF_SHIFT 13 + +#define TEA5777_W_FM_STEP_MASK (3LL << 1) +#define TEA5777_W_FM_STEP_SHIFT 1 + +/* Write reg, AM specific bits */ +#define TEA5777_W_AM_PLL_MASK (0x7ffLL << 34) +#define TEA5777_W_AM_PLL_SHIFT 34 +#define TEA5777_W_AM_AGCRF_MASK (1LL << 33) +#define TEA5777_W_AM_AGCRF_SHIFT 33 +#define TEA5777_W_AM_AGCIF_MASK (1LL << 32) +#define TEA5777_W_AM_AGCIF_SHIFT 32 +#define TEA5777_W_AM_MWLW_MASK (1LL << 31) +#define TEA5777_W_AM_MWLW_SHIFT 31 +#define TEA5777_W_AM_LNA_MASK (1LL << 30) +#define TEA5777_W_AM_LNA_SHIFT 30 + +#define TEA5777_W_AM_PEAK_MASK (1LL << 25) +#define TEA5777_W_AM_PEAK_SHIFT 25 + +#define TEA5777_W_AM_RFB_MASK (1LL << 16) +#define TEA5777_W_AM_RFB_SHIFT 16 +#define TEA5777_W_AM_CALLIGN_MASK (1LL << 15) +#define TEA5777_W_AM_CALLIGN_SHIFT 15 +#define TEA5777_W_AM_CBANK_MASK (0x7fLL << 8) +#define TEA5777_W_AM_CBANK_SHIFT 8 + +#define TEA5777_W_AM_DELAY_MASK (1LL << 2) +#define TEA5777_W_AM_DELAY_SHIFT 2 +#define TEA5777_W_AM_STEP_MASK (1LL << 1) +#define TEA5777_W_AM_STEP_SHIFT 1 + +/* Read reg, common bits */ +#define TEA5777_R_LEVEL_MASK (0x0f << 17) +#define TEA5777_R_LEVEL_SHIFT 17 +#define TEA5777_R_SFOUND_MASK (0x01 << 16) +#define TEA5777_R_SFOUND_SHIFT 16 +#define TEA5777_R_BLIM_MASK (0x01 << 15) +#define TEA5777_R_BLIM_SHIFT 15 + +/* Read reg, FM specific bits */ +#define TEA5777_R_FM_STEREO_MASK (0x01 << 21) +#define TEA5777_R_FM_STEREO_SHIFT 21 +#define TEA5777_R_FM_PLL_MASK 0x1fff +#define TEA5777_R_FM_PLL_SHIFT 0 + +static u32 tea5777_freq_to_v4l2_freq(struct radio_tea5777 *tea, u32 freq) +{ + return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16; +} + +static int radio_tea5777_set_freq(struct radio_tea5777 *tea) +{ + u64 freq; + int res; + + freq = clamp_t(u32, tea->freq, + TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH); + freq = (freq + 8) / 16; /* to kHz */ + + freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP; + + tea->write_reg &= ~(TEA5777_W_FM_PLL_MASK | TEA5777_W_FM_FREF_MASK); + tea->write_reg |= freq << TEA5777_W_FM_PLL_SHIFT; + tea->write_reg |= TEA5777_W_FM_FREF_VALUE << TEA5777_W_FM_FREF_SHIFT; + + res = tea->ops->write_reg(tea, tea->write_reg); + if (res) + return res; + + tea->needs_write = false; + tea->read_reg = -1; + tea->freq = tea5777_freq_to_v4l2_freq(tea, freq); + + return 0; +} + +static int radio_tea5777_update_read_reg(struct radio_tea5777 *tea, int wait) +{ + int res; + + if (tea->read_reg != -1) + return 0; + + if (tea->write_before_read && tea->needs_write) { + res = radio_tea5777_set_freq(tea); + if (res) + return res; + } + + if (wait) { + if (schedule_timeout_interruptible(msecs_to_jiffies(wait))) + return -ERESTARTSYS; + } + + res = tea->ops->read_reg(tea, &tea->read_reg); + if (res) + return res; + + tea->needs_write = true; + return 0; +} + +/* + * Linux Video interface + */ + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strlcpy(v->card, tea->card, sizeof(v->card)); + strlcat(v->card, " TEA5777", sizeof(v->card)); + strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct radio_tea5777 *tea = video_drvdata(file); + int res; + + if (v->index > 0) + return -EINVAL; + + res = radio_tea5777_update_read_reg(tea, 0); + if (res) + return res; + + memset(v, 0, sizeof(*v)); + if (tea->has_am) + strlcpy(v->name, "AM/FM", sizeof(v->name)); + else + strlcpy(v->name, "FM", sizeof(v->name)); + v->type = V4L2_TUNER_RADIO; + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED; + v->rangelow = TEA5777_FM_RANGELOW; + v->rangehigh = TEA5777_FM_RANGEHIGH; + v->rxsubchans = (tea->read_reg & TEA5777_R_FM_STEREO_MASK) ? + V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + v->audmode = (tea->write_reg & TEA5777_W_FM_FORCEMONO_MASK) ? + V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + /* shift - 12 to convert 4-bits (0-15) scale to 16-bits (0-65535) */ + v->signal = (tea->read_reg & TEA5777_R_LEVEL_MASK) >> + (TEA5777_R_LEVEL_SHIFT - 12); + + /* Invalidate read_reg, so that next call we return up2date signal */ + tea->read_reg = -1; + + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + if (v->index) + return -EINVAL; + + if (v->audmode == V4L2_TUNER_MODE_MONO) + tea->write_reg |= TEA5777_W_FM_FORCEMONO_MASK; + else + tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; + + return radio_tea5777_set_freq(tea); +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = tea->freq; + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + + tea->freq = f->frequency; + return radio_tea5777_set_freq(tea); +} + +static int vidioc_s_hw_freq_seek(struct file *file, void *fh, + struct v4l2_hw_freq_seek *a) +{ + struct radio_tea5777 *tea = video_drvdata(file); + u32 orig_freq = tea->freq; + unsigned long timeout; + int res, spacing = 200 * 16; /* 200 kHz */ + /* These are fixed *for now* */ + const u32 seek_rangelow = TEA5777_FM_RANGELOW; + const u32 seek_rangehigh = TEA5777_FM_RANGEHIGH; + + if (a->tuner || a->wrap_around) + return -EINVAL; + + tea->write_reg |= TEA5777_W_PROGBLIM_MASK; + if (seek_rangelow != tea->seek_rangelow) { + tea->write_reg &= ~TEA5777_W_UPDWN_MASK; + tea->freq = seek_rangelow; + res = radio_tea5777_set_freq(tea); + if (res) + goto leave; + tea->seek_rangelow = tea->freq; + } + if (seek_rangehigh != tea->seek_rangehigh) { + tea->write_reg |= TEA5777_W_UPDWN_MASK; + tea->freq = seek_rangehigh; + res = radio_tea5777_set_freq(tea); + if (res) + goto leave; + tea->seek_rangehigh = tea->freq; + } + tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; + + tea->write_reg |= TEA5777_W_SEARCH_MASK; + if (a->seek_upward) { + tea->write_reg |= TEA5777_W_UPDWN_MASK; + tea->freq = orig_freq + spacing; + } else { + tea->write_reg &= ~TEA5777_W_UPDWN_MASK; + tea->freq = orig_freq - spacing; + } + res = radio_tea5777_set_freq(tea); + if (res) + goto leave; + + timeout = jiffies + msecs_to_jiffies(5000); + for (;;) { + if (time_after(jiffies, timeout)) { + res = -ENODATA; + break; + } + + res = radio_tea5777_update_read_reg(tea, 100); + if (res) + break; + + /* + * Note we use tea->freq to track how far we've searched sofar + * this is necessary to ensure we continue seeking at the right + * point, in the write_before_read case. + */ + tea->freq = (tea->read_reg & TEA5777_R_FM_PLL_MASK); + tea->freq = tea5777_freq_to_v4l2_freq(tea, tea->freq); + + if ((tea->read_reg & TEA5777_R_SFOUND_MASK)) { + tea->write_reg &= ~TEA5777_W_SEARCH_MASK; + return 0; + } + + if (tea->read_reg & TEA5777_R_BLIM_MASK) { + res = -ENODATA; + break; + } + + /* Force read_reg update */ + tea->read_reg = -1; + } +leave: + tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; + tea->write_reg &= ~TEA5777_W_SEARCH_MASK; + tea->freq = orig_freq; + radio_tea5777_set_freq(tea); + return res; +} + +static int tea575x_s_ctrl(struct v4l2_ctrl *c) +{ + struct radio_tea5777 *tea = + container_of(c->handler, struct radio_tea5777, ctrl_handler); + + switch (c->id) { + case V4L2_CID_AUDIO_MUTE: + if (c->val) + tea->write_reg |= TEA5777_W_MUTE_MASK; + else + tea->write_reg &= ~TEA5777_W_MUTE_MASK; + + return radio_tea5777_set_freq(tea); + } + + return -EINVAL; +} + +static const struct v4l2_file_operations tea575x_fops = { + .unlocked_ioctl = video_ioctl2, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, +}; + +static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct video_device tea575x_radio = { + .ioctl_ops = &tea575x_ioctl_ops, + .release = video_device_release_empty, +}; + +static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { + .s_ctrl = tea575x_s_ctrl, +}; + +int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner) +{ + int res; + + tea->write_reg = (1LL << TEA5777_W_IFCE_SHIFT) | + (1LL << TEA5777_W_IFW_SHIFT) | + (1LL << TEA5777_W_INTEXT_SHIFT) | + (1LL << TEA5777_W_CHP0_SHIFT) | + (2LL << TEA5777_W_SLEV_SHIFT); + tea->freq = 90500 * 16; /* 90.5Mhz default */ + res = radio_tea5777_set_freq(tea); + if (res) { + v4l2_err(tea->v4l2_dev, "can't set initial freq (%d)\n", res); + return res; + } + + tea->vd = tea575x_radio; + video_set_drvdata(&tea->vd, tea); + mutex_init(&tea->mutex); + strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + tea->vd.lock = &tea->mutex; + tea->vd.v4l2_dev = tea->v4l2_dev; + tea->fops = tea575x_fops; + tea->fops.owner = owner; + tea->vd.fops = &tea->fops; + set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); + + tea->vd.ctrl_handler = &tea->ctrl_handler; + v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); + v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + res = tea->ctrl_handler.error; + if (res) { + v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return res; + } + v4l2_ctrl_handler_setup(&tea->ctrl_handler); + + res = video_register_device(&tea->vd, VFL_TYPE_RADIO, -1); + if (res) { + v4l2_err(tea->v4l2_dev, "can't register video device!\n"); + v4l2_ctrl_handler_free(tea->vd.ctrl_handler); + return res; + } + + return 0; +} +EXPORT_SYMBOL_GPL(radio_tea5777_init); + +void radio_tea5777_exit(struct radio_tea5777 *tea) +{ + video_unregister_device(&tea->vd); + v4l2_ctrl_handler_free(tea->vd.ctrl_handler); +} +EXPORT_SYMBOL_GPL(radio_tea5777_exit); diff --git a/drivers/media/radio/radio-tea5777.h b/drivers/media/radio/radio-tea5777.h new file mode 100644 index 000000000000..55cbd78df5ed --- /dev/null +++ b/drivers/media/radio/radio-tea5777.h @@ -0,0 +1,87 @@ +#ifndef __RADIO_TEA5777_H +#define __RADIO_TEA5777_H + +/* + * v4l2 driver for TEA5777 Philips AM/FM radio tuner chips + * + * Copyright (c) 2012 Hans de Goede + * + * Based on the ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips: + * + * Copyright (c) 2004 Jaroslav Kysela + * Copyright (c) 2012 Hans de Goede + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#define TEA575X_FMIF 10700 +#define TEA575X_AMIF 450 + +struct radio_tea5777; + +struct radio_tea5777_ops { + /* + * Write the 6 bytes large write register of the tea5777 + * + * val represents the 6 write registers, with byte 1 from the + * datasheet being the most significant byte (so byte 5 of the u64), + * and byte 6 from the datasheet being the least significant byte. + * + * returns 0 on success. + */ + int (*write_reg)(struct radio_tea5777 *tea, u64 val); + /* + * Read the 3 bytes large read register of the tea5777 + * + * The read value gets returned in val, akin to write_reg, byte 1 from + * the datasheet is stored as the most significant byte (so byte 2 of + * the u32), and byte 3 from the datasheet gets stored as the least + * significant byte (iow byte 0 of the u32). + * + * returns 0 on success. + */ + int (*read_reg)(struct radio_tea5777 *tea, u32 *val); +}; + +struct radio_tea5777 { + struct v4l2_device *v4l2_dev; + struct v4l2_file_operations fops; + struct video_device vd; /* video device */ + bool has_am; /* Device can tune to AM freqs */ + bool write_before_read; /* must write before read quirk */ + bool needs_write; /* for write before read quirk */ + u32 freq; /* current frequency */ + u32 seek_rangelow; /* current hwseek limits */ + u32 seek_rangehigh; + u32 read_reg; + u64 write_reg; + struct mutex mutex; + struct radio_tea5777_ops *ops; + void *private_data; + u8 card[32]; + u8 bus_info[32]; + struct v4l2_ctrl_handler ctrl_handler; +}; + +int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner); +void radio_tea5777_exit(struct radio_tea5777 *tea); + +#endif /* __RADIO_TEA5777_H */ -- GitLab From 8bbb181308bc348e02bfdbebdedd4e4ec9d452ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Jul 2012 14:52:48 -0700 Subject: [PATCH 4453/5711] tun: Fix formatting. Signed-off-by: David S. Miller --- drivers/net/tun.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index f55c46222613..926d4db5cb38 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1382,9 +1382,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; - } else + } else { memset(&ifr, 0, sizeof(ifr)); - + } if (cmd == TUNGETFEATURES) { /* Currently this just means: "what IFF flags are valid?". * This is needed because we never checked for invalid flags on -- GitLab From 4099040eaaa4fe543c4e915b8cab51b1d843edee Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Fri, 22 Jun 2012 06:19:28 -0300 Subject: [PATCH 4454/5711] [media] videobuf-dma-contig: restore buffer mapping for uncached bufers from commit a8f3c203e19b702fa5e8e83a9b6fb3c5a6d1cce4 restore the mapping scheme for uncached buffers, which was changed in a common scheme for cached and uncached. This apparently was wrong, and was probably intended only for cached buffers. the fix fixes the crash observed while mapping uncached buffers. Signed-off-by: Lad, Prabhakar Signed-off-by: Hadli, Manjunath Acked-by: Federico Vaga Acked-by: Hans Verkuil Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-contig.c | 53 ++++++++++++++--------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 9b9a06fdd0f0..f68284655f20 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -359,32 +359,43 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, size = vma->vm_end - vma->vm_start; size = (size < mem->size) ? size : mem->size; - if (!mem->cached) + if (!mem->cached) { vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - pos = (unsigned long)mem->vaddr; - - while (size > 0) { - page = virt_to_page((void *)pos); - if (NULL == page) { - dev_err(q->dev, "mmap: virt_to_page failed\n"); - __videobuf_dc_free(q->dev, mem); - goto error; - } - retval = vm_insert_page(vma, start, page); + retval = remap_pfn_range(vma, vma->vm_start, + mem->dma_handle >> PAGE_SHIFT, + size, vma->vm_page_prot); if (retval) { - dev_err(q->dev, "mmap: insert failed with error %d\n", - retval); - __videobuf_dc_free(q->dev, mem); + dev_err(q->dev, "mmap: remap failed with error %d. ", + retval); + dma_free_coherent(q->dev, mem->size, + mem->vaddr, mem->dma_handle); goto error; } - start += PAGE_SIZE; - pos += PAGE_SIZE; + } else { + pos = (unsigned long)mem->vaddr; + + while (size > 0) { + page = virt_to_page((void *)pos); + if (NULL == page) { + dev_err(q->dev, "mmap: virt_to_page failed\n"); + __videobuf_dc_free(q->dev, mem); + goto error; + } + retval = vm_insert_page(vma, start, page); + if (retval) { + dev_err(q->dev, "mmap: insert failed with error %d\n", + retval); + __videobuf_dc_free(q->dev, mem); + goto error; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } } vma->vm_ops = &videobuf_vm_ops; -- GitLab From cca32e4bf999a34ac08d959f351f2b30bcd02460 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 29 Jul 2012 21:06:13 +0000 Subject: [PATCH 4455/5711] net: TCP early demux cleanup early_demux() handlers should be called in RCU context, and as we use skb_dst_set_noref(skb, dst), caller must not exit from RCU context before dst use (skb_dst(skb)) or release (skb_drop(dst)) Therefore, rcu_read_lock()/rcu_read_unlock() pairs around ->early_demux() are confusing and not needed : Protocol handlers are already in an RCU read lock section. (__netif_receive_skb() does the rcu_read_lock() ) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_input.c | 2 -- net/ipv6/ip6_input.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 981ff1eef28c..f1395a6fb35f 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -325,14 +325,12 @@ static int ip_rcv_finish(struct sk_buff *skb) const struct net_protocol *ipprot; int protocol = iph->protocol; - rcu_read_lock(); ipprot = rcu_dereference(inet_protos[protocol]); if (ipprot && ipprot->early_demux) { ipprot->early_demux(skb); /* must reload iph, skb->head might have changed */ iph = ip_hdr(skb); } - rcu_read_unlock(); } /* diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 47975e363fcd..a52d864d562b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -52,11 +52,9 @@ int ip6_rcv_finish(struct sk_buff *skb) if (sysctl_ip_early_demux && !skb_dst(skb)) { const struct inet6_protocol *ipprot; - rcu_read_lock(); ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]); if (ipprot && ipprot->early_demux) ipprot->early_demux(skb); - rcu_read_unlock(); } if (!skb_dst(skb)) ip6_route_input(skb); -- GitLab From 404e0a8b6a55d5e1cd138c6deb1bca9abdf75d8c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 29 Jul 2012 23:20:37 +0000 Subject: [PATCH 4456/5711] net: ipv4: fix RCU races on dst refcounts commit c6cffba4ffa2 (ipv4: Fix input route performance regression.) added various fatal races with dst refcounts. crashes happen on tcp workloads if routes are added/deleted at the same time. The dst_free() calls from free_fib_info_rcu() are clearly racy. We need instead regular dst refcounting (dst_release()) and make sure dst_release() is aware of RCU grace periods : Add DST_RCU_FREE flag so that dst_release() respects an RCU grace period before dst destruction for cached dst Introduce a new inet_sk_rx_dst_set() helper, using atomic_inc_not_zero() to make sure we dont increase a zero refcount (On a dst currently waiting an rcu grace period before destruction) rt_cache_route() must take a reference on the new cached route, and release it if was not able to install it. With this patch, my machines survive various benchmarks. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/dst.h | 7 +------ include/net/inet_sock.h | 13 +++++++++++++ net/core/dst.c | 26 +++++++++++++++++++++----- net/decnet/dn_route.c | 6 ++++++ net/ipv4/fib_semantics.c | 4 ++-- net/ipv4/route.c | 16 ++++------------ net/ipv4/tcp_input.c | 3 +-- net/ipv4/tcp_ipv4.c | 12 ++++++------ net/ipv4/tcp_minisocks.c | 3 +-- 9 files changed, 55 insertions(+), 35 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index baf597890064..31a9fd39edb6 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -61,6 +61,7 @@ struct dst_entry { #define DST_NOPEER 0x0040 #define DST_FAKE_RTABLE 0x0080 #define DST_XFRM_TUNNEL 0x0100 +#define DST_RCU_FREE 0x0200 unsigned short pending_confirm; @@ -382,12 +383,6 @@ static inline void dst_free(struct dst_entry *dst) __dst_free(dst); } -static inline void dst_rcu_free(struct rcu_head *head) -{ - struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); - dst_free(dst); -} - static inline void dst_confirm(struct dst_entry *dst) { dst->pending_confirm = 1; diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 613cfa401672..e3fd34c83ac9 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -249,4 +249,17 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) return flags; } +static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + if (atomic_inc_not_zero(&dst->__refcnt)) { + if (!(dst->flags & DST_RCU_FREE)) + dst->flags |= DST_RCU_FREE; + + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + } +} + #endif /* _INET_SOCK_H */ diff --git a/net/core/dst.c b/net/core/dst.c index 069d51d29414..d9e33ebe170f 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -258,6 +258,15 @@ again: } EXPORT_SYMBOL(dst_destroy); +static void dst_rcu_destroy(struct rcu_head *head) +{ + struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); + + dst = dst_destroy(dst); + if (dst) + __dst_free(dst); +} + void dst_release(struct dst_entry *dst) { if (dst) { @@ -265,10 +274,14 @@ void dst_release(struct dst_entry *dst) newrefcnt = atomic_dec_return(&dst->__refcnt); WARN_ON(newrefcnt < 0); - if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) { - dst = dst_destroy(dst); - if (dst) - __dst_free(dst); + if (unlikely(dst->flags & (DST_NOCACHE | DST_RCU_FREE)) && !newrefcnt) { + if (dst->flags & DST_RCU_FREE) { + call_rcu_bh(&dst->rcu_head, dst_rcu_destroy); + } else { + dst = dst_destroy(dst); + if (dst) + __dst_free(dst); + } } } } @@ -320,11 +333,14 @@ EXPORT_SYMBOL(__dst_destroy_metrics_generic); */ void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst) { + bool hold; + WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held()); /* If dst not in cache, we must take a reference, because * dst_release() will destroy dst as soon as its refcount becomes zero */ - if (unlikely(dst->flags & DST_NOCACHE)) { + hold = (dst->flags & (DST_NOCACHE | DST_RCU_FREE)) == DST_NOCACHE; + if (unlikely(hold)) { dst_hold(dst); skb_dst_set(skb, dst); } else { diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 85a3604c87c8..26719779ad8e 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -184,6 +184,12 @@ static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) return dn_rt_hash_mask & (unsigned int)tmp; } +static inline void dst_rcu_free(struct rcu_head *head) +{ + struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); + dst_free(dst); +} + static inline void dnrt_free(struct dn_route *rt) { call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index da0cc2e6b250..e55171f184f9 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -172,9 +172,9 @@ static void free_fib_info_rcu(struct rcu_head *head) if (nexthop_nh->nh_exceptions) free_nh_exceptions(nexthop_nh); if (nexthop_nh->nh_rth_output) - dst_free(&nexthop_nh->nh_rth_output->dst); + dst_release(&nexthop_nh->nh_rth_output->dst); if (nexthop_nh->nh_rth_input) - dst_free(&nexthop_nh->nh_rth_input->dst); + dst_release(&nexthop_nh->nh_rth_input->dst); } endfor_nexthops(fi); release_net(fi->fib_net); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fc1a81ca79a7..d6eabcfe8a90 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1199,11 +1199,6 @@ restart: fnhe->fnhe_stamp = jiffies; } -static inline void rt_free(struct rtable *rt) -{ - call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); -} - static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) { struct rtable *orig, *prev, **p = &nh->nh_rth_output; @@ -1213,17 +1208,14 @@ static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) orig = *p; + rt->dst.flags |= DST_RCU_FREE; + dst_hold(&rt->dst); prev = cmpxchg(p, orig, rt); if (prev == orig) { if (orig) - rt_free(orig); + dst_release(&orig->dst); } else { - /* Routes we intend to cache in the FIB nexthop have - * the DST_NOCACHE bit clear. However, if we are - * unsuccessful at storing this route into the cache - * we really need to set it. - */ - rt->dst.flags |= DST_NOCACHE; + dst_release(&rt->dst); } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a356e1fecf9a..9be30b039ae3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5604,8 +5604,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) tcp_set_state(sk, TCP_ESTABLISHED); if (skb != NULL) { - sk->sk_rx_dst = dst_clone(skb_dst(skb)); - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + inet_sk_rx_dst_set(sk, skb); security_inet_conn_established(sk, skb); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2fbd9921253f..7f91e5ac8277 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1617,19 +1617,19 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) #endif if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ + struct dst_entry *dst = sk->sk_rx_dst; + sock_rps_save_rxhash(sk, skb); - if (sk->sk_rx_dst) { - struct dst_entry *dst = sk->sk_rx_dst; + if (dst) { if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || dst->ops->check(dst, 0) == NULL) { dst_release(dst); sk->sk_rx_dst = NULL; } } - if (unlikely(sk->sk_rx_dst == NULL)) { - sk->sk_rx_dst = dst_clone(skb_dst(skb)); - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; - } + if (unlikely(sk->sk_rx_dst == NULL)) + inet_sk_rx_dst_set(sk, skb); + if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { rsk = sk; goto reset; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 3f1cc2028edd..232a90c3ec86 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -387,8 +387,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct tcp_sock *oldtp = tcp_sk(sk); struct tcp_cookie_values *oldcvp = oldtp->cookie_values; - newsk->sk_rx_dst = dst_clone(skb_dst(skb)); - inet_sk(newsk)->rx_dst_ifindex = skb->skb_iif; + inet_sk_rx_dst_set(newsk, skb); /* TCP Cookie Transactions require space for the cookie pair, * as it differs for each connection. There is no need to -- GitLab From 0c7462a2351b4cc502f326aad7fedd04909928be Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 30 Jul 2012 07:14:29 +0000 Subject: [PATCH 4457/5711] ipv4: remove rt_cache_rebuild_count After IP route cache removal, rt_cache_rebuild_count is no longer used. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ------ include/net/netns/ipv4.h | 2 -- net/ipv4/sysctl_net_ipv4.c | 11 ----------- 3 files changed, 19 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 406a5226220d..ca447b35b833 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -48,12 +48,6 @@ min_adv_mss - INTEGER The advertised MSS depends on the first hop route MTU, but will never be lower than this setting. -rt_cache_rebuild_count - INTEGER - The per net-namespace route cache emergency rebuild threshold. - Any net-namespace having its route cache rebuilt due to - a hash bucket chain being too long more than this many times - will have its route caching disabled - IP Fragmentation: ipfrag_high_thresh - INTEGER diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 0ffb8e31f3cd..1474dd65c66f 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -61,8 +61,6 @@ struct netns_ipv4 { int sysctl_icmp_ratelimit; int sysctl_icmp_ratemask; int sysctl_icmp_errors_use_inbound_ifaddr; - int sysctl_rt_cache_rebuild_count; - int current_rt_cache_rebuild_count; unsigned int sysctl_ping_group_range[2]; long sysctl_tcp_mem[3]; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 5840c3255721..4b6487a68279 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -783,13 +783,6 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "rt_cache_rebuild_count", - .data = &init_net.ipv4.sysctl_rt_cache_rebuild_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "ping_group_range", .data = &init_net.ipv4.sysctl_ping_group_range, @@ -829,8 +822,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) table[5].data = &net->ipv4.sysctl_icmp_ratemask; table[6].data = - &net->ipv4.sysctl_rt_cache_rebuild_count; - table[7].data = &net->ipv4.sysctl_ping_group_range; } @@ -842,8 +833,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_ping_group_range[0] = 1; net->ipv4.sysctl_ping_group_range[1] = 0; - net->ipv4.sysctl_rt_cache_rebuild_count = 4; - tcp_init_mem(net); net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); -- GitLab From 5a0d513b622ee41e117fc37e26e27e8ef42e8dae Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 30 Jul 2012 08:55:49 +0000 Subject: [PATCH 4458/5711] bridge: make port attributes const Simple table that can be marked const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_sysfs_if.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 6229b62749e8..13b36bdc76a7 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -27,7 +27,7 @@ struct brport_attribute { }; #define BRPORT_ATTR(_name,_mode,_show,_store) \ -struct brport_attribute brport_attr_##_name = { \ +const struct brport_attribute brport_attr_##_name = { \ .attr = {.name = __stringify(_name), \ .mode = _mode }, \ .show = _show, \ @@ -164,7 +164,7 @@ static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, store_multicast_router); #endif -static struct brport_attribute *brport_attrs[] = { +static const struct brport_attribute *brport_attrs[] = { &brport_attr_path_cost, &brport_attr_priority, &brport_attr_port_id, @@ -241,7 +241,7 @@ const struct sysfs_ops brport_sysfs_ops = { int br_sysfs_addif(struct net_bridge_port *p) { struct net_bridge *br = p->br; - struct brport_attribute **a; + const struct brport_attribute **a; int err; err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, -- GitLab From cac5d07e3ca696dcacfb123553cf6c722111cfd3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 18 Jul 2012 11:17:11 -0700 Subject: [PATCH 4459/5711] sunrpc: clnt: Add missing braces Add a missing set of braces that commit 4e0038b6b24 ("SUNRPC: Move clnt->cl_server into struct rpc_xprt") forgot. Signed-off-by: Joe Perches Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 3.4] --- net/sunrpc/clnt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f56f045778ae..aaf70aa65904 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1844,12 +1844,13 @@ call_timeout(struct rpc_task *task) return; } if (RPC_IS_SOFT(task)) { - if (clnt->cl_chatty) + if (clnt->cl_chatty) { rcu_read_lock(); printk(KERN_NOTICE "%s: server %s not responding, timed out\n", clnt->cl_protname, rcu_dereference(clnt->cl_xprt)->servername); rcu_read_unlock(); + } if (task->tk_flags & RPC_TASK_TIMEOUT) rpc_exit(task, -ETIMEDOUT); else -- GitLab From b1fc42302b75bb9c4940317e3bf2f1e2efdb3a1a Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:43:10 -0300 Subject: [PATCH 4460/5711] [media] davinci: vpif: add check for genuine interrupts in the isr As the same interrupt is shared between capture and display devices, sometimes we get isr calls where the interrupt might not genuinely belong to capture or display. Hence, add a condition in the isr to check for interrupt ownership and channel number to make sure we do not service wrong interrupts. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif.h | 15 +++++++++++++++ drivers/media/video/davinci/vpif_capture.c | 3 +++ drivers/media/video/davinci/vpif_display.c | 3 +++ 3 files changed, 21 insertions(+) diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h index 8bcac65f9294..a4d2141d1ef3 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/video/davinci/vpif.h @@ -569,6 +569,21 @@ static inline void ch3_set_vbi_addr(unsigned long top_strt_luma, regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_VANC); } +static inline int vpif_intr_status(int channel) +{ + int status = 0; + int mask; + + if (channel < 0 || channel > 3) + return 0; + + mask = 1 << channel; + status = regr(VPIF_STATUS) & mask; + regw(status, VPIF_STATUS_CLR); + + return status; +} + #define VPIF_MAX_NAME (30) /* This structure will store size parameters as per the mode selected by user */ diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 96046957bf21..e01141234846 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -341,6 +341,9 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) int fid = -1, i; channel_id = *(int *)(dev_id); + if (!vpif_intr_status(channel_id)) + return IRQ_NONE; + ch = dev->dev[channel_id]; field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index e6488ee7db18..a5049a92f851 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -307,6 +307,9 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) int channel_id = 0; channel_id = *(int *)(dev_id); + if (!vpif_intr_status(channel_id + 2)) + return IRQ_NONE; + ch = dev->dev[channel_id]; field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; for (i = 0; i < VPIF_NUMOBJECTS; i++) { -- GitLab From 0a63172a8abc135791c73fc418a20ea379745ae6 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:44:00 -0300 Subject: [PATCH 4461/5711] [media] davinci: vpif: make generic changes to re-use the vpif drivers on da850/omap-l138 soc change the dm646x specific strings in the driver to make them generic across platforms. In this case change all the strings which have a dm646x connotation to vpif which is a platform independent ip. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif.c | 2 +- drivers/media/video/davinci/vpif_capture.c | 9 ++++----- drivers/media/video/davinci/vpif_display.c | 14 +++++++------- drivers/media/video/davinci/vpif_display.h | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index af9680273ff9..774bcd3cf50c 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c @@ -1,5 +1,5 @@ /* - * vpif - DM646x Video Port Interface driver + * vpif - Video Port Interface driver * VPIF is a receiver and transmitter for video data. It has two channels(0, 1) * that receiveing video byte stream and two channels(2, 3) for video output. * The hardware supports SDTV, HDTV formats, raw data capture. diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index e01141234846..f31c1661cd56 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -1682,7 +1682,7 @@ static int vpif_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; strlcpy(cap->driver, "vpif capture", sizeof(cap->driver)); - strlcpy(cap->bus_info, "DM646x Platform", sizeof(cap->bus_info)); + strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info)); strlcpy(cap->card, config->card_name, sizeof(cap->card)); return 0; @@ -2190,7 +2190,7 @@ static __init int vpif_probe(struct platform_device *pdev) while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, - "DM646x_Capture", + "VPIF_Capture", (void *)(&vpif_obj.dev[k]->channel_id))) { err = -EBUSY; i--; @@ -2219,7 +2219,7 @@ static __init int vpif_probe(struct platform_device *pdev) vfd->v4l2_dev = &vpif_obj.v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), - "DM646x_VPIFCapture_DRIVER_V%s", + "VPIF_Capture_DRIVER_V%s", VPIF_CAPTURE_VERSION); /* Set video_dev to the video device */ ch->video_dev = vfd; @@ -2278,8 +2278,7 @@ static __init int vpif_probe(struct platform_device *pdev) vpif_obj.sd[i]->grp_id = 1 << i; } - v4l2_info(&vpif_obj.v4l2_dev, - "DM646x VPIF capture driver initialized\n"); + v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); return 0; probe_subdev_out: diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index a5049a92f851..8d8f3b4e558f 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -46,7 +46,7 @@ MODULE_DESCRIPTION("TI DaVinci VPIF Display driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(VPIF_DISPLAY_VERSION); -#define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50) +#define VPIF_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50) #define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg) #define vpif_dbg(level, debug, fmt, arg...) \ @@ -972,7 +972,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; - if (!(*std_id & DM646X_V4L2_STD)) + if (!(*std_id & VPIF_V4L2_STD)) return -EINVAL; if (common->started) { @@ -1223,7 +1223,7 @@ static int vpif_enum_output(struct file *file, void *fh, strcpy(output->name, config->output[output->index]); output->type = V4L2_OUTPUT_TYPE_ANALOG; - output->std = DM646X_V4L2_STD; + output->std = VPIF_V4L2_STD; return 0; } @@ -1608,7 +1608,7 @@ static struct video_device vpif_video_template = { .name = "vpif", .fops = &vpif_fops, .ioctl_ops = &vpif_ioctl_ops, - .tvnorms = DM646X_V4L2_STD, + .tvnorms = VPIF_V4L2_STD, .current_norm = V4L2_STD_625_50, }; @@ -1710,7 +1710,7 @@ static __init int vpif_probe(struct platform_device *pdev) while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, - "DM646x_Display", + "VPIF_Display", (void *)(&vpif_obj.dev[k]->channel_id))) { err = -EBUSY; goto vpif_int_err; @@ -1740,7 +1740,7 @@ static __init int vpif_probe(struct platform_device *pdev) vfd->v4l2_dev = &vpif_obj.v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), - "DM646x_VPIFDisplay_DRIVER_V%s", + "VPIF_Display_DRIVER_V%s", VPIF_DISPLAY_VERSION); /* Set video_dev to the video device */ @@ -1826,7 +1826,7 @@ static __init int vpif_probe(struct platform_device *pdev) } v4l2_info(&vpif_obj.v4l2_dev, - "DM646x VPIF display driver initialized\n"); + " VPIF display driver initialized\n"); return 0; probe_subdev_out: diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h index 56879d1a0684..dd4887c5b3ba 100644 --- a/drivers/media/video/davinci/vpif_display.h +++ b/drivers/media/video/davinci/vpif_display.h @@ -1,5 +1,5 @@ /* - * DM646x display header file + * VPIF display header file * * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ * -- GitLab From 0316b89ae0de139875594d7fa0527cb5af69bd69 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:44:31 -0300 Subject: [PATCH 4462/5711] [media] davinci: vpif: make request_irq flags as shared omap-l138 shares the interrupt between capture and display. Make sure we are able to request for the same irq number by making a shared irq request. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_capture.c | 2 +- drivers/media/video/davinci/vpif_display.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index f31c1661cd56..bce31ea55dc4 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -2189,7 +2189,7 @@ static __init int vpif_probe(struct platform_device *pdev) k = 0; while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, + if (request_irq(i, vpif_channel_isr, IRQF_SHARED, "VPIF_Capture", (void *)(&vpif_obj.dev[k]->channel_id))) { err = -EBUSY; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 8d8f3b4e558f..1d0c18ab7922 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -1709,7 +1709,7 @@ static __init int vpif_probe(struct platform_device *pdev) k = 0; while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, + if (request_irq(i, vpif_channel_isr, IRQF_SHARED, "VPIF_Display", (void *)(&vpif_obj.dev[k]->channel_id))) { err = -EBUSY; -- GitLab From 3bc1953b22ba11922190bc76682ece431b6eefff Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:47:17 -0300 Subject: [PATCH 4463/5711] [media] davinci: vpif: fix setting of data width in config_vpif_params() function fix setting of data width in config_vpif_params() function, which was wrongly set. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index 774bcd3cf50c..8c4ff14377ad 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c @@ -346,7 +346,7 @@ static void config_vpif_params(struct vpif_params *vpifparams, value = regr(reg); /* Set data width */ - value &= ((~(unsigned int)(0x3)) << + value &= ~(0x3u << VPIF_CH_DATA_WIDTH_BIT); value |= ((vpifparams->params.data_sz) << VPIF_CH_DATA_WIDTH_BIT); -- GitLab From fc613d44e08a9f0986e493e2605132161b5b39a5 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:49:10 -0300 Subject: [PATCH 4464/5711] [media] davinci: vpif display: size up the memory for the buffers from the buffer pool Size up the memory for the buffers from the buffer pool allocated in board file. Then adjust the reqbuf count depending the available memory. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_display.c | 42 ++++++++++++++++++++-- drivers/media/video/davinci/vpif_display.h | 1 + 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 1d0c18ab7922..e0070cd6f41e 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -187,6 +187,24 @@ static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, return 0; *size = config_params.channel_bufsize[ch->channel_id]; + + /* + * Checking if the buffer size exceeds the available buffer + * ycmux_mode = 0 means 1 channel mode HD and + * ycmux_mode = 1 means 2 channels mode SD + */ + if (ch->vpifparams.std_info.ycmux_mode == 0) { + if (config_params.video_limit[ch->channel_id]) + while (*size * *count > (config_params.video_limit[0] + + config_params.video_limit[1])) + (*count)--; + } else { + if (config_params.video_limit[ch->channel_id]) + while (*size * *count > + config_params.video_limit[ch->channel_id]) + (*count)--; + } + if (*count < config_params.min_numbuffers) *count = config_params.min_numbuffers; @@ -828,7 +846,7 @@ static int vpif_reqbufs(struct file *file, void *priv, common = &ch->common[index]; - if (common->fmt.type != reqbuf->type) + if (common->fmt.type != reqbuf->type || !vpif_dev) return -EINVAL; if (0 != common->io_usrs) @@ -845,7 +863,7 @@ static int vpif_reqbufs(struct file *file, void *priv, /* Initialize videobuf queue as per the buffer type */ videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, NULL, + &video_qops, vpif_dev, &common->irqlock, reqbuf->type, field, sizeof(struct videobuf_buffer), fh, @@ -1690,9 +1708,9 @@ static __init int vpif_probe(struct platform_device *pdev) struct video_device *vfd; struct resource *res; int subdev_count; + size_t size; vpif_dev = &pdev->dev; - err = initialize_vpif(); if (err) { @@ -1747,6 +1765,24 @@ static __init int vpif_probe(struct platform_device *pdev) ch->video_dev = vfd; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + size = resource_size(res); + /* The resources are divided into two equal memory and when + * we have HD output we can add them together + */ + for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { + ch = vpif_obj.dev[j]; + ch->channel_id = j; + + /* only enabled if second resource exists */ + config_params.video_limit[ch->channel_id] = 0; + if (size) + config_params.video_limit[ch->channel_id] = + size/2; + } + } + for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { ch = vpif_obj.dev[j]; /* Initialize field of the channel objects */ diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h index dd4887c5b3ba..8a311f10cc3a 100644 --- a/drivers/media/video/davinci/vpif_display.h +++ b/drivers/media/video/davinci/vpif_display.h @@ -158,6 +158,7 @@ struct vpif_config_params { u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS]; + u32 video_limit[VPIF_DISPLAY_NUM_CHANNELS]; u8 min_numbuffers; }; -- GitLab From 764af39aa415c9418f035d2a4bd606d7a7814a68 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:49:34 -0300 Subject: [PATCH 4465/5711] [media] davinci: vpif capture: size up the memory for the buffers from the buffer pool Size up the memory for the buffers from the buffer pool allocated in board file. Then adjust the reqbuf count depending the available memory. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_capture.c | 39 ++++++++++++++++++++-- drivers/media/video/davinci/vpif_capture.h | 1 + 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index bce31ea55dc4..d126fb6d74b6 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -217,6 +217,23 @@ static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, /* Calculate the size of the buffer */ *size = config_params.channel_bufsize[ch->channel_id]; + /* + * Checking if the buffer size exceeds the available buffer + * ycmux_mode = 0 means 1 channel mode HD and + * ycmux_mode = 1 means 2 channels mode SD + */ + if (ch->vpifparams.std_info.ycmux_mode == 0) { + if (config_params.video_limit[ch->channel_id]) + while (*size * *count > (config_params.video_limit[0] + + config_params.video_limit[1])) + (*count)--; + } else { + if (config_params.video_limit[ch->channel_id]) + while (*size * *count > + config_params.video_limit[ch->channel_id]) + (*count)--; + } + if (*count < config_params.min_numbuffers) *count = config_params.min_numbuffers; return 0; @@ -890,7 +907,7 @@ static int vpif_reqbufs(struct file *file, void *priv, } } - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type) + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type || !vpif_dev) return -EINVAL; index = VPIF_VIDEO_INDEX; @@ -902,7 +919,7 @@ static int vpif_reqbufs(struct file *file, void *priv, /* Initialize videobuf queue as per the buffer type */ videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, NULL, + &video_qops, vpif_dev, &common->irqlock, reqbuf->type, common->fmt.fmt.pix.field, @@ -2171,6 +2188,7 @@ static __init int vpif_probe(struct platform_device *pdev) struct video_device *vfd; struct resource *res; int subdev_count; + size_t size; vpif_dev = &pdev->dev; @@ -2225,6 +2243,23 @@ static __init int vpif_probe(struct platform_device *pdev) ch->video_dev = vfd; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + size = resource_size(res); + /* The resources are divided into two equal memory and when we + * have HD output we can add them together + */ + for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { + ch = vpif_obj.dev[j]; + ch->channel_id = j; + /* only enabled if second resource exists */ + config_params.video_limit[ch->channel_id] = 0; + if (size) + config_params.video_limit[ch->channel_id] = + size/2; + } + } + for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { ch = vpif_obj.dev[j]; ch->channel_id = j; diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h index a693d4ebda55..8095910f02c1 100644 --- a/drivers/media/video/davinci/vpif_capture.h +++ b/drivers/media/video/davinci/vpif_capture.h @@ -151,6 +151,7 @@ struct vpif_config_params { u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; u8 default_device[VPIF_CAPTURE_NUM_CHANNELS]; + u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS]; u8 max_device_type; }; /* Struct which keeps track of the line numbers for the sliced vbi service */ -- GitLab From 60aa38d87d7d50a89e43b77559307a95a42bf07e Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Thu, 28 Jun 2012 09:28:05 -0300 Subject: [PATCH 4466/5711] [media] davinci: vpif capture: migrate driver to videobuf2 This patch migrates VPIF capture driver to videobuf2 framework. Signed-off-by: Lad, Prabhakar Signed-off-by: Manjunath Hadli Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/Kconfig | 2 +- drivers/media/video/davinci/vpif_capture.c | 596 ++++++++++----------- drivers/media/video/davinci/vpif_capture.h | 15 +- 3 files changed, 281 insertions(+), 332 deletions(-) diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig index 9337b5605c90..c45739dd461f 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/video/davinci/Kconfig @@ -14,7 +14,7 @@ config DISPLAY_DAVINCI_DM646X_EVM config CAPTURE_DAVINCI_DM646X_EVM tristate "DM646x EVM Video Capture" depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF help Support for DM6467 based capture device. diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index d126fb6d74b6..1d4427aa08a5 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -80,108 +80,45 @@ static struct vpif_config_params config_params = { /* global variables */ static struct vpif_device vpif_obj = { {NULL} }; static struct device *vpif_dev; - -/** - * vpif_uservirt_to_phys : translate user/virtual address to phy address - * @virtp: user/virtual address - * - * This inline function is used to convert user space virtual address to - * physical address. - */ -static inline u32 vpif_uservirt_to_phys(u32 virtp) -{ - unsigned long physp = 0; - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - - vma = find_vma(mm, virtp); - - /* For kernel direct-mapped memory, take the easy way */ - if (virtp >= PAGE_OFFSET) - physp = virt_to_phys((void *)virtp); - else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) - /** - * this will catch, kernel-allocated, mmaped-to-usermode - * addresses - */ - physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); - else { - /* otherwise, use get_user_pages() for general userland pages */ - int res, nr_pages = 1; - struct page *pages; - - down_read(¤t->mm->mmap_sem); - - res = get_user_pages(current, current->mm, - virtp, nr_pages, 1, 0, &pages, NULL); - up_read(¤t->mm->mmap_sem); - - if (res == nr_pages) - physp = __pa(page_address(&pages[0]) + - (virtp & ~PAGE_MASK)); - else { - vpif_err("get_user_pages failed\n"); - return 0; - } - } - return physp; -} +static void vpif_calculate_offsets(struct channel_obj *ch); +static void vpif_config_addr(struct channel_obj *ch, int muxmode); /** * buffer_prepare : callback function for buffer prepare - * @q : buffer queue ptr - * @vb: ptr to video buffer - * @field: field info + * @vb: ptr to vb2_buffer * - * This is the callback function for buffer prepare when videobuf_qbuf() + * This is the callback function for buffer prepare when vb2_qbuf() * function is called. The buffer is prepared and user space virtual address * or user address is converted into physical address */ -static int vpif_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) +static int vpif_buffer_prepare(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_queue *q = vb->vb2_queue; struct channel_obj *ch = fh->channel; struct common_obj *common; unsigned long addr; - vpif_dbg(2, debug, "vpif_buffer_prepare\n"); common = &ch->common[VPIF_VIDEO_INDEX]; - /* If buffer is not initialized, initialize it */ - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = common->width; - vb->height = common->height; - vb->size = vb->width * vb->height; - vb->field = field; - } - vb->state = VIDEOBUF_PREPARED; - /** - * if user pointer memory mechanism is used, get the physical - * address of the buffer - */ - if (V4L2_MEMORY_USERPTR == common->memory) { - if (0 == vb->baddr) { - vpif_dbg(1, debug, "buffer address is 0\n"); - return -EINVAL; - - } - vb->boff = vpif_uservirt_to_phys(vb->baddr); - if (!IS_ALIGNED(vb->boff, 8)) + if (vb->state != VB2_BUF_STATE_ACTIVE && + vb->state != VB2_BUF_STATE_PREPARED) { + vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); + if (vb2_plane_vaddr(vb, 0) && + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) goto exit; - } + addr = vb2_dma_contig_plane_dma_addr(vb, 0); - addr = vb->boff; - if (q->streaming) { - if (!IS_ALIGNED((addr + common->ytop_off), 8) || - !IS_ALIGNED((addr + common->ybtm_off), 8) || - !IS_ALIGNED((addr + common->ctop_off), 8) || - !IS_ALIGNED((addr + common->cbtm_off), 8)) - goto exit; + if (q->streaming) { + if (!IS_ALIGNED((addr + common->ytop_off), 8) || + !IS_ALIGNED((addr + common->ybtm_off), 8) || + !IS_ALIGNED((addr + common->ctop_off), 8) || + !IS_ALIGNED((addr + common->cbtm_off), 8)) + goto exit; + } } return 0; exit: @@ -190,66 +127,79 @@ exit: } /** - * vpif_buffer_setup : Callback function for buffer setup. - * @q: buffer queue ptr - * @count: number of buffers - * @size: size of the buffer + * vpif_buffer_queue_setup : Callback function for buffer setup. + * @vq: vb2_queue ptr + * @fmt: v4l2 format + * @nbuffers: ptr to number of buffers requested by application + * @nplanes:: contains number of distinct video planes needed to hold a frame + * @sizes[]: contains the size (in bytes) of each plane. + * @alloc_ctxs: ptr to allocation context * * This callback function is called when reqbuf() is called to adjust * the buffer count and buffer size */ -static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) +static int vpif_buffer_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); struct channel_obj *ch = fh->channel; struct common_obj *common; + unsigned long size; common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_buffer_setup\n"); /* If memory type is not mmap, return */ - if (V4L2_MEMORY_MMAP != common->memory) - return 0; - - /* Calculate the size of the buffer */ - *size = config_params.channel_bufsize[ch->channel_id]; - - /* - * Checking if the buffer size exceeds the available buffer - * ycmux_mode = 0 means 1 channel mode HD and - * ycmux_mode = 1 means 2 channels mode SD - */ - if (ch->vpifparams.std_info.ycmux_mode == 0) { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > (config_params.video_limit[0] + if (V4L2_MEMORY_MMAP == common->memory) { + /* Calculate the size of the buffer */ + size = config_params.channel_bufsize[ch->channel_id]; + /* + * Checking if the buffer size exceeds the available buffer + * ycmux_mode = 0 means 1 channel mode HD and + * ycmux_mode = 1 means 2 channels mode SD + */ + if (ch->vpifparams.std_info.ycmux_mode == 0) { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > + (config_params.video_limit[0] + config_params.video_limit[1])) - (*count)--; - } else { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > + (*nbuffers)--; + } else { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > config_params.video_limit[ch->channel_id]) - (*count)--; + (*nbuffers)--; + } + + } else { + size = common->fmt.fmt.pix.sizeimage; } - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; + if (*nbuffers < config_params.min_numbuffers) + *nbuffers = config_params.min_numbuffers; + + *nplanes = 1; + sizes[0] = size; + alloc_ctxs[0] = common->alloc_ctx; + return 0; } /** * vpif_buffer_queue : Callback function to add buffer to DMA queue - * @q: ptr to videobuf_queue - * @vb: ptr to videobuf_buffer + * @vb: ptr to vb2_buffer */ -static void vpif_buffer_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buffer_queue(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); struct channel_obj *ch = fh->channel; + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); struct common_obj *common; common = &ch->common[VPIF_VIDEO_INDEX]; @@ -257,43 +207,189 @@ static void vpif_buffer_queue(struct videobuf_queue *q, vpif_dbg(2, debug, "vpif_buffer_queue\n"); /* add the buffer to the DMA queue */ - list_add_tail(&vb->queue, &common->dma_queue); - /* Change state of the buffer */ - vb->state = VIDEOBUF_QUEUED; + list_add_tail(&buf->list, &common->dma_queue); } /** - * vpif_buffer_release : Callback function to free buffer - * @q: buffer queue ptr - * @vb: ptr to video buffer + * vpif_buf_cleanup : Callback function to free buffer + * @vb: ptr to vb2_buffer * - * This function is called from the videobuf layer to free memory + * This function is called from the videobuf2 layer to free memory * allocated to the buffers */ -static void vpif_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buf_cleanup(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); struct channel_obj *ch = fh->channel; struct common_obj *common; + unsigned long flags; common = &ch->common[VPIF_VIDEO_INDEX]; - videobuf_dma_contig_free(q, vb); - vb->state = VIDEOBUF_NEEDS_INIT; + spin_lock_irqsave(&common->irqlock, flags); + if (vb->state == VB2_BUF_STATE_ACTIVE) + list_del_init(&buf->list); + spin_unlock_irqrestore(&common->irqlock, flags); + } -static struct videobuf_queue_ops video_qops = { - .buf_setup = vpif_buffer_setup, - .buf_prepare = vpif_buffer_prepare, - .buf_queue = vpif_buffer_queue, - .buf_release = vpif_buffer_release, -}; +static void vpif_wait_prepare(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_unlock(&common->lock); +} + +static void vpif_wait_finish(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); +} + +static int vpif_buffer_init(struct vb2_buffer *vb) +{ + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); + + INIT_LIST_HEAD(&buf->list); + + return 0; +} static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} }; +static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct vpif_capture_config *vpif_config_data = + vpif_dev->platform_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_params *vpif = &ch->vpifparams; + unsigned long addr = 0; + int ret; + + /* If buffer queue is empty, return error */ + if (list_empty(&common->dma_queue)) { + vpif_dbg(1, debug, "buffer queue is empty\n"); + return -EIO; + } + + /* Get the next frame from the buffer queue */ + common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, + struct vpif_cap_buffer, list); + /* Remove buffer from the buffer queue */ + list_del(&common->cur_frm->list); + /* Mark state of the current frame to active */ + common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + /* Initialize field_id and started member */ + ch->field_id = 0; + common->started = 1; + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); + + /* Calculate the offset for Y and C data in the buffer */ + vpif_calculate_offsets(ch); + + if ((vpif->std_info.frm_fmt && + ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && + (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || + (!vpif->std_info.frm_fmt && + (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { + vpif_dbg(1, debug, "conflict in field format and std format\n"); + return -EINVAL; + } + + /* configure 1 or 2 channel mode */ + ret = vpif_config_data->setup_input_channel_mode + (vpif->std_info.ycmux_mode); + + if (ret < 0) { + vpif_dbg(1, debug, "can't set vpif channel mode\n"); + return ret; + } + + /* Call vpif_set_params function to set the parameters and addresses */ + ret = vpif_set_video_params(vpif, ch->channel_id); + + if (ret < 0) { + vpif_dbg(1, debug, "can't set video params\n"); + return ret; + } + + common->started = ret; + vpif_config_addr(ch, ret); + + common->set_addr(addr + common->ytop_off, + addr + common->ybtm_off, + addr + common->ctop_off, + addr + common->cbtm_off); + + /** + * Set interrupt for both the fields in VPIF Register enable channel in + * VPIF register + */ + if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { + channel0_intr_assert(); + channel0_intr_enable(1); + enable_channel0(1); + } + if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || + (common->started == 2)) { + channel1_intr_assert(); + channel1_intr_enable(1); + enable_channel1(1); + } + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; + + return 0; +} + +/* abort streaming and wait for last buffer */ +static int vpif_stop_streaming(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + if (!vb2_is_streaming(vq)) + return 0; + + common = &ch->common[VPIF_VIDEO_INDEX]; + + /* release all active buffers */ + while (!list_empty(&common->dma_queue)) { + common->next_frm = list_entry(common->dma_queue.next, + struct vpif_cap_buffer, list); + list_del(&common->next_frm->list); + vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); + } + + return 0; +} + +static struct vb2_ops video_qops = { + .queue_setup = vpif_buffer_queue_setup, + .wait_prepare = vpif_wait_prepare, + .wait_finish = vpif_wait_finish, + .buf_init = vpif_buffer_init, + .buf_prepare = vpif_buffer_prepare, + .start_streaming = vpif_start_streaming, + .stop_streaming = vpif_stop_streaming, + .buf_cleanup = vpif_buf_cleanup, + .buf_queue = vpif_buffer_queue, +}; + /** * vpif_process_buffer_complete: process a completed buffer * @common: ptr to common channel object @@ -304,9 +400,9 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = */ static void vpif_process_buffer_complete(struct common_obj *common) { - do_gettimeofday(&common->cur_frm->ts); - common->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&common->cur_frm->done); + do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_DONE); /* Make curFrm pointing to nextFrm */ common->cur_frm = common->next_frm; } @@ -324,14 +420,11 @@ static void vpif_schedule_next_buffer(struct common_obj *common) unsigned long addr = 0; common->next_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); + struct vpif_cap_buffer, list); /* Remove that buffer from the buffer queue */ - list_del(&common->next_frm->queue); - common->next_frm->state = VIDEOBUF_ACTIVE; - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->next_frm->boff; - else - addr = videobuf_to_dma_contig(common->next_frm); + list_del(&common->next_frm->list); + common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; + addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); /* Set top and bottom field addresses in VPIF registers */ common->set_addr(addr + common->ytop_off, @@ -505,10 +598,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) } else vid_ch->buf_field = common->fmt.fmt.pix.field; - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = common->fmt.fmt.pix.sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = common->fmt.fmt.pix.sizeimage; hpitch = common->fmt.fmt.pix.bytesperline; vpitch = sizeimage / (hpitch * 2); @@ -660,10 +750,7 @@ static int vpif_check_format(struct channel_obj *ch, hpitch = vpif_params->std_info.width; } - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = pixfmt->sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = pixfmt->sizeimage; vpitch = sizeimage / (hpitch * 2); @@ -736,7 +823,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) vpif_dbg(2, debug, "vpif_mmap\n"); - return videobuf_mmap_mapper(&common->buffer_queue, vma); + return vb2_mmap(&common->buffer_queue, vma); } /** @@ -753,7 +840,7 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait) vpif_dbg(2, debug, "vpif_poll\n"); if (common->started) - return videobuf_poll_stream(filep, &common->buffer_queue, wait); + return vb2_poll(&common->buffer_queue, filep, wait); return 0; } @@ -861,8 +948,8 @@ static int vpif_release(struct file *filep) } common->started = 0; /* Free buffers allocated */ - videobuf_queue_cancel(&common->buffer_queue); - videobuf_mmap_free(&common->buffer_queue); + vb2_queue_release(&common->buffer_queue); + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); } /* Decrement channel usrs counter */ @@ -892,6 +979,7 @@ static int vpif_reqbufs(struct file *file, void *priv, struct channel_obj *ch = fh->channel; struct common_obj *common; u8 index = 0; + struct vb2_queue *q; vpif_dbg(2, debug, "vpif_reqbufs\n"); @@ -917,14 +1005,21 @@ static int vpif_reqbufs(struct file *file, void *priv, if (0 != common->io_usrs) return -EBUSY; - /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, vpif_dev, - &common->irqlock, - reqbuf->type, - common->fmt.fmt.pix.field, - sizeof(struct videobuf_buffer), fh, - &common->lock); + /* Initialize videobuf2 queue as per the buffer type */ + common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); + if (!common->alloc_ctx) { + vpif_err("Failed to get the context\n"); + return -EINVAL; + } + q = &common->buffer_queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = fh; + q->ops = &video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct vpif_cap_buffer); + + vb2_queue_init(q); /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; @@ -935,7 +1030,7 @@ static int vpif_reqbufs(struct file *file, void *priv, INIT_LIST_HEAD(&common->dma_queue); /* Allocate buffers */ - return videobuf_reqbufs(&common->buffer_queue, reqbuf); + return vb2_reqbufs(&common->buffer_queue, reqbuf); } /** @@ -961,7 +1056,7 @@ static int vpif_querybuf(struct file *file, void *priv, return -EINVAL; } - return videobuf_querybuf(&common->buffer_queue, buf); + return vb2_querybuf(&common->buffer_queue, buf); } /** @@ -977,10 +1072,6 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct v4l2_buffer tbuf = *buf; - struct videobuf_buffer *buf1; - unsigned long addr = 0; - unsigned long flags; - int ret = 0; vpif_dbg(2, debug, "vpif_qbuf\n"); @@ -990,76 +1081,11 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) } if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh io not allowed \n"); + vpif_err("fh io not allowed\n"); return -EACCES; } - if (!(list_empty(&common->dma_queue)) || - (common->cur_frm != common->next_frm) || - !common->started || - (common->started && (0 == ch->field_id))) - return videobuf_qbuf(&common->buffer_queue, buf); - - /* bufferqueue is empty store buffer address in VPIF registers */ - mutex_lock(&common->buffer_queue.vb_lock); - buf1 = common->buffer_queue.bufs[tbuf.index]; - - if ((buf1->state == VIDEOBUF_QUEUED) || - (buf1->state == VIDEOBUF_ACTIVE)) { - vpif_err("invalid state\n"); - goto qbuf_exit; - } - - switch (buf1->memory) { - case V4L2_MEMORY_MMAP: - if (buf1->baddr == 0) - goto qbuf_exit; - break; - - case V4L2_MEMORY_USERPTR: - if (tbuf.length < buf1->bsize) - goto qbuf_exit; - - if ((VIDEOBUF_NEEDS_INIT != buf1->state) - && (buf1->baddr != tbuf.m.userptr)) { - vpif_buffer_release(&common->buffer_queue, buf1); - buf1->baddr = tbuf.m.userptr; - } - break; - - default: - goto qbuf_exit; - } - - local_irq_save(flags); - ret = vpif_buffer_prepare(&common->buffer_queue, buf1, - common->buffer_queue.field); - if (ret < 0) { - local_irq_restore(flags); - goto qbuf_exit; - } - - buf1->state = VIDEOBUF_ACTIVE; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = buf1->boff; - else - addr = videobuf_to_dma_contig(buf1); - - common->next_frm = buf1; - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - local_irq_restore(flags); - list_add_tail(&buf1->stream, &common->buffer_queue.stream); - mutex_unlock(&common->buffer_queue.vb_lock); - return 0; - -qbuf_exit: - mutex_unlock(&common->buffer_queue.vb_lock); - return -EINVAL; + return vb2_qbuf(&common->buffer_queue, buf); } /** @@ -1076,8 +1102,8 @@ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) vpif_dbg(2, debug, "vpif_dqbuf\n"); - return videobuf_dqbuf(&common->buffer_queue, buf, - file->f_flags & O_NONBLOCK); + return vb2_dqbuf(&common->buffer_queue, buf, + (file->f_flags & O_NONBLOCK)); } /** @@ -1090,13 +1116,11 @@ static int vpif_streamon(struct file *file, void *priv, enum v4l2_buf_type buftype) { - struct vpif_capture_config *config = vpif_dev->platform_data; struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; struct vpif_params *vpif; - unsigned long addr = 0; int ret = 0; vpif_dbg(2, debug, "vpif_streamon\n"); @@ -1142,95 +1166,13 @@ static int vpif_streamon(struct file *file, void *priv, return ret; } - /* Call videobuf_streamon to start streaming in videobuf */ - ret = videobuf_streamon(&common->buffer_queue); + /* Call vb2_streamon to start streaming in videobuf2 */ + ret = vb2_streamon(&common->buffer_queue, buftype); if (ret) { - vpif_dbg(1, debug, "videobuf_streamon\n"); + vpif_dbg(1, debug, "vb2_streamon\n"); return ret; } - /* If buffer queue is empty, return error */ - if (list_empty(&common->dma_queue)) { - vpif_dbg(1, debug, "buffer queue is empty\n"); - ret = -EIO; - goto exit; - } - - /* Get the next frame from the buffer queue */ - common->cur_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - common->next_frm = common->cur_frm; - - /* Remove buffer from the buffer queue */ - list_del(&common->cur_frm->queue); - /* Mark state of the current frame to active */ - common->cur_frm->state = VIDEOBUF_ACTIVE; - /* Initialize field_id and started member */ - ch->field_id = 0; - common->started = 1; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->cur_frm->boff; - else - addr = videobuf_to_dma_contig(common->cur_frm); - - /* Calculate the offset for Y and C data in the buffer */ - vpif_calculate_offsets(ch); - - if ((vpif->std_info.frm_fmt && - ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && - (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || - (!vpif->std_info.frm_fmt && - (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { - vpif_dbg(1, debug, "conflict in field format and std format\n"); - ret = -EINVAL; - goto exit; - } - - /* configure 1 or 2 channel mode */ - ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set vpif channel mode\n"); - goto exit; - } - - /* Call vpif_set_params function to set the parameters and addresses */ - ret = vpif_set_video_params(vpif, ch->channel_id); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set video params\n"); - goto exit; - } - - common->started = ret; - vpif_config_addr(ch, ret); - - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - /** - * Set interrupt for both the fields in VPIF Register enable channel in - * VPIF register - */ - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { - channel0_intr_assert(); - channel0_intr_enable(1); - enable_channel0(1); - } - if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || - (common->started == 2)) { - channel1_intr_assert(); - channel1_intr_enable(1); - enable_channel1(1); - } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - return ret; - -exit: - videobuf_streamoff(&common->buffer_queue); return ret; } @@ -1285,7 +1227,7 @@ static int vpif_streamoff(struct file *file, void *priv, if (ret && (ret != -ENOIOCTLCMD)) vpif_dbg(1, debug, "stream off failed in subdev\n"); - return videobuf_streamoff(&common->buffer_queue); + return vb2_streamoff(&common->buffer_queue, buftype); } /** diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h index 8095910f02c1..3511510f43ee 100644 --- a/drivers/media/video/davinci/vpif_capture.h +++ b/drivers/media/video/davinci/vpif_capture.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "vpif.h" @@ -60,11 +60,16 @@ struct video_obj { u32 input_idx; }; +struct vpif_cap_buffer { + struct vb2_buffer vb; + struct list_head list; +}; + struct common_obj { /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *cur_frm; + struct vpif_cap_buffer *cur_frm; /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *next_frm; + struct vpif_cap_buffer *next_frm; /* * This field keeps track of type of buffer exchange mechanism * user has selected @@ -73,7 +78,9 @@ struct common_obj { /* Used to store pixel format */ struct v4l2_format fmt; /* Buffer queue used in video-buf */ - struct videobuf_queue buffer_queue; + struct vb2_queue buffer_queue; + /* allocator-specific contexts for each plane */ + struct vb2_alloc_ctx *alloc_ctx; /* Queue of filled frames */ struct list_head dma_queue; /* Used in video-buf */ -- GitLab From 2401dd25c70c07dcec8d7b5497cec4a7e74d2e31 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Thu, 28 Jun 2012 09:28:36 -0300 Subject: [PATCH 4467/5711] [media] davinci: vpif display: migrate driver to videobuf2 This patch migrates VPIF display driver to videobuf2 framework. Signed-off-by: Lad, Prabhakar Signed-off-by: Manjunath Hadli Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/Kconfig | 2 +- drivers/media/video/davinci/vpif_display.c | 576 ++++++++++----------- drivers/media/video/davinci/vpif_display.h | 20 +- 3 files changed, 284 insertions(+), 314 deletions(-) diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig index c45739dd461f..a27e1f5f9055 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/video/davinci/Kconfig @@ -1,7 +1,7 @@ config DISPLAY_DAVINCI_DM646X_EVM tristate "DM646x EVM Video Display" depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF select VIDEO_ADV7343 select VIDEO_THS7303 diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index e0070cd6f41e..787245923a20 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -82,89 +82,38 @@ static struct vpif_config_params config_params = { static struct vpif_device vpif_obj = { {NULL} }; static struct device *vpif_dev; +static void vpif_calculate_offsets(struct channel_obj *ch); +static void vpif_config_addr(struct channel_obj *ch, int muxmode); /* - * vpif_uservirt_to_phys: This function is used to convert user - * space virtual address to physical address. - */ -static u32 vpif_uservirt_to_phys(u32 virtp) -{ - struct mm_struct *mm = current->mm; - unsigned long physp = 0; - struct vm_area_struct *vma; - - vma = find_vma(mm, virtp); - - /* For kernel direct-mapped memory, take the easy way */ - if (virtp >= PAGE_OFFSET) { - physp = virt_to_phys((void *)virtp); - } else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) { - /* this will catch, kernel-allocated, mmaped-to-usermode addr */ - physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); - } else { - /* otherwise, use get_user_pages() for general userland pages */ - int res, nr_pages = 1; - struct page *pages; - down_read(¤t->mm->mmap_sem); - - res = get_user_pages(current, current->mm, - virtp, nr_pages, 1, 0, &pages, NULL); - up_read(¤t->mm->mmap_sem); - - if (res == nr_pages) { - physp = __pa(page_address(&pages[0]) + - (virtp & ~PAGE_MASK)); - } else { - vpif_err("get_user_pages failed\n"); - return 0; - } - } - - return physp; -} - -/* - * buffer_prepare: This is the callback function called from videobuf_qbuf() + * buffer_prepare: This is the callback function called from vb2_qbuf() * function the buffer is prepared and user space virtual address is converted * into physical address */ -static int vpif_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) +static int vpif_buffer_prepare(struct vb2_buffer *vb) { - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_queue *q = vb->vb2_queue; struct common_obj *common; unsigned long addr; common = &fh->channel->common[VPIF_VIDEO_INDEX]; - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = common->width; - vb->height = common->height; - vb->size = vb->width * vb->height; - vb->field = field; - } - vb->state = VIDEOBUF_PREPARED; - - /* if user pointer memory mechanism is used, get the physical - * address of the buffer */ - if (V4L2_MEMORY_USERPTR == common->memory) { - if (!vb->baddr) { - vpif_err("buffer_address is 0\n"); - return -EINVAL; - } - - vb->boff = vpif_uservirt_to_phys(vb->baddr); - if (!ISALIGNED(vb->boff)) + if (vb->state != VB2_BUF_STATE_ACTIVE && + vb->state != VB2_BUF_STATE_PREPARED) { + vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); + if (vb2_plane_vaddr(vb, 0) && + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) goto buf_align_exit; - } - addr = vb->boff; - if (q->streaming && (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { - if (!ISALIGNED(addr + common->ytop_off) || - !ISALIGNED(addr + common->ybtm_off) || - !ISALIGNED(addr + common->ctop_off) || - !ISALIGNED(addr + common->cbtm_off)) - goto buf_align_exit; + addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (q->streaming && + (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { + if (!ISALIGNED(addr + common->ytop_off) || + !ISALIGNED(addr + common->ybtm_off) || + !ISALIGNED(addr + common->ctop_off) || + !ISALIGNED(addr + common->cbtm_off)) + goto buf_align_exit; + } } return 0; @@ -174,104 +123,251 @@ buf_align_exit: } /* - * vpif_buffer_setup: This function allocates memory for the buffers + * vpif_buffer_queue_setup: This function allocates memory for the buffers */ -static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) +static int vpif_buffer_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (V4L2_MEMORY_MMAP != common->memory) - return 0; - - *size = config_params.channel_bufsize[ch->channel_id]; - - /* - * Checking if the buffer size exceeds the available buffer - * ycmux_mode = 0 means 1 channel mode HD and - * ycmux_mode = 1 means 2 channels mode SD - */ - if (ch->vpifparams.std_info.ycmux_mode == 0) { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > (config_params.video_limit[0] - + config_params.video_limit[1])) - (*count)--; - } else { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > + unsigned long size; + + if (V4L2_MEMORY_MMAP == common->memory) { + size = config_params.channel_bufsize[ch->channel_id]; + /* + * Checking if the buffer size exceeds the available buffer + * ycmux_mode = 0 means 1 channel mode HD and + * ycmux_mode = 1 means 2 channels mode SD + */ + if (ch->vpifparams.std_info.ycmux_mode == 0) { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > + (config_params.video_limit[0] + + config_params.video_limit[1])) + (*nbuffers)--; + } else { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > config_params.video_limit[ch->channel_id]) - (*count)--; + (*nbuffers)--; + } + } else { + size = common->fmt.fmt.pix.sizeimage; } - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; + if (*nbuffers < config_params.min_numbuffers) + *nbuffers = config_params.min_numbuffers; + *nplanes = 1; + sizes[0] = size; + alloc_ctxs[0] = common->alloc_ctx; return 0; } /* * vpif_buffer_queue: This function adds the buffer to DMA queue */ -static void vpif_buffer_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buffer_queue(struct vb2_buffer *vb) { - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vpif_disp_buffer *buf = container_of(vb, + struct vpif_disp_buffer, vb); + struct channel_obj *ch = fh->channel; struct common_obj *common; - common = &fh->channel->common[VPIF_VIDEO_INDEX]; + common = &ch->common[VPIF_VIDEO_INDEX]; /* add the buffer to the DMA queue */ - list_add_tail(&vb->queue, &common->dma_queue); - vb->state = VIDEOBUF_QUEUED; + list_add_tail(&buf->list, &common->dma_queue); } /* - * vpif_buffer_release: This function is called from the videobuf layer to + * vpif_buf_cleanup: This function is called from the videobuf2 layer to * free memory allocated to the buffers */ -static void vpif_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buf_cleanup(struct vb2_buffer *vb) { - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vpif_disp_buffer *buf = container_of(vb, + struct vpif_disp_buffer, vb); struct channel_obj *ch = fh->channel; struct common_obj *common; - unsigned int buf_size = 0; + unsigned long flags; common = &ch->common[VPIF_VIDEO_INDEX]; - videobuf_dma_contig_free(q, vb); - vb->state = VIDEOBUF_NEEDS_INIT; + spin_lock_irqsave(&common->irqlock, flags); + if (vb->state == VB2_BUF_STATE_ACTIVE) + list_del_init(&buf->list); + spin_unlock_irqrestore(&common->irqlock, flags); +} + +static void vpif_wait_prepare(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_unlock(&common->lock); +} - if (V4L2_MEMORY_MMAP != common->memory) - return; +static void vpif_wait_finish(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; - buf_size = config_params.channel_bufsize[ch->channel_id]; + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); +} + +static int vpif_buffer_init(struct vb2_buffer *vb) +{ + struct vpif_disp_buffer *buf = container_of(vb, + struct vpif_disp_buffer, vb); + + INIT_LIST_HEAD(&buf->list); + + return 0; } -static struct videobuf_queue_ops video_qops = { - .buf_setup = vpif_buffer_setup, - .buf_prepare = vpif_buffer_prepare, - .buf_queue = vpif_buffer_queue, - .buf_release = vpif_buffer_release, -}; static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; +static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct vpif_display_config *vpif_config_data = + vpif_dev->platform_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_params *vpif = &ch->vpifparams; + unsigned long addr = 0; + int ret; + + /* If buffer queue is empty, return error */ + if (list_empty(&common->dma_queue)) { + vpif_err("buffer queue is empty\n"); + return -EIO; + } + + /* Get the next frame from the buffer queue */ + common->next_frm = common->cur_frm = + list_entry(common->dma_queue.next, + struct vpif_disp_buffer, list); + + list_del(&common->cur_frm->list); + /* Mark state of the current frame to active */ + common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + + /* Initialize field_id and started member */ + ch->field_id = 0; + common->started = 1; + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); + /* Calculate the offset for Y and C data in the buffer */ + vpif_calculate_offsets(ch); + + if ((ch->vpifparams.std_info.frm_fmt && + ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) + && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) + || (!ch->vpifparams.std_info.frm_fmt + && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { + vpif_err("conflict in field format and std format\n"); + return -EINVAL; + } + + /* clock settings */ + ret = + vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, + ch->vpifparams.std_info.hd_sd); + if (ret < 0) { + vpif_err("can't set clock\n"); + return ret; + } + + /* set the parameters and addresses */ + ret = vpif_set_video_params(vpif, ch->channel_id + 2); + if (ret < 0) + return ret; + + common->started = ret; + vpif_config_addr(ch, ret); + common->set_addr((addr + common->ytop_off), + (addr + common->ybtm_off), + (addr + common->ctop_off), + (addr + common->cbtm_off)); + + /* Set interrupt for both the fields in VPIF + Register enable channel in VPIF register */ + if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + channel2_intr_assert(); + channel2_intr_enable(1); + enable_channel2(1); + } + + if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) + || (common->started == 2)) { + channel3_intr_assert(); + channel3_intr_enable(1); + enable_channel3(1); + } + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; + + return 0; +} + +/* abort streaming and wait for last buffer */ +static int vpif_stop_streaming(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + if (!vb2_is_streaming(vq)) + return 0; + + common = &ch->common[VPIF_VIDEO_INDEX]; + + /* release all active buffers */ + while (!list_empty(&common->dma_queue)) { + common->next_frm = list_entry(common->dma_queue.next, + struct vpif_disp_buffer, list); + list_del(&common->next_frm->list); + vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); + } + + return 0; +} + +static struct vb2_ops video_qops = { + .queue_setup = vpif_buffer_queue_setup, + .wait_prepare = vpif_wait_prepare, + .wait_finish = vpif_wait_finish, + .buf_init = vpif_buffer_init, + .buf_prepare = vpif_buffer_prepare, + .start_streaming = vpif_start_streaming, + .stop_streaming = vpif_stop_streaming, + .buf_cleanup = vpif_buf_cleanup, + .buf_queue = vpif_buffer_queue, +}; + static void process_progressive_mode(struct common_obj *common) { unsigned long addr = 0; /* Get the next buffer from buffer queue */ common->next_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); + struct vpif_disp_buffer, list); /* Remove that buffer from the buffer queue */ - list_del(&common->next_frm->queue); + list_del(&common->next_frm->list); /* Mark status of the buffer as active */ - common->next_frm->state = VIDEOBUF_ACTIVE; + common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; /* Set top and bottom field addrs in VPIF registers */ - addr = videobuf_to_dma_contig(common->next_frm); + addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); common->set_addr(addr + common->ytop_off, addr + common->ybtm_off, addr + common->ctop_off, @@ -289,11 +385,10 @@ static void process_interlaced_mode(int fid, struct common_obj *common) /* one frame is displayed If next frame is * available, release cur_frm and move on */ /* Copy frame display time */ - do_gettimeofday(&common->cur_frm->ts); + do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); /* Change status of the cur_frm */ - common->cur_frm->state = VIDEOBUF_DONE; - /* unlock semaphore on cur_frm */ - wake_up_interruptible(&common->cur_frm->done); + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ common->cur_frm = common->next_frm; @@ -344,9 +439,10 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) if (!channel_first_int[i][channel_id]) { /* Mark status of the cur_frm to * done and unlock semaphore on it */ - do_gettimeofday(&common->cur_frm->ts); - common->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&common->cur_frm->done); + do_gettimeofday(&common->cur_frm->vb. + v4l2_buf.timestamp); + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ common->cur_frm = common->next_frm; } @@ -464,10 +560,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) vid_ch->buf_field = common->fmt.fmt.pix.field; } - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = common->fmt.fmt.pix.sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = common->fmt.fmt.pix.sizeimage; hpitch = common->fmt.fmt.pix.bytesperline; vpitch = sizeimage / (hpitch * 2); @@ -544,10 +637,7 @@ static int vpif_check_format(struct channel_obj *ch, if (pixfmt->bytesperline <= 0) goto invalid_pitch_exit; - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = pixfmt->sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = pixfmt->sizeimage; if (vpif_update_resolution(ch)) return -EINVAL; @@ -604,7 +694,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) vpif_dbg(2, debug, "vpif_mmap\n"); - return videobuf_mmap_mapper(&common->buffer_queue, vma); + return vb2_mmap(&common->buffer_queue, vma); } /* @@ -617,7 +707,7 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait) struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; if (common->started) - return videobuf_poll_stream(filep, &common->buffer_queue, wait); + return vb2_poll(&common->buffer_queue, filep, wait); return 0; } @@ -686,9 +776,11 @@ static int vpif_release(struct file *filep) channel3_intr_enable(0); } common->started = 0; + /* Free buffers allocated */ - videobuf_queue_cancel(&common->buffer_queue); - videobuf_mmap_free(&common->buffer_queue); + vb2_queue_release(&common->buffer_queue); + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); + common->numbuffers = config_params.numbuffers[ch->channel_id]; } @@ -827,6 +919,7 @@ static int vpif_reqbufs(struct file *file, void *priv, struct channel_obj *ch = fh->channel; struct common_obj *common; enum v4l2_field field; + struct vb2_queue *q; u8 index = 0; /* This file handle has not initialized the channel, @@ -848,7 +941,6 @@ static int vpif_reqbufs(struct file *file, void *priv, if (common->fmt.type != reqbuf->type || !vpif_dev) return -EINVAL; - if (0 != common->io_usrs) return -EBUSY; @@ -860,14 +952,21 @@ static int vpif_reqbufs(struct file *file, void *priv, } else { field = V4L2_VBI_INTERLACED; } + /* Initialize videobuf2 queue as per the buffer type */ + common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); + if (!common->alloc_ctx) { + vpif_err("Failed to get the context\n"); + return -EINVAL; + } + q = &common->buffer_queue; + q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = fh; + q->ops = &video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct vpif_disp_buffer); - /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, vpif_dev, - &common->irqlock, - reqbuf->type, field, - sizeof(struct videobuf_buffer), fh, - &common->lock); + vb2_queue_init(q); /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; @@ -876,9 +975,8 @@ static int vpif_reqbufs(struct file *file, void *priv, /* Store type of memory requested in channel object */ common->memory = reqbuf->memory; INIT_LIST_HEAD(&common->dma_queue); - /* Allocate buffers */ - return videobuf_reqbufs(&common->buffer_queue, reqbuf); + return vb2_reqbufs(&common->buffer_queue, reqbuf); } static int vpif_querybuf(struct file *file, void *priv, @@ -891,22 +989,25 @@ static int vpif_querybuf(struct file *file, void *priv, if (common->fmt.type != tbuf->type) return -EINVAL; - return videobuf_querybuf(&common->buffer_queue, tbuf); + return vb2_querybuf(&common->buffer_queue, tbuf); } static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { + struct vpif_fh *fh = NULL; + struct channel_obj *ch = NULL; + struct common_obj *common = NULL; - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct v4l2_buffer tbuf = *buf; - struct videobuf_buffer *buf1; - unsigned long addr = 0; - unsigned long flags; - int ret = 0; + if (!buf || !priv) + return -EINVAL; - if (common->fmt.type != tbuf.type) + fh = priv; + ch = fh->channel; + if (!ch) + return -EINVAL; + + common = &(ch->common[VPIF_VIDEO_INDEX]); + if (common->fmt.type != buf->type) return -EINVAL; if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { @@ -914,73 +1015,7 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) return -EACCES; } - if (!(list_empty(&common->dma_queue)) || - (common->cur_frm != common->next_frm) || - !(common->started) || - (common->started && (0 == ch->field_id))) - return videobuf_qbuf(&common->buffer_queue, buf); - - /* bufferqueue is empty store buffer address in VPIF registers */ - mutex_lock(&common->buffer_queue.vb_lock); - buf1 = common->buffer_queue.bufs[tbuf.index]; - if (buf1->memory != tbuf.memory) { - vpif_err("invalid buffer type\n"); - goto qbuf_exit; - } - - if ((buf1->state == VIDEOBUF_QUEUED) || - (buf1->state == VIDEOBUF_ACTIVE)) { - vpif_err("invalid state\n"); - goto qbuf_exit; - } - - switch (buf1->memory) { - case V4L2_MEMORY_MMAP: - if (buf1->baddr == 0) - goto qbuf_exit; - break; - - case V4L2_MEMORY_USERPTR: - if (tbuf.length < buf1->bsize) - goto qbuf_exit; - - if ((VIDEOBUF_NEEDS_INIT != buf1->state) - && (buf1->baddr != tbuf.m.userptr)) { - vpif_buffer_release(&common->buffer_queue, buf1); - buf1->baddr = tbuf.m.userptr; - } - break; - - default: - goto qbuf_exit; - } - - local_irq_save(flags); - ret = vpif_buffer_prepare(&common->buffer_queue, buf1, - common->buffer_queue.field); - if (ret < 0) { - local_irq_restore(flags); - goto qbuf_exit; - } - - buf1->state = VIDEOBUF_ACTIVE; - addr = buf1->boff; - common->next_frm = buf1; - if (tbuf.type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { - common->set_addr((addr + common->ytop_off), - (addr + common->ybtm_off), - (addr + common->ctop_off), - (addr + common->cbtm_off)); - } - - local_irq_restore(flags); - list_add_tail(&buf1->stream, &common->buffer_queue.stream); - mutex_unlock(&common->buffer_queue.vb_lock); - return 0; - -qbuf_exit: - mutex_unlock(&common->buffer_queue.vb_lock); - return -EINVAL; + return vb2_qbuf(&common->buffer_queue, buf); } static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) @@ -1047,7 +1082,7 @@ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - return videobuf_dqbuf(&common->buffer_queue, p, + return vb2_dqbuf(&common->buffer_queue, p, (file->f_flags & O_NONBLOCK)); } @@ -1058,10 +1093,6 @@ static int vpif_streamon(struct file *file, void *priv, struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; - struct vpif_params *vpif = &ch->vpifparams; - struct vpif_display_config *vpif_config_data = - vpif_dev->platform_data; - unsigned long addr = 0; int ret = 0; if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { @@ -1093,82 +1124,13 @@ static int vpif_streamon(struct file *file, void *priv, if (ret < 0) return ret; - /* Call videobuf_streamon to start streaming in videobuf */ - ret = videobuf_streamon(&common->buffer_queue); + /* Call vb2_streamon to start streaming in videobuf2 */ + ret = vb2_streamon(&common->buffer_queue, buftype); if (ret < 0) { - vpif_err("videobuf_streamon\n"); + vpif_err("vb2_streamon\n"); return ret; } - /* If buffer queue is empty, return error */ - if (list_empty(&common->dma_queue)) { - vpif_err("buffer queue is empty\n"); - return -EIO; - } - - /* Get the next frame from the buffer queue */ - common->next_frm = common->cur_frm = - list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - - list_del(&common->cur_frm->queue); - /* Mark state of the current frame to active */ - common->cur_frm->state = VIDEOBUF_ACTIVE; - - /* Initialize field_id and started member */ - ch->field_id = 0; - common->started = 1; - if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - addr = common->cur_frm->boff; - /* Calculate the offset for Y and C data in the buffer */ - vpif_calculate_offsets(ch); - - if ((ch->vpifparams.std_info.frm_fmt && - ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) - && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) - || (!ch->vpifparams.std_info.frm_fmt - && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { - vpif_err("conflict in field format and std format\n"); - return -EINVAL; - } - - /* clock settings */ - ret = - vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, - ch->vpifparams.std_info.hd_sd); - if (ret < 0) { - vpif_err("can't set clock\n"); - return ret; - } - - /* set the parameters and addresses */ - ret = vpif_set_video_params(vpif, ch->channel_id + 2); - if (ret < 0) - return ret; - - common->started = ret; - vpif_config_addr(ch, ret); - common->set_addr((addr + common->ytop_off), - (addr + common->ybtm_off), - (addr + common->ctop_off), - (addr + common->cbtm_off)); - - /* Set interrupt for both the fields in VPIF - Register enable channel in VPIF register */ - if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - channel2_intr_assert(); - channel2_intr_enable(1); - enable_channel2(1); - } - - if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) - || (common->started == 2)) { - channel3_intr_assert(); - channel3_intr_enable(1); - enable_channel3(1); - } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - } return ret; } @@ -1208,7 +1170,7 @@ static int vpif_streamoff(struct file *file, void *priv, } common->started = 0; - return videobuf_streamoff(&common->buffer_queue); + return vb2_streamoff(&common->buffer_queue, buftype); } static int vpif_cropcap(struct file *file, void *priv, diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h index 8a311f10cc3a..8967ffb44058 100644 --- a/drivers/media/video/davinci/vpif_display.h +++ b/drivers/media/video/davinci/vpif_display.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include "vpif.h" @@ -73,21 +73,29 @@ struct vbi_obj { * vbi data */ }; +struct vpif_disp_buffer { + struct vb2_buffer vb; + struct list_head list; +}; + struct common_obj { /* Buffer specific parameters */ u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for * storing frames */ u32 numbuffers; /* number of buffers */ - struct videobuf_buffer *cur_frm; /* Pointer pointing to current - * videobuf_buffer */ - struct videobuf_buffer *next_frm; /* Pointer pointing to next - * videobuf_buffer */ + struct vpif_disp_buffer *cur_frm; /* Pointer pointing to current + * vb2_buffer */ + struct vpif_disp_buffer *next_frm; /* Pointer pointing to next + * vb2_buffer */ enum v4l2_memory memory; /* This field keeps track of * type of buffer exchange * method user has selected */ struct v4l2_format fmt; /* Used to store the format */ - struct videobuf_queue buffer_queue; /* Buffer queue used in + struct vb2_queue buffer_queue; /* Buffer queue used in * video-buf */ + /* allocator-specific contexts for each plane */ + struct vb2_alloc_ctx *alloc_ctx; + struct list_head dma_queue; /* Queue of filled frames */ spinlock_t irqlock; /* Used in video-buf */ -- GitLab From 6964b1036388fee258c48a911ac4a3ff4e55b62d Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 29 Jun 2012 03:20:12 -0300 Subject: [PATCH 4468/5711] [media] davinci: vpif: add support for clipping on output data add hardware clipping support for VPIF output data. This is needed as it is possible that the external encoder might get confused between the FF or 00 which are a part of the data and that of the SAV or EAV codes. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif.h | 30 ++++++++++++++++++++++ drivers/media/video/davinci/vpif_display.c | 10 ++++++++ include/media/davinci/vpif_types.h | 2 ++ 3 files changed, 42 insertions(+) diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h index a4d2141d1ef3..c2ce4d97c279 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/video/davinci/vpif.h @@ -211,6 +211,12 @@ static inline void vpif_clr_bit(u32 reg, u32 bit) #define VPIF_CH3_INT_CTRL_SHIFT (6) #define VPIF_CH_INT_CTRL_SHIFT (6) +#define VPIF_CH2_CLIP_ANC_EN 14 +#define VPIF_CH2_CLIP_ACTIVE_EN 13 + +#define VPIF_CH3_CLIP_ANC_EN 14 +#define VPIF_CH3_CLIP_ACTIVE_EN 13 + /* enabled interrupt on both the fields on vpid_ch0_ctrl register */ #define channel0_intr_assert() (regw((regr(VPIF_CH0_CTRL)|\ (VPIF_INT_BOTH << VPIF_CH0_INT_CTRL_SHIFT)), VPIF_CH0_CTRL)) @@ -515,6 +521,30 @@ static inline void channel3_raw_enable(int enable, u8 index) vpif_clr_bit(VPIF_CH3_CTRL, mask); } +/* function to enable clipping (for both active and blanking regions) on ch 2 */ +static inline void channel2_clipping_enable(int enable) +{ + if (enable) { + vpif_set_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ANC_EN); + vpif_set_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ACTIVE_EN); + } else { + vpif_clr_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ANC_EN); + vpif_clr_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ACTIVE_EN); + } +} + +/* function to enable clipping (for both active and blanking regions) on ch 2 */ +static inline void channel3_clipping_enable(int enable) +{ + if (enable) { + vpif_set_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ANC_EN); + vpif_set_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ACTIVE_EN); + } else { + vpif_clr_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ANC_EN); + vpif_clr_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ACTIVE_EN); + } +} + /* inline function to set buffer addresses in case of Y/C non mux mode */ static inline void ch2_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma, unsigned long btm_strt_luma, diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 787245923a20..c3e2c193dda1 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -306,6 +306,8 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) channel2_intr_assert(); channel2_intr_enable(1); enable_channel2(1); + if (vpif_config_data->ch2_clip_en) + channel2_clipping_enable(1); } if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) @@ -313,6 +315,8 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) channel3_intr_assert(); channel3_intr_enable(1); enable_channel3(1); + if (vpif_config_data->ch3_clip_en) + channel3_clipping_enable(1); } channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; @@ -1140,6 +1144,8 @@ static int vpif_streamoff(struct file *file, void *priv, struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_display_config *vpif_config_data = + vpif_dev->platform_data; if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { vpif_err("buffer type not supported\n"); @@ -1159,11 +1165,15 @@ static int vpif_streamoff(struct file *file, void *priv, if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* disable channel */ if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + if (vpif_config_data->ch2_clip_en) + channel2_clipping_enable(0); enable_channel2(0); channel2_intr_enable(0); } if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || (2 == common->started)) { + if (vpif_config_data->ch3_clip_en) + channel3_clipping_enable(0); enable_channel3(0); channel3_intr_enable(0); } diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h index bd8217c2577c..d8f6ab1943e4 100644 --- a/include/media/davinci/vpif_types.h +++ b/include/media/davinci/vpif_types.h @@ -50,6 +50,8 @@ struct vpif_display_config { const char **output; int output_count; const char *card_name; + bool ch2_clip_en; + bool ch3_clip_en; }; struct vpif_input { -- GitLab From e9530dac31c0c0296242e9209c89f5a580a2d64b Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:50:35 -0300 Subject: [PATCH 4469/5711] [media] davinci: vpif display: Add power management support Implement power management operations - suspend and resume as part of dev_pm_ops for VPIF display driver. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_display.c | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index c3e2c193dda1..e129c98921ad 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -1882,10 +1882,81 @@ static int vpif_remove(struct platform_device *device) return 0; } +#ifdef CONFIG_PM +static int vpif_suspend(struct device *dev) +{ + struct common_obj *common; + struct channel_obj *ch; + int i; + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); + if (atomic_read(&ch->usrs) && common->io_usrs) { + /* Disable channel */ + if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { + enable_channel2(0); + channel2_intr_enable(0); + } + if (ch->channel_id == VPIF_CHANNEL3_VIDEO || + common->started == 2) { + enable_channel3(0); + channel3_intr_enable(0); + } + } + mutex_unlock(&common->lock); + } + + return 0; +} + +static int vpif_resume(struct device *dev) +{ + + struct common_obj *common; + struct channel_obj *ch; + int i; + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); + if (atomic_read(&ch->usrs) && common->io_usrs) { + /* Enable channel */ + if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { + enable_channel2(1); + channel2_intr_enable(1); + } + if (ch->channel_id == VPIF_CHANNEL3_VIDEO || + common->started == 2) { + enable_channel3(1); + channel3_intr_enable(1); + } + } + mutex_unlock(&common->lock); + } + + return 0; +} + +static const struct dev_pm_ops vpif_pm = { + .suspend = vpif_suspend, + .resume = vpif_resume, +}; + +#define vpif_pm_ops (&vpif_pm) +#else +#define vpif_pm_ops NULL +#endif + static __refdata struct platform_driver vpif_driver = { .driver = { .name = "vpif_display", .owner = THIS_MODULE, + .pm = vpif_pm_ops, }, .probe = vpif_probe, .remove = vpif_remove, -- GitLab From 3d5946dcfd4d221126f3f190c5ca4ea41c20f138 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:50:55 -0300 Subject: [PATCH 4470/5711] [media] davinci: vpif capture:Add power management support Implement power management operations - suspend and resume as part of dev_pm_ops for VPIF capture driver. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_capture.c | 73 ++++++++++++++++++---- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 1d4427aa08a5..2727919fe251 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -2312,26 +2312,70 @@ static int vpif_remove(struct platform_device *device) return 0; } +#ifdef CONFIG_PM /** * vpif_suspend: vpif device suspend - * - * TODO: Add suspend code here */ -static int -vpif_suspend(struct device *dev) +static int vpif_suspend(struct device *dev) { - return -1; + + struct common_obj *common; + struct channel_obj *ch; + int i; + + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); + if (ch->usrs && common->io_usrs) { + /* Disable channel */ + if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { + enable_channel0(0); + channel0_intr_enable(0); + } + if (ch->channel_id == VPIF_CHANNEL1_VIDEO || + common->started == 2) { + enable_channel1(0); + channel1_intr_enable(0); + } + } + mutex_unlock(&common->lock); + } + + return 0; } -/** +/* * vpif_resume: vpif device suspend - * - * TODO: Add resume code here */ -static int -vpif_resume(struct device *dev) +static int vpif_resume(struct device *dev) { - return -1; + struct common_obj *common; + struct channel_obj *ch; + int i; + + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); + if (ch->usrs && common->io_usrs) { + /* Disable channel */ + if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { + enable_channel0(1); + channel0_intr_enable(1); + } + if (ch->channel_id == VPIF_CHANNEL1_VIDEO || + common->started == 2) { + enable_channel1(1); + channel1_intr_enable(1); + } + } + mutex_unlock(&common->lock); + } + + return 0; } static const struct dev_pm_ops vpif_dev_pm_ops = { @@ -2339,11 +2383,16 @@ static const struct dev_pm_ops vpif_dev_pm_ops = { .resume = vpif_resume, }; +#define vpif_pm_ops (&vpif_dev_pm_ops) +#else +#define vpif_pm_ops NULL +#endif + static __refdata struct platform_driver vpif_driver = { .driver = { .name = "vpif_capture", .owner = THIS_MODULE, - .pm = &vpif_dev_pm_ops, + .pm = vpif_pm_ops, }, .probe = vpif_probe, .remove = vpif_remove, -- GitLab From 31415d0ef304f26edcba4d3ae106606b83f3c22e Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 13 Apr 2012 04:51:13 -0300 Subject: [PATCH 4471/5711] [media] davinci: vpif: Add suspend/resume callbacks to vpif driver add clock enable and disable in probe and remove functions. Probe will succeed only if the device clock is provided instead of assuming that the clock is always enabled. VPIF clock has to be dealt with during suspend and resume. Implement power management callbacks to VPIF driver to disable/enable clock on suspend/resume respectively. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index 8c4ff14377ad..b3637aff8fee 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include "vpif.h" @@ -40,6 +42,7 @@ static struct resource *res; spinlock_t vpif_lock; void __iomem *vpif_base; +struct clk *vpif_clk; /** * ch_params: video standard configuration parameters for vpif @@ -434,10 +437,19 @@ static int __init vpif_probe(struct platform_device *pdev) goto fail; } + vpif_clk = clk_get(&pdev->dev, "vpif"); + if (IS_ERR(vpif_clk)) { + status = PTR_ERR(vpif_clk); + goto clk_fail; + } + clk_enable(vpif_clk); + spin_lock_init(&vpif_lock); dev_info(&pdev->dev, "vpif probe success\n"); return 0; +clk_fail: + iounmap(vpif_base); fail: release_mem_region(res->start, res_len); return status; @@ -445,15 +457,44 @@ fail: static int __devexit vpif_remove(struct platform_device *pdev) { + if (vpif_clk) { + clk_disable(vpif_clk); + clk_put(vpif_clk); + } + iounmap(vpif_base); release_mem_region(res->start, res_len); return 0; } +#ifdef CONFIG_PM +static int vpif_suspend(struct device *dev) +{ + clk_disable(vpif_clk); + return 0; +} + +static int vpif_resume(struct device *dev) +{ + clk_enable(vpif_clk); + return 0; +} + +static const struct dev_pm_ops vpif_pm = { + .suspend = vpif_suspend, + .resume = vpif_resume, +}; + +#define vpif_pm_ops (&vpif_pm) +#else +#define vpif_pm_ops NULL +#endif + static struct platform_driver vpif_driver = { .driver = { .name = "vpif", .owner = THIS_MODULE, + .pm = vpif_pm_ops, }, .remove = __devexit_p(vpif_remove), .probe = vpif_probe, -- GitLab From 59948db3be76099b14c7103d0f46c5454b173c3a Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 18 Jul 2012 14:20:49 -0400 Subject: [PATCH 4472/5711] NFS: fix pnfs regression with directio reads Commit 1abb50886af "NFS: Create an read_pageio_init() function" did not modify the call in direct.c, preventing direct io from using pnfs. This reintroduces that capability. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 48253372ab1d..69f20c73220e 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -393,7 +393,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, size_t requested_bytes = 0; unsigned long seg; - nfs_pageio_init_read(&desc, dreq->inode, + NFS_PROTO(dreq->inode)->read_pageio_init(&desc, dreq->inode, &nfs_direct_read_completion_ops); get_dreq(dreq); desc.pg_dreq = dreq; -- GitLab From c95908e4c50d218f016e3866f5abf786055df635 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 18 Jul 2012 14:20:50 -0400 Subject: [PATCH 4473/5711] NFS: fix pnfs regression with directio writes Commit 57208fa7e51 "NFS: Create an write_pageio_init() function" did not modify the calls in direct.c, preventing direct io from using pnfs. This reintroduces that capability. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 69f20c73220e..42dce909ec70 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -478,7 +478,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) dreq->count = 0; get_dreq(dreq); - nfs_pageio_init_write(&desc, dreq->inode, FLUSH_STABLE, + NFS_PROTO(dreq->inode)->write_pageio_init(&desc, dreq->inode, FLUSH_STABLE, &nfs_direct_write_completion_ops); desc.pg_dreq = dreq; @@ -782,7 +782,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, size_t requested_bytes = 0; unsigned long seg; - nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, + NFS_PROTO(inode)->write_pageio_init(&desc, inode, FLUSH_COND_STABLE, &nfs_direct_write_completion_ops); desc.pg_dreq = dreq; get_dreq(dreq); -- GitLab From 0fd4652108c596c9f264d9e9e5b20571f00744b2 Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 29 Jun 2012 03:23:37 -0300 Subject: [PATCH 4474/5711] [media] davinci: vpif: add build configuration for vpif drivers add generic build configuration for vpif capture and display drivers as it is common for DM6467/DA850/OMAP-L138. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/Kconfig | 22 +++++++++++++--------- drivers/media/video/davinci/Makefile | 8 ++++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig index a27e1f5f9055..7dc547fa4515 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/video/davinci/Kconfig @@ -1,30 +1,34 @@ -config DISPLAY_DAVINCI_DM646X_EVM - tristate "DM646x EVM Video Display" - depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM +config VIDEO_DAVINCI_VPIF_DISPLAY + tristate "DM646x/DA850/OMAPL138 EVM Video Display" + depends on VIDEO_DEV && (MACH_DAVINCI_DM6467_EVM || MACH_DAVINCI_DA850_EVM) select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF select VIDEO_ADV7343 select VIDEO_THS7303 help - Support for DM6467 based display device. + Enables Davinci VPIF module used for display devices. + This module is common for following DM6467/DA850/OMAPL138 + based display devices. To compile this driver as a module, choose M here: the module will be called vpif_display. -config CAPTURE_DAVINCI_DM646X_EVM - tristate "DM646x EVM Video Capture" - depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM +config VIDEO_DAVINCI_VPIF_CAPTURE + tristate "DM646x/DA850/OMAPL138 EVM Video Capture" + depends on VIDEO_DEV && (MACH_DAVINCI_DM6467_EVM || MACH_DAVINCI_DA850_EVM) select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF help - Support for DM6467 based capture device. + Enables Davinci VPIF module used for captur devices. + This module is common for following DM6467/DA850/OMAPL138 + based capture devices. To compile this driver as a module, choose M here: the module will be called vpif_capture. config VIDEO_DAVINCI_VPIF tristate "DaVinci VPIF Driver" - depends on DISPLAY_DAVINCI_DM646X_EVM + depends on VIDEO_DAVINCI_VPIF_DISPLAY || VIDEO_DAVINCI_VPIF_CAPTURE help Support for DaVinci VPIF Driver. diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile index ae7dafb689ab..74ed92d09257 100644 --- a/drivers/media/video/davinci/Makefile +++ b/drivers/media/video/davinci/Makefile @@ -5,10 +5,10 @@ # VPIF obj-$(CONFIG_VIDEO_DAVINCI_VPIF) += vpif.o -#DM646x EVM Display driver -obj-$(CONFIG_DISPLAY_DAVINCI_DM646X_EVM) += vpif_display.o -#DM646x EVM Capture driver -obj-$(CONFIG_CAPTURE_DAVINCI_DM646X_EVM) += vpif_capture.o +#VPIF Display driver +obj-$(CONFIG_VIDEO_DAVINCI_VPIF_DISPLAY) += vpif_display.o +#VPIF Capture driver +obj-$(CONFIG_VIDEO_DAVINCI_VPIF_CAPTURE) += vpif_capture.o # Capture: DM6446 and DM355 obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o -- GitLab From f44106e2173f08ccb1c9195d85a6c22388b461c1 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 15:49:56 -0400 Subject: [PATCH 4475/5711] nfs: fix fl_type tests in NFSv4 code fl_type is not a bitmap. Reported-by: Al Viro Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 2 +- fs/nfs/nfs4xdr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5e373c30e8d4..6843e0a37de8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4885,7 +4885,7 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) * Don't rely on the VFS having checked the file open mode, * since it won't do this for flock() locks. */ - switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { + switch (request->fl_type) { case F_RDLCK: if (!(filp->f_mode & FMODE_READ)) return -EBADF; diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 610ebccbde5d..6cbd602e26d5 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -1236,7 +1236,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct static inline int nfs4_lock_type(struct file_lock *fl, int block) { - if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) + if (fl->fl_type == F_RDLCK) return block ? NFS4_READW_LT : NFS4_READ_LT; return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; } -- GitLab From 2c026deed9dc1838d1bc0fd2baf484c1ed685d5b Mon Sep 17 00:00:00 2001 From: Manjunath Hadli Date: Fri, 29 Jun 2012 03:24:29 -0300 Subject: [PATCH 4476/5711] [media] davinci: vpif: Enable selection of the ADV7343 and THS7303 The auto selection of pertinent helper chips (VIDEO_HELPER_CHIPS_AUTO) should select the ADV7343 and THS7303 driver, which is used by VPIF display driver. Signed-off-by: Manjunath Hadli Signed-off-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig index 7dc547fa4515..52c5ca68cb3d 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/video/davinci/Kconfig @@ -3,8 +3,8 @@ config VIDEO_DAVINCI_VPIF_DISPLAY depends on VIDEO_DEV && (MACH_DAVINCI_DM6467_EVM || MACH_DAVINCI_DA850_EVM) select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF - select VIDEO_ADV7343 - select VIDEO_THS7303 + select VIDEO_ADV7343 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_THS7303 if VIDEO_HELPER_CHIPS_AUTO help Enables Davinci VPIF module used for display devices. This module is common for following DM6467/DA850/OMAPL138 -- GitLab From 4c1110aabe6283112a2d7c08b16769d0a32be83b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Jul 2012 09:12:45 -0300 Subject: [PATCH 4477/5711] [media] v4l2-dev: forgot to add VIDIOC_DV_TIMINGS_CAP The VIDIOC_DV_TIMINGS_CAP ioctl check wasn't added to determine_valid_ioctls(). This caused this ioctl to always return -ENOTTY. Signed-off-by: Hans Verkuil Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index d13c47fc7202..af70f931727c 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -722,6 +722,7 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings); SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings); SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings); + SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap); /* yes, really vidioc_subscribe_event */ SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event); SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event); -- GitLab From a1acb8f9a088193a66b4d176f5b9a7fb10356ae7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Jul 2012 09:15:06 -0300 Subject: [PATCH 4478/5711] [media] v4l2-ioctl.c: zero the v4l2_dv_timings_cap struct Zero all fields after the first type field. Signed-off-by: Hans Verkuil Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 68d89eadf1ca..3e4db2c1c3d6 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1932,7 +1932,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), - IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, 0), + IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) -- GitLab From 1858c99db41eec26bb33e6b67020a41705e83faf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Jul 2012 10:53:56 -0300 Subject: [PATCH 4479/5711] [media] soc-camera: Don't fail at module init time if no device is present The soc-camera module exports functions that are needed by soc-camera client drivers even when not running in soc-camera mode. Replace the platform_driver_probe() with a platform_driver_register() call to avoid module load failures if no soc-camera device is present. Signed-off-by: Laurent Pinchart Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 0421bf9453b4..e7c6809d1dbe 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -1518,6 +1518,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) } static struct platform_driver __refdata soc_camera_pdrv = { + .probe = soc_camera_pdrv_probe, .remove = __devexit_p(soc_camera_pdrv_remove), .driver = { .name = "soc-camera-pdrv", @@ -1527,7 +1528,7 @@ static struct platform_driver __refdata soc_camera_pdrv = { static int __init soc_camera_init(void) { - return platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe); + return platform_driver_register(&soc_camera_pdrv); } static void __exit soc_camera_exit(void) -- GitLab From 2744782ef15151469ddd1e28c14e4b2c950be6dd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Jul 2012 10:53:57 -0300 Subject: [PATCH 4480/5711] [media] soc-camera: Pass the physical device to the power operation There will be no soc_camera_device instance with a soc-camera device is used with a non soc-camera host, so we won't be able to pass the soc_camera_device fake platform device to board code. Pass the physical device instead. The argument is currently not used by any board file so this is safe. Signed-off-by: Laurent Pinchart Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index e7c6809d1dbe..b03ffecb7438 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -62,7 +62,7 @@ static int soc_camera_power_on(struct soc_camera_device *icd, } if (icl->power) { - ret = icl->power(icd->pdev, 1); + ret = icl->power(icd->control, 1); if (ret < 0) { dev_err(icd->pdev, "Platform failed to power-on the camera.\n"); @@ -78,7 +78,7 @@ static int soc_camera_power_on(struct soc_camera_device *icd, esdpwr: if (icl->power) - icl->power(icd->pdev, 0); + icl->power(icd->control, 0); elinkpwr: regulator_bulk_disable(icl->num_regulators, icl->regulators); @@ -95,7 +95,7 @@ static int soc_camera_power_off(struct soc_camera_device *icd, return ret; if (icl->power) { - ret = icl->power(icd->pdev, 0); + ret = icl->power(icd->control, 0); if (ret < 0) { dev_err(icd->pdev, "Platform failed to power-off the camera.\n"); -- GitLab From f98598391246068359604718cd925020d62bb40e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Jul 2012 10:53:58 -0300 Subject: [PATCH 4481/5711] [media] ov2640: Don't access the device in the g_mbus_fmt operation The g_mbus_fmt operation only needs to return the current mbus frame format and doesn't need to configure the hardware to do so. Fix it to avoid requiring the chip to be powered on when calling the operation. Signed-off-by: Laurent Pinchart Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov2640.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c index 3c2c5d3bcc6b..7c44d1fe3c87 100644 --- a/drivers/media/video/ov2640.c +++ b/drivers/media/video/ov2640.c @@ -837,10 +837,8 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd, if (!priv->win) { u32 width = W_SVGA, height = H_SVGA; - int ret = ov2640_set_params(client, &width, &height, - V4L2_MBUS_FMT_UYVY8_2X8); - if (ret < 0) - return ret; + priv->win = ov2640_select_win(&width, &height); + priv->cfmt_code = V4L2_MBUS_FMT_UYVY8_2X8; } mf->width = priv->win->width; -- GitLab From f2730756ad9649762583cb013f31f636f88bbec0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Jul 2012 10:53:59 -0300 Subject: [PATCH 4482/5711] [media] ov772x: Don't access the device in the g_mbus_fmt operation The g_mbus_fmt operation only needs to return the current mbus frame format and doesn't need to configure the hardware to do so. Fix it to avoid requiring the chip to be powered on when calling the operation. Signed-off-by: Laurent Pinchart Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 74e77d327ed8..6d79b89b8603 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -880,15 +880,11 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); if (!priv->win || !priv->cfmt) { - u32 width = VGA_WIDTH, height = VGA_HEIGHT; - int ret = ov772x_set_params(client, &width, &height, - V4L2_MBUS_FMT_YUYV8_2X8); - if (ret < 0) - return ret; + priv->cfmt = &ov772x_cfmts[0]; + priv->win = ov772x_select_win(VGA_WIDTH, VGA_HEIGHT); } mf->width = priv->win->width; -- GitLab From 7bf6afbb6b528335290e73b74c7f9a8596ef5689 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Jul 2012 10:54:00 -0300 Subject: [PATCH 4483/5711] [media] tw9910: Don't access the device in the g_mbus_fmt operation The g_mbus_fmt operation only needs to return the current mbus frame format and doesn't need to configure the hardware to do so. Fix it to avoid requiring the chip to be powered on when calling the operation. Signed-off-by: Laurent Pinchart Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tw9910.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 8768efb8508a..9f53eacb66e3 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -699,11 +699,9 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd, struct tw9910_priv *priv = to_tw9910(client); if (!priv->scale) { - int ret; - u32 width = 640, height = 480; - ret = tw9910_set_frame(sd, &width, &height); - if (ret < 0) - return ret; + priv->scale = tw9910_select_norm(priv->norm, 640, 480); + if (!priv->scale) + return -EINVAL; } mf->width = priv->scale->width; -- GitLab From d3dd59c232abdd2ab9c5e04e5229dd18f85b551d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2012 10:35:37 -0300 Subject: [PATCH 4484/5711] [media] mem2mem_testdev: convert to the control framework and v4l2_fh Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 234 +++++++++----------------- 1 file changed, 83 insertions(+), 151 deletions(-) diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index f08cf38a496d..a1d5c15eff40 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev" @@ -101,6 +102,8 @@ static struct m2mtest_fmt formats[] = { }, }; +#define NUM_FORMATS ARRAY_SIZE(formats) + /* Per-queue, driver-specific private data */ struct m2mtest_q_data { unsigned int width; @@ -114,50 +117,8 @@ enum { V4L2_M2M_DST = 1, }; -#define V4L2_CID_TRANS_TIME_MSEC V4L2_CID_PRIVATE_BASE -#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_PRIVATE_BASE + 1) - -static struct v4l2_queryctrl m2mtest_ctrls[] = { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Vertical Mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, { - .id = V4L2_CID_TRANS_TIME_MSEC, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Transaction time (msec)", - .minimum = 1, - .maximum = 10000, - .step = 100, - .default_value = 1000, - .flags = 0, - }, { - .id = V4L2_CID_TRANS_NUM_BUFS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Buffers per transaction", - .minimum = 1, - .maximum = MEM2MEM_DEF_NUM_BUFS, - .step = 1, - .default_value = 1, - .flags = 0, - }, -}; - -#define NUM_FORMATS ARRAY_SIZE(formats) +#define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000) +#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001) static struct m2mtest_fmt *find_format(struct v4l2_format *f) { @@ -190,8 +151,11 @@ struct m2mtest_dev { }; struct m2mtest_ctx { + struct v4l2_fh fh; struct m2mtest_dev *dev; + struct v4l2_ctrl_handler hdl; + /* Processed buffers in this transaction */ u8 num_processed; @@ -212,6 +176,11 @@ struct m2mtest_ctx { struct m2mtest_q_data q_data[2]; }; +static inline struct m2mtest_ctx *file2ctx(struct file *file) +{ + return container_of(file->private_data, struct m2mtest_ctx, fh); +} + static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx, enum v4l2_buf_type type) { @@ -227,18 +196,6 @@ static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx, } -static struct v4l2_queryctrl *get_ctrl(int id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) { - if (id == m2mtest_ctrls[i].id) - return &m2mtest_ctrls[i]; - } - - return NULL; -} - static int device_process(struct m2mtest_ctx *ctx, struct vb2_buffer *in_vb, struct vb2_buffer *out_vb) @@ -543,13 +500,13 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) static int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file2ctx(file), f); } static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file2ctx(file), f); } static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) @@ -588,7 +545,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct m2mtest_fmt *fmt; - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { @@ -605,7 +562,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct m2mtest_fmt *fmt; - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { @@ -658,7 +615,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file2ctx(file), f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, @@ -670,13 +627,13 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file2ctx(file), f); } static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); } @@ -684,21 +641,21 @@ static int vidioc_reqbufs(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } @@ -706,7 +663,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); } @@ -714,101 +671,37 @@ static int vidioc_streamon(struct file *file, void *priv, static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct m2mtest_ctx *ctx = priv; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct v4l2_queryctrl *c; - - c = get_ctrl(qc->id); - if (!c) - return -EINVAL; - - *qc = *c; - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct m2mtest_ctx *ctx = priv; - - switch (ctrl->id) { - case V4L2_CID_HFLIP: - ctrl->value = (ctx->mode & MEM2MEM_HFLIP) ? 1 : 0; - break; - - case V4L2_CID_VFLIP: - ctrl->value = (ctx->mode & MEM2MEM_VFLIP) ? 1 : 0; - break; - - case V4L2_CID_TRANS_TIME_MSEC: - ctrl->value = ctx->transtime; - break; - - case V4L2_CID_TRANS_NUM_BUFS: - ctrl->value = ctx->translen; - break; - - default: - v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); - return -EINVAL; - } - - return 0; -} - -static int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl) +static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl) { - struct v4l2_queryctrl *c; - - c = get_ctrl(ctrl->id); - if (!c) - return -EINVAL; - - if (ctrl->value < c->minimum || ctrl->value > c->maximum) { - v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n"); - return -ERANGE; - } - - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct m2mtest_ctx *ctx = priv; - int ret = 0; - - ret = check_ctrl_val(ctx, ctrl); - if (ret != 0) - return ret; + struct m2mtest_ctx *ctx = + container_of(ctrl->handler, struct m2mtest_ctx, hdl); switch (ctrl->id) { case V4L2_CID_HFLIP: - if (ctrl->value) + if (ctrl->val) ctx->mode |= MEM2MEM_HFLIP; else ctx->mode &= ~MEM2MEM_HFLIP; break; case V4L2_CID_VFLIP: - if (ctrl->value) + if (ctrl->val) ctx->mode |= MEM2MEM_VFLIP; else ctx->mode &= ~MEM2MEM_VFLIP; break; case V4L2_CID_TRANS_TIME_MSEC: - ctx->transtime = ctrl->value; + ctx->transtime = ctrl->val; break; case V4L2_CID_TRANS_NUM_BUFS: - ctx->translen = ctrl->value; + ctx->translen = ctrl->val; break; default: @@ -819,6 +712,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return 0; } +static const struct v4l2_ctrl_ops m2mtest_ctrl_ops = { + .s_ctrl = m2mtest_s_ctrl, +}; + static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { .vidioc_querycap = vidioc_querycap, @@ -841,10 +738,6 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, - - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, }; @@ -956,6 +849,28 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds return vb2_queue_init(dst_vq); } +static const struct v4l2_ctrl_config m2mtest_ctrl_trans_time_msec = { + .ops = &m2mtest_ctrl_ops, + .id = V4L2_CID_TRANS_TIME_MSEC, + .name = "Transaction Time (msec)", + .type = V4L2_CTRL_TYPE_INTEGER, + .def = 1001, + .min = 1, + .max = 10001, + .step = 100, +}; + +static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = { + .ops = &m2mtest_ctrl_ops, + .id = V4L2_CID_TRANS_NUM_BUFS, + .name = "Buffers Per Transaction", + .type = V4L2_CTRL_TYPE_INTEGER, + .def = 1, + .min = 1, + .max = MEM2MEM_DEF_NUM_BUFS, + .step = 1, +}; + /* * File operations */ @@ -963,17 +878,29 @@ static int m2mtest_open(struct file *file) { struct m2mtest_dev *dev = video_drvdata(file); struct m2mtest_ctx *ctx = NULL; + struct v4l2_ctrl_handler *hdl; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) return -ENOMEM; - file->private_data = ctx; + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; ctx->dev = dev; - ctx->translen = MEM2MEM_DEF_TRANSLEN; - ctx->transtime = MEM2MEM_DEF_TRANSTIME; - ctx->num_processed = 0; - ctx->mode = 0; + hdl = &ctx->hdl; + v4l2_ctrl_handler_init(hdl, 4); + v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL); + v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL); + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + return err; + } + ctx->fh.ctrl_handler = hdl; + v4l2_ctrl_handler_setup(hdl); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; @@ -983,10 +910,12 @@ static int m2mtest_open(struct file *file) if (IS_ERR(ctx->m2m_ctx)) { int ret = PTR_ERR(ctx->m2m_ctx); + v4l2_ctrl_handler_free(hdl); kfree(ctx); return ret; } + v4l2_fh_add(&ctx->fh); atomic_inc(&dev->num_inst); dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); @@ -997,10 +926,13 @@ static int m2mtest_open(struct file *file) static int m2mtest_release(struct file *file) { struct m2mtest_dev *dev = video_drvdata(file); - struct m2mtest_ctx *ctx = file->private_data; + struct m2mtest_ctx *ctx = file2ctx(file); dprintk(dev, "Releasing instance %p\n", ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->hdl); v4l2_m2m_ctx_release(ctx->m2m_ctx); kfree(ctx); @@ -1012,14 +944,14 @@ static int m2mtest_release(struct file *file) static unsigned int m2mtest_poll(struct file *file, struct poll_table_struct *wait) { - struct m2mtest_ctx *ctx = file->private_data; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); } static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) { - struct m2mtest_ctx *ctx = file->private_data; + struct m2mtest_ctx *ctx = file2ctx(file); return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); } -- GitLab From b0d1499634503ea8947cd8694ada01b263f25ec4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2012 10:46:01 -0300 Subject: [PATCH 4485/5711] [media] mem2mem_testdev: set bus_info and device_caps Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index a1d5c15eff40..fe8c565f35a1 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -427,10 +427,10 @@ static int vidioc_querycap(struct file *file, void *priv, { strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); - cap->bus_info[0] = 0; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT + strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -- GitLab From 08eb85100d114a907e01c76d52d5c95eb4100d20 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2012 10:53:04 -0300 Subject: [PATCH 4486/5711] [media] v4l2-mem2mem: support events in v4l2_m2m_poll v4l2_m2m_poll didn't support events, but that's essential if you want to be able to use control events for example. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-mem2mem.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/video/v4l2-mem2mem.c index 975d0fa938c6..97b48318aee1 100644 --- a/drivers/media/video/v4l2-mem2mem.c +++ b/drivers/media/video/v4l2-mem2mem.c @@ -19,6 +19,9 @@ #include #include +#include +#include +#include MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); MODULE_AUTHOR("Pawel Osciak, "); @@ -407,11 +410,24 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct poll_table_struct *wait) { + struct video_device *vfd = video_devdata(file); + unsigned long req_events = poll_requested_events(wait); struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; unsigned int rc = 0; unsigned long flags; + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { + struct v4l2_fh *fh = file->private_data; + + if (v4l2_event_pending(fh)) + rc = POLLPRI; + else if (req_events & POLLPRI) + poll_wait(file, &fh->wait, wait); + if (!(req_events & (POLLOUT | POLLWRNORM | POLLIN | POLLRDNORM))) + return rc; + } + src_q = v4l2_m2m_get_src_vq(m2m_ctx); dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); @@ -422,7 +438,7 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, */ if ((!src_q->streaming || list_empty(&src_q->queued_list)) && (!dst_q->streaming || list_empty(&dst_q->queued_list))) { - rc = POLLERR; + rc |= POLLERR; goto end; } -- GitLab From 97a3c902e98d772f4310e81d44a27db0d1cf4ddd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2012 10:54:59 -0300 Subject: [PATCH 4487/5711] [media] mem2mem_testdev: add control events support Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index fe8c565f35a1..f7a2a2d635f5 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev" @@ -738,6 +739,8 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; -- GitLab From 47556ffaf212273ca65ce2d3177d4ff2f116db4d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Jul 2012 11:33:22 -0300 Subject: [PATCH 4488/5711] [media] mem2mem_testdev: set default size and fix colorspace Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index f7a2a2d635f5..7fdee8fcf3f7 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -171,6 +171,8 @@ struct m2mtest_ctx { /* Processing mode */ int mode; + enum v4l2_colorspace colorspace; + struct v4l2_m2m_ctx *m2m_ctx; /* Source and destination queue data */ @@ -494,6 +496,7 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) f->fmt.pix.pixelformat = q_data->fmt->fourcc; f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3; f->fmt.pix.sizeimage = q_data->sizeimage; + f->fmt.pix.colorspace = ctx->colorspace; return 0; } @@ -555,6 +558,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat); return -EINVAL; } + f->fmt.pix.colorspace = ctx->colorspace; return vidioc_try_fmt(f, fmt); } @@ -572,6 +576,8 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, f->fmt.pix.pixelformat); return -EINVAL; } + if (!f->fmt.pix.colorspace) + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; return vidioc_try_fmt(f, fmt); } @@ -622,13 +628,17 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { + struct m2mtest_ctx *ctx = file2ctx(file); int ret; ret = vidioc_try_fmt_vid_out(file, priv, f); if (ret) return ret; - return vidioc_s_fmt(file2ctx(file), f); + ret = vidioc_s_fmt(file2ctx(file), f); + if (!ret) + ctx->colorspace = f->fmt.pix.colorspace; + return ret; } static int vidioc_reqbufs(struct file *file, void *priv, @@ -906,7 +916,14 @@ static int m2mtest_open(struct file *file) v4l2_ctrl_handler_setup(hdl); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0]; - ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; + ctx->q_data[V4L2_M2M_SRC].width = 640; + ctx->q_data[V4L2_M2M_SRC].height = 480; + ctx->q_data[V4L2_M2M_SRC].sizeimage = + ctx->q_data[V4L2_M2M_SRC].width * + ctx->q_data[V4L2_M2M_SRC].height * + (ctx->q_data[V4L2_M2M_SRC].fmt->depth >> 3); + ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC]; + ctx->colorspace = V4L2_COLORSPACE_REC709; ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); -- GitLab From 837c7e4256d5285700fe0d500eeb15801b55bb0e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Jul 2012 08:49:25 -0300 Subject: [PATCH 4489/5711] [media] v4l2-dev: G_PARM was incorrectly enabled for all video nodes G_PARM should only be enabled if: - vidioc_g_parm is present - or: it is a video node and vidioc_g_std or tvnorms are set. Without this additional check v4l2-compliance would complain about being able to use g_parm when it didn't expect it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index af70f931727c..1b2f1c52e6c3 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -697,7 +697,8 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd); SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd); SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd); - if (ops->vidioc_g_parm || vdev->vfl_type == VFL_TYPE_GRABBER) + if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && + (ops->vidioc_g_std || vdev->tvnorms))) set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner); -- GitLab From c2d430af08f38a0b3145c3b60381146b8ac88c88 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 27 Jun 2012 09:56:17 -0300 Subject: [PATCH 4490/5711] [media] s5p-fimc: Remove V4L2_FL_LOCK_ALL_FOPS flag This patch adds locking for open(), close(), poll() and mmap() file operations in the driver as a follow up to the changes done in commit 5126f2590bee412e3053de851cb07f531 "v4l2-dev: add flag to have the core lock all file operations". Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 78 ++++++++++++++------- drivers/media/video/s5p-fimc/fimc-m2m.c | 45 +++++++++--- 2 files changed, 87 insertions(+), 36 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 6a34183564d2..8e413dd3c0b0 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -480,48 +480,59 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc); static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); - int ret; + int ret = -EBUSY; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + if (fimc_m2m_active(fimc)) - return -EBUSY; + goto unlock; set_bit(ST_CAPT_BUSY, &fimc->state); ret = pm_runtime_get_sync(&fimc->pdev->dev); if (ret < 0) - return ret; + goto unlock; ret = v4l2_fh_open(file); - if (ret) - return ret; - - if (++fimc->vid_cap.refcnt != 1) - return 0; + if (ret) { + pm_runtime_put(&fimc->pdev->dev); + goto unlock; + } - ret = fimc_pipeline_initialize(&fimc->pipeline, + if (++fimc->vid_cap.refcnt == 1) { + ret = fimc_pipeline_initialize(&fimc->pipeline, &fimc->vid_cap.vfd->entity, true); - if (ret < 0) { - clear_bit(ST_CAPT_BUSY, &fimc->state); - pm_runtime_put_sync(&fimc->pdev->dev); - fimc->vid_cap.refcnt--; - v4l2_fh_release(file); - return ret; - } - ret = fimc_capture_ctrls_create(fimc); - if (!ret && !fimc->vid_cap.user_subdev_api) - ret = fimc_capture_set_default_format(fimc); + if (!ret && !fimc->vid_cap.user_subdev_api) + ret = fimc_capture_set_default_format(fimc); + + if (!ret) + ret = fimc_capture_ctrls_create(fimc); + if (ret < 0) { + clear_bit(ST_CAPT_BUSY, &fimc->state); + pm_runtime_put_sync(&fimc->pdev->dev); + fimc->vid_cap.refcnt--; + v4l2_fh_release(file); + } + } +unlock: + mutex_unlock(&fimc->lock); return ret; } static int fimc_capture_close(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); + int ret; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + if (--fimc->vid_cap.refcnt == 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); fimc_stop_capture(fimc, false); @@ -535,22 +546,40 @@ static int fimc_capture_close(struct file *file) vb2_queue_release(&fimc->vid_cap.vbq); fimc_ctrls_delete(fimc->vid_cap.ctx); } - return v4l2_fh_release(file); + + ret = v4l2_fh_release(file); + + mutex_unlock(&fimc->lock); + return ret; } static unsigned int fimc_capture_poll(struct file *file, struct poll_table_struct *wait) { struct fimc_dev *fimc = video_drvdata(file); + int ret; - return vb2_poll(&fimc->vid_cap.vbq, file, wait); + if (mutex_lock_interruptible(&fimc->lock)) + return POLL_ERR; + + ret = vb2_poll(&fimc->vid_cap.vbq, file, wait); + mutex_unlock(&fimc->lock); + + return ret; } static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) { struct fimc_dev *fimc = video_drvdata(file); + int ret; + + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; - return vb2_mmap(&fimc->vid_cap.vbq, vma); + ret = vb2_mmap(&fimc->vid_cap.vbq, vma); + mutex_unlock(&fimc->lock); + + return ret; } static const struct v4l2_file_operations fimc_capture_fops = { @@ -1589,10 +1618,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, vfd->minor = -1; vfd->release = video_device_release; vfd->lock = &fimc->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); + video_set_drvdata(vfd, fimc); vid_cap = &fimc->vid_cap; diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/video/s5p-fimc/fimc-m2m.c index 4c58e0570962..41eda2e27488 100644 --- a/drivers/media/video/s5p-fimc/fimc-m2m.c +++ b/drivers/media/video/s5p-fimc/fimc-m2m.c @@ -642,21 +642,25 @@ static int fimc_m2m_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx; - int ret; + int ret = -EBUSY; dbg("pid: %d, state: 0x%lx, refcnt: %d", task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; /* * Return if the corresponding video capture node * is already opened. */ if (fimc->vid_cap.refcnt > 0) - return -EBUSY; + goto unlock; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); - if (!ctx) - return -ENOMEM; + if (!ctx) { + ret = -ENOMEM; + goto unlock; + } v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); ctx->fimc_dev = fimc; @@ -687,6 +691,8 @@ static int fimc_m2m_open(struct file *file) if (fimc->m2m.refcnt++ == 0) set_bit(ST_M2M_RUN, &fimc->state); + + mutex_unlock(&fimc->lock); return 0; error_c: @@ -695,6 +701,8 @@ error_fh: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); kfree(ctx); +unlock: + mutex_unlock(&fimc->lock); return ret; } @@ -706,6 +714,9 @@ static int fimc_m2m_release(struct file *file) dbg("pid: %d, state: 0x%lx, refcnt= %d", task_pid_nr(current), fimc->state, fimc->m2m.refcnt); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + v4l2_m2m_ctx_release(ctx->m2m_ctx); fimc_ctrls_delete(ctx); v4l2_fh_del(&ctx->fh); @@ -714,6 +725,8 @@ static int fimc_m2m_release(struct file *file) if (--fimc->m2m.refcnt <= 0) clear_bit(ST_M2M_RUN, &fimc->state); kfree(ctx); + + mutex_unlock(&fimc->lock); return 0; } @@ -721,16 +734,32 @@ static unsigned int fimc_m2m_poll(struct file *file, struct poll_table_struct *wait) { struct fimc_ctx *ctx = fh_to_ctx(file->private_data); + struct fimc_dev *fimc = ctx->fimc_dev; + int ret; - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + + ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_unlock(&fimc->lock); + + return ret; } static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) { struct fimc_ctx *ctx = fh_to_ctx(file->private_data); + struct fimc_dev *fimc = ctx->fimc_dev; + int ret; + + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&fimc->lock); + + return ret; } static const struct v4l2_file_operations fimc_m2m_fops = { @@ -772,10 +801,6 @@ int fimc_register_m2m_device(struct fimc_dev *fimc, vfd->minor = -1; vfd->release = video_device_release; vfd->lock = &fimc->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); video_set_drvdata(vfd, fimc); -- GitLab From a516d08fa6afb703ba508ccc55656d037c5b9e2e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 12 Jun 2012 03:12:26 -0300 Subject: [PATCH 4491/5711] [media] s5p-fimc: Replace custom err() macro with v4l2_err() macro Replace custom err() macro with v4l2_err() macro. [s.nawrocki: added missing end-of-line at the log print] Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.h | 3 --- drivers/media/video/s5p-fimc/fimc-reg.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 95b27ae5cf27..808ccc621846 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -27,9 +27,6 @@ #include #include -#define err(fmt, args...) \ - printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args) - #define dbg(fmt, args...) \ pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 1fc4ce8446f5..74a2fba2c543 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -683,8 +683,8 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; break; default: - v4l2_err(fimc->vid_cap.vfd, - "Not supported camera pixel format: %d", + v4l2_err(vid_cap->vfd, + "Not supported camera pixel format: %#x\n", vid_cap->mf.code); return -EINVAL; } @@ -699,7 +699,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, } else if (cam->bus_type == FIMC_LCD_WB) { cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; } else { - err("invalid camera bus type selected\n"); + v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n"); return -EINVAL; } writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); -- GitLab From 31ce54f6aeb70ecf1b8e758236955dfad1b1e398 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 24 Jul 2012 12:06:26 -0300 Subject: [PATCH 4492/5711] [media] s5p-fimc: Use switch statement for better readability Use switch statement rather than multiple 'else if'. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-reg.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 74a2fba2c543..0e3eb9ce4f98 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -667,7 +667,8 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB | FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG); - if (cam->bus_type == FIMC_MIPI_CSI2) { + switch (cam->bus_type) { + case FIMC_MIPI_CSI2: cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI; if (cam->mux_id == 0) @@ -691,14 +692,15 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, tmp |= (csis_data_alignment == 32) << 8; writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT); - - } else if (cam->bus_type == FIMC_ITU_601 || - cam->bus_type == FIMC_ITU_656) { + break; + case FIMC_ITU_601...FIMC_ITU_656: if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A; - } else if (cam->bus_type == FIMC_LCD_WB) { + break; + case FIMC_LCD_WB: cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; - } else { + break; + default: v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n"); return -EINVAL; } -- GitLab From 6126b912c84240692e26c1b820a7097610eddf34 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 24 Jul 2012 12:12:07 -0300 Subject: [PATCH 4493/5711] [media] m5mols: Correct reported ISO values The V4L2_CID_ISO_SENSITIVITY control menu values should be standard ISO values multiplied by 1000. Multiply all menu items by 1000 so ISO is properly reported as 50...3200 range. This applies to kernels 3.5+. Cc: stable@vger.kernel.org Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols_controls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index 392a028730e2..fdbc205a2969 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c @@ -527,8 +527,8 @@ static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { /* Supported manual ISO values */ static const s64 iso_qmenu[] = { - /* AE_ISO: 0x01...0x07 */ - 50, 100, 200, 400, 800, 1600, 3200 + /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */ + 50000, 100000, 200000, 400000, 800000, 1600000, 3200000 }; /* Supported Exposure Bias values, -2.0EV...+2.0EV */ -- GitLab From f0476a83d61a8004eb535a0b65721ca405421fe8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 26 Jul 2012 09:30:00 -0300 Subject: [PATCH 4494/5711] [media] V4L: Add capability flags for memory-to-memory devices This patch adds new V4L2_CAP_VIDEO_M2M and V4L2_CAP_VIDEO_M2M_MPLANE capability flags that are intended to be used for memory-to-memory (M2M) devices, instead of ORed V4L2_CAP_VIDEO_CAPTURE and V4L2_CAP_VIDEO_OUTPUT. V4L2_CAP_VIDEO_M2M flag is added at the drivers, CAPTURE and OUTPUT capability flags are left untouched and will be removed in future, after a transition period required for existing applications to be adapted to check only for V4L2_CAP_VIDEO_M2M. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Kamil Debski Acked-by: Andrzej Pietrasiewicz Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 9 +++++++++ Documentation/DocBook/media/v4l/vidioc-querycap.xml | 13 +++++++++++++ drivers/media/video/mem2mem_testdev.c | 3 +-- drivers/media/video/mx2_emmaprp.c | 10 +++++++--- drivers/media/video/s5p-fimc/fimc-m2m.c | 7 ++++++- drivers/media/video/s5p-g2d/g2d.c | 9 +++++++-- drivers/media/video/s5p-jpeg/jpeg-core.c | 10 +++++++--- drivers/media/video/s5p-mfc/s5p_mfc_dec.c | 10 ++++++++-- drivers/media/video/s5p-mfc/s5p_mfc_enc.c | 11 ++++++++--- include/linux/videodev2.h | 4 ++++ 10 files changed, 70 insertions(+), 16 deletions(-) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 97b895151bb0..4559a6f8a5f0 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2471,6 +2471,15 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 3.6 + + + Added V4L2_CAP_VIDEO_M2M and V4L2_CAP_VIDEO_M2M_MPLANE capabilities. + + +
+
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml index 4643505cd4ca..f33dd746b66b 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml @@ -191,6 +191,19 @@ linkend="output">Video Output interface. multi-planar API through the Video Output interface. + + V4L2_CAP_VIDEO_M2M + 0x00004000 + The device supports the single-planar API through the + Video Memory-To-Memory interface. + + + V4L2_CAP_VIDEO_M2M_MPLANE + 0x00008000 + The device supports the + multi-planar API through the + Video Memory-To-Memory interface. + V4L2_CAP_VIDEO_OVERLAY 0x00000004 diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 7fdee8fcf3f7..7efe9ad7acc7 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -431,8 +431,7 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; + cap->capabilities = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c index 0bd5815de369..5f8a6f5b98f9 100644 --- a/drivers/media/video/mx2_emmaprp.c +++ b/drivers/media/video/mx2_emmaprp.c @@ -396,9 +396,13 @@ static int vidioc_querycap(struct file *file, void *priv, { strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; - + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; return 0; } diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/video/s5p-fimc/fimc-m2m.c index 41eda2e27488..c587011d80ef 100644 --- a/drivers/media/video/s5p-fimc/fimc-m2m.c +++ b/drivers/media/video/s5p-fimc/fimc-m2m.c @@ -259,7 +259,12 @@ static int fimc_m2m_querycap(struct file *file, void *fh, strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1); strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING | + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE; return 0; diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c index 7c98ee7377ee..7c2200435206 100644 --- a/drivers/media/video/s5p-g2d/g2d.c +++ b/drivers/media/video/s5p-g2d/g2d.c @@ -290,8 +290,13 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; return 0; } diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c index 95f23024b17d..813b801238d1 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.c +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c @@ -489,9 +489,13 @@ static int s5p_jpeg_querycap(struct file *file, void *priv, sizeof(cap->card)); } cap->bus_info[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING | - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OUTPUT; + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M | + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT; return 0; } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c index feea867f318c..c5d567f87d77 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c @@ -220,8 +220,14 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | - V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE; return 0; } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c index 158b78989b89..aa1c244cf66e 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c @@ -779,9 +779,14 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE - | V4L2_CAP_VIDEO_OUTPUT_MPLANE - | V4L2_CAP_STREAMING; + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE; return 0; } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 5d78910f926c..4cf766e6f120 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -274,6 +274,10 @@ struct v4l2_capability { #define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 /* Is a video output device that supports multiplanar formats */ #define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 +/* Is a video mem-to-mem device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_M2M_MPLANE 0x00004000 +/* Is a video mem-to-mem device */ +#define V4L2_CAP_VIDEO_M2M 0x00008000 #define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ #define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ -- GitLab From a1367f1b260d29e9b9fb20d8e2f39f1e74fa6c3b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 26 Jul 2012 09:30:50 -0300 Subject: [PATCH 4495/5711] [media] Feature removal: using capture and output capabilities for m2m devices Identifying a memory-to-memory video device through an ORed output and capture capability flags is not reliable. Schedule this for removal. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b99803066b7b..dbefb17b821d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -576,3 +576,17 @@ Why: The regular V4L2 selections and the subdev selection API originally any instabilities in the user space interface. After few cycles these backward compatibility definitions will be removed. Who: Sylwester Nawrocki + +---------------------------- + +What: Using V4L2_CAP_VIDEO_CAPTURE and V4L2_CAP_VIDEO_OUTPUT flags + to indicate a V4L2 memory-to-memory device capability +When: 3.8 +Why: New drivers should use new V4L2_CAP_VIDEO_M2M capability flag + to indicate a V4L2 video memory-to-memory (M2M) device and + applications can now identify a M2M video device by checking + for V4L2_CAP_VIDEO_M2M, with VIDIOC_QUERYCAP ioctl. Using ORed + V4L2_CAP_VIDEO_CAPTURE and V4L2_CAP_VIDEO_OUTPUT flags for M2M + devices is ambiguous and may lead, for example, to identifying + a M2M device as a video capture or output device. +Who: Sylwester Nawrocki -- GitLab From 938e05bf131334804e08ec4fcd381edfd2d699f6 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 31 Jul 2012 00:36:16 +0200 Subject: [PATCH 4496/5711] regulator: Fix an s5m8767 build failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to a merge conflict we are getting this: drivers/regulator/s5m8767.c: In function ‘s5m8767_pmic_probe’: drivers/regulator/s5m8767.c:575:2: error: implicit declaration of function ‘s5m_reg_write’ [-Werror=implicit-function-declaration] This is fixed by fully converting this driver to the new s5m API. Cc: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/regulator/s5m8767.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 5a0d18a7aa2a..abe64a32aedf 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -572,21 +572,21 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) pdata->buck2_init + buck_voltage_val2.step); - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, pdata->buck3_init, pdata->buck3_init + buck_voltage_val2.step); - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, pdata->buck4_init, pdata->buck4_init + buck_voltage_val2.step); - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); for (i = 0; i < 8; i++) { if (s5m8767->buck2_gpiodvs) { -- GitLab From 159e0561e322dd8008fff59e36efff8d2bdd0b0e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 29 May 2012 13:57:58 +0800 Subject: [PATCH 4497/5711] pnfsblock: bail out partial page IO Current block layout driver read/write code assumes page aligned IO in many places. Add a checker to validate the assumption. Otherwise there would be data corruption like when application does open(O_WRONLY) and page unaliged write. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/blocklayout.c | 39 +++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 7ae8a608956f..dd392ed5f2e2 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -228,6 +228,14 @@ bl_end_par_io_read(void *data, int unused) schedule_work(&rdata->task.u.tk_work); } +static bool +bl_check_alignment(u64 offset, u32 len, unsigned long blkmask) +{ + if ((offset & blkmask) || (len & blkmask)) + return false; + return true; +} + static enum pnfs_try_status bl_read_pagelist(struct nfs_read_data *rdata) { @@ -244,6 +252,9 @@ bl_read_pagelist(struct nfs_read_data *rdata) dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__, rdata->pages.npages, f_offset, (unsigned int)rdata->args.count); + if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK)) + goto use_mds; + par = alloc_parallel(rdata); if (!par) goto use_mds; @@ -552,7 +563,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct bio *bio = NULL; struct pnfs_block_extent *be = NULL, *cow_read = NULL; sector_t isect, last_isect = 0, extent_length = 0; - struct parallel_io *par; + struct parallel_io *par = NULL; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; struct page **pages = wdata->args.pages; @@ -563,6 +574,10 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); + /* Check for alignment first */ + if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK)) + goto out_mds; + /* At this point, wdata->pages is a (sequential) list of nfs_pages. * We want to write each, and if there is an error set pnfs_error * to have it redone using nfs. @@ -996,14 +1011,32 @@ bl_clear_layoutdriver(struct nfs_server *server) return 0; } +static void +bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK)) + nfs_pageio_reset_read_mds(pgio); + else + pnfs_generic_pg_init_read(pgio, req); +} + +static void +bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK)) + nfs_pageio_reset_write_mds(pgio); + else + pnfs_generic_pg_init_write(pgio, req); +} + static const struct nfs_pageio_ops bl_pg_read_ops = { - .pg_init = pnfs_generic_pg_init_read, + .pg_init = bl_pg_init_read, .pg_test = pnfs_generic_pg_test, .pg_doio = pnfs_generic_pg_readpages, }; static const struct nfs_pageio_ops bl_pg_write_ops = { - .pg_init = pnfs_generic_pg_init_write, + .pg_init = bl_pg_init_write, .pg_test = pnfs_generic_pg_test, .pg_doio = pnfs_generic_pg_writepages, }; -- GitLab From 6fe31039d40d73968fe75c543d6b623bcbf5ecb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:46 -0300 Subject: [PATCH 4498/5711] [media] saa7164: Remove useless struct i2c_algo_bit_data The field 'struct i2c_algo_bit_data i2c_algo' is wrongly confused with struct i2c_algorithm. Moreover, i2c_algo field is not used since i2c is registered using i2c_add_adpater() and not i2c_bit_add_bus(). Therefore, it's safe to remove it. Tested by compilation only. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7164/saa7164-i2c.c | 4 ---- drivers/media/video/saa7164/saa7164.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c index 26148f76cba2..1c54ab47fb62 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/video/saa7164/saa7164-i2c.c @@ -109,9 +109,6 @@ int saa7164_i2c_register(struct saa7164_i2c *bus) memcpy(&bus->i2c_adap, &saa7164_i2c_adap_template, sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_algo, &saa7164_i2c_algo_template, - sizeof(bus->i2c_algo)); - memcpy(&bus->i2c_client, &saa7164_i2c_client_template, sizeof(bus->i2c_client)); @@ -120,7 +117,6 @@ int saa7164_i2c_register(struct saa7164_i2c *bus) strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); - bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, bus); i2c_add_adapter(&bus->i2c_adap); diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index 8d120e3baf70..fc1f854cbe89 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h @@ -251,7 +251,6 @@ struct saa7164_i2c { /* I2C I/O */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; }; -- GitLab From c410d09bf3c8019d50d5ce7f1eb26e1b747835f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:47 -0300 Subject: [PATCH 4499/5711] [media] cx23885: Remove useless struct i2c_algo_bit_data The field 'struct i2c_algo_bit_data i2c_algo' is wrongly confused with struct i2c_algorithm. Moreover, i2c_algo field is not used since i2c is registered using i2c_add_adpater() and not i2c_bit_add_bus(). Therefore, it's safe to remove it. Tested by compilation only. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-i2c.c | 3 --- drivers/media/video/cx23885/cx23885.h | 2 -- drivers/media/video/saa7164/saa7164.h | 1 - 3 files changed, 6 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index be1e21d8295c..615c71fb4668 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -318,8 +318,6 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template, sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_algo, &cx23885_i2c_algo_template, - sizeof(bus->i2c_algo)); memcpy(&bus->i2c_client, &cx23885_i2c_client_template, sizeof(bus->i2c_client)); @@ -328,7 +326,6 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); - bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 13c37ec07ae7..5d560c747e09 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -247,7 +246,6 @@ struct cx23885_i2c { /* i2c i/o */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index fc1f854cbe89..35219b9b0fbc 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h @@ -46,7 +46,6 @@ #include #include -#include #include #include #include -- GitLab From 272863540371cd86a7f05d6fef7db7868ea79a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:48 -0300 Subject: [PATCH 4500/5711] [media] cx231xx: Remove useless struct i2c_algo_bit_data The field 'struct i2c_algo_bit_data i2c_algo' is wrongly confused with struct i2c_algorithm. Moreover, i2c_algo field is not used since i2c is registered using i2c_add_adpater() and not i2c_bit_add_bus(). Therefore, it's safe to remove it. Tested by compilation only. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-i2c.c | 2 -- drivers/media/video/cx231xx/cx231xx.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c index 925f3a04e53c..7c0ed1bc49c2 100644 --- a/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -500,7 +500,6 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) BUG_ON(!dev->cx231xx_send_usb_command); memcpy(&bus->i2c_adap, &cx231xx_adap_template, sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_algo, &cx231xx_algo, sizeof(bus->i2c_algo)); memcpy(&bus->i2c_client, &cx231xx_client_template, sizeof(bus->i2c_client)); @@ -508,7 +507,6 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); - bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index e17447554a0d..a89d020de948 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -481,7 +480,6 @@ struct cx231xx_i2c { /* i2c i/o */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; -- GitLab From b26f453963a5275a5c408beee7663d5bc096620f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:49 -0300 Subject: [PATCH 4501/5711] [media] cx25821: Remove useless struct i2c_algo_bit_data The field 'struct i2c_algo_bit_data i2c_algo' is wrongly confused with struct i2c_algorithm. Moreover, i2c_algo field is not used since i2c is registered using i2c_add_adpater() and not i2c_bit_add_bus(). Therefore, it's safe to remove it. Tested by compilation only. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25821/cx25821-i2c.c | 3 --- drivers/media/video/cx25821/cx25821.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c index 6311180f430c..0a44b4ea1cec 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/video/cx25821/cx25821-i2c.c @@ -307,8 +307,6 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template, sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template, - sizeof(bus->i2c_algo)); memcpy(&bus->i2c_client, &cx25821_i2c_client_template, sizeof(bus->i2c_client)); @@ -316,7 +314,6 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); - bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index b9aa801b00a7..ed525016f165 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -213,7 +212,6 @@ struct cx25821_i2c { /* i2c i/o */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; -- GitLab From 5a6fa3fe9a465d1c5e1e6bf8a4ad1ca9063131a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:50 -0300 Subject: [PATCH 4502/5711] [media] saa7164: Remove unused saa7164_call_i2c_clients() This function has no users, so it's safe to remove it. Tested by compilation only. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7164/saa7164-i2c.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c index 1c54ab47fb62..d8d7baa4c636 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/video/saa7164/saa7164-i2c.c @@ -69,15 +69,6 @@ err: return retval; } -void saa7164_call_i2c_clients(struct saa7164_i2c *bus, unsigned int cmd, - void *arg) -{ - if (bus->i2c_rc != 0) - return; - - i2c_clients_command(&bus->i2c_adap, cmd, arg); -} - static u32 saa7164_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C; -- GitLab From ddebe8cdd6c8d5f937c6587d2636079a5d096247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:51 -0300 Subject: [PATCH 4503/5711] [media] saa7164: Replace struct memcpy with struct assignment Copying structs by assignment is type safe. Plus, is shorter and easier to read. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7164/saa7164-i2c.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c index d8d7baa4c636..4f7e3b42263f 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/video/saa7164/saa7164-i2c.c @@ -97,11 +97,8 @@ int saa7164_i2c_register(struct saa7164_i2c *bus) dprintk(DBGLVL_I2C, "%s(bus = %d)\n", __func__, bus->nr); - memcpy(&bus->i2c_adap, &saa7164_i2c_adap_template, - sizeof(bus->i2c_adap)); - - memcpy(&bus->i2c_client, &saa7164_i2c_client_template, - sizeof(bus->i2c_client)); + bus->i2c_adap = saa7164_i2c_adap_template; + bus->i2c_client = saa7164_i2c_client_template; bus->i2c_adap.dev.parent = &dev->pci->dev; -- GitLab From 630081e99072f94788011badd6d12707fa3ab410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:52 -0300 Subject: [PATCH 4504/5711] [media] cx23885: Replace struct memcpy with struct assignment Copying structs by assignment is type safe. Plus, is shorter and easier to read. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-i2c.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 615c71fb4668..4887314339cb 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -316,11 +316,8 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); - memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template, - sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_client, &cx23885_i2c_client_template, - sizeof(bus->i2c_client)); - + bus->i2c_adap = cx23885_i2c_adap_template; + bus->i2c_client = cx23885_i2c_client_template; bus->i2c_adap.dev.parent = &dev->pci->dev; strlcpy(bus->i2c_adap.name, bus->dev->name, -- GitLab From 23ba641a08a5cf1194cfba8480ecfab8b6623110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:53 -0300 Subject: [PATCH 4505/5711] [media] cx231xx: Replace struct memcpy with struct assignment Copying structs by assignment is type safe. Plus, is shorter and easier to read. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-i2c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c index 7c0ed1bc49c2..781feed406f7 100644 --- a/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -499,10 +499,8 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) BUG_ON(!dev->cx231xx_send_usb_command); - memcpy(&bus->i2c_adap, &cx231xx_adap_template, sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_client, &cx231xx_client_template, - sizeof(bus->i2c_client)); - + bus->i2c_adap = cx231xx_adap_template; + bus->i2c_client = cx231xx_client_template; bus->i2c_adap.dev.parent = &dev->udev->dev; strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); -- GitLab From c21813e9746b174e4f426aa0fcb1a69c361a71b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 27 Jun 2012 12:52:54 -0300 Subject: [PATCH 4506/5711] [media] cx25821: Replace struct memcpy with struct assignment Copying structs by assignment is type safe. Plus, is shorter and easier to read. Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25821/cx25821-i2c.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c index 0a44b4ea1cec..9844549764c9 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/video/cx25821/cx25821-i2c.c @@ -305,11 +305,8 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); - memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template, - sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_client, &cx25821_i2c_client_template, - sizeof(bus->i2c_client)); - + bus->i2c_adap = cx25821_i2c_adap_template; + bus->i2c_client = cx25821_i2c_client_template; bus->i2c_adap.dev.parent = &dev->pci->dev; strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); -- GitLab From 6f45b1b9f7e16453c72ad3a8f7bdbc4c8d716839 Mon Sep 17 00:00:00 2001 From: Dror Cohen Date: Tue, 10 Jul 2012 05:43:22 -0300 Subject: [PATCH 4507/5711] [media] media/video: vpif: fixed vpfe->vpif typo Signed-off-by: Dror Cohen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_capture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 2727919fe251..266025e5d81d 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -810,7 +810,7 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode) } /** - * vpfe_mmap : It is used to map kernel space buffers into user spaces + * vpif_mmap : It is used to map kernel space buffers into user spaces * @filep: file pointer * @vma: ptr to vm_area_struct */ @@ -919,7 +919,7 @@ static int vpif_open(struct file *filep) * vpif_release : function to clean up file close * @filep: file pointer * - * This function deletes buffer queue, frees the buffers and the vpfe file + * This function deletes buffer queue, frees the buffers and the vpif file * handle */ static int vpif_release(struct file *filep) -- GitLab From c082266f60b749fa55074ee4c8b2ea99e4b59320 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 10 Jul 2012 07:14:46 -0300 Subject: [PATCH 4508/5711] [media] V4L: Use NULL pointer instead of plain integer in v4l2-ctrls.c file Fixes the following sparse warning: drivers/media/video/v4l2-ctrls.c:2123:43: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ctrls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index babfb13dc7f2..b6a2ee71e5c3 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -2121,7 +2121,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, /* First zero the helper field in the master control references */ for (i = 0; i < cs->count; i++) - helpers[i].mref->helper = 0; + helpers[i].mref->helper = NULL; for (i = 0, h = helpers; i < cs->count; i++, h++) { struct v4l2_ctrl_ref *mref = h->mref; -- GitLab From 506026c3ec270e18402f0c9d33fee37482c23861 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 15:51:55 -0400 Subject: [PATCH 4509/5711] sunrpc: clarify comments on rpc_make_runnable rpc_make_runnable is not generally called with the queue lock held, unless it's waking up a task that has been sitting on a waitqueue. This is safe when the task has not entered the FSM yet, but the comments don't really spell this out. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- net/sunrpc/sched.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 994cfea2bad6..ada1e2c33aa4 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -300,8 +300,9 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); /* * Make an RPC task runnable. * - * Note: If the task is ASYNC, this must be called with - * the spinlock held to protect the wait queue operation. + * Note: If the task is ASYNC, and is being made runnable after sitting on an + * rpc_wait_queue, this must be called with the queue spinlock held to protect + * the wait queue operation. */ static void rpc_make_runnable(struct rpc_task *task) { -- GitLab From 5cf02d09b50b1ee1c2d536c9cf64af5a7d433f56 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 13:58:51 -0400 Subject: [PATCH 4510/5711] nfs: skip commit in releasepage if we're freeing memory for fs-related reasons We've had some reports of a deadlock where rpciod ends up with a stack trace like this: PID: 2507 TASK: ffff88103691ab40 CPU: 14 COMMAND: "rpciod/14" #0 [ffff8810343bf2f0] schedule at ffffffff814dabd9 #1 [ffff8810343bf3b8] nfs_wait_bit_killable at ffffffffa038fc04 [nfs] #2 [ffff8810343bf3c8] __wait_on_bit at ffffffff814dbc2f #3 [ffff8810343bf418] out_of_line_wait_on_bit at ffffffff814dbcd8 #4 [ffff8810343bf488] nfs_commit_inode at ffffffffa039e0c1 [nfs] #5 [ffff8810343bf4f8] nfs_release_page at ffffffffa038bef6 [nfs] #6 [ffff8810343bf528] try_to_release_page at ffffffff8110c670 #7 [ffff8810343bf538] shrink_page_list.clone.0 at ffffffff81126271 #8 [ffff8810343bf668] shrink_inactive_list at ffffffff81126638 #9 [ffff8810343bf818] shrink_zone at ffffffff8112788f #10 [ffff8810343bf8c8] do_try_to_free_pages at ffffffff81127b1e #11 [ffff8810343bf958] try_to_free_pages at ffffffff8112812f #12 [ffff8810343bfa08] __alloc_pages_nodemask at ffffffff8111fdad #13 [ffff8810343bfb28] kmem_getpages at ffffffff81159942 #14 [ffff8810343bfb58] fallback_alloc at ffffffff8115a55a #15 [ffff8810343bfbd8] ____cache_alloc_node at ffffffff8115a2d9 #16 [ffff8810343bfc38] kmem_cache_alloc at ffffffff8115b09b #17 [ffff8810343bfc78] sk_prot_alloc at ffffffff81411808 #18 [ffff8810343bfcb8] sk_alloc at ffffffff8141197c #19 [ffff8810343bfce8] inet_create at ffffffff81483ba6 #20 [ffff8810343bfd38] __sock_create at ffffffff8140b4a7 #21 [ffff8810343bfd98] xs_create_sock at ffffffffa01f649b [sunrpc] #22 [ffff8810343bfdd8] xs_tcp_setup_socket at ffffffffa01f6965 [sunrpc] #23 [ffff8810343bfe38] worker_thread at ffffffff810887d0 #24 [ffff8810343bfee8] kthread at ffffffff8108dd96 #25 [ffff8810343bff48] kernel_thread at ffffffff8100c1ca rpciod is trying to allocate memory for a new socket to talk to the server. The VM ends up calling ->releasepage to get more memory, and it tries to do a blocking commit. That commit can't succeed however without a connected socket, so we deadlock. Fix this by setting PF_FSTRANS on the workqueue task prior to doing the socket allocation, and having nfs_release_page check for that flag when deciding whether to do a commit call. Also, set PF_FSTRANS unconditionally in rpc_async_schedule since that function can also do allocations sometimes. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org --- fs/nfs/file.c | 7 +++++-- net/sunrpc/sched.c | 2 ++ net/sunrpc/xprtrdma/transport.c | 3 ++- net/sunrpc/xprtsock.c | 10 ++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 70d124a61b98..1b3925426929 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -447,8 +447,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp) dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); - /* Only do I/O if gfp is a superset of GFP_KERNEL */ - if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { + /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not + * doing this memory reclaim for a fs-related allocation. + */ + if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL && + !(current->flags & PF_FSTRANS)) { int how = FLUSH_SYNC; /* Don't let kswapd deadlock waiting for OOM RPC calls */ diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ada1e2c33aa4..1f19aa15f89b 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -791,7 +791,9 @@ void rpc_execute(struct rpc_task *task) static void rpc_async_schedule(struct work_struct *work) { + current->flags |= PF_FSTRANS; __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); + current->flags &= ~PF_FSTRANS; } /** diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index b446e100286f..06cdbff79e4a 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -200,6 +200,7 @@ xprt_rdma_connect_worker(struct work_struct *work) int rc = 0; if (!xprt->shutdown) { + current->flags |= PF_FSTRANS; xprt_clear_connected(xprt); dprintk("RPC: %s: %sconnect\n", __func__, @@ -212,10 +213,10 @@ xprt_rdma_connect_worker(struct work_struct *work) out: xprt_wake_pending_tasks(xprt, rc); - out_clear: dprintk("RPC: %s: exit\n", __func__); xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; } /* diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 890b03f8d877..b88c6bf657ba 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1895,6 +1895,8 @@ static void xs_local_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); status = __sock_create(xprt->xprt_net, AF_LOCAL, SOCK_STREAM, 0, &sock, 1); @@ -1928,6 +1930,7 @@ static void xs_local_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) @@ -1970,6 +1973,8 @@ static void xs_udp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + /* Start by resetting any existing state */ xs_reset_transport(transport); sock = xs_create_sock(xprt, transport, @@ -1988,6 +1993,7 @@ static void xs_udp_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /* @@ -2113,6 +2119,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + if (!sock) { clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); sock = xs_create_sock(xprt, transport, @@ -2162,6 +2170,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) case -EINPROGRESS: case -EALREADY: xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; return; case -EINVAL: /* Happens, for instance, if the user specified a link @@ -2174,6 +2183,7 @@ out_eagain: out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /** -- GitLab From a427b9ec4eda8cd6e641ea24541d30b641fc3140 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 25 Jul 2012 16:53:36 +0100 Subject: [PATCH 4511/5711] NFS: Fix a number of bugs in the idmapper Fix a number of bugs in the NFS idmapper code: (1) Only registered key types can be passed to the core keys code, so register the legacy idmapper key type. This is a requirement because the unregister function cleans up keys belonging to that key type so that there aren't dangling pointers to the module left behind - including the key->type pointer. (2) Rename the legacy key type. You can't have two key types with the same name, and (1) would otherwise require that. (3) complete_request_key() must be called in the error path of nfs_idmap_legacy_upcall(). (4) There is one idmap struct for each nfs_client struct. This means that idmap->idmap_key_cons is shared without the use of a lock. This is a problem because key_instantiate_and_link() - as called indirectly by idmap_pipe_downcall() - releases anyone waiting for the key to be instantiated. What happens is that idmap_pipe_downcall() running in the rpc.idmapd thread, releases the NFS filesystem in whatever thread that is running in to continue. This may then make another idmapper call, overwriting idmap_key_cons before idmap_pipe_downcall() gets the chance to call complete_request_key(). I *think* that reading idmap_key_cons only once, before key_instantiate_and_link() is called, and then caching the result in a variable is sufficient. Bug (4) is the cause of: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD 0 Oops: 0010 [#1] SMP CPU 1 Modules linked in: ppdev parport_pc lp parport ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack nfs fscache xt_CHECKSUM auth_rpcgss iptable_mangle nfs_acl bridge stp llc lockd be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi snd_hda_codec_realtek snd_usb_audio snd_hda_intel snd_hda_codec snd_seq snd_pcm snd_hwdep snd_usbmidi_lib snd_rawmidi snd_timer uvcvideo videobuf2_core videodev media videobuf2_vmalloc snd_seq_device videobuf2_memops e1000e vhost_net iTCO_wdt joydev coretemp snd soundcore macvtap macvlan i2c_i801 snd_page_alloc tun iTCO_vendor_support microcode kvm_intel kvm sunrpc hid_logitech_dj usb_storage i915 drm_kms_helper drm i2c_algo_bit i2c_core video [last unloaded: scsi_wait_scan] Pid: 1229, comm: rpc.idmapd Not tainted 3.4.2-1.fc16.x86_64 #1 Gateway DX4710-UB801A/G33M05G1 RIP: 0010:[<0000000000000000>] [< (null)>] (null) RSP: 0018:ffff8801a3645d40 EFLAGS: 00010246 RAX: ffff880077707e30 RBX: ffff880077707f50 RCX: ffff8801a18ccd80 RDX: 0000000000000006 RSI: ffff8801a3645e75 RDI: ffff880077707f50 RBP: ffff8801a3645d88 R08: ffff8801a430f9c0 R09: ffff8801a3645db0 R10: 000000000000000a R11: 0000000000000246 R12: ffff8801a18ccd80 R13: ffff8801a3645e75 R14: ffff8801a430f9c0 R15: 0000000000000006 FS: 00007fb6fb51a700(0000) GS:ffff8801afc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000001a49b0000 CR4: 00000000000027e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process rpc.idmapd (pid: 1229, threadinfo ffff8801a3644000, task ffff8801a3bf9710) Stack: ffffffff81260878 ffff8801a3645db0 ffff8801a3645db0 ffff880077707a90 ffff880077707f50 ffff8801a18ccd80 0000000000000006 ffff8801a3645e75 ffff8801a430f9c0 ffff8801a3645dd8 ffffffff81260983 ffff8801a3645de8 Call Trace: [] ? __key_instantiate_and_link+0x58/0x100 [] key_instantiate_and_link+0x63/0xa0 [] idmap_pipe_downcall+0x1cb/0x1e0 [nfs] [] rpc_pipe_write+0x67/0x90 [sunrpc] [] vfs_write+0xb3/0x180 [] sys_write+0x4a/0x90 [] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [< (null)>] (null) RSP CR2: 0000000000000000 Signed-off-by: David Howells Reviewed-by: Steve Dickson Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 3.4] --- fs/nfs/idmap.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 864c51e4b400..1b5058b4043b 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -205,12 +205,18 @@ static int nfs_idmap_init_keyring(void) if (ret < 0) goto failed_put_key; + ret = register_key_type(&key_type_id_resolver_legacy); + if (ret < 0) + goto failed_reg_legacy; + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; +failed_reg_legacy: + unregister_key_type(&key_type_id_resolver); failed_put_key: key_put(keyring); failed_put_cred: @@ -222,6 +228,7 @@ static void nfs_idmap_quit_keyring(void) { key_revoke(id_resolver_cache->thread_keyring); unregister_key_type(&key_type_id_resolver); + unregister_key_type(&key_type_id_resolver_legacy); put_cred(id_resolver_cache); } @@ -385,7 +392,7 @@ static const struct rpc_pipe_ops idmap_upcall_ops = { }; static struct key_type key_type_id_resolver_legacy = { - .name = "id_resolver", + .name = "id_legacy", .instantiate = user_instantiate, .match = user_match, .revoke = user_revoke, @@ -674,6 +681,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, if (ret < 0) goto out2; + BUG_ON(idmap->idmap_key_cons != NULL); idmap->idmap_key_cons = cons; ret = rpc_queue_upcall(idmap->idmap_pipe, msg); @@ -687,8 +695,7 @@ out2: out1: kfree(msg); out0: - key_revoke(cons->key); - key_revoke(cons->authkey); + complete_request_key(cons, ret); return ret; } @@ -722,11 +729,18 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); struct idmap *idmap = (struct idmap *)rpci->private; - struct key_construction *cons = idmap->idmap_key_cons; + struct key_construction *cons; struct idmap_msg im; size_t namelen_in; int ret; + /* If instantiation is successful, anyone waiting for key construction + * will have been woken up and someone else may now have used + * idmap_key_cons - so after this point we may no longer touch it. + */ + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + if (mlen != sizeof(im)) { ret = -ENOSPC; goto out; @@ -739,7 +753,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { ret = mlen; - complete_request_key(idmap->idmap_key_cons, -ENOKEY); + complete_request_key(cons, -ENOKEY); goto out_incomplete; } @@ -756,7 +770,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } out: - complete_request_key(idmap->idmap_key_cons, ret); + complete_request_key(cons, ret); out_incomplete: return ret; } -- GitLab From ab7017a3a0a64b953e091619c30413b3721d925d Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:16 -0400 Subject: [PATCH 4512/5711] NFS: Add version registering framework This patch adds in the code to track multiple versions of the NFS protocol. I created default structures for v2, v3 and v4 so that each version can continue to work while I convert them into kernel modules. I also removed the const parameter from the rpc_version array so that I can change it at runtime. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Makefile | 4 +- fs/nfs/client.c | 147 +++++++++++++++++++++++++++++--------- fs/nfs/inode.c | 9 +-- fs/nfs/internal.h | 10 +-- fs/nfs/nfs.h | 72 +++++++++++++++++++ fs/nfs/nfs2super.c | 25 +++++++ fs/nfs/nfs3super.c | 25 +++++++ fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4client.c | 4 +- fs/nfs/nfs4super.c | 14 +++- fs/nfs/super.c | 32 ++++++--- include/linux/nfs_fs_sb.h | 1 + 12 files changed, 283 insertions(+), 61 deletions(-) create mode 100644 fs/nfs/nfs.h create mode 100644 fs/nfs/nfs2super.c create mode 100644 fs/nfs/nfs3super.c diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 0b96c2038346..66dd3075e5db 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -9,8 +9,8 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ write.o namespace.o mount_clnt.o \ dns_resolve.o cache_lib.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o -nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o -nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o +nfs-$(CONFIG_NFS_V2) += nfs2super.o proc.o nfs2xdr.o +nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs4super.o nfs4file.o delegation.o idmap.o \ diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 65afa382c5e3..462de24482b4 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -51,25 +51,23 @@ #include "internal.h" #include "fscache.h" #include "pnfs.h" +#include "nfs.h" #include "netns.h" #define NFSDBG_FACILITY NFSDBG_CLIENT static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); +static DEFINE_SPINLOCK(nfs_version_lock); +static DEFINE_MUTEX(nfs_version_mutex); +static LIST_HEAD(nfs_versions); /* * RPC cruft for NFS */ static const struct rpc_version *nfs_version[5] = { -#ifdef CONFIG_NFS_V2 - [2] = &nfs_version2, -#endif -#ifdef CONFIG_NFS_V3 - [3] = &nfs_version3, -#endif -#ifdef CONFIG_NFS_V4 - [4] = &nfs_version4, -#endif + [2] = NULL, + [3] = NULL, + [4] = NULL, }; const struct rpc_program nfs_program = { @@ -101,6 +99,93 @@ const struct rpc_program nfsacl_program = { }; #endif /* CONFIG_NFS_V3_ACL */ +static struct nfs_subversion *find_nfs_version(unsigned int version) +{ + struct nfs_subversion *nfs; + spin_lock(&nfs_version_lock); + + list_for_each_entry(nfs, &nfs_versions, list) { + if (nfs->rpc_ops->version == version) { + spin_unlock(&nfs_version_lock); + return nfs; + } + }; + + spin_unlock(&nfs_version_lock); + return ERR_PTR(-EPROTONOSUPPORT);; +} + +struct nfs_subversion *get_nfs_version(unsigned int version) +{ + struct nfs_subversion *nfs = find_nfs_version(version); + + if (IS_ERR(nfs)) { + mutex_lock(&nfs_version_mutex); + request_module("nfs%d", version); + nfs = find_nfs_version(version); + mutex_unlock(&nfs_version_mutex); + } + + if (!IS_ERR(nfs)) + try_module_get(nfs->owner); + return nfs; +} + +void put_nfs_version(struct nfs_subversion *nfs) +{ + module_put(nfs->owner); +} + +void register_nfs_version(struct nfs_subversion *nfs) +{ + spin_lock(&nfs_version_lock); + + list_add(&nfs->list, &nfs_versions); + nfs_version[nfs->rpc_ops->version] = nfs->rpc_vers; + + spin_unlock(&nfs_version_lock); +} +EXPORT_SYMBOL_GPL(register_nfs_version); + +void unregister_nfs_version(struct nfs_subversion *nfs) +{ + spin_lock(&nfs_version_lock); + + nfs_version[nfs->rpc_ops->version] = NULL; + list_del(&nfs->list); + + spin_unlock(&nfs_version_lock); +} +EXPORT_SYMBOL_GPL(unregister_nfs_version); + +/* + * Preload all configured NFS versions during module init. + * This function should be edited after each protocol is converted, + * and eventually removed. + */ +int __init nfs_register_versions(void) +{ + int err = init_nfs_v2(); + if (err) + return err; + + err = init_nfs_v3(); + if (err) + return err; + + return init_nfs_v4(); +} + +/* + * Remove each pre-loaded NFS version + */ +void nfs_unregister_versions(void) +{ + exit_nfs_v2(); + exit_nfs_v3(); + exit_nfs_v4(); +} + /* * Allocate a shared client record * @@ -116,7 +201,10 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) goto error_0; - clp->rpc_ops = cl_init->rpc_ops; + clp->cl_nfs_mod = cl_init->nfs_mod; + try_module_get(clp->cl_nfs_mod->owner); + + clp->rpc_ops = clp->cl_nfs_mod->rpc_ops; atomic_set(&clp->cl_count, 1); clp->cl_cons_state = NFS_CS_INITING; @@ -145,6 +233,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) return clp; error_cleanup: + put_nfs_version(clp->cl_nfs_mod); kfree(clp); error_0: return ERR_PTR(err); @@ -205,6 +294,7 @@ void nfs_free_client(struct nfs_client *clp) put_rpccred(clp->cl_machine_cred); put_net(clp->cl_net); + put_nfs_version(clp->cl_nfs_mod); kfree(clp->cl_hostname); kfree(clp); @@ -362,7 +452,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat continue; /* Different NFS versions cannot share the same nfs_client */ - if (clp->rpc_ops != data->rpc_ops) + if (clp->rpc_ops != data->nfs_mod->rpc_ops) continue; if (clp->cl_proto != data->proto) @@ -431,9 +521,10 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, { struct nfs_client *clp, *new = NULL; struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id); + const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops; dprintk("--> nfs_get_client(%s,v%u)\n", - cl_init->hostname ?: "", cl_init->rpc_ops->version); + cl_init->hostname ?: "", rpc_ops->version); /* see if the client already exists */ do { @@ -450,14 +541,13 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, list_add(&new->cl_share_link, &nn->nfs_client_list); spin_unlock(&nn->nfs_client_lock); new->cl_flags = cl_init->init_flags; - return cl_init->rpc_ops->init_client(new, - timeparms, ip_addr, - authflavour); + return rpc_ops->init_client(new, timeparms, ip_addr, + authflavour); } spin_unlock(&nn->nfs_client_lock); - new = cl_init->rpc_ops->alloc_client(cl_init); + new = rpc_ops->alloc_client(cl_init); } while (!IS_ERR(new)); dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", @@ -714,13 +804,14 @@ error: * Create a version 2 or 3 client */ static int nfs_init_server(struct nfs_server *server, - const struct nfs_parsed_mount_data *data) + const struct nfs_parsed_mount_data *data, + struct nfs_subversion *nfs_mod) { struct nfs_client_initdata cl_init = { .hostname = data->nfs_server.hostname, .addr = (const struct sockaddr *)&data->nfs_server.address, .addrlen = data->nfs_server.addrlen, - .rpc_ops = NULL, + .nfs_mod = nfs_mod, .proto = data->nfs_server.protocol, .net = data->net, }; @@ -730,21 +821,6 @@ static int nfs_init_server(struct nfs_server *server, dprintk("--> nfs_init_server()\n"); - switch (data->version) { -#ifdef CONFIG_NFS_V2 - case 2: - cl_init.rpc_ops = &nfs_v2_clientops; - break; -#endif -#ifdef CONFIG_NFS_V3 - case 3: - cl_init.rpc_ops = &nfs_v3_clientops; - break; -#endif - default: - return -EPROTONOSUPPORT; - } - nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, data->timeo, data->retrans); if (data->flags & NFS_MOUNT_NORESVPORT) @@ -1033,7 +1109,8 @@ void nfs_free_server(struct nfs_server *server) * - keyed on server and FSID */ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, - struct nfs_fh *mntfh) + struct nfs_fh *mntfh, + struct nfs_subversion *nfs_mod) { struct nfs_server *server; struct nfs_fattr *fattr; @@ -1049,7 +1126,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, goto error; /* Get a client representation */ - error = nfs_init_server(server, data); + error = nfs_init_server(server, data, nfs_mod); if (error < 0) goto error; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 35f7e4bc680e..e8877c82582d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -50,6 +50,7 @@ #include "fscache.h" #include "dns_resolve.h" #include "pnfs.h" +#include "nfs.h" #include "netns.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -1671,21 +1672,17 @@ static int __init init_nfs_fs(void) rpc_proc_register(&init_net, &nfs_rpcstat); #endif -#ifdef CONFIG_NFS_V4 - err = init_nfs_v4(); + err = nfs_register_versions(); if (err) goto out1; -#endif if ((err = register_nfs_fs()) != 0) goto out0; return 0; out0: -#ifdef CONFIG_NFS_V4 - exit_nfs_v4(); + nfs_unregister_versions(); out1: -#endif #ifdef CONFIG_PROC_FS rpc_proc_unregister(&init_net, "nfs"); #endif diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index cfafd13b6fe9..ac936476b3bc 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -90,7 +90,7 @@ struct nfs_client_initdata { const char *hostname; const struct sockaddr *addr; size_t addrlen; - const struct nfs_rpc_ops *rpc_ops; + struct nfs_subversion *nfs_mod; int proto; u32 minorversion; struct net *net; @@ -189,7 +189,8 @@ nfs4_find_client_sessionid(struct net *, const struct sockaddr *, struct nfs4_sessionid *); extern struct nfs_server *nfs_create_server( const struct nfs_parsed_mount_data *, - struct nfs_fh *); + struct nfs_fh *, + struct nfs_subversion *); extern struct nfs_server *nfs4_create_server( const struct nfs_parsed_mount_data *, struct nfs_fh *); @@ -321,6 +322,7 @@ void nfs_zap_acl_cache(struct inode *inode); extern int nfs_wait_bit_killable(void *word); /* super.c */ +extern struct file_system_type nfs_fs_type; extern struct file_system_type nfs_xdev_fs_type; #ifdef CONFIG_NFS_V4 extern struct file_system_type nfs4_xdev_fs_type; @@ -329,8 +331,8 @@ extern struct file_system_type nfs4_referral_fs_type; void nfs_initialise_sb(struct super_block *); int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); -struct dentry *nfs_fs_mount_common(struct file_system_type *, struct nfs_server *, - int, const char *, struct nfs_mount_info *); +struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *, + struct nfs_mount_info *, struct nfs_subversion *); struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *); struct dentry * nfs_xdev_mount_common(struct file_system_type *, int, const char *, struct nfs_mount_info *); diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h new file mode 100644 index 000000000000..ac10b9e6c920 --- /dev/null +++ b/fs/nfs/nfs.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012 Netapp, Inc. All rights reserved. + * + * Function and structures exported by the NFS module + * for use by NFS version-specific modules. + */ +#ifndef __LINUX_INTERNAL_NFS_H +#define __LINUX_INTERNAL_NFS_H + +#include +#include +#include + +struct nfs_subversion { + struct module *owner; /* THIS_MODULE pointer */ + struct file_system_type *nfs_fs; /* NFS filesystem type */ + const struct rpc_version *rpc_vers; /* NFS version information */ + const struct nfs_rpc_ops *rpc_ops; /* NFS operations */ + struct list_head list; /* List of NFS versions */ +}; + +int nfs_register_versions(void); +void nfs_unregister_versions(void); + +#ifdef CONFIG_NFS_V2 +int init_nfs_v2(void); +void exit_nfs_v2(void); +#else /* CONFIG_NFS_V2 */ +static inline int __init init_nfs_v2(void) +{ + return 0; +} + +static inline void exit_nfs_v2(void) +{ +} +#endif /* CONFIG_NFS_V2 */ + +#ifdef CONFIG_NFS_V3 +int init_nfs_v3(void); +void exit_nfs_v3(void); +#else /* CONFIG_NFS_V3 */ +static inline int __init init_nfs_v3(void) +{ + return 0; +} + +static inline void exit_nfs_v3(void) +{ +} +#endif /* CONFIG_NFS_V3 */ + +#ifdef CONFIG_NFS_V4 +int init_nfs_v4(void); +void exit_nfs_v4(void); +#else /* CONFIG_NFS_V4 */ +static inline int __init init_nfs_v4(void) +{ + return 0; +} + +static inline void exit_nfs_v4(void) +{ +} +#endif /* CONFIG_NFS_V4 */ + +struct nfs_subversion *get_nfs_version(unsigned int); +void put_nfs_version(struct nfs_subversion *); +void register_nfs_version(struct nfs_subversion *); +void unregister_nfs_version(struct nfs_subversion *); + +#endif /* __LINUX_INTERNAL_NFS_H */ diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c new file mode 100644 index 000000000000..cef06d42334a --- /dev/null +++ b/fs/nfs/nfs2super.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 Netapp, Inc. All rights reserved. + */ +#include +#include +#include "internal.h" +#include "nfs.h" + +static struct nfs_subversion nfs_v2 = { + .owner = THIS_MODULE, + .nfs_fs = &nfs_fs_type, + .rpc_vers = &nfs_version2, + .rpc_ops = &nfs_v2_clientops, +}; + +int __init init_nfs_v2(void) +{ + register_nfs_version(&nfs_v2); + return 0; +} + +void exit_nfs_v2(void) +{ + unregister_nfs_version(&nfs_v2); +} diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c new file mode 100644 index 000000000000..f815cf359d97 --- /dev/null +++ b/fs/nfs/nfs3super.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 Netapp, Inc. All rights reserved. + */ +#include +#include +#include "internal.h" +#include "nfs.h" + +static struct nfs_subversion nfs_v3 = { + .owner = THIS_MODULE, + .nfs_fs = &nfs_fs_type, + .rpc_vers = &nfs_version3, + .rpc_ops = &nfs_v3_clientops, +}; + +int __init init_nfs_v3(void) +{ + register_nfs_version(&nfs_v3); + return 0; +} + +void exit_nfs_v3(void) +{ + unregister_nfs_version(&nfs_v3); +} diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 5511690de8a5..99c2e7e4d3ea 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -366,6 +366,7 @@ extern const nfs4_stateid zero_stateid; /* nfs4super.c */ struct nfs_mount_info; +extern struct nfs_subversion nfs_v4; struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *); int init_nfs_v4(void); void exit_nfs_v4(void); diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 1c3f13c8e472..769e798b3959 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -357,7 +357,7 @@ static int nfs4_set_client(struct nfs_server *server, .hostname = hostname, .addr = addr, .addrlen = addrlen, - .rpc_ops = &nfs_v4_clientops, + .nfs_mod = &nfs_v4, .proto = proto, .minorversion = minorversion, .net = net, @@ -411,7 +411,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, struct nfs_client_initdata cl_init = { .addr = ds_addr, .addrlen = ds_addrlen, - .rpc_ops = &nfs_v4_clientops, + .nfs_mod = &nfs_v4, .proto = ds_proto, .minorversion = mds_clp->cl_minorversion, .net = mds_clp->cl_net, diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 59264fb335c8..1f3401902c2f 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -8,6 +8,7 @@ #include #include "internal.h" #include "nfs4_fs.h" +#include "nfs.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -75,6 +76,13 @@ static const struct super_operations nfs4_sops = { .remount_fs = nfs_remount, }; +struct nfs_subversion nfs_v4 = { + .owner = THIS_MODULE, + .nfs_fs = &nfs4_fs_type, + .rpc_vers = &nfs_version4, + .rpc_ops = &nfs_v4_clientops, +}; + /* * Set up an NFS4 superblock */ @@ -113,7 +121,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, goto out; } - mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); + mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4); out: return mntroot; @@ -293,7 +301,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, goto out; } - mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info); + mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4); out: nfs_free_fhandle(mount_info.mntfh); return mntroot; @@ -343,6 +351,7 @@ int __init init_nfs_v4(void) if (err < 0) goto out2; + register_nfs_version(&nfs_v4); return 0; out2: nfs4_unregister_sysctl(); @@ -354,6 +363,7 @@ out: void exit_nfs_v4(void) { + unregister_nfs_version(&nfs_v4); unregister_filesystem(&nfs4_fs_type); nfs4_unregister_sysctl(); nfs_idmap_quit(); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 95866a8c21bb..61405a7a6b3c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -64,6 +64,7 @@ #include "internal.h" #include "fscache.h" #include "pnfs.h" +#include "nfs.h" #define NFSDBG_FACILITY NFSDBG_VFS #define NFS_TEXT_DATA 1 @@ -281,7 +282,7 @@ static match_table_t nfs_vers_tokens = { static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); -static struct file_system_type nfs_fs_type = { +struct file_system_type nfs_fs_type = { .owner = THIS_MODULE, .name = "nfs", .mount = nfs_fs_mount, @@ -1650,7 +1651,8 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, } static struct dentry *nfs_try_mount(int flags, const char *dev_name, - struct nfs_mount_info *mount_info) + struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) { int status; struct nfs_server *server; @@ -1662,11 +1664,11 @@ static struct dentry *nfs_try_mount(int flags, const char *dev_name, } /* Get a volume representation */ - server = nfs_create_server(mount_info->parsed, mount_info->mntfh); + server = nfs_create_server(mount_info->parsed, mount_info->mntfh, nfs_mod); if (IS_ERR(server)) return ERR_CAST(server); - return nfs_fs_mount_common(&nfs_fs_type, server, flags, dev_name, mount_info); + return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod); } /* @@ -2297,10 +2299,10 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, return 0; } -struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, - struct nfs_server *server, +struct dentry *nfs_fs_mount_common(struct nfs_server *server, int flags, const char *dev_name, - struct nfs_mount_info *mount_info) + struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) { struct super_block *s; struct dentry *mntroot = ERR_PTR(-ENOMEM); @@ -2319,7 +2321,7 @@ struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, sb_mntdata.mntflags |= MS_SYNCHRONOUS; /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata); + s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata); if (IS_ERR(s)) { mntroot = ERR_CAST(s); goto out_err_nosb; @@ -2378,6 +2380,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type, .set_security = nfs_set_sb_security, }; struct dentry *mntroot = ERR_PTR(-ENOMEM); + struct nfs_subversion *nfs_mod; int error; mount_info.parsed = nfs_alloc_parsed_mount_data(); @@ -2394,12 +2397,20 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type, goto out; } + nfs_mod = get_nfs_version(mount_info.parsed->version); + if (IS_ERR(nfs_mod)) { + mntroot = ERR_CAST(nfs_mod); + goto out; + } + #ifdef CONFIG_NFS_V4 if (mount_info.parsed->version == 4) mntroot = nfs4_try_mount(flags, dev_name, &mount_info); else #endif /* CONFIG_NFS_V4 */ - mntroot = nfs_try_mount(flags, dev_name, &mount_info); + mntroot = nfs_try_mount(flags, dev_name, &mount_info, nfs_mod); + + put_nfs_version(nfs_mod); out: nfs_free_parsed_mount_data(mount_info.parsed); @@ -2440,6 +2451,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, struct nfs_clone_mount *data = mount_info->cloned; struct nfs_server *server; struct dentry *mntroot = ERR_PTR(-ENOMEM); + struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod; int error; dprintk("--> nfs_xdev_mount_common()\n"); @@ -2453,7 +2465,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, goto out_err; } - mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); + mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod); dprintk("<-- nfs_xdev_mount_common() = 0\n"); out: return mntroot; diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 65327652c61a..6039297801f4 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -48,6 +48,7 @@ struct nfs_client { struct rpc_clnt * cl_rpcclient; const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ int cl_proto; /* Network transport protocol */ + struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */ u32 cl_minorversion;/* NFSv4 minorversion */ struct rpc_cred *cl_machine_cred; -- GitLab From e8f25e6d6d198dca7d09d8fe2c24ba3b9683bb24 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:17 -0400 Subject: [PATCH 4513/5711] NFS: Remove the NFS v4 xdev mount function I can now share this code with the v2 and v3 code by using the NFS subversion structure. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/namespace.c | 13 ------------- fs/nfs/nfs4super.c | 25 ------------------------- fs/nfs/super.c | 30 ++++++++++-------------------- 3 files changed, 10 insertions(+), 58 deletions(-) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 08b9c93675da..0f699fefee6e 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -195,20 +195,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, const char *devname, struct nfs_clone_mount *mountdata) { -#ifdef CONFIG_NFS_V4 - struct vfsmount *mnt = ERR_PTR(-EINVAL); - switch (server->nfs_client->rpc_ops->version) { - case 2: - case 3: - mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); - break; - case 4: - mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata); - } - return mnt; -#else return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); -#endif } /** diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 1f3401902c2f..8a505573c289 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -14,8 +14,6 @@ static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); -static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, @@ -37,14 +35,6 @@ static struct file_system_type nfs4_remote_fs_type = { .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -struct file_system_type nfs4_xdev_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs4_xdev_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, -}; - static struct file_system_type nfs4_remote_referral_fs_type = { .owner = THIS_MODULE, .name = "nfs4", @@ -261,21 +251,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name, return res; } -/* - * Clone an NFS4 server record on xdev traversal (FSID-change) - */ -static struct dentry * -nfs4_xdev_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) -{ - struct nfs_mount_info mount_info = { - .fill_super = nfs_clone_super, - .set_security = nfs_clone_sb_security, - .cloned = raw_data, - }; - return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info); -} - static struct dentry * nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 61405a7a6b3c..4faefa19a8c3 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2445,10 +2445,15 @@ void nfs_kill_super(struct super_block *s) * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) */ struct dentry * -nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, - const char *dev_name, struct nfs_mount_info *mount_info) +nfs_xdev_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data) { - struct nfs_clone_mount *data = mount_info->cloned; + struct nfs_clone_mount *data = raw_data; + struct nfs_mount_info mount_info = { + .fill_super = nfs_clone_super, + .set_security = nfs_clone_sb_security, + .cloned = data, + }; struct nfs_server *server; struct dentry *mntroot = ERR_PTR(-ENOMEM); struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod; @@ -2456,7 +2461,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, dprintk("--> nfs_xdev_mount_common()\n"); - mount_info->mntfh = data->fh; + mount_info.mntfh = mount_info.cloned->fh; /* create a new volume representation */ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); @@ -2465,7 +2470,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, goto out_err; } - mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod); + mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod); dprintk("<-- nfs_xdev_mount_common() = 0\n"); out: return mntroot; @@ -2475,21 +2480,6 @@ out_err: goto out; } -/* - * Clone an NFS2/3 server record on xdev traversal (FSID-change) - */ -static struct dentry * -nfs_xdev_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) -{ - struct nfs_mount_info mount_info = { - .fill_super = nfs_clone_super, - .set_security = nfs_clone_sb_security, - .cloned = raw_data, - }; - return nfs_xdev_mount_common(&nfs_fs_type, flags, dev_name, &mount_info); -} - #ifdef CONFIG_NFS_V4 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) -- GitLab From ff9099f26645818563c8d396a154c2ce6ee422eb Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:18 -0400 Subject: [PATCH 4514/5711] NFS: Create a try_mount rpc op I'm already looking up the nfs subversion in nfs_fs_mount(), so I have easy access to rpc_ops that used to be difficult to reach. This allows me to set up a different mount path for NFS v2/3 and NFS v4. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 2 ++ fs/nfs/nfs3proc.c | 1 + fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4proc.c | 1 + fs/nfs/nfs4super.c | 3 ++- fs/nfs/proc.c | 1 + fs/nfs/super.c | 14 ++++---------- include/linux/nfs_xdr.h | 4 ++++ 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index ac936476b3bc..3364eccd17ef 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -328,6 +328,8 @@ extern struct file_system_type nfs_xdev_fs_type; extern struct file_system_type nfs4_xdev_fs_type; extern struct file_system_type nfs4_referral_fs_type; #endif +struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, + struct nfs_subversion *); void nfs_initialise_sb(struct super_block *); int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 65d23eb92fe0..4f4cb8e49716 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -925,6 +925,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = { .file_ops = &nfs_file_operations, .getroot = nfs3_proc_get_root, .submount = nfs_submount, + .try_mount = nfs_try_mount, .getattr = nfs3_proc_getattr, .setattr = nfs3_proc_setattr, .lookup = nfs3_proc_lookup, diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 99c2e7e4d3ea..c321fb59d801 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -367,7 +367,7 @@ extern const nfs4_stateid zero_stateid; /* nfs4super.c */ struct nfs_mount_info; extern struct nfs_subversion nfs_v4; -struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *); +struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *); int init_nfs_v4(void); void exit_nfs_v4(void); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6843e0a37de8..eb4ba1d99df9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6870,6 +6870,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .file_ops = &nfs4_file_operations, .getroot = nfs4_proc_get_root, .submount = nfs4_submount, + .try_mount = nfs4_try_mount, .getattr = nfs4_proc_getattr, .setattr = nfs4_proc_setattr, .lookup = nfs4_proc_lookup, diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 8a505573c289..9384f666b6ab 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -226,7 +226,8 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, } struct dentry *nfs4_try_mount(int flags, const char *dev_name, - struct nfs_mount_info *mount_info) + struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) { char *export_path; struct vfsmount *root_mnt; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 4d3356af3309..ebb3d9c5227b 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -774,6 +774,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = { .file_ops = &nfs_file_operations, .getroot = nfs_proc_get_root, .submount = nfs_submount, + .try_mount = nfs_try_mount, .getattr = nfs_proc_getattr, .setattr = nfs_proc_setattr, .lookup = nfs_proc_lookup, diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 4faefa19a8c3..5fca59d73e40 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1650,9 +1650,9 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, return nfs_walk_authlist(args, &request); } -static struct dentry *nfs_try_mount(int flags, const char *dev_name, - struct nfs_mount_info *mount_info, - struct nfs_subversion *nfs_mod) +struct dentry *nfs_try_mount(int flags, const char *dev_name, + struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) { int status; struct nfs_server *server; @@ -2403,15 +2403,9 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type, goto out; } -#ifdef CONFIG_NFS_V4 - if (mount_info.parsed->version == 4) - mntroot = nfs4_try_mount(flags, dev_name, &mount_info); - else -#endif /* CONFIG_NFS_V4 */ - mntroot = nfs_try_mount(flags, dev_name, &mount_info, nfs_mod); + mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info, nfs_mod); put_nfs_version(nfs_mod); - out: nfs_free_parsed_mount_data(mount_info.parsed); nfs_free_fhandle(mount_info.mntfh); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 0e181c2320b7..bc7415baf44d 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1353,6 +1353,8 @@ struct nfs_renamedata { struct nfs_access_entry; struct nfs_client; struct rpc_timeout; +struct nfs_subversion; +struct nfs_mount_info; struct nfs_client_initdata; struct nfs_pageio_descriptor; @@ -1370,6 +1372,8 @@ struct nfs_rpc_ops { struct nfs_fsinfo *); struct vfsmount *(*submount) (struct nfs_server *, struct dentry *, struct nfs_fh *, struct nfs_fattr *); + struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *, + struct nfs_subversion *); int (*getattr) (struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); int (*setattr) (struct dentry *, struct nfs_fattr *, -- GitLab From 1179acc6a3e260bc4edc74fa94f6c7908290eaec Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:19 -0400 Subject: [PATCH 4515/5711] NFS: Only initialize the ACL client in the v3 case v2 and v4 don't use it, so I create two new nfs_rpc_ops functions to initialize the ACL client only when we are using v3. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Makefile | 2 +- fs/nfs/client.c | 61 ++++---------------------------------- fs/nfs/internal.h | 15 ++++++---- fs/nfs/nfs3client.c | 65 +++++++++++++++++++++++++++++++++++++++++ fs/nfs/nfs3proc.c | 2 ++ fs/nfs/nfs4client.c | 10 ++++--- fs/nfs/nfs4proc.c | 2 ++ fs/nfs/nfs4super.c | 2 +- fs/nfs/proc.c | 2 ++ fs/nfs/super.c | 4 +-- include/linux/nfs_xdr.h | 3 ++ 11 files changed, 99 insertions(+), 69 deletions(-) create mode 100644 fs/nfs/nfs3client.c diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 66dd3075e5db..7ca0125da65e 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -10,7 +10,7 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ dns_resolve.o cache_lib.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o nfs-$(CONFIG_NFS_V2) += nfs2super.o proc.o nfs2xdr.o -nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o +nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs4super.o nfs4file.o delegation.o idmap.o \ diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 462de24482b4..1f2908287cba 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -83,22 +83,6 @@ struct rpc_stat nfs_rpcstat = { .program = &nfs_program }; - -#ifdef CONFIG_NFS_V3_ACL -static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; -static const struct rpc_version *nfsacl_version[] = { - [3] = &nfsacl_version3, -}; - -const struct rpc_program nfsacl_program = { - .name = "nfsacl", - .number = NFS_ACL_PROGRAM, - .nrvers = ARRAY_SIZE(nfsacl_version), - .version = nfsacl_version, - .stats = &nfsacl_rpcstat, -}; -#endif /* CONFIG_NFS_V3_ACL */ - static struct nfs_subversion *find_nfs_version(unsigned int version) { struct nfs_subversion *nfs; @@ -695,36 +679,6 @@ static int nfs_start_lockd(struct nfs_server *server) return 0; } -/* - * Initialise an NFSv3 ACL client connection - */ -#ifdef CONFIG_NFS_V3_ACL -static void nfs_init_server_aclclient(struct nfs_server *server) -{ - if (server->nfs_client->rpc_ops->version != 3) - goto out_noacl; - if (server->flags & NFS_MOUNT_NOACL) - goto out_noacl; - - server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); - if (IS_ERR(server->client_acl)) - goto out_noacl; - - /* No errors! Assume that Sun nfsacls are supported */ - server->caps |= NFS_CAP_ACLS; - return; - -out_noacl: - server->caps &= ~NFS_CAP_ACLS; -} -#else -static inline void nfs_init_server_aclclient(struct nfs_server *server) -{ - server->flags &= ~NFS_MOUNT_NOACL; - server->caps &= ~NFS_CAP_ACLS; -} -#endif - /* * Create a general RPC client */ @@ -874,8 +828,6 @@ static int nfs_init_server(struct nfs_server *server, server->mountd_protocol = data->mount_server.protocol; server->namelen = data->namlen; - /* Create a client RPC handle for the NFSv3 ACL management interface */ - nfs_init_server_aclclient(server); dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); return 0; @@ -1108,8 +1060,7 @@ void nfs_free_server(struct nfs_server *server) * Create a version 2 or 3 volume record * - keyed on server and FSID */ -struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, - struct nfs_fh *mntfh, +struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, struct nfs_subversion *nfs_mod) { struct nfs_server *server; @@ -1126,7 +1077,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, goto error; /* Get a client representation */ - error = nfs_init_server(server, data, nfs_mod); + error = nfs_init_server(server, mount_info->parsed, nfs_mod); if (error < 0) goto error; @@ -1135,13 +1086,13 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); /* Probe the root fh to retrieve its FSID */ - error = nfs_probe_fsinfo(server, mntfh, fattr); + error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr); if (error < 0) goto error; if (server->nfs_client->rpc_ops->version == 3) { if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) server->namelen = NFS3_MAXNAMLEN; - if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) + if (!(mount_info->parsed->flags & NFS_MOUNT_NORDIRPLUS)) server->caps |= NFS_CAP_READDIRPLUS; } else { if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) @@ -1149,7 +1100,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, } if (!(fattr->valid & NFS_ATTR_FATTR)) { - error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); + error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr); if (error < 0) { dprintk("nfs_create_server: getattr error = %d\n", -error); goto error; @@ -1210,8 +1161,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, flavor); if (error < 0) goto out_free_server; - if (!IS_ERR(source->client_acl)) - nfs_init_server_aclclient(server); /* probe the filesystem info for this server filesystem */ error = nfs_probe_fsinfo(server, fh, fattr_fsinfo); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 3364eccd17ef..2151bafd55b4 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -187,13 +187,11 @@ extern struct nfs_client *nfs4_find_client_ident(struct net *, int); extern struct nfs_client * nfs4_find_client_sessionid(struct net *, const struct sockaddr *, struct nfs4_sessionid *); -extern struct nfs_server *nfs_create_server( - const struct nfs_parsed_mount_data *, - struct nfs_fh *, +extern struct nfs_server *nfs_create_server(struct nfs_mount_info *, struct nfs_subversion *); extern struct nfs_server *nfs4_create_server( - const struct nfs_parsed_mount_data *, - struct nfs_fh *); + struct nfs_mount_info *, + struct nfs_subversion *); extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, struct nfs_fh *); extern void nfs_free_server(struct nfs_server *server); @@ -225,6 +223,13 @@ static inline void nfs_fs_proc_exit(void) int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *); #endif +/* nfs3client.c */ +#ifdef CONFIG_NFS_V3 +struct nfs_server *nfs3_create_server(struct nfs_mount_info *, struct nfs_subversion *); +struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *, + struct nfs_fattr *, rpc_authflavor_t); +#endif + /* callback_xdr.c */ extern struct svc_version nfs4_callback_version1; extern struct svc_version nfs4_callback_version4; diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c new file mode 100644 index 000000000000..b3fc65ef39ca --- /dev/null +++ b/fs/nfs/nfs3client.c @@ -0,0 +1,65 @@ +#include +#include +#include "internal.h" + +#ifdef CONFIG_NFS_V3_ACL +static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; +static const struct rpc_version *nfsacl_version[] = { + [3] = &nfsacl_version3, +}; + +const struct rpc_program nfsacl_program = { + .name = "nfsacl", + .number = NFS_ACL_PROGRAM, + .nrvers = ARRAY_SIZE(nfsacl_version), + .version = nfsacl_version, + .stats = &nfsacl_rpcstat, +}; + +/* + * Initialise an NFSv3 ACL client connection + */ +static void nfs_init_server_aclclient(struct nfs_server *server) +{ + if (server->flags & NFS_MOUNT_NOACL) + goto out_noacl; + + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); + if (IS_ERR(server->client_acl)) + goto out_noacl; + + /* No errors! Assume that Sun nfsacls are supported */ + server->caps |= NFS_CAP_ACLS; + return; + +out_noacl: + server->caps &= ~NFS_CAP_ACLS; +} +#else +static inline void nfs_init_server_aclclient(struct nfs_server *server) +{ + server->flags &= ~NFS_MOUNT_NOACL; + server->caps &= ~NFS_CAP_ACLS; +} +#endif + +struct nfs_server *nfs3_create_server(struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) +{ + struct nfs_server *server = nfs_create_server(mount_info, nfs_mod); + /* Create a client RPC handle for the NFS v3 ACL management interface */ + if (!IS_ERR(server)) + nfs_init_server_aclclient(server); + return server; +} + +struct nfs_server *nfs3_clone_server(struct nfs_server *source, + struct nfs_fh *fh, + struct nfs_fattr *fattr, + rpc_authflavor_t flavor) +{ + struct nfs_server *server = nfs_clone_server(source, fh, fattr, flavor); + if (!IS_ERR(server) && !IS_ERR(source->client_acl)) + nfs_init_server_aclclient(server); + return server; +} diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 4f4cb8e49716..0952c791df36 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -969,4 +969,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = { .alloc_client = nfs_alloc_client, .init_client = nfs_init_client, .free_client = nfs_free_client, + .create_server = nfs3_create_server, + .clone_server = nfs3_clone_server, }; diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 769e798b3959..b2d409d2805a 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -574,8 +574,10 @@ error: * Create a version 4 volume record * - keyed on server and FSID */ -struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, - struct nfs_fh *mntfh) +/*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, + struct nfs_fh *mntfh)*/ +struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, + struct nfs_subversion *nfs_mod) { struct nfs_server *server; int error; @@ -587,11 +589,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, return ERR_PTR(-ENOMEM); /* set up the general RPC client */ - error = nfs4_init_server(server, data); + error = nfs4_init_server(server, mount_info->parsed); if (error < 0) goto error; - error = nfs4_server_common_setup(server, mntfh); + error = nfs4_server_common_setup(server, mount_info->mntfh); if (error < 0) goto error; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index eb4ba1d99df9..36c6432aac7b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6916,6 +6916,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .alloc_client = nfs4_alloc_client, .init_client = nfs4_init_client, .free_client = nfs4_free_client, + .create_server = nfs4_create_server, + .clone_server = nfs_clone_server, }; static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 9384f666b6ab..a62836256665 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -105,7 +105,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, mount_info->set_security = nfs_set_sb_security; /* Get a volume representation */ - server = nfs4_create_server(mount_info->parsed, mount_info->mntfh); + server = nfs4_create_server(mount_info, &nfs_v4); if (IS_ERR(server)) { mntroot = ERR_CAST(server); goto out; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index ebb3d9c5227b..50a88c3546ed 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -817,4 +817,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = { .alloc_client = nfs_alloc_client, .init_client = nfs_init_client, .free_client = nfs_free_client, + .create_server = nfs_create_server, + .clone_server = nfs_clone_server, }; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 5fca59d73e40..a5f9fb3bfdcc 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1664,7 +1664,7 @@ struct dentry *nfs_try_mount(int flags, const char *dev_name, } /* Get a volume representation */ - server = nfs_create_server(mount_info->parsed, mount_info->mntfh, nfs_mod); + server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); if (IS_ERR(server)) return ERR_CAST(server); @@ -2458,7 +2458,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, mount_info.mntfh = mount_info.cloned->fh; /* create a new volume representation */ - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); + server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index bc7415baf44d..631182062994 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1439,6 +1439,9 @@ struct nfs_rpc_ops { (*init_client) (struct nfs_client *, const struct rpc_timeout *, const char *, rpc_authflavor_t); void (*free_client) (struct nfs_client *); + struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *); + struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *, + struct nfs_fattr *, rpc_authflavor_t); }; /* -- GitLab From 6a74490dca897471a994a542fc7c5a469b48b46b Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:20 -0400 Subject: [PATCH 4516/5711] NFS: Pass super operations and xattr handlers in the nfs_subversion I can set all variables in the nfs_fill_super() function, allowing me to remove the nfs4_fill_super() function. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 1 + fs/nfs/nfs.h | 2 ++ fs/nfs/nfs2super.c | 1 + fs/nfs/nfs3super.c | 1 + fs/nfs/nfs4super.c | 24 +++--------------------- fs/nfs/super.c | 9 +++++---- 6 files changed, 13 insertions(+), 25 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 2151bafd55b4..17d14709e750 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -327,6 +327,7 @@ void nfs_zap_acl_cache(struct inode *inode); extern int nfs_wait_bit_killable(void *word); /* super.c */ +extern const struct super_operations nfs_sops; extern struct file_system_type nfs_fs_type; extern struct file_system_type nfs_xdev_fs_type; #ifdef CONFIG_NFS_V4 diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index ac10b9e6c920..9f502a0c1e59 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -16,6 +16,8 @@ struct nfs_subversion { struct file_system_type *nfs_fs; /* NFS filesystem type */ const struct rpc_version *rpc_vers; /* NFS version information */ const struct nfs_rpc_ops *rpc_ops; /* NFS operations */ + const struct super_operations *sops; /* NFS Super operations */ + const struct xattr_handler **xattr; /* NFS xattr handlers */ struct list_head list; /* List of NFS versions */ }; diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c index cef06d42334a..a9fb69d72816 100644 --- a/fs/nfs/nfs2super.c +++ b/fs/nfs/nfs2super.c @@ -11,6 +11,7 @@ static struct nfs_subversion nfs_v2 = { .nfs_fs = &nfs_fs_type, .rpc_vers = &nfs_version2, .rpc_ops = &nfs_v2_clientops, + .sops = &nfs_sops, }; int __init init_nfs_v2(void) diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c index f815cf359d97..8378090b8104 100644 --- a/fs/nfs/nfs3super.c +++ b/fs/nfs/nfs3super.c @@ -11,6 +11,7 @@ static struct nfs_subversion nfs_v3 = { .nfs_fs = &nfs_fs_type, .rpc_vers = &nfs_version3, .rpc_ops = &nfs_v3_clientops, + .sops = &nfs_sops, }; int __init init_nfs_v3(void) diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index a62836256665..c70e1730755c 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -71,25 +71,10 @@ struct nfs_subversion nfs_v4 = { .nfs_fs = &nfs4_fs_type, .rpc_vers = &nfs_version4, .rpc_ops = &nfs_v4_clientops, + .sops = &nfs4_sops, + .xattr = nfs4_xattr_handlers, }; -/* - * Set up an NFS4 superblock - */ -static void nfs4_fill_super(struct super_block *sb, - struct nfs_mount_info *mount_info) -{ - sb->s_time_gran = 1; - sb->s_op = &nfs4_sops; - /* - * The VFS shouldn't apply the umask to mode bits. We will do - * so ourselves when necessary. - */ - sb->s_flags |= MS_POSIXACL; - sb->s_xattr = nfs4_xattr_handlers; - nfs_initialise_sb(sb); -} - /* * Get the superblock for the NFS4 root partition */ @@ -101,7 +86,6 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, struct nfs_server *server; struct dentry *mntroot = ERR_PTR(-ENOMEM); - mount_info->fill_super = nfs4_fill_super; mount_info->set_security = nfs_set_sb_security; /* Get a volume representation */ @@ -236,8 +220,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name, dfprintk(MOUNT, "--> nfs4_try_mount()\n"); - mount_info->fill_super = nfs4_fill_super; - export_path = data->nfs_server.export_path; data->nfs_server.export_path = "/"; root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, @@ -257,7 +239,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) { struct nfs_mount_info mount_info = { - .fill_super = nfs4_fill_super, + .fill_super = nfs_fill_super, .set_security = nfs_clone_sb_security, .cloned = raw_data, }; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index a5f9fb3bfdcc..a275d19ae512 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -298,7 +298,7 @@ struct file_system_type nfs_xdev_fs_type = { .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -static const struct super_operations nfs_sops = { +const struct super_operations nfs_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, @@ -2105,10 +2105,12 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) sb->s_blocksize_bits = 0; sb->s_blocksize = 0; - if (data->bsize) + sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr; + sb->s_op = server->nfs_client->cl_nfs_mod->sops; + if (data && data->bsize) sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); - if (server->nfs_client->rpc_ops->version == 3) { + if (server->nfs_client->rpc_ops->version != 2) { /* The VFS shouldn't apply the umask to mode bits. We will do * so ourselves when necessary. */ @@ -2116,7 +2118,6 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) sb->s_time_gran = 1; } - sb->s_op = &nfs_sops; nfs_initialise_sb(sb); } -- GitLab From 19d87ca3623956494b517f3abe0caf2616d55457 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:21 -0400 Subject: [PATCH 4517/5711] NFS: Split out remaining NFS v4 inode functions Somehow I missed this in my previous patch series, but these functions are only needed by the v4 code and should be moved to a v4-only file. I wasn't exactly sure where I should put these functions, so I moved them into nfs4super.c where I could make them static. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 23 +---------------------- fs/nfs/internal.h | 4 +--- fs/nfs/nfs4_fs.h | 3 --- fs/nfs/nfs4super.c | 39 +++++++++++++++++++++++++++++++++++++++ fs/nfs/write.c | 20 -------------------- 5 files changed, 41 insertions(+), 48 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e8877c82582d..a6ffa4be2a03 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -106,7 +106,7 @@ u64 nfs_compat_user_ino64(u64 fileid) return ino; } -static void nfs_clear_inode(struct inode *inode) +void nfs_clear_inode(struct inode *inode) { /* * The following should never happen... @@ -1472,27 +1472,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) return -ESTALE; } - -#ifdef CONFIG_NFS_V4 - -/* - * Clean out any remaining NFSv4 state that might be left over due - * to open() calls that passed nfs_atomic_lookup, but failed to call - * nfs_open(). - */ -void nfs4_evict_inode(struct inode *inode) -{ - truncate_inode_pages(&inode->i_data, 0); - clear_inode(inode); - pnfs_return_layout(inode); - pnfs_destroy_layout(NFS_I(inode)); - /* If we are holding a delegation, return it! */ - nfs_inode_return_delegation_noreclaim(inode); - /* First call standard NFS clear_inode() code */ - nfs_clear_inode(inode); -} -#endif - struct inode *nfs_alloc_inode(struct super_block *sb) { struct nfs_inode *nfsi; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 17d14709e750..4174faf73ec1 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -319,10 +319,8 @@ extern struct workqueue_struct *nfsiod_workqueue; extern struct inode *nfs_alloc_inode(struct super_block *sb); extern void nfs_destroy_inode(struct inode *); extern int nfs_write_inode(struct inode *, struct writeback_control *); +extern void nfs_clear_inode(struct inode *); extern void nfs_evict_inode(struct inode *); -#ifdef CONFIG_NFS_V4 -extern void nfs4_evict_inode(struct inode *); -#endif void nfs_zap_acl_cache(struct inode *inode); extern int nfs_wait_bit_killable(void *word); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c321fb59d801..4811e1251d32 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -205,9 +205,6 @@ extern const struct dentry_operations nfs4_dentry_operations; int nfs_atomic_open(struct inode *, struct dentry *, struct file *, unsigned, umode_t, int *); -/* write.c */ -int nfs4_write_inode(struct inode *, struct writeback_control *); - /* nfs4namespace.c */ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index c70e1730755c..1c825f3bef51 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -6,12 +6,16 @@ #include #include #include +#include "delegation.h" #include "internal.h" #include "nfs4_fs.h" +#include "pnfs.h" #include "nfs.h" #define NFSDBG_FACILITY NFSDBG_VFS +static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc); +static void nfs4_evict_inode(struct inode *inode); static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, @@ -75,6 +79,41 @@ struct nfs_subversion nfs_v4 = { .xattr = nfs4_xattr_handlers, }; +static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + int ret = nfs_write_inode(inode, wbc); + + if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { + int status; + bool sync = true; + + if (wbc->sync_mode == WB_SYNC_NONE) + sync = false; + + status = pnfs_layoutcommit_inode(inode, sync); + if (status < 0) + return status; + } + return ret; +} + +/* + * Clean out any remaining NFSv4 state that might be left over due + * to open() calls that passed nfs_atomic_lookup, but failed to call + * nfs_open(). + */ +static void nfs4_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); + pnfs_return_layout(inode); + pnfs_destroy_layout(NFS_I(inode)); + /* If we are holding a delegation, return it! */ + nfs_inode_return_delegation_noreclaim(inode); + /* First call standard NFS clear_inode() code */ + nfs_clear_inode(inode); +} + /* * Get the superblock for the NFS4 root partition */ diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f312860c15d0..6ddac54dc67f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1674,26 +1674,6 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) return nfs_commit_unstable_pages(inode, wbc); } -#ifdef CONFIG_NFS_V4 -int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - int ret = nfs_write_inode(inode, wbc); - - if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { - int status; - bool sync = true; - - if (wbc->sync_mode == WB_SYNC_NONE) - sync = false; - - status = pnfs_layoutcommit_inode(inode, sync); - if (status < 0) - return status; - } - return ret; -} -#endif - /* * flush the inode to disk. */ -- GitLab From fac1e8e4ef417e958060a6c3a061cc1a180bd8ae Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:22 -0400 Subject: [PATCH 4518/5711] NFS: Keep module parameters in the generic NFS client Otherwise we break backwards compatibility when v4 becomes a modules. Signed-off-by: Trond Myklebust --- fs/nfs/callback.c | 24 ------------------------ fs/nfs/idmap.c | 3 --- fs/nfs/nfs4_fs.h | 4 +++- fs/nfs/nfs4client.c | 9 --------- fs/nfs/nfs4proc.c | 6 ------ fs/nfs/nfs4xdr.c | 6 ------ fs/nfs/super.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 48 insertions(+), 49 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 23ff18fe080a..ca3ac992028b 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -37,31 +37,7 @@ static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; static DEFINE_MUTEX(nfs_callback_mutex); static struct svc_program nfs4_callback_program; -unsigned int nfs_callback_set_tcpport; -unsigned short nfs_callback_tcpport; unsigned short nfs_callback_tcpport6; -#define NFS_CALLBACK_MAXPORTNR (65535U) - -static int param_set_portnr(const char *val, const struct kernel_param *kp) -{ - unsigned long num; - int ret; - - if (!val) - return -EINVAL; - ret = strict_strtoul(val, 0, &num); - if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR) - return -EINVAL; - *((unsigned int *)kp->arg) = num; - return 0; -} -static struct kernel_param_ops param_ops_portnr = { - .set = param_set_portnr, - .get = param_get_uint, -}; -#define param_check_portnr(name, p) __param_check(name, p, unsigned int); - -module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); /* * This is the NFSv4 callback kernel thread. diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 1b5058b4043b..b701358c39c3 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -52,8 +52,6 @@ #define NFS_UINT_MAXLEN 11 -/* Default cache timeout is 10 minutes */ -unsigned int nfs_idmap_cache_timeout = 600; static const struct cred *id_resolver_cache; static struct key_type key_type_id_resolver_legacy; @@ -366,7 +364,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ } /* idmap classic begins here */ -module_param(nfs_idmap_cache_timeout, int, 0644); enum { Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 4811e1251d32..bafe5186c9cd 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -367,7 +367,9 @@ extern struct nfs_subversion nfs_v4; struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *); int init_nfs_v4(void); void exit_nfs_v4(void); - +extern bool nfs4_disable_idmapping; +extern unsigned short max_session_slots; +extern unsigned short send_implementation_id; /* nfs4sysctl.c */ #ifdef CONFIG_SYSCTL int nfs4_register_sysctl(void); diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index b2d409d2805a..cbcdfaf32505 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -17,11 +17,6 @@ #define NFSDBG_FACILITY NFSDBG_CLIENT -/* - * Turn off NFSv4 uid/gid mapping when using AUTH_SYS - */ -static bool nfs4_disable_idmapping = true; - /* * Get a unique NFSv4.0 callback identifier which will be used * by the V4.0 callback service to lookup the nfs_client struct @@ -659,7 +654,3 @@ error: dprintk("<-- nfs4_create_referral_server() = error %d\n", error); return ERR_PTR(error); } - -module_param(nfs4_disable_idmapping, bool, 0644); -MODULE_PARM_DESC(nfs4_disable_idmapping, - "Turn off NFSv4 idmapping when using 'sec=sys'"); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 36c6432aac7b..a99a8d948721 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -72,8 +72,6 @@ #define NFS4_MAX_LOOP_ON_RECOVER (10) -static unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; - struct nfs4_opendata; static int _nfs4_proc_open(struct nfs4_opendata *data); static int _nfs4_recover_proc_open(struct nfs4_opendata *data); @@ -6932,10 +6930,6 @@ const struct xattr_handler *nfs4_xattr_handlers[] = { NULL }; -module_param(max_session_slots, ushort, 0644); -MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " - "requests the client will negotiate"); - /* * Local variables: * c-basic-offset: 8 diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6cbd602e26d5..ca13483edd60 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -852,12 +852,6 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + XDR_UNIT); #endif /* CONFIG_NFS_V4_1 */ -static unsigned short send_implementation_id = 1; - -module_param(send_implementation_id, ushort, 0644); -MODULE_PARM_DESC(send_implementation_id, - "Send implementation ID with NFSv4.1 exchange_id"); - static const umode_t nfs_type2fmt[] = { [NF4BAD] = 0, [NF4REG] = S_IFREG, diff --git a/fs/nfs/super.c b/fs/nfs/super.c index a275d19ae512..8e0da5a6b3c5 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2574,4 +2574,49 @@ out_no_address: return -EINVAL; } +/* + * NFS v4 module parameters need to stay in the + * NFS client for backwards compatibility + */ +unsigned int nfs_callback_set_tcpport; +unsigned short nfs_callback_tcpport; +/* Default cache timeout is 10 minutes */ +unsigned int nfs_idmap_cache_timeout = 600; +/* Turn off NFSv4 uid/gid mapping when using AUTH_SYS */ +bool nfs4_disable_idmapping = true; +unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; +unsigned short send_implementation_id = 1; + +#define NFS_CALLBACK_MAXPORTNR (65535U) + +static int param_set_portnr(const char *val, const struct kernel_param *kp) +{ + unsigned long num; + int ret; + + if (!val) + return -EINVAL; + ret = strict_strtoul(val, 0, &num); + if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR) + return -EINVAL; + *((unsigned int *)kp->arg) = num; + return 0; +} +static struct kernel_param_ops param_ops_portnr = { + .set = param_set_portnr, + .get = param_get_uint, +}; +#define param_check_portnr(name, p) __param_check(name, p, unsigned int); + +module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); +module_param(nfs_idmap_cache_timeout, int, 0644); +module_param(nfs4_disable_idmapping, bool, 0644); +MODULE_PARM_DESC(nfs4_disable_idmapping, + "Turn off NFSv4 idmapping when using 'sec=sys'"); +module_param(max_session_slots, ushort, 0644); +MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " + "requests the client will negotiate"); +module_param(send_implementation_id, ushort, 0644); +MODULE_PARM_DESC(send_implementation_id, + "Send implementation ID with NFSv4.1 exchange_id"); #endif /* CONFIG_NFS_V4 */ -- GitLab From ddda8e0aa8b955e20cb80908189bfa154ab54837 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:23 -0400 Subject: [PATCH 4519/5711] NFS: Convert v2 into a module The module (nfs2.ko) will be created in the same directory as nfs.ko and will be automatically loaded the first time you try to mount over NFS v2. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Kconfig | 2 +- fs/nfs/Makefile | 4 +++- fs/nfs/client.c | 12 ++++++------ fs/nfs/dir.c | 13 +++++++++++++ fs/nfs/file.c | 2 ++ fs/nfs/inode.c | 10 ++++++++++ fs/nfs/namespace.c | 2 ++ fs/nfs/nfs.h | 14 -------------- fs/nfs/nfs2super.c | 9 +++++++-- fs/nfs/read.c | 1 + fs/nfs/super.c | 3 +++ fs/nfs/write.c | 2 ++ 12 files changed, 50 insertions(+), 24 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 404c6a8ac394..6764dbf66d05 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -30,7 +30,7 @@ config NFS_FS If unsure, say N. config NFS_V2 - bool "NFS client support for NFS version 2" + tristate "NFS client support for NFS version 2" depends on NFS_FS default y help diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 7ca0125da65e..df61db41bfa8 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -9,7 +9,6 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ write.o namespace.o mount_clnt.o \ dns_resolve.o cache_lib.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o -nfs-$(CONFIG_NFS_V2) += nfs2super.o proc.o nfs2xdr.o nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ @@ -25,6 +24,9 @@ endif nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o +obj-$(CONFIG_NFS_V2) += nfs2.o +nfs2-y := nfs2super.o proc.o nfs2xdr.o + obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 1f2908287cba..fa8acf510333 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -149,11 +149,7 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version); */ int __init nfs_register_versions(void) { - int err = init_nfs_v2(); - if (err) - return err; - - err = init_nfs_v3(); + int err = init_nfs_v3(); if (err) return err; @@ -165,7 +161,6 @@ int __init nfs_register_versions(void) */ void nfs_unregister_versions(void) { - exit_nfs_v2(); exit_nfs_v3(); exit_nfs_v4(); } @@ -222,6 +217,7 @@ error_cleanup: error_0: return ERR_PTR(err); } +EXPORT_SYMBOL_GPL(nfs_alloc_client); #ifdef CONFIG_NFS_V4 /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ @@ -284,6 +280,7 @@ void nfs_free_client(struct nfs_client *clp) dprintk("<-- nfs_free_client()\n"); } +EXPORT_SYMBOL_GPL(nfs_free_client); /* * Release a reference to a shared client record @@ -753,6 +750,7 @@ error: dprintk("<-- nfs_init_client() = xerror %d\n", error); return ERR_PTR(error); } +EXPORT_SYMBOL_GPL(nfs_init_client); /* * Create a version 2 or 3 client @@ -1122,6 +1120,7 @@ error: nfs_free_server(server); return ERR_PTR(error); } +EXPORT_SYMBOL_GPL(nfs_create_server); /* * Clone an NFS2, NFS3 or NFS4 server record @@ -1191,6 +1190,7 @@ out_free_server: dprintk("<-- nfs_clone_server() = error %d\n", error); return ERR_PTR(error); } +EXPORT_SYMBOL_GPL(nfs_clone_server); void nfs_clients_init(struct net *net) { diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d49f1b9cd3fd..c382a6d5e177 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -17,6 +17,7 @@ * 6 Jun 1999 Cache readdir lookups in the page cache. -DaveM */ +#include #include #include #include @@ -1196,6 +1197,7 @@ const struct dentry_operations nfs_dentry_operations = { .d_automount = nfs_d_automount, .d_release = nfs_d_release, }; +EXPORT_SYMBOL_GPL(nfs_dentry_operations); struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) { @@ -1263,6 +1265,7 @@ out: nfs_free_fhandle(fhandle); return res; } +EXPORT_SYMBOL_GPL(nfs_lookup); #ifdef CONFIG_NFS_V4 static int nfs4_lookup_revalidate(struct dentry *, unsigned int); @@ -1508,6 +1511,7 @@ out_error: dput(parent); return error; } +EXPORT_SYMBOL_GPL(nfs_instantiate); /* * Following a failed create operation, we drop the dentry rather @@ -1536,6 +1540,7 @@ out_err: d_drop(dentry); return error; } +EXPORT_SYMBOL_GPL(nfs_create); /* * See comments for nfs_proc_create regarding failed operations. @@ -1563,6 +1568,7 @@ out_err: d_drop(dentry); return status; } +EXPORT_SYMBOL_GPL(nfs_mknod); /* * See comments for nfs_proc_create regarding failed operations. @@ -1586,6 +1592,7 @@ out_err: d_drop(dentry); return error; } +EXPORT_SYMBOL_GPL(nfs_mkdir); static void nfs_dentry_handle_enoent(struct dentry *dentry) { @@ -1609,6 +1616,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry) return error; } +EXPORT_SYMBOL_GPL(nfs_rmdir); /* * Remove a file after making sure there are no pending writes, @@ -1680,6 +1688,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) d_rehash(dentry); return error; } +EXPORT_SYMBOL_GPL(nfs_unlink); /* * To create a symbolic link, most file systems instantiate a new inode, @@ -1750,6 +1759,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) return 0; } +EXPORT_SYMBOL_GPL(nfs_symlink); int nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) @@ -1771,6 +1781,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) } return error; } +EXPORT_SYMBOL_GPL(nfs_link); /* * RENAME @@ -1869,6 +1880,7 @@ out: dput(dentry); return error; } +EXPORT_SYMBOL_GPL(nfs_rename); static DEFINE_SPINLOCK(nfs_access_lru_lock); static LIST_HEAD(nfs_access_lru_list); @@ -2188,6 +2200,7 @@ out_notsup: res = generic_permission(inode, mask); goto out; } +EXPORT_SYMBOL_GPL(nfs_permission); /* * Local variables: diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1b3925426929..5b3e70389553 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -16,6 +16,7 @@ * nfs regular file handling functions */ +#include #include #include #include @@ -865,3 +866,4 @@ const struct file_operations nfs_file_operations = { .check_flags = nfs_check_flags, .setlease = nfs_setlease, }; +EXPORT_SYMBOL_GPL(nfs_file_operations); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index a6ffa4be2a03..f358b976e9e6 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -193,6 +193,7 @@ void nfs_invalidate_atime(struct inode *inode) NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; spin_unlock(&inode->i_lock); } +EXPORT_SYMBOL_GPL(nfs_invalidate_atime); /* * Invalidate, but do not unhash, the inode. @@ -438,6 +439,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) out: return error; } +EXPORT_SYMBOL_GPL(nfs_setattr); /** * nfs_vmtruncate - unmap mappings "freed" by truncate() syscall @@ -496,6 +498,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) nfs_vmtruncate(inode, attr->ia_size); } } +EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { @@ -535,6 +538,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) out: return err; } +EXPORT_SYMBOL_GPL(nfs_getattr); static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) { @@ -623,6 +627,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync) return; nfs_revalidate_inode(server, inode); } +EXPORT_SYMBOL_GPL(nfs_close_context); struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode) { @@ -1028,6 +1033,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr) fattr->owner_name = NULL; fattr->group_name = NULL; } +EXPORT_SYMBOL_GPL(nfs_fattr_init); struct nfs_fattr *nfs_alloc_fattr(void) { @@ -1038,6 +1044,7 @@ struct nfs_fattr *nfs_alloc_fattr(void) nfs_fattr_init(fattr); return fattr; } +EXPORT_SYMBOL_GPL(nfs_alloc_fattr); struct nfs_fh *nfs_alloc_fhandle(void) { @@ -1048,6 +1055,7 @@ struct nfs_fh *nfs_alloc_fhandle(void) fh->size = 0; return fh; } +EXPORT_SYMBOL_GPL(nfs_alloc_fhandle); #ifdef NFS_DEBUG /* @@ -1168,6 +1176,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) return status; } +EXPORT_SYMBOL_GPL(nfs_refresh_inode); static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) { @@ -1255,6 +1264,7 @@ out_noforce: spin_unlock(&inode->i_lock); return status; } +EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc); /* * Many nfs protocol calls return the new file attributes after diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 0f699fefee6e..2a3b170e88e0 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -7,6 +7,7 @@ * NFS namespace */ +#include #include #include #include @@ -255,3 +256,4 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor); } +EXPORT_SYMBOL_GPL(nfs_submount); diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 9f502a0c1e59..f5d1cf5f5dc7 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -24,20 +24,6 @@ struct nfs_subversion { int nfs_register_versions(void); void nfs_unregister_versions(void); -#ifdef CONFIG_NFS_V2 -int init_nfs_v2(void); -void exit_nfs_v2(void); -#else /* CONFIG_NFS_V2 */ -static inline int __init init_nfs_v2(void) -{ - return 0; -} - -static inline void exit_nfs_v2(void) -{ -} -#endif /* CONFIG_NFS_V2 */ - #ifdef CONFIG_NFS_V3 int init_nfs_v3(void); void exit_nfs_v3(void); diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c index a9fb69d72816..0a9782c9171a 100644 --- a/fs/nfs/nfs2super.c +++ b/fs/nfs/nfs2super.c @@ -14,13 +14,18 @@ static struct nfs_subversion nfs_v2 = { .sops = &nfs_sops, }; -int __init init_nfs_v2(void) +static int __init init_nfs_v2(void) { register_nfs_version(&nfs_v2); return 0; } -void exit_nfs_v2(void) +static void __exit exit_nfs_v2(void) { unregister_nfs_version(&nfs_v2); } + +MODULE_LICENSE("GPL"); + +module_init(init_nfs_v2); +module_exit(exit_nfs_v2); diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6267b873bbcb..b000e4c0cf83 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -113,6 +113,7 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, compl_ops, NFS_SERVER(inode)->rsize, 0); } +EXPORT_SYMBOL_GPL(nfs_pageio_init_read); void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 8e0da5a6b3c5..999ce7505142 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -289,6 +289,7 @@ struct file_system_type nfs_fs_type = { .kill_sb = nfs_kill_super, .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; +EXPORT_SYMBOL_GPL(nfs_fs_type); struct file_system_type nfs_xdev_fs_type = { .owner = THIS_MODULE, @@ -312,6 +313,7 @@ const struct super_operations nfs_sops = { .show_stats = nfs_show_stats, .remount_fs = nfs_remount, }; +EXPORT_SYMBOL_GPL(nfs_sops); #ifdef CONFIG_NFS_V4 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); @@ -1670,6 +1672,7 @@ struct dentry *nfs_try_mount(int flags, const char *dev_name, return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod); } +EXPORT_SYMBOL_GPL(nfs_try_mount); /* * Split "dev_name" into "hostname:export_path". diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 6ddac54dc67f..1e8d4b043769 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1210,6 +1210,7 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, compl_ops, NFS_SERVER(inode)->wsize, ioflags); } +EXPORT_SYMBOL_GPL(nfs_pageio_init_write); void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) { @@ -1688,6 +1689,7 @@ int nfs_wb_all(struct inode *inode) return sync_inode(inode, &wbc); } +EXPORT_SYMBOL_GPL(nfs_wb_all); int nfs_wb_page_cancel(struct inode *inode, struct page *page) { -- GitLab From 1c606fb74c758beafd98cbad9a9133eadeec2371 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:24 -0400 Subject: [PATCH 4520/5711] NFS: Convert v3 into a module This patch exports symbols and moves over the final structures needed by the v3 module. In addition, I also switch over to using IS_ENABLED() to check if CONFIG_NFS_V3 or CONFIG_NFS_V3_MODULE are set. The module (nfs3.ko) will be created in the same directory as nfs.ko and will be automatically loaded the first time you try to mount over NFS v3. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Kconfig | 2 +- fs/nfs/Makefile | 6 ++++-- fs/nfs/client.c | 5 ----- fs/nfs/dir.c | 1 + fs/nfs/direct.c | 2 +- fs/nfs/inode.c | 3 +++ fs/nfs/internal.h | 2 +- fs/nfs/nfs.h | 14 -------------- fs/nfs/nfs3super.c | 9 +++++++-- fs/nfs/super.c | 6 +++--- fs/nfs/write.c | 8 ++++---- 11 files changed, 25 insertions(+), 33 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6764dbf66d05..f81a729c00e9 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -40,7 +40,7 @@ config NFS_V2 If unsure, say Y. config NFS_V3 - bool "NFS client support for NFS version 3" + tristate "NFS client support for NFS version 3" depends on NFS_FS default y help diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index df61db41bfa8..01846edc5c94 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -9,8 +9,6 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ write.o namespace.o mount_clnt.o \ dns_resolve.o cache_lib.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o -nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o -nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs4super.o nfs4file.o delegation.o idmap.o \ callback.o callback_xdr.o callback_proc.o \ @@ -27,6 +25,10 @@ nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o obj-$(CONFIG_NFS_V2) += nfs2.o nfs2-y := nfs2super.o proc.o nfs2xdr.o +obj-$(CONFIG_NFS_V3) += nfs3.o +nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o +nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o + obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/fs/nfs/client.c b/fs/nfs/client.c index fa8acf510333..8687b6b6edc1 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -149,10 +149,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version); */ int __init nfs_register_versions(void) { - int err = init_nfs_v3(); - if (err) - return err; - return init_nfs_v4(); } @@ -161,7 +157,6 @@ int __init nfs_register_versions(void) */ void nfs_unregister_versions(void) { - exit_nfs_v3(); exit_nfs_v4(); } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c382a6d5e177..55438c970cbf 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1981,6 +1981,7 @@ void nfs_access_zap_cache(struct inode *inode) spin_unlock(&nfs_access_lru_lock); nfs_access_free_list(&head); } +EXPORT_SYMBOL_GPL(nfs_access_zap_cache); static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) { diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 42dce909ec70..899238156b11 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -460,7 +460,7 @@ static void nfs_inode_dio_write_done(struct inode *inode) inode_dio_done(inode); } -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) { struct nfs_pageio_descriptor desc; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f358b976e9e6..78dfc3e895ec 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -186,6 +186,7 @@ void nfs_zap_acl_cache(struct inode *inode) NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL; spin_unlock(&inode->i_lock); } +EXPORT_SYMBOL_GPL(nfs_zap_acl_cache); void nfs_invalidate_atime(struct inode *inode) { @@ -847,6 +848,7 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) return NFS_STALE(inode) ? -ESTALE : 0; return __nfs_revalidate_inode(server, inode); } +EXPORT_SYMBOL_GPL(nfs_revalidate_inode); static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) { @@ -1213,6 +1215,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) spin_unlock(&inode->i_lock); return status; } +EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); /** * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 4174faf73ec1..64f0dc41a9b7 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -224,7 +224,7 @@ int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *); #endif /* nfs3client.c */ -#ifdef CONFIG_NFS_V3 +#if IS_ENABLED(CONFIG_NFS_V3) struct nfs_server *nfs3_create_server(struct nfs_mount_info *, struct nfs_subversion *); struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t); diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index f5d1cf5f5dc7..3e1b84baa57f 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -24,20 +24,6 @@ struct nfs_subversion { int nfs_register_versions(void); void nfs_unregister_versions(void); -#ifdef CONFIG_NFS_V3 -int init_nfs_v3(void); -void exit_nfs_v3(void); -#else /* CONFIG_NFS_V3 */ -static inline int __init init_nfs_v3(void) -{ - return 0; -} - -static inline void exit_nfs_v3(void) -{ -} -#endif /* CONFIG_NFS_V3 */ - #ifdef CONFIG_NFS_V4 int init_nfs_v4(void); void exit_nfs_v4(void); diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c index 8378090b8104..cc471c725230 100644 --- a/fs/nfs/nfs3super.c +++ b/fs/nfs/nfs3super.c @@ -14,13 +14,18 @@ static struct nfs_subversion nfs_v3 = { .sops = &nfs_sops, }; -int __init init_nfs_v3(void) +static int __init init_nfs_v3(void) { register_nfs_version(&nfs_v3); return 0; } -void exit_nfs_v3(void) +static void __exit exit_nfs_v3(void) { unregister_nfs_version(&nfs_v3); } + +MODULE_LICENSE("GPL"); + +module_init(init_nfs_v3); +module_exit(exit_nfs_v3); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 999ce7505142..558a85c9594a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -69,7 +69,7 @@ #define NFSDBG_FACILITY NFSDBG_VFS #define NFS_TEXT_DATA 1 -#ifdef CONFIG_NFS_V3 +#if IS_ENABLED(CONFIG_NFS_V3) #define NFS_DEFAULT_VERSION 3 #else #define NFS_DEFAULT_VERSION 2 @@ -1876,7 +1876,7 @@ static int nfs23_validate_mount_data(void *options, return NFS_TEXT_DATA; } -#ifndef CONFIG_NFS_V3 +#if !IS_ENABLED(CONFIG_NFS_V3) if (args->version == 3) goto out_v3_not_compiled; #endif /* !CONFIG_NFS_V3 */ @@ -1896,7 +1896,7 @@ out_no_sec: dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n"); return -EINVAL; -#ifndef CONFIG_NFS_V3 +#if !IS_ENABLED(CONFIG_NFS_V3) out_v3_not_compiled: dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n"); return -EPROTONOSUPPORT; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 1e8d4b043769..f268fe4f2785 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -446,7 +446,7 @@ nfs_mark_request_dirty(struct nfs_page *req) __set_page_dirty_nobuffers(req->wb_page); } -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /** * nfs_request_add_commit_list - add request to a commit list * @req: pointer to a struct nfs_page @@ -636,7 +636,7 @@ out: hdr->release(hdr); } -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo) { @@ -1298,7 +1298,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) return; nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count); -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (resp->verf->committed < argp->stable && task->tk_status >= 0) { /* We tried a write call, but the server did not * commit data to stable storage even though we @@ -1358,7 +1358,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) } -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) { int ret; -- GitLab From 89d77c8fa8e6d1cb7e2cce95b428be30ddcc6f23 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 30 Jul 2012 16:05:25 -0400 Subject: [PATCH 4521/5711] NFS: Convert v4 into a module This patch exports symbols needed by the v4 module. In addition, I also switch over to using IS_ENABLED() to check if CONFIG_NFS_V4 or CONFIG_NFS_V4_MODULE are set. The module (nfs4.ko) will be created in the same directory as nfs.ko and will be automatically loaded the first time you try to mount over NFS v4. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Kconfig | 2 +- fs/nfs/Makefile | 19 +++++------- fs/nfs/callback.h | 2 +- fs/nfs/client.c | 34 +++++++++------------ fs/nfs/delegation.h | 2 +- fs/nfs/dir.c | 6 +++- fs/nfs/direct.c | 2 +- fs/nfs/dns_resolve.c | 4 +++ fs/nfs/file.c | 13 ++++++++ fs/nfs/inode.c | 64 +++++++++++++++++++-------------------- fs/nfs/internal.h | 8 ++--- fs/nfs/namespace.c | 2 ++ fs/nfs/netns.h | 2 +- fs/nfs/nfs.h | 17 ----------- fs/nfs/nfs4_fs.h | 5 ++- fs/nfs/nfs4super.c | 9 ++++-- fs/nfs/pagelist.c | 4 +++ fs/nfs/pnfs.c | 2 ++ fs/nfs/read.c | 4 +++ fs/nfs/super.c | 41 +++++++++++++++++++------ fs/nfs/write.c | 13 +++++--- include/linux/nfs_fs.h | 6 ++-- include/linux/nfs_fs_sb.h | 6 ++-- include/linux/nfs_idmap.h | 2 +- include/linux/nfs_xdr.h | 2 +- 25 files changed, 155 insertions(+), 116 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index f81a729c00e9..195c1ea6151a 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -72,7 +72,7 @@ config NFS_V3_ACL If unsure, say N. config NFS_V4 - bool "NFS client support for NFS version 4" + tristate "NFS client support for NFS version 4" depends on NFS_FS select SUNRPC_GSS select KEYS diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 01846edc5c94..8bf3a3f6925a 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -9,17 +9,7 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ write.o namespace.o mount_clnt.o \ dns_resolve.o cache_lib.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o -nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ - nfs4super.o nfs4file.o delegation.o idmap.o \ - callback.o callback_xdr.o callback_proc.o \ - nfs4namespace.o nfs4getroot.o nfs4client.o -nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o - -ifeq ($(CONFIG_SYSCTL), y) -nfs-y += sysctl.o -nfs-$(CONFIG_NFS_V4) += nfs4sysctl.o -endif - +nfs-$(CONFIG_SYSCTL) += sysctl.o nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o obj-$(CONFIG_NFS_V2) += nfs2.o @@ -29,6 +19,13 @@ obj-$(CONFIG_NFS_V3) += nfs3.o nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o +obj-$(CONFIG_NFS_V4) += nfs4.o +nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ + delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ + nfs4namespace.o nfs4getroot.o nfs4client.o +nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o +nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o + obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index a5527c90a5aa..b44d7b128b71 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -192,7 +192,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_process_state *cps); extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy, struct cb_process_state *cps); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); extern void nfs_callback_down(int minorversion); extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 8687b6b6edc1..9fc0d9dfc91b 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -142,24 +142,6 @@ void unregister_nfs_version(struct nfs_subversion *nfs) } EXPORT_SYMBOL_GPL(unregister_nfs_version); -/* - * Preload all configured NFS versions during module init. - * This function should be edited after each protocol is converted, - * and eventually removed. - */ -int __init nfs_register_versions(void) -{ - return init_nfs_v4(); -} - -/* - * Remove each pre-loaded NFS version - */ -void nfs_unregister_versions(void) -{ - exit_nfs_v4(); -} - /* * Allocate a shared client record * @@ -214,7 +196,7 @@ error_0: } EXPORT_SYMBOL_GPL(nfs_alloc_client); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ void nfs_cleanup_cb_ident_idr(struct net *net) { @@ -390,6 +372,7 @@ int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, } return 0; } +EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr); #endif /* CONFIG_NFS_V4_1 */ /* @@ -456,6 +439,7 @@ int nfs_wait_client_init_complete(const struct nfs_client *clp) return wait_event_killable(nfs_client_active_wq, nfs_client_init_is_complete(clp)); } +EXPORT_SYMBOL_GPL(nfs_wait_client_init_complete); /* * Found an existing client. Make sure it's ready before returning. @@ -530,6 +514,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, cl_init->hostname ?: "", PTR_ERR(new)); return new; } +EXPORT_SYMBOL_GPL(nfs_get_client); /* * Mark a server as ready or failed @@ -540,6 +525,7 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state) clp->cl_cons_state = state; wake_up_all(&nfs_client_active_wq); } +EXPORT_SYMBOL_GPL(nfs_mark_client_ready); /* * Initialise the timeout values for a connection @@ -581,6 +567,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto, BUG(); } } +EXPORT_SYMBOL_GPL(nfs_init_timeout_values); /* * Create an RPC client handle @@ -620,6 +607,7 @@ int nfs_create_rpc_client(struct nfs_client *clp, clp->cl_rpcclient = clnt; return 0; } +EXPORT_SYMBOL_GPL(nfs_create_rpc_client); /* * Version 2 or 3 client destruction @@ -706,6 +694,7 @@ int nfs_init_server_rpcclient(struct nfs_server *server, return 0; } +EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient); /** * nfs_init_client - Initialise an NFS2 or NFS3 client @@ -932,6 +921,7 @@ out_error: dprintk("nfs_probe_fsinfo: error = %d\n", -error); return error; } +EXPORT_SYMBOL_GPL(nfs_probe_fsinfo); /* * Copy useful information when duplicating a server record @@ -948,6 +938,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour target->caps = source->caps; target->options = source->options; } +EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); void nfs_server_insert_lists(struct nfs_server *server) { @@ -961,6 +952,7 @@ void nfs_server_insert_lists(struct nfs_server *server) spin_unlock(&nn->nfs_client_lock); } +EXPORT_SYMBOL_GPL(nfs_server_insert_lists); static void nfs_server_remove_lists(struct nfs_server *server) { @@ -1020,6 +1012,7 @@ struct nfs_server *nfs_alloc_server(void) return server; } +EXPORT_SYMBOL_GPL(nfs_alloc_server); /* * Free up a server record @@ -1048,6 +1041,7 @@ void nfs_free_server(struct nfs_server *server) nfs_release_automount_timer(); dprintk("<-- nfs_free_server()\n"); } +EXPORT_SYMBOL_GPL(nfs_free_server); /* * Create a version 2 or 3 volume record @@ -1193,7 +1187,7 @@ void nfs_clients_init(struct net *net) INIT_LIST_HEAD(&nn->nfs_client_list); INIT_LIST_HEAD(&nn->nfs_volume_list); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) idr_init(&nn->cb_ident_idr); #endif spin_lock_init(&nn->nfs_client_lock); diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 1f3ccd934635..bbc6a4dba0d8 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -8,7 +8,7 @@ #ifndef FS_NFS_DELEGATION_H #define FS_NFS_DELEGATION_H -#if defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V4) /* * NFSv4 delegation */ diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 55438c970cbf..627f108ede23 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -936,6 +936,7 @@ void nfs_force_lookup_revalidate(struct inode *dir) { NFS_I(dir)->cache_change_attribute++; } +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate); /* * A check for whether or not the parent directory has changed. @@ -1267,7 +1268,7 @@ out: } EXPORT_SYMBOL_GPL(nfs_lookup); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static int nfs4_lookup_revalidate(struct dentry *, unsigned int); const struct dentry_operations nfs4_dentry_operations = { @@ -1277,6 +1278,7 @@ const struct dentry_operations nfs4_dentry_operations = { .d_automount = nfs_d_automount, .d_release = nfs_d_release, }; +EXPORT_SYMBOL_GPL(nfs4_dentry_operations); static fmode_t flags_to_mode(int flags) { @@ -1419,6 +1421,7 @@ no_open: return finish_no_open(file, res); } +EXPORT_SYMBOL_GPL(nfs_atomic_open); static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags) { @@ -2142,6 +2145,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) { return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); } +EXPORT_SYMBOL_GPL(nfs_may_open); int nfs_permission(struct inode *inode, int mask) { diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 899238156b11..b7b4f80968b5 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -460,7 +460,7 @@ static void nfs_inode_dio_write_done(struct inode *inode) inode_dio_done(inode); } -#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) { struct nfs_pageio_descriptor desc; diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index b3924b8a6000..31c26c4dcc23 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -8,6 +8,7 @@ #ifdef CONFIG_NFS_USE_KERNEL_DNS +#include #include #include #include "dns_resolve.h" @@ -27,9 +28,11 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, kfree(ip_addr); return ret; } +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); #else +#include #include #include #include @@ -345,6 +348,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, ret = -ESRCH; return ret; } +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); int nfs_dns_resolver_cache_init(struct net *net) { diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5b3e70389553..1557978ca7b3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -53,6 +53,7 @@ int nfs_check_flags(int flags) return 0; } +EXPORT_SYMBOL_GPL(nfs_check_flags); /* * Open file @@ -85,6 +86,7 @@ nfs_file_release(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSRELEASE); return nfs_release(inode, filp); } +EXPORT_SYMBOL_GPL(nfs_file_release); /** * nfs_revalidate_size - Revalidate the file size @@ -138,6 +140,7 @@ loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) return generic_file_llseek(filp, offset, origin); } +EXPORT_SYMBOL_GPL(nfs_file_llseek); /* * Flush all dirty pages, and check for write errors. @@ -166,6 +169,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) /* Flush writes to the server and return any errors */ return vfs_fsync(file, 0); } +EXPORT_SYMBOL_GPL(nfs_file_flush); ssize_t nfs_file_read(struct kiocb *iocb, const struct iovec *iov, @@ -190,6 +194,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, } return result; } +EXPORT_SYMBOL_GPL(nfs_file_read); ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, @@ -212,6 +217,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, } return res; } +EXPORT_SYMBOL_GPL(nfs_file_splice_read); int nfs_file_mmap(struct file * file, struct vm_area_struct * vma) @@ -233,6 +239,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) } return status; } +EXPORT_SYMBOL_GPL(nfs_file_mmap); /* * Flush any dirty pages for this process, and check for write errors. @@ -271,6 +278,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) ret = status; return ret; } +EXPORT_SYMBOL_GPL(nfs_file_fsync_commit); static int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) @@ -615,6 +623,7 @@ out_swapfile: printk(KERN_INFO "NFS: attempt to write to active swap file!\n"); goto out; } +EXPORT_SYMBOL_GPL(nfs_file_write); ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, struct file *filp, loff_t *ppos, @@ -646,6 +655,7 @@ ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); return ret; } +EXPORT_SYMBOL_GPL(nfs_file_splice_write); static int do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) @@ -806,6 +816,7 @@ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) out_err: return ret; } +EXPORT_SYMBOL_GPL(nfs_lock); /* * Lock a (portion of) a file @@ -835,6 +846,7 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) return do_unlk(filp, cmd, fl, is_local); return do_setlk(filp, cmd, fl, is_local); } +EXPORT_SYMBOL_GPL(nfs_flock); /* * There is no protocol support for leases, so we have no way to implement @@ -847,6 +859,7 @@ int nfs_setlease(struct file *file, long arg, struct file_lock **fl) file->f_path.dentry->d_name.name, arg); return -EINVAL; } +EXPORT_SYMBOL_GPL(nfs_setlease); const struct file_operations nfs_file_operations = { .llseek = nfs_file_llseek, diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 78dfc3e895ec..2ed6138f32ad 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -82,6 +82,7 @@ int nfs_wait_bit_killable(void *word) freezable_schedule(); return 0; } +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); /** * nfs_compat_user_ino64 - returns the user-visible inode number @@ -117,6 +118,7 @@ void nfs_clear_inode(struct inode *inode) nfs_access_zap_cache(inode); nfs_fscache_release_inode_cookie(inode); } +EXPORT_SYMBOL_GPL(nfs_clear_inode); void nfs_evict_inode(struct inode *inode) { @@ -393,6 +395,7 @@ out_no_inode: dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode)); goto out; } +EXPORT_SYMBOL_GPL(nfs_fhget); #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN) @@ -655,6 +658,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f ctx->mdsthreshold = NULL; return ctx; } +EXPORT_SYMBOL_GPL(alloc_nfs_open_context); struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) { @@ -662,6 +666,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) atomic_inc(&ctx->lock_context.count); return ctx; } +EXPORT_SYMBOL_GPL(get_nfs_open_context); static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) { @@ -689,6 +694,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx) { __put_nfs_open_context(ctx, 0); } +EXPORT_SYMBOL_GPL(put_nfs_open_context); /* * Ensure that mmap has a recent RPC credential for use when writing out @@ -704,6 +710,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) list_add(&ctx->list, &nfsi->open_files); spin_unlock(&inode->i_lock); } +EXPORT_SYMBOL_GPL(nfs_file_set_open_context); /* * Given an inode, search for an open context with the desired characteristics @@ -1497,11 +1504,12 @@ struct inode *nfs_alloc_inode(struct super_block *sb) nfsi->acl_access = ERR_PTR(-EAGAIN); nfsi->acl_default = ERR_PTR(-EAGAIN); #endif -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) nfsi->nfs4_acl = NULL; #endif /* CONFIG_NFS_V4 */ return &nfsi->vfs_inode; } +EXPORT_SYMBOL_GPL(nfs_alloc_inode); static void nfs_i_callback(struct rcu_head *head) { @@ -1513,10 +1521,11 @@ void nfs_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, nfs_i_callback); } +EXPORT_SYMBOL_GPL(nfs_destroy_inode); static inline void nfs4_init_once(struct nfs_inode *nfsi) { -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) INIT_LIST_HEAD(&nfsi->open_states); nfsi->delegation = NULL; nfsi->delegation_state = 0; @@ -1562,6 +1571,7 @@ static void nfs_destroy_inodecache(void) } struct workqueue_struct *nfsiod_workqueue; +EXPORT_SYMBOL_GPL(nfsiod_workqueue); /* * start up the nfsiod workqueue @@ -1622,90 +1632,80 @@ static int __init init_nfs_fs(void) err = nfs_dns_resolver_init(); if (err < 0) - goto out11; + goto out10;; err = register_pernet_subsys(&nfs_net_ops); if (err < 0) - goto out10; + goto out9; err = nfs_fscache_register(); if (err < 0) - goto out9; + goto out8; err = nfsiod_start(); if (err) - goto out8; + goto out7; err = nfs_fs_proc_init(); if (err) - goto out7; + goto out6; err = nfs_init_nfspagecache(); if (err) - goto out6; + goto out5; err = nfs_init_inodecache(); if (err) - goto out5; + goto out4; err = nfs_init_readpagecache(); if (err) - goto out4; + goto out3; err = nfs_init_writepagecache(); if (err) - goto out3; + goto out2; err = nfs_init_directcache(); if (err) - goto out2; + goto out1; #ifdef CONFIG_PROC_FS rpc_proc_register(&init_net, &nfs_rpcstat); #endif - - err = nfs_register_versions(); - if (err) - goto out1; - if ((err = register_nfs_fs()) != 0) goto out0; return 0; out0: - nfs_unregister_versions(); -out1: #ifdef CONFIG_PROC_FS rpc_proc_unregister(&init_net, "nfs"); #endif nfs_destroy_directcache(); -out2: +out1: nfs_destroy_writepagecache(); -out3: +out2: nfs_destroy_readpagecache(); -out4: +out3: nfs_destroy_inodecache(); -out5: +out4: nfs_destroy_nfspagecache(); -out6: +out5: nfs_fs_proc_exit(); -out7: +out6: nfsiod_stop(); -out8: +out7: nfs_fscache_unregister(); -out9: +out8: unregister_pernet_subsys(&nfs_net_ops); -out10: +out9: nfs_dns_resolver_destroy(); -out11: +out10: return err; } static void __exit exit_nfs_fs(void) { -#ifdef CONFIG_NFS_V4 - exit_nfs_v4(); -#endif nfs_destroy_directcache(); nfs_destroy_writepagecache(); nfs_destroy_readpagecache(); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 64f0dc41a9b7..8865538b26b6 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -262,7 +262,7 @@ extern int nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, int); /* nfs4xdr.c */ -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern int nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, int); #endif @@ -272,7 +272,7 @@ extern const u32 nfs41_maxwrite_overhead; #endif /* nfs4proc.c */ -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern struct rpc_procinfo nfs4_procedures[]; #endif @@ -328,7 +328,7 @@ extern int nfs_wait_bit_killable(void *word); extern const struct super_operations nfs_sops; extern struct file_system_type nfs_fs_type; extern struct file_system_type nfs_xdev_fs_type; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern struct file_system_type nfs4_xdev_fs_type; extern struct file_system_type nfs4_referral_fs_type; #endif @@ -364,7 +364,7 @@ struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *, /* getroot.c */ extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, const char *); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, const char *); diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 2a3b170e88e0..655925373b91 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -113,6 +113,7 @@ Elong_unlock: Elong: return ERR_PTR(-ENAMETOOLONG); } +EXPORT_SYMBOL_GPL(nfs_path); /* * nfs_d_automount - Handle crossing a mountpoint on the server @@ -241,6 +242,7 @@ out: dprintk("<-- nfs_do_submount() = %p\n", mnt); return mnt; } +EXPORT_SYMBOL_GPL(nfs_do_submount); struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr) diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 8a6394edb8b0..0539de1b8d1f 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -20,7 +20,7 @@ struct nfs_net { wait_queue_head_t bl_wq; struct list_head nfs_client_list; struct list_head nfs_volume_list; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) struct idr cb_ident_idr; /* Protected by nfs_client_lock */ #endif spinlock_t nfs_client_lock; diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 3e1b84baa57f..43679df56cd0 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -21,23 +21,6 @@ struct nfs_subversion { struct list_head list; /* List of NFS versions */ }; -int nfs_register_versions(void); -void nfs_unregister_versions(void); - -#ifdef CONFIG_NFS_V4 -int init_nfs_v4(void); -void exit_nfs_v4(void); -#else /* CONFIG_NFS_V4 */ -static inline int __init init_nfs_v4(void) -{ - return 0; -} - -static inline void exit_nfs_v4(void) -{ -} -#endif /* CONFIG_NFS_V4 */ - struct nfs_subversion *get_nfs_version(unsigned int); void put_nfs_version(struct nfs_subversion *); void register_nfs_version(struct nfs_subversion *); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index bafe5186c9cd..3b950dd81e81 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -9,7 +9,7 @@ #ifndef __LINUX_FS_NFS_NFS4_FS_H #define __LINUX_FS_NFS_NFS4_FS_H -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) struct idmap; @@ -365,11 +365,10 @@ extern const nfs4_stateid zero_stateid; struct nfs_mount_info; extern struct nfs_subversion nfs_v4; struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *); -int init_nfs_v4(void); -void exit_nfs_v4(void); extern bool nfs4_disable_idmapping; extern unsigned short max_session_slots; extern unsigned short send_implementation_id; + /* nfs4sysctl.c */ #ifdef CONFIG_SYSCTL int nfs4_register_sysctl(void); diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 1c825f3bef51..12a31a9dbcdd 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -332,7 +332,7 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, } -int __init init_nfs_v4(void) +static int __init init_nfs_v4(void) { int err; @@ -358,10 +358,15 @@ out: return err; } -void exit_nfs_v4(void) +static void __exit exit_nfs_v4(void) { unregister_nfs_version(&nfs_v4); unregister_filesystem(&nfs4_fs_type); nfs4_unregister_sysctl(); nfs_idmap_quit(); } + +MODULE_LICENSE("GPL"); + +module_init(init_nfs_v4); +module_exit(exit_nfs_v4); diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index aed913c833f4..1e7d8879dae6 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -54,6 +54,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, if (hdr->completion_ops->init_hdr) hdr->completion_ops->init_hdr(hdr); } +EXPORT_SYMBOL_GPL(nfs_pgheader_init); void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) { @@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, desc->pg_lseg = NULL; desc->pg_dreq = NULL; } +EXPORT_SYMBOL_GPL(nfs_pageio_init); /** * nfs_can_coalesce_requests - test two requests for compatibility @@ -409,6 +411,7 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, } while (ret); return ret; } +EXPORT_SYMBOL_GPL(nfs_pageio_add_request); /** * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor @@ -424,6 +427,7 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) break; } } +EXPORT_SYMBOL_GPL(nfs_pageio_complete); /** * nfs_pageio_cond_complete - Conditional I/O completion diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 7fbd25afe418..76875bfcf19c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1407,6 +1407,7 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr) put_lseg(hdr->lseg); nfs_writehdr_free(hdr); } +EXPORT_SYMBOL_GPL(pnfs_writehdr_free); int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) @@ -1561,6 +1562,7 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr) put_lseg(hdr->lseg); nfs_readhdr_free(hdr); } +EXPORT_SYMBOL_GPL(pnfs_readhdr_free); int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index b000e4c0cf83..6935e401ad76 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -48,6 +48,7 @@ struct nfs_read_header *nfs_readhdr_alloc(void) } return rhdr; } +EXPORT_SYMBOL_GPL(nfs_readhdr_alloc); static struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr, unsigned int pagecount) @@ -80,6 +81,7 @@ void nfs_readhdr_free(struct nfs_pgio_header *hdr) kmem_cache_free(nfs_rdata_cachep, rhdr); } +EXPORT_SYMBOL_GPL(nfs_readhdr_free); void nfs_readdata_release(struct nfs_read_data *rdata) { @@ -96,6 +98,7 @@ void nfs_readdata_release(struct nfs_read_data *rdata) if (atomic_dec_and_test(&hdr->refcnt)) hdr->completion_ops->completion(hdr); } +EXPORT_SYMBOL_GPL(nfs_readdata_release); static int nfs_return_empty_page(struct page *page) @@ -398,6 +401,7 @@ int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, return nfs_pagein_multi(desc, hdr); return nfs_pagein_one(desc, hdr); } +EXPORT_SYMBOL_GPL(nfs_generic_pagein); static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 558a85c9594a..ac6a3c55dce4 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -315,7 +315,7 @@ const struct super_operations nfs_sops = { }; EXPORT_SYMBOL_GPL(nfs_sops); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); static int nfs4_validate_mount_data(void *options, struct nfs_parsed_mount_data *args, const char *dev_name); @@ -366,6 +366,7 @@ void nfs_sb_active(struct super_block *sb) if (atomic_inc_return(&server->active) == 1) atomic_inc(&sb->s_active); } +EXPORT_SYMBOL_GPL(nfs_sb_active); void nfs_sb_deactive(struct super_block *sb) { @@ -374,6 +375,7 @@ void nfs_sb_deactive(struct super_block *sb) if (atomic_dec_and_test(&server->active)) deactivate_super(sb); } +EXPORT_SYMBOL_GPL(nfs_sb_deactive); /* * Deliver file system statistics to userspace @@ -439,6 +441,7 @@ int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) dprintk("%s: statfs error = %d\n", __func__, -error); return error; } +EXPORT_SYMBOL_GPL(nfs_statfs); /* * Map the security flavour number to a name @@ -544,7 +547,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, nfs_show_mountd_netid(m, nfss, showdefaults); } -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) { @@ -675,8 +678,9 @@ int nfs_show_options(struct seq_file *m, struct dentry *root) return 0; } +EXPORT_SYMBOL_GPL(nfs_show_options); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) #ifdef CONFIG_NFS_V4_1 static void show_sessions(struct seq_file *m, struct nfs_server *server) { @@ -709,7 +713,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss) } } #else -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static void show_pnfs(struct seq_file *m, struct nfs_server *server) { } @@ -734,12 +738,14 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) free_page((unsigned long)page); return err; } +EXPORT_SYMBOL_GPL(nfs_show_devname); int nfs_show_path(struct seq_file *m, struct dentry *dentry) { seq_puts(m, "/"); return 0; } +EXPORT_SYMBOL_GPL(nfs_show_path); /* * Present statistical information for this VFS mountpoint @@ -774,7 +780,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) seq_printf(m, ",bsize=%u", nfss->bsize); seq_printf(m, ",namlen=%u", nfss->namelen); -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) if (nfss->nfs_client->rpc_ops->version == 4) { seq_printf(m, "\n\tnfsv4:\t"); seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); @@ -832,6 +838,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) return 0; } +EXPORT_SYMBOL_GPL(nfs_show_stats); /* * Begin unmount by attempting to remove all automounted mountpoints we added @@ -851,6 +858,7 @@ void nfs_umount_begin(struct super_block *sb) if (!IS_ERR(rpc)) rpc_killall_tasks(rpc); } +EXPORT_SYMBOL_GPL(nfs_umount_begin); static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) { @@ -1915,7 +1923,7 @@ out_invalid_fh: return -EINVAL; } -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static int nfs_validate_mount_data(struct file_system_type *fs_type, void *options, struct nfs_parsed_mount_data *args, @@ -1953,7 +1961,7 @@ static int nfs_validate_text_mount_data(void *options, goto out_no_address; if (args->version == 4) { -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) port = NFS_PORT; max_namelen = NFS4_MAXNAMLEN; max_pathlen = NFS4_MAXPATHLEN; @@ -1976,7 +1984,7 @@ static int nfs_validate_text_mount_data(void *options, &args->nfs_server.export_path, max_pathlen); -#ifndef CONFIG_NFS_V4 +#if !IS_ENABLED(CONFIG_NFS_V4) out_v4_not_compiled: dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n"); return -EPROTONOSUPPORT; @@ -2075,6 +2083,7 @@ out: kfree(data); return error; } +EXPORT_SYMBOL_GPL(nfs_remount); /* * Initialise the common bits of the superblock @@ -2123,6 +2132,7 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) nfs_initialise_sb(sb); } +EXPORT_SYMBOL_GPL(nfs_fill_super); /* * Finish setting up a cloned NFS2/3/4 superblock @@ -2292,6 +2302,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, { return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); } +EXPORT_SYMBOL_GPL(nfs_set_sb_security); int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, struct nfs_mount_info *mount_info) @@ -2302,6 +2313,7 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, return -ESTALE; return 0; } +EXPORT_SYMBOL_GPL(nfs_clone_sb_security); struct dentry *nfs_fs_mount_common(struct nfs_server *server, int flags, const char *dev_name, @@ -2375,6 +2387,7 @@ error_splat_bdi: deactivate_locked_super(s); goto out; } +EXPORT_SYMBOL_GPL(nfs_fs_mount_common); struct dentry *nfs_fs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) @@ -2415,6 +2428,7 @@ out: nfs_free_fhandle(mount_info.mntfh); return mntroot; } +EXPORT_SYMBOL_GPL(nfs_fs_mount); /* * Ensure that we unregister the bdi before kill_anon_super @@ -2426,6 +2440,7 @@ void nfs_put_super(struct super_block *s) bdi_unregister(&server->backing_dev_info); } +EXPORT_SYMBOL_GPL(nfs_put_super); /* * Destroy an NFS2/3 superblock @@ -2438,6 +2453,7 @@ void nfs_kill_super(struct super_block *s) nfs_fscache_release_super_cookie(s); nfs_free_server(server); } +EXPORT_SYMBOL_GPL(nfs_kill_super); /* * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) @@ -2478,7 +2494,7 @@ out_err: goto out; } -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) { @@ -2590,6 +2606,13 @@ bool nfs4_disable_idmapping = true; unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; unsigned short send_implementation_id = 1; +EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport); +EXPORT_SYMBOL_GPL(nfs_callback_tcpport); +EXPORT_SYMBOL_GPL(nfs_idmap_cache_timeout); +EXPORT_SYMBOL_GPL(nfs4_disable_idmapping); +EXPORT_SYMBOL_GPL(max_session_slots); +EXPORT_SYMBOL_GPL(send_implementation_id); + #define NFS_CALLBACK_MAXPORTNR (65535U) static int param_set_portnr(const char *val, const struct kernel_param *kp) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f268fe4f2785..e4a2ad2059bd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -84,6 +84,7 @@ struct nfs_write_header *nfs_writehdr_alloc(void) } return p; } +EXPORT_SYMBOL_GPL(nfs_writehdr_alloc); static struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr, unsigned int pagecount) @@ -115,6 +116,7 @@ void nfs_writehdr_free(struct nfs_pgio_header *hdr) struct nfs_write_header *whdr = container_of(hdr, struct nfs_write_header, header); mempool_free(whdr, nfs_wdata_mempool); } +EXPORT_SYMBOL_GPL(nfs_writehdr_free); void nfs_writedata_release(struct nfs_write_data *wdata) { @@ -131,6 +133,7 @@ void nfs_writedata_release(struct nfs_write_data *wdata) if (atomic_dec_and_test(&hdr->refcnt)) hdr->completion_ops->completion(hdr); } +EXPORT_SYMBOL_GPL(nfs_writedata_release); static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) { @@ -446,7 +449,7 @@ nfs_mark_request_dirty(struct nfs_page *req) __set_page_dirty_nobuffers(req->wb_page); } -#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) /** * nfs_request_add_commit_list - add request to a commit list * @req: pointer to a struct nfs_page @@ -636,7 +639,7 @@ out: hdr->release(hdr); } -#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) static unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo) { @@ -1173,6 +1176,7 @@ int nfs_generic_flush(struct nfs_pageio_descriptor *desc, return nfs_flush_multi(desc, hdr); return nfs_flush_one(desc, hdr); } +EXPORT_SYMBOL_GPL(nfs_generic_flush); static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) { @@ -1298,7 +1302,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) return; nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count); -#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) if (resp->verf->committed < argp->stable && task->tk_status >= 0) { /* We tried a write call, but the server did not * commit data to stable storage even though we @@ -1358,7 +1362,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) } -#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) { int ret; @@ -1674,6 +1678,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) { return nfs_commit_unstable_pages(inode, wbc); } +EXPORT_SYMBOL_GPL(nfs_write_inode); /* * flush the inode to disk. diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 4b6043c20f77..2889877318bc 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -191,7 +191,7 @@ struct nfs_inode { struct hlist_head silly_list; wait_queue_head_t waitqueue; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) struct nfs4_cached_acl *nfs4_acl; /* NFSv4 state */ struct list_head open_states; @@ -428,7 +428,7 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/ * linux/fs/nfs/file.c */ extern const struct file_operations nfs_file_operations; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) extern const struct file_operations nfs4_file_operations; #endif /* CONFIG_NFS_V4 */ extern const struct address_space_operations nfs_file_aops; @@ -538,7 +538,7 @@ extern void nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); extern int nfs_wb_all(struct inode *inode); extern int nfs_wb_page(struct inode *inode, struct page* page); extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); -#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) extern int nfs_commit_inode(struct inode *, int); extern struct nfs_commit_data *nfs_commitdata_alloc(void); extern void nfs_commit_free(struct nfs_commit_data *data); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 6039297801f4..310c63c8ab2c 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -53,7 +53,7 @@ struct nfs_client { u32 cl_minorversion;/* NFSv4 minorversion */ struct rpc_cred *cl_machine_cred; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) u64 cl_clientid; /* constant */ nfs4_verifier cl_confirm; /* Clientid verifier */ unsigned long cl_state; @@ -138,7 +138,7 @@ struct nfs_server { #endif u32 pnfs_blksize; /* layout_blksize attr */ -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) u32 attr_bitmask[3];/* V4 bitmask representing the set of attributes supported on this filesystem */ @@ -201,7 +201,7 @@ struct nfs_server { #define NFS4_MAX_SLOT_TABLE (256U) #define NFS4_NO_SLOT ((u32)-1) -#if defined(CONFIG_NFS_V4) +#if IS_ENABLED(CONFIG_NFS_V4) /* Sessions */ #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h index 7eed2012d288..ece91c57ad79 100644 --- a/include/linux/nfs_idmap.h +++ b/include/linux/nfs_idmap.h @@ -69,7 +69,7 @@ struct nfs_server; struct nfs_fattr; struct nfs4_string; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) int nfs_idmap_init(void); void nfs_idmap_quit(void); #else diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 631182062994..00485e084394 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -824,7 +824,7 @@ struct nfs3_getaclres { struct posix_acl * acl_default; }; -#ifdef CONFIG_NFS_V4 +#if IS_ENABLED(CONFIG_NFS_V4) typedef u64 clientid4; -- GitLab From 16d18b16ace670641de74e6fe8005029b4057559 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Jul 2012 07:48:52 -0300 Subject: [PATCH 4522/5711] [media] Fix DV_TIMINGS_CAP documentation This patch fixes the DV_TIMINGS_CAP documentation: part of it was copy-and-paste from the ENUM_DV_TIMINGS documentation. Regards, Hans Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-dv-timings-cap.xml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index 6673ce582050..cd7720d404ea 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -54,15 +54,9 @@ interface and may change in the future. - To query the available timings, applications initialize the -index field and zero the reserved array of &v4l2-dv-timings-cap; -and call the VIDIOC_DV_TIMINGS_CAP ioctl with a pointer to this -structure. Drivers fill the rest of the structure or return an -&EINVAL; when the index is out of bounds. To enumerate all supported DV timings, -applications shall begin at index zero, incrementing by one until the -driver returns EINVAL. Note that drivers may enumerate a -different set of DV timings after switching the video input or -output. + To query the capabilities of the DV receiver/transmitter applications can call +this ioctl and the driver will fill in the structure. Note that drivers may return +different values after switching the video input or output.
struct <structname>v4l2_bt_timings_cap</structname> @@ -115,7 +109,7 @@ output. __u32 reserved[16] - + Reserved for future extensions. Drivers must set the array to zero. -- GitLab From c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Wed, 11 Jul 2012 11:29:33 -0300 Subject: [PATCH 4523/5711] [media] adv7180.c: convert to v4l2 control framework [mchehab@redhat.com: fix checkpatch.pl ERROR: Macros with complex values should be enclosed in parenthesis] Signed-off-by: Federico Vaga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7180.c | 235 ++++++++++++---------------------- 1 file changed, 84 insertions(+), 151 deletions(-) diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index 174bffacf117..45ecf8db1eae 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -26,11 +26,10 @@ #include #include #include +#include #include #include -#define DRIVER_NAME "adv7180" - #define ADV7180_INPUT_CONTROL_REG 0x00 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 @@ -55,21 +54,21 @@ #define ADV7180_AUTODETECT_ENABLE_REG 0x07 #define ADV7180_AUTODETECT_DEFAULT 0x7f - +/* Contrast */ #define ADV7180_CON_REG 0x08 /*Unsigned */ -#define CON_REG_MIN 0 -#define CON_REG_DEF 128 -#define CON_REG_MAX 255 - +#define ADV7180_CON_MIN 0 +#define ADV7180_CON_DEF 128 +#define ADV7180_CON_MAX 255 +/* Brightness*/ #define ADV7180_BRI_REG 0x0a /*Signed */ -#define BRI_REG_MIN -128 -#define BRI_REG_DEF 0 -#define BRI_REG_MAX 127 - +#define ADV7180_BRI_MIN -128 +#define ADV7180_BRI_DEF 0 +#define ADV7180_BRI_MAX 127 +/* Hue */ #define ADV7180_HUE_REG 0x0b /*Signed, inverted */ -#define HUE_REG_MIN -127 -#define HUE_REG_DEF 0 -#define HUE_REG_MAX 128 +#define ADV7180_HUE_MIN -127 +#define ADV7180_HUE_DEF 0 +#define ADV7180_HUE_MAX 128 #define ADV7180_ADI_CTRL_REG 0x0e #define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 @@ -98,12 +97,12 @@ #define ADV7180_ICONF1_ACTIVE_LOW 0x01 #define ADV7180_ICONF1_PSYNC_ONLY 0x10 #define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 - +/* Saturation */ #define ADV7180_SD_SAT_CB_REG 0xe3 /*Unsigned */ #define ADV7180_SD_SAT_CR_REG 0xe4 /*Unsigned */ -#define SAT_REG_MIN 0 -#define SAT_REG_DEF 128 -#define SAT_REG_MAX 255 +#define ADV7180_SAT_MIN 0 +#define ADV7180_SAT_DEF 128 +#define ADV7180_SAT_MAX 255 #define ADV7180_IRQ1_LOCK 0x01 #define ADV7180_IRQ1_UNLOCK 0x02 @@ -121,18 +120,18 @@ #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F struct adv7180_state { + struct v4l2_ctrl_handler ctrl_hdl; struct v4l2_subdev sd; struct work_struct work; struct mutex mutex; /* mutual excl. when accessing chip */ int irq; v4l2_std_id curr_norm; bool autodetect; - s8 brightness; - s16 hue; - u8 contrast; - u8 saturation; u8 input; }; +#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ + struct adv7180_state, \ + ctrl_hdl)->sd) static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { @@ -237,7 +236,7 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, if (ret) return ret; - /*We cannot discriminate between LQFP and 40-pin LFCSP, so accept + /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept * all inputs and let the card driver take care of validation */ if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) @@ -316,117 +315,39 @@ out: return ret; } -static int adv7180_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) -{ - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, BRI_REG_MIN, BRI_REG_MAX, - 1, BRI_REG_DEF); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, HUE_REG_MIN, HUE_REG_MAX, - 1, HUE_REG_DEF); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(qc, CON_REG_MIN, CON_REG_MAX, - 1, CON_REG_DEF); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, SAT_REG_MIN, SAT_REG_MAX, - 1, SAT_REG_DEF); - default: - break; - } - - return -EINVAL; -} - -static int adv7180_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct adv7180_state *state = to_state(sd); - int ret = mutex_lock_interruptible(&state->mutex); - if (ret) - return ret; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = state->brightness; - break; - case V4L2_CID_HUE: - ctrl->value = state->hue; - break; - case V4L2_CID_CONTRAST: - ctrl->value = state->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = state->saturation; - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&state->mutex); - return ret; -} - -static int adv7180_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) { + struct v4l2_subdev *sd = to_adv7180_sd(ctrl); struct adv7180_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = mutex_lock_interruptible(&state->mutex); + int val; + if (ret) return ret; - + val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - if ((ctrl->value > BRI_REG_MAX) - || (ctrl->value < BRI_REG_MIN)) { - ret = -ERANGE; - break; - } - state->brightness = ctrl->value; - ret = i2c_smbus_write_byte_data(client, - ADV7180_BRI_REG, - state->brightness); + ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val); break; case V4L2_CID_HUE: - if ((ctrl->value > HUE_REG_MAX) - || (ctrl->value < HUE_REG_MIN)) { - ret = -ERANGE; - break; - } - state->hue = ctrl->value; /*Hue is inverted according to HSL chart */ - ret = i2c_smbus_write_byte_data(client, - ADV7180_HUE_REG, -state->hue); + ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val); break; case V4L2_CID_CONTRAST: - if ((ctrl->value > CON_REG_MAX) - || (ctrl->value < CON_REG_MIN)) { - ret = -ERANGE; - break; - } - state->contrast = ctrl->value; - ret = i2c_smbus_write_byte_data(client, - ADV7180_CON_REG, - state->contrast); + ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val); break; case V4L2_CID_SATURATION: - if ((ctrl->value > SAT_REG_MAX) - || (ctrl->value < SAT_REG_MIN)) { - ret = -ERANGE; - break; - } /* *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE *Let's not confuse the user, everybody understands saturation */ - state->saturation = ctrl->value; - ret = i2c_smbus_write_byte_data(client, - ADV7180_SD_SAT_CB_REG, - state->saturation); + ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG, + val); if (ret < 0) break; - ret = i2c_smbus_write_byte_data(client, - ADV7180_SD_SAT_CR_REG, - state->saturation); + ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG, + val); break; default: ret = -EINVAL; @@ -436,6 +357,42 @@ static int adv7180_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ret; } +static const struct v4l2_ctrl_ops adv7180_ctrl_ops = { + .s_ctrl = adv7180_s_ctrl, +}; + +static int adv7180_init_controls(struct adv7180_state *state) +{ + v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); + + v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, + V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN, + ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF); + v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, + V4L2_CID_CONTRAST, ADV7180_CON_MIN, + ADV7180_CON_MAX, 1, ADV7180_CON_DEF); + v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, + V4L2_CID_SATURATION, ADV7180_SAT_MIN, + ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF); + v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, + V4L2_CID_HUE, ADV7180_HUE_MIN, + ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); + state->sd.ctrl_handler = &state->ctrl_hdl; + if (state->ctrl_hdl.error) { + int err = state->ctrl_hdl.error; + + v4l2_ctrl_handler_free(&state->ctrl_hdl); + return err; + } + v4l2_ctrl_handler_setup(&state->ctrl_hdl); + + return 0; +} +static void adv7180_exit_controls(struct adv7180_state *state) +{ + v4l2_ctrl_handler_free(&state->ctrl_hdl); +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, @@ -445,9 +402,9 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { static const struct v4l2_subdev_core_ops adv7180_core_ops = { .g_chip_ident = adv7180_g_chip_ident, .s_std = adv7180_s_std, - .queryctrl = adv7180_queryctrl, - .g_ctrl = adv7180_g_ctrl, - .s_ctrl = adv7180_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, }; static const struct v4l2_subdev_ops adv7180_ops = { @@ -539,7 +496,7 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) /* register for interrupts */ if (state->irq > 0) { - ret = request_irq(state->irq, adv7180_irq, 0, DRIVER_NAME, + ret = request_irq(state->irq, adv7180_irq, 0, KBUILD_MODNAME, state); if (ret) return ret; @@ -580,31 +537,6 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) return ret; } - /*Set default value for controls */ - ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, - state->brightness); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, state->hue); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, - state->contrast); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG, - state->saturation); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG, - state->saturation); - if (ret < 0) - return ret; - return 0; } @@ -632,25 +564,26 @@ static __devinit int adv7180_probe(struct i2c_client *client, INIT_WORK(&state->work, adv7180_work); mutex_init(&state->mutex); state->autodetect = true; - state->brightness = BRI_REG_DEF; - state->hue = HUE_REG_DEF; - state->contrast = CON_REG_DEF; - state->saturation = SAT_REG_DEF; state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); - ret = init_device(client, state); - if (0 != ret) + ret = adv7180_init_controls(state); + if (ret) goto err_unreg_subdev; + ret = init_device(client, state); + if (ret) + goto err_free_ctrl; return 0; +err_free_ctrl: + adv7180_exit_controls(state); err_unreg_subdev: mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); kfree(state); err: - printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret); + printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret); return ret; } @@ -678,7 +611,7 @@ static __devexit int adv7180_remove(struct i2c_client *client) } static const struct i2c_device_id adv7180_id[] = { - {DRIVER_NAME, 0}, + {KBUILD_MODNAME, 0}, {}, }; @@ -716,7 +649,7 @@ MODULE_DEVICE_TABLE(i2c, adv7180_id); static struct i2c_driver adv7180_driver = { .driver = { .owner = THIS_MODULE, - .name = DRIVER_NAME, + .name = KBUILD_MODNAME, }, .probe = adv7180_probe, .remove = __devexit_p(adv7180_remove), -- GitLab From db3912c07349f00923d1c95dadd1e83371dce485 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 11 Jul 2012 11:47:38 -0300 Subject: [PATCH 4524/5711] [media] radio-si470x: Lower firmware version requirements Testing with a firmware version 12 usb radio stick has shown version 12 to work fine too. Reported-by: Antti Palosaari Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index b3b612feaa35..d66523826d3d 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -189,7 +189,7 @@ struct si470x_device { * Firmware Versions **************************************************************************/ -#define RADIO_FW_VERSION 14 +#define RADIO_FW_VERSION 12 -- GitLab From 79ef87edea252c3325f0be8aed684db72dc7e46c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 12 Jul 2012 07:39:50 -0300 Subject: [PATCH 4525/5711] [media] videobuf-dma-contig: Use NULL instead of plain integer Fixes the following sparse warning: drivers/media/video/videobuf-dma-contig.c:59:46: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-contig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index f68284655f20..3a43ba0959bf 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -56,7 +56,7 @@ static int __videobuf_dc_alloc(struct device *dev, dev_err(dev, "dma_map_single failed\n"); free_pages_exact(mem->vaddr, mem->size); - mem->vaddr = 0; + mem->vaddr = NULL; return err; } } -- GitLab From afcc8e8c3474e5771ebdd49fe4f1c2ec1df997e7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 12 Jul 2012 10:47:28 -0300 Subject: [PATCH 4526/5711] [media] tvp5150: signedness bug in tvp5150_selmux() tvp5150_read() returns negative error codes so this needs to be an int for the error handling to work. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 0d897cb1774a..a751b6c146fd 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -257,7 +257,7 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) int opmode = 0; struct tvp5150 *decoder = to_tvp5150(sd); int input = 0; - unsigned char val; + int val; if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable) input = 8; -- GitLab From b67a39e4b6850c0346c0b809886632d4cd2fed7d Mon Sep 17 00:00:00 2001 From: Nicolas THERY Date: Thu, 12 Jul 2012 12:12:12 -0300 Subject: [PATCH 4527/5711] [media] v4l: DocBook: fix version number typo Signed-off-by: Nicolas Thery Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 4559a6f8a5f0..c9c7d1ca8d67 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2460,7 +2460,7 @@ that used it. It was originally scheduled for removal in 2.6.35.
- V4L2 in Linux 3.5 + V4L2 in Linux 3.6 Replaced input in -- GitLab From 3d687b49ff085b325488e7aeb2ee4df99dd7ca6e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 5 Jul 2012 06:04:04 -0300 Subject: [PATCH 4528/5711] [media] videodev2.h: add VIDIOC_ENUM_FREQ_BANDS Add a new ioctl to enumerate the supported frequency bands of a tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 40 +++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 4cf766e6f120..63c950f6fcc2 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -2032,6 +2032,7 @@ struct v4l2_modulator { #define V4L2_TUNER_CAP_RDS 0x0080 #define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100 #define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200 +#define V4L2_TUNER_CAP_FREQ_BANDS 0x0400 /* Flags for the 'rxsubchans' field */ #define V4L2_TUNER_SUB_MONO 0x0001 @@ -2050,19 +2051,34 @@ struct v4l2_modulator { #define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 struct v4l2_frequency { - __u32 tuner; - __u32 type; /* enum v4l2_tuner_type */ - __u32 frequency; - __u32 reserved[8]; + __u32 tuner; + __u32 type; /* enum v4l2_tuner_type */ + __u32 frequency; + __u32 reserved[8]; +}; + +#define V4L2_BAND_MODULATION_VSB (1 << 1) +#define V4L2_BAND_MODULATION_FM (1 << 2) +#define V4L2_BAND_MODULATION_AM (1 << 3) + +struct v4l2_frequency_band { + __u32 tuner; + __u32 type; /* enum v4l2_tuner_type */ + __u32 index; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 modulation; + __u32 reserved[9]; }; struct v4l2_hw_freq_seek { - __u32 tuner; - __u32 type; /* enum v4l2_tuner_type */ - __u32 seek_upward; - __u32 wrap_around; - __u32 spacing; - __u32 reserved[7]; + __u32 tuner; + __u32 type; /* enum v4l2_tuner_type */ + __u32 seek_upward; + __u32 wrap_around; + __u32 spacing; + __u32 reserved[7]; }; /* @@ -2630,6 +2646,10 @@ struct v4l2_create_buffers { #define VIDIOC_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) #define VIDIOC_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) +/* Experimental, this ioctl may change over the next couple of kernel + versions. */ +#define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ -- GitLab From 82b655bfc32b793344ef0ddd46df8af8b98b55c7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 5 Jul 2012 06:37:08 -0300 Subject: [PATCH 4529/5711] [media] v4l2: add core support for the new VIDIOC_ENUM_FREQ_BANDS ioctl This adds the usual core support code for this new ioctl. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-compat-ioctl32.c | 1 + drivers/media/video/v4l2-dev.c | 2 + drivers/media/video/v4l2-ioctl.c | 83 ++++++++++++++++++++++- include/media/v4l2-ioctl.h | 2 + 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index ac365cfb3706..9ebd5c540d10 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -1025,6 +1025,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_ENUM_DV_TIMINGS: case VIDIOC_QUERY_DV_TIMINGS: case VIDIOC_DV_TIMINGS_CAP: + case VIDIOC_ENUM_FREQ_BANDS: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 1b2f1c52e6c3..625248585c85 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -730,6 +730,8 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_UNSUBSCRIBE_EVENT, vidioc_unsubscribe_event); SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs); SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf); + if (ops->vidioc_enum_freq_bands || ops->vidioc_g_tuner || ops->vidioc_g_modulator) + set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls); bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls, BASE_VIDIOC_PRIVATE); } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 3e4db2c1c3d6..0f54f8efe66b 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -825,6 +825,17 @@ static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only) p->service_lines[1][i]); } +static void v4l_print_freq_band(const void *arg, bool write_only) +{ + const struct v4l2_frequency_band *p = arg; + + pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, " + "rangelow=%u, rangehigh=%u, modulation=0x%x\n", + p->tuner, p->type, p->index, + p->capability, p->rangelow, + p->rangehigh, p->modulation); +} + static void v4l_print_u32(const void *arg, bool write_only) { pr_cont("value=%u\n", *(const u32 *)arg); @@ -1245,10 +1256,14 @@ static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, { struct video_device *vfd = video_devdata(file); struct v4l2_tuner *p = arg; + int err; p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - return ops->vidioc_g_tuner(file, fh, p); + err = ops->vidioc_g_tuner(file, fh, p); + if (!err) + p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; + return err; } static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, @@ -1262,6 +1277,18 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, return ops->vidioc_s_tuner(file, fh, p); } +static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_modulator *p = arg; + int err; + + err = ops->vidioc_g_modulator(file, fh, p); + if (!err) + p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; + return err; +} + static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1805,6 +1832,57 @@ static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, return ops->vidioc_g_sliced_vbi_cap(file, fh, p); } +static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_frequency_band *p = arg; + enum v4l2_tuner_type type; + int err; + + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + + if (type != p->type) + return -EINVAL; + if (ops->vidioc_enum_freq_bands) + return ops->vidioc_enum_freq_bands(file, fh, p); + if (ops->vidioc_g_tuner) { + struct v4l2_tuner t = { + .index = p->tuner, + .type = type, + }; + + err = ops->vidioc_g_tuner(file, fh, &t); + if (err) + return err; + p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS; + p->rangelow = t.rangelow; + p->rangehigh = t.rangehigh; + p->modulation = (type == V4L2_TUNER_RADIO) ? + V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; + return 0; + } + if (ops->vidioc_g_modulator) { + struct v4l2_modulator m = { + .index = p->tuner, + }; + + if (type != V4L2_TUNER_RADIO) + return -EINVAL; + err = ops->vidioc_g_modulator(file, fh, &m); + if (err) + return err; + p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS; + p->rangelow = m.rangelow; + p->rangehigh = m.rangehigh; + p->modulation = (type == V4L2_TUNER_RADIO) ? + V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; + return 0; + } + return -ENOTTY; +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -1886,7 +1964,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), - IOCTL_INFO_STD(VIDIOC_G_MODULATOR, vidioc_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), + IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), @@ -1933,6 +2011,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)), + IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 19e93523c2d8..e614c9c15e56 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -230,6 +230,8 @@ struct v4l2_ioctl_ops { struct v4l2_frequency *a); int (*vidioc_s_frequency) (struct file *file, void *fh, struct v4l2_frequency *a); + int (*vidioc_enum_freq_bands) (struct file *file, void *fh, + struct v4l2_frequency_band *band); /* Sliced VBI cap */ int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh, -- GitLab From 50121317c2035c017d62c8ec24f84b91ef8d4de2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 5 Jul 2012 06:54:38 -0300 Subject: [PATCH 4530/5711] [media] v4l2 spec: add VIDIOC_ENUM_FREQ_BANDS documentation Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 12 ++ Documentation/DocBook/media/v4l/v4l2.xml | 6 + .../media/v4l/vidioc-enum-freq-bands.xml | 179 ++++++++++++++++++ .../DocBook/media/v4l/vidioc-g-frequency.xml | 7 +- .../DocBook/media/v4l/vidioc-g-tuner.xml | 26 ++- 5 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index c9c7d1ca8d67..faa0fd14666a 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2480,6 +2480,15 @@ that used it. It was originally scheduled for removal in 2.6.35.
+
+ V4L2 in Linux 3.6 + + + Added support for frequency band enumerations: &VIDIOC-ENUM-FREQ-BANDS;. + + +
+
Relation of V4L2 to other Linux multimedia APIs @@ -2609,6 +2618,9 @@ ioctls. V4L2_CID_AUTO_FOCUS_AREA control. + + Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl. +
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index 36bafc48e03b..eee6908c749f 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -140,6 +140,11 @@ structs, ioctls) must be noted in more detail in the history chapter applications. --> + 3.6 + 2012-07-02 + hv + Added VIDIOC_ENUM_FREQ_BANDS. + 3.5 2012-05-07 sa, sn @@ -534,6 +539,7 @@ and discussions on the V4L mailing list. &sub-enum-fmt; &sub-enum-framesizes; &sub-enum-frameintervals; + &sub-enum-freq-bands; &sub-enuminput; &sub-enumoutput; &sub-enumstd; diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml new file mode 100644 index 000000000000..6541ba0175ed --- /dev/null +++ b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml @@ -0,0 +1,179 @@ + + + ioctl VIDIOC_ENUM_FREQ_BANDS + &manvol; + + + + VIDIOC_ENUM_FREQ_BANDS + Enumerate supported frequency bands + + + + + + int ioctl + int fd + int request + struct v4l2_frequency_band +*argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_ENUM_FREQ_BANDS + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + Enumerates the frequency bands that a tuner or modulator supports. +To do this applications initialize the tuner, +type and index fields, +and zero out the reserved array of a &v4l2-frequency-band; and +call the VIDIOC_ENUM_FREQ_BANDS ioctl with a pointer +to this structure. + + This ioctl is supported if the V4L2_TUNER_CAP_FREQ_BANDS capability + of the corresponding tuner/modulator is set. + +
+ struct <structname>v4l2_frequency_band</structname> + + &cs-str; + + + __u32 + tuner + The tuner or modulator index number. This is the +same value as in the &v4l2-input; tuner +field and the &v4l2-tuner; index field, or +the &v4l2-output; modulator field and the +&v4l2-modulator; index field. + + + __u32 + type + The tuner type. This is the same value as in the +&v4l2-tuner; type field. The type must be set +to V4L2_TUNER_RADIO for /dev/radioX +device nodes, and to V4L2_TUNER_ANALOG_TV +for all others. Set this field to V4L2_TUNER_RADIO for +modulators (currently only radio modulators are supported). +See + + + __u32 + index + Identifies the frequency band, set by the application. + + + __u32 + capability + The tuner/modulator capability flags for +this frequency band, see . The V4L2_TUNER_CAP_LOW +capability must be the same for all frequency bands of the selected tuner/modulator. +So either all bands have that capability set, or none of them have that capability. + + + __u32 + rangelow + The lowest tunable frequency in +units of 62.5 kHz, or if the capability +flag V4L2_TUNER_CAP_LOW is set, in units of 62.5 +Hz, for this frequency band. + + + __u32 + rangehigh + The highest tunable frequency in +units of 62.5 kHz, or if the capability +flag V4L2_TUNER_CAP_LOW is set, in units of 62.5 +Hz, for this frequency band. + + + __u32 + modulation + The supported modulation systems of this frequency band. + See . Note that currently only one + modulation system per frequency band is supported. More work will need to + be done if multiple modulation systems are possible. Contact the + linux-media mailing list (&v4l-ml;) if you need that functionality. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers + must set the array to zero. + + + +
+ + + Band Modulation Systems + + &cs-def; + + + V4L2_BAND_MODULATION_VSB + 0x02 + Vestigial Sideband modulation, used for analog TV. + + + V4L2_BAND_MODULATION_FM + 0x04 + Frequency Modulation, commonly used for analog radio. + + + V4L2_BAND_MODULATION_AM + 0x08 + Amplitude Modulation, commonly used for analog radio. + + + +
+ + + + &return-value; + + + + EINVAL + + The tuner or index +is out of bounds or the type field is wrong. + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml index 40e58a42eb26..c7a1c462e724 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml @@ -98,11 +98,12 @@ the &v4l2-output; modulator field and the __u32 type The tuner type. This is the same value as in the -&v4l2-tuner; type field. See The type must be set +&v4l2-tuner; type field. The type must be set to V4L2_TUNER_RADIO for /dev/radioX device nodes, and to V4L2_TUNER_ANALOG_TV -for all others. The field is not applicable to modulators, &ie; ignored -by drivers. See +for all others. Set this field to V4L2_TUNER_RADIO for +modulators (currently only radio modulators are supported). +See
__u32 diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index 95d5371c1709..720395127904 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -119,10 +119,14 @@ field is not quite clear.--> . Audio flags indicate the ability to decode audio subprograms. They will not change, for example with the current video standard.When -the structure refers to a radio tuner only the -V4L2_TUNER_CAP_LOW, -V4L2_TUNER_CAP_STEREO and -V4L2_TUNER_CAP_RDS flags can be set. +the structure refers to a radio tuner the +V4L2_TUNER_CAP_LANG1, +V4L2_TUNER_CAP_LANG2 and +V4L2_TUNER_CAP_NORM flags can't be used. +If multiple frequency bands are supported, then +capability is the union of all +capability> fields of each &v4l2-frequency-band;. + __u32 @@ -130,7 +134,9 @@ the structure refers to a radio tuner only the The lowest tunable frequency in units of 62.5 kHz, or if the capability flag V4L2_TUNER_CAP_LOW is set, in units of 62.5 -Hz. +Hz. If multiple frequency bands are supported, then +rangelow is the lowest frequency +of all the frequency bands. __u32 @@ -138,7 +144,9 @@ Hz. The highest tunable frequency in units of 62.5 kHz, or if the capability flag V4L2_TUNER_CAP_LOW is set, in units of 62.5 -Hz. +Hz. If multiple frequency bands are supported, then +rangehigh is the highest frequency +of all the frequency bands. __u32 @@ -340,6 +348,12 @@ radio tuners. 0x0200 The RDS data is parsed by the hardware and set via controls. + + V4L2_TUNER_CAP_FREQ_BANDS + 0x0400 + The &VIDIOC-ENUM-FREQ-BANDS; ioctl can be used to enumerate + the available frequency bands. + -- GitLab From b54c97db7f51c47c361533956db18c8b191033b5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 09:36:39 -0300 Subject: [PATCH 4531/5711] [media] radio-cadet: upgrade to latest frameworks - add control framework - use core locking - use V4L2_TUNER_CAP_LOW - remove volume support: there is no hardware volume control Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-cadet.c | 243 ++++++++++-------------------- 1 file changed, 83 insertions(+), 160 deletions(-) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 16a089fad909..93536b7e75c7 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -41,6 +41,9 @@ #include /* outb, outb_p */ #include #include +#include +#include +#include MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); @@ -61,8 +64,8 @@ module_param(radio_nr, int, 0); struct cadet { struct v4l2_device v4l2_dev; struct video_device vdev; + struct v4l2_ctrl_handler ctrl_handler; int io; - int users; int curtuner; int tunestat; int sigstrength; @@ -94,11 +97,9 @@ static int cadet_getstereo(struct cadet *dev) if (dev->curtuner != 0) /* Only FM has stereo capability! */ return V4L2_TUNER_SUB_MONO; - mutex_lock(&dev->lock); outb(7, dev->io); /* Select tuner control */ if ((inb(dev->io + 1) & 0x40) == 0) ret = V4L2_TUNER_SUB_STEREO; - mutex_unlock(&dev->lock); return ret; } @@ -111,8 +112,6 @@ static unsigned cadet_gettune(struct cadet *dev) * Prepare for read */ - mutex_lock(&dev->lock); - outb(7, dev->io); /* Select tuner control */ curvol = inb(dev->io + 1); /* Save current volume/mute setting */ outb(0x00, dev->io + 1); /* Ensure WRITE-ENABLE is LOW */ @@ -134,8 +133,6 @@ static unsigned cadet_gettune(struct cadet *dev) * Restore volume/mute setting */ outb(curvol, dev->io + 1); - mutex_unlock(&dev->lock); - return fifo; } @@ -161,7 +158,7 @@ static unsigned cadet_getfreq(struct cadet *dev) fifo = fifo >> 1; } freq -= 10700000; /* IF frequency is 10.7 MHz */ - freq = (freq * 16) / 1000000; /* Make it 1/16 MHz */ + freq = (freq * 16) / 1000; /* Make it 1/16 kHz */ } if (dev->curtuner == 1) /* AM */ freq = ((fifo & 0x7fff) - 2010) * 16; @@ -174,8 +171,6 @@ static void cadet_settune(struct cadet *dev, unsigned fifo) int i; unsigned test; - mutex_lock(&dev->lock); - outb(7, dev->io); /* Select tuner control */ /* * Write the shift register @@ -194,7 +189,6 @@ static void cadet_settune(struct cadet *dev, unsigned fifo) test = 0x1c | ((fifo >> 23) & 0x02); outb(test, dev->io + 1); } - mutex_unlock(&dev->lock); } static void cadet_setfreq(struct cadet *dev, unsigned freq) @@ -209,7 +203,7 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) fifo = 0; if (dev->curtuner == 0) { /* FM */ test = 102400; - freq = (freq * 1000) / 16; /* Make it kHz */ + freq = freq / 16; /* Make it kHz */ freq += 10700; /* IF is 10700 kHz */ for (i = 0; i < 14; i++) { fifo = fifo << 1; @@ -229,10 +223,8 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) * Save current volume/mute setting */ - mutex_lock(&dev->lock); outb(7, dev->io); /* Select tuner control */ curvol = inb(dev->io + 1); - mutex_unlock(&dev->lock); /* * Tune the card @@ -240,10 +232,8 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) for (j = 3; j > -1; j--) { cadet_settune(dev, fifo | (j << 16)); - mutex_lock(&dev->lock); outb(7, dev->io); /* Select tuner control */ outb(curvol, dev->io + 1); - mutex_unlock(&dev->lock); msleep(100); @@ -257,32 +247,6 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) } -static int cadet_getvol(struct cadet *dev) -{ - int ret = 0; - - mutex_lock(&dev->lock); - - outb(7, dev->io); /* Select tuner control */ - if ((inb(dev->io + 1) & 0x20) != 0) - ret = 0xffff; - - mutex_unlock(&dev->lock); - return ret; -} - - -static void cadet_setvol(struct cadet *dev, int vol) -{ - mutex_lock(&dev->lock); - outb(7, dev->io); /* Select tuner control */ - if (vol > 0) - outb(0x20, dev->io + 1); - else - outb(0x00, dev->io + 1); - mutex_unlock(&dev->lock); -} - static void cadet_handler(unsigned long data) { struct cadet *dev = (void *)data; @@ -337,18 +301,19 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo add_timer(&dev->readtimer); } if (dev->rdsin == dev->rdsout) { - mutex_unlock(&dev->lock); - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; + if (file->f_flags & O_NONBLOCK) { + i = -EWOULDBLOCK; + goto unlock; + } interruptible_sleep_on(&dev->read_queue); - mutex_lock(&dev->lock); } while (i < count && dev->rdsin != dev->rdsout) readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - mutex_unlock(&dev->lock); if (copy_to_user(data, readbuf, i)) - return -EFAULT; + i = -EFAULT; +unlock: + mutex_unlock(&dev->lock); return i; } @@ -359,8 +324,9 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, "ADS Cadet", sizeof(v->driver)); strlcpy(v->card, "ADS Cadet", sizeof(v->card)); strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -374,20 +340,11 @@ static int vidioc_g_tuner(struct file *file, void *priv, case 0: strlcpy(v->name, "FM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_RDS_BLOCK_IO; - v->rangelow = 1400; /* 87.5 MHz */ - v->rangehigh = 1728; /* 108.0 MHz */ + V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW; + v->rangelow = 1400000; /* 87.5 MHz */ + v->rangehigh = 1728000; /* 108.0 MHz */ v->rxsubchans = cadet_getstereo(dev); - switch (v->rxsubchans) { - case V4L2_TUNER_SUB_MONO: - v->audmode = V4L2_TUNER_MODE_MONO; - break; - case V4L2_TUNER_SUB_STEREO: - v->audmode = V4L2_TUNER_MODE_STEREO; - break; - default: - break; - } + v->audmode = V4L2_TUNER_MODE_STEREO; v->rxsubchans |= V4L2_TUNER_SUB_RDS; break; case 1: @@ -408,11 +365,8 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct cadet *dev = video_drvdata(file); - if (v->index != 0 && v->index != 1) return -EINVAL; - dev->curtuner = v->index; return 0; } @@ -421,7 +375,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct cadet *dev = video_drvdata(file); - f->tuner = dev->curtuner; + if (f->tuner > 1) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = cadet_getfreq(dev); return 0; @@ -435,101 +390,52 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->type != V4L2_TUNER_RADIO) return -EINVAL; - if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728)) - return -EINVAL; - if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400)) + if (f->tuner == 0) { + if (f->frequency < 1400000) + f->frequency = 1400000; + else if (f->frequency > 1728000) + f->frequency = 1728000; + } else if (f->tuner == 1) { + if (f->frequency < 8320) + f->frequency = 8320; + else if (f->frequency > 26400) + f->frequency = 26400; + } else return -EINVAL; cadet_setfreq(dev, f->frequency); return 0; } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) +static int cadet_s_ctrl(struct v4l2_ctrl *ctrl) { - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct cadet *dev = video_drvdata(file); + struct cadet *dev = container_of(ctrl->handler, struct cadet, ctrl_handler); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - ctrl->value = (cadet_getvol(dev) == 0); - break; - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = cadet_getvol(dev); - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct cadet *dev = video_drvdata(file); - - switch (ctrl->id){ - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - if (ctrl->value) - cadet_setvol(dev, 0); + case V4L2_CID_AUDIO_MUTE: + outb(7, dev->io); /* Select tuner control */ + if (ctrl->val) + outb(0x00, dev->io + 1); else - cadet_setvol(dev, 0xffff); - break; - case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(dev, ctrl->value); - break; - default: - return -EINVAL; + outb(0x20, dev->io + 1); + return 0; } - return 0; -} - -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; + return -EINVAL; } static int cadet_open(struct file *file) { struct cadet *dev = video_drvdata(file); + int err; mutex_lock(&dev->lock); - dev->users++; - if (1 == dev->users) + err = v4l2_fh_open(file); + if (err) + goto fail; + if (v4l2_fh_is_singular_file(file)) init_waitqueue_head(&dev->read_queue); +fail: mutex_unlock(&dev->lock); - return 0; + return err; } static int cadet_release(struct file *file) @@ -537,11 +443,11 @@ static int cadet_release(struct file *file) struct cadet *dev = video_drvdata(file); mutex_lock(&dev->lock); - dev->users--; - if (0 == dev->users) { + if (v4l2_fh_is_singular_file(file) && dev->rdsstat) { del_timer_sync(&dev->readtimer); dev->rdsstat = 0; } + v4l2_fh_release(file); mutex_unlock(&dev->lock); return 0; } @@ -549,11 +455,12 @@ static int cadet_release(struct file *file) static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { struct cadet *dev = video_drvdata(file); + unsigned int res = v4l2_ctrl_poll(file, wait); poll_wait(file, &dev->read_queue, wait); if (dev->rdsin != dev->rdsout) - return POLLIN | POLLRDNORM; - return 0; + res |= POLLIN | POLLRDNORM; + return res; } @@ -572,13 +479,13 @@ static const struct v4l2_ioctl_ops cadet_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_ctrl_ops cadet_ctrl_ops = { + .s_ctrl = cadet_s_ctrl, }; #ifdef CONFIG_PNP @@ -648,7 +555,8 @@ static int __init cadet_init(void) { struct cadet *dev = &cadet_card; struct v4l2_device *v4l2_dev = &dev->v4l2_dev; - int res; + struct v4l2_ctrl_handler *hdl; + int res = -ENODEV; strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); mutex_init(&dev->lock); @@ -680,23 +588,37 @@ static int __init cadet_init(void) goto fail; } + hdl = &dev->ctrl_handler; + v4l2_ctrl_handler_init(hdl, 2); + v4l2_ctrl_new_std(hdl, &cadet_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + v4l2_dev->ctrl_handler = hdl; + if (hdl->error) { + res = hdl->error; + v4l2_err(v4l2_dev, "Could not register controls\n"); + goto err_hdl; + } + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); dev->vdev.v4l2_dev = v4l2_dev; dev->vdev.fops = &cadet_fops; dev->vdev.ioctl_ops = &cadet_ioctl_ops; dev->vdev.release = video_device_release_empty; + dev->vdev.lock = &dev->lock; + set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); video_set_drvdata(&dev->vdev, dev); - if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { - v4l2_device_unregister(v4l2_dev); - release_region(dev->io, 2); - goto fail; - } + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) + goto err_hdl; v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io); return 0; +err_hdl: + v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 2); fail: pnp_unregister_driver(&cadet_pnp_driver); - return -ENODEV; + return res; } static void __exit cadet_exit(void) @@ -704,6 +626,7 @@ static void __exit cadet_exit(void) struct cadet *dev = &cadet_card; video_unregister_device(&dev->vdev); + v4l2_ctrl_handler_free(&dev->ctrl_handler); v4l2_device_unregister(&dev->v4l2_dev); release_region(dev->io, 2); pnp_unregister_driver(&cadet_pnp_driver); -- GitLab From cc0d32665f9f8d4e7297a470e91b8848c7f0436c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Jul 2012 09:46:46 -0300 Subject: [PATCH 4532/5711] [media] radio-cadet: fix RDS handling The current RDS code suffered from bit rot. Clean it up and make it work again. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-cadet.c | 56 +++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 93536b7e75c7..d1fb42746fc2 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -71,7 +71,7 @@ struct cadet { int sigstrength; wait_queue_head_t read_queue; struct timer_list readtimer; - __u8 rdsin, rdsout, rdsstat; + u8 rdsin, rdsout, rdsstat; unsigned char rdsbuf[RDS_BUFFER]; struct mutex lock; int reading; @@ -85,8 +85,8 @@ static struct cadet cadet_card; * strength value. These values are in microvolts of RF at the tuner's input. */ static __u16 sigtable[2][4] = { - { 5, 10, 30, 150 }, - { 28, 40, 63, 1000 } + { 2185, 4369, 13107, 65535 }, + { 1835, 2621, 4128, 65535 } }; @@ -240,10 +240,13 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) cadet_gettune(dev); if ((dev->tunestat & 0x40) == 0) { /* Tuned */ dev->sigstrength = sigtable[dev->curtuner][j]; - return; + goto reset_rds; } } dev->sigstrength = 0; +reset_rds: + outb(3, dev->io); + outb(inb(dev->io + 1) & 0x7f, dev->io + 1); } @@ -259,7 +262,7 @@ static void cadet_handler(unsigned long data) outb(0x80, dev->io); /* Select RDS fifo */ while ((inb(dev->io) & 0x80) != 0) { dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); - if (dev->rdsin == dev->rdsout) + if (dev->rdsin + 1 == dev->rdsout) printk(KERN_WARNING "cadet: RDS buffer overflow\n"); else dev->rdsin++; @@ -278,11 +281,21 @@ static void cadet_handler(unsigned long data) */ init_timer(&dev->readtimer); dev->readtimer.function = cadet_handler; - dev->readtimer.data = (unsigned long)0; + dev->readtimer.data = data; dev->readtimer.expires = jiffies + msecs_to_jiffies(50); add_timer(&dev->readtimer); } +static void cadet_start_rds(struct cadet *dev) +{ + dev->rdsstat = 1; + outb(0x80, dev->io); /* Select RDS fifo */ + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)dev; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); +} static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { @@ -291,26 +304,21 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo int i = 0; mutex_lock(&dev->lock); - if (dev->rdsstat == 0) { - dev->rdsstat = 1; - outb(0x80, dev->io); /* Select RDS fifo */ - init_timer(&dev->readtimer); - dev->readtimer.function = cadet_handler; - dev->readtimer.data = (unsigned long)dev; - dev->readtimer.expires = jiffies + msecs_to_jiffies(50); - add_timer(&dev->readtimer); - } + if (dev->rdsstat == 0) + cadet_start_rds(dev); if (dev->rdsin == dev->rdsout) { if (file->f_flags & O_NONBLOCK) { i = -EWOULDBLOCK; goto unlock; } + mutex_unlock(&dev->lock); interruptible_sleep_on(&dev->read_queue); + mutex_lock(&dev->lock); } while (i < count && dev->rdsin != dev->rdsout) readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - if (copy_to_user(data, readbuf, i)) + if (i && copy_to_user(data, readbuf, i)) i = -EFAULT; unlock: mutex_unlock(&dev->lock); @@ -345,7 +353,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->rangehigh = 1728000; /* 108.0 MHz */ v->rxsubchans = cadet_getstereo(dev); v->audmode = V4L2_TUNER_MODE_STEREO; - v->rxsubchans |= V4L2_TUNER_SUB_RDS; + outb(3, dev->io); + outb(inb(dev->io + 1) & 0x7f, dev->io + 1); + mdelay(100); + outb(3, dev->io); + if (inb(dev->io + 1) & 0x80) + v->rxsubchans |= V4L2_TUNER_SUB_RDS; break; case 1: strlcpy(v->name, "AM", sizeof(v->name)); @@ -455,9 +468,16 @@ static int cadet_release(struct file *file) static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { struct cadet *dev = video_drvdata(file); + unsigned long req_events = poll_requested_events(wait); unsigned int res = v4l2_ctrl_poll(file, wait); poll_wait(file, &dev->read_queue, wait); + if (dev->rdsstat == 0 && (req_events & (POLLIN | POLLRDNORM))) { + mutex_lock(&dev->lock); + if (dev->rdsstat == 0) + cadet_start_rds(dev); + mutex_unlock(&dev->lock); + } if (dev->rdsin != dev->rdsout) res |= POLLIN | POLLRDNORM; return res; @@ -628,6 +648,8 @@ static void __exit cadet_exit(void) video_unregister_device(&dev->vdev); v4l2_ctrl_handler_free(&dev->ctrl_handler); v4l2_device_unregister(&dev->v4l2_dev); + outb(7, dev->io); /* Mute */ + outb(0x00, dev->io + 1); release_region(dev->io, 2); pnp_unregister_driver(&cadet_pnp_driver); } -- GitLab From 6652c716a5e46f0631d26a7f83a8f7247d293ae7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 10 Jul 2012 08:26:04 -0300 Subject: [PATCH 4533/5711] [media] radio-cadet: implement frequency band enumeration Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-cadet.c | 131 +++++++++++++++++------------- 1 file changed, 74 insertions(+), 57 deletions(-) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index d1fb42746fc2..697a421c9940 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -66,7 +66,8 @@ struct cadet { struct video_device vdev; struct v4l2_ctrl_handler ctrl_handler; int io; - int curtuner; + bool is_fm_band; + u32 curfreq; int tunestat; int sigstrength; wait_queue_head_t read_queue; @@ -84,9 +85,9 @@ static struct cadet cadet_card; * The V4L API spec does not define any particular unit for the signal * strength value. These values are in microvolts of RF at the tuner's input. */ -static __u16 sigtable[2][4] = { +static u16 sigtable[2][4] = { + { 1835, 2621, 4128, 65535 }, { 2185, 4369, 13107, 65535 }, - { 1835, 2621, 4128, 65535 } }; @@ -94,7 +95,7 @@ static int cadet_getstereo(struct cadet *dev) { int ret = V4L2_TUNER_SUB_MONO; - if (dev->curtuner != 0) /* Only FM has stereo capability! */ + if (!dev->is_fm_band) /* Only FM has stereo capability! */ return V4L2_TUNER_SUB_MONO; outb(7, dev->io); /* Select tuner control */ @@ -149,20 +150,18 @@ static unsigned cadet_getfreq(struct cadet *dev) /* * Convert to actual frequency */ - if (dev->curtuner == 0) { /* FM */ - test = 12500; - for (i = 0; i < 14; i++) { - if ((fifo & 0x01) != 0) - freq += test; - test = test << 1; - fifo = fifo >> 1; - } - freq -= 10700000; /* IF frequency is 10.7 MHz */ - freq = (freq * 16) / 1000; /* Make it 1/16 kHz */ + if (!dev->is_fm_band) /* AM */ + return ((fifo & 0x7fff) - 450) * 16; + + test = 12500; + for (i = 0; i < 14; i++) { + if ((fifo & 0x01) != 0) + freq += test; + test = test << 1; + fifo = fifo >> 1; } - if (dev->curtuner == 1) /* AM */ - freq = ((fifo & 0x7fff) - 2010) * 16; - + freq -= 10700000; /* IF frequency is 10.7 MHz */ + freq = (freq * 16) / 1000; /* Make it 1/16 kHz */ return freq; } @@ -197,11 +196,12 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) int i, j, test; int curvol; + dev->curfreq = freq; /* * Formulate a fifo command */ fifo = 0; - if (dev->curtuner == 0) { /* FM */ + if (dev->is_fm_band) { /* FM */ test = 102400; freq = freq / 16; /* Make it kHz */ freq += 10700; /* IF is 10700 kHz */ @@ -213,10 +213,9 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) } test = test >> 1; } - } - if (dev->curtuner == 1) { /* AM */ - fifo = (freq / 16) + 2010; /* Make it kHz */ - fifo |= 0x100000; /* Select AM Band */ + } else { /* AM */ + fifo = (freq / 16) + 450; /* Make it kHz */ + fifo |= 0x100000; /* Select AM Band */ } /* @@ -239,7 +238,7 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) cadet_gettune(dev); if ((dev->tunestat & 0x40) == 0) { /* Tuned */ - dev->sigstrength = sigtable[dev->curtuner][j]; + dev->sigstrength = sigtable[dev->is_fm_band][j]; goto reset_rds; } } @@ -338,39 +337,52 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } +static const struct v4l2_frequency_band bands[] = { + { + .index = 0, + .type = V4L2_TUNER_RADIO, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 8320, /* 520 kHz */ + .rangehigh = 26400, /* 1650 kHz */ + .modulation = V4L2_BAND_MODULATION_AM, + }, { + .index = 1, + .type = V4L2_TUNER_RADIO, + .capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | + V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW | + V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 1400000, /* 87.5 MHz */ + .rangehigh = 1728000, /* 108.0 MHz */ + .modulation = V4L2_BAND_MODULATION_FM, + }, +}; + static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct cadet *dev = video_drvdata(file); + if (v->index) + return -EINVAL; v->type = V4L2_TUNER_RADIO; - switch (v->index) { - case 0: - strlcpy(v->name, "FM", sizeof(v->name)); - v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW; - v->rangelow = 1400000; /* 87.5 MHz */ - v->rangehigh = 1728000; /* 108.0 MHz */ + strlcpy(v->name, "Radio", sizeof(v->name)); + v->capability = bands[0].capability | bands[1].capability; + v->rangelow = bands[0].rangelow; /* 520 kHz (start of AM band) */ + v->rangehigh = bands[1].rangehigh; /* 108.0 MHz (end of FM band) */ + if (dev->is_fm_band) { v->rxsubchans = cadet_getstereo(dev); - v->audmode = V4L2_TUNER_MODE_STEREO; outb(3, dev->io); outb(inb(dev->io + 1) & 0x7f, dev->io + 1); mdelay(100); outb(3, dev->io); if (inb(dev->io + 1) & 0x80) v->rxsubchans |= V4L2_TUNER_SUB_RDS; - break; - case 1: - strlcpy(v->name, "AM", sizeof(v->name)); - v->capability = V4L2_TUNER_CAP_LOW; + } else { v->rangelow = 8320; /* 520 kHz */ v->rangehigh = 26400; /* 1650 kHz */ v->rxsubchans = V4L2_TUNER_SUB_MONO; - v->audmode = V4L2_TUNER_MODE_MONO; - break; - default: - return -EINVAL; } + v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = dev->sigstrength; /* We might need to modify scaling of this */ return 0; } @@ -378,8 +390,17 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index != 0 && v->index != 1) + return v->index ? -EINVAL : 0; +} + +static int vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + if (band->tuner) + return -EINVAL; + if (band->index >= ARRAY_SIZE(bands)) return -EINVAL; + *band = bands[band->index]; return 0; } @@ -388,10 +409,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct cadet *dev = video_drvdata(file); - if (f->tuner > 1) + if (f->tuner) return -EINVAL; f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(dev); + f->frequency = dev->curfreq; return 0; } @@ -401,20 +422,12 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct cadet *dev = video_drvdata(file); - if (f->type != V4L2_TUNER_RADIO) - return -EINVAL; - if (f->tuner == 0) { - if (f->frequency < 1400000) - f->frequency = 1400000; - else if (f->frequency > 1728000) - f->frequency = 1728000; - } else if (f->tuner == 1) { - if (f->frequency < 8320) - f->frequency = 8320; - else if (f->frequency > 26400) - f->frequency = 26400; - } else + if (f->tuner) return -EINVAL; + dev->is_fm_band = + f->frequency >= (bands[0].rangehigh + bands[1].rangelow) / 2; + clamp(f->frequency, bands[dev->is_fm_band].rangelow, + bands[dev->is_fm_band].rangehigh); cadet_setfreq(dev, f->frequency); return 0; } @@ -499,6 +512,7 @@ static const struct v4l2_ioctl_ops cadet_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_enum_freq_bands = vidioc_enum_freq_bands, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -555,8 +569,8 @@ static void cadet_probe(struct cadet *dev) for (i = 0; i < 8; i++) { dev->io = iovals[i]; if (request_region(dev->io, 2, "cadet-probe")) { - cadet_setfreq(dev, 1410); - if (cadet_getfreq(dev) == 1410) { + cadet_setfreq(dev, bands[1].rangelow); + if (cadet_getfreq(dev) == bands[1].rangelow) { release_region(dev->io, 2); return; } @@ -619,6 +633,9 @@ static int __init cadet_init(void) goto err_hdl; } + dev->is_fm_band = true; + dev->curfreq = bands[dev->is_fm_band].rangelow; + cadet_setfreq(dev, dev->curfreq); strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); dev->vdev.v4l2_dev = v4l2_dev; dev->vdev.fops = &cadet_fops; -- GitLab From e0a9b1770bac048171961625875aaf15118a7ae9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Jul 2012 16:55:45 -0300 Subject: [PATCH 4534/5711] [media] v4l2: Add rangelow and rangehigh fields to the v4l2_hw_freq_seek struct To allow apps to limit a hw-freq-seek to a specific band, for further info see the documentation this patch adds for these new fields. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/v4l/vidioc-s-hw-freq-seek.xml | 50 ++++++++++++++++--- include/linux/videodev2.h | 5 +- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml index f4db44d0d95a..3dd1bec6d3c7 100644 --- a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml +++ b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml @@ -52,11 +52,23 @@ Start a hardware frequency seek from the current frequency. To do this applications initialize the tuner, type, seek_upward, -spacing and -wrap_around fields, and zero out the -reserved array of a &v4l2-hw-freq-seek; and -call the VIDIOC_S_HW_FREQ_SEEK ioctl with a pointer -to this structure. +wrap_around, spacing, +rangelow and rangehigh +fields, and zero out the reserved array of a +&v4l2-hw-freq-seek; and call the VIDIOC_S_HW_FREQ_SEEK +ioctl with a pointer to this structure. + + The rangelow and +rangehigh fields can be set to a non-zero value to +tell the driver to search a specific band. If the &v4l2-tuner; +capability field has the +V4L2_TUNER_CAP_HWSEEK_PROG_LIM flag set, these values +must fall within one of the bands returned by &VIDIOC-ENUM-FREQ-BANDS;. If +the V4L2_TUNER_CAP_HWSEEK_PROG_LIM flag is not set, +then these values must exactly match those of one of the bands returned by +&VIDIOC-ENUM-FREQ-BANDS;. If the current frequency of the tuner does not fall +within the selected band it will be clamped to fit in the band before the +seek is started. If an error is returned, then the original frequency will be restored. @@ -102,7 +114,27 @@ field and the &v4l2-tuner; index field. __u32 - reserved[7] + rangelow + If non-zero, the lowest tunable frequency of the band to +search in units of 62.5 kHz, or if the &v4l2-tuner; +capability field has the +V4L2_TUNER_CAP_LOW flag set, in units of 62.5 Hz. +If rangelow is zero a reasonable default value +is used. + + + __u32 + rangehigh + If non-zero, the highest tunable frequency of the band to +search in units of 62.5 kHz, or if the &v4l2-tuner; +capability field has the +V4L2_TUNER_CAP_LOW flag set, in units of 62.5 Hz. +If rangehigh is zero a reasonable default value +is used. + + + __u32 + reserved[5] Reserved for future extensions. Applications must set the array to zero. @@ -119,8 +151,10 @@ field and the &v4l2-tuner; index field. EINVAL The tuner index is out of -bounds, the wrap_around value is not supported or the value in the type field is -wrong. +bounds, the wrap_around value is not supported or +one of the values in the type, +rangelow or rangehigh +fields is wrong. diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 63c950f6fcc2..7a147c8299ab 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -2033,6 +2033,7 @@ struct v4l2_modulator { #define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100 #define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200 #define V4L2_TUNER_CAP_FREQ_BANDS 0x0400 +#define V4L2_TUNER_CAP_HWSEEK_PROG_LIM 0x0800 /* Flags for the 'rxsubchans' field */ #define V4L2_TUNER_SUB_MONO 0x0001 @@ -2078,7 +2079,9 @@ struct v4l2_hw_freq_seek { __u32 seek_upward; __u32 wrap_around; __u32 spacing; - __u32 reserved[7]; + __u32 rangelow; + __u32 rangehigh; + __u32 reserved[5]; }; /* -- GitLab From c1af23c4f7e4c95f0002b6801a9dd82b22cae35d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Jul 2012 16:55:46 -0300 Subject: [PATCH 4535/5711] [media] radio-si470x: restore ctrl settings after suspend/resume Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-usb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 40b963c983c6..0204cf445387 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -792,11 +792,16 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf, static int si470x_usb_driver_resume(struct usb_interface *intf) { struct si470x_device *radio = usb_get_intfdata(intf); + int ret; dev_info(&intf->dev, "resuming now...\n"); /* start radio */ - return si470x_start_usb(radio); + ret = si470x_start_usb(radio); + if (ret == 0) + v4l2_ctrl_handler_setup(&radio->hdl); + + return ret; } -- GitLab From 8d8c1b375cd5b239607037a859661e98cd0dac00 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Jul 2012 16:55:47 -0300 Subject: [PATCH 4536/5711] [media] radio-si470x: Fix band selection The mask was wrong resulting in band 0 and 1 always ending up as band 0 in the register. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index d66523826d3d..b3586e1ec2c4 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -87,7 +87,7 @@ #define SYSCONFIG2 5 /* System Configuration 2 */ #define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ -#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */ +#define SYSCONFIG2_BAND 0x00c0 /* bits 07..06: Band Select */ #define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ #define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ -- GitLab From f140612d025f2b6a00651e7c2a9cc26b61dca119 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Jul 2012 16:55:48 -0300 Subject: [PATCH 4537/5711] [media] radio-si470x: Add support for the new band APIs Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/radio/si470x/radio-si470x-common.c | 215 ++++++++++-------- drivers/media/radio/si470x/radio-si470x-i2c.c | 1 + drivers/media/radio/si470x/radio-si470x-usb.c | 1 + drivers/media/radio/si470x/radio-si470x.h | 1 + 4 files changed, 126 insertions(+), 92 deletions(-) diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 84ab3d5776da..9e38132afec6 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -4,6 +4,7 @@ * Driver for radios with Silicon Labs Si470x FM Radio Receivers * * Copyright (c) 2009 Tobias Lorenz + * Copyright (c) 2012 Hans de Goede * * 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 @@ -127,14 +128,6 @@ static unsigned short space = 2; module_param(space, ushort, 0444); MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); -/* Bottom of Band (MHz) */ -/* 0: 87.5 - 108 MHz (USA, Europe)*/ -/* 1: 76 - 108 MHz (Japan wide band) */ -/* 2: 76 - 90 MHz (Japan) */ -static unsigned short band = 1; -module_param(band, ushort, 0444); -MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); - /* De-emphasis */ /* 0: 75 us (USA) */ /* 1: 50 us (Europe, Australia, Japan) */ @@ -152,12 +145,60 @@ static unsigned int seek_timeout = 5000; module_param(seek_timeout, uint, 0644); MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); - +static const struct v4l2_frequency_band bands[] = { + { + .type = V4L2_TUNER_RADIO, + .index = 0, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_WRAP, + .rangelow = 87500 * 16, + .rangehigh = 108000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 1, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_WRAP, + .rangelow = 76000 * 16, + .rangehigh = 108000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 2, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_WRAP, + .rangelow = 76000 * 16, + .rangehigh = 90000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, +}; /************************************************************************** * Generic Functions **************************************************************************/ +/* + * si470x_set_band - set the band + */ +static int si470x_set_band(struct si470x_device *radio, int band) +{ + if (radio->band == band) + return 0; + + radio->band = band; + radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_BAND; + radio->registers[SYSCONFIG2] |= radio->band << 6; + return si470x_set_register(radio, SYSCONFIG2); +} + /* * si470x_set_chan - set the channel */ @@ -194,48 +235,39 @@ done: return retval; } - /* - * si470x_get_freq - get the frequency + * si470x_get_step - get channel spacing */ -static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) +static unsigned int si470x_get_step(struct si470x_device *radio) { - unsigned int spacing, band_bottom; - unsigned short chan; - int retval; - /* Spacing (kHz) */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { /* 0: 200 kHz (USA, Australia) */ case 0: - spacing = 0.200 * FREQ_MUL; break; + return 200 * 16; /* 1: 100 kHz (Europe, Japan) */ case 1: - spacing = 0.100 * FREQ_MUL; break; + return 100 * 16; /* 2: 50 kHz */ default: - spacing = 0.050 * FREQ_MUL; break; + return 50 * 16; }; +} - /* Bottom of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; break; - }; + +/* + * si470x_get_freq - get the frequency + */ +static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) +{ + int chan, retval; /* read channel */ retval = si470x_get_register(radio, READCHAN); chan = radio->registers[READCHAN] & READCHAN_READCHAN; /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ - *freq = chan * spacing + band_bottom; + *freq = chan * si470x_get_step(radio) + bands[radio->band].rangelow; return retval; } @@ -246,44 +278,12 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) */ int si470x_set_freq(struct si470x_device *radio, unsigned int freq) { - unsigned int spacing, band_bottom, band_top; unsigned short chan; - /* Spacing (kHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { - /* 0: 200 kHz (USA, Australia) */ - case 0: - spacing = 0.200 * FREQ_MUL; break; - /* 1: 100 kHz (Europe, Japan) */ - case 1: - spacing = 0.100 * FREQ_MUL; break; - /* 2: 50 kHz */ - default: - spacing = 0.050 * FREQ_MUL; break; - }; - - /* Bottom/Top of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; - band_top = 108 * FREQ_MUL; - break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; - band_top = 108 * FREQ_MUL; - break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; - band_top = 90 * FREQ_MUL; - break; - }; - - freq = clamp(freq, band_bottom, band_top); + freq = clamp(freq, bands[radio->band].rangelow, + bands[radio->band].rangehigh); /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ - chan = (freq - band_bottom) / spacing; + chan = (freq - bands[radio->band].rangelow) / si470x_get_step(radio); return si470x_set_chan(radio, chan); } @@ -293,18 +293,43 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq) * si470x_set_seek - set seek */ static int si470x_set_seek(struct si470x_device *radio, - unsigned int wrap_around, unsigned int seek_upward) + struct v4l2_hw_freq_seek *seek) { - int retval = 0; + int band, retval; + unsigned int freq; bool timed_out = 0; + /* set band */ + if (seek->rangelow || seek->rangehigh) { + for (band = 0; band < ARRAY_SIZE(bands); band++) { + if (bands[band].rangelow == seek->rangelow && + bands[band].rangehigh == seek->rangehigh) + break; + } + if (band == ARRAY_SIZE(bands)) + return -EINVAL; /* No matching band found */ + } else + band = 1; /* If nothing is specified seek 76 - 108 Mhz */ + + if (radio->band != band) { + retval = si470x_get_freq(radio, &freq); + if (retval) + return retval; + retval = si470x_set_band(radio, band); + if (retval) + return retval; + retval = si470x_set_freq(radio, freq); + if (retval) + return retval; + } + /* start seeking */ radio->registers[POWERCFG] |= POWERCFG_SEEK; - if (wrap_around == 1) + if (seek->wrap_around) radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; else radio->registers[POWERCFG] |= POWERCFG_SKMODE; - if (seek_upward == 1) + if (seek->seek_upward) radio->registers[POWERCFG] |= POWERCFG_SEEKUP; else radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; @@ -360,7 +385,7 @@ int si470x_start(struct si470x_device *radio) /* sysconfig 2 */ radio->registers[SYSCONFIG2] = (0x1f << 8) | /* SEEKTH */ - ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ + ((radio->band << 6) & SYSCONFIG2_BAND) |/* BAND */ ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ 15; /* VOLUME (max) */ retval = si470x_set_register(radio, SYSCONFIG2); @@ -569,25 +594,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP; - - /* range limits */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe, default) */ - default: - tuner->rangelow = 87.5 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 1: 76 - 108 MHz (Japan wide band) */ - case 1: - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 90 * FREQ_MUL; - break; - }; + tuner->rangelow = 76 * FREQ_MUL; + tuner->rangehigh = 108 * FREQ_MUL; /* stereo indicator == stereo (instead of mono) */ if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) @@ -670,10 +678,18 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct si470x_device *radio = video_drvdata(file); + int retval; if (freq->tuner != 0) return -EINVAL; + if (freq->frequency < bands[radio->band].rangelow || + freq->frequency > bands[radio->band].rangehigh) { + /* Switch to band 1 which covers everything we support */ + retval = si470x_set_band(radio, 1); + if (retval) + return retval; + } return si470x_set_freq(radio, freq->frequency); } @@ -689,7 +705,21 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, if (seek->tuner != 0) return -EINVAL; - return si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); + return si470x_set_seek(radio, seek); +} + +/* + * si470x_vidioc_enum_freq_bands - enumerate supported bands + */ +static int si470x_vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + if (band->tuner != 0) + return -EINVAL; + if (band->index >= ARRAY_SIZE(bands)) + return -EINVAL; + *band = bands[band->index]; + return 0; } const struct v4l2_ctrl_ops si470x_ctrl_ops = { @@ -706,6 +736,7 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = { .vidioc_g_frequency = si470x_vidioc_g_frequency, .vidioc_s_frequency = si470x_vidioc_s_frequency, .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, + .vidioc_enum_freq_bands = si470x_vidioc_enum_freq_bands, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index fb401a22b033..643a6ff7c5d0 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -350,6 +350,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, } radio->client = client; + radio->band = 1; /* Default to 76 - 108 MHz */ mutex_init(&radio->lock); init_completion(&radio->completion); diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 0204cf445387..146be4263ea1 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -597,6 +597,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, } radio->usbdev = interface_to_usbdev(intf); radio->intf = intf; + radio->band = 1; /* Default to 76 - 108 MHz */ mutex_init(&radio->lock); init_completion(&radio->completion); diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index b3586e1ec2c4..2f089b4252df 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -147,6 +147,7 @@ struct si470x_device { struct v4l2_device v4l2_dev; struct video_device videodev; struct v4l2_ctrl_handler hdl; + int band; /* Silabs internal registers (0..15) */ unsigned short registers[RADIO_REGISTER_NUM]; -- GitLab From 1fe60e51a3744528f3939b1b1167ca909133d9ae Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:23:22 -0700 Subject: [PATCH 4538/5711] libceph: move feature bits to separate header This is simply cleanup that will keep things more closely synced with the userland code. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- fs/ceph/mds_client.c | 1 + fs/ceph/super.c | 1 + include/linux/ceph/ceph_features.h | 24 ++++++++++++++++++++++++ include/linux/ceph/ceph_fs.h | 14 -------------- include/linux/ceph/libceph.h | 6 ------ net/ceph/ceph_common.c | 5 +++-- 6 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 include/linux/ceph/ceph_features.h diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 418f6a82c90d..39b76d66bc5d 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -10,6 +10,7 @@ #include "super.h" #include "mds_client.h" +#include #include #include #include diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 1e67dd7305a4..2c47ecfe4373 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -18,6 +18,7 @@ #include "super.h" #include "mds_client.h" +#include #include #include #include diff --git a/include/linux/ceph/ceph_features.h b/include/linux/ceph/ceph_features.h new file mode 100644 index 000000000000..342f93dbe162 --- /dev/null +++ b/include/linux/ceph/ceph_features.h @@ -0,0 +1,24 @@ +#ifndef __CEPH_FEATURES +#define __CEPH_FEATURES + +/* + * feature bits + */ +#define CEPH_FEATURE_UID (1<<0) +#define CEPH_FEATURE_NOSRCADDR (1<<1) +#define CEPH_FEATURE_MONCLOCKCHECK (1<<2) +#define CEPH_FEATURE_FLOCK (1<<3) +#define CEPH_FEATURE_SUBSCRIBE2 (1<<4) +#define CEPH_FEATURE_MONNAMES (1<<5) +#define CEPH_FEATURE_RECONNECT_SEQ (1<<6) +#define CEPH_FEATURE_DIRLAYOUTHASH (1<<7) + +/* + * Features supported. + */ +#define CEPH_FEATURES_SUPPORTED_DEFAULT \ + (CEPH_FEATURE_NOSRCADDR) + +#define CEPH_FEATURES_REQUIRED_DEFAULT \ + (CEPH_FEATURE_NOSRCADDR) +#endif diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index e81ab30d4896..d021610efd65 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h @@ -35,20 +35,6 @@ /* arbitrary limit on max # of monitors (cluster of 3 is typical) */ #define CEPH_MAX_MON 31 - -/* - * feature bits - */ -#define CEPH_FEATURE_UID (1<<0) -#define CEPH_FEATURE_NOSRCADDR (1<<1) -#define CEPH_FEATURE_MONCLOCKCHECK (1<<2) -#define CEPH_FEATURE_FLOCK (1<<3) -#define CEPH_FEATURE_SUBSCRIBE2 (1<<4) -#define CEPH_FEATURE_MONNAMES (1<<5) -#define CEPH_FEATURE_RECONNECT_SEQ (1<<6) -#define CEPH_FEATURE_DIRLAYOUTHASH (1<<7) - - /* * ceph_file_layout - describe data layout for a file/inode */ diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 98ec36ae8a3b..ea072e1f9db9 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -22,12 +22,6 @@ #include "osd_client.h" #include "ceph_fs.h" -/* - * Supported features - */ -#define CEPH_FEATURE_SUPPORTED_DEFAULT CEPH_FEATURE_NOSRCADDR -#define CEPH_FEATURE_REQUIRED_DEFAULT CEPH_FEATURE_NOSRCADDR - /* * mount options */ diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 3b45e01fa8d1..69e38db28e5f 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -460,9 +461,9 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, client->auth_err = 0; client->extra_mon_dispatch = NULL; - client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT | + client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT | supported_features; - client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT | + client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT | required_features; /* msgr */ -- GitLab From 6992c0807517b5736c80983c4881d3f9ae3ab20f Mon Sep 17 00:00:00 2001 From: Nicolas THERY Date: Wed, 18 Jul 2012 11:41:36 -0300 Subject: [PATCH 4539/5711] [media] v4l: DocBook: VIDIOC_CREATE_BUFS: add hyperlink Signed-off-by: Nicolas Thery Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-create-bufs.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index 5e73b1c8d095..a8cda1acacd9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml @@ -64,7 +64,7 @@ different sizes. To allocate device buffers applications initialize relevant fields of the v4l2_create_buffers structure. They set the type field in the -v4l2_format structure, embedded in this +&v4l2-format; structure, embedded in this structure, to the respective stream or buffer type. count must be set to the number of required buffers. memory specifies the required I/O method. The @@ -114,7 +114,7 @@ information. /> - struct v4l2_format + &v4l2-format; format Filled in by the application, preserved by the driver. -- GitLab From 1a17a942cd0fe430540e9ead2e57eb358b6963bd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Jul 2012 16:45:49 -0300 Subject: [PATCH 4540/5711] [media] vivi: remove pointless video_nr++ Remove the pointless video_nr++. It doesn't do anything useful and it has the unexpected side-effect of changing the video_nr module option, so cat /sys/module/vivi/parameters/video_nr gives a different value back then what was specified with modprobe. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 1e8c4f3ab602..679e329ffa15 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1330,9 +1330,6 @@ static int __init vivi_create_instance(int inst) /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); - if (video_nr != -1) - video_nr++; - v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(vfd)); return 0; -- GitLab From 3a495ed77a2f582d860472cdfca815c1dc4a5d02 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 21 Jul 2012 04:32:38 -0300 Subject: [PATCH 4541/5711] [media] tuner-xc2028: fix "=" vs "==" typo We intended to do a compare here, not an assignment. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index f88f948efee2..9e602856b2fa 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -756,7 +756,7 @@ retry: * No need to reload base firmware if it matches and if the tuner * is not at sleep mode */ - if ((priv->state = XC2028_ACTIVE) && + if ((priv->state == XC2028_ACTIVE) && (((BASE | new_fw.type) & BASE_TYPES) == (priv->cur_fw.type & BASE_TYPES))) { tuner_dbg("BASE firmware not changed.\n"); -- GitLab From dcf4fc2e2efc605382563d6ab6ba1b6f15fa28a0 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Fri, 20 Jul 2012 10:00:57 -0300 Subject: [PATCH 4542/5711] [media] davinci: vpbe: fix check for s_dv_preset function pointer fix check for s_dv_preset function pointer to be NULL. return -EINVAL if function pointer is NULL. Signed-off-by: Lad, Prabhakar Signed-off-by: Manjunath Hadli Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpbe_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c index e106b72810a9..f78ccc00bc4b 100644 --- a/drivers/media/video/davinci/vpbe_display.c +++ b/drivers/media/video/davinci/vpbe_display.c @@ -1083,7 +1083,7 @@ vpbe_display_s_dv_preset(struct file *file, void *priv, } /* Set the given standard in the encoder */ - if (NULL != vpbe_dev->ops.s_dv_preset) + if (!vpbe_dev->ops.s_dv_preset) return -EINVAL; ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset); -- GitLab From 79980d9c985aa58db50f388634739419e2e20a5a Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 20 Jul 2012 16:35:17 -0300 Subject: [PATCH 4543/5711] [media] Documentation: Add newline at end-of-file to files lacking one This patch simply adds a newline character at end-of-file to those files in Documentation/ that currently lack one. This is done for a few different reasons: A) It's rather annoying when you do "cat some_file.txt" that your prompt/cursor ends up at the end of the last line of output rather than on a new line. B) Some tools that process files line-by-line may get confused by the lack of a newline on the last line. C) The "\ No newline at end of file" line in diffs annoys me for some reason. So, let's just add the missing newline once and for all. Signed-off-by: Jesper Juhl Signed-off-by: Mauro Carvalho Chehab --- Documentation/ABI/stable/vdso | 2 +- Documentation/ABI/testing/sysfs-block-zram | 2 +- Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg | 2 +- Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 | 2 +- Documentation/arm/Samsung-S3C24XX/H1940.txt | 2 +- Documentation/arm/Samsung-S3C24XX/SMDK2440.txt | 2 +- Documentation/sound/alsa/hdspm.txt | 2 +- Documentation/video4linux/cpia2_overview.txt | 2 +- Documentation/video4linux/stv680.txt | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/ABI/stable/vdso b/Documentation/ABI/stable/vdso index 8a1cbb594497..7cdfc28cc2c6 100644 --- a/Documentation/ABI/stable/vdso +++ b/Documentation/ABI/stable/vdso @@ -24,4 +24,4 @@ though. (As of this writing, this ABI documentation as been confirmed for x86_64. The maintainers of the other vDSO-using architectures should confirm - that it is correct for their architecture.) \ No newline at end of file + that it is correct for their architecture.) diff --git a/Documentation/ABI/testing/sysfs-block-zram b/Documentation/ABI/testing/sysfs-block-zram index c8b3b48ec62c..ec93fe33baa6 100644 --- a/Documentation/ABI/testing/sysfs-block-zram +++ b/Documentation/ABI/testing/sysfs-block-zram @@ -96,4 +96,4 @@ Description: overhead, allocated for this disk. So, allocator space efficiency can be calculated using compr_data_size and this statistic. - Unit: bytes \ No newline at end of file + Unit: bytes diff --git a/Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg b/Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg index cb830df8777c..70d00dfa443d 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg +++ b/Documentation/ABI/testing/sysfs-bus-usb-devices-usbsevseg @@ -40,4 +40,4 @@ Description: Controls the decimal places on the device. the value of 10 ** n. Assume this field has the value k and has 1 or more decimal places set, to set the mth place (where m is not already set), - change this fields value to k + 10 ** m. \ No newline at end of file + change this fields value to k + 10 ** m. diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 index 4a9c545bda4b..33e648808117 100644 --- a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 +++ b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 @@ -53,4 +53,4 @@ Description: Documentation/ABI/stable/sysfs-class-backlight. It can be enabled by writing the value stored in /sys/class/backlight//max_brightness to - /sys/class/backlight//brightness. \ No newline at end of file + /sys/class/backlight//brightness. diff --git a/Documentation/arm/Samsung-S3C24XX/H1940.txt b/Documentation/arm/Samsung-S3C24XX/H1940.txt index f4a7b22c8664..b738859b1fc0 100644 --- a/Documentation/arm/Samsung-S3C24XX/H1940.txt +++ b/Documentation/arm/Samsung-S3C24XX/H1940.txt @@ -37,4 +37,4 @@ Maintainers Thanks to the many others who have also provided support. -(c) 2005 Ben Dooks \ No newline at end of file +(c) 2005 Ben Dooks diff --git a/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt index 32e1eae6a25f..429390bd4684 100644 --- a/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt +++ b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt @@ -53,4 +53,4 @@ Maintainers and to Simtec Electronics for allowing me time to work on this. -(c) 2004 Ben Dooks \ No newline at end of file +(c) 2004 Ben Dooks diff --git a/Documentation/sound/alsa/hdspm.txt b/Documentation/sound/alsa/hdspm.txt index 7a67ff71a9f8..7ba31948dea7 100644 --- a/Documentation/sound/alsa/hdspm.txt +++ b/Documentation/sound/alsa/hdspm.txt @@ -359,4 +359,4 @@ Calling Parameter: enable_monitor int array (min = 1, max = 8), "Enable Analog Out on Channel 63/64 by default." - note: here the analog output is enabled (but not routed). \ No newline at end of file + note: here the analog output is enabled (but not routed). diff --git a/Documentation/video4linux/cpia2_overview.txt b/Documentation/video4linux/cpia2_overview.txt index a6e53665216b..ad6adbedfe50 100644 --- a/Documentation/video4linux/cpia2_overview.txt +++ b/Documentation/video4linux/cpia2_overview.txt @@ -35,4 +35,4 @@ the camera. There are three modes for this. Block mode requests a number of contiguous registers. Random mode reads or writes random registers with a tuple structure containing address/value pairs. The repeat mode is only used by VP4 to load a firmware patch. It contains a starting address and -a sequence of bytes to be written into a gpio port. \ No newline at end of file +a sequence of bytes to be written into a gpio port. diff --git a/Documentation/video4linux/stv680.txt b/Documentation/video4linux/stv680.txt index 4f8946f32f51..e3de33645308 100644 --- a/Documentation/video4linux/stv680.txt +++ b/Documentation/video4linux/stv680.txt @@ -50,4 +50,4 @@ The latest info on this driver can be found at: http://personal.clt.bellsouth.net/~kjsisson or at http://stv0680-usb.sourceforge.net -Any questions to me can be send to: kjsisson@bellsouth.net \ No newline at end of file +Any questions to me can be send to: kjsisson@bellsouth.net -- GitLab From f088ccd6404ca5966104afcae319384f41a0b8cb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 21 Jul 2012 04:32:59 -0300 Subject: [PATCH 4544/5711] [media] tuner-xc2028: unlock on error in xc2028_get_afc() We need to do a mutex_unlock(&priv->lock) before returning. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 9e602856b2fa..ea0550eafe7d 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -978,7 +978,7 @@ static int xc2028_get_afc(struct dvb_frontend *fe, s32 *afc) /* Get AFC */ rc = xc2028_get_reg(priv, XREG_FREQ_ERROR, &afc_reg); if (rc < 0) - return rc; + goto ret; *afc = afc_reg * 15625; /* Hz */ -- GitLab From 53aa3b19c584faf0ea6e4cc910a9ff4ac31e2390 Mon Sep 17 00:00:00 2001 From: Nicolas THERY Date: Fri, 20 Jul 2012 09:25:37 -0300 Subject: [PATCH 4545/5711] [media] v4l: fix copy/paste typo in vb2_reqbufs comment Signed-off-by: Nicolas Thery Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 4e0290ab5071..268c7dd4f823 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -715,8 +715,8 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create } /** - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and - * type values. + * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the + * memory and type values. * @q: videobuf2 queue * @create: creation parameters, passed from userspace to vidioc_create_bufs * handler in driver -- GitLab From 4927c3f1c48fff3473b684d2dac5b4e432861b4e Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Fri, 20 Jul 2012 09:56:48 -0300 Subject: [PATCH 4546/5711] [media] davinci: vpbe: fix build error when CONFIG_VIDEO_ADV_DEBUG is enabled Fix build error when CONFIG_VIDEO_ADV_DEBUG is enabled, declare the vpbe_dev variable. Signed-off-by: Lad, Prabhakar Signed-off-by: Manjunath Hadli Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpbe_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c index f78ccc00bc4b..6fe7034bea7c 100644 --- a/drivers/media/video/davinci/vpbe_display.c +++ b/drivers/media/video/davinci/vpbe_display.c @@ -1517,6 +1517,8 @@ static int vpbe_display_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct v4l2_dbg_match *match = ®->match; + struct vpbe_fh *fh = file->private_data; + struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; if (match->type >= 2) { v4l2_subdev_call(vpbe_dev->venc, -- GitLab From 908d4d141f9608d1966ea8b483ee1c1aad04e438 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 11:50:49 -0300 Subject: [PATCH 4547/5711] [media] ov9640: fix missing break Without this rev2 ends up behaving as rev3 Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44081 Reported-by: dcb314@hotmail.com Signed-off-by: Alan Cox Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov9640.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 23412debb36b..9ed4ba4236c4 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -605,6 +605,7 @@ static int ov9640_video_probe(struct i2c_client *client) devname = "ov9640"; priv->model = V4L2_IDENT_OV9640; priv->revision = 2; + break; case OV9640_V3: devname = "ov9640"; priv->model = V4L2_IDENT_OV9640; -- GitLab From c79a3c352469ea0a9cb2ed9e32c1932a7ff66c5c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 12:00:24 -0300 Subject: [PATCH 4548/5711] [media] cx25821,medusa: incorrect check on decoder type Unsupported requests should be ignored but in fact affected VDEC_A Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44051 Reported-by: dcb314@hotmail.com Signed-off-by: Alan Cox Cc: Palash Bandyopadhyay Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25821/cx25821-medusa-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c index 313fb20a0b47..6a92e5c70c2a 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/video/cx25821/cx25821-medusa-video.c @@ -499,7 +499,7 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, mutex_lock(&dev->lock); /* no support */ - if (decoder < VDEC_A && decoder > VDEC_H) { + if (decoder < VDEC_A || decoder > VDEC_H) { mutex_unlock(&dev->lock); return; } -- GitLab From 3bbae04b126fbd4c191b4167ea46ba9c4da46425 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 10:03:52 +1000 Subject: [PATCH 4549/5711] MD RAID10: Fix compiler warning. MD RAID10: Fix compiler warning. Initialize variable to prevent compiler warning. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8da6282254c3..b3d79db35e9b 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -717,7 +717,7 @@ static struct md_rdev *read_balance(struct r10conf *conf, int sectors = r10_bio->sectors; int best_good_sectors; sector_t new_distance, best_dist; - struct md_rdev *rdev, *best_rdev; + struct md_rdev *best_rdev, *rdev = NULL; int do_balance; int best_slot; struct geom *geo = &conf->geo; -- GitLab From dc280d987f039ef35ac1e59c09b7154b61f385cf Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 10:03:52 +1000 Subject: [PATCH 4550/5711] MD RAID10: rename mirror_info structure MD RAID10: Rename the structure 'mirror_info' to 'raid10_info' The same structure name ('mirror_info') is used by raid1. Each of these structures are defined in there respective header files. If dm-raid is to support both RAID1 and RAID10, the header files will be included and the structure names must not collide. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid10.c | 18 +++++++++--------- drivers/md/raid10.h | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b3d79db35e9b..f9c4baa7964d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1546,7 +1546,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) static void print_conf(struct r10conf *conf) { int i; - struct mirror_info *tmp; + struct raid10_info *tmp; printk(KERN_DEBUG "RAID10 conf printout:\n"); if (!conf) { @@ -1580,7 +1580,7 @@ static int raid10_spare_active(struct mddev *mddev) { int i; struct r10conf *conf = mddev->private; - struct mirror_info *tmp; + struct raid10_info *tmp; int count = 0; unsigned long flags; @@ -1655,7 +1655,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) else mirror = first; for ( ; mirror <= last ; mirror++) { - struct mirror_info *p = &conf->mirrors[mirror]; + struct raid10_info *p = &conf->mirrors[mirror]; if (p->recovery_disabled == mddev->recovery_disabled) continue; if (p->rdev) { @@ -1709,7 +1709,7 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev) int err = 0; int number = rdev->raid_disk; struct md_rdev **rdevp; - struct mirror_info *p = conf->mirrors + number; + struct raid10_info *p = conf->mirrors + number; print_conf(conf); if (rdev == p->rdev) @@ -2876,7 +2876,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, sector_t sect; int must_sync; int any_working; - struct mirror_info *mirror = &conf->mirrors[i]; + struct raid10_info *mirror = &conf->mirrors[i]; if ((mirror->rdev == NULL || test_bit(In_sync, &mirror->rdev->flags)) @@ -3388,7 +3388,7 @@ static struct r10conf *setup_conf(struct mddev *mddev) goto out; /* FIXME calc properly */ - conf->mirrors = kzalloc(sizeof(struct mirror_info)*(mddev->raid_disks + + conf->mirrors = kzalloc(sizeof(struct raid10_info)*(mddev->raid_disks + max(0,mddev->delta_disks)), GFP_KERNEL); if (!conf->mirrors) @@ -3452,7 +3452,7 @@ static int run(struct mddev *mddev) { struct r10conf *conf; int i, disk_idx, chunk_size; - struct mirror_info *disk; + struct raid10_info *disk; struct md_rdev *rdev; sector_t size; sector_t min_offset_diff = 0; @@ -3805,7 +3805,7 @@ static int raid10_check_reshape(struct mddev *mddev) if (mddev->delta_disks > 0) { /* allocate new 'mirrors' list */ conf->mirrors_new = kzalloc( - sizeof(struct mirror_info) + sizeof(struct raid10_info) *(mddev->raid_disks + mddev->delta_disks), GFP_KERNEL); @@ -3930,7 +3930,7 @@ static int raid10_start_reshape(struct mddev *mddev) spin_lock_irq(&conf->device_lock); if (conf->mirrors_new) { memcpy(conf->mirrors_new, conf->mirrors, - sizeof(struct mirror_info)*conf->prev.raid_disks); + sizeof(struct raid10_info)*conf->prev.raid_disks); smp_mb(); kfree(conf->mirrors_old); /* FIXME and elsewhere */ conf->mirrors_old = conf->mirrors; diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 135b1b0a1554..ecdb440b003a 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -1,7 +1,7 @@ #ifndef _RAID10_H #define _RAID10_H -struct mirror_info { +struct raid10_info { struct md_rdev *rdev, *replacement; sector_t head_position; int recovery_disabled; /* matches @@ -13,8 +13,8 @@ struct mirror_info { struct r10conf { struct mddev *mddev; - struct mirror_info *mirrors; - struct mirror_info *mirrors_new, *mirrors_old; + struct raid10_info *mirrors; + struct raid10_info *mirrors_new, *mirrors_old; spinlock_t device_lock; /* geometry */ -- GitLab From 0eaf822cb3dfcf2a64b2d27f4f6219186adb2695 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 10:03:52 +1000 Subject: [PATCH 4551/5711] MD RAID1: rename mirror_info structure MD RAID1: Rename the structure 'mirror_info' to 'raid1_info' The same structure name ('mirror_info') is used by raid10. Each of these structures are defined in there respective header files. If dm-raid is to support both RAID1 and RAID10, the header files will be included and the structure names must not collide. While only one of these structure names needs to change, this patch adds consistency to the naming of the structure. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid1.c | 14 +++++++------- drivers/md/raid1.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index cacd008d6864..57d6abd497ef 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -873,7 +873,7 @@ do_sync_io: static void make_request(struct mddev *mddev, struct bio * bio) { struct r1conf *conf = mddev->private; - struct mirror_info *mirror; + struct raid1_info *mirror; struct r1bio *r1_bio; struct bio *read_bio; int i, disks; @@ -1364,7 +1364,7 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) struct r1conf *conf = mddev->private; int err = -EEXIST; int mirror = 0; - struct mirror_info *p; + struct raid1_info *p; int first = 0; int last = conf->raid_disks - 1; struct request_queue *q = bdev_get_queue(rdev->bdev); @@ -1433,7 +1433,7 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev) struct r1conf *conf = mddev->private; int err = 0; int number = rdev->raid_disk; - struct mirror_info *p = conf->mirrors+ number; + struct raid1_info *p = conf->mirrors + number; if (rdev != p->rdev) p = conf->mirrors + conf->raid_disks + number; @@ -2521,7 +2521,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) { struct r1conf *conf; int i; - struct mirror_info *disk; + struct raid1_info *disk; struct md_rdev *rdev; int err = -ENOMEM; @@ -2529,7 +2529,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) if (!conf) goto abort; - conf->mirrors = kzalloc(sizeof(struct mirror_info) + conf->mirrors = kzalloc(sizeof(struct raid1_info) * mddev->raid_disks * 2, GFP_KERNEL); if (!conf->mirrors) @@ -2798,7 +2798,7 @@ static int raid1_reshape(struct mddev *mddev) */ mempool_t *newpool, *oldpool; struct pool_info *newpoolinfo; - struct mirror_info *newmirrors; + struct raid1_info *newmirrors; struct r1conf *conf = mddev->private; int cnt, raid_disks; unsigned long flags; @@ -2841,7 +2841,7 @@ static int raid1_reshape(struct mddev *mddev) kfree(newpoolinfo); return -ENOMEM; } - newmirrors = kzalloc(sizeof(struct mirror_info) * raid_disks * 2, + newmirrors = kzalloc(sizeof(struct raid1_info) * raid_disks * 2, GFP_KERNEL); if (!newmirrors) { kfree(newpoolinfo); diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 80ded139314c..6b49336575fe 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -1,7 +1,7 @@ #ifndef _RAID1_H #define _RAID1_H -struct mirror_info { +struct raid1_info { struct md_rdev *rdev; sector_t head_position; }; @@ -24,7 +24,7 @@ struct pool_info { struct r1conf { struct mddev *mddev; - struct mirror_info *mirrors; /* twice 'raid_disks' to + struct raid1_info *mirrors; /* twice 'raid_disks' to * allow for replacements. */ int raid_disks; -- GitLab From 473e87ce485ffcac041f7911b33f0b4cd4d6cf2b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 10:03:52 +1000 Subject: [PATCH 4552/5711] MD: Move macros from raid1*.h to raid1*.c MD RAID1/RAID10: Move some macros from .h file to .c file There are three macros (IO_BLOCKED,IO_MADE_GOOD,BIO_SPECIAL) which are defined in both raid1.h and raid10.h. They are only used in there respective .c files. However, if we wish to make RAID10 accessible to the device-mapper RAID target (dm-raid.c), then we need to move these macros into the .c files where they are used so that they do not conflict with each other. The macros from the two files are identical and could be moved into md.h, but I chose to leave the duplication and have them remain in the personality files. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid1.c | 14 ++++++++++++++ drivers/md/raid1.h | 14 -------------- drivers/md/raid10.c | 16 +++++++++++++++- drivers/md/raid10.h | 14 -------------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 57d6abd497ef..d3d3568b4fb1 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -46,6 +46,20 @@ */ #define NR_RAID1_BIOS 256 +/* when we get a read error on a read-only array, we redirect to another + * device without failing the first device, or trying to over-write to + * correct the read error. To keep track of bad blocks on a per-bio + * level, we store IO_BLOCKED in the appropriate 'bios' pointer + */ +#define IO_BLOCKED ((struct bio *)1) +/* When we successfully write to a known bad-block, we need to remove the + * bad-block marking which must be done from process context. So we record + * the success by setting devs[n].bio to IO_MADE_GOOD + */ +#define IO_MADE_GOOD ((struct bio *)2) + +#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2) + /* When there are this many requests queue to be written by * the raid1 thread, we become 'congested' to provide back-pressure * for writeback. diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 6b49336575fe..4e3613daaea2 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -135,20 +135,6 @@ struct r1bio { /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/ }; -/* when we get a read error on a read-only array, we redirect to another - * device without failing the first device, or trying to over-write to - * correct the read error. To keep track of bad blocks on a per-bio - * level, we store IO_BLOCKED in the appropriate 'bios' pointer - */ -#define IO_BLOCKED ((struct bio *)1) -/* When we successfully write to a known bad-block, we need to remove the - * bad-block marking which must be done from process context. So we record - * the success by setting bios[n] to IO_MADE_GOOD - */ -#define IO_MADE_GOOD ((struct bio *)2) - -#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2) - /* bits for r1bio.state */ #define R1BIO_Uptodate 0 #define R1BIO_IsSync 1 diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f9c4baa7964d..e77acf024055 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -60,7 +60,21 @@ */ #define NR_RAID10_BIOS 256 -/* When there are this many requests queue to be written by +/* when we get a read error on a read-only array, we redirect to another + * device without failing the first device, or trying to over-write to + * correct the read error. To keep track of bad blocks on a per-bio + * level, we store IO_BLOCKED in the appropriate 'bios' pointer + */ +#define IO_BLOCKED ((struct bio *)1) +/* When we successfully write to a known bad-block, we need to remove the + * bad-block marking which must be done from process context. So we record + * the success by setting devs[n].bio to IO_MADE_GOOD + */ +#define IO_MADE_GOOD ((struct bio *)2) + +#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2) + +/* When there are this many requests queued to be written by * the raid10 thread, we become 'congested' to provide back-pressure * for writeback. */ diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index ecdb440b003a..b0a435869dca 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -123,20 +123,6 @@ struct r10bio { } devs[0]; }; -/* when we get a read error on a read-only array, we redirect to another - * device without failing the first device, or trying to over-write to - * correct the read error. To keep track of bad blocks on a per-bio - * level, we store IO_BLOCKED in the appropriate 'bios' pointer - */ -#define IO_BLOCKED ((struct bio*)1) -/* When we successfully write to a known bad-block, we need to remove the - * bad-block marking which must be done from process context. So we record - * the success by setting devs[n].bio to IO_MADE_GOOD - */ -#define IO_MADE_GOOD ((struct bio *)2) - -#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2) - /* bits for r10bio.state */ enum r10bio_state { R10BIO_Uptodate, -- GitLab From cc4d1efdd017083bbcbaf23feb4cdc717fa7dab8 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 10:03:53 +1000 Subject: [PATCH 4553/5711] MD RAID10: Export md_raid10_congested md/raid10: Export is_congested test. In similar fashion to commits 11d8a6e3719519fbc0e2c9d61b6fa931b84bf813 1ed7242e591af7e233234d483f12d33818b189d9 we export the RAID10 congestion checking function so that dm-raid.c can make use of it and make use of the personality. The 'queue' and 'gendisk' structures will not be available to the MD code when device-mapper sets up the device, so we conditionalize access to these fields also. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid10.c | 56 +++++++++++++++++++++++++++------------------ drivers/md/raid10.h | 3 +++ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index e77acf024055..e2549deab7c3 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -853,9 +853,8 @@ retry: return rdev; } -static int raid10_congested(void *data, int bits) +int md_raid10_congested(struct mddev *mddev, int bits) { - struct mddev *mddev = data; struct r10conf *conf = mddev->private; int i, ret = 0; @@ -863,8 +862,6 @@ static int raid10_congested(void *data, int bits) conf->pending_count >= max_queued_requests) return 1; - if (mddev_congested(mddev, bits)) - return 1; rcu_read_lock(); for (i = 0; (i < conf->geo.raid_disks || i < conf->prev.raid_disks) @@ -880,6 +877,15 @@ static int raid10_congested(void *data, int bits) rcu_read_unlock(); return ret; } +EXPORT_SYMBOL_GPL(md_raid10_congested); + +static int raid10_congested(void *data, int bits) +{ + struct mddev *mddev = data; + + return mddev_congested(mddev, bits) || + md_raid10_congested(mddev, bits); +} static void flush_pending_writes(struct r10conf *conf) { @@ -3486,12 +3492,14 @@ static int run(struct mddev *mddev) conf->thread = NULL; chunk_size = mddev->chunk_sectors << 9; - blk_queue_io_min(mddev->queue, chunk_size); - if (conf->geo.raid_disks % conf->geo.near_copies) - blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); - else - blk_queue_io_opt(mddev->queue, chunk_size * - (conf->geo.raid_disks / conf->geo.near_copies)); + if (mddev->queue) { + blk_queue_io_min(mddev->queue, chunk_size); + if (conf->geo.raid_disks % conf->geo.near_copies) + blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); + else + blk_queue_io_opt(mddev->queue, chunk_size * + (conf->geo.raid_disks / conf->geo.near_copies)); + } rdev_for_each(rdev, mddev) { long long diff; @@ -3525,8 +3533,9 @@ static int run(struct mddev *mddev) if (first || diff < min_offset_diff) min_offset_diff = diff; - disk_stack_limits(mddev->gendisk, rdev->bdev, - rdev->data_offset << 9); + if (mddev->gendisk) + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); disk->head_position = 0; } @@ -3589,22 +3598,22 @@ static int run(struct mddev *mddev) md_set_array_sectors(mddev, size); mddev->resync_max_sectors = size; - mddev->queue->backing_dev_info.congested_fn = raid10_congested; - mddev->queue->backing_dev_info.congested_data = mddev; - - /* Calculate max read-ahead size. - * We need to readahead at least twice a whole stripe.... - * maybe... - */ - { + if (mddev->queue) { int stripe = conf->geo.raid_disks * ((mddev->chunk_sectors << 9) / PAGE_SIZE); + mddev->queue->backing_dev_info.congested_fn = raid10_congested; + mddev->queue->backing_dev_info.congested_data = mddev; + + /* Calculate max read-ahead size. + * We need to readahead at least twice a whole stripe.... + * maybe... + */ stripe /= conf->geo.near_copies; if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe) mddev->queue->backing_dev_info.ra_pages = 2 * stripe; + blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); } - blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); if (md_integrity_register(mddev)) goto out_free_conf; @@ -3655,7 +3664,10 @@ static int stop(struct mddev *mddev) lower_barrier(conf); md_unregister_thread(&mddev->thread); - blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ + if (mddev->queue) + /* the unplug fn references 'conf'*/ + blk_sync_queue(mddev->queue); + if (conf->r10bio_pool) mempool_destroy(conf->r10bio_pool); kfree(conf->mirrors); diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index b0a435869dca..007c2c68dd83 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -145,4 +145,7 @@ enum r10bio_state { */ R10BIO_Previous, }; + +extern int md_raid10_congested(struct mddev *mddev, int bits); + #endif -- GitLab From be4d3280b17bc51f23ec6ebb345728f302f80a0c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Jul 2012 10:03:53 +1000 Subject: [PATCH 4554/5711] md/raid1: make sequential read detection per disk based Currently the sequential read detection is global wide. It's natural to make it per disk based, which can improve the detection for concurrent multiple sequential reads. And next patch will make SSD read balance not use distance based algorithm, where this change help detect truly sequential read for SSD. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid1.c | 35 +++++++---------------------------- drivers/md/raid1.h | 11 +++++------ 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d3d3568b4fb1..fb96c0c2db40 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -497,9 +497,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect const sector_t this_sector = r1_bio->sector; int sectors; int best_good_sectors; - int start_disk; int best_disk; - int i; + int disk; sector_t best_dist; struct md_rdev *rdev; int choose_first; @@ -517,23 +516,16 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect best_good_sectors = 0; if (conf->mddev->recovery_cp < MaxSector && - (this_sector + sectors >= conf->next_resync)) { + (this_sector + sectors >= conf->next_resync)) choose_first = 1; - start_disk = 0; - } else { + else choose_first = 0; - start_disk = conf->last_used; - } - for (i = 0 ; i < conf->raid_disks * 2 ; i++) { + for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) { sector_t dist; sector_t first_bad; int bad_sectors; - int disk = start_disk + i; - if (disk >= conf->raid_disks * 2) - disk -= conf->raid_disks * 2; - rdev = rcu_dereference(conf->mirrors[disk].rdev); if (r1_bio->bios[disk] == IO_BLOCKED || rdev == NULL @@ -594,7 +586,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect dist = abs(this_sector - conf->mirrors[disk].head_position); if (choose_first /* Don't change to another disk for sequential reads */ - || conf->next_seq_sect == this_sector + || conf->mirrors[disk].next_seq_sect == this_sector || dist == 0 /* If device is idle, use it */ || atomic_read(&rdev->nr_pending) == 0) { @@ -620,8 +612,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect goto retry; } sectors = best_good_sectors; - conf->next_seq_sect = this_sector + sectors; - conf->last_used = best_disk; + conf->mirrors[best_disk].next_seq_sect = this_sector + sectors; } rcu_read_unlock(); *max_sectors = sectors; @@ -2599,7 +2590,6 @@ static struct r1conf *setup_conf(struct mddev *mddev) conf->recovery_disabled = mddev->recovery_disabled - 1; err = -EIO; - conf->last_used = -1; for (i = 0; i < conf->raid_disks * 2; i++) { disk = conf->mirrors + i; @@ -2625,19 +2615,9 @@ static struct r1conf *setup_conf(struct mddev *mddev) if (disk->rdev && (disk->rdev->saved_raid_disk < 0)) conf->fullsync = 1; - } else if (conf->last_used < 0) - /* - * The first working device is used as a - * starting point to read balancing. - */ - conf->last_used = i; + } } - if (conf->last_used < 0) { - printk(KERN_ERR "md/raid1:%s: no operational mirrors\n", - mdname(mddev)); - goto abort; - } err = -ENOMEM; conf->thread = md_register_thread(raid1d, mddev, "raid1"); if (!conf->thread) { @@ -2894,7 +2874,6 @@ static int raid1_reshape(struct mddev *mddev) conf->raid_disks = mddev->raid_disks = raid_disks; mddev->delta_disks = 0; - conf->last_used = 0; /* just make sure it is in-range */ lower_barrier(conf); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 4e3613daaea2..3770b4a27662 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -4,6 +4,11 @@ struct raid1_info { struct md_rdev *rdev; sector_t head_position; + + /* When choose the best device for a read (read_balance()) + * we try to keep sequential reads one the same device + */ + sector_t next_seq_sect; }; /* @@ -29,12 +34,6 @@ struct r1conf { */ int raid_disks; - /* When choose the best device for a read (read_balance()) - * we try to keep sequential reads one the same device - * using 'last_used' and 'next_seq_sect' - */ - int last_used; - sector_t next_seq_sect; /* During resync, read_balancing is only allowed on the part * of the array that has been resynced. 'next_resync' tells us * where that is. -- GitLab From 9dedf60313fa4dddfd5b9b226a0ef12a512bf9dc Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Jul 2012 10:03:53 +1000 Subject: [PATCH 4555/5711] md/raid1: read balance chooses idlest disk for SSD SSD hasn't spindle, distance between requests means nothing. And the original distance based algorithm sometimes can cause severe performance issue for SSD raid. Considering two thread groups, one accesses file A, the other access file B. The first group will access one disk and the second will access the other disk, because requests are near from one group and far between groups. In this case, read balance might keep one disk very busy but the other relative idle. For SSD, we should try best to distribute requests to as many disks as possible. There isn't spindle move penality anyway. With below patch, I can see more than 50% throughput improvement sometimes depending on workloads. The only exception is small requests can be merged to a big request which typically can drive higher throughput for SSD too. Such small requests are sequential reads. Unlike hard disk, sequential read which can't be merged (for example direct IO, or read without readahead) can be ignored for SSD. Again there is no spindle move penality. readahead dispatches small requests and such requests can be merged. Last patch can help detect sequential read well, at least if concurrent read number isn't greater than raid disk number. In that case, distance based algorithm doesn't work well too. V2: For hard disk and SSD mixed raid, doesn't use distance based algorithm for random IO too. This makes the algorithm generic for raid with SSD. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid1.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index fb96c0c2db40..d9869f25aa75 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -497,9 +497,11 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect const sector_t this_sector = r1_bio->sector; int sectors; int best_good_sectors; - int best_disk; + int best_disk, best_dist_disk, best_pending_disk; + int has_nonrot_disk; int disk; sector_t best_dist; + unsigned int min_pending; struct md_rdev *rdev; int choose_first; @@ -512,8 +514,12 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect retry: sectors = r1_bio->sectors; best_disk = -1; + best_dist_disk = -1; best_dist = MaxSector; + best_pending_disk = -1; + min_pending = UINT_MAX; best_good_sectors = 0; + has_nonrot_disk = 0; if (conf->mddev->recovery_cp < MaxSector && (this_sector + sectors >= conf->next_resync)) @@ -525,6 +531,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect sector_t dist; sector_t first_bad; int bad_sectors; + unsigned int pending; rdev = rcu_dereference(conf->mirrors[disk].rdev); if (r1_bio->bios[disk] == IO_BLOCKED @@ -583,22 +590,43 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect } else best_good_sectors = sectors; + has_nonrot_disk |= blk_queue_nonrot(bdev_get_queue(rdev->bdev)); + pending = atomic_read(&rdev->nr_pending); dist = abs(this_sector - conf->mirrors[disk].head_position); if (choose_first /* Don't change to another disk for sequential reads */ || conf->mirrors[disk].next_seq_sect == this_sector || dist == 0 /* If device is idle, use it */ - || atomic_read(&rdev->nr_pending) == 0) { + || pending == 0) { best_disk = disk; break; } + + if (min_pending > pending) { + min_pending = pending; + best_pending_disk = disk; + } + if (dist < best_dist) { best_dist = dist; - best_disk = disk; + best_dist_disk = disk; } } + /* + * If all disks are rotational, choose the closest disk. If any disk is + * non-rotational, choose the disk with less pending request even the + * disk is rotational, which might/might not be optimal for raids with + * mixed ratation/non-rotational disks depending on workload. + */ + if (best_disk == -1) { + if (has_nonrot_disk) + best_disk = best_pending_disk; + else + best_disk = best_dist_disk; + } + if (best_disk >= 0) { rdev = rcu_dereference(conf->mirrors[best_disk].rdev); if (!rdev) -- GitLab From 12cee5a8a29e7263e39953f1d941f723c617ca5f Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Jul 2012 10:03:53 +1000 Subject: [PATCH 4556/5711] md/raid1: prevent merging too large request For SSD, if request size exceeds specific value (optimal io size), request size isn't important for bandwidth. In such condition, if making request size bigger will cause some disks idle, the total throughput will actually drop. A good example is doing a readahead in a two-disk raid1 setup. So when should we split big requests? We absolutly don't want to split big request to very small requests. Even in SSD, big request transfer is more efficient. This patch only considers request with size above optimal io size. If all disks are busy, is it worth doing a split? Say optimal io size is 16k, two requests 32k and two disks. We can let each disk run one 32k request, or split the requests to 4 16k requests and each disk runs two. It's hard to say which case is better, depending on hardware. So only consider case where there are idle disks. For readahead, split is always better in this case. And in my test, below patch can improve > 30% thoughput. Hmm, not 100%, because disk isn't 100% busy. Such case can happen not just in readahead, for example, in directio. But I suppose directio usually will have bigger IO depth and make all disks busy, so I ignored it. Note: if the raid uses any hard disk, we don't prevent merging. That will make performace worse. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid1.c | 56 ++++++++++++++++++++++++++++++++++++++++------ drivers/md/raid1.h | 1 + 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d9869f25aa75..7aa958ed2847 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -504,6 +504,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect unsigned int min_pending; struct md_rdev *rdev; int choose_first; + int choose_next_idle; rcu_read_lock(); /* @@ -520,6 +521,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect min_pending = UINT_MAX; best_good_sectors = 0; has_nonrot_disk = 0; + choose_next_idle = 0; if (conf->mddev->recovery_cp < MaxSector && (this_sector + sectors >= conf->next_resync)) @@ -532,6 +534,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect sector_t first_bad; int bad_sectors; unsigned int pending; + bool nonrot; rdev = rcu_dereference(conf->mirrors[disk].rdev); if (r1_bio->bios[disk] == IO_BLOCKED @@ -590,18 +593,52 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect } else best_good_sectors = sectors; - has_nonrot_disk |= blk_queue_nonrot(bdev_get_queue(rdev->bdev)); + nonrot = blk_queue_nonrot(bdev_get_queue(rdev->bdev)); + has_nonrot_disk |= nonrot; pending = atomic_read(&rdev->nr_pending); dist = abs(this_sector - conf->mirrors[disk].head_position); - if (choose_first - /* Don't change to another disk for sequential reads */ - || conf->mirrors[disk].next_seq_sect == this_sector - || dist == 0 - /* If device is idle, use it */ - || pending == 0) { + if (choose_first) { best_disk = disk; break; } + /* Don't change to another disk for sequential reads */ + if (conf->mirrors[disk].next_seq_sect == this_sector + || dist == 0) { + int opt_iosize = bdev_io_opt(rdev->bdev) >> 9; + struct raid1_info *mirror = &conf->mirrors[disk]; + + best_disk = disk; + /* + * If buffered sequential IO size exceeds optimal + * iosize, check if there is idle disk. If yes, choose + * the idle disk. read_balance could already choose an + * idle disk before noticing it's a sequential IO in + * this disk. This doesn't matter because this disk + * will idle, next time it will be utilized after the + * first disk has IO size exceeds optimal iosize. In + * this way, iosize of the first disk will be optimal + * iosize at least. iosize of the second disk might be + * small, but not a big deal since when the second disk + * starts IO, the first disk is likely still busy. + */ + if (nonrot && opt_iosize > 0 && + mirror->seq_start != MaxSector && + mirror->next_seq_sect > opt_iosize && + mirror->next_seq_sect - opt_iosize >= + mirror->seq_start) { + choose_next_idle = 1; + continue; + } + break; + } + /* If device is idle, use it */ + if (pending == 0) { + best_disk = disk; + break; + } + + if (choose_next_idle) + continue; if (min_pending > pending) { min_pending = pending; @@ -640,6 +677,10 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect goto retry; } sectors = best_good_sectors; + + if (conf->mirrors[best_disk].next_seq_sect != this_sector) + conf->mirrors[best_disk].seq_start = this_sector; + conf->mirrors[best_disk].next_seq_sect = this_sector + sectors; } rcu_read_unlock(); @@ -2605,6 +2646,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) mddev->merge_check_needed = 1; disk->head_position = 0; + disk->seq_start = MaxSector; } conf->raid_disks = mddev->raid_disks; conf->mddev = mddev; diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 3770b4a27662..0ff3715fb7eb 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -9,6 +9,7 @@ struct raid1_info { * we try to keep sequential reads one the same device */ sector_t next_seq_sect; + sector_t seq_start; }; /* -- GitLab From 3f9e7c140e4c4e75bdeeb8df46dd40e49386c978 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Tue, 31 Jul 2012 10:04:21 +1000 Subject: [PATCH 4557/5711] raid5: Add R5_ReadNoMerge flag which prevent bio from merging at block layer Because bios will merge at block-layer,so bios-error may caused by other bio which be merged into to the same request. Using this flag,it will find exactly error-sector and not do redundant operation like re-write and re-read. V0->V1:Using REQ_FLUSH instead REQ_NOMERGE avoid bio merging at block layer. Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown --- drivers/md/raid5.c | 14 ++++++++++++-- drivers/md/raid5.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c2192a2907e4..29493982dbf5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -653,6 +653,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) else bi->bi_sector = (sh->sector + rdev->data_offset); + if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) + bi->bi_rw |= REQ_FLUSH; + bi->bi_flags = 1 << BIO_UPTODATE; bi->bi_idx = 0; bi->bi_io_vec[0].bv_len = STRIPE_SIZE; @@ -1750,7 +1753,9 @@ static void raid5_end_read_request(struct bio * bi, int error) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); - } + } else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) + clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); + if (atomic_read(&rdev->read_errors)) atomic_set(&rdev->read_errors, 0); } else { @@ -1795,7 +1800,11 @@ static void raid5_end_read_request(struct bio * bi, int error) else retry = 1; if (retry) - set_bit(R5_ReadError, &sh->dev[i].flags); + if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) { + set_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); + } else + set_bit(R5_ReadNoMerge, &sh->dev[i].flags); else { clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); @@ -4515,6 +4524,7 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio) return handled; } + set_bit(R5_ReadNoMerge, &sh->dev[dd_idx].flags); handle_stripe(sh); release_stripe(sh); handled++; diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index f03fb3395183..61dbb615c30b 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -274,6 +274,7 @@ enum r5dev_flags { R5_Wantwrite, R5_Overlap, /* There is a pending overlapping request * on this block */ + R5_ReadNoMerge, /* prevent bio from merging in block-layer */ R5_ReadError, /* seen a read error here recently */ R5_ReWrite, /* have tried to over-write the readerror */ -- GitLab From 90cf195d9bcb4bf70e8b6df5073b05164b279ba0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 10:04:55 +1000 Subject: [PATCH 4558/5711] md: remove duplicated test on ->openers when calling do_md_stop() do_md_stop tests mddev->openers while holding ->open_mutex, and fails if this count is too high. So callers do not need to check mddev->openers and doing so isn't very meaningful as they don't hold ->open_mutex so the number could change. So remove the unnecessary tests on mddev->openers. These are not called often enough for there to be any gain in an early test on ->open_mutex to avoid the need for a slightly more costly mutex_lock call. Signed-off-by: NeilBrown --- drivers/md/md.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d5ab4493c8be..f6c46109b071 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3942,17 +3942,13 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) break; case clear: /* stopping an active array */ - if (atomic_read(&mddev->openers) > 0) - return -EBUSY; err = do_md_stop(mddev, 0, NULL); break; case inactive: /* stopping an active array */ - if (mddev->pers) { - if (atomic_read(&mddev->openers) > 0) - return -EBUSY; + if (mddev->pers) err = do_md_stop(mddev, 2, NULL); - } else + else err = 0; /* already inactive */ break; case suspended: -- GitLab From 5a7a570bf4205d2cc36c5abb5498df601dd828e3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 12:02:46 -0300 Subject: [PATCH 4559/5711] [media] az6007: fix incorrect memcpy Some parts of the C language are subtle and evil. This is one example. Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44041 Reported-by: dcb314@hotmail.com Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 8ffcad000ad3..86861e6f86d2 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -590,7 +590,7 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) int ret; ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); - memcpy(mac, st->data, sizeof(mac)); + memcpy(mac, st->data, 6); if (ret > 0) deb_info("%s: mac is %pM\n", __func__, mac); -- GitLab From b7219ccb33aa0df9949a60c68b5e9f712615e56f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 10:05:34 +1000 Subject: [PATCH 4560/5711] md/raid1: don't abort a resync on the first badblock. If a resync of a RAID1 array with 2 devices finds a known bad block one device it will neither read from, or write to, that device for this block offset. So there will be one read_target (The other device) and zero write targets. This condition causes md/raid1 to abort the resync assuming that it has finished - without known bad blocks this would be true. When there are no write targets because of the presence of bad blocks we should only skip over the area covered by the bad block. RAID10 already gets this right, raid1 doesn't. Or didn't. As this can cause a 'sync' to abort early and appear to have succeeded it could lead to some data corruption, so it suitable for -stable. Cc: stable@vger.kernel.org Reported-by: Alexander Lyakas Signed-off-by: NeilBrown --- drivers/md/raid1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7aa958ed2847..d2361b162de5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2502,7 +2502,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp /* There is nowhere to write, so all non-sync * drives must be failed - so we are finished */ - sector_t rv = max_sector - sector_nr; + sector_t rv; + if (min_bad > 0) + max_sector = sector_nr + min_bad; + rv = max_sector - sector_nr; *skipped = 1; put_buf(r1_bio); return rv; -- GitLab From 895e3c5c58a80bb9e4e05d9ac38b4f30e0f97d80 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Tue, 31 Jul 2012 10:05:44 +1000 Subject: [PATCH 4561/5711] md/raid5: For odirect-write performance, do not set STRIPE_PREREAD_ACTIVE. 'sync' writes set both REQ_SYNC and REQ_NOIDLE. O_DIRECT writes set REQ_SYNC but not REQ_NOIDLE. We currently assume that a REQ_SYNC request will not be followed by more requests and so set STRIPE_PREREAD_ACTIVE to expedite the request. This is appropriate for sync requests, but not for O_DIRECT requests. So make the setting of STRIPE_PREREAD_ACTIVE conditional on REQ_NOIDLE rather than REQ_SYNC. This is consistent with the documented meaning of REQ_NOIDLE: __REQ_NOIDLE, /* don't anticipate more IO after this one */ Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 29493982dbf5..259f519814ca 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4135,7 +4135,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) finish_wait(&conf->wait_for_overlap, &w); set_bit(STRIPE_HANDLE, &sh->state); clear_bit(STRIPE_DELAYED, &sh->state); - if ((bi->bi_rw & REQ_SYNC) && + if ((bi->bi_rw & REQ_NOIDLE) && !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) atomic_inc(&conf->preread_active_stripes); mddev_check_plugged(mddev); -- GitLab From e53a99eb154d1ab6a7ddcaa960b4bddc701c7c2d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 24 Jul 2012 11:06:09 -0300 Subject: [PATCH 4562/5711] [media] drivers/staging/media/easycap/easycap_main.c: add missing usb_free_urb Add missing usb_free_urb on failure path after usb_alloc_urb. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @km exists@ local idexpression e; expression e1,e2,e3; type T,T1; identifier f; @@ * e = usb_alloc_urb(...) ... when any when != e = e1 when != e1 = (T)e when != e1(...,(T)e,...) when != &e->f if(...) { ... when != e2(...,(T1)e,...) when != e3 = e when forall ( return <+...e...+>; | * return ...; ) } // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/easycap/easycap_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index aed953751a90..19d2d9d64236 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -3083,6 +3083,7 @@ static int create_video_urbs(struct easycap *peasycap) peasycap->allocation_video_urb += 1; pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); if (!pdata_urb) { + usb_free_urb(purb); SAM("ERROR: Could not allocate struct data_urb.\n"); return -ENOMEM; } -- GitLab From cd779254f92f30cef8d43d0c4345cfeebfc94db8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Jul 2012 11:48:53 -0300 Subject: [PATCH 4563/5711] [media] vivi: fix a few format-related compliance issues This patch will always set the field to INTERLACED (this fixes a bug were a driver should never return FIELD_ANY), and will default to YUYV pixelformat if an unknown pixelformat was specified. This way S/TRY_FMT will always return a valid format struct. Regards, Hans Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 679e329ffa15..a05494b71b20 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -230,7 +230,6 @@ struct vivi_dev { struct vivi_fmt *fmt; unsigned int width, height; struct vb2_queue vb_vidq; - enum v4l2_field field; unsigned int field_count; u8 bars[9][3]; @@ -623,7 +622,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) dev->mv_count += 2; - buf->vb.v4l2_buf.field = dev->field; + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; dev->field_count++; buf->vb.v4l2_buf.sequence = dev->field_count >> 1; do_gettimeofday(&ts); @@ -925,7 +924,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; - f->fmt.pix.field = dev->field; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; f->fmt.pix.pixelformat = dev->fmt->fourcc; f->fmt.pix.bytesperline = (f->fmt.pix.width * dev->fmt->depth) >> 3; @@ -944,25 +943,16 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, { struct vivi_dev *dev = video_drvdata(file); struct vivi_fmt *fmt; - enum v4l2_field field; fmt = get_format(f); if (!fmt) { - dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n", + dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n", f->fmt.pix.pixelformat); - return -EINVAL; - } - - field = f->fmt.pix.field; - - if (field == V4L2_FIELD_ANY) { - field = V4L2_FIELD_INTERLACED; - } else if (V4L2_FIELD_INTERLACED != field) { - dprintk(dev, 1, "Field type invalid.\n"); - return -EINVAL; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt = get_format(f); } - f->fmt.pix.field = field; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); f->fmt.pix.bytesperline = @@ -996,7 +986,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, dev->pixelsize = dev->fmt->depth / 8; dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; - dev->field = f->fmt.pix.field; return 0; } -- GitLab From 8f695d3f07bf9fd2914d18d1d2f89e3574b809ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Thu, 26 Jul 2012 07:59:04 -0300 Subject: [PATCH 4564/5711] [media] v4l2-dev.c: Move video_put() after debug printk It is possible that video_put() releases video_device struct, provoking a panic when debug printk wants to get video_device node name. Signed-off-by: Ezequiel Garcia Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 625248585c85..07aeafca9eaa 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -478,12 +478,12 @@ static int v4l2_open(struct inode *inode, struct file *filp) } err: - /* decrease the refcount in case of an error */ - if (ret) - video_put(vdev); if (vdev->debug) printk(KERN_DEBUG "%s: open (%d)\n", video_device_node_name(vdev), ret); + /* decrease the refcount in case of an error */ + if (ret) + video_put(vdev); return ret; } @@ -500,12 +500,12 @@ static int v4l2_release(struct inode *inode, struct file *filp) if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) mutex_unlock(vdev->lock); } - /* decrease the refcount unconditionally since the release() - return value is ignored. */ - video_put(vdev); if (vdev->debug) printk(KERN_DEBUG "%s: release\n", video_device_node_name(vdev)); + /* decrease the refcount unconditionally since the release() + return value is ignored. */ + video_put(vdev); return ret; } -- GitLab From 720bb6436ff30fccad05cf5bdf961ea5b1f5686d Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 6 Jul 2012 23:27:57 -0300 Subject: [PATCH 4565/5711] [media] Avoid sysfs oops when an rc_dev's raw device is absent For some reason, when the lirc daemon learns that a usb remote control has been unplugged, it wants to read the sysfs attributes of the disappearing device. This is useful for uncovering transient inconsistencies, but less so for keeping the system running when such inconsistencies exist. Under some circumstances (like every time I unplug my dvb stick from my laptop), lirc catches an rc_dev whose raw event handler has been removed (presumably by ir_raw_event_unregister), and proceeds to interrogate the raw protocols supported by the NULL pointer. This patch avoids the NULL dereference, and ignores the issue of how this state of affairs came about in the first place. Version 2 incorporates changes recommended by Mauro Carvalho Chehab (-ENODEV instead of -EINVAL, and a signed-off-by). Signed-off-by: Douglas Bagnall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 6e16b09c24a9..cabc19c10515 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -775,10 +775,11 @@ static ssize_t show_protocols(struct device *device, if (dev->driver_type == RC_DRIVER_SCANCODE) { enabled = dev->rc_map.rc_type; allowed = dev->allowed_protos; - } else { + } else if (dev->raw) { enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return -ENODEV; IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, -- GitLab From a342daea70c4769ce7709c0f49aa17113228c1ed Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Sat, 7 Jul 2012 03:53:28 -0300 Subject: [PATCH 4566/5711] [media] rc: ati_remote.c: code style fixing changes: 1. wrap some lines that are longer than 80 characters. 2. remove local function prototype declarations which do not need. 3. replace TAB character with a space character in function comments. Signed-off-by: Du, Changbin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ati_remote.c | 133 ++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 53 deletions(-) diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 7be377fc1be8..8fa72e2dacb1 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -147,7 +147,8 @@ static bool mouse = true; module_param(mouse, bool, 0444); MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes"); -#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) +#define dbginfo(dev, format, arg...) \ + do { if (debug) dev_info(dev , format , ## arg); } while (0) #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) @@ -191,17 +192,41 @@ static const char *get_medion_keymap(struct usb_interface *interface) return RC_MAP_MEDION_X10; } -static const struct ati_receiver_type type_ati = { .default_keymap = RC_MAP_ATI_X10 }; -static const struct ati_receiver_type type_medion = { .get_default_keymap = get_medion_keymap }; -static const struct ati_receiver_type type_firefly = { .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY }; +static const struct ati_receiver_type type_ati = { + .default_keymap = RC_MAP_ATI_X10 +}; +static const struct ati_receiver_type type_medion = { + .get_default_keymap = get_medion_keymap +}; +static const struct ati_receiver_type type_firefly = { + .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY +}; static struct usb_device_id ati_remote_table[] = { - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_medion }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_firefly }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_ati + }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_ati + }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_ati + }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_ati + }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_medion + }, + { + USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID), + .driver_info = (unsigned long)&type_firefly + }, {} /* Terminating entry */ }; @@ -296,25 +321,8 @@ static const struct { {KIND_END, 0x00, EV_MAX + 1, 0, 0} }; -/* Local function prototypes */ -static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); -static void ati_remote_irq_out (struct urb *urb); -static void ati_remote_irq_in (struct urb *urb); -static void ati_remote_input_report (struct urb *urb); -static int ati_remote_initialize (struct ati_remote *ati_remote); -static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote_disconnect (struct usb_interface *interface); - -/* usb specific object to register with the usb subsystem */ -static struct usb_driver ati_remote_driver = { - .name = "ati_remote", - .probe = ati_remote_probe, - .disconnect = ati_remote_disconnect, - .id_table = ati_remote_table, -}; - /* - * ati_remote_dump_input + * ati_remote_dump_input */ static void ati_remote_dump(struct device *dev, unsigned char *data, unsigned int len) @@ -326,12 +334,14 @@ static void ati_remote_dump(struct device *dev, unsigned char *data, dev_warn(dev, "Weird key %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]); else - dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n", - len, data[0], data[1], data[2], data[3], data[4], data[5]); + dev_warn(dev, + "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n", + len, data[0], data[1], data[2], data[3], data[4], + data[5]); } /* - * ati_remote_open + * ati_remote_open */ static int ati_remote_open(struct ati_remote *ati_remote) { @@ -355,7 +365,7 @@ out: mutex_unlock(&ati_remote->open_mutex); } /* - * ati_remote_close + * ati_remote_close */ static void ati_remote_close(struct ati_remote *ati_remote) { @@ -390,7 +400,7 @@ static void ati_remote_rc_close(struct rc_dev *rdev) } /* - * ati_remote_irq_out + * ati_remote_irq_out */ static void ati_remote_irq_out(struct urb *urb) { @@ -408,11 +418,12 @@ static void ati_remote_irq_out(struct urb *urb) } /* - * ati_remote_sendpacket + * ati_remote_sendpacket * - * Used to send device initialization strings + * Used to send device initialization strings */ -static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) +static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, + unsigned char *data) { int retval = 0; @@ -441,7 +452,7 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne } /* - * ati_remote_compute_accel + * ati_remote_compute_accel * * Implements acceleration curve for directional control pad * If elapsed time since last event is > 1/4 second, user "stopped", @@ -478,7 +489,7 @@ static int ati_remote_compute_accel(struct ati_remote *ati_remote) } /* - * ati_remote_report_input + * ati_remote_report_input */ static void ati_remote_input_report(struct urb *urb) { @@ -518,7 +529,8 @@ static void ati_remote_input_report(struct urb *urb) remote_num = (data[3] >> 4) & 0x0f; if (channel_mask & (1 << (remote_num + 1))) { dbginfo(&ati_remote->interface->dev, - "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", + "Masked input from channel 0x%02x: data %02x,%02x, " + "mask= 0x%02lx\n", remote_num, data[1], data[2], channel_mask); return; } @@ -546,7 +558,9 @@ static void ati_remote_input_report(struct urb *urb) if (wheel_keycode == KEY_RESERVED) { /* scrollwheel was not mapped, assume mouse */ - /* Look up event code index in the mouse translation table. */ + /* Look up event code index in the mouse translation + * table. + */ for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { if (scancode == ati_remote_tbl[i].data) { index = i; @@ -630,9 +644,9 @@ static void ati_remote_input_report(struct urb *urb) } else { /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. + * Other event kinds are from the directional control pad, and + * have an acceleration factor applied to them. Without this + * acceleration, the control pad is mostly unusable. */ acc = ati_remote_compute_accel(ati_remote); @@ -659,7 +673,8 @@ static void ati_remote_input_report(struct urb *urb) input_report_rel(dev, REL_Y, acc); break; default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + dev_dbg(&ati_remote->interface->dev, + "ati_remote kind=%d\n", ati_remote_tbl[index].kind); } input_sync(dev); @@ -670,7 +685,7 @@ static void ati_remote_input_report(struct urb *urb) } /* - * ati_remote_irq_in + * ati_remote_irq_in */ static void ati_remote_irq_in(struct urb *urb) { @@ -684,22 +699,25 @@ static void ati_remote_irq_in(struct urb *urb) case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: - dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", + dev_dbg(&ati_remote->interface->dev, + "%s: urb error status, unlink?\n", __func__); return; default: /* error */ - dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", + dev_dbg(&ati_remote->interface->dev, + "%s: Nonzero urb status %d\n", __func__, urb->status); } retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", + dev_err(&ati_remote->interface->dev, + "%s: usb_submit_urb()=%d\n", __func__, retval); } /* - * ati_remote_alloc_buffers + * ati_remote_alloc_buffers */ static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote) @@ -726,7 +744,7 @@ static int ati_remote_alloc_buffers(struct usb_device *udev, } /* - * ati_remote_free_buffers + * ati_remote_free_buffers */ static void ati_remote_free_buffers(struct ati_remote *ati_remote) { @@ -825,9 +843,10 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) } /* - * ati_remote_probe + * ati_remote_probe */ -static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) +static int ati_remote_probe(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); struct usb_host_interface *iface_host = interface->cur_altsetting; @@ -949,7 +968,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de } /* - * ati_remote_disconnect + * ati_remote_disconnect */ static void ati_remote_disconnect(struct usb_interface *interface) { @@ -971,6 +990,14 @@ static void ati_remote_disconnect(struct usb_interface *interface) kfree(ati_remote); } +/* usb specific object to register with the usb subsystem */ +static struct usb_driver ati_remote_driver = { + .name = "ati_remote", + .probe = ati_remote_probe, + .disconnect = ati_remote_disconnect, + .id_table = ati_remote_table, +}; + module_usb_driver(ati_remote_driver); MODULE_AUTHOR(DRIVER_AUTHOR); -- GitLab From cadc7920acd7d8fadfe98a33068af764e3247da0 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Sat, 7 Jul 2012 14:53:25 -0300 Subject: [PATCH 4567/5711] [media] lirc: fix non-ANSI function declaration warning Sparse is warning about non-ANSI function declaration. Add void to the parameterless function. drivers/staging/media/lirc/lirc_bt829.c:174:22: warning: non-ANSI function declaration of function 'poll_main' Signed-off-by: Emil Goode Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_bt829.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index 4d20e9f74118..951007a3fc96 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -171,7 +171,7 @@ static void cycle_delay(int cycle) } -static int poll_main() +static int poll_main(void) { unsigned char status_high, status_low; -- GitLab From dc32f63453f56d07a1073a697dcd843dd3098c09 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Mon, 30 Jul 2012 14:39:04 -0700 Subject: [PATCH 4568/5711] mm: fix wrong argument of migrate_huge_pages() in soft_offline_huge_page() Commit a6bc32b89922 ("mm: compaction: introduce sync-light migration for use by compaction") changed the declaration of migrate_pages() and migrate_huge_pages(). But it missed changing the argument of migrate_huge_pages() in soft_offline_huge_page(). In this case, we should call migrate_huge_pages() with MIGRATE_SYNC. Additionally, there is a mismatch between type the of argument and the function declaration for migrate_pages(). Signed-off-by: Joonsoo Kim Cc: Christoph Lameter Cc: Mel Gorman Acked-by: David Rientjes Cc: "Aneesh Kumar K.V" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index de4ce7058450..6de0d613bbe6 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1433,8 +1433,8 @@ static int soft_offline_huge_page(struct page *page, int flags) /* Keep page count to indicate a given hugepage is isolated. */ list_add(&hpage->lru, &pagelist); - ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0, - true); + ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false, + MIGRATE_SYNC); if (ret) { struct page *page1, *page2; list_for_each_entry_safe(page1, page2, &pagelist, lru) @@ -1563,7 +1563,7 @@ int soft_offline_page(struct page *page, int flags) page_is_file_cache(page)); list_add(&page->lru, &pagelist); ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, - 0, MIGRATE_SYNC); + false, MIGRATE_SYNC); if (ret) { putback_lru_pages(&pagelist); pr_info("soft offline: %#lx: migration failed %d, type %lx\n", -- GitLab From 6c4088ac3a4d82779903433bcd5f048c58fb1aca Mon Sep 17 00:00:00 2001 From: Greg Pearson Date: Mon, 30 Jul 2012 14:39:05 -0700 Subject: [PATCH 4569/5711] pcdp: use early_ioremap/early_iounmap to access pcdp table efi_setup_pcdp_console() is called during boot to parse the HCDP/PCDP EFI system table and setup an early console for printk output. The routine uses ioremap/iounmap to setup access to the HCDP/PCDP table information. The call to ioremap is happening early in the boot process which leads to a panic on x86_64 systems: panic+0x01ca do_exit+0x043c oops_end+0x00a7 no_context+0x0119 __bad_area_nosemaphore+0x0138 bad_area_nosemaphore+0x000e do_page_fault+0x0321 page_fault+0x0020 reserve_memtype+0x02a1 __ioremap_caller+0x0123 ioremap_nocache+0x0012 efi_setup_pcdp_console+0x002b setup_arch+0x03a9 start_kernel+0x00d4 x86_64_start_reservations+0x012c x86_64_start_kernel+0x00fe This replaces the calls to ioremap/iounmap in efi_setup_pcdp_console() with calls to early_ioremap/early_iounmap which can be called during early boot. This patch was tested on an x86_64 prototype system which uses the HCDP/PCDP table for early console setup. Signed-off-by: Greg Pearson Acked-by: Khalid Aziz Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/pcdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 51e0e2d8fac6..a330492e06f9 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -95,7 +95,7 @@ efi_setup_pcdp_console(char *cmdline) if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; - pcdp = ioremap(efi.hcdp, 4096); + pcdp = early_ioremap(efi.hcdp, 4096); printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); if (strstr(cmdline, "console=hcdp")) { @@ -131,6 +131,6 @@ efi_setup_pcdp_console(char *cmdline) } out: - iounmap(pcdp); + early_iounmap(pcdp, 4096); return rc; } -- GitLab From f1fd75bfa07822b1de314062baff3280419a8bf4 Mon Sep 17 00:00:00 2001 From: Sasikantha babu Date: Mon, 30 Jul 2012 14:39:08 -0700 Subject: [PATCH 4570/5711] prctl: remove redunant assignment of "error" to zero Just setting the "error" to error number is enough on failure and It doesn't require to set "error" variable to zero in each switch case, since it was already initialized with zero. And also removed return 0 in switch case with break statement Signed-off-by: Sasikantha babu Acked-by: Kees Cook Acked-by: Serge E. Hallyn Cc: Cyrill Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sys.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index 2d39a84cd857..b04ae0390df3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2015,7 +2015,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, break; } me->pdeath_signal = arg2; - error = 0; break; case PR_GET_PDEATHSIG: error = put_user(me->pdeath_signal, (int __user *)arg2); @@ -2029,7 +2028,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, break; } set_dumpable(me->mm, arg2); - error = 0; break; case PR_SET_UNALIGN: @@ -2056,10 +2054,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, case PR_SET_TIMING: if (arg2 != PR_TIMING_STATISTICAL) error = -EINVAL; - else - error = 0; break; - case PR_SET_NAME: comm[sizeof(me->comm)-1] = 0; if (strncpy_from_user(comm, (char __user *)arg2, @@ -2067,20 +2062,19 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, return -EFAULT; set_task_comm(me, comm); proc_comm_connector(me); - return 0; + break; case PR_GET_NAME: get_task_comm(comm, me); if (copy_to_user((char __user *)arg2, comm, sizeof(comm))) return -EFAULT; - return 0; + break; case PR_GET_ENDIAN: error = GET_ENDIAN(me, arg2); break; case PR_SET_ENDIAN: error = SET_ENDIAN(me, arg2); break; - case PR_GET_SECCOMP: error = prctl_get_seccomp(); break; @@ -2108,7 +2102,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, current->default_timer_slack_ns; else current->timer_slack_ns = arg2; - error = 0; break; case PR_MCE_KILL: if (arg4 | arg5) @@ -2134,7 +2127,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, default: return -EINVAL; } - error = 0; break; case PR_MCE_KILL_GET: if (arg2 | arg3 | arg4 | arg5) @@ -2153,7 +2145,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, break; case PR_SET_CHILD_SUBREAPER: me->signal->is_child_subreaper = !!arg2; - error = 0; break; case PR_GET_CHILD_SUBREAPER: error = put_user(me->signal->is_child_subreaper, -- GitLab From 32b4560b04af6e4fee241ea6de6db780eaf354f2 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Mon, 30 Jul 2012 14:39:10 -0700 Subject: [PATCH 4571/5711] ntfs: remove references to long gone super operations and unimplemented methods ->delete_inode(), ->write_super_lockfs(), ->unlockfs() are gone so remove refereces to them in the NTFS code. Remove unnecessary comments about unimplemented methods while at it (suggested by Christoph Hellwig). Noticed while cleaning up the fsfreeze mess. Signed-off-by: Fernando Luis Vazquez Cao Cc: Anton Altaparmakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ntfs/super.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index b341492542ca..2bc149d6a784 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2660,31 +2660,14 @@ static const struct super_operations ntfs_sops = { .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ .destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */ #ifdef NTFS_RW - //.dirty_inode = NULL, /* VFS: Called from - // __mark_inode_dirty(). */ .write_inode = ntfs_write_inode, /* VFS: Write dirty inode to disk. */ - //.drop_inode = NULL, /* VFS: Called just after the - // inode reference count has - // been decreased to zero. - // NOTE: The inode lock is - // held. See fs/inode.c:: - // generic_drop_inode(). */ - //.delete_inode = NULL, /* VFS: Delete inode from disk. - // Called when i_count becomes - // 0 and i_nlink is also 0. */ - //.write_super = NULL, /* Flush dirty super block to - // disk. */ - //.sync_fs = NULL, /* ? */ - //.write_super_lockfs = NULL, /* ? */ - //.unlockfs = NULL, /* ? */ #endif /* NTFS_RW */ .put_super = ntfs_put_super, /* Syscall: umount. */ .statfs = ntfs_statfs, /* Syscall: statfs */ .remount_fs = ntfs_remount, /* Syscall: mount -o remount. */ .evict_inode = ntfs_evict_big_inode, /* VFS: Called when an inode is removed from memory. */ - //.umount_begin = NULL, /* Forced umount. */ .show_options = ntfs_show_options, /* Show mount options in proc. */ }; -- GitLab From 779302e67835fe9a6b74327e54969ba59cb3478a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 30 Jul 2012 14:39:13 -0700 Subject: [PATCH 4572/5711] fs/xattr.c:getxattr(): improve handling of allocation failures This allocation can be as large as 64k. - Add __GFP_NOWARN so the falied kmalloc() is silent - Fall back to vmalloc() if the kmalloc() failed Signed-off-by: Sasha Levin Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/xattr.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index 1d7ac3790458..4d45b7189e7e 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -427,6 +427,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, { ssize_t error; void *kvalue = NULL; + void *vvalue = NULL; char kname[XATTR_NAME_MAX + 1]; error = strncpy_from_user(kname, name, sizeof(kname)); @@ -438,9 +439,13 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, if (size) { if (size > XATTR_SIZE_MAX) size = XATTR_SIZE_MAX; - kvalue = kzalloc(size, GFP_KERNEL); - if (!kvalue) - return -ENOMEM; + kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!kvalue) { + vvalue = vmalloc(size); + if (!vvalue) + return -ENOMEM; + kvalue = vvalue; + } } error = vfs_getxattr(d, kname, kvalue, size); @@ -452,7 +457,10 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, than XATTR_SIZE_MAX bytes. Not possible. */ error = -E2BIG; } - kfree(kvalue); + if (vvalue) + vfree(vvalue); + else + kfree(kvalue); return error; } -- GitLab From 9520628e8ceb69fa9a4aee6b57f22675d9e1b709 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 30 Jul 2012 14:39:15 -0700 Subject: [PATCH 4573/5711] fs: make dumpable=2 require fully qualified path When the suid_dumpable sysctl is set to "2", and there is no core dump pipe defined in the core_pattern sysctl, a local user can cause core files to be written to root-writable directories, potentially with user-controlled content. This means an admin can unknowningly reintroduce a variation of CVE-2006-2451, allowing local users to gain root privileges. $ cat /proc/sys/fs/suid_dumpable 2 $ cat /proc/sys/kernel/core_pattern core $ ulimit -c unlimited $ cd / $ ls -l core ls: cannot access core: No such file or directory $ touch core touch: cannot touch `core': Permission denied $ OHAI="evil-string-here" ping localhost >/dev/null 2>&1 & $ pid=$! $ sleep 1 $ kill -SEGV $pid $ ls -l core -rw------- 1 root kees 458752 Jun 21 11:35 core $ sudo strings core | grep evil OHAI=evil-string-here While cron has been fixed to abort reading a file when there is any parse error, there are still other sensitive directories that will read any file present and skip unparsable lines. Instead of introducing a suid_dumpable=3 mode and breaking all users of mode 2, this only disables the unsafe portion of mode 2 (writing to disk via relative path). Most users of mode 2 (e.g. Chrome OS) already use a core dump pipe handler, so this change will not break them. For the situations where a pipe handler is not defined but mode 2 is still active, crash dumps will only be written to fully qualified paths. If a relative path is defined (e.g. the default "core" pattern), dump attempts will trigger a printk yelling about the lack of a fully qualified path. Signed-off-by: Kees Cook Cc: Alexander Viro Cc: Alan Cox Cc: "Eric W. Biederman" Cc: Doug Ledford Cc: Serge Hallyn Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysctl/fs.txt | 18 ++++++++++++------ fs/exec.c | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 13d6166d7a27..8c235b6e4246 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -163,16 +163,22 @@ This value can be used to query and set the core dump mode for setuid or otherwise protected/tainted binaries. The modes are 0 - (default) - traditional behaviour. Any process which has changed - privilege levels or is execute only will not be dumped + privilege levels or is execute only will not be dumped. 1 - (debug) - all processes dump core when possible. The core dump is owned by the current user and no security is applied. This is intended for system debugging situations only. Ptrace is unchecked. + This is insecure as it allows regular users to examine the memory + contents of privileged processes. 2 - (suidsafe) - any binary which normally would not be dumped is dumped - readable by root only. This allows the end user to remove - such a dump but not access it directly. For security reasons - core dumps in this mode will not overwrite one another or - other files. This mode is appropriate when administrators are - attempting to debug problems in a normal environment. + anyway, but only if the "core_pattern" kernel sysctl is set to + either a pipe handler or a fully qualified path. (For more details + on this limitation, see CVE-2006-2451.) This mode is appropriate + when administrators are attempting to debug problems in a normal + environment, and either have a core dump pipe handler that knows + to treat privileged core dumps with care, or specific directory + defined for catching core dumps. If a core dump happens without + a pipe handler or fully qualifid path, a message will be emitted + to syslog warning about the lack of a correct setting. ============================================================== diff --git a/fs/exec.c b/fs/exec.c index e95aeeddd25c..95aae3f9c036 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -2111,6 +2111,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) int retval = 0; int flag = 0; int ispipe; + bool need_nonrelative = false; static atomic_t core_dump_count = ATOMIC_INIT(0); struct coredump_params cprm = { .signr = signr, @@ -2136,14 +2137,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) if (!cred) goto fail; /* - * We cannot trust fsuid as being the "true" uid of the - * process nor do we know its entire history. We only know it - * was tainted so we dump it as root in mode 2. + * We cannot trust fsuid as being the "true" uid of the process + * nor do we know its entire history. We only know it was tainted + * so we dump it as root in mode 2, and only into a controlled + * environment (pipe handler or fully qualified path). */ if (__get_dumpable(cprm.mm_flags) == 2) { /* Setuid core dump mode */ flag = O_EXCL; /* Stop rewrite attacks */ cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ + need_nonrelative = true; } retval = coredump_wait(exit_code, &core_state); @@ -2223,6 +2226,14 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) if (cprm.limit < binfmt->min_coredump) goto fail_unlock; + if (need_nonrelative && cn.corename[0] != '/') { + printk(KERN_WARNING "Pid %d(%s) can only dump core "\ + "to fully qualified path!\n", + task_tgid_vnr(current), current->comm); + printk(KERN_WARNING "Skipping core dump\n"); + goto fail_unlock; + } + cprm.file = filp_open(cn.corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); -- GitLab From 54b501992dd2a839e94e76aa392c392b55080ce8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 30 Jul 2012 14:39:18 -0700 Subject: [PATCH 4574/5711] coredump: warn about unsafe suid_dumpable / core_pattern combo When suid_dumpable=2, detect unsafe core_pattern settings and warn when they are seen. Signed-off-by: Kees Cook Suggested-by: Andrew Morton Cc: Alexander Viro Cc: Alan Cox Cc: "Eric W. Biederman" Cc: Doug Ledford Cc: Serge Hallyn Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 10 +++++----- include/linux/sched.h | 5 +++++ kernel/sysctl.c | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 95aae3f9c036..5af8390e0fae 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -2002,17 +2002,17 @@ static void coredump_finish(struct mm_struct *mm) void set_dumpable(struct mm_struct *mm, int value) { switch (value) { - case 0: + case SUID_DUMPABLE_DISABLED: clear_bit(MMF_DUMPABLE, &mm->flags); smp_wmb(); clear_bit(MMF_DUMP_SECURELY, &mm->flags); break; - case 1: + case SUID_DUMPABLE_ENABLED: set_bit(MMF_DUMPABLE, &mm->flags); smp_wmb(); clear_bit(MMF_DUMP_SECURELY, &mm->flags); break; - case 2: + case SUID_DUMPABLE_SAFE: set_bit(MMF_DUMP_SECURELY, &mm->flags); smp_wmb(); set_bit(MMF_DUMPABLE, &mm->flags); @@ -2025,7 +2025,7 @@ static int __get_dumpable(unsigned long mm_flags) int ret; ret = mm_flags & MMF_DUMPABLE_MASK; - return (ret >= 2) ? 2 : ret; + return (ret > SUID_DUMPABLE_ENABLED) ? SUID_DUMPABLE_SAFE : ret; } int get_dumpable(struct mm_struct *mm) @@ -2142,7 +2142,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) * so we dump it as root in mode 2, and only into a controlled * environment (pipe handler or fully qualified path). */ - if (__get_dumpable(cprm.mm_flags) == 2) { + if (__get_dumpable(cprm.mm_flags) == SUID_DUMPABLE_SAFE) { /* Setuid core dump mode */ flag = O_EXCL; /* Stop rewrite attacks */ cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ diff --git a/include/linux/sched.h b/include/linux/sched.h index a721cef7e2d4..1e26a5e45aa6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -406,6 +406,11 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {} extern void set_dumpable(struct mm_struct *mm, int value); extern int get_dumpable(struct mm_struct *mm); +/* get/set_dumpable() values */ +#define SUID_DUMPABLE_DISABLED 0 +#define SUID_DUMPABLE_ENABLED 1 +#define SUID_DUMPABLE_SAFE 2 + /* mm flags */ /* dumpable bits */ #define MMF_DUMPABLE 0 /* core dump is permitted */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4ab11879aeb4..b46f496405e4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -174,6 +174,11 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); #endif +static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); +static int proc_dostring_coredump(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); + #ifdef CONFIG_MAGIC_SYSRQ /* Note: sysrq code uses it's own private copy */ static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; @@ -410,7 +415,7 @@ static struct ctl_table kern_table[] = { .data = core_pattern, .maxlen = CORENAME_MAX_SIZE, .mode = 0644, - .proc_handler = proc_dostring, + .proc_handler = proc_dostring_coredump, }, { .procname = "core_pipe_limit", @@ -1498,7 +1503,7 @@ static struct ctl_table fs_table[] = { .data = &suid_dumpable, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax_coredump, .extra1 = &zero, .extra2 = &two, }, @@ -2009,6 +2014,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, do_proc_dointvec_minmax_conv, ¶m); } +static void validate_coredump_safety(void) +{ + if (suid_dumpable == SUID_DUMPABLE_SAFE && + core_pattern[0] != '/' && core_pattern[0] != '|') { + printk(KERN_WARNING "Unsafe core_pattern used with "\ + "suid_dumpable=2. Pipe handler or fully qualified "\ + "core dump path required.\n"); + } +} + +static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + if (!error) + validate_coredump_safety(); + return error; +} + +static int proc_dostring_coredump(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int error = proc_dostring(table, write, buffer, lenp, ppos); + if (!error) + validate_coredump_safety(); + return error; +} + static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos, -- GitLab From f107701f011e681a21b95259f950bf9c836884e0 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Mon, 30 Jul 2012 14:39:21 -0700 Subject: [PATCH 4575/5711] xtensa/mm/fault.c: port OOM changes to do_page_fault Commits d065bd810b6d ("mm: retry page fault when blocking on disk transfer") and 37b23e0525d3 ("x86,mm: make pagefault killable") introduced changes into the x86 pagefault handler for making the page fault handler retryable as well as killable. These changes reduce the mmap_sem hold time, which is crucial during OOM killer invocation. Port these changes to xtensa. Signed-off-by: Kautuk Consul Acked-by: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/mm/fault.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index b17885a0b508..5a74c53bc69c 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -44,6 +44,7 @@ void do_page_fault(struct pt_regs *regs) int is_write, is_exec; int fault; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; info.si_code = SEGV_MAPERR; @@ -71,6 +72,7 @@ void do_page_fault(struct pt_regs *regs) address, exccause, regs->pc, is_write? "w":"", is_exec? "x":""); #endif +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); @@ -93,6 +95,7 @@ good_area: if (is_write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; + flags |= FAULT_FLAG_WRITE; } else if (is_exec) { if (!(vma->vm_flags & VM_EXEC)) goto bad_area; @@ -104,7 +107,11 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return; + if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; @@ -112,10 +119,22 @@ good_area: goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + + /* No need to up_read(&mm->mmap_sem) as we would + * have already released it in __lock_page_or_retry + * in mm/filemap.c. + */ + + goto retry; + } + } up_read(&mm->mmap_sem); return; -- GitLab From 7eafef6d1d712aa9973c3cbd0013a5b66d5a6604 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 30 Jul 2012 14:39:24 -0700 Subject: [PATCH 4576/5711] alpha: remove mysterious if zero-ed out includes There's a small group of odd looking includes in smc37c669.c. These includes appear to be if zero-ed out ever since they were added to the tree (in v2.1.89). Their purpose is unclear to me. Perhaps they were used in someones build system. Whatever their purpose was, nothing else uses something comparable. This entire if zero-ed out block might as well be removed. Signed-off-by: Paul Bolle Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/smc37c669.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c index 0435921d41c6..c803fc76ae4f 100644 --- a/arch/alpha/kernel/smc37c669.c +++ b/arch/alpha/kernel/smc37c669.c @@ -933,18 +933,6 @@ void SMC37c669_display_device_info( * *-- */ -#if 0 -/* $INCLUDE_OPTIONS$ */ -#include "cp$inc:platform_io.h" -/* $INCLUDE_OPTIONS_END$ */ -#include "cp$src:common.h" -#include "cp$inc:prototypes.h" -#include "cp$src:kernel_def.h" -#include "cp$src:msg_def.h" -#include "cp$src:smcc669_def.h" -/* Platform-specific includes */ -#include "cp$src:platform.h" -#endif #ifndef TRUE #define TRUE 1 -- GitLab From bf7c27e9887af48952743753916f9cfbe900d0e9 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Mon, 30 Jul 2012 14:39:25 -0700 Subject: [PATCH 4577/5711] avr32/mm/fault.c: port OOM changes to do_page_fault Commits d065bd810b6d ("mm: retry page fault when blocking on disk transfer") and 37b23e0525d3 ("x86,mm: make pagefault killable") introduced changes into the x86 pagefault handler for making the page fault handler retryable as well as killable. These changes reduce the mmap_sem hold time, which is crucial during OOM killer invocation. Port these changes to AVR32. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Mohd. Faris Signed-off-by: Kautuk Consul Acked-by: Havard Skinnemoen Cc: Hans-Christian Egtvedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/avr32/mm/fault.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index f7040a1e399f..b92e60958617 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -61,10 +61,10 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) const struct exception_table_entry *fixup; unsigned long address; unsigned long page; - int writeaccess; long signr; int code; int fault; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; if (notify_page_fault(regs, ecr)) return; @@ -86,6 +86,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) local_irq_enable(); +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); @@ -104,7 +105,6 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) */ good_area: code = SEGV_ACCERR; - writeaccess = 0; switch (ecr) { case ECR_PROTECTION_X: @@ -121,7 +121,7 @@ good_area: case ECR_TLB_MISS_W: if (!(vma->vm_flags & VM_WRITE)) goto bad_area; - writeaccess = 1; + flags |= FAULT_FLAG_WRITE; break; default: panic("Unhandled case %lu in do_page_fault!", ecr); @@ -132,7 +132,11 @@ good_area: * sure we exit gracefully rather than endlessly redo the * fault. */ - fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return; + if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; @@ -140,10 +144,23 @@ good_area: goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) - tsk->maj_flt++; - else - tsk->min_flt++; + + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) + tsk->maj_flt++; + else + tsk->min_flt++; + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + + /* + * No need to up_read(&mm->mmap_sem) as we would have + * already released it in __lock_page_or_retry() in + * mm/filemap.c. + */ + goto retry; + } + } up_read(&mm->mmap_sem); return; -- GitLab From 93abe8e4b13ae9a0428ce940a8a03ac72a7626f1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:27 -0700 Subject: [PATCH 4578/5711] clk: add non CONFIG_HAVE_CLK routines Many drivers are shared between architectures that may or may not have HAVE_CLK selected for them. To remove compilation errors for them we enclose clk_*() calls in these drivers within #ifdef CONFIG_HAVE_CLK, #endif. This patch removes the need of these CONFIG_HAVE_CLK statements, by introducing dummy routines when HAVE_CLK is not selected by platforms. So, definition of these routines will always be available. These calls will return error for platforms that don't select HAVE_CLK. Signed-off-by: Viresh Kumar Cc: Wolfram Sang Cc: Greg Kroah-Hartman Cc: Jeff Garzik Cc: Andrew Lunn Cc: Bhupesh Sharma Cc: Giuseppe Cavallaro Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/clk.h | 168 ++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 59 deletions(-) diff --git a/include/linux/clk.h b/include/linux/clk.h index 2fd6a4234531..b3ac22d0fc1f 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -84,6 +84,43 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb); #endif +/** + * clk_prepare - prepare a clock source + * @clk: clock source + * + * This prepares the clock source for use. + * + * Must not be called from within atomic context. + */ +#ifdef CONFIG_HAVE_CLK_PREPARE +int clk_prepare(struct clk *clk); +#else +static inline int clk_prepare(struct clk *clk) +{ + might_sleep(); + return 0; +} +#endif + +/** + * clk_unprepare - undo preparation of a clock source + * @clk: clock source + * + * This undoes a previously prepared clock. The caller must balance + * the number of prepare and unprepare calls. + * + * Must not be called from within atomic context. + */ +#ifdef CONFIG_HAVE_CLK_PREPARE +void clk_unprepare(struct clk *clk); +#else +static inline void clk_unprepare(struct clk *clk) +{ + might_sleep(); +} +#endif + +#ifdef CONFIG_HAVE_CLK /** * clk_get - lookup and obtain a reference to a clock producer. * @dev: device for clock "consumer" @@ -121,24 +158,6 @@ struct clk *clk_get(struct device *dev, const char *id); */ struct clk *devm_clk_get(struct device *dev, const char *id); -/** - * clk_prepare - prepare a clock source - * @clk: clock source - * - * This prepares the clock source for use. - * - * Must not be called from within atomic context. - */ -#ifdef CONFIG_HAVE_CLK_PREPARE -int clk_prepare(struct clk *clk); -#else -static inline int clk_prepare(struct clk *clk) -{ - might_sleep(); - return 0; -} -#endif - /** * clk_enable - inform the system when the clock source should be running. * @clk: clock source @@ -167,47 +186,6 @@ int clk_enable(struct clk *clk); */ void clk_disable(struct clk *clk); - -/** - * clk_unprepare - undo preparation of a clock source - * @clk: clock source - * - * This undoes a previously prepared clock. The caller must balance - * the number of prepare and unprepare calls. - * - * Must not be called from within atomic context. - */ -#ifdef CONFIG_HAVE_CLK_PREPARE -void clk_unprepare(struct clk *clk); -#else -static inline void clk_unprepare(struct clk *clk) -{ - might_sleep(); -} -#endif - -/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */ -static inline int clk_prepare_enable(struct clk *clk) -{ - int ret; - - ret = clk_prepare(clk); - if (ret) - return ret; - ret = clk_enable(clk); - if (ret) - clk_unprepare(clk); - - return ret; -} - -/* clk_disable_unprepare helps cases using clk_disable in non-atomic context. */ -static inline void clk_disable_unprepare(struct clk *clk) -{ - clk_disable(clk); - clk_unprepare(clk); -} - /** * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. * This is only valid once the clock source has been enabled. @@ -298,6 +276,78 @@ struct clk *clk_get_parent(struct clk *clk); */ struct clk *clk_get_sys(const char *dev_id, const char *con_id); +#else /* !CONFIG_HAVE_CLK */ + +static inline struct clk *clk_get(struct device *dev, const char *id) +{ + return NULL; +} + +static inline struct clk *devm_clk_get(struct device *dev, const char *id) +{ + return NULL; +} + +static inline void clk_put(struct clk *clk) {} + +static inline void devm_clk_put(struct device *dev, struct clk *clk) {} + +static inline int clk_enable(struct clk *clk) +{ + return 0; +} + +static inline void clk_disable(struct clk *clk) {} + +static inline unsigned long clk_get_rate(struct clk *clk) +{ + return 0; +} + +static inline int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +static inline long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +static inline int clk_set_parent(struct clk *clk, struct clk *parent) +{ + return 0; +} + +static inline struct clk *clk_get_parent(struct clk *clk) +{ + return NULL; +} + +#endif + +/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */ +static inline int clk_prepare_enable(struct clk *clk) +{ + int ret; + + ret = clk_prepare(clk); + if (ret) + return ret; + ret = clk_enable(clk); + if (ret) + clk_unprepare(clk); + + return ret; +} + +/* clk_disable_unprepare helps cases using clk_disable in non-atomic context. */ +static inline void clk_disable_unprepare(struct clk *clk) +{ + clk_disable(clk); + clk_unprepare(clk); +} + /** * clk_add_alias - add a new clock alias * @alias: name for clock alias -- GitLab From 01da40bf8791434455d6e56c711eb224ddbf3161 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:29 -0700 Subject: [PATCH 4579/5711] clk: remove redundant depends on from drivers/Kconfig menu "Common Clock Framework" has "depends on COMMON_CLK" and so configs defined within menu don't require these "depends on COMMON_CLK again". Signed-off-by: Viresh Kumar Cc: Wolfram Sang Cc: Greg Kroah-Hartman Cc: Jeff Garzik Cc: Andrew Lunn Cc: Bhupesh Sharma Cc: Giuseppe Cavallaro Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clk/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3f99b9099658..7f0b5ca78516 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -25,7 +25,6 @@ menu "Common Clock Framework" config COMMON_CLK_DEBUG bool "DebugFS representation of clock tree" - depends on COMMON_CLK select DEBUG_FS ---help--- Creates a directory hierchy in debugfs for visualizing the clk -- GitLab From dd995c9d82b6eedb2e704daf44e903da0b7f6ac1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:30 -0700 Subject: [PATCH 4580/5711] i2c/i2c-pxa: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. pxa i2c also has these dummy macros defined locally. Remove them as they aren't required anymore. Signed-off-by: Viresh Kumar Acked-by: Wolfram Sang Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/i2c-pxa.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index a997c7d3f95d..1034d93fb838 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -41,13 +41,6 @@ #include -#ifndef CONFIG_HAVE_CLK -#define clk_get(dev, id) NULL -#define clk_put(clk) do { } while (0) -#define clk_disable(clk) do { } while (0) -#define clk_enable(clk) do { } while (0) -#endif - struct pxa_reg_layout { u32 ibmr; u32 idbr; -- GitLab From 714904e1c3f48b17ceff06b827485f8b1b5d8a91 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:32 -0700 Subject: [PATCH 4581/5711] usb/marvell: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Marvell usb also has these dummy macros defined locally. Remove them as they aren't required anymore. Signed-off-by: Viresh Kumar Cc: Greg Kroah-Hartman Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/platform_data/mv_usb.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/linux/platform_data/mv_usb.h b/include/linux/platform_data/mv_usb.h index d94804aca764..944b01dd103e 100644 --- a/include/linux/platform_data/mv_usb.h +++ b/include/linux/platform_data/mv_usb.h @@ -52,13 +52,4 @@ struct mv_usb_platform_data { int (*set_vbus)(unsigned int vbus); int (*private_init)(void __iomem *opregs, void __iomem *phyregs); }; - -#ifndef CONFIG_HAVE_CLK -/* Dummy stub for clk framework */ -#define clk_get(dev, id) NULL -#define clk_put(clock) do {} while (0) -#define clk_enable(clock) do {} while (0) -#define clk_disable(clock) do {} while (0) -#endif - #endif -- GitLab From 08aff5358207ee80e4fe162845c17ea125295eec Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:34 -0700 Subject: [PATCH 4582/5711] usb/musb: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. musb also has these dummy macros defined locally. Remove them as they aren't required anymore. Signed-off-by: Viresh Kumar Acked-by: Jeff Garzik Cc: Greg Kroah-Hartman Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/musb/musb_core.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index dbcdeea30f09..586105b55a7c 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -81,14 +81,6 @@ struct musb_ep; #define is_peripheral_active(m) (!(m)->is_host) #define is_host_active(m) ((m)->is_host) -#ifndef CONFIG_HAVE_CLK -/* Dummy stub for clk framework */ -#define clk_get(dev, id) NULL -#define clk_put(clock) do {} while (0) -#define clk_enable(clock) do {} while (0) -#define clk_disable(clock) do {} while (0) -#endif - #ifdef CONFIG_PROC_FS #include #define MUSB_CONFIG_PROC_FS -- GitLab From d14fb1e93086ec1acec34d5e17c989fa528c65e5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:35 -0700 Subject: [PATCH 4583/5711] ata/pata_arasan: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Signed-off-by: Viresh Kumar Cc: Jeff Garzik Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ata/pata_arasan_cf.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index ac6a5beb28f3..bfaa5cb1629a 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -184,10 +184,8 @@ struct arasan_cf_dev { /* pointer to ata_host structure */ struct ata_host *host; - /* clk structure, only if HAVE_CLK is defined */ -#ifdef CONFIG_HAVE_CLK + /* clk structure */ struct clk *clk; -#endif /* physical base address of controller */ dma_addr_t pbase; @@ -312,13 +310,11 @@ static int cf_init(struct arasan_cf_dev *acdev) unsigned long flags; int ret = 0; -#ifdef CONFIG_HAVE_CLK ret = clk_enable(acdev->clk); if (ret) { dev_dbg(acdev->host->dev, "clock enable failed"); return ret; } -#endif spin_lock_irqsave(&acdev->host->lock, flags); /* configure CF interface clock */ @@ -344,9 +340,7 @@ static void cf_exit(struct arasan_cf_dev *acdev) writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB, acdev->vbase + OP_MODE); spin_unlock_irqrestore(&acdev->host->lock, flags); -#ifdef CONFIG_HAVE_CLK clk_disable(acdev->clk); -#endif } static void dma_callback(void *dev) @@ -828,13 +822,11 @@ static int __devinit arasan_cf_probe(struct platform_device *pdev) return -ENOMEM; } -#ifdef CONFIG_HAVE_CLK acdev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(acdev->clk)) { dev_warn(&pdev->dev, "Clock not found\n"); return PTR_ERR(acdev->clk); } -#endif /* allocate host */ host = ata_host_alloc(&pdev->dev, 1); @@ -899,9 +891,7 @@ static int __devinit arasan_cf_probe(struct platform_device *pdev) &arasan_cf_sht); free_clk: -#ifdef CONFIG_HAVE_CLK clk_put(acdev->clk); -#endif return ret; } @@ -912,9 +902,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev) ata_host_detach(host); cf_exit(acdev); -#ifdef CONFIG_HAVE_CLK clk_put(acdev->clk); -#endif return 0; } -- GitLab From 2b1463ddde35a720de2fb4013057396e7f8011f0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:38 -0700 Subject: [PATCH 4584/5711] net/c_can: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Signed-off-by: Viresh Kumar Acked-by: David S. Miller Cc: Bhupesh Sharma Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/can/c_can/c_can_platform.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index f0921d16f0a9..6ff7ad006c30 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -74,7 +74,6 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) const struct platform_device_id *id; struct resource *mem; int irq; -#ifdef CONFIG_HAVE_CLK struct clk *clk; /* get the appropriate clk */ @@ -84,7 +83,6 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) ret = -ENODEV; goto exit; } -#endif /* get the platform data */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -145,10 +143,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) dev->irq = irq; priv->base = addr; -#ifdef CONFIG_HAVE_CLK priv->can.clock.freq = clk_get_rate(clk); priv->priv = clk; -#endif platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -172,10 +168,8 @@ exit_iounmap: exit_release_mem: release_mem_region(mem->start, resource_size(mem)); exit_free_clk: -#ifdef CONFIG_HAVE_CLK clk_put(clk); exit: -#endif dev_err(&pdev->dev, "probe failed\n"); return ret; @@ -196,9 +190,7 @@ static int __devexit c_can_plat_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); -#ifdef CONFIG_HAVE_CLK clk_put(priv->priv); -#endif return 0; } -- GitLab From 6a81c26f868b2fc5f88b9f78a6f82aeab1191e61 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:41 -0700 Subject: [PATCH 4585/5711] net/stmmac: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. This also fixes error paths of probe(), as a goto is required in this patch. Signed-off-by: Viresh Kumar Cc: Giuseppe Cavallaro Acked-by: David S. Miller Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 42 ------------------- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 33 ++++++++------- 2 files changed, 17 insertions(+), 58 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index ab4c376cb276..f2d3665430ad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -82,9 +82,7 @@ struct stmmac_priv { struct stmmac_counters mmc; struct dma_features dma_cap; int hw_cap_support; -#ifdef CONFIG_HAVE_CLK struct clk *stmmac_clk; -#endif int clk_csr; int synopsys_id; struct timer_list eee_ctrl_timer; @@ -113,46 +111,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, void stmmac_disable_eee_mode(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv); -#ifdef CONFIG_HAVE_CLK -static inline int stmmac_clk_enable(struct stmmac_priv *priv) -{ - if (!IS_ERR(priv->stmmac_clk)) - return clk_prepare_enable(priv->stmmac_clk); - - return 0; -} - -static inline void stmmac_clk_disable(struct stmmac_priv *priv) -{ - if (IS_ERR(priv->stmmac_clk)) - return; - - clk_disable_unprepare(priv->stmmac_clk); -} -static inline int stmmac_clk_get(struct stmmac_priv *priv) -{ - priv->stmmac_clk = clk_get(priv->device, NULL); - - if (IS_ERR(priv->stmmac_clk)) - return PTR_ERR(priv->stmmac_clk); - - return 0; -} -#else -static inline int stmmac_clk_enable(struct stmmac_priv *priv) -{ - return 0; -} -static inline void stmmac_clk_disable(struct stmmac_priv *priv) -{ -} -static inline int stmmac_clk_get(struct stmmac_priv *priv) -{ - return 0; -} -#endif /* CONFIG_HAVE_CLK */ - - #ifdef CONFIG_STMMAC_PLATFORM extern struct platform_driver stmmac_pltfr_driver; static inline int stmmac_register_platform(void) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f6b04c1a3672..fd8882f9602a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -28,6 +28,7 @@ https://bugzilla.stlinux.com/ *******************************************************************************/ +#include #include #include #include @@ -173,12 +174,8 @@ static void stmmac_verify_args(void) static void stmmac_clk_csr_set(struct stmmac_priv *priv) { -#ifdef CONFIG_HAVE_CLK u32 clk_rate; - if (IS_ERR(priv->stmmac_clk)) - return; - clk_rate = clk_get_rate(priv->stmmac_clk); /* Platform provided default clk_csr would be assumed valid @@ -200,7 +197,6 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv) * we can not estimate the proper divider as it is not known * the frequency of clk_csr_i. So we do not change the default * divider. */ -#endif } #if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG) @@ -1070,7 +1066,7 @@ static int stmmac_open(struct net_device *dev) } else priv->tm->enable = 1; #endif - stmmac_clk_enable(priv); + clk_enable(priv->stmmac_clk); stmmac_check_ether_addr(priv); @@ -1192,7 +1188,7 @@ open_error: if (priv->phydev) phy_disconnect(priv->phydev); - stmmac_clk_disable(priv); + clk_disable(priv->stmmac_clk); return ret; } @@ -1250,7 +1246,7 @@ static int stmmac_release(struct net_device *dev) #ifdef CONFIG_STMMAC_DEBUG_FS stmmac_exit_fs(); #endif - stmmac_clk_disable(priv); + clk_disable(priv->stmmac_clk); return 0; } @@ -2078,11 +2074,14 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, ret = register_netdev(ndev); if (ret) { pr_err("%s: ERROR %i registering the device\n", __func__, ret); - goto error; + goto error_netdev_register; } - if (stmmac_clk_get(priv)) + priv->stmmac_clk = clk_get(priv->device, NULL); + if (IS_ERR(priv->stmmac_clk)) { pr_warning("%s: warning: cannot get CSR clock\n", __func__); + goto error_clk_get; + } /* If a specific clk_csr value is passed from the platform * this means that the CSR Clock Range selection cannot be @@ -2100,15 +2099,17 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, if (ret < 0) { pr_debug("%s: MDIO bus (id: %d) registration failed", __func__, priv->plat->bus_id); - goto error; + goto error_mdio_register; } return priv; -error: - netif_napi_del(&priv->napi); - +error_mdio_register: + clk_put(priv->stmmac_clk); +error_clk_get: unregister_netdev(ndev); +error_netdev_register: + netif_napi_del(&priv->napi); free_netdev(ndev); return NULL; @@ -2177,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev) else { stmmac_set_mac(priv->ioaddr, false); /* Disable clock in case of PWM is off */ - stmmac_clk_disable(priv); + clk_disable(priv->stmmac_clk); } spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -2202,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev) priv->hw->mac->pmt(priv->ioaddr, 0); else /* enable the clk prevously disabled */ - stmmac_clk_enable(priv); + clk_enable(priv->stmmac_clk); netif_device_attach(ndev); -- GitLab From f12a86a0987a443fb1bc2d4298e5db9c17f3e7cd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:43 -0700 Subject: [PATCH 4586/5711] gadget/m66592: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Signed-off-by: Viresh Kumar Cc: Greg Kroah-Hartman Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/gadget/m66592-udc.c | 9 +-------- drivers/usb/gadget/m66592-udc.h | 5 ----- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 8981fbb5748c..cf6bd626f3fe 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1583,12 +1583,10 @@ static int __exit m66592_remove(struct platform_device *pdev) iounmap(m66592->reg); free_irq(platform_get_irq(pdev, 0), m66592); m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); -#ifdef CONFIG_HAVE_CLK if (m66592->pdata->on_chip) { clk_disable(m66592->clk); clk_put(m66592->clk); } -#endif kfree(m66592); return 0; } @@ -1602,9 +1600,7 @@ static int __init m66592_probe(struct platform_device *pdev) struct resource *res, *ires; void __iomem *reg = NULL; struct m66592 *m66592 = NULL; -#ifdef CONFIG_HAVE_CLK char clk_name[8]; -#endif int ret = 0; int i; @@ -1671,7 +1667,6 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } -#ifdef CONFIG_HAVE_CLK if (m66592->pdata->on_chip) { snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id); m66592->clk = clk_get(&pdev->dev, clk_name); @@ -1683,7 +1678,7 @@ static int __init m66592_probe(struct platform_device *pdev) } clk_enable(m66592->clk); } -#endif + INIT_LIST_HEAD(&m66592->gadget.ep_list); m66592->gadget.ep0 = &m66592->ep[0].ep; INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list); @@ -1731,13 +1726,11 @@ err_add_udc: m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); clean_up3: -#ifdef CONFIG_HAVE_CLK if (m66592->pdata->on_chip) { clk_disable(m66592->clk); clk_put(m66592->clk); } clean_up2: -#endif free_irq(ires->start, m66592); clean_up: if (m66592) { diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 88c85b4116a2..16c7e14678b8 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -13,10 +13,7 @@ #ifndef __M66592_UDC_H__ #define __M66592_UDC_H__ -#ifdef CONFIG_HAVE_CLK #include -#endif - #include #define M66592_SYSCFG 0x00 @@ -468,9 +465,7 @@ struct m66592_ep { struct m66592 { spinlock_t lock; void __iomem *reg; -#ifdef CONFIG_HAVE_CLK struct clk *clk; -#endif struct m66592_platdata *pdata; unsigned long irq_trigger; -- GitLab From 569a50da7fe5144ac3831ffa6f400aa276b9781a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:46 -0700 Subject: [PATCH 4587/5711] gadget/r8a66597: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Signed-off-by: Viresh Kumar Cc: Greg Kroah-Hartman Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/gadget/r8a66597-udc.c | 11 +++-------- drivers/usb/gadget/r8a66597-udc.h | 5 ----- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index f3ac2a20c27c..5a80751accb7 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1831,12 +1831,12 @@ static int __exit r8a66597_remove(struct platform_device *pdev) iounmap(r8a66597->sudmac_reg); free_irq(platform_get_irq(pdev, 0), r8a66597); r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); -#ifdef CONFIG_HAVE_CLK + if (r8a66597->pdata->on_chip) { clk_disable(r8a66597->clk); clk_put(r8a66597->clk); } -#endif + device_unregister(&r8a66597->gadget.dev); kfree(r8a66597); return 0; @@ -1868,9 +1868,7 @@ static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597, static int __init r8a66597_probe(struct platform_device *pdev) { -#ifdef CONFIG_HAVE_CLK char clk_name[8]; -#endif struct resource *res, *ires; int irq; void __iomem *reg = NULL; @@ -1934,7 +1932,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->timer.data = (unsigned long)r8a66597; r8a66597->reg = reg; -#ifdef CONFIG_HAVE_CLK if (r8a66597->pdata->on_chip) { snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id); r8a66597->clk = clk_get(&pdev->dev, clk_name); @@ -1946,7 +1943,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) } clk_enable(r8a66597->clk); } -#endif + if (r8a66597->pdata->sudmac) { ret = r8a66597_sudmac_ioremap(r8a66597, pdev); if (ret < 0) @@ -2006,13 +2003,11 @@ err_add_udc: clean_up3: free_irq(irq, r8a66597); clean_up2: -#ifdef CONFIG_HAVE_CLK if (r8a66597->pdata->on_chip) { clk_disable(r8a66597->clk); clk_put(r8a66597->clk); } clean_up_dev: -#endif device_unregister(&r8a66597->gadget.dev); clean_up: if (r8a66597) { diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 99908c76ccd1..45c4b2df1785 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -13,10 +13,7 @@ #ifndef __R8A66597_H__ #define __R8A66597_H__ -#ifdef CONFIG_HAVE_CLK #include -#endif - #include #define R8A66597_MAX_SAMPLING 10 @@ -92,9 +89,7 @@ struct r8a66597 { void __iomem *reg; void __iomem *sudmac_reg; -#ifdef CONFIG_HAVE_CLK struct clk *clk; -#endif struct r8a66597_platdata *pdata; struct usb_gadget gadget; -- GitLab From c311b78b2a2fc644da2e748b7999b9ff081ec00e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:49 -0700 Subject: [PATCH 4588/5711] usb/host/r8a66597: remove conditional compilation of clk code With addition of dummy clk_*() calls for non CONFIG_HAVE_CLK cases in clk.h, there is no need to have clk code enclosed in #ifdef CONFIG_HAVE_CLK, #endif macros. Signed-off-by: Viresh Kumar Cc: Greg Kroah-Hartman Cc: Russell King Cc: Mike Turquette Cc: Sergei Shtylyov Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/host/r8a66597-hcd.c | 12 ------------ drivers/usb/host/r8a66597.h | 5 ----- 2 files changed, 17 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c868be65e763..4c634eb56358 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -95,9 +95,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) int i = 0; if (r8a66597->pdata->on_chip) { -#ifdef CONFIG_HAVE_CLK clk_enable(r8a66597->clk); -#endif do { r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); @@ -141,9 +139,7 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597) udelay(1); if (r8a66597->pdata->on_chip) { -#ifdef CONFIG_HAVE_CLK clk_disable(r8a66597->clk); -#endif } else { r8a66597_bclr(r8a66597, PLLC, SYSCFG0); r8a66597_bclr(r8a66597, XCKE, SYSCFG0); @@ -2406,19 +2402,15 @@ static int __devexit r8a66597_remove(struct platform_device *pdev) del_timer_sync(&r8a66597->rh_timer); usb_remove_hcd(hcd); iounmap(r8a66597->reg); -#ifdef CONFIG_HAVE_CLK if (r8a66597->pdata->on_chip) clk_put(r8a66597->clk); -#endif usb_put_hcd(hcd); return 0; } static int __devinit r8a66597_probe(struct platform_device *pdev) { -#ifdef CONFIG_HAVE_CLK char clk_name[8]; -#endif struct resource *res = NULL, *ires; int irq = -1; void __iomem *reg = NULL; @@ -2482,7 +2474,6 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; if (r8a66597->pdata->on_chip) { -#ifdef CONFIG_HAVE_CLK snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id); r8a66597->clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(r8a66597->clk)) { @@ -2491,7 +2482,6 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) ret = PTR_ERR(r8a66597->clk); goto clean_up2; } -#endif r8a66597->max_root_hub = 1; } else r8a66597->max_root_hub = 2; @@ -2531,11 +2521,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) return 0; clean_up3: -#ifdef CONFIG_HAVE_CLK if (r8a66597->pdata->on_chip) clk_put(r8a66597->clk); clean_up2: -#endif usb_put_hcd(hcd); clean_up: diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index f28782d20eef..672cea307abb 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -26,10 +26,7 @@ #ifndef __R8A66597_H__ #define __R8A66597_H__ -#ifdef CONFIG_HAVE_CLK #include -#endif - #include #define R8A66597_MAX_NUM_PIPE 10 @@ -113,9 +110,7 @@ struct r8a66597_root_hub { struct r8a66597 { spinlock_t lock; void __iomem *reg; -#ifdef CONFIG_HAVE_CLK struct clk *clk; -#endif struct r8a66597_platdata *pdata; struct r8a66597_device device0; struct r8a66597_root_hub root_hub[R8A66597_MAX_ROOT_HUB]; -- GitLab From 7041717e7c6ca33310d0c7333d9f7cebc65b2534 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 30 Jul 2012 14:39:52 -0700 Subject: [PATCH 4589/5711] arch/arm/mach-netx/fb.c: reuse dummy clk routines for CONFIG_HAVE_CLK=n mach-netx had its own implementation of clk routines like, clk_get{put}, clk_enable{disable}, etc. And with introduction of following patchset: https://lkml.org/lkml/2012/4/24/154 we get compilation error for multiple definition of these routines. Sascha had following suggestion to deal with it: http://www.spinics.net/lists/arm-kernel/msg179369.html So, remove this code completely. Signed-off-by: Viresh Kumar Reported-by: Paul Gortmaker Acked-by: Sascha Hauer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-netx/fb.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c index 2cdf6ef69bee..d122ee6ab991 100644 --- a/arch/arm/mach-netx/fb.c +++ b/arch/arm/mach-netx/fb.c @@ -69,29 +69,6 @@ void netx_clcd_remove(struct clcd_fb *fb) fb->fb.screen_base, fb->fb.fix.smem_start); } -void clk_disable(struct clk *clk) -{ -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return 0; -} - -int clk_enable(struct clk *clk) -{ - return 0; -} - -struct clk *clk_get(struct device *dev, const char *id) -{ - return dev && strcmp(dev_name(dev), "fb") == 0 ? NULL : ERR_PTR(-ENOENT); -} - -void clk_put(struct clk *clk) -{ -} - static AMBA_AHB_DEVICE(fb, "fb", 0, 0x00104000, { NETX_IRQ_LCD }, NULL); int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel) -- GitLab From e47c6a3408ea6bcfc5204f23d5a5b209de6e68b9 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Mon, 30 Jul 2012 14:39:54 -0700 Subject: [PATCH 4590/5711] clk: validate pointer in __clk_disable() clk_get() returns -ENOENT on error and some careless caller might dereference it without error checking: In mxc_rnga_remove(): struct clk *clk = clk_get(&pdev->dev, "rng"); // ... clk_disable(clk); Since it's insane to audit the lots of existing and future clk users, let's add a check in the callee to avoid kernel panic and warn about any buggy user. Cc: Russell King Cc: Paul Gortmaker Cc: Viresh Kumar Cc: viresh kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clk/clk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c87fdd710560..efdfd009c270 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -465,6 +465,9 @@ static void __clk_disable(struct clk *clk) if (!clk) return; + if (WARN_ON(IS_ERR(clk))) + return; + if (WARN_ON(clk->enable_count == 0)) return; -- GitLab From 6c55845e71ba7a862395f504a240a5b62632e0d6 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Mon, 30 Jul 2012 14:39:57 -0700 Subject: [PATCH 4591/5711] avr32: fix build error in ATSTK1002 code Fix the error arch/avr32/boards/atstk1000/atstk1002.c:100: error: 'num_partitions' undeclared here (not in a function) which was introduced by commit 1754aab9bb86 ("mtd: ATMEL, AVR32: inline nand partition table access "). Signed-off-by: Fengguang Wu Cc: Dmitry Eremin-Solenikov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index dc5263321480..6c80aba7bf96 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -97,7 +97,7 @@ static struct atmel_nand_data atstk1006_nand_data __initdata = { .enable_pin = GPIO_PIN_PB(29), .ecc_mode = NAND_ECC_SOFT, .parts = nand_partitions, - .num_parts = ARRAY_SIZE(num_partitions), + .num_parts = ARRAY_SIZE(nand_partitions), }; #endif -- GitLab From 190320c3b6640d4104650f55ff69611e050ea06b Mon Sep 17 00:00:00 2001 From: Vikram Mulukutla Date: Mon, 30 Jul 2012 14:39:58 -0700 Subject: [PATCH 4592/5711] panic: fix a possible deadlock in panic() panic_lock is meant to ensure that panic processing takes place only on one cpu; if any of the other cpus encounter a panic, they will spin waiting to be shut down. However, this causes a regression in this scenario: 1. Cpu 0 encounters a panic and acquires the panic_lock and proceeds with the panic processing. 2. There is an interrupt on cpu 0 that also encounters an error condition and invokes panic. 3. This second invocation fails to acquire the panic_lock and enters the infinite while loop in panic_smp_self_stop. Thus all panic processing is stopped, and the cpu is stuck for eternity in the while(1) inside panic_smp_self_stop. To address this, disable local interrupts with local_irq_disable before acquiring the panic_lock. This will prevent interrupt handlers from executing during the panic processing, thus avoiding this particular problem. Signed-off-by: Vikram Mulukutla Reviewed-by: Stephen Boyd Cc: Michael Holzheu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/panic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/panic.c b/kernel/panic.c index d2a5f4ecc6dd..e1b2822fff97 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -74,6 +74,14 @@ void panic(const char *fmt, ...) long i, i_next = 0; int state = 0; + /* + * Disable local interrupts. This will prevent panic_smp_self_stop + * from deadlocking the first cpu that invokes the panic, since + * there is nothing to prevent an interrupt handler (that runs + * after the panic_lock is acquired) from invoking panic again. + */ + local_irq_disable(); + /* * It's possible to come here directly from a panic-assertion and * not have preempt disabled. Some functions called from here want -- GitLab From 45226e944ce071d0231949f2fea90969437cd2dc Mon Sep 17 00:00:00 2001 From: Sameer Nanda Date: Mon, 30 Jul 2012 14:40:00 -0700 Subject: [PATCH 4593/5711] NMI watchdog: fix for lockup detector breakage on resume On the suspend/resume path the boot CPU does not go though an offline->online transition. This breaks the NMI detector post-resume since it depends on PMU state that is lost when the system gets suspended. Fix this by forcing a CPU offline->online transition for the lockup detector on the boot CPU during resume. To provide more context, we enable NMI watchdog on Chrome OS. We have seen several reports of systems freezing up completely which indicated that the NMI watchdog was not firing for some reason. Debugging further, we found a simple way of repro'ing system freezes -- issuing the command 'tasket 1 sh -c "echo nmilockup > /proc/breakme"' after the system has been suspended/resumed one or more times. With this patch in place, the system freeze result in panics, as expected. These panics provide a nice stack trace for us to debug the actual issue causing the freeze. [akpm@linux-foundation.org: fiddle with code comment] [akpm@linux-foundation.org: make lockup_detector_bootcpu_resume() conditional on CONFIG_SUSPEND] [akpm@linux-foundation.org: fix section errors] Signed-off-by: Sameer Nanda Cc: Ingo Molnar Cc: Peter Zijlstra Cc: "Rafael J. Wysocki" Cc: Don Zickus Cc: Mandeep Singh Baines Cc: Srivatsa S. Bhat Cc: Anshuman Khandual Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 8 ++++++++ kernel/power/suspend.c | 3 +++ kernel/watchdog.c | 21 +++++++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 1e26a5e45aa6..68dcffaa62a0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -334,6 +334,14 @@ static inline void lockup_detector_init(void) } #endif +#if defined(CONFIG_LOCKUP_DETECTOR) && defined(CONFIG_SUSPEND) +void lockup_detector_bootcpu_resume(void); +#else +static inline void lockup_detector_bootcpu_resume(void) +{ +} +#endif + #ifdef CONFIG_DETECT_HUNG_TASK extern unsigned int sysctl_hung_task_panic; extern unsigned long sysctl_hung_task_check_count; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c8b7446b27df..1da39ea248fd 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -178,6 +178,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); + /* Kick the lockup detector */ + lockup_detector_bootcpu_resume(); + Enable_cpus: enable_nonboot_cpus(); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 4b1dfba70f7c..69add8a9da68 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -575,7 +575,7 @@ out: /* * Create/destroy watchdog threads as CPUs come and go: */ -static int __cpuinit +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -610,10 +610,27 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; +#ifdef CONFIG_SUSPEND +/* + * On exit from suspend we force an offline->online transition on the boot CPU + * so that the PMU state that was lost while in suspended state gets set up + * properly for the boot CPU. This information is required for restarting the + * NMI watchdog. + */ +void lockup_detector_bootcpu_resume(void) +{ + void *cpu = (void *)(long)smp_processor_id(); + + cpu_callback(&cpu_nfb, CPU_DEAD_FROZEN, cpu); + cpu_callback(&cpu_nfb, CPU_UP_PREPARE_FROZEN, cpu); + cpu_callback(&cpu_nfb, CPU_ONLINE_FROZEN, cpu); +} +#endif + void __init lockup_detector_init(void) { void *cpu = (void *)(long)smp_processor_id(); -- GitLab From b57b44ae698944ffc6161352b8ff5c9cf9c592e2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:40:03 -0700 Subject: [PATCH 4594/5711] kernel/sys.c: avoid argv_free(NULL) If argv_split() failed, the code will end up calling argv_free(NULL). Fix it up and clean things up a bit. Addresses Coverity report 703573. Cc: Cyrill Gorcunov Cc: Kees Cook Cc: Serge Hallyn Cc: "Eric W. Biederman" Cc: WANG Cong Cc: Alan Cox Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sys.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index b04ae0390df3..241507f23eca 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2186,46 +2186,52 @@ static void argv_cleanup(struct subprocess_info *info) argv_free(info->argv); } -/** - * orderly_poweroff - Trigger an orderly system poweroff - * @force: force poweroff if command execution fails - * - * This may be called from any context to trigger a system shutdown. - * If the orderly shutdown fails, it will force an immediate shutdown. - */ -int orderly_poweroff(bool force) +static int __orderly_poweroff(void) { int argc; - char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); + char **argv; static char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; - int ret = -ENOMEM; + int ret; + argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); if (argv == NULL) { printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", __func__, poweroff_cmd); - goto out; + return -ENOMEM; } ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, NULL, argv_cleanup, NULL); -out: - if (likely(!ret)) - return 0; - if (ret == -ENOMEM) argv_free(argv); - if (force) { + return ret; +} + +/** + * orderly_poweroff - Trigger an orderly system poweroff + * @force: force poweroff if command execution fails + * + * This may be called from any context to trigger a system shutdown. + * If the orderly shutdown fails, it will force an immediate shutdown. + */ +int orderly_poweroff(bool force) +{ + int ret = __orderly_poweroff(); + + if (ret && force) { printk(KERN_WARNING "Failed to start orderly shutdown: " "forcing the issue\n"); - /* I guess this should try to kick off some daemon to - sync and poweroff asap. Or not even bother syncing - if we're doing an emergency shutdown? */ + /* + * I guess this should try to kick off some daemon to sync and + * poweroff asap. Or not even bother syncing if we're doing an + * emergency shutdown? + */ emergency_sync(); kernel_power_off(); } -- GitLab From 5353cf089bb32b69a7515be909c14bf05fe2e81e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 30 Jul 2012 14:40:06 -0700 Subject: [PATCH 4595/5711] drivers/misc/ti-st/st_core.c: missing NULL check Addresses https://bugzilla.kernel.org/show_bug.cgi?44431 Reported-by: Signed-off-by: Alan Cox Cc: Pavan Savoy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/ti-st/st_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 2b62232c2c6a..acfaeeb9e01a 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -349,6 +349,11 @@ void st_int_recv(void *disc_data, st_gdata->rx_skb = alloc_skb( st_gdata->list[type]->max_frame_size, GFP_ATOMIC); + if (st_gdata->rx_skb == NULL) { + pr_err("out of memory: dropping\n"); + goto done; + } + skb_reserve(st_gdata->rx_skb, st_gdata->list[type]->reserve); /* next 2 required for BT only */ -- GitLab From cdf53441368cc02ee4aa8a8343a5dc25132836f0 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 30 Jul 2012 14:40:08 -0700 Subject: [PATCH 4596/5711] kmsg: /dev/kmsg - properly return possible copy_from_user() failure Reported-by: Andrew Morton Signed-off-by: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index 50c96b5651b6..852269adad25 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -389,8 +389,10 @@ static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, line = buf; for (i = 0; i < count; i++) { - if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) + if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) { + ret = -EFAULT; goto out; + } line += iv[i].iov_len; } -- GitLab From acc8fa41ad31c576cdbc569cc3e0e443b1b98b44 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:09 -0700 Subject: [PATCH 4597/5711] printk: add generic functions to find KERN_ headers The current form of a KERN_ is "<.>". Add printk_get_level and printk_skip_level functions to handle these formats. These functions centralize tests of KERN_ so a future modification can change the KERN_ style and shorten the number of bytes consumed by these headers. [akpm@linux-foundation.org: fix build error and warning] Signed-off-by: Joe Perches Cc: Kay Sievers Cc: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/printk.h | 26 ++++++++++++++++++++++++++ kernel/printk.c | 14 +++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 1bec2f7a2d42..6e12e1f09047 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -24,6 +24,32 @@ extern const char linux_proc_banner[]; */ #define KERN_CONT "" +static inline int printk_get_level(const char *buffer) +{ + if (buffer[0] == '<' && buffer[1] && buffer[2] == '>') { + switch (buffer[1]) { + case '0' ... '7': + case 'd': /* KERN_DEFAULT */ + case 'c': /* KERN_CONT */ + return buffer[1]; + } + } + return 0; +} + +static inline const char *printk_skip_level(const char *buffer) +{ + if (printk_get_level(buffer)) { + switch (buffer[1]) { + case '0' ... '7': + case 'd': /* KERN_DEFAULT */ + case 'c': /* KERN_CONT */ + return buffer + 3; + } + } + return buffer; +} + extern int console_printk[]; #define console_loglevel (console_printk[0]) diff --git a/kernel/printk.c b/kernel/printk.c index 852269adad25..0d882a2f231e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1487,6 +1487,7 @@ asmlinkage int vprintk_emit(int facility, int level, size_t text_len; enum log_flags lflags = 0; unsigned long flags; + int kern_level; int this_cpu; int printed_len = 0; @@ -1543,17 +1544,20 @@ asmlinkage int vprintk_emit(int facility, int level, } /* strip syslog prefix and extract log level or control flags */ - if (text[0] == '<' && text[1] && text[2] == '>') { - switch (text[1]) { + kern_level = printk_get_level(text); + if (kern_level) { + const char *end_of_header = printk_skip_level(text); + switch (kern_level) { case '0' ... '7': if (level == -1) - level = text[1] - '0'; + level = kern_level - '0'; case 'd': /* KERN_DEFAULT */ lflags |= LOG_PREFIX; case 'c': /* KERN_CONT */ - text += 3; - text_len -= 3; + break; } + text_len -= end_of_header - text; + text = (char *)end_of_header; } if (level == -1) -- GitLab From 314ba3520e513a78be80e8c2ddbd65c91e78a114 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:11 -0700 Subject: [PATCH 4598/5711] printk: add kern_levels.h to make KERN_ available for asm use Separate the printk.h file into 2 pieces so the definitions can be used in asm files. Signed-off-by: Joe Perches Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kern_levels.h | 22 ++++++++++++++++++++++ include/linux/printk.h | 19 +------------------ 2 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 include/linux/kern_levels.h diff --git a/include/linux/kern_levels.h b/include/linux/kern_levels.h new file mode 100644 index 000000000000..337e56ff5332 --- /dev/null +++ b/include/linux/kern_levels.h @@ -0,0 +1,22 @@ +#ifndef __KERN_LEVELS_H__ +#define __KERN_LEVELS_H__ + +#define KERN_EMERG "<0>" /* system is unusable */ +#define KERN_ALERT "<1>" /* action must be taken immediately */ +#define KERN_CRIT "<2>" /* critical conditions */ +#define KERN_ERR "<3>" /* error conditions */ +#define KERN_WARNING "<4>" /* warning conditions */ +#define KERN_NOTICE "<5>" /* normal but significant condition */ +#define KERN_INFO "<6>" /* informational */ +#define KERN_DEBUG "<7>" /* debug-level messages */ + +/* Use the default kernel loglevel */ +#define KERN_DEFAULT "" +/* + * Annotation for a "continued" line of log printout (only done after a + * line that had no enclosing \n). Only to be used by core/arch code + * during early bootup (a continued line is not SMP-safe otherwise). + */ +#define KERN_CONT "" + +#endif diff --git a/include/linux/printk.h b/include/linux/printk.h index 6e12e1f09047..fea2de37b645 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -2,28 +2,11 @@ #define __KERNEL_PRINTK__ #include +#include extern const char linux_banner[]; extern const char linux_proc_banner[]; -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ - -/* Use the default kernel loglevel */ -#define KERN_DEFAULT "" -/* - * Annotation for a "continued" line of log printout (only done after a - * line that had no enclosing \n). Only to be used by core/arch code - * during early bootup (a continued line is not SMP-safe otherwise). - */ -#define KERN_CONT "" - static inline int printk_get_level(const char *buffer) { if (buffer[0] == '<' && buffer[1] && buffer[2] == '>') { -- GitLab From 0cc41e4a21d43695154fe6a151abf3b6f27b0bb0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:12 -0700 Subject: [PATCH 4599/5711] arch: remove direct definitions of KERN_ uses Add #include so that the #define KERN_ macros don't have to be duplicated. Signed-off-by: Joe Perches Cc: Kay Sievers Cc: Russell King Cc: Kay Sievers Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/lib/io-acorn.S | 3 ++- arch/arm/vfp/vfphw.S | 7 ++++--- arch/frv/kernel/kernel_thread.S | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S index 1b197ea7aab3..69719bad674d 100644 --- a/arch/arm/lib/io-acorn.S +++ b/arch/arm/lib/io-acorn.S @@ -11,13 +11,14 @@ * */ #include +#include #include .text .align .Liosl_warning: - .ascii "<4>insl/outsl not implemented, called from %08lX\0" + .ascii KERN_WARNING "insl/outsl not implemented, called from %08lX\0" .align /* diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 2d30c7f6edd3..d50f0e486cf2 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -16,6 +16,7 @@ */ #include #include +#include #include "../kernel/entry-header.S" .macro DBGSTR, str @@ -24,7 +25,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif @@ -37,7 +38,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif @@ -52,7 +53,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif diff --git a/arch/frv/kernel/kernel_thread.S b/arch/frv/kernel/kernel_thread.S index 4531c830d20b..f0e52943f923 100644 --- a/arch/frv/kernel/kernel_thread.S +++ b/arch/frv/kernel/kernel_thread.S @@ -10,10 +10,10 @@ */ #include +#include #include #define CLONE_VM 0x00000100 /* set if VM shared between processes */ -#define KERN_ERR "<3>" .section .rodata kernel_thread_emsg: -- GitLab From 533574c6bc30cf526cc1c41bde050c854a945efb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:13 -0700 Subject: [PATCH 4600/5711] btrfs: use printk_get_level and printk_skip_level, add __printf, fix fallout Use the generic printk_get_level() to search a message for a kern_level. Add __printf to verify format and arguments. Fix a few messages that had mismatches in format and arguments. Add #ifdef CONFIG_PRINTK blocks to shrink the object size a bit when not using printk. [akpm@linux-foundation.org: whitespace tweak] Signed-off-by: Joe Perches Cc: Kay Sievers Cc: Chris Mason Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/btrfs/ctree.h | 13 +++++++++++++ fs/btrfs/disk-io.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/super.c | 41 +++++++++++++++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index adb1cd7ceb9b..4bab807227ad 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3342,10 +3342,22 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size); /* super.c */ int btrfs_parse_options(struct btrfs_root *root, char *options); int btrfs_sync_fs(struct super_block *sb, int wait); + +#ifdef CONFIG_PRINTK +__printf(2, 3) void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...); +#else +static inline __printf(2, 3) +void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) +{ +} +#endif + +__printf(5, 6) void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, unsigned int line, int errno, const char *fmt, ...); + void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *function, unsigned int line, int errno); @@ -3386,6 +3398,7 @@ do { \ (errno), fmt, ##args); \ } while (0) +__printf(5, 6) void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function, unsigned int line, int errno, const char *fmt, ...); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 502b20c56e84..fadeba6a5db9 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1114,7 +1114,7 @@ void clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, spin_unlock(&root->fs_info->delalloc_lock); btrfs_panic(root->fs_info, -EOVERFLOW, "Can't clear %lu bytes from " - " dirty_mdatadata_bytes (%lu)", + " dirty_mdatadata_bytes (%llu)", buf->len, root->fs_info->dirty_metadata_bytes); } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index c5dbd9149679..4da08652004d 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1241,7 +1241,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) if (rb_node) { btrfs_panic(root->fs_info, -EEXIST, "Duplicate root found " "for start=%llu while inserting into relocation " - "tree\n"); + "tree\n", node->bytenr); kfree(node); return -EEXIST; } diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index fa61ef59cd61..8c6e61d6eed5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -125,6 +125,7 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) } } +#ifdef CONFIG_PRINTK /* * __btrfs_std_error decodes expected errors from the caller and * invokes the approciate error response. @@ -167,7 +168,7 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, va_end(args); } -const char *logtypes[] = { +static const char * const logtypes[] = { "emergency", "alert", "critical", @@ -185,22 +186,50 @@ void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) struct va_format vaf; va_list args; const char *type = logtypes[4]; + int kern_level; va_start(args, fmt); - if (fmt[0] == '<' && isdigit(fmt[1]) && fmt[2] == '>') { - memcpy(lvl, fmt, 3); - lvl[3] = '\0'; - fmt += 3; - type = logtypes[fmt[1] - '0']; + kern_level = printk_get_level(fmt); + if (kern_level) { + size_t size = printk_skip_level(fmt) - fmt; + memcpy(lvl, fmt, size); + lvl[size] = '\0'; + fmt += size; + type = logtypes[kern_level - '0']; } else *lvl = '\0'; vaf.fmt = fmt; vaf.va = &args; + printk("%sBTRFS %s (device %s): %pV", lvl, type, sb->s_id, &vaf); + + va_end(args); } +#else + +void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, + unsigned int line, int errno, const char *fmt, ...) +{ + struct super_block *sb = fs_info->sb; + + /* + * Special case: if the error is EROFS, and we're already + * under MS_RDONLY, then it is safe here. + */ + if (errno == -EROFS && (sb->s_flags & MS_RDONLY)) + return; + + /* Don't go through full error handling during mount */ + if (sb->s_flags & MS_BORN) { + save_error_info(fs_info); + btrfs_handle_error(fs_info); + } +} +#endif + /* * We only mark the transaction aborted and then set the file system read-only. * This will prevent new transactions from starting or trying to join this -- GitLab From b778b3f25baf46dd88f16d51f1682828be0aa2ad Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:15 -0700 Subject: [PATCH 4601/5711] sound: use printk_get_level and printk_skip_level Make the output logging routine independent of the KERN_ style. Signed-off-by: Joe Perches Cc: Kay Sievers Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/core/misc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/core/misc.c b/sound/core/misc.c index 768167925409..30e027ecf4da 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -68,6 +68,7 @@ void __snd_printk(unsigned int level, const char *path, int line, { va_list args; #ifdef CONFIG_SND_VERBOSE_PRINTK + int kern_level; struct va_format vaf; char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; #endif @@ -81,12 +82,16 @@ void __snd_printk(unsigned int level, const char *path, int line, #ifdef CONFIG_SND_VERBOSE_PRINTK vaf.fmt = format; vaf.va = &args; - if (format[0] == '<' && format[2] == '>') { - memcpy(verbose_fmt, format, 3); - vaf.fmt = format + 3; + + kern_level = printk_get_level(format); + if (kern_level) { + const char *end_of_header = printk_skip_level(format); + memcpy(verbose_fmt, format, end_of_header - format); + vaf.fmt = end_of_header; } else if (level) - memcpy(verbose_fmt, KERN_DEBUG, 3); + memcpy(verbose_fmt, KERN_DEBUG, sizeof(KERN_DEBUG) - 1); printk(verbose_fmt, sanity_file_name(path), line, &vaf); + #else vprintk(format, args); #endif -- GitLab From 04d2c8c83d0e3ac5f78aeede51babb3236200112 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:17 -0700 Subject: [PATCH 4602/5711] printk: convert the format for KERN_ to a 2 byte pattern Instead of "<.>", use an ASCII SOH for the KERN_ prefix initiator. This saves 1 byte per printk, thousands of bytes in a normal kernel. No output changes are produced as vprintk_emit converts these uses to "<.>". Signed-off-by: Joe Perches Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kern_levels.h | 25 ++++++++++++++----------- include/linux/printk.h | 4 ++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/linux/kern_levels.h b/include/linux/kern_levels.h index 337e56ff5332..8c719a955b5b 100644 --- a/include/linux/kern_levels.h +++ b/include/linux/kern_levels.h @@ -1,22 +1,25 @@ #ifndef __KERN_LEVELS_H__ #define __KERN_LEVELS_H__ -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ +#define KERN_SOH "\001" /* ASCII Start Of Header */ +#define KERN_SOH_ASCII '\001' + +#define KERN_EMERG KERN_SOH "0" /* system is unusable */ +#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */ +#define KERN_CRIT KERN_SOH "2" /* critical conditions */ +#define KERN_ERR KERN_SOH "3" /* error conditions */ +#define KERN_WARNING KERN_SOH "4" /* warning conditions */ +#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */ +#define KERN_INFO KERN_SOH "6" /* informational */ +#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ + +#define KERN_DEFAULT KERN_SOH "d" /* the default kernel loglevel */ -/* Use the default kernel loglevel */ -#define KERN_DEFAULT "" /* * Annotation for a "continued" line of log printout (only done after a * line that had no enclosing \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). */ -#define KERN_CONT "" +#define KERN_CONT KERN_SOH "c" #endif diff --git a/include/linux/printk.h b/include/linux/printk.h index fea2de37b645..93a231f9835c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -9,7 +9,7 @@ extern const char linux_proc_banner[]; static inline int printk_get_level(const char *buffer) { - if (buffer[0] == '<' && buffer[1] && buffer[2] == '>') { + if (buffer[0] == KERN_SOH_ASCII && buffer[1]) { switch (buffer[1]) { case '0' ... '7': case 'd': /* KERN_DEFAULT */ @@ -27,7 +27,7 @@ static inline const char *printk_skip_level(const char *buffer) case '0' ... '7': case 'd': /* KERN_DEFAULT */ case 'c': /* KERN_CONT */ - return buffer + 3; + return buffer + 2; } } return buffer; -- GitLab From 088a52aac810655c1db1e40331e4936946701e9c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:19 -0700 Subject: [PATCH 4603/5711] printk: only look for prefix levels in kernel messages vprintk_emit() prefix parsing should only be done for internal kernel messages. This allows existing behavior to be kept in all cases. Signed-off-by: Joe Perches Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index 0d882a2f231e..6a76ab9d4476 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1487,7 +1487,6 @@ asmlinkage int vprintk_emit(int facility, int level, size_t text_len; enum log_flags lflags = 0; unsigned long flags; - int kern_level; int this_cpu; int printed_len = 0; @@ -1543,21 +1542,24 @@ asmlinkage int vprintk_emit(int facility, int level, lflags |= LOG_NEWLINE; } - /* strip syslog prefix and extract log level or control flags */ - kern_level = printk_get_level(text); - if (kern_level) { - const char *end_of_header = printk_skip_level(text); - switch (kern_level) { - case '0' ... '7': - if (level == -1) - level = kern_level - '0'; - case 'd': /* KERN_DEFAULT */ - lflags |= LOG_PREFIX; - case 'c': /* KERN_CONT */ - break; + /* strip kernel syslog prefix and extract log level or control flags */ + if (facility == 0) { + int kern_level = printk_get_level(text); + + if (kern_level) { + const char *end_of_header = printk_skip_level(text); + switch (kern_level) { + case '0' ... '7': + if (level == -1) + level = kern_level - '0'; + case 'd': /* KERN_DEFAULT */ + lflags |= LOG_PREFIX; + case 'c': /* KERN_CONT */ + break; + } + text_len -= end_of_header - text; + text = (char *)end_of_header; } - text_len -= end_of_header - text; - text = (char *)end_of_header; } if (level == -1) -- GitLab From 61e99ab8e35a88b8c4d0f80d3df9ee16df471be5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:40:21 -0700 Subject: [PATCH 4604/5711] printk: remove the now unnecessary "C" annotation for KERN_CONT Now that all KERN_ uses are prefixed with ASCII SOH, there is no need for a KERN_CONT. Keep it backward compatible by adding #define KERN_CONT "" Reduces kernel image size a thousand bytes. Signed-off-by: Joe Perches Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kern_levels.h | 2 +- include/linux/printk.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/kern_levels.h b/include/linux/kern_levels.h index 8c719a955b5b..866caaa9e2bb 100644 --- a/include/linux/kern_levels.h +++ b/include/linux/kern_levels.h @@ -20,6 +20,6 @@ * line that had no enclosing \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). */ -#define KERN_CONT KERN_SOH "c" +#define KERN_CONT "" #endif diff --git a/include/linux/printk.h b/include/linux/printk.h index 93a231f9835c..9afc01e5a0a6 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -13,7 +13,6 @@ static inline int printk_get_level(const char *buffer) switch (buffer[1]) { case '0' ... '7': case 'd': /* KERN_DEFAULT */ - case 'c': /* KERN_CONT */ return buffer[1]; } } @@ -26,7 +25,6 @@ static inline const char *printk_skip_level(const char *buffer) switch (buffer[1]) { case '0' ... '7': case 'd': /* KERN_DEFAULT */ - case 'c': /* KERN_CONT */ return buffer + 2; } } -- GitLab From 76597ff989a1fbaa9b9a1e54007cd759bf257ab7 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 30 Jul 2012 14:40:23 -0700 Subject: [PATCH 4605/5711] vsprintf: add %pMR for Bluetooth MAC address Bluetooth uses mostly LE byte order which is reversed for visual interpretation. Currently in Bluetooth in use unsafe batostr function. This is a slightly modified version of Joe's patch (sent Sat, Dec 4, 2010). Signed-off-by: Andrei Emeltchenko Cc: Joe Perches Cc: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/printk-formats.txt | 5 +++++ lib/vsprintf.c | 23 +++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 5df176ed59b8..d8d168fa79d6 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -56,6 +56,7 @@ Struct Resources: MAC/FDDI addresses: %pM 00:01:02:03:04:05 + %pMR 05:04:03:02:01:00 %pMF 00-01-02-03-04-05 %pm 000102030405 @@ -67,6 +68,10 @@ MAC/FDDI addresses: the 'M' specifier to use dash ('-') separators instead of the default separator. + For Bluetooth addresses the 'R' specifier shall be used after the 'M' + specifier to use reversed byte order suitable for visual interpretation + of Bluetooth addresses which are in the little endian order. + IPv4 addresses: %pI4 1.2.3.4 diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c3f36d415bdf..736974576e2d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -662,15 +662,28 @@ char *mac_address_string(char *buf, char *end, u8 *addr, char *p = mac_addr; int i; char separator; + bool reversed = false; - if (fmt[1] == 'F') { /* FDDI canonical format */ + switch (fmt[1]) { + case 'F': separator = '-'; - } else { + break; + + case 'R': + reversed = true; + /* fall through */ + + default: separator = ':'; + break; } for (i = 0; i < 6; i++) { - p = hex_byte_pack(p, addr[i]); + if (reversed) + p = hex_byte_pack(p, addr[5 - i]); + else + p = hex_byte_pack(p, addr[i]); + if (fmt[0] == 'M' && i != 5) *p++ = separator; } @@ -933,6 +946,7 @@ int kptr_restrict __read_mostly; * - 'm' For a 6-byte MAC address, it prints the hex address without colons * - 'MF' For a 6-byte MAC FDDI address, it prints the address * with a dash-separated hex notation + * - '[mM]R For a 6-byte MAC address, Reverse order (Bluetooth) * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) * IPv6 uses colon separated network-order 16 bit hex with leading 0's @@ -995,7 +1009,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, return resource_string(buf, end, ptr, spec, fmt); case 'M': /* Colon separated: 00:01:02:03:04:05 */ case 'm': /* Contiguous: 000102030405 */ - /* [mM]F (FDDI, bit reversed) */ + /* [mM]F (FDDI) */ + /* [mM]R (Reverse order; Bluetooth) */ return mac_address_string(buf, end, ptr, spec, fmt); case 'I': /* Formatted IP supported * 4: 1.2.3.4 -- GitLab From 80f548e04d0b1d67d4fa8f59dbecc247f7b71c92 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:40:25 -0700 Subject: [PATCH 4606/5711] lib/vsprintf.c: remind people to update Documentation/printk-formats.txt when adding printk formats Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 736974576e2d..a0b5f15c92cf 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1297,6 +1297,8 @@ qualifier: * case. * %n is ignored * + * ** Please update Documentation/printk-formats.txt when making changes ** + * * The return value is the number of characters which would * be generated for the given input, excluding the trailing * '\0', as per ISO C99. If you want to have the exact -- GitLab From 3715c5309f6d175c3053672b73fd4f73be16fd07 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 30 Jul 2012 14:40:26 -0700 Subject: [PATCH 4607/5711] lib/vsprintf.c: kptr_restrict: fix pK-error in SysRq show-all-timers(Q) When using ALT+SysRq+Q all the pointers are replaced with "pK-error" like this: [23153.208033] .base: pK-error with echo h > /proc/sysrq-trigger it works: [23107.776363] .base: ffff88023e60d540 The intent behind this behavior was to return "pK-error" in cases where the %pK format specifier was used in interrupt context, because the CAP_SYSLOG check wouldn't be meaningful. Clearly this should only apply when kptr_restrict is actually enabled though. Reported-by: Stevie Trujillo Signed-off-by: Dan Rosenberg Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a0b5f15c92cf..225aa683e175 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1045,7 +1045,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, * %pK cannot be used in IRQ context because its test * for CAP_SYSLOG would be meaningless. */ - if (in_irq() || in_serving_softirq() || in_nmi()) { + if (kptr_restrict && (in_irq() || in_serving_softirq() || + in_nmi())) { if (spec.field_width == -1) spec.field_width = default_width; return string(buf, end, "pK-error", spec); -- GitLab From 31550a16a5d2af859e8a11839e8c6c6c9c92dfa7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 30 Jul 2012 14:40:27 -0700 Subject: [PATCH 4608/5711] vsprintf: add support of '%*ph[CDN]' There are many places in the kernel where the drivers print small buffers as a hex string. This patch adds a support of the variable width buffer to print it as a hex string with a delimiter. The idea came from Pavel Roskin here: http://www.digipedia.pl/usenet/thread/18835/17449/ Sample output of pr_info("buf[%d:%d] %*phC\n", from, len, len, &buf[from]); could be look like this: [ 0.726130] buf[51:8] e8:16:b6:ef:e3:74:45:6e [ 0.750736] buf[59:15] 31:81:b8:3f:35:49:06:ae:df:32:06:05:4a:af:55 [ 0.757602] buf[17:5] ac:16:d5:2c:ef Signed-off-by: Andy Shevchenko Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/printk-formats.txt | 10 ++++++ lib/vsprintf.c | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index d8d168fa79d6..7561d7ed8e11 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -53,6 +53,16 @@ Struct Resources: For printing struct resources. The 'R' and 'r' specifiers result in a printed resource with ('R') or without ('r') a decoded flags member. +Raw buffer as a hex string: + %*ph 00 01 02 ... 3f + %*phC 00:01:02: ... :3f + %*phD 00-01-02- ... -3f + %*phN 000102 ... 3f + + For printing a small buffers (up to 64 bytes long) as a hex string with + certain separator. For the larger buffers consider to use + print_hex_dump(). + MAC/FDDI addresses: %pM 00:01:02:03:04:05 diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 225aa683e175..0e337541f005 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -654,6 +654,50 @@ char *resource_string(char *buf, char *end, struct resource *res, return string(buf, end, sym, spec); } +static noinline_for_stack +char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, + const char *fmt) +{ + int i, len = 1; /* if we pass '%ph[CDN]', field witdh remains + negative value, fallback to the default */ + char separator; + + if (spec.field_width == 0) + /* nothing to print */ + return buf; + + if (ZERO_OR_NULL_PTR(addr)) + /* NULL pointer */ + return string(buf, end, NULL, spec); + + switch (fmt[1]) { + case 'C': + separator = ':'; + break; + case 'D': + separator = '-'; + break; + case 'N': + separator = 0; + break; + default: + separator = ' '; + break; + } + + if (spec.field_width > 0) + len = min_t(int, spec.field_width, 64); + + for (i = 0; i < len && buf < end - 1; i++) { + buf = hex_byte_pack(buf, addr[i]); + + if (buf < end && separator && i != len - 1) + *buf++ = separator; + } + + return buf; +} + static noinline_for_stack char *mac_address_string(char *buf, char *end, u8 *addr, struct printf_spec spec, const char *fmt) @@ -974,6 +1018,13 @@ int kptr_restrict __read_mostly; * correctness of the format string and va_list arguments. * - 'K' For a kernel pointer that should be hidden from unprivileged users * - 'NF' For a netdev_features_t + * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with + * a certain separator (' ' by default): + * C colon + * D dash + * N no separator + * The maximum supported length is 64 bytes of the input. Consider + * to use print_hex_dump() for the larger input. * * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a @@ -1007,6 +1058,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'R': case 'r': return resource_string(buf, end, ptr, spec, fmt); + case 'h': + return hex_string(buf, end, ptr, spec, fmt); case 'M': /* Colon separated: 00:01:02:03:04:05 */ case 'm': /* Contiguous: 000102030405 */ /* [mM]F (FDDI) */ @@ -1296,6 +1349,8 @@ qualifier: * %pI6c print an IPv6 address as specified by RFC 5952 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper * case. + * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 + * bytes of the input) * %n is ignored * * ** Please update Documentation/printk-formats.txt when making changes ** -- GitLab From a824c73cc33e149f79914bcebd90ace1433c0721 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:29 -0700 Subject: [PATCH 4609/5711] MAINTAINERS: update EXYNOS DP DRIVER F: patterns Add patterns for Exynos DP header to MAINTAINERS file. Signed-off-by: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index bd451649f13a..c8804c048ac8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2750,6 +2750,7 @@ M: Jingoo Han L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/exynos/exynos_dp* +F: include/video/exynos_dp* EXYNOS MIPI DISPLAY DRIVERS M: Inki Dae -- GitLab From a4be29ac6df4f7c7a0225f7f72c78f4fb10114c0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:31 -0700 Subject: [PATCH 4610/5711] drivers/video/backlight/atmel-pwm-bl.c: use devm_ functions The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_kzalloc of these functions. Signed-off-by: Jingoo Han Acked-by: Hans-Christian Egtvedt Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/atmel-pwm-bl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index 0443a4f71858..cd64073d3f53 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -127,7 +127,8 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) struct atmel_pwm_bl *pwmbl; int retval; - pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL); + pwmbl = devm_kzalloc(&pdev->dev, sizeof(struct atmel_pwm_bl), + GFP_KERNEL); if (!pwmbl) return -ENOMEM; @@ -202,7 +203,6 @@ err_free_gpio: err_free_pwm: pwm_channel_free(&pwmbl->pwmc); err_free_mem: - kfree(pwmbl); return retval; } @@ -218,7 +218,6 @@ static int __exit atmel_pwm_bl_remove(struct platform_device *pdev) pwm_channel_free(&pwmbl->pwmc); backlight_device_unregister(pwmbl->bldev); platform_set_drvdata(pdev, NULL); - kfree(pwmbl); return 0; } -- GitLab From f1b60d46b6f1274f1eacfc89ddbf7f6b63348196 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:33 -0700 Subject: [PATCH 4611/5711] drivers/video/backlight/ot200_bl.c: use devm_ functions The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_kzalloc of these functions Signed-off-by: Jingoo Han Cc: Christian Gmeiner Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/ot200_bl.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/video/backlight/ot200_bl.c b/drivers/video/backlight/ot200_bl.c index f519d55a294c..ef637ffc0799 100644 --- a/drivers/video/backlight/ot200_bl.c +++ b/drivers/video/backlight/ot200_bl.c @@ -97,10 +97,10 @@ static int ot200_backlight_probe(struct platform_device *pdev) goto error_mfgpt_alloc; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { retval = -ENOMEM; - goto error_kzalloc; + goto error_devm_kzalloc; } /* setup gpio */ @@ -122,16 +122,14 @@ static int ot200_backlight_probe(struct platform_device *pdev) if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); retval = PTR_ERR(bl); - goto error_backlight_device_register; + goto error_devm_kzalloc; } platform_set_drvdata(pdev, bl); return 0; -error_backlight_device_register: - kfree(data); -error_kzalloc: +error_devm_kzalloc: cs5535_mfgpt_free_timer(pwm_timer); error_mfgpt_alloc: gpio_free(GPIO_DIMM); @@ -141,7 +139,6 @@ error_mfgpt_alloc: static int ot200_backlight_remove(struct platform_device *pdev) { struct backlight_device *bl = platform_get_drvdata(pdev); - struct ot200_backlight_data *data = bl_get_data(bl); backlight_device_unregister(bl); @@ -154,7 +151,6 @@ static int ot200_backlight_remove(struct platform_device *pdev) cs5535_mfgpt_free_timer(pwm_timer); gpio_free(GPIO_DIMM); - kfree(data); return 0; } -- GitLab From b4a74615a4729ca4e6903bd3027339c4e6e7ae03 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:34 -0700 Subject: [PATCH 4612/5711] drivers/video/backlight/lm3533_bl.c: use devm_ functions The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_kzalloc of these functions. Signed-off-by: Jingoo Han Acked-by: Johan Hovold Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lm3533_bl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index bebeb63607db..18dca0c29c68 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -295,7 +295,7 @@ static int __devinit lm3533_bl_probe(struct platform_device *pdev) return -EINVAL; } - bl = kzalloc(sizeof(*bl), GFP_KERNEL); + bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL); if (!bl) { dev_err(&pdev->dev, "failed to allocate memory for backlight\n"); @@ -317,8 +317,7 @@ static int __devinit lm3533_bl_probe(struct platform_device *pdev) &lm3533_bl_ops, &props); if (IS_ERR(bd)) { dev_err(&pdev->dev, "failed to register backlight device\n"); - ret = PTR_ERR(bd); - goto err_free; + return PTR_ERR(bd); } bl->bd = bd; @@ -348,8 +347,6 @@ err_sysfs_remove: sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group); err_unregister: backlight_device_unregister(bd); -err_free: - kfree(bl); return ret; } @@ -367,7 +364,6 @@ static int __devexit lm3533_bl_remove(struct platform_device *pdev) lm3533_ctrlbank_disable(&bl->cb); sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group); backlight_device_unregister(bd); - kfree(bl); return 0; } -- GitLab From 5f9dd5c9fd4efacc9f8c36c0b3c17a4308bbe4d9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:36 -0700 Subject: [PATCH 4613/5711] backlight: atmel-pwm-bl: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Cc: Hans-Christian Egtvedt Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/atmel-pwm-bl.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index cd64073d3f53..df1cbb7ef6ca 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -155,7 +155,8 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) goto err_free_mem; if (pwmbl->gpio_on != -1) { - retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl"); + retval = devm_gpio_request(&pdev->dev, pwmbl->gpio_on, + "gpio_atmel_pwm_bl"); if (retval) { pwmbl->gpio_on = -1; goto err_free_pwm; @@ -165,7 +166,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) retval = gpio_direction_output(pwmbl->gpio_on, 0 ^ pdata->on_active_low); if (retval) - goto err_free_gpio; + goto err_free_pwm; } memset(&props, 0, sizeof(struct backlight_properties)); @@ -175,7 +176,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) &atmel_pwm_bl_ops, &props); if (IS_ERR(bldev)) { retval = PTR_ERR(bldev); - goto err_free_gpio; + goto err_free_pwm; } pwmbl->bldev = bldev; @@ -197,9 +198,6 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) err_free_bl_dev: platform_set_drvdata(pdev, NULL); backlight_device_unregister(bldev); -err_free_gpio: - if (pwmbl->gpio_on != -1) - gpio_free(pwmbl->gpio_on); err_free_pwm: pwm_channel_free(&pwmbl->pwmc); err_free_mem: @@ -210,10 +208,8 @@ static int __exit atmel_pwm_bl_remove(struct platform_device *pdev) { struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev); - if (pwmbl->gpio_on != -1) { + if (pwmbl->gpio_on != -1) gpio_set_value(pwmbl->gpio_on, 0); - gpio_free(pwmbl->gpio_on); - } pwm_channel_disable(&pwmbl->pwmc); pwm_channel_free(&pwmbl->pwmc); backlight_device_unregister(pwmbl->bldev); -- GitLab From f673934c615987abe16919ede8fcd3ff6805d0d6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:37 -0700 Subject: [PATCH 4614/5711] backlight: ot200_bl: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Acked-by: Christian Gmeiner Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/ot200_bl.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/ot200_bl.c b/drivers/video/backlight/ot200_bl.c index ef637ffc0799..469cf0f109d2 100644 --- a/drivers/video/backlight/ot200_bl.c +++ b/drivers/video/backlight/ot200_bl.c @@ -84,7 +84,8 @@ static int ot200_backlight_probe(struct platform_device *pdev) int retval = 0; /* request gpio */ - if (gpio_request(GPIO_DIMM, "ot200 backlight dimmer") < 0) { + if (devm_gpio_request(&pdev->dev, GPIO_DIMM, + "ot200 backlight dimmer") < 0) { dev_err(&pdev->dev, "failed to request GPIO %d\n", GPIO_DIMM); return -ENODEV; } @@ -93,8 +94,7 @@ static int ot200_backlight_probe(struct platform_device *pdev) pwm_timer = cs5535_mfgpt_alloc_timer(7, MFGPT_DOMAIN_ANY); if (!pwm_timer) { dev_err(&pdev->dev, "MFGPT 7 not available\n"); - retval = -ENODEV; - goto error_mfgpt_alloc; + return -ENODEV; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -131,8 +131,6 @@ static int ot200_backlight_probe(struct platform_device *pdev) error_devm_kzalloc: cs5535_mfgpt_free_timer(pwm_timer); -error_mfgpt_alloc: - gpio_free(GPIO_DIMM); return retval; } @@ -149,7 +147,6 @@ static int ot200_backlight_remove(struct platform_device *pdev) MAX_COMP2 - dim_table[100]); cs5535_mfgpt_free_timer(pwm_timer); - gpio_free(GPIO_DIMM); return 0; } -- GitLab From 402ff9a26427c2c8fa5424c24ba04a7f6ecc25f1 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:39 -0700 Subject: [PATCH 4615/5711] backlight: tosa_lcd: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Cc: Dmitry Baryshkov Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/tosa_lcd.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 47823b8efff0..33047a66cc24 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -193,7 +193,7 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi) data->spi = spi; dev_set_drvdata(&spi->dev, data); - ret = gpio_request(TOSA_GPIO_TG_ON, "tg #pwr"); + ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr"); if (ret < 0) goto err_gpio_tg; @@ -201,7 +201,7 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi) ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0); if (ret < 0) - goto err_gpio_dir; + goto err_gpio_tg; mdelay(60); tosa_lcd_tg_init(data); @@ -221,8 +221,6 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi) err_register: tosa_lcd_tg_off(data); -err_gpio_dir: - gpio_free(TOSA_GPIO_TG_ON); err_gpio_tg: dev_set_drvdata(&spi->dev, NULL); return ret; @@ -239,7 +237,6 @@ static int __devexit tosa_lcd_remove(struct spi_device *spi) tosa_lcd_tg_off(data); - gpio_free(TOSA_GPIO_TG_ON); dev_set_drvdata(&spi->dev, NULL); return 0; -- GitLab From f5b71941a5359cd6702be26715fd57d47187c0d9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:40 -0700 Subject: [PATCH 4616/5711] backlight: tosa_bl: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Cc: Dmitry Baryshkov Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/tosa_bl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 0d54e607e82d..49342e1d20be 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -92,14 +92,14 @@ static int __devinit tosa_bl_probe(struct i2c_client *client, data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; - ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight"); + ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight"); if (ret) { dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); return ret; } ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0); if (ret) - goto err_gpio_dir; + return ret; i2c_set_clientdata(client, data); data->i2c = client; @@ -123,8 +123,6 @@ static int __devinit tosa_bl_probe(struct i2c_client *client, err_reg: data->bl = NULL; -err_gpio_dir: - gpio_free(TOSA_GPIO_BL_C20MA); return ret; } @@ -135,8 +133,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client) backlight_device_unregister(data->bl); data->bl = NULL; - gpio_free(TOSA_GPIO_BL_C20MA); - return 0; } -- GitLab From 04e961fb1da31258f7bf4480a59518c3de3caa60 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:43 -0700 Subject: [PATCH 4617/5711] backlight: lms283gf05: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Acked-by: Marek Vasut Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lms283gf05.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index a9f2c36966f1..ea43f2254196 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -158,29 +158,27 @@ static int __devinit lms283gf05_probe(struct spi_device *spi) int ret = 0; if (pdata != NULL) { - ret = gpio_request(pdata->reset_gpio, "LMS285GF05 RESET"); + ret = devm_gpio_request(&spi->dev, pdata->reset_gpio, + "LMS285GF05 RESET"); if (ret) return ret; ret = gpio_direction_output(pdata->reset_gpio, !pdata->reset_inverted); if (ret) - goto err; + return ret; } st = devm_kzalloc(&spi->dev, sizeof(struct lms283gf05_state), GFP_KERNEL); if (st == NULL) { dev_err(&spi->dev, "No memory for device state\n"); - ret = -ENOMEM; - goto err; + return -ENOMEM; } ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops); - if (IS_ERR(ld)) { - ret = PTR_ERR(ld); - goto err; - } + if (IS_ERR(ld)) + return PTR_ERR(ld); st->spi = spi; st->ld = ld; @@ -193,24 +191,14 @@ static int __devinit lms283gf05_probe(struct spi_device *spi) lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); return 0; - -err: - if (pdata != NULL) - gpio_free(pdata->reset_gpio); - - return ret; } static int __devexit lms283gf05_remove(struct spi_device *spi) { struct lms283gf05_state *st = dev_get_drvdata(&spi->dev); - struct lms283gf05_pdata *pdata = st->spi->dev.platform_data; lcd_device_unregister(st->ld); - if (pdata != NULL) - gpio_free(pdata->reset_gpio); - return 0; } -- GitLab From 4405d5d9dd76740bfb715fc6a32343e087a13e1e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:45 -0700 Subject: [PATCH 4618/5711] backlight: corgi_lcd: use devm_gpio_request() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request() for these functions. Signed-off-by: Jingoo Han Cc: Eric Miao Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/corgi_lcd.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index 23d732677ba1..c781768ba892 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -492,7 +492,8 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, lcd->gpio_backlight_cont = -1; if (gpio_is_valid(pdata->gpio_backlight_on)) { - err = gpio_request(pdata->gpio_backlight_on, "BL_ON"); + err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on, + "BL_ON"); if (err) { dev_err(&spi->dev, "failed to request GPIO%d for " "backlight_on\n", pdata->gpio_backlight_on); @@ -504,11 +505,12 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, } if (gpio_is_valid(pdata->gpio_backlight_cont)) { - err = gpio_request(pdata->gpio_backlight_cont, "BL_CONT"); + err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont, + "BL_CONT"); if (err) { dev_err(&spi->dev, "failed to request GPIO%d for " "backlight_cont\n", pdata->gpio_backlight_cont); - goto err_free_backlight_on; + return err; } lcd->gpio_backlight_cont = pdata->gpio_backlight_cont; @@ -525,11 +527,6 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, } } return 0; - -err_free_backlight_on: - if (gpio_is_valid(lcd->gpio_backlight_on)) - gpio_free(lcd->gpio_backlight_on); - return err; } static int __devinit corgi_lcd_probe(struct spi_device *spi) @@ -602,12 +599,6 @@ static int __devexit corgi_lcd_remove(struct spi_device *spi) backlight_update_status(lcd->bl_dev); backlight_device_unregister(lcd->bl_dev); - if (gpio_is_valid(lcd->gpio_backlight_on)) - gpio_free(lcd->gpio_backlight_on); - - if (gpio_is_valid(lcd->gpio_backlight_cont)) - gpio_free(lcd->gpio_backlight_cont); - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); lcd_device_unregister(lcd->lcd_dev); -- GitLab From 62a5c075bafb91895506bc68f76db1ff1b5d1a02 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 30 Jul 2012 14:40:47 -0700 Subject: [PATCH 4619/5711] backlight: l4f00242t03: export and use devm_gpio_request_one() The devm_ functions allocate memory that is released when a driver detaches. This patch uses devm_gpio_request_one() for these functions. Signed-off-by: Jingoo Han Cc: Alberto Panizzo Cc: Richard Purdie Cc: Grant Likely Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/l4f00242t03.c | 29 +++++++++------------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 40f606a86093..2d90c0648aa0 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -175,28 +175,27 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) priv->spi = spi; - ret = gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, - "lcd l4f00242t03 reset"); + ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, + GPIOF_OUT_INIT_HIGH, "lcd l4f00242t03 reset"); if (ret) { dev_err(&spi->dev, "Unable to get the lcd l4f00242t03 reset gpio.\n"); return ret; } - ret = gpio_request_one(pdata->data_enable_gpio, GPIOF_OUT_INIT_LOW, - "lcd l4f00242t03 data enable"); + ret = devm_gpio_request_one(&spi->dev, pdata->data_enable_gpio, + GPIOF_OUT_INIT_LOW, "lcd l4f00242t03 data enable"); if (ret) { dev_err(&spi->dev, "Unable to get the lcd l4f00242t03 data en gpio.\n"); - goto err; + return ret; } priv->io_reg = regulator_get(&spi->dev, "vdd"); if (IS_ERR(priv->io_reg)) { - ret = PTR_ERR(priv->io_reg); dev_err(&spi->dev, "%s: Unable to get the IO regulator\n", __func__); - goto err2; + return PTR_ERR(priv->io_reg); } priv->core_reg = regulator_get(&spi->dev, "vcore"); @@ -204,14 +203,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) ret = PTR_ERR(priv->core_reg); dev_err(&spi->dev, "%s: Unable to get the core regulator\n", __func__); - goto err3; + goto err1; } priv->ld = lcd_device_register("l4f00242t03", &spi->dev, priv, &l4f_ops); if (IS_ERR(priv->ld)) { ret = PTR_ERR(priv->ld); - goto err4; + goto err2; } /* Init the LCD */ @@ -223,14 +222,10 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) return 0; -err4: +err2: regulator_put(priv->core_reg); -err3: +err1: regulator_put(priv->io_reg); -err2: - gpio_free(pdata->data_enable_gpio); -err: - gpio_free(pdata->reset_gpio); return ret; } @@ -238,16 +233,12 @@ err: static int __devexit l4f00242t03_remove(struct spi_device *spi) { struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); - struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); lcd_device_unregister(priv->ld); dev_set_drvdata(&spi->dev, NULL); - gpio_free(pdata->data_enable_gpio); - gpio_free(pdata->reset_gpio); - regulator_put(priv->io_reg); regulator_put(priv->core_reg); -- GitLab From a1fcb2e31822c0617c6e274de4af2a2bb5dc7d3f Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Mon, 30 Jul 2012 14:40:50 -0700 Subject: [PATCH 4620/5711] backlight: move register definitions from header to source ROM boundary definitions do not need to be exported because these are used only internally in the lp855x driver. And few code cosmetic changes Signed-off-by: Milo(Woogyom) Kim Cc: Richard Purdie Cc: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lp855x_bl.c | 8 ++++++-- include/linux/lp855x.h | 6 ------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 72a0e0c917cf..3d24314bc4e1 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -17,8 +17,12 @@ #include /* Registers */ -#define BRIGHTNESS_CTRL (0x00) -#define DEVICE_CTRL (0x01) +#define BRIGHTNESS_CTRL 0x00 +#define DEVICE_CTRL 0x01 +#define EEPROM_START 0xA0 +#define EEPROM_END 0xA7 +#define EPROM_START 0xA0 +#define EPROM_END 0xAF #define BUF_SIZE 20 #define DEFAULT_BL_NAME "lcd-backlight" diff --git a/include/linux/lp855x.h b/include/linux/lp855x.h index 781a490a451b..cc76f1f18f18 100644 --- a/include/linux/lp855x.h +++ b/include/linux/lp855x.h @@ -47,12 +47,6 @@ (LP8556_I2C_ONLY << BRT_MODE_SHFT)) #define LP8556_COMB2_CONFIG (LP8556_COMBINED2 << BRT_MODE_SHFT) -/* ROM area boundary */ -#define EEPROM_START (0xA0) -#define EEPROM_END (0xA7) -#define EPROM_START (0xA0) -#define EPROM_END (0xAF) - enum lp855x_chip_id { LP8550, LP8551, -- GitLab From f7f95056779eb69c5fc3ac30e5cb6fd28bdbba43 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Mon, 30 Jul 2012 14:40:53 -0700 Subject: [PATCH 4621/5711] backlight: move lp855x header into platform_data directory The lp855x header is used only in the platform side, so it can be moved into platform_data directory Signed-off-by: Milo(Woogyom) Kim Cc: Richard Purdie Cc: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lp855x_bl.c | 2 +- include/linux/{ => platform_data}/lp855x.h | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename include/linux/{ => platform_data}/lp855x.h (100%) diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 3d24314bc4e1..aa6d4f71131f 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include /* Registers */ #define BRIGHTNESS_CTRL 0x00 diff --git a/include/linux/lp855x.h b/include/linux/platform_data/lp855x.h similarity index 100% rename from include/linux/lp855x.h rename to include/linux/platform_data/lp855x.h -- GitLab From 639b9e34f15e4b2c30068a4e4485586af0cdf709 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:40:55 -0700 Subject: [PATCH 4622/5711] string: introduce memweight() memweight() is the function that counts the total number of bits set in memory area. Unlike bitmap_weight(), memweight() takes pointer and size in bytes to specify a memory area which does not need to be aligned to long-word boundary. [akpm@linux-foundation.org: rename `w' to `ret'] Signed-off-by: Akinobu Mita Cc: Anders Larsen Cc: Alasdair Kergon Cc: Laurent Pinchart Cc: Mark Fasheh Cc: Joel Becker Cc: Jan Kara Cc: Andreas Dilger Cc: "Theodore Ts'o" Cc: Matthew Wilcox Cc: Mauro Carvalho Chehab Cc: Tony Luck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/string.h | 3 +++ lib/Makefile | 2 +- lib/memweight.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 lib/memweight.c diff --git a/include/linux/string.h b/include/linux/string.h index e033564f10ba..ffe0442e18d2 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -145,4 +145,7 @@ static inline bool strstarts(const char *str, const char *prefix) return strncmp(str, prefix, strlen(prefix)) == 0; } #endif + +extern size_t memweight(const void *ptr, size_t bytes); + #endif /* _LINUX_STRING_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 8c31a0cb75e9..df663cc05c73 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -22,7 +22,7 @@ lib-y += kobject.o klist.o obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \ - bsearch.o find_last_bit.o find_next_bit.o llist.o + bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o obj-y += kstrtox.o obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o diff --git a/lib/memweight.c b/lib/memweight.c new file mode 100644 index 000000000000..e35fc8771893 --- /dev/null +++ b/lib/memweight.c @@ -0,0 +1,38 @@ +#include +#include +#include + +/** + * memweight - count the total number of bits set in memory area + * @ptr: pointer to the start of the area + * @bytes: the size of the area + */ +size_t memweight(const void *ptr, size_t bytes) +{ + size_t ret = 0; + size_t longs; + const unsigned char *bitmap = ptr; + + for (; bytes > 0 && ((unsigned long)bitmap) % sizeof(long); + bytes--, bitmap++) + ret += hweight8(*bitmap); + + longs = bytes / sizeof(long); + if (longs) { + BUG_ON(longs >= INT_MAX / BITS_PER_LONG); + ret += bitmap_weight((unsigned long *)bitmap, + longs * BITS_PER_LONG); + bytes -= longs * sizeof(long); + bitmap += longs * sizeof(long); + } + /* + * The reason that this last loop is distinct from the preceding + * bitmap_weight() call is to compute 1-bits in the last region smaller + * than sizeof(long) properly on big-endian systems. + */ + for (; bytes > 0; bytes--, bitmap++) + ret += hweight8(*bitmap); + + return ret; +} +EXPORT_SYMBOL(memweight); -- GitLab From 9b58f6d4aaef070bf6e0744713b6d2b6fc1b3578 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:40:57 -0700 Subject: [PATCH 4623/5711] qnx4fs: use memweight() Use memweight() to count the total number of bits clear in memory area. Note that this memweight() call can't be replaced with a single bitmap_weight() call, although the pointer to the memory area is aligned to long-word boundary. Because the size of the memory area may not be a multiple of BITS_PER_LONG, then it returns wrong value on big-endian architecture. Signed-off-by: Akinobu Mita Acked-by: Anders Larsen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/qnx4/bitmap.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c index 22e0d60e53ef..76a7a697b778 100644 --- a/fs/qnx4/bitmap.c +++ b/fs/qnx4/bitmap.c @@ -17,23 +17,6 @@ #include #include "qnx4.h" -static void count_bits(register const char *bmPart, register int size, - int *const tf) -{ - char b; - int tot = *tf; - - if (size > QNX4_BLOCK_SIZE) { - size = QNX4_BLOCK_SIZE; - } - do { - b = *bmPart++; - tot += 8 - hweight8(b); - size--; - } while (size != 0); - *tf = tot; -} - unsigned long qnx4_count_free_blocks(struct super_block *sb) { int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1; @@ -44,13 +27,16 @@ unsigned long qnx4_count_free_blocks(struct super_block *sb) struct buffer_head *bh; while (total < size) { + int bytes = min(size - total, QNX4_BLOCK_SIZE); + if ((bh = sb_bread(sb, start + offset)) == NULL) { printk(KERN_ERR "qnx4: I/O error in counting free blocks\n"); break; } - count_bits(bh->b_data, size - total, &total_free); + total_free += bytes * BITS_PER_BYTE - + memweight(bh->b_data, bytes); brelse(bh); - total += QNX4_BLOCK_SIZE; + total += bytes; offset++; } -- GitLab From 8fb980e35b41bbb79aa47f48839d95f0354af3c4 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:40:59 -0700 Subject: [PATCH 4624/5711] dm: use memweight() Use memweight() to count the total number of bits set in memory area. Signed-off-by: Akinobu Mita Cc: Alasdair Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-log.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 65ebaebf502b..627d19186d5a 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -571,16 +571,6 @@ static void disk_dtr(struct dm_dirty_log *log) destroy_log_context(lc); } -static int count_bits32(uint32_t *addr, unsigned size) -{ - int count = 0, i; - - for (i = 0; i < size; i++) { - count += hweight32(*(addr+i)); - } - return count; -} - static void fail_log_device(struct log_c *lc) { if (lc->log_dev_failed) @@ -629,7 +619,8 @@ static int disk_resume(struct dm_dirty_log *log) /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); - lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); + lc->sync_count = memweight(lc->clean_bits, + lc->bitset_uint32_count * sizeof(uint32_t)); lc->sync_search = 0; /* set the correct number of regions in the header */ -- GitLab From 0121ad62c20ed779e38ad689071da2805f03249f Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:00 -0700 Subject: [PATCH 4625/5711] affs: use memweight() Use memweight() to count the total number of bits set in memory area. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/affs/bitmap.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 6e0be43ef6ef..a32246b8359e 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -10,30 +10,6 @@ #include #include "affs.h" -/* This is, of course, shamelessly stolen from fs/minix */ - -static const int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; - -static u32 -affs_count_free_bits(u32 blocksize, const void *data) -{ - const u32 *map; - u32 free; - u32 tmp; - - map = data; - free = 0; - for (blocksize /= 4; blocksize > 0; blocksize--) { - tmp = *map++; - while (tmp) { - free += nibblemap[tmp & 0xf]; - tmp >>= 4; - } - } - - return free; -} - u32 affs_count_free_blocks(struct super_block *sb) { @@ -317,7 +293,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags) goto out; } pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key); - bm->bm_free = affs_count_free_bits(sb->s_blocksize - 4, bh->b_data + 4); + bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4); /* Don't try read the extension if this is the last block, * but we also need the right bm pointer below @@ -367,7 +343,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags) /* recalculate bitmap count for last block */ bm--; - bm->bm_free = affs_count_free_bits(sb->s_blocksize - 4, bh->b_data + 4); + bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4); out: affs_brelse(bh); -- GitLab From 9a601396e8681d9884a9f429cba7ceb2b2a4d21c Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:02 -0700 Subject: [PATCH 4626/5711] video/uvc: use memweight() Use memweight() to count the total number of bits set in memory area. Signed-off-by: Akinobu Mita Acked-by: Laurent Pinchart Acked-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/uvc/uvc_ctrl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index af26bbe6f76e..f7061a5ef1d2 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -2083,7 +2083,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) /* Walk the entities list and instantiate controls */ list_for_each_entry(entity, &dev->entities, list) { struct uvc_control *ctrl; - unsigned int bControlSize = 0, ncontrols = 0; + unsigned int bControlSize = 0, ncontrols; __u8 *bmControls = NULL; if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { @@ -2101,8 +2101,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) uvc_ctrl_prune_entity(dev, entity); /* Count supported controls and allocate the controls array */ - for (i = 0; i < bControlSize; ++i) - ncontrols += hweight8(bmControls[i]); + ncontrols = memweight(bmControls, bControlSize); if (ncontrols == 0) continue; -- GitLab From a75613ec73ec87726a81fe421385a13c25fdcfc4 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:03 -0700 Subject: [PATCH 4627/5711] ocfs2: use memweight() Use memweight to count the total number of bits set in memory area. Signed-off-by: Akinobu Mita Cc: Mark Fasheh Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ocfs2/localalloc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 210c35237548..a9f78c74d687 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -784,14 +784,10 @@ bail: static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) { - int i; - u8 *buffer; - u32 count = 0; + u32 count; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - buffer = la->la_bitmap; - for (i = 0; i < le16_to_cpu(la->la_size); i++) - count += hweight8(buffer[i]); + count = memweight(la->la_bitmap, le16_to_cpu(la->la_size)); trace_ocfs2_local_alloc_count_bits(count); return count; -- GitLab From ecd0afa3ced0ebf36901b53fd9ee431f8a34a161 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:05 -0700 Subject: [PATCH 4628/5711] ext2: use memweight() Convert ext2_count_free() to use memweight() instead of table lookup based counting clear bits implementation. This change only affects the code segments enabled by EXT2FS_DEBUG. Note that this memweight() call can't be replaced with a single bitmap_weight() call, although the pointer to the memory area is aligned to long-word boundary. Because the size of the memory area may not be a multiple of BITS_PER_LONG, then it returns wrong value on big-endian architecture. This also includes the following changes. - Remove unnecessary map == NULL check in ext2_count_free() which always takes non-null pointer as the memory area. - Fix printk format warning that only reveals with EXT2FS_DEBUG. Signed-off-by: Akinobu Mita Acked-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/balloc.c | 14 ++------------ fs/ext2/ialloc.c | 1 + 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 1c3613998862..376aa77f3ca7 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -1444,19 +1444,9 @@ ext2_fsblk_t ext2_new_block(struct inode *inode, unsigned long goal, int *errp) #ifdef EXT2FS_DEBUG -static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; - -unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars) +unsigned long ext2_count_free(struct buffer_head *map, unsigned int numchars) { - unsigned int i; - unsigned long sum = 0; - - if (!map) - return (0); - for (i = 0; i < numchars; i++) - sum += nibblemap[map->b_data[i] & 0xf] + - nibblemap[(map->b_data[i] >> 4) & 0xf]; - return (sum); + return numchars * BITS_PER_BYTE - memweight(map->b_data, numchars); } #endif /* EXT2FS_DEBUG */ diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index c13eb7b91a11..8f370e012e61 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -644,6 +644,7 @@ unsigned long ext2_count_free_inodes (struct super_block * sb) } brelse(bitmap_bh); printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n", + (unsigned long) percpu_counter_read(&EXT2_SB(sb)->s_freeinodes_counter), desc_count, bitmap_count); return desc_count; -- GitLab From 10d470849a7c6dd360e8ad4770160ad7af9adb4b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:06 -0700 Subject: [PATCH 4629/5711] ext3: use memweight() Convert ext3_count_free() to use memweight() instead of table lookup based counting clear bits implementation. This change only affects the code segments enabled by EXT3FS_DEBUG. Note that this memweight() call can't be replaced with a single bitmap_weight() call, although the pointer to the memory area is aligned to long-word boundary. Because the size of the memory area may not be a multiple of BITS_PER_LONG, then it returns wrong value on big-endian architecture. This also includes the following changes. - Remove unnecessary map == NULL check in ext3_count_free() which always takes non-null pointer as the memory area. - Fix printk format warning that only reveals with EXT3FS_DEBUG. Signed-off-by: Akinobu Mita Acked-by: Jan Kara Cc: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- fs/ext3/bitmap.c | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 25cd60892116..90d901f0486b 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1813,7 +1813,7 @@ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb) brelse(bitmap_bh); printk("ext3_count_free_blocks: stored = "E3FSBLK ", computed = "E3FSBLK", "E3FSBLK"\n", - le32_to_cpu(es->s_free_blocks_count), + (ext3_fsblk_t)le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); return bitmap_count; #else diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c index 909d13e26560..ef9c643e8e9d 100644 --- a/fs/ext3/bitmap.c +++ b/fs/ext3/bitmap.c @@ -11,19 +11,9 @@ #ifdef EXT3FS_DEBUG -static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; - unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars) { - unsigned int i; - unsigned long sum = 0; - - if (!map) - return (0); - for (i = 0; i < numchars; i++) - sum += nibblemap[map->b_data[i] & 0xf] + - nibblemap[(map->b_data[i] >> 4) & 0xf]; - return (sum); + return numchars * BITS_PER_BYTE - memweight(map->b_data, numchars); } #endif /* EXT3FS_DEBUG */ -- GitLab From 6017b485caeae5915956190b4f3d8307021e785d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:41:08 -0700 Subject: [PATCH 4630/5711] ext4: use memweight() Convert ext4_count_free() to use memweight() instead of table lookup based counting clear bits implementation. This change only affects the code segments enabled by EXT4FS_DEBUG. Note that this memweight() call can't be replaced with a single bitmap_weight() call, although the pointer to the memory area is aligned to long-word boundary. Because the size of the memory area may not be a multiple of BITS_PER_LONG, then it returns wrong value on big-endian architecture. This also includes the following change. - Remove unnecessary map == NULL check in ext4_count_free() which always takes non-null pointer as the memory area. Signed-off-by: Akinobu Mita Cc: "Theodore Ts'o" Cc: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext4/bitmap.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index a94b9c63ee5c..f8716eab9995 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -11,16 +11,9 @@ #include #include "ext4.h" -static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; - unsigned int ext4_count_free(char *bitmap, unsigned int numchars) { - unsigned int i, sum = 0; - - for (i = 0; i < numchars; i++) - sum += nibblemap[bitmap[i] & 0xf] + - nibblemap[(bitmap[i] >> 4) & 0xf]; - return sum; + return numchars * BITS_PER_BYTE - memweight(bitmap, numchars); } int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, -- GitLab From 7463449b8287162454d7e00bf7fd2c64f72c1dc8 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 30 Jul 2012 14:41:09 -0700 Subject: [PATCH 4631/5711] atomic64_test: simplify the #ifdef for atomic64_dec_if_positive() test Introduce CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE and use this instead of the multitude of #if defined() checks in atomic64_test.c Signed-off-by: Catalin Marinas Cc: Russell King Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/Kconfig | 1 + arch/mips/Kconfig | 1 + arch/powerpc/Kconfig | 1 + arch/s390/Kconfig | 1 + arch/x86/Kconfig | 1 + lib/Kconfig | 3 +++ lib/atomic64_test.c | 5 ++--- 7 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fbdd8533c05d..4172c3cea228 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -11,6 +11,7 @@ config ARM select RTC_LIB select SYS_SUPPORTS_APM_EMULATION select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_KGDB diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b3e10fdd3898..5e238d03960d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -20,6 +20,7 @@ config MIPS select ARCH_BINFMT_ELF_RANDOMIZE_PIE select RTC_LIB if !MACH_LOONGSON select GENERIC_ATOMIC64 if !64BIT + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_DMA_ATTRS select HAVE_DMA_API_DEBUG select HAVE_GENERIC_HARDIRQS diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9a5d3cdc3e12..4f681b78dd8b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -115,6 +115,7 @@ config PPC select HAVE_OPROFILE select HAVE_SYSCALL_WRAPPERS if PPC64 select GENERIC_ATOMIC64 if PPC32 + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_IRQ_WORK select HAVE_PERF_EVENTS select HAVE_REGS_AND_STACK_ACCESS_API diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a39b4690c171..d0a5e92b6b9e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -85,6 +85,7 @@ config S390 select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select ARCH_SAVE_PAGE_KEYS if HIBERNATION + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select HAVE_CMPXCHG_LOCAL diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c70684f859e1..ca4fdefe79e6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -70,6 +70,7 @@ config X86 select HAVE_ARCH_JUMP_LABEL select HAVE_TEXT_POKE_SMP select HAVE_GENERIC_HARDIRQS + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select SPARSE_IRQ select GENERIC_FIND_FIRST_BIT select GENERIC_IRQ_PROBE diff --git a/lib/Kconfig b/lib/Kconfig index 8269d56dcdaa..72c1d4693068 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -340,6 +340,9 @@ config NLATTR config GENERIC_ATOMIC64 bool +config ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE + def_bool y if GENERIC_ATOMIC64 + config LRU_CACHE tristate diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index cb99b91c3a1d..00bca223d1e1 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -114,8 +114,7 @@ static __init int test_atomic64(void) r += one; BUG_ON(v.counter != r); -#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \ - defined(CONFIG_S390) || defined(_ASM_GENERIC_ATOMIC64_H) || defined(CONFIG_ARM) +#ifdef CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE INIT(onestwos); BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1)); r -= one; @@ -129,7 +128,7 @@ static __init int test_atomic64(void) BUG_ON(atomic64_dec_if_positive(&v) != (-one - one)); BUG_ON(v.counter != r); #else -#warning Please implement atomic64_dec_if_positive for your architecture, and add it to the IF above +#warning Please implement atomic64_dec_if_positive for your architecture and select the above Kconfig symbol #endif INIT(onestwos); -- GitLab From 4b0681487bf72fdb86b42c93b7d8a607e5a426b1 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 30 Jul 2012 14:41:11 -0700 Subject: [PATCH 4632/5711] spinlock_debug: print offset in addition to symbol name If there are two spinlocks embedded in a structure that kallsyms knows about and one of the spinlocks locks up we will print the name of the containing structure instead of the address of the lock. This is quite bad, so let's use %pS instead of %ps so we get an offset in addition to the symbol so we can determine which particular lock is having problems. Signed-off-by: Stephen Boyd Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/spinlock_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index e91fbc23fff1..eb10578ae055 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -58,7 +58,7 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", msg, raw_smp_processor_id(), current->comm, task_pid_nr(current)); - printk(KERN_EMERG " lock: %ps, .magic: %08x, .owner: %s/%d, " + printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, " ".owner_cpu: %d\n", lock, lock->magic, owner ? owner->comm : "", -- GitLab From 4ed940d4c34c21a1a356969a923f2815d608e0bf Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Mon, 30 Jul 2012 14:41:13 -0700 Subject: [PATCH 4633/5711] firmware_map: make firmware_map_add_early() argument consistent with firmware_map_add_hotplug() There are two ways to create /sys/firmware/memmap/X sysfs: - firmware_map_add_early When the system starts, it is calledd from e820_reserve_resources() - firmware_map_add_hotplug When the memory is hot plugged, it is called from add_memory() But these functions are called without unifying value of end argument as below: - end argument of firmware_map_add_early() : start + size - 1 - end argument of firmware_map_add_hogplug() : start + size The patch unifies them to "start + size". Even if applying the patch, /sys/firmware/memmap/X/end file content does not change. [akpm@linux-foundation.org: clarify comments] Signed-off-by: Yasuaki Ishimatsu Reviewed-by: Dave Hansen Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/kernel/e820.c | 2 +- drivers/firmware/memmap.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 41857970517f..ed858e9e9a74 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -944,7 +944,7 @@ void __init e820_reserve_resources(void) for (i = 0; i < e820_saved.nr_map; i++) { struct e820entry *entry = &e820_saved.map[i]; firmware_map_add_early(entry->addr, - entry->addr + entry->size - 1, + entry->addr + entry->size, e820_type_to_string(entry->type)); } } diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index adc07102a20d..c1cdc9236666 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -98,7 +98,7 @@ static LIST_HEAD(map_entries); /** * firmware_map_add_entry() - Does the real work to add a firmware memmap entry. * @start: Start of the memory range. - * @end: End of the memory range (inclusive). + * @end: End of the memory range (exclusive). * @type: Type of the memory range. * @entry: Pre-allocated (either kmalloc() or bootmem allocator), uninitialised * entry. @@ -113,7 +113,7 @@ static int firmware_map_add_entry(u64 start, u64 end, BUG_ON(start > end); entry->start = start; - entry->end = end; + entry->end = end - 1; entry->type = type; INIT_LIST_HEAD(&entry->list); kobject_init(&entry->kobj, &memmap_ktype); @@ -148,7 +148,7 @@ static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry) * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do * memory hotplug. * @start: Start of the memory range. - * @end: End of the memory range (inclusive). + * @end: End of the memory range (exclusive) * @type: Type of the memory range. * * Adds a firmware mapping entry. This function is for memory hotplug, it is @@ -175,7 +175,7 @@ int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type) /** * firmware_map_add_early() - Adds a firmware mapping entry. * @start: Start of the memory range. - * @end: End of the memory range (inclusive). + * @end: End of the memory range. * @type: Type of the memory range. * * Adds a firmware mapping entry. This function uses the bootmem allocator -- GitLab From b34a26f3158cca932b6f1427b97fe12c7838ee68 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:41:16 -0700 Subject: [PATCH 4634/5711] checkpatch: Update alignment check Parenthesis alignment doesn't correctly check an existing line after an inserted or modified line with an open parenthesis. Fix it. Signed-off-by: Joe Perches Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e5bd60ff48e3..630319acb826 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1848,8 +1848,8 @@ sub process { my $pos = pos_last_openparen($rest); if ($pos >= 0) { - $line =~ /^\+([ \t]*)/; - my $newindent = $1; + $line =~ /^(\+| )([ \t]*)/; + my $newindent = $2; my $goodtabindent = $oldindent . "\t" x ($pos / 8) . -- GitLab From ce0338df3c9a43e709b8a478265b32b9edcc7ccc Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:41:18 -0700 Subject: [PATCH 4635/5711] checkpatch: test for non-standard signatures Warn on non-standard signature styles. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 630319acb826..3e04f80375de 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1600,13 +1600,17 @@ sub process { # Check signature styles if (!$in_header_lines && - $line =~ /^(\s*)($signature_tags)(\s*)(.*)/) { + $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { my $space_before = $1; my $sign_off = $2; my $space_after = $3; my $email = $4; my $ucfirst_sign_off = ucfirst(lc($sign_off)); + if ($sign_off !~ /$signature_tags/) { + WARN("BAD_SIGN_OFF", + "Non-standard signature: $sign_off\n" . $herecurr); + } if (defined $space_before && $space_before ne "") { WARN("BAD_SIGN_OFF", "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr); -- GitLab From 4a273195a551a27a9a3ebed072c8df16c853da7f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:41:20 -0700 Subject: [PATCH 4636/5711] checkpatch: check usleep_range() arguments usleep_range() shouldn't use the same args for min and max. Report it when it happens and when both args are decimal and min > max. Signed-off-by: Joe Perches Cc: Yuval Mintz Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3e04f80375de..4bad5700670a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3313,6 +3313,22 @@ sub process { } } +# check usleep_range arguments + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { + my $min = $1; + my $max = $7; + if ($min eq $max) { + WARN("USLEEP_RANGE", + "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && + $min > $max) { + WARN("USLEEP_RANGE", + "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } + } + # check for new externs in .c files. if ($realfile =~ /\.c$/ && defined $stat && $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) -- GitLab From 66c80b6077256898df948ac6acf547b47ddb1fcf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:41:22 -0700 Subject: [PATCH 4637/5711] checkpatch: Add acheck for use of sizeof without parenthesis Kernel style uses parenthesis around sizeof. Signed-off-by: Joe Perches Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 4bad5700670a..40b0627aeb5e 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3265,6 +3265,12 @@ sub process { "sizeof(& should be avoided\n" . $herecurr); } +# check for sizeof without parenthesis + if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { + WARN("SIZEOF_PARENTHESIS", + "sizeof $1 should be sizeof($1)\n" . $herecurr); + } + # check for line continuations in quoted strings with odd counts of " if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { WARN("LINE_CONTINUATIONS", -- GitLab From b13edf7ff2dd0fef95e981170fa71fa6b60421b0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jul 2012 14:41:24 -0700 Subject: [PATCH 4638/5711] checkpatch: add checks for do {} while (0) macro misuses These types of macros should not be used for either a single statement nor should the macro end with a semi-colon. Add tests for these conditions. Signed-off-by: Joe Perches Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 40b0627aeb5e..913d6bdfdda3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2988,6 +2988,45 @@ sub process { } } +# do {} while (0) macro tests: +# single-statement macros do not need to be enclosed in do while (0) loop, +# macro should not end with a semicolon + if ($^V && $^V ge 5.10.0 && + $realfile !~ m@/vmlinux.lds.h$@ && + $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { + my $ln = $linenr; + my $cnt = $realcnt; + my ($off, $dstat, $dcond, $rest); + my $ctx = ''; + ($dstat, $dcond, $ln, $cnt, $off) = + ctx_statement_block($linenr, $realcnt, 0); + $ctx = $dstat; + + $dstat =~ s/\\\n.//g; + + if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { + my $stmts = $2; + my $semis = $3; + + $ctx =~ s/\n*$//; + my $cnt = statement_rawlines($ctx); + my $herectx = $here . "\n"; + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + if (($stmts =~ tr/;/;/) == 1) { + WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", + "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); + } + if (defined $semis && $semis ne "") { + WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", + "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); + } + } + } + # make sure symbols are always wrapped with VMLINUX_SYMBOL() ... # all assignments may have only one of the following with an assignment: # . -- GitLab From 49ac572b93832210dc1895839692b3a51e5d0e27 Mon Sep 17 00:00:00 2001 From: Thiago Rafael Becker Date: Mon, 30 Jul 2012 14:41:26 -0700 Subject: [PATCH 4639/5711] lib/crc32.c: fix unused variables warnings Variables t4, t5, t6 and t7 are only used when CRC_LE_BITS != 32. Fix the following compilation warnings: lib/crc32.c: In function 'crc32_body': lib/crc32.c:77:55: warning: unused variable 't7' lib/crc32.c:77:41: warning: unused variable 't6' lib/crc32.c:77:27: warning: unused variable 't5' lib/crc32.c:77:13: warning: unused variable 't4' Signed-off-by: Thiago Rafael Becker Cc: "Darrick J. Wong" Cc: Bob Pearson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/crc32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/crc32.c b/lib/crc32.c index b0d278fb1d91..61774b8db4de 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -74,7 +74,9 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) size_t i; # endif const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3]; +# if CRC_LE_BITS != 32 const u32 *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7]; +# endif u32 q; /* Align it */ -- GitLab From 40251b8eb46e48c011939a3ddf056fe13a223319 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 30 Jul 2012 14:41:29 -0700 Subject: [PATCH 4640/5711] drivers/message/i2o/i2o_proc.c: the pointer returned from chtostr() points to an array which is no longer valid ... when being used in the calling function. Although it may work, the behavior is undefined. Detected by cppcheck. Signed-off-by: Kamil Dudka Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/i2o_proc.c | 37 ++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 506c36f6e1db..8001aa6bfb48 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -255,9 +255,8 @@ static char *scsi_devices[] = { "Array Controller Device" }; -static char *chtostr(u8 * chars, int n) +static char *chtostr(char *tmp, u8 *chars, int n) { - char tmp[256]; tmp[0] = 0; return strncat(tmp, (char *)chars, n); } @@ -791,6 +790,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) } *result; i2o_exec_execute_ddm_table ddm_table; + char tmp[28 + 1]; result = kmalloc(sizeof(*result), GFP_KERNEL); if (!result) @@ -826,7 +826,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); seq_printf(seq, "%-#8x", ddm_table.module_id); seq_printf(seq, "%-29s", - chtostr(ddm_table.module_name_version, 28)); + chtostr(tmp, ddm_table.module_name_version, 28)); seq_printf(seq, "%9d ", ddm_table.data_size); seq_printf(seq, "%8d", ddm_table.code_size); @@ -893,6 +893,7 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) i2o_driver_result_table *result; i2o_driver_store_table *dst; + char tmp[28 + 1]; result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); if (result == NULL) @@ -927,8 +928,9 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", dst->i2o_vendor_id); seq_printf(seq, "%-#8x", dst->module_id); - seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28)); - seq_printf(seq, "%-9s", chtostr(dst->date, 8)); + seq_printf(seq, "%-29s", + chtostr(tmp, dst->module_name_version, 28)); + seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); seq_printf(seq, "%8d ", dst->module_size); seq_printf(seq, "%8d ", dst->mpb_size); seq_printf(seq, "0x%04x", dst->module_flags); @@ -1248,6 +1250,7 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) // == (allow) 512d bytes (max) static u16 *work16 = (u16 *) work32; int token; + char tmp[16 + 1]; token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); @@ -1260,13 +1263,13 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); seq_printf(seq, "Vendor info : %s\n", - chtostr((u8 *) (work32 + 2), 16)); + chtostr(tmp, (u8 *) (work32 + 2), 16)); seq_printf(seq, "Product info : %s\n", - chtostr((u8 *) (work32 + 6), 16)); + chtostr(tmp, (u8 *) (work32 + 6), 16)); seq_printf(seq, "Description : %s\n", - chtostr((u8 *) (work32 + 10), 16)); + chtostr(tmp, (u8 *) (work32 + 10), 16)); seq_printf(seq, "Product rev. : %s\n", - chtostr((u8 *) (work32 + 14), 8)); + chtostr(tmp, (u8 *) (work32 + 14), 8)); seq_printf(seq, "Serial number : "); print_serial_number(seq, (u8 *) (work32 + 16), @@ -1303,6 +1306,8 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) u8 pad[256]; // allow up to 256 byte (max) serial number } result; + char tmp[24 + 1]; + token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); if (token < 0) { @@ -1312,9 +1317,9 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); seq_printf(seq, "Module name : %s\n", - chtostr(result.module_name, 24)); + chtostr(tmp, result.module_name, 24)); seq_printf(seq, "Module revision : %s\n", - chtostr(result.module_rev, 8)); + chtostr(tmp, result.module_rev, 8)); seq_printf(seq, "Serial number : "); print_serial_number(seq, result.serial_number, sizeof(result) - 36); @@ -1338,6 +1343,8 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) u8 instance_number[4]; } result; + char tmp[64 + 1]; + token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); if (token < 0) { @@ -1346,13 +1353,13 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) } seq_printf(seq, "Device name : %s\n", - chtostr(result.device_name, 64)); + chtostr(tmp, result.device_name, 64)); seq_printf(seq, "Service name : %s\n", - chtostr(result.service_name, 64)); + chtostr(tmp, result.service_name, 64)); seq_printf(seq, "Physical name : %s\n", - chtostr(result.physical_location, 64)); + chtostr(tmp, result.physical_location, 64)); seq_printf(seq, "Instance number : %s\n", - chtostr(result.instance_number, 4)); + chtostr(tmp, result.instance_number, 4)); return 0; } -- GitLab From 261eba73353edd48b0c0cb7aad59553dfc712ebc Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 30 Jul 2012 14:41:30 -0700 Subject: [PATCH 4641/5711] drivers/message/i2o/i2o_config.c: bound allocation Fix a case where users can try to allocate arbitarily large amounts of memory. 64K is overkill for a config request so apply an upper bound. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/i2o_config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 098de2b35784..9a49c243a6ac 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -188,6 +188,13 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) if (!dev) return -ENXIO; + /* + * Stop users being able to try and allocate arbitary amounts + * of DMA space. 64K is way more than sufficient for this. + */ + if (kcmd.oplen > 65536) + return -EMSGSIZE; + ops = memdup_user(kcmd.opbuf, kcmd.oplen); if (IS_ERR(ops)) return PTR_ERR(ops); -- GitLab From 8384dfeb759acac48ea24b81f134cac3cbb3e6fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:31 -0700 Subject: [PATCH 4642/5711] drivers/rtc/rtc-coh901331.c: use clk_prepare/unprepare Make sure we prepare/unprepare the clock for the COH901331 RTC driver as is required by the clk API especially if you use common clock. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-coh901331.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index a5b8a0c4ea84..58665029d6f3 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -157,6 +157,7 @@ static int __exit coh901331_remove(struct platform_device *pdev) if (rtap) { free_irq(rtap->irq, rtap); rtc_device_unregister(rtap->rtc); + clk_unprepare(rtap->clk); clk_put(rtap->clk); iounmap(rtap->virtbase); release_mem_region(rtap->phybase, rtap->physize); @@ -213,10 +214,10 @@ static int __init coh901331_probe(struct platform_device *pdev) } /* We enable/disable the clock only to assure it works */ - ret = clk_enable(rtap->clk); + ret = clk_prepare_enable(rtap->clk); if (ret) { dev_err(&pdev->dev, "could not enable clock\n"); - goto out_no_clk_enable; + goto out_no_clk_prepenable; } clk_disable(rtap->clk); @@ -232,7 +233,8 @@ static int __init coh901331_probe(struct platform_device *pdev) out_no_rtc: platform_set_drvdata(pdev, NULL); - out_no_clk_enable: + clk_unprepare(rtap->clk); + out_no_clk_prepenable: clk_put(rtap->clk); out_no_clk: free_irq(rtap->irq, rtap); @@ -265,6 +267,7 @@ static int coh901331_suspend(struct platform_device *pdev, pm_message_t state) writel(0, rtap->virtbase + COH901331_IRQ_MASK); clk_disable(rtap->clk); } + clk_unprepare(rtap->clk); return 0; } @@ -272,6 +275,7 @@ static int coh901331_resume(struct platform_device *pdev) { struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); + clk_prepare(rtap->clk); if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(rtap->irq); } else { @@ -293,6 +297,7 @@ static void coh901331_shutdown(struct platform_device *pdev) clk_enable(rtap->clk); writel(0, rtap->virtbase + COH901331_IRQ_MASK); clk_disable(rtap->clk); + clk_unprepare(rtap->clk); } static struct platform_driver coh901331_driver = { -- GitLab From 36ac1d24f1488c32b85a1718a4edfda615b2ef77 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:32 -0700 Subject: [PATCH 4643/5711] drivers/rtc/rtc-coh901331.c: use devm allocation Allocate memory, region, remap and irq for device state using devm_* helpers to simplify memory accounting. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-coh901331.c | 50 +++++++++++-------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 58665029d6f3..76b2156d3c62 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -155,14 +155,10 @@ static int __exit coh901331_remove(struct platform_device *pdev) struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); if (rtap) { - free_irq(rtap->irq, rtap); rtc_device_unregister(rtap->rtc); clk_unprepare(rtap->clk); clk_put(rtap->clk); - iounmap(rtap->virtbase); - release_mem_region(rtap->phybase, rtap->physize); platform_set_drvdata(pdev, NULL); - kfree(rtap); } return 0; @@ -175,42 +171,36 @@ static int __init coh901331_probe(struct platform_device *pdev) struct coh901331_port *rtap; struct resource *res; - rtap = kzalloc(sizeof(struct coh901331_port), GFP_KERNEL); + rtap = devm_kzalloc(&pdev->dev, + sizeof(struct coh901331_port), GFP_KERNEL); if (!rtap) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto out_no_resource; - } + if (!res) + return -ENOENT; + rtap->phybase = res->start; rtap->physize = resource_size(res); - if (request_mem_region(rtap->phybase, rtap->physize, - "rtc-coh901331") == NULL) { - ret = -EBUSY; - goto out_no_memregion; - } + if (devm_request_mem_region(&pdev->dev, rtap->phybase, rtap->physize, + "rtc-coh901331") == NULL) + return -EBUSY; - rtap->virtbase = ioremap(rtap->phybase, rtap->physize); - if (!rtap->virtbase) { - ret = -ENOMEM; - goto out_no_remap; - } + rtap->virtbase = devm_ioremap(&pdev->dev, rtap->phybase, rtap->physize); + if (!rtap->virtbase) + return -ENOMEM; rtap->irq = platform_get_irq(pdev, 0); - if (request_irq(rtap->irq, coh901331_interrupt, 0, - "RTC COH 901 331 Alarm", rtap)) { - ret = -EIO; - goto out_no_irq; - } + if (devm_request_irq(&pdev->dev, rtap->irq, coh901331_interrupt, 0, + "RTC COH 901 331 Alarm", rtap)) + return -EIO; rtap->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(rtap->clk)) { ret = PTR_ERR(rtap->clk); dev_err(&pdev->dev, "could not get clock\n"); - goto out_no_clk; + return ret; } /* We enable/disable the clock only to assure it works */ @@ -236,16 +226,6 @@ static int __init coh901331_probe(struct platform_device *pdev) clk_unprepare(rtap->clk); out_no_clk_prepenable: clk_put(rtap->clk); - out_no_clk: - free_irq(rtap->irq, rtap); - out_no_irq: - iounmap(rtap->virtbase); - out_no_remap: - platform_set_drvdata(pdev, NULL); - out_no_memregion: - release_mem_region(rtap->phybase, SZ_4K); - out_no_resource: - kfree(rtap); return ret; } -- GitLab From aff05ed5d103524bd69bd9d7b621c5c8a6c63198 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:34 -0700 Subject: [PATCH 4644/5711] rtc: pl031: encapsulate per-vendor ops Move the per-vendor operations for this RTC into a encapsulating struct so we can have more per-vendor variables than just the ops. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 61 ++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index cc0533994f6e..575fbbf966db 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -68,7 +68,16 @@ #define RTC_TIMER_FREQ 32768 +/** + * struct pl031_vendor_data - per-vendor variations + * @ops: the vendor-specific operations used on this silicon version + */ +struct pl031_vendor_data { + struct rtc_class_ops ops; +}; + struct pl031_local { + struct pl031_vendor_data *vendor; struct rtc_device *rtc; void __iomem *base; u8 hw_designer; @@ -303,7 +312,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) { int ret; struct pl031_local *ldata; - struct rtc_class_ops *ops = id->data; + struct pl031_vendor_data *vendor = id->data; + struct rtc_class_ops *ops = &vendor->ops; unsigned long time; ret = amba_request_regions(adev, NULL); @@ -315,6 +325,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) ret = -ENOMEM; goto out; } + ldata->vendor = vendor; ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); @@ -383,48 +394,54 @@ err_req: } /* Operations for the original ARM version */ -static struct rtc_class_ops arm_pl031_ops = { - .read_time = pl031_read_time, - .set_time = pl031_set_time, - .read_alarm = pl031_read_alarm, - .set_alarm = pl031_set_alarm, - .alarm_irq_enable = pl031_alarm_irq_enable, +static struct pl031_vendor_data arm_pl031 = { + .ops = { + .read_time = pl031_read_time, + .set_time = pl031_set_time, + .read_alarm = pl031_read_alarm, + .set_alarm = pl031_set_alarm, + .alarm_irq_enable = pl031_alarm_irq_enable, + }, }; /* The First ST derivative */ -static struct rtc_class_ops stv1_pl031_ops = { - .read_time = pl031_read_time, - .set_time = pl031_set_time, - .read_alarm = pl031_read_alarm, - .set_alarm = pl031_set_alarm, - .alarm_irq_enable = pl031_alarm_irq_enable, +static struct pl031_vendor_data stv1_pl031 = { + .ops = { + .read_time = pl031_read_time, + .set_time = pl031_set_time, + .read_alarm = pl031_read_alarm, + .set_alarm = pl031_set_alarm, + .alarm_irq_enable = pl031_alarm_irq_enable, + }, }; /* And the second ST derivative */ -static struct rtc_class_ops stv2_pl031_ops = { - .read_time = pl031_stv2_read_time, - .set_time = pl031_stv2_set_time, - .read_alarm = pl031_stv2_read_alarm, - .set_alarm = pl031_stv2_set_alarm, - .alarm_irq_enable = pl031_alarm_irq_enable, +static struct pl031_vendor_data stv2_pl031 = { + .ops = { + .read_time = pl031_stv2_read_time, + .set_time = pl031_stv2_set_time, + .read_alarm = pl031_stv2_read_alarm, + .set_alarm = pl031_stv2_set_alarm, + .alarm_irq_enable = pl031_alarm_irq_enable, + }, }; static struct amba_id pl031_ids[] = { { .id = 0x00041031, .mask = 0x000fffff, - .data = &arm_pl031_ops, + .data = &arm_pl031, }, /* ST Micro variants */ { .id = 0x00180031, .mask = 0x00ffffff, - .data = &stv1_pl031_ops, + .data = &stv1_pl031, }, { .id = 0x00280031, .mask = 0x00ffffff, - .data = &stv2_pl031_ops, + .data = &stv2_pl031, }, {0, 0}, }; -- GitLab From 1bb457fc9268bb75156af8db78b72a4463baaec4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:36 -0700 Subject: [PATCH 4645/5711] rtc: pl031: use per-vendor variables for special init Instead of hard-checking for certain vendor codes, follow the pattern of other AMBA (PrimeCell) drivers and use variables in the vendor data. Get rid of the locally cached vendor and hardware revision since we already have the nice vendor data variable in the state. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 575fbbf966db..e66afb816d61 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -71,17 +71,21 @@ /** * struct pl031_vendor_data - per-vendor variations * @ops: the vendor-specific operations used on this silicon version + * @clockwatch: if this is an ST Microelectronics silicon version with a + * clockwatch function + * @st_weekday: if this is an ST Microelectronics silicon version that need + * the weekday fix */ struct pl031_vendor_data { struct rtc_class_ops ops; + bool clockwatch; + bool st_weekday; }; struct pl031_local { struct pl031_vendor_data *vendor; struct rtc_device *rtc; void __iomem *base; - u8 hw_designer; - u8 hw_revision:4; }; static int pl031_alarm_irq_enable(struct device *dev, @@ -336,14 +340,11 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) amba_set_drvdata(adev, ldata); - ldata->hw_designer = amba_manf(adev); - ldata->hw_revision = amba_rev(adev); - - dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer); - dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); + dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev)); + dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev)); /* Enable the clockwatch on ST Variants */ - if (ldata->hw_designer == AMBA_VENDOR_ST) + if (vendor->clockwatch) writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, ldata->base + RTC_CR); @@ -351,7 +352,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) * On ST PL031 variants, the RTC reset value does not provide correct * weekday for 2000-01-01. Correct the erroneous sunday to saturday. */ - if (ldata->hw_designer == AMBA_VENDOR_ST) { + if (vendor->st_weekday) { if (readl(ldata->base + RTC_YDR) == 0x2000) { time = readl(ldata->base + RTC_DR); if ((time & @@ -413,6 +414,8 @@ static struct pl031_vendor_data stv1_pl031 = { .set_alarm = pl031_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .clockwatch = true, + .st_weekday = true, }; /* And the second ST derivative */ @@ -424,6 +427,8 @@ static struct pl031_vendor_data stv2_pl031 = { .set_alarm = pl031_stv2_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .clockwatch = true, + .st_weekday = true, }; static struct amba_id pl031_ids[] = { -- GitLab From 559a6fc0508392a665a26d93db9ff875bfdc6540 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Mon, 30 Jul 2012 14:41:39 -0700 Subject: [PATCH 4646/5711] rtc: pl031: fix up IRQ flags The pl031 interrupt is shared between the timer part and the clockwatch part of the same HW block on the ux500, so mark it IRQF_SHARED on this variant. This patch also adds the IRQF_NO_SUSPEND flag to the rtc irq on all variants as we don't want this pretty important IRQ to be disabled in suspend. Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij Reviewed-by: Rickard Andersson Reviewed-by: Jonas Aberg Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index e66afb816d61..08378e3cc21c 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -75,11 +75,13 @@ * clockwatch function * @st_weekday: if this is an ST Microelectronics silicon version that need * the weekday fix + * @irqflags: special IRQ flags per variant */ struct pl031_vendor_data { struct rtc_class_ops ops; bool clockwatch; bool st_weekday; + unsigned long irqflags; }; struct pl031_local { @@ -373,7 +375,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } if (request_irq(adev->irq[0], pl031_interrupt, - 0, "rtc-pl031", ldata)) { + vendor->irqflags, "rtc-pl031", ldata)) { ret = -EIO; goto out_no_irq; } @@ -403,6 +405,7 @@ static struct pl031_vendor_data arm_pl031 = { .set_alarm = pl031_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .irqflags = IRQF_NO_SUSPEND, }; /* The First ST derivative */ @@ -416,6 +419,7 @@ static struct pl031_vendor_data stv1_pl031 = { }, .clockwatch = true, .st_weekday = true, + .irqflags = IRQF_NO_SUSPEND, }; /* And the second ST derivative */ @@ -429,6 +433,11 @@ static struct pl031_vendor_data stv2_pl031 = { }, .clockwatch = true, .st_weekday = true, + /* + * This variant shares the IRQ with another block and must not + * suspend that IRQ line. + */ + .irqflags = IRQF_SHARED | IRQF_NO_SUSPEND, }; static struct amba_id pl031_ids[] = { -- GitLab From dc43d4a26b808240410ce3ea1c72a8047f90d1d8 Mon Sep 17 00:00:00 2001 From: Ramesh Chandrasekaran Date: Mon, 30 Jul 2012 14:41:41 -0700 Subject: [PATCH 4647/5711] drivers/rtc/rtc-ab8500.c: use UIE emulation RTC: Fix to correct improper implementation of clock update irq (RTC_UIE) and enable UIE Emulation. [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Ramesh Chandrasekaran Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-ab8500.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 08cbdb900a18..668da5922d9e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -694,6 +694,7 @@ config RTC_DRV_AB3100 config RTC_DRV_AB8500 tristate "ST-Ericsson AB8500 RTC" depends on AB8500_CORE + select RTC_INTF_DEV_UIE_EMUL help Select this to enable the ST-Ericsson AB8500 power management IC RTC support. This chip contains a battery- and capacitor-backed RTC. diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 370889d0489b..1a57e03e169d 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -225,7 +225,8 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { int retval, i; unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; - unsigned long mins, secs = 0; + unsigned long mins, secs = 0, cursec = 0; + struct rtc_time curtm; if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { dev_dbg(dev, "year should be equal to or greater than %d\n", @@ -236,6 +237,18 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) /* Get the number of seconds since 1970 */ rtc_tm_to_time(&alarm->time, &secs); + /* + * Check whether alarm is set less than 1min. + * Since our RTC doesn't support alarm resolution less than 1min, + * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON + */ + ab8500_rtc_read_time(dev, &curtm); /* Read current time */ + rtc_tm_to_time(&curtm, &cursec); + if ((secs - cursec) < 59) { + dev_dbg(dev, "Alarm less than 1 minute not supported\r\n"); + return -EINVAL; + } + /* * Convert it to the number of seconds since 01-01-2000 00:00:00, since * we only have a small counter in the RTC. -- GitLab From 064407f1c0d54ad215927b4c14b3f4e68fa486f4 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Mon, 30 Jul 2012 14:41:43 -0700 Subject: [PATCH 4648/5711] drivers/rtc/rtc-ab8500.c: remove fix for AB8500 ED version AB8500 ED (Early Drop) is no longer supported by the kernel. Signed-off-by: Bengt Jonsson Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ab8500.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 1a57e03e169d..bf3c2f669c3c 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -89,22 +89,17 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) if (retval < 0) return retval; - /* Early AB8500 chips will not clear the rtc read request bit */ - if (abx500_get_chip_id(dev) == 0) { - usleep_range(1000, 1000); - } else { - /* Wait for some cycles after enabling the rtc read in ab8500 */ - while (time_before(jiffies, timeout)) { - retval = abx500_get_register_interruptible(dev, - AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); - if (retval < 0) - return retval; - - if (!(value & RTC_READ_REQUEST)) - break; - - usleep_range(1000, 5000); - } + /* Wait for some cycles after enabling the rtc read in ab8500 */ + while (time_before(jiffies, timeout)) { + retval = abx500_get_register_interruptible(dev, + AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); + if (retval < 0) + return retval; + + if (!(value & RTC_READ_REQUEST)) + break; + + usleep_range(1000, 5000); } /* Read the Watchtime registers */ -- GitLab From aa11ec593e2c68d57728d2ebb2da265468e410c9 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Mon, 30 Jul 2012 14:41:45 -0700 Subject: [PATCH 4649/5711] drivers/rtc/rtc-r9701.c: avoid second call to rtc_valid_tm() r9701_get_datetime() calls rtc_valid_tm() and returns the value returned by rtc_valid_tm(), which can be used in the `if', so calling rtc_valid_tm() a second time is not required. Signed-off-by: Devendra Naga Cc: Alessandro Zummo Cc: Anatolij Gustschin Cc: Andreas Dumberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-r9701.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 33b6ba0afa0d..e6c34c024706 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -138,8 +138,7 @@ static int __devinit r9701_probe(struct spi_device *spi) * contain invalid values. If so, try to write a default date: * 2000/1/1 00:00:00 */ - r9701_get_datetime(&spi->dev, &dt); - if (rtc_valid_tm(&dt)) { + if (r9701_get_datetime(&spi->dev, &dt)) { dev_info(&spi->dev, "trying to repair invalid date/time\n"); dt.tm_sec = 0; dt.tm_min = 0; -- GitLab From 8e74b6edc9b7befd9f7a61b9271384eeb1eb8251 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:41:47 -0700 Subject: [PATCH 4650/5711] drivers/rtc/rtc-r9701.c: check that r9701_set_datetime() succeeded When the driver detects that the clock time is invalid, it attempts to write a sane time into the hardware. We curently assume that everything is OK if those writes succeeded. But it is better to re-read the time from the hardware to ensure that the new settings got there OK. Cc: Devendra Naga Cc: Alessandro Zummo Cc: Anatolij Gustschin Cc: Andreas Dumberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-r9701.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index e6c34c024706..2c183ebff715 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -147,7 +147,8 @@ static int __devinit r9701_probe(struct spi_device *spi) dt.tm_mon = 0; dt.tm_year = 100; - if (r9701_set_datetime(&spi->dev, &dt)) { + if (r9701_set_datetime(&spi->dev, &dt) || + r9701_get_datetime(&spi->dev, &dt)) { dev_err(&spi->dev, "cannot repair RTC register\n"); return -ENODEV; } -- GitLab From dbd9acbef2f178e74c2f2def23eb4e8c2bd14270 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 30 Jul 2012 14:41:48 -0700 Subject: [PATCH 4651/5711] drivers/rtc/rtc-s3c.c: replace #include header files from asm/* to linux/* Fixes the following checkpatch warnings: WARNING: Use #include instead of WARNING: Use #include instead of Signed-off-by: Sachin Kamat Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 7e6af0b22f17..bfbd92c8d1c9 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -26,10 +26,10 @@ #include #include #include +#include +#include #include -#include -#include #include #include -- GitLab From 0f636fc16f80fe64261ce39440e49a259ff2b0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 30 Jul 2012 14:41:50 -0700 Subject: [PATCH 4652/5711] rtc/mc13xxx: use MODULE_DEVICE_TABLE instead of MODULE_ALIAS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows automatic driver loading for all supported device types. Signed-off-by: Uwe Kleine-König Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-mc13xxx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 546f6850bffb..0ce060280e6b 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -405,8 +405,9 @@ static const struct platform_device_id mc13xxx_rtc_idtable[] = { }, { .name = "mc13892-rtc", }, - { } + { /* sentinel */ } }; +MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable); static struct platform_driver mc13xxx_rtc_driver = { .id_table = mc13xxx_rtc_idtable, @@ -432,4 +433,3 @@ module_exit(mc13xxx_rtc_exit); MODULE_AUTHOR("Sascha Hauer "); MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRIVER_NAME); -- GitLab From 19a1ac505d5f3545ebc5b0a195d65cef4da94bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 30 Jul 2012 14:41:52 -0700 Subject: [PATCH 4653/5711] rtc/mc13xxx: add support for the rtc in the mc34708 pmic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-mc13xxx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 0ce060280e6b..2643d8874925 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -404,6 +404,8 @@ static const struct platform_device_id mc13xxx_rtc_idtable[] = { .name = "mc13783-rtc", }, { .name = "mc13892-rtc", + }, { + .name = "mc34708-rtc", }, { /* sentinel */ } }; -- GitLab From 007def046711479f3d19bec4016b65fd73deed6c Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Mon, 30 Jul 2012 14:41:54 -0700 Subject: [PATCH 4654/5711] rtc/rtc-da9052: remove unneed devm_kfree call Freeing will trigger when driver unloads, so using devm_kfree() is not needed. Signed-off-by: Devendra Naga Cc: Alessandro Zummo Cc: Ashish Jangam Cc: David Dajun Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-da9052.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index da6ab5291a41..78070255bd3f 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -245,7 +245,7 @@ static int __devinit da9052_rtc_probe(struct platform_device *pdev) "ALM", rtc); if (ret != 0) { rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); - goto err_mem; + return ret; } rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, @@ -259,8 +259,6 @@ static int __devinit da9052_rtc_probe(struct platform_device *pdev) err_free_irq: free_irq(rtc->irq, rtc); -err_mem: - devm_kfree(&pdev->dev, rtc); return ret; } @@ -271,7 +269,6 @@ static int __devexit da9052_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc->rtc); free_irq(rtc->irq, rtc); platform_set_drvdata(pdev, NULL); - devm_kfree(&pdev->dev, rtc); return 0; } -- GitLab From 0a25bf40d8ea9aeb8412666a7bc8ab95b4cddcb1 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Mon, 30 Jul 2012 14:41:57 -0700 Subject: [PATCH 4655/5711] drivers/rtc/rtc-pcf8563.c: set owner field in driver struct The owner member is supposed to be set to the module implementing the device driver, i.e., THIS_MODULE. This enables the appropriate module link in sysfs. Signed-off-by: Nick Bowler Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8563.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 97a3284bb7c6..24a9d6a9c72d 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -288,6 +288,7 @@ MODULE_DEVICE_TABLE(i2c, pcf8563_id); static struct i2c_driver pcf8563_driver = { .driver = { .name = "rtc-pcf8563", + .owner = THIS_MODULE, }, .probe = pcf8563_probe, .remove = pcf8563_remove, -- GitLab From 8dccaf0607b3e047680952d0baf4da0486fbbcc1 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Mon, 30 Jul 2012 14:41:59 -0700 Subject: [PATCH 4656/5711] drivers/rtc/rtc-pcf8563.c: add device tree support Set the of_match_table for this driver so that devices can be described in the device tree. Signed-off-by: Nick Bowler Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8563.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 24a9d6a9c72d..c2fe426a6ef2 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -19,6 +19,7 @@ #include #include #include +#include #define DRV_VERSION "0.4.3" @@ -285,10 +286,19 @@ static const struct i2c_device_id pcf8563_id[] = { }; MODULE_DEVICE_TABLE(i2c, pcf8563_id); +#ifdef CONFIG_OF +static const struct of_device_id pcf8563_of_match[] __devinitconst = { + { .compatible = "nxp,pcf8563" }, + {} +}; +MODULE_DEVICE_TABLE(of, pcf8563_of_match); +#endif + static struct i2c_driver pcf8563_driver = { .driver = { .name = "rtc-pcf8563", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pcf8563_of_match), }, .probe = pcf8563_probe, .remove = pcf8563_remove, -- GitLab From 6ed6a722f9abac25b0549e7507a2b745ede4475c Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 30 Jul 2012 14:42:00 -0700 Subject: [PATCH 4657/5711] minixfs: fix block limit check On minix2 and minix3 usually max_size is 7fffffff and the check in question prohibits creation of last block spanning right before 7fffffff, due to downward rounding during the division. Fix it by using multiplication instead. [akpm@linux-foundation.org: fix up code layout, use local `sb'] Signed-off-by: Vladimir Serbinenko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/minix/itree_v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c index 13487ad16894..78e2d93e5c83 100644 --- a/fs/minix/itree_v2.c +++ b/fs/minix/itree_v2.c @@ -32,7 +32,8 @@ static int block_to_path(struct inode * inode, long block, int offsets[DEPTH]) if (block < 0) { printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n", block, bdevname(sb->s_bdev, b)); - } else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) { + } else if ((u64)block * (u64)sb->s_blocksize >= + minix_sb(sb)->s_max_size) { if (printk_ratelimit()) printk("MINIX-fs: block_to_path: " "block %ld too big on dev %s\n", -- GitLab From 6b0f3393e38584ec22bab62fe01df58ae5a73ee7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Mon, 30 Jul 2012 14:42:02 -0700 Subject: [PATCH 4658/5711] nilfs2: add omitted comment for ns_mount_state field of the_nilfs structure Add omitted comment for ns_mount_state field of the_nilfs structure. Signed-off-by: Vyacheslav Dubeyko Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/the_nilfs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 9992b11312ff..ef40a510e2f3 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -52,6 +52,7 @@ enum { * @ns_sbwtime: previous write time of super block * @ns_sbwcount: write count of super block * @ns_sbsize: size of valid data in super block + * @ns_mount_state: file system state * @ns_seg_seq: segment sequence counter * @ns_segnum: index number of the latest full segment. * @ns_nextnum: index number of the full segment index to be used next -- GitLab From 278038ac53c6c4f53d1d34f978beb9aba1410b2c Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Mon, 30 Jul 2012 14:42:03 -0700 Subject: [PATCH 4659/5711] nilfs2: remove references to long gone super operations ->delete_inode(), ->write_super_lockfs(), ->unlockfs() are gone so remove references to them in the NTFS code. Noticed while cleaning up the fsfreeze mess. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/super.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index d57c42f974ea..a76d6ea51ffb 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -677,7 +677,6 @@ static const struct super_operations nilfs_sops = { .destroy_inode = nilfs_destroy_inode, .dirty_inode = nilfs_dirty_inode, /* .write_inode = nilfs_write_inode, */ - /* .put_inode = nilfs_put_inode, */ /* .drop_inode = nilfs_drop_inode, */ .evict_inode = nilfs_evict_inode, .put_super = nilfs_put_super, @@ -685,8 +684,6 @@ static const struct super_operations nilfs_sops = { .sync_fs = nilfs_sync_fs, .freeze_fs = nilfs_freeze, .unfreeze_fs = nilfs_unfreeze, - /* .write_super_lockfs */ - /* .unlockfs */ .statfs = nilfs_statfs, .remount_fs = nilfs_remount, /* .umount_begin */ -- GitLab From fe0627e7b3d32a41c16fac6e0af091991545865e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 30 Jul 2012 14:42:05 -0700 Subject: [PATCH 4660/5711] nilfs2: fix timing issue between rmcp and chcp ioctls The checkpoint deletion ioctl (rmcp ioctl) has potential for breaking snapshot because it is not fully exclusive with checkpoint mode change ioctl (chcp ioctl). The rmcp ioctl first tests if the specified checkpoint is a snapshot or not within nilfs_cpfile_delete_checkpoint function, and then calls nilfs_cpfile_delete_checkpoints function to actually invalidate the checkpoint only if it's not a snapshot. However, the checkpoint can be changed into a snapshot by the chcp ioctl between these two operations. In that case, calling nilfs_cpfile_delete_checkpoints() wrongly invalidates the snapshot, which leads to snapshot list corruption and snapshot count mismatch. This fixes the issue by changing nilfs_cpfile_delete_checkpoints() so that it reconfirms the target checkpoints are snapshot or not. This second check is exclusive with the chcp operation since it is protected by an existing semaphore. Signed-off-by: Ryusuke Konishi Cc: Fernando Luis Vazquez Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/cpfile.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index dab5c4c6dfaf..deaa3d33a0aa 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -286,7 +286,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, __u64 cno; void *kaddr; unsigned long tnicps; - int ret, ncps, nicps, count, i; + int ret, ncps, nicps, nss, count, i; if (unlikely(start == 0 || start > end)) { printk(KERN_ERR "%s: invalid range of checkpoint numbers: " @@ -301,6 +301,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, if (ret < 0) goto out_sem; tnicps = 0; + nss = 0; for (cno = start; cno < end; cno += ncps) { ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, end); @@ -318,8 +319,9 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, cpfile, cno, cp_bh, kaddr); nicps = 0; for (i = 0; i < ncps; i++, cp = (void *)cp + cpsz) { - WARN_ON(nilfs_checkpoint_snapshot(cp)); - if (!nilfs_checkpoint_invalid(cp)) { + if (nilfs_checkpoint_snapshot(cp)) { + nss++; + } else if (!nilfs_checkpoint_invalid(cp)) { nilfs_checkpoint_set_invalid(cp); nicps++; } @@ -364,6 +366,8 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, } brelse(header_bh); + if (nss > 0) + ret = -EBUSY; out_sem: up_write(&NILFS_MDT(cpfile)->mi_sem); -- GitLab From 572d8b3945a31bee7c40d21556803e4807fd9141 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 30 Jul 2012 14:42:07 -0700 Subject: [PATCH 4661/5711] nilfs2: fix deadlock issue between chcp and thaw ioctls An fs-thaw ioctl causes deadlock with a chcp or mkcp -s command: chcp D ffff88013870f3d0 0 1325 1324 0x00000004 ... Call Trace: nilfs_transaction_begin+0x11c/0x1a0 [nilfs2] wake_up_bit+0x20/0x20 copy_from_user+0x18/0x30 [nilfs2] nilfs_ioctl_change_cpmode+0x7d/0xcf [nilfs2] nilfs_ioctl+0x252/0x61a [nilfs2] do_page_fault+0x311/0x34c get_unmapped_area+0x132/0x14e do_vfs_ioctl+0x44b/0x490 __set_task_blocked+0x5a/0x61 vm_mmap_pgoff+0x76/0x87 __set_current_blocked+0x30/0x4a sys_ioctl+0x4b/0x6f system_call_fastpath+0x16/0x1b thaw D ffff88013870d890 0 1352 1351 0x00000004 ... Call Trace: rwsem_down_failed_common+0xdb/0x10f call_rwsem_down_write_failed+0x13/0x20 down_write+0x25/0x27 thaw_super+0x13/0x9e do_vfs_ioctl+0x1f5/0x490 vm_mmap_pgoff+0x76/0x87 sys_ioctl+0x4b/0x6f filp_close+0x64/0x6c system_call_fastpath+0x16/0x1b where the thaw ioctl deadlocked at thaw_super() when called while chcp was waiting at nilfs_transaction_begin() called from nilfs_ioctl_change_cpmode(). This deadlock is 100% reproducible. This is because nilfs_ioctl_change_cpmode() first locks sb->s_umount in read mode and then waits for unfreezing in nilfs_transaction_begin(), whereas thaw_super() locks sb->s_umount in write mode. The locking of sb->s_umount here was intended to make snapshot mounts and the downgrade of snapshots to checkpoints exclusive. This fixes the deadlock issue by replacing the sb->s_umount usage in nilfs_ioctl_change_cpmode() with a dedicated mutex which protects snapshot mounts. Signed-off-by: Ryusuke Konishi Cc: Fernando Luis Vazquez Cao Tested-by: Ryusuke Konishi Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/ioctl.c | 4 ++-- fs/nilfs2/super.c | 3 +++ fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 06658caa18bd..0b6387c67e6c 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -182,7 +182,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, if (copy_from_user(&cpmode, argp, sizeof(cpmode))) goto out; - down_read(&inode->i_sb->s_umount); + mutex_lock(&nilfs->ns_snapshot_mount_mutex); nilfs_transaction_begin(inode->i_sb, &ti, 0); ret = nilfs_cpfile_change_cpmode( @@ -192,7 +192,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, else nilfs_transaction_commit(inode->i_sb); /* never fails */ - up_read(&inode->i_sb->s_umount); + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); out: mnt_drop_write_file(filp); return ret; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a76d6ea51ffb..6522cac6057c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -945,6 +945,8 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, struct nilfs_root *root; int ret; + mutex_lock(&nilfs->ns_snapshot_mount_mutex); + down_read(&nilfs->ns_segctor_sem); ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno); up_read(&nilfs->ns_segctor_sem); @@ -969,6 +971,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, ret = nilfs_get_root_dentry(s, root, root_dentry); nilfs_put_root(root); out: + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); return ret; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 501b7f8b739f..41e6a04a561f 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_bdev = bdev; atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); + mutex_init(&nilfs->ns_snapshot_mount_mutex); INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); spin_lock_init(&nilfs->ns_inode_lock); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index ef40a510e2f3..2558f320b821 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -47,6 +47,7 @@ enum { * @ns_flags: flags * @ns_bdev: block device * @ns_sem: semaphore for shared states + * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts * @ns_sbh: buffer heads of on-disk super blocks * @ns_sbp: pointers to super block data * @ns_sbwtime: previous write time of super block @@ -100,6 +101,7 @@ struct the_nilfs { struct block_device *ns_bdev; struct rw_semaphore ns_sem; + struct mutex ns_snapshot_mount_mutex; /* * used for -- GitLab From 8c74ac0557b4cabc9017c2740c5f62b330192416 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Mon, 30 Jul 2012 14:42:09 -0700 Subject: [PATCH 4662/5711] nilfs2: add omitted comments for structures in nilfs2_fs.h Add omitted comments for structures in nilfs2_fs.h. Signed-off-by: Vyacheslav Dubeyko Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/nilfs2_fs.h | 63 ++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 89bd4a4dcfb4..98755767c7b0 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -293,7 +293,7 @@ struct nilfs_dir_entry { __le64 inode; /* Inode number */ __le16 rec_len; /* Directory entry length */ __u8 name_len; /* Name length */ - __u8 file_type; + __u8 file_type; /* Dir entry type (file, dir, etc) */ char name[NILFS_NAME_LEN]; /* File name */ char pad; }; @@ -395,7 +395,7 @@ union nilfs_binfo { }; /** - * struct nilfs_segment_summary - segment summary + * struct nilfs_segment_summary - segment summary header * @ss_datasum: checksum of data * @ss_sumsum: checksum of segment summary * @ss_magic: magic number @@ -683,9 +683,9 @@ struct nilfs_sufile_header { /** * nilfs_suinfo - segment usage information - * @sui_lastmod: - * @sui_nblocks: - * @sui_flags: + * @sui_lastmod: timestamp of last modification + * @sui_nblocks: number of written blocks in segment + * @sui_flags: segment usage flags */ struct nilfs_suinfo { __u64 sui_lastmod; @@ -716,9 +716,10 @@ enum { }; /** - * struct nilfs_cpmode - - * @cc_cno: - * @cc_mode: + * struct nilfs_cpmode - change checkpoint mode structure + * @cm_cno: checkpoint number + * @cm_mode: mode of checkpoint + * @cm_pad: padding */ struct nilfs_cpmode { __u64 cm_cno; @@ -728,11 +729,11 @@ struct nilfs_cpmode { /** * struct nilfs_argv - argument vector - * @v_base: - * @v_nmembs: - * @v_size: - * @v_flags: - * @v_index: + * @v_base: pointer on data array from userspace + * @v_nmembs: number of members in data array + * @v_size: size of data array in bytes + * @v_flags: flags + * @v_index: start number of target data items */ struct nilfs_argv { __u64 v_base; @@ -743,9 +744,9 @@ struct nilfs_argv { }; /** - * struct nilfs_period - - * @p_start: - * @p_end: + * struct nilfs_period - period of checkpoint numbers + * @p_start: start checkpoint number (inclusive) + * @p_end: end checkpoint number (exclusive) */ struct nilfs_period { __u64 p_start; @@ -753,7 +754,7 @@ struct nilfs_period { }; /** - * struct nilfs_cpstat - + * struct nilfs_cpstat - checkpoint statistics * @cs_cno: checkpoint number * @cs_ncps: number of checkpoints * @cs_nsss: number of snapshots @@ -765,7 +766,7 @@ struct nilfs_cpstat { }; /** - * struct nilfs_sustat - + * struct nilfs_sustat - segment usage statistics * @ss_nsegs: number of segments * @ss_ncleansegs: number of clean segments * @ss_ndirtysegs: number of dirty segments @@ -784,10 +785,10 @@ struct nilfs_sustat { /** * struct nilfs_vinfo - virtual block number information - * @vi_vblocknr: - * @vi_start: - * @vi_end: - * @vi_blocknr: + * @vi_vblocknr: virtual block number + * @vi_start: start checkpoint number (inclusive) + * @vi_end: end checkpoint number (exclusive) + * @vi_blocknr: disk block number */ struct nilfs_vinfo { __u64 vi_vblocknr; @@ -797,7 +798,15 @@ struct nilfs_vinfo { }; /** - * struct nilfs_vdesc - + * struct nilfs_vdesc - descriptor of virtual block number + * @vd_ino: inode number + * @vd_cno: checkpoint number + * @vd_vblocknr: virtual block number + * @vd_period: period of checkpoint numbers + * @vd_blocknr: disk block number + * @vd_offset: logical block offset inside a file + * @vd_flags: flags (data or node block) + * @vd_pad: padding */ struct nilfs_vdesc { __u64 vd_ino; @@ -811,7 +820,13 @@ struct nilfs_vdesc { }; /** - * struct nilfs_bdesc - + * struct nilfs_bdesc - descriptor of disk block number + * @bd_ino: inode number + * @bd_oblocknr: disk block address (for skipping dead blocks) + * @bd_blocknr: disk block address + * @bd_offset: logical block offset inside a file + * @bd_level: level in the b-tree organization + * @bd_pad: padding */ struct nilfs_bdesc { __u64 bd_ino; -- GitLab From f5974c8f8cf431baf44e7127b669e3b1960f184f Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Mon, 30 Jul 2012 14:42:10 -0700 Subject: [PATCH 4663/5711] nilfs2: add omitted comments for different structures in driver implementation Add omitted comments for different structures in driver implementation. Signed-off-by: Vyacheslav Dubeyko Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/alloc.h | 14 +++++++++++--- fs/nilfs2/bmap.h | 7 +++++++ fs/nilfs2/btnode.h | 8 +++++++- fs/nilfs2/dat.c | 6 ++++++ fs/nilfs2/export.h | 8 ++++++++ fs/nilfs2/ifile.c | 6 +++++- fs/nilfs2/inode.c | 7 +++++++ fs/nilfs2/mdt.h | 7 +++++++ fs/nilfs2/nilfs.h | 17 +++++++++++++++-- fs/nilfs2/sufile.c | 8 +++++++- fs/nilfs2/the_nilfs.h | 3 +-- 11 files changed, 81 insertions(+), 10 deletions(-) diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h index f5fde36b9e28..fb7238100548 100644 --- a/fs/nilfs2/alloc.h +++ b/fs/nilfs2/alloc.h @@ -76,15 +76,23 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t); #define nilfs_clear_bit_atomic ext2_clear_bit_atomic #define nilfs_find_next_zero_bit find_next_zero_bit_le -/* - * persistent object allocator cache +/** + * struct nilfs_bh_assoc - block offset and buffer head association + * @blkoff: block offset + * @bh: buffer head */ - struct nilfs_bh_assoc { unsigned long blkoff; struct buffer_head *bh; }; +/** + * struct nilfs_palloc_cache - persistent object allocator cache + * @lock: cache protecting lock + * @prev_desc: blockgroup descriptors cache + * @prev_bitmap: blockgroup bitmap cache + * @prev_entry: translation entries cache + */ struct nilfs_palloc_cache { spinlock_t lock; struct nilfs_bh_assoc prev_desc; diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 40d9f453d31c..b89e68076adc 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -135,6 +135,13 @@ struct nilfs_bmap { /* state */ #define NILFS_BMAP_DIRTY 0x00000001 +/** + * struct nilfs_bmap_store - shadow copy of bmap state + * @data: cached raw block mapping of on-disk inode + * @last_allocated_key: cached value of last allocated key for data block + * @last_allocated_ptr: cached value of last allocated ptr for data block + * @state: cached value of state field of bmap structure + */ struct nilfs_bmap_store { __le64 data[NILFS_BMAP_SIZE / sizeof(__le64)]; __u64 last_allocated_key; diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 3a4dd2d8d3fc..d876b565ce64 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h @@ -29,7 +29,13 @@ #include #include - +/** + * struct nilfs_btnode_chkey_ctxt - change key context + * @oldkey: old key of block's moving content + * @newkey: new key for block's content + * @bh: buffer head of old buffer + * @newbh: buffer head of new buffer + */ struct nilfs_btnode_chkey_ctxt { __u64 oldkey; __u64 newkey; diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index b5c13f3576b9..fa0f80308c2d 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -33,6 +33,12 @@ #define NILFS_CNO_MIN ((__u64)1) #define NILFS_CNO_MAX (~(__u64)0) +/** + * struct nilfs_dat_info - on-memory private data of DAT file + * @mi: on-memory private data of metadata file + * @palloc_cache: persistent object allocator cache of DAT file + * @shadow: shadow map of DAT file + */ struct nilfs_dat_info { struct nilfs_mdt_info mi; struct nilfs_palloc_cache palloc_cache; diff --git a/fs/nilfs2/export.h b/fs/nilfs2/export.h index a71cc412b651..19ccbf9522ab 100644 --- a/fs/nilfs2/export.h +++ b/fs/nilfs2/export.h @@ -5,6 +5,14 @@ extern const struct export_operations nilfs_export_ops; +/** + * struct nilfs_fid - NILFS file id type + * @cno: checkpoint number + * @ino: inode number + * @gen: file generation (version) for NFS + * @parent_gen: parent generation (version) for NFS + * @parent_ino: parent inode number + */ struct nilfs_fid { u64 cno; u64 ino; diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c index 5a48df79d674..d8e65bde083c 100644 --- a/fs/nilfs2/ifile.c +++ b/fs/nilfs2/ifile.c @@ -29,7 +29,11 @@ #include "alloc.h" #include "ifile.h" - +/** + * struct nilfs_ifile_info - on-memory private data of ifile + * @mi: on-memory private data of metadata file + * @palloc_cache: persistent object allocator cache of ifile + */ struct nilfs_ifile_info { struct nilfs_mdt_info mi; struct nilfs_palloc_cache palloc_cache; diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 7cc64465ec26..6e2c3db976b2 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -34,6 +34,13 @@ #include "cpfile.h" #include "ifile.h" +/** + * struct nilfs_iget_args - arguments used during comparison between inodes + * @ino: inode number + * @cno: checkpoint number + * @root: pointer on NILFS root object (mounted checkpoint) + * @for_gc: inode for GC flag + */ struct nilfs_iget_args { u64 ino; __u64 cno; diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index ab20a4baa50f..ab172e8549c5 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -28,6 +28,13 @@ #include "nilfs.h" #include "page.h" +/** + * struct nilfs_shadow_map - shadow mapping of meta data file + * @bmap_store: shadow copy of bmap state + * @frozen_data: shadowed dirty data pages + * @frozen_btnodes: shadowed dirty b-tree nodes' pages + * @frozen_buffers: list of frozen buffers + */ struct nilfs_shadow_map { struct nilfs_bmap_store bmap_store; struct address_space frozen_data; diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 250add84da76..74cece80e9a3 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -32,8 +32,21 @@ #include "the_nilfs.h" #include "bmap.h" -/* - * nilfs inode data in memory +/** + * struct nilfs_inode_info - nilfs inode data in memory + * @i_flags: inode flags + * @i_state: dynamic state flags + * @i_bmap: pointer on i_bmap_data + * @i_bmap_data: raw block mapping + * @i_xattr: + * @i_dir_start_lookup: page index of last successful search + * @i_cno: checkpoint number for GC inode + * @i_btnode_cache: cached pages of b-tree nodes + * @i_dirty: list for connecting dirty files + * @xattr_sem: semaphore for extended attributes processing + * @i_bh: buffer contains disk inode + * @i_root: root object of the current filesystem tree + * @vfs_inode: VFS inode object */ struct nilfs_inode_info { __u32 i_flags; diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index c5b7653a4391..3127e9f438a7 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c @@ -30,7 +30,13 @@ #include "mdt.h" #include "sufile.h" - +/** + * struct nilfs_sufile_info - on-memory private data of sufile + * @mi: on-memory private data of metadata file + * @ncleansegs: number of clean segments + * @allocmin: lower limit of allocatable segment range + * @allocmax: upper limit of allocatable segment range + */ struct nilfs_sufile_info { struct nilfs_mdt_info mi; unsigned long ncleansegs;/* number of clean segments */ diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 2558f320b821..6eee4177807b 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -232,9 +232,8 @@ THE_NILFS_FNS(SB_DIRTY, sb_dirty) * @count: refcount of this structure * @nilfs: nilfs object * @ifile: inode file - * @root: root inode * @inodes_count: number of inodes - * @blocks_count: number of blocks (Reserved) + * @blocks_count: number of blocks */ struct nilfs_root { __u64 cno; -- GitLab From 497d48bd27ec1c44b4600e8e98a776188f2e11f2 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 30 Jul 2012 14:42:11 -0700 Subject: [PATCH 4664/5711] hfsplus: use -ENOMEM when kzalloc() fails Use -ENOMEM return value instead of -EINVAL when kzalloc() fails. Signed-off-by: Namjae Jeon Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfsplus/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 473332098013..fdafb2d71654 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -365,7 +365,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) u64 last_fs_block, last_fs_page; int err; - err = -EINVAL; + err = -ENOMEM; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) goto out; -- GitLab From a943ed71c9171fb5e3b256e8022bbedff95cc826 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Mon, 30 Jul 2012 14:42:13 -0700 Subject: [PATCH 4665/5711] fat: accessors for msdos_dir_entry 'start' fields Simplify code by providing accessor functions for the directory entry start cluster fields. Signed-off-by: Steven J. Magnani Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/fat.h | 15 +++++++++++++++ fs/fat/inode.c | 12 +++--------- fs/fat/namei_msdos.c | 11 +++-------- fs/fat/namei_vfat.c | 11 +++-------- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index fc35c5c69136..2deeeb86f331 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -217,6 +217,21 @@ static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) #endif } +static inline int fat_get_start(const struct msdos_sb_info *sbi, + const struct msdos_dir_entry *de) +{ + int cluster = le16_to_cpu(de->start); + if (sbi->fat_bits == 32) + cluster |= (le16_to_cpu(de->starthi) << 16); + return cluster; +} + +static inline void fat_set_start(struct msdos_dir_entry *de, int cluster) +{ + de->start = cpu_to_le16(cluster); + de->starthi = cpu_to_le16(cluster >> 16); +} + static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) { #ifdef __BIG_ENDIAN diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 0038b32cb362..05e897fe9866 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -369,10 +369,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_op = sbi->dir_ops; inode->i_fop = &fat_dir_operations; - MSDOS_I(inode)->i_start = le16_to_cpu(de->start); - if (sbi->fat_bits == 32) - MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); - + MSDOS_I(inode)->i_start = fat_get_start(sbi, de); MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; error = fat_calc_dir_size(inode); if (error < 0) @@ -385,9 +382,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_mode = fat_make_mode(sbi, de->attr, ((sbi->options.showexec && !is_exec(de->name + 8)) ? S_IRUGO|S_IWUGO : S_IRWXUGO)); - MSDOS_I(inode)->i_start = le16_to_cpu(de->start); - if (sbi->fat_bits == 32) - MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); + MSDOS_I(inode)->i_start = fat_get_start(sbi, de); MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; inode->i_size = le32_to_cpu(de->size); @@ -613,8 +608,7 @@ retry: else raw_entry->size = cpu_to_le32(inode->i_size); raw_entry->attr = fat_make_attrs(inode); - raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); - raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); + fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart); fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time, &raw_entry->date, NULL); if (sbi->options.isvfat) { diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 70d993a93805..b0e12bf9f4a1 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -246,8 +246,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, de.ctime_cs = 0; de.time = time; de.date = date; - de.start = cpu_to_le16(cluster); - de.starthi = cpu_to_le16(cluster >> 16); + fat_set_start(&de, cluster); de.size = 0; err = fat_add_entries(dir, &de, 1, sinfo); @@ -530,9 +529,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, mark_inode_dirty(old_inode); if (update_dotdot) { - int start = MSDOS_I(new_dir)->i_logstart; - dotdot_de->start = cpu_to_le16(start); - dotdot_de->starthi = cpu_to_le16(start >> 16); + fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); mark_buffer_dirty_inode(dotdot_bh, old_inode); if (IS_DIRSYNC(new_dir)) { err = sync_dirty_buffer(dotdot_bh); @@ -572,9 +569,7 @@ error_dotdot: corrupt = 1; if (update_dotdot) { - int start = MSDOS_I(old_dir)->i_logstart; - dotdot_de->start = cpu_to_le16(start); - dotdot_de->starthi = cpu_to_le16(start >> 16); + fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); mark_buffer_dirty_inode(dotdot_bh, old_inode); corrupt |= sync_dirty_buffer(dotdot_bh); } diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 6cc480652433..6a6d8c0715a1 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -651,8 +651,7 @@ shortname: de->time = de->ctime = time; de->date = de->cdate = de->adate = date; de->ctime_cs = time_cs; - de->start = cpu_to_le16(cluster); - de->starthi = cpu_to_le16(cluster >> 16); + fat_set_start(de, cluster); de->size = 0; out_free: __putname(uname); @@ -965,9 +964,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, mark_inode_dirty(old_inode); if (update_dotdot) { - int start = MSDOS_I(new_dir)->i_logstart; - dotdot_de->start = cpu_to_le16(start); - dotdot_de->starthi = cpu_to_le16(start >> 16); + fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); mark_buffer_dirty_inode(dotdot_bh, old_inode); if (IS_DIRSYNC(new_dir)) { err = sync_dirty_buffer(dotdot_bh); @@ -1009,9 +1006,7 @@ error_dotdot: corrupt = 1; if (update_dotdot) { - int start = MSDOS_I(old_dir)->i_logstart; - dotdot_de->start = cpu_to_le16(start); - dotdot_de->starthi = cpu_to_le16(start >> 16); + fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); mark_buffer_dirty_inode(dotdot_bh, old_inode); corrupt |= sync_dirty_buffer(dotdot_bh); } -- GitLab From deb8274a0cf44827ec260330cc1d94d0f3dcfb94 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Mon, 30 Jul 2012 14:42:16 -0700 Subject: [PATCH 4666/5711] fat: refactor shortname parsing Nearly identical shortname parsing is performed in fat_search_long() and __fat_readdir(). Extract this code into a function that may be called by both. Signed-off-by: Steven J. Magnani Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/dir.c | 255 +++++++++++++++++++++++++++------------------------ 1 file changed, 137 insertions(+), 118 deletions(-) diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 6eaa28c98ad1..dc49ed2cbffa 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -35,6 +35,11 @@ #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1) #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t)) +static inline unsigned char fat_tolower(unsigned char c) +{ + return ((c >= 'A') && (c <= 'Z')) ? c+32 : c; +} + static inline loff_t fat_make_i_pos(struct super_block *sb, struct buffer_head *bh, struct msdos_dir_entry *de) @@ -333,6 +338,124 @@ parse_long: return 0; } +/** + * fat_parse_short - Parse MS-DOS (short) directory entry. + * @sb: superblock + * @de: directory entry to parse + * @name: FAT_MAX_SHORT_SIZE array in which to place extracted name + * @dot_hidden: Nonzero == prepend '.' to names with ATTR_HIDDEN + * + * Returns the number of characters extracted into 'name'. + */ +static int fat_parse_short(struct super_block *sb, + const struct msdos_dir_entry *de, + unsigned char *name, int dot_hidden) +{ + const struct msdos_sb_info *sbi = MSDOS_SB(sb); + int isvfat = sbi->options.isvfat; + int nocase = sbi->options.nocase; + unsigned short opt_shortname = sbi->options.shortname; + struct nls_table *nls_disk = sbi->nls_disk; + wchar_t uni_name[14]; + unsigned char c, work[MSDOS_NAME]; + unsigned char *ptname = name; + int chi, chl, i, j, k; + int dotoffset = 0; + int name_len = 0, uni_len = 0; + + if (!isvfat && dot_hidden && (de->attr & ATTR_HIDDEN)) { + *ptname++ = '.'; + dotoffset = 1; + } + + memcpy(work, de->name, sizeof(work)); + /* see namei.c, msdos_format_name */ + if (work[0] == 0x05) + work[0] = 0xE5; + + /* Filename */ + for (i = 0, j = 0; i < 8;) { + c = work[i]; + if (!c) + break; + chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, + &uni_name[j++], opt_shortname, + de->lcase & CASE_LOWER_BASE); + if (chl <= 1) { + if (!isvfat) + ptname[i] = nocase ? c : fat_tolower(c); + i++; + if (c != ' ') { + name_len = i; + uni_len = j; + } + } else { + uni_len = j; + if (isvfat) + i += min(chl, 8-i); + else { + for (chi = 0; chi < chl && i < 8; chi++, i++) + ptname[i] = work[i]; + } + if (chl) + name_len = i; + } + } + + i = name_len; + j = uni_len; + fat_short2uni(nls_disk, ".", 1, &uni_name[j++]); + if (!isvfat) + ptname[i] = '.'; + i++; + + /* Extension */ + for (k = 8; k < MSDOS_NAME;) { + c = work[k]; + if (!c) + break; + chl = fat_shortname2uni(nls_disk, &work[k], MSDOS_NAME - k, + &uni_name[j++], opt_shortname, + de->lcase & CASE_LOWER_EXT); + if (chl <= 1) { + k++; + if (!isvfat) + ptname[i] = nocase ? c : fat_tolower(c); + i++; + if (c != ' ') { + name_len = i; + uni_len = j; + } + } else { + uni_len = j; + if (isvfat) { + int offset = min(chl, MSDOS_NAME-k); + k += offset; + i += offset; + } else { + for (chi = 0; chi < chl && k < MSDOS_NAME; + chi++, i++, k++) { + ptname[i] = work[k]; + } + } + if (chl) + name_len = i; + } + } + + if (name_len > 0) { + name_len += dotoffset; + + if (sbi->options.isvfat) { + uni_name[uni_len] = 0x0000; + name_len = fat_uni_to_x8(sb, uni_name, name, + FAT_MAX_SHORT_SIZE); + } + } + + return name_len; +} + /* * Return values: negative -> error, 0 -> not found, positive -> found, * value is the total amount of slots, including the shortname entry. @@ -344,15 +467,11 @@ int fat_search_long(struct inode *inode, const unsigned char *name, struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh = NULL; struct msdos_dir_entry *de; - struct nls_table *nls_disk = sbi->nls_disk; unsigned char nr_slots; - wchar_t bufuname[14]; wchar_t *unicode = NULL; - unsigned char work[MSDOS_NAME]; unsigned char bufname[FAT_MAX_SHORT_SIZE]; - unsigned short opt_shortname = sbi->options.shortname; loff_t cpos = 0; - int chl, i, j, last_u, err, len; + int err, len; err = -ENOENT; while (1) { @@ -380,47 +499,16 @@ parse_record: goto end_of_dir; } - memcpy(work, de->name, sizeof(de->name)); - /* see namei.c, msdos_format_name */ - if (work[0] == 0x05) - work[0] = 0xE5; - for (i = 0, j = 0, last_u = 0; i < 8;) { - if (!work[i]) - break; - chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, - &bufuname[j++], opt_shortname, - de->lcase & CASE_LOWER_BASE); - if (chl <= 1) { - if (work[i] != ' ') - last_u = j; - } else { - last_u = j; - } - i += chl; - } - j = last_u; - fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); - for (i = 8; i < MSDOS_NAME;) { - if (!work[i]) - break; - chl = fat_shortname2uni(nls_disk, &work[i], - MSDOS_NAME - i, - &bufuname[j++], opt_shortname, - de->lcase & CASE_LOWER_EXT); - if (chl <= 1) { - if (work[i] != ' ') - last_u = j; - } else { - last_u = j; - } - i += chl; - } - if (!last_u) + /* Never prepend '.' to hidden files here. + * That is done only for msdos mounts (and only when + * 'dotsOK=yes'); if we are executing here, it is in the + * context of a vfat mount. + */ + len = fat_parse_short(sb, de, bufname, 0); + if (len == 0) continue; /* Compare shortname */ - bufuname[last_u] = 0x0000; - len = fat_uni_to_x8(sb, bufuname, bufname, sizeof(bufname)); if (fat_name_match(sbi, name, name_len, bufname, len)) goto found; @@ -469,20 +557,15 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; struct msdos_dir_entry *de; - struct nls_table *nls_disk = sbi->nls_disk; unsigned char nr_slots; - wchar_t bufuname[14]; wchar_t *unicode = NULL; - unsigned char c, work[MSDOS_NAME]; - unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname; - unsigned short opt_shortname = sbi->options.shortname; + unsigned char bufname[FAT_MAX_SHORT_SIZE]; int isvfat = sbi->options.isvfat; - int nocase = sbi->options.nocase; const char *fill_name = NULL; unsigned long inum; unsigned long lpos, dummy, *furrfu = &lpos; loff_t cpos; - int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0; + int short_len = 0, fill_len = 0; int ret = 0; lock_super(sb); @@ -556,74 +639,10 @@ parse_record: } } - if (sbi->options.dotsOK) { - ptname = bufname; - dotoffset = 0; - if (de->attr & ATTR_HIDDEN) { - *ptname++ = '.'; - dotoffset = 1; - } - } - - memcpy(work, de->name, sizeof(de->name)); - /* see namei.c, msdos_format_name */ - if (work[0] == 0x05) - work[0] = 0xE5; - for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) { - if (!(c = work[i])) - break; - chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, - &bufuname[j++], opt_shortname, - de->lcase & CASE_LOWER_BASE); - if (chl <= 1) { - ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; - if (c != ' ') { - last = i; - last_u = j; - } - } else { - last_u = j; - for (chi = 0; chi < chl && i < 8; chi++) { - ptname[i] = work[i]; - i++; last = i; - } - } - } - i = last; - j = last_u; - fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); - ptname[i++] = '.'; - for (i2 = 8; i2 < MSDOS_NAME;) { - if (!(c = work[i2])) - break; - chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2, - &bufuname[j++], opt_shortname, - de->lcase & CASE_LOWER_EXT); - if (chl <= 1) { - i2++; - ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; - if (c != ' ') { - last = i; - last_u = j; - } - } else { - last_u = j; - for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) { - ptname[i++] = work[i2++]; - last = i; - } - } - } - if (!last) + short_len = fat_parse_short(sb, de, bufname, sbi->options.dotsOK); + if (short_len == 0) goto record_end; - i = last + dotoffset; - j = last_u; - - if (isvfat) { - bufuname[j] = 0x0000; - i = fat_uni_to_x8(sb, bufuname, bufname, sizeof(bufname)); - } if (nr_slots) { /* hack for fat_ioctl_filldir() */ struct fat_ioctl_filldir_callback *p = dirent; @@ -631,12 +650,12 @@ parse_record: p->longname = fill_name; p->long_len = fill_len; p->shortname = bufname; - p->short_len = i; + p->short_len = short_len; fill_name = NULL; fill_len = 0; } else { fill_name = bufname; - fill_len = i; + fill_len = short_len; } start_filldir: -- GitLab From 79c743dd1e8de61c31f484c0a1b48930543044b3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:42:17 -0700 Subject: [PATCH 4667/5711] kernel/kmod.c: document call_usermodehelper_fns() a bit This function's interface is, uh, subtle. Attempt to apologise for it. Cc: WANG Cong Cc: Cyrill Gorcunov Cc: Kees Cook Cc: Serge Hallyn Cc: "Eric W. Biederman" Cc: Alan Cox Cc: Oleg Nesterov Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kmod.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/kmod.c b/kernel/kmod.c index ff2c7cb86d77..2a8351516a0e 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -577,6 +577,12 @@ unlock: return retval; } +/* + * call_usermodehelper_fns() will not run the caller-provided cleanup function + * if a memory allocation failure is experienced. So the caller might need to + * check the call_usermodehelper_fns() return value: if it is -ENOMEM, perform + * the necessaary cleanup within the caller. + */ int call_usermodehelper_fns( char *path, char **argv, char **envp, int wait, int (*init)(struct subprocess_info *info, struct cred *new), -- GitLab From 0f20784d4ba3f88ca33b703b23372d8ccf6dbd42 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 30 Jul 2012 14:42:20 -0700 Subject: [PATCH 4668/5711] kmod: avoid deadlock from recursive kmod call The system deadlocks (at least since 2.6.10) when call_usermodehelper(UMH_WAIT_EXEC) request triggers call_usermodehelper(UMH_WAIT_PROC) request. This is because "khelper thread is waiting for the worker thread at wait_for_completion() in do_fork() since the worker thread was created with CLONE_VFORK flag" and "the worker thread cannot call complete() because do_execve() is blocked at UMH_WAIT_PROC request" and "the khelper thread cannot start processing UMH_WAIT_PROC request because the khelper thread is waiting for the worker thread at wait_for_completion() in do_fork()". The easiest example to observe this deadlock is to use a corrupted /sbin/hotplug binary (like shown below). # : > /tmp/dummy # chmod 755 /tmp/dummy # echo /tmp/dummy > /proc/sys/kernel/hotplug # modprobe whatever call_usermodehelper("/tmp/dummy", UMH_WAIT_EXEC) is called from kobject_uevent_env() in lib/kobject_uevent.c upon loading/unloading a module. do_execve("/tmp/dummy") triggers a call to request_module("binfmt-0000") from search_binary_handler() which in turn calls call_usermodehelper(UMH_WAIT_PROC). In order to avoid deadlock, as a for-now and easy-to-backport solution, do not try to call wait_for_completion() in call_usermodehelper_exec() if the worker thread was created by khelper thread with CLONE_VFORK flag. Future and fundamental solution might be replacing singleton khelper thread with some workqueue so that recursive calls up to max_active dependency loop can be handled without deadlock. [akpm@linux-foundation.org: add comment to kmod_thread_locker] Signed-off-by: Tetsuo Handa Cc: Arjan van de Ven Acked-by: Rusty Russell Cc: Tejun Heo Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kmod.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/kernel/kmod.c b/kernel/kmod.c index 2a8351516a0e..6f99aead66c6 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -45,6 +45,13 @@ extern int max_threads; static struct workqueue_struct *khelper_wq; +/* + * kmod_thread_locker is used for deadlock avoidance. There is no explicit + * locking to protect this global - it is private to the singleton khelper + * thread and should only ever be modified by that thread. + */ +static const struct task_struct *kmod_thread_locker; + #define CAP_BSET (void *)1 #define CAP_PI (void *)2 @@ -221,6 +228,13 @@ fail: return 0; } +static int call_helper(void *data) +{ + /* Worker thread started blocking khelper thread. */ + kmod_thread_locker = current; + return ____call_usermodehelper(data); +} + static void call_usermodehelper_freeinfo(struct subprocess_info *info) { if (info->cleanup) @@ -295,9 +309,12 @@ static void __call_usermodehelper(struct work_struct *work) if (wait == UMH_WAIT_PROC) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); - else - pid = kernel_thread(____call_usermodehelper, sub_info, + else { + pid = kernel_thread(call_helper, sub_info, CLONE_VFORK | SIGCHLD); + /* Worker thread stopped blocking khelper thread. */ + kmod_thread_locker = NULL; + } switch (wait) { case UMH_NO_WAIT: @@ -548,6 +565,16 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) retval = -EBUSY; goto out; } + /* + * Worker thread must not wait for khelper thread at below + * wait_for_completion() if the thread was created with CLONE_VFORK + * flag, for khelper thread is already waiting for the thread at + * wait_for_completion() in do_fork(). + */ + if (wait != UMH_NO_WAIT && current == kmod_thread_locker) { + retval = -EBUSY; + goto out; + } sub_info->complete = &done; sub_info->wait = wait; -- GitLab From 108ceeb020bb3558fe175a3fc8b60fd6c1a2a279 Mon Sep 17 00:00:00 2001 From: Jovi Zhang Date: Mon, 30 Jul 2012 14:42:23 -0700 Subject: [PATCH 4669/5711] coredump: fix wrong comments on core limits of pipe coredump case In commit 898b374af6f7 ("exec: replace call_usermodehelper_pipe with use of umh init function and resolve limit"), the core limits recursive check value was changed from 0 to 1, but the corresponding comments were not updated. Signed-off-by: Jovi Zhang Cc: Oleg Nesterov Cc: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 5af8390e0fae..3684353ebd5f 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -2174,15 +2174,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) } if (cprm.limit == 1) { - /* + /* See umh_pipe_setup() which sets RLIMIT_CORE = 1. + * * Normally core limits are irrelevant to pipes, since * we're not writing to the file system, but we use - * cprm.limit of 1 here as a speacial value. Any - * non-1 limit gets set to RLIM_INFINITY below, but - * a limit of 0 skips the dump. This is a consistent - * way to catch recursive crashes. We can still crash - * if the core_pattern binary sets RLIM_CORE = !1 - * but it runs as root, and can do lots of stupid things + * cprm.limit of 1 here as a speacial value, this is a + * consistent way to catch recursive crashes. + * We can still crash if the core_pattern binary sets + * RLIM_CORE = !1, but it runs as root, and can do + * lots of stupid things. + * * Note that we use task_tgid_vnr here to grab the pid * of the process group leader. That way we get the * right pid if a thread in a multi-threaded -- GitLab From e8905ec27e2f4ea1b9f7e03df68a060b3ae6fca8 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 30 Jul 2012 14:42:26 -0700 Subject: [PATCH 4670/5711] proc: environ_read() make sure offset points to environment address range Currently the following offset and environment address range check in environ_read() of /proc//environ is buggy: int this_len = mm->env_end - (mm->env_start + src); if (this_len <= 0) break; Large or negative offsets on /proc//environ converted to 'unsigned long' may pass this check since '(mm->env_start + src)' can overflow and 'this_len' will be positive. This can turn /proc//environ to act like /proc//mem since (mm->env_start + src) will point and read from another VMA. There are two fixes here plus some code cleaning: 1) Fix the overflow by checking if the offset that was converted to unsigned long will always point to the [mm->env_start, mm->env_end] address range. 2) Remove the truncation that was made to the result of the check, storing the result in 'int this_len' will alter its value and we can not depend on it. For kernels that have commit b409e578d ("proc: clean up /proc//environ handling") which adds the appropriate ptrace check and saves the 'mm' at ->open() time, this is not a security issue. This patch is taken from the grsecurity patch since it was just made available. Signed-off-by: Djalal Harouni Cc: Oleg Nesterov Cc: Brad Spengler Acked-by: Kees Cook Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 2772208338f8..39ee093b5e96 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -827,15 +827,16 @@ static ssize_t environ_read(struct file *file, char __user *buf, if (!atomic_inc_not_zero(&mm->mm_users)) goto free; while (count > 0) { - int this_len, retval, max_len; + size_t this_len, max_len; + int retval; - this_len = mm->env_end - (mm->env_start + src); - - if (this_len <= 0) + if (src >= (mm->env_end - mm->env_start)) break; - max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - this_len = (this_len > max_len) ? max_len : this_len; + this_len = mm->env_end - (mm->env_start + src); + + max_len = min_t(size_t, PAGE_SIZE, count); + this_len = min(max_len, this_len); retval = access_remote_vm(mm, (mm->env_start + src), page, this_len, 0); -- GitLab From bc452b4b65bd589083a7a7ba4f14f85dfc8454fa Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 30 Jul 2012 14:42:28 -0700 Subject: [PATCH 4671/5711] proc: do not allow negative offsets on /proc//environ __mem_open() which is called by both /proc//environ and /proc//mem ->open() handlers will allow the use of negative offsets. /proc//mem has negative offsets but not /proc//environ. Clean this by moving the 'force FMODE_UNSIGNED_OFFSET flag' to mem_open() to allow negative offsets only on /proc//mem. Signed-off-by: Djalal Harouni Cc: Oleg Nesterov Cc: Brad Spengler Acked-by: Kees Cook Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 39ee093b5e96..1b6c84cbdb73 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -695,8 +695,6 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode) mmput(mm); } - /* OK to pass negative loff_t, we can catch out-of-range */ - file->f_mode |= FMODE_UNSIGNED_OFFSET; file->private_data = mm; return 0; @@ -704,7 +702,12 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode) static int mem_open(struct inode *inode, struct file *file) { - return __mem_open(inode, file, PTRACE_MODE_ATTACH); + int ret = __mem_open(inode, file, PTRACE_MODE_ATTACH); + + /* OK to pass negative loff_t, we can catch out-of-range */ + file->f_mode |= FMODE_UNSIGNED_OFFSET; + + return ret; } static ssize_t mem_rw(struct file *file, char __user *buf, -- GitLab From b2412b7fa7a3816fa8633dc2ff19f1a90aabe423 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Mon, 30 Jul 2012 14:42:30 -0700 Subject: [PATCH 4672/5711] fork: use vma_pages() to simplify the code The current code can be replaced by vma_pages(). So use it to simplify the code. [akpm@linux-foundation.org: initialise `len' at its definition site] Signed-off-by: Huang Shijie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index ff1cad3b7bdc..2c1802948a38 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -391,8 +391,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) } charge = 0; if (mpnt->vm_flags & VM_ACCOUNT) { - unsigned long len; - len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + unsigned long len = vma_pages(mpnt); + if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ goto fail_nomem; charge = len; -- GitLab From 87bec58a52652e2eb2a575692a40f9466c7bd31b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:42:31 -0700 Subject: [PATCH 4673/5711] revert "sched: Fix fork() error path to not crash" To make way for "fork: fix error handling in dup_task()", which fixes the errors more completely. Cc: Salman Qazi Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index 2c1802948a38..088025bd1925 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -304,17 +304,12 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) } err = arch_dup_task_struct(tsk, orig); - - /* - * We defer looking at err, because we will need this setup - * for the clean up path to work correctly. - */ - tsk->stack = ti; - setup_thread_stack(tsk, orig); - if (err) goto out; + tsk->stack = ti; + + setup_thread_stack(tsk, orig); clear_user_return_notifier(tsk); clear_tsk_need_resched(tsk); stackend = end_of_stack(tsk); -- GitLab From f19b9f74b7ea3b21ddcee55d852a6488239608a4 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:42:33 -0700 Subject: [PATCH 4674/5711] fork: fix error handling in dup_task() The function dup_task() may fail at the following function calls in the following order. 0) alloc_task_struct_node() 1) alloc_thread_info_node() 2) arch_dup_task_struct() Error by 0) is not a matter, it can just return. But error by 1) requires releasing task_struct allocated by 0) before it returns. Likewise, error by 2) requires releasing task_struct and thread_info allocated by 0) and 1). The existing error handling calls free_task_struct() and free_thread_info() which do not only release task_struct and thread_info, but also call architecture specific arch_release_task_struct() and arch_release_thread_info(). The problem is that task_struct and thread_info are not fully initialized yet at this point, but arch_release_task_struct() and arch_release_thread_info() are called with them. For example, x86 defines its own arch_release_task_struct() that releases a task_xstate. If alloc_thread_info_node() fails in dup_task(), arch_release_task_struct() is called with task_struct which is just allocated and filled with garbage in this error handling. This actually happened with tools/testing/fault-injection/failcmd.sh # env FAILCMD_TYPE=fail_page_alloc \ ./tools/testing/fault-injection/failcmd.sh --times=100 \ --min-order=0 --ignore-gfp-wait=0 \ -- make -C tools/testing/selftests/ run_tests In order to fix this issue, make free_{task_struct,thread_info}() not to call arch_release_{task_struct,thread_info}() and call arch_release_{task_struct,thread_info}() implicitly where needed. Default arch_release_task_struct() and arch_release_thread_info() are defined as empty by default. So this change only affects the architectures which implement their own arch_release_task_struct() or arch_release_thread_info() as listed below. arch_release_task_struct(): x86, sh arch_release_thread_info(): mn10300, tile Signed-off-by: Akinobu Mita Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: David Howells Cc: Koichi Yasutake Cc: Paul Mundt Cc: Chris Metcalf Cc: Salman Qazi Cc: Peter Zijlstra Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index 088025bd1925..8efac1fe56bc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -114,6 +114,10 @@ int nr_processes(void) return total; } +void __weak arch_release_task_struct(struct task_struct *tsk) +{ +} + #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR static struct kmem_cache *task_struct_cachep; @@ -122,17 +126,17 @@ static inline struct task_struct *alloc_task_struct_node(int node) return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node); } -void __weak arch_release_task_struct(struct task_struct *tsk) { } - static inline void free_task_struct(struct task_struct *tsk) { - arch_release_task_struct(tsk); kmem_cache_free(task_struct_cachep, tsk); } #endif +void __weak arch_release_thread_info(struct thread_info *ti) +{ +} + #ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR -void __weak arch_release_thread_info(struct thread_info *ti) { } /* * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a @@ -150,7 +154,6 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, static inline void free_thread_info(struct thread_info *ti) { - arch_release_thread_info(ti); free_pages((unsigned long)ti, THREAD_SIZE_ORDER); } # else @@ -164,7 +167,6 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, static void free_thread_info(struct thread_info *ti) { - arch_release_thread_info(ti); kmem_cache_free(thread_info_cache, ti); } @@ -205,10 +207,12 @@ static void account_kernel_stack(struct thread_info *ti, int account) void free_task(struct task_struct *tsk) { account_kernel_stack(tsk->stack, -1); + arch_release_thread_info(tsk->stack); free_thread_info(tsk->stack); rt_mutex_debug_task_free(tsk); ftrace_graph_exit_task(tsk); put_seccomp_filter(tsk); + arch_release_task_struct(tsk); free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -298,14 +302,12 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) return NULL; ti = alloc_thread_info_node(tsk, node); - if (!ti) { - free_task_struct(tsk); - return NULL; - } + if (!ti) + goto free_tsk; err = arch_dup_task_struct(tsk, orig); if (err) - goto out; + goto free_ti; tsk->stack = ti; @@ -333,8 +335,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) return tsk; -out: +free_ti: free_thread_info(ti); +free_tsk: free_task_struct(tsk); return NULL; } -- GitLab From 63dca8d5b5ef7effb58b8d6892a024125c0fab0b Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 30 Jul 2012 14:42:36 -0700 Subject: [PATCH 4675/5711] kdump: append newline to the last lien of vmcoreinfo note The last line of vmcoreinfo note does not end with \n. Parsing all the lines in note becomes easier if all lines end with \n instead of trying to special case the last line. I know at least one tool, vmcore-dmesg in kexec-tools tree which made the assumption that all lines end with \n. I think it is a good idea to fix it. Signed-off-by: Vivek Goyal Cc: "Eric W. Biederman" Cc: Atsushi Kumagai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kexec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6aeb..0668d58d6413 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1424,7 +1424,7 @@ static void update_vmcoreinfo_note(void) void crash_save_vmcoreinfo(void) { - vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); + vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds()); update_vmcoreinfo_note(); } -- GitLab From 079a96ae3871f0ed9083aac2218136ccec5b9877 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jul 2012 14:42:38 -0700 Subject: [PATCH 4676/5711] ipc: add COMPAT_SHMLBA support If the SHMLBA definition for a native task differs from the definition for a compat task, the do_shmat() function would need to handle both. This patch introduces COMPAT_SHMLBA, which is used by the compat shmat syscall when calling the ipc code and allows architectures such as AArch64 (where the native SHMLBA is 64k but the compat (AArch32) definition is 16k) to provide the correct semantics for compat IPC system calls. Cc: David S. Miller Cc: Chris Zankel Cc: Arnd Bergmann Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/sys_sparc_64.c | 2 +- arch/xtensa/kernel/syscall.c | 2 +- include/linux/shm.h | 6 ++++-- ipc/compat.c | 8 ++++++-- ipc/shm.c | 9 +++++---- ipc/syscall.c | 2 +- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index c38e5aaae56f..0dc1f5786081 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -470,7 +470,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second switch (call) { case SHMAT: { ulong raddr; - err = do_shmat(first, ptr, (int)second, &raddr); + err = do_shmat(first, ptr, (int)second, &raddr, SHMLBA); if (!err) { if (put_user(raddr, (ulong __user *) third)) diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index 816e6d0d686c..05b3f093d5d7 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -44,7 +44,7 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) unsigned long ret; long err; - err = do_shmat(shmid, shmaddr, shmflg, &ret); + err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA); if (err) return err; return (long)ret; diff --git a/include/linux/shm.h b/include/linux/shm.h index 92808b86703b..edd086883ccb 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -107,12 +107,14 @@ struct shmid_kernel /* private to the kernel */ #define SHM_NORESERVE 010000 /* don't check for reservations */ #ifdef CONFIG_SYSVIPC -long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr); +long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr, + unsigned long shmlba); extern int is_file_shm_hugepages(struct file *file); extern void exit_shm(struct task_struct *task); #else static inline long do_shmat(int shmid, char __user *shmaddr, - int shmflg, unsigned long *addr) + int shmflg, unsigned long *addr, + unsigned long shmlba) { return -ENOSYS; } diff --git a/ipc/compat.c b/ipc/compat.c index a6df704f521e..53cebdf80e3c 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -514,6 +514,10 @@ long compat_sys_msgctl(int first, int second, void __user *uptr) return err; } +#ifndef COMPAT_SHMLBA +#define COMPAT_SHMLBA SHMLBA +#endif + #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, void __user *uptr) @@ -524,7 +528,7 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, if (version == 1) return -EINVAL; - err = do_shmat(first, uptr, second, &raddr); + err = do_shmat(first, uptr, second, &raddr, COMPAT_SHMLBA); if (err < 0) return err; uaddr = compat_ptr(third); @@ -536,7 +540,7 @@ long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg) unsigned long ret; long err; - err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret); + err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA); if (err) return err; force_successful_syscall_return(); diff --git a/ipc/shm.c b/ipc/shm.c index 41c1285d697a..00faa05cf72a 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -953,7 +953,8 @@ out: * "raddr" thing points to kernel space, and there has to be a wrapper around * this. */ -long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) +long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, + unsigned long shmlba) { struct shmid_kernel *shp; unsigned long addr; @@ -973,9 +974,9 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) if (shmid < 0) goto out; else if ((addr = (ulong)shmaddr)) { - if (addr & (SHMLBA-1)) { + if (addr & (shmlba - 1)) { if (shmflg & SHM_RND) - addr &= ~(SHMLBA-1); /* round down */ + addr &= ~(shmlba - 1); /* round down */ else #ifndef __ARCH_FORCE_SHMLBA if (addr & ~PAGE_MASK) @@ -1107,7 +1108,7 @@ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) unsigned long ret; long err; - err = do_shmat(shmid, shmaddr, shmflg, &ret); + err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA); if (err) return err; force_successful_syscall_return(); diff --git a/ipc/syscall.c b/ipc/syscall.c index 1d6f53f6b562..0d1e32ce048e 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c @@ -73,7 +73,7 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, default: { unsigned long raddr; ret = do_shmat(first, (char __user *)ptr, - second, &raddr); + second, &raddr, SHMLBA); if (ret) return ret; return put_user(raddr, (unsigned long __user *) third); -- GitLab From b610c04c667f3c056243fd64041c7f152a512ee4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jul 2012 14:42:40 -0700 Subject: [PATCH 4677/5711] ipc: allow compat IPC version field parsing if !ARCH_WANT_OLD_COMPAT_IPC Commit 48b25c43e6ee ("ipc: provide generic compat versions of IPC syscalls") added a new ARCH_WANT_OLD_COMPAT_IPC config option for architectures to select if their compat target requires the old IPC syscall interface. For architectures (such as AArch64) that do not require the internal calling conventions provided by this option, but have a compat target where the C library passes the IPC_64 flag explicitly, compat_ipc_parse_version no longer strips out the flag before calling the native system call implementation, resulting in unknown SHM/IPC commands and -EINVAL being returned to userspace. This patch separates the selection of the internal calling conventions for the IPC syscalls from the version parsing, allowing architectures to select __ARCH_WANT_COMPAT_IPC_PARSE_VERSION if they want to use version parsing whilst retaining the newer syscall calling conventions. Acked-by: Chris Metcalf Cc: Arnd Bergmann Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compat.h | 1 + ipc/compat.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index 4e890394ef99..9f68e90a14ec 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -256,6 +256,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, compat_size_t __user *len_ptr); #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC +#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION long compat_sys_semctl(int first, int second, int third, void __user *uptr); long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); long compat_sys_msgrcv(int first, int second, int msgtyp, int third, diff --git a/ipc/compat.c b/ipc/compat.c index 53cebdf80e3c..a41600f6ba52 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -118,7 +118,7 @@ extern int sem_ctls[]; static inline int compat_ipc_parse_version(int *cmd) { -#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC +#ifdef __ARCH_WANT_COMPAT_IPC_PARSE_VERSION int version = *cmd & IPC_64; /* this is tricky: architectures that have support for the old -- GitLab From 05ba3f1aa1b04e921068249dd52a80bc84c2aeb4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jul 2012 14:42:43 -0700 Subject: [PATCH 4678/5711] ipc: compat: use signed size_t types for msgsnd and msgrcv The msgsnd and msgrcv system calls use size_t to represent the size of the message being transferred. POSIX states that values of msgsz greater than SSIZE_MAX cause the result to be implementation-defined. On Linux, this equates to returning -EINVAL if (long) msgsz < 0. For compat tasks where !CONFIG_ARCH_WANT_OLD_COMPAT_IPC and compat_size_t is smaller than size_t, negative size values passed from userspace will be interpreted as positive values by do_msg{rcv,snd} and will fail to exit early with -EINVAL. This patch changes the compat prototypes for msg{rcv,snd} so that the message size is represented as a compat_ssize_t, which we cast to the native ssize_t type for the core IPC code. Cc: Arnd Bergmann Acked-by: Chris Metcalf Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compat.h | 4 ++-- ipc/compat.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index 9f68e90a14ec..f2b8fe20cc8e 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -266,9 +266,9 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, #else long compat_sys_semctl(int semid, int semnum, int cmd, int arg); long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, - size_t msgsz, int msgflg); + compat_ssize_t msgsz, int msgflg); long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, - size_t msgsz, long msgtyp, int msgflg); + compat_ssize_t msgsz, long msgtyp, int msgflg); long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg); #endif long compat_sys_msgctl(int first, int second, void __user *uptr); diff --git a/ipc/compat.c b/ipc/compat.c index a41600f6ba52..20f92b2f2932 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -373,21 +373,21 @@ long compat_sys_semctl(int semid, int semnum, int cmd, int arg) } long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, - size_t msgsz, int msgflg) + compat_ssize_t msgsz, int msgflg) { compat_long_t mtype; if (get_user(mtype, &msgp->mtype)) return -EFAULT; - return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); + return do_msgsnd(msqid, mtype, msgp->mtext, (ssize_t)msgsz, msgflg); } long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, - size_t msgsz, long msgtyp, int msgflg) + compat_ssize_t msgsz, long msgtyp, int msgflg) { long err, mtype; - err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); + err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg); if (err < 0) goto out; -- GitLab From c1d7e01d7877a397655277a920aeaa3830ed9461 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jul 2012 14:42:46 -0700 Subject: [PATCH 4679/5711] ipc: use Kconfig options for __ARCH_WANT_[COMPAT_]IPC_PARSE_VERSION Rather than #define the options manually in the architecture code, add Kconfig options for them and select them there instead. This also allows us to select the compat IPC version parsing automatically for platforms using the old compat IPC interface. Reported-by: Andrew Morton Signed-off-by: Will Deacon Cc: Arnd Bergmann Cc: Chris Metcalf Cc: Catalin Marinas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/Kconfig | 7 +++++++ arch/alpha/Kconfig | 1 + arch/alpha/include/asm/unistd.h | 1 - arch/arm/Kconfig | 1 + arch/arm/include/asm/unistd.h | 1 - arch/avr32/Kconfig | 1 + arch/avr32/include/asm/unistd.h | 1 - arch/blackfin/Kconfig | 1 + arch/blackfin/include/asm/unistd.h | 1 - arch/cris/Kconfig | 1 + arch/cris/include/asm/unistd.h | 1 - arch/frv/Kconfig | 1 + arch/frv/include/asm/unistd.h | 1 - arch/h8300/Kconfig | 1 + arch/h8300/include/asm/unistd.h | 1 - arch/m32r/Kconfig | 1 + arch/m32r/include/asm/unistd.h | 1 - arch/m68k/Kconfig | 1 + arch/m68k/include/asm/unistd.h | 1 - arch/microblaze/Kconfig | 1 + arch/microblaze/include/asm/unistd.h | 1 - arch/mips/Kconfig | 1 + arch/mips/include/asm/unistd.h | 1 - arch/mn10300/Kconfig | 1 + arch/mn10300/include/asm/unistd.h | 1 - arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/unistd.h | 1 - arch/s390/Kconfig | 1 + arch/s390/include/asm/unistd.h | 1 - arch/sh/Kconfig | 2 ++ arch/sh/include/asm/unistd.h | 1 - arch/sparc/Kconfig | 1 + arch/sparc/include/asm/unistd.h | 1 - arch/x86/Kconfig | 1 + arch/x86/include/asm/unistd.h | 1 - include/linux/compat.h | 1 - ipc/compat.c | 2 +- ipc/util.c | 4 ++-- ipc/util.h | 2 +- 39 files changed, 29 insertions(+), 22 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 8c3d957fa8e2..72f2fa189cc5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -248,7 +248,14 @@ config HAVE_CMPXCHG_LOCAL config HAVE_CMPXCHG_DOUBLE bool +config ARCH_WANT_IPC_PARSE_VERSION + bool + +config ARCH_WANT_COMPAT_IPC_PARSE_VERSION + bool + config ARCH_WANT_OLD_COMPAT_IPC + select ARCH_WANT_COMPAT_IPC_PARSE_VERSION bool config HAVE_ARCH_SECCOMP_FILTER diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 3de74c9f9610..d5b9b5e645cc 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -14,6 +14,7 @@ config ALPHA select AUTO_IRQ_AFFINITY if SMP select GENERIC_IRQ_SHOW select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_WANT_IPC_PARSE_VERSION select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_SMP_IDLE_THREAD select GENERIC_CMOS_UPDATE diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index d1f23b722df4..633b23b0664a 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -470,7 +470,6 @@ #define NR_SYSCALLS 504 -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4172c3cea228..5df11147be84 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -39,6 +39,7 @@ config ARM select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW select GENERIC_IRQ_PROBE + select ARCH_WANT_IPC_PARSE_VERSION select HARDIRQS_SW_RESEND select CPU_PM if (SUSPEND || CPU_IDLE) select GENERIC_PCI_IOMAP diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 512cd1473454..0cab47d4a83f 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -446,7 +446,6 @@ #ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 71d38c76726c..5ade51c8a87f 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -12,6 +12,7 @@ config AVR32 select HARDIRQS_SW_RESEND select GENERIC_IRQ_SHOW select ARCH_HAVE_CUSTOM_GPIO_H + select ARCH_WANT_IPC_PARSE_VERSION select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_CLOCKEVENTS help diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h index f714544e5560..1358e366f4be 100644 --- a/arch/avr32/include/asm/unistd.h +++ b/arch/avr32/include/asm/unistd.h @@ -318,7 +318,6 @@ /* SMP stuff */ #define __IGNORE_getcpu -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 9b765107e15c..fb9fe00e51a6 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -33,6 +33,7 @@ config BLACKFIN select HAVE_PERF_EVENTS select ARCH_HAVE_CUSTOM_GPIO_H select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_WANT_IPC_PARSE_VERSION select HAVE_GENERIC_HARDIRQS select GENERIC_ATOMIC64 select GENERIC_IRQ_PROBE diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h index 3287222cba34..5b2a0748d7d3 100644 --- a/arch/blackfin/include/asm/unistd.h +++ b/arch/blackfin/include/asm/unistd.h @@ -434,7 +434,6 @@ #define __IGNORE_getcpu #ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index bb344650a14f..e92215428a37 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -42,6 +42,7 @@ config CRIS select HAVE_IDE select GENERIC_ATOMIC64 select HAVE_GENERIC_HARDIRQS + select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_IRQ_SHOW select GENERIC_IOMAP select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h index f921b8b0f97e..51873a446f87 100644 --- a/arch/cris/include/asm/unistd.h +++ b/arch/cris/include/asm/unistd.h @@ -347,7 +347,6 @@ #include -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index a685910d2d5c..971c0a19facb 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -9,6 +9,7 @@ config FRV select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_CPU_DEVICES + select ARCH_WANT_IPC_PARSE_VERSION config ZONE_DMA bool diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index a569dff7cd59..67f23a311db6 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h @@ -349,7 +349,6 @@ #define NR_syscalls 338 -#define __ARCH_WANT_IPC_PARSE_VERSION /* #define __ARCH_WANT_OLD_READDIR */ #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 56e890df5053..5e8a0d9a09ce 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -3,6 +3,7 @@ config H8300 default y select HAVE_IDE select HAVE_GENERIC_HARDIRQS + select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h index 718511303b4e..5cd882801d79 100644 --- a/arch/h8300/include/asm/unistd.h +++ b/arch/h8300/include/asm/unistd.h @@ -331,7 +331,6 @@ #define NR_syscalls 321 -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index b638d5bfa14d..49498bbb9616 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -7,6 +7,7 @@ config M32R select HAVE_KERNEL_GZIP select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_LZMA + select ARCH_WANT_IPC_PARSE_VERSION select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index 3e1db561aacc..d5e66a480782 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h @@ -336,7 +336,6 @@ #define NR_syscalls 326 -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 147120128260..0b0f8b8c4a26 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -10,6 +10,7 @@ config M68K select GENERIC_STRNCPY_FROM_USER if MMU select GENERIC_STRNLEN_USER if MMU select FPU if MMU + select ARCH_WANT_IPC_PARSE_VERSION select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE config RWSEM_GENERIC_SPINLOCK diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index ea0b502f845e..045cfd6a9e31 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -357,7 +357,6 @@ #define NR_syscalls 347 -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 0bf44231aaf9..ab9afcaa7f6a 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -15,6 +15,7 @@ config MICROBLAZE select TRACING_SUPPORT select OF select OF_EARLY_FLATTREE + select ARCH_WANT_IPC_PARSE_VERSION select IRQ_DOMAIN select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index d20ffbc86beb..6985e6e9d826 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -400,7 +400,6 @@ #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -#define __ARCH_WANT_IPC_PARSE_VERSION /* #define __ARCH_WANT_OLD_READDIR */ /* #define __ARCH_WANT_OLD_STAT */ #define __ARCH_WANT_STAT64 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5e238d03960d..2d56cd5af336 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -27,6 +27,7 @@ config MIPS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW select HAVE_ARCH_JUMP_LABEL + select ARCH_WANT_IPC_PARSE_VERSION select IRQ_FORCED_THREADING select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index d8dad5340ea3..bebbde01be92 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -1034,7 +1034,6 @@ #ifndef __ASSEMBLY__ #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 687f9b4a2ed6..5cfb086b3903 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -3,6 +3,7 @@ config MN10300 select HAVE_OPROFILE select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW + select ARCH_WANT_IPC_PARSE_VERSION select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_KGDB select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h index 9051f921cbc7..866eb14749d7 100644 --- a/arch/mn10300/include/asm/unistd.h +++ b/arch/mn10300/include/asm/unistd.h @@ -358,7 +358,6 @@ /* * specify the deprecated syscalls we want to support on this arch */ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4f681b78dd8b..352f416269ce 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -121,6 +121,7 @@ config PPC select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 select HAVE_GENERIC_HARDIRQS + select ARCH_WANT_IPC_PARSE_VERSION select SPARSE_IRQ select IRQ_PER_CPU select IRQ_DOMAIN diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index d3d1b5efd7eb..bd377a368611 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -389,7 +389,6 @@ #include #include -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index d0a5e92b6b9e..296cd32466df 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -118,6 +118,7 @@ config S390 select ARCH_INLINE_WRITE_UNLOCK_BH select ARCH_INLINE_WRITE_UNLOCK_IRQ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL select GENERIC_CLOCKEVENTS diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 2e37157ba6a9..6756e78f4808 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -388,7 +388,6 @@ #define __IGNORE_recvmmsg #define __IGNORE_sendmmsg -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index a24595d83ad6..36f5141e8041 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -21,6 +21,7 @@ config SUPERH select HAVE_KERNEL_LZMA select HAVE_KERNEL_XZ select HAVE_KERNEL_LZO + select ARCH_WANT_IPC_PARSE_VERSION select HAVE_SYSCALL_TRACEPOINTS select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_GENERIC_HARDIRQS @@ -50,6 +51,7 @@ config SUPERH32 select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE + select ARCH_WANT_IPC_PARSE_VERSION select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB select HAVE_HW_BREAKPOINT diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index e800a38c9f8d..7bc67076baac 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h @@ -6,7 +6,6 @@ # endif # define __ARCH_WANT_SYS_RT_SIGSUSPEND -# define __ARCH_WANT_IPC_PARSE_VERSION # define __ARCH_WANT_OLD_READDIR # define __ARCH_WANT_OLD_STAT # define __ARCH_WANT_STAT64 diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index e74ff1377626..67f1f6f5f4e1 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -27,6 +27,7 @@ config SPARC select HAVE_ARCH_JUMP_LABEL select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW + select ARCH_WANT_IPC_PARSE_VERSION select USE_GENERIC_SMP_HELPERS if SMP select GENERIC_PCI_IOMAP select HAVE_NMI_WATCHDOG if SPARC64 diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index c7cb0af0eb59..fb2693464807 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -423,7 +423,6 @@ #endif #ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ca4fdefe79e6..ba2657c49217 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -85,6 +85,7 @@ config X86 select GENERIC_IOMAP select DCACHE_WORD_ACCESS select GENERIC_SMP_IDLE_THREAD + select ARCH_WANT_IPC_PARSE_VERSION if X86_32 select HAVE_ARCH_SECCOMP_FILTER select BUILDTIME_EXTABLE_SORT select GENERIC_CMOS_UPDATE diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 4437001d8e3d..0d9776e9e2dc 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -15,7 +15,6 @@ # ifdef CONFIG_X86_32 # include -# define __ARCH_WANT_IPC_PARSE_VERSION # define __ARCH_WANT_STAT64 # define __ARCH_WANT_SYS_IPC # define __ARCH_WANT_SYS_OLD_MMAP diff --git a/include/linux/compat.h b/include/linux/compat.h index f2b8fe20cc8e..09b28b7369d7 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -256,7 +256,6 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, compat_size_t __user *len_ptr); #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC -#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION long compat_sys_semctl(int first, int second, int third, void __user *uptr); long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); long compat_sys_msgrcv(int first, int second, int msgtyp, int third, diff --git a/ipc/compat.c b/ipc/compat.c index 20f92b2f2932..ad9518eb26e0 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -118,7 +118,7 @@ extern int sem_ctls[]; static inline int compat_ipc_parse_version(int *cmd) { -#ifdef __ARCH_WANT_COMPAT_IPC_PARSE_VERSION +#ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION int version = *cmd & IPC_64; /* this is tricky: architectures that have support for the old diff --git a/ipc/util.c b/ipc/util.c index 75261a31d48d..eb07fd356f27 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -804,7 +804,7 @@ out_up: return ERR_PTR(err); } -#ifdef __ARCH_WANT_IPC_PARSE_VERSION +#ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION /** @@ -826,7 +826,7 @@ int ipc_parse_version (int *cmd) } } -#endif /* __ARCH_WANT_IPC_PARSE_VERSION */ +#endif /* CONFIG_ARCH_WANT_IPC_PARSE_VERSION */ #ifdef CONFIG_PROC_FS struct ipc_proc_iter { diff --git a/ipc/util.h b/ipc/util.h index 6f5c20bedaab..850ef3e962cb 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -130,7 +130,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, struct ipc_ids *ids, int id, int cmd, struct ipc64_perm *perm, int extra_perm); -#ifndef __ARCH_WANT_IPC_PARSE_VERSION +#ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION /* On IA-64, we always use the "64-bit version" of the IPC structures. */ # define ipc_parse_version(cmd) IPC_64 #else -- GitLab From fd4b616b0fbb77e3f349e7d60914f2b7c7e39f9c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 30 Jul 2012 14:42:48 -0700 Subject: [PATCH 4680/5711] sysctl: suppress kmemleak messages register_sysctl_table() is a strange function, as it makes internal allocations (a header) to register a sysctl_table. This header is a handle to the table that is created, and can be used to unregister the table. But if the table is permanent and never unregistered, the header acts the same as a static variable. Unfortunately, this allocation of memory that is never expected to be freed fools kmemleak in thinking that we have leaked memory. For those sysctl tables that are never unregistered, and have no pointer referencing them, kmemleak will think that these are memory leaks: unreferenced object 0xffff880079fb9d40 (size 192): comm "swapper/0", pid 0, jiffies 4294667316 (age 12614.152s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x73/0x98 [] kmemleak_alloc_recursive.constprop.42+0x16/0x18 [] __kmalloc+0x107/0x153 [] kzalloc.constprop.8+0xe/0x10 [] __register_sysctl_paths+0xe1/0x160 [] register_sysctl_paths+0x1b/0x1d [] register_sysctl_table+0x18/0x1a [] sysctl_init+0x10/0x14 [] proc_sys_init+0x2f/0x31 [] proc_root_init+0xa5/0xa7 [] start_kernel+0x3d0/0x40a [] x86_64_start_reservations+0xae/0xb2 [] x86_64_start_kernel+0x102/0x111 [] 0xffffffffffffffff The sysctl_base_table used by sysctl itself is one such instance that registers the table to never be unregistered. Use kmemleak_not_leak() to suppress the kmemleak false positive. Signed-off-by: Steven Rostedt Acked-by: Catalin Marinas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sysctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b46f496405e4..97186b99b0e4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1556,7 +1557,10 @@ static struct ctl_table dev_table[] = { int __init sysctl_init(void) { - register_sysctl_table(sysctl_base_table); + struct ctl_table_header *hdr; + + hdr = register_sysctl_table(sysctl_base_table); + kmemleak_not_leak(hdr); return 0; } -- GitLab From 25353b3377d5a75d4b830477bb90a3691155de72 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 30 Jul 2012 14:42:49 -0700 Subject: [PATCH 4681/5711] taskstats: check nla_reserve() return Addresses https://bugzilla.kernel.org/show_bug.cgi?id=44621 Reported-by: Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/taskstats.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index e66046456f4f..d0a32796550f 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -436,6 +436,11 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info) na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, sizeof(struct cgroupstats)); + if (na == NULL) { + rc = -EMSGSIZE; + goto err; + } + stats = nla_data(na); memset(stats, 0, sizeof(*stats)); -- GitLab From 668f06b9fb846ecedb73964ca5dd95ce441707be Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Mon, 30 Jul 2012 14:42:51 -0700 Subject: [PATCH 4682/5711] pps: return PTR_ERR on error in device_create We should return PTR_ERR if the call to the device_create function fails. Without this patch we instead return the value from a successful call to cdev_add if the call to device_create fails. Signed-off-by: Emil Goode Acked-by: Devendra Naga Cc: Alexander Gordeev Cc: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pps/pps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index 98fbe62694d4..e771487132f7 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c @@ -327,8 +327,10 @@ int pps_register_cdev(struct pps_device *pps) } pps->dev = device_create(pps_class, pps->info.dev, devt, pps, "pps%d", pps->id); - if (IS_ERR(pps->dev)) + if (IS_ERR(pps->dev)) { + err = PTR_ERR(pps->dev); goto del_cdev; + } pps->dev->release = pps_device_destruct; -- GitLab From 98c350cda2c14a343d34ea01a3d9c24fea5ec66d Mon Sep 17 00:00:00 2001 From: Justin Lecher Date: Mon, 30 Jul 2012 14:42:53 -0700 Subject: [PATCH 4683/5711] fs: cachefiles: add support for large files in filesystem caching Support the caching of large files. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=31182 Signed-off-by: Justin Lecher Signed-off-by: Suresh Jayaraman Tested-by: Suresh Jayaraman Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/cachefiles/rdwr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index c0353dfac51f..c994691d9445 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -919,7 +919,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) * own time */ path.mnt = cache->mnt; path.dentry = object->backer; - file = dentry_open(&path, O_RDWR, cache->cache_cred); + file = dentry_open(&path, O_RDWR | O_LARGEFILE, cache->cache_cred); if (IS_ERR(file)) { ret = PTR_ERR(file); } else { -- GitLab From f7e1becb078c2b996420a61f2a411ef19335e2da Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Jul 2012 14:42:56 -0700 Subject: [PATCH 4684/5711] include/linux/aio.h: cpp->C conversions Convert init_sync_kiocb() from a nasty macro into a nice C function. The struct assignment trick takes care of zeroing all unmentioned fields. Shrinks fs/read_write.o's .text from 9857 bytes to 9714. Also demacroize is_sync_kiocb() and aio_ring_avail(). The latter fixes an arg-referenced-multiple-times hand grenade. Cc: Junxiao Bi Cc: Mark Fasheh Acked-by: Jeff Moyer Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/aio.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/include/linux/aio.h b/include/linux/aio.h index b1a520ec8b59..31ff6dba4872 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -126,22 +126,20 @@ struct kiocb { struct eventfd_ctx *ki_eventfd; }; -#define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY) -#define init_sync_kiocb(x, filp) \ - do { \ - struct task_struct *tsk = current; \ - (x)->ki_flags = 0; \ - (x)->ki_users = 1; \ - (x)->ki_key = KIOCB_SYNC_KEY; \ - (x)->ki_filp = (filp); \ - (x)->ki_ctx = NULL; \ - (x)->ki_cancel = NULL; \ - (x)->ki_retry = NULL; \ - (x)->ki_dtor = NULL; \ - (x)->ki_obj.tsk = tsk; \ - (x)->ki_user_data = 0; \ - (x)->private = NULL; \ - } while (0) +static inline bool is_sync_kiocb(struct kiocb *kiocb) +{ + return kiocb->ki_key == KIOCB_SYNC_KEY; +} + +static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) +{ + *kiocb = (struct kiocb) { + .ki_users = 1, + .ki_key = KIOCB_SYNC_KEY, + .ki_filp = filp, + .ki_obj.tsk = current, + }; +} #define AIO_RING_MAGIC 0xa10a10a1 #define AIO_RING_COMPAT_FEATURES 1 @@ -161,8 +159,6 @@ struct aio_ring { struct io_event io_events[0]; }; /* 128 bytes + ring size */ -#define aio_ring_avail(info, ring) (((ring)->head + (info)->nr - 1 - (ring)->tail) % (info)->nr) - #define AIO_RING_PAGES 8 struct aio_ring_info { unsigned long mmap_base; @@ -177,6 +173,12 @@ struct aio_ring_info { struct page *internal_pages[AIO_RING_PAGES]; }; +static inline unsigned aio_ring_avail(struct aio_ring_info *info, + struct aio_ring *ring) +{ + return (ring->head + info->nr - 1 - ring->tail) % info->nr; +} + struct kioctx { atomic_t users; int dead; -- GitLab From 65fed8f6f23070b56d0ed3841173ddd410130a89 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 30 Jul 2012 14:42:58 -0700 Subject: [PATCH 4685/5711] resource: make sure requested range is included in the root range When the requested range is outside of the root range the logic in __reserve_region_with_split will cause an infinite recursion which will overflow the stack as seen in the warning bellow. This particular stack overflow was caused by requesting the (100000000-107ffffff) range while the root range was (0-ffffffff). In this case __request_resource would return the whole root range as conflict range (i.e. 0-ffffffff). Then, the logic in __reserve_region_with_split would continue the recursion requesting the new range as (conflict->end+1, end) which incidentally in this case equals the originally requested range. This patch aborts looking for an usable range when the request does not intersect with the root range. When the request partially overlaps with the root range, it ajust the request to fall in the root range and then continues with the new request. When the request is modified or aborted errors and a stack trace are logged to allow catching the errors in the upper layers. [ 5.968374] WARNING: at kernel/sched.c:4129 sub_preempt_count+0x63/0x89() [ 5.975150] Modules linked in: [ 5.978184] Pid: 1, comm: swapper Not tainted 3.0.22-mid27-00004-gb72c817 #46 [ 5.985324] Call Trace: [ 5.987759] [] ? console_unlock+0x17b/0x18d [ 5.992891] [] warn_slowpath_common+0x48/0x5d [ 5.998194] [] ? sub_preempt_count+0x63/0x89 [ 6.003412] [] warn_slowpath_null+0xf/0x13 [ 6.008453] [] sub_preempt_count+0x63/0x89 [ 6.013499] [] _raw_spin_unlock+0x27/0x3f [ 6.018453] [] add_partial+0x36/0x3b [ 6.022973] [] deactivate_slab+0x96/0xb4 [ 6.027842] [] __slab_alloc.isra.54.constprop.63+0x204/0x241 [ 6.034456] [] ? kzalloc.constprop.5+0x29/0x38 [ 6.039842] [] ? kzalloc.constprop.5+0x29/0x38 [ 6.045232] [] kmem_cache_alloc_trace+0x51/0xb0 [ 6.050710] [] ? kzalloc.constprop.5+0x29/0x38 [ 6.056100] [] kzalloc.constprop.5+0x29/0x38 [ 6.061320] [] __reserve_region_with_split+0x1c/0xd1 [ 6.067230] [] __reserve_region_with_split+0xc6/0xd1 ... [ 7.179057] [] __reserve_region_with_split+0xc6/0xd1 [ 7.184970] [] reserve_region_with_split+0x30/0x42 [ 7.190709] [] e820_reserve_resources_late+0xd1/0xe9 [ 7.196623] [] pcibios_resource_survey+0x23/0x2a [ 7.202184] [] pcibios_init+0x23/0x35 [ 7.206789] [] pci_subsys_init+0x3f/0x44 [ 7.211659] [] do_one_initcall+0x72/0x122 [ 7.216615] [] ? pci_legacy_init+0x3d/0x3d [ 7.221659] [] kernel_init+0xa6/0x118 [ 7.226265] [] ? start_kernel+0x334/0x334 [ 7.231223] [] kernel_thread_helper+0x6/0x10 Signed-off-by: Octavian Purdila Signed-off-by: Ram Pai Cc: Jesse Barnes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/resource.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/resource.c b/kernel/resource.c index dc8b47764443..34d45886ee84 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -7,6 +7,8 @@ * Arbitrary resource management. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -791,8 +793,28 @@ void __init reserve_region_with_split(struct resource *root, resource_size_t start, resource_size_t end, const char *name) { + int abort = 0; + write_lock(&resource_lock); - __reserve_region_with_split(root, start, end, name); + if (root->start > start || root->end < end) { + pr_err("requested range [0x%llx-0x%llx] not in root %pr\n", + (unsigned long long)start, (unsigned long long)end, + root); + if (start > root->end || end < root->start) + abort = 1; + else { + if (end > root->end) + end = root->end; + if (start < root->start) + start = root->start; + pr_err("fixing request to [0x%llx-0x%llx]\n", + (unsigned long long)start, + (unsigned long long)end); + } + dump_stack(); + } + if (!abort) + __reserve_region_with_split(root, start, end, name); write_unlock(&resource_lock); } -- GitLab From 1d151c337d79fa3de88654d2514f58fbd916a8e0 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 30 Jul 2012 14:43:00 -0700 Subject: [PATCH 4686/5711] c/r: fcntl: add F_GETOWNER_UIDS option When we restore file descriptors we would like them to look exactly as they were at dumping time. With help of fcntl it's almost possible, the missing snippet is file owners UIDs. To be able to read their values the F_GETOWNER_UIDS is introduced. This option is valid iif CONFIG_CHECKPOINT_RESTORE is turned on, otherwise returning -EINVAL. Signed-off-by: Cyrill Gorcunov Acked-by: "Eric W. Biederman" Cc: "Serge E. Hallyn" Cc: Oleg Nesterov Cc: Pavel Emelyanov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fcntl.c | 29 +++++++++++++++++++++++++++++ include/asm-generic/fcntl.h | 4 ++++ security/selinux/hooks.c | 1 + 3 files changed, 34 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index 81b70e665bf0..887b5ba8c9b5 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -340,6 +341,31 @@ static int f_getown_ex(struct file *filp, unsigned long arg) return ret; } +#ifdef CONFIG_CHECKPOINT_RESTORE +static int f_getowner_uids(struct file *filp, unsigned long arg) +{ + struct user_namespace *user_ns = current_user_ns(); + uid_t * __user dst = (void * __user)arg; + uid_t src[2]; + int err; + + read_lock(&filp->f_owner.lock); + src[0] = from_kuid(user_ns, filp->f_owner.uid); + src[1] = from_kuid(user_ns, filp->f_owner.euid); + read_unlock(&filp->f_owner.lock); + + err = put_user(src[0], &dst[0]); + err |= put_user(src[1], &dst[1]); + + return err; +} +#else +static int f_getowner_uids(struct file *filp, unsigned long arg) +{ + return -EINVAL; +} +#endif + static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, struct file *filp) { @@ -396,6 +422,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_SETOWN_EX: err = f_setown_ex(filp, arg); break; + case F_GETOWNER_UIDS: + err = f_getowner_uids(filp, arg); + break; case F_GETSIG: err = filp->f_owner.signum; break; diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h index 9e5b0356e2bb..a48937d4a5ea 100644 --- a/include/asm-generic/fcntl.h +++ b/include/asm-generic/fcntl.h @@ -120,6 +120,10 @@ #define F_GETOWN_EX 16 #endif +#ifndef F_GETOWNER_UIDS +#define F_GETOWNER_UIDS 17 +#endif + #define F_OWNER_TID 0 #define F_OWNER_PID 1 #define F_OWNER_PGRP 2 diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 94c45a1531a4..ec43760a8a03 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3180,6 +3180,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, case F_GETFL: case F_GETOWN: case F_GETSIG: + case F_GETOWNER_UIDS: /* Just check FD__USE permission */ err = file_has_perm(cred, file, 0); break; -- GitLab From 8d438288145f19f253a82ca71290b44fce79e23f Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:02 -0700 Subject: [PATCH 4687/5711] fault-injection: notifier error injection This patchset provides kernel modules that can be used to test the error handling of notifier call chain failures by injecting artifical errors to the following notifier chain callbacks. * CPU notifier * PM notifier * memory hotplug notifier * powerpc pSeries reconfig notifier Example: Inject CPU offline error (-1 == -EPERM) # cd /sys/kernel/debug/notifier-error-inject/cpu # echo -1 > actions/CPU_DOWN_PREPARE/error # echo 0 > /sys/devices/system/cpu/cpu1/online bash: echo: write error: Operation not permitted The patchset also adds cpu and memory hotplug tests to tools/testing/selftests These tests first do simple online and offline test and then do fault injection tests if notifier error injection module is available. This patch: The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../fault-injection/notifier-error-inject.txt | 99 ++++++++++++++++ lib/Kconfig.debug | 11 ++ lib/Makefile | 1 + lib/notifier-error-inject.c | 112 ++++++++++++++++++ lib/notifier-error-inject.h | 24 ++++ 5 files changed, 247 insertions(+) create mode 100644 Documentation/fault-injection/notifier-error-inject.txt create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h diff --git a/Documentation/fault-injection/notifier-error-inject.txt b/Documentation/fault-injection/notifier-error-inject.txt new file mode 100644 index 000000000000..c83526c364e5 --- /dev/null +++ b/Documentation/fault-injection/notifier-error-inject.txt @@ -0,0 +1,99 @@ +Notifier error injection +======================== + +Notifier error injection provides the ability to inject artifical errors to +specified notifier chain callbacks. It is useful to test the error handling of +notifier call chain failures which is rarely executed. There are kernel +modules that can be used to test the following notifiers. + + * CPU notifier + * PM notifier + * Memory hotplug notifier + * powerpc pSeries reconfig notifier + +CPU notifier error injection module +----------------------------------- +This feature can be used to test the error handling of the CPU notifiers by +injecting artifical errors to CPU notifier chain callbacks. + +If the notifier call chain should be failed with some events notified, write +the error code to debugfs interface +/sys/kernel/debug/notifier-error-inject/cpu/actions//error + +Possible CPU notifier events to be failed are: + + * CPU_UP_PREPARE + * CPU_UP_PREPARE_FROZEN + * CPU_DOWN_PREPARE + * CPU_DOWN_PREPARE_FROZEN + +Example1: Inject CPU offline error (-1 == -EPERM) + + # cd /sys/kernel/debug/notifier-error-inject/cpu + # echo -1 > actions/CPU_DOWN_PREPARE/error + # echo 0 > /sys/devices/system/cpu/cpu1/online + bash: echo: write error: Operation not permitted + +Example2: inject CPU online error (-2 == -ENOENT) + + # echo -2 > actions/CPU_UP_PREPARE/error + # echo 1 > /sys/devices/system/cpu/cpu1/online + bash: echo: write error: No such file or directory + +PM notifier error injection module +---------------------------------- +This feature is controlled through debugfs interface +/sys/kernel/debug/notifier-error-inject/pm/actions//error + +Possible PM notifier events to be failed are: + + * PM_HIBERNATION_PREPARE + * PM_SUSPEND_PREPARE + * PM_RESTORE_PREPARE + +Example: Inject PM suspend error (-12 = -ENOMEM) + + # cd /sys/kernel/debug/notifier-error-inject/pm/ + # echo -12 > actions/PM_SUSPEND_PREPARE/error + # echo mem > /sys/power/state + bash: echo: write error: Cannot allocate memory + +Memory hotplug notifier error injection module +---------------------------------------------- +This feature is controlled through debugfs interface +/sys/kernel/debug/notifier-error-inject/memory/actions//error + +Possible memory notifier events to be failed are: + + * MEM_GOING_ONLINE + * MEM_GOING_OFFLINE + +Example: Inject memory hotplug offline error (-12 == -ENOMEM) + + # cd /sys/kernel/debug/notifier-error-inject/memory + # echo -12 > actions/MEM_GOING_OFFLINE/error + # echo offline > /sys/devices/system/memory/memoryXXX/state + bash: echo: write error: Cannot allocate memory + +powerpc pSeries reconfig notifier error injection module +-------------------------------------------------------- +This feature is controlled through debugfs interface +/sys/kernel/debug/notifier-error-inject/pSeries-reconfig/actions//error + +Possible pSeries reconfig notifier events to be failed are: + + * PSERIES_RECONFIG_ADD + * PSERIES_RECONFIG_REMOVE + * PSERIES_DRCONF_MEM_ADD + * PSERIES_DRCONF_MEM_REMOVE + +For more usage examples +----------------------- +There are tools/testing/selftests using the notifier error injection features +for CPU and memory notifiers. + + * tools/testing/selftests/cpu-hotplug/on-off-test.sh + * tools/testing/selftests/memory-hotplug/on-off-test.sh + +These scripts first do simple online and offline tests and then do fault +injection tests if notifier error injection module is available. diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 4a186508bf8b..bdee91d50a5b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1084,6 +1084,17 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.txt +config NOTIFIER_ERROR_INJECTION + tristate "Notifier error injection" + depends on DEBUG_KERNEL + select DEBUG_FS + help + This option provides the ability to inject artifical errors to + specified notifier chain callbacks. It is useful to test the error + handling of notifier call chain failures. + + Say N if unsure. + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index df663cc05c73..71acfa4489f3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o +obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c new file mode 100644 index 000000000000..44b92cb6224f --- /dev/null +++ b/lib/notifier-error-inject.c @@ -0,0 +1,112 @@ +#include + +#include "notifier-error-inject.h" + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int notifier_err_inject_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct notifier_err_inject *err_inject = + container_of(nb, struct notifier_err_inject, nb); + struct notifier_err_inject_action *action; + + for (action = err_inject->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) + pr_info("Injecting error (%d) to %s\n", err, action->name); + + return notifier_from_errno(err); +} + +struct dentry *notifier_err_inject_dir; +EXPORT_SYMBOL_GPL(notifier_err_inject_dir); + +struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent, + struct notifier_err_inject *err_inject, int priority) +{ + struct notifier_err_inject_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + struct dentry *actions_dir; + + err_inject->nb.notifier_call = notifier_err_inject_callback; + err_inject->nb.priority = priority; + + dir = debugfs_create_dir(name, parent); + if (!dir) + return ERR_PTR(-ENOMEM); + + actions_dir = debugfs_create_dir("actions", dir); + if (!actions_dir) + goto fail; + + for (action = err_inject->actions; action->name; action++) { + struct dentry *action_dir; + + action_dir = debugfs_create_dir(action->name, actions_dir); + if (!action_dir) + goto fail; + + /* + * Create debugfs r/w file containing action->error. If + * notifier call chain is called with action->val, it will + * fail with the error code + */ + if (!debugfs_create_errno("error", mode, action_dir, + &action->error)) + goto fail; + } + return dir; +fail: + debugfs_remove_recursive(dir); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(notifier_err_inject_init); + +static int __init err_inject_init(void) +{ + notifier_err_inject_dir = + debugfs_create_dir("notifier-error-inject", NULL); + + if (!notifier_err_inject_dir) + return -ENOMEM; + + return 0; +} + +static void __exit err_inject_exit(void) +{ + debugfs_remove_recursive(notifier_err_inject_dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("Notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); diff --git a/lib/notifier-error-inject.h b/lib/notifier-error-inject.h new file mode 100644 index 000000000000..99b3b6fc470b --- /dev/null +++ b/lib/notifier-error-inject.h @@ -0,0 +1,24 @@ +#include +#include +#include + +struct notifier_err_inject_action { + unsigned long val; + int error; + const char *name; +}; + +#define NOTIFIER_ERR_INJECT_ACTION(action) \ + .name = #action, .val = (action), + +struct notifier_err_inject { + struct notifier_block nb; + struct notifier_err_inject_action actions[]; + /* The last slot must be terminated with zero sentinel */ +}; + +extern struct dentry *notifier_err_inject_dir; + +extern struct dentry *notifier_err_inject_init(const char *name, + struct dentry *parent, struct notifier_err_inject *err_inject, + int priority); -- GitLab From f5a9f52e2c5654c3d212dbf7e7a169c60876691a Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:03 -0700 Subject: [PATCH 4688/5711] cpu: rewrite cpu-notifier-error-inject module Rewrite existing cpu-notifier-error-inject module to use debugfs based new framework. This change removes cpu_up_prepare_error and cpu_down_prepare_error module parameters which were used to specify error code to be injected. We could keep these module parameters for backward compatibility by module_param_cb but it seems overkill for this module. This provides the ability to inject artifical errors to CPU notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/cpu If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Example1: inject CPU offline error (-1 == -EPERM) # cd /sys/kernel/debug/notifier-error-inject/cpu # echo -1 > actions/CPU_DOWN_PREPARE/error # echo 0 > /sys/devices/system/cpu/cpu1/online bash: echo: write error: Operation not permitted Example2: inject CPU online error (-2 == -ENOENT) # cd /sys/kernel/debug/notifier-error-inject/cpu # echo -2 > actions/CPU_UP_PREPARE/error # echo 1 > /sys/devices/system/cpu/cpu1/online bash: echo: write error: No such file or directory Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 16 +++++++-- lib/cpu-notifier-error-inject.c | 63 +++++++++++++-------------------- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index bdee91d50a5b..20341480bb54 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1097,10 +1097,22 @@ config NOTIFIER_ERROR_INJECTION config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" - depends on HOTPLUG_CPU && DEBUG_KERNEL + depends on HOTPLUG_CPU && NOTIFIER_ERROR_INJECTION help This option provides a kernel module that can be used to test - the error handling of the cpu notifiers + the error handling of the cpu notifiers by injecting artifical + errors to CPU notifier chain callbacks. It is controlled through + debugfs interface under /sys/kernel/debug/notifier-error-inject/cpu + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + Example: Inject CPU offline error (-1 == -EPERM) + + # cd /sys/kernel/debug/notifier-error-inject/cpu + # echo -1 > actions/CPU_DOWN_PREPARE/error + # echo 0 > /sys/devices/system/cpu/cpu1/online + bash: echo: write error: Operation not permitted To compile this code as a module, choose M here: the module will be called cpu-notifier-error-inject. diff --git a/lib/cpu-notifier-error-inject.c b/lib/cpu-notifier-error-inject.c index 4dc20321b0d5..707ca24f7b18 100644 --- a/lib/cpu-notifier-error-inject.c +++ b/lib/cpu-notifier-error-inject.c @@ -1,58 +1,45 @@ #include -#include #include -#include +#include -static int priority; -static int cpu_up_prepare_error; -static int cpu_down_prepare_error; +#include "notifier-error-inject.h" +static int priority; module_param(priority, int, 0); MODULE_PARM_DESC(priority, "specify cpu notifier priority"); -module_param(cpu_up_prepare_error, int, 0644); -MODULE_PARM_DESC(cpu_up_prepare_error, - "specify error code to inject CPU_UP_PREPARE action"); - -module_param(cpu_down_prepare_error, int, 0644); -MODULE_PARM_DESC(cpu_down_prepare_error, - "specify error code to inject CPU_DOWN_PREPARE action"); - -static int err_inject_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - int err = 0; - - switch (action) { - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: - err = cpu_up_prepare_error; - break; - case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - err = cpu_down_prepare_error; - break; +static struct notifier_err_inject cpu_notifier_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(CPU_UP_PREPARE) }, + { NOTIFIER_ERR_INJECT_ACTION(CPU_UP_PREPARE_FROZEN) }, + { NOTIFIER_ERR_INJECT_ACTION(CPU_DOWN_PREPARE) }, + { NOTIFIER_ERR_INJECT_ACTION(CPU_DOWN_PREPARE_FROZEN) }, + {} } - if (err) - printk(KERN_INFO "Injecting error (%d) at cpu notifier\n", err); - - return notifier_from_errno(err); -} - -static struct notifier_block err_inject_cpu_notifier = { - .notifier_call = err_inject_cpu_callback, }; +static struct dentry *dir; + static int err_inject_init(void) { - err_inject_cpu_notifier.priority = priority; + int err; + + dir = notifier_err_inject_init("cpu", notifier_err_inject_dir, + &cpu_notifier_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = register_hotcpu_notifier(&cpu_notifier_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); - return register_hotcpu_notifier(&err_inject_cpu_notifier); + return err; } static void err_inject_exit(void) { - unregister_hotcpu_notifier(&err_inject_cpu_notifier); + unregister_hotcpu_notifier(&cpu_notifier_err_inject.nb); + debugfs_remove_recursive(dir); } module_init(err_inject_init); -- GitLab From 048b9c3549790af21eabd06a5ebdad305e75b1c5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:07 -0700 Subject: [PATCH 4689/5711] PM: PM notifier error injection module This provides the ability to inject artifical errors to PM notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/pm Each of the files in "error" directory represents an event which can be failed and contains the error code. If the notifier call chain should be failed with some events notified, write the error code to the files. If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Example: Inject PM suspend error (-12 = -ENOMEM) # cd /sys/kernel/debug/notifier-error-inject/pm # echo -12 > actions/PM_SUSPEND_PREPARE/error # echo mem > /sys/power/state bash: echo: write error: Cannot allocate memory Signed-off-by: Akinobu Mita Acked-by: "Rafael J. Wysocki" Cc: Pavel Machek Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 24 +++++++++++++++++ lib/Makefile | 1 + lib/pm-notifier-error-inject.c | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 lib/pm-notifier-error-inject.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 20341480bb54..c2024d86fb12 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1119,6 +1119,30 @@ config CPU_NOTIFIER_ERROR_INJECT If unsure, say N. +config PM_NOTIFIER_ERROR_INJECT + tristate "PM notifier error injection module" + depends on PM && NOTIFIER_ERROR_INJECTION + default m if PM_DEBUG + help + This option provides the ability to inject artifical errors to + PM notifier chain callbacks. It is controlled through debugfs + interface /sys/kernel/debug/notifier-error-inject/pm + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + Example: Inject PM suspend error (-12 = -ENOMEM) + + # cd /sys/kernel/debug/notifier-error-inject/pm/ + # echo -12 > actions/PM_SUSPEND_PREPARE/error + # echo mem > /sys/power/state + bash: echo: write error: Cannot allocate memory + + To compile this code as a module, choose M here: the module will + be called pm-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index 71acfa4489f3..c32c66473ba1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o +obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/pm-notifier-error-inject.c b/lib/pm-notifier-error-inject.c new file mode 100644 index 000000000000..c094b2dedc23 --- /dev/null +++ b/lib/pm-notifier-error-inject.c @@ -0,0 +1,49 @@ +#include +#include +#include + +#include "notifier-error-inject.h" + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify PM notifier priority"); + +static struct notifier_err_inject pm_notifier_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(PM_HIBERNATION_PREPARE) }, + { NOTIFIER_ERR_INJECT_ACTION(PM_SUSPEND_PREPARE) }, + { NOTIFIER_ERR_INJECT_ACTION(PM_RESTORE_PREPARE) }, + {} + } +}; + +static struct dentry *dir; + +static int err_inject_init(void) +{ + int err; + + dir = notifier_err_inject_init("pm", notifier_err_inject_dir, + &pm_notifier_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = register_pm_notifier(&pm_notifier_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); + + return err; +} + +static void err_inject_exit(void) +{ + unregister_pm_notifier(&pm_notifier_err_inject.nb); + debugfs_remove_recursive(dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("PM notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); -- GitLab From 9579f5bd31a04e80a87a7b58bd52dff6dc68bc99 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:10 -0700 Subject: [PATCH 4690/5711] memory: memory notifier error injection module This provides the ability to inject artifical errors to memory hotplug notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/memory If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Example: Inject memory hotplug offline error (-12 == -ENOMEM) # cd /sys/kernel/debug/notifier-error-inject/memory # echo -12 > actions/MEM_GOING_OFFLINE/error # echo offline > /sys/devices/system/memory/memoryXXX/state bash: echo: write error: Cannot allocate memory Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 23 ++++++++++++++ lib/Makefile | 1 + lib/memory-notifier-error-inject.c | 48 ++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 lib/memory-notifier-error-inject.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c2024d86fb12..35cfd9eef0e0 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1143,6 +1143,29 @@ config PM_NOTIFIER_ERROR_INJECT If unsure, say N. +config MEMORY_NOTIFIER_ERROR_INJECT + tristate "Memory hotplug notifier error injection module" + depends on MEMORY_HOTPLUG_SPARSE && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + memory hotplug notifier chain callbacks. It is controlled through + debugfs interface under /sys/kernel/debug/notifier-error-inject/memory + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + Example: Inject memory hotplug offline error (-12 == -ENOMEM) + + # cd /sys/kernel/debug/notifier-error-inject/memory + # echo -12 > actions/MEM_GOING_OFFLINE/error + # echo offline > /sys/devices/system/memory/memoryXXX/state + bash: echo: write error: Cannot allocate memory + + To compile this code as a module, choose M here: the module will + be called pSeries-reconfig-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index c32c66473ba1..c34719337d26 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o +obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/memory-notifier-error-inject.c b/lib/memory-notifier-error-inject.c new file mode 100644 index 000000000000..e6239bf0b0df --- /dev/null +++ b/lib/memory-notifier-error-inject.c @@ -0,0 +1,48 @@ +#include +#include +#include + +#include "notifier-error-inject.h" + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify memory notifier priority"); + +static struct notifier_err_inject memory_notifier_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(MEM_GOING_ONLINE) }, + { NOTIFIER_ERR_INJECT_ACTION(MEM_GOING_OFFLINE) }, + {} + } +}; + +static struct dentry *dir; + +static int err_inject_init(void) +{ + int err; + + dir = notifier_err_inject_init("memory", notifier_err_inject_dir, + &memory_notifier_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = register_memory_notifier(&memory_notifier_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); + + return err; +} + +static void err_inject_exit(void) +{ + unregister_memory_notifier(&memory_notifier_err_inject.nb); + debugfs_remove_recursive(dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("memory notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); -- GitLab From 08dfb4ddeeeebdee4f3d5a08a87dc9aa68d26f81 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:13 -0700 Subject: [PATCH 4691/5711] powerpc: pSeries reconfig notifier error injection module This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/pSeries-reconfig If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 17 +++++++ lib/Makefile | 2 + lib/pSeries-reconfig-notifier-error-inject.c | 51 ++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 35cfd9eef0e0..2403a63b5da5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1166,6 +1166,23 @@ config MEMORY_NOTIFIER_ERROR_INJECT If unsure, say N. +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT + tristate "pSeries reconfig notifier error injection module" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/notifier-error-inject/pSeries-reconfig/ + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + To compile this code as a module, choose M here: the module will + be called memory-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index c34719337d26..1054de86ae82 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -94,6 +94,8 @@ obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o +obj-$(CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT) += \ + pSeries-reconfig-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/pSeries-reconfig-notifier-error-inject.c b/lib/pSeries-reconfig-notifier-error-inject.c new file mode 100644 index 000000000000..7f7c98dcd5c4 --- /dev/null +++ b/lib/pSeries-reconfig-notifier-error-inject.c @@ -0,0 +1,51 @@ +#include +#include + +#include + +#include "notifier-error-inject.h" + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify pSeries reconfig notifier priority"); + +static struct notifier_err_inject reconfig_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_REMOVE) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static struct dentry *dir; + +static int err_inject_init(void) +{ + int err; + + dir = notifier_err_inject_init("pSeries-reconfig", + notifier_err_inject_dir, &reconfig_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = pSeries_reconfig_notifier_register(&reconfig_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); + + return err; +} + +static void err_inject_exit(void) +{ + pSeries_reconfig_notifier_unregister(&reconfig_err_inject.nb); + debugfs_remove_recursive(dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("pSeries reconfig notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); -- GitLab From d89dffa976bcd13fd87eb76e02e3b71c3a7868e3 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:17 -0700 Subject: [PATCH 4692/5711] fault-injection: add selftests for cpu and memory hotplug This adds two selftests * tools/testing/selftests/cpu-hotplug/on-off-test.sh is testing script for CPU hotplug 1. Online all hot-pluggable CPUs 2. Offline all hot-pluggable CPUs 3. Online all hot-pluggable CPUs again 4. Exit if cpu-notifier-error-inject.ko is not available 5. Offline all hot-pluggable CPUs in preparation for testing 6. Test CPU hot-add error handling by injecting notifier errors 7. Online all hot-pluggable CPUs in preparation for testing 8. Test CPU hot-remove error handling by injecting notifier errors * tools/testing/selftests/memory-hotplug/on-off-test.sh is doing the similar thing for memory hotplug. 1. Online all hot-pluggable memory 2. Offline 10% of hot-pluggable memory 3. Online all hot-pluggable memory again 4. Exit if memory-notifier-error-inject.ko is not available 5. Offline 10% of hot-pluggable memory in preparation for testing 6. Test memory hot-add error handling by injecting notifier errors 7. Online all hot-pluggable memory in preparation for testing 8. Test memory hot-remove error handling by injecting notifier errors Signed-off-by: Akinobu Mita Suggested-by: Andrew Morton Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg KH Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/testing/selftests/Makefile | 2 +- tools/testing/selftests/cpu-hotplug/Makefile | 6 + .../selftests/cpu-hotplug/on-off-test.sh | 221 +++++++++++++++++ .../testing/selftests/memory-hotplug/Makefile | 6 + .../selftests/memory-hotplug/on-off-test.sh | 230 ++++++++++++++++++ 5 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/cpu-hotplug/Makefile create mode 100644 tools/testing/selftests/cpu-hotplug/on-off-test.sh create mode 100644 tools/testing/selftests/memory-hotplug/Makefile create mode 100644 tools/testing/selftests/memory-hotplug/on-off-test.sh diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index a4162e15c25f..85baf11e2acd 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -1,4 +1,4 @@ -TARGETS = breakpoints kcmp mqueue vm +TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug all: for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile new file mode 100644 index 000000000000..7c9c20ff578a --- /dev/null +++ b/tools/testing/selftests/cpu-hotplug/Makefile @@ -0,0 +1,6 @@ +all: + +run_tests: + ./on-off-test.sh + +clean: diff --git a/tools/testing/selftests/cpu-hotplug/on-off-test.sh b/tools/testing/selftests/cpu-hotplug/on-off-test.sh new file mode 100644 index 000000000000..bdde7cf428bb --- /dev/null +++ b/tools/testing/selftests/cpu-hotplug/on-off-test.sh @@ -0,0 +1,221 @@ +#!/bin/bash + +SYSFS= + +prerequisite() +{ + msg="skip all tests:" + + if [ $UID != 0 ]; then + echo $msg must be run as root >&2 + exit 0 + fi + + SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` + + if [ ! -d "$SYSFS" ]; then + echo $msg sysfs is not mounted >&2 + exit 0 + fi + + if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then + echo $msg cpu hotplug is not supported >&2 + exit 0 + fi +} + +# +# list all hot-pluggable CPUs +# +hotpluggable_cpus() +{ + local state=${1:-.\*} + + for cpu in $SYSFS/devices/system/cpu/cpu*; do + if [ -f $cpu/online ] && grep -q $state $cpu/online; then + echo ${cpu##/*/cpu} + fi + done +} + +hotplaggable_offline_cpus() +{ + hotpluggable_cpus 0 +} + +hotpluggable_online_cpus() +{ + hotpluggable_cpus 1 +} + +cpu_is_online() +{ + grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online +} + +cpu_is_offline() +{ + grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online +} + +online_cpu() +{ + echo 1 > $SYSFS/devices/system/cpu/cpu$1/online +} + +offline_cpu() +{ + echo 0 > $SYSFS/devices/system/cpu/cpu$1/online +} + +online_cpu_expect_success() +{ + local cpu=$1 + + if ! online_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +online_cpu_expect_fail() +{ + local cpu=$1 + + if online_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected online >&2 + fi +} + +offline_cpu_expect_success() +{ + local cpu=$1 + + if ! offline_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +offline_cpu_expect_fail() +{ + local cpu=$1 + + if offline_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +error=-12 +priority=0 + +while getopts e:hp: opt; do + case $opt in + e) + error=$OPTARG + ;; + h) + echo "Usage $0 [ -e errno ] [ -p notifier-priority ]" + exit + ;; + p) + priority=$OPTARG + ;; + esac +done + +if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then + echo "error code must be -4095 <= errno < 0" >&2 + exit 1 +fi + +prerequisite + +# +# Online all hot-pluggable CPUs +# +for cpu in `hotplaggable_offline_cpus`; do + online_cpu_expect_success $cpu +done + +# +# Offline all hot-pluggable CPUs +# +for cpu in `hotpluggable_online_cpus`; do + offline_cpu_expect_success $cpu +done + +# +# Online all hot-pluggable CPUs again +# +for cpu in `hotplaggable_offline_cpus`; do + online_cpu_expect_success $cpu +done + +# +# Test with cpu notifier error injection +# + +DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` +NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu + +prerequisite_extra() +{ + msg="skip extra tests:" + + /sbin/modprobe -q -r cpu-notifier-error-inject + /sbin/modprobe -q cpu-notifier-error-inject priority=$priority + + if [ ! -d "$DEBUGFS" ]; then + echo $msg debugfs is not mounted >&2 + exit 0 + fi + + if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then + echo $msg cpu-notifier-error-inject module is not available >&2 + exit 0 + fi +} + +prerequisite_extra + +# +# Offline all hot-pluggable CPUs +# +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +for cpu in `hotpluggable_online_cpus`; do + offline_cpu_expect_success $cpu +done + +# +# Test CPU hot-add error handling (offline => online) +# +echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error +for cpu in `hotplaggable_offline_cpus`; do + online_cpu_expect_fail $cpu +done + +# +# Online all hot-pluggable CPUs +# +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error +for cpu in `hotplaggable_offline_cpus`; do + online_cpu_expect_success $cpu +done + +# +# Test CPU hot-remove error handling (online => offline) +# +echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +for cpu in `hotpluggable_online_cpus`; do + offline_cpu_expect_fail $cpu +done + +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +/sbin/modprobe -q -r cpu-notifier-error-inject diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile new file mode 100644 index 000000000000..7c9c20ff578a --- /dev/null +++ b/tools/testing/selftests/memory-hotplug/Makefile @@ -0,0 +1,6 @@ +all: + +run_tests: + ./on-off-test.sh + +clean: diff --git a/tools/testing/selftests/memory-hotplug/on-off-test.sh b/tools/testing/selftests/memory-hotplug/on-off-test.sh new file mode 100644 index 000000000000..a2816f631542 --- /dev/null +++ b/tools/testing/selftests/memory-hotplug/on-off-test.sh @@ -0,0 +1,230 @@ +#!/bin/bash + +SYSFS= + +prerequisite() +{ + msg="skip all tests:" + + if [ $UID != 0 ]; then + echo $msg must be run as root >&2 + exit 0 + fi + + SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` + + if [ ! -d "$SYSFS" ]; then + echo $msg sysfs is not mounted >&2 + exit 0 + fi + + if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then + echo $msg memory hotplug is not supported >&2 + exit 0 + fi +} + +# +# list all hot-pluggable memory +# +hotpluggable_memory() +{ + local state=${1:-.\*} + + for memory in $SYSFS/devices/system/memory/memory*; do + if grep -q 1 $memory/removable && + grep -q $state $memory/state; then + echo ${memory##/*/memory} + fi + done +} + +hotplaggable_offline_memory() +{ + hotpluggable_memory offline +} + +hotpluggable_online_memory() +{ + hotpluggable_memory online +} + +memory_is_online() +{ + grep -q online $SYSFS/devices/system/memory/memory$1/state +} + +memory_is_offline() +{ + grep -q offline $SYSFS/devices/system/memory/memory$1/state +} + +online_memory() +{ + echo online > $SYSFS/devices/system/memory/memory$1/state +} + +offline_memory() +{ + echo offline > $SYSFS/devices/system/memory/memory$1/state +} + +online_memory_expect_success() +{ + local memory=$1 + + if ! online_memory $memory; then + echo $FUNCNAME $memory: unexpected fail >&2 + elif ! memory_is_online $memory; then + echo $FUNCNAME $memory: unexpected offline >&2 + fi +} + +online_memory_expect_fail() +{ + local memory=$1 + + if online_memory $memory 2> /dev/null; then + echo $FUNCNAME $memory: unexpected success >&2 + elif ! memory_is_offline $memory; then + echo $FUNCNAME $memory: unexpected online >&2 + fi +} + +offline_memory_expect_success() +{ + local memory=$1 + + if ! offline_memory $memory; then + echo $FUNCNAME $memory: unexpected fail >&2 + elif ! memory_is_offline $memory; then + echo $FUNCNAME $memory: unexpected offline >&2 + fi +} + +offline_memory_expect_fail() +{ + local memory=$1 + + if offline_memory $memory 2> /dev/null; then + echo $FUNCNAME $memory: unexpected success >&2 + elif ! memory_is_online $memory; then + echo $FUNCNAME $memory: unexpected offline >&2 + fi +} + +error=-12 +priority=0 +ratio=10 + +while getopts e:hp:r: opt; do + case $opt in + e) + error=$OPTARG + ;; + h) + echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]" + exit + ;; + p) + priority=$OPTARG + ;; + r) + ratio=$OPTARG + ;; + esac +done + +if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then + echo "error code must be -4095 <= errno < 0" >&2 + exit 1 +fi + +prerequisite + +# +# Online all hot-pluggable memory +# +for memory in `hotplaggable_offline_memory`; do + online_memory_expect_success $memory +done + +# +# Offline $ratio percent of hot-pluggable memory +# +for memory in `hotpluggable_online_memory`; do + if [ $((RANDOM % 100)) -lt $ratio ]; then + offline_memory_expect_success $memory + fi +done + +# +# Online all hot-pluggable memory again +# +for memory in `hotplaggable_offline_memory`; do + online_memory_expect_success $memory +done + +# +# Test with memory notifier error injection +# + +DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` +NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory + +prerequisite_extra() +{ + msg="skip extra tests:" + + /sbin/modprobe -q -r memory-notifier-error-inject + /sbin/modprobe -q memory-notifier-error-inject priority=$priority + + if [ ! -d "$DEBUGFS" ]; then + echo $msg debugfs is not mounted >&2 + exit 0 + fi + + if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then + echo $msg memory-notifier-error-inject module is not available >&2 + exit 0 + fi +} + +prerequisite_extra + +# +# Offline $ratio percent of hot-pluggable memory +# +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error +for memory in `hotpluggable_online_memory`; do + if [ $((RANDOM % 100)) -lt $ratio ]; then + offline_memory_expect_success $memory + fi +done + +# +# Test memory hot-add error handling (offline => online) +# +echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error +for memory in `hotplaggable_offline_memory`; do + online_memory_expect_fail $memory +done + +# +# Online all hot-pluggable memory +# +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error +for memory in `hotplaggable_offline_memory`; do + online_memory_expect_success $memory +done + +# +# Test memory hot-remove error handling (online => offline) +# +echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error +for memory in `hotpluggable_online_memory`; do + offline_memory_expect_fail $memory +done + +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error +/sbin/modprobe -q -r memory-notifier-error-inject -- GitLab From c24aa64d169b7224f1a5bc6a4b1365da37ce861b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Jul 2012 14:43:20 -0700 Subject: [PATCH 4693/5711] fault-injection: add tool to run command with failslab or fail_page_alloc This adds tools/testing/fault-injection/failcmd.sh to run a command while injecting slab/page allocation failures via fault injection. Example: Run a command "make -C tools/testing/selftests/ run_tests" with injecting slab allocation failure. # ./tools/testing/fault-injection/failcmd.sh \ -- make -C tools/testing/selftests/ run_tests Same as above except to specify 100 times failures at most instead of one time at most by default. # ./tools/testing/fault-injection/failcmd.sh --times=100 \ -- make -C tools/testing/selftests/ run_tests Same as above except to inject page allocation failure instead of slab allocation failure. # env FAILCMD_TYPE=fail_page_alloc \ ./tools/testing/fault-injection/failcmd.sh --times=100 \ -- make -C tools/testing/selftests/ run_tests Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../fault-injection/fault-injection.txt | 27 +++ tools/testing/fault-injection/failcmd.sh | 219 ++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 tools/testing/fault-injection/failcmd.sh diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt index ba4be8b77093..4cf1a2a6bd72 100644 --- a/Documentation/fault-injection/fault-injection.txt +++ b/Documentation/fault-injection/fault-injection.txt @@ -240,3 +240,30 @@ trap "echo 0 > /sys/kernel/debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT echo "Injecting errors into the module $module... (interrupt to stop)" sleep 1000000 +Tool to run command with failslab or fail_page_alloc +---------------------------------------------------- +In order to make it easier to accomplish the tasks mentioned above, we can use +tools/testing/fault-injection/failcmd.sh. Please run a command +"./tools/testing/fault-injection/failcmd.sh --help" for more information and +see the following examples. + +Examples: + +Run a command "make -C tools/testing/selftests/ run_tests" with injecting slab +allocation failure. + + # ./tools/testing/fault-injection/failcmd.sh \ + -- make -C tools/testing/selftests/ run_tests + +Same as above except to specify 100 times failures at most instead of one time +at most by default. + + # ./tools/testing/fault-injection/failcmd.sh --times=100 \ + -- make -C tools/testing/selftests/ run_tests + +Same as above except to inject page allocation failure instead of slab +allocation failure. + + # env FAILCMD_TYPE=fail_page_alloc \ + ./tools/testing/fault-injection/failcmd.sh --times=100 \ + -- make -C tools/testing/selftests/ run_tests diff --git a/tools/testing/fault-injection/failcmd.sh b/tools/testing/fault-injection/failcmd.sh new file mode 100644 index 000000000000..1776e924b202 --- /dev/null +++ b/tools/testing/fault-injection/failcmd.sh @@ -0,0 +1,219 @@ +#!/bin/bash +# +# NAME +# failcmd.sh - run a command with injecting slab/page allocation failures +# +# SYNOPSIS +# failcmd.sh --help +# failcmd.sh [] command [arguments] +# +# DESCRIPTION +# Run command with injecting slab/page allocation failures by fault +# injection. +# +# NOTE: you need to run this script as root. +# + +usage() +{ + cat >&2 <&2 + exit 1 +fi + +DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3}'` + +if [ ! -d "$DEBUGFS" ]; then + echo debugfs is not mounted >&2 + exit 1 +fi + +FAILCMD_TYPE=${FAILCMD_TYPE:-failslab} +FAULTATTR=$DEBUGFS/$FAILCMD_TYPE + +if [ ! -d $FAULTATTR ]; then + echo $FAILCMD_TYPE is not available >&2 + exit 1 +fi + +LONGOPTS=probability:,interval:,times:,space:,verbose:,task-filter: +LONGOPTS=$LONGOPTS,stacktrace-depth:,require-start:,require-end: +LONGOPTS=$LONGOPTS,reject-start:,reject-end:,oom-kill-allocating-task:,help + +if [ $FAILCMD_TYPE = failslab ]; then + LONGOPTS=$LONGOPTS,ignore-gfp-wait:,cache-filter: +elif [ $FAILCMD_TYPE = fail_page_alloc ]; then + LONGOPTS=$LONGOPTS,ignore-gfp-wait:,ignore-gfp-highmem:,min-order: +fi + +TEMP=`getopt -o p:i:t:s:v:h --long $LONGOPTS -n 'failcmd.sh' -- "$@"` + +if [ $? != 0 ]; then + usage + exit 1 +fi + +eval set -- "$TEMP" + +fault_attr_default() +{ + echo N > $FAULTATTR/task-filter + echo 0 > $FAULTATTR/probability + echo 1 > $FAULTATTR/times +} + +fault_attr_default + +oom_kill_allocating_task_saved=`cat /proc/sys/vm/oom_kill_allocating_task` + +restore_values() +{ + fault_attr_default + echo $oom_kill_allocating_task_saved \ + > /proc/sys/vm/oom_kill_allocating_task +} + +# +# Default options +# +declare -i oom_kill_allocating_task=1 +declare task_filter=Y +declare -i probability=1 +declare -i times=1 + +while true; do + case "$1" in + -p|--probability) + probability=$2 + shift 2 + ;; + -i|--interval) + echo $2 > $FAULTATTR/interval + shift 2 + ;; + -t|--times) + times=$2 + shift 2 + ;; + -s|--space) + echo $2 > $FAULTATTR/space + shift 2 + ;; + -v|--verbose) + echo $2 > $FAULTATTR/verbose + shift 2 + ;; + --task-filter) + task_filter=$2 + shift 2 + ;; + --stacktrace-depth) + echo $2 > $FAULTATTR/stacktrace-depth + shift 2 + ;; + --require-start) + echo $2 > $FAULTATTR/require-start + shift 2 + ;; + --require-end) + echo $2 > $FAULTATTR/require-end + shift 2 + ;; + --reject-start) + echo $2 > $FAULTATTR/reject-start + shift 2 + ;; + --reject-end) + echo $2 > $FAULTATTR/reject-end + shift 2 + ;; + --oom-kill-allocating-task) + oom_kill_allocating_task=$2 + shift 2 + ;; + --ignore-gfp-wait) + echo $2 > $FAULTATTR/ignore-gfp-wait + shift 2 + ;; + --cache-filter) + echo $2 > $FAULTATTR/cache_filter + shift 2 + ;; + --ignore-gfp-highmem) + echo $2 > $FAULTATTR/ignore-gfp-highmem + shift 2 + ;; + --min-order) + echo $2 > $FAULTATTR/min-order + shift 2 + ;; + -h|--help) + usage + exit 0 + shift + ;; + --) + shift + break + ;; + esac +done + +[ -z "$@" ] && exit 0 + +echo $oom_kill_allocating_task > /proc/sys/vm/oom_kill_allocating_task +echo $task_filter > $FAULTATTR/task-filter +echo $probability > $FAULTATTR/probability +echo $times > $FAULTATTR/times + +trap "restore_values" SIGINT SIGTERM EXIT + +cmd="echo 1 > /proc/self/make-it-fail && exec $@" +bash -c "$cmd" -- GitLab From e04f228335bde305d2833e40382ed37fc36f9efe Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Mon, 30 Jul 2012 14:43:22 -0700 Subject: [PATCH 4694/5711] lib/scatterlist: do not re-write gfp_flags in __sg_alloc_table() We are seeing a lot of sg_alloc_table allocation failures using the new drm prime infrastructure. We isolated the cause to code in __sg_alloc_table that was re-writing the gfp_flags. There is a comment in the code that suggest that there is an assumption about the allocation coming from a memory pool. This was likely true when sg lists were primarily used for disk I/O. Signed-off-by: Mandeep Singh Baines Cc: Jens Axboe Cc: Paul Gortmaker Cc: Cong Wang Cc: Daniel Vetter Cc: Rob Clark Cc: Sumit Semwal Cc: Inki Dae Cc: Dave Airlie Cc: Sonny Rao Cc: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/scatterlist.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 6096e89bee55..d09bdd8b40ce 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -279,14 +279,6 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, if (!left) sg_mark_end(&sg[sg_size - 1]); - /* - * only really needed for mempool backed sg allocations (like - * SCSI), a possible improvement here would be to pass the - * table pointer into the allocator and let that clear these - * flags - */ - gfp_mask &= ~__GFP_WAIT; - gfp_mask |= __GFP_HIGH; prv = sg; } while (left); -- GitLab From 086ff4b3a7fb9cdf41e6a5d0ccd99b86d84633a1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 30 Jul 2012 14:43:24 -0700 Subject: [PATCH 4695/5711] drivers/misc/lkdtm.c: fix missing allocation failure check Addresses https://bugzilla.kernel.org/show_bug.cgi?id=44691 Reported-by: Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/lkdtm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 28adefe70f96..08aad69c8da4 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -477,6 +477,8 @@ static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, int i, n, out; buf = (char *)__get_free_page(GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; n = snprintf(buf, PAGE_SIZE, "Available crash types:\n"); for (i = 0; i < ARRAY_SIZE(cp_type); i++) -- GitLab From 1a3acd3d7f1f7ba1037cfd8c04a9159988f70079 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 02:43:48 -0300 Subject: [PATCH 4696/5711] [media] staging/media/dt3155v4l: use module_pci_driver macro the driver duplicates the module_pci_driver code, remove the duplicate code and use the module_pci_driver macro. Signed-off-by: Devendra Naga Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/dt3155v4l/dt3155v4l.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c index c365cdf714ea..ebe5a27c06f5 100644 --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c @@ -971,20 +971,7 @@ static struct pci_driver pci_driver = { .remove = __devexit_p(dt3155_remove), }; -static int __init -dt3155_init_module(void) -{ - return pci_register_driver(&pci_driver); -} - -static void __exit -dt3155_exit_module(void) -{ - pci_unregister_driver(&pci_driver); -} - -module_init(dt3155_init_module); -module_exit(dt3155_exit_module); +module_pci_driver(pci_driver); MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber"); MODULE_AUTHOR("Marin Mitov "); -- GitLab From b1f093ac6807a264100b24b1a4939cff6e35c144 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 10 Jul 2012 02:45:26 -0300 Subject: [PATCH 4697/5711] [media] staging/media/solo6x10: use module_pci_driver macro the driver duplicates the module_pci_driver code, how? module_pci_driver is used for those drivers whose init and exit paths does only register and unregister to pci API and nothing else. so use the module_pci_driver macro instead Signed-off-by: Devendra Naga Acked-by: Ismael Luceno Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/solo6x10/core.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c index d2fd842e37cf..3ee9b125797f 100644 --- a/drivers/staging/media/solo6x10/core.c +++ b/drivers/staging/media/solo6x10/core.c @@ -318,15 +318,4 @@ static struct pci_driver solo_pci_driver = { .remove = solo_pci_remove, }; -static int __init solo_module_init(void) -{ - return pci_register_driver(&solo_pci_driver); -} - -static void __exit solo_module_exit(void) -{ - pci_unregister_driver(&solo_pci_driver); -} - -module_init(solo_module_init); -module_exit(solo_module_exit); +module_pci_driver(solo_pci_driver); -- GitLab From a4de5f058c56a3cc72dc31dabc548eab100e3d2d Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 11 Jul 2012 18:53:28 -0300 Subject: [PATCH 4698/5711] [media] mceusb: Add Twisted Melon USB IDs Add USB identifiers for MCE compatible I/R transceivers from Twisted Melon. Signed-off-by: Mark Lord Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 84e06d3aa696..b7d3588fe87a 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -199,6 +199,7 @@ static bool debug; #define VENDOR_REALTEK 0x0bda #define VENDOR_TIVO 0x105a #define VENDOR_CONEXANT 0x0572 +#define VENDOR_TWISTEDMELON 0x2596 enum mceusb_model_type { MCE_GEN2 = 0, /* Most boards */ @@ -391,6 +392,12 @@ static struct usb_device_id mceusb_dev_table[] = { /* Conexant Hybrid TV RDU253S Polaris */ { USB_DEVICE(VENDOR_CONEXANT, 0x58a5), .driver_info = CX_HYBRID_TV }, + /* Twisted Melon Inc. - Manta Mini Receiver */ + { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8008) }, + /* Twisted Melon Inc. - Manta Pico Receiver */ + { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8016) }, + /* Twisted Melon Inc. - Manta Transceiver */ + { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8042) }, /* Terminating entry */ { } }; -- GitLab From caea33da898e4e14f0ba58173e3b7689981d2c0b Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Fri, 20 Jul 2012 15:57:48 +0400 Subject: [PATCH 4699/5711] SUNRPC: return negative value in case rpcbind client creation error Without this patch kernel will panic on LockD start, because lockd_up() checks lockd_up_net() result for negative value. From my pow it's better to return negative value from rpcbind routines instead of replacing all such checks like in lockd_up(). Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 3.0] --- net/sunrpc/rpcb_clnt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 92509ffe15fc..a70acae496e4 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -251,7 +251,7 @@ static int rpcb_create_local_unix(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create AF_LOCAL rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } @@ -298,7 +298,7 @@ static int rpcb_create_local_net(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create local rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } -- GitLab From 26ddcbcca3057125a0e5f3901b06439a20869640 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Jul 2012 12:06:24 -0300 Subject: [PATCH 4700/5711] [media] Use a named union in struct v4l2_ioctl_info Hi Mauro, struct v4l2_ioctl_info uses an anonymous union, which is initialized in the v4l2_ioctls table. Unfortunately gcc < 4.6 uses a non-standard syntax for that, so trying to compile v4l2-ioctl.c with an older gcc will fail. It is possible to work around this by testing the gcc version, but in this case it is easier to make the union named since it is used in only a few places. Signed-off-by: Hans Verkuil Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 0f54f8efe66b..c3b7b5f59b32 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1891,7 +1891,7 @@ struct v4l2_ioctl_info { u32 offset; int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *p); - }; + } u; void (*debug)(const void *arg, bool write_only); }; @@ -1916,7 +1916,7 @@ struct v4l2_ioctl_info { .ioctl = _ioctl, \ .flags = _flags | INFO_FL_STD, \ .name = #_ioctl, \ - .offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ + .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ .debug = _debug, \ } @@ -1925,7 +1925,7 @@ struct v4l2_ioctl_info { .ioctl = _ioctl, \ .flags = _flags | INFO_FL_FUNC, \ .name = #_ioctl, \ - .func = _func, \ + .u.func = _func, \ .debug = _debug, \ } @@ -2124,11 +2124,11 @@ static long __video_do_ioctl(struct file *file, if (info->flags & INFO_FL_STD) { typedef int (*vidioc_op)(struct file *file, void *fh, void *p); const void *p = vfd->ioctl_ops; - const vidioc_op *vidioc = p + info->offset; + const vidioc_op *vidioc = p + info->u.offset; ret = (*vidioc)(file, fh, arg); } else if (info->flags & INFO_FL_FUNC) { - ret = info->func(ops, file, fh, arg); + ret = info->u.func(ops, file, fh, arg); } else if (!ops->vidioc_default) { ret = -ENOTTY; } else { -- GitLab From 0208c15e5c639ff08b9767fee907a99bcc94b2f5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 15 Jul 2012 05:25:22 -0300 Subject: [PATCH 4701/5711] [media] drivers/media/dvb/siano/smscoreapi.c: use list_for_each_entry Use list_for_each_entry and perform some other induced simplifications. The semantic match that finds the opportunity for this reorganization is as follows: (http://coccinelle.lip6.fr/) // @@ struct list_head *pos; struct list_head *head; statement S; @@ *for (pos = (head)->next; pos != (head); pos = pos->next) S // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smscoreapi.c | 39 ++++++++++++---------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index 7331e8450d1a..9cc55546cc30 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -276,16 +276,13 @@ static void smscore_notify_clients(struct smscore_device_t *coredev) static int smscore_notify_callbacks(struct smscore_device_t *coredev, struct device *device, int arrival) { - struct list_head *next, *first; + struct smscore_device_notifyee_t *elem; int rc = 0; /* note: must be called under g_deviceslock */ - first = &g_smscore_notifyees; - - for (next = first->next; next != first; next = next->next) { - rc = ((struct smscore_device_notifyee_t *) next)-> - hotplug(coredev, device, arrival); + list_for_each_entry(elem, &g_smscore_notifyees, entry) { + rc = elem->hotplug(coredev, device, arrival); if (rc < 0) break; } @@ -940,29 +937,25 @@ static struct smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, int data_type, int id) { - struct smscore_client_t *client = NULL; - struct list_head *next, *first; + struct list_head *first; + struct smscore_client_t *client; unsigned long flags; - struct list_head *firstid, *nextid; - + struct list_head *firstid; + struct smscore_idlist_t *client_id; spin_lock_irqsave(&coredev->clientslock, flags); first = &coredev->clients; - for (next = first->next; - (next != first) && !client; - next = next->next) { - firstid = &((struct smscore_client_t *)next)->idlist; - for (nextid = firstid->next; - nextid != firstid; - nextid = nextid->next) { - if ((((struct smscore_idlist_t *)nextid)->id == id) && - (((struct smscore_idlist_t *)nextid)->data_type == data_type || - (((struct smscore_idlist_t *)nextid)->data_type == 0))) { - client = (struct smscore_client_t *) next; - break; - } + list_for_each_entry(client, first, entry) { + firstid = &client->idlist; + list_for_each_entry(client_id, firstid, entry) { + if ((client_id->id == id) && + (client_id->data_type == data_type || + (client_id->data_type == 0))) + goto found; } } + client = NULL; +found: spin_unlock_irqrestore(&coredev->clientslock, flags); return client; } -- GitLab From 6ac454aa98be6b9d5ead482263d37dd92cbcb0eb Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 15 Jul 2012 13:31:31 -0300 Subject: [PATCH 4702/5711] [media] Minor cleanups for MCE USB Signed-off-by: Sean Young Cc: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index b7d3588fe87a..f38d9a8c6880 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -417,14 +417,12 @@ struct mceusb_dev { /* usb */ struct usb_device *usbdev; struct urb *urb_in; - struct usb_endpoint_descriptor *usb_ep_in; struct usb_endpoint_descriptor *usb_ep_out; /* buffers and dma */ unsigned char *buf_in; unsigned int len_in; dma_addr_t dma_in; - dma_addr_t dma_out; enum { CMD_HEADER = 0, @@ -693,7 +691,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem); } -static void mce_async_callback(struct urb *urb, struct pt_regs *regs) +static void mce_async_callback(struct urb *urb) { struct mceusb_dev *ir; int len; @@ -740,7 +738,7 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, pipe = usb_sndintpipe(ir->usbdev, ir->usb_ep_out->bEndpointAddress); usb_fill_int_urb(async_urb, ir->usbdev, pipe, - async_buf, size, (usb_complete_t)mce_async_callback, + async_buf, size, mce_async_callback, ir, ir->usb_ep_out->bInterval); memcpy(async_buf, data, size); @@ -1038,7 +1036,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) ir_raw_event_handle(ir->rc); } -static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) +static void mceusb_dev_recv(struct urb *urb) { struct mceusb_dev *ir; int buf_len; @@ -1338,7 +1336,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ir->model = model; /* Saving usb interface data for use by the transmitter routine */ - ir->usb_ep_in = ep_in; ir->usb_ep_out = ep_out; if (dev->descriptor.iManufacturer @@ -1356,8 +1353,8 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, goto rc_dev_fail; /* wire up inbound data handler */ - usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, - maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); + usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, + mceusb_dev_recv, ir, ep_in->bInterval); ir->urb_in->transfer_dma = ir->dma_in; ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -- GitLab From 26ff63137c45886169ed102bddd6e90d6c27f00d Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 15 Jul 2012 13:31:00 -0300 Subject: [PATCH 4703/5711] [media] Add support for the IguanaWorks USB IR Transceiver Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 11 + drivers/media/rc/Makefile | 1 + drivers/media/rc/iguanair.c | 639 ++++++++++++++++++++++++++++++++++++ 3 files changed, 651 insertions(+) create mode 100644 drivers/media/rc/iguanair.c diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 908ef70430e9..5180390be7ab 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -259,6 +259,17 @@ config IR_WINBOND_CIR To compile this driver as a module, choose M here: the module will be called winbond_cir. +config IR_IGUANA + tristate "IguanaWorks USB IR Transceiver" + depends on RC_CORE + select USB + ---help--- + Say Y here if you want to use the IgaunaWorks USB IR Transceiver. + Both infrared receive and send are supported. + + To compile this driver as a module, choose M here: the module will + be called iguanair. + config RC_LOOPBACK tristate "Remote Control Loopback Driver" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 29f364f88a94..f871d1986c21 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o +obj-$(CONFIG_IR_IGUANA) += iguanair.o diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c new file mode 100644 index 000000000000..5e2eaf8ba73e --- /dev/null +++ b/drivers/media/rc/iguanair.c @@ -0,0 +1,639 @@ +/* + * IguanaWorks USB IR Transceiver support + * + * Copyright (C) 2012 Sean Young + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "iguanair" + +struct iguanair { + struct rc_dev *rc; + + struct device *dev; + struct usb_device *udev; + + int pipe_in, pipe_out; + uint8_t bufsize; + uint8_t version[2]; + + struct mutex lock; + + /* receiver support */ + bool receiver_on; + dma_addr_t dma_in; + uint8_t *buf_in; + struct urb *urb_in; + struct completion completion; + + /* transmit support */ + bool tx_overflow; + uint32_t carrier; + uint8_t cycle_overhead; + uint8_t channels; + uint8_t busy4; + uint8_t busy7; + + char name[64]; + char phys[64]; +}; + +#define CMD_GET_VERSION 0x01 +#define CMD_GET_BUFSIZE 0x11 +#define CMD_GET_FEATURES 0x10 +#define CMD_SEND 0x15 +#define CMD_EXECUTE 0x1f +#define CMD_RX_OVERFLOW 0x31 +#define CMD_TX_OVERFLOW 0x32 +#define CMD_RECEIVER_ON 0x12 +#define CMD_RECEIVER_OFF 0x14 + +#define DIR_IN 0xdc +#define DIR_OUT 0xcd + +#define MAX_PACKET_SIZE 8u +#define TIMEOUT 1000 + +struct packet { + uint16_t start; + uint8_t direction; + uint8_t cmd; +}; + +struct response_packet { + struct packet header; + uint8_t data[4]; +}; + +struct send_packet { + struct packet header; + uint8_t length; + uint8_t channels; + uint8_t busy7; + uint8_t busy4; + uint8_t payload[0]; +}; + +static void process_ir_data(struct iguanair *ir, unsigned len) +{ + if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) { + switch (ir->buf_in[3]) { + case CMD_TX_OVERFLOW: + ir->tx_overflow = true; + case CMD_RECEIVER_OFF: + case CMD_RECEIVER_ON: + case CMD_SEND: + complete(&ir->completion); + break; + case CMD_RX_OVERFLOW: + dev_warn(ir->dev, "receive overflow\n"); + break; + default: + dev_warn(ir->dev, "control code %02x received\n", + ir->buf_in[3]); + break; + } + } else if (len >= 7) { + DEFINE_IR_RAW_EVENT(rawir); + unsigned i; + + init_ir_raw_event(&rawir); + + for (i = 0; i < 7; i++) { + if (ir->buf_in[i] == 0x80) { + rawir.pulse = false; + rawir.duration = US_TO_NS(21845); + } else { + rawir.pulse = (ir->buf_in[i] & 0x80) == 0; + rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) * + 21330; + } + + ir_raw_event_store_with_filter(ir->rc, &rawir); + } + + ir_raw_event_handle(ir->rc); + } +} + +static void iguanair_rx(struct urb *urb) +{ + struct iguanair *ir; + + if (!urb) + return; + + ir = urb->context; + if (!ir) { + usb_unlink_urb(urb); + return; + } + + switch (urb->status) { + case 0: + process_ir_data(ir, urb->actual_length); + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; + case -EPIPE: + default: + dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); + break; + } + + usb_submit_urb(urb, GFP_ATOMIC); +} + +static int iguanair_send(struct iguanair *ir, void *data, unsigned size, + struct response_packet *response, unsigned *res_len) +{ + unsigned offset, len; + int rc, transferred; + + for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) { + len = min(size - offset, MAX_PACKET_SIZE); + + if (ir->tx_overflow) + return -EOVERFLOW; + + rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset, + len, &transferred, TIMEOUT); + if (rc) + return rc; + + if (transferred != len) + return -EIO; + } + + if (response) { + rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response, + sizeof(*response), res_len, TIMEOUT); + } + + return rc; +} + +static int iguanair_get_features(struct iguanair *ir) +{ + struct packet packet; + struct response_packet response; + int rc, len; + + packet.start = 0; + packet.direction = DIR_OUT; + packet.cmd = CMD_GET_VERSION; + + rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + if (rc) { + dev_info(ir->dev, "failed to get version\n"); + goto out; + } + + if (len != 6) { + dev_info(ir->dev, "failed to get version\n"); + rc = -EIO; + goto out; + } + + ir->version[0] = response.data[0]; + ir->version[1] = response.data[1]; + ir->bufsize = 150; + ir->cycle_overhead = 65; + + packet.cmd = CMD_GET_BUFSIZE; + + rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + if (rc) { + dev_info(ir->dev, "failed to get buffer size\n"); + goto out; + } + + if (len != 5) { + dev_info(ir->dev, "failed to get buffer size\n"); + rc = -EIO; + goto out; + } + + ir->bufsize = response.data[0]; + + if (ir->version[0] == 0 || ir->version[1] == 0) + goto out; + + packet.cmd = CMD_GET_FEATURES; + + rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + if (rc) { + dev_info(ir->dev, "failed to get features\n"); + goto out; + } + + if (len < 5) { + dev_info(ir->dev, "failed to get features\n"); + rc = -EIO; + goto out; + } + + if (len > 5 && ir->version[0] >= 4) + ir->cycle_overhead = response.data[1]; + +out: + return rc; +} + +static int iguanair_receiver(struct iguanair *ir, bool enable) +{ + struct packet packet = { 0, DIR_OUT, enable ? + CMD_RECEIVER_ON : CMD_RECEIVER_OFF }; + int rc; + + INIT_COMPLETION(ir->completion); + + rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL); + if (rc) + return rc; + + wait_for_completion_timeout(&ir->completion, TIMEOUT); + + return 0; +} + +/* + * The iguana ir creates the carrier by busy spinning after each pulse or + * space. This is counted in CPU cycles, with the CPU running at 24MHz. It is + * broken down into 7-cycles and 4-cyles delays, with a preference for + * 4-cycle delays. + */ +static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier) +{ + struct iguanair *ir = dev->priv; + + if (carrier < 25000 || carrier > 150000) + return -EINVAL; + + mutex_lock(&ir->lock); + + if (carrier != ir->carrier) { + uint32_t cycles, fours, sevens; + + ir->carrier = carrier; + + cycles = DIV_ROUND_CLOSEST(24000000, carrier * 2) - + ir->cycle_overhead; + + /* make up the the remainer of 4-cycle blocks */ + switch (cycles & 3) { + case 0: + sevens = 0; + break; + case 1: + sevens = 3; + break; + case 2: + sevens = 2; + break; + case 3: + sevens = 1; + break; + } + + fours = (cycles - sevens * 7) / 4; + + /* magic happens here */ + ir->busy7 = (4 - sevens) * 2; + ir->busy4 = 110 - fours; + } + + mutex_unlock(&ir->lock); + + return carrier; +} + +static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask) +{ + struct iguanair *ir = dev->priv; + + if (mask > 15) + return 4; + + mutex_lock(&ir->lock); + ir->channels = mask; + mutex_unlock(&ir->lock); + + return 0; +} + +static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) +{ + struct iguanair *ir = dev->priv; + uint8_t space, *payload; + unsigned i, size, rc; + struct send_packet *packet; + + mutex_lock(&ir->lock); + + /* convert from us to carrier periods */ + for (i = size = 0; i < count; i++) { + txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); + size += (txbuf[i] + 126) / 127; + } + + packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL); + if (!packet) { + rc = -ENOMEM; + goto out; + } + + if (size > ir->bufsize) { + rc = -E2BIG; + goto out; + } + + packet->header.start = 0; + packet->header.direction = DIR_OUT; + packet->header.cmd = CMD_SEND; + packet->length = size; + packet->channels = ir->channels << 4; + packet->busy7 = ir->busy7; + packet->busy4 = ir->busy4; + + space = 0; + payload = packet->payload; + + for (i = 0; i < count; i++) { + unsigned periods = txbuf[i]; + + while (periods > 127) { + *payload++ = 127 | space; + periods -= 127; + } + + *payload++ = periods | space; + space ^= 0x80; + } + + if (ir->receiver_on) { + rc = iguanair_receiver(ir, false); + if (rc) { + dev_warn(ir->dev, "disable receiver before transmit failed\n"); + goto out; + } + } + + ir->tx_overflow = false; + + INIT_COMPLETION(ir->completion); + + rc = iguanair_send(ir, packet, size + 8, NULL, NULL); + + if (rc == 0) { + wait_for_completion_timeout(&ir->completion, TIMEOUT); + if (ir->tx_overflow) + rc = -EOVERFLOW; + } + + ir->tx_overflow = false; + + if (ir->receiver_on) { + if (iguanair_receiver(ir, true)) + dev_warn(ir->dev, "re-enable receiver after transmit failed\n"); + } + +out: + mutex_unlock(&ir->lock); + kfree(packet); + + return rc; +} + +static int iguanair_open(struct rc_dev *rdev) +{ + struct iguanair *ir = rdev->priv; + int rc; + + mutex_lock(&ir->lock); + + usb_submit_urb(ir->urb_in, GFP_KERNEL); + + BUG_ON(ir->receiver_on); + + rc = iguanair_receiver(ir, true); + if (rc == 0) + ir->receiver_on = true; + + mutex_unlock(&ir->lock); + + return rc; +} + +static void iguanair_close(struct rc_dev *rdev) +{ + struct iguanair *ir = rdev->priv; + int rc; + + mutex_lock(&ir->lock); + + rc = iguanair_receiver(ir, false); + ir->receiver_on = false; + if (rc) + dev_warn(ir->dev, "failed to disable receiver: %d\n", rc); + + usb_kill_urb(ir->urb_in); + + mutex_unlock(&ir->lock); +} + +static int __devinit iguanair_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct iguanair *ir; + struct rc_dev *rc; + int ret; + struct usb_host_interface *idesc; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + rc = rc_allocate_device(); + if (!ir || !rc) { + ret = ENOMEM; + goto out; + } + + ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC, + &ir->dma_in); + ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); + + if (!ir->buf_in || !ir->urb_in) { + ret = ENOMEM; + goto out; + } + + idesc = intf->altsetting; + + if (idesc->desc.bNumEndpoints < 2) { + ret = -ENODEV; + goto out; + } + + ir->rc = rc; + ir->dev = &intf->dev; + ir->udev = udev; + ir->pipe_in = usb_rcvintpipe(udev, + idesc->endpoint[0].desc.bEndpointAddress); + ir->pipe_out = usb_sndintpipe(udev, + idesc->endpoint[1].desc.bEndpointAddress); + mutex_init(&ir->lock); + init_completion(&ir->completion); + + ret = iguanair_get_features(ir); + if (ret) { + dev_warn(&intf->dev, "failed to get device features"); + goto out; + } + + usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in, + MAX_PACKET_SIZE, iguanair_rx, ir, + idesc->endpoint[0].desc.bInterval); + ir->urb_in->transfer_dma = ir->dma_in; + ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + snprintf(ir->name, sizeof(ir->name), + "IguanaWorks USB IR Transceiver version %d.%d", + ir->version[0], ir->version[1]); + + usb_make_path(ir->udev, ir->phys, sizeof(ir->phys)); + + rc->input_name = ir->name; + rc->input_phys = ir->phys; + usb_to_input_id(ir->udev, &rc->input_id); + rc->dev.parent = &intf->dev; + rc->driver_type = RC_DRIVER_IR_RAW; + rc->allowed_protos = RC_TYPE_ALL; + rc->priv = ir; + rc->open = iguanair_open; + rc->close = iguanair_close; + rc->s_tx_mask = iguanair_set_tx_mask; + rc->s_tx_carrier = iguanair_set_tx_carrier; + rc->tx_ir = iguanair_tx; + rc->driver_name = DRIVER_NAME; + rc->map_name = RC_MAP_EMPTY; + + iguanair_set_tx_carrier(rc, 38000); + + ret = rc_register_device(rc); + if (ret < 0) { + dev_err(&intf->dev, "failed to register rc device %d", ret); + goto out; + } + + usb_set_intfdata(intf, ir); + + dev_info(&intf->dev, "Registered %s", ir->name); + + return 0; +out: + if (ir) { + usb_free_urb(ir->urb_in); + usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in, + ir->dma_in); + } + rc_free_device(rc); + kfree(ir); + return ret; +} + +static void __devexit iguanair_disconnect(struct usb_interface *intf) +{ + struct iguanair *ir = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + + usb_kill_urb(ir->urb_in); + usb_free_urb(ir->urb_in); + usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in); + rc_unregister_device(ir->rc); + kfree(ir); +} + +static int iguanair_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct iguanair *ir = usb_get_intfdata(intf); + int rc = 0; + + mutex_lock(&ir->lock); + + if (ir->receiver_on) { + rc = iguanair_receiver(ir, false); + if (rc) + dev_warn(ir->dev, "failed to disable receiver for suspend\n"); + } + + mutex_unlock(&ir->lock); + + return rc; +} + +static int iguanair_resume(struct usb_interface *intf) +{ + struct iguanair *ir = usb_get_intfdata(intf); + int rc = 0; + + mutex_lock(&ir->lock); + + if (ir->receiver_on) { + rc = iguanair_receiver(ir, true); + if (rc) + dev_warn(ir->dev, "failed to enable receiver after resume\n"); + } + + mutex_unlock(&ir->lock); + + return rc; +} + +static const struct usb_device_id iguanair_table[] = { + { USB_DEVICE(0x1781, 0x0938) }, + { } +}; + +static struct usb_driver iguanair_driver = { + .name = DRIVER_NAME, + .probe = iguanair_probe, + .disconnect = __devexit_p(iguanair_disconnect), + .suspend = iguanair_suspend, + .resume = iguanair_resume, + .reset_resume = iguanair_resume, + .id_table = iguanair_table +}; + +module_usb_driver(iguanair_driver); + +MODULE_DESCRIPTION("IguanaWorks USB IR Transceiver"); +MODULE_AUTHOR("Sean Young "); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, iguanair_table); + -- GitLab From fc4b3fa714fb2a078531bccb501cf2ef8c7f888a Mon Sep 17 00:00:00 2001 From: Hans-Frieder Vogt Date: Sun, 15 Jul 2012 13:56:47 -0300 Subject: [PATCH 4704/5711] [media] rtl2832.c: minor cleanup The current formulation of the bw_params loop uses the counter j as an index for the first dimension of the bw_params array which is later incremented by the variable i. It is evaluated correctly only, because j is initialized to 0 at the beginning of the loop. I think that explicitly using the index 0 better reflects the intent of the expression. Signed-off-by: Hans-Frieder Vogt Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/rtl2832.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb/frontends/rtl2832.c index 2da592fb38ad..28269ccaeab7 100644 --- a/drivers/media/dvb/frontends/rtl2832.c +++ b/drivers/media/dvb/frontends/rtl2832.c @@ -589,7 +589,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) return -EINVAL; } - for (j = 0; j < sizeof(bw_params[j]); j++) { + for (j = 0; j < sizeof(bw_params[0]); j++) { ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1); if (ret) goto err; -- GitLab From 7980a4d544a451bd99ee9f8714f7dc6d5104a2b7 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sun, 15 Jul 2012 17:23:05 -0300 Subject: [PATCH 4705/5711] [media] via-camera: pass correct format settings to sensor The code attempts to maintain a "user format" and a "sensor format", but in this case it looks like a typo is passing the user format down to the sensor. This was preventing display of video at anything other than 640x480. Signed-off-by: Daniel Drake Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/via-camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index 308e150a39bc..eb404c2ce270 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c @@ -963,7 +963,7 @@ static int viacam_do_try_fmt(struct via_camera *cam, upix->pixelformat = f->pixelformat; viacam_fmt_pre(upix, spix); - v4l2_fill_mbus_format(&mbus_fmt, upix, f->mbus_code); + v4l2_fill_mbus_format(&mbus_fmt, spix, f->mbus_code); ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); v4l2_fill_pix_format(spix, &mbus_fmt); viacam_fmt_post(upix, spix); -- GitLab From 3b6961ba8c682cc71e51079017743c1b282fd259 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 26 Jul 2012 19:40:08 -0400 Subject: [PATCH 4706/5711] ACPI/x86: revert 'x86, acpi: Call acpi_enter_sleep_state via an asmlinkage C function from assembler' cd74257b974d6d26442c97891c4d05772748b177 patched up GTS/BFS -- a feature we want to remove. So revert it (by hand, due to conflict in sleep.h) to prepare for GTS/BFS removal. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Konrad Rzeszutek Wilk --- arch/x86/kernel/acpi/sleep.c | 4 ---- arch/x86/kernel/acpi/sleep.h | 2 -- arch/x86/kernel/acpi/wakeup_32.S | 4 +++- arch/x86/kernel/acpi/wakeup_64.S | 4 +++- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 95bf99de9058..1b8e5a03d942 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -25,10 +25,6 @@ unsigned long acpi_realmode_flags; static char temp_stack[4096]; #endif -asmlinkage void acpi_enter_s3(void) -{ - acpi_enter_sleep_state(3, wake_sleep_flags); -} /** * acpi_suspend_lowlevel - save kernel state * diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 5653a5791ec9..67f59f8c6956 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -2,7 +2,6 @@ * Variables and functions used by the code in sleep.c */ -#include #include extern unsigned long saved_video_mode; @@ -11,7 +10,6 @@ extern long saved_magic; extern int wakeup_pmode_return; extern u8 wake_sleep_flags; -extern asmlinkage void acpi_enter_s3(void); extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index 72610839f03b..13ab720573e3 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -74,7 +74,9 @@ restore_registers: ENTRY(do_suspend_lowlevel) call save_processor_state call save_registers - call acpi_enter_s3 + pushl $3 + call acpi_enter_sleep_state + addl $4, %esp # In case of S3 failure, we'll emerge here. Jump # to ret_point to recover diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 014d1d28c397..8ea5164cbd04 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -71,7 +71,9 @@ ENTRY(do_suspend_lowlevel) movq %rsi, saved_rsi addq $8, %rsp - call acpi_enter_s3 + movl $3, %edi + xorl %eax, %eax + call acpi_enter_sleep_state /* in case something went wrong, restore the machine status and go on */ jmp resume_point -- GitLab From 3f6f49c7854c9294119437a82c5b35be78f9cea6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 26 Jul 2012 20:08:54 -0400 Subject: [PATCH 4707/5711] ACPI: delete _GTS/_BFS support _GTS and _BFS were added to the suspend/resume flow in the ACPI 2.0 specification. Linux dutifully implemented _GTS and _BFS. We discovered that it was rarely seen in systems in the field. Further, some of those systems had AML so bogus that it could never work -- proof that no other operating system supports _GTS and _BFS. So we made _GTS and _BFS optional via modparam, and disabled them by default. But we've had to complicate some code to keep this support in the kernel, as these methods are defined to be evaluated very close to sleep entry and exit. Indeed, no other AML is ever evaluated with interrupts off. We have submitted a proposal for _GTS and _BFS to be officially removed from the ACPI specification on the next revision. Here we remove it from Linux. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Konrad Rzeszutek Wilk --- drivers/acpi/acpica/achware.h | 12 +++--- drivers/acpi/acpica/hwesleep.c | 19 ++------- drivers/acpi/acpica/hwsleep.c | 20 ++------- drivers/acpi/acpica/hwxfsleep.c | 22 +++++----- drivers/acpi/sleep.c | 73 ++++----------------------------- include/acpi/acpixf.h | 4 +- include/acpi/actypes.h | 2 +- 7 files changed, 34 insertions(+), 118 deletions(-) diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 5ccb99ae3a6f..5de4ec72766d 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -83,22 +83,22 @@ acpi_status acpi_hw_clear_acpi_status(void); /* * hwsleep - sleep/wake support (Legacy sleep registers) */ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_sleep(u8 sleep_state); -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state); -acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_wake(u8 sleep_state); /* * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers) */ void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument); -acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_sleep(u8 sleep_state); -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state); -acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_wake(u8 sleep_state); /* * hwvalid - Port I/O with validation diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 48518dac5342..94996f9ae3ad 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -90,7 +90,6 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) * FUNCTION: acpi_hw_extended_sleep * * PARAMETERS: sleep_state - Which sleep state to enter - * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -100,7 +99,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) * ******************************************************************************/ -acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_sleep(u8 sleep_state) { acpi_status status; u8 sleep_type_value; @@ -125,12 +124,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) acpi_gbl_system_awake_and_running = FALSE; - /* Optionally execute _GTS (Going To Sleep) */ - - if (flags & ACPI_EXECUTE_GTS) { - acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); - } - /* Flush caches, as per ACPI specification */ ACPI_FLUSH_CPU_CACHE(); @@ -172,7 +165,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) * FUNCTION: acpi_hw_extended_wake_prep * * PARAMETERS: sleep_state - Which sleep state we just exited - * flags - ACPI_EXECUTE_BFS to run optional method * * RETURN: Status * @@ -181,7 +173,7 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) * ******************************************************************************/ -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) { acpi_status status; u8 sleep_type_value; @@ -200,11 +192,6 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) &acpi_gbl_FADT.sleep_control); } - /* Optionally execute _BFS (Back From Sleep) */ - - if (flags & ACPI_EXECUTE_BFS) { - acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); - } return_ACPI_STATUS(AE_OK); } @@ -222,7 +209,7 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) * ******************************************************************************/ -acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_wake(u8 sleep_state) { ACPI_FUNCTION_TRACE(hw_extended_wake); diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 9960fe9ef533..3fddde056a5e 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -56,7 +56,6 @@ ACPI_MODULE_NAME("hwsleep") * FUNCTION: acpi_hw_legacy_sleep * * PARAMETERS: sleep_state - Which sleep state to enter - * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -64,7 +63,7 @@ ACPI_MODULE_NAME("hwsleep") * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_sleep(u8 sleep_state) { struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; @@ -110,12 +109,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) return_ACPI_STATUS(status); } - /* Optionally execute _GTS (Going To Sleep) */ - - if (flags & ACPI_EXECUTE_GTS) { - acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); - } - /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, @@ -214,7 +207,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) * FUNCTION: acpi_hw_legacy_wake_prep * * PARAMETERS: sleep_state - Which sleep state we just exited - * flags - ACPI_EXECUTE_BFS to run optional method * * RETURN: Status * @@ -224,7 +216,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) * ******************************************************************************/ -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) { acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; @@ -275,11 +267,6 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) } } - /* Optionally execute _BFS (Back From Sleep) */ - - if (flags & ACPI_EXECUTE_BFS) { - acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); - } return_ACPI_STATUS(status); } @@ -288,7 +275,6 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) * FUNCTION: acpi_hw_legacy_wake * * PARAMETERS: sleep_state - Which sleep state we just exited - * flags - Reserved, set to zero * * RETURN: Status * @@ -297,7 +283,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) * ******************************************************************************/ -acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_wake(u8 sleep_state) { acpi_status status; diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index f8684bfe7907..1f165a750ae2 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("hwxfsleep") /* Local prototypes */ static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id); +acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); /* * Dispatch table used to efficiently branch to the various sleep @@ -235,7 +235,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) * ******************************************************************************/ static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id) +acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) { acpi_status status; struct acpi_sleep_functions *sleep_functions = @@ -248,11 +248,11 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id) * use the extended sleep registers */ if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) { - status = sleep_functions->extended_function(sleep_state, flags); + status = sleep_functions->extended_function(sleep_state); } else { /* Legacy sleep */ - status = sleep_functions->legacy_function(sleep_state, flags); + status = sleep_functions->legacy_function(sleep_state); } return (status); @@ -262,7 +262,7 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id) * For the case where reduced-hardware-only code is being generated, * we know that only the extended sleep registers are available */ - status = sleep_functions->extended_function(sleep_state, flags); + status = sleep_functions->extended_function(sleep_state); return (status); #endif /* !ACPI_REDUCED_HARDWARE */ @@ -349,7 +349,6 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * FUNCTION: acpi_enter_sleep_state * * PARAMETERS: sleep_state - Which sleep state to enter - * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -357,7 +356,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags) +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { acpi_status status; @@ -371,7 +370,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags) } status = - acpi_hw_sleep_dispatch(sleep_state, flags, ACPI_SLEEP_FUNCTION_ID); + acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); return_ACPI_STATUS(status); } @@ -391,14 +390,14 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) * Called with interrupts DISABLED. * ******************************************************************************/ -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags) +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) { acpi_status status; ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); status = - acpi_hw_sleep_dispatch(sleep_state, flags, + acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID); return_ACPI_STATUS(status); } @@ -423,8 +422,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); - - status = acpi_hw_sleep_dispatch(sleep_state, 0, ACPI_WAKE_FUNCTION_ID); + status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 23a53c013f1e..bd35e3c5e530 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -28,34 +28,6 @@ #include "internal.h" #include "sleep.h" -u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS; -static unsigned int gts, bfs; -static int set_param_wake_flag(const char *val, struct kernel_param *kp) -{ - int ret = param_set_int(val, kp); - - if (ret) - return ret; - - if (kp->arg == (const char *)>s) { - if (gts) - wake_sleep_flags |= ACPI_EXECUTE_GTS; - else - wake_sleep_flags &= ~ACPI_EXECUTE_GTS; - } - if (kp->arg == (const char *)&bfs) { - if (bfs) - wake_sleep_flags |= ACPI_EXECUTE_BFS; - else - wake_sleep_flags &= ~ACPI_EXECUTE_BFS; - } - return ret; -} -module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644); -module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644); -MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); -MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); - static u8 sleep_states[ACPI_S_STATE_COUNT]; static bool pwr_btn_event_pending; @@ -305,7 +277,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) switch (acpi_state) { case ACPI_STATE_S1: barrier(); - status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags); + status = acpi_enter_sleep_state(acpi_state); break; case ACPI_STATE_S3: @@ -319,8 +291,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* This violates the spec but is required for bug compatibility. */ acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags); + /* Reprogram control registers */ + acpi_leave_sleep_state_prep(acpi_state); /* ACPI 3.0 specs (P62) says that it's the responsibility * of the OSPM to clear the status bit [ implying that the @@ -603,9 +575,9 @@ static int acpi_hibernation_enter(void) ACPI_FLUSH_CPU_CACHE(); /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags); - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); + status = acpi_enter_sleep_state(ACPI_STATE_S4); + /* Reprogram control registers */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4); return ACPI_SUCCESS(status) ? 0 : -EFAULT; } @@ -617,8 +589,8 @@ static void acpi_hibernation_leave(void) * enable it here. */ acpi_enable(); - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); + /* Reprogram control registers */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4); /* Check the hardware signature */ if (facs && s4_hardware_signature != facs->hardware_signature) { printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " @@ -876,33 +848,7 @@ static void acpi_power_off(void) /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ printk(KERN_DEBUG "%s called\n", __func__); local_irq_disable(); - acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags); -} - -/* - * ACPI 2.0 created the optional _GTS and _BFS, - * but industry adoption has been neither rapid nor broad. - * - * Linux gets into trouble when it executes poorly validated - * paths through the BIOS, so disable _GTS and _BFS by default, - * but do speak up and offer the option to enable them. - */ -static void __init acpi_gts_bfs_check(void) -{ - acpi_handle dummy; - - if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__GTS, &dummy))) - { - printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n"); - printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, " - "please notify linux-acpi@vger.kernel.org\n"); - } - if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__BFS, &dummy))) - { - printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n"); - printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, " - "please notify linux-acpi@vger.kernel.org\n"); - } + acpi_enter_sleep_state(ACPI_STATE_S5); } int __init acpi_sleep_init(void) @@ -963,6 +909,5 @@ int __init acpi_sleep_init(void) * object can also be evaluated when the system enters S5. */ register_reboot_notifier(&tts_notifier); - acpi_gts_bfs_check(); return 0; } diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 2c744c7a5b3d..26a92fc28a59 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -491,11 +491,11 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b); acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags); +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)) -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags); +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); acpi_status acpi_leave_sleep_state(u8 sleep_state); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 3af87de6a68c..3d00bd5bd7e3 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -803,7 +803,7 @@ typedef u8 acpi_adr_space_type; /* Sleep function dispatch */ -typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state, u8 flags); +typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state); struct acpi_sleep_functions { ACPI_SLEEP_FUNCTION legacy_function; -- GitLab From 2d9c86774756193edff2a2a9077264f666c626de Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 30 Jul 2012 22:40:32 +0200 Subject: [PATCH 4708/5711] ACPI / PCI: Do not try to acquire _OSC control if that is hopeless If acpi_pci_osc_support() fails for the given flags, it doesn't make sense to call acpi_pci_osc_control_set() down the road for the same flags, because it will certainly fail too. Moreover, problem diagnostics is then harder, because it is not too easy to identify the reason of the _OSC failure in those cases. For this reason, check the status returned by acpi_pci_osc_support() for PCIe support flags and do not attempt to execute acpi_pci_osc_control_set() for those flags and print a message if it's "failure". For compatibility with the existing code, disable ASPM in that case too. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7aff6312ce7c..c86b39217400 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -571,8 +571,15 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) OSC_CLOCK_PWR_CAPABILITY_SUPPORT; if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; - if (flags != base_flags) - acpi_pci_osc_support(root, flags); + if (flags != base_flags) { + status = acpi_pci_osc_support(root, flags); + if (ACPI_FAILURE(status)) { + dev_info(root->bus->bridge, "ACPI _OSC support " + "notification failed, disabling PCIe ASPM\n"); + pcie_no_aspm(); + flags = base_flags; + } + } if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { -- GitLab From 546f04ef716dd49521774653d8b032a7d64c05d9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:15:23 -0700 Subject: [PATCH 4709/5711] libceph: support crush tunables The server side recently added support for tuning some magic crush variables. Decode these variables if they are present, or use the default values if they are not present. Corresponds to ceph.git commit 89af369c25f274fe62ef730e5e8aad0c54f1e5a5. Signed-off-by: caleb miles Reviewed-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- include/linux/ceph/ceph_features.h | 5 +++- include/linux/crush/crush.h | 8 ++++++ net/ceph/crush/mapper.c | 13 +++++----- net/ceph/osdmap.c | 39 ++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/include/linux/ceph/ceph_features.h b/include/linux/ceph/ceph_features.h index 342f93dbe162..dad579b0c0e6 100644 --- a/include/linux/ceph/ceph_features.h +++ b/include/linux/ceph/ceph_features.h @@ -12,12 +12,15 @@ #define CEPH_FEATURE_MONNAMES (1<<5) #define CEPH_FEATURE_RECONNECT_SEQ (1<<6) #define CEPH_FEATURE_DIRLAYOUTHASH (1<<7) +/* bits 8-17 defined by user-space; not supported yet here */ +#define CEPH_FEATURE_CRUSH_TUNABLES (1<<18) /* * Features supported. */ #define CEPH_FEATURES_SUPPORTED_DEFAULT \ - (CEPH_FEATURE_NOSRCADDR) + (CEPH_FEATURE_NOSRCADDR | \ + CEPH_FEATURE_CRUSH_TUNABLES) #define CEPH_FEATURES_REQUIRED_DEFAULT \ (CEPH_FEATURE_NOSRCADDR) diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h index 7c4750811b96..25baa287cff7 100644 --- a/include/linux/crush/crush.h +++ b/include/linux/crush/crush.h @@ -154,6 +154,14 @@ struct crush_map { __s32 max_buckets; __u32 max_rules; __s32 max_devices; + + /* choose local retries before re-descent */ + __u32 choose_local_tries; + /* choose local attempts using a fallback permutation before + * re-descent */ + __u32 choose_local_fallback_tries; + /* choose attempts before giving up */ + __u32 choose_total_tries; }; diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index d7edc24333b8..35fce755ce10 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -306,7 +306,6 @@ static int crush_choose(const struct crush_map *map, int item = 0; int itemtype; int collide, reject; - const unsigned int orig_tries = 5; /* attempts before we fall back to search */ dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", bucket->id, x, outpos, numrep); @@ -351,8 +350,9 @@ static int crush_choose(const struct crush_map *map, reject = 1; goto reject; } - if (flocal >= (in->size>>1) && - flocal > orig_tries) + if (map->choose_local_fallback_tries > 0 && + flocal >= (in->size>>1) && + flocal > map->choose_local_fallback_tries) item = bucket_perm_choose(in, x, r); else item = crush_bucket_choose(in, x, r); @@ -422,13 +422,14 @@ reject: ftotal++; flocal++; - if (collide && flocal < 3) + if (collide && flocal <= map->choose_local_tries) /* retry locally a few times */ retry_bucket = 1; - else if (flocal <= in->size + orig_tries) + else if (map->choose_local_fallback_tries > 0 && + flocal <= in->size + map->choose_local_fallback_tries) /* exhaustive bucket search */ retry_bucket = 1; - else if (ftotal < 20) + else if (ftotal <= map->choose_total_tries) /* then retry descent */ retry_descent = 1; else diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 9600674c2c39..3124b71a8883 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -135,6 +135,21 @@ bad: return -EINVAL; } +static int skip_name_map(void **p, void *end) +{ + int len; + ceph_decode_32_safe(p, end, len ,bad); + while (len--) { + int strlen; + *p += sizeof(u32); + ceph_decode_32_safe(p, end, strlen, bad); + *p += strlen; +} + return 0; +bad: + return -EINVAL; +} + static struct crush_map *crush_decode(void *pbyval, void *end) { struct crush_map *c; @@ -143,6 +158,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end) void **p = &pbyval; void *start = pbyval; u32 magic; + u32 num_name_maps; dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p)); @@ -150,6 +166,11 @@ static struct crush_map *crush_decode(void *pbyval, void *end) if (c == NULL) return ERR_PTR(-ENOMEM); + /* set tunables to default values */ + c->choose_local_tries = 2; + c->choose_local_fallback_tries = 5; + c->choose_total_tries = 19; + ceph_decode_need(p, end, 4*sizeof(u32), bad); magic = ceph_decode_32(p); if (magic != CRUSH_MAGIC) { @@ -297,7 +318,25 @@ static struct crush_map *crush_decode(void *pbyval, void *end) } /* ignore trailing name maps. */ + for (num_name_maps = 0; num_name_maps < 3; num_name_maps++) { + err = skip_name_map(p, end); + if (err < 0) + goto done; + } + + /* tunables */ + ceph_decode_need(p, end, 3*sizeof(u32), done); + c->choose_local_tries = ceph_decode_32(p); + c->choose_local_fallback_tries = ceph_decode_32(p); + c->choose_total_tries = ceph_decode_32(p); + dout("crush decode tunable choose_local_tries = %d", + c->choose_local_tries); + dout("crush decode tunable choose_local_fallback_tries = %d", + c->choose_local_fallback_tries); + dout("crush decode tunable choose_total_tries = %d", + c->choose_total_tries); +done: dout("crush_decode success\n"); return c; -- GitLab From 3a140a0d5c4b9e35373b016e41dfc85f1e526bdb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:24:21 -0700 Subject: [PATCH 4710/5711] libceph: report socket read/write error message We need to set error_msg to something useful before calling ceph_fault(); do so here for try_{read,write}(). This is more informative than libceph: osd0 192.168.106.220:6801 (null) Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- net/ceph/messenger.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 63e1252d3af5..6e2f67816f61 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2287,14 +2287,18 @@ restart: ret = try_read(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on read"; goto fault; + } ret = try_write(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on write"; goto fault; + } done: mutex_unlock(&con->mutex); -- GitLab From 8c50c817566dfa4581f82373aac39f3e608a7dc8 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:24:37 -0700 Subject: [PATCH 4711/5711] libceph: fix mutex coverage for ceph_con_close Hold the mutex while twiddling all of the state bits to avoid possible races. While we're here, make not of why we cannot close the socket directly. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- net/ceph/messenger.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 6e2f67816f61..e65b15d5d8b9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -503,6 +503,7 @@ static void reset_connection(struct ceph_connection *con) */ void ceph_con_close(struct ceph_connection *con) { + mutex_lock(&con->mutex); dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); @@ -515,11 +516,16 @@ void ceph_con_close(struct ceph_connection *con) clear_bit(KEEPALIVE_PENDING, &con->flags); clear_bit(WRITE_PENDING, &con->flags); - mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; cancel_delayed_work(&con->work); mutex_unlock(&con->mutex); + + /* + * We cannot close the socket directly from here because the + * work threads use it without holding the mutex. Instead, let + * con_work() do it. + */ queue_con(con); } EXPORT_SYMBOL(ceph_con_close); -- GitLab From 6194ea895e447fdf4adfd23f67873a32bf4f15ae Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:19:28 -0700 Subject: [PATCH 4712/5711] libceph: resubmit linger ops when pg mapping changes The linger op registration (i.e., watch) modifies the object state. As such, the OSD will reply with success if it has already applied without doing the associated side-effects (setting up the watch session state). If we lose the ACK and resubmit, we will see success but the watch will not be correctly registered and we won't get notifies. To fix this, always resubmit the linger op with a new tid. We accomplish this by re-registering as a linger (i.e., 'registered') if we are not yet registered. Then the second loop will treat this just like a normal case of re-registering. This mirrors a similar fix on the userland ceph.git, commit 5dd68b95, and ceph bug #2796. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- net/ceph/osd_client.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 07920cac31a6..c605705c2f57 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -891,7 +891,9 @@ static void __register_linger_request(struct ceph_osd_client *osdc, { dout("__register_linger_request %p\n", req); list_add_tail(&req->r_linger_item, &osdc->req_linger); - list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests); + if (req->r_osd) + list_add_tail(&req->r_linger_osd, + &req->r_osd->o_linger_requests); } static void __unregister_linger_request(struct ceph_osd_client *osdc, @@ -1305,8 +1307,9 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("kick_requests %s\n", force_resend ? " (force resend)" : ""); mutex_lock(&osdc->request_mutex); - for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { + for (p = rb_first(&osdc->requests); p; ) { req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); err = __map_request(osdc, req, force_resend); if (err < 0) continue; /* error */ @@ -1314,10 +1317,23 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("%p tid %llu maps to no osd\n", req, req->r_tid); needmap++; /* request a newer map */ } else if (err > 0) { - dout("%p tid %llu requeued on osd%d\n", req, req->r_tid, - req->r_osd ? req->r_osd->o_osd : -1); - if (!req->r_linger) + if (!req->r_linger) { + dout("%p tid %llu requeued on osd%d\n", req, + req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); req->r_flags |= CEPH_OSD_FLAG_RETRY; + } + } + if (req->r_linger && list_empty(&req->r_linger_item)) { + /* + * register as a linger so that we will + * re-submit below and get a new tid + */ + dout("%p tid %llu restart on osd%d\n", + req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); + __register_linger_request(osdc, req); + __unregister_request(osdc, req); } } -- GitLab From a4107026976f06c9a6ce8cc84a763564ee39d901 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:20:25 -0700 Subject: [PATCH 4713/5711] libceph: (re)initialize bio_iter on start of message receive Previously, we were opportunistically initializing the bio_iter if it appeared to be uninitialized in the middle of the read path. The problem is that a sequence like: - start reading message - initialize bio_iter - read half a message - messenger fault, reconnect - restart reading message - ** bio_iter now non-NULL, not reinitialized ** - read past end of bio, crash Instead, initialize the bio_iter unconditionally when we allocate/claim the message for read. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- net/ceph/messenger.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e65b15d5d8b9..f1bd3bbb0c46 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1872,6 +1872,11 @@ static int read_partial_message(struct ceph_connection *con) else con->in_msg_pos.page_pos = 0; con->in_msg_pos.data_pos = 0; + +#ifdef CONFIG_BLOCK + if (m->bio) + init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); +#endif } /* front */ @@ -1888,10 +1893,6 @@ static int read_partial_message(struct ceph_connection *con) if (ret <= 0) return ret; } -#ifdef CONFIG_BLOCK - if (m->bio && !m->bio_iter) - init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); -#endif /* (page) data */ while (con->in_msg_pos.data_pos < data_len) { @@ -1902,7 +1903,7 @@ static int read_partial_message(struct ceph_connection *con) return ret; #ifdef CONFIG_BLOCK } else if (m->bio) { - + BUG_ON(!m->bio_iter); ret = read_partial_message_bio(con, &m->bio_iter, &m->bio_seg, data_len, do_datacrc); -- GitLab From a53aab645c82f0146e35684b34692c69b5118121 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:21:17 -0700 Subject: [PATCH 4714/5711] ceph: close old con before reopening on mds reconnect When we detect a mds session reset, close the old ceph_connection before reopening it. This ensures we clean up the old socket properly and keep the ceph_connection state correct. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh --- fs/ceph/mds_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 39b76d66bc5d..a5a735422aa7 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2518,6 +2518,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, session->s_state = CEPH_MDS_SESSION_RECONNECTING; session->s_seq = 0; + ceph_con_close(&session->s_con); ceph_con_open(&session->s_con, CEPH_ENTITY_TYPE_MDS, mds, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); -- GitLab From 5469155f2bc83bb2c88b0a0370c3d54d87eed06e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:21:40 -0700 Subject: [PATCH 4715/5711] libceph: protect ceph_con_open() with mutex Take the con mutex while we are initiating a ceph open. This is necessary because the may have previously been in use and then closed, which could result in a racing workqueue running con_work(). Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh Reviewed-by: Alex Elder --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f1bd3bbb0c46..a4779988c847 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -537,6 +537,7 @@ void ceph_con_open(struct ceph_connection *con, __u8 entity_type, __u64 entity_num, struct ceph_entity_addr *addr) { + mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); @@ -546,6 +547,7 @@ void ceph_con_open(struct ceph_connection *con, memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ + mutex_unlock(&con->mutex); queue_con(con); } EXPORT_SYMBOL(ceph_con_open); -- GitLab From 85effe183dd45854d1ad1a370b88cddb403c4c91 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:22:05 -0700 Subject: [PATCH 4716/5711] libceph: reset connection retry on successfully negotiation We exponentially back off when we encounter connection errors. If several errors accumulate, we will eventually wait ages before even trying to reconnect. Fix this by resetting the backoff counter after a successful negotiation/ connection with the remote node. Fixes ceph issue #2802. Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh Reviewed-by: Alex Elder --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index a4779988c847..07204f19e856 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1629,6 +1629,8 @@ static int process_connect(struct ceph_connection *con) if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) set_bit(LOSSYTX, &con->flags); + con->delay = 0; /* reset backoff memory */ + prepare_read_tag(con); break; -- GitLab From 21ec6ffa46719a4ed45531b5b01014c26f0416c4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 20 Jul 2012 08:18:36 -0500 Subject: [PATCH 4717/5711] ceph: fix potential double free We re-run the loop but we don't re-set the attrs pointer back to NULL. Signed-off-by: Alan Cox Reviewed-by: Alex Elder --- fs/ceph/xattr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 785cb3057c95..2c2ae5be9902 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -457,6 +457,7 @@ start: for (i = 0; i < numattr; i++) kfree(xattrs[i]); kfree(xattrs); + xattrs = NULL; goto start; } err = -EIO; -- GitLab From 048a9d2d069e3d63c9169de82649be00de65a8f6 Mon Sep 17 00:00:00 2001 From: Jiaju Zhang Date: Fri, 20 Jul 2012 08:18:36 -0500 Subject: [PATCH 4718/5711] libceph: trivial fix for the incorrect debug output This is a trivial fix for the debug output, as it is inconsistent with the function name so may confuse people when debugging. [elder@inktank.com: switched to use __func__] Signed-off-by: Jiaju Zhang Reviewed-by: Alex Elder --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index c605705c2f57..ad427e698890 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -688,7 +688,7 @@ static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) static void remove_all_osds(struct ceph_osd_client *osdc) { - dout("__remove_old_osds %p\n", osdc); + dout("%s %p\n", __func__, osdc); mutex_lock(&osdc->request_mutex); while (!RB_EMPTY_ROOT(&osdc->osds)) { struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds), -- GitLab From e88a36ec961b8c1899c59c5e4ae35a318c0209d3 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 21 Nov 2011 18:14:25 -0800 Subject: [PATCH 4719/5711] rbd: return errors for mapped but deleted snapshot When a snapshot is deleted, the OSD will return ENOENT when reading from it. This is normally interpreted as a hole by rbd, which will return zeroes. To minimize the time in which this can happen, stop requests early when we are notified that our snapshot no longer exists. [elder@inktank.com: updated __rbd_init_snaps_header() logic] Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index b124442dab3a..730d0ce505e1 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -172,9 +172,13 @@ struct rbd_device { /* protects updating the header */ struct rw_semaphore header_rwsem; + /* name of the snapshot this device reads from */ char *snap_name; + /* id of the snapshot this device reads from */ u64 snap_id; /* current snapshot id */ - int read_only; + /* whether the snap_id this device reads from still exists */ + bool snap_exists; + int read_only; struct list_head node; @@ -597,6 +601,7 @@ static int rbd_header_set_snap(struct rbd_device *rbd_dev, u64 *size) else snapc->seq = 0; rbd_dev->snap_id = CEPH_NOSNAP; + rbd_dev->snap_exists = false; rbd_dev->read_only = 0; if (size) *size = header->image_size; @@ -606,6 +611,7 @@ static int rbd_header_set_snap(struct rbd_device *rbd_dev, u64 *size) if (ret < 0) goto done; rbd_dev->snap_id = snapc->seq; + rbd_dev->snap_exists = true; rbd_dev->read_only = 1; } @@ -1468,6 +1474,21 @@ static void rbd_rq_fn(struct request_queue *q) spin_unlock_irq(q->queue_lock); + if (rbd_dev->snap_id != CEPH_NOSNAP) { + bool snap_exists; + + down_read(&rbd_dev->header_rwsem); + snap_exists = rbd_dev->snap_exists; + up_read(&rbd_dev->header_rwsem); + + if (!snap_exists) { + dout("request for non-existent snapshot"); + spin_lock_irq(q->queue_lock); + __blk_end_request_all(rq, -ENXIO); + continue; + } + } + dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", size, blk_rq_pos(rq) * SECTOR_SIZE); @@ -2088,7 +2109,14 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) cur_id = rbd_dev->header.snapc->snaps[i - 1]; if (!i || old_snap->id < cur_id) { - /* old_snap->id was skipped, thus was removed */ + /* + * old_snap->id was skipped, thus was + * removed. If this rbd_dev is mapped to + * the removed snapshot, record that it no + * longer exists, to prevent further I/O. + */ + if (rbd_dev->snap_id == old_snap->id) + rbd_dev->snap_exists = false; __rbd_remove_snap_dev(rbd_dev, old_snap); continue; } -- GitLab From 474ef7ce832d471148f63a9d07f67fc5564834f1 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 21 Nov 2011 17:13:54 -0800 Subject: [PATCH 4720/5711] rbd: only reset capacity when pointing to head Snapshots cannot be resized, and the new capacity of head should not be reflected by the snapshot. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 730d0ce505e1..f171cebabda9 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1725,7 +1725,12 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) return ret; /* resized? */ - set_capacity(rbd_dev->disk, h.image_size / SECTOR_SIZE); + if (rbd_dev->snap_id == CEPH_NOSNAP) { + sector_t size = (sector_t) h.image_size / SECTOR_SIZE; + + dout("setting size to %llu sectors", (unsigned long long) size); + set_capacity(rbd_dev->disk, size); + } down_write(&rbd_dev->header_rwsem); -- GitLab From a51aa0c042fa39946dd017d5f91a073300a71577 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 10:35:04 -0800 Subject: [PATCH 4721/5711] rbd: expose the correct size of the device in sysfs If an image was mapped to a snapshot, the size of the head version would be shown. Protect capacity with header_rwsem, since it may change. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index f171cebabda9..9c3a1db49ac4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1724,6 +1724,8 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) if (ret < 0) return ret; + down_write(&rbd_dev->header_rwsem); + /* resized? */ if (rbd_dev->snap_id == CEPH_NOSNAP) { sector_t size = (sector_t) h.image_size / SECTOR_SIZE; @@ -1732,8 +1734,6 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) set_capacity(rbd_dev->disk, size); } - down_write(&rbd_dev->header_rwsem); - snap_seq = rbd_dev->header.snapc->seq; if (rbd_dev->header.total_snaps && rbd_dev->header.snapc->snaps[0] == snap_seq) @@ -1853,8 +1853,13 @@ static ssize_t rbd_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); + sector_t size; + + down_read(&rbd_dev->header_rwsem); + size = get_capacity(rbd_dev->disk); + up_read(&rbd_dev->header_rwsem); - return sprintf(buf, "%llu\n", (unsigned long long)rbd_dev->header.image_size); + return sprintf(buf, "%llu\n", (unsigned long long) size * SECTOR_SIZE); } static ssize_t rbd_major_show(struct device *dev, -- GitLab From 93a24e084d67ba2fcb9a4c289135825b623ec864 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 10:41:28 -0800 Subject: [PATCH 4722/5711] rbd: set image size when header is updated The image may have been resized. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 9c3a1db49ac4..a6bbda2e5eb8 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1746,6 +1746,7 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) kfree(rbd_dev->header.snap_names); kfree(rbd_dev->header.snapc); + rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; rbd_dev->header.snapc = h.snapc; rbd_dev->header.snap_names = h.snap_names; -- GitLab From d1d25646543134d756a02ffe4e02073faa761f2c Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 14:03:05 -0800 Subject: [PATCH 4723/5711] rbd: use reference counting for the snap context This prevents a race between requests with a given snap context and header updates that free it. The osd client was already expecting the snap context to be reference counted, since it get()s it in ceph_osdc_build_request and put()s it when the request completes. Also remove the second down_read()/up_read() on header_rwsem in rbd_do_request, which wasn't actually preventing this race or protecting any other data. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index a6bbda2e5eb8..988f94458f95 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -626,7 +626,7 @@ static void rbd_header_free(struct rbd_image_header *header) kfree(header->object_prefix); kfree(header->snap_sizes); kfree(header->snap_names); - kfree(header->snapc); + ceph_put_snap_context(header->snapc); } /* @@ -902,13 +902,10 @@ static int rbd_do_request(struct request *rq, dout("rbd_do_request object_name=%s ofs=%lld len=%lld\n", object_name, len, ofs); - down_read(&rbd_dev->header_rwsem); - osdc = &rbd_dev->rbd_client->client->osdc; req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, false, GFP_NOIO, pages, bio); if (!req) { - up_read(&rbd_dev->header_rwsem); ret = -ENOMEM; goto done_pages; } @@ -942,7 +939,6 @@ static int rbd_do_request(struct request *rq, snapc, &mtime, req->r_oid, req->r_oid_len); - up_read(&rbd_dev->header_rwsem); if (linger_req) { ceph_osdc_set_request_linger(osdc, req); @@ -1448,6 +1444,7 @@ static void rbd_rq_fn(struct request_queue *q) u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; + struct ceph_snap_context *snapc; /* peek at request from block layer */ if (!rq) @@ -1474,21 +1471,20 @@ static void rbd_rq_fn(struct request_queue *q) spin_unlock_irq(q->queue_lock); - if (rbd_dev->snap_id != CEPH_NOSNAP) { - bool snap_exists; + down_read(&rbd_dev->header_rwsem); - down_read(&rbd_dev->header_rwsem); - snap_exists = rbd_dev->snap_exists; + if (rbd_dev->snap_id != CEPH_NOSNAP && !rbd_dev->snap_exists) { up_read(&rbd_dev->header_rwsem); - - if (!snap_exists) { - dout("request for non-existent snapshot"); - spin_lock_irq(q->queue_lock); - __blk_end_request_all(rq, -ENXIO); - continue; - } + dout("request for non-existent snapshot"); + spin_lock_irq(q->queue_lock); + __blk_end_request_all(rq, -ENXIO); + continue; } + snapc = ceph_get_snap_context(rbd_dev->header.snapc); + + up_read(&rbd_dev->header_rwsem); + dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", size, blk_rq_pos(rq) * SECTOR_SIZE); @@ -1498,6 +1494,7 @@ static void rbd_rq_fn(struct request_queue *q) if (!coll) { spin_lock_irq(q->queue_lock); __blk_end_request_all(rq, -ENOMEM); + ceph_put_snap_context(snapc); continue; } @@ -1521,7 +1518,7 @@ static void rbd_rq_fn(struct request_queue *q) /* init OSD command: write or read */ if (do_write) rbd_req_write(rq, rbd_dev, - rbd_dev->header.snapc, + snapc, ofs, op_size, bio, coll, cur_seg); @@ -1544,6 +1541,8 @@ next_seg: if (bp) bio_pair_release(bp); spin_lock_irq(q->queue_lock); + + ceph_put_snap_context(snapc); } } @@ -1744,7 +1743,8 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) /* rbd_dev->header.object_prefix shouldn't change */ kfree(rbd_dev->header.snap_sizes); kfree(rbd_dev->header.snap_names); - kfree(rbd_dev->header.snapc); + /* osd requests may still refer to snapc */ + ceph_put_snap_context(rbd_dev->header.snapc); rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; -- GitLab From a71b891bc7d77a070e723c8c53d1dd73cf931555 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 18:10:44 -0800 Subject: [PATCH 4724/5711] rbd: send header version when notifying Previously the original header version was sent. Now, we update it when the header changes. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 988f94458f95..4d3a1e02130b 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1197,7 +1197,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *rbd_dev, if (ret < 0) return ret; - ops[0].watch.ver = cpu_to_le64(rbd_dev->header.obj_version); + ops[0].watch.ver = cpu_to_le64(ver); ops[0].watch.cookie = notify_id; ops[0].watch.flag = 0; @@ -1216,6 +1216,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *rbd_dev, static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) { struct rbd_device *rbd_dev = (struct rbd_device *)data; + u64 hver; int rc; if (!rbd_dev) @@ -1225,12 +1226,13 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) rbd_dev->header_name, notify_id, (int) opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rc = __rbd_refresh_header(rbd_dev); + hver = rbd_dev->header.obj_version; mutex_unlock(&ctl_mutex); if (rc) pr_warning(RBD_DRV_NAME "%d got notification but failed to " " update snaps: %d\n", rbd_dev->major, rc); - rbd_req_sync_notify_ack(rbd_dev, ver, notify_id, rbd_dev->header_name); + rbd_req_sync_notify_ack(rbd_dev, hver, notify_id, rbd_dev->header_name); } /* @@ -1746,6 +1748,7 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) /* osd requests may still refer to snapc */ ceph_put_snap_context(rbd_dev->header.snapc); + rbd_dev->header.obj_version = h.obj_version; rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; rbd_dev->header.snapc = h.snapc; -- GitLab From 75fe9e19816d6ed3e90f1bd3b741f99bf030e848 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 08:49:18 -0500 Subject: [PATCH 4725/5711] rbd: don't use snapc->seq that way In what appears to be an artifact of a different way of encoding whether an rbd image maps a snapshot, __rbd_refresh_header() has code that arranges to update the seq value in an rbd image's snapshot context to point to the first entry in its snapshot array if that's where it was pointing initially. We now use rbd_dev->snap_id to record the snapshot id--using the special value CEPH_NOSNAP to indicate the rbd_dev is not mapping a snapshot at all. There is therefore no need to check for this case, nor to update the seq value, in __rbd_refresh_header(). Just preserve the seq value that rbd_read_header() provides (which, at the moment, is nothing). Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4d3a1e02130b..8a4659997e05 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1718,8 +1718,6 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) { int ret; struct rbd_image_header h; - u64 snap_seq; - int follow_seq = 0; ret = rbd_read_header(rbd_dev, &h); if (ret < 0) @@ -1735,13 +1733,6 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) set_capacity(rbd_dev->disk, size); } - snap_seq = rbd_dev->header.snapc->seq; - if (rbd_dev->header.total_snaps && - rbd_dev->header.snapc->snaps[0] == snap_seq) - /* pointing at the head, will need to follow that - if head moves */ - follow_seq = 1; - /* rbd_dev->header.object_prefix shouldn't change */ kfree(rbd_dev->header.snap_sizes); kfree(rbd_dev->header.snap_names); @@ -1759,11 +1750,6 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) WARN_ON(strcmp(rbd_dev->header.object_prefix, h.object_prefix)); kfree(h.object_prefix); - if (follow_seq) - rbd_dev->header.snapc->seq = rbd_dev->header.snapc->snaps[0]; - else - rbd_dev->header.snapc->seq = snap_seq; - ret = __rbd_init_snaps_header(rbd_dev); up_write(&rbd_dev->header_rwsem); -- GitLab From 78dc447d3ca3701206a1dd813c901556a3fad451 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 08:49:18 -0500 Subject: [PATCH 4726/5711] rbd: preserve snapc->seq in rbd_header_set_snap() In rbd_header_set_snap(), there is logic to make the snap context's seq field get set to a particular snapshot id, or 0 if there is no snapshot for the rbd image. This seems to be an artifact of how the current snapshot id for an rbd_dev was recorded before the rbd_dev->snap_id field began to be used for that purpose. There's no need to update the value of snapc->seq here any more, so stop doing it. Tidy up a few local variables in that function while we're at it. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 8a4659997e05..ac8a83fc2ad9 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -588,29 +588,25 @@ static int snap_by_name(struct rbd_image_header *header, const char *snap_name, static int rbd_header_set_snap(struct rbd_device *rbd_dev, u64 *size) { - struct rbd_image_header *header = &rbd_dev->header; - struct ceph_snap_context *snapc = header->snapc; - int ret = -ENOENT; + int ret; down_write(&rbd_dev->header_rwsem); if (!memcmp(rbd_dev->snap_name, RBD_SNAP_HEAD_NAME, sizeof (RBD_SNAP_HEAD_NAME))) { - if (header->total_snaps) - snapc->seq = header->snap_seq; - else - snapc->seq = 0; rbd_dev->snap_id = CEPH_NOSNAP; rbd_dev->snap_exists = false; rbd_dev->read_only = 0; if (size) - *size = header->image_size; + *size = rbd_dev->header.image_size; } else { - ret = snap_by_name(header, rbd_dev->snap_name, - &snapc->seq, size); + u64 snap_id = 0; + + ret = snap_by_name(&rbd_dev->header, rbd_dev->snap_name, + &snap_id, size); if (ret < 0) goto done; - rbd_dev->snap_id = snapc->seq; + rbd_dev->snap_id = snap_id; rbd_dev->snap_exists = true; rbd_dev->read_only = 1; } -- GitLab From 505cbb9bedc8c609c31d86ff4f8f656e5a0f9c49 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 08:49:18 -0500 Subject: [PATCH 4727/5711] rbd: set snapc->seq only when refreshing header In rbd_header_add_snap() there is code to set snapc->seq to the just-added snapshot id. This is the only remnant left of the use of that field for recording which snapshot an rbd_dev was associated with. That functionality is no longer supported, so get rid of that final bit of code. Doing so means we never actually set snapc->seq any more. On the server, the snapshot context's sequence value represents the highest snapshot id ever issued for a particular rbd image. So we'll make it have that meaning here as well. To do so, set this value whenever the rbd header is (re-)read. That way it will always be consistent with the rest of the snapshot context we maintain. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index ac8a83fc2ad9..c299a55e3ff1 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -537,6 +537,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, atomic_set(&header->snapc->nref, 1); header->snap_seq = le64_to_cpu(ondisk->snap_seq); + header->snapc->seq = le64_to_cpu(ondisk->snap_seq); header->snapc->num_snaps = snap_count; header->total_snaps = snap_count; @@ -1685,14 +1686,7 @@ static int rbd_header_add_snap(struct rbd_device *rbd_dev, kfree(data); - if (ret < 0) - return ret; - - down_write(&rbd_dev->header_rwsem); - rbd_dev->header.snapc->seq = new_snapid; - up_write(&rbd_dev->header_rwsem); - - return 0; + return ret < 0 ? ret : 0; bad: return -ERANGE; } -- GitLab From 9e15dc735a7a0418be14e2deab44ddee369af857 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 08:49:18 -0500 Subject: [PATCH 4728/5711] rbd: kill rbd_image_header->snap_seq The snap_seq field in an rbd_image_header structure held the value from the rbd image header when it was last refreshed. We now maintain this value in the snapc->seq field. So get rid of the other one. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index c299a55e3ff1..6df8c62c40f5 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -82,7 +82,6 @@ struct rbd_image_header { __u8 comp_type; struct ceph_snap_context *snapc; size_t snap_names_len; - u64 snap_seq; u32 total_snaps; char *snap_names; @@ -536,7 +535,6 @@ static int rbd_header_from_disk(struct rbd_image_header *header, header->comp_type = ondisk->options.comp_type; atomic_set(&header->snapc->nref, 1); - header->snap_seq = le64_to_cpu(ondisk->snap_seq); header->snapc->seq = le64_to_cpu(ondisk->snap_seq); header->snapc->num_snaps = snap_count; header->total_snaps = snap_count; -- GitLab From a66f8c97a31fd7b2cfd7b86d4789858dbfbedffb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 09:09:27 -0500 Subject: [PATCH 4729/5711] rbd: drop extra header_rwsem init In commit c666601a there was inadvertently added an extra initialization of rbd_dev->header_rwsem. This gets rid of the duplicate. Reported-by: Guangliang Zhao Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 6df8c62c40f5..b9895feda5ee 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2458,8 +2458,6 @@ static ssize_t rbd_add(struct bus_type *bus, INIT_LIST_HEAD(&rbd_dev->snaps); init_rwsem(&rbd_dev->header_rwsem); - init_rwsem(&rbd_dev->header_rwsem); - /* generate unique id: find highest unique id, add one */ rbd_id_get(rbd_dev); -- GitLab From a05932905695f8c6c06d353ecd52c8e5d607cc77 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 09:09:27 -0500 Subject: [PATCH 4730/5711] rbd: simplify __rbd_remove_all_snaps() This just replaces a while loop with list_for_each_entry_safe() in __rbd_remove_all_snaps(). Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index b9895feda5ee..74e6a3329706 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1692,11 +1692,10 @@ bad: static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) { struct rbd_snap *snap; + struct rbd_snap *next; - while (!list_empty(&rbd_dev->snaps)) { - snap = list_first_entry(&rbd_dev->snaps, struct rbd_snap, node); + list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) __rbd_remove_snap_dev(rbd_dev, snap); - } } /* -- GitLab From bd919d45aa61c19d9ed82548d6deb06bcae31153 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 13 Jul 2012 20:35:11 -0500 Subject: [PATCH 4731/5711] rbd: clean up a few dout() calls There was a dout() call in rbd_do_request() that was reporting the reporting the offset as the length and vice versa. While fixing that I did a quick scan of other dout() calls and fixed a couple of other minor things. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 74e6a3329706..bb7f436b1765 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -734,9 +734,8 @@ static struct bio *bio_chain_clone(struct bio **old, struct bio **next, * split_bio will BUG_ON if this is not the case */ dout("bio_chain_clone split! total=%d remaining=%d" - "bi_size=%d\n", - (int)total, (int)len-total, - (int)old_chain->bi_size); + "bi_size=%u\n", + total, len - total, old_chain->bi_size); /* split the bio. We'll release it either in the next call, or it will have to be released outside */ @@ -816,8 +815,8 @@ static void rbd_coll_end_req_index(struct request *rq, struct request_queue *q; int min, max, i; - dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n", - coll, index, ret, len); + dout("rbd_coll_end_req_index %p index %d ret %d len %llu\n", + coll, index, ret, (unsigned long long) len); if (!rq) return; @@ -894,8 +893,8 @@ static int rbd_do_request(struct request *rq, req_data->coll_index = coll_index; } - dout("rbd_do_request object_name=%s ofs=%lld len=%lld\n", - object_name, len, ofs); + dout("rbd_do_request object_name=%s ofs=%llu len=%llu\n", object_name, + (unsigned long long) ofs, (unsigned long long) len); osdc = &rbd_dev->rbd_client->client->osdc; req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, @@ -948,8 +947,9 @@ static int rbd_do_request(struct request *rq, ret = ceph_osdc_wait_request(osdc, req); if (ver) *ver = le64_to_cpu(req->r_reassert_version.version); - dout("reassert_ver=%lld\n", - le64_to_cpu(req->r_reassert_version.version)); + dout("reassert_ver=%llu\n", + (unsigned long long) + le64_to_cpu(req->r_reassert_version.version)); ceph_osdc_put_request(req); } return ret; @@ -983,7 +983,8 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg) bytes = le64_to_cpu(op->extent.length); read_op = (le16_to_cpu(op->op) == CEPH_OSD_OP_READ); - dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc); + dout("rbd_req_cb bytes=%llu readop=%d rc=%d\n", + (unsigned long long) bytes, read_op, (int) rc); if (rc == -ENOENT && read_op) { zero_bio_chain(req_data->bio, 0); @@ -1217,8 +1218,9 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) if (!rbd_dev) return; - dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", - rbd_dev->header_name, notify_id, (int) opcode); + dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n", + rbd_dev->header_name, (unsigned long long) notify_id, + (unsigned int) opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rc = __rbd_refresh_header(rbd_dev); hver = rbd_dev->header.obj_version; @@ -1314,9 +1316,9 @@ static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data) if (!rbd_dev) return; - dout("rbd_notify_cb %s notify_id=%lld opcode=%d\n", - rbd_dev->header_name, - notify_id, (int)opcode); + dout("rbd_notify_cb %s notify_id=%llu opcode=%u\n", + rbd_dev->header_name, (unsigned long long) notify_id, + (unsigned int) opcode); } /* @@ -1437,7 +1439,8 @@ static void rbd_rq_fn(struct request_queue *q) struct bio *bio; struct bio *rq_bio, *next_bio = NULL; bool do_write; - int size, op_size = 0; + unsigned int size; + u64 op_size = 0; u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; @@ -1484,7 +1487,7 @@ static void rbd_rq_fn(struct request_queue *q) dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", - size, blk_rq_pos(rq) * SECTOR_SIZE); + size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE); num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size); coll = rbd_alloc_coll(num_segs); @@ -1497,7 +1500,7 @@ static void rbd_rq_fn(struct request_queue *q) do { /* a bio clone to be passed down to OSD req */ - dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); + dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt); op_size = rbd_get_segment(&rbd_dev->header, rbd_dev->header.object_prefix, ofs, size, @@ -1664,7 +1667,7 @@ static int rbd_header_add_snap(struct rbd_device *rbd_dev, monc = &rbd_dev->rbd_client->client->monc; ret = ceph_monc_create_snapid(monc, rbd_dev->pool_id, &new_snapid); - dout("created snapid=%lld\n", new_snapid); + dout("created snapid=%llu\n", (unsigned long long) new_snapid); if (ret < 0) return ret; -- GitLab From aa711ee3402ad10ffd5b70ce0417fadc9a95cccf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 13 Jul 2012 20:35:11 -0500 Subject: [PATCH 4732/5711] ceph: define snap counts as u32 everywhere There are two structures in which a count of snapshots are maintained: struct ceph_snap_context { ... u32 num_snaps; ... } and struct ceph_snap_realm { ... u32 num_prior_parent_snaps; /* had prior to parent_since */ ... u32 num_snaps; ... } These fields never take on negative values (e.g., to hold special meaning), and so are really inherently unsigned. Furthermore they take their value from over-the-wire or on-disk formatted 32-bit values. So change their definition to have type u32, and change some spots elsewhere in the code to account for this change. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- fs/ceph/snap.c | 18 ++++++++++-------- fs/ceph/super.h | 4 ++-- include/linux/ceph/libceph.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index e5206fc76562..cbb2f54a3019 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -296,8 +296,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) struct ceph_snap_realm *parent = realm->parent; struct ceph_snap_context *snapc; int err = 0; - int i; - int num = realm->num_prior_parent_snaps + realm->num_snaps; + u32 num = realm->num_prior_parent_snaps + realm->num_snaps; /* * build parent context, if it hasn't been built. @@ -321,11 +320,11 @@ static int build_snap_context(struct ceph_snap_realm *realm) realm->cached_context->seq == realm->seq && (!parent || realm->cached_context->seq >= parent->cached_context->seq)) { - dout("build_snap_context %llx %p: %p seq %lld (%d snaps)" + dout("build_snap_context %llx %p: %p seq %lld (%u snaps)" " (unchanged)\n", realm->ino, realm, realm->cached_context, realm->cached_context->seq, - realm->cached_context->num_snaps); + (unsigned int) realm->cached_context->num_snaps); return 0; } @@ -342,6 +341,8 @@ static int build_snap_context(struct ceph_snap_realm *realm) num = 0; snapc->seq = realm->seq; if (parent) { + u32 i; + /* include any of parent's snaps occurring _after_ my parent became my parent */ for (i = 0; i < parent->cached_context->num_snaps; i++) @@ -361,8 +362,9 @@ static int build_snap_context(struct ceph_snap_realm *realm) sort(snapc->snaps, num, sizeof(u64), cmpu64_rev, NULL); snapc->num_snaps = num; - dout("build_snap_context %llx %p: %p seq %lld (%d snaps)\n", - realm->ino, realm, snapc, snapc->seq, snapc->num_snaps); + dout("build_snap_context %llx %p: %p seq %lld (%u snaps)\n", + realm->ino, realm, snapc, snapc->seq, + (unsigned int) snapc->num_snaps); if (realm->cached_context) ceph_put_snap_context(realm->cached_context); @@ -402,9 +404,9 @@ static void rebuild_snap_realms(struct ceph_snap_realm *realm) * helper to allocate and decode an array of snapids. free prior * instance, if any. */ -static int dup_array(u64 **dst, __le64 *src, int num) +static int dup_array(u64 **dst, __le64 *src, u32 num) { - int i; + u32 i; kfree(*dst); if (num) { diff --git a/fs/ceph/super.h b/fs/ceph/super.h index fc35036d258d..3ea48b7b98b3 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -612,9 +612,9 @@ struct ceph_snap_realm { u64 parent_since; /* snapid when our current parent became so */ u64 *prior_parent_snaps; /* snaps inherited from any parents we */ - int num_prior_parent_snaps; /* had prior to parent_since */ + u32 num_prior_parent_snaps; /* had prior to parent_since */ u64 *snaps; /* snaps specific to this realm */ - int num_snaps; + u32 num_snaps; struct ceph_snap_realm *parent; struct list_head children; /* list of child realms */ diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index ea072e1f9db9..42624789b06f 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -154,7 +154,7 @@ struct ceph_client { struct ceph_snap_context { atomic_t nref; u64 seq; - int num_snaps; + u32 num_snaps; u64 snaps[]; }; -- GitLab From 8e94af8e2b582e5915abc171a28130881d1c26e4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:40 -0500 Subject: [PATCH 4733/5711] rbd: encapsulate header validity test If an rbd image header is read and it doesn't begin with the expected magic information, a warning is displayed. This is a fairly simple test, but it could be extended at some point. Fix the comparison so it actually looks at the "text" field rather than the front of the structure. In any case, encapsulate the validity test in its own function. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index bb7f436b1765..ae65fac2c42b 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -481,6 +481,12 @@ static void rbd_coll_release(struct kref *kref) kfree(coll); } +static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) +{ + return !memcmp(&ondisk->text, + RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT)); +} + /* * Create a new header structure, translate header format from the on-disk * header. @@ -492,7 +498,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, { u32 i, snap_count; - if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) + if (!rbd_dev_ondisk_valid(ondisk)) return -ENXIO; snap_count = le32_to_cpu(ondisk->snap_count); -- GitLab From de71a2970d57463d3d965025e33ec3adcf391248 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 3 Jul 2012 16:01:19 -0500 Subject: [PATCH 4734/5711] rbd: rename rbd_device->id The "id" field of an rbd device structure represents the unique client-local device id mapped to the underlying rbd image. Each rbd image will have another id--the image id--and each snapshot has its own id as well. The simple name "id" no longer conveys the information one might like to have. Rename the device "id" field in struct rbd_dev to be "dev_id" to make it a little more obvious what we're dealing with without having to think more about context. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index ae65fac2c42b..fe7a9e15b6f2 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -147,7 +147,7 @@ struct rbd_snap { * a single device */ struct rbd_device { - int id; /* blkdev unique id */ + int dev_id; /* blkdev unique id */ int major; /* blkdev assigned major */ struct gendisk *disk; /* blkdev's gendisk and rq */ @@ -1782,7 +1782,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) goto out; snprintf(disk->disk_name, sizeof(disk->disk_name), RBD_DRV_NAME "%d", - rbd_dev->id); + rbd_dev->dev_id); disk->major = rbd_dev->major; disk->first_minor = 0; disk->fops = &rbd_bd_ops; @@ -2171,7 +2171,7 @@ static int rbd_bus_add_dev(struct rbd_device *rbd_dev) dev->type = &rbd_device_type; dev->parent = &rbd_root_dev; dev->release = rbd_dev_release; - dev_set_name(dev, "%d", rbd_dev->id); + dev_set_name(dev, "%d", rbd_dev->dev_id); ret = device_register(dev); if (ret < 0) goto out; @@ -2219,7 +2219,7 @@ static atomic64_t rbd_id_max = ATOMIC64_INIT(0); */ static void rbd_id_get(struct rbd_device *rbd_dev) { - rbd_dev->id = atomic64_inc_return(&rbd_id_max); + rbd_dev->dev_id = atomic64_inc_return(&rbd_id_max); spin_lock(&rbd_dev_list_lock); list_add_tail(&rbd_dev->node, &rbd_dev_list); @@ -2233,7 +2233,7 @@ static void rbd_id_get(struct rbd_device *rbd_dev) static void rbd_id_put(struct rbd_device *rbd_dev) { struct list_head *tmp; - int rbd_id = rbd_dev->id; + int rbd_id = rbd_dev->dev_id; int max_id; BUG_ON(rbd_id < 1); @@ -2472,7 +2472,7 @@ static ssize_t rbd_add(struct bus_type *bus, /* Fill in the device name, now that we have its id. */ BUILD_BUG_ON(DEV_NAME_LEN < sizeof (RBD_DRV_NAME) + MAX_INT_FORMAT_WIDTH); - sprintf(rbd_dev->name, "%s%d", RBD_DRV_NAME, rbd_dev->id); + sprintf(rbd_dev->name, "%s%d", RBD_DRV_NAME, rbd_dev->dev_id); /* parse add command */ rc = rbd_add_parse_args(rbd_dev, buf, &mon_addrs, &mon_addrs_size, @@ -2549,7 +2549,7 @@ err_nomem: return (ssize_t) rc; } -static struct rbd_device *__rbd_get_dev(unsigned long id) +static struct rbd_device *__rbd_get_dev(unsigned long dev_id) { struct list_head *tmp; struct rbd_device *rbd_dev; @@ -2557,7 +2557,7 @@ static struct rbd_device *__rbd_get_dev(unsigned long id) spin_lock(&rbd_dev_list_lock); list_for_each(tmp, &rbd_dev_list) { rbd_dev = list_entry(tmp, struct rbd_device, node); - if (rbd_dev->id == id) { + if (rbd_dev->dev_id == dev_id) { spin_unlock(&rbd_dev_list_lock); return rbd_dev; } -- GitLab From 9a5d690b08478fc2358d885703014853e44a357e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 09:09:27 -0500 Subject: [PATCH 4735/5711] rbd: snapc is unused in rbd_req_sync_read() The "snapc" parameter to in rbd_req_sync_read() is not used, so get rid of it. Reported-by: Josh Durgin Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index fe7a9e15b6f2..eed58e99e18d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1169,7 +1169,6 @@ static int rbd_req_read(struct request *rq, * Request sync osd read */ static int rbd_req_sync_read(struct rbd_device *rbd_dev, - struct ceph_snap_context *snapc, u64 snapid, const char *object_name, u64 ofs, u64 len, @@ -1619,7 +1618,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev, return -ENOMEM; rc = rbd_req_sync_read(rbd_dev, - NULL, CEPH_NOSNAP, + CEPH_NOSNAP, rbd_dev->header_name, 0, len, (char *)dh, &ver); -- GitLab From ed63f4fd9a88218ee709e8f57c36c0c5f219a7ad Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 09:09:27 -0500 Subject: [PATCH 4736/5711] rbd: drop rbd_header_from_disk() gfp_flags parameter The function rbd_header_from_disk() is only called in one spot, and it passes GFP_KERNEL as its value for the gfp_flags parameter. Just drop that parameter and substitute GFP_KERNEL everywhere within that function it had been used. (If we find we need the parameter again in the future it's easy enough to add back again.) Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index eed58e99e18d..34ca5c686b46 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -493,8 +493,7 @@ static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) */ static int rbd_header_from_disk(struct rbd_image_header *header, struct rbd_image_header_ondisk *ondisk, - u32 allocated_snaps, - gfp_t gfp_flags) + u32 allocated_snaps) { u32 i, snap_count; @@ -507,18 +506,18 @@ static int rbd_header_from_disk(struct rbd_image_header *header, return -EINVAL; header->snapc = kmalloc(sizeof(struct ceph_snap_context) + snap_count * sizeof(u64), - gfp_flags); + GFP_KERNEL); if (!header->snapc) return -ENOMEM; header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); if (snap_count) { header->snap_names = kmalloc(header->snap_names_len, - gfp_flags); + GFP_KERNEL); if (!header->snap_names) goto err_snapc; header->snap_sizes = kmalloc(snap_count * sizeof(u64), - gfp_flags); + GFP_KERNEL); if (!header->snap_sizes) goto err_names; } else { @@ -527,7 +526,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, } header->object_prefix = kmalloc(sizeof (ondisk->block_name) + 1, - gfp_flags); + GFP_KERNEL); if (!header->object_prefix) goto err_sizes; @@ -1625,7 +1624,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev, if (rc < 0) goto out_dh; - rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL); + rc = rbd_header_from_disk(header, dh, snap_count); if (rc < 0) { if (rc == -ENXIO) pr_warning("unrecognized header format" -- GitLab From 14e7085d8460bf45e7145524a13802f1f4f9d81f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 19 Jul 2012 09:09:27 -0500 Subject: [PATCH 4737/5711] rbd: drop rbd_dev parameter in snap functions Both rbd_register_snap_dev() and __rbd_remove_snap_dev() have rbd_dev parameters that are unused. Remove them. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 34ca5c686b46..9e960c3ce1c4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -202,8 +202,7 @@ static ssize_t rbd_snap_add(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); -static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev, - struct rbd_snap *snap); +static void __rbd_remove_snap_dev(struct rbd_snap *snap); static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count); @@ -1702,7 +1701,7 @@ static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) struct rbd_snap *next; list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) - __rbd_remove_snap_dev(rbd_dev, snap); + __rbd_remove_snap_dev(snap); } /* @@ -2010,15 +2009,13 @@ static struct device_type rbd_snap_device_type = { .release = rbd_snap_dev_release, }; -static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev, - struct rbd_snap *snap) +static void __rbd_remove_snap_dev(struct rbd_snap *snap) { list_del(&snap->node); device_unregister(&snap->dev); } -static int rbd_register_snap_dev(struct rbd_device *rbd_dev, - struct rbd_snap *snap, +static int rbd_register_snap_dev(struct rbd_snap *snap, struct device *parent) { struct device *dev = &snap->dev; @@ -2045,8 +2042,7 @@ static int __rbd_add_snap_dev(struct rbd_device *rbd_dev, snap->size = rbd_dev->header.snap_sizes[i]; snap->id = rbd_dev->header.snapc->snaps[i]; if (device_is_registered(&rbd_dev->dev)) { - ret = rbd_register_snap_dev(rbd_dev, snap, - &rbd_dev->dev); + ret = rbd_register_snap_dev(snap, &rbd_dev->dev); if (ret < 0) goto err; } @@ -2111,7 +2107,7 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) */ if (rbd_dev->snap_id == old_snap->id) rbd_dev->snap_exists = false; - __rbd_remove_snap_dev(rbd_dev, old_snap); + __rbd_remove_snap_dev(old_snap); continue; } if (old_snap->id == cur_id) { @@ -2175,8 +2171,7 @@ static int rbd_bus_add_dev(struct rbd_device *rbd_dev) goto out; list_for_each_entry(snap, &rbd_dev->snaps, node) { - ret = rbd_register_snap_dev(rbd_dev, snap, - &rbd_dev->dev); + ret = rbd_register_snap_dev(snap, &rbd_dev->dev); if (ret < 0) break; } -- GitLab From 0e6f322d550a104b2065288c9f6426d5c0414b76 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:40 -0500 Subject: [PATCH 4738/5711] rbd: drop "object_name" from rbd_req_sync_watch() rbd_req_sync_watch() is only called in one place, and in that place it passes rbd_dev->header_name as the value of the "object_name" parameter. This value is available within the function already. Having the extra parameter leaves the impression the object name could take on different values, but it does not. So get rid of the parameter. We can always add it back again if we find we want to watch some other object in the future. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 9e960c3ce1c4..b8e557fbf73b 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1238,9 +1238,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) /* * Request sync osd watch */ -static int rbd_req_sync_watch(struct rbd_device *rbd_dev, - const char *object_name, - u64 ver) +static int rbd_req_sync_watch(struct rbd_device *rbd_dev) { struct ceph_osd_req_op *ops; struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; @@ -1254,7 +1252,7 @@ static int rbd_req_sync_watch(struct rbd_device *rbd_dev, if (ret < 0) goto fail; - ops[0].watch.ver = cpu_to_le64(ver); + ops[0].watch.ver = cpu_to_le64(rbd_dev->header.obj_version); ops[0].watch.cookie = cpu_to_le64(rbd_dev->watch_event->cookie); ops[0].watch.flag = 1; @@ -1263,7 +1261,8 @@ static int rbd_req_sync_watch(struct rbd_device *rbd_dev, 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, - object_name, 0, 0, NULL, + rbd_dev->header_name, + 0, 0, NULL, &rbd_dev->watch_request, NULL); if (ret < 0) @@ -2190,8 +2189,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) int ret, rc; do { - ret = rbd_req_sync_watch(rbd_dev, rbd_dev->header_name, - rbd_dev->header.obj_version); + ret = rbd_req_sync_watch(rbd_dev); if (ret == -ERANGE) { mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rc = __rbd_refresh_header(rbd_dev); -- GitLab From 4cb162508afade6d24d58e30be2bbaed80cf84d5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:40 -0500 Subject: [PATCH 4739/5711] rbd: drop "object_name" from rbd_req_sync_notify() rbd_req_sync_notify() only ever uses rbd_dev->header_name as the value of its "object_name" parameter, and that value is available within the function already. So get rid of the parameter. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index b8e557fbf73b..d187d087a505 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1326,8 +1326,7 @@ static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data) /* * Request sync osd notify */ -static int rbd_req_sync_notify(struct rbd_device *rbd_dev, - const char *object_name) +static int rbd_req_sync_notify(struct rbd_device *rbd_dev) { struct ceph_osd_req_op *ops; struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; @@ -1358,7 +1357,8 @@ static int rbd_req_sync_notify(struct rbd_device *rbd_dev, 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, - object_name, 0, 0, NULL, NULL, NULL); + rbd_dev->header_name, + 0, 0, NULL, NULL, NULL); if (ret < 0) goto fail_event; @@ -2651,7 +2651,7 @@ static ssize_t rbd_snap_add(struct device *dev, mutex_unlock(&ctl_mutex); /* make a best effort, don't error if failed */ - rbd_req_sync_notify(rbd_dev, rbd_dev->header_name); + rbd_req_sync_notify(rbd_dev); ret = count; kfree(name); -- GitLab From 7f0a24d8552db422640e810414c43579bb3d9fb9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:40 -0500 Subject: [PATCH 4740/5711] rbd: drop "object_name" from rbd_req_sync_notify_ack() rbd_req_sync_notify_ack() only ever uses rbd_dev->header_name as the value of its "object_name" parameter, and that value is available within the function already. So get rid of the parameter. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d187d087a505..7884cb0f7ce1 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1186,8 +1186,7 @@ static int rbd_req_sync_read(struct rbd_device *rbd_dev, */ static int rbd_req_sync_notify_ack(struct rbd_device *rbd_dev, u64 ver, - u64 notify_id, - const char *object_name) + u64 notify_id) { struct ceph_osd_req_op *ops; int ret; @@ -1201,7 +1200,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *rbd_dev, ops[0].watch.flag = 0; ret = rbd_do_request(NULL, rbd_dev, NULL, CEPH_NOSNAP, - object_name, 0, 0, NULL, + rbd_dev->header_name, 0, 0, NULL, NULL, 0, CEPH_OSD_FLAG_READ, ops, @@ -1232,7 +1231,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) pr_warning(RBD_DRV_NAME "%d got notification but failed to " " update snaps: %d\n", rbd_dev->major, rc); - rbd_req_sync_notify_ack(rbd_dev, hver, notify_id, rbd_dev->header_name); + rbd_req_sync_notify_ack(rbd_dev, hver, notify_id); } /* -- GitLab From 070c633f60c23a89c226eb696f4a17b08a164b10 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:41 -0500 Subject: [PATCH 4741/5711] rbd: drop "object_name" from rbd_req_sync_unwatch() rbd_req_sync_unwatch() only ever uses rbd_dev->header_name as the value of its "object_name" parameter, and that value is available within the function already. So get rid of the parameter. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 7884cb0f7ce1..30eb01e300a4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1281,8 +1281,7 @@ fail: /* * Request sync osd unwatch */ -static int rbd_req_sync_unwatch(struct rbd_device *rbd_dev, - const char *object_name) +static int rbd_req_sync_unwatch(struct rbd_device *rbd_dev) { struct ceph_osd_req_op *ops; @@ -1299,7 +1298,9 @@ static int rbd_req_sync_unwatch(struct rbd_device *rbd_dev, 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, - object_name, 0, 0, NULL, NULL, NULL); + rbd_dev->header_name, + 0, 0, NULL, NULL, NULL); + rbd_destroy_ops(ops); ceph_osdc_cancel_event(rbd_dev->watch_event); @@ -2567,7 +2568,7 @@ static void rbd_dev_release(struct device *dev) rbd_dev->watch_request); } if (rbd_dev->watch_event) - rbd_req_sync_unwatch(rbd_dev, rbd_dev->header_name); + rbd_req_sync_unwatch(rbd_dev); rbd_put_client(rbd_dev); -- GitLab From 3b5ede07b55b52c3be27749d183d87257d032065 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:22:53 -0700 Subject: [PATCH 4742/5711] libceph: fix fault locking; close socket on lossy fault If we fault on a lossy connection, we should still close the socket immediately, and do so under the con mutex. We should also take the con mutex before printing out the state bits in the debug output. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 07204f19e856..9aaf539942ac 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2330,22 +2330,23 @@ fault: */ static void ceph_fault(struct ceph_connection *con) { + mutex_lock(&con->mutex); + pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(LOSSYTX, &con->flags)) { - dout("fault on LOSSYTX channel\n"); - goto out; - } - - mutex_lock(&con->mutex); if (test_bit(CLOSED, &con->state)) goto out_unlock; con_close_socket(con); + if (test_bit(LOSSYTX, &con->flags)) { + dout("fault on LOSSYTX channel\n"); + goto out_unlock; + } + if (con->in_msg) { BUG_ON(con->in_msg->con != con); con->in_msg->con = NULL; @@ -2392,7 +2393,6 @@ static void ceph_fault(struct ceph_connection *con) out_unlock: mutex_unlock(&con->mutex); -out: /* * in case we faulted due to authentication, invalidate our * current tickets so that we can get new ones. -- GitLab From 00650931e52e97fe64096bec167f5a6780dfd94a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:33:04 -0700 Subject: [PATCH 4743/5711] libceph: move msgr clear_standby under con mutex protection Avoid dropping and retaking con->mutex in the ceph_con_send() case by leaving locking up to the caller. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9aaf539942ac..1a3cb4a4f180 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2441,12 +2441,10 @@ static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ if (test_and_clear_bit(STANDBY, &con->state)) { - mutex_lock(&con->mutex); dout("clear_standby %p and ++connect_seq\n", con); con->connect_seq++; WARN_ON(test_bit(WRITE_PENDING, &con->flags)); WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); - mutex_unlock(&con->mutex); } } @@ -2483,11 +2481,12 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) le32_to_cpu(msg->hdr.front_len), le32_to_cpu(msg->hdr.middle_len), le32_to_cpu(msg->hdr.data_len)); + + clear_standby(con); mutex_unlock(&con->mutex); /* if there wasn't anything waiting to send before, queue * new work */ - clear_standby(con); if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } @@ -2574,7 +2573,9 @@ void ceph_msg_revoke_incoming(struct ceph_msg *msg) void ceph_con_keepalive(struct ceph_connection *con) { dout("con_keepalive %p\n", con); + mutex_lock(&con->mutex); clear_standby(con); + mutex_unlock(&con->mutex); if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); -- GitLab From a59b55a602b6c741052d79c1e3643f8440cddd27 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:34:04 -0700 Subject: [PATCH 4744/5711] libceph: move ceph_con_send() closed check under the con mutex Take the con mutex before checking whether the connection is closed to avoid racing with someone else closing it. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1a3cb4a4f180..20e60a80bc29 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2453,22 +2453,20 @@ static void clear_standby(struct ceph_connection *con) */ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) { - if (test_bit(CLOSED, &con->state)) { - dout("con_send %p closed, dropping %p\n", con, msg); - ceph_msg_put(msg); - return; - } - /* set src+dst */ msg->hdr.src = con->msgr->inst.name; - BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len)); - msg->needs_out_seq = true; - /* queue */ mutex_lock(&con->mutex); + if (test_bit(CLOSED, &con->state)) { + dout("con_send %p closed, dropping %p\n", con, msg); + ceph_msg_put(msg); + mutex_unlock(&con->mutex); + return; + } + BUG_ON(msg->con != NULL); msg->con = con->ops->get(con); BUG_ON(msg->con == NULL); -- GitLab From 2e8cb10063820af7ed7638e3fd9013eee21266e7 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:40:04 -0700 Subject: [PATCH 4745/5711] libceph: drop gratuitous socket close calls in con_work If the state is CLOSED or OPENING, we shouldn't have a socket. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 20e60a80bc29..32ab7cd089a3 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2284,15 +2284,15 @@ restart: dout("con_work %p STANDBY\n", con); goto done; } - if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */ - dout("con_work CLOSED\n"); - con_close_socket(con); + if (test_bit(CLOSED, &con->state)) { + dout("con_work %p CLOSED\n", con); + BUG_ON(con->sock); goto done; } if (test_and_clear_bit(OPENING, &con->state)) { /* reopen w/ new peer */ dout("con_work OPENING\n"); - con_close_socket(con); + BUG_ON(con->sock); } ret = try_read(con); -- GitLab From ee76e0736db8455e3b11827d6899bd2a4e1d0584 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 16:45:49 -0700 Subject: [PATCH 4746/5711] libceph: close socket directly from ceph_con_close() It is simpler to do this immediately, since we already hold the con mutex. It also avoids the need to deal with a not-quite-CLOSED socket in con_work. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 32ab7cd089a3..46ce113732e6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -519,14 +519,8 @@ void ceph_con_close(struct ceph_connection *con) reset_connection(con); con->peer_global_seq = 0; cancel_delayed_work(&con->work); + con_close_socket(con); mutex_unlock(&con->mutex); - - /* - * We cannot close the socket directly from here because the - * work threads use it without holding the mutex. Instead, let - * con_work() do it. - */ - queue_con(con); } EXPORT_SYMBOL(ceph_con_close); -- GitLab From d7353dd5aaf22ed611fbcd0d4a4a12fb30659290 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:19:43 -0700 Subject: [PATCH 4747/5711] libceph: drop unnecessary CLOSED check in socket state change callback If we are CLOSED, the socket is closed and we won't get these. Signed-off-by: Sage Weil --- net/ceph/messenger.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 46ce113732e6..e7320cd5fdbc 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -296,9 +296,6 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s %p state = %lu sk_state = %u\n", __func__, con, con->state, sk->sk_state); - if (test_bit(CLOSED, &con->state)) - return; - switch (sk->sk_state) { case TCP_CLOSE: dout("%s TCP_CLOSE\n", __func__); -- GitLab From 8dacc7da69a491c515851e68de6036f21b5663ce Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:24:40 -0700 Subject: [PATCH 4748/5711] libceph: replace connection state bits with states Use a simple set of 6 enumerated values for the socket states (CON_STATE_*) and use those instead of the state bits. All of the con->state checks are now under the protection of the con mutex, so this is safe. It also simplifies many of the state checks because we can check for anything other than the expected state instead of various bits for races we can think of. This appears to hold up well to stress testing both with and without socket failure injection on the server side. Signed-off-by: Sage Weil --- include/linux/ceph/messenger.h | 12 --- net/ceph/messenger.c | 130 +++++++++++++++++---------------- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index a310d7fe6e29..d9c2b8f5abde 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -116,18 +116,6 @@ struct ceph_msg_pos { #define SOCK_CLOSED 11 /* socket state changed to closed */ #define BACKOFF 15 -/* - * ceph_connection states - */ -#define CONNECTING 1 -#define NEGOTIATING 2 -#define CONNECTED 5 -#define STANDBY 8 /* no outgoing messages, socket closed. we keep - * the ceph_connection around to maintain shared - * state with the peer. */ -#define CLOSED 10 /* we've closed the connection */ -#define OPENING 13 /* open connection w/ (possibly new) peer */ - /* * A single connection with another host. * diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e7320cd5fdbc..563e46aa4d6d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -77,6 +77,17 @@ #define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ #define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ +/* + * connection states + */ +#define CON_STATE_CLOSED 1 /* -> PREOPEN */ +#define CON_STATE_PREOPEN 2 /* -> CONNECTING, CLOSED */ +#define CON_STATE_CONNECTING 3 /* -> NEGOTIATING, CLOSED */ +#define CON_STATE_NEGOTIATING 4 /* -> OPEN, CLOSED */ +#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ +#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ + + /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; static char tag_ack = CEPH_MSGR_TAG_ACK; @@ -503,11 +514,7 @@ void ceph_con_close(struct ceph_connection *con) mutex_lock(&con->mutex); dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); - clear_bit(NEGOTIATING, &con->state); - clear_bit(CONNECTING, &con->state); - clear_bit(CONNECTED, &con->state); - clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ - set_bit(CLOSED, &con->state); + con->state = CON_STATE_CLOSED; clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(KEEPALIVE_PENDING, &con->flags); @@ -530,8 +537,9 @@ void ceph_con_open(struct ceph_connection *con, { mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); - set_bit(OPENING, &con->state); - WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + + BUG_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; con->peer_name.type = (__u8) entity_type; con->peer_name.num = cpu_to_le64(entity_num); @@ -571,7 +579,7 @@ void ceph_con_init(struct ceph_connection *con, void *private, INIT_LIST_HEAD(&con->out_sent); INIT_DELAYED_WORK(&con->work, con_work); - set_bit(CLOSED, &con->state); + con->state = CON_STATE_CLOSED; } EXPORT_SYMBOL(ceph_con_init); @@ -809,27 +817,21 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection if (!con->ops->get_authorizer) { con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; con->out_connect.authorizer_len = 0; - return NULL; } /* Can't hold the mutex while getting authorizer */ - mutex_unlock(&con->mutex); - auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry); - mutex_lock(&con->mutex); if (IS_ERR(auth)) return auth; - if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags)) + if (con->state != CON_STATE_NEGOTIATING) return ERR_PTR(-EAGAIN); con->auth_reply_buf = auth->authorizer_reply_buf; con->auth_reply_buf_len = auth->authorizer_reply_buf_len; - - return auth; } @@ -1484,7 +1486,8 @@ static int process_banner(struct ceph_connection *con) static void fail_protocol(struct ceph_connection *con) { reset_connection(con); - set_bit(CLOSED, &con->state); /* in case there's queued work */ + BUG_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_CLOSED; } static int process_connect(struct ceph_connection *con) @@ -1558,8 +1561,7 @@ static int process_connect(struct ceph_connection *con) if (con->ops->peer_reset) con->ops->peer_reset(con); mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) + if (con->state != CON_STATE_NEGOTIATING) return -EAGAIN; break; @@ -1605,8 +1607,10 @@ static int process_connect(struct ceph_connection *con) fail_protocol(con); return -1; } - clear_bit(NEGOTIATING, &con->state); - set_bit(CONNECTED, &con->state); + + BUG_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; @@ -1994,8 +1998,9 @@ more: dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); /* open the socket first? */ - if (con->sock == NULL) { - set_bit(CONNECTING, &con->state); + if (con->state == CON_STATE_PREOPEN) { + BUG_ON(con->sock); + con->state = CON_STATE_CONNECTING; con_out_kvec_reset(con); prepare_write_banner(con); @@ -2046,8 +2051,7 @@ more_kvec: } do_next: - if (!test_bit(CONNECTING, &con->state) && - !test_bit(NEGOTIATING, &con->state)) { + if (con->state == CON_STATE_OPEN) { /* is anything else pending? */ if (!list_empty(&con->out_queue)) { prepare_write_message(con); @@ -2081,29 +2085,19 @@ static int try_read(struct ceph_connection *con) { int ret = -1; - if (!con->sock) - return 0; - - if (test_bit(STANDBY, &con->state)) +more: + dout("try_read start on %p state %lu\n", con, con->state); + if (con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN) return 0; - dout("try_read start on %p\n", con); + BUG_ON(!con->sock); -more: dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag, con->in_base_pos); - /* - * process_connect and process_message drop and re-take - * con->mutex. make sure we handle a racing close or reopen. - */ - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) { - ret = -EAGAIN; - goto out; - } - - if (test_bit(CONNECTING, &con->state)) { + if (con->state == CON_STATE_CONNECTING) { dout("try_read connecting\n"); ret = read_partial_banner(con); if (ret <= 0) @@ -2112,8 +2106,8 @@ more: if (ret < 0) goto out; - clear_bit(CONNECTING, &con->state); - set_bit(NEGOTIATING, &con->state); + BUG_ON(con->state != CON_STATE_CONNECTING); + con->state = CON_STATE_NEGOTIATING; /* Banner is good, exchange connection info */ ret = prepare_write_connect(con); @@ -2125,7 +2119,7 @@ more: goto out; } - if (test_bit(NEGOTIATING, &con->state)) { + if (con->state == CON_STATE_NEGOTIATING) { dout("try_read negotiating\n"); ret = read_partial_connect(con); if (ret <= 0) @@ -2136,6 +2130,8 @@ more: goto more; } + BUG_ON(con->state != CON_STATE_OPEN); + if (con->in_base_pos < 0) { /* * skipping + discarding content. @@ -2169,8 +2165,8 @@ more: prepare_read_ack(con); break; case CEPH_MSGR_TAG_CLOSE: - clear_bit(CONNECTED, &con->state); - set_bit(CLOSED, &con->state); /* fixme */ + con_close_socket(con); + con->state = CON_STATE_CLOSED; goto out; default: goto bad_tag; @@ -2246,14 +2242,21 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTED, &con->state)) - con->error_msg = "socket closed"; - else if (test_and_clear_bit(NEGOTIATING, &con->state)) - con->error_msg = "negotiation failed"; - else if (test_and_clear_bit(CONNECTING, &con->state)) + switch (con->state) { + case CON_STATE_CONNECTING: con->error_msg = "connection failed"; - else + break; + case CON_STATE_NEGOTIATING: + con->error_msg = "negotiation failed"; + break; + case CON_STATE_OPEN: + con->error_msg = "socket closed"; + break; + default: + dout("unrecognized con state %d\n", (int)con->state); con->error_msg = "unrecognized con state"; + BUG(); + } goto fault; } @@ -2271,17 +2274,16 @@ restart: } } - if (test_bit(STANDBY, &con->state)) { + if (con->state == CON_STATE_STANDBY) { dout("con_work %p STANDBY\n", con); goto done; } - if (test_bit(CLOSED, &con->state)) { + if (con->state == CON_STATE_CLOSED) { dout("con_work %p CLOSED\n", con); BUG_ON(con->sock); goto done; } - if (test_and_clear_bit(OPENING, &con->state)) { - /* reopen w/ new peer */ + if (con->state == CON_STATE_PREOPEN) { dout("con_work OPENING\n"); BUG_ON(con->sock); } @@ -2328,13 +2330,15 @@ static void ceph_fault(struct ceph_connection *con) dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(CLOSED, &con->state)) - goto out_unlock; + BUG_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); con_close_socket(con); if (test_bit(LOSSYTX, &con->flags)) { - dout("fault on LOSSYTX channel\n"); + dout("fault on LOSSYTX channel, marking CLOSED\n"); + con->state = CON_STATE_CLOSED; goto out_unlock; } @@ -2355,9 +2359,10 @@ static void ceph_fault(struct ceph_connection *con) !test_bit(KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); clear_bit(WRITE_PENDING, &con->flags); - set_bit(STANDBY, &con->state); + con->state = CON_STATE_STANDBY; } else { /* retry after a delay. */ + con->state = CON_STATE_PREOPEN; if (con->delay == 0) con->delay = BASE_DELAY_INTERVAL; else if (con->delay < MAX_DELAY_INTERVAL) @@ -2431,8 +2436,9 @@ EXPORT_SYMBOL(ceph_messenger_init); static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ - if (test_and_clear_bit(STANDBY, &con->state)) { + if (con->state == CON_STATE_STANDBY) { dout("clear_standby %p and ++connect_seq\n", con); + con->state = CON_STATE_PREOPEN; con->connect_seq++; WARN_ON(test_bit(WRITE_PENDING, &con->flags)); WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); @@ -2451,7 +2457,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state)) { + if (con->state == CON_STATE_CLOSED) { dout("con_send %p closed, dropping %p\n", con, msg); ceph_msg_put(msg); mutex_unlock(&con->mutex); -- GitLab From 4a8616920860920abaa51193146fe36b38ef09aa Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:29:55 -0700 Subject: [PATCH 4749/5711] libceph: clean up con flags Rename flags with CON_FLAG prefix, move the definitions into the c file, and (better) document their meaning. Signed-off-by: Sage Weil --- include/linux/ceph/messenger.h | 10 ------ net/ceph/messenger.c | 62 ++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index d9c2b8f5abde..189ae0637634 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -106,16 +106,6 @@ struct ceph_msg_pos { #define BASE_DELAY_INTERVAL (HZ/2) #define MAX_DELAY_INTERVAL (5 * 60 * HZ) -/* - * ceph_connection flag bits - */ - -#define LOSSYTX 0 /* we can close channel or drop messages on errors */ -#define KEEPALIVE_PENDING 3 -#define WRITE_PENDING 4 /* we have data ready to send */ -#define SOCK_CLOSED 11 /* socket state changed to closed */ -#define BACKOFF 15 - /* * A single connection with another host. * diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 563e46aa4d6d..b872db5c4989 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -87,6 +87,15 @@ #define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ #define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ +/* + * ceph_connection flag bits + */ +#define CON_FLAG_LOSSYTX 0 /* we can close channel or drop + * messages on errors */ +#define CON_FLAG_KEEPALIVE_PENDING 1 /* we need to send a keepalive */ +#define CON_FLAG_WRITE_PENDING 2 /* we have data ready to send */ +#define CON_FLAG_SOCK_CLOSED 3 /* socket state changed to closed */ +#define CON_FLAG_BACKOFF 4 /* need to retry queuing delayed work */ /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; @@ -288,7 +297,7 @@ static void ceph_sock_write_space(struct sock *sk) * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ - if (test_bit(WRITE_PENDING, &con->flags)) { + if (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); @@ -313,7 +322,7 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - set_bit(SOCK_CLOSED, &con->flags); + set_bit(CON_FLAG_SOCK_CLOSED, &con->flags); queue_con(con); break; case TCP_ESTABLISHED: @@ -449,12 +458,12 @@ static int con_close_socket(struct ceph_connection *con) con->sock = NULL; /* - * Forcibly clear the SOCK_CLOSE flag. It gets set + * Forcibly clear the SOCK_CLOSED flag. It gets set * independent of the connection mutex, and we could have * received a socket close event before we had the chance to * shut the socket down. */ - clear_bit(SOCK_CLOSED, &con->flags); + clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; } @@ -516,9 +525,9 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); con->state = CON_STATE_CLOSED; - clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ - clear_bit(KEEPALIVE_PENDING, &con->flags); - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); reset_connection(con); con->peer_global_seq = 0; @@ -770,7 +779,7 @@ static void prepare_write_message(struct ceph_connection *con) /* no, queue up footer too and be done */ prepare_write_message_footer(con); - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -791,7 +800,7 @@ static void prepare_write_ack(struct ceph_connection *con) &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -802,7 +811,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) dout("prepare_write_keepalive %p\n", con); con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -845,7 +854,7 @@ static void prepare_write_banner(struct ceph_connection *con) &con->msgr->my_enc_addr); con->out_more = 0; - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } static int prepare_write_connect(struct ceph_connection *con) @@ -896,7 +905,7 @@ static int prepare_write_connect(struct ceph_connection *con) auth->authorizer_buf); con->out_more = 0; - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); return 0; } @@ -1622,7 +1631,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.connect_seq)); if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) - set_bit(LOSSYTX, &con->flags); + set_bit(CON_FLAG_LOSSYTX, &con->flags); con->delay = 0; /* reset backoff memory */ @@ -2061,14 +2070,15 @@ do_next: prepare_write_ack(con); goto more; } - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_KEEPALIVE_PENDING, + &con->flags)) { prepare_write_keepalive(con); goto more; } } /* Nothing to do! */ - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); dout("try_write nothing else to write.\n"); ret = 0; out: @@ -2241,7 +2251,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { switch (con->state) { case CON_STATE_CONNECTING: con->error_msg = "connection failed"; @@ -2260,7 +2270,7 @@ restart: goto fault; } - if (test_and_clear_bit(BACKOFF, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, round_jiffies_relative(con->delay))) { @@ -2336,7 +2346,7 @@ static void ceph_fault(struct ceph_connection *con) con_close_socket(con); - if (test_bit(LOSSYTX, &con->flags)) { + if (test_bit(CON_FLAG_LOSSYTX, &con->flags)) { dout("fault on LOSSYTX channel, marking CLOSED\n"); con->state = CON_STATE_CLOSED; goto out_unlock; @@ -2356,9 +2366,9 @@ static void ceph_fault(struct ceph_connection *con) /* If there are no messages queued or keepalive pending, place * the connection in a STANDBY state */ if (list_empty(&con->out_queue) && - !test_bit(KEEPALIVE_PENDING, &con->flags)) { + !test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); con->state = CON_STATE_STANDBY; } else { /* retry after a delay. */ @@ -2383,7 +2393,7 @@ static void ceph_fault(struct ceph_connection *con) * that when con_work restarts we schedule the * delay then. */ - set_bit(BACKOFF, &con->flags); + set_bit(CON_FLAG_BACKOFF, &con->flags); } } @@ -2440,8 +2450,8 @@ static void clear_standby(struct ceph_connection *con) dout("clear_standby %p and ++connect_seq\n", con); con->state = CON_STATE_PREOPEN; con->connect_seq++; - WARN_ON(test_bit(WRITE_PENDING, &con->flags)); - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); + WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags)); + WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)); } } @@ -2482,7 +2492,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* if there wasn't anything waiting to send before, queue * new work */ - if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) + if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_send); @@ -2571,8 +2581,8 @@ void ceph_con_keepalive(struct ceph_connection *con) mutex_lock(&con->mutex); clear_standby(con); mutex_unlock(&con->mutex); - if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && - test_and_set_bit(WRITE_PENDING, &con->flags) == 0) + if (test_and_set_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags) == 0 && + test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_keepalive); -- GitLab From 43c7427d100769451601b8a36988ac0528ce0124 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:30:40 -0700 Subject: [PATCH 4750/5711] libceph: clear all flags on con_close Signed-off-by: Sage Weil --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b872db5c4989..fa16f2cc35fe 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -528,6 +528,8 @@ void ceph_con_close(struct ceph_connection *con) clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_BACKOFF, &con->flags); reset_connection(con); con->peer_global_seq = 0; -- GitLab From 756a16a5d53c072cd1f937b261641c1a3b53fdd7 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:26:13 -0700 Subject: [PATCH 4751/5711] libceph: be less chatty about stray replies There are many (normal) conditions that can lead to us getting unexpected replies, include cluster topology changes, osd failures, and timeouts. There's no need to spam the console about it. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index ad427e698890..42119c05e82c 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2037,8 +2037,8 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, if (!req) { *skip = 1; m = NULL; - pr_info("get_reply unknown tid %llu from osd%d\n", tid, - osd->o_osd); + dout("get_reply unknown tid %llu from osd%d\n", tid, + osd->o_osd); goto out; } -- GitLab From 09d9032751bfdabcba8752ab4b01a30fedea3d67 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:27:48 -0700 Subject: [PATCH 4752/5711] ceph: update MAINTAINERS file * shiny new inktank.com email addresses * add include/linux/crush directory (previous oversight) Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- MAINTAINERS | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 55f0fda602ec..3afd002ef95a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1761,15 +1761,16 @@ F: arch/powerpc/oprofile/*cell* F: arch/powerpc/platforms/cell/ CEPH DISTRIBUTED FILE SYSTEM CLIENT -M: Sage Weil +M: Sage Weil L: ceph-devel@vger.kernel.org -W: http://ceph.newdream.net/ +W: http://ceph.com/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git S: Supported F: Documentation/filesystems/ceph.txt F: fs/ceph F: net/ceph F: include/linux/ceph +F: include/linux/crush CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: L: linux-usb@vger.kernel.org @@ -5573,10 +5574,12 @@ S: Supported F: arch/hexagon/ RADOS BLOCK DEVICE (RBD) -F: include/linux/qnxtypes.h -M: Yehuda Sadeh -M: Sage Weil +M: Yehuda Sadeh +M: Sage Weil +M: Alex Elder M: ceph-devel@vger.kernel.org +W: http://ceph.com/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git S: Supported F: drivers/block/rbd.c F: drivers/block/rbd_types.h -- GitLab From 8007b8d626b49c34fb146ec16dc639d8b10c862f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:16 -0700 Subject: [PATCH 4753/5711] libceph: fix handling of immediate socket connect failure If the connect() call immediately fails such that sock == NULL, we still need con_close_socket() to reset our socket state to CLOSED. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index fa16f2cc35fe..a6a0c7a0a979 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -224,6 +224,8 @@ static void con_sock_state_init(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); } static void con_sock_state_connecting(struct ceph_connection *con) @@ -233,6 +235,8 @@ static void con_sock_state_connecting(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTING); } static void con_sock_state_connected(struct ceph_connection *con) @@ -242,6 +246,8 @@ static void con_sock_state_connected(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTED); } static void con_sock_state_closing(struct ceph_connection *con) @@ -253,6 +259,8 @@ static void con_sock_state_closing(struct ceph_connection *con) old_state != CON_SOCK_STATE_CONNECTED && old_state != CON_SOCK_STATE_CLOSING)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSING); } static void con_sock_state_closed(struct ceph_connection *con) @@ -262,8 +270,11 @@ static void con_sock_state_closed(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && old_state != CON_SOCK_STATE_CLOSING && - old_state != CON_SOCK_STATE_CONNECTING)) + old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CLOSED)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); } /* @@ -448,14 +459,14 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, */ static int con_close_socket(struct ceph_connection *con) { - int rc; + int rc = 0; dout("con_close_socket on %p sock %p\n", con, con->sock); - if (!con->sock) - return 0; - rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); - sock_release(con->sock); - con->sock = NULL; + if (con->sock) { + rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); + sock_release(con->sock); + con->sock = NULL; + } /* * Forcibly clear the SOCK_CLOSED flag. It gets set @@ -464,6 +475,7 @@ static int con_close_socket(struct ceph_connection *con) * shut the socket down. */ clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); + con_sock_state_closed(con); return rc; } -- GitLab From 4f471e4a9c7db0256834e1b376ea50c82e345c3c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:40 -0700 Subject: [PATCH 4754/5711] libceph: revoke mon_client messages on session restart Revoke all mon_client messages when we shut down the old connection. This is mostly moot since we are re-using the same ceph_connection, but it is cleaner. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/mon_client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index bfd21a891d69..105d533b55f3 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -118,6 +118,9 @@ static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); ceph_msg_revoke(monc->m_auth); + ceph_msg_revoke_incoming(monc->m_auth_reply); + ceph_msg_revoke(monc->m_subscribe); + ceph_msg_revoke_incoming(monc->m_subscribe_ack); ceph_con_close(&monc->con); monc->cur_mon = -1; monc->pending_auth = 0; @@ -685,6 +688,7 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); ceph_msg_revoke(req->request); + ceph_msg_revoke_incoming(req->reply); ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } -- GitLab From 7b862e07b1a4d5c963d19027f10ea78085f27f9b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:56 -0700 Subject: [PATCH 4755/5711] libceph: verify state after retaking con lock after dispatch We drop the con mutex when delivering a message. When we retake the lock, we need to verify we are still in the OPEN state before preparing to read the next tag, or else we risk stepping on a connection that has been closed. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index a6a0c7a0a979..feb5a2ac724c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2003,7 +2003,6 @@ static void process_message(struct ceph_connection *con) con->ops->dispatch(con, msg); mutex_lock(&con->mutex); - prepare_read_tag(con); } @@ -2213,6 +2212,8 @@ more: if (con->in_tag == CEPH_MSGR_TAG_READY) goto more; process_message(con); + if (con->state == CON_STATE_OPEN) + prepare_read_tag(con); goto more; } if (con->in_tag == CEPH_MSGR_TAG_ACK) { -- GitLab From 8636ea672f0c5ab7478c42c5b6705ebd1db7eb6a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:17:13 -0700 Subject: [PATCH 4756/5711] libceph: avoid dropping con mutex before fault The ceph_fault() function takes the con mutex, so we should avoid dropping it before calling it. This fixes a potential race with another thread calling ceph_con_close(), or _open(), or similar (we don't reverify con->state after retaking the lock). Add annotation so that lockdep realizes we will drop the mutex before returning. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index feb5a2ac724c..c3b628c76194 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2336,7 +2336,6 @@ done_unlocked: return; fault: - mutex_unlock(&con->mutex); ceph_fault(con); /* error/fault path */ goto done_unlocked; } @@ -2347,9 +2346,8 @@ fault: * exponential backoff */ static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) { - mutex_lock(&con->mutex); - pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", -- GitLab From 4740a623d20c51d167da7f752b63e2b8714b2543 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:19:30 -0700 Subject: [PATCH 4757/5711] libceph: change ceph_con_in_msg_alloc convention to be less weird This function's calling convention is very limiting. In particular, we can't return any error other than ENOMEM (and only implicitly), which is a problem (see next patch). Instead, return an normal 0 or error code, and make the skip a pointer output parameter. Drop the useless in_hdr argument (we have the con pointer). Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 56 ++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index c3b628c76194..13b549b6b1bf 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1733,9 +1733,7 @@ static int read_partial_message_section(struct ceph_connection *con, return 1; } -static bool ceph_con_in_msg_alloc(struct ceph_connection *con, - struct ceph_msg_header *hdr); - +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip); static int read_partial_message_pages(struct ceph_connection *con, struct page **pages, @@ -1864,9 +1862,14 @@ static int read_partial_message(struct ceph_connection *con) /* allocate message? */ if (!con->in_msg) { + int skip = 0; + dout("got hdr type %d front %d data %d\n", con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); - if (ceph_con_in_msg_alloc(con, &con->in_hdr)) { + ret = ceph_con_in_msg_alloc(con, &skip); + if (ret < 0) + return ret; + if (skip) { /* skip this message */ dout("alloc_msg said skip message\n"); BUG_ON(con->in_msg); @@ -1876,12 +1879,8 @@ static int read_partial_message(struct ceph_connection *con) con->in_seq++; return 0; } - if (!con->in_msg) { - con->error_msg = - "error allocating memory for incoming message"; - return -ENOMEM; - } + BUG_ON(!con->in_msg); BUG_ON(con->in_msg->con != con); m = con->in_msg; m->front.iov_len = 0; /* haven't read it yet */ @@ -2715,43 +2714,50 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) * connection, and save the result in con->in_msg. Uses the * connection's private alloc_msg op if available. * - * Returns true if the message should be skipped, false otherwise. - * If true is returned (skip message), con->in_msg will be NULL. - * If false is returned, con->in_msg will contain a pointer to the - * newly-allocated message, or NULL in case of memory exhaustion. + * Returns 0 on success, or a negative error code. + * + * On success, if we set *skip = 1: + * - the next message should be skipped and ignored. + * - con->in_msg == NULL + * or if we set *skip = 0: + * - con->in_msg is non-null. + * On error (ENOMEM, EAGAIN, ...), + * - con->in_msg == NULL */ -static bool ceph_con_in_msg_alloc(struct ceph_connection *con, - struct ceph_msg_header *hdr) +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) { + struct ceph_msg_header *hdr = &con->in_hdr; int type = le16_to_cpu(hdr->type); int front_len = le32_to_cpu(hdr->front_len); int middle_len = le32_to_cpu(hdr->middle_len); - int ret; + int ret = 0; BUG_ON(con->in_msg != NULL); if (con->ops->alloc_msg) { - int skip = 0; - mutex_unlock(&con->mutex); - con->in_msg = con->ops->alloc_msg(con, hdr, &skip); + con->in_msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->in_msg) { con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); } - if (skip) + if (*skip) { con->in_msg = NULL; - - if (!con->in_msg) - return skip != 0; + return 0; + } + if (!con->in_msg) { + con->error_msg = + "error allocating memory for incoming message"; + return -ENOMEM; + } } if (!con->in_msg) { con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); if (!con->in_msg) { pr_err("unable to allocate msg type %d len %d\n", type, front_len); - return false; + return -ENOMEM; } con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); @@ -2767,7 +2773,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, } } - return false; + return ret; } -- GitLab From 6139919133377652992a5fe134e22abce3e9c25e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:19:45 -0700 Subject: [PATCH 4758/5711] libceph: recheck con state after allocating incoming message We drop the lock when calling the ->alloc_msg() con op, which means we need to (a) not clobber con->in_msg without the mutex held, and (b) we need to verify that we are still in the OPEN state when we retake it to avoid causing any mayhem. If the state does change, -EAGAIN will get us back to con_work() and loop. Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/messenger.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 13b549b6b1bf..b6655b131558 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2735,9 +2735,16 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) BUG_ON(con->in_msg != NULL); if (con->ops->alloc_msg) { + struct ceph_msg *msg; + mutex_unlock(&con->mutex); - con->in_msg = con->ops->alloc_msg(con, hdr, skip); + msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); + if (con->state != CON_STATE_OPEN) { + ceph_msg_put(msg); + return -EAGAIN; + } + con->in_msg = msg; if (con->in_msg) { con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); -- GitLab From 4e891e0af0f0011c90067373c46d7228568ec079 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 10 Jul 2012 20:30:10 -0500 Subject: [PATCH 4759/5711] rbd: have __rbd_add_snap_dev() return a pointer It's not obvious whether the snapshot pointer whose address is provided to __rbd_add_snap_dev() will be assigned by that function. Change it to return the snapshot, or a pointer-coded errno in the event of a failure. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 30eb01e300a4..aba0d71a0345 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2029,15 +2029,21 @@ static int rbd_register_snap_dev(struct rbd_snap *snap, return ret; } -static int __rbd_add_snap_dev(struct rbd_device *rbd_dev, - int i, const char *name, - struct rbd_snap **snapp) +static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev, + int i, const char *name) { + struct rbd_snap *snap; int ret; - struct rbd_snap *snap = kzalloc(sizeof(*snap), GFP_KERNEL); + + snap = kzalloc(sizeof (*snap), GFP_KERNEL); if (!snap) - return -ENOMEM; + return ERR_PTR(-ENOMEM); + + ret = -ENOMEM; snap->name = kstrdup(name, GFP_KERNEL); + if (!snap->name) + goto err; + snap->size = rbd_dev->header.snap_sizes[i]; snap->id = rbd_dev->header.snapc->snaps[i]; if (device_is_registered(&rbd_dev->dev)) { @@ -2045,12 +2051,14 @@ static int __rbd_add_snap_dev(struct rbd_device *rbd_dev, if (ret < 0) goto err; } - *snapp = snap; - return 0; + + return snap; + err: kfree(snap->name); kfree(snap); - return ret; + + return ERR_PTR(ret); } /* @@ -2083,7 +2091,6 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) const char *name, *first_name; int i = rbd_dev->header.total_snaps; struct rbd_snap *snap, *old_snap = NULL; - int ret; struct list_head *p, *n; first_name = rbd_dev->header.snap_names; @@ -2126,9 +2133,9 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) if (cur_id >= old_snap->id) break; /* a new snapshot */ - ret = __rbd_add_snap_dev(rbd_dev, i - 1, name, &snap); - if (ret < 0) - return ret; + snap = __rbd_add_snap_dev(rbd_dev, i - 1, name); + if (IS_ERR(snap)) + return PTR_ERR(snap); /* note that we add it backward so using n and not p */ list_add(&snap->node, n); @@ -2142,9 +2149,9 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) WARN_ON(1); return -EINVAL; } - ret = __rbd_add_snap_dev(rbd_dev, i - 1, name, &snap); - if (ret < 0) - return ret; + snap = __rbd_add_snap_dev(rbd_dev, i - 1, name); + if (IS_ERR(snap)) + return PTR_ERR(snap); list_add(&snap->node, &rbd_dev->snaps); } -- GitLab From 57cfc1060f35ac2345cb37ea474f9644ac5cfd75 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 26 Jun 2012 12:57:03 -0700 Subject: [PATCH 4760/5711] rbd: make rbd_create_rw_ops() return a pointer Either rbd_create_rw_ops() will succeed, or it will fail because a memory allocation failed. Have it just return a valid pointer or null rather than stuffing a pointer into a provided address and returning an errno. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 70 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index aba0d71a0345..28670c0c68d5 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -788,22 +788,24 @@ err_out: /* * helpers for osd request op vectors. */ -static int rbd_create_rw_ops(struct ceph_osd_req_op **ops, - int num_ops, - int opcode, - u32 payload_len) -{ - *ops = kzalloc(sizeof(struct ceph_osd_req_op) * (num_ops + 1), - GFP_NOIO); - if (!*ops) - return -ENOMEM; - (*ops)[0].op = opcode; +static struct ceph_osd_req_op *rbd_create_rw_ops(int num_ops, + int opcode, u32 payload_len) +{ + struct ceph_osd_req_op *ops; + + ops = kzalloc(sizeof (*ops) * (num_ops + 1), GFP_NOIO); + if (!ops) + return NULL; + + ops[0].op = opcode; + /* * op extent offset and length will be set later on * in calc_raw_layout() */ - (*ops)[0].payload_len = payload_len; - return 0; + ops[0].payload_len = payload_len; + + return ops; } static void rbd_destroy_ops(struct ceph_osd_req_op *ops) @@ -1040,8 +1042,9 @@ static int rbd_req_sync_op(struct rbd_device *rbd_dev, if (!orig_ops) { payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0); - ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len); - if (ret < 0) + ret = -ENOMEM; + ops = rbd_create_rw_ops(1, opcode, payload_len); + if (!ops) goto done; if ((flags & CEPH_OSD_FLAG_WRITE) && buf) { @@ -1104,8 +1107,9 @@ static int rbd_do_op(struct request *rq, payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0); - ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len); - if (ret < 0) + ret = -ENOMEM; + ops = rbd_create_rw_ops(1, opcode, payload_len); + if (!ops) goto done; /* we've taken care of segment sizes earlier when we @@ -1191,9 +1195,9 @@ static int rbd_req_sync_notify_ack(struct rbd_device *rbd_dev, struct ceph_osd_req_op *ops; int ret; - ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); - if (ret < 0) - return ret; + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_NOTIFY_ACK, 0); + if (!ops) + return -ENOMEM; ops[0].watch.ver = cpu_to_le64(ver); ops[0].watch.cookie = notify_id; @@ -1241,10 +1245,11 @@ static int rbd_req_sync_watch(struct rbd_device *rbd_dev) { struct ceph_osd_req_op *ops; struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; + int ret; - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0); - if (ret < 0) - return ret; + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_WATCH, 0); + if (!ops) + return -ENOMEM; ret = ceph_osdc_create_event(osdc, rbd_watch_cb, 0, (void *)rbd_dev, &rbd_dev->watch_event); @@ -1284,10 +1289,11 @@ fail: static int rbd_req_sync_unwatch(struct rbd_device *rbd_dev) { struct ceph_osd_req_op *ops; + int ret; - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0); - if (ret < 0) - return ret; + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_WATCH, 0); + if (!ops) + return -ENOMEM; ops[0].watch.ver = 0; ops[0].watch.cookie = cpu_to_le64(rbd_dev->watch_event->cookie); @@ -1335,9 +1341,9 @@ static int rbd_req_sync_notify(struct rbd_device *rbd_dev) int payload_len = sizeof(u32) + sizeof(u32); int ret; - ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY, payload_len); - if (ret < 0) - return ret; + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_NOTIFY, payload_len); + if (!ops) + return -ENOMEM; info.rbd_dev = rbd_dev; @@ -1388,10 +1394,12 @@ static int rbd_req_sync_exec(struct rbd_device *rbd_dev, struct ceph_osd_req_op *ops; int class_name_len = strlen(class_name); int method_name_len = strlen(method_name); - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_CALL, + int ret; + + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_CALL, class_name_len + method_name_len + len); - if (ret < 0) - return ret; + if (!ops) + return -ENOMEM; ops[0].cls.class_name = class_name; ops[0].cls.class_len = (__u8) class_name_len; -- GitLab From d67d4be56a3ec8d07b1f29aab6095b363085b028 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 13 Jul 2012 20:35:11 -0500 Subject: [PATCH 4761/5711] rbd: pass null version pointer in add_snap() rbd_header_add_snap() passes the address of a version variable to rbd_req_sync_exec(), but it ignores the result. Just pass a null pointer instead. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 28670c0c68d5..e1fa12b2ae2e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1668,7 +1668,6 @@ static int rbd_header_add_snap(struct rbd_device *rbd_dev, u64 new_snapid; int ret; void *data, *p, *e; - u64 ver; struct ceph_mon_client *monc; /* we should create a snapshot only if we're pointing at the head */ @@ -1693,7 +1692,7 @@ static int rbd_header_add_snap(struct rbd_device *rbd_dev, ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name, "rbd", "snap_add", - data, p - data, &ver); + data, p - data, NULL); kfree(data); -- GitLab From 913d2fdcf60576cbbd82969fcb2bc78a4d59ba33 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 26 Jun 2012 12:57:03 -0700 Subject: [PATCH 4762/5711] rbd: always pass ops array to rbd_req_sync_op() All of the callers of rbd_req_sync_op() except one pass a non-null "ops" pointer. The only one that does not is rbd_req_sync_read(), which passes CEPH_OSD_OP_READ as its "opcode" and, CEPH_OSD_FLAG_READ for "flags". By allocating the ops array in rbd_req_sync_read() and moving the special case code for the null ops pointer into it, it becomes clear that much of that code is not even necessary. In addition, the "opcode" argument to rbd_req_sync_op() is never actually used, so get rid of that. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 46 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index e1fa12b2ae2e..1222d583ac2c 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1020,9 +1020,8 @@ static void rbd_simple_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg static int rbd_req_sync_op(struct rbd_device *rbd_dev, struct ceph_snap_context *snapc, u64 snapid, - int opcode, int flags, - struct ceph_osd_req_op *orig_ops, + struct ceph_osd_req_op *ops, const char *object_name, u64 ofs, u64 len, char *buf, @@ -1032,28 +1031,14 @@ static int rbd_req_sync_op(struct rbd_device *rbd_dev, int ret; struct page **pages; int num_pages; - struct ceph_osd_req_op *ops = orig_ops; - u32 payload_len; + + BUG_ON(ops == NULL); num_pages = calc_pages_for(ofs , len); pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL); if (IS_ERR(pages)) return PTR_ERR(pages); - if (!orig_ops) { - payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0); - ret = -ENOMEM; - ops = rbd_create_rw_ops(1, opcode, payload_len); - if (!ops) - goto done; - - if ((flags & CEPH_OSD_FLAG_WRITE) && buf) { - ret = ceph_copy_to_page_vector(pages, buf, ofs, len); - if (ret < 0) - goto done_ops; - } - } - ret = rbd_do_request(NULL, rbd_dev, snapc, snapid, object_name, ofs, len, NULL, pages, num_pages, @@ -1063,14 +1048,11 @@ static int rbd_req_sync_op(struct rbd_device *rbd_dev, NULL, linger_req, ver); if (ret < 0) - goto done_ops; + goto done; if ((flags & CEPH_OSD_FLAG_READ) && buf) ret = ceph_copy_from_page_vector(pages, buf, ofs, ret); -done_ops: - if (!orig_ops) - rbd_destroy_ops(ops); done: ceph_release_page_vector(pages, num_pages); return ret; @@ -1177,12 +1159,20 @@ static int rbd_req_sync_read(struct rbd_device *rbd_dev, char *buf, u64 *ver) { - return rbd_req_sync_op(rbd_dev, NULL, + struct ceph_osd_req_op *ops; + int ret; + + ops = rbd_create_rw_ops(1, CEPH_OSD_OP_READ, 0); + if (!ops) + return -ENOMEM; + + ret = rbd_req_sync_op(rbd_dev, NULL, snapid, - CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, - NULL, - object_name, ofs, len, buf, NULL, ver); + ops, object_name, ofs, len, buf, NULL, ver); + rbd_destroy_ops(ops); + + return ret; } /* @@ -1262,7 +1252,6 @@ static int rbd_req_sync_watch(struct rbd_device *rbd_dev) ret = rbd_req_sync_op(rbd_dev, NULL, CEPH_NOSNAP, - 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, rbd_dev->header_name, @@ -1301,7 +1290,6 @@ static int rbd_req_sync_unwatch(struct rbd_device *rbd_dev) ret = rbd_req_sync_op(rbd_dev, NULL, CEPH_NOSNAP, - 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, rbd_dev->header_name, @@ -1360,7 +1348,6 @@ static int rbd_req_sync_notify(struct rbd_device *rbd_dev) ret = rbd_req_sync_op(rbd_dev, NULL, CEPH_NOSNAP, - 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, rbd_dev->header_name, @@ -1411,7 +1398,6 @@ static int rbd_req_sync_exec(struct rbd_device *rbd_dev, ret = rbd_req_sync_op(rbd_dev, NULL, CEPH_NOSNAP, - 0, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, ops, object_name, 0, 0, NULL, NULL, ver); -- GitLab From ccece235d3737221e7a1118fdbd8474112adac84 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 10 Jul 2012 20:30:10 -0500 Subject: [PATCH 4763/5711] rbd: fixes in rbd_header_from_disk() This fixes a few issues in rbd_header_from_disk(): - There is a check intended to catch overflow, but it's wrong in two ways. - First, the type we don't want to overflow is size_t, not unsigned int, and there is now a SIZE_MAX we can use for use with that type. - Second, we're allocating the snapshot ids and snapshot image sizes separately (each has type u64; on disk they grouped together as a rbd_image_header_ondisk structure). So we can use the size of u64 in this overflow check. - If there are no snapshots, then there should be no snapshot names. Enforce this, and issue a warning if we encounter a header with no snapshots but a non-zero snap_names_len. - When saving the snapshot names into the header, be more direct in defining the offset in the on-disk structure from which they're being copied by using "snap_count" rather than "i" in the array index. - If an error occurs, the "snapc" and "snap_names" fields are freed at the end of the function. Make those fields be null pointers after they're freed, to be explicit that they are no longer valid. - Finally, move the definition of the local variable "i" to the innermost scope in which it's needed. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 1222d583ac2c..34676937d2d2 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -494,14 +494,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header, struct rbd_image_header_ondisk *ondisk, u32 allocated_snaps) { - u32 i, snap_count; + u32 snap_count; if (!rbd_dev_ondisk_valid(ondisk)) return -ENXIO; snap_count = le32_to_cpu(ondisk->snap_count); - if (snap_count > (UINT_MAX - sizeof(struct ceph_snap_context)) - / sizeof (*ondisk)) + if (snap_count > (SIZE_MAX - sizeof(struct ceph_snap_context)) + / sizeof (u64)) return -EINVAL; header->snapc = kmalloc(sizeof(struct ceph_snap_context) + snap_count * sizeof(u64), @@ -509,8 +509,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header, if (!header->snapc) return -ENOMEM; - header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); if (snap_count) { + header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); header->snap_names = kmalloc(header->snap_names_len, GFP_KERNEL); if (!header->snap_names) @@ -520,6 +520,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header, if (!header->snap_sizes) goto err_names; } else { + WARN_ON(ondisk->snap_names_len); + header->snap_names_len = 0; header->snap_names = NULL; header->snap_sizes = NULL; } @@ -544,6 +546,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header, header->total_snaps = snap_count; if (snap_count && allocated_snaps == snap_count) { + int i; + for (i = 0; i < snap_count; i++) { header->snapc->snaps[i] = le64_to_cpu(ondisk->snaps[i].id); @@ -552,7 +556,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, } /* copy snapshot names */ - memcpy(header->snap_names, &ondisk->snaps[i], + memcpy(header->snap_names, &ondisk->snaps[snap_count], header->snap_names_len); } @@ -560,10 +564,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header, err_sizes: kfree(header->snap_sizes); + header->snap_sizes = NULL; err_names: kfree(header->snap_names); + header->snap_names = NULL; err_snapc: kfree(header->snapc); + header->snapc = NULL; + return -ENOMEM; } -- GitLab From b813623ab95d0b4bbeb22e160bd5461965d0c571 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:41 -0500 Subject: [PATCH 4764/5711] rbd: return obj version in __rbd_refresh_header() Add a new parameter to __rbd_refresh_header() through which the version of the header object is passed back to the caller. In most cases this isn't needed. The main motivation is to normalize (almost) all calls to __rbd_refresh_header() so they are all wrapped immediately by mutex_lock()/mutex_unlock(). Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 34676937d2d2..de981ac72362 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -240,7 +240,7 @@ static void rbd_put_dev(struct rbd_device *rbd_dev) put_device(&rbd_dev->dev); } -static int __rbd_refresh_header(struct rbd_device *rbd_dev); +static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver); static int rbd_open(struct block_device *bdev, fmode_t mode) { @@ -1226,8 +1226,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) rbd_dev->header_name, (unsigned long long) notify_id, (unsigned int) opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - rc = __rbd_refresh_header(rbd_dev); - hver = rbd_dev->header.obj_version; + rc = __rbd_refresh_header(rbd_dev, &hver); mutex_unlock(&ctl_mutex); if (rc) pr_warning(RBD_DRV_NAME "%d got notification but failed to " @@ -1707,7 +1706,7 @@ static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) /* * only read the first part of the ondisk header, without the snaps info */ -static int __rbd_refresh_header(struct rbd_device *rbd_dev) +static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) { int ret; struct rbd_image_header h; @@ -1732,6 +1731,8 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev) /* osd requests may still refer to snapc */ ceph_put_snap_context(rbd_dev->header.snapc); + if (hver) + *hver = h.obj_version; rbd_dev->header.obj_version = h.obj_version; rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; @@ -1901,17 +1902,13 @@ static ssize_t rbd_image_refresh(struct device *dev, size_t size) { struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); - int rc; - int ret = size; + int ret; mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - - rc = __rbd_refresh_header(rbd_dev); - if (rc < 0) - ret = rc; - + ret = __rbd_refresh_header(rbd_dev, NULL); mutex_unlock(&ctl_mutex); - return ret; + + return ret < 0 ? ret : size; } static DEVICE_ATTR(size, S_IRUGO, rbd_size_show, NULL); @@ -2200,7 +2197,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) ret = rbd_req_sync_watch(rbd_dev); if (ret == -ERANGE) { mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - rc = __rbd_refresh_header(rbd_dev); + rc = __rbd_refresh_header(rbd_dev, NULL); mutex_unlock(&ctl_mutex); if (rc < 0) return rc; @@ -2650,7 +2647,7 @@ static ssize_t rbd_snap_add(struct device *dev, if (ret < 0) goto err_unlock; - ret = __rbd_refresh_header(rbd_dev); + ret = __rbd_refresh_header(rbd_dev, NULL); if (ret < 0) goto err_unlock; -- GitLab From 1fe5e9932156f6122c3b1ff6ba7541c27c86718c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 25 Jul 2012 09:32:41 -0500 Subject: [PATCH 4765/5711] rbd: create rbd_refresh_helper() Create a simple helper that handles the common case of calling __rbd_refresh_header() while holding the ctl_mutex. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin --- drivers/block/rbd.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index de981ac72362..9917943a3572 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -240,7 +240,7 @@ static void rbd_put_dev(struct rbd_device *rbd_dev) put_device(&rbd_dev->dev); } -static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver); +static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver); static int rbd_open(struct block_device *bdev, fmode_t mode) { @@ -1225,9 +1225,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n", rbd_dev->header_name, (unsigned long long) notify_id, (unsigned int) opcode); - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - rc = __rbd_refresh_header(rbd_dev, &hver); - mutex_unlock(&ctl_mutex); + rc = rbd_refresh_header(rbd_dev, &hver); if (rc) pr_warning(RBD_DRV_NAME "%d got notification but failed to " " update snaps: %d\n", rbd_dev->major, rc); @@ -1751,6 +1749,17 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) return ret; } +static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) +{ + int ret; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + ret = __rbd_refresh_header(rbd_dev, hver); + mutex_unlock(&ctl_mutex); + + return ret; +} + static int rbd_init_disk(struct rbd_device *rbd_dev) { struct gendisk *disk; @@ -1904,9 +1913,7 @@ static ssize_t rbd_image_refresh(struct device *dev, struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); int ret; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - ret = __rbd_refresh_header(rbd_dev, NULL); - mutex_unlock(&ctl_mutex); + ret = rbd_refresh_header(rbd_dev, NULL); return ret < 0 ? ret : size; } @@ -2196,9 +2203,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) do { ret = rbd_req_sync_watch(rbd_dev); if (ret == -ERANGE) { - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - rc = __rbd_refresh_header(rbd_dev, NULL); - mutex_unlock(&ctl_mutex); + rc = rbd_refresh_header(rbd_dev, NULL); if (rc < 0) return rc; } -- GitLab From dee923bdd1a0c2bc22715096389306dfbd0f588e Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Wed, 18 Jul 2012 10:38:16 -0300 Subject: [PATCH 4766/5711] [media] smiapp-core.c: remove duplicated include Signed-off-by: Duan Jiong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/smiapp/smiapp-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/video/smiapp/smiapp-core.c index f466a7edcb2a..bfd47c106134 100644 --- a/drivers/media/video/smiapp/smiapp-core.c +++ b/drivers/media/video/smiapp/smiapp-core.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include -- GitLab From eabdc68fffddb722f3653b1bee9bf1bb24207fec Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Wed, 18 Jul 2012 10:41:47 -0300 Subject: [PATCH 4767/5711] [media] pms.c: remove duplicated include Signed-off-by: Duan Jiong Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pms.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index b4c679b3fb0f..77f9c92186f4 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include -- GitLab From d57368afe63b3b7b45ce6c2b8c5276417935be2f Mon Sep 17 00:00:00 2001 From: Alexander Lyakas Date: Tue, 17 Jul 2012 13:17:55 +0300 Subject: [PATCH 4768/5711] md/RAID1: Add missing case for attempting to repair known bad blocks. When doing resync or repair, attempt to correct bad blocks, according to WriteErrorSeen policy Signed-off-by: Alex Lyakas Signed-off-by: NeilBrown --- drivers/md/raid1.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d2361b162de5..197f62681db5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2445,6 +2445,18 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp bio->bi_rw = READ; bio->bi_end_io = end_sync_read; read_targets++; + } else if (!test_bit(WriteErrorSeen, &rdev->flags) && + test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && + !test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) { + /* + * The device is suitable for reading (InSync), + * but has bad block(s) here. Let's try to correct them, + * if we are doing resync or repair. Otherwise, leave + * this device alone for this sync request. + */ + bio->bi_rw = WRITE; + bio->bi_end_io = end_sync_write; + write_targets++; } } if (bio->bi_end_io) { -- GitLab From c854d8883fec59332f0662917f8c94dcfb1c405d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 18 Jul 2012 13:41:11 -0300 Subject: [PATCH 4769/5711] [media] cx25821: Remove bad strcpy to read-only char* The strcpy was being used to set the name of the board. This was both wrong and redundant, since the destination char* was read-only and the name is set statically at compile time. The type of the name field is changed to const char* to prevent future errors. Reported-by: Radek Masin Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25821/cx25821-core.c | 3 --- drivers/media/video/cx25821/cx25821.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index 83c1aa6b2e6c..f11f6f07e915 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -904,9 +904,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) list_add_tail(&dev->devlist, &cx25821_devlist); mutex_unlock(&cx25821_devlist_mutex); - strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); - strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); - if (dev->pci->device != 0x8210) { pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", __func__, dev->pci->device); diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index ed525016f165..8a9c0c869412 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h @@ -186,7 +186,7 @@ enum port { }; struct cx25821_board { - char *name; + const char *name; enum port porta; enum port portb; enum port portc; -- GitLab From 9d2952d70f175193b609929427a88a62eaa381bb Mon Sep 17 00:00:00 2001 From: Tony Gentile Date: Thu, 19 Jul 2012 09:36:33 -0300 Subject: [PATCH 4770/5711] [media] bttv: add support for Aposonic W-DVR Forwarded-by: Gerd Hoffmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bt8xx/bttv-cards.c | 10 +++++++++- drivers/media/video/bt8xx/bttv.h | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index b753906c7183..581f666a76cf 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -159,3 +159,4 @@ 158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d] 159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] 160 -> Tongwei Video Technology TD-3116 [f200:3116] +161 -> Aposonic W-DVR [0279:0228] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 5f3a00c2c4f6..38952faaffda 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -345,7 +345,7 @@ static struct CARD { { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, { 0x3116f200, BTTV_BOARD_TVT_TD3116, "Tongwei Video Technology TD-3116" }, - + { 0x02280279, BTTV_BOARD_APOSONIC_WDVR, "Aposonic W-DVR" }, { 0, -1, NULL } }; @@ -2818,6 +2818,14 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, }, + [BTTV_BOARD_APOSONIC_WDVR] = { + .name = "Aposonic W-DVR", + .video_inputs = 4, + .svhs = NO_SVHS, + .muxsel = MUXSEL(2, 3, 1, 0), + .tuner_type = TUNER_ABSENT, + }, + }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index acfe2f3b92d9..79a11240a590 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -184,7 +184,7 @@ #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e #define BTTV_BOARD_PV183 0x9f #define BTTV_BOARD_TVT_TD3116 0xa0 - +#define BTTV_BOARD_APOSONIC_WDVR 0xa1 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 -- GitLab From d1b4a085fbd31d182a19f8a0c5144e4f5e831b8a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Jul 2012 23:10:38 -0300 Subject: [PATCH 4771/5711] [media] Documentation: Update cardlists Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.au0828 | 2 +- Documentation/video4linux/CARDLIST.cx23885 | 4 +++- Documentation/video4linux/CARDLIST.saa7134 | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828 index 7b59e953c4bf..a8a65753e544 100644 --- a/Documentation/video4linux/CARDLIST.au0828 +++ b/Documentation/video4linux/CARDLIST.au0828 @@ -3,4 +3,4 @@ 2 -> Hauppauge HVR850 (au0828) [2040:7240] 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] 4 -> Hauppauge HVR950Q rev xxF8 (au0828) [2040:7201,2040:7211,2040:7281] - 5 -> Hauppauge Woodbury (au0828) [2040:8200] + 5 -> Hauppauge Woodbury (au0828) [05e1:0480,2040:8200] diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index f316d1816fcd..652aecd13199 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -18,7 +18,7 @@ 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] 18 -> Hauppauge WinTV-HVR1270 [0070:2211] 19 -> Hauppauge WinTV-HVR1275 [0070:2215,0070:221d,0070:22f2] - 20 -> Hauppauge WinTV-HVR1255 [0070:2251,0070:2259,0070:22f1] + 20 -> Hauppauge WinTV-HVR1255 [0070:2251,0070:22f1] 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5] 22 -> Mygica X8506 DMB-TH [14f1:8651] 23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657] @@ -33,3 +33,5 @@ 32 -> MPX-885 33 -> Mygica X8507 [14f1:8502] 34 -> TerraTec Cinergy T PCIe Dual [153b:117e] + 35 -> TeVii S471 [d471:9022] + 36 -> Hauppauge WinTV-HVR1255 [0070:2259] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 34f3b330e5f4..94d9025aa82d 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -188,3 +188,4 @@ 187 -> Beholder BeholdTV 503 FM [5ace:5030] 188 -> Sensoray 811/911 [6000:0811,6000:0911] 189 -> Kworld PC150-U [17de:a134] +190 -> Asus My Cinema PS3-100 [1043:48cd] -- GitLab From e04f4b2debc84ab801ee26f0e4c1c99e3ac2bd04 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 20 Jul 2012 07:11:57 -0300 Subject: [PATCH 4772/5711] [media] dib8000: move dereference after check for NULL My static checker complains that we dereference "state" inside the call to fft_to_mode() before checking for NULL. The comments say that it is possible for "state" to be NULL so I have moved the dereference after the check. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib8000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 9ca34f495009..1f3bcb5a1de8 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -2680,12 +2680,14 @@ static int dib8000_tune(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; int ret = 0; - u16 lock, value, mode = fft_to_mode(state); + u16 lock, value, mode; // we are already tuned - just resuming from suspend if (state == NULL) return -EINVAL; + mode = fft_to_mode(state); + dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); dib8000_set_channel(state, 0, 0); -- GitLab From 1bec982dd432a187459d59900a16cd79d5eea7fc Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Tue, 24 Jul 2012 16:52:27 -0300 Subject: [PATCH 4773/5711] [media] s2255drv: Add MODULE_FIRMWARE statement Cc: Mauro Carvalho Chehab Cc: Dean Anderson Cc: Hans Verkuil Cc: Dan Carpenter Cc: Hans de Goede Cc: linux-media@vger.kernel.org Signed-off-by: Tim Gardner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 01c2179f0520..95007dda0c93 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -2686,3 +2686,4 @@ MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver"); MODULE_AUTHOR("Dean Anderson (Sensoray Company Inc.)"); MODULE_LICENSE("GPL"); MODULE_VERSION(S2255_VERSION); +MODULE_FIRMWARE(FIRMWARE_FILE_NAME); -- GitLab From 3422f2a6bc0ed9b1fa159a33d94efef08f142570 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 25 Jul 2012 09:15:19 -0300 Subject: [PATCH 4774/5711] [media] xc5000: Add MODULE_FIRMWARE statements This will make modinfo more useful with regard to discovering necessary firmware files. Cc: Mauro Carvalho Chehab Cc: Michael Krufky Cc: Eddi De Pieri Cc: linux-media@vger.kernel.org Signed-off-by: Tim Gardner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index bac8009e1d49..362a8d7c9738 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -210,13 +210,15 @@ struct xc5000_fw_cfg { u16 size; }; +#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" static const struct xc5000_fw_cfg xc5000a_1_6_114 = { - .name = "dvb-fe-xc5000-1.6.114.fw", + .name = XC5000A_FIRMWARE, .size = 12401, }; +#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw" static const struct xc5000_fw_cfg xc5000c_41_024_5 = { - .name = "dvb-fe-xc5000c-41.024.5.fw", + .name = XC5000C_FIRMWARE, .size = 16497, }; @@ -1259,3 +1261,5 @@ EXPORT_SYMBOL(xc5000_attach); MODULE_AUTHOR("Steven Toth"); MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(XC5000A_FIRMWARE); +MODULE_FIRMWARE(XC5000C_FIRMWARE); -- GitLab From ccb7c5939cc7185fdecb913f4c7cba94cf82287e Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 25 Jul 2012 12:54:02 -0300 Subject: [PATCH 4775/5711] [media] lgs8gxx: Declare MODULE_FIRMWARE usage Cc: Mauro Carvalho Chehab Cc: Hans Verkuil Cc: linux-media@vger.kernel.org Signed-off-by: Tim Gardner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgs8gxx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index 568363a10a31..c2ea2749ebed 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c @@ -40,6 +40,8 @@ static int debug; static int fake_signal_str = 1; +#define LGS8GXX_FIRMWARE "lgs8g75.fw" + module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); @@ -592,7 +594,7 @@ static int lgs8g75_init_data(struct lgs8gxx_state *priv) int rc; int i; - rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev); + rc = request_firmware(&fw, LGS8GXX_FIRMWARE, &priv->i2c->dev); if (rc) return rc; @@ -1070,3 +1072,4 @@ EXPORT_SYMBOL(lgs8gxx_attach); MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver"); MODULE_AUTHOR("David T. L. Wong "); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(LGS8GXX_FIRMWARE); -- GitLab From 4d98015eef6fa97b0cbba7310041ab75b223524b Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 25 Jul 2012 15:41:04 -0300 Subject: [PATCH 4776/5711] [media] tlg2300: Declare MODULE_FIRMWARE usage Cc: Huang Shijie Cc: Kang Yong Cc: Zhang Xiaobing Cc: Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org Signed-off-by: Tim Gardner Acked-by: Huang Shijie Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tlg2300/pd-main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index c096b3f74200..7b1f6ebd0e2c 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c @@ -53,7 +53,8 @@ int debug_mode; module_param(debug_mode, int, 0644); MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); -static const char *firmware_name = "tlg2300_firmware.bin"; +#define TLG2300_FIRMWARE "tlg2300_firmware.bin" +static const char *firmware_name = TLG2300_FIRMWARE; static struct usb_driver poseidon_driver; static LIST_HEAD(pd_device_list); @@ -532,3 +533,4 @@ MODULE_AUTHOR("Telegent Systems"); MODULE_DESCRIPTION("For tlg2300-based USB device "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.0.2"); +MODULE_FIRMWARE(TLG2300_FIRMWARE); -- GitLab From ad36cb0d1d3e2b7f161cd33932433f9349cade1e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 30 Jul 2012 12:32:59 +0000 Subject: [PATCH 4777/5711] powerpc/kvm/book3s_32: Fix MTMSR_EERI macro Commit b38c77d82e4 moved the MTMSR_EERI macro from the KVM code to generic ppc_asm.h code. However, while adding it in the headers for the ppc32 case, it missed out to remove the former definition in the KVM code. This patch fixes compilation on server type PPC32 targets with CONFIG_KVM enabled. Signed-off-by: Alexander Graf Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kvm/book3s_rmhandlers.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S index ab523f3c1731..9ecf6e35cd8d 100644 --- a/arch/powerpc/kvm/book3s_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_rmhandlers.S @@ -67,7 +67,6 @@ kvmppc_skip_Hinterrupt: #elif defined(CONFIG_PPC_BOOK3S_32) #define FUNC(name) name -#define MTMSR_EERI(reg) mtmsr (reg) .macro INTERRUPT_TRAMPOLINE intno -- GitLab From d87aae2f3c8e90bd0fe03f5309b4d066b712b8ec Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 31 Jul 2012 09:28:31 +0400 Subject: [PATCH 4778/5711] switch the protection of percpu_counter list to spinlock ... making percpu_counter_destroy() non-blocking Signed-off-by: Al Viro --- lib/percpu_counter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index f8a3f1a829b8..ba6085d9c741 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -12,7 +12,7 @@ #ifdef CONFIG_HOTPLUG_CPU static LIST_HEAD(percpu_counters); -static DEFINE_MUTEX(percpu_counters_lock); +static DEFINE_SPINLOCK(percpu_counters_lock); #endif #ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER @@ -123,9 +123,9 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, #ifdef CONFIG_HOTPLUG_CPU INIT_LIST_HEAD(&fbc->list); - mutex_lock(&percpu_counters_lock); + spin_lock(&percpu_counters_lock); list_add(&fbc->list, &percpu_counters); - mutex_unlock(&percpu_counters_lock); + spin_unlock(&percpu_counters_lock); #endif return 0; } @@ -139,9 +139,9 @@ void percpu_counter_destroy(struct percpu_counter *fbc) debug_percpu_counter_deactivate(fbc); #ifdef CONFIG_HOTPLUG_CPU - mutex_lock(&percpu_counters_lock); + spin_lock(&percpu_counters_lock); list_del(&fbc->list); - mutex_unlock(&percpu_counters_lock); + spin_unlock(&percpu_counters_lock); #endif free_percpu(fbc->counters); fbc->counters = NULL; @@ -170,7 +170,7 @@ static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, return NOTIFY_OK; cpu = (unsigned long)hcpu; - mutex_lock(&percpu_counters_lock); + spin_lock(&percpu_counters_lock); list_for_each_entry(fbc, &percpu_counters, list) { s32 *pcount; unsigned long flags; @@ -181,7 +181,7 @@ static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, *pcount = 0; raw_spin_unlock_irqrestore(&fbc->lock, flags); } - mutex_unlock(&percpu_counters_lock); + spin_unlock(&percpu_counters_lock); #endif return NOTIFY_OK; } -- GitLab From 5accdf82ba25cacefd6c1867f1704beb4d244cdd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:34 +0200 Subject: [PATCH 4779/5711] fs: Improve filesystem freezing handling vfs_check_frozen() tests are racy since the filesystem can be frozen just after the test is performed. Thus in write paths we can end up marking some pages or inodes dirty even though the file system is already frozen. This creates problems with flusher thread hanging on frozen filesystem. Another problem is that exclusion between ->page_mkwrite() and filesystem freezing has been handled by setting page dirty and then verifying s_frozen. This guaranteed that either the freezing code sees the faulted page, writes it, and writeprotects it again or we see s_frozen set and bail out of page fault. This works to protect from page being marked writeable while filesystem freezing is running but has an unpleasant artefact of leaving dirty (although unmodified and writeprotected) pages on frozen filesystem resulting in similar problems with flusher thread as the first problem. This patch aims at providing exclusion between write paths and filesystem freezing. We implement a writer-freeze read-write semaphore in the superblock. Actually, there are three such semaphores because of lock ranking reasons - one for page fault handlers (->page_mkwrite), one for all other writers, and one of internal filesystem purposes (used e.g. to track running transactions). Write paths which should block freezing (e.g. directory operations, ->aio_write(), ->page_mkwrite) hold reader side of the semaphore. Code freezing the filesystem takes the writer side. Only that we don't really want to bounce cachelines of the semaphores between CPUs for each write happening. So we implement the reader side of the semaphore as a per-cpu counter and the writer side is implemented using s_writers.frozen superblock field. [AV: microoptimize sb_start_write(); we want it fast in normal case] BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/super.c | 251 +++++++++++++++++++++++++++++++++++++++++---- include/linux/fs.h | 150 +++++++++++++++++++++++++-- 2 files changed, 373 insertions(+), 28 deletions(-) diff --git a/fs/super.c b/fs/super.c index c743fb3be4b8..0f64ecb7b1bf 100644 --- a/fs/super.c +++ b/fs/super.c @@ -33,12 +33,19 @@ #include #include #include +#include #include "internal.h" LIST_HEAD(super_blocks); DEFINE_SPINLOCK(sb_lock); +static char *sb_writers_name[SB_FREEZE_LEVELS] = { + "sb_writers", + "sb_pagefaults", + "sb_internal", +}; + /* * One thing we have to be careful of with a per-sb shrinker is that we don't * drop the last active reference to the superblock from within the shrinker. @@ -102,6 +109,35 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) return total_objects; } +static int init_sb_writers(struct super_block *s, struct file_system_type *type) +{ + int err; + int i; + + for (i = 0; i < SB_FREEZE_LEVELS; i++) { + err = percpu_counter_init(&s->s_writers.counter[i], 0); + if (err < 0) + goto err_out; + lockdep_init_map(&s->s_writers.lock_map[i], sb_writers_name[i], + &type->s_writers_key[i], 0); + } + init_waitqueue_head(&s->s_writers.wait); + init_waitqueue_head(&s->s_writers.wait_unfrozen); + return 0; +err_out: + while (--i >= 0) + percpu_counter_destroy(&s->s_writers.counter[i]); + return err; +} + +static void destroy_sb_writers(struct super_block *s) +{ + int i; + + for (i = 0; i < SB_FREEZE_LEVELS; i++) + percpu_counter_destroy(&s->s_writers.counter[i]); +} + /** * alloc_super - create new superblock * @type: filesystem type superblock should belong to @@ -117,18 +153,19 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) if (s) { if (security_sb_alloc(s)) { + /* + * We cannot call security_sb_free() without + * security_sb_alloc() succeeding. So bail out manually + */ kfree(s); s = NULL; goto out; } #ifdef CONFIG_SMP s->s_files = alloc_percpu(struct list_head); - if (!s->s_files) { - security_sb_free(s); - kfree(s); - s = NULL; - goto out; - } else { + if (!s->s_files) + goto err_out; + else { int i; for_each_possible_cpu(i) @@ -137,6 +174,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) #else INIT_LIST_HEAD(&s->s_files); #endif + if (init_sb_writers(s, type)) + goto err_out; s->s_flags = flags; s->s_bdi = &default_backing_dev_info; INIT_HLIST_NODE(&s->s_instances); @@ -190,6 +229,16 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) } out: return s; +err_out: + security_sb_free(s); +#ifdef CONFIG_SMP + if (s->s_files) + free_percpu(s->s_files); +#endif + destroy_sb_writers(s); + kfree(s); + s = NULL; + goto out; } /** @@ -203,6 +252,7 @@ static inline void destroy_super(struct super_block *s) #ifdef CONFIG_SMP free_percpu(s->s_files); #endif + destroy_sb_writers(s); security_sb_free(s); WARN_ON(!list_empty(&s->s_mounts)); kfree(s->s_subtype); @@ -651,10 +701,11 @@ struct super_block *get_super_thawed(struct block_device *bdev) { while (1) { struct super_block *s = get_super(bdev); - if (!s || s->s_frozen == SB_UNFROZEN) + if (!s || s->s_writers.frozen == SB_UNFROZEN) return s; up_read(&s->s_umount); - vfs_check_frozen(s, SB_FREEZE_WRITE); + wait_event(s->s_writers.wait_unfrozen, + s->s_writers.frozen == SB_UNFROZEN); put_super(s); } } @@ -732,7 +783,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) int retval; int remount_ro; - if (sb->s_frozen != SB_UNFROZEN) + if (sb->s_writers.frozen != SB_UNFROZEN) return -EBUSY; #ifdef CONFIG_BLOCK @@ -1163,6 +1214,120 @@ out: return ERR_PTR(error); } +/* + * This is an internal function, please use sb_end_{write,pagefault,intwrite} + * instead. + */ +void __sb_end_write(struct super_block *sb, int level) +{ + percpu_counter_dec(&sb->s_writers.counter[level-1]); + /* + * Make sure s_writers are updated before we wake up waiters in + * freeze_super(). + */ + smp_mb(); + if (waitqueue_active(&sb->s_writers.wait)) + wake_up(&sb->s_writers.wait); + rwsem_release(&sb->s_writers.lock_map[level-1], 1, _RET_IP_); +} +EXPORT_SYMBOL(__sb_end_write); + +#ifdef CONFIG_LOCKDEP +/* + * We want lockdep to tell us about possible deadlocks with freezing but + * it's it bit tricky to properly instrument it. Getting a freeze protection + * works as getting a read lock but there are subtle problems. XFS for example + * gets freeze protection on internal level twice in some cases, which is OK + * only because we already hold a freeze protection also on higher level. Due + * to these cases we have to tell lockdep we are doing trylock when we + * already hold a freeze protection for a higher freeze level. + */ +static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock, + unsigned long ip) +{ + int i; + + if (!trylock) { + for (i = 0; i < level - 1; i++) + if (lock_is_held(&sb->s_writers.lock_map[i])) { + trylock = true; + break; + } + } + rwsem_acquire_read(&sb->s_writers.lock_map[level-1], 0, trylock, ip); +} +#endif + +/* + * This is an internal function, please use sb_start_{write,pagefault,intwrite} + * instead. + */ +int __sb_start_write(struct super_block *sb, int level, bool wait) +{ +retry: + if (unlikely(sb->s_writers.frozen >= level)) { + if (!wait) + return 0; + wait_event(sb->s_writers.wait_unfrozen, + sb->s_writers.frozen < level); + } + +#ifdef CONFIG_LOCKDEP + acquire_freeze_lock(sb, level, !wait, _RET_IP_); +#endif + percpu_counter_inc(&sb->s_writers.counter[level-1]); + /* + * Make sure counter is updated before we check for frozen. + * freeze_super() first sets frozen and then checks the counter. + */ + smp_mb(); + if (unlikely(sb->s_writers.frozen >= level)) { + __sb_end_write(sb, level); + goto retry; + } + return 1; +} +EXPORT_SYMBOL(__sb_start_write); + +/** + * sb_wait_write - wait until all writers to given file system finish + * @sb: the super for which we wait + * @level: type of writers we wait for (normal vs page fault) + * + * This function waits until there are no writers of given type to given file + * system. Caller of this function should make sure there can be no new writers + * of type @level before calling this function. Otherwise this function can + * livelock. + */ +static void sb_wait_write(struct super_block *sb, int level) +{ + s64 writers; + + /* + * We just cycle-through lockdep here so that it does not complain + * about returning with lock to userspace + */ + rwsem_acquire(&sb->s_writers.lock_map[level-1], 0, 0, _THIS_IP_); + rwsem_release(&sb->s_writers.lock_map[level-1], 1, _THIS_IP_); + + do { + DEFINE_WAIT(wait); + + /* + * We use a barrier in prepare_to_wait() to separate setting + * of frozen and checking of the counter + */ + prepare_to_wait(&sb->s_writers.wait, &wait, + TASK_UNINTERRUPTIBLE); + + writers = percpu_counter_sum(&sb->s_writers.counter[level-1]); + if (writers) + schedule(); + + finish_wait(&sb->s_writers.wait, &wait); + } while (writers); +} + /** * freeze_super - lock the filesystem and force it into a consistent state * @sb: the super to lock @@ -1170,6 +1335,31 @@ out: * Syncs the super to make sure the filesystem is consistent and calls the fs's * freeze_fs. Subsequent calls to this without first thawing the fs will return * -EBUSY. + * + * During this function, sb->s_writers.frozen goes through these values: + * + * SB_UNFROZEN: File system is normal, all writes progress as usual. + * + * SB_FREEZE_WRITE: The file system is in the process of being frozen. New + * writes should be blocked, though page faults are still allowed. We wait for + * all writes to complete and then proceed to the next stage. + * + * SB_FREEZE_PAGEFAULT: Freezing continues. Now also page faults are blocked + * but internal fs threads can still modify the filesystem (although they + * should not dirty new pages or inodes), writeback can run etc. After waiting + * for all running page faults we sync the filesystem which will clean all + * dirty pages and inodes (no new dirty pages or inodes can be created when + * sync is running). + * + * SB_FREEZE_FS: The file system is frozen. Now all internal sources of fs + * modification are blocked (e.g. XFS preallocation truncation on inode + * reclaim). This is usually implemented by blocking new transactions for + * filesystems that have them and need this additional guard. After all + * internal writers are finished we call ->freeze_fs() to finish filesystem + * freezing. Then we transition to SB_FREEZE_COMPLETE state. This state is + * mostly auxiliary for filesystems to verify they do not modify frozen fs. + * + * sb->s_writers.frozen is protected by sb->s_umount. */ int freeze_super(struct super_block *sb) { @@ -1177,7 +1367,7 @@ int freeze_super(struct super_block *sb) atomic_inc(&sb->s_active); down_write(&sb->s_umount); - if (sb->s_frozen) { + if (sb->s_writers.frozen != SB_UNFROZEN) { deactivate_locked_super(sb); return -EBUSY; } @@ -1188,33 +1378,53 @@ int freeze_super(struct super_block *sb) } if (sb->s_flags & MS_RDONLY) { - sb->s_frozen = SB_FREEZE_TRANS; - smp_wmb(); + /* Nothing to do really... */ + sb->s_writers.frozen = SB_FREEZE_COMPLETE; up_write(&sb->s_umount); return 0; } - sb->s_frozen = SB_FREEZE_WRITE; + /* From now on, no new normal writers can start */ + sb->s_writers.frozen = SB_FREEZE_WRITE; + smp_wmb(); + + /* Release s_umount to preserve sb_start_write -> s_umount ordering */ + up_write(&sb->s_umount); + + sb_wait_write(sb, SB_FREEZE_WRITE); + + /* Now we go and block page faults... */ + down_write(&sb->s_umount); + sb->s_writers.frozen = SB_FREEZE_PAGEFAULT; smp_wmb(); + sb_wait_write(sb, SB_FREEZE_PAGEFAULT); + + /* All writers are done so after syncing there won't be dirty data */ sync_filesystem(sb); - sb->s_frozen = SB_FREEZE_TRANS; + /* Now wait for internal filesystem counter */ + sb->s_writers.frozen = SB_FREEZE_FS; smp_wmb(); + sb_wait_write(sb, SB_FREEZE_FS); - sync_blockdev(sb->s_bdev); if (sb->s_op->freeze_fs) { ret = sb->s_op->freeze_fs(sb); if (ret) { printk(KERN_ERR "VFS:Filesystem freeze failed\n"); - sb->s_frozen = SB_UNFROZEN; + sb->s_writers.frozen = SB_UNFROZEN; smp_wmb(); - wake_up(&sb->s_wait_unfrozen); + wake_up(&sb->s_writers.wait_unfrozen); deactivate_locked_super(sb); return ret; } } + /* + * This is just for debugging purposes so that fs can warn if it + * sees write activity when frozen is set to SB_FREEZE_COMPLETE. + */ + sb->s_writers.frozen = SB_FREEZE_COMPLETE; up_write(&sb->s_umount); return 0; } @@ -1231,7 +1441,7 @@ int thaw_super(struct super_block *sb) int error; down_write(&sb->s_umount); - if (sb->s_frozen == SB_UNFROZEN) { + if (sb->s_writers.frozen == SB_UNFROZEN) { up_write(&sb->s_umount); return -EINVAL; } @@ -1244,16 +1454,15 @@ int thaw_super(struct super_block *sb) if (error) { printk(KERN_ERR "VFS:Filesystem thaw failed\n"); - sb->s_frozen = SB_FREEZE_TRANS; up_write(&sb->s_umount); return error; } } out: - sb->s_frozen = SB_UNFROZEN; + sb->s_writers.frozen = SB_UNFROZEN; smp_wmb(); - wake_up(&sb->s_wait_unfrozen); + wake_up(&sb->s_writers.wait_unfrozen); deactivate_locked_super(sb); return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index 80c819cbe272..aefed9426b03 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -412,6 +412,7 @@ struct inodes_stat_t { #include #include #include +#include #include @@ -1439,6 +1440,8 @@ extern void f_delown(struct file *filp); extern pid_t f_getown(struct file *filp); extern int send_sigurg(struct fown_struct *fown); +struct mm_struct; + /* * Umount options */ @@ -1452,6 +1455,32 @@ extern int send_sigurg(struct fown_struct *fown); extern struct list_head super_blocks; extern spinlock_t sb_lock; +/* Possible states of 'frozen' field */ +enum { + SB_UNFROZEN = 0, /* FS is unfrozen */ + SB_FREEZE_WRITE = 1, /* Writes, dir ops, ioctls frozen */ + SB_FREEZE_TRANS = 2, + SB_FREEZE_PAGEFAULT = 2, /* Page faults stopped as well */ + SB_FREEZE_FS = 3, /* For internal FS use (e.g. to stop + * internal threads if needed) */ + SB_FREEZE_COMPLETE = 4, /* ->freeze_fs finished successfully */ +}; + +#define SB_FREEZE_LEVELS (SB_FREEZE_COMPLETE - 1) + +struct sb_writers { + /* Counters for counting writers at each level */ + struct percpu_counter counter[SB_FREEZE_LEVELS]; + wait_queue_head_t wait; /* queue for waiting for + writers / faults to finish */ + int frozen; /* Is sb frozen? */ + wait_queue_head_t wait_unfrozen; /* queue for waiting for + sb to be thawed */ +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map lock_map[SB_FREEZE_LEVELS]; +#endif +}; + struct super_block { struct list_head s_list; /* Keep this first */ dev_t s_dev; /* search index; _not_ kdev_t */ @@ -1501,6 +1530,7 @@ struct super_block { int s_frozen; wait_queue_head_t s_wait_unfrozen; + struct sb_writers s_writers; char s_id[32]; /* Informational name */ u8 s_uuid[16]; /* UUID */ @@ -1555,14 +1585,119 @@ extern struct timespec current_fs_time(struct super_block *sb); /* * Snapshotting support. */ -enum { - SB_UNFROZEN = 0, - SB_FREEZE_WRITE = 1, - SB_FREEZE_TRANS = 2, -}; +/* Will go away when all users are converted */ +#define vfs_check_frozen(sb, level) do { } while (0) + +void __sb_end_write(struct super_block *sb, int level); +int __sb_start_write(struct super_block *sb, int level, bool wait); + +/** + * sb_end_write - drop write access to a superblock + * @sb: the super we wrote to + * + * Decrement number of writers to the filesystem. Wake up possible waiters + * wanting to freeze the filesystem. + */ +static inline void sb_end_write(struct super_block *sb) +{ + __sb_end_write(sb, SB_FREEZE_WRITE); +} + +/** + * sb_end_pagefault - drop write access to a superblock from a page fault + * @sb: the super we wrote to + * + * Decrement number of processes handling write page fault to the filesystem. + * Wake up possible waiters wanting to freeze the filesystem. + */ +static inline void sb_end_pagefault(struct super_block *sb) +{ + __sb_end_write(sb, SB_FREEZE_PAGEFAULT); +} + +/** + * sb_end_intwrite - drop write access to a superblock for internal fs purposes + * @sb: the super we wrote to + * + * Decrement fs-internal number of writers to the filesystem. Wake up possible + * waiters wanting to freeze the filesystem. + */ +static inline void sb_end_intwrite(struct super_block *sb) +{ + __sb_end_write(sb, SB_FREEZE_FS); +} + +/** + * sb_start_write - get write access to a superblock + * @sb: the super we write to + * + * When a process wants to write data or metadata to a file system (i.e. dirty + * a page or an inode), it should embed the operation in a sb_start_write() - + * sb_end_write() pair to get exclusion against file system freezing. This + * function increments number of writers preventing freezing. If the file + * system is already frozen, the function waits until the file system is + * thawed. + * + * Since freeze protection behaves as a lock, users have to preserve + * ordering of freeze protection and other filesystem locks. Generally, + * freeze protection should be the outermost lock. In particular, we have: + * + * sb_start_write + * -> i_mutex (write path, truncate, directory ops, ...) + * -> s_umount (freeze_super, thaw_super) + */ +static inline void sb_start_write(struct super_block *sb) +{ + __sb_start_write(sb, SB_FREEZE_WRITE, true); +} + +static inline int sb_start_write_trylock(struct super_block *sb) +{ + return __sb_start_write(sb, SB_FREEZE_WRITE, false); +} + +/** + * sb_start_pagefault - get write access to a superblock from a page fault + * @sb: the super we write to + * + * When a process starts handling write page fault, it should embed the + * operation into sb_start_pagefault() - sb_end_pagefault() pair to get + * exclusion against file system freezing. This is needed since the page fault + * is going to dirty a page. This function increments number of running page + * faults preventing freezing. If the file system is already frozen, the + * function waits until the file system is thawed. + * + * Since page fault freeze protection behaves as a lock, users have to preserve + * ordering of freeze protection and other filesystem locks. It is advised to + * put sb_start_pagefault() close to mmap_sem in lock ordering. Page fault + * handling code implies lock dependency: + * + * mmap_sem + * -> sb_start_pagefault + */ +static inline void sb_start_pagefault(struct super_block *sb) +{ + __sb_start_write(sb, SB_FREEZE_PAGEFAULT, true); +} + +/* + * sb_start_intwrite - get write access to a superblock for internal fs purposes + * @sb: the super we write to + * + * This is the third level of protection against filesystem freezing. It is + * free for use by a filesystem. The only requirement is that it must rank + * below sb_start_pagefault. + * + * For example filesystem can call sb_start_intwrite() when starting a + * transaction which somewhat eases handling of freezing for internal sources + * of filesystem changes (internal fs threads, discarding preallocation on file + * close, etc.). + */ +static inline void sb_start_intwrite(struct super_block *sb) +{ + __sb_start_write(sb, SB_FREEZE_FS, true); +} -#define vfs_check_frozen(sb, level) \ - wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) extern bool inode_owner_or_capable(const struct inode *inode); @@ -1886,6 +2021,7 @@ struct file_system_type { struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; struct lock_class_key s_vfs_rename_key; + struct lock_class_key s_writers_key[SB_FREEZE_LEVELS]; struct lock_class_key i_lock_key; struct lock_class_key i_mutex_key; -- GitLab From eb04c28288bb0098d0e75d81ba2a575239de71d8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:35 +0200 Subject: [PATCH 4780/5711] fs: Add freezing handling to mnt_want_write() / mnt_drop_write() Most of places where we want freeze protection coincides with the places where we also have remount-ro protection. So make mnt_want_write() and mnt_drop_write() (and their _file alternative) prevent freezing as well. For the few cases that are really interested only in remount-ro protection provide new function variants. BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/file_table.c | 2 +- fs/inode.c | 4 +- fs/internal.h | 4 ++ fs/namespace.c | 97 +++++++++++++++++++++++++++++++++++++++---------- fs/open.c | 2 +- 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/fs/file_table.c b/fs/file_table.c index b54bf7fd0b15..701985e4ccda 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -217,7 +217,7 @@ static void drop_file_write_access(struct file *file) return; if (file_check_writeable(file) != 0) return; - mnt_drop_write(mnt); + __mnt_drop_write(mnt); file_release_write(file); } diff --git a/fs/inode.c b/fs/inode.c index 775cbabd4fa5..006c85ca06eb 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1660,11 +1660,11 @@ int file_update_time(struct file *file) return 0; /* Finally allowed to write? Takes lock. */ - if (mnt_want_write_file(file)) + if (__mnt_want_write_file(file)) return 0; ret = update_time(inode, &now, sync_it); - mnt_drop_write_file(file); + __mnt_drop_write_file(file); return ret; } diff --git a/fs/internal.h b/fs/internal.h index a6fd56c68b11..371bcc4b1697 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -61,6 +61,10 @@ extern void __init mnt_init(void); extern struct lglock vfsmount_lock; +extern int __mnt_want_write(struct vfsmount *); +extern int __mnt_want_write_file(struct file *); +extern void __mnt_drop_write(struct vfsmount *); +extern void __mnt_drop_write_file(struct file *); /* * fs_struct.c diff --git a/fs/namespace.c b/fs/namespace.c index c53d3381b0d0..4d31f73e2561 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -283,24 +283,22 @@ static int mnt_is_readonly(struct vfsmount *mnt) } /* - * Most r/o checks on a fs are for operations that take - * discrete amounts of time, like a write() or unlink(). - * We must keep track of when those operations start - * (for permission checks) and when they end, so that - * we can determine when writes are able to occur to - * a filesystem. + * Most r/o & frozen checks on a fs are for operations that take discrete + * amounts of time, like a write() or unlink(). We must keep track of when + * those operations start (for permission checks) and when they end, so that we + * can determine when writes are able to occur to a filesystem. */ /** - * mnt_want_write - get write access to a mount + * __mnt_want_write - get write access to a mount without freeze protection * @m: the mount on which to take a write * - * This tells the low-level filesystem that a write is - * about to be performed to it, and makes sure that - * writes are allowed before returning success. When - * the write operation is finished, mnt_drop_write() - * must be called. This is effectively a refcount. + * This tells the low-level filesystem that a write is about to be performed to + * it, and makes sure that writes are allowed (mnt it read-write) before + * returning success. This operation does not protect against filesystem being + * frozen. When the write operation is finished, __mnt_drop_write() must be + * called. This is effectively a refcount. */ -int mnt_want_write(struct vfsmount *m) +int __mnt_want_write(struct vfsmount *m) { struct mount *mnt = real_mount(m); int ret = 0; @@ -326,6 +324,27 @@ int mnt_want_write(struct vfsmount *m) ret = -EROFS; } preempt_enable(); + + return ret; +} + +/** + * mnt_want_write - get write access to a mount + * @m: the mount on which to take a write + * + * This tells the low-level filesystem that a write is about to be performed to + * it, and makes sure that writes are allowed (mount is read-write, filesystem + * is not frozen) before returning success. When the write operation is + * finished, mnt_drop_write() must be called. This is effectively a refcount. + */ +int mnt_want_write(struct vfsmount *m) +{ + int ret; + + sb_start_write(m->mnt_sb); + ret = __mnt_want_write(m); + if (ret) + sb_end_write(m->mnt_sb); return ret; } EXPORT_SYMBOL_GPL(mnt_want_write); @@ -355,38 +374,76 @@ int mnt_clone_write(struct vfsmount *mnt) EXPORT_SYMBOL_GPL(mnt_clone_write); /** - * mnt_want_write_file - get write access to a file's mount + * __mnt_want_write_file - get write access to a file's mount * @file: the file who's mount on which to take a write * - * This is like mnt_want_write, but it takes a file and can + * This is like __mnt_want_write, but it takes a file and can * do some optimisations if the file is open for write already */ -int mnt_want_write_file(struct file *file) +int __mnt_want_write_file(struct file *file) { struct inode *inode = file->f_dentry->d_inode; + if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) - return mnt_want_write(file->f_path.mnt); + return __mnt_want_write(file->f_path.mnt); else return mnt_clone_write(file->f_path.mnt); } + +/** + * mnt_want_write_file - get write access to a file's mount + * @file: the file who's mount on which to take a write + * + * This is like mnt_want_write, but it takes a file and can + * do some optimisations if the file is open for write already + */ +int mnt_want_write_file(struct file *file) +{ + int ret; + + sb_start_write(file->f_path.mnt->mnt_sb); + ret = __mnt_want_write_file(file); + if (ret) + sb_end_write(file->f_path.mnt->mnt_sb); + return ret; +} EXPORT_SYMBOL_GPL(mnt_want_write_file); /** - * mnt_drop_write - give up write access to a mount + * __mnt_drop_write - give up write access to a mount * @mnt: the mount on which to give up write access * * Tells the low-level filesystem that we are done * performing writes to it. Must be matched with - * mnt_want_write() call above. + * __mnt_want_write() call above. */ -void mnt_drop_write(struct vfsmount *mnt) +void __mnt_drop_write(struct vfsmount *mnt) { preempt_disable(); mnt_dec_writers(real_mount(mnt)); preempt_enable(); } + +/** + * mnt_drop_write - give up write access to a mount + * @mnt: the mount on which to give up write access + * + * Tells the low-level filesystem that we are done performing writes to it and + * also allows filesystem to be frozen again. Must be matched with + * mnt_want_write() call above. + */ +void mnt_drop_write(struct vfsmount *mnt) +{ + __mnt_drop_write(mnt); + sb_end_write(mnt->mnt_sb); +} EXPORT_SYMBOL_GPL(mnt_drop_write); +void __mnt_drop_write_file(struct file *file) +{ + __mnt_drop_write(file->f_path.mnt); +} + void mnt_drop_write_file(struct file *file) { mnt_drop_write(file->f_path.mnt); diff --git a/fs/open.c b/fs/open.c index 8d2c8970029c..9ddc18565503 100644 --- a/fs/open.c +++ b/fs/open.c @@ -620,7 +620,7 @@ static inline int __get_file_write_access(struct inode *inode, /* * Balanced in __fput() */ - error = mnt_want_write(mnt); + error = __mnt_want_write(mnt); if (error) put_write_access(inode); } -- GitLab From 5d37e9e6dec65cd21be68ee92de99686213e916b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:36 +0200 Subject: [PATCH 4781/5711] fs: Skip atime update on frozen filesystem It is unexpected to block reading of frozen filesystem because of atime update. Also handling blocking on frozen filesystem because of atime update would make locking more complex than it already is. So just skip atime update when filesystem is frozen like we skip it when filesystem is remounted read-only. BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 006c85ca06eb..74d7c20fac88 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1542,9 +1542,11 @@ void touch_atime(struct path *path) if (timespec_equal(&inode->i_atime, &now)) return; - if (mnt_want_write(mnt)) + if (!sb_start_write_trylock(inode->i_sb)) return; + if (__mnt_want_write(mnt)) + goto skip_update; /* * File systems can error out when updating inodes if they need to * allocate new space to modify an inode (such is the case for @@ -1553,7 +1555,9 @@ void touch_atime(struct path *path) * so just ignore the return value. */ update_time(inode, &now, S_ATIME); - mnt_drop_write(mnt); + __mnt_drop_write(mnt); +skip_update: + sb_end_write(inode->i_sb); } EXPORT_SYMBOL(touch_atime); -- GitLab From 14da9200140f8d722ad1767dfabadebd8b34f2ad Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:37 +0200 Subject: [PATCH 4782/5711] fs: Protect write paths by sb_start_write - sb_end_write There are several entry points which dirty pages in a filesystem. mmap (handled by block_page_mkwrite()), buffered write (handled by __generic_file_aio_write()), splice write (generic_file_splice_write), truncate, and fallocate (these can dirty last partial page - handled inside each filesystem separately). Protect these places with sb_start_write() and sb_end_write(). ->page_mkwrite() calls are particularly complex since they are called with mmap_sem held and thus we cannot use standard sb_start_write() due to lock ordering constraints. We solve the problem by using a special freeze protection sb_start_pagefault() which ranks below mmap_sem. BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/buffer.c | 22 ++++------------------ fs/open.c | 7 ++++++- fs/splice.c | 3 +++ mm/filemap.c | 12 ++++++++++-- mm/filemap_xip.c | 5 +++-- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index d5ec360e332d..9f6d2e41281d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2306,8 +2306,8 @@ EXPORT_SYMBOL(block_commit_write); * beyond EOF, then the page is guaranteed safe against truncation until we * unlock the page. * - * Direct callers of this function should call vfs_check_frozen() so that page - * fault does not busyloop until the fs is thawed. + * Direct callers of this function should protect against filesystem freezing + * using sb_start_write() - sb_end_write() functions. */ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, get_block_t get_block) @@ -2345,18 +2345,7 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, if (unlikely(ret < 0)) goto out_unlock; - /* - * Freezing in progress? We check after the page is marked dirty and - * with page lock held so if the test here fails, we are sure freezing - * code will wait during syncing until the page fault is done - at that - * point page will be dirty and unlocked so freezing code will write it - * and writeprotect it again. - */ set_page_dirty(page); - if (inode->i_sb->s_frozen != SB_UNFROZEN) { - ret = -EAGAIN; - goto out_unlock; - } wait_on_page_writeback(page); return 0; out_unlock: @@ -2371,12 +2360,9 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, int ret; struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb; - /* - * This check is racy but catches the common case. The check in - * __block_page_mkwrite() is reliable. - */ - vfs_check_frozen(sb, SB_FREEZE_WRITE); + sb_start_pagefault(sb); ret = __block_page_mkwrite(vma, vmf, get_block); + sb_end_pagefault(sb); return block_page_mkwrite_return(ret); } EXPORT_SYMBOL(block_page_mkwrite); diff --git a/fs/open.c b/fs/open.c index 9ddc18565503..f3d96e7e7b19 100644 --- a/fs/open.c +++ b/fs/open.c @@ -164,11 +164,13 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) if (IS_APPEND(inode)) goto out_putf; + sb_start_write(inode->i_sb); error = locks_verify_truncate(inode, file, length); if (!error) error = security_path_truncate(&file->f_path); if (!error) error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); + sb_end_write(inode->i_sb); out_putf: fput(file); out: @@ -266,7 +268,10 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!file->f_op->fallocate) return -EOPNOTSUPP; - return file->f_op->fallocate(file, mode, offset, len); + sb_start_write(inode->i_sb); + ret = file->f_op->fallocate(file, mode, offset, len); + sb_end_write(inode->i_sb); + return ret; } SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) diff --git a/fs/splice.c b/fs/splice.c index 7bf08fa22ec9..41514dd89462 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -996,6 +996,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, }; ssize_t ret; + sb_start_write(inode->i_sb); + pipe_lock(pipe); splice_from_pipe_begin(&sd); @@ -1034,6 +1036,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, *ppos += ret; balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } + sb_end_write(inode->i_sb); return ret; } diff --git a/mm/filemap.c b/mm/filemap.c index 51efee65c2cc..fa5ca304148e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1718,6 +1718,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct inode *inode = vma->vm_file->f_path.dentry->d_inode; int ret = VM_FAULT_LOCKED; + sb_start_pagefault(inode->i_sb); file_update_time(vma->vm_file); lock_page(page); if (page->mapping != inode->i_mapping) { @@ -1725,7 +1726,14 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ret = VM_FAULT_NOPAGE; goto out; } + /* + * We mark the page dirty already here so that when freeze is in + * progress, we are guaranteed that writeback during freezing will + * see the dirty page and writeprotect it again. + */ + set_page_dirty(page); out: + sb_end_pagefault(inode->i_sb); return ret; } EXPORT_SYMBOL(filemap_page_mkwrite); @@ -2426,8 +2434,6 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, count = ocount; pos = *ppos; - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); - /* We can write back this queue in page reclaim */ current->backing_dev_info = mapping->backing_dev_info; written = 0; @@ -2526,6 +2532,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, BUG_ON(iocb->ki_pos != pos); + sb_start_write(inode->i_sb); mutex_lock(&inode->i_mutex); blk_start_plug(&plug); ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); @@ -2539,6 +2546,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ret = err; } blk_finish_plug(&plug); + sb_end_write(inode->i_sb); return ret; } EXPORT_SYMBOL(generic_file_aio_write); diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 80b34ef82dfe..13e013b1270c 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -402,6 +402,8 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, loff_t pos; ssize_t ret; + sb_start_write(inode->i_sb); + mutex_lock(&inode->i_mutex); if (!access_ok(VERIFY_READ, buf, len)) { @@ -412,8 +414,6 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, pos = *ppos; count = len; - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); - /* We can write back this queue in page reclaim */ current->backing_dev_info = mapping->backing_dev_info; @@ -437,6 +437,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, current->backing_dev_info = NULL; out_up: mutex_unlock(&inode->i_mutex); + sb_end_write(inode->i_sb); return ret; } EXPORT_SYMBOL_GPL(xip_file_write); -- GitLab From 8e8ad8a57c75f3bda2d03a4c4396a9a7024ad275 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:38 +0200 Subject: [PATCH 4783/5711] ext4: Convert to new freezing mechanism We remove most of frozen checks since upper layer takes care of blocking all writes. We have to handle protection in ext4_page_mkwrite() in a special way because we cannot use generic block_page_mkwrite(). Also we add a freeze protection to ext4_evict_inode() so that iput() of unlinked inode cannot modify a frozen filesystem (we cannot easily instrument ext4_journal_start() / ext4_journal_stop() with freeze protection because we are missing the superblock pointer in ext4_journal_stop() in nojournal mode). CC: linux-ext4@vger.kernel.org CC: "Theodore Ts'o" BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Acked-by: "Theodore Ts'o" Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/ext4/inode.c | 15 ++++++++++----- fs/ext4/mmp.c | 6 ++++++ fs/ext4/super.c | 31 +++++++------------------------ 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 02bc8cbe7281..301e1c2db891 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -233,6 +233,11 @@ void ext4_evict_inode(struct inode *inode) if (is_bad_inode(inode)) goto no_delete; + /* + * Protect us against freezing - iput() caller didn't have to have any + * protection against it + */ + sb_start_intwrite(inode->i_sb); handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3); if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); @@ -242,6 +247,7 @@ void ext4_evict_inode(struct inode *inode) * cleaned up. */ ext4_orphan_del(NULL, inode); + sb_end_intwrite(inode->i_sb); goto no_delete; } @@ -273,6 +279,7 @@ void ext4_evict_inode(struct inode *inode) stop_handle: ext4_journal_stop(handle); ext4_orphan_del(NULL, inode); + sb_end_intwrite(inode->i_sb); goto no_delete; } } @@ -301,6 +308,7 @@ void ext4_evict_inode(struct inode *inode) else ext4_free_inode(handle, inode); ext4_journal_stop(handle); + sb_end_intwrite(inode->i_sb); return; no_delete: ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ @@ -4701,11 +4709,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) get_block_t *get_block; int retries = 0; - /* - * This check is racy but catches the common case. We rely on - * __block_page_mkwrite() to do a reliable check. - */ - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + sb_start_pagefault(inode->i_sb); /* Delalloc case is easy... */ if (test_opt(inode->i_sb, DELALLOC) && !ext4_should_journal_data(inode) && @@ -4773,5 +4777,6 @@ retry_alloc: out_ret: ret = block_page_mkwrite_return(ret); out: + sb_end_pagefault(inode->i_sb); return ret; } diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index f99a1311e847..fe7c63f4717e 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -44,6 +44,11 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) { struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); + /* + * We protect against freezing so that we don't create dirty buffers + * on frozen filesystem. + */ + sb_start_write(sb); ext4_mmp_csum_set(sb, mmp); mark_buffer_dirty(bh); lock_buffer(bh); @@ -51,6 +56,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) get_bh(bh); submit_bh(WRITE_SYNC, bh); wait_on_buffer(bh); + sb_end_write(sb); if (unlikely(!buffer_uptodate(bh))) return 1; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d8759401ecae..9cc9bfd5176b 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -332,33 +332,17 @@ static void ext4_put_nojournal(handle_t *handle) * journal_end calls result in the superblock being marked dirty, so * that sync() will call the filesystem's write_super callback if * appropriate. - * - * To avoid j_barrier hold in userspace when a user calls freeze(), - * ext4 prevents a new handle from being started by s_frozen, which - * is in an upper layer. */ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) { journal_t *journal; - handle_t *handle; trace_ext4_journal_start(sb, nblocks, _RET_IP_); if (sb->s_flags & MS_RDONLY) return ERR_PTR(-EROFS); + WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); journal = EXT4_SB(sb)->s_journal; - handle = ext4_journal_current_handle(); - - /* - * If a handle has been started, it should be allowed to - * finish, otherwise deadlock could happen between freeze - * and others(e.g. truncate) due to the restart of the - * journal handle if the filesystem is forzen and active - * handles are not stopped. - */ - if (!handle) - vfs_check_frozen(sb, SB_FREEZE_TRANS); - if (!journal) return ext4_get_nojournal(); /* @@ -2723,6 +2707,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) sb = elr->lr_super; ngroups = EXT4_SB(sb)->s_groups_count; + sb_start_write(sb); for (group = elr->lr_next_group; group < ngroups; group++) { gdp = ext4_get_group_desc(sb, group, NULL); if (!gdp) { @@ -2749,6 +2734,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) elr->lr_next_sched = jiffies + elr->lr_timeout; elr->lr_next_group = group + 1; } + sb_end_write(sb); return ret; } @@ -4302,10 +4288,8 @@ int ext4_force_commit(struct super_block *sb) return 0; journal = EXT4_SB(sb)->s_journal; - if (journal) { - vfs_check_frozen(sb, SB_FREEZE_TRANS); + if (journal) ret = ext4_journal_force_commit(journal); - } return ret; } @@ -4342,9 +4326,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait) * gives us a chance to flush the journal completely and mark the fs clean. * * Note that only this function cannot bring a filesystem to be in a clean - * state independently, because ext4 prevents a new handle from being started - * by @sb->s_frozen, which stays in an upper layer. It thus needs help from - * the upper layer. + * state independently. It relies on upper layer to stop all data & metadata + * modifications. */ static int ext4_freeze(struct super_block *sb) { @@ -4371,7 +4354,7 @@ static int ext4_freeze(struct super_block *sb) EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); error = ext4_commit_super(sb, 1); out: - /* we rely on s_frozen to stop further updates */ + /* we rely on upper layer to stop further updates */ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); return error; } -- GitLab From d9457dc056249913a7abe8b71dc09e427e590e35 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:39 +0200 Subject: [PATCH 4784/5711] xfs: Convert to new freezing code Generic code now blocks all writers from standard write paths. So we add blocking of all writers coming from ioctl (we get a protection of ioctl against racing remount read-only as a bonus) and convert xfs_file_aio_write() to a non-racy freeze protection. We also keep freeze protection on transaction start to block internal filesystem writes such as removal of preallocated blocks. CC: Ben Myers CC: Alex Elder CC: xfs@oss.sgi.com Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/xfs/xfs_aops.c | 18 +++++++++++++++ fs/xfs/xfs_file.c | 10 +++++--- fs/xfs/xfs_ioctl.c | 55 +++++++++++++++++++++++++++++++++++++++++--- fs/xfs/xfs_ioctl32.c | 12 ++++++++++ fs/xfs/xfs_iomap.c | 4 ++-- fs/xfs/xfs_mount.c | 2 +- fs/xfs/xfs_mount.h | 3 --- fs/xfs/xfs_sync.c | 2 +- fs/xfs/xfs_trans.c | 17 +++++++++++--- fs/xfs/xfs_trans.h | 2 ++ 10 files changed, 109 insertions(+), 16 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8dad722c0041..daa42383ebd9 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -123,6 +123,12 @@ xfs_setfilesize_trans_alloc( ioend->io_append_trans = tp; + /* + * We will pass freeze protection with a transaction. So tell lockdep + * we released it. + */ + rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], + 1, _THIS_IP_); /* * We hand off the transaction to the completion thread now, so * clear the flag here. @@ -199,6 +205,15 @@ xfs_end_io( struct xfs_inode *ip = XFS_I(ioend->io_inode); int error = 0; + if (ioend->io_append_trans) { + /* + * We've got freeze protection passed with the transaction. + * Tell lockdep about it. + */ + rwsem_acquire_read( + &ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], + 0, 1, _THIS_IP_); + } if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { ioend->io_error = -EIO; goto done; @@ -1410,6 +1425,9 @@ out_trans_cancel: if (ioend->io_append_trans) { current_set_flags_nested(&ioend->io_append_trans->t_pflags, PF_FSTRANS); + rwsem_acquire_read( + &inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], + 0, 1, _THIS_IP_); xfs_trans_cancel(ioend->io_append_trans, 0); } out_destroy_ioend: diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 9f7ec15a6522..f0081f20e5c0 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -781,10 +781,12 @@ xfs_file_aio_write( if (ocount == 0) return 0; - xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); + sb_start_write(inode->i_sb); - if (XFS_FORCED_SHUTDOWN(ip->i_mount)) - return -EIO; + if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { + ret = -EIO; + goto out; + } if (unlikely(file->f_flags & O_DIRECT)) ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); @@ -803,6 +805,8 @@ xfs_file_aio_write( ret = err; } +out: + sb_end_write(inode->i_sb); return ret; } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 1f1535d25a9b..0e0232c3b6d9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -364,9 +364,15 @@ xfs_fssetdm_by_handle( if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(parfilp); + if (error) + return error; + dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); - if (IS_ERR(dentry)) + if (IS_ERR(dentry)) { + mnt_drop_write_file(parfilp); return PTR_ERR(dentry); + } if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { error = -XFS_ERROR(EPERM); @@ -382,6 +388,7 @@ xfs_fssetdm_by_handle( fsd.fsd_dmstate); out: + mnt_drop_write_file(parfilp); dput(dentry); return error; } @@ -634,7 +641,11 @@ xfs_ioc_space( if (ioflags & IO_INVIS) attr_flags |= XFS_ATTR_DMI; + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); + mnt_drop_write_file(filp); return -error; } @@ -1163,6 +1174,7 @@ xfs_ioc_fssetxattr( { struct fsxattr fa; unsigned int mask; + int error; if (copy_from_user(&fa, arg, sizeof(fa))) return -EFAULT; @@ -1171,7 +1183,12 @@ xfs_ioc_fssetxattr( if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) mask |= FSX_NONBLOCK; - return -xfs_ioctl_setattr(ip, &fa, mask); + error = mnt_want_write_file(filp); + if (error) + return error; + error = xfs_ioctl_setattr(ip, &fa, mask); + mnt_drop_write_file(filp); + return -error; } STATIC int @@ -1196,6 +1213,7 @@ xfs_ioc_setxflags( struct fsxattr fa; unsigned int flags; unsigned int mask; + int error; if (copy_from_user(&flags, arg, sizeof(flags))) return -EFAULT; @@ -1210,7 +1228,12 @@ xfs_ioc_setxflags( mask |= FSX_NONBLOCK; fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); - return -xfs_ioctl_setattr(ip, &fa, mask); + error = mnt_want_write_file(filp); + if (error) + return error; + error = xfs_ioctl_setattr(ip, &fa, mask); + mnt_drop_write_file(filp); + return -error; } STATIC int @@ -1385,8 +1408,13 @@ xfs_file_ioctl( if (copy_from_user(&dmi, arg, sizeof(dmi))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; + error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, dmi.fsd_dmstate); + mnt_drop_write_file(filp); return -error; } @@ -1434,7 +1462,11 @@ xfs_file_ioctl( if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_swapext(&sxp); + mnt_drop_write_file(filp); return -error; } @@ -1463,9 +1495,14 @@ xfs_file_ioctl( if (copy_from_user(&inout, arg, sizeof(inout))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; + /* input parameter is passed in resblks field of structure */ in = inout.resblks; error = xfs_reserve_blocks(mp, &in, &inout); + mnt_drop_write_file(filp); if (error) return -error; @@ -1496,7 +1533,11 @@ xfs_file_ioctl( if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_growfs_data(mp, &in); + mnt_drop_write_file(filp); return -error; } @@ -1506,7 +1547,11 @@ xfs_file_ioctl( if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_growfs_log(mp, &in); + mnt_drop_write_file(filp); return -error; } @@ -1516,7 +1561,11 @@ xfs_file_ioctl( if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_growfs_rt(mp, &in); + mnt_drop_write_file(filp); return -error; } diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index c4f2da0d2bf5..1244274a5674 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -600,7 +600,11 @@ xfs_file_compat_ioctl( if (xfs_compat_growfs_data_copyin(&in, arg)) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_growfs_data(mp, &in); + mnt_drop_write_file(filp); return -error; } case XFS_IOC_FSGROWFSRT_32: { @@ -608,7 +612,11 @@ xfs_file_compat_ioctl( if (xfs_compat_growfs_rt_copyin(&in, arg)) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_growfs_rt(mp, &in); + mnt_drop_write_file(filp); return -error; } #endif @@ -627,7 +635,11 @@ xfs_file_compat_ioctl( offsetof(struct xfs_swapext, sx_stat)) || xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) return -XFS_ERROR(EFAULT); + error = mnt_want_write_file(filp); + if (error) + return error; error = xfs_swapext(&sxp); + mnt_drop_write_file(filp); return -error; } case XFS_IOC_FSBULKSTAT_32: diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index aadfce6681ee..b3b9b26091a3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -680,9 +680,9 @@ xfs_iomap_write_unwritten( * the same inode that we complete here and might deadlock * on the iolock. */ - xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); + sb_start_intwrite(mp->m_super); tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); - tp->t_flags |= XFS_TRANS_RESERVE; + tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT; error = xfs_trans_reserve(tp, resblks, XFS_WRITE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 536021fb3d4e..b09a4a7eb640 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1544,7 +1544,7 @@ xfs_unmountfs( int xfs_fs_writable(xfs_mount_t *mp) { - return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || + return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) || (mp->m_flags & XFS_MOUNT_RDONLY)); } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 90c1fc9eaea4..c6bca0d92cb1 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -314,9 +314,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ -#define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen) -#define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l)) - /* * Flags for xfs_mountfs */ diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 1e9ee064dbb2..0b9feacdcd1f 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -394,7 +394,7 @@ xfs_sync_worker( if (!(mp->m_super->s_flags & MS_ACTIVE) && !(mp->m_flags & XFS_MOUNT_RDONLY)) { /* dgc: errors ignored here */ - if (mp->m_super->s_frozen == SB_UNFROZEN && + if (mp->m_super->s_writers.frozen == SB_UNFROZEN && xfs_log_need_covered(mp)) error = xfs_fs_log_dummy(mp); else diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index fdf324508c5e..06ed520a767f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -576,8 +576,12 @@ xfs_trans_alloc( xfs_mount_t *mp, uint type) { - xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); - return _xfs_trans_alloc(mp, type, KM_SLEEP); + xfs_trans_t *tp; + + sb_start_intwrite(mp->m_super); + tp = _xfs_trans_alloc(mp, type, KM_SLEEP); + tp->t_flags |= XFS_TRANS_FREEZE_PROT; + return tp; } xfs_trans_t * @@ -588,6 +592,7 @@ _xfs_trans_alloc( { xfs_trans_t *tp; + WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); atomic_inc(&mp->m_active_trans); tp = kmem_zone_zalloc(xfs_trans_zone, memflags); @@ -611,6 +616,8 @@ xfs_trans_free( xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); atomic_dec(&tp->t_mountp->m_active_trans); + if (tp->t_flags & XFS_TRANS_FREEZE_PROT) + sb_end_intwrite(tp->t_mountp->m_super); xfs_trans_free_dqinfo(tp); kmem_zone_free(xfs_trans_zone, tp); } @@ -643,7 +650,11 @@ xfs_trans_dup( ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(tp->t_ticket != NULL); - ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE); + ntp->t_flags = XFS_TRANS_PERM_LOG_RES | + (tp->t_flags & XFS_TRANS_RESERVE) | + (tp->t_flags & XFS_TRANS_FREEZE_PROT); + /* We gave our writer reference to the new transaction */ + tp->t_flags &= ~XFS_TRANS_FREEZE_PROT; ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; tp->t_blk_res = tp->t_blk_res_used; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 7c37b533aa8e..19c174282878 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -179,6 +179,8 @@ struct xfs_log_item_desc { #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ +#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer + count in superblock */ /* * Values for call flags parameter. -- GitLab From fef6925cd4c6b564ecff477e07a0fca987542223 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:40 +0200 Subject: [PATCH 4785/5711] ocfs2: Convert to new freezing mechanism Protect ocfs2_page_mkwrite() and ocfs2_file_aio_write() using the new freeze protection. We also protect several ioctl entry points which were missing the protection. Finally, we add freeze protection to the journaling mechanism so that iput() of unlinked inode cannot modify a frozen filesystem. CC: Mark Fasheh CC: Joel Becker CC: ocfs2-devel@oss.oracle.com Acked-by: Joel Becker Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/ocfs2/file.c | 11 +++++++++-- fs/ocfs2/ioctl.c | 14 ++++++++++++-- fs/ocfs2/journal.c | 7 ++++++- fs/ocfs2/mmap.c | 2 ++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 7602783d7f41..46a1f6d75104 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1971,6 +1971,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, { struct inode *inode = file->f_path.dentry->d_inode; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + int ret; if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && !ocfs2_writes_unwritten_extents(osb)) @@ -1985,7 +1986,12 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, if (!(file->f_mode & FMODE_WRITE)) return -EBADF; - return __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); + ret = mnt_want_write_file(file); + if (ret) + return ret; + ret = __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); + mnt_drop_write_file(file); + return ret; } static long ocfs2_fallocate(struct file *file, int mode, loff_t offset, @@ -2261,7 +2267,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, if (iocb->ki_left == 0) return 0; - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + sb_start_write(inode->i_sb); appending = file->f_flags & O_APPEND ? 1 : 0; direct_io = file->f_flags & O_DIRECT ? 1 : 0; @@ -2436,6 +2442,7 @@ out_sems: ocfs2_iocb_clear_sem_locked(iocb); mutex_unlock(&inode->i_mutex); + sb_end_write(inode->i_sb); if (written) ret = written; diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index d96f7f81d8dd..f20edcbfe700 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -928,7 +928,12 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (get_user(new_clusters, (int __user *)arg)) return -EFAULT; - return ocfs2_group_extend(inode, new_clusters); + status = mnt_want_write_file(filp); + if (status) + return status; + status = ocfs2_group_extend(inode, new_clusters); + mnt_drop_write_file(filp); + return status; case OCFS2_IOC_GROUP_ADD: case OCFS2_IOC_GROUP_ADD64: if (!capable(CAP_SYS_RESOURCE)) @@ -937,7 +942,12 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&input, (int __user *) arg, sizeof(input))) return -EFAULT; - return ocfs2_group_add(inode, &input); + status = mnt_want_write_file(filp); + if (status) + return status; + status = ocfs2_group_add(inode, &input); + mnt_drop_write_file(filp); + return status; case OCFS2_IOC_REFLINK: if (copy_from_user(&args, argp, sizeof(args))) return -EFAULT; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 0a42ae96dca7..2dd36af79e26 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -355,11 +355,14 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs) if (journal_current_handle()) return jbd2_journal_start(journal, max_buffs); + sb_start_intwrite(osb->sb); + down_read(&osb->journal->j_trans_barrier); handle = jbd2_journal_start(journal, max_buffs); if (IS_ERR(handle)) { up_read(&osb->journal->j_trans_barrier); + sb_end_intwrite(osb->sb); mlog_errno(PTR_ERR(handle)); @@ -388,8 +391,10 @@ int ocfs2_commit_trans(struct ocfs2_super *osb, if (ret < 0) mlog_errno(ret); - if (!nested) + if (!nested) { up_read(&journal->j_trans_barrier); + sb_end_intwrite(osb->sb); + } return ret; } diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 9cd41083e991..d150372fd81d 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -136,6 +136,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) sigset_t oldset; int ret; + sb_start_pagefault(inode->i_sb); ocfs2_block_signals(&oldset); /* @@ -165,6 +166,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) out: ocfs2_unblock_signals(&oldset); + sb_end_pagefault(inode->i_sb); return ret; } -- GitLab From 39263d5e71d0fad09eab0d855a9407ad2af8378c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:41 +0200 Subject: [PATCH 4786/5711] gfs2: Convert to new freezing mechanism We update gfs2_page_mkwrite() to use new freeze protection and the transaction code to use freeze protection while the transaction is running. That is needed to stop iput() of unlinked file from modifying the filesystem. The rest is handled by the generic code. CC: cluster-devel@redhat.com CC: Steven Whitehouse Acked-by: Steven Whitehouse Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/gfs2/file.c | 15 +++------------ fs/gfs2/trans.c | 4 ++++ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 07959150d44e..8ffeb031248e 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -370,11 +370,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) loff_t size; int ret; - /* Wait if fs is frozen. This is racy so we check again later on - * and retry if the fs has been frozen after the page lock has - * been acquired - */ - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + sb_start_pagefault(inode->i_sb); /* Update file times before taking page lock */ file_update_time(vma->vm_file); @@ -458,14 +454,9 @@ out: gfs2_holder_uninit(&gh); if (ret == 0) { set_page_dirty(page); - /* This check must be post dropping of transaction lock */ - if (inode->i_sb->s_frozen == SB_UNFROZEN) { - wait_on_page_writeback(page); - } else { - ret = -EAGAIN; - unlock_page(page); - } + wait_on_page_writeback(page); } + sb_end_pagefault(inode->i_sb); return block_page_mkwrite_return(ret); } diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index ad3e2fb763d7..adbd27875ef9 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -50,6 +50,7 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, if (revokes) tr->tr_reserved += gfs2_struct2blk(sdp, revokes, sizeof(u64)); + sb_start_intwrite(sdp->sd_vfs); gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); error = gfs2_glock_nq(&tr->tr_t_gh); @@ -68,6 +69,7 @@ fail_gunlock: gfs2_glock_dq(&tr->tr_t_gh); fail_holder_uninit: + sb_end_intwrite(sdp->sd_vfs); gfs2_holder_uninit(&tr->tr_t_gh); kfree(tr); @@ -116,6 +118,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) gfs2_holder_uninit(&tr->tr_t_gh); kfree(tr); } + sb_end_intwrite(sdp->sd_vfs); return; } @@ -136,6 +139,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) gfs2_log_flush(sdp, NULL); + sb_end_intwrite(sdp->sd_vfs); } /** -- GitLab From 58ef6a75c38e9faa7d19bb7d7b45fe0df02e8621 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:42 +0200 Subject: [PATCH 4787/5711] fuse: Convert to new freezing mechanism Convert check in fuse_file_aio_write() to using new freeze protection. CC: fuse-devel@lists.sourceforge.net CC: Miklos Szeredi Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/fuse/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b321a688cde7..93d8d6c9494d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -944,9 +944,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, return err; count = ocount; - + sb_start_write(inode->i_sb); mutex_lock(&inode->i_mutex); - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); /* We can write back this queue in page reclaim */ current->backing_dev_info = mapping->backing_dev_info; @@ -1004,6 +1003,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, out: current->backing_dev_info = NULL; mutex_unlock(&inode->i_mutex); + sb_end_write(inode->i_sb); return written ? written : err; } -- GitLab From fbf8fb76505a9e5bbb47e91d964105b6ea59b0ec Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:43 +0200 Subject: [PATCH 4788/5711] ntfs: Convert to new freezing mechanism Move check in ntfs_file_aio_write_nolock() to ntfs_file_aio_write() and use new freeze protection. CC: linux-ntfs-dev@lists.sourceforge.net CC: Anton Altaparmakov Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/ntfs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 7389d2d5e51d..1ecf46448f85 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -2084,7 +2084,6 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb, if (err) return err; pos = *ppos; - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); /* We can write back this queue in page reclaim. */ current->backing_dev_info = mapping->backing_dev_info; written = 0; @@ -2119,6 +2118,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, BUG_ON(iocb->ki_pos != pos); + sb_start_write(inode->i_sb); mutex_lock(&inode->i_mutex); ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos); mutex_unlock(&inode->i_mutex); @@ -2127,6 +2127,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err < 0) ret = err; } + sb_end_write(inode->i_sb); return ret; } -- GitLab From 2c22b337b5bbb497c41b348b2357b7070ed5ba88 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:44 +0200 Subject: [PATCH 4789/5711] nilfs2: Convert to new freezing mechanism We change nilfs_page_mkwrite() to provide proper freeze protection for writeable page faults (we must wait for frozen filesystem even if the page is fully mapped). We remove all vfs_check_frozen() checks since they are now handled by the generic code. CC: linux-nilfs@vger.kernel.org CC: KONISHI Ryusuke Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/nilfs2/file.c | 18 +++++++++++------- fs/nilfs2/ioctl.c | 2 -- fs/nilfs2/segment.c | 5 ++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 62cebc8e1a1f..a4d56ac02e6c 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -69,16 +69,18 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct page *page = vmf->page; struct inode *inode = vma->vm_file->f_dentry->d_inode; struct nilfs_transaction_info ti; - int ret; + int ret = 0; if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info))) return VM_FAULT_SIGBUS; /* -ENOSPC */ + sb_start_pagefault(inode->i_sb); lock_page(page); if (page->mapping != inode->i_mapping || page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) { unlock_page(page); - return VM_FAULT_NOPAGE; /* make the VM retry the fault */ + ret = -EFAULT; /* make the VM retry the fault */ + goto out; } /* @@ -112,19 +114,21 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ret = nilfs_transaction_begin(inode->i_sb, &ti, 1); /* never returns -ENOMEM, but may return -ENOSPC */ if (unlikely(ret)) - return VM_FAULT_SIGBUS; + goto out; - ret = block_page_mkwrite(vma, vmf, nilfs_get_block); - if (ret != VM_FAULT_LOCKED) { + ret = __block_page_mkwrite(vma, vmf, nilfs_get_block); + if (ret) { nilfs_transaction_abort(inode->i_sb); - return ret; + goto out; } nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits)); nilfs_transaction_commit(inode->i_sb); mapped: wait_on_page_writeback(page); - return VM_FAULT_LOCKED; + out: + sb_end_pagefault(inode->i_sb); + return block_page_mkwrite_return(ret); } static const struct vm_operations_struct nilfs_file_vm_ops = { diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 06658caa18bd..08f27968a7a9 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -660,8 +660,6 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, goto out_free; } - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); - ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); if (ret < 0) printk(KERN_ERR "NILFS: GC failed during preparation: " diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 88e11fb346b6..a5752a589932 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -189,7 +189,7 @@ int nilfs_transaction_begin(struct super_block *sb, if (ret > 0) return 0; - vfs_check_frozen(sb, SB_FREEZE_WRITE); + sb_start_intwrite(sb); nilfs = sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); @@ -205,6 +205,7 @@ int nilfs_transaction_begin(struct super_block *sb, current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) kmem_cache_free(nilfs_transaction_cachep, ti); + sb_end_intwrite(sb); return ret; } @@ -246,6 +247,7 @@ int nilfs_transaction_commit(struct super_block *sb) err = nilfs_construct_segment(sb); if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) kmem_cache_free(nilfs_transaction_cachep, ti); + sb_end_intwrite(sb); return err; } @@ -264,6 +266,7 @@ void nilfs_transaction_abort(struct super_block *sb) current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) kmem_cache_free(nilfs_transaction_cachep, ti); + sb_end_intwrite(sb); } void nilfs_relax_pressure_in_lock(struct super_block *sb) -- GitLab From b2b5ef5c8e89f19b68c174bf246f3ca212dbf0bc Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:45 +0200 Subject: [PATCH 4790/5711] btrfs: Convert to new freezing mechanism We convert btrfs_file_aio_write() to use new freeze check. We also add proper freeze protection to btrfs_page_mkwrite(). We also add freeze protection to the transaction mechanism to avoid starting transactions on frozen filesystem. At minimum this is necessary to stop iput() of unlinked file to change frozen filesystem during truncation. Checks in cleaner_kthread() and transaction_kthread() can be safely removed since btrfs_freeze() will lock the mutexes and thus block the threads (and they shouldn't have anything to do anyway). CC: linux-btrfs@vger.kernel.org CC: Chris Mason Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/btrfs/disk-io.c | 3 --- fs/btrfs/file.c | 3 ++- fs/btrfs/inode.c | 6 +++++- fs/btrfs/transaction.c | 7 +++++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2936ca49b3b4..20c49b16b759 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1533,8 +1533,6 @@ static int cleaner_kthread(void *arg) struct btrfs_root *root = arg; do { - vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); - if (!(root->fs_info->sb->s_flags & MS_RDONLY) && mutex_trylock(&root->fs_info->cleaner_mutex)) { btrfs_run_delayed_iputs(root); @@ -1566,7 +1564,6 @@ static int transaction_kthread(void *arg) do { cannot_commit = false; delay = HZ * 30; - vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); mutex_lock(&root->fs_info->transaction_kthread_mutex); spin_lock(&root->fs_info->trans_lock); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 9aa01ec2138d..5caf285c6e4d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1379,7 +1379,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, ssize_t err = 0; size_t count, ocount; - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + sb_start_write(inode->i_sb); mutex_lock(&inode->i_mutex); @@ -1469,6 +1469,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, num_written = err; } out: + sb_end_write(inode->i_sb); current->backing_dev_info = NULL; return num_written ? num_written : err; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fb8d671d00e6..f4d901786b3c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6620,6 +6620,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) u64 page_start; u64 page_end; + sb_start_pagefault(inode->i_sb); ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); if (!ret) { ret = file_update_time(vma->vm_file); @@ -6709,12 +6710,15 @@ again: unlock_extent_cached(io_tree, page_start, page_end, &cached_state, GFP_NOFS); out_unlock: - if (!ret) + if (!ret) { + sb_end_pagefault(inode->i_sb); return VM_FAULT_LOCKED; + } unlock_page(page); out: btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); out_noreserve: + sb_end_pagefault(inode->i_sb); return ret; } diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b72b068183ec..fa67ba51516e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -329,6 +329,8 @@ again: if (!h) return ERR_PTR(-ENOMEM); + sb_start_intwrite(root->fs_info->sb); + if (may_wait_transaction(root, type)) wait_current_trans(root); @@ -339,6 +341,7 @@ again: } while (ret == -EBUSY); if (ret < 0) { + sb_end_intwrite(root->fs_info->sb); kmem_cache_free(btrfs_trans_handle_cachep, h); return ERR_PTR(ret); } @@ -528,6 +531,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, count++; } + sb_end_intwrite(root->fs_info->sb); + if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && should_end_transaction(trans, root)) { trans->transaction->blocked = 1; @@ -1517,6 +1522,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, put_transaction(cur_trans); put_transaction(cur_trans); + sb_end_intwrite(root->fs_info->sb); + trace_btrfs_transaction_commit(root); btrfs_scrub_continue(root); -- GitLab From 1e8b212fe5dcee9d3dbb152d235f3c33458fb26e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:46 +0200 Subject: [PATCH 4791/5711] ext2: Implement freezing The only missing piece to make freezing work reliably with ext2 is to stop iput() of unlinked inode from deleting the inode on frozen filesystem. So add a necessary protection to ext2_evict_inode(). We also provide appropriate ->freeze_fs and ->unfreeze_fs functions. Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/ext2/inode.c | 5 ++++- fs/ext2/super.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 264d315f6c47..6363ac66fafa 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -79,6 +79,7 @@ void ext2_evict_inode(struct inode * inode) truncate_inode_pages(&inode->i_data, 0); if (want_delete) { + sb_start_intwrite(inode->i_sb); /* set dtime */ EXT2_I(inode)->i_dtime = get_seconds(); mark_inode_dirty(inode); @@ -98,8 +99,10 @@ void ext2_evict_inode(struct inode * inode) if (unlikely(rsv)) kfree(rsv); - if (want_delete) + if (want_delete) { ext2_free_inode(inode); + sb_end_intwrite(inode->i_sb); + } } typedef struct { diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 5df3d2d8169c..15761e638dae 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -42,6 +42,8 @@ static void ext2_sync_super(struct super_block *sb, static int ext2_remount (struct super_block * sb, int * flags, char * data); static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); static int ext2_sync_fs(struct super_block *sb, int wait); +static int ext2_freeze(struct super_block *sb); +static int ext2_unfreeze(struct super_block *sb); void ext2_error(struct super_block *sb, const char *function, const char *fmt, ...) @@ -305,6 +307,8 @@ static const struct super_operations ext2_sops = { .evict_inode = ext2_evict_inode, .put_super = ext2_put_super, .sync_fs = ext2_sync_fs, + .freeze_fs = ext2_freeze, + .unfreeze_fs = ext2_unfreeze, .statfs = ext2_statfs, .remount_fs = ext2_remount, .show_options = ext2_show_options, @@ -1200,6 +1204,35 @@ static int ext2_sync_fs(struct super_block *sb, int wait) return 0; } +static int ext2_freeze(struct super_block *sb) +{ + struct ext2_sb_info *sbi = EXT2_SB(sb); + + /* + * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared + * because we have unattached inodes and thus filesystem is not fully + * consistent. + */ + if (atomic_long_read(&sb->s_remove_count)) { + ext2_sync_fs(sb, 1); + return 0; + } + /* Set EXT2_FS_VALID flag */ + spin_lock(&sbi->s_lock); + sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state); + spin_unlock(&sbi->s_lock); + ext2_sync_super(sb, sbi->s_es, 1); + + return 0; +} + +static int ext2_unfreeze(struct super_block *sb) +{ + /* Just write sb to clear EXT2_VALID_FS flag */ + ext2_write_super(sb); + + return 0; +} void ext2_write_super(struct super_block *sb) { -- GitLab From d9c95bdd53a8d9116d269c91ce3d151472e6bcd6 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jun 2012 16:20:47 +0200 Subject: [PATCH 4792/5711] fs: Remove old freezing mechanism Now that all users are converted, we can remove functions, variables, and constants defined by the old freezing mechanism. BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa Tested-by: Peter M. Petrakis Tested-by: Dann Frazier Tested-by: Massimo Morana Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/super.c | 1 - include/linux/fs.h | 5 ----- 2 files changed, 6 deletions(-) diff --git a/fs/super.c b/fs/super.c index 0f64ecb7b1bf..a87dc1b1ac92 100644 --- a/fs/super.c +++ b/fs/super.c @@ -217,7 +217,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) mutex_init(&s->s_dquot.dqio_mutex); mutex_init(&s->s_dquot.dqonoff_mutex); init_rwsem(&s->s_dquot.dqptr_sem); - init_waitqueue_head(&s->s_wait_unfrozen); s->s_maxbytes = MAX_NON_LFS; s->s_op = &default_op; s->s_time_gran = 1000000000; diff --git a/include/linux/fs.h b/include/linux/fs.h index aefed9426b03..0f4b79be8717 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1459,7 +1459,6 @@ extern spinlock_t sb_lock; enum { SB_UNFROZEN = 0, /* FS is unfrozen */ SB_FREEZE_WRITE = 1, /* Writes, dir ops, ioctls frozen */ - SB_FREEZE_TRANS = 2, SB_FREEZE_PAGEFAULT = 2, /* Page faults stopped as well */ SB_FREEZE_FS = 3, /* For internal FS use (e.g. to stop * internal threads if needed) */ @@ -1528,8 +1527,6 @@ struct super_block { struct hlist_node s_instances; struct quota_info s_dquot; /* Diskquota specific options */ - int s_frozen; - wait_queue_head_t s_wait_unfrozen; struct sb_writers s_writers; char s_id[32]; /* Informational name */ @@ -1585,8 +1582,6 @@ extern struct timespec current_fs_time(struct super_block *sb); /* * Snapshotting support. */ -/* Will go away when all users are converted */ -#define vfs_check_frozen(sb, level) do { } while (0) void __sb_end_write(struct super_block *sb, int level); int __sb_start_write(struct super_block *sb, int level, bool wait); -- GitLab From 06fd516c1a504828780fcd81dfe21f94dec4c868 Mon Sep 17 00:00:00 2001 From: Valerie Aurora Date: Tue, 12 Jun 2012 16:20:48 +0200 Subject: [PATCH 4793/5711] Documentation: Correct s_umount state for freeze_fs/unfreeze_fs freeze_fs/unfreeze_fs ops are called with s_umount held for write, not read. Signed-off-by: Valerie Aurora Signed-off-by: Kamal Mostafa Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Al Viro --- Documentation/filesystems/Locking | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index e0cce2a5f820..f566b477e81f 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -138,8 +138,8 @@ evict_inode: put_super: write write_super: read sync_fs: read -freeze_fs: read -unfreeze_fs: read +freeze_fs: write +unfreeze_fs: write statfs: maybe(read) (see below) remount_fs: write umount_begin: no -- GitLab From 01ff5dbc0925d11c8ad76eed3bdd02d0c7e1e0f5 Mon Sep 17 00:00:00 2001 From: Chetan Loke Date: Tue, 31 Jul 2012 08:47:13 +0200 Subject: [PATCH 4794/5711] block/nbd: micro-optimization in nbd request completion Add in-flight cmds to the tail. That way while searching (during request completion),we will always get a hit on the first element. Signed-off-by: Chetan Loke Acked-by: Paul.Clements@steeleye.com Signed-off-by: Jens Axboe --- drivers/block/nbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 061427a75d37..8957b9f0cfad 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -481,7 +481,7 @@ static void nbd_handle_req(struct nbd_device *nbd, struct request *req) nbd_end_request(req); } else { spin_lock(&nbd->queue_lock); - list_add(&req->queuelist, &nbd->queue_head); + list_add_tail(&req->queuelist, &nbd->queue_head); spin_unlock(&nbd->queue_lock); } -- GitLab From 0021b7bc045e4b0b85d8c53614342aaf84ca96a5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 09:08:14 +0200 Subject: [PATCH 4795/5711] md: remove plug_cnt feature of plugging. This seemed like a good idea at the time, but after further thought I cannot see it making a difference other than very occasionally and testing to try to exercise the case it is most likely to help did not show any performance difference by removing it. So remove the counting of active plugs and allow 'pending writes' to be activated at any time, not just when no plugs are active. This is only relevant when there is a write-intent bitmap, and the updating of the bitmap will likely introduce enough delay that the single-threading of bitmap updates will be enough to collect large numbers of updates together. Removing this will make it easier to centralise the unplug code, and will clear the other for other unplug enhancements which have a measurable effect. Signed-off-by: NeilBrown Signed-off-by: Jens Axboe --- drivers/md/md.c | 5 +---- drivers/md/md.h | 3 --- drivers/md/raid1.c | 3 +-- drivers/md/raid10.c | 3 +-- drivers/md/raid5.c | 5 ++--- 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d5ab4493c8be..34381172a947 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -514,8 +514,7 @@ struct md_plug_cb { static void plugger_unplug(struct blk_plug_cb *cb) { struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb); - if (atomic_dec_and_test(&mdcb->mddev->plug_cnt)) - md_wakeup_thread(mdcb->mddev->thread); + md_wakeup_thread(mdcb->mddev->thread); kfree(mdcb); } @@ -548,7 +547,6 @@ int mddev_check_plugged(struct mddev *mddev) mdcb->mddev = mddev; mdcb->cb.callback = plugger_unplug; - atomic_inc(&mddev->plug_cnt); list_add(&mdcb->cb.list, &plug->cb_list); return 1; } @@ -602,7 +600,6 @@ void mddev_init(struct mddev *mddev) atomic_set(&mddev->active, 1); atomic_set(&mddev->openers, 0); atomic_set(&mddev->active_io, 0); - atomic_set(&mddev->plug_cnt, 0); spin_lock_init(&mddev->write_lock); atomic_set(&mddev->flush_pending, 0); init_waitqueue_head(&mddev->sb_wait); diff --git a/drivers/md/md.h b/drivers/md/md.h index 7b4a3c318cae..91786c46b85c 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -266,9 +266,6 @@ struct mddev { int new_chunk_sectors; int reshape_backwards; - atomic_t plug_cnt; /* If device is expecting - * more bios soon. - */ struct md_thread *thread; /* management thread */ struct md_thread *sync_thread; /* doing resync or reconstruct */ sector_t curr_resync; /* last block scheduled */ diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index cacd008d6864..36a8fc059ac3 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2173,8 +2173,7 @@ static void raid1d(struct mddev *mddev) blk_start_plug(&plug); for (;;) { - if (atomic_read(&mddev->plug_cnt) == 0) - flush_pending_writes(conf); + flush_pending_writes(conf); spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) { diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8da6282254c3..5d33603a497d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2660,8 +2660,7 @@ static void raid10d(struct mddev *mddev) blk_start_plug(&plug); for (;;) { - if (atomic_read(&mddev->plug_cnt) == 0) - flush_pending_writes(conf); + flush_pending_writes(conf); spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 04348d76bb30..bde9da2baa39 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4543,7 +4543,7 @@ static void raid5d(struct mddev *mddev) while (1) { struct bio *bio; - if (atomic_read(&mddev->plug_cnt) == 0 && + if ( !list_empty(&conf->bitmap_list)) { /* Now is a good time to flush some bitmap updates */ conf->seq_flush++; @@ -4553,8 +4553,7 @@ static void raid5d(struct mddev *mddev) conf->seq_write = conf->seq_flush; activate_bit_delay(conf); } - if (atomic_read(&mddev->plug_cnt) == 0) - raid5_activate_delayed(conf); + raid5_activate_delayed(conf); while ((bio = remove_bio_from_retry(conf))) { int ok; -- GitLab From 9cbb17508808f8a6bdd83354b61e126ac4fa6fed Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 09:08:14 +0200 Subject: [PATCH 4796/5711] blk: centralize non-request unplug handling. Both md and umem has similar code for getting notified on an blk_finish_plug event. Centralize this code in block/ and allow each driver to provide its distinctive difference. Signed-off-by: NeilBrown Signed-off-by: Jens Axboe --- block/blk-core.c | 25 +++++++++++++++++++ drivers/block/umem.c | 35 +++++--------------------- drivers/md/md.c | 56 ++++-------------------------------------- drivers/md/md.h | 8 +++++- include/linux/blkdev.h | 8 ++++-- 5 files changed, 49 insertions(+), 83 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index dd134d834d58..177ddcf356e6 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2927,6 +2927,31 @@ static void flush_plug_callbacks(struct blk_plug *plug) } } +struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, void *data, + int size) +{ + struct blk_plug *plug = current->plug; + struct blk_plug_cb *cb; + + if (!plug) + return NULL; + + list_for_each_entry(cb, &plug->cb_list, list) + if (cb->callback == unplug && cb->data == data) + return cb; + + /* Not currently on the callback list */ + BUG_ON(size < sizeof(*cb)); + cb = kzalloc(size, GFP_ATOMIC); + if (cb) { + cb->data = data; + cb->callback = unplug; + list_add(&cb->list, &plug->cb_list); + } + return cb; +} +EXPORT_SYMBOL(blk_check_plugged); + void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) { struct request_queue *q; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 9a72277a31df..6ef3489568e3 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -513,42 +513,19 @@ static void process_page(unsigned long data) } } -struct mm_plug_cb { - struct blk_plug_cb cb; - struct cardinfo *card; -}; - static void mm_unplug(struct blk_plug_cb *cb) { - struct mm_plug_cb *mmcb = container_of(cb, struct mm_plug_cb, cb); + struct cardinfo *card = cb->data; - spin_lock_irq(&mmcb->card->lock); - activate(mmcb->card); - spin_unlock_irq(&mmcb->card->lock); - kfree(mmcb); + spin_lock_irq(&card->lock); + activate(card); + spin_unlock_irq(&card->lock); + kfree(cb); } static int mm_check_plugged(struct cardinfo *card) { - struct blk_plug *plug = current->plug; - struct mm_plug_cb *mmcb; - - if (!plug) - return 0; - - list_for_each_entry(mmcb, &plug->cb_list, cb.list) { - if (mmcb->cb.callback == mm_unplug && mmcb->card == card) - return 1; - } - /* Not currently on the callback list */ - mmcb = kmalloc(sizeof(*mmcb), GFP_ATOMIC); - if (!mmcb) - return 0; - - mmcb->card = card; - mmcb->cb.callback = mm_unplug; - list_add(&mmcb->cb.list, &plug->cb_list); - return 1; + return !!blk_check_plugged(mm_unplug, card, sizeof(struct blk_plug_cb)); } static void mm_make_request(struct request_queue *q, struct bio *bio) diff --git a/drivers/md/md.c b/drivers/md/md.c index 34381172a947..b493fa417387 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -498,59 +498,13 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) } EXPORT_SYMBOL(md_flush_request); -/* Support for plugging. - * This mirrors the plugging support in request_queue, but does not - * require having a whole queue or request structures. - * We allocate an md_plug_cb for each md device and each thread it gets - * plugged on. This links tot the private plug_handle structure in the - * personality data where we keep a count of the number of outstanding - * plugs so other code can see if a plug is active. - */ -struct md_plug_cb { - struct blk_plug_cb cb; - struct mddev *mddev; -}; - -static void plugger_unplug(struct blk_plug_cb *cb) +void md_unplug(struct blk_plug_cb *cb) { - struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb); - md_wakeup_thread(mdcb->mddev->thread); - kfree(mdcb); -} - -/* Check that an unplug wakeup will come shortly. - * If not, wakeup the md thread immediately - */ -int mddev_check_plugged(struct mddev *mddev) -{ - struct blk_plug *plug = current->plug; - struct md_plug_cb *mdcb; - - if (!plug) - return 0; - - list_for_each_entry(mdcb, &plug->cb_list, cb.list) { - if (mdcb->cb.callback == plugger_unplug && - mdcb->mddev == mddev) { - /* Already on the list, move to top */ - if (mdcb != list_first_entry(&plug->cb_list, - struct md_plug_cb, - cb.list)) - list_move(&mdcb->cb.list, &plug->cb_list); - return 1; - } - } - /* Not currently on the callback list */ - mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC); - if (!mdcb) - return 0; - - mdcb->mddev = mddev; - mdcb->cb.callback = plugger_unplug; - list_add(&mdcb->cb.list, &plug->cb_list); - return 1; + struct mddev *mddev = cb->data; + md_wakeup_thread(mddev->thread); + kfree(cb); } -EXPORT_SYMBOL_GPL(mddev_check_plugged); +EXPORT_SYMBOL(md_unplug); static inline struct mddev *mddev_get(struct mddev *mddev) { diff --git a/drivers/md/md.h b/drivers/md/md.h index 91786c46b85c..8f998e08fb87 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -627,6 +627,12 @@ extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask, struct mddev *mddev); extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, struct mddev *mddev); -extern int mddev_check_plugged(struct mddev *mddev); extern void md_trim_bio(struct bio *bio, int offset, int size); + +extern void md_unplug(struct blk_plug_cb *cb); +static inline int mddev_check_plugged(struct mddev *mddev) +{ + return !!blk_check_plugged(md_unplug, mddev, + sizeof(struct blk_plug_cb)); +} #endif /* _MD_MD_H */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3816ce8a08fc..607ca228f47e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -922,11 +922,15 @@ struct blk_plug { }; #define BLK_MAX_REQUEST_COUNT 16 +struct blk_plug_cb; +typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *); struct blk_plug_cb { struct list_head list; - void (*callback)(struct blk_plug_cb *); + blk_plug_cb_fn callback; + void *data; }; - +extern struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, + void *data, int size); extern void blk_start_plug(struct blk_plug *); extern void blk_finish_plug(struct blk_plug *); extern void blk_flush_plug_list(struct blk_plug *, bool); -- GitLab From 2a7d5559b346574057dce4672d1ed9aaa9d1e685 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Jul 2012 09:08:15 +0200 Subject: [PATCH 4797/5711] block: stack unplug MD raid1 prepares to dispatch request in unplug callback. If make_request in low level queue also uses unplug callback to dispatch request, the low level queue's unplug callback will not be called. Recheck the callback list helps this case. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown Signed-off-by: Jens Axboe --- block/blk-core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 177ddcf356e6..35bf4fe8234c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2913,17 +2913,16 @@ static void flush_plug_callbacks(struct blk_plug *plug) { LIST_HEAD(callbacks); - if (list_empty(&plug->cb_list)) - return; - - list_splice_init(&plug->cb_list, &callbacks); + while (!list_empty(&plug->cb_list)) { + list_splice_init(&plug->cb_list, &callbacks); - while (!list_empty(&callbacks)) { - struct blk_plug_cb *cb = list_first_entry(&callbacks, + while (!list_empty(&callbacks)) { + struct blk_plug_cb *cb = list_first_entry(&callbacks, struct blk_plug_cb, list); - list_del(&cb->list); - cb->callback(cb); + list_del(&cb->list); + cb->callback(cb); + } } } -- GitLab From 74018dc3063a2c729fc73041c0a9f03aac995920 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 09:08:15 +0200 Subject: [PATCH 4798/5711] blk: pass from_schedule to non-request unplug functions. This will allow md/raid to know why the unplug was called, and will be able to act according - if !from_schedule it is safe to perform tasks which could themselves schedule. Signed-off-by: NeilBrown Signed-off-by: Jens Axboe --- block/blk-core.c | 6 +++--- drivers/block/umem.c | 2 +- drivers/md/md.c | 2 +- drivers/md/md.h | 2 +- include/linux/blkdev.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 35bf4fe8234c..4b4dbdfbca89 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2909,7 +2909,7 @@ static void queue_unplugged(struct request_queue *q, unsigned int depth, } -static void flush_plug_callbacks(struct blk_plug *plug) +static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule) { LIST_HEAD(callbacks); @@ -2921,7 +2921,7 @@ static void flush_plug_callbacks(struct blk_plug *plug) struct blk_plug_cb, list); list_del(&cb->list); - cb->callback(cb); + cb->callback(cb, from_schedule); } } } @@ -2961,7 +2961,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) BUG_ON(plug->magic != PLUG_MAGIC); - flush_plug_callbacks(plug); + flush_plug_callbacks(plug, from_schedule); if (list_empty(&plug->list)) return; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 6ef3489568e3..eb0d8216f557 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -513,7 +513,7 @@ static void process_page(unsigned long data) } } -static void mm_unplug(struct blk_plug_cb *cb) +static void mm_unplug(struct blk_plug_cb *cb, bool from_schedule) { struct cardinfo *card = cb->data; diff --git a/drivers/md/md.c b/drivers/md/md.c index b493fa417387..db02d2efb76f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -498,7 +498,7 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) } EXPORT_SYMBOL(md_flush_request); -void md_unplug(struct blk_plug_cb *cb) +void md_unplug(struct blk_plug_cb *cb, bool from_schedule) { struct mddev *mddev = cb->data; md_wakeup_thread(mddev->thread); diff --git a/drivers/md/md.h b/drivers/md/md.h index 8f998e08fb87..f385b038589d 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -629,7 +629,7 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, struct mddev *mddev); extern void md_trim_bio(struct bio *bio, int offset, int size); -extern void md_unplug(struct blk_plug_cb *cb); +extern void md_unplug(struct blk_plug_cb *cb, bool from_schedule); static inline int mddev_check_plugged(struct mddev *mddev) { return !!blk_check_plugged(md_unplug, mddev, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 607ca228f47e..4e72a9d48232 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -923,7 +923,7 @@ struct blk_plug { #define BLK_MAX_REQUEST_COUNT 16 struct blk_plug_cb; -typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *); +typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *, bool); struct blk_plug_cb { struct list_head list; blk_plug_cb_fn callback; -- GitLab From ff8a1e274cbc11da6b57849f925b895a212b56c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 31 Jul 2012 10:16:59 +0200 Subject: [PATCH 4799/5711] ALSA: hda - Fix polarity of mute LED on HP Mini 210 The commit a3e199732b made the LED working again on HP Mini 210 but with a wrong polarity. This patch fixes the polarity for this machine, and also introduce a new model string "hp-inv-led". Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=772923 Cc: [v3.3+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 217ee1f344b8..a760c30f1caa 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -102,6 +102,7 @@ enum { STAC_HP_DV7_4000, STAC_HP_ZEPHYR, STAC_92HD83XXX_HP_LED, + STAC_92HD83XXX_HP_INV_LED, STAC_92HD83XXX_MODELS }; @@ -1677,6 +1678,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_HP_DV7_4000] = "hp-dv7-4000", [STAC_HP_ZEPHYR] = "hp-zephyr", [STAC_92HD83XXX_HP_LED] = "hp-led", + [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -5561,6 +5563,9 @@ again: spec->init = stac92hd83xxx_hp_zephyr_init; break; case STAC_92HD83XXX_HP_LED: + default_polarity = 0; + break; + case STAC_92HD83XXX_HP_INV_LED: default_polarity = 1; break; } -- GitLab From c9dbc4802b413e2d0b08fc483cbf5db7f8e2f360 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 31 Jul 2012 10:26:34 +0200 Subject: [PATCH 4800/5711] ALSA: hda - Add descriptions for missing IDT 92HD83x models Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 0a2cdac96c28..a92bba816843 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -274,6 +274,10 @@ STAC92HD83* dell-s14 Dell laptop dell-vostro-3500 Dell Vostro 3500 laptop hp-dv7-4000 HP dv-7 4000 + hp_cNB11_intquad HP CNB models with 4 speakers + hp-zephyr HP Zephyr + hp-led HP with broken BIOS for mute LED + hp-inv-led HP with broken BIOS for inverted mute LED auto BIOS setup (default) STAC9872 -- GitLab From 1f43f6c1bc8d740e75b4177eb29110858bb5fea2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 31 Jul 2012 10:40:05 +0200 Subject: [PATCH 4801/5711] ALSA: hda - Fix mute-LED GPIO initialization for IDT codecs The IDT codecs initializes the GPIO setup for mute LEDs via snd_hda_sync_vmaster_hook(). This works in most cases except for the very first call, which is called before PCM and control creations. Thus before Master switch is set manually via alsactl, the mute LED may show the wrong state, depending on the polarity. Now it's fixed by calling the LED-status update function manually when no vmaster is set yet. Cc: [v3.4+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a760c30f1caa..94040ccf8e8f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4420,7 +4420,12 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_jack_report_sync(codec); /* sync mute LED */ - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + if (spec->gpio_led) { + if (spec->vmaster_mute.hook) + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + else /* the very first init call doesn't have vmaster yet */ + stac92xx_update_led_status(codec, false); + } /* sync the power-map */ if (spec->num_pwrs) -- GitLab From 98bd8b96b26db3399a48202318dca4aaa2515355 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 13 Jul 2012 08:19:34 +0100 Subject: [PATCH 4802/5711] ARM: 7466/1: disable interrupt before spinning endlessly The CPU will endlessly spin at the end of machine_halt and machine_restart calls. However, this will lead to a soft lockup warning after about 20 seconds, if CONFIG_LOCKUP_DETECTOR is enabled, as system timer is still alive. Disable interrupt before going to spin endlessly, so that the lockup warning will never be seen. Cc: Reported-by: Marek Vasut Signed-off-by: Shawn Guo Signed-off-by: Russell King --- arch/arm/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 19c95ea65b2f..693b744fd572 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -247,6 +247,7 @@ void machine_shutdown(void) void machine_halt(void) { machine_shutdown(); + local_irq_disable(); while (1); } @@ -268,6 +269,7 @@ void machine_restart(char *cmd) /* Whoops - the platform was unable to reboot. Tell the user! */ printk("Reboot failed -- System halted\n"); + local_irq_disable(); while (1); } -- GitLab From a76d7bd96d65fa5119adba97e1b58d95f2e78829 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 13 Jul 2012 19:15:40 +0100 Subject: [PATCH 4803/5711] ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+ The open-coded mutex implementation for ARMv6+ cores suffers from a severe lack of barriers, so in the uncontended case we don't actually protect any accesses performed during the critical section. Furthermore, the code is largely a duplication of the ARMv6+ atomic_dec code but optimised to remove a branch instruction, as the mutex fastpath was previously inlined. Now that this is executed out-of-line, we can reuse the atomic access code for the locking (in fact, we use the xchg code as this produces shorter critical sections). This patch uses the generic xchg based implementation for mutexes on ARMv6+, which introduces barriers to the lock/unlock operations and also has the benefit of removing a fair amount of inline assembly code. Cc: Acked-by: Arnd Bergmann Acked-by: Nicolas Pitre Reported-by: Shan Kang Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/mutex.h | 119 ++--------------------------------- 1 file changed, 4 insertions(+), 115 deletions(-) diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h index 93226cf23ae0..b1479fd04a95 100644 --- a/arch/arm/include/asm/mutex.h +++ b/arch/arm/include/asm/mutex.h @@ -7,121 +7,10 @@ */ #ifndef _ASM_MUTEX_H #define _ASM_MUTEX_H - -#if __LINUX_ARM_ARCH__ < 6 -/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */ -# include -#else - /* - * Attempting to lock a mutex on ARMv6+ can be done with a bastardized - * atomic decrement (it is not a reliable atomic decrement but it satisfies - * the defined semantics for our purpose, while being smaller and faster - * than a real atomic decrement or atomic swap. The idea is to attempt - * decrementing the lock value only once. If once decremented it isn't zero, - * or if its store-back fails due to a dispute on the exclusive store, we - * simply bail out immediately through the slow path where the lock will be - * reattempted until it succeeds. + * On pre-ARMv6 hardware this results in a swp-based implementation, + * which is the most efficient. For ARMv6+, we emit a pair of exclusive + * accesses instead. */ -static inline void -__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res; - - __asm__ ( - - "ldrex %0, [%2] \n\t" - "sub %0, %0, #1 \n\t" - "strex %1, %0, [%2] " - - : "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __res |= __ex_flag; - if (unlikely(__res != 0)) - fail_fn(count); -} - -static inline int -__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res; - - __asm__ ( - - "ldrex %0, [%2] \n\t" - "sub %0, %0, #1 \n\t" - "strex %1, %0, [%2] " - - : "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __res |= __ex_flag; - if (unlikely(__res != 0)) - __res = fail_fn(count); - return __res; -} - -/* - * Same trick is used for the unlock fast path. However the original value, - * rather than the result, is used to test for success in order to have - * better generated assembly. - */ -static inline void -__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res, __orig; - - __asm__ ( - - "ldrex %0, [%3] \n\t" - "add %1, %0, #1 \n\t" - "strex %2, %1, [%3] " - - : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __orig |= __ex_flag; - if (unlikely(__orig != 0)) - fail_fn(count); -} - -/* - * If the unlock was done on a contended lock, or if the unlock simply fails - * then the mutex remains locked. - */ -#define __mutex_slowpath_needs_to_unlock() 1 - -/* - * For __mutex_fastpath_trylock we use another construct which could be - * described as a "single value cmpxchg". - * - * This provides the needed trylock semantics like cmpxchg would, but it is - * lighter and less generic than a true cmpxchg implementation. - */ -static inline int -__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res, __orig; - - __asm__ ( - - "1: ldrex %0, [%3] \n\t" - "subs %1, %0, #1 \n\t" - "strexeq %2, %1, [%3] \n\t" - "movlt %0, #0 \n\t" - "cmpeq %2, #0 \n\t" - "bgt 1b " - - : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) - : "r" (&count->counter) - : "cc", "memory" ); - - return __orig; -} - -#endif +#include #endif -- GitLab From 4c36595ec87115f2f876f7d4fdec8ca284a42b9c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 18 Jul 2012 19:15:25 +0100 Subject: [PATCH 4804/5711] ARM: 7468/1: ftrace: Trace function entry before updating index Commit 722b3c74695377d11d18a52f3da08114d37f3f37 modified x86 ftrace to avoid tracing all functions called from irqs when function graph was used with a filter. Port the same fix to ARM. Acked-by: Steven Rostedt Signed-off-by: Colin Cross Signed-off-by: Russell King --- arch/arm/kernel/ftrace.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index df0bf0c8cb79..34e56647dcee 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -179,19 +179,20 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, old = *parent; *parent = return_hooker; - err = ftrace_push_return_trace(old, self_addr, &trace.depth, - frame_pointer); - if (err == -EBUSY) { - *parent = old; - return; - } - trace.func = self_addr; + trace.depth = current->curr_ret_stack + 1; /* Only trace if the calling function expects to */ if (!ftrace_graph_entry(&trace)) { - current->curr_ret_stack--; *parent = old; + return; + } + + err = ftrace_push_return_trace(old, self_addr, &trace.depth, + frame_pointer); + if (err == -EBUSY) { + *parent = old; + return; } } -- GitLab From a84b895a2348f0dbff31b71ddf954f70a6cde368 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 20 Jul 2012 02:03:43 +0100 Subject: [PATCH 4805/5711] ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend vfp_pm_suspend runs on each cpu, only clear the hardware state pointer for the current cpu. Prevents a possible crash if one cpu clears the hw state pointer when another cpu has already checked if it is valid. Cc: stable@vger.kernel.org Signed-off-by: Colin Cross Signed-off-by: Russell King --- arch/arm/vfp/vfpmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 586961929e96..9428006728f2 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -460,7 +460,7 @@ static int vfp_pm_suspend(void) } /* clear any information we had about last context state */ - memset(vfp_current_hw_state, 0, sizeof(vfp_current_hw_state)); + vfp_current_hw_state[ti->cpu] = NULL; return 0; } -- GitLab From 24b35521b8ddf088531258f06f681bb7b227bf47 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 20 Jul 2012 02:03:42 +0100 Subject: [PATCH 4806/5711] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP vfp_pm_suspend should save the VFP state in suspend after any lazy context switch. If it only saves when the VFP is enabled, the state can get lost when, on a UP system: Thread 1 uses the VFP Context switch occurs to thread 2, VFP is disabled but the VFP context is not saved Thread 2 initiates suspend vfp_pm_suspend is called with the VFP disabled, and the unsaved VFP context of Thread 1 in the registers Modify vfp_pm_suspend to save the VFP context whenever vfp_current_hw_state is not NULL. Includes a fix from Ido Yariv , who pointed out that on SMP systems, the state pointer can be pointing to a freed task struct if a task exited on another cpu, fixed by using #ifndef CONFIG_SMP in the new if clause. Cc: Barry Song Cc: Catalin Marinas Cc: Ido Yariv Cc: Daniel Drake Cc: Will Deacon Cc: stable@vger.kernel.org Signed-off-by: Colin Cross Signed-off-by: Russell King --- arch/arm/vfp/vfpmodule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 9428006728f2..fb849d044bde 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -457,6 +457,12 @@ static int vfp_pm_suspend(void) /* disable, just in case */ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP + fmxr(FPEXC, fpexc | FPEXC_EN); + vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); + fmxr(FPEXC, fpexc); +#endif } /* clear any information we had about last context state */ -- GitLab From 5a783cbc48367cfc7b65afc75430953dfe60098f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 20 Jul 2012 18:24:55 +0100 Subject: [PATCH 4807/5711] ARM: 7478/1: errata: extend workaround for erratum #720789 Commit cdf357f1 ("ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID") replaced by-ASID TLB flushing operations with all-ASID variants to workaround A9 erratum #720789. This patch extends the workaround to include the tlb_range operations, which were overlooked by the original patch. Cc: Tested-by: Steve Capper Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/tlb-v7.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index 845f461f8ec1..c2021139cb56 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -38,11 +38,19 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT +#ifdef CONFIG_ARM_ERRATA_720789 + mov r3, #0 +#else asid r3, r3 @ mask ASID +#endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ @@ -67,7 +75,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) mov r0, r0, lsl #PAGE_SHIFT mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ cmp r0, r1 -- GitLab From c5dff4ffd327088d85035bec535b7d0c9ea03151 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sat, 28 Jul 2012 15:19:55 +0100 Subject: [PATCH 4808/5711] ARM: 7480/1: only call smp_send_stop() on SMP On reboot or poweroff (machine_shutdown()) a call to smp_send_stop() is made (to stop the others CPU's) when CONFIG_SMP=y. arch/arm/kernel/process.c: void machine_shutdown(void) { #ifdef CONFIG_SMP smp_send_stop(); #endif } smp_send_stop() calls the function pointer smp_cross_call(), which is set on the smp_init_cpus() function for OMAP processors. arch/arm/mach-omap2/omap-smp.c: void __init smp_init_cpus(void) { ... set_smp_cross_call(gic_raise_softirq); ... } But the ARM setup_arch() function only calls smp_init_cpus() if CONFIG_SMP=y && is_smp(). arm/kernel/setup.c: void __init setup_arch(char **cmdline_p) { ... #ifdef CONFIG_SMP if (is_smp()) smp_init_cpus(); #endif ... } Newer OMAP CPU's are SMP machines so omap2plus_defconfig sets CONFIG_SMP=y. Unfortunately on an OMAP UP machine is_smp() returns false and smp_init_cpus() is never called and the smp_cross_call() function remains NULL. If the machine is rebooted or powered off, smp_send_stop() will be called (since CONFIG_SMP=y) leading to the following error: [ 42.815551] Restarting system. [ 42.819030] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 42.827667] pgd = d7a74000 [ 42.830566] [00000000] *pgd=96ce7831, *pte=00000000, *ppte=00000000 [ 42.837249] Internal error: Oops: 80000007 [#1] SMP ARM [ 42.842773] Modules linked in: [ 42.846008] CPU: 0 Not tainted (3.5.0-rc3-next-20120622-00002-g62e87ba-dirty #44) [ 42.854278] PC is at 0x0 [ 42.856994] LR is at smp_send_stop+0x4c/0xe4 [ 42.861511] pc : [<00000000>] lr : [] psr: 60000013 [ 42.861511] sp : d6c85e70 ip : 00000000 fp : 00000000 [ 42.873626] r10: 00000000 r9 : d6c84000 r8 : 00000002 [ 42.879150] r7 : c07235a0 r6 : c06dd2d0 r5 : 000f4241 r4 : d6c85e74 [ 42.886047] r3 : 00000000 r2 : 00000000 r1 : 00000006 r0 : d6c85e74 [ 42.892944] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 42.900482] Control: 10c5387d Table: 97a74019 DAC: 00000015 [ 42.906555] Process reboot (pid: 1166, stack limit = 0xd6c842f8) [ 42.912902] Stack: (0xd6c85e70 to 0xd6c86000) [ 42.917510] 5e60: c07235a0 00000000 00000000 d6c84000 [ 42.926177] 5e80: 01234567 c00143d0 4321fedc c00511bc d6c85ebc 00000168 00000460 00000000 [ 42.934814] 5ea0: c1017950 a0000013 c1017900 d8014390 d7ec3858 c0498e48 c1017950 00000000 [ 42.943481] 5ec0: d6ddde10 d6c85f78 00000003 00000000 d6ddde10 d6c84000 00000000 00000000 [ 42.952117] 5ee0: 00000002 00000000 00000000 c0088c88 00000002 00000000 00000000 c00f4b90 [ 42.960784] 5f00: 00000000 d6c85ebc d8014390 d7e311c8 60000013 00000103 00000002 d6c84000 [ 42.969421] 5f20: c00f3274 d6e00a00 00000001 60000013 d6c84000 00000000 00000000 c00895d4 [ 42.978057] 5f40: 00000002 d8007c80 d781f000 c00f6150 d8010cc0 c00f3274 d781f000 d6c84000 [ 42.986694] 5f60: c0013020 d6e00a00 00000001 20000010 0001257c ef000000 00000000 c00895d4 [ 42.995361] 5f80: 00000002 00000001 00000003 00000000 00000001 00000003 00000000 00000058 [ 43.003997] 5fa0: c00130c8 c0012f00 00000001 00000003 fee1dead 28121969 01234567 00000002 [ 43.012634] 5fc0: 00000001 00000003 00000000 00000058 00012584 0001257c 00000001 00000000 [ 43.021270] 5fe0: 000124bc bec5cc6c 00008f9c 4a2f7c40 20000010 fee1dead 00000000 00000000 [ 43.029968] [] (smp_send_stop+0x4c/0xe4) from [] (machine_restart+0xc/0x4c) [ 43.039154] [] (machine_restart+0xc/0x4c) from [] (sys_reboot+0x144/0x1f0) [ 43.048278] [] (sys_reboot+0x144/0x1f0) from [] (ret_fast_syscall+0x0/0x3c) [ 43.057464] Code: bad PC value [ 43.060760] ---[ end trace c3988d1dd0b8f0fb ]--- Add a check so smp_cross_call() is only called when there is more than one CPU on-line. Cc: Signed-off-by: Javier Martinez Canillas Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index aea74f5bc34a..ebd8ad274d76 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -563,7 +563,8 @@ void smp_send_stop(void) cpumask_copy(&mask, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &mask); - smp_cross_call(&mask, IPI_CPU_STOP); + if (!cpumask_empty(&mask)) + smp_cross_call(&mask, IPI_CPU_STOP); /* Wait up to one second for other CPUs to stop */ timeout = USEC_PER_SEC; -- GitLab From 2fb2ca6f5b953192d5a94fcc778d9abba06462df Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Sat, 28 Jul 2012 19:45:59 +0800 Subject: [PATCH 4809/5711] floppy: remove duplicated flag FD_RAW_NEED_DISK Fix coccinelle warning (without behavior change): drivers/block/floppy.c:2518:32-48: duplicated argument to & or | Signed-off-by: Fengguang Wu Signed-off-by: Jiri Kosina --- drivers/block/floppy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 1347ba8b8377..9d6ef68e2f1b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2516,8 +2516,7 @@ static int make_raw_rw_request(void) set_fdc((long)current_req->rq_disk->private_data); raw_cmd = &default_raw_cmd; - raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | - FD_RAW_NEED_SEEK; + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; raw_cmd->cmd_count = NR_RW; if (rq_data_dir(current_req) == READ) { raw_cmd->flags |= FD_RAW_READ; -- GitLab From 15ac49b65024f55c4371a53214879a9c77c4fbf9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 30 Jul 2012 19:42:10 +0100 Subject: [PATCH 4810/5711] ARM: Fix undefined instruction exception handling While trying to get a v3.5 kernel booted on the cubox, I noticed that VFP does not work correctly with VFP bounce handling. This is because of the confusion over 16-bit vs 32-bit instructions, and where PC is supposed to point to. The rule is that FP handlers are entered with regs->ARM_pc pointing at the _next_ instruction to be executed. However, if the exception is not handled, regs->ARM_pc points at the faulting instruction. This is easy for ARM mode, because we know that the next instruction and previous instructions are separated by four bytes. This is not true of Thumb2 though. Since all FP instructions are 32-bit in Thumb2, it makes things easy. We just need to select the appropriate adjustment. Do this by moving the adjustment out of do_undefinstr() into the assembly code, as only the assembly code knows whether it's dealing with a 32-bit or 16-bit instruction. Cc: Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 111 +++++++++++++++++++++++------------ arch/arm/kernel/traps.c | 8 --- arch/arm/vfp/entry.S | 16 ++--- arch/arm/vfp/vfphw.S | 19 +++--- 4 files changed, 92 insertions(+), 62 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 0d1851ca6eb9..0f82098c9bfe 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -244,6 +244,19 @@ svc_preempt: b 1b #endif +__und_fault: + @ Correct the PC such that it is pointing at the instruction + @ which caused the fault. If the faulting instruction was ARM + @ the PC will be pointing at the next instruction, and have to + @ subtract 4. Otherwise, it is Thumb, and the PC will be + @ pointing at the second half of the Thumb instruction. We + @ have to subtract 2. + ldr r2, [r0, #S_PC] + sub r2, r2, r1 + str r2, [r0, #S_PC] + b do_undefinstr +ENDPROC(__und_fault) + .align 5 __und_svc: #ifdef CONFIG_KPROBES @@ -261,25 +274,32 @@ __und_svc: @ @ r0 - instruction @ -#ifndef CONFIG_THUMB2_KERNEL +#ifndef CONFIG_THUMB2_KERNEL ldr r0, [r4, #-4] #else + mov r1, #2 ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 - ldrhhs r9, [r4] @ bottom 16 bits - orrhs r0, r9, r0, lsl #16 + blo __und_svc_fault + ldrh r9, [r4] @ bottom 16 bits + add r4, r4, #2 + str r4, [sp, #S_PC] + orr r0, r9, r0, lsl #16 #endif - adr r9, BSYM(1f) + adr r9, BSYM(__und_svc_finish) mov r2, r4 bl call_fpe + mov r1, #4 @ PC correction to apply +__und_svc_fault: mov r0, sp @ struct pt_regs *regs - bl do_undefinstr + bl __und_fault @ @ IRQs off again before pulling preserved data off the stack @ -1: disable_irq_notrace +__und_svc_finish: + disable_irq_notrace @ @ restore SPSR and restart the instruction @@ -423,25 +443,33 @@ __und_usr: mov r2, r4 mov r3, r5 + @ r2 = regs->ARM_pc, which is either 2 or 4 bytes ahead of the + @ faulting instruction depending on Thumb mode. + @ r3 = regs->ARM_cpsr @ - @ fall through to the emulation code, which returns using r9 if - @ it has emulated the instruction, or the more conventional lr - @ if we are to treat this as a real undefined instruction - @ - @ r0 - instruction + @ The emulation code returns using r9 if it has emulated the + @ instruction, or the more conventional lr if we are to treat + @ this as a real undefined instruction @ adr r9, BSYM(ret_from_exception) - adr lr, BSYM(__und_usr_unknown) + tst r3, #PSR_T_BIT @ Thumb mode? - itet eq @ explicit IT needed for the 1f label - subeq r4, r2, #4 @ ARM instr at LR - 4 - subne r4, r2, #2 @ Thumb instr at LR - 2 -1: ldreqt r0, [r4] + bne __und_usr_thumb + sub r4, r2, #4 @ ARM instr at LR - 4 +1: ldrt r0, [r4] #ifdef CONFIG_CPU_ENDIAN_BE8 - reveq r0, r0 @ little endian instruction + rev r0, r0 @ little endian instruction #endif - beq call_fpe + @ r0 = 32-bit ARM instruction which caused the exception + @ r2 = PC value for the following instruction (:= regs->ARM_pc) + @ r4 = PC value for the faulting instruction + @ lr = 32-bit undefined instruction function + adr lr, BSYM(__und_usr_fault_32) + b call_fpe + +__und_usr_thumb: @ Thumb instruction + sub r4, r2, #2 @ First half of thumb instr at LR - 2 #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 /* * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms @@ -455,7 +483,7 @@ __und_usr: ldr r5, .LCcpu_architecture ldr r5, [r5] cmp r5, #CPU_ARCH_ARMv7 - blo __und_usr_unknown + blo __und_usr_fault_16 @ 16bit undefined instruction /* * The following code won't get run unless the running CPU really is v7, so * coding round the lack of ldrht on older arches is pointless. Temporarily @@ -463,15 +491,18 @@ __und_usr: */ .arch armv6t2 #endif -2: - ARM( ldrht r5, [r4], #2 ) - THUMB( ldrht r5, [r4] ) - THUMB( add r4, r4, #2 ) +2: ldrht r5, [r4] cmp r5, #0xe800 @ 32bit instruction if xx != 0 - blo __und_usr_unknown -3: ldrht r0, [r4] + blo __und_usr_fault_16 @ 16bit undefined instruction +3: ldrht r0, [r2] add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 + str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 + adr lr, BSYM(__und_usr_fault_32) + @ r0 = the two 16-bit Thumb instructions which caused the exception + @ r2 = PC value for the following Thumb instruction (:= regs->ARM_pc) + @ r4 = PC value for the first 16-bit Thumb instruction + @ lr = 32bit undefined instruction function #if __LINUX_ARM_ARCH__ < 7 /* If the target arch was overridden, change it back: */ @@ -482,17 +513,13 @@ __und_usr: #endif #endif /* __LINUX_ARM_ARCH__ < 7 */ #else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ - b __und_usr_unknown + b __und_usr_fault_16 #endif - UNWIND(.fnend ) + UNWIND(.fnend) ENDPROC(__und_usr) - @ - @ fallthrough to call_fpe - @ - /* - * The out of line fixup for the ldrt above. + * The out of line fixup for the ldrt instructions above. */ .pushsection .fixup, "ax" .align 2 @@ -524,11 +551,12 @@ ENDPROC(__und_usr) * NEON handler code. * * Emulators may wish to make use of the following registers: - * r0 = instruction opcode. - * r2 = PC+4 + * r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) + * r2 = PC value to resume execution after successful emulation * r9 = normal "successful" return address - * r10 = this threads thread_info structure. + * r10 = this threads thread_info structure * lr = unrecognised instruction return address + * IRQs disabled, FIQs enabled. */ @ @ Fall-through from Thumb-2 __und_usr @@ -659,12 +687,17 @@ ENTRY(no_fp) mov pc, lr ENDPROC(no_fp) -__und_usr_unknown: - enable_irq +__und_usr_fault_32: + mov r1, #4 + b 1f +__und_usr_fault_16: + mov r1, #2 +1: enable_irq mov r0, sp adr lr, BSYM(ret_from_exception) - b do_undefinstr -ENDPROC(__und_usr_unknown) + b __und_fault +ENDPROC(__und_usr_fault_32) +ENDPROC(__und_usr_fault_16) .align 5 __pabt_usr: diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3647170e9a16..c7cae6b9a4d9 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -370,18 +370,10 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { - unsigned int correction = thumb_mode(regs) ? 2 : 4; unsigned int instr; siginfo_t info; void __user *pc; - /* - * According to the ARM ARM, PC is 2 or 4 bytes ahead, - * depending whether we're in Thumb mode or not. - * Correct this offset. - */ - regs->ARM_pc -= correction; - pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index 4fa9903b83cf..cc926c985981 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -7,18 +7,20 @@ * 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. - * - * Basic entry code, called from the kernel's undefined instruction trap. - * r0 = faulted instruction - * r5 = faulted PC+4 - * r9 = successful return - * r10 = thread_info structure - * lr = failure return */ #include #include #include "../kernel/entry-header.S" +@ VFP entry point. +@ +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address +@ r10 = this threads thread_info structure +@ lr = unrecognised instruction return address +@ IRQs disabled. +@ ENTRY(do_vfp) #ifdef CONFIG_PREEMPT ldr r4, [r10, #TI_PREEMPT] @ get preempt count diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 2d30c7f6edd3..3a0efaad6090 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -61,13 +61,13 @@ @ VFP hardware support entry point. @ -@ r0 = faulted instruction -@ r2 = faulted PC+4 -@ r9 = successful return +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address @ r10 = vfp_state union @ r11 = CPU number -@ lr = failure return - +@ lr = unrecognised instruction return address +@ IRQs enabled. ENTRY(vfp_support_entry) DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 @@ -161,9 +161,12 @@ vfp_hw_state_valid: @ exception before retrying branch @ out before setting an FPEXC that @ stops us reading stuff - VFPFMXR FPEXC, r1 @ restore FPEXC last - sub r2, r2, #4 - str r2, [sp, #S_PC] @ retry the instruction + VFPFMXR FPEXC, r1 @ Restore FPEXC last + sub r2, r2, #4 @ Retry current instruction - if Thumb + str r2, [sp, #S_PC] @ mode it's two 16-bit instructions, + @ else it's one 32-bit instruction, so + @ always subtract 4 from the following + @ instruction address. #ifdef CONFIG_PREEMPT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count -- GitLab From b74253f78400f9a4b42da84bb1de7540b88ce7c4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 23 Jul 2012 14:18:13 +0100 Subject: [PATCH 4811/5711] ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches The vivt_flush_cache_{range,page} functions check that the mm_struct of the VMA being flushed has been active on the current CPU before performing the cache maintenance. The gate_vma has a NULL mm_struct pointer and, as such, will cause a kernel fault if we try to flush it with the above operations. This happens during ELF core dumps, which include the gate_vma as it may be useful for debugging purposes. This patch adds checks to the VIVT cache flushing functions so that VMAs with a NULL mm_struct are flushed unconditionally (the vectors page may be dirty if we use it to store the current TLS pointer). Cc: # 3.4+ Reported-by: Gilles Chanteperdrix Tested-by: Uros Bizjak Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 004c1bc95d2b..e4448e16046d 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -215,7 +215,9 @@ static inline void vivt_flush_cache_mm(struct mm_struct *mm) static inline void vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), vma->vm_flags); } @@ -223,7 +225,9 @@ vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned static inline void vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) { unsigned long addr = user_addr & PAGE_MASK; __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); } -- GitLab From 7bedaa5537604f34d1d63c5ec7891e559d2a61ed Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Apr 2012 12:10:24 +0100 Subject: [PATCH 4812/5711] dmaengine: add OMAP DMA engine driver Tested-by: Tony Lindgren Signed-off-by: Russell King --- drivers/dma/Kconfig | 6 + drivers/dma/Makefile | 1 + drivers/dma/omap-dma.c | 524 +++++++++++++++++++++++++++++++++++++++ include/linux/omap-dma.h | 22 ++ 4 files changed, 553 insertions(+) create mode 100644 drivers/dma/omap-dma.c create mode 100644 include/linux/omap-dma.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index eb2b60e8e1cb..8be3bf68c0bd 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -261,6 +261,12 @@ config DMA_SA11X0 SA-1110 SoCs. This DMA engine can only be used with on-chip devices. +config DMA_OMAP + tristate "OMAP DMA support" + depends on ARCH_OMAP + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + config DMA_ENGINE bool diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index fc05f7ddac7e..ddc291a2116a 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_PCH_DMA) += pch_dma.o obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o +obj-$(CONFIG_DMA_OMAP) += omap-dma.o diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c new file mode 100644 index 000000000000..fe33ddd8eb0f --- /dev/null +++ b/drivers/dma/omap-dma.c @@ -0,0 +1,524 @@ +/* + * OMAP DMAengine support + * + * 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 "virt-dma.h" +#include + +struct omap_dmadev { + struct dma_device ddev; + spinlock_t lock; + struct tasklet_struct task; + struct list_head pending; +}; + +struct omap_chan { + struct virt_dma_chan vc; + struct list_head node; + + struct dma_slave_config cfg; + unsigned dma_sig; + + int dma_ch; + struct omap_desc *desc; + unsigned sgidx; +}; + +struct omap_sg { + dma_addr_t addr; + uint32_t en; /* number of elements (24-bit) */ + uint32_t fn; /* number of frames (16-bit) */ +}; + +struct omap_desc { + struct virt_dma_desc vd; + enum dma_transfer_direction dir; + dma_addr_t dev_addr; + + uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ + uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ + uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ + uint8_t periph_port; /* Peripheral port */ + + unsigned sglen; + struct omap_sg sg[0]; +}; + +static const unsigned es_bytes[] = { + [OMAP_DMA_DATA_TYPE_S8] = 1, + [OMAP_DMA_DATA_TYPE_S16] = 2, + [OMAP_DMA_DATA_TYPE_S32] = 4, +}; + +static inline struct omap_dmadev *to_omap_dma_dev(struct dma_device *d) +{ + return container_of(d, struct omap_dmadev, ddev); +} + +static inline struct omap_chan *to_omap_dma_chan(struct dma_chan *c) +{ + return container_of(c, struct omap_chan, vc.chan); +} + +static inline struct omap_desc *to_omap_dma_desc(struct dma_async_tx_descriptor *t) +{ + return container_of(t, struct omap_desc, vd.tx); +} + +static void omap_dma_desc_free(struct virt_dma_desc *vd) +{ + kfree(container_of(vd, struct omap_desc, vd)); +} + +static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, + unsigned idx) +{ + struct omap_sg *sg = d->sg + idx; + + if (d->dir == DMA_DEV_TO_MEM) + omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, + OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); + else + omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, + OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); + + omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn, + d->sync_mode, c->dma_sig, d->sync_type); + + omap_start_dma(c->dma_ch); +} + +static void omap_dma_start_desc(struct omap_chan *c) +{ + struct virt_dma_desc *vd = vchan_next_desc(&c->vc); + struct omap_desc *d; + + if (!vd) { + c->desc = NULL; + return; + } + + list_del(&vd->node); + + c->desc = d = to_omap_dma_desc(&vd->tx); + c->sgidx = 0; + + if (d->dir == DMA_DEV_TO_MEM) + omap_set_dma_src_params(c->dma_ch, d->periph_port, + OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0); + else + omap_set_dma_dest_params(c->dma_ch, d->periph_port, + OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0); + + omap_dma_start_sg(c, d, 0); +} + +static void omap_dma_callback(int ch, u16 status, void *data) +{ + struct omap_chan *c = data; + struct omap_desc *d; + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + d = c->desc; + if (d) { + if (++c->sgidx < d->sglen) { + omap_dma_start_sg(c, d, c->sgidx); + } else { + omap_dma_start_desc(c); + vchan_cookie_complete(&d->vd); + } + } + spin_unlock_irqrestore(&c->vc.lock, flags); +} + +/* + * This callback schedules all pending channels. We could be more + * clever here by postponing allocation of the real DMA channels to + * this point, and freeing them when our virtual channel becomes idle. + * + * We would then need to deal with 'all channels in-use' + */ +static void omap_dma_sched(unsigned long data) +{ + struct omap_dmadev *d = (struct omap_dmadev *)data; + LIST_HEAD(head); + + spin_lock_irq(&d->lock); + list_splice_tail_init(&d->pending, &head); + spin_unlock_irq(&d->lock); + + while (!list_empty(&head)) { + struct omap_chan *c = list_first_entry(&head, + struct omap_chan, node); + + spin_lock_irq(&c->vc.lock); + list_del_init(&c->node); + omap_dma_start_desc(c); + spin_unlock_irq(&c->vc.lock); + } +} + +static int omap_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + + dev_info(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig); + + return omap_request_dma(c->dma_sig, "DMA engine", + omap_dma_callback, c, &c->dma_ch); +} + +static void omap_dma_free_chan_resources(struct dma_chan *chan) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + + vchan_free_chan_resources(&c->vc); + omap_free_dma(c->dma_ch); + + dev_info(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig); +} + +static enum dma_status omap_dma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ + /* + * FIXME: do we need to return pending bytes? + * We have no users of that info at the moment... + */ + return dma_cookie_status(chan, cookie, txstate); +} + +static void omap_dma_issue_pending(struct dma_chan *chan) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + if (vchan_issue_pending(&c->vc) && !c->desc) { + struct omap_dmadev *d = to_omap_dma_dev(chan->device); + spin_lock(&d->lock); + if (list_empty(&c->node)) + list_add_tail(&c->node, &d->pending); + spin_unlock(&d->lock); + tasklet_schedule(&d->task); + } + spin_unlock_irqrestore(&c->vc.lock, flags); +} + +static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen, + enum dma_transfer_direction dir, unsigned long tx_flags, void *context) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + enum dma_slave_buswidth dev_width; + struct scatterlist *sgent; + struct omap_desc *d; + dma_addr_t dev_addr; + unsigned i, j = 0, es, en, frame_bytes, sync_type; + u32 burst; + + if (dir == DMA_DEV_TO_MEM) { + dev_addr = c->cfg.src_addr; + dev_width = c->cfg.src_addr_width; + burst = c->cfg.src_maxburst; + sync_type = OMAP_DMA_SRC_SYNC; + } else if (dir == DMA_MEM_TO_DEV) { + dev_addr = c->cfg.dst_addr; + dev_width = c->cfg.dst_addr_width; + burst = c->cfg.dst_maxburst; + sync_type = OMAP_DMA_DST_SYNC; + } else { + dev_err(chan->device->dev, "%s: bad direction?\n", __func__); + return NULL; + } + + /* Bus width translates to the element size (ES) */ + switch (dev_width) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + es = OMAP_DMA_DATA_TYPE_S8; + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + es = OMAP_DMA_DATA_TYPE_S16; + break; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + es = OMAP_DMA_DATA_TYPE_S32; + break; + default: /* not reached */ + return NULL; + } + + /* Now allocate and setup the descriptor. */ + d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); + if (!d) + return NULL; + + d->dir = dir; + d->dev_addr = dev_addr; + d->es = es; + d->sync_mode = OMAP_DMA_SYNC_FRAME; + d->sync_type = sync_type; + d->periph_port = OMAP_DMA_PORT_TIPB; + + /* + * Build our scatterlist entries: each contains the address, + * the number of elements (EN) in each frame, and the number of + * frames (FN). Number of bytes for this entry = ES * EN * FN. + * + * Burst size translates to number of elements with frame sync. + * Note: DMA engine defines burst to be the number of dev-width + * transfers. + */ + en = burst; + frame_bytes = es_bytes[es] * en; + for_each_sg(sgl, sgent, sglen, i) { + d->sg[j].addr = sg_dma_address(sgent); + d->sg[j].en = en; + d->sg[j].fn = sg_dma_len(sgent) / frame_bytes; + j++; + } + + d->sglen = j; + + return vchan_tx_prep(&c->vc, &d->vd, tx_flags); +} + +static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) +{ + if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || + cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) + return -EINVAL; + + memcpy(&c->cfg, cfg, sizeof(c->cfg)); + + return 0; +} + +static int omap_dma_terminate_all(struct omap_chan *c) +{ + struct omap_dmadev *d = to_omap_dma_dev(c->vc.chan.device); + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&c->vc.lock, flags); + + /* Prevent this channel being scheduled */ + spin_lock(&d->lock); + list_del_init(&c->node); + spin_unlock(&d->lock); + + /* + * Stop DMA activity: we assume the callback will not be called + * after omap_stop_dma() returns (even if it does, it will see + * c->desc is NULL and exit.) + */ + if (c->desc) { + c->desc = NULL; + omap_stop_dma(c->dma_ch); + } + + vchan_get_all_descriptors(&c->vc, &head); + spin_unlock_irqrestore(&c->vc.lock, flags); + vchan_dma_desc_free_list(&c->vc, &head); + + return 0; +} + +static int omap_dma_pause(struct omap_chan *c) +{ + /* FIXME: not supported by platform private API */ + return -EINVAL; +} + +static int omap_dma_resume(struct omap_chan *c) +{ + /* FIXME: not supported by platform private API */ + return -EINVAL; +} + +static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + int ret; + + switch (cmd) { + case DMA_SLAVE_CONFIG: + ret = omap_dma_slave_config(c, (struct dma_slave_config *)arg); + break; + + case DMA_TERMINATE_ALL: + ret = omap_dma_terminate_all(c); + break; + + case DMA_PAUSE: + ret = omap_dma_pause(c); + break; + + case DMA_RESUME: + ret = omap_dma_resume(c); + break; + + default: + ret = -ENXIO; + break; + } + + return ret; +} + +static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) +{ + struct omap_chan *c; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + + c->dma_sig = dma_sig; + c->vc.desc_free = omap_dma_desc_free; + vchan_init(&c->vc, &od->ddev); + INIT_LIST_HEAD(&c->node); + + od->ddev.chancnt++; + + return 0; +} + +static void omap_dma_free(struct omap_dmadev *od) +{ + tasklet_kill(&od->task); + while (!list_empty(&od->ddev.channels)) { + struct omap_chan *c = list_first_entry(&od->ddev.channels, + struct omap_chan, vc.chan.device_node); + + list_del(&c->vc.chan.device_node); + tasklet_kill(&c->vc.task); + kfree(c); + } + kfree(od); +} + +static int omap_dma_probe(struct platform_device *pdev) +{ + struct omap_dmadev *od; + int rc, i; + + od = kzalloc(sizeof(*od), GFP_KERNEL); + if (!od) + return -ENOMEM; + + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); + od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; + od->ddev.device_free_chan_resources = omap_dma_free_chan_resources; + od->ddev.device_tx_status = omap_dma_tx_status; + od->ddev.device_issue_pending = omap_dma_issue_pending; + od->ddev.device_prep_slave_sg = omap_dma_prep_slave_sg; + od->ddev.device_control = omap_dma_control; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + INIT_LIST_HEAD(&od->pending); + spin_lock_init(&od->lock); + + tasklet_init(&od->task, omap_dma_sched, (unsigned long)od); + + for (i = 0; i < 127; i++) { + rc = omap_dma_chan_init(od, i); + if (rc) { + omap_dma_free(od); + return rc; + } + } + + rc = dma_async_device_register(&od->ddev); + if (rc) { + pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n", + rc); + omap_dma_free(od); + } else { + platform_set_drvdata(pdev, od); + } + + dev_info(&pdev->dev, "OMAP DMA engine driver\n"); + + return rc; +} + +static int omap_dma_remove(struct platform_device *pdev) +{ + struct omap_dmadev *od = platform_get_drvdata(pdev); + + dma_async_device_unregister(&od->ddev); + omap_dma_free(od); + + return 0; +} + +static struct platform_driver omap_dma_driver = { + .probe = omap_dma_probe, + .remove = omap_dma_remove, + .driver = { + .name = "omap-dma-engine", + .owner = THIS_MODULE, + }, +}; + +bool omap_dma_filter_fn(struct dma_chan *chan, void *param) +{ + if (chan->device->dev->driver == &omap_dma_driver.driver) { + struct omap_chan *c = to_omap_dma_chan(chan); + unsigned req = *(unsigned *)param; + + return req == c->dma_sig; + } + return false; +} +EXPORT_SYMBOL_GPL(omap_dma_filter_fn); + +static struct platform_device *pdev; + +static const struct platform_device_info omap_dma_dev_info = { + .name = "omap-dma-engine", + .id = -1, + .dma_mask = DMA_BIT_MASK(32), +}; + +static int omap_dma_init(void) +{ + int rc = platform_driver_register(&omap_dma_driver); + + if (rc == 0) { + pdev = platform_device_register_full(&omap_dma_dev_info); + if (IS_ERR(pdev)) { + platform_driver_unregister(&omap_dma_driver); + rc = PTR_ERR(pdev); + } + } + return rc; +} +subsys_initcall(omap_dma_init); + +static void __exit omap_dma_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&omap_dma_driver); +} +module_exit(omap_dma_exit); + +MODULE_AUTHOR("Russell King"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h new file mode 100644 index 000000000000..eb475a8ea25b --- /dev/null +++ b/include/linux/omap-dma.h @@ -0,0 +1,22 @@ +/* + * OMAP DMA Engine support + * + * 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 __LINUX_OMAP_DMA_H +#define __LINUX_OMAP_DMA_H + +struct dma_chan; + +#if defined(CONFIG_DMA_OMAP) || defined(CONFIG_DMA_OMAP_MODULE) +bool omap_dma_filter_fn(struct dma_chan *, void *); +#else +static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) +{ + return false; +} +#endif + +#endif -- GitLab From 3850e22f5146d2ff5b66f1b7460d4720d5f1b6c7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Jun 2012 10:37:35 +0100 Subject: [PATCH 4813/5711] dmaengine: omap: add support for returning residue in tx_state method Add support for returning the residue for a particular descriptor by reading the current DMA address for the source or destination side of the transfer as appropriate, and walking the scatterlist until we find an entry containing the current DMA address. Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 69 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index fe33ddd8eb0f..82a7ac7c048b 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -194,14 +194,73 @@ static void omap_dma_free_chan_resources(struct dma_chan *chan) dev_info(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig); } +static size_t omap_dma_sg_size(struct omap_sg *sg) +{ + return sg->en * sg->fn; +} + +static size_t omap_dma_desc_size(struct omap_desc *d) +{ + unsigned i; + size_t size; + + for (size = i = 0; i < d->sglen; i++) + size += omap_dma_sg_size(&d->sg[i]); + + return size * es_bytes[d->es]; +} + +static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) +{ + unsigned i; + size_t size, es_size = es_bytes[d->es]; + + for (size = i = 0; i < d->sglen; i++) { + size_t this_size = omap_dma_sg_size(&d->sg[i]) * es_size; + + if (size) + size += this_size; + else if (addr >= d->sg[i].addr && + addr < d->sg[i].addr + this_size) + size += d->sg[i].addr + this_size - addr; + } + return size; +} + static enum dma_status omap_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { - /* - * FIXME: do we need to return pending bytes? - * We have no users of that info at the moment... - */ - return dma_cookie_status(chan, cookie, txstate); + struct omap_chan *c = to_omap_dma_chan(chan); + struct virt_dma_desc *vd; + enum dma_status ret; + unsigned long flags; + + ret = dma_cookie_status(chan, cookie, txstate); + if (ret == DMA_SUCCESS || !txstate) + return ret; + + spin_lock_irqsave(&c->vc.lock, flags); + vd = vchan_find_desc(&c->vc, cookie); + if (vd) { + txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx)); + } else if (c->desc && c->desc->vd.tx.cookie == cookie) { + struct omap_desc *d = c->desc; + dma_addr_t pos; + + if (d->dir == DMA_MEM_TO_DEV) + pos = omap_get_dma_src_pos(c->dma_ch); + else if (d->dir == DMA_DEV_TO_MEM) + pos = omap_get_dma_dst_pos(c->dma_ch); + else + pos = 0; + + txstate->residue = omap_dma_desc_size_pos(d, pos); + } else { + txstate->residue = 0; + } + spin_unlock_irqrestore(&c->vc.lock, flags); + + return ret; } static void omap_dma_issue_pending(struct dma_chan *chan) -- GitLab From 7c836bc7f9f71d62a8dc50712db122a69b405486 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 18 Jun 2012 16:45:19 +0100 Subject: [PATCH 4814/5711] dmaengine: omap: add support for setting fi Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 82a7ac7c048b..f2e919fcea36 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -50,6 +50,7 @@ struct omap_desc { enum dma_transfer_direction dir; dma_addr_t dev_addr; + int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ @@ -120,10 +121,10 @@ static void omap_dma_start_desc(struct omap_chan *c) if (d->dir == DMA_DEV_TO_MEM) omap_set_dma_src_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0); + OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); else omap_set_dma_dest_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0); + OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); omap_dma_start_sg(c, d, 0); } -- GitLab From 3a774ea91a5d05e7af58db6ae1ba298263c4a3d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Jun 2012 10:40:15 +0100 Subject: [PATCH 4815/5711] dmaengine: omap: add support for cyclic DMA Add support for cyclic DMA to the OMAP DMA engine driver. Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 93 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index f2e919fcea36..ae0561826137 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -33,6 +33,7 @@ struct omap_chan { struct dma_slave_config cfg; unsigned dma_sig; + bool cyclic; int dma_ch; struct omap_desc *desc; @@ -138,11 +139,15 @@ static void omap_dma_callback(int ch, u16 status, void *data) spin_lock_irqsave(&c->vc.lock, flags); d = c->desc; if (d) { - if (++c->sgidx < d->sglen) { - omap_dma_start_sg(c, d, c->sgidx); + if (!c->cyclic) { + if (++c->sgidx < d->sglen) { + omap_dma_start_sg(c, d, c->sgidx); + } else { + omap_dma_start_desc(c); + vchan_cookie_complete(&d->vd); + } } else { - omap_dma_start_desc(c); - vchan_cookie_complete(&d->vd); + vchan_cyclic_callback(&d->vd); } } spin_unlock_irqrestore(&c->vc.lock, flags); @@ -358,6 +363,79 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( return vchan_tx_prep(&c->vc, &d->vd, tx_flags); } +static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction dir, void *context) +{ + struct omap_chan *c = to_omap_dma_chan(chan); + enum dma_slave_buswidth dev_width; + struct omap_desc *d; + dma_addr_t dev_addr; + unsigned es, sync_type; + u32 burst; + + if (dir == DMA_DEV_TO_MEM) { + dev_addr = c->cfg.src_addr; + dev_width = c->cfg.src_addr_width; + burst = c->cfg.src_maxburst; + sync_type = OMAP_DMA_SRC_SYNC; + } else if (dir == DMA_MEM_TO_DEV) { + dev_addr = c->cfg.dst_addr; + dev_width = c->cfg.dst_addr_width; + burst = c->cfg.dst_maxburst; + sync_type = OMAP_DMA_DST_SYNC; + } else { + dev_err(chan->device->dev, "%s: bad direction?\n", __func__); + return NULL; + } + + /* Bus width translates to the element size (ES) */ + switch (dev_width) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + es = OMAP_DMA_DATA_TYPE_S8; + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + es = OMAP_DMA_DATA_TYPE_S16; + break; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + es = OMAP_DMA_DATA_TYPE_S32; + break; + default: /* not reached */ + return NULL; + } + + /* Now allocate and setup the descriptor. */ + d = kzalloc(sizeof(*d) + sizeof(d->sg[0]), GFP_ATOMIC); + if (!d) + return NULL; + + d->dir = dir; + d->dev_addr = dev_addr; + d->fi = burst; + d->es = es; + d->sync_mode = OMAP_DMA_SYNC_PACKET; + d->sync_type = sync_type; + d->periph_port = OMAP_DMA_PORT_MPUI; + d->sg[0].addr = buf_addr; + d->sg[0].en = period_len / es_bytes[es]; + d->sg[0].fn = buf_len / period_len; + d->sglen = 1; + + if (!c->cyclic) { + c->cyclic = true; + omap_dma_link_lch(c->dma_ch, c->dma_ch); + omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); + omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); + } + + if (!cpu_class_is_omap1()) { + omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); + omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); + } + + return vchan_tx_prep(&c->vc, &d->vd, DMA_CTRL_ACK | DMA_PREP_INTERRUPT); +} + static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) { if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || @@ -392,6 +470,11 @@ static int omap_dma_terminate_all(struct omap_chan *c) omap_stop_dma(c->dma_ch); } + if (c->cyclic) { + c->cyclic = false; + omap_dma_unlink_lch(c->dma_ch, c->dma_ch); + } + vchan_get_all_descriptors(&c->vc, &head); spin_unlock_irqrestore(&c->vc.lock, flags); vchan_dma_desc_free_list(&c->vc, &head); @@ -484,11 +567,13 @@ static int omap_dma_probe(struct platform_device *pdev) return -ENOMEM; dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); + dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; od->ddev.device_free_chan_resources = omap_dma_free_chan_resources; od->ddev.device_tx_status = omap_dma_tx_status; od->ddev.device_issue_pending = omap_dma_issue_pending; od->ddev.device_prep_slave_sg = omap_dma_prep_slave_sg; + od->ddev.device_prep_dma_cyclic = omap_dma_prep_dma_cyclic; od->ddev.device_control = omap_dma_control; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); -- GitLab From c5c98927d74cd6853579e1a5b56cd6eb0d4885f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Apr 2012 12:14:39 +0100 Subject: [PATCH 4816/5711] mmc: omap_hsmmc: add DMA engine support Add DMA engine support to the OMAP HSMMC driver. This supplements the private DMA API implementation contained within this driver, and the driver can be switched at build time between using DMA engine and the private DMA API. Tested-by: Grazvydas Ignotas Tested-by: Tony Lindgren Acked-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/omap_hsmmc.c | 192 +++++++++++++++++++++++++++++----- 1 file changed, 165 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 389a3eedfc24..effe328c1c14 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -165,7 +166,9 @@ struct omap_hsmmc_host { u32 bytesleft; int suspended; int irq; - int use_dma, dma_ch; + int use_dma, dma_ch, dma2; + struct dma_chan *tx_chan; + struct dma_chan *rx_chan; int dma_line_tx, dma_line_rx; int slot_id; int response_busy; @@ -797,19 +800,26 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) return DMA_FROM_DEVICE; } +static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host, + struct mmc_data *data) +{ + return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; +} + static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) { - int dma_ch; + int dma_ch, dma2; unsigned long flags; spin_lock_irqsave(&host->irq_lock, flags); host->req_in_progress = 0; dma_ch = host->dma_ch; + dma2 = host->dma2; spin_unlock_irqrestore(&host->irq_lock, flags); omap_hsmmc_disable_irq(host); /* Do not complete the request if DMA is still in progress */ - if (mrq->data && host->use_dma && dma_ch != -1) + if (mrq->data && host->use_dma && (dma_ch != -1 || dma2 != -1)) return; host->mrq = NULL; mmc_request_done(host->mmc, mrq); @@ -878,7 +888,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) */ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) { - int dma_ch; + int dma_ch, dma2; unsigned long flags; host->data->error = errno; @@ -886,8 +896,20 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) spin_lock_irqsave(&host->irq_lock, flags); dma_ch = host->dma_ch; host->dma_ch = -1; + dma2 = host->dma2; + host->dma2 = -1; spin_unlock_irqrestore(&host->irq_lock, flags); + if (host->use_dma && dma2 != -1) { + struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data); + + dmaengine_terminate_all(chan); + dma_unmap_sg(chan->device->dev, + host->data->sg, host->data->sg_len, + omap_hsmmc_get_dma_dir(host, host->data)); + + host->data->host_cookie = 0; + } if (host->use_dma && dma_ch != -1) { dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->data->sg_len, @@ -1284,9 +1306,43 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) } } +static void omap_hsmmc_dma_callback(void *param) +{ + struct omap_hsmmc_host *host = param; + struct dma_chan *chan; + struct mmc_data *data; + int req_in_progress; + + spin_lock_irq(&host->irq_lock); + if (host->dma2 < 0) { + spin_unlock_irq(&host->irq_lock); + return; + } + + data = host->mrq->data; + chan = omap_hsmmc_get_dma_chan(host, data); + if (!data->host_cookie) + dma_unmap_sg(chan->device->dev, + data->sg, data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); + + req_in_progress = host->req_in_progress; + host->dma2 = -1; + spin_unlock_irq(&host->irq_lock); + + /* If DMA has finished after TC, complete the request */ + if (!req_in_progress) { + struct mmc_request *mrq = host->mrq; + + host->mrq = NULL; + mmc_request_done(host->mmc, mrq); + } +} + static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, struct mmc_data *data, - struct omap_hsmmc_next *next) + struct omap_hsmmc_next *next, + struct device *dev) { int dma_len; @@ -1301,8 +1357,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, /* Check if next job is already prepared */ if (next || (!next && data->host_cookie != host->next_data.cookie)) { - dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, + dma_len = dma_map_sg(dev, data->sg, data->sg_len, omap_hsmmc_get_dma_dir(host, data)); } else { @@ -1331,6 +1386,7 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, { int dma_ch = 0, ret = 0, i; struct mmc_data *data = req->data; + struct dma_chan *chan; /* Sanity check: all the SG entries must be aligned by block size. */ for (i = 0; i < data->sg_len; i++) { @@ -1346,24 +1402,66 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, */ return -EINVAL; - BUG_ON(host->dma_ch != -1); + BUG_ON(host->dma_ch != -1 || host->dma2 != -1); - ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), - "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); - if (ret != 0) { - dev_err(mmc_dev(host->mmc), - "%s: omap_request_dma() failed with %d\n", - mmc_hostname(host->mmc), ret); - return ret; - } - ret = omap_hsmmc_pre_dma_transfer(host, data, NULL); - if (ret) - return ret; + chan = omap_hsmmc_get_dma_chan(host, data); + if (!chan) { + ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), + "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); + if (ret != 0) { + dev_err(mmc_dev(host->mmc), + "%s: omap_request_dma() failed with %d\n", + mmc_hostname(host->mmc), ret); + return ret; + } + ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, + mmc_dev(host->mmc)); + if (ret) + return ret; + + host->dma_ch = dma_ch; + host->dma_sg_idx = 0; + + omap_hsmmc_config_dma_params(host, data, data->sg); + } else { + struct dma_slave_config cfg; + struct dma_async_tx_descriptor *tx; + + cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA; + cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA; + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.src_maxburst = data->blksz / 4; + cfg.dst_maxburst = data->blksz / 4; + + ret = dmaengine_slave_config(chan, &cfg); + if (ret) + return ret; + + ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, + chan->device->dev); + if (ret) + return ret; + + tx = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, + data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) { + dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); + /* FIXME: cleanup */ + return -1; + } - host->dma_ch = dma_ch; - host->dma_sg_idx = 0; + tx->callback = omap_hsmmc_dma_callback; + tx->callback_param = host; - omap_hsmmc_config_dma_params(host, data, data->sg); + /* Does not fail */ + dmaengine_submit(tx); + + host->dma2 = 1; + + dma_async_issue_pending(chan); + } return 0; } @@ -1446,9 +1544,12 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct mmc_data *data = mrq->data; if (host->use_dma) { + struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data); + struct device *dev = c ? c->device->dev : mmc_dev(mmc); + if (data->host_cookie) - dma_unmap_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, + dma_unmap_sg(dev, + data->sg, data->sg_len, omap_hsmmc_get_dma_dir(host, data)); data->host_cookie = 0; } @@ -1464,10 +1565,14 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, return ; } - if (host->use_dma) + if (host->use_dma) { + struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data); + struct device *dev = c ? c->device->dev : mmc_dev(mmc); + if (omap_hsmmc_pre_dma_transfer(host, mrq->data, - &host->next_data)) + &host->next_data, dev)) mrq->data->host_cookie = 0; + } } /* @@ -1479,7 +1584,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) int err; BUG_ON(host->req_in_progress); - BUG_ON(host->dma_ch != -1); + BUG_ON(host->dma_ch != -1 || host->dma2 != -1); if (host->protect_card) { if (host->reqs_blocked < 3) { /* @@ -1846,6 +1951,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) host->use_dma = 1; host->dev->dma_mask = &pdata->dma_mask; host->dma_ch = -1; + host->dma2 = -1; host->irq = irq; host->slot_id = 0; host->mapbase = res->start + pdata->reg_offset; @@ -1942,6 +2048,29 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) } host->dma_line_rx = res->start; + { + dma_cap_mask_t mask; + unsigned sig; + extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); +#if 1 + sig = host->dma_line_rx; + host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!host->rx_chan) { + dev_warn(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", sig); + } +#endif +#if 1 + sig = host->dma_line_tx; + host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!host->tx_chan) { + dev_warn(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", sig); + } +#endif + } + /* Request IRQ for MMC operations */ ret = request_irq(host->irq, omap_hsmmc_irq, 0, mmc_hostname(mmc), host); @@ -2019,6 +2148,10 @@ err_reg: err_irq_cd_init: free_irq(host->irq, host); err_irq: + if (host->tx_chan) + dma_release_channel(host->tx_chan); + if (host->rx_chan) + dma_release_channel(host->rx_chan); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); clk_put(host->fclk); @@ -2054,6 +2187,11 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev) if (mmc_slot(host).card_detect_irq) free_irq(mmc_slot(host).card_detect_irq, host); + if (host->tx_chan) + dma_release_channel(host->tx_chan); + if (host->rx_chan) + dma_release_channel(host->rx_chan); + pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); clk_put(host->fclk); -- GitLab From 26b88520b80695a6fa5fd95b5d97c03f4daf87e0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Apr 2012 12:27:37 +0100 Subject: [PATCH 4817/5711] mmc: omap_hsmmc: remove private DMA API implementation Remove the private DMA API implementation from omap_hsmmc, making it use entirely the DMA engine API. Tested-by: Tony Lindgren Tested-by: Venkatraman S Signed-off-by: Russell King --- drivers/mmc/host/omap_hsmmc.c | 263 ++++++++-------------------------- 1 file changed, 63 insertions(+), 200 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index effe328c1c14..2b2c98773f15 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -166,10 +165,9 @@ struct omap_hsmmc_host { u32 bytesleft; int suspended; int irq; - int use_dma, dma_ch, dma2; + int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; - int dma_line_tx, dma_line_rx; int slot_id; int response_busy; int context_loss; @@ -808,18 +806,17 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host, static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) { - int dma_ch, dma2; + int dma_ch; unsigned long flags; spin_lock_irqsave(&host->irq_lock, flags); host->req_in_progress = 0; dma_ch = host->dma_ch; - dma2 = host->dma2; spin_unlock_irqrestore(&host->irq_lock, flags); omap_hsmmc_disable_irq(host); /* Do not complete the request if DMA is still in progress */ - if (mrq->data && host->use_dma && (dma_ch != -1 || dma2 != -1)) + if (mrq->data && host->use_dma && dma_ch != -1) return; host->mrq = NULL; mmc_request_done(host->mmc, mrq); @@ -888,7 +885,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) */ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) { - int dma_ch, dma2; + int dma_ch; unsigned long flags; host->data->error = errno; @@ -896,11 +893,9 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) spin_lock_irqsave(&host->irq_lock, flags); dma_ch = host->dma_ch; host->dma_ch = -1; - dma2 = host->dma2; - host->dma2 = -1; spin_unlock_irqrestore(&host->irq_lock, flags); - if (host->use_dma && dma2 != -1) { + if (host->use_dma && dma_ch != -1) { struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data); dmaengine_terminate_all(chan); @@ -910,13 +905,6 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) host->data->host_cookie = 0; } - if (host->use_dma && dma_ch != -1) { - dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, - host->data->sg_len, - omap_hsmmc_get_dma_dir(host, host->data)); - omap_free_dma(dma_ch); - host->data->host_cookie = 0; - } host->data = NULL; } @@ -1212,100 +1200,6 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) return IRQ_HANDLED; } -static int omap_hsmmc_get_dma_sync_dev(struct omap_hsmmc_host *host, - struct mmc_data *data) -{ - int sync_dev; - - if (data->flags & MMC_DATA_WRITE) - sync_dev = host->dma_line_tx; - else - sync_dev = host->dma_line_rx; - return sync_dev; -} - -static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, - struct mmc_data *data, - struct scatterlist *sgl) -{ - int blksz, nblk, dma_ch; - - dma_ch = host->dma_ch; - if (data->flags & MMC_DATA_WRITE) { - omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - (host->mapbase + OMAP_HSMMC_DATA), 0, 0); - omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, - sg_dma_address(sgl), 0, 0); - } else { - omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - (host->mapbase + OMAP_HSMMC_DATA), 0, 0); - omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, - sg_dma_address(sgl), 0, 0); - } - - blksz = host->data->blksz; - nblk = sg_dma_len(sgl) / blksz; - - omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, - blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, - omap_hsmmc_get_dma_sync_dev(host, data), - !(data->flags & MMC_DATA_WRITE)); - - omap_start_dma(dma_ch); -} - -/* - * DMA call back function - */ -static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) -{ - struct omap_hsmmc_host *host = cb_data; - struct mmc_data *data; - int dma_ch, req_in_progress; - unsigned long flags; - - if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { - dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n", - ch_status); - return; - } - - spin_lock_irqsave(&host->irq_lock, flags); - if (host->dma_ch < 0) { - spin_unlock_irqrestore(&host->irq_lock, flags); - return; - } - - data = host->mrq->data; - host->dma_sg_idx++; - if (host->dma_sg_idx < host->dma_len) { - /* Fire up the next transfer. */ - omap_hsmmc_config_dma_params(host, data, - data->sg + host->dma_sg_idx); - spin_unlock_irqrestore(&host->irq_lock, flags); - return; - } - - if (!data->host_cookie) - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - omap_hsmmc_get_dma_dir(host, data)); - - req_in_progress = host->req_in_progress; - dma_ch = host->dma_ch; - host->dma_ch = -1; - spin_unlock_irqrestore(&host->irq_lock, flags); - - omap_free_dma(dma_ch); - - /* If DMA has finished after TC, complete the request */ - if (!req_in_progress) { - struct mmc_request *mrq = host->mrq; - - host->mrq = NULL; - mmc_request_done(host->mmc, mrq); - } -} - static void omap_hsmmc_dma_callback(void *param) { struct omap_hsmmc_host *host = param; @@ -1314,7 +1208,7 @@ static void omap_hsmmc_dma_callback(void *param) int req_in_progress; spin_lock_irq(&host->irq_lock); - if (host->dma2 < 0) { + if (host->dma_ch < 0) { spin_unlock_irq(&host->irq_lock); return; } @@ -1327,7 +1221,7 @@ static void omap_hsmmc_dma_callback(void *param) omap_hsmmc_get_dma_dir(host, data)); req_in_progress = host->req_in_progress; - host->dma2 = -1; + host->dma_ch = -1; spin_unlock_irq(&host->irq_lock); /* If DMA has finished after TC, complete the request */ @@ -1342,7 +1236,7 @@ static void omap_hsmmc_dma_callback(void *param) static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, struct mmc_data *data, struct omap_hsmmc_next *next, - struct device *dev) + struct dma_chan *chan) { int dma_len; @@ -1357,7 +1251,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, /* Check if next job is already prepared */ if (next || (!next && data->host_cookie != host->next_data.cookie)) { - dma_len = dma_map_sg(dev, data->sg, data->sg_len, + dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, omap_hsmmc_get_dma_dir(host, data)); } else { @@ -1384,7 +1278,9 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, struct mmc_request *req) { - int dma_ch = 0, ret = 0, i; + struct dma_slave_config cfg; + struct dma_async_tx_descriptor *tx; + int ret = 0, i; struct mmc_data *data = req->data; struct dma_chan *chan; @@ -1402,66 +1298,43 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, */ return -EINVAL; - BUG_ON(host->dma_ch != -1 || host->dma2 != -1); + BUG_ON(host->dma_ch != -1); chan = omap_hsmmc_get_dma_chan(host, data); - if (!chan) { - ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), - "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); - if (ret != 0) { - dev_err(mmc_dev(host->mmc), - "%s: omap_request_dma() failed with %d\n", - mmc_hostname(host->mmc), ret); - return ret; - } - ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, - mmc_dev(host->mmc)); - if (ret) - return ret; - - host->dma_ch = dma_ch; - host->dma_sg_idx = 0; - omap_hsmmc_config_dma_params(host, data, data->sg); - } else { - struct dma_slave_config cfg; - struct dma_async_tx_descriptor *tx; + cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA; + cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA; + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.src_maxburst = data->blksz / 4; + cfg.dst_maxburst = data->blksz / 4; - cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA; - cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA; - cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - cfg.src_maxburst = data->blksz / 4; - cfg.dst_maxburst = data->blksz / 4; - - ret = dmaengine_slave_config(chan, &cfg); - if (ret) - return ret; + ret = dmaengine_slave_config(chan, &cfg); + if (ret) + return ret; - ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, - chan->device->dev); - if (ret) - return ret; + ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, chan); + if (ret) + return ret; - tx = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, - data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx) { - dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); - /* FIXME: cleanup */ - return -1; - } + tx = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, + data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) { + dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); + /* FIXME: cleanup */ + return -1; + } - tx->callback = omap_hsmmc_dma_callback; - tx->callback_param = host; + tx->callback = omap_hsmmc_dma_callback; + tx->callback_param = host; - /* Does not fail */ - dmaengine_submit(tx); + /* Does not fail */ + dmaengine_submit(tx); - host->dma2 = 1; + host->dma_ch = 1; - dma_async_issue_pending(chan); - } + dma_async_issue_pending(chan); return 0; } @@ -1543,14 +1416,11 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct omap_hsmmc_host *host = mmc_priv(mmc); struct mmc_data *data = mrq->data; - if (host->use_dma) { + if (host->use_dma && data->host_cookie) { struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data); - struct device *dev = c ? c->device->dev : mmc_dev(mmc); - if (data->host_cookie) - dma_unmap_sg(dev, - data->sg, data->sg_len, - omap_hsmmc_get_dma_dir(host, data)); + dma_unmap_sg(c->device->dev, data->sg, data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); data->host_cookie = 0; } } @@ -1567,10 +1437,9 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, if (host->use_dma) { struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data); - struct device *dev = c ? c->device->dev : mmc_dev(mmc); if (omap_hsmmc_pre_dma_transfer(host, mrq->data, - &host->next_data, dev)) + &host->next_data, c)) mrq->data->host_cookie = 0; } } @@ -1584,7 +1453,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) int err; BUG_ON(host->req_in_progress); - BUG_ON(host->dma_ch != -1 || host->dma2 != -1); + BUG_ON(host->dma_ch != -1); if (host->protect_card) { if (host->reqs_blocked < 3) { /* @@ -1897,6 +1766,8 @@ static inline struct omap_mmc_platform_data } #endif +extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param); + static int __devinit omap_hsmmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; @@ -1905,6 +1776,8 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) struct resource *res; int ret, irq; const struct of_device_id *match; + dma_cap_mask_t mask; + unsigned tx_req, rx_req; match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); if (match) { @@ -1949,9 +1822,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) host->pdata = pdata; host->dev = &pdev->dev; host->use_dma = 1; - host->dev->dma_mask = &pdata->dma_mask; host->dma_ch = -1; - host->dma2 = -1; host->irq = irq; host->slot_id = 0; host->mapbase = res->start + pdata->reg_offset; @@ -2039,36 +1910,28 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n"); goto err_irq; } - host->dma_line_tx = res->start; + tx_req = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); if (!res) { dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n"); goto err_irq; } - host->dma_line_rx = res->start; + rx_req = res->start; - { - dma_cap_mask_t mask; - unsigned sig; - extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param); - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); -#if 1 - sig = host->dma_line_rx; - host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &sig); - if (!host->rx_chan) { - dev_warn(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", sig); - } -#endif -#if 1 - sig = host->dma_line_tx; - host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &sig); - if (!host->tx_chan) { - dev_warn(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", sig); - } -#endif + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req); + if (!host->rx_chan) { + dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req); + goto err_irq; + } + + host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req); + if (!host->tx_chan) { + dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req); + goto err_irq; } /* Request IRQ for MMC operations */ -- GitLab From 3451c06754b5777d227aa99f85c35bdfabac3ca0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 21 Apr 2012 22:35:42 +0100 Subject: [PATCH 4818/5711] mmc: omap: add DMA engine support Add DMA engine support to the OMAP driver. This supplements the private DMA API implementation contained within this driver, and the driver can be switched at build time between using DMA engine and the private DMA API. Tested-by: Tony Lindgren Acked-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/omap.c | 199 ++++++++++++++++++++++++++++++++-- drivers/mmc/host/omap_hsmmc.c | 3 +- 2 files changed, 190 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 3e8dcf8d2e05..25e7efee5733 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -17,10 +17,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -99,6 +101,8 @@ struct mmc_omap_host; +#define USE_DMA_PRIVATE + struct mmc_omap_slot { int id; unsigned int vdd; @@ -128,6 +132,10 @@ struct mmc_omap_host { unsigned char id; /* 16xx chips have 2 MMC blocks */ struct clk * iclk; struct clk * fclk; + struct dma_chan *dma_rx; + u32 dma_rx_burst; + struct dma_chan *dma_tx; + u32 dma_tx_burst; struct resource *mem_res; void __iomem *virt_base; unsigned int phys_base; @@ -153,12 +161,14 @@ struct mmc_omap_host { unsigned use_dma:1; unsigned brs_received:1, dma_done:1; - unsigned dma_is_read:1; unsigned dma_in_use:1; +#ifdef USE_DMA_PRIVATE + unsigned dma_is_read:1; int dma_ch; - spinlock_t dma_lock; struct timer_list dma_timer; unsigned dma_len; +#endif + spinlock_t dma_lock; struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; struct mmc_omap_slot *current_slot; @@ -406,18 +416,32 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data, int abort) { enum dma_data_direction dma_data_dir; + struct device *dev = mmc_dev(host->mmc); + struct dma_chan *c; +#ifdef USE_DMA_PRIVATE BUG_ON(host->dma_ch < 0); if (data->error) omap_stop_dma(host->dma_ch); /* Release DMA channel lazily */ mod_timer(&host->dma_timer, jiffies + HZ); - if (data->flags & MMC_DATA_WRITE) +#endif + if (data->flags & MMC_DATA_WRITE) { dma_data_dir = DMA_TO_DEVICE; - else + c = host->dma_tx; + } else { dma_data_dir = DMA_FROM_DEVICE; - dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, - dma_data_dir); + c = host->dma_rx; + } + if (c) { + if (data->error) { + dmaengine_terminate_all(c); + /* Claim nothing transferred on error... */ + data->bytes_xfered = 0; + } + dev = c->device->dev; + } + dma_unmap_sg(dev, data->sg, host->sg_len, dma_data_dir); } static void mmc_omap_send_stop_work(struct work_struct *work) @@ -524,6 +548,7 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) mmc_omap_xfer_done(host, data); } +#ifdef USE_DMA_PRIVATE static void mmc_omap_dma_timer(unsigned long data) { @@ -533,6 +558,7 @@ mmc_omap_dma_timer(unsigned long data) omap_free_dma(host->dma_ch); host->dma_ch = -1; } +#endif static void mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) @@ -891,6 +917,18 @@ static void mmc_omap_cover_handler(unsigned long param) jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY)); } +static void mmc_omap_dma_callback(void *priv) +{ + struct mmc_omap_host *host = priv; + struct mmc_data *data = host->data; + + /* If we got to the end of DMA, assume everything went well */ + data->bytes_xfered += data->blocks * data->blksz; + + mmc_omap_dma_done(host, data); +} + +#ifdef USE_DMA_PRIVATE /* Prepare to transfer the next segment of a scatterlist */ static void mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) @@ -1045,6 +1083,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data return 0; } +#endif static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) { @@ -1117,6 +1156,80 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) } host->sg_idx = 0; + if (use_dma) { + enum dma_data_direction dma_data_dir; + struct dma_async_tx_descriptor *tx; + struct dma_chan *c; + u32 burst, *bp; + u16 buf; + + /* + * FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx + * and 24xx. Use 16 or 32 word frames when the + * blocksize is at least that large. Blocksize is + * usually 512 bytes; but not for some SD reads. + */ + burst = cpu_is_omap15xx() ? 32 : 64; + if (burst > data->blksz) + burst = data->blksz; + + burst >>= 1; + + if (data->flags & MMC_DATA_WRITE) { + c = host->dma_tx; + bp = &host->dma_tx_burst; + buf = 0x0f80 | (burst - 1) << 0; + dma_data_dir = DMA_TO_DEVICE; + } else { + c = host->dma_rx; + bp = &host->dma_rx_burst; + buf = 0x800f | (burst - 1) << 8; + dma_data_dir = DMA_FROM_DEVICE; + } + + if (!c) + goto use_pio; + + /* Only reconfigure if we have a different burst size */ + if (*bp != burst) { + struct dma_slave_config cfg; + + cfg.src_addr = host->phys_base + OMAP_MMC_REG(host, DATA); + cfg.dst_addr = host->phys_base + OMAP_MMC_REG(host, DATA); + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + cfg.src_maxburst = burst; + cfg.dst_maxburst = burst; + + if (dmaengine_slave_config(c, &cfg)) + goto use_pio; + + *bp = burst; + } + + host->sg_len = dma_map_sg(c->device->dev, data->sg, sg_len, + dma_data_dir); + if (host->sg_len == 0) + goto use_pio; + + tx = dmaengine_prep_slave_sg(c, data->sg, host->sg_len, + data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) + goto use_pio; + + OMAP_MMC_WRITE(host, BUF, buf); + + tx->callback = mmc_omap_dma_callback; + tx->callback_param = host; + dmaengine_submit(tx); + host->brs_received = 0; + host->dma_done = 0; + host->dma_in_use = 1; + return; + } + use_pio: +#ifdef USE_DMA_PRIVATE if (use_dma) { if (mmc_omap_get_dma_channel(host, data) == 0) { enum dma_data_direction dma_data_dir; @@ -1136,6 +1249,9 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) } else use_dma = 0; } +#else + use_dma = 0; +#endif /* Revert to PIO? */ if (!use_dma) { @@ -1157,8 +1273,17 @@ static void mmc_omap_start_request(struct mmc_omap_host *host, /* only touch fifo AFTER the controller readies it */ mmc_omap_prepare_data(host, req); mmc_omap_start_command(host, req->cmd); - if (host->dma_in_use) - omap_start_dma(host->dma_ch); + if (host->dma_in_use) { + struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ? + host->dma_tx : host->dma_rx; + + if (c) + dma_async_issue_pending(c); +#ifdef USE_DMA_PRIVATE + else + omap_start_dma(host->dma_ch); +#endif + } } static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) @@ -1400,6 +1525,8 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; struct mmc_omap_host *host = NULL; struct resource *res; + dma_cap_mask_t mask; + unsigned sig; int i, ret = 0; int irq; @@ -1439,7 +1566,9 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); spin_lock_init(&host->dma_lock); +#ifdef USE_DMA_PRIVATE setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host); +#endif spin_lock_init(&host->slot_lock); init_waitqueue_head(&host->slot_wq); @@ -1452,8 +1581,10 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) host->irq = irq; host->use_dma = 1; +#ifdef USE_DMA_PRIVATE host->dev->dma_mask = &pdata->dma_mask; host->dma_ch = -1; +#endif host->irq = irq; host->phys_base = host->mem_res->start; @@ -1474,9 +1605,48 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) goto err_free_iclk; } + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + host->dma_tx_burst = -1; + host->dma_rx_burst = -1; + + if (cpu_is_omap24xx()) + sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX; + else + sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX; + host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); +#if 0 + if (!host->dma_tx) { + dev_err(host->dev, "unable to obtain TX DMA engine channel %u\n", + sig); + goto err_dma; + } +#else + if (!host->dma_tx) + dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", + sig); +#endif + if (cpu_is_omap24xx()) + sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX; + else + sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX; + host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); +#if 0 + if (!host->dma_rx) { + dev_err(host->dev, "unable to obtain RX DMA engine channel %u\n", + sig); + goto err_dma; + } +#else + if (!host->dma_rx) + dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", + sig); +#endif + ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); if (ret) - goto err_free_fclk; + goto err_free_dma; if (pdata->init != NULL) { ret = pdata->init(&pdev->dev); @@ -1510,7 +1680,11 @@ err_plat_cleanup: pdata->cleanup(&pdev->dev); err_free_irq: free_irq(host->irq, host); -err_free_fclk: +err_free_dma: + if (host->dma_tx) + dma_release_channel(host->dma_tx); + if (host->dma_rx) + dma_release_channel(host->dma_rx); clk_put(host->fclk); err_free_iclk: clk_disable(host->iclk); @@ -1545,6 +1719,11 @@ static int __devexit mmc_omap_remove(struct platform_device *pdev) clk_disable(host->iclk); clk_put(host->iclk); + if (host->dma_tx) + dma_release_channel(host->dma_tx); + if (host->dma_rx) + dma_release_channel(host->dma_rx); + iounmap(host->virt_base); release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2b2c98773f15..2338703746a4 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1766,8 +1767,6 @@ static inline struct omap_mmc_platform_data } #endif -extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param); - static int __devinit omap_hsmmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; -- GitLab From 4e078fbd581a92fa26ba2def4ac8f2a633cdcb5b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 21 Apr 2012 22:41:10 +0100 Subject: [PATCH 4819/5711] mmc: omap: remove private DMA API implementation Remove the private DMA API implementation from omap, making it use entirely the DMA engine API. Tested-by: Tony Lindgren Signed-off-by: Russell King --- drivers/mmc/host/omap.c | 235 +--------------------------------------- 1 file changed, 6 insertions(+), 229 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 25e7efee5733..50e08f03aa65 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -101,8 +101,6 @@ struct mmc_omap_host; -#define USE_DMA_PRIVATE - struct mmc_omap_slot { int id; unsigned int vdd; @@ -162,12 +160,6 @@ struct mmc_omap_host { unsigned use_dma:1; unsigned brs_received:1, dma_done:1; unsigned dma_in_use:1; -#ifdef USE_DMA_PRIVATE - unsigned dma_is_read:1; - int dma_ch; - struct timer_list dma_timer; - unsigned dma_len; -#endif spinlock_t dma_lock; struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; @@ -419,13 +411,6 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data, struct device *dev = mmc_dev(host->mmc); struct dma_chan *c; -#ifdef USE_DMA_PRIVATE - BUG_ON(host->dma_ch < 0); - if (data->error) - omap_stop_dma(host->dma_ch); - /* Release DMA channel lazily */ - mod_timer(&host->dma_timer, jiffies + HZ); -#endif if (data->flags & MMC_DATA_WRITE) { dma_data_dir = DMA_TO_DEVICE; c = host->dma_tx; @@ -548,18 +533,6 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) mmc_omap_xfer_done(host, data); } -#ifdef USE_DMA_PRIVATE -static void -mmc_omap_dma_timer(unsigned long data) -{ - struct mmc_omap_host *host = (struct mmc_omap_host *) data; - - BUG_ON(host->dma_ch < 0); - omap_free_dma(host->dma_ch); - host->dma_ch = -1; -} -#endif - static void mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) { @@ -928,163 +901,6 @@ static void mmc_omap_dma_callback(void *priv) mmc_omap_dma_done(host, data); } -#ifdef USE_DMA_PRIVATE -/* Prepare to transfer the next segment of a scatterlist */ -static void -mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) -{ - int dma_ch = host->dma_ch; - unsigned long data_addr; - u16 buf, frame; - u32 count; - struct scatterlist *sg = &data->sg[host->sg_idx]; - int src_port = 0; - int dst_port = 0; - int sync_dev = 0; - - data_addr = host->phys_base + OMAP_MMC_REG(host, DATA); - frame = data->blksz; - count = sg_dma_len(sg); - - if ((data->blocks == 1) && (count > data->blksz)) - count = frame; - - host->dma_len = count; - - /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. - * Use 16 or 32 word frames when the blocksize is at least that large. - * Blocksize is usually 512 bytes; but not for some SD reads. - */ - if (cpu_is_omap15xx() && frame > 32) - frame = 32; - else if (frame > 64) - frame = 64; - count /= frame; - frame >>= 1; - - if (!(data->flags & MMC_DATA_WRITE)) { - buf = 0x800f | ((frame - 1) << 8); - - if (cpu_class_is_omap1()) { - src_port = OMAP_DMA_PORT_TIPB; - dst_port = OMAP_DMA_PORT_EMIFF; - } - if (cpu_is_omap24xx()) - sync_dev = OMAP24XX_DMA_MMC1_RX; - - omap_set_dma_src_params(dma_ch, src_port, - OMAP_DMA_AMODE_CONSTANT, - data_addr, 0, 0); - omap_set_dma_dest_params(dma_ch, dst_port, - OMAP_DMA_AMODE_POST_INC, - sg_dma_address(sg), 0, 0); - omap_set_dma_dest_data_pack(dma_ch, 1); - omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); - } else { - buf = 0x0f80 | ((frame - 1) << 0); - - if (cpu_class_is_omap1()) { - src_port = OMAP_DMA_PORT_EMIFF; - dst_port = OMAP_DMA_PORT_TIPB; - } - if (cpu_is_omap24xx()) - sync_dev = OMAP24XX_DMA_MMC1_TX; - - omap_set_dma_dest_params(dma_ch, dst_port, - OMAP_DMA_AMODE_CONSTANT, - data_addr, 0, 0); - omap_set_dma_src_params(dma_ch, src_port, - OMAP_DMA_AMODE_POST_INC, - sg_dma_address(sg), 0, 0); - omap_set_dma_src_data_pack(dma_ch, 1); - omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); - } - - /* Max limit for DMA frame count is 0xffff */ - BUG_ON(count > 0xffff); - - OMAP_MMC_WRITE(host, BUF, buf); - omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, - frame, count, OMAP_DMA_SYNC_FRAME, - sync_dev, 0); -} - -/* A scatterlist segment completed */ -static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) -{ - struct mmc_omap_host *host = (struct mmc_omap_host *) data; - struct mmc_data *mmcdat = host->data; - - if (unlikely(host->dma_ch < 0)) { - dev_err(mmc_dev(host->mmc), - "DMA callback while DMA not enabled\n"); - return; - } - /* FIXME: We really should do something to _handle_ the errors */ - if (ch_status & OMAP1_DMA_TOUT_IRQ) { - dev_err(mmc_dev(host->mmc),"DMA timeout\n"); - return; - } - if (ch_status & OMAP_DMA_DROP_IRQ) { - dev_err(mmc_dev(host->mmc), "DMA sync error\n"); - return; - } - if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { - return; - } - mmcdat->bytes_xfered += host->dma_len; - host->sg_idx++; - if (host->sg_idx < host->sg_len) { - mmc_omap_prepare_dma(host, host->data); - omap_start_dma(host->dma_ch); - } else - mmc_omap_dma_done(host, host->data); -} - -static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data) -{ - const char *dma_dev_name; - int sync_dev, dma_ch, is_read, r; - - is_read = !(data->flags & MMC_DATA_WRITE); - del_timer_sync(&host->dma_timer); - if (host->dma_ch >= 0) { - if (is_read == host->dma_is_read) - return 0; - omap_free_dma(host->dma_ch); - host->dma_ch = -1; - } - - if (is_read) { - if (host->id == 0) { - sync_dev = OMAP_DMA_MMC_RX; - dma_dev_name = "MMC1 read"; - } else { - sync_dev = OMAP_DMA_MMC2_RX; - dma_dev_name = "MMC2 read"; - } - } else { - if (host->id == 0) { - sync_dev = OMAP_DMA_MMC_TX; - dma_dev_name = "MMC1 write"; - } else { - sync_dev = OMAP_DMA_MMC2_TX; - dma_dev_name = "MMC2 write"; - } - } - r = omap_request_dma(sync_dev, dma_dev_name, mmc_omap_dma_cb, - host, &dma_ch); - if (r != 0) { - dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r); - return r; - } - host->dma_ch = dma_ch; - host->dma_is_read = is_read; - - return 0; -} -#endif - static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) { u16 reg; @@ -1229,38 +1045,13 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) return; } use_pio: -#ifdef USE_DMA_PRIVATE - if (use_dma) { - if (mmc_omap_get_dma_channel(host, data) == 0) { - enum dma_data_direction dma_data_dir; - - if (data->flags & MMC_DATA_WRITE) - dma_data_dir = DMA_TO_DEVICE; - else - dma_data_dir = DMA_FROM_DEVICE; - - host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, - sg_len, dma_data_dir); - host->total_bytes_left = 0; - mmc_omap_prepare_dma(host, req->data); - host->brs_received = 0; - host->dma_done = 0; - host->dma_in_use = 1; - } else - use_dma = 0; - } -#else - use_dma = 0; -#endif /* Revert to PIO? */ - if (!use_dma) { - OMAP_MMC_WRITE(host, BUF, 0x1f1f); - host->total_bytes_left = data->blocks * block_size; - host->sg_len = sg_len; - mmc_omap_sg_to_buf(host); - host->dma_in_use = 0; - } + OMAP_MMC_WRITE(host, BUF, 0x1f1f); + host->total_bytes_left = data->blocks * block_size; + host->sg_len = sg_len; + mmc_omap_sg_to_buf(host); + host->dma_in_use = 0; } static void mmc_omap_start_request(struct mmc_omap_host *host, @@ -1277,12 +1068,7 @@ static void mmc_omap_start_request(struct mmc_omap_host *host, struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ? host->dma_tx : host->dma_rx; - if (c) - dma_async_issue_pending(c); -#ifdef USE_DMA_PRIVATE - else - omap_start_dma(host->dma_ch); -#endif + dma_async_issue_pending(c); } } @@ -1566,9 +1352,6 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); spin_lock_init(&host->dma_lock); -#ifdef USE_DMA_PRIVATE - setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host); -#endif spin_lock_init(&host->slot_lock); init_waitqueue_head(&host->slot_wq); @@ -1579,13 +1362,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) host->id = pdev->id; host->mem_res = res; host->irq = irq; - host->use_dma = 1; -#ifdef USE_DMA_PRIVATE - host->dev->dma_mask = &pdata->dma_mask; - host->dma_ch = -1; -#endif - host->irq = irq; host->phys_base = host->mem_res->start; host->virt_base = ioremap(res->start, resource_size(res)); -- GitLab From 8a23fa1b95b2e3878c16dcc4e18976bc46dd970b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 18 Apr 2012 10:43:18 +0100 Subject: [PATCH 4820/5711] ARM: omap: remove mmc platform data dma_mask and initialization DMAengine uses the DMA engine device structure when mapping/unmapping memory for DMA, so the MMC devices do not need their DMA masks initialized (this reflects hardware: the MMC device is not the device doing DMA.) Tested-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/board-h2-mmc.c | 1 - arch/arm/mach-omap1/board-h3-mmc.c | 1 - arch/arm/mach-omap1/board-nokia770.c | 1 - arch/arm/mach-omap2/board-n8x0.c | 1 - arch/arm/mach-omap2/hsmmc.c | 1 - arch/arm/plat-omap/include/plat/mmc.h | 2 -- 6 files changed, 7 deletions(-) diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c index da0e37d40823..e1362ce48497 100644 --- a/arch/arm/mach-omap1/board-h2-mmc.c +++ b/arch/arm/mach-omap1/board-h2-mmc.c @@ -54,7 +54,6 @@ static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, .init = mmc_late_init, .cleanup = mmc_cleanup, - .dma_mask = 0xffffffff, .slots[0] = { .set_power = mmc_set_power, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index f8242aa9b763..c74daace8cd6 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -36,7 +36,6 @@ static int mmc_set_power(struct device *dev, int slot, int power_on, */ static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, - .dma_mask = 0xffffffff, .slots[0] = { .set_power = mmc_set_power, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 7212ae97f44a..c54b45f32638 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -185,7 +185,6 @@ static int nokia770_mmc_get_cover_state(struct device *dev, int slot) static struct omap_mmc_platform_data nokia770_mmc2_data = { .nr_slots = 1, - .dma_mask = 0xffffffff, .max_freq = 12000000, .slots[0] = { .set_power = nokia770_mmc_set_power, diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 2c5d0ed75285..677357ff61ac 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -468,7 +468,6 @@ static struct omap_mmc_platform_data mmc1_data = { .cleanup = n8x0_mmc_cleanup, .shutdown = n8x0_mmc_shutdown, .max_freq = 24000000, - .dma_mask = 0xffffffff, .slots[0] = { .wires = 4, .set_power = n8x0_mmc_set_power, diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index be697d4e0843..a9675d8d1822 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -315,7 +315,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].caps = c->caps; mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; - mmc->dma_mask = 0xffffffff; mmc->max_freq = c->max_freq; if (cpu_is_omap44xx()) mmc->reg_offset = OMAP4_MMC_REG_OFFSET; diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index 5493bd95da5e..eb3e4d555343 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -81,8 +81,6 @@ struct omap_mmc_platform_data { /* Return context loss count due to PM states changing */ int (*get_context_loss_count)(struct device *dev); - u64 dma_mask; - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; -- GitLab From 53741ed8f0a3fc646576b6d7adf563f403ba6c03 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 23 Apr 2012 13:51:48 +0100 Subject: [PATCH 4821/5711] spi: omap2-mcspi: add DMA engine support Add DMA engine support to the OMAP SPI driver. This supplements the private DMA API implementation contained within this driver, and the driver can be independently switched at build time between using DMA engine and the private DMA API for the transmit and receive sides. Tested-by: Shubhrajyoti Acked-by: Grant Likely Acked-by: Linus Walleij Signed-off-by: Russell King --- drivers/spi/spi-omap2-mcspi.c | 181 ++++++++++++++++++++++++++++------ 1 file changed, 150 insertions(+), 31 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 0c73dd4f43a0..9fdb7a9ae03f 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#define USE_DMA_ENGINE_RX +#define USE_DMA_ENGINE_TX #include #include @@ -28,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -93,6 +97,8 @@ /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; int dma_tx_channel; int dma_rx_channel; @@ -300,6 +306,30 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) return 0; } +static void omap2_mcspi_rx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_rx_completion); + + /* We must disable the DMA RX request */ + omap2_mcspi_set_dma_req(spi, 1, 0); +} + +static void omap2_mcspi_tx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_tx_completion); + + /* We must disable the DMA TX request */ + omap2_mcspi_set_dma_req(spi, 0, 0); +} + static unsigned omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) { @@ -314,6 +344,9 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) u8 * rx; const u8 * tx; void __iomem *chstat_reg; + struct dma_slave_config cfg; + enum dma_slave_buswidth width; + unsigned es; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -321,6 +354,71 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + if (cs->word_len <= 8) { + width = DMA_SLAVE_BUSWIDTH_1_BYTE; + es = 1; + } else if (cs->word_len <= 16) { + width = DMA_SLAVE_BUSWIDTH_2_BYTES; + es = 2; + } else { + width = DMA_SLAVE_BUSWIDTH_4_BYTES; + es = 4; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; + cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; + cfg.src_addr_width = width; + cfg.dst_addr_width = width; + cfg.src_maxburst = 1; + cfg.dst_maxburst = 1; + + if (xfer->tx_buf && mcspi_dma->dma_tx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + + dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->tx_dma; + sg_dma_len(&sg) = xfer->len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_tx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + + if (xfer->rx_buf && mcspi_dma->dma_rx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + size_t len = xfer->len - es; + + dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + + if (l & OMAP2_MCSPI_CHCONF_TURBO) + len -= es; + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->rx_dma; + sg_dma_len(&sg) = len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_rx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + count = xfer->len; c = count; word_len = cs->word_len; @@ -342,7 +440,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) element_count = count >> 2; } - if (tx != NULL) { + if (tx != NULL && mcspi_dma->dma_tx_channel != -1) { omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, data_type, element_count, 1, OMAP_DMA_SYNC_ELEMENT, @@ -357,7 +455,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) xfer->tx_dma, 0, 0); } - if (rx != NULL) { + if (rx != NULL && mcspi_dma->dma_rx_channel != -1) { elements = element_count - 1; if (l & OMAP2_MCSPI_CHCONF_TURBO) elements--; @@ -377,12 +475,18 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) } if (tx != NULL) { - omap_start_dma(mcspi_dma->dma_tx_channel); + if (mcspi_dma->dma_tx) + dma_async_issue_pending(mcspi_dma->dma_tx); + else + omap_start_dma(mcspi_dma->dma_tx_channel); omap2_mcspi_set_dma_req(spi, 0, 1); } if (rx != NULL) { - omap_start_dma(mcspi_dma->dma_rx_channel); + if (mcspi_dma->dma_rx) + dma_async_issue_pending(mcspi_dma->dma_rx); + else + omap_start_dma(mcspi_dma->dma_rx_channel); omap2_mcspi_set_dma_req(spi, 1, 1); } @@ -406,7 +510,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); omap2_mcspi_set_enable(spi, 0); + elements = element_count - 1; + if (l & OMAP2_MCSPI_CHCONF_TURBO) { + elements--; if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) & OMAP2_MCSPI_CHSTAT_RXS)) { @@ -725,32 +832,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_rx_completion); - - /* We must disable the DMA RX request */ - omap2_mcspi_set_dma_req(spi, 1, 0); + omap2_mcspi_rx_callback(data); } static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_tx_completion); - - /* We must disable the DMA TX request */ - omap2_mcspi_set_dma_req(spi, 0, 0); + omap2_mcspi_tx_callback(data); } static int omap2_mcspi_request_dma(struct spi_device *spi) @@ -758,17 +845,43 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) struct spi_master *master = spi->master; struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; + dma_cap_mask_t mask; + unsigned sig; mcspi = spi_master_get_devdata(master); mcspi_dma = mcspi->dma_channels + spi->chip_select; + init_completion(&mcspi_dma->dma_rx_completion); + init_completion(&mcspi_dma->dma_tx_completion); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); +#ifdef USE_DMA_ENGINE_RX + sig = mcspi_dma->dma_rx_sync_dev; + mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_rx) { + dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX", omap2_mcspi_dma_rx_callback, spi, &mcspi_dma->dma_rx_channel)) { dev_err(&spi->dev, "no RX DMA channel for McSPI\n"); return -EAGAIN; } +#endif +#ifdef USE_DMA_ENGINE_TX + sig = mcspi_dma->dma_tx_sync_dev; + mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_tx) { + dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n"); + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX", omap2_mcspi_dma_tx_callback, spi, &mcspi_dma->dma_tx_channel)) { @@ -777,9 +890,7 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); return -EAGAIN; } - - init_completion(&mcspi_dma->dma_rx_completion); - init_completion(&mcspi_dma->dma_tx_completion); +#endif return 0; } @@ -812,8 +923,8 @@ static int omap2_mcspi_setup(struct spi_device *spi) list_add_tail(&cs->node, &ctx->cs); } - if (mcspi_dma->dma_rx_channel == -1 - || mcspi_dma->dma_tx_channel == -1) { + if ((!mcspi_dma->dma_rx && mcspi_dma->dma_rx_channel == -1) || + (!mcspi_dma->dma_tx && mcspi_dma->dma_tx_channel == -1)) { ret = omap2_mcspi_request_dma(spi); if (ret < 0) return ret; @@ -848,6 +959,14 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) if (spi->chip_select < spi->master->num_chipselect) { mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + if (mcspi_dma->dma_rx) { + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + } + if (mcspi_dma->dma_tx) { + dma_release_channel(mcspi_dma->dma_tx); + mcspi_dma->dma_tx = NULL; + } if (mcspi_dma->dma_rx_channel != -1) { omap_free_dma(mcspi_dma->dma_rx_channel); mcspi_dma->dma_rx_channel = -1; -- GitLab From 8c7494a501bd45e1bf1599a51331b1c210cadbae Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 23 Apr 2012 13:56:25 +0100 Subject: [PATCH 4822/5711] spi: omap2-mcspi: remove private DMA API implementation Remove the private DMA API implementation from spi-omap2-mcspi.c, making it use entirely the DMA engine API. Acked-by: Grant Likely Signed-off-by: Russell King --- drivers/spi/spi-omap2-mcspi.c | 104 ++-------------------------------- 1 file changed, 5 insertions(+), 99 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 9fdb7a9ae03f..26a99ae9a599 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -20,8 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#define USE_DMA_ENGINE_RX -#define USE_DMA_ENGINE_TX #include #include @@ -43,7 +41,6 @@ #include -#include #include #include @@ -99,8 +96,6 @@ struct omap2_mcspi_dma { struct dma_chan *dma_tx; struct dma_chan *dma_rx; - int dma_tx_channel; - int dma_rx_channel; int dma_tx_sync_dev; int dma_rx_sync_dev; @@ -336,9 +331,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) struct omap2_mcspi *mcspi; struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi_dma *mcspi_dma; - unsigned int count, c; - unsigned long base, tx_reg, rx_reg; - int word_len, data_type, element_count; + unsigned int count; + int word_len, element_count; int elements = 0; u32 l; u8 * rx; @@ -420,73 +414,26 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) } count = xfer->len; - c = count; word_len = cs->word_len; - base = cs->phys; - tx_reg = base + OMAP2_MCSPI_TX0; - rx_reg = base + OMAP2_MCSPI_RX0; rx = xfer->rx_buf; tx = xfer->tx_buf; if (word_len <= 8) { - data_type = OMAP_DMA_DATA_TYPE_S8; element_count = count; } else if (word_len <= 16) { - data_type = OMAP_DMA_DATA_TYPE_S16; element_count = count >> 1; } else /* word_len <= 32 */ { - data_type = OMAP_DMA_DATA_TYPE_S32; element_count = count >> 2; } - if (tx != NULL && mcspi_dma->dma_tx_channel != -1) { - omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, - data_type, element_count, 1, - OMAP_DMA_SYNC_ELEMENT, - mcspi_dma->dma_tx_sync_dev, 0); - - omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0, - OMAP_DMA_AMODE_CONSTANT, - tx_reg, 0, 0); - - omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0, - OMAP_DMA_AMODE_POST_INC, - xfer->tx_dma, 0, 0); - } - - if (rx != NULL && mcspi_dma->dma_rx_channel != -1) { - elements = element_count - 1; - if (l & OMAP2_MCSPI_CHCONF_TURBO) - elements--; - - omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel, - data_type, elements, 1, - OMAP_DMA_SYNC_ELEMENT, - mcspi_dma->dma_rx_sync_dev, 1); - - omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0, - OMAP_DMA_AMODE_CONSTANT, - rx_reg, 0, 0); - - omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0, - OMAP_DMA_AMODE_POST_INC, - xfer->rx_dma, 0, 0); - } - if (tx != NULL) { - if (mcspi_dma->dma_tx) - dma_async_issue_pending(mcspi_dma->dma_tx); - else - omap_start_dma(mcspi_dma->dma_tx_channel); + dma_async_issue_pending(mcspi_dma->dma_tx); omap2_mcspi_set_dma_req(spi, 0, 1); } if (rx != NULL) { - if (mcspi_dma->dma_rx) - dma_async_issue_pending(mcspi_dma->dma_rx); - else - omap_start_dma(mcspi_dma->dma_rx_channel); + dma_async_issue_pending(mcspi_dma->dma_rx); omap2_mcspi_set_dma_req(spi, 1, 1); } @@ -830,16 +777,6 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, return 0; } -static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data) -{ - omap2_mcspi_rx_callback(data); -} - -static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data) -{ - omap2_mcspi_tx_callback(data); -} - static int omap2_mcspi_request_dma(struct spi_device *spi) { struct spi_master *master = spi->master; @@ -856,23 +793,13 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); -#ifdef USE_DMA_ENGINE_RX sig = mcspi_dma->dma_rx_sync_dev; mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); if (!mcspi_dma->dma_rx) { dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); return -EAGAIN; } -#else - if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX", - omap2_mcspi_dma_rx_callback, spi, - &mcspi_dma->dma_rx_channel)) { - dev_err(&spi->dev, "no RX DMA channel for McSPI\n"); - return -EAGAIN; - } -#endif -#ifdef USE_DMA_ENGINE_TX sig = mcspi_dma->dma_tx_sync_dev; mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); if (!mcspi_dma->dma_tx) { @@ -881,16 +808,6 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) mcspi_dma->dma_rx = NULL; return -EAGAIN; } -#else - if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX", - omap2_mcspi_dma_tx_callback, spi, - &mcspi_dma->dma_tx_channel)) { - omap_free_dma(mcspi_dma->dma_rx_channel); - mcspi_dma->dma_rx_channel = -1; - dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); - return -EAGAIN; - } -#endif return 0; } @@ -923,8 +840,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) list_add_tail(&cs->node, &ctx->cs); } - if ((!mcspi_dma->dma_rx && mcspi_dma->dma_rx_channel == -1) || - (!mcspi_dma->dma_tx && mcspi_dma->dma_tx_channel == -1)) { + if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { ret = omap2_mcspi_request_dma(spi); if (ret < 0) return ret; @@ -967,14 +883,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) dma_release_channel(mcspi_dma->dma_tx); mcspi_dma->dma_tx = NULL; } - if (mcspi_dma->dma_rx_channel != -1) { - omap_free_dma(mcspi_dma->dma_rx_channel); - mcspi_dma->dma_rx_channel = -1; - } - if (mcspi_dma->dma_tx_channel != -1) { - omap_free_dma(mcspi_dma->dma_tx_channel); - mcspi_dma->dma_tx_channel = -1; - } } } @@ -1293,7 +1201,6 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) break; } - mcspi->dma_channels[i].dma_rx_channel = -1; mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; sprintf(dma_ch_name, "tx%d", i); dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, @@ -1304,7 +1211,6 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) break; } - mcspi->dma_channels[i].dma_tx_channel = -1; mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; } -- GitLab From 763e735910922382c2577e820e2a51df0a7cf17c Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Apr 2012 00:16:00 +0100 Subject: [PATCH 4823/5711] mtd: omap2: add DMA engine support Add DMA engine support to the OMAP2 NAND driver. This supplements the private DMA API implementation contained within this driver, and the driver can be independently switched at build time between using DMA engine and the private DMA API. Tested-by: Grazvydas Ignotas Signed-off-by: Russell King --- drivers/mtd/nand/omap2.c | 92 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index d7f681d0c9b9..2912d6c93635 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -123,6 +125,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; struct completion comp; + struct dma_chan *dma; int dma_ch; int gpmc_irq; enum { @@ -345,6 +348,10 @@ static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) { complete((struct completion *) data); } +static void omap_nand_dma_callback(void *data) +{ + complete((struct completion *) data); +} /* * omap_nand_dma_transfer: configer and start dma transfer @@ -382,6 +389,56 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, addr = page_address(p1) + ((size_t)addr & ~PAGE_MASK); } + if (info->dma) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + unsigned n; + + sg_init_one(&sg, addr, len); + n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); + if (n == 0) { + dev_err(&info->pdev->dev, + "Couldn't DMA map a %d byte buffer\n", len); + goto out_copy; + } + + tx = dmaengine_prep_slave_sg(info->dma, &sg, n, + is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) { + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); + goto out_copy; + } + tx->callback = omap_nand_dma_callback; + tx->callback_param = &info->comp; + dmaengine_submit(tx); + + /* configure and start prefetch transfer */ + ret = gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); + if (ret) { + /* PFPW engine is busy, use cpu copy method */ + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); + goto out_copy; + } + + init_completion(&info->comp); + dma_async_issue_pending(info->dma); + + /* setup and start DMA using dma_addr */ + wait_for_completion(&info->comp); + tim = 0; + limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) + cpu_relax(); + + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); + + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); + return 0; + } + dma_addr = dma_map_single(&info->pdev->dev, addr, len, dir); if (dma_mapping_error(&info->pdev->dev, dma_addr)) { dev_err(&info->pdev->dev, @@ -414,7 +471,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, goto out_copy_unmap; init_completion(&info->comp); - omap_start_dma(info->dma_ch); /* setup and start DMA using dma_addr */ @@ -1164,6 +1220,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + dma_cap_mask_t mask; + unsigned sig; pdata = pdev->dev.platform_data; if (pdata == NULL) { @@ -1244,6 +1302,33 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) break; case NAND_OMAP_PREFETCH_DMA: + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + sig = OMAP24XX_DMA_GPMC; + info->dma = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!info->dma) { + dev_warn(&pdev->dev, "DMA engine request failed\n"); + } else { + struct dma_slave_config cfg; + int rc; + + memset(&cfg, 0, sizeof(cfg)); + cfg.src_addr = info->phys_base; + cfg.dst_addr = info->phys_base; + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.src_maxburst = 16; + cfg.dst_maxburst = 16; + rc = dmaengine_slave_config(info->dma, &cfg); + if (rc) { + dev_err(&pdev->dev, "DMA engine slave config failed: %d\n", + rc); + goto out_release_mem_region; + } + info->nand.read_buf = omap_read_buf_dma_pref; + info->nand.write_buf = omap_write_buf_dma_pref; + break; + } err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", omap_nand_dma_cb, &info->comp, &info->dma_ch); if (err < 0) { @@ -1358,6 +1443,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: + if (info->dma) + dma_release_channel(info->dma); release_mem_region(info->phys_base, NAND_IO_SIZE); out_free_info: kfree(info); @@ -1376,6 +1463,9 @@ static int omap_nand_remove(struct platform_device *pdev) if (info->dma_ch != -1) omap_free_dma(info->dma_ch); + if (info->dma) + dma_release_channel(info->dma); + if (info->gpmc_irq) free_irq(info->gpmc_irq, info); -- GitLab From 2df41d0533ad1a77f5914667a1699068bf83ae64 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Apr 2012 00:19:39 +0100 Subject: [PATCH 4824/5711] mtd: omap2: remove private DMA API implementation Remove the private DMA API implementation from nand/omap2.c making it use entirely the DMA engine API. Signed-off-by: Russell King --- drivers/mtd/nand/omap2.c | 136 ++++++++------------------------------- 1 file changed, 26 insertions(+), 110 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 2912d6c93635..e9309b3659e7 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -126,7 +126,6 @@ struct omap_nand_info { unsigned long phys_base; struct completion comp; struct dma_chan *dma; - int dma_ch; int gpmc_irq; enum { OMAP_NAND_IO_READ = 0, /* read */ @@ -339,15 +338,9 @@ static void omap_write_buf_pref(struct mtd_info *mtd, } /* - * omap_nand_dma_cb: callback on the completion of dma transfer - * @lch: logical channel - * @ch_satuts: channel status + * omap_nand_dma_callback: callback on the completion of dma transfer * @data: pointer to completion data structure */ -static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) -{ - complete((struct completion *) data); -} static void omap_nand_dma_callback(void *data) { complete((struct completion *) data); @@ -365,17 +358,13 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); + struct dma_async_tx_descriptor *tx; enum dma_data_direction dir = is_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma_addr_t dma_addr; - int ret; + struct scatterlist sg; unsigned long tim, limit; - - /* The fifo depth is 64 bytes max. - * But configure the FIFO-threahold to 32 to get a sync at each frame - * and frame length is 32 bytes. - */ - int buf_len = len >> 6; + unsigned n; + int ret; if (addr >= high_memory) { struct page *p1; @@ -389,89 +378,33 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, addr = page_address(p1) + ((size_t)addr & ~PAGE_MASK); } - if (info->dma) { - struct dma_async_tx_descriptor *tx; - struct scatterlist sg; - unsigned n; - - sg_init_one(&sg, addr, len); - n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); - if (n == 0) { - dev_err(&info->pdev->dev, - "Couldn't DMA map a %d byte buffer\n", len); - goto out_copy; - } - - tx = dmaengine_prep_slave_sg(info->dma, &sg, n, - is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx) { - dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); - goto out_copy; - } - tx->callback = omap_nand_dma_callback; - tx->callback_param = &info->comp; - dmaengine_submit(tx); - - /* configure and start prefetch transfer */ - ret = gpmc_prefetch_enable(info->gpmc_cs, - PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); - if (ret) { - /* PFPW engine is busy, use cpu copy method */ - dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); - goto out_copy; - } - - init_completion(&info->comp); - dma_async_issue_pending(info->dma); - - /* setup and start DMA using dma_addr */ - wait_for_completion(&info->comp); - tim = 0; - limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); - while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) - cpu_relax(); - - /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(info->gpmc_cs); - - dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); - return 0; - } - - dma_addr = dma_map_single(&info->pdev->dev, addr, len, dir); - if (dma_mapping_error(&info->pdev->dev, dma_addr)) { + sg_init_one(&sg, addr, len); + n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); + if (n == 0) { dev_err(&info->pdev->dev, "Couldn't DMA map a %d byte buffer\n", len); goto out_copy; } - if (is_write) { - omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - info->phys_base, 0, 0); - omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, - dma_addr, 0, 0); - omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S32, - 0x10, buf_len, OMAP_DMA_SYNC_FRAME, - OMAP24XX_DMA_GPMC, OMAP_DMA_DST_SYNC); - } else { - omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - info->phys_base, 0, 0); - omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, - dma_addr, 0, 0); - omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S32, - 0x10, buf_len, OMAP_DMA_SYNC_FRAME, - OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC); - } - /* configure and start prefetch transfer */ + tx = dmaengine_prep_slave_sg(info->dma, &sg, n, + is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) + goto out_copy_unmap; + + tx->callback = omap_nand_dma_callback; + tx->callback_param = &info->comp; + dmaengine_submit(tx); + + /* configure and start prefetch transfer */ ret = gpmc_prefetch_enable(info->gpmc_cs, - PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); + PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); if (ret) /* PFPW engine is busy, use cpu copy method */ goto out_copy_unmap; init_completion(&info->comp); - omap_start_dma(info->dma_ch); + dma_async_issue_pending(info->dma); /* setup and start DMA using dma_addr */ wait_for_completion(&info->comp); @@ -483,11 +416,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /* disable and stop the PFPW engine */ gpmc_prefetch_reset(info->gpmc_cs); - dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); return 0; out_copy_unmap: - dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); out_copy: if (info->nand.options & NAND_BUSWIDTH_16) is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len) @@ -1307,7 +1240,9 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) sig = OMAP24XX_DMA_GPMC; info->dma = dma_request_channel(mask, omap_dma_filter_fn, &sig); if (!info->dma) { - dev_warn(&pdev->dev, "DMA engine request failed\n"); + dev_err(&pdev->dev, "DMA engine request failed\n"); + err = -ENXIO; + goto out_release_mem_region; } else { struct dma_slave_config cfg; int rc; @@ -1327,22 +1262,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) } info->nand.read_buf = omap_read_buf_dma_pref; info->nand.write_buf = omap_write_buf_dma_pref; - break; - } - err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", - omap_nand_dma_cb, &info->comp, &info->dma_ch); - if (err < 0) { - info->dma_ch = -1; - dev_err(&pdev->dev, "DMA request failed!\n"); - goto out_release_mem_region; - } else { - omap_set_dma_dest_burst_mode(info->dma_ch, - OMAP_DMA_DATA_BURST_16); - omap_set_dma_src_burst_mode(info->dma_ch, - OMAP_DMA_DATA_BURST_16); - - info->nand.read_buf = omap_read_buf_dma_pref; - info->nand.write_buf = omap_write_buf_dma_pref; } break; @@ -1460,9 +1379,6 @@ static int omap_nand_remove(struct platform_device *pdev) omap3_free_bch(&info->mtd); platform_set_drvdata(pdev, NULL); - if (info->dma_ch != -1) - omap_free_dma(info->dma_ch); - if (info->dma) dma_release_channel(info->dma); -- GitLab From 4e1755bbb4857ea4c5a5e12927cbc04e843cb4d4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 23 Apr 2012 16:52:29 +0100 Subject: [PATCH 4825/5711] Add feature removal of old OMAP private DMA implementation Acked-by: Linus Walleij Acked-by: Tony Lindgren Acked-by: Santosh Shilimkar Signed-off-by: Russell King --- Documentation/feature-removal-schedule.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 56000b33340b..1f7ba3537a85 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -612,3 +612,14 @@ When: June 2013 Why: Unsupported/unmaintained/unused since 2.6 ---------------------------- + +What: OMAP private DMA implementation +When: 2013 +Why: We have a DMA engine implementation; all users should be updated + to use this rather than persisting with the old APIs. The old APIs + block merging the old DMA engine implementation into the DMA + engine driver. +Who: Russell King , + Santosh Shilimkar + +---------------------------- -- GitLab From 04e8c7bc2c1eda2d06ff6eb57a7df97e64d895e6 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 11 Jul 2012 17:51:40 +0100 Subject: [PATCH 4826/5711] ARM: 7464/1: mmc: omap_hsmmc: ensure probe returns error if DMA channel request fails If dma_request_channel() fails (e.g. because DMA enine is not built into the kernel), the return value from probe is zero causing the driver to be bound to the device even though probe failed. To fix, ensure that probe returns an error value when a DMA channel request fail. Signed-off-by: Kevin Hilman Signed-off-by: Russell King --- drivers/mmc/host/omap_hsmmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2338703746a4..823d21cb87c0 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1924,12 +1924,14 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req); if (!host->rx_chan) { dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req); + ret = -ENXIO; goto err_irq; } host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req); if (!host->tx_chan) { dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req); + ret = -ENXIO; goto err_irq; } -- GitLab From 89269ef1f0abc72c551198123e19cd4edfd43cf4 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 30 Jul 2012 17:59:48 +0100 Subject: [PATCH 4827/5711] ARM: 7481/1: OMAP2+: omap2plus_defconfig: enable OMAP DMA engine commit 13f30fc893e4610f67dd7a8b0b67aec02eac1775 Author: Russell King Date: Sat Apr 21 22:41:10 2012 +0100 mmc: omap: remove private DMA API implementation removed the private DMA API implementation from the OMAP mmc host to exclusively use the DMA engine API. Unfortunately OMAP MMC and High Speed MMC host drivers don't support poll mode and only works with DMA. Since omap2plus_defconfig doesn't enable this feature by default, the following error is happens on an IGEPv2 Rev.C (and probably on most OMAP boards with MMC support): [ 2.199981] omap_hsmmc omap_hsmmc.1: unable to obtain RX DMA engine channel 48 [ 2.215087] omap_hsmmc omap_hsmmc.0: unable to obtain RX DMA engine channel 62 Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/configs/omap2plus_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 9854ff4279e0..3b391b23bdda 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -194,6 +194,8 @@ CONFIG_MMC_OMAP_HS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_TWL92330=y CONFIG_RTC_DRV_TWL4030=y +CONFIG_DMADEVICES=y +CONFIG_DMA_OMAP=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -- GitLab From 4b1bf5871f7d59de6484cc887e205d6d2f1e6fbd Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Tue, 31 Jul 2012 04:39:30 -0700 Subject: [PATCH 4828/5711] thermal: Constify 'type' argument for the registration routine thermal_zone_device_register() does not modify 'type' argument, so it is safe to declare it as const. Otherwise, if we pass a const string, we are getting the ugly warning: CC drivers/power/power_supply_core.o drivers/power/power_supply_core.c: In function 'psy_register_thermal': drivers/power/power_supply_core.c:204:6: warning: passing argument 1 of 'thermal_zone_device_register' discards 'const' qualifier from pointer target type [enabled by default] include/linux/thermal.h:140:29: note: expected 'char *' but argument is of type 'const char *' Signed-off-by: Anton Vorontsov Acked-by: Jean Delvare --- drivers/thermal/thermal_sys.c | 2 +- include/linux/thermal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 5feb3353213f..32aa66d7d6b3 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -1173,7 +1173,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) * longer needed. The passive cooling formula uses tc1 and tc2 as described in * section 11.1.5.1 of the ACPI specification 3.0. */ -struct thermal_zone_device *thermal_zone_device_register(char *type, +struct thermal_zone_device *thermal_zone_device_register(const char *type, int trips, int mask, void *devdata, const struct thermal_zone_device_ops *ops, int tc1, int tc2, int passive_delay, int polling_delay) diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 6eaf9146c847..4821735f3e77 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -146,7 +146,7 @@ enum { }; #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) -struct thermal_zone_device *thermal_zone_device_register(char *, int, int, +struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, void *, const struct thermal_zone_device_ops *, int tc1, int tc2, int passive_freq, int polling_freq); void thermal_zone_device_unregister(struct thermal_zone_device *); -- GitLab From 0f26d0e0a715556270d85b7946b99546a2f92888 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Mon, 30 Jul 2012 22:44:41 -0500 Subject: [PATCH 4829/5711] kdb: Remove unused KDB_FLAG_ONLY_DO_DUMP This code cleanup was missed in the original kdb merge, and this code is simply not used at all. The code that was previously used to set the KDB_FLAG_ONLY_DO_DUMP was removed prior to the initial kdb merge. Signed-off-by: Jason Wessel --- include/linux/kdb.h | 2 -- kernel/debug/kdb/kdb_main.c | 15 +-------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/include/linux/kdb.h b/include/linux/kdb.h index 064725854db8..42d9e863a313 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h @@ -75,8 +75,6 @@ extern const char *kdb_diemsg; #define KDB_FLAG_CATASTROPHIC (1 << 1) /* A catastrophic event has occurred */ #define KDB_FLAG_CMD_INTERRUPT (1 << 2) /* Previous command was interrupted */ #define KDB_FLAG_NOIPI (1 << 3) /* Do not send IPIs */ -#define KDB_FLAG_ONLY_DO_DUMP (1 << 4) /* Only do a dump, used when - * kdb is off */ #define KDB_FLAG_NO_CONSOLE (1 << 5) /* No console is available, * kdb is disabled */ #define KDB_FLAG_NO_VT_CONSOLE (1 << 6) /* No VT console is available, do diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 1f91413edb87..31df1706b9a9 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -139,11 +139,10 @@ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); static char *__env[] = { #if defined(CONFIG_SMP) "PROMPT=[%d]kdb> ", - "MOREPROMPT=[%d]more> ", #else "PROMPT=kdb> ", - "MOREPROMPT=more> ", #endif + "MOREPROMPT=more> ", "RADIX=16", "MDCOUNT=8", /* lines of md output */ KDB_PLATFORM_ENV, @@ -1236,18 +1235,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, *cmdbuf = '\0'; *(cmd_hist[cmd_head]) = '\0'; - if (KDB_FLAG(ONLY_DO_DUMP)) { - /* kdb is off but a catastrophic error requires a dump. - * Take the dump and reboot. - * Turn on logging so the kdb output appears in the log - * buffer in the dump. - */ - const char *setargs[] = { "set", "LOGGING", "1" }; - kdb_set(2, setargs); - kdb_reboot(0, NULL); - /*NOTREACHED*/ - } - do_full_getstr: #if defined(CONFIG_SMP) snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), -- GitLab From 07cd27bbd4d07af6c3e24ae479316a69e7935e1e Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Mon, 30 Jul 2012 22:44:41 -0500 Subject: [PATCH 4830/5711] kdb: Remove cpu from the more prompt Having the CPU in the more prompt is completely redundent vs the standard kdb prompt, and it also wastes 32 bytes on the stack. Signed-off-by: Jason Wessel --- kernel/debug/kdb/kdb_io.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index bb9520f0f6ff..0a69d2adc4f3 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -715,9 +715,6 @@ kdb_printit: /* check for having reached the LINES number of printed lines */ if (kdb_nextline == linecount) { char buf1[16] = ""; -#if defined(CONFIG_SMP) - char buf2[32]; -#endif /* Watch out for recursion here. Any routine that calls * kdb_printf will come back through here. And kdb_read @@ -732,14 +729,6 @@ kdb_printit: if (moreprompt == NULL) moreprompt = "more> "; -#if defined(CONFIG_SMP) - if (strchr(moreprompt, '%')) { - sprintf(buf2, moreprompt, get_cpu()); - put_cpu(); - moreprompt = buf2; - } -#endif - kdb_input_flush(); c = console_drivers; -- GitLab From b10d22d6e8f76b9e94871aebe0fc62aab2748200 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 30 Jul 2012 04:58:10 -0700 Subject: [PATCH 4831/5711] kernel/debug: Make use of KGDB_REASON_NMI Currently kernel never set KGDB_REASON_NMI. We do now, when we enter KGDB/KDB from an NMI. This is not to be confused with kgdb_nmicallback(), NMI callback is an entry for the slave CPUs during CPUs roundup, but REASON_NMI is the entry for the master CPU. Signed-off-by: Anton Vorontsov Signed-off-by: Jason Wessel --- kernel/debug/kdb/kdb_debugger.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c index 8b68ce78ff17..be7b33b73d30 100644 --- a/kernel/debug/kdb/kdb_debugger.c +++ b/kernel/debug/kdb/kdb_debugger.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "kdb_private.h" #include "../debug_core.h" @@ -52,6 +53,9 @@ int kdb_stub(struct kgdb_state *ks) if (atomic_read(&kgdb_setting_breakpoint)) reason = KDB_REASON_KEYBOARD; + if (in_nmi()) + reason = KDB_REASON_NMI; + for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if ((bp->bp_enabled) && (bp->bp_addr == addr)) { reason = KDB_REASON_BREAK; -- GitLab From f96a4216e85050c0a9d41a41ecb0ae9d8e39b509 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 30 Jul 2012 16:06:42 +0100 Subject: [PATCH 4832/5711] USB: echi-dbgp: increase the controller wait time to come out of halt. The default 10 microsecond delay for the controller to come out of halt in dbgp_ehci_startup is too short, so increase it to 1 millisecond. This is based on emperical testing on various USB debug ports on modern machines such as a Lenovo X220i and an Ivybridge development platform that needed to wait ~450-950 microseconds. Cc: Signed-off-by: Colin Ian King Signed-off-by: Jason Wessel --- drivers/usb/early/ehci-dbgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 1fc8f1249806..347bb058e1ee 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void) writel(FLAG_CF, &ehci_regs->configured_flag); /* Wait until the controller is no longer halted */ - loop = 10; + loop = 1000; do { status = readl(&ehci_regs->status); if (!(status & STS_HALT)) -- GitLab From cba3345cc494ad286ca8823f44b2c16cae496679 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 31 Jul 2012 08:16:22 -0600 Subject: [PATCH 4833/5711] vfio: VFIO core VFIO is a secure user level driver for use with both virtual machines and user level drivers. VFIO makes use of IOMMU groups to ensure the isolation of devices in use, allowing unprivileged user access. It's intended that VFIO will replace KVM device assignment and UIO drivers (in cases where the target platform includes a sufficiently capable IOMMU). New in this version of VFIO is support for IOMMU groups managed through the IOMMU core as well as a rework of the API, removing the group merge interface. We now go back to a model more similar to original VFIO with UIOMMU support where the file descriptor obtained from /dev/vfio/vfio allows access to the IOMMU, but only after a group is added, avoiding the previous privilege issues with this type of model. IOMMU support is also now fully modular as IOMMUs have vastly different interface requirements on different platforms. VFIO users are able to query and initialize the IOMMU model of their choice. Please see the follow-on Documentation commit for further description and usage example. Signed-off-by: Alex Williamson --- Documentation/ioctl/ioctl-number.txt | 1 + MAINTAINERS | 8 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/vfio/Kconfig | 8 + drivers/vfio/Makefile | 1 + drivers/vfio/vfio.c | 1413 ++++++++++++++++++++++++++ include/linux/vfio.h | 367 +++++++ 8 files changed, 1801 insertions(+) create mode 100644 drivers/vfio/Kconfig create mode 100644 drivers/vfio/Makefile create mode 100644 drivers/vfio/vfio.c create mode 100644 include/linux/vfio.h diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 915f28c470e9..849b771c5e03 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -88,6 +88,7 @@ Code Seq#(hex) Include File Comments and kernel/power/user.c '8' all SNP8023 advanced NIC card +';' 64-7F linux/vfio.h '@' 00-0F linux/radeonfb.h conflict! '@' 00-0F drivers/video/aty/aty128fb.c conflict! 'A' 00-1F linux/apm_bios.h conflict! diff --git a/MAINTAINERS b/MAINTAINERS index fb036a062a5d..eceaab93811e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7411,6 +7411,14 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VFIO DRIVER +M: Alex Williamson +L: kvm@vger.kernel.org +S: Maintained +F: Documentation/vfio.txt +F: drivers/vfio/ +F: include/linux/vfio.h + VIDEOBUF2 FRAMEWORK M: Pawel Osciak M: Marek Szyprowski diff --git a/drivers/Kconfig b/drivers/Kconfig index 805c432c9439..ece958d3762e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -112,6 +112,8 @@ source "drivers/auxdisplay/Kconfig" source "drivers/uio/Kconfig" +source "drivers/vfio/Kconfig" + source "drivers/vlynq/Kconfig" source "drivers/virtio/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index bd36f09f2246..5b421840c48d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ obj-y += firewire/ obj-$(CONFIG_UIO) += uio/ +obj-$(CONFIG_VFIO) += vfio/ obj-y += cdrom/ obj-y += auxdisplay/ obj-$(CONFIG_PCCARD) += pcmcia/ diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig new file mode 100644 index 000000000000..9acb1e729bd6 --- /dev/null +++ b/drivers/vfio/Kconfig @@ -0,0 +1,8 @@ +menuconfig VFIO + tristate "VFIO Non-Privileged userspace driver framework" + depends on IOMMU_API + help + VFIO provides a framework for secure userspace device drivers. + See Documentation/vfio.txt for more details. + + If you don't know what to do here, say N. diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile new file mode 100644 index 000000000000..7500a67a42a0 --- /dev/null +++ b/drivers/vfio/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VFIO) += vfio.o diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c new file mode 100644 index 000000000000..052e310aed72 --- /dev/null +++ b/drivers/vfio/vfio.c @@ -0,0 +1,1413 @@ +/* + * VFIO core + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "0.3" +#define DRIVER_AUTHOR "Alex Williamson " +#define DRIVER_DESC "VFIO - User Level meta-driver" + +static struct vfio { + struct class *class; + struct list_head iommu_drivers_list; + struct mutex iommu_drivers_lock; + struct list_head group_list; + struct idr group_idr; + struct mutex group_lock; + struct cdev group_cdev; + struct device *dev; + dev_t devt; + struct cdev cdev; + wait_queue_head_t release_q; +} vfio; + +struct vfio_iommu_driver { + const struct vfio_iommu_driver_ops *ops; + struct list_head vfio_next; +}; + +struct vfio_container { + struct kref kref; + struct list_head group_list; + struct mutex group_lock; + struct vfio_iommu_driver *iommu_driver; + void *iommu_data; +}; + +struct vfio_group { + struct kref kref; + int minor; + atomic_t container_users; + struct iommu_group *iommu_group; + struct vfio_container *container; + struct list_head device_list; + struct mutex device_lock; + struct device *dev; + struct notifier_block nb; + struct list_head vfio_next; + struct list_head container_next; +}; + +struct vfio_device { + struct kref kref; + struct device *dev; + const struct vfio_device_ops *ops; + struct vfio_group *group; + struct list_head group_next; + void *device_data; +}; + +/** + * IOMMU driver registration + */ +int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops) +{ + struct vfio_iommu_driver *driver, *tmp; + + driver = kzalloc(sizeof(*driver), GFP_KERNEL); + if (!driver) + return -ENOMEM; + + driver->ops = ops; + + mutex_lock(&vfio.iommu_drivers_lock); + + /* Check for duplicates */ + list_for_each_entry(tmp, &vfio.iommu_drivers_list, vfio_next) { + if (tmp->ops == ops) { + mutex_unlock(&vfio.iommu_drivers_lock); + kfree(driver); + return -EINVAL; + } + } + + list_add(&driver->vfio_next, &vfio.iommu_drivers_list); + + mutex_unlock(&vfio.iommu_drivers_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(vfio_register_iommu_driver); + +void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops) +{ + struct vfio_iommu_driver *driver; + + mutex_lock(&vfio.iommu_drivers_lock); + list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) { + if (driver->ops == ops) { + list_del(&driver->vfio_next); + mutex_unlock(&vfio.iommu_drivers_lock); + kfree(driver); + return; + } + } + mutex_unlock(&vfio.iommu_drivers_lock); +} +EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); + +/** + * Group minor allocation/free - both called with vfio.group_lock held + */ +static int vfio_alloc_group_minor(struct vfio_group *group) +{ + int ret, minor; + +again: + if (unlikely(idr_pre_get(&vfio.group_idr, GFP_KERNEL) == 0)) + return -ENOMEM; + + /* index 0 is used by /dev/vfio/vfio */ + ret = idr_get_new_above(&vfio.group_idr, group, 1, &minor); + if (ret == -EAGAIN) + goto again; + if (ret || minor > MINORMASK) { + if (minor > MINORMASK) + idr_remove(&vfio.group_idr, minor); + return -ENOSPC; + } + + return minor; +} + +static void vfio_free_group_minor(int minor) +{ + idr_remove(&vfio.group_idr, minor); +} + +static int vfio_iommu_group_notifier(struct notifier_block *nb, + unsigned long action, void *data); +static void vfio_group_get(struct vfio_group *group); + +/** + * Container objects - containers are created when /dev/vfio/vfio is + * opened, but their lifecycle extends until the last user is done, so + * it's freed via kref. Must support container/group/device being + * closed in any order. + */ +static void vfio_container_get(struct vfio_container *container) +{ + kref_get(&container->kref); +} + +static void vfio_container_release(struct kref *kref) +{ + struct vfio_container *container; + container = container_of(kref, struct vfio_container, kref); + + kfree(container); +} + +static void vfio_container_put(struct vfio_container *container) +{ + kref_put(&container->kref, vfio_container_release); +} + +/** + * Group objects - create, release, get, put, search + */ +static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) +{ + struct vfio_group *group, *tmp; + struct device *dev; + int ret, minor; + + group = kzalloc(sizeof(*group), GFP_KERNEL); + if (!group) + return ERR_PTR(-ENOMEM); + + kref_init(&group->kref); + INIT_LIST_HEAD(&group->device_list); + mutex_init(&group->device_lock); + atomic_set(&group->container_users, 0); + group->iommu_group = iommu_group; + + group->nb.notifier_call = vfio_iommu_group_notifier; + + /* + * blocking notifiers acquire a rwsem around registering and hold + * it around callback. Therefore, need to register outside of + * vfio.group_lock to avoid A-B/B-A contention. Our callback won't + * do anything unless it can find the group in vfio.group_list, so + * no harm in registering early. + */ + ret = iommu_group_register_notifier(iommu_group, &group->nb); + if (ret) { + kfree(group); + return ERR_PTR(ret); + } + + mutex_lock(&vfio.group_lock); + + minor = vfio_alloc_group_minor(group); + if (minor < 0) { + mutex_unlock(&vfio.group_lock); + kfree(group); + return ERR_PTR(minor); + } + + /* Did we race creating this group? */ + list_for_each_entry(tmp, &vfio.group_list, vfio_next) { + if (tmp->iommu_group == iommu_group) { + vfio_group_get(tmp); + vfio_free_group_minor(minor); + mutex_unlock(&vfio.group_lock); + kfree(group); + return tmp; + } + } + + dev = device_create(vfio.class, NULL, MKDEV(MAJOR(vfio.devt), minor), + group, "%d", iommu_group_id(iommu_group)); + if (IS_ERR(dev)) { + vfio_free_group_minor(minor); + mutex_unlock(&vfio.group_lock); + kfree(group); + return (struct vfio_group *)dev; /* ERR_PTR */ + } + + group->minor = minor; + group->dev = dev; + + list_add(&group->vfio_next, &vfio.group_list); + + mutex_unlock(&vfio.group_lock); + + return group; +} + +static void vfio_group_release(struct kref *kref) +{ + struct vfio_group *group = container_of(kref, struct vfio_group, kref); + + WARN_ON(!list_empty(&group->device_list)); + + device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); + list_del(&group->vfio_next); + vfio_free_group_minor(group->minor); + + mutex_unlock(&vfio.group_lock); + + /* + * Unregister outside of lock. A spurious callback is harmless now + * that the group is no longer in vfio.group_list. + */ + iommu_group_unregister_notifier(group->iommu_group, &group->nb); + + kfree(group); +} + +static void vfio_group_put(struct vfio_group *group) +{ + mutex_lock(&vfio.group_lock); + /* + * Release needs to unlock to unregister the notifier, so only + * unlock if not released. + */ + if (!kref_put(&group->kref, vfio_group_release)) + mutex_unlock(&vfio.group_lock); +} + +/* Assume group_lock or group reference is held */ +static void vfio_group_get(struct vfio_group *group) +{ + kref_get(&group->kref); +} + +/* + * Not really a try as we will sleep for mutex, but we need to make + * sure the group pointer is valid under lock and get a reference. + */ +static struct vfio_group *vfio_group_try_get(struct vfio_group *group) +{ + struct vfio_group *target = group; + + mutex_lock(&vfio.group_lock); + list_for_each_entry(group, &vfio.group_list, vfio_next) { + if (group == target) { + vfio_group_get(group); + mutex_unlock(&vfio.group_lock); + return group; + } + } + mutex_unlock(&vfio.group_lock); + + return NULL; +} + +static +struct vfio_group *vfio_group_get_from_iommu(struct iommu_group *iommu_group) +{ + struct vfio_group *group; + + mutex_lock(&vfio.group_lock); + list_for_each_entry(group, &vfio.group_list, vfio_next) { + if (group->iommu_group == iommu_group) { + vfio_group_get(group); + mutex_unlock(&vfio.group_lock); + return group; + } + } + mutex_unlock(&vfio.group_lock); + + return NULL; +} + +static struct vfio_group *vfio_group_get_from_minor(int minor) +{ + struct vfio_group *group; + + mutex_lock(&vfio.group_lock); + group = idr_find(&vfio.group_idr, minor); + if (!group) { + mutex_unlock(&vfio.group_lock); + return NULL; + } + vfio_group_get(group); + mutex_unlock(&vfio.group_lock); + + return group; +} + +/** + * Device objects - create, release, get, put, search + */ +static +struct vfio_device *vfio_group_create_device(struct vfio_group *group, + struct device *dev, + const struct vfio_device_ops *ops, + void *device_data) +{ + struct vfio_device *device; + int ret; + + device = kzalloc(sizeof(*device), GFP_KERNEL); + if (!device) + return ERR_PTR(-ENOMEM); + + kref_init(&device->kref); + device->dev = dev; + device->group = group; + device->ops = ops; + device->device_data = device_data; + + ret = dev_set_drvdata(dev, device); + if (ret) { + kfree(device); + return ERR_PTR(ret); + } + + /* No need to get group_lock, caller has group reference */ + vfio_group_get(group); + + mutex_lock(&group->device_lock); + list_add(&device->group_next, &group->device_list); + mutex_unlock(&group->device_lock); + + return device; +} + +static void vfio_device_release(struct kref *kref) +{ + struct vfio_device *device = container_of(kref, + struct vfio_device, kref); + struct vfio_group *group = device->group; + + mutex_lock(&group->device_lock); + list_del(&device->group_next); + mutex_unlock(&group->device_lock); + + dev_set_drvdata(device->dev, NULL); + + kfree(device); + + /* vfio_del_group_dev may be waiting for this device */ + wake_up(&vfio.release_q); +} + +/* Device reference always implies a group reference */ +static void vfio_device_put(struct vfio_device *device) +{ + kref_put(&device->kref, vfio_device_release); + vfio_group_put(device->group); +} + +static void vfio_device_get(struct vfio_device *device) +{ + vfio_group_get(device->group); + kref_get(&device->kref); +} + +static struct vfio_device *vfio_group_get_device(struct vfio_group *group, + struct device *dev) +{ + struct vfio_device *device; + + mutex_lock(&group->device_lock); + list_for_each_entry(device, &group->device_list, group_next) { + if (device->dev == dev) { + vfio_device_get(device); + mutex_unlock(&group->device_lock); + return device; + } + } + mutex_unlock(&group->device_lock); + return NULL; +} + +/* + * Whitelist some drivers that we know are safe (no dma) or just sit on + * a device. It's not always practical to leave a device within a group + * driverless as it could get re-bound to something unsafe. + */ +static const char * const vfio_driver_whitelist[] = { "pci-stub" }; + +static bool vfio_whitelisted_driver(struct device_driver *drv) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) { + if (!strcmp(drv->name, vfio_driver_whitelist[i])) + return true; + } + + return false; +} + +/* + * A vfio group is viable for use by userspace if all devices are either + * driver-less or bound to a vfio or whitelisted driver. We test the + * latter by the existence of a struct vfio_device matching the dev. + */ +static int vfio_dev_viable(struct device *dev, void *data) +{ + struct vfio_group *group = data; + struct vfio_device *device; + + if (!dev->driver || vfio_whitelisted_driver(dev->driver)) + return 0; + + device = vfio_group_get_device(group, dev); + if (device) { + vfio_device_put(device); + return 0; + } + + return -EINVAL; +} + +/** + * Async device support + */ +static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) +{ + struct vfio_device *device; + + /* Do we already know about it? We shouldn't */ + device = vfio_group_get_device(group, dev); + if (WARN_ON_ONCE(device)) { + vfio_device_put(device); + return 0; + } + + /* Nothing to do for idle groups */ + if (!atomic_read(&group->container_users)) + return 0; + + /* TODO Prevent device auto probing */ + WARN("Device %s added to live group %d!\n", dev_name(dev), + iommu_group_id(group->iommu_group)); + + return 0; +} + +static int vfio_group_nb_del_dev(struct vfio_group *group, struct device *dev) +{ + struct vfio_device *device; + + /* + * Expect to fall out here. If a device was in use, it would + * have been bound to a vfio sub-driver, which would have blocked + * in .remove at vfio_del_group_dev. Sanity check that we no + * longer track the device, so it's safe to remove. + */ + device = vfio_group_get_device(group, dev); + if (likely(!device)) + return 0; + + WARN("Device %s removed from live group %d!\n", dev_name(dev), + iommu_group_id(group->iommu_group)); + + vfio_device_put(device); + return 0; +} + +static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev) +{ + /* We don't care what happens when the group isn't in use */ + if (!atomic_read(&group->container_users)) + return 0; + + return vfio_dev_viable(dev, group); +} + +static int vfio_iommu_group_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct vfio_group *group = container_of(nb, struct vfio_group, nb); + struct device *dev = data; + + /* + * Need to go through a group_lock lookup to get a reference or + * we risk racing a group being removed. Leave a WARN_ON for + * debuging, but if the group no longer exists, a spurious notify + * is harmless. + */ + group = vfio_group_try_get(group); + if (WARN_ON(!group)) + return NOTIFY_OK; + + switch (action) { + case IOMMU_GROUP_NOTIFY_ADD_DEVICE: + vfio_group_nb_add_dev(group, dev); + break; + case IOMMU_GROUP_NOTIFY_DEL_DEVICE: + vfio_group_nb_del_dev(group, dev); + break; + case IOMMU_GROUP_NOTIFY_BIND_DRIVER: + pr_debug("%s: Device %s, group %d binding to driver\n", + __func__, dev_name(dev), + iommu_group_id(group->iommu_group)); + break; + case IOMMU_GROUP_NOTIFY_BOUND_DRIVER: + pr_debug("%s: Device %s, group %d bound to driver %s\n", + __func__, dev_name(dev), + iommu_group_id(group->iommu_group), dev->driver->name); + BUG_ON(vfio_group_nb_verify(group, dev)); + break; + case IOMMU_GROUP_NOTIFY_UNBIND_DRIVER: + pr_debug("%s: Device %s, group %d unbinding from driver %s\n", + __func__, dev_name(dev), + iommu_group_id(group->iommu_group), dev->driver->name); + break; + case IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER: + pr_debug("%s: Device %s, group %d unbound from driver\n", + __func__, dev_name(dev), + iommu_group_id(group->iommu_group)); + /* + * XXX An unbound device in a live group is ok, but we'd + * really like to avoid the above BUG_ON by preventing other + * drivers from binding to it. Once that occurs, we have to + * stop the system to maintain isolation. At a minimum, we'd + * want a toggle to disable driver auto probe for this device. + */ + break; + } + + vfio_group_put(group); + return NOTIFY_OK; +} + +/** + * VFIO driver API + */ +int vfio_add_group_dev(struct device *dev, + const struct vfio_device_ops *ops, void *device_data) +{ + struct iommu_group *iommu_group; + struct vfio_group *group; + struct vfio_device *device; + + iommu_group = iommu_group_get(dev); + if (!iommu_group) + return -EINVAL; + + group = vfio_group_get_from_iommu(iommu_group); + if (!group) { + group = vfio_create_group(iommu_group); + if (IS_ERR(group)) { + iommu_group_put(iommu_group); + return PTR_ERR(group); + } + } + + device = vfio_group_get_device(group, dev); + if (device) { + WARN(1, "Device %s already exists on group %d\n", + dev_name(dev), iommu_group_id(iommu_group)); + vfio_device_put(device); + vfio_group_put(group); + iommu_group_put(iommu_group); + return -EBUSY; + } + + device = vfio_group_create_device(group, dev, ops, device_data); + if (IS_ERR(device)) { + vfio_group_put(group); + iommu_group_put(iommu_group); + return PTR_ERR(device); + } + + /* + * Added device holds reference to iommu_group and vfio_device + * (which in turn holds reference to vfio_group). Drop extra + * group reference used while acquiring device. + */ + vfio_group_put(group); + + return 0; +} +EXPORT_SYMBOL_GPL(vfio_add_group_dev); + +/* Test whether a struct device is present in our tracking */ +static bool vfio_dev_present(struct device *dev) +{ + struct iommu_group *iommu_group; + struct vfio_group *group; + struct vfio_device *device; + + iommu_group = iommu_group_get(dev); + if (!iommu_group) + return false; + + group = vfio_group_get_from_iommu(iommu_group); + if (!group) { + iommu_group_put(iommu_group); + return false; + } + + device = vfio_group_get_device(group, dev); + if (!device) { + vfio_group_put(group); + iommu_group_put(iommu_group); + return false; + } + + vfio_device_put(device); + vfio_group_put(group); + iommu_group_put(iommu_group); + return true; +} + +/* + * Decrement the device reference count and wait for the device to be + * removed. Open file descriptors for the device... */ +void *vfio_del_group_dev(struct device *dev) +{ + struct vfio_device *device = dev_get_drvdata(dev); + struct vfio_group *group = device->group; + struct iommu_group *iommu_group = group->iommu_group; + void *device_data = device->device_data; + + vfio_device_put(device); + + /* TODO send a signal to encourage this to be released */ + wait_event(vfio.release_q, !vfio_dev_present(dev)); + + iommu_group_put(iommu_group); + + return device_data; +} +EXPORT_SYMBOL_GPL(vfio_del_group_dev); + +/** + * VFIO base fd, /dev/vfio/vfio + */ +static long vfio_ioctl_check_extension(struct vfio_container *container, + unsigned long arg) +{ + struct vfio_iommu_driver *driver = container->iommu_driver; + long ret = 0; + + switch (arg) { + /* No base extensions yet */ + default: + /* + * If no driver is set, poll all registered drivers for + * extensions and return the first positive result. If + * a driver is already set, further queries will be passed + * only to that driver. + */ + if (!driver) { + mutex_lock(&vfio.iommu_drivers_lock); + list_for_each_entry(driver, &vfio.iommu_drivers_list, + vfio_next) { + if (!try_module_get(driver->ops->owner)) + continue; + + ret = driver->ops->ioctl(NULL, + VFIO_CHECK_EXTENSION, + arg); + module_put(driver->ops->owner); + if (ret > 0) + break; + } + mutex_unlock(&vfio.iommu_drivers_lock); + } else + ret = driver->ops->ioctl(container->iommu_data, + VFIO_CHECK_EXTENSION, arg); + } + + return ret; +} + +/* hold container->group_lock */ +static int __vfio_container_attach_groups(struct vfio_container *container, + struct vfio_iommu_driver *driver, + void *data) +{ + struct vfio_group *group; + int ret = -ENODEV; + + list_for_each_entry(group, &container->group_list, container_next) { + ret = driver->ops->attach_group(data, group->iommu_group); + if (ret) + goto unwind; + } + + return ret; + +unwind: + list_for_each_entry_continue_reverse(group, &container->group_list, + container_next) { + driver->ops->detach_group(data, group->iommu_group); + } + + return ret; +} + +static long vfio_ioctl_set_iommu(struct vfio_container *container, + unsigned long arg) +{ + struct vfio_iommu_driver *driver; + long ret = -ENODEV; + + mutex_lock(&container->group_lock); + + /* + * The container is designed to be an unprivileged interface while + * the group can be assigned to specific users. Therefore, only by + * adding a group to a container does the user get the privilege of + * enabling the iommu, which may allocate finite resources. There + * is no unset_iommu, but by removing all the groups from a container, + * the container is deprivileged and returns to an unset state. + */ + if (list_empty(&container->group_list) || container->iommu_driver) { + mutex_unlock(&container->group_lock); + return -EINVAL; + } + + mutex_lock(&vfio.iommu_drivers_lock); + list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) { + void *data; + + if (!try_module_get(driver->ops->owner)) + continue; + + /* + * The arg magic for SET_IOMMU is the same as CHECK_EXTENSION, + * so test which iommu driver reported support for this + * extension and call open on them. We also pass them the + * magic, allowing a single driver to support multiple + * interfaces if they'd like. + */ + if (driver->ops->ioctl(NULL, VFIO_CHECK_EXTENSION, arg) <= 0) { + module_put(driver->ops->owner); + continue; + } + + /* module reference holds the driver we're working on */ + mutex_unlock(&vfio.iommu_drivers_lock); + + data = driver->ops->open(arg); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + module_put(driver->ops->owner); + goto skip_drivers_unlock; + } + + ret = __vfio_container_attach_groups(container, driver, data); + if (!ret) { + container->iommu_driver = driver; + container->iommu_data = data; + } else { + driver->ops->release(data); + module_put(driver->ops->owner); + } + + goto skip_drivers_unlock; + } + + mutex_unlock(&vfio.iommu_drivers_lock); +skip_drivers_unlock: + mutex_unlock(&container->group_lock); + + return ret; +} + +static long vfio_fops_unl_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + struct vfio_container *container = filep->private_data; + struct vfio_iommu_driver *driver; + void *data; + long ret = -EINVAL; + + if (!container) + return ret; + + driver = container->iommu_driver; + data = container->iommu_data; + + switch (cmd) { + case VFIO_GET_API_VERSION: + ret = VFIO_API_VERSION; + break; + case VFIO_CHECK_EXTENSION: + ret = vfio_ioctl_check_extension(container, arg); + break; + case VFIO_SET_IOMMU: + ret = vfio_ioctl_set_iommu(container, arg); + break; + default: + if (driver) /* passthrough all unrecognized ioctls */ + ret = driver->ops->ioctl(data, cmd, arg); + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long vfio_fops_compat_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + arg = (unsigned long)compat_ptr(arg); + return vfio_fops_unl_ioctl(filep, cmd, arg); +} +#endif /* CONFIG_COMPAT */ + +static int vfio_fops_open(struct inode *inode, struct file *filep) +{ + struct vfio_container *container; + + container = kzalloc(sizeof(*container), GFP_KERNEL); + if (!container) + return -ENOMEM; + + INIT_LIST_HEAD(&container->group_list); + mutex_init(&container->group_lock); + kref_init(&container->kref); + + filep->private_data = container; + + return 0; +} + +static int vfio_fops_release(struct inode *inode, struct file *filep) +{ + struct vfio_container *container = filep->private_data; + + filep->private_data = NULL; + + vfio_container_put(container); + + return 0; +} + +/* + * Once an iommu driver is set, we optionally pass read/write/mmap + * on to the driver, allowing management interfaces beyond ioctl. + */ +static ssize_t vfio_fops_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + struct vfio_container *container = filep->private_data; + struct vfio_iommu_driver *driver = container->iommu_driver; + + if (unlikely(!driver || !driver->ops->read)) + return -EINVAL; + + return driver->ops->read(container->iommu_data, buf, count, ppos); +} + +static ssize_t vfio_fops_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct vfio_container *container = filep->private_data; + struct vfio_iommu_driver *driver = container->iommu_driver; + + if (unlikely(!driver || !driver->ops->write)) + return -EINVAL; + + return driver->ops->write(container->iommu_data, buf, count, ppos); +} + +static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct vfio_container *container = filep->private_data; + struct vfio_iommu_driver *driver = container->iommu_driver; + + if (unlikely(!driver || !driver->ops->mmap)) + return -EINVAL; + + return driver->ops->mmap(container->iommu_data, vma); +} + +static const struct file_operations vfio_fops = { + .owner = THIS_MODULE, + .open = vfio_fops_open, + .release = vfio_fops_release, + .read = vfio_fops_read, + .write = vfio_fops_write, + .unlocked_ioctl = vfio_fops_unl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vfio_fops_compat_ioctl, +#endif + .mmap = vfio_fops_mmap, +}; + +/** + * VFIO Group fd, /dev/vfio/$GROUP + */ +static void __vfio_group_unset_container(struct vfio_group *group) +{ + struct vfio_container *container = group->container; + struct vfio_iommu_driver *driver; + + mutex_lock(&container->group_lock); + + driver = container->iommu_driver; + if (driver) + driver->ops->detach_group(container->iommu_data, + group->iommu_group); + + group->container = NULL; + list_del(&group->container_next); + + /* Detaching the last group deprivileges a container, remove iommu */ + if (driver && list_empty(&container->group_list)) { + driver->ops->release(container->iommu_data); + module_put(driver->ops->owner); + container->iommu_driver = NULL; + container->iommu_data = NULL; + } + + mutex_unlock(&container->group_lock); + + vfio_container_put(container); +} + +/* + * VFIO_GROUP_UNSET_CONTAINER should fail if there are other users or + * if there was no container to unset. Since the ioctl is called on + * the group, we know that still exists, therefore the only valid + * transition here is 1->0. + */ +static int vfio_group_unset_container(struct vfio_group *group) +{ + int users = atomic_cmpxchg(&group->container_users, 1, 0); + + if (!users) + return -EINVAL; + if (users != 1) + return -EBUSY; + + __vfio_group_unset_container(group); + + return 0; +} + +/* + * When removing container users, anything that removes the last user + * implicitly removes the group from the container. That is, if the + * group file descriptor is closed, as well as any device file descriptors, + * the group is free. + */ +static void vfio_group_try_dissolve_container(struct vfio_group *group) +{ + if (0 == atomic_dec_if_positive(&group->container_users)) + __vfio_group_unset_container(group); +} + +static int vfio_group_set_container(struct vfio_group *group, int container_fd) +{ + struct file *filep; + struct vfio_container *container; + struct vfio_iommu_driver *driver; + int ret = 0; + + if (atomic_read(&group->container_users)) + return -EINVAL; + + filep = fget(container_fd); + if (!filep) + return -EBADF; + + /* Sanity check, is this really our fd? */ + if (filep->f_op != &vfio_fops) { + fput(filep); + return -EINVAL; + } + + container = filep->private_data; + WARN_ON(!container); /* fget ensures we don't race vfio_release */ + + mutex_lock(&container->group_lock); + + driver = container->iommu_driver; + if (driver) { + ret = driver->ops->attach_group(container->iommu_data, + group->iommu_group); + if (ret) + goto unlock_out; + } + + group->container = container; + list_add(&group->container_next, &container->group_list); + + /* Get a reference on the container and mark a user within the group */ + vfio_container_get(container); + atomic_inc(&group->container_users); + +unlock_out: + mutex_unlock(&container->group_lock); + fput(filep); + + return ret; +} + +static bool vfio_group_viable(struct vfio_group *group) +{ + return (iommu_group_for_each_dev(group->iommu_group, + group, vfio_dev_viable) == 0); +} + +static const struct file_operations vfio_device_fops; + +static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) +{ + struct vfio_device *device; + struct file *filep; + int ret = -ENODEV; + + if (0 == atomic_read(&group->container_users) || + !group->container->iommu_driver || !vfio_group_viable(group)) + return -EINVAL; + + mutex_lock(&group->device_lock); + list_for_each_entry(device, &group->device_list, group_next) { + if (strcmp(dev_name(device->dev), buf)) + continue; + + ret = device->ops->open(device->device_data); + if (ret) + break; + /* + * We can't use anon_inode_getfd() because we need to modify + * the f_mode flags directly to allow more than just ioctls + */ + ret = get_unused_fd(); + if (ret < 0) { + device->ops->release(device->device_data); + break; + } + + filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops, + device, O_RDWR); + if (IS_ERR(filep)) { + put_unused_fd(ret); + ret = PTR_ERR(filep); + device->ops->release(device->device_data); + break; + } + + /* + * TODO: add an anon_inode interface to do this. + * Appears to be missing by lack of need rather than + * explicitly prevented. Now there's need. + */ + filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + + fd_install(ret, filep); + + vfio_device_get(device); + atomic_inc(&group->container_users); + break; + } + mutex_unlock(&group->device_lock); + + return ret; +} + +static long vfio_group_fops_unl_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + struct vfio_group *group = filep->private_data; + long ret = -ENOTTY; + + switch (cmd) { + case VFIO_GROUP_GET_STATUS: + { + struct vfio_group_status status; + unsigned long minsz; + + minsz = offsetofend(struct vfio_group_status, flags); + + if (copy_from_user(&status, (void __user *)arg, minsz)) + return -EFAULT; + + if (status.argsz < minsz) + return -EINVAL; + + status.flags = 0; + + if (vfio_group_viable(group)) + status.flags |= VFIO_GROUP_FLAGS_VIABLE; + + if (group->container) + status.flags |= VFIO_GROUP_FLAGS_CONTAINER_SET; + + if (copy_to_user((void __user *)arg, &status, minsz)) + return -EFAULT; + + ret = 0; + break; + } + case VFIO_GROUP_SET_CONTAINER: + { + int fd; + + if (get_user(fd, (int __user *)arg)) + return -EFAULT; + + if (fd < 0) + return -EINVAL; + + ret = vfio_group_set_container(group, fd); + break; + } + case VFIO_GROUP_UNSET_CONTAINER: + ret = vfio_group_unset_container(group); + break; + case VFIO_GROUP_GET_DEVICE_FD: + { + char *buf; + + buf = strndup_user((const char __user *)arg, PAGE_SIZE); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + ret = vfio_group_get_device_fd(group, buf); + kfree(buf); + break; + } + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long vfio_group_fops_compat_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + arg = (unsigned long)compat_ptr(arg); + return vfio_group_fops_unl_ioctl(filep, cmd, arg); +} +#endif /* CONFIG_COMPAT */ + +static int vfio_group_fops_open(struct inode *inode, struct file *filep) +{ + struct vfio_group *group; + + group = vfio_group_get_from_minor(iminor(inode)); + if (!group) + return -ENODEV; + + if (group->container) { + vfio_group_put(group); + return -EBUSY; + } + + filep->private_data = group; + + return 0; +} + +static int vfio_group_fops_release(struct inode *inode, struct file *filep) +{ + struct vfio_group *group = filep->private_data; + + filep->private_data = NULL; + + vfio_group_try_dissolve_container(group); + + vfio_group_put(group); + + return 0; +} + +static const struct file_operations vfio_group_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = vfio_group_fops_unl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vfio_group_fops_compat_ioctl, +#endif + .open = vfio_group_fops_open, + .release = vfio_group_fops_release, +}; + +/** + * VFIO Device fd + */ +static int vfio_device_fops_release(struct inode *inode, struct file *filep) +{ + struct vfio_device *device = filep->private_data; + + device->ops->release(device->device_data); + + vfio_group_try_dissolve_container(device->group); + + vfio_device_put(device); + + return 0; +} + +static long vfio_device_fops_unl_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + struct vfio_device *device = filep->private_data; + + if (unlikely(!device->ops->ioctl)) + return -EINVAL; + + return device->ops->ioctl(device->device_data, cmd, arg); +} + +static ssize_t vfio_device_fops_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + struct vfio_device *device = filep->private_data; + + if (unlikely(!device->ops->read)) + return -EINVAL; + + return device->ops->read(device->device_data, buf, count, ppos); +} + +static ssize_t vfio_device_fops_write(struct file *filep, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct vfio_device *device = filep->private_data; + + if (unlikely(!device->ops->write)) + return -EINVAL; + + return device->ops->write(device->device_data, buf, count, ppos); +} + +static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct vfio_device *device = filep->private_data; + + if (unlikely(!device->ops->mmap)) + return -EINVAL; + + return device->ops->mmap(device->device_data, vma); +} + +#ifdef CONFIG_COMPAT +static long vfio_device_fops_compat_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + arg = (unsigned long)compat_ptr(arg); + return vfio_device_fops_unl_ioctl(filep, cmd, arg); +} +#endif /* CONFIG_COMPAT */ + +static const struct file_operations vfio_device_fops = { + .owner = THIS_MODULE, + .release = vfio_device_fops_release, + .read = vfio_device_fops_read, + .write = vfio_device_fops_write, + .unlocked_ioctl = vfio_device_fops_unl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vfio_device_fops_compat_ioctl, +#endif + .mmap = vfio_device_fops_mmap, +}; + +/** + * Module/class support + */ +static char *vfio_devnode(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev)); +} + +static int __init vfio_init(void) +{ + int ret; + + idr_init(&vfio.group_idr); + mutex_init(&vfio.group_lock); + mutex_init(&vfio.iommu_drivers_lock); + INIT_LIST_HEAD(&vfio.group_list); + INIT_LIST_HEAD(&vfio.iommu_drivers_list); + init_waitqueue_head(&vfio.release_q); + + vfio.class = class_create(THIS_MODULE, "vfio"); + if (IS_ERR(vfio.class)) { + ret = PTR_ERR(vfio.class); + goto err_class; + } + + vfio.class->devnode = vfio_devnode; + + ret = alloc_chrdev_region(&vfio.devt, 0, MINORMASK, "vfio"); + if (ret) + goto err_base_chrdev; + + cdev_init(&vfio.cdev, &vfio_fops); + ret = cdev_add(&vfio.cdev, vfio.devt, 1); + if (ret) + goto err_base_cdev; + + vfio.dev = device_create(vfio.class, NULL, vfio.devt, NULL, "vfio"); + if (IS_ERR(vfio.dev)) { + ret = PTR_ERR(vfio.dev); + goto err_base_dev; + } + + /* /dev/vfio/$GROUP */ + cdev_init(&vfio.group_cdev, &vfio_group_fops); + ret = cdev_add(&vfio.group_cdev, + MKDEV(MAJOR(vfio.devt), 1), MINORMASK - 1); + if (ret) + goto err_groups_cdev; + + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + return 0; + +err_groups_cdev: + device_destroy(vfio.class, vfio.devt); +err_base_dev: + cdev_del(&vfio.cdev); +err_base_cdev: + unregister_chrdev_region(vfio.devt, MINORMASK); +err_base_chrdev: + class_destroy(vfio.class); + vfio.class = NULL; +err_class: + return ret; +} + +static void __exit vfio_cleanup(void) +{ + WARN_ON(!list_empty(&vfio.group_list)); + + idr_destroy(&vfio.group_idr); + cdev_del(&vfio.group_cdev); + device_destroy(vfio.class, vfio.devt); + cdev_del(&vfio.cdev); + unregister_chrdev_region(vfio.devt, MINORMASK); + class_destroy(vfio.class); + vfio.class = NULL; +} + +module_init(vfio_init); +module_exit(vfio_cleanup); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/include/linux/vfio.h b/include/linux/vfio.h new file mode 100644 index 000000000000..03e56a5154b6 --- /dev/null +++ b/include/linux/vfio.h @@ -0,0 +1,367 @@ +/* + * VFIO API definition + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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 VFIO_H +#define VFIO_H + +#include +#include + +#define VFIO_API_VERSION 0 + +#ifdef __KERNEL__ /* Internal VFIO-core/bus driver API */ + +#include +#include + +/** + * struct vfio_device_ops - VFIO bus driver device callbacks + * + * @open: Called when userspace creates new file descriptor for device + * @release: Called when userspace releases file descriptor for device + * @read: Perform read(2) on device file descriptor + * @write: Perform write(2) on device file descriptor + * @ioctl: Perform ioctl(2) on device file descriptor, supporting VFIO_DEVICE_* + * operations documented below + * @mmap: Perform mmap(2) on a region of the device file descriptor + */ +struct vfio_device_ops { + char *name; + int (*open)(void *device_data); + void (*release)(void *device_data); + ssize_t (*read)(void *device_data, char __user *buf, + size_t count, loff_t *ppos); + ssize_t (*write)(void *device_data, const char __user *buf, + size_t count, loff_t *size); + long (*ioctl)(void *device_data, unsigned int cmd, + unsigned long arg); + int (*mmap)(void *device_data, struct vm_area_struct *vma); +}; + +extern int vfio_add_group_dev(struct device *dev, + const struct vfio_device_ops *ops, + void *device_data); + +extern void *vfio_del_group_dev(struct device *dev); + +/** + * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks + */ +struct vfio_iommu_driver_ops { + char *name; + struct module *owner; + void *(*open)(unsigned long arg); + void (*release)(void *iommu_data); + ssize_t (*read)(void *iommu_data, char __user *buf, + size_t count, loff_t *ppos); + ssize_t (*write)(void *iommu_data, const char __user *buf, + size_t count, loff_t *size); + long (*ioctl)(void *iommu_data, unsigned int cmd, + unsigned long arg); + int (*mmap)(void *iommu_data, struct vm_area_struct *vma); + int (*attach_group)(void *iommu_data, + struct iommu_group *group); + void (*detach_group)(void *iommu_data, + struct iommu_group *group); + +}; + +extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops); + +extern void vfio_unregister_iommu_driver( + const struct vfio_iommu_driver_ops *ops); + +/** + * offsetofend(TYPE, MEMBER) + * + * @TYPE: The type of the structure + * @MEMBER: The member within the structure to get the end offset of + * + * Simple helper macro for dealing with variable sized structures passed + * from user space. This allows us to easily determine if the provided + * structure is sized to include various fields. + */ +#define offsetofend(TYPE, MEMBER) ({ \ + TYPE tmp; \ + offsetof(TYPE, MEMBER) + sizeof(tmp.MEMBER); }) \ + +#endif /* __KERNEL__ */ + +/* Kernel & User level defines for VFIO IOCTLs. */ + +/* Extensions */ + +/* None yet */ + +/* + * The IOCTL interface is designed for extensibility by embedding the + * structure length (argsz) and flags into structures passed between + * kernel and userspace. We therefore use the _IO() macro for these + * defines to avoid implicitly embedding a size into the ioctl request. + * As structure fields are added, argsz will increase to match and flag + * bits will be defined to indicate additional fields with valid data. + * It's *always* the caller's responsibility to indicate the size of + * the structure passed by setting argsz appropriately. + */ + +#define VFIO_TYPE (';') +#define VFIO_BASE 100 + +/* -------- IOCTLs for VFIO file descriptor (/dev/vfio/vfio) -------- */ + +/** + * VFIO_GET_API_VERSION - _IO(VFIO_TYPE, VFIO_BASE + 0) + * + * Report the version of the VFIO API. This allows us to bump the entire + * API version should we later need to add or change features in incompatible + * ways. + * Return: VFIO_API_VERSION + * Availability: Always + */ +#define VFIO_GET_API_VERSION _IO(VFIO_TYPE, VFIO_BASE + 0) + +/** + * VFIO_CHECK_EXTENSION - _IOW(VFIO_TYPE, VFIO_BASE + 1, __u32) + * + * Check whether an extension is supported. + * Return: 0 if not supported, 1 (or some other positive integer) if supported. + * Availability: Always + */ +#define VFIO_CHECK_EXTENSION _IO(VFIO_TYPE, VFIO_BASE + 1) + +/** + * VFIO_SET_IOMMU - _IOW(VFIO_TYPE, VFIO_BASE + 2, __s32) + * + * Set the iommu to the given type. The type must be supported by an + * iommu driver as verified by calling CHECK_EXTENSION using the same + * type. A group must be set to this file descriptor before this + * ioctl is available. The IOMMU interfaces enabled by this call are + * specific to the value set. + * Return: 0 on success, -errno on failure + * Availability: When VFIO group attached + */ +#define VFIO_SET_IOMMU _IO(VFIO_TYPE, VFIO_BASE + 2) + +/* -------- IOCTLs for GROUP file descriptors (/dev/vfio/$GROUP) -------- */ + +/** + * VFIO_GROUP_GET_STATUS - _IOR(VFIO_TYPE, VFIO_BASE + 3, + * struct vfio_group_status) + * + * Retrieve information about the group. Fills in provided + * struct vfio_group_info. Caller sets argsz. + * Return: 0 on succes, -errno on failure. + * Availability: Always + */ +struct vfio_group_status { + __u32 argsz; + __u32 flags; +#define VFIO_GROUP_FLAGS_VIABLE (1 << 0) +#define VFIO_GROUP_FLAGS_CONTAINER_SET (1 << 1) +}; +#define VFIO_GROUP_GET_STATUS _IO(VFIO_TYPE, VFIO_BASE + 3) + +/** + * VFIO_GROUP_SET_CONTAINER - _IOW(VFIO_TYPE, VFIO_BASE + 4, __s32) + * + * Set the container for the VFIO group to the open VFIO file + * descriptor provided. Groups may only belong to a single + * container. Containers may, at their discretion, support multiple + * groups. Only when a container is set are all of the interfaces + * of the VFIO file descriptor and the VFIO group file descriptor + * available to the user. + * Return: 0 on success, -errno on failure. + * Availability: Always + */ +#define VFIO_GROUP_SET_CONTAINER _IO(VFIO_TYPE, VFIO_BASE + 4) + +/** + * VFIO_GROUP_UNSET_CONTAINER - _IO(VFIO_TYPE, VFIO_BASE + 5) + * + * Remove the group from the attached container. This is the + * opposite of the SET_CONTAINER call and returns the group to + * an initial state. All device file descriptors must be released + * prior to calling this interface. When removing the last group + * from a container, the IOMMU will be disabled and all state lost, + * effectively also returning the VFIO file descriptor to an initial + * state. + * Return: 0 on success, -errno on failure. + * Availability: When attached to container + */ +#define VFIO_GROUP_UNSET_CONTAINER _IO(VFIO_TYPE, VFIO_BASE + 5) + +/** + * VFIO_GROUP_GET_DEVICE_FD - _IOW(VFIO_TYPE, VFIO_BASE + 6, char) + * + * Return a new file descriptor for the device object described by + * the provided string. The string should match a device listed in + * the devices subdirectory of the IOMMU group sysfs entry. The + * group containing the device must already be added to this context. + * Return: new file descriptor on success, -errno on failure. + * Availability: When attached to container + */ +#define VFIO_GROUP_GET_DEVICE_FD _IO(VFIO_TYPE, VFIO_BASE + 6) + +/* --------------- IOCTLs for DEVICE file descriptors --------------- */ + +/** + * VFIO_DEVICE_GET_INFO - _IOR(VFIO_TYPE, VFIO_BASE + 7, + * struct vfio_device_info) + * + * Retrieve information about the device. Fills in provided + * struct vfio_device_info. Caller sets argsz. + * Return: 0 on success, -errno on failure. + */ +struct vfio_device_info { + __u32 argsz; + __u32 flags; +#define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */ + __u32 num_regions; /* Max region index + 1 */ + __u32 num_irqs; /* Max IRQ index + 1 */ +}; +#define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7) + +/** + * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8, + * struct vfio_region_info) + * + * Retrieve information about a device region. Caller provides + * struct vfio_region_info with index value set. Caller sets argsz. + * Implementation of region mapping is bus driver specific. This is + * intended to describe MMIO, I/O port, as well as bus specific + * regions (ex. PCI config space). Zero sized regions may be used + * to describe unimplemented regions (ex. unimplemented PCI BARs). + * Return: 0 on success, -errno on failure. + */ +struct vfio_region_info { + __u32 argsz; + __u32 flags; +#define VFIO_REGION_INFO_FLAG_READ (1 << 0) /* Region supports read */ +#define VFIO_REGION_INFO_FLAG_WRITE (1 << 1) /* Region supports write */ +#define VFIO_REGION_INFO_FLAG_MMAP (1 << 2) /* Region supports mmap */ + __u32 index; /* Region index */ + __u32 resv; /* Reserved for alignment */ + __u64 size; /* Region size (bytes) */ + __u64 offset; /* Region offset from start of device fd */ +}; +#define VFIO_DEVICE_GET_REGION_INFO _IO(VFIO_TYPE, VFIO_BASE + 8) + +/** + * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9, + * struct vfio_irq_info) + * + * Retrieve information about a device IRQ. Caller provides + * struct vfio_irq_info with index value set. Caller sets argsz. + * Implementation of IRQ mapping is bus driver specific. Indexes + * using multiple IRQs are primarily intended to support MSI-like + * interrupt blocks. Zero count irq blocks may be used to describe + * unimplemented interrupt types. + * + * The EVENTFD flag indicates the interrupt index supports eventfd based + * signaling. + * + * The MASKABLE flags indicates the index supports MASK and UNMASK + * actions described below. + * + * AUTOMASKED indicates that after signaling, the interrupt line is + * automatically masked by VFIO and the user needs to unmask the line + * to receive new interrupts. This is primarily intended to distinguish + * level triggered interrupts. + * + * The NORESIZE flag indicates that the interrupt lines within the index + * are setup as a set and new subindexes cannot be enabled without first + * disabling the entire index. This is used for interrupts like PCI MSI + * and MSI-X where the driver may only use a subset of the available + * indexes, but VFIO needs to enable a specific number of vectors + * upfront. In the case of MSI-X, where the user can enable MSI-X and + * then add and unmask vectors, it's up to userspace to make the decision + * whether to allocate the maximum supported number of vectors or tear + * down setup and incrementally increase the vectors as each is enabled. + */ +struct vfio_irq_info { + __u32 argsz; + __u32 flags; +#define VFIO_IRQ_INFO_EVENTFD (1 << 0) +#define VFIO_IRQ_INFO_MASKABLE (1 << 1) +#define VFIO_IRQ_INFO_AUTOMASKED (1 << 2) +#define VFIO_IRQ_INFO_NORESIZE (1 << 3) + __u32 index; /* IRQ index */ + __u32 count; /* Number of IRQs within this index */ +}; +#define VFIO_DEVICE_GET_IRQ_INFO _IO(VFIO_TYPE, VFIO_BASE + 9) + +/** + * VFIO_DEVICE_SET_IRQS - _IOW(VFIO_TYPE, VFIO_BASE + 10, struct vfio_irq_set) + * + * Set signaling, masking, and unmasking of interrupts. Caller provides + * struct vfio_irq_set with all fields set. 'start' and 'count' indicate + * the range of subindexes being specified. + * + * The DATA flags specify the type of data provided. If DATA_NONE, the + * operation performs the specified action immediately on the specified + * interrupt(s). For example, to unmask AUTOMASKED interrupt [0,0]: + * flags = (DATA_NONE|ACTION_UNMASK), index = 0, start = 0, count = 1. + * + * DATA_BOOL allows sparse support for the same on arrays of interrupts. + * For example, to mask interrupts [0,1] and [0,3] (but not [0,2]): + * flags = (DATA_BOOL|ACTION_MASK), index = 0, start = 1, count = 3, + * data = {1,0,1} + * + * DATA_EVENTFD binds the specified ACTION to the provided __s32 eventfd. + * A value of -1 can be used to either de-assign interrupts if already + * assigned or skip un-assigned interrupts. For example, to set an eventfd + * to be trigger for interrupts [0,0] and [0,2]: + * flags = (DATA_EVENTFD|ACTION_TRIGGER), index = 0, start = 0, count = 3, + * data = {fd1, -1, fd2} + * If index [0,1] is previously set, two count = 1 ioctls calls would be + * required to set [0,0] and [0,2] without changing [0,1]. + * + * Once a signaling mechanism is set, DATA_BOOL or DATA_NONE can be used + * with ACTION_TRIGGER to perform kernel level interrupt loopback testing + * from userspace (ie. simulate hardware triggering). + * + * Setting of an event triggering mechanism to userspace for ACTION_TRIGGER + * enables the interrupt index for the device. Individual subindex interrupts + * can be disabled using the -1 value for DATA_EVENTFD or the index can be + * disabled as a whole with: flags = (DATA_NONE|ACTION_TRIGGER), count = 0. + * + * Note that ACTION_[UN]MASK specify user->kernel signaling (irqfds) while + * ACTION_TRIGGER specifies kernel->user signaling. + */ +struct vfio_irq_set { + __u32 argsz; + __u32 flags; +#define VFIO_IRQ_SET_DATA_NONE (1 << 0) /* Data not present */ +#define VFIO_IRQ_SET_DATA_BOOL (1 << 1) /* Data is bool (u8) */ +#define VFIO_IRQ_SET_DATA_EVENTFD (1 << 2) /* Data is eventfd (s32) */ +#define VFIO_IRQ_SET_ACTION_MASK (1 << 3) /* Mask interrupt */ +#define VFIO_IRQ_SET_ACTION_UNMASK (1 << 4) /* Unmask interrupt */ +#define VFIO_IRQ_SET_ACTION_TRIGGER (1 << 5) /* Trigger interrupt */ + __u32 index; + __u32 start; + __u32 count; + __u8 data[]; +}; +#define VFIO_DEVICE_SET_IRQS _IO(VFIO_TYPE, VFIO_BASE + 10) + +#define VFIO_IRQ_SET_DATA_TYPE_MASK (VFIO_IRQ_SET_DATA_NONE | \ + VFIO_IRQ_SET_DATA_BOOL | \ + VFIO_IRQ_SET_DATA_EVENTFD) +#define VFIO_IRQ_SET_ACTION_TYPE_MASK (VFIO_IRQ_SET_ACTION_MASK | \ + VFIO_IRQ_SET_ACTION_UNMASK | \ + VFIO_IRQ_SET_ACTION_TRIGGER) +/** + * VFIO_DEVICE_RESET - _IO(VFIO_TYPE, VFIO_BASE + 11) + * + * Reset a device. + */ +#define VFIO_DEVICE_RESET _IO(VFIO_TYPE, VFIO_BASE + 11) + +#endif /* VFIO_H */ -- GitLab From 4a5b2a20ec87384eeb19e70991e7e15a00cad87b Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 31 Jul 2012 08:16:23 -0600 Subject: [PATCH 4834/5711] vfio: Add documentation Signed-off-by: Alex Williamson --- Documentation/vfio.txt | 314 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 Documentation/vfio.txt diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt new file mode 100644 index 000000000000..0cb6685c8029 --- /dev/null +++ b/Documentation/vfio.txt @@ -0,0 +1,314 @@ +VFIO - "Virtual Function I/O"[1] +------------------------------------------------------------------------------- +Many modern system now provide DMA and interrupt remapping facilities +to help ensure I/O devices behave within the boundaries they've been +allotted. This includes x86 hardware with AMD-Vi and Intel VT-d, +POWER systems with Partitionable Endpoints (PEs) and embedded PowerPC +systems such as Freescale PAMU. The VFIO driver is an IOMMU/device +agnostic framework for exposing direct device access to userspace, in +a secure, IOMMU protected environment. In other words, this allows +safe[2], non-privileged, userspace drivers. + +Why do we want that? Virtual machines often make use of direct device +access ("device assignment") when configured for the highest possible +I/O performance. From a device and host perspective, this simply +turns the VM into a userspace driver, with the benefits of +significantly reduced latency, higher bandwidth, and direct use of +bare-metal device drivers[3]. + +Some applications, particularly in the high performance computing +field, also benefit from low-overhead, direct device access from +userspace. Examples include network adapters (often non-TCP/IP based) +and compute accelerators. Prior to VFIO, these drivers had to either +go through the full development cycle to become proper upstream +driver, be maintained out of tree, or make use of the UIO framework, +which has no notion of IOMMU protection, limited interrupt support, +and requires root privileges to access things like PCI configuration +space. + +The VFIO driver framework intends to unify these, replacing both the +KVM PCI specific device assignment code as well as provide a more +secure, more featureful userspace driver environment than UIO. + +Groups, Devices, and IOMMUs +------------------------------------------------------------------------------- + +Devices are the main target of any I/O driver. Devices typically +create a programming interface made up of I/O access, interrupts, +and DMA. Without going into the details of each of these, DMA is +by far the most critical aspect for maintaining a secure environment +as allowing a device read-write access to system memory imposes the +greatest risk to the overall system integrity. + +To help mitigate this risk, many modern IOMMUs now incorporate +isolation properties into what was, in many cases, an interface only +meant for translation (ie. solving the addressing problems of devices +with limited address spaces). With this, devices can now be isolated +from each other and from arbitrary memory access, thus allowing +things like secure direct assignment of devices into virtual machines. + +This isolation is not always at the granularity of a single device +though. Even when an IOMMU is capable of this, properties of devices, +interconnects, and IOMMU topologies can each reduce this isolation. +For instance, an individual device may be part of a larger multi- +function enclosure. While the IOMMU may be able to distinguish +between devices within the enclosure, the enclosure may not require +transactions between devices to reach the IOMMU. Examples of this +could be anything from a multi-function PCI device with backdoors +between functions to a non-PCI-ACS (Access Control Services) capable +bridge allowing redirection without reaching the IOMMU. Topology +can also play a factor in terms of hiding devices. A PCIe-to-PCI +bridge masks the devices behind it, making transaction appear as if +from the bridge itself. Obviously IOMMU design plays a major factor +as well. + +Therefore, while for the most part an IOMMU may have device level +granularity, any system is susceptible to reduced granularity. The +IOMMU API therefore supports a notion of IOMMU groups. A group is +a set of devices which is isolatable from all other devices in the +system. Groups are therefore the unit of ownership used by VFIO. + +While the group is the minimum granularity that must be used to +ensure secure user access, it's not necessarily the preferred +granularity. In IOMMUs which make use of page tables, it may be +possible to share a set of page tables between different groups, +reducing the overhead both to the platform (reduced TLB thrashing, +reduced duplicate page tables), and to the user (programming only +a single set of translations). For this reason, VFIO makes use of +a container class, which may hold one or more groups. A container +is created by simply opening the /dev/vfio/vfio character device. + +On its own, the container provides little functionality, with all +but a couple version and extension query interfaces locked away. +The user needs to add a group into the container for the next level +of functionality. To do this, the user first needs to identify the +group associated with the desired device. This can be done using +the sysfs links described in the example below. By unbinding the +device from the host driver and binding it to a VFIO driver, a new +VFIO group will appear for the group as /dev/vfio/$GROUP, where +$GROUP is the IOMMU group number of which the device is a member. +If the IOMMU group contains multiple devices, each will need to +be bound to a VFIO driver before operations on the VFIO group +are allowed (it's also sufficient to only unbind the device from +host drivers if a VFIO driver is unavailable; this will make the +group available, but not that particular device). TBD - interface +for disabling driver probing/locking a device. + +Once the group is ready, it may be added to the container by opening +the VFIO group character device (/dev/vfio/$GROUP) and using the +VFIO_GROUP_SET_CONTAINER ioctl, passing the file descriptor of the +previously opened container file. If desired and if the IOMMU driver +supports sharing the IOMMU context between groups, multiple groups may +be set to the same container. If a group fails to set to a container +with existing groups, a new empty container will need to be used +instead. + +With a group (or groups) attached to a container, the remaining +ioctls become available, enabling access to the VFIO IOMMU interfaces. +Additionally, it now becomes possible to get file descriptors for each +device within a group using an ioctl on the VFIO group file descriptor. + +The VFIO device API includes ioctls for describing the device, the I/O +regions and their read/write/mmap offsets on the device descriptor, as +well as mechanisms for describing and registering interrupt +notifications. + +VFIO Usage Example +------------------------------------------------------------------------------- + +Assume user wants to access PCI device 0000:06:0d.0 + +$ readlink /sys/bus/pci/devices/0000:06:0d.0/iommu_group +../../../../kernel/iommu_groups/26 + +This device is therefore in IOMMU group 26. This device is on the +pci bus, therefore the user will make use of vfio-pci to manage the +group: + +# modprobe vfio-pci + +Binding this device to the vfio-pci driver creates the VFIO group +character devices for this group: + +$ lspci -n -s 0000:06:0d.0 +06:0d.0 0401: 1102:0002 (rev 08) +# echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind +# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id + +Now we need to look at what other devices are in the group to free +it for use by VFIO: + +$ ls -l /sys/bus/pci/devices/0000:06:0d.0/iommu_group/devices +total 0 +lrwxrwxrwx. 1 root root 0 Apr 23 16:13 0000:00:1e.0 -> + ../../../../devices/pci0000:00/0000:00:1e.0 +lrwxrwxrwx. 1 root root 0 Apr 23 16:13 0000:06:0d.0 -> + ../../../../devices/pci0000:00/0000:00:1e.0/0000:06:0d.0 +lrwxrwxrwx. 1 root root 0 Apr 23 16:13 0000:06:0d.1 -> + ../../../../devices/pci0000:00/0000:00:1e.0/0000:06:0d.1 + +This device is behind a PCIe-to-PCI bridge[4], therefore we also +need to add device 0000:06:0d.1 to the group following the same +procedure as above. Device 0000:00:1e.0 is a bridge that does +not currently have a host driver, therefore it's not required to +bind this device to the vfio-pci driver (vfio-pci does not currently +support PCI bridges). + +The final step is to provide the user with access to the group if +unprivileged operation is desired (note that /dev/vfio/vfio provides +no capabilities on its own and is therefore expected to be set to +mode 0666 by the system). + +# chown user:user /dev/vfio/26 + +The user now has full access to all the devices and the iommu for this +group and can access them as follows: + + int container, group, device, i; + struct vfio_group_status group_status = + { .argsz = sizeof(group_status) }; + struct vfio_iommu_x86_info iommu_info = { .argsz = sizeof(iommu_info) }; + struct vfio_iommu_x86_dma_map dma_map = { .argsz = sizeof(dma_map) }; + struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; + + /* Create a new container */ + container = open("/dev/vfio/vfio, O_RDWR); + + if (ioctl(container, VFIO_GET_API_VERSION) != VFIO_API_VERSION) + /* Unknown API version */ + + if (!ioctl(container, VFIO_CHECK_EXTENSION, VFIO_X86_IOMMU)) + /* Doesn't support the IOMMU driver we want. */ + + /* Open the group */ + group = open("/dev/vfio/26", O_RDWR); + + /* Test the group is viable and available */ + ioctl(group, VFIO_GROUP_GET_STATUS, &group_status); + + if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) + /* Group is not viable (ie, not all devices bound for vfio) */ + + /* Add the group to the container */ + ioctl(group, VFIO_GROUP_SET_CONTAINER, &container); + + /* Enable the IOMMU model we want */ + ioctl(container, VFIO_SET_IOMMU, VFIO_X86_IOMMU) + + /* Get addition IOMMU info */ + ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info); + + /* Allocate some space and setup a DMA mapping */ + dma_map.vaddr = mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + dma_map.size = 1024 * 1024; + dma_map.iova = 0; /* 1MB starting at 0x0 from device view */ + dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; + + ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); + + /* Get a file descriptor for the device */ + device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:06:0d.0"); + + /* Test and setup the device */ + ioctl(device, VFIO_DEVICE_GET_INFO, &device_info); + + for (i = 0; i < device_info.num_regions; i++) { + struct vfio_region_info reg = { .argsz = sizeof(reg) }; + + reg.index = i; + + ioctl(device, VFIO_DEVICE_GET_REGION_INFO, ®); + + /* Setup mappings... read/write offsets, mmaps + * For PCI devices, config space is a region */ + } + + for (i = 0; i < device_info.num_irqs; i++) { + struct vfio_irq_info irq = { .argsz = sizeof(irq) }; + + irq.index = i; + + ioctl(device, VFIO_DEVICE_GET_IRQ_INFO, ®); + + /* Setup IRQs... eventfds, VFIO_DEVICE_SET_IRQS */ + } + + /* Gratuitous device reset and go... */ + ioctl(device, VFIO_DEVICE_RESET); + +VFIO User API +------------------------------------------------------------------------------- + +Please see include/linux/vfio.h for complete API documentation. + +VFIO bus driver API +------------------------------------------------------------------------------- + +VFIO bus drivers, such as vfio-pci make use of only a few interfaces +into VFIO core. When devices are bound and unbound to the driver, +the driver should call vfio_add_group_dev() and vfio_del_group_dev() +respectively: + +extern int vfio_add_group_dev(struct iommu_group *iommu_group, + struct device *dev, + const struct vfio_device_ops *ops, + void *device_data); + +extern void *vfio_del_group_dev(struct device *dev); + +vfio_add_group_dev() indicates to the core to begin tracking the +specified iommu_group and register the specified dev as owned by +a VFIO bus driver. The driver provides an ops structure for callbacks +similar to a file operations structure: + +struct vfio_device_ops { + int (*open)(void *device_data); + void (*release)(void *device_data); + ssize_t (*read)(void *device_data, char __user *buf, + size_t count, loff_t *ppos); + ssize_t (*write)(void *device_data, const char __user *buf, + size_t size, loff_t *ppos); + long (*ioctl)(void *device_data, unsigned int cmd, + unsigned long arg); + int (*mmap)(void *device_data, struct vm_area_struct *vma); +}; + +Each function is passed the device_data that was originally registered +in the vfio_add_group_dev() call above. This allows the bus driver +an easy place to store its opaque, private data. The open/release +callbacks are issued when a new file descriptor is created for a +device (via VFIO_GROUP_GET_DEVICE_FD). The ioctl interface provides +a direct pass through for VFIO_DEVICE_* ioctls. The read/write/mmap +interfaces implement the device region access defined by the device's +own VFIO_DEVICE_GET_REGION_INFO ioctl. + +------------------------------------------------------------------------------- + +[1] VFIO was originally an acronym for "Virtual Function I/O" in its +initial implementation by Tom Lyon while as Cisco. We've since +outgrown the acronym, but it's catchy. + +[2] "safe" also depends upon a device being "well behaved". It's +possible for multi-function devices to have backdoors between +functions and even for single function devices to have alternative +access to things like PCI config space through MMIO registers. To +guard against the former we can include additional precautions in the +IOMMU driver to group multi-function PCI devices together +(iommu=group_mf). The latter we can't prevent, but the IOMMU should +still provide isolation. For PCI, SR-IOV Virtual Functions are the +best indicator of "well behaved", as these are designed for +virtualization usage models. + +[3] As always there are trade-offs to virtual machine device +assignment that are beyond the scope of VFIO. It's expected that +future IOMMU technologies will reduce some, but maybe not all, of +these trade-offs. + +[4] In this case the device is below a PCI bridge, so transactions +from either function of the device are indistinguishable to the iommu: + +-[0000:00]-+-1e.0-[06]--+-0d.0 + \-0d.1 + +00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 90) -- GitLab From 73fa0d10d077d9521ee2dace2307ae2c9a965336 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 31 Jul 2012 08:16:23 -0600 Subject: [PATCH 4835/5711] vfio: Type1 IOMMU implementation This VFIO IOMMU backend is designed primarily for AMD-Vi and Intel VT-d hardware, but is potentially usable by anything supporting similar mapping functionality. We arbitrarily call this a Type1 backend for lack of a better name. This backend has no IOVA or host memory mapping restrictions for the user and is optimized for relatively static mappings. Mapped areas are pinned into system memory. Signed-off-by: Alex Williamson --- drivers/vfio/Kconfig | 6 + drivers/vfio/Makefile | 2 + drivers/vfio/vfio.c | 7 + drivers/vfio/vfio_iommu_type1.c | 753 ++++++++++++++++++++++++++++++++ include/linux/vfio.h | 54 ++- 5 files changed, 821 insertions(+), 1 deletion(-) create mode 100644 drivers/vfio/vfio_iommu_type1.c diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 9acb1e729bd6..128b97910b8e 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -1,6 +1,12 @@ +config VFIO_IOMMU_TYPE1 + tristate + depends on VFIO + default n + menuconfig VFIO tristate "VFIO Non-Privileged userspace driver framework" depends on IOMMU_API + select VFIO_IOMMU_TYPE1 if X86 help VFIO provides a framework for secure userspace device drivers. See Documentation/vfio.txt for more details. diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile index 7500a67a42a0..2398d4a0e38b 100644 --- a/drivers/vfio/Makefile +++ b/drivers/vfio/Makefile @@ -1 +1,3 @@ obj-$(CONFIG_VFIO) += vfio.o +obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o +obj-$(CONFIG_VFIO_PCI) += pci/ diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 052e310aed72..9591e2b509d7 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1376,6 +1376,13 @@ static int __init vfio_init(void) pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + /* + * Attempt to load known iommu-drivers. This gives us a working + * environment without the user needing to explicitly load iommu + * drivers. + */ + request_module_nowait("vfio_iommu_type1"); + return 0; err_groups_cdev: diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c new file mode 100644 index 000000000000..6f3fbc48a6c7 --- /dev/null +++ b/drivers/vfio/vfio_iommu_type1.c @@ -0,0 +1,753 @@ +/* + * VFIO: IOMMU DMA mapping support for Type1 IOMMU + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + * + * We arbitrarily define a Type1 IOMMU as one matching the below code. + * It could be called the x86 IOMMU as it's designed for AMD-Vi & Intel + * VT-d, but that makes it harder to re-use as theoretically anyone + * implementing a similar IOMMU could make use of this. We expect the + * IOMMU to support the IOMMU API and have few to no restrictions around + * the IOVA range that can be mapped. The Type1 IOMMU is currently + * optimized for relatively static mappings of a userspace process with + * userpsace pages pinned into memory. We also assume devices and IOMMU + * domains are PCI based as the IOMMU API is still centered around a + * device/bus interface rather than a group interface. + */ + +#include +#include +#include +#include +#include +#include +#include /* pci_bus_type */ +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "0.2" +#define DRIVER_AUTHOR "Alex Williamson " +#define DRIVER_DESC "Type1 IOMMU driver for VFIO" + +static bool allow_unsafe_interrupts; +module_param_named(allow_unsafe_interrupts, + allow_unsafe_interrupts, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(allow_unsafe_interrupts, + "Enable VFIO IOMMU support for on platforms without interrupt remapping support."); + +struct vfio_iommu { + struct iommu_domain *domain; + struct mutex lock; + struct list_head dma_list; + struct list_head group_list; + bool cache; +}; + +struct vfio_dma { + struct list_head next; + dma_addr_t iova; /* Device address */ + unsigned long vaddr; /* Process virtual addr */ + long npage; /* Number of pages */ + int prot; /* IOMMU_READ/WRITE */ +}; + +struct vfio_group { + struct iommu_group *iommu_group; + struct list_head next; +}; + +/* + * This code handles mapping and unmapping of user data buffers + * into DMA'ble space using the IOMMU + */ + +#define NPAGE_TO_SIZE(npage) ((size_t)(npage) << PAGE_SHIFT) + +struct vwork { + struct mm_struct *mm; + long npage; + struct work_struct work; +}; + +/* delayed decrement/increment for locked_vm */ +static void vfio_lock_acct_bg(struct work_struct *work) +{ + struct vwork *vwork = container_of(work, struct vwork, work); + struct mm_struct *mm; + + mm = vwork->mm; + down_write(&mm->mmap_sem); + mm->locked_vm += vwork->npage; + up_write(&mm->mmap_sem); + mmput(mm); + kfree(vwork); +} + +static void vfio_lock_acct(long npage) +{ + struct vwork *vwork; + struct mm_struct *mm; + + if (!current->mm) + return; /* process exited */ + + if (down_write_trylock(¤t->mm->mmap_sem)) { + current->mm->locked_vm += npage; + up_write(¤t->mm->mmap_sem); + return; + } + + /* + * Couldn't get mmap_sem lock, so must setup to update + * mm->locked_vm later. If locked_vm were atomic, we + * wouldn't need this silliness + */ + vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL); + if (!vwork) + return; + mm = get_task_mm(current); + if (!mm) { + kfree(vwork); + return; + } + INIT_WORK(&vwork->work, vfio_lock_acct_bg); + vwork->mm = mm; + vwork->npage = npage; + schedule_work(&vwork->work); +} + +/* + * Some mappings aren't backed by a struct page, for example an mmap'd + * MMIO range for our own or another device. These use a different + * pfn conversion and shouldn't be tracked as locked pages. + */ +static bool is_invalid_reserved_pfn(unsigned long pfn) +{ + if (pfn_valid(pfn)) { + bool reserved; + struct page *tail = pfn_to_page(pfn); + struct page *head = compound_trans_head(tail); + reserved = !!(PageReserved(head)); + if (head != tail) { + /* + * "head" is not a dangling pointer + * (compound_trans_head takes care of that) + * but the hugepage may have been split + * from under us (and we may not hold a + * reference count on the head page so it can + * be reused before we run PageReferenced), so + * we've to check PageTail before returning + * what we just read. + */ + smp_rmb(); + if (PageTail(tail)) + return reserved; + } + return PageReserved(tail); + } + + return true; +} + +static int put_pfn(unsigned long pfn, int prot) +{ + if (!is_invalid_reserved_pfn(pfn)) { + struct page *page = pfn_to_page(pfn); + if (prot & IOMMU_WRITE) + SetPageDirty(page); + put_page(page); + return 1; + } + return 0; +} + +/* Unmap DMA region */ +static long __vfio_dma_do_unmap(struct vfio_iommu *iommu, dma_addr_t iova, + long npage, int prot) +{ + long i, unlocked = 0; + + for (i = 0; i < npage; i++, iova += PAGE_SIZE) { + unsigned long pfn; + + pfn = iommu_iova_to_phys(iommu->domain, iova) >> PAGE_SHIFT; + if (pfn) { + iommu_unmap(iommu->domain, iova, PAGE_SIZE); + unlocked += put_pfn(pfn, prot); + } + } + return unlocked; +} + +static void vfio_dma_unmap(struct vfio_iommu *iommu, dma_addr_t iova, + long npage, int prot) +{ + long unlocked; + + unlocked = __vfio_dma_do_unmap(iommu, iova, npage, prot); + vfio_lock_acct(-unlocked); +} + +static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn) +{ + struct page *page[1]; + struct vm_area_struct *vma; + int ret = -EFAULT; + + if (get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE), page) == 1) { + *pfn = page_to_pfn(page[0]); + return 0; + } + + down_read(¤t->mm->mmap_sem); + + vma = find_vma_intersection(current->mm, vaddr, vaddr + 1); + + if (vma && vma->vm_flags & VM_PFNMAP) { + *pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + if (is_invalid_reserved_pfn(*pfn)) + ret = 0; + } + + up_read(¤t->mm->mmap_sem); + + return ret; +} + +/* Map DMA region */ +static int __vfio_dma_map(struct vfio_iommu *iommu, dma_addr_t iova, + unsigned long vaddr, long npage, int prot) +{ + dma_addr_t start = iova; + long i, locked = 0; + int ret; + + /* Verify that pages are not already mapped */ + for (i = 0; i < npage; i++, iova += PAGE_SIZE) + if (iommu_iova_to_phys(iommu->domain, iova)) + return -EBUSY; + + iova = start; + + if (iommu->cache) + prot |= IOMMU_CACHE; + + /* + * XXX We break mappings into pages and use get_user_pages_fast to + * pin the pages in memory. It's been suggested that mlock might + * provide a more efficient mechanism, but nothing prevents the + * user from munlocking the pages, which could then allow the user + * access to random host memory. We also have no guarantee from the + * IOMMU API that the iommu driver can unmap sub-pages of previous + * mappings. This means we might lose an entire range if a single + * page within it is unmapped. Single page mappings are inefficient, + * but provide the most flexibility for now. + */ + for (i = 0; i < npage; i++, iova += PAGE_SIZE, vaddr += PAGE_SIZE) { + unsigned long pfn = 0; + + ret = vaddr_get_pfn(vaddr, prot, &pfn); + if (ret) { + __vfio_dma_do_unmap(iommu, start, i, prot); + return ret; + } + + /* + * Only add actual locked pages to accounting + * XXX We're effectively marking a page locked for every + * IOVA page even though it's possible the user could be + * backing multiple IOVAs with the same vaddr. This over- + * penalizes the user process, but we currently have no + * easy way to do this properly. + */ + if (!is_invalid_reserved_pfn(pfn)) + locked++; + + ret = iommu_map(iommu->domain, iova, + (phys_addr_t)pfn << PAGE_SHIFT, + PAGE_SIZE, prot); + if (ret) { + /* Back out mappings on error */ + put_pfn(pfn, prot); + __vfio_dma_do_unmap(iommu, start, i, prot); + return ret; + } + } + vfio_lock_acct(locked); + return 0; +} + +static inline bool ranges_overlap(dma_addr_t start1, size_t size1, + dma_addr_t start2, size_t size2) +{ + if (start1 < start2) + return (start2 - start1 < size1); + else if (start2 < start1) + return (start1 - start2 < size2); + return (size1 > 0 && size2 > 0); +} + +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu, + dma_addr_t start, size_t size) +{ + struct vfio_dma *dma; + + list_for_each_entry(dma, &iommu->dma_list, next) { + if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage), + start, size)) + return dma; + } + return NULL; +} + +static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, + size_t size, struct vfio_dma *dma) +{ + struct vfio_dma *split; + long npage_lo, npage_hi; + + /* Existing dma region is completely covered, unmap all */ + if (start <= dma->iova && + start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) { + vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); + list_del(&dma->next); + npage_lo = dma->npage; + kfree(dma); + return npage_lo; + } + + /* Overlap low address of existing range */ + if (start <= dma->iova) { + size_t overlap; + + overlap = start + size - dma->iova; + npage_lo = overlap >> PAGE_SHIFT; + + vfio_dma_unmap(iommu, dma->iova, npage_lo, dma->prot); + dma->iova += overlap; + dma->vaddr += overlap; + dma->npage -= npage_lo; + return npage_lo; + } + + /* Overlap high address of existing range */ + if (start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) { + size_t overlap; + + overlap = dma->iova + NPAGE_TO_SIZE(dma->npage) - start; + npage_hi = overlap >> PAGE_SHIFT; + + vfio_dma_unmap(iommu, start, npage_hi, dma->prot); + dma->npage -= npage_hi; + return npage_hi; + } + + /* Split existing */ + npage_lo = (start - dma->iova) >> PAGE_SHIFT; + npage_hi = dma->npage - (size >> PAGE_SHIFT) - npage_lo; + + split = kzalloc(sizeof *split, GFP_KERNEL); + if (!split) + return -ENOMEM; + + vfio_dma_unmap(iommu, start, size >> PAGE_SHIFT, dma->prot); + + dma->npage = npage_lo; + + split->npage = npage_hi; + split->iova = start + size; + split->vaddr = dma->vaddr + NPAGE_TO_SIZE(npage_lo) + size; + split->prot = dma->prot; + list_add(&split->next, &iommu->dma_list); + return size >> PAGE_SHIFT; +} + +static int vfio_dma_do_unmap(struct vfio_iommu *iommu, + struct vfio_iommu_type1_dma_unmap *unmap) +{ + long ret = 0, npage = unmap->size >> PAGE_SHIFT; + struct vfio_dma *dma, *tmp; + uint64_t mask; + + mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1; + + if (unmap->iova & mask) + return -EINVAL; + if (unmap->size & mask) + return -EINVAL; + + /* XXX We still break these down into PAGE_SIZE */ + WARN_ON(mask & PAGE_MASK); + + mutex_lock(&iommu->lock); + + list_for_each_entry_safe(dma, tmp, &iommu->dma_list, next) { + if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage), + unmap->iova, unmap->size)) { + ret = vfio_remove_dma_overlap(iommu, unmap->iova, + unmap->size, dma); + if (ret > 0) + npage -= ret; + if (ret < 0 || npage == 0) + break; + } + } + mutex_unlock(&iommu->lock); + return ret > 0 ? 0 : (int)ret; +} + +static int vfio_dma_do_map(struct vfio_iommu *iommu, + struct vfio_iommu_type1_dma_map *map) +{ + struct vfio_dma *dma, *pdma = NULL; + dma_addr_t iova = map->iova; + unsigned long locked, lock_limit, vaddr = map->vaddr; + size_t size = map->size; + int ret = 0, prot = 0; + uint64_t mask; + long npage; + + mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1; + + /* READ/WRITE from device perspective */ + if (map->flags & VFIO_DMA_MAP_FLAG_WRITE) + prot |= IOMMU_WRITE; + if (map->flags & VFIO_DMA_MAP_FLAG_READ) + prot |= IOMMU_READ; + + if (!prot) + return -EINVAL; /* No READ/WRITE? */ + + if (vaddr & mask) + return -EINVAL; + if (iova & mask) + return -EINVAL; + if (size & mask) + return -EINVAL; + + /* XXX We still break these down into PAGE_SIZE */ + WARN_ON(mask & PAGE_MASK); + + /* Don't allow IOVA wrap */ + if (iova + size && iova + size < iova) + return -EINVAL; + + /* Don't allow virtual address wrap */ + if (vaddr + size && vaddr + size < vaddr) + return -EINVAL; + + npage = size >> PAGE_SHIFT; + if (!npage) + return -EINVAL; + + mutex_lock(&iommu->lock); + + if (vfio_find_dma(iommu, iova, size)) { + ret = -EBUSY; + goto out_lock; + } + + /* account for locked pages */ + locked = current->mm->locked_vm + npage; + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { + pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", + __func__, rlimit(RLIMIT_MEMLOCK)); + ret = -ENOMEM; + goto out_lock; + } + + ret = __vfio_dma_map(iommu, iova, vaddr, npage, prot); + if (ret) + goto out_lock; + + /* Check if we abut a region below - nothing below 0 */ + if (iova) { + dma = vfio_find_dma(iommu, iova - 1, 1); + if (dma && dma->prot == prot && + dma->vaddr + NPAGE_TO_SIZE(dma->npage) == vaddr) { + + dma->npage += npage; + iova = dma->iova; + vaddr = dma->vaddr; + npage = dma->npage; + size = NPAGE_TO_SIZE(npage); + + pdma = dma; + } + } + + /* Check if we abut a region above - nothing above ~0 + 1 */ + if (iova + size) { + dma = vfio_find_dma(iommu, iova + size, 1); + if (dma && dma->prot == prot && + dma->vaddr == vaddr + size) { + + dma->npage += npage; + dma->iova = iova; + dma->vaddr = vaddr; + + /* + * If merged above and below, remove previously + * merged entry. New entry covers it. + */ + if (pdma) { + list_del(&pdma->next); + kfree(pdma); + } + pdma = dma; + } + } + + /* Isolated, new region */ + if (!pdma) { + dma = kzalloc(sizeof *dma, GFP_KERNEL); + if (!dma) { + ret = -ENOMEM; + vfio_dma_unmap(iommu, iova, npage, prot); + goto out_lock; + } + + dma->npage = npage; + dma->iova = iova; + dma->vaddr = vaddr; + dma->prot = prot; + list_add(&dma->next, &iommu->dma_list); + } + +out_lock: + mutex_unlock(&iommu->lock); + return ret; +} + +static int vfio_iommu_type1_attach_group(void *iommu_data, + struct iommu_group *iommu_group) +{ + struct vfio_iommu *iommu = iommu_data; + struct vfio_group *group, *tmp; + int ret; + + group = kzalloc(sizeof(*group), GFP_KERNEL); + if (!group) + return -ENOMEM; + + mutex_lock(&iommu->lock); + + list_for_each_entry(tmp, &iommu->group_list, next) { + if (tmp->iommu_group == iommu_group) { + mutex_unlock(&iommu->lock); + kfree(group); + return -EINVAL; + } + } + + /* + * TODO: Domain have capabilities that might change as we add + * groups (see iommu->cache, currently never set). Check for + * them and potentially disallow groups to be attached when it + * would change capabilities (ugh). + */ + ret = iommu_attach_group(iommu->domain, iommu_group); + if (ret) { + mutex_unlock(&iommu->lock); + kfree(group); + return ret; + } + + group->iommu_group = iommu_group; + list_add(&group->next, &iommu->group_list); + + mutex_unlock(&iommu->lock); + + return 0; +} + +static void vfio_iommu_type1_detach_group(void *iommu_data, + struct iommu_group *iommu_group) +{ + struct vfio_iommu *iommu = iommu_data; + struct vfio_group *group; + + mutex_lock(&iommu->lock); + + list_for_each_entry(group, &iommu->group_list, next) { + if (group->iommu_group == iommu_group) { + iommu_detach_group(iommu->domain, iommu_group); + list_del(&group->next); + kfree(group); + break; + } + } + + mutex_unlock(&iommu->lock); +} + +static void *vfio_iommu_type1_open(unsigned long arg) +{ + struct vfio_iommu *iommu; + + if (arg != VFIO_TYPE1_IOMMU) + return ERR_PTR(-EINVAL); + + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + if (!iommu) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&iommu->group_list); + INIT_LIST_HEAD(&iommu->dma_list); + mutex_init(&iommu->lock); + + /* + * Wish we didn't have to know about bus_type here. + */ + iommu->domain = iommu_domain_alloc(&pci_bus_type); + if (!iommu->domain) { + kfree(iommu); + return ERR_PTR(-EIO); + } + + /* + * Wish we could specify required capabilities rather than create + * a domain, see what comes out and hope it doesn't change along + * the way. Fortunately we know interrupt remapping is global for + * our iommus. + */ + if (!allow_unsafe_interrupts && + !iommu_domain_has_cap(iommu->domain, IOMMU_CAP_INTR_REMAP)) { + pr_warn("%s: No interrupt remapping support. Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n", + __func__); + iommu_domain_free(iommu->domain); + kfree(iommu); + return ERR_PTR(-EPERM); + } + + return iommu; +} + +static void vfio_iommu_type1_release(void *iommu_data) +{ + struct vfio_iommu *iommu = iommu_data; + struct vfio_group *group, *group_tmp; + struct vfio_dma *dma, *dma_tmp; + + list_for_each_entry_safe(group, group_tmp, &iommu->group_list, next) { + iommu_detach_group(iommu->domain, group->iommu_group); + list_del(&group->next); + kfree(group); + } + + list_for_each_entry_safe(dma, dma_tmp, &iommu->dma_list, next) { + vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); + list_del(&dma->next); + kfree(dma); + } + + iommu_domain_free(iommu->domain); + iommu->domain = NULL; + kfree(iommu); +} + +static long vfio_iommu_type1_ioctl(void *iommu_data, + unsigned int cmd, unsigned long arg) +{ + struct vfio_iommu *iommu = iommu_data; + unsigned long minsz; + + if (cmd == VFIO_CHECK_EXTENSION) { + switch (arg) { + case VFIO_TYPE1_IOMMU: + return 1; + default: + return 0; + } + } else if (cmd == VFIO_IOMMU_GET_INFO) { + struct vfio_iommu_type1_info info; + + minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = 0; + + info.iova_pgsizes = iommu->domain->ops->pgsize_bitmap; + + return copy_to_user((void __user *)arg, &info, minsz); + + } else if (cmd == VFIO_IOMMU_MAP_DMA) { + struct vfio_iommu_type1_dma_map map; + uint32_t mask = VFIO_DMA_MAP_FLAG_READ | + VFIO_DMA_MAP_FLAG_WRITE; + + minsz = offsetofend(struct vfio_iommu_type1_dma_map, size); + + if (copy_from_user(&map, (void __user *)arg, minsz)) + return -EFAULT; + + if (map.argsz < minsz || map.flags & ~mask) + return -EINVAL; + + return vfio_dma_do_map(iommu, &map); + + } else if (cmd == VFIO_IOMMU_UNMAP_DMA) { + struct vfio_iommu_type1_dma_unmap unmap; + + minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size); + + if (copy_from_user(&unmap, (void __user *)arg, minsz)) + return -EFAULT; + + if (unmap.argsz < minsz || unmap.flags) + return -EINVAL; + + return vfio_dma_do_unmap(iommu, &unmap); + } + + return -ENOTTY; +} + +static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = { + .name = "vfio-iommu-type1", + .owner = THIS_MODULE, + .open = vfio_iommu_type1_open, + .release = vfio_iommu_type1_release, + .ioctl = vfio_iommu_type1_ioctl, + .attach_group = vfio_iommu_type1_attach_group, + .detach_group = vfio_iommu_type1_detach_group, +}; + +static int __init vfio_iommu_type1_init(void) +{ + if (!iommu_present(&pci_bus_type)) + return -ENODEV; + + return vfio_register_iommu_driver(&vfio_iommu_driver_ops_type1); +} + +static void __exit vfio_iommu_type1_cleanup(void) +{ + vfio_unregister_iommu_driver(&vfio_iommu_driver_ops_type1); +} + +module_init(vfio_iommu_type1_init); +module_exit(vfio_iommu_type1_cleanup); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 03e56a5154b6..acb046fd5b70 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -98,7 +98,7 @@ extern void vfio_unregister_iommu_driver( /* Extensions */ -/* None yet */ +#define VFIO_TYPE1_IOMMU 1 /* * The IOCTL interface is designed for extensibility by embedding the @@ -364,4 +364,56 @@ struct vfio_irq_set { */ #define VFIO_DEVICE_RESET _IO(VFIO_TYPE, VFIO_BASE + 11) +/* -------- API for Type1 VFIO IOMMU -------- */ + +/** + * VFIO_IOMMU_GET_INFO - _IOR(VFIO_TYPE, VFIO_BASE + 12, struct vfio_iommu_info) + * + * Retrieve information about the IOMMU object. Fills in provided + * struct vfio_iommu_info. Caller sets argsz. + * + * XXX Should we do these by CHECK_EXTENSION too? + */ +struct vfio_iommu_type1_info { + __u32 argsz; + __u32 flags; +#define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ + __u64 iova_pgsizes; /* Bitmap of supported page sizes */ +}; + +#define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) + +/** + * VFIO_IOMMU_MAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 13, struct vfio_dma_map) + * + * Map process virtual addresses to IO virtual addresses using the + * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required. + */ +struct vfio_iommu_type1_dma_map { + __u32 argsz; + __u32 flags; +#define VFIO_DMA_MAP_FLAG_READ (1 << 0) /* readable from device */ +#define VFIO_DMA_MAP_FLAG_WRITE (1 << 1) /* writable from device */ + __u64 vaddr; /* Process virtual address */ + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of mapping (bytes) */ +}; + +#define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) + +/** + * VFIO_IOMMU_UNMAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 14, struct vfio_dma_unmap) + * + * Unmap IO virtual addresses using the provided struct vfio_dma_unmap. + * Caller sets argsz. + */ +struct vfio_iommu_type1_dma_unmap { + __u32 argsz; + __u32 flags; + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of mapping (bytes) */ +}; + +#define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14) + #endif /* VFIO_H */ -- GitLab From 89e1f7d4c66d85f42c3d52ea3866eb10cadf6153 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 31 Jul 2012 08:16:24 -0600 Subject: [PATCH 4836/5711] vfio: Add PCI device driver Add PCI device support for VFIO. PCI devices expose regions for accessing config space, I/O port space, and MMIO areas of the device. PCI config access is virtualized in the kernel, allowing us to ensure the integrity of the system, by preventing various accesses while reducing duplicate support across various userspace drivers. I/O port supports read/write access while MMIO also supports mmap of sufficiently sized regions. Support for INTx, MSI, and MSI-X interrupts are provided using eventfds to userspace. Signed-off-by: Alex Williamson --- drivers/vfio/Kconfig | 2 + drivers/vfio/pci/Kconfig | 8 + drivers/vfio/pci/Makefile | 4 + drivers/vfio/pci/vfio_pci.c | 579 ++++++++++ drivers/vfio/pci/vfio_pci_config.c | 1540 +++++++++++++++++++++++++++ drivers/vfio/pci/vfio_pci_intrs.c | 740 +++++++++++++ drivers/vfio/pci/vfio_pci_private.h | 91 ++ drivers/vfio/pci/vfio_pci_rdwr.c | 269 +++++ include/linux/vfio.h | 26 + 9 files changed, 3259 insertions(+) create mode 100644 drivers/vfio/pci/Kconfig create mode 100644 drivers/vfio/pci/Makefile create mode 100644 drivers/vfio/pci/vfio_pci.c create mode 100644 drivers/vfio/pci/vfio_pci_config.c create mode 100644 drivers/vfio/pci/vfio_pci_intrs.c create mode 100644 drivers/vfio/pci/vfio_pci_private.h create mode 100644 drivers/vfio/pci/vfio_pci_rdwr.c diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 128b97910b8e..7cd5dec0abd1 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -12,3 +12,5 @@ menuconfig VFIO See Documentation/vfio.txt for more details. If you don't know what to do here, say N. + +source "drivers/vfio/pci/Kconfig" diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig new file mode 100644 index 000000000000..5980758563eb --- /dev/null +++ b/drivers/vfio/pci/Kconfig @@ -0,0 +1,8 @@ +config VFIO_PCI + tristate "VFIO support for PCI devices" + depends on VFIO && PCI && EVENTFD + help + Support for the PCI VFIO bus driver. This is required to make + use of PCI drivers using the VFIO framework. + + If you don't know what to do here, say N. diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile new file mode 100644 index 000000000000..131079255fd9 --- /dev/null +++ b/drivers/vfio/pci/Makefile @@ -0,0 +1,4 @@ + +vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o + +obj-$(CONFIG_VFIO_PCI) += vfio-pci.o diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c new file mode 100644 index 000000000000..6968b7232232 --- /dev/null +++ b/drivers/vfio/pci/vfio_pci.c @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vfio_pci_private.h" + +#define DRIVER_VERSION "0.2" +#define DRIVER_AUTHOR "Alex Williamson " +#define DRIVER_DESC "VFIO PCI - User Level meta-driver" + +static bool nointxmask; +module_param_named(nointxmask, nointxmask, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(nointxmask, + "Disable support for PCI 2.3 style INTx masking. If this resolves problems for specific devices, report lspci -vvvxxx to linux-pci@vger.kernel.org so the device can be fixed automatically via the broken_intx_masking flag."); + +static int vfio_pci_enable(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + int ret; + u16 cmd; + u8 msix_pos; + + vdev->reset_works = (pci_reset_function(pdev) == 0); + pci_save_state(pdev); + vdev->pci_saved_state = pci_store_saved_state(pdev); + if (!vdev->pci_saved_state) + pr_debug("%s: Couldn't store %s saved state\n", + __func__, dev_name(&pdev->dev)); + + ret = vfio_config_init(vdev); + if (ret) + goto out; + + if (likely(!nointxmask)) + vdev->pci_2_3 = pci_intx_mask_supported(pdev); + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) { + cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + } + + msix_pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + if (msix_pos) { + u16 flags; + u32 table; + + pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags); + pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table); + + vdev->msix_bar = table & PCI_MSIX_FLAGS_BIRMASK; + vdev->msix_offset = table & ~PCI_MSIX_FLAGS_BIRMASK; + vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16; + } else + vdev->msix_bar = 0xFF; + + ret = pci_enable_device(pdev); + if (ret) + goto out; + + return ret; + +out: + kfree(vdev->pci_saved_state); + vdev->pci_saved_state = NULL; + vfio_config_free(vdev); + return ret; +} + +static void vfio_pci_disable(struct vfio_pci_device *vdev) +{ + int bar; + + pci_disable_device(vdev->pdev); + + vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE | + VFIO_IRQ_SET_ACTION_TRIGGER, + vdev->irq_type, 0, 0, NULL); + + vdev->virq_disabled = false; + + vfio_config_free(vdev); + + pci_reset_function(vdev->pdev); + + if (pci_load_and_free_saved_state(vdev->pdev, + &vdev->pci_saved_state) == 0) + pci_restore_state(vdev->pdev); + else + pr_info("%s: Couldn't reload %s saved state\n", + __func__, dev_name(&vdev->pdev->dev)); + + for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { + if (!vdev->barmap[bar]) + continue; + pci_iounmap(vdev->pdev, vdev->barmap[bar]); + pci_release_selected_regions(vdev->pdev, 1 << bar); + vdev->barmap[bar] = NULL; + } +} + +static void vfio_pci_release(void *device_data) +{ + struct vfio_pci_device *vdev = device_data; + + if (atomic_dec_and_test(&vdev->refcnt)) + vfio_pci_disable(vdev); + + module_put(THIS_MODULE); +} + +static int vfio_pci_open(void *device_data) +{ + struct vfio_pci_device *vdev = device_data; + + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + if (atomic_inc_return(&vdev->refcnt) == 1) { + int ret = vfio_pci_enable(vdev); + if (ret) { + module_put(THIS_MODULE); + return ret; + } + } + + return 0; +} + +static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) +{ + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { + u8 pin; + pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); + if (pin) + return 1; + + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { + u8 pos; + u16 flags; + + pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSI); + if (pos) { + pci_read_config_word(vdev->pdev, + pos + PCI_MSI_FLAGS, &flags); + + return 1 << (flags & PCI_MSI_FLAGS_QMASK); + } + } else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) { + u8 pos; + u16 flags; + + pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(vdev->pdev, + pos + PCI_MSIX_FLAGS, &flags); + + return (flags & PCI_MSIX_FLAGS_QSIZE) + 1; + } + } + + return 0; +} + +static long vfio_pci_ioctl(void *device_data, + unsigned int cmd, unsigned long arg) +{ + struct vfio_pci_device *vdev = device_data; + unsigned long minsz; + + if (cmd == VFIO_DEVICE_GET_INFO) { + struct vfio_device_info info; + + minsz = offsetofend(struct vfio_device_info, num_irqs); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = VFIO_DEVICE_FLAGS_PCI; + + if (vdev->reset_works) + info.flags |= VFIO_DEVICE_FLAGS_RESET; + + info.num_regions = VFIO_PCI_NUM_REGIONS; + info.num_irqs = VFIO_PCI_NUM_IRQS; + + return copy_to_user((void __user *)arg, &info, minsz); + + } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) { + struct pci_dev *pdev = vdev->pdev; + struct vfio_region_info info; + + minsz = offsetofend(struct vfio_region_info, offset); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + switch (info.index) { + case VFIO_PCI_CONFIG_REGION_INDEX: + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); + info.size = pdev->cfg_size; + info.flags = VFIO_REGION_INFO_FLAG_READ | + VFIO_REGION_INFO_FLAG_WRITE; + break; + case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX: + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); + info.size = pci_resource_len(pdev, info.index); + if (!info.size) { + info.flags = 0; + break; + } + + info.flags = VFIO_REGION_INFO_FLAG_READ | + VFIO_REGION_INFO_FLAG_WRITE; + if (pci_resource_flags(pdev, info.index) & + IORESOURCE_MEM && info.size >= PAGE_SIZE) + info.flags |= VFIO_REGION_INFO_FLAG_MMAP; + break; + case VFIO_PCI_ROM_REGION_INDEX: + { + void __iomem *io; + size_t size; + + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); + info.flags = 0; + + /* Report the BAR size, not the ROM size */ + info.size = pci_resource_len(pdev, info.index); + if (!info.size) + break; + + /* Is it really there? */ + io = pci_map_rom(pdev, &size); + if (!io || !size) { + info.size = 0; + break; + } + pci_unmap_rom(pdev, io); + + info.flags = VFIO_REGION_INFO_FLAG_READ; + break; + } + default: + return -EINVAL; + } + + return copy_to_user((void __user *)arg, &info, minsz); + + } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { + struct vfio_irq_info info; + + minsz = offsetofend(struct vfio_irq_info, count); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS) + return -EINVAL; + + info.flags = VFIO_IRQ_INFO_EVENTFD; + + info.count = vfio_pci_get_irq_count(vdev, info.index); + + if (info.index == VFIO_PCI_INTX_IRQ_INDEX) + info.flags |= (VFIO_IRQ_INFO_MASKABLE | + VFIO_IRQ_INFO_AUTOMASKED); + else + info.flags |= VFIO_IRQ_INFO_NORESIZE; + + return copy_to_user((void __user *)arg, &info, minsz); + + } else if (cmd == VFIO_DEVICE_SET_IRQS) { + struct vfio_irq_set hdr; + u8 *data = NULL; + int ret = 0; + + minsz = offsetofend(struct vfio_irq_set, count); + + if (copy_from_user(&hdr, (void __user *)arg, minsz)) + return -EFAULT; + + if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || + hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | + VFIO_IRQ_SET_ACTION_TYPE_MASK)) + return -EINVAL; + + if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { + size_t size; + + if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) + size = sizeof(uint8_t); + else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) + size = sizeof(int32_t); + else + return -EINVAL; + + if (hdr.argsz - minsz < hdr.count * size || + hdr.count > vfio_pci_get_irq_count(vdev, hdr.index)) + return -EINVAL; + + data = kmalloc(hdr.count * size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + if (copy_from_user(data, (void __user *)(arg + minsz), + hdr.count * size)) { + kfree(data); + return -EFAULT; + } + } + + mutex_lock(&vdev->igate); + + ret = vfio_pci_set_irqs_ioctl(vdev, hdr.flags, hdr.index, + hdr.start, hdr.count, data); + + mutex_unlock(&vdev->igate); + kfree(data); + + return ret; + + } else if (cmd == VFIO_DEVICE_RESET) + return vdev->reset_works ? + pci_reset_function(vdev->pdev) : -EINVAL; + + return -ENOTTY; +} + +static ssize_t vfio_pci_read(void *device_data, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos); + struct vfio_pci_device *vdev = device_data; + struct pci_dev *pdev = vdev->pdev; + + if (index >= VFIO_PCI_NUM_REGIONS) + return -EINVAL; + + if (index == VFIO_PCI_CONFIG_REGION_INDEX) + return vfio_pci_config_readwrite(vdev, buf, count, ppos, false); + else if (index == VFIO_PCI_ROM_REGION_INDEX) + return vfio_pci_mem_readwrite(vdev, buf, count, ppos, false); + else if (pci_resource_flags(pdev, index) & IORESOURCE_IO) + return vfio_pci_io_readwrite(vdev, buf, count, ppos, false); + else if (pci_resource_flags(pdev, index) & IORESOURCE_MEM) + return vfio_pci_mem_readwrite(vdev, buf, count, ppos, false); + + return -EINVAL; +} + +static ssize_t vfio_pci_write(void *device_data, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos); + struct vfio_pci_device *vdev = device_data; + struct pci_dev *pdev = vdev->pdev; + + if (index >= VFIO_PCI_NUM_REGIONS) + return -EINVAL; + + if (index == VFIO_PCI_CONFIG_REGION_INDEX) + return vfio_pci_config_readwrite(vdev, (char __user *)buf, + count, ppos, true); + else if (index == VFIO_PCI_ROM_REGION_INDEX) + return -EINVAL; + else if (pci_resource_flags(pdev, index) & IORESOURCE_IO) + return vfio_pci_io_readwrite(vdev, (char __user *)buf, + count, ppos, true); + else if (pci_resource_flags(pdev, index) & IORESOURCE_MEM) { + return vfio_pci_mem_readwrite(vdev, (char __user *)buf, + count, ppos, true); + } + + return -EINVAL; +} + +static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) +{ + struct vfio_pci_device *vdev = device_data; + struct pci_dev *pdev = vdev->pdev; + unsigned int index; + u64 phys_len, req_len, pgoff, req_start, phys; + int ret; + + index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT); + + if (vma->vm_end < vma->vm_start) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + if (index >= VFIO_PCI_ROM_REGION_INDEX) + return -EINVAL; + if (!(pci_resource_flags(pdev, index) & IORESOURCE_MEM)) + return -EINVAL; + + phys_len = pci_resource_len(pdev, index); + req_len = vma->vm_end - vma->vm_start; + pgoff = vma->vm_pgoff & + ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); + req_start = pgoff << PAGE_SHIFT; + + if (phys_len < PAGE_SIZE || req_start + req_len > phys_len) + return -EINVAL; + + if (index == vdev->msix_bar) { + /* + * Disallow mmaps overlapping the MSI-X table; users don't + * get to touch this directly. We could find somewhere + * else to map the overlap, but page granularity is only + * a recommendation, not a requirement, so the user needs + * to know which bits are real. Requiring them to mmap + * around the table makes that clear. + */ + + /* If neither entirely above nor below, then it overlaps */ + if (!(req_start >= vdev->msix_offset + vdev->msix_size || + req_start + req_len <= vdev->msix_offset)) + return -EINVAL; + } + + /* + * Even though we don't make use of the barmap for the mmap, + * we need to request the region and the barmap tracks that. + */ + if (!vdev->barmap[index]) { + ret = pci_request_selected_regions(pdev, + 1 << index, "vfio-pci"); + if (ret) + return ret; + + vdev->barmap[index] = pci_iomap(pdev, index, 0); + } + + vma->vm_private_data = vdev; + vma->vm_flags |= (VM_IO | VM_RESERVED); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + phys = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff; + + return remap_pfn_range(vma, vma->vm_start, phys, + req_len, vma->vm_page_prot); +} + +static const struct vfio_device_ops vfio_pci_ops = { + .name = "vfio-pci", + .open = vfio_pci_open, + .release = vfio_pci_release, + .ioctl = vfio_pci_ioctl, + .read = vfio_pci_read, + .write = vfio_pci_write, + .mmap = vfio_pci_mmap, +}; + +static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + u8 type; + struct vfio_pci_device *vdev; + struct iommu_group *group; + int ret; + + pci_read_config_byte(pdev, PCI_HEADER_TYPE, &type); + if ((type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) + return -EINVAL; + + group = iommu_group_get(&pdev->dev); + if (!group) + return -EINVAL; + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) { + iommu_group_put(group); + return -ENOMEM; + } + + vdev->pdev = pdev; + vdev->irq_type = VFIO_PCI_NUM_IRQS; + mutex_init(&vdev->igate); + spin_lock_init(&vdev->irqlock); + atomic_set(&vdev->refcnt, 0); + + ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); + if (ret) { + iommu_group_put(group); + kfree(vdev); + } + + return ret; +} + +static void vfio_pci_remove(struct pci_dev *pdev) +{ + struct vfio_pci_device *vdev; + + vdev = vfio_del_group_dev(&pdev->dev); + if (!vdev) + return; + + iommu_group_put(pdev->dev.iommu_group); + kfree(vdev); +} + +static struct pci_driver vfio_pci_driver = { + .name = "vfio-pci", + .id_table = NULL, /* only dynamic ids */ + .probe = vfio_pci_probe, + .remove = vfio_pci_remove, +}; + +static void __exit vfio_pci_cleanup(void) +{ + pci_unregister_driver(&vfio_pci_driver); + vfio_pci_virqfd_exit(); + vfio_pci_uninit_perm_bits(); +} + +static int __init vfio_pci_init(void) +{ + int ret; + + /* Allocate shared config space permision data used by all devices */ + ret = vfio_pci_init_perm_bits(); + if (ret) + return ret; + + /* Start the virqfd cleanup handler */ + ret = vfio_pci_virqfd_init(); + if (ret) + goto out_virqfd; + + /* Register and scan for devices */ + ret = pci_register_driver(&vfio_pci_driver); + if (ret) + goto out_driver; + + return 0; + +out_virqfd: + vfio_pci_virqfd_exit(); +out_driver: + vfio_pci_uninit_perm_bits(); + return ret; +} + +module_init(vfio_pci_init); +module_exit(vfio_pci_cleanup); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c new file mode 100644 index 000000000000..8b8f7d11e102 --- /dev/null +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -0,0 +1,1540 @@ +/* + * VFIO PCI config space virtualization + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +/* + * This code handles reading and writing of PCI configuration registers. + * This is hairy because we want to allow a lot of flexibility to the + * user driver, but cannot trust it with all of the config fields. + * Tables determine which fields can be read and written, as well as + * which fields are 'virtualized' - special actions and translations to + * make it appear to the user that he has control, when in fact things + * must be negotiated with the underlying OS. + */ + +#include +#include +#include +#include + +#include "vfio_pci_private.h" + +#define PCI_CFG_SPACE_SIZE 256 + +/* Useful "pseudo" capabilities */ +#define PCI_CAP_ID_BASIC 0 +#define PCI_CAP_ID_INVALID 0xFF + +#define is_bar(offset) \ + ((offset >= PCI_BASE_ADDRESS_0 && offset < PCI_BASE_ADDRESS_5 + 4) || \ + (offset >= PCI_ROM_ADDRESS && offset < PCI_ROM_ADDRESS + 4)) + +/* + * Lengths of PCI Config Capabilities + * 0: Removed from the user visible capability list + * FF: Variable length + */ +static u8 pci_cap_length[] = { + [PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */ + [PCI_CAP_ID_PM] = PCI_PM_SIZEOF, + [PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF, + [PCI_CAP_ID_VPD] = PCI_CAP_VPD_SIZEOF, + [PCI_CAP_ID_SLOTID] = 0, /* bridge - don't care */ + [PCI_CAP_ID_MSI] = 0xFF, /* 10, 14, 20, or 24 */ + [PCI_CAP_ID_CHSWP] = 0, /* cpci - not yet */ + [PCI_CAP_ID_PCIX] = 0xFF, /* 8 or 24 */ + [PCI_CAP_ID_HT] = 0xFF, /* hypertransport */ + [PCI_CAP_ID_VNDR] = 0xFF, /* variable */ + [PCI_CAP_ID_DBG] = 0, /* debug - don't care */ + [PCI_CAP_ID_CCRC] = 0, /* cpci - not yet */ + [PCI_CAP_ID_SHPC] = 0, /* hotswap - not yet */ + [PCI_CAP_ID_SSVID] = 0, /* bridge - don't care */ + [PCI_CAP_ID_AGP3] = 0, /* AGP8x - not yet */ + [PCI_CAP_ID_SECDEV] = 0, /* secure device not yet */ + [PCI_CAP_ID_EXP] = 0xFF, /* 20 or 44 */ + [PCI_CAP_ID_MSIX] = PCI_CAP_MSIX_SIZEOF, + [PCI_CAP_ID_SATA] = 0xFF, + [PCI_CAP_ID_AF] = PCI_CAP_AF_SIZEOF, +}; + +/* + * Lengths of PCIe/PCI-X Extended Config Capabilities + * 0: Removed or masked from the user visible capabilty list + * FF: Variable length + */ +static u16 pci_ext_cap_length[] = { + [PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND, + [PCI_EXT_CAP_ID_VC] = 0xFF, + [PCI_EXT_CAP_ID_DSN] = PCI_EXT_CAP_DSN_SIZEOF, + [PCI_EXT_CAP_ID_PWR] = PCI_EXT_CAP_PWR_SIZEOF, + [PCI_EXT_CAP_ID_RCLD] = 0, /* root only - don't care */ + [PCI_EXT_CAP_ID_RCILC] = 0, /* root only - don't care */ + [PCI_EXT_CAP_ID_RCEC] = 0, /* root only - don't care */ + [PCI_EXT_CAP_ID_MFVC] = 0xFF, + [PCI_EXT_CAP_ID_VC9] = 0xFF, /* same as CAP_ID_VC */ + [PCI_EXT_CAP_ID_RCRB] = 0, /* root only - don't care */ + [PCI_EXT_CAP_ID_VNDR] = 0xFF, + [PCI_EXT_CAP_ID_CAC] = 0, /* obsolete */ + [PCI_EXT_CAP_ID_ACS] = 0xFF, + [PCI_EXT_CAP_ID_ARI] = PCI_EXT_CAP_ARI_SIZEOF, + [PCI_EXT_CAP_ID_ATS] = PCI_EXT_CAP_ATS_SIZEOF, + [PCI_EXT_CAP_ID_SRIOV] = PCI_EXT_CAP_SRIOV_SIZEOF, + [PCI_EXT_CAP_ID_MRIOV] = 0, /* not yet */ + [PCI_EXT_CAP_ID_MCAST] = PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF, + [PCI_EXT_CAP_ID_PRI] = PCI_EXT_CAP_PRI_SIZEOF, + [PCI_EXT_CAP_ID_AMD_XXX] = 0, /* not yet */ + [PCI_EXT_CAP_ID_REBAR] = 0xFF, + [PCI_EXT_CAP_ID_DPA] = 0xFF, + [PCI_EXT_CAP_ID_TPH] = 0xFF, + [PCI_EXT_CAP_ID_LTR] = PCI_EXT_CAP_LTR_SIZEOF, + [PCI_EXT_CAP_ID_SECPCI] = 0, /* not yet */ + [PCI_EXT_CAP_ID_PMUX] = 0, /* not yet */ + [PCI_EXT_CAP_ID_PASID] = 0, /* not yet */ +}; + +/* + * Read/Write Permission Bits - one bit for each bit in capability + * Any field can be read if it exists, but what is read depends on + * whether the field is 'virtualized', or just pass thru to the + * hardware. Any virtualized field is also virtualized for writes. + * Writes are only permitted if they have a 1 bit here. + */ +struct perm_bits { + u8 *virt; /* read/write virtual data, not hw */ + u8 *write; /* writeable bits */ + int (*readfn)(struct vfio_pci_device *vdev, int pos, int count, + struct perm_bits *perm, int offset, __le32 *val); + int (*writefn)(struct vfio_pci_device *vdev, int pos, int count, + struct perm_bits *perm, int offset, __le32 val); +}; + +#define NO_VIRT 0 +#define ALL_VIRT 0xFFFFFFFFU +#define NO_WRITE 0 +#define ALL_WRITE 0xFFFFFFFFU + +static int vfio_user_config_read(struct pci_dev *pdev, int offset, + __le32 *val, int count) +{ + int ret = -EINVAL; + u32 tmp_val = 0; + + switch (count) { + case 1: + { + u8 tmp; + ret = pci_user_read_config_byte(pdev, offset, &tmp); + tmp_val = tmp; + break; + } + case 2: + { + u16 tmp; + ret = pci_user_read_config_word(pdev, offset, &tmp); + tmp_val = tmp; + break; + } + case 4: + ret = pci_user_read_config_dword(pdev, offset, &tmp_val); + break; + } + + *val = cpu_to_le32(tmp_val); + + return pcibios_err_to_errno(ret); +} + +static int vfio_user_config_write(struct pci_dev *pdev, int offset, + __le32 val, int count) +{ + int ret = -EINVAL; + u32 tmp_val = le32_to_cpu(val); + + switch (count) { + case 1: + ret = pci_user_write_config_byte(pdev, offset, tmp_val); + break; + case 2: + ret = pci_user_write_config_word(pdev, offset, tmp_val); + break; + case 4: + ret = pci_user_write_config_dword(pdev, offset, tmp_val); + break; + } + + return pcibios_err_to_errno(ret); +} + +static int vfio_default_config_read(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 *val) +{ + __le32 virt = 0; + + memcpy(val, vdev->vconfig + pos, count); + + memcpy(&virt, perm->virt + offset, count); + + /* Any non-virtualized bits? */ + if (cpu_to_le32(~0U >> (32 - (count * 8))) != virt) { + struct pci_dev *pdev = vdev->pdev; + __le32 phys_val = 0; + int ret; + + ret = vfio_user_config_read(pdev, pos, &phys_val, count); + if (ret) + return ret; + + *val = (phys_val & ~virt) | (*val & virt); + } + + return count; +} + +static int vfio_default_config_write(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 val) +{ + __le32 virt = 0, write = 0; + + memcpy(&write, perm->write + offset, count); + + if (!write) + return count; /* drop, no writable bits */ + + memcpy(&virt, perm->virt + offset, count); + + /* Virtualized and writable bits go to vconfig */ + if (write & virt) { + __le32 virt_val = 0; + + memcpy(&virt_val, vdev->vconfig + pos, count); + + virt_val &= ~(write & virt); + virt_val |= (val & (write & virt)); + + memcpy(vdev->vconfig + pos, &virt_val, count); + } + + /* Non-virtualzed and writable bits go to hardware */ + if (write & ~virt) { + struct pci_dev *pdev = vdev->pdev; + __le32 phys_val = 0; + int ret; + + ret = vfio_user_config_read(pdev, pos, &phys_val, count); + if (ret) + return ret; + + phys_val &= ~(write & ~virt); + phys_val |= (val & (write & ~virt)); + + ret = vfio_user_config_write(pdev, pos, phys_val, count); + if (ret) + return ret; + } + + return count; +} + +/* Allow direct read from hardware, except for capability next pointer */ +static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 *val) +{ + int ret; + + ret = vfio_user_config_read(vdev->pdev, pos, val, count); + if (ret) + return pcibios_err_to_errno(ret); + + if (pos >= PCI_CFG_SPACE_SIZE) { /* Extended cap header mangling */ + if (offset < 4) + memcpy(val, vdev->vconfig + pos, count); + } else if (pos >= PCI_STD_HEADER_SIZEOF) { /* Std cap mangling */ + if (offset == PCI_CAP_LIST_ID && count > 1) + memcpy(val, vdev->vconfig + pos, + min(PCI_CAP_FLAGS, count)); + else if (offset == PCI_CAP_LIST_NEXT) + memcpy(val, vdev->vconfig + pos, 1); + } + + return count; +} + +static int vfio_direct_config_write(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 val) +{ + int ret; + + ret = vfio_user_config_write(vdev->pdev, pos, val, count); + if (ret) + return ret; + + return count; +} + +/* Default all regions to read-only, no-virtualization */ +static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = { + [0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read } +}; +static struct perm_bits ecap_perms[PCI_EXT_CAP_ID_MAX + 1] = { + [0 ... PCI_EXT_CAP_ID_MAX] = { .readfn = vfio_direct_config_read } +}; + +static void free_perm_bits(struct perm_bits *perm) +{ + kfree(perm->virt); + kfree(perm->write); + perm->virt = NULL; + perm->write = NULL; +} + +static int alloc_perm_bits(struct perm_bits *perm, int size) +{ + /* + * Round up all permission bits to the next dword, this lets us + * ignore whether a read/write exceeds the defined capability + * structure. We can do this because: + * - Standard config space is already dword aligned + * - Capabilities are all dword alinged (bits 0:1 of next reserved) + * - Express capabilities defined as dword aligned + */ + size = round_up(size, 4); + + /* + * Zero state is + * - All Readable, None Writeable, None Virtualized + */ + perm->virt = kzalloc(size, GFP_KERNEL); + perm->write = kzalloc(size, GFP_KERNEL); + if (!perm->virt || !perm->write) { + free_perm_bits(perm); + return -ENOMEM; + } + + perm->readfn = vfio_default_config_read; + perm->writefn = vfio_default_config_write; + + return 0; +} + +/* + * Helper functions for filling in permission tables + */ +static inline void p_setb(struct perm_bits *p, int off, u8 virt, u8 write) +{ + p->virt[off] = virt; + p->write[off] = write; +} + +/* Handle endian-ness - pci and tables are little-endian */ +static inline void p_setw(struct perm_bits *p, int off, u16 virt, u16 write) +{ + *(__le16 *)(&p->virt[off]) = cpu_to_le16(virt); + *(__le16 *)(&p->write[off]) = cpu_to_le16(write); +} + +/* Handle endian-ness - pci and tables are little-endian */ +static inline void p_setd(struct perm_bits *p, int off, u32 virt, u32 write) +{ + *(__le32 *)(&p->virt[off]) = cpu_to_le32(virt); + *(__le32 *)(&p->write[off]) = cpu_to_le32(write); +} + +/* + * Restore the *real* BARs after we detect a FLR or backdoor reset. + * (backdoor = some device specific technique that we didn't catch) + */ +static void vfio_bar_restore(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + u32 *rbar = vdev->rbar; + int i; + + if (pdev->is_virtfn) + return; + + pr_info("%s: %s reset recovery - restoring bars\n", + __func__, dev_name(&pdev->dev)); + + for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4, rbar++) + pci_user_write_config_dword(pdev, i, *rbar); + + pci_user_write_config_dword(pdev, PCI_ROM_ADDRESS, *rbar); +} + +static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar) +{ + unsigned long flags = pci_resource_flags(pdev, bar); + u32 val; + + if (flags & IORESOURCE_IO) + return cpu_to_le32(PCI_BASE_ADDRESS_SPACE_IO); + + val = PCI_BASE_ADDRESS_SPACE_MEMORY; + + if (flags & IORESOURCE_PREFETCH) + val |= PCI_BASE_ADDRESS_MEM_PREFETCH; + + if (flags & IORESOURCE_MEM_64) + val |= PCI_BASE_ADDRESS_MEM_TYPE_64; + + return cpu_to_le32(val); +} + +/* + * Pretend we're hardware and tweak the values of the *virtual* PCI BARs + * to reflect the hardware capabilities. This implements BAR sizing. + */ +static void vfio_bar_fixup(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + int i; + __le32 *bar; + u64 mask; + + bar = (__le32 *)&vdev->vconfig[PCI_BASE_ADDRESS_0]; + + for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++, bar++) { + if (!pci_resource_start(pdev, i)) { + *bar = 0; /* Unmapped by host = unimplemented to user */ + continue; + } + + mask = ~(pci_resource_len(pdev, i) - 1); + + *bar &= cpu_to_le32((u32)mask); + *bar |= vfio_generate_bar_flags(pdev, i); + + if (*bar & cpu_to_le32(PCI_BASE_ADDRESS_MEM_TYPE_64)) { + bar++; + *bar &= cpu_to_le32((u32)(mask >> 32)); + i++; + } + } + + bar = (__le32 *)&vdev->vconfig[PCI_ROM_ADDRESS]; + + /* + * NB. we expose the actual BAR size here, regardless of whether + * we can read it. When we report the REGION_INFO for the ROM + * we report what PCI tells us is the actual ROM size. + */ + if (pci_resource_start(pdev, PCI_ROM_RESOURCE)) { + mask = ~(pci_resource_len(pdev, PCI_ROM_RESOURCE) - 1); + mask |= PCI_ROM_ADDRESS_ENABLE; + *bar &= cpu_to_le32((u32)mask); + } else + *bar = 0; + + vdev->bardirty = false; +} + +static int vfio_basic_config_read(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 *val) +{ + if (is_bar(offset)) /* pos == offset for basic config */ + vfio_bar_fixup(vdev); + + count = vfio_default_config_read(vdev, pos, count, perm, offset, val); + + /* Mask in virtual memory enable for SR-IOV devices */ + if (offset == PCI_COMMAND && vdev->pdev->is_virtfn) { + u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]); + u32 tmp_val = le32_to_cpu(*val); + + tmp_val |= cmd & PCI_COMMAND_MEMORY; + *val = cpu_to_le32(tmp_val); + } + + return count; +} + +static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 val) +{ + struct pci_dev *pdev = vdev->pdev; + __le16 *virt_cmd; + u16 new_cmd = 0; + int ret; + + virt_cmd = (__le16 *)&vdev->vconfig[PCI_COMMAND]; + + if (offset == PCI_COMMAND) { + bool phys_mem, virt_mem, new_mem, phys_io, virt_io, new_io; + u16 phys_cmd; + + ret = pci_user_read_config_word(pdev, PCI_COMMAND, &phys_cmd); + if (ret) + return ret; + + new_cmd = le32_to_cpu(val); + + phys_mem = !!(phys_cmd & PCI_COMMAND_MEMORY); + virt_mem = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_MEMORY); + new_mem = !!(new_cmd & PCI_COMMAND_MEMORY); + + phys_io = !!(phys_cmd & PCI_COMMAND_IO); + virt_io = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_IO); + new_io = !!(new_cmd & PCI_COMMAND_IO); + + /* + * If the user is writing mem/io enable (new_mem/io) and we + * think it's already enabled (virt_mem/io), but the hardware + * shows it disabled (phys_mem/io, then the device has + * undergone some kind of backdoor reset and needs to be + * restored before we allow it to enable the bars. + * SR-IOV devices will trigger this, but we catch them later + */ + if ((new_mem && virt_mem && !phys_mem) || + (new_io && virt_io && !phys_io)) + vfio_bar_restore(vdev); + } + + count = vfio_default_config_write(vdev, pos, count, perm, offset, val); + if (count < 0) + return count; + + /* + * Save current memory/io enable bits in vconfig to allow for + * the test above next time. + */ + if (offset == PCI_COMMAND) { + u16 mask = PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + + *virt_cmd &= cpu_to_le16(~mask); + *virt_cmd |= cpu_to_le16(new_cmd & mask); + } + + /* Emulate INTx disable */ + if (offset >= PCI_COMMAND && offset <= PCI_COMMAND + 1) { + bool virt_intx_disable; + + virt_intx_disable = !!(le16_to_cpu(*virt_cmd) & + PCI_COMMAND_INTX_DISABLE); + + if (virt_intx_disable && !vdev->virq_disabled) { + vdev->virq_disabled = true; + vfio_pci_intx_mask(vdev); + } else if (!virt_intx_disable && vdev->virq_disabled) { + vdev->virq_disabled = false; + vfio_pci_intx_unmask(vdev); + } + } + + if (is_bar(offset)) + vdev->bardirty = true; + + return count; +} + +/* Permissions for the Basic PCI Header */ +static int __init init_pci_cap_basic_perm(struct perm_bits *perm) +{ + if (alloc_perm_bits(perm, PCI_STD_HEADER_SIZEOF)) + return -ENOMEM; + + perm->readfn = vfio_basic_config_read; + perm->writefn = vfio_basic_config_write; + + /* Virtualized for SR-IOV functions, which just have FFFF */ + p_setw(perm, PCI_VENDOR_ID, (u16)ALL_VIRT, NO_WRITE); + p_setw(perm, PCI_DEVICE_ID, (u16)ALL_VIRT, NO_WRITE); + + /* + * Virtualize INTx disable, we use it internally for interrupt + * control and can emulate it for non-PCI 2.3 devices. + */ + p_setw(perm, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE, (u16)ALL_WRITE); + + /* Virtualize capability list, we might want to skip/disable */ + p_setw(perm, PCI_STATUS, PCI_STATUS_CAP_LIST, NO_WRITE); + + /* No harm to write */ + p_setb(perm, PCI_CACHE_LINE_SIZE, NO_VIRT, (u8)ALL_WRITE); + p_setb(perm, PCI_LATENCY_TIMER, NO_VIRT, (u8)ALL_WRITE); + p_setb(perm, PCI_BIST, NO_VIRT, (u8)ALL_WRITE); + + /* Virtualize all bars, can't touch the real ones */ + p_setd(perm, PCI_BASE_ADDRESS_0, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_BASE_ADDRESS_1, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_BASE_ADDRESS_2, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_BASE_ADDRESS_3, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_BASE_ADDRESS_4, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_BASE_ADDRESS_5, ALL_VIRT, ALL_WRITE); + p_setd(perm, PCI_ROM_ADDRESS, ALL_VIRT, ALL_WRITE); + + /* Allow us to adjust capability chain */ + p_setb(perm, PCI_CAPABILITY_LIST, (u8)ALL_VIRT, NO_WRITE); + + /* Sometimes used by sw, just virtualize */ + p_setb(perm, PCI_INTERRUPT_LINE, (u8)ALL_VIRT, (u8)ALL_WRITE); + return 0; +} + +/* Permissions for the Power Management capability */ +static int __init init_pci_cap_pm_perm(struct perm_bits *perm) +{ + if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_PM])) + return -ENOMEM; + + /* + * We always virtualize the next field so we can remove + * capabilities from the chain if we want to. + */ + p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); + + /* + * Power management is defined *per function*, + * so we let the user write this + */ + p_setd(perm, PCI_PM_CTRL, NO_VIRT, ALL_WRITE); + return 0; +} + +/* Permissions for PCI-X capability */ +static int __init init_pci_cap_pcix_perm(struct perm_bits *perm) +{ + /* Alloc 24, but only 8 are used in v0 */ + if (alloc_perm_bits(perm, PCI_CAP_PCIX_SIZEOF_V2)) + return -ENOMEM; + + p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); + + p_setw(perm, PCI_X_CMD, NO_VIRT, (u16)ALL_WRITE); + p_setd(perm, PCI_X_ECC_CSR, NO_VIRT, ALL_WRITE); + return 0; +} + +/* Permissions for PCI Express capability */ +static int __init init_pci_cap_exp_perm(struct perm_bits *perm) +{ + /* Alloc larger of two possible sizes */ + if (alloc_perm_bits(perm, PCI_CAP_EXP_ENDPOINT_SIZEOF_V2)) + return -ENOMEM; + + p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); + + /* + * Allow writes to device control fields (includes FLR!) + * but not to devctl_phantom which could confuse IOMMU + * or to the ARI bit in devctl2 which is set at probe time + */ + p_setw(perm, PCI_EXP_DEVCTL, NO_VIRT, ~PCI_EXP_DEVCTL_PHANTOM); + p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI); + return 0; +} + +/* Permissions for Advanced Function capability */ +static int __init init_pci_cap_af_perm(struct perm_bits *perm) +{ + if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_AF])) + return -ENOMEM; + + p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); + p_setb(perm, PCI_AF_CTRL, NO_VIRT, PCI_AF_CTRL_FLR); + return 0; +} + +/* Permissions for Advanced Error Reporting extended capability */ +static int __init init_pci_ext_cap_err_perm(struct perm_bits *perm) +{ + u32 mask; + + if (alloc_perm_bits(perm, pci_ext_cap_length[PCI_EXT_CAP_ID_ERR])) + return -ENOMEM; + + /* + * Virtualize the first dword of all express capabilities + * because it includes the next pointer. This lets us later + * remove capabilities from the chain if we need to. + */ + p_setd(perm, 0, ALL_VIRT, NO_WRITE); + + /* Writable bits mask */ + mask = PCI_ERR_UNC_TRAIN | /* Training */ + PCI_ERR_UNC_DLP | /* Data Link Protocol */ + PCI_ERR_UNC_SURPDN | /* Surprise Down */ + PCI_ERR_UNC_POISON_TLP | /* Poisoned TLP */ + PCI_ERR_UNC_FCP | /* Flow Control Protocol */ + PCI_ERR_UNC_COMP_TIME | /* Completion Timeout */ + PCI_ERR_UNC_COMP_ABORT | /* Completer Abort */ + PCI_ERR_UNC_UNX_COMP | /* Unexpected Completion */ + PCI_ERR_UNC_RX_OVER | /* Receiver Overflow */ + PCI_ERR_UNC_MALF_TLP | /* Malformed TLP */ + PCI_ERR_UNC_ECRC | /* ECRC Error Status */ + PCI_ERR_UNC_UNSUP | /* Unsupported Request */ + PCI_ERR_UNC_ACSV | /* ACS Violation */ + PCI_ERR_UNC_INTN | /* internal error */ + PCI_ERR_UNC_MCBTLP | /* MC blocked TLP */ + PCI_ERR_UNC_ATOMEG | /* Atomic egress blocked */ + PCI_ERR_UNC_TLPPRE; /* TLP prefix blocked */ + p_setd(perm, PCI_ERR_UNCOR_STATUS, NO_VIRT, mask); + p_setd(perm, PCI_ERR_UNCOR_MASK, NO_VIRT, mask); + p_setd(perm, PCI_ERR_UNCOR_SEVER, NO_VIRT, mask); + + mask = PCI_ERR_COR_RCVR | /* Receiver Error Status */ + PCI_ERR_COR_BAD_TLP | /* Bad TLP Status */ + PCI_ERR_COR_BAD_DLLP | /* Bad DLLP Status */ + PCI_ERR_COR_REP_ROLL | /* REPLAY_NUM Rollover */ + PCI_ERR_COR_REP_TIMER | /* Replay Timer Timeout */ + PCI_ERR_COR_ADV_NFAT | /* Advisory Non-Fatal */ + PCI_ERR_COR_INTERNAL | /* Corrected Internal */ + PCI_ERR_COR_LOG_OVER; /* Header Log Overflow */ + p_setd(perm, PCI_ERR_COR_STATUS, NO_VIRT, mask); + p_setd(perm, PCI_ERR_COR_MASK, NO_VIRT, mask); + + mask = PCI_ERR_CAP_ECRC_GENE | /* ECRC Generation Enable */ + PCI_ERR_CAP_ECRC_CHKE; /* ECRC Check Enable */ + p_setd(perm, PCI_ERR_CAP, NO_VIRT, mask); + return 0; +} + +/* Permissions for Power Budgeting extended capability */ +static int __init init_pci_ext_cap_pwr_perm(struct perm_bits *perm) +{ + if (alloc_perm_bits(perm, pci_ext_cap_length[PCI_EXT_CAP_ID_PWR])) + return -ENOMEM; + + p_setd(perm, 0, ALL_VIRT, NO_WRITE); + + /* Writing the data selector is OK, the info is still read-only */ + p_setb(perm, PCI_PWR_DATA, NO_VIRT, (u8)ALL_WRITE); + return 0; +} + +/* + * Initialize the shared permission tables + */ +void vfio_pci_uninit_perm_bits(void) +{ + free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]); + + free_perm_bits(&cap_perms[PCI_CAP_ID_PM]); + free_perm_bits(&cap_perms[PCI_CAP_ID_PCIX]); + free_perm_bits(&cap_perms[PCI_CAP_ID_EXP]); + free_perm_bits(&cap_perms[PCI_CAP_ID_AF]); + + free_perm_bits(&ecap_perms[PCI_EXT_CAP_ID_ERR]); + free_perm_bits(&ecap_perms[PCI_EXT_CAP_ID_PWR]); +} + +int __init vfio_pci_init_perm_bits(void) +{ + int ret; + + /* Basic config space */ + ret = init_pci_cap_basic_perm(&cap_perms[PCI_CAP_ID_BASIC]); + + /* Capabilities */ + ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]); + cap_perms[PCI_CAP_ID_VPD].writefn = vfio_direct_config_write; + ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]); + cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_direct_config_write; + ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]); + ret |= init_pci_cap_af_perm(&cap_perms[PCI_CAP_ID_AF]); + + /* Extended capabilities */ + ret |= init_pci_ext_cap_err_perm(&ecap_perms[PCI_EXT_CAP_ID_ERR]); + ret |= init_pci_ext_cap_pwr_perm(&ecap_perms[PCI_EXT_CAP_ID_PWR]); + ecap_perms[PCI_EXT_CAP_ID_VNDR].writefn = vfio_direct_config_write; + + if (ret) + vfio_pci_uninit_perm_bits(); + + return ret; +} + +static int vfio_find_cap_start(struct vfio_pci_device *vdev, int pos) +{ + u8 cap; + int base = (pos >= PCI_CFG_SPACE_SIZE) ? PCI_CFG_SPACE_SIZE : + PCI_STD_HEADER_SIZEOF; + base /= 4; + pos /= 4; + + cap = vdev->pci_config_map[pos]; + + if (cap == PCI_CAP_ID_BASIC) + return 0; + + /* XXX Can we have to abutting capabilities of the same type? */ + while (pos - 1 >= base && vdev->pci_config_map[pos - 1] == cap) + pos--; + + return pos * 4; +} + +static int vfio_msi_config_read(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 *val) +{ + /* Update max available queue size from msi_qmax */ + if (offset <= PCI_MSI_FLAGS && offset + count >= PCI_MSI_FLAGS) { + __le16 *flags; + int start; + + start = vfio_find_cap_start(vdev, pos); + + flags = (__le16 *)&vdev->vconfig[start]; + + *flags &= cpu_to_le16(~PCI_MSI_FLAGS_QMASK); + *flags |= cpu_to_le16(vdev->msi_qmax << 1); + } + + return vfio_default_config_read(vdev, pos, count, perm, offset, val); +} + +static int vfio_msi_config_write(struct vfio_pci_device *vdev, int pos, + int count, struct perm_bits *perm, + int offset, __le32 val) +{ + count = vfio_default_config_write(vdev, pos, count, perm, offset, val); + if (count < 0) + return count; + + /* Fixup and write configured queue size and enable to hardware */ + if (offset <= PCI_MSI_FLAGS && offset + count >= PCI_MSI_FLAGS) { + __le16 *pflags; + u16 flags; + int start, ret; + + start = vfio_find_cap_start(vdev, pos); + + pflags = (__le16 *)&vdev->vconfig[start + PCI_MSI_FLAGS]; + + flags = le16_to_cpu(*pflags); + + /* MSI is enabled via ioctl */ + if (!is_msi(vdev)) + flags &= ~PCI_MSI_FLAGS_ENABLE; + + /* Check queue size */ + if ((flags & PCI_MSI_FLAGS_QSIZE) >> 4 > vdev->msi_qmax) { + flags &= ~PCI_MSI_FLAGS_QSIZE; + flags |= vdev->msi_qmax << 4; + } + + /* Write back to virt and to hardware */ + *pflags = cpu_to_le16(flags); + ret = pci_user_write_config_word(vdev->pdev, + start + PCI_MSI_FLAGS, + flags); + if (ret) + return pcibios_err_to_errno(ret); + } + + return count; +} + +/* + * MSI determination is per-device, so this routine gets used beyond + * initialization time. Don't add __init + */ +static int init_pci_cap_msi_perm(struct perm_bits *perm, int len, u16 flags) +{ + if (alloc_perm_bits(perm, len)) + return -ENOMEM; + + perm->readfn = vfio_msi_config_read; + perm->writefn = vfio_msi_config_write; + + p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); + + /* + * The upper byte of the control register is reserved, + * just setup the lower byte. + */ + p_setb(perm, PCI_MSI_FLAGS, (u8)ALL_VIRT, (u8)ALL_WRITE); + p_setd(perm, PCI_MSI_ADDRESS_LO, ALL_VIRT, ALL_WRITE); + if (flags & PCI_MSI_FLAGS_64BIT) { + p_setd(perm, PCI_MSI_ADDRESS_HI, ALL_VIRT, ALL_WRITE); + p_setw(perm, PCI_MSI_DATA_64, (u16)ALL_VIRT, (u16)ALL_WRITE); + if (flags & PCI_MSI_FLAGS_MASKBIT) { + p_setd(perm, PCI_MSI_MASK_64, NO_VIRT, ALL_WRITE); + p_setd(perm, PCI_MSI_PENDING_64, NO_VIRT, ALL_WRITE); + } + } else { + p_setw(perm, PCI_MSI_DATA_32, (u16)ALL_VIRT, (u16)ALL_WRITE); + if (flags & PCI_MSI_FLAGS_MASKBIT) { + p_setd(perm, PCI_MSI_MASK_32, NO_VIRT, ALL_WRITE); + p_setd(perm, PCI_MSI_PENDING_32, NO_VIRT, ALL_WRITE); + } + } + return 0; +} + +/* Determine MSI CAP field length; initialize msi_perms on 1st call per vdev */ +static int vfio_msi_cap_len(struct vfio_pci_device *vdev, u8 pos) +{ + struct pci_dev *pdev = vdev->pdev; + int len, ret; + u16 flags; + + ret = pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &flags); + if (ret) + return pcibios_err_to_errno(ret); + + len = 10; /* Minimum size */ + if (flags & PCI_MSI_FLAGS_64BIT) + len += 4; + if (flags & PCI_MSI_FLAGS_MASKBIT) + len += 10; + + if (vdev->msi_perm) + return len; + + vdev->msi_perm = kmalloc(sizeof(struct perm_bits), GFP_KERNEL); + if (!vdev->msi_perm) + return -ENOMEM; + + ret = init_pci_cap_msi_perm(vdev->msi_perm, len, flags); + if (ret) + return ret; + + return len; +} + +/* Determine extended capability length for VC (2 & 9) and MFVC */ +static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos) +{ + struct pci_dev *pdev = vdev->pdev; + u32 tmp; + int ret, evcc, phases, vc_arb; + int len = PCI_CAP_VC_BASE_SIZEOF; + + ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG1, &tmp); + if (ret) + return pcibios_err_to_errno(ret); + + evcc = tmp & PCI_VC_REG1_EVCC; /* extended vc count */ + ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG2, &tmp); + if (ret) + return pcibios_err_to_errno(ret); + + if (tmp & PCI_VC_REG2_128_PHASE) + phases = 128; + else if (tmp & PCI_VC_REG2_64_PHASE) + phases = 64; + else if (tmp & PCI_VC_REG2_32_PHASE) + phases = 32; + else + phases = 0; + + vc_arb = phases * 4; + + /* + * Port arbitration tables are root & switch only; + * function arbitration tables are function 0 only. + * In either case, we'll never let user write them so + * we don't care how big they are + */ + len += (1 + evcc) * PCI_CAP_VC_PER_VC_SIZEOF; + if (vc_arb) { + len = round_up(len, 16); + len += vc_arb / 8; + } + return len; +} + +static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos) +{ + struct pci_dev *pdev = vdev->pdev; + u16 word; + u8 byte; + int ret; + + switch (cap) { + case PCI_CAP_ID_MSI: + return vfio_msi_cap_len(vdev, pos); + case PCI_CAP_ID_PCIX: + ret = pci_read_config_word(pdev, pos + PCI_X_CMD, &word); + if (ret) + return pcibios_err_to_errno(ret); + + if (PCI_X_CMD_VERSION(word)) { + vdev->extended_caps = true; + return PCI_CAP_PCIX_SIZEOF_V2; + } else + return PCI_CAP_PCIX_SIZEOF_V0; + case PCI_CAP_ID_VNDR: + /* length follows next field */ + ret = pci_read_config_byte(pdev, pos + PCI_CAP_FLAGS, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + return byte; + case PCI_CAP_ID_EXP: + /* length based on version */ + ret = pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &word); + if (ret) + return pcibios_err_to_errno(ret); + + if ((word & PCI_EXP_FLAGS_VERS) == 1) + return PCI_CAP_EXP_ENDPOINT_SIZEOF_V1; + else { + vdev->extended_caps = true; + return PCI_CAP_EXP_ENDPOINT_SIZEOF_V2; + } + case PCI_CAP_ID_HT: + ret = pci_read_config_byte(pdev, pos + 3, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + return (byte & HT_3BIT_CAP_MASK) ? + HT_CAP_SIZEOF_SHORT : HT_CAP_SIZEOF_LONG; + case PCI_CAP_ID_SATA: + ret = pci_read_config_byte(pdev, pos + PCI_SATA_REGS, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + byte &= PCI_SATA_REGS_MASK; + if (byte == PCI_SATA_REGS_INLINE) + return PCI_SATA_SIZEOF_LONG; + else + return PCI_SATA_SIZEOF_SHORT; + default: + pr_warn("%s: %s unknown length for pci cap 0x%x@0x%x\n", + dev_name(&pdev->dev), __func__, cap, pos); + } + + return 0; +} + +static int vfio_ext_cap_len(struct vfio_pci_device *vdev, u16 ecap, u16 epos) +{ + struct pci_dev *pdev = vdev->pdev; + u8 byte; + u32 dword; + int ret; + + switch (ecap) { + case PCI_EXT_CAP_ID_VNDR: + ret = pci_read_config_dword(pdev, epos + PCI_VSEC_HDR, &dword); + if (ret) + return pcibios_err_to_errno(ret); + + return dword >> PCI_VSEC_HDR_LEN_SHIFT; + case PCI_EXT_CAP_ID_VC: + case PCI_EXT_CAP_ID_VC9: + case PCI_EXT_CAP_ID_MFVC: + return vfio_vc_cap_len(vdev, epos); + case PCI_EXT_CAP_ID_ACS: + ret = pci_read_config_byte(pdev, epos + PCI_ACS_CAP, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + if (byte & PCI_ACS_EC) { + int bits; + + ret = pci_read_config_byte(pdev, + epos + PCI_ACS_EGRESS_BITS, + &byte); + if (ret) + return pcibios_err_to_errno(ret); + + bits = byte ? round_up(byte, 32) : 256; + return 8 + (bits / 8); + } + return 8; + + case PCI_EXT_CAP_ID_REBAR: + ret = pci_read_config_byte(pdev, epos + PCI_REBAR_CTRL, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + byte &= PCI_REBAR_CTRL_NBAR_MASK; + byte >>= PCI_REBAR_CTRL_NBAR_SHIFT; + + return 4 + (byte * 8); + case PCI_EXT_CAP_ID_DPA: + ret = pci_read_config_byte(pdev, epos + PCI_DPA_CAP, &byte); + if (ret) + return pcibios_err_to_errno(ret); + + byte &= PCI_DPA_CAP_SUBSTATE_MASK; + byte = round_up(byte + 1, 4); + return PCI_DPA_BASE_SIZEOF + byte; + case PCI_EXT_CAP_ID_TPH: + ret = pci_read_config_dword(pdev, epos + PCI_TPH_CAP, &dword); + if (ret) + return pcibios_err_to_errno(ret); + + if ((dword & PCI_TPH_CAP_LOC_MASK) == PCI_TPH_LOC_CAP) { + int sts; + + sts = byte & PCI_TPH_CAP_ST_MASK; + sts >>= PCI_TPH_CAP_ST_SHIFT; + return PCI_TPH_BASE_SIZEOF + round_up(sts * 2, 4); + } + return PCI_TPH_BASE_SIZEOF; + default: + pr_warn("%s: %s unknown length for pci ecap 0x%x@0x%x\n", + dev_name(&pdev->dev), __func__, ecap, epos); + } + + return 0; +} + +static int vfio_fill_vconfig_bytes(struct vfio_pci_device *vdev, + int offset, int size) +{ + struct pci_dev *pdev = vdev->pdev; + int ret = 0; + + /* + * We try to read physical config space in the largest chunks + * we can, assuming that all of the fields support dword access. + * pci_save_state() makes this same assumption and seems to do ok. + */ + while (size) { + int filled; + + if (size >= 4 && !(offset % 4)) { + __le32 *dwordp = (__le32 *)&vdev->vconfig[offset]; + u32 dword; + + ret = pci_read_config_dword(pdev, offset, &dword); + if (ret) + return ret; + *dwordp = cpu_to_le32(dword); + filled = 4; + } else if (size >= 2 && !(offset % 2)) { + __le16 *wordp = (__le16 *)&vdev->vconfig[offset]; + u16 word; + + ret = pci_read_config_word(pdev, offset, &word); + if (ret) + return ret; + *wordp = cpu_to_le16(word); + filled = 2; + } else { + u8 *byte = &vdev->vconfig[offset]; + ret = pci_read_config_byte(pdev, offset, byte); + if (ret) + return ret; + filled = 1; + } + + offset += filled; + size -= filled; + } + + return ret; +} + +static int vfio_cap_init(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + u8 *map = vdev->pci_config_map; + u16 status; + u8 pos, *prev, cap; + int loops, ret, caps = 0; + + /* Any capabilities? */ + ret = pci_read_config_word(pdev, PCI_STATUS, &status); + if (ret) + return ret; + + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; /* Done */ + + ret = pci_read_config_byte(pdev, PCI_CAPABILITY_LIST, &pos); + if (ret) + return ret; + + /* Mark the previous position in case we want to skip a capability */ + prev = &vdev->vconfig[PCI_CAPABILITY_LIST]; + + /* We can bound our loop, capabilities are dword aligned */ + loops = (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF; + while (pos && loops--) { + u8 next; + int i, len = 0; + + ret = pci_read_config_byte(pdev, pos, &cap); + if (ret) + return ret; + + ret = pci_read_config_byte(pdev, + pos + PCI_CAP_LIST_NEXT, &next); + if (ret) + return ret; + + if (cap <= PCI_CAP_ID_MAX) { + len = pci_cap_length[cap]; + if (len == 0xFF) { /* Variable length */ + len = vfio_cap_len(vdev, cap, pos); + if (len < 0) + return len; + } + } + + if (!len) { + pr_info("%s: %s hiding cap 0x%x\n", + __func__, dev_name(&pdev->dev), cap); + *prev = next; + pos = next; + continue; + } + + /* Sanity check, do we overlap other capabilities? */ + for (i = 0; i < len; i += 4) { + if (likely(map[(pos + i) / 4] == PCI_CAP_ID_INVALID)) + continue; + + pr_warn("%s: %s pci config conflict @0x%x, was cap 0x%x now cap 0x%x\n", + __func__, dev_name(&pdev->dev), + pos + i, map[pos + i], cap); + } + + memset(map + (pos / 4), cap, len / 4); + ret = vfio_fill_vconfig_bytes(vdev, pos, len); + if (ret) + return ret; + + prev = &vdev->vconfig[pos + PCI_CAP_LIST_NEXT]; + pos = next; + caps++; + } + + /* If we didn't fill any capabilities, clear the status flag */ + if (!caps) { + __le16 *vstatus = (__le16 *)&vdev->vconfig[PCI_STATUS]; + *vstatus &= ~cpu_to_le16(PCI_STATUS_CAP_LIST); + } + + return 0; +} + +static int vfio_ecap_init(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + u8 *map = vdev->pci_config_map; + u16 epos; + __le32 *prev = NULL; + int loops, ret, ecaps = 0; + + if (!vdev->extended_caps) + return 0; + + epos = PCI_CFG_SPACE_SIZE; + + loops = (pdev->cfg_size - PCI_CFG_SPACE_SIZE) / PCI_CAP_SIZEOF; + + while (loops-- && epos >= PCI_CFG_SPACE_SIZE) { + u32 header; + u16 ecap; + int i, len = 0; + bool hidden = false; + + ret = pci_read_config_dword(pdev, epos, &header); + if (ret) + return ret; + + ecap = PCI_EXT_CAP_ID(header); + + if (ecap <= PCI_EXT_CAP_ID_MAX) { + len = pci_ext_cap_length[ecap]; + if (len == 0xFF) { + len = vfio_ext_cap_len(vdev, ecap, epos); + if (len < 0) + return ret; + } + } + + if (!len) { + pr_info("%s: %s hiding ecap 0x%x@0x%x\n", + __func__, dev_name(&pdev->dev), ecap, epos); + + /* If not the first in the chain, we can skip over it */ + if (prev) { + u32 val = epos = PCI_EXT_CAP_NEXT(header); + *prev &= cpu_to_le32(~(0xffcU << 20)); + *prev |= cpu_to_le32(val << 20); + continue; + } + + /* + * Otherwise, fill in a placeholder, the direct + * readfn will virtualize this automatically + */ + len = PCI_CAP_SIZEOF; + hidden = true; + } + + for (i = 0; i < len; i += 4) { + if (likely(map[(epos + i) / 4] == PCI_CAP_ID_INVALID)) + continue; + + pr_warn("%s: %s pci config conflict @0x%x, was ecap 0x%x now ecap 0x%x\n", + __func__, dev_name(&pdev->dev), + epos + i, map[epos + i], ecap); + } + + /* + * Even though ecap is 2 bytes, we're currently a long way + * from exceeding 1 byte capabilities. If we ever make it + * up to 0xFF we'll need to up this to a two-byte, byte map. + */ + BUILD_BUG_ON(PCI_EXT_CAP_ID_MAX >= PCI_CAP_ID_INVALID); + + memset(map + (epos / 4), ecap, len / 4); + ret = vfio_fill_vconfig_bytes(vdev, epos, len); + if (ret) + return ret; + + /* + * If we're just using this capability to anchor the list, + * hide the real ID. Only count real ecaps. XXX PCI spec + * indicates to use cap id = 0, version = 0, next = 0 if + * ecaps are absent, hope users check all the way to next. + */ + if (hidden) + *(__le32 *)&vdev->vconfig[epos] &= + cpu_to_le32((0xffcU << 20)); + else + ecaps++; + + prev = (__le32 *)&vdev->vconfig[epos]; + epos = PCI_EXT_CAP_NEXT(header); + } + + if (!ecaps) + *(u32 *)&vdev->vconfig[PCI_CFG_SPACE_SIZE] = 0; + + return 0; +} + +/* + * For each device we allocate a pci_config_map that indicates the + * capability occupying each dword and thus the struct perm_bits we + * use for read and write. We also allocate a virtualized config + * space which tracks reads and writes to bits that we emulate for + * the user. Initial values filled from device. + * + * Using shared stuct perm_bits between all vfio-pci devices saves + * us from allocating cfg_size buffers for virt and write for every + * device. We could remove vconfig and allocate individual buffers + * for each area requring emulated bits, but the array of pointers + * would be comparable in size (at least for standard config space). + */ +int vfio_config_init(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + u8 *map, *vconfig; + int ret; + + /* + * Config space, caps and ecaps are all dword aligned, so we can + * use one byte per dword to record the type. + */ + map = kmalloc(pdev->cfg_size / 4, GFP_KERNEL); + if (!map) + return -ENOMEM; + + vconfig = kmalloc(pdev->cfg_size, GFP_KERNEL); + if (!vconfig) { + kfree(map); + return -ENOMEM; + } + + vdev->pci_config_map = map; + vdev->vconfig = vconfig; + + memset(map, PCI_CAP_ID_BASIC, PCI_STD_HEADER_SIZEOF / 4); + memset(map + (PCI_STD_HEADER_SIZEOF / 4), PCI_CAP_ID_INVALID, + (pdev->cfg_size - PCI_STD_HEADER_SIZEOF) / 4); + + ret = vfio_fill_vconfig_bytes(vdev, 0, PCI_STD_HEADER_SIZEOF); + if (ret) + goto out; + + vdev->bardirty = true; + + /* + * XXX can we just pci_load_saved_state/pci_restore_state? + * may need to rebuild vconfig after that + */ + + /* For restore after reset */ + vdev->rbar[0] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_0]); + vdev->rbar[1] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_1]); + vdev->rbar[2] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_2]); + vdev->rbar[3] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_3]); + vdev->rbar[4] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_4]); + vdev->rbar[5] = le32_to_cpu(*(__le32 *)&vconfig[PCI_BASE_ADDRESS_5]); + vdev->rbar[6] = le32_to_cpu(*(__le32 *)&vconfig[PCI_ROM_ADDRESS]); + + if (pdev->is_virtfn) { + *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor); + *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); + } + + ret = vfio_cap_init(vdev); + if (ret) + goto out; + + ret = vfio_ecap_init(vdev); + if (ret) + goto out; + + return 0; + +out: + kfree(map); + vdev->pci_config_map = NULL; + kfree(vconfig); + vdev->vconfig = NULL; + return pcibios_err_to_errno(ret); +} + +void vfio_config_free(struct vfio_pci_device *vdev) +{ + kfree(vdev->vconfig); + vdev->vconfig = NULL; + kfree(vdev->pci_config_map); + vdev->pci_config_map = NULL; + kfree(vdev->msi_perm); + vdev->msi_perm = NULL; +} + +static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf, + size_t count, loff_t *ppos, bool iswrite) +{ + struct pci_dev *pdev = vdev->pdev; + struct perm_bits *perm; + __le32 val = 0; + int cap_start = 0, offset; + u8 cap_id; + ssize_t ret = count; + + if (*ppos < 0 || *ppos + count > pdev->cfg_size) + return -EFAULT; + + /* + * gcc can't seem to figure out we're a static function, only called + * with count of 1/2/4 and hits copy_from_user_overflow without this. + */ + if (count > sizeof(val)) + return -EINVAL; + + cap_id = vdev->pci_config_map[*ppos / 4]; + + if (cap_id == PCI_CAP_ID_INVALID) { + if (iswrite) + return ret; /* drop */ + + /* + * Per PCI spec 3.0, section 6.1, reads from reserved and + * unimplemented registers return 0 + */ + if (copy_to_user(buf, &val, count)) + return -EFAULT; + + return ret; + } + + /* + * All capabilities are minimum 4 bytes and aligned on dword + * boundaries. Since we don't support unaligned accesses, we're + * only ever accessing a single capability. + */ + if (*ppos >= PCI_CFG_SPACE_SIZE) { + WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX); + + perm = &ecap_perms[cap_id]; + cap_start = vfio_find_cap_start(vdev, *ppos); + + } else { + WARN_ON(cap_id > PCI_CAP_ID_MAX); + + perm = &cap_perms[cap_id]; + + if (cap_id == PCI_CAP_ID_MSI) + perm = vdev->msi_perm; + + if (cap_id > PCI_CAP_ID_BASIC) + cap_start = vfio_find_cap_start(vdev, *ppos); + } + + WARN_ON(!cap_start && cap_id != PCI_CAP_ID_BASIC); + WARN_ON(cap_start > *ppos); + + offset = *ppos - cap_start; + + if (iswrite) { + if (!perm->writefn) + return ret; + + if (copy_from_user(&val, buf, count)) + return -EFAULT; + + ret = perm->writefn(vdev, *ppos, count, perm, offset, val); + } else { + if (perm->readfn) { + ret = perm->readfn(vdev, *ppos, count, + perm, offset, &val); + if (ret < 0) + return ret; + } + + if (copy_to_user(buf, &val, count)) + return -EFAULT; + } + + return ret; +} + +ssize_t vfio_pci_config_readwrite(struct vfio_pci_device *vdev, + char __user *buf, size_t count, + loff_t *ppos, bool iswrite) +{ + size_t done = 0; + int ret = 0; + loff_t pos = *ppos; + + pos &= VFIO_PCI_OFFSET_MASK; + + /* + * We want to both keep the access size the caller users as well as + * support reading large chunks of config space in a single call. + * PCI doesn't support unaligned accesses, so we can safely break + * those apart. + */ + while (count) { + if (count >= 4 && !(pos % 4)) + ret = vfio_config_do_rw(vdev, buf, 4, &pos, iswrite); + else if (count >= 2 && !(pos % 2)) + ret = vfio_config_do_rw(vdev, buf, 2, &pos, iswrite); + else + ret = vfio_config_do_rw(vdev, buf, 1, &pos, iswrite); + + if (ret < 0) + return ret; + + count -= ret; + done += ret; + buf += ret; + pos += ret; + } + + *ppos += done; + + return done; +} diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c new file mode 100644 index 000000000000..211a4920b88a --- /dev/null +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -0,0 +1,740 @@ +/* + * VFIO PCI interrupt handling + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vfio_pci_private.h" + +/* + * IRQfd - generic + */ +struct virqfd { + struct vfio_pci_device *vdev; + struct eventfd_ctx *eventfd; + int (*handler)(struct vfio_pci_device *, void *); + void (*thread)(struct vfio_pci_device *, void *); + void *data; + struct work_struct inject; + wait_queue_t wait; + poll_table pt; + struct work_struct shutdown; + struct virqfd **pvirqfd; +}; + +static struct workqueue_struct *vfio_irqfd_cleanup_wq; + +int __init vfio_pci_virqfd_init(void) +{ + vfio_irqfd_cleanup_wq = + create_singlethread_workqueue("vfio-irqfd-cleanup"); + if (!vfio_irqfd_cleanup_wq) + return -ENOMEM; + + return 0; +} + +void vfio_pci_virqfd_exit(void) +{ + destroy_workqueue(vfio_irqfd_cleanup_wq); +} + +static void virqfd_deactivate(struct virqfd *virqfd) +{ + queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown); +} + +static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + struct virqfd *virqfd = container_of(wait, struct virqfd, wait); + unsigned long flags = (unsigned long)key; + + if (flags & POLLIN) { + /* An event has been signaled, call function */ + if ((!virqfd->handler || + virqfd->handler(virqfd->vdev, virqfd->data)) && + virqfd->thread) + schedule_work(&virqfd->inject); + } + + if (flags & POLLHUP) + /* The eventfd is closing, detach from VFIO */ + virqfd_deactivate(virqfd); + + return 0; +} + +static void virqfd_ptable_queue_proc(struct file *file, + wait_queue_head_t *wqh, poll_table *pt) +{ + struct virqfd *virqfd = container_of(pt, struct virqfd, pt); + add_wait_queue(wqh, &virqfd->wait); +} + +static void virqfd_shutdown(struct work_struct *work) +{ + struct virqfd *virqfd = container_of(work, struct virqfd, shutdown); + struct virqfd **pvirqfd = virqfd->pvirqfd; + u64 cnt; + + eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt); + flush_work(&virqfd->inject); + eventfd_ctx_put(virqfd->eventfd); + + kfree(virqfd); + *pvirqfd = NULL; +} + +static void virqfd_inject(struct work_struct *work) +{ + struct virqfd *virqfd = container_of(work, struct virqfd, inject); + if (virqfd->thread) + virqfd->thread(virqfd->vdev, virqfd->data); +} + +static int virqfd_enable(struct vfio_pci_device *vdev, + int (*handler)(struct vfio_pci_device *, void *), + void (*thread)(struct vfio_pci_device *, void *), + void *data, struct virqfd **pvirqfd, int fd) +{ + struct file *file = NULL; + struct eventfd_ctx *ctx = NULL; + struct virqfd *virqfd; + int ret = 0; + unsigned int events; + + if (*pvirqfd) + return -EBUSY; + + virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL); + if (!virqfd) + return -ENOMEM; + + virqfd->pvirqfd = pvirqfd; + *pvirqfd = virqfd; + virqfd->vdev = vdev; + virqfd->handler = handler; + virqfd->thread = thread; + virqfd->data = data; + + INIT_WORK(&virqfd->shutdown, virqfd_shutdown); + INIT_WORK(&virqfd->inject, virqfd_inject); + + file = eventfd_fget(fd); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto fail; + } + + ctx = eventfd_ctx_fileget(file); + if (IS_ERR(ctx)) { + ret = PTR_ERR(ctx); + goto fail; + } + + virqfd->eventfd = ctx; + + /* + * Install our own custom wake-up handling so we are notified via + * a callback whenever someone signals the underlying eventfd. + */ + init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup); + init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc); + + events = file->f_op->poll(file, &virqfd->pt); + + /* + * Check if there was an event already pending on the eventfd + * before we registered and trigger it as if we didn't miss it. + */ + if (events & POLLIN) { + if ((!handler || handler(vdev, data)) && thread) + schedule_work(&virqfd->inject); + } + + /* + * Do not drop the file until the irqfd is fully initialized, + * otherwise we might race against the POLLHUP. + */ + fput(file); + + return 0; + +fail: + if (ctx && !IS_ERR(ctx)) + eventfd_ctx_put(ctx); + + if (file && !IS_ERR(file)) + fput(file); + + kfree(virqfd); + *pvirqfd = NULL; + + return ret; +} + +static void virqfd_disable(struct virqfd *virqfd) +{ + if (!virqfd) + return; + + virqfd_deactivate(virqfd); + + /* Block until we know all outstanding shutdown jobs have completed. */ + flush_workqueue(vfio_irqfd_cleanup_wq); +} + +/* + * INTx + */ +static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused) +{ + if (likely(is_intx(vdev) && !vdev->virq_disabled)) + eventfd_signal(vdev->ctx[0].trigger, 1); +} + +void vfio_pci_intx_mask(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + unsigned long flags; + + spin_lock_irqsave(&vdev->irqlock, flags); + + /* + * Masking can come from interrupt, ioctl, or config space + * via INTx disable. The latter means this can get called + * even when not using intx delivery. In this case, just + * try to have the physical bit follow the virtual bit. + */ + if (unlikely(!is_intx(vdev))) { + if (vdev->pci_2_3) + pci_intx(pdev, 0); + } else if (!vdev->ctx[0].masked) { + /* + * Can't use check_and_mask here because we always want to + * mask, not just when something is pending. + */ + if (vdev->pci_2_3) + pci_intx(pdev, 0); + else + disable_irq_nosync(pdev->irq); + + vdev->ctx[0].masked = true; + } + + spin_unlock_irqrestore(&vdev->irqlock, flags); +} + +/* + * If this is triggered by an eventfd, we can't call eventfd_signal + * or else we'll deadlock on the eventfd wait queue. Return >0 when + * a signal is necessary, which can then be handled via a work queue + * or directly depending on the caller. + */ +int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev, void *unused) +{ + struct pci_dev *pdev = vdev->pdev; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&vdev->irqlock, flags); + + /* + * Unmasking comes from ioctl or config, so again, have the + * physical bit follow the virtual even when not using INTx. + */ + if (unlikely(!is_intx(vdev))) { + if (vdev->pci_2_3) + pci_intx(pdev, 1); + } else if (vdev->ctx[0].masked && !vdev->virq_disabled) { + /* + * A pending interrupt here would immediately trigger, + * but we can avoid that overhead by just re-sending + * the interrupt to the user. + */ + if (vdev->pci_2_3) { + if (!pci_check_and_unmask_intx(pdev)) + ret = 1; + } else + enable_irq(pdev->irq); + + vdev->ctx[0].masked = (ret > 0); + } + + spin_unlock_irqrestore(&vdev->irqlock, flags); + + return ret; +} + +void vfio_pci_intx_unmask(struct vfio_pci_device *vdev) +{ + if (vfio_pci_intx_unmask_handler(vdev, NULL) > 0) + vfio_send_intx_eventfd(vdev, NULL); +} + +static irqreturn_t vfio_intx_handler(int irq, void *dev_id) +{ + struct vfio_pci_device *vdev = dev_id; + unsigned long flags; + int ret = IRQ_NONE; + + spin_lock_irqsave(&vdev->irqlock, flags); + + if (!vdev->pci_2_3) { + disable_irq_nosync(vdev->pdev->irq); + vdev->ctx[0].masked = true; + ret = IRQ_HANDLED; + } else if (!vdev->ctx[0].masked && /* may be shared */ + pci_check_and_mask_intx(vdev->pdev)) { + vdev->ctx[0].masked = true; + ret = IRQ_HANDLED; + } + + spin_unlock_irqrestore(&vdev->irqlock, flags); + + if (ret == IRQ_HANDLED) + vfio_send_intx_eventfd(vdev, NULL); + + return ret; +} + +static int vfio_intx_enable(struct vfio_pci_device *vdev) +{ + if (!is_irq_none(vdev)) + return -EINVAL; + + if (!vdev->pdev->irq) + return -ENODEV; + + vdev->ctx = kzalloc(sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); + if (!vdev->ctx) + return -ENOMEM; + + vdev->num_ctx = 1; + vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX; + + return 0; +} + +static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd) +{ + struct pci_dev *pdev = vdev->pdev; + unsigned long irqflags = IRQF_SHARED; + struct eventfd_ctx *trigger; + unsigned long flags; + int ret; + + if (vdev->ctx[0].trigger) { + free_irq(pdev->irq, vdev); + kfree(vdev->ctx[0].name); + eventfd_ctx_put(vdev->ctx[0].trigger); + vdev->ctx[0].trigger = NULL; + } + + if (fd < 0) /* Disable only */ + return 0; + + vdev->ctx[0].name = kasprintf(GFP_KERNEL, "vfio-intx(%s)", + pci_name(pdev)); + if (!vdev->ctx[0].name) + return -ENOMEM; + + trigger = eventfd_ctx_fdget(fd); + if (IS_ERR(trigger)) { + kfree(vdev->ctx[0].name); + return PTR_ERR(trigger); + } + + if (!vdev->pci_2_3) + irqflags = 0; + + ret = request_irq(pdev->irq, vfio_intx_handler, + irqflags, vdev->ctx[0].name, vdev); + if (ret) { + kfree(vdev->ctx[0].name); + eventfd_ctx_put(trigger); + return ret; + } + + vdev->ctx[0].trigger = trigger; + + /* + * INTx disable will stick across the new irq setup, + * disable_irq won't. + */ + spin_lock_irqsave(&vdev->irqlock, flags); + if (!vdev->pci_2_3 && (vdev->ctx[0].masked || vdev->virq_disabled)) + disable_irq_nosync(pdev->irq); + spin_unlock_irqrestore(&vdev->irqlock, flags); + + return 0; +} + +static void vfio_intx_disable(struct vfio_pci_device *vdev) +{ + vfio_intx_set_signal(vdev, -1); + virqfd_disable(vdev->ctx[0].unmask); + virqfd_disable(vdev->ctx[0].mask); + vdev->irq_type = VFIO_PCI_NUM_IRQS; + vdev->num_ctx = 0; + kfree(vdev->ctx); +} + +/* + * MSI/MSI-X + */ +static irqreturn_t vfio_msihandler(int irq, void *arg) +{ + struct eventfd_ctx *trigger = arg; + + eventfd_signal(trigger, 1); + return IRQ_HANDLED; +} + +static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix) +{ + struct pci_dev *pdev = vdev->pdev; + int ret; + + if (!is_irq_none(vdev)) + return -EINVAL; + + vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); + if (!vdev->ctx) + return -ENOMEM; + + if (msix) { + int i; + + vdev->msix = kzalloc(nvec * sizeof(struct msix_entry), + GFP_KERNEL); + if (!vdev->msix) { + kfree(vdev->ctx); + return -ENOMEM; + } + + for (i = 0; i < nvec; i++) + vdev->msix[i].entry = i; + + ret = pci_enable_msix(pdev, vdev->msix, nvec); + if (ret) { + kfree(vdev->msix); + kfree(vdev->ctx); + return ret; + } + } else { + ret = pci_enable_msi_block(pdev, nvec); + if (ret) { + kfree(vdev->ctx); + return ret; + } + } + + vdev->num_ctx = nvec; + vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX : + VFIO_PCI_MSI_IRQ_INDEX; + + if (!msix) { + /* + * Compute the virtual hardware field for max msi vectors - + * it is the log base 2 of the number of vectors. + */ + vdev->msi_qmax = fls(nvec * 2 - 1) - 1; + } + + return 0; +} + +static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, + int vector, int fd, bool msix) +{ + struct pci_dev *pdev = vdev->pdev; + int irq = msix ? vdev->msix[vector].vector : pdev->irq + vector; + char *name = msix ? "vfio-msix" : "vfio-msi"; + struct eventfd_ctx *trigger; + int ret; + + if (vector >= vdev->num_ctx) + return -EINVAL; + + if (vdev->ctx[vector].trigger) { + free_irq(irq, vdev->ctx[vector].trigger); + kfree(vdev->ctx[vector].name); + eventfd_ctx_put(vdev->ctx[vector].trigger); + vdev->ctx[vector].trigger = NULL; + } + + if (fd < 0) + return 0; + + vdev->ctx[vector].name = kasprintf(GFP_KERNEL, "%s[%d](%s)", + name, vector, pci_name(pdev)); + if (!vdev->ctx[vector].name) + return -ENOMEM; + + trigger = eventfd_ctx_fdget(fd); + if (IS_ERR(trigger)) { + kfree(vdev->ctx[vector].name); + return PTR_ERR(trigger); + } + + ret = request_irq(irq, vfio_msihandler, 0, + vdev->ctx[vector].name, trigger); + if (ret) { + kfree(vdev->ctx[vector].name); + eventfd_ctx_put(trigger); + return ret; + } + + vdev->ctx[vector].trigger = trigger; + + return 0; +} + +static int vfio_msi_set_block(struct vfio_pci_device *vdev, unsigned start, + unsigned count, int32_t *fds, bool msix) +{ + int i, j, ret = 0; + + if (start + count > vdev->num_ctx) + return -EINVAL; + + for (i = 0, j = start; i < count && !ret; i++, j++) { + int fd = fds ? fds[i] : -1; + ret = vfio_msi_set_vector_signal(vdev, j, fd, msix); + } + + if (ret) { + for (--j; j >= start; j--) + vfio_msi_set_vector_signal(vdev, j, -1, msix); + } + + return ret; +} + +static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix) +{ + struct pci_dev *pdev = vdev->pdev; + int i; + + vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix); + + for (i = 0; i < vdev->num_ctx; i++) { + virqfd_disable(vdev->ctx[i].unmask); + virqfd_disable(vdev->ctx[i].mask); + } + + if (msix) { + pci_disable_msix(vdev->pdev); + kfree(vdev->msix); + } else + pci_disable_msi(pdev); + + vdev->irq_type = VFIO_PCI_NUM_IRQS; + vdev->num_ctx = 0; + kfree(vdev->ctx); +} + +/* + * IOCTL support + */ +static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev, + unsigned index, unsigned start, + unsigned count, uint32_t flags, void *data) +{ + if (!is_intx(vdev) || start != 0 || count != 1) + return -EINVAL; + + if (flags & VFIO_IRQ_SET_DATA_NONE) { + vfio_pci_intx_unmask(vdev); + } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { + uint8_t unmask = *(uint8_t *)data; + if (unmask) + vfio_pci_intx_unmask(vdev); + } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + int32_t fd = *(int32_t *)data; + if (fd >= 0) + return virqfd_enable(vdev, vfio_pci_intx_unmask_handler, + vfio_send_intx_eventfd, NULL, + &vdev->ctx[0].unmask, fd); + + virqfd_disable(vdev->ctx[0].unmask); + } + + return 0; +} + +static int vfio_pci_set_intx_mask(struct vfio_pci_device *vdev, + unsigned index, unsigned start, + unsigned count, uint32_t flags, void *data) +{ + if (!is_intx(vdev) || start != 0 || count != 1) + return -EINVAL; + + if (flags & VFIO_IRQ_SET_DATA_NONE) { + vfio_pci_intx_mask(vdev); + } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { + uint8_t mask = *(uint8_t *)data; + if (mask) + vfio_pci_intx_mask(vdev); + } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + return -ENOTTY; /* XXX implement me */ + } + + return 0; +} + +static int vfio_pci_set_intx_trigger(struct vfio_pci_device *vdev, + unsigned index, unsigned start, + unsigned count, uint32_t flags, void *data) +{ + if (is_intx(vdev) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) { + vfio_intx_disable(vdev); + return 0; + } + + if (!(is_intx(vdev) || is_irq_none(vdev)) || start != 0 || count != 1) + return -EINVAL; + + if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + int32_t fd = *(int32_t *)data; + int ret; + + if (is_intx(vdev)) + return vfio_intx_set_signal(vdev, fd); + + ret = vfio_intx_enable(vdev); + if (ret) + return ret; + + ret = vfio_intx_set_signal(vdev, fd); + if (ret) + vfio_intx_disable(vdev); + + return ret; + } + + if (!is_intx(vdev)) + return -EINVAL; + + if (flags & VFIO_IRQ_SET_DATA_NONE) { + vfio_send_intx_eventfd(vdev, NULL); + } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { + uint8_t trigger = *(uint8_t *)data; + if (trigger) + vfio_send_intx_eventfd(vdev, NULL); + } + return 0; +} + +static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev, + unsigned index, unsigned start, + unsigned count, uint32_t flags, void *data) +{ + int i; + bool msix = (index == VFIO_PCI_MSIX_IRQ_INDEX) ? true : false; + + if (irq_is(vdev, index) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) { + vfio_msi_disable(vdev, msix); + return 0; + } + + if (!(irq_is(vdev, index) || is_irq_none(vdev))) + return -EINVAL; + + if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + int32_t *fds = data; + int ret; + + if (vdev->irq_type == index) + return vfio_msi_set_block(vdev, start, count, + fds, msix); + + ret = vfio_msi_enable(vdev, start + count, msix); + if (ret) + return ret; + + ret = vfio_msi_set_block(vdev, start, count, fds, msix); + if (ret) + vfio_msi_disable(vdev, msix); + + return ret; + } + + if (!irq_is(vdev, index) || start + count > vdev->num_ctx) + return -EINVAL; + + for (i = start; i < start + count; i++) { + if (!vdev->ctx[i].trigger) + continue; + if (flags & VFIO_IRQ_SET_DATA_NONE) { + eventfd_signal(vdev->ctx[i].trigger, 1); + } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { + uint8_t *bools = data; + if (bools[i - start]) + eventfd_signal(vdev->ctx[i].trigger, 1); + } + } + return 0; +} + +int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, + unsigned index, unsigned start, unsigned count, + void *data) +{ + int (*func)(struct vfio_pci_device *vdev, unsigned index, + unsigned start, unsigned count, uint32_t flags, + void *data) = NULL; + + switch (index) { + case VFIO_PCI_INTX_IRQ_INDEX: + switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) { + case VFIO_IRQ_SET_ACTION_MASK: + func = vfio_pci_set_intx_mask; + break; + case VFIO_IRQ_SET_ACTION_UNMASK: + func = vfio_pci_set_intx_unmask; + break; + case VFIO_IRQ_SET_ACTION_TRIGGER: + func = vfio_pci_set_intx_trigger; + break; + } + break; + case VFIO_PCI_MSI_IRQ_INDEX: + case VFIO_PCI_MSIX_IRQ_INDEX: + switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) { + case VFIO_IRQ_SET_ACTION_MASK: + case VFIO_IRQ_SET_ACTION_UNMASK: + /* XXX Need masking support exported */ + break; + case VFIO_IRQ_SET_ACTION_TRIGGER: + func = vfio_pci_set_msi_trigger; + break; + } + break; + } + + if (!func) + return -ENOTTY; + + return func(vdev, index, start, count, flags, data); +} diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h new file mode 100644 index 000000000000..611827cba8cd --- /dev/null +++ b/drivers/vfio/pci/vfio_pci_private.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include + +#ifndef VFIO_PCI_PRIVATE_H +#define VFIO_PCI_PRIVATE_H + +#define VFIO_PCI_OFFSET_SHIFT 40 + +#define VFIO_PCI_OFFSET_TO_INDEX(off) (off >> VFIO_PCI_OFFSET_SHIFT) +#define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT) +#define VFIO_PCI_OFFSET_MASK (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1) + +struct vfio_pci_irq_ctx { + struct eventfd_ctx *trigger; + struct virqfd *unmask; + struct virqfd *mask; + char *name; + bool masked; +}; + +struct vfio_pci_device { + struct pci_dev *pdev; + void __iomem *barmap[PCI_STD_RESOURCE_END + 1]; + u8 *pci_config_map; + u8 *vconfig; + struct perm_bits *msi_perm; + spinlock_t irqlock; + struct mutex igate; + struct msix_entry *msix; + struct vfio_pci_irq_ctx *ctx; + int num_ctx; + int irq_type; + u8 msi_qmax; + u8 msix_bar; + u16 msix_size; + u32 msix_offset; + u32 rbar[7]; + bool pci_2_3; + bool virq_disabled; + bool reset_works; + bool extended_caps; + bool bardirty; + struct pci_saved_state *pci_saved_state; + atomic_t refcnt; +}; + +#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX) +#define is_msi(vdev) (vdev->irq_type == VFIO_PCI_MSI_IRQ_INDEX) +#define is_msix(vdev) (vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX) +#define is_irq_none(vdev) (!(is_intx(vdev) || is_msi(vdev) || is_msix(vdev))) +#define irq_is(vdev, type) (vdev->irq_type == type) + +extern void vfio_pci_intx_mask(struct vfio_pci_device *vdev); +extern void vfio_pci_intx_unmask(struct vfio_pci_device *vdev); + +extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, + uint32_t flags, unsigned index, + unsigned start, unsigned count, void *data); + +extern ssize_t vfio_pci_config_readwrite(struct vfio_pci_device *vdev, + char __user *buf, size_t count, + loff_t *ppos, bool iswrite); +extern ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, + char __user *buf, size_t count, + loff_t *ppos, bool iswrite); +extern ssize_t vfio_pci_io_readwrite(struct vfio_pci_device *vdev, + char __user *buf, size_t count, + loff_t *ppos, bool iswrite); + +extern int vfio_pci_init_perm_bits(void); +extern void vfio_pci_uninit_perm_bits(void); + +extern int vfio_pci_virqfd_init(void); +extern void vfio_pci_virqfd_exit(void); + +extern int vfio_config_init(struct vfio_pci_device *vdev); +extern void vfio_config_free(struct vfio_pci_device *vdev); +#endif /* VFIO_PCI_PRIVATE_H */ diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c new file mode 100644 index 000000000000..4362d9e7baa3 --- /dev/null +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -0,0 +1,269 @@ +/* + * VFIO PCI I/O Port & MMIO access + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include +#include +#include + +#include "vfio_pci_private.h" + +/* I/O Port BAR access */ +ssize_t vfio_pci_io_readwrite(struct vfio_pci_device *vdev, char __user *buf, + size_t count, loff_t *ppos, bool iswrite) +{ + struct pci_dev *pdev = vdev->pdev; + loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK; + int bar = VFIO_PCI_OFFSET_TO_INDEX(*ppos); + void __iomem *io; + size_t done = 0; + + if (!pci_resource_start(pdev, bar)) + return -EINVAL; + + if (pos + count > pci_resource_len(pdev, bar)) + return -EINVAL; + + if (!vdev->barmap[bar]) { + int ret; + + ret = pci_request_selected_regions(pdev, 1 << bar, "vfio"); + if (ret) + return ret; + + vdev->barmap[bar] = pci_iomap(pdev, bar, 0); + + if (!vdev->barmap[bar]) { + pci_release_selected_regions(pdev, 1 << bar); + return -EINVAL; + } + } + + io = vdev->barmap[bar]; + + while (count) { + int filled; + + if (count >= 3 && !(pos % 4)) { + __le32 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 4)) + return -EFAULT; + + iowrite32(le32_to_cpu(val), io + pos); + } else { + val = cpu_to_le32(ioread32(io + pos)); + + if (copy_to_user(buf, &val, 4)) + return -EFAULT; + } + + filled = 4; + + } else if ((pos % 2) == 0 && count >= 2) { + __le16 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 2)) + return -EFAULT; + + iowrite16(le16_to_cpu(val), io + pos); + } else { + val = cpu_to_le16(ioread16(io + pos)); + + if (copy_to_user(buf, &val, 2)) + return -EFAULT; + } + + filled = 2; + } else { + u8 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 1)) + return -EFAULT; + + iowrite8(val, io + pos); + } else { + val = ioread8(io + pos); + + if (copy_to_user(buf, &val, 1)) + return -EFAULT; + } + + filled = 1; + } + + count -= filled; + done += filled; + buf += filled; + pos += filled; + } + + *ppos += done; + + return done; +} + +/* + * MMIO BAR access + * We handle two excluded ranges here as well, if the user tries to read + * the ROM beyond what PCI tells us is available or the MSI-X table region, + * we return 0xFF and writes are dropped. + */ +ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf, + size_t count, loff_t *ppos, bool iswrite) +{ + struct pci_dev *pdev = vdev->pdev; + loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK; + int bar = VFIO_PCI_OFFSET_TO_INDEX(*ppos); + void __iomem *io; + resource_size_t end; + size_t done = 0; + size_t x_start = 0, x_end = 0; /* excluded range */ + + if (!pci_resource_start(pdev, bar)) + return -EINVAL; + + end = pci_resource_len(pdev, bar); + + if (pos > end) + return -EINVAL; + + if (pos == end) + return 0; + + if (pos + count > end) + count = end - pos; + + if (bar == PCI_ROM_RESOURCE) { + io = pci_map_rom(pdev, &x_start); + x_end = end; + } else { + if (!vdev->barmap[bar]) { + int ret; + + ret = pci_request_selected_regions(pdev, 1 << bar, + "vfio"); + if (ret) + return ret; + + vdev->barmap[bar] = pci_iomap(pdev, bar, 0); + + if (!vdev->barmap[bar]) { + pci_release_selected_regions(pdev, 1 << bar); + return -EINVAL; + } + } + + io = vdev->barmap[bar]; + + if (bar == vdev->msix_bar) { + x_start = vdev->msix_offset; + x_end = vdev->msix_offset + vdev->msix_size; + } + } + + if (!io) + return -EINVAL; + + while (count) { + size_t fillable, filled; + + if (pos < x_start) + fillable = x_start - pos; + else if (pos >= x_end) + fillable = end - pos; + else + fillable = 0; + + if (fillable >= 4 && !(pos % 4) && (count >= 4)) { + __le32 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 4)) + goto out; + + iowrite32(le32_to_cpu(val), io + pos); + } else { + val = cpu_to_le32(ioread32(io + pos)); + + if (copy_to_user(buf, &val, 4)) + goto out; + } + + filled = 4; + } else if (fillable >= 2 && !(pos % 2) && (count >= 2)) { + __le16 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 2)) + goto out; + + iowrite16(le16_to_cpu(val), io + pos); + } else { + val = cpu_to_le16(ioread16(io + pos)); + + if (copy_to_user(buf, &val, 2)) + goto out; + } + + filled = 2; + } else if (fillable) { + u8 val; + + if (iswrite) { + if (copy_from_user(&val, buf, 1)) + goto out; + + iowrite8(val, io + pos); + } else { + val = ioread8(io + pos); + + if (copy_to_user(buf, &val, 1)) + goto out; + } + + filled = 1; + } else { + /* Drop writes, fill reads with FF */ + if (!iswrite) { + char val = 0xFF; + size_t i; + + for (i = 0; i < x_end - pos; i++) { + if (put_user(val, buf + i)) + goto out; + } + } + + filled = x_end - pos; + } + + count -= filled; + done += filled; + buf += filled; + pos += filled; + } + + *ppos += done; + +out: + if (bar == PCI_ROM_RESOURCE) + pci_unmap_rom(pdev, io); + + return count ? -EFAULT : done; +} diff --git a/include/linux/vfio.h b/include/linux/vfio.h index acb046fd5b70..0a4f180a11d8 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -223,6 +223,7 @@ struct vfio_device_info { __u32 argsz; __u32 flags; #define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */ +#define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */ __u32 num_regions; /* Max region index + 1 */ __u32 num_irqs; /* Max IRQ index + 1 */ }; @@ -364,6 +365,31 @@ struct vfio_irq_set { */ #define VFIO_DEVICE_RESET _IO(VFIO_TYPE, VFIO_BASE + 11) +/* + * The VFIO-PCI bus driver makes use of the following fixed region and + * IRQ index mapping. Unimplemented regions return a size of zero. + * Unimplemented IRQ types return a count of zero. + */ + +enum { + VFIO_PCI_BAR0_REGION_INDEX, + VFIO_PCI_BAR1_REGION_INDEX, + VFIO_PCI_BAR2_REGION_INDEX, + VFIO_PCI_BAR3_REGION_INDEX, + VFIO_PCI_BAR4_REGION_INDEX, + VFIO_PCI_BAR5_REGION_INDEX, + VFIO_PCI_ROM_REGION_INDEX, + VFIO_PCI_CONFIG_REGION_INDEX, + VFIO_PCI_NUM_REGIONS +}; + +enum { + VFIO_PCI_INTX_IRQ_INDEX, + VFIO_PCI_MSI_IRQ_INDEX, + VFIO_PCI_MSIX_IRQ_INDEX, + VFIO_PCI_NUM_IRQS +}; + /* -------- API for Type1 VFIO IOMMU -------- */ /** -- GitLab From b9403130a5350fca59a50ed11c198cb8c7e54119 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 12 Jul 2012 16:10:13 +0800 Subject: [PATCH 4837/5711] sched/cleanups: Add load balance cpumask pointer to 'struct lb_env' With this patch struct ld_env will have a pointer of the load balancing cpumask and we don't need to pass a cpumask around anymore. Signed-off-by: Michael Wang Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/4FFE8665.3080705@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 22321db64952..d0cc03b3e70b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3069,6 +3069,9 @@ struct lb_env { int new_dst_cpu; enum cpu_idle_type idle; long imbalance; + /* The set of CPUs under consideration for load-balancing */ + struct cpumask *cpus; + unsigned int flags; unsigned int loop; @@ -3653,8 +3656,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group) */ static inline void update_sg_lb_stats(struct lb_env *env, struct sched_group *group, int load_idx, - int local_group, const struct cpumask *cpus, - int *balance, struct sg_lb_stats *sgs) + int local_group, int *balance, struct sg_lb_stats *sgs) { unsigned long nr_running, max_nr_running, min_nr_running; unsigned long load, max_cpu_load, min_cpu_load; @@ -3671,7 +3673,7 @@ static inline void update_sg_lb_stats(struct lb_env *env, max_nr_running = 0; min_nr_running = ~0UL; - for_each_cpu_and(i, sched_group_cpus(group), cpus) { + for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { struct rq *rq = cpu_rq(i); nr_running = rq->nr_running; @@ -3800,8 +3802,7 @@ static bool update_sd_pick_busiest(struct lb_env *env, * @sds: variable to hold the statistics for this sched_domain. */ static inline void update_sd_lb_stats(struct lb_env *env, - const struct cpumask *cpus, - int *balance, struct sd_lb_stats *sds) + int *balance, struct sd_lb_stats *sds) { struct sched_domain *child = env->sd->child; struct sched_group *sg = env->sd->groups; @@ -3818,8 +3819,7 @@ static inline void update_sd_lb_stats(struct lb_env *env, local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg)); memset(&sgs, 0, sizeof(sgs)); - update_sg_lb_stats(env, sg, load_idx, local_group, - cpus, balance, &sgs); + update_sg_lb_stats(env, sg, load_idx, local_group, balance, &sgs); if (local_group && !(*balance)) return; @@ -4055,7 +4055,6 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * to restore balance. * * @env: The load balancing environment. - * @cpus: The set of CPUs under consideration for load-balancing. * @balance: Pointer to a variable indicating if this_cpu * is the appropriate cpu to perform load balancing at this_level. * @@ -4065,7 +4064,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * put to idle by rebalancing its tasks onto our group. */ static struct sched_group * -find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance) +find_busiest_group(struct lb_env *env, int *balance) { struct sd_lb_stats sds; @@ -4075,7 +4074,7 @@ find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance) * Compute the various statistics relavent for load balancing at * this level. */ - update_sd_lb_stats(env, cpus, balance, &sds); + update_sd_lb_stats(env, balance, &sds); /* * this_cpu is not the appropriate cpu to perform load balancing at @@ -4155,8 +4154,7 @@ ret: * find_busiest_queue - find the busiest runqueue among the cpus in group. */ static struct rq *find_busiest_queue(struct lb_env *env, - struct sched_group *group, - const struct cpumask *cpus) + struct sched_group *group) { struct rq *busiest = NULL, *rq; unsigned long max_load = 0; @@ -4171,7 +4169,7 @@ static struct rq *find_busiest_queue(struct lb_env *env, if (!capacity) capacity = fix_small_capacity(env->sd, group); - if (!cpumask_test_cpu(i, cpus)) + if (!cpumask_test_cpu(i, env->cpus)) continue; rq = cpu_rq(i); @@ -4252,6 +4250,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, .dst_grpmask = sched_group_cpus(sd->groups), .idle = idle, .loop_break = sched_nr_migrate_break, + .cpus = cpus, }; cpumask_copy(cpus, cpu_active_mask); @@ -4260,7 +4259,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, schedstat_inc(sd, lb_count[idle]); redo: - group = find_busiest_group(&env, cpus, balance); + group = find_busiest_group(&env, balance); if (*balance == 0) goto out_balanced; @@ -4270,7 +4269,7 @@ redo: goto out_balanced; } - busiest = find_busiest_queue(&env, group, cpus); + busiest = find_busiest_queue(&env, group); if (!busiest) { schedstat_inc(sd, lb_nobusyq[idle]); goto out_balanced; -- GitLab From 7740dfc0363a70546ef25c0383aca252f95a91d2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 21 Jul 2012 10:53:46 +1000 Subject: [PATCH 4838/5711] perf/x86/intel/uncore: Make UNCORE_PMU_HRTIMER_INTERVAL 64-bit i386 allmodconfig: arch/x86/kernel/cpu/perf_event_intel_uncore.c: In function 'uncore_pmu_hrtimer': arch/x86/kernel/cpu/perf_event_intel_uncore.c:728: warning: integer overflow in expression arch/x86/kernel/cpu/perf_event_intel_uncore.c: In function 'uncore_pmu_start_hrtimer': arch/x86/kernel/cpu/perf_event_intel_uncore.c:735: warning: integer overflow in expression Signed-off-by: Andrew Morton Cc: Zheng Yan Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-h84qlqj02zrojmxxybzmy9hi@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f3851892e077..c9e5dc56630a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -5,7 +5,7 @@ #include "perf_event.h" #define UNCORE_PMU_NAME_LEN 32 -#define UNCORE_PMU_HRTIMER_INTERVAL (60 * NSEC_PER_SEC) +#define UNCORE_PMU_HRTIMER_INTERVAL (60LL * NSEC_PER_SEC) #define UNCORE_FIXED_EVENT 0xff #define UNCORE_PMC_IDX_MAX_GENERIC 8 -- GitLab From d07bdfd322d307789f15b427dbcc39257665356f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 10 Jul 2012 09:42:15 +0200 Subject: [PATCH 4839/5711] perf/x86: Fix USER/KERNEL tagging of samples properly Some PMUs don't provide a full register set for their sample, specifically 'advanced' PMUs like AMD IBS and Intel PEBS which provide 'better' than regular interrupt accuracy. In this case we use the interrupt regs as basis and over-write some fields (typically IP) with different information. The perf core however uses user_mode() to distinguish user/kernel samples, user_mode() relies on regs->cs. If the interrupt skid pushed us over a boundary the new IP might not be in the same domain as the interrupt. Commit ce5c1fe9a9e ("perf/x86: Fix USER/KERNEL tagging of samples") tried to fix this by making the perf core use kernel_ip(). This however is wrong (TM), as pointed out by Linus, since it doesn't allow for VM86 and non-zero based segments in IA32 mode. Therefore, provide a new helper to set the regs->ip field, set_linear_ip(), which massages the regs into a suitable state assuming the provided IP is in fact a linear address. Also modify perf_instruction_pointer() and perf_callchain_user() to deal with segments base offsets. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1341910954.3462.102.camel@twins Signed-off-by: Ingo Molnar --- arch/x86/include/asm/perf_event.h | 11 ++- arch/x86/kernel/cpu/perf_event.c | 89 ++++++++++++++++++++--- arch/x86/kernel/cpu/perf_event.h | 20 +++++ arch/x86/kernel/cpu/perf_event_amd_ibs.c | 4 +- arch/x86/kernel/cpu/perf_event_intel_ds.c | 7 +- 5 files changed, 114 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index dab39350e51e..cb4e43bce98a 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -196,11 +196,16 @@ static inline u32 get_ibs_caps(void) { return 0; } extern void perf_events_lapic_init(void); /* - * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. - * This flag is otherwise unused and ABI specified to be 0, so nobody should - * care what we do with it. + * Abuse bits {3,5} of the cpu eflags register. These flags are otherwise + * unused and ABI specified to be 0, so nobody should care what we do with + * them. + * + * EXACT - the IP points to the exact instruction that triggered the + * event (HW bugs exempt). + * VM - original X86_VM_MASK; see set_linear_ip(). */ #define PERF_EFLAGS_EXACT (1UL << 3) +#define PERF_EFLAGS_VM (1UL << 5) struct pt_regs; extern unsigned long perf_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 29557aa06dda..915b876edd1e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "perf_event.h" @@ -1738,6 +1740,29 @@ valid_user_frame(const void __user *fp, unsigned long size) return (__range_not_ok(fp, size, TASK_SIZE) == 0); } +static unsigned long get_segment_base(unsigned int segment) +{ + struct desc_struct *desc; + int idx = segment >> 3; + + if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) { + if (idx > LDT_ENTRIES) + return 0; + + if (idx > current->active_mm->context.size) + return 0; + + desc = current->active_mm->context.ldt; + } else { + if (idx > GDT_ENTRIES) + return 0; + + desc = __this_cpu_ptr(&gdt_page.gdt[0]); + } + + return get_desc_base(desc + idx); +} + #ifdef CONFIG_COMPAT #include @@ -1746,13 +1771,17 @@ static inline int perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) { /* 32-bit process in 64-bit kernel. */ + unsigned long ss_base, cs_base; struct stack_frame_ia32 frame; const void __user *fp; if (!test_thread_flag(TIF_IA32)) return 0; - fp = compat_ptr(regs->bp); + cs_base = get_segment_base(regs->cs); + ss_base = get_segment_base(regs->ss); + + fp = compat_ptr(ss_base + regs->bp); while (entry->nr < PERF_MAX_STACK_DEPTH) { unsigned long bytes; frame.next_frame = 0; @@ -1765,8 +1794,8 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) if (!valid_user_frame(fp, sizeof(frame))) break; - perf_callchain_store(entry, frame.return_address); - fp = compat_ptr(frame.next_frame); + perf_callchain_store(entry, cs_base + frame.return_address); + fp = compat_ptr(ss_base + frame.next_frame); } return 1; } @@ -1789,6 +1818,12 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) return; } + /* + * We don't know what to do with VM86 stacks.. ignore them for now. + */ + if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM)) + return; + fp = (void __user *)regs->bp; perf_callchain_store(entry, regs->ip); @@ -1816,16 +1851,50 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) } } -unsigned long perf_instruction_pointer(struct pt_regs *regs) +/* + * Deal with code segment offsets for the various execution modes: + * + * VM86 - the good olde 16 bit days, where the linear address is + * 20 bits and we use regs->ip + 0x10 * regs->cs. + * + * IA32 - Where we need to look at GDT/LDT segment descriptor tables + * to figure out what the 32bit base address is. + * + * X32 - has TIF_X32 set, but is running in x86_64 + * + * X86_64 - CS,DS,SS,ES are all zero based. + */ +static unsigned long code_segment_base(struct pt_regs *regs) { - unsigned long ip; + /* + * If we are in VM86 mode, add the segment offset to convert to a + * linear address. + */ + if (regs->flags & X86_VM_MASK) + return 0x10 * regs->cs; + + /* + * For IA32 we look at the GDT/LDT segment base to convert the + * effective IP to a linear address. + */ +#ifdef CONFIG_X86_32 + if (user_mode(regs) && regs->cs != __USER_CS) + return get_segment_base(regs->cs); +#else + if (test_thread_flag(TIF_IA32)) { + if (user_mode(regs) && regs->cs != __USER32_CS) + return get_segment_base(regs->cs); + } +#endif + return 0; +} +unsigned long perf_instruction_pointer(struct pt_regs *regs) +{ if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) - ip = perf_guest_cbs->get_guest_ip(); - else - ip = instruction_pointer(regs); + return perf_guest_cbs->get_guest_ip(); - return ip; + return regs->ip + code_segment_base(regs); } unsigned long perf_misc_flags(struct pt_regs *regs) @@ -1838,7 +1907,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs) else misc |= PERF_RECORD_MISC_GUEST_KERNEL; } else { - if (!kernel_ip(regs->ip)) + if (user_mode(regs)) misc |= PERF_RECORD_MISC_USER; else misc |= PERF_RECORD_MISC_KERNEL; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 821d53b696d1..6605a81ba339 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -516,6 +516,26 @@ static inline bool kernel_ip(unsigned long ip) #endif } +/* + * Not all PMUs provide the right context information to place the reported IP + * into full context. Specifically segment registers are typically not + * supplied. + * + * Assuming the address is a linear address (it is for IBS), we fake the CS and + * vm86 mode using the known zero-based code segment and 'fix up' the registers + * to reflect this. + * + * Intel PEBS/LBR appear to typically provide the effective address, nothing + * much we can do about that but pray and treat it like a linear address. + */ +static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) +{ + regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS; + if (regs->flags & X86_VM_MASK) + regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK); + regs->ip = ip; +} + #ifdef CONFIG_CPU_SUP_AMD int amd_pmu_init(void); diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index da9bcdcd9856..7bfb5bec8630 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -13,6 +13,8 @@ #include +#include "perf_event.h" + static u32 ibs_caps; #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) @@ -536,7 +538,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) { regs.flags &= ~PERF_EFLAGS_EXACT; } else { - instruction_pointer_set(®s, ibs_data.regs[1]); + set_linear_ip(®s, ibs_data.regs[1]); regs.flags |= PERF_EFLAGS_EXACT; } diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 629ae0b7ad90..e38d97bf4259 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -499,7 +499,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) * We sampled a branch insn, rewind using the LBR stack */ if (ip == to) { - regs->ip = from; + set_linear_ip(regs, from); return 1; } @@ -529,7 +529,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) } while (to < ip); if (to == ip) { - regs->ip = old_to; + set_linear_ip(regs, old_to); return 1; } @@ -569,7 +569,8 @@ static void __intel_pmu_pebs_event(struct perf_event *event, * A possible PERF_SAMPLE_REGS will have to transfer all regs. */ regs = *iregs; - regs.ip = pebs->ip; + regs.flags = pebs->flags; + set_linear_ip(®s, pebs->ip); regs.bp = pebs->bp; regs.sp = pebs->sp; -- GitLab From e6dab5ffab59e910ec0e3355f4a6f29f7a7be474 Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Wed, 11 Jul 2012 18:14:58 +0400 Subject: [PATCH 4840/5711] perf/trace: Add ability to set a target task for events A few events are interesting not only for a current task. For example, sched_stat_* events are interesting for a task which wakes up. For this reason, it will be good if such events will be delivered to a target task too. Now a target task can be set by using __perf_task(). The original idea and a draft patch belongs to Peter Zijlstra. I need these events for profiling sleep times. sched_switch is used for getting callchains and sched_stat_* is used for getting time periods. These events are combined in user space, then it can be analyzed by perf tools. Inspired-by: Peter Zijlstra Cc: Steven Rostedt Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Steven Rostedt Cc: Arun Sharma Signed-off-by: Andrew Vagin Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1342016098-213063-1-git-send-email-avagin@openvz.org Signed-off-by: Ingo Molnar --- include/linux/ftrace_event.h | 5 +++-- include/linux/perf_event.h | 3 ++- include/trace/events/sched.h | 4 ++++ include/trace/ftrace.h | 6 +++++- kernel/events/callchain.c | 9 ++++++++- kernel/events/core.c | 30 ++++++++++++++++++++++++++++-- kernel/events/internal.h | 3 ++- kernel/trace/trace_event_perf.c | 2 +- kernel/trace/trace_kprobe.c | 6 ++++-- kernel/trace/trace_syscalls.c | 4 ++-- kernel/trace/trace_uprobe.c | 2 +- 11 files changed, 60 insertions(+), 14 deletions(-) diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index af961d6f7ab1..642928cf57b4 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -306,9 +306,10 @@ extern void *perf_trace_buf_prepare(int size, unsigned short type, static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, - u64 count, struct pt_regs *regs, void *head) + u64 count, struct pt_regs *regs, void *head, + struct task_struct *task) { - perf_tp_event(addr, count, raw_data, size, regs, head, rctx); + perf_tp_event(addr, count, raw_data, size, regs, head, rctx, task); } #endif diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 76c5c8b724a7..7602ccb3f40e 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1272,7 +1272,8 @@ static inline bool perf_paranoid_kernel(void) extern void perf_event_init(void); extern void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, struct pt_regs *regs, - struct hlist_head *head, int rctx); + struct hlist_head *head, int rctx, + struct task_struct *task); extern void perf_bp_event(struct perf_event *event, void *data); #ifndef perf_misc_flags diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index ea7a2035456d..5a8671e8a67f 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -73,6 +73,9 @@ DECLARE_EVENT_CLASS(sched_wakeup_template, __entry->prio = p->prio; __entry->success = success; __entry->target_cpu = task_cpu(p); + ) + TP_perf_assign( + __perf_task(p); ), TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d", @@ -325,6 +328,7 @@ DECLARE_EVENT_CLASS(sched_stat_template, ) TP_perf_assign( __perf_count(delay); + __perf_task(tsk); ), TP_printk("comm=%s pid=%d delay=%Lu [ns]", diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index c6bc2faaf261..a763888a36f9 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -712,6 +712,9 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call #undef __perf_count #define __perf_count(c) __count = (c) +#undef __perf_task +#define __perf_task(t) __task = (t) + #undef TP_perf_assign #define TP_perf_assign(args...) args @@ -725,6 +728,7 @@ perf_trace_##call(void *__data, proto) \ struct ftrace_raw_##call *entry; \ struct pt_regs __regs; \ u64 __addr = 0, __count = 1; \ + struct task_struct *__task = NULL; \ struct hlist_head *head; \ int __entry_size; \ int __data_size; \ @@ -752,7 +756,7 @@ perf_trace_##call(void *__data, proto) \ \ head = this_cpu_ptr(event_call->perf_events); \ perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ - __count, &__regs, head); \ + __count, &__regs, head, __task); \ } /* diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 6581a040f399..98d4597f43d6 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -153,7 +153,8 @@ put_callchain_entry(int rctx) put_recursion_context(__get_cpu_var(callchain_recursion), rctx); } -struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) +struct perf_callchain_entry * +perf_callchain(struct perf_event *event, struct pt_regs *regs) { int rctx; struct perf_callchain_entry *entry; @@ -178,6 +179,12 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) } if (regs) { + /* + * Disallow cross-task user callchains. + */ + if (event->ctx->task && event->ctx->task != current) + goto exit_put; + perf_callchain_store(entry, PERF_CONTEXT_USER); perf_callchain_user(entry, regs); } diff --git a/kernel/events/core.c b/kernel/events/core.c index f1cf0edeb39a..b7935fcec7d9 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4039,7 +4039,7 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type & PERF_SAMPLE_CALLCHAIN) { int size = 1; - data->callchain = perf_callchain(regs); + data->callchain = perf_callchain(event, regs); if (data->callchain) size += data->callchain->nr; @@ -5209,7 +5209,8 @@ static int perf_tp_event_match(struct perf_event *event, } void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, - struct pt_regs *regs, struct hlist_head *head, int rctx) + struct pt_regs *regs, struct hlist_head *head, int rctx, + struct task_struct *task) { struct perf_sample_data data; struct perf_event *event; @@ -5228,6 +5229,31 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, perf_swevent_event(event, count, &data, regs); } + /* + * If we got specified a target task, also iterate its context and + * deliver this event there too. + */ + if (task && task != current) { + struct perf_event_context *ctx; + struct trace_entry *entry = record; + + rcu_read_lock(); + ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]); + if (!ctx) + goto unlock; + + list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { + if (event->attr.type != PERF_TYPE_TRACEPOINT) + continue; + if (event->attr.config != entry->type) + continue; + if (perf_tp_event_match(event, &data, regs)) + perf_swevent_event(event, count, &data, regs); + } +unlock: + rcu_read_unlock(); + } + perf_swevent_put_recursion_context(rctx); } EXPORT_SYMBOL_GPL(perf_tp_event); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index b0b107f90afc..a096c19f2c2a 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -101,7 +101,8 @@ __output_copy(struct perf_output_handle *handle, } /* Callchain handling */ -extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); +extern struct perf_callchain_entry * +perf_callchain(struct perf_event *event, struct pt_regs *regs); extern int get_callchain_buffers(void); extern void put_callchain_buffers(void); diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index fee3752ae8f6..8a6d2ee2086c 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -281,7 +281,7 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip) head = this_cpu_ptr(event_function.perf_events); perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, 0, - 1, ®s, head); + 1, ®s, head, NULL); #undef ENTRY_SIZE } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index b31d3d5699fe..1a2117043bb1 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1002,7 +1002,8 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); + perf_trace_buf_submit(entry, size, rctx, + entry->ip, 1, regs, head, NULL); } /* Kretprobe profile handler */ @@ -1033,7 +1034,8 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); + perf_trace_buf_submit(entry, size, rctx, + entry->ret_ip, 1, regs, head, NULL); } #endif /* CONFIG_PERF_EVENTS */ diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 96fc73369099..60e4d7875672 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -532,7 +532,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) (unsigned long *)&rec->args); head = this_cpu_ptr(sys_data->enter_event->perf_events); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); + perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); } int perf_sysenter_enable(struct ftrace_event_call *call) @@ -608,7 +608,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) rec->ret = syscall_get_return_value(current, regs); head = this_cpu_ptr(sys_data->exit_event->perf_events); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); + perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); } int perf_sysexit_enable(struct ftrace_event_call *call) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 2b36ac68549e..03003cd7dd96 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -670,7 +670,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); + perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head, NULL); out: preempt_enable(); -- GitLab From a7ea3bbf5d58f4df2265d312f91d5769eabc8144 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 27 Jul 2012 14:48:09 -0400 Subject: [PATCH 4841/5711] time/jiffies: Allow CLOCK_TICK_RATE to be undefined CLOCK_TICK_RATE is a legacy constant that defines the timer device's granularity. On hardware with particularly coarse granularity, this constant is used to reduce accumulated time error when using jiffies as a clocksource, by calculating the hardware's actual tick length rather then just assuming it is 1sec/HZ. However, for the most part this is unnecessary, as most modern systems don't use jiffies for their clocksource, and their tick device is sufficiently fine grained to avoid major error. Thus, this patch allows an architecture to not define CLOCK_TICK_RATE, in which case ACTHZ defaults to (HZ << 8). Signed-off-by: Catalin Marinas Acked-by: Arnd Bergmann Cc: Richard Cochran Cc: Prarit Bhargava Cc: Andrew Morton [ Commit log & intention tweaks ] Signed-off-by: John Stultz Link: http://lkml.kernel.org/r/1343414893-45779-2-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar --- include/linux/jiffies.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 265e2c3cbd1c..7d24466fb80b 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -39,9 +39,6 @@ # error Invalid value of HZ. #endif -/* LATCH is used in the interval timer and ftape setup. */ -#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - /* Suppose we want to divide two numbers NOM and DEN: NOM/DEN, then we can * improve accuracy by shifting LSH bits, hence calculating: * (NOM << LSH) / DEN @@ -54,8 +51,15 @@ #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) +#ifdef CLOCK_TICK_RATE +/* LATCH is used in the interval timer and ftape setup. */ +# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ + /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ -#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) +# define ACTHZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) +#else +# define ACTHZ (HZ << 8) +#endif /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) -- GitLab From 02ab20ae38337b99b5c29c81090f594b8fd61283 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 27 Jul 2012 14:48:10 -0400 Subject: [PATCH 4842/5711] time/jiffies: Rename ACTHZ to SHIFTED_HZ Ingo noted that ACTHZ is a confusing name, and requested it be renamed, so this patch renames ACTHZ to SHIFTED_HZ to better describe it. Signed-off-by: John Stultz Cc: Prarit Bhargava Link: http://lkml.kernel.org/r/1343414893-45779-3-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar --- include/linux/jiffies.h | 21 +++++++++++++-------- include/linux/timex.h | 2 +- kernel/time/jiffies.c | 2 +- kernel/time/ntp.c | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 7d24466fb80b..82680541576d 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -55,21 +55,26 @@ /* LATCH is used in the interval timer and ftape setup. */ # define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ -/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ -# define ACTHZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) +/* + * HZ is the requested value. However the CLOCK_TICK_RATE may not allow + * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy) + */ +# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) #else -# define ACTHZ (HZ << 8) +# define SHIFTED_HZ (HZ << 8) #endif -/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ -#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) +/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ +#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8)) /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) -/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and */ -/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ -#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) +/* + * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and + * a value TUSEC for TICK_USEC (can be set bij adjtimex) + */ +#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8)) /* some arch's have a small-data section that can be accessed register-relative * but that can only take up to, say, 4-byte variables. jiffies being part of diff --git a/include/linux/timex.h b/include/linux/timex.h index 99bc88b1fc02..7c5ceb20e03a 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -232,7 +232,7 @@ struct timex { * estimated error = NTP dispersion. */ extern unsigned long tick_usec; /* USER_HZ period (usec) */ -extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ +extern unsigned long tick_nsec; /* SHIFTED_HZ period (nsec) */ extern void ntp_init(void); extern void ntp_clear(void); diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index a470154e0408..46da0537c10b 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -37,7 +37,7 @@ * requested HZ value. It is also not recommended * for "tick-less" systems. */ -#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) +#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ)) /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier * conversion, the .shift value could be zero. However diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index b7fbadc5c973..24174b4d669b 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -28,7 +28,7 @@ DEFINE_SPINLOCK(ntp_lock); /* USER_HZ period (usecs): */ unsigned long tick_usec = TICK_USEC; -/* ACTHZ period (nsecs): */ +/* SHIFTED_HZ period (nsecs): */ unsigned long tick_nsec; static u64 tick_length; -- GitLab From d4e3ab384b2343c7074f713ac330f839c38c52ee Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 27 Jul 2012 14:48:11 -0400 Subject: [PATCH 4843/5711] time: Clean up stray newlines Ingo noted inconsistent newline usage between functions. This patch cleans those up. Signed-off-by: John Stultz Cc: Prarit Bhargava Link: http://lkml.kernel.org/r/1343414893-45779-4-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar --- kernel/time/timekeeping.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index cf364db5589f..05b37a5ec7fb 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -239,7 +239,6 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp) update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult); } - /** * timekeeping_forward_now - update clock to the current time * @@ -436,7 +435,6 @@ int do_settimeofday(const struct timespec *tv) } EXPORT_SYMBOL(do_settimeofday); - /** * timekeeping_inject_offset - Adds or subtracts from the current time. * @tv: pointer to the timespec variable containing the offset @@ -550,7 +548,6 @@ void getrawmonotonic(struct timespec *ts) } EXPORT_SYMBOL(getrawmonotonic); - /** * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres */ @@ -683,7 +680,6 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, update_sleep_time(timespec_add(tk->total_sleep_time, *delta)); } - /** * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values * @delta: pointer to a timespec delta value @@ -718,7 +714,6 @@ void timekeeping_inject_sleeptime(struct timespec *delta) clock_was_set(); } - /** * timekeeping_resume - Resumes the generic timekeeping subsystem. * @@ -1003,7 +998,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) } - /** * accumulate_nsecs_to_secs - Accumulates nsecs into secs * @@ -1032,7 +1026,6 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) } } - /** * logarithmic_accumulation - shifted accumulation of cycles * @@ -1076,7 +1069,6 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, return offset; } - /** * update_wall_time - Uses the current clocksource to increment the wall time * @@ -1177,7 +1169,6 @@ void getboottime(struct timespec *ts) } EXPORT_SYMBOL_GPL(getboottime); - /** * get_monotonic_boottime - Returns monotonic time since boot * @ts: pointer to the timespec to be set @@ -1358,7 +1349,6 @@ ktime_t ktime_get_monotonic_offset(void) } EXPORT_SYMBOL_GPL(ktime_get_monotonic_offset); - /** * xtime_update() - advances the timekeeping infrastructure * @ticks: number of ticks, that have elapsed since the last call. -- GitLab From 6d0ef903e2bda70da124c10d8ad89f2382c87991 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 27 Jul 2012 14:48:12 -0400 Subject: [PATCH 4844/5711] time: Clean up offs_real/wall_to_mono and offs_boot/total_sleep_time updates For performance reasons, we maintain ktime_t based duplicates of wall_to_monotonic (offs_real) and total_sleep_time (offs_boot). Since large problems could occur (such as the resume regression on 3.5-rc7, or the leapsecond hrtimer issue) if these value pairs were to be inconsistently updated, this patch this cleans up how we modify these value pairs to ensure we are always consistent. As a side-effect this is also more efficient as we only caulculate the duplicate values when they are changed, rather then every update_wall_time call. This also provides WARN_ONs to detect if future changes break the invariants. Signed-off-by: John Stultz Cc: Peter Zijlstra Cc: Richard Cochran Cc: Prarit Bhargava Link: http://lkml.kernel.org/r/1343414893-45779-5-git-send-email-john.stultz@linaro.org [ Cleaned up minor style issues. ] Signed-off-by: Ingo Molnar --- kernel/time/timekeeping.c | 90 +++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 05b37a5ec7fb..4da65592b4d9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -65,14 +65,14 @@ struct timekeeper { * used instead. */ struct timespec wall_to_monotonic; - /* time spent in suspend */ - struct timespec total_sleep_time; - /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ - struct timespec raw_time; /* Offset clock monotonic -> clock realtime */ ktime_t offs_real; + /* time spent in suspend */ + struct timespec total_sleep_time; /* Offset clock monotonic -> clock boottime */ ktime_t offs_boot; + /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ + struct timespec raw_time; /* Seqlock for all timekeeper values */ seqlock_t lock; }; @@ -117,6 +117,31 @@ static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts) tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift; } +static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) +{ + struct timespec tmp; + + /* + * Verify consistency of: offset_real = -wall_to_monotonic + * before modifying anything + */ + set_normalized_timespec(&tmp, -tk->wall_to_monotonic.tv_sec, + -tk->wall_to_monotonic.tv_nsec); + WARN_ON_ONCE(tk->offs_real.tv64 != timespec_to_ktime(tmp).tv64); + tk->wall_to_monotonic = wtm; + set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); + tk->offs_real = timespec_to_ktime(tmp); +} + +static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) +{ + /* Verify consistency before modifying */ + WARN_ON_ONCE(tk->offs_boot.tv64 != timespec_to_ktime(tk->total_sleep_time).tv64); + + tk->total_sleep_time = t; + tk->offs_boot = timespec_to_ktime(t); +} + /** * timekeeper_setup_internals - Set up internals to use clocksource clock. * @@ -217,14 +242,6 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) return nsec + arch_gettimeoffset(); } -static void update_rt_offset(struct timekeeper *tk) -{ - struct timespec tmp, *wtm = &tk->wall_to_monotonic; - - set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); - tk->offs_real = timespec_to_ktime(tmp); -} - /* must hold write on timekeeper.lock */ static void timekeeping_update(struct timekeeper *tk, bool clearntp) { @@ -234,7 +251,6 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp) tk->ntp_error = 0; ntp_clear(); } - update_rt_offset(tk); xt = tk_xtime(tk); update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult); } @@ -419,8 +435,8 @@ int do_settimeofday(const struct timespec *tv) ts_delta.tv_sec = tv->tv_sec - xt.tv_sec; ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; - timekeeper.wall_to_monotonic = - timespec_sub(timekeeper.wall_to_monotonic, ts_delta); + tk_set_wall_to_mono(&timekeeper, + timespec_sub(timekeeper.wall_to_monotonic, ts_delta)); tk_set_xtime(&timekeeper, tv); @@ -454,8 +470,8 @@ int timekeeping_inject_offset(struct timespec *ts) tk_xtime_add(&timekeeper, ts); - timekeeper.wall_to_monotonic = - timespec_sub(timekeeper.wall_to_monotonic, *ts); + tk_set_wall_to_mono(&timekeeper, + timespec_sub(timekeeper.wall_to_monotonic, *ts)); timekeeping_update(&timekeeper, true); @@ -621,7 +637,7 @@ void __init timekeeping_init(void) { struct clocksource *clock; unsigned long flags; - struct timespec now, boot; + struct timespec now, boot, tmp; read_persistent_clock(&now); read_boot_clock(&boot); @@ -642,23 +658,19 @@ void __init timekeeping_init(void) if (boot.tv_sec == 0 && boot.tv_nsec == 0) boot = tk_xtime(&timekeeper); - set_normalized_timespec(&timekeeper.wall_to_monotonic, - -boot.tv_sec, -boot.tv_nsec); - update_rt_offset(&timekeeper); - timekeeper.total_sleep_time.tv_sec = 0; - timekeeper.total_sleep_time.tv_nsec = 0; + set_normalized_timespec(&tmp, -boot.tv_sec, -boot.tv_nsec); + tk_set_wall_to_mono(&timekeeper, tmp); + + tmp.tv_sec = 0; + tmp.tv_nsec = 0; + tk_set_sleep_time(&timekeeper, tmp); + write_sequnlock_irqrestore(&timekeeper.lock, flags); } /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; -static void update_sleep_time(struct timespec t) -{ - timekeeper.total_sleep_time = t; - timekeeper.offs_boot = timespec_to_ktime(t); -} - /** * __timekeeping_inject_sleeptime - Internal function to add sleep interval * @delta: pointer to a timespec delta value @@ -674,10 +686,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, "sleep delta value!\n"); return; } - tk_xtime_add(tk, delta); - tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta); - update_sleep_time(timespec_add(tk->total_sleep_time, *delta)); + tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta)); + tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta)); } /** @@ -1018,11 +1029,18 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) /* Figure out if its a leap sec and apply if needed */ leap = second_overflow(tk->xtime_sec); - tk->xtime_sec += leap; - tk->wall_to_monotonic.tv_sec -= leap; - if (leap) - clock_was_set_delayed(); + if (unlikely(leap)) { + struct timespec ts; + + tk->xtime_sec += leap; + ts.tv_sec = leap; + ts.tv_nsec = 0; + tk_set_wall_to_mono(tk, + timespec_sub(tk->wall_to_monotonic, ts)); + + clock_was_set_delayed(); + } } } -- GitLab From 4e250fdde9be50581c7dd5fed88c9b9960615314 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 27 Jul 2012 14:48:13 -0400 Subject: [PATCH 4845/5711] time: Remove all direct references to timekeeper Ingo noted that the numerous timekeeper.value references made the timekeeping code ugly and caused many long lines that had to be broken up. He recommended replacing timekeeper.value references with tk->value. This patch provides a local tk value for all top level time functions and sets it to &timekeeper. Then all timekeeper access is done via a tk pointer. Signed-off-by: John Stultz Cc: Prarit Bhargava Link: http://lkml.kernel.org/r/1343414893-45779-6-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar --- kernel/time/timekeeping.c | 282 +++++++++++++++++++++----------------- 1 file changed, 154 insertions(+), 128 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 4da65592b4d9..2988bc819187 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -292,18 +292,19 @@ static void timekeeping_forward_now(struct timekeeper *tk) */ void getnstimeofday(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs = 0; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - ts->tv_sec = timekeeper.xtime_sec; - ts->tv_nsec = timekeeping_get_ns(&timekeeper); + ts->tv_sec = tk->xtime_sec; + ts->tv_nsec = timekeeping_get_ns(tk); - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); timespec_add_ns(ts, nsecs); } @@ -311,19 +312,18 @@ EXPORT_SYMBOL(getnstimeofday); ktime_t ktime_get(void) { + struct timekeeper *tk = &timekeeper; unsigned int seq; s64 secs, nsecs; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&timekeeper.lock); - secs = timekeeper.xtime_sec + - timekeeper.wall_to_monotonic.tv_sec; - nsecs = timekeeping_get_ns(&timekeeper) + - timekeeper.wall_to_monotonic.tv_nsec; + seq = read_seqbegin(&tk->lock); + secs = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; + nsecs = timekeeping_get_ns(tk) + tk->wall_to_monotonic.tv_nsec; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); /* * Use ktime_set/ktime_add_ns to create a proper ktime on * 32-bit architectures without CONFIG_KTIME_SCALAR. @@ -342,18 +342,19 @@ EXPORT_SYMBOL_GPL(ktime_get); */ void ktime_get_ts(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; struct timespec tomono; unsigned int seq; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&timekeeper.lock); - ts->tv_sec = timekeeper.xtime_sec; - ts->tv_nsec = timekeeping_get_ns(&timekeeper); - tomono = timekeeper.wall_to_monotonic; + seq = read_seqbegin(&tk->lock); + ts->tv_sec = tk->xtime_sec; + ts->tv_nsec = timekeeping_get_ns(tk); + tomono = tk->wall_to_monotonic; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, ts->tv_nsec + tomono.tv_nsec); @@ -373,22 +374,23 @@ EXPORT_SYMBOL_GPL(ktime_get_ts); */ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real) { + struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs_raw, nsecs_real; WARN_ON_ONCE(timekeeping_suspended); do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - *ts_raw = timekeeper.raw_time; - ts_real->tv_sec = timekeeper.xtime_sec; + *ts_raw = tk->raw_time; + ts_real->tv_sec = tk->xtime_sec; ts_real->tv_nsec = 0; - nsecs_raw = timekeeping_get_ns_raw(&timekeeper); - nsecs_real = timekeeping_get_ns(&timekeeper); + nsecs_raw = timekeeping_get_ns_raw(tk); + nsecs_real = timekeeping_get_ns(tk); - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); timespec_add_ns(ts_raw, nsecs_raw); timespec_add_ns(ts_real, nsecs_real); @@ -421,28 +423,28 @@ EXPORT_SYMBOL(do_gettimeofday); */ int do_settimeofday(const struct timespec *tv) { + struct timekeeper *tk = &timekeeper; struct timespec ts_delta, xt; unsigned long flags; if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); - timekeeping_forward_now(&timekeeper); + timekeeping_forward_now(tk); - xt = tk_xtime(&timekeeper); + xt = tk_xtime(tk); ts_delta.tv_sec = tv->tv_sec - xt.tv_sec; ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; - tk_set_wall_to_mono(&timekeeper, - timespec_sub(timekeeper.wall_to_monotonic, ts_delta)); + tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta)); - tk_set_xtime(&timekeeper, tv); + tk_set_xtime(tk, tv); - timekeeping_update(&timekeeper, true); + timekeeping_update(tk, true); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); /* signal hrtimers about time change */ clock_was_set(); @@ -459,23 +461,23 @@ EXPORT_SYMBOL(do_settimeofday); */ int timekeeping_inject_offset(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; unsigned long flags; if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); - timekeeping_forward_now(&timekeeper); + timekeeping_forward_now(tk); - tk_xtime_add(&timekeeper, ts); - tk_set_wall_to_mono(&timekeeper, - timespec_sub(timekeeper.wall_to_monotonic, *ts)); + tk_xtime_add(tk, ts); + tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); - timekeeping_update(&timekeeper, true); + timekeeping_update(tk, true); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); /* signal hrtimers about time change */ clock_was_set(); @@ -491,23 +493,24 @@ EXPORT_SYMBOL(timekeeping_inject_offset); */ static int change_clocksource(void *data) { + struct timekeeper *tk = &timekeeper; struct clocksource *new, *old; unsigned long flags; new = (struct clocksource *) data; - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); - timekeeping_forward_now(&timekeeper); + timekeeping_forward_now(tk); if (!new->enable || new->enable(new) == 0) { - old = timekeeper.clock; - tk_setup_internals(&timekeeper, new); + old = tk->clock; + tk_setup_internals(tk, new); if (old->disable) old->disable(old); } - timekeeping_update(&timekeeper, true); + timekeeping_update(tk, true); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); return 0; } @@ -521,7 +524,9 @@ static int change_clocksource(void *data) */ void timekeeping_notify(struct clocksource *clock) { - if (timekeeper.clock == clock) + struct timekeeper *tk = &timekeeper; + + if (tk->clock == clock) return; stop_machine(change_clocksource, clock, NULL); tick_clock_notify(); @@ -550,15 +555,16 @@ EXPORT_SYMBOL_GPL(ktime_get_real); */ void getrawmonotonic(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs; do { - seq = read_seqbegin(&timekeeper.lock); - nsecs = timekeeping_get_ns_raw(&timekeeper); - *ts = timekeeper.raw_time; + seq = read_seqbegin(&tk->lock); + nsecs = timekeeping_get_ns_raw(tk); + *ts = tk->raw_time; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); timespec_add_ns(ts, nsecs); } @@ -569,15 +575,16 @@ EXPORT_SYMBOL(getrawmonotonic); */ int timekeeping_valid_for_hres(void) { + struct timekeeper *tk = &timekeeper; unsigned long seq; int ret; do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - ret = timekeeper.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; + ret = tk->clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); return ret; } @@ -587,15 +594,16 @@ int timekeeping_valid_for_hres(void) */ u64 timekeeping_max_deferment(void) { + struct timekeeper *tk = &timekeeper; unsigned long seq; u64 ret; do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - ret = timekeeper.clock->max_idle_ns; + ret = tk->clock->max_idle_ns; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); return ret; } @@ -635,6 +643,7 @@ void __attribute__((weak)) read_boot_clock(struct timespec *ts) */ void __init timekeeping_init(void) { + struct timekeeper *tk = &timekeeper; struct clocksource *clock; unsigned long flags; struct timespec now, boot, tmp; @@ -642,30 +651,30 @@ void __init timekeeping_init(void) read_persistent_clock(&now); read_boot_clock(&boot); - seqlock_init(&timekeeper.lock); + seqlock_init(&tk->lock); ntp_init(); - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); clock = clocksource_default_clock(); if (clock->enable) clock->enable(clock); - tk_setup_internals(&timekeeper, clock); + tk_setup_internals(tk, clock); - tk_set_xtime(&timekeeper, &now); - timekeeper.raw_time.tv_sec = 0; - timekeeper.raw_time.tv_nsec = 0; + tk_set_xtime(tk, &now); + tk->raw_time.tv_sec = 0; + tk->raw_time.tv_nsec = 0; if (boot.tv_sec == 0 && boot.tv_nsec == 0) - boot = tk_xtime(&timekeeper); + boot = tk_xtime(tk); set_normalized_timespec(&tmp, -boot.tv_sec, -boot.tv_nsec); - tk_set_wall_to_mono(&timekeeper, tmp); + tk_set_wall_to_mono(tk, tmp); tmp.tv_sec = 0; tmp.tv_nsec = 0; - tk_set_sleep_time(&timekeeper, tmp); + tk_set_sleep_time(tk, tmp); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); } /* time in seconds when suspend began */ @@ -703,6 +712,7 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, */ void timekeeping_inject_sleeptime(struct timespec *delta) { + struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec ts; @@ -711,15 +721,15 @@ void timekeeping_inject_sleeptime(struct timespec *delta) if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) return; - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); - timekeeping_forward_now(&timekeeper); + timekeeping_forward_now(tk); - __timekeeping_inject_sleeptime(&timekeeper, delta); + __timekeeping_inject_sleeptime(tk, delta); - timekeeping_update(&timekeeper, true); + timekeeping_update(tk, true); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); /* signal hrtimers about time change */ clock_was_set(); @@ -734,6 +744,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta) */ static void timekeeping_resume(void) { + struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec ts; @@ -741,18 +752,18 @@ static void timekeeping_resume(void) clocksource_resume(); - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { ts = timespec_sub(ts, timekeeping_suspend_time); - __timekeeping_inject_sleeptime(&timekeeper, &ts); + __timekeeping_inject_sleeptime(tk, &ts); } /* re-base the last cycle value */ - timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); - timekeeper.ntp_error = 0; + tk->clock->cycle_last = tk->clock->read(tk->clock); + tk->ntp_error = 0; timekeeping_suspended = 0; - timekeeping_update(&timekeeper, false); - write_sequnlock_irqrestore(&timekeeper.lock, flags); + timekeeping_update(tk, false); + write_sequnlock_irqrestore(&tk->lock, flags); touch_softlockup_watchdog(); @@ -764,14 +775,15 @@ static void timekeeping_resume(void) static int timekeeping_suspend(void) { + struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec delta, delta_delta; static struct timespec old_delta; read_persistent_clock(&timekeeping_suspend_time); - write_seqlock_irqsave(&timekeeper.lock, flags); - timekeeping_forward_now(&timekeeper); + write_seqlock_irqsave(&tk->lock, flags); + timekeeping_forward_now(tk); timekeeping_suspended = 1; /* @@ -780,7 +792,7 @@ static int timekeeping_suspend(void) * try to compensate so the difference in system time * and persistent_clock time stays close to constant. */ - delta = timespec_sub(tk_xtime(&timekeeper), timekeeping_suspend_time); + delta = timespec_sub(tk_xtime(tk), timekeeping_suspend_time); delta_delta = timespec_sub(delta, old_delta); if (abs(delta_delta.tv_sec) >= 2) { /* @@ -793,7 +805,7 @@ static int timekeeping_suspend(void) timekeeping_suspend_time = timespec_add(timekeeping_suspend_time, delta_delta); } - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); clocksource_suspend(); @@ -904,7 +916,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) * the error. This causes the likely below to be unlikely. * * The proper fix is to avoid rounding up by using - * the high precision timekeeper.xtime_nsec instead of + * the high precision tk->xtime_nsec instead of * xtime.tv_nsec everywhere. Fixing this will take some * time. */ @@ -1094,21 +1106,22 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, static void update_wall_time(void) { struct clocksource *clock; + struct timekeeper *tk = &timekeeper; cycle_t offset; int shift = 0, maxshift; unsigned long flags; s64 remainder; - write_seqlock_irqsave(&timekeeper.lock, flags); + write_seqlock_irqsave(&tk->lock, flags); /* Make sure we're fully resumed: */ if (unlikely(timekeeping_suspended)) goto out; - clock = timekeeper.clock; + clock = tk->clock; #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET - offset = timekeeper.cycle_interval; + offset = tk->cycle_interval; #else offset = (clock->read(clock) - clock->cycle_last) & clock->mask; #endif @@ -1121,19 +1134,19 @@ static void update_wall_time(void) * chunk in one go, and then try to consume the next smaller * doubled multiple. */ - shift = ilog2(offset) - ilog2(timekeeper.cycle_interval); + shift = ilog2(offset) - ilog2(tk->cycle_interval); shift = max(0, shift); /* Bound shift to one less than what overflows tick_length */ maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; shift = min(shift, maxshift); - while (offset >= timekeeper.cycle_interval) { - offset = logarithmic_accumulation(&timekeeper, offset, shift); - if(offset < timekeeper.cycle_interval<= tk->cycle_interval) { + offset = logarithmic_accumulation(tk, offset, shift); + if (offset < tk->cycle_interval<xtime_nsec & ((1 << tk->shift) - 1); + tk->xtime_nsec -= remainder; + tk->xtime_nsec += 1 << tk->shift; + tk->ntp_error += remainder << tk->ntp_error_shift; /* * Finally, make sure that after the rounding * xtime_nsec isn't larger than NSEC_PER_SEC */ - accumulate_nsecs_to_secs(&timekeeper); + accumulate_nsecs_to_secs(tk); - timekeeping_update(&timekeeper, false); + timekeeping_update(tk, false); out: - write_sequnlock_irqrestore(&timekeeper.lock, flags); + write_sequnlock_irqrestore(&tk->lock, flags); } @@ -1176,11 +1189,12 @@ out: */ void getboottime(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; struct timespec boottime = { - .tv_sec = timekeeper.wall_to_monotonic.tv_sec + - timekeeper.total_sleep_time.tv_sec, - .tv_nsec = timekeeper.wall_to_monotonic.tv_nsec + - timekeeper.total_sleep_time.tv_nsec + .tv_sec = tk->wall_to_monotonic.tv_sec + + tk->total_sleep_time.tv_sec, + .tv_nsec = tk->wall_to_monotonic.tv_nsec + + tk->total_sleep_time.tv_nsec }; set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec); @@ -1198,19 +1212,20 @@ EXPORT_SYMBOL_GPL(getboottime); */ void get_monotonic_boottime(struct timespec *ts) { + struct timekeeper *tk = &timekeeper; struct timespec tomono, sleep; unsigned int seq; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&timekeeper.lock); - ts->tv_sec = timekeeper.xtime_sec; - ts->tv_nsec = timekeeping_get_ns(&timekeeper); - tomono = timekeeper.wall_to_monotonic; - sleep = timekeeper.total_sleep_time; + seq = read_seqbegin(&tk->lock); + ts->tv_sec = tk->xtime_sec; + ts->tv_nsec = timekeeping_get_ns(tk); + tomono = tk->wall_to_monotonic; + sleep = tk->total_sleep_time; - } while (read_seqretry(&timekeeper.lock, seq)); + } while (read_seqretry(&tk->lock, seq)); set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec); @@ -1240,31 +1255,38 @@ EXPORT_SYMBOL_GPL(ktime_get_boottime); */ void monotonic_to_bootbased(struct timespec *ts) { - *ts = timespec_add(*ts, timekeeper.total_sleep_time); + struct timekeeper *tk = &timekeeper; + + *ts = timespec_add(*ts, tk->total_sleep_time); } EXPORT_SYMBOL_GPL(monotonic_to_bootbased); unsigned long get_seconds(void) { - return timekeeper.xtime_sec; + struct timekeeper *tk = &timekeeper; + + return tk->xtime_sec; } EXPORT_SYMBOL(get_seconds); struct timespec __current_kernel_time(void) { - return tk_xtime(&timekeeper); + struct timekeeper *tk = &timekeeper; + + return tk_xtime(tk); } struct timespec current_kernel_time(void) { + struct timekeeper *tk = &timekeeper; struct timespec now; unsigned long seq; do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - now = tk_xtime(&timekeeper); - } while (read_seqretry(&timekeeper.lock, seq)); + now = tk_xtime(tk); + } while (read_seqretry(&tk->lock, seq)); return now; } @@ -1272,15 +1294,16 @@ EXPORT_SYMBOL(current_kernel_time); struct timespec get_monotonic_coarse(void) { + struct timekeeper *tk = &timekeeper; struct timespec now, mono; unsigned long seq; do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - now = tk_xtime(&timekeeper); - mono = timekeeper.wall_to_monotonic; - } while (read_seqretry(&timekeeper.lock, seq)); + now = tk_xtime(tk); + mono = tk->wall_to_monotonic; + } while (read_seqretry(&tk->lock, seq)); set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, now.tv_nsec + mono.tv_nsec); @@ -1309,14 +1332,15 @@ void do_timer(unsigned long ticks) void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, struct timespec *wtom, struct timespec *sleep) { + struct timekeeper *tk = &timekeeper; unsigned long seq; do { - seq = read_seqbegin(&timekeeper.lock); - *xtim = tk_xtime(&timekeeper); - *wtom = timekeeper.wall_to_monotonic; - *sleep = timekeeper.total_sleep_time; - } while (read_seqretry(&timekeeper.lock, seq)); + seq = read_seqbegin(&tk->lock); + *xtim = tk_xtime(tk); + *wtom = tk->wall_to_monotonic; + *sleep = tk->total_sleep_time; + } while (read_seqretry(&tk->lock, seq)); } #ifdef CONFIG_HIGH_RES_TIMERS @@ -1330,19 +1354,20 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, */ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) { + struct timekeeper *tk = &timekeeper; ktime_t now; unsigned int seq; u64 secs, nsecs; do { - seq = read_seqbegin(&timekeeper.lock); + seq = read_seqbegin(&tk->lock); - secs = timekeeper.xtime_sec; - nsecs = timekeeping_get_ns(&timekeeper); + secs = tk->xtime_sec; + nsecs = timekeeping_get_ns(tk); - *offs_real = timekeeper.offs_real; - *offs_boot = timekeeper.offs_boot; - } while (read_seqretry(&timekeeper.lock, seq)); + *offs_real = tk->offs_real; + *offs_boot = tk->offs_boot; + } while (read_seqretry(&tk->lock, seq)); now = ktime_add_ns(ktime_set(secs, 0), nsecs); now = ktime_sub(now, *offs_real); @@ -1355,13 +1380,14 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) */ ktime_t ktime_get_monotonic_offset(void) { + struct timekeeper *tk = &timekeeper; unsigned long seq; struct timespec wtom; do { - seq = read_seqbegin(&timekeeper.lock); - wtom = timekeeper.wall_to_monotonic; - } while (read_seqretry(&timekeeper.lock, seq)); + seq = read_seqbegin(&tk->lock); + wtom = tk->wall_to_monotonic; + } while (read_seqretry(&tk->lock, seq)); return timespec_to_ktime(wtom); } -- GitLab From 58f598ff0bb0c030e026a0738450c6a46248f6a8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 31 Jul 2012 15:45:41 +0100 Subject: [PATCH 4846/5711] ASoC: ab8500: Inform SoC Core that we have our own I/O arrangements If codec->control_data is not populated SoC Core assumes we want to use regmap, which fails catastrophically, as we don't have one: Unable to handle kernel NULL pointer dereference at virtual address 00000080 pgd = c0004000 [00000080] *pgd=00000000 Internal error: Oops: 17 [#1] PREEMPT SMP ARM Modules linked in: CPU: 1 Not tainted (3.5.0-rc6-00884-g0b2419e-dirty #130) PC is at regmap_read+0x10/0x5c LR is at hw_read+0x80/0x90 pc : [] lr : [] psr: 60000013 Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 3c795921c5f6..23b40186f9b8 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2406,6 +2406,10 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) /* Setup AB8500 according to board-settings */ pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); + + /* Inform SoC Core that we have our own I/O arrangements. */ + codec->control_data = (void *)true; + status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); if (status < 0) { pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); -- GitLab From eef69ac7c9672049069a0bb88dae756fdec4de07 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 27 Jul 2012 19:18:42 +0800 Subject: [PATCH 4847/5711] ASoC: sgtl5000: enable VAG_POWER for LINE_IN LINE_IN also needs VAG_POWER on or we may hear noise when directly route LINE_IN to Headphone Mux. Tested on imx28evk. Signed-off-by: Dong Aisheng Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 5c54b6f4623a..df2f99d1d428 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -239,6 +239,7 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ {"LO", NULL, "DAC"}, /* dac --> line_out */ + {"LINE_IN", NULL, "VAG_POWER"}, {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ -- GitLab From d0e3cce9144eb8bff0852531aadbe221addaa2d5 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Tue, 31 Jul 2012 14:42:27 +0200 Subject: [PATCH 4848/5711] ASoC: AC97 doesn't use regmap by default Since commit 38cbf9598feba97de9f9b43efa9153fd7c1a2ec9 ("ASoC: core: Try to use regmap if the driver doesn't set up any I/O") any ASoC codec which doesn't set codec::control_data is assumed to use regmap. That doesn't work with AC97 so this workaround sets the codec::control_data member to a random value to restore proper behaviour. Tested with WM9712. Signed-off-by: Manuel Lauss Signed-off-by: Mark Brown --- sound/soc/codecs/ad1980.c | 1 + sound/soc/codecs/stac9766.c | 1 + sound/soc/codecs/wm9712.c | 1 + sound/soc/codecs/wm9713.c | 1 + 4 files changed, 4 insertions(+) diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 8c39dddd7d00..11b1b714b8b5 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -186,6 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); + codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 982e437799a8..33c0f3d39c87 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -340,6 +340,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); + codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 099e6ec32125..f16fb361a4eb 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -619,6 +619,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) { int ret = 0; + codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 3eb19fb71d17..d0b8a3287a85 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1196,6 +1196,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) if (wm9713 == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, wm9713); + codec->control_data = wm9713; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) -- GitLab From b042414feb240df5f5911b9bca39b61e6738e814 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 14:40:12 +1000 Subject: [PATCH 4849/5711] nfs: increase number of permitted callback connections. By default a sunrpc service is limited to (N+3)*20 connections where N is the number of threads. This is 80 when N==1. If this number is exceeded a warning is printed suggesting that the number of threads be increased. However with services which run a single thread, this is impossible. For such services there is a ->sv_maxconn setting that can be used to forcibly increase the limit, and silence the message. This is used by lockd. The nfs client uses a sunrpc service to handle callbacks and it too is single-threaded, so to avoid the useless messages, and to allow a reasonable number of concurrent connections, we need to set ->sv_maxconn. 1024 seems like a good number. Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust --- fs/nfs/callback.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index ca3ac992028b..4c8459e5bdee 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -241,6 +241,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) ret = -ENOMEM; goto out_err; } + /* As there is only one thread we need to over-ride the + * default maximum of 80 connections + */ + serv->sv_maxconn = 1024; ret = svc_bind(serv, net); if (ret < 0) { -- GitLab From 9d40e5582c9c4cfb6977ba2a0ca9c2ed82c56f21 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Jul 2012 18:24:19 +0100 Subject: [PATCH 4850/5711] ASoC: wm8962: Allow VMID time to fully ramp Required for reliable power up from cold. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8962.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index eaf65863ec21..aa9ce9dd7d8a 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2501,6 +2501,9 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, /* VMID 2*250k */ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, WM8962_VMID_SEL_MASK, 0x100); + + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + msleep(100); break; case SND_SOC_BIAS_OFF: -- GitLab From ad0fcd4eb68059de02e1766948263c71b8a5b1dc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 15:46:23 -0400 Subject: [PATCH 4851/5711] nfs: explicitly reject LOCK_MAND flock() requests We have no mechanism to emulate LOCK_MAND locks on NFSv4, so explicitly return -EINVAL if someone requests it. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1557978ca7b3..b039a17ee941 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -834,6 +834,15 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; + /* + * The NFSv4 protocol doesn't support LOCK_MAND, which is not part of + * any standard. In principle we might be able to support LOCK_MAND + * on NFSv2/3 since NLMv3/4 support DOS share modes, but for now the + * NFS code is not set up for it. + */ + if (fl->fl_type & LOCK_MAND) + return -EINVAL; + if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) is_local = 1; -- GitLab From adfe1560de1c696324554fba70c92f2d7c947ff7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 31 Jul 2012 16:38:41 -0300 Subject: [PATCH 4852/5711] [media] radio-tea5777: use library for 64bits div drivers/built-in.o: In function `radio_tea5777_set_freq': radio-tea5777.c:(.text+0x4d8704): undefined reference to `__udivdi3' Reported-by: Randy Dunlap Cc: Hans de Goede Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5777.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c index 3e12179364f8..5bc9fa62720b 100644 --- a/drivers/media/radio/radio-tea5777.c +++ b/drivers/media/radio/radio-tea5777.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "radio-tea5777.h" MODULE_AUTHOR("Hans de Goede "); @@ -158,10 +159,11 @@ static int radio_tea5777_set_freq(struct radio_tea5777 *tea) int res; freq = clamp_t(u32, tea->freq, - TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH); - freq = (freq + 8) / 16; /* to kHz */ + TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH) + 8; + do_div(freq, 16); /* to kHz */ - freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP; + freq -= TEA5777_FM_IF; + do_div(freq, TEA5777_FM_FREQ_STEP); tea->write_reg &= ~(TEA5777_W_FM_PLL_MASK | TEA5777_W_FM_FREF_MASK); tea->write_reg |= freq << TEA5777_W_FM_PLL_SHIFT; -- GitLab From 54764bb647b2e847c512acf8d443df965da35000 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Jul 2012 01:08:23 +0000 Subject: [PATCH 4853/5711] ipv4: Restore old dst_free() behavior. commit 404e0a8b6a55 (net: ipv4: fix RCU races on dst refcounts) tried to solve a race but added a problem at device/fib dismantle time : We really want to call dst_free() as soon as possible, even if sockets still have dst in their cache. dst_release() calls in free_fib_info_rcu() are not welcomed. Root of the problem was that now we also cache output routes (in nh_rth_output), we must use call_rcu() instead of call_rcu_bh() in rt_free(), because output route lookups are done in process context. Based on feedback and initial patch from David Miller (adding another call_rcu_bh() call in fib, but it appears it was not the right fix) I left the inet_sk_rx_dst_set() helper and added __rcu attributes to nh_rth_output and nh_rth_input to better document what is going on in this code. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/dst.h | 7 ++++++- include/net/inet_sock.h | 10 +++------- include/net/ip_fib.h | 4 ++-- net/core/dst.c | 26 +++++--------------------- net/decnet/dn_route.c | 6 ------ net/ipv4/fib_semantics.c | 21 +++++++++++++++++---- net/ipv4/route.c | 26 +++++++++++++++++--------- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 31a9fd39edb6..baf597890064 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -61,7 +61,6 @@ struct dst_entry { #define DST_NOPEER 0x0040 #define DST_FAKE_RTABLE 0x0080 #define DST_XFRM_TUNNEL 0x0100 -#define DST_RCU_FREE 0x0200 unsigned short pending_confirm; @@ -383,6 +382,12 @@ static inline void dst_free(struct dst_entry *dst) __dst_free(dst); } +static inline void dst_rcu_free(struct rcu_head *head) +{ + struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); + dst_free(dst); +} + static inline void dst_confirm(struct dst_entry *dst) { dst->pending_confirm = 1; diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index e3fd34c83ac9..83b567fe1941 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -253,13 +253,9 @@ static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb { struct dst_entry *dst = skb_dst(skb); - if (atomic_inc_not_zero(&dst->__refcnt)) { - if (!(dst->flags & DST_RCU_FREE)) - dst->flags |= DST_RCU_FREE; - - sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; - } + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; } #endif /* _INET_SOCK_H */ diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e69c3a47153d..e521a03515b1 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -81,8 +81,8 @@ struct fib_nh { __be32 nh_gw; __be32 nh_saddr; int nh_saddr_genid; - struct rtable *nh_rth_output; - struct rtable *nh_rth_input; + struct rtable __rcu *nh_rth_output; + struct rtable __rcu *nh_rth_input; struct fnhe_hash_bucket *nh_exceptions; }; diff --git a/net/core/dst.c b/net/core/dst.c index d9e33ebe170f..069d51d29414 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -258,15 +258,6 @@ again: } EXPORT_SYMBOL(dst_destroy); -static void dst_rcu_destroy(struct rcu_head *head) -{ - struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); - - dst = dst_destroy(dst); - if (dst) - __dst_free(dst); -} - void dst_release(struct dst_entry *dst) { if (dst) { @@ -274,14 +265,10 @@ void dst_release(struct dst_entry *dst) newrefcnt = atomic_dec_return(&dst->__refcnt); WARN_ON(newrefcnt < 0); - if (unlikely(dst->flags & (DST_NOCACHE | DST_RCU_FREE)) && !newrefcnt) { - if (dst->flags & DST_RCU_FREE) { - call_rcu_bh(&dst->rcu_head, dst_rcu_destroy); - } else { - dst = dst_destroy(dst); - if (dst) - __dst_free(dst); - } + if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) { + dst = dst_destroy(dst); + if (dst) + __dst_free(dst); } } } @@ -333,14 +320,11 @@ EXPORT_SYMBOL(__dst_destroy_metrics_generic); */ void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst) { - bool hold; - WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held()); /* If dst not in cache, we must take a reference, because * dst_release() will destroy dst as soon as its refcount becomes zero */ - hold = (dst->flags & (DST_NOCACHE | DST_RCU_FREE)) == DST_NOCACHE; - if (unlikely(hold)) { + if (unlikely(dst->flags & DST_NOCACHE)) { dst_hold(dst); skb_dst_set(skb, dst); } else { diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 26719779ad8e..85a3604c87c8 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -184,12 +184,6 @@ static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) return dn_rt_hash_mask & (unsigned int)tmp; } -static inline void dst_rcu_free(struct rcu_head *head) -{ - struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); - dst_free(dst); -} - static inline void dnrt_free(struct dn_route *rt) { call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index e55171f184f9..625cf185c489 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -161,6 +161,21 @@ static void free_nh_exceptions(struct fib_nh *nh) kfree(hash); } +static void rt_nexthop_free(struct rtable __rcu **rtp) +{ + struct rtable *rt = rcu_dereference_protected(*rtp, 1); + + if (!rt) + return; + + /* Not even needed : RCU_INIT_POINTER(*rtp, NULL); + * because we waited an RCU grace period before calling + * free_fib_info_rcu() + */ + + dst_free(&rt->dst); +} + /* Release a nexthop info record */ static void free_fib_info_rcu(struct rcu_head *head) { @@ -171,10 +186,8 @@ static void free_fib_info_rcu(struct rcu_head *head) dev_put(nexthop_nh->nh_dev); if (nexthop_nh->nh_exceptions) free_nh_exceptions(nexthop_nh); - if (nexthop_nh->nh_rth_output) - dst_release(&nexthop_nh->nh_rth_output->dst); - if (nexthop_nh->nh_rth_input) - dst_release(&nexthop_nh->nh_rth_input->dst); + rt_nexthop_free(&nexthop_nh->nh_rth_output); + rt_nexthop_free(&nexthop_nh->nh_rth_input); } endfor_nexthops(fi); release_net(fi->fib_net); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d6eabcfe8a90..2bd107477469 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1199,23 +1199,31 @@ restart: fnhe->fnhe_stamp = jiffies; } +static inline void rt_free(struct rtable *rt) +{ + call_rcu(&rt->dst.rcu_head, dst_rcu_free); +} + static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) { - struct rtable *orig, *prev, **p = &nh->nh_rth_output; + struct rtable *orig, *prev, **p = (struct rtable **)&nh->nh_rth_output; if (rt_is_input_route(rt)) - p = &nh->nh_rth_input; + p = (struct rtable **)&nh->nh_rth_input; orig = *p; - rt->dst.flags |= DST_RCU_FREE; - dst_hold(&rt->dst); prev = cmpxchg(p, orig, rt); if (prev == orig) { if (orig) - dst_release(&orig->dst); + rt_free(orig); } else { - dst_release(&rt->dst); + /* Routes we intend to cache in the FIB nexthop have + * the DST_NOCACHE bit clear. However, if we are + * unsuccessful at storing this route into the cache + * we really need to set it. + */ + rt->dst.flags |= DST_NOCACHE; } } @@ -1412,7 +1420,7 @@ static int __mkroute_input(struct sk_buff *skb, do_cache = false; if (res->fi) { if (!itag) { - rth = FIB_RES_NH(*res).nh_rth_input; + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); if (rt_cache_valid(rth)) { skb_dst_set_noref(skb, &rth->dst); goto out; @@ -1574,7 +1582,7 @@ local_input: do_cache = false; if (res.fi) { if (!itag) { - rth = FIB_RES_NH(res).nh_rth_input; + rth = rcu_dereference(FIB_RES_NH(res).nh_rth_input); if (rt_cache_valid(rth)) { skb_dst_set_noref(skb, &rth->dst); err = 0; @@ -1742,7 +1750,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (fi) { fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); if (!fnhe) { - rth = FIB_RES_NH(*res).nh_rth_output; + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_output); if (rt_cache_valid(rth)) { dst_hold(&rth->dst); return rth; -- GitLab From d26b3a7c4b3b26319f18bb645de93eba8f4bdcd5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Jul 2012 05:45:30 +0000 Subject: [PATCH 4854/5711] ipv4: percpu nh_rth_output cache Input path is mostly run under RCU and doesnt touch dst refcnt But output path on forwarding or UDP workloads hits badly dst refcount, and we have lot of false sharing, for example in ipv4_mtu() when reading rt->rt_pmtu Using a percpu cache for nh_rth_output gives a nice performance increase at a small cost. 24 udpflood test on my 24 cpu machine (dummy0 output device) (each process sends 1.000.000 udp frames, 24 processes are started) before : 5.24 s after : 2.06 s For reference, time on linux-3.5 : 6.60 s Signed-off-by: Eric Dumazet Tested-by: Alexander Duyck Signed-off-by: David S. Miller --- include/net/ip_fib.h | 3 ++- net/ipv4/fib_semantics.c | 20 +++++++++++++++++++- net/ipv4/route.c | 18 +++++++++++++----- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e521a03515b1..e331746029b4 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -21,6 +21,7 @@ #include #include #include +#include struct fib_config { u8 fc_dst_len; @@ -81,7 +82,7 @@ struct fib_nh { __be32 nh_gw; __be32 nh_saddr; int nh_saddr_genid; - struct rtable __rcu *nh_rth_output; + struct rtable __rcu * __percpu *nh_pcpu_rth_output; struct rtable __rcu *nh_rth_input; struct fnhe_hash_bucket *nh_exceptions; }; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 625cf185c489..fe2ca02a1979 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -176,6 +176,23 @@ static void rt_nexthop_free(struct rtable __rcu **rtp) dst_free(&rt->dst); } +static void rt_nexthop_free_cpus(struct rtable __rcu * __percpu *rtp) +{ + int cpu; + + if (!rtp) + return; + + for_each_possible_cpu(cpu) { + struct rtable *rt; + + rt = rcu_dereference_protected(*per_cpu_ptr(rtp, cpu), 1); + if (rt) + dst_free(&rt->dst); + } + free_percpu(rtp); +} + /* Release a nexthop info record */ static void free_fib_info_rcu(struct rcu_head *head) { @@ -186,7 +203,7 @@ static void free_fib_info_rcu(struct rcu_head *head) dev_put(nexthop_nh->nh_dev); if (nexthop_nh->nh_exceptions) free_nh_exceptions(nexthop_nh); - rt_nexthop_free(&nexthop_nh->nh_rth_output); + rt_nexthop_free_cpus(nexthop_nh->nh_pcpu_rth_output); rt_nexthop_free(&nexthop_nh->nh_rth_input); } endfor_nexthops(fi); @@ -817,6 +834,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi->fib_nhs = nhs; change_nexthops(fi) { nexthop_nh->nh_parent = fi; + nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *); } endfor_nexthops(fi) if (cfg->fc_mx) { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2bd107477469..4f6276ce0af3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1206,11 +1206,15 @@ static inline void rt_free(struct rtable *rt) static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) { - struct rtable *orig, *prev, **p = (struct rtable **)&nh->nh_rth_output; + struct rtable *orig, *prev, **p; - if (rt_is_input_route(rt)) + if (rt_is_input_route(rt)) { p = (struct rtable **)&nh->nh_rth_input; - + } else { + if (!nh->nh_pcpu_rth_output) + goto nocache; + p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output); + } orig = *p; prev = cmpxchg(p, orig, rt); @@ -1223,6 +1227,7 @@ static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) * unsuccessful at storing this route into the cache * we really need to set it. */ +nocache: rt->dst.flags |= DST_NOCACHE; } } @@ -1749,8 +1754,11 @@ static struct rtable *__mkroute_output(const struct fib_result *res, fnhe = NULL; if (fi) { fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); - if (!fnhe) { - rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_output); + if (!fnhe && FIB_RES_NH(*res).nh_pcpu_rth_output) { + struct rtable __rcu **prth; + + prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output); + rth = rcu_dereference(*prth); if (rt_cache_valid(rth)) { dst_hold(&rth->dst); return rth; -- GitLab From c5038a8327b980a5b279fa193163c468011de009 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 31 Jul 2012 15:02:02 -0700 Subject: [PATCH 4855/5711] ipv4: Cache routes in nexthop exception entries. Signed-off-by: David S. Miller --- include/net/ip_fib.h | 1 + net/ipv4/fib_semantics.c | 39 ++++++++------- net/ipv4/route.c | 103 ++++++++++++++++++++++----------------- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e331746029b4..926142ed8d7a 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -55,6 +55,7 @@ struct fib_nh_exception { u32 fnhe_pmtu; __be32 fnhe_gw; unsigned long fnhe_expires; + struct rtable __rcu *fnhe_rth; unsigned long fnhe_stamp; }; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index fe2ca02a1979..da80dc14cc76 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -140,6 +140,21 @@ const struct fib_prop fib_props[RTN_MAX + 1] = { }, }; +static void rt_fibinfo_free(struct rtable __rcu **rtp) +{ + struct rtable *rt = rcu_dereference_protected(*rtp, 1); + + if (!rt) + return; + + /* Not even needed : RCU_INIT_POINTER(*rtp, NULL); + * because we waited an RCU grace period before calling + * free_fib_info_rcu() + */ + + dst_free(&rt->dst); +} + static void free_nh_exceptions(struct fib_nh *nh) { struct fnhe_hash_bucket *hash = nh->nh_exceptions; @@ -153,6 +168,9 @@ static void free_nh_exceptions(struct fib_nh *nh) struct fib_nh_exception *next; next = rcu_dereference_protected(fnhe->fnhe_next, 1); + + rt_fibinfo_free(&fnhe->fnhe_rth); + kfree(fnhe); fnhe = next; @@ -161,22 +179,7 @@ static void free_nh_exceptions(struct fib_nh *nh) kfree(hash); } -static void rt_nexthop_free(struct rtable __rcu **rtp) -{ - struct rtable *rt = rcu_dereference_protected(*rtp, 1); - - if (!rt) - return; - - /* Not even needed : RCU_INIT_POINTER(*rtp, NULL); - * because we waited an RCU grace period before calling - * free_fib_info_rcu() - */ - - dst_free(&rt->dst); -} - -static void rt_nexthop_free_cpus(struct rtable __rcu * __percpu *rtp) +static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp) { int cpu; @@ -203,8 +206,8 @@ static void free_fib_info_rcu(struct rcu_head *head) dev_put(nexthop_nh->nh_dev); if (nexthop_nh->nh_exceptions) free_nh_exceptions(nexthop_nh); - rt_nexthop_free_cpus(nexthop_nh->nh_pcpu_rth_output); - rt_nexthop_free(&nexthop_nh->nh_rth_input); + rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output); + rt_fibinfo_free(&nexthop_nh->nh_rth_input); } endfor_nexthops(fi); release_net(fi->fib_net); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4f6276ce0af3..b102eeb16e34 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -587,11 +587,17 @@ static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk, build_sk_flow_key(fl4, sk); } -static DEFINE_SEQLOCK(fnhe_seqlock); +static inline void rt_free(struct rtable *rt) +{ + call_rcu(&rt->dst.rcu_head, dst_rcu_free); +} + +static DEFINE_SPINLOCK(fnhe_lock); static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) { struct fib_nh_exception *fnhe, *oldest; + struct rtable *orig; oldest = rcu_dereference(hash->chain); for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe; @@ -599,6 +605,11 @@ static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) oldest = fnhe; } + orig = rcu_dereference(oldest->fnhe_rth); + if (orig) { + RCU_INIT_POINTER(oldest->fnhe_rth, NULL); + rt_free(orig); + } return oldest; } @@ -620,7 +631,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, int depth; u32 hval = fnhe_hashfun(daddr); - write_seqlock_bh(&fnhe_seqlock); + spin_lock_bh(&fnhe_lock); hash = nh->nh_exceptions; if (!hash) { @@ -667,7 +678,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_stamp = jiffies; out_unlock: - write_sequnlock_bh(&fnhe_seqlock); + spin_unlock_bh(&fnhe_lock); return; } @@ -1167,41 +1178,40 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr) static void rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, __be32 daddr) { - __be32 fnhe_daddr, gw; - unsigned long expires; - unsigned int seq; - u32 pmtu; - -restart: - seq = read_seqbegin(&fnhe_seqlock); - fnhe_daddr = fnhe->fnhe_daddr; - gw = fnhe->fnhe_gw; - pmtu = fnhe->fnhe_pmtu; - expires = fnhe->fnhe_expires; - if (read_seqretry(&fnhe_seqlock, seq)) - goto restart; - - if (daddr != fnhe_daddr) - return; + spin_lock_bh(&fnhe_lock); - if (pmtu) { - unsigned long diff = expires - jiffies; + if (daddr == fnhe->fnhe_daddr) { + struct rtable *orig; - if (time_before(jiffies, expires)) { - rt->rt_pmtu = pmtu; - dst_set_expires(&rt->dst, diff); + if (fnhe->fnhe_pmtu) { + unsigned long expires = fnhe->fnhe_expires; + unsigned long diff = expires - jiffies; + + if (time_before(jiffies, expires)) { + rt->rt_pmtu = fnhe->fnhe_pmtu; + dst_set_expires(&rt->dst, diff); + } + } + if (fnhe->fnhe_gw) { + rt->rt_flags |= RTCF_REDIRECTED; + rt->rt_gateway = fnhe->fnhe_gw; } - } - if (gw) { - rt->rt_flags |= RTCF_REDIRECTED; - rt->rt_gateway = gw; - } - fnhe->fnhe_stamp = jiffies; -} -static inline void rt_free(struct rtable *rt) -{ - call_rcu(&rt->dst.rcu_head, dst_rcu_free); + orig = rcu_dereference(fnhe->fnhe_rth); + rcu_assign_pointer(fnhe->fnhe_rth, rt); + if (orig) + rt_free(orig); + + fnhe->fnhe_stamp = jiffies; + } else { + /* Routes we intend to cache in nexthop exception have + * the DST_NOCACHE bit clear. However, if we are + * unsuccessful at storing this route into the cache + * we really need to set it. + */ + rt->dst.flags |= DST_NOCACHE; + } + spin_unlock_bh(&fnhe_lock); } static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) @@ -1249,13 +1259,13 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) rt->rt_gateway = nh->nh_gw; - if (unlikely(fnhe)) - rt_bind_exception(rt, fnhe, daddr); dst_init_metrics(&rt->dst, fi->fib_metrics, true); #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid; #endif - if (!(rt->dst.flags & DST_NOCACHE)) + if (unlikely(fnhe)) + rt_bind_exception(rt, fnhe, daddr); + else if (!(rt->dst.flags & DST_NOCACHE)) rt_cache_route(nh, rt); } @@ -1753,22 +1763,23 @@ static struct rtable *__mkroute_output(const struct fib_result *res, fnhe = NULL; if (fi) { - fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); - if (!fnhe && FIB_RES_NH(*res).nh_pcpu_rth_output) { - struct rtable __rcu **prth; + struct rtable __rcu **prth; + fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); + if (fnhe) + prth = &fnhe->fnhe_rth; + else prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output); - rth = rcu_dereference(*prth); - if (rt_cache_valid(rth)) { - dst_hold(&rth->dst); - return rth; - } + rth = rcu_dereference(*prth); + if (rt_cache_valid(rth)) { + dst_hold(&rth->dst); + return rth; } } rth = rt_dst_alloc(dev_out, IN_DEV_CONF_GET(in_dev, NOPOLICY), IN_DEV_CONF_GET(in_dev, NOXFRM), - fi && !fnhe); + fi); if (!rth) return ERR_PTR(-ENOBUFS); -- GitLab From caacf05e5ad1abf0a2864863da4e33024bc68ec6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 31 Jul 2012 15:06:50 -0700 Subject: [PATCH 4856/5711] ipv4: Properly purge netdev references on uncached routes. When a device is unregistered, we have to purge all of the references to it that may exist in the entire system. If a route is uncached, we currently have no way of accomplishing this. So create a global list that is scanned when a network device goes down. This mirrors the logic in net/core/dst.c's dst_ifdown(). Signed-off-by: David S. Miller --- include/net/route.h | 3 ++ net/ipv4/fib_frontend.c | 1 + net/ipv4/route.c | 68 ++++++++++++++++++++++++++++++++++++++--- net/ipv4/xfrm4_policy.c | 1 + 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 8c52bc6f1c90..776a27f1ab78 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -57,6 +57,8 @@ struct rtable { /* Miscellaneous cached information */ u32 rt_pmtu; + + struct list_head rt_uncached; }; static inline bool rt_is_input_route(const struct rtable *rt) @@ -107,6 +109,7 @@ extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; extern int ip_rt_init(void); extern void rt_cache_flush(struct net *net, int how); +extern void rt_flush_dev(struct net_device *dev); extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, struct sock *sk); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 8732cc7920ed..c43ae3fba792 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1046,6 +1046,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo if (event == NETDEV_UNREGISTER) { fib_disable_ip(dev, 2, -1); + rt_flush_dev(dev); return NOTIFY_DONE; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b102eeb16e34..c035251beb07 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -147,6 +147,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu); static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb); +static void ipv4_dst_destroy(struct dst_entry *dst); static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, int how) @@ -170,6 +171,7 @@ static struct dst_ops ipv4_dst_ops = { .default_advmss = ipv4_default_advmss, .mtu = ipv4_mtu, .cow_metrics = ipv4_cow_metrics, + .destroy = ipv4_dst_destroy, .ifdown = ipv4_dst_ifdown, .negative_advice = ipv4_negative_advice, .link_failure = ipv4_link_failure, @@ -1175,9 +1177,11 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr) return NULL; } -static void rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, +static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, __be32 daddr) { + bool ret = false; + spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { @@ -1203,6 +1207,7 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, rt_free(orig); fnhe->fnhe_stamp = jiffies; + ret = true; } else { /* Routes we intend to cache in nexthop exception have * the DST_NOCACHE bit clear. However, if we are @@ -1212,11 +1217,14 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, rt->dst.flags |= DST_NOCACHE; } spin_unlock_bh(&fnhe_lock); + + return ret; } -static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) +static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) { struct rtable *orig, *prev, **p; + bool ret = true; if (rt_is_input_route(rt)) { p = (struct rtable **)&nh->nh_rth_input; @@ -1239,6 +1247,48 @@ static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) */ nocache: rt->dst.flags |= DST_NOCACHE; + ret = false; + } + + return ret; +} + +static DEFINE_SPINLOCK(rt_uncached_lock); +static LIST_HEAD(rt_uncached_list); + +static void rt_add_uncached_list(struct rtable *rt) +{ + spin_lock_bh(&rt_uncached_lock); + list_add_tail(&rt->rt_uncached, &rt_uncached_list); + spin_unlock_bh(&rt_uncached_lock); +} + +static void ipv4_dst_destroy(struct dst_entry *dst) +{ + struct rtable *rt = (struct rtable *) dst; + + if (dst->flags & DST_NOCACHE) { + spin_lock_bh(&rt_uncached_lock); + list_del(&rt->rt_uncached); + spin_unlock_bh(&rt_uncached_lock); + } +} + +void rt_flush_dev(struct net_device *dev) +{ + if (!list_empty(&rt_uncached_list)) { + struct net *net = dev_net(dev); + struct rtable *rt; + + spin_lock_bh(&rt_uncached_lock); + list_for_each_entry(rt, &rt_uncached_list, rt_uncached) { + if (rt->dst.dev != dev) + continue; + rt->dst.dev = net->loopback_dev; + dev_hold(rt->dst.dev); + dev_put(dev); + } + spin_unlock_bh(&rt_uncached_lock); } } @@ -1254,6 +1304,8 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, struct fib_nh_exception *fnhe, struct fib_info *fi, u16 type, u32 itag) { + bool cached = false; + if (fi) { struct fib_nh *nh = &FIB_RES_NH(*res); @@ -1264,10 +1316,12 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, rt->dst.tclassid = nh->nh_tclassid; #endif if (unlikely(fnhe)) - rt_bind_exception(rt, fnhe, daddr); + cached = rt_bind_exception(rt, fnhe, daddr); else if (!(rt->dst.flags & DST_NOCACHE)) - rt_cache_route(nh, rt); + cached = rt_cache_route(nh, rt); } + if (unlikely(!cached)) + rt_add_uncached_list(rt); #ifdef CONFIG_IP_ROUTE_CLASSID #ifdef CONFIG_IP_MULTIPLE_TABLES @@ -1334,6 +1388,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + INIT_LIST_HEAD(&rth->rt_uncached); if (our) { rth->dst.input= ip_local_deliver; rth->rt_flags |= RTCF_LOCAL; @@ -1459,6 +1514,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + INIT_LIST_HEAD(&rth->rt_uncached); rth->dst.input = ip_forward; rth->dst.output = ip_output; @@ -1625,6 +1681,7 @@ local_input: rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + INIT_LIST_HEAD(&rth->rt_uncached); if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; rth->dst.error= -err; @@ -1792,6 +1849,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_iif = orig_oif ? : 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + INIT_LIST_HEAD(&rth->rt_uncached); RT_CACHE_STAT_INC(out_slow_tot); @@ -2071,6 +2129,8 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_type = ort->rt_type; rt->rt_gateway = ort->rt_gateway; + INIT_LIST_HEAD(&rt->rt_uncached); + dst_free(new); } diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index c6281847f16a..681ea2f413e2 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -92,6 +92,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.rt.rt_type = rt->rt_type; xdst->u.rt.rt_gateway = rt->rt_gateway; xdst->u.rt.rt_pmtu = rt->rt_pmtu; + INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); return 0; } -- GitLab From d6b09e754c23b657544f6e7f39fbf7de24c58aa2 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 31 Jul 2012 16:41:31 -0700 Subject: [PATCH 4857/5711] fault-injection: fix failcmd.sh warning "fault-injection: add tool to run command with failslab or fail_page_alloc" added tools/testing/fault-injection/failcmd.sh to make it easier to inject slab/page allocation failures by fault injection. failcmd.sh prints the following warning when running with arguments for command. # ./failcmd.sh echo aaa failcmd.sh: line 209: [: echo: binary operator expected aaa This warning is caused by an improper check whether at least one parameter is left after parsing command options. Fix it by testing the length of $1 instead of $@ Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/testing/fault-injection/failcmd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/fault-injection/failcmd.sh b/tools/testing/fault-injection/failcmd.sh index 1776e924b202..78a9ed7fecdb 100644 --- a/tools/testing/fault-injection/failcmd.sh +++ b/tools/testing/fault-injection/failcmd.sh @@ -206,7 +206,7 @@ while true; do esac done -[ -z "$@" ] && exit 0 +[ -z "$1" ] && exit 0 echo $oom_kill_allocating_task > /proc/sys/vm/oom_kill_allocating_task echo $task_filter > $FAULTATTR/task-filter -- GitLab From c66af411189fdae3bcb301fae830f078fc205fca Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 31 Jul 2012 16:41:33 -0700 Subject: [PATCH 4858/5711] xtensa: select generic atomic64_t support This will fix build errors: block/blk-cgroup.c:609:2: error: unknown type name 'atomic64_t' block/blk-cgroup.c:609:2: error: implicit declaration of function 'ATOMIC64_INIT' [-Werror=implicit-function-declaration] Signed-off-by: Fengguang Wu Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8a3f8351f438..8ed64cfae4ff 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -7,6 +7,7 @@ config ZONE_DMA config XTENSA def_bool y select HAVE_IDE + select GENERIC_ATOMIC64 select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES -- GitLab From c2cddf991974a00aa7b40a21e829bc034b8199b6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 31 Jul 2012 16:41:34 -0700 Subject: [PATCH 4859/5711] drivers/media/video/v4l2-ioctl.c: fix build Fix zillions of these: drivers/media/video/v4l2-ioctl.c:1848: error: unknown field 'func' specified in initializer drivers/media/video/v4l2-ioctl.c:1848: warning: missing braces around initializer drivers/media/video/v4l2-ioctl.c:1848: warning: (near initialization for 'v4l2_ioctls[0].') drivers/media/video/v4l2-ioctl.c:1848: warning: initialization makes integer from pointer without a cast drivers/media/video/v4l2-ioctl.c:1848: error: initializer element is not computable at load time drivers/media/video/v4l2-ioctl.c:1848: error: (near initialization for 'v4l2_ioctls[0]..offset') Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/v4l2-ioctl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 70e0efb127a6..4b4059d64272 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1831,7 +1831,9 @@ struct v4l2_ioctl_info { .ioctl = _ioctl, \ .flags = _flags | INFO_FL_STD, \ .name = #_ioctl, \ - .offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ + { \ + .offset = offsetof(struct v4l2_ioctl_ops, _vidioc),\ + }, \ .debug = _debug, \ } @@ -1840,7 +1842,9 @@ struct v4l2_ioctl_info { .ioctl = _ioctl, \ .flags = _flags | INFO_FL_FUNC, \ .name = #_ioctl, \ - .func = _func, \ + { \ + .func = _func, \ + }, \ .debug = _debug, \ } -- GitLab From 92ca922f0a19145f2dcc99d84fe656fa55b52c2e Mon Sep 17 00:00:00 2001 From: Hong zhi guo Date: Tue, 31 Jul 2012 16:41:35 -0700 Subject: [PATCH 4860/5711] vmalloc: walk vmap_areas by sorted list instead of rb_next() There's a walk by repeating rb_next to find a suitable hole. Could be simply replaced by walk on the sorted vmap_area_list. More simpler and efficient. Mutation of the list and tree only happens in pair within __insert_vmap_area and __free_vmap_area, under protection of vmap_area_lock. The patch code is also under vmap_area_lock, so the list walk is safe, and consistent with the tree walk. Tested on SMP by repeating batch of vmalloc anf vfree for random sizes and rounds for hours. Signed-off-by: Hong Zhiguo Cc: Nick Piggin Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e03f4c7307a5..7e25ee3ce6e5 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -413,11 +413,11 @@ nocache: if (addr + size - 1 < addr) goto overflow; - n = rb_next(&first->rb_node); - if (n) - first = rb_entry(n, struct vmap_area, rb_node); - else + if (list_is_last(&first->list, &vmap_area_list)) goto found; + + first = list_entry(first->list.next, + struct vmap_area, list); } found: -- GitLab From aa91c4d898c062804f4d0a5da6d8ab013cd0e868 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 31 Jul 2012 16:41:37 -0700 Subject: [PATCH 4861/5711] mm: make vb_alloc() more foolproof If someone calls vb_alloc() (or vm_map_ram() for that matter) to allocate 0 bytes (0 pages), get_order() returns BITS_PER_LONG - PAGE_CACHE_SHIFT and interesting stuff happens. So make debugging such problems easier and warn about 0-size allocation. [akpm@linux-foundation.org: use WARN_ON-return-value feature] Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 7e25ee3ce6e5..2bb90b1d241c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -904,6 +904,14 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask) BUG_ON(size & ~PAGE_MASK); BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC); + if (WARN_ON(size == 0)) { + /* + * Allocating 0 bytes isn't what caller wants since + * get_order(0) returns funny result. Just warn and terminate + * early. + */ + return NULL; + } order = get_order(size); again: -- GitLab From bff6bb83f38105b39b0cc3a9ad81103edbb56f7a Mon Sep 17 00:00:00 2001 From: Kamezawa Hiroyuki Date: Tue, 31 Jul 2012 16:41:38 -0700 Subject: [PATCH 4862/5711] memcg: rename MEM_CGROUP_STAT_SWAPOUT as MEM_CGROUP_STAT_SWAP MEM_CGROUP_STAT_SWAPOUT represents the usage of swap rather than the number of swap-out events. Rename it to be MEM_CGROUP_STAT_SWAP. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Acked-by: Hugh Dickins Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index f72b5e52451a..91ce7b2ee1e4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -87,7 +87,7 @@ enum mem_cgroup_stat_index { MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ - MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */ + MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */ MEM_CGROUP_STAT_NSTATS, }; @@ -703,7 +703,7 @@ static void mem_cgroup_swap_statistics(struct mem_cgroup *memcg, bool charge) { int val = (charge) ? 1 : -1; - this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_SWAPOUT], val); + this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_SWAP], val); } static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg, @@ -3831,7 +3831,7 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS); if (swap) - val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_SWAPOUT); + val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_SWAP); return val << PAGE_SHIFT; } @@ -4082,7 +4082,7 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, unsigned int i; for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) { - if (i == MEM_CGROUP_STAT_SWAPOUT && !do_swap_account) + if (i == MEM_CGROUP_STAT_SWAP && !do_swap_account) continue; seq_printf(m, "%s %ld\n", mem_cgroup_stat_names[i], mem_cgroup_read_stat(memcg, i) * PAGE_SIZE); @@ -4109,7 +4109,7 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) { long long val = 0; - if (i == MEM_CGROUP_STAT_SWAPOUT && !do_swap_account) + if (i == MEM_CGROUP_STAT_SWAP && !do_swap_account) continue; for_each_mem_cgroup_tree(mi, memcg) val += mem_cgroup_read_stat(mi, i) * PAGE_SIZE; -- GitLab From 41326c17fc1b45289a82567553249f60d3638a23 Mon Sep 17 00:00:00 2001 From: Kamezawa Hiroyuki Date: Tue, 31 Jul 2012 16:41:40 -0700 Subject: [PATCH 4863/5711] memcg: rename MEM_CGROUP_CHARGE_TYPE_MAPPED as MEM_CGROUP_CHARGE_TYPE_ANON Now, in memcg, 2 "MAPPED" enum/macro are found MEM_CGROUP_CHARGE_TYPE_MAPPED MEM_CGROUP_STAT_FILE_MAPPED Thier names looks similar to each other but the former is used for accounting anonymous memory. rename it as TYPE_ANON. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 91ce7b2ee1e4..1b3dd27ead6d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -378,7 +378,7 @@ static bool move_file(void) enum charge_type { MEM_CGROUP_CHARGE_TYPE_CACHE = 0, - MEM_CGROUP_CHARGE_TYPE_MAPPED, + MEM_CGROUP_CHARGE_TYPE_ANON, MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ @@ -2519,7 +2519,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, spin_unlock_irq(&zone->lru_lock); } - if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED) + if (ctype == MEM_CGROUP_CHARGE_TYPE_ANON) anon = true; else anon = false; @@ -2728,7 +2728,7 @@ int mem_cgroup_newpage_charge(struct page *page, VM_BUG_ON(page->mapping && !PageAnon(page)); VM_BUG_ON(!mm); return mem_cgroup_charge_common(page, mm, gfp_mask, - MEM_CGROUP_CHARGE_TYPE_MAPPED); + MEM_CGROUP_CHARGE_TYPE_ANON); } static void @@ -2842,7 +2842,7 @@ void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg) { __mem_cgroup_commit_charge_swapin(page, memcg, - MEM_CGROUP_CHARGE_TYPE_MAPPED); + MEM_CGROUP_CHARGE_TYPE_ANON); } void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) @@ -2945,7 +2945,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) anon = PageAnon(page); switch (ctype) { - case MEM_CGROUP_CHARGE_TYPE_MAPPED: + case MEM_CGROUP_CHARGE_TYPE_ANON: /* * Generally PageAnon tells if it's the anon statistics to be * updated; but sometimes e.g. mem_cgroup_uncharge_page() is @@ -3005,7 +3005,7 @@ void mem_cgroup_uncharge_page(struct page *page) if (page_mapped(page)) return; VM_BUG_ON(page->mapping && !PageAnon(page)); - __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED); + __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON); } void mem_cgroup_uncharge_cache_page(struct page *page) @@ -3248,7 +3248,7 @@ int mem_cgroup_prepare_migration(struct page *page, * mapcount will be finally 0 and we call uncharge in end_migration(). */ if (PageAnon(page)) - ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED; + ctype = MEM_CGROUP_CHARGE_TYPE_ANON; else if (page_is_file_cache(page)) ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; else @@ -3287,7 +3287,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg, unlock_page_cgroup(pc); anon = PageAnon(used); __mem_cgroup_uncharge_common(unused, - anon ? MEM_CGROUP_CHARGE_TYPE_MAPPED + anon ? MEM_CGROUP_CHARGE_TYPE_ANON : MEM_CGROUP_CHARGE_TYPE_CACHE); /* -- GitLab From a7d6f529fe1d96a477614eb93f40213d133029e6 Mon Sep 17 00:00:00 2001 From: Kamezawa Hiroyuki Date: Tue, 31 Jul 2012 16:41:41 -0700 Subject: [PATCH 4864/5711] memcg: remove MEM_CGROUP_CHARGE_TYPE_FORCE There are no users since commit b24028572fb69 ("memcg: remove PCG_CACHE"). Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Hugh Dickins Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1b3dd27ead6d..1940ba8e6f00 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -380,7 +380,6 @@ enum charge_type { MEM_CGROUP_CHARGE_TYPE_CACHE = 0, MEM_CGROUP_CHARGE_TYPE_ANON, MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ - MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ MEM_CGROUP_CHARGE_TYPE_DROP, /* a page was unused swap cache */ NR_CHARGE_TYPE, -- GitLab From 3fb5c298b04eb6e472f8db1f0fb472749d30041c Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Tue, 31 Jul 2012 16:41:44 -0700 Subject: [PATCH 4865/5711] swap: allow swap readahead to be merged Swap readahead works fine, but the I/O to disk is almost always done in page size requests, despite the fact that readahead submits 1< Acked-by: Rik van Riel Acked-by: Jens Axboe Reviewed-by: Minchan Kim Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swap_state.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/swap_state.c b/mm/swap_state.c index 4c5ff7f284d9..c85b5590cccd 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,7 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask, unsigned long offset = swp_offset(entry); unsigned long start_offset, end_offset; unsigned long mask = (1UL << page_cluster) - 1; + struct blk_plug plug; /* Read a page_cluster sized and aligned cluster around offset. */ start_offset = offset & ~mask; @@ -383,6 +385,7 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask, if (!start_offset) /* First page is swap header. */ start_offset++; + blk_start_plug(&plug); for (offset = start_offset; offset <= end_offset ; offset++) { /* Ok, do the async read-ahead now */ page = read_swap_cache_async(swp_entry(swp_type(entry), offset), @@ -391,6 +394,8 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask, continue; page_cache_release(page); } + blk_finish_plug(&plug); + lru_add_drain(); /* Push any new pages onto the LRU now */ return read_swap_cache_async(entry, gfp_mask, vma, addr); } -- GitLab From df858fa8276f85106f2f5c3cd49c1fa524058070 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Tue, 31 Jul 2012 16:41:46 -0700 Subject: [PATCH 4866/5711] documentation: update how page-cluster affects swap I/O Fix of the documentation of /proc/sys/vm/page-cluster to match the behavior of the code and add some comments about what the tunable will change in that behavior. Signed-off-by: Christian Ehrhardt Acked-by: Jens Axboe Reviewed-by: Minchan Kim Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysctl/vm.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 96f0ee825bed..84eb25cd69aa 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -574,16 +574,24 @@ of physical RAM. See above. page-cluster -page-cluster controls the number of pages which are written to swap in -a single attempt. The swap I/O size. +page-cluster controls the number of pages up to which consecutive pages +are read in from swap in a single attempt. This is the swap counterpart +to page cache readahead. +The mentioned consecutivity is not in terms of virtual/physical addresses, +but consecutive on swap space - that means they were swapped out together. It is a logarithmic value - setting it to zero means "1 page", setting it to 1 means "2 pages", setting it to 2 means "4 pages", etc. +Zero disables swap readahead completely. The default value is three (eight pages at a time). There may be some small benefits in tuning this to a different value if your workload is swap-intensive. +Lower values mean lower latencies for initial faults, but at the same time +extra faults and I/O delays for following faults if they would have been part of +that consecutive pages readahead would have brought in. + ============================================================= panic_on_oom -- GitLab From 44de9d0cad41f2c51ef26916842be046b582dcc9 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Tue, 31 Jul 2012 16:41:49 -0700 Subject: [PATCH 4867/5711] mm: account the total_vm in the vm_stat_account() vm_stat_account() accounts the shared_vm, stack_vm and reserved_vm now. But we can also account for total_vm in the vm_stat_account() which makes the code tidy. Even for mprotect_fixup(), we can get the right result in the end. Signed-off-by: Huang Shijie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/perfmon.c | 1 - include/linux/mm.h | 1 + kernel/fork.c | 4 +--- mm/mmap.c | 5 ++--- mm/mremap.c | 2 -- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index d7f558c1e711..3fa4bc536953 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2353,7 +2353,6 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t */ insert_vm_struct(mm, vma); - mm->total_vm += size >> PAGE_SHIFT; vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, vma_pages(vma)); up_write(&task->mm->mmap_sem); diff --git a/include/linux/mm.h b/include/linux/mm.h index f9f279cf5b1b..3955bedeeed1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1528,6 +1528,7 @@ void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); static inline void vm_stat_account(struct mm_struct *mm, unsigned long flags, struct file *file, long pages) { + mm->total_vm += pages; } #endif /* CONFIG_PROC_FS */ diff --git a/kernel/fork.c b/kernel/fork.c index 8efac1fe56bc..aaa8813c45d1 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -381,10 +381,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) struct file *file; if (mpnt->vm_flags & VM_DONTCOPY) { - long pages = vma_pages(mpnt); - mm->total_vm -= pages; vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file, - -pages); + -vma_pages(mpnt)); continue; } charge = 0; diff --git a/mm/mmap.c b/mm/mmap.c index 3edfcdfa42d9..1ee2fd8bc486 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -943,6 +943,8 @@ void vm_stat_account(struct mm_struct *mm, unsigned long flags, const unsigned long stack_flags = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN); + mm->total_vm += pages; + if (file) { mm->shared_vm += pages; if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC) @@ -1347,7 +1349,6 @@ munmap_back: out: perf_event_mmap(vma); - mm->total_vm += len >> PAGE_SHIFT; vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT); if (vm_flags & VM_LOCKED) { if (!mlock_vma_pages_range(vma, addr, addr + len)) @@ -1707,7 +1708,6 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns return -ENOMEM; /* Ok, everything looks good - let it rip */ - mm->total_vm += grow; if (vma->vm_flags & VM_LOCKED) mm->locked_vm += grow; vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow); @@ -1889,7 +1889,6 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) if (vma->vm_flags & VM_ACCOUNT) nr_accounted += nrpages; - mm->total_vm -= nrpages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); vma = remove_vma(vma); } while (vma); diff --git a/mm/mremap.c b/mm/mremap.c index 21fed202ddad..cc06d0e48d05 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -260,7 +260,6 @@ static unsigned long move_vma(struct vm_area_struct *vma, * If this were a serious issue, we'd add a flag to do_munmap(). */ hiwater_vm = mm->hiwater_vm; - mm->total_vm += new_len >> PAGE_SHIFT; vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT); if (do_munmap(mm, old_addr, old_len) < 0) { @@ -497,7 +496,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, goto out; } - mm->total_vm += pages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages); if (vma->vm_flags & VM_LOCKED) { mm->locked_vm += pages; -- GitLab From deaf386ee58d5336bbef8959bf304573afb67c20 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 31 Jul 2012 16:41:51 -0700 Subject: [PATCH 4868/5711] mm/buddy: cleanup on should_fail_alloc_page Currently, function should_fail() has "bool" for its return value, so it's reasonable to change the return value of function should_fail_alloc_page() into "bool" as well. The patch does cleanup on function should_fail_alloc_page() to have "bool" for its return value. Signed-off-by: Gavin Shan Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4a4f9219683f..80ef99234b89 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1529,16 +1529,16 @@ static int __init setup_fail_page_alloc(char *str) } __setup("fail_page_alloc=", setup_fail_page_alloc); -static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) +static bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) { if (order < fail_page_alloc.min_order) - return 0; + return false; if (gfp_mask & __GFP_NOFAIL) - return 0; + return false; if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM)) - return 0; + return false; if (fail_page_alloc.ignore_gfp_wait && (gfp_mask & __GFP_WAIT)) - return 0; + return false; return should_fail(&fail_page_alloc.attr, 1 << order); } @@ -1578,9 +1578,9 @@ late_initcall(fail_page_alloc_debugfs); #else /* CONFIG_FAIL_PAGE_ALLOC */ -static inline int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) +static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) { - return 0; + return false; } #endif /* CONFIG_FAIL_PAGE_ALLOC */ -- GitLab From 3965c9ae47d64aadf6f13b6fcd37767b83c0689a Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:41:52 -0700 Subject: [PATCH 4869/5711] mm: prepare for removal of obsolete /proc/sys/vm/nr_pdflush_threads Since per-BDI flusher threads were introduced in 2.6, the pdflush mechanism is not used any more. But the old interface exported through /proc/sys/vm/nr_pdflush_threads still exists and is obviously useless. For back-compatibility, printk warning information and return 2 to notify the users that the interface is removed. Signed-off-by: Wanpeng Li Cc: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../obsolete/proc-sys-vm-nr_pdflush_threads | 5 +++++ Documentation/feature-removal-schedule.txt | 8 ++++++++ Documentation/sysctl/vm.txt | 11 ---------- fs/fs-writeback.c | 5 ----- include/linux/backing-dev.h | 3 +++ include/linux/writeback.h | 5 ----- kernel/sysctl.c | 8 +++----- kernel/sysctl_binary.c | 2 +- mm/backing-dev.c | 20 +++++++++++++++++++ 9 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 Documentation/ABI/obsolete/proc-sys-vm-nr_pdflush_threads diff --git a/Documentation/ABI/obsolete/proc-sys-vm-nr_pdflush_threads b/Documentation/ABI/obsolete/proc-sys-vm-nr_pdflush_threads new file mode 100644 index 000000000000..b0b0eeb20fe3 --- /dev/null +++ b/Documentation/ABI/obsolete/proc-sys-vm-nr_pdflush_threads @@ -0,0 +1,5 @@ +What: /proc/sys/vm/nr_pdflush_threads +Date: June 2012 +Contact: Wanpeng Li +Description: Since pdflush is replaced by per-BDI flusher, the interface of old pdflush + exported in /proc/sys/vm/ should be removed. diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index e9237fb71950..88f2fa48bb63 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -13,6 +13,14 @@ Who: Jim Cromie , Jason Baron --------------------------- +What: /proc/sys/vm/nr_pdflush_threads +When: 2012 +Why: Since pdflush is deprecated, the interface exported in /proc/sys/vm/ + should be removed. +Who: Wanpeng Li + +--------------------------- + What: CONFIG_APM_CPU_IDLE, and its ability to call APM BIOS in idle When: 2012 Why: This optional sub-feature of APM is of dubious reliability, diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 84eb25cd69aa..06d662b1c5d5 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -42,7 +42,6 @@ Currently, these files are in /proc/sys/vm: - mmap_min_addr - nr_hugepages - nr_overcommit_hugepages -- nr_pdflush_threads - nr_trim_pages (only if CONFIG_MMU=n) - numa_zonelist_order - oom_dump_tasks @@ -426,16 +425,6 @@ See Documentation/vm/hugetlbpage.txt ============================================================== -nr_pdflush_threads - -The current number of pdflush threads. This value is read-only. -The value changes according to the number of dirty pages in the system. - -When necessary, additional pdflush threads are created, one per second, up to -nr_pdflush_threads_max. - -============================================================== - nr_trim_pages This is available only on NOMMU kernels. diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 50d0b78130a1..be3efc4f64f4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -52,11 +52,6 @@ struct wb_writeback_work { struct completion *done; /* set if the caller waits */ }; -/* - * We don't actually have pdflush, but this one is exported though /proc... - */ -int nr_pdflush_threads; - /** * writeback_in_progress - determine whether there is writeback in progress * @bdi: the device's backing_dev_info structure. diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 489de625cd25..c97c6b9cd38e 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -17,6 +17,7 @@ #include #include #include +#include struct page; struct device; @@ -304,6 +305,8 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int sync); void set_bdi_congested(struct backing_dev_info *bdi, int sync); long congestion_wait(int sync, long timeout); long wait_iff_congested(struct zone *zone, int sync, long timeout); +int pdflush_proc_obsolete(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) { diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 6d0a0fcd80e7..c66fe3332d83 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -189,9 +189,4 @@ void tag_pages_for_writeback(struct address_space *mapping, void account_page_redirty(struct page *page); -/* pdflush.c */ -extern int nr_pdflush_threads; /* Global so it can be exported to sysctl - read-only. */ - - #endif /* WRITEBACK_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 97186b99b0e4..6502d35a25ba 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1101,11 +1101,9 @@ static struct ctl_table vm_table[] = { .extra1 = &zero, }, { - .procname = "nr_pdflush_threads", - .data = &nr_pdflush_threads, - .maxlen = sizeof nr_pdflush_threads, - .mode = 0444 /* read-only*/, - .proc_handler = proc_dointvec, + .procname = "nr_pdflush_threads", + .mode = 0444 /* read-only */, + .proc_handler = pdflush_proc_obsolete, }, { .procname = "swappiness", diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index a650694883a1..65bdcf198d4e 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c @@ -147,7 +147,7 @@ static const struct bin_table bin_vm_table[] = { { CTL_INT, VM_DIRTY_RATIO, "dirty_ratio" }, /* VM_DIRTY_WB_CS "dirty_writeback_centisecs" no longer used */ /* VM_DIRTY_EXPIRE_CS "dirty_expire_centisecs" no longer used */ - { CTL_INT, VM_NR_PDFLUSH_THREADS, "nr_pdflush_threads" }, + /* VM_NR_PDFLUSH_THREADS "nr_pdflush_threads" no longer used */ { CTL_INT, VM_OVERCOMMIT_RATIO, "overcommit_ratio" }, /* VM_PAGEBUF unused */ /* VM_HUGETLB_PAGES "nr_hugepages" no longer used */ diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 3387aea11209..6b4718e2ee34 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -886,3 +886,23 @@ out: return ret; } EXPORT_SYMBOL(wait_iff_congested); + +int pdflush_proc_obsolete(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + char kbuf[] = "0\n"; + + if (*ppos) { + *lenp = 0; + return 0; + } + + if (copy_to_user(buffer, kbuf, sizeof(kbuf))) + return -EFAULT; + printk_once(KERN_WARNING "%s exported in /proc is scheduled for removal\n", + table->procname); + + *lenp = 2; + *ppos += *lenp; + return 2; +} -- GitLab From 47d38344abd0c7c6793b59ac741aa5b205fc197c Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:41:54 -0700 Subject: [PATCH 4870/5711] hugetlb: rename max_hstate to hugetlb_max_hstate This patchset implements a cgroup resource controller for HugeTLB pages. The controller allows to limit the HugeTLB usage per control group and enforces the controller limit during page fault. Since HugeTLB doesn't support page reclaim, enforcing the limit at page fault time implies that, the application will get SIGBUS signal if it tries to access HugeTLB pages beyond its limit. This requires the application to know beforehand how much HugeTLB pages it would require for its use. The goal is to control how many HugeTLB pages a group of task can allocate. It can be looked at as an extension of the existing quota interface which limits the number of HugeTLB pages per hugetlbfs superblock. HPC job scheduler requires jobs to specify their resource requirements in the job file. Once their requirements can be met, job schedulers like (SLURM) will schedule the job. We need to make sure that the jobs won't consume more resources than requested. If they do we should either error out or kill the application. This patch: Rename max_hstate to hugetlb_max_hstate. We will be using this from other subsystems like hugetlb controller in later patches. Signed-off-by: Aneesh Kumar K.V Acked-by: David Rientjes Reviewed-by: KAMEZAWA Hiroyuki Acked-by: Hillf Danton Acked-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index e198831276a3..c86830931cc6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -34,7 +34,7 @@ const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; static gfp_t htlb_alloc_mask = GFP_HIGHUSER; unsigned long hugepages_treat_as_movable; -static int max_hstate; +static int hugetlb_max_hstate; unsigned int default_hstate_idx; struct hstate hstates[HUGE_MAX_HSTATE]; @@ -46,7 +46,7 @@ static unsigned long __initdata default_hstate_max_huge_pages; static unsigned long __initdata default_hstate_size; #define for_each_hstate(h) \ - for ((h) = hstates; (h) < &hstates[max_hstate]; (h)++) + for ((h) = hstates; (h) < &hstates[hugetlb_max_hstate]; (h)++) /* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages @@ -1897,9 +1897,9 @@ void __init hugetlb_add_hstate(unsigned order) printk(KERN_WARNING "hugepagesz= specified twice, ignoring\n"); return; } - BUG_ON(max_hstate >= HUGE_MAX_HSTATE); + BUG_ON(hugetlb_max_hstate >= HUGE_MAX_HSTATE); BUG_ON(order == 0); - h = &hstates[max_hstate++]; + h = &hstates[hugetlb_max_hstate++]; h->order = order; h->mask = ~((1ULL << (order + PAGE_SHIFT)) - 1); h->nr_huge_pages = 0; @@ -1920,10 +1920,10 @@ static int __init hugetlb_nrpages_setup(char *s) static unsigned long *last_mhp; /* - * !max_hstate means we haven't parsed a hugepagesz= parameter yet, + * !hugetlb_max_hstate means we haven't parsed a hugepagesz= parameter yet, * so this hugepages= parameter goes to the "default hstate". */ - if (!max_hstate) + if (!hugetlb_max_hstate) mhp = &default_hstate_max_huge_pages; else mhp = &parsed_hstate->max_huge_pages; @@ -1942,7 +1942,7 @@ static int __init hugetlb_nrpages_setup(char *s) * But we need to allocate >= MAX_ORDER hstates here early to still * use the bootmem allocator. */ - if (max_hstate && parsed_hstate->order >= MAX_ORDER) + if (hugetlb_max_hstate && parsed_hstate->order >= MAX_ORDER) hugetlb_hstate_alloc_pages(parsed_hstate); last_mhp = mhp; -- GitLab From 76dcee75c1aff61259f5ed55e2bcfab60cc4bd5f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:41:57 -0700 Subject: [PATCH 4871/5711] hugetlb: don't use ERR_PTR with VM_FAULT* values The current use of VM_FAULT_* codes with ERR_PTR requires us to ensure VM_FAULT_* values will not exceed MAX_ERRNO value. Decouple the VM_FAULT_* values from MAX_ERRNO. Signed-off-by: Aneesh Kumar K.V Acked-by: Hillf Danton Acked-by: KOSAKI Motohiro Reviewed-by: KAMEZAWA Hiroyuki Cc: David Rientjes Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c86830931cc6..34a7e2375478 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1123,10 +1123,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, */ chg = vma_needs_reservation(h, vma, addr); if (chg < 0) - return ERR_PTR(-VM_FAULT_OOM); + return ERR_PTR(-ENOMEM); if (chg) if (hugepage_subpool_get_pages(spool, chg)) - return ERR_PTR(-VM_FAULT_SIGBUS); + return ERR_PTR(-ENOSPC); spin_lock(&hugetlb_lock); page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve); @@ -1136,7 +1136,7 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, page = alloc_buddy_huge_page(h, NUMA_NO_NODE); if (!page) { hugepage_subpool_put_pages(spool, chg); - return ERR_PTR(-VM_FAULT_SIGBUS); + return ERR_PTR(-ENOSPC); } } @@ -2496,6 +2496,7 @@ retry_avoidcopy: new_page = alloc_huge_page(vma, address, outside_reserve); if (IS_ERR(new_page)) { + long err = PTR_ERR(new_page); page_cache_release(old_page); /* @@ -2524,7 +2525,10 @@ retry_avoidcopy: /* Caller expects lock to be held */ spin_lock(&mm->page_table_lock); - return -PTR_ERR(new_page); + if (err == -ENOMEM) + return VM_FAULT_OOM; + else + return VM_FAULT_SIGBUS; } /* @@ -2642,7 +2646,11 @@ retry: goto out; page = alloc_huge_page(vma, address, 0); if (IS_ERR(page)) { - ret = -PTR_ERR(page); + ret = PTR_ERR(page); + if (ret == -ENOMEM) + ret = VM_FAULT_OOM; + else + ret = VM_FAULT_SIGBUS; goto out; } clear_huge_page(page, address, pages_per_huge_page(h)); -- GitLab From 972dc4de13f667a7df27ee32573b2e6fc6cc8434 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:00 -0700 Subject: [PATCH 4872/5711] hugetlb: add an inline helper for finding hstate index Add an inline helper and use it in the code. Signed-off-by: Aneesh Kumar K.V Acked-by: David Rientjes Acked-by: Michal Hocko Reviewed-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 6 ++++++ mm/hugetlb.c | 20 +++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index d5d6bbe2259e..217f52859fa7 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -302,6 +302,11 @@ static inline unsigned hstate_index_to_shift(unsigned index) return hstates[index].order + PAGE_SHIFT; } +static inline int hstate_index(struct hstate *h) +{ + return h - hstates; +} + #else struct hstate {}; #define alloc_huge_page_node(h, nid) NULL @@ -320,6 +325,7 @@ static inline unsigned int pages_per_huge_page(struct hstate *h) return 1; } #define hstate_index_to_shift(index) 0 +#define hstate_index(h) 0 #endif #endif /* _LINUX_HUGETLB_H */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 34a7e2375478..b1e0ed1ea912 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1646,7 +1646,7 @@ static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent, struct attribute_group *hstate_attr_group) { int retval; - int hi = h - hstates; + int hi = hstate_index(h); hstate_kobjs[hi] = kobject_create_and_add(h->name, parent); if (!hstate_kobjs[hi]) @@ -1741,11 +1741,13 @@ void hugetlb_unregister_node(struct node *node) if (!nhs->hugepages_kobj) return; /* no hstate attributes */ - for_each_hstate(h) - if (nhs->hstate_kobjs[h - hstates]) { - kobject_put(nhs->hstate_kobjs[h - hstates]); - nhs->hstate_kobjs[h - hstates] = NULL; + for_each_hstate(h) { + int idx = hstate_index(h); + if (nhs->hstate_kobjs[idx]) { + kobject_put(nhs->hstate_kobjs[idx]); + nhs->hstate_kobjs[idx] = NULL; } + } kobject_put(nhs->hugepages_kobj); nhs->hugepages_kobj = NULL; @@ -1848,7 +1850,7 @@ static void __exit hugetlb_exit(void) hugetlb_unregister_all_nodes(); for_each_hstate(h) { - kobject_put(hstate_kobjs[h - hstates]); + kobject_put(hstate_kobjs[hstate_index(h)]); } kobject_put(hugepages_kobj); @@ -1869,7 +1871,7 @@ static int __init hugetlb_init(void) if (!size_to_hstate(default_hstate_size)) hugetlb_add_hstate(HUGETLB_PAGE_ORDER); } - default_hstate_idx = size_to_hstate(default_hstate_size) - hstates; + default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size)); if (default_hstate_max_huge_pages) default_hstate.max_huge_pages = default_hstate_max_huge_pages; @@ -2687,7 +2689,7 @@ retry: */ if (unlikely(PageHWPoison(page))) { ret = VM_FAULT_HWPOISON | - VM_FAULT_SET_HINDEX(h - hstates); + VM_FAULT_SET_HINDEX(hstate_index(h)); goto backout_unlocked; } } @@ -2760,7 +2762,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, return 0; } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) return VM_FAULT_HWPOISON_LARGE | - VM_FAULT_SET_HINDEX(h - hstates); + VM_FAULT_SET_HINDEX(hstate_index(h)); } ptep = huge_pte_alloc(mm, address, huge_page_size(h)); -- GitLab From 24669e58477e2752c1fbca9c1c988e9dd0d79d15 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:03 -0700 Subject: [PATCH 4873/5711] hugetlb: use mmu_gather instead of a temporary linked list for accumulating pages Use a mmu_gather instead of a temporary linked list for accumulating pages when we unmap a hugepage range Signed-off-by: Aneesh Kumar K.V Reviewed-by: KAMEZAWA Hiroyuki Cc: David Rientjes Cc: Hillf Danton Cc: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hugetlbfs/inode.c | 4 +-- include/linux/hugetlb.h | 22 +++++++++++---- mm/hugetlb.c | 59 ++++++++++++++++++++++++----------------- mm/memory.c | 7 +++-- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index e13e9bdb0bf5..8349a899912e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -416,8 +416,8 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff) else v_offset = 0; - __unmap_hugepage_range(vma, - vma->vm_start + v_offset, vma->vm_end, NULL); + unmap_hugepage_range(vma, vma->vm_start + v_offset, + vma->vm_end, NULL); } } diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 217f52859fa7..0f23c1840c9b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -7,6 +7,7 @@ struct ctl_table; struct user_struct; +struct mmu_gather; #ifdef CONFIG_HUGETLB_PAGE @@ -40,9 +41,10 @@ int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, unsigned int flags); void unmap_hugepage_range(struct vm_area_struct *, - unsigned long, unsigned long, struct page *); -void __unmap_hugepage_range(struct vm_area_struct *, - unsigned long, unsigned long, struct page *); + unsigned long, unsigned long, struct page *); +void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct page *ref_page); int hugetlb_prefault(struct address_space *, struct vm_area_struct *); void hugetlb_report_meminfo(struct seq_file *); int hugetlb_report_node_meminfo(int, char *); @@ -98,7 +100,6 @@ static inline unsigned long hugetlb_total_pages(void) #define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL) #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; }) #define hugetlb_prefault(mapping, vma) ({ BUG(); 0; }) -#define unmap_hugepage_range(vma, start, end, page) BUG() static inline void hugetlb_report_meminfo(struct seq_file *m) { } @@ -112,13 +113,24 @@ static inline void hugetlb_report_meminfo(struct seq_file *m) #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) #define hugetlb_fault(mm, vma, addr, flags) ({ BUG(); 0; }) #define huge_pte_offset(mm, address) 0 -#define dequeue_hwpoisoned_huge_page(page) 0 +static inline int dequeue_hwpoisoned_huge_page(struct page *page) +{ + return 0; +} + static inline void copy_huge_page(struct page *dst, struct page *src) { } #define hugetlb_change_protection(vma, address, end, newprot) +static inline void __unmap_hugepage_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long start, + unsigned long end, struct page *ref_page) +{ + BUG(); +} + #endif /* !CONFIG_HUGETLB_PAGE */ #define HUGETLB_ANON_FILE "anon_hugepage" diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b1e0ed1ea912..e54b695336f9 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -24,8 +24,9 @@ #include #include -#include +#include +#include #include #include #include "internal.h" @@ -2310,30 +2311,26 @@ static int is_hugetlb_entry_hwpoisoned(pte_t pte) return 0; } -void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end, struct page *ref_page) +void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct page *ref_page) { + int force_flush = 0; struct mm_struct *mm = vma->vm_mm; unsigned long address; pte_t *ptep; pte_t pte; struct page *page; - struct page *tmp; struct hstate *h = hstate_vma(vma); unsigned long sz = huge_page_size(h); - /* - * A page gathering list, protected by per file i_mmap_mutex. The - * lock is used to avoid list corruption from multiple unmapping - * of the same page since we are using page->lru. - */ - LIST_HEAD(page_list); - WARN_ON(!is_vm_hugetlb_page(vma)); BUG_ON(start & ~huge_page_mask(h)); BUG_ON(end & ~huge_page_mask(h)); + tlb_start_vma(tlb, vma); mmu_notifier_invalidate_range_start(mm, start, end); +again: spin_lock(&mm->page_table_lock); for (address = start; address < end; address += sz) { ptep = huge_pte_offset(mm, address); @@ -2372,30 +2369,45 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, } pte = huge_ptep_get_and_clear(mm, address, ptep); + tlb_remove_tlb_entry(tlb, ptep, address); if (pte_dirty(pte)) set_page_dirty(page); - list_add(&page->lru, &page_list); + page_remove_rmap(page); + force_flush = !__tlb_remove_page(tlb, page); + if (force_flush) + break; /* Bail out after unmapping reference page if supplied */ if (ref_page) break; } - flush_tlb_range(vma, start, end); spin_unlock(&mm->page_table_lock); - mmu_notifier_invalidate_range_end(mm, start, end); - list_for_each_entry_safe(page, tmp, &page_list, lru) { - page_remove_rmap(page); - list_del(&page->lru); - put_page(page); + /* + * mmu_gather ran out of room to batch pages, we break out of + * the PTE lock to avoid doing the potential expensive TLB invalidate + * and page-free while holding it. + */ + if (force_flush) { + force_flush = 0; + tlb_flush_mmu(tlb); + if (address < end && !ref_page) + goto again; } + mmu_notifier_invalidate_range_end(mm, start, end); + tlb_end_vma(tlb, vma); } void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, struct page *ref_page) { - mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex); - __unmap_hugepage_range(vma, start, end, ref_page); - mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); + struct mm_struct *mm; + struct mmu_gather tlb; + + mm = vma->vm_mm; + + tlb_gather_mmu(&tlb, mm, 0); + __unmap_hugepage_range(&tlb, vma, start, end, ref_page); + tlb_finish_mmu(&tlb, start, end); } /* @@ -2440,9 +2452,8 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, * from the time of fork. This would look like data corruption */ if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER)) - __unmap_hugepage_range(iter_vma, - address, address + huge_page_size(h), - page); + unmap_hugepage_range(iter_vma, address, + address + huge_page_size(h), page); } mutex_unlock(&mapping->i_mmap_mutex); diff --git a/mm/memory.c b/mm/memory.c index 91f69459d3e8..59e5bebc2e35 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1343,8 +1343,11 @@ static void unmap_single_vma(struct mmu_gather *tlb, * Since no pte has actually been setup, it is * safe to do nothing in this case. */ - if (vma->vm_file) - unmap_hugepage_range(vma, start, end, NULL); + if (vma->vm_file) { + mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex); + __unmap_hugepage_range(tlb, vma, start, end, NULL); + mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); + } } else unmap_page_range(tlb, vma, start, end, details); } -- GitLab From 189ebff2894a9d0f4e250dd1e154d282ef0a6779 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:06 -0700 Subject: [PATCH 4874/5711] hugetlb: simplify migrate_huge_page() Since we migrate only one hugepage, don't use linked list for passing the page around. Directly pass the page that need to be migrated as argument. This also removes the usage of page->lru in the migrate path. Signed-off-by: Aneesh Kumar K.V Reviewed-by: KAMEZAWA Hiroyuki Cc: David Rientjes Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/migrate.h | 4 +-- mm/memory-failure.c | 15 +++------- mm/migrate.c | 65 +++++++++++++---------------------------- 3 files changed, 27 insertions(+), 57 deletions(-) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 855c337b20c3..ce7e6671968b 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -15,7 +15,7 @@ extern int migrate_page(struct address_space *, extern int migrate_pages(struct list_head *l, new_page_t x, unsigned long private, bool offlining, enum migrate_mode mode); -extern int migrate_huge_pages(struct list_head *l, new_page_t x, +extern int migrate_huge_page(struct page *, new_page_t x, unsigned long private, bool offlining, enum migrate_mode mode); @@ -36,7 +36,7 @@ static inline void putback_lru_pages(struct list_head *l) {} static inline int migrate_pages(struct list_head *l, new_page_t x, unsigned long private, bool offlining, enum migrate_mode mode) { return -ENOSYS; } -static inline int migrate_huge_pages(struct list_head *l, new_page_t x, +static inline int migrate_huge_page(struct page *page, new_page_t x, unsigned long private, bool offlining, enum migrate_mode mode) { return -ENOSYS; } diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 6de0d613bbe6..b04ff2d6f73d 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1416,7 +1416,6 @@ static int soft_offline_huge_page(struct page *page, int flags) int ret; unsigned long pfn = page_to_pfn(page); struct page *hpage = compound_head(page); - LIST_HEAD(pagelist); ret = get_any_page(page, pfn, flags); if (ret < 0) @@ -1431,24 +1430,18 @@ static int soft_offline_huge_page(struct page *page, int flags) } /* Keep page count to indicate a given hugepage is isolated. */ - - list_add(&hpage->lru, &pagelist); - ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false, + ret = migrate_huge_page(hpage, new_page, MPOL_MF_MOVE_ALL, false, MIGRATE_SYNC); + put_page(hpage); if (ret) { - struct page *page1, *page2; - list_for_each_entry_safe(page1, page2, &pagelist, lru) - put_page(page1); - pr_info("soft offline: %#lx: migration failed %d, type %lx\n", pfn, ret, page->flags); - if (ret > 0) - ret = -EIO; return ret; } done: if (!PageHWPoison(hpage)) - atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages); + atomic_long_add(1 << compound_trans_order(hpage), + &mce_bad_pages); set_page_hwpoison_huge_page(hpage); dequeue_hwpoisoned_huge_page(hpage); /* keep elevated page count for bad page */ diff --git a/mm/migrate.c b/mm/migrate.c index be26d5cbe56b..fdce3a29fc4c 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -932,15 +932,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (anon_vma) put_anon_vma(anon_vma); unlock_page(hpage); - out: - if (rc != -EAGAIN) { - list_del(&hpage->lru); - put_page(hpage); - } - put_page(new_hpage); - if (result) { if (rc) *result = rc; @@ -1016,48 +1009,32 @@ out: return nr_failed + retry; } -int migrate_huge_pages(struct list_head *from, - new_page_t get_new_page, unsigned long private, bool offlining, - enum migrate_mode mode) +int migrate_huge_page(struct page *hpage, new_page_t get_new_page, + unsigned long private, bool offlining, + enum migrate_mode mode) { - int retry = 1; - int nr_failed = 0; - int pass = 0; - struct page *page; - struct page *page2; - int rc; - - for (pass = 0; pass < 10 && retry; pass++) { - retry = 0; - - list_for_each_entry_safe(page, page2, from, lru) { + int pass, rc; + + for (pass = 0; pass < 10; pass++) { + rc = unmap_and_move_huge_page(get_new_page, + private, hpage, pass > 2, offlining, + mode); + switch (rc) { + case -ENOMEM: + goto out; + case -EAGAIN: + /* try again */ cond_resched(); - - rc = unmap_and_move_huge_page(get_new_page, - private, page, pass > 2, offlining, - mode); - - switch(rc) { - case -ENOMEM: - goto out; - case -EAGAIN: - retry++; - break; - case 0: - break; - default: - /* Permanent failure */ - nr_failed++; - break; - } + break; + case 0: + goto out; + default: + rc = -EIO; + goto out; } } - rc = 0; out: - if (rc) - return rc; - - return nr_failed + retry; + return rc; } #ifdef CONFIG_NUMA -- GitLab From 0edaecfab218d747d30de4575e911907371e2cd2 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:07 -0700 Subject: [PATCH 4875/5711] hugetlb: add a list for tracking in-use HugeTLB pages hugepage_activelist will be used to track currently used HugeTLB pages. We need to find the in-use HugeTLB pages to support HugeTLB cgroup removal. On cgroup removal we update the page's HugeTLB cgroup to point to parent cgroup. Signed-off-by: Aneesh Kumar K.V Reviewed-by: KAMEZAWA Hiroyuki Cc: David Rientjes Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 1 + mm/hugetlb.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 0f23c1840c9b..ed550d819044 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -211,6 +211,7 @@ struct hstate { unsigned long resv_huge_pages; unsigned long surplus_huge_pages; unsigned long nr_overcommit_huge_pages; + struct list_head hugepage_activelist; struct list_head hugepage_freelists[MAX_NUMNODES]; unsigned int nr_huge_pages_node[MAX_NUMNODES]; unsigned int free_huge_pages_node[MAX_NUMNODES]; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index e54b695336f9..b5b6e156ca76 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -510,7 +510,7 @@ void copy_huge_page(struct page *dst, struct page *src) static void enqueue_huge_page(struct hstate *h, struct page *page) { int nid = page_to_nid(page); - list_add(&page->lru, &h->hugepage_freelists[nid]); + list_move(&page->lru, &h->hugepage_freelists[nid]); h->free_huge_pages++; h->free_huge_pages_node[nid]++; } @@ -522,7 +522,7 @@ static struct page *dequeue_huge_page_node(struct hstate *h, int nid) if (list_empty(&h->hugepage_freelists[nid])) return NULL; page = list_entry(h->hugepage_freelists[nid].next, struct page, lru); - list_del(&page->lru); + list_move(&page->lru, &h->hugepage_activelist); set_page_refcounted(page); h->free_huge_pages--; h->free_huge_pages_node[nid]--; @@ -626,10 +626,11 @@ static void free_huge_page(struct page *page) page->mapping = NULL; BUG_ON(page_count(page)); BUG_ON(page_mapcount(page)); - INIT_LIST_HEAD(&page->lru); spin_lock(&hugetlb_lock); if (h->surplus_huge_pages_node[nid] && huge_page_order(h) < MAX_ORDER) { + /* remove the page from active list */ + list_del(&page->lru); update_and_free_page(h, page); h->surplus_huge_pages--; h->surplus_huge_pages_node[nid]--; @@ -642,6 +643,7 @@ static void free_huge_page(struct page *page) static void prep_new_huge_page(struct hstate *h, struct page *page, int nid) { + INIT_LIST_HEAD(&page->lru); set_compound_page_dtor(page, free_huge_page); spin_lock(&hugetlb_lock); h->nr_huge_pages++; @@ -890,6 +892,7 @@ static struct page *alloc_buddy_huge_page(struct hstate *h, int nid) spin_lock(&hugetlb_lock); if (page) { + INIT_LIST_HEAD(&page->lru); r_nid = page_to_nid(page); set_compound_page_dtor(page, free_huge_page); /* @@ -994,7 +997,6 @@ retry: list_for_each_entry_safe(page, tmp, &surplus_list, lru) { if ((--needed) < 0) break; - list_del(&page->lru); /* * This page is now managed by the hugetlb allocator and has * no users -- drop the buddy allocator's reference. @@ -1009,7 +1011,6 @@ free: /* Free unnecessary surplus pages to the buddy allocator */ if (!list_empty(&surplus_list)) { list_for_each_entry_safe(page, tmp, &surplus_list, lru) { - list_del(&page->lru); put_page(page); } } @@ -1909,6 +1910,7 @@ void __init hugetlb_add_hstate(unsigned order) h->free_huge_pages = 0; for (i = 0; i < MAX_NUMNODES; ++i) INIT_LIST_HEAD(&h->hugepage_freelists[i]); + INIT_LIST_HEAD(&h->hugepage_activelist); h->next_nid_to_alloc = first_node(node_states[N_HIGH_MEMORY]); h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]); snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", -- GitLab From c3f38a38715e9b4e7b1dda6840a1375f6894744d Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:10 -0700 Subject: [PATCH 4876/5711] hugetlb: make some static variables global We will use them later in hugetlb_cgroup.c Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 5 +++++ mm/hugetlb.c | 7 ++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index ed550d819044..3d677dd41898 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -21,6 +21,11 @@ struct hugepage_subpool { long max_hpages, used_hpages; }; +extern spinlock_t hugetlb_lock; +extern int hugetlb_max_hstate __read_mostly; +#define for_each_hstate(h) \ + for ((h) = hstates; (h) < &hstates[hugetlb_max_hstate]; (h)++) + struct hugepage_subpool *hugepage_new_subpool(long nr_blocks); void hugepage_put_subpool(struct hugepage_subpool *spool); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b5b6e156ca76..d5971597736b 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -35,7 +35,7 @@ const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; static gfp_t htlb_alloc_mask = GFP_HIGHUSER; unsigned long hugepages_treat_as_movable; -static int hugetlb_max_hstate; +int hugetlb_max_hstate __read_mostly; unsigned int default_hstate_idx; struct hstate hstates[HUGE_MAX_HSTATE]; @@ -46,13 +46,10 @@ static struct hstate * __initdata parsed_hstate; static unsigned long __initdata default_hstate_max_huge_pages; static unsigned long __initdata default_hstate_size; -#define for_each_hstate(h) \ - for ((h) = hstates; (h) < &hstates[hugetlb_max_hstate]; (h)++) - /* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages */ -static DEFINE_SPINLOCK(hugetlb_lock); +DEFINE_SPINLOCK(hugetlb_lock); static inline void unlock_or_release_subpool(struct hugepage_subpool *spool) { -- GitLab From 2bc64a2046975410505bb119bba32705892b9255 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:12 -0700 Subject: [PATCH 4877/5711] mm/hugetlb: add new HugeTLB cgroup Implement a new controller that allows us to control HugeTLB allocations. The extension allows to limit the HugeTLB usage per control group and enforces the controller limit during page fault. Since HugeTLB doesn't support page reclaim, enforcing the limit at page fault time implies that, the application will get SIGBUS signal if it tries to access HugeTLB pages beyond its limit. This requires the application to know beforehand how much HugeTLB pages it would require for its use. The charge/uncharge calls will be added to HugeTLB code in later patch. Support for cgroup removal will be added in later patches. [akpm@linux-foundation.org: s/CONFIG_CGROUP_HUGETLB_RES_CTLR/CONFIG_MEMCG_HUGETLB/g] [akpm@linux-foundation.org: s/CONFIG_MEMCG_HUGETLB/CONFIG_CGROUP_HUGETLB/g] Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/cgroup_subsys.h | 6 ++ include/linux/hugetlb_cgroup.h | 37 ++++++++++ init/Kconfig | 15 +++++ mm/Makefile | 1 + mm/hugetlb_cgroup.c | 120 +++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+) create mode 100644 include/linux/hugetlb_cgroup.h create mode 100644 mm/hugetlb_cgroup.c diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 0bd390ce98b2..5b41ce079024 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -72,3 +72,9 @@ SUBSYS(net_prio) #endif /* */ + +#ifdef CONFIG_CGROUP_HUGETLB +SUBSYS(hugetlb) +#endif + +/* */ diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h new file mode 100644 index 000000000000..f19889e56b47 --- /dev/null +++ b/include/linux/hugetlb_cgroup.h @@ -0,0 +1,37 @@ +/* + * Copyright IBM Corporation, 2012 + * Author Aneesh Kumar K.V + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_HUGETLB_CGROUP_H +#define _LINUX_HUGETLB_CGROUP_H + +#include + +struct hugetlb_cgroup; + +#ifdef CONFIG_CGROUP_HUGETLB +static inline bool hugetlb_cgroup_disabled(void) +{ + if (hugetlb_subsys.disabled) + return true; + return false; +} + +#else +static inline bool hugetlb_cgroup_disabled(void) +{ + return true; +} + +#endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ +#endif diff --git a/init/Kconfig b/init/Kconfig index b3f55f15e107..72437760e90e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -751,6 +751,21 @@ config CGROUP_MEM_RES_CTLR_KMEM the kmem extension can use it to guarantee that no group of processes will ever exhaust kernel resources alone. +config CGROUP_HUGETLB + bool "HugeTLB Resource Controller for Control Groups" + depends on RESOURCE_COUNTERS && HUGETLB_PAGE && EXPERIMENTAL + default n + help + Provides a cgroup Resource Controller for HugeTLB pages. + When you enable this, you can put a per cgroup limit on HugeTLB usage. + The limit is enforced during page fault. Since HugeTLB doesn't + support page reclaim, enforcing the limit at page fault time implies + that, the application will get SIGBUS signal if it tries to access + HugeTLB pages beyond its limit. This requires the application to know + beforehand how much HugeTLB pages it would require for its use. The + control group is tracked in the third page lru pointer. This means + that we cannot use the controller with huge page less than 3 pages. + config CGROUP_PERF bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" depends on PERF_EVENTS && CGROUPS diff --git a/mm/Makefile b/mm/Makefile index 8e81fe263c94..fd6fc1c1966c 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o +obj-$(CONFIG_CGROUP_HUGETLB) += hugetlb_cgroup.o obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c new file mode 100644 index 000000000000..0d1a66e9039b --- /dev/null +++ b/mm/hugetlb_cgroup.c @@ -0,0 +1,120 @@ +/* + * + * Copyright IBM Corporation, 2012 + * Author Aneesh Kumar K.V + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include +#include +#include +#include + +struct hugetlb_cgroup { + struct cgroup_subsys_state css; + /* + * the counter to account for hugepages from hugetlb. + */ + struct res_counter hugepage[HUGE_MAX_HSTATE]; +}; + +struct cgroup_subsys hugetlb_subsys __read_mostly; +static struct hugetlb_cgroup *root_h_cgroup __read_mostly; + +static inline +struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s) +{ + return container_of(s, struct hugetlb_cgroup, css); +} + +static inline +struct hugetlb_cgroup *hugetlb_cgroup_from_cgroup(struct cgroup *cgroup) +{ + return hugetlb_cgroup_from_css(cgroup_subsys_state(cgroup, + hugetlb_subsys_id)); +} + +static inline +struct hugetlb_cgroup *hugetlb_cgroup_from_task(struct task_struct *task) +{ + return hugetlb_cgroup_from_css(task_subsys_state(task, + hugetlb_subsys_id)); +} + +static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg) +{ + return (h_cg == root_h_cgroup); +} + +static inline struct hugetlb_cgroup *parent_hugetlb_cgroup(struct cgroup *cg) +{ + if (!cg->parent) + return NULL; + return hugetlb_cgroup_from_cgroup(cg->parent); +} + +static inline bool hugetlb_cgroup_have_usage(struct cgroup *cg) +{ + int idx; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cg); + + for (idx = 0; idx < hugetlb_max_hstate; idx++) { + if ((res_counter_read_u64(&h_cg->hugepage[idx], RES_USAGE)) > 0) + return true; + } + return false; +} + +static struct cgroup_subsys_state *hugetlb_cgroup_create(struct cgroup *cgroup) +{ + int idx; + struct cgroup *parent_cgroup; + struct hugetlb_cgroup *h_cgroup, *parent_h_cgroup; + + h_cgroup = kzalloc(sizeof(*h_cgroup), GFP_KERNEL); + if (!h_cgroup) + return ERR_PTR(-ENOMEM); + + parent_cgroup = cgroup->parent; + if (parent_cgroup) { + parent_h_cgroup = hugetlb_cgroup_from_cgroup(parent_cgroup); + for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) + res_counter_init(&h_cgroup->hugepage[idx], + &parent_h_cgroup->hugepage[idx]); + } else { + root_h_cgroup = h_cgroup; + for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) + res_counter_init(&h_cgroup->hugepage[idx], NULL); + } + return &h_cgroup->css; +} + +static void hugetlb_cgroup_destroy(struct cgroup *cgroup) +{ + struct hugetlb_cgroup *h_cgroup; + + h_cgroup = hugetlb_cgroup_from_cgroup(cgroup); + kfree(h_cgroup); +} + +static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup) +{ + /* We will add the cgroup removal support in later patches */ + return -EBUSY; +} + +struct cgroup_subsys hugetlb_subsys = { + .name = "hugetlb", + .create = hugetlb_cgroup_create, + .pre_destroy = hugetlb_cgroup_pre_destroy, + .destroy = hugetlb_cgroup_destroy, + .subsys_id = hugetlb_subsys_id, +}; -- GitLab From 9dd540e23111d8884773ab942a736f3aba4040d4 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:15 -0700 Subject: [PATCH 4878/5711] hugetlb/cgroup: add the cgroup pointer to page lru Add the hugetlb cgroup pointer to 3rd page lru.next. This limit the usage to hugetlb cgroup to only hugepages with 3 or more normal pages. I guess that is an acceptable limitation. Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb_cgroup.h | 37 ++++++++++++++++++++++++++++++++++ mm/hugetlb.c | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h index f19889e56b47..e5451a3b4ebc 100644 --- a/include/linux/hugetlb_cgroup.h +++ b/include/linux/hugetlb_cgroup.h @@ -18,8 +18,34 @@ #include struct hugetlb_cgroup; +/* + * Minimum page order trackable by hugetlb cgroup. + * At least 3 pages are necessary for all the tracking information. + */ +#define HUGETLB_CGROUP_MIN_ORDER 2 #ifdef CONFIG_CGROUP_HUGETLB + +static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) +{ + VM_BUG_ON(!PageHuge(page)); + + if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) + return NULL; + return (struct hugetlb_cgroup *)page[2].lru.next; +} + +static inline +int set_hugetlb_cgroup(struct page *page, struct hugetlb_cgroup *h_cg) +{ + VM_BUG_ON(!PageHuge(page)); + + if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) + return -1; + page[2].lru.next = (void *)h_cg; + return 0; +} + static inline bool hugetlb_cgroup_disabled(void) { if (hugetlb_subsys.disabled) @@ -28,6 +54,17 @@ static inline bool hugetlb_cgroup_disabled(void) } #else +static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) +{ + return NULL; +} + +static inline +int set_hugetlb_cgroup(struct page *page, struct hugetlb_cgroup *h_cg) +{ + return 0; +} + static inline bool hugetlb_cgroup_disabled(void) { return true; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index d5971597736b..efe29b53daff 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "internal.h" @@ -591,6 +592,7 @@ static void update_and_free_page(struct hstate *h, struct page *page) 1 << PG_active | 1 << PG_reserved | 1 << PG_private | 1 << PG_writeback); } + VM_BUG_ON(hugetlb_cgroup_from_page(page)); set_compound_page_dtor(page, NULL); set_page_refcounted(page); arch_release_hugepage(page); @@ -643,6 +645,7 @@ static void prep_new_huge_page(struct hstate *h, struct page *page, int nid) INIT_LIST_HEAD(&page->lru); set_compound_page_dtor(page, free_huge_page); spin_lock(&hugetlb_lock); + set_hugetlb_cgroup(page, NULL); h->nr_huge_pages++; h->nr_huge_pages_node[nid]++; spin_unlock(&hugetlb_lock); @@ -892,6 +895,7 @@ static struct page *alloc_buddy_huge_page(struct hstate *h, int nid) INIT_LIST_HEAD(&page->lru); r_nid = page_to_nid(page); set_compound_page_dtor(page, free_huge_page); + set_hugetlb_cgroup(page, NULL); /* * We incremented the global counters already */ -- GitLab From 6d76dcf40405144a448040a350fd214ddc243d5e Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:18 -0700 Subject: [PATCH 4879/5711] hugetlb/cgroup: add charge/uncharge routines for hugetlb cgroup Add the charge and uncharge routines for hugetlb cgroup. We do cgroup charging in page alloc and uncharge in compound page destructor. Assigning page's hugetlb cgroup is protected by hugetlb_lock. [liwp@linux.vnet.ibm.com: add huge_page_order check to avoid incorrect uncharge] Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Cc: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Aneesh Kumar K.V Signed-off-by: Wanpeng Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb_cgroup.h | 38 ++++++++++++++++ mm/hugetlb.c | 16 ++++++- mm/hugetlb_cgroup.c | 80 ++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h index e5451a3b4ebc..7d3fde996be3 100644 --- a/include/linux/hugetlb_cgroup.h +++ b/include/linux/hugetlb_cgroup.h @@ -53,6 +53,16 @@ static inline bool hugetlb_cgroup_disabled(void) return false; } +extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup **ptr); +extern void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg, + struct page *page); +extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, + struct page *page); +extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg); + #else static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) { @@ -70,5 +80,33 @@ static inline bool hugetlb_cgroup_disabled(void) return true; } +static inline int +hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup **ptr) +{ + return 0; +} + +static inline void +hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg, + struct page *page) +{ + return; +} + +static inline void +hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, struct page *page) +{ + return; +} + +static inline void +hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg) +{ + return; +} + #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ #endif diff --git a/mm/hugetlb.c b/mm/hugetlb.c index efe29b53daff..16a0f32c4820 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -627,6 +627,8 @@ static void free_huge_page(struct page *page) BUG_ON(page_mapcount(page)); spin_lock(&hugetlb_lock); + hugetlb_cgroup_uncharge_page(hstate_index(h), + pages_per_huge_page(h), page); if (h->surplus_huge_pages_node[nid] && huge_page_order(h) < MAX_ORDER) { /* remove the page from active list */ list_del(&page->lru); @@ -1115,7 +1117,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, struct hstate *h = hstate_vma(vma); struct page *page; long chg; + int ret, idx; + struct hugetlb_cgroup *h_cg; + idx = hstate_index(h); /* * Processes that did not create the mapping will have no * reserves and will not have accounted against subpool @@ -1131,6 +1136,11 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, if (hugepage_subpool_get_pages(spool, chg)) return ERR_PTR(-ENOSPC); + ret = hugetlb_cgroup_charge_cgroup(idx, pages_per_huge_page(h), &h_cg); + if (ret) { + hugepage_subpool_put_pages(spool, chg); + return ERR_PTR(-ENOSPC); + } spin_lock(&hugetlb_lock); page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve); spin_unlock(&hugetlb_lock); @@ -1138,6 +1148,9 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, if (!page) { page = alloc_buddy_huge_page(h, NUMA_NO_NODE); if (!page) { + hugetlb_cgroup_uncharge_cgroup(idx, + pages_per_huge_page(h), + h_cg); hugepage_subpool_put_pages(spool, chg); return ERR_PTR(-ENOSPC); } @@ -1146,7 +1159,8 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, set_page_private(page, (unsigned long)spool); vma_commit_reservation(h, vma, addr); - + /* update page cgroup details */ + hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h), h_cg, page); return page; } diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 0d1a66e9039b..63e04cfa437d 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -111,6 +111,86 @@ static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup) return -EBUSY; } +int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup **ptr) +{ + int ret = 0; + struct res_counter *fail_res; + struct hugetlb_cgroup *h_cg = NULL; + unsigned long csize = nr_pages * PAGE_SIZE; + + if (hugetlb_cgroup_disabled()) + goto done; + /* + * We don't charge any cgroup if the compound page have less + * than 3 pages. + */ + if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER) + goto done; +again: + rcu_read_lock(); + h_cg = hugetlb_cgroup_from_task(current); + if (!css_tryget(&h_cg->css)) { + rcu_read_unlock(); + goto again; + } + rcu_read_unlock(); + + ret = res_counter_charge(&h_cg->hugepage[idx], csize, &fail_res); + css_put(&h_cg->css); +done: + *ptr = h_cg; + return ret; +} + +void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg, + struct page *page) +{ + if (hugetlb_cgroup_disabled() || !h_cg) + return; + + spin_lock(&hugetlb_lock); + set_hugetlb_cgroup(page, h_cg); + spin_unlock(&hugetlb_lock); + return; +} + +/* + * Should be called with hugetlb_lock held + */ +void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, + struct page *page) +{ + struct hugetlb_cgroup *h_cg; + unsigned long csize = nr_pages * PAGE_SIZE; + + if (hugetlb_cgroup_disabled()) + return; + VM_BUG_ON(!spin_is_locked(&hugetlb_lock)); + h_cg = hugetlb_cgroup_from_page(page); + if (unlikely(!h_cg)) + return; + set_hugetlb_cgroup(page, NULL); + res_counter_uncharge(&h_cg->hugepage[idx], csize); + return; +} + +void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, + struct hugetlb_cgroup *h_cg) +{ + unsigned long csize = nr_pages * PAGE_SIZE; + + if (hugetlb_cgroup_disabled() || !h_cg) + return; + + if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER) + return; + + res_counter_uncharge(&h_cg->hugepage[idx], csize); + return; +} + struct cgroup_subsys hugetlb_subsys = { .name = "hugetlb", .create = hugetlb_cgroup_create, -- GitLab From da1def55919f4852c4759249a78d63a0c5d2d8f9 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:21 -0700 Subject: [PATCH 4880/5711] hugetlb/cgroup: add support for cgroup removal Add support for cgroup removal. If we don't have parent cgroup, the charges are moved to root cgroup. Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb_cgroup.c | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 63e04cfa437d..bc518bedea98 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -105,10 +105,76 @@ static void hugetlb_cgroup_destroy(struct cgroup *cgroup) kfree(h_cgroup); } + +/* + * Should be called with hugetlb_lock held. + * Since we are holding hugetlb_lock, pages cannot get moved from + * active list or uncharged from the cgroup, So no need to get + * page reference and test for page active here. This function + * cannot fail. + */ +static void hugetlb_cgroup_move_parent(int idx, struct cgroup *cgroup, + struct page *page) +{ + int csize; + struct res_counter *counter; + struct res_counter *fail_res; + struct hugetlb_cgroup *page_hcg; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cgroup); + struct hugetlb_cgroup *parent = parent_hugetlb_cgroup(cgroup); + + page_hcg = hugetlb_cgroup_from_page(page); + /* + * We can have pages in active list without any cgroup + * ie, hugepage with less than 3 pages. We can safely + * ignore those pages. + */ + if (!page_hcg || page_hcg != h_cg) + goto out; + + csize = PAGE_SIZE << compound_order(page); + if (!parent) { + parent = root_h_cgroup; + /* root has no limit */ + res_counter_charge_nofail(&parent->hugepage[idx], + csize, &fail_res); + } + counter = &h_cg->hugepage[idx]; + res_counter_uncharge_until(counter, counter->parent, csize); + + set_hugetlb_cgroup(page, parent); +out: + return; +} + +/* + * Force the hugetlb cgroup to empty the hugetlb resources by moving them to + * the parent cgroup. + */ static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup) { - /* We will add the cgroup removal support in later patches */ - return -EBUSY; + struct hstate *h; + struct page *page; + int ret = 0, idx = 0; + + do { + if (cgroup_task_count(cgroup) || + !list_empty(&cgroup->children)) { + ret = -EBUSY; + goto out; + } + for_each_hstate(h) { + spin_lock(&hugetlb_lock); + list_for_each_entry(page, &h->hugepage_activelist, lru) + hugetlb_cgroup_move_parent(idx, cgroup, page); + + spin_unlock(&hugetlb_lock); + idx++; + } + cond_resched(); + } while (hugetlb_cgroup_have_usage(cgroup)); +out: + return ret; } int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, -- GitLab From abb8206cb07734d0b7bf033c715995d6371a94c3 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:24 -0700 Subject: [PATCH 4881/5711] hugetlb/cgroup: add hugetlb cgroup control files Add the control files for hugetlb controller [akpm@linux-foundation.org: s/CONFIG_CGROUP_HUGETLB_RES_CTLR/CONFIG_MEMCG_HUGETLB/g] [akpm@linux-foundation.org: s/CONFIG_MEMCG_HUGETLB/CONFIG_CGROUP_HUGETLB/] Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 5 ++ include/linux/hugetlb_cgroup.h | 6 ++ mm/hugetlb.c | 8 ++ mm/hugetlb_cgroup.c | 129 +++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 3d677dd41898..f9db20bfa9fc 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -4,6 +4,7 @@ #include #include #include +#include struct ctl_table; struct user_struct; @@ -221,6 +222,10 @@ struct hstate { unsigned int nr_huge_pages_node[MAX_NUMNODES]; unsigned int free_huge_pages_node[MAX_NUMNODES]; unsigned int surplus_huge_pages_node[MAX_NUMNODES]; +#ifdef CONFIG_CGROUP_HUGETLB + /* cgroup control files */ + struct cftype cgroup_files[5]; +#endif char name[HSTATE_NAME_LEN]; }; diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h index 7d3fde996be3..73f1e600fc12 100644 --- a/include/linux/hugetlb_cgroup.h +++ b/include/linux/hugetlb_cgroup.h @@ -62,6 +62,7 @@ extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, struct page *page); extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, struct hugetlb_cgroup *h_cg); +extern int hugetlb_cgroup_file_init(int idx) __init; #else static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) @@ -108,5 +109,10 @@ hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, return; } +static inline int __init hugetlb_cgroup_file_init(int idx) +{ + return 0; +} + #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ #endif diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 16a0f32c4820..c57740bb203a 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; @@ -1930,6 +1931,13 @@ void __init hugetlb_add_hstate(unsigned order) h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]); snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", huge_page_size(h)/1024); + /* + * Add cgroup control files only if the huge page consists + * of more than two normal pages. This is because we use + * page[2].lru.next for storing cgoup details. + */ + if (order >= HUGETLB_CGROUP_MIN_ORDER) + hugetlb_cgroup_file_init(hugetlb_max_hstate - 1); parsed_hstate = h; } diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index bc518bedea98..d1ca1196e62f 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -26,6 +26,10 @@ struct hugetlb_cgroup { struct res_counter hugepage[HUGE_MAX_HSTATE]; }; +#define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) +#define MEMFILE_IDX(val) (((val) >> 16) & 0xffff) +#define MEMFILE_ATTR(val) ((val) & 0xffff) + struct cgroup_subsys hugetlb_subsys __read_mostly; static struct hugetlb_cgroup *root_h_cgroup __read_mostly; @@ -257,6 +261,131 @@ void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, return; } +static ssize_t hugetlb_cgroup_read(struct cgroup *cgroup, struct cftype *cft, + struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + u64 val; + char str[64]; + int idx, name, len; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cgroup); + + idx = MEMFILE_IDX(cft->private); + name = MEMFILE_ATTR(cft->private); + + val = res_counter_read_u64(&h_cg->hugepage[idx], name); + len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val); + return simple_read_from_buffer(buf, nbytes, ppos, str, len); +} + +static int hugetlb_cgroup_write(struct cgroup *cgroup, struct cftype *cft, + const char *buffer) +{ + int idx, name, ret; + unsigned long long val; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cgroup); + + idx = MEMFILE_IDX(cft->private); + name = MEMFILE_ATTR(cft->private); + + switch (name) { + case RES_LIMIT: + if (hugetlb_cgroup_is_root(h_cg)) { + /* Can't set limit on root */ + ret = -EINVAL; + break; + } + /* This function does all necessary parse...reuse it */ + ret = res_counter_memparse_write_strategy(buffer, &val); + if (ret) + break; + ret = res_counter_set_limit(&h_cg->hugepage[idx], val); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int hugetlb_cgroup_reset(struct cgroup *cgroup, unsigned int event) +{ + int idx, name, ret = 0; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cgroup); + + idx = MEMFILE_IDX(event); + name = MEMFILE_ATTR(event); + + switch (name) { + case RES_MAX_USAGE: + res_counter_reset_max(&h_cg->hugepage[idx]); + break; + case RES_FAILCNT: + res_counter_reset_failcnt(&h_cg->hugepage[idx]); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static char *mem_fmt(char *buf, int size, unsigned long hsize) +{ + if (hsize >= (1UL << 30)) + snprintf(buf, size, "%luGB", hsize >> 30); + else if (hsize >= (1UL << 20)) + snprintf(buf, size, "%luMB", hsize >> 20); + else + snprintf(buf, size, "%luKB", hsize >> 10); + return buf; +} + +int __init hugetlb_cgroup_file_init(int idx) +{ + char buf[32]; + struct cftype *cft; + struct hstate *h = &hstates[idx]; + + /* format the size */ + mem_fmt(buf, 32, huge_page_size(h)); + + /* Add the limit file */ + cft = &h->cgroup_files[0]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT); + cft->read = hugetlb_cgroup_read; + cft->write_string = hugetlb_cgroup_write; + + /* Add the usage file */ + cft = &h->cgroup_files[1]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_USAGE); + cft->read = hugetlb_cgroup_read; + + /* Add the MAX usage file */ + cft = &h->cgroup_files[2]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE); + cft->trigger = hugetlb_cgroup_reset; + cft->read = hugetlb_cgroup_read; + + /* Add the failcntfile */ + cft = &h->cgroup_files[3]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_FAILCNT); + cft->trigger = hugetlb_cgroup_reset; + cft->read = hugetlb_cgroup_read; + + /* NULL terminate the last cft */ + cft = &h->cgroup_files[4]; + memset(cft, 0, sizeof(*cft)); + + WARN_ON(cgroup_add_cftypes(&hugetlb_subsys, h->cgroup_files)); + + return 0; +} + struct cgroup_subsys hugetlb_subsys = { .name = "hugetlb", .create = hugetlb_cgroup_create, -- GitLab From 8e6ac7fab374816de9a8b0a8fbb02ef761a30ff4 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:27 -0700 Subject: [PATCH 4882/5711] hugetlb/cgroup: migrate hugetlb cgroup info from oldpage to new page during migration With HugeTLB pages, hugetlb cgroup is uncharged in compound page destructor. Since we are holding a hugepage reference, we can be sure that old page won't get uncharged till the last put_page(). Signed-off-by: Aneesh Kumar K.V Cc: David Rientjes Acked-by: KAMEZAWA Hiroyuki Cc: Hillf Danton Cc: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb_cgroup.h | 8 ++++++++ mm/hugetlb_cgroup.c | 20 ++++++++++++++++++++ mm/migrate.c | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h index 73f1e600fc12..d73878c694b3 100644 --- a/include/linux/hugetlb_cgroup.h +++ b/include/linux/hugetlb_cgroup.h @@ -63,6 +63,8 @@ extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, struct hugetlb_cgroup *h_cg); extern int hugetlb_cgroup_file_init(int idx) __init; +extern void hugetlb_cgroup_migrate(struct page *oldhpage, + struct page *newhpage); #else static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) @@ -114,5 +116,11 @@ static inline int __init hugetlb_cgroup_file_init(int idx) return 0; } +static inline void hugetlb_cgroup_migrate(struct page *oldhpage, + struct page *newhpage) +{ + return; +} + #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ #endif diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index d1ca1196e62f..680e4819e077 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -386,6 +386,26 @@ int __init hugetlb_cgroup_file_init(int idx) return 0; } +void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) +{ + struct hugetlb_cgroup *h_cg; + + if (hugetlb_cgroup_disabled()) + return; + + VM_BUG_ON(!PageHuge(oldhpage)); + spin_lock(&hugetlb_lock); + h_cg = hugetlb_cgroup_from_page(oldhpage); + set_hugetlb_cgroup(oldhpage, NULL); + cgroup_exclude_rmdir(&h_cg->css); + + /* move the h_cg details to new cgroup */ + set_hugetlb_cgroup(newhpage, h_cg); + spin_unlock(&hugetlb_lock); + cgroup_release_and_wakeup_rmdir(&h_cg->css); + return; +} + struct cgroup_subsys hugetlb_subsys = { .name = "hugetlb", .create = hugetlb_cgroup_create, diff --git a/mm/migrate.c b/mm/migrate.c index fdce3a29fc4c..6c37c51565e5 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -931,6 +932,10 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (anon_vma) put_anon_vma(anon_vma); + + if (!rc) + hugetlb_cgroup_migrate(hpage, new_hpage); + unlock_page(hpage); out: put_page(new_hpage); -- GitLab From 585e27ea6d2e71d0091443c39a00a35e6a5c5e8f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:30 -0700 Subject: [PATCH 4883/5711] hugetlb/cgroup: add HugeTLB controller documentation Signed-off-by: Aneesh Kumar K.V Reviewed-by: KAMEZAWA Hiroyuki Cc: David Rientjes Cc: Hillf Danton Reviewed-by: Michal Hocko Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups/hugetlb.txt | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/cgroups/hugetlb.txt diff --git a/Documentation/cgroups/hugetlb.txt b/Documentation/cgroups/hugetlb.txt new file mode 100644 index 000000000000..a9faaca1f029 --- /dev/null +++ b/Documentation/cgroups/hugetlb.txt @@ -0,0 +1,45 @@ +HugeTLB Controller +------------------- + +The HugeTLB controller allows to limit the HugeTLB usage per control group and +enforces the controller limit during page fault. Since HugeTLB doesn't +support page reclaim, enforcing the limit at page fault time implies that, +the application will get SIGBUS signal if it tries to access HugeTLB pages +beyond its limit. This requires the application to know beforehand how much +HugeTLB pages it would require for its use. + +HugeTLB controller can be created by first mounting the cgroup filesystem. + +# mount -t cgroup -o hugetlb none /sys/fs/cgroup + +With the above step, the initial or the parent HugeTLB group becomes +visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in +the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup. + +New groups can be created under the parent group /sys/fs/cgroup. + +# cd /sys/fs/cgroup +# mkdir g1 +# echo $$ > g1/tasks + +The above steps create a new group g1 and move the current shell +process (bash) into it. + +Brief summary of control files + + hugetlb..limit_in_bytes # set/show limit of "hugepagesize" hugetlb usage + hugetlb..max_usage_in_bytes # show max "hugepagesize" hugetlb usage recorded + hugetlb..usage_in_bytes # show current res_counter usage for "hugepagesize" hugetlb + hugetlb..failcnt # show the number of allocation failure due to HugeTLB limit + +For a system supporting two hugepage size (16M and 16G) the control +files include: + +hugetlb.16GB.limit_in_bytes +hugetlb.16GB.max_usage_in_bytes +hugetlb.16GB.usage_in_bytes +hugetlb.16GB.failcnt +hugetlb.16MB.limit_in_bytes +hugetlb.16MB.max_usage_in_bytes +hugetlb.16MB.usage_in_bytes +hugetlb.16MB.failcnt -- GitLab From 79dbb2368ae3515fad9c8b7c8f831cd86be59b1d Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:32 -0700 Subject: [PATCH 4884/5711] hugetlb: move all the in use pages to active list When we fail to allocate pages from the reserve pool, hugetlb tries to allocate huge pages using alloc_buddy_huge_page. Add these to the active list. We also need to add the huge page we allocate when we soft offline the oldpage to active list. Signed-off-by: Aneesh Kumar K.V Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c57740bb203a..ec7b86ebf9d9 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -928,8 +928,14 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid) page = dequeue_huge_page_node(h, nid); spin_unlock(&hugetlb_lock); - if (!page) + if (!page) { page = alloc_buddy_huge_page(h, nid); + if (page) { + spin_lock(&hugetlb_lock); + list_move(&page->lru, &h->hugepage_activelist); + spin_unlock(&hugetlb_lock); + } + } return page; } @@ -1155,6 +1161,9 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, hugepage_subpool_put_pages(spool, chg); return ERR_PTR(-ENOSPC); } + spin_lock(&hugetlb_lock); + list_move(&page->lru, &h->hugepage_activelist); + spin_unlock(&hugetlb_lock); } set_page_private(page, (unsigned long)spool); -- GitLab From 94ae8ba7176666d1e7d8bbb9f93670a27540b6a8 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:35 -0700 Subject: [PATCH 4885/5711] hugetlb/cgroup: assign the page hugetlb cgroup when we move the page to active list. A page's hugetlb cgroup assignment and movement to the active list should occur with hugetlb_lock held. Otherwise when we remove the hugetlb cgroup we will iterate the active list and find pages with NULL hugetlb cgroup values. Signed-off-by: Aneesh Kumar K.V Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 22 ++++++++++------------ mm/hugetlb_cgroup.c | 5 +++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ec7b86ebf9d9..c39e4beeb63a 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -928,14 +928,8 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid) page = dequeue_huge_page_node(h, nid); spin_unlock(&hugetlb_lock); - if (!page) { + if (!page) page = alloc_buddy_huge_page(h, nid); - if (page) { - spin_lock(&hugetlb_lock); - list_move(&page->lru, &h->hugepage_activelist); - spin_unlock(&hugetlb_lock); - } - } return page; } @@ -1150,9 +1144,13 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, } spin_lock(&hugetlb_lock); page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve); - spin_unlock(&hugetlb_lock); - - if (!page) { + if (page) { + /* update page cgroup details */ + hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h), + h_cg, page); + spin_unlock(&hugetlb_lock); + } else { + spin_unlock(&hugetlb_lock); page = alloc_buddy_huge_page(h, NUMA_NO_NODE); if (!page) { hugetlb_cgroup_uncharge_cgroup(idx, @@ -1162,6 +1160,8 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, return ERR_PTR(-ENOSPC); } spin_lock(&hugetlb_lock); + hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h), + h_cg, page); list_move(&page->lru, &h->hugepage_activelist); spin_unlock(&hugetlb_lock); } @@ -1169,8 +1169,6 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, set_page_private(page, (unsigned long)spool); vma_commit_reservation(h, vma, addr); - /* update page cgroup details */ - hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h), h_cg, page); return page; } diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 680e4819e077..9834a01c79dc 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -213,6 +213,7 @@ done: return ret; } +/* Should be called with hugetlb_lock held */ void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, struct hugetlb_cgroup *h_cg, struct page *page) @@ -220,9 +221,7 @@ void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, if (hugetlb_cgroup_disabled() || !h_cg) return; - spin_lock(&hugetlb_lock); set_hugetlb_cgroup(page, h_cg); - spin_unlock(&hugetlb_lock); return; } @@ -389,6 +388,7 @@ int __init hugetlb_cgroup_file_init(int idx) void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) { struct hugetlb_cgroup *h_cg; + struct hstate *h = page_hstate(oldhpage); if (hugetlb_cgroup_disabled()) return; @@ -401,6 +401,7 @@ void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) /* move the h_cg details to new cgroup */ set_hugetlb_cgroup(newhpage, h_cg); + list_move(&newhpage->lru, &h->hugepage_activelist); spin_unlock(&hugetlb_lock); cgroup_release_and_wakeup_rmdir(&h_cg->css); return; -- GitLab From 75754681fe79b84dde1048470a44eeb64192fad6 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 31 Jul 2012 16:42:36 -0700 Subject: [PATCH 4886/5711] hugetlb/cgroup: remove exclude and wakeup rmdir calls from migrate We already hold the hugetlb_lock. That should prevent a parallel cgroup rmdir from touching page's hugetlb cgroup. So remove the exclude and wakeup calls. Signed-off-by: Aneesh Kumar K.V Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb_cgroup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 9834a01c79dc..a3f358fb8a0c 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -385,6 +385,10 @@ int __init hugetlb_cgroup_file_init(int idx) return 0; } +/* + * hugetlb_lock will make sure a parallel cgroup rmdir won't happen + * when we migrate hugepages + */ void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) { struct hugetlb_cgroup *h_cg; @@ -397,13 +401,11 @@ void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) spin_lock(&hugetlb_lock); h_cg = hugetlb_cgroup_from_page(oldhpage); set_hugetlb_cgroup(oldhpage, NULL); - cgroup_exclude_rmdir(&h_cg->css); /* move the h_cg details to new cgroup */ set_hugetlb_cgroup(newhpage, h_cg); list_move(&newhpage->lru, &h->hugepage_activelist); spin_unlock(&hugetlb_lock); - cgroup_release_and_wakeup_rmdir(&h_cg->css); return; } -- GitLab From 4f774b912dd1d5752cd33b696509531b0321c3e0 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:42:37 -0700 Subject: [PATCH 4887/5711] mm, oom: do not schedule if current has been killed The oom killer currently schedules away from current in an uninterruptible sleep if it does not have access to memory reserves. It's possible that current was killed because it shares memory with the oom killed thread or because it was killed by the user in the interim, however. This patch only schedules away from current if it does not have a pending kill, i.e. if it does not share memory with the oom killed thread. It's possible that it will immediately retry its memory allocation and fail, but it will immediately be given access to memory reserves if it calls the oom killer again. This prevents the delay of memory freeing when threads that share memory with the oom killed thread get unnecessarily scheduled. Signed-off-by: David Rientjes Cc: Oleg Nesterov Acked-by: KOSAKI Motohiro Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index ac300c99baf6..e8ab3dfbc74b 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -745,11 +745,11 @@ out: read_unlock(&tasklist_lock); /* - * Give "p" a good chance of killing itself before we - * retry to allocate memory unless "p" is current + * Give the killed threads a good chance of exiting before trying to + * allocate memory again. */ - if (killed && !test_thread_flag(TIF_MEMDIE)) - schedule_timeout_uninterruptible(1); + if (killed) + schedule_timeout_killable(1); } /* @@ -764,6 +764,5 @@ void pagefault_out_of_memory(void) out_of_memory(NULL, 0, 0, NULL, false); clear_system_oom(); } - if (!test_thread_flag(TIF_MEMDIE)) - schedule_timeout_uninterruptible(1); + schedule_timeout_killable(1); } -- GitLab From fd07383b6bbc1418b1bdd5f295d13e600222fffa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 31 Jul 2012 16:42:40 -0700 Subject: [PATCH 4888/5711] mm/memblock.c:memblock_double_array(): cosmetic cleanups This function is an 80-column eyesore, quite unnecessarily. Clean that up, and use standard comment layout style. Cc: Benjamin Herrenschmidt Cc: Greg Pearson Cc: Tejun Heo Cc: Yinghai Lu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memblock.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 5cc6731b00cc..4d9393c7edc9 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -222,13 +222,13 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, /* Try to find some space for it. * * WARNING: We assume that either slab_is_available() and we use it or - * we use MEMBLOCK for allocations. That means that this is unsafe to use - * when bootmem is currently active (unless bootmem itself is implemented - * on top of MEMBLOCK which isn't the case yet) + * we use MEMBLOCK for allocations. That means that this is unsafe to + * use when bootmem is currently active (unless bootmem itself is + * implemented on top of MEMBLOCK which isn't the case yet) * * This should however not be an issue for now, as we currently only - * call into MEMBLOCK while it's still active, or much later when slab is - * active for memory hotplug operations + * call into MEMBLOCK while it's still active, or much later when slab + * is active for memory hotplug operations */ if (use_slab) { new_array = kmalloc(new_size, GFP_KERNEL); @@ -243,8 +243,8 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, new_alloc_size, PAGE_SIZE); if (!addr && new_area_size) addr = memblock_find_in_range(0, - min(new_area_start, memblock.current_limit), - new_alloc_size, PAGE_SIZE); + min(new_area_start, memblock.current_limit), + new_alloc_size, PAGE_SIZE); new_array = addr ? __va(addr) : 0; } @@ -254,12 +254,14 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, return -1; } - memblock_dbg("memblock: %s array is doubled to %ld at [%#010llx-%#010llx]", - memblock_type_name(type), type->max * 2, (u64)addr, (u64)addr + new_size - 1); + memblock_dbg("memblock: %s is doubled to %ld at [%#010llx-%#010llx]", + memblock_type_name(type), type->max * 2, (u64)addr, + (u64)addr + new_size - 1); - /* Found space, we now need to move the array over before - * we add the reserved region since it may be our reserved - * array itself that is full. + /* + * Found space, we now need to move the array over before we add the + * reserved region since it may be our reserved array itself that is + * full. */ memcpy(new_array, type->regions, old_size); memset(new_array + type->max, 0, old_size); @@ -267,17 +269,16 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, type->regions = new_array; type->max <<= 1; - /* Free old array. We needn't free it if the array is the - * static one - */ + /* Free old array. We needn't free it if the array is the static one */ if (*in_slab) kfree(old_array); else if (old_array != memblock_memory_init_regions && old_array != memblock_reserved_init_regions) memblock_free(__pa(old_array), old_alloc_size); - /* Reserve the new array if that comes from the memblock. - * Otherwise, we needn't do it + /* + * Reserve the new array if that comes from the memblock. Otherwise, we + * needn't do it */ if (!use_slab) BUG_ON(memblock_reserve(addr, new_alloc_size)); -- GitLab From 59b8e85c26e77d236ebdd61866ffc5e69c5f531d Mon Sep 17 00:00:00 2001 From: Kamezawa Hiroyuki Date: Tue, 31 Jul 2012 16:42:42 -0700 Subject: [PATCH 4889/5711] memcg: remove check for signal_pending() during rmdir() After bf544fdc241da8 "memcg: move charges to root cgroup if use_hierarchy=0 in mem_cgroup_move_hugetlb_parent()", no memory reclaim will occur when removing a memory cgroup. If -EINTR is returned here, cgroup will show a warning. We don't need to handle any user interruption signal. Remove this. Signed-off-by: KAMEZAWA Hiroyuki Cc: Johannes Weiner Acked-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1940ba8e6f00..8062d45ee7f4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3691,9 +3691,6 @@ move_account: ret = -EBUSY; if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children)) goto out; - ret = -EINTR; - if (signal_pending(current)) - goto out; /* This is for making all *used* pages to be on LRU. */ lru_add_drain_all(); drain_all_stock_sync(memcg); -- GitLab From d845aa2c75bcff87dacf098378b5706b12d1588f Mon Sep 17 00:00:00 2001 From: Kamezawa Hiroyuki Date: Tue, 31 Jul 2012 16:42:44 -0700 Subject: [PATCH 4890/5711] memcg: clean up force_empty_list() return value check After bf544fdc241da8 "memcg: move charges to root cgroup if use_hierarchy=0 in mem_cgroup_move_hugetlb_parent()" mem_cgroup_move_parent() returns only -EBUSY or -EINVAL. So we can remove the -ENOMEM and -EINTR checks. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 8062d45ee7f4..a1f00f0a66cd 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3653,8 +3653,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, pc = lookup_page_cgroup(page); ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL); - if (ret == -ENOMEM || ret == -EINTR) - break; if (ret == -EBUSY || ret == -EINVAL) { /* found lock contention or "pc" is obsolete. */ @@ -3711,9 +3709,6 @@ move_account: } mem_cgroup_end_move(memcg); memcg_oom_recover(memcg); - /* it seems parent cgroup doesn't have enough mem */ - if (ret == -ENOMEM) - goto try_to_free; cond_resched(); /* "ret" should also be checked to ensure all lists are empty. */ } while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret); -- GitLab From 6068bf0104becf07792b2867bc4d17c369419f8b Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 31 Jul 2012 16:42:45 -0700 Subject: [PATCH 4891/5711] memcg: mem_cgroup_move_parent() doesn't need gfp_mask Signed-off-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a1f00f0a66cd..964786634746 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2643,8 +2643,7 @@ out: static int mem_cgroup_move_parent(struct page *page, struct page_cgroup *pc, - struct mem_cgroup *child, - gfp_t gfp_mask) + struct mem_cgroup *child) { struct mem_cgroup *parent; unsigned int nr_pages; @@ -3652,7 +3651,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, pc = lookup_page_cgroup(page); - ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL); + ret = mem_cgroup_move_parent(page, pc, memcg); if (ret == -EBUSY || ret == -EINVAL) { /* found lock contention or "pc" is obsolete. */ -- GitLab From 3c935d189be9bb877c5a1110ac5fbf9c8e310658 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 31 Jul 2012 16:42:46 -0700 Subject: [PATCH 4892/5711] memcg: make mem_cgroup_force_empty_list() return bool mem_cgroup_force_empty_list() just returns 0 or -EBUSY and -EBUSY indicates 'you need to retry'. Make mem_cgroup_force_empty_list() return a bool to simplify the logic. [akpm@linux-foundation.org: rework mem_cgroup_force_empty_list()'s comment] Signed-off-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 964786634746..a2677e0a6387 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3609,10 +3609,12 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, } /* - * This routine traverse page_cgroup in given list and drop them all. - * *And* this routine doesn't reclaim page itself, just removes page_cgroup. + * Traverse a specified page_cgroup list and try to drop them all. This doesn't + * reclaim the pages page themselves - it just removes the page_cgroups. + * Returns true if some page_cgroups were not freed, indicating that the caller + * must retry this operation. */ -static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, +static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg, int node, int zid, enum lru_list lru) { struct mem_cgroup_per_zone *mz; @@ -3620,7 +3622,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, struct list_head *list; struct page *busy; struct zone *zone; - int ret = 0; zone = &NODE_DATA(node)->node_zones[zid]; mz = mem_cgroup_zoneinfo(memcg, node, zid); @@ -3634,7 +3635,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, struct page_cgroup *pc; struct page *page; - ret = 0; spin_lock_irqsave(&zone->lru_lock, flags); if (list_empty(list)) { spin_unlock_irqrestore(&zone->lru_lock, flags); @@ -3651,19 +3651,14 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, pc = lookup_page_cgroup(page); - ret = mem_cgroup_move_parent(page, pc, memcg); - - if (ret == -EBUSY || ret == -EINVAL) { + if (mem_cgroup_move_parent(page, pc, memcg)) { /* found lock contention or "pc" is obsolete. */ busy = page; cond_resched(); } else busy = NULL; } - - if (!ret && !list_empty(list)) - return -EBUSY; - return ret; + return !list_empty(list); } /* -- GitLab From c59e26104e3e0e952cd7d63e79cd71ee5a9ec25a Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 31 Jul 2012 16:42:49 -0700 Subject: [PATCH 4893/5711] mm/compaction: cleanup on compaction_deferred When CONFIG_COMPACTION is enabled, compaction_deferred() tries to recalculate the deferred limit again, which isn't necessary. When CONFIG_COMPACTION is disabled, compaction_deferred() should return "true" or "false" since it has "bool" for its return value. Signed-off-by: Gavin Shan Acked-by: Minchan Kim Acked-by: Johannes Weiner Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compaction.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 51a90b7f2d60..133ddcf83397 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -58,7 +58,7 @@ static inline bool compaction_deferred(struct zone *zone, int order) if (++zone->compact_considered > defer_limit) zone->compact_considered = defer_limit; - return zone->compact_considered < (1UL << zone->compact_defer_shift); + return zone->compact_considered < defer_limit; } #else @@ -85,7 +85,7 @@ static inline void defer_compaction(struct zone *zone, int order) static inline bool compaction_deferred(struct zone *zone, int order) { - return 1; + return true; } #endif /* CONFIG_COMPACTION */ -- GitLab From 3d3727cdb07ff17ddc3c551ef8d03d37b60a0372 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 31 Jul 2012 16:42:50 -0700 Subject: [PATCH 4894/5711] mm, fadvise: don't return -EINVAL when filesystem cannot implement fadvise() Eric Wong reported his test suite failex when /tmp is tmpfs. https://lkml.org/lkml/2012/2/24/479 Currentlt the input check of POSIX_FADV_WILLNEED has two problems. - requires a_ops->readpage. But in fact, force_page_cache_readahead() requires that the target filesystem has either ->readpage or ->readpages. - returns -EINVAL when the filesystem doesn't have ->readpage. But posix says that fadvise is merely a hint. Thus fadvise() should return 0 if filesystem has no means of implementing fadvise(). The userland application should not know nor care whcih type of filesystem backs the TMPDIR directory, as Eric pointed out. There is nothing which userspace can do to solve this error. So change the return value to 0 when filesytem doesn't support readahead. [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: KOSAKI Motohiro Cc: Hugh Dickins Cc: Hillf Danton Signed-off-by: Eric Wong Tested-by: Eric Wong Reviewed-by: Wanlong Gao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/fadvise.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/mm/fadvise.c b/mm/fadvise.c index 469491e0af79..9b75a045dbf4 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -93,11 +93,6 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) spin_unlock(&file->f_lock); break; case POSIX_FADV_WILLNEED: - if (!mapping->a_ops->readpage) { - ret = -EINVAL; - break; - } - /* First and last PARTIAL page! */ start_index = offset >> PAGE_CACHE_SHIFT; end_index = endbyte >> PAGE_CACHE_SHIFT; @@ -106,12 +101,13 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) nrpages = end_index - start_index + 1; if (!nrpages) nrpages = ~0UL; - - ret = force_page_cache_readahead(mapping, file, - start_index, - nrpages); - if (ret > 0) - ret = 0; + + /* + * Ignore return value because fadvise() shall return + * success even if filesystem can't retrieve a hint, + */ + force_page_cache_readahead(mapping, file, start_index, + nrpages); break; case POSIX_FADV_NOREUSE: break; -- GitLab From 2a13515c398bbe471bf64519ada87fd708152ced Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 31 Jul 2012 16:42:53 -0700 Subject: [PATCH 4895/5711] mm: clear pages_scanned only if draining a pcp adds pages to the buddy allocator again commit 2ff754fa8f ("mm: clear pages_scanned only if draining a pcp adds pages to the buddy allocator again") fixed one free_pcppages_bulk() misuse. But two another miuse still exist. This patch fixes it. Signed-off-by: KOSAKI Motohiro Acked-by: David Rientjes Acked-by: Mel Gorman Acked-by: Johannes Weiner Reviewed-by: Minchan Kim Cc: Wu Fengguang Reviewed-by: KAMEZAWA Hiroyuki Cc: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 80ef99234b89..18747528eec3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1158,8 +1158,10 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp) to_drain = pcp->batch; else to_drain = pcp->count; - free_pcppages_bulk(zone, to_drain, pcp); - pcp->count -= to_drain; + if (to_drain > 0) { + free_pcppages_bulk(zone, to_drain, pcp); + pcp->count -= to_drain; + } local_irq_restore(flags); } #endif @@ -3915,7 +3917,8 @@ static int __zone_pcp_update(void *data) pcp = &pset->pcp; local_irq_save(flags); - free_pcppages_bulk(zone, pcp->count, pcp); + if (pcp->count > 0) + free_pcppages_bulk(zone, pcp->count, pcp); setup_pageset(pset, batch); local_irq_restore(flags); } -- GitLab From 121d1ba0a019e1465a53533aea133b1b0f6b442d Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:42:55 -0700 Subject: [PATCH 4896/5711] mm, oom: fix potential killing of thread that is disabled from oom killing /proc/sys/vm/oom_kill_allocating_task will immediately kill current when the oom killer is called to avoid a potentially expensive tasklist scan for large systems. Currently, however, it is not checking current's oom_score_adj value which may be OOM_SCORE_ADJ_MIN, meaning that it has been disabled from oom killing. This patch avoids killing current in such a condition and simply falls back to the tasklist scan since memory still needs to be freed. Signed-off-by: David Rientjes Cc: KAMEZAWA Hiroyuki Acked-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index e8ab3dfbc74b..50e74373e855 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -719,9 +719,9 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, check_panic_on_oom(constraint, gfp_mask, order, mpol_mask); read_lock(&tasklist_lock); - if (sysctl_oom_kill_allocating_task && + if (sysctl_oom_kill_allocating_task && current->mm && !oom_unkillable_task(current, NULL, nodemask) && - current->mm) { + current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL, nodemask, "Out of memory (oom_kill_allocating_task)"); -- GitLab From de34d965a80d0f61a354bdefa0b15a88bcff2028 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:42:56 -0700 Subject: [PATCH 4897/5711] mm, oom: replace some information in tasklist dump The number of ptes and swap entries are used in the oom killer's badness heuristic, so they should be shown in the tasklist dump. This patch adds those fields and replaces cpu and oom_adj values that are currently emitted. Cpu isn't interesting and oom_adj is deprecated and will be removed later this year, the same information is already displayed as oom_score_adj which is used internally. At the same time, make the documentation a little more clear to state this information is helpful to determine why the oom killer chose the task it did to kill. Signed-off-by: David Rientjes Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysctl/vm.txt | 7 ++++--- mm/oom_kill.c | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 06d662b1c5d5..dcc2a94ae34e 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -491,9 +491,10 @@ oom_dump_tasks Enables a system-wide task dump (excluding kernel threads) to be produced when the kernel performs an OOM-killing and includes such -information as pid, uid, tgid, vm size, rss, cpu, oom_adj score, and -name. This is helpful to determine why the OOM killer was invoked -and to identify the rogue task that caused it. +information as pid, uid, tgid, vm size, rss, nr_ptes, swapents, +oom_score_adj score, and name. This is helpful to determine why the +OOM killer was invoked, to identify the rogue task that caused it, +and to determine why the OOM killer chose the task it did to kill. If this is set to zero, this information is suppressed. On very large systems with thousands of tasks it may not be feasible to dump diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 50e74373e855..c82ede69bf3f 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -371,8 +371,8 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, * Dumps the current memory state of all eligible tasks. Tasks not in the same * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes * are not shown. - * State information includes task's pid, uid, tgid, vm size, rss, cpu, oom_adj - * value, oom_score_adj value, and name. + * State information includes task's pid, uid, tgid, vm size, rss, nr_ptes, + * swapents, oom_score_adj value, and name. * * Call with tasklist_lock read-locked. */ @@ -381,7 +381,7 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas struct task_struct *p; struct task_struct *task; - pr_info("[ pid ] uid tgid total_vm rss cpu oom_adj oom_score_adj name\n"); + pr_info("[ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name\n"); for_each_process(p) { if (oom_unkillable_task(p, memcg, nodemask)) continue; @@ -396,10 +396,11 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas continue; } - pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", + pr_info("[%5d] %5d %5d %8lu %8lu %7lu %8lu %5d %s\n", task->pid, from_kuid(&init_user_ns, task_uid(task)), task->tgid, task->mm->total_vm, get_mm_rss(task->mm), - task_cpu(task), task->signal->oom_adj, + task->mm->nr_ptes, + get_mm_counter(task->mm, MM_SWAPENTS), task->signal->oom_score_adj, task->comm); task_unlock(task); } -- GitLab From 97d255c816946388bab504122937730d3447c612 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:42:59 -0700 Subject: [PATCH 4898/5711] mm: do not use page_count() without a page pin d179e84ba ("mm: vmscan: do not use page_count without a page pin") fixed this problem in vmscan.c but same problem is in __count_immobile_pages(). I copy and paste d179e84ba's contents for description. "It is unsafe to run page_count during the physical pfn scan because compound_head could trip on a dangling pointer when reading page->first_page if the compound page is being freed by another CPU." Signed-off-by: Minchan Kim Cc: Andrea Arcangeli Cc: Mel Gorman Cc: Michal Hocko Reviewed-by: KAMEZAWA Hiroyuki Cc: Wanpeng Li Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 18747528eec3..bb790f5919e3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5500,11 +5500,18 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count) continue; page = pfn_to_page(check); - if (!page_count(page)) { + /* + * We can't use page_count without pin a page + * because another CPU can free compound page. + * This check already skips compound tails of THP + * because their page->_count is zero at all time. + */ + if (!atomic_read(&page->_count)) { if (PageBuddy(page)) iter += (1 << page_order(page)) - 1; continue; } + if (!PageLRU(page)) found++; /* -- GitLab From 80934513b230bfcf70265f2ef0fdae89fb391633 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:43:01 -0700 Subject: [PATCH 4899/5711] mm: clean up __count_immobile_pages() The __count_immobile_pages() naming is rather awkward. Choose a more clear name and add a comment. Signed-off-by: Minchan Kim Cc: Andrea Arcangeli Cc: Mel Gorman Cc: Michal Hocko Acked-by: KAMEZAWA Hiroyuki Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bb790f5919e3..fba2a1223f14 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5471,26 +5471,28 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, } /* - * This is designed as sub function...plz see page_isolation.c also. - * set/clear page block's type to be ISOLATE. - * page allocater never alloc memory from ISOLATE block. + * This function checks whether pageblock includes unmovable pages or not. + * If @count is not zero, it is okay to include less @count unmovable pages + * + * PageLRU check wihtout isolation or lru_lock could race so that + * MIGRATE_MOVABLE block might include unmovable pages. It means you can't + * expect this function should be exact. */ - -static int -__count_immobile_pages(struct zone *zone, struct page *page, int count) +static bool +__has_unmovable_pages(struct zone *zone, struct page *page, int count) { unsigned long pfn, iter, found; int mt; /* * For avoiding noise data, lru_add_drain_all() should be called - * If ZONE_MOVABLE, the zone never contains immobile pages + * If ZONE_MOVABLE, the zone never contains unmovable pages */ if (zone_idx(zone) == ZONE_MOVABLE) - return true; + return false; mt = get_pageblock_migratetype(page); if (mt == MIGRATE_MOVABLE || is_migrate_cma(mt)) - return true; + return false; pfn = page_to_pfn(page); for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) { @@ -5528,9 +5530,9 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count) * page at boot. */ if (found > count) - return false; + return true; } - return true; + return false; } bool is_pageblock_removable_nolock(struct page *page) @@ -5554,7 +5556,7 @@ bool is_pageblock_removable_nolock(struct page *page) zone->zone_start_pfn + zone->spanned_pages <= pfn) return false; - return __count_immobile_pages(zone, page, 0); + return !__has_unmovable_pages(zone, page, 0); } int set_migratetype_isolate(struct page *page) @@ -5593,12 +5595,12 @@ int set_migratetype_isolate(struct page *page) * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. * We just check MOVABLE pages. */ - if (__count_immobile_pages(zone, page, arg.pages_found)) + if (!__has_unmovable_pages(zone, page, arg.pages_found)) ret = 0; - /* - * immobile means "not-on-lru" paes. If immobile is larger than - * removable-by-driver pages reported by notifier, we'll fail. + * Unmovable means "not-on-lru" pages. If Unmovable pages are + * larger than removable-by-driver pages reported by notifier, + * we'll fail. */ out: -- GitLab From c255a458055e459f65eb7b7f51dc5dbdd0caf1d8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 31 Jul 2012 16:43:02 -0700 Subject: [PATCH 4900/5711] memcg: rename config variables Sanity: CONFIG_CGROUP_MEM_RES_CTLR -> CONFIG_MEMCG CONFIG_CGROUP_MEM_RES_CTLR_SWAP -> CONFIG_MEMCG_SWAP CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED -> CONFIG_MEMCG_SWAP_ENABLED CONFIG_CGROUP_MEM_RES_CTLR_KMEM -> CONFIG_MEMCG_KMEM [mhocko@suse.cz: fix missed bits] Cc: Glauber Costa Acked-by: Michal Hocko Cc: Johannes Weiner Cc: KAMEZAWA Hiroyuki Cc: Hugh Dickins Cc: Tejun Heo Cc: Aneesh Kumar K.V Cc: David Rientjes Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups/memory.txt | 10 +++++----- arch/powerpc/configs/chroma_defconfig | 4 ++-- arch/s390/defconfig | 2 +- arch/sh/configs/apsh4ad0a_defconfig | 2 +- arch/sh/configs/sdk7786_defconfig | 4 ++-- arch/sh/configs/se7206_defconfig | 2 +- arch/sh/configs/shx3_defconfig | 2 +- arch/sh/configs/urquell_defconfig | 4 ++-- arch/tile/configs/tilegx_defconfig | 4 ++-- arch/tile/configs/tilepro_defconfig | 4 ++-- arch/um/defconfig | 8 ++++---- include/linux/cgroup_subsys.h | 2 +- include/linux/memcontrol.h | 14 +++++++------- include/linux/mmzone.h | 8 ++++---- include/linux/page_cgroup.h | 10 +++++----- include/linux/sched.h | 2 +- include/linux/swap.h | 6 +++--- include/net/sock.h | 4 ++-- init/Kconfig | 14 +++++++------- kernel/fork.c | 2 +- mm/Makefile | 2 +- mm/hwpoison-inject.c | 2 +- mm/memcontrol.c | 20 ++++++++++---------- mm/memory-failure.c | 2 +- mm/mmzone.c | 2 +- mm/oom_kill.c | 2 +- mm/page_cgroup.c | 2 +- mm/vmscan.c | 4 ++-- net/core/sock.c | 2 +- net/ipv4/Makefile | 2 +- net/ipv4/sysctl_net_ipv4.c | 4 ++-- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- 33 files changed, 78 insertions(+), 78 deletions(-) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index dd88540bb995..672676ac9615 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -187,12 +187,12 @@ the cgroup that brought it in -- this will happen on memory pressure). But see section 8.2: when moving a task to another cgroup, its pages may be recharged to the new cgroup, if move_charge_at_immigrate has been chosen. -Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used. +Exception: If CONFIG_CGROUP_CGROUP_MEMCG_SWAP is not used. When you do swapoff and make swapped-out pages of shmem(tmpfs) to be backed into memory in force, charges for pages are accounted against the caller of swapoff rather than the users of shmem. -2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP) +2.4 Swap Extension (CONFIG_MEMCG_SWAP) Swap Extension allows you to record charge for swap. A swapped-in page is charged back to original page allocator if possible. @@ -259,7 +259,7 @@ When oom event notifier is registered, event will be delivered. per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by zone->lru_lock, it has no lock of its own. -2.7 Kernel Memory Extension (CONFIG_CGROUP_MEM_RES_CTLR_KMEM) +2.7 Kernel Memory Extension (CONFIG_MEMCG_KMEM) With the Kernel memory extension, the Memory Controller is able to limit the amount of kernel memory used by the system. Kernel memory is fundamentally @@ -286,8 +286,8 @@ per cgroup, instead of globally. a. Enable CONFIG_CGROUPS b. Enable CONFIG_RESOURCE_COUNTERS -c. Enable CONFIG_CGROUP_MEM_RES_CTLR -d. Enable CONFIG_CGROUP_MEM_RES_CTLR_SWAP (to use swap extension) +c. Enable CONFIG_MEMCG +d. Enable CONFIG_MEMCG_SWAP (to use swap extension) 1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?) # mount -t tmpfs none /sys/fs/cgroup diff --git a/arch/powerpc/configs/chroma_defconfig b/arch/powerpc/configs/chroma_defconfig index b1f9597fe312..29bb11ec6c64 100644 --- a/arch/powerpc/configs/chroma_defconfig +++ b/arch/powerpc/configs/chroma_defconfig @@ -21,8 +21,8 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y CONFIG_NAMESPACES=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 37d2bf267964..de57702a3f44 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -13,7 +13,7 @@ CONFIG_CGROUPS=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEMCG=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y diff --git a/arch/sh/configs/apsh4ad0a_defconfig b/arch/sh/configs/apsh4ad0a_defconfig index e7583484cc07..95ae23fcfdd6 100644 --- a/arch/sh/configs/apsh4ad0a_defconfig +++ b/arch/sh/configs/apsh4ad0a_defconfig @@ -11,7 +11,7 @@ CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEMCG=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig index 8a7dd7b59c5c..76a76a295d74 100644 --- a/arch/sh/configs/sdk7786_defconfig +++ b/arch/sh/configs/sdk7786_defconfig @@ -18,8 +18,8 @@ CONFIG_CPUSETS=y # CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig index 72c3fad7383f..6bc30ab9fd18 100644 --- a/arch/sh/configs/se7206_defconfig +++ b/arch/sh/configs/se7206_defconfig @@ -11,7 +11,7 @@ CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEMCG=y CONFIG_RELAY=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig index 6bb413036892..cd6c519f8fad 100644 --- a/arch/sh/configs/shx3_defconfig +++ b/arch/sh/configs/shx3_defconfig @@ -13,7 +13,7 @@ CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEMCG=y CONFIG_RELAY=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig index 8bfa4d056d7a..d7f89be9f474 100644 --- a/arch/sh/configs/urquell_defconfig +++ b/arch/sh/configs/urquell_defconfig @@ -15,8 +15,8 @@ CONFIG_CPUSETS=y # CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_DEV_INITRD=y diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index b8d99aca5431..0270620a1692 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -18,8 +18,8 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index 2b1fd31894f1..c11de27a9bcb 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -17,8 +17,8 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y diff --git a/arch/um/defconfig b/arch/um/defconfig index 7823ab12e6a4..fec0d5d27460 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -155,10 +155,10 @@ CONFIG_CPUSETS=y CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set -# CONFIG_CGROUP_MEM_RES_CTLR_KMEM is not set +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEMCG_SWAP=y +# CONFIG_CGROUP_MEMCG_SWAP_ENABLED is not set +# CONFIG_CGROUP_MEMCG_KMEM is not set CONFIG_CGROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_CFS_BANDWIDTH is not set diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 5b41ce079024..dfae957398c3 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -31,7 +31,7 @@ SUBSYS(cpuacct) /* */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG SUBSYS(mem_cgroup) #endif diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 83e7ba90d6e5..170076222431 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -38,7 +38,7 @@ struct mem_cgroup_reclaim_cookie { unsigned int generation; }; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG /* * All "charge" functions with gfp_mask should use GFP_KERNEL or * (gfp_mask & GFP_RECLAIM_MASK). In current implementatin, memcg doesn't @@ -124,7 +124,7 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, extern void mem_cgroup_replace_page_cache(struct page *oldpage, struct page *newpage); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP extern int do_swap_account; #endif @@ -193,7 +193,7 @@ void mem_cgroup_split_huge_fixup(struct page *head); bool mem_cgroup_bad_page_check(struct page *page); void mem_cgroup_print_bad_page(struct page *page); #endif -#else /* CONFIG_CGROUP_MEM_RES_CTLR */ +#else /* CONFIG_MEMCG */ struct mem_cgroup; static inline int mem_cgroup_newpage_charge(struct page *page, @@ -384,9 +384,9 @@ static inline void mem_cgroup_replace_page_cache(struct page *oldpage, struct page *newpage) { } -#endif /* CONFIG_CGROUP_MEM_RES_CTLR */ +#endif /* CONFIG_MEMCG */ -#if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM) +#if !defined(CONFIG_MEMCG) || !defined(CONFIG_DEBUG_VM) static inline bool mem_cgroup_bad_page_check(struct page *page) { @@ -406,7 +406,7 @@ enum { }; struct sock; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM void sock_update_memcg(struct sock *sk); void sock_release_memcg(struct sock *sk); #else @@ -416,6 +416,6 @@ static inline void sock_update_memcg(struct sock *sk) static inline void sock_release_memcg(struct sock *sk) { } -#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ +#endif /* CONFIG_MEMCG_KMEM */ #endif /* _LINUX_MEMCONTROL_H */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 458988bd55a1..3bdfa15b2012 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -201,7 +201,7 @@ struct zone_reclaim_stat { struct lruvec { struct list_head lists[NR_LRU_LISTS]; struct zone_reclaim_stat reclaim_stat; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG struct zone *zone; #endif }; @@ -671,7 +671,7 @@ typedef struct pglist_data { int nr_zones; #ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */ struct page *node_mem_map; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG struct page_cgroup *node_page_cgroup; #endif #endif @@ -736,7 +736,7 @@ extern void lruvec_init(struct lruvec *lruvec, struct zone *zone); static inline struct zone *lruvec_zone(struct lruvec *lruvec) { -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG return lruvec->zone; #else return container_of(lruvec, struct zone, lruvec); @@ -1052,7 +1052,7 @@ struct mem_section { /* See declaration of similar field in struct zone */ unsigned long *pageblock_flags; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG /* * If !SPARSEMEM, pgdat doesn't have page_cgroup pointer. We use * section. (see memcontrol.h/page_cgroup.h about this.) diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index a88cdba27809..777a524716db 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h @@ -12,7 +12,7 @@ enum { #ifndef __GENERATING_BOUNDS_H #include -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG #include /* @@ -82,7 +82,7 @@ static inline void unlock_page_cgroup(struct page_cgroup *pc) bit_spin_unlock(PCG_LOCK, &pc->flags); } -#else /* CONFIG_CGROUP_MEM_RES_CTLR */ +#else /* CONFIG_MEMCG */ struct page_cgroup; static inline void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) @@ -102,11 +102,11 @@ static inline void __init page_cgroup_init_flatmem(void) { } -#endif /* CONFIG_CGROUP_MEM_RES_CTLR */ +#endif /* CONFIG_MEMCG */ #include -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP extern unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, unsigned short old, unsigned short new); extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id); @@ -138,7 +138,7 @@ static inline void swap_cgroup_swapoff(int type) return; } -#endif /* CONFIG_CGROUP_MEM_RES_CTLR_SWAP */ +#endif /* CONFIG_MEMCG_SWAP */ #endif /* !__GENERATING_BOUNDS_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 68dcffaa62a0..865725adb9d3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1584,7 +1584,7 @@ struct task_struct { /* bitmask and counter of trace recursion */ unsigned long trace_recursion; #endif /* CONFIG_TRACING */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */ +#ifdef CONFIG_MEMCG /* memcg uses this to do batch job */ struct memcg_batch_info { int do_batch; /* incremented when batch uncharge started */ struct mem_cgroup *memcg; /* target memcg of uncharge */ diff --git a/include/linux/swap.h b/include/linux/swap.h index c84ec68eaec9..9a16bb1cefd1 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -301,7 +301,7 @@ static inline void scan_unevictable_unregister_node(struct node *node) extern int kswapd_run(int nid); extern void kswapd_stop(int nid); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG extern int mem_cgroup_swappiness(struct mem_cgroup *mem); #else static inline int mem_cgroup_swappiness(struct mem_cgroup *mem) @@ -309,7 +309,7 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem) return vm_swappiness; } #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP extern void mem_cgroup_uncharge_swap(swp_entry_t ent); #else static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) @@ -360,7 +360,7 @@ extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); #else diff --git a/include/net/sock.h b/include/net/sock.h index e067f8c18f88..cee528c119ca 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -913,7 +913,7 @@ struct proto { #ifdef SOCK_REFCNT_DEBUG atomic_t socks; #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM /* * cgroup specific init/deinit functions. Called once for all * protocols that implement it, from cgroups populate function. @@ -994,7 +994,7 @@ inline void sk_refcnt_debug_release(const struct sock *sk) #define sk_refcnt_debug_release(sk) do { } while (0) #endif /* SOCK_REFCNT_DEBUG */ -#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET) +#if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_NET) extern struct static_key memcg_socket_limit_enabled; static inline struct cg_proto *parent_cg_proto(struct proto *proto, struct cg_proto *cg_proto) diff --git a/init/Kconfig b/init/Kconfig index 72437760e90e..af6c7f8ba019 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -686,7 +686,7 @@ config RESOURCE_COUNTERS This option enables controller independent resource accounting infrastructure that works with cgroups. -config CGROUP_MEM_RES_CTLR +config MEMCG bool "Memory Resource Controller for Control Groups" depends on RESOURCE_COUNTERS select MM_OWNER @@ -709,9 +709,9 @@ config CGROUP_MEM_RES_CTLR This config option also selects MM_OWNER config option, which could in turn add some fork/exit overhead. -config CGROUP_MEM_RES_CTLR_SWAP +config MEMCG_SWAP bool "Memory Resource Controller Swap Extension" - depends on CGROUP_MEM_RES_CTLR && SWAP + depends on MEMCG && SWAP help Add swap management feature to memory resource controller. When you enable this, you can limit mem+swap usage per cgroup. In other words, @@ -726,9 +726,9 @@ config CGROUP_MEM_RES_CTLR_SWAP if boot option "swapaccount=0" is set, swap will not be accounted. Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page size is 4096bytes, 512k per 1Gbytes of swap. -config CGROUP_MEM_RES_CTLR_SWAP_ENABLED +config MEMCG_SWAP_ENABLED bool "Memory Resource Controller Swap Extension enabled by default" - depends on CGROUP_MEM_RES_CTLR_SWAP + depends on MEMCG_SWAP default y help Memory Resource Controller Swap Extension comes with its price in @@ -739,9 +739,9 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED For those who want to have the feature enabled by default should select this option (if, for some reason, they need to disable it then swapaccount=0 does the trick). -config CGROUP_MEM_RES_CTLR_KMEM +config MEMCG_KMEM bool "Memory Resource Controller Kernel Memory accounting (EXPERIMENTAL)" - depends on CGROUP_MEM_RES_CTLR && EXPERIMENTAL + depends on MEMCG && EXPERIMENTAL default n help The Kernel Memory extension for Memory Resource Controller can limit diff --git a/kernel/fork.c b/kernel/fork.c index aaa8813c45d1..3bd2280d79f6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1306,7 +1306,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, #ifdef CONFIG_DEBUG_MUTEXES p->blocked_on = NULL; /* not blocked yet */ #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG p->memcg_batch.do_batch = 0; p->memcg_batch.memcg = NULL; #endif diff --git a/mm/Makefile b/mm/Makefile index fd6fc1c1966c..290bbfe33698 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_FS_XIP) += filemap_xip.o obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o -obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o +obj-$(CONFIG_MEMCG) += memcontrol.o page_cgroup.o obj-$(CONFIG_CGROUP_HUGETLB) += hugetlb_cgroup.o obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c index cc448bb983ba..3a61efc518d5 100644 --- a/mm/hwpoison-inject.c +++ b/mm/hwpoison-inject.c @@ -123,7 +123,7 @@ static int pfn_inject_init(void) if (!dentry) goto fail; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP dentry = debugfs_create_u64("corrupt-filter-memcg", 0600, hwpoison_dir, &hwpoison_filter_memcg); if (!dentry) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a2677e0a6387..55a85e1a342f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -61,12 +61,12 @@ struct cgroup_subsys mem_cgroup_subsys __read_mostly; #define MEM_CGROUP_RECLAIM_RETRIES 5 static struct mem_cgroup *root_mem_cgroup __read_mostly; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP /* Turned on only when memory cgroup is enabled && really_do_swap_account = 1 */ int do_swap_account __read_mostly; /* for remember boot option*/ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED +#ifdef CONFIG_MEMCG_SWAP_ENABLED static int really_do_swap_account __initdata = 1; #else static int really_do_swap_account __initdata = 0; @@ -407,7 +407,7 @@ static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); /* Writing them here to avoid exposing memcg's inner layout */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM #include #include @@ -466,9 +466,9 @@ struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg) } EXPORT_SYMBOL(tcp_proto_cgroup); #endif /* CONFIG_INET */ -#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ +#endif /* CONFIG_MEMCG_KMEM */ -#if defined(CONFIG_INET) && defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) +#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM) static void disarm_sock_keys(struct mem_cgroup *memcg) { if (!memcg_proto_activated(&memcg->tcp_mem.cg_proto)) @@ -3085,7 +3085,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) } #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP /* * called from swap_entry_free(). remove record in swap_cgroup and * uncharge "memsw" account. @@ -4518,7 +4518,7 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp, return 0; } -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss) { return mem_cgroup_sockets_init(memcg, ss); @@ -4608,7 +4608,7 @@ static struct cftype mem_cgroup_files[] = { .read_seq_string = mem_control_numa_stat_show, }, #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP { .name = "memsw.usage_in_bytes", .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), @@ -4795,7 +4795,7 @@ struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg) } EXPORT_SYMBOL(parent_mem_cgroup); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP static void __init enable_swap_cgroup(void) { if (!mem_cgroup_disabled() && really_do_swap_account) @@ -5526,7 +5526,7 @@ struct cgroup_subsys mem_cgroup_subsys = { .__DEPRECATED_clear_css_refs = true, }; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP static int __init enable_swap_account(char *s) { /* consider enabled if no parameter or 1 is given */ diff --git a/mm/memory-failure.c b/mm/memory-failure.c index b04ff2d6f73d..a6e2141a6610 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -128,7 +128,7 @@ static int hwpoison_filter_flags(struct page *p) * can only guarantee that the page either belongs to the memcg tasks, or is * a freed page. */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP u64 hwpoison_filter_memcg; EXPORT_SYMBOL_GPL(hwpoison_filter_memcg); static int hwpoison_filter_task(struct page *p) diff --git a/mm/mmzone.c b/mm/mmzone.c index 6830eab5bf09..3cef80f6ac79 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -96,7 +96,7 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone) for_each_lru(lru) INIT_LIST_HEAD(&lruvec->lists[lru]); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG lruvec->zone = zone; #endif } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index c82ede69bf3f..e6c10640e56b 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -541,7 +541,7 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, int order) { diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index eb750f851395..5ddad0c6daa6 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -317,7 +317,7 @@ void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +#ifdef CONFIG_MEMCG_SWAP static DEFINE_MUTEX(swap_cgroup_mutex); struct swap_cgroup_ctrl { diff --git a/mm/vmscan.c b/mm/vmscan.c index 347b3ff2a478..6b1f89a91212 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -133,7 +133,7 @@ long vm_total_pages; /* The total number of pages which the VM controls */ static LIST_HEAD(shrinker_list); static DECLARE_RWSEM(shrinker_rwsem); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG static bool global_reclaim(struct scan_control *sc) { return !sc->target_mem_cgroup; @@ -2142,7 +2142,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, return nr_reclaimed; } -#ifdef CONFIG_CGROUP_MEM_RES_CTLR +#ifdef CONFIG_MEMCG unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *memcg, gfp_t gfp_mask, bool noswap, diff --git a/net/core/sock.c b/net/core/sock.c index 2676a88f533e..a67b06280e4c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -142,7 +142,7 @@ static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss) { struct proto *proto; diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index ae2ccf2890e4..15ca63ec604e 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o -obj-$(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) += tcp_memcontrol.o +obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 5840c3255721..ed7db3f1b6f2 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -184,7 +184,7 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, int ret; unsigned long vec[3]; struct net *net = current->nsproxy->net_ns; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM struct mem_cgroup *memcg; #endif @@ -203,7 +203,7 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, if (ret) return ret; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM rcu_read_lock(); memcg = mem_cgroup_from_task(current); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2fbd9921253f..4bc8f6769b57 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2633,7 +2633,7 @@ struct proto tcp_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM .init_cgroup = tcp_init_cgroup, .destroy_cgroup = tcp_destroy_cgroup, .proto_cgroup = tcp_proto_cgroup, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 221224e72507..61c7b6d83176 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2015,7 +2015,7 @@ struct proto tcpv6_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM .proto_cgroup = tcp_proto_cgroup, #endif }; -- GitLab From ca28ddc908fcfef0e5c1b6e5df632db7fc26de10 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:43:04 -0700 Subject: [PATCH 4901/5711] mm: remove unused LRU_ALL_EVICTABLE Signed-off-by: Wanpeng Li Acked-by: KAMEZAWA Hiroyuki Cc: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 3bdfa15b2012..1495d952e641 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -209,7 +209,6 @@ struct lruvec { /* Mask used at gathering information at once (see memcontrol.c) */ #define LRU_ALL_FILE (BIT(LRU_INACTIVE_FILE) | BIT(LRU_ACTIVE_FILE)) #define LRU_ALL_ANON (BIT(LRU_INACTIVE_ANON) | BIT(LRU_ACTIVE_ANON)) -#define LRU_ALL_EVICTABLE (LRU_ALL_FILE | LRU_ALL_ANON) #define LRU_ALL ((1 << NR_LRU_LISTS) - 1) /* Isolate clean file */ -- GitLab From 567fb435bb7a37afda35902b884562c40756dc45 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Tue, 31 Jul 2012 16:43:07 -0700 Subject: [PATCH 4902/5711] memcg: fix bad behavior in use_hierarchy file I have an application that does the following: * copy the state of all controllers attached to a hierarchy * replicate it as a child of the current level. I would expect writes to the files to mostly succeed, since they are inheriting sane values from parents. But that is not the case for use_hierarchy. If it is set to 0, we succeed ok. If we're set to 1, the value of the file is automatically set to 1 in the children, but if userspace tries to write the very same 1, it will fail. That same situation happens if we set use_hierarchy, create a child, and then try to write 1 again. Now, there is no reason whatsoever for failing to write a value that is already there. It doesn't even match the comments, that states: /* If parent's use_hierarchy is set, we can't make any modifications * in the child subtrees... since we are not changing anything. So test the new value against the one we're storing, and automatically return 0 if we're not proposing a change. Signed-off-by: Glauber Costa Cc: Dhaval Giani Acked-by: Michal Hocko Cc: Kamezawa Hiroyuki Acked-by: Johannes Weiner Cc: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 55a85e1a342f..6d3dd54ec429 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3764,6 +3764,10 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft, parent_memcg = mem_cgroup_from_cont(parent); cgroup_lock(); + + if (memcg->use_hierarchy == val) + goto out; + /* * If parent's use_hierarchy is set, we can't make any modifications * in the child subtrees. If it is unset, then the change can @@ -3780,6 +3784,8 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft, retval = -EBUSY; } else retval = -EINVAL; + +out: cgroup_unlock(); return retval; -- GitLab From ab2158848775c7918288f2c423d3e4dbbc7d34eb Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:43:09 -0700 Subject: [PATCH 4903/5711] memcg: rename mem_control_xxx to memcg_xxx Replace memory_cgroup_xxx() with memcg_xxx() Signed-off-by: Wanpeng Li Acked-by: Johannes Weiner Acked-by: Michal Hocko Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6d3dd54ec429..b11fb2fe77c1 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4006,7 +4006,7 @@ static int mem_cgroup_move_charge_write(struct cgroup *cgrp, #endif #ifdef CONFIG_NUMA -static int mem_control_numa_stat_show(struct cgroup *cont, struct cftype *cft, +static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft, struct seq_file *m) { int nid; @@ -4065,7 +4065,7 @@ static inline void mem_cgroup_lru_names_not_uptodate(void) BUILD_BUG_ON(ARRAY_SIZE(mem_cgroup_lru_names) != NR_LRU_LISTS); } -static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, +static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, struct seq_file *m) { struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); @@ -4579,7 +4579,7 @@ static struct cftype mem_cgroup_files[] = { }, { .name = "stat", - .read_seq_string = mem_control_stat_show, + .read_seq_string = memcg_stat_show, }, { .name = "force_empty", @@ -4611,7 +4611,7 @@ static struct cftype mem_cgroup_files[] = { #ifdef CONFIG_NUMA { .name = "numa_stat", - .read_seq_string = mem_control_numa_stat_show, + .read_seq_string = memcg_numa_stat_show, }, #endif #ifdef CONFIG_MEMCG_SWAP -- GitLab From 7db8889ab05b57200158432755af318fb68854a2 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 31 Jul 2012 16:43:12 -0700 Subject: [PATCH 4904/5711] mm: have order > 0 compaction start off where it left Order > 0 compaction stops when enough free pages of the correct page order have been coalesced. When doing subsequent higher order allocations, it is possible for compaction to be invoked many times. However, the compaction code always starts out looking for things to compact at the start of the zone, and for free pages to compact things to at the end of the zone. This can cause quadratic behaviour, with isolate_freepages starting at the end of the zone each time, even though previous invocations of the compaction code already filled up all free memory on that end of the zone. This can cause isolate_freepages to take enormous amounts of CPU with certain workloads on larger memory systems. The obvious solution is to have isolate_freepages remember where it left off last time, and continue at that point the next time it gets invoked for an order > 0 compaction. This could cause compaction to fail if cc->free_pfn and cc->migrate_pfn are close together initially, in that case we restart from the end of the zone and try once more. Forced full (order == -1) compactions are left alone. [akpm@linux-foundation.org: checkpatch fixes] [akpm@linux-foundation.org: s/laste/last/, use 80 cols] Signed-off-by: Rik van Riel Reported-by: Jim Schutt Tested-by: Jim Schutt Cc: Minchan Kim Reviewed-by: KAMEZAWA Hiroyuki Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 4 +++ mm/compaction.c | 63 ++++++++++++++++++++++++++++++++++++++---- mm/internal.h | 6 ++++ mm/page_alloc.c | 5 ++++ 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 1495d952e641..1aeadce4d56e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -368,6 +368,10 @@ struct zone { */ spinlock_t lock; int all_unreclaimable; /* All pages pinned */ +#if defined CONFIG_COMPACTION || defined CONFIG_CMA + /* pfn where the last incremental compaction isolated free pages */ + unsigned long compact_cached_free_pfn; +#endif #ifdef CONFIG_MEMORY_HOTPLUG /* see spanned/present_pages for more description */ seqlock_t span_seqlock; diff --git a/mm/compaction.c b/mm/compaction.c index 2f42d9528539..e78cb9688421 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -422,6 +422,17 @@ static void isolate_freepages(struct zone *zone, pfn -= pageblock_nr_pages) { unsigned long isolated; + /* + * Skip ahead if another thread is compacting in the area + * simultaneously. If we wrapped around, we can only skip + * ahead if zone->compact_cached_free_pfn also wrapped to + * above our starting point. + */ + if (cc->order > 0 && (!cc->wrapped || + zone->compact_cached_free_pfn > + cc->start_free_pfn)) + pfn = min(pfn, zone->compact_cached_free_pfn); + if (!pfn_valid(pfn)) continue; @@ -461,8 +472,11 @@ static void isolate_freepages(struct zone *zone, * looking for free pages, the search will restart here as * page migration may have returned some pages to the allocator */ - if (isolated) + if (isolated) { high_pfn = max(high_pfn, pfn); + if (cc->order > 0) + zone->compact_cached_free_pfn = high_pfn; + } } /* split_free_page does not map the pages */ @@ -556,6 +570,20 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, return ISOLATE_SUCCESS; } +/* + * Returns the start pfn of the last page block in a zone. This is the starting + * point for full compaction of a zone. Compaction searches for free pages from + * the end of each zone, while isolate_freepages_block scans forward inside each + * page block. + */ +static unsigned long start_free_pfn(struct zone *zone) +{ + unsigned long free_pfn; + free_pfn = zone->zone_start_pfn + zone->spanned_pages; + free_pfn &= ~(pageblock_nr_pages-1); + return free_pfn; +} + static int compact_finished(struct zone *zone, struct compact_control *cc) { @@ -565,8 +593,26 @@ static int compact_finished(struct zone *zone, if (fatal_signal_pending(current)) return COMPACT_PARTIAL; - /* Compaction run completes if the migrate and free scanner meet */ - if (cc->free_pfn <= cc->migrate_pfn) + /* + * A full (order == -1) compaction run starts at the beginning and + * end of a zone; it completes when the migrate and free scanner meet. + * A partial (order > 0) compaction can start with the free scanner + * at a random point in the zone, and may have to restart. + */ + if (cc->free_pfn <= cc->migrate_pfn) { + if (cc->order > 0 && !cc->wrapped) { + /* We started partway through; restart at the end. */ + unsigned long free_pfn = start_free_pfn(zone); + zone->compact_cached_free_pfn = free_pfn; + cc->free_pfn = free_pfn; + cc->wrapped = 1; + return COMPACT_CONTINUE; + } + return COMPACT_COMPLETE; + } + + /* We wrapped around and ended up where we started. */ + if (cc->wrapped && cc->free_pfn <= cc->start_free_pfn) return COMPACT_COMPLETE; /* @@ -664,8 +710,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) /* Setup to move all movable pages to the end of the zone */ cc->migrate_pfn = zone->zone_start_pfn; - cc->free_pfn = cc->migrate_pfn + zone->spanned_pages; - cc->free_pfn &= ~(pageblock_nr_pages-1); + + if (cc->order > 0) { + /* Incremental compaction. Start where the last one stopped. */ + cc->free_pfn = zone->compact_cached_free_pfn; + cc->start_free_pfn = cc->free_pfn; + } else { + /* Order == -1 starts at the end of the zone. */ + cc->free_pfn = start_free_pfn(zone); + } migrate_prep_local(); diff --git a/mm/internal.h b/mm/internal.h index 2ba87fbfb75b..da6b9b2ed3fc 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -118,8 +118,14 @@ struct compact_control { unsigned long nr_freepages; /* Number of isolated free pages */ unsigned long nr_migratepages; /* Number of pages to migrate */ unsigned long free_pfn; /* isolate_freepages search base */ + unsigned long start_free_pfn; /* where we started the search */ unsigned long migrate_pfn; /* isolate_migratepages search base */ bool sync; /* Synchronous migration */ + bool wrapped; /* Order > 0 compactions are + incremental, once free_pfn + and migrate_pfn meet, we restart + from the top of the zone; + remember we wrapped around. */ int order; /* order a direct compactor needs */ int migratetype; /* MOVABLE, RECLAIMABLE etc */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index fba2a1223f14..94fc475c3f94 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4397,6 +4397,11 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, zone->spanned_pages = size; zone->present_pages = realsize; +#if defined CONFIG_COMPACTION || defined CONFIG_CMA + zone->compact_cached_free_pfn = zone->zone_start_pfn + + zone->spanned_pages; + zone->compact_cached_free_pfn &= ~(pageblock_nr_pages-1); +#endif #ifdef CONFIG_NUMA zone->node = nid; zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio) -- GitLab From fe03025db3f4ade1f231b174938e0fe224722759 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 31 Jul 2012 16:43:14 -0700 Subject: [PATCH 4905/5711] mm: CONFIG_HAVE_MEMBLOCK_NODE -> CONFIG_HAVE_MEMBLOCK_NODE_MAP 0ee332c14518699 ("memblock: Kill early_node_map[]") wanted to replace CONFIG_ARCH_POPULATES_NODE_MAP with CONFIG_HAVE_MEMBLOCK_NODE_MAP but ended up replacing one occurence with a reference to the non-existent symbol CONFIG_HAVE_MEMBLOCK_NODE. The resulting omission of code would probably have been causing problems to 32-bit machines with memory hotplug. Signed-off-by: Rabin Vincent Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 1aeadce4d56e..f64afa5929fe 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -776,7 +776,7 @@ extern int movable_zone; static inline int zone_movable_is_highmem(void) { -#if defined(CONFIG_HIGHMEM) && defined(CONFIG_HAVE_MEMBLOCK_NODE) +#if defined(CONFIG_HIGHMEM) && defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) return movable_zone == ZONE_HIGHMEM; #else return 0; -- GitLab From 8e125cd85517c9716695b0abfabc0a4a3fcb94f3 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:43:16 -0700 Subject: [PATCH 4906/5711] vmscan: remove obsolete shrink_control comment 09f363c7 ("vmscan: fix shrinker callback bug in fs/super.c") fixed a shrinker callback which was returning -1 when nr_to_scan is zero, which caused excessive slab scanning. But 635697c6 ("vmscan: fix initial shrinker size handling") fixed the problem, again so we can freely return -1 although nr_to_scan is zero. So let's revert 09f363c7 because the comment added in 09f363c7 made an unnecessary rule. Signed-off-by: Minchan Kim Cc: Al Viro Cc: Mikulas Patocka Cc: Konstantin Khlebnikov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/super.c | 2 +- include/linux/shrinker.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/super.c b/fs/super.c index 4c5d82f56ec4..4bf714459a4b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -62,7 +62,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) return -1; if (!grab_super_passive(sb)) - return !sc->nr_to_scan ? 0 : -1; + return -1; if (sb->s_op && sb->s_op->nr_cached_objects) fs_objects = sb->s_op->nr_cached_objects(sb); diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 07ceb97d53fa..ac6b8ee07825 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -20,7 +20,6 @@ struct shrink_control { * 'nr_to_scan' entries and attempt to free them up. It should return * the number of objects which remain in the cache. If it returns -1, it means * it cannot do any scanning at this time (eg. there is a risk of deadlock). - * The callback must not return -1 if nr_to_scan is zero. * * The 'gfpmask' refers to the allocation we are currently trying to * fulfil. -- GitLab From 51a07e50b230d14e1b8bef50d66655d003fa006c Mon Sep 17 00:00:00 2001 From: Jeff Liu Date: Tue, 31 Jul 2012 16:43:18 -0700 Subject: [PATCH 4907/5711] mm/memory.c:print_vma_addr(): call up_read(&mm->mmap_sem) directly Call up_read(&mm->mmap_sem) directly since we have already got mm via current->mm at the beginning of print_vma_addr(). Signed-off-by: Jie Liu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 59e5bebc2e35..ec72a616ccd4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3941,7 +3941,7 @@ void print_vma_addr(char *prefix, unsigned long ip) free_page((unsigned long)buf); } } - up_read(¤t->mm->mmap_sem); + up_read(&mm->mmap_sem); } #ifdef CONFIG_PROVE_LOCKING -- GitLab From ca57df79d4f64e1a4886606af4289d40636189c5 Mon Sep 17 00:00:00 2001 From: Xishi Qiu Date: Tue, 31 Jul 2012 16:43:19 -0700 Subject: [PATCH 4908/5711] mm: setup pageblock_order before it's used by sparsemem On architectures with CONFIG_HUGETLB_PAGE_SIZE_VARIABLE set, such as Itanium, pageblock_order is a variable with default value of 0. It's set to the right value by set_pageblock_order() in function free_area_init_core(). But pageblock_order may be used by sparse_init() before free_area_init_core() is called along path: sparse_init() ->sparse_early_usemaps_alloc_node() ->usemap_size() ->SECTION_BLOCKFLAGS_BITS ->((1UL << (PFN_SECTION_SHIFT - pageblock_order)) * NR_PAGEBLOCK_BITS) The uninitialized pageblock_size will cause memory wasting because usemap_size() returns a much bigger value then it's really needed. For example, on an Itanium platform, sparse_init() pageblock_order=0 usemap_size=24576 free_area_init_core() before pageblock_order=0, usemap_size=24576 free_area_init_core() after pageblock_order=12, usemap_size=8 That means 24K memory has been wasted for each section, so fix it by calling set_pageblock_order() from sparse_init(). Signed-off-by: Xishi Qiu Signed-off-by: Jiang Liu Cc: Tony Luck Cc: Yinghai Lu Cc: KAMEZAWA Hiroyuki Cc: Benjamin Herrenschmidt Cc: KOSAKI Motohiro Cc: David Rientjes Cc: Keping Chen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/internal.h | 2 ++ mm/page_alloc.c | 4 ++-- mm/sparse.c | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index da6b9b2ed3fc..3314f79d775a 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -353,3 +353,5 @@ extern u32 hwpoison_filter_enable; extern unsigned long vm_mmap_pgoff(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); + +extern void set_pageblock_order(void); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 94fc475c3f94..6c7e3bd93a85 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4304,7 +4304,7 @@ static inline void setup_usemap(struct pglist_data *pgdat, #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE /* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */ -static inline void __init set_pageblock_order(void) +void __init set_pageblock_order(void) { unsigned int order; @@ -4332,7 +4332,7 @@ static inline void __init set_pageblock_order(void) * include/linux/pageblock-flags.h for the values of pageblock_order based on * the kernel config */ -static inline void set_pageblock_order(void) +void __init set_pageblock_order(void) { } diff --git a/mm/sparse.c b/mm/sparse.c index c7bb952400c8..950981fd07c5 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -493,6 +493,9 @@ void __init sparse_init(void) struct page **map_map; #endif + /* Setup pageblock_order for HUGETLB_PAGE_SIZE_VARIABLE */ + set_pageblock_order(); + /* * map is using big page (aka 2M in x86 64 bit) * usemap is less one page (aka 24 bytes) -- GitLab From 05a73ed29a3aef4cf8d095ec5b08afecb959fa24 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:43:21 -0700 Subject: [PATCH 4909/5711] mm/memcg: complete documentation for tcp memcg files Signed-off-by: Wanpeng Li Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups/memory.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 672676ac9615..4372e6b8a353 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -73,6 +73,8 @@ Brief summary of control files. memory.kmem.tcp.limit_in_bytes # set/show hard limit for tcp buf memory memory.kmem.tcp.usage_in_bytes # show current tcp buf memory allocation + memory.kmem.tcp.failcnt # show the number of tcp buf memory usage hits limits + memory.kmem.tcp.max_usage_in_bytes # show max tcp buf memory usage recorded 1. History -- GitLab From aaad153e3408a4b8784de4c8446a40e70d57481f Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:43:23 -0700 Subject: [PATCH 4910/5711] mm/memcg: mem_cgroup_relize_xxx_limit can guarantee memcg->res.limit <= memcg->memsw.limit Signed-off-by: Wanpeng Li Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b11fb2fe77c1..ac87e79b00d1 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3416,7 +3416,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, /* * Rather than hide all in some function, I do this in * open coded manner. You see what this really does. - * We have to guarantee memcg->res.limit < memcg->memsw.limit. + * We have to guarantee memcg->res.limit <= memcg->memsw.limit. */ mutex_lock(&set_limit_mutex); memswlimit = res_counter_read_u64(&memcg->memsw, RES_LIMIT); @@ -3477,7 +3477,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, /* * Rather than hide all in some function, I do this in * open coded manner. You see what this really does. - * We have to guarantee memcg->res.limit < memcg->memsw.limit. + * We have to guarantee memcg->res.limit <= memcg->memsw.limit. */ mutex_lock(&set_limit_mutex); memlimit = res_counter_read_u64(&memcg->res, RES_LIMIT); -- GitLab From da92c47d069890106484cb6605df701a54d24499 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:43:26 -0700 Subject: [PATCH 4911/5711] mm/memcg: replace inexistence move_lock_page_cgroup() by move_lock_mem_cgroup() in comment Signed-off-by: Wanpeng Li Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ac87e79b00d1..4f73c823c59f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1898,7 +1898,7 @@ again: return; /* * If this memory cgroup is not under account moving, we don't - * need to take move_lock_page_cgroup(). Because we already hold + * need to take move_lock_mem_cgroup(). Because we already hold * rcu_read_lock(), any calls to move_account will be delayed until * rcu_read_unlock() if mem_cgroup_stolen() == true. */ @@ -1920,7 +1920,7 @@ void __mem_cgroup_end_update_page_stat(struct page *page, unsigned long *flags) /* * It's guaranteed that pc->mem_cgroup never changes while * lock is held because a routine modifies pc->mem_cgroup - * should take move_lock_page_cgroup(). + * should take move_lock_mem_cgroup(). */ move_unlock_mem_cgroup(pc->mem_cgroup, flags); } -- GitLab From 9adb62a5df9c0fbef7b4665919329f73a34651ed Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 31 Jul 2012 16:43:28 -0700 Subject: [PATCH 4912/5711] mm/hotplug: correctly setup fallback zonelists when creating new pgdat When hotadd_new_pgdat() is called to create new pgdat for a new node, a fallback zonelist should be created for the new node. There's code to try to achieve that in hotadd_new_pgdat() as below: /* * The node we allocated has no zone fallback lists. For avoiding * to access not-initialized zonelist, build here. */ mutex_lock(&zonelists_mutex); build_all_zonelists(pgdat, NULL); mutex_unlock(&zonelists_mutex); But it doesn't work as expected. When hotadd_new_pgdat() is called, the new node is still in offline state because node_set_online(nid) hasn't been called yet. And build_all_zonelists() only builds zonelists for online nodes as: for_each_online_node(nid) { pg_data_t *pgdat = NODE_DATA(nid); build_zonelists(pgdat); build_zonelist_cache(pgdat); } Though we hope to create zonelist for the new pgdat, but it doesn't. So add a new parameter "pgdat" the build_all_zonelists() to build pgdat for the new pgdat too. Signed-off-by: Jiang Liu Signed-off-by: Xishi Qiu Cc: Mel Gorman Cc: Michal Hocko Cc: Minchan Kim Cc: Rusty Russell Cc: Yinghai Lu Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: David Rientjes Cc: Keping Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 2 +- init/main.c | 2 +- kernel/cpu.c | 2 +- mm/memory_hotplug.c | 4 ++-- mm/page_alloc.c | 17 ++++++++++++----- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f64afa5929fe..98f079bcf399 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -721,7 +721,7 @@ typedef struct pglist_data { #include extern struct mutex zonelists_mutex; -void build_all_zonelists(void *data); +void build_all_zonelists(pg_data_t *pgdat, struct zone *zone); void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx); bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, int classzone_idx, int alloc_flags); diff --git a/init/main.c b/init/main.c index 95316a1b4a76..e60679de61c3 100644 --- a/init/main.c +++ b/init/main.c @@ -506,7 +506,7 @@ asmlinkage void __init start_kernel(void) setup_per_cpu_areas(); smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ - build_all_zonelists(NULL); + build_all_zonelists(NULL, NULL); page_alloc_init(); printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line); diff --git a/kernel/cpu.c b/kernel/cpu.c index a4eb5227a19e..14d32588cccd 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -416,7 +416,7 @@ int __cpuinit cpu_up(unsigned int cpu) if (pgdat->node_zonelists->_zonerefs->zone == NULL) { mutex_lock(&zonelists_mutex); - build_all_zonelists(NULL); + build_all_zonelists(NULL, NULL); mutex_unlock(&zonelists_mutex); } #endif diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 427bb291dd0f..b8731040b9f9 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -513,7 +513,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages) zone->present_pages += onlined_pages; zone->zone_pgdat->node_present_pages += onlined_pages; if (need_zonelists_rebuild) - build_all_zonelists(zone); + build_all_zonelists(NULL, zone); else zone_pcp_update(zone); @@ -562,7 +562,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) * to access not-initialized zonelist, build here. */ mutex_lock(&zonelists_mutex); - build_all_zonelists(NULL); + build_all_zonelists(pgdat, NULL); mutex_unlock(&zonelists_mutex); return pgdat; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6c7e3bd93a85..9ad6866ac49c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3032,7 +3032,7 @@ int numa_zonelist_order_handler(ctl_table *table, int write, user_zonelist_order = oldval; } else if (oldval != user_zonelist_order) { mutex_lock(&zonelists_mutex); - build_all_zonelists(NULL); + build_all_zonelists(NULL, NULL); mutex_unlock(&zonelists_mutex); } } @@ -3415,10 +3415,17 @@ static __init_refok int __build_all_zonelists(void *data) { int nid; int cpu; + pg_data_t *self = data; #ifdef CONFIG_NUMA memset(node_load, 0, sizeof(node_load)); #endif + + if (self && !node_online(self->node_id)) { + build_zonelists(self); + build_zonelist_cache(self); + } + for_each_online_node(nid) { pg_data_t *pgdat = NODE_DATA(nid); @@ -3463,7 +3470,7 @@ static __init_refok int __build_all_zonelists(void *data) * Called with zonelists_mutex held always * unless system_state == SYSTEM_BOOTING. */ -void __ref build_all_zonelists(void *data) +void __ref build_all_zonelists(pg_data_t *pgdat, struct zone *zone) { set_zonelist_order(); @@ -3475,10 +3482,10 @@ void __ref build_all_zonelists(void *data) /* we have to stop all cpus to guarantee there is no user of zonelist */ #ifdef CONFIG_MEMORY_HOTPLUG - if (data) - setup_zone_pageset((struct zone *)data); + if (zone) + setup_zone_pageset(zone); #endif - stop_machine(__build_all_zonelists, NULL, NULL); + stop_machine(__build_all_zonelists, pgdat, NULL); /* cpuset refresh routine should be here */ } vm_total_pages = nr_free_pagecache_pages(); -- GitLab From 08dff7b7d629807dbb1f398c68dd9cd58dd657a1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 31 Jul 2012 16:43:30 -0700 Subject: [PATCH 4913/5711] mm/hotplug: correctly add new zone to all other nodes' zone lists When online_pages() is called to add new memory to an empty zone, it rebuilds all zone lists by calling build_all_zonelists(). But there's a bug which prevents the new zone to be added to other nodes' zone lists. online_pages() { build_all_zonelists() ..... node_set_state(zone_to_nid(zone), N_HIGH_MEMORY) } Here the node of the zone is put into N_HIGH_MEMORY state after calling build_all_zonelists(), but build_all_zonelists() only adds zones from nodes in N_HIGH_MEMORY state to the fallback zone lists. build_all_zonelists() ->__build_all_zonelists() ->build_zonelists() ->find_next_best_node() ->for_each_node_state(n, N_HIGH_MEMORY) So memory in the new zone will never be used by other nodes, and it may cause strange behavor when system is under memory pressure. So put node into N_HIGH_MEMORY state before calling build_all_zonelists(). Signed-off-by: Jianguo Wu Signed-off-by: Jiang Liu Cc: Mel Gorman Cc: Michal Hocko Cc: Minchan Kim Cc: Rusty Russell Cc: Yinghai Lu Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: David Rientjes Cc: Keping Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index b8731040b9f9..597d371329d3 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -512,19 +512,20 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages) zone->present_pages += onlined_pages; zone->zone_pgdat->node_present_pages += onlined_pages; - if (need_zonelists_rebuild) - build_all_zonelists(NULL, zone); - else - zone_pcp_update(zone); + if (onlined_pages) { + node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); + if (need_zonelists_rebuild) + build_all_zonelists(NULL, zone); + else + zone_pcp_update(zone); + } mutex_unlock(&zonelists_mutex); init_per_zone_wmark_min(); - if (onlined_pages) { + if (onlined_pages) kswapd_run(zone_to_nid(zone)); - node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); - } vm_total_pages = nr_free_pagecache_pages(); -- GitLab From 340175b7d14d5617559d0c1a54fa0ea204d9edcd Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 31 Jul 2012 16:43:32 -0700 Subject: [PATCH 4914/5711] mm/hotplug: free zone->pageset when a zone becomes empty When a zone becomes empty after memory offlining, free zone->pageset. Otherwise it will cause memory leak when adding memory to the empty zone again because build_all_zonelists() will allocate zone->pageset for an empty zone. Signed-off-by: Jiang Liu Signed-off-by: Wei Wang Cc: Mel Gorman Cc: Michal Hocko Cc: Minchan Kim Cc: Rusty Russell Cc: Yinghai Lu Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: David Rientjes Cc: Keping Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/memory_hotplug.c | 3 +++ mm/page_alloc.c | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 3955bedeeed1..7c6dfd2faa69 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1331,6 +1331,7 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...); extern void setup_per_cpu_pageset(void); extern void zone_pcp_update(struct zone *zone); +extern void zone_pcp_reset(struct zone *zone); /* nommu.c */ extern atomic_long_t mmap_pages_allocated; diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 597d371329d3..3ad25f9d1fc1 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -966,6 +966,9 @@ repeat: init_per_zone_wmark_min(); + if (!populated_zone(zone)) + zone_pcp_reset(zone); + if (!node_present_pages(node)) { node_clear_state(node, N_HIGH_MEMORY); kswapd_stop(node); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9ad6866ac49c..9c9a31665a78 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5894,6 +5894,19 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages) #endif #ifdef CONFIG_MEMORY_HOTREMOVE +void zone_pcp_reset(struct zone *zone) +{ + unsigned long flags; + + /* avoid races with drain_pages() */ + local_irq_save(flags); + if (zone->pageset != &boot_pageset) { + free_percpu(zone->pageset); + zone->pageset = &boot_pageset; + } + local_irq_restore(flags); +} + /* * All pages in the range must be isolated before calling this. */ -- GitLab From 4ed7e02222aba062bd0ed3ab12dfc8e9fc0467b5 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 31 Jul 2012 16:43:35 -0700 Subject: [PATCH 4915/5711] mm/hotplug: mark memory hotplug code in page_alloc.c as __meminit Mark functions used by both boot and memory hotplug as __meminit to reduce memory footprint when memory hotplug is disabled. Alos guard zone_pcp_update() with CONFIG_MEMORY_HOTPLUG because it's only used by memory hotplug code. Signed-off-by: Jiang Liu Cc: Wei Wang Cc: Mel Gorman Cc: Michal Hocko Cc: Minchan Kim Cc: Rusty Russell Cc: Yinghai Lu Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: David Rientjes Cc: Keping Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 66 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9c9a31665a78..667338e80e94 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3411,7 +3411,7 @@ static void setup_zone_pageset(struct zone *zone); DEFINE_MUTEX(zonelists_mutex); /* return values int ....just for stop_machine() */ -static __init_refok int __build_all_zonelists(void *data) +static int __build_all_zonelists(void *data) { int nid; int cpu; @@ -3755,7 +3755,7 @@ static void __meminit zone_init_free_lists(struct zone *zone) memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) #endif -static int zone_batchsize(struct zone *zone) +static int __meminit zone_batchsize(struct zone *zone) { #ifdef CONFIG_MMU int batch; @@ -3837,7 +3837,7 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p, pcp->batch = PAGE_SHIFT * 8; } -static void setup_zone_pageset(struct zone *zone) +static void __meminit setup_zone_pageset(struct zone *zone) { int cpu; @@ -3910,33 +3910,6 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) return 0; } -static int __zone_pcp_update(void *data) -{ - struct zone *zone = data; - int cpu; - unsigned long batch = zone_batchsize(zone), flags; - - for_each_possible_cpu(cpu) { - struct per_cpu_pageset *pset; - struct per_cpu_pages *pcp; - - pset = per_cpu_ptr(zone->pageset, cpu); - pcp = &pset->pcp; - - local_irq_save(flags); - if (pcp->count > 0) - free_pcppages_bulk(zone, pcp->count, pcp); - setup_pageset(pset, batch); - local_irq_restore(flags); - } - return 0; -} - -void zone_pcp_update(struct zone *zone) -{ - stop_machine(__zone_pcp_update, zone, NULL); -} - static __meminit void zone_pcp_init(struct zone *zone) { /* @@ -3952,7 +3925,7 @@ static __meminit void zone_pcp_init(struct zone *zone) zone_batchsize(zone)); } -__meminit int init_currently_empty_zone(struct zone *zone, +int __meminit init_currently_empty_zone(struct zone *zone, unsigned long zone_start_pfn, unsigned long size, enum memmap_context context) @@ -4765,7 +4738,7 @@ out: } /* Any regular memory on that node ? */ -static void check_for_regular_memory(pg_data_t *pgdat) +static void __init check_for_regular_memory(pg_data_t *pgdat) { #ifdef CONFIG_HIGHMEM enum zone_type zone_type; @@ -5893,6 +5866,35 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages) } #endif +#ifdef CONFIG_MEMORY_HOTPLUG +static int __meminit __zone_pcp_update(void *data) +{ + struct zone *zone = data; + int cpu; + unsigned long batch = zone_batchsize(zone), flags; + + for_each_possible_cpu(cpu) { + struct per_cpu_pageset *pset; + struct per_cpu_pages *pcp; + + pset = per_cpu_ptr(zone->pageset, cpu); + pcp = &pset->pcp; + + local_irq_save(flags); + if (pcp->count > 0) + free_pcppages_bulk(zone, pcp->count, pcp); + setup_pageset(pset, batch); + local_irq_restore(flags); + } + return 0; +} + +void __meminit zone_pcp_update(struct zone *zone) +{ + stop_machine(__zone_pcp_update, zone, NULL); +} +#endif + #ifdef CONFIG_MEMORY_HOTREMOVE void zone_pcp_reset(struct zone *zone) { -- GitLab From 62ce1c706f817cb9defef3ac2dfdd815149f2968 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:43:39 -0700 Subject: [PATCH 4916/5711] mm, oom: move declaration for mem_cgroup_out_of_memory to oom.h mem_cgroup_out_of_memory() is defined in mm/oom_kill.c, so declare it in linux/oom.h rather than linux/memcontrol.h. Acked-by: KAMEZAWA Hiroyuki Acked-by: KOSAKI Motohiro Acked-by: Michal Hocko Signed-off-by: David Rientjes Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 2 -- include/linux/oom.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 170076222431..c0bff8976a69 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -72,8 +72,6 @@ extern void mem_cgroup_uncharge_end(void); extern void mem_cgroup_uncharge_page(struct page *page); extern void mem_cgroup_uncharge_cache_page(struct page *page); -extern void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, - int order); bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg, struct mem_cgroup *memcg); int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *memcg); diff --git a/include/linux/oom.h b/include/linux/oom.h index e4c29bc72e70..eb9dc14362c5 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -49,6 +49,8 @@ extern unsigned long oom_badness(struct task_struct *p, extern int try_set_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); +extern void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, + int order); extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order, nodemask_t *mask, bool force_kill); extern int register_oom_notifier(struct notifier_block *nb); -- GitLab From 462607ecc519b197f7b5cc6b024a1c26fa6fc0ac Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:43:40 -0700 Subject: [PATCH 4917/5711] mm, oom: introduce helper function to process threads during scan This patch introduces a helper function to process each thread during the iteration over the tasklist. A new return type, enum oom_scan_t, is defined to determine the future behavior of the iteration: - OOM_SCAN_OK: continue scanning the thread and find its badness, - OOM_SCAN_CONTINUE: do not consider this thread for oom kill, it's ineligible, - OOM_SCAN_ABORT: abort the iteration and return, or - OOM_SCAN_SELECT: always select this thread with the highest badness possible. There is no functional change with this patch. This new helper function will be used in the next patch in the memory controller. Reviewed-by: KAMEZAWA Hiroyuki Acked-by: KOSAKI Motohiro Reviewed-by: Michal Hocko Signed-off-by: David Rientjes Cc: Oleg Nesterov Reviewed-by: Sha Zhengju Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 111 +++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index e6c10640e56b..f8eba9651c0c 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -288,6 +288,59 @@ static enum oom_constraint constrained_alloc(struct zonelist *zonelist, } #endif +enum oom_scan_t { + OOM_SCAN_OK, /* scan thread and find its badness */ + OOM_SCAN_CONTINUE, /* do not consider thread for oom kill */ + OOM_SCAN_ABORT, /* abort the iteration and return */ + OOM_SCAN_SELECT, /* always select this thread first */ +}; + +static enum oom_scan_t oom_scan_process_thread(struct task_struct *task, + struct mem_cgroup *memcg, unsigned long totalpages, + const nodemask_t *nodemask, bool force_kill) +{ + if (task->exit_state) + return OOM_SCAN_CONTINUE; + if (oom_unkillable_task(task, memcg, nodemask)) + return OOM_SCAN_CONTINUE; + + /* + * This task already has access to memory reserves and is being killed. + * Don't allow any other task to have access to the reserves. + */ + if (test_tsk_thread_flag(task, TIF_MEMDIE)) { + if (unlikely(frozen(task))) + __thaw_task(task); + if (!force_kill) + return OOM_SCAN_ABORT; + } + if (!task->mm) + return OOM_SCAN_CONTINUE; + + if (task->flags & PF_EXITING) { + /* + * If task is current and is in the process of releasing memory, + * allow the "kill" to set TIF_MEMDIE, which will allow it to + * access memory reserves. Otherwise, it may stall forever. + * + * The iteration isn't broken here, however, in case other + * threads are found to have already been oom killed. + */ + if (task == current) + return OOM_SCAN_SELECT; + else if (!force_kill) { + /* + * If this task is not being ptraced on exit, then wait + * for it to finish before killing some other task + * unnecessarily. + */ + if (!(task->group_leader->ptrace & PT_TRACE_EXIT)) + return OOM_SCAN_ABORT; + } + } + return OOM_SCAN_OK; +} + /* * Simple selection loop. We chose the process with the highest * number of 'points'. We expect the caller will lock the tasklist. @@ -305,53 +358,19 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, do_each_thread(g, p) { unsigned int points; - if (p->exit_state) - continue; - if (oom_unkillable_task(p, memcg, nodemask)) - continue; - - /* - * This task already has access to memory reserves and is - * being killed. Don't allow any other task access to the - * memory reserve. - * - * Note: this may have a chance of deadlock if it gets - * blocked waiting for another task which itself is waiting - * for memory. Is there a better alternative? - */ - if (test_tsk_thread_flag(p, TIF_MEMDIE)) { - if (unlikely(frozen(p))) - __thaw_task(p); - if (!force_kill) - return ERR_PTR(-1UL); - } - if (!p->mm) + switch (oom_scan_process_thread(p, memcg, totalpages, nodemask, + force_kill)) { + case OOM_SCAN_SELECT: + chosen = p; + chosen_points = ULONG_MAX; + /* fall through */ + case OOM_SCAN_CONTINUE: continue; - - if (p->flags & PF_EXITING) { - /* - * If p is the current task and is in the process of - * releasing memory, we allow the "kill" to set - * TIF_MEMDIE, which will allow it to gain access to - * memory reserves. Otherwise, it may stall forever. - * - * The loop isn't broken here, however, in case other - * threads are found to have already been oom killed. - */ - if (p == current) { - chosen = p; - chosen_points = ULONG_MAX; - } else if (!force_kill) { - /* - * If this task is not being ptraced on exit, - * then wait for it to finish before killing - * some other task unnecessarily. - */ - if (!(p->group_leader->ptrace & PT_TRACE_EXIT)) - return ERR_PTR(-1UL); - } - } - + case OOM_SCAN_ABORT: + return ERR_PTR(-1UL); + case OOM_SCAN_OK: + break; + }; points = oom_badness(p, memcg, nodemask, totalpages); if (points > chosen_points) { chosen = p; -- GitLab From 9cbb78bb314360a860a8b23723971cb6fcb54176 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:43:44 -0700 Subject: [PATCH 4918/5711] mm, memcg: introduce own oom handler to iterate only over its own threads The global oom killer is serialized by the per-zonelist try_set_zonelist_oom() which is used in the page allocator. Concurrent oom kills are thus a rare event and only occur in systems using mempolicies and with a large number of nodes. Memory controller oom kills, however, can frequently be concurrent since there is no serialization once the oom killer is called for oom conditions in several different memcgs in parallel. This creates a massive contention on tasklist_lock since the oom killer requires the readside for the tasklist iteration. If several memcgs are calling the oom killer, this lock can be held for a substantial amount of time, especially if threads continue to enter it as other threads are exiting. Since the exit path grabs the writeside of the lock with irqs disabled in a few different places, this can cause a soft lockup on cpus as a result of tasklist_lock starvation. The kernel lacks unfair writelocks, and successful calls to the oom killer usually result in at least one thread entering the exit path, so an alternative solution is needed. This patch introduces a seperate oom handler for memcgs so that they do not require tasklist_lock for as much time. Instead, it iterates only over the threads attached to the oom memcg and grabs a reference to the selected thread before calling oom_kill_process() to ensure it doesn't prematurely exit. This still requires tasklist_lock for the tasklist dump, iterating children of the selected process, and killing all other threads on the system sharing the same memory as the selected victim. So while this isn't a complete solution to tasklist_lock starvation, it significantly reduces the amount of time that it is held. Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Signed-off-by: David Rientjes Cc: Oleg Nesterov Cc: KOSAKI Motohiro Reviewed-by: Sha Zhengju Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 9 ++---- include/linux/oom.h | 16 ++++++++++ mm/memcontrol.c | 61 +++++++++++++++++++++++++++++++++++++- mm/oom_kill.c | 48 ++++++++++-------------------- 4 files changed, 93 insertions(+), 41 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index c0bff8976a69..2a80544aec99 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -180,7 +180,8 @@ static inline void mem_cgroup_dec_page_stat(struct page *page, unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, gfp_t gfp_mask, unsigned long *total_scanned); -u64 mem_cgroup_get_limit(struct mem_cgroup *memcg); +extern void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, + int order); void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -364,12 +365,6 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, return 0; } -static inline -u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) -{ - return 0; -} - static inline void mem_cgroup_split_huge_fixup(struct page *head) { } diff --git a/include/linux/oom.h b/include/linux/oom.h index eb9dc14362c5..5dc0e384ae9e 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -40,17 +40,33 @@ enum oom_constraint { CONSTRAINT_MEMCG, }; +enum oom_scan_t { + OOM_SCAN_OK, /* scan thread and find its badness */ + OOM_SCAN_CONTINUE, /* do not consider thread for oom kill */ + OOM_SCAN_ABORT, /* abort the iteration and return */ + OOM_SCAN_SELECT, /* always select this thread first */ +}; + extern void compare_swap_oom_score_adj(int old_val, int new_val); extern int test_set_oom_score_adj(int new_val); extern unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, const nodemask_t *nodemask, unsigned long totalpages); +extern void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, + unsigned int points, unsigned long totalpages, + struct mem_cgroup *memcg, nodemask_t *nodemask, + const char *message); + extern int try_set_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); +extern enum oom_scan_t oom_scan_process_thread(struct task_struct *task, + unsigned long totalpages, const nodemask_t *nodemask, + bool force_kill); extern void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, int order); + extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order, nodemask_t *mask, bool force_kill); extern int register_oom_notifier(struct notifier_block *nb); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 4f73c823c59f..b78972e2f43f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1453,7 +1453,7 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) /* * Return the memory (and swap, if configured) limit for a memcg. */ -u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) +static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) { u64 limit; u64 memsw; @@ -1469,6 +1469,65 @@ u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) return min(limit, memsw); } +void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, + int order) +{ + struct mem_cgroup *iter; + unsigned long chosen_points = 0; + unsigned long totalpages; + unsigned int points = 0; + struct task_struct *chosen = NULL; + + totalpages = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1; + for_each_mem_cgroup_tree(iter, memcg) { + struct cgroup *cgroup = iter->css.cgroup; + struct cgroup_iter it; + struct task_struct *task; + + cgroup_iter_start(cgroup, &it); + while ((task = cgroup_iter_next(cgroup, &it))) { + switch (oom_scan_process_thread(task, totalpages, NULL, + false)) { + case OOM_SCAN_SELECT: + if (chosen) + put_task_struct(chosen); + chosen = task; + chosen_points = ULONG_MAX; + get_task_struct(chosen); + /* fall through */ + case OOM_SCAN_CONTINUE: + continue; + case OOM_SCAN_ABORT: + cgroup_iter_end(cgroup, &it); + mem_cgroup_iter_break(memcg, iter); + if (chosen) + put_task_struct(chosen); + return; + case OOM_SCAN_OK: + break; + }; + points = oom_badness(task, memcg, NULL, totalpages); + if (points > chosen_points) { + if (chosen) + put_task_struct(chosen); + chosen = task; + chosen_points = points; + get_task_struct(chosen); + } + } + cgroup_iter_end(cgroup, &it); + } + + if (!chosen) + return; + points = chosen_points * 1000 / totalpages; + read_lock(&tasklist_lock); + oom_kill_process(chosen, gfp_mask, order, points, totalpages, memcg, + NULL, "Memory cgroup out of memory"); + read_unlock(&tasklist_lock); + put_task_struct(chosen); +} + static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg, gfp_t gfp_mask, unsigned long flags) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index f8eba9651c0c..c0c97aea837f 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -288,20 +288,13 @@ static enum oom_constraint constrained_alloc(struct zonelist *zonelist, } #endif -enum oom_scan_t { - OOM_SCAN_OK, /* scan thread and find its badness */ - OOM_SCAN_CONTINUE, /* do not consider thread for oom kill */ - OOM_SCAN_ABORT, /* abort the iteration and return */ - OOM_SCAN_SELECT, /* always select this thread first */ -}; - -static enum oom_scan_t oom_scan_process_thread(struct task_struct *task, - struct mem_cgroup *memcg, unsigned long totalpages, - const nodemask_t *nodemask, bool force_kill) +enum oom_scan_t oom_scan_process_thread(struct task_struct *task, + unsigned long totalpages, const nodemask_t *nodemask, + bool force_kill) { if (task->exit_state) return OOM_SCAN_CONTINUE; - if (oom_unkillable_task(task, memcg, nodemask)) + if (oom_unkillable_task(task, NULL, nodemask)) return OOM_SCAN_CONTINUE; /* @@ -348,8 +341,8 @@ static enum oom_scan_t oom_scan_process_thread(struct task_struct *task, * (not docbooked, we don't want this one cluttering up the manual) */ static struct task_struct *select_bad_process(unsigned int *ppoints, - unsigned long totalpages, struct mem_cgroup *memcg, - const nodemask_t *nodemask, bool force_kill) + unsigned long totalpages, const nodemask_t *nodemask, + bool force_kill) { struct task_struct *g, *p; struct task_struct *chosen = NULL; @@ -358,7 +351,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, do_each_thread(g, p) { unsigned int points; - switch (oom_scan_process_thread(p, memcg, totalpages, nodemask, + switch (oom_scan_process_thread(p, totalpages, nodemask, force_kill)) { case OOM_SCAN_SELECT: chosen = p; @@ -371,7 +364,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, case OOM_SCAN_OK: break; }; - points = oom_badness(p, memcg, nodemask, totalpages); + points = oom_badness(p, NULL, nodemask, totalpages); if (points > chosen_points) { chosen = p; chosen_points = points; @@ -443,10 +436,10 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, } #define K(x) ((x) << (PAGE_SHIFT-10)) -static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, - unsigned int points, unsigned long totalpages, - struct mem_cgroup *memcg, nodemask_t *nodemask, - const char *message) +void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, + unsigned int points, unsigned long totalpages, + struct mem_cgroup *memcg, nodemask_t *nodemask, + const char *message) { struct task_struct *victim = p; struct task_struct *child; @@ -564,10 +557,6 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, int order) { - unsigned long limit; - unsigned int points = 0; - struct task_struct *p; - /* * If current has a pending SIGKILL, then automatically select it. The * goal is to allow it to allocate so that it may quickly exit and free @@ -579,13 +568,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, } check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL); - limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1; - read_lock(&tasklist_lock); - p = select_bad_process(&points, limit, memcg, NULL, false); - if (p && PTR_ERR(p) != -1UL) - oom_kill_process(p, gfp_mask, order, points, limit, memcg, NULL, - "Memory cgroup out of memory"); - read_unlock(&tasklist_lock); + __mem_cgroup_out_of_memory(memcg, gfp_mask, order); } #endif @@ -710,7 +693,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, struct task_struct *p; unsigned long totalpages; unsigned long freed = 0; - unsigned int points; + unsigned int uninitialized_var(points); enum oom_constraint constraint = CONSTRAINT_NONE; int killed = 0; @@ -748,8 +731,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, goto out; } - p = select_bad_process(&points, totalpages, NULL, mpol_mask, - force_kill); + p = select_bad_process(&points, totalpages, mpol_mask, force_kill); /* Found nothing?!?! Either we hang forever, or we panic. */ if (!p) { dump_header(NULL, gfp_mask, order, NULL, mpol_mask); -- GitLab From 6b0c81b3be114a93f79bd4c5639ade5107d77c21 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:43:45 -0700 Subject: [PATCH 4919/5711] mm, oom: reduce dependency on tasklist_lock Since exiting tasks require write_lock_irq(&tasklist_lock) several times, try to reduce the amount of time the readside is held for oom kills. This makes the interface with the memcg oom handler more consistent since it now never needs to take tasklist_lock unnecessarily. The only time the oom killer now takes tasklist_lock is when iterating the children of the selected task, everything else is protected by rcu_read_lock(). This requires that a reference to the selected process, p, is grabbed before calling oom_kill_process(). It may release it and grab a reference on another one of p's threads if !p->mm, but it also guarantees that it will release the reference before returning. [hughd@google.com: fix duplicate put_task_struct()] Signed-off-by: David Rientjes Cc: KAMEZAWA Hiroyuki Reviewed-by: Michal Hocko Cc: Oleg Nesterov Cc: KOSAKI Motohiro Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 3 --- mm/oom_kill.c | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b78972e2f43f..77a29cea5d76 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1521,11 +1521,8 @@ void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, if (!chosen) return; points = chosen_points * 1000 / totalpages; - read_lock(&tasklist_lock); oom_kill_process(chosen, gfp_mask, order, points, totalpages, memcg, NULL, "Memory cgroup out of memory"); - read_unlock(&tasklist_lock); - put_task_struct(chosen); } static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg, diff --git a/mm/oom_kill.c b/mm/oom_kill.c index c0c97aea837f..a3a32ae02e9d 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -336,7 +336,7 @@ enum oom_scan_t oom_scan_process_thread(struct task_struct *task, /* * Simple selection loop. We chose the process with the highest - * number of 'points'. We expect the caller will lock the tasklist. + * number of 'points'. * * (not docbooked, we don't want this one cluttering up the manual) */ @@ -348,6 +348,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, struct task_struct *chosen = NULL; unsigned long chosen_points = 0; + rcu_read_lock(); do_each_thread(g, p) { unsigned int points; @@ -360,6 +361,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, case OOM_SCAN_CONTINUE: continue; case OOM_SCAN_ABORT: + rcu_read_unlock(); return ERR_PTR(-1UL); case OOM_SCAN_OK: break; @@ -370,6 +372,9 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, chosen_points = points; } } while_each_thread(g, p); + if (chosen) + get_task_struct(chosen); + rcu_read_unlock(); *ppoints = chosen_points * 1000 / totalpages; return chosen; @@ -385,8 +390,6 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, * are not shown. * State information includes task's pid, uid, tgid, vm size, rss, nr_ptes, * swapents, oom_score_adj value, and name. - * - * Call with tasklist_lock read-locked. */ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemask) { @@ -394,6 +397,7 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas struct task_struct *task; pr_info("[ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name\n"); + rcu_read_lock(); for_each_process(p) { if (oom_unkillable_task(p, memcg, nodemask)) continue; @@ -416,6 +420,7 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas task->signal->oom_score_adj, task->comm); task_unlock(task); } + rcu_read_unlock(); } static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, @@ -436,6 +441,10 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, } #define K(x) ((x) << (PAGE_SHIFT-10)) +/* + * Must be called while holding a reference to p, which will be released upon + * returning. + */ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, unsigned int points, unsigned long totalpages, struct mem_cgroup *memcg, nodemask_t *nodemask, @@ -455,6 +464,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, */ if (p->flags & PF_EXITING) { set_tsk_thread_flag(p, TIF_MEMDIE); + put_task_struct(p); return; } @@ -472,6 +482,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, * parent. This attempts to lose the minimal amount of work done while * still freeing memory. */ + read_lock(&tasklist_lock); do { list_for_each_entry(child, &t->children, sibling) { unsigned int child_points; @@ -484,15 +495,26 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, child_points = oom_badness(child, memcg, nodemask, totalpages); if (child_points > victim_points) { + put_task_struct(victim); victim = child; victim_points = child_points; + get_task_struct(victim); } } } while_each_thread(p, t); + read_unlock(&tasklist_lock); - victim = find_lock_task_mm(victim); - if (!victim) + rcu_read_lock(); + p = find_lock_task_mm(victim); + if (!p) { + rcu_read_unlock(); + put_task_struct(victim); return; + } else if (victim != p) { + get_task_struct(p); + put_task_struct(victim); + victim = p; + } /* mm cannot safely be dereferenced after task_unlock(victim) */ mm = victim->mm; @@ -523,9 +545,11 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, task_unlock(p); do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true); } + rcu_read_unlock(); set_tsk_thread_flag(victim, TIF_MEMDIE); do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true); + put_task_struct(victim); } #undef K @@ -546,9 +570,7 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, if (constraint != CONSTRAINT_NONE) return; } - read_lock(&tasklist_lock); dump_header(NULL, gfp_mask, order, NULL, nodemask); - read_unlock(&tasklist_lock); panic("Out of memory: %s panic_on_oom is enabled\n", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } @@ -721,10 +743,10 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, mpol_mask = (constraint == CONSTRAINT_MEMORY_POLICY) ? nodemask : NULL; check_panic_on_oom(constraint, gfp_mask, order, mpol_mask); - read_lock(&tasklist_lock); if (sysctl_oom_kill_allocating_task && current->mm && !oom_unkillable_task(current, NULL, nodemask) && current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { + get_task_struct(current); oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL, nodemask, "Out of memory (oom_kill_allocating_task)"); @@ -735,7 +757,6 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, /* Found nothing?!?! Either we hang forever, or we panic. */ if (!p) { dump_header(NULL, gfp_mask, order, NULL, mpol_mask); - read_unlock(&tasklist_lock); panic("Out of memory and no killable processes...\n"); } if (PTR_ERR(p) != -1UL) { @@ -744,8 +765,6 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, killed = 1; } out: - read_unlock(&tasklist_lock); - /* * Give the killed threads a good chance of exiting before trying to * allocate memory again. -- GitLab From 876aafbfd9ba5bb352f1b14622c27f3fe9a99013 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 31 Jul 2012 16:43:48 -0700 Subject: [PATCH 4920/5711] mm, memcg: move all oom handling to memcontrol.c By globally defining check_panic_on_oom(), the memcg oom handler can be moved entirely to mm/memcontrol.c. This removes the ugly #ifdef in the oom killer and cleans up the code. Signed-off-by: David Rientjes Cc: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: Oleg Nesterov Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 2 -- include/linux/oom.h | 3 +++ mm/memcontrol.c | 15 +++++++++++++-- mm/oom_kill.c | 23 ++--------------------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 2a80544aec99..5a3ee6423634 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -180,8 +180,6 @@ static inline void mem_cgroup_dec_page_stat(struct page *page, unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, gfp_t gfp_mask, unsigned long *total_scanned); -extern void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, - int order); void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); #ifdef CONFIG_TRANSPARENT_HUGEPAGE diff --git a/include/linux/oom.h b/include/linux/oom.h index 5dc0e384ae9e..49a3031fda50 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -61,6 +61,9 @@ extern void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, extern int try_set_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); +extern void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, + int order, const nodemask_t *nodemask); + extern enum oom_scan_t oom_scan_process_thread(struct task_struct *task, unsigned long totalpages, const nodemask_t *nodemask, bool force_kill); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 77a29cea5d76..0f692a2dbfcb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1469,8 +1469,8 @@ static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) return min(limit, memsw); } -void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, - int order) +void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, + int order) { struct mem_cgroup *iter; unsigned long chosen_points = 0; @@ -1478,6 +1478,17 @@ void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, unsigned int points = 0; struct task_struct *chosen = NULL; + /* + * If current has a pending SIGKILL, then automatically select it. The + * goal is to allow it to allocate so that it may quickly exit and free + * its memory. + */ + if (fatal_signal_pending(current)) { + set_thread_flag(TIF_MEMDIE); + return; + } + + check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL); totalpages = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1; for_each_mem_cgroup_tree(iter, memcg) { struct cgroup *cgroup = iter->css.cgroup; diff --git a/mm/oom_kill.c b/mm/oom_kill.c index a3a32ae02e9d..198600861638 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -556,8 +556,8 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, /* * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ -static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, - int order, const nodemask_t *nodemask) +void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, + int order, const nodemask_t *nodemask) { if (likely(!sysctl_panic_on_oom)) return; @@ -575,25 +575,6 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } -#ifdef CONFIG_MEMCG -void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, - int order) -{ - /* - * If current has a pending SIGKILL, then automatically select it. The - * goal is to allow it to allocate so that it may quickly exit and free - * its memory. - */ - if (fatal_signal_pending(current)) { - set_thread_flag(TIF_MEMDIE); - return; - } - - check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL); - __mem_cgroup_out_of_memory(memcg, gfp_mask, order); -} -#endif - static BLOCKING_NOTIFIER_HEAD(oom_notify_list); int register_oom_notifier(struct notifier_block *nb) -- GitLab From ee6f509c3274014d1f52e7a7a10aee9f85393c5e Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:43:50 -0700 Subject: [PATCH 4921/5711] mm: factor out memory isolate functions mm/page_alloc.c has some memory isolation functions but they are used only when we enable CONFIG_{CMA|MEMORY_HOTPLUG|MEMORY_FAILURE}. So let's make it configurable by new CONFIG_MEMORY_ISOLATION so that it can reduce binary size and we can check it simple by CONFIG_MEMORY_ISOLATION, not if defined CONFIG_{CMA|MEMORY_HOTPLUG|MEMORY_FAILURE}. Signed-off-by: Minchan Kim Cc: Andi Kleen Cc: Marek Szyprowski Acked-by: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: Mel Gorman Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/Kconfig | 1 + include/linux/page-isolation.h | 13 ++++-- mm/Kconfig | 5 +++ mm/Makefile | 5 ++- mm/page_alloc.c | 80 ++-------------------------------- mm/page_isolation.c | 71 ++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 82 deletions(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 9b21469482ae..08b4c5209384 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -196,6 +196,7 @@ config CMA bool "Contiguous Memory Allocator (EXPERIMENTAL)" depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL select MIGRATION + select MEMORY_ISOLATION help This enables the Contiguous Memory Allocator which allows drivers to allocate big physically-contiguous blocks of memory for use with diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h index 3bdcab30ca41..105077aa7685 100644 --- a/include/linux/page-isolation.h +++ b/include/linux/page-isolation.h @@ -1,6 +1,11 @@ #ifndef __LINUX_PAGEISOLATION_H #define __LINUX_PAGEISOLATION_H + +bool has_unmovable_pages(struct zone *zone, struct page *page, int count); +void set_pageblock_migratetype(struct page *page, int migratetype); +int move_freepages_block(struct zone *zone, struct page *page, + int migratetype); /* * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE. * If specified range includes migrate types other than MOVABLE or CMA, @@ -10,7 +15,7 @@ * free all pages in the range. test_page_isolated() can be used for * test it. */ -extern int +int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, unsigned migratetype); @@ -18,7 +23,7 @@ start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. * target range is [start_pfn, end_pfn) */ -extern int +int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, unsigned migratetype); @@ -30,8 +35,8 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn); /* * Internal functions. Changes pageblock's migrate type. */ -extern int set_migratetype_isolate(struct page *page); -extern void unset_migratetype_isolate(struct page *page, unsigned migratetype); +int set_migratetype_isolate(struct page *page); +void unset_migratetype_isolate(struct page *page, unsigned migratetype); #endif diff --git a/mm/Kconfig b/mm/Kconfig index 82fed4eb2b6f..d5c8019c6627 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -140,9 +140,13 @@ config ARCH_DISCARD_MEMBLOCK config NO_BOOTMEM boolean +config MEMORY_ISOLATION + boolean + # eventually, we can have this option just 'select SPARSEMEM' config MEMORY_HOTPLUG bool "Allow for memory hot-add" + select MEMORY_ISOLATION depends on SPARSEMEM || X86_64_ACPI_NUMA depends on HOTPLUG && ARCH_ENABLE_MEMORY_HOTPLUG depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390) @@ -272,6 +276,7 @@ config MEMORY_FAILURE depends on MMU depends on ARCH_SUPPORTS_MEMORY_FAILURE bool "Enable recovery from hardware memory errors" + select MEMORY_ISOLATION help Enables code to recover from some memory failures on systems with MCA recovery. This allows a system to continue running diff --git a/mm/Makefile b/mm/Makefile index 290bbfe33698..92753e2d82da 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -15,8 +15,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ maccess.o page_alloc.o page-writeback.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ - page_isolation.o mm_init.o mmu_context.o percpu.o \ - compaction.o slab_common.o $(mmu-y) + mm_init.o mmu_context.o percpu.o slab_common.o \ + compaction.o $(mmu-y) obj-y += init-mm.o @@ -56,3 +56,4 @@ obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o obj-$(CONFIG_CLEANCACHE) += cleancache.o +obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 667338e80e94..228194728ccd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -219,7 +218,7 @@ EXPORT_SYMBOL(nr_online_nodes); int page_group_by_mobility_disabled __read_mostly; -static void set_pageblock_migratetype(struct page *page, int migratetype) +void set_pageblock_migratetype(struct page *page, int migratetype) { if (unlikely(page_group_by_mobility_disabled)) @@ -954,7 +953,7 @@ static int move_freepages(struct zone *zone, return pages_moved; } -static int move_freepages_block(struct zone *zone, struct page *page, +int move_freepages_block(struct zone *zone, struct page *page, int migratetype) { unsigned long start_pfn, end_pfn; @@ -5463,8 +5462,7 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, * MIGRATE_MOVABLE block might include unmovable pages. It means you can't * expect this function should be exact. */ -static bool -__has_unmovable_pages(struct zone *zone, struct page *page, int count) +bool has_unmovable_pages(struct zone *zone, struct page *page, int count) { unsigned long pfn, iter, found; int mt; @@ -5541,77 +5539,7 @@ bool is_pageblock_removable_nolock(struct page *page) zone->zone_start_pfn + zone->spanned_pages <= pfn) return false; - return !__has_unmovable_pages(zone, page, 0); -} - -int set_migratetype_isolate(struct page *page) -{ - struct zone *zone; - unsigned long flags, pfn; - struct memory_isolate_notify arg; - int notifier_ret; - int ret = -EBUSY; - - zone = page_zone(page); - - spin_lock_irqsave(&zone->lock, flags); - - pfn = page_to_pfn(page); - arg.start_pfn = pfn; - arg.nr_pages = pageblock_nr_pages; - arg.pages_found = 0; - - /* - * It may be possible to isolate a pageblock even if the - * migratetype is not MIGRATE_MOVABLE. The memory isolation - * notifier chain is used by balloon drivers to return the - * number of pages in a range that are held by the balloon - * driver to shrink memory. If all the pages are accounted for - * by balloons, are free, or on the LRU, isolation can continue. - * Later, for example, when memory hotplug notifier runs, these - * pages reported as "can be isolated" should be isolated(freed) - * by the balloon driver through the memory notifier chain. - */ - notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); - notifier_ret = notifier_to_errno(notifier_ret); - if (notifier_ret) - goto out; - /* - * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. - * We just check MOVABLE pages. - */ - if (!__has_unmovable_pages(zone, page, arg.pages_found)) - ret = 0; - /* - * Unmovable means "not-on-lru" pages. If Unmovable pages are - * larger than removable-by-driver pages reported by notifier, - * we'll fail. - */ - -out: - if (!ret) { - set_pageblock_migratetype(page, MIGRATE_ISOLATE); - move_freepages_block(zone, page, MIGRATE_ISOLATE); - } - - spin_unlock_irqrestore(&zone->lock, flags); - if (!ret) - drain_all_pages(); - return ret; -} - -void unset_migratetype_isolate(struct page *page, unsigned migratetype) -{ - struct zone *zone; - unsigned long flags; - zone = page_zone(page); - spin_lock_irqsave(&zone->lock, flags); - if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) - goto out; - set_pageblock_migratetype(page, migratetype); - move_freepages_block(zone, page, migratetype); -out: - spin_unlock_irqrestore(&zone->lock, flags); + return !has_unmovable_pages(zone, page, 0); } #ifdef CONFIG_CMA diff --git a/mm/page_isolation.c b/mm/page_isolation.c index c9f04774f2b8..fb482cf438da 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -5,8 +5,79 @@ #include #include #include +#include #include "internal.h" +int set_migratetype_isolate(struct page *page) +{ + struct zone *zone; + unsigned long flags, pfn; + struct memory_isolate_notify arg; + int notifier_ret; + int ret = -EBUSY; + + zone = page_zone(page); + + spin_lock_irqsave(&zone->lock, flags); + + pfn = page_to_pfn(page); + arg.start_pfn = pfn; + arg.nr_pages = pageblock_nr_pages; + arg.pages_found = 0; + + /* + * It may be possible to isolate a pageblock even if the + * migratetype is not MIGRATE_MOVABLE. The memory isolation + * notifier chain is used by balloon drivers to return the + * number of pages in a range that are held by the balloon + * driver to shrink memory. If all the pages are accounted for + * by balloons, are free, or on the LRU, isolation can continue. + * Later, for example, when memory hotplug notifier runs, these + * pages reported as "can be isolated" should be isolated(freed) + * by the balloon driver through the memory notifier chain. + */ + notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); + notifier_ret = notifier_to_errno(notifier_ret); + if (notifier_ret) + goto out; + /* + * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. + * We just check MOVABLE pages. + */ + if (!has_unmovable_pages(zone, page, arg.pages_found)) + ret = 0; + + /* + * immobile means "not-on-lru" paes. If immobile is larger than + * removable-by-driver pages reported by notifier, we'll fail. + */ + +out: + if (!ret) { + set_pageblock_migratetype(page, MIGRATE_ISOLATE); + move_freepages_block(zone, page, MIGRATE_ISOLATE); + } + + spin_unlock_irqrestore(&zone->lock, flags); + if (!ret) + drain_all_pages(); + return ret; +} + +void unset_migratetype_isolate(struct page *page, unsigned migratetype) +{ + struct zone *zone; + unsigned long flags; + zone = page_zone(page); + spin_lock_irqsave(&zone->lock, flags); + if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) + goto out; + set_pageblock_migratetype(page, migratetype); + move_freepages_block(zone, page, migratetype); +out: + spin_unlock_irqrestore(&zone->lock, flags); +} + static inline struct page * __first_valid_page(unsigned long pfn, unsigned long nr_pages) { -- GitLab From 2cfed0752808625d30aca7fc9f383af386fd8a13 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:43:53 -0700 Subject: [PATCH 4922/5711] mm: fix free page check in zone_watermark_ok() __zone_watermark_ok currently compares free_pages which is a signed type with z->lowmem_reserve[classzone_idx] which is unsigned which might lead to sign overflow if free_pages doesn't satisfy the given order (or it came as negative already) and then we rely on the following order loop to fix it (which doesn't work for order-0). Let's fix the type conversion and do not rely on the given value of free_pages or follow up fixups. This patch fixes it because "memory-hotplug: fix kswapd looping forever problem" depends on this. As benefit of this patch, it doesn't rely on the loop to exit __zone_watermark_ok in case of high order check and make the first test effective.(ie, if (free_pages <= min + lowmem_reserve)) Aaditya reported this problem when he test my hotplug patch. Reported-off-by: Aaditya Kumar Tested-by: Aaditya Kumar Signed-off-by: Aaditya Kumar Signed-off-by: Minchan Kim Cc: KOSAKI Motohiro Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 228194728ccd..2e6635993558 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1595,6 +1595,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, { /* free_pages my go negative - that's OK */ long min = mark; + long lowmem_reserve = z->lowmem_reserve[classzone_idx]; int o; free_pages -= (1 << order) - 1; @@ -1603,7 +1604,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, if (alloc_flags & ALLOC_HARDER) min -= min / 4; - if (free_pages <= min + z->lowmem_reserve[classzone_idx]) + if (free_pages <= min + lowmem_reserve) return false; for (o = 0; o < order; o++) { /* At the next order, this order's pages become unavailable */ -- GitLab From 702d1a6e0766d45642c934444fd41f658d251305 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:43:56 -0700 Subject: [PATCH 4923/5711] memory-hotplug: fix kswapd looping forever problem When hotplug offlining happens on zone A, it starts to mark freed page as MIGRATE_ISOLATE type in buddy for preventing further allocation. (MIGRATE_ISOLATE is very irony type because it's apparently on buddy but we can't allocate them). When the memory shortage happens during hotplug offlining, current task starts to reclaim, then wake up kswapd. Kswapd checks watermark, then go sleep because current zone_watermark_ok_safe doesn't consider MIGRATE_ISOLATE freed page count. Current task continue to reclaim in direct reclaim path without kswapd's helping. The problem is that zone->all_unreclaimable is set by only kswapd so that current task would be looping forever like below. __alloc_pages_slowpath restart: wake_all_kswapd rebalance: __alloc_pages_direct_reclaim do_try_to_free_pages if global_reclaim && !all_unreclaimable return 1; /* It means we did did_some_progress */ skip __alloc_pages_may_oom should_alloc_retry goto rebalance; If we apply KOSAKI's patch[1] which doesn't depends on kswapd about setting zone->all_unreclaimable, we can solve this problem by killing some task in direct reclaim path. But it doesn't wake up kswapd, still. It could be a problem still if other subsystem needs GFP_ATOMIC request. So kswapd should consider MIGRATE_ISOLATE when it calculate free pages BEFORE going sleep. This patch counts the number of MIGRATE_ISOLATE page block and zone_watermark_ok_safe will consider it if the system has such blocks (fortunately, it's very rare so no problem in POV overhead and kswapd is never hotpath). Copy/modify from Mel's quote " Ideal solution would be "allocating" the pageblock. It would keep the free space accounting as it is but historically, memory hotplug didn't allocate pages because it would be difficult to detect if a pageblock was isolated or if part of some balloon. Allocating just full pageblocks would work around this, However, it would play very badly with CMA. " [1] http://lkml.org/lkml/2012/6/14/74 [akpm@linux-foundation.org: simplify nr_zone_isolate_freepages(), rework zone_watermark_ok_safe() comment, simplify set_pageblock_isolate() and restore_pageblock_isolate()] [akpm@linux-foundation.org: fix CONFIG_MEMORY_ISOLATION=n build] Signed-off-by: Minchan Kim Suggested-by: KOSAKI Motohiro Tested-by: Aaditya Kumar Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 8 ++++++++ mm/page_alloc.c | 30 ++++++++++++++++++++++++++++++ mm/page_isolation.c | 26 ++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 98f079bcf399..64b2c3a48286 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -478,6 +478,14 @@ struct zone { * rarely used fields: */ const char *name; +#ifdef CONFIG_MEMORY_ISOLATION + /* + * the number of MIGRATE_ISOLATE *pageblock*. + * We need this for free page counting. Look at zone_watermark_ok_safe. + * It's protected by zone->lock + */ + int nr_pageblock_isolate; +#endif } ____cacheline_internodealigned_in_smp; typedef enum { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2e6635993558..6a29ed8e6e60 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -218,6 +218,11 @@ EXPORT_SYMBOL(nr_online_nodes); int page_group_by_mobility_disabled __read_mostly; +/* + * NOTE: + * Don't use set_pageblock_migratetype(page, MIGRATE_ISOLATE) directly. + * Instead, use {un}set_pageblock_isolate. + */ void set_pageblock_migratetype(struct page *page, int migratetype) { @@ -1619,6 +1624,20 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, return true; } +#ifdef CONFIG_MEMORY_ISOLATION +static inline unsigned long nr_zone_isolate_freepages(struct zone *zone) +{ + if (unlikely(zone->nr_pageblock_isolate)) + return zone->nr_pageblock_isolate * pageblock_nr_pages; + return 0; +} +#else +static inline unsigned long nr_zone_isolate_freepages(struct zone *zone) +{ + return 0; +} +#endif + bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, int classzone_idx, int alloc_flags) { @@ -1634,6 +1653,14 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark) free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES); + /* + * If the zone has MIGRATE_ISOLATE type free pages, we should consider + * it. nr_zone_isolate_freepages is never accurate so kswapd might not + * sleep although it could do so. But this is more desirable for memory + * hotplug than sleeping which can cause a livelock in the direct + * reclaim path. + */ + free_pages -= nr_zone_isolate_freepages(z); return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, free_pages); } @@ -4398,6 +4425,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, lruvec_init(&zone->lruvec, zone); zap_zone_vm_stats(zone); zone->flags = 0; +#ifdef CONFIG_MEMORY_ISOLATION + zone->nr_pageblock_isolate = 0; +#endif if (!size) continue; diff --git a/mm/page_isolation.c b/mm/page_isolation.c index fb482cf438da..247d1f175739 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -8,6 +8,28 @@ #include #include "internal.h" +/* called while holding zone->lock */ +static void set_pageblock_isolate(struct page *page) +{ + if (get_pageblock_migratetype(page) == MIGRATE_ISOLATE) + return; + + set_pageblock_migratetype(page, MIGRATE_ISOLATE); + page_zone(page)->nr_pageblock_isolate++; +} + +/* called while holding zone->lock */ +static void restore_pageblock_isolate(struct page *page, int migratetype) +{ + struct zone *zone = page_zone(page); + if (WARN_ON(get_pageblock_migratetype(page) != MIGRATE_ISOLATE)) + return; + + BUG_ON(zone->nr_pageblock_isolate <= 0); + set_pageblock_migratetype(page, migratetype); + zone->nr_pageblock_isolate--; +} + int set_migratetype_isolate(struct page *page) { struct zone *zone; @@ -54,7 +76,7 @@ int set_migratetype_isolate(struct page *page) out: if (!ret) { - set_pageblock_migratetype(page, MIGRATE_ISOLATE); + set_pageblock_isolate(page); move_freepages_block(zone, page, MIGRATE_ISOLATE); } @@ -72,8 +94,8 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype) spin_lock_irqsave(&zone->lock, flags); if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) goto out; - set_pageblock_migratetype(page, migratetype); move_freepages_block(zone, page, migratetype); + restore_pageblock_isolate(page, migratetype); out: spin_unlock_irqrestore(&zone->lock, flags); } -- GitLab From 072bb0aa5e062902968c5c1007bba332c7820cf4 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:43:58 -0700 Subject: [PATCH 4924/5711] mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages When a user or administrator requires swap for their application, they create a swap partition and file, format it with mkswap and activate it with swapon. Swap over the network is considered as an option in diskless systems. The two likely scenarios are when blade servers are used as part of a cluster where the form factor or maintenance costs do not allow the use of disks and thin clients. The Linux Terminal Server Project recommends the use of the Network Block Device (NBD) for swap according to the manual at https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download There is also documentation and tutorials on how to setup swap over NBD at places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The nbd-client also documents the use of NBD as swap. Despite this, the fact is that a machine using NBD for swap can deadlock within minutes if swap is used intensively. This patch series addresses the problem. The core issue is that network block devices do not use mempools like normal block devices do. As the host cannot control where they receive packets from, they cannot reliably work out in advance how much memory they might need. Some years ago, Peter Zijlstra developed a series of patches that supported swap over an NFS that at least one distribution is carrying within their kernels. This patch series borrows very heavily from Peter's work to support swapping over NBD as a pre-requisite to supporting swap-over-NFS. The bulk of the complexity is concerned with preserving memory that is allocated from the PFMEMALLOC reserves for use by the network layer which is needed for both NBD and NFS. Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to preserve access to pages allocated under low memory situations to callers that are freeing memory. Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC reserves without setting PFMEMALLOC. Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves for later use by network packet processing. Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set. Patches 7-12 allows network processing to use PFMEMALLOC reserves when the socket has been marked as being used by the VM to clean pages. If packets are received and stored in pages that were allocated under low-memory situations and are unrelated to the VM, the packets are dropped. Patch 11 reintroduces __skb_alloc_page which the networking folk may object to but is needed in some cases to propogate pfmemalloc from a newly allocated page to an skb. If there is a strong objection, this patch can be dropped with the impact being that swap-over-network will be slower in some cases but it should not fail. Patch 13 is a micro-optimisation to avoid a function call in the common case. Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use PFMEMALLOC if necessary. Patch 15 notes that it is still possible for the PFMEMALLOC reserve to be depleted. To prevent this, direct reclaimers get throttled on a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is expected that kswapd and the direct reclaimers already running will clean enough pages for the low watermark to be reached and the throttled processes are woken up. Patch 16 adds a statistic to track how often processes get throttled Some basic performance testing was run using kernel builds, netperf on loopback for UDP and TCP, hackbench (pipes and sockets), iozone and sysbench. Each of them were expected to use the sl*b allocators reasonably heavily but there did not appear to be significant performance variances. For testing swap-over-NBD, a machine was booted with 2G of RAM with a swapfile backed by NBD. 8*NUM_CPU processes were started that create anonymous memory mappings and read them linearly in a loop. The total size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under memory pressure. Without the patches and using SLUB, the machine locks up within minutes and runs to completion with them applied. With SLAB, the story is different as an unpatched kernel run to completion. However, the patched kernel completed the test 45% faster. MICRO 3.5.0-rc2 3.5.0-rc2 vanilla swapnbd Unrecognised test vmscan-anon-mmap-write MMTests Statistics: duration Sys Time Running Test (seconds) 197.80 173.07 User+Sys Time Running Test (seconds) 206.96 182.03 Total Elapsed Time (seconds) 3240.70 1762.09 This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages Allocations of pages below the min watermark run a risk of the machine hanging due to a lack of memory. To prevent this, only callers who have PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to a slab though, nothing prevents other callers consuming free objects within those slabs. This patch limits access to slab pages that were alloced from the PFMEMALLOC reserves. When this patch is applied, pages allocated from below the low watermark are returned with page->pfmemalloc set and it is up to the caller to determine how the page should be protected. SLAB restricts access to any page with page->pfmemalloc set to callers which are known to able to access the PFMEMALLOC reserve. If one is not available, an attempt is made to allocate a new page rather than use a reserve. SLUB is a bit more relaxed in that it only records if the current per-CPU page was allocated from PFMEMALLOC reserve and uses another partial slab if the caller does not have the necessary GFP or process flags. This was found to be sufficient in tests to avoid hangs due to SLUB generally maintaining smaller lists than SLAB. In low-memory conditions it does mean that !PFMEMALLOC allocators can fail a slab allocation even though free objects are available because they are being preserved for callers that are freeing pages. [a.p.zijlstra@chello.nl: Original implementation] [sebastian@breakpoint.cc: Correct order of page flag clearing] Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm_types.h | 9 ++ include/linux/page-flags.h | 29 ++++++ mm/internal.h | 3 + mm/page_alloc.c | 27 +++++- mm/slab.c | 192 +++++++++++++++++++++++++++++++++---- mm/slub.c | 29 +++++- 6 files changed, 264 insertions(+), 25 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 074eb98fe15d..375e79eb009b 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -54,6 +54,15 @@ struct page { union { pgoff_t index; /* Our offset within mapping. */ void *freelist; /* slub/slob first free object */ + bool pfmemalloc; /* If set by the page allocator, + * ALLOC_PFMEMALLOC was set + * and the low watermark was not + * met implying that the system + * is under some pressure. The + * caller should try ensure + * this page is only used to + * free other pages. + */ }; union { diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index c88d2a9451af..b5d13841604e 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -7,6 +7,7 @@ #include #include +#include #ifndef __GENERATING_BOUNDS_H #include #include @@ -453,6 +454,34 @@ static inline int PageTransTail(struct page *page) } #endif +/* + * If network-based swap is enabled, sl*b must keep track of whether pages + * were allocated from pfmemalloc reserves. + */ +static inline int PageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + return PageActive(page); +} + +static inline void SetPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + SetPageActive(page); +} + +static inline void __ClearPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + __ClearPageActive(page); +} + +static inline void ClearPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + ClearPageActive(page); +} + #ifdef CONFIG_MMU #define __PG_MLOCKED (1 << PG_mlocked) #else diff --git a/mm/internal.h b/mm/internal.h index 3314f79d775a..eb76b67890d0 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -279,6 +279,9 @@ static inline struct page *mem_map_next(struct page *iter, #define __paginginit __init #endif +/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */ +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask); + /* Memory initialisation debug and verification */ enum mminit_level { MMINIT_WARNING, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6a29ed8e6e60..38e5be65f24e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1513,6 +1513,7 @@ failed: #define ALLOC_HARDER 0x10 /* try to alloc harder */ #define ALLOC_HIGH 0x20 /* __GFP_HIGH set */ #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ +#define ALLOC_PFMEMALLOC 0x80 /* Caller has PF_MEMALLOC set */ #ifdef CONFIG_FAIL_PAGE_ALLOC @@ -2293,16 +2294,22 @@ gfp_to_alloc_flags(gfp_t gfp_mask) } else if (unlikely(rt_task(current)) && !in_interrupt()) alloc_flags |= ALLOC_HARDER; - if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { - if (!in_interrupt() && - ((current->flags & PF_MEMALLOC) || - unlikely(test_thread_flag(TIF_MEMDIE)))) + if ((current->flags & PF_MEMALLOC) || + unlikely(test_thread_flag(TIF_MEMDIE))) { + alloc_flags |= ALLOC_PFMEMALLOC; + + if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) alloc_flags |= ALLOC_NO_WATERMARKS; } return alloc_flags; } +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) +{ + return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_PFMEMALLOC); +} + static inline struct page * __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, @@ -2490,10 +2497,18 @@ nopage: warn_alloc_failed(gfp_mask, order, NULL); return page; got_pg: + /* + * page->pfmemalloc is set when the caller had PFMEMALLOC set or is + * been OOM killed. The expectation is that the caller is taking + * steps that will free more memory. The caller should avoid the + * page being used for !PFMEMALLOC purposes. + */ + page->pfmemalloc = !!(alloc_flags & ALLOC_PFMEMALLOC); + if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask); - return page; + return page; } /* @@ -2544,6 +2559,8 @@ retry_cpuset: page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); + else + page->pfmemalloc = false; trace_mm_page_alloc(page, order, gfp_mask, migratetype); diff --git a/mm/slab.c b/mm/slab.c index 1fcf3ac94b6c..55d84a22ad96 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -124,6 +124,8 @@ #include +#include "internal.h" + /* * DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON. * 0 for faster, smaller code (especially in the critical paths). @@ -152,6 +154,12 @@ #define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN #endif +/* + * true if a page was allocated from pfmemalloc reserves for network-based + * swap + */ +static bool pfmemalloc_active __read_mostly; + /* Legal flag mask for kmem_cache_create(). */ #if DEBUG # define CREATE_MASK (SLAB_RED_ZONE | \ @@ -257,9 +265,30 @@ struct array_cache { * Must have this definition in here for the proper * alignment of array_cache. Also simplifies accessing * the entries. + * + * Entries should not be directly dereferenced as + * entries belonging to slabs marked pfmemalloc will + * have the lower bits set SLAB_OBJ_PFMEMALLOC */ }; +#define SLAB_OBJ_PFMEMALLOC 1 +static inline bool is_obj_pfmemalloc(void *objp) +{ + return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC; +} + +static inline void set_obj_pfmemalloc(void **objp) +{ + *objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC); + return; +} + +static inline void clear_obj_pfmemalloc(void **objp) +{ + *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC); +} + /* * bootstrap: The caches do not work without cpuarrays anymore, but the * cpuarrays are allocated from the generic caches... @@ -900,6 +929,102 @@ static struct array_cache *alloc_arraycache(int node, int entries, return nc; } +static inline bool is_slab_pfmemalloc(struct slab *slabp) +{ + struct page *page = virt_to_page(slabp->s_mem); + + return PageSlabPfmemalloc(page); +} + +/* Clears pfmemalloc_active if no slabs have pfmalloc set */ +static void recheck_pfmemalloc_active(struct kmem_cache *cachep, + struct array_cache *ac) +{ + struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()]; + struct slab *slabp; + unsigned long flags; + + if (!pfmemalloc_active) + return; + + spin_lock_irqsave(&l3->list_lock, flags); + list_for_each_entry(slabp, &l3->slabs_full, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + list_for_each_entry(slabp, &l3->slabs_partial, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + list_for_each_entry(slabp, &l3->slabs_free, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + pfmemalloc_active = false; +out: + spin_unlock_irqrestore(&l3->list_lock, flags); +} + +static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, + gfp_t flags, bool force_refill) +{ + int i; + void *objp = ac->entry[--ac->avail]; + + /* Ensure the caller is allowed to use objects from PFMEMALLOC slab */ + if (unlikely(is_obj_pfmemalloc(objp))) { + struct kmem_list3 *l3; + + if (gfp_pfmemalloc_allowed(flags)) { + clear_obj_pfmemalloc(&objp); + return objp; + } + + /* The caller cannot use PFMEMALLOC objects, find another one */ + for (i = 1; i < ac->avail; i++) { + /* If a !PFMEMALLOC object is found, swap them */ + if (!is_obj_pfmemalloc(ac->entry[i])) { + objp = ac->entry[i]; + ac->entry[i] = ac->entry[ac->avail]; + ac->entry[ac->avail] = objp; + return objp; + } + } + + /* + * If there are empty slabs on the slabs_free list and we are + * being forced to refill the cache, mark this one !pfmemalloc. + */ + l3 = cachep->nodelists[numa_mem_id()]; + if (!list_empty(&l3->slabs_free) && force_refill) { + struct slab *slabp = virt_to_slab(objp); + ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem)); + clear_obj_pfmemalloc(&objp); + recheck_pfmemalloc_active(cachep, ac); + return objp; + } + + /* No !PFMEMALLOC objects available */ + ac->avail++; + objp = NULL; + } + + return objp; +} + +static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, + void *objp) +{ + if (unlikely(pfmemalloc_active)) { + /* Some pfmemalloc slabs exist, check if this is one */ + struct page *page = virt_to_page(objp); + if (PageSlabPfmemalloc(page)) + set_obj_pfmemalloc(&objp); + } + + ac->entry[ac->avail++] = objp; +} + /* * Transfer objects in one arraycache to another. * Locking must be handled by the caller. @@ -1076,7 +1201,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) STATS_INC_ACOVERFLOW(cachep); __drain_alien_cache(cachep, alien, nodeid); } - alien->entry[alien->avail++] = objp; + ac_put_obj(cachep, alien, objp); spin_unlock(&alien->lock); } else { spin_lock(&(cachep->nodelists[nodeid])->list_lock); @@ -1759,6 +1884,10 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) return NULL; } + /* Record if ALLOC_PFMEMALLOC was set when allocating the slab */ + if (unlikely(page->pfmemalloc)) + pfmemalloc_active = true; + nr_pages = (1 << cachep->gfporder); if (cachep->flags & SLAB_RECLAIM_ACCOUNT) add_zone_page_state(page_zone(page), @@ -1766,9 +1895,13 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) else add_zone_page_state(page_zone(page), NR_SLAB_UNRECLAIMABLE, nr_pages); - for (i = 0; i < nr_pages; i++) + for (i = 0; i < nr_pages; i++) { __SetPageSlab(page + i); + if (page->pfmemalloc) + SetPageSlabPfmemalloc(page + i); + } + if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) { kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid); @@ -1800,6 +1933,7 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) NR_SLAB_UNRECLAIMABLE, nr_freed); while (i--) { BUG_ON(!PageSlab(page)); + __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); page++; } @@ -3015,16 +3149,19 @@ bad: #define check_slabp(x,y) do { } while(0) #endif -static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) +static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, + bool force_refill) { int batchcount; struct kmem_list3 *l3; struct array_cache *ac; int node; -retry: check_irq_off(); node = numa_mem_id(); + if (unlikely(force_refill)) + goto force_grow; +retry: ac = cpu_cache_get(cachep); batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -3074,8 +3211,8 @@ retry: STATS_INC_ACTIVE(cachep); STATS_SET_HIGH(cachep); - ac->entry[ac->avail++] = slab_get_obj(cachep, slabp, - node); + ac_put_obj(cachep, ac, slab_get_obj(cachep, slabp, + node)); } check_slabp(cachep, slabp); @@ -3094,18 +3231,22 @@ alloc_done: if (unlikely(!ac->avail)) { int x; +force_grow: x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL); /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); - if (!x && ac->avail == 0) /* no objects in sight? abort */ + + /* no objects in sight? abort */ + if (!x && (ac->avail == 0 || force_refill)) return NULL; if (!ac->avail) /* objects refilled by interrupt? */ goto retry; } ac->touched = 1; - return ac->entry[--ac->avail]; + + return ac_get_obj(cachep, ac, flags, force_refill); } static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep, @@ -3187,23 +3328,35 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; + bool force_refill = false; check_irq_off(); ac = cpu_cache_get(cachep); if (likely(ac->avail)) { - STATS_INC_ALLOCHIT(cachep); ac->touched = 1; - objp = ac->entry[--ac->avail]; - } else { - STATS_INC_ALLOCMISS(cachep); - objp = cache_alloc_refill(cachep, flags); + objp = ac_get_obj(cachep, ac, flags, false); + /* - * the 'ac' may be updated by cache_alloc_refill(), - * and kmemleak_erase() requires its correct value. + * Allow for the possibility all avail objects are not allowed + * by the current flags */ - ac = cpu_cache_get(cachep); + if (objp) { + STATS_INC_ALLOCHIT(cachep); + goto out; + } + force_refill = true; } + + STATS_INC_ALLOCMISS(cachep); + objp = cache_alloc_refill(cachep, flags, force_refill); + /* + * the 'ac' may be updated by cache_alloc_refill(), + * and kmemleak_erase() requires its correct value. + */ + ac = cpu_cache_get(cachep); + +out: /* * To avoid a false negative, if an object that is in one of the * per-CPU caches is leaked, we need to make sure kmemleak doesn't @@ -3525,9 +3678,12 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects, struct kmem_list3 *l3; for (i = 0; i < nr_objects; i++) { - void *objp = objpp[i]; + void *objp; struct slab *slabp; + clear_obj_pfmemalloc(&objpp[i]); + objp = objpp[i]; + slabp = virt_to_slab(objp); l3 = cachep->nodelists[node]; list_del(&slabp->list); @@ -3645,7 +3801,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, cache_flusharray(cachep, ac); } - ac->entry[ac->avail++] = objp; + ac_put_obj(cachep, ac, objp); } /** diff --git a/mm/slub.c b/mm/slub.c index e517d435e5dc..c3f05e1599c0 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -34,6 +34,8 @@ #include +#include "internal.h" + /* * Lock order: * 1. slab_mutex (Global Mutex) @@ -1354,6 +1356,8 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) inc_slabs_node(s, page_to_nid(page), page->objects); page->slab = s; __SetPageSlab(page); + if (page->pfmemalloc) + SetPageSlabPfmemalloc(page); start = page_address(page); @@ -1397,6 +1401,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page) NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, -pages); + __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); reset_page_mapcount(page); if (current->reclaim_state) @@ -2126,6 +2131,14 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, return freelist; } +static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags) +{ + if (unlikely(PageSlabPfmemalloc(page))) + return gfp_pfmemalloc_allowed(gfpflags); + + return true; +} + /* * Check the page->freelist of a page and either transfer the freelist to the per cpu freelist * or deactivate the page. @@ -2206,6 +2219,18 @@ redo: goto new_slab; } + /* + * By rights, we should be searching for a slab page that was + * PFMEMALLOC but right now, we are losing the pfmemalloc + * information when the page leaves the per-cpu allocator + */ + if (unlikely(!pfmemalloc_match(page, gfpflags))) { + deactivate_slab(s, page, c->freelist); + c->page = NULL; + c->freelist = NULL; + goto new_slab; + } + /* must check again c->freelist in case of cpu migration or IRQ */ freelist = c->freelist; if (freelist) @@ -2312,8 +2337,8 @@ redo: object = c->freelist; page = c->page; - if (unlikely(!object || !node_match(page, node))) - + if (unlikely(!object || !node_match(page, node) || + !pfmemalloc_match(page, gfpflags))) object = __slab_alloc(s, gfpflags, node, addr, c); else { -- GitLab From 5091b74a95d447e34530e713a8971450a45498b3 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 31 Jul 2012 16:44:00 -0700 Subject: [PATCH 4925/5711] mm: slub: optimise the SLUB fast path to avoid pfmemalloc checks This patch removes the check for pfmemalloc from the alloc hotpath and puts the logic after the election of a new per cpu slab. For a pfmemalloc page we do not use the fast path but force the use of the slow path which is also used for the debug case. This has the side-effect of weakening pfmemalloc processing in the following way; 1. A process that is allocating for network swap calls __slab_alloc. pfmemalloc_match is true so the freelist is loaded and c->freelist is now pointing to a pfmemalloc page. 2. A process that is attempting normal allocations calls slab_alloc, finds the pfmemalloc page on the freelist and uses it because it did not check pfmemalloc_match() The patch allows non-pfmemalloc allocations to use pfmemalloc pages with the kmalloc slabs being the most vunerable caches on the grounds they are most likely to have a mix of pfmemalloc and !pfmemalloc requests. A later patch will still protect the system as processes will get throttled if the pfmemalloc reserves get depleted but performance will not degrade as smoothly. [mgorman@suse.de: Expanded changelog] Signed-off-by: Christoph Lameter Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slub.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index c3f05e1599c0..8f78e2577031 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2281,11 +2281,11 @@ new_slab: } page = c->page; - if (likely(!kmem_cache_debug(s))) + if (likely(!kmem_cache_debug(s) && pfmemalloc_match(page, gfpflags))) goto load_freelist; /* Only entered in the debug case */ - if (!alloc_debug_processing(s, page, freelist, addr)) + if (kmem_cache_debug(s) && !alloc_debug_processing(s, page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ deactivate_slab(s, page, get_freepointer(s, freelist)); @@ -2337,8 +2337,7 @@ redo: object = c->freelist; page = c->page; - if (unlikely(!object || !node_match(page, node) || - !pfmemalloc_match(page, gfpflags))) + if (unlikely(!object || !node_match(page, node))) object = __slab_alloc(s, gfpflags, node, addr, c); else { -- GitLab From b37f1dd0f543d9714f96c2f9b9f74f7bdfdfdf31 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:03 -0700 Subject: [PATCH 4926/5711] mm: introduce __GFP_MEMALLOC to allow access to emergency reserves __GFP_MEMALLOC will allow the allocation to disregard the watermarks, much like PF_MEMALLOC. It allows one to pass along the memalloc state in object related allocation flags as opposed to task related flags, such as sk->sk_allocation. This removes the need for ALLOC_PFMEMALLOC as callers using __GFP_MEMALLOC can get the ALLOC_NO_WATERMARK flag which is now enough to identify allocations related to page reclaim. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 10 ++++++++-- include/linux/mm_types.h | 2 +- include/trace/events/gfpflags.h | 1 + mm/page_alloc.c | 22 ++++++++++------------ mm/slab.c | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 1e49be49d324..cbd7400e5862 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -23,6 +23,7 @@ struct vm_area_struct; #define ___GFP_REPEAT 0x400u #define ___GFP_NOFAIL 0x800u #define ___GFP_NORETRY 0x1000u +#define ___GFP_MEMALLOC 0x2000u #define ___GFP_COMP 0x4000u #define ___GFP_ZERO 0x8000u #define ___GFP_NOMEMALLOC 0x10000u @@ -76,9 +77,14 @@ struct vm_area_struct; #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */ #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */ #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* See above */ +#define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)/* Allow access to emergency reserves */ #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* Add compound page metadata */ #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */ -#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */ +#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves. + * This takes precedence over the + * __GFP_MEMALLOC flag if both are + * set + */ #define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */ #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */ #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */ @@ -129,7 +135,7 @@ struct vm_area_struct; /* Control page allocator reclaim behavior */ #define GFP_RECLAIM_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|\ __GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\ - __GFP_NORETRY|__GFP_NOMEMALLOC) + __GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC) /* Control slab gfp mask during early boot */ #define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS)) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 375e79eb009b..bf7867200b95 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -55,7 +55,7 @@ struct page { pgoff_t index; /* Our offset within mapping. */ void *freelist; /* slub/slob first free object */ bool pfmemalloc; /* If set by the page allocator, - * ALLOC_PFMEMALLOC was set + * ALLOC_NO_WATERMARKS was set * and the low watermark was not * met implying that the system * is under some pressure. The diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h index 9fe3a36646e9..d6fd8e5b14b7 100644 --- a/include/trace/events/gfpflags.h +++ b/include/trace/events/gfpflags.h @@ -30,6 +30,7 @@ {(unsigned long)__GFP_COMP, "GFP_COMP"}, \ {(unsigned long)__GFP_ZERO, "GFP_ZERO"}, \ {(unsigned long)__GFP_NOMEMALLOC, "GFP_NOMEMALLOC"}, \ + {(unsigned long)__GFP_MEMALLOC, "GFP_MEMALLOC"}, \ {(unsigned long)__GFP_HARDWALL, "GFP_HARDWALL"}, \ {(unsigned long)__GFP_THISNODE, "GFP_THISNODE"}, \ {(unsigned long)__GFP_RECLAIMABLE, "GFP_RECLAIMABLE"}, \ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 38e5be65f24e..8f65abeb9ad6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1513,7 +1513,6 @@ failed: #define ALLOC_HARDER 0x10 /* try to alloc harder */ #define ALLOC_HIGH 0x20 /* __GFP_HIGH set */ #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ -#define ALLOC_PFMEMALLOC 0x80 /* Caller has PF_MEMALLOC set */ #ifdef CONFIG_FAIL_PAGE_ALLOC @@ -2294,11 +2293,10 @@ gfp_to_alloc_flags(gfp_t gfp_mask) } else if (unlikely(rt_task(current)) && !in_interrupt()) alloc_flags |= ALLOC_HARDER; - if ((current->flags & PF_MEMALLOC) || - unlikely(test_thread_flag(TIF_MEMDIE))) { - alloc_flags |= ALLOC_PFMEMALLOC; - - if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) + if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { + if (gfp_mask & __GFP_MEMALLOC) + alloc_flags |= ALLOC_NO_WATERMARKS; + else if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) alloc_flags |= ALLOC_NO_WATERMARKS; } @@ -2307,7 +2305,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask) bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) { - return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_PFMEMALLOC); + return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_NO_WATERMARKS); } static inline struct page * @@ -2498,12 +2496,12 @@ nopage: return page; got_pg: /* - * page->pfmemalloc is set when the caller had PFMEMALLOC set or is - * been OOM killed. The expectation is that the caller is taking - * steps that will free more memory. The caller should avoid the - * page being used for !PFMEMALLOC purposes. + * page->pfmemalloc is set when the caller had PFMEMALLOC set, is + * been OOM killed or specified __GFP_MEMALLOC. The expectation is + * that the caller is taking steps that will free more memory. The + * caller should avoid the page being used for !PFMEMALLOC purposes. */ - page->pfmemalloc = !!(alloc_flags & ALLOC_PFMEMALLOC); + page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask); diff --git a/mm/slab.c b/mm/slab.c index 55d84a22ad96..77be18dab73c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1884,7 +1884,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) return NULL; } - /* Record if ALLOC_PFMEMALLOC was set when allocating the slab */ + /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */ if (unlikely(page->pfmemalloc)) pfmemalloc_active = true; -- GitLab From 907aed48f65efeecf91575397e3d79335d93a466 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:07 -0700 Subject: [PATCH 4927/5711] mm: allow PF_MEMALLOC from softirq context This is needed to allow network softirq packet processing to make use of PF_MEMALLOC. Currently softirq context cannot use PF_MEMALLOC due to it not being associated with a task, and therefore not having task flags to fiddle with - thus the gfp to alloc flag mapping ignores the task flags when in interrupts (hard or soft) context. Allowing softirqs to make use of PF_MEMALLOC therefore requires some trickery. This patch borrows the task flags from whatever process happens to be preempted by the softirq. It then modifies the gfp to alloc flags mapping to not exclude task flags in softirq context, and modify the softirq code to save, clear and restore the PF_MEMALLOC flag. The save and clear, ensures the preempted task's PF_MEMALLOC flag doesn't leak into the softirq. The restore ensures a softirq's PF_MEMALLOC flag cannot leak back into the preempted process. This should be safe due to the following reasons Softirqs can run on multiple CPUs sure but the same task should not be executing the same softirq code. Neither should the softirq handler be preempted by any other softirq handler so the flags should not leak to an unrelated softirq. Softirqs re-enable hardware interrupts in __do_softirq() so can be preempted by hardware interrupts so PF_MEMALLOC is inherited by the hard IRQ. However, this is similar to a process in reclaim being preempted by a hardirq. While PF_MEMALLOC is set, gfp_to_alloc_flags() distinguishes between hard and soft irqs and avoids giving a hardirq the ALLOC_NO_WATERMARKS flag. If the softirq is deferred to ksoftirq then its flags may be used instead of a normal tasks but as the softirq cannot be preempted, the PF_MEMALLOC flag does not leak to other code by accident. [davem@davemloft.net: Document why PF_MEMALLOC is safe] Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 7 +++++++ kernel/softirq.c | 9 +++++++++ mm/page_alloc.c | 6 +++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 865725adb9d3..c147e7024f11 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1894,6 +1894,13 @@ static inline void rcu_copy_process(struct task_struct *p) #endif +static inline void tsk_restore_flags(struct task_struct *task, + unsigned long orig_flags, unsigned long flags) +{ + task->flags &= ~flags; + task->flags |= orig_flags & flags; +} + #ifdef CONFIG_SMP extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask); diff --git a/kernel/softirq.c b/kernel/softirq.c index 671f9594e368..b73e681df09e 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -210,6 +210,14 @@ asmlinkage void __do_softirq(void) __u32 pending; int max_restart = MAX_SOFTIRQ_RESTART; int cpu; + unsigned long old_flags = current->flags; + + /* + * Mask out PF_MEMALLOC s current task context is borrowed for the + * softirq. A softirq handled such as network RX might set PF_MEMALLOC + * again if the socket is related to swap + */ + current->flags &= ~PF_MEMALLOC; pending = local_softirq_pending(); account_system_vtime(current); @@ -265,6 +273,7 @@ restart: account_system_vtime(current); __local_bh_enable(SOFTIRQ_OFFSET); + tsk_restore_flags(current, old_flags, PF_MEMALLOC); } #ifndef __ARCH_HAS_DO_SOFTIRQ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8f65abeb9ad6..cd5390f2f18d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2296,7 +2296,11 @@ gfp_to_alloc_flags(gfp_t gfp_mask) if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { if (gfp_mask & __GFP_MEMALLOC) alloc_flags |= ALLOC_NO_WATERMARKS; - else if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) + else if (in_serving_softirq() && (current->flags & PF_MEMALLOC)) + alloc_flags |= ALLOC_NO_WATERMARKS; + else if (!in_interrupt() && + ((current->flags & PF_MEMALLOC) || + unlikely(test_thread_flag(TIF_MEMDIE)))) alloc_flags |= ALLOC_NO_WATERMARKS; } -- GitLab From cfd19c5a9ecf8e5e38de2603077c4330af21316e Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:10 -0700 Subject: [PATCH 4928/5711] mm: only set page->pfmemalloc when ALLOC_NO_WATERMARKS was used __alloc_pages_slowpath() is called when the number of free pages is below the low watermark. If the caller is entitled to use ALLOC_NO_WATERMARKS then the page will be marked page->pfmemalloc. This protects more pages than are strictly necessary as we only need to protect pages allocated below the min watermark (the pfmemalloc reserves). This patch only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required to allocate the page. [rientjes@google.com: David noticed the problem during review] Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cd5390f2f18d..f9d925451bfd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2116,8 +2116,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, - alloc_flags, preferred_zone, - migratetype); + alloc_flags & ~ALLOC_NO_WATERMARKS, + preferred_zone, migratetype); if (page) { preferred_zone->compact_considered = 0; preferred_zone->compact_defer_shift = 0; @@ -2209,8 +2209,8 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, retry: page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, - alloc_flags, preferred_zone, - migratetype); + alloc_flags & ~ALLOC_NO_WATERMARKS, + preferred_zone, migratetype); /* * If an allocation failed after direct reclaim, it could be because @@ -2381,8 +2381,17 @@ rebalance: page = __alloc_pages_high_priority(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); - if (page) + if (page) { + /* + * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was + * necessary to allocate the page. The expectation is + * that the caller is taking steps that will free more + * memory. The caller should avoid the page being used + * for !PFMEMALLOC purposes. + */ + page->pfmemalloc = true; goto got_pg; + } } /* Atomic allocations - we can't balance anything */ @@ -2499,14 +2508,6 @@ nopage: warn_alloc_failed(gfp_mask, order, NULL); return page; got_pg: - /* - * page->pfmemalloc is set when the caller had PFMEMALLOC set, is - * been OOM killed or specified __GFP_MEMALLOC. The expectation is - * that the caller is taking steps that will free more memory. The - * caller should avoid the page being used for !PFMEMALLOC purposes. - */ - page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); - if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask); -- GitLab From 183f6371aac2a5496a8ef2b0b0a68562652c3cdb Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:12 -0700 Subject: [PATCH 4929/5711] mm: ignore mempolicies when using ALLOC_NO_WATERMARK The reserve is proportionally distributed over all !highmem zones in the system. So we need to allow an emergency allocation access to all zones. In order to do that we need to break out of any mempolicy boundaries we might have. In my opinion that does not break mempolicies as those are user oriented and not system oriented. That is, system allocations are not guaranteed to be within mempolicy boundaries. For instance IRQs do not even have a mempolicy. So breaking out of mempolicy boundaries for 'rare' emergency allocations, which are always system allocations (as opposed to user) is ok. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f9d925451bfd..ef2d1e72fc07 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2378,6 +2378,13 @@ rebalance: /* Allocate without watermarks if the context allows */ if (alloc_flags & ALLOC_NO_WATERMARKS) { + /* + * Ignore mempolicies if ALLOC_NO_WATERMARKS on the grounds + * the allocation is high priority and these type of + * allocations are system rather than user orientated + */ + zonelist = node_zonelist(numa_node_id(), gfp_mask); + page = __alloc_pages_high_priority(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); -- GitLab From 99a1dec70d5acbd8c6b3928cdebb4a2d1da676c8 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:14 -0700 Subject: [PATCH 4930/5711] net: introduce sk_gfp_atomic() to allow addition of GFP flags depending on the individual socket Introduce sk_gfp_atomic(), this function allows to inject sock specific flags to each sock related allocation. It is only used on allocation paths that may be required for writing pages back to network storage. [davem@davemloft.net: Use sk_gfp_atomic only when necessary] Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/net/sock.h | 5 +++++ net/ipv4/tcp_output.c | 12 +++++++----- net/ipv6/tcp_ipv6.c | 8 +++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index cee528c119ca..11ccde65c4cf 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -658,6 +658,11 @@ static inline bool sock_flag(const struct sock *sk, enum sock_flags flag) return test_bit(flag, &sk->sk_flags); } +static inline gfp_t sk_gfp_atomic(struct sock *sk, gfp_t gfp_mask) +{ + return GFP_ATOMIC; +} + static inline void sk_acceptq_removed(struct sock *sk) { sk->sk_ack_backlog--; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 33cd065cfbd8..3f1bcff0b10b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2045,7 +2045,8 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, if (unlikely(sk->sk_state == TCP_CLOSE)) return; - if (tcp_write_xmit(sk, cur_mss, nonagle, 0, GFP_ATOMIC)) + if (tcp_write_xmit(sk, cur_mss, nonagle, 0, + sk_gfp_atomic(sk, GFP_ATOMIC))) tcp_check_probe_timer(sk); } @@ -2666,7 +2667,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) s_data_desired = cvp->s_data_desired; - skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC); + skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, + sk_gfp_atomic(sk, GFP_ATOMIC)); if (unlikely(!skb)) { dst_release(dst); return NULL; @@ -3064,7 +3066,7 @@ void tcp_send_ack(struct sock *sk) * tcp_transmit_skb() will set the ownership to this * sock. */ - buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC); + buff = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC)); if (buff == NULL) { inet_csk_schedule_ack(sk); inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN; @@ -3079,7 +3081,7 @@ void tcp_send_ack(struct sock *sk) /* Send it off, this clears delayed acks for us. */ TCP_SKB_CB(buff)->when = tcp_time_stamp; - tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC); + tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC)); } /* This routine sends a packet with an out of date sequence @@ -3099,7 +3101,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent) struct sk_buff *skb; /* We don't queue it, tcp_transmit_skb() sets ownership. */ - skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC); + skb = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC)); if (skb == NULL) return -1; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 61c7b6d83176..c66b90f71c9b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1299,7 +1299,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, /* Clone pktoptions received with SYN */ newnp->pktoptions = NULL; if (treq->pktopts != NULL) { - newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC); + newnp->pktoptions = skb_clone(treq->pktopts, + sk_gfp_atomic(sk, GFP_ATOMIC)); consume_skb(treq->pktopts); treq->pktopts = NULL; if (newnp->pktoptions) @@ -1349,7 +1350,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * across. Shucks. */ tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newnp->daddr, - AF_INET6, key->key, key->keylen, GFP_ATOMIC); + AF_INET6, key->key, key->keylen, + sk_gfp_atomic(sk, GFP_ATOMIC)); } #endif @@ -1442,7 +1444,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) --ANK (980728) */ if (np->rxopt.all) - opt_skb = skb_clone(skb, GFP_ATOMIC); + opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ sock_rps_save_rxhash(sk, skb); -- GitLab From 7cb0240492caea2f6467f827313478f41877e6ef Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:16 -0700 Subject: [PATCH 4931/5711] netvm: allow the use of __GFP_MEMALLOC by specific sockets Allow specific sockets to be tagged SOCK_MEMALLOC and use __GFP_MEMALLOC for their allocations. These sockets will be able to go below watermarks and allocate from the emergency reserve. Such sockets are to be used to service the VM (iow. to swap over). They must be handled kernel side, exposing such a socket to user-space is a bug. There is a risk that the reserves be depleted so for now, the administrator is responsible for increasing min_free_kbytes as necessary to prevent deadlock for their workloads. [a.p.zijlstra@chello.nl: Original patches] Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/net/sock.h | 5 ++++- net/core/sock.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 11ccde65c4cf..bfa7d20e6646 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -621,6 +621,7 @@ enum sock_flags { SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */ + SOCK_MEMALLOC, /* VM depends on this socket for swapping */ SOCK_TIMESTAMPING_TX_HARDWARE, /* %SOF_TIMESTAMPING_TX_HARDWARE */ SOCK_TIMESTAMPING_TX_SOFTWARE, /* %SOF_TIMESTAMPING_TX_SOFTWARE */ SOCK_TIMESTAMPING_RX_HARDWARE, /* %SOF_TIMESTAMPING_RX_HARDWARE */ @@ -660,7 +661,7 @@ static inline bool sock_flag(const struct sock *sk, enum sock_flags flag) static inline gfp_t sk_gfp_atomic(struct sock *sk, gfp_t gfp_mask) { - return GFP_ATOMIC; + return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC); } static inline void sk_acceptq_removed(struct sock *sk) @@ -803,6 +804,8 @@ extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p); extern void sk_stream_wait_close(struct sock *sk, long timeo_p); extern int sk_stream_error(struct sock *sk, int flags, int err); extern void sk_stream_kill_queues(struct sock *sk); +extern void sk_set_memalloc(struct sock *sk); +extern void sk_clear_memalloc(struct sock *sk); extern int sk_wait_data(struct sock *sk, long *timeo); diff --git a/net/core/sock.c b/net/core/sock.c index a67b06280e4c..3617f652f6b0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -271,6 +271,28 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); EXPORT_SYMBOL(sysctl_optmem_max); +/** + * sk_set_memalloc - sets %SOCK_MEMALLOC + * @sk: socket to set it on + * + * Set %SOCK_MEMALLOC on a socket for access to emergency reserves. + * It's the responsibility of the admin to adjust min_free_kbytes + * to meet the requirements + */ +void sk_set_memalloc(struct sock *sk) +{ + sock_set_flag(sk, SOCK_MEMALLOC); + sk->sk_allocation |= __GFP_MEMALLOC; +} +EXPORT_SYMBOL_GPL(sk_set_memalloc); + +void sk_clear_memalloc(struct sock *sk) +{ + sock_reset_flag(sk, SOCK_MEMALLOC); + sk->sk_allocation &= ~__GFP_MEMALLOC; +} +EXPORT_SYMBOL_GPL(sk_clear_memalloc); + #if defined(CONFIG_CGROUPS) #if !defined(CONFIG_NET_CLS_CGROUP) int net_cls_subsys_id = -1; -- GitLab From c93bdd0e03e848555d144eb44a1f275b871a8dd5 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:19 -0700 Subject: [PATCH 4932/5711] netvm: allow skb allocation to use PFMEMALLOC reserves Change the skb allocation API to indicate RX usage and use this to fall back to the PFMEMALLOC reserve when needed. SKBs allocated from the reserve are tagged in skb->pfmemalloc. If an SKB is allocated from the reserve and the socket is later found to be unrelated to page reclaim, the packet is dropped so that the memory remains available for page reclaim. Network protocols are expected to recover from this packet loss. [a.p.zijlstra@chello.nl: Ideas taken from various patches] [davem@davemloft.net: Use static branches, coding style corrections] [sebastian@breakpoint.cc: Avoid unnecessary cast, fix !CONFIG_NET build] Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 3 + include/linux/skbuff.h | 14 ++++- include/net/sock.h | 15 +++++ mm/internal.h | 3 - net/core/filter.c | 8 +++ net/core/skbuff.c | 124 ++++++++++++++++++++++++++++++++--------- net/core/sock.c | 5 ++ 7 files changed, 142 insertions(+), 30 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index cbd7400e5862..4883f393f50a 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -385,6 +385,9 @@ void drain_local_pages(void *dummy); */ extern gfp_t gfp_allowed_mask; +/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */ +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask); + extern void pm_restrict_gfp_mask(void); extern void pm_restore_gfp_mask(void); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d205c4be7f5b..0336f02e3667 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -462,6 +462,7 @@ struct sk_buff { #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif + __u8 pfmemalloc:1; __u8 ooo_okay:1; __u8 l4_rxhash:1; __u8 wifi_acked_valid:1; @@ -502,6 +503,15 @@ struct sk_buff { #include +#define SKB_ALLOC_FCLONE 0x01 +#define SKB_ALLOC_RX 0x02 + +/* Returns true if the skb was allocated from PFMEMALLOC reserves */ +static inline bool skb_pfmemalloc(const struct sk_buff *skb) +{ + return unlikely(skb->pfmemalloc); +} + /* * skb might have a dst pointer attached, refcounted or not. * _skb_refdst low order bit is set if refcount was _not_ taken @@ -565,7 +575,7 @@ extern bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, bool *fragstolen, int *delta_truesize); extern struct sk_buff *__alloc_skb(unsigned int size, - gfp_t priority, int fclone, int node); + gfp_t priority, int flags, int node); extern struct sk_buff *build_skb(void *data, unsigned int frag_size); static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority) @@ -576,7 +586,7 @@ static inline struct sk_buff *alloc_skb(unsigned int size, static inline struct sk_buff *alloc_skb_fclone(unsigned int size, gfp_t priority) { - return __alloc_skb(size, priority, 1, NUMA_NO_NODE); + return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); } extern void skb_recycle(struct sk_buff *skb); diff --git a/include/net/sock.h b/include/net/sock.h index bfa7d20e6646..81198632ac2a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -659,6 +659,21 @@ static inline bool sock_flag(const struct sock *sk, enum sock_flags flag) return test_bit(flag, &sk->sk_flags); } +#ifdef CONFIG_NET +extern struct static_key memalloc_socks; +static inline int sk_memalloc_socks(void) +{ + return static_key_false(&memalloc_socks); +} +#else + +static inline int sk_memalloc_socks(void) +{ + return 0; +} + +#endif + static inline gfp_t sk_gfp_atomic(struct sock *sk, gfp_t gfp_mask) { return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC); diff --git a/mm/internal.h b/mm/internal.h index eb76b67890d0..3314f79d775a 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -279,9 +279,6 @@ static inline struct page *mem_map_next(struct page *iter, #define __paginginit __init #endif -/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */ -bool gfp_pfmemalloc_allowed(gfp_t gfp_mask); - /* Memory initialisation debug and verification */ enum mminit_level { MMINIT_WARNING, diff --git a/net/core/filter.c b/net/core/filter.c index d4ce2dc712e3..907efd27ec77 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -83,6 +83,14 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) int err; struct sk_filter *filter; + /* + * If the skb was allocated from pfmemalloc reserves, only + * allow SOCK_MEMALLOC sockets to use it as this socket is + * helping free memory + */ + if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) + return -ENOMEM; + err = security_sock_rcv_skb(sk, skb); if (err) return err; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 368f65c15e4f..fe00d1208167 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -145,6 +145,43 @@ static void skb_under_panic(struct sk_buff *skb, int sz, void *here) BUG(); } + +/* + * kmalloc_reserve is a wrapper around kmalloc_node_track_caller that tells + * the caller if emergency pfmemalloc reserves are being used. If it is and + * the socket is later found to be SOCK_MEMALLOC then PFMEMALLOC reserves + * may be used. Otherwise, the packet data may be discarded until enough + * memory is free + */ +#define kmalloc_reserve(size, gfp, node, pfmemalloc) \ + __kmalloc_reserve(size, gfp, node, _RET_IP_, pfmemalloc) +void *__kmalloc_reserve(size_t size, gfp_t flags, int node, unsigned long ip, + bool *pfmemalloc) +{ + void *obj; + bool ret_pfmemalloc = false; + + /* + * Try a regular allocation, when that fails and we're not entitled + * to the reserves, fail. + */ + obj = kmalloc_node_track_caller(size, + flags | __GFP_NOMEMALLOC | __GFP_NOWARN, + node); + if (obj || !(gfp_pfmemalloc_allowed(flags))) + goto out; + + /* Try again but now we are using pfmemalloc reserves */ + ret_pfmemalloc = true; + obj = kmalloc_node_track_caller(size, flags, node); + +out: + if (pfmemalloc) + *pfmemalloc = ret_pfmemalloc; + + return obj; +} + /* Allocate a new skbuff. We do this ourselves so we can fill in a few * 'private' fields and also do memory statistics to find all the * [BEEP] leaks. @@ -155,8 +192,10 @@ static void skb_under_panic(struct sk_buff *skb, int sz, void *here) * __alloc_skb - allocate a network buffer * @size: size to allocate * @gfp_mask: allocation mask - * @fclone: allocate from fclone cache instead of head cache - * and allocate a cloned (child) skb + * @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache + * instead of head cache and allocate a cloned (child) skb. + * If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for + * allocations in case the data is required for writeback * @node: numa node to allocate memory on * * Allocate a new &sk_buff. The returned buffer has no headroom and a @@ -167,14 +206,19 @@ static void skb_under_panic(struct sk_buff *skb, int sz, void *here) * %GFP_ATOMIC. */ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, - int fclone, int node) + int flags, int node) { struct kmem_cache *cache; struct skb_shared_info *shinfo; struct sk_buff *skb; u8 *data; + bool pfmemalloc; - cache = fclone ? skbuff_fclone_cache : skbuff_head_cache; + cache = (flags & SKB_ALLOC_FCLONE) + ? skbuff_fclone_cache : skbuff_head_cache; + + if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX)) + gfp_mask |= __GFP_MEMALLOC; /* Get the HEAD */ skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); @@ -189,7 +233,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, */ size = SKB_DATA_ALIGN(size); size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - data = kmalloc_node_track_caller(size, gfp_mask, node); + data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc); if (!data) goto nodata; /* kmalloc(size) might give us more room than requested. @@ -207,6 +251,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, memset(skb, 0, offsetof(struct sk_buff, tail)); /* Account for allocated memory : skb + skb->head */ skb->truesize = SKB_TRUESIZE(size); + skb->pfmemalloc = pfmemalloc; atomic_set(&skb->users, 1); skb->head = data; skb->data = data; @@ -222,7 +267,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, atomic_set(&shinfo->dataref, 1); kmemcheck_annotate_variable(shinfo->destructor_arg); - if (fclone) { + if (flags & SKB_ALLOC_FCLONE) { struct sk_buff *child = skb + 1; atomic_t *fclone_ref = (atomic_t *) (child + 1); @@ -232,6 +277,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, atomic_set(fclone_ref, 1); child->fclone = SKB_FCLONE_UNAVAILABLE; + child->pfmemalloc = pfmemalloc; } out: return skb; @@ -302,14 +348,7 @@ static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); #define NETDEV_PAGECNT_BIAS (PAGE_SIZE / SMP_CACHE_BYTES) -/** - * netdev_alloc_frag - allocate a page fragment - * @fragsz: fragment size - * - * Allocates a frag from a page for receive buffer. - * Uses GFP_ATOMIC allocations. - */ -void *netdev_alloc_frag(unsigned int fragsz) +static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { struct netdev_alloc_cache *nc; void *data = NULL; @@ -319,7 +358,7 @@ void *netdev_alloc_frag(unsigned int fragsz) nc = &__get_cpu_var(netdev_alloc_cache); if (unlikely(!nc->page)) { refill: - nc->page = alloc_page(GFP_ATOMIC | __GFP_COLD); + nc->page = alloc_page(gfp_mask); if (unlikely(!nc->page)) goto end; recycle: @@ -343,6 +382,18 @@ end: local_irq_restore(flags); return data; } + +/** + * netdev_alloc_frag - allocate a page fragment + * @fragsz: fragment size + * + * Allocates a frag from a page for receive buffer. + * Uses GFP_ATOMIC allocations. + */ +void *netdev_alloc_frag(unsigned int fragsz) +{ + return __netdev_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD); +} EXPORT_SYMBOL(netdev_alloc_frag); /** @@ -366,7 +417,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) { - void *data = netdev_alloc_frag(fragsz); + void *data; + + if (sk_memalloc_socks()) + gfp_mask |= __GFP_MEMALLOC; + + data = __netdev_alloc_frag(fragsz, gfp_mask); if (likely(data)) { skb = build_skb(data, fragsz); @@ -374,7 +430,8 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, put_page(virt_to_head_page(data)); } } else { - skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE); + skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, + SKB_ALLOC_RX, NUMA_NO_NODE); } if (likely(skb)) { skb_reserve(skb, NET_SKB_PAD); @@ -656,6 +713,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) #if IS_ENABLED(CONFIG_IP_VS) new->ipvs_property = old->ipvs_property; #endif + new->pfmemalloc = old->pfmemalloc; new->protocol = old->protocol; new->mark = old->mark; new->skb_iif = old->skb_iif; @@ -814,6 +872,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) n->fclone = SKB_FCLONE_CLONE; atomic_inc(fclone_ref); } else { + if (skb_pfmemalloc(skb)) + gfp_mask |= __GFP_MEMALLOC; + n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); if (!n) return NULL; @@ -850,6 +911,13 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; } +static inline int skb_alloc_rx_flag(const struct sk_buff *skb) +{ + if (skb_pfmemalloc(skb)) + return SKB_ALLOC_RX; + return 0; +} + /** * skb_copy - create private copy of an sk_buff * @skb: buffer to copy @@ -871,7 +939,8 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) { int headerlen = skb_headroom(skb); unsigned int size = skb_end_offset(skb) + skb->data_len; - struct sk_buff *n = alloc_skb(size, gfp_mask); + struct sk_buff *n = __alloc_skb(size, gfp_mask, + skb_alloc_rx_flag(skb), NUMA_NO_NODE); if (!n) return NULL; @@ -906,7 +975,8 @@ EXPORT_SYMBOL(skb_copy); struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) { unsigned int size = skb_headlen(skb) + headroom; - struct sk_buff *n = alloc_skb(size, gfp_mask); + struct sk_buff *n = __alloc_skb(size, gfp_mask, + skb_alloc_rx_flag(skb), NUMA_NO_NODE); if (!n) goto out; @@ -979,8 +1049,10 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, size = SKB_DATA_ALIGN(size); - data = kmalloc(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), - gfp_mask); + if (skb_pfmemalloc(skb)) + gfp_mask |= __GFP_MEMALLOC; + data = kmalloc_reserve(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), + gfp_mask, NUMA_NO_NODE, NULL); if (!data) goto nodata; size = SKB_WITH_OVERHEAD(ksize(data)); @@ -1092,8 +1164,9 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, /* * Allocate the copy buffer */ - struct sk_buff *n = alloc_skb(newheadroom + skb->len + newtailroom, - gfp_mask); + struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom, + gfp_mask, skb_alloc_rx_flag(skb), + NUMA_NO_NODE); int oldheadroom = skb_headroom(skb); int head_copy_len, head_copy_off; int off; @@ -2775,8 +2848,9 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) skb_release_head_state(nskb); __skb_push(nskb, doffset); } else { - nskb = alloc_skb(hsize + doffset + headroom, - GFP_ATOMIC); + nskb = __alloc_skb(hsize + doffset + headroom, + GFP_ATOMIC, skb_alloc_rx_flag(skb), + NUMA_NO_NODE); if (unlikely(!nskb)) goto err; diff --git a/net/core/sock.c b/net/core/sock.c index 3617f652f6b0..c8c5816289fe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -271,6 +271,9 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); EXPORT_SYMBOL(sysctl_optmem_max); +struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE; +EXPORT_SYMBOL_GPL(memalloc_socks); + /** * sk_set_memalloc - sets %SOCK_MEMALLOC * @sk: socket to set it on @@ -283,6 +286,7 @@ void sk_set_memalloc(struct sock *sk) { sock_set_flag(sk, SOCK_MEMALLOC); sk->sk_allocation |= __GFP_MEMALLOC; + static_key_slow_inc(&memalloc_socks); } EXPORT_SYMBOL_GPL(sk_set_memalloc); @@ -290,6 +294,7 @@ void sk_clear_memalloc(struct sock *sk) { sock_reset_flag(sk, SOCK_MEMALLOC); sk->sk_allocation &= ~__GFP_MEMALLOC; + static_key_slow_dec(&memalloc_socks); } EXPORT_SYMBOL_GPL(sk_clear_memalloc); -- GitLab From c48a11c7ad2623b99bbd6859b0b4234e7f11176f Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:23 -0700 Subject: [PATCH 4933/5711] netvm: propagate page->pfmemalloc to skb The skb->pfmemalloc flag gets set to true iff during the slab allocation of data in __alloc_skb that the the PFMEMALLOC reserves were used. If the packet is fragmented, it is possible that pages will be allocated from the PFMEMALLOC reserve without propagating this information to the skb. This patch propagates page->pfmemalloc from pages allocated for fragments to the skb. Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/skbuff.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0336f02e3667..b814bb8fd5ab 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1247,6 +1247,17 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + /* + * Propagate page->pfmemalloc to the skb if we can. The problem is + * that not all callers have unique ownership of the page. If + * pfmemalloc is set, we check the mapping as a mapping implies + * page->index is set (index and pfmemalloc share space). + * If it's a valid mapping, we cannot use page->pfmemalloc but we + * do not lose pfmemalloc information as the pages would not be + * allocated using __GFP_MEMALLOC. + */ + if (page->pfmemalloc && !page->mapping) + skb->pfmemalloc = true; frag->page.p = page; frag->page_offset = off; skb_frag_size_set(frag, size); -- GitLab From 0614002bb5f7411e61ffa0dfe5be1f2c84df3da3 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:24 -0700 Subject: [PATCH 4934/5711] netvm: propagate page->pfmemalloc from skb_alloc_page to skb The skb->pfmemalloc flag gets set to true iff during the slab allocation of data in __alloc_skb that the the PFMEMALLOC reserves were used. If page splitting is used, it is possible that pages will be allocated from the PFMEMALLOC reserve without propagating this information to the skb. This patch propagates page->pfmemalloc from pages allocated for fragments to the skb. It works by reintroducing and expanding the skb_alloc_page() API to take an skb. If the page was allocated from pfmemalloc reserves, it is automatically copied. If the driver allocates the page before the skb, it should call skb_propagate_pfmemalloc() after the skb is allocated to ensure the flag is copied properly. Failure to do so is not critical. The resulting driver may perform slower if it is used for swap-over-NBD or swap-over-NFS but it should not result in failure. [davem@davemloft.net: API rename and consistency] Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 +- drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 2 +- drivers/net/ethernet/intel/igb/igb_main.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +- .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 1 - drivers/net/usb/cdc-phonet.c | 2 +- drivers/usb/gadget/f_phonet.c | 2 +- include/linux/skbuff.h | 55 +++++++++++++++++++ 8 files changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 8596acaa402b..d49933ed551f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -528,7 +528,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, #endif while (n--) { - pg = alloc_page(gfp); + pg = __skb_alloc_page(gfp, NULL); if (unlikely(!pg)) { q->alloc_failed++; break; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index f2d1ecdcaf98..8877fbfefb63 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -653,7 +653,7 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl, alloc_small_pages: while (n--) { - page = alloc_page(gfp | __GFP_NOWARN | __GFP_COLD); + page = __skb_alloc_page(gfp | __GFP_NOWARN, NULL); if (unlikely(!page)) { fl->alloc_failed++; break; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 1050411e7ca3..b7c2d5050572 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -6235,7 +6235,7 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, return true; if (!page) { - page = alloc_page(GFP_ATOMIC | __GFP_COLD); + page = __skb_alloc_page(GFP_ATOMIC, bi->skb); bi->page = page; if (unlikely(!page)) { rx_ring->rx_stats.alloc_failed++; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c709eae58c63..4326f74f7137 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1141,8 +1141,8 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring, /* alloc new page for storage */ if (likely(!page)) { - page = alloc_pages(GFP_ATOMIC | __GFP_COLD | __GFP_COMP, - ixgbe_rx_pg_order(rx_ring)); + page = __skb_alloc_pages(GFP_ATOMIC | __GFP_COLD | __GFP_COMP, + bi->skb, ixgbe_rx_pg_order(rx_ring)); if (unlikely(!page)) { rx_ring->rx_stats.alloc_rx_page_failed++; return false; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 3f9841d619ad..60ef64587412 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -352,7 +352,6 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, adapter->alloc_rx_buff_failed++; goto no_buffers; } - bi->skb = skb; } if (!bi->dma) { diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 187c144c5e5b..64610048ce87 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -130,7 +130,7 @@ static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags) struct page *page; int err; - page = alloc_page(gfp_flags); + page = __skb_alloc_page(gfp_flags | __GFP_NOMEMALLOC, NULL); if (!page) return -ENOMEM; diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 965a6293206a..8ee9268fe253 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -301,7 +301,7 @@ pn_rx_submit(struct f_phonet *fp, struct usb_request *req, gfp_t gfp_flags) struct page *page; int err; - page = alloc_page(gfp_flags); + page = __skb_alloc_page(gfp_flags | __GFP_NOMEMALLOC, NULL); if (!page) return -ENOMEM; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b814bb8fd5ab..7632c87da2c9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1774,6 +1774,61 @@ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, return __netdev_alloc_skb_ip_align(dev, length, GFP_ATOMIC); } +/* + * __skb_alloc_page - allocate pages for ps-rx on a skb and preserve pfmemalloc data + * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX + * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used + * @order: size of the allocation + * + * Allocate a new page. + * + * %NULL is returned if there is no free memory. +*/ +static inline struct page *__skb_alloc_pages(gfp_t gfp_mask, + struct sk_buff *skb, + unsigned int order) +{ + struct page *page; + + gfp_mask |= __GFP_COLD; + + if (!(gfp_mask & __GFP_NOMEMALLOC)) + gfp_mask |= __GFP_MEMALLOC; + + page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order); + if (skb && page && page->pfmemalloc) + skb->pfmemalloc = true; + + return page; +} + +/** + * __skb_alloc_page - allocate a page for ps-rx for a given skb and preserve pfmemalloc data + * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX + * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used + * + * Allocate a new page. + * + * %NULL is returned if there is no free memory. + */ +static inline struct page *__skb_alloc_page(gfp_t gfp_mask, + struct sk_buff *skb) +{ + return __skb_alloc_pages(gfp_mask, skb, 0); +} + +/** + * skb_propagate_pfmemalloc - Propagate pfmemalloc if skb is allocated after RX page + * @page: The page that was allocated from skb_alloc_page + * @skb: The skb that may need pfmemalloc set + */ +static inline void skb_propagate_pfmemalloc(struct page *page, + struct sk_buff *skb) +{ + if (page && page->pfmemalloc) + skb->pfmemalloc = true; +} + /** * skb_frag_page - retrieve the page refered to by a paged fragment * @frag: the paged fragment -- GitLab From b4b9e3558508980fc0cd161a545ffb55a1f13ee9 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:26 -0700 Subject: [PATCH 4935/5711] netvm: set PF_MEMALLOC as appropriate during SKB processing In order to make sure pfmemalloc packets receive all memory needed to proceed, ensure processing of pfmemalloc SKBs happens under PF_MEMALLOC. This is limited to a subset of protocols that are expected to be used for writing to swap. Taps are not allowed to use PF_MEMALLOC as these are expected to communicate with userspace processes which could be paged out. [a.p.zijlstra@chello.nl: Ideas taken from various patches] [jslaby@suse.cz: Lock imbalance fix] Signed-off-by: Mel Gorman Acked-by: David S. Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/net/sock.h | 5 +++++ net/core/dev.c | 53 ++++++++++++++++++++++++++++++++++++++++------ net/core/sock.c | 16 ++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 81198632ac2a..43a470d40d76 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -754,8 +754,13 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s return 0; } +extern int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); + static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) { + if (sk_memalloc_socks() && skb_pfmemalloc(skb)) + return __sk_backlog_rcv(sk, skb); + return sk->sk_backlog_rcv(sk, skb); } diff --git a/net/core/dev.c b/net/core/dev.c index 0ebaea16632f..ce132443d5d1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3155,6 +3155,23 @@ void netdev_rx_handler_unregister(struct net_device *dev) } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); +/* + * Limit the use of PFMEMALLOC reserves to those protocols that implement + * the special handling of PFMEMALLOC skbs. + */ +static bool skb_pfmemalloc_protocol(struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_ARP): + case __constant_htons(ETH_P_IP): + case __constant_htons(ETH_P_IPV6): + case __constant_htons(ETH_P_8021Q): + return true; + default: + return false; + } +} + static int __netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; @@ -3164,14 +3181,27 @@ static int __netif_receive_skb(struct sk_buff *skb) bool deliver_exact = false; int ret = NET_RX_DROP; __be16 type; + unsigned long pflags = current->flags; net_timestamp_check(!netdev_tstamp_prequeue, skb); trace_netif_receive_skb(skb); + /* + * PFMEMALLOC skbs are special, they should + * - be delivered to SOCK_MEMALLOC sockets only + * - stay away from userspace + * - have bounded memory usage + * + * Use PF_MEMALLOC as this saves us from propagating the allocation + * context down to all allocation sites. + */ + if (sk_memalloc_socks() && skb_pfmemalloc(skb)) + current->flags |= PF_MEMALLOC; + /* if we've gotten here through NAPI, check netpoll */ if (netpoll_receive_skb(skb)) - return NET_RX_DROP; + goto out; orig_dev = skb->dev; @@ -3191,7 +3221,7 @@ another_round: if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { skb = vlan_untag(skb); if (unlikely(!skb)) - goto out; + goto unlock; } #ifdef CONFIG_NET_CLS_ACT @@ -3201,6 +3231,9 @@ another_round: } #endif + if (sk_memalloc_socks() && skb_pfmemalloc(skb)) + goto skip_taps; + list_for_each_entry_rcu(ptype, &ptype_all, list) { if (!ptype->dev || ptype->dev == skb->dev) { if (pt_prev) @@ -3209,13 +3242,18 @@ another_round: } } +skip_taps: #ifdef CONFIG_NET_CLS_ACT skb = handle_ing(skb, &pt_prev, &ret, orig_dev); if (!skb) - goto out; + goto unlock; ncls: #endif + if (sk_memalloc_socks() && skb_pfmemalloc(skb) + && !skb_pfmemalloc_protocol(skb)) + goto drop; + rx_handler = rcu_dereference(skb->dev->rx_handler); if (vlan_tx_tag_present(skb)) { if (pt_prev) { @@ -3225,7 +3263,7 @@ ncls: if (vlan_do_receive(&skb, !rx_handler)) goto another_round; else if (unlikely(!skb)) - goto out; + goto unlock; } if (rx_handler) { @@ -3235,7 +3273,7 @@ ncls: } switch (rx_handler(&skb)) { case RX_HANDLER_CONSUMED: - goto out; + goto unlock; case RX_HANDLER_ANOTHER: goto another_round; case RX_HANDLER_EXACT: @@ -3268,6 +3306,7 @@ ncls: else ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { +drop: atomic_long_inc(&skb->dev->rx_dropped); kfree_skb(skb); /* Jamal, now you will not able to escape explaining @@ -3276,8 +3315,10 @@ ncls: ret = NET_RX_DROP; } -out: +unlock: rcu_read_unlock(); +out: + tsk_restore_flags(current, pflags, PF_MEMALLOC); return ret; } diff --git a/net/core/sock.c b/net/core/sock.c index c8c5816289fe..32fdcd2d6e8f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -298,6 +298,22 @@ void sk_clear_memalloc(struct sock *sk) } EXPORT_SYMBOL_GPL(sk_clear_memalloc); +int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + int ret; + unsigned long pflags = current->flags; + + /* these should have been dropped before queueing */ + BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); + + current->flags |= PF_MEMALLOC; + ret = sk->sk_backlog_rcv(sk, skb); + tsk_restore_flags(current, pflags, PF_MEMALLOC); + + return ret; +} +EXPORT_SYMBOL(__sk_backlog_rcv); + #if defined(CONFIG_CGROUPS) #if !defined(CONFIG_NET_CLS_CGROUP) int net_cls_subsys_id = -1; -- GitLab From 381760eadc393bcb1bb328510ad75cf13431806d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:30 -0700 Subject: [PATCH 4936/5711] mm: micro-optimise slab to avoid a function call Getting and putting objects in SLAB currently requires a function call but the bulk of the work is related to PFMEMALLOC reserves which are only consumed when network-backed storage is critical. Use an inline function to determine if the function call is required. Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 77be18dab73c..f8b0d539b482 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -118,6 +118,8 @@ #include #include +#include + #include #include #include @@ -965,7 +967,7 @@ out: spin_unlock_irqrestore(&l3->list_lock, flags); } -static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, +static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, gfp_t flags, bool force_refill) { int i; @@ -1012,7 +1014,20 @@ static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, return objp; } -static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, +static inline void *ac_get_obj(struct kmem_cache *cachep, + struct array_cache *ac, gfp_t flags, bool force_refill) +{ + void *objp; + + if (unlikely(sk_memalloc_socks())) + objp = __ac_get_obj(cachep, ac, flags, force_refill); + else + objp = ac->entry[--ac->avail]; + + return objp; +} + +static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, void *objp) { if (unlikely(pfmemalloc_active)) { @@ -1022,6 +1037,15 @@ static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, set_obj_pfmemalloc(&objp); } + return objp; +} + +static inline void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, + void *objp) +{ + if (unlikely(sk_memalloc_socks())) + objp = __ac_put_obj(cachep, ac, objp); + ac->entry[ac->avail++] = objp; } -- GitLab From 7f338fe4540b1d0600b02314c7d885fd358e9eca Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:32 -0700 Subject: [PATCH 4937/5711] nbd: set SOCK_MEMALLOC for access to PFMEMALLOC reserves Set SOCK_MEMALLOC on the NBD socket to allow access to PFMEMALLOC reserves so pages backed by NBD, particularly if swap related, can be cleaned to prevent the machine being deadlocked. It is still possible that the PFMEMALLOC reserves get depleted resulting in deadlock but this can be resolved by the administrator by increasing min_free_kbytes. Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/nbd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 061427a75d37..76bc96fd01c8 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -154,6 +154,7 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, struct msghdr msg; struct kvec iov; sigset_t blocked, oldset; + unsigned long pflags = current->flags; if (unlikely(!sock)) { dev_err(disk_to_dev(nbd->disk), @@ -167,8 +168,9 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, siginitsetinv(&blocked, sigmask(SIGKILL)); sigprocmask(SIG_SETMASK, &blocked, &oldset); + current->flags |= PF_MEMALLOC; do { - sock->sk->sk_allocation = GFP_NOIO; + sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; @@ -214,6 +216,7 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, } while (size > 0); sigprocmask(SIG_SETMASK, &oldset, NULL); + tsk_restore_flags(current, pflags, PF_MEMALLOC); return result; } @@ -405,6 +408,7 @@ static int nbd_do_it(struct nbd_device *nbd) BUG_ON(nbd->magic != NBD_MAGIC); + sk_set_memalloc(nbd->sock->sk); nbd->pid = task_pid_nr(current); ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); if (ret) { -- GitLab From 5515061d22f0f9976ae7815864bfd22042d36848 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:35 -0700 Subject: [PATCH 4938/5711] mm: throttle direct reclaimers if PF_MEMALLOC reserves are low and swap is backed by network storage If swap is backed by network storage such as NBD, there is a risk that a large number of reclaimers can hang the system by consuming all PF_MEMALLOC reserves. To avoid these hangs, the administrator must tune min_free_kbytes in advance which is a bit fragile. This patch throttles direct reclaimers if half the PF_MEMALLOC reserves are in use. If the system is routinely getting throttled the system administrator can increase min_free_kbytes so degradation is smoother but the system will keep running. Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 1 + mm/page_alloc.c | 1 + mm/vmscan.c | 128 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 122 insertions(+), 8 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 64b2c3a48286..2daa54f55db7 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -705,6 +705,7 @@ typedef struct pglist_data { range, including holes */ int node_id; wait_queue_head_t kswapd_wait; + wait_queue_head_t pfmemalloc_wait; struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */ int kswapd_max_order; enum zone_type classzone_idx; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ef2d1e72fc07..48aee0f5902f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4389,6 +4389,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, pgdat_resize_init(pgdat); pgdat->nr_zones = 0; init_waitqueue_head(&pgdat->kswapd_wait); + init_waitqueue_head(&pgdat->pfmemalloc_wait); pgdat->kswapd_max_order = 0; pgdat_page_cgroup_init(pgdat); diff --git a/mm/vmscan.c b/mm/vmscan.c index 6b1f89a91212..021a44a7bd20 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2112,6 +2112,80 @@ out: return 0; } +static bool pfmemalloc_watermark_ok(pg_data_t *pgdat) +{ + struct zone *zone; + unsigned long pfmemalloc_reserve = 0; + unsigned long free_pages = 0; + int i; + bool wmark_ok; + + for (i = 0; i <= ZONE_NORMAL; i++) { + zone = &pgdat->node_zones[i]; + pfmemalloc_reserve += min_wmark_pages(zone); + free_pages += zone_page_state(zone, NR_FREE_PAGES); + } + + wmark_ok = free_pages > pfmemalloc_reserve / 2; + + /* kswapd must be awake if processes are being throttled */ + if (!wmark_ok && waitqueue_active(&pgdat->kswapd_wait)) { + pgdat->classzone_idx = min(pgdat->classzone_idx, + (enum zone_type)ZONE_NORMAL); + wake_up_interruptible(&pgdat->kswapd_wait); + } + + return wmark_ok; +} + +/* + * Throttle direct reclaimers if backing storage is backed by the network + * and the PFMEMALLOC reserve for the preferred node is getting dangerously + * depleted. kswapd will continue to make progress and wake the processes + * when the low watermark is reached + */ +static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, + nodemask_t *nodemask) +{ + struct zone *zone; + int high_zoneidx = gfp_zone(gfp_mask); + pg_data_t *pgdat; + + /* + * Kernel threads should not be throttled as they may be indirectly + * responsible for cleaning pages necessary for reclaim to make forward + * progress. kjournald for example may enter direct reclaim while + * committing a transaction where throttling it could forcing other + * processes to block on log_wait_commit(). + */ + if (current->flags & PF_KTHREAD) + return; + + /* Check if the pfmemalloc reserves are ok */ + first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone); + pgdat = zone->zone_pgdat; + if (pfmemalloc_watermark_ok(pgdat)) + return; + + /* + * If the caller cannot enter the filesystem, it's possible that it + * is due to the caller holding an FS lock or performing a journal + * transaction in the case of a filesystem like ext[3|4]. In this case, + * it is not safe to block on pfmemalloc_wait as kswapd could be + * blocked waiting on the same lock. Instead, throttle for up to a + * second before continuing. + */ + if (!(gfp_mask & __GFP_FS)) { + wait_event_interruptible_timeout(pgdat->pfmemalloc_wait, + pfmemalloc_watermark_ok(pgdat), HZ); + return; + } + + /* Throttle until kswapd wakes the process */ + wait_event_killable(zone->zone_pgdat->pfmemalloc_wait, + pfmemalloc_watermark_ok(pgdat)); +} + unsigned long try_to_free_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask) { @@ -2131,6 +2205,15 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, .gfp_mask = sc.gfp_mask, }; + throttle_direct_reclaim(gfp_mask, zonelist, nodemask); + + /* + * Do not enter reclaim if fatal signal is pending. 1 is returned so + * that the page allocator does not consider triggering OOM + */ + if (fatal_signal_pending(current)) + return 1; + trace_mm_vmscan_direct_reclaim_begin(order, sc.may_writepage, gfp_mask); @@ -2275,8 +2358,13 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages, return balanced_pages >= (present_pages >> 2); } -/* is kswapd sleeping prematurely? */ -static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, +/* + * Prepare kswapd for sleeping. This verifies that there are no processes + * waiting in throttle_direct_reclaim() and that watermarks have been met. + * + * Returns true if kswapd is ready to sleep + */ +static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, int classzone_idx) { int i; @@ -2285,7 +2373,21 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, /* If a direct reclaimer woke kswapd within HZ/10, it's premature */ if (remaining) - return true; + return false; + + /* + * There is a potential race between when kswapd checks its watermarks + * and a process gets throttled. There is also a potential race if + * processes get throttled, kswapd wakes, a large process exits therby + * balancing the zones that causes kswapd to miss a wakeup. If kswapd + * is going to sleep, no process should be sleeping on pfmemalloc_wait + * so wake them now if necessary. If necessary, processes will wake + * kswapd and get throttled again + */ + if (waitqueue_active(&pgdat->pfmemalloc_wait)) { + wake_up(&pgdat->pfmemalloc_wait); + return false; + } /* Check the watermark levels */ for (i = 0; i <= classzone_idx; i++) { @@ -2318,9 +2420,9 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, * must be balanced */ if (order) - return !pgdat_balanced(pgdat, balanced, classzone_idx); + return pgdat_balanced(pgdat, balanced, classzone_idx); else - return !all_zones_ok; + return all_zones_ok; } /* @@ -2546,6 +2648,16 @@ loop_again: } } + + /* + * If the low watermark is met there is no need for processes + * to be throttled on pfmemalloc_wait as they should not be + * able to safely make forward progress. Wake them + */ + if (waitqueue_active(&pgdat->pfmemalloc_wait) && + pfmemalloc_watermark_ok(pgdat)) + wake_up(&pgdat->pfmemalloc_wait); + if (all_zones_ok || (order && pgdat_balanced(pgdat, balanced, *classzone_idx))) break; /* kswapd: all done */ /* @@ -2647,7 +2759,7 @@ out: } /* - * Return the order we were reclaiming at so sleeping_prematurely() + * Return the order we were reclaiming at so prepare_kswapd_sleep() * makes a decision on the order we were last reclaiming at. However, * if another caller entered the allocator slow path while kswapd * was awake, order will remain at the higher level @@ -2667,7 +2779,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); /* Try to sleep for a short interval */ - if (!sleeping_prematurely(pgdat, order, remaining, classzone_idx)) { + if (prepare_kswapd_sleep(pgdat, order, remaining, classzone_idx)) { remaining = schedule_timeout(HZ/10); finish_wait(&pgdat->kswapd_wait, &wait); prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); @@ -2677,7 +2789,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) * After a short sleep, check if it was a premature sleep. If not, then * go fully to sleep until explicitly woken up. */ - if (!sleeping_prematurely(pgdat, order, remaining, classzone_idx)) { + if (prepare_kswapd_sleep(pgdat, order, remaining, classzone_idx)) { trace_mm_vmscan_kswapd_sleep(pgdat->node_id); /* -- GitLab From 68243e76ee343d63c6cf76978588a885951e2818 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:39 -0700 Subject: [PATCH 4939/5711] mm: account for the number of times direct reclaimers get throttled Under significant pressure when writing back to network-backed storage, direct reclaimers may get throttled. This is expected to be a short-lived event and the processes get woken up again but processes do get stalled. This patch counts how many times such stalling occurs. It's up to the administrator whether to reduce these stalls by increasing min_free_kbytes. Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/vm_event_item.h | 1 + mm/vmscan.c | 3 +++ mm/vmstat.c | 1 + 3 files changed, 5 insertions(+) diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 06f8e3858251..57f7b1091511 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -30,6 +30,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, FOR_ALL_ZONES(PGSTEAL_DIRECT), FOR_ALL_ZONES(PGSCAN_KSWAPD), FOR_ALL_ZONES(PGSCAN_DIRECT), + PGSCAN_DIRECT_THROTTLE, #ifdef CONFIG_NUMA PGSCAN_ZONE_RECLAIM_FAILED, #endif diff --git a/mm/vmscan.c b/mm/vmscan.c index 021a44a7bd20..88804017e7d6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2167,6 +2167,9 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, if (pfmemalloc_watermark_ok(pgdat)) return; + /* Account for the throttling */ + count_vm_event(PGSCAN_DIRECT_THROTTLE); + /* * If the caller cannot enter the filesystem, it's possible that it * is due to the caller holding an FS lock or performing a journal diff --git a/mm/vmstat.c b/mm/vmstat.c index 1bbbbd9776ad..df7a6748231d 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -745,6 +745,7 @@ const char * const vmstat_text[] = { TEXTS_FOR_ZONES("pgsteal_direct") TEXTS_FOR_ZONES("pgscan_kswapd") TEXTS_FOR_ZONES("pgscan_direct") + "pgscan_direct_throttle", #ifdef CONFIG_NUMA "zone_reclaim_failed", -- GitLab From c76562b6709fee5eff8a6a779be41c0bce661fd7 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:41 -0700 Subject: [PATCH 4940/5711] netvm: prevent a stream-specific deadlock This patch series is based on top of "Swap-over-NBD without deadlocking v15" as it depends on the same reservation of PF_MEMALLOC reserves logic. When a user or administrator requires swap for their application, they create a swap partition and file, format it with mkswap and activate it with swapon. In diskless systems this is not an option so if swap if required then swapping over the network is considered. The two likely scenarios are when blade servers are used as part of a cluster where the form factor or maintenance costs do not allow the use of disks and thin clients. The Linux Terminal Server Project recommends the use of the Network Block Device (NBD) for swap but this is not always an option. There is no guarantee that the network attached storage (NAS) device is running Linux or supports NBD. However, it is likely that it supports NFS so there are users that want support for swapping over NFS despite any performance concern. Some distributions currently carry patches that support swapping over NFS but it would be preferable to support it in the mainline kernel. Patch 1 avoids a stream-specific deadlock that potentially affects TCP. Patch 2 is a small modification to SELinux to avoid using PFMEMALLOC reserves. Patch 3 adds three helpers for filesystems to handle swap cache pages. For example, page_file_mapping() returns page->mapping for file-backed pages and the address_space of the underlying swap file for swap cache pages. Patch 4 adds two address_space_operations to allow a filesystem to pin all metadata relevant to a swapfile in memory. Upon successful activation, the swapfile is marked SWP_FILE and the address space operation ->direct_IO is used for writing and ->readpage for reading in swap pages. Patch 5 notes that patch 3 is bolting filesystem-specific-swapfile-support onto the side and that the default handlers have different information to what is available to the filesystem. This patch refactors the code so that there are generic handlers for each of the new address_space operations. Patch 6 adds an API to allow a vector of kernel addresses to be translated to struct pages and pinned for IO. Patch 7 adds support for using highmem pages for swap by kmapping the pages before calling the direct_IO handler. Patch 8 updates NFS to use the helpers from patch 3 where necessary. Patch 9 avoids setting PF_private on PG_swapcache pages within NFS. Patch 10 implements the new swapfile-related address_space operations for NFS and teaches the direct IO handler how to manage kernel addresses. Patch 11 prevents page allocator recursions in NFS by using GFP_NOIO where appropriate. Patch 12 fixes a NULL pointer dereference that occurs when using swap-over-NFS. With the patches applied, it is possible to mount a swapfile that is on an NFS filesystem. Swap performance is not great with a swap stress test taking roughly twice as long to complete than if the swap device was backed by NBD. This patch: netvm: prevent a stream-specific deadlock It could happen that all !SOCK_MEMALLOC sockets have buffered so much data that we're over the global rmem limit. This will prevent SOCK_MEMALLOC buffers from receiving data, which will prevent userspace from running, which is needed to reduce the buffered data. Fix this by exempting the SOCK_MEMALLOC sockets from the rmem limit. Once this change it applied, it is important that sockets that set SOCK_MEMALLOC do not clear the flag until the socket is being torn down. If this happens, a warning is generated and the tokens reclaimed to avoid accounting errors until the bug is fixed. [davem@davemloft.net: Warning about clearing SOCK_MEMALLOC] Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: David S. Miller Acked-by: Rik van Riel Cc: Trond Myklebust Cc: Neil Brown Cc: Christoph Hellwig Cc: Mike Christie Cc: Eric B Munson Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/net/sock.h | 8 +++++--- net/caif/caif_socket.c | 2 +- net/core/sock.c | 14 +++++++++++++- net/ipv4/tcp_input.c | 21 +++++++++++---------- net/sctp/ulpevent.c | 3 ++- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 43a470d40d76..b3730239bf18 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1329,12 +1329,14 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size) __sk_mem_schedule(sk, size, SK_MEM_SEND); } -static inline bool sk_rmem_schedule(struct sock *sk, int size) +static inline bool +sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size) { if (!sk_has_account(sk)) return true; - return size <= sk->sk_forward_alloc || - __sk_mem_schedule(sk, size, SK_MEM_RECV); + return size<= sk->sk_forward_alloc || + __sk_mem_schedule(sk, size, SK_MEM_RECV) || + skb_pfmemalloc(skb); } static inline void sk_mem_reclaim(struct sock *sk) diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 78f1cdad5b33..095259f83902 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -141,7 +141,7 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) err = sk_filter(sk, skb); if (err) return err; - if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { + if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { set_rx_flow_off(cf_sk); net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); diff --git a/net/core/sock.c b/net/core/sock.c index 32fdcd2d6e8f..6b654b3ddfda 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -295,6 +295,18 @@ void sk_clear_memalloc(struct sock *sk) sock_reset_flag(sk, SOCK_MEMALLOC); sk->sk_allocation &= ~__GFP_MEMALLOC; static_key_slow_dec(&memalloc_socks); + + /* + * SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward + * progress of swapping. However, if SOCK_MEMALLOC is cleared while + * it has rmem allocations there is a risk that the user of the + * socket cannot make forward progress due to exceeding the rmem + * limits. By rights, sk_clear_memalloc() should only be called + * on sockets being torn down but warn and reset the accounting if + * that assumption breaks. + */ + if (WARN_ON(sk->sk_forward_alloc)) + sk_mem_reclaim(sk); } EXPORT_SYMBOL_GPL(sk_clear_memalloc); @@ -396,7 +408,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) return err; - if (!sk_rmem_schedule(sk, skb->truesize)) { + if (!sk_rmem_schedule(sk, skb, skb->truesize)) { atomic_inc(&sk->sk_drops); return -ENOBUFS; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a356e1fecf9a..00b91b4b8665 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4351,19 +4351,20 @@ static void tcp_ofo_queue(struct sock *sk) static bool tcp_prune_ofo_queue(struct sock *sk); static int tcp_prune_queue(struct sock *sk); -static int tcp_try_rmem_schedule(struct sock *sk, unsigned int size) +static int tcp_try_rmem_schedule(struct sock *sk, struct sk_buff *skb, + unsigned int size) { if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || - !sk_rmem_schedule(sk, size)) { + !sk_rmem_schedule(sk, skb, size)) { if (tcp_prune_queue(sk) < 0) return -1; - if (!sk_rmem_schedule(sk, size)) { + if (!sk_rmem_schedule(sk, skb, size)) { if (!tcp_prune_ofo_queue(sk)) return -1; - if (!sk_rmem_schedule(sk, size)) + if (!sk_rmem_schedule(sk, skb, size)) return -1; } } @@ -4418,7 +4419,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) TCP_ECN_check_ce(tp, skb); - if (unlikely(tcp_try_rmem_schedule(sk, skb->truesize))) { + if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); __kfree_skb(skb); return; @@ -4552,17 +4553,17 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) { - struct sk_buff *skb; + struct sk_buff *skb = NULL; struct tcphdr *th; bool fragstolen; - if (tcp_try_rmem_schedule(sk, size + sizeof(*th))) - goto err; - skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); if (!skb) goto err; + if (tcp_try_rmem_schedule(sk, skb, size + sizeof(*th))) + goto err_free; + th = (struct tcphdr *)skb_put(skb, sizeof(*th)); skb_reset_transport_header(skb); memset(th, 0, sizeof(*th)); @@ -4633,7 +4634,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (eaten <= 0) { queue_and_out: if (eaten < 0 && - tcp_try_rmem_schedule(sk, skb->truesize)) + tcp_try_rmem_schedule(sk, skb, skb->truesize)) goto drop; eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen); diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 33d894776192..10c018a5b9fe 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -702,7 +702,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, if (rx_count >= asoc->base.sk->sk_rcvbuf) { if ((asoc->base.sk->sk_userlocks & SOCK_RCVBUF_LOCK) || - (!sk_rmem_schedule(asoc->base.sk, chunk->skb->truesize))) + (!sk_rmem_schedule(asoc->base.sk, chunk->skb, + chunk->skb->truesize))) goto fail; } -- GitLab From 6290c2c439732727899405f39fb76c2f5585b707 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:44 -0700 Subject: [PATCH 4941/5711] selinux: tag avc cache alloc as non-critical Failing to allocate a cache entry will only harm performance not correctness. Do not consume valuable reserve pages for something like that. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: Eric Paris Acked-by: Rik van Riel Cc: James Morris Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/avc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 68d82daed257..4d3fab47e643 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -274,7 +274,7 @@ static struct avc_node *avc_alloc_node(void) { struct avc_node *node; - node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC); + node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC|__GFP_NOMEMALLOC); if (!node) goto out; -- GitLab From f981c5950fa85916ba49bea5d9a7a5078f47e569 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:47 -0700 Subject: [PATCH 4942/5711] mm: methods for teaching filesystems about PG_swapcache pages In order to teach filesystems to handle swap cache pages, three new page functions are introduced: pgoff_t page_file_index(struct page *); loff_t page_file_offset(struct page *); struct address_space *page_file_mapping(struct page *); page_file_index() - gives the offset of this page in the file in PAGE_CACHE_SIZE blocks. Like page->index is for mapped pages, this function also gives the correct index for PG_swapcache pages. page_file_offset() - uses page_file_index(), so that it will give the expected result, even for PG_swapcache pages. page_file_mapping() - gives the mapping backing the actual page; that is for swap cache pages it will give swap_file->f_mapping. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 25 +++++++++++++++++++++++++ include/linux/pagemap.h | 5 +++++ include/linux/swap.h | 1 + mm/swapfile.c | 26 ++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 7c6dfd2faa69..7cdac1676b59 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -805,6 +805,17 @@ static inline void *page_rmapping(struct page *page) return (void *)((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS); } +extern struct address_space *__page_file_mapping(struct page *); + +static inline +struct address_space *page_file_mapping(struct page *page) +{ + if (unlikely(PageSwapCache(page))) + return __page_file_mapping(page); + + return page->mapping; +} + static inline int PageAnon(struct page *page) { return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; @@ -821,6 +832,20 @@ static inline pgoff_t page_index(struct page *page) return page->index; } +extern pgoff_t __page_file_index(struct page *page); + +/* + * Return the file index of the page. Regular pagecache pages use ->index + * whereas swapcache pages use swp_offset(->private) + */ +static inline pgoff_t page_file_index(struct page *page) +{ + if (unlikely(PageSwapCache(page))) + return __page_file_index(page); + + return page->index; +} + /* * Return true if this page is mapped into pagetables. */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 7cfad3bbb0cc..e42c762f0dc7 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -286,6 +286,11 @@ static inline loff_t page_offset(struct page *page) return ((loff_t)page->index) << PAGE_CACHE_SHIFT; } +static inline loff_t page_file_offset(struct page *page) +{ + return ((loff_t)page_file_index(page)) << PAGE_CACHE_SHIFT; +} + extern pgoff_t linear_hugepage_index(struct vm_area_struct *vma, unsigned long address); diff --git a/include/linux/swap.h b/include/linux/swap.h index 9a16bb1cefd1..e62425ded2ed 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -356,6 +356,7 @@ extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t swapdev_block(int, pgoff_t); extern int page_swapcount(struct page *); +extern struct swap_info_struct *page_swap_info(struct page *); extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; diff --git a/mm/swapfile.c b/mm/swapfile.c index 71373d03fcee..f89af5ba2eb2 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -2285,6 +2286,31 @@ int swapcache_prepare(swp_entry_t entry) return __swap_duplicate(entry, SWAP_HAS_CACHE); } +struct swap_info_struct *page_swap_info(struct page *page) +{ + swp_entry_t swap = { .val = page_private(page) }; + BUG_ON(!PageSwapCache(page)); + return swap_info[swp_type(swap)]; +} + +/* + * out-of-line __page_file_ methods to avoid include hell. + */ +struct address_space *__page_file_mapping(struct page *page) +{ + VM_BUG_ON(!PageSwapCache(page)); + return page_swap_info(page)->swap_file->f_mapping; +} +EXPORT_SYMBOL_GPL(__page_file_mapping); + +pgoff_t __page_file_index(struct page *page) +{ + swp_entry_t swap = { .val = page_private(page) }; + VM_BUG_ON(!PageSwapCache(page)); + return swp_offset(swap); +} +EXPORT_SYMBOL_GPL(__page_file_index); + /* * add_swap_count_continuation - called when a swap count is duplicated * beyond SWAP_MAP_MAX, it allocates a new page and links that to the entry's -- GitLab From 18022c5d8627a7a9ba8097a0f238b513fae6f5b8 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:51 -0700 Subject: [PATCH 4943/5711] mm: add get_kernel_page[s] for pinning of kernel addresses for I/O This patch adds two new APIs get_kernel_pages() and get_kernel_page() that may be used to pin a vector of kernel addresses for IO. The initial user is expected to be NFS for allowing pages to be written to swap using aops->direct_IO(). Strictly speaking, swap-over-NFS only needs to pin one page for IO but it makes sense to express the API in terms of a vector and add a helper for pinning single pages. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Cc: Mark Salter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/blk_types.h | 2 ++ include/linux/fs.h | 2 ++ include/linux/mm.h | 4 +++ mm/swap.c | 53 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 0edb65dd8edd..7b7ac9ccec7a 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -160,6 +160,7 @@ enum rq_flag_bits { __REQ_FLUSH_SEQ, /* request for flush sequence */ __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ + __REQ_KERNEL, /* direct IO to kernel pages */ __REQ_NR_BITS, /* stops here */ }; @@ -201,5 +202,6 @@ enum rq_flag_bits { #define REQ_IO_STAT (1 << __REQ_IO_STAT) #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) #define REQ_SECURE (1 << __REQ_SECURE) +#define REQ_KERNEL (1 << __REQ_KERNEL) #endif /* __LINUX_BLK_TYPES_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 8fabb037a48d..9d77309da153 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -165,6 +165,8 @@ struct inodes_stat_t { #define READ 0 #define WRITE RW_MASK #define READA RWA_MASK +#define KERNEL_READ (READ|REQ_KERNEL) +#define KERNEL_WRITE (WRITE|REQ_KERNEL) #define READ_SYNC (READ | REQ_SYNC) #define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE) diff --git a/include/linux/mm.h b/include/linux/mm.h index 7cdac1676b59..bd079a1b0fdc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1019,6 +1019,10 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, struct page **pages, struct vm_area_struct **vmas); int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages); +struct kvec; +int get_kernel_pages(const struct kvec *iov, int nr_pages, int write, + struct page **pages); +int get_kernel_page(unsigned long start, int write, struct page **pages); struct page *get_dump_page(unsigned long addr); extern int try_to_release_page(struct page * page, gfp_t gfp_mask); diff --git a/mm/swap.c b/mm/swap.c index 4e7e2ec67078..7d7f80c8044a 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -236,6 +236,59 @@ void put_pages_list(struct list_head *pages) } EXPORT_SYMBOL(put_pages_list); +/* + * get_kernel_pages() - pin kernel pages in memory + * @kiov: An array of struct kvec structures + * @nr_segs: number of segments to pin + * @write: pinning for read/write, currently ignored + * @pages: array that receives pointers to the pages pinned. + * Should be at least nr_segs long. + * + * Returns number of pages pinned. This may be fewer than the number + * requested. If nr_pages is 0 or negative, returns 0. If no pages + * were pinned, returns -errno. Each page returned must be released + * with a put_page() call when it is finished with. + */ +int get_kernel_pages(const struct kvec *kiov, int nr_segs, int write, + struct page **pages) +{ + int seg; + + for (seg = 0; seg < nr_segs; seg++) { + if (WARN_ON(kiov[seg].iov_len != PAGE_SIZE)) + return seg; + + /* virt_to_page sanity checks the PFN */ + pages[seg] = virt_to_page(kiov[seg].iov_base); + page_cache_get(pages[seg]); + } + + return seg; +} +EXPORT_SYMBOL_GPL(get_kernel_pages); + +/* + * get_kernel_page() - pin a kernel page in memory + * @start: starting kernel address + * @write: pinning for read/write, currently ignored + * @pages: array that receives pointer to the page pinned. + * Must be at least nr_segs long. + * + * Returns 1 if page is pinned. If the page was not pinned, returns + * -errno. The page returned must be released with a put_page() call + * when it is finished with. + */ +int get_kernel_page(unsigned long start, int write, struct page **pages) +{ + const struct kvec kiov = { + .iov_base = (void *)start, + .iov_len = PAGE_SIZE + }; + + return get_kernel_pages(&kiov, 1, write, pages); +} +EXPORT_SYMBOL_GPL(get_kernel_page); + static void pagevec_lru_move_fn(struct pagevec *pvec, void (*move_fn)(struct page *page, struct lruvec *lruvec, void *arg), void *arg) -- GitLab From 62c230bc1790923a1b35da03596a68a6c9b5b100 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:55 -0700 Subject: [PATCH 4944/5711] mm: add support for a filesystem to activate swap files and use direct_IO for writing swap pages Currently swapfiles are managed entirely by the core VM by using ->bmap to allocate space and write to the blocks directly. This effectively ensures that the underlying blocks are allocated and avoids the need for the swap subsystem to locate what physical blocks store offsets within a file. If the swap subsystem is to use the filesystem information to locate the blocks, it is critical that information such as block groups, block bitmaps and the block descriptor table that map the swap file were resident in memory. This patch adds address_space_operations that the VM can call when activating or deactivating swap backed by a file. int swap_activate(struct file *); int swap_deactivate(struct file *); The ->swap_activate() method is used to communicate to the file that the VM relies on it, and the address_space should take adequate measures such as reserving space in the underlying device, reserving memory for mempools and pinning information such as the block descriptor table in memory. The ->swap_deactivate() method is called on sys_swapoff() if ->swap_activate() returned success. After a successful swapfile ->swap_activate, the swapfile is marked SWP_FILE and swapper_space.a_ops will proxy to sis->swap_file->f_mappings->a_ops using ->direct_io to write swapcache pages and ->readpage to read. It is perfectly possible that direct_IO be used to read the swap pages but it is an unnecessary complication. Similarly, it is possible that ->writepage be used instead of direct_io to write the pages but filesystem developers have stated that calling writepage from the VM is undesirable for a variety of reasons and using direct_IO opens up the possibility of writing back batches of swap pages in the future. [a.p.zijlstra@chello.nl: Original patch] Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/Locking | 13 ++++++++ Documentation/filesystems/vfs.txt | 12 +++++++ include/linux/fs.h | 4 +++ include/linux/swap.h | 2 ++ mm/page_io.c | 52 +++++++++++++++++++++++++++++++ mm/swap_state.c | 2 +- mm/swapfile.c | 23 ++++++++++++-- 7 files changed, 105 insertions(+), 3 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index e0cce2a5f820..2db1900d7538 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -206,6 +206,8 @@ prototypes: int (*launder_page)(struct page *); int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long); int (*error_remove_page)(struct address_space *, struct page *); + int (*swap_activate)(struct file *); + int (*swap_deactivate)(struct file *); locking rules: All except set_page_dirty and freepage may block @@ -229,6 +231,8 @@ migratepage: yes (both) launder_page: yes is_partially_uptodate: yes error_remove_page: yes +swap_activate: no +swap_deactivate: no ->write_begin(), ->write_end(), ->sync_page() and ->readpage() may be called from the request handler (/dev/loop). @@ -330,6 +334,15 @@ cleaned, or an error value if not. Note that in order to prevent the page getting mapped back in and redirtied, it needs to be kept locked across the entire operation. + ->swap_activate will be called with a non-zero argument on +files backing (non block device backed) swapfiles. A return value +of zero indicates success, in which case this file can be used for +backing swapspace. The swapspace operations will be proxied to the +address space operations. + + ->swap_deactivate() will be called in the sys_swapoff() +path after ->swap_activate() returned success. + ----------------------- file_lock_operations ------------------------------ prototypes: void (*fl_copy_lock)(struct file_lock *, struct file_lock *); diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index aa754e01464e..065aa2dc0835 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -592,6 +592,8 @@ struct address_space_operations { int (*migratepage) (struct page *, struct page *); int (*launder_page) (struct page *); int (*error_remove_page) (struct mapping *mapping, struct page *page); + int (*swap_activate)(struct file *); + int (*swap_deactivate)(struct file *); }; writepage: called by the VM to write a dirty page to backing store. @@ -760,6 +762,16 @@ struct address_space_operations { Setting this implies you deal with pages going away under you, unless you have them locked or reference counts increased. + swap_activate: Called when swapon is used on a file to allocate + space if necessary and pin the block lookup information in + memory. A return value of zero indicates success, + in which case this file can be used to back swapspace. The + swapspace operations will be proxied to this address space's + ->swap_{out,in} methods. + + swap_deactivate: Called during swapoff on files where swap_activate + was successful. + The File Object =============== diff --git a/include/linux/fs.h b/include/linux/fs.h index 9d77309da153..38356ab827c9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -638,6 +638,10 @@ struct address_space_operations { int (*is_partially_uptodate) (struct page *, read_descriptor_t *, unsigned long); int (*error_remove_page)(struct address_space *, struct page *); + + /* swapfile support */ + int (*swap_activate)(struct file *file); + int (*swap_deactivate)(struct file *file); }; extern const struct address_space_operations empty_aops; diff --git a/include/linux/swap.h b/include/linux/swap.h index e62425ded2ed..ab230b1ebf61 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -151,6 +151,7 @@ enum { SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ SWP_BLKDEV = (1 << 6), /* its a block device */ + SWP_FILE = (1 << 7), /* set after swap_activate success */ /* add others here before... */ SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ }; @@ -320,6 +321,7 @@ static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) /* linux/mm/page_io.c */ extern int swap_readpage(struct page *); extern int swap_writepage(struct page *page, struct writeback_control *wbc); +extern int swap_set_page_dirty(struct page *page); extern void end_swap_bio_read(struct bio *bio, int err); /* linux/mm/swap_state.c */ diff --git a/mm/page_io.c b/mm/page_io.c index 34f02923744c..307a3e795290 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) { struct bio *bio; int ret = 0, rw = WRITE; + struct swap_info_struct *sis = page_swap_info(page); if (try_to_free_swap(page)) { unlock_page(page); @@ -105,6 +107,32 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) end_page_writeback(page); goto out; } + + if (sis->flags & SWP_FILE) { + struct kiocb kiocb; + struct file *swap_file = sis->swap_file; + struct address_space *mapping = swap_file->f_mapping; + struct iovec iov = { + .iov_base = page_address(page), + .iov_len = PAGE_SIZE, + }; + + init_sync_kiocb(&kiocb, swap_file); + kiocb.ki_pos = page_file_offset(page); + kiocb.ki_left = PAGE_SIZE; + kiocb.ki_nbytes = PAGE_SIZE; + + unlock_page(page); + ret = mapping->a_ops->direct_IO(KERNEL_WRITE, + &kiocb, &iov, + kiocb.ki_pos, 1); + if (ret == PAGE_SIZE) { + count_vm_event(PSWPOUT); + ret = 0; + } + return ret; + } + bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write); if (bio == NULL) { set_page_dirty(page); @@ -126,6 +154,7 @@ int swap_readpage(struct page *page) { struct bio *bio; int ret = 0; + struct swap_info_struct *sis = page_swap_info(page); VM_BUG_ON(!PageLocked(page)); VM_BUG_ON(PageUptodate(page)); @@ -134,6 +163,17 @@ int swap_readpage(struct page *page) unlock_page(page); goto out; } + + if (sis->flags & SWP_FILE) { + struct file *swap_file = sis->swap_file; + struct address_space *mapping = swap_file->f_mapping; + + ret = mapping->a_ops->readpage(swap_file, page); + if (!ret) + count_vm_event(PSWPIN); + return ret; + } + bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); if (bio == NULL) { unlock_page(page); @@ -145,3 +185,15 @@ int swap_readpage(struct page *page) out: return ret; } + +int swap_set_page_dirty(struct page *page) +{ + struct swap_info_struct *sis = page_swap_info(page); + + if (sis->flags & SWP_FILE) { + struct address_space *mapping = sis->swap_file->f_mapping; + return mapping->a_ops->set_page_dirty(page); + } else { + return __set_page_dirty_no_writeback(page); + } +} diff --git a/mm/swap_state.c b/mm/swap_state.c index c85b5590cccd..0cb36fb1f61c 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -27,7 +27,7 @@ */ static const struct address_space_operations swap_aops = { .writepage = swap_writepage, - .set_page_dirty = __set_page_dirty_no_writeback, + .set_page_dirty = swap_set_page_dirty, .migratepage = migrate_page, }; diff --git a/mm/swapfile.c b/mm/swapfile.c index f89af5ba2eb2..6ffc87602f4a 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1329,6 +1329,14 @@ static void destroy_swap_extents(struct swap_info_struct *sis) list_del(&se->list); kfree(se); } + + if (sis->flags & SWP_FILE) { + struct file *swap_file = sis->swap_file; + struct address_space *mapping = swap_file->f_mapping; + + sis->flags &= ~SWP_FILE; + mapping->a_ops->swap_deactivate(swap_file); + } } /* @@ -1410,7 +1418,9 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, */ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) { - struct inode *inode; + struct file *swap_file = sis->swap_file; + struct address_space *mapping = swap_file->f_mapping; + struct inode *inode = mapping->host; unsigned blocks_per_page; unsigned long page_no; unsigned blkbits; @@ -1421,13 +1431,22 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) int nr_extents = 0; int ret; - inode = sis->swap_file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { ret = add_swap_extent(sis, 0, sis->max, 0); *span = sis->pages; goto out; } + if (mapping->a_ops->swap_activate) { + ret = mapping->a_ops->swap_activate(swap_file); + if (!ret) { + sis->flags |= SWP_FILE; + ret = add_swap_extent(sis, 0, sis->max, 0); + *span = sis->pages; + } + goto out; + } + blkbits = inode->i_blkbits; blocks_per_page = PAGE_SIZE >> blkbits; -- GitLab From a509bc1a9e487d952d9404318f7f990166ab57a7 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:44:57 -0700 Subject: [PATCH 4945/5711] mm: swap: implement generic handler for swap_activate The version of swap_activate introduced is sufficient for swap-over-NFS but would not provide enough information to implement a generic handler. This patch shuffles things slightly to ensure the same information is available for aops->swap_activate() as is available to the core. No functionality change. Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 6 ++- include/linux/swap.h | 5 +++ mm/page_io.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ mm/swapfile.c | 91 +++---------------------------------------- 4 files changed, 106 insertions(+), 88 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 38356ab827c9..c8667f8b5358 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -429,6 +429,7 @@ struct kstatfs; struct vm_area_struct; struct vfsmount; struct cred; +struct swap_info_struct; extern void __init inode_init(void); extern void __init inode_init_early(void); @@ -640,8 +641,9 @@ struct address_space_operations { int (*error_remove_page)(struct address_space *, struct page *); /* swapfile support */ - int (*swap_activate)(struct file *file); - int (*swap_deactivate)(struct file *file); + int (*swap_activate)(struct swap_info_struct *sis, struct file *file, + sector_t *span); + void (*swap_deactivate)(struct file *file); }; extern const struct address_space_operations empty_aops; diff --git a/include/linux/swap.h b/include/linux/swap.h index ab230b1ebf61..388e70601413 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -324,6 +324,11 @@ extern int swap_writepage(struct page *page, struct writeback_control *wbc); extern int swap_set_page_dirty(struct page *page); extern void end_swap_bio_read(struct bio *bio, int err); +int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, + unsigned long nr_pages, sector_t start_block); +int generic_swapfile_activate(struct swap_info_struct *, struct file *, + sector_t *); + /* linux/mm/swap_state.c */ extern struct address_space swapper_space; #define total_swapcache_pages swapper_space.nrpages diff --git a/mm/page_io.c b/mm/page_io.c index 307a3e795290..4a379629e31f 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -87,6 +87,98 @@ void end_swap_bio_read(struct bio *bio, int err) bio_put(bio); } +int generic_swapfile_activate(struct swap_info_struct *sis, + struct file *swap_file, + sector_t *span) +{ + struct address_space *mapping = swap_file->f_mapping; + struct inode *inode = mapping->host; + unsigned blocks_per_page; + unsigned long page_no; + unsigned blkbits; + sector_t probe_block; + sector_t last_block; + sector_t lowest_block = -1; + sector_t highest_block = 0; + int nr_extents = 0; + int ret; + + blkbits = inode->i_blkbits; + blocks_per_page = PAGE_SIZE >> blkbits; + + /* + * Map all the blocks into the extent list. This code doesn't try + * to be very smart. + */ + probe_block = 0; + page_no = 0; + last_block = i_size_read(inode) >> blkbits; + while ((probe_block + blocks_per_page) <= last_block && + page_no < sis->max) { + unsigned block_in_page; + sector_t first_block; + + first_block = bmap(inode, probe_block); + if (first_block == 0) + goto bad_bmap; + + /* + * It must be PAGE_SIZE aligned on-disk + */ + if (first_block & (blocks_per_page - 1)) { + probe_block++; + goto reprobe; + } + + for (block_in_page = 1; block_in_page < blocks_per_page; + block_in_page++) { + sector_t block; + + block = bmap(inode, probe_block + block_in_page); + if (block == 0) + goto bad_bmap; + if (block != first_block + block_in_page) { + /* Discontiguity */ + probe_block++; + goto reprobe; + } + } + + first_block >>= (PAGE_SHIFT - blkbits); + if (page_no) { /* exclude the header page */ + if (first_block < lowest_block) + lowest_block = first_block; + if (first_block > highest_block) + highest_block = first_block; + } + + /* + * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks + */ + ret = add_swap_extent(sis, page_no, 1, first_block); + if (ret < 0) + goto out; + nr_extents += ret; + page_no++; + probe_block += blocks_per_page; +reprobe: + continue; + } + ret = nr_extents; + *span = 1 + highest_block - lowest_block; + if (page_no == 0) + page_no = 1; /* force Empty message */ + sis->max = page_no; + sis->pages = page_no - 1; + sis->highest_bit = page_no - 1; +out: + return ret; +bad_bmap: + printk(KERN_ERR "swapon: swapfile has holes\n"); + ret = -EINVAL; + goto out; +} + /* * We may have stale swap cache pages in memory: notice * them here and get rid of the unnecessary final write. diff --git a/mm/swapfile.c b/mm/swapfile.c index 6ffc87602f4a..7307fc928d7b 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1345,7 +1345,7 @@ static void destroy_swap_extents(struct swap_info_struct *sis) * * This function rather assumes that it is called in ascending page order. */ -static int +int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, unsigned long nr_pages, sector_t start_block) { @@ -1421,106 +1421,25 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) struct file *swap_file = sis->swap_file; struct address_space *mapping = swap_file->f_mapping; struct inode *inode = mapping->host; - unsigned blocks_per_page; - unsigned long page_no; - unsigned blkbits; - sector_t probe_block; - sector_t last_block; - sector_t lowest_block = -1; - sector_t highest_block = 0; - int nr_extents = 0; int ret; if (S_ISBLK(inode->i_mode)) { ret = add_swap_extent(sis, 0, sis->max, 0); *span = sis->pages; - goto out; + return ret; } if (mapping->a_ops->swap_activate) { - ret = mapping->a_ops->swap_activate(swap_file); + ret = mapping->a_ops->swap_activate(sis, swap_file, span); if (!ret) { sis->flags |= SWP_FILE; ret = add_swap_extent(sis, 0, sis->max, 0); *span = sis->pages; } - goto out; + return ret; } - blkbits = inode->i_blkbits; - blocks_per_page = PAGE_SIZE >> blkbits; - - /* - * Map all the blocks into the extent list. This code doesn't try - * to be very smart. - */ - probe_block = 0; - page_no = 0; - last_block = i_size_read(inode) >> blkbits; - while ((probe_block + blocks_per_page) <= last_block && - page_no < sis->max) { - unsigned block_in_page; - sector_t first_block; - - first_block = bmap(inode, probe_block); - if (first_block == 0) - goto bad_bmap; - - /* - * It must be PAGE_SIZE aligned on-disk - */ - if (first_block & (blocks_per_page - 1)) { - probe_block++; - goto reprobe; - } - - for (block_in_page = 1; block_in_page < blocks_per_page; - block_in_page++) { - sector_t block; - - block = bmap(inode, probe_block + block_in_page); - if (block == 0) - goto bad_bmap; - if (block != first_block + block_in_page) { - /* Discontiguity */ - probe_block++; - goto reprobe; - } - } - - first_block >>= (PAGE_SHIFT - blkbits); - if (page_no) { /* exclude the header page */ - if (first_block < lowest_block) - lowest_block = first_block; - if (first_block > highest_block) - highest_block = first_block; - } - - /* - * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks - */ - ret = add_swap_extent(sis, page_no, 1, first_block); - if (ret < 0) - goto out; - nr_extents += ret; - page_no++; - probe_block += blocks_per_page; -reprobe: - continue; - } - ret = nr_extents; - *span = 1 + highest_block - lowest_block; - if (page_no == 0) - page_no = 1; /* force Empty message */ - sis->max = page_no; - sis->pages = page_no - 1; - sis->highest_bit = page_no - 1; -out: - return ret; -bad_bmap: - printk(KERN_ERR "swapon: swapfile has holes\n"); - ret = -EINVAL; - goto out; + return generic_swapfile_activate(sis, swap_file, span); } static void enable_swap_info(struct swap_info_struct *p, int prio, -- GitLab From 5a178119b0fbe37f7dfb602b37df9cc4b1dc9d71 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:02 -0700 Subject: [PATCH 4946/5711] mm: add support for direct_IO to highmem pages The patch "mm: add support for a filesystem to activate swap files and use direct_IO for writing swap pages" added support for using direct_IO to write swap pages but it is insufficient for highmem pages. To support highmem pages, this patch kmaps() the page before calling the direct_IO() handler. As direct_IO deals with virtual addresses an additional helper is necessary for get_kernel_pages() to lookup the struct page for a kmap virtual address. Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/highmem.h | 7 +++++++ mm/highmem.c | 12 ++++++++++++ mm/page_io.c | 3 ++- mm/swap.c | 3 +-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 774fa47b3b5b..ef788b5b4a35 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -39,10 +39,17 @@ extern unsigned long totalhigh_pages; void kmap_flush_unused(void); +struct page *kmap_to_page(void *addr); + #else /* CONFIG_HIGHMEM */ static inline unsigned int nr_free_highpages(void) { return 0; } +static inline struct page *kmap_to_page(void *addr) +{ + return virt_to_page(addr); +} + #define totalhigh_pages 0UL #ifndef ARCH_HAS_KMAP diff --git a/mm/highmem.c b/mm/highmem.c index 57d82c6250c3..d517cd16a6eb 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -94,6 +94,18 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); do { spin_unlock(&kmap_lock); (void)(flags); } while (0) #endif +struct page *kmap_to_page(void *vaddr) +{ + unsigned long addr = (unsigned long)vaddr; + + if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) { + int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT; + return pte_page(pkmap_page_table[i]); + } + + return virt_to_page(addr); +} + static void flush_all_zero_pkmaps(void) { int i; diff --git a/mm/page_io.c b/mm/page_io.c index 4a379629e31f..78eee32ee486 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -205,7 +205,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) struct file *swap_file = sis->swap_file; struct address_space *mapping = swap_file->f_mapping; struct iovec iov = { - .iov_base = page_address(page), + .iov_base = kmap(page), .iov_len = PAGE_SIZE, }; @@ -218,6 +218,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) ret = mapping->a_ops->direct_IO(KERNEL_WRITE, &kiocb, &iov, kiocb.ki_pos, 1); + kunmap(page); if (ret == PAGE_SIZE) { count_vm_event(PSWPOUT); ret = 0; diff --git a/mm/swap.c b/mm/swap.c index 7d7f80c8044a..77825883298f 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -258,8 +258,7 @@ int get_kernel_pages(const struct kvec *kiov, int nr_segs, int write, if (WARN_ON(kiov[seg].iov_len != PAGE_SIZE)) return seg; - /* virt_to_page sanity checks the PFN */ - pages[seg] = virt_to_page(kiov[seg].iov_base); + pages[seg] = kmap_to_page(kiov[seg].iov_base); page_cache_get(pages[seg]); } -- GitLab From d56b4ddf7781ef8dd050542781cc7f55673af002 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:06 -0700 Subject: [PATCH 4947/5711] nfs: teach the NFS client how to treat PG_swapcache pages Replace all relevant occurences of page->index and page->mapping in the NFS client with the new page_file_index() and page_file_mapping() functions. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfs/file.c | 6 +++--- fs/nfs/internal.h | 7 ++++--- fs/nfs/pagelist.c | 2 +- fs/nfs/read.c | 6 +++--- fs/nfs/write.c | 36 ++++++++++++++++++------------------ 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 70d124a61b98..acd4e4cd2906 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -430,7 +430,7 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) if (offset != 0) return; /* Cancel any unstarted writes on this page */ - nfs_wb_page_cancel(page->mapping->host, page); + nfs_wb_page_cancel(page_file_mapping(page)->host, page); nfs_fscache_invalidate_page(page, page->mapping->host); } @@ -472,7 +472,7 @@ static int nfs_release_page(struct page *page, gfp_t gfp) */ static int nfs_launder_page(struct page *page) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_inode *nfsi = NFS_I(inode); dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", @@ -521,7 +521,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) nfs_fscache_wait_on_page_write(NFS_I(dentry->d_inode), page); lock_page(page); - mapping = page->mapping; + mapping = page_file_mapping(page); if (mapping != dentry->d_inode->i_mapping) goto out_unlock; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index cfafd13b6fe9..4be14b3e0a18 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -546,13 +546,14 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) static inline unsigned int nfs_page_length(struct page *page) { - loff_t i_size = i_size_read(page->mapping->host); + loff_t i_size = i_size_read(page_file_mapping(page)->host); if (i_size > 0) { + pgoff_t page_index = page_file_index(page); pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; - if (page->index < end_index) + if (page_index < end_index) return PAGE_CACHE_SIZE; - if (page->index == end_index) + if (page_index == end_index) return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1; } return 0; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index aed913c833f4..9ef8b3cf7fc7 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -117,7 +117,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, * long write-back delay. This will be adjusted in * update_nfs_request below if the region is not locked. */ req->wb_page = page; - req->wb_index = page->index; + req->wb_index = page_file_index(page); page_cache_get(page); req->wb_offset = offset; req->wb_pgbase = offset; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6267b873bbcb..7cb020782687 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -522,11 +522,11 @@ static const struct rpc_call_ops nfs_read_common_ops = { int nfs_readpage(struct file *file, struct page *page) { struct nfs_open_context *ctx; - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; int error; dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", - page, PAGE_CACHE_SIZE, page->index); + page, PAGE_CACHE_SIZE, page_file_index(page)); nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); nfs_add_stats(inode, NFSIOS_READPAGES, 1); @@ -580,7 +580,7 @@ static int readpage_async_filler(void *data, struct page *page) { struct nfs_readdesc *desc = (struct nfs_readdesc *)data; - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_page *new; unsigned int len; int error; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f312860c15d0..d0feca32b4fe 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -153,7 +153,7 @@ static struct nfs_page *nfs_page_find_request_locked(struct page *page) static struct nfs_page *nfs_page_find_request(struct page *page) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_page *req = NULL; spin_lock(&inode->i_lock); @@ -165,16 +165,16 @@ static struct nfs_page *nfs_page_find_request(struct page *page) /* Adjust the file length if we're writing beyond the end */ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; loff_t end, i_size; pgoff_t end_index; spin_lock(&inode->i_lock); i_size = i_size_read(inode); end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; - if (i_size > 0 && page->index < end_index) + if (i_size > 0 && page_file_index(page) < end_index) goto out; - end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); + end = page_file_offset(page) + ((loff_t)offset+count); if (i_size >= end) goto out; i_size_write(inode, end); @@ -187,7 +187,7 @@ out: static void nfs_set_pageerror(struct page *page) { SetPageError(page); - nfs_zap_mapping(page->mapping->host, page->mapping); + nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); } /* We can set the PG_uptodate flag if we see that a write request @@ -228,7 +228,7 @@ static int nfs_set_page_writeback(struct page *page) int ret = test_set_page_writeback(page); if (!ret) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_server *nfss = NFS_SERVER(inode); if (atomic_long_inc_return(&nfss->writeback) > @@ -242,7 +242,7 @@ static int nfs_set_page_writeback(struct page *page) static void nfs_end_page_writeback(struct page *page) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_server *nfss = NFS_SERVER(inode); end_page_writeback(page); @@ -252,7 +252,7 @@ static void nfs_end_page_writeback(struct page *page) static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_page *req; int ret; @@ -313,13 +313,13 @@ out: static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; int ret; nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); - nfs_pageio_cond_complete(pgio, page->index); + nfs_pageio_cond_complete(pgio, page_file_index(page)); ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); if (ret == -EAGAIN) { redirty_page_for_writepage(wbc, page); @@ -336,7 +336,7 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc struct nfs_pageio_descriptor pgio; int err; - NFS_PROTO(page->mapping->host)->write_pageio_init(&pgio, + NFS_PROTO(page_file_mapping(page)->host)->write_pageio_init(&pgio, page->mapping->host, wb_priority(wbc), &nfs_async_write_completion_ops); @@ -471,7 +471,7 @@ nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, spin_unlock(cinfo->lock); if (!cinfo->dreq) { inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - inc_bdi_stat(req->wb_page->mapping->backing_dev_info, + inc_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, BDI_RECLAIMABLE); __mark_inode_dirty(req->wb_context->dentry->d_inode, I_DIRTY_DATASYNC); @@ -538,7 +538,7 @@ static void nfs_clear_page_commit(struct page *page) { dec_zone_page_state(page, NR_UNSTABLE_NFS); - dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); + dec_bdi_stat(page_file_mapping(page)->backing_dev_info, BDI_RECLAIMABLE); } static void @@ -789,7 +789,7 @@ out_err: static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, struct page *page, unsigned int offset, unsigned int bytes) { - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; struct nfs_page *req; req = nfs_try_to_update_request(inode, page, offset, bytes); @@ -842,7 +842,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page) nfs_release_request(req); if (!do_flush) return 0; - status = nfs_wb_page(page->mapping->host, page); + status = nfs_wb_page(page_file_mapping(page)->host, page); } while (status == 0); return status; } @@ -872,7 +872,7 @@ int nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsigned int count) { struct nfs_open_context *ctx = nfs_file_open_context(file); - struct inode *inode = page->mapping->host; + struct inode *inode = page_file_mapping(page)->host; int status = 0; nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); @@ -880,7 +880,7 @@ int nfs_updatepage(struct file *file, struct page *page, dprintk("NFS: nfs_updatepage(%s/%s %d@%lld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, count, - (long long)(page_offset(page) + offset)); + (long long)(page_file_offset(page) + offset)); /* If we're not using byte range locks, and we know the page * is up to date, it may be more efficient to extend the write @@ -1469,7 +1469,7 @@ void nfs_retry_commit(struct list_head *page_list, nfs_mark_request_commit(req, lseg, cinfo); if (!cinfo->dreq) { dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - dec_bdi_stat(req->wb_page->mapping->backing_dev_info, + dec_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, BDI_RECLAIMABLE); } nfs_unlock_and_release_request(req); -- GitLab From 29418aa4bd487c82016733ef5c6a06d656ed3c7d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:10 -0700 Subject: [PATCH 4948/5711] nfs: disable data cache revalidation for swapfiles The VM does not like PG_private set on PG_swapcache pages. As suggested by Trond in http://lkml.org/lkml/2006/8/25/348, this patch disables NFS data cache revalidation on swap files. as it does not make sense to have other clients change the file while it is being used as swap. This avoids setting PG_private on swap pages, since there ought to be no further races with invalidate_inode_pages2() to deal with. Since we cannot set PG_private we cannot use page->private which is already used by PG_swapcache pages to store the nfs_page. Thus augment the new nfs_page_find_request logic. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfs/inode.c | 4 ++++ fs/nfs/write.c | 49 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 35f7e4bc680e..1d57fe9f49a9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -882,6 +882,10 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) struct nfs_inode *nfsi = NFS_I(inode); int ret = 0; + /* swapfiles are not supposed to be shared. */ + if (IS_SWAPFILE(inode)) + goto out; + if (nfs_mapping_need_revalidate_inode(inode)) { ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); if (ret < 0) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d0feca32b4fe..974e9c2d31fd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -139,15 +139,28 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); } -static struct nfs_page *nfs_page_find_request_locked(struct page *page) +static struct nfs_page * +nfs_page_find_request_locked(struct nfs_inode *nfsi, struct page *page) { struct nfs_page *req = NULL; - if (PagePrivate(page)) { + if (PagePrivate(page)) req = (struct nfs_page *)page_private(page); - if (req != NULL) - kref_get(&req->wb_kref); + else if (unlikely(PageSwapCache(page))) { + struct nfs_page *freq, *t; + + /* Linearly search the commit list for the correct req */ + list_for_each_entry_safe(freq, t, &nfsi->commit_info.list, wb_list) { + if (freq->wb_page == page) { + req = freq; + break; + } + } } + + if (req) + kref_get(&req->wb_kref); + return req; } @@ -157,7 +170,7 @@ static struct nfs_page *nfs_page_find_request(struct page *page) struct nfs_page *req = NULL; spin_lock(&inode->i_lock); - req = nfs_page_find_request_locked(page); + req = nfs_page_find_request_locked(NFS_I(inode), page); spin_unlock(&inode->i_lock); return req; } @@ -258,7 +271,7 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblo spin_lock(&inode->i_lock); for (;;) { - req = nfs_page_find_request_locked(page); + req = nfs_page_find_request_locked(NFS_I(inode), page); if (req == NULL) break; if (nfs_lock_request(req)) @@ -413,9 +426,15 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) spin_lock(&inode->i_lock); if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) inode->i_version++; - set_bit(PG_MAPPED, &req->wb_flags); - SetPagePrivate(req->wb_page); - set_page_private(req->wb_page, (unsigned long)req); + /* + * Swap-space should not get truncated. Hence no need to plug the race + * with invalidate/truncate. + */ + if (likely(!PageSwapCache(req->wb_page))) { + set_bit(PG_MAPPED, &req->wb_flags); + SetPagePrivate(req->wb_page); + set_page_private(req->wb_page, (unsigned long)req); + } nfsi->npages++; kref_get(&req->wb_kref); spin_unlock(&inode->i_lock); @@ -432,9 +451,11 @@ static void nfs_inode_remove_request(struct nfs_page *req) BUG_ON (!NFS_WBACK_BUSY(req)); spin_lock(&inode->i_lock); - set_page_private(req->wb_page, 0); - ClearPagePrivate(req->wb_page); - clear_bit(PG_MAPPED, &req->wb_flags); + if (likely(!PageSwapCache(req->wb_page))) { + set_page_private(req->wb_page, 0); + ClearPagePrivate(req->wb_page); + clear_bit(PG_MAPPED, &req->wb_flags); + } nfsi->npages--; spin_unlock(&inode->i_lock); nfs_release_request(req); @@ -730,7 +751,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, spin_lock(&inode->i_lock); for (;;) { - req = nfs_page_find_request_locked(page); + req = nfs_page_find_request_locked(NFS_I(inode), page); if (req == NULL) goto out_unlock; @@ -1744,7 +1765,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) */ int nfs_wb_page(struct inode *inode, struct page *page) { - loff_t range_start = page_offset(page); + loff_t range_start = page_file_offset(page); loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, -- GitLab From a564b8f0398636ba30b07c0eaebdef7ff7837249 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:12 -0700 Subject: [PATCH 4949/5711] nfs: enable swap on NFS Implement the new swapfile a_ops for NFS and hook up ->direct_IO. This will set the NFS socket to SOCK_MEMALLOC and run socket reconnect under PF_MEMALLOC as well as reset SOCK_MEMALLOC before engaging the protocol ->connect() method. PF_MEMALLOC should allow the allocation of struct socket and related objects and the early (re)setting of SOCK_MEMALLOC should allow us to receive the packets required for the TCP connection buildup. [jlayton@redhat.com: Restore PF_MEMALLOC task flags in all cases] [dfeng@redhat.com: Fix handling of multiple swap files] [a.p.zijlstra@chello.nl: Original patch] Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfs/Kconfig | 8 ++++ fs/nfs/direct.c | 82 ++++++++++++++++++++++++------------- fs/nfs/file.c | 22 +++++++++- include/linux/nfs_fs.h | 4 +- include/linux/sunrpc/xprt.h | 3 ++ net/sunrpc/Kconfig | 5 +++ net/sunrpc/clnt.c | 9 ++++ net/sunrpc/sched.c | 7 +++- net/sunrpc/xprtsock.c | 43 +++++++++++++++++++ 9 files changed, 149 insertions(+), 34 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 404c6a8ac394..6fd5f2cdcd1e 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -86,6 +86,14 @@ config NFS_V4 If unsure, say Y. +config NFS_SWAP + bool "Provide swap over NFS support" + default n + depends on NFS_FS + select SUNRPC_SWAP + help + This option enables swapon to work on files located on NFS mounts. + config NFS_V4_1 bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" depends on NFS_V4 && EXPERIMENTAL diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 42dce909ec70..bf9c8d0ec16a 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -115,17 +115,28 @@ static inline int put_dreq(struct nfs_direct_req *dreq) * @nr_segs: size of iovec array * * The presence of this routine in the address space ops vector means - * the NFS client supports direct I/O. However, we shunt off direct - * read and write requests before the VFS gets them, so this method - * should never be called. + * the NFS client supports direct I/O. However, for most direct IO, we + * shunt off direct read and write requests before the VFS gets them, + * so this method is only ever called for swap. */ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) { +#ifndef CONFIG_NFS_SWAP dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", iocb->ki_filp->f_path.dentry->d_name.name, (long long) pos, nr_segs); return -EINVAL; +#else + VM_BUG_ON(iocb->ki_left != PAGE_SIZE); + VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE); + + if (rw == READ || rw == KERNEL_READ) + return nfs_file_direct_read(iocb, iov, nr_segs, pos, + rw == READ ? true : false); + return nfs_file_direct_write(iocb, iov, nr_segs, pos, + rw == WRITE ? true : false); +#endif /* CONFIG_NFS_SWAP */ } static void nfs_direct_release_pages(struct page **pages, unsigned int npages) @@ -303,7 +314,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_read_completion_ops = { */ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *desc, const struct iovec *iov, - loff_t pos) + loff_t pos, bool uio) { struct nfs_direct_req *dreq = desc->pg_dreq; struct nfs_open_context *ctx = dreq->ctx; @@ -331,12 +342,20 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de GFP_KERNEL); if (!pagevec) break; - down_read(¤t->mm->mmap_sem); - result = get_user_pages(current, current->mm, user_addr, + if (uio) { + down_read(¤t->mm->mmap_sem); + result = get_user_pages(current, current->mm, user_addr, npages, 1, 0, pagevec, NULL); - up_read(¤t->mm->mmap_sem); - if (result < 0) - break; + up_read(¤t->mm->mmap_sem); + if (result < 0) + break; + } else { + WARN_ON(npages != 1); + result = get_kernel_page(user_addr, 1, pagevec); + if (WARN_ON(result != 1)) + break; + } + if ((unsigned)result < npages) { bytes = result * PAGE_SIZE; if (bytes <= pgbase) { @@ -386,7 +405,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, const struct iovec *iov, unsigned long nr_segs, - loff_t pos) + loff_t pos, bool uio) { struct nfs_pageio_descriptor desc; ssize_t result = -EINVAL; @@ -400,7 +419,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, for (seg = 0; seg < nr_segs; seg++) { const struct iovec *vec = &iov[seg]; - result = nfs_direct_read_schedule_segment(&desc, vec, pos); + result = nfs_direct_read_schedule_segment(&desc, vec, pos, uio); if (result < 0) break; requested_bytes += result; @@ -426,7 +445,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, } static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) + unsigned long nr_segs, loff_t pos, bool uio) { ssize_t result = -ENOMEM; struct inode *inode = iocb->ki_filp->f_mapping->host; @@ -444,7 +463,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); + result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); if (!result) result = nfs_direct_wait(dreq); NFS_I(inode)->read_io += result; @@ -610,7 +629,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode */ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *desc, const struct iovec *iov, - loff_t pos) + loff_t pos, bool uio) { struct nfs_direct_req *dreq = desc->pg_dreq; struct nfs_open_context *ctx = dreq->ctx; @@ -638,12 +657,19 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d if (!pagevec) break; - down_read(¤t->mm->mmap_sem); - result = get_user_pages(current, current->mm, user_addr, - npages, 0, 0, pagevec, NULL); - up_read(¤t->mm->mmap_sem); - if (result < 0) - break; + if (uio) { + down_read(¤t->mm->mmap_sem); + result = get_user_pages(current, current->mm, user_addr, + npages, 0, 0, pagevec, NULL); + up_read(¤t->mm->mmap_sem); + if (result < 0) + break; + } else { + WARN_ON(npages != 1); + result = get_kernel_page(user_addr, 0, pagevec); + if (WARN_ON(result != 1)) + break; + } if ((unsigned)result < npages) { bytes = result * PAGE_SIZE; @@ -774,7 +800,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = { static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, const struct iovec *iov, unsigned long nr_segs, - loff_t pos) + loff_t pos, bool uio) { struct nfs_pageio_descriptor desc; struct inode *inode = dreq->inode; @@ -790,7 +816,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, for (seg = 0; seg < nr_segs; seg++) { const struct iovec *vec = &iov[seg]; - result = nfs_direct_write_schedule_segment(&desc, vec, pos); + result = nfs_direct_write_schedule_segment(&desc, vec, pos, uio); if (result < 0) break; requested_bytes += result; @@ -818,7 +844,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos, - size_t count) + size_t count, bool uio) { ssize_t result = -ENOMEM; struct inode *inode = iocb->ki_filp->f_mapping->host; @@ -836,7 +862,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos); + result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); if (!result) result = nfs_direct_wait(dreq); out_release: @@ -867,7 +893,7 @@ out: * cache. */ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) + unsigned long nr_segs, loff_t pos, bool uio) { ssize_t retval = -EINVAL; struct file *file = iocb->ki_filp; @@ -892,7 +918,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, task_io_account_read(count); - retval = nfs_direct_read(iocb, iov, nr_segs, pos); + retval = nfs_direct_read(iocb, iov, nr_segs, pos, uio); if (retval > 0) iocb->ki_pos = pos + retval; @@ -923,7 +949,7 @@ out: * is no atomic O_APPEND write facility in the NFS protocol. */ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) + unsigned long nr_segs, loff_t pos, bool uio) { ssize_t retval = -EINVAL; struct file *file = iocb->ki_filp; @@ -955,7 +981,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, task_io_account_write(count); - retval = nfs_direct_write(iocb, iov, nr_segs, pos, count); + retval = nfs_direct_write(iocb, iov, nr_segs, pos, count, uio); if (retval > 0) { struct inode *inode = mapping->host; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index acd4e4cd2906..50fb83a88b1b 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -175,7 +175,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, ssize_t result; if (iocb->ki_filp->f_flags & O_DIRECT) - return nfs_file_direct_read(iocb, iov, nr_segs, pos); + return nfs_file_direct_read(iocb, iov, nr_segs, pos, true); dprintk("NFS: read(%s/%s, %lu@%lu)\n", dentry->d_parent->d_name.name, dentry->d_name.name, @@ -482,6 +482,20 @@ static int nfs_launder_page(struct page *page) return nfs_wb_page(inode, page); } +#ifdef CONFIG_NFS_SWAP +static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, + sector_t *span) +{ + *span = sis->pages; + return xs_swapper(NFS_CLIENT(file->f_mapping->host)->cl_xprt, 1); +} + +static void nfs_swap_deactivate(struct file *file) +{ + xs_swapper(NFS_CLIENT(file->f_mapping->host)->cl_xprt, 0); +} +#endif + const struct address_space_operations nfs_file_aops = { .readpage = nfs_readpage, .readpages = nfs_readpages, @@ -496,6 +510,10 @@ const struct address_space_operations nfs_file_aops = { .migratepage = nfs_migrate_page, .launder_page = nfs_launder_page, .error_remove_page = generic_error_remove_page, +#ifdef CONFIG_NFS_SWAP + .swap_activate = nfs_swap_activate, + .swap_deactivate = nfs_swap_deactivate, +#endif }; /* @@ -570,7 +588,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, size_t count = iov_length(iov, nr_segs); if (iocb->ki_filp->f_flags & O_DIRECT) - return nfs_file_direct_write(iocb, iov, nr_segs, pos); + return nfs_file_direct_write(iocb, iov, nr_segs, pos, true); dprintk("NFS: write(%s/%s, %lu@%Ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 4b6043c20f77..35994f975a7f 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -473,10 +473,10 @@ extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t, unsigned long); extern ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, - loff_t pos); + loff_t pos, bool uio); extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, - loff_t pos); + loff_t pos, bool uio); /* * linux/fs/nfs/dir.c diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 77d278defa70..cff40aa7db62 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -174,6 +174,8 @@ struct rpc_xprt { unsigned long state; /* transport state */ unsigned char shutdown : 1, /* being shut down */ resvport : 1; /* use a reserved port */ + unsigned int swapper; /* we're swapping over this + transport */ unsigned int bind_index; /* bind function index */ /* @@ -316,6 +318,7 @@ void xprt_release_rqst_cong(struct rpc_task *task); void xprt_disconnect_done(struct rpc_xprt *xprt); void xprt_force_disconnect(struct rpc_xprt *xprt); void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie); +int xs_swapper(struct rpc_xprt *xprt, int enable); /* * Reserved bit positions in xprt->state diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 9fe8857d8d59..03d03e37a7d5 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -21,6 +21,11 @@ config SUNRPC_XPRT_RDMA If unsure, say N. +config SUNRPC_SWAP + bool + depends on SUNRPC + select NETVM + config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism" depends on SUNRPC && CRYPTO diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index b05df36692ff..fa48c60aef23 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -717,6 +717,15 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) atomic_inc(&clnt->cl_count); if (clnt->cl_softrtry) task->tk_flags |= RPC_TASK_SOFT; + if (sk_memalloc_socks()) { + struct rpc_xprt *xprt; + + rcu_read_lock(); + xprt = rcu_dereference(clnt->cl_xprt); + if (xprt->swapper) + task->tk_flags |= RPC_TASK_SWAPPER; + rcu_read_unlock(); + } /* Add to the client's list of all tasks */ spin_lock(&clnt->cl_lock); list_add_tail(&task->tk_task, &clnt->cl_tasks); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 994cfea2bad6..83a4c43cee7f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -812,7 +812,10 @@ static void rpc_async_schedule(struct work_struct *work) void *rpc_malloc(struct rpc_task *task, size_t size) { struct rpc_buffer *buf; - gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT; + gfp_t gfp = GFP_NOWAIT; + + if (RPC_IS_SWAPPER(task)) + gfp |= __GFP_MEMALLOC; size += sizeof(struct rpc_buffer); if (size <= RPC_BUFFER_MAXSIZE) @@ -886,7 +889,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta static struct rpc_task * rpc_alloc_task(void) { - return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS); + return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOIO); } /* diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 62d0dac8f780..bd59d01f035b 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1927,6 +1927,45 @@ out: xprt_wake_pending_tasks(xprt, status); } +#ifdef CONFIG_SUNRPC_SWAP +static void xs_set_memalloc(struct rpc_xprt *xprt) +{ + struct sock_xprt *transport = container_of(xprt, struct sock_xprt, + xprt); + + if (xprt->swapper) + sk_set_memalloc(transport->inet); +} + +/** + * xs_swapper - Tag this transport as being used for swap. + * @xprt: transport to tag + * @enable: enable/disable + * + */ +int xs_swapper(struct rpc_xprt *xprt, int enable) +{ + struct sock_xprt *transport = container_of(xprt, struct sock_xprt, + xprt); + int err = 0; + + if (enable) { + xprt->swapper++; + xs_set_memalloc(xprt); + } else if (xprt->swapper) { + xprt->swapper--; + sk_clear_memalloc(transport->inet); + } + + return err; +} +EXPORT_SYMBOL_GPL(xs_swapper); +#else +static void xs_set_memalloc(struct rpc_xprt *xprt) +{ +} +#endif + static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); @@ -1951,6 +1990,8 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) transport->sock = sock; transport->inet = sk; + xs_set_memalloc(xprt); + write_unlock_bh(&sk->sk_callback_lock); } xs_udp_do_set_buffer_size(xprt); @@ -2075,6 +2116,8 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) if (!xprt_bound(xprt)) goto out; + xs_set_memalloc(xprt); + /* Tell the socket layer to start connecting... */ xprt->stat.connect_count++; xprt->stat.connect_start = jiffies; -- GitLab From 192e501b0438bb0e1574179773537f84c4752e25 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:16 -0700 Subject: [PATCH 4950/5711] nfs: prevent page allocator recursions with swap over NFS. GFP_NOFS is _more_ permissive than GFP_NOIO in that it will initiate IO, just not of any filesystem data. The problem is that previously NOFS was correct because that avoids recursion into the NFS code. With swap-over-NFS, it is no longer correct as swap IO can lead to this recursion. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Cc: Xiaotian Feng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfs/pagelist.c | 2 +- fs/nfs/write.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 9ef8b3cf7fc7..7de1646c4e6b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -70,7 +70,7 @@ void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) static inline struct nfs_page * nfs_page_alloc(void) { - struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL); + struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_NOIO); if (p) INIT_LIST_HEAD(&p->wb_list); return p; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 974e9c2d31fd..211ba6566772 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -52,7 +52,7 @@ static mempool_t *nfs_commit_mempool; struct nfs_commit_data *nfs_commitdata_alloc(void) { - struct nfs_commit_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS); + struct nfs_commit_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOIO); if (p) { memset(p, 0, sizeof(*p)); @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(nfs_commit_free); struct nfs_write_header *nfs_writehdr_alloc(void) { - struct nfs_write_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); + struct nfs_write_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO); if (p) { struct nfs_pgio_header *hdr = &p->header; -- GitLab From 737449236240e30a7bbe99f4d5586b8ed1416763 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:45:20 -0700 Subject: [PATCH 4951/5711] swapfile: avoid dereferencing bd_disk during swap_entry_free for network storage Commit b3a27d ("swap: Add swap slot free callback to block_device_operations") dereferences p->bdev->bd_disk but this is a NULL dereference if using swap-over-NFS. This patch checks SWP_BLKDEV on the swap_info_struct before dereferencing. With reference to this callback, Christoph Hellwig stated "Please just remove the callback entirely. It has no user outside the staging tree and was added clearly against the rules for that staging tree". This would also be my preference but there was not an obvious way of keeping zram in staging/ happy. Signed-off-by: Xiaotian Feng Signed-off-by: Mel Gorman Acked-by: Rik van Riel Cc: Christoph Hellwig Cc: David S. Miller Cc: Eric B Munson Cc: Eric Paris Cc: James Morris Cc: Mel Gorman Cc: Mike Christie Cc: Neil Brown Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swapfile.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 7307fc928d7b..63958d60ecb0 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -549,7 +549,6 @@ static unsigned char swap_entry_free(struct swap_info_struct *p, /* free if no reference */ if (!usage) { - struct gendisk *disk = p->bdev->bd_disk; if (offset < p->lowest_bit) p->lowest_bit = offset; if (offset > p->highest_bit) @@ -560,9 +559,12 @@ static unsigned char swap_entry_free(struct swap_info_struct *p, nr_swap_pages++; p->inuse_pages--; frontswap_invalidate_page(p->type, offset); - if ((p->flags & SWP_BLKDEV) && - disk->fops->swap_slot_free_notify) - disk->fops->swap_slot_free_notify(p->bdev, offset); + if (p->flags & SWP_BLKDEV) { + struct gendisk *disk = p->bdev->bd_disk; + if (disk->fops->swap_slot_free_notify) + disk->fops->swap_slot_free_notify(p->bdev, + offset); + } } return usage; -- GitLab From 0030f535a5cf9b1841d2088c10a0b2f8f2987460 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:25 -0700 Subject: [PATCH 4952/5711] mm: memcg: fix compaction/migration failing due to memcg limits Compaction (and page migration in general) can currently be hindered through pages being owned by memory cgroups that are at their limits and unreclaimable. The reason is that the replacement page is being charged against the limit while the page being replaced is also still charged. But this seems unnecessary, given that only one of the two pages will still be in use after migration finishes. This patch changes the memcg migration sequence so that the replacement page is not charged. Whatever page is still in use after successful or failed migration gets to keep the charge of the page that was going to be replaced. The replacement page will still show up temporarily in the rss/cache statistics, this can be fixed in a later patch as it's less urgent. Reported-by: David Rientjes Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: Hugh Dickins Cc: David Rientjes Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 11 +++---- mm/memcontrol.c | 67 ++++++++++++++++++++------------------ mm/migrate.c | 11 ++----- 3 files changed, 43 insertions(+), 46 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 5a3ee6423634..8d9489fdab2e 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -98,9 +98,9 @@ int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg); -extern int -mem_cgroup_prepare_migration(struct page *page, - struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask); +extern void +mem_cgroup_prepare_migration(struct page *page, struct page *newpage, + struct mem_cgroup **memcgp); extern void mem_cgroup_end_migration(struct mem_cgroup *memcg, struct page *oldpage, struct page *newpage, bool migration_ok); @@ -276,11 +276,10 @@ static inline struct cgroup_subsys_state return NULL; } -static inline int +static inline void mem_cgroup_prepare_migration(struct page *page, struct page *newpage, - struct mem_cgroup **memcgp, gfp_t gfp_mask) + struct mem_cgroup **memcgp) { - return 0; } static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f692a2dbfcb..7eadcdad06f3 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2976,7 +2976,8 @@ direct_uncharge: * uncharge if !page_mapped(page) */ static struct mem_cgroup * -__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) +__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype, + bool end_migration) { struct mem_cgroup *memcg = NULL; unsigned int nr_pages = 1; @@ -3020,7 +3021,16 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) /* fallthrough */ case MEM_CGROUP_CHARGE_TYPE_DROP: /* See mem_cgroup_prepare_migration() */ - if (page_mapped(page) || PageCgroupMigration(pc)) + if (page_mapped(page)) + goto unlock_out; + /* + * Pages under migration may not be uncharged. But + * end_migration() /must/ be the one uncharging the + * unused post-migration page and so it has to call + * here with the migration bit still set. See the + * res_counter handling below. + */ + if (!end_migration && PageCgroupMigration(pc)) goto unlock_out; break; case MEM_CGROUP_CHARGE_TYPE_SWAPOUT: @@ -3054,7 +3064,12 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) mem_cgroup_swap_statistics(memcg, true); mem_cgroup_get(memcg); } - if (!mem_cgroup_is_root(memcg)) + /* + * Migration does not charge the res_counter for the + * replacement page, so leave it alone when phasing out the + * page that is unused after the migration. + */ + if (!end_migration && !mem_cgroup_is_root(memcg)) mem_cgroup_do_uncharge(memcg, nr_pages, ctype); return memcg; @@ -3070,14 +3085,14 @@ void mem_cgroup_uncharge_page(struct page *page) if (page_mapped(page)) return; VM_BUG_ON(page->mapping && !PageAnon(page)); - __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON); + __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false); } void mem_cgroup_uncharge_cache_page(struct page *page) { VM_BUG_ON(page_mapped(page)); VM_BUG_ON(page->mapping); - __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE); + __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false); } /* @@ -3141,7 +3156,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) if (!swapout) /* this was a swap cache but the swap is unused ! */ ctype = MEM_CGROUP_CHARGE_TYPE_DROP; - memcg = __mem_cgroup_uncharge_common(page, ctype); + memcg = __mem_cgroup_uncharge_common(page, ctype, false); /* * record memcg information, if swapout && memcg != NULL, @@ -3231,19 +3246,18 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry, * Before starting migration, account PAGE_SIZE to mem_cgroup that the old * page belongs to. */ -int mem_cgroup_prepare_migration(struct page *page, - struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask) +void mem_cgroup_prepare_migration(struct page *page, struct page *newpage, + struct mem_cgroup **memcgp) { struct mem_cgroup *memcg = NULL; struct page_cgroup *pc; enum charge_type ctype; - int ret = 0; *memcgp = NULL; VM_BUG_ON(PageTransHuge(page)); if (mem_cgroup_disabled()) - return 0; + return; pc = lookup_page_cgroup(page); lock_page_cgroup(pc); @@ -3288,24 +3302,9 @@ int mem_cgroup_prepare_migration(struct page *page, * we return here. */ if (!memcg) - return 0; + return; *memcgp = memcg; - ret = __mem_cgroup_try_charge(NULL, gfp_mask, 1, memcgp, false); - css_put(&memcg->css);/* drop extra refcnt */ - if (ret) { - if (PageAnon(page)) { - lock_page_cgroup(pc); - ClearPageCgroupMigration(pc); - unlock_page_cgroup(pc); - /* - * The old page may be fully unmapped while we kept it. - */ - mem_cgroup_uncharge_page(page); - } - /* we'll need to revisit this error code (we have -EINTR) */ - return -ENOMEM; - } /* * We charge new page before it's used/mapped. So, even if unlock_page() * is called before end_migration, we can catch all events on this new @@ -3318,8 +3317,12 @@ int mem_cgroup_prepare_migration(struct page *page, ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; else ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM; + /* + * The page is committed to the memcg, but it's not actually + * charged to the res_counter since we plan on replacing the + * old one and only one page is going to be left afterwards. + */ __mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false); - return ret; } /* remove redundant charge if migration failed*/ @@ -3341,6 +3344,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg, used = newpage; unused = oldpage; } + anon = PageAnon(used); + __mem_cgroup_uncharge_common(unused, + anon ? MEM_CGROUP_CHARGE_TYPE_ANON + : MEM_CGROUP_CHARGE_TYPE_CACHE, + true); + css_put(&memcg->css); /* * We disallowed uncharge of pages under migration because mapcount * of the page goes down to zero, temporarly. @@ -3350,10 +3359,6 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg, lock_page_cgroup(pc); ClearPageCgroupMigration(pc); unlock_page_cgroup(pc); - anon = PageAnon(used); - __mem_cgroup_uncharge_common(unused, - anon ? MEM_CGROUP_CHARGE_TYPE_ANON - : MEM_CGROUP_CHARGE_TYPE_CACHE); /* * If a page is a file cache, radix-tree replacement is very atomic diff --git a/mm/migrate.c b/mm/migrate.c index 6c37c51565e5..77ed2d773705 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -683,7 +683,6 @@ static int __unmap_and_move(struct page *page, struct page *newpage, { int rc = -EAGAIN; int remap_swapcache = 1; - int charge = 0; struct mem_cgroup *mem; struct anon_vma *anon_vma = NULL; @@ -725,12 +724,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage, } /* charge against new page */ - charge = mem_cgroup_prepare_migration(page, newpage, &mem, GFP_KERNEL); - if (charge == -ENOMEM) { - rc = -ENOMEM; - goto unlock; - } - BUG_ON(charge); + mem_cgroup_prepare_migration(page, newpage, &mem); if (PageWriteback(page)) { /* @@ -820,8 +814,7 @@ skip_unmap: put_anon_vma(anon_vma); uncharge: - if (!charge) - mem_cgroup_end_migration(mem, page, newpage, rc == 0); + mem_cgroup_end_migration(mem, page, newpage, rc == 0); unlock: unlock_page(page); out: -- GitLab From 5d84c7766e8aacc6e3477bdf02fdb417163cf89b Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:28 -0700 Subject: [PATCH 4953/5711] mm: swapfile: clean up unuse_pte race handling The conditional mem_cgroup_cancel_charge_swapin() is a leftover from when the function would continue to reestablish the page even after mem_cgroup_try_charge_swapin() failed. After 85d9fc8 "memcg: fix refcnt handling at swapoff", the condition is always true when this code is reached. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: Hugh Dickins Cc: Johannes Weiner Cc: Michal Hocko Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swapfile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 63958d60ecb0..14e254c768fc 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -835,8 +835,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) { - if (ret > 0) - mem_cgroup_cancel_charge_swapin(memcg); + mem_cgroup_cancel_charge_swapin(memcg); ret = 0; goto out; } -- GitLab From 0c59b89c81eab7fe7dcf08f2252ae22a6c081ce8 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:31 -0700 Subject: [PATCH 4954/5711] mm: memcg: push down PageSwapCache check into uncharge entry functions Not all uncharge paths need to check if the page is swapcache, some of them can know for sure. Push down the check into all callsites of uncharge_common() so that the patch that removes some of them is more obvious. Signed-off-by: Johannes Weiner Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7eadcdad06f3..87c2ec49b482 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2987,8 +2987,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype, if (mem_cgroup_disabled()) return NULL; - if (PageSwapCache(page)) - return NULL; + VM_BUG_ON(PageSwapCache(page)); if (PageTransHuge(page)) { nr_pages <<= compound_order(page); @@ -3085,6 +3084,8 @@ void mem_cgroup_uncharge_page(struct page *page) if (page_mapped(page)) return; VM_BUG_ON(page->mapping && !PageAnon(page)); + if (PageSwapCache(page)) + return; __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false); } @@ -3092,6 +3093,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page) { VM_BUG_ON(page_mapped(page)); VM_BUG_ON(page->mapping); + if (PageSwapCache(page)) + return; __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false); } @@ -3156,6 +3159,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) if (!swapout) /* this was a swap cache but the swap is unused ! */ ctype = MEM_CGROUP_CHARGE_TYPE_DROP; + if (PageSwapCache(page)) + return; memcg = __mem_cgroup_uncharge_common(page, ctype, false); /* @@ -3345,10 +3350,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg, unused = oldpage; } anon = PageAnon(used); - __mem_cgroup_uncharge_common(unused, - anon ? MEM_CGROUP_CHARGE_TYPE_ANON - : MEM_CGROUP_CHARGE_TYPE_CACHE, - true); + if (!PageSwapCache(unused)) + __mem_cgroup_uncharge_common(unused, + anon ? MEM_CGROUP_CHARGE_TYPE_ANON + : MEM_CGROUP_CHARGE_TYPE_CACHE, + true); css_put(&memcg->css); /* * We disallowed uncharge of pages under migration because mapcount -- GitLab From 7d188958bb64708577aa77e6b1ad68abbf0480f5 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:34 -0700 Subject: [PATCH 4955/5711] mm: memcg: only check for PageSwapCache when uncharging anon Only anon pages that are uncharged at the time of the last page table mapping vanishing may be in swapcache. When shmem pages, file pages, swap-freed anon pages, or just migrated pages are uncharged, they are known for sure to be not in swapcache. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 87c2ec49b482..29bc4400378d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3093,8 +3093,6 @@ void mem_cgroup_uncharge_cache_page(struct page *page) { VM_BUG_ON(page_mapped(page)); VM_BUG_ON(page->mapping); - if (PageSwapCache(page)) - return; __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false); } @@ -3159,8 +3157,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) if (!swapout) /* this was a swap cache but the swap is unused ! */ ctype = MEM_CGROUP_CHARGE_TYPE_DROP; - if (PageSwapCache(page)) - return; memcg = __mem_cgroup_uncharge_common(page, ctype, false); /* @@ -3350,11 +3346,10 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg, unused = oldpage; } anon = PageAnon(used); - if (!PageSwapCache(unused)) - __mem_cgroup_uncharge_common(unused, - anon ? MEM_CGROUP_CHARGE_TYPE_ANON - : MEM_CGROUP_CHARGE_TYPE_CACHE, - true); + __mem_cgroup_uncharge_common(unused, + anon ? MEM_CGROUP_CHARGE_TYPE_ANON + : MEM_CGROUP_CHARGE_TYPE_CACHE, + true); css_put(&memcg->css); /* * We disallowed uncharge of pages under migration because mapcount -- GitLab From 827a03d22e776ff7838b5b2780b71092e0b9de1e Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:36 -0700 Subject: [PATCH 4956/5711] mm: memcg: move swapin charge functions above callsites Charging cache pages may require swapin in the shmem case. Save the forward declaration and just move the swapin functions above the cache charging functions. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 68 +++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 29bc4400378d..3be1afab8523 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2796,37 +2796,6 @@ int mem_cgroup_newpage_charge(struct page *page, MEM_CGROUP_CHARGE_TYPE_ANON); } -static void -__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr, - enum charge_type ctype); - -int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, - gfp_t gfp_mask) -{ - struct mem_cgroup *memcg = NULL; - enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE; - int ret; - - if (mem_cgroup_disabled()) - return 0; - if (PageCompound(page)) - return 0; - - if (unlikely(!mm)) - mm = &init_mm; - if (!page_is_file_cache(page)) - type = MEM_CGROUP_CHARGE_TYPE_SHMEM; - - if (!PageSwapCache(page)) - ret = mem_cgroup_charge_common(page, mm, gfp_mask, type); - else { /* page is swapcache/shmem */ - ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg); - if (!ret) - __mem_cgroup_commit_charge_swapin(page, memcg, type); - } - return ret; -} - /* * While swap-in, try_charge -> commit or cancel, the page is locked. * And when try_charge() successfully returns, one refcnt to memcg without @@ -2873,6 +2842,15 @@ charge_cur_mm: return ret; } +void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) +{ + if (mem_cgroup_disabled()) + return; + if (!memcg) + return; + __mem_cgroup_cancel_charge(memcg, 1); +} + static void __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg, enum charge_type ctype) @@ -2910,13 +2888,31 @@ void mem_cgroup_commit_charge_swapin(struct page *page, MEM_CGROUP_CHARGE_TYPE_ANON); } -void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) +int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, + gfp_t gfp_mask) { + struct mem_cgroup *memcg = NULL; + enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE; + int ret; + if (mem_cgroup_disabled()) - return; - if (!memcg) - return; - __mem_cgroup_cancel_charge(memcg, 1); + return 0; + if (PageCompound(page)) + return 0; + + if (unlikely(!mm)) + mm = &init_mm; + if (!page_is_file_cache(page)) + type = MEM_CGROUP_CHARGE_TYPE_SHMEM; + + if (!PageSwapCache(page)) + ret = mem_cgroup_charge_common(page, mm, gfp_mask, type); + else { /* page is swapcache/shmem */ + ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg); + if (!ret) + __mem_cgroup_commit_charge_swapin(page, memcg, type); + } + return ret; } static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg, -- GitLab From 62ba7442c8e286b6dd68fe82a3cc85c9414d909b Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:39 -0700 Subject: [PATCH 4957/5711] mm: memcg: remove unneeded shmem charge type shmem page charges have not needed a separate charge type to tell them from regular file pages since 08e552c ("memcg: synchronized LRU"). Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3be1afab8523..17a79e5ed688 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -379,7 +379,6 @@ static bool move_file(void) enum charge_type { MEM_CGROUP_CHARGE_TYPE_CACHE = 0, MEM_CGROUP_CHARGE_TYPE_ANON, - MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ MEM_CGROUP_CHARGE_TYPE_DROP, /* a page was unused swap cache */ NR_CHARGE_TYPE, @@ -2902,8 +2901,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, if (unlikely(!mm)) mm = &init_mm; - if (!page_is_file_cache(page)) - type = MEM_CGROUP_CHARGE_TYPE_SHMEM; if (!PageSwapCache(page)) ret = mem_cgroup_charge_common(page, mm, gfp_mask, type); @@ -3310,10 +3307,8 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage, */ if (PageAnon(page)) ctype = MEM_CGROUP_CHARGE_TYPE_ANON; - else if (page_is_file_cache(page)) - ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; else - ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM; + ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; /* * The page is committed to the memcg, but it's not actually * charged to the res_counter since we plan on replacing the @@ -3407,10 +3402,6 @@ void mem_cgroup_replace_page_cache(struct page *oldpage, */ if (!memcg) return; - - if (PageSwapBacked(oldpage)) - type = MEM_CGROUP_CHARGE_TYPE_SHMEM; - /* * Even if newpage->mapping was NULL before starting replacement, * the newpage may be on LRU(or pagevec for LRU) already. We lock -- GitLab From 24467cacc03cf8b156d4c6786697e5e5d13c9321 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:40 -0700 Subject: [PATCH 4958/5711] mm: memcg: remove needless !mm fixup to init_mm when charging It does not matter to __mem_cgroup_try_charge() if the passed mm is NULL or init_mm, it will charge the root memcg in either case. Also fix up the comment in __mem_cgroup_try_charge() that claimed the init_mm would be charged when no mm was passed. It's not really incorrect, but confusing. Clarify that the root memcg is charged in this case. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 17a79e5ed688..10b370345a5b 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2333,7 +2333,7 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, * We always charge the cgroup the mm_struct belongs to. * The mm_struct's mem_cgroup changes on task migration if the * thread group leader migrates. It's possible that mm is not - * set, if so charge the init_mm (happens for pagecache usage). + * set, if so charge the root memcg (happens for pagecache usage). */ if (!*ptr && !mm) *ptr = root_mem_cgroup; @@ -2833,8 +2833,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, ret = 0; return ret; charge_cur_mm: - if (unlikely(!mm)) - mm = &init_mm; ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true); if (ret == -EINTR) ret = 0; @@ -2899,9 +2897,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, if (PageCompound(page)) return 0; - if (unlikely(!mm)) - mm = &init_mm; - if (!PageSwapCache(page)) ret = mem_cgroup_charge_common(page, mm, gfp_mask, type); else { /* page is swapcache/shmem */ -- GitLab From 0435a2fdcb50f8e53a67e98c27708e5d9396b71a Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:43 -0700 Subject: [PATCH 4959/5711] mm: memcg: split swapin charge function into private and public part When shmem is charged upon swapin, it does not need to check twice whether the memory controller is enabled. Also, shmem pages do not have to be checked for everything that regular anon pages have to be checked for, so let shmem use the internal version directly and allow future patches to move around checks that are only required when swapping in anon pages. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 10b370345a5b..4cc962d566ce 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2801,18 +2801,14 @@ int mem_cgroup_newpage_charge(struct page *page, * struct page_cgroup is acquired. This refcnt will be consumed by * "commit()" or removed by "cancel()" */ -int mem_cgroup_try_charge_swapin(struct mm_struct *mm, - struct page *page, - gfp_t mask, struct mem_cgroup **memcgp) +static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm, + struct page *page, + gfp_t mask, + struct mem_cgroup **memcgp) { struct mem_cgroup *memcg; int ret; - *memcgp = NULL; - - if (mem_cgroup_disabled()) - return 0; - if (!do_swap_account) goto charge_cur_mm; /* @@ -2839,6 +2835,15 @@ charge_cur_mm: return ret; } +int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page, + gfp_t gfp_mask, struct mem_cgroup **memcgp) +{ + *memcgp = NULL; + if (mem_cgroup_disabled()) + return 0; + return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp); +} + void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) { if (mem_cgroup_disabled()) @@ -2900,7 +2905,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, if (!PageSwapCache(page)) ret = mem_cgroup_charge_common(page, mm, gfp_mask, type); else { /* page is swapcache/shmem */ - ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg); + ret = __mem_cgroup_try_charge_swapin(mm, page, + gfp_mask, &memcg); if (!ret) __mem_cgroup_commit_charge_swapin(page, memcg, type); } -- GitLab From 90deb78839faedd194b65d419dbd9cba981e1922 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:47 -0700 Subject: [PATCH 4960/5711] mm: memcg: only check swap cache pages for repeated charging Only anon and shmem pages in the swap cache are attempted to be charged multiple times, from every swap pte fault or from shmem_unuse(). No other pages require checking PageCgroupUsed(). Charging pages in the swap cache is also serialized by the page lock, and since both the try_charge and commit_charge are called under the same page lock section, the PageCgroupUsed() check might as well happen before the counter charging, let alone reclaim. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 4cc962d566ce..1a2020d72ca0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2538,11 +2538,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, bool anon; lock_page_cgroup(pc); - if (unlikely(PageCgroupUsed(pc))) { - unlock_page_cgroup(pc); - __mem_cgroup_cancel_charge(memcg, nr_pages); - return; - } + VM_BUG_ON(PageCgroupUsed(pc)); /* * we don't need page_cgroup_lock about tail pages, becase they are not * accessed by any other context at this point. @@ -2807,8 +2803,19 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct mem_cgroup **memcgp) { struct mem_cgroup *memcg; + struct page_cgroup *pc; int ret; + pc = lookup_page_cgroup(page); + /* + * Every swap fault against a single page tries to charge the + * page, bail as early as possible. shmem_unuse() encounters + * already charged pages, too. The USED bit is protected by + * the page lock, which serializes swap cache removal, which + * in turn serializes uncharging. + */ + if (PageCgroupUsed(pc)) + return 0; if (!do_swap_account) goto charge_cur_mm; /* -- GitLab From bdf4f4d2161a795b9323855a81a047bd68f16202 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 31 Jul 2012 16:45:50 -0700 Subject: [PATCH 4961/5711] mm: memcg: only check anon swapin page charges for swap cache shmem knows for sure that the page is in swap cache when attempting to charge a page, because the cache charge entry function has a check for it. Only anon pages may be removed from swap cache already when trying to charge their swapin. Adjust the comment, though: '4969c11 mm: fix swapin race condition' added a stable PageSwapCache check under the page lock in the do_swap_page() before calling the memory controller, so it's unuse_pte()'s pte_same() that may fail. Signed-off-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: David Rientjes Cc: Hugh Dickins Cc: Johannes Weiner Cc: Wanpeng Li Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1a2020d72ca0..b06833f2b89e 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2818,14 +2818,6 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm, return 0; if (!do_swap_account) goto charge_cur_mm; - /* - * A racing thread's fault, or swapoff, may have already updated - * the pte, and even removed page from swap cache: in those cases - * do_swap_page()'s pte_same() test will fail; but there's also a - * KSM case which does need to charge the page. - */ - if (!PageSwapCache(page)) - goto charge_cur_mm; memcg = try_get_mem_cgroup_from_page(page); if (!memcg) goto charge_cur_mm; @@ -2848,6 +2840,20 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page, *memcgp = NULL; if (mem_cgroup_disabled()) return 0; + /* + * A racing thread's fault, or swapoff, may have already + * updated the pte, and even removed page from swap cache: in + * those cases unuse_pte()'s pte_same() test will fail; but + * there's also a KSM case which does need to charge the page. + */ + if (!PageSwapCache(page)) { + int ret; + + ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, memcgp, true); + if (ret == -EINTR) + ret = 0; + return ret; + } return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp); } -- GitLab From 3ad3d901bbcfb15a5e4690e55350db0899095a68 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 31 Jul 2012 16:45:52 -0700 Subject: [PATCH 4962/5711] mm: mmu_notifier: fix freed page still mapped in secondary MMU mmu_notifier_release() is called when the process is exiting. It will delete all the mmu notifiers. But at this time the page belonging to the process is still present in page tables and is present on the LRU list, so this race will happen: CPU 0 CPU 1 mmu_notifier_release: try_to_unmap: hlist_del_init_rcu(&mn->hlist); ptep_clear_flush_notify: mmu nofifler not found free page !!!!!! /* * At the point, the page has been * freed, but it is still mapped in * the secondary MMU. */ mn->ops->release(mn, mm); Then the box is not stable and sometimes we can get this bug: [ 738.075923] BUG: Bad page state in process migrate-perf pfn:03bec [ 738.075931] page:ffffea00000efb00 count:0 mapcount:0 mapping: (null) index:0x8076 [ 738.075936] page flags: 0x20000000000014(referenced|dirty) The same issue is present in mmu_notifier_unregister(). We can call ->release before deleting the notifier to ensure the page has been unmapped from the secondary MMU before it is freed. Signed-off-by: Xiao Guangrong Cc: Avi Kivity Cc: Marcelo Tosatti Cc: Paul Gortmaker Cc: Andrea Arcangeli Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmu_notifier.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 9a611d3a1848..862b60822d9f 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -33,6 +33,24 @@ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; + struct hlist_node *n; + + /* + * RCU here will block mmu_notifier_unregister until + * ->release returns. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) + /* + * if ->release runs before mmu_notifier_unregister it + * must be handled as it's the only way for the driver + * to flush all existing sptes and stop the driver + * from establishing any more sptes before all the + * pages in the mm are freed. + */ + if (mn->ops->release) + mn->ops->release(mn, mm); + rcu_read_unlock(); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_struct *mm) * mmu_notifier_unregister to return. */ hlist_del_init_rcu(&mn->hlist); - /* - * RCU here will block mmu_notifier_unregister until - * ->release returns. - */ - rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); - /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. - */ - if (mn->ops->release) - mn->ops->release(mn, mm); - rcu_read_unlock(); - spin_lock(&mm->mmu_notifier_mm->lock); } spin_unlock(&mm->mmu_notifier_mm->lock); @@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) { BUG_ON(atomic_read(&mm->mm_count) <= 0); - spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { - hlist_del_rcu(&mn->hlist); - /* * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); + /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the @@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (mn->ops->release) mn->ops->release(mn, mm); rcu_read_unlock(); - } else + + spin_lock(&mm->mmu_notifier_mm->lock); + hlist_del_rcu(&mn->hlist); spin_unlock(&mm->mmu_notifier_mm->lock); + } /* * Wait any running method to finish, of course including -- GitLab From e62e384e9da8d9a0c599795464a7e76fd490931c Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 31 Jul 2012 16:45:55 -0700 Subject: [PATCH 4963/5711] memcg: prevent OOM with too many dirty pages The current implementation of dirty pages throttling is not memcg aware which makes it easy to have memcg LRUs full of dirty pages. Without throttling, these LRUs can be scanned faster than the rate of writeback, leading to memcg OOM conditions when the hard limit is small. This patch fixes the problem by throttling the allocating process (possibly a writer) during the hard limit reclaim by waiting on PageReclaim pages. We are waiting only for PageReclaim pages because those are the pages that made one full round over LRU and that means that the writeback is much slower than scanning. The solution is far from being ideal - long term solution is memcg aware dirty throttling - but it is meant to be a band aid until we have a real fix. We are seeing this happening during nightly backups which are placed into containers to prevent from eviction of the real working set. The change affects only memcg reclaim and only when we encounter PageReclaim pages which is a signal that the reclaim doesn't catch up on with the writers so somebody should be throttled. This could be potentially unfair because it could be somebody else from the group who gets throttled on behalf of the writer but as writers need to allocate as well and they allocate in higher rate the probability that only innocent processes would be penalized is not that high. I have tested this change by a simple dd copying /dev/zero to tmpfs or ext3 running under small memcg (1G copy under 5M, 60M, 300M and 2G containers) and dd got killed by OOM killer every time. With the patch I could run the dd with the same size under 5M controller without any OOM. The issue is more visible with slower devices for output. * With the patch ================ * tmpfs size=2G --------------- $ vim cgroup_cache_oom_test.sh $ ./cgroup_cache_oom_test.sh 5M using Limit 5M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 30.4049 s, 34.5 MB/s $ ./cgroup_cache_oom_test.sh 60M using Limit 60M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 31.4561 s, 33.3 MB/s $ ./cgroup_cache_oom_test.sh 300M using Limit 300M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 20.4618 s, 51.2 MB/s $ ./cgroup_cache_oom_test.sh 2G using Limit 2G for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 1.42172 s, 738 MB/s * ext3 ------ $ ./cgroup_cache_oom_test.sh 5M using Limit 5M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 27.9547 s, 37.5 MB/s $ ./cgroup_cache_oom_test.sh 60M using Limit 60M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 30.3221 s, 34.6 MB/s $ ./cgroup_cache_oom_test.sh 300M using Limit 300M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 24.5764 s, 42.7 MB/s $ ./cgroup_cache_oom_test.sh 2G using Limit 2G for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 3.35828 s, 312 MB/s * Without the patch =================== * tmpfs size=2G --------------- $ ./cgroup_cache_oom_test.sh 5M using Limit 5M for group ./cgroup_cache_oom_test.sh: line 46: 4668 Killed dd if=/dev/zero of=$OUT/zero bs=1M count=$count $ ./cgroup_cache_oom_test.sh 60M using Limit 60M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 25.4989 s, 41.1 MB/s $ ./cgroup_cache_oom_test.sh 300M using Limit 300M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 24.3928 s, 43.0 MB/s $ ./cgroup_cache_oom_test.sh 2G using Limit 2G for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 1.49797 s, 700 MB/s * ext3 ------ $ ./cgroup_cache_oom_test.sh 5M using Limit 5M for group ./cgroup_cache_oom_test.sh: line 46: 4689 Killed dd if=/dev/zero of=$OUT/zero bs=1M count=$count $ ./cgroup_cache_oom_test.sh 60M using Limit 60M for group ./cgroup_cache_oom_test.sh: line 46: 4692 Killed dd if=/dev/zero of=$OUT/zero bs=1M count=$count $ ./cgroup_cache_oom_test.sh 300M using Limit 300M for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 20.248 s, 51.8 MB/s $ ./cgroup_cache_oom_test.sh 2G using Limit 2G for group 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 2.85201 s, 368 MB/s [akpm@linux-foundation.org: tweak changelog, reordered the test to optimize for CONFIG_CGROUP_MEM_RES_CTLR=n] [hughd@google.com: fix deadlock with loop driver] Cc: KAMEZAWA Hiroyuki Cc: Minchan Kim Cc: Rik van Riel Cc: Ying Han Cc: Greg Thelen Cc: Hugh Dickins Reviewed-by: Mel Gorman Acked-by: Johannes Weiner Reviewed-by: Fengguang Wu Signed-off-by: Michal Hocko Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 88804017e7d6..ca43aa00ea0e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -720,9 +720,26 @@ static unsigned long shrink_page_list(struct list_head *page_list, (PageSwapCache(page) && (sc->gfp_mask & __GFP_IO)); if (PageWriteback(page)) { - nr_writeback++; - unlock_page(page); - goto keep; + /* + * memcg doesn't have any dirty pages throttling so we + * could easily OOM just because too many pages are in + * writeback from reclaim and there is nothing else to + * reclaim. + * + * Check may_enter_fs, certainly because a loop driver + * thread might enter reclaim, and deadlock if it waits + * on a page for which it is needed to do the write + * (loop masks off __GFP_IO|__GFP_FS for this reason); + * but more thought would probably show more reasons. + */ + if (!global_reclaim(sc) && PageReclaim(page) && + may_enter_fs) + wait_on_page_writeback(page); + else { + nr_writeback++; + unlock_page(page); + goto keep; + } } references = page_check_references(page, sc); -- GitLab From c3b94f44fcb0725471ecebb701c077a0ed67bd07 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 31 Jul 2012 16:45:59 -0700 Subject: [PATCH 4964/5711] memcg: further prevent OOM with too many dirty pages The may_enter_fs test turns out to be too restrictive: though I saw no problem with it when testing on 3.5-rc6, it very soon OOMed when I tested on 3.5-rc6-mm1. I don't know what the difference there is, perhaps I just slightly changed the way I started off the testing: dd if=/dev/zero of=/mnt/temp bs=1M count=1024; rm -f /mnt/temp; sync repeatedly, in 20M memory.limit_in_bytes cgroup to ext4 on USB stick. ext4 (and gfs2 and xfs) turn out to allocate new pages for writing with AOP_FLAG_NOFS: that seems a little worrying, and it's unclear to me why the transaction needs to be started even before allocating pagecache memory. But it may not be worth worrying about these days: if direct reclaim avoids FS writeback, does __GFP_FS now mean anything? Anyway, we insisted on the may_enter_fs test to avoid hangs with the loop device; but since that also masks off __GFP_IO, we can test for __GFP_IO directly, ignoring may_enter_fs and __GFP_FS. But even so, the test still OOMs sometimes: when originally testing on 3.5-rc6, it OOMed about one time in five or ten; when testing just now on 3.5-rc6-mm1, it OOMed on the first iteration. This residual problem comes from an accumulation of pages under ordinary writeback, not marked PageReclaim, so rightly not causing the memcg check to wait on their writeback: these too can prevent shrink_page_list() from freeing any pages, so many times that memcg reclaim fails and OOMs. Deal with these in the same way as direct reclaim now deals with dirty FS pages: mark them PageReclaim. It is appropriate to rotate these to tail of list when writepage completes, but more importantly, the PageReclaim flag makes memcg reclaim wait on them if encountered again. Increment NR_VMSCAN_IMMEDIATE? That's arguable: I chose not. Setting PageReclaim here may occasionally race with end_page_writeback() clearing it: lru_deactivate_fn() already faced the same race, and correctly concluded that the window is small and the issue non-critical. With these changes, the test runs indefinitely without OOMing on ext4, ext3 and ext2: I'll move on to test with other filesystems later. Trivia: invert conditions for a clearer block without an else, and goto keep_locked to do the unlock_page. Signed-off-by: Hugh Dickins Cc: KAMEZAWA Hiroyuki Cc: Minchan Kim Cc: Rik van Riel Cc: Ying Han Cc: Greg Thelen Cc: Hugh Dickins Cc: Mel Gorman Cc: Johannes Weiner Cc: Fengguang Wu Acked-by: Michal Hocko Cc: Dave Chinner Cc: Theodore Ts'o Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index ca43aa00ea0e..e37e68725090 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -723,23 +723,38 @@ static unsigned long shrink_page_list(struct list_head *page_list, /* * memcg doesn't have any dirty pages throttling so we * could easily OOM just because too many pages are in - * writeback from reclaim and there is nothing else to - * reclaim. + * writeback and there is nothing else to reclaim. * - * Check may_enter_fs, certainly because a loop driver + * Check __GFP_IO, certainly because a loop driver * thread might enter reclaim, and deadlock if it waits * on a page for which it is needed to do the write * (loop masks off __GFP_IO|__GFP_FS for this reason); * but more thought would probably show more reasons. + * + * Don't require __GFP_FS, since we're not going into + * the FS, just waiting on its writeback completion. + * Worryingly, ext4 gfs2 and xfs allocate pages with + * grab_cache_page_write_begin(,,AOP_FLAG_NOFS), so + * testing may_enter_fs here is liable to OOM on them. */ - if (!global_reclaim(sc) && PageReclaim(page) && - may_enter_fs) - wait_on_page_writeback(page); - else { + if (global_reclaim(sc) || + !PageReclaim(page) || !(sc->gfp_mask & __GFP_IO)) { + /* + * This is slightly racy - end_page_writeback() + * might have just cleared PageReclaim, then + * setting PageReclaim here end up interpreted + * as PageReadahead - but that does not matter + * enough to care. What we do want is for this + * page to have PageReclaim set next time memcg + * reclaim reaches the tests above, so it will + * then wait_on_page_writeback() to avoid OOM; + * and it's also appropriate in global reclaim. + */ + SetPageReclaim(page); nr_writeback++; - unlock_page(page); - goto keep; + goto keep_locked; } + wait_on_page_writeback(page); } references = page_check_references(page, sc); -- GitLab From b214514592d2dcb0b9d14ee8dd14f3699e3b0a84 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 31 Jul 2012 16:46:01 -0700 Subject: [PATCH 4965/5711] memcg: add mem_cgroup_from_css() helper Add a mem_cgroup_from_css() helper to replace open-coded invokations of container_of(). To clarify the code and to add a little more type safety. [akpm@linux-foundation.org: fix extensive breakage] Signed-off-by: Wanpeng Li Acked-by: Michal Hocko Cc: Johannes Weiner Cc: KAMEZAWA Hiroyuki Cc: Gavin Shan Cc: Wanpeng Li Cc: Gavin Shan Cc: Johannes Weiner Cc: KAMEZAWA Hiroyuki Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b06833f2b89e..795e525afaba 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -405,6 +405,12 @@ enum charge_type { static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); +static inline +struct mem_cgroup *mem_cgroup_from_css(struct cgroup_subsys_state *s) +{ + return container_of(s, struct mem_cgroup, css); +} + /* Writing them here to avoid exposing memcg's inner layout */ #ifdef CONFIG_MEMCG_KMEM #include @@ -862,9 +868,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) { - return container_of(cgroup_subsys_state(cont, - mem_cgroup_subsys_id), struct mem_cgroup, - css); + return mem_cgroup_from_css( + cgroup_subsys_state(cont, mem_cgroup_subsys_id)); } struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) @@ -877,8 +882,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) if (unlikely(!p)) return NULL; - return container_of(task_subsys_state(p, mem_cgroup_subsys_id), - struct mem_cgroup, css); + return mem_cgroup_from_css(task_subsys_state(p, mem_cgroup_subsys_id)); } struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) @@ -964,8 +968,7 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, css = css_get_next(&mem_cgroup_subsys, id + 1, &root->css, &id); if (css) { if (css == &root->css || css_tryget(css)) - memcg = container_of(css, - struct mem_cgroup, css); + memcg = mem_cgroup_from_css(css); } else id = 0; rcu_read_unlock(); @@ -2494,7 +2497,7 @@ static struct mem_cgroup *mem_cgroup_lookup(unsigned short id) css = css_lookup(&mem_cgroup_subsys, id); if (!css) return NULL; - return container_of(css, struct mem_cgroup, css); + return mem_cgroup_from_css(css); } struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) -- GitLab From 5b760e64a64c8940cdccd0ba6fce19a9bd010d20 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 31 Jul 2012 16:46:02 -0700 Subject: [PATCH 4966/5711] mm/sparse: optimize sparse_index_alloc With CONFIG_SPARSEMEM_EXTREME, the two levels of memory section descriptors are allocated from slab or bootmem. When allocating from slab, let slab/bootmem allocator clear the memory chunk. We needn't clear it explicitly. Signed-off-by: Gavin Shan Reviewed-by: Michal Hocko Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/sparse.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index 950981fd07c5..fa933f43b2c9 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -65,14 +65,12 @@ static struct mem_section noinline __init_refok *sparse_index_alloc(int nid) if (slab_is_available()) { if (node_state(nid, N_HIGH_MEMORY)) - section = kmalloc_node(array_size, GFP_KERNEL, nid); + section = kzalloc_node(array_size, GFP_KERNEL, nid); else - section = kmalloc(array_size, GFP_KERNEL); - } else + section = kzalloc(array_size, GFP_KERNEL); + } else { section = alloc_bootmem_node(NODE_DATA(nid), array_size); - - if (section) - memset(section, 0, array_size); + } return section; } -- GitLab From db36a46113e101a8aa2d6ede41e78f2eaabed3f1 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 31 Jul 2012 16:46:04 -0700 Subject: [PATCH 4967/5711] mm/sparse: more checks on mem_section number __section_nr() was implemented to retrieve the corresponding memory section number according to its descriptor. It's possible that the specified memory section descriptor doesn't exist in the global array. So add more checking on that and report an error for a wrong case. Signed-off-by: Gavin Shan Acked-by: David Rientjes Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/sparse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/sparse.c b/mm/sparse.c index fa933f43b2c9..42ca0ea9af1b 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -130,6 +130,8 @@ int __section_nr(struct mem_section* ms) break; } + VM_BUG_ON(root_nr == NR_SECTION_ROOTS); + return (root_nr * SECTIONS_PER_ROOT) + (ms - root); } -- GitLab From c1c9518331969f97ea403bac66f0fd4a85d204d5 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 31 Jul 2012 16:46:06 -0700 Subject: [PATCH 4968/5711] mm/sparse: remove index_init_lock sparse_index_init() uses the index_init_lock spinlock to protect root mem_section assignment. The lock is not necessary anymore because the function is called only during boot (during paging init which is executed only from a single CPU) and from the hotplug code (by add_memory() via arch_add_memory()) which uses mem_hotplug_mutex. The lock was introduced by 28ae55c9 ("sparsemem extreme: hotplug preparation") and sparse_index_init() was used only during boot at that time. Later when the hotplug code (and add_memory()) was introduced there was no synchronization so it was possible to online more sections from the same root probably (though I am not 100% sure about that). The first synchronization has been added by 6ad696d2 ("mm: allow memory hotplug and hibernation in the same kernel") which was later replaced by the mem_hotplug_mutex - 20d6c96b ("mem-hotplug: introduce {un}lock_memory_hotplug()"). Let's remove the lock as it is not needed and it makes the code more confusing. [mhocko@suse.cz: changelog] Signed-off-by: Gavin Shan Reviewed-by: Michal Hocko Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/sparse.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index 42ca0ea9af1b..fac95f2888f2 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -77,7 +77,6 @@ static struct mem_section noinline __init_refok *sparse_index_alloc(int nid) static int __meminit sparse_index_init(unsigned long section_nr, int nid) { - static DEFINE_SPINLOCK(index_init_lock); unsigned long root = SECTION_NR_TO_ROOT(section_nr); struct mem_section *section; int ret = 0; @@ -88,20 +87,9 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid) section = sparse_index_alloc(nid); if (!section) return -ENOMEM; - /* - * This lock keeps two different sections from - * reallocating for the same index - */ - spin_lock(&index_init_lock); - - if (mem_section[root]) { - ret = -EEXIST; - goto out; - } mem_section[root] = section; -out: - spin_unlock(&index_init_lock); + return ret; } #else /* !SPARSEMEM_EXTREME */ -- GitLab From 69980e31754ef23307d51372e61bf7c2584f8a4b Mon Sep 17 00:00:00 2001 From: Tim Chen Date: Tue, 31 Jul 2012 16:46:08 -0700 Subject: [PATCH 4969/5711] memcg: gix memory accounting scalability in shrink_page_list I noticed in a multi-process parallel files reading benchmark I ran on a 8 socket machine, throughput slowed down by a factor of 8 when I ran the benchmark within a cgroup container. I traced the problem to the following code path (see below) when we are trying to reclaim memory from file cache. The res_counter_uncharge function is called on every page that's reclaimed and created heavy lock contention. The patch below allows the reclaimed pages to be uncharged from the resource counter in batch and recovered the regression. Tim 40.67% usemem [kernel.kallsyms] [k] _raw_spin_lock | --- _raw_spin_lock | |--92.61%-- res_counter_uncharge | | | |--100.00%-- __mem_cgroup_uncharge_common | | | | | |--100.00%-- mem_cgroup_uncharge_cache_page | | | __remove_mapping | | | shrink_page_list | | | shrink_inactive_list | | | shrink_mem_cgroup_zone | | | shrink_zone | | | do_try_to_free_pages | | | try_to_free_pages | | | __alloc_pages_nodemask | | | alloc_pages_current Signed-off-by: Tim Chen Acked-by: KAMEZAWA Hiroyuki Acked-by: Johannes Weiner Acked-by: Kirill A. Shutemov Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/vmscan.c b/mm/vmscan.c index e37e68725090..8d01243d9560 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -687,6 +687,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, cond_resched(); + mem_cgroup_uncharge_start(); while (!list_empty(page_list)) { enum page_references references; struct address_space *mapping; @@ -953,6 +954,7 @@ keep: list_splice(&ret_pages, page_list); count_vm_events(PGACTIVATE, pgactivate); + mem_cgroup_uncharge_end(); *ret_nr_dirty += nr_dirty; *ret_nr_writeback += nr_writeback; return nr_reclaimed; -- GitLab From 93180cec0064d072a984f91c429c5e6bcc816976 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:46:11 -0700 Subject: [PATCH 4970/5711] mips: zero out pg_data_t when it's allocated This patch is preparation for the next patch which removes the zeroing of the pg_data_t in core MM. All archs except MIPS already do this. Signed-off-by: Minchan Kim Cc: Ralf Baechle Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/sgi-ip27/ip27-memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index b105eca3c020..cd8fcab6b054 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -401,6 +401,7 @@ static void __init node_mem_init(cnodeid_t node) * Allocate the node data structures on the node first. */ __node_data[node] = __va(slot_freepfn << PAGE_SHIFT); + memset(__node_data[node], 0, PAGE_SIZE); NODE_DATA(node)->bdata = &bootmem_node_data[node]; NODE_DATA(node)->node_start_pfn = start_pfn; -- GitLab From 88fdf75d1bb51d85ba00c466391770056d44bc03 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:46:14 -0700 Subject: [PATCH 4971/5711] mm: warn if pg_data_t isn't initialized with zero Warn if memory-hotplug/boot code doesn't initialize pg_data_t with zero when it is allocated. Arch code and memory hotplug already initiailize pg_data_t. So this warning should never happen. I select fields randomly near the beginning, middle and end of pg_data_t for checking. This patch isn't for performance but for removing initialization code which is necessary to add whenever we adds new field to pg_data_t or zone. Firstly, Andrew suggested clearing out of pg_data_t in MM core part but Tejun doesn't like it because in the future, some archs can initialize some fields in arch code and pass them into general MM part so blindly clearing it out in mm core part would be very annoying. Signed-off-by: Minchan Kim Cc: Tejun Heo Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 48aee0f5902f..a6f7576aecae 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4515,6 +4515,9 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, { pg_data_t *pgdat = NODE_DATA(nid); + /* pg_data_t should be reset to zero when it's allocated */ + WARN_ON(pgdat->nr_zones || pgdat->node_start_pfn || pgdat->classzone_idx); + pgdat->node_id = nid; pgdat->node_start_pfn = node_start_pfn; calculate_node_totalpages(pgdat, zones_size, zholes_size); -- GitLab From 6527af5d1bea219d64095a5e30c1b1e0868aae16 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 31 Jul 2012 16:46:16 -0700 Subject: [PATCH 4972/5711] mm: remove redundant initialization pg_data_t is zeroed before reaching free_area_init_core(), so remove the now unnecessary initializations. Signed-off-by: Minchan Kim Cc: Tejun Heo Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/vmstat.h | 5 ----- mm/page_alloc.c | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 65efb92da996..ad2cfd53dadc 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -179,11 +179,6 @@ extern void zone_statistics(struct zone *, struct zone *, gfp_t gfp); #define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d) #define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d)) -static inline void zap_zone_vm_stats(struct zone *zone) -{ - memset(zone->vm_stat, 0, sizeof(zone->vm_stat)); -} - extern void inc_zone_state(struct zone *, enum zone_stat_item); #ifdef CONFIG_SMP diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a6f7576aecae..889532b8e6c1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4377,6 +4377,8 @@ void __init set_pageblock_order(void) * - mark all pages reserved * - mark all memory queues empty * - clear the memory bitmaps + * + * NOTE: pgdat should get zeroed by caller. */ static void __paginginit free_area_init_core(struct pglist_data *pgdat, unsigned long *zones_size, unsigned long *zholes_size) @@ -4387,10 +4389,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, int ret; pgdat_resize_init(pgdat); - pgdat->nr_zones = 0; init_waitqueue_head(&pgdat->kswapd_wait); init_waitqueue_head(&pgdat->pfmemalloc_wait); - pgdat->kswapd_max_order = 0; pgdat_page_cgroup_init(pgdat); for (j = 0; j < MAX_NR_ZONES; j++) { @@ -4451,11 +4451,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, zone_pcp_init(zone); lruvec_init(&zone->lruvec, zone); - zap_zone_vm_stats(zone); - zone->flags = 0; -#ifdef CONFIG_MEMORY_ISOLATION - zone->nr_pageblock_isolate = 0; -#endif if (!size) continue; -- GitLab From 09c231cb8bfdc35e7d896850d34440b8553b084f Mon Sep 17 00:00:00 2001 From: Nathan Zimmer Date: Tue, 31 Jul 2012 16:46:17 -0700 Subject: [PATCH 4973/5711] tmpfs: distribute interleave better across nodes When tmpfs has the interleave memory policy, it always starts allocating for each file from node 0 at offset 0. When there are many small files, the lower nodes fill up disproportionately. This patch spreads out node usage by starting files at nodes other than 0, by using the inode number to bias the starting node for interleave. Signed-off-by: Nathan Zimmer Signed-off-by: Hugh Dickins Cc: Christoph Lameter Cc: Nick Piggin Cc: Lee Schermerhorn Cc: KOSAKI Motohiro Cc: Rik van Riel Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/shmem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index c15b998e5a86..d4e184e2a38e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -929,7 +929,8 @@ static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; - pvma.vm_pgoff = index; + /* Bias interleave by inode number to distribute better across nodes */ + pvma.vm_pgoff = index + info->vfs_inode.i_ino; pvma.vm_ops = NULL; pvma.vm_policy = spol; return swapin_readahead(swap, gfp, &pvma, 0); @@ -942,7 +943,8 @@ static struct page *shmem_alloc_page(gfp_t gfp, /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; - pvma.vm_pgoff = index; + /* Bias interleave by inode number to distribute better across nodes */ + pvma.vm_pgoff = index + info->vfs_inode.i_ino; pvma.vm_ops = NULL; pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); -- GitLab From d833352a4338dc31295ed832a30c9ccff5c7a183 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:46:20 -0700 Subject: [PATCH 4974/5711] mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables If a process creates a large hugetlbfs mapping that is eligible for page table sharing and forks heavily with children some of whom fault and others which destroy the mapping then it is possible for page tables to get corrupted. Some teardowns of the mapping encounter a "bad pmd" and output a message to the kernel log. The final teardown will trigger a BUG_ON in mm/filemap.c. This was reproduced in 3.4 but is known to have existed for a long time and goes back at least as far as 2.6.37. It was probably was introduced in 2.6.20 by [39dde65c: shared page table for hugetlb page]. The messages look like this; [ ..........] Lots of bad pmd messages followed by this [ 127.164256] mm/memory.c:391: bad pmd ffff880412e04fe8(80000003de4000e7). [ 127.164257] mm/memory.c:391: bad pmd ffff880412e04ff0(80000003de6000e7). [ 127.164258] mm/memory.c:391: bad pmd ffff880412e04ff8(80000003de0000e7). [ 127.186778] ------------[ cut here ]------------ [ 127.186781] kernel BUG at mm/filemap.c:134! [ 127.186782] invalid opcode: 0000 [#1] SMP [ 127.186783] CPU 7 [ 127.186784] Modules linked in: af_packet cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf ext3 jbd dm_mod coretemp crc32c_intel usb_storage ghash_clmulni_intel aesni_intel i2c_i801 r8169 mii uas sr_mod cdrom sg iTCO_wdt iTCO_vendor_support shpchp serio_raw cryptd aes_x86_64 e1000e pci_hotplug dcdbas aes_generic container microcode ext4 mbcache jbd2 crc16 sd_mod crc_t10dif i915 drm_kms_helper drm i2c_algo_bit ehci_hcd ahci libahci usbcore rtc_cmos usb_common button i2c_core intel_agp video intel_gtt fan processor thermal thermal_sys hwmon ata_generic pata_atiixp libata scsi_mod [ 127.186801] [ 127.186802] Pid: 9017, comm: hugetlbfs-test Not tainted 3.4.0-autobuild #53 Dell Inc. OptiPlex 990/06D7TR [ 127.186804] RIP: 0010:[] [] __delete_from_page_cache+0x15e/0x160 [ 127.186809] RSP: 0000:ffff8804144b5c08 EFLAGS: 00010002 [ 127.186810] RAX: 0000000000000001 RBX: ffffea000a5c9000 RCX: 00000000ffffffc0 [ 127.186811] RDX: 0000000000000000 RSI: 0000000000000009 RDI: ffff88042dfdad00 [ 127.186812] RBP: ffff8804144b5c18 R08: 0000000000000009 R09: 0000000000000003 [ 127.186813] R10: 0000000000000000 R11: 000000000000002d R12: ffff880412ff83d8 [ 127.186814] R13: ffff880412ff83d8 R14: 0000000000000000 R15: ffff880412ff83d8 [ 127.186815] FS: 00007fe18ed2c700(0000) GS:ffff88042dce0000(0000) knlGS:0000000000000000 [ 127.186816] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 127.186817] CR2: 00007fe340000503 CR3: 0000000417a14000 CR4: 00000000000407e0 [ 127.186818] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 127.186819] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 127.186820] Process hugetlbfs-test (pid: 9017, threadinfo ffff8804144b4000, task ffff880417f803c0) [ 127.186821] Stack: [ 127.186822] ffffea000a5c9000 0000000000000000 ffff8804144b5c48 ffffffff810ed83b [ 127.186824] ffff8804144b5c48 000000000000138a 0000000000001387 ffff8804144b5c98 [ 127.186825] ffff8804144b5d48 ffffffff811bc925 ffff8804144b5cb8 0000000000000000 [ 127.186827] Call Trace: [ 127.186829] [] delete_from_page_cache+0x3b/0x80 [ 127.186832] [] truncate_hugepages+0x115/0x220 [ 127.186834] [] hugetlbfs_evict_inode+0x13/0x30 [ 127.186837] [] evict+0xa7/0x1b0 [ 127.186839] [] iput_final+0xd3/0x1f0 [ 127.186840] [] iput+0x39/0x50 [ 127.186842] [] d_kill+0xf8/0x130 [ 127.186843] [] dput+0xd2/0x1a0 [ 127.186845] [] __fput+0x170/0x230 [ 127.186848] [] ? rb_erase+0xce/0x150 [ 127.186849] [] fput+0x1d/0x30 [ 127.186851] [] remove_vma+0x37/0x80 [ 127.186853] [] do_munmap+0x2d2/0x360 [ 127.186855] [] sys_shmdt+0xc9/0x170 [ 127.186857] [] system_call_fastpath+0x16/0x1b [ 127.186858] Code: 0f 1f 44 00 00 48 8b 43 08 48 8b 00 48 8b 40 28 8b b0 40 03 00 00 85 f6 0f 88 df fe ff ff 48 89 df e8 e7 cb 05 00 e9 d2 fe ff ff <0f> 0b 55 83 e2 fd 48 89 e5 48 83 ec 30 48 89 5d d8 4c 89 65 e0 [ 127.186868] RIP [] __delete_from_page_cache+0x15e/0x160 [ 127.186870] RSP [ 127.186871] ---[ end trace 7cbac5d1db69f426 ]--- The bug is a race and not always easy to reproduce. To reproduce it I was doing the following on a single socket I7-based machine with 16G of RAM. $ hugeadm --pool-pages-max DEFAULT:13G $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmmax $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmall $ for i in `seq 1 9000`; do ./hugetlbfs-test; done On my particular machine, it usually triggers within 10 minutes but enabling debug options can change the timing such that it never hits. Once the bug is triggered, the machine is in trouble and needs to be rebooted. The machine will respond but processes accessing proc like "ps aux" will hang due to the BUG_ON. shutdown will also hang and needs a hard reset or a sysrq-b. The basic problem is a race between page table sharing and teardown. For the most part page table sharing depends on i_mmap_mutex. In some cases, it is also taking the mm->page_table_lock for the PTE updates but with shared page tables, it is the i_mmap_mutex that is more important. Unfortunately it appears to be also insufficient. Consider the following situation Process A Process B --------- --------- hugetlb_fault shmdt LockWrite(mmap_sem) do_munmap unmap_region unmap_vmas unmap_single_vma unmap_hugepage_range Lock(i_mmap_mutex) Lock(mm->page_table_lock) huge_pmd_unshare/unmap tables <--- (1) Unlock(mm->page_table_lock) Unlock(i_mmap_mutex) huge_pte_alloc ... Lock(i_mmap_mutex) ... vma_prio_walk, find svma, spte ... Lock(mm->page_table_lock) ... share spte ... Unlock(mm->page_table_lock) ... Unlock(i_mmap_mutex) ... hugetlb_no_page <--- (2) free_pgtables unlink_file_vma hugetlb_free_pgd_range remove_vma_list In this scenario, it is possible for Process A to share page tables with Process B that is trying to tear them down. The i_mmap_mutex on its own does not prevent Process A walking Process B's page tables. At (1) above, the page tables are not shared yet so it unmaps the PMDs. Process A sets up page table sharing and at (2) faults a new entry. Process B then trips up on it in free_pgtables. This patch fixes the problem by adding a new function __unmap_hugepage_range_final that is only called when the VMA is about to be destroyed. This function clears VM_MAYSHARE during unmap_hugepage_range() under the i_mmap_mutex. This makes the VMA ineligible for sharing and avoids the race. Superficially this looks like it would then be vunerable to truncate and madvise issues but hugetlbfs has its own truncate handlers so does not use unmap_mapping_range() and does not support madvise(DONTNEED). This should be treated as a -stable candidate if it is merged. Test program is as follows. The test case was mostly written by Michal Hocko with a few minor changes to reproduce this bug. ==== CUT HERE ==== static size_t huge_page_size = (2UL << 20); static size_t nr_huge_page_A = 512; static size_t nr_huge_page_B = 5632; unsigned int get_random(unsigned int max) { struct timeval tv; gettimeofday(&tv, NULL); srandom(tv.tv_usec); return random() % max; } static void play(void *addr, size_t size) { unsigned char *start = addr, *end = start + size, *a; start += get_random(size/2); /* we could itterate on huge pages but let's give it more time. */ for (a = start; a < end; a += 4096) *a = 0; } int main(int argc, char **argv) { key_t key = IPC_PRIVATE; size_t sizeA = nr_huge_page_A * huge_page_size; size_t sizeB = nr_huge_page_B * huge_page_size; int shmidA, shmidB; void *addrA = NULL, *addrB = NULL; int nr_children = 300, n = 0; if ((shmidA = shmget(key, sizeA, IPC_CREAT|SHM_HUGETLB|0660)) == -1) { perror("shmget:"); return 1; } if ((addrA = shmat(shmidA, addrA, SHM_R|SHM_W)) == (void *)-1UL) { perror("shmat"); return 1; } if ((shmidB = shmget(key, sizeB, IPC_CREAT|SHM_HUGETLB|0660)) == -1) { perror("shmget:"); return 1; } if ((addrB = shmat(shmidB, addrB, SHM_R|SHM_W)) == (void *)-1UL) { perror("shmat"); return 1; } fork_child: switch(fork()) { case 0: switch (n%3) { case 0: play(addrA, sizeA); break; case 1: play(addrB, sizeB); break; case 2: break; } break; case -1: perror("fork:"); break; default: if (++n < nr_children) goto fork_child; play(addrA, sizeA); break; } shmdt(addrA); shmdt(addrB); do { wait(NULL); } while (--n > 0); shmctl(shmidA, IPC_RMID, NULL); shmctl(shmidB, IPC_RMID, NULL); return 0; } [akpm@linux-foundation.org: name the declaration's args, fix CONFIG_HUGETLBFS=n build] Signed-off-by: Hugh Dickins Reviewed-by: Michal Hocko Signed-off-by: Mel Gorman Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 11 +++++++++++ mm/hugetlb.c | 28 ++++++++++++++++++++++++++-- mm/memory.c | 2 +- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index f9db20bfa9fc..225164842ab6 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -48,6 +48,10 @@ int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, unsigned long *, int *, int, unsigned int flags); void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long, struct page *); +void __unmap_hugepage_range_final(struct mmu_gather *tlb, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct page *ref_page); void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, unsigned long start, unsigned long end, struct page *ref_page); @@ -130,6 +134,13 @@ static inline void copy_huge_page(struct page *dst, struct page *src) #define hugetlb_change_protection(vma, address, end, newprot) +static inline void __unmap_hugepage_range_final(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long start, + unsigned long end, struct page *ref_page) +{ + BUG(); +} + static inline void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, unsigned long start, unsigned long end, struct page *ref_page) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c39e4beeb63a..bc727122dd44 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2429,6 +2429,25 @@ again: tlb_end_vma(tlb, vma); } +void __unmap_hugepage_range_final(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long start, + unsigned long end, struct page *ref_page) +{ + __unmap_hugepage_range(tlb, vma, start, end, ref_page); + + /* + * Clear this flag so that x86's huge_pmd_share page_table_shareable + * test will fail on a vma being torn down, and not grab a page table + * on its way out. We're lucky that the flag has such an appropriate + * name, and can in fact be safely cleared here. We could clear it + * before the __unmap_hugepage_range above, but all that's necessary + * is to clear it before releasing the i_mmap_mutex. This works + * because in the context this is called, the VMA is about to be + * destroyed and the i_mmap_mutex is held. + */ + vma->vm_flags &= ~VM_MAYSHARE; +} + void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, struct page *ref_page) { @@ -3012,9 +3031,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma, } } spin_unlock(&mm->page_table_lock); - mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); - + /* + * Must flush TLB before releasing i_mmap_mutex: x86's huge_pmd_unshare + * may have cleared our pud entry and done put_page on the page table: + * once we release i_mmap_mutex, another task can do the final put_page + * and that page table be reused and filled with junk. + */ flush_tlb_range(vma, start, end); + mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } int hugetlb_reserve_pages(struct inode *inode, diff --git a/mm/memory.c b/mm/memory.c index ec72a616ccd4..482f089765ff 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1345,7 +1345,7 @@ static void unmap_single_vma(struct mmu_gather *tlb, */ if (vma->vm_file) { mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex); - __unmap_hugepage_range(tlb, vma, start, end, NULL); + __unmap_hugepage_range_final(tlb, vma, start, end, NULL); mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } } else -- GitLab From 7ead55119ba58523c31f52365b5eb33f3bb34b3e Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 31 Jul 2012 16:46:22 -0700 Subject: [PATCH 4975/5711] rtc/rtc-88pm80x: assign ret only when rtc_register_driver fails At the probe we are assigning ret to return value of PTR_ERR right after the rtc_register_drive()r, as we would have done it in the if (IS_ERR(ptr)) check, since the function fails and goes inside that case Signed-off-by: Devendra Naga Cc: Alessandro Zummo Cc: Ashish Jangam Cc: David Dajun Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-88pm80x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index a2f956d90de0..7e050b44b2de 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -314,8 +314,8 @@ static int __devinit pm80x_rtc_probe(struct platform_device *pdev) info->rtc_dev = rtc_device_register("88pm80x-rtc", &pdev->dev, &pm80x_rtc_ops, THIS_MODULE); - ret = PTR_ERR(info->rtc_dev); if (IS_ERR(info->rtc_dev)) { + ret = PTR_ERR(info->rtc_dev); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); goto out_rtc; } -- GitLab From 437ea90cc3afdca5229b41c6b1d38c4842756cb9 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Tue, 31 Jul 2012 16:46:24 -0700 Subject: [PATCH 4976/5711] rtc/rtc-88pm80x: remove unneed devm_kfree devm_kzalloc() doesn't need a matching devm_kfree(), the freeing mechanism will trigger when driver unloads. Signed-off-by: Devendra Naga Cc: Alessandro Zummo Cc: Ashish Jangam Cc: David Dajun Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-88pm80x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 7e050b44b2de..6367984e0565 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -339,7 +339,6 @@ static int __devinit pm80x_rtc_probe(struct platform_device *pdev) out_rtc: pm80x_free_irq(chip, info->irq, info); out: - devm_kfree(&pdev->dev, info); return ret; } @@ -349,7 +348,6 @@ static int __devexit pm80x_rtc_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); rtc_device_unregister(info->rtc_dev); pm80x_free_irq(info->chip, info->irq, info); - devm_kfree(&pdev->dev, info); return 0; } -- GitLab From 392a325c4351339cfbf182bb5a1444df1cf65dbb Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 10 Jul 2012 19:31:51 -0700 Subject: [PATCH 4977/5711] Platform: OLPC: add a stub to drivers/platform/ for the OLPC EC driver The OLPC EC driver has outgrown arch/x86/platform/. It's time to both share common code amongst different architectures, as well as move it out of arch/x86/. The XO-1.75 is ARM-based, and the EC driver shares a lot of code with the x86 code. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 19 +++---------------- arch/x86/platform/olpc/olpc.c | 4 ++-- drivers/platform/Makefile | 1 + drivers/platform/olpc/Makefile | 4 ++++ drivers/platform/olpc/olpc-ec.c | 16 ++++++++++++++++ include/linux/olpc-ec.h | 29 +++++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 drivers/platform/olpc/Makefile create mode 100644 drivers/platform/olpc/olpc-ec.c create mode 100644 include/linux/olpc-ec.h diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 87bdbca72f94..513e9992771d 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -4,6 +4,7 @@ #define _ASM_X86_OLPC_H #include +#include struct olpc_platform_t { int flags; @@ -102,22 +103,8 @@ extern int pci_olpc_init(void); /* EC related functions */ -extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, - unsigned char *outbuf, size_t outlen); - -/* EC commands */ - -#define EC_FIRMWARE_REV 0x08 -#define EC_WRITE_SCI_MASK 0x1b -#define EC_WAKE_UP_WLAN 0x24 -#define EC_WLAN_LEAVE_RESET 0x25 -#define EC_READ_EB_MODE 0x2a -#define EC_SET_SCI_INHIBIT 0x32 -#define EC_SET_SCI_INHIBIT_RELEASE 0x34 -#define EC_WLAN_ENTER_RESET 0x35 -#define EC_WRITE_EXT_SCI_MASK 0x38 -#define EC_SCI_QUERY 0x84 -#define EC_EXT_SCI_QUERY 0x85 +extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, + size_t inlen, unsigned char *outbuf, size_t outlen); /* SCI source values */ diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index a4bee53c2e54..796e199ac77a 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -125,7 +125,7 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired) * . Unfortunately, while * OpenFirmware's source is available, the EC's is not. */ -int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, +int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen, unsigned char *outbuf, size_t outlen) { unsigned long flags; @@ -201,7 +201,7 @@ err: spin_unlock_irqrestore(&ec_lock, flags); return ret; } -EXPORT_SYMBOL_GPL(olpc_ec_cmd); +EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86); void olpc_ec_wakeup_set(u16 value) { diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 782953ae4c03..b17c16ce54ad 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_X86) += x86/ +obj-$(CONFIG_OLPC) += olpc/ diff --git a/drivers/platform/olpc/Makefile b/drivers/platform/olpc/Makefile new file mode 100644 index 000000000000..dc8b26bc7209 --- /dev/null +++ b/drivers/platform/olpc/Makefile @@ -0,0 +1,4 @@ +# +# OLPC XO platform-specific drivers +# +obj-$(CONFIG_OLPC) += olpc-ec.o diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c new file mode 100644 index 000000000000..42026036cd3e --- /dev/null +++ b/drivers/platform/olpc/olpc-ec.c @@ -0,0 +1,16 @@ +/* + * Generic driver for the OLPC Embedded Controller. + * + * Copyright (C) 2011-2012 One Laptop per Child Foundation. + * + * Licensed under the GPL v2 or later. + */ +#include +#include + +int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) +{ + /* Currently a stub; this will be expanded upon later. */ + return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen); +} +EXPORT_SYMBOL_GPL(olpc_ec_cmd); diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h new file mode 100644 index 000000000000..6d4e426d9fdc --- /dev/null +++ b/include/linux/olpc-ec.h @@ -0,0 +1,29 @@ +#ifndef _LINUX_OLPC_EC_H +#define _LINUX_OLPC_EC_H + +/* XO-1 EC commands */ +#define EC_FIRMWARE_REV 0x08 +#define EC_WRITE_SCI_MASK 0x1b +#define EC_WAKE_UP_WLAN 0x24 +#define EC_WLAN_LEAVE_RESET 0x25 +#define EC_READ_EB_MODE 0x2a +#define EC_SET_SCI_INHIBIT 0x32 +#define EC_SET_SCI_INHIBIT_RELEASE 0x34 +#define EC_WLAN_ENTER_RESET 0x35 +#define EC_WRITE_EXT_SCI_MASK 0x38 +#define EC_SCI_QUERY 0x84 +#define EC_EXT_SCI_QUERY 0x85 + +#ifdef CONFIG_OLPC + +extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, + size_t outlen); + +#else + +static inline int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, + size_t outlen) { return -ENODEV; } + +#endif /* CONFIG_OLPC */ + +#endif /* _LINUX_OLPC_EC_H */ -- GitLab From 3bf9428f220911795edde453a95f9509945004e5 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Wed, 11 Jul 2012 01:16:29 -0700 Subject: [PATCH 4978/5711] drivers: OLPC: update various drivers to include olpc-ec.h Switch over to using olpc-ec.h in multiple steps, so as not to break builds. This covers every driver that calls olpc_ec_cmd(). Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 1 - arch/x86/platform/olpc/olpc-xo1-pm.c | 1 + arch/x86/platform/olpc/olpc-xo1-sci.c | 1 + arch/x86/platform/olpc/olpc-xo15-sci.c | 1 + arch/x86/platform/olpc/olpc.c | 1 + drivers/net/wireless/libertas/if_usb.c | 1 + drivers/platform/x86/xo1-rfkill.c | 3 +-- drivers/power/olpc_battery.c | 1 + drivers/staging/olpc_dcon/olpc_dcon.c | 1 + 9 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 513e9992771d..5b28f3e69758 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -4,7 +4,6 @@ #define _ASM_X86_OLPC_H #include -#include struct olpc_platform_t { int flags; diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index 0ce8616c88ae..8054b64ec4ce 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 04b8c73659c5..63d4aa40956e 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 599be499fdf7..2fdca25905ae 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index 796e199ac77a..a3fa180c15c8 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 55a77e41170a..27980778d992 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CONFIG_OLPC #include diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c index b57ad8641480..1da13ed34b04 100644 --- a/drivers/platform/x86/xo1-rfkill.c +++ b/drivers/platform/x86/xo1-rfkill.c @@ -12,8 +12,7 @@ #include #include #include - -#include +#include static bool card_blocked; diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 7385092f9bc8..eaf917dc30d4 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c @@ -17,6 +17,7 @@ #include #include #include +#include #include diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 992275c0d87c..2c4bd746715a 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include -- GitLab From 3d26c20bae9e97c98f7240184427d3a38515d406 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Wed, 11 Jul 2012 17:40:25 -0700 Subject: [PATCH 4979/5711] Platform: OLPC: allow EC cmd to be overridden, and create a workqueue to call it This provides a new API allows different OLPC architectures to override the EC driver. x86 and ARM OLPC machines use completely different EC backends. The olpc_ec_cmd is synchronous, and waits for the workqueue to send the command to the EC. Multiple callers can run olpc_ec_cmd() at once, and they will by serialized and sleep while only one executes on the EC at a time. We don't provide an unregister function, as that doesn't make sense within the context of OLPC machines - there's only ever 1 EC, it's critical to functionality, and it certainly not hotpluggable. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- drivers/platform/olpc/olpc-ec.c | 112 +++++++++++++++++++++++++++++++- include/linux/olpc-ec.h | 6 ++ 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index 42026036cd3e..44e6a4fae79b 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -5,12 +5,120 @@ * * Licensed under the GPL v2 or later. */ +#include +#include +#include +#include #include +#include +#include #include +struct ec_cmd_desc { + u8 cmd; + u8 *inbuf, *outbuf; + size_t inlen, outlen; + + int err; + struct completion finished; + struct list_head node; + + void *priv; +}; + +static void olpc_ec_worker(struct work_struct *w); + +static DECLARE_WORK(ec_worker, olpc_ec_worker); +static LIST_HEAD(ec_cmd_q); +static DEFINE_SPINLOCK(ec_cmd_q_lock); + +static struct olpc_ec_driver *ec_driver; +static void *ec_cb_arg; +static DEFINE_MUTEX(ec_cb_lock); + +void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg) +{ + ec_driver = drv; + ec_cb_arg = arg; +} +EXPORT_SYMBOL_GPL(olpc_ec_driver_register); + +static void olpc_ec_worker(struct work_struct *w) +{ + struct ec_cmd_desc *desc = NULL; + unsigned long flags; + + /* Grab the first pending command from the queue */ + spin_lock_irqsave(&ec_cmd_q_lock, flags); + if (!list_empty(&ec_cmd_q)) { + desc = list_first_entry(&ec_cmd_q, struct ec_cmd_desc, node); + list_del(&desc->node); + } + spin_unlock_irqrestore(&ec_cmd_q_lock, flags); + + /* Do we actually have anything to do? */ + if (!desc) + return; + + /* Protect the EC hw with a mutex; only run one cmd at a time */ + mutex_lock(&ec_cb_lock); + desc->err = ec_driver->ec_cmd(desc->cmd, desc->inbuf, desc->inlen, + desc->outbuf, desc->outlen, ec_cb_arg); + mutex_unlock(&ec_cb_lock); + + /* Finished, wake up olpc_ec_cmd() */ + complete(&desc->finished); + + /* Run the worker thread again in case there are more cmds pending */ + schedule_work(&ec_worker); +} + +/* + * Throw a cmd descripter onto the list. We now have SMP OLPC machines, so + * locking is pretty critical. + */ +static void queue_ec_descriptor(struct ec_cmd_desc *desc) +{ + unsigned long flags; + + INIT_LIST_HEAD(&desc->node); + + spin_lock_irqsave(&ec_cmd_q_lock, flags); + list_add_tail(&desc->node, &ec_cmd_q); + spin_unlock_irqrestore(&ec_cmd_q_lock, flags); + + schedule_work(&ec_worker); +} + int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) { - /* Currently a stub; this will be expanded upon later. */ - return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen); + struct ec_cmd_desc desc; + + /* XXX: this will be removed in later patches */ + /* Are we using old-style callers? */ + if (!ec_driver || !ec_driver->ec_cmd) + return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen); + + /* Ensure a driver and ec hook have been registered */ + if (WARN_ON(!ec_driver || !ec_driver->ec_cmd)) + return -ENODEV; + + might_sleep(); + + desc.cmd = cmd; + desc.inbuf = inbuf; + desc.outbuf = outbuf; + desc.inlen = inlen; + desc.outlen = outlen; + desc.err = 0; + init_completion(&desc.finished); + + queue_ec_descriptor(&desc); + + /* Timeouts must be handled in the platform-specific EC hook */ + wait_for_completion(&desc.finished); + + /* The worker thread dequeues the cmd; no need to do anything here */ + return desc.err; } EXPORT_SYMBOL_GPL(olpc_ec_cmd); diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h index 6d4e426d9fdc..231e96f5dfe2 100644 --- a/include/linux/olpc-ec.h +++ b/include/linux/olpc-ec.h @@ -14,8 +14,14 @@ #define EC_SCI_QUERY 0x84 #define EC_EXT_SCI_QUERY 0x85 +struct olpc_ec_driver { + int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *); +}; + #ifdef CONFIG_OLPC +extern void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg); + extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen); -- GitLab From ac2504151f5af27bbf0c0362b7da5951e05dfc43 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Fri, 13 Jul 2012 05:57:17 -0700 Subject: [PATCH 4980/5711] Platform: OLPC: turn EC driver into a platform_driver The 1.75-based OLPC EC driver already does this; let's do it for all EC drivers. This gives us nice suspend/resume hooks, amongst other things. We want to run the EC's suspend hooks later than other drivers (which may be setting wakeup masks or be running EC commands). We also want to run the EC's resume hooks earlier than other drivers (which may want to run EC commands). Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- drivers/platform/olpc/olpc-ec.c | 48 +++++++++++++++++++++++++++++++++ include/linux/olpc-ec.h | 6 +++++ 2 files changed, 54 insertions(+) diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index 44e6a4fae79b..d00523c65191 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -122,3 +123,50 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) return desc.err; } EXPORT_SYMBOL_GPL(olpc_ec_cmd); + +static int olpc_ec_probe(struct platform_device *pdev) +{ + int err; + + if (!ec_driver) + return -ENODEV; + + err = ec_driver->probe ? ec_driver->probe(pdev) : 0; + + return err; +} + +static int olpc_ec_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return ec_driver->suspend ? ec_driver->suspend(pdev) : 0; +} + +static int olpc_ec_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return ec_driver->resume ? ec_driver->resume(pdev) : 0; +} + +static const struct dev_pm_ops olpc_ec_pm_ops = { + .suspend_late = olpc_ec_suspend, + .resume_early = olpc_ec_resume, +}; + +static struct platform_driver olpc_ec_plat_driver = { + .probe = olpc_ec_probe, + .driver = { + .name = "olpc-ec", + .pm = &olpc_ec_pm_ops, + }, +}; + +static int __init olpc_ec_init_module(void) +{ + return platform_driver_register(&olpc_ec_plat_driver); +} + +module_init(olpc_ec_init_module); + +MODULE_AUTHOR("Andres Salomon "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h index 231e96f5dfe2..5bb6e760aa61 100644 --- a/include/linux/olpc-ec.h +++ b/include/linux/olpc-ec.h @@ -14,7 +14,13 @@ #define EC_SCI_QUERY 0x84 #define EC_EXT_SCI_QUERY 0x85 +struct platform_device; + struct olpc_ec_driver { + int (*probe)(struct platform_device *); + int (*suspend)(struct platform_device *); + int (*resume)(struct platform_device *); + int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *); }; -- GitLab From d278b7a2f90f91f908b19b50cfa59e10632b5afc Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Fri, 13 Jul 2012 15:54:25 -0700 Subject: [PATCH 4981/5711] Platform: OLPC: add a suspended flag to the EC driver A problem we've noticed on XO-1.75 is when we suspend in the middle of an EC command. Don't allow that. In the process, create a private object for the generic EC driver to use; we have a framework for passing around a struct, use that rather than a proliferation of global variables. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- drivers/platform/olpc/olpc-ec.c | 46 ++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index d00523c65191..cfba41fb04de 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,21 @@ struct ec_cmd_desc { void *priv; }; +struct olpc_ec_priv { + struct olpc_ec_driver *drv; + + /* + * Running an EC command while suspending means we don't always finish + * the command before the machine suspends. This means that the EC + * is expecting the command protocol to finish, but we after a period + * of time (while the OS is asleep) the EC times out and restarts its + * idle loop. Meanwhile, the OS wakes up, thinks it's still in the + * middle of the command protocol, starts throwing random things at + * the EC... and everyone's uphappy. + */ + bool suspended; +}; + static void olpc_ec_worker(struct work_struct *w); static DECLARE_WORK(ec_worker, olpc_ec_worker); @@ -34,6 +50,7 @@ static LIST_HEAD(ec_cmd_q); static DEFINE_SPINLOCK(ec_cmd_q_lock); static struct olpc_ec_driver *ec_driver; +static struct olpc_ec_priv *ec_priv; static void *ec_cb_arg; static DEFINE_MUTEX(ec_cb_lock); @@ -93,6 +110,7 @@ static void queue_ec_descriptor(struct ec_cmd_desc *desc) int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) { + struct olpc_ec_priv *ec = ec_priv; struct ec_cmd_desc desc; /* XXX: this will be removed in later patches */ @@ -104,6 +122,13 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) if (WARN_ON(!ec_driver || !ec_driver->ec_cmd)) return -ENODEV; + if (!ec) + return -ENOMEM; + + /* Suspending in the middle of a command hoses things really badly */ + if (WARN_ON(ec->suspended)) + return -EBUSY; + might_sleep(); desc.cmd = cmd; @@ -126,11 +151,19 @@ EXPORT_SYMBOL_GPL(olpc_ec_cmd); static int olpc_ec_probe(struct platform_device *pdev) { + struct olpc_ec_priv *ec; int err; if (!ec_driver) return -ENODEV; + ec = kzalloc(sizeof(*ec), GFP_KERNEL); + if (!ec) + return -ENOMEM; + ec->drv = ec_driver; + ec_priv = ec; + platform_set_drvdata(pdev, ec); + err = ec_driver->probe ? ec_driver->probe(pdev) : 0; return err; @@ -139,12 +172,23 @@ static int olpc_ec_probe(struct platform_device *pdev) static int olpc_ec_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - return ec_driver->suspend ? ec_driver->suspend(pdev) : 0; + struct olpc_ec_priv *ec = platform_get_drvdata(pdev); + int err = 0; + + if (ec_driver->suspend) + err = ec_driver->suspend(pdev); + if (!err) + ec->suspended = true; + + return err; } static int olpc_ec_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + struct olpc_ec_priv *ec = platform_get_drvdata(pdev); + + ec->suspended = false; return ec_driver->resume ? ec_driver->resume(pdev) : 0; } -- GitLab From 85f90cf6ca569b19cee212844b543a7355b77163 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 12 Jul 2012 17:57:28 -0700 Subject: [PATCH 4982/5711] x86: OLPC: switch over to using new EC driver on x86 This uses the new EC driver framework in drivers/platform/olpc. The XO-1 and XO-1.5-specific code is still in arch/x86, but the generic stuff (including a new workqueue; no more running EC commands with IRQs disabled!) can be shared with other architectures. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 5 ---- arch/x86/platform/olpc/olpc.c | 53 +++++++++++++++++---------------- drivers/platform/olpc/olpc-ec.c | 5 ---- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 5b28f3e69758..72f9adf6eca4 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -100,11 +100,6 @@ extern void olpc_xo1_pm_wakeup_clear(u16 value); extern int pci_olpc_init(void); -/* EC related functions */ - -extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, - size_t inlen, unsigned char *outbuf, size_t outlen); - /* SCI source values */ #define EC_SCI_SRC_EMPTY 0x00 diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index a3fa180c15c8..45900968fb89 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -32,8 +31,6 @@ struct olpc_platform_t olpc_platform_info; EXPORT_SYMBOL_GPL(olpc_platform_info); -static DEFINE_SPINLOCK(ec_lock); - /* debugfs interface to EC commands */ #define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */ #define EC_MAX_CMD_REPLY (8) @@ -126,16 +123,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired) * . Unfortunately, while * OpenFirmware's source is available, the EC's is not. */ -int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen, - unsigned char *outbuf, size_t outlen) +static int olpc_xo1_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, + size_t outlen, void *arg) { - unsigned long flags; int ret = -EIO; int i; int restarts = 0; - spin_lock_irqsave(&ec_lock, flags); - /* Clear OBF */ for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++) inb(0x68); @@ -199,10 +193,8 @@ restart: ret = 0; err: - spin_unlock_irqrestore(&ec_lock, flags); return ret; } -EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86); void olpc_ec_wakeup_set(u16 value) { @@ -366,7 +358,7 @@ static void setup_debugfs(void) &ec_debugfs_genops); } -static int olpc_ec_suspend(void) +static int olpc_ec_suspend(struct platform_device *pdev) { return olpc_ec_mask_write(ec_wakeup_mask); } @@ -425,8 +417,28 @@ static int __init add_xo1_platform_devices(void) return 0; } -static struct syscore_ops olpc_syscore_ops = { +static int olpc_xo1_ec_probe(struct platform_device *pdev) +{ + /* get the EC revision */ + olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, + (unsigned char *) &olpc_platform_info.ecver, 1); + + /* EC version 0x5f adds support for wide SCI mask */ + if (olpc_platform_info.ecver >= 0x5f) + olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; + + pr_info("OLPC board revision %s%X (EC=%x)\n", + ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", + olpc_platform_info.boardrev >> 4, + olpc_platform_info.ecver); + + return 0; +} + +static struct olpc_ec_driver ec_xo1_driver = { .suspend = olpc_ec_suspend, + .probe = olpc_xo1_ec_probe, + .ec_cmd = olpc_xo1_ec_cmd, }; static int __init olpc_init(void) @@ -436,16 +448,14 @@ static int __init olpc_init(void) if (!olpc_ofw_present() || !platform_detect()) return 0; - spin_lock_init(&ec_lock); + /* register the XO-1 and 1.5-specific EC handler */ + olpc_ec_driver_register(&ec_xo1_driver, NULL); + platform_device_register_simple("olpc-ec", -1, NULL, 0); /* assume B1 and above models always have a DCON */ if (olpc_board_at_least(olpc_board(0xb1))) olpc_platform_info.flags |= OLPC_F_DCON; - /* get the EC revision */ - olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, - (unsigned char *) &olpc_platform_info.ecver, 1); - #ifdef CONFIG_PCI_OLPC /* If the VSA exists let it emulate PCI, if not emulate in kernel. * XO-1 only. */ @@ -453,14 +463,6 @@ static int __init olpc_init(void) !cs5535_has_vsa2()) x86_init.pci.arch_init = pci_olpc_init; #endif - /* EC version 0x5f adds support for wide SCI mask */ - if (olpc_platform_info.ecver >= 0x5f) - olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; - - printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", - ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", - olpc_platform_info.boardrev >> 4, - olpc_platform_info.ecver); if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */ r = add_xo1_platform_devices(); @@ -468,7 +470,6 @@ static int __init olpc_init(void) return r; } - register_syscore_ops(&olpc_syscore_ops); setup_debugfs(); return 0; diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index cfba41fb04de..a3d32c2eeb1a 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -113,11 +113,6 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) struct olpc_ec_priv *ec = ec_priv; struct ec_cmd_desc desc; - /* XXX: this will be removed in later patches */ - /* Are we using old-style callers? */ - if (!ec_driver || !ec_driver->ec_cmd) - return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen); - /* Ensure a driver and ec hook have been registered */ if (WARN_ON(!ec_driver || !ec_driver->ec_cmd)) return -ENODEV; -- GitLab From 6cca83d498bda0999302079bd59786370590c5c2 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 12 Jul 2012 20:45:14 -0700 Subject: [PATCH 4983/5711] Platform: OLPC: move debugfs support from x86 EC driver There's nothing about the debugfs interface for the EC driver that is architecture-specific, so move it into the arch-independent driver. The code is mostly unchanged with the exception of renamed variables, coding style changes, and API updates. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/platform/olpc/olpc.c | 97 -------------------------- drivers/platform/olpc/olpc-ec.c | 117 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 97 deletions(-) diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index 45900968fb89..ed41b437b37b 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -31,15 +30,6 @@ struct olpc_platform_t olpc_platform_info; EXPORT_SYMBOL_GPL(olpc_platform_info); -/* debugfs interface to EC commands */ -#define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */ -#define EC_MAX_CMD_REPLY (8) - -static struct dentry *ec_debugfs_dir; -static DEFINE_MUTEX(ec_debugfs_cmd_lock); -static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY]; -static unsigned int ec_debugfs_resp_bytes; - /* EC event mask to be applied during suspend (defining wakeup sources). */ static u16 ec_wakeup_mask; @@ -273,91 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value) } EXPORT_SYMBOL_GPL(olpc_ec_sci_query); -static ssize_t ec_debugfs_cmd_write(struct file *file, const char __user *buf, - size_t size, loff_t *ppos) -{ - int i, m; - unsigned char ec_cmd[EC_MAX_CMD_ARGS]; - unsigned int ec_cmd_int[EC_MAX_CMD_ARGS]; - char cmdbuf[64]; - int ec_cmd_bytes; - - mutex_lock(&ec_debugfs_cmd_lock); - - size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size); - - m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0], - &ec_debugfs_resp_bytes, - &ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3], - &ec_cmd_int[4], &ec_cmd_int[5]); - if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) { - /* reset to prevent overflow on read */ - ec_debugfs_resp_bytes = 0; - - printk(KERN_DEBUG "olpc-ec: bad ec cmd: " - "cmd:response-count [arg1 [arg2 ...]]\n"); - size = -EINVAL; - goto out; - } - - /* convert scanf'd ints to char */ - ec_cmd_bytes = m - 2; - for (i = 0; i <= ec_cmd_bytes; i++) - ec_cmd[i] = ec_cmd_int[i]; - - printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args " - "%02x %02x %02x %02x %02x, want %d returns\n", - ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3], - ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes); - - olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1], - ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes); - - printk(KERN_DEBUG "olpc-ec: response " - "%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n", - ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2], - ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5], - ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes); - -out: - mutex_unlock(&ec_debugfs_cmd_lock); - return size; -} - -static ssize_t ec_debugfs_cmd_read(struct file *file, char __user *buf, - size_t size, loff_t *ppos) -{ - unsigned int i, r; - char *rp; - char respbuf[64]; - - mutex_lock(&ec_debugfs_cmd_lock); - rp = respbuf; - rp += sprintf(rp, "%02x", ec_debugfs_resp[0]); - for (i = 1; i < ec_debugfs_resp_bytes; i++) - rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]); - mutex_unlock(&ec_debugfs_cmd_lock); - rp += sprintf(rp, "\n"); - - r = rp - respbuf; - return simple_read_from_buffer(buf, size, ppos, respbuf, r); -} - -static const struct file_operations ec_debugfs_genops = { - .write = ec_debugfs_cmd_write, - .read = ec_debugfs_cmd_read, -}; - -static void setup_debugfs(void) -{ - ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0); - if (ec_debugfs_dir == ERR_PTR(-ENODEV)) - return; - - debugfs_create_file("cmd", 0600, ec_debugfs_dir, NULL, - &ec_debugfs_genops); -} - static int olpc_ec_suspend(struct platform_device *pdev) { return olpc_ec_mask_write(ec_wakeup_mask); @@ -470,8 +375,6 @@ static int __init olpc_init(void) return r; } - setup_debugfs(); - return 0; } diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index a3d32c2eeb1a..1a15a79fff05 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -6,6 +6,7 @@ * Licensed under the GPL v2 or later. */ #include +#include #include #include #include @@ -31,6 +32,8 @@ struct ec_cmd_desc { struct olpc_ec_priv { struct olpc_ec_driver *drv; + struct dentry *dbgfs_dir; + /* * Running an EC command while suspending means we don't always finish * the command before the machine suspends. This means that the EC @@ -144,6 +147,114 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) } EXPORT_SYMBOL_GPL(olpc_ec_cmd); +#ifdef CONFIG_DEBUG_FS + +/* + * debugfs support for "generic commands", to allow sending + * arbitrary EC commands from userspace. + */ + +#define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */ +#define EC_MAX_CMD_REPLY (8) + +static DEFINE_MUTEX(ec_dbgfs_lock); +static unsigned char ec_dbgfs_resp[EC_MAX_CMD_REPLY]; +static unsigned int ec_dbgfs_resp_bytes; + +static ssize_t ec_dbgfs_cmd_write(struct file *file, const char __user *buf, + size_t size, loff_t *ppos) +{ + int i, m; + unsigned char ec_cmd[EC_MAX_CMD_ARGS]; + unsigned int ec_cmd_int[EC_MAX_CMD_ARGS]; + char cmdbuf[64]; + int ec_cmd_bytes; + + mutex_lock(&ec_dbgfs_lock); + + size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size); + + m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0], + &ec_dbgfs_resp_bytes, &ec_cmd_int[1], &ec_cmd_int[2], + &ec_cmd_int[3], &ec_cmd_int[4], &ec_cmd_int[5]); + if (m < 2 || ec_dbgfs_resp_bytes > EC_MAX_CMD_REPLY) { + /* reset to prevent overflow on read */ + ec_dbgfs_resp_bytes = 0; + + pr_debug("olpc-ec: bad ec cmd: cmd:response-count [arg1 [arg2 ...]]\n"); + size = -EINVAL; + goto out; + } + + /* convert scanf'd ints to char */ + ec_cmd_bytes = m - 2; + for (i = 0; i <= ec_cmd_bytes; i++) + ec_cmd[i] = ec_cmd_int[i]; + + pr_debug("olpc-ec: debugfs cmd 0x%02x with %d args %02x %02x %02x %02x %02x, want %d returns\n", + ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], + ec_cmd[3], ec_cmd[4], ec_cmd[5], ec_dbgfs_resp_bytes); + + olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1], + ec_cmd_bytes, ec_dbgfs_resp, ec_dbgfs_resp_bytes); + + pr_debug("olpc-ec: response %02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n", + ec_dbgfs_resp[0], ec_dbgfs_resp[1], ec_dbgfs_resp[2], + ec_dbgfs_resp[3], ec_dbgfs_resp[4], ec_dbgfs_resp[5], + ec_dbgfs_resp[6], ec_dbgfs_resp[7], + ec_dbgfs_resp_bytes); + +out: + mutex_unlock(&ec_dbgfs_lock); + return size; +} + +static ssize_t ec_dbgfs_cmd_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + unsigned int i, r; + char *rp; + char respbuf[64]; + + mutex_lock(&ec_dbgfs_lock); + rp = respbuf; + rp += sprintf(rp, "%02x", ec_dbgfs_resp[0]); + for (i = 1; i < ec_dbgfs_resp_bytes; i++) + rp += sprintf(rp, ", %02x", ec_dbgfs_resp[i]); + mutex_unlock(&ec_dbgfs_lock); + rp += sprintf(rp, "\n"); + + r = rp - respbuf; + return simple_read_from_buffer(buf, size, ppos, respbuf, r); +} + +static const struct file_operations ec_dbgfs_ops = { + .write = ec_dbgfs_cmd_write, + .read = ec_dbgfs_cmd_read, +}; + +static struct dentry *olpc_ec_setup_debugfs(void) +{ + struct dentry *dbgfs_dir; + + dbgfs_dir = debugfs_create_dir("olpc-ec", NULL); + if (IS_ERR_OR_NULL(dbgfs_dir)) + return NULL; + + debugfs_create_file("cmd", 0600, dbgfs_dir, NULL, &ec_dbgfs_ops); + + return dbgfs_dir; +} + +#else + +static struct dentry *olpc_ec_setup_debugfs(void) +{ + return NULL; +} + +#endif /* CONFIG_DEBUG_FS */ + static int olpc_ec_probe(struct platform_device *pdev) { struct olpc_ec_priv *ec; @@ -160,6 +271,12 @@ static int olpc_ec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ec); err = ec_driver->probe ? ec_driver->probe(pdev) : 0; + if (err) { + ec_priv = NULL; + kfree(ec); + } else { + ec->dbgfs_dir = olpc_ec_setup_debugfs(); + } return err; } -- GitLab From 99ecb01cdf0378783b317b8f839ac9cc5e128aa5 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Fri, 13 Jul 2012 17:10:45 -0700 Subject: [PATCH 4984/5711] Platform: OLPC: move global variables into priv struct Populate olpc_ec_priv with variables that were previously global. This makes things a tad bit clearer, IMO. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- drivers/platform/olpc/olpc-ec.c | 48 +++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c index 1a15a79fff05..0f9f8596b300 100644 --- a/drivers/platform/olpc/olpc-ec.c +++ b/drivers/platform/olpc/olpc-ec.c @@ -31,6 +31,12 @@ struct ec_cmd_desc { struct olpc_ec_priv { struct olpc_ec_driver *drv; + struct work_struct worker; + struct mutex cmd_lock; + + /* Pending EC commands */ + struct list_head cmd_q; + spinlock_t cmd_q_lock; struct dentry *dbgfs_dir; @@ -46,16 +52,9 @@ struct olpc_ec_priv { bool suspended; }; -static void olpc_ec_worker(struct work_struct *w); - -static DECLARE_WORK(ec_worker, olpc_ec_worker); -static LIST_HEAD(ec_cmd_q); -static DEFINE_SPINLOCK(ec_cmd_q_lock); - static struct olpc_ec_driver *ec_driver; static struct olpc_ec_priv *ec_priv; static void *ec_cb_arg; -static DEFINE_MUTEX(ec_cb_lock); void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg) { @@ -66,49 +65,51 @@ EXPORT_SYMBOL_GPL(olpc_ec_driver_register); static void olpc_ec_worker(struct work_struct *w) { + struct olpc_ec_priv *ec = container_of(w, struct olpc_ec_priv, worker); struct ec_cmd_desc *desc = NULL; unsigned long flags; /* Grab the first pending command from the queue */ - spin_lock_irqsave(&ec_cmd_q_lock, flags); - if (!list_empty(&ec_cmd_q)) { - desc = list_first_entry(&ec_cmd_q, struct ec_cmd_desc, node); + spin_lock_irqsave(&ec->cmd_q_lock, flags); + if (!list_empty(&ec->cmd_q)) { + desc = list_first_entry(&ec->cmd_q, struct ec_cmd_desc, node); list_del(&desc->node); } - spin_unlock_irqrestore(&ec_cmd_q_lock, flags); + spin_unlock_irqrestore(&ec->cmd_q_lock, flags); /* Do we actually have anything to do? */ if (!desc) return; /* Protect the EC hw with a mutex; only run one cmd at a time */ - mutex_lock(&ec_cb_lock); + mutex_lock(&ec->cmd_lock); desc->err = ec_driver->ec_cmd(desc->cmd, desc->inbuf, desc->inlen, desc->outbuf, desc->outlen, ec_cb_arg); - mutex_unlock(&ec_cb_lock); + mutex_unlock(&ec->cmd_lock); /* Finished, wake up olpc_ec_cmd() */ complete(&desc->finished); /* Run the worker thread again in case there are more cmds pending */ - schedule_work(&ec_worker); + schedule_work(&ec->worker); } /* * Throw a cmd descripter onto the list. We now have SMP OLPC machines, so * locking is pretty critical. */ -static void queue_ec_descriptor(struct ec_cmd_desc *desc) +static void queue_ec_descriptor(struct ec_cmd_desc *desc, + struct olpc_ec_priv *ec) { unsigned long flags; INIT_LIST_HEAD(&desc->node); - spin_lock_irqsave(&ec_cmd_q_lock, flags); - list_add_tail(&desc->node, &ec_cmd_q); - spin_unlock_irqrestore(&ec_cmd_q_lock, flags); + spin_lock_irqsave(&ec->cmd_q_lock, flags); + list_add_tail(&desc->node, &ec->cmd_q); + spin_unlock_irqrestore(&ec->cmd_q_lock, flags); - schedule_work(&ec_worker); + schedule_work(&ec->worker); } int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) @@ -137,7 +138,7 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) desc.err = 0; init_completion(&desc.finished); - queue_ec_descriptor(&desc); + queue_ec_descriptor(&desc, ec); /* Timeouts must be handled in the platform-specific EC hook */ wait_for_completion(&desc.finished); @@ -266,7 +267,14 @@ static int olpc_ec_probe(struct platform_device *pdev) ec = kzalloc(sizeof(*ec), GFP_KERNEL); if (!ec) return -ENOMEM; + ec->drv = ec_driver; + INIT_WORK(&ec->worker, olpc_ec_worker); + mutex_init(&ec->cmd_lock); + + INIT_LIST_HEAD(&ec->cmd_q); + spin_lock_init(&ec->cmd_q_lock); + ec_priv = ec; platform_set_drvdata(pdev, ec); -- GitLab From 1fcfd08bd0704e1888bd73153e8d2ca3640e22f2 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 17 Jul 2012 01:26:10 -0700 Subject: [PATCH 4985/5711] x86: OLPC: move s/r-related EC cmds to EC driver The new EC driver calls platform-specific suspend and resume hooks; run XO-1-specific EC commands from there, rather than deep in s/r code. If we attempt to run EC commands after the new EC driver has suspended, it is refused by the ec->suspended checks. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/platform/olpc/olpc-xo1-pm.c | 15 ---------- arch/x86/platform/olpc/olpc.c | 43 +++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index 8054b64ec4ce..d75582d1aa55 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -52,16 +52,11 @@ EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear); static int xo1_power_state_enter(suspend_state_t pm_state) { unsigned long saved_sci_mask; - int r; /* Only STR is supported */ if (pm_state != PM_SUSPEND_MEM) return -EINVAL; - r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0); - if (r) - return r; - /* * Save SCI mask (this gets lost since PM1_EN is used as a mask for * wakeup events, which is not necessarily the same event set) @@ -77,16 +72,6 @@ static int xo1_power_state_enter(suspend_state_t pm_state) /* Restore SCI mask (using dword access to CS5536_PM1_EN) */ outl(saved_sci_mask, acpi_base + CS5536_PM1_STS); - /* Tell the EC to stop inhibiting SCIs */ - olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0); - - /* - * Tell the wireless module to restart USB communication. - * Must be done twice. - */ - olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); - olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); - return 0; } diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index ed41b437b37b..27376081ddec 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -263,11 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value) } EXPORT_SYMBOL_GPL(olpc_ec_sci_query); -static int olpc_ec_suspend(struct platform_device *pdev) -{ - return olpc_ec_mask_write(ec_wakeup_mask); -} - static bool __init check_ofw_architecture(struct device_node *root) { const char *olpc_arch; @@ -339,9 +334,40 @@ static int olpc_xo1_ec_probe(struct platform_device *pdev) return 0; } +static int olpc_xo1_ec_suspend(struct platform_device *pdev) +{ + olpc_ec_mask_write(ec_wakeup_mask); + + /* + * Squelch SCIs while suspended. This is a fix for + * . + */ + return olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0); +} + +static int olpc_xo1_ec_resume(struct platform_device *pdev) +{ + /* Tell the EC to stop inhibiting SCIs */ + olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0); + + /* + * Tell the wireless module to restart USB communication. + * Must be done twice. + */ + olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); + olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); + + return 0; +} static struct olpc_ec_driver ec_xo1_driver = { - .suspend = olpc_ec_suspend, + .probe = olpc_xo1_ec_probe, + .suspend = olpc_xo1_ec_suspend, + .resume = olpc_xo1_ec_resume, + .ec_cmd = olpc_xo1_ec_cmd, +}; + +static struct olpc_ec_driver ec_xo1_5_driver = { .probe = olpc_xo1_ec_probe, .ec_cmd = olpc_xo1_ec_cmd, }; @@ -354,7 +380,10 @@ static int __init olpc_init(void) return 0; /* register the XO-1 and 1.5-specific EC handler */ - olpc_ec_driver_register(&ec_xo1_driver, NULL); + if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */ + olpc_ec_driver_register(&ec_xo1_driver, NULL); + else + olpc_ec_driver_register(&ec_xo1_5_driver, NULL); platform_device_register_simple("olpc-ec", -1, NULL, 0); /* assume B1 and above models always have a DCON */ -- GitLab From 4f46f8ac80416b0e8fd3aba6a0d842205fb29140 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 30 Jul 2012 21:28:27 +0200 Subject: [PATCH 4986/5711] dmaengine: shdma: restore partial transfer calculation The recent shdma driver split has mistakenly removed support for partial DMA transfer size calculation on forced termination. This patch restores it. Signed-off-by: Guennadi Liakhovetski Acked-by: Vinod Koul Signed-off-by: Paul Mundt --- drivers/dma/sh/shdma-base.c | 9 +++++++++ drivers/dma/sh/shdma.c | 12 ++++++++++++ include/linux/shdma-base.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 27f5c781fd73..f4cd946d259d 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c @@ -483,6 +483,7 @@ static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan, new->mark = DESC_PREPARED; new->async_tx.flags = flags; new->direction = direction; + new->partial = 0; *len -= copy_size; if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) @@ -644,6 +645,14 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, case DMA_TERMINATE_ALL: spin_lock_irqsave(&schan->chan_lock, flags); ops->halt_channel(schan); + + if (ops->get_partial && !list_empty(&schan->ld_queue)) { + /* Record partial transfer */ + struct shdma_desc *desc = list_first_entry(&schan->ld_queue, + struct shdma_desc, node); + desc->partial = ops->get_partial(schan, desc); + } + spin_unlock_irqrestore(&schan->chan_lock, flags); shdma_chan_ld_cleanup(schan, true); diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index 027c9be97654..f41bcc5267fd 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c @@ -381,6 +381,17 @@ static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq) return true; } +static size_t sh_dmae_get_partial(struct shdma_chan *schan, + struct shdma_desc *sdesc) +{ + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); + struct sh_dmae_desc *sh_desc = container_of(sdesc, + struct sh_dmae_desc, shdma_desc); + return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) << + sh_chan->xmit_shift; +} + /* Called from error IRQ or NMI */ static bool sh_dmae_reset(struct sh_dmae_device *shdev) { @@ -632,6 +643,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = { .start_xfer = sh_dmae_start_xfer, .embedded_desc = sh_dmae_embedded_desc, .chan_irq = sh_dmae_chan_irq, + .get_partial = sh_dmae_get_partial, }; static int __devinit sh_dmae_probe(struct platform_device *pdev) diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h index 93f9821554b6..a3728bf66f0e 100644 --- a/include/linux/shdma-base.h +++ b/include/linux/shdma-base.h @@ -50,6 +50,7 @@ struct shdma_desc { struct list_head node; struct dma_async_tx_descriptor async_tx; enum dma_transfer_direction direction; + size_t partial; dma_cookie_t cookie; int chunks; int mark; @@ -98,6 +99,7 @@ struct shdma_ops { void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); struct shdma_desc *(*embedded_desc)(void *, int); bool (*chan_irq)(struct shdma_chan *, int); + size_t (*get_partial)(struct shdma_chan *, struct shdma_desc *); }; struct shdma_dev { -- GitLab From 4dc4c51675c137c30838425ecc8d471ff5eb138b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 30 Jul 2012 21:28:47 +0200 Subject: [PATCH 4987/5711] serial: sh-sci: fix compilation breakage, when DMA is enabled A recent commit: commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7 Author: Guennadi Liakhovetski serial: sh-sci: prepare for conversion to the shdma base library is not sufficient to update the sh-sci driver to the new shdma driver layout. This caused compilation breakage, when CONFIG_SERIAL_SH_SCI_DMA is enabled. This patch trivially fixes the problem by updating the DMA descriptor manipulation code. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d4d8c9453cd8..9be296cf7295 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1410,8 +1411,8 @@ static void work_fn_rx(struct work_struct *work) /* Handle incomplete DMA receive */ struct tty_struct *tty = port->state->port.tty; struct dma_chan *chan = s->chan_rx; - struct sh_desc *sh_desc = container_of(desc, struct sh_desc, - async_tx); + struct shdma_desc *sh_desc = container_of(desc, + struct shdma_desc, async_tx); unsigned long flags; int count; -- GitLab From 1e32dfe323d156d5d7b25b9feffe015d19713db2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 1 Aug 2012 16:27:38 +0900 Subject: [PATCH 4988/5711] sh: pfc: Fix up init ordering mess. Commit ca5481c68e9fbcea62bb3c78ae6cccf99ca8fb73 ("sh: pfc: Rudimentary pinctrl-backed GPIO support.") introduced a regression for platforms that were doing early GPIO API calls (from arch_initcall() or earlier), leading to a situation where our two-stage registration logic would trip itself up and we'd -ENODEV out of the pinctrl registration path, resulting in endless -EPROBE_DEFER errors. Further lack of checking any sort of errors from gpio_request() resulted in boot time warnings, tripping on the FLAG_REQUESTED test-and-set in gpio_ensure_requested(). As it turns out there's no particular need to bother with the two-stage registration, as the platform bus is already available at the point that we have to start caring. As such, it's easiest to simply fold these together in to a single init path, the ordering of which is ensured through the platform's mux registration, as usual. Reported-by: Rafael J. Wysocki Reported-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/sh/pfc/pinctrl.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c index 814b29255aef..2804eaae804e 100644 --- a/drivers/sh/pfc/pinctrl.c +++ b/drivers/sh/pfc/pinctrl.c @@ -325,20 +325,6 @@ static struct pinctrl_desc sh_pfc_pinctrl_desc = { .confops = &sh_pfc_pinconf_ops, }; -int sh_pfc_register_pinctrl(struct sh_pfc *pfc) -{ - sh_pfc_pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL); - if (unlikely(!sh_pfc_pmx)) - return -ENOMEM; - - spin_lock_init(&sh_pfc_pmx->lock); - - sh_pfc_pmx->pfc = pfc; - - return 0; -} -EXPORT_SYMBOL_GPL(sh_pfc_register_pinctrl); - static inline void __devinit sh_pfc_map_one_gpio(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx, struct pinmux_gpio *gpio, @@ -505,7 +491,7 @@ static struct platform_device sh_pfc_pinctrl_device = { .id = -1, }; -static int __init sh_pfc_pinctrl_init(void) +static int sh_pfc_pinctrl_init(void) { int rc; @@ -519,10 +505,22 @@ static int __init sh_pfc_pinctrl_init(void) return rc; } +int sh_pfc_register_pinctrl(struct sh_pfc *pfc) +{ + sh_pfc_pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL); + if (unlikely(!sh_pfc_pmx)) + return -ENOMEM; + + spin_lock_init(&sh_pfc_pmx->lock); + + sh_pfc_pmx->pfc = pfc; + + return sh_pfc_pinctrl_init(); +} +EXPORT_SYMBOL_GPL(sh_pfc_register_pinctrl); + static void __exit sh_pfc_pinctrl_exit(void) { platform_driver_unregister(&sh_pfc_pinctrl_driver); } - -subsys_initcall(sh_pfc_pinctrl_init); module_exit(sh_pfc_pinctrl_exit); -- GitLab From 1d6a21b0a672fb29b01ccf397d478e0541e17716 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 1 Aug 2012 17:13:46 +0900 Subject: [PATCH 4989/5711] sh: intc: initial irqdomain support. Trivial support for irq domains, using either a linear map or radix tree depending on the vector layout. Signed-off-by: Paul Mundt --- drivers/sh/intc/Kconfig | 4 +++ drivers/sh/intc/Makefile | 2 +- drivers/sh/intc/core.c | 11 +++--- drivers/sh/intc/internals.h | 5 +++ drivers/sh/intc/irqdomain.c | 68 +++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 drivers/sh/intc/irqdomain.c diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig index c88cbccc62b0..a305731742a9 100644 --- a/drivers/sh/intc/Kconfig +++ b/drivers/sh/intc/Kconfig @@ -1,3 +1,7 @@ +config SH_INTC + def_bool y + select IRQ_DOMAIN + comment "Interrupt controller options" config INTC_USERIMASK diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile index 44f006d09471..54ec2a0643df 100644 --- a/drivers/sh/intc/Makefile +++ b/drivers/sh/intc/Makefile @@ -1,4 +1,4 @@ -obj-y := access.o chip.o core.o handle.o virq.o +obj-y := access.o chip.o core.o handle.o irqdomain.o virq.o obj-$(CONFIG_INTC_BALANCING) += balancing.o obj-$(CONFIG_INTC_USERIMASK) += userimask.o diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 7e562ccb6997..2374468615ed 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -310,6 +311,8 @@ int __init register_intc_controller(struct intc_desc *desc) BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + intc_irq_domain_init(d, hw); + /* register the vectors one by one */ for (i = 0; i < hw->nr_vectors; i++) { struct intc_vect *vect = hw->vectors + i; @@ -319,8 +322,8 @@ int __init register_intc_controller(struct intc_desc *desc) if (!vect->enum_id) continue; - res = irq_alloc_desc_at(irq, numa_node_id()); - if (res != irq && res != -EEXIST) { + res = irq_create_identity_mapping(d->domain, irq); + if (unlikely(res)) { pr_err("can't get irq_desc for %d\n", irq); continue; } @@ -340,8 +343,8 @@ int __init register_intc_controller(struct intc_desc *desc) * IRQ support, each vector still needs to have * its own backing irq_desc. */ - res = irq_alloc_desc_at(irq2, numa_node_id()); - if (res != irq2 && res != -EEXIST) { + res = irq_create_identity_mapping(d->domain, irq2); + if (unlikely(res)) { pr_err("can't get irq_desc for %d\n", irq2); continue; } diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h index f034a979a16f..7dff08e2a071 100644 --- a/drivers/sh/intc/internals.h +++ b/drivers/sh/intc/internals.h @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -66,6 +67,7 @@ struct intc_desc_int { unsigned int nr_sense; struct intc_window *window; unsigned int nr_windows; + struct irq_domain *domain; struct irq_chip chip; bool skip_suspend; }; @@ -187,6 +189,9 @@ unsigned long intc_get_ack_handle(unsigned int irq); void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d, intc_enum enum_id, int enable); +/* irqdomain.c */ +void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw); + /* virq.c */ void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d); void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d); diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c new file mode 100644 index 000000000000..3968f1c3c5c3 --- /dev/null +++ b/drivers/sh/intc/irqdomain.c @@ -0,0 +1,68 @@ +/* + * IRQ domain support for SH INTC subsystem + * + * Copyright (C) 2012 Paul Mundt + * + * 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. + */ +#define pr_fmt(fmt) "intc: " fmt + +#include +#include +#include +#include "internals.h" + +/** + * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs. + * + * This takes care of exception vector to hwirq translation through + * by way of evt2irq() translation. + * + * Note: For platforms that use a flat vector space without INTEVT this + * basically just mimics irq_domain_xlate_onecell() by way of a nopped + * out evt2irq() implementation. + */ +static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize < 1)) + return -EINVAL; + + *out_hwirq = evt2irq(intspec[0]); + *out_type = IRQ_TYPE_NONE; + + return 0; +} + +static const struct irq_domain_ops intc_evt_ops = { + .xlate = intc_evt_xlate, +}; + +void __init intc_irq_domain_init(struct intc_desc_int *d, + struct intc_hw_desc *hw) +{ + unsigned int irq_base, irq_end; + + /* + * Quick linear revmap check + */ + irq_base = evt2irq(hw->vectors[0].vect); + irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect); + + /* + * Linear domains have a hard-wired assertion that IRQs start at + * 0 in order to make some performance optimizations. Lamely + * restrict the linear case to these conditions here, taking the + * tree penalty for linear cases with non-zero hwirq bases. + */ + if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1)) + d->domain = irq_domain_add_linear(NULL, hw->nr_vectors, + &intc_evt_ops, NULL); + else + d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL); + + BUG_ON(!d->domain); +} -- GitLab From 8a87776dee0019bd87471c55121bb6934bd6d302 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 1 Aug 2012 00:54:22 -0700 Subject: [PATCH 4990/5711] sh: sh7724: fixup renesas_usbhs clock settings 8cc88a55b03bd4940390125c2521c99368513be5 (sh: sh7724: use runtime PM implementation) broke sh7724 clocks. renesas_usbhs needs HWBLK_USB0/1 clock on sh7724 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index c87e78f73234..5f30f805d2f2 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -334,8 +334,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]), CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]), CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]), - CLKDEV_CON_ID("usb1", &mstp_clks[HWBLK_USB1]), - CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB0]), + CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[HWBLK_USB1]), + CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[HWBLK_USB0]), CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]), CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]), -- GitLab From 1ca8fe38a6c958babe6571e39cb0115a40b94603 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 1 Aug 2012 00:54:58 -0700 Subject: [PATCH 4991/5711] sh: ecovec: care CN5 VBUS if USB host mode renesas_usbhs driver can control both USB Host/Gadget, but it needs VBUS output if Host mode. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/boards/mach-ecovec24/setup.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index a06c5c8a14a8..64559e8af14b 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -244,9 +244,17 @@ static int usbhs_get_id(struct platform_device *pdev) return gpio_get_value(GPIO_PTB3); } +static void usbhs_phy_reset(struct platform_device *pdev) +{ + /* enable vbus if HOST */ + if (!gpio_get_value(GPIO_PTB3)) + gpio_set_value(GPIO_PTB5, 1); +} + static struct renesas_usbhs_platform_info usbhs_info = { .platform_callback = { .get_id = usbhs_get_id, + .phy_reset = usbhs_phy_reset, }, .driver_param = { .buswait_bwait = 4, -- GitLab From aff252a848ce21b431ba822de3dab9c4c94571cb Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 1 Aug 2012 10:16:53 +0200 Subject: [PATCH 4992/5711] ALSA: snd-usb: fix clock source validity index uac_clock_source_is_valid() uses the control selector value to access the bmControls bitmap of the clock source unit. This is wrong, as control selector values start from 1, while the bitmap uses all available bits. In other words, "Clock Validity Control" is stored in D3..2, not D5..4 of the clock selector unit's bmControls. Signed-off-by: Daniel Mack Reported-by: Andreas Koch Cc: stable@kernel.org Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 379baad3d5ad..5e634a2eb282 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -111,7 +111,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) return 0; /* If a clock source can't tell us whether it's valid, we assume it is */ - if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) + if (!uac2_control_is_readable(cs_desc->bmControls, + UAC2_CS_CONTROL_CLOCK_VALID - 1)) return 1; err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, -- GitLab From fe86cdcef73ba19a2246a124f0ddbd19b14fb549 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 1 Aug 2012 10:44:28 +0200 Subject: [PATCH 4993/5711] block: do not artificially constrain max_sectors for stacking drivers blk_set_stacking_limits is intended to allow stacking drivers to build up the limits of the stacked device based on the underlying devices' limits. But defaulting 'max_sectors' to BLK_DEF_MAX_SECTORS (1024) doesn't allow the stacking driver to inherit a max_sectors larger than 1024 -- due to blk_stack_limits' use of min_not_zero. It is now clear that this artificial limit is getting in the way so change blk_set_stacking_limits's max_sectors to UINT_MAX (which allows stacking drivers like dm-multipath to inherit 'max_sectors' from the underlying paths). Reported-by: Vijay Chauhan Tested-by: Vijay Chauhan Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe --- block/blk-settings.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index d3234fc494ad..565a6786032f 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -143,8 +143,7 @@ void blk_set_stacking_limits(struct queue_limits *lim) lim->discard_zeroes_data = 1; lim->max_segments = USHRT_MAX; lim->max_hw_sectors = UINT_MAX; - - lim->max_sectors = BLK_DEF_MAX_SECTORS; + lim->max_sectors = UINT_MAX; } EXPORT_SYMBOL(blk_set_stacking_limits); -- GitLab From 4638a83e8615de9c16c39dfed234951d0f468cf1 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 1 Aug 2012 12:17:27 +0200 Subject: [PATCH 4994/5711] block: uninitialized ioc->nr_tasks triggers WARN_ON Hi, I'm using the old-fashioned 'dump' backup tool, and I noticed that it spews the below warning as of 3.5-rc1 and later (3.4 is fine): [ 10.886893] ------------[ cut here ]------------ [ 10.886904] WARNING: at include/linux/iocontext.h:140 copy_process+0x1488/0x1560() [ 10.886905] Hardware name: Bochs [ 10.886906] Modules linked in: [ 10.886908] Pid: 2430, comm: dump Not tainted 3.5.0-rc7+ #27 [ 10.886908] Call Trace: [ 10.886911] [] warn_slowpath_common+0x7a/0xb0 [ 10.886912] [] warn_slowpath_null+0x15/0x20 [ 10.886913] [] copy_process+0x1488/0x1560 [ 10.886914] [] do_fork+0xb4/0x340 [ 10.886918] [] ? recalc_sigpending+0x1a/0x50 [ 10.886919] [] ? __set_task_blocked+0x32/0x80 [ 10.886920] [] ? __set_current_blocked+0x3a/0x60 [ 10.886923] [] sys_clone+0x23/0x30 [ 10.886925] [] stub_clone+0x13/0x20 [ 10.886927] [] ? system_call_fastpath+0x16/0x1b [ 10.886928] ---[ end trace 32a14af7ee6a590b ]--- Reproducing is easy, I can hit it on a KVM system with a very basic config (x86_64 make defconfig + enable the drivers needed). To hit it, just install dump (on debian/ubuntu, not sure what the package might be called on Fedora), and: dump -o -f /tmp/foo / You'll see the warning in dmesg once it forks off the I/O process and starts dumping filesystem contents. I bisected it down to the following commit: commit f6e8d01bee036460e03bd4f6a79d014f98ba712e Author: Tejun Heo Date: Mon Mar 5 13:15:26 2012 -0800 block: add io_context->active_ref Currently ioc->nr_tasks is used to decide two things - whether an ioc is done issuing IOs and whether it's shared by multiple tasks. This patch separate out the first into ioc->active_ref, which is acquired and released using {get|put}_io_context_active() respectively. This will be used to associate bio's with a given task. This patch doesn't introduce any visible behavior change. Signed-off-by: Tejun Heo Cc: Vivek Goyal Signed-off-by: Jens Axboe It seems like the init of ioc->nr_tasks was removed in that patch, so it starts out at 0 instead of 1. Tejun, is the right thing here to add back the init, or should something else be done? The below patch removes the warning, but I haven't done any more extensive testing on it. Signed-off-by: Olof Johansson Acked-by: Tejun Heo Cc: stable@kernel.org Signed-off-by: Jens Axboe --- block/blk-ioc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 893b8007c657..fab4cdd3f7bb 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -244,6 +244,7 @@ int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node) /* initialize */ atomic_long_set(&ioc->refcount, 1); + atomic_set(&ioc->nr_tasks, 1); atomic_set(&ioc->active_ref, 1); spin_lock_init(&ioc->lock); INIT_RADIX_TREE(&ioc->icq_tree, GFP_ATOMIC | __GFP_HIGH); -- GitLab From c83f6bf98dc1f1a194118b3830706cebbebda8c4 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 1 Aug 2012 12:24:18 +0200 Subject: [PATCH 4995/5711] block: add partition resize function to blkpg ioctl Add a new operation code (BLKPG_RESIZE_PARTITION) to the BLKPG ioctl that allows altering the size of an existing partition, even if it is currently in use. This patch converts hd_struct->nr_sects into sequence counter because One might extend a partition while IO is happening to it and update of nr_sects can be non-atomic on 32bit machines with 64bit sector_t. This can lead to issues like reading inconsistent size of a partition. Sequence counter have been used so that readers don't have to take bdev mutex lock as we call sector_in_part() very frequently. Now all the access to hd_struct->nr_sects should happen using sequence counter read/update helper functions part_nr_sects_read/part_nr_sects_write. There is one exception though, set_capacity()/get_capacity(). I think theoritically race should exist there too but this patch does not modify set_capacity()/get_capacity() due to sheer number of call sites and I am afraid that change might break something. I have left that as a TODO item. We can handle it later if need be. This patch does not introduce any new races as such w.r.t set_capacity()/get_capacity(). v2: Add CONFIG_LBDAF test to UP preempt case as suggested by Phillip. Signed-off-by: Vivek Goyal Signed-off-by: Phillip Susi Signed-off-by: Jens Axboe --- block/genhd.c | 20 +++++++++---- block/ioctl.c | 59 +++++++++++++++++++++++++++++++++++++-- block/partition-generic.c | 4 ++- include/linux/blkpg.h | 1 + include/linux/genhd.h | 57 +++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 9 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 9cf5583c90ff..cac7366957c3 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -154,7 +154,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) part = rcu_dereference(ptbl->part[piter->idx]); if (!part) continue; - if (!part->nr_sects && + if (!part_nr_sects_read(part) && !(piter->flags & DISK_PITER_INCL_EMPTY) && !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && piter->idx == 0)) @@ -191,7 +191,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit); static inline int sector_in_part(struct hd_struct *part, sector_t sector) { return part->start_sect <= sector && - sector < part->start_sect + part->nr_sects; + sector < part->start_sect + part_nr_sects_read(part); } /** @@ -769,8 +769,8 @@ void __init printk_all_partitions(void) printk("%s%s %10llu %s %s", is_part0 ? "" : " ", bdevt_str(part_devt(part), devt_buf), - (unsigned long long)part->nr_sects >> 1, - disk_name(disk, part->partno, name_buf), + (unsigned long long)part_nr_sects_read(part) >> 1 + , disk_name(disk, part->partno, name_buf), uuid_buf); if (is_part0) { if (disk->driverfs_dev != NULL && @@ -862,7 +862,7 @@ static int show_partition(struct seq_file *seqf, void *v) while ((part = disk_part_iter_next(&piter))) seq_printf(seqf, "%4d %7d %10llu %s\n", MAJOR(part_devt(part)), MINOR(part_devt(part)), - (unsigned long long)part->nr_sects >> 1, + (unsigned long long)part_nr_sects_read(part) >> 1, disk_name(sgp, part->partno, buf)); disk_part_iter_exit(&piter); @@ -1268,6 +1268,16 @@ struct gendisk *alloc_disk_node(int minors, int node_id) } disk->part_tbl->part[0] = &disk->part0; + /* + * set_capacity() and get_capacity() currently don't use + * seqcounter to read/update the part0->nr_sects. Still init + * the counter as we can read the sectors in IO submission + * patch using seqence counters. + * + * TODO: Ideally set_capacity() and get_capacity() should be + * converted to make use of bd_mutex and sequence counters. + */ + seqcount_init(&disk->part0.nr_sects_seq); hd_ref_init(&disk->part0); disk->minors = minors; diff --git a/block/ioctl.c b/block/ioctl.c index ba15b2dbfb98..4476e0e85d16 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -13,7 +13,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user { struct block_device *bdevp; struct gendisk *disk; - struct hd_struct *part; + struct hd_struct *part, *lpart; struct blkpg_ioctl_arg a; struct blkpg_partition p; struct disk_part_iter piter; @@ -36,8 +36,8 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user case BLKPG_ADD_PARTITION: start = p.start >> 9; length = p.length >> 9; - /* check for fit in a hd_struct */ - if (sizeof(sector_t) == sizeof(long) && + /* check for fit in a hd_struct */ + if (sizeof(sector_t) == sizeof(long) && sizeof(long long) > sizeof(long)) { long pstart = start, plength = length; if (pstart != start || plength != length @@ -91,6 +91,59 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); + return 0; + case BLKPG_RESIZE_PARTITION: + start = p.start >> 9; + /* new length of partition in bytes */ + length = p.length >> 9; + /* check for fit in a hd_struct */ + if (sizeof(sector_t) == sizeof(long) && + sizeof(long long) > sizeof(long)) { + long pstart = start, plength = length; + if (pstart != start || plength != length + || pstart < 0 || plength < 0) + return -EINVAL; + } + part = disk_get_part(disk, partno); + if (!part) + return -ENXIO; + bdevp = bdget(part_devt(part)); + if (!bdevp) { + disk_put_part(part); + return -ENOMEM; + } + mutex_lock(&bdevp->bd_mutex); + mutex_lock_nested(&bdev->bd_mutex, 1); + if (start != part->start_sect) { + mutex_unlock(&bdevp->bd_mutex); + mutex_unlock(&bdev->bd_mutex); + bdput(bdevp); + disk_put_part(part); + return -EINVAL; + } + /* overlap? */ + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY); + while ((lpart = disk_part_iter_next(&piter))) { + if (lpart->partno != partno && + !(start + length <= lpart->start_sect || + start >= lpart->start_sect + lpart->nr_sects) + ) { + disk_part_iter_exit(&piter); + mutex_unlock(&bdevp->bd_mutex); + mutex_unlock(&bdev->bd_mutex); + bdput(bdevp); + disk_put_part(part); + return -EBUSY; + } + } + disk_part_iter_exit(&piter); + part_nr_sects_write(part, (sector_t)length); + i_size_write(bdevp->bd_inode, p.length); + mutex_unlock(&bdevp->bd_mutex); + mutex_unlock(&bdev->bd_mutex); + bdput(bdevp); + disk_put_part(part); return 0; default: return -EINVAL; diff --git a/block/partition-generic.c b/block/partition-generic.c index 6df5d6928a44..f1d14519cc04 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -84,7 +84,7 @@ ssize_t part_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); - return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); + return sprintf(buf, "%llu\n",(unsigned long long)part_nr_sects_read(p)); } static ssize_t part_ro_show(struct device *dev, @@ -294,6 +294,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, err = -ENOMEM; goto out_free; } + + seqcount_init(&p->nr_sects_seq); pdev = part_to_dev(p); p->start_sect = start; diff --git a/include/linux/blkpg.h b/include/linux/blkpg.h index faf8a45af210..a8519446c111 100644 --- a/include/linux/blkpg.h +++ b/include/linux/blkpg.h @@ -40,6 +40,7 @@ struct blkpg_ioctl_arg { /* The subfunctions (for the op field) */ #define BLKPG_ADD_PARTITION 1 #define BLKPG_DEL_PARTITION 2 +#define BLKPG_RESIZE_PARTITION 3 /* Sizes of name fields. Unused at present. */ #define BLKPG_DEVNAMELTH 64 diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 017a7fb5a1fc..b88723b81b3d 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -98,7 +98,13 @@ struct partition_meta_info { struct hd_struct { sector_t start_sect; + /* + * nr_sects is protected by sequence counter. One might extend a + * partition while IO is happening to it and update of nr_sects + * can be non-atomic on 32bit machines with 64bit sector_t. + */ sector_t nr_sects; + seqcount_t nr_sects_seq; sector_t alignment_offset; unsigned int discard_alignment; struct device __dev; @@ -648,6 +654,57 @@ static inline void hd_struct_put(struct hd_struct *part) __delete_partition(part); } +/* + * Any access of part->nr_sects which is not protected by partition + * bd_mutex or gendisk bdev bd_mutex, should be done using this + * accessor function. + * + * Code written along the lines of i_size_read() and i_size_write(). + * CONFIG_PREEMPT case optimizes the case of UP kernel with preemption + * on. + */ +static inline sector_t part_nr_sects_read(struct hd_struct *part) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_SMP) + sector_t nr_sects; + unsigned seq; + do { + seq = read_seqcount_begin(&part->nr_sects_seq); + nr_sects = part->nr_sects; + } while (read_seqcount_retry(&part->nr_sects_seq, seq)); + return nr_sects; +#elif BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_PREEMPT) + sector_t nr_sects; + + preempt_disable(); + nr_sects = part->nr_sects; + preempt_enable(); + return nr_sects; +#else + return part->nr_sects; +#endif +} + +/* + * Should be called with mutex lock held (typically bd_mutex) of partition + * to provide mutual exlusion among writers otherwise seqcount might be + * left in wrong state leaving the readers spinning infinitely. + */ +static inline void part_nr_sects_write(struct hd_struct *part, sector_t size) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_SMP) + write_seqcount_begin(&part->nr_sects_seq); + part->nr_sects = size; + write_seqcount_end(&part->nr_sects_seq); +#elif BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_PREEMPT) + preempt_disable(); + part->nr_sects = size; + preempt_enable(); +#else + part->nr_sects = size; +#endif +} + #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } -- GitLab From 80799fbb7d10c30df78015b3fa21f7ffcfc0eb2c Mon Sep 17 00:00:00 2001 From: Yuanhan Liu Date: Wed, 1 Aug 2012 12:25:54 +0200 Subject: [PATCH 4996/5711] block: remove dead func declaration __generic_unplug_device() function is removed with commit 7eaceaccab5f40bbfda044629a6298616aeaed50, which forgot to remove the declaration at meantime. Here remove it. Signed-off-by: Yuanhan Liu Signed-off-by: Jens Axboe --- block/blk.h | 1 - 1 file changed, 1 deletion(-) diff --git a/block/blk.h b/block/blk.h index a134231fd22a..2a0ea32d249f 100644 --- a/block/blk.h +++ b/block/blk.h @@ -36,7 +36,6 @@ bool __blk_end_bidi_request(struct request *rq, int error, void blk_rq_timed_out_timer(unsigned long data); void blk_delete_timer(struct request *); void blk_add_timer(struct request *); -void __generic_unplug_device(struct request_queue *); /* * Internal atomic flags for request handling -- GitLab From 63f33b8dda88923487004b20fba825486d009e7b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 31 Jul 2012 21:44:26 -0500 Subject: [PATCH 4997/5711] DM RAID: Add support for MD RAID10 Support the MD RAID10 personality through dm-raid.c Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- Documentation/device-mapper/dm-raid.txt | 26 +++++++ drivers/md/dm-raid.c | 95 +++++++++++++++++++++++-- 2 files changed, 116 insertions(+), 5 deletions(-) diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt index 946c73342cde..1c1844957166 100644 --- a/Documentation/device-mapper/dm-raid.txt +++ b/Documentation/device-mapper/dm-raid.txt @@ -27,6 +27,10 @@ The target is named "raid" and it accepts the following parameters: - rotating parity N (right-to-left) with data restart raid6_nc RAID6 N continue - rotating parity N (right-to-left) with data continuation + raid10 Various RAID10 inspired algorithms chosen by additional params + - RAID10: Striped Mirrors (aka 'Striping on top of mirrors') + - RAID1E: Integrated Adjacent Stripe Mirroring + - and other similar RAID10 variants Reference: Chapter 4 of http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf @@ -59,6 +63,28 @@ The target is named "raid" and it accepts the following parameters: logical size of the array. The bitmap records the device synchronisation state for each region. + [raid10_copies <# copies>] + [raid10_format near] + These two options are used to alter the default layout of + a RAID10 configuration. The number of copies is can be + specified, but the default is 2. There are other variations + to how the copies are laid down - the default and only current + option is "near". Near copies are what most people think of + with respect to mirroring. If these options are left + unspecified, or 'raid10_copies 2' and/or 'raid10_format near' + are given, then the layouts for 2, 3 and 4 devices are: + 2 drives 3 drives 4 drives + -------- ---------- -------------- + A1 A1 A1 A1 A2 A1 A1 A2 A2 + A2 A2 A2 A3 A3 A3 A3 A4 A4 + A3 A3 A4 A4 A5 A5 A5 A6 A6 + A4 A4 A5 A6 A6 A7 A7 A8 A8 + .. .. .. .. .. .. .. .. .. + The 2-device layout is equivalent 2-way RAID1. The 4-device + layout is what a traditional RAID10 would look like. The + 3-device layout is what might be called a 'RAID1E - Integrated + Adjacent Stripe Mirroring'. + <#raid_devs>: The number of devices composing the array. Each device consists of two entries. The first is the device containing the metadata (if any); the second is the one containing the diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index f4275a8e860c..691b3c59088e 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -11,6 +11,7 @@ #include "md.h" #include "raid1.h" #include "raid5.h" +#include "raid10.h" #include "bitmap.h" #include @@ -52,7 +53,10 @@ struct raid_dev { #define DMPF_MAX_RECOVERY_RATE 0x20 #define DMPF_MAX_WRITE_BEHIND 0x40 #define DMPF_STRIPE_CACHE 0x80 -#define DMPF_REGION_SIZE 0X100 +#define DMPF_REGION_SIZE 0x100 +#define DMPF_RAID10_COPIES 0x200 +#define DMPF_RAID10_FORMAT 0x400 + struct raid_set { struct dm_target *ti; @@ -76,6 +80,7 @@ static struct raid_type { const unsigned algorithm; /* RAID algorithm. */ } raid_types[] = { {"raid1", "RAID1 (mirroring)", 0, 2, 1, 0 /* NONE */}, + {"raid10", "RAID10 (striped mirrors)", 0, 2, 10, UINT_MAX /* Varies */}, {"raid4", "RAID4 (dedicated parity disk)", 1, 2, 5, ALGORITHM_PARITY_0}, {"raid5_la", "RAID5 (left asymmetric)", 1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC}, {"raid5_ra", "RAID5 (right asymmetric)", 1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC}, @@ -86,6 +91,17 @@ static struct raid_type { {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} }; +static unsigned raid10_md_layout_to_copies(int layout) +{ + return layout & 0xFF; +} + +static int raid10_format_to_md_layout(char *format, unsigned copies) +{ + /* 1 "far" copy, and 'copies' "near" copies */ + return (1 << 8) | (copies & 0xFF); +} + static struct raid_type *get_raid_type(char *name) { int i; @@ -339,10 +355,16 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) * [max_write_behind ] See '-write-behind=' (man mdadm) * [stripe_cache ] Stripe cache size for higher RAIDs * [region_size ] Defines granularity of bitmap + * + * RAID10-only options: + * [raid10_copies <# copies>] Number of copies. (Default: 2) + * [raid10_format ] Layout algorithm. (Default: near) */ static int parse_raid_params(struct raid_set *rs, char **argv, unsigned num_raid_params) { + char *raid10_format = "near"; + unsigned raid10_copies = 2; unsigned i, rebuild_cnt = 0; unsigned long value, region_size = 0; sector_t sectors_per_dev = rs->ti->len; @@ -416,11 +438,28 @@ static int parse_raid_params(struct raid_set *rs, char **argv, } key = argv[i++]; + + /* Parameters that take a string value are checked here. */ + if (!strcasecmp(key, "raid10_format")) { + if (rs->raid_type->level != 10) { + rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; + return -EINVAL; + } + if (strcmp("near", argv[i])) { + rs->ti->error = "Invalid 'raid10_format' value given"; + return -EINVAL; + } + raid10_format = argv[i]; + rs->print_flags |= DMPF_RAID10_FORMAT; + continue; + } + if (strict_strtoul(argv[i], 10, &value) < 0) { rs->ti->error = "Bad numerical argument given in raid params"; return -EINVAL; } + /* Parameters that take a numeric value are checked here */ if (!strcasecmp(key, "rebuild")) { rebuild_cnt++; @@ -439,6 +478,7 @@ static int parse_raid_params(struct raid_set *rs, char **argv, return -EINVAL; } break; + case 10: default: DMERR("The rebuild parameter is not supported for %s", rs->raid_type->name); rs->ti->error = "Rebuild not supported for this RAID type"; @@ -495,7 +535,8 @@ static int parse_raid_params(struct raid_set *rs, char **argv, */ value /= 2; - if (rs->raid_type->level < 5) { + if ((rs->raid_type->level != 5) && + (rs->raid_type->level != 6)) { rs->ti->error = "Inappropriate argument: stripe_cache"; return -EINVAL; } @@ -520,6 +561,14 @@ static int parse_raid_params(struct raid_set *rs, char **argv, } else if (!strcasecmp(key, "region_size")) { rs->print_flags |= DMPF_REGION_SIZE; region_size = value; + } else if (!strcasecmp(key, "raid10_copies") && + (rs->raid_type->level == 10)) { + if ((value < 2) || (value > 0xFF)) { + rs->ti->error = "Bad value for 'raid10_copies'"; + return -EINVAL; + } + rs->print_flags |= DMPF_RAID10_COPIES; + raid10_copies = value; } else { DMERR("Unable to parse RAID parameter: %s", key); rs->ti->error = "Unable to parse RAID parameters"; @@ -538,8 +587,22 @@ static int parse_raid_params(struct raid_set *rs, char **argv, if (dm_set_target_max_io_len(rs->ti, max_io_len)) return -EINVAL; - if ((rs->raid_type->level > 1) && - sector_div(sectors_per_dev, (rs->md.raid_disks - rs->raid_type->parity_devs))) { + if (rs->raid_type->level == 10) { + if (raid10_copies > rs->md.raid_disks) { + rs->ti->error = "Not enough devices to satisfy specification"; + return -EINVAL; + } + + /* (Len * #mirrors) / #devices */ + sectors_per_dev = rs->ti->len * raid10_copies; + sector_div(sectors_per_dev, rs->md.raid_disks); + + rs->md.layout = raid10_format_to_md_layout(raid10_format, + raid10_copies); + rs->md.new_layout = rs->md.layout; + } else if ((rs->raid_type->level > 1) && + sector_div(sectors_per_dev, + (rs->md.raid_disks - rs->raid_type->parity_devs))) { rs->ti->error = "Target length not divisible by number of data devices"; return -EINVAL; } @@ -566,6 +629,9 @@ static int raid_is_congested(struct dm_target_callbacks *cb, int bits) if (rs->raid_type->level == 1) return md_raid1_congested(&rs->md, bits); + if (rs->raid_type->level == 10) + return md_raid10_congested(&rs->md, bits); + return md_raid5_congested(&rs->md, bits); } @@ -884,6 +950,9 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) case 6: redundancy = rs->raid_type->parity_devs; break; + case 10: + redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; + break; default: ti->error = "Unknown RAID type"; return -EINVAL; @@ -1049,12 +1118,19 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) goto bad; } + if (ti->len != rs->md.array_sectors) { + ti->error = "Array size does not match requested target length"; + ret = -EINVAL; + goto size_mismatch; + } rs->callbacks.congested_fn = raid_is_congested; dm_table_add_target_callbacks(ti->table, &rs->callbacks); mddev_suspend(&rs->md); return 0; +size_mismatch: + md_stop(&rs->md); bad: context_free(rs); @@ -1203,6 +1279,13 @@ static int raid_status(struct dm_target *ti, status_type_t type, DMEMIT(" region_size %lu", rs->md.bitmap_info.chunksize >> 9); + if (rs->print_flags & DMPF_RAID10_COPIES) + DMEMIT(" raid10_copies %u", + raid10_md_layout_to_copies(rs->md.layout)); + + if (rs->print_flags & DMPF_RAID10_FORMAT) + DMEMIT(" raid10_format near"); + DMEMIT(" %d", rs->md.raid_disks); for (i = 0; i < rs->md.raid_disks; i++) { if (rs->dev[i].meta_dev) @@ -1277,7 +1360,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 2, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr, @@ -1304,6 +1387,8 @@ module_init(dm_raid_init); module_exit(dm_raid_exit); MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target"); +MODULE_ALIAS("dm-raid1"); +MODULE_ALIAS("dm-raid10"); MODULE_ALIAS("dm-raid4"); MODULE_ALIAS("dm-raid5"); MODULE_ALIAS("dm-raid6"); -- GitLab From dbc6e0222d79e78925fe20733844a796a4b72cf9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 1 Aug 2012 13:07:04 +0400 Subject: [PATCH 4998/5711] delousing target_core_file a bit * set_fs(KERNEL_DS) + getname() is probably the weirdest implementation of strdup() I've seen. Especially since they don't to copy it at all... * filp_open() never returns NULL; it's ERR_PTR(-E...) on failure. * file->f_dentry is never going to be NULL, TYVM. * match_strdup() + snprintf() + kfree() is a bloody weird way to spell match_strlcpy(). Pox on cargo-cult programmers... Signed-off-by: Al Viro --- drivers/target/target_core_file.c | 32 +++++-------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 9f99d0404908..f84cbff83bcd 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -109,46 +109,29 @@ static struct se_device *fd_create_virtdevice( struct se_subsystem_dev *se_dev, void *p) { - char *dev_p = NULL; struct se_device *dev; struct se_dev_limits dev_limits; struct queue_limits *limits; struct fd_dev *fd_dev = p; struct fd_host *fd_host = hba->hba_ptr; - mm_segment_t old_fs; struct file *file; struct inode *inode = NULL; int dev_flags = 0, flags, ret = -EINVAL; memset(&dev_limits, 0, sizeof(struct se_dev_limits)); - old_fs = get_fs(); - set_fs(get_ds()); - dev_p = getname(fd_dev->fd_dev_name); - set_fs(old_fs); - - if (IS_ERR(dev_p)) { - pr_err("getname(%s) failed: %lu\n", - fd_dev->fd_dev_name, IS_ERR(dev_p)); - ret = PTR_ERR(dev_p); - goto fail; - } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; - file = filp_open(dev_p, flags, 0600); + file = filp_open(fd_dev->fd_dev_name, flags, 0600); if (IS_ERR(file)) { - pr_err("filp_open(%s) failed\n", dev_p); + pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name); ret = PTR_ERR(file); goto fail; } - if (!file || !file->f_dentry) { - pr_err("filp_open(%s) failed\n", dev_p); - goto fail; - } fd_dev->fd_file = file; /* * If using a block backend with this struct file, we extract @@ -212,14 +195,12 @@ static struct se_device *fd_create_virtdevice( " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, fd_dev->fd_dev_name, fd_dev->fd_dev_size); - putname(dev_p); return dev; fail: if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); fd_dev->fd_file = NULL; } - putname(dev_p); return ERR_PTR(ret); } @@ -448,14 +429,11 @@ static ssize_t fd_set_configfs_dev_params( token = match_token(ptr, tokens, args); switch (token) { case Opt_fd_dev_name: - arg_p = match_strdup(&args[0]); - if (!arg_p) { - ret = -ENOMEM; + if (match_strlcpy(fd_dev->fd_dev_name, &args[0], + FD_MAX_DEV_NAME) == 0) { + ret = -EINVAL; break; } - snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME, - "%s", arg_p); - kfree(arg_p); pr_debug("FILEIO: Referencing Path: %s\n", fd_dev->fd_dev_name); fd_dev->fbd_flags |= FBDF_HAS_PATH; -- GitLab From e29b72f5e129b4dd4b77dc01dba340006bb103f8 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:55:57 +0200 Subject: [PATCH 4999/5711] MIPS: Lantiq: Fix interface clock and PCI control register offset The XRX200 based SoC have a different register offset for the interface clock and PCI control registers. This patch detects the SoC and sets the register offset at runtime. This make PCI work on the VR9 SoC. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4113/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/xway/sysctrl.c | 49 +++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 83780f7c842b..befbb760ab76 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -20,10 +20,12 @@ /* clock control register */ #define CGU_IFCCR 0x0018 +#define CGU_IFCCR_VR9 0x0024 /* system clock register */ #define CGU_SYS 0x0010 /* pci control register */ #define CGU_PCICR 0x0034 +#define CGU_PCICR_VR9 0x0038 /* ephy configuration register */ #define CGU_EPHY 0x10 /* power control register */ @@ -80,6 +82,9 @@ static void __iomem *pmu_membase; void __iomem *ltq_cgu_membase; void __iomem *ltq_ebu_membase; +static u32 ifccr = CGU_IFCCR; +static u32 pcicr = CGU_PCICR; + /* legacy function kept alive to ease clkdev transition */ void ltq_pmu_enable(unsigned int module) { @@ -103,14 +108,14 @@ EXPORT_SYMBOL(ltq_pmu_disable); /* enable a hw clock */ static int cgu_enable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) | clk->bits, ifccr); return 0; } /* disable a hw clock */ static void cgu_disable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) & ~clk->bits, ifccr); } /* enable a clock gate */ @@ -138,22 +143,22 @@ static void pmu_disable(struct clk *clk) /* the pci enable helper */ static int pci_enable(struct clk *clk) { - unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + unsigned int val = ltq_cgu_r32(ifccr); /* set bus clock speed */ if (of_machine_is_compatible("lantiq,ar9")) { - ifccr &= ~0x1f00000; + val &= ~0x1f00000; if (clk->rate == CLOCK_33M) - ifccr |= 0xe00000; + val |= 0xe00000; else - ifccr |= 0x700000; /* 62.5M */ + val |= 0x700000; /* 62.5M */ } else { - ifccr &= ~0xf00000; + val &= ~0xf00000; if (clk->rate == CLOCK_33M) - ifccr |= 0x800000; + val |= 0x800000; else - ifccr |= 0x400000; /* 62.5M */ + val |= 0x400000; /* 62.5M */ } - ltq_cgu_w32(ifccr, CGU_IFCCR); + ltq_cgu_w32(val, ifccr); pmu_enable(clk); return 0; } @@ -161,18 +166,16 @@ static int pci_enable(struct clk *clk) /* enable the external clock as a source */ static int pci_ext_enable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16), - CGU_IFCCR); - ltq_cgu_w32((1 << 30), CGU_PCICR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) & ~(1 << 16), ifccr); + ltq_cgu_w32((1 << 30), pcicr); return 0; } /* disable the external clock as a source */ static void pci_ext_disable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16), - CGU_IFCCR); - ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) | (1 << 16), ifccr); + ltq_cgu_w32((1 << 31) | (1 << 30), pcicr); } /* enable a clockout source */ @@ -184,11 +187,11 @@ static int clkout_enable(struct clk *clk) for (i = 0; i < 4; i++) { if (clk->rates[i] == clk->rate) { int shift = 14 - (2 * clk->module); - unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + unsigned int val = ltq_cgu_r32(ifccr); - ifccr &= ~(3 << shift); - ifccr |= i << shift; - ltq_cgu_w32(ifccr, CGU_IFCCR); + val &= ~(3 << shift); + val |= i << shift; + ltq_cgu_w32(val, ifccr); return 0; } } @@ -336,8 +339,12 @@ void __init ltq_soc_init(void) clkdev_add_clkout(); /* add the soc dependent clocks */ - if (!of_machine_is_compatible("lantiq,vr9")) + if (of_machine_is_compatible("lantiq,vr9")) { + ifccr = CGU_IFCCR_VR9; + pcicr = CGU_PCICR_VR9; + } else { clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE); + } if (!of_machine_is_compatible("lantiq,ase")) { clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1); -- GitLab From a9188bc1628366bea7157209df93acc0f74625cc Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:56:00 +0200 Subject: [PATCH 5000/5711] MIPS: Lantiq: Add device_tree_init function Add a lantiq specific version of device_tree_init. The generic MIPS version was removed by. commit 594e966bc412d64eec9282d28ce511bdd62fea39 Author: David Daney Date: Thu Jul 5 18:12:38 2012 +0200 MIPS: Prune some target specific code out of prom.c Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4116/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/prom.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index d185e8477fdf..6cfd6117fbfd 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -8,7 +8,10 @@ #include #include +#include #include +#include + #include #include @@ -70,6 +73,25 @@ void __init plat_mem_setup(void) __dt_setup_arch(&__dtb_start); } +void __init device_tree_init(void) +{ + unsigned long base, size; + + if (!initial_boot_params) + return; + + base = virt_to_phys((void *)initial_boot_params); + size = be32_to_cpu(initial_boot_params->totalsize); + + /* Before we do anything, lets reserve the dt blob */ + reserve_bootmem(base, size, BOOTMEM_DEFAULT); + + unflatten_device_tree(); + + /* free the space reserved for the dt blob */ + free_bootmem(base, size); +} + void __init prom_init(void) { /* call the soc specific detetcion code and get it to fill soc_info */ -- GitLab From b902d9a98e2bd0d3a2b7ddf7bca850b7f853569a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:56:01 +0200 Subject: [PATCH 5001/5711] MIPS: Lantiq: Platform specific CLK fixup As we use CLKDEV_LOOKUP but dont have support for COMMON_CLK yet, we need to provide our own version of of_clk_get_from_provider(). Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4117/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/clk.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index d3bcc33f4699..ce2f129b081f 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -135,6 +135,11 @@ void clk_deactivate(struct clk *clk) } EXPORT_SYMBOL(clk_deactivate); +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +{ + return NULL; +} + static inline u32 get_counter_resolution(void) { u32 res; -- GitLab From 8551fb643ad6fe07f16d0825c8b6d99246024b9a Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:38:00 +0900 Subject: [PATCH 5002/5711] MIPS: AR7: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/ar7/clock.c:420:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/ar7/clock.c:426:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/ar7/clock.c:431:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/ar7/clock.c:437:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/ar7/clock.c:454:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[2]: *** [arch/mips/ar7/clock.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Acked-by: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/4140/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e3efc06e6409..45fdad419d82 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -77,6 +77,7 @@ config AR7 select SYS_SUPPORTS_ZBOOT_UART16550 select ARCH_REQUIRE_GPIOLIB select VLYNQ + select HAVE_CLK help Support for the Texas Instruments AR7 System-on-a-Chip family: TNETD7100, 7200 and 7300. -- GitLab From 3e82eeebad58a8bd9d263236ead0a0734e752792 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:39:52 +0900 Subject: [PATCH 5003/5711] MIPS: BCM63xx: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/bcm63xx/clk.c:249:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/bcm63xx/clk.c:259:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/bcm63xx/clk.c:268:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/bcm63xx/clk.c:275:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/bcm63xx/clk.c:302:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[2]: *** [arch/mips/bcm63xx/clk.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Patchwork: https://patchwork.linux-mips.org/patch/4141/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 45fdad419d82..331d574df99c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -125,6 +125,7 @@ config BCM63XX select SYS_HAS_EARLY_PRINTK select SWAP_IO_SPACE select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK help Support for BCM63XX based boards -- GitLab From 47cd7343f5467bf38d17a78eb99eaa8019e17007 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:41:06 +0900 Subject: [PATCH 5004/5711] MIPS: txx9: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/txx9/generic/setup.c:87:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/txx9/generic/setup.c:97:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/txx9/generic/setup.c:103:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/txx9/generic/setup.c:108:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/txx9/generic/setup.c:114:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[3]: *** [arch/mips/txx9/generic/setup.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Patchwork: https://patchwork.linux-mips.org/patch/4142/ Signed-off-by: Ralf Baechle --- arch/mips/txx9/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 852ae4bb7a85..6d40bc783459 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -20,6 +20,7 @@ config MACH_TXX9 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN + select HAVE_CLK config TOSHIBA_JMR3927 bool "Toshiba JMR-TX3927 board" -- GitLab From 4b00951f6f2fd335f063e553b474fe4648b3307d Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:42:16 +0900 Subject: [PATCH 5005/5711] MIPS: Loongson 1: more clk support and add select HAVE_CLK This fixes a redefinition of clk_*: arch/mips/loongson1/common/clock.c:23:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/loongson1/common/clock.c:41:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here make[3]: *** [arch/mips/loongson1/common/clock.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Acked-by: Kelvin Cheung Patchwork: https://patchwork.linux-mips.org/patch/4143/ Signed-off-by: Ralf Baechle --- arch/mips/loongson1/Kconfig | 1 + arch/mips/loongson1/common/clock.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig index 237fa214de9f..a9a14d6e81af 100644 --- a/arch/mips/loongson1/Kconfig +++ b/arch/mips/loongson1/Kconfig @@ -15,6 +15,7 @@ config LOONGSON1_LS1B select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_HAS_EARLY_PRINTK + select HAVE_CLK endchoice diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c index 2d98fb030596..1bbbbec12085 100644 --- a/arch/mips/loongson1/common/clock.c +++ b/arch/mips/loongson1/common/clock.c @@ -38,12 +38,28 @@ struct clk *clk_get(struct device *dev, const char *name) } EXPORT_SYMBOL(clk_get); +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + unsigned long clk_get_rate(struct clk *clk) { return clk->rate; } EXPORT_SYMBOL(clk_get_rate); +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + static void pll_clk_init(struct clk *clk) { u32 pll; -- GitLab From 068535f1fef4c90aee23eb7b9b9a71c5b72d7cd0 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 1 Aug 2012 07:56:16 -0400 Subject: [PATCH 5006/5711] locks: remove unused lm_release_private In commit 3b6e2723f32d ("locks: prevent side-effects of locks_release_private before file_lock is initialized") we removed the last user of lm_release_private without removing the field itself. Signed-off-by: J. Bruce Fields Signed-off-by: Linus Torvalds --- Documentation/filesystems/Locking | 2 -- fs/locks.c | 6 +----- include/linux/fs.h | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 2db1900d7538..7f647e17830c 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -359,7 +359,6 @@ prototypes: int (*lm_compare_owner)(struct file_lock *, struct file_lock *); void (*lm_notify)(struct file_lock *); /* unblock callback */ int (*lm_grant)(struct file_lock *, struct file_lock *, int); - void (*lm_release_private)(struct file_lock *); void (*lm_break)(struct file_lock *); /* break_lease callback */ int (*lm_change)(struct file_lock **, int); @@ -368,7 +367,6 @@ locking rules: lm_compare_owner: yes no lm_notify: yes no lm_grant: no no -lm_release_private: maybe no lm_break: yes no lm_change yes no diff --git a/fs/locks.c b/fs/locks.c index cdcf219a7391..7e81bfc75164 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -200,11 +200,7 @@ void locks_release_private(struct file_lock *fl) fl->fl_ops->fl_release_private(fl); fl->fl_ops = NULL; } - if (fl->fl_lmops) { - if (fl->fl_lmops->lm_release_private) - fl->fl_lmops->lm_release_private(fl); - fl->fl_lmops = NULL; - } + fl->fl_lmops = NULL; } EXPORT_SYMBOL_GPL(locks_release_private); diff --git a/include/linux/fs.h b/include/linux/fs.h index d7eed5b98ae2..4ba5c8715523 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1162,7 +1162,6 @@ struct lock_manager_operations { int (*lm_compare_owner)(struct file_lock *, struct file_lock *); void (*lm_notify)(struct file_lock *); /* unblock callback */ int (*lm_grant)(struct file_lock *, struct file_lock *, int); - void (*lm_release_private)(struct file_lock *); void (*lm_break)(struct file_lock *); int (*lm_change)(struct file_lock **, int); }; -- GitLab From 95cf1468f712df516cc471adcd1c861df4e3d371 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 1 Aug 2012 17:15:32 +0200 Subject: [PATCH 5007/5711] MIPS: Loongson 2: Sort out clock managment. For unexplainable reasons the Loongson 2 clock API was implemented in a module so fixing this involved shifting large amounts of code around. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/clock.h | 11 ----- .../mips/include/asm/mach-loongson/loongson.h | 1 - arch/mips/kernel/cpufreq/Makefile | 2 +- arch/mips/kernel/cpufreq/loongson2_cpufreq.c | 21 ++++++++- arch/mips/loongson/Kconfig | 1 + arch/mips/loongson/lemote-2f/Makefile | 2 +- .../lemote-2f/clock.c} | 46 ++++--------------- 7 files changed, 33 insertions(+), 51 deletions(-) rename arch/mips/{kernel/cpufreq/loongson2_clock.c => loongson/lemote-2f/clock.c} (76%) diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h index 83894aa7932c..c9456e7a7283 100644 --- a/arch/mips/include/asm/clock.h +++ b/arch/mips/include/asm/clock.h @@ -50,15 +50,4 @@ void clk_recalc_rate(struct clk *); int clk_register(struct clk *); void clk_unregister(struct clk *); -/* the exported API, in addition to clk_set_rate */ -/** - * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter - * @clk: clock source - * @rate: desired clock rate in Hz - * @algo_id: algorithm id to be passed down to ops->set_rate - * - * Returns success (0) or negative errno. - */ -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); - #endif /* __ASM_MIPS_CLOCK_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 06367c37e1b2..5222a007bc21 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -245,7 +245,6 @@ static inline void do_perfcnt_IRQ(void) #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ #include -extern void loongson2_cpu_wait(void); extern struct cpufreq_frequency_table loongson2_clockmod_table[]; /* Chip Config */ diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile index c3479a432efe..05a5715ee38c 100644 --- a/arch/mips/kernel/cpufreq/Makefile +++ b/arch/mips/kernel/cpufreq/Makefile @@ -2,4 +2,4 @@ # Makefile for the Linux/MIPS cpufreq. # -obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o +obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c index ae5db206347c..e7c98e2b78b6 100644 --- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c +++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c @@ -19,7 +19,7 @@ #include -#include +#include static uint nowait; @@ -181,6 +181,25 @@ static struct platform_driver platform_driver = { .id_table = platform_device_ids, }; +/* + * This is the simple version of Loongson-2 wait, Maybe we need do this in + * interrupt disabled context. + */ + +static DEFINE_SPINLOCK(loongson2_wait_lock); + +static void loongson2_cpu_wait(void) +{ + unsigned long flags; + u32 cpu_freq; + + spin_lock_irqsave(&loongson2_wait_lock, flags); + cpu_freq = LOONGSON_CHIPCFG0; + LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ + LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ + spin_unlock_irqrestore(&loongson2_wait_lock, flags); +} + static int __init cpufreq_init(void) { int ret; diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index aca93eed8779..263beb9322a8 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -41,6 +41,7 @@ config LEMOTE_MACH2F select CSRC_R4K if ! MIPS_EXTERNAL_TIMER select DMA_NONCOHERENT select GENERIC_ISA_DMA_SUPPORT_BROKEN + select HAVE_CLK select HW_HAS_PCI select I8259 select IRQ_CPU diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index 8699a53f0477..4f9eaa328a16 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -2,7 +2,7 @@ # Makefile for lemote loongson2f family machines # -obj-y += machtype.o irq.o reset.o ec_kb3310b.o +obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o # # Suspend Support diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/loongson/lemote-2f/clock.c similarity index 76% rename from arch/mips/kernel/cpufreq/loongson2_clock.c rename to arch/mips/loongson/lemote-2f/clock.c index 5426779d9fdb..bc739d4bab2e 100644 --- a/arch/mips/kernel/cpufreq/loongson2_clock.c +++ b/arch/mips/loongson/lemote-2f/clock.c @@ -6,14 +6,17 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ - -#include +#include #include -#include +#include +#include +#include +#include +#include +#include #include - -#include +#include static LIST_HEAD(clock_list); static DEFINE_SPINLOCK(clock_lock); @@ -88,12 +91,6 @@ void clk_put(struct clk *clk) EXPORT_SYMBOL(clk_put); int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return clk_set_rate_ex(clk, rate, 0); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) { int ret = 0; int regval; @@ -103,7 +100,7 @@ int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) unsigned long flags; spin_lock_irqsave(&clock_lock, flags); - ret = clk->ops->set_rate(clk, rate, algo_id); + ret = clk->ops->set_rate(clk, rate, 0); spin_unlock_irqrestore(&clock_lock, flags); } @@ -129,7 +126,7 @@ int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) return ret; } -EXPORT_SYMBOL_GPL(clk_set_rate_ex); +EXPORT_SYMBOL_GPL(clk_set_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { @@ -146,26 +143,3 @@ long clk_round_rate(struct clk *clk, unsigned long rate) return rate; } EXPORT_SYMBOL_GPL(clk_round_rate); - -/* - * This is the simple version of Loongson-2 wait, Maybe we need do this in - * interrupt disabled content - */ - -DEFINE_SPINLOCK(loongson2_wait_lock); -void loongson2_cpu_wait(void) -{ - u32 cpu_freq; - unsigned long flags; - - spin_lock_irqsave(&loongson2_wait_lock, flags); - cpu_freq = LOONGSON_CHIPCFG0; - LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ - LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ - spin_unlock_irqrestore(&loongson2_wait_lock, flags); -} -EXPORT_SYMBOL_GPL(loongson2_cpu_wait); - -MODULE_AUTHOR("Yanhua "); -MODULE_DESCRIPTION("cpufreq driver for Loongson 2F"); -MODULE_LICENSE("GPL"); -- GitLab From 2d9957cce674308f744f37f68b6bc3261bfdbbf4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Aug 2012 20:54:52 +0200 Subject: [PATCH 5008/5711] mac80211: clear timer bits when disconnecting There's a corner case that can happen when we suspend with a timer running, then resume and disconnect. If we connect again, suspend and resume we might start timers that shouldn't be running. Reset the timer flags to avoid this. This affects both mesh and managed modes. Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 2 ++ net/mac80211/mlme.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6fac18c0423f..d60b3d362e00 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -634,6 +634,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) local->fif_other_bss--; atomic_dec(&local->iff_allmultis); ieee80211_configure_filter(local); + + sdata->u.mesh.timers_running = 0; } static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cef0c9e79aba..a4a5acdbaa4d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1430,6 +1430,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.bcn_mon_timer); del_timer_sync(&sdata->u.mgd.timer); del_timer_sync(&sdata->u.mgd.chswitch_timer); + + sdata->u.mgd.timers_running = 0; } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, -- GitLab From dd4c9260e7f23f2e951cbfb2726e468c6d30306c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Aug 2012 21:03:21 +0200 Subject: [PATCH 5009/5711] mac80211: cancel mesh path timer The mesh path timer needs to be canceled when leaving the mesh as otherwise it could fire after the interface has been removed already. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d60b3d362e00..85572353a7e3 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -622,6 +622,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); + del_timer_sync(&sdata->u.mesh.mesh_path_timer); /* * If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again -- GitLab From 4b6486659a7defef82ea51b276024b3aa357fefc Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Fri, 20 Jul 2012 10:44:24 -0600 Subject: [PATCH 5010/5711] KVM: x86: apply kvmclock offset to guest wall clock time When a guest migrates to a new host, the system time difference from the previous host is used in the updates to the kvmclock system time visible to the guest, resulting in a continuation of correct kvmclock based guest timekeeping. The wall clock component of the kvmclock provided time is currently not updated with this same time offset. Since the Linux guest caches the wall clock based time, this discrepency is not noticed until the guest is rebooted. After reboot the guest's time calculations are off. This patch adjusts the wall clock by the kvmclock_offset, resulting in correct guest time after a reboot. Cc: Zachary Amsden Signed-off-by: Bruce Rogers Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/x86.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 59b59508ff07..42bce48f6928 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -925,6 +925,10 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) */ getboottime(&boot); + if (kvm->arch.kvmclock_offset) { + struct timespec ts = ns_to_timespec(kvm->arch.kvmclock_offset); + boot = timespec_sub(boot, ts); + } wc.sec = boot.tv_sec; wc.nsec = boot.tv_nsec; wc.version = version; -- GitLab From a3170d2ec25f841bee1b52487693ac1a2f191ba6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 22 May 2012 21:16:35 -0400 Subject: [PATCH 5011/5711] um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/kernel/process.c | 2 +- arch/um/kernel/skas/syscall.c | 2 +- arch/x86/um/asm/ptrace.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index ccb9a9d283f1..f19ca6152460 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -193,7 +193,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, if (current->thread.forking) { memcpy(&p->thread.regs.regs, ®s->regs, sizeof(p->thread.regs.regs)); - UPT_SET_SYSCALL_RETURN(&p->thread.regs.regs, 0); + PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); if (sp != 0) REGS_SP(p->thread.regs.regs.gp) = sp; diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 05fbeb480e0b..800551a29dbf 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); - UPT_SET_SYSCALL_RETURN(r, result); + PT_REGS_SET_SYSCALL_RETURN(regs, result); syscall_trace(r, 1); } diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h index 950dfb7b8417..e72cd0df5ba3 100644 --- a/arch/x86/um/asm/ptrace.h +++ b/arch/x86/um/asm/ptrace.h @@ -30,10 +30,10 @@ #define profile_pc(regs) PT_REGS_IP(regs) #define UPT_RESTART_SYSCALL(r) (UPT_IP(r) -= 2) -#define UPT_SET_SYSCALL_RETURN(r, res) (UPT_AX(r) = (res)) +#define PT_REGS_SET_SYSCALL_RETURN(r, res) (PT_REGS_AX(r) = (res)) -static inline long regs_return_value(struct uml_pt_regs *regs) +static inline long regs_return_value(struct pt_regs *regs) { - return UPT_AX(regs); + return PT_REGS_AX(regs); } #endif /* __UM_X86_PTRACE_H */ -- GitLab From 30f31c0a492d0c1cd64af631476697f38d6a79d4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 1 Aug 2012 14:48:58 +0200 Subject: [PATCH 5012/5711] perf test: Fix parse events automated tests Parse events tests got broken after following commit: perf tools: Fix trace events storms due to weight demux commit 0983cc0dbca45250cbb5984bec7c303ac265b8e5 Author: Frederic Weisbecker that added PERF_SAMPLE_PERIOD sample type for tracepoints. Updating related tests. Signed-off-by: Jiri Olsa Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343825338-10618-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events-test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 1b997d2b89ce..127d648cc548 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -13,6 +13,9 @@ do { \ } \ } while (0) +#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ + PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) + static int test__checkevent_tracepoint(struct perf_evlist *evlist) { struct perf_evsel *evsel = list_entry(evlist->entries.next, @@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == - evsel->attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); return 0; } @@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) - == evsel->attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); } @@ -428,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist) evsel = list_entry(evsel->node.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == - evsel->attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); -- GitLab From 028df76726c5637c6f70a064d94452808ec74f9e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 1 Aug 2012 14:47:57 +0200 Subject: [PATCH 5013/5711] perf symbols: Fix array sizes for binary types arrays Following commit introduced wrong array boundaries, that could lead to SIGSEGV. perf symbols: Factor DSO symtab types to generic binary types commit 44f24cb3156a1e7d2b6bb501b7f6153aed08994c Author: Jiri Olsa Fixing to use proper array size. Reported-by: Markus Trippelsdorf Signed-off-by: Jiri Olsa Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Markus Trippelsdorf Link: http://lkml.kernel.org/r/1343825277-10517-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fdad4eeeb429..fe86612afadc 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) +#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) +#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data) int dso__name_len(const struct dso *dso) { -- GitLab From 0ecf4f0c02b7802de5d1251e03e6eab360f158e1 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 Jul 2012 10:50:10 +0900 Subject: [PATCH 5014/5711] perf target: Fix check on buffer size It was a mistake just replace assert to BUG_ON since its condition should be negated. Fix it. Signed-off-by: Namhyung Kim Cc: "Kirill A. Shutemov" Cc: Ingo Molnar Cc: Kirill A. Shutemov Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Ulrich Drepper Link: http://lkml.kernel.org/r/1343267410-7758-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 3f59c496e64c..051eaa68095e 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c @@ -110,7 +110,7 @@ int perf_target__strerror(struct perf_target *target, int errnum, int idx; const char *msg; - BUG_ON(buflen > 0); + BUG_ON(buflen == 0); if (errnum >= 0) { const char *err = strerror_r(errnum, buf, buflen); -- GitLab From bde09467b56c5a3cfe2a29d58edc5f7172c15184 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 1 Aug 2012 18:53:11 -0300 Subject: [PATCH 5015/5711] perf evsel: Precalculate the sample size So that we don't have to store it in the perf_session instance, because in the future perf_session instances may have multiple evlists, each with different sample_type/sizes. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ptod86fxkpgq3h62m9refkv4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-test.c | 9 ++++----- tools/perf/util/evsel.c | 3 ++- tools/perf/util/evsel.h | 8 +------- tools/perf/util/python.c | 2 +- tools/perf/util/session.c | 14 +++++++++++++- tools/perf/util/session.h | 13 +++---------- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index d909eb74a0eb..2ea5fe4cc940 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -478,7 +478,6 @@ static int test__basic_mmap(void) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; struct perf_evsel *evsels[nsyscalls], *evsel; - int sample_size = __perf_evsel__sample_size(attr.sample_type); for (i = 0; i < nsyscalls; ++i) { char name[64]; @@ -563,7 +562,8 @@ static int test__basic_mmap(void) goto out_munmap; } - err = perf_event__parse_sample(event, attr.sample_type, sample_size, + err = perf_event__parse_sample(event, attr.sample_type, + evsels[0]->sample_size, false, &sample, false); if (err) { pr_err("Can't parse sample, err = %d\n", err); @@ -666,7 +666,7 @@ static int test__PERF_RECORD(void) found_libc_mmap = false, found_vdso_mmap = false, found_ld_mmap = false; - int err = -1, errs = 0, i, wakeups = 0, sample_size; + int err = -1, errs = 0, i, wakeups = 0; u32 cpu; int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; @@ -761,7 +761,6 @@ static int test__PERF_RECORD(void) * event. */ sample_type = perf_evlist__sample_type(evlist); - sample_size = __perf_evsel__sample_size(sample_type); /* * Now that all is properly set up, enable the events, they will @@ -789,7 +788,7 @@ static int test__PERF_RECORD(void) nr_events[type]++; err = perf_event__parse_sample(event, sample_type, - sample_size, true, + evsel->sample_size, true, &sample, false); if (err < 0) { if (verbose) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e81771364867..8feec4011356 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -20,7 +20,7 @@ #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) -int __perf_evsel__sample_size(u64 sample_type) +static int __perf_evsel__sample_size(u64 sample_type) { u64 mask = sample_type & PERF_SAMPLE_MASK; int size = 0; @@ -53,6 +53,7 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->attr = *attr; INIT_LIST_HEAD(&evsel->node); hists__init(&evsel->hists); + evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); } struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 67cc5033d192..894bd77d90cc 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -65,6 +65,7 @@ struct perf_evsel { void *func; void *data; } handler; + unsigned int sample_size; bool supported; }; @@ -177,13 +178,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } -int __perf_evsel__sample_size(u64 sample_type); - -static inline int perf_evsel__sample_size(struct perf_evsel *evsel) -{ - return __perf_evsel__sample_size(evsel->attr.sample_type); -} - void hists__init(struct hists *hists); #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index e03b58a48424..b0d6f85e30f1 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -806,7 +806,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, first = list_entry(evlist->entries.next, struct perf_evsel, node); err = perf_event__parse_sample(event, first->attr.sample_type, - perf_evsel__sample_size(first), + first->sample_size, sample_id_all, &pevent->sample, false); if (err) return PyErr_Format(PyExc_OSError, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8e4f0755d2aa..b8da60d1ecb5 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -16,6 +16,19 @@ #include "cpumap.h" #include "event-parse.h" +int perf_session__parse_sample(struct perf_session *session, + const union perf_event *event, + struct perf_sample *sample) +{ + struct perf_evsel *first; + first = list_entry(session->evlist->entries.next, struct perf_evsel, node); + + return perf_event__parse_sample(event, session->sample_type, + first->sample_size, + session->sample_id_all, sample, + session->header.needs_swap); +} + static int perf_session__open(struct perf_session *self, bool force) { struct stat input_stat; @@ -83,7 +96,6 @@ out_close: void perf_session__update_sample_type(struct perf_session *self) { self->sample_type = perf_evlist__sample_type(self->evlist); - self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); self->host_machine.id_hdr_size = self->id_hdr_size; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7c435bde6eb0..4d549e28248f 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -42,7 +42,6 @@ struct perf_session { */ struct hists hists; u64 sample_type; - int sample_size; int fd; bool fd_pipe; bool repipe; @@ -130,15 +129,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); -static inline int perf_session__parse_sample(struct perf_session *session, - const union perf_event *event, - struct perf_sample *sample) -{ - return perf_event__parse_sample(event, session->sample_type, - session->sample_size, - session->sample_id_all, sample, - session->header.needs_swap); -} +int perf_session__parse_sample(struct perf_session *session, + const union perf_event *event, + struct perf_sample *sample); static inline int perf_session__synthesize_sample(struct perf_session *session, union perf_event *event, -- GitLab From 7f3be652c1a8866251bfba9ea8b02067328f5db9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 1 Aug 2012 19:15:52 -0300 Subject: [PATCH 5016/5711] perf session: Use perf_evlist__sample_type more extensively Removing perf_session->sample_type, as it can be obtained from the evsel/evlist. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-mnt1zwlik7sp7z6ljc9kyefg@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 5 +++-- tools/perf/builtin-test.c | 10 ++-------- tools/perf/util/session.c | 31 ++++++++++++++++++++++--------- tools/perf/util/session.h | 11 +++-------- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 69b1c1185159..7c88a243b5db 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -249,8 +249,9 @@ static int process_read_event(struct perf_tool *tool, static int perf_report__setup_sample_type(struct perf_report *rep) { struct perf_session *self = rep->session; + u64 sample_type = perf_evlist__sample_type(self->evlist); - if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { + if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { if (sort__has_parent) { ui__error("Selected --sort parent, but no " "callchain data. Did you call " @@ -274,7 +275,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep) if (sort__branch_mode == 1) { if (!self->fd_pipe && - !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { + !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { ui__error("Selected -b but no branch data. " "Did you call perf record without -b?\n"); return -1; diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 2ea5fe4cc940..e5032ed2f259 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -661,7 +661,7 @@ static int test__PERF_RECORD(void) const char *cmd = "sleep"; const char *argv[] = { cmd, "1", NULL, }; char *bname; - u64 sample_type, prev_time = 0; + u64 prev_time = 0; bool found_cmd_mmap = false, found_libc_mmap = false, found_vdso_mmap = false, @@ -756,12 +756,6 @@ static int test__PERF_RECORD(void) goto out_delete_evlist; } - /* - * We'll need these two to parse the PERF_SAMPLE_* fields in each - * event. - */ - sample_type = perf_evlist__sample_type(evlist); - /* * Now that all is properly set up, enable the events, they will * count just on workload.pid, which will start... @@ -787,7 +781,7 @@ static int test__PERF_RECORD(void) if (type < PERF_RECORD_MAX) nr_events[type]++; - err = perf_event__parse_sample(event, sample_type, + err = perf_event__parse_sample(event, evsel->attr.sample_type, evsel->sample_size, true, &sample, false); if (err < 0) { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b8da60d1ecb5..00e180e116e7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -23,12 +23,20 @@ int perf_session__parse_sample(struct perf_session *session, struct perf_evsel *first; first = list_entry(session->evlist->entries.next, struct perf_evsel, node); - return perf_event__parse_sample(event, session->sample_type, + return perf_event__parse_sample(event, first->attr.sample_type, first->sample_size, session->sample_id_all, sample, session->header.needs_swap); } +int perf_session__synthesize_sample(struct perf_session *session, + union perf_event *event, + const struct perf_sample *sample) +{ + return perf_event__synthesize_sample(event, perf_evlist__sample_type(session->evlist), + sample, session->header.needs_swap); +} + static int perf_session__open(struct perf_session *self, bool force) { struct stat input_stat; @@ -95,7 +103,6 @@ out_close: void perf_session__update_sample_type(struct perf_session *self) { - self->sample_type = perf_evlist__sample_type(self->evlist); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); self->host_machine.id_hdr_size = self->id_hdr_size; @@ -877,16 +884,18 @@ static void perf_session__print_tstamp(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { + u64 sample_type = perf_evlist__sample_type(session->evlist); + if (event->header.type != PERF_RECORD_SAMPLE && !session->sample_id_all) { fputs("-1 -1 ", stdout); return; } - if ((session->sample_type & PERF_SAMPLE_CPU)) + if ((sample_type & PERF_SAMPLE_CPU)) printf("%u ", sample->cpu); - if (session->sample_type & PERF_SAMPLE_TIME) + if (sample_type & PERF_SAMPLE_TIME) printf("%" PRIu64 " ", sample->time); } @@ -911,6 +920,8 @@ static void dump_event(struct perf_session *session, union perf_event *event, static void dump_sample(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { + u64 sample_type; + if (!dump_trace) return; @@ -918,10 +929,12 @@ static void dump_sample(struct perf_session *session, union perf_event *event, event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); - if (session->sample_type & PERF_SAMPLE_CALLCHAIN) + sample_type = perf_evlist__sample_type(session->evlist); + + if (sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(sample); - if (session->sample_type & PERF_SAMPLE_BRANCH_STACK) + if (sample_type & PERF_SAMPLE_BRANCH_STACK) branch_stack__printf(sample); } @@ -1018,7 +1031,7 @@ static int perf_session__preprocess_sample(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { if (event->header.type != PERF_RECORD_SAMPLE || - !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) + !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN)) return 0; if (!ip_callchain__valid(sample->callchain, event)) { @@ -1401,9 +1414,9 @@ int perf_session__process_events(struct perf_session *self, return err; } -bool perf_session__has_traces(struct perf_session *self, const char *msg) +bool perf_session__has_traces(struct perf_session *session, const char *msg) { - if (!(self->sample_type & PERF_SAMPLE_RAW)) { + if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) { pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); return false; } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 4d549e28248f..c45ce4348b83 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -41,7 +41,6 @@ struct perf_session { * perf.data file. */ struct hists hists; - u64 sample_type; int fd; bool fd_pipe; bool repipe; @@ -133,13 +132,9 @@ int perf_session__parse_sample(struct perf_session *session, const union perf_event *event, struct perf_sample *sample); -static inline int perf_session__synthesize_sample(struct perf_session *session, - union perf_event *event, - const struct perf_sample *sample) -{ - return perf_event__synthesize_sample(event, session->sample_type, - sample, session->header.needs_swap); -} +int perf_session__synthesize_sample(struct perf_session *session, + union perf_event *event, + const struct perf_sample *sample); struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -- GitLab From 5e5624745d7e4a2c956c072ef2542872955b59c4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 1 Aug 2012 19:25:26 -0300 Subject: [PATCH 5017/5711] perf session: Use perf_evlist__sample_id_all more extensively Removing perf_session->sample_id_all, as it can be obtained from the evsel/evlist. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ok58u1mlc5ci9b6p36r52uh1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 9 ++++----- tools/perf/util/session.h | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 00e180e116e7..348cc11385b7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -25,7 +25,7 @@ int perf_session__parse_sample(struct perf_session *session, return perf_event__parse_sample(event, first->attr.sample_type, first->sample_size, - session->sample_id_all, sample, + first->attr.sample_id_all, sample, session->header.needs_swap); } @@ -103,7 +103,6 @@ out_close: void perf_session__update_sample_type(struct perf_session *self) { - self->sample_id_all = perf_evlist__sample_id_all(self->evlist); self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); self->host_machine.id_hdr_size = self->id_hdr_size; machines__set_id_hdr_size(&self->machines, self->id_hdr_size); @@ -177,7 +176,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, } if (tool && tool->ordering_requires_timestamps && - tool->ordered_samples && !self->sample_id_all) { + tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } @@ -887,7 +886,7 @@ static void perf_session__print_tstamp(struct perf_session *session, u64 sample_type = perf_evlist__sample_type(session->evlist); if (event->header.type != PERF_RECORD_SAMPLE && - !session->sample_id_all) { + !perf_evlist__sample_id_all(session->evlist)) { fputs("-1 -1 ", stdout); return; } @@ -1090,7 +1089,7 @@ static int perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, session->sample_id_all); + event_swap(event, perf_evlist__sample_id_all(session->evlist)); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index c45ce4348b83..a2c3ce9e716d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -44,7 +44,6 @@ struct perf_session { int fd; bool fd_pipe; bool repipe; - bool sample_id_all; u16 id_hdr_size; int cwdlen; char *cwd; -- GitLab From 1bfa2317b21750f739b59ab6df2c8efb12875045 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 May 2012 00:18:33 -0400 Subject: [PATCH 5018/5711] um: split syscall_trace(), pass pt_regs to it Signed-off-by: Al Viro [richard@nod.at: Fixed some minor build issues] Signed-off-by: Richard Weinberger --- arch/um/include/asm/ptrace-generic.h | 2 + arch/um/kernel/ptrace.c | 71 ++++++++++++---------------- arch/um/kernel/skas/syscall.c | 4 +- 3 files changed, 34 insertions(+), 43 deletions(-) diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index e786a6a3ec5e..442f1d025dc2 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -37,6 +37,8 @@ extern int putreg(struct task_struct *child, int regno, unsigned long value); extern int arch_copy_tls(struct task_struct *new); extern void clear_flushed_tls(struct task_struct *task); +extern void syscall_trace_enter(struct pt_regs *regs); +extern void syscall_trace_leave(struct pt_regs *regs); #endif diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 06b190390505..694d551c8899 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -3,11 +3,12 @@ * Licensed under the GPL */ -#include "linux/audit.h" -#include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "skas_ptrace.h" +#include +#include +#include +#include +#include +#include @@ -162,48 +163,36 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check */ -void syscall_trace(struct uml_pt_regs *regs, int entryexit) +void syscall_trace_enter(struct pt_regs *regs) { - int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; - int tracesysgood; - - if (!entryexit) - audit_syscall_entry(HOST_AUDIT_ARCH, - UPT_SYSCALL_NR(regs), - UPT_SYSCALL_ARG1(regs), - UPT_SYSCALL_ARG2(regs), - UPT_SYSCALL_ARG3(regs), - UPT_SYSCALL_ARG4(regs)); - else - audit_syscall_exit(regs); - - /* Fake a debug trap */ - if (is_singlestep) - send_sigtrap(current, regs, 0); + audit_syscall_entry(HOST_AUDIT_ARCH, + UPT_SYSCALL_NR(®s->regs), + UPT_SYSCALL_ARG1(®s->regs), + UPT_SYSCALL_ARG2(®s->regs), + UPT_SYSCALL_ARG3(®s->regs), + UPT_SYSCALL_ARG4(®s->regs)); if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; - if (!(current->ptrace & PT_PTRACED)) - return; + tracehook_report_syscall_entry(regs); +} - /* - * the 0x80 provides a way for the tracing parent to distinguish - * between a syscall stop and SIGTRAP delivery - */ - tracesysgood = (current->ptrace & PT_TRACESYSGOOD); - ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); +void syscall_trace_leave(struct pt_regs *regs) +{ + int ptraced = current->ptrace; - if (entryexit) /* force do_signal() --> is_syscall() */ - set_thread_flag(TIF_SIGPENDING); + audit_syscall_exit(regs); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } + /* Fake a debug trap */ + if (ptraced & PT_DTRACE) + send_sigtrap(current, ®s->regs, 0); + + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + + tracehook_report_syscall_exit(regs, 0); + /* force do_signal() --> is_syscall() */ + if (ptraced & PT_PTRACED) + set_thread_flag(TIF_SIGPENDING); } diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 800551a29dbf..86368a025a96 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -18,7 +18,7 @@ void handle_syscall(struct uml_pt_regs *r) long result; int syscall; - syscall_trace(r, 0); + syscall_trace_enter(regs); /* * This should go in the declaration of syscall, but when I do that, @@ -36,5 +36,5 @@ void handle_syscall(struct uml_pt_regs *r) PT_REGS_SET_SYSCALL_RETURN(regs, result); - syscall_trace(r, 1); + syscall_trace_leave(regs); } -- GitLab From b8a420952336ed81ef5c9bf8bad90d3deaee5521 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 May 2012 00:25:15 -0400 Subject: [PATCH 5019/5711] um: pull interrupt_end() into userspace() Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/kernel/process.c | 11 +++-------- arch/um/os-Linux/skas/process.c | 3 +++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index f19ca6152460..57fc7028714a 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -151,12 +151,10 @@ void new_thread_handler(void) * 0 if it just exits */ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if (n == 1) { - /* Handle any immediate reschedules or signals */ - interrupt_end(); + if (n == 1) userspace(¤t->thread.regs.regs); - } - else do_exit(0); + else + do_exit(0); } /* Called magically, see new_thread_handler above */ @@ -175,9 +173,6 @@ void fork_handler(void) current->thread.prev_sched = NULL; - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index cd65727854eb..2687f1f3a709 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -347,6 +347,9 @@ void userspace(struct uml_pt_regs *regs) /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + /* Handle any immediate reschedules or signals */ + interrupt_end(); + if (getitimer(ITIMER_VIRTUAL, &timer)) printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + -- GitLab From 7b56cce27123ccbf2cb82febbbc88443d719f1f8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 1 Aug 2012 19:31:00 -0300 Subject: [PATCH 5020/5711] perf session: Use perf_evlist__id_hdr_size more extensively Removing perf_session->id_hdr_size, as it can be obtained from the evsel/evlist. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-1nwc2kslu7gsfblu98xbqbll@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/session.c | 13 +++++++------ tools/perf/util/session.h | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f5a6452931e6..dc2b62565aa1 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -313,7 +313,7 @@ try_again: } } - perf_session__update_sample_type(session); + perf_session__set_id_hdr_size(session); } static int process_buildids(struct perf_record *rec) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 35e86c6df713..520e4256fc66 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1032,7 +1032,7 @@ static int __cmd_top(struct perf_top *top) &top->session->host_machine); perf_top__start_counters(top); top->session->evlist = top->evlist; - perf_session__update_sample_type(top->session); + perf_session__set_id_hdr_size(top->session); /* Wait for a minimal set of events before starting the snapshot */ poll(top->evlist->pollfd, top->evlist->nr_fds, 100); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 348cc11385b7..5b8601df2392 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -101,11 +101,12 @@ out_close: return -1; } -void perf_session__update_sample_type(struct perf_session *self) +void perf_session__set_id_hdr_size(struct perf_session *session) { - self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); - self->host_machine.id_hdr_size = self->id_hdr_size; - machines__set_id_hdr_size(&self->machines, self->id_hdr_size); + u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); + + session->host_machine.id_hdr_size = id_hdr_size; + machines__set_id_hdr_size(&session->machines, id_hdr_size); } int perf_session__create_kernel_maps(struct perf_session *self) @@ -165,7 +166,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; - perf_session__update_sample_type(self); + perf_session__set_id_hdr_size(self); } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the @@ -1054,7 +1055,7 @@ static int perf_session__process_user_event(struct perf_session *session, union case PERF_RECORD_HEADER_ATTR: err = tool->attr(event, &session->evlist); if (err == 0) - perf_session__update_sample_type(session); + perf_session__set_id_hdr_size(session); return err; case PERF_RECORD_HEADER_EVENT_TYPE: return tool->event_type(tool, event); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index a2c3ce9e716d..e2a1a4b7b236 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -44,7 +44,6 @@ struct perf_session { int fd; bool fd_pipe; bool repipe; - u16 id_hdr_size; int cwdlen; char *cwd; struct ordered_samples ordered_samples; @@ -83,7 +82,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr); int perf_session__create_kernel_maps(struct perf_session *self); -void perf_session__update_sample_type(struct perf_session *self); +void perf_session__set_id_hdr_size(struct perf_session *session); void perf_session__remove_thread(struct perf_session *self, struct thread *th); static inline -- GitLab From 8811b5968f6216e97ccb9fe7b9883af39e339921 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 2 Aug 2012 08:33:00 +1000 Subject: [PATCH 5021/5711] raid5: make_request use batch stripe release make_request() does stripe release for every stripe and the stripe usually has count 1, which makes previous release_stripe() optimization not work. In my test, this release_stripe() becomes the heaviest pleace to take conf->device_lock after previous patches applied. Below patch makes stripe release batch. All the stripes will be released in unplug. The STRIPE_ON_UNPLUG_LIST bit is to protect concurrent access stripe lru. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid5.c | 62 +++++++++++++++++++++++++++++++++++++++++++--- drivers/md/raid5.h | 1 + 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index bde9da2baa39..978ba9b7a3c4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -471,7 +471,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector, } else { if (atomic_read(&sh->count)) { BUG_ON(!list_empty(&sh->lru) - && !test_bit(STRIPE_EXPANDING, &sh->state)); + && !test_bit(STRIPE_EXPANDING, &sh->state) + && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state)); } else { if (!test_bit(STRIPE_HANDLE, &sh->state)) atomic_inc(&conf->active_stripes); @@ -3988,6 +3989,62 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf) return sh; } +struct raid5_plug_cb { + struct blk_plug_cb cb; + struct list_head list; +}; + +static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule) +{ + struct raid5_plug_cb *cb = container_of( + blk_cb, struct raid5_plug_cb, cb); + struct stripe_head *sh; + struct mddev *mddev = cb->cb.data; + struct r5conf *conf = mddev->private; + + if (cb->list.next && !list_empty(&cb->list)) { + spin_lock_irq(&conf->device_lock); + while (!list_empty(&cb->list)) { + sh = list_first_entry(&cb->list, struct stripe_head, lru); + list_del_init(&sh->lru); + /* + * avoid race release_stripe_plug() sees + * STRIPE_ON_UNPLUG_LIST clear but the stripe + * is still in our list + */ + smp_mb__before_clear_bit(); + clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state); + __release_stripe(conf, sh); + } + spin_unlock_irq(&conf->device_lock); + } + kfree(cb); +} + +static void release_stripe_plug(struct mddev *mddev, + struct stripe_head *sh) +{ + struct blk_plug_cb *blk_cb = blk_check_plugged( + raid5_unplug, mddev, + sizeof(struct raid5_plug_cb)); + struct raid5_plug_cb *cb; + + if (!blk_cb) { + release_stripe(sh); + return; + } + + cb = container_of(blk_cb, struct raid5_plug_cb, cb); + + if (cb->list.next == NULL) + INIT_LIST_HEAD(&cb->list); + + if (!test_and_set_bit(STRIPE_ON_UNPLUG_LIST, &sh->state)) + list_add_tail(&sh->lru, &cb->list); + else + release_stripe(sh); +} + static void make_request(struct mddev *mddev, struct bio * bi) { struct r5conf *conf = mddev->private; @@ -4116,8 +4173,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) if ((bi->bi_rw & REQ_SYNC) && !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) atomic_inc(&conf->preread_active_stripes); - mddev_check_plugged(mddev); - release_stripe(sh); + release_stripe_plug(mddev, sh); } else { /* cannot get stripe for read-ahead, just give-up */ clear_bit(BIO_UPTODATE, &bi->bi_flags); diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 2164021f3b5f..9a7b36f0a425 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -319,6 +319,7 @@ enum { STRIPE_BIOFILL_RUN, STRIPE_COMPUTE_RUN, STRIPE_OPS_REQ_PENDING, + STRIPE_ON_UNPLUG_LIST, }; /* -- GitLab From 46a06401f6ba13e59d24746fa9ffa6773b69eee3 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 2 Aug 2012 08:33:15 +1000 Subject: [PATCH 5022/5711] raid5: raid5d handle stripe in batch way Let raid5d handle stripe in batch way to reduce conf->device_lock locking. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid5.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 978ba9b7a3c4..9e41ae37bd40 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4574,6 +4574,30 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio) return handled; } +#define MAX_STRIPE_BATCH 8 +static int handle_active_stripes(struct r5conf *conf) +{ + struct stripe_head *batch[MAX_STRIPE_BATCH], *sh; + int i, batch_size = 0; + + while (batch_size < MAX_STRIPE_BATCH && + (sh = __get_priority_stripe(conf)) != NULL) + batch[batch_size++] = sh; + + if (batch_size == 0) + return batch_size; + spin_unlock_irq(&conf->device_lock); + + for (i = 0; i < batch_size; i++) + handle_stripe(batch[i]); + + cond_resched(); + + spin_lock_irq(&conf->device_lock); + for (i = 0; i < batch_size; i++) + __release_stripe(conf, batch[i]); + return batch_size; +} /* * This is our raid5 kernel thread. @@ -4584,7 +4608,6 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio) */ static void raid5d(struct mddev *mddev) { - struct stripe_head *sh; struct r5conf *conf = mddev->private; int handled; struct blk_plug plug; @@ -4598,6 +4621,7 @@ static void raid5d(struct mddev *mddev) spin_lock_irq(&conf->device_lock); while (1) { struct bio *bio; + int batch_size; if ( !list_empty(&conf->bitmap_list)) { @@ -4621,21 +4645,16 @@ static void raid5d(struct mddev *mddev) handled++; } - sh = __get_priority_stripe(conf); - - if (!sh) + batch_size = handle_active_stripes(conf); + if (!batch_size) break; - spin_unlock_irq(&conf->device_lock); - - handled++; - handle_stripe(sh); - release_stripe(sh); - cond_resched(); + handled += batch_size; - if (mddev->flags & ~(1<flags & ~(1<device_lock); md_check_recovery(mddev); - - spin_lock_irq(&conf->device_lock); + spin_lock_irq(&conf->device_lock); + } } pr_debug("%d stripes handled\n", handled); -- GitLab From f54a9d0e59c4bea3db733921ca9147612a6f292c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 2 Aug 2012 08:33:20 +1000 Subject: [PATCH 5023/5711] md/raid1: submit IO from originating thread instead of md thread. queuing writes to the md thread means that all requests go through the one processor which may not be able to keep up with very high request rates. So use the plugging infrastructure to submit all requests on unplug. If a 'schedule' is needed, we fall back on the old approach of handing the requests to the thread for it to handle. Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 2 +- drivers/md/raid1.c | 57 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 15dbe03117e4..94e7f6ba2e11 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1305,7 +1305,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect prepare_to_wait(&bitmap->overflow_wait, &__wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&bitmap->counts.lock); - io_schedule(); + schedule(); finish_wait(&bitmap->overflow_wait, &__wait); continue; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 36a8fc059ac3..9f01870d031c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -870,6 +870,44 @@ do_sync_io: pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size); } +struct raid1_plug_cb { + struct blk_plug_cb cb; + struct bio_list pending; + int pending_cnt; +}; + +static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) +{ + struct raid1_plug_cb *plug = container_of(cb, struct raid1_plug_cb, + cb); + struct mddev *mddev = plug->cb.data; + struct r1conf *conf = mddev->private; + struct bio *bio; + + if (from_schedule) { + spin_lock_irq(&conf->device_lock); + bio_list_merge(&conf->pending_bio_list, &plug->pending); + conf->pending_count += plug->pending_cnt; + spin_unlock_irq(&conf->device_lock); + md_wakeup_thread(mddev->thread); + kfree(plug); + return; + } + + /* we aren't scheduling, so we can do the write-out directly. */ + bio = bio_list_get(&plug->pending); + bitmap_unplug(mddev->bitmap); + wake_up(&conf->wait_barrier); + + while (bio) { /* submit pending writes */ + struct bio *next = bio->bi_next; + bio->bi_next = NULL; + generic_make_request(bio); + bio = next; + } + kfree(plug); +} + static void make_request(struct mddev *mddev, struct bio * bio) { struct r1conf *conf = mddev->private; @@ -883,6 +921,8 @@ static void make_request(struct mddev *mddev, struct bio * bio) const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); struct md_rdev *blocked_rdev; + struct blk_plug_cb *cb; + struct raid1_plug_cb *plug = NULL; int first_clone; int sectors_handled; int max_sectors; @@ -1185,11 +1225,22 @@ read_again: mbio->bi_private = r1_bio; atomic_inc(&r1_bio->remaining); + + cb = blk_check_plugged(raid1_unplug, mddev, sizeof(*plug)); + if (cb) + plug = container_of(cb, struct raid1_plug_cb, cb); + else + plug = NULL; spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; + if (plug) { + bio_list_add(&plug->pending, mbio); + plug->pending_cnt++; + } else { + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + } spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) + if (!plug) md_wakeup_thread(mddev->thread); } /* Mustn't call r1_bio_write_done before this next test, -- GitLab From d9f691c365a83ce2530f0e46b947365c2db44ea0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 2 Aug 2012 08:35:43 +1000 Subject: [PATCH 5024/5711] md/dm-raid: DM_RAID should select MD_RAID10 Now that DM_RAID supports raid10, it needs to select that code to ensure it is included. Cc: Jonathan Brassow Reported-by: Fengguang Wu Signed-off-by: NeilBrown --- drivers/md/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 10f122a3a856..1de441a6c55f 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -277,13 +277,14 @@ config DM_MIRROR needed for live data migration tools such as 'pvmove'. config DM_RAID - tristate "RAID 1/4/5/6 target" + tristate "RAID 1/4/5/6/10 target" depends on BLK_DEV_DM select MD_RAID1 + select MD_RAID10 select MD_RAID456 select BLK_DEV_MD ---help--- - A dm target that supports RAID1, RAID4, RAID5 and RAID6 mappings + A dm target that supports RAID1, RAID10, RAID4, RAID5 and RAID6 mappings A RAID-5 set of N drives with a capacity of C MB per drive provides the capacity of C * (N - 1) MB, and protects against a failure -- GitLab From d4afcba95fca4dd0f831fe72c1fa4f0638f23765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A4rtel?= Date: Thu, 2 Aug 2012 00:44:22 +0200 Subject: [PATCH 5025/5711] um: fix ubd_file_size for read-only files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made ubd_file_size not request write access. Fixes use of read-only images. Signed-off-by: Martin Pärtel Signed-off-by: Richard Weinberger --- arch/um/drivers/ubd_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 20505cafa299..0643e5bc9f41 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -514,7 +514,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) goto out; } - fd = os_open_file(ubd_dev->file, global_openflags, 0); + fd = os_open_file(ubd_dev->file, of_read(OPENFLAGS()), 0); if (fd < 0) return fd; -- GitLab From d3c1cfcdb43e023ab1b1c7a555cd9e929026500a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A4rtel?= Date: Thu, 2 Aug 2012 00:49:17 +0200 Subject: [PATCH 5026/5711] um: pass siginfo to guest process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct where previously they were si_addr = NULL and si_code = 128. Signed-off-by: Martin Pärtel Signed-off-by: Richard Weinberger --- arch/um/include/shared/as-layout.h | 3 ++- arch/um/include/shared/irq_user.h | 3 ++- arch/um/include/shared/kern_util.h | 13 +++++----- arch/um/kernel/irq.c | 2 +- arch/um/kernel/time.c | 2 +- arch/um/kernel/trap.c | 39 ++++++++++++++++++++++++------ arch/um/os-Linux/internal.h | 2 +- arch/um/os-Linux/signal.c | 26 +++++++++++--------- arch/um/os-Linux/skas/process.c | 13 +++++++--- arch/um/os-Linux/time.c | 2 +- 10 files changed, 71 insertions(+), 34 deletions(-) diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index 896e16602176..86daa5461815 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h @@ -60,7 +60,8 @@ extern unsigned long host_task_size; extern int linux_main(int argc, char **argv); -extern void (*sig_info[])(int, struct uml_pt_regs *); +struct siginfo; +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); #endif diff --git a/arch/um/include/shared/irq_user.h b/arch/um/include/shared/irq_user.h index c6c784df2673..2b6d703925b5 100644 --- a/arch/um/include/shared/irq_user.h +++ b/arch/um/include/shared/irq_user.h @@ -20,7 +20,8 @@ struct irq_fd { enum { IRQ_READ, IRQ_WRITE }; -extern void sigio_handler(int sig, struct uml_pt_regs *regs); +struct siginfo; +extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void free_irq_by_fd(int fd); extern void reactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum); diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h index 00965d06d2ca..af6b6dc868ba 100644 --- a/arch/um/include/shared/kern_util.h +++ b/arch/um/include/shared/kern_util.h @@ -9,6 +9,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +struct siginfo; + extern int uml_exitcode; extern int ncpus; @@ -22,7 +24,7 @@ extern void free_stack(unsigned long stack, int order); extern int do_signal(void); extern void interrupt_end(void); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); @@ -33,9 +35,8 @@ extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); extern int smp_sigio_handler(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); -extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern void timer_handler(int sig, struct uml_pt_regs *regs); +extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern int start_uml(void); extern void paging_init(void); @@ -59,9 +60,9 @@ extern unsigned long from_irq_stack(int nested); extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); extern int singlestepping(void *t); -extern void segv_handler(int sig, struct uml_pt_regs *regs); -extern void bus_handler(int sig, struct uml_pt_regs *regs); -extern void winch(int sig, struct uml_pt_regs *regs); +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 00506c3d5d6e..9883026f0730 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; extern void free_irqs(void); -void sigio_handler(int sig, struct uml_pt_regs *regs) +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct irq_fd *irq_fd; int n; diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index d1a23fb3190d..5f76d4ba151c 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -13,7 +13,7 @@ #include "kern_util.h" #include "os.h" -void timer_handler(int sig, struct uml_pt_regs *regs) +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { unsigned long flags; diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 3be60765c0e2..0353b98ae35a 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -172,7 +172,7 @@ void fatal_sigsegv(void) os_dump_core(); } -void segv_handler(int sig, struct uml_pt_regs *regs) +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -258,8 +258,11 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) { + struct faultinfo *fi; + struct siginfo clean_si; + if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -269,18 +272,40 @@ void relay_signal(int sig, struct uml_pt_regs *regs) arch_examine_signal(sig, regs); - current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); - force_sig(sig, current); + memset(&clean_si, 0, sizeof(clean_si)); + clean_si.si_signo = si->si_signo; + clean_si.si_errno = si->si_errno; + clean_si.si_code = si->si_code; + switch (sig) { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + fi = UPT_FAULTINFO(regs); + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); + current->thread.arch.faultinfo = *fi; +#ifdef __ARCH_SI_TRAPNO + clean_si.si_trapno = si->si_trapno; +#endif + break; + default: + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", + sig, si->si_code); + } + + force_sig_info(sig, &clean_si, current); } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); - else relay_signal(sig, regs); + else + relay_signal(sig, si, regs); } -void winch(int sig, struct uml_pt_regs *regs) +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } diff --git a/arch/um/os-Linux/internal.h b/arch/um/os-Linux/internal.h index 2c3c3ecd8c01..0dc2c9f135f6 100644 --- a/arch/um/os-Linux/internal.h +++ b/arch/um/os-Linux/internal.h @@ -1 +1 @@ -void alarm_handler(int, mcontext_t *); +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc); diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 2d22f1fcd8e2..6366ce904b9b 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -13,8 +13,9 @@ #include "kern_util.h" #include "os.h" #include "sysdep/mcontext.h" +#include "internal.h" -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, @@ -24,7 +25,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { [SIGIO] = sigio_handler, [SIGVTALRM] = timer_handler }; -static void sig_handler_common(int sig, mcontext_t *mc) +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -40,7 +41,7 @@ static void sig_handler_common(int sig, mcontext_t *mc) if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); - (*sig_info[sig])(sig, &r); + (*sig_info[sig])(sig, si, &r); errno = save_errno; } @@ -60,7 +61,7 @@ static void sig_handler_common(int sig, mcontext_t *mc) static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, mcontext_t *mc) +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) { int enabled; @@ -72,7 +73,7 @@ void sig_handler(int sig, mcontext_t *mc) block_signals(); - sig_handler_common(sig, mc); + sig_handler_common(sig, si, mc); set_signals(enabled); } @@ -85,10 +86,10 @@ static void real_alarm_handler(mcontext_t *mc) get_regs_from_mc(®s, mc); regs.is_user = 0; unblock_signals(); - timer_handler(SIGVTALRM, ®s); + timer_handler(SIGVTALRM, NULL, ®s); } -void alarm_handler(int sig, mcontext_t *mc) +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) { int enabled; @@ -119,7 +120,7 @@ void set_sigstack(void *sig_stack, int size) panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { [SIGSEGV] = sig_handler, [SIGBUS] = sig_handler, [SIGILL] = sig_handler, @@ -132,7 +133,7 @@ static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { }; -static void hard_handler(int sig, siginfo_t *info, void *p) +static void hard_handler(int sig, siginfo_t *si, void *p) { struct ucontext *uc = p; mcontext_t *mc = &uc->uc_mcontext; @@ -161,7 +162,7 @@ static void hard_handler(int sig, siginfo_t *info, void *p) while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, mc); + (*handlers[sig])(sig, si, mc); } /* @@ -273,9 +274,12 @@ void unblock_signals(void) * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. + * + * SIGIO's handler doesn't use siginfo or mcontext, + * so they can be NULL. */ if (save_pending & SIGIO_MASK) - sig_handler_common(SIGIO, NULL); + sig_handler_common(SIGIO, NULL, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 2687f1f3a709..d93bb40499f7 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -346,6 +346,7 @@ void userspace(struct uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + siginfo_t si; /* Handle any immediate reschedules or signals */ interrupt_end(); @@ -407,13 +408,17 @@ void userspace(struct uml_pt_regs *regs) if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); + + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); + switch (sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, regs); + (*sig_info[SIGSEGV])(SIGSEGV, &si, + regs); } else handle_segv(pid, regs); break; @@ -421,14 +426,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, regs); + relay_signal(SIGTRAP, &si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -442,7 +447,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); break; default: diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 910499d76a67..f60238559af3 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -87,7 +87,7 @@ static int after_sleep_interval(struct timespec *ts) static void deliver_alarm(void) { - alarm_handler(SIGVTALRM, NULL); + alarm_handler(SIGVTALRM, NULL, NULL); } static unsigned long long sleep_time(unsigned long long nsecs) -- GitLab From b070989aeb47ccdfe56d95e046bd317baa47f4fa Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 2 Aug 2012 01:00:47 +0200 Subject: [PATCH 5027/5711] um: Add arch/x86/um to MAINTAINERS Signed-off-by: Richard Weinberger --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index fe643e7b9df6..f13d107f9b1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7305,6 +7305,7 @@ W: http://user-mode-linux.sourceforge.net S: Maintained F: Documentation/virtual/uml/ F: arch/um/ +F: arch/x86/um/ F: fs/hostfs/ F: fs/hppfs/ -- GitLab From eaf4ce6c5fed6b4c55f7efcd5fc3477435cab5e9 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 1 Aug 2012 15:59:58 -0700 Subject: [PATCH 5028/5711] x86-64, kcmp: The kcmp system call can be common We already use the same system call handler for i386 and x86-64, there is absolutely no reason x32 can't use the same system call, too. Signed-off-by: H. Peter Anvin Cc: H.J. Lu Cc: Cyrill Gorcunov Cc: v3.5 Link: http://lkml.kernel.org/n/tip-vwzk3qbcr3yjyxjg2j38vgy9@git.kernel.org --- arch/x86/syscalls/syscall_64.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 51171aeff0dc..29aed7ac2c02 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -318,7 +318,7 @@ 309 common getcpu sys_getcpu 310 64 process_vm_readv sys_process_vm_readv 311 64 process_vm_writev sys_process_vm_writev -312 64 kcmp sys_kcmp +312 common kcmp sys_kcmp # # x32-specific system call numbers start at 512 to avoid cache impact -- GitLab From aa67f6096c19bcdb1951ef88be3cf3d2118809dc Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 1 Aug 2012 16:48:03 +0300 Subject: [PATCH 5029/5711] KVM: VMX: Fix ds/es corruption on i386 with preemption Commit b2da15ac26a0c ("KVM: VMX: Optimize %ds, %es reload") broke i386 in the following scenario: vcpu_load ... vmx_save_host_state vmx_vcpu_run (ds.rpl, es.rpl cleared by hardware) interrupt push ds, es # pushes bad ds, es schedule vmx_vcpu_put vmx_load_host_state reload ds, es (with __USER_DS) pop ds, es # of other thread's stack iret # other thread runs interrupt push ds, es schedule # back in vcpu thread pop ds, es # now with rpl=0 iret ... vcpu_put resume_userspace iret # clears ds, es due to mismatched rpl (instead of resume_userspace, we might return with SYSEXIT and then take an exception; when the exception IRETs we end up with cleared ds, es) Fix by avoiding the optimization on i386 and reloading ds, es on the lightweight exit path. Reported-by: Chris Clayron Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/vmx.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c39b60707e02..c00f03de1b79 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1488,13 +1488,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) loadsegment(ds, vmx->host_state.ds_sel); loadsegment(es, vmx->host_state.es_sel); } -#else - /* - * The sysexit path does not restore ds/es, so we must set them to - * a reasonable value ourselves. - */ - loadsegment(ds, __USER_DS); - loadsegment(es, __USER_DS); #endif reload_tss(); #ifdef CONFIG_X86_64 @@ -6370,6 +6363,19 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) #endif ); +#ifndef CONFIG_X86_64 + /* + * The sysexit path does not restore ds/es, so we must set them to + * a reasonable value ourselves. + * + * We can't defer this to vmx_load_host_state() since that function + * may be executed in interrupt context, which saves and restore segments + * around it, nullifying its effect. + */ + loadsegment(ds, __USER_DS); + loadsegment(es, __USER_DS); +#endif + vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP) | (1 << VCPU_EXREG_RFLAGS) | (1 << VCPU_EXREG_CPL) -- GitLab From 08298f0612e5e369d1da89b92cac5d2c71ddb9af Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 1 Aug 2012 10:44:57 +0200 Subject: [PATCH 5030/5711] sh: explicitly include sh_dma.h in setup-sh7722.c setup-sh7722.c defines several objects, whose types are defined in sh_dma.h, so, it has to be included explicitly. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 65786c7f5ded..6a868b091c2d 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include -- GitLab From 707fba3fa76a4c8855552f5d4c1a12430c09bce8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 2 Aug 2012 09:04:39 +0200 Subject: [PATCH 5031/5711] ALSA: hda - Support dock on Lenovo Thinkpad T530 with ALC269VC Lenovo Thinkpad T530 with ALC269VC codec has a dock port but BIOS doesn't set up the pins properly. Enable the pins as well as on Thinkpad X230 Tablet. Reported-and-tested-by: Mario Cc: [v3.2+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 344b221d2102..b9a5c4503336 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6206,6 +6206,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), -- GitLab From 30b678d844af3305cda5953467005cebb5d7b687 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 15:57:00 +0000 Subject: [PATCH 5032/5711] net: Allow driver to limit number of GSO segments per skb A peer (or local user) may cause TCP to use a nominal MSS of as little as 88 (actual MSS of 76 with timestamps). Given that we have a sufficiently prodigious local sender and the peer ACKs quickly enough, it is nevertheless possible to grow the window for such a connection to the point that we will try to send just under 64K at once. This results in a single skb that expands to 861 segments. In some drivers with TSO support, such an skb will require hundreds of DMA descriptors; a substantial fraction of a TX ring or even more than a full ring. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This particularly affects sfc, for which the issue is designated as CVE-2012-3412. Therefore: 1. Add the field net_device::gso_max_segs holding the device-specific limit. 2. In netif_skb_features(), if the number of segments is too high then mask out GSO features to force fall back to software GSO. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index eb06e58bed0b..a9db4f33407f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1300,6 +1300,8 @@ struct net_device { /* for setting kernel sock attribute on TCP connection setup */ #define GSO_MAX_SIZE 65536 unsigned int gso_max_size; +#define GSO_MAX_SEGS 65535 + u16 gso_max_segs; #ifdef CONFIG_DCB /* Data Center Bridging netlink ops */ diff --git a/net/core/dev.c b/net/core/dev.c index 0cb3fe8d8e72..f91abf800161 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2134,6 +2134,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) __be16 protocol = skb->protocol; netdev_features_t features = skb->dev->features; + if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) + features &= ~NETIF_F_GSO_MASK; + if (protocol == htons(ETH_P_8021Q)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; @@ -5986,6 +5989,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev_net_set(dev, &init_net); dev->gso_max_size = GSO_MAX_SIZE; + dev->gso_max_segs = GSO_MAX_SEGS; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); -- GitLab From 7e6d06f0de3f74ca929441add094518ae332257c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 15:57:44 +0000 Subject: [PATCH 5033/5711] sfc: Fix maximum number of TSO segments and minimum TX queue size Currently an skb requiring TSO may not fit within a minimum-size TX queue. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This issue is designated as CVE-2012-3412. Set the maximum number of TSO segments for our devices to 100. This should make no difference to behaviour unless the actual MSS is less than about 700. Increase the minimum TX queue size accordingly to allow for 2 worst-case skbs, so that there will definitely be space to add an skb after we wake a queue. To avoid invalidating existing configurations, change efx_ethtool_set_ringparam() to fix up values that are too small rather than returning -EINVAL. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 6 ++++++ drivers/net/ethernet/sfc/efx.h | 14 ++++++++++---- drivers/net/ethernet/sfc/ethtool.c | 16 +++++++++++----- drivers/net/ethernet/sfc/tx.c | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 70554a1b2b02..65a8d49106a4 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1503,6 +1503,11 @@ static int efx_probe_all(struct efx_nic *efx) goto fail2; } + BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); + if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { + rc = -EINVAL; + goto fail3; + } efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; rc = efx_probe_filters(efx); @@ -2070,6 +2075,7 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->irq = efx->pci_dev->irq; net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); + net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; rtnl_lock(); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index be8f9158a714..70755c97251a 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -30,6 +30,7 @@ extern netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); +extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); /* RX */ extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_EVQ_SIZE 16384UL #define EFX_MIN_EVQ_SIZE 512UL -/* The smallest [rt]xq_entries that the driver supports. Callers of - * efx_wake_queue() assume that they can subsequently send at least one - * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ -#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) +/* Maximum number of TCP segments we support for soft-TSO */ +#define EFX_TSO_MAX_SEGS 100 + +/* The smallest [rt]xq_entries that the driver supports. RX minimum + * is a bit arbitrary. For TX, we must have space for at least 2 + * TSO skbs. + */ +#define EFX_RXQ_MIN_ENT 128U +#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) /* Filters */ extern int efx_probe_filters(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 10536f93b561..8cba2df82b18 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, struct ethtool_ringparam *ring) { struct efx_nic *efx = netdev_priv(net_dev); + u32 txq_entries; if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->rx_pending > EFX_MAX_DMAQ_SIZE || ring->tx_pending > EFX_MAX_DMAQ_SIZE) return -EINVAL; - if (ring->rx_pending < EFX_MIN_RING_SIZE || - ring->tx_pending < EFX_MIN_RING_SIZE) { + if (ring->rx_pending < EFX_RXQ_MIN_ENT) { netif_err(efx, drv, efx->net_dev, - "TX and RX queues cannot be smaller than %ld\n", - EFX_MIN_RING_SIZE); + "RX queues cannot be smaller than %u\n", + EFX_RXQ_MIN_ENT); return -EINVAL; } - return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); + txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); + if (txq_entries != ring->tx_pending) + netif_warn(efx, drv, efx->net_dev, + "increasing TX queue size to minimum of %u\n", + txq_entries); + + return efx_realloc_channels(efx, ring->rx_pending, txq_entries); } static int efx_ethtool_set_pauseparam(struct net_device *net_dev, diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 9b225a7769f7..18713436b443 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) return len; } +unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) +{ + /* Header and payload descriptor for each output segment, plus + * one for every input fragment boundary within a segment + */ + unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; + + /* Possibly one more per segment for the alignment workaround */ + if (EFX_WORKAROUND_5391(efx)) + max_descs += EFX_TSO_MAX_SEGS; + + /* Possibly more for PCIe page boundaries within input fragments */ + if (PAGE_SIZE > EFX_PAGE_SIZE) + max_descs += max_t(unsigned int, MAX_SKB_FRAGS, + DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); + + return max_descs; +} + /* * Add a socket buffer to a TX queue * -- GitLab From 1485348d2424e1131ea42efc033cbd9366462b01 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 16:11:42 +0000 Subject: [PATCH 5034/5711] tcp: Apply device TSO segment limit earlier Cache the device gso_max_segs in sock::sk_gso_max_segs and use it to limit the size of TSO skbs. This avoids the need to fall back to software GSO for local TCP senders. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/net/sock.h | 2 ++ net/core/sock.c | 1 + net/ipv4/tcp.c | 4 +++- net/ipv4/tcp_cong.c | 3 ++- net/ipv4/tcp_output.c | 21 ++++++++++++--------- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index b3730239bf18..72132aef53fc 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -218,6 +218,7 @@ struct cg_proto; * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_gso_max_size: Maximum GSO segment size to build + * @sk_gso_max_segs: Maximum number of GSO segments * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct @@ -338,6 +339,7 @@ struct sock { netdev_features_t sk_route_nocaps; int sk_gso_type; unsigned int sk_gso_max_size; + u16 sk_gso_max_segs; int sk_rcvlowat; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; diff --git a/net/core/sock.c b/net/core/sock.c index 6b654b3ddfda..8f67ced8d6a8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1458,6 +1458,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) } else { sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; sk->sk_gso_max_size = dst->dev->gso_max_size; + sk->sk_gso_max_segs = dst->dev->gso_max_segs; } } } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e7e6eeae49c0..2109ff4a1daf 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -811,7 +811,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, old_size_goal + mss_now > xmit_size_goal)) { xmit_size_goal = old_size_goal; } else { - tp->xmit_size_goal_segs = xmit_size_goal / mss_now; + tp->xmit_size_goal_segs = + min_t(u16, xmit_size_goal / mss_now, + sk->sk_gso_max_segs); xmit_size_goal = tp->xmit_size_goal_segs * mss_now; } } diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 4d4db16e336e..1432cdb0644c 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -291,7 +291,8 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) left = tp->snd_cwnd - in_flight; if (sk_can_gso(sk) && left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && - left * tp->mss_cache < sk->sk_gso_max_size) + left * tp->mss_cache < sk->sk_gso_max_size && + left < sk->sk_gso_max_segs) return true; return left <= tcp_max_tso_deferred_mss(tp); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3f1bcff0b10b..a7b3ec9b6c3e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1522,21 +1522,21 @@ static void tcp_cwnd_validate(struct sock *sk) * when we would be allowed to send the split-due-to-Nagle skb fully. */ static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, - unsigned int mss_now, unsigned int cwnd) + unsigned int mss_now, unsigned int max_segs) { const struct tcp_sock *tp = tcp_sk(sk); - u32 needed, window, cwnd_len; + u32 needed, window, max_len; window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; - cwnd_len = mss_now * cwnd; + max_len = mss_now * max_segs; - if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) - return cwnd_len; + if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) + return max_len; needed = min(skb->len, window); - if (cwnd_len <= needed) - return cwnd_len; + if (max_len <= needed) + return max_len; return needed - needed % mss_now; } @@ -1765,7 +1765,8 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) limit = min(send_win, cong_win); /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= sk->sk_gso_max_size) + if (limit >= min_t(unsigned int, sk->sk_gso_max_size, + sk->sk_gso_max_segs * tp->mss_cache)) goto send_now; /* Middle in queue won't get any more data, full sendable already? */ @@ -1999,7 +2000,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, - cwnd_quota); + min_t(unsigned int, + cwnd_quota, + sk->sk_gso_max_segs)); if (skb->len > limit && unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) -- GitLab From e3c0d04750751389d5116267f8cf4687444d9a50 Mon Sep 17 00:00:00 2001 From: Fan Du Date: Mon, 30 Jul 2012 21:43:54 +0000 Subject: [PATCH 5035/5711] Fix unexpected SA hard expiration after changing date After SA is setup, one timer is armed to detect soft/hard expiration, however the timer handler uses xtime to do the math. This makes hard expiration occurs first before soft expiration after setting new date with big interval. As a result new child SA is deleted before rekeying the new one. Signed-off-by: Fan Du Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++++ net/xfrm/xfrm_state.c | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d9509eb29b80..62b619e82a90 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -213,6 +213,9 @@ struct xfrm_state { struct xfrm_lifetime_cur curlft; struct tasklet_hrtimer mtimer; + /* used to fix curlft->add_time when changing date */ + long saved_tmo; + /* Last used time */ unsigned long lastused; @@ -238,6 +241,7 @@ static inline struct net *xs_net(struct xfrm_state *x) /* xflags - make enum if more show up */ #define XFRM_TIME_DEFER 1 +#define XFRM_SOFT_EXPIRE 2 enum { XFRM_STATE_VOID, diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5b228f97d4b3..87cd0e4d4282 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) if (x->lft.hard_add_expires_seconds) { long tmo = x->lft.hard_add_expires_seconds + x->curlft.add_time - now; - if (tmo <= 0) - goto expired; + if (tmo <= 0) { + if (x->xflags & XFRM_SOFT_EXPIRE) { + /* enter hard expire without soft expire first?! + * setting a new date could trigger this. + * workarbound: fix x->curflt.add_time by below: + */ + x->curlft.add_time = now - x->saved_tmo - 1; + tmo = x->lft.hard_add_expires_seconds - x->saved_tmo; + } else + goto expired; + } if (tmo < next) next = tmo; } @@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) if (x->lft.soft_add_expires_seconds) { long tmo = x->lft.soft_add_expires_seconds + x->curlft.add_time - now; - if (tmo <= 0) + if (tmo <= 0) { warn = 1; - else if (tmo < next) + x->xflags &= ~XFRM_SOFT_EXPIRE; + } else if (tmo < next) { next = tmo; + x->xflags |= XFRM_SOFT_EXPIRE; + x->saved_tmo = tmo; + } } if (x->lft.soft_use_expires_seconds) { long tmo = x->lft.soft_use_expires_seconds + -- GitLab From 8b6d5c09bc0c49aea041486d77c2f67e98ae0bc3 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 31 Jul 2012 11:39:37 +0000 Subject: [PATCH 5036/5711] bnx2x: fix mem leak when command is unknown In bnx2x_mcast_enqueue_cmd() we'll leak the memory allocated to 'new_cmd' if we hit the deafault case of the 'switch (cmd)'. Add a 'kfree(new_cmd)' to that case to avoid the leak. Signed-off-by: Jesper Juhl Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 734fd87cd990..62f754bd0dfe 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -2485,6 +2485,7 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp, break; default: + kfree(new_cmd); BNX2X_ERR("Unknown command: %d\n", cmd); return -EINVAL; } -- GitLab From a27032eee8cb6e16516f13c8a9752e9d5d4cc430 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 1 Aug 2012 21:10:51 +0200 Subject: [PATCH 5037/5711] sparc64: do not clobber personality flags in sys_sparc64_personality() There are multiple errors in how sys_sparc64_personality() handles personality flags stored in top three bytes. - directly comparing current->personality against PER_LINUX32 doesn't work in cases when any of the personality flags stored in the top three bytes are used. - directly forcefully setting personality to PER_LINUX32 or PER_LINUX discards any flags stored in the top three bytes Fix the first one by properly using personality() macro to compare only PER_MASK bytes. Fix the second one by setting only the bits that should be set, instead of overwriting the whole value. Signed-off-by: Jiri Kosina Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 0dc1f5786081..11c6c9603e71 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -502,12 +502,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) { int ret; - if (current->personality == PER_LINUX32 && - personality == PER_LINUX) - personality = PER_LINUX32; + if (personality(current->personality) == PER_LINUX32 && + personality(personality) == PER_LINUX) + personality |= PER_LINUX32; ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; + if (personality(ret) == PER_LINUX32) + ret &= ~PER_LINUX32; return ret; } -- GitLab From 2d4e6dc628b43fbbbc9219e233ec3ee0afb707e3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 30 Jul 2012 11:23:16 -0300 Subject: [PATCH 5038/5711] ARM: dts: imx27-3ds.dts: Fix serial console node Fix serial console node and allow the board to boot again. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- arch/arm/boot/dts/imx27-3ds.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx27-3ds.dts b/arch/arm/boot/dts/imx27-3ds.dts index d3f8296e19e0..0a8978a40ece 100644 --- a/arch/arm/boot/dts/imx27-3ds.dts +++ b/arch/arm/boot/dts/imx27-3ds.dts @@ -27,7 +27,7 @@ status = "okay"; }; - uart@1000a000 { + uart1: serial@1000a000 { fsl,uart-has-rtscts; status = "okay"; }; -- GitLab From e33cdac014d50dd9753e1399ae8b0b5cd98d7aa0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 1 Aug 2012 23:23:40 +0000 Subject: [PATCH 5039/5711] ipv4: route.c cleanup Remove unused includes after IP cache removal Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c035251beb07..e4ba974f143c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -70,7 +70,6 @@ #include #include #include -#include #include #include #include @@ -80,7 +79,6 @@ #include #include #include -#include #include #include #include @@ -88,11 +86,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include -- GitLab From 98d3088e534a2a61f6690b5426909b0c3b57a785 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Aug 2012 20:05:47 +0100 Subject: [PATCH 5040/5711] ASoC: core: Fix check before defaulting to regmap Check if the chip has provided a write operation (which is mandatory for I/O) rather than looking for control data as some of the MFDs use a global for this. Also skip the attempt if there's no regmap available by device in case things get confused by the attempt to default. Signed-off-by: Mark Brown Tested-by: Peter Ujfalusi --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f219b2f7ee68..f81c5976b961 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1096,7 +1096,7 @@ static int soc_probe_codec(struct snd_soc_card *card, } /* If the driver didn't set I/O up try regmap */ - if (!codec->control_data) + if (!codec->write && dev_get_regmap(codec->dev, NULL)) snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (driver->controls) -- GitLab From 0e8d96dd2c99405c707f540b5922ec869b848979 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Mon, 20 Feb 2012 03:46:12 -0500 Subject: [PATCH 5041/5711] exofs: readpage_strip: Add a BUG_ON to check for PageLocked(page) readpage_strip can be called from several code paths all of which require that the page be locked before any operations are carried out. Since we export the exofs_readpage callback to the VFS, add a BUG_ON to check for PageLocked(page) to make sure that this understanding is never compromised. Signed-off-by: Kautuk Consul Signed-off-by: Boaz Harrosh --- fs/exofs/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 5badb0c039de..9a5ed30b8a35 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -389,6 +389,8 @@ static int readpage_strip(void *data, struct page *page) size_t len; int ret; + BUG_ON(!PageLocked(page)); + /* FIXME: Just for debugging, will be removed */ if (PageUptodate(page)) EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, -- GitLab From 66153f6e0f89c75d18e490739b0149dfd2e53b69 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 4 Jun 2012 14:48:27 +0300 Subject: [PATCH 5042/5711] exofs: stop using s_dirt Exofs has the '->write_super()' handler and makes some use of the '->s_dirt' superblock flag, but it really needs neither of them because it never sets 's_dirt' to one which means the VFS never calls its '->write_super()' handler. Thus, remove both. Note, I am trying to remove both 's_dirt' and 'write_super()' from VFS altogether once all users are gone. Signed-off-by: Artem Bityutskiy Signed-off-by: Boaz Harrosh --- fs/exofs/super.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 433783624d10..dde41a75c7c8 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -400,8 +400,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait) ret = ore_write(ios); if (unlikely(ret)) EXOFS_ERR("%s: ore_write failed.\n", __func__); - else - sb->s_dirt = 0; unlock_super(sb); @@ -412,14 +410,6 @@ out: return ret; } -static void exofs_write_super(struct super_block *sb) -{ - if (!(sb->s_flags & MS_RDONLY)) - exofs_sync_fs(sb, 1); - else - sb->s_dirt = 0; -} - static void _exofs_print_device(const char *msg, const char *dev_path, struct osd_dev *od, u64 pid) { @@ -952,7 +942,6 @@ static const struct super_operations exofs_sops = { .write_inode = exofs_write_inode, .evict_inode = exofs_evict_inode, .put_super = exofs_put_super, - .write_super = exofs_write_super, .sync_fs = exofs_sync_fs, .statfs = exofs_statfs, }; -- GitLab From 4b74f6ea8417e48bb1fc65880a0574134a8b4745 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 20 Jul 2012 15:50:27 +0300 Subject: [PATCH 5043/5711] exofs: Fix __r4w_get_page when offset is beyond i_size It is very common for the end of the file to be unaligned on stripe size. But since we know it's beyond file's end then the XOR should be preformed with all zeros. Old code used to just read zeros out of the OSD devices, which is a great waist. But what scares me more about this situation is that, we now have pages attached to the file's mapping that are beyond i_size. I don't like the kind of bugs this calls for. Fix both birds, by returning a global ZERO_PAGE, if offset is beyond i_size. Signed-off-by: Boaz Harrosh --- fs/exofs/inode.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 9a5ed30b8a35..3b2ee72aecbe 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -574,8 +574,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) if (!pcol->that_locked_page || (pcol->that_locked_page->index != index)) { - struct page *page = find_get_page(pcol->inode->i_mapping, index); + struct page *page; + loff_t i_size = i_size_read(pcol->inode); + if (offset >= i_size) { + *uptodate = true; + EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); + return ZERO_PAGE(0); + } + + page = find_get_page(pcol->inode->i_mapping, index); if (!page) { page = find_or_create_page(pcol->inode->i_mapping, index, GFP_NOFS); @@ -604,12 +612,13 @@ static void __r4w_put_page(void *priv, struct page *page) { struct page_collect *pcol = priv; - if (pcol->that_locked_page != page) { + if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { EXOFS_DBGMSG("index=0x%lx\n", page->index); page_cache_release(page); return; } - EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); + EXOFS_DBGMSG("that_locked_page index=0x%lx\n", + ZERO_PAGE(0) == page ? -1 : page->index); } static const struct _ore_r4w_op _r4w_op = { -- GitLab From 03f6b0843ad6512f27bc2e48f04c21065311e03e Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 1 Aug 2012 15:58:42 -0500 Subject: [PATCH 5044/5711] cfg80211: add channel flag to prohibit OFDM operation Currently the only way for wireless drivers to tell whether or not OFDM is allowed on the current channel is to check the regulatory information. However, this requires hodling cfg80211_mutex, which is not visible to the drivers. Other regulatory restrictions are provided as flags in the channel definition, so let's do similarly with OFDM. This patch adds a new flag, IEEE80211_CHAN_NO_OFDM, to tell drivers that OFDM on a channel is not allowed. This flag is set on any channels for which regulatory indicates that OFDM is prohibited. Signed-off-by: Seth Forshee Tested-by: Arend van Spriel Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ net/wireless/reg.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 493fa0c79005..3d254e10ff30 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -96,6 +96,7 @@ enum ieee80211_band { * is not permitted. * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. */ enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, @@ -104,6 +105,7 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_HT40PLUS = 1<<4, IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + IEEE80211_CHAN_NO_OFDM = 1<<6, }; #define IEEE80211_CHAN_NO_HT40 \ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a9175fedeb59..cbf30de79c69 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -680,6 +680,8 @@ static u32 map_regdom_flags(u32 rd_flags) channel_flags |= IEEE80211_CHAN_NO_IBSS; if (rd_flags & NL80211_RRF_DFS) channel_flags |= IEEE80211_CHAN_RADAR; + if (rd_flags & NL80211_RRF_NO_OFDM) + channel_flags |= IEEE80211_CHAN_NO_OFDM; return channel_flags; } -- GitLab From 899852af60c212bfe9a2fb71d4d9082d2622df5c Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Wed, 1 Aug 2012 16:54:42 -0700 Subject: [PATCH 5045/5711] cfg80211: Clear "beacon_found" on regulatory restore Restore the default state to the "beacon_found" flag when the channel flags are restored. Otherwise, we can end up with a channel that we can no longer transmit on even when we can see beacons on that channel. Signed-off-by: Paul Stewart Signed-off-by: Johannes Berg --- net/wireless/reg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index cbf30de79c69..2ded3c7fad06 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1901,6 +1901,7 @@ static void restore_custom_reg_settings(struct wiphy *wiphy) chan->flags = chan->orig_flags; chan->max_antenna_gain = chan->orig_mag; chan->max_power = chan->orig_mpwr; + chan->beacon_found = false; } } } -- GitLab From be388f3d9af4155db0dc9e7e59dd49db90271c1c Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 2 Aug 2012 14:59:57 +0300 Subject: [PATCH 5046/5711] exofs: Use proper max_IO calculations from ore exofs_max_io_pages should just use the ORE's calculated layout->max_io_length, And avoid unnecessary BUGs, calculations made here were also a layering violation. Signed-off-by: Boaz Harrosh --- fs/exofs/inode.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 3b2ee72aecbe..1562c27a2fab 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -37,15 +37,12 @@ #define EXOFS_DBGMSG2(M...) do {} while (0) -enum {MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; - unsigned exofs_max_io_pages(struct ore_layout *layout, unsigned expected_pages) { - unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); + unsigned pages = min_t(unsigned, expected_pages, + layout->max_io_length / PAGE_SIZE); - /* TODO: easily support bio chaining */ - pages = min_t(unsigned, pages, layout->max_io_length / PAGE_SIZE); return pages; } @@ -101,7 +98,8 @@ static void _pcol_reset(struct page_collect *pcol) * it might not end here. don't be left with nothing */ if (!pcol->expected_pages) - pcol->expected_pages = MAX_PAGES_KMALLOC; + pcol->expected_pages = + exofs_max_io_pages(&pcol->sbi->layout, ~0); } static int pcol_try_alloc(struct page_collect *pcol) -- GitLab From 9e62bb4458ad2cf28bd701aa5fab380b846db326 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 1 Aug 2012 17:48:36 +0300 Subject: [PATCH 5047/5711] ore: Fix out-of-bounds access in _ios_obj() _ios_obj() is accessed by group_index not device_table index. The oc->comps array is only a group_full of devices at a time it is not like ore_comp_dev() which is indexed by a global device_table index. This did not BUG until now because exofs only uses a single COMP for all devices. But with other FSs like PanFS this is not true. This bug was only in the write_path, all other users were using it correctly [This is a bug since 3.2 Kernel] CC: Stable Tree Signed-off-by: Boaz Harrosh --- fs/exofs/ore.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 24a49d47e935..1585db1aa365 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -837,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) bio->bi_rw |= REQ_WRITE; } - osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, - bio, per_dev->length); + osd_req_write(or, _ios_obj(ios, cur_comp), + per_dev->offset, bio, per_dev->length); ORE_DBGMSG("write(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(per_dev->length), dev); } else if (ios->kern_buff) { @@ -853,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) (ios->si.unit_off + ios->length > ios->layout->stripe_unit)); - ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), + ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), per_dev->offset, ios->kern_buff, ios->length); if (unlikely(ret)) goto out; ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(ios->length), per_dev->dev); } else { - osd_req_set_attributes(or, _ios_obj(ios, dev)); + osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), ios->out_attr_len, dev); } -- GitLab From 5bc6f9888db5739abfa0cae279b4b442e4db8049 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 30 Jul 2012 10:18:05 -0400 Subject: [PATCH 5048/5711] xen/p2m: Reserve 8MB of _brk space for P2M leafs when populating back. When we release pages back during bootup: Freeing 9d-100 pfn range: 99 pages freed Freeing 9cf36-9d0d2 pfn range: 412 pages freed Freeing 9f6bd-9f6bf pfn range: 2 pages freed Freeing 9f714-9f7bf pfn range: 171 pages freed Freeing 9f7e0-9f7ff pfn range: 31 pages freed Freeing 9f800-100000 pfn range: 395264 pages freed Released 395979 pages of unused memory We then try to populate those pages back. In the P2M tree however the space for those leafs must be reserved - as such we use extend_brk. We reserve 8MB of _brk space, which means we can fit over 1048576 PFNs - which is more than we should ever need. Without this, on certain compilation of the kernel we would hit: (XEN) domain_crash_sync called from entry.S (XEN) CPU: 0 (XEN) RIP: e033:[] (XEN) RFLAGS: 0000000000000206 EM: 1 CONTEXT: pv guest (XEN) rax: ffffffff81a7c000 rbx: 000000000000003d rcx: 0000000000001000 (XEN) rdx: ffffffff81a7b000 rsi: 0000000000001000 rdi: 0000000000001000 (XEN) rbp: ffffffff81801cd8 rsp: ffffffff81801c98 r8: 0000000000100000 (XEN) r9: ffffffff81a7a000 r10: 0000000000000001 r11: 0000000000000003 (XEN) r12: 0000000000000004 r13: 0000000000000004 r14: 000000000000003d (XEN) r15: 00000000000001e8 cr0: 000000008005003b cr4: 00000000000006f0 (XEN) cr3: 0000000125803000 cr2: 0000000000000000 (XEN) ds: 0000 es: 0000 fs: 0000 gs: 0000 ss: e02b cs: e033 (XEN) Guest stack trace from rsp=ffffffff81801c98: .. which is extend_brk hitting a BUG_ON. Interestingly enough, most of the time we are not going to hit this b/c the _brk space is quite large (v3.5): ffffffff81a25000 B __brk_base ffffffff81e43000 B __brk_limit = ~4MB. vs earlier kernels (with this back-ported), the space is smaller: ffffffff81a25000 B __brk_base ffffffff81a7b000 B __brk_limit = 344 kBytes. where we would certainly hit this and hit extend_brk. Note that git commit c3d93f880197953f86ab90d9da4744e926b38e33 (xen: populate correct number of pages when across mem boundary (v2)) exposed this bug). [v1: Made it 8MB of _brk space instead of 4MB per Jan's suggestion] CC: stable@vger.kernel.org #only for 3.5 Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/p2m.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 64effdc6da94..b2e91d40a4cb 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -194,6 +194,11 @@ RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID * boundary violation will require three middle nodes. */ RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3); +/* When we populate back during bootup, the amount of pages can vary. The + * max we have is seen is 395979, but that does not mean it can't be more. + * But some machines can have 3GB I/O holes even. So lets reserve enough + * for 4GB of I/O and E820 holes. */ +RESERVE_BRK(p2m_populated, PMD_SIZE * 4); static inline unsigned p2m_top_index(unsigned long pfn) { BUG_ON(pfn >= MAX_P2M_PFN); -- GitLab From cb0b29e0861659c9eef9664772cd7e845ba1104a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Aug 2012 11:42:57 -0300 Subject: [PATCH 5049/5711] perf evlist: Introduce perf_evlist__parse_sample That is a more compact form of perf_session__parse_sample and to support multiple evlists per perf_session is the way to go anyway. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-vkxx3j5qktoj11bvcwmfjj13@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-test.c | 8 ++------ tools/perf/builtin-top.c | 2 +- tools/perf/util/evlist.c | 9 +++++++++ tools/perf/util/evlist.h | 4 ++++ tools/perf/util/python.c | 6 +----- tools/perf/util/session.c | 19 ++++--------------- tools/perf/util/session.h | 4 ---- 7 files changed, 21 insertions(+), 31 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index e5032ed2f259..1d592f5cbea9 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -562,9 +562,7 @@ static int test__basic_mmap(void) goto out_munmap; } - err = perf_event__parse_sample(event, attr.sample_type, - evsels[0]->sample_size, - false, &sample, false); + err = perf_evlist__parse_sample(evlist, event, &sample, false); if (err) { pr_err("Can't parse sample, err = %d\n", err); goto out_munmap; @@ -781,9 +779,7 @@ static int test__PERF_RECORD(void) if (type < PERF_RECORD_MAX) nr_events[type]++; - err = perf_event__parse_sample(event, evsel->attr.sample_type, - evsel->sample_size, true, - &sample, false); + err = perf_evlist__parse_sample(evlist, event, &sample, false); if (err < 0) { if (verbose) perf_event__fprintf(event, stderr); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 520e4256fc66..40264eaa9f0f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -811,7 +811,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) int ret; while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { - ret = perf_session__parse_sample(session, event, &sample); + ret = perf_evlist__parse_sample(top->evlist, event, &sample, false); if (ret) { pr_err("Can't parse sample, err = %d\n", ret); continue; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3edfd3483816..1a560e0904a5 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -881,3 +881,12 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) return 0; } + +int perf_evlist__parse_sample(struct perf_evlist *evlist, + const union perf_event *event, + struct perf_sample *sample, bool swapped) +{ + struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); + return perf_event__parse_sample(event, e->attr.sample_type, e->sample_size, + e->attr.sample_id_all, sample, swapped); +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 40d4d3cdced0..a5a49118a91a 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -122,6 +122,10 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist); bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); +int perf_evlist__parse_sample(struct perf_evlist *evlist, + const union perf_event *event, + struct perf_sample *sample, bool swapped); + bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index b0d6f85e30f1..0688bfb6d280 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -797,17 +797,13 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, event = perf_evlist__mmap_read(evlist, cpu); if (event != NULL) { - struct perf_evsel *first; PyObject *pyevent = pyrf_event__new(event); struct pyrf_event *pevent = (struct pyrf_event *)pyevent; if (pyevent == NULL) return PyErr_NoMemory(); - first = list_entry(evlist->entries.next, struct perf_evsel, node); - err = perf_event__parse_sample(event, first->attr.sample_type, - first->sample_size, - sample_id_all, &pevent->sample, false); + err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false); if (err) return PyErr_Format(PyExc_OSError, "perf: can't parse sample, err=%d", err); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 5b8601df2392..7d07324db41c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -16,19 +16,6 @@ #include "cpumap.h" #include "event-parse.h" -int perf_session__parse_sample(struct perf_session *session, - const union perf_event *event, - struct perf_sample *sample) -{ - struct perf_evsel *first; - first = list_entry(session->evlist->entries.next, struct perf_evsel, node); - - return perf_event__parse_sample(event, first->attr.sample_type, - first->sample_size, - first->attr.sample_id_all, sample, - session->header.needs_swap); -} - int perf_session__synthesize_sample(struct perf_session *session, union perf_event *event, const struct perf_sample *sample) @@ -692,7 +679,8 @@ static void flush_sample_queue(struct perf_session *s, if (iter->timestamp > limit) break; - ret = perf_session__parse_sample(s, iter->event, &sample); + ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample, + s->header.needs_swap); if (ret) pr_err("Can't parse sample, err = %d\n", ret); else @@ -1103,7 +1091,8 @@ static int perf_session__process_event(struct perf_session *session, /* * For all kernel events we get the sample data */ - ret = perf_session__parse_sample(session, event, &sample); + ret = perf_evlist__parse_sample(session->evlist, event, &sample, + session->header.needs_swap); if (ret) return ret; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index e2a1a4b7b236..7389fb1f010a 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -126,10 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); -int perf_session__parse_sample(struct perf_session *session, - const union perf_event *event, - struct perf_sample *sample); - int perf_session__synthesize_sample(struct perf_session *session, union perf_event *event, const struct perf_sample *sample); -- GitLab From a3f698fe3082ff80a7f3b27c9b64b4b748c81f9d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Aug 2012 12:23:46 -0300 Subject: [PATCH 5050/5711] perf evsel: Adopt parse_sample method from perf_event Since we need evsel->{attr.{sample_{id_all,type}},sample_size}, reducing the number of parameters tools have to pass. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-wdtmgak0ihgsmw1brb54a8h4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.h | 3 --- tools/perf/util/evlist.c | 6 ++---- tools/perf/util/evlist.h | 3 +-- tools/perf/util/evsel.c | 12 ++++++------ tools/perf/util/evsel.h | 2 ++ 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 1b197280c621..d84870b06426 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -197,9 +197,6 @@ int perf_event__preprocess_sample(const union perf_event *self, const char *perf_event__name(unsigned int id); -int perf_event__parse_sample(const union perf_event *event, u64 type, - int sample_size, bool sample_id_all, - struct perf_sample *sample, bool swapped); int perf_event__synthesize_sample(union perf_event *event, u64 type, const struct perf_sample *sample, bool swapped); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 1a560e0904a5..9b38681add9e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -882,11 +882,9 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) return 0; } -int perf_evlist__parse_sample(struct perf_evlist *evlist, - const union perf_event *event, +int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample, bool swapped) { struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); - return perf_event__parse_sample(event, e->attr.sample_type, e->sample_size, - e->attr.sample_id_all, sample, swapped); + return perf_evsel__parse_sample(e, event, sample, swapped); } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a5a49118a91a..528c1acd9298 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -122,8 +122,7 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist); bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); -int perf_evlist__parse_sample(struct perf_evlist *evlist, - const union perf_event *event, +int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample, bool swapped); bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8feec4011356..2eaae140def2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -729,10 +729,10 @@ static bool sample_overlap(const union perf_event *event, return false; } -int perf_event__parse_sample(const union perf_event *event, u64 type, - int sample_size, bool sample_id_all, +int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *data, bool swapped) { + u64 type = evsel->attr.sample_type; const u64 *array; /* @@ -747,14 +747,14 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, data->period = 1; if (event->header.type != PERF_RECORD_SAMPLE) { - if (!sample_id_all) + if (!evsel->attr.sample_id_all) return 0; return perf_event__parse_id_sample(event, type, data, swapped); } array = event->sample.array; - if (sample_size + sizeof(event->header) > event->header.size) + if (evsel->sample_size + sizeof(event->header) > event->header.size) return -EFAULT; if (type & PERF_SAMPLE_IP) { @@ -896,7 +896,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u.val32[1] = sample->tid; if (swapped) { /* - * Inverse of what is done in perf_event__parse_sample + * Inverse of what is done in perf_evsel__parse_sample */ u.val32[0] = bswap_32(u.val32[0]); u.val32[1] = bswap_32(u.val32[1]); @@ -931,7 +931,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u.val32[0] = sample->cpu; if (swapped) { /* - * Inverse of what is done in perf_event__parse_sample + * Inverse of what is done in perf_evsel__parse_sample */ u.val32[0] = bswap_32(u.val32[0]); u.val64 = bswap_64(u.val64); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 894bd77d90cc..b559929983bb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -180,4 +180,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, void hists__init(struct hists *hists); +int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, + struct perf_sample *sample, bool swapped); #endif /* __PERF_EVSEL_H */ -- GitLab From 5ef50c3bec20060bc114f62d6503c5d86d70bdd7 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 31 Jul 2012 11:27:36 -0700 Subject: [PATCH 5051/5711] ceph: simplify+fix atomic_open The initial ->atomic_open op was carried over from the old intent code, which was incomplete and didn't really work. Replace it with a fresh method. In particular: * always attempt to do an atomic open+lookup, both for the create case and for lookups of existing files. * fix symlink handling by returning 1 to the VFS so that we can follow the link to its destination. This fixes a longstanding ceph bug (#2392). Signed-off-by: Sage Weil --- fs/ceph/dir.c | 38 ------------------------------ fs/ceph/file.c | 62 +++++++++++++++++++++++++++++-------------------- fs/ceph/super.h | 6 ++--- 3 files changed, 40 insertions(+), 66 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index f391f1e75414..e5b77319c97b 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -633,44 +633,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, return dentry; } -int ceph_atomic_open(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t mode, - int *opened) -{ - int err; - struct dentry *res = NULL; - - if (!(flags & O_CREAT)) { - if (dentry->d_name.len > NAME_MAX) - return -ENAMETOOLONG; - - err = ceph_init_dentry(dentry); - if (err < 0) - return err; - - return ceph_lookup_open(dir, dentry, file, flags, mode, opened); - } - - if (d_unhashed(dentry)) { - res = ceph_lookup(dir, dentry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); - - if (res) - dentry = res; - } - - /* We don't deal with positive dentries here */ - if (dentry->d_inode) - return finish_no_open(file, res); - - *opened |= FILE_CREATED; - err = ceph_lookup_open(dir, dentry, file, flags, mode, opened); - dput(res); - - return err; -} - /* * If we do a create but get no trace back from the MDS, follow up with * a lookup (the VFS expects us to link up the provided dentry). diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 1b81d6c31878..ecebbc09bfc7 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -106,9 +107,6 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) } /* - * If the filp already has private_data, that means the file was - * already opened by intent during lookup, and we do nothing. - * * If we already have the requisite capabilities, we can satisfy * the open request locally (no need to request new caps from the * MDS). We do, however, need to inform the MDS (asynchronously) @@ -207,24 +205,29 @@ out: /* - * Do a lookup + open with a single request. - * - * If this succeeds, but some subsequent check in the vfs - * may_open() fails, the struct *file gets cleaned up (i.e. - * ceph_release gets called). So fear not! + * Do a lookup + open with a single request. If we get a non-existent + * file or symlink, return 1 so the VFS can retry. */ -int ceph_lookup_open(struct inode *dir, struct dentry *dentry, +int ceph_atomic_open(struct inode *dir, struct dentry *dentry, struct file *file, unsigned flags, umode_t mode, int *opened) { struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_request *req; - struct dentry *ret; + struct dentry *dn; int err; - dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", - dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); + dout("atomic_open %p dentry %p '%.*s' %s flags %d mode 0%o\n", + dir, dentry, dentry->d_name.len, dentry->d_name.name, + d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode); + + if (dentry->d_name.len > NAME_MAX) + return -ENAMETOOLONG; + + err = ceph_init_dentry(dentry); + if (err < 0) + return err; /* do the open */ req = prepare_open_request(dir->i_sb, flags, mode); @@ -241,22 +244,31 @@ int ceph_lookup_open(struct inode *dir, struct dentry *dentry, (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, req); err = ceph_handle_snapdir(req, dentry, err); - if (err) - goto out; - if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry) + if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); - if (err) - goto out; - err = finish_open(file, req->r_dentry, ceph_open, opened); -out: - ret = ceph_finish_lookup(req, dentry, err); - ceph_mdsc_put_request(req); - dout("ceph_lookup_open result=%p\n", ret); - if (IS_ERR(ret)) - return PTR_ERR(ret); + if (d_unhashed(dentry)) { + dn = ceph_finish_lookup(req, dentry, err); + if (IS_ERR(dn)) + err = PTR_ERR(dn); + } else { + /* we were given a hashed negative dentry */ + dn = NULL; + } + if (err) + goto out_err; + if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) { + /* make vfs retry on splice, ENOENT, or symlink */ + dout("atomic_open finish_no_open on dn %p\n", dn); + err = finish_no_open(file, dn); + } else { + dout("atomic_open finish_open on dn %p\n", dn); + err = finish_open(file, dentry, ceph_open, opened); + } - dput(ret); +out_err: + ceph_mdsc_put_request(req); + dout("atomic_open result=%d\n", err); return err; } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index ebc95cc652be..66ebe720e40d 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages, loff_t off, size_t len); extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); extern int ceph_open(struct inode *inode, struct file *file); -extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry, - struct file *od, unsigned flags, - umode_t mode, int *opened); +extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry, + struct file *file, unsigned flags, umode_t mode, + int *opened); extern int ceph_release(struct inode *inode, struct file *filp); /* dir.c */ -- GitLab From f0666b1ac875ff32fe290219b150ec62eebbe10e Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 2 Aug 2012 09:12:59 -0700 Subject: [PATCH 5052/5711] libceph: fix crypto key null deref, memory leak Avoid crashing if the crypto key payload was NULL, as when it was not correctly allocated and initialized. Also, avoid leaking it. Signed-off-by: Sylvain Munaut Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- net/ceph/crypto.c | 1 + net/ceph/crypto.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index b780cb7947dd..9da7fdd3cd8a 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) { struct ceph_crypto_key *ckey = key->payload.data; ceph_crypto_key_destroy(ckey); + kfree(ckey); } struct key_type key_type_ceph = { diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 1919d1550d75..3572dc518bc9 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -16,7 +16,8 @@ struct ceph_crypto_key { static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) { - kfree(key->key); + if (key) + kfree(key->key); } extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, -- GitLab From debeaf6c2ded82bea65c1a487fb629fb0d2bb66f Mon Sep 17 00:00:00 2001 From: Barry Song Date: Mon, 30 Jul 2012 13:29:30 +0800 Subject: [PATCH 5053/5711] ARM: PRIMA2: delete redundant codes to restore LATCHED when timer resumes The only way to write LATCHED registers to write LATCH_BIT to LATCH register, that will latch COUNTER into LATCHED.e.g. writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); Writing values to LATCHED registers directly is useless at all. Signed-off-by: Barry Song Signed-off-by: Olof Johansson --- arch/arm/mach-prima2/timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c index 0d024b1e916d..f224107de7bc 100644 --- a/arch/arm/mach-prima2/timer.c +++ b/arch/arm/mach-prima2/timer.c @@ -132,11 +132,11 @@ static void sirfsoc_clocksource_resume(struct clocksource *cs) { int i; - for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++) + for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++) writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); - writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); - writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); } static struct clock_event_device sirfsoc_clockevent = { -- GitLab From 10b683cba5ef5cf4e0b50aabe5ed7137960b64e0 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 2 Aug 2012 17:13:47 +0200 Subject: [PATCH 5054/5711] arm: mvebu: fix typo in .dtsi comment for Armada XP SoCs The comment was wrongly referring to Armada 370 while the file is related to Armada XP. Signed-off-by: Thomas Petazzoni Signed-off-by: Olof Johansson --- arch/arm/boot/dts/armada-xp.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index e1fa7e6edfe8..71d6b5d0daf1 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -12,7 +12,7 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. * - * Contains definitions specific to the Armada 370 SoC that are not + * Contains definitions specific to the Armada XP SoC that are not * common to all Armada SoCs. */ -- GitLab From bac6f61550043195ee59e9cef0db67af23baf11e Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 30 Jul 2012 22:20:34 +0800 Subject: [PATCH 5055/5711] ARM: mmp: add missing irqs.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/arm/mach-mmp/gplugd.c:195:13: error: ‘MMP_NR_IRQS’ undeclared here (not in a function) make[1]: *** [arch/arm/mach-mmp/gplugd.o] Error 1 Include to fix this issue. Signed-off-by: Haojian Zhuang Signed-off-by: Olof Johansson --- arch/arm/mach-mmp/gplugd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index f516e74ce0d5..5c3d61ee729a 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -14,6 +14,7 @@ #include #include +#include #include #include -- GitLab From 8783b6e2b2cb726f2734cf208d101f73ac1ba616 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 2 Aug 2012 10:37:03 -0700 Subject: [PATCH 5056/5711] mm: remove node_start_pfn checking in new WARN_ON for now Borislav Petkov reports that the new warning added in commit 88fdf75d1bb5 ("mm: warn if pg_data_t isn't initialized with zero") triggers for him, and it is the node_start_pfn field that has already been initialized once. The call trace looks like this: x86_64_start_kernel -> x86_64_start_reservations -> start_kernel -> setup_arch -> paging_init -> zone_sizes_init -> free_area_init_nodes -> free_area_init_node and (with the warning replaced by debug output), Borislav sees On node 0 totalpages: 4193848 DMA zone: 64 pages used for memmap DMA zone: 6 pages reserved DMA zone: 3890 pages, LIFO batch:0 DMA32 zone: 16320 pages used for memmap DMA32 zone: 798464 pages, LIFO batch:31 Normal zone: 52736 pages used for memmap Normal zone: 3322368 pages, LIFO batch:31 free_area_init_node: pgdat->node_start_pfn: 4423680 <---- On node 1 totalpages: 4194304 Normal zone: 65536 pages used for memmap Normal zone: 4128768 pages, LIFO batch:31 free_area_init_node: pgdat->node_start_pfn: 8617984 <---- On node 2 totalpages: 4194304 Normal zone: 65536 pages used for memmap Normal zone: 4128768 pages, LIFO batch:31 free_area_init_node: pgdat->node_start_pfn: 12812288 <---- On node 3 totalpages: 4194304 Normal zone: 65536 pages used for memmap Normal zone: 4128768 pages, LIFO batch:31 so remove the bogus warning for now to avoid annoying people. Minchan Kim is looking at it. Reported-by: Borislav Petkov Cc: Minchan Kim Cc: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 889532b8e6c1..009ac285fea7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4511,7 +4511,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, pg_data_t *pgdat = NODE_DATA(nid); /* pg_data_t should be reset to zero when it's allocated */ - WARN_ON(pgdat->nr_zones || pgdat->node_start_pfn || pgdat->classzone_idx); + WARN_ON(pgdat->nr_zones || pgdat->classzone_idx); pgdat->node_id = nid; pgdat->node_start_pfn = node_start_pfn; -- GitLab From c263c2c1ad615e935d563cd7be11d417f94895d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 23 Jul 2012 18:20:12 +0200 Subject: [PATCH 5057/5711] bcma: BCM43228 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/host_pci.c | 1 + drivers/bcma/sprom.c | 4 +++- include/linux/bcma/bcma_driver_chipcommon.h | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 11b32d2642df..a6e5672c67e7 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -272,6 +272,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, }; diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 26823d97fd9f..9ea4627dc0c2 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -507,7 +507,9 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) /* for these chips OTP is always available */ present = true; break; - + case BCMA_CHIP_ID_BCM43228: + present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; + break; default: present = false; break; diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 3c80885fa829..d323a4b4143c 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -89,6 +89,12 @@ #define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 #define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 #define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 +#define BCMA_CC_CHIPST_43228_ILP_DIV_EN 0x00000001 +#define BCMA_CC_CHIPST_43228_OTP_PRESENT 0x00000002 +#define BCMA_CC_CHIPST_43228_SERDES_REFCLK_PADSEL 0x00000004 +#define BCMA_CC_CHIPST_43228_SDIO_MODE 0x00000008 +#define BCMA_CC_CHIPST_43228_SDIO_OTP_PRESENT 0x00000010 +#define BCMA_CC_CHIPST_43228_SDIO_RESET 0x00000020 #define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */ #define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */ #define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ -- GitLab From 828afd26fe78f87d0bd1dfce64c561f78c1a8969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 23 Jul 2012 22:57:01 +0200 Subject: [PATCH 5058/5711] b43: fix logic in GPIO init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some comments by the way Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b80352b308d5..a140165dfee0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2719,32 +2719,37 @@ static int b43_gpio_init(struct b43_wldev *dev) if (dev->dev->chip_id == 0x4301) { mask |= 0x0060; set |= 0x0060; + } else if (dev->dev->chip_id == 0x5354) { + /* Don't allow overtaking buttons GPIOs */ + set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ } - if (dev->dev->chip_id == 0x5354) - set &= 0xff02; + if (0 /* FIXME: conditional unknown */ ) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0100); - mask |= 0x0180; - set |= 0x0180; + /* BT Coexistance Input */ + mask |= 0x0080; + set |= 0x0080; + /* BT Coexistance Out */ + mask |= 0x0100; + set |= 0x0100; } if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) { + /* PA is controlled by gpio 9, let ucode handle it */ b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0200); mask |= 0x0200; set |= 0x0200; } - if (dev->dev->core_rev >= 2) - mask |= 0x0010; /* FIXME: This is redundant. */ switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, - BCMA_CC_GPIOCTL) & mask) | set); + BCMA_CC_GPIOCTL) & ~mask) | set); break; #endif #ifdef CONFIG_B43_SSB @@ -2753,7 +2758,7 @@ static int b43_gpio_init(struct b43_wldev *dev) if (gpiodev) ssb_write32(gpiodev, B43_GPIO_CONTROL, (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & mask) | set); + & ~mask) | set); break; #endif } -- GitLab From 9d5d496c3464b7ad0ba942b4ada5f27c07e07079 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 30 Jul 2012 22:58:04 +0100 Subject: [PATCH 5059/5711] libertas: don't reset card on error when it is being removed On an OLPC XO-1.5 we have seen the following situation: - the system starts going into suspend - no wake params are set, so the mmc layer removes the card - during remove, we send a command to the card - that command fails, causing if_sdio's reset method to try and remove the mmc card in attempt to reset it - the mmc layer is not happy about being asked to remove a card that it is already removing, and the kernel crashes While the MMC layer could possibly be taught to behave better here, it also seems sensible for libertas not to try and reset a card if we're in the process of removing it anyway. Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 58048189bd24..fe1ea43c5149 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -571,7 +571,10 @@ static int lbs_thread(void *data) netdev_info(dev, "Timeout submitting command 0x%04x\n", le16_to_cpu(cmdnode->cmdbuf->command)); lbs_complete_command(priv, cmdnode, -ETIMEDOUT); - if (priv->reset_card) + + /* Reset card, but only when it isn't in the process + * of being shutdown anyway. */ + if (!dev->dismantle && priv->reset_card) priv->reset_card(priv); } priv->cmd_timed_out = 0; -- GitLab From 16ebd60856bc5d980722cb85b259a4d5b301e94a Mon Sep 17 00:00:00 2001 From: Woody Hung Date: Tue, 31 Jul 2012 21:53:33 +0800 Subject: [PATCH 5060/5711] rt2x00 : fix rt3290 resuming failed. This patch is going to fix the resuming failed from S3/S4 for rt3290 chip. Signed-off-by: Woody Hung Cc: Kevin Chou Signed-off-by: Chen, Chien-Chia Reviewed-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 68 +++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800pci.c | 71 ------------------------- 2 files changed, 68 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 88455b1b9fe0..cb8c2aca54e4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -221,6 +221,67 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } +static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + int i, count; + + rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); + if (rt2x00_get_field32(reg, WLAN_EN)) + return 0; + + rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); + rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); + rt2x00_set_field32(®, WLAN_CLK_EN, 0); + rt2x00_set_field32(®, WLAN_EN, 1); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + + udelay(REGISTER_BUSY_DELAY); + + count = 0; + do { + /* + * Check PLL_LD & XTAL_RDY. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); + if (rt2x00_get_field32(reg, PLL_LD) && + rt2x00_get_field32(reg, XTAL_RDY)) + break; + udelay(REGISTER_BUSY_DELAY); + } + + if (i >= REGISTER_BUSY_COUNT) { + + if (count >= 10) + return -EIO; + + rt2800_register_write(rt2x00dev, 0x58, 0x018); + udelay(REGISTER_BUSY_DELAY); + rt2800_register_write(rt2x00dev, 0x58, 0x418); + udelay(REGISTER_BUSY_DELAY); + rt2800_register_write(rt2x00dev, 0x58, 0x618); + udelay(REGISTER_BUSY_DELAY); + count++; + } else { + count = 0; + } + + rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); + rt2x00_set_field32(®, WLAN_CLK_EN, 1); + rt2x00_set_field32(®, WLAN_RESET, 1); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + udelay(10); + rt2x00_set_field32(®, WLAN_RESET, 0); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + udelay(10); + rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); + } while (count != 0); + + return 0; +} + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1) @@ -400,6 +461,13 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, { unsigned int i; u32 reg; + int retval; + + if (rt2x00_rt(rt2x00dev, RT3290)) { + retval = rt2800_enable_wlan_rt3290(rt2x00dev); + if (retval) + return -EBUSY; + } /* * If driver doesn't wake up firmware here, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 235376e9cb04..98aa426a3564 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -980,66 +980,6 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) return rt2800_validate_eeprom(rt2x00dev); } -static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - int i, count; - - rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - if (rt2x00_get_field32(reg, WLAN_EN)) - return 0; - - rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); - rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); - rt2x00_set_field32(®, WLAN_CLK_EN, 0); - rt2x00_set_field32(®, WLAN_EN, 1); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - - udelay(REGISTER_BUSY_DELAY); - - count = 0; - do { - /* - * Check PLL_LD & XTAL_RDY. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, CMB_CTRL, ®); - if (rt2x00_get_field32(reg, PLL_LD) && - rt2x00_get_field32(reg, XTAL_RDY)) - break; - udelay(REGISTER_BUSY_DELAY); - } - - if (i >= REGISTER_BUSY_COUNT) { - - if (count >= 10) - return -EIO; - - rt2800_register_write(rt2x00dev, 0x58, 0x018); - udelay(REGISTER_BUSY_DELAY); - rt2800_register_write(rt2x00dev, 0x58, 0x418); - udelay(REGISTER_BUSY_DELAY); - rt2800_register_write(rt2x00dev, 0x58, 0x618); - udelay(REGISTER_BUSY_DELAY); - count++; - } else { - count = 0; - } - - rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); - rt2x00_set_field32(®, WLAN_CLK_EN, 1); - rt2x00_set_field32(®, WLAN_RESET, 1); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - udelay(10); - rt2x00_set_field32(®, WLAN_RESET, 0); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - udelay(10); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); - } while (count != 0); - - return 0; -} static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; @@ -1062,17 +1002,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan - * clk for rt3290. That avoid the MCU fail in start phase. - */ - if (rt2x00_rt(rt2x00dev, RT3290)) { - retval = rt2800_enable_wlan_rt3290(rt2x00dev); - - if (retval) - return retval; - } - /* * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. -- GitLab From 8c1057e43c99e393fe2e14cca879affcb516d36b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 1 Aug 2012 21:35:36 +0100 Subject: [PATCH 5061/5711] libertas: fix two memory leaks The if_sdio_card structure was never being freed, and neither was the command structure used for association. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 1 + drivers/net/wireless/libertas/if_sdio.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index eb5de800ed90..1c10b542ab23 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -1254,6 +1254,7 @@ static int lbs_associate(struct lbs_private *priv, netif_tx_wake_all_queues(priv->dev); } + kfree(cmd); done: lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret; diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 76caebaa4397..e970897f6ab5 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1314,6 +1314,7 @@ static void if_sdio_remove(struct sdio_func *func) kfree(packet); } + kfree(card); lbs_deb_leave(LBS_DEB_SDIO); } -- GitLab From 7f38e5bc93203bc76b215dcd2df2067b5b0e004c Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 1 Aug 2012 15:58:43 -0500 Subject: [PATCH 5062/5711] brcmsmac: use channel flags to restrict OFDM brcmsmac cannot call freq_reg_info() during channel changes as it does not hold cfg80211_lock, and as a result it generates a lockdep warning. freq_reg_info() is being used to determine whether OFDM is allowed on the current channel, so we can avoid the errant call by using the new IEEE80211_CHAN_NO_OFDM for this purpose instead. Reported-by: Josh Boyer Signed-off-by: Seth Forshee Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/channel.c | 5 +---- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 9a4c63f927cb..7ed7d7577024 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -382,9 +382,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, { struct brcms_c_info *wlc = wlc_cm->wlc; struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; - const struct ieee80211_reg_rule *reg_rule; struct txpwr_limits txpwr; - int ret; brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); @@ -393,8 +391,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, ); /* set or restore gmode as required by regulatory */ - ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, ®_rule); - if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM)) + if (ch->flags & IEEE80211_CHAN_NO_OFDM) brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); else brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 9e79d47e077f..192ad5c1fcc8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -121,7 +121,8 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = { IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(14, 2484, IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | + IEEE80211_CHAN_NO_OFDM) }; static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { -- GitLab From 3dd4765fce04c0b4af1e0bc4c0b10f906f95fabc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 2 Aug 2012 14:30:56 -0400 Subject: [PATCH 5063/5711] nfs: tear down caches in nfs_init_writepagecache when allocation fails ...and ensure that we tear down the nfs_commit_data cache too when unloading the module. Cc: Bryan Schumaker Cc: stable@vger.kernel.org Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5829d0ce7cfb..e3b55372726c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1814,19 +1814,19 @@ int __init nfs_init_writepagecache(void) nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, nfs_wdata_cachep); if (nfs_wdata_mempool == NULL) - return -ENOMEM; + goto out_destroy_write_cache; nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", sizeof(struct nfs_commit_data), 0, SLAB_HWCACHE_ALIGN, NULL); if (nfs_cdata_cachep == NULL) - return -ENOMEM; + goto out_destroy_write_mempool; nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, nfs_wdata_cachep); if (nfs_commit_mempool == NULL) - return -ENOMEM; + goto out_destroy_commit_cache; /* * NFS congestion size, scale with available memory. @@ -1849,11 +1849,20 @@ int __init nfs_init_writepagecache(void) nfs_congestion_kb = 256*1024; return 0; + +out_destroy_commit_cache: + kmem_cache_destroy(nfs_cdata_cachep); +out_destroy_write_mempool: + mempool_destroy(nfs_wdata_mempool); +out_destroy_write_cache: + kmem_cache_destroy(nfs_wdata_cachep); + return -ENOMEM; } void nfs_destroy_writepagecache(void) { mempool_destroy(nfs_commit_mempool); + kmem_cache_destroy(nfs_cdata_cachep); mempool_destroy(nfs_wdata_mempool); kmem_cache_destroy(nfs_wdata_cachep); } -- GitLab From 8554116e17eef055d9dd58a94b3427cb2ad1c317 Mon Sep 17 00:00:00 2001 From: Idan Kedar Date: Thu, 2 Aug 2012 11:47:10 +0300 Subject: [PATCH 5064/5711] pnfs: defer release of pages in layoutget we have encountered a bug whereby reading a lot of files (copying fedora's /bin) from a pNFS mount and hitting Ctrl+C in the middle caused a general protection fault in xdr_shrink_bufhead. this function is called when decoding the response from LAYOUTGET. the decoding is done by a worker thread, and the caller of LAYOUTGET waits for the worker thread to complete. hitting Ctrl+C caused the synchronous wait to end and the next thing the caller does is to free the pages, so when the worker thread calls xdr_shrink_bufhead, the pages are gone. therefore, the cleanup of these pages has been moved to nfs4_layoutget_release. Signed-off-by: Idan Kedar Signed-off-by: Benny Halevy Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.c | 39 +------------------------------- fs/nfs/pnfs.h | 2 +- 3 files changed, 58 insertions(+), 40 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a99a8d948721..6a78d49da5c1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6223,11 +6223,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) dprintk("<-- %s\n", __func__); } +static size_t max_response_pages(struct nfs_server *server) +{ + u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; + return nfs_page_array_len(0, max_resp_sz); +} + +static void nfs4_free_pages(struct page **pages, size_t size) +{ + int i; + + if (!pages) + return; + + for (i = 0; i < size; i++) { + if (!pages[i]) + break; + __free_page(pages[i]); + } + kfree(pages); +} + +static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) +{ + struct page **pages; + int i; + + pages = kcalloc(size, sizeof(struct page *), gfp_flags); + if (!pages) { + dprintk("%s: can't alloc array of %zu pages\n", __func__, size); + return NULL; + } + + for (i = 0; i < size; i++) { + pages[i] = alloc_page(gfp_flags); + if (!pages[i]) { + dprintk("%s: failed to allocate page\n", __func__); + nfs4_free_pages(pages, size); + return NULL; + } + } + + return pages; +} + static void nfs4_layoutget_release(void *calldata) { struct nfs4_layoutget *lgp = calldata; + struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); dprintk("--> %s\n", __func__); + nfs4_free_pages(lgp->args.layout.pages, max_pages); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -6239,9 +6286,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { .rpc_release = nfs4_layoutget_release, }; -int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) +int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) { struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); struct rpc_task *task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], @@ -6259,6 +6307,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) dprintk("--> %s\n", __func__); + lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); + if (!lgp->args.layout.pages) { + nfs4_layoutget_release(lgp); + return -ENOMEM; + } + lgp->args.layout.pglen = max_pages * PAGE_SIZE; + lgp->res.layoutp = &lgp->args.layout; lgp->res.seq_res.sr_slot = NULL; nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 76875bfcf19c..2e00feacd4be 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -583,9 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; - struct page **pages = NULL; - int i; - u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -594,20 +591,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, if (lgp == NULL) return NULL; - /* allocate pages for xdr post processing */ - max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - max_pages = nfs_page_array_len(0, max_resp_sz); - - pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); - if (!pages) - goto out_err_free; - - for (i = 0; i < max_pages; i++) { - pages[i] = alloc_page(gfp_flags); - if (!pages[i]) - goto out_err_free; - } - lgp->args.minlength = PAGE_CACHE_SIZE; if (lgp->args.minlength > range->length) lgp->args.minlength = range->length; @@ -616,39 +599,19 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); - lgp->args.layout.pages = pages; - lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; lgp->gfp_flags = gfp_flags; /* Synchronously retrieve layout information from server and * store in lseg. */ - nfs4_proc_layoutget(lgp); + nfs4_proc_layoutget(lgp, gfp_flags); if (!lseg) { /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); } - /* free xdr pages */ - for (i = 0; i < max_pages; i++) - __free_page(pages[i]); - kfree(pages); - return lseg; - -out_err_free: - /* free any allocated xdr pages, lgp as it's not used */ - if (pages) { - for (i = 0; i < max_pages; i++) { - if (!pages[i]) - break; - __free_page(pages[i]); - } - kfree(pages); - } - kfree(lgp); - return NULL; } /* diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2c6c80503ba4..5ea019e80b4c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, struct pnfs_devicelist *devlist); extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *dev); -extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); +extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); /* pnfs.c */ -- GitLab From 21d1f58aedc5f7ac4bb0c4e3d78c74ea31ac050f Mon Sep 17 00:00:00 2001 From: Idan Kedar Date: Thu, 2 Aug 2012 11:47:11 +0300 Subject: [PATCH 5065/5711] pnfs: nfs4_proc_layoutget returns void since the only user of nfs4_proc_layoutget is send_layoutget, which ignores its return value, there is no reason to return any value. Signed-off-by: Idan Kedar Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 8 ++++---- fs/nfs/pnfs.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6a78d49da5c1..f94f6b3928fc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6286,7 +6286,7 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { .rpc_release = nfs4_layoutget_release, }; -int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) +void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) { struct nfs_server *server = NFS_SERVER(lgp->args.inode); size_t max_pages = max_response_pages(server); @@ -6310,7 +6310,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); if (!lgp->args.layout.pages) { nfs4_layoutget_release(lgp); - return -ENOMEM; + return; } lgp->args.layout.pglen = max_pages * PAGE_SIZE; @@ -6319,7 +6319,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) - return PTR_ERR(task); + return; status = nfs4_wait_for_completion_rpc_task(task); if (status == 0) status = task->tk_status; @@ -6327,7 +6327,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) status = pnfs_layout_process(lgp); rpc_put_task(task); dprintk("<-- %s status=%d\n", __func__, status); - return status; + return; } static void diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 5ea019e80b4c..745aa1b39e7c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, struct pnfs_devicelist *devlist); extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *dev); -extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); +extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); /* pnfs.c */ -- GitLab From f6166384095b7ecf77752b5e9096e6d03d75f7ae Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 2 Aug 2012 15:36:09 +0300 Subject: [PATCH 5066/5711] NFS41: add pg_layout_private to nfs_pageio_descriptor To allow layout driver to pass private information around pg_init/pg_doio. Signed-off-by: Peng Tao Signed-off-by: Boaz Harrosh Signed-off-by: Trond Myklebust --- fs/nfs/pagelist.c | 2 ++ include/linux/nfs_page.h | 1 + include/linux/nfs_xdr.h | 1 + 3 files changed, 4 insertions(+) diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 1a6732ed04a4..311a79681e2b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -49,6 +49,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, hdr->io_start = req_offset(hdr->req); hdr->good_bytes = desc->pg_count; hdr->dreq = desc->pg_dreq; + hdr->layout_private = desc->pg_layout_private; hdr->release = release; hdr->completion_ops = desc->pg_completion_ops; if (hdr->completion_ops->init_hdr) @@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, desc->pg_error = 0; desc->pg_lseg = NULL; desc->pg_dreq = NULL; + desc->pg_layout_private = NULL; } EXPORT_SYMBOL_GPL(nfs_pageio_init); diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 880805774f9f..92ce5783b707 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -69,6 +69,7 @@ struct nfs_pageio_descriptor { const struct nfs_pgio_completion_ops *pg_completion_ops; struct pnfs_layout_segment *pg_lseg; struct nfs_direct_req *pg_dreq; + void *pg_layout_private; }; #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 00485e084394..ac7c8ae254f2 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1248,6 +1248,7 @@ struct nfs_pgio_header { void (*release) (struct nfs_pgio_header *hdr); const struct nfs_pgio_completion_ops *completion_ops; struct nfs_direct_req *dreq; + void *layout_private; spinlock_t lock; /* fields protected by lock */ int pnfs_error; -- GitLab From 7de6e28417c65919cf2c1621841a650c4a3afbbd Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 2 Aug 2012 15:38:23 +0300 Subject: [PATCH 5067/5711] pnfs-obj: Better IO pattern in case of unaligned offset Depending on layout and ARCH, ORE has some limits on max IO sizes which is communicated on (what else) ore_layout->max_io_length, which is always stripe aligned. This was considered as the pg_test boundary for splitting and starting a new IO. But in the case of a long IO where the start offset is not aligned what would happen is that both end of IO[N] and start of IO[N+1] would be unaligned, causing each IO boundary parity unit to be calculated and written twice. So what we do in this patch is split the very start of an unaligned IO, up to a stripe boundary, and then next IO's can continue fully aligned til the end. We might be sacrificing the case where the full unaligned IO would fit within a single max_io_length, but the sacrifice is well worth the elimination of double calculation and parity units IO. Actually the sacrificing is marginal and is almost unmeasurable. TODO: If we know the total expected linear segment that will be received, at pg_init, we could use that information in many places: 1. blocks-layout get_layout write segment size 2. Better mds-threshold 3. In above situation for a better clean split I will do this in future submission. Signed-off-by: Boaz Harrosh Signed-off-by: Trond Myklebust --- fs/nfs/objlayout/objio_osd.c | 55 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index f50d3e8d6f22..ea6d111b03e9 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -570,17 +570,66 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, return false; return pgio->pg_count + req->wb_bytes <= - OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; + (unsigned long)pgio->pg_layout_private; +} + +void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + pnfs_generic_pg_init_read(pgio, req); + if (unlikely(pgio->pg_lseg == NULL)) + return; /* Not pNFS */ + + pgio->pg_layout_private = (void *) + OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; +} + +static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, + unsigned long *stripe_end) +{ + u32 stripe_off; + unsigned stripe_size; + + if (layout->raid_algorithm == PNFS_OSD_RAID_0) + return true; + + stripe_size = layout->stripe_unit * + (layout->group_width - layout->parity); + + div_u64_rem(offset, stripe_size, &stripe_off); + if (!stripe_off) + return true; + + *stripe_end = stripe_size - stripe_off; + return false; +} + +void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + unsigned long stripe_end = 0; + + pnfs_generic_pg_init_write(pgio, req); + if (unlikely(pgio->pg_lseg == NULL)) + return; /* Not pNFS */ + + if (req->wb_offset || + !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, + &OBJIO_LSEG(pgio->pg_lseg)->layout, + &stripe_end)) { + pgio->pg_layout_private = (void *)stripe_end; + } else { + pgio->pg_layout_private = (void *) + OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; + } } static const struct nfs_pageio_ops objio_pg_read_ops = { - .pg_init = pnfs_generic_pg_init_read, + .pg_init = objio_init_read, .pg_test = objio_pg_test, .pg_doio = pnfs_generic_pg_readpages, }; static const struct nfs_pageio_ops objio_pg_write_ops = { - .pg_init = pnfs_generic_pg_init_write, + .pg_init = objio_init_write, .pg_test = objio_pg_test, .pg_doio = pnfs_generic_pg_writepages, }; -- GitLab From 9e2760d18b3cf179534bbc27692c84879c61b97c Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 28 Jul 2012 00:20:34 +0200 Subject: [PATCH 5068/5711] m68k: Make sys_atomic_cmpxchg_32 work on classic m68k User space access must always go through uaccess accessors, since on classic m68k user space and kernel space are completely separate. Signed-off-by: Andreas Schwab Tested-by: Thorsten Glaser Signed-off-by: Geert Uytterhoeven Cc: stable@vger.kernel.org --- arch/m68k/kernel/sys_m68k.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 8623f8dc16f8..9a5932ec3689 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -479,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, goto bad_access; } - mem_value = *mem; + /* + * No need to check for EFAULT; we know that the page is + * present and writable. + */ + __get_user(mem_value, mem); if (mem_value == oldval) - *mem = newval; + __put_user(newval, mem); pte_unmap_unlock(pte, ptl); up_read(&mm->mmap_sem); -- GitLab From 0d7614f09c1ebdbaa1599a5aba7593f147bf96ee Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 2 Aug 2012 16:38:10 -0700 Subject: [PATCH 5069/5711] Linux 3.6-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8e4c0a7d402b..ddf5be952e45 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 -PATCHLEVEL = 5 +PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- GitLab From 7405ed10f6adcdd556d59c360b5b216fccada3d9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Aug 2012 21:01:17 -0300 Subject: [PATCH 5070/5711] perf session: Remove no longer used synthesize_sample method Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-jd8tqbx8o8bs4t4g50vyhoc2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 8 -------- tools/perf/util/session.h | 4 ---- 2 files changed, 12 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7d07324db41c..2437fb0b463a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -16,14 +16,6 @@ #include "cpumap.h" #include "event-parse.h" -int perf_session__synthesize_sample(struct perf_session *session, - union perf_event *event, - const struct perf_sample *sample) -{ - return perf_event__synthesize_sample(event, perf_evlist__sample_type(session->evlist), - sample, session->header.needs_swap); -} - static int perf_session__open(struct perf_session *self, bool force) { struct stat input_stat; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7389fb1f010a..1f7ec87db7d7 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -126,10 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); -int perf_session__synthesize_sample(struct perf_session *session, - union perf_event *event, - const struct perf_sample *sample); - struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -- GitLab From f3946fb6e50b750d34f445188fa6746d14596afa Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Tue, 31 Jul 2012 17:41:08 +0200 Subject: [PATCH 5071/5711] ACPI: Untangle a return statement for better readability No functional change. Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/numa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index e56f3be7b07d..2a6399345c85 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -304,8 +304,10 @@ int __init acpi_numa_init(void) acpi_numa_arch_fixup(); - if (cnt <= 0) - return cnt ?: -ENOENT; + if (cnt < 0) + return cnt; + else if (cnt == 0) + return -ENOENT; return 0; } -- GitLab From 095adbb6441172985f5ddc3b9e88cb3191bdeac4 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Tue, 31 Jul 2012 17:41:09 +0200 Subject: [PATCH 5072/5711] ACPI: Only count valid srat memory structures Otherwise you could run into: WARN_ON in numa_register_memblks(), because node_possible_map is zero References: https://bugzilla.novell.com/show_bug.cgi?id=757888 On this machine (ProLiant ML570 G3) the SRAT table contains: - No processor affinities - One memory affinity structure (which is set disabled) CC: Per Jessen CC: Andi Kleen Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- arch/ia64/kernel/acpi.c | 5 +++-- arch/x86/mm/srat.c | 15 ++++++++------- drivers/acpi/numa.c | 8 +++++--- include/linux/acpi.h | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 6f38b6120d96..440578850ae5 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -497,7 +497,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) srat_num_cpus++; } -void __init +int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) { unsigned long paddr, size; @@ -512,7 +512,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) /* Ignore disabled entries */ if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) - return; + return -1; /* record this node in proximity bitmap */ pxm_bit_set(pxm); @@ -531,6 +531,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) p->size = size; p->nid = pxm; num_node_memblks++; + return 0; } void __init acpi_numa_arch_fixup(void) diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 4599c3e8bcb6..4ddf497ca65b 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -142,23 +142,23 @@ static inline int save_add_info(void) {return 0;} #endif /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ -void __init +int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) { u64 start, end; int node, pxm; if (srat_disabled()) - return; + return -1; if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) { bad_srat(); - return; + return -1; } if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) - return; + return -1; if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info()) - return; + return -1; start = ma->base_address; end = start + ma->length; pxm = ma->proximity_domain; @@ -168,12 +168,12 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains.\n"); bad_srat(); - return; + return -1; } if (numa_add_memblk(node, start, end) < 0) { bad_srat(); - return; + return -1; } node_set(node, numa_nodes_parsed); @@ -181,6 +181,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n", node, pxm, (unsigned long long) start, (unsigned long long) end - 1); + return 0; } void __init acpi_numa_arch_fixup(void) {} diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 2a6399345c85..cb31298ca684 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -237,6 +237,8 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header, return 0; } +static int __initdata parsed_numa_memblks; + static int __init acpi_parse_memory_affinity(struct acpi_subtable_header * header, const unsigned long end) @@ -250,8 +252,8 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header, acpi_table_print_srat_entry(header); /* let architecture-dependent part to do it */ - acpi_numa_memory_affinity_init(memory_affinity); - + if (!acpi_numa_memory_affinity_init(memory_affinity)) + parsed_numa_memblks++; return 0; } @@ -306,7 +308,7 @@ int __init acpi_numa_init(void) if (cnt < 0) return cnt; - else if (cnt == 0) + else if (!parsed_numa_memblks) return -ENOENT; return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3ad510b25283..4f2a76224509 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -96,7 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); -void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); +int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); void acpi_numa_arch_fixup(void); #ifdef CONFIG_ACPI_HOTPLUG_CPU -- GitLab From b7db60f45d74497c723dc7ae1370cf0b37dfb0d8 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 31 Jul 2012 12:44:43 +0800 Subject: [PATCH 5073/5711] ACPI processor: Fix tick_broadcast_mask online/offline regression In commit 99b725084 "ACPI processor hotplug: Delay acpi_processor_start() call for hotplugged cores", acpi_processor_hotplug(pr) was wrongly replaced by acpi_processor_cst_has_changed() inside the acpi_cpu_soft_notify(). This patch will restore it back, fixing the tick_broadcast_mask regression: https://lkml.org/lkml/2012/7/30/169 Signed-off-by: Feng Tang Cc: Thomas Renninger Cc: # 3.3+ Reviewed-by: Rafael J. Wysocki Reviewed-by: Deepthi Dharwar Signed-off-by: Len Brown --- drivers/acpi/processor_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0734086537b8..bbac51e79d1f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -442,7 +442,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, /* Normal CPU soft online event */ } else { acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_cst_has_changed(pr); + acpi_processor_hotplug(pr); acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } -- GitLab From e2b34fa0466500de7814fc4e492689cee5ac120b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 27 Jul 2012 07:53:02 +1000 Subject: [PATCH 5074/5711] drm/nve0/fifo: add support for the flip completion swmthd Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nve0_fifo.c | 37 +++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c index 1855ecbd843b..e98d144e6eb9 100644 --- a/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -294,6 +294,25 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) printk(" on channel 0x%010llx\n", (u64)inst << 12); } +static int +nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +{ + struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (likely(chid >= 0 && chid < priv->base.channels)) { + chan = dev_priv->channels.ptr[chid]; + if (likely(chan)) + ret = nouveau_finish_page_flip(chan, NULL); + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return ret; +} + static void nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) { @@ -303,11 +322,21 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; u32 subc = (addr & 0x00070000); u32 mthd = (addr & 0x00003ffc); + u32 show = stat; + + if (stat & 0x00200000) { + if (mthd == 0x0054) { + if (!nve0_fifo_page_flip(dev, chid)) + show &= ~0x00200000; + } + } - NV_INFO(dev, "PSUBFIFO %d:", unit); - nouveau_bitfield_print(nve0_fifo_subfifo_intr, stat); - NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); + if (show) { + NV_INFO(dev, "PFIFO%d:", unit); + nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); + NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", + unit, chid, subc, mthd, data); + } nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); -- GitLab From 1f3f7eceff47f9e320ca67b3e9f16fb295106514 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 25 Jun 2012 13:36:14 +0530 Subject: [PATCH 5075/5711] usb: musb: Fix wrong config for am33xx and ti81xx Commit "bb6abcf: ARM: OMAP2+: Kconfig: convert SOC_OMAPAM33XX to SOC_AM33XX" and "3395955: ARM: OMAP2+: Kconfig: convert SOC_OMAPTI81XX to SOC_TI81XX" has changed the SOC config for AM33XX and TI81XX as shown below CONFIG_SOC_OMAPAM33XX --> CONFIG_SOC_AM33XX CONFIG_SOC_OMAPTI81XX --> CONFIG_SOC_TI81XX So updating the same at musb driver for AM33XX and TI81XX platforms. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index ef0c3f9f0947..6259f0d99324 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -8,7 +8,7 @@ config USB_MUSB_HDRC tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' depends on USB && USB_GADGET select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) - select NOP_USB_XCEIV if (SOC_OMAPTI81XX || SOC_OMAPAM33XX) + select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX) select TWL4030_USB if MACH_OMAP_3430SDP select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA select USB_OTG_UTILS @@ -57,7 +57,7 @@ config USB_MUSB_AM35X config USB_MUSB_DSPS tristate "TI DSPS platforms" - depends on SOC_OMAPTI81XX || SOC_OMAPAM33XX + depends on SOC_TI81XX || SOC_AM33XX config USB_MUSB_BLACKFIN tristate "Blackfin" -- GitLab From 3bb5534853dbb1e445a9b26ecab8ad331ff14a7e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 3 Jul 2012 17:37:10 +0530 Subject: [PATCH 5076/5711] usb: musb: am335x: fix pdev resource bug We are overwriting the resource->name to "mc" so that musb_core.c can understand it but this is also changing the platform device's resource->name as the "name" address remains same. Fixing the same by changing the resource->name field of local structure only. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 217808d9fbe1..dabe7b63654f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -479,9 +479,9 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) ret = -ENODEV; goto err0; } - strcpy((u8 *)res->name, "mc"); res->parent = NULL; resources[1] = *res; + resources[1].name = "mc"; /* allocate the child platform device */ musb = platform_device_alloc("musb-hdrc", -1); -- GitLab From 0e38c4ed83027e7e7d16568e43fb34a32c14f800 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 3 Jul 2012 17:37:11 +0530 Subject: [PATCH 5077/5711] usb: musb: reorder runtime pm call The clock need to be enabled before the musb_core platform device is created and registered. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index dabe7b63654f..494772fc9e23 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -566,27 +566,28 @@ static int __devinit dsps_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, glue); - /* create the child platform device for first instances of musb */ - ret = dsps_create_musb_pdev(glue, 0); - if (ret != 0) { - dev_err(&pdev->dev, "failed to create child pdev\n"); - goto err2; - } - /* enable the usbss clocks */ pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); + goto err2; + } + + /* create the child platform device for first instances of musb */ + ret = dsps_create_musb_pdev(glue, 0); + if (ret != 0) { + dev_err(&pdev->dev, "failed to create child pdev\n"); goto err3; } return 0; err3: - pm_runtime_disable(&pdev->dev); + pm_runtime_put(&pdev->dev); err2: + pm_runtime_disable(&pdev->dev); kfree(glue->wrp); err1: kfree(glue); -- GitLab From c810f9039f040681ec9d9f2983b748c193037297 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2012 12:48:32 +0200 Subject: [PATCH 5078/5711] ALSA: PCM: Fix possible memory leaks in the error path When the first page allocation failed for sgbuf, it leaks the records that have been formerly allocated. Signed-off-by: Takashi Iwai --- sound/core/sgbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 4e7ec2b49873..d0f00356fc11 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -101,7 +101,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, chunk, &tmpb) < 0) { if (!sgbuf->pages) - return NULL; + goto _failed; if (!res_size) goto _failed; size = sgbuf->pages * PAGE_SIZE; -- GitLab From fcfb7866af9a5d0280b7e51dd772990c636b7dec Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2012 12:51:21 +0200 Subject: [PATCH 5079/5711] ALSA: emu10k1: Avoid access to invalid pages when period=1 When period=1, the driver tries to allocate a bit bigger buffer than requested by the user due to the irq latency tolerance. This may lead to accesses over the actually allocated pages. This patch adds a check of the page index and assigns the silent page when it's over the given buffer size. Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/memory.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4f502a2bdc3c..0a436626182b 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -326,7 +326,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst for (page = blk->first_page; page <= blk->last_page; page++, idx++) { unsigned long ofs = idx << PAGE_SHIFT; dma_addr_t addr; - addr = snd_pcm_sgbuf_get_addr(substream, ofs); + if (ofs >= runtime->dma_bytes) + addr = emu->silent_page.addr; + else + addr = snd_pcm_sgbuf_get_addr(substream, ofs); if (! is_valid_page(emu, addr)) { printk(KERN_ERR "emu: failure page = %d\n", idx); mutex_unlock(&hdr->block_mutex); -- GitLab From 97a7dab42355d1332deef27c18b26cbeb3a2262b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 1 Aug 2012 22:11:08 -0300 Subject: [PATCH 5080/5711] ARM: imx6q-sabrelite: Setup CLKO IOMUX In order to have audio functional on mx6qsabrelite, it is necessary to setup the IOMUX for MX6Q_PAD_GPIO_0__CCM_CLKO pins as it provides the audio clock. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-sabrelite.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index d42e851ceb97..72f30f3e6171 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -53,6 +53,7 @@ fsl,pins = < 144 0x80000000 /* MX6Q_PAD_EIM_D22__GPIO_3_22 */ 121 0x80000000 /* MX6Q_PAD_EIM_D19__GPIO_3_19 */ + 953 0x80000000 /* MX6Q_PAD_GPIO_0__CCM_CLKO */ >; }; }; -- GitLab From 640bf0607c110b0be4da04b9d480bf0aad9de772 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 30 Jul 2012 21:29:18 -0300 Subject: [PATCH 5081/5711] ARM: mx23: Fix registers range Fix registers range. Cc: stable@vger.kernel.org Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx23.dtsi | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index a874dbfb5ae6..e6138310e5ce 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -51,11 +51,11 @@ dma-apbh@80004000 { compatible = "fsl,imx23-dma-apbh"; - reg = <0x80004000 2000>; + reg = <0x80004000 0x2000>; }; ecc@80008000 { - reg = <0x80008000 2000>; + reg = <0x80008000 0x2000>; status = "disabled"; }; @@ -63,7 +63,7 @@ compatible = "fsl,imx23-gpmi-nand"; #address-cells = <1>; #size-cells = <1>; - reg = <0x8000c000 2000>, <0x8000a000 2000>; + reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>; reg-names = "gpmi-nand", "bch"; interrupts = <13>, <56>; interrupt-names = "gpmi-dma", "bch"; @@ -72,14 +72,14 @@ }; ssp0: ssp@80010000 { - reg = <0x80010000 2000>; + reg = <0x80010000 0x2000>; interrupts = <15 14>; fsl,ssp-dma-channel = <1>; status = "disabled"; }; etm@80014000 { - reg = <0x80014000 2000>; + reg = <0x80014000 0x2000>; status = "disabled"; }; @@ -87,7 +87,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx23-pinctrl", "simple-bus"; - reg = <0x80018000 2000>; + reg = <0x80018000 0x2000>; gpio0: gpio@0 { compatible = "fsl,imx23-gpio", "fsl,mxs-gpio"; @@ -273,32 +273,32 @@ }; emi@80020000 { - reg = <0x80020000 2000>; + reg = <0x80020000 0x2000>; status = "disabled"; }; dma-apbx@80024000 { compatible = "fsl,imx23-dma-apbx"; - reg = <0x80024000 2000>; + reg = <0x80024000 0x2000>; }; dcp@80028000 { - reg = <0x80028000 2000>; + reg = <0x80028000 0x2000>; status = "disabled"; }; pxp@8002a000 { - reg = <0x8002a000 2000>; + reg = <0x8002a000 0x2000>; status = "disabled"; }; ocotp@8002c000 { - reg = <0x8002c000 2000>; + reg = <0x8002c000 0x2000>; status = "disabled"; }; axi-ahb@8002e000 { - reg = <0x8002e000 2000>; + reg = <0x8002e000 0x2000>; status = "disabled"; }; @@ -310,14 +310,14 @@ }; ssp1: ssp@80034000 { - reg = <0x80034000 2000>; + reg = <0x80034000 0x2000>; interrupts = <2 20>; fsl,ssp-dma-channel = <2>; status = "disabled"; }; tvenc@80038000 { - reg = <0x80038000 2000>; + reg = <0x80038000 0x2000>; status = "disabled"; }; }; @@ -330,37 +330,37 @@ ranges; clkctl@80040000 { - reg = <0x80040000 2000>; + reg = <0x80040000 0x2000>; status = "disabled"; }; saif0: saif@80042000 { - reg = <0x80042000 2000>; + reg = <0x80042000 0x2000>; status = "disabled"; }; power@80044000 { - reg = <0x80044000 2000>; + reg = <0x80044000 0x2000>; status = "disabled"; }; saif1: saif@80046000 { - reg = <0x80046000 2000>; + reg = <0x80046000 0x2000>; status = "disabled"; }; audio-out@80048000 { - reg = <0x80048000 2000>; + reg = <0x80048000 0x2000>; status = "disabled"; }; audio-in@8004c000 { - reg = <0x8004c000 2000>; + reg = <0x8004c000 0x2000>; status = "disabled"; }; lradc@80050000 { - reg = <0x80050000 2000>; + reg = <0x80050000 0x2000>; status = "disabled"; }; @@ -370,26 +370,26 @@ }; i2c@80058000 { - reg = <0x80058000 2000>; + reg = <0x80058000 0x2000>; status = "disabled"; }; rtc@8005c000 { compatible = "fsl,imx23-rtc", "fsl,stmp3xxx-rtc"; - reg = <0x8005c000 2000>; + reg = <0x8005c000 0x2000>; interrupts = <22>; }; pwm: pwm@80064000 { compatible = "fsl,imx23-pwm"; - reg = <0x80064000 2000>; + reg = <0x80064000 0x2000>; #pwm-cells = <2>; fsl,pwm-number = <5>; status = "disabled"; }; timrot@80068000 { - reg = <0x80068000 2000>; + reg = <0x80068000 0x2000>; status = "disabled"; }; @@ -429,7 +429,7 @@ ranges; usbctrl@80080000 { - reg = <0x80080000 0x10000>; + reg = <0x80080000 0x40000>; status = "disabled"; }; }; -- GitLab From 0f06cde7347bff81a92395693ef977dc92756028 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 30 Jul 2012 21:29:19 -0300 Subject: [PATCH 5082/5711] ARM: mx28: Fix registers range Fix registers range. Cc: stable@vger.kernel.org Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28.dtsi | 74 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 787efac68da8..3fa6d190fab4 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -57,18 +57,18 @@ }; hsadc@80002000 { - reg = <0x80002000 2000>; + reg = <0x80002000 0x2000>; interrupts = <13 87>; status = "disabled"; }; dma-apbh@80004000 { compatible = "fsl,imx28-dma-apbh"; - reg = <0x80004000 2000>; + reg = <0x80004000 0x2000>; }; perfmon@80006000 { - reg = <0x80006000 800>; + reg = <0x80006000 0x800>; interrupts = <27>; status = "disabled"; }; @@ -77,7 +77,7 @@ compatible = "fsl,imx28-gpmi-nand"; #address-cells = <1>; #size-cells = <1>; - reg = <0x8000c000 2000>, <0x8000a000 2000>; + reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>; reg-names = "gpmi-nand", "bch"; interrupts = <88>, <41>; interrupt-names = "gpmi-dma", "bch"; @@ -86,28 +86,28 @@ }; ssp0: ssp@80010000 { - reg = <0x80010000 2000>; + reg = <0x80010000 0x2000>; interrupts = <96 82>; fsl,ssp-dma-channel = <0>; status = "disabled"; }; ssp1: ssp@80012000 { - reg = <0x80012000 2000>; + reg = <0x80012000 0x2000>; interrupts = <97 83>; fsl,ssp-dma-channel = <1>; status = "disabled"; }; ssp2: ssp@80014000 { - reg = <0x80014000 2000>; + reg = <0x80014000 0x2000>; interrupts = <98 84>; fsl,ssp-dma-channel = <2>; status = "disabled"; }; ssp3: ssp@80016000 { - reg = <0x80016000 2000>; + reg = <0x80016000 0x2000>; interrupts = <99 85>; fsl,ssp-dma-channel = <3>; status = "disabled"; @@ -117,7 +117,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-pinctrl", "simple-bus"; - reg = <0x80018000 2000>; + reg = <0x80018000 0x2000>; gpio0: gpio@0 { compatible = "fsl,imx28-gpio", "fsl,mxs-gpio"; @@ -510,96 +510,96 @@ }; digctl@8001c000 { - reg = <0x8001c000 2000>; + reg = <0x8001c000 0x2000>; interrupts = <89>; status = "disabled"; }; etm@80022000 { - reg = <0x80022000 2000>; + reg = <0x80022000 0x2000>; status = "disabled"; }; dma-apbx@80024000 { compatible = "fsl,imx28-dma-apbx"; - reg = <0x80024000 2000>; + reg = <0x80024000 0x2000>; }; dcp@80028000 { - reg = <0x80028000 2000>; + reg = <0x80028000 0x2000>; interrupts = <52 53 54>; status = "disabled"; }; pxp@8002a000 { - reg = <0x8002a000 2000>; + reg = <0x8002a000 0x2000>; interrupts = <39>; status = "disabled"; }; ocotp@8002c000 { - reg = <0x8002c000 2000>; + reg = <0x8002c000 0x2000>; status = "disabled"; }; axi-ahb@8002e000 { - reg = <0x8002e000 2000>; + reg = <0x8002e000 0x2000>; status = "disabled"; }; lcdif@80030000 { compatible = "fsl,imx28-lcdif"; - reg = <0x80030000 2000>; + reg = <0x80030000 0x2000>; interrupts = <38 86>; status = "disabled"; }; can0: can@80032000 { compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; - reg = <0x80032000 2000>; + reg = <0x80032000 0x2000>; interrupts = <8>; status = "disabled"; }; can1: can@80034000 { compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; - reg = <0x80034000 2000>; + reg = <0x80034000 0x2000>; interrupts = <9>; status = "disabled"; }; simdbg@8003c000 { - reg = <0x8003c000 200>; + reg = <0x8003c000 0x200>; status = "disabled"; }; simgpmisel@8003c200 { - reg = <0x8003c200 100>; + reg = <0x8003c200 0x100>; status = "disabled"; }; simsspsel@8003c300 { - reg = <0x8003c300 100>; + reg = <0x8003c300 0x100>; status = "disabled"; }; simmemsel@8003c400 { - reg = <0x8003c400 100>; + reg = <0x8003c400 0x100>; status = "disabled"; }; gpiomon@8003c500 { - reg = <0x8003c500 100>; + reg = <0x8003c500 0x100>; status = "disabled"; }; simenet@8003c700 { - reg = <0x8003c700 100>; + reg = <0x8003c700 0x100>; status = "disabled"; }; armjtag@8003c800 { - reg = <0x8003c800 100>; + reg = <0x8003c800 0x100>; status = "disabled"; }; }; @@ -612,45 +612,45 @@ ranges; clkctl@80040000 { - reg = <0x80040000 2000>; + reg = <0x80040000 0x2000>; status = "disabled"; }; saif0: saif@80042000 { compatible = "fsl,imx28-saif"; - reg = <0x80042000 2000>; + reg = <0x80042000 0x2000>; interrupts = <59 80>; fsl,saif-dma-channel = <4>; status = "disabled"; }; power@80044000 { - reg = <0x80044000 2000>; + reg = <0x80044000 0x2000>; status = "disabled"; }; saif1: saif@80046000 { compatible = "fsl,imx28-saif"; - reg = <0x80046000 2000>; + reg = <0x80046000 0x2000>; interrupts = <58 81>; fsl,saif-dma-channel = <5>; status = "disabled"; }; lradc@80050000 { - reg = <0x80050000 2000>; + reg = <0x80050000 0x2000>; status = "disabled"; }; spdif@80054000 { - reg = <0x80054000 2000>; + reg = <0x80054000 0x2000>; interrupts = <45 66>; status = "disabled"; }; rtc@80056000 { compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc"; - reg = <0x80056000 2000>; + reg = <0x80056000 0x2000>; interrupts = <29>; }; @@ -658,7 +658,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-i2c"; - reg = <0x80058000 2000>; + reg = <0x80058000 0x2000>; interrupts = <111 68>; clock-frequency = <100000>; status = "disabled"; @@ -668,7 +668,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-i2c"; - reg = <0x8005a000 2000>; + reg = <0x8005a000 0x2000>; interrupts = <110 69>; clock-frequency = <100000>; status = "disabled"; @@ -676,14 +676,14 @@ pwm: pwm@80064000 { compatible = "fsl,imx28-pwm", "fsl,imx23-pwm"; - reg = <0x80064000 2000>; + reg = <0x80064000 0x2000>; #pwm-cells = <2>; fsl,pwm-number = <8>; status = "disabled"; }; timrot@80068000 { - reg = <0x80068000 2000>; + reg = <0x80068000 0x2000>; status = "disabled"; }; -- GitLab From 1a31fc904f1c897e4aaf7c3176e6aafa49f5d395 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 29 Jul 2012 20:53:03 -0600 Subject: [PATCH 5083/5711] perf top: Error handling for counter creation should parallel perf-record 5a7ed29 fixed up perf-record but not perf-top. Similar argument holds for it -- fallback to PMU only if it does not exist and handle invalid attributes separately. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Robert Richter Link: http://lkml.kernel.org/r/1343616783-6360-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 40264eaa9f0f..34096275a7b5 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -943,8 +943,10 @@ try_again: * based cpu-clock-tick sw counter, which * is always available even if no PMU support: */ - if (attr->type == PERF_TYPE_HARDWARE && - attr->config == PERF_COUNT_HW_CPU_CYCLES) { + if ((err == ENOENT || err == ENXIO) && + (attr->type == PERF_TYPE_HARDWARE) && + (attr->config == PERF_COUNT_HW_CPU_CYCLES)) { + if (verbose) ui__warning("Cycles event not supported,\n" "trying to fall back to cpu-clock-ticks\n"); -- GitLab From 56e6f602aa4432f7fe90a0d9ba379b2735b07b6b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 29 Jul 2012 20:53:51 -0600 Subject: [PATCH 5084/5711] perf tool: Save cmdline from user in file header vs what is passed to record A number of builtin commands process some user args and then pass the rest to cmd_record. cmd_record then saves argc/argv that it receives into the header of the perf data file. But this loses the arguments handled by the first command -- ie., the real command line from the user. This patch saves the command line as typed by the user rather than what was passed to cmd_record. As an example consider the command: $ perf kvm --guest --host --guestmount=/tmp/guest-mount record -fo /tmp/perf.data -ag -- sleep 10 Currently the command saved to the header is: cmdline : /tmp/p3.5/perf record -o perf.data.kvm -fo /tmp/perf.data -ag -- sleep 1 (ignore the duplicated -o -- the first would be yet another bug with perf-kvm). With this patch the command line saved to the header is: cmdline : /tmp/p3.5/perf kvm --guest --host --guestmount=/tmp/guest-mount record -fo /tmp/perf.data -ag -- sleep 1 v2: simplified to saving the command in parse_options per Stephane's suggestion Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1343616831-6408-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 -- tools/perf/util/header.c | 9 +++++++++ tools/perf/util/parse-options.c | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dc2b62565aa1..4db6e1ba54e3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -844,8 +844,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) struct perf_record *rec = &record; char errbuf[BUFSIZ]; - perf_header__set_cmdline(argc, argv); - evsel_list = perf_evlist__new(NULL, NULL); if (evsel_list == NULL) return -ENOMEM; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3a6d20443330..74ea3c2f8138 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -174,6 +174,15 @@ perf_header__set_cmdline(int argc, const char **argv) { int i; + /* + * If header_argv has already been set, do not override it. + * This allows a command to set the cmdline, parse args and + * then call another builtin function that implements a + * command -- e.g, cmd_kvm calling cmd_record. + */ + if (header_argv) + return 0; + header_argc = (u32)argc; /* do not include NULL termination */ diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 99d02aa57dbf..594f8fad5ecd 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -1,6 +1,7 @@ #include "util.h" #include "parse-options.h" #include "cache.h" +#include "header.h" #define OPT_SHORT 1 #define OPT_UNSET 2 @@ -413,6 +414,8 @@ int parse_options(int argc, const char **argv, const struct option *options, { struct parse_opt_ctx_t ctx; + perf_header__set_cmdline(argc, argv); + parse_options_start(&ctx, argc, argv, flags); switch (parse_options_step(&ctx, options, usagestr)) { case PARSE_OPT_HELP: -- GitLab From 347ed9903a10179d1cf733d5d77072b283d89da3 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 29 Jul 2012 20:54:35 -0600 Subject: [PATCH 5085/5711] perf kvm: Use strtol for walking guestmount directory Only want to process directories under the guestmnount directory that have a pid as a name (ie, all digits). Other entries in the guestmount directory should be ignored. There is already a check that requires the first character of each entry to be a digit, but atoi is used to convert the directory name to a pid. For example if guestmount contains a directory with the name 1foo, atoi converts it to a pid of 1 and a machine is created with a pid of 1. This is wrong; this directory really should be ignored. Use strtol to do that. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343616875-6455-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fe86612afadc..8b63b678e127 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2875,6 +2875,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) int i, items = 0; char path[PATH_MAX]; pid_t pid; + char *endp; if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || @@ -2891,7 +2892,14 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) /* Filter out . and .. */ continue; } - pid = atoi(namelist[i]->d_name); + pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10); + if ((*endp != '\0') || + (endp == namelist[i]->d_name) || + (errno == ERANGE)) { + pr_debug("invalid directory (%s). Skipping.\n", + namelist[i]->d_name); + continue; + } sprintf(path, "%s/%s/proc/kallsyms", symbol_conf.guestmount, namelist[i]->d_name); -- GitLab From 37bbd3fff1480a1f5d57abb9e9e56f468954c1b1 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 Jul 2012 22:31:32 -0600 Subject: [PATCH 5086/5711] perf tools: Introducing rblist rblist is the rbtree based code from strlist. It will be the common code for strlist and the to-be-introduced intlist. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343709095-7089-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 + tools/perf/util/rblist.c | 107 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/rblist.h | 47 +++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 tools/perf/util/rblist.c create mode 100644 tools/perf/util/rblist.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 77f124fe57ad..285f700a7836 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -319,6 +319,7 @@ LIB_H += $(ARCH_INCLUDE) LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h +LIB_H += util/rblist.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -383,6 +384,7 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o LIB_OBJS += $(OUTPUT)util/cpumap.o LIB_OBJS += $(OUTPUT)util/cgroup.o LIB_OBJS += $(OUTPUT)util/target.o +LIB_OBJS += $(OUTPUT)util/rblist.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c new file mode 100644 index 000000000000..0171fb611004 --- /dev/null +++ b/tools/perf/util/rblist.c @@ -0,0 +1,107 @@ +/* + * Based on strlist.c by: + * (c) 2009 Arnaldo Carvalho de Melo + * + * Licensed under the GPLv2. + */ + +#include +#include +#include + +#include "rblist.h" + +int rblist__add_node(struct rblist *rblist, const void *new_entry) +{ + struct rb_node **p = &rblist->entries.rb_node; + struct rb_node *parent = NULL, *new_node; + + while (*p != NULL) { + int rc; + + parent = *p; + + rc = rblist->node_cmp(parent, new_entry); + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return -EEXIST; + } + + new_node = rblist->node_new(rblist, new_entry); + if (new_node == NULL) + return -ENOMEM; + + rb_link_node(new_node, parent, p); + rb_insert_color(new_node, &rblist->entries); + ++rblist->nr_entries; + + return 0; +} + +void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) +{ + rb_erase(rb_node, &rblist->entries); + rblist->node_delete(rblist, rb_node); +} + +struct rb_node *rblist__find(struct rblist *rblist, const void *entry) +{ + struct rb_node **p = &rblist->entries.rb_node; + struct rb_node *parent = NULL; + + while (*p != NULL) { + int rc; + + parent = *p; + + rc = rblist->node_cmp(parent, entry); + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return parent; + } + + return NULL; +} + +void rblist__init(struct rblist *rblist) +{ + if (rblist != NULL) { + rblist->entries = RB_ROOT; + rblist->nr_entries = 0; + } + + return; +} + +void rblist__delete(struct rblist *rblist) +{ + if (rblist != NULL) { + struct rb_node *pos, *next = rb_first(&rblist->entries); + + while (next) { + pos = next; + next = rb_next(pos); + rb_erase(pos, &rblist->entries); + rblist->node_delete(rblist, pos); + } + free(rblist); + } +} + +struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) +{ + struct rb_node *node; + + for (node = rb_first(&rblist->entries); node; node = rb_next(node)) { + if (!idx--) + return node; + } + + return NULL; +} diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h new file mode 100644 index 000000000000..6d0cae5ae83d --- /dev/null +++ b/tools/perf/util/rblist.h @@ -0,0 +1,47 @@ +#ifndef __PERF_RBLIST_H +#define __PERF_RBLIST_H + +#include +#include + +/* + * create node structs of the form: + * struct my_node { + * struct rb_node rb_node; + * ... my data ... + * }; + * + * create list structs of the form: + * struct mylist { + * struct rblist rblist; + * ... my data ... + * }; + */ + +struct rblist { + struct rb_root entries; + unsigned int nr_entries; + + int (*node_cmp)(struct rb_node *rbn, const void *entry); + struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry); + void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node); +}; + +void rblist__init(struct rblist *rblist); +void rblist__delete(struct rblist *rblist); +int rblist__add_node(struct rblist *rblist, const void *new_entry); +void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); +struct rb_node *rblist__find(struct rblist *rblist, const void *entry); +struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); + +static inline bool rblist__empty(const struct rblist *rblist) +{ + return rblist->nr_entries == 0; +} + +static inline unsigned int rblist__nr_entries(const struct rblist *rblist) +{ + return rblist->nr_entries; +} + +#endif /* __PERF_RBLIST_H */ -- GitLab From ee8dd3ca43f151d9fbe1edeef68fb8a77eb9f047 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 Jul 2012 22:31:33 -0600 Subject: [PATCH 5087/5711] perf tools: Change strlist to use the new rblist Replaces the direct use of rbtree code with the rblist API. In the end the patch is a no-op on strlist functionality; the API for strlist is not changed, only its implementaton. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343709095-7089-3-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/strlist.c | 130 +++++++++++++++----------------------- tools/perf/util/strlist.h | 11 ++-- 2 files changed, 57 insertions(+), 84 deletions(-) diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index 6783a2043555..95856ff3dda4 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c @@ -10,23 +10,28 @@ #include #include -static struct str_node *str_node__new(const char *s, bool dupstr) +static +struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry) { - struct str_node *self = malloc(sizeof(*self)); + const char *s = entry; + struct rb_node *rc = NULL; + struct strlist *strlist = container_of(rblist, struct strlist, rblist); + struct str_node *snode = malloc(sizeof(*snode)); - if (self != NULL) { - if (dupstr) { + if (snode != NULL) { + if (strlist->dupstr) { s = strdup(s); if (s == NULL) goto out_delete; } - self->s = s; + snode->s = s; + rc = &snode->rb_node; } - return self; + return rc; out_delete: - free(self); + free(snode); return NULL; } @@ -37,36 +42,26 @@ static void str_node__delete(struct str_node *self, bool dupstr) free(self); } -int strlist__add(struct strlist *self, const char *new_entry) +static +void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node) { - struct rb_node **p = &self->entries.rb_node; - struct rb_node *parent = NULL; - struct str_node *sn; - - while (*p != NULL) { - int rc; - - parent = *p; - sn = rb_entry(parent, struct str_node, rb_node); - rc = strcmp(sn->s, new_entry); - - if (rc > 0) - p = &(*p)->rb_left; - else if (rc < 0) - p = &(*p)->rb_right; - else - return -EEXIST; - } + struct strlist *slist = container_of(rblist, struct strlist, rblist); + struct str_node *snode = container_of(rb_node, struct str_node, rb_node); - sn = str_node__new(new_entry, self->dupstr); - if (sn == NULL) - return -ENOMEM; + str_node__delete(snode, slist->dupstr); +} - rb_link_node(&sn->rb_node, parent, p); - rb_insert_color(&sn->rb_node, &self->entries); - ++self->nr_entries; +static int strlist__node_cmp(struct rb_node *rb_node, const void *entry) +{ + const char *str = entry; + struct str_node *snode = container_of(rb_node, struct str_node, rb_node); + + return strcmp(snode->s, str); +} - return 0; +int strlist__add(struct strlist *self, const char *new_entry) +{ + return rblist__add_node(&self->rblist, new_entry); } int strlist__load(struct strlist *self, const char *filename) @@ -96,34 +91,20 @@ out: return err; } -void strlist__remove(struct strlist *self, struct str_node *sn) +void strlist__remove(struct strlist *slist, struct str_node *snode) { - rb_erase(&sn->rb_node, &self->entries); - str_node__delete(sn, self->dupstr); + str_node__delete(snode, slist->dupstr); } -struct str_node *strlist__find(struct strlist *self, const char *entry) +struct str_node *strlist__find(struct strlist *slist, const char *entry) { - struct rb_node **p = &self->entries.rb_node; - struct rb_node *parent = NULL; - - while (*p != NULL) { - struct str_node *sn; - int rc; - - parent = *p; - sn = rb_entry(parent, struct str_node, rb_node); - rc = strcmp(sn->s, entry); - - if (rc > 0) - p = &(*p)->rb_left; - else if (rc < 0) - p = &(*p)->rb_right; - else - return sn; - } + struct str_node *snode = NULL; + struct rb_node *rb_node = rblist__find(&slist->rblist, entry); - return NULL; + if (rb_node) + snode = container_of(rb_node, struct str_node, rb_node); + + return snode; } static int strlist__parse_list_entry(struct strlist *self, const char *s) @@ -156,9 +137,12 @@ struct strlist *strlist__new(bool dupstr, const char *slist) struct strlist *self = malloc(sizeof(*self)); if (self != NULL) { - self->entries = RB_ROOT; + rblist__init(&self->rblist); + self->rblist.node_cmp = strlist__node_cmp; + self->rblist.node_new = strlist__node_new; + self->rblist.node_delete = strlist__node_delete; + self->dupstr = dupstr; - self->nr_entries = 0; if (slist && strlist__parse_list(self, slist) != 0) goto out_error; } @@ -171,30 +155,18 @@ out_error: void strlist__delete(struct strlist *self) { - if (self != NULL) { - struct str_node *pos; - struct rb_node *next = rb_first(&self->entries); - - while (next) { - pos = rb_entry(next, struct str_node, rb_node); - next = rb_next(&pos->rb_node); - strlist__remove(self, pos); - } - self->entries = RB_ROOT; - free(self); - } + if (self != NULL) + rblist__delete(&self->rblist); } -struct str_node *strlist__entry(const struct strlist *self, unsigned int idx) +struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx) { - struct rb_node *nd; + struct str_node *snode = NULL; + struct rb_node *rb_node; - for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { - struct str_node *pos = rb_entry(nd, struct str_node, rb_node); + rb_node = rblist__entry(&slist->rblist, idx); + if (rb_node) + snode = container_of(rb_node, struct str_node, rb_node); - if (!idx--) - return pos; - } - - return NULL; + return snode; } diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index 3ba839007d2c..dd9f922ec67c 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h @@ -4,14 +4,15 @@ #include #include +#include "rblist.h" + struct str_node { struct rb_node rb_node; const char *s; }; struct strlist { - struct rb_root entries; - unsigned int nr_entries; + struct rblist rblist; bool dupstr; }; @@ -32,18 +33,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry) static inline bool strlist__empty(const struct strlist *self) { - return self->nr_entries == 0; + return rblist__empty(&self->rblist); } static inline unsigned int strlist__nr_entries(const struct strlist *self) { - return self->nr_entries; + return rblist__nr_entries(&self->rblist); } /* For strlist iteration */ static inline struct str_node *strlist__first(struct strlist *self) { - struct rb_node *rn = rb_first(&self->entries); + struct rb_node *rn = rb_first(&self->rblist.entries); return rn ? rb_entry(rn, struct str_node, rb_node) : NULL; } static inline struct str_node *strlist__next(struct str_node *sn) -- GitLab From 70b40c4a43ddfcf7a06dad4be32ff1dd2b62be09 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 Jul 2012 22:31:34 -0600 Subject: [PATCH 5088/5711] perf tools: Introduce intlist Built on rblist - like strlist. Used in the next patch. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343709095-7089-4-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 + tools/perf/util/intlist.c | 101 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/intlist.h | 75 ++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 tools/perf/util/intlist.c create mode 100644 tools/perf/util/intlist.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 285f700a7836..32912af430f0 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -320,6 +320,7 @@ LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h LIB_H += util/rblist.h +LIB_H += util/intlist.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -385,6 +386,7 @@ LIB_OBJS += $(OUTPUT)util/cpumap.o LIB_OBJS += $(OUTPUT)util/cgroup.o LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o +LIB_OBJS += $(OUTPUT)util/intlist.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c new file mode 100644 index 000000000000..fd530dced9cb --- /dev/null +++ b/tools/perf/util/intlist.c @@ -0,0 +1,101 @@ +/* + * Based on intlist.c by: + * (c) 2009 Arnaldo Carvalho de Melo + * + * Licensed under the GPLv2. + */ + +#include +#include +#include + +#include "intlist.h" + +static struct rb_node *intlist__node_new(struct rblist *rblist __used, + const void *entry) +{ + int i = (int)((long)entry); + struct rb_node *rc = NULL; + struct int_node *node = malloc(sizeof(*node)); + + if (node != NULL) { + node->i = i; + rc = &node->rb_node; + } + + return rc; +} + +static void int_node__delete(struct int_node *ilist) +{ + free(ilist); +} + +static void intlist__node_delete(struct rblist *rblist __used, + struct rb_node *rb_node) +{ + struct int_node *node = container_of(rb_node, struct int_node, rb_node); + + int_node__delete(node); +} + +static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) +{ + int i = (int)((long)entry); + struct int_node *node = container_of(rb_node, struct int_node, rb_node); + + return node->i - i; +} + +int intlist__add(struct intlist *ilist, int i) +{ + return rblist__add_node(&ilist->rblist, (void *)((long)i)); +} + +void intlist__remove(struct intlist *ilist __used, struct int_node *node) +{ + int_node__delete(node); +} + +struct int_node *intlist__find(struct intlist *ilist, int i) +{ + struct int_node *node = NULL; + struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); + + if (rb_node) + node = container_of(rb_node, struct int_node, rb_node); + + return node; +} + +struct intlist *intlist__new(void) +{ + struct intlist *ilist = malloc(sizeof(*ilist)); + + if (ilist != NULL) { + rblist__init(&ilist->rblist); + ilist->rblist.node_cmp = intlist__node_cmp; + ilist->rblist.node_new = intlist__node_new; + ilist->rblist.node_delete = intlist__node_delete; + } + + return ilist; +} + +void intlist__delete(struct intlist *ilist) +{ + if (ilist != NULL) + rblist__delete(&ilist->rblist); +} + +struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) +{ + struct int_node *node = NULL; + struct rb_node *rb_node; + + rb_node = rblist__entry(&ilist->rblist, idx); + if (rb_node) + node = container_of(rb_node, struct int_node, rb_node); + + return node; +} diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h new file mode 100644 index 000000000000..6d63ab90db50 --- /dev/null +++ b/tools/perf/util/intlist.h @@ -0,0 +1,75 @@ +#ifndef __PERF_INTLIST_H +#define __PERF_INTLIST_H + +#include +#include + +#include "rblist.h" + +struct int_node { + struct rb_node rb_node; + int i; +}; + +struct intlist { + struct rblist rblist; +}; + +struct intlist *intlist__new(void); +void intlist__delete(struct intlist *ilist); + +void intlist__remove(struct intlist *ilist, struct int_node *in); +int intlist__add(struct intlist *ilist, int i); + +struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); +struct int_node *intlist__find(struct intlist *ilist, int i); + +static inline bool intlist__has_entry(struct intlist *ilist, int i) +{ + return intlist__find(ilist, i) != NULL; +} + +static inline bool intlist__empty(const struct intlist *ilist) +{ + return rblist__empty(&ilist->rblist); +} + +static inline unsigned int intlist__nr_entries(const struct intlist *ilist) +{ + return rblist__nr_entries(&ilist->rblist); +} + +/* For intlist iteration */ +static inline struct int_node *intlist__first(struct intlist *ilist) +{ + struct rb_node *rn = rb_first(&ilist->rblist.entries); + return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; +} +static inline struct int_node *intlist__next(struct int_node *in) +{ + struct rb_node *rn; + if (!in) + return NULL; + rn = rb_next(&in->rb_node); + return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; +} + +/** + * intlist_for_each - iterate over a intlist + * @pos: the &struct int_node to use as a loop cursor. + * @ilist: the &struct intlist for loop. + */ +#define intlist__for_each(pos, ilist) \ + for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) + +/** + * intlist_for_each_safe - iterate over a intlist safe against removal of + * int_node + * @pos: the &struct int_node to use as a loop cursor. + * @n: another &struct int_node to use as temporary storage. + * @ilist: the &struct intlist for loop. + */ +#define intlist__for_each_safe(pos, n, ilist) \ + for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ + pos = n, n = intlist__next(n)) +#endif /* __PERF_INTLIST_H */ -- GitLab From 6b118e92cc78ccef7b54a296158d4738fd377bcc Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 Jul 2012 22:31:35 -0600 Subject: [PATCH 5089/5711] perf kvm top: Limit guest kernel info message to once 'perf kvm top' shows a continual flurry of: Can't find guest [5201]'s kernel information if it can't find the guest info and with a lot of VMs running a user has no chance of reading them all. Limit message to once per guest. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343709095-7089-5-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 34096275a7b5..68cd61ef6ac5 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -38,6 +38,7 @@ #include "util/cpumap.h" #include "util/xyarray.h" #include "util/sort.h" +#include "util/intlist.h" #include "util/debug.h" @@ -706,8 +707,16 @@ static void perf_event__process_sample(struct perf_tool *tool, int err; if (!machine && perf_guest) { - pr_err("Can't find guest [%d]'s kernel information\n", - event->ip.pid); + static struct intlist *seen; + + if (!seen) + seen = intlist__new(); + + if (!intlist__has_entry(seen, event->ip.pid)) { + pr_err("Can't find guest [%d]'s kernel information\n", + event->ip.pid); + intlist__add(seen, event->ip.pid); + } return; } -- GitLab From 7f309ed6453926a81e2a97d274f67f1e48f0d74c Mon Sep 17 00:00:00 2001 From: Palmer Cox Date: Sun, 29 Jul 2012 17:54:43 -0400 Subject: [PATCH 5090/5711] perf tools: Remove brace expansion from clean target The clean target uses brace expansion to remove some generated files. However, the default shells on many systems do not support this feature resulting in some generated files not being removed by clean. Signed-off-by: Palmer Cox Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1343598883-17907-1-git-send-email-p@lmercox.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 32912af430f0..35655c3a7b7a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -987,7 +987,8 @@ clean: $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS - $(RM) $(OUTPUT)util/*-{bison,flex}* + $(RM) $(OUTPUT)util/*-bison* + $(RM) $(OUTPUT)util/*-flex* $(python-clean) .PHONY: all install clean strip $(LIBTRACEEVENT) -- GitLab From 9579a974d1018c7f1d42455c29aa3f0d512c99fe Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 8 Jul 2012 13:37:42 +0200 Subject: [PATCH 5091/5711] iommu/tegra: remove invalid reference to list iterator variable If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. Replace c->dev by dev, which is the value that c->dev has been compared to. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Acked-by: Stephen Warren Acked-by: Hiroshi DOYU Signed-off-by: Joerg Roedel --- drivers/iommu/tegra-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 4ba325ab6262..a9bf4c30cd84 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -799,7 +799,7 @@ static void smmu_iommu_detach_dev(struct iommu_domain *domain, goto out; } } - dev_err(smmu->dev, "Couldn't find %s\n", dev_name(c->dev)); + dev_err(smmu->dev, "Couldn't find %s\n", dev_name(dev)); out: spin_unlock(&as->client_lock); } -- GitLab From d2900bd63f65bf1f40bf17f3c51457ae29fae6a8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 24 Jul 2012 16:18:14 +0200 Subject: [PATCH 5092/5711] iommu/intel: add missing free_domain_mem Add missing free_domain_mem on failure path after alloc_domain. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @km exists@ local idexpression e; expression e1,e2,e3; type T,T1; identifier f; @@ * e = alloc_domain(...) ... when any when != e = e1 when != e1 = (T)e when != e1(...,(T)e,...) when != &e->f if(...) { ... when != e2(...,(T1)e,...) when != e3 = e when forall ( return <+...e...+>; | * return ...; ) } // Signed-off-by: Julia Lawall Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 7469b5346643..0204b62480b0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2008,6 +2008,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) if (!drhd) { printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n", pci_name(pdev)); + free_domain_mem(domain); return NULL; } iommu = drhd->iommu; -- GitLab From 76582d0a68ab6c46987dd678165c26ad81c44cdb Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 25 Jul 2012 16:24:49 +0200 Subject: [PATCH 5093/5711] iommu: Include linux/types.h The linux/iommu.h header uses types defined in linux/types.h but doesn't include it. Signed-off-by: Thierry Reding Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 54d6d690073c..0a85199191b9 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -20,6 +20,7 @@ #define __LINUX_IOMMU_H #include +#include #define IOMMU_READ (1) #define IOMMU_WRITE (2) -- GitLab From ba1eabfade3272596000bf3c62b68ca375e48b08 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 3 Aug 2012 15:55:41 +0200 Subject: [PATCH 5094/5711] iommu: Add missing forward declaration in include file The 'struct notifier_block' is not used in linux/iommu.h but not declared anywhere. Add a forward declaration for it. Reported-by: Thierry Reding Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0a85199191b9..7e83370e6fd2 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -31,6 +31,7 @@ struct iommu_group; struct bus_type; struct device; struct iommu_domain; +struct notifier_block; /* iommu fault flags */ #define IOMMU_FAULT_READ 0x0 -- GitLab From d2453b2c7875dac9b323bff5d21981c41de177b1 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Mon, 30 Jul 2012 08:39:18 +0300 Subject: [PATCH 5095/5711] iommu/tegra: smmu: Cleanup with lesser nest Small clean up with lesser nest for readability. Signed-off-by: Hiroshi Doyu Signed-off-by: Joerg Roedel --- drivers/iommu/tegra-smmu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index a9bf4c30cd84..37669cc483b1 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -814,11 +814,14 @@ static int smmu_iommu_domain_init(struct iommu_domain *domain) /* Look for a free AS with lock held */ for (i = 0; i < smmu->num_as; i++) { as = &smmu->as[i]; - if (!as->pdir_page) { - err = alloc_pdir(as); - if (!err) - goto found; - } + + if (as->pdir_page) + continue; + + err = alloc_pdir(as); + if (!err) + goto found; + if (err != -EAGAIN) break; } -- GitLab From d1d076f16376066d0a51aa7d465f43059da71562 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Mon, 30 Jul 2012 08:39:19 +0300 Subject: [PATCH 5096/5711] iommu/tegra: smmu: Fix error initial value at domain_init err initial value should be -EAGAIN. Otherwise 2nd iteration always fails in the case as[0] is occupied. Signed-off-by: Hiroshi Doyu Signed-off-by: Joerg Roedel --- drivers/iommu/tegra-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 37669cc483b1..2a4bb36bc688 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -806,7 +806,7 @@ out: static int smmu_iommu_domain_init(struct iommu_domain *domain) { - int i, err = -ENODEV; + int i, err = -EAGAIN; unsigned long flags; struct smmu_as *as; struct smmu_device *smmu = smmu_handle; -- GitLab From eb51637b6ec73ff5f8eaca57658a9945aa7bd45f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 1 Aug 2012 14:35:17 +0530 Subject: [PATCH 5097/5711] iommu/exynos: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following build error introduced by commit 3177bb76a8 ("iommu/exynos: Implement DOMAIN_ATTR_GEOMETRY attribute"): drivers/iommu/exynos-iommu.c: In function ‘exynos_iommu_domain_init’: drivers/iommu/exynos-iommu.c:735:2: error: ‘dom’ undeclared (first use in this function) Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Signed-off-by: Joerg Roedel --- drivers/iommu/exynos-iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 45350ff5e93c..80bad32aa463 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -732,9 +732,9 @@ static int exynos_iommu_domain_init(struct iommu_domain *domain) spin_lock_init(&priv->pgtablelock); INIT_LIST_HEAD(&priv->clients); - dom->geometry.aperture_start = 0; - dom->geometry.aperture_end = ~0UL; - dom->geometry.force_aperture = true; + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = ~0UL; + domain->geometry.force_aperture = true; domain->priv = priv; return 0; -- GitLab From d4e5979c0da95791aa717c18e162540c7a596360 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 2 Aug 2012 11:58:50 +0530 Subject: [PATCH 5098/5711] ath9k: Add PID/VID support for AR1111 AR1111 is same as AR9485. The h/w difference between them is quite insignificant, Felix suggests only very few baseband features may not be available in AR1111. The h/w code for AR9485 is already present, so AR1111 should work fine with the addition of its PID/VID. Cc: stable@vger.kernel.org [2.6.39+] Cc: Felix Bitterli Reported-by: Tim Bentley Signed-off-by: Mohammed Shafi Shajakhan Tested-by: Tim Bentley Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/pci.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index cfa91ab7acf8..60b6a9daff7e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -730,6 +730,7 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_QCA955X: case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9462: + case AR9485_DEVID_AR1111: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dd0c146d81dc..ce7332c64efb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -49,6 +49,7 @@ #define AR9300_DEVID_AR9462 0x0034 #define AR9300_DEVID_AR9330 0x0035 #define AR9300_DEVID_QCA955X 0x0038 +#define AR9485_DEVID_AR1111 0x0037 #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 87b89d55e637..d455de9162ec 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -37,6 +37,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ + { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { 0 } }; -- GitLab From 8cc7a2b9f75355f60922db4adf27742ba7f2f6bc Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 26 Jul 2012 16:08:53 -0300 Subject: [PATCH 5099/5711] ARM: clk-imx31: Fix the keypad clock name Fix the keypad clock name, in order to fix the following error: imx-keypad imx-keypad: failed to get keypad clock imx-keypad: probe of imx-keypad failed with error -2 Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer Cc: stable@vger.kernel.org --- arch/arm/mach-imx/clk-imx31.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index 8e19e70f90f9..1253af2d9971 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -130,7 +130,7 @@ int __init mx31_clocks_init(unsigned long fref) clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0"); clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core"); clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); - clk_register_clkdev(clk[kpp_gate], "kpp", NULL); + clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad"); clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0"); clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0"); clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0"); -- GitLab From 68b0562df90a76ba964423986b2472c7e791729a Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 2 Aug 2012 22:28:49 +0800 Subject: [PATCH 5100/5711] ARM: imx: enable emi_slow_gate clock for imx5 The imx5 common clock migration causes a regression with smsc911x driver on imx53-ard board, where a smsc lan9220 controller gets connected on imx53 with EIM interface. EIM needs clock emi_slow_gate to be functional. In the new imx5 clock driver, there is no use count incremented for the clock by enabling it, so the framework closes the clock at late init time and makes EIM stop working then. Enable emi_slow_gate in clock driver initialization to fix the regression. Cc: stable@vger.kernel.org Signed-off-by: Shawn Guo Acked-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx51-imx53.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index f6086693ebd2..4bdcaa97bd98 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -303,6 +303,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_prepare_enable(clk[aips_tz2]); /* fec */ clk_prepare_enable(clk[spba]); clk_prepare_enable(clk[emi_fast_gate]); /* fec */ + clk_prepare_enable(clk[emi_slow_gate]); /* eim */ clk_prepare_enable(clk[tmax1]); clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */ clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */ -- GitLab From 1eec0c569523782392b5e6245effddb626213b8c Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 2 Aug 2012 22:48:39 +0800 Subject: [PATCH 5101/5711] ARM: dts: imx53-ard: add regulators for lan9220 Since commit c7e963f (net/smsc911x: Add regulator support), the lan9220 device tree probe fails on imx53-ard board, because the commit makes VDD33A and VDDVARIO supplies mandatory for the driver. Add a fixed dummy 3V3 supplying lan9220 to fix the regression. Cc: stable@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx53-ard.dts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index 5b8eafcdbeec..fa95f4aa8ce6 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -66,10 +66,30 @@ interrupt-parent = <&gpio2>; interrupts = <31>; reg-io-width = <4>; + /* + * VDD33A and VDDVARIO of LAN9220 are supplied by + * SW4_3V3 of LTC3589. Before the regulator driver + * for this PMIC is available, we use a fixed dummy + * 3V3 regulator to get LAN9220 driver probing work. + */ + vdd33a-supply = <®_3p3v>; + vddvario-supply = <®_3p3v>; smsc,irq-push-pull; }; }; + regulators { + compatible = "simple-bus"; + + reg_3p3v: 3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + gpio-keys { compatible = "gpio-keys"; -- GitLab From 65dee07c9927d4af17b1832e4b7a1bb704607f91 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 2 Aug 2012 22:08:26 +0800 Subject: [PATCH 5102/5711] ARM: dts: imx: fix gpio interrupts property Commit 88cde8b (ARM: dts: imx: update #interrupt-cells for gpio nodes) changes gpio #interrupt-cells from 1 to 2 without updating the users. It causes the gpio irq requesting call failing in client driver's probe function. Add the irq type cell for those gpio interrupt users to fix their driver probe failure. Reported-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx51-babbage.dts | 2 +- arch/arm/boot/dts/imx53-ard.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts index de065b5976e6..cd86177a3ea2 100644 --- a/arch/arm/boot/dts/imx51-babbage.dts +++ b/arch/arm/boot/dts/imx51-babbage.dts @@ -53,7 +53,7 @@ spi-max-frequency = <6000000>; reg = <0>; interrupt-parent = <&gpio1>; - interrupts = <8>; + interrupts = <8 0x4>; regulators { sw1_reg: sw1 { diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index fa95f4aa8ce6..da895e93a999 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -64,7 +64,7 @@ reg = <0xf4000000 0x2000000>; phy-mode = "mii"; interrupt-parent = <&gpio2>; - interrupts = <31>; + interrupts = <31 0x8>; reg-io-width = <4>; /* * VDD33A and VDDVARIO of LAN9220 are supplied by -- GitLab From f0cd2dbb6cf387c11f87265462e370bb5469299e Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:11:59 +0300 Subject: [PATCH 5103/5711] vfs: kill write_super and sync_supers Finally we can kill the 'sync_supers' kernel thread along with the '->write_super()' superblock operation because all the users are gone. Now every file-system is supposed to self-manage own superblock and its dirty state. The nice thing about killing this thread is that it improves power management. Indeed, 'sync_supers' is a source of monotonic system wake-ups - it woke up every 5 seconds no matter what - even if there were no dirty superblocks and even if there were no file-systems using this service (e.g., btrfs and journalled ext4 do not need it). So it was wasting power most of the time. And because the thread was in the core of the kernel, all systems had to have it. So I am quite happy to make it go away. Interestingly, this thread is a left-over from the pdflush kernel thread which was a self-forking kernel thread responsible for all the write-back in old Linux kernels. It was turned into per-block device BDI threads, and 'sync_supers' was a left-over. Thus, R.I.P, pdflush as well. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/super.c | 40 ---------------------------- include/linux/backing-dev.h | 1 - include/linux/fs.h | 3 --- mm/backing-dev.c | 52 ------------------------------------- mm/page-writeback.c | 1 - 5 files changed, 97 deletions(-) diff --git a/fs/super.c b/fs/super.c index b05cf47463d0..0902cfa6a12e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -536,46 +536,6 @@ void drop_super(struct super_block *sb) EXPORT_SYMBOL(drop_super); -/** - * sync_supers - helper for periodic superblock writeback - * - * Call the write_super method if present on all dirty superblocks in - * the system. This is for the periodic writeback used by most older - * filesystems. For data integrity superblock writeback use - * sync_filesystems() instead. - * - * Note: check the dirty flag before waiting, so we don't - * hold up the sync while mounting a device. (The newly - * mounted device won't need syncing.) - */ -void sync_supers(void) -{ - struct super_block *sb, *p = NULL; - - spin_lock(&sb_lock); - list_for_each_entry(sb, &super_blocks, s_list) { - if (hlist_unhashed(&sb->s_instances)) - continue; - if (sb->s_op->write_super && sb->s_dirt) { - sb->s_count++; - spin_unlock(&sb_lock); - - down_read(&sb->s_umount); - if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN)) - sb->s_op->write_super(sb); - up_read(&sb->s_umount); - - spin_lock(&sb_lock); - if (p) - __put_super(p); - p = sb; - } - } - if (p) - __put_super(p); - spin_unlock(&sb_lock); -} - /** * iterate_supers - call function for all active superblocks * @f: function to call diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index c97c6b9cd38e..2a9a9abc9126 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -124,7 +124,6 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, void bdi_start_background_writeback(struct backing_dev_info *bdi); int bdi_writeback_thread(void *data); int bdi_has_dirty_io(struct backing_dev_info *bdi); -void bdi_arm_supers_timer(void); void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2); diff --git a/include/linux/fs.h b/include/linux/fs.h index 38dba16c4176..aa110476a95b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1491,7 +1491,6 @@ struct sb_writers { struct super_block { struct list_head s_list; /* Keep this first */ dev_t s_dev; /* search index; _not_ kdev_t */ - unsigned char s_dirt; unsigned char s_blocksize_bits; unsigned long s_blocksize; loff_t s_maxbytes; /* Max file size */ @@ -1861,7 +1860,6 @@ struct super_operations { int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); - void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -2397,7 +2395,6 @@ extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync); extern int vfs_fsync(struct file *file, int datasync); extern int generic_write_sync(struct file *file, loff_t pos, loff_t count); -extern void sync_supers(void); extern void emergency_sync(void); extern void emergency_remount(void); #ifdef CONFIG_BLOCK diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 6b4718e2ee34..b41823cc05e6 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -39,12 +39,6 @@ DEFINE_SPINLOCK(bdi_lock); LIST_HEAD(bdi_list); LIST_HEAD(bdi_pending_list); -static struct task_struct *sync_supers_tsk; -static struct timer_list sync_supers_timer; - -static int bdi_sync_supers(void *); -static void sync_supers_timer_fn(unsigned long); - void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2) { if (wb1 < wb2) { @@ -250,12 +244,6 @@ static int __init default_bdi_init(void) { int err; - sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers"); - BUG_ON(IS_ERR(sync_supers_tsk)); - - setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0); - bdi_arm_supers_timer(); - err = bdi_init(&default_backing_dev_info); if (!err) bdi_register(&default_backing_dev_info, NULL, "default"); @@ -270,46 +258,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi) return wb_has_dirty_io(&bdi->wb); } -/* - * kupdated() used to do this. We cannot do it from the bdi_forker_thread() - * or we risk deadlocking on ->s_umount. The longer term solution would be - * to implement sync_supers_bdi() or similar and simply do it from the - * bdi writeback thread individually. - */ -static int bdi_sync_supers(void *unused) -{ - set_user_nice(current, 0); - - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - - /* - * Do this periodically, like kupdated() did before. - */ - sync_supers(); - } - - return 0; -} - -void bdi_arm_supers_timer(void) -{ - unsigned long next; - - if (!dirty_writeback_interval) - return; - - next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies; - mod_timer(&sync_supers_timer, round_jiffies_up(next)); -} - -static void sync_supers_timer_fn(unsigned long unused) -{ - wake_up_process(sync_supers_tsk); - bdi_arm_supers_timer(); -} - static void wakeup_timer_fn(unsigned long data) { struct backing_dev_info *bdi = (struct backing_dev_info *)data; diff --git a/mm/page-writeback.c b/mm/page-writeback.c index e5363f34e025..5ad5ce23c1e0 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1532,7 +1532,6 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { proc_dointvec(table, write, buffer, length, ppos); - bdi_arm_supers_timer(); return 0; } -- GitLab From 34e5053fbe88800f5c2c6cbc849abb5a9f390974 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:00 +0300 Subject: [PATCH 5104/5711] Documentation: get rid of write_super The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from various pieces of the kernel documentation. Cc: Randy Dunlap Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- Documentation/DocBook/filesystems.tmpl | 4 ++-- Documentation/filesystems/Locking | 2 -- Documentation/filesystems/porting | 5 ++--- Documentation/filesystems/vfs.txt | 4 ---- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl index 3fca32c41927..25b58efd955d 100644 --- a/Documentation/DocBook/filesystems.tmpl +++ b/Documentation/DocBook/filesystems.tmpl @@ -224,8 +224,8 @@ all your transactions. -Then at umount time , in your put_super() (2.4) or write_super() (2.5) -you can then call journal_destroy() to clean up your in-core journal object. +Then at umount time , in your put_super() you can then call journal_destroy() +to clean up your in-core journal object. diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 0f103e39b4f6..e540a24e5d06 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -114,7 +114,6 @@ prototypes: int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); - void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -136,7 +135,6 @@ write_inode: drop_inode: !!!inode->i_lock!!! evict_inode: put_super: write -write_super: read sync_fs: read freeze_fs: write unfreeze_fs: write diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 2bef2b3843d1..0742feebc6e2 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -94,9 +94,8 @@ protected. --- [mandatory] -BKL is also moved from around sb operations. ->write_super() Is now called -without BKL held. BKL should have been shifted into individual fs sb_op -functions. If you don't need it, remove it. +BKL is also moved from around sb operations. BKL should have been shifted into +individual fs sb_op functions. If you don't need it, remove it. --- [informational] diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 065aa2dc0835..2ee133e030c3 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -216,7 +216,6 @@ struct super_operations { void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); - void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -273,9 +272,6 @@ or bottom half). put_super: called when the VFS wishes to free the superblock (i.e. unmount). This is called with the superblock lock held - write_super: called when the VFS superblock needs to be written to - disc. This method is optional - sync_fs: called when VFS is writing out all dirty data associated with a superblock. The second parameter indicates whether the method should wait until the write out has been completed. Optional. -- GitLab From f3f9f332e231abaf28e14344733b7d000b830f7c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 3 Aug 2012 02:36:51 +0000 Subject: [PATCH 5105/5711] emulex: benet: Add a missing CR in the end of message Missing a CR in printk causes 2 messages printed in one line. Signed-off-by: Masanari Iida Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index c60de89b6669..90a903d83d87 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1948,7 +1948,7 @@ static int be_rx_cqs_create(struct be_adapter *adapter) if (adapter->num_rx_qs != MAX_RX_QS) dev_info(&adapter->pdev->dev, - "Created only %d receive queues", adapter->num_rx_qs); + "Created only %d receive queues\n", adapter->num_rx_qs); return 0; } -- GitLab From 696ecdc10622d86541f2e35cc16e15b6b3b1b67e Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Fri, 3 Aug 2012 19:57:52 +0900 Subject: [PATCH 5106/5711] net_sched: gact: Fix potential panic in tcf_gact(). gact_rand array is accessed by gact->tcfg_ptype whose value is assumed to less than MAX_RAND, but any range checks are not performed. So add a check in tcf_gact_init(). And in tcf_gact(), we can reduce a branch. Signed-off-by: Hiroaki SHIMODA Signed-off-by: David S. Miller --- net/sched/act_gact.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index f10fb8256442..05d60859d8e3 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, struct tcf_common *pc; int ret = 0; int err; +#ifdef CONFIG_GACT_PROB + struct tc_gact_p *p_parm = NULL; +#endif if (nla == NULL) return -EINVAL; @@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, #ifndef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB] != NULL) return -EOPNOTSUPP; +#else + if (tb[TCA_GACT_PROB]) { + p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm->ptype >= MAX_RAND) + return -EINVAL; + } #endif pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); @@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, spin_lock_bh(&gact->tcf_lock); gact->tcf_action = parm->action; #ifdef CONFIG_GACT_PROB - if (tb[TCA_GACT_PROB] != NULL) { - struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm) { gact->tcfg_paction = p_parm->paction; gact->tcfg_pval = p_parm->pval; gact->tcfg_ptype = p_parm->ptype; @@ -133,7 +141,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, spin_lock(&gact->tcf_lock); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) + if (gact->tcfg_ptype) action = gact_rand[gact->tcfg_ptype](gact); else action = gact->tcf_action; -- GitLab From c8c40b7f32abe0878ee693480fb2f7453d80add5 Mon Sep 17 00:00:00 2001 From: Amir Vadai Date: Fri, 3 Aug 2012 00:38:36 +0000 Subject: [PATCH 5107/5711] net/mlx4_en: loopbacked packets are dropped when SMAC=DMAC Should NOT check SMAC=DMAC when: 1. loopback is turned on 2. validate_loopback is true. Fixed it accordingly. Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index f32e70300770..5aba5ecdf1e2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -614,8 +614,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud /* If source MAC is equal to our own MAC and not performing * the selftest or flb disabled - drop the packet */ if (s_mac == priv->mac && - (!(dev->features & NETIF_F_LOOPBACK) || - !priv->validate_loopback)) + !((dev->features & NETIF_F_LOOPBACK) || + priv->validate_loopback)) goto next; /* -- GitLab From c18520bd1b244fe8e3ac5358137321780a70d6e7 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Fri, 3 Aug 2012 00:38:37 +0000 Subject: [PATCH 5108/5711] net/mlx4_en: Fixing TX queue stop/wake flow Removing the ring->blocked flag, it is redundant and leads to a race: We close the TX queue and then set the "blocked" flag. Between those 2 operations the completion function can check the "blocked" flag, sees that it is 0, and wouldn't open the TX queue. Using netif_tx_queue_stopped to check the state of the queue to avoid this race. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 17 +++++++---------- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 019d856b1334..10bba09c44ea 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -164,7 +164,6 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, ring->cons = 0xffffffff; ring->last_nr_txbb = 1; ring->poll_cnt = 0; - ring->blocked = 0; memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info)); memset(ring->buf, 0, ring->buf_size); @@ -365,14 +364,13 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) ring->cons += txbbs_skipped; netdev_tx_completed_queue(ring->tx_queue, packets, bytes); - /* Wakeup Tx queue if this ring stopped it */ - if (unlikely(ring->blocked)) { - if ((u32) (ring->prod - ring->cons) <= - ring->size - HEADROOM - MAX_DESC_TXBBS) { - ring->blocked = 0; - netif_tx_wake_queue(ring->tx_queue); - priv->port_stats.wake_queue++; - } + /* + * Wakeup Tx queue if this stopped, and at least 1 packet + * was completed + */ + if (netif_tx_queue_stopped(ring->tx_queue) && txbbs_skipped > 0) { + netif_tx_wake_queue(ring->tx_queue); + priv->port_stats.wake_queue++; } } @@ -592,7 +590,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->size - HEADROOM - MAX_DESC_TXBBS)) { /* every full Tx ring stops queue */ netif_tx_stop_queue(ring->tx_queue); - ring->blocked = 1; priv->port_stats.queue_stopped++; 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 5f1ab105debc..9d27e42264e2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -248,7 +248,6 @@ struct mlx4_en_tx_ring { u32 doorbell_qpn; void *buf; u16 poll_cnt; - int blocked; struct mlx4_en_tx_info *tx_info; u8 *bounce_buf; u32 last_nr_txbb; -- GitLab From 2207b60ffb6545040e2e2620fced13deba7643c2 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Fri, 3 Aug 2012 00:38:38 +0000 Subject: [PATCH 5109/5711] net/mlx4_core: Remove port type restrictions Port1=Eth, Port2=IB restriction is no longer required. Having RoCE, there will always rdma port initialized over ConnectX physical port, no matter whether the link layer is IB or Ethernet. So we always have dual port IB device. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 3 --- drivers/net/ethernet/mellanox/mlx4/sense.c | 14 -------------- 2 files changed, 17 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 48d0e90194cb..827b72dfce99 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -157,9 +157,6 @@ int mlx4_check_port_params(struct mlx4_dev *dev, "on this HCA, aborting.\n"); return -EINVAL; } - if (port_type[i] == MLX4_PORT_TYPE_ETH && - port_type[i + 1] == MLX4_PORT_TYPE_IB) - return -EINVAL; } } diff --git a/drivers/net/ethernet/mellanox/mlx4/sense.c b/drivers/net/ethernet/mellanox/mlx4/sense.c index 802498293528..34ee09bae36e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/sense.c +++ b/drivers/net/ethernet/mellanox/mlx4/sense.c @@ -80,20 +80,6 @@ void mlx4_do_sense_ports(struct mlx4_dev *dev, stype[i - 1] = defaults[i - 1]; } - /* - * Adjust port configuration: - * If port 1 sensed nothing and port 2 is IB, set both as IB - * If port 2 sensed nothing and port 1 is Eth, set both as Eth - */ - if (stype[0] == MLX4_PORT_TYPE_ETH) { - for (i = 1; i < dev->caps.num_ports; i++) - stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_ETH; - } - if (stype[dev->caps.num_ports - 1] == MLX4_PORT_TYPE_IB) { - for (i = 0; i < dev->caps.num_ports - 1; i++) - stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_IB; - } - /* * If sensed nothing, remain in current configuration. */ -- GitLab From ae9e63bb2c0cf5437d9d13d822b27149336c6e0e Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Fri, 3 Aug 2012 09:32:18 +0000 Subject: [PATCH 5110/5711] hyperv: Move wait completion msg code into rndis_filter_halt_device() We need to wait for send_completion msg before put_rndis_request() at the end of rndis_filter_halt_device(). Otherwise, netvsc_send_completion() may reference freed memory which is overwritten, and cause panic. Reported-by: Long Li Reported-by: Jason Wang Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc.c | 7 ------- drivers/net/hyperv/rndis_filter.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 6cee2917eb02..4a1a5f58fa73 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -383,13 +383,6 @@ int netvsc_device_remove(struct hv_device *device) unsigned long flags; net_device = hv_get_drvdata(device); - spin_lock_irqsave(&device->channel->inbound_lock, flags); - net_device->destroy = true; - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - - /* Wait for all send completions */ - wait_event(net_device->wait_drain, - atomic_read(&net_device->num_outstanding_sends) == 0); netvsc_disconnect_vsp(net_device); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index e5d6146937fa..1e88a1095934 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -718,6 +718,9 @@ static void rndis_filter_halt_device(struct rndis_device *dev) { struct rndis_request *request; struct rndis_halt_request *halt; + struct netvsc_device *nvdev = dev->net_dev; + struct hv_device *hdev = nvdev->dev; + ulong flags; /* Attempt to do a rndis device halt */ request = get_rndis_request(dev, RNDIS_MSG_HALT, @@ -735,6 +738,14 @@ static void rndis_filter_halt_device(struct rndis_device *dev) dev->state = RNDIS_DEV_UNINITIALIZED; cleanup: + spin_lock_irqsave(&hdev->channel->inbound_lock, flags); + nvdev->destroy = true; + spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags); + + /* Wait for all send completions */ + wait_event(nvdev->wait_drain, + atomic_read(&nvdev->num_outstanding_sends) == 0); + if (request) put_rndis_request(dev, request); return; -- GitLab From 77f00f6324cb97cf1df6f9c4aaeea6ada23abdb2 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Thu, 2 Aug 2012 23:10:01 +0000 Subject: [PATCH 5111/5711] isdnloop: fix and simplify isdnloop_init() Fix a buffer overflow bug by removing the revision and printk. [ 22.016214] isdnloop-ISDN-driver Rev 1.11.6.7 [ 22.097508] isdnloop: (loop0) virtual card added [ 22.174400] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff83244972 [ 22.174400] [ 22.436157] Pid: 1, comm: swapper Not tainted 3.5.0-bisect-00018-gfa8bbb1-dirty #129 [ 22.624071] Call Trace: [ 22.720558] [] ? CallcNew+0x56/0x56 [ 22.815248] [] panic+0x110/0x329 [ 22.914330] [] ? isdnloop_init+0xaf/0xb1 [ 23.014800] [] ? CallcNew+0x56/0x56 [ 23.090763] [] __stack_chk_fail+0x2b/0x30 [ 23.185748] [] isdnloop_init+0xaf/0xb1 Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- drivers/isdn/isdnloop/isdnloop.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 5405ec644db3..baf2686aa8eb 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -16,7 +16,6 @@ #include #include "isdnloop.h" -static char *revision = "$Revision: 1.11.6.7 $"; static char *isdnloop_id = "loop0"; MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); @@ -1494,17 +1493,6 @@ isdnloop_addcard(char *id1) static int __init isdnloop_init(void) { - char *p; - char rev[10]; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); - if (isdnloop_id) return (isdnloop_addcard(isdnloop_id)); -- GitLab From f3a1ef9cee4812e2d08c855eb373f0d83433e34c Mon Sep 17 00:00:00 2001 From: Peter Meiser Date: Thu, 2 Aug 2012 02:30:20 +0000 Subject: [PATCH 5112/5711] cdc-ncm: tag Ericsson WWAN devices (eg F5521gw) with FLAG_WWAN Hello, looking at http://sourceforge.net/apps/mediawiki/mbm/index.php?title=Main_Page#Supported_devices, there are branded Ericsson devices from Dell and Toshiba. The to-be-added vendor IDs are 0x413c for Dell and 0x0930 for Toshiba. Please find attached a patch to add these vendor IDs. Signed-off-by: Peter Meiser Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index f4ce5957df32..4cd582a4f625 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1225,6 +1225,26 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, + /* Dell branded MBM devices like DW5550 */ + { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_VENDOR, + .idVendor = 0x413c, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = (unsigned long) &wwan_info, + }, + + /* Toshiba branded MBM devices */ + { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_VENDOR, + .idVendor = 0x0930, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = (unsigned long) &wwan_info, + }, + /* Generic CDC-NCM devices */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), -- GitLab From ff6e1225957cce9e93b8d84dc240e5a44094d0ec Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 3 Aug 2012 14:38:07 +0000 Subject: [PATCH 5113/5711] cris: fix eth_v10.c build error Fix build error on cris (not tested, no toolchain here): drivers/net/cris/eth_v10.c: error: too many arguments to function 'e100rxtx_interrupt' Reported-by: Geert Uytterhoeven Signed-off-by: Randy Dunlap Cc: Mikael Starvik Cc: Jesper Nilsson Cc: linux-cris-kernel@axis.com Signed-off-by: David S. Miller --- drivers/net/cris/eth_v10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index f0c8bd54ce29..021d69c5d9bc 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1712,7 +1712,7 @@ e100_set_network_leds(int active) static void e100_netpoll(struct net_device* netdev) { - e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); + e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev); } #endif -- GitLab From 6601fac822778aa6003aed37d8ba7acdc9a4f369 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:01 +0300 Subject: [PATCH 5114/5711] Documentation: fix the VM knobs descritpion WRT pdflush The pdflush thread is long gone, however we still mention it incorrectly in the kernel documentation. This patch fixes the situation. Cc: Randy Dunlap Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- Documentation/laptops/laptop-mode.txt | 12 ++++++------ Documentation/sysctl/vm.txt | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/laptops/laptop-mode.txt b/Documentation/laptops/laptop-mode.txt index 0bf25eebce94..4ebbfc3f1c6e 100644 --- a/Documentation/laptops/laptop-mode.txt +++ b/Documentation/laptops/laptop-mode.txt @@ -262,9 +262,9 @@ MINIMUM_BATTERY_MINUTES=10 # # Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio. Set this nice and low, so once -# some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake flusher threads which will then reduce the +# amount of dirty memory to dirty_background_ratio. Set this nice and low, +# so once some writeout has commenced, we do a lot of it. # #DIRTY_BACKGROUND_RATIO=5 @@ -384,9 +384,9 @@ CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'} # # Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio. Set this nice and low, so once -# some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake flusher threads which will then reduce the +# amount of dirty memory to dirty_background_ratio. Set this nice and low, +# so once some writeout has commenced, we do a lot of it. # DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'} diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index dcc2a94ae34e..078701fdbd4d 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -76,8 +76,8 @@ huge pages although processes will also directly compact memory as required. dirty_background_bytes -Contains the amount of dirty memory at which the pdflush background writeback -daemon will start writeback. +Contains the amount of dirty memory at which the background kernel +flusher threads will start writeback. Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only one of them may be specified at a time. When one sysctl is written it is @@ -89,7 +89,7 @@ other appears as 0 when read. dirty_background_ratio Contains, as a percentage of total system memory, the number of pages at which -the pdflush background writeback daemon will start writing out dirty data. +the background kernel flusher threads will start writing out dirty data. ============================================================== @@ -112,9 +112,9 @@ retained. dirty_expire_centisecs This tunable is used to define when dirty data is old enough to be eligible -for writeout by the pdflush daemons. It is expressed in 100'ths of a second. -Data which has been dirty in-memory for longer than this interval will be -written out next time a pdflush daemon wakes up. +for writeout by the kernel flusher threads. It is expressed in 100'ths +of a second. Data which has been dirty in-memory for longer than this +interval will be written out next time a flusher thread wakes up. ============================================================== @@ -128,7 +128,7 @@ data. dirty_writeback_centisecs -The pdflush writeback daemons will periodically wake up and write `old' data +The kernel flusher threads will periodically wake up and write `old' data out to disk. This tunable expresses the interval between those wakeups, in 100'ths of a second. -- GitLab From d3009c6cffd37e9bc8435a002fe862548c440d97 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:02 +0300 Subject: [PATCH 5115/5711] ext3: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from ext3. Cc: Jan Kara Cc: Andrew Morton Cc: Andreas Dilger Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ext3/inode.c | 8 -------- fs/ext3/super.c | 11 ----------- 2 files changed, 19 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 9a4a5c48b1c9..a07597307fd1 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3459,14 +3459,6 @@ ext3_reserve_inode_write(handle_t *handle, struct inode *inode, * inode out, but prune_icache isn't a user-visible syncing function. * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) * we start and wait on commits. - * - * Is this efficient/effective? Well, we're being nice to the system - * by cleaning up our inodes proactively so they can be reaped - * without I/O. But we are potentially leaving up to five seconds' - * worth of inodes floating about which prune_icache wants us to - * write out. One way to fix that would be to get prune_icache() - * to do a write_super() to free up some memory. It has the desired - * effect. */ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) { diff --git a/fs/ext3/super.c b/fs/ext3/super.c index ff9bcdc5b0d5..8c892e93d8e7 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -64,11 +64,6 @@ static int ext3_freeze(struct super_block *sb); /* * Wrappers for journal_start/end. - * - * The only special thing we need to do here is to make sure that all - * journal_end calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. */ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) { @@ -90,12 +85,6 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) return journal_start(journal, nblocks); } -/* - * The only special thing we need to do here is to make sure that all - * journal_stop calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. - */ int __ext3_journal_stop(const char *where, handle_t *handle) { struct super_block *sb; -- GitLab From 7652bdfcb5888a389a7850ed19a4630e3a09cb9c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:03 +0300 Subject: [PATCH 5116/5711] ext4: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from ext3. Cc: "Theodore Ts'o" Cc: Andreas Dilger Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ext4/inode.c | 8 -------- fs/ext4/super.c | 11 ----------- 2 files changed, 19 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6324f74e0342..bcb60d08a964 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4589,14 +4589,6 @@ static int ext4_expand_extra_isize(struct inode *inode, * inode out, but prune_icache isn't a user-visible syncing function. * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) * we start and wait on commits. - * - * Is this efficient/effective? Well, we're being nice to the system - * by cleaning up our inodes proactively so they can be reaped - * without I/O. But we are potentially leaving up to five seconds' - * worth of inodes floating about which prune_icache wants us to - * write out. One way to fix that would be to get prune_icache() - * to do a write_super() to free up some memory. It has the desired - * effect. */ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) { diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d76ec8277d3f..3e0851e4f468 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -326,11 +326,6 @@ static void ext4_put_nojournal(handle_t *handle) /* * Wrappers for jbd2_journal_start/end. - * - * The only special thing we need to do here is to make sure that all - * journal_end calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. */ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) { @@ -356,12 +351,6 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) return jbd2_journal_start(journal, nblocks); } -/* - * The only special thing we need to do here is to make sure that all - * jbd2_journal_stop calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. - */ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) { struct super_block *sb; -- GitLab From f6463b0da6937e288b115d641ccd46c70fb3a4a8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:04 +0300 Subject: [PATCH 5117/5711] ext4: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from ext4 comments. Cc: "Theodore Ts'o" Cc: Andreas Dilger Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bcb60d08a964..dff171c3a123 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1970,7 +1970,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); * This function can get called via... * - ext4_da_writepages after taking page lock (have journal handle) * - journal_submit_inode_data_buffers (no journal handle) - * - shrink_page_list via pdflush (no journal handle) + * - shrink_page_list via the kswapd/direct reclaim (no journal handle) * - grab_page_cache when doing write_begin (have journal handle) * * We don't do any block allocation in this function. If we have page with -- GitLab From 34eaadaf22b0dd453288c6b115e0c823a0fb74d5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:05 +0300 Subject: [PATCH 5118/5711] btrfs: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from btrfs. Cc: Chris Mason Cc: linux-btrfs@vger.kernel.org Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/btrfs/super.c | 4 ---- fs/btrfs/volumes.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8c6e61d6eed5..f2eb24c477a3 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -100,10 +100,6 @@ static void __save_error_info(struct btrfs_fs_info *fs_info) fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR; } -/* NOTE: - * We move write_super stuff at umount in order to avoid deadlock - * for umount hold all lock. - */ static void save_error_info(struct btrfs_fs_info *fs_info) { __save_error_info(fs_info); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b8708f994e67..e86ae04abe6a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1744,10 +1744,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) device->fs_devices = root->fs_info->fs_devices; - /* - * we don't want write_supers to jump in here with our device - * half setup - */ mutex_lock(&root->fs_info->fs_devices->device_list_mutex); list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); list_add(&device->dev_alloc_list, -- GitLab From b257031408945eb89980e14cb79d5fd854d8f25f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:06 +0300 Subject: [PATCH 5119/5711] btrfs: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from btrfs comments. Cc: Chris Mason Cc: linux-btrfs@vger.kernel.org Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/btrfs/inode.c | 3 ++- fs/btrfs/ordered-data.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 83baec24946d..6e8f416773d4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -324,7 +324,8 @@ static noinline int add_async_extent(struct async_cow *cow, * If this code finds it can't get good compression, it puts an * entry onto the work queue to write the uncompressed bytes. This * makes sure that both compressed inodes and uncompressed inodes - * are written in the same order that pdflush sent them down. + * are written in the same order that the flusher thread sent them + * down. */ static noinline int compress_file_range(struct inode *inode, struct page *locked_page, diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 643335a4fe3c..051c7fe551dd 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -596,7 +596,7 @@ void btrfs_start_ordered_extent(struct inode *inode, /* * pages in the range can be dirty, clean or writeback. We * start IO on any dirty ones so the wait doesn't stall waiting - * for pdflush to find them + * for the flusher thread to find them */ if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) filemap_fdatawrite_range(inode->i_mapping, start, end); -- GitLab From 12810ad70858af10f5e00b3c178085c03baa457b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:07 +0300 Subject: [PATCH 5120/5711] jbd/jbd2: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from various jbd and jbd2. Cc: Andrew Morton Cc: Jan Kara Cc: "Theodore Ts'o" Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/jbd/journal.c | 4 ++-- fs/jbd2/journal.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 425c2f2cf170..09357508ec9a 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -534,8 +534,8 @@ int journal_start_commit(journal_t *journal, tid_t *ptid) ret = 1; } else if (journal->j_committing_transaction) { /* - * If ext3_write_super() recently started a commit, then we - * have to wait for completion of that transaction + * If commit has been started, then we have to wait for + * completion of that transaction. */ if (ptid) *ptid = journal->j_committing_transaction->t_tid; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e9a3c4c85594..8625da27eccf 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -612,8 +612,8 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) ret = 1; } else if (journal->j_committing_transaction) { /* - * If ext3_write_super() recently started a commit, then we - * have to wait for completion of that transaction + * If commit has been started, then we have to wait for + * completion of that transaction. */ if (ptid) *ptid = journal->j_committing_transaction->t_tid; -- GitLab From 0d5c3eba2e1e5aa74e097f49bc90b58f607e101c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:08 +0300 Subject: [PATCH 5121/5711] vfs: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from vfs comments. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/bio.c | 2 +- include/linux/writeback.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index 73922abba832..5eaa70c9d96e 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1312,7 +1312,7 @@ EXPORT_SYMBOL(bio_copy_kern); * Note that this code is very hard to test under normal circumstances because * direct-io pins the pages with get_user_pages(). This makes * is_page_cache_freeable return false, and the VM will not clean the pages. - * But other code (eg, pdflush) could clean the pages if they are mapped + * But other code (eg, flusher threads) could clean the pages if they are mapped * pagecache. * * Simply disabling the call to bio_set_pages_dirty() is a good way to test the diff --git a/include/linux/writeback.h b/include/linux/writeback.h index c66fe3332d83..50c3e8fa06a8 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -104,7 +104,6 @@ static inline void wait_on_inode(struct inode *inode) wait_on_bit(&inode->i_state, __I_NEW, inode_wait, TASK_UNINTERRUPTIBLE); } - /* * mm/page-writeback.c */ -- GitLab From 50640bcc0a0e5a66587fa051b327654c739c9c19 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:09 +0300 Subject: [PATCH 5122/5711] hfs: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from hfs. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/hfs/mdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 5fd51a5833ff..b7ec224910c5 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -236,10 +236,10 @@ out: * hfs_mdb_commit() * * Description: - * This updates the MDB on disk (look also at hfs_write_super()). + * This updates the MDB on disk. * It does not check, if the superblock has been modified, or * if the filesystem has been mounted read-only. It is mainly - * called by hfs_write_super() and hfs_btree_extend(). + * called by hfs_sync_fs() and flush_mdb(). * Input Variable(s): * struct hfs_mdb *mdb: Pointer to the hfs MDB * int backup; -- GitLab From 166ac34b74faa757ca936fde790d2121a3f40f65 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:11 +0300 Subject: [PATCH 5123/5711] nilfs2: nuke write_super from comments The '->write_super' superblock method is gone, and this patch removes all the references to 'write_super' from ntfs. Cc: KONISHI Ryusuke Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/nilfs2/super.c | 4 ---- fs/nilfs2/the_nilfs.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6522cac6057c..6a10812711c1 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -676,17 +676,13 @@ static const struct super_operations nilfs_sops = { .alloc_inode = nilfs_alloc_inode, .destroy_inode = nilfs_destroy_inode, .dirty_inode = nilfs_dirty_inode, - /* .write_inode = nilfs_write_inode, */ - /* .drop_inode = nilfs_drop_inode, */ .evict_inode = nilfs_evict_inode, .put_super = nilfs_put_super, - /* .write_super = nilfs_write_super, */ .sync_fs = nilfs_sync_fs, .freeze_fs = nilfs_freeze, .unfreeze_fs = nilfs_unfreeze, .statfs = nilfs_statfs, .remount_fs = nilfs_remount, - /* .umount_begin */ .show_options = nilfs_show_options }; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 6eee4177807b..be1267a34cea 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -107,8 +107,6 @@ struct the_nilfs { * used for * - loading the latest checkpoint exclusively. * - allocating a new full segment. - * - protecting s_dirt in the super_block struct - * (see nilfs_write_super) and the following fields. */ struct buffer_head *ns_sbh[2]; struct nilfs_super_block *ns_sbp[2]; -- GitLab From d97482ede202f424670a53673c362e5189107875 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:12 +0300 Subject: [PATCH 5124/5711] drbd: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from drbd comments. Cc: drbd-dev@lists.linbit.com Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- drivers/block/drbd/drbd_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 2e0e7fc1dbba..dbe6135a2abe 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3537,9 +3537,9 @@ static void drbd_cleanup(void) } /** - * drbd_congested() - Callback for pdflush + * drbd_congested() - Callback for the flusher thread * @congested_data: User data - * @bdi_bits: Bits pdflush is currently interested in + * @bdi_bits: Bits the BDI flusher thread is currently interested in * * Returns 1< Date: Wed, 25 Jul 2012 18:12:13 +0300 Subject: [PATCH 5125/5711] gfs2: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from gfs comments. Cc: Steven Whitehouse Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/gfs2/meta_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 3a56c8d94de0..22255d96b27e 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -52,7 +52,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb /* * If it's a fully non-blocking write attempt and we cannot * lock the buffer then redirty the page. Note that this can - * potentially cause a busy-wait loop from pdflush and kswapd + * potentially cause a busy-wait loop from flusher thread and kswapd * activity, but those code paths have their own higher-level * throttling. */ -- GitLab From 5c57f20b824a163bd7dfa42abc76582ad24a745a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 25 Jul 2012 18:12:14 +0300 Subject: [PATCH 5126/5711] UBIFS: nuke pdflush from comments The pdflush thread is long gone, so this patch removes references to pdflush from UBIFS comments. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ubifs/file.c | 10 +++++----- fs/ubifs/super.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 35389ca2d267..7bd6e72afd11 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -37,11 +37,11 @@ * * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we * implement. However, this is not true for 'ubifs_writepage()', which may be - * called with @i_mutex unlocked. For example, when pdflush is doing background - * write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. At "normal" - * work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. in the - * "sys_write -> alloc_pages -> direct reclaim path". So, in 'ubifs_writepage()' - * we are only guaranteed that the page is locked. + * called with @i_mutex unlocked. For example, when flusher thread is doing + * background write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. + * At "normal" work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. + * in the "sys_write -> alloc_pages -> direct reclaim path". So, in + * 'ubifs_writepage()' we are only guaranteed that the page is locked. * * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1c766c39c038..c3fa6c5327a3 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -303,7 +303,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) mutex_lock(&ui->ui_mutex); /* * Due to races between write-back forced by budgeting - * (see 'sync_some_inodes()') and pdflush write-back, the inode may + * (see 'sync_some_inodes()') and background write-back, the inode may * have already been synchronized, do not do this again. This might * also happen if it was synchronized in an VFS operation, e.g. * 'ubifs_link()'. -- GitLab From fe7c80518e34d1786f4a940ce673a0bfcbe53298 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 4 Aug 2012 08:39:23 +0400 Subject: [PATCH 5127/5711] missed mnt_drop_write() in do_dentry_open() This one ought to be __mnt_drop_write(), to match __mnt_want_write() in the beginning... Signed-off-by: Al Viro --- fs/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/open.c b/fs/open.c index f3d96e7e7b19..bc132e167d2d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -717,7 +717,7 @@ cleanup_all: * here, so just reset the state. */ file_reset_write(f); - mnt_drop_write(f->f_path.mnt); + __mnt_drop_write(f->f_path.mnt); } } cleanup_file: -- GitLab From 925b11f706642732ce2ae53b0f0d3fd54adc5075 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Tue, 31 Jul 2012 01:01:23 +0000 Subject: [PATCH 5128/5711] igb: Fix for failure to init on some 82576 devices. Move nvm invalid size check to before size assigned by mac_type for 82575 and later parts in get_invariants function. This fixes a problem found on some 82576 devices where the part will not initialize because the nvm_read function pointer ends up getting assigned to the incorrect function. Reported By: Stefan Assmann Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/e1000_82575.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 5e84eaac48c1..ba994fb4cec6 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -254,6 +254,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ size += NVM_WORD_SIZE_BASE_SHIFT; + /* + * Check for invalid size + */ + if ((hw->mac.type == e1000_82576) && (size > 15)) { + pr_notice("The NVM size is not valid, defaulting to 32K\n"); + size = 15; + } + nvm->word_size = 1 << size; if (hw->mac.type < e1000_i210) { nvm->opcode_bits = 8; @@ -281,14 +289,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) } else nvm->type = e1000_nvm_flash_hw; - /* - * Check for invalid size - */ - if ((hw->mac.type == e1000_82576) && (size > 15)) { - pr_notice("The NVM size is not valid, defaulting to 32K\n"); - size = 15; - } - /* NVM Function Pointers */ switch (hw->mac.type) { case e1000_82580: -- GitLab From 89d351c046c287f293b4b2fda1d76c4df44b95ce Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 1 Aug 2012 05:41:25 +0000 Subject: [PATCH 5129/5711] igb: correct hardware type (i210/i211) check in igb_loopback_test() In the original code ... if ((adapter->hw.mac.type == e1000_i210) || (adapter->hw.mac.type == e1000_i210)) { ... the second check of 'adapter->hw.mac.type' is pointless since it tests for the exact same value as the first. Signed-off-by: Jesper Juhl Acked-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index a19c84cad0e9..ad489b76980f 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -1783,7 +1783,7 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) goto out; } if ((adapter->hw.mac.type == e1000_i210) - || (adapter->hw.mac.type == e1000_i210)) { + || (adapter->hw.mac.type == e1000_i211)) { dev_err(&adapter->pdev->dev, "Loopback test not supported " "on this part at this time.\n"); -- GitLab From d836200a1c239a488cd2ed9867f4792f25f721d5 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 1 Aug 2012 05:41:30 +0000 Subject: [PATCH 5130/5711] igb: don't break user visible strings over multiple lines in igb_ethtool.c Even when they go beyond 80 characters, user visible strings should be on one line to make them easy to grep for. Signed-off-by: Jesper Juhl Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index ad489b76980f..90550f5e3dd9 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -209,8 +209,8 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) /* When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ if (igb_check_reset_block(hw)) { - dev_err(&adapter->pdev->dev, "Cannot change link " - "characteristics when SoL/IDER is active.\n"); + dev_err(&adapter->pdev->dev, + "Cannot change link characteristics when SoL/IDER is active.\n"); return -EINVAL; } @@ -1089,8 +1089,8 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, wr32(reg, (_test[pat] & write)); val = rd32(reg) & mask; if (val != (_test[pat] & write & mask)) { - dev_err(&adapter->pdev->dev, "pattern test reg %04X " - "failed: got 0x%08X expected 0x%08X\n", + dev_err(&adapter->pdev->dev, + "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", reg, val, (_test[pat] & write & mask)); *data = reg; return 1; @@ -1108,8 +1108,8 @@ static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, wr32(reg, write & mask); val = rd32(reg); if ((write & mask) != (val & mask)) { - dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" - " got 0x%08X expected 0x%08X\n", reg, + dev_err(&adapter->pdev->dev, + "set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", reg, (val & mask), (write & mask)); *data = reg; return 1; @@ -1171,8 +1171,9 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) wr32(E1000_STATUS, toggle); after = rd32(E1000_STATUS) & toggle; if (value != after) { - dev_err(&adapter->pdev->dev, "failed STATUS register test " - "got: 0x%08X expected: 0x%08X\n", after, value); + dev_err(&adapter->pdev->dev, + "failed STATUS register test got: 0x%08X expected: 0x%08X\n", + after, value); *data = 1; return 1; } @@ -1777,16 +1778,14 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) * sessions are active */ if (igb_check_reset_block(&adapter->hw)) { dev_err(&adapter->pdev->dev, - "Cannot do PHY loopback test " - "when SoL/IDER is active.\n"); + "Cannot do PHY loopback test when SoL/IDER is active.\n"); *data = 0; goto out; } if ((adapter->hw.mac.type == e1000_i210) || (adapter->hw.mac.type == e1000_i211)) { dev_err(&adapter->pdev->dev, - "Loopback test not supported " - "on this part at this time.\n"); + "Loopback test not supported on this part at this time.\n"); *data = 0; goto out; } -- GitLab From 10ce0473e0de3ff8c091735f85c20fceace061cd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 Aug 2012 10:08:12 +0530 Subject: [PATCH 5131/5711] spi/s3c64xx: Add missing static storage class specifiers Silences the following sparse warnings: drivers/spi/spi-s3c64xx.c:1482:32: warning: symbol 's3c2443_spi_port_config' was not declared. Should it be static? drivers/spi/spi-s3c64xx.c:1489:32: warning: symbol 's3c6410_spi_port_config' was not declared. Should it be static? drivers/spi/spi-s3c64xx.c:1495:32: warning: symbol 's5p64x0_spi_port_config' was not declared. Should it be static? drivers/spi/spi-s3c64xx.c:1501:32: warning: symbol 's5pc100_spi_port_config' was not declared. Should it be static? drivers/spi/spi-s3c64xx.c:1508:32: warning: symbol 's5pv210_spi_port_config' was not declared. Should it be static? drivers/spi/spi-s3c64xx.c:1515:32: warning: symbol 'exynos4_spi_port_config' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 646a7657fe62..5ed1a76636c6 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1479,40 +1479,40 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { s3c64xx_spi_runtime_resume, NULL) }; -struct s3c64xx_spi_port_config s3c2443_spi_port_config = { +static struct s3c64xx_spi_port_config s3c2443_spi_port_config = { .fifo_lvl_mask = { 0x7f }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -struct s3c64xx_spi_port_config s3c6410_spi_port_config = { +static struct s3c64xx_spi_port_config s3c6410_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, }; -struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { +static struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, }; -struct s3c64xx_spi_port_config s5pc100_spi_port_config = { +static struct s3c64xx_spi_port_config s5pc100_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -struct s3c64xx_spi_port_config s5pv210_spi_port_config = { +static struct s3c64xx_spi_port_config s5pv210_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, .high_speed = true, }; -struct s3c64xx_spi_port_config exynos4_spi_port_config = { +static struct s3c64xx_spi_port_config exynos4_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, -- GitLab From 37a2d84a38df16e614bbfbb18a5155ebd8256938 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Thu, 2 Aug 2012 16:41:25 +0530 Subject: [PATCH 5132/5711] spi: omap2-mcspi: Fix the error handling in probe The kfree() is taken care of by the spi core (spi_master_release() function) that is called once the last reference to the underlying struct device has been released. So the driver need not call kfree. Also the put was missed in some of the error handling fix the same. There by fixing the missing device_put in some of the error paths. Acked-by: Guenter Roeck Reported-by: Guenter Roeck Signed-off-by: Shubhrajyoti D Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index bc4778175e34..b2fb141da375 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1228,18 +1228,16 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) status = spi_register_master(master); if (status < 0) - goto err_spi_register; + goto disable_pm; return status; -err_spi_register: - spi_master_put(master); disable_pm: pm_runtime_disable(&pdev->dev); dma_chnl_free: kfree(mcspi->dma_channels); free_master: - kfree(master); + spi_master_put(master); platform_set_drvdata(pdev, NULL); return status; } -- GitLab From 3bed491c8d28329e34f8a31e3fe64d03f3a350f1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 3 Aug 2012 20:54:48 +0200 Subject: [PATCH 5133/5711] ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig The CONFIG_DEFAULT_MMAP_MIN_ADDR was set to 65536 in mxs_defconfig, this caused severe breakage of userland applications since the upper limit for ARM is 32768. By default CONFIG_DEFAULT_MMAP_MIN_ADDR is set to 4096 and can also be changed via /proc/sys/vm/mmap_min_addr if needed. Quoting Russell King [1]: "4096 is also fine for ARM too. There's not much point in having defconfigs change it - that would just be pure noise in the config files." the CONFIG_DEFAULT_MMAP_MIN_ADDR can be removed from the defconfig altogether. This problem was introduced by commit cde7c41 (ARM: configs: add defconfig for mach-mxs). [1] http://marc.info/?l=linux-arm-kernel&m=134401593807820&w=2 Signed-off-by: Marek Vasut Cc: stable@vger.kernel.org Cc: Russell King Cc: Wolfgang Denk Signed-off-by: Shawn Guo --- arch/arm/configs/mxs_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index ccdb6357fb74..4edcfb4e4dee 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -34,7 +34,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_AUTO_ZRELADDR=y CONFIG_FPE_NWFPE=y CONFIG_NET=y -- GitLab From 6eec0152c4aa43636e180b21d5c71743f25d1220 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 30 Jul 2012 15:06:14 +0200 Subject: [PATCH 5134/5711] ARM: mxs: always build ocotp With this patch ocotp support will always be build into the kernel on mxs. Otherwise a DT-only kernel fails to link with: arch/arm/mach-mxs/mach-mxs.c:169: undefined reference to `mxs_get_ocotp' Signed-off-by: Marc Kleine-Budde Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/Kconfig | 6 ------ arch/arm/mach-mxs/Makefile | 3 +-- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index ccdf83b17cf1..9a8bbda195b2 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -2,9 +2,6 @@ if ARCH_MXS source "arch/arm/mach-mxs/devices/Kconfig" -config MXS_OCOTP - bool - config SOC_IMX23 bool select ARM_AMBA @@ -66,7 +63,6 @@ config MACH_MX28EVK select MXS_HAVE_PLATFORM_MXS_SAIF select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_RTC_STMP3XXX - select MXS_OCOTP help Include support for MX28EVK platform. This includes specific configurations for the board and its peripherals. @@ -94,7 +90,6 @@ config MODULE_M28 select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXSFB - select MXS_OCOTP config MODULE_APX4 bool @@ -106,7 +101,6 @@ config MODULE_APX4 select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXS_SAIF - select MXS_OCOTP config MACH_TX28 bool "Ka-Ro TX28 module" diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile index e41590ccb437..fed3695a1339 100644 --- a/arch/arm/mach-mxs/Makefile +++ b/arch/arm/mach-mxs/Makefile @@ -1,7 +1,6 @@ # Common support -obj-y := devices.o icoll.o iomux.o system.o timer.o mm.o +obj-y := devices.o icoll.o iomux.o ocotp.o system.o timer.o mm.o -obj-$(CONFIG_MXS_OCOTP) += ocotp.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o -- GitLab From c43ba8008252d26e023f3943bb83a48641b3dec4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 19 Jul 2012 16:41:10 +0800 Subject: [PATCH 5135/5711] pinctrl: mxs: register driver at postcore_initcall time It's not so usual, but there are still some cases which require pinctrl driver function at arch_initcall time. So register imx23 and imx28 pinctrl driver at postcore_initcall time. Signed-off-by: Shawn Guo Reviewed-by: Richard Zhao Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-imx23.c | 2 +- drivers/pinctrl/pinctrl-imx28.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c index 75d3eff94296..3674d877ed7c 100644 --- a/drivers/pinctrl/pinctrl-imx23.c +++ b/drivers/pinctrl/pinctrl-imx23.c @@ -292,7 +292,7 @@ static int __init imx23_pinctrl_init(void) { return platform_driver_register(&imx23_pinctrl_driver); } -arch_initcall(imx23_pinctrl_init); +postcore_initcall(imx23_pinctrl_init); static void __exit imx23_pinctrl_exit(void) { diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c index b973026811a2..0f5b2122b1ba 100644 --- a/drivers/pinctrl/pinctrl-imx28.c +++ b/drivers/pinctrl/pinctrl-imx28.c @@ -408,7 +408,7 @@ static int __init imx28_pinctrl_init(void) { return platform_driver_register(&imx28_pinctrl_driver); } -arch_initcall(imx28_pinctrl_init); +postcore_initcall(imx28_pinctrl_init); static void __exit imx28_pinctrl_exit(void) { -- GitLab From 0e3ac20d9f9872cbf2d00d6a63f92759cb8dd082 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 21 Jul 2012 14:22:58 +0545 Subject: [PATCH 5136/5711] pinctrl/pinctrl-u300: remove unneeded devm_kfree call the allocated memory will be destroyed at the driver unload time, automatically if driver uses the devm_ functions, so no need of doing devm_kfree at the error path Signed-off-by: Devendra Naga Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-u300.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index a7ad8c112d91..309f5b9a70ec 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -1121,10 +1121,8 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) upmx->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto out_no_resource; - } + if (!res) + return -ENOENT; upmx->phybase = res->start; upmx->physize = resource_size(res); @@ -1165,8 +1163,6 @@ out_no_remap: platform_set_drvdata(pdev, NULL); out_no_memregion: release_mem_region(upmx->phybase, upmx->physize); -out_no_resource: - devm_kfree(&pdev->dev, upmx); return ret; } -- GitLab From 8abdd2d2d873ece35a201c2e05af7b6998cf0dca Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 13:55:10 +0100 Subject: [PATCH 5137/5711] gpio-sch: Fix leak of resource Signed-off-by: Alan Cox Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 424dce8e3f30..8707d4572a06 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -241,7 +241,8 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) break; default: - return -ENODEV; + err = -ENODEV; + goto err_sch_gpio_core; } sch_gpio_core.dev = &pdev->dev; -- GitLab From f7da0bdbf585c0404fc89901ee4bdb806e70530f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Jul 2012 18:35:16 +0800 Subject: [PATCH 5138/5711] gpio: msic: Fix calculating register address in msic_gpio_to_oreg() In the case offset is 20 ... 23, the equation to get the register should be: INTEL_MSIC_GPIO1HV0CTLO - offset + 20 With above equation, we can get below mapping between offset and the register: offset is 20: INTEL_MSIC_GPIO1HV0CTLO offset is 21: INTEL_MSIC_GPIO1HV1CTLO offset is 22: INTEL_MSIC_GPIO1HV2CTLO offset is 23: INTEL_MSIC_GPIO1HV3CTLO Signed-off-by: Axel Lin Acked-by: Mathias Nyman Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 71a838f44501..b38986285868 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -99,7 +99,7 @@ static int msic_gpio_to_oreg(unsigned offset) if (offset < 20) return INTEL_MSIC_GPIO0HV0CTLO - offset + 16; - return INTEL_MSIC_GPIO1HV0CTLO + offset + 20; + return INTEL_MSIC_GPIO1HV0CTLO - offset + 20; } static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -- GitLab From 72121572670973bec6fb1b9fdb454b106b253235 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 25 Jul 2012 17:35:39 +0200 Subject: [PATCH 5139/5711] GPIO: gpio-pxa: fix devicetree functions Provide an of_xlate function for the PXA GPIO chips and make it work for devicetree environments. Successfully tested on a PXA3xx board. Signed-off-by: Daniel Mack Acked-by: Haojian Zhuang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 58a6a63a6ece..793767b0962a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -62,6 +62,7 @@ int pxa_last_gpio; #ifdef CONFIG_OF static struct irq_domain *domain; +static struct device_node *pxa_gpio_of_node; #endif struct pxa_gpio_chip { @@ -277,6 +278,24 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) (value ? GPSR_OFFSET : GPCR_OFFSET)); } +#ifdef CONFIG_OF_GPIO +static int pxa_gpio_of_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, + u32 *flags) +{ + if (gpiospec->args[0] > pxa_last_gpio) + return -EINVAL; + + if (gc != &pxa_gpio_chips[gpiospec->args[0] / 32].chip) + return -EINVAL; + + if (flags) + *flags = gpiospec->args[1]; + + return gpiospec->args[0] % 32; +} +#endif + static int __devinit pxa_init_gpio_chip(int gpio_end, int (*set_wake)(unsigned int, unsigned int)) { @@ -304,6 +323,11 @@ static int __devinit pxa_init_gpio_chip(int gpio_end, c->get = pxa_gpio_get; c->set = pxa_gpio_set; c->to_irq = pxa_gpio_to_irq; +#ifdef CONFIG_OF_GPIO + c->of_node = pxa_gpio_of_node; + c->of_xlate = pxa_gpio_of_xlate; + c->of_gpio_n_cells = 2; +#endif /* number of GPIOs on last bank may be less than 32 */ c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -505,6 +529,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, const struct irq_domain_ops pxa_irq_domain_ops = { .map = pxa_irq_domain_map, + .xlate = irq_domain_xlate_twocell, }; #ifdef CONFIG_OF @@ -545,6 +570,7 @@ static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) } domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0, &pxa_irq_domain_ops, NULL); + pxa_gpio_of_node = np; return 0; err: iounmap(gpio_reg_base); -- GitLab From 1d17d17484d40f2d5b35c79518597a2b25296996 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 4 Aug 2012 21:21:14 +0200 Subject: [PATCH 5140/5711] time: Fix adjustment cleanup bug in timekeeping_adjust() Tetsuo Handa reported that sporadically the system clock starts counting up too quickly which is enough to confuse the hangcheck timer to print a bogus stall warning. Commit 2a8c0883 "time: Move xtime_nsec adjustment underflow handling timekeeping_adjust" overlooked this exit path: } else return; which should really be a proper exit sequence, fixing the bug as a side effect. Also make the flow more readable by properly balancing curly braces. Reported-by: Tetsuo Handa wrote: Tested-by: Tetsuo Handa wrote: Signed-off-by: Ingo Molnar Cc: john.stultz@linaro.org Cc: a.p.zijlstra@chello.nl Cc: richardcochran@gmail.com Cc: prarit@redhat.com Link: http://lkml.kernel.org/r/20120804192114.GA28347@gmail.com Signed-off-by: Ingo Molnar --- kernel/time/timekeeping.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2988bc819187..e16af197a2bc 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -923,20 +923,22 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) if (likely(error <= interval)) adj = 1; else - adj = timekeeping_bigadjust(tk, error, &interval, - &offset); - } else if (error < -interval) { - /* See comment above, this is just switched for the negative */ - error >>= 2; - if (likely(error >= -interval)) { - adj = -1; - interval = -interval; - offset = -offset; - } else - adj = timekeeping_bigadjust(tk, error, &interval, - &offset); - } else - return; + adj = timekeeping_bigadjust(tk, error, &interval, &offset); + } else { + if (error < -interval) { + /* See comment above, this is just switched for the negative */ + error >>= 2; + if (likely(error >= -interval)) { + adj = -1; + interval = -interval; + offset = -offset; + } else { + adj = timekeeping_bigadjust(tk, error, &interval, &offset); + } + } else { + goto out_adjust; + } + } if (unlikely(tk->clock->maxadj && (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { @@ -999,6 +1001,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) tk->xtime_nsec -= offset; tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; +out_adjust: /* * It may be possible that when we entered this function, xtime_nsec * was very small. Further, if we're slightly speeding the clocksource -- GitLab From e844b990b1df9242bb91b7d490552f3198946838 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Jul 2012 15:35:01 -0700 Subject: [PATCH 5141/5711] drm/i915: Don't forget to apply SNB PIPE_CONTROL GTT workaround. If a buffer that was the target of a PIPE_CONTROL from userland was a reused one that hadn't been evicted which had not previously had this workaround applied, then the early return for a correct presumed_offset in this function meant we would not bind it into the GTT and the write would land somewhere else. Fixes reproducible failures with GL_EXT_timer_query usage in apitrace, and I also expect it to fix the intermittent OQ issues on snb that danvet's been working on. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=48019 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=52932 Signed-off-by: Eric Anholt Reviewed-by: Chris Wilson Reviewed-by: Carl Worth Tested-by: Carl Worth Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5af631e788c8..ff2819ea0813 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -291,6 +291,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = to_intel_bo(target_obj); target_offset = target_i915_obj->gtt_offset; + /* 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) && + reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && + !target_i915_obj->has_global_gtt_mapping)) { + i915_gem_gtt_bind_object(target_i915_obj, + target_i915_obj->cache_level); + } + /* The target buffer should have appeared before us in the * exec_object list, so it should have a GTT space bound by now. */ @@ -399,16 +409,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, io_mapping_unmap_atomic(reloc_page); } - /* 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) && - reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && - !target_i915_obj->has_global_gtt_mapping)) { - i915_gem_gtt_bind_object(target_i915_obj, - target_i915_obj->cache_level); - } - /* and update the user's relocation entry */ reloc->presumed_offset = target_offset; -- GitLab From e47e9ad9186ff265ddf316d25cd4942bab019d57 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 28 Jul 2012 18:46:35 +0545 Subject: [PATCH 5142/5711] drm/i915: remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the following warning was produced, drivers/gpu/drm/i915/i915_gem_context.c: In function ‘i915_switch_context’: drivers/gpu/drm/i915/i915_gem_context.c:454:6: warning: unused variable ‘ret’ [-Wunused-variable] fix up by removing it Signed-off-by: Devendra Naga Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index da8b01fb1bf8..a9d58d72bb4d 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -451,7 +451,6 @@ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_i915_file_private *file_priv = NULL; struct i915_hw_context *to; struct drm_i915_gem_object *from_obj = ring->last_context_obj; - int ret; if (dev_priv->hw_contexts_disabled) return 0; -- GitLab From f00f979145756e39b5512d7d4e4050534d1c3d7f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 31 Jul 2012 15:58:13 +1000 Subject: [PATCH 5143/5711] i915: don't map imported dma-bufs for dmar. The exporter should have given us pages in the correct place, avoid the prepare object mapping phase on dmar systems. This fixes an oops on a GM45/R600 machine, when running the intel/radeon tests. Signed-off-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9fd25a435536..ee9b68f6bc36 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -361,7 +361,8 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->mm.gtt->needs_dmar) + /* don't map imported dma buf objects */ + if (dev_priv->mm.gtt->needs_dmar && !obj->sg_table) return intel_gtt_map_memory(obj->pages, obj->base.size >> PAGE_SHIFT, &obj->sg_list, -- GitLab From d796c52ef0b71a988364f6109aeb63d79c5b116b Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 5 Aug 2012 19:04:57 -0400 Subject: [PATCH 5144/5711] ext4: make sure the journal sb is written in ext4_clear_journal_err() After we transfer set the EXT4_ERROR_FS bit in the file system superblock, it's not enough to call jbd2_journal_clear_err() to clear the error indication from journal superblock --- we need to call jbd2_journal_update_sb_errno() as well. Otherwise, when the root file system is mounted read-only, the journal is replayed, and the error indicator is transferred to the superblock --- but the s_errno field in the jbd2 superblock is left set (since although we cleared it in memory, we never flushed it out to disk). This can end up confusing e2fsck. We should make e2fsck more robust in this case, but the kernel shouldn't be leaving things in this confused state, either. Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/super.c | 1 + fs/jbd2/journal.c | 3 ++- include/linux/jbd2.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d76ec8277d3f..ccc4bcad5616 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4430,6 +4430,7 @@ static void ext4_clear_journal_err(struct super_block *sb, ext4_commit_super(sb, 1); jbd2_journal_clear_err(journal); + jbd2_journal_update_sb_errno(journal); } } diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e9a3c4c85594..bd23f2ebaa67 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) * Update a journal's errno. Write updated superblock to disk waiting for IO * to complete. */ -static void jbd2_journal_update_sb_errno(journal_t *journal) +void jbd2_journal_update_sb_errno(journal_t *journal) { journal_superblock_t *sb = journal->j_superblock; @@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) jbd2_write_superblock(journal, WRITE_SYNC); } +EXPORT_SYMBOL(jbd2_journal_update_sb_errno); /* * Read the superblock for a given journal, performing initial diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index f334c7fab967..3efc43f3f162 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1125,6 +1125,7 @@ extern int jbd2_journal_destroy (journal_t *); extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); extern int jbd2_journal_skip_recovery (journal_t *); +extern void jbd2_journal_update_sb_errno(journal_t *); extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, unsigned long, int); extern void __jbd2_journal_abort_hard (journal_t *); -- GitLab From 7e731bc9a12339f344cddf82166b82633d99dd86 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 5 Aug 2012 23:28:16 -0400 Subject: [PATCH 5145/5711] ext4: avoid kmemcheck complaint from reading uninitialized memory Commit 03179fe923 introduced a kmemcheck complaint in ext4_da_get_block_prep() because we save and restore ei->i_da_metadata_calc_last_lblock even though it is left uninitialized in the case where i_da_metadata_calc_len is zero. This doesn't hurt anything, but silencing the kmemcheck complaint makes it easier for people to find real bugs. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631 (which is marked as a regression). Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ccc4bcad5616..56bcaec9149c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -959,6 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->i_reserved_meta_blocks = 0; ei->i_allocated_meta_blocks = 0; ei->i_da_metadata_calc_len = 0; + ei->i_da_metadata_calc_last_lblock = 0; spin_lock_init(&(ei->i_block_reservation_lock)); #ifdef CONFIG_QUOTA ei->i_reserved_quota = 0; -- GitLab From faea35dd8a9d3605c411c8ecd7f97f0f9ecbaf58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marchesin?= Date: Mon, 30 Jul 2012 13:51:38 -0700 Subject: [PATCH 5146/5711] drm/i915: Make intel_panel_get_backlight static. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function isn't used outside of intel_panel.c, so make it static. Signed-off-by: Stéphane Marchesin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_panel.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 84353559441c..3afe3550e4ae 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -380,7 +380,6 @@ extern void intel_pch_panel_fitting(struct drm_device *dev, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern u32 intel_panel_get_max_backlight(struct drm_device *dev); -extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); extern int intel_panel_setup_backlight(struct drm_device *dev); extern void intel_panel_enable_backlight(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 10c7d39034e1..9474488db948 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -213,7 +213,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) return val; } -u32 intel_panel_get_backlight(struct drm_device *dev) +static u32 intel_panel_get_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; -- GitLab From bcf9dcc1e6269fac674e41f25d007ff75f76e840 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 15 Jul 2012 09:42:38 +0100 Subject: [PATCH 5147/5711] drm/i915: Workaround hang with BSD and forcewake on SandyBridge For reasons that are not apparent to anybody, 990bbdadaba (drm/i915: Group the GT routines together in both code and vtable) breaks the use of the BitStream Decoder ring on SandyBridge. The active ingredient of that patch is the conversion from a udelay(10) to a udelay(1) in the busy-wait loop of waiting for the forcewake acknowledge. If we restore that udelay(10) or insert another udelay(1) afterwards (or any wait longer than 250ns) everything works again. An alternative is also to remove any delay from the busy-wait loop. Given that in the atomic sections we want to complete the wait as quick as possible to avoid blocking the CPU for too long, it makes sense to remove the delay altogether and simply spin on the exit condition until it completes. So we replace the udelay(1) with cpu_relax(). Papers over regression from commit 990bbdadabaa51828e475eda86ee5720a4910cc3 Author: Chris Wilson Date: Mon Jul 2 11:51:02 2012 -0300 drm/i915: Group the GT routines together in both code and vtable Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51738 Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3afe3550e4ae..132ab511b90c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -46,15 +46,16 @@ }) #define wait_for_atomic_us(COND, US) ({ \ - int i, ret__ = -ETIMEDOUT; \ - for (i = 0; i < (US); i++) { \ - if ((COND)) { \ - ret__ = 0; \ - break; \ - } \ - udelay(1); \ - } \ - ret__; \ + unsigned long timeout__ = jiffies + usecs_to_jiffies(US); \ + int ret__ = 0; \ + while (!(COND)) { \ + if (time_after(jiffies, timeout__)) { \ + ret__ = -ETIMEDOUT; \ + break; \ + } \ + cpu_relax(); \ + } \ + ret__; \ }) #define wait_for(COND, MS) _wait_for(COND, MS, 1) -- GitLab From 4407be6ba217514b1bc01488f8b56467d309e416 Mon Sep 17 00:00:00 2001 From: "Philipp A. Mohrenweiser" Date: Mon, 6 Aug 2012 13:14:18 +0200 Subject: [PATCH 5148/5711] ALSA: hda - add dock support for Thinkpad T430s Add a model/fixup string "lenovo-dock", for Thinkpad T430s, to allow sound in docking station. Tested on Lenovo T430s with ThinkPad Mini Dock Plus Series 3 Cc: stable@kernel.org Signed-off-by: Philipp A. Mohrenweiser Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b9a5c4503336..bb93f927f7be 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6207,6 +6207,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), -- GitLab From 8dfaa573918afa34c8eaf8b2120b2e38cc4f651f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 Aug 2012 14:49:36 +0200 Subject: [PATCH 5149/5711] ALSA: hda - Fix regression of HDMI codec probing The commit c4bfe94a causes a regression on some codecs at probing. Since this was just a workaround to shut up a kernel warning, it'd be better to revert and fix properly. So we ended up with re-adding the cleanup callback. Tested-and-reported-by: Matt Horan Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 69b928449789..8f23374fa642 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -877,8 +877,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; - hinfo->nid = 0; /* clear the leftover value */ - /* Validate hinfo */ pin_idx = hinfo_to_pin_index(spec, hinfo); if (snd_BUG_ON(pin_idx < 0)) @@ -1163,6 +1161,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } +static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + snd_hda_codec_cleanup_stream(codec, hinfo->nid); + return 0; +} + static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1202,6 +1208,7 @@ static const struct hda_pcm_ops generic_ops = { .open = hdmi_pcm_open, .close = hdmi_pcm_close, .prepare = generic_hdmi_playback_pcm_prepare, + .cleanup = generic_hdmi_playback_pcm_cleanup, }; static int generic_hdmi_build_pcms(struct hda_codec *codec) @@ -1220,7 +1227,6 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; pstr->substreams = 1; pstr->ops = generic_ops; - pstr->nid = 1; /* FIXME: just for avoiding a debug WARNING */ /* other pstr fields are set in open */ } -- GitLab From e4651a9ff469935687778219f8ab43a8e715dd05 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Aug 2012 09:52:52 +0200 Subject: [PATCH 5150/5711] MAINTAINERS: update entry for Linus Walleij I prefer to use the Linaro mail address for the MAINTAINERS entry due to heavy mail traffic. Take this opportunity to update the wildcards, including removing the stmpe* drivers from the ux500 entry since these are not specific to that machine. Cc: Srinidhi Kasagar Signed-off-by: Linus Walleij Signed-off-by: Arnd Bergmann --- MAINTAINERS | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 94b823f71e94..b694a9d4e3ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -925,14 +925,14 @@ S: Maintained ARM/NOMADIK ARCHITECTURE M: Alessandro Rubini -M: Linus Walleij +M: Linus Walleij M: STEricsson L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-nomadik/ F: arch/arm/plat-nomadik/ F: drivers/i2c/busses/i2c-nomadik.c -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT M: Nelson Castillo @@ -1146,7 +1146,7 @@ F: drivers/usb/host/ehci-w90x900.c F: drivers/video/nuc900fb.c ARM/U300 MACHINE SUPPORT -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported F: arch/arm/mach-u300/ @@ -1161,15 +1161,20 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ARM/Ux500 ARM ARCHITECTURE M: Srinidhi Kasagar -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ux500/ +F: drivers/clocksource/clksrc-dbx500-prcmu.c F: drivers/dma/ste_dma40* +F: drivers/hwspinlock/u8500_hsem.c F: drivers/mfd/abx500* F: drivers/mfd/ab8500* -F: drivers/mfd/stmpe* +F: drivers/mfd/dbx500* +F: drivers/mfd/db8500* +F: drivers/pinctrl/pinctrl-nomadik* F: drivers/rtc/rtc-ab8500.c +F: drivers/rtc/rtc-pl031.c T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ARM/VFP SUPPORT @@ -3094,7 +3099,7 @@ F: include/linux/gigaset_dev.h GPIO SUBSYSTEM M: Grant Likely -M: Linus Walleij +M: Linus Walleij S: Maintained T: git git://git.secretlab.ca/git/linux-2.6.git F: Documentation/gpio.txt -- GitLab From 1adb7d31b051cd97fbb75c46772b00c13ec29c9e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 6 Aug 2012 14:18:42 +0200 Subject: [PATCH 5151/5711] iommu/amd: Fix pci_request_acs() call-place The pci_request_acs() function needs to be called before PCI probing to be effective. So move it to another call-place to ensure that. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 500e7f15f5c2..0a2ea317120a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1131,9 +1131,6 @@ static int __init amd_iommu_init_pci(void) break; } - /* Make sure ACS will be enabled */ - pci_request_acs(); - ret = amd_iommu_init_devices(); print_iommu_info(); @@ -1652,6 +1649,9 @@ static bool detect_ivrs(void) early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); + /* Make sure ACS will be enabled during PCI probe */ + pci_request_acs(); + return true; } -- GitLab From a4ff1fc2ccbd81e83ac51ea44570caa361c666af Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Sat, 4 Aug 2012 12:08:55 -0600 Subject: [PATCH 5152/5711] iommu/intel: Fix ACS path checking SR-IOV can create buses without a bridge. There may be other cases where this happens as well. In these cases skip to the parent bus and continue testing devices there. Signed-off-by: Alex Williamson Tested-by: David Ahern Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0204b62480b0..2297ec193eb4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4125,8 +4125,13 @@ static int intel_iommu_add_device(struct device *dev) } else dma_pdev = pci_dev_get(pdev); + /* Account for quirked devices */ swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); + /* + * If it's a multifunction device that does not support our + * required ACS flags, add to the same group as function 0. + */ if (dma_pdev->multifunction && !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) swap_pci_ref(&dma_pdev, @@ -4134,14 +4139,28 @@ static int intel_iommu_add_device(struct device *dev) PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), 0))); + /* + * Devices on the root bus go through the iommu. If that's not us, + * find the next upstream device and test ACS up to the root bus. + * Finding the next device may require skipping virtual buses. + */ while (!pci_is_root_bus(dma_pdev->bus)) { - if (pci_acs_path_enabled(dma_pdev->bus->self, - NULL, REQ_ACS_FLAGS)) + struct pci_bus *bus = dma_pdev->bus; + + while (!bus->self) { + if (!pci_is_root_bus(bus)) + bus = bus->parent; + else + goto root_bus; + } + + if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) break; - swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); + swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); } +root_bus: group = iommu_group_get(&dma_pdev->dev); pci_dev_put(dma_pdev); if (!group) { -- GitLab From 31fe943599b7e5870edb9decb7fbb9538b218f26 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Sat, 4 Aug 2012 12:09:03 -0600 Subject: [PATCH 5153/5711] iommu/amd: Fix ACS path checking SR-IOV can create buses without a bridge. There may be other cases where this happens as well. In these cases skip to the parent bus and continue testing devices there. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 6d1cbdfc9b2a..b64502dfa9f4 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -296,8 +296,13 @@ static int iommu_init_device(struct device *dev) } else dma_pdev = pci_dev_get(pdev); + /* Account for quirked devices */ swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); + /* + * If it's a multifunction device that does not support our + * required ACS flags, add to the same group as function 0. + */ if (dma_pdev->multifunction && !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) swap_pci_ref(&dma_pdev, @@ -305,14 +310,28 @@ static int iommu_init_device(struct device *dev) PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), 0))); + /* + * Devices on the root bus go through the iommu. If that's not us, + * find the next upstream device and test ACS up to the root bus. + * Finding the next device may require skipping virtual buses. + */ while (!pci_is_root_bus(dma_pdev->bus)) { - if (pci_acs_path_enabled(dma_pdev->bus->self, - NULL, REQ_ACS_FLAGS)) + struct pci_bus *bus = dma_pdev->bus; + + while (!bus->self) { + if (!pci_is_root_bus(bus)) + bus = bus->parent; + else + goto root_bus; + } + + if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) break; - swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); + swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); } +root_bus: group = iommu_group_get(&dma_pdev->dev); pci_dev_put(dma_pdev); if (!group) { -- GitLab From fb6ccff667712c46b4501b920ea73a326e49626a Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 24 Jul 2012 12:10:11 -0700 Subject: [PATCH 5154/5711] fuse: verify all ioctl retry iov elements Commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 attempted to verify that the total iovec from the client doesn't overflow iov_length() but it only checked the first element. The iovec could still overflow by starting with a small element. The obvious fix is to check all the elements. The overflow case doesn't look dangerous to the kernel as the copy is limited by the length after the overflow. This fix restores the intention of returning an error instead of successfully copying less than the iovec represented. I found this by code inspection. I built it but don't have a test case. I'm cc:ing stable because the initial commit did as well. Signed-off-by: Zach Brown Signed-off-by: Miklos Szeredi CC: [2.6.37+] --- fs/fuse/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 5800101e5ce1..2eed3acfb6a6 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1703,7 +1703,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) size_t n; u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; - for (n = 0; n < count; n++) { + for (n = 0; n < count; n++, iov++) { if (iov->iov_len > (size_t) max) return -ENOMEM; max -= iov->iov_len; -- GitLab From 5ab3633d6907018b0b830a720e877c3884d679c3 Mon Sep 17 00:00:00 2001 From: Hunt Xu Date: Sun, 1 Jul 2012 03:45:07 +0000 Subject: [PATCH 5155/5711] drm/i915: make rc6 in sysfs functions conditional Commit 0136db586c028f71e7cc21cc183064ff0d5919c8 merges rc6 information into the power group. However, when compiled with CONFIG_PM not set, modprobing i915 would taint since power_group_name is defined as NULL. This patch makes these rc6 in sysfs functions conditional upon the definition of the CONFIG_PM macro to avoid the above-mentioned problem. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45181 Cc: stable@vger.kernel.org Tested-by: Kris Karas Signed-off-by: Hunt Xu Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_sysfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2f5388af8df9..7631807a2788 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,6 +32,7 @@ #include "intel_drv.h" #include "i915_drv.h" +#ifdef CONFIG_PM static u32 calc_residency(struct drm_device *dev, const u32 reg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -224,3 +225,14 @@ void i915_teardown_sysfs(struct drm_device *dev) device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); } +#else +void i915_setup_sysfs(struct drm_device *dev) +{ + return; +} + +void i915_teardown_sysfs(struct drm_device *dev) +{ + return; +} +#endif /* CONFIG_PM */ -- GitLab From 8bb8148c78317e9360a21a0e69a58be6862adb07 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 5 Aug 2012 22:37:55 +0200 Subject: [PATCH 5156/5711] ARM: integrator: use clk_prepare_enable() for timer The Integrator timer is using the clock framework to get the timer frequency, but missed to prepare the clock before enabling. Signed-off-by: Linus Walleij Signed-off-by: Arnd Bergmann --- arch/arm/mach-integrator/integrator_ap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 7b1055c8e0b9..3b2267529f5e 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -456,7 +456,7 @@ static void __init ap_init_timer(void) clk = clk_get_sys("ap_timer", NULL); BUG_ON(IS_ERR(clk)); - clk_enable(clk); + clk_prepare_enable(clk); rate = clk_get_rate(clk); writel(0, TIMER0_VA_BASE + TIMER_CTRL); -- GitLab From 61c964ba1748e984cb232b431582815899bf10fe Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Tue, 10 Jul 2012 14:07:38 -0500 Subject: [PATCH 5157/5711] Bluetooth: btusb: Add vendor specific ID (0a5c:21f4) BCM20702A0 Patch adds support for BCM20702A0 device id (0a5c:21f4). usb-devices after patch was applied: T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21f4 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=E4D53DF154D6 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) usb-devices before patch was applied: T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21f4 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=E4D53DF154D6 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Manoj Iyer Tested-by: Chris Gagnon Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e27221411036..da6aa390d950 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -98,6 +98,7 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE(0x0a5c, 0x21e6) }, { USB_DEVICE(0x0a5c, 0x21e8) }, { USB_DEVICE(0x0a5c, 0x21f3) }, + { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ -- GitLab From 269c4845d5b3627b95b1934107251bacbe99bb68 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Fri, 15 Jun 2012 02:30:20 -0300 Subject: [PATCH 5158/5711] Bluetooth: Fix possible deadlock in SCO code sco_chan_del() only has conn != NULL when called from sco_conn_del() so just move the code from it that deal with conn to sco_conn_del(). [ 120.765529] [ 120.765529] ====================================================== [ 120.766529] [ INFO: possible circular locking dependency detected ] [ 120.766529] 3.5.0-rc1-10292-g3701f94-dirty #70 Tainted: G W [ 120.766529] ------------------------------------------------------- [ 120.766529] kworker/u:3/1497 is trying to acquire lock: [ 120.766529] (&(&conn->lock)->rlock#2){+.+...}, at: [] sco_chan_del+0x4c/0x170 [bluetooth] [ 120.766529] [ 120.766529] but task is already holding lock: [ 120.766529] (slock-AF_BLUETOOTH-BTPROTO_SCO){+.+...}, at: [] sco_conn_del+0x61/0xe0 [bluetooth] [ 120.766529] [ 120.766529] which lock already depends on the new lock. [ 120.766529] [ 120.766529] [ 120.766529] the existing dependency chain (in reverse order) is: [ 120.766529] [ 120.766529] -> #1 (slock-AF_BLUETOOTH-BTPROTO_SCO){+.+...}: [ 120.766529] [] lock_acquire+0x8e/0xb0 [ 120.766529] [] _raw_spin_lock+0x40/0x80 [ 120.766529] [] sco_connect_cfm+0x79/0x300 [bluetooth] [ 120.766529] [] hci_sync_conn_complete_evt.isra.90+0x343/0x400 [bluetooth] [ 120.766529] [] hci_event_packet+0x317/0xfb0 [bluetooth] [ 120.766529] [] hci_rx_work+0x2c8/0x890 [bluetooth] [ 120.766529] [] process_one_work+0x197/0x460 [ 120.766529] [] worker_thread+0x126/0x2d0 [ 120.766529] [] kthread+0x9d/0xb0 [ 120.766529] [] kernel_thread_helper+0x4/0x10 [ 120.766529] [ 120.766529] -> #0 (&(&conn->lock)->rlock#2){+.+...}: [ 120.766529] [] __lock_acquire+0x154a/0x1d30 [ 120.766529] [] lock_acquire+0x8e/0xb0 [ 120.766529] [] _raw_spin_lock+0x40/0x80 [ 120.766529] [] sco_chan_del+0x4c/0x170 [bluetooth] [ 120.766529] [] sco_conn_del+0x74/0xe0 [bluetooth] [ 120.766529] [] sco_disconn_cfm+0x32/0x60 [bluetooth] [ 120.766529] [] hci_disconn_complete_evt.isra.53+0x242/0x390 [bluetooth] [ 120.766529] [] hci_event_packet+0x617/0xfb0 [bluetooth] [ 120.766529] [] hci_rx_work+0x2c8/0x890 [bluetooth] [ 120.766529] [] process_one_work+0x197/0x460 [ 120.766529] [] worker_thread+0x126/0x2d0 [ 120.766529] [] kthread+0x9d/0xb0 [ 120.766529] [] kernel_thread_helper+0x4/0x10 [ 120.766529] [ 120.766529] other info that might help us debug this: [ 120.766529] [ 120.766529] Possible unsafe locking scenario: [ 120.766529] [ 120.766529] CPU0 CPU1 [ 120.766529] ---- ---- [ 120.766529] lock(slock-AF_BLUETOOTH-BTPROTO_SCO); [ 120.766529] lock(&(&conn->lock)->rlock#2); [ 120.766529] lock(slock-AF_BLUETOOTH-BTPROTO_SCO); [ 120.766529] lock(&(&conn->lock)->rlock#2); [ 120.766529] [ 120.766529] *** DEADLOCK *** Signed-off-by: Gustavo Padovan --- net/bluetooth/sco.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff7..3589e21edb09 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -131,6 +131,15 @@ static int sco_conn_del(struct hci_conn *hcon, int err) sco_sock_clear_timer(sk); sco_chan_del(sk, err); bh_unlock_sock(sk); + + sco_conn_lock(conn); + conn->sk = NULL; + sco_pi(sk)->conn = NULL; + sco_conn_unlock(conn); + + if (conn->hcon) + hci_conn_put(conn->hcon); + sco_sock_kill(sk); } @@ -821,16 +830,6 @@ static void sco_chan_del(struct sock *sk, int err) BT_DBG("sk %p, conn %p, err %d", sk, conn, err); - if (conn) { - sco_conn_lock(conn); - conn->sk = NULL; - sco_pi(sk)->conn = NULL; - sco_conn_unlock(conn); - - if (conn->hcon) - hci_conn_put(conn->hcon); - } - sk->sk_state = BT_CLOSED; sk->sk_err = err; sk->sk_state_change(sk); -- GitLab From a9ea3ed9b71cc3271dd59e76f65748adcaa76422 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 19 Jul 2012 14:46:08 +0200 Subject: [PATCH 5159/5711] Bluetooth: Fix legacy pairing with some devices Some devices e.g. some Android based phones don't do SDP search before pairing and cancel legacy pairing when ACL is disconnected. PIN Code Request event which changes ACL timeout to HCI_PAIRING_TIMEOUT is only received after remote user entered PIN. In that case no L2CAP is connected so default HCI_DISCONN_TIMEOUT (2 seconds) is being used to timeout ACL connection. This results in problems with legacy pairing as remote user has only few seconds to enter PIN before ACL is disconnected. Increase disconnect timeout for incomming connection to HCI_PAIRING_TIMEOUT if SSP is disabled and no linkey exists. To avoid keeping ACL alive for too long after SDP search set ACL timeout back to HCI_DISCONN_TIMEOUT when L2CAP is connected. 2012-07-19 13:24:43.413521 < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr 00:02:72:D6:6A:3F ptype 0xcc18 rswitch 0x01 clkoffset 0x0000 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 2012-07-19 13:24:43.425224 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 2012-07-19 13:24:43.885222 > HCI Event: Role Change (0x12) plen 8 status 0x00 bdaddr 00:02:72:D6:6A:3F role 0x01 Role: Slave 2012-07-19 13:24:44.054221 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 42 bdaddr 00:02:72:D6:6A:3F type ACL encrypt 0x00 2012-07-19 13:24:44.054313 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 42 2012-07-19 13:24:44.055176 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 bdaddr 00:02:72:D6:6A:3F mode 0 2012-07-19 13:24:44.056217 > HCI Event: Max Slots Change (0x1b) plen 3 handle 42 slots 5 2012-07-19 13:24:44.059218 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 0 2012-07-19 13:24:44.062192 > HCI Event: Command Status (0x0f) plen 4 Unknown (0x00|0x0000) status 0x00 ncmd 1 2012-07-19 13:24:44.067219 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 42 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 2012-07-19 13:24:44.067248 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 42 page 1 2012-07-19 13:24:44.071217 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 2012-07-19 13:24:44.076218 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 42 page 1 max 1 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 2012-07-19 13:24:44.076249 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:02:72:D6:6A:3F mode 2 clkoffset 0x0000 2012-07-19 13:24:44.081218 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 1 2012-07-19 13:24:44.105214 > HCI Event: Remote Name Req Complete (0x07) plen 255 status 0x00 bdaddr 00:02:72:D6:6A:3F name 'uw000951-0' 2012-07-19 13:24:44.105284 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 42 2012-07-19 13:24:44.111207 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 2012-07-19 13:24:44.112220 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.112249 < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.115215 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 status 0x00 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.116215 > HCI Event: PIN Code Request (0x16) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:48.099184 > HCI Event: Auth Complete (0x06) plen 3 status 0x13 handle 42 Error: Remote User Terminated Connection 2012-07-19 13:24:48.179182 > HCI Event: Disconn Complete (0x05) plen 4 status 0x00 handle 42 reason 0x13 Reason: Remote User Terminated Connection Cc: stable@vger.kernel.org Signed-off-by: Szymon Janc Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 7 ++++++- net/bluetooth/l2cap_core.c | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f9..248632cec11d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1762,7 +1762,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); - conn->disc_timeout = HCI_DISCONN_TIMEOUT; + + if (!conn->out && !hci_conn_ssp_enabled(conn) && + !hci_find_link_key(hdev, &ev->bdaddr)) + conn->disc_timeout = HCI_PAIRING_TIMEOUT; + else + conn->disc_timeout = HCI_DISCONN_TIMEOUT; } else conn->state = BT_CONNECTED; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bfb..daa149b7003c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1181,6 +1181,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) sk = chan->sk; hci_conn_hold(conn->hcon); + conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); -- GitLab From c810089c27e48b816181b454fcc493d19fdbc2ba Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:09 +0300 Subject: [PATCH 5160/5711] Bluetooth: Fix using NULL inquiry entry If entry wasn't found in the hci_inquiry_cache_lookup_resolve do not resolve the name.This will fix a kernel crash when trying to use NULL pointer. Cc: stable@vger.kernel.org Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 248632cec11d..b64cfa213bd6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1365,6 +1365,9 @@ static bool hci_resolve_next_name(struct hci_dev *hdev) return false; e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); + if (!e) + return false; + if (hci_resolve_name(hdev, e) == 0) { e->name_state = NAME_PENDING; return true; -- GitLab From 7cc8380eb10347016d95bf6f9d842c2ae6d12932 Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:10 +0300 Subject: [PATCH 5161/5711] Bluetooth: Fix using a NULL inquiry cache entry If the device was not found in a list of found devices names of which are pending.This may happen in a case when HCI Remote Name Request was sent as a part of incoming connection establishment procedure. Hence there is no need to continue resolving a next name as it will be done upon receiving another Remote Name Request Complete Event. This will fix a kernel crash when trying to use this entry to resolve the next name. Cc: stable@vger.kernel.org Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b64cfa213bd6..fe9a3d6d30b0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1396,12 +1396,18 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, return; e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); - if (e) { + /* If the device was not found in a list of found devices names of which + * are pending. there is no need to continue resolving a next name as it + * will be done upon receiving another Remote Name Request Complete + * Event */ + if (!e) + return; + + list_del(&e->list); + if (name) { e->name_state = NAME_KNOWN; - list_del(&e->list); - if (name) - mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, - e->data.rssi, name, name_len); + mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, + e->data.rssi, name, name_len); } if (hci_resolve_next_name(hdev)) -- GitLab From c3e7c0d90b14a3e7ac091d24cef09efb516d587b Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:11 +0300 Subject: [PATCH 5162/5711] Bluetooth: Set name_state to unknown when entry name is empty When the name of the given entry is empty , the state needs to be updated accordingly. Cc: stable@vger.kernel.org Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index fe9a3d6d30b0..715d7e33fba0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1408,6 +1408,8 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, e->name_state = NAME_KNOWN; mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, e->data.rssi, name, name_len); + } else { + e->name_state = NAME_NOT_KNOWN; } if (hci_resolve_next_name(hdev)) -- GitLab From d08fd0e712a834d4abb869c0215a702e290bc51e Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:43 +0300 Subject: [PATCH 5163/5711] Bluetooth: smp: Fix possible NULL dereference smp_chan_create might return NULL so we need to check before dereferencing smp. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 16ef0dc85a0a..901a616c8083 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -579,8 +579,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) smp = smp_chan_create(conn); + else + smp = conn->smp_chan; - smp = conn->smp_chan; + if (!smp) + return SMP_UNSPECIFIED; smp->preq[0] = SMP_CMD_PAIRING_REQ; memcpy(&smp->preq[1], req, sizeof(*req)); -- GitLab From 49dfbb9129c4edb318578de35cc45c555df37884 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Thu, 19 Jul 2012 12:54:04 +0530 Subject: [PATCH 5164/5711] Bluetooth: Fix socket not getting freed if l2cap channel create fails If l2cap_chan_create() fails then it will return from l2cap_sock_kill since zapped flag of sk is reset. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427e..b94abd30e6f9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1174,7 +1174,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p chan = l2cap_chan_create(); if (!chan) { - l2cap_sock_kill(sk); + sk_free(sk); return NULL; } -- GitLab From 1f6fc43e621167492ed4b7f3b4269c584c3d6ccc Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 2 Aug 2012 18:41:48 +0100 Subject: [PATCH 5165/5711] cfg80211: process pending events when unregistering net device libertas currently calls cfg80211_disconnected() when it is being brought down. This causes an event to be allocated, but since the wdev is already removed from the rdev by the time that the event processing work executes, the event is never processed or freed. http://article.gmane.org/gmane.linux.kernel.wireless.general/95666 Fix this leak, and other possible situations, by processing the event queue when a device is being unregistered. Thanks to Johannes Berg for the suggestion. Signed-off-by: Daniel Drake Cc: stable@vger.kernel.org Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 5 +++++ net/wireless/core.h | 1 + net/wireless/util.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 31b40cc4a9c3..dcd64d5b07aa 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -952,6 +952,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, */ synchronize_rcu(); INIT_LIST_HEAD(&wdev->list); + /* + * Ensure that all events have been processed and + * freed. + */ + cfg80211_process_wdev_events(wdev); break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/net/wireless/core.h b/net/wireless/core.h index 5206c6844fd7..bc7430b54771 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); +void cfg80211_process_wdev_events(struct wireless_dev *wdev); int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, diff --git a/net/wireless/util.c b/net/wireless/util.c index 26f8cd30f712..994e2f0cc7a8 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -735,7 +735,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) wdev->connect_keys = NULL; } -static void cfg80211_process_wdev_events(struct wireless_dev *wdev) +void cfg80211_process_wdev_events(struct wireless_dev *wdev) { struct cfg80211_event *ev; unsigned long flags; -- GitLab From deee0214def5d8a32b8112f11d9c2b1696e9c0cb Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Aug 2012 12:49:14 +0200 Subject: [PATCH 5166/5711] rt61pci: fix NULL pointer dereference in config_lna_gain We can not pass NULL libconf->conf->channel to rt61pci_config() as it is dereferenced unconditionally in rt61pci_config_lna_gain() subroutine. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=44361 Cc: stable@vger.kernel.org Reported-and-tested-by: Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f32259686b45..3f7bc5cadf9a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2243,8 +2243,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) { - struct ieee80211_conf conf = { .flags = 0 }; - struct rt2x00lib_conf libconf = { .conf = &conf }; + struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf }; rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -- GitLab From 50e2a30cf6fcaeb2d27360ba614dd169a10041c5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 5 Aug 2012 18:31:46 +0200 Subject: [PATCH 5167/5711] iwlwifi: disable greenfield transmissions as a workaround There's a bug that causes the rate scaling to get stuck when it has to use single-stream rates with a peer that can do GF and SGI; the two are incompatible so we can't use them together, but that causes the algorithm to not work at all, it always rejects updates. Disable greenfield for now to prevent that problem. Cc: stable@vger.kernel.org Reviewed-by: Emmanuel Grumbach Tested-by: Cesar Eduardo Barros Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/dvm/rs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 6fddd2785e6e..a82f46c10f5e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -707,11 +707,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, */ static bool rs_use_green(struct ieee80211_sta *sta) { - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; - - return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ctx->ht.non_gf_sta_present); + /* + * There's a bug somewhere in this code that causes the + * scaling to get stuck because GF+SGI can't be combined + * in SISO rates. Until we find that bug, disable GF, it + * has only limited benefit and we still interoperate with + * GF APs since we can always receive GF transmissions. + */ + return false; } /** -- GitLab From 2096ae6ca647302d50a68aa36cb66a00e7dfac70 Mon Sep 17 00:00:00 2001 From: Peng Chen Date: Wed, 1 Aug 2012 10:11:59 +0800 Subject: [PATCH 5168/5711] Bluetooth: add support for atheros 0489:e057 Add support for the AR3012 chip found on Fioxconn. usb-devices shows: T: Bus=06 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 44 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e057 Rev= 0.02 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Peng Chen Signed-off-by: Gustavo Padovan --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 10308cd8a7ed..11f36e502136 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -79,6 +79,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0489, 0xe057) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -104,6 +105,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index da6aa390d950..cef3bac1a543 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, -- GitLab From 25099335944a23db75d4916644122c746684e093 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Sat, 4 Aug 2012 00:14:25 +0000 Subject: [PATCH 5169/5711] mISDN: Bugfix for layer2 fixed TEI mode If a fixed TEI is used, the initial state of the layer 2 statmachine need to be 4 (TEI assigned). This was true only for Point to Point connections, but not for the other fixed TEIs. It was not found before, because usually only the TEI 0 is used as fixed TEI for PtP mode, but if you try X31 packet mode connections with SAPI 16, TEI 1, it did fail. Signed-off-by: Karsten Keil Cc: # 3.5.x Signed-off-by: David S. Miller --- drivers/isdn/mISDN/layer2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 0dc8abca1407..949cabb88f1c 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -2222,7 +2222,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei, InitWin(l2); l2->l2m.fsm = &l2fsm; if (test_bit(FLG_LAPB, &l2->flag) || - test_bit(FLG_PTP, &l2->flag) || + test_bit(FLG_FIXED_TEI, &l2->flag) || test_bit(FLG_LAPD_NET, &l2->flag)) l2->l2m.state = ST_L2_4; else -- GitLab From caa0bf648cd20a2efbb6558531711e9ce2c6e948 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sat, 4 Aug 2012 04:13:26 +0000 Subject: [PATCH 5170/5711] batman-adv: select an internet gateway if none was chosen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a regression introduced by: 2265c141086474bbae55a5bb3afa1ebb78ccaa7c ("batman-adv: gateway election code refactoring") Reported-by: Nicolás Echániz Signed-off-by: Marek Lindner Acked-by: Antonio Quartulli Signed-off-by: Antonio Quartulli Signed-off-by: David S. Miller --- net/batman-adv/gateway_client.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index b421cc49d2cd..fc866f2e4528 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -200,11 +200,11 @@ void batadv_gw_election(struct batadv_priv *bat_priv) if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) goto out; - if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect)) - goto out; - curr_gw = batadv_gw_get_selected_gw_node(bat_priv); + if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect) && curr_gw) + goto out; + next_gw = batadv_gw_get_best_gw_node(bat_priv); if (curr_gw == next_gw) -- GitLab From 7cefdd1f55ec075f1f2da0a321495d5a8262ffaa Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Aug 2012 06:50:49 +0000 Subject: [PATCH 5171/5711] drivers/net/phy/mdio-mux-gpio.c: drop devm_kfree of devm_kzalloc'd data devm_kfree should not have to be explicitly used. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,d; @@ x = devm_kzalloc(...) ... ?-devm_kfree(d,x); // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-gpio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c index e0cc4ef33dee..eefe49e8713c 100644 --- a/drivers/net/phy/mdio-mux-gpio.c +++ b/drivers/net/phy/mdio-mux-gpio.c @@ -101,7 +101,6 @@ err: n--; gpio_free(s->gpio[n]); } - devm_kfree(&pdev->dev, s); return r; } -- GitLab From 8e7dfbc8d1ea9ca9058aa641a8fe795ebca320e2 Mon Sep 17 00:00:00 2001 From: Silviu-Mihai Popescu Date: Sat, 4 Aug 2012 09:31:29 +0000 Subject: [PATCH 5172/5711] tcp_output: fix sparse warning for tcp_wfree Fix sparse warning: * symbol 'tcp_wfree' was not declared. Should it be static? Signed-off-by: Silviu-Mihai Popescu Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a7b3ec9b6c3e..20dfd892c86f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -940,7 +940,7 @@ void __init tcp_tasklet_init(void) * We cant xmit new skbs from this context, as we might already * hold qdisc lock. */ -void tcp_wfree(struct sk_buff *skb) +static void tcp_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; struct tcp_sock *tp = tcp_sk(sk); -- GitLab From f716168b8aee528cf685246f0e7247aa0d08b79c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Aug 2012 23:52:36 +0000 Subject: [PATCH 5173/5711] drivers/atm/iphase.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/atm/iphase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index d4386019af5d..96cce6d53195 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -2362,7 +2362,7 @@ static int __devinit ia_init(struct atm_dev *dev) { printk(DEV_LABEL " (itf %d): can't set up page mapping\n", dev->number); - return error; + return -ENOMEM; } IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n", dev->number, iadev->pci->revision, base, iadev->irq);) -- GitLab From 8b82f7c3c90fa67fd6d5be1deb3cec0e17cc32d9 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Sun, 5 Aug 2012 10:30:11 +0000 Subject: [PATCH 5174/5711] ixp4xx_eth: fix ptp_ixp46x build failure When building with ixp4xx_eth and ptp_ixp46x as module, one is getting the following error: ERROR: "ixp46x_phc_index" [drivers/ptp/ptp_ixp46x.ko] undefined! This has been introduced by commit 509a7c25729feab353502e1b544c614772a1d49a. Signed-off-by: Arnaud Patard Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/xscale/ixp4xx_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 482648fcf0b6..98934bdf6acf 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1003,6 +1003,7 @@ static int ixp4xx_nway_reset(struct net_device *dev) } int ixp46x_phc_index = -1; +EXPORT_SYMBOL_GPL(ixp46x_phc_index); static int ixp4xx_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) -- GitLab From 91d27a8650d5359a7a320daeb35b88cdea15e3a8 Mon Sep 17 00:00:00 2001 From: Sorin Dumitru Date: Mon, 6 Aug 2012 02:35:58 +0000 Subject: [PATCH 5175/5711] llc: free the right skb We are freeing skb instead of nskb, resulting in a double free on skb and a leak from nskb. Signed-off-by: Sorin Dumitru Signed-off-by: David S. Miller --- net/llc/llc_station.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 39a8d8924b9c..6828e39ec2ec 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -268,7 +268,7 @@ static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) out: return rc; free: - kfree_skb(skb); + kfree_skb(nskb); goto out; } @@ -293,7 +293,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) out: return rc; free: - kfree_skb(skb); + kfree_skb(nskb); goto out; } @@ -322,7 +322,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) out: return rc; free: - kfree_skb(skb); + kfree_skb(nskb); goto out; } -- GitLab From 9871f1ad677d95ffeca80e2c21b70af9bfc9cc91 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 6 Aug 2012 03:55:29 +0000 Subject: [PATCH 5176/5711] ip: fix error handling in ip_finish_output2() __neigh_create() returns either a pointer to struct neighbour or PTR_ERR(). But the caller expects it to return either a pointer or NULL. Replace the NULL check with IS_ERR() check. The bug was introduced in a263b3093641fb1ec377582c90986a7fd0625184 ("ipv4: Make neigh lookups directly in output packet path."). Signed-off-by: Vasily Kulikov Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ba39a52d18c1..76dde25fb9a0 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -197,7 +197,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) neigh = __ipv4_neigh_lookup_noref(dev, nexthop); if (unlikely(!neigh)) neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); - if (neigh) { + if (!IS_ERR(neigh)) { int res = dst_neigh_output(dst, neigh, skb); rcu_read_unlock_bh(); -- GitLab From 47fd92f5a76eb3f5b407773766e7d7fa1a179419 Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Mon, 6 Aug 2012 05:45:48 +0000 Subject: [PATCH 5177/5711] net_sched: act: Delete estimator in error path. Some action modules free struct tcf_common in their error path while estimator is still active. This results in est_timer() dereference freed memory. Add gen_kill_estimator() in ipt, pedit and simple action. Signed-off-by: Hiroaki SHIMODA Signed-off-by: David S. Miller --- net/sched/act_ipt.c | 7 ++++++- net/sched/act_pedit.c | 5 ++++- net/sched/act_simple.c | 5 ++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 60e281ad0f07..58fb3c7aab9e 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -185,7 +185,12 @@ err3: err2: kfree(tname); err1: - kfree(pc); + if (ret == ACT_P_CREATED) { + if (est) + gen_kill_estimator(&pc->tcfc_bstats, + &pc->tcfc_rate_est); + kfree_rcu(pc, tcfc_rcu); + } return err; } diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 26aa2f6ce257..45c53ab067a6 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -74,7 +74,10 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est, p = to_pedit(pc); keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) { - kfree(pc); + if (est) + gen_kill_estimator(&pc->tcfc_bstats, + &pc->tcfc_rate_est); + kfree_rcu(pc, tcfc_rcu); return -ENOMEM; } ret = ACT_P_CREATED; diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 3922f2a2821b..3714f60f0b3c 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -131,7 +131,10 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, d = to_defact(pc); ret = alloc_defdata(d, defdata); if (ret < 0) { - kfree(pc); + if (est) + gen_kill_estimator(&pc->tcfc_bstats, + &pc->tcfc_rate_est); + kfree_rcu(pc, tcfc_rcu); return ret; } d->tcf_action = parm->action; -- GitLab From b5497eeb37d7d4a5a61b91f64efedc90d1ad6fa3 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Mon, 6 Aug 2012 07:51:16 +0000 Subject: [PATCH 5178/5711] net: Use PTR_RET rather than if(IS_ERR(.. [1] The semantic patch that makes this change is available in scripts/coccinelle/api/ptr_ret.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: David S. Miller --- drivers/net/appletalk/cops.c | 4 +--- drivers/net/appletalk/ltpc.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 545c09ed9079..cff6f023c03a 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -996,9 +996,7 @@ static int __init cops_module_init(void) printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", cardname); cops_dev = cops_probe(-1); - if (IS_ERR(cops_dev)) - return PTR_ERR(cops_dev); - return 0; + return PTR_RET(cops_dev); } static void __exit cops_module_exit(void) diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 0910dce3996d..b5782cdf0bca 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1243,9 +1243,7 @@ static int __init ltpc_module_init(void) "ltpc: Autoprobing is not recommended for modules\n"); dev_ltpc = ltpc_probe(); - if (IS_ERR(dev_ltpc)) - return PTR_ERR(dev_ltpc); - return 0; + return PTR_RET(dev_ltpc); } module_init(ltpc_module_init); #endif -- GitLab From 5d299f3d3c8a2fbc732b1bf03af36333ccec3130 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 6 Aug 2012 05:09:33 +0000 Subject: [PATCH 5179/5711] net: ipv6: fix TCP early demux IPv6 needs a cookie in dst_check() call. We need to add rx_dst_cookie and provide a family independent sk_rx_dst_set(sk, skb) method to properly support IPv6 TCP early demux. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/ipv6.h | 1 + include/net/inet_connection_sock.h | 1 + include/net/inet_sock.h | 9 --------- net/ipv4/tcp_input.c | 4 +++- net/ipv4/tcp_ipv4.c | 13 ++++++++++--- net/ipv4/tcp_minisocks.c | 2 +- net/ipv6/tcp_ipv6.c | 27 +++++++++++++++++++++++++-- 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 379e433e15e0..879db26ec401 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -369,6 +369,7 @@ struct ipv6_pinfo { __u8 rcv_tclass; __u32 dst_cookie; + __u32 rx_dst_cookie; struct ipv6_mc_socklist __rcu *ipv6_mc_list; struct ipv6_ac_socklist *ipv6_ac_list; diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 5ee66f517b4f..ba1d3615acbb 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -39,6 +39,7 @@ struct inet_connection_sock_af_ops { int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl); void (*send_check)(struct sock *sk, struct sk_buff *skb); int (*rebuild_header)(struct sock *sk); + void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb); int (*conn_request)(struct sock *sk, struct sk_buff *skb); struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, struct request_sock *req, diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 83b567fe1941..613cfa401672 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -249,13 +249,4 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) return flags; } -static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - - dst_hold(dst); - sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; -} - #endif /* _INET_SOCK_H */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2fd2bc9e3c64..85308b90df80 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5392,6 +5392,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, { struct tcp_sock *tp = tcp_sk(sk); + if (unlikely(sk->sk_rx_dst == NULL)) + inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); /* * Header prediction. * The code loosely follows the one in the famous @@ -5605,7 +5607,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) tcp_set_state(sk, TCP_ESTABLISHED); if (skb != NULL) { - inet_sk_rx_dst_set(sk, skb); + icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); security_inet_conn_established(sk, skb); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 42b2a6a73092..272241f16fcb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1627,9 +1627,6 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) sk->sk_rx_dst = NULL; } } - if (unlikely(sk->sk_rx_dst == NULL)) - inet_sk_rx_dst_set(sk, skb); - if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { rsk = sk; goto reset; @@ -1872,10 +1869,20 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_destructor= tcp_twsk_destructor, }; +static void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +} + const struct inet_connection_sock_af_ops ipv4_specific = { .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, + .sk_rx_dst_set = inet_sk_rx_dst_set, .conn_request = tcp_v4_conn_request, .syn_recv_sock = tcp_v4_syn_recv_sock, .net_header_len = sizeof(struct iphdr), diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 232a90c3ec86..d9c9dcef2de3 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -387,7 +387,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct tcp_sock *oldtp = tcp_sk(sk); struct tcp_cookie_values *oldcvp = oldtp->cookie_values; - inet_sk_rx_dst_set(newsk, skb); + newicsk->icsk_af_ops->sk_rx_dst_set(newsk, skb); /* TCP Cookie Transactions require space for the cookie pair, * as it differs for each connection. There is no need to diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c66b90f71c9b..5a439e9a4c01 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1447,7 +1447,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ + struct dst_entry *dst = sk->sk_rx_dst; + sock_rps_save_rxhash(sk, skb); + if (dst) { + if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || + dst->ops->check(dst, np->rx_dst_cookie) == NULL) { + dst_release(dst); + sk->sk_rx_dst = NULL; + } + } + if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) goto reset; if (opt_skb) @@ -1705,9 +1715,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb) struct dst_entry *dst = sk->sk_rx_dst; struct inet_sock *icsk = inet_sk(sk); if (dst) - dst = dst_check(dst, 0); + dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); if (dst && - icsk->rx_dst_ifindex == inet6_iif(skb)) + icsk->rx_dst_ifindex == skb->skb_iif) skb_dst_set_noref(skb, dst); } } @@ -1719,10 +1729,23 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_destructor= tcp_twsk_destructor, }; +static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + const struct rt6_info *rt = (const struct rt6_info *)dst; + + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + if (rt->rt6i_node) + inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; +} + static const struct inet_connection_sock_af_ops ipv6_specific = { .queue_xmit = inet6_csk_xmit, .send_check = tcp_v6_send_check, .rebuild_header = inet6_sk_rebuild_header, + .sk_rx_dst_set = inet6_sk_rx_dst_set, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, .net_header_len = sizeof(struct ipv6hdr), -- GitLab From c8415a48fcb7a29889f4405d38c57db351e4b50a Mon Sep 17 00:00:00 2001 From: Felix Kaechele Date: Mon, 6 Aug 2012 23:02:01 +0200 Subject: [PATCH 5180/5711] ALSA: hda - add dock support for Thinkpad X230 As with the ThinkPad Models X230 Tablet and T530 the X230 needs a qurik to correctly set up the pins for the dock port. Signed-off-by: Felix Kaechele Cc: [v3.2+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bb93f927f7be..daa5103eb936 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6207,6 +6207,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), -- GitLab From f6b0ca25ee402f714487b31c35f8e11f2bf4310b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 5 Aug 2012 14:01:25 +0800 Subject: [PATCH 5181/5711] gpio/mxc: remove redundant shadow variables initialization With commit 3e11f7b (gpio/generic: initialize basic_mmio_gpio shadow variables properly) in place, the shadow variables initialization is being done in generic driver bgpio_init call. Remove the redundant shadow variables initialization from gpio-mxc driver. Signed-off-by: Shawn Guo Tested-by: Dirk Behme Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 4db460b6ecf7..76e8cda9c06f 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -466,8 +466,6 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) port->bgc.gc.to_irq = mxc_gpio_to_irq; port->bgc.gc.base = pdev->id * 32; - port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir); - port->bgc.data = port->bgc.read_reg(port->bgc.reg_set); err = gpiochip_add(&port->bgc.gc); if (err) -- GitLab From 7e6086d9e54a159a6257c02bb7fc5805c614aad2 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 5 Aug 2012 14:01:26 +0800 Subject: [PATCH 5182/5711] gpio/mxc: specify gpio base for device tree probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, unlike the non-DT probe where the gpio base is specified with pdev->id, the DT probe uses the base dynamically allocated by gpio core, which uses a completely different numbering scheme. This causes two issues to user space applications which access sysfs entry /sys/class/gpio/gpioN. * It breaks the compatibility with user space applications between non-DT and DT kernels. * It's not intuitive and sometimes hard for users to map the Linux gpio number to the actual hardware pin. Use alias to identify the gpio port/bank, and then the gpio base can be specified with port id to solve above issues. If alias is not defined in device tree, the base number dynamically allocated by gpio core will be used. Signed-off-by: Shawn Guo Tested-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 76e8cda9c06f..80f44bb64a87 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -465,7 +465,8 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) goto out_iounmap; port->bgc.gc.to_irq = mxc_gpio_to_irq; - port->bgc.gc.base = pdev->id * 32; + port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : + pdev->id * 32; err = gpiochip_add(&port->bgc.gc); if (err) -- GitLab From 5230f8fe9ad870ac24f23bca496347b87185c7c5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 5 Aug 2012 14:01:28 +0800 Subject: [PATCH 5183/5711] ARM: dts: imx: add alias for gpio Add alias for gpio nodes, so that gpio driver can identify the port number and then specify a sensible gpio base rather than using the one dynamically allocated by gpio core. Signed-off-by: Shawn Guo Signed-off-by: Linus Walleij --- arch/arm/boot/dts/imx27.dtsi | 6 ++++++ arch/arm/boot/dts/imx51.dtsi | 4 ++++ arch/arm/boot/dts/imx53.dtsi | 7 +++++++ arch/arm/boot/dts/imx6q.dtsi | 7 +++++++ 4 files changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 00bae3aad5ab..5303ab680a34 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -19,6 +19,12 @@ serial3 = &uart4; serial4 = &uart5; serial5 = &uart6; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + gpio5 = &gpio6; }; avic: avic-interrupt-controller@e0000000 { diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 53cbaa3d4f90..aba28dc87fc8 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -17,6 +17,10 @@ serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; }; tzic: tz-interrupt-controller@e0000000 { diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index fc79cdc4b4e6..cd37165edce5 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -19,6 +19,13 @@ serial2 = &uart3; serial3 = &uart4; serial4 = &uart5; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + gpio5 = &gpio6; + gpio6 = &gpio7; }; tzic: tz-interrupt-controller@0fffc000 { diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 3d3c64b014e6..fd57079f71a9 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -19,6 +19,13 @@ serial2 = &uart3; serial3 = &uart4; serial4 = &uart5; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + gpio5 = &gpio6; + gpio6 = &gpio7; }; cpus { -- GitLab From f7093f3e7a50bfeeceb8950f9130cbf8af74bf92 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Fri, 20 Jul 2012 13:58:59 -0700 Subject: [PATCH 5184/5711] gpio: samsung: Fix off-by-one bug in gpio addresses Move gpc4 to the end of the automatically processed gpio controllers so we don't taint the automatic offset calculation. This bug caused all controllers coming after gpc4 to map to the incorrect address. The result is <&gpd1 0 0 0 0> would actually map to GPIO 0 in gpd0. Signed-off-by: Sean Paul Reviewed-by: Thomas Abraham Acked-by: Doug Anderson Acked-by: Kukjin Kim Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 92f7b2bb79d4..ba126cc04073 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2452,12 +2452,6 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { .ngpio = EXYNOS5_GPIO_C3_NR, .label = "GPC3", }, - }, { - .chip = { - .base = EXYNOS5_GPC4(0), - .ngpio = EXYNOS5_GPIO_C4_NR, - .label = "GPC4", - }, }, { .chip = { .base = EXYNOS5_GPD0(0), @@ -2512,6 +2506,12 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { .ngpio = EXYNOS5_GPIO_Y6_NR, .label = "GPY6", }, + }, { + .chip = { + .base = EXYNOS5_GPC4(0), + .ngpio = EXYNOS5_GPIO_C4_NR, + .label = "GPC4", + }, }, { .config = &samsung_gpio_cfgs[9], .irq_base = IRQ_EINT(0), @@ -2836,7 +2836,7 @@ static __init void exynos5_gpiolib_init(void) } /* need to set base address for gpc4 */ - exynos5_gpios_1[11].base = gpio_base1 + 0x2E0; + exynos5_gpios_1[20].base = gpio_base1 + 0x2E0; /* need to set base address for gpx */ chip = &exynos5_gpios_1[21]; -- GitLab From d6a2b7ba67334a7e72cd153c142c449831557cb9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 5 Aug 2012 11:52:34 +0200 Subject: [PATCH 5185/5711] drivers/gpio/gpio-langwell.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Linus Walleij --- drivers/gpio/gpio-langwell.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index a1c8754f52cf..202a99207b7d 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c @@ -339,7 +339,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, resource_size_t start, len; struct lnw_gpio *lnw; u32 gpio_base; - int retval = 0; + int retval; int ngpio = id->driver_data; retval = pci_enable_device(pdev); @@ -357,6 +357,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, base = ioremap_nocache(start, len); if (!base) { dev_err(&pdev->dev, "error mapping bar1\n"); + retval = -EFAULT; goto err3; } gpio_base = *((u32 *)base + 1); @@ -381,8 +382,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, &lnw_gpio_irq_ops, lnw); - if (!lnw->domain) + if (!lnw->domain) { + retval = -ENOMEM; goto err3; + } lnw->reg_base = base; lnw->chip.label = dev_name(&pdev->dev); -- GitLab From 9de76b6df70003b657d907571b17ac3c17cd9082 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Thu, 26 Jul 2012 13:20:34 +0200 Subject: [PATCH 5186/5711] i.MX27: Fix emma-prp and csi clocks. Naming of emma-prp related clocks for the i.MX27 is not correct. Signed-off-by: Javier Martin Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx27.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 7aa6313fb167..f69ca4680049 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -223,7 +223,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0"); - clk_register_clkdev(clk[csi_ahb_gate], NULL, "mx2-camera.0"); + clk_register_clkdev(clk[csi_ahb_gate], "ahb", "mx2-camera.0"); clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc"); clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc"); @@ -250,8 +250,10 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1"); clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0"); clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad"); - clk_register_clkdev(clk[emma_ahb_gate], "ahb", "imx-emma"); - clk_register_clkdev(clk[emma_ipg_gate], "ipg", "imx-emma"); + clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "mx2-camera.0"); + clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "mx2-camera.0"); + clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0"); + clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0"); clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL); clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL); clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL); -- GitLab From b7ec70be01a87f2c85df3ae11046e74f9b67e323 Mon Sep 17 00:00:00 2001 From: Tushar Dave Date: Tue, 31 Jul 2012 02:02:43 +0000 Subject: [PATCH 5187/5711] e1000e: NIC goes up and immediately goes down Found that commit d478eb44 was a bad commit. If the link partner is transmitting codeword (even if NULL codeword), then the RXCW.C bit will be set so check for RXCW.CW is unnecessary. Ref: RH BZ 840642 Reported-by: Fabio Futigami Signed-off-by: Tushar Dave CC: Marcelo Ricardo Leitner CC: stable [2.6.38+] Tested-by: Aaron Brown Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/e1000e/82571.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 0b3bade957fd..2a4ded2fd6e5 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1601,10 +1601,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. - * If the partner code word is null, stop forcing - * and restart auto negotiation. */ - if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { + if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); -- GitLab From eca90f550494171f54f8a700caee65ec16455a5b Mon Sep 17 00:00:00 2001 From: Tushar Dave Date: Wed, 1 Aug 2012 02:11:15 +0000 Subject: [PATCH 5188/5711] e1000e: 82571 Tx Data Corruption during Tx hang recovery A bus trace shows that while executing e1000e_down, TCTL is cleared except for the PSP bit. This occurs while in the middle of fetching a TSO packet since the Tx packet buffer is full at that point. Before the device is reset, the e1000_watchdog_task starts to run from the middle (it was apparently pre-empted earlier, although that is not in the trace) and sets TCTL.EN. At that point, 82571 transmits the corrupted packet, apparently because TCTL.MULR was cleared in the middle of fetching a packet, which is forbidden. Driver should just clear TCTL.EN in e1000_reset_hw_82571 instead of clearing the entire register, so as not to change any settings in the middle of fetching a packet. Signed-off-by: Tushar Dave Tested-by: Aaron Brown Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/e1000e/82571.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 2a4ded2fd6e5..080c89093feb 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -999,7 +999,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) **/ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) { - u32 ctrl, ctrl_ext, eecd; + u32 ctrl, ctrl_ext, eecd, tctl; s32 ret_val; /* @@ -1014,7 +1014,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); + tctl = er32(TCTL); + tctl &= ~E1000_TCTL_EN; + ew32(TCTL, tctl); e1e_flush(); usleep_range(10000, 20000); -- GitLab From 119b0e0351bcdb7833f368781e6241ff283b49e5 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 7 Aug 2012 00:45:57 -0700 Subject: [PATCH 5189/5711] igb: add delay to allow igb loopback test to succeed on 8086:10c9 Some 8086:10c9 NICs have a problem completing the ethtool loopback test. The result looks like this: ethtool -t eth1 The test result is FAIL The test extra info: Register test (offline) 0 Eeprom test (offline) 0 Interrupt test (offline) 0 Loopback test (offline) 13 Link test (on/offline) 0 A bisect clearly points to commit a95a07445ee97a2fef65befafbadcc30ca1bd145. However that seems to only trigger the bug. While adding some printk the problem disappeared, so this might be a timing issue. After some trial and error I discovered that adding a small delay just before igb_write_phy_reg() in igb_integrated_phy_loopback() allows the loopback test to succeed. I was unable to figure out the root cause so far but I expect it to be somewhere in the following executing path igb_integrated_phy_loopback ->igb_write_phy_reg_igp ->igb_write_phy_reg_mdic ->igb_acquire_phy_82575 ->igb_acquire_swfw_sync_82575 The problem could only be observed on 8086:10c9 NICs so far and not all of them show the behaviour. I did not restrict the workaround to this type of NIC as it should do no harm to other igb NICs. With the patch below the loopback test succeeded 500 times in a row using a NIC that would otherwise fail. Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 90550f5e3dd9..70591117051b 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -1498,6 +1498,9 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) break; } + /* add small delay to avoid loopback test failure */ + msleep(50); + /* force 1000, set loopback */ igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); -- GitLab From 035534ed3377d9def2c17717899fd64a111a785b Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 6 Aug 2012 18:02:29 +0200 Subject: [PATCH 5190/5711] canfd: remove redundant CAN FD flag The first idea of the CAN FD implementation started with a new struct canfd_frame to be used for both CAN FD frames and legacy CAN frames. The now mainlined implementation supports both CAN frame types simultaneously and distinguishes them only by their required sizes: CAN_MTU and CANFD_MTU. Only the struct canfd_frame contains a flags element which is needed for the additional CAN FD information. As CAN FD implicitly means that the 'Extened Data Length' mode is enabled the formerly defined CANFD_EDL bit became redundant and also confusing as an unset bit would be an error and would always need to be tested. This patch removes the obsolete CANFD_EDL bit and clarifies the documentation for the use of struct canfd_frame and the CAN FD relevant flags. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/linux/can.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/include/linux/can.h b/include/linux/can.h index 018055efc034..e52958d7c2d1 100644 --- a/include/linux/can.h +++ b/include/linux/can.h @@ -74,20 +74,21 @@ struct can_frame { /* * defined bits for canfd_frame.flags * - * As the default for CAN FD should be to support the high data rate in the - * payload section of the frame (HDR) and to support up to 64 byte in the - * data section (EDL) the bits are only set in the non-default case. - * Btw. as long as there's no real implementation for CAN FD network driver - * these bits are only preliminary. + * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to + * be set in the CAN frame bitstream on the wire. The EDL bit switch turns + * the CAN controllers bitstream processor into the CAN FD mode which creates + * two new options within the CAN FD frame specification: * - * RX: NOHDR/NOEDL - info about received CAN FD frame - * ESI - bit from originating CAN controller - * TX: NOHDR/NOEDL - control per-frame settings if supported by CAN controller - * ESI - bit is set by local CAN controller + * Bit Rate Switch - to indicate a second bitrate is/was used for the payload + * Error State Indicator - represents the error state of the transmitting node + * + * As the CANFD_ESI bit is internally generated by the transmitting CAN + * controller only the CANFD_BRS bit is relevant for real CAN controllers when + * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make + * sense for virtual CAN interfaces to test applications with echoed frames. */ -#define CANFD_NOHDR 0x01 /* frame without high data rate */ -#define CANFD_NOEDL 0x02 /* frame without extended data length */ -#define CANFD_ESI 0x04 /* error state indicator */ +#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ /** * struct canfd_frame - CAN flexible data rate frame structure -- GitLab From 3b6c9440873d97728998854feb3bc5ffb827dd99 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Sun, 5 Aug 2012 16:45:32 +0200 Subject: [PATCH 5191/5711] ARM: kirkwood: fix typo in Makefile.boot Just a small typo fix to make lsxl dtbs compile Signed-off-by: Sebastian Hesselbarth Cc: Jason Cooper Cc: Andrew Lunn Cc: Russell King Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Arnd Bergmann --- arch/arm/mach-kirkwood/Makefile.boot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot index 2a576abf409b..a5717558ee89 100644 --- a/arch/arm/mach-kirkwood/Makefile.boot +++ b/arch/arm/mach-kirkwood/Makefile.boot @@ -9,5 +9,5 @@ dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-qnap-ts219.dtb dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb -dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb -dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb +dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb +dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb -- GitLab From da612d880fbc598ac0efcef579355fb90d4bca4e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 6 Aug 2012 18:45:01 -0300 Subject: [PATCH 5192/5711] drm/i915: add more Haswell PCI IDs Also properly indent the HB IDs. Reviewed-by: Rodrigo Vivi Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-agp.h | 39 ++++++++++++++++++--- drivers/char/agp/intel-gtt.c | 60 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.c | 31 ++++++++++++++++- 3 files changed, 123 insertions(+), 7 deletions(-) diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 57226424690c..6f007b6c240d 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -239,16 +239,45 @@ #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB 0x0F00 /* VLV1 */ #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG 0x0F30 -#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG 0x0402 #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG 0x0412 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG 0x0422 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG 0x0406 #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG 0x0416 -#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG 0x0426 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG 0x040a #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG 0x041a -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ -#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG 0x042a +#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG 0x0C02 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG 0x0C12 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG 0x0C22 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG 0x0C06 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG 0x0C16 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG 0x0C26 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG 0x0C0A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG 0x0C1A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG 0x0C2A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG 0x0A02 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG 0x0A12 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG 0x0A22 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG 0x0A06 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG 0x0A16 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG 0x0A26 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG 0x0A0A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG 0x0A1A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG 0x0A2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG 0x0D12 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG 0x0D22 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG 0x0D32 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG 0x0D16 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG 0x0D26 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG 0x0D36 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG 0x0D1A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG 0x0D2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG 0x0D3A #endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 9ed92ef5829b..08fc5cbb13cd 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1502,15 +1502,73 @@ static const struct intel_gtt_driver_description { "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, "Haswell", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV, + { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, "Haswell", &sandybridge_gtt_driver }, { 0, NULL, NULL } }; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ed22612bc847..a24ffbe97c01 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -346,11 +346,40 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */ INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */ INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ + INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */ INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */ INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */ + INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */ INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ - INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ + INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */ + INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */ + INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */ + INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */ + INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */ + INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */ + INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */ + INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */ + INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */ + INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */ + INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */ + INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */ + INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */ + INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */ + INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */ + INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */ + INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ + INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ + INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ + INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ + INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ + INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ + INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ + INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ + INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ + INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ + INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ + INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */ INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), -- GitLab From 606b64ea666dc45675c5ecce6f73022355172d78 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 31 Jul 2012 14:57:38 +0200 Subject: [PATCH 5193/5711] pinctrl/nomadik: fix hsi function group list Tidy up a small typo in the HSI function group list. Signed-off-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik-db8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c index 6f99769c6733..5f3e9d0221e1 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -766,7 +766,7 @@ DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1", DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1"); DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1"); DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1dir_a_1"); -DB8500_FUNC_GROUPS(hsi, "hsir1_a_1", "hsit1_a_1", "hsit_a_2"); +DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1"); DB8500_FUNC_GROUPS(usb, "usb_a_1"); DB8500_FUNC_GROUPS(trig, "trig_b_1"); -- GitLab From e9fc83cb2e5877801a255a37ddbc5be996ea8046 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 7 Aug 2012 14:03:29 +0200 Subject: [PATCH 5194/5711] ALSA: hda - remove quirk for Dell Vostro 1015 This computer is confirmed working with model=auto on kernel 3.2. Also, parsing fails with hda-emu with the current model. Cc: stable@kernel.org (3.2+) Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 14361184ae1e..6f538eb3871e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2972,7 +2972,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), -- GitLab From bb10b09a8ea10228ef3e56365fae40f1e24e5589 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 7 Aug 2012 14:03:30 +0200 Subject: [PATCH 5195/5711] ALSA: hda - remove redundant auto quirks for conexant 506x Now that the auto model is the default, these quirks are redundant and can be removed. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6f538eb3871e..5e22a8f43d2e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2967,7 +2967,6 @@ static const char * const cxt5066_models[CXT5066_MODELS] = { }; static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO), SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), @@ -2987,14 +2986,10 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO), - SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO), SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), - SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; -- GitLab From f4b49dee1ac0ae0660ef697fdab789dc92f59c6f Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sun, 29 Jul 2012 13:56:38 +0545 Subject: [PATCH 5196/5711] pinctrl-sirf: remove devm_kfree at error path the pointers that are allocated with devm_kzalloc will be automatically freed, at unload time. Signed-off-by: Devendra Naga Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sirf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 2aae8a8978e9..7fca6ce5952b 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1217,7 +1217,6 @@ out_no_rsc_remap: iounmap(spmx->gpio_virtbase); out_no_gpio_remap: platform_set_drvdata(pdev, NULL); - devm_kfree(&pdev->dev, spmx); return ret; } -- GitLab From 8e406fe4aebee50b18176947a68aab6f519843de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 30 Jul 2012 18:38:34 +0200 Subject: [PATCH 5197/5711] MAINTAINERS: fix a few pinctrl related entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- MAINTAINERS | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 94b823f71e94..63ce3a38b332 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5329,14 +5329,15 @@ PIN CONTROL SUBSYSTEM M: Linus Walleij S: Maintained F: drivers/pinctrl/ +F: include/linux/pinctrl/ PIN CONTROLLER - ST SPEAR -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear S: Maintained -F: driver/pinctrl/spear/ +F: drivers/pinctrl/spear/ PKTCDVD DRIVER M: Peter Osterlund -- GitLab From 75c353ecacf54dbcca5e2e4388088893aac0fc34 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Aug 2012 18:50:47 +0200 Subject: [PATCH 5198/5711] drivers/pinctrl/pinctrl-nomadik.c: drop devm_kfree of devm_kzalloc'd data devm_kfree should not have to be explicitly used. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,d; @@ x = devm_kzalloc(...) ... ?-devm_kfree(d,x); // Signed-off-by: Julia Lawall Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 53b0d49a7a1c..ec6ac501b23a 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1731,7 +1731,6 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < npct->soc->gpio_num_ranges; i++) { if (!nmk_gpio_chips[i]) { dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); - devm_kfree(&pdev->dev, npct); return -EPROBE_DEFER; } npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip; -- GitLab From d0db84e713eaaccea2a435e1625fb3150b335f4a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Aug 2012 15:37:47 +0300 Subject: [PATCH 5199/5711] ASoC: omap-mcbsp: Fix 6pin mux configuration The check for the mux_signal callback was wrong which prevents us to configure the 6pin port's FSR/CLKR signal mux. Reported-by: CF Adad Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown Cc: stable@vger.kernel.org (3.4+) --- sound/soc/omap/mcbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 34835e8a9160..d33c48baaf71 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -745,7 +745,7 @@ int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) { const char *signal, *src; - if (mcbsp->pdata->mux_signal) + if (!mcbsp->pdata->mux_signal) return -EINVAL; switch (mux) { -- GitLab From 709aea6b05f8f6c852c293fb5d47a6461373b4dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Aug 2012 18:09:23 +0200 Subject: [PATCH 5200/5711] ALSA: hda - Fix ugly debug prints with CONFIG_SND_VERBOSE_PRINTK=y When CONFIG_SND_VERBOSE_PRINTK=y is set, the debug print in hda_auto_parser.c looks really ugly like: ALSA sound/pci/hda/hda_auto_parser.c:331 mono: mono_out=0x0 ALSA sound/pci/hda/hda_auto_parser.c:334 dig-out=0x12/0x0 ALSA sound/pci/hda/hda_auto_parser.c:335 inputs: ALSA sound/pci/hda/hda_auto_parser.c:339 Mic=0x11ALSA sound/pci/hda/hda_auto_parser.c:339 Line=0x10 ALSA sound/pci/hda/hda_auto_parser.c:341 ALSA sound/pci/hda/hda_auto_parser.c:343 dig-in=0x13 Better to put one item at each line. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_auto_parser.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 647218d69f68..4f7d2dfcef7b 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -332,13 +332,12 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, if (cfg->dig_outs) snd_printd(" dig-out=0x%x/0x%x\n", cfg->dig_out_pins[0], cfg->dig_out_pins[1]); - snd_printd(" inputs:"); + snd_printd(" inputs:\n"); for (i = 0; i < cfg->num_inputs; i++) { - snd_printd(" %s=0x%x", + snd_printd(" %s=0x%x\n", hda_get_autocfg_input_label(codec, cfg, i), cfg->inputs[i].pin); } - snd_printd("\n"); if (cfg->dig_in_pin) snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); -- GitLab From a5f8ae2154eeb7ed18c6e3dbf6ac095ea4c3d5cf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jul 2012 12:30:11 +0800 Subject: [PATCH 5201/5711] regulator: palmas: Fix calculating selector in palmas_map_voltage_ldo This patch fixes below issues when choosing selector: 1. Current code returns negative selector if min_uV < 900000 which is wrong. For example, it is possible to satisfy the request with selector = 1 if the requested min_uV is 850000. 2. Current code may select a voltage lower than requested min_uV. For example, if the requested min_uV is 945000, current code chooses selector = 1 which is lower than requested min_uV. DIV_ROUND_UP to avoid this case. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 17d19fbbc490..0fcf3550f65d 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -486,9 +486,12 @@ static int palmas_map_voltage_ldo(struct regulator_dev *rdev, { int ret, voltage; - ret = ((min_uV - 900000) / 50000) + 1; - if (ret < 0) - return ret; + if (min_uV == 0) + return 0; + + if (min_uV < 900000) + min_uV = 900000; + ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1; /* Map back into a voltage to verify we're still in bounds */ voltage = palmas_list_voltage_ldo(rdev, ret); -- GitLab From 12565b166dab7966c2991c1561f3c22e9dad5535 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jul 2012 12:31:03 +0800 Subject: [PATCH 5202/5711] regulator: palmas: Fix regmap offsets for PALMAS_REG_SMPS10 vsel_reg Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 0fcf3550f65d..9e3e7f3c4086 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -679,7 +679,9 @@ static __devinit int palmas_probe(struct platform_device *pdev) case PALMAS_REG_SMPS10: pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES; pmic->desc[id].ops = &palmas_ops_smps10; - pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; + pmic->desc[id].vsel_reg = + PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, + PALMAS_SMPS10_CTRL); pmic->desc[id].vsel_mask = SMPS10_VSEL; pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, -- GitLab From 2735daeb161d3eb1ba041158c21ac2a0e42da6a2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jul 2012 12:31:59 +0800 Subject: [PATCH 5203/5711] regulator: palmas: Call palmas_ldo_[read|write] in palmas_ldo_init Current code uses wrong calls palmas_smps_[read|write] in palmas_ldo_init(), should be palmas_ldo_[read|write] instead. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 9e3e7f3c4086..de68347cbc69 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -589,7 +589,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, addr = palmas_regs_info[id].ctrl_addr; - ret = palmas_smps_read(palmas, addr, ®); + ret = palmas_ldo_read(palmas, addr, ®); if (ret) return ret; @@ -599,7 +599,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, if (reg_init->mode_sleep) reg |= PALMAS_LDO1_CTRL_MODE_SLEEP; - ret = palmas_smps_write(palmas, addr, reg); + ret = palmas_ldo_write(palmas, addr, reg); if (ret) return ret; -- GitLab From 1c9d2d71a3cb0fcbfe91307b3c18d22f7d93f0cd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jul 2012 12:33:20 +0800 Subject: [PATCH 5204/5711] regulator: palmas: Fix palmas_probe error handling Fix below error handling cases: 1. If reading PALMAS_SMPS_CTRL fails, simply returns ret rather than goto err_unregister_regulator because we have not call regulator_register(). 2. If palmas_ldo_init() fails, we need to call regulator_unregister() for the regulator we just successfully registered in this for loop iteration. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index de68347cbc69..46c7e88f8381 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -633,7 +633,7 @@ static __devinit int palmas_probe(struct platform_device *pdev) ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, ®); if (ret) - goto err_unregister_regulator; + return ret; if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) pmic->smps123 = 1; @@ -783,8 +783,10 @@ static __devinit int palmas_probe(struct platform_device *pdev) reg_init = pdata->reg_init[id]; if (reg_init) { ret = palmas_ldo_init(palmas, id, reg_init); - if (ret) + if (ret) { + regulator_unregister(pmic->rdev[id]); goto err_unregister_regulator; + } } } } -- GitLab From 7f852e0584f67654060f7814149744a1b7250480 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 24 Jul 2012 13:48:00 +0530 Subject: [PATCH 5205/5711] regulator: tps6586x: correct vin pin for sm0/sm1/sm2 As per datasheet, the vin pin for the regulator is named as vin_sm0, vin_sm1, vin_sm2 for sm0, sm1 and sm2 respectively. Correcting the names in driver and documentation to match with datasheet. Signed-off-by: Laxman Dewangan Reported-by: Stephen Warren Acked-by: Stephen Warren Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/tps6586x.txt | 12 ++++++------ drivers/regulator/tps6586x-regulator.c | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index d156e1b5db12..da80c2ae0915 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -9,9 +9,9 @@ Required properties: - regulators: list of regulators provided by this controller, must have property "regulator-compatible" to match their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc -- sm0-supply: The input supply for the SM0. -- sm1-supply: The input supply for the SM1. -- sm2-supply: The input supply for the SM2. +- vin-sm0-supply: The input supply for the SM0. +- vin-sm1-supply: The input supply for the SM1. +- vin-sm2-supply: The input supply for the SM2. - vinldo01-supply: The input supply for the LDO1 and LDO2 - vinldo23-supply: The input supply for the LDO2 and LDO3 - vinldo4-supply: The input supply for the LDO4 @@ -30,9 +30,9 @@ Example: #gpio-cells = <2>; gpio-controller; - sm0-supply = <&some_reg>; - sm1-supply = <&some_reg>; - sm2-supply = <&some_reg>; + vin-sm0-supply = <&some_reg>; + vin-sm1-supply = <&some_reg>; + vin-sm2-supply = <&some_reg>; vinldo01-supply = <...>; vinldo23-supply = <...>; vinldo4-supply = <...>; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index e6da90ab5153..19241fc30050 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -240,14 +240,16 @@ static struct tps6586x_regulator tps6586x_regulator[] = { TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), - TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), + TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), - TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), - TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), + TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, + ENB, 1, VCC1, 2), + TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, + ENB, 0, VCC1, 0), }; /* -- GitLab From 3e2a928472daa839e7be0d71c1d8320334ea76e1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Jul 2012 00:10:42 +0800 Subject: [PATCH 5206/5711] regulator: anatop: Fix wrong mask used in anatop_get_voltage_sel The mask used in anatop_get_voltage_sel does not match the mask used in anatop_set_voltage_sel. We need to do left shift anatop_reg->vol_bit_shift bits for the correct mask. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/anatop-regulator.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index e9c2085f9dfb..ce0fe72a428e 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -64,14 +64,15 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector) static int anatop_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val; + u32 val, mask; if (!anatop_reg->control_reg) return -ENOTSUPP; val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg); - val = (val & ((1 << anatop_reg->vol_bit_width) - 1)) >> + mask = ((1 << anatop_reg->vol_bit_width) - 1) << anatop_reg->vol_bit_shift; + val = (val & mask) >> anatop_reg->vol_bit_shift; return val - anatop_reg->min_bit_val; } -- GitLab From cfa9cfbc083c7fc882286dcfba59c7e5a1a15545 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Aug 2012 17:11:40 +0200 Subject: [PATCH 5207/5711] regulator: ab3100: add missing voltage table The conversion to voltage tables in commit a3beb74261f26142019847128b2441b0301797ac "regulator: ab3100: Use regulator_list_voltage_table()" missed to add the voltage table to the buck. Fix this and it works like a charm. Signed-off-by: Linus Walleij Acked-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 182b553059c9..c151fd5d8c97 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -486,6 +486,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_BUCK, .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), + .volt_table = ldo_e_buck_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_time = 1000, -- GitLab From 817fea2df3c24b22f6123dc0106eb063b7132883 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 7 Aug 2012 11:48:33 -0600 Subject: [PATCH 5208/5711] vfio: Include vfio.h in installed headers Signed-off-by: Alex Williamson --- include/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/Kbuild b/include/linux/Kbuild index d9a754474878..fa217607c582 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -391,6 +391,7 @@ header-y += v4l2-dv-timings.h header-y += v4l2-mediabus.h header-y += v4l2-subdev.h header-y += veth.h +header-y += vfio.h header-y += vhost.h header-y += videodev2.h header-y += virtio_9p.h -- GitLab From 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 23 Jul 2012 16:06:08 -0700 Subject: [PATCH 5209/5711] xhci: Increase reset timeout for Renesas 720201 host. The NEC/Renesas 720201 xHCI host controller does not complete its reset within 250 milliseconds. In fact, it takes about 9 seconds to reset the host controller, and 1 second for the host to be ready for doorbell rings. Extend the reset and CNR polling timeout to 10 seconds each. This patch should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Sarah Sharp Reported-by: Edwin Klein Mentink Cc: stable@vger.kernel.org --- drivers/usb/host/xhci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7648b2d4b268..5c3a3f75e4d5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_writel(xhci, command, &xhci->op_regs->command); ret = handshake(xhci, &xhci->op_regs->command, - CMD_RESET, 0, 250 * 1000); + CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; @@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, + STS_CNR, 0, 10 * 1000 * 1000); for (i = 0; i < 2; ++i) { xhci->bus_state[i].port_c_suspend = 0; -- GitLab From 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 2 Jul 2012 13:36:23 -0700 Subject: [PATCH 5210/5711] xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk. Gary reports that with recent kernels, he notices more xHCI driver warnings: xhci_hcd 0000:03:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk? We think his Etron xHCI host controller may have the same buggy behavior as the Fresco Logic xHCI host. When a short transfer is received, the host will mark the transfer as successfully completed when it should be marking it with a short completion. Fix this by turning on the XHCI_TRUST_TX_LENGTH quirk when the Etron host is discovered. Note that Gary has revision 1, but if Etron fixes this bug in future revisions, the quirk will have no effect. This patch should be backported to kernels as old as 2.6.36, that contain a backported version of commit 1530bbc6272d9da1e39ef8e06190d42c13a02733 "xhci: Add new short TX quirk for Fresco Logic host." Signed-off-by: Sarah Sharp Reported-by: Gary E. Miller Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 18b231b0c5d3..92eaff6097c0 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_ASROCK_P67) { xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); + xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; -- GitLab From 8202ce2e2921941098aa72894ac5d7b486a9d273 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 25 Jul 2012 10:52:45 -0700 Subject: [PATCH 5211/5711] xhci: Rate-limit XHCI_TRUST_TX_LENGTH quirk warning. When we encounter an xHCI host that needs the XHCI_TRUST_TX_LENGTH quirk, the xHCI driver ends up spewing messages about the quirk into dmesg every time a short packet occurs. Change the xHCI driver to rate-limit such warnings. Signed-off-by: Sarah Sharp Reported-by: Matthew Hall Reported-by: Gary E. Miller --- drivers/usb/host/xhci-ring.c | 4 ++-- drivers/usb/host/xhci.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 8275645889da..0c93f5dcea6f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2073,8 +2073,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (xhci->quirks & XHCI_TRUST_TX_LENGTH) trb_comp_code = COMP_SHORT_TX; else - xhci_warn(xhci, "WARN Successful completion on short TX: " - "needs XHCI_TRUST_TX_LENGTH quirk?\n"); + xhci_warn_ratelimited(xhci, + "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); case COMP_SHORT_TX: break; case COMP_STOP: diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 55c0785810c9..96f49dbb50ac 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1537,6 +1537,8 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args) #define xhci_warn(xhci, fmt, args...) \ dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args) +#define xhci_warn_ratelimited(xhci, fmt, args...) \ + dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) /* TODO: copied from ehci.h - can be refactored? */ /* xHCI spec says all registers are little endian */ -- GitLab From 8258d3923c7d8f9a28c43612c3f91c7b9d61191b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 20 Jul 2012 10:31:43 -0700 Subject: [PATCH 5212/5711] staging: comedi: remove pci_is_enabled() tests As mentioned by Ian Abbott, the comedi pci drivers that try to locate an unused pci device with the pci_is_enabled() test might actually skip over a perfectly good unused device. This test is also not consistent with the other comedi pci drivers. Remove the test from all the comedi pci drivers. Reported-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1710.c | 3 --- drivers/staging/comedi/drivers/adv_pci1723.c | 2 -- drivers/staging/comedi/drivers/adv_pci_dio.c | 2 -- 3 files changed, 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 31986608eaf1..6b4d0d68e637 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1349,9 +1349,6 @@ static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev, } if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH) continue; - if (pci_is_enabled(pcidev)) - continue; - if (strcmp(this_board->name, DRV_NAME) == 0) { for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { if (pcidev->device == boardtypes[i].device_id) { diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index da5ee69d2c9d..dfde0f6328dd 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -301,8 +301,6 @@ static struct pci_dev *pci1723_find_pci_dev(struct comedi_device *dev, } if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH) continue; - if (pci_is_enabled(pcidev)) - continue; return pcidev; } dev_err(dev->class_dev, diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 97f06dc8e48d..2d4cb7f638b2 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1064,8 +1064,6 @@ static struct pci_dev *pci_dio_find_pci_dev(struct comedi_device *dev, slot != PCI_SLOT(pcidev->devfn)) continue; } - if (pci_is_enabled(pcidev)) - continue; for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { if (boardtypes[i].vendor_id != pcidev->vendor) continue; -- GitLab From 7e8401b23e7fd4f585b0fcb62d0895487d5f11d6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 20 Jul 2012 10:32:10 -0700 Subject: [PATCH 5213/5711] staging: comedi: daqboard2000: add back subsystem_device check As mentioned by Ian Abbott, this driver originally checked the pci_dev subsystem_device in order to make sure that the pci_dev was compatible with this driver. The cleanup of the "find pci device" code removed this check. Add it back. Reported-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index ef28385c1482..7236cbe87e2b 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -718,7 +718,8 @@ static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev, continue; } if (pcidev->vendor != PCI_VENDOR_ID_IOTECH || - pcidev->device != 0x0409) + pcidev->device != 0x0409 || + pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH) continue; for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { -- GitLab From 325a01f38d8e443b9a10a84606740cf570efddd1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 20 Jul 2012 10:32:29 -0700 Subject: [PATCH 5214/5711] staging: comedi: daqboard2000: ioremap'ed addresses are resource_size_t As mentioned by Ian Abbott, the pci address passed to ioremap should be a resource_size_t not an unsigned long. Use a local variable of that type to hold the pci_resource_start() that is passed to ioremp(). Set the dev->iobase to a dummy non-zero value so that the "detach" can use it as a flag to know that comedi_pci_disable() needs to be called. Reported-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 7236cbe87e2b..cad559a1a730 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -740,6 +740,7 @@ static int daqboard2000_attach(struct comedi_device *dev, { struct pci_dev *pcidev; struct comedi_subdevice *s; + resource_size_t pci_base; void *aux_data; unsigned int aux_len; int result; @@ -759,11 +760,12 @@ static int daqboard2000_attach(struct comedi_device *dev, "failed to enable PCI device and request regions\n"); return -EIO; } - dev->iobase = pci_resource_start(pcidev, 2); + dev->iobase = 1; /* the "detach" needs this */ - devpriv->plx = - ioremap(pci_resource_start(pcidev, 0), DAQBOARD2000_PLX_SIZE); - devpriv->daq = ioremap(dev->iobase, DAQBOARD2000_DAQ_SIZE); + pci_base = pci_resource_start(pcidev, 0); + devpriv->plx = ioremap(pci_base, DAQBOARD2000_PLX_SIZE); + pci_base = pci_resource_start(pcidev, 2); + devpriv->daq = ioremap(pci_base, DAQBOARD2000_DAQ_SIZE); if (!devpriv->plx || !devpriv->daq) return -ENOMEM; @@ -800,8 +802,6 @@ static int daqboard2000_attach(struct comedi_device *dev, printk("Interrupt after is: %x\n", interrupt); */ - dev->iobase = (unsigned long)devpriv->daq; - dev->board_name = this_board->name; s = dev->subdevices + 0; @@ -825,7 +825,7 @@ static int daqboard2000_attach(struct comedi_device *dev, s = dev->subdevices + 2; result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - (unsigned long)(dev->iobase + 0x40)); + (unsigned long)(devpriv->daq + 0x40)); out: return result; -- GitLab From 2724f01856fafbe9f76d8e74a564b576b6f02d72 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 20 Jul 2012 10:32:47 -0700 Subject: [PATCH 5215/5711] staging: comedi: dt3000: ioremap'ed addresses are resource_size_t As mentioned by Ian Abbott, the pci address passed to ioremap should be a resource_size_t not an unsigned long. Use a local variable of that type to hold the pci_resource_start() that is passed to ioremp(). Set the dev->iobase to a dummy non-zero value so that the "detach" can use it as a flag to know that comedi_pci_disable() needs to be called. Reported-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt3000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index a6fe6c9be87e..3476cda0fff0 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -804,6 +804,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pcidev; struct comedi_subdevice *s; + resource_size_t pci_base; int ret = 0; dev_dbg(dev->class_dev, "dt3000:\n"); @@ -820,9 +821,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = comedi_pci_enable(pcidev, "dt3000"); if (ret < 0) return ret; + dev->iobase = 1; /* the "detach" needs this */ - dev->iobase = pci_resource_start(pcidev, 0); - devpriv->io_addr = ioremap(dev->iobase, DT3000_SIZE); + pci_base = pci_resource_start(pcidev, 0); + devpriv->io_addr = ioremap(pci_base, DT3000_SIZE); if (!devpriv->io_addr) return -ENOMEM; -- GitLab From a26f4dd0ebd18f061366ca0231fdb74210e16140 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 20 Jul 2012 10:33:08 -0700 Subject: [PATCH 5216/5711] staging: comedi: rtd520: ioremap'ed addresses are resource_size_t As mentioned by Ian Abbott, the pci address passed to ioremap should be a resource_size_t not an unsigned long. Use a local variable of that type to hold the pci_resource_start() that is passed to ioremp(). Set the dev->iobase to a dummy non-zero value so that the "detach" can use it as a flag to know that comedi_pci_disable() needs to be called. Reported-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rtd520.c | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 112fdc3e9c69..5aa8be1e7b92 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1619,9 +1619,8 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct rtdPrivate *devpriv; struct pci_dev *pcidev; struct comedi_subdevice *s; + resource_size_t pci_base; int ret; - resource_size_t physLas1; /* data area */ - resource_size_t physLcfg; /* PLX9080 */ #ifdef USE_DMA int index; #endif @@ -1655,20 +1654,15 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "Failed to enable PCI device and request regions.\n"); return ret; } - - /* - * Initialize base addresses - */ - /* Get the physical address from PCI config */ - dev->iobase = pci_resource_start(pcidev, LAS0_PCIINDEX); - physLas1 = pci_resource_start(pcidev, LAS1_PCIINDEX); - physLcfg = pci_resource_start(pcidev, LCFG_PCIINDEX); - /* Now have the kernel map this into memory */ - /* ASSUME page aligned */ - devpriv->las0 = ioremap_nocache(dev->iobase, LAS0_PCISIZE); - devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); - devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); - + dev->iobase = 1; /* the "detach" needs this */ + + /* Initialize the base addresses */ + pci_base = pci_resource_start(pcidev, LAS0_PCIINDEX); + devpriv->las0 = ioremap_nocache(pci_base, LAS0_PCISIZE); + pci_base = pci_resource_start(pcidev, LAS1_PCIINDEX); + devpriv->las1 = ioremap_nocache(pci_base, LAS1_PCISIZE); + pci_base = pci_resource_start(pcidev, LCFG_PCIINDEX); + devpriv->lcfg = ioremap_nocache(pci_base, LCFG_PCISIZE); if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) return -ENOMEM; -- GitLab From 4df7309af6f7988da15fc9a0175fc60b997cc0d7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Aug 2012 20:40:34 +0800 Subject: [PATCH 5217/5711] leds: lp8788: Fix updating scale configuration bits We need to do left shift (cfg->num + LP8788_ISINK_SCALE_OFFSET) bits for updating scale configuration. Signed-off-by: Axel Lin Acked-by: Milo(Woogyom) Kim Tested-by: Milo(Woogyom) Kim Signed-off-by: Bryan Wu --- drivers/leds/leds-lp8788.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c index 53bd136f1ef0..0ade6ebfc914 100644 --- a/drivers/leds/leds-lp8788.c +++ b/drivers/leds/leds-lp8788.c @@ -63,7 +63,7 @@ static int lp8788_led_init_device(struct lp8788_led *led, /* scale configuration */ addr = LP8788_ISINK_CTRL; mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET); - val = cfg->scale << cfg->num; + val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET); ret = lp8788_update_bits(led->lp, addr, mask, val); if (ret) return ret; -- GitLab From 012e7eb1e501d0120e0383b81477f63091f5e365 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 8 Aug 2012 08:43:37 +0200 Subject: [PATCH 5218/5711] ALSA: hda - Fix double quirk for Quanta FL1 / Lenovo Ideapad The same ID is twice in the quirk table, so the second one is not used. Signed-off-by: David Henningsson Cc: [v3.2+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index daa5103eb936..4f81dd44c837 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6099,6 +6099,8 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_PCM_44K] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pcm_44k, + .chained = true, + .chain_id = ALC269_FIXUP_QUANTA_MUTE }, [ALC269_FIXUP_STEREO_DMIC] = { .type = ALC_FIXUP_FUNC, @@ -6210,8 +6212,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), + SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), #if 0 -- GitLab From 0d8957c8a90bbb5d34fab9a304459448a5131e06 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 7 Aug 2012 09:54:14 +0200 Subject: [PATCH 5219/5711] drm/i915: correctly order the ring init sequence We may only start to set up the new register values after having confirmed that the ring is truely off. Otherwise the hw might lose the newly written register values. This is caught later on in the init sequence, when we check whether the register writes have stuck. Cc: stable@vger.kernel.org Reviewed-by: Jani Nikula Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522 Tested-by: Yang Guang Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index bf0195a96d53..414af1e2973b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -289,8 +289,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_WRITE_HEAD(ring, 0); ring->write_tail(ring, 0); - /* Initialize the ring. */ - I915_WRITE_START(ring, obj->gtt_offset); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* G45 ring initialization fails to reset head to zero */ @@ -316,6 +314,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) } } + /* Initialize the ring. This must happen _after_ we've cleared the ring + * registers with the above sequence (the readback of the HEAD registers + * also enforces ordering), otherwise the hw might lose the new ring + * register values. */ + I915_WRITE_START(ring, obj->gtt_offset); I915_WRITE_CTL(ring, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); -- GitLab From 48a08bab3066a9452216f8c52e0d6f35566de04d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 8 Aug 2012 00:47:21 -0300 Subject: [PATCH 5220/5711] ASoC: mxs: Fix the name of the SoC family SND_SOC_MXS_SGTL5000 is used on MXS boards, so fix the SoC family name. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/mxs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index 99a997f19bb9..b6fa77678d97 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig @@ -10,7 +10,7 @@ menuconfig SND_MXS_SOC if SND_MXS_SOC config SND_SOC_MXS_SGTL5000 - tristate "SoC Audio support for i.MX boards with sgtl5000" + tristate "SoC Audio support for MXS boards with sgtl5000" depends on I2C select SND_SOC_SGTL5000 help -- GitLab From eb0c5686b3c6332892b3eb5d8bb9eb04f943cb25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Wed, 8 Aug 2012 00:50:19 +0200 Subject: [PATCH 5221/5711] regulator: gpio-regulator: Split setting of voltages and currents Originally gpio-regulator used the first item of its state list that matched the given voltage or current range. Commit 4dbd8f63f0 (regulator: gpio-regulator: Set the smallest voltage/current in the specified range) changed this, to make the selection independent of the ordering of the state list. But selecting the minimal value is only true for voltage regulators. For current regulators the maximum in the given range should be selected instead. Therefore split the previous common selection function into specific functions for voltage and current regulators. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 38 ++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 34b67bee9323..8b5944f2d7d1 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -57,16 +57,17 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) return -EINVAL; } -static int gpio_regulator_set_value(struct regulator_dev *dev, - int min, int max, unsigned *selector) +static int gpio_regulator_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, + unsigned *selector) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); int ptr, target = 0, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && - data->states[ptr].value >= min && - data->states[ptr].value <= max) { + data->states[ptr].value >= min_uV && + data->states[ptr].value <= max_uV) { target = data->states[ptr].gpios; best_val = data->states[ptr].value; if (selector) @@ -85,13 +86,6 @@ static int gpio_regulator_set_value(struct regulator_dev *dev, return 0; } -static int gpio_regulator_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned *selector) -{ - return gpio_regulator_set_value(dev, min_uV, max_uV, selector); -} - static int gpio_regulator_list_voltage(struct regulator_dev *dev, unsigned selector) { @@ -106,7 +100,27 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); + struct gpio_regulator_data *data = rdev_get_drvdata(dev); + int ptr, target = 0, state, best_val = 0; + + for (ptr = 0; ptr < data->nr_states; ptr++) + if (data->states[ptr].value > best_val && + data->states[ptr].value >= min_uA && + data->states[ptr].value <= max_uA) { + target = data->states[ptr].gpios; + best_val = data->states[ptr].value; + } + + if (best_val == 0) + return -EINVAL; + + for (ptr = 0; ptr < data->nr_gpios; ptr++) { + state = (target & (1 << ptr)) >> ptr; + gpio_set_value(data->gpios[ptr].gpio, state); + } + data->state = target; + + return 0; } static struct regulator_ops gpio_regulator_voltage_ops = { -- GitLab From 0865a75d4166bddc533fd50831829ceefb94f9b0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 7 Aug 2012 16:51:34 -0300 Subject: [PATCH 5222/5711] ASoC: imx-ssi: Remove mono support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playing a mono track results in incorrect playback rate, ie, the audio is played at a faster rate. Remove mono support in the driver by setting 'channes_min' to dual-channel and this allows mono tracks to be played correctly. Reported-by: Gaëtan Carlier Tested-by: Gaëtan Carlier Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 28dd76c7cb1c..81d7728cf67f 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -380,13 +380,14 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) static struct snd_soc_dai_driver imx_ssi_dai = { .probe = imx_ssi_dai_probe, .playback = { - .channels_min = 1, + /* The SSI does not support monaural audio. */ + .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, -- GitLab From d0503513817bc6175cededcbe146e06b0ea20f68 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 30 Jul 2012 10:04:39 +0200 Subject: [PATCH 5223/5711] s390/mm: remove MAX_PHYSADDR_BITS define It's unused, so remove it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sparsemem.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h index 0fb34027d3f6..a60d085ddb4d 100644 --- a/arch/s390/include/asm/sparsemem.h +++ b/arch/s390/include/asm/sparsemem.h @@ -4,13 +4,11 @@ #ifdef CONFIG_64BIT #define SECTION_SIZE_BITS 28 -#define MAX_PHYSADDR_BITS 46 #define MAX_PHYSMEM_BITS 46 #else #define SECTION_SIZE_BITS 25 -#define MAX_PHYSADDR_BITS 31 #define MAX_PHYSMEM_BITS 31 #endif /* CONFIG_64BIT */ -- GitLab From e206d3da58803de5cd38dc728f6da5221ec18ab0 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Tue, 31 Jul 2012 11:01:30 +0200 Subject: [PATCH 5224/5711] s390/sclp_sdias: Add missing break and "fall through" If the last block of the HSA is read, EVSTATE_ALL_STORED is returned by SCLP. Because of a missing break in the switch statement two trace entries are written in this case: "all stored" and "part stored". This patch adds the missing break and also adds a "fall through" comment to improve the readability. Signed-off-by: Michael Holzheu Reported-by: David A Gilbert Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_sdias.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c index 6a6f76bf6e3d..b1032931a1c4 100644 --- a/drivers/s390/char/sclp_sdias.c +++ b/drivers/s390/char/sclp_sdias.c @@ -242,11 +242,13 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) switch (sdias_evbuf.event_status) { case EVSTATE_ALL_STORED: TRACE("all stored\n"); + break; case EVSTATE_PART_STORED: TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); break; case EVSTATE_NO_DATA: TRACE("no data\n"); + /* fall through */ default: pr_err("Error from SCLP while copying hsa. " "Event status = %x\n", -- GitLab From c63cb468f373f479ff52b4a1b75f8ecdeaaf4f16 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 31 Jul 2012 15:37:13 +0200 Subject: [PATCH 5225/5711] s390/seccomp: add support for system call filtering using BPF Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/include/asm/syscall.h | 10 ++++++++++ arch/s390/kernel/ptrace.c | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 76de6b68487c..107610e01a29 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -124,6 +124,7 @@ config S390 select GENERIC_TIME_VSYSCALL select GENERIC_CLOCKEVENTS select KTIME_SCALAR if 32BIT + select HAVE_ARCH_SECCOMP_FILTER config SCHED_OMIT_FRAME_POINTER def_bool y diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index fb214dd9b7e0..fe7b99759e12 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -12,6 +12,7 @@ #ifndef _ASM_SYSCALL_H #define _ASM_SYSCALL_H 1 +#include #include #include #include @@ -87,4 +88,13 @@ static inline void syscall_set_arguments(struct task_struct *task, regs->orig_gpr2 = args[0]; } +static inline int syscall_get_arch(struct task_struct *task, + struct pt_regs *regs) +{ +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(task, TIF_31BIT)) + return AUDIT_ARCH_S390; +#endif + return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; +} #endif /* _ASM_SYSCALL_H */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f4eb37680b91..e4be113fbac6 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -719,7 +719,11 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) long ret = 0; /* Do the secure computing check first. */ - secure_computing_strict(regs->gprs[2]); + if (secure_computing(regs->gprs[2])) { + /* seccomp failures shouldn't expose any additional code. */ + ret = -1; + goto out; + } /* * The sysc_tracesys code in entry.S stored the system @@ -745,6 +749,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) regs->gprs[2], regs->orig_gpr2, regs->gprs[3], regs->gprs[4], regs->gprs[5]); +out: return ret ?: regs->gprs[2]; } -- GitLab From 5ab37e1b226b7b40a44eea7d8d1fe19e67ff65a9 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 2 Aug 2012 09:11:23 +0200 Subject: [PATCH 5226/5711] s390: do not clobber personality flags in sys_32_personality() There are multiple errors in how sys_32_personality() handles personality flags stored in top three bytes. - directly comparing current->personality against PER_LINUX32 doesn't work in cases when any of the personality flags stored in the top three bytes are used. - directly forcefully setting personality to PER_LINUX32 or PER_LINUX discards any flags stored in the top three bytes Fix the first one by properly using personality() macro to compare only PER_MASK bytes. Fix the second one by setting only the bits that should be set, instead of overwriting the whole value. Signed-off-by: Jiri Kosina Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/sys_s390.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index b4a29eee41b8..d0964d22adb5 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -81,11 +81,12 @@ SYSCALL_DEFINE1(s390_personality, unsigned int, personality) { unsigned int ret; - if (current->personality == PER_LINUX32 && personality == PER_LINUX) - personality = PER_LINUX32; + if (personality(current->personality) == PER_LINUX32 && + personality(personality) == PER_LINUX) + personality |= PER_LINUX32; ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; + if (personality(ret) == PER_LINUX32) + ret &= ~PER_LINUX32; return ret; } -- GitLab From 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 7 Aug 2012 09:48:13 +0200 Subject: [PATCH 5227/5711] s390/compat: fix compat wrappers for process_vm system calls The compat wrappers incorrectly called the non compat versions of the system process_vm system calls. Cc: stable@vger.kernel.org Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_wrapper.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index e835d6d5b7fd..2d82cfcbce5b 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1635,7 +1635,7 @@ ENTRY(compat_sys_process_vm_readv_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_readv + jg compat_sys_process_vm_readv ENTRY(compat_sys_process_vm_writev_wrapper) lgfr %r2,%r2 # compat_pid_t @@ -1645,4 +1645,4 @@ ENTRY(compat_sys_process_vm_writev_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_writev + jg compat_sys_process_vm_writev -- GitLab From e85871218513c54f7dfdb6009043cb638f2fecbe Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 8 Aug 2012 09:32:20 +0200 Subject: [PATCH 5228/5711] s390/compat: fix mmap compat system calls The native 31 bit and the compat behaviour for the mmap system calls differ: In native 31 bit mode the passed in address for the mmap system call will be unmodified passed to sys_mmap_pgoff(). In compat mode however the passed in address will be modified with compat_ptr() which masks out the most significant bit. The result is that in native 31 bit mode each mmap request (with MAP_FIXED) will fail where the most significat bit is set, while in compat mode it may succeed. This odd behaviour was introduced with d3815898 "[S390] mmap: add missing compat_ptr conversion to both mmap compat syscalls". To restore a consistent behaviour accross native and compat mode this patch functionally reverts the above mentioned commit. Cc: stable@vger.kernel.org Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_linux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index d1225089a4bb..f606d935f495 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -620,7 +620,6 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) return -EFAULT; if (a.offset & ~PAGE_MASK) return -EINVAL; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); } @@ -631,7 +630,6 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); } -- GitLab From ed36081350d2ca4f692f04c6a2d24d1e3a339da1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Aug 2012 17:12:52 +0200 Subject: [PATCH 5229/5711] ALSA: hda - Add codec->pcm_format_first flag Introduced a new flag to set up the PCM stream format at first before the stream_id and channel tag. Some codecs (e.g. CA0132) seem preferring this over stream_id -> format order. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 69 +++++++++++++++++++++++++-------------- sound/pci/hda/hda_codec.h | 1 + 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 88a9c20eb7a2..598b9e2d85e6 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1386,6 +1386,44 @@ int snd_hda_codec_configure(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_codec_configure); +/* update the stream-id if changed */ +static void update_pcm_stream_id(struct hda_codec *codec, + struct hda_cvt_setup *p, hda_nid_t nid, + u32 stream_tag, int channel_id) +{ + unsigned int oldval, newval; + + if (p->stream_tag != stream_tag || p->channel_id != channel_id) { + oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); + newval = (stream_tag << 4) | channel_id; + if (oldval != newval) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + newval); + p->stream_tag = stream_tag; + p->channel_id = channel_id; + } +} + +/* update the format-id if changed */ +static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p, + hda_nid_t nid, int format) +{ + unsigned int oldval; + + if (p->format_id != format) { + oldval = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_STREAM_FORMAT, 0); + if (oldval != format) { + msleep(1); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, + format); + } + p->format_id = format; + } +} + /** * snd_hda_codec_setup_stream - set up the codec for streaming * @codec: the CODEC to set up @@ -1400,7 +1438,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, { struct hda_codec *c; struct hda_cvt_setup *p; - unsigned int oldval, newval; int type; int i; @@ -1413,29 +1450,13 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, p = get_hda_cvt_setup(codec, nid); if (!p) return; - /* update the stream-id if changed */ - if (p->stream_tag != stream_tag || p->channel_id != channel_id) { - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - p->stream_tag = stream_tag; - p->channel_id = channel_id; - } - /* update the format-id if changed */ - if (p->format_id != format) { - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, 0); - if (oldval != format) { - msleep(1); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - p->format_id = format; - } + + if (codec->pcm_format_first) + update_pcm_format(codec, p, nid, format); + update_pcm_stream_id(codec, p, nid, stream_tag, channel_id); + if (!codec->pcm_format_first) + update_pcm_format(codec, p, nid, format); + p->active = 1; p->dirty = 0; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c422d330ca54..7fbc1bcaf1a9 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -861,6 +861,7 @@ struct hda_codec { unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ unsigned int no_jack_detect:1; /* Machine has no jack-detection */ + unsigned int pcm_format_first:1; /* PCM format must be set first */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ int power_transition; /* power-state in transition */ -- GitLab From 55cf87fe0e9783e25f442be1e48b8319d86131ea Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Aug 2012 17:15:55 +0200 Subject: [PATCH 5230/5711] ALSA: hda - Fix superfluous "-in" suffix from CA0132 capture items Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index d0d3540e39e7..2685590925ff 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -988,12 +988,12 @@ static void ca0132_config(struct hda_codec *codec) /* Mic-in */ spec->input_pins[0] = 0x12; - spec->input_labels[0] = "Mic-In"; + spec->input_labels[0] = "Mic"; spec->adcs[0] = 0x07; /* Line-In */ spec->input_pins[1] = 0x11; - spec->input_labels[1] = "Line-In"; + spec->input_labels[1] = "Line"; spec->adcs[1] = 0x08; spec->num_inputs = 2; } -- GitLab From 27ebeb0b1b5bb26908e485a7e8bd2ec30366ffef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Aug 2012 17:20:18 +0200 Subject: [PATCH 5231/5711] ALSA: hda - Use the standard PCM ops for CA0132 Now with the workaround using codec->pcm_format_first flag, we can clean up the home-baked codes in patch_ca0132.c. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 142 +++++++---------------------------- 1 file changed, 29 insertions(+), 113 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 2685590925ff..31512a0f1d07 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -464,50 +464,17 @@ exit: } /* - * PCM stuffs + * PCM callbacks */ -static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, - int channel_id, int format) +static int ca0132_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) { - unsigned int oldval, newval; - - if (!nid) - return; - - snd_printdd("ca0132_setup_stream: " - "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", - nid, stream_tag, channel_id, format); - - /* update the format-id if changed */ - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, - 0); - if (oldval != format) { - msleep(20); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - } -} - -static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) -{ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); + struct ca0132_spec *spec = codec->spec; + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); } -/* - * PCM callbacks - */ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -515,10 +482,8 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); - - return 0; + return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, + stream_tag, format, substream); } static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, @@ -526,92 +491,45 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dacs[0]); - - return 0; + return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); } /* * Digital out */ -static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) +static int ca0132_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format); - - return 0; -} - -static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dig_out); - - return 0; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -/* - * Analog capture - */ -static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, +static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->adcs[substream->number], - stream_tag, 0, format); - - return 0; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, + stream_tag, format, substream); } -static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->adcs[substream->number]); - - return 0; -} - -/* - * Digital capture - */ -static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo, +static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format); - - return 0; + return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); } -static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) +static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dig_in); - - return 0; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); } /* @@ -621,6 +539,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = { .channels_min = 2, .channels_max = 2, .ops = { + .open = ca0132_playback_pcm_open, .prepare = ca0132_playback_pcm_prepare, .cleanup = ca0132_playback_pcm_cleanup }, @@ -630,10 +549,6 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, - .ops = { - .prepare = ca0132_capture_pcm_prepare, - .cleanup = ca0132_capture_pcm_cleanup - }, }; static struct hda_pcm_stream ca0132_pcm_digital_playback = { @@ -641,6 +556,8 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = { .channels_min = 2, .channels_max = 2, .ops = { + .open = ca0132_dig_playback_pcm_open, + .close = ca0132_dig_playback_pcm_close, .prepare = ca0132_dig_playback_pcm_prepare, .cleanup = ca0132_dig_playback_pcm_cleanup }, @@ -650,10 +567,6 @@ static struct hda_pcm_stream ca0132_pcm_digital_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, - .ops = { - .prepare = ca0132_dig_capture_pcm_prepare, - .cleanup = ca0132_dig_capture_pcm_cleanup - }, }; static int ca0132_build_pcms(struct hda_codec *codec) @@ -961,6 +874,9 @@ static void ca0132_config(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; + codec->pcm_format_first = 1; + codec->no_sticky_stream = 1; + /* line-outs */ cfg->line_outs = 1; cfg->line_out_pins[0] = 0x0b; /* front */ -- GitLab From 8e13fc1c5f694a6ae4032c7f94103c137136733f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Aug 2012 17:26:54 +0200 Subject: [PATCH 5232/5711] ALSA: hda - Add missing SPDIF I/O setup for CA0132 CA0132 driver had some codes to handle the S/PDIF I/O, but the actual setups of pins and converters were missing. Now the pins are added. Also, fixed a few points triggering invalid codec verbs and mixer elements since the digital I/O audio widgets on CA0132 have no amp. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 31512a0f1d07..9c0ec0a55bef 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -246,7 +246,7 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); } - if (dac) + if (dac && (get_wcaps(codec, dac) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); } @@ -261,7 +261,7 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)); } - if (adc) + if (adc && (get_wcaps(codec, adc) & AC_WCAP_IN_AMP)) snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)); } @@ -841,18 +841,16 @@ static int ca0132_build_controls(struct hda_codec *codec) spec->dig_out); if (err < 0) return err; - err = add_out_volume(codec, spec->dig_out, "IEC958"); + err = snd_hda_create_spdif_share_sw(codec, &spec->multiout); if (err < 0) return err; + /* spec->multiout.share_spdif = 1; */ } if (spec->dig_in) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); if (err < 0) return err; - err = add_in_volume(codec, spec->dig_in, "IEC958"); - if (err < 0) - return err; } return 0; } @@ -912,6 +910,16 @@ static void ca0132_config(struct hda_codec *codec) spec->input_labels[1] = "Line"; spec->adcs[1] = 0x08; spec->num_inputs = 2; + + /* SPDIF I/O */ + spec->dig_out = 0x05; + spec->multiout.dig_out_nid = spec->dig_out; + cfg->dig_out_pins[0] = 0x0c; + cfg->dig_outs = 1; + cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; + spec->dig_in = 0x09; + cfg->dig_in_pin = 0x0e; + cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; } static void ca0132_init_chip(struct hda_codec *codec) -- GitLab From 7523ceed42d84c1afaa1dc498bffed53c2aa444e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 5 Aug 2012 22:56:20 +0200 Subject: [PATCH 5233/5711] RTC: Avoid races between RTC alarm wakeup and suspend. If an RTC alarm fires just as suspend is happening, it is possible for suspend to complete and the alarm to be missed. To avoid the race, we must register the event with the PM core. As the event is made visible to userspace through a thread which is only scheduled by the interrupt, we need a pm_stay_awake/pm_relax pair preventing suspend from the interrupt until the thread completes its work. This makes the pm_wakeup_event() call in cmos_interrupt unnecessary as it provides suspend protection for all RTCs that use rtc_update_irq. Signed-off-by: NeilBrown Signed-off-by: Rafael J. Wysocki --- drivers/rtc/interface.c | 2 ++ drivers/rtc/rtc-cmos.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index eb415bd76494..9592b936b71b 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -582,6 +582,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) void rtc_update_irq(struct rtc_device *rtc, unsigned long num, unsigned long events) { + pm_stay_awake(rtc->dev.parent); schedule_work(&rtc->irqwork); } EXPORT_SYMBOL_GPL(rtc_update_irq); @@ -844,6 +845,7 @@ void rtc_timer_do_work(struct work_struct *work) mutex_lock(&rtc->ops_lock); again: + pm_relax(rtc->dev.parent); __rtc_read_time(rtc, &tm); now = rtc_tm_to_ktime(tm); while ((next = timerqueue_getnext(&rtc->timerqueue))) { diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 132333d75408..4267789ca995 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -568,7 +568,6 @@ static irqreturn_t cmos_interrupt(int irq, void *p) hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); - pm_wakeup_event(cmos_rtc.dev, 0); } spin_unlock(&rtc_lock); -- GitLab From d06a8a4fe7d81e8d1fa3d753be9b14c785b4b2e7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 5 Aug 2012 22:56:43 +0200 Subject: [PATCH 5234/5711] drivers/cpufreq/pcc-cpufreq.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/pcc-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index cdc02ac8f41a..503996a94a6a 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -454,6 +454,7 @@ static int __init pcc_cpufreq_probe(void) mem_resource->address_length); if (pcch_virt_addr == NULL) { pr_debug("probe: could not map shared mem region\n"); + ret = -ENOMEM; goto out_free; } pcch_hdr = pcch_virt_addr; -- GitLab From 77254950bb174d637cd88d1a74e137ecf3185a65 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Aug 2012 13:50:14 +0200 Subject: [PATCH 5235/5711] PM: Make dev_pm_get_subsys_data() always return 0 on success MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commits 1d5fcfec22 (PM / Domains: Add device domain data reference counter) and 62d4490294 (PM / Domains: Allow device callbacks to be added at any time) added checks for the return value of dev_pm_get_subsys_data(), but those checks were incorrect, because that function returned 1 on success in some cases. Since all of the existing users of dev_pm_get_subsys_data() don't use the positive value returned by it on success, change its definition so that it always returns 0 when successful. Reported-by: Heiko Stübner Reported-by: Tushar Behera Signed-off-by: Rafael J. Wysocki --- drivers/base/power/clock_ops.c | 3 +-- drivers/base/power/common.c | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 869d7ff2227f..eb78e9640c4a 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -169,8 +169,7 @@ void pm_clk_init(struct device *dev) */ int pm_clk_create(struct device *dev) { - int ret = dev_pm_get_subsys_data(dev); - return ret < 0 ? ret : 0; + return dev_pm_get_subsys_data(dev); } /** diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index a14085cc613f..39c32529b833 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -24,7 +24,6 @@ int dev_pm_get_subsys_data(struct device *dev) { struct pm_subsys_data *psd; - int ret = 0; psd = kzalloc(sizeof(*psd), GFP_KERNEL); if (!psd) @@ -40,7 +39,6 @@ int dev_pm_get_subsys_data(struct device *dev) dev->power.subsys_data = psd; pm_clk_init(dev); psd = NULL; - ret = 1; } spin_unlock_irq(&dev->power.lock); @@ -48,7 +46,7 @@ int dev_pm_get_subsys_data(struct device *dev) /* kfree() verifies that its argument is nonzero. */ kfree(psd); - return ret; + return 0; } EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data); -- GitLab From 300d3739e873d50d4c6e3656f89007a217fb1d29 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Aug 2012 13:50:22 +0200 Subject: [PATCH 5236/5711] Revert "NMI watchdog: fix for lockup detector breakage on resume" Revert commit 45226e9 (NMI watchdog: fix for lockup detector breakage on resume) which breaks resume from system suspend on my SH7372 Mackerel board (by causing a NULL pointer dereference to happen) and is generally wrong, because it abuses the CPU hotplug functionality in a shamelessly blatant way. The original issue should be addressed through appropriate syscore resume callback instead. Signed-off-by: Rafael J. Wysocki --- include/linux/sched.h | 8 -------- kernel/power/suspend.c | 3 --- kernel/watchdog.c | 21 ++------------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index c147e7024f11..b8c86648a2f9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -334,14 +334,6 @@ static inline void lockup_detector_init(void) } #endif -#if defined(CONFIG_LOCKUP_DETECTOR) && defined(CONFIG_SUSPEND) -void lockup_detector_bootcpu_resume(void); -#else -static inline void lockup_detector_bootcpu_resume(void) -{ -} -#endif - #ifdef CONFIG_DETECT_HUNG_TASK extern unsigned int sysctl_hung_task_panic; extern unsigned long sysctl_hung_task_check_count; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 1da39ea248fd..c8b7446b27df 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -178,9 +178,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); - /* Kick the lockup detector */ - lockup_detector_bootcpu_resume(); - Enable_cpus: enable_nonboot_cpus(); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 69add8a9da68..4b1dfba70f7c 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -575,7 +575,7 @@ out: /* * Create/destroy watchdog threads as CPUs come and go: */ -static int +static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -610,27 +610,10 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block cpu_nfb = { +static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; -#ifdef CONFIG_SUSPEND -/* - * On exit from suspend we force an offline->online transition on the boot CPU - * so that the PMU state that was lost while in suspended state gets set up - * properly for the boot CPU. This information is required for restarting the - * NMI watchdog. - */ -void lockup_detector_bootcpu_resume(void) -{ - void *cpu = (void *)(long)smp_processor_id(); - - cpu_callback(&cpu_nfb, CPU_DEAD_FROZEN, cpu); - cpu_callback(&cpu_nfb, CPU_UP_PREPARE_FROZEN, cpu); - cpu_callback(&cpu_nfb, CPU_ONLINE_FROZEN, cpu); -} -#endif - void __init lockup_detector_init(void) { void *cpu = (void *)(long)smp_processor_id(); -- GitLab From b2f0fa828ee7265028f1bca87928b0dc69663b53 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 06:20:49 +0000 Subject: [PATCH 5237/5711] mfd/asic3: fix asic3_mfd_probe return value In commit 4f304245b "mfd: Set asic3 DS1WM clock_rate", a possible path through asic3_mfd_probe was introduced that would lead to an unpredictable return value, if everything succeeds but there are pdata->leds is NULL. This was reported correctly by gcc. Without this patch, building magician_defconfig results in: drivers/mfd/asic3.c: In function 'asic3_mfd_probe': drivers/mfd/asic3.c:940:2: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Arnd Bergmann Cc: Paul Parsons Cc: Philipp Zabel Cc: Samuel Ortiz --- drivers/mfd/asic3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 383421bf5760..683e18a23329 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -925,6 +925,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, goto out; } + ret = 0; if (pdata->leds) { int i; -- GitLab From bb1a5805edf1d1e5da02b23dfca76ed99dfa18b1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 07:12:00 +0000 Subject: [PATCH 5238/5711] usb/ohci-omap: remove unused variable Commit c2e935a7d "USB: move transceiver from ehci_hcd and ohci_hcd to hcd and rename it as phy" removed the last use of the "ohci" variable in the usb_hcd_omap_remove function, but left the variable in place unused. Without this patch, building omap1_defconfig results in: In file included from drivers/usb/host/ohci-hcd.c:1013:0: drivers/usb/host/ohci-omap.c: In function 'usb_hcd_omap_remove': drivers/usb/host/ohci-omap.c:406:19: warning: unused variable 'ohci' [-Wunused-variable] Signed-off-by: Arnd Bergmann Acked-by: Alan Stern Acked-by: Greg Kroah-Hartman Cc: Richard Zhao --- drivers/usb/host/ohci-omap.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index e7d75d295988..f8b2d91851f7 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -403,8 +403,6 @@ err0: static inline void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - usb_remove_hcd(hcd); if (!IS_ERR_OR_NULL(hcd->phy)) { (void) otg_set_host(hcd->phy->otg, 0); -- GitLab From 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 26 Jul 2012 12:03:59 -0700 Subject: [PATCH 5239/5711] xhci: Fix bug after deq ptr set to link TRB. This patch fixes a particularly nasty bug that was revealed by the ring expansion patches. The bug has been present since the very beginning of the xHCI driver history, and could have caused general protection faults from bad memory accesses. The first thing to note is that a Set TR Dequeue Pointer command can move the dequeue pointer to a link TRB, if the canceled or stalled transfer TD ended just before a link TRB. The function to increment the dequeue pointer, inc_deq, was written before cancellation and stall support was added. It assumed that the dequeue pointer could never point to a link TRB. It would unconditionally increment the dequeue pointer at the start of the function, check if the pointer was now on a link TRB, and move it to the top of the next segment if so. This means that if a Set TR Dequeue Point command moved the dequeue pointer to a link TRB, a subsequent call to inc_deq() would move the pointer off the segment and into la-la-land. It would then read from that memory to determine if it was a link TRB. Other functions would often call inc_deq() until the dequeue pointer matched some other pointer, which means this function would quite happily read all of system memory before wrapping around to the right pointer value. Often, there would be another endpoint segment from a different ring allocated from the same DMA pool, which would be contiguous to the segment inc_deq just stepped off of. inc_deq would eventually find the link TRB in that segment, and blindly move the dequeue pointer back to the top of the correct ring segment. The only reason the original code worked at all is because there was only one ring segment. With the ring expansion patches, the dequeue pointer would eventually wrap into place, but the dequeue segment would be out-of-sync. On the second TD after the dequeue pointer was moved to a link TRB, trb_in_td() would fail (because the dequeue pointer and dequeue segment were out-of-sync), and this message would appear: ERROR Transfer event TRB DMA ptr not part of current TD This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0 port: "Transfer event TRB DMA ptr not part of current TD", "rejecting I/O to offline device"), https://bugzilla.kernel.org/show_bug.cgi?id=43333 and possibly other general protection fault bugs as well. This patch should be backported to kernels as old as 2.6.31. A separate patch will be created for kernels older than 3.4, since inc_deq was modified in 3.4 and this patch will not apply. Signed-off-by: Sarah Sharp Tested-by: James Ettle Tested-by: Matthew Hall Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0c93f5dcea6f..643c2f3f3e73 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci, */ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) { - union xhci_trb *next; unsigned long long addr; ring->deq_updates++; - /* If this is not event ring, there is one more usable TRB */ + /* + * If this is not event ring, and the dequeue pointer + * is not on a link TRB, there is one more usable TRB + */ if (ring->type != TYPE_EVENT && !last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) ring->num_trbs_free++; - next = ++(ring->dequeue); - /* Update the dequeue pointer further if that was a link TRB or we're at - * the end of an event ring segment (which doesn't have link TRBS) - */ - while (last_trb(xhci, ring, ring->deq_seg, next)) { - if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, - ring, ring->deq_seg, next)) { - ring->cycle_state = (ring->cycle_state ? 0 : 1); + do { + /* + * Update the dequeue pointer further if that was a link TRB or + * we're at the end of an event ring segment (which doesn't have + * link TRBS) + */ + if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { + if (ring->type == TYPE_EVENT && + last_trb_on_last_seg(xhci, ring, + ring->deq_seg, ring->dequeue)) { + ring->cycle_state = (ring->cycle_state ? 0 : 1); + } + ring->deq_seg = ring->deq_seg->next; + ring->dequeue = ring->deq_seg->trbs; + } else { + ring->dequeue++; } - ring->deq_seg = ring->deq_seg->next; - ring->dequeue = ring->deq_seg->trbs; - next = ring->dequeue; - } + } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); + addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); } -- GitLab From 47fbf7976e0b7d9dcdd799e2a1baba19064d9631 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 8 Aug 2012 16:03:13 -0400 Subject: [PATCH 5240/5711] NFSv4.1: Remove a bogus BUG_ON() in nfs4_layoutreturn_done Ever since commit 0a57cdac3f (NFSv4.1 send layoutreturn to fence disconnected data server) we've been sending layoutreturn calls while there is potentially still outstanding I/O to the data servers. The reason we do this is to avoid races between replayed writes to the MDS and the original writes to the DS. When this happens, the BUG_ON() in nfs4_layoutreturn_done can be triggered because it assumes that we would never call layoutreturn without knowing that all I/O to the DS is finished. The fix is to remove the BUG_ON() now that the assumptions behind the test are obsolete. Reported-by: Boaz Harrosh Reported-by: Tigran Mkrtchyan Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>=3.5] --- fs/nfs/nfs4proc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f94f6b3928fc..c77d296bdaa6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6359,12 +6359,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) return; } spin_lock(&lo->plh_inode->i_lock); - if (task->tk_status == 0) { - if (lrp->res.lrs_present) { - pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); - } else - BUG_ON(!list_empty(&lo->plh_segs)); - } + if (task->tk_status == 0 && lrp->res.lrs_present) + pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); lo->plh_block_lgets--; spin_unlock(&lo->plh_inode->i_lock); dprintk("<-- %s\n", __func__); -- GitLab From c6fd893da927c6cefb2ece22402765379921a834 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 31 Jul 2012 10:29:14 -0700 Subject: [PATCH 5241/5711] x86, avx: don't use avx instructions with "noxsave" boot param Clear AVX, AVX2 features along with clearing XSAVE feature bits, as part of the parsing "noxsave" parameter. Fixes the kernel boot panic with "noxsave" boot parameter. We could have checked cpu_has_osxsave along with cpu_has_avx etc, but Peter mentioned clearing the feature bits will be better for uses like static_cpu_has() etc. Signed-off-by: Suresh Siddha Link: http://lkml.kernel.org/r/1343755754.2041.2.camel@sbsiddha-desk.sc.intel.com Cc: # v3.5 Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 46d8786d655e..a5fbc3c5fccc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -144,6 +144,8 @@ static int __init x86_xsave_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_XSAVE); setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); + setup_clear_cpu_cap(X86_FEATURE_AVX); + setup_clear_cpu_cap(X86_FEATURE_AVX2); return 1; } __setup("noxsave", x86_xsave_setup); -- GitLab From 920d087e44c228be6270e07fdb59043380a4bb00 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 6 Aug 2012 16:08:36 +0000 Subject: [PATCH 5242/5711] drivers: net: irda: bfin_sir: fix compile error Bit IREN is replaced by UMOD_IRDA and UMOD_MASK since blackfin 60x added, but this driver didn't update which will cause bfin_sir build error: drivers/net/irda/bfin_sir.c:161:9: error: 'IREN' undeclared (first use in this function) drivers/net/irda/bfin_sir.c:435:18: error: 'IREN' undeclared (first use in this function) drivers/net/irda/bfin_sir.c:521:11: error: 'IREN' undeclared (first use in this function) This patch fix it. Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Acked-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/bfin_sir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index a561ae44a9ac..c6a0299aa9f9 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -158,7 +158,7 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) /* If not add the 'RPOLC', we can't catch the receive interrupt. * It's related with the HW layout and the IR transiver. */ - val |= IREN | RPOLC; + val |= UMOD_IRDA | RPOLC; UART_PUT_GCTL(port, val); return ret; } @@ -432,7 +432,7 @@ static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev bfin_sir_stop_rx(port); val = UART_GET_GCTL(port); - val &= ~(UCEN | IREN | RPOLC); + val &= ~(UCEN | UMOD_MASK | RPOLC); UART_PUT_GCTL(port, val); #ifdef CONFIG_SIR_BFIN_DMA @@ -518,10 +518,10 @@ static void bfin_sir_send_work(struct work_struct *work) * reset all the UART. */ val = UART_GET_GCTL(port); - val &= ~(IREN | RPOLC); + val &= ~(UMOD_MASK | RPOLC); UART_PUT_GCTL(port, val); SSYNC(); - val |= IREN | RPOLC; + val |= UMOD_IRDA | RPOLC; UART_PUT_GCTL(port, val); SSYNC(); /* bfin_sir_set_speed(port, self->speed); */ -- GitLab From 99aa3473e672ca610905838997fa018b95cd643f Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 6 Aug 2012 16:27:10 +0000 Subject: [PATCH 5243/5711] af_packet: Quiet sparse noise about using plain integer as NULL pointer Quiets the sparse warning: warning: Using plain integer as NULL pointer Signed-off-by: Ying Xue Signed-off-by: David S. Miller --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ceaca7c134a0..f016f6634a79 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1079,7 +1079,7 @@ static void *packet_current_rx_frame(struct packet_sock *po, default: WARN(1, "TPACKET version not supported\n"); BUG(); - return 0; + return NULL; } } -- GitLab From 08252b32311c3fa84219ad794d640af7399b5485 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 7 Aug 2012 00:23:11 +0000 Subject: [PATCH 5244/5711] pptp: lookup route with the proper net namespace pptp always use init_net as the net namespace to lookup route, this will cause route lookup failed in container. because we already set the correct net namespace to struct sock in pptp_create,so fix this by using sock_net(sk) to replace &init_net. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- drivers/net/ppp/pptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 1c98321b56cc..162464fe86bf 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -189,7 +189,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(&init_net, &fl4, NULL, + rt = ip_route_output_ports(sock_net(sk), &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -468,7 +468,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(&init_net, &fl4, sk, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, -- GitLab From 0c03eca3d995e73d691edea8c787e25929ec156d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Aug 2012 00:47:11 +0000 Subject: [PATCH 5245/5711] net: fib: fix incorrect call_rcu_bh() After IP route cache removal, I believe rcu_bh() has very little use and we should remove this RCU variant, since it adds some cycles in fast path. Anyway, the call_rcu_bh() use in fib_true is obviously wrong, since some users only assert rcu_read_lock(). Signed-off-by: Eric Dumazet Cc: "Paul E. McKenney" Signed-off-by: David S. Miller --- net/ipv4/fib_trie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f0cdb30921c0..57bd978483e1 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -367,7 +367,7 @@ static void __leaf_free_rcu(struct rcu_head *head) static inline void free_leaf(struct leaf *l) { - call_rcu_bh(&l->rcu, __leaf_free_rcu); + call_rcu(&l->rcu, __leaf_free_rcu); } static inline void free_leaf_info(struct leaf_info *leaf) -- GitLab From a37e6e344910a43b9ebc2bbf29a029f5ea942598 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Aug 2012 10:55:45 +0000 Subject: [PATCH 5246/5711] net: force dst_default_metrics to const section While investigating on network performance problems, I found this little gem : $ nm -v vmlinux | grep -1 dst_default_metrics ffffffff82736540 b busy.46605 ffffffff82736560 B dst_default_metrics ffffffff82736598 b dst_busy_list Apparently, declaring a const array without initializer put it in (writeable) bss section, in middle of possibly often dirtied cache lines. Since we really want dst_default_metrics be const to avoid any possible false sharing and catch any buggy writes, I force a null initializer. ffffffff818a4c20 R dst_default_metrics Signed-off-by: Eric Dumazet Cc: Ben Hutchings Signed-off-by: David S. Miller --- include/net/dst.h | 2 +- net/core/dst.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index baf597890064..621e3513ef5e 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -110,7 +110,7 @@ struct dst_entry { }; extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); -extern const u32 dst_default_metrics[RTAX_MAX]; +extern const u32 dst_default_metrics[]; #define DST_METRICS_READ_ONLY 0x1UL #define __DST_METRICS_PTR(Y) \ diff --git a/net/core/dst.c b/net/core/dst.c index 069d51d29414..56d63612e1e4 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -149,7 +149,15 @@ int dst_discard(struct sk_buff *skb) } EXPORT_SYMBOL(dst_discard); -const u32 dst_default_metrics[RTAX_MAX]; +const u32 dst_default_metrics[RTAX_MAX + 1] = { + /* This initializer is needed to force linker to place this variable + * into const section. Otherwise it might end into bss section. + * We really want to avoid false sharing on this variable, and catch + * any writes on it. + */ + [RTAX_MAX] = 0xdeadbeef, +}; + void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, int initial_obsolete, unsigned short flags) -- GitLab From be72f63b4cd5d6778cf7eb0d0a86f18f96b51c0c Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Tue, 7 Aug 2012 07:27:25 +0000 Subject: [PATCH 5247/5711] sched: add missing group change to qfq_change_class [Resending again, as the text was corrupted by the email client] To speed up operations, QFQ internally divides classes into groups. Which group a class belongs to depends on the ratio between the maximum packet length and the weight of the class. Unfortunately the function qfq_change_class lacks the steps for changing the group of a class when the ratio max_pkt_len/weight of the class changes. For example, when the last of the following three commands is executed, the group of class 1:1 is not correctly changed: tc disc add dev XXX root handle 1: qfq tc class add dev XXX parent 1: qfq classid 1:1 weight 1 tc class change dev XXX parent 1: classid 1:1 qfq weight 4 Not changing the group of a class does not affect the long-term bandwidth guaranteed to the class, as the latter is independent of the maximum packet length, and correctly changes (only) if the weight of the class changes. In contrast, if the group of the class is not updated, the class is still guaranteed the short-term bandwidth and packet delay related to its old group, instead of the guarantees that it should receive according to its new weight and/or maximum packet length. This may also break service guarantees for other classes. This patch adds the missing operations. Signed-off-by: Paolo Valente Signed-off-by: David S. Miller --- net/sched/sch_qfq.c | 95 ++++++++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 9af01f3df18c..e4723d31fdd5 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -203,6 +203,34 @@ out: return index; } +/* Length of the next packet (0 if the queue is empty). */ +static unsigned int qdisc_peek_len(struct Qdisc *sch) +{ + struct sk_buff *skb; + + skb = sch->ops->peek(sch); + return skb ? qdisc_pkt_len(skb) : 0; +} + +static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *); +static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, + unsigned int len); + +static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl, + u32 lmax, u32 inv_w, int delta_w) +{ + int i; + + /* update qfq-specific data */ + cl->lmax = lmax; + cl->inv_w = inv_w; + i = qfq_calc_index(cl->inv_w, cl->lmax); + + cl->grp = &q->groups[i]; + + q->wsum += delta_w; +} + static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca, unsigned long *arg) { @@ -250,6 +278,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, lmax = 1UL << QFQ_MTU_SHIFT; if (cl != NULL) { + bool need_reactivation = false; + if (tca[TCA_RATE]) { err = gen_replace_estimator(&cl->bstats, &cl->rate_est, qdisc_root_sleeping_lock(sch), @@ -258,12 +288,29 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, return err; } - if (inv_w != cl->inv_w) { - sch_tree_lock(sch); - q->wsum += delta_w; - cl->inv_w = inv_w; - sch_tree_unlock(sch); + if (lmax == cl->lmax && inv_w == cl->inv_w) + return 0; /* nothing to update */ + + i = qfq_calc_index(inv_w, lmax); + sch_tree_lock(sch); + if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { + /* + * shift cl->F back, to not charge the + * class for the not-yet-served head + * packet + */ + cl->F = cl->S; + /* remove class from its slot in the old group */ + qfq_deactivate_class(q, cl); + need_reactivation = true; } + + qfq_update_class_params(q, cl, lmax, inv_w, delta_w); + + if (need_reactivation) /* activate in new group */ + qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); + sch_tree_unlock(sch); + return 0; } @@ -273,11 +320,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, cl->refcnt = 1; cl->common.classid = classid; - cl->lmax = lmax; - cl->inv_w = inv_w; - i = qfq_calc_index(cl->inv_w, cl->lmax); - cl->grp = &q->groups[i]; + qfq_update_class_params(q, cl, lmax, inv_w, delta_w); cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid); @@ -294,7 +338,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, return err; } } - q->wsum += weight; sch_tree_lock(sch); qdisc_class_hash_insert(&q->clhash, &cl->common); @@ -711,15 +754,6 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V) } } -/* What is length of next packet in queue (0 if queue is empty) */ -static unsigned int qdisc_peek_len(struct Qdisc *sch) -{ - struct sk_buff *skb; - - skb = sch->ops->peek(sch); - return skb ? qdisc_pkt_len(skb) : 0; -} - /* * Updates the class, returns true if also the group needs to be updated. */ @@ -843,11 +877,8 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct qfq_sched *q = qdisc_priv(sch); - struct qfq_group *grp; struct qfq_class *cl; int err; - u64 roundedS; - int s; cl = qfq_classify(skb, sch, &err); if (cl == NULL) { @@ -876,11 +907,25 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) return err; /* If reach this point, queue q was idle */ - grp = cl->grp; + qfq_activate_class(q, cl, qdisc_pkt_len(skb)); + + return err; +} + +/* + * Handle class switch from idle to backlogged. + */ +static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, + unsigned int pkt_len) +{ + struct qfq_group *grp = cl->grp; + u64 roundedS; + int s; + qfq_update_start(q, cl); /* compute new finish time and rounded start. */ - cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; + cl->F = cl->S + (u64)pkt_len * cl->inv_w; roundedS = qfq_round_down(cl->S, grp->slot_shift); /* @@ -917,8 +962,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) skip_update: qfq_slot_insert(grp, cl, roundedS); - - return err; } -- GitLab From 155e4e12b9f49c2dc817bb4c44e9416c46833c3d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 7 Aug 2012 08:32:34 +0000 Subject: [PATCH 5248/5711] batman-adv: Fix mem leak in the batadv_tt_local_event() function Memory is allocated for 'tt_change_node' with kmalloc(). 'tt_change_node' may go out of scope really being used for anything (except have a few members initialized) if we hit the 'del:' label. This patch makes sure we free the memory in that case. Signed-off-by: Jesper Juhl Acked-by: Antonio Quartulli Signed-off-by: David S. Miller --- net/batman-adv/translation-table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index a438f4b582fc..99dd8f75b3ff 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -197,6 +197,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, del: list_del(&entry->list); kfree(entry); + kfree(tt_change_node); event_removed = true; goto unlock; } -- GitLab From 47dffc7547ed3b105dabd570ed864347687beac2 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 7 Aug 2012 11:56:26 +0000 Subject: [PATCH 5249/5711] cdc-phonet: Don't leak in usbpn_open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allocate memory for 'req' with usb_alloc_urb() and then test 'if (!req || rx_submit(pnd, req, GFP_KERNEL | __GFP_COLD))'. If we enter that branch due to '!req' then there is no problem. But if we enter the branch due to 'req' being != 0 and the 'rx_submit()' call being false, then we'll leak the memory we allocated. Deal with the leak by always calling 'usb_free_urb(req)' when entering the branch. If 'req' happens to be 0 then the call is harmless, if it is not 0 then we free the memory we allocated but don't need. Signed-off-by: Jesper Juhl Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- drivers/net/usb/cdc-phonet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 64610048ce87..7d78669000d7 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -232,6 +232,7 @@ static int usbpn_open(struct net_device *dev) struct urb *req = usb_alloc_urb(0, GFP_KERNEL); if (!req || rx_submit(pnd, req, GFP_KERNEL | __GFP_COLD)) { + usb_free_urb(req); usbpn_close(dev); return -ENOMEM; } -- GitLab From 7364e445f62825758fa61195d237a5b8ecdd06ec Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 00:33:25 +0000 Subject: [PATCH 5250/5711] net/core: Fix potential memory leak in dev_set_alias() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: David S. Miller --- net/core/dev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index f91abf800161..a39354ee1432 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1055,6 +1055,8 @@ rollback: */ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) { + char *new_ifalias; + ASSERT_RTNL(); if (len >= IFALIASZ) @@ -1068,9 +1070,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) return 0; } - dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); - if (!dev->ifalias) + new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); + if (!new_ifalias) return -ENOMEM; + dev->ifalias = new_ifalias; strlcpy(dev->ifalias, alias, len+1); return len; -- GitLab From 3a32aea6e01b10a462763e0b0e00805f387ca010 Mon Sep 17 00:00:00 2001 From: "stigge@antcom.de" Date: Wed, 8 Aug 2012 03:18:54 +0000 Subject: [PATCH 5251/5711] lpc_eth: remove obsolete ifdefs The #ifdefs regarding CONFIG_ARCH_LPC32XX_MII_SUPPORT and CONFIG_ARCH_LPC32XX_IRAM_FOR_NET are obsolete since the symbols have been removed from Kconfig and replaced by devicetree based configuration. Signed-off-by: Roland Stigge Signed-off-by: David S. Miller --- drivers/net/ethernet/nxp/lpc_eth.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 4069edab229e..53743f7a2ca9 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -346,28 +346,15 @@ static phy_interface_t lpc_phy_interface_mode(struct device *dev) "phy-mode", NULL); if (mode && !strcmp(mode, "mii")) return PHY_INTERFACE_MODE_MII; - return PHY_INTERFACE_MODE_RMII; } - - /* non-DT */ -#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT - return PHY_INTERFACE_MODE_MII; -#else return PHY_INTERFACE_MODE_RMII; -#endif } static bool use_iram_for_net(struct device *dev) { if (dev && dev->of_node) return of_property_read_bool(dev->of_node, "use-iram"); - - /* non-DT */ -#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET - return true; -#else return false; -#endif } /* Receive Status information word */ -- GitLab From f5addb91d14e63beb6224a62fb81b6e610cee3bc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Aug 2012 04:47:24 +0000 Subject: [PATCH 5252/5711] net/stmmac: mark probe function as __devinit Driver probe functions are generally __devinit so they will be discarded after initialization for non-hotplug kernels. This was found by a new warning after patch 6a228452d "stmmac: Add device-tree support" adds a new __devinit function that is called from stmmac_pltfr_probe. Without this patch, building socfpga_defconfig results in: WARNING: drivers/net/ethernet/stmicro/stmmac/stmmac.o(.text+0x5d4c): Section mismatch in reference from the function stmmac_pltfr_probe() to the function .devinit.text:stmmac_probe_config_dt() The function stmmac_pltfr_probe() references the function __devinit stmmac_probe_config_dt(). This is often because stmmac_pltfr_probe lacks a __devinit annotation or the annotation of stmmac_probe_config_dt is wrong. Signed-off-by: Arnd Bergmann Cc: Stefan Roese Cc: Giuseppe Cavallaro Cc: David S. Miller Cc: netdev@vger.kernel.org Acked-by: Stefan Roese Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index cd01ee7ecef1..b93245c11995 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ -static int stmmac_pltfr_probe(struct platform_device *pdev) +static int __devinit stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; -- GitLab From 0f457e488c79922dfd646f94ed058764f7ba758c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 29 Jul 2012 16:24:57 +0200 Subject: [PATCH 5253/5711] drm/radeon/kms: allow "invalid" DB formats as a means to disable DB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Reviewed-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen_cs.c | 6 ++++-- drivers/gpu/drm/radeon/evergreend.h | 2 ++ drivers/gpu/drm/radeon/r600_cs.c | 6 ++++-- drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index c16554122ccd..f2e5c545c973 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -961,13 +961,15 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) if (track->db_dirty) { /* Check stencil buffer */ - if (G_028800_STENCIL_ENABLE(track->db_depth_control)) { + if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && + G_028800_STENCIL_ENABLE(track->db_depth_control)) { r = evergreen_cs_track_validate_stencil(p); if (r) return r; } /* Check depth buffer */ - if (G_028800_Z_ENABLE(track->db_depth_control)) { + if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && + G_028800_Z_ENABLE(track->db_depth_control)) { r = evergreen_cs_track_validate_depth(p); if (r) return r; diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index d3bd098e4e19..79347855d9bf 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1277,6 +1277,8 @@ #define S_028044_FORMAT(x) (((x) & 0x1) << 0) #define G_028044_FORMAT(x) (((x) >> 0) & 0x1) #define C_028044_FORMAT 0xFFFFFFFE +#define V_028044_STENCIL_INVALID 0 +#define V_028044_STENCIL_8 1 #define G_028044_TILE_SPLIT(x) (((x) >> 8) & 0x7) #define DB_Z_READ_BASE 0x28048 #define DB_STENCIL_READ_BASE 0x2804c diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ca87f7afaf23..1119e31e5c2f 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -764,8 +764,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) } /* Check depth buffer */ - if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) || - G_028800_Z_ENABLE(track->db_depth_control))) { + if (track->db_dirty && + G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID && + (G_028800_STENCIL_ENABLE(track->db_depth_control) || + G_028800_Z_ENABLE(track->db_depth_control))) { r = r600_cs_track_validate_db(p); if (r) return r; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dcea6f01ae4e..4b736ecb0aa5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -59,9 +59,10 @@ * 2.15.0 - add max_pipes query * 2.16.0 - fix evergreen 2D tiled surface calculation * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx + * 2.18.0 - r600-eg: allow "invalid" DB formats */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 17 +#define KMS_DRIVER_MINOR 18 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); -- GitLab From 959f724728b6a1cb5185230972119dd7bc8b610e Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 7 Aug 2012 06:57:25 +0000 Subject: [PATCH 5254/5711] drm/udl: Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(.. [1] The semantic patch that makes this change is available in scripts/coccinelle/api/err_cast.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 7bd65bdd15a8..291ecc145585 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -308,7 +308,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, /* need to attach */ attach = dma_buf_attach(dma_buf, dev->dev); if (IS_ERR(attach)) - return ERR_PTR(PTR_ERR(attach)); + return ERR_CAST(attach); sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR(sg)) { -- GitLab From 800fb3ddee2c50918d651fbd70515f1e38857305 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 4 Aug 2012 21:54:05 -0400 Subject: [PATCH 5255/5711] sh: dma: fix request_irq usage When calling request_irq with IRQF_SHARED, the dev cookie must be set (i.e. non-NULL), otherwise the code rejects it immediately with -EINVAL. So restore the logic here where we'd pass a pointer to the name as a dummy unique val. Otherwise, booting up on my LANDISK system would fail with: DMAC Address Error0 request_irq fail This was introduced in commit 7f47c7189b3e8f19a589f77a3ad169d7b691b582. Signed-off-by: Mike Frysinger Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/dma-sh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 4c171f13b0e8..b22565623142 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -335,7 +335,7 @@ static int dmae_irq_init(void) for (n = 0; n < NR_DMAE; n++) { int i = request_irq(get_dma_error_irq(n), dma_err, - IRQF_SHARED, dmae_name[n], NULL); + IRQF_SHARED, dmae_name[n], (void *)dmae_name[n]); if (unlikely(i < 0)) { printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]); return i; -- GitLab From d0b464d67001d202e59f7e60a30074c4d74021aa Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 7 Aug 2012 08:10:40 +0100 Subject: [PATCH 5256/5711] sh: sh7269: Fix LCD pinmux There are two ports that can output the LCD data, therefore they have to use separate pimux identifiers so we can select the one we want to use. Signed-off-by: Phil Edworthy Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh2a/cpu/sh7269.h | 36 +++-- arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c | 195 ++++++++++++++---------- 2 files changed, 141 insertions(+), 90 deletions(-) diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh2a/cpu/sh7269.h index 48d14498e774..2a0ca8780f0d 100644 --- a/arch/sh/include/cpu-sh2a/cpu/sh7269.h +++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h @@ -183,18 +183,30 @@ enum { GPIO_FN_DV_DATA1, GPIO_FN_DV_DATA0, GPIO_FN_LCD_CLK, GPIO_FN_LCD_EXTCLK, GPIO_FN_LCD_VSYNC, GPIO_FN_LCD_HSYNC, GPIO_FN_LCD_DE, - GPIO_FN_LCD_DATA23, GPIO_FN_LCD_DATA22, - GPIO_FN_LCD_DATA21, GPIO_FN_LCD_DATA20, - GPIO_FN_LCD_DATA19, GPIO_FN_LCD_DATA18, - GPIO_FN_LCD_DATA17, GPIO_FN_LCD_DATA16, - GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14, - GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12, - GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10, - GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8, - GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6, - GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4, - GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2, - GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0, + GPIO_FN_LCD_DATA23_PG23, GPIO_FN_LCD_DATA22_PG22, + GPIO_FN_LCD_DATA21_PG21, GPIO_FN_LCD_DATA20_PG20, + GPIO_FN_LCD_DATA19_PG19, GPIO_FN_LCD_DATA18_PG18, + GPIO_FN_LCD_DATA17_PG17, GPIO_FN_LCD_DATA16_PG16, + GPIO_FN_LCD_DATA15_PG15, GPIO_FN_LCD_DATA14_PG14, + GPIO_FN_LCD_DATA13_PG13, GPIO_FN_LCD_DATA12_PG12, + GPIO_FN_LCD_DATA11_PG11, GPIO_FN_LCD_DATA10_PG10, + GPIO_FN_LCD_DATA9_PG9, GPIO_FN_LCD_DATA8_PG8, + GPIO_FN_LCD_DATA7_PG7, GPIO_FN_LCD_DATA6_PG6, + GPIO_FN_LCD_DATA5_PG5, GPIO_FN_LCD_DATA4_PG4, + GPIO_FN_LCD_DATA3_PG3, GPIO_FN_LCD_DATA2_PG2, + GPIO_FN_LCD_DATA1_PG1, GPIO_FN_LCD_DATA0_PG0, + GPIO_FN_LCD_DATA23_PJ23, GPIO_FN_LCD_DATA22_PJ22, + GPIO_FN_LCD_DATA21_PJ21, GPIO_FN_LCD_DATA20_PJ20, + GPIO_FN_LCD_DATA19_PJ19, GPIO_FN_LCD_DATA18_PJ18, + GPIO_FN_LCD_DATA17_PJ17, GPIO_FN_LCD_DATA16_PJ16, + GPIO_FN_LCD_DATA15_PJ15, GPIO_FN_LCD_DATA14_PJ14, + GPIO_FN_LCD_DATA13_PJ13, GPIO_FN_LCD_DATA12_PJ12, + GPIO_FN_LCD_DATA11_PJ11, GPIO_FN_LCD_DATA10_PJ10, + GPIO_FN_LCD_DATA9_PJ9, GPIO_FN_LCD_DATA8_PJ8, + GPIO_FN_LCD_DATA7_PJ7, GPIO_FN_LCD_DATA6_PJ6, + GPIO_FN_LCD_DATA5_PJ5, GPIO_FN_LCD_DATA4_PJ4, + GPIO_FN_LCD_DATA3_PJ3, GPIO_FN_LCD_DATA2_PJ2, + GPIO_FN_LCD_DATA1_PJ1, GPIO_FN_LCD_DATA0_PJ0, GPIO_FN_LCD_M_DISP, }; diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c index f25127c46eca..039e4587dd9b 100644 --- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c +++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c @@ -758,12 +758,22 @@ enum { DV_DATA3_MARK, DV_DATA2_MARK, DV_DATA1_MARK, DV_DATA0_MARK, LCD_CLK_MARK, LCD_EXTCLK_MARK, LCD_VSYNC_MARK, LCD_HSYNC_MARK, LCD_DE_MARK, - LCD_DATA23_MARK, LCD_DATA22_MARK, LCD_DATA21_MARK, LCD_DATA20_MARK, - LCD_DATA19_MARK, LCD_DATA18_MARK, LCD_DATA17_MARK, LCD_DATA16_MARK, - LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK, - LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK, - LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK, - LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK, + LCD_DATA23_PG23_MARK, LCD_DATA22_PG22_MARK, LCD_DATA21_PG21_MARK, + LCD_DATA20_PG20_MARK, LCD_DATA19_PG19_MARK, LCD_DATA18_PG18_MARK, + LCD_DATA17_PG17_MARK, LCD_DATA16_PG16_MARK, LCD_DATA15_PG15_MARK, + LCD_DATA14_PG14_MARK, LCD_DATA13_PG13_MARK, LCD_DATA12_PG12_MARK, + LCD_DATA11_PG11_MARK, LCD_DATA10_PG10_MARK, LCD_DATA9_PG9_MARK, + LCD_DATA8_PG8_MARK, LCD_DATA7_PG7_MARK, LCD_DATA6_PG6_MARK, + LCD_DATA5_PG5_MARK, LCD_DATA4_PG4_MARK, LCD_DATA3_PG3_MARK, + LCD_DATA2_PG2_MARK, LCD_DATA1_PG1_MARK, LCD_DATA0_PG0_MARK, + LCD_DATA23_PJ23_MARK, LCD_DATA22_PJ22_MARK, LCD_DATA21_PJ21_MARK, + LCD_DATA20_PJ20_MARK, LCD_DATA19_PJ19_MARK, LCD_DATA18_PJ18_MARK, + LCD_DATA17_PJ17_MARK, LCD_DATA16_PJ16_MARK, LCD_DATA15_PJ15_MARK, + LCD_DATA14_PJ14_MARK, LCD_DATA13_PJ13_MARK, LCD_DATA12_PJ12_MARK, + LCD_DATA11_PJ11_MARK, LCD_DATA10_PJ10_MARK, LCD_DATA9_PJ9_MARK, + LCD_DATA8_PJ8_MARK, LCD_DATA7_PJ7_MARK, LCD_DATA6_PJ6_MARK, + LCD_DATA5_PJ5_MARK, LCD_DATA4_PJ4_MARK, LCD_DATA3_PJ3_MARK, + LCD_DATA2_PJ2_MARK, LCD_DATA1_PJ1_MARK, LCD_DATA0_PJ0_MARK, LCD_TCON6_MARK, LCD_TCON5_MARK, LCD_TCON4_MARK, LCD_TCON3_MARK, LCD_TCON2_MARK, LCD_TCON1_MARK, LCD_TCON0_MARK, LCD_M_DISP_MARK, @@ -1036,6 +1046,7 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PF1_DATA, PF1MD_000), PINMUX_DATA(BACK_MARK, PF1MD_001), + PINMUX_DATA(SSL10_MARK, PF1MD_011), PINMUX_DATA(TIOC4B_MARK, PF1MD_100), PINMUX_DATA(DACK0_MARK, PF1MD_101), @@ -1049,47 +1060,50 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PG27_DATA, PG27MD_00), PINMUX_DATA(LCD_TCON2_MARK, PG27MD_10), PINMUX_DATA(LCD_EXTCLK_MARK, PG27MD_11), + PINMUX_DATA(LCD_DE_MARK, PG27MD_11), PINMUX_DATA(PG26_DATA, PG26MD_00), PINMUX_DATA(LCD_TCON1_MARK, PG26MD_10), + PINMUX_DATA(LCD_HSYNC_MARK, PG26MD_10), PINMUX_DATA(PG25_DATA, PG25MD_00), PINMUX_DATA(LCD_TCON0_MARK, PG25MD_10), + PINMUX_DATA(LCD_VSYNC_MARK, PG25MD_10), PINMUX_DATA(PG24_DATA, PG24MD_00), PINMUX_DATA(LCD_CLK_MARK, PG24MD_10), PINMUX_DATA(PG23_DATA, PG23MD_000), - PINMUX_DATA(LCD_DATA23_MARK, PG23MD_010), + PINMUX_DATA(LCD_DATA23_PG23_MARK, PG23MD_010), PINMUX_DATA(LCD_TCON6_MARK, PG23MD_011), PINMUX_DATA(TXD5_MARK, PG23MD_100), PINMUX_DATA(PG22_DATA, PG22MD_000), - PINMUX_DATA(LCD_DATA22_MARK, PG22MD_010), + PINMUX_DATA(LCD_DATA22_PG22_MARK, PG22MD_010), PINMUX_DATA(LCD_TCON5_MARK, PG22MD_011), PINMUX_DATA(RXD5_MARK, PG22MD_100), PINMUX_DATA(PG21_DATA, PG21MD_000), PINMUX_DATA(DV_DATA7_MARK, PG21MD_001), - PINMUX_DATA(LCD_DATA21_MARK, PG21MD_010), + PINMUX_DATA(LCD_DATA21_PG21_MARK, PG21MD_010), PINMUX_DATA(LCD_TCON4_MARK, PG21MD_011), PINMUX_DATA(TXD4_MARK, PG21MD_100), PINMUX_DATA(PG20_DATA, PG20MD_000), PINMUX_DATA(DV_DATA6_MARK, PG20MD_001), - PINMUX_DATA(LCD_DATA20_MARK, PG21MD_010), + PINMUX_DATA(LCD_DATA20_PG20_MARK, PG21MD_010), PINMUX_DATA(LCD_TCON3_MARK, PG20MD_011), PINMUX_DATA(RXD4_MARK, PG20MD_100), PINMUX_DATA(PG19_DATA, PG19MD_000), PINMUX_DATA(DV_DATA5_MARK, PG19MD_001), - PINMUX_DATA(LCD_DATA19_MARK, PG19MD_010), + PINMUX_DATA(LCD_DATA19_PG19_MARK, PG19MD_010), PINMUX_DATA(SPDIF_OUT_MARK, PG19MD_011), PINMUX_DATA(SCK5_MARK, PG19MD_100), PINMUX_DATA(PG18_DATA, PG18MD_000), PINMUX_DATA(DV_DATA4_MARK, PG18MD_001), - PINMUX_DATA(LCD_DATA18_MARK, PG18MD_010), + PINMUX_DATA(LCD_DATA18_PG18_MARK, PG18MD_010), PINMUX_DATA(SPDIF_IN_MARK, PG18MD_011), PINMUX_DATA(SCK4_MARK, PG18MD_100), @@ -1097,103 +1111,103 @@ static pinmux_enum_t pinmux_data[] = { // we're going with 2 bits PINMUX_DATA(PG17_DATA, PG17MD_00), PINMUX_DATA(WE3ICIOWRAHDQMUU_MARK, PG17MD_01), - PINMUX_DATA(LCD_DATA17_MARK, PG17MD_10), + PINMUX_DATA(LCD_DATA17_PG17_MARK, PG17MD_10), // TODO hardware manual has PG16 3 bits wide in reg picture and 2 bits in description // we're going with 2 bits PINMUX_DATA(PG16_DATA, PG16MD_00), PINMUX_DATA(WE2ICIORDDQMUL_MARK, PG16MD_01), - PINMUX_DATA(LCD_DATA16_MARK, PG16MD_10), + PINMUX_DATA(LCD_DATA16_PG16_MARK, PG16MD_10), PINMUX_DATA(PG15_DATA, PG15MD_00), PINMUX_DATA(D31_MARK, PG15MD_01), - PINMUX_DATA(LCD_DATA15_MARK, PG15MD_10), + PINMUX_DATA(LCD_DATA15_PG15_MARK, PG15MD_10), PINMUX_DATA(PINT7_PG_MARK, PG15MD_11), PINMUX_DATA(PG14_DATA, PG14MD_00), PINMUX_DATA(D30_MARK, PG14MD_01), - PINMUX_DATA(LCD_DATA14_MARK, PG14MD_10), + PINMUX_DATA(LCD_DATA14_PG14_MARK, PG14MD_10), PINMUX_DATA(PINT6_PG_MARK, PG14MD_11), PINMUX_DATA(PG13_DATA, PG13MD_00), PINMUX_DATA(D29_MARK, PG13MD_01), - PINMUX_DATA(LCD_DATA13_MARK, PG13MD_10), + PINMUX_DATA(LCD_DATA13_PG13_MARK, PG13MD_10), PINMUX_DATA(PINT5_PG_MARK, PG13MD_11), PINMUX_DATA(PG12_DATA, PG12MD_00), PINMUX_DATA(D28_MARK, PG12MD_01), - PINMUX_DATA(LCD_DATA12_MARK, PG12MD_10), + PINMUX_DATA(LCD_DATA12_PG12_MARK, PG12MD_10), PINMUX_DATA(PINT4_PG_MARK, PG12MD_11), PINMUX_DATA(PG11_DATA, PG11MD_000), PINMUX_DATA(D27_MARK, PG11MD_001), - PINMUX_DATA(LCD_DATA11_MARK, PG11MD_010), + PINMUX_DATA(LCD_DATA11_PG11_MARK, PG11MD_010), PINMUX_DATA(PINT3_PG_MARK, PG11MD_011), PINMUX_DATA(TIOC3D_MARK, PG11MD_100), PINMUX_DATA(PG10_DATA, PG10MD_000), PINMUX_DATA(D26_MARK, PG10MD_001), - PINMUX_DATA(LCD_DATA10_MARK, PG10MD_010), + PINMUX_DATA(LCD_DATA10_PG10_MARK, PG10MD_010), PINMUX_DATA(PINT2_PG_MARK, PG10MD_011), PINMUX_DATA(TIOC3C_MARK, PG10MD_100), PINMUX_DATA(PG9_DATA, PG9MD_000), PINMUX_DATA(D25_MARK, PG9MD_001), - PINMUX_DATA(LCD_DATA9_MARK, PG9MD_010), + PINMUX_DATA(LCD_DATA9_PG9_MARK, PG9MD_010), PINMUX_DATA(PINT1_PG_MARK, PG9MD_011), PINMUX_DATA(TIOC3B_MARK, PG9MD_100), PINMUX_DATA(PG8_DATA, PG8MD_000), PINMUX_DATA(D24_MARK, PG8MD_001), - PINMUX_DATA(LCD_DATA8_MARK, PG8MD_010), + PINMUX_DATA(LCD_DATA8_PG8_MARK, PG8MD_010), PINMUX_DATA(PINT0_PG_MARK, PG8MD_011), PINMUX_DATA(TIOC3A_MARK, PG8MD_100), PINMUX_DATA(PG7_DATA, PG7MD_000), PINMUX_DATA(D23_MARK, PG7MD_001), - PINMUX_DATA(LCD_DATA7_MARK, PG7MD_010), + PINMUX_DATA(LCD_DATA7_PG7_MARK, PG7MD_010), PINMUX_DATA(IRQ7_PG_MARK, PG7MD_011), PINMUX_DATA(TIOC2B_MARK, PG7MD_100), PINMUX_DATA(PG6_DATA, PG6MD_000), PINMUX_DATA(D22_MARK, PG6MD_001), - PINMUX_DATA(LCD_DATA6_MARK, PG6MD_010), + PINMUX_DATA(LCD_DATA6_PG6_MARK, PG6MD_010), PINMUX_DATA(IRQ6_PG_MARK, PG6MD_011), PINMUX_DATA(TIOC2A_MARK, PG6MD_100), PINMUX_DATA(PG5_DATA, PG5MD_000), PINMUX_DATA(D21_MARK, PG5MD_001), - PINMUX_DATA(LCD_DATA5_MARK, PG5MD_010), + PINMUX_DATA(LCD_DATA5_PG5_MARK, PG5MD_010), PINMUX_DATA(IRQ5_PG_MARK, PG5MD_011), PINMUX_DATA(TIOC1B_MARK, PG5MD_100), PINMUX_DATA(PG4_DATA, PG4MD_000), PINMUX_DATA(D20_MARK, PG4MD_001), - PINMUX_DATA(LCD_DATA4_MARK, PG4MD_010), + PINMUX_DATA(LCD_DATA4_PG4_MARK, PG4MD_010), PINMUX_DATA(IRQ4_PG_MARK, PG4MD_011), PINMUX_DATA(TIOC1A_MARK, PG4MD_100), PINMUX_DATA(PG3_DATA, PG3MD_000), PINMUX_DATA(D19_MARK, PG3MD_001), - PINMUX_DATA(LCD_DATA3_MARK, PG3MD_010), + PINMUX_DATA(LCD_DATA3_PG3_MARK, PG3MD_010), PINMUX_DATA(IRQ3_PG_MARK, PG3MD_011), PINMUX_DATA(TIOC0D_MARK, PG3MD_100), PINMUX_DATA(PG2_DATA, PG2MD_000), PINMUX_DATA(D18_MARK, PG2MD_001), - PINMUX_DATA(LCD_DATA2_MARK, PG2MD_010), + PINMUX_DATA(LCD_DATA2_PG2_MARK, PG2MD_010), PINMUX_DATA(IRQ2_PG_MARK, PG2MD_011), PINMUX_DATA(TIOC0C_MARK, PG2MD_100), PINMUX_DATA(PG1_DATA, PG1MD_000), PINMUX_DATA(D17_MARK, PG1MD_001), - PINMUX_DATA(LCD_DATA1_MARK, PG1MD_010), + PINMUX_DATA(LCD_DATA1_PG1_MARK, PG1MD_010), PINMUX_DATA(IRQ1_PG_MARK, PG1MD_011), PINMUX_DATA(TIOC0B_MARK, PG1MD_100), PINMUX_DATA(PG0_DATA, PG0MD_000), PINMUX_DATA(D16_MARK, PG0MD_001), - PINMUX_DATA(LCD_DATA0_MARK, PG0MD_010), + PINMUX_DATA(LCD_DATA0_PG0_MARK, PG0MD_010), PINMUX_DATA(IRQ0_PG_MARK, PG0MD_011), PINMUX_DATA(TIOC0A_MARK, PG0MD_100), @@ -1275,14 +1289,14 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ23_DATA, PJ23MD_000), PINMUX_DATA(DV_DATA23_MARK, PJ23MD_001), - PINMUX_DATA(LCD_DATA23_MARK, PJ23MD_010), + PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010), PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011), PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100), PINMUX_DATA(CTX1_MARK, PJ23MD_101), PINMUX_DATA(PJ22_DATA, PJ22MD_000), PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001), - PINMUX_DATA(LCD_DATA22_MARK, PJ22MD_010), + PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010), PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011), PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100), PINMUX_DATA(CRX1_MARK, PJ22MD_101), @@ -1290,14 +1304,14 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ21_DATA, PJ21MD_000), PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001), - PINMUX_DATA(LCD_DATA21_MARK, PJ21MD_010), + PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010), PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011), PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100), PINMUX_DATA(CTX2_MARK, PJ21MD_101), PINMUX_DATA(PJ20_DATA, PJ20MD_000), PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001), - PINMUX_DATA(LCD_DATA20_MARK, PJ20MD_010), + PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010), PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011), PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100), PINMUX_DATA(CRX2_MARK, PJ20MD_101), @@ -1305,7 +1319,7 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ19_DATA, PJ19MD_000), PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001), - PINMUX_DATA(LCD_DATA19_MARK, PJ19MD_010), + PINMUX_DATA(LCD_DATA19_PJ19_MARK, PJ19MD_010), PINMUX_DATA(MISO0_PJ19_MARK, PJ19MD_011), PINMUX_DATA(TIOC0D_MARK, PJ19MD_100), PINMUX_DATA(SIOFRXD_MARK, PJ19MD_101), @@ -1313,126 +1327,126 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ18_DATA, PJ18MD_000), PINMUX_DATA(DV_DATA18_MARK, PJ18MD_001), - PINMUX_DATA(LCD_DATA18_MARK, PJ18MD_010), + PINMUX_DATA(LCD_DATA18_PJ18_MARK, PJ18MD_010), PINMUX_DATA(MOSI0_PJ18_MARK, PJ18MD_011), PINMUX_DATA(TIOC0C_MARK, PJ18MD_100), PINMUX_DATA(SIOFTXD_MARK, PJ18MD_101), PINMUX_DATA(PJ17_DATA, PJ17MD_000), PINMUX_DATA(DV_DATA17_MARK, PJ17MD_001), - PINMUX_DATA(LCD_DATA17_MARK, PJ17MD_010), + PINMUX_DATA(LCD_DATA17_PJ17_MARK, PJ17MD_010), PINMUX_DATA(SSL00_PJ17_MARK, PJ17MD_011), PINMUX_DATA(TIOC0B_MARK, PJ17MD_100), PINMUX_DATA(SIOFSYNC_MARK, PJ17MD_101), PINMUX_DATA(PJ16_DATA, PJ16MD_000), PINMUX_DATA(DV_DATA16_MARK, PJ16MD_001), - PINMUX_DATA(LCD_DATA16_MARK, PJ16MD_010), + PINMUX_DATA(LCD_DATA16_PJ16_MARK, PJ16MD_010), PINMUX_DATA(RSPCK0_PJ16_MARK, PJ16MD_011), PINMUX_DATA(TIOC0A_MARK, PJ16MD_100), PINMUX_DATA(SIOFSCK_MARK, PJ16MD_101), PINMUX_DATA(PJ15_DATA, PJ15MD_000), PINMUX_DATA(DV_DATA15_MARK, PJ15MD_001), - PINMUX_DATA(LCD_DATA15_MARK, PJ15MD_010), + PINMUX_DATA(LCD_DATA15_PJ15_MARK, PJ15MD_010), PINMUX_DATA(PINT7_PJ_MARK, PJ15MD_011), PINMUX_DATA(PWM2H_MARK, PJ15MD_100), PINMUX_DATA(TXD7_MARK, PJ15MD_101), PINMUX_DATA(PJ14_DATA, PJ14MD_000), PINMUX_DATA(DV_DATA14_MARK, PJ14MD_001), - PINMUX_DATA(LCD_DATA14_MARK, PJ14MD_010), + PINMUX_DATA(LCD_DATA14_PJ14_MARK, PJ14MD_010), PINMUX_DATA(PINT6_PJ_MARK, PJ14MD_011), PINMUX_DATA(PWM2G_MARK, PJ14MD_100), PINMUX_DATA(TXD6_MARK, PJ14MD_101), PINMUX_DATA(PJ13_DATA, PJ13MD_000), PINMUX_DATA(DV_DATA13_MARK, PJ13MD_001), - PINMUX_DATA(LCD_DATA13_MARK, PJ13MD_010), + PINMUX_DATA(LCD_DATA13_PJ13_MARK, PJ13MD_010), PINMUX_DATA(PINT5_PJ_MARK, PJ13MD_011), PINMUX_DATA(PWM2F_MARK, PJ13MD_100), PINMUX_DATA(TXD5_MARK, PJ13MD_101), PINMUX_DATA(PJ12_DATA, PJ12MD_000), PINMUX_DATA(DV_DATA12_MARK, PJ12MD_001), - PINMUX_DATA(LCD_DATA12_MARK, PJ12MD_010), + PINMUX_DATA(LCD_DATA12_PJ12_MARK, PJ12MD_010), PINMUX_DATA(PINT4_PJ_MARK, PJ12MD_011), PINMUX_DATA(PWM2E_MARK, PJ12MD_100), PINMUX_DATA(SCK7_MARK, PJ12MD_101), PINMUX_DATA(PJ11_DATA, PJ11MD_000), PINMUX_DATA(DV_DATA11_MARK, PJ11MD_001), - PINMUX_DATA(LCD_DATA11_MARK, PJ11MD_010), + PINMUX_DATA(LCD_DATA11_PJ11_MARK, PJ11MD_010), PINMUX_DATA(PINT3_PJ_MARK, PJ11MD_011), PINMUX_DATA(PWM2D_MARK, PJ11MD_100), PINMUX_DATA(SCK6_MARK, PJ11MD_101), PINMUX_DATA(PJ10_DATA, PJ10MD_000), PINMUX_DATA(DV_DATA10_MARK, PJ10MD_001), - PINMUX_DATA(LCD_DATA10_MARK, PJ10MD_010), + PINMUX_DATA(LCD_DATA10_PJ10_MARK, PJ10MD_010), PINMUX_DATA(PINT2_PJ_MARK, PJ10MD_011), PINMUX_DATA(PWM2C_MARK, PJ10MD_100), PINMUX_DATA(SCK5_MARK, PJ10MD_101), PINMUX_DATA(PJ9_DATA, PJ9MD_000), PINMUX_DATA(DV_DATA9_MARK, PJ9MD_001), - PINMUX_DATA(LCD_DATA9_MARK, PJ9MD_010), + PINMUX_DATA(LCD_DATA9_PJ9_MARK, PJ9MD_010), PINMUX_DATA(PINT1_PJ_MARK, PJ9MD_011), PINMUX_DATA(PWM2B_MARK, PJ9MD_100), PINMUX_DATA(RTS5_MARK, PJ9MD_101), PINMUX_DATA(PJ8_DATA, PJ8MD_000), PINMUX_DATA(DV_DATA8_MARK, PJ8MD_001), - PINMUX_DATA(LCD_DATA8_MARK, PJ8MD_010), + PINMUX_DATA(LCD_DATA8_PJ8_MARK, PJ8MD_010), PINMUX_DATA(PINT0_PJ_MARK, PJ8MD_011), PINMUX_DATA(PWM2A_MARK, PJ8MD_100), PINMUX_DATA(CTS5_MARK, PJ8MD_101), PINMUX_DATA(PJ7_DATA, PJ7MD_000), PINMUX_DATA(DV_DATA7_MARK, PJ7MD_001), - PINMUX_DATA(LCD_DATA7_MARK, PJ7MD_010), + PINMUX_DATA(LCD_DATA7_PJ7_MARK, PJ7MD_010), PINMUX_DATA(SD_D2_MARK, PJ7MD_011), PINMUX_DATA(PWM1H_MARK, PJ7MD_100), PINMUX_DATA(PJ6_DATA, PJ6MD_000), PINMUX_DATA(DV_DATA6_MARK, PJ6MD_001), - PINMUX_DATA(LCD_DATA6_MARK, PJ6MD_010), + PINMUX_DATA(LCD_DATA6_PJ6_MARK, PJ6MD_010), PINMUX_DATA(SD_D3_MARK, PJ6MD_011), PINMUX_DATA(PWM1G_MARK, PJ6MD_100), PINMUX_DATA(PJ5_DATA, PJ5MD_000), PINMUX_DATA(DV_DATA5_MARK, PJ5MD_001), - PINMUX_DATA(LCD_DATA5_MARK, PJ5MD_010), + PINMUX_DATA(LCD_DATA5_PJ5_MARK, PJ5MD_010), PINMUX_DATA(SD_CMD_MARK, PJ5MD_011), PINMUX_DATA(PWM1F_MARK, PJ5MD_100), PINMUX_DATA(PJ4_DATA, PJ4MD_000), PINMUX_DATA(DV_DATA4_MARK, PJ4MD_001), - PINMUX_DATA(LCD_DATA4_MARK, PJ4MD_010), + PINMUX_DATA(LCD_DATA4_PJ4_MARK, PJ4MD_010), PINMUX_DATA(SD_CLK_MARK, PJ4MD_011), PINMUX_DATA(PWM1E_MARK, PJ4MD_100), PINMUX_DATA(PJ3_DATA, PJ3MD_000), PINMUX_DATA(DV_DATA3_MARK, PJ3MD_001), - PINMUX_DATA(LCD_DATA3_MARK, PJ3MD_010), + PINMUX_DATA(LCD_DATA3_PJ3_MARK, PJ3MD_010), PINMUX_DATA(SD_D0_MARK, PJ3MD_011), PINMUX_DATA(PWM1D_MARK, PJ3MD_100), PINMUX_DATA(PJ2_DATA, PJ2MD_000), PINMUX_DATA(DV_DATA2_MARK, PJ2MD_001), - PINMUX_DATA(LCD_DATA2_MARK, PJ2MD_010), + PINMUX_DATA(LCD_DATA2_PJ2_MARK, PJ2MD_010), PINMUX_DATA(SD_D1_MARK, PJ2MD_011), PINMUX_DATA(PWM1C_MARK, PJ2MD_100), PINMUX_DATA(PJ1_DATA, PJ1MD_000), PINMUX_DATA(DV_DATA1_MARK, PJ1MD_001), - PINMUX_DATA(LCD_DATA1_MARK, PJ1MD_010), + PINMUX_DATA(LCD_DATA1_PJ1_MARK, PJ1MD_010), PINMUX_DATA(SD_WP_MARK, PJ1MD_011), PINMUX_DATA(PWM1B_MARK, PJ1MD_100), PINMUX_DATA(PJ0_DATA, PJ0MD_000), PINMUX_DATA(DV_DATA0_MARK, PJ0MD_001), - PINMUX_DATA(LCD_DATA0_MARK, PJ0MD_010), + PINMUX_DATA(LCD_DATA0_PJ0_MARK, PJ0MD_010), PINMUX_DATA(SD_CD_MARK, PJ0MD_011), PINMUX_DATA(PWM1A_MARK, PJ0MD_100), }; @@ -1877,30 +1891,55 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK), PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA23, LCD_DATA23_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA22, LCD_DATA22_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA21, LCD_DATA21_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA20, LCD_DATA20_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA19, LCD_DATA19_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA18, LCD_DATA18_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA17, LCD_DATA17_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA16, LCD_DATA16_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA23_PG23, LCD_DATA23_PG23_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA22_PG22, LCD_DATA22_PG22_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA21_PG21, LCD_DATA21_PG21_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA20_PG20, LCD_DATA20_PG20_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA19_PG19, LCD_DATA19_PG19_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA18_PG18, LCD_DATA18_PG18_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA17_PG17, LCD_DATA17_PG17_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA16_PG16, LCD_DATA16_PG16_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA15_PG15, LCD_DATA15_PG15_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA14_PG14, LCD_DATA14_PG14_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA13_PG13, LCD_DATA13_PG13_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA12_PG12, LCD_DATA12_PG12_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA11_PG11, LCD_DATA11_PG11_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA10_PG10, LCD_DATA10_PG10_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA9_PG9, LCD_DATA9_PG9_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA8_PG8, LCD_DATA8_PG8_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA7_PG7, LCD_DATA7_PG7_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA6_PG6, LCD_DATA6_PG6_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA5_PG5, LCD_DATA5_PG5_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA4_PG4, LCD_DATA4_PG4_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA3_PG3, LCD_DATA3_PG3_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA2_PG2, LCD_DATA2_PG2_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA1_PG1, LCD_DATA1_PG1_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA0_PG0, LCD_DATA0_PG0_MARK), + + PINMUX_GPIO(GPIO_FN_LCD_DATA23_PJ23, LCD_DATA23_PJ23_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA22_PJ22, LCD_DATA22_PJ22_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA21_PJ21, LCD_DATA21_PJ21_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA20_PJ20, LCD_DATA20_PJ20_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA19_PJ19, LCD_DATA19_PJ19_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA18_PJ18, LCD_DATA18_PJ18_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA17_PJ17, LCD_DATA17_PJ17_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA16_PJ16, LCD_DATA16_PJ16_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA15_PJ15, LCD_DATA15_PJ15_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA14_PJ14, LCD_DATA14_PJ14_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA13_PJ13, LCD_DATA13_PJ13_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA12_PJ12, LCD_DATA12_PJ12_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA11_PJ11, LCD_DATA11_PJ11_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA10_PJ10, LCD_DATA10_PJ10_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA9_PJ9, LCD_DATA9_PJ9_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA8_PJ8, LCD_DATA8_PJ8_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA7_PJ7, LCD_DATA7_PJ7_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA6_PJ6, LCD_DATA6_PJ6_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA5_PJ5, LCD_DATA5_PJ5_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA4_PJ4, LCD_DATA4_PJ4_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA3_PJ3, LCD_DATA3_PJ3_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA2_PJ2, LCD_DATA2_PJ2_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA1_PJ1, LCD_DATA1_PJ1_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA0_PJ0, LCD_DATA0_PJ0_MARK), PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK), }; -- GitLab From 1026023705b0baa2b37df2a0d1da0022fc7b985e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 9 Aug 2012 12:59:40 +0900 Subject: [PATCH 5257/5711] sh: intc: Handle domain association for sparseirq pre-allocated vectors. Presently it's assumed that the irqdomain code handles the irq_desc allocation for us, but this isn't necessarily the case when we've pre-allocated IRQs via sparseirq. Previously we had a -EEXIST check in the code that attempted to trap these cases and simply update them in-place, but this behaviour was inadvertently lost in the transition to irqdomains. This simply restores the previous behaviour, first attempting to let the irqdomain core fetch the allocation for us, and falling back to an in-place domain association in the extant IRQ case. Fixes up regressions on platforms that pre-allocate legacy IRQs (specifically ARM-based SH-Mobile platforms, as SH stopped pre-allocating vectors some time ago). Reported-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/sh/intc/core.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 2374468615ed..32c26d795ed0 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -324,8 +324,16 @@ int __init register_intc_controller(struct intc_desc *desc) res = irq_create_identity_mapping(d->domain, irq); if (unlikely(res)) { - pr_err("can't get irq_desc for %d\n", irq); - continue; + if (res == -EEXIST) { + res = irq_domain_associate(d->domain, irq, irq); + if (unlikely(res)) { + pr_err("domain association failure\n"); + continue; + } + } else { + pr_err("can't identity map IRQ %d\n", irq); + continue; + } } intc_irq_xlate_set(irq, vect->enum_id, d); @@ -345,8 +353,19 @@ int __init register_intc_controller(struct intc_desc *desc) */ res = irq_create_identity_mapping(d->domain, irq2); if (unlikely(res)) { - pr_err("can't get irq_desc for %d\n", irq2); - continue; + if (res == -EEXIST) { + res = irq_domain_associate(d->domain, + irq, irq); + if (unlikely(res)) { + pr_err("domain association " + "failure\n"); + continue; + } + } else { + pr_err("can't identity map IRQ %d\n", + irq); + continue; + } } vect2->enum_id = 0; -- GitLab From 39f78e70567a07a6fc0d7a4ca9e3331e44dd400d Mon Sep 17 00:00:00 2001 From: Chris Brand Date: Tue, 7 Aug 2012 14:01:14 +0200 Subject: [PATCH 5258/5711] ARM: mm: fix MMU mapping of CMA regions Fix dma_contiguous_remap() so that it continues through all the regions, even after encountering one that is outside lowmem. Without this change, if you have two CMA regions, the first outside lowmem and the seocnd inside lowmem, only the second one will get set up in the MMU. Data written to that region then doesn't get automatically flushed from the cache into memory. Signed-off-by: Chris Brand [extended patch subject with 'fix' word] Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index c2cdf6500f75..334dd79ad5e6 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -358,7 +358,7 @@ void __init dma_contiguous_remap(void) if (end > arm_lowmem_limit) end = arm_lowmem_limit; if (start >= end) - return; + continue; map.pfn = __phys_to_pfn(start); map.virtual = __phys_to_virt(start); -- GitLab From e4ea6918c93b9f59d34e8ca2124b2b64b1afe73b Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 7 Aug 2012 14:39:25 +0200 Subject: [PATCH 5259/5711] ARM: dma-mapping: fix atomic allocation alignment The alignment mask is calculated incorrectly. Fixing the calculation makes strange hangs/lockups disappear during the boot with Amstrad E3 and 3.6-rc1 kernel. Signed-off-by: Aaro Koskinen Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 334dd79ad5e6..4bdeccd24d93 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -423,7 +423,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) unsigned int pageno; unsigned long flags; void *ptr = NULL; - size_t align; + unsigned long align_mask; if (!pool->vaddr) { WARN(1, "coherent pool not initialised!\n"); @@ -435,11 +435,11 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) * small, so align them to their order in pages, minimum is a page * size. This helps reduce fragmentation of the DMA space. */ - align = PAGE_SIZE << get_order(size); + align_mask = (1 << get_order(size)) - 1; spin_lock_irqsave(&pool->lock, flags); pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages, - 0, count, (1 << align) - 1); + 0, count, align_mask); if (pageno < pool->nr_pages) { bitmap_set(pool->bitmap, pageno, count); ptr = pool->vaddr + PAGE_SIZE * pageno; -- GitLab From d9e0d149b5dcc2ef4688afc572b9906bcda941ef Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 7 Aug 2012 14:44:05 +0200 Subject: [PATCH 5260/5711] ARM: dma-mapping: fix incorrect freeing of atomic allocations Commit e9da6e9905e639b0f842a244bc770b48ad0523e9 (ARM: dma-mapping: remove custom consistent dma region) changed the way atomic allocations are handled. However, arm_dma_free() was not modified accordingly, and as a result freeing of atomic allocations does not work correctly when CMA is disabled. Memory is leaked and following WARNINGs are seen: [ 57.698911] ------------[ cut here ]------------ [ 57.753518] WARNING: at arch/arm/mm/dma-mapping.c:263 arm_dma_free+0x88/0xe4() [ 57.811473] trying to free invalid coherent area: e0848000 [ 57.867398] Modules linked in: sata_mv(-) [ 57.921373] [] (unwind_backtrace+0x0/0xf0) from [] (warn_slowpath_common+0x50/0x68) [ 58.033924] [] (warn_slowpath_common+0x50/0x68) from [] (warn_slowpath_fmt+0x30/0x40) [ 58.152024] [] (warn_slowpath_fmt+0x30/0x40) from [] (arm_dma_free+0x88/0xe4) [ 58.219592] [] (arm_dma_free+0x88/0xe4) from [] (dma_pool_destroy+0x100/0x148) [ 58.345526] [] (dma_pool_destroy+0x100/0x148) from [] (release_nodes+0x144/0x218) [ 58.475782] [] (release_nodes+0x144/0x218) from [] (__device_release_driver+0x60/0xb8) [ 58.614260] [] (__device_release_driver+0x60/0xb8) from [] (driver_detach+0xd8/0xec) [ 58.756527] [] (driver_detach+0xd8/0xec) from [] (bus_remove_driver+0x7c/0xc4) [ 58.901648] [] (bus_remove_driver+0x7c/0xc4) from [] (sys_delete_module+0x19c/0x220) [ 59.051447] [] (sys_delete_module+0x19c/0x220) from [] (ret_fast_syscall+0x0/0x2c) [ 59.207996] ---[ end trace 0745420412c0325a ]--- [ 59.287110] ------------[ cut here ]------------ [ 59.366324] WARNING: at arch/arm/mm/dma-mapping.c:263 arm_dma_free+0x88/0xe4() [ 59.450511] trying to free invalid coherent area: e0847000 [ 59.534357] Modules linked in: sata_mv(-) [ 59.616785] [] (unwind_backtrace+0x0/0xf0) from [] (warn_slowpath_common+0x50/0x68) [ 59.790030] [] (warn_slowpath_common+0x50/0x68) from [] (warn_slowpath_fmt+0x30/0x40) [ 59.972322] [] (warn_slowpath_fmt+0x30/0x40) from [] (arm_dma_free+0x88/0xe4) [ 60.070701] [] (arm_dma_free+0x88/0xe4) from [] (dma_pool_destroy+0x100/0x148) [ 60.256817] [] (dma_pool_destroy+0x100/0x148) from [] (release_nodes+0x144/0x218) [ 60.445201] [] (release_nodes+0x144/0x218) from [] (__device_release_driver+0x60/0xb8) [ 60.634148] [] (__device_release_driver+0x60/0xb8) from [] (driver_detach+0xd8/0xec) [ 60.823623] [] (driver_detach+0xd8/0xec) from [] (bus_remove_driver+0x7c/0xc4) [ 61.013268] [] (bus_remove_driver+0x7c/0xc4) from [] (sys_delete_module+0x19c/0x220) [ 61.203472] [] (sys_delete_module+0x19c/0x220) from [] (ret_fast_syscall+0x0/0x2c) [ 61.393390] ---[ end trace 0745420412c0325b ]--- The patch fixes this. Signed-off-by: Aaro Koskinen Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 4bdeccd24d93..4e7d1182e8a3 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -648,12 +648,12 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr, if (arch_is_coherent() || nommu()) { __dma_free_buffer(page, size); + } else if (__free_from_pool(cpu_addr, size)) { + return; } else if (!IS_ENABLED(CONFIG_CMA)) { __dma_free_remap(cpu_addr, size); __dma_free_buffer(page, size); } else { - if (__free_from_pool(cpu_addr, size)) - return; /* * Non-atomic allocations cannot be freed with IRQs disabled */ -- GitLab From 94c142a160d63edac0e1fca7848960dcf75dd2a9 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 9 Aug 2012 10:56:12 +0200 Subject: [PATCH 5261/5711] ALSA: hda - Fix pop noise in headphones on S3 for Asus X55A, X55V To turn off pin control for the pin was tested, and helped against this issue. BugLink: https://bugs.launchpad.net/bugs/1034779 Tested-by: Chih-Hsyuan Ho Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 80d90cb42853..430771776915 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1752,6 +1752,14 @@ static int via_suspend(struct hda_codec *codec) { struct via_spec *spec = codec->spec; vt1708_stop_hp_work(spec); + + if (spec->codec_type == VT1802) { + /* Fix pop noise on headphones */ + int i; + for (i = 0; i < spec->autocfg.hp_outs; i++) + snd_hda_set_pin_ctl(codec, spec->autocfg.hp_pins[i], 0); + } + return 0; } #endif -- GitLab From 36471012e2ae28ca3178f84d4687a2d88a36593e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 9 Aug 2012 11:19:13 +0200 Subject: [PATCH 5262/5711] tcp: must free metrics at net dismantle We currently leak all tcp metrics at struct net dismantle time. tcp_net_metrics_exit() frees the hash table, we must first iterate it to free all metrics. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_metrics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 2288a6399e1e..0abe67bb4d3a 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -731,6 +731,18 @@ static int __net_init tcp_net_metrics_init(struct net *net) static void __net_exit tcp_net_metrics_exit(struct net *net) { + unsigned int i; + + for (i = 0; i < (1U << net->ipv4.tcp_metrics_hash_log) ; i++) { + struct tcp_metrics_block *tm, *next; + + tm = rcu_dereference_protected(net->ipv4.tcp_metrics_hash[i].chain, 1); + while (tm) { + next = rcu_dereference_protected(tm->tcpm_next, 1); + kfree(tm); + tm = next; + } + } kfree(net->ipv4.tcp_metrics_hash); } -- GitLab From b669588abaceb5c6d70699b6c009e5cedc42449b Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 28 Jul 2012 05:07:48 +0000 Subject: [PATCH 5263/5711] igb: fix panic while dumping packets on Tx hang with IOMMU This patch resolves a "BUG: unable to handle kernel paging request at ..." oops while dumping packet data. The issue occurs with IOMMU enabled due to the address provided by phys_to_virt(). This patch avoids phys_to_virt() by making using skb->data and the address of the pages allocated for Rx. Signed-off-by: Emil Tantilov Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/igb_main.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b7c2d5050572..48cc4fb1a307 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -462,10 +462,10 @@ static void igb_dump(struct igb_adapter *adapter) (u64)buffer_info->time_stamp, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) + if (netif_msg_pktdata(adapter) && buffer_info->skb) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, phys_to_virt(buffer_info->dma), + 16, 1, buffer_info->skb->data, buffer_info->length, true); } } @@ -547,18 +547,17 @@ rx_ring_summary: (u64)buffer_info->dma, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter)) { + if (netif_msg_pktdata(adapter) && + buffer_info->dma && buffer_info->skb) { print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, - 16, 1, - phys_to_virt(buffer_info->dma), - IGB_RX_HDR_LEN, true); + DUMP_PREFIX_ADDRESS, + 16, 1, buffer_info->skb->data, + IGB_RX_HDR_LEN, true); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, - phys_to_virt( - buffer_info->page_dma + - buffer_info->page_offset), + page_address(buffer_info->page) + + buffer_info->page_offset, PAGE_SIZE/2, true); } } -- GitLab From f0c5dadff3fbda77a65b8577fee437c3d771233d Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 1 Aug 2012 08:12:21 +0000 Subject: [PATCH 5264/5711] e1000e: fix panic while dumping packets on Tx hang with IOMMU This patch resolves a "BUG: unable to handle kernel paging request at ..." oops while dumping packet data. The issue occurs with IOMMU enabled due to the address provided by phys_to_virt(). This patch avoids phys_to_virt() by using skb->data and the address of the pages allocated for Rx. Signed-off-by: Emil Tantilov Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/e1000e/netdev.c | 36 ++++++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 95b245310f17..46c3b1f9ff89 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -178,6 +178,24 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]); } +static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, + struct e1000_buffer *bi) +{ + int i; + struct e1000_ps_page *ps_page; + + for (i = 0; i < adapter->rx_ps_pages; i++) { + ps_page = &bi->ps_pages[i]; + + if (ps_page->page) { + pr_info("packet dump for ps_page %d:\n", i); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, + 16, 1, page_address(ps_page->page), + PAGE_SIZE, true); + } + } +} + /* * e1000e_dump - Print registers, Tx-ring and Rx-ring */ @@ -299,10 +317,10 @@ static void e1000e_dump(struct e1000_adapter *adapter) (unsigned long long)buffer_info->time_stamp, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) + if (netif_msg_pktdata(adapter) && buffer_info->skb) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, phys_to_virt(buffer_info->dma), - buffer_info->length, true); + 16, 1, buffer_info->skb->data, + buffer_info->skb->len, true); } /* Print Rx Ring Summary */ @@ -381,10 +399,8 @@ rx_ring_summary: buffer_info->skb, next_desc); if (netif_msg_pktdata(adapter)) - print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, 16, 1, - phys_to_virt(buffer_info->dma), - adapter->rx_ps_bsize0, true); + e1000e_dump_ps_pages(adapter, + buffer_info); } } break; @@ -444,12 +460,12 @@ rx_ring_summary: (unsigned long long)buffer_info->dma, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter)) + if (netif_msg_pktdata(adapter) && + buffer_info->skb) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, - phys_to_virt - (buffer_info->dma), + buffer_info->skb->data, adapter->rx_buffer_len, true); } -- GitLab From a2d6a1d5a435b051d3660961d5dee5b33b15f754 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 8 Aug 2012 05:18:04 +0000 Subject: [PATCH 5265/5711] igb: Fix register defines for all non-82575 hardware It looks like the register defines for DCA were never updated after going from 82575 to 82576. This change addresses that by updating the defines. Signed-off-by: Alexander Duyck Tested-by: Jeff Pieper Signed-off-by: Peter P Waskiewicz Jr --- drivers/net/ethernet/intel/igb/e1000_regs.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h index 10efcd88dca0..28394bea5253 100644 --- a/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -156,8 +156,12 @@ : (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \ : (0x0E028 + ((_n) * 0x40))) -#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) -#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) +#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ + (0x0C014 + ((_n) * 0x40))) +#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) +#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ + (0x0E014 + ((_n) * 0x40))) +#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \ : (0x0E038 + ((_n) * 0x40))) #define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \ -- GitLab From e76ab829cc2d8b6350a3f01fffb208df4d7d8c1b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Aug 2012 15:51:44 +0100 Subject: [PATCH 5266/5711] regulator: twl: Remove references to the twl4030 regulator It's not referenced anywhere any more and the compiler notices. Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 242fe90dc565..30cb62289b74 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1048,7 +1048,6 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); -TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0); TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); -- GitLab From 0d624275720a4b01217693eb80d967a0d5f1f3a3 Mon Sep 17 00:00:00 2001 From: Vaibhav Bedia Date: Wed, 8 Aug 2012 20:40:31 +0530 Subject: [PATCH 5267/5711] ASoC: Davinci: McASP: Flush the FIFO before enabling FIFO should be flushed before it is enabled for the first time. This fixes the I/O errors reported by the ASoC core on a fresh boot Signed-off-by: Vaibhav Bedia Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 95441bfc8190..ce5e5cd254dd 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -380,14 +380,20 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* enable FIFO */ + if (dev->txnumevt) { /* enable FIFO */ + mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + FIFO_ENABLE); mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + } mcasp_start_tx(dev); } else { - if (dev->rxnumevt) /* enable FIFO */ + if (dev->rxnumevt) { /* enable FIFO */ + mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + FIFO_ENABLE); mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } mcasp_start_rx(dev); } } -- GitLab From 8b5eae137b91cb2db15fe2c5a913cafde4629339 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Thu, 9 Aug 2012 18:08:40 -0400 Subject: [PATCH 5268/5711] ASoC: bfin: fix memory leak in sport3 controller driver Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- sound/soc/blackfin/bf6xx-sport.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/blackfin/bf6xx-sport.c b/sound/soc/blackfin/bf6xx-sport.c index 318c5ba5360f..dfb744381c42 100644 --- a/sound/soc/blackfin/bf6xx-sport.c +++ b/sound/soc/blackfin/bf6xx-sport.c @@ -413,7 +413,14 @@ EXPORT_SYMBOL(sport_create); void sport_delete(struct sport_device *sport) { + if (sport->tx_desc) + dma_free_coherent(NULL, sport->tx_desc_size, + sport->tx_desc, 0); + if (sport->rx_desc) + dma_free_coherent(NULL, sport->rx_desc_size, + sport->rx_desc, 0); sport_free_resource(sport); + kfree(sport); } EXPORT_SYMBOL(sport_delete); -- GitLab From 52c0eee3329b08dfd912a59e0246e21026308301 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Jul 2012 18:23:35 +0100 Subject: [PATCH 5269/5711] ASoC: wm8962: Don't duplicate bias level management in resume The core will bring the bias level up for us since we use idle_bias_off, duplicating this may be harmful. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index aa9ce9dd7d8a..ce6720073798 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3733,21 +3733,6 @@ static int wm8962_runtime_resume(struct device *dev) regcache_sync(wm8962->regmap); - regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, - WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, - WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); - - /* Bias enable at 2*50k for ramp */ - regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, - WM8962_BIAS_ENA | 0x180); - - msleep(5); - - /* VMID back to 2x250k for standby */ - regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK, 0x100); - return 0; } -- GitLab From 798bd59ce94c8218332996e650ded48ded039fe1 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 3 Aug 2012 17:45:21 -0600 Subject: [PATCH 5270/5711] ARM: tegra: more regulator fixes for Harmony Commit 3d55c29 "ARM: tegra: harmony: add regulator supply name and its input supply" was supposed to fix all the problems with regulators on Harmony. However, it appears that I only tested it when booting using board files, not when booting using device tree. This change fixes two problems with regulators when booting using device tree: 1) That patch only created the vdd_sys regulator when booting using a board file. Since this is the root of the whole regulator tree, this caused no regulators to successfully initialize when booting using device tree. The registration of vdd_sys is moved to fix this. 2) When booting use DT, the regulator core sets has_full_constraints, which in turn causes the core to turn off any regulators not marked as always on. Some of the affected regulators are required for basic system operation. To solve this, add always on constraints to all relevant regulators. This doesn't affect booting using a board file since nothing sets has_full_constraints in that case. Signed-off-by: Stephen Warren Signed-off-by: Arnd Bergmann --- arch/arm/mach-tegra/board-harmony-power.c | 32 ++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index 8fd387bf31f0..b7344beec102 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -51,7 +51,7 @@ static struct regulator_init_data ldo0_data = { .consumer_supplies = tps658621_ldo0_supply, }; -#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv) \ +#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv, _on)\ static struct regulator_init_data _id##_data = { \ .supply_regulator = _supply, \ .constraints = { \ @@ -63,21 +63,22 @@ static struct regulator_init_data ldo0_data = { .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ REGULATOR_CHANGE_STATUS | \ REGULATOR_CHANGE_VOLTAGE), \ + .always_on = _on, \ }, \ } -HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500); -HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500); -HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550); -HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500); -HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500); -HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475); -HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300); -HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1); +HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1); +HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1); +HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1); +HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); +HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); +HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); +HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300, 1); +HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1); #define TPS_REG(_id, _data) \ { \ @@ -119,9 +120,10 @@ static struct i2c_board_info __initdata harmony_regulators[] = { int __init harmony_regulator_init(void) { + regulator_register_always_on(0, "vdd_sys", + NULL, 0, 5000000); + if (machine_is_harmony()) { - regulator_register_always_on(0, "vdd_sys", - NULL, 0, 5000000); i2c_register_board_info(3, harmony_regulators, 1); } else { /* Harmony, booted using device tree */ struct device_node *np; -- GitLab From 59ee93a528b94ef4e81a08db252b0326feff171f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 5 Aug 2012 14:58:37 +0000 Subject: [PATCH 5271/5711] ARM: pxa: remove irq_to_gpio from ezx-pcap driver The irq_to_gpio function was removed from the pxa platform in linux-3.2, and this driver has been broken since. There is actually no in-tree user of this driver that adds this platform device, but the driver can and does get enabled on some platforms. Without this patch, building ezx_defconfig results in: drivers/mfd/ezx-pcap.c: In function 'pcap_isr_work': drivers/mfd/ezx-pcap.c:205:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] Signed-off-by: Arnd Bergmann Acked-by: Haojian Zhuang Cc: stable@vger.kernel.org (v3.2+) Cc: Samuel Ortiz Cc: Daniel Ribeiro --- drivers/mfd/ezx-pcap.c | 2 +- include/linux/mfd/ezx-pcap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 43a76c41cfcc..db662e2dcfa5 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work) } local_irq_enable(); ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); - } while (gpio_get_value(irq_to_gpio(pcap->spi->irq))); + } while (gpio_get_value(pdata->gpio)); } static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 40c372165f3e..32a1b5cfeba1 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h @@ -16,6 +16,7 @@ struct pcap_subdev { struct pcap_platform_data { unsigned int irq_base; unsigned int config; + int gpio; void (*init) (void *); /* board specific init */ int num_subdevs; struct pcap_subdev *subdevs; -- GitLab From 4eef6cbfcc03b294d9d334368a851b35b496ce53 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 16:21:37 +0000 Subject: [PATCH 5272/5711] Input: eeti_ts: pass gpio value instead of IRQ The EETI touchscreen asserts its IRQ line as soon as it has data in its internal buffers. The line is automatically deasserted once all data has been read via I2C. Hence, the driver has to monitor the GPIO line and cannot simply rely on the interrupt handler reception. In the current implementation of the driver, irq_to_gpio() is used to determine the GPIO number from the i2c_client's IRQ value. As irq_to_gpio() is not available on all platforms, this patch changes this and makes the driver ignore the passed in IRQ. Instead, a GPIO is added to the platform_data struct and gpio_to_irq is used to derive the IRQ from that GPIO. If this fails, bail out. The driver is only able to work in environments where the touchscreen GPIO can be mapped to an IRQ. Without this patch, building raumfeld_defconfig results in: drivers/input/touchscreen/eeti_ts.c: In function 'eeti_ts_irq_active': drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] Signed-off-by: Daniel Mack Signed-off-by: Arnd Bergmann Cc: stable@vger.kernel.org (v3.2+) Cc: Dmitry Torokhov Cc: Sven Neumann Cc: linux-input@vger.kernel.org Cc: Haojian Zhuang --- arch/arm/mach-pxa/raumfeld.c | 2 +- drivers/input/touchscreen/eeti_ts.c | 21 +++++++++++++-------- include/linux/input/eeti_ts.h | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 5905ed130e94..d89d87ae144c 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -953,12 +953,12 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, + .irq_gpio = GPIO_TOUCH_IRQ, }; static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, - .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 503c7096ed36..908407efc672 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -48,7 +48,7 @@ struct eeti_ts_priv { struct input_dev *input; struct work_struct work; struct mutex mutex; - int irq, irq_active_high; + int irq_gpio, irq, irq_active_high; }; #define EETI_TS_BITDEPTH (11) @@ -62,7 +62,7 @@ struct eeti_ts_priv { static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) { - return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; + return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; } static void eeti_ts_read(struct work_struct *work) @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int __devinit eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata; + struct eeti_ts_platform_data *pdata = client->dev.platform_data; struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; @@ -199,9 +199,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->irq = client->irq; + priv->irq_gpio = pdata->irq_gpio; + priv->irq = gpio_to_irq(pdata->irq_gpio); - pdata = client->dev.platform_data; + err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); + if (err < 0) + goto err1; if (pdata) priv->irq_active_high = pdata->irq_active_high; @@ -215,13 +218,13 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, err = input_register_device(input); if (err) - goto err1; + goto err2; err = request_irq(priv->irq, eeti_ts_isr, irq_flags, client->name, priv); if (err) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err2; + goto err3; } /* @@ -233,9 +236,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, device_init_wakeup(&client->dev, 0); return 0; -err2: +err3: input_unregister_device(input); input = NULL; /* so we dont try to free it below */ +err2: + gpio_free(pdata->irq_gpio); err1: input_free_device(input); kfree(priv); diff --git a/include/linux/input/eeti_ts.h b/include/linux/input/eeti_ts.h index f875b316249d..16625d799b6f 100644 --- a/include/linux/input/eeti_ts.h +++ b/include/linux/input/eeti_ts.h @@ -2,6 +2,7 @@ #define LINUX_INPUT_EETI_TS_H struct eeti_ts_platform_data { + int irq_gpio; unsigned int irq_active_high; }; -- GitLab From 9c97738c5d3378e8ee525ff7f9fc160be3c8ed92 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 04:59:34 +0000 Subject: [PATCH 5273/5711] ARM: sa1100: include linux/io.h in hackkit leds code The sa1100 definition of the io_p2v macro has changed in v3.6, and this one file stopped working because of that. Without this patch, building hackkit_defconfig results in: arch/arm/mach-sa1100/leds-hackkit.c: In function 'hackkit_leds_event': arch/arm/mach-sa1100/leds-hackkit.c:39:4: error: implicit declaration of function 'IOMEM' [-Werror=implicit-function-declaration] Signed-off-by: Arnd Bergmann Cc: Russell King --- arch/arm/mach-sa1100/leds-hackkit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-sa1100/leds-hackkit.c b/arch/arm/mach-sa1100/leds-hackkit.c index 6a2352436e62..f8e47235babe 100644 --- a/arch/arm/mach-sa1100/leds-hackkit.c +++ b/arch/arm/mach-sa1100/leds-hackkit.c @@ -10,6 +10,7 @@ * as cpu led, the green one is used as timer led. */ #include +#include #include #include -- GitLab From 35e7906145d6d487002b738271890a7e7936067e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 07:52:19 +0000 Subject: [PATCH 5274/5711] ARM: s3c24xx: use new PWM driver The samsung PWM driver has moved to the new PWM subsystem, which changed the Kconfig symbol for that driver, but the rx1950 and gta02 boards still uses the old one. Without this patch, building s3c2410_defconfig results in: arch/arm/mach-s3c24xx/built-in.o: In function `rx1950_lcd_power': arch/arm/mach-s3c24xx/mach-rx1950.c:430: undefined reference to `pwm_config' arch/arm/mach-s3c24xx/mach-rx1950.c:431: undefined reference to `pwm_disable' arch/arm/mach-s3c24xx/mach-rx1950.c:437: undefined reference to `pwm_config' arch/arm/mach-s3c24xx/mach-rx1950.c:438: undefined reference to `pwm_enable' arch/arm/mach-s3c24xx/built-in.o: In function `rx1950_backlight_exit': arch/arm/mach-s3c24xx/mach-rx1950.c:504: undefined reference to `pwm_free' arch/arm/mach-s3c24xx/built-in.o: In function `rx1950_backlight_init': arch/arm/mach-s3c24xx/mach-rx1950.c:487: undefined reference to `pwm_request' Signed-off-by: Arnd Bergmann Reported-by: Tushar Behera Cc: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 4 ++-- arch/arm/plat-samsung/Kconfig | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index e24961109b70..d56b0f7f2b20 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -483,7 +483,7 @@ config MACH_NEO1973_GTA02 select I2C select POWER_SUPPLY select MACH_NEO1973 - select S3C2410_PWM + select S3C24XX_PWM select S3C_DEV_USB_HOST help Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone @@ -493,7 +493,7 @@ config MACH_RX1950 select S3C24XX_DCLK select PM_H1940 if PM select I2C - select S3C2410_PWM + select S3C24XX_PWM select S3C_DEV_NAND select S3C2410_IOTIMING if S3C2440_CPUFREQ select S3C2440_XTAL_16934400 diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 7aca31c1df1f..9c3b90c3538e 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -403,7 +403,8 @@ config S5P_DEV_USB_EHCI config S3C24XX_PWM bool "PWM device support" - select HAVE_PWM + select PWM + select PWM_SAMSUNG help Support for exporting the PWM timer blocks via the pwm device system -- GitLab From b434f5c95d2d9318482fda3af615ebcda7e2c0da Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 10:31:24 +0000 Subject: [PATCH 5275/5711] ARM: integrator: include Without this patch, building integrator_defconfig results in: arch/arm/mach-integrator/core.c:150:1: warning: data definition has no type or storage class [enabled by default] arch/arm/mach-integrator/core.c:150:1: warning: type defaults to 'int' in declaration of 'EXPORT_SYMBOL' [-Wimplicit-int] arch/arm/mach-integrator/core.c:150:1: warning: parameter names (without types) in function declaration [enabled by default] Signed-off-by: Arnd Bergmann Acked-by: Linus Walleij Cc: Russell King --- arch/arm/mach-integrator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index ebf680bebdf2..3fa6c51390da 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include -- GitLab From a33493775dd141a99bcd2aac9a5b6b7e8385b5a4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 10:48:12 +0000 Subject: [PATCH 5276/5711] ARM: imx: gpmi-nand depends on mxs-dma It is not currently possible to build the gpmi-nand driver without also building the mxs-dma driver. Clarify this Kconfig and enable both in the defconfig file so we can build it again with both enabled. drivers/built-in.o: In function `gpmi_dma_filter': clk-fixed-factor.c:(.text+0xafc18): undefined reference to `mxs_dma_is_apbh' make[1]: *** [vmlinux] Error 1 make: *** [sub-make] Error 2 Signed-off-by: Arnd Bergmann Acked-by: Dirk Behme Cc: Shawn Guo Cc: Sascha Hauer --- arch/arm/configs/imx_v6_v7_defconfig | 1 + drivers/mtd/nand/Kconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index f725b9637b33..3c9f32f9b6b4 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -192,6 +192,7 @@ CONFIG_RTC_DRV_MC13XXX=y CONFIG_RTC_DRV_MXC=y CONFIG_DMADEVICES=y CONFIG_IMX_SDMA=y +CONFIG_MXS_DMA=y CONFIG_COMMON_CLK_DEBUG=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT2_FS=y diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 31bb7e5b504a..8ca417614c57 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -480,7 +480,7 @@ config MTD_NAND_NANDSIM config MTD_NAND_GPMI_NAND bool "GPMI NAND Flash Controller driver" - depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) + depends on MTD_NAND && MXS_DMA help Enables NAND Flash support for IMX23 or IMX28. The GPMI controller is very powerful, with the help of BCH -- GitLab From 15676937e6a7e98d37f4c1eaa0e7b3c111627fce Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Thu, 9 Aug 2012 10:10:54 +0100 Subject: [PATCH 5277/5711] ASoC: wm8994: Add missing dapm routes for WM8958 rev A Signed-off-by: Chris Rattray Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 04ef03175c51..6c9eeca85b95 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4038,6 +4038,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) break; case WM8958: if (wm8994->revision < 1) { + snd_soc_dapm_add_routes(dapm, wm8994_intercon, + ARRAY_SIZE(wm8994_intercon)); snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, ARRAY_SIZE(wm8994_revd_intercon)); snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, -- GitLab From d34e4e00adbbc91ff9fc96ed9a4e4b65161868da Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 9 Aug 2012 15:47:15 +0200 Subject: [PATCH 5278/5711] ALSA: platform: Check CONFIG_PM_SLEEP instead of CONFIG_PM When CONFIG_PM is set but CONFIG_PM_SLEEP is unset, SIMPLE_DEV_PM_OPS() ignores the given functions, and this leads to compile warnings. For avoiding this, simply check CONFIG_PM_SLEEP instead of CONFIG_PM. Reported-by: Arnd Bergmann Signed-off-by: Takashi Iwai --- sound/arm/pxa2xx-ac97.c | 4 ++-- sound/atmel/abdac.c | 2 +- sound/atmel/ac97c.c | 2 +- sound/drivers/aloop.c | 2 +- sound/drivers/dummy.c | 2 +- sound/drivers/pcsp/pcsp.c | 4 ++-- sound/ppc/powermac.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 0d7b25e81643..4e1fda75c1c9 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -106,7 +106,7 @@ static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = { .prepare = pxa2xx_ac97_pcm_prepare, }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int pxa2xx_ac97_do_suspend(struct snd_card *card) { @@ -243,7 +243,7 @@ static struct platform_driver pxa2xx_ac97_driver = { .driver = { .name = "pxa2xx-ac97", .owner = THIS_MODULE, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .pm = &pxa2xx_ac97_pm_ops, #endif }, diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index eb4ceb71123e..98554f4882b7 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -534,7 +534,7 @@ out_put_pclk: return retval; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int atmel_abdac_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index bf47025bdf45..3c8d3ba7ddfc 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -1134,7 +1134,7 @@ err_snd_card_new: return retval; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int atmel_ac97c_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 1128b35b2b05..5a34355e78e8 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1176,7 +1176,7 @@ static int __devexit loopback_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int loopback_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index f7d3bfc6bca8..54bb6644a598 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -1064,7 +1064,7 @@ static int __devexit snd_dummy_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int snd_dummy_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 6ca59fc6dcb9..ef171295f6d4 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -199,7 +199,7 @@ static void pcsp_stop_beep(struct snd_pcsp *chip) pcspkr_stop_sound(); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int pcsp_suspend(struct device *dev) { struct snd_pcsp *chip = dev_get_drvdata(dev); @@ -212,7 +212,7 @@ static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL); #define PCSP_PM_OPS &pcsp_pm #else #define PCSP_PM_OPS NULL -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ static void pcsp_shutdown(struct platform_device *dev) { diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index f5ceb6f282de..210cafe04890 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -143,7 +143,7 @@ static int __devexit snd_pmac_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int snd_pmac_driver_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); -- GitLab From e00da2067b78a9246f767012a3803224c40b1f9f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 2 Aug 2012 17:16:20 -0600 Subject: [PATCH 5279/5711] Btrfs: remove mnt_want_write call in btrfs_mksubvol We got a recursive lock in mksubvol because the caller already held a lock. I think we got into this due to a merge error. Commit a874a63 removed the mnt_want_write call from btrfs_mksubvol and added a replacement call to mnt_want_write_file in btrfs_ioctl_snap_create_transid. Commit e7848683 however tried to move all calls to mnt_want_write above i_mutex. So somewhere while merging this, it got mixed up. The solution is to remove the mnt_want_write call completely from mksubvol. Reported-by: David Sterba Signed-off-by: Alexander Block Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bc2f6ffff3cf..7bb755677a22 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -664,10 +664,6 @@ static noinline int btrfs_mksubvol(struct path *parent, struct dentry *dentry; int error; - error = mnt_want_write(parent->mnt); - if (error) - return error; - mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(name, parent->dentry, namelen); @@ -703,7 +699,6 @@ out_dput: dput(dentry); out_unlock: mutex_unlock(&dir->i_mutex); - mnt_drop_write(parent->mnt); return error; } -- GitLab From 144dad99ef6ad10c8c8ebe787d08157c4a94201f Mon Sep 17 00:00:00 2001 From: James Ralston Date: Thu, 9 Aug 2012 09:38:59 -0700 Subject: [PATCH 5280/5711] ALSA: hda_intel: Add Device IDs for Intel Lynx Point-LP PCH This patch adds the Intel HD Audio Device IDs for the Intel Lynx Point-LP PCH Signed-off-by: James Ralston Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c8aced182fd1..60882c62f180 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -151,6 +151,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, CPT}," "{Intel, PPT}," "{Intel, LPT}," + "{Intel, LPT_LP}," "{Intel, HPT}," "{Intel, PBG}," "{Intel, SCH}," @@ -3270,6 +3271,14 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + /* Lynx Point-LP */ + { PCI_DEVICE(0x8086, 0x9c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + /* Lynx Point-LP */ + { PCI_DEVICE(0x8086, 0x9c21), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0c0c), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | -- GitLab From fb099cb712e878b9eb4e78dd6b268312a0b2b50f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 18:44:37 +0100 Subject: [PATCH 5281/5711] ASoC: core: Upgrade the severity of probe deferral errors to dev_err() In the past when ASoC had a custom probe deferral mechanism people complained about the logspam it generated and didn't want to know about the fact that we were doing probe deferral so all the error messages for it were at dev_dbg(), making diagnostics hard. Now that we have probe deferral as an accepted thing and it's generating log messages anyway there's no need to worry about this so upgrade the severity of all the probe deferral sources to dev_err() so that they are displayed by default. Also add one for missing aux_devs since there wasn't one. Reported-by: Russell King Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f81c5976b961..c501af6d8dbe 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -826,7 +826,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) } if (!rtd->cpu_dai) { - dev_dbg(card->dev, "CPU DAI %s not registered\n", + dev_err(card->dev, "CPU DAI %s not registered\n", dai_link->cpu_dai_name); return -EPROBE_DEFER; } @@ -857,14 +857,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) } if (!rtd->codec_dai) { - dev_dbg(card->dev, "CODEC DAI %s not registered\n", + dev_err(card->dev, "CODEC DAI %s not registered\n", dai_link->codec_dai_name); return -EPROBE_DEFER; } } if (!rtd->codec) { - dev_dbg(card->dev, "CODEC %s not registered\n", + dev_err(card->dev, "CODEC %s not registered\n", dai_link->codec_name); return -EPROBE_DEFER; } @@ -888,7 +888,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) rtd->platform = platform; } if (!rtd->platform) { - dev_dbg(card->dev, "platform %s not registered\n", + dev_err(card->dev, "platform %s not registered\n", dai_link->platform_name); return -EPROBE_DEFER; } @@ -1481,6 +1481,8 @@ static int soc_check_aux_dev(struct snd_soc_card *card, int num) return 0; } + dev_err(card->dev, "%s not registered\n", aux_dev->codec_name); + return -EPROBE_DEFER; } -- GitLab From b2a1ef473b031b630a26685c91a46b9ae668d35c Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 9 Aug 2012 16:33:00 +0200 Subject: [PATCH 5282/5711] regulator: core: request only valid gpio pins for regulator enable Commit 65f735082de3 ("regulator: core: Add core support for GPIO controlled enable lines") introduced enable gpio entry in regulator configuration structure. Some drivers use '-1' as a placeholder for marking that such gpio line is not available, because '0' is considered as a valid gpio number. This patch fixes initialization of such drivers (like MAX8952 on UniversalC210 board), when '-1' is provided as enable gpio pin in the regulator's platform data. Signed-off-by: Marek Szyprowski Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f092588a078c..48385318175a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3217,7 +3217,7 @@ regulator_register(const struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); - if (config->ena_gpio) { + if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { ret = gpio_request_one(config->ena_gpio, GPIOF_DIR_OUT | config->ena_gpio_flags, rdev_get_name(rdev)); -- GitLab From e95829f474f0db3a4d940cae1423783edd966027 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 23 Jul 2012 18:59:30 +0300 Subject: [PATCH 5283/5711] xhci: Switch PPT ports to EHCI on shutdown. The Intel desktop boards DH77EB and DH77DF have a hardware issue that can be worked around by BIOS. If the USB ports are switched to xHCI on shutdown, the xHCI host will send a spurious interrupt, which will wake the system. Some BIOS will work around this, but not all. The bug can be avoided if the USB ports are switched back to EHCI on shutdown. The Intel Windows driver switches the ports back to EHCI, so change the Linux xHCI driver to do the same. Unfortunately, we can't tell the two effected boards apart from other working motherboards, because the vendors will change the DMI strings for the DH77EB and DH77DF boards to their own custom names. One example is Compulab's mini-desktop, the Intense-PC. Instead, key off the Panther Point xHCI host PCI vendor and device ID, and switch the ports over for all PPT xHCI hosts. The only impact this will have on non-effected boards is to add a couple hundred milliseconds delay on boot when the BIOS has to switch the ports over from EHCI to xHCI. This patch should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Sarah Sharp Reported-by: Denis Turischev Tested-by: Denis Turischev Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 7 +++++++ drivers/usb/host/pci-quirks.h | 1 + drivers/usb/host/xhci-pci.c | 9 +++++++++ drivers/usb/host/xhci.c | 3 +++ drivers/usb/host/xhci.h | 1 + 5 files changed, 21 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index df0828cb2aa3..c5e9e4a76f14 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) } EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) +{ + pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); + pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); +} +EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); + /** * PCI Quirks for xHCI. * diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b1002a8ef96f..ef004a5de20f 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void); void usb_amd_quirk_pll_enable(void); bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); #else static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 92eaff6097c0..9bfd4ca1153c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -94,6 +94,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; xhci->quirks |= XHCI_SW_BW_CHECKING; + /* + * PPT desktop boards DH77EB and DH77DF will power back on after + * a few seconds of being shutdown. The fix for this is to + * switch the ports from xHCI to EHCI on shutdown. We can't use + * DMI information to find those particular boards (since each + * vendor will change the board name), so we have to key off all + * PPT chipsets. + */ + xhci->quirks |= XHCI_SPURIOUS_REBOOT; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5c3a3f75e4d5..c59d5b5b6c7d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -659,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + if (xhci->quirks && XHCI_SPURIOUS_REBOOT) + usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); + spin_lock_irq(&xhci->lock); xhci_halt(xhci); spin_unlock_irq(&xhci->lock); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 96f49dbb50ac..c713256297ac 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1494,6 +1494,7 @@ struct xhci_hcd { #define XHCI_TRUST_TX_LENGTH (1 << 10) #define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_INTEL_HOST (1 << 12) +#define XHCI_SPURIOUS_REBOOT (1 << 13) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- GitLab From 66d1b9263a371abd15806c53f486f0645ef31a8f Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Thu, 9 Aug 2012 02:50:40 +0000 Subject: [PATCH 5284/5711] tun: don't zeroize sock->file on detach This is a fix for bug, introduced in 3.4 kernel by commit 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d ("tun: don't hold network namespace by tun sockets"), which, among other things, replaced simple sock_put() by sk_release_kernel(). Below is sequence, which leads to oops for non-persistent devices: tun_chr_close() tun_detach() <== tun->socket.file = NULL tun_free_netdev() sk_release_sock() sock_release(sock->file == NULL) iput(SOCK_INODE(sock)) <== dereference on NULL pointer This patch just removes zeroing of socket's file from __tun_detach(). sock_release() will do this. Cc: stable@vger.kernel.org Reported-by: Ruan Zhijie Tested-by: Ruan Zhijie Acked-by: Al Viro Acked-by: Eric Dumazet Acked-by: Yuchung Cheng Signed-off-by: Stanislav Kinsbursky Signed-off-by: David S. Miller --- drivers/net/tun.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 926d4db5cb38..3a16d4fdaa05 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -187,7 +187,6 @@ static void __tun_detach(struct tun_struct *tun) netif_tx_lock_bh(tun->dev); netif_carrier_off(tun->dev); tun->tfile = NULL; - tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); /* Drop read queue */ -- GitLab From 8eee694c3e667e6f0856d9c8525208058f9d42bf Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 9 Aug 2012 04:37:25 +0000 Subject: [PATCH 5285/5711] bnx2x: fix unload previous driver flow when flr-capable The existing previous driver unload flow is flawed, causing the probe of functions reaching the 'uncommon fork' in flr-capable devices to fail. This patch resolves this, as well as fixing the flow for hypervisors which disable flr capabilities from functions as they pass them as PDA to VMs, as we cannot base the flow on the pci configuration space. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index dd451c3dd83d..5384a6dd155f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9384,32 +9384,24 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) return rc; } -static bool __devinit bnx2x_can_flr(struct bnx2x *bp) -{ - int pos; - u32 cap; - struct pci_dev *dev = bp->pdev; - - pos = pci_pcie_cap(dev); - if (!pos) - return false; - - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); - if (!(cap & PCI_EXP_DEVCAP_FLR)) - return false; - - return true; -} - static int __devinit bnx2x_do_flr(struct bnx2x *bp) { int i, pos; u16 status; struct pci_dev *dev = bp->pdev; - /* probe the capability first */ - if (bnx2x_can_flr(bp)) - return -ENOTTY; + + if (CHIP_IS_E1x(bp)) { + BNX2X_DEV_INFO("FLR not supported in E1/E1H\n"); + return -EINVAL; + } + + /* only bootcode REQ_BC_VER_4_INITIATE_FLR and onwards support flr */ + if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { + BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", + bp->common.bc_ver); + return -EINVAL; + } pos = pci_pcie_cap(dev); if (!pos) @@ -9429,12 +9421,8 @@ static int __devinit bnx2x_do_flr(struct bnx2x *bp) "transaction is not cleared; proceeding with reset anyway\n"); clear: - if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { - BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", - bp->common.bc_ver); - return -EINVAL; - } + BNX2X_DEV_INFO("Initiating FLR\n"); bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0); return 0; @@ -9454,8 +9442,21 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp) * the one required, then FLR will be sufficient to clean any residue * left by previous driver */ - if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp)) - return bnx2x_do_flr(bp); + rc = bnx2x_test_firmware_version(bp, false); + + if (!rc) { + /* fw version is good */ + BNX2X_DEV_INFO("FW version matches our own. Attempting FLR\n"); + rc = bnx2x_do_flr(bp); + } + + if (!rc) { + /* FLR was performed */ + BNX2X_DEV_INFO("FLR successful\n"); + return 0; + } + + BNX2X_DEV_INFO("Could not FLR\n"); /* Close the MCP request, return failure*/ rc = bnx2x_prev_mcp_done(bp); -- GitLab From 2070ffa2c8d4dc17cd8fc4b30d2710bcde27b051 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 9 Aug 2012 04:37:26 +0000 Subject: [PATCH 5286/5711] bnx2x: Fix recovery flow cleanup during probe During probe, every function probed clears the recovery registers from all functions on its path - thus signaling that given a future recovery event, there will be no need to wait for those functions. This is a flawed behaviour - each function should only be responsible for its own bit. Since this registers are handled during the load/unload routines, this cleanup is removed altogether. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 5384a6dd155f..02b5a343b195 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -4041,20 +4041,6 @@ static bool bnx2x_get_load_status(struct bnx2x *bp, int engine) return val != 0; } -/* - * Reset the load status for the current engine. - */ -static void bnx2x_clear_load_status(struct bnx2x *bp) -{ - u32 val; - u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : - BNX2X_PATH0_LOAD_CNT_MASK); - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); - val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); - REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); -} - static void _print_next_block(int idx, const char *blk) { pr_cont("%s%s", idx ? ", " : "", blk); @@ -11428,9 +11414,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, if (!chip_is_e1x) REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); - /* Reset the load counter */ - bnx2x_clear_load_status(bp); - dev->watchdog_timeo = TX_TIMEOUT; dev->netdev_ops = &bnx2x_netdev_ops; -- GitLab From 3a7c384ffd57ef5fbd95f48edaa2ca4eb3d9f2ee Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 9 Aug 2012 13:56:06 +0000 Subject: [PATCH 5287/5711] ipv4: tcp: unicast_sock should not land outside of TCP stack commit be9f4a44e7d41cee (ipv4: tcp: remove per net tcp_sock) added a selinux regression, reported and bisected by John Stultz selinux_ip_postroute_compat() expect to find a valid sk->sk_security pointer, but this field is NULL for unicast_sock It turns out that unicast_sock are really temporary stuff to be able to reuse part of IP stack (ip_append_data()/ip_push_pending_frames()) Fact is that frames sent by ip_send_unicast_reply() should be orphaned to not fool LSM. Note IPv6 never had this problem, as tcp_v6_send_response() doesnt use a fake socket at all. I'll probably implement tcp_v4_send_response() to remove these unicast_sock in linux-3.7 Reported-by: John Stultz Bisected-by: John Stultz Signed-off-by: Eric Dumazet Cc: Paul Moore Cc: Eric Paris Cc: "Serge E. Hallyn" Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 76dde25fb9a0..ec410e08b4b9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1536,6 +1536,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, arg->csumoffset) = csum_fold(csum_add(nskb->csum, arg->csum)); nskb->ip_summed = CHECKSUM_NONE; + skb_orphan(nskb); skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); ip_push_pending_frames(sk, &fl4); } -- GitLab From 63d02d157ec4124990258d66517b6c11fd6df0cf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 9 Aug 2012 14:11:00 +0000 Subject: [PATCH 5288/5711] net: tcp: ipv6_mapped needs sk_rx_dst_set method commit 5d299f3d3c8a2fb (net: ipv6: fix TCP early demux) added a regression for ipv6_mapped case. [ 67.422369] SELinux: initialized (dev autofs, type autofs), uses genfs_contexts [ 67.449678] SELinux: initialized (dev autofs, type autofs), uses genfs_contexts [ 92.631060] BUG: unable to handle kernel NULL pointer dereference at (null) [ 92.631435] IP: [< (null)>] (null) [ 92.631645] PGD 0 [ 92.631846] Oops: 0010 [#1] SMP [ 92.632095] Modules linked in: autofs4 sunrpc ipv6 dm_mirror dm_region_hash dm_log dm_multipath dm_mod video sbs sbshc battery ac lp parport sg snd_hda_intel snd_hda_codec snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device pcspkr snd_pcm_oss snd_mixer_oss snd_pcm snd_timer serio_raw button floppy snd i2c_i801 i2c_core soundcore snd_page_alloc shpchp ide_cd_mod cdrom microcode ehci_hcd ohci_hcd uhci_hcd [ 92.634294] CPU 0 [ 92.634294] Pid: 4469, comm: sendmail Not tainted 3.6.0-rc1 #3 [ 92.634294] RIP: 0010:[<0000000000000000>] [< (null)>] (null) [ 92.634294] RSP: 0018:ffff880245fc7cb0 EFLAGS: 00010282 [ 92.634294] RAX: ffffffffa01985f0 RBX: ffff88024827ad00 RCX: 0000000000000000 [ 92.634294] RDX: 0000000000000218 RSI: ffff880254735380 RDI: ffff88024827ad00 [ 92.634294] RBP: ffff880245fc7cc8 R08: 0000000000000001 R09: 0000000000000000 [ 92.634294] R10: 0000000000000000 R11: ffff880245fc7bf8 R12: ffff880254735380 [ 92.634294] R13: ffff880254735380 R14: 0000000000000000 R15: 7fffffffffff0218 [ 92.634294] FS: 00007f4516ccd6f0(0000) GS:ffff880256600000(0000) knlGS:0000000000000000 [ 92.634294] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 92.634294] CR2: 0000000000000000 CR3: 0000000245ed1000 CR4: 00000000000007f0 [ 92.634294] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 92.634294] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 92.634294] Process sendmail (pid: 4469, threadinfo ffff880245fc6000, task ffff880254b8cac0) [ 92.634294] Stack: [ 92.634294] ffffffff813837a7 ffff88024827ad00 ffff880254b6b0e8 ffff880245fc7d68 [ 92.634294] ffffffff81385083 00000000001d2680 ffff8802547353a8 ffff880245fc7d18 [ 92.634294] ffffffff8105903a ffff88024827ad60 0000000000000002 00000000000000ff [ 92.634294] Call Trace: [ 92.634294] [] ? tcp_finish_connect+0x2c/0xfa [ 92.634294] [] tcp_rcv_state_process+0x2b6/0x9c6 [ 92.634294] [] ? sched_clock_cpu+0xc3/0xd1 [ 92.634294] [] ? local_clock+0x2b/0x3c [ 92.634294] [] tcp_v4_do_rcv+0x63a/0x670 [ 92.634294] [] release_sock+0x128/0x1bd [ 92.634294] [] __inet_stream_connect+0x1b1/0x352 [ 92.634294] [] ? lock_sock_nested+0x74/0x7f [ 92.634294] [] ? wake_up_bit+0x25/0x25 [ 92.634294] [] ? lock_sock_nested+0x74/0x7f [ 92.634294] [] ? inet_stream_connect+0x22/0x4b [ 92.634294] [] inet_stream_connect+0x33/0x4b [ 92.634294] [] sys_connect+0x78/0x9e [ 92.634294] [] ? sysret_check+0x1b/0x56 [ 92.634294] [] ? __audit_syscall_entry+0x195/0x1c8 [ 92.634294] [] ? trace_hardirqs_on_thunk+0x3a/0x3f [ 92.634294] [] system_call_fastpath+0x16/0x1b [ 92.634294] Code: Bad RIP value. [ 92.634294] RIP [< (null)>] (null) [ 92.634294] RSP [ 92.634294] CR2: 0000000000000000 [ 92.648982] ---[ end trace 24e2bed94314c8d9 ]--- [ 92.649146] Kernel panic - not syncing: Fatal exception in interrupt Fix this using inet_sk_rx_dst_set(), and export this function in case IPv6 is modular. Reported-by: Andrew Morton Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 1 + net/ipv4/tcp_ipv4.c | 3 ++- net/ipv6/tcp_ipv6.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index e19124b84cd2..1f000ffe7075 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -464,6 +464,7 @@ extern int tcp_disconnect(struct sock *sk, int flags); void tcp_connect_init(struct sock *sk); void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); +void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb); /* From syncookies.c */ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 272241f16fcb..767823764016 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1869,7 +1869,7 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_destructor= tcp_twsk_destructor, }; -static void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); @@ -1877,6 +1877,7 @@ static void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) sk->sk_rx_dst = dst; inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; } +EXPORT_SYMBOL(inet_sk_rx_dst_set); const struct inet_connection_sock_af_ops ipv4_specific = { .queue_xmit = ip_queue_xmit, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5a439e9a4c01..bb9ce2b2f377 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1777,6 +1777,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, + .sk_rx_dst_set = inet_sk_rx_dst_set, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, .net_header_len = sizeof(struct iphdr), -- GitLab From 32ab31e01e2def6f48294d872d9bb42573aae00f Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 8 Aug 2012 08:27:03 -0500 Subject: [PATCH 5289/5711] irq_remap: disable IRQ remapping if any IOAPIC lacks an IOMMU The ACPI tables in the Macbook Air 5,1 define a single IOAPIC with id 2, but the only remapping unit described in the DMAR table matches id 0. Interrupt remapping fails as a result, and the kernel panics with the message "timer doesn't work through Interrupt-remapped IO-APIC." To fix this, check each IOAPIC for a corresponding IOMMU. If an IOMMU is not found, do not allow IRQ remapping to be enabled. v2: Move check to parse_ioapics_under_ir(), raise log level to KERN_ERR, and add FW_BUG to the log message v3: Skip check if IOMMU doesn't support interrupt remapping and remove existing check that the IOMMU count equals the IOAPIC count Acked-by: Suresh Siddha Signed-off-by: Seth Forshee Acked-by: Yinghai Lu Signed-off-by: Joerg Roedel --- drivers/iommu/intel_irq_remapping.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index e0b18f3ae9a8..af8904de1d44 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -736,6 +736,7 @@ int __init parse_ioapics_under_ir(void) { struct dmar_drhd_unit *drhd; int ir_supported = 0; + int ioapic_idx; for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -748,13 +749,20 @@ int __init parse_ioapics_under_ir(void) } } - if (ir_supported && ir_ioapic_num != nr_ioapics) { - printk(KERN_WARNING - "Not all IO-APIC's listed under remapping hardware\n"); - return -1; + if (!ir_supported) + return 0; + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { + int ioapic_id = mpc_ioapic_id(ioapic_idx); + if (!map_ioapic_to_ir(ioapic_id)) { + pr_err(FW_BUG "ioapic %d has no mapping iommu, " + "interrupt remapping will be disabled\n", + ioapic_id); + return -1; + } } - return ir_supported; + return 1; } int __init ir_dev_scope_init(void) -- GitLab From 2bd5ed002c0c493ac328f13a9e2a504261a7d48e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 10 Aug 2012 11:34:08 +0200 Subject: [PATCH 5290/5711] iommu/amd: Fix wrong check for ARRAY_SIZE() The check in the for-loop is broken. Fix it and the boot-crash it causes in AMD IOMMUv2 systems. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 0a2ea317120a..18a89b760aaa 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1111,7 +1111,7 @@ static void print_iommu_info(void) if (iommu->cap & (1 << IOMMU_CAP_EFR)) { pr_info("AMD-Vi: Extended features: "); - for (i = 0; ARRAY_SIZE(feat_str); ++i) { + for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) pr_cont(" %s", feat_str[i]); } -- GitLab From e9324b2ce656e1910d2385b9b47a2f926456dbe3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 9 Aug 2012 10:08:45 +0000 Subject: [PATCH 5291/5711] netfilter: nf_ct_sip: fix helper name Commit 3a8fc53a (netfilter: nf_ct_helper: allocate 16 bytes for the helper and policy names) introduced a bug in the SIP helper, the helper name is sprinted to the sip_names array instead of instead of into the helper structure. This breaks the helper match and the /proc/net/nf_conntrack_expect output. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_sip.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 758a1bacc126..2fb666920cc9 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1515,7 +1515,6 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, } static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; -static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { [SIP_EXPECT_SIGNALLING] = { @@ -1585,9 +1584,9 @@ static int __init nf_conntrack_sip_init(void) sip[i][j].me = THIS_MODULE; if (ports[i] == SIP_PORT) - sprintf(sip_names[i][j], "sip"); + sprintf(sip[i][j].name, "sip"); else - sprintf(sip_names[i][j], "sip-%u", i); + sprintf(sip[i][j].name, "sip-%u", i); pr_debug("port #%u: %u\n", i, ports[i]); -- GitLab From 02b69cbdc2fb2e1bfbfd9ac0c246d7be1b08d3cd Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 9 Aug 2012 10:08:46 +0000 Subject: [PATCH 5292/5711] netfilter: nf_ct_sip: fix IPv6 address parsing Within SIP messages IPv6 addresses are enclosed in square brackets in most cases, with the exception of the "received=" header parameter. Currently the helper fails to parse enclosed addresses. This patch: - changes the SIP address parsing function to enforce square brackets when required, and accept them when not required but present, as recommended by RFC 5118. - adds a new SDP address parsing function that never accepts square brackets since SDP doesn't use them. With these changes, the SIP helper correctly parses all test messages from RFC 5118 (Session Initiation Protocol (SIP) Torture Test Messages for Internet Protocol Version 6 (IPv6)). Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_conntrack_sip.h | 2 +- net/ipv4/netfilter/nf_nat_sip.c | 4 +- net/netfilter/nf_conntrack_sip.c | 87 +++++++++++++++++----- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 0dfc8b7210a3..89f2a627f3f0 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -164,7 +164,7 @@ extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr unsigned int dataoff, unsigned int datalen, const char *name, unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr); + union nf_inet_addr *addr, bool delim); extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, unsigned int off, unsigned int datalen, const char *name, diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index ea4a23813d26..eef8f29e8bf8 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -173,7 +173,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, * the reply. */ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, "maddr=", &poff, &plen, - &addr) > 0 && + &addr, true) > 0 && addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { buflen = sprintf(buffer, "%pI4", @@ -187,7 +187,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, * from which the server received the request. */ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, "received=", &poff, &plen, - &addr) > 0 && + &addr, false) > 0 && addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { buflen = sprintf(buffer, "%pI4", diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 2fb666920cc9..5c0a112aeee6 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -183,12 +183,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr, return len + digits_len(ct, dptr, limit, shift); } -static int parse_addr(const struct nf_conn *ct, const char *cp, - const char **endp, union nf_inet_addr *addr, - const char *limit) +static int sip_parse_addr(const struct nf_conn *ct, const char *cp, + const char **endp, union nf_inet_addr *addr, + const char *limit, bool delim) { const char *end; - int ret = 0; + int ret; if (!ct) return 0; @@ -197,16 +197,28 @@ static int parse_addr(const struct nf_conn *ct, const char *cp, switch (nf_ct_l3num(ct)) { case AF_INET: ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); + if (ret == 0) + return 0; break; case AF_INET6: + if (cp < limit && *cp == '[') + cp++; + else if (delim) + return 0; + ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); + if (ret == 0) + return 0; + + if (end < limit && *end == ']') + end++; + else if (delim) + return 0; break; default: BUG(); } - if (ret == 0 || end == cp) - return 0; if (endp) *endp = end; return 1; @@ -219,7 +231,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr, union nf_inet_addr addr; const char *aux = dptr; - if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { + if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) { pr_debug("ip: %s parse failed.!\n", dptr); return 0; } @@ -296,7 +308,7 @@ int ct_sip_parse_request(const struct nf_conn *ct, return 0; dptr += shift; - if (!parse_addr(ct, dptr, &end, addr, limit)) + if (!sip_parse_addr(ct, dptr, &end, addr, limit, true)) return -1; if (end < limit && *end == ':') { end++; @@ -550,7 +562,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, if (ret == 0) return ret; - if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) + if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true)) return -1; if (*c == ':') { c++; @@ -599,7 +611,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, unsigned int dataoff, unsigned int datalen, const char *name, unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr) + union nf_inet_addr *addr, bool delim) { const char *limit = dptr + datalen; const char *start, *end; @@ -613,7 +625,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, return 0; start += strlen(name); - if (!parse_addr(ct, start, &end, addr, limit)) + if (!sip_parse_addr(ct, start, &end, addr, limit, delim)) return 0; *matchoff = start - dptr; *matchlen = end - start; @@ -675,6 +687,47 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, return 1; } +static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, + const char **endp, union nf_inet_addr *addr, + const char *limit) +{ + const char *end; + int ret; + + memset(addr, 0, sizeof(*addr)); + switch (nf_ct_l3num(ct)) { + case AF_INET: + ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); + break; + case AF_INET6: + ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); + break; + default: + BUG(); + } + + if (ret == 0) + return 0; + if (endp) + *endp = end; + return 1; +} + +/* skip ip address. returns its length. */ +static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, + const char *limit, int *shift) +{ + union nf_inet_addr addr; + const char *aux = dptr; + + if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { + pr_debug("ip: %s parse failed.!\n", dptr); + return 0; + } + + return dptr - aux; +} + /* SDP header parsing: a SDP session description contains an ordered set of * headers, starting with a section containing general session parameters, * optionally followed by multiple media descriptions. @@ -686,10 +739,10 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, */ static const struct sip_header ct_sdp_hdrs[] = { [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), - [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), - [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), - [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), - [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), + [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len), + [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len), + [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len), + [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len), [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), }; @@ -775,8 +828,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, if (ret <= 0) return ret; - if (!parse_addr(ct, dptr + *matchoff, NULL, addr, - dptr + *matchoff + *matchlen)) + if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, + dptr + *matchoff + *matchlen)) return -1; return 1; } -- GitLab From f22eb25cf5b1157b29ef88c793b71972efc47143 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 9 Aug 2012 10:08:47 +0000 Subject: [PATCH 5293/5711] netfilter: nf_nat_sip: fix via header translation with multiple parameters Via-headers are parsed beginning at the first character after the Via-address. When the address is translated first and its length decreases, the offset to start parsing at is incorrect and header parameters might be missed. Update the offset after translating the Via-address to fix this. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_nat_sip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index eef8f29e8bf8..4ad9cf173992 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { - unsigned int matchend, poff, plen, buflen, n; + unsigned int olen, matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; /* We're only interested in headers related to this @@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, goto next; } + olen = *datalen; if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; - matchend = matchoff + matchlen; + matchend = matchoff + matchlen + *datalen - olen; /* The maddr= parameter (RFC 2361) specifies where to send * the reply. */ -- GitLab From 9d8dad742ad1c74d7e7210ee05d0b44961d5ea16 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 9 Aug 2012 19:01:26 -0700 Subject: [PATCH 5294/5711] Yama: higher restrictions should block PTRACE_TRACEME The higher ptrace restriction levels should be blocking even PTRACE_TRACEME requests. The comments in the LSM documentation are misleading about when the checks happen (the parent does not go through security_ptrace_access_check() on a PTRACE_TRACEME call). Signed-off-by: Kees Cook Cc: stable@vger.kernel.org # 3.5.x and later Signed-off-by: James Morris --- Documentation/security/Yama.txt | 14 +++++------ include/linux/security.h | 2 -- security/yama/yama_lsm.c | 41 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt index e369de2d48cd..dd908cf64ecf 100644 --- a/Documentation/security/Yama.txt +++ b/Documentation/security/Yama.txt @@ -46,14 +46,13 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...) so that any otherwise allowed process (even those in external pid namespaces) may attach. -These restrictions do not change how ptrace via PTRACE_TRACEME operates. - -The sysctl settings are: +The sysctl settings (writable only with CAP_SYS_PTRACE) are: 0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other process running under the same uid, as long as it is dumpable (i.e. did not transition uids, start privileged, or have called - prctl(PR_SET_DUMPABLE...) already). + prctl(PR_SET_DUMPABLE...) already). Similarly, PTRACE_TRACEME is + unchanged. 1 - restricted ptrace: a process must have a predefined relationship with the inferior it wants to call PTRACE_ATTACH on. By default, @@ -61,12 +60,13 @@ The sysctl settings are: classic criteria is also met. To change the relationship, an inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare an allowed debugger PID to call PTRACE_ATTACH on the inferior. + Using PTRACE_TRACEME is unchanged. 2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace - with PTRACE_ATTACH. + with PTRACE_ATTACH, or through children calling PTRACE_TRACEME. -3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set, - this sysctl cannot be changed to a lower value. +3 - no attach: no processes may use ptrace with PTRACE_ATTACH nor via + PTRACE_TRACEME. Once set, this sysctl value cannot be changed. The original children-only logic was based on the restrictions in grsecurity. diff --git a/include/linux/security.h b/include/linux/security.h index 4e5a73cdbbef..3dea6a9d568f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1242,8 +1242,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * Check that the @parent process has sufficient permission to trace the * current process before allowing the current process to present itself * to the @parent process for tracing. - * The parent process will still have to undergo the ptrace_access_check - * checks before it is allowed to trace this one. * @parent contains the task_struct structure for debugger process. * Return 0 if permission is granted. * @capget: diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 83554ee8a587..d51b7c76c37d 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -290,10 +290,51 @@ static int yama_ptrace_access_check(struct task_struct *child, return rc; } +/** + * yama_ptrace_traceme - validate PTRACE_TRACEME calls + * @parent: task that will become the ptracer of the current task + * + * Returns 0 if following the ptrace is allowed, -ve on error. + */ +static int yama_ptrace_traceme(struct task_struct *parent) +{ + int rc; + + /* If standard caps disallows it, so does Yama. We should + * only tighten restrictions further. + */ + rc = cap_ptrace_traceme(parent); + if (rc) + return rc; + + /* Only disallow PTRACE_TRACEME on more aggressive settings. */ + switch (ptrace_scope) { + case YAMA_SCOPE_CAPABILITY: + if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE)) + rc = -EPERM; + break; + case YAMA_SCOPE_NO_ATTACH: + rc = -EPERM; + break; + } + + if (rc) { + char name[sizeof(current->comm)]; + printk_ratelimited(KERN_NOTICE + "ptraceme of pid %d was attempted by: %s (pid %d)\n", + current->pid, + get_task_comm(name, parent), + parent->pid); + } + + return rc; +} + static struct security_operations yama_ops = { .name = "yama", .ptrace_access_check = yama_ptrace_access_check, + .ptrace_traceme = yama_ptrace_traceme, .task_prctl = yama_task_prctl, .task_free = yama_task_free, }; -- GitLab From 9c30959884261518de46e0b79ac7a902e6ddd147 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 23 Jun 2012 11:25:43 +0100 Subject: [PATCH 5295/5711] MAINTAINERS: Add entries for Wolfson Arizona class devices Signed-off-by: Mark Brown --- MAINTAINERS | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 94b823f71e94..dba8941fb425 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7665,23 +7665,28 @@ S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/clk/clk-wm83*.c +F: drivers/extcon/extcon-arizona.c F: drivers/leds/leds-wm83*.c F: drivers/gpio/gpio-*wm*.c +F: drivers/gpio/gpio-arizona.c F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c F: drivers/input/touchscreen/wm97*.c -F: drivers/mfd/wm8*.c +F: drivers/mfd/arizona* +F: drivers/mfd/wm*.c F: drivers/power/wm83*.c F: drivers/rtc/rtc-wm83*.c F: drivers/regulator/wm8*.c F: drivers/video/backlight/wm83*_bl.c F: drivers/watchdog/wm83*_wdt.c +F: include/linux/mfd/arizona/ F: include/linux/mfd/wm831x/ F: include/linux/mfd/wm8350/ F: include/linux/mfd/wm8400* F: include/linux/wm97xx.h F: include/sound/wm????.h +F: sound/soc/codecs/arizona.? F: sound/soc/codecs/wm* WORKQUEUE -- GitLab From de64c0ee7dbcbfbbe63bd9ea45783d87babc6452 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Aug 2012 12:22:58 +0300 Subject: [PATCH 5296/5711] ALSA: cs46xx - signedness bug in snd_cs46xx_codec_read() This function returns its own error codes instead of normal negative error codes. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/cs46xx/cs46xx_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index f75f5ffdfdfb..a71d1c14a0f6 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -94,7 +94,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return -EINVAL; + return 0xffff; chip->active_ctrl(chip, 1); -- GitLab From 8ab08c0c4c39f36d3bf89e03a4bc3e6898e1563c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 10:28:33 +0000 Subject: [PATCH 5297/5711] ARM: exynos: exynos_pm_add_dev_to_genpd may be unused exynos_pm_add_dev_to_genpd is used if one or more out of a large number of Kconfig symbols are enabled. However the new exynos_defconfig selects none of those, so the function becomes unused. Marking it so lets the compiler automatically discard it. Without this patch, building exynos_defconfig results in: arch/arm/mach-exynos/pm_domains.c:118:123: warning: 'exynos_pm_add_dev_to_genpd' defined but not used [-Wunused-function] Signed-off-by: Arnd Bergmann Acked-by: Thomas Abraham Acked-by: Kukjin Kim Cc: Rafael J. Wysocki --- arch/arm/mach-exynos/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index 373c3c00d24c..c0bc83a7663e 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -115,7 +115,7 @@ static __init int exynos_pm_dt_parse_domains(void) } #endif /* CONFIG_OF */ -static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, +static __init __maybe_unused void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd) { if (pdev->dev.bus) { -- GitLab From 38eaed327dc5bea2e5548ea3d195de83a2070c6d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 10:33:24 +0000 Subject: [PATCH 5298/5711] gpio: em: do not discard em_gio_irq_domain_cleanup The newly added gpio-em driver marks its em_gio_irq_domain_cleanup function as __devexit, which would lead to that function being discarded in case CONFIG_HOTPLUG is disabled. However, the function is also called by the error handling logic em_gio_probe, which would cause a jump into a NULL pointer if it was removed from the kernel or module. Without this patch, building kzm9d_defconfig results in: WARNING: drivers/gpio/built-in.o(.devinit.text+0x330): Section mismatch in reference from the function em_gio_probe() to the function .devexit.text:em_gio_irq_domain_cleanup() The function __devinit em_gio_probe() references a function __devexit em_gio_irq_domain_cleanup(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of em_gio_irq_domain_cleanup() so it may be used outside an exit section. Signed-off-by: Arnd Bergmann Cc: Magnus Damm Cc: Linus Walleij Cc: Rafael J. Wysocki --- drivers/gpio/gpio-em.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 150d9768811d..ae37181798b3 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -266,7 +266,7 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) return 0; } -static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p) +static void em_gio_irq_domain_cleanup(struct em_gio_priv *p) { struct gpio_em_config *pdata = p->pdev->dev.platform_data; -- GitLab From d680e2c11eb0ddd21ba438b3a537e2eb093ff86f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 11:05:25 +0000 Subject: [PATCH 5299/5711] mtd/omap2: fix dmaengine_slave_config error handling The newly added dmaengine support in the omap2 nand driver potentially causes an undefined return value from the omap_nand_probe function when dmaengine_slave_config reports an error. Let's handle this by returning the same error back to the caller. Without this patch, building omap2plus_defconfig results in: drivers/mtd/nand/omap2.c: In function 'omap_nand_probe': drivers/mtd/nand/omap2.c:1154:6: warning: 'err' may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Arnd Bergmann Cc: Russell King Cc: Grazvydas Ignotas --- drivers/mtd/nand/omap2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e9309b3659e7..ac4fd756eda3 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1245,7 +1245,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } else { struct dma_slave_config cfg; - int rc; memset(&cfg, 0, sizeof(cfg)); cfg.src_addr = info->phys_base; @@ -1254,10 +1253,10 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.src_maxburst = 16; cfg.dst_maxburst = 16; - rc = dmaengine_slave_config(info->dma, &cfg); - if (rc) { + err = dmaengine_slave_config(info->dma, &cfg); + if (err) { dev_err(&pdev->dev, "DMA engine slave config failed: %d\n", - rc); + err); goto out_release_mem_region; } info->nand.read_buf = omap_read_buf_dma_pref; -- GitLab From 4732cc636075ff1a0219bf933d8c23d1a99f41ed Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 11:18:20 +0000 Subject: [PATCH 5300/5711] spi/s3c64xx: improve error handling When a device tree definition os an s3c64xx SPI master is missing a "controller-data" subnode, the newly added s3c64xx_get_slave_ctrldata function might use uninitialized memory in place of that node, which was correctly reported by gcc. Without this patch, building s3c6400_defconfig results in: drivers/spi/spi-s3c64xx.c: In function 's3c64xx_get_slave_ctrldata.isra.25': drivers/spi/spi-s3c64xx.c:841:5: warning: 'data_np' may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Arnd Bergmann Acked-by: Thomas Abraham Acked-by: Kukjin Kim Cc: Jaswinder Singh Cc: Grant Likely --- drivers/spi/spi-s3c64xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 646a7657fe62..cfa2c35dfeed 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -826,7 +826,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs; - struct device_node *slave_np, *data_np; + struct device_node *slave_np, *data_np = NULL; u32 fb_delay = 0; slave_np = spi->dev.of_node; -- GitLab From 59596df640eb049952dbfe5e7e64ffe826abfe61 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 07:11:34 +0000 Subject: [PATCH 5301/5711] omap-rng: fix use of SIMPLE_DEV_PM_OPS omap_rng_suspend and omap_rng_resume are unused if CONFIG_PM is enabled but CONFIG_PM_SLEEP is disabled. I found this while building all defconfig files on ARM. It's not clear to me if this is the right solution, but at least it makes the code consistent again. Without this patch, building omap1_defconfig results in: drivers/char/hw_random/omap-rng.c:165:12: warning: 'omap_rng_suspend' defined but not used [-Wunused-function] drivers/char/hw_random/omap-rng.c:171:12: warning: 'omap_rng_resume' defined but not used [-Wunused-function] Signed-off-by: Arnd Bergmann Acked-by: Kevin Hilman Cc: Rafael J. Wysocki Cc: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index d706bd0e9e80..4fbdceb6f773 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -160,7 +160,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int omap_rng_suspend(struct device *dev) { -- GitLab From f7b83b908fbecadefa73c0d76b9c719d09c1d96d Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 7 Aug 2012 12:23:06 +0000 Subject: [PATCH 5302/5711] drm/edid: Fix potential memory leak in edid_load() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Reviewed-by: Carsten Emde Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid_load.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 66d4a28ad5a2..0303935d10e2 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -119,7 +119,7 @@ static int edid_load(struct drm_connector *connector, char *name, { const struct firmware *fw; struct platform_device *pdev; - u8 *fwdata = NULL, *edid; + u8 *fwdata = NULL, *edid, *new_edid; int fwsize, expected; int builtin = 0, err = 0; int i, valid_extensions = 0; @@ -195,12 +195,14 @@ static int edid_load(struct drm_connector *connector, char *name, "\"%s\" for connector \"%s\"\n", valid_extensions, edid[0x7e], name, connector_name); edid[0x7e] = valid_extensions; - edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, + new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); - if (edid == NULL) { + if (new_edid == NULL) { err = -ENOMEM; + kfree(edid); goto relfw_out; } + edid = new_edid; } connector->display_info.raw_edid = edid; -- GitLab From 9830605d4c070b16ec5c24a75503877cc7698409 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 9 Aug 2012 15:00:15 +1000 Subject: [PATCH 5303/5711] drm/mgag200: fix G200ER pll picking algorithm The original code was misported from the X driver, a) an int went to unsigned int, breaking the downward counting testm code b) the port did the vco/computed clock bits completely wrong. This fixes an infinite loop on modprobe on some Dell servers with the G200ER chipset variant. Found in internal testing. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/mgag200/mgag200_mode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a4d7c500c97b..b69642d5d850 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -468,10 +468,11 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) { unsigned int vcomax, vcomin, pllreffreq; unsigned int delta, tmpdelta; - unsigned int testr, testn, testm, testo; + int testr, testn, testm, testo; unsigned int p, m, n; - unsigned int computed; + unsigned int computed, vco; int tmp; + const unsigned int m_div_val[] = { 1, 2, 4, 8 }; m = n = p = 0; vcomax = 1488000; @@ -490,12 +491,13 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) if (delta == 0) break; for (testo = 5; testo < 33; testo++) { - computed = pllreffreq * (testn + 1) / + vco = pllreffreq * (testn + 1) / (testr + 1); - if (computed < vcomin) + if (vco < vcomin) continue; - if (computed > vcomax) + if (vco > vcomax) continue; + computed = vco / (m_div_val[testm] * (testo + 1)); if (computed > clock) tmpdelta = computed - clock; else -- GitLab From 15b5eb2d913f857ad30b0b4f1cd6867495962221 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 3 May 2012 12:47:54 +0000 Subject: [PATCH 5304/5711] ARM: s3c24xx: enable CONFIG_BUG for tct_hammer Disabling CONFIG_BUG creates an insane amount of build warnings, which makes it useless to check for building defconfigs to see if new warnings show up. Without this patch, building tct_hammer_defconfig results in: net/packet/af_packet.c: In function 'tpacket_rcv': net/packet/af_packet.c:1889:30: warning: 'hdrlen' may be used uninitialized in this function [-Wuninitialized] net/core/ethtool.c: In function 'ethtool_get_feature_mask': net/core/ethtool.c:213:1: warning: control reaches end of non-void function [-Wreturn-type] block/cfq-iosched.c: In function 'cfq_async_queue_prio': block/cfq-iosched.c:2914:1: warning: control reaches end of non-void function [-Wreturn-type] mm/bootmem.c: In function 'mark_bootmem': mm/bootmem.c:352:1: warning: control reaches end of non-void function [-Wreturn-type] net/core/dev.c: In function 'skb_warn_bad_offload': net/core/dev.c:1904:33: warning: unused variable 'null_features' [-Wunused-variable] drivers/mtd/chips/cfi_probe.c: In function 'cfi_chip_setup': include/linux/mtd/cfi.h:489:3: warning: 'r.x[0]' may be used uninitialized in this function [-Wuninitialized] include/linux/mtd/map.h:394:11: note: 'r.x[0]' was declared here include/linux/mtd/cfi.h:489:3: warning: 'r.x[0]' may be used uninitialized in this function [-Wuninitialized] (and many more) The size of vmlinux increases by 1.78% because of this: size obj-arm/vmlinux.nobug text data bss dec hex filename 2108474 116916 55352 2280742 22cd26 obj-arm/vmlinux size obj-arm/vmlinux.bug text data bss dec hex filename 2150804 116916 53696 2321416 236c08 obj-arm/vmlinux Signed-off-by: Arnd Bergmann Acked-by: Kukjin Kim Cc: Ben Dooks --- arch/arm/configs/tct_hammer_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig index 1d24f8458bef..71277a1591ba 100644 --- a/arch/arm/configs/tct_hammer_defconfig +++ b/arch/arm/configs/tct_hammer_defconfig @@ -7,7 +7,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_KALLSYMS is not set -# CONFIG_BUG is not set +# CONFIG_BUGVERBOSE is not set # CONFIG_ELF_CORE is not set # CONFIG_SHMEM is not set CONFIG_SLOB=y -- GitLab From de9234306bb28fe6c8c3bb908e3f9956f5276a02 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 14:03:33 +0000 Subject: [PATCH 5305/5711] ARM: davinci: remove broken ntosd2_init_i2c ntosd2_init_i2c walks the ntosd2_i2c_info array, which it expects to be populated with at least one member. gcc correctly warns about the out-of-bounds access here. Since this can not possibly work, it's better to disable i2c support entirely on this board. Without this patch, building davinci_all_defconfig results in: arch/arm/mach-davinci/board-neuros-osd2.c: In function 'davinci_ntosd2_init': arch/arm/mach-davinci/board-neuros-osd2.c:187:20: warning: array subscript is above array bounds [-Warray-bounds] Signed-off-by: Arnd Bergmann Acked-by: Sekhar Nori Cc: Kevin Hilman Cc: Andrey Porodko --- arch/arm/mach-davinci/board-neuros-osd2.c | 39 ----------------------- 1 file changed, 39 deletions(-) diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 5de69f2fcca9..f6b9fc70161b 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -162,38 +162,6 @@ static void __init davinci_ntosd2_map_io(void) dm644x_init(); } -/* - I2C initialization -*/ -static struct davinci_i2c_platform_data ntosd2_i2c_pdata = { - .bus_freq = 20 /* kHz */, - .bus_delay = 100 /* usec */, -}; - -static struct i2c_board_info __initdata ntosd2_i2c_info[] = { -}; - -static int ntosd2_init_i2c(void) -{ - int status; - - davinci_init_i2c(&ntosd2_i2c_pdata); - status = gpio_request(NTOSD2_MSP430_IRQ, ntosd2_i2c_info[0].type); - if (status == 0) { - status = gpio_direction_input(NTOSD2_MSP430_IRQ); - if (status == 0) { - status = gpio_to_irq(NTOSD2_MSP430_IRQ); - if (status > 0) { - ntosd2_i2c_info[0].irq = status; - i2c_register_board_info(1, - ntosd2_i2c_info, - ARRAY_SIZE(ntosd2_i2c_info)); - } - } - } - return status; -} - static struct davinci_mmc_config davinci_ntosd2_mmc_config = { .wires = 4, .version = MMC_CTLR_VERSION_1 @@ -218,7 +186,6 @@ static __init void davinci_ntosd2_init(void) { struct clk *aemif_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; - int status; aemif_clk = clk_get(NULL, "aemif"); clk_enable(aemif_clk); @@ -242,12 +209,6 @@ static __init void davinci_ntosd2_init(void) platform_add_devices(davinci_ntosd2_devices, ARRAY_SIZE(davinci_ntosd2_devices)); - /* Initialize I2C interface specific for this board */ - status = ntosd2_init_i2c(); - if (status < 0) - pr_warning("davinci_ntosd2_init: msp430 irq setup failed:" - " %d\n", status); - davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); -- GitLab From 9069240480e24a2d6ce23404c9ad6cabf59b7258 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 9 Aug 2012 23:00:02 +0200 Subject: [PATCH 5306/5711] ACPI / PM: Fix unused function warnings for CONFIG_PM_SLEEP According to compiler warnings, several suspend/resume functions in ACPI drivers are not used for CONFIG_PM_SLEEP unset, so add #ifdefs to prevent them from being built in that case. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 4 ++++ drivers/acpi/battery.c | 2 ++ drivers/acpi/button.c | 4 ++++ drivers/acpi/fan.c | 4 ++++ drivers/acpi/power.c | 4 ++++ drivers/acpi/sbs.c | 2 ++ drivers/acpi/thermal.c | 4 ++++ 7 files changed, 24 insertions(+) diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index ac7034129f3f..d5fdd36190cc 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -69,7 +69,9 @@ static const struct acpi_device_id ac_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ac_device_ids); +#ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static struct acpi_driver acpi_ac_driver = { @@ -313,6 +315,7 @@ static int acpi_ac_add(struct acpi_device *device) return result; } +#ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev) { struct acpi_ac *ac; @@ -332,6 +335,7 @@ static int acpi_ac_resume(struct device *dev) kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); return 0; } +#endif static int acpi_ac_remove(struct acpi_device *device, int type) { diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ff2c876ec412..45e3e1759fb8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1052,6 +1052,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) return 0; } +#ifdef CONFIG_PM_SLEEP /* this is needed to learn about changes made in suspended state */ static int acpi_battery_resume(struct device *dev) { @@ -1068,6 +1069,7 @@ static int acpi_battery_resume(struct device *dev) acpi_battery_update(battery); return 0; } +#endif static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 79d4c22f7a6d..314a3b84bbc7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -78,7 +78,9 @@ static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); static void acpi_button_notify(struct acpi_device *device, u32 event); +#ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); static struct acpi_driver acpi_button_driver = { @@ -310,6 +312,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) } } +#ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev) { struct acpi_device *device = to_acpi_device(dev); @@ -319,6 +322,7 @@ static int acpi_button_resume(struct device *dev) return acpi_lid_send_state(device); return 0; } +#endif static int acpi_button_add(struct acpi_device *device) { diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 669d9ee80d16..bc36a476f1ab 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -53,8 +53,10 @@ static const struct acpi_device_id fan_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, fan_device_ids); +#ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev); static int acpi_fan_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume); static struct acpi_driver acpi_fan_driver = { @@ -184,6 +186,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) return 0; } +#ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev) { if (!dev) @@ -207,6 +210,7 @@ static int acpi_fan_resume(struct device *dev) return result; } +#endif static int __init acpi_fan_init(void) { diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 215ecd097408..fc1803414629 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -67,7 +67,9 @@ static const struct acpi_device_id power_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, power_device_ids); +#ifdef CONFIG_PM_SLEEP static int acpi_power_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); static struct acpi_driver acpi_power_driver = { @@ -775,6 +777,7 @@ static int acpi_power_remove(struct acpi_device *device, int type) return 0; } +#ifdef CONFIG_PM_SLEEP static int acpi_power_resume(struct device *dev) { int result = 0, state; @@ -803,6 +806,7 @@ static int acpi_power_resume(struct device *dev) return result; } +#endif int __init acpi_power_init(void) { diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index c0b9aa5faf4c..ff0740e0a9c2 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -988,6 +988,7 @@ static void acpi_sbs_rmdirs(void) #endif } +#ifdef CONFIG_PM_SLEEP static int acpi_sbs_resume(struct device *dev) { struct acpi_sbs *sbs; @@ -997,6 +998,7 @@ static int acpi_sbs_resume(struct device *dev) acpi_sbs_callback(sbs); return 0; } +#endif static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9fe90e9fecb5..edda74a43406 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -106,7 +106,9 @@ static const struct acpi_device_id thermal_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, thermal_device_ids); +#ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); static struct acpi_driver acpi_thermal_driver = { @@ -1041,6 +1043,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) return 0; } +#ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev) { struct acpi_thermal *tz; @@ -1075,6 +1078,7 @@ static int acpi_thermal_resume(struct device *dev) return AE_OK; } +#endif static int thermal_act(const struct dmi_system_id *d) { -- GitLab From 14bc9c6dc694e2d7930802f7afd275de25ef8394 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 10 Aug 2012 13:29:32 +0200 Subject: [PATCH 5307/5711] ALSA: hda - Fix panned "Beep Playback Switch" When "Beep Playback Switch" had a different value on left and right channels (such as muting left but not right, or vice versa), this could result in the right channel being ignored. This patch enables beep to be sounding from right channel only, and also give correct result back to userspace (e g amixer). Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0bc2315b181d..d26ae65b43b7 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -237,10 +237,9 @@ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; - if (beep) { + if (beep && !beep->enabled) { ucontrol->value.integer.value[0] = - ucontrol->value.integer.value[1] = - beep->enabled; + ucontrol->value.integer.value[1] = 0; return 0; } return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); @@ -252,9 +251,18 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; - if (beep) - snd_hda_enable_beep_device(codec, - *ucontrol->value.integer.value); + if (beep) { + u8 chs = get_amp_channels(kcontrol); + int enable = 0; + long *valp = ucontrol->value.integer.value; + if (chs & 1) { + enable |= *valp; + valp++; + } + if (chs & 2) + enable |= *valp; + snd_hda_enable_beep_device(codec, enable); + } return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); -- GitLab From e037cb4a54e26b5f55f856e0e7445cfcfb2f3d31 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 10 Aug 2012 14:11:58 +0200 Subject: [PATCH 5308/5711] ALSA : hda - bug fix on checking the supported power states of a codec The return value of snd_hda_param_read() is -1 for an error, otherwise it's the supported power states of a codec. The supported power states is a 32-bit value. Bit 31 will be set to 1 if the codec supports EPSS, thus making "sup" negative. And the bit 28:5 is reserved as "0". So a negative value other than -1 shall be further checked. Please refer to High-Definition spec 7.3.4.12 "Supported Power States", thanks! Signed-off-by: Mengdong Lin Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 88a9c20eb7a2..629131ad7b8b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3497,7 +3497,7 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg { int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); - if (sup < 0) + if (sup == -1) return false; if (sup & power_state) return true; -- GitLab From 3567a4e2c52ce2f6fe74fc85690335ec7c96608e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 9 Aug 2012 23:00:13 +0200 Subject: [PATCH 5309/5711] platform / x86 / PM: Fix unused function warnings for CONFIG_PM_SLEEP According to compiler warnings, quite some suspend/resume functions in platform x86 drivers are not used for CONFIG_PM_SLEEP unset, so add #ifdefs to prevent them from being built in that case. Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/classmate-laptop.c | 4 ++++ drivers/platform/x86/fujitsu-tablet.c | 2 ++ drivers/platform/x86/hdaps.c | 2 ++ drivers/platform/x86/hp_accel.c | 2 +- drivers/platform/x86/msi-laptop.c | 4 ++++ drivers/platform/x86/panasonic-laptop.c | 4 ++++ drivers/platform/x86/sony-laptop.c | 12 +++++++++++- drivers/platform/x86/thinkpad_acpi.c | 2 ++ drivers/platform/x86/toshiba_acpi.c | 2 ++ drivers/platform/x86/toshiba_bluetooth.c | 4 ++++ drivers/platform/x86/xo15-ebook.c | 2 ++ 11 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 2ca7dd1ab3e4..cd33add118ce 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -350,6 +350,7 @@ static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) inputdev->close = cmpc_accel_close_v4; } +#ifdef CONFIG_PM_SLEEP static int cmpc_accel_suspend_v4(struct device *dev) { struct input_dev *inputdev; @@ -384,6 +385,7 @@ static int cmpc_accel_resume_v4(struct device *dev) return 0; } +#endif static int cmpc_accel_add_v4(struct acpi_device *acpi) { @@ -752,6 +754,7 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type) return cmpc_remove_acpi_notify_device(acpi); } +#ifdef CONFIG_PM_SLEEP static int cmpc_tablet_resume(struct device *dev) { struct input_dev *inputdev = dev_get_drvdata(dev); @@ -761,6 +764,7 @@ static int cmpc_tablet_resume(struct device *dev) input_report_switch(inputdev, SW_TABLET_MODE, !val); return 0; } +#endif static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume); diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index d2e41735a47b..7acae3f85f3b 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -440,11 +440,13 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type) return 0; } +#ifdef CONFIG_PM_SLEEP static int acpi_fujitsu_resume(struct device *dev) { fujitsu_reset(); return 0; } +#endif static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume); diff --git a/drivers/platform/x86/hdaps.c b/drivers/platform/x86/hdaps.c index d9ab6f64dcec..777c7e3dda51 100644 --- a/drivers/platform/x86/hdaps.c +++ b/drivers/platform/x86/hdaps.c @@ -305,10 +305,12 @@ static int hdaps_probe(struct platform_device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP static int hdaps_resume(struct device *dev) { return hdaps_device_init(); } +#endif static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume); diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index f4d91154ad67..6b9af989632b 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -352,7 +352,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int lis3lv02d_suspend(struct device *dev) { /* make sure the device is off when we suspend */ diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index f64441844317..2111dbb7e1e3 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -85,7 +85,9 @@ #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4 #define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4) +#ifdef CONFIG_PM_SLEEP static int msi_laptop_resume(struct device *device); +#endif static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume); #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f @@ -753,6 +755,7 @@ err_bluetooth: return retval; } +#ifdef CONFIG_PM_SLEEP static int msi_laptop_resume(struct device *device) { u8 data; @@ -773,6 +776,7 @@ static int msi_laptop_resume(struct device *device) return 0; } +#endif static int __init msi_laptop_input_setup(void) { diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 24480074bcf0..8e8caa767d6a 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -188,7 +188,9 @@ static const struct acpi_device_id pcc_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, pcc_device_ids); +#ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume); static struct acpi_driver acpi_pcc_driver = { @@ -540,6 +542,7 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc) /* kernel module interface */ +#ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev) { struct pcc_acpi *pcc; @@ -556,6 +559,7 @@ static int acpi_pcc_hotkey_resume(struct device *dev) return acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); } +#endif static int acpi_pcc_hotkey_add(struct acpi_device *device) { diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9363969ad07a..daaddec68def 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -140,7 +140,10 @@ MODULE_PARM_DESC(kbd_backlight_timeout, "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " "(default: 0)"); +#ifdef CONFIG_PM_SLEEP static void sony_nc_kbd_backlight_resume(void); +static void sony_nc_thermal_resume(void); +#endif static int sony_nc_kbd_backlight_setup(struct platform_device *pd, unsigned int handle); static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); @@ -151,7 +154,6 @@ static void sony_nc_battery_care_cleanup(struct platform_device *pd); static int sony_nc_thermal_setup(struct platform_device *pd); static void sony_nc_thermal_cleanup(struct platform_device *pd); -static void sony_nc_thermal_resume(void); static int sony_nc_lid_resume_setup(struct platform_device *pd); static void sony_nc_lid_resume_cleanup(struct platform_device *pd); @@ -1431,6 +1433,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) sony_nc_handles_cleanup(pd); } +#ifdef CONFIG_PM_SLEEP static void sony_nc_function_resume(void) { unsigned int i, result, bitmask, arg; @@ -1508,6 +1511,7 @@ static int sony_nc_resume(struct device *dev) return 0; } +#endif static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume); @@ -1872,6 +1876,7 @@ static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) } } +#ifdef CONFIG_PM_SLEEP static void sony_nc_kbd_backlight_resume(void) { int ignore = 0; @@ -1888,6 +1893,7 @@ static void sony_nc_kbd_backlight_resume(void) (kbdbl_ctl->base + 0x200) | (kbdbl_ctl->timeout << 0x10), &ignore); } +#endif struct battery_care_control { struct device_attribute attrs[2]; @@ -2210,6 +2216,7 @@ static void sony_nc_thermal_cleanup(struct platform_device *pd) } } +#ifdef CONFIG_PM_SLEEP static void sony_nc_thermal_resume(void) { unsigned int status = sony_nc_thermal_mode_get(); @@ -2217,6 +2224,7 @@ static void sony_nc_thermal_resume(void) if (status != th_handle->mode) sony_nc_thermal_mode_set(th_handle->mode); } +#endif /* resume on LID open */ struct snc_lid_resume_control { @@ -4287,6 +4295,7 @@ err_free_resources: return result; } +#ifdef CONFIG_PM_SLEEP static int sony_pic_suspend(struct device *dev) { if (sony_pic_disable(to_acpi_device(dev))) @@ -4300,6 +4309,7 @@ static int sony_pic_resume(struct device *dev) spic_dev.cur_ioport, spic_dev.cur_irq); return 0; } +#endif static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume); diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e7f73287636c..f28f36ccdcf4 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -922,6 +922,7 @@ static struct input_dev *tpacpi_inputdev; static struct mutex tpacpi_inputdev_send_mutex; static LIST_HEAD(tpacpi_all_drivers); +#ifdef CONFIG_PM_SLEEP static int tpacpi_suspend_handler(struct device *dev) { struct ibm_struct *ibm, *itmp; @@ -949,6 +950,7 @@ static int tpacpi_resume_handler(struct device *dev) return 0; } +#endif static SIMPLE_DEV_PM_OPS(tpacpi_pm, tpacpi_suspend_handler, tpacpi_resume_handler); diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c13ba5bac93f..5f1256d5e933 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1296,6 +1296,7 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) } } +#ifdef CONFIG_PM_SLEEP static int toshiba_acpi_suspend(struct device *device) { struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); @@ -1317,6 +1318,7 @@ static int toshiba_acpi_resume(struct device *device) return 0; } +#endif static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm, toshiba_acpi_suspend, toshiba_acpi_resume); diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index 715a43cb5e3c..5e5d6317d690 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -41,7 +41,9 @@ static const struct acpi_device_id bt_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, bt_device_ids); +#ifdef CONFIG_PM_SLEEP static int toshiba_bt_resume(struct device *dev); +#endif static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume); static struct acpi_driver toshiba_bt_rfkill_driver = { @@ -90,10 +92,12 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event) toshiba_bluetooth_enable(device->handle); } +#ifdef CONFIG_PM_SLEEP static int toshiba_bt_resume(struct device *dev) { return toshiba_bluetooth_enable(to_acpi_device(dev)->handle); } +#endif static int toshiba_bt_rfkill_add(struct acpi_device *device) { diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 849c07c13bf6..38ba39d7ca7d 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -77,10 +77,12 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event) } } +#ifdef CONFIG_PM_SLEEP static int ebook_switch_resume(struct device *dev) { return ebook_send_state(to_acpi_device(dev)); } +#endif static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume); -- GitLab From 07368d32f1a67e797def08cf2ee3ea1647b204b6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 9 Aug 2012 23:00:35 +0200 Subject: [PATCH 5310/5711] tpm_tis / PM: Fix unused function warning for CONFIG_PM_SLEEP According to a compiler warning, the tpm_tis_resume() function is not used for CONFIG_PM_SLEEP unset, so add a #ifdef to prevent it from being built in that case. Signed-off-by: Rafael J. Wysocki --- drivers/char/tpm/tpm_tis.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 89682fa8801e..c4be3519a587 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -807,6 +807,7 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); #endif +#ifdef CONFIG_PM_SLEEP static int tpm_tis_resume(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); @@ -816,6 +817,7 @@ static int tpm_tis_resume(struct device *dev) return tpm_pm_resume(dev); } +#endif static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); -- GitLab From 61f5d61ef94d7082d96494e2a6dd79de2b4437d2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 8 Aug 2012 11:34:43 +0530 Subject: [PATCH 5311/5711] ASoC: Samsung: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following build error: In file included from arch/arm/mach-exynos/include/mach/dma.h:24:0, from arch/arm/plat-samsung/include/plat/dma-ops.h:17, from arch/arm/plat-samsung/include/plat/dma.h:128, from sound/soc/samsung/pcm.c:23: arch/arm/plat-samsung/include/plat/dma-pl330.h:106:8: error: redefinition of ‘struct s3c2410_dma_client’ arch/arm/plat-samsung/include/plat/dma.h:40:8: note: originally defined here make[3]: *** [sound/soc/samsung/pcm.o] Error 1 Signed-off-by: Sachin Kamat Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Signed-off-by: Mark Brown --- sound/soc/samsung/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index b7b2a1f91425..89b064650f14 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include "dma.h" #include "pcm.h" -- GitLab From 7724a1edbe463b06d4e7831a41149ba095b16c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20=C3=87a=C4=9Flayan?= Date: Fri, 10 Aug 2012 17:25:10 +0300 Subject: [PATCH 5312/5711] USB: ftdi_sio: Add VID/PID for Kondo Serial USB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds VID/PID for Kondo Kagaku Co. Ltd. Serial USB Adapter interface: http://www.kondo-robot.com/EN/wp/?cat=28 Tested by controlling an RCB3 board using libRCB3. Signed-off-by: Ozan Çağlayan Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bc912e5a3beb..5620db6469e5 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -811,6 +811,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5661c7e2d415..5dd96ca6c380 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -794,6 +794,13 @@ #define PI_VID 0x1a72 /* Vendor ID */ #define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +/* + * Kondo Kagaku Co.Ltd. + * http://www.kondo-robot.com/EN + */ +#define KONDO_VID 0x165c +#define KONDO_USB_SERIAL_PID 0x0002 + /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. * http://winglucofacts.com/cables/ -- GitLab From ee6f827df9107139e8960326e49e1376352ced4d Mon Sep 17 00:00:00 2001 From: fangxiaozhi Date: Wed, 8 Aug 2012 09:24:45 +0000 Subject: [PATCH 5313/5711] USB: support the new interfaces of Huawei Data Card devices in option driver In this patch, we add new declarations into option.c to support the new interfaces of Huawei Data Card devices. And at the same time, remove the redundant declarations from option.c. Signed-off-by: fangxiaozhi Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 279 ++++++++++++++---------------------- 1 file changed, 111 insertions(+), 168 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 08ff9b862049..b09388606dc0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -80,85 +80,9 @@ static void option_instat_callback(struct urb *urb); #define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 -#define HUAWEI_PRODUCT_E600 0x1001 -#define HUAWEI_PRODUCT_E220 0x1003 -#define HUAWEI_PRODUCT_E220BIS 0x1004 -#define HUAWEI_PRODUCT_E1401 0x1401 -#define HUAWEI_PRODUCT_E1402 0x1402 -#define HUAWEI_PRODUCT_E1403 0x1403 -#define HUAWEI_PRODUCT_E1404 0x1404 -#define HUAWEI_PRODUCT_E1405 0x1405 -#define HUAWEI_PRODUCT_E1406 0x1406 -#define HUAWEI_PRODUCT_E1407 0x1407 -#define HUAWEI_PRODUCT_E1408 0x1408 -#define HUAWEI_PRODUCT_E1409 0x1409 -#define HUAWEI_PRODUCT_E140A 0x140A -#define HUAWEI_PRODUCT_E140B 0x140B -#define HUAWEI_PRODUCT_E140C 0x140C -#define HUAWEI_PRODUCT_E140D 0x140D -#define HUAWEI_PRODUCT_E140E 0x140E -#define HUAWEI_PRODUCT_E140F 0x140F -#define HUAWEI_PRODUCT_E1410 0x1410 -#define HUAWEI_PRODUCT_E1411 0x1411 -#define HUAWEI_PRODUCT_E1412 0x1412 -#define HUAWEI_PRODUCT_E1413 0x1413 -#define HUAWEI_PRODUCT_E1414 0x1414 -#define HUAWEI_PRODUCT_E1415 0x1415 -#define HUAWEI_PRODUCT_E1416 0x1416 -#define HUAWEI_PRODUCT_E1417 0x1417 -#define HUAWEI_PRODUCT_E1418 0x1418 -#define HUAWEI_PRODUCT_E1419 0x1419 -#define HUAWEI_PRODUCT_E141A 0x141A -#define HUAWEI_PRODUCT_E141B 0x141B -#define HUAWEI_PRODUCT_E141C 0x141C -#define HUAWEI_PRODUCT_E141D 0x141D -#define HUAWEI_PRODUCT_E141E 0x141E -#define HUAWEI_PRODUCT_E141F 0x141F -#define HUAWEI_PRODUCT_E1420 0x1420 -#define HUAWEI_PRODUCT_E1421 0x1421 -#define HUAWEI_PRODUCT_E1422 0x1422 -#define HUAWEI_PRODUCT_E1423 0x1423 -#define HUAWEI_PRODUCT_E1424 0x1424 -#define HUAWEI_PRODUCT_E1425 0x1425 -#define HUAWEI_PRODUCT_E1426 0x1426 -#define HUAWEI_PRODUCT_E1427 0x1427 -#define HUAWEI_PRODUCT_E1428 0x1428 -#define HUAWEI_PRODUCT_E1429 0x1429 -#define HUAWEI_PRODUCT_E142A 0x142A -#define HUAWEI_PRODUCT_E142B 0x142B -#define HUAWEI_PRODUCT_E142C 0x142C -#define HUAWEI_PRODUCT_E142D 0x142D -#define HUAWEI_PRODUCT_E142E 0x142E -#define HUAWEI_PRODUCT_E142F 0x142F -#define HUAWEI_PRODUCT_E1430 0x1430 -#define HUAWEI_PRODUCT_E1431 0x1431 -#define HUAWEI_PRODUCT_E1432 0x1432 -#define HUAWEI_PRODUCT_E1433 0x1433 -#define HUAWEI_PRODUCT_E1434 0x1434 -#define HUAWEI_PRODUCT_E1435 0x1435 -#define HUAWEI_PRODUCT_E1436 0x1436 -#define HUAWEI_PRODUCT_E1437 0x1437 -#define HUAWEI_PRODUCT_E1438 0x1438 -#define HUAWEI_PRODUCT_E1439 0x1439 -#define HUAWEI_PRODUCT_E143A 0x143A -#define HUAWEI_PRODUCT_E143B 0x143B -#define HUAWEI_PRODUCT_E143C 0x143C -#define HUAWEI_PRODUCT_E143D 0x143D -#define HUAWEI_PRODUCT_E143E 0x143E -#define HUAWEI_PRODUCT_E143F 0x143F #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 -#define HUAWEI_PRODUCT_E14AC 0x14AC -#define HUAWEI_PRODUCT_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 -#define HUAWEI_PRODUCT_K5005 0x14C8 -#define HUAWEI_PRODUCT_K3770 0x14C9 -#define HUAWEI_PRODUCT_K3771 0x14CA -#define HUAWEI_PRODUCT_K4510 0x14CB -#define HUAWEI_PRODUCT_K4511 0x14CC -#define HUAWEI_PRODUCT_ETS1220 0x1803 -#define HUAWEI_PRODUCT_E353 0x1506 -#define HUAWEI_PRODUCT_E173S 0x1C05 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -615,104 +539,123 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -- GitLab From 71a5e61b81191cfb5624add64f925990487d64c0 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 20 Jul 2012 09:33:45 +0200 Subject: [PATCH 5314/5711] usb: chipidea: fix and improve dependencies if usb host or gadget support is built as module Since commit "5e0aa49 usb: chipidea: use generic map/unmap routines", the udc part of the chipidea driver needs the generic usb gadget helper functions. If the chipidea driver with udc support is built into the kernel and usb gadget is built a module, the linking of the kernel fails with: drivers/built-in.o: In function `_hardware_dequeue': drivers/usb/chipidea/udc.c:527: undefined reference to `usb_gadget_unmap_request' drivers/usb/chipidea/udc.c:1269: undefined reference to `usb_gadget_unmap_request' drivers/usb/chipidea/udc.c:1821: undefined reference to `usb_del_gadget_udc' drivers/usb/chipidea/udc.c:443: undefined reference to `usb_gadget_map_request' drivers/usb/chipidea/udc.c:1774: undefined reference to `usb_add_gadget_udc' This patch changes the dependencies, so that udc support can only be activated if the linux gadget support (USB_GADGET) is builtin or both chipidea driver and USB_GADGET are modular. Same dependencies for the chipidea host support and the linux host side USB support (USB). While there, fix the indention of chipidea the help text. Cc: Alexander Shishkin Reviewed-by: Felipe Balbi Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/Kconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 8337fb5d988d..47e499c9c0b6 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -1,9 +1,9 @@ config USB_CHIPIDEA tristate "ChipIdea Highspeed Dual Role Controller" - depends on USB + depends on USB || USB_GADGET help - Say Y here if your system has a dual role high speed USB - controller based on ChipIdea silicon IP. Currently, only the + Say Y here if your system has a dual role high speed USB + controller based on ChipIdea silicon IP. Currently, only the peripheral mode is supported. When compiled dynamically, the module will be called ci-hdrc.ko. @@ -12,7 +12,7 @@ if USB_CHIPIDEA config USB_CHIPIDEA_UDC bool "ChipIdea device controller" - depends on USB_GADGET + depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA select USB_GADGET_DUALSPEED help Say Y here to enable device controller functionality of the @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC config USB_CHIPIDEA_HOST bool "ChipIdea host controller" + depends on USB=y || USB=USB_CHIPIDEA select USB_EHCI_ROOT_HUB_TT help Say Y here to enable host controller functionality of the -- GitLab From 872c495dd0f9d1f48814a8ee80c2c7b3b7c3b4d9 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Fri, 20 Jul 2012 15:13:35 +0530 Subject: [PATCH 5315/5711] OMAP: USB : Fix the EHCI enumeration and core retention issue This commit 354ab8567ae3107a8cbe7228c3181990ba598aac titled "Fix OMAP EHCI suspend/resume failure (i693)" is causing the usb hub and device detection fails in beagle XM causeing NFS not functional. This affects the core retention too. The same commit logic needs to be revisted adhering to hwmod and device tree framework. for now, this commit id 354ab8567ae3107a8cbe7228c3181990ba598aac titled "Fix OMAP EHCI suspend/resume failure (i693)" reverted. This patch is validated on BeagleXM with NFS support over usb ethernet and USB mass storage and other device detection. Signed-off-by: Keshava Munegowda Acked-by: Felipe Balbi Cc: stable # 3.5 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-omap.c | 167 +---------------------------------- 1 file changed, 1 insertion(+), 166 deletions(-) diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index bb55eb4a7d48..d7fe287d0678 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -56,15 +56,6 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 -/* Errata i693 */ -static struct clk *utmi_p1_fck; -static struct clk *utmi_p2_fck; -static struct clk *xclk60mhsp1_ck; -static struct clk *xclk60mhsp2_ck; -static struct clk *usbhost_p1_fck; -static struct clk *usbhost_p2_fck; -static struct clk *init_60m_fclk; - /*-------------------------------------------------------------------------*/ static const struct hc_driver ehci_omap_hc_driver; @@ -80,40 +71,6 @@ static inline u32 ehci_read(void __iomem *base, u32 reg) return __raw_readl(base + reg); } -/* Erratum i693 workaround sequence */ -static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) -{ - int ret = 0; - - /* Switch to the internal 60 MHz clock */ - ret = clk_set_parent(utmi_p1_fck, init_60m_fclk); - if (ret != 0) - ehci_err(ehci, "init_60m_fclk set parent" - "failed error:%d\n", ret); - - ret = clk_set_parent(utmi_p2_fck, init_60m_fclk); - if (ret != 0) - ehci_err(ehci, "init_60m_fclk set parent" - "failed error:%d\n", ret); - - clk_enable(usbhost_p1_fck); - clk_enable(usbhost_p2_fck); - - /* Wait 1ms and switch back to the external clock */ - mdelay(1); - ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck); - if (ret != 0) - ehci_err(ehci, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - - ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck); - if (ret != 0) - ehci_err(ehci, "xclk60mhsp2_ck set parent" - "failed error:%d\n", ret); - - clk_disable(usbhost_p1_fck); - clk_disable(usbhost_p2_fck); -} static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) { @@ -195,50 +152,6 @@ static int omap_ehci_init(struct usb_hcd *hcd) return rc; } -static int omap_ehci_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 __iomem *status_reg = &ehci->regs->port_status[ - (wIndex & 0xff) - 1]; - u32 temp; - unsigned long flags; - int retval = 0; - - spin_lock_irqsave(&ehci->lock, flags); - - if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { - temp = ehci_readl(ehci, status_reg); - if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { - retval = -EPIPE; - goto done; - } - - temp &= ~PORT_WKCONN_E; - temp |= PORT_WKDISC_E | PORT_WKOC_E; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - - omap_ehci_erratum_i693(ehci); - - set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); - goto done; - } - - spin_unlock_irqrestore(&ehci->lock, flags); - - /* Handle the hub control events here */ - return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); -done: - spin_unlock_irqrestore(&ehci->lock, flags); - return retval; -} - static void disable_put_regulator( struct ehci_hcd_omap_platform_data *pdata) { @@ -351,79 +264,9 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_pm_runtime; } - /* get clocks */ - utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); - if (IS_ERR(utmi_p1_fck)) { - ret = PTR_ERR(utmi_p1_fck); - dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_add_hcd; - } - - xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); - if (IS_ERR(xclk60mhsp1_ck)) { - ret = PTR_ERR(xclk60mhsp1_ck); - dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); - goto err_utmi_p1_fck; - } - - utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); - if (IS_ERR(utmi_p2_fck)) { - ret = PTR_ERR(utmi_p2_fck); - dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); - goto err_xclk60mhsp1_ck; - } - - xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); - if (IS_ERR(xclk60mhsp2_ck)) { - ret = PTR_ERR(xclk60mhsp2_ck); - dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); - goto err_utmi_p2_fck; - } - - usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); - if (IS_ERR(usbhost_p1_fck)) { - ret = PTR_ERR(usbhost_p1_fck); - dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); - goto err_xclk60mhsp2_ck; - } - - usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); - if (IS_ERR(usbhost_p2_fck)) { - ret = PTR_ERR(usbhost_p2_fck); - dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); - goto err_usbhost_p1_fck; - } - - init_60m_fclk = clk_get(dev, "init_60m_fclk"); - if (IS_ERR(init_60m_fclk)) { - ret = PTR_ERR(init_60m_fclk); - dev_err(dev, "init_60m_fclk failed error:%d\n", ret); - goto err_usbhost_p2_fck; - } return 0; -err_usbhost_p2_fck: - clk_put(usbhost_p2_fck); - -err_usbhost_p1_fck: - clk_put(usbhost_p1_fck); - -err_xclk60mhsp2_ck: - clk_put(xclk60mhsp2_ck); - -err_utmi_p2_fck: - clk_put(utmi_p2_fck); - -err_xclk60mhsp1_ck: - clk_put(xclk60mhsp1_ck); - -err_utmi_p1_fck: - clk_put(utmi_p1_fck); - -err_add_hcd: - usb_remove_hcd(hcd); - err_pm_runtime: disable_put_regulator(pdata); pm_runtime_put_sync(dev); @@ -454,14 +297,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) iounmap(hcd->regs); usb_put_hcd(hcd); - clk_put(utmi_p1_fck); - clk_put(utmi_p2_fck); - clk_put(xclk60mhsp1_ck); - clk_put(xclk60mhsp2_ck); - clk_put(usbhost_p1_fck); - clk_put(usbhost_p2_fck); - clk_put(init_60m_fclk); - pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -532,7 +367,7 @@ static const struct hc_driver ehci_omap_hc_driver = { * root hub support */ .hub_status_data = ehci_hub_status_data, - .hub_control = omap_ehci_hub_control, + .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, -- GitLab From 4840ae17ba7e21f2932120383a2c9a0f30e66123 Mon Sep 17 00:00:00 2001 From: Bruno Morelli Date: Mon, 30 Jul 2012 15:26:50 +0200 Subject: [PATCH 5316/5711] USB: isp1362-hcd.c: usb message always saved in case of underrun The usb message must be saved also in case the USB endpoint is not a control endpoint (i.e., "endpoint 0"), otherwise in some circumstances we don't have a payload in case of error. The patch has been created by tracing with usbmon the different error messages generated by this driver with respect to the ehci-hcd driver. Signed-off-by: Bruno Morelli Signed-off-by: Claudio Scordino Tested-by: Bruno Morelli Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 2ed112d3e159..256326322cfd 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -543,12 +543,12 @@ static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep) usb_pipein(urb->pipe) ? "IN" : "OUT", ep->nextpid, short_ok ? "" : "not_", PTD_GET_COUNT(ptd), ep->maxpacket, len); + /* save the data underrun error code for later and + * proceed with the status stage + */ + urb->actual_length += PTD_GET_COUNT(ptd); if (usb_pipecontrol(urb->pipe)) { ep->nextpid = USB_PID_ACK; - /* save the data underrun error code for later and - * proceed with the status stage - */ - urb->actual_length += PTD_GET_COUNT(ptd); BUG_ON(urb->actual_length > urb->transfer_buffer_length); if (urb->status == -EINPROGRESS) -- GitLab From f41a9b3b15e0f74656f69e6da403d870c53ea4e6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 8 Aug 2012 16:25:03 +0200 Subject: [PATCH 5317/5711] ath9k: fix interrupt storms on queued hardware reset commit b74713d04effbacd3d126ce94cec18742187b6ce "ath9k: Handle fatal interrupts properly" introduced a race condition, where IRQs are being left enabled, however the irq handler returns IRQ_HANDLED while the reset is still queued without addressing the IRQ cause. This leads to an IRQ storm that prevents the system from even getting to the reset code. Fix this by disabling IRQs in the handler without touching intr_ref_cnt. Cc: Rajkumar Manoharan Cc: Sujith Manoharan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 18 ++++++++++++------ drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7990cd55599c..b42be910a83d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -773,15 +773,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_intrpend); -void ath9k_hw_disable_interrupts(struct ath_hw *ah) +void ath9k_hw_kill_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - if (!(ah->imask & ATH9K_INT_GLOBAL)) - atomic_set(&ah->intr_ref_cnt, -1); - else - atomic_dec(&ah->intr_ref_cnt); - ath_dbg(common, INTERRUPT, "disable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_DISABLE); (void) REG_READ(ah, AR_IER); @@ -793,6 +788,17 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); } } +EXPORT_SYMBOL(ath9k_hw_kill_interrupts); + +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ + if (!(ah->imask & ATH9K_INT_GLOBAL)) + atomic_set(&ah->intr_ref_cnt, -1); + else + atomic_dec(&ah->intr_ref_cnt); + + ath9k_hw_kill_interrupts(ah); +} EXPORT_SYMBOL(ath9k_hw_disable_interrupts); void ath9k_hw_enable_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0eba36dca6f8..4a745e68dd94 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -738,6 +738,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah); void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); +void ath9k_hw_kill_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6049d8b82855..a22df749b8db 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -462,8 +462,10 @@ irqreturn_t ath_isr(int irq, void *dev) if (!ath9k_hw_intrpend(ah)) return IRQ_NONE; - if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) + if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { + ath9k_hw_kill_interrupts(ah); return IRQ_HANDLED; + } /* * Figure out the reason(s) for the interrupt. Note -- GitLab From 60f53cf99060472973f16452116d9c467f8b08c6 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 19:44:21 +0400 Subject: [PATCH 5318/5711] rndis_wlan: Fix potential memory leak in update_pmkid() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 241162e8111d..7a4ae9ee1c63 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1803,6 +1803,7 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { + struct ndis_80211_pmkid *new_pmkids; int i, err, newlen; unsigned int count; @@ -1833,11 +1834,12 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, /* add new pmkid */ newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); - pmkids = krealloc(pmkids, newlen, GFP_KERNEL); - if (!pmkids) { + new_pmkids = krealloc(pmkids, newlen, GFP_KERNEL); + if (!new_pmkids) { err = -ENOMEM; goto error; } + pmkids = new_pmkids; pmkids->length = cpu_to_le32(newlen); pmkids->bssid_info_count = cpu_to_le32(count + 1); -- GitLab From 5d774b74ef7d0428a3e45c9bb5b3a0915d2240cb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Aug 2012 09:57:30 +0300 Subject: [PATCH 5319/5711] wireless: at76c50x: signedness bug in at76_dfu_get_state() This return holds the number of bytes transfered (1 byte) or a negative error code. The type should be int instead of u8. Signed-off-by: Dan Carpenter Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index efc162e0b511..88b8d64c90f1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -342,7 +342,7 @@ static int at76_dfu_get_status(struct usb_device *udev, return ret; } -static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state) +static int at76_dfu_get_state(struct usb_device *udev, u8 *state) { int ret; -- GitLab From e19f15ac6437624b6214b2f0ec0d69fb7eb205fa Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 9 Aug 2012 12:37:26 +0530 Subject: [PATCH 5320/5711] ath9k: stop btcoex on device suspend During suspend, the device will be moved to FULLSLEEP state. As btcoex is never been stopped, the btcoex timer is running and tries to access hw on fullsleep state. Fix that. Cc: stable@vger.kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index d455de9162ec..a978984d78a5 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -321,6 +321,7 @@ static int ath_pci_suspend(struct device *device) * Otherwise the chip never moved to full sleep, * when no interface is up. */ + ath9k_stop_btcoex(sc); ath9k_hw_disable(sc->sc_ah); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); -- GitLab From 5c263b92f828af6a8cf54041db45ceae5af8f2ab Mon Sep 17 00:00:00 2001 From: Mark Ferrell Date: Tue, 24 Jul 2012 14:15:13 -0500 Subject: [PATCH 5321/5711] usb: serial: mos7840: Fixup mos7840_chars_in_buffer() * Use the buffer content length as opposed to the total buffer size. This can be a real problem when using the mos7840 as a usb serial-console as all kernel output is truncated during boot. Signed-off-by: Mark Ferrell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 57eca2448424..009c1d99e146 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1232,9 +1232,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) return 0; spin_lock_irqsave(&mos7840_port->pool_lock, flags); - for (i = 0; i < NUM_URBS; ++i) - if (mos7840_port->busy[i]) - chars += URB_TRANSFER_BUFFER_SIZE; + for (i = 0; i < NUM_URBS; ++i) { + if (mos7840_port->busy[i]) { + struct urb *urb = mos7840_port->write_urb_pool[i]; + chars += urb->transfer_buffer_length; + } + } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); dbg("%s - returns %d", __func__, chars); return chars; -- GitLab From a1028f0abfb321e0f87c10ac0cce8508097c2b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 27 Jul 2012 01:11:41 +0200 Subject: [PATCH 5322/5711] usb: usb_wwan: replace release and disconnect with a port_remove hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doing port specific cleanup in the .port_remove hook is a lot simpler and safer than doing it in the USB driver .release or .disconnect methods. The removal of the port from the usb-serial bus will happen before the USB driver cleanup, so we must be careful about accessing port specific driver data from any USB driver functions. This problem surfaced after the commit 0998d0631 device-core: Ensure drvdata = NULL when no driver is bound which turned the previous unsafe access into a reliable NULL pointer dereference. Fixes the following Oops: [ 243.148471] BUG: unable to handle kernel NULL pointer dereference at (null) [ 243.148508] IP: [] stop_read_write_urbs+0x37/0x80 [usb_wwan] [ 243.148556] PGD 79d60067 PUD 79d61067 PMD 0 [ 243.148590] Oops: 0000 [#1] SMP [ 243.148617] Modules linked in: sr_mod cdrom qmi_wwan usbnet option cdc_wdm usb_wwan usbserial usb_storage uas fuse af_packet ip6table_filter ip6_tables iptable_filter ip_tables x_tables tun edd cpufreq_conservative cpufreq_userspace cpufreq_powersave snd_pcm_oss snd_mixer_oss acpi_cpufreq snd_seq mperf snd_seq_device coretemp arc4 sg hp_wmi sparse_keymap uvcvideo videobuf2_core videodev videobuf2_vmalloc videobuf2_memops rtl8192ce rtl8192c_common rtlwifi joydev pcspkr microcode mac80211 i2c_i801 lpc_ich r8169 snd_hda_codec_idt cfg80211 snd_hda_intel snd_hda_codec rfkill snd_hwdep snd_pcm wmi snd_timer ac snd soundcore snd_page_alloc battery uhci_hcd i915 drm_kms_helper drm i2c_algo_bit ehci_hcd thermal usbcore video usb_common button processor thermal_sys [ 243.149007] CPU 1 [ 243.149027] Pid: 135, comm: khubd Not tainted 3.5.0-rc7-next-20120720-1-vanilla #1 Hewlett-Packard HP Mini 110-3700 /1584 [ 243.149072] RIP: 0010:[] [] stop_read_write_urbs+0x37/0x80 [usb_wwan] [ 243.149118] RSP: 0018:ffff880037e75b30 EFLAGS: 00010286 [ 243.149133] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88005912aa28 [ 243.149150] RDX: ffff88005e95f028 RSI: 0000000000000000 RDI: ffff88005f7c1a10 [ 243.149166] RBP: ffff880037e75b60 R08: 0000000000000000 R09: ffffffff812cea90 [ 243.149182] R10: 0000000000000000 R11: 0000000000000001 R12: ffff88006539b440 [ 243.149198] R13: ffff88006539b440 R14: 0000000000000000 R15: 0000000000000000 [ 243.149216] FS: 0000000000000000(0000) GS:ffff88007ee80000(0000) knlGS:0000000000000000 [ 243.149233] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 243.149248] CR2: 0000000000000000 CR3: 0000000079fe0000 CR4: 00000000000007e0 [ 243.149264] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 243.149280] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 243.149298] Process khubd (pid: 135, threadinfo ffff880037e74000, task ffff880037d40600) [ 243.149313] Stack: [ 243.149323] ffff880037e75b40 ffff88006539b440 ffff8800799bc830 ffff88005f7c1800 [ 243.149348] 0000000000000001 ffff88006539b448 ffff880037e75b70 ffffffffa04685e9 [ 243.149371] ffff880037e75bc0 ffffffffa0473765 ffff880037354988 ffff88007b594800 [ 243.149395] Call Trace: [ 243.149419] [] usb_wwan_disconnect+0x9/0x10 [usb_wwan] [ 243.149447] [] usb_serial_disconnect+0xd5/0x120 [usbserial] [ 243.149511] [] usb_unbind_interface+0x58/0x1a0 [usbcore] [ 243.149545] [] __device_release_driver+0x77/0xe0 [ 243.149567] [] device_release_driver+0x27/0x40 [ 243.149587] [] bus_remove_device+0xdf/0x150 [ 243.149608] [] device_del+0x118/0x1a0 [ 243.149661] [] usb_disable_device+0xb0/0x280 [usbcore] [ 243.149718] [] usb_disconnect+0x9d/0x140 [usbcore] [ 243.149770] [] hub_port_connect_change+0xad/0x8a0 [usbcore] [ 243.149825] [] ? usb_control_msg+0xe5/0x110 [usbcore] [ 243.149878] [] hub_events+0x473/0x760 [usbcore] [ 243.149931] [] hub_thread+0x35/0x1d0 [usbcore] [ 243.149955] [] ? add_wait_queue+0x60/0x60 [ 243.150004] [] ? hub_events+0x760/0x760 [usbcore] [ 243.150026] [] kthread+0x8e/0xa0 [ 243.150047] [] kernel_thread_helper+0x4/0x10 [ 243.150068] [] ? flush_kthread_work+0x120/0x120 [ 243.150088] [] ? gs_change+0xb/0xb [ 243.150101] Code: fd 41 54 53 48 83 ec 08 80 7f 1a 00 74 57 49 89 fc 31 db 90 49 8b 7c 24 20 45 31 f6 48 81 c7 10 02 00 00 e8 bc 64 f3 e0 49 89 c7 <4b> 8b 3c 37 49 83 c6 08 e8 4c a5 bd ff 49 83 fe 20 75 ed 45 30 [ 243.150257] RIP [] stop_read_write_urbs+0x37/0x80 [usb_wwan] [ 243.150282] RSP [ 243.150294] CR2: 0000000000000000 [ 243.177170] ---[ end trace fba433d9015ffb8c ]--- Reported-by: Dan Carpenter Reported-by: Thomas Schäfer Suggested-by: Alan Stern Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 3 +- drivers/usb/serial/option.c | 4 +-- drivers/usb/serial/qcserial.c | 5 ++- drivers/usb/serial/usb-wwan.h | 3 +- drivers/usb/serial/usb_wwan.c | 64 ++++++++++++++--------------------- 5 files changed, 31 insertions(+), 48 deletions(-) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 5811d34b6c6b..2cb30c535839 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -227,7 +227,6 @@ static void ipw_release(struct usb_serial *serial) { struct usb_wwan_intf_private *data = usb_get_serial_data(serial); - usb_wwan_release(serial); usb_set_serial_data(serial, NULL); kfree(data); } @@ -309,12 +308,12 @@ static struct usb_serial_driver ipw_device = { .description = "IPWireless converter", .id_table = id_table, .num_ports = 1, - .disconnect = usb_wwan_disconnect, .open = ipw_open, .close = ipw_close, .probe = ipw_probe, .attach = usb_wwan_startup, .release = ipw_release, + .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, }; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b09388606dc0..99306281dcba 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1240,8 +1240,8 @@ static struct usb_serial_driver option_1port_device = { .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, .attach = usb_wwan_startup, - .disconnect = usb_wwan_disconnect, .release = option_release, + .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, @@ -1357,8 +1357,6 @@ static void option_release(struct usb_serial *serial) struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct option_private *priv = intfdata->private; - usb_wwan_release(serial); - kfree(priv); kfree(intfdata); } diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 8d103019d6aa..314ae8ceba41 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -262,8 +262,7 @@ static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Call usb_wwan release & free the private data allocated in qcprobe */ - usb_wwan_release(serial); + /* Free the private data allocated in qcprobe */ usb_set_serial_data(serial, NULL); kfree(priv); } @@ -283,8 +282,8 @@ static struct usb_serial_driver qcdevice = { .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, .attach = usb_wwan_startup, - .disconnect = usb_wwan_disconnect, .release = qc_release, + .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, .resume = usb_wwan_resume, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index c47b6ec03063..1f034d2397c6 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -9,8 +9,7 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on); extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); extern int usb_wwan_startup(struct usb_serial *serial); -extern void usb_wwan_disconnect(struct usb_serial *serial); -extern void usb_wwan_release(struct usb_serial *serial); +extern int usb_wwan_port_remove(struct usb_serial_port *port); extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index f35971dff4a5..7d0811335b9a 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -565,62 +565,50 @@ bail_out_error: } EXPORT_SYMBOL(usb_wwan_startup); -static void stop_read_write_urbs(struct usb_serial *serial) +int usb_wwan_port_remove(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; + int i; struct usb_wwan_port_private *portdata; - /* Stop reading/writing urbs */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - for (j = 0; j < N_IN_URB; j++) - usb_kill_urb(portdata->in_urbs[j]); - for (j = 0; j < N_OUT_URB; j++) - usb_kill_urb(portdata->out_urbs[j]); + portdata = usb_get_serial_port_data(port); + usb_set_serial_port_data(port, NULL); + + /* Stop reading/writing urbs and free them */ + for (i = 0; i < N_IN_URB; i++) { + usb_kill_urb(portdata->in_urbs[i]); + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } + for (i = 0; i < N_OUT_URB; i++) { + usb_kill_urb(portdata->out_urbs[i]); + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); } -} -void usb_wwan_disconnect(struct usb_serial *serial) -{ - stop_read_write_urbs(serial); + /* Now free port private data */ + kfree(portdata); + return 0; } -EXPORT_SYMBOL(usb_wwan_disconnect); +EXPORT_SYMBOL(usb_wwan_port_remove); -void usb_wwan_release(struct usb_serial *serial) +#ifdef CONFIG_PM +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - /* Now free them */ + /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); - - for (j = 0; j < N_IN_URB; j++) { - usb_free_urb(portdata->in_urbs[j]); - free_page((unsigned long) - portdata->in_buffer[j]); - portdata->in_urbs[j] = NULL; - } - for (j = 0; j < N_OUT_URB; j++) { - usb_free_urb(portdata->out_urbs[j]); - kfree(portdata->out_buffer[j]); - portdata->out_urbs[j] = NULL; - } - } - - /* Now free per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - kfree(usb_get_serial_port_data(port)); + for (j = 0; j < N_IN_URB; j++) + usb_kill_urb(portdata->in_urbs[j]); + for (j = 0; j < N_OUT_URB; j++) + usb_kill_urb(portdata->out_urbs[j]); } } -EXPORT_SYMBOL(usb_wwan_release); -#ifdef CONFIG_PM int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) { struct usb_wwan_intf_private *intfdata = serial->private; -- GitLab From d5fd650cfc7ffeca4af0da939293c8e7a5aa7c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 27 Jul 2012 01:11:42 +0200 Subject: [PATCH 5323/5711] usb: serial: prevent suspend/resume from racing against probe/remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some usb-serial drivers may access port data in their suspend/ resume functions. Such drivers must always verify the validity of the data as both suspend and resume can be called both before usb_serial_device_probe and after usb_serial_device_remove. But the port data may be invalidated during port_probe and port_remove. This patch prevents the race against suspend and resume by disabling suspend while port_probe or port_remove is running. Suggested-by: Alan Stern Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/bus.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index f398d1e34474..c15f2e7cefc7 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -61,18 +61,23 @@ static int usb_serial_device_probe(struct device *dev) goto exit; } + /* make sure suspend/resume doesn't race against port_probe */ + retval = usb_autopm_get_interface(port->serial->interface); + if (retval) + goto exit; + driver = port->serial->type; if (driver->port_probe) { retval = driver->port_probe(port); if (retval) - goto exit; + goto exit_with_autopm; } retval = device_create_file(dev, &dev_attr_port_number); if (retval) { if (driver->port_remove) retval = driver->port_remove(port); - goto exit; + goto exit_with_autopm; } minor = port->number; @@ -81,6 +86,8 @@ static int usb_serial_device_probe(struct device *dev) "%s converter now attached to ttyUSB%d\n", driver->description, minor); +exit_with_autopm: + usb_autopm_put_interface(port->serial->interface); exit: return retval; } @@ -96,6 +103,9 @@ static int usb_serial_device_remove(struct device *dev) if (!port) return -ENODEV; + /* make sure suspend/resume doesn't race against port_remove */ + usb_autopm_get_interface(port->serial->interface); + device_remove_file(&port->dev, &dev_attr_port_number); driver = port->serial->type; @@ -107,6 +117,7 @@ static int usb_serial_device_remove(struct device *dev) dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", driver->description, minor); + usb_autopm_put_interface(port->serial->interface); return retval; } -- GitLab From 032129cb03df196c4216a82295e6555539da4ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 27 Jul 2012 01:11:43 +0200 Subject: [PATCH 5324/5711] usb: usb_wwan: resume/suspend can be called after port is gone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We cannot unconditionally access any usb-serial port specific data from the interface driver. Both supending and resuming may happen after the port has been removed and portdata is freed. Treat ports with no portdata as closed ports to avoid a NULL pointer dereference on resume. No need to kill URBs for removed ports on suspend, avoiding the same NULL pointer reference there. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_wwan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 7d0811335b9a..6855d5ed0331 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -602,6 +602,8 @@ static void stop_read_write_urbs(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; for (j = 0; j < N_IN_URB; j++) usb_kill_urb(portdata->in_urbs[j]); for (j = 0; j < N_OUT_URB; j++) @@ -700,7 +702,7 @@ int usb_wwan_resume(struct usb_serial *serial) /* skip closed ports */ spin_lock_irq(&intfdata->susp_lock); - if (!portdata->opened) { + if (!portdata || !portdata->opened) { spin_unlock_irq(&intfdata->susp_lock); continue; } -- GitLab From 61eee9a72e40551b8ee7c4d06f4e7a3f3549d296 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 1 Aug 2012 14:32:55 +0200 Subject: [PATCH 5325/5711] update MAINTAINERS for Oliver Neukum my neukum.name address has run out Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 94b823f71e94..e7e8eda91d9a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2212,7 +2212,7 @@ S: Maintained F: drivers/scsi/tmscsim.* DC395x SCSI driver -M: Oliver Neukum +M: Oliver Neukum M: Ali Akcaagac M: Jamie Lenehan W: http://twibble.org/dist/dc395x/ @@ -4533,7 +4533,7 @@ S: Supported F: arch/microblaze/ MICROTEK X6 SCANNER -M: Oliver Neukum +M: Oliver Neukum S: Maintained F: drivers/usb/image/microtek.* @@ -7071,7 +7071,7 @@ F: include/linux/mtd/ubi.h F: include/mtd/ubi-user.h USB ACM DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: Documentation/usb/acm.txt @@ -7092,7 +7092,7 @@ S: Supported F: drivers/block/ub.c USB CDC ETHERNET DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: drivers/net/usb/cdc_*.c @@ -7165,7 +7165,7 @@ F: drivers/usb/host/isp116x* F: include/linux/usb/isp116x.h USB KAWASAKI LSI DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/kl5kusb105.* -- GitLab From e7ae64c7545f48ae8672ae5026710794bc069979 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 5 Aug 2012 22:44:07 -0700 Subject: [PATCH 5326/5711] usb: renesas_usbhs: mod_host: add missing .bus_suspend/resume suspend/resume will failed on renesas_usbhs without this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_host.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 1834cf50888c..9b69a1323294 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1266,6 +1266,12 @@ static int usbhsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, return ret; } +static int usbhsh_bus_nop(struct usb_hcd *hcd) +{ + /* nothing to do */ + return 0; +} + static struct hc_driver usbhsh_driver = { .description = usbhsh_hcd_name, .hcd_priv_size = sizeof(struct usbhsh_hpriv), @@ -1290,6 +1296,8 @@ static struct hc_driver usbhsh_driver = { */ .hub_status_data = usbhsh_hub_status_data, .hub_control = usbhsh_hub_control, + .bus_suspend = usbhsh_bus_nop, + .bus_resume = usbhsh_bus_nop, }; /* -- GitLab From 5b50d3b52601651ef3183cfb33d03cf486180e48 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 5 Aug 2012 22:44:43 -0700 Subject: [PATCH 5327/5711] usb: renesas_usbhs: fixup resume method for autonomy mode If renesas_usbhs is probed as autonomy mode, phy reset should be called after power resumed, and manual cold-plug should be called with slight delay. Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 8c9bb1ad3069..681da06170c2 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -603,12 +603,12 @@ static int usbhsc_resume(struct device *dev) struct usbhs_priv *priv = dev_get_drvdata(dev); struct platform_device *pdev = usbhs_priv_to_pdev(priv); - usbhs_platform_call(priv, phy_reset, pdev); - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, 1); - usbhsc_hotplug(priv); + usbhs_platform_call(priv, phy_reset, pdev); + + usbhsc_drvcllbck_notify_hotplug(pdev); return 0; } -- GitLab From cc59c7a9633a2d68d8bf908e4e45571d10e08117 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Mon, 6 Aug 2012 17:29:31 -0500 Subject: [PATCH 5328/5711] usb: host: mips: sead3: Update for EHCI register structure. One line fix after 'struct ehci_regs' definition was changed in commit a46af4ebf9ffec35eea0390e89935197b833dc61 (USB: EHCI: define extension registers like normal ones). Signed-off-by: Steven J. Hill Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sead3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 58c96bd50d22..0c9e43cfaff5 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -40,7 +40,7 @@ static int ehci_sead3_setup(struct usb_hcd *hcd) ehci->need_io_watchdog = 0; /* Set burst length to 16 words. */ - ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]); + ehci_writel(ehci, 0x1010, &ehci->regs->reserved1[1]); return ret; } -- GitLab From ecc8a0cdca18df5c9a7e84ab29160259123f3ae5 Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Fri, 10 Aug 2012 11:42:43 +0530 Subject: [PATCH 5329/5711] usb: host: tegra: fix warning messages in ehci_remove Existing implementation of tegra_ehci_remove() calls usb_put_hcd(hcd) first and then iounmap(hcd->regs). usb_put_hcd() implementation calls hcd_release() which frees up memory allocated for hcd. As iounmap is trying to unmap hcd->regs, after hcd getting freed up, warning messages were observed during unload of USB. Hence fixing it. Signed-off-by: Venu Byravarasu Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-tegra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 950e95efa381..26dedb30ad0b 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -799,11 +799,12 @@ static int tegra_ehci_remove(struct platform_device *pdev) #endif usb_remove_hcd(hcd); - usb_put_hcd(hcd); tegra_usb_phy_close(tegra->phy); iounmap(hcd->regs); + usb_put_hcd(hcd); + clk_disable_unprepare(tegra->clk); clk_put(tegra->clk); -- GitLab From b1b552a69b8805e7e338074a9e8b670b4a795218 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 8 Aug 2012 11:48:10 +0200 Subject: [PATCH 5330/5711] usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop This patch fixes an issue introduced by patch: 72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep Without this patch we see a kworker taking 100% CPU, after this sequence: - Connect gadget to a windows host - load g_ether - ifconfig up ; ifconfig down; ifconfig up - ping The "ifconfig down" results in calling eth_stop(), which will call usb_ep_disable() and, if the carrier is still ok, usb_ep_enable(): usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } The ep should stay enabled, but will not, as ep_disable set the desc pointer to NULL, therefore the subsequent ep_enable will fail. This leads to permanent rescheduling of the eth_work() worker as usb_ep_queue() (called by the worker) will fail due to the unconfigured endpoint. We fix this issue by saving the ep descriptors and re-assign them before usb_ep_enable(). Cc: Tatyana Brokhman Signed-off-by: Michael Grzeschik Signed-off-by: Marc Kleine-Budde Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/u_ether.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 90e82e288eb9..0e5230926154 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -669,6 +669,8 @@ static int eth_stop(struct net_device *net) spin_lock_irqsave(&dev->lock, flags); if (dev->port_usb) { struct gether *link = dev->port_usb; + const struct usb_endpoint_descriptor *in; + const struct usb_endpoint_descriptor *out; if (link->close) link->close(link); @@ -682,10 +684,14 @@ static int eth_stop(struct net_device *net) * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ + in = link->in_ep->desc; + out = link->out_ep->desc; usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { DBG(dev, "host still using in/out endpoints\n"); + link->in_ep->desc = in; + link->out_ep->desc = out; usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } -- GitLab From df7fba66471c6bbbaebb55e1bb3658eb7ce00a9b Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Fri, 3 Aug 2012 08:26:45 +0000 Subject: [PATCH 5331/5711] IB/mlx4: Fix possible deadlock on sm_lock spinlock The sm_lock spinlock is taken in the process context by mlx4_ib_modify_device, and in the interrupt context by update_sm_ah, so we need to take that spinlock with irqsave, and release it with irqrestore. Lockdeps reports this as follows: [ INFO: inconsistent lock state ] 3.5.0+ #20 Not tainted inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes: (&(&ibdev->sm_lock)->rlock){?.+...}, at: [] update_sm_ah+0xad/0x100 [mlx4_ib] {HARDIRQ-ON-W} state was registered at: [] mark_irqflags+0x120/0x190 [] __lock_acquire+0x307/0x4c0 [] lock_acquire+0xb1/0x150 [] _raw_spin_lock+0x41/0x50 [] mlx4_ib_modify_device+0x63/0x240 [mlx4_ib] [] ib_modify_device+0x1c/0x20 [ib_core] [] set_node_desc+0x83/0xc0 [ib_core] [] dev_attr_store+0x20/0x30 [] sysfs_write_file+0xe6/0x170 [] vfs_write+0xc8/0x190 [] sys_write+0x51/0x90 [] system_call_fastpath+0x16/0x1b ... *** DEADLOCK *** 1 lock held by swapper/0/0: stack backtrace: Pid: 0, comm: swapper/0 Not tainted 3.5.0+ #20 Call Trace: [] print_usage_bug+0x18a/0x190 [] ? print_irq_inversion_bug+0x210/0x210 [] mark_lock_irq+0xf2/0x280 [] mark_lock+0x150/0x240 [] mark_irqflags+0x16f/0x190 [] __lock_acquire+0x307/0x4c0 [] ? update_sm_ah+0xad/0x100 [mlx4_ib] [] lock_acquire+0xb1/0x150 [] ? update_sm_ah+0xad/0x100 [mlx4_ib] [] _raw_spin_lock+0x41/0x50 [] ? update_sm_ah+0xad/0x100 [mlx4_ib] [] ? ib_create_ah+0x1a/0x40 [ib_core] [] update_sm_ah+0xad/0x100 [mlx4_ib] [] ? is_module_address+0x23/0x30 [] handle_port_mgmt_change_event+0xeb/0x150 [mlx4_ib] [] mlx4_ib_event+0x117/0x160 [mlx4_ib] [] ? _raw_spin_lock_irqsave+0x61/0x70 [] mlx4_dispatch_event+0x6c/0x90 [mlx4_core] [] mlx4_eq_int+0x500/0x950 [mlx4_core] Reported by: Or Gerlitz Tested-by: Bart Van Assche Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 16 ++++++++++------ drivers/infiniband/hw/mlx4/main.c | 5 +++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index c27141fef1ab..9c2ae7efd00f 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -125,6 +125,7 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) { struct ib_ah *new_ah; struct ib_ah_attr ah_attr; + unsigned long flags; if (!dev->send_agent[port_num - 1][0]) return; @@ -139,11 +140,11 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) if (IS_ERR(new_ah)) return; - spin_lock(&dev->sm_lock); + spin_lock_irqsave(&dev->sm_lock, flags); if (dev->sm_ah[port_num - 1]) ib_destroy_ah(dev->sm_ah[port_num - 1]); dev->sm_ah[port_num - 1] = new_ah; - spin_unlock(&dev->sm_lock); + spin_unlock_irqrestore(&dev->sm_lock, flags); } /* @@ -197,13 +198,15 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, static void node_desc_override(struct ib_device *dev, struct ib_mad *mad) { + unsigned long flags; + if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP && mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { - spin_lock(&to_mdev(dev)->sm_lock); + spin_lock_irqsave(&to_mdev(dev)->sm_lock, flags); memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); - spin_unlock(&to_mdev(dev)->sm_lock); + spin_unlock_irqrestore(&to_mdev(dev)->sm_lock, flags); } } @@ -213,6 +216,7 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma struct ib_mad_send_buf *send_buf; struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn]; int ret; + unsigned long flags; if (agent) { send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, @@ -225,13 +229,13 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma * wrong following the IB spec strictly, but we know * it's OK for our devices). */ - spin_lock(&dev->sm_lock); + spin_lock_irqsave(&dev->sm_lock, flags); memcpy(send_buf->mad, mad, sizeof *mad); if ((send_buf->ah = dev->sm_ah[port_num - 1])) ret = ib_post_send_mad(send_buf, NULL); else ret = -EINVAL; - spin_unlock(&dev->sm_lock); + spin_unlock_irqrestore(&dev->sm_lock, flags); if (ret) ib_free_send_mad(send_buf); diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index fe2088cfa6ee..cc05579ebce7 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -423,6 +423,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, struct ib_device_modify *props) { struct mlx4_cmd_mailbox *mailbox; + unsigned long flags; if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) return -EOPNOTSUPP; @@ -430,9 +431,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, if (!(mask & IB_DEVICE_MODIFY_NODE_DESC)) return 0; - spin_lock(&to_mdev(ibdev)->sm_lock); + spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags); memcpy(ibdev->node_desc, props->node_desc, 64); - spin_unlock(&to_mdev(ibdev)->sm_lock); + spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags); /* * If possible, pass node desc to FW, so it can generate -- GitLab From b53cc0fadef59583a9056c973e639852bed47e73 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 31 Jul 2012 18:29:08 +0400 Subject: [PATCH 5332/5711] serial: Change Kconfig entry for CLPS711X-target This trivial patch adds a short description for SERIAL_CLPS711X Kconfig entry, removes excess dependence on the ARM-platform (this is done globally for the platform), allows the driver to be compiled by default and removes unnecessary description about GRUB and LILO, because these bootloaders do not supported this platform. Signed-off-by: Alexander Shiyan Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 070b442c1f81..4720b4ba096a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -160,10 +160,12 @@ config SERIAL_KS8695_CONSOLE config SERIAL_CLPS711X tristate "CLPS711X serial port support" - depends on ARM && ARCH_CLPS711X + depends on ARCH_CLPS711X select SERIAL_CORE + default y help - ::: To be written ::: + This enables the driver for the on-chip UARTs of the Cirrus + Logic EP711x/EP721x/EP731x processors. config SERIAL_CLPS711X_CONSOLE bool "Support for console on CLPS711X serial port" @@ -173,9 +175,7 @@ config SERIAL_CLPS711X_CONSOLE Even if you say Y here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as - "console=ttyCL1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) + "console=ttyCL1". config SERIAL_SAMSUNG tristate "Samsung SoC serial support" -- GitLab From 7d9739cd6b03575bc88c6ce3c60853dbc50a6ae2 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 7 Aug 2012 13:12:47 +0800 Subject: [PATCH 5333/5711] serial: ifx6x60: fix paging fault on spi_register_driver [ 117.240866] BUG: unable to handle kernel paging request at 815b627c [ 117.240866] IP: [<813fe94b>] spi_register_driver+0xb/0x50 ... [ 117.240866] Call Trace: [ 117.240866] [<817de977>] ifx_spi_init+0xbe/0xf0 The root cause is, spi_register_driver() is trying to write into the passed *const* struct spi_driver. Signed-off-by: Fengguang Wu Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 144cd3987d4c..3ad079ffd049 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1331,7 +1331,7 @@ static const struct spi_device_id ifx_id_table[] = { MODULE_DEVICE_TABLE(spi, ifx_id_table); /* spi operations */ -static const struct spi_driver ifx_spi_driver = { +static struct spi_driver ifx_spi_driver = { .driver = { .name = DRVNAME, .pm = &ifx_spi_pm, -- GitLab From b5ec8eeac46a99004c26791f70b15d001e970acf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 10 Aug 2012 02:22:47 +0000 Subject: [PATCH 5334/5711] ipv4: fix ip_send_skb() ip_send_skb() can send orphaned skb, so we must pass the net pointer to avoid possible NULL dereference in error path. Bug added by commit 3a7c384ffd57 (ipv4: tcp: unicast_sock should not land outside of TCP stack) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 2 +- net/ipv4/ip_output.c | 5 ++--- net/ipv4/udp.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index bd5e444a19ce..5a5d84d3d2c6 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -120,7 +120,7 @@ extern struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, struct sk_buff_head *queue, struct inet_cork *cork); -extern int ip_send_skb(struct sk_buff *skb); +extern int ip_send_skb(struct net *net, struct sk_buff *skb); extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); extern void ip_flush_pending_frames(struct sock *sk); extern struct sk_buff *ip_make_skb(struct sock *sk, diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ec410e08b4b9..147ccc3e93db 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1366,9 +1366,8 @@ out: return skb; } -int ip_send_skb(struct sk_buff *skb) +int ip_send_skb(struct net *net, struct sk_buff *skb) { - struct net *net = sock_net(skb->sk); int err; err = ip_local_out(skb); @@ -1391,7 +1390,7 @@ int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) return 0; /* Netfilter gets whole the not fragmented skb. */ - return ip_send_skb(skb); + return ip_send_skb(sock_net(sk), skb); } /* diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b4c3582a991f..6f6d1aca3c3d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -758,7 +758,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) uh->check = CSUM_MANGLED_0; send: - err = ip_send_skb(skb); + err = ip_send_skb(sock_net(sk), skb); if (err) { if (err == -ENOBUFS && !inet->recverr) { UDP_INC_STATS_USER(sock_net(sk), -- GitLab From 484d90eec884d814b005c9736bcf3fd018acba65 Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Fri, 10 Aug 2012 11:49:06 -0700 Subject: [PATCH 5335/5711] x86, build: Globally set -fno-pic GCC built with nonstandard options can enable -fpic by default. We never want this for 32-bit kernels and it will break the build. [ hpa: Notably the Android toolchain apparently does this. ] Change-Id: Iaab7d66e598b1c65ac4a4f0229eca2cd3d0d2898 Signed-off-by: Andrew Boie Link: http://lkml.kernel.org/r/1344624546-29691-1-git-send-email-andrew.p.boie@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/Makefile | 4 ++++ arch/x86/boot/Makefile | 2 +- arch/x86/realmode/rm/Makefile | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index b0c5276861ec..682e9c210baa 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -27,6 +27,10 @@ ifeq ($(CONFIG_X86_32),y) KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return + # Never want PIC in a 32-bit kernel, prevent breakage with GCC built + # with nonstandard options + KBUILD_CFLAGS += -fno-pic + # prevent gcc from keeping the stack 16 byte aligned KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 5a747dd884db..f7535bedc33f 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -57,7 +57,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/code16gcc.h \ - -fno-strict-aliasing -fomit-frame-pointer \ + -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ $(call cc-option, -ffreestanding) \ $(call cc-option, -fno-toplevel-reorder,\ $(call cc-option, -fno-unit-at-a-time)) \ diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index b2d534cab25f..88692871823f 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -72,7 +72,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/../../boot/code16gcc.h \ - -fno-strict-aliasing -fomit-frame-pointer \ + -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ $(call cc-option, -ffreestanding) \ $(call cc-option, -fno-toplevel-reorder,\ $(call cc-option, -fno-unit-at-a-time)) \ -- GitLab From 55461ddbcb0b36d1575e01fb4f130c609ca1cfee Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 10 Aug 2012 07:35:14 +0000 Subject: [PATCH 5336/5711] ixgbe: add missing braces This patch adds missing braces around the 10gig link check to include the check for KR support. Signed-off-by: Emil Tantilov Reported-by: Sascha Wildner Tested-by: Phil Schmitt Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 50fc137501da..18bf08c9d7a4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -804,12 +804,13 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); - if (speed & IXGBE_LINK_SPEED_10GB_FULL) + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && (hw->phy.smart_speed_active == false)) autoc |= IXGBE_AUTOC_KR_SUPP; + } if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && -- GitLab From d549f55f2e132e3d1f1288ce4231f45f12988bbf Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 10 Aug 2012 16:52:13 -0700 Subject: [PATCH 5337/5711] RDMA/ocrdma: Don't call vlan_dev_real_dev() for non-VLAN netdevs If CONFIG_VLAN_8021Q is not set, then vlan_dev_real_dev() just goes BUG(), so we shouldn't call it unless we're actually dealing with a VLAN netdev. Reported-by: Fengguang Wu Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 5a044526e4f4..c4e0131f1b57 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -161,7 +161,7 @@ static void ocrdma_add_default_sgid(struct ocrdma_dev *dev) ocrdma_get_guid(dev, &sgid->raw[8]); } -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if IS_ENABLED(CONFIG_VLAN_8021Q) static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev) { struct net_device *netdev, *tmp; @@ -202,14 +202,13 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev) return 0; } -#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_VLAN_8021Q) +#if IS_ENABLED(CONFIG_IPV6) static int ocrdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; - struct net_device *event_netdev = ifa->idev->dev; - struct net_device *netdev = NULL; + struct net_device *netdev = ifa->idev->dev; struct ib_event gid_event; struct ocrdma_dev *dev; bool found = false; @@ -217,11 +216,12 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier, bool is_vlan = false; u16 vid = 0; - netdev = vlan_dev_real_dev(event_netdev); - if (netdev != event_netdev) { - is_vlan = true; - vid = vlan_dev_vlan_id(event_netdev); + is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN; + if (is_vlan) { + vid = vlan_dev_vlan_id(netdev); + netdev = vlan_dev_real_dev(netdev); } + rcu_read_lock(); list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) { if (dev->nic_info.netdev == netdev) { -- GitLab From 2359a47671fc4fb0fe5e9945f76c2cb10792c0f8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 29 Jul 2012 20:52:21 +0000 Subject: [PATCH 5338/5711] codel: refine one condition to avoid a nul rec_inv_sqrt One condition before codel_Newton_step() was not good if we never left the dropping state for a flow. As a result rec_inv_sqrt was 0, instead of the ~0 initial value. codel control law was then set to a very aggressive mode, dropping many packets before reaching 'target' and recovering from this problem. To keep codel_vars_init() as efficient as possible, refine the condition to make sure rec_inv_sqrt initial value is correct Many thanks to Anton Mich for discovering the issue and suggesting a fix. Reported-by: Anton Mich Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/codel.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/net/codel.h b/include/net/codel.h index 550debfc2403..389cf621161d 100644 --- a/include/net/codel.h +++ b/include/net/codel.h @@ -305,6 +305,8 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, } } } else if (drop) { + u32 delta; + if (params->ecn && INET_ECN_set_ce(skb)) { stats->ecn_mark++; } else { @@ -320,9 +322,11 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, * assume that the drop rate that controlled the queue on the * last cycle is a good starting point to control it now. */ - if (codel_time_before(now - vars->drop_next, + delta = vars->count - vars->lastcount; + if (delta > 1 && + codel_time_before(now - vars->drop_next, 16 * params->interval)) { - vars->count = (vars->count - vars->lastcount) | 1; + vars->count = delta; /* we dont care if rec_inv_sqrt approximation * is not very precise : * Next Newton steps will correct it quadratically. -- GitLab From f7e416eb923d0f9ff1e5e9b5c0e8b75ddd7db865 Mon Sep 17 00:00:00 2001 From: Venkatraman Sathiyamoorthy Date: Fri, 3 Aug 2012 07:58:33 +0100 Subject: [PATCH 5339/5711] ARM: 7482/1: topology: fix section mismatch warning for init_cpu_topology Get rid of this warning.. arch/arm/kernel/built-in.o(.text+0xac78): Section mismatch in reference from the function init_cpu_topology() to the function .init.text:parse_dt_topology() The function init_cpu_topology() references the function __init parse_dt_topology(). This is often because init_cpu_topology lacks a __init annotation or the annotation of parse_dt_topology is wrong. Signed-off-by: Venkatraman S Signed-off-by: Russell King --- arch/arm/kernel/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 198b08456e90..26c12c6440fc 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -321,7 +321,7 @@ void store_cpu_topology(unsigned int cpuid) * init_cpu_topology is called at boot when only one cpu is running * which prevent simultaneous write access to cpu_topology array */ -void init_cpu_topology(void) +void __init init_cpu_topology(void) { unsigned int cpu; -- GitLab From 3d9fb0038a9b02febb01efc79a4a5d97f1822a90 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Aug 2012 17:24:14 +0100 Subject: [PATCH 5340/5711] ARM: 7483/1: vfp: only advertise VFPv4 in hwcaps if CONFIG_VFPv3 is enabled VFPv4 support depends on the VFPv3 context save/restore code, so only advertise support in the hwcaps if the kernel can actually handle it. Cc: # 3.1+ Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/vfp/vfpmodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index fb849d044bde..c834b32af275 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -719,8 +719,10 @@ static int __init vfp_init(void) if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) elf_hwcap |= HWCAP_NEON; #endif +#ifdef CONFIG_VFPv3 if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) elf_hwcap |= HWCAP_VFPv4; +#endif } } return 0; -- GitLab From f1898f6be9a2e3690fb62d8307849b86a89cc36c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 6 Aug 2012 18:43:42 +0100 Subject: [PATCH 5341/5711] ARM: 7484/1: Don't enable GENERIC_LOCKBREAK with ticket spinlocks Now that ARM has implemented its spinlocks with tickets we don't need to use the generic lockbreak algorithm. Remove the Kconfig from ARM so that we use the arch_spin_is_contended() definition from the asm header. This also saves a word in each lock because we don't need the break_lock member anymore. Signed-off-by: Stephen Boyd Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e91c7cdc6fe5..e4191ccbdb7a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -126,11 +126,6 @@ config TRACE_IRQFLAGS_SUPPORT bool default y -config GENERIC_LOCKBREAK - bool - default y - depends on SMP && PREEMPT - config RWSEM_GENERIC_SPINLOCK bool default y -- GitLab From 237ec6f2e51d2fc2ff37c7c5f1ccc9264d09c85b Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 7 Aug 2012 19:05:10 +0100 Subject: [PATCH 5342/5711] ARM: 7486/1: sched_clock: update epoch_cyc on resume Many clocks that are used to provide sched_clock will reset during suspend. If read_sched_clock returns 0 after suspend, sched_clock will appear to jump forward. This patch resets cd.epoch_cyc to the current value of read_sched_clock during resume, which causes sched_clock() just after suspend to return the same value as sched_clock() just before suspend. In addition, during the window where epoch_ns has been updated before suspend, but epoch_cyc has not been updated after suspend, it is unknown whether the clock has reset or not, and sched_clock() could return a bogus value. Add a suspended flag, and return the pre-suspend epoch_ns value during this period. The new behavior is triggered by calling setup_sched_clock_needs_suspend instead of setup_sched_clock. Signed-off-by: Colin Cross Reviewed-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/include/asm/sched_clock.h | 2 ++ arch/arm/kernel/sched_clock.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index e3f757263438..05b8e82ec9f5 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -10,5 +10,7 @@ extern void sched_clock_postinit(void); extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); +extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, + unsigned long rate); #endif diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 27d186abbc06..f4515393248d 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -21,6 +21,8 @@ struct clock_data { u32 epoch_cyc_copy; u32 mult; u32 shift; + bool suspended; + bool needs_suspend; }; static void sched_clock_poll(unsigned long wrap_ticks); @@ -49,6 +51,9 @@ static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) u64 epoch_ns; u32 epoch_cyc; + if (cd.suspended) + return cd.epoch_ns; + /* * Load the epoch_cyc and epoch_ns atomically. We do this by * ensuring that we always write epoch_cyc, epoch_ns and @@ -98,6 +103,13 @@ static void sched_clock_poll(unsigned long wrap_ticks) update_sched_clock(); } +void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, + unsigned long rate) +{ + setup_sched_clock(read, bits, rate); + cd.needs_suspend = true; +} + void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) { unsigned long r, w; @@ -169,11 +181,23 @@ void __init sched_clock_postinit(void) static int sched_clock_suspend(void) { sched_clock_poll(sched_clock_timer.data); + if (cd.needs_suspend) + cd.suspended = true; return 0; } +static void sched_clock_resume(void) +{ + if (cd.needs_suspend) { + cd.epoch_cyc = read_sched_clock(); + cd.epoch_cyc_copy = cd.epoch_cyc; + cd.suspended = false; + } +} + static struct syscore_ops sched_clock_ops = { .suspend = sched_clock_suspend, + .resume = sched_clock_resume, }; static int __init sched_clock_syscore_init(void) -- GitLab From 47f1204329237a0f8655f5a9f14a38ac81946ca1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 17:51:18 +0100 Subject: [PATCH 5343/5711] ARM: 7487/1: mm: avoid setting nG bit for user mappings that aren't present Swap entries are encoding in ptes such that !pte_present(pte) and pte_file(pte). The remaining bits of the descriptor are used to identify the swapfile and offset within it to the swap entry. When writing such a pte for a user virtual address, set_pte_at unconditionally sets the nG bit, which (in the case of LPAE) will corrupt the swapfile offset and lead to a BUG: [ 140.494067] swap_free: Unused swap offset entry 000763b4 [ 140.509989] BUG: Bad page map in process rs:main Q:Reg pte:0ec76800 pmd:8f92e003 This patch fixes the problem by only setting the nG bit for user mappings that are actually present. Cc: Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 34 ++++++++++++++++++---------------- arch/arm/mm/flush.c | 2 -- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7d..d88f9f049e95 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -195,6 +195,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) +#define pte_special(pte) (0) + +#define pte_present_user(pte) \ + ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ + (L_PTE_PRESENT | L_PTE_USER)) + #if __LINUX_ARM_ARCH__ < 6 static inline void __sync_icache_dcache(pte_t pteval) { @@ -206,25 +218,15 @@ extern void __sync_icache_dcache(pte_t pteval); static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { - if (addr >= TASK_SIZE) - set_pte_ext(ptep, pteval, 0); - else { + unsigned long ext = 0; + + if (addr < TASK_SIZE && pte_present_user(pteval)) { __sync_icache_dcache(pteval); - set_pte_ext(ptep, pteval, PTE_EXT_NG); + ext |= PTE_EXT_NG; } -} -#define pte_none(pte) (!pte_val(pte)) -#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) -#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) -#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) -#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) -#define pte_special(pte) (0) - -#define pte_present_user(pte) \ - ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ - (L_PTE_PRESENT | L_PTE_USER)) + set_pte_ext(ptep, pteval, ext); +} #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 77458548e031..40ca11ed6e5f 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -231,8 +231,6 @@ void __sync_icache_dcache(pte_t pteval) struct page *page; struct address_space *mapping; - if (!pte_present_user(pteval)) - return; if (cache_is_vipt_nonaliasing() && !pte_exec(pteval)) /* only flush non-aliasing VIPT caches for exec mappings */ return; -- GitLab From f5f2025ef3e2cdb593707cbf87378761f17befbe Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 17:51:19 +0100 Subject: [PATCH 5344/5711] ARM: 7488/1: mm: use 5 bits for swapfile type encoding Page migration encodes the pfn in the offset field of a swp_entry_t. For LPAE, we support physical addresses of up to 36 bits (due to sparsemem limitations with the size of page flags), requiring 24 bits to represent a pfn. A further 3 bits are used to encode a swp_entry into a pte, leaving 5 bits for the type field. Furthermore, the core code defines MAX_SWAPFILES_SHIFT as 5, so the additional type bit does not get used. This patch reduces the width of the type field to 5 bits, allowing us to create up to 31 swapfiles of 64GB each. Cc: Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index d88f9f049e95..41dc31f834c3 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -253,13 +253,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <--------------- offset --------------------> <- type --> 0 0 0 + * <--------------- offset ----------------------> < type -> 0 0 0 * - * This gives us up to 63 swap files and 32GB per swap file. Note that + * This gives us up to 31 swap files and 64GB per swap file. Note that * the offset field is always non-zero. */ #define __SWP_TYPE_SHIFT 3 -#define __SWP_TYPE_BITS 6 +#define __SWP_TYPE_BITS 5 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) -- GitLab From 730a8128cd8978467eb1cf546b11014acb57d433 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 19:13:36 +0100 Subject: [PATCH 5345/5711] ARM: 7489/1: errata: fix workaround for erratum #720789 on UP systems Commit 5a783cbc4836 ("ARM: 7478/1: errata: extend workaround for erratum #720789") added workarounds for erratum #720789 to the range TLB invalidation functions with the observation that the erratum only affects SMP platforms. However, when running an SMP_ON_UP kernel on a uniprocessor platform we must take care to preserve the ASID as the workaround is not required. This patch ensures that we don't set the ASID to 0 when flushing the TLB on such a system, preserving the original behaviour with the workaround disabled. Cc: Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/tlb-v7.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index c2021139cb56..ea94765acf9a 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -38,10 +38,10 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT -#ifdef CONFIG_ARM_ERRATA_720789 - mov r3, #0 -#else asid r3, r3 @ mask ASID +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(W(mov) r3, #0 ) + ALT_UP(W(nop) ) #endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT -- GitLab From 8a3f0ede2b3f5477122060af1a816c6bbf09fcd2 Mon Sep 17 00:00:00 2001 From: Jayakrishnan Memana Date: Sun, 15 Jul 2012 10:54:03 -0300 Subject: [PATCH 5346/5711] [media] uvcvideo: Reset the bytesused field when recycling an erroneous buffer Buffers marked as erroneous are recycled immediately by the driver if the nodrop module parameter isn't set. The buffer payload size is reset to 0, but the buffer bytesused field isn't. This results in the buffer being immediately considered as complete, leading to an infinite loop in interrupt context. Fix the problem by resetting the bytesused field when recycling the buffer. Cc: Signed-off-by: Jayakrishnan Memana Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 9288fbd5001b..5577381b5bf0 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; + buf->bytesused = 0; vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } -- GitLab From 467548aa9fe91c35fc908a844129a788aec6a2d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 3 Aug 2012 11:16:29 -0300 Subject: [PATCH 5347/5711] [media] DocBook: Remove a spurious character Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-g-tuner.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index 720395127904..701138f1209d 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -125,7 +125,7 @@ the structure refers to a radio tuner the V4L2_TUNER_CAP_NORM flags can't be used. If multiple frequency bands are supported, then capability is the union of all -capability> fields of each &v4l2-frequency-band;. +capability fields of each &v4l2-frequency-band;. -- GitLab From 3273781068268c404ea239dde4f6c246686dfa00 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 3 Aug 2012 11:16:59 -0300 Subject: [PATCH 5348/5711] [media] si470x: v4l2-compliance fixes Just a few fixes for problems found after updating v4l2-compliance to check the frequency band enumeration. Note that the i2c driver doesn't fill in bus_info, but since I can't test that driver I've decided not to fix that. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-common.c | 3 +++ drivers/media/radio/si470x/radio-si470x-i2c.c | 5 +++-- drivers/media/radio/si470x/radio-si470x-usb.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 9e38132afec6..9bb65e170d99 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -151,6 +151,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 0, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 87500 * 16, @@ -162,6 +163,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 1, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, @@ -173,6 +175,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 2, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 643a6ff7c5d0..f867f04cccc9 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -225,8 +225,9 @@ int si470x_vidioc_querycap(struct file *file, void *priv, { strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | - V4L2_CAP_TUNER | V4L2_CAP_RADIO; + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; + capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 146be4263ea1..be076f7181e7 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -531,7 +531,7 @@ int si470x_vidioc_querycap(struct file *file, void *priv, strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); - capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; -- GitLab From 770c12312ad617172b1a65b911d3e6564fc5aca8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 11 Aug 2012 08:56:42 +0200 Subject: [PATCH 5349/5711] drm/i915: Fix blank panel at reopening lid When you reopen the lid on a laptop with PCH, the panel suddenly goes blank sometimes. It seems because BLC_PWM_CPU_CTL register is cleared to zero when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 registers are enabled. This patch fixes the problem by moving the call of the function setting BLC_PWM_CPU_CTL after enabling other two registers. Reported-and-tested-by: Hugh Dickins Signed-off-by: Takashi Iwai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 9474488db948..3df4f5fa892a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -311,9 +311,6 @@ void intel_panel_enable_backlight(struct drm_device *dev, if (dev_priv->backlight_level == 0) dev_priv->backlight_level = intel_panel_get_max_backlight(dev); - dev_priv->backlight_enabled = true; - intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); - if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; @@ -326,7 +323,7 @@ void intel_panel_enable_backlight(struct drm_device *dev, * we don't track the backlight dpms state, hence check whether * we have to do anything first. */ if (tmp & BLM_PWM_ENABLE) - return; + goto set_level; if (dev_priv->num_pipe == 3) tmp &= ~BLM_PIPE_SELECT_IVB; @@ -347,6 +344,14 @@ void intel_panel_enable_backlight(struct drm_device *dev, I915_WRITE(BLC_PWM_PCH_CTL1, tmp); } } + +set_level: + /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. + * BLC_PWM_CPU_CTL may be cleared to zero automatically when these + * registers are set. + */ + dev_priv->backlight_enabled = true; + intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); } static void intel_panel_init_backlight(struct drm_device *dev) -- GitLab From 4344b813f105a19f793f1fd93ad775b784648b95 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Aug 2012 11:10:20 +0200 Subject: [PATCH 5350/5711] drm/i915: ignore eDP bpc settings from vbt This has originally been introduced to not oversubscribe the dp links in commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Author: Zhenyu Wang Date: Tue Jan 12 05:38:31 2010 +0800 drm/i915: fix pixel color depth setting on eDP Since then we've fixed up the dp link bandwidth calculation code and should now automatically fall back to 6bpc dithering. So this is unnecessary. Furthermore it seems to break the new MacbookPro with retina display, hence let's just rip this out. Reported-by: Benoit Gschwind Cc: Benoit Gschwind Cc: Francois Rigaut Cc: Greg KH Cc: stable@vger.kernel.org Tested-by: Benoit Gschwind Tested-by: Bernhard Froemel Signed-off-by: Daniel Vetter -- Testing feedback highgly welcome, and thanks for Benoit for finding out that the bpc computations are busted. -Daniel --- drivers/gpu/drm/i915/intel_display.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 88913a47cd34..a69a3d0d3acf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3754,17 +3754,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, continue; } - if (intel_encoder->type == INTEL_OUTPUT_EDP) { - /* Use VBT settings if we have an eDP panel */ - unsigned int edp_bpc = dev_priv->edp.bpp / 3; - - if (edp_bpc < display_bpc) { - DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); - display_bpc = edp_bpc; - } - continue; - } - /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- GitLab From 00424c7ec5d39044df1ce79d48ff3022838aad44 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Aug 2012 03:32:33 -0300 Subject: [PATCH 5351/5711] [media] mem2mem_testdev: fix querycap regression Trival but important patch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 7efe9ad7acc7..0b91a5cd38eb 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -431,7 +431,7 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -- GitLab From aa4d9b53f0d71ff805bbd1e30fcba9d1827a7dd8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Aug 2012 15:52:46 -0300 Subject: [PATCH 5352/5711] [media] VIDIOC_ENUM_FREQ_BANDS fix When VIDIOC_ENUM_FREQ_BANDS is called for a driver that doesn't supply an enum_freq_bands op, then it will fall back to reporting a single freq band based on information from g_tuner or g_modulator. Due to a bug this is an infinite list since the index field wasn't tested. This patch fixes this and returns -EINVAL if index != 0. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index c3b7b5f59b32..54f4ac612e8e 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1853,6 +1853,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, .type = type, }; + if (p->index) + return -EINVAL; err = ops->vidioc_g_tuner(file, fh, &t); if (err) return err; @@ -1870,6 +1872,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, if (type != V4L2_TUNER_RADIO) return -EINVAL; + if (p->index) + return -EINVAL; err = ops->vidioc_g_modulator(file, fh, &m); if (err) return err; -- GitLab From 5e78831756bc455f334782514f2e1b0f605a81d6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Aug 2012 16:18:41 -0300 Subject: [PATCH 5353/5711] [media] Add missing logging for rangelow/high of hwseek struct v4l2_hw_freq_seek has two new fields that weren't printed in the logging function. Added. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 54f4ac612e8e..6bc47fc82fe2 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -402,8 +402,10 @@ static void v4l_print_hw_freq_seek(const void *arg, bool write_only) { const struct v4l2_hw_freq_seek *p = arg; - pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", - p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); + pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " + "rangelow=%u, rangehigh=%u\n", + p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, + p->rangelow, p->rangehigh); } static void v4l_print_requestbuffers(const void *arg, bool write_only) -- GitLab From ac6eb458f5f9d45dd3bbfe8a91683c09860910c5 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 6 Aug 2012 00:15:20 -0300 Subject: [PATCH 5354/5711] [media] Add USB dependency for IguanaWorks USB IR Transceiver This patch fixes the error drivers/usb/core/hub.c:3753: undefined reference to `usb_speed_string' seen in various random configurations. Cc: Sean Young Cc: Mauro Carvalho Chehab Signed-off-by: Guenter Roeck Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5180390be7ab..8be57634ba60 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -261,6 +261,7 @@ config IR_WINBOND_CIR config IR_IGUANA tristate "IguanaWorks USB IR Transceiver" + depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB ---help--- -- GitLab From 820ddfa6ca87fc12bf202907b77f635df2098e66 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 11 Aug 2012 06:34:52 -0300 Subject: [PATCH 5355/5711] [media] radio-shark*: Remove work-around for dangling pointer in usb intfdata Recent kernels properly clear the usb intfdata pointer when another driver fails to bind (in the radio-shark* case the usbhid driver would try to bind first. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark.c | 9 --------- drivers/media/radio/radio-shark2.c | 9 --------- 2 files changed, 18 deletions(-) diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index d0b6bb507634..e35b8d938a30 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -286,15 +286,6 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - /* - * Work around a bug in usbhid/hid-core.c, where it leaves a dangling - * pointer in intfdata causing v4l2-device.c to not set it. Which - * results in usb_shark_disconnect() referencing the dangling pointer - * - * REMOVE (as soon as the above bug is fixed, patch submitted) - */ - usb_set_intfdata(intf, NULL); - shark->v4l2_dev.release = usb_shark_release; v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index b9575de3e7e8..fc0289d5da4e 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -258,15 +258,6 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - /* - * Work around a bug in usbhid/hid-core.c, where it leaves a dangling - * pointer in intfdata causing v4l2-device.c to not set it. Which - * results in usb_shark_disconnect() referencing the dangling pointer - * - * REMOVE (as soon as the above bug is fixed, patch submitted) - */ - usb_set_intfdata(intf, NULL); - shark->v4l2_dev.release = usb_shark_release; v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); -- GitLab From cfc1b2a06f87f562da2ffb9f8d1ae4203d9bfbfa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 11 Aug 2012 06:34:53 -0300 Subject: [PATCH 5356/5711] [media] radio-shark*: Call cancel_work_sync from disconnect rather then release This removes the need for shark_led_work to take the v4l2 lock. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark.c | 13 ++----------- drivers/media/radio/radio-shark2.c | 12 ++---------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index e35b8d938a30..1d76afa9e1b7 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -181,14 +181,6 @@ static void shark_led_work(struct work_struct *work) container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; - /* - * We use the v4l2_dev lock and registered bit to ensure the device - * does not get unplugged and unreffed while we're running. - */ - mutex_lock(&shark->tea.mutex); - if (!video_is_registered(&shark->tea.vd)) - goto leave; - for (i = 0; i < 3; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) continue; @@ -208,8 +200,6 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } -leave: - mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -259,6 +249,8 @@ static void usb_shark_disconnect(struct usb_interface *intf) for (i = 0; i < NO_LEDS; i++) led_classdev_unregister(&shark->leds[i]); + cancel_work_sync(&shark->led_work); + v4l2_device_put(&shark->v4l2_dev); } @@ -266,7 +258,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index fc0289d5da4e..217483ca1b18 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -166,13 +166,6 @@ static void shark_led_work(struct work_struct *work) struct shark_device *shark = container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; - /* - * We use the v4l2_dev lock and registered bit to ensure the device - * does not get unplugged and unreffed while we're running. - */ - mutex_lock(&shark->tea.mutex); - if (!video_is_registered(&shark->tea.vd)) - goto leave; for (i = 0; i < 2; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) @@ -191,8 +184,6 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } -leave: - mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -231,6 +222,8 @@ static void usb_shark_disconnect(struct usb_interface *intf) for (i = 0; i < NO_LEDS; i++) led_classdev_unregister(&shark->leds[i]); + cancel_work_sync(&shark->led_work); + v4l2_device_put(&shark->v4l2_dev); } @@ -238,7 +231,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); -- GitLab From 3e3b92cac5371031e9d2f916189577025f508ab8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 11 Aug 2012 06:34:54 -0300 Subject: [PATCH 5357/5711] [media] radio-shark: Only compile led support when CONFIG_LED_CLASS is set Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark.c | 135 +++++++++++++++++------------- 1 file changed, 79 insertions(+), 56 deletions(-) diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 1d76afa9e1b7..72ded29728bb 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -35,6 +35,11 @@ #include #include +#if defined(CONFIG_LEDS_CLASS) || \ + (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) +#define SHARK_USE_LEDS 1 +#endif + /* * Version Information */ @@ -56,44 +61,18 @@ MODULE_LICENSE("GPL"); enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, - enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [BLUE_PULSE_LED] = { - .name = "%s:blue-pulse:", - .brightness = LED_OFF, - .max_brightness = 255, - .brightness_set = shark_led_set_blue_pulse, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct snd_tea575x tea; +#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; +#endif u8 *transfer_buffer; u32 last_val; @@ -175,6 +154,7 @@ static struct snd_tea575x_ops shark_tea_ops = { .read_val = shark_read_val, }; +#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = @@ -235,21 +215,78 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [BLUE_PULSE_LED] = { + .name = "%s:blue-pulse:", + .brightness = LED_OFF, + .max_brightness = 255, + .brightness_set = shark_led_set_blue_pulse, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + int i, retval; + + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + retval = led_classdev_register(dev, &shark->leds[i]); + if (retval) { + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + return retval; + } + } + return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); + + cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + v4l2_warn(&shark->v4l2_dev, + "CONFIG_LED_CLASS not enabled, LED support disabled\n"); + return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif + static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); snd_tea575x_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); - - cancel_work_sync(&shark->led_work); + shark_unregister_leds(shark); v4l2_device_put(&shark->v4l2_dev); } @@ -267,7 +304,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int i, retval = -ENOMEM; + int retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -277,8 +314,13 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - shark->v4l2_dev.release = usb_shark_release; v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + + retval = shark_register_leds(shark, &intf->dev); + if (retval) + goto err_reg_leds; + + shark->v4l2_dev.release = usb_shark_release; retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -302,32 +344,13 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - /* - * We don't fail the probe if we fail to register the leds, - * because once we've called snd_tea575x_init, the /dev/radio0 - * node may be opened from userspace holding a reference to us! - * - * Note we cannot register the leds first instead as - * shark_led_work depends on the v4l2 mutex and registered bit. - */ - retval = led_classdev_register(&intf->dev, &shark->leds[i]); - if (retval) - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - } - return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: + shark_unregister_leds(shark); +err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); -- GitLab From be0c44fb480fe43fe8794ec4bff0b0e7e0b50c72 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 11 Aug 2012 06:34:55 -0300 Subject: [PATCH 5358/5711] [media] radio-shark2: Only compile led support when CONFIG_LED_CLASS is set Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark2.c | 122 +++++++++++++++++------------ 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 217483ca1b18..7b4efdfaae28 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -35,6 +35,11 @@ #include #include "radio-tea5777.h" +#if defined(CONFIG_LEDS_CLASS) || \ + (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE)) +#define SHARK_USE_LEDS 1 +#endif + MODULE_AUTHOR("Hans de Goede "); MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver"); MODULE_LICENSE("GPL"); @@ -43,7 +48,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); - #define SHARK_IN_EP 0x83 #define SHARK_OUT_EP 0x05 @@ -54,36 +58,18 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); enum { BLUE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, - enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct radio_tea5777 tea; +#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; +#endif u8 *transfer_buffer; }; @@ -161,6 +147,7 @@ static struct radio_tea5777_ops shark_tea_ops = { .read_reg = shark_read_reg, }; +#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = @@ -208,21 +195,72 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + int i, retval; + + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + retval = led_classdev_register(dev, &shark->leds[i]); + if (retval) { + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + return retval; + } + } + return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); + + cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + v4l2_warn(&shark->v4l2_dev, + "CONFIG_LED_CLASS not enabled, LED support disabled\n"); + return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif + static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); radio_tea5777_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); - - cancel_work_sync(&shark->led_work); + shark_unregister_leds(shark); v4l2_device_put(&shark->v4l2_dev); } @@ -240,7 +278,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int i, retval = -ENOMEM; + int retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -250,8 +288,13 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - shark->v4l2_dev.release = usb_shark_release; v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + + retval = shark_register_leds(shark, &intf->dev); + if (retval) + goto err_reg_leds; + + shark->v4l2_dev.release = usb_shark_release; retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -275,32 +318,13 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - /* - * We don't fail the probe if we fail to register the leds, - * because once we've called radio_tea5777_init, the /dev/radio0 - * node may be opened from userspace holding a reference to us! - * - * Note we cannot register the leds first instead as - * shark_led_work depends on the v4l2 mutex and registered bit. - */ - retval = led_classdev_register(&intf->dev, &shark->leds[i]); - if (retval) - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - } - return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: + shark_unregister_leds(shark); +err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); -- GitLab From e3756477aec028427fec767957c0d4b6cfb87208 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 10 Aug 2012 15:07:09 -0400 Subject: [PATCH 5359/5711] printk: Fix calculation of length used to discard records While tracking down a weird buffer overflow issue in a program that looked to be sane, I started double checking the length returned by syslog(SYSLOG_ACTION_READ_ALL, ...) to make sure it wasn't overflowing the buffer. Sure enough, it was. I saw this in strace: 11339 syslog(SYSLOG_ACTION_READ_ALL, "<5>[244017.708129] REISERFS (dev"..., 8192) = 8279 It turns out that the loops that calculate how much space the entries will take when they're copied don't include the newlines and prefixes that will be included in the final output since prev flags is passed as zero. This patch properly accounts for it and fixes the overflow. CC: stable@kernel.org Signed-off-by: Jeff Mahoney Signed-off-by: Linus Torvalds --- kernel/printk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/printk.c b/kernel/printk.c index 6a76ab9d4476..66a2ea37b576 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1034,6 +1034,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) struct log *msg = log_from_idx(idx); len += msg_print_text(msg, prev, true, NULL, 0); + prev = msg->flags; idx = log_next(idx); seq++; } @@ -1046,6 +1047,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) struct log *msg = log_from_idx(idx); len -= msg_print_text(msg, prev, true, NULL, 0); + prev = msg->flags; idx = log_next(idx); seq++; } -- GitLab From 3a7f8c34fefb109903af9a0fac6d0d05f93335c5 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Sat, 11 Aug 2012 20:26:31 +0000 Subject: [PATCH 5360/5711] macvtap: rcu_dereference outside read-lock section rcu_dereference occurs in update section. Replacement by rcu_dereference_protected in order to prevent lockdep complaint. Found by Linux Driver Verification project (linuxtesting.org) Signed-off-by: Denis Efremov Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 0737bd4d1669..0f0f9ce3a776 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -94,7 +94,8 @@ static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q) int i; for (i = 0; i < MAX_MACVTAP_QUEUES; i++) { - if (rcu_dereference(vlan->taps[i]) == q) + if (rcu_dereference_protected(vlan->taps[i], + lockdep_is_held(&macvtap_lock)) == q) return i; } -- GitLab From 7f5c3e3a80e6654cf48dfba7cf94f88c6b505467 Mon Sep 17 00:00:00 2001 From: "danborkmann@iogearbox.net" Date: Fri, 10 Aug 2012 22:48:54 +0000 Subject: [PATCH 5361/5711] af_packet: remove BUG statement in tpacket_destruct_skb Here's a quote of the comment about the BUG macro from asm-generic/bug.h: Don't use BUG() or BUG_ON() unless there's really no way out; one example might be detecting data structure corruption in the middle of an operation that can't be backed out of. If the (sub)system can somehow continue operating, perhaps with reduced functionality, it's probably not BUG-worthy. If you're tempted to BUG(), think again: is completely giving up really the *only* solution? There are usually better options, where users don't need to reboot ASAP and can mostly shut down cleanly. In our case, the status flag of a ring buffer slot is managed from both sides, the kernel space and the user space. This means that even though the kernel side might work as expected, the user space screws up and changes this flag right between the send(2) is triggered when the flag is changed to TP_STATUS_SENDING and a given skb is destructed after some time. Then, this will hit the BUG macro. As David suggested, the best solution is to simply remove this statement since it cannot be used for kernel side internal consistency checks. I've tested it and the system still behaves /stable/ in this case, so in accordance with the above comment, we should rather remove it. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/packet/af_packet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f016f6634a79..8ac890a1a4c0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1936,7 +1936,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) if (likely(po->tx_ring.pg_vec)) { ph = skb_shinfo(skb)->destructor_arg; - BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); BUG_ON(atomic_read(&po->tx_ring.pending) == 0); atomic_dec(&po->tx_ring.pending); __packet_set_status(po, ph, TP_STATUS_AVAILABLE); -- GitLab From f57b07c0c7ca9e4dde36acfabdf474ee3c478e6d Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Sat, 11 Aug 2012 17:10:35 +0000 Subject: [PATCH 5362/5711] bnx2x: Fix compiler warnings Fix the following compiler warnings: - drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c:2908:3: warning: comparison of distinct pointer types lacks a cast [enabled by default] - drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:1709:7: warning: comparison of distinct pointer types lacks a cast [enabled by default] Signed-off-by: Joren Van Onder Acked-By: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 77bcd4cb4ffb..463b9ec57d80 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1278,7 +1278,7 @@ struct bnx2x { #define BNX2X_FW_RX_ALIGN_START (1UL << BNX2X_RX_ALIGN_SHIFT) #define BNX2X_FW_RX_ALIGN_END \ - max(1UL << BNX2X_RX_ALIGN_SHIFT, \ + max_t(u64, 1UL << BNX2X_RX_ALIGN_SHIFT, \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) #define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5) -- GitLab From ffc493062ce9987156945aa21a677d83a179fc0a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 20 Jul 2012 13:31:08 +0530 Subject: [PATCH 5363/5711] dma: tegra: enable/disable dma clock Enable the DMA clock when allocating channel and disable clock when freeing channels. Signed-off-by: Laxman Dewangan Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index d52dbc6c54ab..24acd711e032 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1119,15 +1119,21 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma *tdma = tdc->tdma; + int ret; dma_cookie_init(&tdc->dma_chan); tdc->config_init = false; - return 0; + ret = clk_prepare_enable(tdma->dma_clk); + if (ret < 0) + dev_err(tdc2dev(tdc), "clk_prepare_enable failed: %d\n", ret); + return ret; } static void tegra_dma_free_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma *tdma = tdc->tdma; struct tegra_dma_desc *dma_desc; struct tegra_dma_sg_req *sg_req; @@ -1163,6 +1169,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) list_del(&sg_req->node); kfree(sg_req); } + clk_disable_unprepare(tdma->dma_clk); } /* Tegra20 specific DMA controller information */ @@ -1255,6 +1262,13 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev) } } + /* Enable clock before accessing registers */ + ret = clk_prepare_enable(tdma->dma_clk); + if (ret < 0) { + dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); + goto err_pm_disable; + } + /* Reset DMA controller */ tegra_periph_reset_assert(tdma->dma_clk); udelay(2); @@ -1265,6 +1279,8 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev) tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); + clk_disable_unprepare(tdma->dma_clk); + INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < cdata->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; -- GitLab From 86e99d23d0210e8d43a0bb576582a455d907578e Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Mon, 13 Aug 2012 14:27:24 +0800 Subject: [PATCH 5364/5711] Revert "leds: use led_set_brightness in led_trigger_event" This reverts commit a0193cbee0809d65362a0767b2d50306b145b2f5. The problem with the original commit was that it caused a warning with the MMC trigger calling del_timer_sync from hard-irq context. Signed-off-by: Fabio Baltieri Reported-by: Pawel Moll Signed-off-by: Bryan Wu --- drivers/leds/led-triggers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 6157cbbf4113..363975b3c925 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -224,7 +224,7 @@ void led_trigger_event(struct led_trigger *trig, struct led_classdev *led_cdev; led_cdev = list_entry(entry, struct led_classdev, trig_list); - led_set_brightness(led_cdev, brightness); + __led_set_brightness(led_cdev, brightness); } read_unlock(&trig->leddev_list_lock); } -- GitLab From 4a5a4184628c529774c1492bc1a21743b69b5fc3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 9 Aug 2012 05:27:58 +0800 Subject: [PATCH 5365/5711] leds: renesas: fix error handling bfe4c041 "leds: convert Renesas TPU LED driver to devm_kzalloc() and cleanup error exit path" introduced a possible case in which r_tpu_probe calls iounmap on a wild pointer. This changes the one case that was missed in the same way as the other error paths. Without this patch, building kota2_defconfig results in: drivers/leds/leds-renesas-tpu.c: In function 'r_tpu_probe': drivers/leds/leds-renesas-tpu.c:246:6: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] drivers/leds/leds-renesas-tpu.c:308:17: warning: 'p' may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Arnd Bergmann Cc: Magnus Damm Signed-off-by: Bryan Wu --- drivers/leds/leds-renesas-tpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c index 9ee12c28059a..771ea067e680 100644 --- a/drivers/leds/leds-renesas-tpu.c +++ b/drivers/leds/leds-renesas-tpu.c @@ -247,7 +247,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev) if (!cfg) { dev_err(&pdev->dev, "missing platform data\n"); - goto err0; + return -ENODEV; } p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); -- GitLab From 088c820b732dbfd515fc66d459d5f5777f79b406 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Mon, 13 Aug 2012 14:11:10 +0800 Subject: [PATCH 5366/5711] ALSA: hda - fix Copyright debug message As spec said, 1 indicates no copyright is asserted. Signed-off-by: Wang Xingchao Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 7e46258fc700..6894ec66258c 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -412,7 +412,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer, if (digi1 & AC_DIG1_EMPHASIS) snd_iprintf(buffer, " Preemphasis"); if (digi1 & AC_DIG1_COPYRIGHT) - snd_iprintf(buffer, " Copyright"); + snd_iprintf(buffer, " Non-Copyright"); if (digi1 & AC_DIG1_NONAUDIO) snd_iprintf(buffer, " Non-Audio"); if (digi1 & AC_DIG1_PROFESSIONAL) -- GitLab From 080fc66fb5b6feae19fbbe8c6cbd7b11a4dac636 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 13 Aug 2012 11:44:13 +0100 Subject: [PATCH 5367/5711] ARM: Bring back ARMv3 IO and user access code This partially reverts 357c9c1f07d4546bc3fbc0fd1044d96b114d14ed (ARM: Remove support for ARMv3 ARM610 and ARM710 CPUs). Although we only support StrongARM on the RiscPC, we need to keep the ARMv3 user access code for this platform because the bus does not understand half-word load/stores. Reported-by: Arnd Bergmann Signed-off-by: Russell King --- arch/arm/lib/Makefile | 23 +- arch/arm/lib/io-readsw-armv3.S | 106 ++++++ arch/arm/lib/io-writesw-armv3.S | 126 +++++++ arch/arm/lib/uaccess.S | 564 ++++++++++++++++++++++++++++++++ 4 files changed, 816 insertions(+), 3 deletions(-) create mode 100644 arch/arm/lib/io-readsw-armv3.S create mode 100644 arch/arm/lib/io-writesw-armv3.S create mode 100644 arch/arm/lib/uaccess.S diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 2473fd1fd51c..af72969820b4 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -16,13 +16,30 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ call_with_stack.o mmu-y := clear_user.o copy_page.o getuser.o putuser.o -mmu-y += copy_from_user.o copy_to_user.o + +# the code in uaccess.S is not preemption safe and +# probably faster on ARMv3 only +ifeq ($(CONFIG_PREEMPT),y) + mmu-y += copy_from_user.o copy_to_user.o +else +ifneq ($(CONFIG_CPU_32v3),y) + mmu-y += copy_from_user.o copy_to_user.o +else + mmu-y += uaccess.o +endif +endif # using lib_ here won't override already available weak symbols obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o -lib-$(CONFIG_MMU) += $(mmu-y) -lib-y += io-readsw-armv4.o io-writesw-armv4.o +lib-$(CONFIG_MMU) += $(mmu-y) + +ifeq ($(CONFIG_CPU_32v3),y) + lib-y += io-readsw-armv3.o io-writesw-armv3.o +else + lib-y += io-readsw-armv4.o io-writesw-armv4.o +endif + lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o lib-$(CONFIG_ARCH_SHARK) += io-shark.o diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S new file mode 100644 index 000000000000..88487c8c4f23 --- /dev/null +++ b/arch/arm/lib/io-readsw-armv3.S @@ -0,0 +1,106 @@ +/* + * linux/arch/arm/lib/io-readsw-armv3.S + * + * Copyright (C) 1995-2000 Russell King + * + * 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 + +.Linsw_bad_alignment: + adr r0, .Linsw_bad_align_msg + mov r2, lr + b panic +.Linsw_bad_align_msg: + .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.Linsw_align: tst r1, #1 + bne .Linsw_bad_alignment + + ldr r3, [r0] + strb r3, [r1], #1 + mov r3, r3, lsr #8 + strb r3, [r1], #1 + + subs r2, r2, #1 + moveq pc, lr + +ENTRY(__raw_readsw) + teq r2, #0 @ do we have to check for the zero len? + moveq pc, lr + tst r1, #3 + bne .Linsw_align + +.Linsw_aligned: mov ip, #0xff + orr ip, ip, ip, lsl #8 + stmfd sp!, {r4, r5, r6, lr} + + subs r2, r2, #8 + bmi .Lno_insw_8 + +.Linsw_8_lp: ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + ldr r4, [r0] + and r4, r4, ip + ldr r5, [r0] + orr r4, r4, r5, lsl #16 + + ldr r5, [r0] + and r5, r5, ip + ldr r6, [r0] + orr r5, r5, r6, lsl #16 + + ldr r6, [r0] + and r6, r6, ip + ldr lr, [r0] + orr r6, r6, lr, lsl #16 + + stmia r1!, {r3 - r6} + + subs r2, r2, #8 + bpl .Linsw_8_lp + + tst r2, #7 + ldmeqfd sp!, {r4, r5, r6, pc} + +.Lno_insw_8: tst r2, #4 + beq .Lno_insw_4 + + ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + ldr r4, [r0] + and r4, r4, ip + ldr r5, [r0] + orr r4, r4, r5, lsl #16 + + stmia r1!, {r3, r4} + +.Lno_insw_4: tst r2, #2 + beq .Lno_insw_2 + + ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + str r3, [r1], #4 + +.Lno_insw_2: tst r2, #1 + ldrne r3, [r0] + strneb r3, [r1], #1 + movne r3, r3, lsr #8 + strneb r3, [r1] + + ldmfd sp!, {r4, r5, r6, pc} + + diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S new file mode 100644 index 000000000000..49b800419e32 --- /dev/null +++ b/arch/arm/lib/io-writesw-armv3.S @@ -0,0 +1,126 @@ +/* + * linux/arch/arm/lib/io-writesw-armv3.S + * + * Copyright (C) 1995-2000 Russell King + * + * 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 + +.Loutsw_bad_alignment: + adr r0, .Loutsw_bad_align_msg + mov r2, lr + b panic +.Loutsw_bad_align_msg: + .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.Loutsw_align: tst r1, #1 + bne .Loutsw_bad_alignment + + add r1, r1, #2 + + ldr r3, [r1, #-4] + mov r3, r3, lsr #16 + orr r3, r3, r3, lsl #16 + str r3, [r0] + subs r2, r2, #1 + moveq pc, lr + +ENTRY(__raw_writesw) + teq r2, #0 @ do we have to check for the zero len? + moveq pc, lr + tst r1, #3 + bne .Loutsw_align + + stmfd sp!, {r4, r5, r6, lr} + + subs r2, r2, #8 + bmi .Lno_outsw_8 + +.Loutsw_8_lp: ldmia r1!, {r3, r4, r5, r6} + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r4, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r4, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r5, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r5, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r6, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r6, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + subs r2, r2, #8 + bpl .Loutsw_8_lp + + tst r2, #7 + ldmeqfd sp!, {r4, r5, r6, pc} + +.Lno_outsw_8: tst r2, #4 + beq .Lno_outsw_4 + + ldmia r1!, {r3, r4} + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r4, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r4, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + +.Lno_outsw_4: tst r2, #2 + beq .Lno_outsw_2 + + ldr r3, [r1], #4 + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + +.Lno_outsw_2: tst r2, #1 + + ldrne r3, [r1] + + movne ip, r3, lsl #16 + orrne ip, ip, ip, lsr #16 + strne ip, [r0] + + ldmfd sp!, {r4, r5, r6, pc} diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S new file mode 100644 index 000000000000..5c908b1cb8ed --- /dev/null +++ b/arch/arm/lib/uaccess.S @@ -0,0 +1,564 @@ +/* + * linux/arch/arm/lib/uaccess.S + * + * Copyright (C) 1995, 1996,1997,1998 Russell King + * + * 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. + * + * Routines to block copy data to/from user memory + * These are highly optimised both for the 4k page size + * and for various alignments. + */ +#include +#include +#include +#include + + .text + +#define PAGE_SHIFT 12 + +/* Prototype: int __copy_to_user(void *to, const char *from, size_t n) + * Purpose : copy a block to user memory from kernel memory + * Params : to - user memory + * : from - kernel memory + * : n - number of bytes to copy + * Returns : Number of bytes NOT copied. + */ + +.Lc2u_dest_not_aligned: + rsb ip, ip, #4 + cmp ip, #2 + ldrb r3, [r1], #1 +USER( TUSER( strb) r3, [r0], #1) @ May fault + ldrgeb r3, [r1], #1 +USER( TUSER( strgeb) r3, [r0], #1) @ May fault + ldrgtb r3, [r1], #1 +USER( TUSER( strgtb) r3, [r0], #1) @ May fault + sub r2, r2, ip + b .Lc2u_dest_aligned + +ENTRY(__copy_to_user) + stmfd sp!, {r2, r4 - r7, lr} + cmp r2, #4 + blt .Lc2u_not_enough + ands ip, r0, #3 + bne .Lc2u_dest_not_aligned +.Lc2u_dest_aligned: + + ands ip, r1, #3 + bne .Lc2u_src_not_aligned +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.Lc2u_0fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lc2u_0nowords + ldr r3, [r1], #4 +USER( TUSER( str) r3, [r0], #4) @ May fault + mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lc2u_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #32 + blt .Lc2u_0rem8lp + +.Lc2u_0cpy8lp: ldmia r1!, {r3 - r6} + stmia r0!, {r3 - r6} @ Shouldnt fault + ldmia r1!, {r3 - r6} + subs ip, ip, #32 + stmia r0!, {r3 - r6} @ Shouldnt fault + bpl .Lc2u_0cpy8lp + +.Lc2u_0rem8lp: cmn ip, #16 + ldmgeia r1!, {r3 - r6} + stmgeia r0!, {r3 - r6} @ Shouldnt fault + tst ip, #8 + ldmneia r1!, {r3 - r4} + stmneia r0!, {r3 - r4} @ Shouldnt fault + tst ip, #4 + ldrne r3, [r1], #4 + TUSER( strne) r3, [r0], #4 @ Shouldnt fault + ands ip, ip, #3 + beq .Lc2u_0fupi +.Lc2u_0nowords: teq ip, #0 + beq .Lc2u_finished +.Lc2u_nowords: cmp ip, #2 + ldrb r3, [r1], #1 +USER( TUSER( strb) r3, [r0], #1) @ May fault + ldrgeb r3, [r1], #1 +USER( TUSER( strgeb) r3, [r0], #1) @ May fault + ldrgtb r3, [r1], #1 +USER( TUSER( strgtb) r3, [r0], #1) @ May fault + b .Lc2u_finished + +.Lc2u_not_enough: + movs ip, r2 + bne .Lc2u_nowords +.Lc2u_finished: mov r0, #0 + ldmfd sp!, {r2, r4 - r7, pc} + +.Lc2u_src_not_aligned: + bic r1, r1, #3 + ldr r7, [r1], #4 + cmp ip, #2 + bgt .Lc2u_3fupi + beq .Lc2u_2fupi +.Lc2u_1fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lc2u_1nowords + mov r3, r7, pull #8 + ldr r7, [r1], #4 + orr r3, r3, r7, push #24 +USER( TUSER( str) r3, [r0], #4) @ May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lc2u_1fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lc2u_1rem8lp + +.Lc2u_1cpy8lp: mov r3, r7, pull #8 + ldmia r1!, {r4 - r7} + subs ip, ip, #16 + orr r3, r3, r4, push #24 + mov r4, r4, pull #8 + orr r4, r4, r5, push #24 + mov r5, r5, pull #8 + orr r5, r5, r6, push #24 + mov r6, r6, pull #8 + orr r6, r6, r7, push #24 + stmia r0!, {r3 - r6} @ Shouldnt fault + bpl .Lc2u_1cpy8lp + +.Lc2u_1rem8lp: tst ip, #8 + movne r3, r7, pull #8 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, push #24 + movne r4, r4, pull #8 + orrne r4, r4, r7, push #24 + stmneia r0!, {r3 - r4} @ Shouldnt fault + tst ip, #4 + movne r3, r7, pull #8 + ldrne r7, [r1], #4 + orrne r3, r3, r7, push #24 + TUSER( strne) r3, [r0], #4 @ Shouldnt fault + ands ip, ip, #3 + beq .Lc2u_1fupi +.Lc2u_1nowords: mov r3, r7, get_byte_1 + teq ip, #0 + beq .Lc2u_finished + cmp ip, #2 +USER( TUSER( strb) r3, [r0], #1) @ May fault + movge r3, r7, get_byte_2 +USER( TUSER( strgeb) r3, [r0], #1) @ May fault + movgt r3, r7, get_byte_3 +USER( TUSER( strgtb) r3, [r0], #1) @ May fault + b .Lc2u_finished + +.Lc2u_2fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lc2u_2nowords + mov r3, r7, pull #16 + ldr r7, [r1], #4 + orr r3, r3, r7, push #16 +USER( TUSER( str) r3, [r0], #4) @ May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lc2u_2fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lc2u_2rem8lp + +.Lc2u_2cpy8lp: mov r3, r7, pull #16 + ldmia r1!, {r4 - r7} + subs ip, ip, #16 + orr r3, r3, r4, push #16 + mov r4, r4, pull #16 + orr r4, r4, r5, push #16 + mov r5, r5, pull #16 + orr r5, r5, r6, push #16 + mov r6, r6, pull #16 + orr r6, r6, r7, push #16 + stmia r0!, {r3 - r6} @ Shouldnt fault + bpl .Lc2u_2cpy8lp + +.Lc2u_2rem8lp: tst ip, #8 + movne r3, r7, pull #16 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, push #16 + movne r4, r4, pull #16 + orrne r4, r4, r7, push #16 + stmneia r0!, {r3 - r4} @ Shouldnt fault + tst ip, #4 + movne r3, r7, pull #16 + ldrne r7, [r1], #4 + orrne r3, r3, r7, push #16 + TUSER( strne) r3, [r0], #4 @ Shouldnt fault + ands ip, ip, #3 + beq .Lc2u_2fupi +.Lc2u_2nowords: mov r3, r7, get_byte_2 + teq ip, #0 + beq .Lc2u_finished + cmp ip, #2 +USER( TUSER( strb) r3, [r0], #1) @ May fault + movge r3, r7, get_byte_3 +USER( TUSER( strgeb) r3, [r0], #1) @ May fault + ldrgtb r3, [r1], #0 +USER( TUSER( strgtb) r3, [r0], #1) @ May fault + b .Lc2u_finished + +.Lc2u_3fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lc2u_3nowords + mov r3, r7, pull #24 + ldr r7, [r1], #4 + orr r3, r3, r7, push #8 +USER( TUSER( str) r3, [r0], #4) @ May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lc2u_3fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lc2u_3rem8lp + +.Lc2u_3cpy8lp: mov r3, r7, pull #24 + ldmia r1!, {r4 - r7} + subs ip, ip, #16 + orr r3, r3, r4, push #8 + mov r4, r4, pull #24 + orr r4, r4, r5, push #8 + mov r5, r5, pull #24 + orr r5, r5, r6, push #8 + mov r6, r6, pull #24 + orr r6, r6, r7, push #8 + stmia r0!, {r3 - r6} @ Shouldnt fault + bpl .Lc2u_3cpy8lp + +.Lc2u_3rem8lp: tst ip, #8 + movne r3, r7, pull #24 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, push #8 + movne r4, r4, pull #24 + orrne r4, r4, r7, push #8 + stmneia r0!, {r3 - r4} @ Shouldnt fault + tst ip, #4 + movne r3, r7, pull #24 + ldrne r7, [r1], #4 + orrne r3, r3, r7, push #8 + TUSER( strne) r3, [r0], #4 @ Shouldnt fault + ands ip, ip, #3 + beq .Lc2u_3fupi +.Lc2u_3nowords: mov r3, r7, get_byte_3 + teq ip, #0 + beq .Lc2u_finished + cmp ip, #2 +USER( TUSER( strb) r3, [r0], #1) @ May fault + ldrgeb r3, [r1], #1 +USER( TUSER( strgeb) r3, [r0], #1) @ May fault + ldrgtb r3, [r1], #0 +USER( TUSER( strgtb) r3, [r0], #1) @ May fault + b .Lc2u_finished +ENDPROC(__copy_to_user) + + .pushsection .fixup,"ax" + .align 0 +9001: ldmfd sp!, {r0, r4 - r7, pc} + .popsection + +/* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n); + * Purpose : copy a block from user memory to kernel memory + * Params : to - kernel memory + * : from - user memory + * : n - number of bytes to copy + * Returns : Number of bytes NOT copied. + */ +.Lcfu_dest_not_aligned: + rsb ip, ip, #4 + cmp ip, #2 +USER( TUSER( ldrb) r3, [r1], #1) @ May fault + strb r3, [r0], #1 +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault + strgeb r3, [r0], #1 +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault + strgtb r3, [r0], #1 + sub r2, r2, ip + b .Lcfu_dest_aligned + +ENTRY(__copy_from_user) + stmfd sp!, {r0, r2, r4 - r7, lr} + cmp r2, #4 + blt .Lcfu_not_enough + ands ip, r0, #3 + bne .Lcfu_dest_not_aligned +.Lcfu_dest_aligned: + ands ip, r1, #3 + bne .Lcfu_src_not_aligned + +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.Lcfu_0fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lcfu_0nowords +USER( TUSER( ldr) r3, [r1], #4) + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lcfu_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #32 + blt .Lcfu_0rem8lp + +.Lcfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault + stmia r0!, {r3 - r6} + ldmia r1!, {r3 - r6} @ Shouldnt fault + subs ip, ip, #32 + stmia r0!, {r3 - r6} + bpl .Lcfu_0cpy8lp + +.Lcfu_0rem8lp: cmn ip, #16 + ldmgeia r1!, {r3 - r6} @ Shouldnt fault + stmgeia r0!, {r3 - r6} + tst ip, #8 + ldmneia r1!, {r3 - r4} @ Shouldnt fault + stmneia r0!, {r3 - r4} + tst ip, #4 + TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault + strne r3, [r0], #4 + ands ip, ip, #3 + beq .Lcfu_0fupi +.Lcfu_0nowords: teq ip, #0 + beq .Lcfu_finished +.Lcfu_nowords: cmp ip, #2 +USER( TUSER( ldrb) r3, [r1], #1) @ May fault + strb r3, [r0], #1 +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault + strgeb r3, [r0], #1 +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault + strgtb r3, [r0], #1 + b .Lcfu_finished + +.Lcfu_not_enough: + movs ip, r2 + bne .Lcfu_nowords +.Lcfu_finished: mov r0, #0 + add sp, sp, #8 + ldmfd sp!, {r4 - r7, pc} + +.Lcfu_src_not_aligned: + bic r1, r1, #3 +USER( TUSER( ldr) r7, [r1], #4) @ May fault + cmp ip, #2 + bgt .Lcfu_3fupi + beq .Lcfu_2fupi +.Lcfu_1fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lcfu_1nowords + mov r3, r7, pull #8 +USER( TUSER( ldr) r7, [r1], #4) @ May fault + orr r3, r3, r7, push #24 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lcfu_1fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lcfu_1rem8lp + +.Lcfu_1cpy8lp: mov r3, r7, pull #8 + ldmia r1!, {r4 - r7} @ Shouldnt fault + subs ip, ip, #16 + orr r3, r3, r4, push #24 + mov r4, r4, pull #8 + orr r4, r4, r5, push #24 + mov r5, r5, pull #8 + orr r5, r5, r6, push #24 + mov r6, r6, pull #8 + orr r6, r6, r7, push #24 + stmia r0!, {r3 - r6} + bpl .Lcfu_1cpy8lp + +.Lcfu_1rem8lp: tst ip, #8 + movne r3, r7, pull #8 + ldmneia r1!, {r4, r7} @ Shouldnt fault + orrne r3, r3, r4, push #24 + movne r4, r4, pull #8 + orrne r4, r4, r7, push #24 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, pull #8 +USER( TUSER( ldrne) r7, [r1], #4) @ May fault + orrne r3, r3, r7, push #24 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .Lcfu_1fupi +.Lcfu_1nowords: mov r3, r7, get_byte_1 + teq ip, #0 + beq .Lcfu_finished + cmp ip, #2 + strb r3, [r0], #1 + movge r3, r7, get_byte_2 + strgeb r3, [r0], #1 + movgt r3, r7, get_byte_3 + strgtb r3, [r0], #1 + b .Lcfu_finished + +.Lcfu_2fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lcfu_2nowords + mov r3, r7, pull #16 +USER( TUSER( ldr) r7, [r1], #4) @ May fault + orr r3, r3, r7, push #16 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lcfu_2fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lcfu_2rem8lp + + +.Lcfu_2cpy8lp: mov r3, r7, pull #16 + ldmia r1!, {r4 - r7} @ Shouldnt fault + subs ip, ip, #16 + orr r3, r3, r4, push #16 + mov r4, r4, pull #16 + orr r4, r4, r5, push #16 + mov r5, r5, pull #16 + orr r5, r5, r6, push #16 + mov r6, r6, pull #16 + orr r6, r6, r7, push #16 + stmia r0!, {r3 - r6} + bpl .Lcfu_2cpy8lp + +.Lcfu_2rem8lp: tst ip, #8 + movne r3, r7, pull #16 + ldmneia r1!, {r4, r7} @ Shouldnt fault + orrne r3, r3, r4, push #16 + movne r4, r4, pull #16 + orrne r4, r4, r7, push #16 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, pull #16 +USER( TUSER( ldrne) r7, [r1], #4) @ May fault + orrne r3, r3, r7, push #16 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .Lcfu_2fupi +.Lcfu_2nowords: mov r3, r7, get_byte_2 + teq ip, #0 + beq .Lcfu_finished + cmp ip, #2 + strb r3, [r0], #1 + movge r3, r7, get_byte_3 + strgeb r3, [r0], #1 +USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault + strgtb r3, [r0], #1 + b .Lcfu_finished + +.Lcfu_3fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .Lcfu_3nowords + mov r3, r7, pull #24 +USER( TUSER( ldr) r7, [r1], #4) @ May fault + orr r3, r3, r7, push #8 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .Lcfu_3fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .Lcfu_3rem8lp + +.Lcfu_3cpy8lp: mov r3, r7, pull #24 + ldmia r1!, {r4 - r7} @ Shouldnt fault + orr r3, r3, r4, push #8 + mov r4, r4, pull #24 + orr r4, r4, r5, push #8 + mov r5, r5, pull #24 + orr r5, r5, r6, push #8 + mov r6, r6, pull #24 + orr r6, r6, r7, push #8 + stmia r0!, {r3 - r6} + subs ip, ip, #16 + bpl .Lcfu_3cpy8lp + +.Lcfu_3rem8lp: tst ip, #8 + movne r3, r7, pull #24 + ldmneia r1!, {r4, r7} @ Shouldnt fault + orrne r3, r3, r4, push #8 + movne r4, r4, pull #24 + orrne r4, r4, r7, push #8 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, pull #24 +USER( TUSER( ldrne) r7, [r1], #4) @ May fault + orrne r3, r3, r7, push #8 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .Lcfu_3fupi +.Lcfu_3nowords: mov r3, r7, get_byte_3 + teq ip, #0 + beq .Lcfu_finished + cmp ip, #2 + strb r3, [r0], #1 +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault + strgeb r3, [r0], #1 +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault + strgtb r3, [r0], #1 + b .Lcfu_finished +ENDPROC(__copy_from_user) + + .pushsection .fixup,"ax" + .align 0 + /* + * We took an exception. r0 contains a pointer to + * the byte not copied. + */ +9001: ldr r2, [sp], #4 @ void *to + sub r2, r0, r2 @ bytes copied + ldr r1, [sp], #4 @ unsigned long count + subs r4, r1, r2 @ bytes left to copy + movne r1, r4 + blne __memzero + mov r0, r4 + ldmfd sp!, {r4 - r7, pc} + .popsection + -- GitLab From 14ebd8a8c15e9fed638120bdb93f1a814e13d6a9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 10 Aug 2012 15:40:12 +0100 Subject: [PATCH 5368/5711] ASoC: wm5102: Add missing input PGA routes Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 6537f16d383e..496ce9a9d8be 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -639,6 +639,15 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "AIF2 Capture", NULL, "SYSCLK" }, { "AIF3 Capture", NULL, "SYSCLK" }, + { "IN1L PGA", NULL, "IN1L" }, + { "IN1R PGA", NULL, "IN1R" }, + + { "IN2L PGA", NULL, "IN2L" }, + { "IN2R PGA", NULL, "IN2R" }, + + { "IN3L PGA", NULL, "IN3L" }, + { "IN3R PGA", NULL, "IN3R" }, + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), -- GitLab From 17c3f7e8f3ef796a9db3b22f3797188d0e7ac88c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 10 Aug 2012 15:40:22 +0100 Subject: [PATCH 5369/5711] ASoC: wm5110: Add missing input PGA routes Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 8033f7065189..01ebbcc5c6a4 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -681,6 +681,18 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "AIF2 Capture", NULL, "SYSCLK" }, { "AIF3 Capture", NULL, "SYSCLK" }, + { "IN1L PGA", NULL, "IN1L" }, + { "IN1R PGA", NULL, "IN1R" }, + + { "IN2L PGA", NULL, "IN2L" }, + { "IN2R PGA", NULL, "IN2R" }, + + { "IN3L PGA", NULL, "IN3L" }, + { "IN3R PGA", NULL, "IN3R" }, + + { "IN4L PGA", NULL, "IN4L" }, + { "IN4R PGA", NULL, "IN4R" }, + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), -- GitLab From 1f68237865b2f55badbb3f73792d573899a62475 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 10 Aug 2012 13:56:27 -0700 Subject: [PATCH 5370/5711] spi/bcm63xx: Ensure that memory is freed only after it is no longer used The call to spi_unregister_master() in the device remove function frees device memory, and with it any device local data. However, device local data is still accessed after the call to spi_unregister_master(). Acquire a reference to the SPI device and release it after cleanup is complete to solve the problem. Signed-off-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 6e25ef1bce91..ea0aaa3f13d0 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -438,7 +438,7 @@ out: static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct bcm63xx_spi *bs = spi_master_get_devdata(master); spi_unregister_master(master); @@ -452,6 +452,8 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) platform_set_drvdata(pdev, 0); + spi_master_put(master); + return 0; } -- GitLab From 3d61bd42135a5801ce6c2bc47f33277fde74e5ea Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 19 Jul 2012 20:11:44 -0400 Subject: [PATCH 5371/5711] drm/radeon: fix handling for ddc type 5 on combios When ddc type is 5, need to look up the i2c channel in the i2c table. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_combios.c | 57 ++++++++++++++++--------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 576f4f6919f2..f75247d42ffd 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -719,6 +719,34 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde return i2c; } +static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct radeon_i2c_bus_rec i2c; + u16 offset; + u8 id, blocks, clk, data; + int i; + + i2c.valid = false; + + offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); + if (offset) { + blocks = RBIOS8(offset + 2); + for (i = 0; i < blocks; i++) { + id = RBIOS8(offset + 3 + (i * 5) + 0); + if (id == 136) { + clk = RBIOS8(offset + 3 + (i * 5) + 3); + data = RBIOS8(offset + 3 + (i * 5) + 4); + /* gpiopad */ + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, + (1 << clk), (1 << data)); + break; + } + } + } + return i2c; +} + void radeon_combios_i2c_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; @@ -755,30 +783,14 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) } else if (rdev->family == CHIP_RS300 || rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) { - u16 offset; - u8 id, blocks, clk, data; - int i; - /* 0x68 */ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); - offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); - if (offset) { - blocks = RBIOS8(offset + 2); - for (i = 0; i < blocks; i++) { - id = RBIOS8(offset + 3 + (i * 5) + 0); - if (id == 136) { - clk = RBIOS8(offset + 3 + (i * 5) + 3); - data = RBIOS8(offset + 3 + (i * 5) + 4); - /* gpiopad */ - i2c = combios_setup_i2c_bus(rdev, DDC_MONID, - (1 << clk), (1 << data)); - rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); - break; - } - } - } + /* gpiopad */ + i2c = radeon_combios_get_i2c_info_from_table(rdev); + if (i2c.valid) + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); } else if ((rdev->family == CHIP_R200) || (rdev->family >= CHIP_R300)) { /* 0x68 */ @@ -2321,7 +2333,10 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) connector = (tmp >> 12) & 0xf; ddc_type = (tmp >> 8) & 0xf; - ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); + if (ddc_type == 5) + ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); + else + ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); switch (connector) { case CONNECTOR_PROPRIETARY_LEGACY: -- GitLab From f4254a2bb4555e26289a19b71bfa8a4965c5b5ee Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Jul 2012 15:20:24 -0400 Subject: [PATCH 5372/5711] drm/radeon/dce4+: set a more reasonable cursor watermark Set a more reasonable default cursor watermark. The recommended default value is 4. This should reduce urgency requests to the MC form the display hw. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_cursor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 711e95ad39bf..8794744cdf1a 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -67,7 +67,8 @@ static void radeon_hide_cursor(struct drm_crtc *crtc) if (ASIC_IS_DCE4(rdev)) { WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); - WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); + WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); } else if (ASIC_IS_AVIVO(rdev)) { WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); @@ -94,7 +95,8 @@ static void radeon_show_cursor(struct drm_crtc *crtc) if (ASIC_IS_DCE4(rdev)) { WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | - EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); } else if (ASIC_IS_AVIVO(rdev)) { WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | -- GitLab From 3838f46e363d5a07e61d0352bf11d534dc61f921 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 25 Jul 2012 12:32:59 -0400 Subject: [PATCH 5373/5711] drm/radeon: properly handle SS overrides on TN (v2) The IntegratedSystemInfo table changed versions on TN. Update the SS override lookup to handle it. v2: fix copy-paste typo. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 49 ++++++++++++++++++------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b1e3820df363..f9c21f9d16bc 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1263,6 +1263,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) union igp_info { struct _ATOM_INTEGRATED_SYSTEM_INFO info; struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; }; bool radeon_atombios_sideport_present(struct radeon_device *rdev) @@ -1390,27 +1392,50 @@ static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, struct radeon_mode_info *mode_info = &rdev->mode_info; int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); u16 data_offset, size; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; + union igp_info *igp_info; u8 frev, crev; u16 percentage = 0, rate = 0; /* get any igp specific overrides */ if (atom_parse_data_header(mode_info->atom_context, index, &size, &frev, &crev, &data_offset)) { - igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) + igp_info = (union igp_info *) (mode_info->atom_context->bios + data_offset); - switch (id) { - case ASIC_INTERNAL_SS_ON_TMDS: - percentage = le16_to_cpu(igp_info->usDVISSPercentage); - rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); + switch (crev) { + case 6: + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); + rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); + rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); + break; + } break; - case ASIC_INTERNAL_SS_ON_HDMI: - percentage = le16_to_cpu(igp_info->usHDMISSPercentage); - rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); + case 7: + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); + rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); + rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); + break; + } break; - case ASIC_INTERNAL_SS_ON_LVDS: - percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); - rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); + default: + DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); break; } if (percentage) -- GitLab From 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 26 Jul 2012 13:38:52 -0400 Subject: [PATCH 5374/5711] drm/radeon: properly handle crtc powergating Need to make sure the crtc is gated on before modesetting. Explicitly gate the crtc on in prepare() and set a flag so that the dpms functions don't gate it off during mode set. Noticed by sylware on IRC. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++-- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 9e6f76fec527..dc279ebf7afb 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); /* disable crtc pair power gating before programming */ - if (ASIC_IS_DCE6(rdev)) + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev)) { + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { struct drm_crtc *other_crtc; struct radeon_crtc *other_radeon_crtc; list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { @@ -1635,18 +1635,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + radeon_crtc->in_mode_set = true; /* pick pll */ radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + atombios_lock_crtc(crtc, ATOM_ENABLE); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void atombios_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); atombios_lock_crtc(crtc, ATOM_DISABLE); + radeon_crtc->in_mode_set = false; } static void atombios_crtc_disable(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index d5fd615897ec..94b4a1c12893 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, static void radeon_crtc_prepare(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; + radeon_crtc->in_mode_set = true; /* * The hardware wedges sometimes if you reconfigure one CRTC * whilst another is running (see fdo bug #24611). @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) static void radeon_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) if (crtci->enabled) radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); } + radeon_crtc->in_mode_set = false; } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f380d59c5763..d56978949f34 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -275,6 +275,7 @@ struct radeon_crtc { u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; + bool in_mode_set; uint32_t crtc_offset; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; -- GitLab From dca571a6a4edda1f61ba7ecb47431a22245490a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 31 Jul 2012 13:48:51 +0200 Subject: [PATCH 5375/5711] drm/radeon: fix bank tiling parameters on SI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sixteen bank case wasn't handled here, leading to GPU crashes because of userspace miscalculation. Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c053f8193771..c153a7f359c8 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1639,11 +1639,19 @@ static void si_gpu_init(struct radeon_device *rdev) /* XXX what about 12? */ rdev->config.si.tile_config |= (3 << 0); break; - } - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.si.tile_config |= 1 << 4; - else + } + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.si.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.si.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.si.tile_config |= 2 << 4; + break; + } rdev->config.si.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.si.tile_config |= -- GitLab From c8d15edc17d836686d1f071e564800e1a2724fa6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 31 Jul 2012 11:01:10 -0400 Subject: [PATCH 5376/5711] drm/radeon: fix bank tiling parameters on evergreen Handle the 16 bank case. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e585a3b947eb..f4ef24f11419 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1986,10 +1986,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.evergreen.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.evergreen.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.evergreen.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.evergreen.tile_config |= 2 << 4; + break; + } } rdev->config.evergreen.tile_config |= 0 << 8; rdev->config.evergreen.tile_config |= -- GitLab From 5b23c9045a8b61352986270b2d109edf5085e113 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 31 Jul 2012 11:05:11 -0400 Subject: [PATCH 5377/5711] drm/radeon: fix bank tiling parameters on cayman Handle the 16 bank case. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ni.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 9945d86d9001..853800e8582f 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -574,10 +574,18 @@ static void cayman_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.cayman.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.cayman.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.cayman.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.cayman.tile_config |= 2 << 4; + break; + } } rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; -- GitLab From 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 27 Jul 2012 16:32:24 -0400 Subject: [PATCH 5378/5711] drm/radeon: do not reenable crtc after moving vram start address It seems we can not update the crtc scanout address. After disabling crtc, update to base address do not take effect after crtc being reenable leading to at least frame being scanout from the old crtc base address. Disabling crtc display request lead to same behavior. So after changing the vram address if we don't keep crtc disabled we will have the GPU trying to read some random system memory address with some iommu this will broke the crtc engine and will lead to broken display and iommu error message. So to avoid this, disable crtc. For flicker less boot we will need to avoid moving the vram start address. This patch should also fix : https://bugs.freedesktop.org/show_bug.cgi?id=42373 Cc: Signed-off-by: Jerome Glisse --- drivers/gpu/drm/radeon/evergreen.c | 57 ---------------------------- drivers/gpu/drm/radeon/radeon_asic.h | 8 +--- drivers/gpu/drm/radeon/rv515.c | 13 ------- 3 files changed, 2 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index f4ef24f11419..e93b80a6d4e9 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1229,24 +1229,8 @@ void evergreen_agp_enable(struct radeon_device *rdev) void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) { - save->vga_control[0] = RREG32(D1VGA_CONTROL); - save->vga_control[1] = RREG32(D2VGA_CONTROL); save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); - save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (rdev->num_crtc >= 4) { - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); - save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); - save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); - } - if (rdev->num_crtc >= 6) { - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); - save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); - save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); - } /* Stop all video */ WREG32(VGA_RENDER_CONTROL, 0); @@ -1357,47 +1341,6 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s /* Unlock host access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(D1VGA_CONTROL, save->vga_control[0]); - WREG32(D2VGA_CONTROL, save->vga_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); - WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index f4af24310438..0d445e7d00d1 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -255,13 +255,10 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); * rv515 */ struct rv515_mc_save { - u32 d1vga_control; - u32 d2vga_control; u32 vga_render_control; u32 vga_hdp_control; - u32 d1crtc_control; - u32 d2crtc_control; }; + int rv515_init(struct radeon_device *rdev); void rv515_fini(struct radeon_device *rdev); uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -389,11 +386,10 @@ void r700_cp_fini(struct radeon_device *rdev); * evergreen */ struct evergreen_mc_save { - u32 vga_control[6]; u32 vga_render_control; u32 vga_hdp_control; - u32 crtc_control[6]; }; + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); int evergreen_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index a12fbcc8ccb6..aa8ef491ef3c 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) { - save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); - save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); - save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); - save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); /* Stop all video */ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) /* Unlock host access */ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); - WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); - WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); - WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); } -- GitLab From ecd67955fd4c8e66e4df312098989d5fa7da624c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Aug 2012 17:06:03 -0400 Subject: [PATCH 5379/5711] drm/radeon: fix ordering in pll picking on dce4+ No functional change, but re-order the cases so they evaluate properly due to the way the DCE macros work. Noticed by kallisti5 on IRC. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index dc279ebf7afb..c6fcb5b86a45 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1531,12 +1531,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (ASIC_IS_DCE5(rdev)) - return ATOM_DCPLL; + if (rdev->clock.dp_extclk) + return ATOM_PPLL_INVALID; else if (ASIC_IS_DCE6(rdev)) return ATOM_PPLL0; - else if (rdev->clock.dp_extclk) - return ATOM_PPLL_INVALID; + else if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; } } } -- GitLab From 2f292004dd1fb005788dc0a9cdd5559812ed866e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Aug 2012 10:03:59 -0400 Subject: [PATCH 5380/5711] drm/radeon: add some new SI pci ids Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- include/drm/drm_pciids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 7ff5c99b1638..c78bb997e2c6 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -213,9 +213,12 @@ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -- GitLab From 69b62ad8a488727d5aab931c238aa399e6c3550c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 3 Aug 2012 11:50:54 -0400 Subject: [PATCH 5381/5711] drm/radeon: fix some missing parens in asic macros Better safe than sorry. Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse --- drivers/gpu/drm/radeon/radeon.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5431af292408..583e0f19e1c7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1733,11 +1733,11 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pflip.pre_page_flip((rdev), (crtc)) -#define radeon_page_flip(rdev, crtc, base) rdev->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) rdev->asic->pflip.post_page_flip((rdev), (crtc)) -#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->display.wait_for_vblank((rdev), (crtc)) -#define radeon_mc_wait_for_idle(rdev) rdev->asic->mc_wait_for_idle((rdev)) +#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) +#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) /* Common functions */ /* AGP */ -- GitLab From e43b5ec05afdc232be25aa481315035c1888d389 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 6 Aug 2012 12:32:21 -0400 Subject: [PATCH 5382/5711] drm/radeon: fence virtual address and free it once idle v4 Virtual address need to be fenced to know when we can safely remove it. This patch also properly clear the pagetable. Previously it was serouisly broken. Kernel 3.5/3.4 need a similar patch but adapted for difference in mutex locking. v2: For to update pagetable when unbinding bo (don't bailout if bo_va->valid is true). v3: Add kernel 3.5/3.4 comment. v4: Fix compilation warnings. Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_cs.c | 32 +++++++++++++++++++++++--- drivers/gpu/drm/radeon/radeon_gart.c | 24 +++++++++++++++++-- drivers/gpu/drm/radeon/radeon_gem.c | 13 ++--------- drivers/gpu/drm/radeon/radeon_object.c | 6 +---- 5 files changed, 55 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 583e0f19e1c7..b237a29142d1 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -300,6 +300,7 @@ struct radeon_bo_va { uint64_t soffset; uint64_t eoffset; uint32_t flags; + struct radeon_fence *fence; bool valid; }; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 8a4c49ef0cc4..b4a0db24f4dd 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -278,6 +278,30 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) return 0; } +static void radeon_bo_vm_fence_va(struct radeon_cs_parser *parser, + struct radeon_fence *fence) +{ + struct radeon_fpriv *fpriv = parser->filp->driver_priv; + struct radeon_vm *vm = &fpriv->vm; + struct radeon_bo_list *lobj; + + if (parser->chunk_ib_idx == -1) { + return; + } + if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) { + return; + } + + list_for_each_entry(lobj, &parser->validated, tv.head) { + struct radeon_bo_va *bo_va; + struct radeon_bo *rbo = lobj->bo; + + bo_va = radeon_bo_va(rbo, vm); + radeon_fence_unref(&bo_va->fence); + bo_va->fence = radeon_fence_ref(fence); + } +} + /** * cs_parser_fini() - clean parser states * @parser: parser structure holding parsing context. @@ -290,11 +314,14 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) { unsigned i; - if (!error) + if (!error) { + /* fence all bo va before ttm_eu_fence_buffer_objects so bo are still reserved */ + radeon_bo_vm_fence_va(parser, parser->ib.fence); ttm_eu_fence_buffer_objects(&parser->validated, parser->ib.fence); - else + } else { ttm_eu_backoff_reservation(&parser->validated); + } if (parser->relocs != NULL) { for (i = 0; i < parser->nrelocs; i++) { @@ -388,7 +415,6 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if (parser->chunk_ib_idx == -1) return 0; - if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) return 0; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index b3720054614d..9912182682ec 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -814,7 +814,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, return -EINVAL; } - if (bo_va->valid) + if (bo_va->valid && mem) return 0; ngpu_pages = radeon_bo_ngpu_pages(bo); @@ -859,11 +859,27 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, struct radeon_bo *bo) { struct radeon_bo_va *bo_va; + int r; bo_va = radeon_bo_va(bo, vm); if (bo_va == NULL) return 0; + /* wait for va use to end */ + while (bo_va->fence) { + r = radeon_fence_wait(bo_va->fence, false); + if (r) { + DRM_ERROR("error while waiting for fence: %d\n", r); + } + if (r == -EDEADLK) { + r = radeon_gpu_reset(rdev); + if (!r) + continue; + } + break; + } + radeon_fence_unref(&bo_va->fence); + mutex_lock(&rdev->vm_manager.lock); mutex_lock(&vm->mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); @@ -952,12 +968,15 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) radeon_vm_unbind_locked(rdev, vm); mutex_unlock(&rdev->vm_manager.lock); - /* remove all bo */ + /* remove all bo at this point non are busy any more because unbind + * waited for the last vm fence to signal + */ r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (!r) { bo_va = radeon_bo_va(rdev->ring_tmp_bo.bo, vm); list_del_init(&bo_va->bo_list); list_del_init(&bo_va->vm_list); + radeon_fence_unref(&bo_va->fence); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); kfree(bo_va); } @@ -969,6 +988,7 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) r = radeon_bo_reserve(bo_va->bo, false); if (!r) { list_del_init(&bo_va->bo_list); + radeon_fence_unref(&bo_va->fence); radeon_bo_unreserve(bo_va->bo); kfree(bo_va); } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 84d045245739..1b57b0058ad6 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -134,25 +134,16 @@ void radeon_gem_object_close(struct drm_gem_object *obj, struct radeon_device *rdev = rbo->rdev; struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; - struct radeon_bo_va *bo_va, *tmp; if (rdev->family < CHIP_CAYMAN) { return; } if (radeon_bo_reserve(rbo, false)) { + dev_err(rdev->dev, "leaking bo va because we fail to reserve bo\n"); return; } - list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) { - if (bo_va->vm == vm) { - /* remove from this vm address space */ - mutex_lock(&vm->mutex); - list_del(&bo_va->vm_list); - mutex_unlock(&vm->mutex); - list_del(&bo_va->bo_list); - kfree(bo_va); - } - } + radeon_vm_bo_rmv(rdev, vm, rbo); radeon_bo_unreserve(rbo); } diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1f1a4c803c1d..1cb014b571ab 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -52,11 +52,7 @@ void radeon_bo_clear_va(struct radeon_bo *bo) list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) { /* remove from all vm address space */ - mutex_lock(&bo_va->vm->mutex); - list_del(&bo_va->vm_list); - mutex_unlock(&bo_va->vm->mutex); - list_del(&bo_va->bo_list); - kfree(bo_va); + radeon_vm_bo_rmv(bo->rdev, bo_va->vm, bo); } } -- GitLab From f00245f182fab57c5eed28a50764600b2bf1ccdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 9 Aug 2012 16:34:15 +0200 Subject: [PATCH 5383/5711] drm/radeon/kms: reorder code in r600_check_texture_resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Reviewed-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 52 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 1119e31e5c2f..ff61402ef795 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1559,13 +1559,14 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, u32 tiling_flags) { struct r600_cs_track *track = p->track; - u32 nfaces, llevel, blevel, w0, h0, d0; - u32 word0, word1, l0_size, mipmap_size, word2, word3; + u32 dim, nfaces, llevel, blevel, w0, h0, d0; + u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5; u32 height_align, pitch, pitch_align, depth_align; - u32 array, barray, larray; + u32 barray, larray; u64 base_align; struct array_mode_checker array_check; u32 format; + bool is_array; /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) @@ -1583,12 +1584,28 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); } word1 = radeon_get_ib_value(p, idx + 1); + word2 = radeon_get_ib_value(p, idx + 2) << 8; + word3 = radeon_get_ib_value(p, idx + 3) << 8; + word4 = radeon_get_ib_value(p, idx + 4); + word5 = radeon_get_ib_value(p, idx + 5); + dim = G_038000_DIM(word0); w0 = G_038000_TEX_WIDTH(word0) + 1; + pitch = (G_038000_PITCH(word0) + 1) * 8; h0 = G_038004_TEX_HEIGHT(word1) + 1; d0 = G_038004_TEX_DEPTH(word1); + format = G_038004_DATA_FORMAT(word1); + blevel = G_038010_BASE_LEVEL(word4); + llevel = G_038014_LAST_LEVEL(word5); + /* pitch in texels */ + array_check.array_mode = G_038000_TILE_MODE(word0); + array_check.group_size = track->group_size; + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = 1; + array_check.blocksize = r600_fmt_get_blocksize(format); nfaces = 1; - array = 0; - switch (G_038000_DIM(word0)) { + is_array = false; + switch (dim) { case V_038000_SQ_TEX_DIM_1D: case V_038000_SQ_TEX_DIM_2D: case V_038000_SQ_TEX_DIM_3D: @@ -1601,7 +1618,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, break; case V_038000_SQ_TEX_DIM_1D_ARRAY: case V_038000_SQ_TEX_DIM_2D_ARRAY: - array = 1; + is_array = true; break; case V_038000_SQ_TEX_DIM_2D_MSAA: case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: @@ -1609,21 +1626,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); return -EINVAL; } - format = G_038004_DATA_FORMAT(word1); if (!r600_fmt_is_valid_texture(format, p->family)) { dev_warn(p->dev, "%s:%d texture invalid format %d\n", __func__, __LINE__, format); return -EINVAL; } - /* pitch in texels */ - pitch = (G_038000_PITCH(word0) + 1) * 8; - array_check.array_mode = G_038000_TILE_MODE(word0); - array_check.group_size = track->group_size; - array_check.nbanks = track->nbanks; - array_check.npipes = track->npipes; - array_check.nsamples = 1; - array_check.blocksize = r600_fmt_get_blocksize(format); if (r600_get_array_mode_alignment(&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", @@ -1649,20 +1657,13 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return -EINVAL; } - word2 = radeon_get_ib_value(p, idx + 2) << 8; - word3 = radeon_get_ib_value(p, idx + 3) << 8; - - word0 = radeon_get_ib_value(p, idx + 4); - word1 = radeon_get_ib_value(p, idx + 5); - blevel = G_038010_BASE_LEVEL(word0); - llevel = G_038014_LAST_LEVEL(word1); if (blevel > llevel) { dev_warn(p->dev, "texture blevel %d > llevel %d\n", blevel, llevel); } - if (array == 1) { - barray = G_038014_BASE_ARRAY(word1); - larray = G_038014_LAST_ARRAY(word1); + if (is_array) { + barray = G_038014_BASE_ARRAY(word5); + larray = G_038014_LAST_ARRAY(word5); nfaces = larray - barray + 1; } @@ -1679,7 +1680,6 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return -EINVAL; } /* using get ib will give us the offset into the mipmap bo */ - word3 = radeon_get_ib_value(p, idx + 3) << 8; if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ -- GitLab From b51ad12a36234c1f6707c9c54a414cfca23f3cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 9 Aug 2012 16:34:16 +0200 Subject: [PATCH 5384/5711] drm/radeon/kms: add MSAA texture support for r600-evergreen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the checking seems to be in place already. As you can see, log2(number of samples) resides in LAST_LEVEL. This is required for MSAA support (namely for depth-stencil resolve and blitting between MSAA resources). Signed-off-by: Marek Olšák Reviewed-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen_cs.c | 7 +++++++ drivers/gpu/drm/radeon/r600_cs.c | 7 ++++++- drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f2e5c545c973..e44a62a07fe3 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -788,6 +788,13 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, case V_030000_SQ_TEX_DIM_1D_ARRAY: case V_030000_SQ_TEX_DIM_2D_ARRAY: depth = 1; + break; + case V_030000_SQ_TEX_DIM_2D_MSAA: + case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: + surf.nsamples = 1 << llevel; + llevel = 0; + depth = 1; + break; case V_030000_SQ_TEX_DIM_3D: break; default: diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ff61402ef795..3dab49cb1d4a 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1620,8 +1620,13 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, case V_038000_SQ_TEX_DIM_2D_ARRAY: is_array = true; break; - case V_038000_SQ_TEX_DIM_2D_MSAA: case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: + is_array = true; + /* fall through */ + case V_038000_SQ_TEX_DIM_2D_MSAA: + array_check.nsamples = 1 << llevel; + llevel = 0; + break; default: dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4b736ecb0aa5..a7f8ac0d8f03 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -60,9 +60,10 @@ * 2.16.0 - fix evergreen 2D tiled surface calculation * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx * 2.18.0 - r600-eg: allow "invalid" DB formats + * 2.19.0 - r600-eg: MSAA textures */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 18 +#define KMS_DRIVER_MINOR 19 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); -- GitLab From 6759a0a7a0496dbbd4fb062c6a76d61c55d0fbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 9 Aug 2012 16:34:17 +0200 Subject: [PATCH 5385/5711] drm/radeon/kms: implement timestamp userspace query (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returns a snapshot of the GPU clock counter. Needed for certain OpenGL extensions. v2: agd5f - address Jerome's comments - add function documentation Signed-off-by: Marek Olšák Reviewed-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600.c | 20 +++++++++++++++ drivers/gpu/drm/radeon/r600d.h | 3 +++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ drivers/gpu/drm/radeon/radeon_device.c | 1 + drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- drivers/gpu/drm/radeon/radeon_kms.c | 35 +++++++++++++++++++++----- drivers/gpu/drm/radeon/si.c | 19 ++++++++++++++ drivers/gpu/drm/radeon/sid.h | 3 +++ include/drm/radeon_drm.h | 2 ++ 10 files changed, 82 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 637280f541a3..d79c639ae739 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3789,3 +3789,23 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); } } + +/** + * r600_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (R6xx-cayman). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) +{ + uint64_t clock; + + mutex_lock(&rdev->gpu_clock_mutex); + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); + mutex_unlock(&rdev->gpu_clock_mutex); + return clock; +} diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 4b116ae75fc2..fd328f4c3ea8 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -602,6 +602,9 @@ #define RLC_HB_WPTR 0x3f1c #define RLC_HB_WPTR_LSB_ADDR 0x3f14 #define RLC_HB_WPTR_MSB_ADDR 0x3f18 +#define RLC_GPU_CLOCK_COUNT_LSB 0x3f38 +#define RLC_GPU_CLOCK_COUNT_MSB 0x3f3c +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x3f40 #define RLC_MC_CNTL 0x3f44 #define RLC_UCODE_CNTL 0x3f48 #define RLC_UCODE_ADDR 0x3f2c diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b237a29142d1..99304194a65c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1534,6 +1534,7 @@ struct radeon_device { unsigned debugfs_count; /* virtual memory */ struct radeon_vm_manager vm_manager; + struct mutex gpu_clock_mutex; }; int radeon_device_init(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 0d445e7d00d1..18c38d14c8cd 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -368,6 +368,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, unsigned num_gpu_pages, struct radeon_sa_bo *vb); int r600_mc_wait_for_idle(struct radeon_device *rdev); +uint64_t r600_get_gpu_clock(struct radeon_device *rdev); /* * rv770,rv730,rv710,rv740 @@ -468,5 +469,6 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id); void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +uint64_t si_get_gpu_clock(struct radeon_device *rdev); #endif diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 742af8244e89..d2e243867ac6 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1009,6 +1009,7 @@ int radeon_device_init(struct radeon_device *rdev, atomic_set(&rdev->ih.lock, 0); mutex_init(&rdev->gem.mutex); mutex_init(&rdev->pm.mutex); + mutex_init(&rdev->gpu_clock_mutex); init_rwsem(&rdev->pm.mclk_lock); init_rwsem(&rdev->exclusive_lock); init_waitqueue_head(&rdev->irq.vblank_queue); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a7f8ac0d8f03..d7269f48d37c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -61,9 +61,10 @@ * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx * 2.18.0 - r600-eg: allow "invalid" DB formats * 2.19.0 - r600-eg: MSAA textures + * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 19 +#define KMS_DRIVER_MINOR 20 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 1d73f16b5d97..414b4acf6947 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -29,6 +29,7 @@ #include "drm_sarea.h" #include "radeon.h" #include "radeon_drm.h" +#include "radeon_asic.h" #include #include @@ -167,17 +168,39 @@ static void radeon_set_filp_rights(struct drm_device *dev, int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; - struct drm_radeon_info *info; + struct drm_radeon_info *info = data; struct radeon_mode_info *minfo = &rdev->mode_info; - uint32_t *value_ptr; - uint32_t value; + uint32_t value, *value_ptr; + uint64_t value64, *value_ptr64; struct drm_crtc *crtc; int i, found; - info = data; + /* TIMESTAMP is a 64-bit value, needs special handling. */ + if (info->request == RADEON_INFO_TIMESTAMP) { + if (rdev->family >= CHIP_R600) { + value_ptr64 = (uint64_t*)((unsigned long)info->value); + if (rdev->family >= CHIP_TAHITI) { + value64 = si_get_gpu_clock(rdev); + } else { + value64 = r600_get_gpu_clock(rdev); + } + + if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); + return -EFAULT; + } + return 0; + } else { + DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); + return -EINVAL; + } + } + value_ptr = (uint32_t *)((unsigned long)info->value); - if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) + if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { + DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; + } switch (info->request) { case RADEON_INFO_DEVICE_ID: @@ -337,7 +360,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { - DRM_ERROR("copy_to_user\n"); + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); return -EFAULT; } return 0; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c153a7f359c8..0139e227e3c7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -3968,3 +3968,22 @@ void si_fini(struct radeon_device *rdev) rdev->bios = NULL; } +/** + * si_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (SI). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t si_get_gpu_clock(struct radeon_device *rdev) +{ + uint64_t clock; + + mutex_lock(&rdev->gpu_clock_mutex); + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); + mutex_unlock(&rdev->gpu_clock_mutex); + return clock; +} diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7869089e8761..ef4815c27b1c 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -698,6 +698,9 @@ #define RLC_UCODE_ADDR 0xC32C #define RLC_UCODE_DATA 0xC330 +#define RLC_GPU_CLOCK_COUNT_LSB 0xC338 +#define RLC_GPU_CLOCK_COUNT_MSB 0xC33C +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340 #define RLC_MC_CNTL 0xC344 #define RLC_UCODE_CNTL 0xC348 diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 58056865b8e9..dc3a8cd7db8a 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -964,6 +964,8 @@ struct drm_radeon_cs { #define RADEON_INFO_IB_VM_MAX_SIZE 0x0f /* max pipes - needed for compute shaders */ #define RADEON_INFO_MAX_PIPES 0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP 0x11 struct drm_radeon_info { uint32_t request; -- GitLab From f59abbf28696389c91c2697c7db31f20cfa91d8a Mon Sep 17 00:00:00 2001 From: Dmitrii Cherkasov Date: Mon, 13 Aug 2012 10:53:29 -0400 Subject: [PATCH 5386/5711] drm/radeon: fix typo in function header comment Signed-off-by: Dmitrii Cherkasov Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 9912182682ec..bb3b7fe05ccd 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -950,7 +950,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) } /** - * radeon_vm_init - tear down a vm instance + * radeon_vm_fini - tear down a vm instance * * @rdev: radeon_device pointer * @vm: requested vm -- GitLab From a35b6466aabb051568b844e8c63f87a356d3d129 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 8 Aug 2012 21:46:40 +0200 Subject: [PATCH 5387/5711] sched, cgroup: Reduce rq->lock hold times for large cgroup hierarchies Peter Portante reported that for large cgroup hierarchies (and or on large CPU counts) we get immense lock contention on rq->lock and stuff stops working properly. His workload was a ton of processes, each in their own cgroup, everybody idling except for a sporadic wakeup once every so often. It was found that: schedule() idle_balance() load_balance() local_irq_save() double_rq_lock() update_h_load() walk_tg_tree(tg_load_down) tg_load_down() Results in an entire cgroup hierarchy walk under rq->lock for every new-idle balance and since new-idle balance isn't throttled this results in a lot of work while holding the rq->lock. This patch does two things, it removes the work from under rq->lock based on the good principle of race and pray which is widely employed in the load-balancer as a whole. And secondly it throttles the update_h_load() calculation to max once per jiffy. I considered excluding update_h_load() for new-idle balance all-together, but purely relying on regular balance passes to update this data might not work out under some rare circumstances where the new-idle busiest isn't the regular busiest for a while (unlikely, but a nightmare to debug if someone hits it and suffers). Cc: pjt@google.com Cc: Larry Woodman Cc: Mike Galbraith Reported-by: Peter Portante Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-aaarrzfpnaam7pqrekofu8a6@git.kernel.org Signed-off-by: Thomas Gleixner --- kernel/sched/fair.c | 11 +++++++++-- kernel/sched/sched.h | 6 +++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d0cc03b3e70b..c219bf8d704c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3387,6 +3387,14 @@ static int tg_load_down(struct task_group *tg, void *data) static void update_h_load(long cpu) { + struct rq *rq = cpu_rq(cpu); + unsigned long now = jiffies; + + if (rq->h_load_throttle == now) + return; + + rq->h_load_throttle = now; + rcu_read_lock(); walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); rcu_read_unlock(); @@ -4293,11 +4301,10 @@ redo: env.src_rq = busiest; env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running); + update_h_load(env.src_cpu); more_balance: local_irq_save(flags); double_rq_lock(this_rq, busiest); - if (!env.loop) - update_h_load(env.src_cpu); /* * cur_ld_moved - load moved in current iteration diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c35a1a7dd4d6..531411b1044e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -374,7 +374,11 @@ struct rq { #ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */ struct list_head leaf_cfs_rq_list; -#endif +#ifdef CONFIG_SMP + unsigned long h_load_throttle; +#endif /* CONFIG_SMP */ +#endif /* CONFIG_FAIR_GROUP_SCHED */ + #ifdef CONFIG_RT_GROUP_SCHED struct list_head leaf_rt_rq_list; #endif -- GitLab From bea6832cc8c4a0a9a65dd17da6aaa657fe27bc3e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 8 Aug 2012 11:27:15 +0200 Subject: [PATCH 5388/5711] sched: fix divide by zero at {thread_group,task}_times On architectures where cputime_t is 64 bit type, is possible to trigger divide by zero on do_div(temp, (__force u32) total) line, if total is a non zero number but has lower 32 bit's zeroed. Removing casting is not a good solution since some do_div() implementations do cast to u32 internally. This problem can be triggered in practice on very long lived processes: PID: 2331 TASK: ffff880472814b00 CPU: 2 COMMAND: "oraagent.bin" #0 [ffff880472a51b70] machine_kexec at ffffffff8103214b #1 [ffff880472a51bd0] crash_kexec at ffffffff810b91c2 #2 [ffff880472a51ca0] oops_end at ffffffff814f0b00 #3 [ffff880472a51cd0] die at ffffffff8100f26b #4 [ffff880472a51d00] do_trap at ffffffff814f03f4 #5 [ffff880472a51d60] do_divide_error at ffffffff8100cfff #6 [ffff880472a51e00] divide_error at ffffffff8100be7b [exception RIP: thread_group_times+0x56] RIP: ffffffff81056a16 RSP: ffff880472a51eb8 RFLAGS: 00010046 RAX: bc3572c9fe12d194 RBX: ffff880874150800 RCX: 0000000110266fad RDX: 0000000000000000 RSI: ffff880472a51eb8 RDI: 001038ae7d9633dc RBP: ffff880472a51ef8 R8: 00000000b10a3a64 R9: ffff880874150800 R10: 00007fcba27ab680 R11: 0000000000000202 R12: ffff880472a51f08 R13: ffff880472a51f10 R14: 0000000000000000 R15: 0000000000000007 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #7 [ffff880472a51f00] do_sys_times at ffffffff8108845d #8 [ffff880472a51f40] sys_times at ffffffff81088524 #9 [ffff880472a51f80] system_call_fastpath at ffffffff8100b0f2 RIP: 0000003808caac3a RSP: 00007fcba27ab6d8 RFLAGS: 00000202 RAX: 0000000000000064 RBX: ffffffff8100b0f2 RCX: 0000000000000000 RDX: 00007fcba27ab6e0 RSI: 000000000076d58e RDI: 00007fcba27ab6e0 RBP: 00007fcba27ab700 R8: 0000000000000020 R9: 000000000000091b R10: 00007fcba27ab680 R11: 0000000000000202 R12: 00007fff9ca41940 R13: 0000000000000000 R14: 00007fcba27ac9c0 R15: 00007fff9ca41940 ORIG_RAX: 0000000000000064 CS: 0033 SS: 002b Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120808092714.GA3580@redhat.com Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2cb4e7777998..e2c5841c7dfe 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3142,6 +3142,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) # define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) #endif +static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) +{ + u64 temp = (__force u64) rtime; + + temp *= (__force u64) utime; + + if (sizeof(cputime_t) == 4) + temp = div_u64(temp, (__force u32) total); + else + temp = div64_u64(temp, (__force u64) total); + + return (__force cputime_t) temp; +} + void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) { cputime_t rtime, utime = p->utime, total = utime + p->stime; @@ -3151,13 +3165,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) */ rtime = nsecs_to_cputime(p->se.sum_exec_runtime); - if (total) { - u64 temp = (__force u64) rtime; - - temp *= (__force u64) utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(utime, rtime, total); + else utime = rtime; /* @@ -3184,13 +3194,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) total = cputime.utime + cputime.stime; rtime = nsecs_to_cputime(cputime.sum_exec_runtime); - if (total) { - u64 temp = (__force u64) rtime; - - temp *= (__force u64) cputime.utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(cputime.utime, rtime, total); + else utime = rtime; sig->prev_utime = max(sig->prev_utime, utime); -- GitLab From 35cf4e50b16331def6cfcbee11e49270b6db07f5 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 7 Aug 2012 05:00:13 +0200 Subject: [PATCH 5389/5711] sched,cgroup: Fix up task_groups list With multiple instances of task_groups, for_each_rt_rq() is a noop, no task groups having been added to the rt.c list instance. This renders __enable/disable_runtime() and print_rt_stats() noop, the user (non) visible effect being that rt task groups are missing in /proc/sched_debug. Signed-off-by: Mike Galbraith Cc: stable@kernel.org # v3.3+ Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344308413.6846.7.camel@marge.simpson.net Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 1 + kernel/sched/sched.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e2c5841c7dfe..6aa212f3c581 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7252,6 +7252,7 @@ int in_sched_functions(unsigned long addr) #ifdef CONFIG_CGROUP_SCHED struct task_group root_task_group; +LIST_HEAD(task_groups); #endif DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 531411b1044e..f6714d009e77 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -80,7 +80,7 @@ extern struct mutex sched_domains_mutex; struct cfs_rq; struct rt_rq; -static LIST_HEAD(task_groups); +extern struct list_head task_groups; struct cfs_bandwidth { #ifdef CONFIG_CFS_BANDWIDTH -- GitLab From e221d028bb08b47e624c5f0a31732c642db9d19a Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 7 Aug 2012 10:02:38 +0200 Subject: [PATCH 5390/5711] sched,rt: fix isolated CPUs leaving root_task_group indefinitely throttled Root task group bandwidth replenishment must service all CPUs, regardless of where the timer was last started, and regardless of the isolation mechanism, lest 'Quoth the Raven, "Nevermore"' become rt scheduling policy. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344326558.6968.25.camel@marge.simpson.net Signed-off-by: Thomas Gleixner --- kernel/sched/rt.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 573e1ca01102..944cb68420e9 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -788,6 +788,19 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) const struct cpumask *span; span = sched_rt_period_mask(); +#ifdef CONFIG_RT_GROUP_SCHED + /* + * FIXME: isolated CPUs should really leave the root task group, + * whether they are isolcpus or were isolated via cpusets, lest + * the timer run on a CPU which does not service all runqueues, + * potentially leaving other CPUs indefinitely throttled. If + * isolation is really required, the user will turn the throttle + * off to kill the perturbations it causes anyway. Meanwhile, + * this maintains functionality for boot and/or troubleshooting. + */ + if (rt_b == &root_task_group.rt_bandwidth) + span = cpu_online_mask; +#endif for_each_cpu(i, span) { int enqueue = 0; struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i); -- GitLab From 8f6189684eb4e85e6c593cd710693f09c944450a Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Sat, 4 Aug 2012 05:44:14 +0200 Subject: [PATCH 5391/5711] sched: Fix migration thread runtime bogosity Make stop scheduler class do the same accounting as other classes, Migration threads can be caught in the act while doing exec balancing, leading to the below due to use of unmaintained ->se.exec_start. The load that triggered this particular instance was an apparently out of control heavily threaded application that does system monitoring in what equated to an exec bomb, with one of the VERY frequently migrated tasks being ps. %CPU PID USER CMD 99.3 45 root [migration/10] 97.7 53 root [migration/12] 97.0 57 root [migration/13] 90.1 49 root [migration/11] 89.6 65 root [migration/15] 88.7 17 root [migration/3] 80.4 37 root [migration/8] 78.1 41 root [migration/9] 44.2 13 root [migration/2] Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344051854.6739.19.camel@marge.simpson.net Signed-off-by: Thomas Gleixner --- kernel/sched/stop_task.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 7b386e86fd23..da5eb5bed84a 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -27,8 +27,10 @@ static struct task_struct *pick_next_task_stop(struct rq *rq) { struct task_struct *stop = rq->stop; - if (stop && stop->on_rq) + if (stop && stop->on_rq) { + stop->se.exec_start = rq->clock_task; return stop; + } return NULL; } @@ -52,6 +54,21 @@ static void yield_task_stop(struct rq *rq) static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { + struct task_struct *curr = rq->curr; + u64 delta_exec; + + delta_exec = rq->clock_task - curr->se.exec_start; + if (unlikely((s64)delta_exec < 0)) + delta_exec = 0; + + schedstat_set(curr->se.statistics.exec_max, + max(curr->se.statistics.exec_max, delta_exec)); + + curr->se.sum_exec_runtime += delta_exec; + account_group_exec_runtime(curr, delta_exec); + + curr->se.exec_start = rq->clock_task; + cpuacct_charge(curr, delta_exec); } static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) @@ -60,6 +77,9 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) static void set_curr_task_stop(struct rq *rq) { + struct task_struct *stop = rq->stop; + + stop->se.exec_start = rq->clock_task; } static void switched_to_stop(struct rq *rq, struct task_struct *p) -- GitLab From 0bce9c46bf3b15f485d82d7e81dabed6ebcc24b1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 15:22:09 +0100 Subject: [PATCH 5392/5711] mutex: Place lock in contended state after fastpath_lock failure ARM recently moved to asm-generic/mutex-xchg.h for its mutex implementation after the previous implementation was found to be missing some crucial memory barriers. However, this has revealed some problems running hackbench on SMP platforms due to the way in which the MUTEX_SPIN_ON_OWNER code operates. The symptoms are that a bunch of hackbench tasks are left waiting on an unlocked mutex and therefore never get woken up to claim it. This boils down to the following sequence of events: Task A Task B Task C Lock value 0 1 1 lock() 0 2 lock() 0 3 spin(A) 0 4 unlock() 1 5 lock() 0 6 cmpxchg(1,0) 0 7 contended() -1 8 lock() 0 9 spin(C) 0 10 unlock() 1 11 cmpxchg(1,0) 0 12 unlock() 1 At this point, the lock is unlocked, but Task B is in an uninterruptible sleep with nobody to wake it up. This patch fixes the problem by ensuring we put the lock into the contended state if we fail to acquire it on the fastpath, ensuring that any blocked waiters are woken up when the mutex is released. Signed-off-by: Will Deacon Cc: Arnd Bergmann Cc: Chris Mason Cc: Ingo Molnar Cc: Reviewed-by: Nicolas Pitre Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-6e9lrw2avczr0617fzl5vqb8@git.kernel.org Signed-off-by: Thomas Gleixner --- include/asm-generic/mutex-xchg.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h index 580a6d35c700..c04e0db8a2d6 100644 --- a/include/asm-generic/mutex-xchg.h +++ b/include/asm-generic/mutex-xchg.h @@ -26,7 +26,13 @@ static inline void __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - fail_fn(count); + /* + * We failed to acquire the lock, so mark it contended + * to ensure that any waiting tasks are woken up by the + * unlock slow path. + */ + if (likely(atomic_xchg(count, -1) != 1)) + fail_fn(count); } /** @@ -43,7 +49,8 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - return fail_fn(count); + if (likely(atomic_xchg(count, -1) != 1)) + return fail_fn(count); return 0; } -- GitLab From cffa59baa5f1cf3e3e9e172697db48912471531c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 2 Aug 2012 12:55:27 +0200 Subject: [PATCH 5393/5711] perf, x86: Fix uncore_types_exit section mismatch Fix the following section mismatch: WARNING: arch/x86/kernel/cpu/built-in.o(.text+0x7ad9): Section mismatch in reference from the function uncore_types_exit() to the function .init.text:uncore_type_exit() The function uncore_types_exit() references the function __init uncore_type_exit(). This is often because uncore_types_exit lacks a __init annotation or the annotation of uncore_type_exit is wrong. caused by 14371cce03c2 ("perf: Add generic PCI uncore PMU device support"). Cc: Zheng Yan Cc: Ingo Molnar Signed-off-by: Borislav Petkov Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1339741902-8449-8-git-send-email-zheng.z.yan@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 7563fda9f033..a7ccd68aa13a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -2373,7 +2373,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) type->attr_groups[1] = NULL; } -static void uncore_types_exit(struct intel_uncore_type **types) +static void __init uncore_types_exit(struct intel_uncore_type **types) { int i; for (i = 0; types[i]; i++) -- GitLab From ebb6cc03596cc89c89670473282ea46573feb34f Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 6 Aug 2012 13:11:21 +0800 Subject: [PATCH 5394/5711] perf/x86: Fixes for Nehalem-EX uncore driver This patch includes following fixes and update: - Only some events in the Sbox and Mbox can use the match/mask registers, add code to check this. - The format definitions for xbr_mm_cfg and xbr_match registers in the Rbox are wrong, xbr_mm_cfg should use 32 bits, xbr_match should use 64 bits. - Cleanup the Rbox code. Compute the addresses extra registers in the enable_event function instead of the hw_config function. This simplifies the code in nhmex_rbox_alter_er(). Signed-off-by: Yan, Zheng Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344229882-3907-2-git-send-email-zheng.z.yan@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 195 ++++++++---------- arch/x86/kernel/cpu/perf_event_intel_uncore.h | 1 + 2 files changed, 87 insertions(+), 109 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index a7ccd68aa13a..84434e2a676f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -796,7 +796,6 @@ static struct intel_uncore_type *nhm_msr_uncores[] = { DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); -DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63"); DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); @@ -1032,24 +1031,22 @@ static struct intel_uncore_type nhmex_uncore_bbox = { static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) { - struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; - struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; + struct hw_perf_event *hwc = &event->hw; + struct hw_perf_event_extra *reg1 = &hwc->extra_reg; + struct hw_perf_event_extra *reg2 = &hwc->branch_reg; - if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { - reg1->config = event->attr.config1; - reg2->config = event->attr.config2; - } else { - reg1->config = ~0ULL; - reg2->config = ~0ULL; - } + /* only TO_R_PROG_EV event uses the match/mask register */ + if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != + NHMEX_S_EVENT_TO_R_PROG_EV) + return 0; if (box->pmu->pmu_idx == 0) reg1->reg = NHMEX_S0_MSR_MM_CFG; else reg1->reg = NHMEX_S1_MSR_MM_CFG; - reg1->idx = 0; - + reg1->config = event->attr.config1; + reg2->config = event->attr.config2; return 0; } @@ -1059,8 +1056,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per struct hw_perf_event_extra *reg1 = &hwc->extra_reg; struct hw_perf_event_extra *reg2 = &hwc->branch_reg; - wrmsrl(reg1->reg, 0); - if (reg1->config != ~0ULL || reg2->config != ~0ULL) { + if (reg1->idx != EXTRA_REG_NONE) { + wrmsrl(reg1->reg, 0); wrmsrl(reg1->reg + 1, reg1->config); wrmsrl(reg1->reg + 2, reg2->config); wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); @@ -1074,7 +1071,6 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = { &format_attr_edge.attr, &format_attr_inv.attr, &format_attr_thresh8.attr, - &format_attr_mm_cfg.attr, &format_attr_match.attr, &format_attr_mask.attr, NULL, @@ -1264,7 +1260,8 @@ again: } /* for the match/mask registers */ - if ((uncore_box_is_fake(box) || !reg2->alloc) && + if (reg2->idx != EXTRA_REG_NONE && + (uncore_box_is_fake(box) || !reg2->alloc) && !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) goto fail; @@ -1278,7 +1275,8 @@ again: if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) nhmex_mbox_alter_er(event, idx[0], true); reg1->alloc |= alloc; - reg2->alloc = 1; + if (reg2->idx != EXTRA_REG_NONE) + reg2->alloc = 1; } return NULL; fail: @@ -1342,9 +1340,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event struct extra_reg *er; unsigned msr; int reg_idx = 0; - - if (WARN_ON_ONCE(reg1->idx != -1)) - return -EINVAL; /* * The mbox events may require 2 extra MSRs at the most. But only * the lower 32 bits in these MSRs are significant, so we can use @@ -1355,11 +1350,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event continue; if (event->attr.config1 & ~er->valid_mask) return -EINVAL; - if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || - er->idx == __BITS_VALUE(reg1->idx, 1, 8)) - continue; - if (WARN_ON_ONCE(reg_idx >= 2)) - return -EINVAL; msr = er->msr + type->msr_offset * box->pmu->pmu_idx; if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) @@ -1368,6 +1358,8 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event /* always use the 32~63 bits to pass the PLD config */ if (er->idx == EXTRA_REG_NHMEX_M_PLD) reg_idx = 1; + else if (WARN_ON_ONCE(reg_idx > 0)) + return -EINVAL; reg1->idx &= ~(0xff << (reg_idx * 8)); reg1->reg &= ~(0xffff << (reg_idx * 16)); @@ -1376,17 +1368,21 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event reg1->config = event->attr.config1; reg_idx++; } - /* use config2 to pass the filter config */ - reg2->idx = EXTRA_REG_NHMEX_M_FILTER; - if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) - reg2->config = event->attr.config2; - else - reg2->config = ~0ULL; - if (box->pmu->pmu_idx == 0) - reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; - else - reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; - + /* + * The mbox only provides ability to perform address matching + * for the PLD events. + */ + if (reg_idx == 2) { + reg2->idx = EXTRA_REG_NHMEX_M_FILTER; + if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) + reg2->config = event->attr.config2; + else + reg2->config = ~0ULL; + if (box->pmu->pmu_idx == 0) + reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; + else + reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; + } return 0; } @@ -1422,34 +1418,36 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), nhmex_mbox_shared_reg_config(box, idx)); - wrmsrl(reg2->reg, 0); - if (reg2->config != ~0ULL) { - wrmsrl(reg2->reg + 1, - reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); - wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & - (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); - wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); + if (reg2->idx != EXTRA_REG_NONE) { + wrmsrl(reg2->reg, 0); + if (reg2->config != ~0ULL) { + wrmsrl(reg2->reg + 1, + reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); + wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & + (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); + wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); + } } wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); } -DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); -DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); -DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); -DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); -DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); -DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); -DEFINE_UNCORE_FORMAT_ATTR(filter_cfg, filter_cfg, "config2:63"); -DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); -DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); -DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); +DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); +DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); +DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); +DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); +DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); +DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63"); +DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); +DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); +DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); static struct attribute *nhmex_uncore_mbox_formats_attr[] = { &format_attr_count_mode.attr, @@ -1458,7 +1456,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = { &format_attr_flag_mode.attr, &format_attr_inc_sel.attr, &format_attr_set_flag_sel.attr, - &format_attr_filter_cfg.attr, + &format_attr_filter_cfg_en.attr, &format_attr_filter_match.attr, &format_attr_filter_mask.attr, &format_attr_dsp.attr, @@ -1513,7 +1511,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) struct hw_perf_event_extra *reg1 = &hwc->extra_reg; int port; - /* adjust the main event selector */ + /* adjust the main event selector and extra register index */ if (reg1->idx % 2) { reg1->idx--; hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1522,29 +1520,17 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; } - /* adjust address or config of extra register */ + /* adjust extra register config */ port = reg1->idx / 6 + box->pmu->pmu_idx * 4; switch (reg1->idx % 6) { - case 0: - reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); - break; - case 1: - reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); - break; case 2: - /* the 8~15 bits to the 0~7 bits */ + /* shift the 8~15 bits to the 0~7 bits */ reg1->config >>= 8; break; case 3: - /* the 0~7 bits to the 8~15 bits */ + /* shift the 0~7 bits to the 8~15 bits */ reg1->config <<= 8; break; - case 4: - reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); - break; - case 5: - reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); - break; }; } @@ -1671,7 +1657,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event struct hw_perf_event *hwc = &event->hw; struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; - int port, idx; + int idx; idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1681,27 +1667,11 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event reg1->idx = idx; reg1->config = event->attr.config1; - port = idx / 6 + box->pmu->pmu_idx * 4; - idx %= 6; - switch (idx) { - case 0: - reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); - break; - case 1: - reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); - break; - case 2: - case 3: - reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); - break; + switch (idx % 6) { case 4: case 5: - if (idx == 4) - reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); - else - reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); - reg2->config = event->attr.config2; hwc->config |= event->attr.config & (~0ULL << 32); + reg2->config = event->attr.config2; break; }; return 0; @@ -1727,28 +1697,34 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per struct hw_perf_event *hwc = &event->hw; struct hw_perf_event_extra *reg1 = &hwc->extra_reg; struct hw_perf_event_extra *reg2 = &hwc->branch_reg; - int idx, er_idx; + int idx, port; - idx = reg1->idx % 6; - er_idx = idx; - if (er_idx > 2) - er_idx--; - er_idx += (reg1->idx / 6) * 5; + idx = reg1->idx; + port = idx / 6 + box->pmu->pmu_idx * 4; - switch (idx) { + switch (idx % 6) { case 0: + wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); + break; case 1: - wrmsrl(reg1->reg, reg1->config); + wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config); break; case 2: case 3: - wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); + wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), + nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5)); break; case 4: + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), + hwc->config >> 32); + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); + break; case 5: - wrmsrl(reg1->reg, reg1->config); - wrmsrl(reg1->reg + 1, hwc->config >> 32); - wrmsrl(reg1->reg + 2, reg2->config); + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), + hwc->config >> 32); + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); + wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config); break; }; @@ -1756,8 +1732,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); } -DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); -DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63"); DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); @@ -2303,6 +2279,7 @@ int uncore_pmu_event_init(struct perf_event *event) event->hw.idx = -1; event->hw.last_tag = ~0ULL; event->hw.extra_reg.idx = EXTRA_REG_NONE; + event->hw.branch_reg.idx = EXTRA_REG_NONE; if (event->attr.config == UNCORE_FIXED_EVENT) { /* no fixed counter */ diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index c9e5dc56630a..8384e9b543b7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -230,6 +230,7 @@ #define NHMEX_S1_MSR_MASK 0xe5a #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) +#define NHMEX_S_EVENT_TO_R_PROG_EV 0 /* NHM-EX Mbox */ #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 -- GitLab From cb37af77124e8532e6ae3f9ca332593ba423b5f8 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 6 Aug 2012 13:11:22 +0800 Subject: [PATCH 5395/5711] perf/x86: Add Intel Westmere-EX uncore support The Westmere-EX uncore is similar to the Nehalem-EX uncore. The differences are: - Westmere-EX uncore has 10 instances of Cbox. The MSRs for Cbox8 and Cbox9 in the Westmere-EX aren't contiguous with Cbox 0~7. - The fvid field in the ZDP_CTL_FVC register in the Mbox is different. It's 5 bits in the Nehalem-EX, 6 bits in the Westmere-EX. Signed-off-by: Yan, Zheng Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344229882-3907-3-git-send-email-zheng.z.yan@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 56 ++++++++++++++++--- arch/x86/kernel/cpu/perf_event_intel_uncore.h | 45 +++++++-------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 84434e2a676f..0a5571080e74 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -901,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = { .attrs = nhmex_uncore_cbox_formats_attr, }; +/* msr offset for each instance of cbox */ +static unsigned nhmex_cbox_msr_offsets[] = { + 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, +}; + static struct intel_uncore_type nhmex_uncore_cbox = { .name = "cbox", .num_counters = 6, - .num_boxes = 8, + .num_boxes = 10, .perf_ctr_bits = 48, .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, .event_mask = NHMEX_PMON_RAW_EVENT_MASK, .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, - .msr_offset = NHMEX_C_MSR_OFFSET, + .msr_offsets = nhmex_cbox_msr_offsets, .pair_ctr_ctl = 1, .ops = &nhmex_uncore_ops, .format_group = &nhmex_uncore_cbox_format_group @@ -1138,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = { EVENT_EXTRA_END }; +/* Nehalem-EX or Westmere-EX ? */ +bool uncore_nhmex; + static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) { struct intel_uncore_extra_reg *er; @@ -1167,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 return false; /* mask of the shared fields */ - mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; + if (uncore_nhmex) + mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; + else + mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK; er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; raw_spin_lock_irqsave(&er->lock, flags); /* add mask of the non-shared field if it's in use */ - if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) - mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { + if (uncore_nhmex) + mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + else + mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + } if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { atomic_add(1 << (idx * 8), &er->ref); - mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | - NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + if (uncore_nhmex) + mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | + NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + else + mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | + WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); er->config &= ~mask; er->config |= (config & mask); ret = true; @@ -1212,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) /* get the non-shared control bits and shift them */ idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; - config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + if (uncore_nhmex) + config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + else + config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); if (new_idx > orig_idx) { idx = new_idx - orig_idx; config <<= 3 * idx; @@ -1222,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) } /* add the shared control bits back */ + if (uncore_nhmex) + config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; + else + config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; if (modify) { /* adjust the main event selector */ @@ -1480,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = { { /* end: all zeroes */ }, }; +static struct uncore_event_desc wsmex_uncore_mbox_events[] = { + INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), + INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), + { /* end: all zeroes */ }, +}; + static struct intel_uncore_ops nhmex_uncore_mbox_ops = { NHMEX_UNCORE_OPS_COMMON_INIT(), .enable_event = nhmex_mbox_msr_enable_event, @@ -2791,7 +2823,13 @@ static int __init uncore_cpu_init(void) snbep_uncore_cbox.num_boxes = max_cores; msr_uncores = snbep_msr_uncores; break; - case 46: + case 46: /* Nehalem-EX */ + uncore_nhmex = true; + case 47: /* Westmere-EX aka. Xeon E7 */ + if (!uncore_nhmex) + nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; + if (nhmex_uncore_cbox.num_boxes > max_cores) + nhmex_uncore_cbox.num_boxes = max_cores; msr_uncores = nhmex_msr_uncores; break; default: diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 8384e9b543b7..5b81c1856aac 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -276,18 +276,12 @@ NHMEX_M_PMON_CTL_INC_SEL_MASK | \ NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) - -#define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK 0x1f -#define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK (0x7 << 5) -#define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK (0x7 << 8) -#define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR (1 << 23) -#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK \ - (NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK | \ - NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK | \ - NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK | \ - NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) +#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23)) #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) +#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24)) +#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (12 + 3 * (n))) + /* * use the 9~13 bits to select event If the 7th bit is not set, * otherwise use the 19~21 bits to select event. @@ -369,6 +363,7 @@ struct intel_uncore_type { unsigned num_shared_regs:8; unsigned single_fixed:1; unsigned pair_ctr_ctl:1; + unsigned *msr_offsets; struct event_constraint unconstrainted; struct event_constraint *constraints; struct intel_uncore_pmu *pmus; @@ -486,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx) return idx * 8 + box->pmu->type->perf_ctr; } -static inline -unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) +{ + struct intel_uncore_pmu *pmu = box->pmu; + return pmu->type->msr_offsets ? + pmu->type->msr_offsets[pmu->pmu_idx] : + pmu->type->msr_offset * pmu->pmu_idx; +} + +static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) { if (!box->pmu->type->box_ctl) return 0; - return box->pmu->type->box_ctl + - box->pmu->type->msr_offset * box->pmu->pmu_idx; + return box->pmu->type->box_ctl + uncore_msr_box_offset(box); } -static inline -unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) { if (!box->pmu->type->fixed_ctl) return 0; - return box->pmu->type->fixed_ctl + - box->pmu->type->msr_offset * box->pmu->pmu_idx; + return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box); } -static inline -unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) { - return box->pmu->type->fixed_ctr + - box->pmu->type->msr_offset * box->pmu->pmu_idx; + return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box); } static inline @@ -516,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) { return box->pmu->type->event_ctl + (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + - box->pmu->type->msr_offset * box->pmu->pmu_idx; + uncore_msr_box_offset(box); } static inline @@ -524,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) { return box->pmu->type->perf_ctr + (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + - box->pmu->type->msr_offset * box->pmu->pmu_idx; + uncore_msr_box_offset(box); } static inline -- GitLab From 26a4f3c08de49c1437a7b7f97693cf22d8c31656 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Thu, 9 Aug 2012 11:52:34 +0300 Subject: [PATCH 5396/5711] perf/x86: disable PEBS on a guest entry. If PMU counter has PEBS enabled it is not enough to disable counter on a guest entry since PEBS memory write can overshoot guest entry and corrupt guest memory. Disabling PEBS during guest entry solves the problem. Tested-by: David Ahern Signed-off-by: Gleb Natapov Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120809085234.GI3341@redhat.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 382366977d4c..7f2739e03e79 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1522,8 +1522,16 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr) arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL; arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask; arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; + /* + * If PMU counter has PEBS enabled it is not enough to disable counter + * on a guest entry since PEBS memory write can overshoot guest entry + * and corrupt guest memory. Disabling PEBS solves the problem. + */ + arr[1].msr = MSR_IA32_PEBS_ENABLE; + arr[1].host = cpuc->pebs_enabled; + arr[1].guest = 0; - *nr = 1; + *nr = 2; return arr; } -- GitLab From cee25168e9c4ef7f9417632af2dc78b8521dfda7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 13 Aug 2012 17:33:02 +0300 Subject: [PATCH 5397/5711] drm/i915: ensure i2c adapter is all set before adding it i2c_add_adapter() may do i2c transfers on the bus to detect supported devices. Therefore the adapter needs to be all set before adding it. This was not the case for the bit-banging fallback, resulting in an oops if the device detection GMBUS transfers timed out. Fix the issue by calling i2c_add_adapter() only after intel_gpio_setup(). LKML-Reference: <5021F00B.7000503@ionic.de> Tested-by: Mihai Moldovan Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_i2c.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d79500bc1ce5..b9755f6378d8 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -486,9 +486,6 @@ int intel_setup_gmbus(struct drm_device *dev) bus->dev_priv = dev_priv; bus->adapter.algo = &gmbus_algorithm; - ret = i2c_add_adapter(&bus->adapter); - if (ret) - goto err; /* By default use a conservative clock rate */ bus->reg0 = port | GMBUS_RATE_100KHZ; @@ -498,6 +495,10 @@ int intel_setup_gmbus(struct drm_device *dev) bus->force_bit = true; intel_gpio_setup(bus, port); + + ret = i2c_add_adapter(&bus->adapter); + if (ret) + goto err; } intel_i2c_reset(dev_priv->dev); -- GitLab From e1352fde5682ab1bdd2a9e5d75c22d1fe210ef77 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 10 Aug 2012 11:00:24 +0200 Subject: [PATCH 5398/5711] ath9k: fix decrypt_error initialization in ath_rx_tasklet() ath_rx_tasklet() calls ath9k_rx_skb_preprocess() and ath9k_rx_skb_postprocess() in a loop over the received frames. The decrypt_error flag is initialized to false just outside ath_rx_tasklet() loop. ath9k_rx_accept(), called by ath9k_rx_skb_preprocess(), only sets decrypt_error to true and never to false. Then ath_rx_tasklet() calls ath9k_rx_skb_postprocess() and passes decrypt_error to it. So, after a decryption error, in ath9k_rx_skb_postprocess(), we can have a leftover value from another processed frame. In that case, the frame will not be marked with RX_FLAG_DECRYPTED even if it is decrypted correctly. When using CCMP encryption this issue can lead to connection stuck because of CCMP PN corruption and a waste of CPU time since mac80211 tries to decrypt an already deciphered frame with ieee80211_aes_ccm_decrypt. Fix the issue initializing decrypt_error flag at the begging of the ath_rx_tasklet() loop. Signed-off-by: Lorenzo Bianconi Cc: Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 12aca02228c2..4480c0cc655f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1044,7 +1044,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; - bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1066,6 +1065,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { + bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) break; -- GitLab From 7dd6753f6d2e7e0ccbf2263cef3a9fff6bc89988 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 12 Aug 2012 21:18:33 -0400 Subject: [PATCH 5399/5711] ath5k: fix spin_lock_irqsave/spin_lock_bh nesting in mesh Lockdep found an inconsistent lock state when joining a mesh with ath5k. The problem is that ath5k takes the lock for its beacon state, ah->block, with spin_lock_irqsave(), while mesh internally takes the sync_offset_lock with spin_lock_bh() in mesh_sync_offset_adjust_tbtt(), which in turn is called under ah->block. This could deadlock if the beacon tasklet was run on the processor that held the beacon lock during the do_softirq() in spin_unlock_bh(). We probably shouldn't hold the lock around the callbacks, but the easiest fix is to switch to spin_lock_bh for ah->block: it doesn't need interrupts disabled anyway as the data in question is only accessed in softirq or process context. Fixes the following lockdep warning: [ 446.892304] WARNING: at kernel/softirq.c:159 _local_bh_enable_ip+0x38/0xa6() [ 446.892306] Hardware name: MacBook1,1 [ 446.892309] Modules linked in: tcp_lp fuse sunrpc cpufreq_ondemand acpi_cpufreq mperf ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 nf_conntrack_ipv4 ip6table_filter nf_defrag_ipv4 xt_state nf_conntrack ip6_tables ext2 arc4 btusb bluetooth snd_hda_codec_idt snd_hda_intel carl9170 snd_hda_codec coretemp joydev ath5k snd_hwdep snd_seq isight_firmware ath snd_seq_device snd_pcm applesmc appletouch mac80211 input_polldev snd_timer microcode cfg80211 snd lpc_ich pcspkr i2c_i801 mfd_core soundcore rfkill snd_page_alloc sky2 tpm_infineon virtio_net kvm_intel kvm i915 drm_kms_helper drm i2c_algo_bit i2c_core video [ 446.892385] Pid: 1892, comm: iw Not tainted 3.6.0-rc1-wl+ #296 [ 446.892387] Call Trace: [ 446.892394] [] warn_slowpath_common+0x7c/0x91 [ 446.892398] [] ? _local_bh_enable_ip+0x38/0xa6 [ 446.892403] [] ? _local_bh_enable_ip+0x38/0xa6 [ 446.892459] [] ? mesh_sync_offset_adjust_tbtt+0x95/0x99 [mac80211] [ 446.892464] [] warn_slowpath_null+0x22/0x24 [ 446.892468] [] _local_bh_enable_ip+0x38/0xa6 [ 446.892473] [] local_bh_enable_ip+0xd/0xf [ 446.892479] [] _raw_spin_unlock_bh+0x34/0x37 [ 446.892527] [] mesh_sync_offset_adjust_tbtt+0x95/0x99 [mac80211] [ 446.892569] [] ieee80211_beacon_get_tim+0x28f/0x4e0 [mac80211] [ 446.892575] [] ? trace_hardirqs_on_caller+0x10e/0x13f [ 446.892591] [] ath5k_beacon_update+0x40/0x26b [ath5k] [ 446.892597] [] ? lock_acquired+0x1f5/0x21e [ 446.892612] [] ? ath5k_bss_info_changed+0x167/0x1b2 [ath5k] [ 446.892617] [] ? _raw_spin_lock_irqsave+0x78/0x82 [ 446.892632] [] ? ath5k_bss_info_changed+0x167/0x1b2 [ath5k] [ 446.892647] [] ath5k_bss_info_changed+0x175/0x1b2 [ath5k] [ 446.892651] [] ? lock_is_held+0x73/0x7b [ 446.892662] [] ? __might_sleep+0xa7/0x17a [ 446.892698] [] ieee80211_bss_info_change_notify+0x1ed/0x21a [mac80211] [ 446.892703] [] ? queue_work+0x24/0x32 [ 446.892718] [] ? ath5k_configure_filter+0x163/0x163 [ath5k] [ 446.892766] [] ieee80211_start_mesh+0xb9/0xbd [mac80211] [ 446.892806] [] ieee80211_join_mesh+0x10c/0x116 [mac80211] [ 446.892834] [] __cfg80211_join_mesh+0x176/0x1b3 [cfg80211] [ 446.892855] [] cfg80211_join_mesh+0x4f/0x6a [cfg80211] [ 446.892875] [] nl80211_join_mesh+0x1de/0x1ed [cfg80211] [ 446.892908] [] ? nl80211_set_wiphy+0x4cf/0x4cf [cfg80211] [ 446.892919] [] genl_rcv_msg+0x1d5/0x1f3 [ 446.892940] [] ? genl_rcv+0x25/0x25 [ 446.892946] [] netlink_rcv_skb+0x37/0x78 [ 446.892950] [] genl_rcv+0x1e/0x25 [ 446.892955] [] netlink_unicast+0xc3/0x12d [ 446.892959] [] netlink_sendmsg+0x1e9/0x213 [ 446.892966] [] sock_sendmsg+0x79/0x96 [ 446.892972] [] ? might_fault+0x9d/0xa3 [ 446.892978] [] ? copy_from_user+0x8/0xa [ 446.892983] [] ? verify_iovec+0x43/0x77 [ 446.892987] [] __sys_sendmsg+0x180/0x215 [ 446.892993] [] ? sched_clock_cpu+0x134/0x144 [ 446.892997] [] ? trace_hardirqs_off+0xb/0xd [ 446.893002] [] ? __lock_acquire+0x46b/0xb6e [ 446.893006] [] ? trace_hardirqs_off+0xb/0xd [ 446.893010] [] ? local_clock+0x32/0x49 [ 446.893015] [] ? lock_release_holdtime.part.9+0x4b/0x51 [ 446.893020] [] ? lock_is_held+0x73/0x7b [ 446.893025] [] ? fcheck_files+0x97/0xcd [ 446.893029] [] ? fget_light+0x2d/0x81 [ 446.893034] [] sys_sendmsg+0x3b/0x52 [ 446.893038] [] sys_socketcall+0x238/0x2a2 [ 446.893044] [] sysenter_do_call+0x12/0x38 [ 446.893047] ---[ end trace a9af5998f929270f ]--- [ 447.627222] [ 447.627232] ================================= [ 447.627237] [ INFO: inconsistent lock state ] [ 447.627244] 3.6.0-rc1-wl+ #296 Tainted: G W [ 447.627248] --------------------------------- [ 447.627253] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 447.627260] swapper/0/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 447.627264] (&(&ah->block)->rlock){+.?...}, at: [] ath5k_tasklet_beacon+0x91/0xa7 [ath5k] [ 447.627299] {SOFTIRQ-ON-W} state was registered at: [ 447.627304] [] mark_held_locks+0x59/0x77 [ 447.627316] [] trace_hardirqs_on_caller+0x10e/0x13f [ 447.627324] [] trace_hardirqs_on+0xb/0xd [ 447.627332] [] _local_bh_enable_ip+0x9e/0xa6 [ 447.627342] [] local_bh_enable_ip+0xd/0xf [ 447.627349] [] _raw_spin_unlock_bh+0x34/0x37 [ 447.627359] [] mesh_sync_offset_adjust_tbtt+0x95/0x99 [mac80211] [ 447.627451] [] ieee80211_beacon_get_tim+0x28f/0x4e0 [mac80211] [ 447.627526] [] ath5k_beacon_update+0x40/0x26b [ath5k] [ 447.627547] [] ath5k_bss_info_changed+0x175/0x1b2 [ath5k] [ 447.627569] [] ieee80211_bss_info_change_notify+0x1ed/0x21a [mac80211] [ 447.627628] [] ieee80211_start_mesh+0xb9/0xbd [mac80211] [ 447.627712] [] ieee80211_join_mesh+0x10c/0x116 [mac80211] [ 447.627782] [] __cfg80211_join_mesh+0x176/0x1b3 [cfg80211] [ 447.627816] [] cfg80211_join_mesh+0x4f/0x6a [cfg80211] [ 447.627845] [] nl80211_join_mesh+0x1de/0x1ed [cfg80211] [ 447.627872] [] genl_rcv_msg+0x1d5/0x1f3 [ 447.627881] [] netlink_rcv_skb+0x37/0x78 [ 447.627891] [] genl_rcv+0x1e/0x25 [ 447.627898] [] netlink_unicast+0xc3/0x12d [ 447.627907] [] netlink_sendmsg+0x1e9/0x213 [ 447.627915] [] sock_sendmsg+0x79/0x96 [ 447.627926] [] __sys_sendmsg+0x180/0x215 [ 447.627934] [] sys_sendmsg+0x3b/0x52 [ 447.627941] [] sys_socketcall+0x238/0x2a2 [ 447.627949] [] sysenter_do_call+0x12/0x38 [ 447.627959] irq event stamp: 1929200 [ 447.627963] hardirqs last enabled at (1929200): [] tasklet_hi_action+0x3e/0xbf [ 447.627972] hardirqs last disabled at (1929199): [] tasklet_hi_action+0x15/0xbf [ 447.627981] softirqs last enabled at (1929196): [] _local_bh_enable+0x12/0x14 [ 447.627989] softirqs last disabled at (1929197): [] do_softirq+0x63/0xb8 [ 447.627999] [ 447.627999] other info that might help us debug this: [ 447.628004] Possible unsafe locking scenario: [ 447.628004] [ 447.628009] CPU0 [ 447.628012] ---- [ 447.628016] lock(&(&ah->block)->rlock); [ 447.628023] [ 447.628027] lock(&(&ah->block)->rlock); [ 447.628034] [ 447.628034] *** DEADLOCK *** Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 6 ++---- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8c4c040a47b8..2aab20ee9f38 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2056,9 +2056,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) void ath5k_beacon_config(struct ath5k_hw *ah) { - unsigned long flags; - - spin_lock_irqsave(&ah->block, flags); + spin_lock_bh(&ah->block); ah->bmisscount = 0; ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); @@ -2085,7 +2083,7 @@ ath5k_beacon_config(struct ath5k_hw *ah) ath5k_hw_set_imr(ah, ah->imask); mmiowb(); - spin_unlock_irqrestore(&ah->block, flags); + spin_unlock_bh(&ah->block); } static void ath5k_tasklet_beacon(unsigned long data) diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 260e7dc7f751..d56453e43d7e 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -254,7 +254,6 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ath5k_vif *avf = (void *)vif->drv_priv; struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); - unsigned long flags; mutex_lock(&ah->lock); @@ -300,9 +299,9 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changes & BSS_CHANGED_BEACON) { - spin_lock_irqsave(&ah->block, flags); + spin_lock_bh(&ah->block); ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&ah->block, flags); + spin_unlock_bh(&ah->block); } if (changes & BSS_CHANGED_BEACON_ENABLED) -- GitLab From 12022a785328fdf61a3e1a4bc34db0098dabe839 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 13 Aug 2012 16:28:36 +0100 Subject: [PATCH 5400/5711] ASoC: jack: Always notify full jack status Don't just notify for the bits we've updated, notify the full state of the jack otherwise users might get confused by misleading reports. Signed-off-by: Mark Brown --- sound/soc/soc-jack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7f8b3b7428bb..0c172938b82a 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -103,7 +103,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) } /* Report before the DAPM sync to help users updating micbias status */ - blocking_notifier_call_chain(&jack->notifier, status, jack); + blocking_notifier_call_chain(&jack->notifier, jack->status, jack); snd_soc_dapm_sync(dapm); -- GitLab From 418edaaba96e58112b15c82b4907084e2a9caf42 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 3 Aug 2012 23:59:41 +0000 Subject: [PATCH 5401/5711] RDMA/ucma.c: Fix for events with wrong context on iWARP It is possible for asynchronous RDMA_CM_EVENT_ESTABLISHED events to be generated with ctx->uid == 0, because ucma_set_event_context() copies ctx->uid to the event structure outside of ctx->file->mut. This leads to a crash in the userspace library, since it gets a bogus event. Fix this by taking the mutex a bit earlier in ucma_event_handler. Signed-off-by: Tatyana Nikolova Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 6bf850422895..055ed59838dc 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -267,6 +267,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, if (!uevent) return event->event == RDMA_CM_EVENT_CONNECT_REQUEST; + mutex_lock(&ctx->file->mut); uevent->cm_id = cm_id; ucma_set_event_context(ctx, event, uevent); uevent->resp.event = event->event; @@ -277,7 +278,6 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, ucma_copy_conn_event(&uevent->resp.param.conn, &event->param.conn); - mutex_lock(&ctx->file->mut); if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) { if (!ctx->backlog) { ret = -ENOMEM; -- GitLab From af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Thu, 26 Jul 2012 20:53:19 +0200 Subject: [PATCH 5402/5711] drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate Signed-off-by: Christoph Bumiller Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d0d60e1e7f95..dac525b2994e 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ch = EVO_CURS(nv_crtc->index); - evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); + evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); evo_piow(crtc->dev, ch, 0x0080, 0x00000000); return 0; } -- GitLab From 3d7a1da2c2bddb916450b1a124a9bcd9c507bdce Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 27 Jul 2012 14:18:03 +1000 Subject: [PATCH 5403/5711] drm/nouveau/aux: mask off higher bits of auxch index in i2c table entry At least partially fixes DP output detection on W530. Not sure if more issues remain, or if my adaptor is just behaving weirdly (it does that sometimes). In any case, this patch is necessary. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 77e564667b5c..240cf962c999 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -229,7 +229,7 @@ nouveau_i2c_init(struct drm_device *dev) } break; case 6: /* NV50- DP AUX */ - port->drive = entry[0]; + port->drive = entry[0] & 0x0f; port->sense = port->drive; port->adapter.algo = &nouveau_dp_i2c_algo; break; -- GitLab From 44b9f44e111c1e4a50bff66a642cc7c5cb59af4e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 30 Jul 2012 12:03:30 +0200 Subject: [PATCH 5404/5711] nouveau: fixup scanout enable in nvc0_pm Fixes screen being black after changing performance level. Signed-off-by: Maarten Lankhorst Cc: stable@vger.kernel.org [3.5+] Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvc0_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 7c95c44e2887..4e712b10ebdb 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -557,7 +557,7 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) nouveau_mem_exec(&exec, info->perflvl); if (dev_priv->chipset < 0xd0) - nv_wr32(dev, 0x611200, 0x00003300); + nv_wr32(dev, 0x611200, 0x00003330); else nv_wr32(dev, 0x62c000, 0x03030300); } -- GitLab From fe0aac129c247be62fd8ad697ff510523fd71f74 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 4 Aug 2012 08:00:45 +0200 Subject: [PATCH 5405/5711] drm/nouveau: disable copy engine on NVAF The copy engine exhibits random memory corruption in at least one case, the GeForce 320M (nv50, 0xaf) in the MacBookAir3,1. This patch omits creating the engine for the specific chipset, falling back to M2MF, which kills the symptoms. Signed-off-by: Henrik Rydberg Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1cdfd6e757ce..1866dbb49979 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -731,7 +731,6 @@ nouveau_card_init(struct drm_device *dev) case 0xa3: case 0xa5: case 0xa8: - case 0xaf: nva3_copy_create(dev); break; } -- GitLab From 2064db725cc6d4ea19a24c138bc37939b63e3ae6 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Tue, 14 Aug 2012 02:22:07 +0300 Subject: [PATCH 5406/5711] drm/nv86/fifo: suspend fix This fix is a backport from the reworked nouveau driver. It masks off the engines we're not expecting to use before attempting a channel kickoff. Signed-off-by: Maxim Levitsky Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv84_fifo.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nv84_fifo.c b/drivers/gpu/drm/nouveau/nv84_fifo.c index cc82d799fc3b..c564c5e4c30a 100644 --- a/drivers/gpu/drm/nouveau/nv84_fifo.c +++ b/drivers/gpu/drm/nouveau/nv84_fifo.c @@ -117,17 +117,22 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; + u32 save; /* remove channel from playlist, will context switch if active */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); nv50_fifo_playlist_update(dev); + save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); + /* tell any engines on this channel to unload their contexts */ nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); + nv_wr32(dev, 0x002520, save); + nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -184,10 +189,13 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv84_fifo_priv *priv = nv_engine(dev, engine); int i; + u32 save; /* set playlist length to zero, fifo will unload context */ nv_wr32(dev, 0x0032ec, 0); + save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); + /* tell all connected engines to unload their contexts */ for (i = 0; i < priv->base.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; @@ -199,6 +207,7 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) } } + nv_wr32(dev, 0x002520, save); nv_wr32(dev, 0x002140, 0); return 0; } -- GitLab From f43e04ec46b67071d432fc3f368dc9891a3443e5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 13 Aug 2012 14:36:10 +0000 Subject: [PATCH 5407/5711] GPIO: gpio-pxa: fix building without CONFIG_OF Commit 7212157267 ("GPIO: gpio-pxa: fix devicetree functions") added an "xlate" function pointer to the irq_domain_ops, but this function is nor declared or defined anywhere when CONFIG_OF is disabled, causing the build error: drivers/gpio/gpio-pxa.c:532:11: error: 'irq_domain_xlate_twocell' undeclared here (not in a function) Extending the DT-only code section to cover the irq_domain_ops and the pxa_gpio_dt_ids solves this problem and makes it clearer which code is actually used without DT. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Torvalds --- drivers/gpio/gpio-pxa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 793767b0962a..9cac88a65f78 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -512,6 +512,7 @@ static int pxa_gpio_nums(void) return count; } +#ifdef CONFIG_OF static struct of_device_id pxa_gpio_dt_ids[] = { { .compatible = "mrvl,pxa-gpio" }, { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, @@ -532,7 +533,6 @@ const struct irq_domain_ops pxa_irq_domain_ops = { .xlate = irq_domain_xlate_twocell, }; -#ifdef CONFIG_OF static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) { int ret, nr_banks, nr_gpios, irq_base; @@ -679,7 +679,7 @@ static struct platform_driver pxa_gpio_driver = { .probe = pxa_gpio_probe, .driver = { .name = "pxa-gpio", - .of_match_table = pxa_gpio_dt_ids, + .of_match_table = of_match_ptr(pxa_gpio_dt_ids), }, }; -- GitLab From 35a38556d900b9cb5dfa2529c93944b847f8a8a4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 12 Aug 2012 22:17:14 +0200 Subject: [PATCH 5408/5711] drm/i915: reorder edp disabling to fix ivb MacBook Air eDP is tons of fun. It turns out that at least the new MacBook Air 5,1 model absolutely doesn't like the new force vdd dance we've introduced in commit 6cb49835da0426f69a2931bc2a0a8156344b0e41 Author: Daniel Vetter Date: Sun May 20 17:14:50 2012 +0200 drm/i915: enable vdd when switching off the eDP panel But that patch also tried to fix some neat edp sequence issue with the force_vdd timings. Closer inspection reveals that we've raised force_vdd only to do the aux channel communication dp_sink_dpms. If we move the edp_panel_off below that, we don't need any force_vdd for the disable sequence, which makes the Air happy. Unfortunately the reporter of the original bug that the above commit fixed is travelling, so we can't test whether this regresses things. But my theory is that since we don't check for any power-off -> force_vdd-on delays in edp_panel_vdd_on, this was the actual root-cause of this failure. With that force_vdd dance completely eliminated, I'm hopeful the original bug stays fixed, too. For reference the old bug, which hopefully doesn't get broken by this: https://bugzilla.kernel.org/show_bug.cgi?id=43163 In any case, regression fixers win over plain bugfixes, so this needs to go in asap. v2: The crucial pieces seems to be to clear the force_vdd flag uncoditionally, too, in edp_panel_off. Looks like this is left behind by the firmware somehow. v3: The Apple firmware seems to switch off the panel on it's own, hence we still need to keep force_vdd on, but properly clear it when switching the panel off. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45671 Tested-by: Roberto Romer Tested-by: Daniel Wagner Tested-by: Keith Packard Cc: stable@vger.kernel.org Cc: Keith Packard Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a56b9ab0f58..a6c426afaa7a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1174,10 +1174,14 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); + /* We need to switch off panel power _and_ force vdd, for otherwise some + * panels get very unhappy and cease to work. */ + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); + intel_dp->want_panel_vdd = false; + ironlake_wait_panel_off(intel_dp); } @@ -1287,11 +1291,9 @@ static void intel_dp_prepare(struct drm_encoder *encoder) * ensure that we have vdd while we switch off the panel. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1326,11 +1328,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) /* Switching the panel off requires vdd. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, mode); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); if (is_cpu_edp(intel_dp)) ironlake_edp_pll_off(encoder); -- GitLab From 7d54a904285b6e780291b91a518267bec5591913 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 10 Aug 2012 10:18:10 +0100 Subject: [PATCH 5409/5711] drm/i915: Apply post-sync write for pipe control invalidates When invalidating the TLBs it is documentated as requiring a post-sync write. Failure to do so seems to result in a GPU hang. Exposure to this hang on IVB seems to be a result of removing the extra stalls required for SNB pipecontrol workarounds: commit 6c6cf5aa9c583478b19e23149feaa92d01fb8c2d Author: Chris Wilson Date: Fri Jul 20 18:02:28 2012 +0100 drm/i915: Only apply the SNB pipe control w/a to gen6 Note: Manually switch the pipe_control cmd to 4 dwords to avoid a (silent) functional conflict with -next. This way will get a loud (but conflict with next (since the scratch_addr has been deleted there). Reported-and-tested-by: yex.tian@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=53322 Acked-by: Ben Widawsky Signed-off-by: Chris Wilson [danvet: added note about merge conflict with -next.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 41 ++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 414af1e2973b..e2a73b38abe9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -227,31 +227,36 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, * number of bits based on the write domains has little performance * impact. */ - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_TLB_INVALIDATE; - flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; - flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - /* - * Ensure that any following seqno writes only happen when the render - * cache is indeed flushed (but only if the caller actually wants that). - */ - if (flush_domains) + if (flush_domains) { + flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; + flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + /* + * Ensure that any following seqno writes only happen + * when the render cache is indeed flushed. + */ flags |= PIPE_CONTROL_CS_STALL; + } + if (invalidate_domains) { + flags |= PIPE_CONTROL_TLB_INVALIDATE; + flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; + /* + * TLB invalidate requires a post-sync write. + */ + flags |= PIPE_CONTROL_QW_WRITE; + } - ret = intel_ring_begin(ring, 6); + ret = intel_ring_begin(ring, 4); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); intel_ring_emit(ring, flags); intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, 0); /* lower dword */ - intel_ring_emit(ring, 0); /* uppwer dword */ - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, 0); intel_ring_advance(ring); return 0; -- GitLab From 265d931a9e9a7e290faa5e2145f4b2ebf38ea84c Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 13 Aug 2012 17:10:46 +0200 Subject: [PATCH 5410/5711] ALSA: hda - Fix 'Beep Playback Switch' with no underlying mute switch Some Conexant devices (e g CX20590) have no mute capability on their Beep widgets. This patch makes sure we don't try setting mutes on those widgets. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index d26ae65b43b7..0849aac449f2 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -231,15 +231,22 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); +static bool ctl_has_mute(struct snd_kcontrol *kcontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + return query_amp_caps(codec, get_amp_nid(kcontrol), + get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE; +} + /* get/put callbacks for beep mute mixer switches */ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; - if (beep && !beep->enabled) { + if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) { ucontrol->value.integer.value[0] = - ucontrol->value.integer.value[1] = 0; + ucontrol->value.integer.value[1] = beep->enabled; return 0; } return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); @@ -263,6 +270,8 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, enable |= *valp; snd_hda_enable_beep_device(codec, enable); } + if (!ctl_has_mute(kcontrol)) + return 0; return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); -- GitLab From 68e035c950dbceaf660144bf74054dfdfb6aad15 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 14 Aug 2012 12:47:37 +0200 Subject: [PATCH 5411/5711] netfilter: ctnetlink: fix missing locking while changing conntrack from nfqueue Since 9cb017665 netfilter: add glue code to integrate nfnetlink_queue and ctnetlink, we can modify the conntrack entry via nfnl_queue. However, the change of the conntrack entry via nfnetlink_queue requires appropriate locking to avoid concurrent updates. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 14f67a2cbcb5..da4fc37a8578 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1896,10 +1896,15 @@ static int ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) { struct nlattr *cda[CTA_MAX+1]; + int ret; nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); - return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); + spin_lock_bh(&nf_conntrack_lock); + ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); + spin_unlock_bh(&nf_conntrack_lock); + + return ret; } static struct nfq_ct_hook ctnetlink_nfqueue_hook = { -- GitLab From 3bdcff70b6cd049e6f4437b955850f5db83653cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Aug 2012 17:42:11 +0200 Subject: [PATCH 5412/5711] ALSA: lx6464es: Add a missing error check Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=44541 Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx6464es.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index d1ab43706735..5579b08bb35b 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -851,6 +851,8 @@ static int __devinit lx_pcm_create(struct lx6464es *chip) /* hardcoded device name & channel count */ err = snd_pcm_new(chip->card, (char *)card_name, 0, 1, 1, &pcm); + if (err < 0) + return err; pcm->private_data = chip; -- GitLab From f1c6300183dbf5b9da25988e13f6f25a9e27151b Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 8 Aug 2012 12:16:52 -0700 Subject: [PATCH 5413/5711] x86, apic: fix broken legacy interrupts in the logical apic mode Recent commit 332afa656e76458ee9cf0f0d123016a0658539e4 cleaned up a workaround that updates irq_cfg domain for legacy irq's that are handled by the IO-APIC. This was assuming that the recent changes in assign_irq_vector() were sufficient to remove the workaround. But this broke couple of AMD platforms. One of them seems to be sending interrupts to the offline cpu's, resulting in spurious "No irq handler for vector xx (irq -1)" messages when those cpu's come online. And the other platform seems to always send the interrupt to the last logical CPU (cpu-7). Recent changes had an unintended side effect of using only logical cpu-0 in the IO-APIC RTE (during boot for the legacy interrupts) and this broke the legacy interrupts not getting routed to the cpu-7 on the AMD platform, resulting in a boot hang. For now, reintroduce the removed workaround, (essentially not allowing the vector to change for legacy irq's when io-apic starts to handle the irq. Which also addressed the uninteded sife effect of just specifying cpu-0 in the IO-APIC RTE for those irq's during boot). Reported-and-tested-by: Robert Richter Reported-and-tested-by: Borislav Petkov Signed-off-by: Suresh Siddha Link: http://lkml.kernel.org/r/1344453412.29170.5.camel@sbsiddha-desk.sc.intel.com Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic/io_apic.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index a6c64aaddf9a..c265593ec2cd 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1356,6 +1356,16 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, if (!IO_APIC_IRQ(irq)) return; + /* + * For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC + * can handle this irq and the apic driver is finialized at this point, + * update the cfg->domain. + */ + if (irq < legacy_pic->nr_legacy_irqs && + cpumask_equal(cfg->domain, cpumask_of(0))) + apic->vector_allocation_domain(0, cfg->domain, + apic->target_cpus()); + if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; -- GitLab From f026cfa82f628db24b8cea41b9d6202af104cecb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 14 Aug 2012 09:53:38 -0700 Subject: [PATCH 5414/5711] Revert "x86-64/efi: Use EFI to deal with platform wall clock" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bacef661acdb634170a8faddbc1cf28e8f8b9eee. This commit has been found to cause serious regressions on a number of ASUS machines at the least. We probably need to provide a 1:1 map in addition to the EFI virtual memory map in order for this to work. Signed-off-by: H. Peter Anvin Reported-and-bisected-by: Jérôme Carretero Cc: Jan Beulich Cc: Matt Fleming Cc: Matthew Garrett Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20120805172903.5f8bb24c@zougloub.eu --- arch/x86/mm/pageattr.c | 10 ++++------ arch/x86/platform/efi/efi.c | 30 ++++++++++++++++++++++++++---- include/linux/efi.h | 2 ++ init/main.c | 8 ++++---- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 931930a96160..a718e0d23503 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -919,13 +919,11 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, /* * On success we use clflush, when the CPU supports it to - * avoid the wbindv. If the CPU does not support it, in the - * error case, and during early boot (for EFI) we fall back - * to cpa_flush_all (which uses wbinvd): + * avoid the wbindv. If the CPU does not support it and in the + * error case we fall back to cpa_flush_all (which uses + * wbindv): */ - if (early_boot_irqs_disabled) - __cpa_flush_all((void *)(long)cache); - else if (!ret && cpu_has_clflush) { + if (!ret && cpu_has_clflush) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 2dc29f51e75a..92660edaa1e7 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -234,7 +234,22 @@ static efi_status_t __init phys_efi_set_virtual_address_map( return status; } -static int efi_set_rtc_mmss(unsigned long nowtime) +static efi_status_t __init phys_efi_get_time(efi_time_t *tm, + efi_time_cap_t *tc) +{ + unsigned long flags; + efi_status_t status; + + spin_lock_irqsave(&rtc_lock, flags); + efi_call_phys_prelog(); + status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), + virt_to_phys(tc)); + efi_call_phys_epilog(); + spin_unlock_irqrestore(&rtc_lock, flags); + return status; +} + +int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -263,7 +278,7 @@ static int efi_set_rtc_mmss(unsigned long nowtime) return 0; } -static unsigned long efi_get_time(void) +unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; @@ -606,13 +621,18 @@ static int __init efi_runtime_init(void) } /* * We will only need *early* access to the following - * EFI runtime service before set_virtual_address_map + * two EFI runtime services before set_virtual_address_map * is invoked. */ + efi_phys.get_time = (efi_get_time_t *)runtime->get_time; efi_phys.set_virtual_address_map = (efi_set_virtual_address_map_t *) runtime->set_virtual_address_map; - + /* + * Make efi_get_time can be called before entering + * virtual mode. + */ + efi.get_time = phys_efi_get_time; early_iounmap(runtime, sizeof(efi_runtime_services_t)); return 0; @@ -700,10 +720,12 @@ void __init efi_init(void) efi_enabled = 0; return; } +#ifdef CONFIG_X86_32 if (efi_native) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } +#endif #if EFI_DEBUG print_efi_memmap(); diff --git a/include/linux/efi.h b/include/linux/efi.h index 103adc6d7e3a..ec45ccd8708a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -503,6 +503,8 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); +extern unsigned long efi_get_time(void); +extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; diff --git a/init/main.c b/init/main.c index e60679de61c3..b28673087ac0 100644 --- a/init/main.c +++ b/init/main.c @@ -461,10 +461,6 @@ static void __init mm_init(void) percpu_init_late(); pgtable_cache_init(); vmalloc_init(); -#ifdef CONFIG_X86 - if (efi_enabled) - efi_enter_virtual_mode(); -#endif } asmlinkage void __init start_kernel(void) @@ -606,6 +602,10 @@ asmlinkage void __init start_kernel(void) calibrate_delay(); pidmap_init(); anon_vma_init(); +#ifdef CONFIG_X86 + if (efi_enabled) + efi_enter_virtual_mode(); +#endif thread_info_cache_init(); cred_init(); fork_init(totalram_pages); -- GitLab From 47be03a28cc6c80e3aa2b3e8ed6d960ff0c5c0af Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:37 +0000 Subject: [PATCH 5415/5711] netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup() slave_enable_netpoll() and __netpoll_setup() may be called with read_lock() held, so should use GFP_ATOMIC to allocate memory. Eric suggested to pass gfp flags to __netpoll_setup(). Cc: Eric Dumazet Cc: "David S. Miller" Reported-by: Dan Carpenter Signed-off-by: Eric Dumazet Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 6 +++--- drivers/net/team/team.c | 16 +++++++++------- include/linux/netdevice.h | 3 ++- include/linux/netpoll.h | 2 +- net/8021q/vlan_dev.c | 7 ++++--- net/bridge/br_device.c | 12 ++++++------ net/bridge/br_if.c | 2 +- net/bridge/br_private.h | 4 ++-- net/core/netpoll.c | 8 ++++---- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6fae5f3ec7f6..8697136e27c0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave) struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*np), GFP_KERNEL); + np = kzalloc(sizeof(*np), GFP_ATOMIC); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, slave->dev); + err = __netpoll_setup(np, slave->dev, GFP_ATOMIC); if (err) { kfree(np); goto out; @@ -1292,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) read_unlock(&bond->lock); } -static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) +static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) { struct bonding *bond = netdev_priv(dev); struct slave *slave; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 87707ab39430..341b65dbbcd3 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port) } #ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, + gfp_t gfp) { struct netpoll *np; int err; - np = kzalloc(sizeof(*np), GFP_KERNEL); + np = kzalloc(sizeof(*np), gfp); if (!np) return -ENOMEM; - err = __netpoll_setup(np, port->dev); + err = __netpoll_setup(np, port->dev, gfp); if (err) { kfree(np); return err; @@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team) } #else -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, + gfp_t gfp) { return 0; } @@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) } if (team_netpoll_info(team)) { - err = team_port_enable_netpoll(team, port); + err = team_port_enable_netpoll(team, port, GFP_KERNEL); if (err) { netdev_err(dev, "Failed to enable netpoll on device %s\n", portname); @@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev) } static int team_netpoll_setup(struct net_device *dev, - struct netpoll_info *npifo) + struct netpoll_info *npifo, gfp_t gfp) { struct team *team = netdev_priv(dev); struct team_port *port; @@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev, mutex_lock(&team->lock); list_for_each_entry(port, &team->port_list, list) { - err = team_port_enable_netpoll(team, port); + err = team_port_enable_netpoll(team, port, gfp); if (err) { __team_netpoll_cleanup(team); break; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a9db4f33407f..3560d688161e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -953,7 +953,8 @@ struct net_device_ops { #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); int (*ndo_netpoll_setup)(struct net_device *dev, - struct netpoll_info *info); + struct netpoll_info *info, + gfp_t gfp); void (*ndo_netpoll_cleanup)(struct net_device *dev); #endif int (*ndo_set_vf_mac)(struct net_device *dev, diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 28f5389c924b..bf2d51eec0f3 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -43,7 +43,7 @@ struct netpoll_info { void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_print_options(struct netpoll *np); int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev); +int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp); int netpoll_setup(struct netpoll *np); int netpoll_trap(void); void netpoll_set_trap(int trap); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 73a2a83ee2da..ee4ae0944cef 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -669,19 +669,20 @@ static void vlan_dev_poll_controller(struct net_device *dev) return; } -static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) +static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, + gfp_t gfp) { struct vlan_dev_priv *info = vlan_dev_priv(dev); struct net_device *real_dev = info->real_dev; struct netpoll *netpoll; int err = 0; - netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); + netpoll = kzalloc(sizeof(*netpoll), gfp); err = -ENOMEM; if (!netpoll) goto out; - err = __netpoll_setup(netpoll, real_dev); + err = __netpoll_setup(netpoll, real_dev, gfp); if (err) { kfree(netpoll); goto out; diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 333484537600..ed0e0f9dc788 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -213,7 +213,8 @@ static void br_netpoll_cleanup(struct net_device *dev) } } -static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) +static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, + gfp_t gfp) { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p, *n; @@ -222,8 +223,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) list_for_each_entry_safe(p, n, &br->port_list, list) { if (!p->dev) continue; - - err = br_netpoll_enable(p); + err = br_netpoll_enable(p, gfp); if (err) goto fail; } @@ -236,17 +236,17 @@ fail: goto out; } -int br_netpoll_enable(struct net_bridge_port *p) +int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) { struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*p->np), GFP_KERNEL); + np = kzalloc(sizeof(*p->np), gfp); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, p->dev); + err = __netpoll_setup(np, p->dev, gfp); if (err) { kfree(np); goto out; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e1144e1617be..171fd6b9bfe6 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err2; - if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) + if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) goto err3; err = netdev_set_master(dev, br->dev); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a768b2408edf..f507d2af9646 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, netpoll_send_skb(np, skb); } -extern int br_netpoll_enable(struct net_bridge_port *p); +extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); extern void br_netpoll_disable(struct net_bridge_port *p); #else static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) @@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, { } -static inline int br_netpoll_enable(struct net_bridge_port *p) +static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) { return 0; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b4c90e42b443..37cc854774a4 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -715,7 +715,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) } EXPORT_SYMBOL(netpoll_parse_options); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev) +int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) { struct netpoll_info *npinfo; const struct net_device_ops *ops; @@ -734,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) } if (!ndev->npinfo) { - npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); + npinfo = kmalloc(sizeof(*npinfo), gfp); if (!npinfo) { err = -ENOMEM; goto out; @@ -752,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) ops = np->dev->netdev_ops; if (ops->ndo_netpoll_setup) { - err = ops->ndo_netpoll_setup(ndev, npinfo); + err = ops->ndo_netpoll_setup(ndev, npinfo, gfp); if (err) goto free_npinfo; } @@ -857,7 +857,7 @@ int netpoll_setup(struct netpoll *np) refill_skbs(); rtnl_lock(); - err = __netpoll_setup(np, ndev); + err = __netpoll_setup(np, ndev, GFP_KERNEL); rtnl_unlock(); if (err) -- GitLab From 38e6bc185d9544dfad1774b3f8902a0b061aea25 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:38 +0000 Subject: [PATCH 5416/5711] netpoll: make __netpoll_cleanup non-block Like the previous patch, slave_disable_netpoll() and __netpoll_cleanup() may be called with read_lock() held too, so we should make them non-block, by moving the cleanup and kfree() to call_rcu_bh() callbacks. Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 +--- include/linux/netpoll.h | 3 +++ net/8021q/vlan_dev.c | 6 +---- net/bridge/br_device.c | 6 +---- net/core/netpoll.c | 42 +++++++++++++++++++++++++-------- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8697136e27c0..e42891683e3b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1257,9 +1257,7 @@ static inline void slave_disable_netpoll(struct slave *slave) return; slave->np = NULL; - synchronize_rcu_bh(); - __netpoll_cleanup(np); - kfree(np); + __netpoll_free_rcu(np); } static inline bool slave_dev_support_netpoll(struct net_device *slave_dev) { diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index bf2d51eec0f3..907812efb4d9 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -23,6 +23,7 @@ struct netpoll { u8 remote_mac[ETH_ALEN]; struct list_head rx; /* rx_np list element */ + struct rcu_head rcu; }; struct netpoll_info { @@ -38,6 +39,7 @@ struct netpoll_info { struct delayed_work tx_work; struct netpoll *netpoll; + struct rcu_head rcu; }; void netpoll_send_udp(struct netpoll *np, const char *msg, int len); @@ -48,6 +50,7 @@ int netpoll_setup(struct netpoll *np); int netpoll_trap(void); void netpoll_set_trap(int trap); void __netpoll_cleanup(struct netpoll *np); +void __netpoll_free_rcu(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); int __netpoll_rx(struct sk_buff *skb); void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ee4ae0944cef..b65623f90660 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -704,11 +704,7 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev) info->netpoll = NULL; - /* Wait for transmitting packets to finish before freeing. */ - synchronize_rcu_bh(); - - __netpoll_cleanup(netpoll); - kfree(netpoll); + __netpoll_free_rcu(netpoll); } #endif /* CONFIG_NET_POLL_CONTROLLER */ diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ed0e0f9dc788..f41ba4048c9a 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p) p->np = NULL; - /* Wait for transmitting packets to finish before freeing. */ - synchronize_rcu_bh(); - - __netpoll_cleanup(np); - kfree(np); + __netpoll_free_rcu(np); } #endif diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 37cc854774a4..dc17f1db1479 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -878,6 +878,24 @@ static int __init netpoll_init(void) } core_initcall(netpoll_init); +static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) +{ + struct netpoll_info *npinfo = + container_of(rcu_head, struct netpoll_info, rcu); + + skb_queue_purge(&npinfo->arp_tx); + skb_queue_purge(&npinfo->txq); + + /* we can't call cancel_delayed_work_sync here, as we are in softirq */ + cancel_delayed_work(&npinfo->tx_work); + + /* clean after last, unfinished work */ + __skb_queue_purge(&npinfo->txq); + /* now cancel it again */ + cancel_delayed_work(&npinfo->tx_work); + kfree(npinfo); +} + void __netpoll_cleanup(struct netpoll *np) { struct netpoll_info *npinfo; @@ -903,20 +921,24 @@ void __netpoll_cleanup(struct netpoll *np) ops->ndo_netpoll_cleanup(np->dev); RCU_INIT_POINTER(np->dev->npinfo, NULL); + call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); + } +} +EXPORT_SYMBOL_GPL(__netpoll_cleanup); - /* avoid racing with NAPI reading npinfo */ - synchronize_rcu_bh(); +static void rcu_cleanup_netpoll(struct rcu_head *rcu_head) +{ + struct netpoll *np = container_of(rcu_head, struct netpoll, rcu); - skb_queue_purge(&npinfo->arp_tx); - skb_queue_purge(&npinfo->txq); - cancel_delayed_work_sync(&npinfo->tx_work); + __netpoll_cleanup(np); + kfree(np); +} - /* clean after last, unfinished work */ - __skb_queue_purge(&npinfo->txq); - kfree(npinfo); - } +void __netpoll_free_rcu(struct netpoll *np) +{ + call_rcu_bh(&np->rcu, rcu_cleanup_netpoll); } -EXPORT_SYMBOL_GPL(__netpoll_cleanup); +EXPORT_SYMBOL_GPL(__netpoll_free_rcu); void netpoll_cleanup(struct netpoll *np) { -- GitLab From 3335f0ca130c201f8680e97f63612053fbc16e22 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:39 +0000 Subject: [PATCH 5417/5711] netconsole: do not release spin_lock when calling __netpoll_cleanup With the previous patch applied, __netpoll_cleanup() is non-block now, so we don't need to release the spin_lock before calling it. Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f9347ea3d381..f0ad56c13933 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -640,12 +640,7 @@ static int netconsole_netdev_event(struct notifier_block *this, * rtnl_lock already held */ if (nt->np.dev) { - spin_unlock_irqrestore( - &target_list_lock, - flags); __netpoll_cleanup(&nt->np); - spin_lock_irqsave(&target_list_lock, - flags); dev_put(nt->np.dev); nt->np.dev = NULL; netconsole_target_put(nt); -- GitLab From 57c5d46191e75312934c00eba65b13a31ca95120 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:40 +0000 Subject: [PATCH 5418/5711] netpoll: take rcu_read_lock_bh() in netpoll_rx() In __netpoll_rx(), it dereferences ->npinfo without rcu_dereference_bh(), this patch fixes it by using the 'npinfo' passed from netpoll_rx() where it is already dereferenced with rcu_dereference_bh(). Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/netpoll.h | 4 ++-- net/core/netpoll.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 907812efb4d9..5d881c388273 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -52,7 +52,7 @@ void netpoll_set_trap(int trap); void __netpoll_cleanup(struct netpoll *np); void __netpoll_free_rcu(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); -int __netpoll_rx(struct sk_buff *skb); +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo); void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev); static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) @@ -77,7 +77,7 @@ static inline bool netpoll_rx(struct sk_buff *skb) spin_lock(&npinfo->rx_lock); /* check rx_flags again with the lock held */ - if (npinfo->rx_flags && __netpoll_rx(skb)) + if (npinfo->rx_flags && __netpoll_rx(skb, npinfo)) ret = true; spin_unlock(&npinfo->rx_lock); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index dc17f1db1479..d055bb01328b 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -543,13 +543,12 @@ static void arp_reply(struct sk_buff *skb) spin_unlock_irqrestore(&npinfo->rx_lock, flags); } -int __netpoll_rx(struct sk_buff *skb) +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) { int proto, len, ulen; int hits = 0; const struct iphdr *iph; struct udphdr *uh; - struct netpoll_info *npinfo = skb->dev->npinfo; struct netpoll *np, *tmp; if (list_empty(&npinfo->rx_np)) -- GitLab From 91fe4a4b9e490a24f6702dd8afe72d8afab6fcdb Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:41 +0000 Subject: [PATCH 5419/5711] netpoll: use netpoll_rx_on() in netpoll_rx() The logic of the code is same, just call netpoll_rx_on(). Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/netpoll.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 5d881c388273..2d178baa49df 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -63,6 +63,13 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) #ifdef CONFIG_NETPOLL +static inline int netpoll_rx_on(struct sk_buff *skb) +{ + struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); + + return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); +} + static inline bool netpoll_rx(struct sk_buff *skb) { struct netpoll_info *npinfo; @@ -70,11 +77,11 @@ static inline bool netpoll_rx(struct sk_buff *skb) bool ret = false; local_irq_save(flags); - npinfo = rcu_dereference_bh(skb->dev->npinfo); - if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) + if (!netpoll_rx_on(skb)) goto out; + npinfo = rcu_dereference_bh(skb->dev->npinfo); spin_lock(&npinfo->rx_lock); /* check rx_flags again with the lock held */ if (npinfo->rx_flags && __netpoll_rx(skb, npinfo)) @@ -86,13 +93,6 @@ out: return ret; } -static inline int netpoll_rx_on(struct sk_buff *skb) -{ - struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - - return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); -} - static inline int netpoll_receive_skb(struct sk_buff *skb) { if (!list_empty(&skb->dev->napi_list)) -- GitLab From 2899656b494dcd118123af1126826b115c8ea6f9 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:42 +0000 Subject: [PATCH 5420/5711] netpoll: take rcu_read_lock_bh() in netpoll_send_skb_on_dev() This patch fixes several problems in the call path of netpoll_send_skb_on_dev(): 1. Disable IRQ's before calling netpoll_send_skb_on_dev(). 2. All the callees of netpoll_send_skb_on_dev() should use rcu_dereference_bh() to dereference ->npinfo. 3. Rename arp_reply() to netpoll_arp_reply(), the former is too generic. Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/netpoll.h | 3 +++ net/core/netpoll.c | 31 +++++++++++++++++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 2d178baa49df..61aee86cf21d 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -57,7 +57,10 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev); static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { + unsigned long flags; + local_irq_save(flags); netpoll_send_skb_on_dev(np, skb, np->dev); + local_irq_restore(flags); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index d055bb01328b..174346ac15a0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -54,7 +54,7 @@ static atomic_t trapped; MAX_UDP_CHUNK) static void zap_completion_queue(void); -static void arp_reply(struct sk_buff *skb); +static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo); static unsigned int carrier_timeout = 4; module_param(carrier_timeout, uint, 0644); @@ -170,7 +170,8 @@ static void poll_napi(struct net_device *dev) list_for_each_entry(napi, &dev->napi_list, dev_list) { if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - budget = poll_one_napi(dev->npinfo, napi, budget); + budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), + napi, budget); spin_unlock(&napi->poll_lock); if (!budget) @@ -185,13 +186,14 @@ static void service_arp_queue(struct netpoll_info *npi) struct sk_buff *skb; while ((skb = skb_dequeue(&npi->arp_tx))) - arp_reply(skb); + netpoll_arp_reply(skb, npi); } } static void netpoll_poll_dev(struct net_device *dev) { const struct net_device_ops *ops; + struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); if (!dev || !netif_running(dev)) return; @@ -206,17 +208,18 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev); if (dev->flags & IFF_SLAVE) { - if (dev->npinfo) { + if (ni) { struct net_device *bond_dev = dev->master; struct sk_buff *skb; - while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) { + struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo); + while ((skb = skb_dequeue(&ni->arp_tx))) { skb->dev = bond_dev; - skb_queue_tail(&bond_dev->npinfo->arp_tx, skb); + skb_queue_tail(&bond_ni->arp_tx, skb); } } } - service_arp_queue(dev->npinfo); + service_arp_queue(ni); zap_completion_queue(); } @@ -302,6 +305,7 @@ static int netpoll_owner_active(struct net_device *dev) return 0; } +/* call with IRQ disabled */ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev) { @@ -309,8 +313,11 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, unsigned long tries; const struct net_device_ops *ops = dev->netdev_ops; /* It is up to the caller to keep npinfo alive. */ - struct netpoll_info *npinfo = np->dev->npinfo; + struct netpoll_info *npinfo; + + WARN_ON_ONCE(!irqs_disabled()); + npinfo = rcu_dereference_bh(np->dev->npinfo); if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { __kfree_skb(skb); return; @@ -319,11 +326,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, /* don't get messages out of order, and no recursion */ if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) { struct netdev_queue *txq; - unsigned long flags; txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); - local_irq_save(flags); /* try until next clock tick */ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { @@ -347,10 +352,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, } WARN_ONCE(!irqs_disabled(), - "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n", + "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", dev->name, ops->ndo_start_xmit); - local_irq_restore(flags); } if (status != NETDEV_TX_OK) { @@ -423,9 +427,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) } EXPORT_SYMBOL(netpoll_send_udp); -static void arp_reply(struct sk_buff *skb) +static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo) { - struct netpoll_info *npinfo = skb->dev->npinfo; struct arphdr *arp; unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; -- GitLab From d30362c0712eb567334b3b66de7c40d4372f2c6f Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:43 +0000 Subject: [PATCH 5421/5711] bridge: add some comments for NETDEV_RELEASE Add comments on why we don't notify NETDEV_RELEASE. Cc: David Miller Cc: Stephen Hemminger Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_if.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 171fd6b9bfe6..1c8fdc3558cd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -427,6 +427,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) if (!p || p->br != br) return -EINVAL; + /* Since more than one interface can be attached to a bridge, + * there still maybe an alternate path for netconsole to use; + * therefore there is no reason for a NETDEV_RELEASE event. + */ del_nbp(p); spin_lock_bh(&br->lock); -- GitLab From 4e3828c4bfd90b00a951cad7c8da27d1966beefe Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:44 +0000 Subject: [PATCH 5422/5711] bridge: use list_for_each_entry() in netpoll functions We don't delete 'p' from the list in the loop, so we can just use list_for_each_entry(). Cc: David Miller Cc: Stephen Hemminger Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index f41ba4048c9a..32211fa5b506 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -206,21 +206,20 @@ static void br_poll_controller(struct net_device *br_dev) static void br_netpoll_cleanup(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); - struct net_bridge_port *p, *n; + struct net_bridge_port *p; - list_for_each_entry_safe(p, n, &br->port_list, list) { + list_for_each_entry(p, &br->port_list, list) br_netpoll_disable(p); - } } static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) { struct net_bridge *br = netdev_priv(dev); - struct net_bridge_port *p, *n; + struct net_bridge_port *p; int err = 0; - list_for_each_entry_safe(p, n, &br->port_list, list) { + list_for_each_entry(p, &br->port_list, list) { if (!p->dev) continue; err = br_netpoll_enable(p, gfp); -- GitLab From e15c3c2294605f09f9b336b2f3b97086ab4b8145 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:45 +0000 Subject: [PATCH 5423/5711] netpoll: check netpoll tx status on the right device Although this doesn't matter actually, because netpoll_tx_running() doesn't use the parameter, the code will be more readable. For team_dev_queue_xmit() we have to move it down to avoid compile errors. Cc: David Miller Signed-off-by: Jiri Pirko Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- include/linux/if_team.h | 30 +++++++++++++++--------------- net/bridge/br_forward.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e42891683e3b..d688a8af432c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -398,7 +398,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping; - if (unlikely(netpoll_tx_running(slave_dev))) + if (unlikely(netpoll_tx_running(bond->dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); else dev_queue_xmit(skb); diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 6960fc1841a7..aa2e167e1ef4 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -96,21 +96,6 @@ static inline void team_netpoll_send_skb(struct team_port *port, } #endif -static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, - struct sk_buff *skb) -{ - BUILD_BUG_ON(sizeof(skb->queue_mapping) != - sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); - skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); - - skb->dev = port->dev; - if (unlikely(netpoll_tx_running(port->dev))) { - team_netpoll_send_skb(port, skb); - return 0; - } - return dev_queue_xmit(skb); -} - struct team_mode_ops { int (*init)(struct team *team); void (*exit)(struct team *team); @@ -200,6 +185,21 @@ struct team { long mode_priv[TEAM_MODE_PRIV_LONGS]; }; +static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, + struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(skb->queue_mapping) != + sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); + skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); + + skb->dev = port->dev; + if (unlikely(netpoll_tx_running(team->dev))) { + team_netpoll_send_skb(port, skb); + return 0; + } + return dev_queue_xmit(skb); +} + static inline struct hlist_head *team_port_index_hash(struct team *team, int port_index) { diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index e9466d412707..02015a505d2a 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -65,7 +65,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) { skb->dev = to->dev; - if (unlikely(netpoll_tx_running(to->dev))) { + if (unlikely(netpoll_tx_running(to->br->dev))) { if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) kfree_skb(skb); else { -- GitLab From 77ab8a54d9a8dcc4a46484a04133314f33f2aba6 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:46 +0000 Subject: [PATCH 5424/5711] netpoll: convert several functions to bool These functions are just boolean, let them return bool instead of int. Cc: David Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/netpoll.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 61aee86cf21d..66d5379c305e 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -66,7 +66,7 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) #ifdef CONFIG_NETPOLL -static inline int netpoll_rx_on(struct sk_buff *skb) +static inline bool netpoll_rx_on(struct sk_buff *skb) { struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); @@ -125,7 +125,7 @@ static inline void netpoll_poll_unlock(void *have) } } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev) { return irqs_disabled(); } @@ -133,11 +133,11 @@ static inline int netpoll_tx_running(struct net_device *dev) #else static inline bool netpoll_rx(struct sk_buff *skb) { - return 0; + return false; } -static inline int netpoll_rx_on(struct sk_buff *skb) +static inline bool netpoll_rx_on(struct sk_buff *skb) { - return 0; + return false; } static inline int netpoll_receive_skb(struct sk_buff *skb) { @@ -153,9 +153,9 @@ static inline void netpoll_poll_unlock(void *have) static inline void netpoll_netdev_init(struct net_device *dev) { } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev) { - return 0; + return false; } #endif -- GitLab From f3da38932b46d1bf171634cc7aae3da405eaf7a6 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:47 +0000 Subject: [PATCH 5425/5711] vlan: clean up some variable names To be consistent, s/info/vlan/. Cc: Benjamin LaHaise Cc: Patrick McHardy Cc: David Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b65623f90660..0347d48aa7c9 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -672,8 +672,8 @@ static void vlan_dev_poll_controller(struct net_device *dev) static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, gfp_t gfp) { - struct vlan_dev_priv *info = vlan_dev_priv(dev); - struct net_device *real_dev = info->real_dev; + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct net_device *real_dev = vlan->real_dev; struct netpoll *netpoll; int err = 0; @@ -688,7 +688,7 @@ static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *n goto out; } - info->netpoll = netpoll; + vlan->netpoll = netpoll; out: return err; @@ -696,13 +696,13 @@ out: static void vlan_dev_netpoll_cleanup(struct net_device *dev) { - struct vlan_dev_priv *info = vlan_dev_priv(dev); - struct netpoll *netpoll = info->netpoll; + struct vlan_dev_priv *vlan= vlan_dev_priv(dev); + struct netpoll *netpoll = vlan->netpoll; if (!netpoll) return; - info->netpoll = NULL; + vlan->netpoll = NULL; __netpoll_free_rcu(netpoll); } -- GitLab From 6eacf8ad8d01c49b95b994b0bf379db2b5b29460 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:48 +0000 Subject: [PATCH 5426/5711] vlan: clean up vlan_dev_hard_start_xmit() Clean up vlan_dev_hard_start_xmit() function. Cc: Benjamin LaHaise Cc: Patrick McHardy Cc: David Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 0347d48aa7c9..402442402af7 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -137,9 +137,21 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, return rc; } +static inline netdev_tx_t vlan_netpoll_send_skb(struct vlan_dev_priv *vlan, struct sk_buff *skb) +{ +#ifdef CONFIG_NET_POLL_CONTROLLER + if (vlan->netpoll) + netpoll_send_skb(vlan->netpoll, skb); +#else + BUG(); +#endif + return NETDEV_TX_OK; +} + static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); unsigned int len; int ret; @@ -150,29 +162,30 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if (veth->h_vlan_proto != htons(ETH_P_8021Q) || - vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR) { + vlan->flags & VLAN_FLAG_REORDER_HDR) { u16 vlan_tci; - vlan_tci = vlan_dev_priv(dev)->vlan_id; + vlan_tci = vlan->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); } - skb->dev = vlan_dev_priv(dev)->real_dev; + skb->dev = vlan->real_dev; len = skb->len; - if (netpoll_tx_running(dev)) - return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); + if (unlikely(netpoll_tx_running(dev))) + return vlan_netpoll_send_skb(vlan, skb); + ret = dev_queue_xmit(skb); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { struct vlan_pcpu_stats *stats; - stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); + stats = this_cpu_ptr(vlan->vlan_pcpu_stats); u64_stats_update_begin(&stats->syncp); stats->tx_packets++; stats->tx_bytes += len; u64_stats_update_end(&stats->syncp); } else { - this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); + this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped); } return ret; -- GitLab From 689971b44613883ee74ae9c1b31a864aaa3a8e17 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:49 +0000 Subject: [PATCH 5427/5711] netpoll: handle vlan tags in netpoll tx and rx path Without this patch, I can't get netconsole logs remotely over vlan. The reason is probably we don't handle vlan tags in either netpoll tx or rx path. I am not sure if I use these vlan functions correctly, at least this patch works. Cc: Benjamin LaHaise Cc: Patrick McHardy Cc: David Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/core/netpoll.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 174346ac15a0..e4ba3e70c174 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -334,6 +335,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, tries > 0; --tries) { if (__netif_tx_trylock(txq)) { if (!netif_xmit_stopped(txq)) { + if (vlan_tx_tag_present(skb) && + !(netif_skb_features(skb) & NETIF_F_HW_VLAN_TX)) { + skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb)); + if (unlikely(!skb)) + break; + skb->vlan_tci = 0; + } + status = ops->ndo_start_xmit(skb, dev); if (status == NETDEV_TX_OK) txq_trans_update(txq); @@ -567,6 +576,12 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) return 1; } + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { + skb = vlan_untag(skb); + if (unlikely(!skb)) + goto out; + } + proto = ntohs(eth_hdr(skb)->h_proto); if (proto != ETH_P_IP) goto out; -- GitLab From 6bdb7fe31046ac50b47e83c35cd6c6b6160a475d Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 10 Aug 2012 01:24:50 +0000 Subject: [PATCH 5428/5711] netpoll: re-enable irq in poll_napi() napi->poll() needs IRQ enabled, so we have to re-enable IRQ before calling it. Cc: David Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/core/netpoll.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e4ba3e70c174..346b1eb83a1f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -168,16 +168,24 @@ static void poll_napi(struct net_device *dev) struct napi_struct *napi; int budget = 16; + WARN_ON_ONCE(!irqs_disabled()); + list_for_each_entry(napi, &dev->napi_list, dev_list) { + local_irq_enable(); if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { + rcu_read_lock_bh(); budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), napi, budget); + rcu_read_unlock_bh(); spin_unlock(&napi->poll_lock); - if (!budget) + if (!budget) { + local_irq_disable(); break; + } } + local_irq_disable(); } } -- GitLab From 6556bfde65b1d4bea29eb2e1566398676792eaaa Mon Sep 17 00:00:00 2001 From: Dirk Gouders Date: Fri, 10 Aug 2012 01:24:51 +0000 Subject: [PATCH 5429/5711] netconsole.txt: revision of examples for the receiver of kernel messages There are at least 4 implementations of netcat with the BSD-based being the only one that has to be used without the -p switch to specify the listening port. Jan Engelhardt suggested to add an example for socat(1). Signed-off-by: Dirk Gouders Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- Documentation/networking/netconsole.txt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt index 8d022073e3ef..2e9e0ae2cd45 100644 --- a/Documentation/networking/netconsole.txt +++ b/Documentation/networking/netconsole.txt @@ -51,8 +51,23 @@ Built-in netconsole starts immediately after the TCP stack is initialized and attempts to bring up the supplied dev at the supplied address. -The remote host can run either 'netcat -u -l -p ', -'nc -l -u ' or syslogd. +The remote host has several options to receive the kernel messages, +for example: + +1) syslogd + +2) netcat + + On distributions using a BSD-based netcat version (e.g. Fedora, + openSUSE and Ubuntu) the listening port must be specified without + the -p switch: + + 'nc -u -l -p ' / 'nc -u -l ' or + 'netcat -u -l -p ' / 'netcat -u -l ' + +3) socat + + 'socat udp-recv: -' Dynamic reconfiguration: ======================== -- GitLab From 03304bcb5ec4421c0d272d7f8d688804d82b1efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 12 Aug 2012 09:16:30 +0000 Subject: [PATCH 5430/5711] net: qmi_wwan: use fixed interface number matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver support many composite USB devices where the interface class/subclass/protocol provides no information about the interface function. Interfaces with different functions may all use ff/ff/ff, like this example of a device with three serial interfaces and three QMI/wwan interfaces: T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#=116 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1199 ProdID=68a2 Rev= 0.06 S: Manufacturer=Sierra Wireless, Incorporated S: Product=MC7710 S: SerialNumber=3581780xxxxxx C:* #Ifs= 6 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 8 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=19 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=20 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms Instead of class/subclass/protocol the vendor use fixed interface numbers for each function, and the Windows drivers use these numbers to match driver and function. The driver has had its own interface number whitelisting code to simulate this functionality. Replace this with generic interface number matching now that the USB subsystem support is there. This - removes the need for a driver_info structure per interface number, - avoids running the probe function for unsupported interfaces, and - simplifies the code. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 215 +++++-------------------------------- 1 file changed, 28 insertions(+), 187 deletions(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2ea126a16d79..c6a587366a57 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -247,30 +247,12 @@ err: */ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) { - int rv; struct qmi_wwan_state *info = (void *)&dev->data; - /* ZTE makes devices where the interface descriptors and endpoint - * configurations of two or more interfaces are identical, even - * though the functions are completely different. If set, then - * driver_info->data is a bitmap of acceptable interface numbers - * allowing us to bind to one such interface without binding to - * all of them - */ - if (dev->driver_info->data && - !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) { - dev_info(&intf->dev, "not on our whitelist - ignored"); - rv = -ENODEV; - goto err; - } - /* control and data is shared */ info->control = intf; info->data = intf; - rv = qmi_wwan_register_subdriver(dev); - -err: - return rv; + return qmi_wwan_register_subdriver(dev); } static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) @@ -356,86 +338,23 @@ static const struct driver_info qmi_wwan_shared = { .manage_power = qmi_wwan_manage_power, }; -static const struct driver_info qmi_wwan_force_int0 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(0), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int1 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(1), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int2 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(2), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int3 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(3), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int4 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(4), /* interface whitelist bitmap */ -}; - -/* Sierra Wireless provide equally useless interface descriptors - * Devices in QMI mode can be switched between two different - * configurations: - * a) USB interface #8 is QMI/wwan - * b) USB interfaces #8, #19 and #20 are QMI/wwan - * - * Both configurations provide a number of other interfaces (serial++), - * some of which have the same endpoint configuration as we expect, so - * a whitelist or blacklist is necessary. - * - * FIXME: The below whitelist should include BIT(20). It does not - * because I cannot get it to work... - */ -static const struct driver_info qmi_wwan_sierra = { - .description = "Sierra Wireless wwan/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ -}; - #define HUAWEI_VENDOR_ID 0x12D1 +/* map QMI/wwan function by a fixed interface number */ +#define QMI_FIXED_INTF(vend, prod, num) \ + USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ + .driver_info = (unsigned long)&qmi_wwan_shared + /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ #define QMI_GOBI1K_DEVICE(vend, prod) \ - USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long)&qmi_wwan_force_int3 + QMI_FIXED_INTF(vend, prod, 3) -/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ +/* Gobi 2000/3000 QMI/wwan interface number is 0 according to qcserial */ #define QMI_GOBI_DEVICE(vend, prod) \ - USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long)&qmi_wwan_force_int0 + QMI_FIXED_INTF(vend, prod, 0) static const struct usb_device_id products[] = { + /* 1. CDC ECM like devices match on the control interface */ { /* Huawei E392, E398 and possibly others sharing both device id and more... */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = HUAWEI_VENDOR_ID, @@ -452,10 +371,9 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */ .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Huawei E392, E398 and possibly others in "Windows mode" - * using a combined control and data interface without any CDC - * functional descriptors - */ + + /* 2. Combined interface devices matching on class+protocol */ + { /* Huawei E392, E398 and possibly others in "Windows mode" */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = HUAWEI_VENDOR_ID, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, @@ -472,98 +390,21 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_shared, }, - { /* ZTE MF820D */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0167, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE MF821D */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0326, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3520-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0055, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int1, - }, - { /* ZTE (Vodafone) K3565-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0063, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3570-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1008, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3571-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1010, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3765-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x2002, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K4505-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0104, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE MF60 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1402, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int2, - }, - { /* Sierra Wireless MC77xx in QMI mode */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x1199, - .idProduct = 0x68a2, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_sierra, - }, - /* Gobi 1000 devices */ + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ + {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ + {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ + {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ + + /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ @@ -579,7 +420,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - /* Gobi 2000 and 3000 devices */ + /* 5. Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ -- GitLab From 9b469a60d68b13c288d5c3fc23de29d9d482dbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 12 Aug 2012 09:16:31 +0000 Subject: [PATCH 5431/5711] net: qmi_wwan: add Sierra Wireless devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 6 new devices and one modified device, based on information from laptop vendor Windows drivers. Sony provides a driver with two new devices using a Gobi 2k+ layout (1199:68a5 and 1199:68a9). The Sony driver also adds a non-standard QMI/net interface to the already supported 1199:9011 Gobi device. We do not know whether this is an alternate interface number or an additional interface which might be present, but that doesn't really matter. Lenovo provides a driver supporting 4 new devices: - MC7770 (1199:901b) with standard Gobi 2k+ layout - MC7700 (0f3d:68a2) with layout similar to MC7710 - MC7750 (114f:68a2) with layout similar to MC7710 - EM7700 (1199:901c) with layout similar to MC7710 Note regaring the three devices similar to MC7710: The Windows drivers only support interface #8 on these devices. The MC7710 can support QMI/net functions on interface #19 and #20 as well, and this driver is verified to work on interface #19 (a firmware bug is suspected to prevent #20 from working). We do not enable these additional interfaces until they either show up in a Windows driver or are verified to work in some other way. Therefore limiting the new devices to interface #8 for now. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index c6a587366a57..24524b24329b 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -401,8 +401,11 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ + {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ @@ -430,6 +433,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ + {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -441,11 +446,14 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ + {QMI_FIXED_INTF(0x1199, 0x9011, 5)}, /* alternate interface number!? */ {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); -- GitLab From 5ea429638fbd9f18e6837e3e83a1f517741ec43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 12 Aug 2012 09:16:32 +0000 Subject: [PATCH 5432/5711] net: qmi_wwan: compress device_id list using macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Take advantage of the matching macros to make the device id list easier to read and maintain. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 24524b24329b..aaa061b7355d 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -356,38 +356,21 @@ static const struct driver_info qmi_wwan_shared = { static const struct usb_device_id products[] = { /* 1. CDC ECM like devices match on the control interface */ { /* Huawei E392, E398 and possibly others sharing both device id and more... */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 9, /* CDC Ethernet *control* interface */ + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9), .driver_info = (unsigned long)&qmi_wwan_info, }, { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */ + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), .driver_info = (unsigned long)&qmi_wwan_info, }, /* 2. Combined interface devices matching on class+protocol */ { /* Huawei E392, E398 and possibly others in "Windows mode" */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 17, + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), .driver_info = (unsigned long)&qmi_wwan_shared, }, { /* Pantech UML290 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x106c, - .idProduct = 0x3718, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xf0, - .bInterfaceProtocol = 0xff, + USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), .driver_info = (unsigned long)&qmi_wwan_shared, }, -- GitLab From aefe5c0060639914cce7ed4947f2c030f615bebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 12 Aug 2012 09:53:38 +0000 Subject: [PATCH 5433/5711] net: sierra_net: replace whitelist with ifnumber match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/sierra_net.c | 52 +++++++++--------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index d75d1f56becf..7be49ea60b6d 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -68,15 +68,8 @@ static atomic_t iface_counter = ATOMIC_INIT(0); */ #define SIERRA_NET_USBCTL_BUF_LEN 1024 -/* list of interface numbers - used for constructing interface lists */ -struct sierra_net_iface_info { - const u32 infolen; /* number of interface numbers on list */ - const u8 *ifaceinfo; /* pointer to the array holding the numbers */ -}; - struct sierra_net_info_data { u16 rx_urb_size; - struct sierra_net_iface_info whitelist; }; /* Private data structure */ @@ -637,21 +630,6 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu) return usbnet_change_mtu(net, new_mtu); } -static int is_whitelisted(const u8 ifnum, - const struct sierra_net_iface_info *whitelist) -{ - if (whitelist) { - const u8 *list = whitelist->ifaceinfo; - int i; - - for (i = 0; i < whitelist->infolen; i++) { - if (list[i] == ifnum) - return 1; - } - } - return 0; -} - static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) { int result = 0; @@ -706,11 +684,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev_dbg(&dev->udev->dev, "%s", __func__); ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; - /* We only accept certain interfaces */ - if (!is_whitelisted(ifacenum, &data->whitelist)) { - dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); - return -ENODEV; - } numendpoints = intf->cur_altsetting->desc.bNumEndpoints; /* We have three endpoints, bulk in and out, and a status */ if (numendpoints != 3) { @@ -945,13 +918,8 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, return NULL; } -static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, - .whitelist = { - .infolen = ARRAY_SIZE(sierra_net_ifnum_list), - .ifaceinfo = sierra_net_ifnum_list - } }; static const struct driver_info sierra_net_info_direct_ip = { @@ -965,15 +933,19 @@ static const struct driver_info sierra_net_info_direct_ip = { .data = (unsigned long)&sierra_net_info_data_direct_ip, }; +#define DIRECT_IP_DEVICE(vend, prod) \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 10), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 11), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip} + static const struct usb_device_id products[] = { - {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + DIRECT_IP_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ + DIRECT_IP_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + DIRECT_IP_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + DIRECT_IP_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ {}, /* last item */ }; -- GitLab From 7bd86cc282a458b66c41e3f6676de6656c99b8db Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Sun, 12 Aug 2012 20:09:59 +0000 Subject: [PATCH 5434/5711] ipv4: Cache local output routes Commit caacf05e5ad1abf causes big drop of UDP loop back performance. The cause of the regression is that we do not cache the local output routes. Each time we send a datagram from unconnected UDP socket, the kernel allocates a dst_entry and adds it to the rt_uncached_list. It creates lock contention on the rt_uncached_lock. Reported-by: Alex Shi Signed-off-by: Yan, Zheng Signed-off-by: David S. Miller --- net/ipv4/route.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e4ba974f143c..fd9ecb52c66b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2028,7 +2028,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) } dev_out = net->loopback_dev; fl4->flowi4_oif = dev_out->ifindex; - res.fi = NULL; flags |= RTCF_LOCAL; goto make_route; } -- GitLab From 4855d6f3116e891b66198838b683dce3dcf6e874 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Sun, 12 Aug 2012 22:31:58 +0000 Subject: [PATCH 5435/5711] net: ipv6: proc: Fix error handling Fix error handling in case making of dir dev_snmp6 failes Signed-off-by: Igor Maravic Signed-off-by: David S. Miller --- net/ipv6/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index da2e92d05c15..745a32042950 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net) goto proc_dev_snmp6_fail; return 0; +proc_dev_snmp6_fail: + proc_net_remove(net, "snmp6"); proc_snmp6_fail: proc_net_remove(net, "sockstat6"); -proc_dev_snmp6_fail: - proc_net_remove(net, "dev_snmp6"); return -ENOMEM; } -- GitLab From fa16ebed31f336e41970f3f0ea9e8279f6be2d27 Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Mon, 13 Aug 2012 14:39:49 +0000 Subject: [PATCH 5436/5711] IB/ipoib: Add missing locking when CM object is deleted Commit b63b70d87741 ("IPoIB: Use a private hash table for path lookup in xmit path") introduced a bug where in ipoib_cm_destroy_tx() a CM object is moved between lists without any supported locking. Under a stress test, this eventually leads to list corruption and a crash. Previously when this routine was called, callers were taking the device priv lock. Currently this function is called from the RCU callback associated with neighbour deletion. Fix the race by taking the same lock we used to before. Signed-off-by: Shlomo Pongratz Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 95ecf4eadf5f..24683fda8e21 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1271,12 +1271,15 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx) { struct ipoib_dev_priv *priv = netdev_priv(tx->dev); + unsigned long flags; if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { + spin_lock_irqsave(&priv->lock, flags); list_move(&tx->list, &priv->cm.reap_list); queue_work(ipoib_workqueue, &priv->cm.reap_task); ipoib_dbg(priv, "Reap connection for gid %pI6\n", tx->neigh->daddr + 4); tx->neigh = NULL; + spin_unlock_irqrestore(&priv->lock, flags); } } -- GitLab From 6c723a68c661008adf415ee90efe5f737e928ce0 Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Mon, 13 Aug 2012 14:39:50 +0000 Subject: [PATCH 5437/5711] IB/ipoib: Fix RCU pointer dereference of wrong object Commit b63b70d87741 ("IPoIB: Use a private hash table for path lookup in xmit path") introduced a bug where in ipoib_neigh_free() (which is called from a few errors flows in the driver), rcu_dereference() is invoked with the wrong pointer object, which results in a crash. Signed-off-by: Shlomo Pongratz Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 97920b77a5d0..3e2085a3ee47 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1052,7 +1052,7 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh) for (n = rcu_dereference_protected(*np, lockdep_is_held(&ntbl->rwlock)); n != NULL; - n = rcu_dereference_protected(neigh->hnext, + n = rcu_dereference_protected(*np, lockdep_is_held(&ntbl->rwlock))) { if (n == neigh) { /* found */ -- GitLab From 6024935f5ff5f1646bce8404416318e5fd4a0c4a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 13 Aug 2012 02:49:59 +0000 Subject: [PATCH 5438/5711] llc2: Fix silent failure of llc_station_init() llc_station_init() creates and processes an event skb with no effect other than to change the state from DOWN to UP. Allocation failure is reported, but then ignored by its caller, llc2_init(). Remove this possibility by simply initialising the state as UP. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/net/llc.h | 2 +- net/llc/llc_station.c | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/include/net/llc.h b/include/net/llc.h index 226c846cab08..f2d0fc570527 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -133,7 +133,7 @@ extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_station_init(void); +extern void llc_station_init(void); extern void llc_station_exit(void); #ifdef CONFIG_PROC_FS diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 6828e39ec2ec..45ddbb93c5d0 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -687,12 +687,8 @@ static void llc_station_rcv(struct sk_buff *skb) llc_station_state_process(skb); } -int __init llc_station_init(void) +void __init llc_station_init(void) { - int rc = -ENOBUFS; - struct sk_buff *skb; - struct llc_station_state_ev *ev; - skb_queue_head_init(&llc_main_station.mac_pdu_q); skb_queue_head_init(&llc_main_station.ev_q.list); spin_lock_init(&llc_main_station.ev_q.lock); @@ -700,20 +696,9 @@ int __init llc_station_init(void) (unsigned long)&llc_main_station); llc_main_station.ack_timer.expires = jiffies + sysctl_llc_station_ack_timeout; - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) - goto out; - rc = 0; llc_set_station_handler(llc_station_rcv); - ev = llc_station_ev(skb); - memset(ev, 0, sizeof(*ev)); llc_main_station.maximum_retry = 1; - llc_main_station.state = LLC_STATION_STATE_DOWN; - ev->type = LLC_STATION_EV_TYPE_SIMPLE; - ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; - rc = llc_station_next_state(skb); -out: - return rc; + llc_main_station.state = LLC_STATION_STATE_UP; } void __exit llc_station_exit(void) -- GitLab From f4f8720febf0d785a054fc09bde5e3ad09728a58 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 13 Aug 2012 02:50:43 +0000 Subject: [PATCH 5439/5711] llc2: Call llc_station_exit() on llc2_init() failure path Otherwise the station packet handler will remain registered even though the module is unloaded. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/llc/af_llc.c | 5 +++-- net/llc/llc_station.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f6fe4d400502..8c2919ca36f6 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1206,7 +1206,7 @@ static int __init llc2_init(void) rc = llc_proc_init(); if (rc != 0) { printk(llc_proc_err_msg); - goto out_unregister_llc_proto; + goto out_station; } rc = llc_sysctl_init(); if (rc) { @@ -1226,7 +1226,8 @@ out_sysctl: llc_sysctl_exit(); out_proc: llc_proc_exit(); -out_unregister_llc_proto: +out_station: + llc_station_exit(); proto_unregister(&llc_proto); goto out; } diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 45ddbb93c5d0..bba5184fafd7 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -701,7 +701,7 @@ void __init llc_station_init(void) llc_main_station.state = LLC_STATION_STATE_UP; } -void __exit llc_station_exit(void) +void llc_station_exit(void) { llc_set_station_handler(NULL); } -- GitLab From aadf31de16a7b2878af00a02e6557df84efa784b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 13 Aug 2012 02:50:55 +0000 Subject: [PATCH 5440/5711] llc: Fix races between llc2 handler use and (un)registration When registering the handlers, any state they rely on must be completely initialised first. When unregistering, we must wait until they are definitely no longer running. llc_rcv() must also avoid reading the handler pointers again after checking for NULL. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/llc/llc_input.c | 21 +++++++++++++++++---- net/llc/llc_station.c | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index e32cab44ea95..dd3e83328ad5 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -42,6 +42,7 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap, void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, struct sk_buff *skb)) { + smp_wmb(); /* ensure initialisation is complete before it's called */ if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = handler; } @@ -50,11 +51,19 @@ void llc_remove_pack(int type) { if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = NULL; + synchronize_net(); } void llc_set_station_handler(void (*handler)(struct sk_buff *skb)) { + /* Ensure initialisation is complete before it's called */ + if (handler) + smp_wmb(); + llc_station_handler = handler; + + if (!handler) + synchronize_net(); } /** @@ -150,6 +159,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, int dest; int (*rcv)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); + void (*sta_handler)(struct sk_buff *skb); + void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); if (!net_eq(dev_net(dev), &init_net)) goto drop; @@ -182,7 +193,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, */ rcv = rcu_dereference(sap->rcv_func); dest = llc_pdu_type(skb); - if (unlikely(!dest || !llc_type_handlers[dest - 1])) { + sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL; + if (unlikely(!sap_handler)) { if (rcv) rcv(skb, dev, pt, orig_dev); else @@ -193,7 +205,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, if (cskb) rcv(cskb, dev, pt, orig_dev); } - llc_type_handlers[dest - 1](sap, skb); + sap_handler(sap, skb); } llc_sap_put(sap); out: @@ -202,9 +214,10 @@ drop: kfree_skb(skb); goto out; handle_station: - if (!llc_station_handler) + sta_handler = ACCESS_ONCE(llc_station_handler); + if (!sta_handler) goto drop; - llc_station_handler(skb); + sta_handler(skb); goto out; } diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index bba5184fafd7..b2f2bac2c2a2 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -696,9 +696,9 @@ void __init llc_station_init(void) (unsigned long)&llc_main_station); llc_main_station.ack_timer.expires = jiffies + sysctl_llc_station_ack_timeout; - llc_set_station_handler(llc_station_rcv); llc_main_station.maximum_retry = 1; llc_main_station.state = LLC_STATION_STATE_UP; + llc_set_station_handler(llc_station_rcv); } void llc_station_exit(void) -- GitLab From 80eb7a506fdcea08f86c9dfc7c638303bf02a3c8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 14 Aug 2012 11:29:17 +0100 Subject: [PATCH 5441/5711] staging: comedi: Fix reversed test in comedi_device_attach() Commit 3902a370281d2f2b130f141e8cf94eab40125769 (staging: comedi: refactor comedi_device_attach() a bit) by yours truly introduced an inverted logic bug in comedi_device_attach() for the case where the driver expects the device to be configured by driver name rather than board name. The result of a strcmp() is being tested incorrectly. Fix it. Thanks to Stephen N Chivers for discovering the bug and suggesting the fix. Cc: # 3.5.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index c0fdb00783ed..2359151af7e1 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -168,7 +168,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = comedi_recognize(driv, it->board_name); if (dev->board_ptr) break; - } else if (strcmp(driv->driver_name, it->board_name)) + } else if (strcmp(driv->driver_name, it->board_name) == 0) break; module_put(driv->module); } -- GitLab From 8607dcbefb9e1bcbefe2d77f74809cf31e6a04a1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Aug 2012 16:53:21 -0700 Subject: [PATCH 5442/5711] staging: csr: add INET dependancy Randy noticed that with CONFIG_INET turned off, the following build errors happen: ERROR: "register_inetaddr_notifier" [drivers/staging/csr/csr_wifi.ko] undefined! ERROR: "unregister_inetaddr_notifier" [drivers/staging/csr/csr_wifi.ko] undefined! Reported-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig index cee8d48d2af9..ad2a1096e920 100644 --- a/drivers/staging/csr/Kconfig +++ b/drivers/staging/csr/Kconfig @@ -1,6 +1,6 @@ config CSR_WIFI tristate "CSR wireless driver" - depends on MMC && CFG80211_WEXT + depends on MMC && CFG80211_WEXT && INET select WIRELESS_EXT select WEXT_PRIV help -- GitLab From f37c54b6a6c56489221d42ff27305e4f8098e34b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 05:49:47 +0000 Subject: [PATCH 5443/5711] drivers/net/ethernet/ti/davinci_cpdma.c: Remove potential NULL dereference If the NULL test is necessary, the initialization involving a dereference of the tested value should be moved after the NULL test. The sematic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ type T; expression E; identifier i,fld; statement S; @@ - T i = E->fld; + T i; ... when != E when != i if (E == NULL) S + i = E->fld; // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 3b5c4571b55e..d15c888e9df8 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -538,11 +538,12 @@ EXPORT_SYMBOL_GPL(cpdma_chan_create); int cpdma_chan_destroy(struct cpdma_chan *chan) { - struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_ctlr *ctlr; unsigned long flags; if (!chan) return -EINVAL; + ctlr = chan->ctlr; spin_lock_irqsave(&ctlr->lock, flags); if (chan->state != CPDMA_STATE_IDLE) -- GitLab From 137bc99ff30aa1d9bf556ee9c8ba788a8ec0f595 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 02:58:33 +0000 Subject: [PATCH 5444/5711] drivers/net/ethernet/freescale/fs_enet: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c | 4 +++- drivers/net/ethernet/freescale/fs_enet/mii-fec.c | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 0f2d1a710909..151453309401 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -174,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) + if (!new_bus->irq) { + ret = -ENOMEM; goto out_unmap_regs; + } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 55bb867258e6..cdf702a59485 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -137,8 +137,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start); fec->fecp = ioremap(res.start, resource_size(&res)); - if (!fec->fecp) + if (!fec->fecp) { + ret = -ENOMEM; goto out_fec; + } if (get_bus_freq) { clock = get_bus_freq(ofdev->dev.of_node); @@ -172,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) + if (!new_bus->irq) { + ret = -ENOMEM; goto out_unmap_regs; + } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); -- GitLab From 499b95f6b324ec49e8ff50000d47877445b8590a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 02:58:34 +0000 Subject: [PATCH 5445/5711] drivers/net/ethernet/mellanox/mlx4/mcg.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 4ec3835e1bc2..a018ea2a43de 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -432,8 +432,10 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { /* Entry already exists, add to duplicates */ dqp = kmalloc(sizeof *dqp, GFP_KERNEL); - if (!dqp) + if (!dqp) { + err = -ENOMEM; goto out_mailbox; + } dqp->qpn = qpn; list_add_tail(&dqp->list, &entry->duplicates); found = true; -- GitLab From 4acd4945cd1e1f92b20d14e349c6c6a52acbd42d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 14 Aug 2012 08:54:51 +0000 Subject: [PATCH 5446/5711] ipv6: addrconf: Avoid calling netdevice notifiers with RCU read-side lock Cong Wang reports that lockdep detected suspicious RCU usage while enabling IPV6 forwarding: [ 1123.310275] =============================== [ 1123.442202] [ INFO: suspicious RCU usage. ] [ 1123.558207] 3.6.0-rc1+ #109 Not tainted [ 1123.665204] ------------------------------- [ 1123.768254] include/linux/rcupdate.h:430 Illegal context switch in RCU read-side critical section! [ 1123.992320] [ 1123.992320] other info that might help us debug this: [ 1123.992320] [ 1124.307382] [ 1124.307382] rcu_scheduler_active = 1, debug_locks = 0 [ 1124.522220] 2 locks held by sysctl/5710: [ 1124.648364] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_trylock+0x15/0x17 [ 1124.882211] #1: (rcu_read_lock){.+.+.+}, at: [] rcu_lock_acquire+0x0/0x29 [ 1125.085209] [ 1125.085209] stack backtrace: [ 1125.332213] Pid: 5710, comm: sysctl Not tainted 3.6.0-rc1+ #109 [ 1125.441291] Call Trace: [ 1125.545281] [] lockdep_rcu_suspicious+0x109/0x112 [ 1125.667212] [] rcu_preempt_sleep_check+0x45/0x47 [ 1125.781838] [] __might_sleep+0x1e/0x19b [...] [ 1127.445223] [] call_netdevice_notifiers+0x4a/0x4f [...] [ 1127.772188] [] dev_disable_lro+0x32/0x6b [ 1127.885174] [] dev_forward_change+0x30/0xcb [ 1128.013214] [] addrconf_forward_change+0x85/0xc5 [...] addrconf_forward_change() uses RCU iteration over the netdev list, which is unnecessary since it already holds the RTNL lock. We also cannot reasonably require netdevice notifier functions not to sleep. Reported-by: Cong Wang Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 79181819a24f..6bc85f7c31e3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -494,8 +494,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf) struct net_device *dev; struct inet6_dev *idev; - rcu_read_lock(); - for_each_netdev_rcu(net, dev) { + for_each_netdev(net, dev) { idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.forwarding) ^ (!newf); @@ -504,7 +503,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf) dev_forward_change(idev); } } - rcu_read_unlock(); } static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) -- GitLab From 2856cc2e4d0852c3ddaae9dcb19cb9396512eb08 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 15 Aug 2012 00:37:29 -0700 Subject: [PATCH 5447/5711] sparc64: Be less verbose during vmemmap population. On a 2-node machine with 256GB of ram we get 512 lines of console output, which is just too much. This mimicks Yinghai Lu's x86 commit c2b91e2eec9678dbda274e906cc32ea8f711da3b (x86_64/mm: check and print vmemmap allocation continuous) except that we aren't ever going to get contiguous block pointers in between calls so just print when the virtual address or node changes. This decreases the output by an order of 16. Also demote this to KERN_DEBUG. Signed-off-by: David S. Miller --- arch/sparc/mm/init_64.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 6026fdd1b2ed..d58edf5fefdb 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2020,6 +2020,9 @@ EXPORT_SYMBOL(_PAGE_CACHE); #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long vmemmap_table[VMEMMAP_SIZE]; +static long __meminitdata addr_start, addr_end; +static int __meminitdata node_start; + int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) { unsigned long vstart = (unsigned long) start; @@ -2050,15 +2053,30 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) *vmem_pp = pte_base | __pa(block); - printk(KERN_INFO "[%p-%p] page_structs=%lu " - "node=%d entry=%lu/%lu\n", start, block, nr, - node, - addr >> VMEMMAP_CHUNK_SHIFT, - VMEMMAP_SIZE); + /* check to see if we have contiguous blocks */ + if (addr_end != addr || node_start != node) { + if (addr_start) + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = addr; + node_start = node; + } + addr_end = addr + VMEMMAP_CHUNK; } } return 0; } + +void __meminit vmemmap_populate_print_last(void) +{ + if (addr_start) { + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = 0; + addr_end = 0; + node_start = 0; + } +} #endif /* CONFIG_SPARSEMEM_VMEMMAP */ static void prot_init_common(unsigned long page_none, -- GitLab From 89868730a756feca7e4b21a97c86487cd565ed22 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 13 Aug 2012 19:57:31 +0100 Subject: [PATCH 5448/5711] ARM: 7490/1: Drop duplicate select for GENERIC_IRQ_PROBE Seems that Thomas' and my patches collided during the last merge window. Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e4191ccbdb7a..6d6e18fee9fe 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -38,7 +38,6 @@ config ARM select HARDIRQS_SW_RESEND select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW - select GENERIC_IRQ_PROBE select ARCH_WANT_IPC_PARSE_VERSION select HARDIRQS_SW_RESEND select CPU_PM if (SUSPEND || CPU_IDLE) -- GitLab From 0fe33aae0e94b4097dd433c9399e16e17d638cd8 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 12:55:22 +0200 Subject: [PATCH 5449/5711] audit: don't free_chunk() after fsnotify_add_mark() Don't do free_chunk() after fsnotify_add_mark(). That one does a delayed unref via the destroy list and this results in use-after-free. Signed-off-by: Miklos Szeredi Acked-by: Eric Paris CC: stable@vger.kernel.org --- kernel/audit_tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 3a5ca582ba1e..69a58515f43f 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -259,7 +259,7 @@ static void untag_chunk(struct node *p) fsnotify_duplicate_mark(&new->mark, entry); if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { - free_chunk(new); + fsnotify_put_mark(&new->mark); goto Fallback; } @@ -322,7 +322,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) entry = &chunk->mark; if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { - free_chunk(chunk); + fsnotify_put_mark(entry); return -ENOSPC; } @@ -396,7 +396,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) fsnotify_duplicate_mark(chunk_entry, old_entry); if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { spin_unlock(&old_entry->lock); - free_chunk(chunk); + fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); return -ENOSPC; } -- GitLab From a2140fc0cb0325bb6384e788edd27b9a568714e2 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 12:55:22 +0200 Subject: [PATCH 5450/5711] audit: fix refcounting in audit-tree Refcounting of fsnotify_mark in audit tree is broken. E.g: refcount create_chunk alloc_chunk 1 fsnotify_add_mark 2 untag_chunk fsnotify_get_mark 3 fsnotify_destroy_mark audit_tree_freeing_mark 2 fsnotify_put_mark 1 fsnotify_put_mark 0 via destroy_list fsnotify_mark_destroy -1 This was reported by various people as triggering Oops when stopping auditd. We could just remove the put_mark from audit_tree_freeing_mark() but that would break freeing via inode destruction. So this patch simply omits a put_mark after calling destroy_mark or adds a get_mark before. The additional get_mark is necessary where there's no other put_mark after fsnotify_destroy_mark() since it assumes that the caller is holding a reference (or the inode is keeping the mark pinned, not the case here AFAICS). Signed-off-by: Miklos Szeredi Reported-by: Valentin Avram Reported-by: Peter Moody Acked-by: Eric Paris CC: stable@vger.kernel.org --- kernel/audit_tree.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 69a58515f43f..2b2ffff9eca2 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -250,7 +250,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; } @@ -293,7 +292,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; Fallback: @@ -332,6 +330,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); chunk->dead = 1; spin_unlock(&entry->lock); + fsnotify_get_mark(entry); fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); return 0; @@ -412,6 +411,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); + fsnotify_get_mark(chunk_entry); fsnotify_destroy_mark(chunk_entry); fsnotify_put_mark(chunk_entry); @@ -445,7 +445,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&old_entry->lock); fsnotify_destroy_mark(old_entry); fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ - fsnotify_put_mark(old_entry); /* and kill it */ return 0; } -- GitLab From b3e8692b4dde5cf5fc60e4b95385229a72623182 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 12:55:22 +0200 Subject: [PATCH 5451/5711] audit: clean up refcounting in audit-tree Drop the initial reference by fsnotify_init_mark early instead of audit_tree_freeing_mark() at destroy time. In the cases we destroy the mark before we drop the initial reference we need to get rid of the get_mark that balances the put_mark in audit_tree_freeing_mark(). Signed-off-by: Miklos Szeredi --- kernel/audit_tree.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 2b2ffff9eca2..ed206fd88cca 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -292,6 +292,7 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); + fsnotify_put_mark(&new->mark); /* drop initial reference */ goto out; Fallback: @@ -330,7 +331,6 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); chunk->dead = 1; spin_unlock(&entry->lock); - fsnotify_get_mark(entry); fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); return 0; @@ -346,6 +346,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) insert_hash(chunk); spin_unlock(&hash_lock); spin_unlock(&entry->lock); + fsnotify_put_mark(entry); /* drop initial reference */ return 0; } @@ -411,7 +412,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); - fsnotify_get_mark(chunk_entry); fsnotify_destroy_mark(chunk_entry); fsnotify_put_mark(chunk_entry); @@ -444,6 +444,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); fsnotify_destroy_mark(old_entry); + fsnotify_put_mark(chunk_entry); /* drop initial reference */ fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ return 0; } @@ -915,7 +916,12 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); evict_chunk(chunk); - fsnotify_put_mark(entry); + + /* + * We are guaranteed to have at least one reference to the mark from + * either the inode or the caller of fsnotify_destroy_mark(). + */ + BUG_ON(atomic_read(&entry->refcnt) < 1); } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, -- GitLab From e68726ff72cf7ba5e7d789857fcd9a75ca573f03 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 13:01:24 +0200 Subject: [PATCH 5452/5711] vfs: canonicalize create mode in build_open_flags() Userspace can pass weird create mode in open(2) that we canonicalize to "(mode & S_IALLUGO) | S_IFREG" in vfs_create(). The problem is that we use the uncanonicalized mode before calling vfs_create() with unforseen consequences. So do the canonicalization early in build_open_flags(). Signed-off-by: Miklos Szeredi Tested-by: Richard W.M. Jones CC: stable@vger.kernel.org --- fs/open.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/open.c b/fs/open.c index bc132e167d2d..e1f2cdb91a4d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -852,9 +852,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o int lookup_flags = 0; int acc_mode; - if (!(flags & O_CREAT)) - mode = 0; - op->mode = mode; + if (flags & O_CREAT) + op->mode = (mode & S_IALLUGO) | S_IFREG; + else + op->mode = 0; /* Must never be set by userspace */ flags &= ~FMODE_NONOTIFY; -- GitLab From 62b259d8b3ea9d4a73108fc599e40c863ec25ae6 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 13:01:24 +0200 Subject: [PATCH 5453/5711] vfs: atomic_open(): fix create mode usage Don't mask S_ISREG off the create mode before passing to ->atomic_open(). Other methods (->create, ->mknod) also get the complete file mode and filesystems expect it. Reported-by: Steve Reported-by: Richard W.M. Jones Signed-off-by: Miklos Szeredi Tested-by: Richard W.M. Jones --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 1b464390dde8..5bac1bb6e585 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2414,7 +2414,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, goto out; } - mode = op->mode & S_IALLUGO; + mode = op->mode; if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) mode &= ~current_umask(); -- GitLab From 38227f78a5020b3100cbb0406c89807563b10dae Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 13:01:24 +0200 Subject: [PATCH 5454/5711] vfs: pass right create mode to may_o_create() Pass the umask-ed create mode to may_o_create() instead of the original one. Signed-off-by: Miklos Szeredi Tested-by: Richard W.M. Jones --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 5bac1bb6e585..26c28ec4f4af 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2452,7 +2452,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, } if (open_flag & O_CREAT) { - error = may_o_create(&nd->path, dentry, op->mode); + error = may_o_create(&nd->path, dentry, mode); if (error) { create_error = error; if (open_flag & O_EXCL) -- GitLab From af109bca94a8a223c4632a4ff769b3419fe7ed8c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 13:01:24 +0200 Subject: [PATCH 5455/5711] fuse: check create mode in atomic open Verify that the VFS is passing us a complete create mode with the S_IFREG to atomic open. Reported-by: Steve Reported-by: Richard W.M. Jones Signed-off-by: Miklos Szeredi Tested-by: Richard W.M. Jones --- fs/fuse/dir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8964cf3999b2..324bc0850534 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -383,6 +383,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, struct fuse_entry_out outentry; struct fuse_file *ff; + /* Userspace expects S_IFREG in create mode */ + BUG_ON((mode & S_IFMT) != S_IFREG); + forget = fuse_alloc_forget(); err = -ENOMEM; if (!forget) -- GitLab From 908d6d52928a7f2a4b317aac47542c5fbef43d88 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 15 Aug 2012 01:10:04 +0300 Subject: [PATCH 5456/5711] regulator: twl-regulator: fix up VINTANA1/VINTANA2 It seems commit 2098e95ce9bb039ff2e7bf836df358d18a176139 (regulator: twl: adapt twl-regulator driver to dt) accidentally deleted VINTANA1. Also the same commit defines VINTANA2 twice with TWL4030_ADJUSTABLE_LDO and TWL4030_FIXED_LDO. This patch changes the fixed one to be VINTANA1. I noticed this when auditing my N900 boot logs. I could not notice any change in device behaviour, though, except that the boot logs are now like before: ... [ 0.282928] VDAC: 1800 mV normal standby [ 0.284027] VCSI: 1800 mV normal standby [ 0.285400] VINTANA1: 1500 mV normal standby [ 0.286865] VINTANA2: 2750 mV normal standby [ 0.288208] VINTDIG: 1500 mV normal standby [ 0.289978] VSDI_CSI: 1800 mV normal standby ... Signed-off-by: Aaro Koskinen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/twl-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 30cb62289b74..77a71a5c17c3 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1037,7 +1037,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), - TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), + TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), -- GitLab From 6330c790dae1229bb33571c48984ca42a8a4c250 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Wed, 15 Aug 2012 11:52:01 -0400 Subject: [PATCH 5457/5711] C6X: add Lx_CACHE_SHIFT defines C6X currently lacks Lx_CACHE_SHIFT defines which are needed in a few places in the generic kernel. This patch adds _SHIFT defines for the various caches and bases the Lx_CACHE_BYTES defines on them. Signed-off-by: Mark Salter --- arch/c6x/include/asm/cache.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/c6x/include/asm/cache.h b/arch/c6x/include/asm/cache.h index 6d521d96d941..09c5a0f5f4d1 100644 --- a/arch/c6x/include/asm/cache.h +++ b/arch/c6x/include/asm/cache.h @@ -1,7 +1,7 @@ /* * Port on Texas Instruments TMS320C6x architecture * - * Copyright (C) 2005, 2006, 2009, 2010 Texas Instruments Incorporated + * Copyright (C) 2005, 2006, 2009, 2010, 2012 Texas Instruments Incorporated * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) * * This program is free software; you can redistribute it and/or modify @@ -16,9 +16,14 @@ /* * Cache line size */ -#define L1D_CACHE_BYTES 64 -#define L1P_CACHE_BYTES 32 -#define L2_CACHE_BYTES 128 +#define L1D_CACHE_SHIFT 6 +#define L1D_CACHE_BYTES (1 << L1D_CACHE_SHIFT) + +#define L1P_CACHE_SHIFT 5 +#define L1P_CACHE_BYTES (1 << L1P_CACHE_SHIFT) + +#define L2_CACHE_SHIFT 7 +#define L2_CACHE_BYTES (1 << L2_CACHE_SHIFT) /* * L2 used as cache @@ -29,7 +34,8 @@ * For practical reasons the L1_CACHE_BYTES defines should not be smaller than * the L2 line size */ -#define L1_CACHE_BYTES L2_CACHE_BYTES +#define L1_CACHE_SHIFT L2_CACHE_SHIFT +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #define L2_CACHE_ALIGN_LOW(x) \ (((x) & ~(L2_CACHE_BYTES - 1))) -- GitLab From 01ddd9a809b9a95df097ff1b5565f806e681a606 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Wed, 15 Aug 2012 12:12:16 -0400 Subject: [PATCH 5458/5711] C6X: select GENERIC_ATOMIC64 The generic atomic64 support came in 2009 to support the perf subsystem with the expectation that all architectures would implement atomic64 support. Since then, other optional parts of the generic kernel have also come to expect atomic64 support. This patch enables generic atomic64 support for C6X architecture. Signed-off-by: Mark Salter --- arch/c6x/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index 052f81a76239..983c859e40b7 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig @@ -6,6 +6,7 @@ config C6X def_bool y select CLKDEV_LOOKUP + select GENERIC_ATOMIC64 select GENERIC_IRQ_SHOW select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG -- GitLab From 3d0882c0d10d4b4785aeaf26043e764e3aaca825 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 4 Aug 2012 23:27:32 +0200 Subject: [PATCH 5459/5711] PCI / PM: Fix D3/D3cold/D4 messages printed by acpi_pci_set_power_state() If a PCI device is put into D3_cold by acpi_bus_set_power(), the message printed by acpi_pci_set_power_state() says that its power state has been changed to D4, which doesn't make sense. In turn, if the device is put into D3_hot, the message simply says "D3" without specifying the variant of the D3 state. Fix this by using the pci_power_name() macro for printing the state name instead of building it from the numeric value corresponding to the given state directly. Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index fbf7b26c7c8a..c5792d622dc4 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -266,8 +266,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) } if (!error) - dev_printk(KERN_INFO, &dev->dev, - "power state changed by ACPI to D%d\n", state); + dev_info(&dev->dev, "power state changed by ACPI to %s\n", + pci_power_name(state)); return error; } -- GitLab From 0b68c8e2c3afaf9807eb1ebe0ccfb3b809570aa4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 12 Aug 2012 23:26:07 +0200 Subject: [PATCH 5460/5711] PCI: EHCI: Fix crash during hibernation on ASUS computers Commit dbf0e4c (PCI: EHCI: fix crash during suspend on ASUS computers) added a workaround for an ASUS suspend issue related to USB EHCI and a bug in a number of ASUS BIOSes that attempt to shut down the EHCI controller during system suspend if its PCI command register doesn't contain 0 at that time. It turns out that the same workaround is necessary in the analogous hibernation code path, so add it. References: https://bugzilla.kernel.org/show_bug.cgi?id=45811 Reported-and-tested-by: Oleksij Rempel Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org --- drivers/pci/pci-driver.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 185be3703343..5270f1a99328 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -959,6 +959,13 @@ static int pci_pm_poweroff_noirq(struct device *dev) if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) pci_prepare_to_sleep(pci_dev); + /* + * The reason for doing this here is the same as for the analogous code + * in pci_pm_suspend_noirq(). + */ + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) + pci_write_config_word(pci_dev, PCI_COMMAND, 0); + return 0; } -- GitLab From 142ad5db2b29a1c392e1b14934fae5d161d6c6e7 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 10 Aug 2012 00:07:58 +0000 Subject: [PATCH 5461/5711] IB: Fix typos in infiniband drivers Correct spelling typos in comments in drivers/infiniband. Signed-off-by: Masanari Iida Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_rnic.c | 2 +- drivers/infiniband/hw/cxgb3/iwch_cm.c | 2 +- drivers/infiniband/hw/qib/qib_sd7220.c | 2 +- drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 8c81992fa6db..e4a73158fc7f 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -439,7 +439,7 @@ static int c2_rnic_close(struct c2_dev *c2dev) /* * Called by c2_probe to initialize the RNIC. This principally - * involves initalizing the various limits and resouce pools that + * involves initializing the various limits and resource pools that * comprise the RNIC instance. */ int __devinit c2_rnic_init(struct c2_dev *c2dev) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 77b6b182778a..aaf88ef9409c 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1680,7 +1680,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) * T3A does 3 things when a TERM is received: * 1) send up a CPL_RDMA_TERMINATE message with the TERM packet * 2) generate an async event on the QP with the TERMINATE opcode - * 3) post a TERMINATE opcde cqe into the associated CQ. + * 3) post a TERMINATE opcode cqe into the associated CQ. * * For (1), we save the message in the qp for later consumer consumption. * For (2), we move the QP into TERMINATE, post a QP event and disconnect. diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index a322d5171a2c..50a8a0d4fe67 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c @@ -372,7 +372,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd, /* Read CTRL reg for each channel to check TRIMDONE */ if (baduns & (1 << chn)) { qib_dev_err(dd, - "Reseting TRIMDONE on chn %d (%s)\n", + "Resetting TRIMDONE on chn %d (%s)\n", chn, where); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 7a0ce8d42887..9e1449f8c6a2 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1469,7 +1469,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, * * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping * the data that has been transferred via IB RDMA had to be postponed until the - * check_stop_free() callback. None of this is nessecary anymore and needs to + * check_stop_free() callback. None of this is necessary anymore and needs to * be cleaned up. */ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, -- GitLab From 51fa3ca37e3bebb291dbe50faa3cb259af35e978 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 12:58:35 +0000 Subject: [PATCH 5462/5711] IB/qib: Fix error return code in qib_init_7322_variables() Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Acked-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba7322.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 0d7280af99bc..3f6b21e9dc11 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -6346,8 +6346,10 @@ static int qib_init_7322_variables(struct qib_devdata *dd) dd->piobcnt4k * dd->align4k; dd->piovl15base = ioremap_nocache(vl15off, NUM_VL15_BUFS * dd->align4k); - if (!dd->piovl15base) + if (!dd->piovl15base) { + ret = -ENOMEM; goto bail; + } } qib_7322_set_baseaddrs(dd); /* set chip access pointers now */ -- GitLab From 220329916c72ee3d54ae7262b215a050f04a18fc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 14 Aug 2012 13:18:53 +0000 Subject: [PATCH 5463/5711] IB/srp: Fix a race condition Avoid a crash caused by the scmnd->scsi_done(scmnd) call in srp_process_rsp() being invoked with scsi_done == NULL. This can happen if a reply is received during or after a command abort. Reported-by: Joseph Glanville Reference: http://marc.info/?l=linux-rdma&m=134314367801595 Cc: Acked-by: David Dillow Signed-off-by: Bart Van Assche Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 87 +++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bcbf22ee0aa7..1b5b0c730054 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, scmnd->sc_data_direction); } -static void srp_remove_req(struct srp_target_port *target, - struct srp_request *req, s32 req_lim_delta) +/** + * srp_claim_req - Take ownership of the scmnd associated with a request. + * @target: SRP target port. + * @req: SRP request. + * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take + * ownership of @req->scmnd if it equals @scmnd. + * + * Return value: + * Either NULL or a pointer to the SCSI command the caller became owner of. + */ +static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, + struct srp_request *req, + struct scsi_cmnd *scmnd) +{ + unsigned long flags; + + spin_lock_irqsave(&target->lock, flags); + if (!scmnd) { + scmnd = req->scmnd; + req->scmnd = NULL; + } else if (req->scmnd == scmnd) { + req->scmnd = NULL; + } else { + scmnd = NULL; + } + spin_unlock_irqrestore(&target->lock, flags); + + return scmnd; +} + +/** + * srp_free_req() - Unmap data and add request to the free request list. + */ +static void srp_free_req(struct srp_target_port *target, + struct srp_request *req, struct scsi_cmnd *scmnd, + s32 req_lim_delta) { unsigned long flags; - srp_unmap_data(req->scmnd, target, req); + srp_unmap_data(scmnd, target, req); + spin_lock_irqsave(&target->lock, flags); target->req_lim += req_lim_delta; - req->scmnd = NULL; list_add_tail(&req->list, &target->free_reqs); spin_unlock_irqrestore(&target->lock, flags); } static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) { - req->scmnd->result = DID_RESET << 16; - req->scmnd->scsi_done(req->scmnd); - srp_remove_req(target, req, 0); + struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); + + if (scmnd) { + scmnd->result = DID_RESET << 16; + scmnd->scsi_done(scmnd); + srp_free_req(target, req, scmnd, 0); + } } static int srp_reconnect_target(struct srp_target_port *target) @@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) complete(&target->tsk_mgmt_done); } else { req = &target->req_ring[rsp->tag]; - scmnd = req->scmnd; - if (!scmnd) + scmnd = srp_claim_req(target, req, NULL); + if (!scmnd) { shost_printk(KERN_ERR, target->scsi_host, "Null scmnd for RSP w/tag %016llx\n", (unsigned long long) rsp->tag); + + spin_lock_irqsave(&target->lock, flags); + target->req_lim += be32_to_cpu(rsp->req_lim_delta); + spin_unlock_irqrestore(&target->lock, flags); + + return; + } scmnd->result = rsp->status; if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { @@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); + srp_free_req(target, req, scmnd, + be32_to_cpu(rsp->req_lim_delta)); + scmnd->host_scribble = NULL; scmnd->scsi_done(scmnd); } @@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_request *req = (struct srp_request *) scmnd->host_scribble; - int ret = SUCCESS; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (!req || target->qp_in_error) + if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) return FAILED; - if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK)) - return FAILED; - - if (req->scmnd) { - if (!target->tsk_mgmt_status) { - srp_remove_req(target, req, 0); - scmnd->result = DID_ABORT << 16; - } else - ret = FAILED; - } + srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK); + srp_free_req(target, req, scmnd, 0); + scmnd->result = DID_ABORT << 16; - return ret; + return SUCCESS; } static int srp_reset_device(struct scsi_cmnd *scmnd) -- GitLab From c03307eab68d583ea6db917681afa14ed1fb3b84 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 14 Aug 2012 08:19:33 -0700 Subject: [PATCH 5464/5711] bridge: fix rcu dereference outside of rcu_read_lock Alternative solution for problem found by Linux Driver Verification project (linuxtesting.org). As it noted in the comment before the br_handle_frame_finish function, this function should be called under rcu_read_lock. The problem callgraph: br_dev_xmit -> br_nf_pre_routing_finish_bridge_slow -> -> br_handle_frame_finish -> br_port_get_rcu -> rcu_dereference And in this case there is no read-lock section. Reported-by: Denis Efremov Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 32211fa5b506..070e8a68cfc6 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -31,9 +31,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct net_bridge_mdb_entry *mdst; struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); + rcu_read_lock(); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { br_nf_pre_routing_finish_bridge_slow(skb); + rcu_read_unlock(); return NETDEV_TX_OK; } #endif @@ -48,7 +50,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); - rcu_read_lock(); if (is_broadcast_ether_addr(dest)) br_flood_deliver(br, skb); else if (is_multicast_ether_addr(dest)) { -- GitLab From e3bc4ffb814c847bde7706a80d5684d12c676a8b Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Tue, 14 Aug 2012 17:13:36 +0100 Subject: [PATCH 5465/5711] vmxnet3: Fix race between dev_open() and register_netdev() dev_open() can complete before register_netdev() returns. Fix vmxnet3_probe_device() to support this. Signed-off-by: Steve Hodgson Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 93e0cfb739b8..ce9d4f2c9776 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -3019,6 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, netdev->watchdog_timeo = 5 * HZ; INIT_WORK(&adapter->work, vmxnet3_reset_work); + set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); if (adapter->intr.type == VMXNET3_IT_MSIX) { int i; @@ -3043,7 +3044,6 @@ vmxnet3_probe_device(struct pci_dev *pdev, goto err_register; } - set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); vmxnet3_check_link(adapter, false); atomic_inc(&devices_found); return 0; -- GitLab From f1b5c997e68533df1f96dcd3068a231bca495603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 15 Aug 2012 15:43:33 +0200 Subject: [PATCH 5466/5711] USB: option: add ZTE K5006-Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ZTE (Vodafone) K5006-Z use the following interface layout: 00 DIAG 01 secondary 02 modem 03 networkcard 04 storage Ignoring interface #3 which is handled by the qmi_wwan driver. Cc: Thomas Schäfer Cc: stable Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 99306281dcba..cc40f47ecea1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,6 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, -- GitLab From 1e658489ba8d87b7c89ca6f734b8319acc534dbc Mon Sep 17 00:00:00 2001 From: Mark Ferrell Date: Tue, 24 Jul 2012 13:38:31 -0500 Subject: [PATCH 5467/5711] USB: serial: Fix mos7840 timeout * mos7840 driver was using multiple of HZ for the timeout handed off to usb_control_msg(). Changed the timeout to use msecs instead. * Remove unused WAIT_FOR_EVER definition Signed-off-by: Mark Ferrell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 009c1d99e146..2f6da1e89bfa 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -82,8 +82,7 @@ * Defines used for sending commands to port */ -#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */ -#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */ +#define MOS_WDR_TIMEOUT 5000 /* default urb timeout */ #define MOS_PORT1 0x0200 #define MOS_PORT2 0x0300 @@ -1347,7 +1346,7 @@ static void mos7840_close(struct usb_serial_port *port) static void mos7840_block_until_chase_response(struct tty_struct *tty, struct moschip_port *mos7840_port) { - int timeout = 1 * HZ; + int timeout = msecs_to_jiffies(1000); int wait = 10; int count; @@ -2675,7 +2674,7 @@ static int mos7840_startup(struct usb_serial *serial) /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); + (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); return 0; error: for (/* nothing */; i >= 0; i--) { -- GitLab From 1690d86aa33fa14c0ae4ac97e59d806eeddccd2c Mon Sep 17 00:00:00 2001 From: Alex Gershgorin Date: Wed, 1 Aug 2012 05:05:10 -0300 Subject: [PATCH 5468/5711] [media] media: mx3_camera: buf_init() add buffer state check This patch checks the state of the buffer when calling .buf_init() method. This is needed for the USERPTR buffer type, because in that case .buf_init() is called every time a buffer is queued, and not only once during the preparation stage, like in the MMAP case. Without this check buffers get initialised repeatedly, which also leads to the allocation of new DMA descriptors, of which there is only a final relatively small number available. Both MMAP and USERPTR methods were successfully tested. Signed-off-by: Alex Gershgorin [g.liakhovetski@gmx.de: remove mx3_camera_buffer::state completely] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx3_camera.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index f13643d31353..af2297dd49c8 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -61,15 +61,9 @@ #define MAX_VIDEO_MEM 16 -enum csi_buffer_state { - CSI_BUF_NEEDS_INIT, - CSI_BUF_PREPARED, -}; - struct mx3_camera_buffer { /* common v4l buffer stuff -- must be first */ struct vb2_buffer vb; - enum csi_buffer_state state; struct list_head queue; /* One descriptot per scatterlist (per frame) */ @@ -285,7 +279,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) goto error; } - if (buf->state == CSI_BUF_NEEDS_INIT) { + if (!buf->txd) { sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); sg_dma_len(sg) = new_size; @@ -298,7 +292,6 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) txd->callback_param = txd; txd->callback = mx3_cam_dma_done; - buf->state = CSI_BUF_PREPARED; buf->txd = txd; } else { txd = buf->txd; @@ -385,7 +378,6 @@ static void mx3_videobuf_release(struct vb2_buffer *vb) /* Doesn't hurt also if the list is empty */ list_del_init(&buf->queue); - buf->state = CSI_BUF_NEEDS_INIT; if (txd) { buf->txd = NULL; @@ -405,13 +397,13 @@ static int mx3_videobuf_init(struct vb2_buffer *vb) struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_buffer *buf = to_mx3_vb(vb); - /* This is for locking debugging only */ - INIT_LIST_HEAD(&buf->queue); - sg_init_table(&buf->sg, 1); + if (!buf->txd) { + /* This is for locking debugging only */ + INIT_LIST_HEAD(&buf->queue); + sg_init_table(&buf->sg, 1); - buf->state = CSI_BUF_NEEDS_INIT; - - mx3_cam->buf_total += vb2_plane_size(vb, 0); + mx3_cam->buf_total += vb2_plane_size(vb, 0); + } return 0; } -- GitLab From 5c4dfc84a88e1108f5ddba256ecaab6fe45f94e5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 May 2012 20:14:47 -0300 Subject: [PATCH 5469/5711] [media] video: mx1_camera: Use clk_prepare_enable/clk_disable_unprepare Prepare the clock before enabling it. Cc: Guennadi Liakhovetski Cc: Signed-off-by: Fabio Estevam Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx1_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index d2e6f82ecfac..560a65aa7038 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -403,7 +403,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) dev_dbg(pcdev->icd->parent, "Activate device\n"); - clk_enable(pcdev->clk); + clk_prepare_enable(pcdev->clk); /* enable CSI before doing anything else */ __raw_writel(csicr1, pcdev->base + CSICR1); @@ -422,7 +422,7 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); - clk_disable(pcdev->clk); + clk_disable_unprepare(pcdev->clk); } /* -- GitLab From f8afbf3caa991655e989ecd10c135162d84288b2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 May 2012 20:14:48 -0300 Subject: [PATCH 5470/5711] [media] video: mx2_camera: Use clk_prepare_enable/clk_disable_unprepare Prepare the clock before enabling it. Cc: Guennadi Liakhovetski Cc: Signed-off-by: Fabio Estevam Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx2_camera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 637bde8aca28..2c3ec94769a5 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -407,7 +407,7 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) { unsigned long flags; - clk_disable(pcdev->clk_csi); + clk_disable_unprepare(pcdev->clk_csi); writel(0, pcdev->base_csi + CSICR1); if (cpu_is_mx27()) { writel(0, pcdev->base_emma + PRP_CNTL); @@ -435,7 +435,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) if (pcdev->icd) return -EBUSY; - ret = clk_enable(pcdev->clk_csi); + ret = clk_prepare_enable(pcdev->clk_csi); if (ret < 0) return ret; @@ -1639,7 +1639,7 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) goto exit_free_irq; } - clk_enable(pcdev->clk_emma); + clk_prepare_enable(pcdev->clk_emma); err = mx27_camera_emma_prp_reset(pcdev); if (err) @@ -1648,7 +1648,7 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) return err; exit_clk_emma_put: - clk_disable(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma); clk_put(pcdev->clk_emma); exit_free_irq: free_irq(pcdev->irq_emma, pcdev); @@ -1785,7 +1785,7 @@ exit_free_emma: eallocctx: if (cpu_is_mx27()) { free_irq(pcdev->irq_emma, pcdev); - clk_disable(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma); clk_put(pcdev->clk_emma); iounmap(pcdev->base_emma); release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); @@ -1825,7 +1825,7 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) iounmap(pcdev->base_csi); if (cpu_is_mx27()) { - clk_disable(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma); clk_put(pcdev->clk_emma); iounmap(pcdev->base_emma); res = pcdev->res_emma; -- GitLab From ad5b987031835b0ac3064ef12209282277dbae54 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Wed, 1 Aug 2012 06:16:44 -0300 Subject: [PATCH 5471/5711] [media] media: mx2_camera: Fix clock handling for i.MX27 On i.MX27 two clocks are required: emma-ipg and emma-ahb. The ahb clock has to be requested using both a device and a connection ID. Signed-off-by: Javier Martin [g.liakhovetski@gmx.de: rebase to the current media tree] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx2_camera.c | 43 +++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 2c3ec94769a5..ac175406e582 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -272,7 +272,7 @@ struct mx2_camera_dev { struct device *dev; struct soc_camera_host soc_host; struct soc_camera_device *icd; - struct clk *clk_csi, *clk_emma; + struct clk *clk_csi, *clk_emma_ahb, *clk_emma_ipg; unsigned int irq_csi, irq_emma; void __iomem *base_csi, *base_emma; @@ -1633,23 +1633,34 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) goto exit_iounmap; } - pcdev->clk_emma = clk_get(NULL, "emma"); - if (IS_ERR(pcdev->clk_emma)) { - err = PTR_ERR(pcdev->clk_emma); + pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg"); + if (IS_ERR(pcdev->clk_emma_ipg)) { + err = PTR_ERR(pcdev->clk_emma_ipg); goto exit_free_irq; } - clk_prepare_enable(pcdev->clk_emma); + clk_prepare_enable(pcdev->clk_emma_ipg); + + pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb"); + if (IS_ERR(pcdev->clk_emma_ahb)) { + err = PTR_ERR(pcdev->clk_emma_ahb); + goto exit_clk_emma_ipg_put; + } + + clk_prepare_enable(pcdev->clk_emma_ahb); err = mx27_camera_emma_prp_reset(pcdev); if (err) - goto exit_clk_emma_put; + goto exit_clk_emma_ahb_put; return err; -exit_clk_emma_put: - clk_disable_unprepare(pcdev->clk_emma); - clk_put(pcdev->clk_emma); +exit_clk_emma_ahb_put: + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); +exit_clk_emma_ipg_put: + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); exit_free_irq: free_irq(pcdev->irq_emma, pcdev); exit_iounmap: @@ -1685,7 +1696,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) goto exit; } - pcdev->clk_csi = clk_get(&pdev->dev, NULL); + pcdev->clk_csi = clk_get(&pdev->dev, "ahb"); if (IS_ERR(pcdev->clk_csi)) { dev_err(&pdev->dev, "Could not get csi clock\n"); err = PTR_ERR(pcdev->clk_csi); @@ -1785,8 +1796,10 @@ exit_free_emma: eallocctx: if (cpu_is_mx27()) { free_irq(pcdev->irq_emma, pcdev); - clk_disable_unprepare(pcdev->clk_emma); - clk_put(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); iounmap(pcdev->base_emma); release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); } @@ -1825,8 +1838,10 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) iounmap(pcdev->base_csi); if (cpu_is_mx27()) { - clk_disable_unprepare(pcdev->clk_emma); - clk_put(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); iounmap(pcdev->base_emma); res = pcdev->res_emma; release_mem_region(res->start, resource_size(res)); -- GitLab From 991b3137f21e13db4711f313edbe67d49bed795b Mon Sep 17 00:00:00 2001 From: Albert Wang Date: Wed, 1 Aug 2012 02:45:41 -0300 Subject: [PATCH 5472/5711] [media] media: soc_camera: don't clear pix->sizeimage in JPEG mode In JPEG mode, the size of image is variable due to different JPEG compression rate. We only can get the pix->sizeimage from the user. If we clear pix->sizeimage in soc_camera_try_fmt() then we will get it from: ret = soc_mbus_image_size(xlate->host_fmt, pix->bytesperline, pix->height); if (ret < 0) return ret; pix->sizeimage = max_t(u32, pix->sizeimage, ret); In general, this sizeimage will be larger than the actul JPEG image size. But vb2 will check the buffer and size of image in __qbuf_userptr(): /* Check if the provided plane buffer is large enough */ if (planes[plane].length < q->plane_sizes[plane]) So we shouldn't clear the pix->sizeimage and also shouldn't re-calculate the pix->sizeimage in soc_mbus_image_size() in JPEG mode We also shouldn't re-calculate pix->bytesperline: ret = soc_mbus_bytes_per_line(pix->width, xlate->host_fmt); if (ret < 0) return ret; pix->bytesperline = max_t(u32, pix->bytesperline, ret); pix->bytesperline also should be set by the user or by the driver's try_fmt() implementation. Change-Id: I700690a2287346127a624b5260922eaa5427a596 Signed-off-by: Albert Wang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 3 ++- drivers/media/video/soc_mediabus.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b03ffecb7438..1bde255e45df 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -171,7 +171,8 @@ static int soc_camera_try_fmt(struct soc_camera_device *icd, dev_dbg(icd->pdev, "TRY_FMT(%c%c%c%c, %ux%u)\n", pixfmtstr(pix->pixelformat), pix->width, pix->height); - if (!(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { + if (pix->pixelformat != V4L2_PIX_FMT_JPEG && + !(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { pix->bytesperline = 0; pix->sizeimage = 0; } diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index 89dce097a827..a397812635d6 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c @@ -378,6 +378,9 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel); s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) { + if (mf->fourcc == V4L2_PIX_FMT_JPEG) + return 0; + if (mf->layout != SOC_MBUS_LAYOUT_PACKED) return width * mf->bits_per_sample / 8; @@ -400,6 +403,9 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf, u32 bytes_per_line, u32 height) { + if (mf->fourcc == V4L2_PIX_FMT_JPEG) + return 0; + if (mf->layout == SOC_MBUS_LAYOUT_PACKED) return bytes_per_line * height; -- GitLab From 89dd86db78e08b51bab29e168fd41b2fd943e6b6 Mon Sep 17 00:00:00 2001 From: Yishai Hadas Date: Mon, 13 Aug 2012 08:15:06 +0000 Subject: [PATCH 5473/5711] mlx4_core: Allow large mlx4_buddy bitmaps mlx4_buddy_init uses kmalloc() to allocate bitmaps, which fails when the required size is beyond the max supported value (or when memory is too fragmented to handle a huge allocation). Extend this to use use vmalloc() if kmalloc() fails, and take that into account when freeing the bitmaps as well. This fixes a driver load failure when log num mtt is 26 or higher, and is a step in the direction of allowing to register huge amounts of memory on large memory systems. Signed-off-by: Yishai Hadas Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/mr.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index af55b7ce5341..d6a3a392a377 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -130,8 +131,11 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) for (i = 0; i <= buddy->max_order; ++i) { s = BITS_TO_LONGS(1 << (buddy->max_order - i)); buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); - if (!buddy->bits[i]) - goto err_out_free; + if (!buddy->bits[i]) { + buddy->bits[i] = vmalloc(s * sizeof(long)); + if (!buddy->bits[i]) + goto err_out_free; + } bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); } @@ -142,7 +146,10 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) err_out_free: for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); + if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i])) + vfree(buddy->bits[i]); + else + kfree(buddy->bits[i]); err_out: kfree(buddy->bits); @@ -156,7 +163,10 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) int i; for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); + if (is_vmalloc_addr(buddy->bits[i])) + vfree(buddy->bits[i]); + else + kfree(buddy->bits[i]); kfree(buddy->bits); kfree(buddy->num_free); -- GitLab From 3de819e6b642fdd51904f5f4d2716d7466a2f7f5 Mon Sep 17 00:00:00 2001 From: Yishai Hadas Date: Mon, 13 Aug 2012 08:15:07 +0000 Subject: [PATCH 5474/5711] mlx4_core: Fix integer overflow issues around MTT table Fix some issues around int variables used in data structures related to memory registration. Handle int overflow in mlx4_init_icm_table by using a u64 intermediate variable and changing struct mlx4_icm_table num_obj field to be u32. Change some more fields/variables to use u32 instead of int to prevent a case where the variable becomes negative when bit 31 is set. Also subtract log_mtts_per_seg from the exponent when computing num_mtt, since its added later on in that very same code area. This and the previous commit fixes some issues which actually prevent commit db5a7a65c058 ("mlx4_core: Scale size of MTT table with system RAM") from working. Now, when the number of MTTs is scaled with the size of the RAM we can map up to 8TB. Signed-off-by: Yishai Hadas Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/icm.c | 9 ++++++--- drivers/net/ethernet/mellanox/mlx4/icm.h | 2 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 4 ++-- drivers/net/ethernet/mellanox/mlx4/mr.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/profile.c | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index 88b7b3e75ab1..daf417923661 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -358,13 +358,14 @@ void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, } int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, + u64 virt, int obj_size, u32 nobj, int reserved, int use_lowmem, int use_coherent) { int obj_per_chunk; int num_icm; unsigned chunk_size; int i; + u64 size; obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size; num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk; @@ -380,10 +381,12 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, table->coherent = use_coherent; mutex_init(&table->mutex); + size = (u64) nobj * obj_size; for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { chunk_size = MLX4_TABLE_CHUNK_SIZE; - if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > nobj * obj_size) - chunk_size = PAGE_ALIGN(nobj * obj_size - i * MLX4_TABLE_CHUNK_SIZE); + if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > size) + chunk_size = PAGE_ALIGN(size - + i * MLX4_TABLE_CHUNK_SIZE); table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index 19e4efc0b342..a67744f53506 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -78,7 +78,7 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, int start, int end); int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, + u64 virt, int obj_size, u32 nobj, int reserved, int use_lowmem, int use_coherent); void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 59ebc0339638..4d9df8f2a126 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -249,7 +249,7 @@ struct mlx4_bitmap { struct mlx4_buddy { unsigned long **bits; unsigned int *num_free; - int max_order; + u32 max_order; spinlock_t lock; }; @@ -258,7 +258,7 @@ struct mlx4_icm; struct mlx4_icm_table { u64 virt; int num_icm; - int num_obj; + u32 num_obj; int obj_size; int lowmem; int coherent; diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index d6a3a392a377..44b8e1ea1cd8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -678,7 +678,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) return err; err = mlx4_buddy_init(&mr_table->mtt_buddy, - ilog2(dev->caps.num_mtts / + ilog2((u32)dev->caps.num_mtts / (1 << log_mtts_per_seg))); if (err) goto err_buddy; @@ -688,7 +688,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) mlx4_alloc_mtt_range(dev, fls(dev->caps.reserved_mtts - 1)); if (priv->reserved_mtts < 0) { - mlx4_warn(dev, "MTT table of order %d is too small.\n", + mlx4_warn(dev, "MTT table of order %u is too small.\n", mr_table->mtt_buddy.max_order); err = -ENOMEM; goto err_reserve_mtts; diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c index 9ee4725363d5..8e0c3cc2a1ec 100644 --- a/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -76,7 +76,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, u64 size; u64 start; int type; - int num; + u32 num; int log_num; }; @@ -105,7 +105,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, si_meminfo(&si); request->num_mtt = roundup_pow_of_two(max_t(unsigned, request->num_mtt, - min(1UL << 31, + min(1UL << (31 - log_mtts_per_seg), si.totalram >> (log_mtts_per_seg - 1)))); profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz; -- GitLab From 96f17d590092ae2511adf599a252e8ed1901b7a4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 14 Aug 2012 15:17:10 -0700 Subject: [PATCH 5475/5711] mlx4_core: Clean up buddy bitmap allocation - Use kcalloc() / vzalloc() instead of an extra bitmap_zero(). - Add __GFP_NOWARN to kcalloc() since we'll try vzalloc() if it fails. Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/mr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 44b8e1ea1cd8..c202d3ad2a0e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -121,7 +121,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) buddy->max_order = max_order; spin_lock_init(&buddy->lock); - buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), + buddy->bits = kcalloc(buddy->max_order + 1, sizeof (long *), GFP_KERNEL); buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free, GFP_KERNEL); @@ -130,13 +130,12 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) for (i = 0; i <= buddy->max_order; ++i) { s = BITS_TO_LONGS(1 << (buddy->max_order - i)); - buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); + buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN); if (!buddy->bits[i]) { - buddy->bits[i] = vmalloc(s * sizeof(long)); + buddy->bits[i] = vzalloc(s * sizeof(long)); if (!buddy->bits[i]) goto err_out_free; } - bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); } set_bit(0, buddy->bits[buddy->max_order]); -- GitLab From e862f1a9b7df4e8196ebec45ac62295138aa3fc2 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:44 +0000 Subject: [PATCH 5476/5711] atm: fix info leak in getsockopt(SO_ATMPVC) The ATM code fails to initialize the two padding bytes of struct sockaddr_atmpvc inserted for alignment. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller --- net/atm/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/atm/common.c b/net/atm/common.c index b4b44dbed645..0c0ad930a632 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -812,6 +812,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) return -ENOTCONN; + memset(&pvc, 0, sizeof(pvc)); pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = vcc->dev->number; pvc.sap_addr.vpi = vcc->vpi; -- GitLab From 3c0c5cfdcd4d69ffc4b9c0907cec99039f30a50a Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:45 +0000 Subject: [PATCH 5477/5711] atm: fix info leak via getsockname() The ATM code fails to initialize the two padding bytes of struct sockaddr_atmpvc inserted for alignment. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller --- net/atm/pvc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 3a734919c36c..ae0324021407 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -95,6 +95,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); addr = (struct sockaddr_atmpvc *)sockaddr; + memset(addr, 0, sizeof(*addr)); addr->sap_family = AF_ATMPVC; addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; -- GitLab From e15ca9a0ef9a86f0477530b0f44a725d67f889ee Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:46 +0000 Subject: [PATCH 5478/5711] Bluetooth: HCI - Fix info leak in getsockopt(HCI_FILTER) The HCI code fails to initialize the two padding bytes of struct hci_ufilter before copying it to userland -- that for leaking two bytes kernel stack. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/hci_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d79..a27bbc3cd4b7 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1009,6 +1009,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, { struct hci_filter *f = &hci_pi(sk)->filter; + memset(&uf, 0, sizeof(uf)); uf.type_mask = f->type_mask; uf.opcode = f->opcode; uf.event_mask[0] = *((u32 *) f->event_mask + 0); -- GitLab From 3f68ba07b1da811bf383b4b701b129bfcb2e4988 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:47 +0000 Subject: [PATCH 5479/5711] Bluetooth: HCI - Fix info leak via getsockname() The HCI code fails to initialize the hci_channel member of struct sockaddr_hci and that for leaks two bytes kernel stack via the getsockname() syscall. Initialize hci_channel with 0 to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/hci_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a27bbc3cd4b7..19fdac78e555 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -694,6 +694,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, *addr_len = sizeof(*haddr); haddr->hci_family = AF_BLUETOOTH; haddr->hci_dev = hdev->id; + haddr->hci_channel= 0; release_sock(sk); return 0; -- GitLab From 9ad2de43f1aee7e7274a4e0d41465489299e344b Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:48 +0000 Subject: [PATCH 5480/5711] Bluetooth: RFCOMM - Fix info leak in getsockopt(BT_SECURITY) The RFCOMM code fails to initialize the key_size member of struct bt_security before copying it to userland -- that for leaking one byte kernel stack. Initialize key_size with 0 to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/rfcomm/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c05..64f55ca61472 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -822,6 +822,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c } sec.level = rfcomm_pi(sk)->sec_level; + sec.key_size = 0; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) -- GitLab From f9432c5ec8b1e9a09b9b0e5569e3c73db8de432a Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:49 +0000 Subject: [PATCH 5481/5711] Bluetooth: RFCOMM - Fix info leak in ioctl(RFCOMMGETDEVLIST) The RFCOMM code fails to initialize the two padding bytes of struct rfcomm_dev_list_req inserted for alignment before copying it to userland. Additionally there are two padding bytes in each instance of struct rfcomm_dev_info. The ioctl() that for disclosures two bytes plus dev_num times two bytes uninitialized kernel heap memory. Allocate the memory using kzalloc() to fix this issue. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/rfcomm/tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index cb960773c002..56f182393c4c 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -456,7 +456,7 @@ static int rfcomm_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*di); - dl = kmalloc(size, GFP_KERNEL); + dl = kzalloc(size, GFP_KERNEL); if (!dl) return -ENOMEM; -- GitLab From 9344a972961d1a6d2c04d9008b13617bcb6ec2ef Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:50 +0000 Subject: [PATCH 5482/5711] Bluetooth: RFCOMM - Fix info leak via getsockname() The RFCOMM code fails to initialize the trailing padding byte of struct sockaddr_rc added for alignment. It that for leaks one byte kernel stack via the getsockname() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/rfcomm/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 64f55ca61472..1a17850d093c 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -528,6 +528,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * BT_DBG("sock %p, sk %p", sock, sk); + memset(sa, 0, sizeof(*sa)); sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) -- GitLab From 792039c73cf176c8e39a6e8beef2c94ff46522ed Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:51 +0000 Subject: [PATCH 5483/5711] Bluetooth: L2CAP - Fix info leak via getsockname() The L2CAP code fails to initialize the l2_bdaddr_type member of struct sockaddr_l2 and the padding byte added for alignment. It that for leaks two bytes kernel stack via the getsockname() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller --- net/bluetooth/l2cap_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b94abd30e6f9..1497edd191a2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -245,6 +245,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l BT_DBG("sock %p, sk %p", sock, sk); + memset(la, 0, sizeof(struct sockaddr_l2)); addr->sa_family = AF_BLUETOOTH; *len = sizeof(struct sockaddr_l2); -- GitLab From 04d4fbca1017c11381e7d82acea21dd741e748bc Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:52 +0000 Subject: [PATCH 5484/5711] l2tp: fix info leak via getsockname() The L2TP code for IPv6 fails to initialize the l2tp_unused member of struct sockaddr_l2tpip6 and that for leaks two bytes kernel stack via the getsockname() syscall. Initialize l2tp_unused with 0 to avoid the info leak. Signed-off-by: Mathias Krause Cc: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 35e1e4bde587..927547171bc7 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -410,6 +410,7 @@ static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr, lsa->l2tp_family = AF_INET6; lsa->l2tp_flowinfo = 0; lsa->l2tp_scope_id = 0; + lsa->l2tp_unused = 0; if (peer) { if (!lsk->peer_conn_id) return -ENOTCONN; -- GitLab From 3592aaeb80290bda0f2cf0b5456c97bfc638b192 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:53 +0000 Subject: [PATCH 5485/5711] llc: fix info leak via getsockname() The LLC code wrongly returns 0, i.e. "success", when the socket is zapped. Together with the uninitialized uaddrlen pointer argument from sys_getsockname this leads to an arbitrary memory leak of up to 128 bytes kernel stack via the getsockname() syscall. Return an error instead when the socket is zapped to prevent the info leak. Also remove the unnecessary memset(0). We don't directly write to the memory pointed by uaddr but memcpy() a local structure at the end of the function that is properly initialized. Signed-off-by: Mathias Krause Cc: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/llc/af_llc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 8c2919ca36f6..c2190005a114 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -969,14 +969,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_llc sllc; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = 0; + int rc = -EBADF; memset(&sllc, 0, sizeof(sllc)); lock_sock(sk); if (sock_flag(sk, SOCK_ZAPPED)) goto out; *uaddrlen = sizeof(sllc); - memset(uaddr, 0, *uaddrlen); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) -- GitLab From 276bdb82dedb290511467a5a4fdbe9f0b52dce6f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:54 +0000 Subject: [PATCH 5486/5711] dccp: check ccid before dereferencing ccid_hc_rx_getsockopt() and ccid_hc_tx_getsockopt() might be called with a NULL ccid pointer leading to a NULL pointer dereference. This could lead to a privilege escalation if the attacker is able to map page 0 and prepare it with a fake ccid_ops pointer. Signed-off-by: Mathias Krause Cc: Gerrit Renker Cc: stable@vger.kernel.org Signed-off-by: David S. Miller --- net/dccp/ccid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 75c3582a7678..fb85d371a8de 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; @@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; -- GitLab From 7b07f8eb75aa3097cdfd4f6eac3da49db787381d Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:55 +0000 Subject: [PATCH 5487/5711] dccp: fix info leak via getsockopt(DCCP_SOCKOPT_CCID_TX_INFO) The CCID3 code fails to initialize the trailing padding bytes of struct tfrc_tx_info added for alignment on 64 bit architectures. It that for potentially leaks four bytes kernel stack via the getsockopt() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/ccid3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index d65e98798eca..119c04317d48 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -535,6 +535,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, case DCCP_SOCKOPT_CCID_TX_INFO: if (len < sizeof(tfrc)) return -EINVAL; + memset(&tfrc, 0, sizeof(tfrc)); tfrc.tfrctx_x = hc->tx_x; tfrc.tfrctx_x_recv = hc->tx_x_recv; tfrc.tfrctx_x_calc = hc->tx_x_calc; -- GitLab From 2d8a041b7bfe1097af21441cb77d6af95f4f4680 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:56 +0000 Subject: [PATCH 5488/5711] ipvs: fix info leak in getsockopt(IP_VS_SO_GET_TIMEOUT) If at least one of CONFIG_IP_VS_PROTO_TCP or CONFIG_IP_VS_PROTO_UDP is not set, __ip_vs_get_timeouts() does not fully initialize the structure that gets copied to userland and that for leaks up to 12 bytes of kernel stack. Add an explicit memset(0) before passing the structure to __ip_vs_get_timeouts() to avoid the info leak. Signed-off-by: Mathias Krause Cc: Wensong Zhang Cc: Simon Horman Cc: Julian Anastasov Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_ctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 84444dda194b..72bf32a84874 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2759,6 +2759,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; + memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; -- GitLab From 43da5f2e0d0c69ded3d51907d9552310a6b545e8 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:57 +0000 Subject: [PATCH 5489/5711] net: fix info leak in compat dev_ifconf() The implementation of dev_ifconf() for the compat ioctl interface uses an intermediate ifc structure allocated in userland for the duration of the syscall. Though, it fails to initialize the padding bytes inserted for alignment and that for leaks four bytes of kernel stack. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller --- net/socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/socket.c b/net/socket.c index dfe5b66c97e0..a5471f804d99 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2657,6 +2657,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) return -EFAULT; + memset(&ifc, 0, sizeof(ifc)); if (ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; -- GitLab From e9ba389c5ffc4dd29dfe17e00e48877302111135 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Aug 2012 12:32:00 +0200 Subject: [PATCH 5490/5711] ALSA: usb-audio: Fix scheduling-while-atomic bug in PCM capture stream A PCM capture stream on usb-audio causes a scheduling-while-atomic BUG, as reported in the bugzilla entry below. It's because snd_usb_endpoint_start() is called at first at trigger START for a capture stream, and this function contains the left-over EP deactivation codes. The problem doesn't happen for a playback stream because the function is called at PCM prepare time, which can sleep. This patch fixes the BUG by moving the EP deactivation code into the PCM prepare callback. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46011 Cc: [v3.5+] Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 4 ---- sound/usb/pcm.c | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 0f647d22cb4a..c41181202688 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -821,10 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (++ep->use_count != 1) return 0; - /* just to be sure */ - deactivate_urbs(ep, 0, 1); - wait_clear_urbs(ep); - ep->active_mask = 0; ep->unlink_mask = 0; ep->phase = 0; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index a1298f379428..62ec808ed792 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -544,6 +544,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->last_frame_number = 0; runtime->delay = 0; + /* clear the pending deactivation on the target EPs */ + deactivate_endpoints(subs); + /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) -- GitLab From 667a5313ecd7308d79629c0738b0db588b0b0a4e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2012 16:46:12 +1000 Subject: [PATCH 5491/5711] md: Don't truncate size at 4TB for RAID0 and Linear commit 27a7b260f71439c40546b43588448faac01adb93 md: Fix handling for devices from 2TB to 4TB in 0.90 metadata. changed 0.90 metadata handling to truncated size to 4TB as that is all that 0.90 can record. However for RAID0 and Linear, 0.90 doesn't need to record the size, so this truncation is not needed and causes working arrays to become too small. So avoid the truncation for RAID0 and Linear This bug was introduced in 3.1 and is suitable for any stable kernels from then onwards. As the offending commit was tagged for 'stable', any stable kernel that it was applied to should also get this patch. That includes at least 2.6.32, 2.6.33 and 3.0. (Thanks to Ben Hutchings for providing that list). Cc: stable@vger.kernel.org Signed-off-by: Neil Brown --- drivers/md/md.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index fcd098794d37..3f6203a4c7ea 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1108,8 +1108,11 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ret = 0; } rdev->sectors = rdev->sb_start; - /* Limit to 4TB as metadata cannot record more than that */ - if (rdev->sectors >= (2ULL << 32)) + /* Limit to 4TB as metadata cannot record more than that. + * (not needed for Linear and RAID0 as metadata doesn't + * record this size) + */ + if (rdev->sectors >= (2ULL << 32) && sb->level >= 1) rdev->sectors = (2ULL << 32) - 2; if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) @@ -1400,7 +1403,7 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) /* Limit to 4TB as metadata cannot record more than that. * 4TB == 2^32 KB, or 2*2^32 sectors. */ - if (num_sectors >= (2ULL << 32)) + if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1) num_sectors = (2ULL << 32) - 2; md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); -- GitLab From 2614f86490122bf51eb7c12ec73927f1900f4e7d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Aug 2012 02:25:24 +0200 Subject: [PATCH 5492/5711] netfilter: nf_ct_expect: fix possible access to uninitialized timer In __nf_ct_expect_check, the function refresh_timer returns 1 if a matching expectation is found and its timer is successfully refreshed. This results in nf_ct_expect_related returning 0. Note that at this point: - the passed expectation is not inserted in the expectation table and its timer was not initialized, since we have refreshed one matching/existing expectation. - nf_ct_expect_alloc uses kmem_cache_alloc, so the expectation timer is in some undefined state just after the allocation, until it is appropriately initialized. This can be a problem for the SIP helper during the expectation addition: ... if (nf_ct_expect_related(rtp_exp) == 0) { if (nf_ct_expect_related(rtcp_exp) != 0) nf_ct_unexpect_related(rtp_exp); ... Note that nf_ct_expect_related(rtp_exp) may return 0 for the timer refresh case that is detailed above. Then, if nf_ct_unexpect_related(rtcp_exp) returns != 0, nf_ct_unexpect_related(rtp_exp) is called, which does: spin_lock_bh(&nf_conntrack_lock); if (del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); } spin_unlock_bh(&nf_conntrack_lock); Note that del_timer always returns false if the timer has been initialized. However, the timer was not initialized since setup_timer was not called, therefore, the expectation timer remains in some undefined state. If I'm not missing anything, this may lead to the removal an unexistent expectation. To fix this, the optimization that allows refreshing an expectation is removed. Now nf_conntrack_expect_related looks more consistent to me since it always add the expectation in case that it returns success. Thanks to Patrick McHardy for participating in the discussion of this patch. I think this may be the source of the problem described by: http://marc.info/?l=netfilter-devel&m=134073514719421&w=2 Reported-by: Rafal Fitt Acked-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_expect.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 45cf602a76bc..527651a53a45 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -361,23 +361,6 @@ static void evict_oldest_expect(struct nf_conn *master, } } -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ - struct nf_conn_help *master_help = nfct_help(i->master); - const struct nf_conntrack_expect_policy *p; - - if (!del_timer(&i->timeout)) - return 0; - - p = &rcu_dereference_protected( - master_help->helper, - lockdep_is_held(&nf_conntrack_lock) - )->expect_policy[i->class]; - i->timeout.expires = jiffies + p->timeout * HZ; - add_timer(&i->timeout); - return 1; -} - static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) { const struct nf_conntrack_expect_policy *p; @@ -386,7 +369,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) struct nf_conn_help *master_help = nfct_help(master); struct nf_conntrack_helper *helper; struct net *net = nf_ct_exp_net(expect); - struct hlist_node *n; + struct hlist_node *n, *next; unsigned int h; int ret = 1; @@ -395,12 +378,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) goto out; } h = nf_ct_expect_dst_hash(&expect->tuple); - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { if (expect_matches(i, expect)) { - /* Refresh timer: if it's dying, ignore.. */ - if (refresh_timer(i)) { - ret = 0; - goto out; + if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_ct_expect_put(i); + break; } } else if (expect_clash(i, expect)) { ret = -EBUSY; -- GitLab From 5e68fb3cab23b327e9f15803607e697d7eea1966 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 16 Aug 2012 14:11:09 +0200 Subject: [PATCH 5493/5711] ALSA: hda - Don't send invalid volume knob command on IDT 92hd75bxx Instead of blindly initializing a volume knob widget, first check that there actually is a volume knob widget. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 94040ccf8e8f..ea5775a1a7db 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4272,7 +4272,8 @@ static int stac92xx_init(struct hda_codec *codec) unsigned int gpio; int i; - snd_hda_sequence_write(codec, spec->init); + if (spec->init) + snd_hda_sequence_write(codec, spec->init); /* power down adcs initially */ if (spec->powerdown_adcs) @@ -5748,7 +5749,6 @@ again: /* fallthru */ case 0x111d76b4: /* 6 Port without Analog Mixer */ case 0x111d76b5: - spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92xx_connected_ports(codec, stac92hd71bxx_dmic_nids, @@ -5773,7 +5773,6 @@ again: spec->stream_delay = 40; /* 40 milliseconds */ /* disable VSW */ - spec->init = stac92hd71bxx_core_init; unmute_init++; snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); @@ -5788,7 +5787,6 @@ again: /* fallthru */ default: - spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92xx_connected_ports(codec, stac92hd71bxx_dmic_nids, @@ -5796,6 +5794,9 @@ again: break; } + if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) + spec->init = stac92hd71bxx_core_init; + if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) snd_hda_sequence_write_cache(codec, unmute_init); -- GitLab From a0675a386a3a68f71e831bd064082e6717b45fdc Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Fri, 10 Aug 2012 18:25:34 +0000 Subject: [PATCH 5494/5711] IB/mlx4: Check iboe netdev pointer before dereferencing it Unlike other parts of the mlx4_ib code, the function build_mlx_header() doesn't check if the iboe netdev of the given port is valid before dereferencing it, which can cause a crash if the ethernet interface has already been taken down. Fix this by checking for a valid netdev pointer before using it to get the port MAC address. Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/qp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index a6d8ea060ea8..f585eddef4b7 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1407,6 +1407,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, struct mlx4_wqe_mlx_seg *mlx = wqe; struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); + struct net_device *ndev; union ib_gid sgid; u16 pkey; int send_size; @@ -1483,7 +1484,10 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6); /* FIXME: cache smac value? */ - smac = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]->dev_addr; + ndev = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]; + if (!ndev) + return -ENODEV; + smac = ndev->dev_addr; memcpy(sqp->ud_header.eth.smac_h, smac, 6); if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); -- GitLab From 3e8309551777e2a54367daddb65b53e236754374 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 16:25:33 +0300 Subject: [PATCH 5495/5711] mei: fix device stall after wd is stopped After watchdog was disabled the driver would stall due to wrong calculation of credits reduction The cat&paste bug was introduced in the commit 7bdf72d3d8059a50214069ea4b87c2174645f40f mei: introduce mei_data2slots wrapper Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index c6ffbbe5a6c0..d78c05e693f7 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1253,7 +1253,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, if (dev->wd_timeout) *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); else - *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); + *slots -= mei_data2slots(MEI_WD_PARAMS_SIZE); } } if (dev->stop) -- GitLab From 731879f8e3d4c61220462160311fa650a8b96abf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Jul 2012 14:26:07 -0500 Subject: [PATCH 5496/5711] USB: qcserial: fix port handling on Gobi 1K and 2K+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bjorn's latest patchset does break Gobi 1K and 2K because on both devices as it claims usb interface 0. That's because usbif 0 is not handled in the switch statement, and thus the if0 gets claimed when it should not. So let's just make things even simpler yet, and handle both the 1K and 2K+ cases separately. This patch should not affect the new Sierra device support, because those devices are matched via interface-specific matching and thus should never hit the composite code. Signed-off-by: Dan Williams Tested-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 314ae8ceba41..bfd50779f0c9 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -199,43 +199,49 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) /* default to enabling interface */ altsetting = 0; - switch (ifnum) { - /* Composite mode; don't bind to the QMI/net interface as that - * gets handled by other drivers. - */ + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ + + if (is_gobi1k) { /* Gobi 1K USB layout: * 0: serial port (doesn't respond) * 1: serial port (doesn't respond) * 2: AT-capable modem port * 3: QMI/net - * - * Gobi 2K+ USB layout: + */ + if (ifnum == 2) + dev_dbg(dev, "Modem port found\n"); + else + altsetting = -1; + } else { + /* Gobi 2K+ USB layout: * 0: QMI/net * 1: DM/DIAG (use libqcdm from ModemManager for communication) * 2: AT-capable modem port * 3: NMEA */ - - case 1: - if (is_gobi1k) + switch (ifnum) { + case 0: + /* Don't claim the QMI/net interface */ altsetting = -1; - else + break; + case 1: dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n"); - break; - case 2: - dev_dbg(dev, "Modem port found\n"); - break; - case 3: - if (is_gobi1k) - altsetting = -1; - else + break; + case 2: + dev_dbg(dev, "Modem port found\n"); + break; + case 3: /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); + break; + } } done: -- GitLab From af7f2158fdee9d7f55b793b09f8170a3391f889a Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Thu, 19 Jul 2012 13:46:21 -0600 Subject: [PATCH 5497/5711] drivers-core: make structured logging play nice with dynamic-debug commit c4e00daaa96d3a0786f1f4fe6456281c60ef9a16 changed __dev_printk in a way that broke dynamic-debug's ability to control the dynamic prefix of dev_dbg(dev,..), but not dev_dbg(NULL,..) or pr_debug(..), which is why it wasnt noticed sooner. When dev==NULL, __dev_printk() just calls printk(), which just works. But otherwise, it assumed that level was always a string like "" and just plucked out the 'L', ignoring the rest. However, dynamic_emit_prefix() adds "[tid] module:func:line:" to the string, those additions all got lost. Signed-off-by: Jim Cromie Acked-by: Jason Baron Cc: stable Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index f338037a4f3d..cdd01c52c629 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1865,6 +1865,7 @@ int __dev_printk(const char *level, const struct device *dev, struct va_format *vaf) { char dict[128]; + const char *level_extra = ""; size_t dictlen = 0; const char *subsys; @@ -1911,10 +1912,14 @@ int __dev_printk(const char *level, const struct device *dev, "DEVICE=+%s:%s", subsys, dev_name(dev)); } skip: + if (level[3]) + level_extra = &level[3]; /* skip past "" */ + return printk_emit(0, level[1] - '0', dictlen ? dict : NULL, dictlen, - "%s %s: %pV", - dev_driver_string(dev), dev_name(dev), vaf); + "%s %s: %s%pV", + dev_driver_string(dev), dev_name(dev), + level_extra, vaf); } EXPORT_SYMBOL(__dev_printk); -- GitLab From 7b7e995d69199b555181ac057c47b017c510a129 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Jul 2012 09:26:57 +0800 Subject: [PATCH 5498/5711] extcon: extcon_gpio: Replace gpio_request_one by devm_gpio_request_one commit 01eaf24 "extcon: Convert extcon_gpio to devm_gpio_request_one" missed the replacement for devm_gpio_request_one. fix it. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon_gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c index fe3db45fa83c..3cc152e690b0 100644 --- a/drivers/extcon/extcon_gpio.c +++ b/drivers/extcon/extcon_gpio.c @@ -107,7 +107,8 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) if (ret < 0) return ret; - ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); + ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, + pdev->name); if (ret < 0) goto err; -- GitLab From 62b2ce964bb901f00a480104bd35a2e1f8d2cf58 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 15 Aug 2012 13:30:12 -0700 Subject: [PATCH 5499/5711] vfs: fix propagation of atomic_open create error on negative dentry If ->atomic_open() returns -ENOENT, we take care to return the create error (e.g., EACCES), if any. Do the same when ->atomic_open() returns 1 and provides a negative dentry. This fixes a regression where an unprivileged open O_CREAT fails with ENOENT instead of EACCES, introduced with the new atomic_open code. It is tested by the open/08.t test in the pjd posix test suite, and was observed on top of fuse (backed by ceph-fuse). Signed-off-by: Sage Weil Signed-off-by: Miklos Szeredi --- fs/namei.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index 26c28ec4f4af..db76b866a097 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2489,6 +2489,10 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, dput(dentry); dentry = file->f_path.dentry; } + if (create_error && dentry->d_inode == NULL) { + error = create_error; + goto out; + } goto looked_up; } -- GitLab From a2f6985332d2564e443d9d889ce70f39b3293d09 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 6 Aug 2012 15:23:55 +0300 Subject: [PATCH 5500/5711] mei: add mei_quirk_probe function The main purpose of this function is to exclude ME devices without support for MEI/HECI interface from binding Currently affected systems are C600/X79 based servers that expose PCI device even though it doesn't supported ME Interface. MEI driver accessing such nonfunctional device can corrupt the system. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 092330208869..7422c7652845 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -924,6 +924,27 @@ static struct miscdevice mei_misc_device = { .minor = MISC_DYNAMIC_MINOR, }; +/** + * mei_quirk_probe - probe for devices that doesn't valid ME interface + * @pdev: PCI device structure + * @ent: entry into pci_device_table + * + * returns true if ME Interface is valid, false otherwise + */ +static bool __devinit mei_quirk_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + u32 reg; + if (ent->device == MEI_DEV_ID_PBG_1) { + pci_read_config_dword(pdev, 0x48, ®); + /* make sure that bit 9 is up and bit 10 is down */ + if ((reg & 0x600) == 0x200) { + dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); + return false; + } + } + return true; +} /** * mei_probe - Device Initialization Routine * @@ -939,6 +960,12 @@ static int __devinit mei_probe(struct pci_dev *pdev, int err; mutex_lock(&mei_mutex); + + if (!mei_quirk_probe(pdev, ent)) { + err = -ENODEV; + goto end; + } + if (mei_device) { err = -EEXIST; goto end; -- GitLab From 2a95e37c128d1c12b3cb0eb6dfdc1739a7104cd8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 15 Aug 2012 13:00:51 +0200 Subject: [PATCH 5501/5711] scripts/decodecode: Fixup trapping instruction marker When dumping "Code: " sections from an oops, the trapping instruction %rip points to can be a string copy 2b:* f3 a5 rep movsl %ds:(%rsi),%es:(%rdi) and the line contain a bunch of ":". Current "cut" selects only the and the second field output looks funnily overlaid this: 2b:* f3 a5 rep movsl %ds <-- trapping instruction:(%rsi),%es:(%rdi Fix this by selecting the remaining fields too. Cc: Andrew Morton Cc: Linus Torvalds Cc: linux-kbuild@vger.kernel.org Signed-off-by: Borislav Petkov Signed-off-by: Linus Torvalds --- scripts/decodecode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/decodecode b/scripts/decodecode index 18ba881c3415..4f8248d5a11f 100755 --- a/scripts/decodecode +++ b/scripts/decodecode @@ -89,7 +89,7 @@ echo $code >> $T.s disas $T cat $T.dis >> $T.aa -faultline=`cat $T.dis | head -1 | cut -d":" -f2` +faultline=`cat $T.dis | head -1 | cut -d":" -f2-` faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'` cat $T.oo | sed -e "s/\($faultline\)/\*\1 <-- trapping instruction/g" -- GitLab From a1d95cfc07d637e024027101a691dad5b0eef27a Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 16 Aug 2012 11:19:11 -0600 Subject: [PATCH 5502/5711] staging: comedi: usbduxsigma: Declare MODULE_FIRMWARE usage Cc: Ian Abbott Cc: Mori Hess Cc: Bernd Porr Cc: Dan Carpenter Cc: H Hartley Sweeten Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 543e604791e2..f54ab8c2fcfd 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -63,6 +63,7 @@ Status: testing #define BULK_TIMEOUT 1000 /* constants for "firmware" upload and download */ +#define FIRMWARE "usbduxsigma_firmware.bin" #define USBDUXSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -2780,7 +2781,7 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "usbduxsigma_firmware.bin", + FIRMWARE, &udev->dev, GFP_KERNEL, usbduxsub + index, @@ -2845,3 +2846,4 @@ module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); -- GitLab From 1e1ccc3ad6ebe720e14dd9787f6b5cebaf46f573 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 16 Aug 2012 11:15:37 -0600 Subject: [PATCH 5503/5711] staging: comedi: usbdux: Declare MODULE_FIRMWARE usage Cc: Ian Abbott Cc: Mori Hess Cc: H Hartley Sweeten Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 848c7ec06976..11ee83681da7 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -102,6 +102,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define BULK_TIMEOUT 1000 /* constants for "firmware" upload and download */ +#define FIRMWARE "usbdux_firmware.bin" #define USBDUXSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -2791,7 +2792,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "usbdux_firmware.bin", + FIRMWARE, &udev->dev, GFP_KERNEL, usbduxsub + index, @@ -2850,3 +2851,4 @@ module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); -- GitLab From e74f7fc5d85c5c0bedb69913e2a10774ddb6f367 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 16 Aug 2012 11:09:28 -0600 Subject: [PATCH 5504/5711] staging: comedi: usbduxfast: Declare MODULE_FIRMWARE usage Cc: Ian Abbott Cc: Mori Hess Cc: H Hartley Sweeten Cc: Ravishankar Karkala Mallikarjunayya Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxfast.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index d9911588c10a..8eb41257c6ce 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -57,6 +57,7 @@ /* * constants for "firmware" upload and download */ +#define FIRMWARE "usbduxfast_firmware.bin" #define USBDUXFASTSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -1706,7 +1707,7 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "usbduxfast_firmware.bin", + FIRMWARE, &udev->dev, GFP_KERNEL, usbduxfastsub + index, @@ -1774,3 +1775,4 @@ module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); -- GitLab From 1dd8372d350583b0acc8d7cfd7a1dee05e1942dc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 15 Aug 2012 19:20:02 -0700 Subject: [PATCH 5505/5711] MAINTAINERS: update address for Dan Williams Moved to djbw@fb.com Cc: Dave Jiang Cc: Vinod Koul Signed-off-by: Dan Williams Signed-off-by: Linus Torvalds --- MAINTAINERS | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f87589075552..61ad79ea2b08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -827,24 +827,24 @@ F: arch/arm/mach-pxa/colibri-pxa270-income.c ARM/INTEL IOP32X ARM ARCHITECTURE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IOP33X ARM ARCHITECTURE -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IOP13XX ARM ARCHITECTURE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IQ81342EX MACHINE SUPPORT M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -869,7 +869,7 @@ F: drivers/pcmcia/pxa2xx_stargate2.c ARM/INTEL XSC3 (MANZANO) ARM CORE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -1232,9 +1232,9 @@ S: Maintained F: drivers/hwmon/asb100.c ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API -M: Dan Williams +M: Dan Williams W: http://sourceforge.net/projects/xscaleiop -S: Supported +S: Maintained F: Documentation/crypto/async-tx-api.txt F: crypto/async_tx/ F: drivers/dma/ @@ -2364,7 +2364,7 @@ T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git DMA GENERIC OFFLOAD ENGINE SUBSYSTEM M: Vinod Koul -M: Dan Williams +M: Dan Williams S: Supported F: drivers/dma/ F: include/linux/dma* @@ -3552,7 +3552,6 @@ K: \b(ABS|SYN)_MT_ INTEL C600 SERIES SAS CONTROLLER DRIVER M: Intel SCU Linux support -M: Dan Williams M: Dave Jiang M: Ed Nadolski L: linux-scsi@vger.kernel.org @@ -3595,8 +3594,8 @@ F: arch/x86/kernel/microcode_core.c F: arch/x86/kernel/microcode_intel.c INTEL I/OAT DMA DRIVER -M: Dan Williams -S: Supported +M: Dan Williams +S: Maintained F: drivers/dma/ioat* INTEL IOMMU (VT-d) @@ -3608,8 +3607,8 @@ F: drivers/iommu/intel-iommu.c F: include/linux/intel-iommu.h INTEL IOP-ADMA DMA DRIVER -M: Dan Williams -S: Maintained +M: Dan Williams +S: Odd fixes F: drivers/dma/iop-adma.c INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT -- GitLab From a45440f05e9ebc26f2a375df911823fdef5b5281 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 6 Aug 2012 09:37:47 +0800 Subject: [PATCH 5506/5711] autofs4 - fix get_next_positive_subdir() Following a report of a crash during an automount expire I found that the locking in fs/autofs4/expire.c:get_next_positive_subdir() was wrong. Not only is the locking wrong but the function is more complex than it needs to be. The function is meant to calculate (and dget) the next entry in the list of directories contained in the root of an autofs mount point (an autofs indirect mount to be precise). The main problem was that the d_lock of the owner of the list was not being taken when walking the list, which lead to list corruption under load. The only other lock that needs to be taken is against the next dentry candidate so it can be checked for usability. Signed-off-by: Ian Kent Signed-off-by: Linus Torvalds --- fs/autofs4/expire.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 1feb68ecef95..8c0e56d92938 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -94,25 +94,21 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, { struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); struct list_head *next; - struct dentry *p, *q; + struct dentry *q; spin_lock(&sbi->lookup_lock); + spin_lock(&root->d_lock); - if (prev == NULL) { - spin_lock(&root->d_lock); + if (prev) + next = prev->d_u.d_child.next; + else { prev = dget_dlock(root); next = prev->d_subdirs.next; - p = prev; - goto start; } - p = prev; - spin_lock(&p->d_lock); -again: - next = p->d_u.d_child.next; -start: +cont: if (next == &root->d_subdirs) { - spin_unlock(&p->d_lock); + spin_unlock(&root->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); return NULL; @@ -121,16 +117,15 @@ start: q = list_entry(next, struct dentry, d_u.d_child); spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); - /* Negative dentry - try next */ - if (!simple_positive(q)) { - spin_unlock(&p->d_lock); - lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_); - p = q; - goto again; + /* Already gone or negative dentry (under construction) - try next */ + if (q->d_count == 0 || !simple_positive(q)) { + spin_unlock(&q->d_lock); + next = q->d_u.d_child.next; + goto cont; } dget_dlock(q); spin_unlock(&q->d_lock); - spin_unlock(&p->d_lock); + spin_unlock(&root->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); -- GitLab From 00592021010ad86d3b26bac7034034f6af145a2c Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 8 Aug 2012 10:37:59 +0800 Subject: [PATCH 5507/5711] serial: mxs-auart: fix the wrong RTS hardware flow control Without checking if the auart supports the hardware flow control or not, the old mxs_auart_set_mctrl() asserted the RTS pin blindly. This will causes the auart receives wrong data in the following case: The far-end has already started the write operation, and wait for the auart asserts the RTS pin. Then the auart starts the read operation, but mxs_auart_set_mctrl() may be called before we set the RTSCTS in the mxs_auart_settermios(). So the RTS pin is asserted in a wrong situation, and we get the wrong data in the end. This bug has been catched when I connect the mx23(DTE) to the mx53(DCE). This patch also replaces the AUART_CTRL2_RTS with AUART_CTRL2_RTSEN. We should use the real the hardware flow control, not the software-controled hardware flow control. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 2e341b81ff89..3a667eed63d6 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -73,6 +73,7 @@ #define AUART_CTRL0_CLKGATE (1 << 30) #define AUART_CTRL2_CTSEN (1 << 15) +#define AUART_CTRL2_RTSEN (1 << 14) #define AUART_CTRL2_RTS (1 << 11) #define AUART_CTRL2_RXE (1 << 9) #define AUART_CTRL2_TXE (1 << 8) @@ -259,9 +260,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) u32 ctrl = readl(u->membase + AUART_CTRL2); - ctrl &= ~AUART_CTRL2_RTS; - if (mctrl & TIOCM_RTS) - ctrl |= AUART_CTRL2_RTS; + ctrl &= ~AUART_CTRL2_RTSEN; + if (mctrl & TIOCM_RTS) { + if (u->state->port.flags & ASYNC_CTS_FLOW) + ctrl |= AUART_CTRL2_RTSEN; + } + s->ctrl = mctrl; writel(ctrl, u->membase + AUART_CTRL2); } @@ -359,9 +363,9 @@ static void mxs_auart_settermios(struct uart_port *u, /* figure out the hardware flow control settings */ if (cflag & CRTSCTS) - ctrl2 |= AUART_CTRL2_CTSEN; + ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN; else - ctrl2 &= ~AUART_CTRL2_CTSEN; + ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN); /* set baud rate */ baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); -- GitLab From 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 12 Aug 2012 07:16:43 -0500 Subject: [PATCH 5508/5711] pmac_zilog,kdb: Fix console poll hook to return instead of loop kdb <-> kgdb transitioning does not work properly with this UART driver because the get character routine loops indefinitely as opposed to returning NO_POLL_CHAR per the expectation of the KDB I/O driver API. The symptom is a kernel hang when trying to switch debug modes. Cc: Alan Cox Signed-off-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 654755a990df..333c8d012b0e 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser) static int pmz_poll_get_char(struct uart_port *port) { struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + int tries = 2; - while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) - udelay(5); - return read_zsdata(uap); + while (tries) { + if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) + return read_zsdata(uap); + if (tries--) + udelay(5); + } + + return NO_POLL_CHAR; } static void pmz_poll_put_char(struct uart_port *port, unsigned char c) -- GitLab From dfffd0d65fdf16d034681716dcbea74776f62e40 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 16 Jul 2012 09:42:00 +0100 Subject: [PATCH 5509/5711] iio: staging: ad7298_ring: Fix maybe-uninitialized warning drivers/staging/iio/adc/ad7298_ring.c:97:37: warning: 'time_ns' may be used uninitialized in this function [-Wmaybe-uninitialized] Reported-by: Fengguang Wu Signed-off-by: Michael Hennerich Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7298_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index fd1d855ff57a..506016f01593 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -76,7 +76,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct ad7298_state *st = iio_priv(indio_dev); struct iio_buffer *ring = indio_dev->buffer; - s64 time_ns; + s64 time_ns = 0; __u16 buf[16]; int b_sent, i; -- GitLab From 8857df3aceb7a8eb7558059b7da109e41dd1fb95 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 20 Jul 2012 09:31:00 +0100 Subject: [PATCH 5510/5711] iio: frequency: ADF4350: Fix potential reference div factor overflow. With small channel spacing values and high reference frequencies it is possible to exceed the range of the 10-bit counter. Workaround by checking the range and widening some constrains. We don't use the REG1_PHASE value in this case the datasheet recommends to set it to 1 if not used. Signed-off-by: Michael Hennerich Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/adf4350.c | 24 +++++++++++++++--------- include/linux/iio/frequency/adf4350.h | 2 ++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 59fbb3ae40e7..e35bb8f6fe75 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -129,7 +129,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) { struct adf4350_platform_data *pdata = st->pdata; u64 tmp; - u32 div_gcd, prescaler; + u32 div_gcd, prescaler, chspc; u16 mdiv, r_cnt = 0; u8 band_sel_div; @@ -158,14 +158,20 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) if (pdata->ref_div_factor) r_cnt = pdata->ref_div_factor - 1; - do { - r_cnt = adf4350_tune_r_cnt(st, r_cnt); + chspc = st->chspc; - st->r1_mod = st->fpfd / st->chspc; - while (st->r1_mod > ADF4350_MAX_MODULUS) { - r_cnt = adf4350_tune_r_cnt(st, r_cnt); - st->r1_mod = st->fpfd / st->chspc; - } + do { + do { + do { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / chspc; + if (r_cnt > ADF4350_MAX_R_CNT) { + /* try higher spacing values */ + chspc++; + r_cnt = 0; + } + } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); + } while (r_cnt == 0); tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ @@ -194,7 +200,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | ADF4350_REG0_FRACT(st->r0_fract); - st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(1) | ADF4350_REG1_MOD(st->r1_mod) | prescaler; diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h index b76b4a87065e..be91f344d5fc 100644 --- a/include/linux/iio/frequency/adf4350.h +++ b/include/linux/iio/frequency/adf4350.h @@ -87,6 +87,8 @@ #define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ #define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ #define ADF4350_MAX_MODULUS 4095 +#define ADF4350_MAX_R_CNT 1023 + /** * struct adf4350_platform_data - platform specific information -- GitLab From 1c795ebd00042b3a5c97e049fd1c08763714a7a8 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 10:58:00 +0100 Subject: [PATCH 5511/5711] iio/adjd_s311: Fix potential memory leak in adjd_s311_update_scan_mode() Do not leak memory by updating pointer with potentially NULL realloc return value. There is no need to preserve data in the buffer, so replace krealloc() by kfree()-kmalloc() pair. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/adjd_s311.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 1cbb449b319a..9a99f43094f0 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -271,9 +271,10 @@ static int adjd_s311_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { struct adjd_s311_data *data = iio_priv(indio_dev); - data->buffer = krealloc(data->buffer, indio_dev->scan_bytes, - GFP_KERNEL); - if (!data->buffer) + + kfree(data->buffer); + data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (data->buffer == NULL) return -ENOMEM; return 0; -- GitLab From 421afe5805cbeda35097dc2ea36b9f6f077b4858 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5512/5711] staging:iio:ad7793: Add missing break in switch statement Without the break statement we fall right through to the default case and return an error value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 76fdd7145fc5..1d0cd09be86e 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -676,7 +676,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, } ret = 0; } - + break; default: ret = -EINVAL; } -- GitLab From e83539092c390c95e30b0d9e434709f195340f80 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5513/5711] staging:iio:ad7793: Mark channels as unsigned The values reported by the AD7793 are unsigned. In uniploar mode: 0x000000 is zeroscale 0xffffff is fullscale In bipolar mode: 0x000000 is negative fullscale 0x800000 is zeroscale 0xffffff is positive fullscale In bipolar mode there is a binary offset, but the values are still unsigned. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 1d0cd09be86e..5e457a4b4232 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -722,7 +722,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 0, - .scan_type = IIO_ST('s', 24, 32, 0) + .scan_type = IIO_ST('u', 24, 32, 0) }, .channel[1] = { .type = IIO_VOLTAGE, @@ -734,7 +734,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 1, - .scan_type = IIO_ST('s', 24, 32, 0) + .scan_type = IIO_ST('u', 24, 32, 0) }, .channel[2] = { .type = IIO_VOLTAGE, @@ -746,7 +746,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, - .scan_type = IIO_ST('s', 24, 32, 0) + .scan_type = IIO_ST('u', 24, 32, 0) }, .channel[3] = { .type = IIO_VOLTAGE, @@ -759,7 +759,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 3, - .scan_type = IIO_ST('s', 24, 32, 0) + .scan_type = IIO_ST('u', 24, 32, 0) }, .channel[4] = { .type = IIO_TEMP, @@ -769,7 +769,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 4, - .scan_type = IIO_ST('s', 24, 32, 0), + .scan_type = IIO_ST('u', 24, 32, 0), }, .channel[5] = { .type = IIO_VOLTAGE, @@ -780,7 +780,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 5, - .scan_type = IIO_ST('s', 24, 32, 0), + .scan_type = IIO_ST('u', 24, 32, 0), }, .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, @@ -795,7 +795,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 0, - .scan_type = IIO_ST('s', 16, 32, 0) + .scan_type = IIO_ST('u', 16, 32, 0) }, .channel[1] = { .type = IIO_VOLTAGE, @@ -807,7 +807,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 1, - .scan_type = IIO_ST('s', 16, 32, 0) + .scan_type = IIO_ST('u', 16, 32, 0) }, .channel[2] = { .type = IIO_VOLTAGE, @@ -819,7 +819,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, - .scan_type = IIO_ST('s', 16, 32, 0) + .scan_type = IIO_ST('u', 16, 32, 0) }, .channel[3] = { .type = IIO_VOLTAGE, @@ -832,7 +832,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 3, - .scan_type = IIO_ST('s', 16, 32, 0) + .scan_type = IIO_ST('u', 16, 32, 0) }, .channel[4] = { .type = IIO_TEMP, @@ -842,7 +842,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 4, - .scan_type = IIO_ST('s', 16, 32, 0), + .scan_type = IIO_ST('u', 16, 32, 0), }, .channel[5] = { .type = IIO_VOLTAGE, @@ -853,7 +853,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 5, - .scan_type = IIO_ST('s', 16, 32, 0), + .scan_type = IIO_ST('u', 16, 32, 0), }, .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, -- GitLab From 680f8ea0e85c5c3a7283be99435d6461e8725348 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5514/5711] staging:iio:ad7793: Report channel offset In bipolar mode there is a a binary offset of 2**(N-1) (with N being the number of bits) on the reported value. Currently this value is subtracted when doing a manual read. While this works for manual channel readings it does not work for buffered mode. So report the offset in the channels offset property, which will work in both modes. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 39 +++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 5e457a4b4232..56014a8b6876 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -604,9 +604,6 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, *val = (smpl >> chan->scan_type.shift) & ((1 << (chan->scan_type.realbits)) - 1); - if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); - return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -639,6 +636,12 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, *val = scale_uv; return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_OFFSET: + if (!unipolar) + *val -= (1 << (chan->scan_type.realbits - 1)); + else + *val = 0; + return IIO_VAL_INT; } return -EINVAL; } @@ -720,7 +723,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 0, .address = AD7793_CH_AIN1P_AIN1M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 0, .scan_type = IIO_ST('u', 24, 32, 0) }, @@ -732,7 +736,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 1, .address = AD7793_CH_AIN2P_AIN2M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 1, .scan_type = IIO_ST('u', 24, 32, 0) }, @@ -744,7 +749,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 2, .address = AD7793_CH_AIN3P_AIN3M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('u', 24, 32, 0) }, @@ -757,7 +763,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 2, .address = AD7793_CH_AIN1M_AIN1M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 3, .scan_type = IIO_ST('u', 24, 32, 0) }, @@ -778,7 +785,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 4, .address = AD7793_CH_AVDD_MONITOR, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 5, .scan_type = IIO_ST('u', 24, 32, 0), }, @@ -793,7 +801,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 0, .address = AD7793_CH_AIN1P_AIN1M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 0, .scan_type = IIO_ST('u', 16, 32, 0) }, @@ -805,7 +814,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 1, .address = AD7793_CH_AIN2P_AIN2M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 1, .scan_type = IIO_ST('u', 16, 32, 0) }, @@ -817,7 +827,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 2, .address = AD7793_CH_AIN3P_AIN3M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('u', 16, 32, 0) }, @@ -830,7 +841,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel2 = 2, .address = AD7793_CH_AIN1M_AIN1M, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 3, .scan_type = IIO_ST('u', 16, 32, 0) }, @@ -851,7 +863,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 4, .address = AD7793_CH_AVDD_MONITOR, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_index = 5, .scan_type = IIO_ST('u', 16, 32, 0), }, -- GitLab From 2a9e0662f6779d2074ecaa80ea5753d5f0cf1b93 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5515/5711] staging:iio:ad7793: Fix temperature scale and offset The temperature channel uses the internal 1.17V reference with 0.81 mv/C. The reported temperature is in Kevlin, so we need to add the Kelvin to Celcius offset when reporting the offset for the temperature channel. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 56014a8b6876..3c8d1d4c6192 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -617,30 +617,37 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; } else { /* 1170mV / 2^23 * 6 */ - scale_uv = (1170ULL * 100000000ULL * 6ULL) - >> (chan->scan_type.realbits - - (unipolar ? 0 : 1)); + scale_uv = (1170ULL * 100000000ULL * 6ULL); } break; case IIO_TEMP: - /* Always uses unity gain and internal ref */ - scale_uv = (2500ULL * 100000000ULL) - >> (chan->scan_type.realbits - - (unipolar ? 0 : 1)); + /* 1170mV / 0.81 mV/C / 2^23 */ + scale_uv = 1444444444444ULL; break; default: return -EINVAL; } - *val2 = do_div(scale_uv, 100000000) * 10; - *val = scale_uv; - + scale_uv >>= (chan->scan_type.realbits - (unipolar ? 0 : 1)); + *val = 0; + *val2 = scale_uv; return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_OFFSET: if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); + *val = -(1 << (chan->scan_type.realbits - 1)); else *val = 0; + + /* Kelvin to Celsius */ + if (chan->type == IIO_TEMP) { + unsigned long long offset; + unsigned int shift; + + shift = chan->scan_type.realbits - (unipolar ? 0 : 1); + offset = 273ULL << shift; + do_div(offset, 1444); + *val -= offset; + } return IIO_VAL_INT; } return -EINVAL; -- GitLab From 08ca3b78505b4fba1e782ae9266bfaf878e4bdd1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5516/5711] staging:iio:ad7793: Follow new IIO naming spec Make the "in-in_scale_available" attribute follow the new naming spec and rename it to "in_voltage-voltage_scale_available". Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 3c8d1d4c6192..91cb95c67635 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -563,8 +563,9 @@ static ssize_t ad7793_show_scale_available(struct device *dev, return len; } -static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, - S_IRUGO, ad7793_show_scale_available, NULL, 0); +static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, + in_voltage-voltage_scale_available, S_IRUGO, + ad7793_show_scale_available, NULL, 0); static struct attribute *ad7793_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, -- GitLab From 87a0c1574d2fd478c24e841c96f5019e5b44762f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5517/5711] staging:iio:ad7793: Fix internal reference value The internal reference for the ad7793 and similar is 1.17V Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7793.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 91cb95c67635..112e2b7b5bc4 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -922,7 +922,7 @@ static int __devinit ad7793_probe(struct spi_device *spi) else if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else - st->int_vref_mv = 2500; /* Build-in ref */ + st->int_vref_mv = 1170; /* Build-in ref */ spi_set_drvdata(spi, indio_dev); st->spi = spi; -- GitLab From f09906f43b8a0d52e3321db7d6f9d031097b0bc9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5518/5711] staging:iio:ad7192: Add missing break in switch statement Without the break statement we fall right through to the default case and return an error value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 22c3923d55eb..b9a74425ff75 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -890,7 +890,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, } ret = 0; } - + break; default: ret = -EINVAL; } -- GitLab From 74aa933894e1c32376a8372ec8264b8c6f7faf24 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5519/5711] staging:iio:ad7192: Fix setting ACX Write to the correct register when setting the ACX bit. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index b9a74425ff75..0a1bc6a31d02 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -754,7 +754,7 @@ static ssize_t ad7192_set(struct device *dev, else st->mode &= ~AD7192_MODE_ACX; - ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); + ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); break; default: ret = -EINVAL; -- GitLab From a684a0c711d384665b43f9079a035e52a2761eab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5520/5711] staging:iio:ad7192: Mark channels as unsigned The values reported by the AD7793 are unsigned. In uniploar mode: 0x000000 is zeroscale 0xffffff is fullscale In bipolar mode: 0x000000 is negative fullscale 0x800000 is zeroscale 0xffffff is positive fullscale In bipolar mode there is a binary offset, but the values are still unsigned. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 0a1bc6a31d02..7ba699486326 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -945,7 +945,7 @@ static const struct iio_info ad7195_info = { IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} + .scan_type = IIO_ST('u', 24, 32, 0)} #define AD7192_CHAN(_chan, _address, _si) \ { .type = IIO_VOLTAGE, \ @@ -955,7 +955,7 @@ static const struct iio_info ad7195_info = { IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} + .scan_type = IIO_ST('u', 24, 32, 0)} #define AD7192_CHAN_TEMP(_chan, _address, _si) \ { .type = IIO_TEMP, \ @@ -965,7 +965,7 @@ static const struct iio_info ad7195_info = { IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ .address = _address, \ .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} + .scan_type = IIO_ST('u', 24, 32, 0)} static struct iio_chan_spec ad7192_channels[] = { AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), -- GitLab From 58cdff6ee71b4ea00a6b822a52ebf9ceb0b6a7d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5521/5711] staging:iio:ad7192: Report channel offset In bipolar mode there is a a binary offset of 2**(N-1) (with N being the number of bits) on the reported value. Currently this value is subtracted when doing a manual read. While this works for manual channel readings it does not work for buffered mode. So report the offset in the channels offset property, which will work in both modes. Signed-off-by: Lars-Peter Clausen --- drivers/staging/iio/adc/ad7192.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 7ba699486326..73483d26a034 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -826,8 +826,6 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_VOLTAGE: - if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); break; case IIO_TEMP: *val -= 0x800000; @@ -853,6 +851,12 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_OFFSET: + if (!unipolar) + *val -= (1 << (chan->scan_type.realbits - 1)); + else + *val = 0; + return IIO_VAL_INT; } return -EINVAL; @@ -942,7 +946,8 @@ static const struct iio_info ad7195_info = { .channel = _chan, \ .channel2 = _chan2, \ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ .scan_type = IIO_ST('u', 24, 32, 0)} @@ -952,7 +957,8 @@ static const struct iio_info ad7195_info = { .indexed = 1, \ .channel = _chan, \ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ .scan_type = IIO_ST('u', 24, 32, 0)} -- GitLab From 4fcbcf95b775acc430742a09fb3334dce08b6c10 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5522/5711] staging:iio:ad7192: Report offset and scale for temperature channel The temperature channel reports values in degree Kelvin with sensitivity of 5630 codes per degree. If the chip is configured in bipolar mode there is an additional binary offset of 0x800000 and the sensitivity is divided by two. Currently the driver does the mapping from the raw value to degree Celsius when doing a manual conversion. This has several disadvantages, the major one being that it does not work for buffered mode, also by doing the division by the sensitivity in the driver the precession of the reported value is needlessly reduced. Furthermore the current calculation only works in bipolar mode and the current scale is of by a factor of 1000. This patch modifies the driver to report correct offset and scale values in both unipolar and bipolar mode and to report the raw temperature value for manual conversions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 73483d26a034..095837285f4f 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -798,6 +798,11 @@ static const struct attribute_group ad7195_attribute_group = { .attrs = ad7195_attributes, }; +static unsigned int ad7192_get_temp_scale(bool unipolar) +{ + return unipolar ? 2815 * 2 : 2815; +} + static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -824,17 +829,6 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val = (smpl >> chan->scan_type.shift) & ((1 << (chan->scan_type.realbits)) - 1); - switch (chan->type) { - case IIO_VOLTAGE: - break; - case IIO_TEMP: - *val -= 0x800000; - *val /= 2815; /* temp Kelvin */ - *val -= 273; /* temp Celsius */ - break; - default: - return -EINVAL; - } return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -846,16 +840,20 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT_PLUS_NANO; case IIO_TEMP: - *val = 1000; - return IIO_VAL_INT; + *val = 0; + *val2 = 1000000000 / ad7192_get_temp_scale(unipolar); + return IIO_VAL_INT_PLUS_NANO; default: return -EINVAL; } case IIO_CHAN_INFO_OFFSET: if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); + *val = -(1 << (chan->scan_type.realbits - 1)); else *val = 0; + /* Kelvin to Celsius */ + if (chan->type == IIO_TEMP) + *val -= 273 * ad7192_get_temp_scale(unipolar); return IIO_VAL_INT; } -- GitLab From 70e01880a9b2c548d3911d0eed467d664aad5986 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Aug 2012 17:36:00 +0100 Subject: [PATCH 5523/5711] staging:iio:ad7780: Mark channels as unsigned The values reported by the AD7780 are unsigned with a binary offset: 0x000000 is negative fullscale 0x800000 is zeroscale 0xffffff is positive fullscale So mark the channel in the channel spec as unsigned rather than signed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7780.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index 1ece2ac8de56..19ee49c95de4 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -131,9 +131,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { .indexed = 1, .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_type = { - .sign = 's', + .sign = 'u', .realbits = 24, .storagebits = 32, .shift = 8, @@ -146,9 +147,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { .indexed = 1, .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT, .scan_type = { - .sign = 's', + .sign = 'u', .realbits = 20, .storagebits = 32, .shift = 12, -- GitLab From 95d1c8c7e26e303ccab5b65fe0ce04f70f42ea8a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 2 Aug 2012 11:10:00 +0100 Subject: [PATCH 5524/5711] iio: lm3533-als: Fix build warnings Fix below build warnings: CC [M] drivers/iio/light/lm3533-als.o drivers/iio/light/lm3533-als.c:667:8: warning: initialization from incompatible pointer type [enabled by default] drivers/iio/light/lm3533-als.c:667:8: warning: (near initialization for 'dev_attr_in_illuminance0_thresh_either_en.show') [enabled by default] drivers/iio/light/lm3533-als.c:667:8: warning: initialization from incompatible pointer type [enabled by default] drivers/iio/light/lm3533-als.c:667:8: warning: (near initialization for 'dev_attr_in_illuminance0_thresh_either_en.store') [enabled by default] Signed-off-by: Axel Lin --- drivers/iio/light/lm3533-als.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index c3e7bac13123..e45712a921ce 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -404,7 +404,7 @@ out: return ret; } -static int show_thresh_either_en(struct device *dev, +static ssize_t show_thresh_either_en(struct device *dev, struct device_attribute *attr, char *buf) { @@ -424,7 +424,7 @@ static int show_thresh_either_en(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%u\n", enable); } -static int store_thresh_either_en(struct device *dev, +static ssize_t store_thresh_either_en(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { -- GitLab From f3d9d365ff7f36c4e3491ef31788449f419b781b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 2 Aug 2012 22:17:48 +0200 Subject: [PATCH 5525/5711] ti-st: Fix check for pdata->chip_awake function pointer ll_device_want_to_wakeup(): Fix the NULL pointer check on pdata->chip_awake, which is performed on the wrong function pointer Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_ll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c index 1ff460a8e9c7..93b4d67cc4a3 100644 --- a/drivers/misc/ti-st/st_ll.c +++ b/drivers/misc/ti-st/st_ll.c @@ -87,7 +87,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data) /* communicate to platform about chip wakeup */ kim_data = st_data->kim_data; pdata = kim_data->kim_pdev->dev.platform_data; - if (pdata->chip_asleep) + if (pdata->chip_awake) pdata->chip_awake(NULL); } -- GitLab From f3261dfb5538e2ff0264fde3050dbd4e922fa296 Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Thu, 16 Aug 2012 12:56:40 -0400 Subject: [PATCH 5526/5711] 1-Wire: Add support for the maxim ds1825 temperature sensor This patch adds support for maxim ds1825 based 1-wire temperature sensors. Signed-off-by: Raphael Assenat Signed-off-by: Greg Kroah-Hartman --- Documentation/w1/slaves/w1_therm | 2 ++ drivers/w1/slaves/w1_therm.c | 9 +++++++++ drivers/w1/w1_family.h | 1 + 3 files changed, 12 insertions(+) diff --git a/Documentation/w1/slaves/w1_therm b/Documentation/w1/slaves/w1_therm index 0403aaaba878..874a8ca93feb 100644 --- a/Documentation/w1/slaves/w1_therm +++ b/Documentation/w1/slaves/w1_therm @@ -3,6 +3,7 @@ Kernel driver w1_therm Supported chips: * Maxim ds18*20 based temperature sensors. + * Maxim ds1825 based temperature sensors. Author: Evgeniy Polyakov @@ -15,6 +16,7 @@ supported family codes: W1_THERM_DS18S20 0x10 W1_THERM_DS1822 0x22 W1_THERM_DS18B20 0x28 +W1_THERM_DS1825 0x3B Support is provided through the sysfs w1_slave file. Each open and read sequence will initiate a temperature conversion then provide two diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index d90062b211f8..92d08e7fcba2 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -91,6 +91,11 @@ static struct w1_family w1_therm_family_DS28EA00 = { .fops = &w1_therm_fops, }; +static struct w1_family w1_therm_family_DS1825 = { + .fid = W1_THERM_DS1825, + .fops = &w1_therm_fops, +}; + struct w1_therm_family_converter { u8 broken; @@ -120,6 +125,10 @@ static struct w1_therm_family_converter w1_therm_families[] = { .f = &w1_therm_family_DS28EA00, .convert = w1_DS18B20_convert_temp }, + { + .f = &w1_therm_family_DS1825, + .convert = w1_DS18B20_convert_temp + } }; static inline int w1_DS18B20_convert_temp(u8 rom[9]) diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index b00ada44a89b..a1f0ce151d53 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -39,6 +39,7 @@ #define W1_EEPROM_DS2431 0x2D #define W1_FAMILY_DS2760 0x30 #define W1_FAMILY_DS2780 0x32 +#define W1_THERM_DS1825 0x3B #define W1_FAMILY_DS2781 0x3D #define W1_THERM_DS28EA00 0x42 -- GitLab From 1ae811ee27912a0521e4b92dc9a1850c0243a247 Mon Sep 17 00:00:00 2001 From: "bjschuma@gmail.com" Date: Wed, 8 Aug 2012 13:57:06 -0400 Subject: [PATCH 5527/5711] NFS: Fix a regression when loading the NFS v4 module Some systems have a modprobe.d/nfs.conf file that sets an nfs4 alias pointing to nfs.ko, rather than nfs4.ko. This can prevent the v4 module from loading on mount, since the kernel sees that something named "nfs4" has already been loaded. To work around this, I've renamed the modules to "nfsv2.ko" "nfsv3.ko" and "nfsv4.ko". I also had to move the nfs4_fs_type back to nfs.ko to ensure that `mount -t nfs4` still works. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/Makefile | 18 +++++++++--------- fs/nfs/client.c | 2 +- fs/nfs/nfs4_fs.h | 3 +++ fs/nfs/nfs4super.c | 15 --------------- fs/nfs/super.c | 37 ++++++++++++++++++++++++++++++++++++- 5 files changed, 49 insertions(+), 26 deletions(-) diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 8bf3a3f6925a..b7db60897f91 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -12,19 +12,19 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o nfs-$(CONFIG_SYSCTL) += sysctl.o nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o -obj-$(CONFIG_NFS_V2) += nfs2.o -nfs2-y := nfs2super.o proc.o nfs2xdr.o +obj-$(CONFIG_NFS_V2) += nfsv2.o +nfsv2-y := nfs2super.o proc.o nfs2xdr.o -obj-$(CONFIG_NFS_V3) += nfs3.o -nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o -nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o +obj-$(CONFIG_NFS_V3) += nfsv3.o +nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o +nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o -obj-$(CONFIG_NFS_V4) += nfs4.o -nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ +obj-$(CONFIG_NFS_V4) += nfsv4.o +nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o nfs4getroot.o nfs4client.o -nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o -nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o +nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o +nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 9fc0d9dfc91b..99694442b93f 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -105,7 +105,7 @@ struct nfs_subversion *get_nfs_version(unsigned int version) if (IS_ERR(nfs)) { mutex_lock(&nfs_version_mutex); - request_module("nfs%d", version); + request_module("nfsv%d", version); nfs = find_nfs_version(version); mutex_unlock(&nfs_version_mutex); } diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 3b950dd81e81..da0618aeeadb 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -205,6 +205,9 @@ extern const struct dentry_operations nfs4_dentry_operations; int nfs_atomic_open(struct inode *, struct dentry *, struct file *, unsigned, umode_t, int *); +/* super.c */ +extern struct file_system_type nfs4_fs_type; + /* nfs4namespace.c */ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 12a31a9dbcdd..bd61221ad2c5 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -23,14 +23,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); -static struct file_system_type nfs4_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs_fs_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, -}; - static struct file_system_type nfs4_remote_fs_type = { .owner = THIS_MODULE, .name = "nfs4", @@ -344,14 +336,8 @@ static int __init init_nfs_v4(void) if (err) goto out1; - err = register_filesystem(&nfs4_fs_type); - if (err < 0) - goto out2; - register_nfs_version(&nfs_v4); return 0; -out2: - nfs4_unregister_sysctl(); out1: nfs_idmap_quit(); out: @@ -361,7 +347,6 @@ out: static void __exit exit_nfs_v4(void) { unregister_nfs_version(&nfs_v4); - unregister_filesystem(&nfs4_fs_type); nfs4_unregister_sysctl(); nfs_idmap_quit(); } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ac6a3c55dce4..c4a15c55519c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -319,6 +319,34 @@ EXPORT_SYMBOL_GPL(nfs_sops); static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); static int nfs4_validate_mount_data(void *options, struct nfs_parsed_mount_data *args, const char *dev_name); + +struct file_system_type nfs4_fs_type = { + .owner = THIS_MODULE, + .name = "nfs4", + .mount = nfs_fs_mount, + .kill_sb = nfs_kill_super, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; +EXPORT_SYMBOL_GPL(nfs4_fs_type); + +static int __init register_nfs4_fs(void) +{ + return register_filesystem(&nfs4_fs_type); +} + +static void unregister_nfs4_fs(void) +{ + unregister_filesystem(&nfs4_fs_type); +} +#else +static int __init register_nfs4_fs(void) +{ + return 0; +} + +static void unregister_nfs4_fs(void) +{ +} #endif static struct shrinker acl_shrinker = { @@ -337,12 +365,18 @@ int __init register_nfs_fs(void) if (ret < 0) goto error_0; - ret = nfs_register_sysctl(); + ret = register_nfs4_fs(); if (ret < 0) goto error_1; + + ret = nfs_register_sysctl(); + if (ret < 0) + goto error_2; register_shrinker(&acl_shrinker); return 0; +error_2: + unregister_nfs4_fs(); error_1: unregister_filesystem(&nfs_fs_type); error_0: @@ -356,6 +390,7 @@ void __exit unregister_nfs_fs(void) { unregister_shrinker(&acl_shrinker); nfs_unregister_sysctl(); + unregister_nfs4_fs(); unregister_filesystem(&nfs_fs_type); } -- GitLab From 425e776d93a7a5070b77d4f458a5bab0f924652c Mon Sep 17 00:00:00 2001 From: "bjschuma@gmail.com" Date: Wed, 8 Aug 2012 13:57:10 -0400 Subject: [PATCH 5528/5711] NFS: Alias the nfs module to nfs4 This allows distros to remove the line from their modprobe configuration. Signed-off-by: Bryan Schumaker Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust --- fs/nfs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index c4a15c55519c..239aff7338eb 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2680,4 +2680,6 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " module_param(send_implementation_id, ushort, 0644); MODULE_PARM_DESC(send_implementation_id, "Send implementation ID with NFSv4.1 exchange_id"); +MODULE_ALIAS("nfs4"); + #endif /* CONFIG_NFS_V4 */ -- GitLab From 519d3959e30a98f8e135e7a16647c10af5ad63d5 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 14 Aug 2012 17:30:10 -0400 Subject: [PATCH 5529/5711] NFSv4: Fix pointer arithmetic in decode_getacl Resetting the cursor xdr->p to a previous value is not a safe practice: if the xdr_stream has crossed out of the initial iovec, then a bunch of other fields would need to be reset too. Fix this issue by using xdr_enter_page() so that the buffer gets page aligned at the bitmap _before_ we decode it. Also fix the confusion of the ACL length with the page buffer length by not adding the base offset to the ACL length... Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org --- fs/nfs/nfs4proc.c | 2 +- fs/nfs/nfs4xdr.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c77d296bdaa6..286ab7078413 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3819,7 +3819,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu if (ret) goto out_free; - acl_len = res.acl_len - res.acl_data_offset; + acl_len = res.acl_len; if (acl_len > args.acl_len) nfs4_write_cached_acl(inode, NULL, 0, acl_len); else diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index ca13483edd60..54d3f5a9faa6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -5049,18 +5049,14 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, uint32_t attrlen, bitmap[3] = {0}; int status; - size_t page_len = xdr->buf->page_len; res->acl_len = 0; if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) goto out; + xdr_enter_page(xdr, xdr->buf->page_len); + bm_p = xdr->p; - res->acl_data_offset = be32_to_cpup(bm_p) + 2; - res->acl_data_offset <<= 2; - /* Check if the acl data starts beyond the allocated buffer */ - if (res->acl_data_offset > page_len) - return -ERANGE; if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) goto out; @@ -5074,23 +5070,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, /* The bitmap (xdr len + bitmaps) and the attr xdr len words * are stored with the acl data to handle the problem of * variable length bitmaps.*/ - xdr->p = bm_p; + res->acl_data_offset = (xdr->p - bm_p) << 2; /* We ignore &savep and don't do consistency checks on * the attr length. Let userspace figure it out.... */ - attrlen += res->acl_data_offset; - if (attrlen > page_len) { + res->acl_len = attrlen; + if (attrlen + res->acl_data_offset > xdr->buf->page_len) { if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { /* getxattr interface called with a NULL buf */ - res->acl_len = attrlen; goto out; } - dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", - attrlen, page_len); + dprintk("NFS: acl reply: attrlen %u > page_len %u\n", + attrlen, xdr->buf->page_len); return -EINVAL; } - xdr_read_pages(xdr, attrlen); - res->acl_len = attrlen; } else status = -EOPNOTSUPP; -- GitLab From b291f1b1c86aa0c7bc3df2994e6a1a4e53f1fde0 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 14 Aug 2012 18:30:41 -0400 Subject: [PATCH 5530/5711] NFSv4: Fix the acl cache size calculation Currently, we do not take into account the size of the 16 byte struct nfs4_cached_acl header, when deciding whether or not we should cache the acl data. Consequently, we will end up allocating an 8k buffer in order to fit a maximum size 4k acl. This patch adjusts the calculation so that we limit the cache size to 4k for the acl header+data. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 286ab7078413..635274140b18 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3737,9 +3737,10 @@ out: static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) { struct nfs4_cached_acl *acl; + size_t buflen = sizeof(*acl) + acl_len; - if (pages && acl_len <= PAGE_SIZE) { - acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); + if (pages && buflen <= PAGE_SIZE) { + acl = kmalloc(buflen, GFP_KERNEL); if (acl == NULL) goto out; acl->cached = 1; -- GitLab From cff298c721099c9ac4cea7196a37097ba2847946 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 14 Aug 2012 17:14:17 -0400 Subject: [PATCH 5531/5711] NFSv4: Don't use private xdr_stream fields in decode_getacl Instead of using the private field xdr->p from struct xdr_stream, use the public xdr_stream_pos(). Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 54d3f5a9faa6..1bfbd67c556d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -5045,10 +5045,10 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_getaclres *res) { unsigned int savep; - __be32 *bm_p; uint32_t attrlen, bitmap[3] = {0}; int status; + unsigned int pg_offset; res->acl_len = 0; if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) @@ -5056,7 +5056,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, xdr_enter_page(xdr, xdr->buf->page_len); - bm_p = xdr->p; + /* Calculate the offset of the page data */ + pg_offset = xdr->buf->head[0].iov_len; if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) goto out; @@ -5070,18 +5071,18 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, /* The bitmap (xdr len + bitmaps) and the attr xdr len words * are stored with the acl data to handle the problem of * variable length bitmaps.*/ - res->acl_data_offset = (xdr->p - bm_p) << 2; + res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; /* We ignore &savep and don't do consistency checks on * the attr length. Let userspace figure it out.... */ res->acl_len = attrlen; - if (attrlen + res->acl_data_offset > xdr->buf->page_len) { + if (attrlen > (xdr->nwords << 2)) { if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { /* getxattr interface called with a NULL buf */ goto out; } dprintk("NFS: acl reply: attrlen %u > page_len %u\n", - attrlen, xdr->buf->page_len); + attrlen, xdr->nwords << 2); return -EINVAL; } } else -- GitLab From c5066945b7ea346a11424dbeb7830b7d7d00c206 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 9 Aug 2012 14:05:49 -0400 Subject: [PATCH 5532/5711] NFS: Clear key construction data if the idmap upcall fails idmap_pipe_downcall already clears this field if the upcall succeeds, but if it fails (rpc.idmapd isn't running) the field will still be set on the next call triggering a BUG_ON(). This patch tries to handle all possible ways that the upcall could fail and clear the idmap key data for each one. Signed-off-by: Bryan Schumaker Tested-by: William Dauchy Cc: stable@vger.kernel.org [>= 3.4] Signed-off-by: Trond Myklebust --- fs/nfs/idmap.c | 56 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b701358c39c3..6703c73307a5 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -61,6 +61,12 @@ struct idmap { struct mutex idmap_mutex; }; +struct idmap_legacy_upcalldata { + struct rpc_pipe_msg pipe_msg; + struct idmap_msg idmap_msg; + struct idmap *idmap; +}; + /** * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * @fattr: fully initialised struct nfs_fattr @@ -324,6 +330,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, name, namelen, type, data, data_size, idmap); + idmap->idmap_key_cons = NULL; mutex_unlock(&idmap->idmap_mutex); } return ret; @@ -380,11 +387,13 @@ static const match_table_t nfs_idmap_tokens = { static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); static ssize_t idmap_pipe_downcall(struct file *, const char __user *, size_t); +static void idmap_release_pipe(struct inode *); static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); static const struct rpc_pipe_ops idmap_upcall_ops = { .upcall = rpc_pipe_generic_upcall, .downcall = idmap_pipe_downcall, + .release_pipe = idmap_release_pipe, .destroy_msg = idmap_pipe_destroy_msg, }; @@ -616,7 +625,8 @@ void nfs_idmap_quit(void) nfs_idmap_quit_keyring(); } -static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, +static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, + struct idmap_msg *im, struct rpc_pipe_msg *msg) { substring_t substr; @@ -659,6 +669,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, const char *op, void *aux) { + struct idmap_legacy_upcalldata *data; struct rpc_pipe_msg *msg; struct idmap_msg *im; struct idmap *idmap = (struct idmap *)aux; @@ -666,15 +677,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, int ret = -ENOMEM; /* msg and im are freed in idmap_pipe_destroy_msg */ - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (!msg) - goto out0; - - im = kmalloc(sizeof(*im), GFP_KERNEL); - if (!im) + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) goto out1; - ret = nfs_idmap_prepare_message(key->description, im, msg); + msg = &data->pipe_msg; + im = &data->idmap_msg; + data->idmap = idmap; + + ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); if (ret < 0) goto out2; @@ -683,15 +694,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, ret = rpc_queue_upcall(idmap->idmap_pipe, msg); if (ret < 0) - goto out2; + goto out3; return ret; +out3: + idmap->idmap_key_cons = NULL; out2: - kfree(im); + kfree(data); out1: - kfree(msg); -out0: complete_request_key(cons, ret); return ret; } @@ -775,9 +786,26 @@ out_incomplete: static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) { + struct idmap_legacy_upcalldata *data = container_of(msg, + struct idmap_legacy_upcalldata, + pipe_msg); + struct idmap *idmap = data->idmap; + struct key_construction *cons; + if (msg->errno) { + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + complete_request_key(cons, msg->errno); + } /* Free memory allocated in nfs_idmap_legacy_upcall() */ - kfree(msg->data); - kfree(msg); + kfree(data); +} + +static void +idmap_release_pipe(struct inode *inode) +{ + struct rpc_inode *rpci = RPC_I(inode); + struct idmap *idmap = (struct idmap *)rpci->private; + idmap->idmap_key_cons = NULL; } int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) -- GitLab From 12dfd080556124088ed61a292184947711b46cbe Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 9 Aug 2012 14:05:50 -0400 Subject: [PATCH 5533/5711] NFS: return -ENOKEY when the upcall fails to map the name This allows the normal error-paths to handle the error, rather than making a special call to complete_request_key() just for this instance. Signed-off-by: Bryan Schumaker Tested-by: William Dauchy Cc: stable@vger.kernel.org [>= 3.4] Signed-off-by: Trond Myklebust --- fs/nfs/idmap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 6703c73307a5..a850079467d8 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -760,9 +760,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { - ret = mlen; - complete_request_key(cons, -ENOKEY); - goto out_incomplete; + ret = -ENOKEY; + goto out; } namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); @@ -779,7 +778,6 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) out: complete_request_key(cons, ret); -out_incomplete: return ret; } -- GitLab From d9875690d9b89a866022ff49e3fcea892345ad92 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Aug 2012 14:51:24 -0700 Subject: [PATCH 5534/5711] Linux 3.6-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ddf5be952e45..9cc77acfc881 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- GitLab From 16c0b164bd24d44db137693a36b428ba28970c62 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 15 Aug 2012 20:44:27 +0000 Subject: [PATCH 5535/5711] act_mirred: do not drop packets when fails to mirror it We drop packet unconditionally when we fail to mirror it. This is not intended in some cases. Consdier for kvm guest, we may mirror the traffic of the bridge to a tap device used by a VM. When kernel fails to mirror the packet in conditions such as when qemu crashes or stop polling the tap, it's hard for the management software to detect such condition and clean the the mirroring before. This would lead all packets to the bridge to be dropped and break the netowrk of other virtual machines. To solve the issue, the patch does not drop packets when kernel fails to mirror it, and only drop the redirected packets. Signed-off-by: Jason Wang Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/act_mirred.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fe81cc18e9e0..9c0fd0c78814 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -200,13 +200,12 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, out: if (err) { m->tcf_qstats.overlimits++; - /* should we be asking for packet to be dropped? - * may make sense for redirect case only - */ - retval = TC_ACT_SHOT; - } else { + if (m->tcfm_eaction != TCA_EGRESS_MIRROR) + retval = TC_ACT_SHOT; + else + retval = m->tcf_action; + } else retval = m->tcf_action; - } spin_unlock(&m->tcf_lock); return retval; -- GitLab From f796c20cf67aa54c9130d0dc41307c0025719b85 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 14 Aug 2012 12:34:24 +0000 Subject: [PATCH 5536/5711] net: netprio: fix files lock and remove useless d_path bits Add lock to prevent a race with a file closing and also remove useless and ugly sscanf code. The extra code was never needed and the case it supposedly protected against is in fact handled correctly by sock_from_file as pointed out by Al Viro. CC: Neil Horman Reported-by: Al Viro Signed-off-by: John Fastabend Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/netprio_cgroup.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index ed0c0431fcd8..f65dba3afd99 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -277,12 +277,6 @@ out_free_devname: void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) { struct task_struct *p; - char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); - - if (!tmp) { - pr_warn("Unable to attach cgrp due to alloc failure!\n"); - return; - } cgroup_taskset_for_each(p, cgrp, tset) { unsigned int fd; @@ -296,32 +290,24 @@ void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) continue; } - rcu_read_lock(); + spin_lock(&files->file_lock); fdt = files_fdtable(files); for (fd = 0; fd < fdt->max_fds; fd++) { - char *path; struct file *file; struct socket *sock; - unsigned long s; - int rv, err = 0; + int err; file = fcheck_files(files, fd); if (!file) continue; - path = d_path(&file->f_path, tmp, PAGE_SIZE); - rv = sscanf(path, "socket:[%lu]", &s); - if (rv <= 0) - continue; - sock = sock_from_file(file, &err); - if (!err) + if (sock) sock_update_netprioidx(sock->sk, p); } - rcu_read_unlock(); + spin_unlock(&files->file_lock); task_unlock(p); } - kfree(tmp); } static struct cftype ss_files[] = { -- GitLab From 48a87cc26c13b68f6cce4e9d769fcb17a6b3e4b8 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 14 Aug 2012 12:34:30 +0000 Subject: [PATCH 5537/5711] net: netprio: fd passed in SCM_RIGHTS datagram not set correctly A socket fd passed in a SCM_RIGHTS datagram was not getting updated with the new tasks cgrp prioidx. This leaves IO on the socket tagged with the old tasks priority. To fix this add a check in the scm recvmsg path to update the sock cgrp prioidx with the new tasks value. Thanks to Al Viro for catching this. CC: Neil Horman Reported-by: Al Viro Signed-off-by: John Fastabend Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/scm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/scm.c b/net/core/scm.c index 8f6ccfd68ef4..040cebeed45b 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -265,6 +265,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); isk, current); fd_install(new_fd, fp[i]); } -- GitLab From 476ad154f3b41dd7d9a08a2f641e28388abc2fd1 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 14 Aug 2012 12:34:35 +0000 Subject: [PATCH 5538/5711] net: netprio: fix cgrp create and write priomap race A race exists where creating cgroups and also updating the priomap may result in losing a priomap update. This is because priomap writers are not protected by rtnl_lock. Move priority writer into rtnl_lock()/rtnl_unlock(). CC: Neil Horman Reported-by: Al Viro Signed-off-by: John Fastabend Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/netprio_cgroup.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index f65dba3afd99..c75e3f9d060f 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -101,12 +101,10 @@ static int write_update_netdev_table(struct net_device *dev) u32 max_len; struct netprio_map *map; - rtnl_lock(); max_len = atomic_read(&max_prioidx) + 1; map = rtnl_dereference(dev->priomap); if (!map || map->priomap_len < max_len) ret = extend_netdev_table(dev, max_len); - rtnl_unlock(); return ret; } @@ -256,17 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, if (!dev) goto out_free_devname; + rtnl_lock(); ret = write_update_netdev_table(dev); if (ret < 0) goto out_put_dev; - rcu_read_lock(); - map = rcu_dereference(dev->priomap); + map = rtnl_dereference(dev->priomap); if (map) map->priomap[prioidx] = priority; - rcu_read_unlock(); out_put_dev: + rtnl_unlock(); dev_put(dev); out_free_devname: -- GitLab From e7d6582e04212943d23d6e42b86ede5d9a0ebe04 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Fri, 3 Aug 2012 16:08:36 +1000 Subject: [PATCH 5539/5711] m68knommu: select CONFIG_HAVE_CLK for ColdFire CPU types The ColdFire CPU sub-arch has kernel clk code support, so select CONFIG_HAVE_CLK. Signed-off-by: Greg Ungerer --- arch/m68k/Kconfig.cpu | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 82068349a2bb..59eb9f359809 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -28,6 +28,7 @@ config COLDFIRE select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM + select HAVE_CLK endchoice -- GitLab From 42b1b94635a467407841c89e91d9209c55f6bc61 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 14 Aug 2012 14:31:33 +1000 Subject: [PATCH 5540/5711] m68k: select CONFIG_GENERIC_ATOMIC64 for all m68k CPU types There is no specific atomic64 support code for any m68k CPUs, so we should select CONFIG_GENERIC_ATOMC64 for all. Remove the existing per CPU selection of this and select it for all m68k. Signed-off-by: Greg Ungerer Acked-by: Fengguang Wu Acked-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 1 + arch/m68k/Kconfig.cpu | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 4a469907f04a..b22df9410dce 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -5,6 +5,7 @@ config M68K select HAVE_AOUT if MMU select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW + select GENERIC_ATOMIC64 select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select GENERIC_CPU_DEVICES select GENERIC_STRNCPY_FROM_USER if MMU diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 59eb9f359809..c4eb79edecec 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -59,7 +59,6 @@ config MCPU32 config M68020 bool "68020 support" depends on MMU - select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68020 @@ -70,7 +69,6 @@ config M68020 config M68030 bool "68030 support" depends on MMU && !MMU_SUN3 - select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68030 @@ -80,7 +78,6 @@ config M68030 config M68040 bool "68040 support" depends on MMU && !MMU_SUN3 - select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68LC040 @@ -91,7 +88,6 @@ config M68040 config M68060 bool "68060 support" depends on MMU && !MMU_SUN3 - select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68060 -- GitLab From f0e0e9bba5eed2086f6001be14f21566a49bed10 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Mon, 30 Jul 2012 13:19:07 -0700 Subject: [PATCH 5541/5711] tcm_vhost: Fix incorrect IS_ERR() usage in vhost_scsi_map_iov_to_sgl Fix up a new coccinelle warnings reported by Fengguang Wu + Intel 0-DAY kernel build testing backend: drivers/vhost/tcm_vhost.c:537:23-29: ERROR: allocation function on line 533 returns NULL not ERR_PTR on failure vim +537 drivers/vhost/tcm_vhost.c 534 if (!sg) 535 return -ENOMEM; 536 pr_debug("%s sg %p sgl_count %u is_err %ld\n", __func__, > 537 sg, sgl_count, IS_ERR(sg)); 538 sg_init_table(sg, sgl_count); 539 540 tv_cmd->tvc_sgl = sg; Signed-off-by: Fengguang Wu Signed-off-by: Nicholas Bellinger --- drivers/vhost/tcm_vhost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index fb366540ed54..481af88a5ff5 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -533,8 +533,8 @@ static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); if (!sg) return -ENOMEM; - pr_debug("%s sg %p sgl_count %u is_err %ld\n", __func__, - sg, sgl_count, IS_ERR(sg)); + pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__, + sg, sgl_count, !sg); sg_init_table(sg, sgl_count); tv_cmd->tvc_sgl = sg; -- GitLab From 101998f6fcd680ed12d85633b81504feb1cb0667 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 30 Jul 2012 13:30:00 -0700 Subject: [PATCH 5542/5711] tcm_vhost: Post-merge review changes requested by MST This patch contains the post RFC-v5 (post-merge) changes, this includes: - Add locking comment - Move vhost_scsi_complete_cmd ahead of TFO callbacks in order to drop forward declarations - Drop extra '!= NULL' usage in vhost_scsi_complete_cmd_work() - Change vhost_scsi_*_handle_kick() to use pr_debug - Fix possible race in vhost_scsi_set_endpoint() for vs->vs_tpg checking + assignment. - Convert tv_tpg->tpg_vhost_count + ->tv_tpg_port_count from atomic_t -> int, and make sure reference is protected by ->tv_tpg_mutex. - Drop unnecessary vhost_scsi->vhost_ref_cnt - Add 'err:' label for exception path in vhost_scsi_clear_endpoint() - Add enum for VQ numbers, add usage in vhost_scsi_open() - Add vhost_scsi_flush() + vhost_scsi_flush_vq() following drivers/vhost/net.c - Add smp_wmb() + vhost_scsi_flush() call during vhost_scsi_set_features() - Drop unnecessary copy_from_user() usage with GET_ABI_VERSION ioctl - Add missing vhost_scsi_compat_ioctl() caller for vhost_scsi_fops - Fix function parameter definition first line to follow existing vhost code style - Change 'vHost' usage -> 'vhost' in handful of locations - Change -EPERM -> -EBUSY usage for two failures in tcm_vhost_drop_nexus() - Add comment for tcm_vhost_workqueue in tcm_vhost_init() - Make GET_ABI_VERSION return 'int' + add comment in tcm_vhost.h Reported-by: Michael S. Tsirkin Cc: Michael S. Tsirkin Cc: Stefan Hajnoczi Cc: Anthony Liguori Cc: Zhi Yong Wu Cc: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/vhost/tcm_vhost.c | 195 +++++++++++++++++++++----------------- drivers/vhost/tcm_vhost.h | 9 +- 2 files changed, 111 insertions(+), 93 deletions(-) diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index 481af88a5ff5..74b2edaaf1f6 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -53,9 +53,14 @@ #include "vhost.h" #include "tcm_vhost.h" +enum { + VHOST_SCSI_VQ_CTL = 0, + VHOST_SCSI_VQ_EVT = 1, + VHOST_SCSI_VQ_IO = 2, +}; + struct vhost_scsi { - atomic_t vhost_ref_cnt; - struct tcm_vhost_tpg *vs_tpg; + struct tcm_vhost_tpg *vs_tpg; /* Protected by vhost_scsi->dev.mutex */ struct vhost_dev dev; struct vhost_virtqueue vqs[3]; @@ -131,8 +136,7 @@ static u32 tcm_vhost_get_default_depth(struct se_portal_group *se_tpg) return 1; } -static u32 tcm_vhost_get_pr_transport_id( - struct se_portal_group *se_tpg, +static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, struct se_node_acl *se_nacl, struct t10_pr_registration *pr_reg, int *format_code, @@ -162,8 +166,7 @@ static u32 tcm_vhost_get_pr_transport_id( format_code, buf); } -static u32 tcm_vhost_get_pr_transport_id_len( - struct se_portal_group *se_tpg, +static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, struct se_node_acl *se_nacl, struct t10_pr_registration *pr_reg, int *format_code) @@ -192,8 +195,7 @@ static u32 tcm_vhost_get_pr_transport_id_len( format_code); } -static char *tcm_vhost_parse_pr_out_transport_id( - struct se_portal_group *se_tpg, +static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, const char *buf, u32 *out_tid_len, char **port_nexus_ptr) @@ -236,8 +238,7 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl( return &nacl->se_node_acl; } -static void tcm_vhost_release_fabric_acl( - struct se_portal_group *se_tpg, +static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, struct se_node_acl *se_nacl) { struct tcm_vhost_nacl *nacl = container_of(se_nacl, @@ -297,7 +298,16 @@ static int tcm_vhost_get_cmd_state(struct se_cmd *se_cmd) return 0; } -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *); +static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) +{ + struct vhost_scsi *vs = tv_cmd->tvc_vhost; + + spin_lock_bh(&vs->vs_completion_lock); + list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); + spin_unlock_bh(&vs->vs_completion_lock); + + vhost_work_queue(&vs->dev, &vs->vs_completion_work); +} static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) { @@ -381,7 +391,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) vs_completion_work); struct tcm_vhost_cmd *tv_cmd; - while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs)) != NULL) { + while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) { struct virtio_scsi_cmd_resp v_rsp; struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; int ret; @@ -408,19 +418,6 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) vhost_signal(&vs->dev, &vs->vqs[2]); } -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) -{ - struct vhost_scsi *vs = tv_cmd->tvc_vhost; - - pr_debug("%s tv_cmd %p\n", __func__, tv_cmd); - - spin_lock_bh(&vs->vs_completion_lock); - list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); - spin_unlock_bh(&vs->vs_completion_lock); - - vhost_work_queue(&vs->dev, &vs->vs_completion_work); -} - static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( struct tcm_vhost_tpg *tv_tpg, struct virtio_scsi_cmd_req *v_req, @@ -787,12 +784,12 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs) static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) { - pr_err("%s: The handling func for control queue.\n", __func__); + pr_debug("%s: The handling func for control queue.\n", __func__); } static void vhost_scsi_evt_handle_kick(struct vhost_work *work) { - pr_err("%s: The handling func for event queue.\n", __func__); + pr_debug("%s: The handling func for event queue.\n", __func__); } static void vhost_scsi_handle_kick(struct vhost_work *work) @@ -825,11 +822,6 @@ static int vhost_scsi_set_endpoint( return -EFAULT; } } - - if (vs->vs_tpg) { - mutex_unlock(&vs->dev.mutex); - return -EEXIST; - } mutex_unlock(&vs->dev.mutex); mutex_lock(&tcm_vhost_mutex); @@ -839,7 +831,7 @@ static int vhost_scsi_set_endpoint( mutex_unlock(&tv_tpg->tv_tpg_mutex); continue; } - if (atomic_read(&tv_tpg->tv_tpg_vhost_count)) { + if (tv_tpg->tv_tpg_vhost_count != 0) { mutex_unlock(&tv_tpg->tv_tpg_mutex); continue; } @@ -847,14 +839,20 @@ static int vhost_scsi_set_endpoint( if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) && (tv_tpg->tport_tpgt == t->vhost_tpgt)) { - atomic_inc(&tv_tpg->tv_tpg_vhost_count); - smp_mb__after_atomic_inc(); + tv_tpg->tv_tpg_vhost_count++; mutex_unlock(&tv_tpg->tv_tpg_mutex); mutex_unlock(&tcm_vhost_mutex); mutex_lock(&vs->dev.mutex); + if (vs->vs_tpg) { + mutex_unlock(&vs->dev.mutex); + mutex_lock(&tv_tpg->tv_tpg_mutex); + tv_tpg->tv_tpg_vhost_count--; + mutex_unlock(&tv_tpg->tv_tpg_mutex); + return -EEXIST; + } + vs->vs_tpg = tv_tpg; - atomic_inc(&vs->vhost_ref_cnt); smp_mb__after_atomic_inc(); mutex_unlock(&vs->dev.mutex); return 0; @@ -871,38 +869,42 @@ static int vhost_scsi_clear_endpoint( { struct tcm_vhost_tport *tv_tport; struct tcm_vhost_tpg *tv_tpg; - int index; + int index, ret; mutex_lock(&vs->dev.mutex); /* Verify that ring has been setup correctly. */ for (index = 0; index < vs->dev.nvqs; ++index) { if (!vhost_vq_access_ok(&vs->vqs[index])) { - mutex_unlock(&vs->dev.mutex); - return -EFAULT; + ret = -EFAULT; + goto err; } } if (!vs->vs_tpg) { - mutex_unlock(&vs->dev.mutex); - return -ENODEV; + ret = -ENODEV; + goto err; } tv_tpg = vs->vs_tpg; tv_tport = tv_tpg->tport; if (strcmp(tv_tport->tport_name, t->vhost_wwpn) || (tv_tpg->tport_tpgt != t->vhost_tpgt)) { - mutex_unlock(&vs->dev.mutex); pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", tv_tport->tport_name, tv_tpg->tport_tpgt, t->vhost_wwpn, t->vhost_tpgt); - return -EINVAL; + ret = -EINVAL; + goto err; } - atomic_dec(&tv_tpg->tv_tpg_vhost_count); + tv_tpg->tv_tpg_vhost_count--; vs->vs_tpg = NULL; mutex_unlock(&vs->dev.mutex); return 0; + +err: + mutex_unlock(&vs->dev.mutex); + return ret; } static int vhost_scsi_open(struct inode *inode, struct file *f) @@ -918,9 +920,9 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) INIT_LIST_HEAD(&s->vs_completion_list); spin_lock_init(&s->vs_completion_lock); - s->vqs[0].handle_kick = vhost_scsi_ctl_handle_kick; - s->vqs[1].handle_kick = vhost_scsi_evt_handle_kick; - s->vqs[2].handle_kick = vhost_scsi_handle_kick; + s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick; + s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick; + s->vqs[VHOST_SCSI_VQ_IO].handle_kick = vhost_scsi_handle_kick; r = vhost_dev_init(&s->dev, s->vqs, 3); if (r < 0) { kfree(s); @@ -949,6 +951,18 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) return 0; } +static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index) +{ + vhost_poll_flush(&vs->dev.vqs[index].poll); +} + +static void vhost_scsi_flush(struct vhost_scsi *vs) +{ + vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_CTL); + vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_EVT); + vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_IO); +} + static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) { if (features & ~VHOST_FEATURES) @@ -961,7 +975,8 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) return -EFAULT; } vs->dev.acked_features = features; - /* TODO possibly smp_wmb() and flush vqs */ + smp_wmb(); + vhost_scsi_flush(vs); mutex_unlock(&vs->dev.mutex); return 0; } @@ -974,7 +989,7 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, void __user *argp = (void __user *)arg; u64 __user *featurep = argp; u64 features; - int r; + int r, abi_version = VHOST_SCSI_ABI_VERSION; switch (ioctl) { case VHOST_SCSI_SET_ENDPOINT: @@ -988,12 +1003,7 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, return vhost_scsi_clear_endpoint(vs, &backend); case VHOST_SCSI_GET_ABI_VERSION: - if (copy_from_user(&backend, argp, sizeof backend)) - return -EFAULT; - - backend.abi_version = VHOST_SCSI_ABI_VERSION; - - if (copy_to_user(argp, &backend, sizeof backend)) + if (copy_to_user(argp, &abi_version, sizeof abi_version)) return -EFAULT; return 0; case VHOST_GET_FEATURES: @@ -1013,11 +1023,21 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, } } +#ifdef CONFIG_COMPAT +static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl, + unsigned long arg) +{ + return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); +} +#endif + static const struct file_operations vhost_scsi_fops = { .owner = THIS_MODULE, .release = vhost_scsi_release, .unlocked_ioctl = vhost_scsi_ioctl, - /* TODO compat ioctl? */ +#ifdef CONFIG_COMPAT + .compat_ioctl = vhost_scsi_compat_ioctl, +#endif .open = vhost_scsi_open, .llseek = noop_llseek, }; @@ -1054,28 +1074,28 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport) return "Unknown"; } -static int tcm_vhost_port_link( - struct se_portal_group *se_tpg, +static int tcm_vhost_port_link(struct se_portal_group *se_tpg, struct se_lun *lun) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); - atomic_inc(&tv_tpg->tv_tpg_port_count); - smp_mb__after_atomic_inc(); + mutex_lock(&tv_tpg->tv_tpg_mutex); + tv_tpg->tv_tpg_port_count++; + mutex_unlock(&tv_tpg->tv_tpg_mutex); return 0; } -static void tcm_vhost_port_unlink( - struct se_portal_group *se_tpg, +static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, struct se_lun *se_lun) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); - atomic_dec(&tv_tpg->tv_tpg_port_count); - smp_mb__after_atomic_dec(); + mutex_lock(&tv_tpg->tv_tpg_mutex); + tv_tpg->tv_tpg_port_count--; + mutex_unlock(&tv_tpg->tv_tpg_mutex); } static struct se_node_acl *tcm_vhost_make_nodeacl( @@ -1122,8 +1142,7 @@ static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) kfree(nacl); } -static int tcm_vhost_make_nexus( - struct tcm_vhost_tpg *tv_tpg, +static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, const char *name) { struct se_portal_group *se_tpg; @@ -1168,7 +1187,7 @@ static int tcm_vhost_make_nexus( return -ENOMEM; } /* - * Now register the TCM vHost virtual I_T Nexus as active with the + * Now register the TCM vhost virtual I_T Nexus as active with the * call to __transport_register_session() */ __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, @@ -1179,8 +1198,7 @@ static int tcm_vhost_make_nexus( return 0; } -static int tcm_vhost_drop_nexus( - struct tcm_vhost_tpg *tpg) +static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) { struct se_session *se_sess; struct tcm_vhost_nexus *tv_nexus; @@ -1198,27 +1216,27 @@ static int tcm_vhost_drop_nexus( return -ENODEV; } - if (atomic_read(&tpg->tv_tpg_port_count)) { + if (tpg->tv_tpg_port_count != 0) { mutex_unlock(&tpg->tv_tpg_mutex); - pr_err("Unable to remove TCM_vHost I_T Nexus with" + pr_err("Unable to remove TCM_vhost I_T Nexus with" " active TPG port count: %d\n", - atomic_read(&tpg->tv_tpg_port_count)); - return -EPERM; + tpg->tv_tpg_port_count); + return -EBUSY; } - if (atomic_read(&tpg->tv_tpg_vhost_count)) { + if (tpg->tv_tpg_vhost_count != 0) { mutex_unlock(&tpg->tv_tpg_mutex); - pr_err("Unable to remove TCM_vHost I_T Nexus with" + pr_err("Unable to remove TCM_vhost I_T Nexus with" " active TPG vhost count: %d\n", - atomic_read(&tpg->tv_tpg_vhost_count)); - return -EPERM; + tpg->tv_tpg_vhost_count); + return -EBUSY; } - pr_debug("TCM_vHost_ConfigFS: Removing I_T Nexus to emulated" + pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated" " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), tv_nexus->tvn_se_sess->se_node_acl->initiatorname); /* - * Release the SCSI I_T Nexus to the emulated vHost Target Port + * Release the SCSI I_T Nexus to the emulated vhost Target Port */ transport_deregister_session(tv_nexus->tvn_se_sess); tpg->tpg_nexus = NULL; @@ -1228,8 +1246,7 @@ static int tcm_vhost_drop_nexus( return 0; } -static ssize_t tcm_vhost_tpg_show_nexus( - struct se_portal_group *se_tpg, +static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, char *page) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, @@ -1250,8 +1267,7 @@ static ssize_t tcm_vhost_tpg_show_nexus( return ret; } -static ssize_t tcm_vhost_tpg_store_nexus( - struct se_portal_group *se_tpg, +static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, const char *page, size_t count) { @@ -1336,8 +1352,7 @@ static struct configfs_attribute *tcm_vhost_tpg_attrs[] = { NULL, }; -static struct se_portal_group *tcm_vhost_make_tpg( - struct se_wwn *wwn, +static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn, struct config_group *group, const char *name) { @@ -1385,7 +1400,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) list_del(&tpg->tv_tpg_list); mutex_unlock(&tcm_vhost_mutex); /* - * Release the virtual I_T Nexus for this vHost TPG + * Release the virtual I_T Nexus for this vhost TPG */ tcm_vhost_drop_nexus(tpg); /* @@ -1395,8 +1410,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) kfree(tpg); } -static struct se_wwn *tcm_vhost_make_tport( - struct target_fabric_configfs *tf, +static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf, struct config_group *group, const char *name) { @@ -1592,7 +1606,10 @@ static void tcm_vhost_deregister_configfs(void) static int __init tcm_vhost_init(void) { int ret = -ENOMEM; - + /* + * Use our own dedicated workqueue for submitting I/O into + * target core to avoid contention within system_wq. + */ tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); if (!tcm_vhost_workqueue) goto out; diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h index c983ed21e413..eff42df14de9 100644 --- a/drivers/vhost/tcm_vhost.h +++ b/drivers/vhost/tcm_vhost.h @@ -47,9 +47,9 @@ struct tcm_vhost_tpg { /* Vhost port target portal group tag for TCM */ u16 tport_tpgt; /* Used to track number of TPG Port/Lun Links wrt to explict I_T Nexus shutdown */ - atomic_t tv_tpg_port_count; - /* Used for vhost_scsi device reference to tpg_nexus */ - atomic_t tv_tpg_vhost_count; + int tv_tpg_port_count; + /* Used for vhost_scsi device reference to tpg_nexus, protected by tv_tpg_mutex */ + int tv_tpg_vhost_count; /* list for tcm_vhost_list */ struct list_head tv_tpg_list; /* Used to protect access for tpg_nexus */ @@ -98,4 +98,5 @@ struct vhost_scsi_target { /* VHOST_SCSI specific defines */ #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) -#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, struct vhost_scsi_target) +/* Changing this breaks userspace. */ +#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) -- GitLab From 1fa8f4504130adc34a071a29170f570102136835 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Wed, 1 Aug 2012 14:51:53 -0700 Subject: [PATCH 5543/5711] tcm_fc: Avoid debug overhead when not debugging Stop doing a pile of work related to debugging messages when the ft_debug_logging flag is not set. Use unlikely to add the check in a way that the check can be inlined without inlining the whole thing. Signed-off-by: Mark Rustad Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tcm_fc.h | 1 + drivers/target/tcm_fc/tfc_cmd.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index c5eb3c33c3db..eea69358ced3 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -131,6 +131,7 @@ extern struct list_head ft_lport_list; extern struct mutex ft_lport_lock; extern struct fc4_prov ft_prov; extern struct target_fabric_configfs *ft_configfs; +extern unsigned int ft_debug_logging; /* * Fabric methods. diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index b9cb5006177e..823e6922249d 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -48,7 +48,7 @@ /* * Dump cmd state for debugging. */ -void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) +static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller) { struct fc_exch *ep; struct fc_seq *sp; @@ -80,6 +80,12 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) } } +void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) +{ + if (unlikely(ft_debug_logging)) + _ft_dump_cmd(cmd, caller); +} + static void ft_free_cmd(struct ft_cmd *cmd) { struct fc_frame *fp; -- GitLab From d0e27c88d795fb9647153063ec48051fd84e1731 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 14 Aug 2012 16:06:43 -0700 Subject: [PATCH 5544/5711] target: fix NULL pointer dereference bug alloc_page() fails to get memory I am hitting this bug when the target is low in memory that fails the alloc_page() for the newly submitted command. This is a sort of off-by-one bug causing NULL pointer dereference in __free_page() since 'i' here is really the counter of total pages that have been successfully allocated here. Signed-off-by: Yi Zou Cc: Andy Grover Cc: Nicholas Bellinger Cc: Open-FCoE.org Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0eaae23d12b5..a7589ccdb6f3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2294,9 +2294,9 @@ transport_generic_get_mem(struct se_cmd *cmd) return 0; out: - while (i >= 0) { - __free_page(sg_page(&cmd->t_data_sg[i])); + while (i > 0) { i--; + __free_page(sg_page(&cmd->t_data_sg[i])); } kfree(cmd->t_data_sg); cmd->t_data_sg = NULL; -- GitLab From 5b7517f81449067caf3d402e4abc6cd92096fe62 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 16 Aug 2012 18:56:34 -0700 Subject: [PATCH 5545/5711] tcm_vhost: Change vhost_scsi_target->vhost_wwpn to char * This patch changes the vhost_scsi_target->vhost_wwpn[] type used by VHOST_SCSI_* ioctls to 'char *' as requested by Blue Swirl in order to match the latest QEMU vhost-scsi RFC-v3 userspace code. Queuing this up into target-pending/master for a -rc3 PULL. Reported-by: Blue Swirl Cc: Michael S. Tsirkin Cc: Stefan Hajnoczi Cc: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/vhost/tcm_vhost.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h index eff42df14de9..e9d5c020fb39 100644 --- a/drivers/vhost/tcm_vhost.h +++ b/drivers/vhost/tcm_vhost.h @@ -91,7 +91,7 @@ struct tcm_vhost_tport { struct vhost_scsi_target { int abi_version; - unsigned char vhost_wwpn[TRANSPORT_IQN_LEN]; + char vhost_wwpn[TRANSPORT_IQN_LEN]; unsigned short vhost_tpgt; }; -- GitLab From 1d2a2cd95ee0137a2353d1b5635739c281f27cd4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 8 Aug 2012 00:14:13 +0000 Subject: [PATCH 5546/5711] target/pscsi: Fix bug with REPORT_LUNs handling for SCSI passthrough This patch fixes a regression bug in pscsi_transport_complete() callback code where *pt was being NULL dereferenced during REPORT_LUNS handling, that was introduced with the spc/sbc refactoring in: commit 1fd032ee10d2816c947f5d5b9abda95e728f0a8f Author: Christoph Hellwig Date: Sun May 20 11:59:15 2012 -0400 target: move code for CDB emulation As this is a special case for pscsi_parse_cdb() to call spc_parse_cdb() to allow TCM to handle REPORT_LUN emulation, pscsi_plugin_task will have not been allocated.. So now in pscsi_transport_complete() just check for existence of *pt and return for this special case. Reported-by: Alex Elsayed Cc: Alex Elsayed Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 6e32ff6f2fa0..5552fa7426bc 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -673,8 +673,15 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) struct scsi_device *sd = pdv->pdv_sd; int result; struct pscsi_plugin_task *pt = cmd->priv; - unsigned char *cdb = &pt->pscsi_cdb[0]; + unsigned char *cdb; + /* + * Special case for REPORT_LUNs handling where pscsi_plugin_task has + * not been allocated because TCM is handling the emulation directly. + */ + if (!pt) + return 0; + cdb = &pt->pscsi_cdb[0]; result = pt->pscsi_result; /* * Hack to make sure that Write-Protect modepage is set if R/O mode is -- GitLab From 38ab8a2009e33ded06bf80d3a95da393d8d651d6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 15 Aug 2012 12:32:36 +0300 Subject: [PATCH 5547/5711] drm/i915: fix EDID memory leak in SDVO The EDID returned by drm_get_edid() was never freed. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d172e9873131..d81bb0bf2885 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1692,6 +1692,7 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) edid = intel_sdvo_get_edid(connector); if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL) has_audio = drm_detect_monitor_audio(edid); + kfree(edid); return has_audio; } -- GitLab From b6c7488df68ae3660d81b149b61b55b97929da83 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 14 Aug 2012 14:35:14 -0700 Subject: [PATCH 5548/5711] drm/i915/contexts: fix list corruption After reset we unconditionally reinitialize lists. If the context switch hasn't yet completed before the suspend, the default context object will end up on lists that are going to go away when we resume. The patch forces the context switch to be synchronous before suspend assuring that the active/inactive tracking is correct at the time of resume. References: https://bugs.freedesktop.org/show_bug.cgi?id=52429 Tested-by: Guang A Yang Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5c4657a54f97..489e2b162b27 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2365,6 +2365,10 @@ int i915_gpu_idle(struct drm_device *dev) /* Flush everything onto the inactive list. */ for_each_ring(ring, dev_priv, i) { + ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); + if (ret) + return ret; + ret = i915_ring_idle(ring); if (ret) return ret; @@ -2372,10 +2376,6 @@ int i915_gpu_idle(struct drm_device *dev) /* Is the device fubar? */ if (WARN_ON(!list_empty(&ring->gpu_write_list))) return -EBUSY; - - ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); - if (ret) - return ret; } return 0; -- GitLab From a843af186c3157cee58f1cf689385ab906e1f109 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Aug 2012 11:42:14 -0300 Subject: [PATCH 5549/5711] drm/i915: fix hsw uncached pte They've changed it ... for no apparent reason. Meh. V2: remove unused 'is_hsw' field. Signed-off-by: Daniel Vetter Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-agp.h | 1 + drivers/char/agp/intel-gtt.c | 105 ++++++++++++++++++---------- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +- drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 75 insertions(+), 37 deletions(-) diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 6f007b6c240d..6ec0fff79bc2 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -64,6 +64,7 @@ #define I830_PTE_SYSTEM_CACHED 0x00000006 /* GT PTE cache control fields */ #define GEN6_PTE_UNCACHED 0x00000002 +#define HSW_PTE_UNCACHED 0x00000000 #define GEN6_PTE_LLC 0x00000004 #define GEN6_PTE_LLC_MLC 0x00000006 #define GEN6_PTE_GFDT 0x00000008 diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 08fc5cbb13cd..58e32f7c3229 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1156,6 +1156,30 @@ static bool gen6_check_flags(unsigned int flags) return true; } +static void haswell_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; + u32 pte_flags; + + if (type_mask == AGP_USER_MEMORY) + pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { + pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } else { /* set 'normal'/'cached' to LLC by default */ + pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } + + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; + writel(addr | pte_flags, intel_private.gtt + entry); +} + static void gen6_write_entry(dma_addr_t addr, unsigned int entry, unsigned int flags) { @@ -1382,6 +1406,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = { .check_flags = gen6_check_flags, .chipset_flush = i9xx_chipset_flush, }; +static const struct intel_gtt_driver haswell_gtt_driver = { + .gen = 6, + .setup = i9xx_setup, + .cleanup = gen6_cleanup, + .write_entry = haswell_write_entry, + .dma_mask_size = 40, + .check_flags = gen6_check_flags, + .chipset_flush = i9xx_chipset_flush, +}; static const struct intel_gtt_driver valleyview_gtt_driver = { .gen = 7, .setup = i9xx_setup, @@ -1499,77 +1532,77 @@ static const struct intel_gtt_driver_description { { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, "ValleyView", &valleyview_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, - "Haswell", &sandybridge_gtt_driver }, + "Haswell", &haswell_gtt_driver }, { 0, NULL, NULL } }; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ee9b68f6bc36..d9a5372ec56f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -261,7 +261,10 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, pte_flags |= GEN6_PTE_CACHE_LLC; break; case I915_CACHE_NONE: - pte_flags |= GEN6_PTE_UNCACHED; + if (IS_HASWELL(dev)) + pte_flags |= HSW_PTE_UNCACHED; + else + pte_flags |= GEN6_PTE_UNCACHED; break; default: BUG(); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index acc99b21e0b6..28725ce5b82c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -115,6 +115,7 @@ #define GEN6_PTE_VALID (1 << 0) #define GEN6_PTE_UNCACHED (1 << 1) +#define HSW_PTE_UNCACHED (0) #define GEN6_PTE_CACHE_LLC (2 << 1) #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) #define GEN6_PTE_CACHE_BITS (3 << 1) -- GitLab From 4eab81366465aedcfd26de960c595bc03599c09f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 13 Aug 2012 13:22:34 +0300 Subject: [PATCH 5550/5711] drm/i915: extract connector update from intel_ddc_get_modes() for reuse Refactor the connector update part of intel_ddc_get_modes() into a separate intel_connector_update_modes() function for reuse. No functional changes. Signed-off-by: Jani Nikula Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881 Tested-by: Alex Ferrando Cc: stable@vger.kernel.org (for 3.4+3.5) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_modes.c | 31 +++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 132ab511b90c..cd54cf88a28f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -342,6 +342,8 @@ struct intel_fbc_work { int interval; }; +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); extern void intel_attach_force_audio_property(struct drm_connector *connector); diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 45848b9b670b..29b72593fbb2 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -32,6 +32,25 @@ #include "intel_drv.h" #include "i915_drv.h" +/** + * intel_connector_update_modes - update connector from edid + * @connector: DRM connector device to use + * @edid: previously read EDID information + */ +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + + return ret; +} + /** * intel_ddc_get_modes - get modelist from monitor * @connector: DRM connector device to use @@ -43,18 +62,12 @@ int intel_ddc_get_modes(struct drm_connector *connector, struct i2c_adapter *adapter) { struct edid *edid; - int ret = 0; edid = drm_get_edid(connector, adapter); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - connector->display_info.raw_edid = NULL; - kfree(edid); - } + if (!edid) + return 0; - return ret; + return intel_connector_update_modes(connector, edid); } static const struct drm_prop_enum_list force_audio_names[] = { -- GitLab From f1a2f5b7c5f0941d23eef0a095c0b99bf8d051e6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 13 Aug 2012 13:22:35 +0300 Subject: [PATCH 5551/5711] drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads GMBUS was enabled over bit-banging as the default in commits: commit c3dfefa0a6d235bd465309e12f4c56ea16e71111 Author: Daniel Vetter Date: Tue Feb 14 22:37:25 2012 +0100 drm/i915: reenable gmbus on gen3+ again and commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15 Author: Daniel Vetter Date: Fri Mar 2 19:38:30 2012 +0100 drm/i915: enable gmbus on gen2 Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging fallback to CRT EDID reads. LKML-Reference: <201207251020.47637.maciej.rutecki@gmail.com> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881 Signed-off-by: Jani Nikula Tested-by: Alex Ferrando Cc: stable@vger.kernel.org (for 3.4+3.5) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 7ed4a41c3965..23bdc8cd1458 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -326,6 +326,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } +static struct edid *intel_crt_get_edid(struct drm_connector *connector, + struct i2c_adapter *i2c) +{ + struct edid *edid; + + edid = drm_get_edid(connector, i2c); + + if (!edid && !intel_gmbus_is_forced_bit(i2c)) { + DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); + intel_gmbus_force_bit(i2c, true); + edid = drm_get_edid(connector, i2c); + intel_gmbus_force_bit(i2c, false); + } + + return edid; +} + +/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ +static int intel_crt_ddc_get_modes(struct drm_connector *connector, + struct i2c_adapter *adapter) +{ + struct edid *edid; + + edid = intel_crt_get_edid(connector, adapter); + if (!edid) + return 0; + + return intel_connector_update_modes(connector, edid); +} + static bool intel_crt_detect_ddc(struct drm_connector *connector) { struct intel_crt *crt = intel_attached_crt(connector); @@ -336,7 +366,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG); i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); - edid = drm_get_edid(connector, i2c); + edid = intel_crt_get_edid(connector, i2c); if (edid) { bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; @@ -544,13 +574,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) struct i2c_adapter *i2c; i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); - ret = intel_ddc_get_modes(connector, i2c); + ret = intel_crt_ddc_get_modes(connector, i2c); if (ret || !IS_G4X(dev)) return ret; /* Try to probe digital port for output in DVI-I -> VGA mode. */ i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); - return intel_ddc_get_modes(connector, i2c); + return intel_crt_ddc_get_modes(connector, i2c); } static int intel_crt_set_property(struct drm_connector *connector, -- GitLab From 2ee38d4de5b0f1bd4ed9f0c830ae6949e39c18f0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 10 Aug 2012 11:07:51 +0200 Subject: [PATCH 5552/5711] pinctrl/nomadik: fix null in irqdomain errorpath The irqdomain conversion failed to notice that we do not always have a DT node to dereference, fix this up by using a simple dev_err() that also tells the name of the device. Cc: Loic Pallardy Cc: Patrice Chotard Acked-by: Lee Jones Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index ec6ac501b23a..3dde6537adb8 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1292,7 +1292,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) NOMADIK_GPIO_TO_IRQ(pdata->first_gpio), 0, &nmk_gpio_irq_simple_ops, nmk_chip); if (!nmk_chip->domain) { - pr_err("%s: Failed to create irqdomain\n", np->full_name); + dev_err(&dev->dev, "failed to create irqdomain\n"); ret = -ENOSYS; goto out; } -- GitLab From d1a83d3b1729ac53ebcc6134f0d88faa311c42b9 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 9 Aug 2012 21:02:19 +0200 Subject: [PATCH 5553/5711] Documentation/pinctrl.txt: Fix some misspelled macros Signed-off-by: Daniel Mack Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index e40f4b4e1977..1479aca23744 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -840,9 +840,9 @@ static unsigned long i2c_pin_configs[] = { static struct pinctrl_map __initdata mapping[] = { PIN_MAP_MUX_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", "i2c0"), - PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), - PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), - PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), + PIN_MAP_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), + PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), + PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), }; Finally, some devices expect the mapping table to contain certain specific -- GitLab From ac5aa7f9e0891a115ab307b4bdde9c55b9232970 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 10 Aug 2012 16:52:58 +0200 Subject: [PATCH 5554/5711] pinctrl: header: trivial: declare struct device As struct device is used as a function argument, it should at least be declared (device.h is not included). Signed-off-by: Richard Genoud Signed-off-by: Linus Walleij --- include/linux/pinctrl/consumer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 6dd96fb45482..e9b7f4350844 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h @@ -20,6 +20,7 @@ /* This struct is private to the core and should be regarded as a cookie */ struct pinctrl; struct pinctrl_state; +struct device; #ifdef CONFIG_PINCTRL -- GitLab From d599bfb324ad74e63b616809c1c13c76d1493cf9 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 10 Aug 2012 16:53:49 +0200 Subject: [PATCH 5555/5711] trivial: pinctrl core: remove extraneous code lines In function pinctrl_get_locked, pointer p is returned on error, and also return on no_error. So, we just return it with no error test. It's pretty the same in function pinctrl_lookup_state_locked: state is returned in every case, so we drop the error test and just return state. Signed-off-by: Richard Genoud --- drivers/pinctrl/core.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index fb7f3bebdc69..dc5c126e398a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -657,11 +657,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev) if (p != NULL) return ERR_PTR(-EBUSY); - p = create_pinctrl(dev); - if (IS_ERR(p)) - return p; - - return p; + return create_pinctrl(dev); } /** @@ -738,11 +734,8 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p, dev_dbg(p->dev, "using pinctrl dummy state (%s)\n", name); state = create_state(p, name); - if (IS_ERR(state)) - return state; - } else { - return ERR_PTR(-ENODEV); - } + } else + state = ERR_PTR(-ENODEV); } return state; -- GitLab From b20fd25a947584cf949ad3066e41697c5cdad816 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 13 Aug 2012 22:18:52 +0800 Subject: [PATCH 5556/5711] pinctrl: imx51: fix .conf_reg of MX51_PAD_SD2_CMD__CSPI_MOSI The .conf_reg of MX51_PAD_SD2_CMD__CSPI_MOSI should be 0x7bc rather than NO_PAD. This error will cause SD2 probe failure. Signed-off-by: Shawn Guo Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-imx51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c index 689b3c88dd2e..9fd02162a3c2 100644 --- a/drivers/pinctrl/pinctrl-imx51.c +++ b/drivers/pinctrl/pinctrl-imx51.c @@ -974,7 +974,7 @@ static struct imx_pin_reg imx51_pin_regs[] = { IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */ IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */ IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */ - IMX_PIN_REG(MX51_PAD_SD2_CMD, NO_PAD, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ + IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */ -- GitLab From 4c39104da846379151b9c37cffaf8b00a5580229 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 10 Aug 2012 11:02:19 +0200 Subject: [PATCH 5557/5711] pinctrl/nomadik: add kp_b_2 keyboard function group list There is yet another way to mux the keyboard, so fix up that group. Signed-off-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik-db8500.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c index 5f3e9d0221e1..a39fb7a6fc51 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -505,6 +505,8 @@ static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1, DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2, DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 }; +static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, + DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3}; static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, @@ -662,6 +664,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), @@ -751,7 +754,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1"); DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1"); DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); -DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); -- GitLab From 7612bfeecc197bbb6629842b5c6ff1967f0a9b70 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 15 Aug 2012 11:41:55 -0700 Subject: [PATCH 5558/5711] Yama: access task_struct->comm directly The core ptrace access checking routine holds a task lock, and when reporting a failure, Yama takes a separate task lock. To avoid a potential deadlock with two ptracers taking the opposite locks, do not use get_task_comm() and just use ->comm directly since accuracy is not important for the report. Reported-by: Fengguang Wu Suggested-by: Oleg Nesterov CC: stable@vger.kernel.org Signed-off-by: Kees Cook Acked-by: John Johansen Signed-off-by: James Morris --- security/yama/yama_lsm.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index d51b7c76c37d..0cc99a3ea42d 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -279,12 +279,9 @@ static int yama_ptrace_access_check(struct task_struct *child, } if (rc) { - char name[sizeof(current->comm)]; printk_ratelimited(KERN_NOTICE "ptrace of pid %d was attempted by: %s (pid %d)\n", - child->pid, - get_task_comm(name, current), - current->pid); + child->pid, current->comm, current->pid); } return rc; @@ -319,12 +316,9 @@ static int yama_ptrace_traceme(struct task_struct *parent) } if (rc) { - char name[sizeof(current->comm)]; printk_ratelimited(KERN_NOTICE "ptraceme of pid %d was attempted by: %s (pid %d)\n", - current->pid, - get_task_comm(name, parent), - parent->pid); + current->pid, parent->comm, parent->pid); } return rc; -- GitLab From dfeb86ecde7ae6ce15bd69a6a205b5e13aea8111 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 2 Aug 2012 12:32:42 +0530 Subject: [PATCH 5559/5711] pwm: Add missing static storage class specifiers in core.c file Fixes the following sparse warnings: drivers/pwm/core.c:152:6: warning: symbol 'of_pwmchip_add' was not declared. Should it be static? drivers/pwm/core.c:165:6: warning: symbol 'of_pwmchip_remove' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ecb76909e946..4a8bdfa79e7f 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -149,7 +149,7 @@ static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, return pwm; } -void of_pwmchip_add(struct pwm_chip *chip) +static void of_pwmchip_add(struct pwm_chip *chip) { if (!chip->dev || !chip->dev->of_node) return; @@ -162,7 +162,7 @@ void of_pwmchip_add(struct pwm_chip *chip) of_node_get(chip->dev->of_node); } -void of_pwmchip_remove(struct pwm_chip *chip) +static void of_pwmchip_remove(struct pwm_chip *chip) { if (chip->dev && chip->dev->of_node) of_node_put(chip->dev->of_node); -- GitLab From ecefeb79218064bf011c5d3ff25322ffa60c302c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 2 Aug 2012 17:55:54 +0900 Subject: [PATCH 5560/5711] pwm: samsung: add missing device pointer to struct pwm_chip This patch adds missing device pointer to struct pwm_chip. If the device pointer is NULL, pwmchip_add() will return error. Signed-off-by: Jingoo Han Signed-off-by: Thierry Reding --- drivers/pwm/pwm-samsung.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index d10386528c9c..e5187c0ade9f 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c @@ -225,6 +225,7 @@ static int s3c_pwm_probe(struct platform_device *pdev) /* calculate base of control bits in TCON */ s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; + s3c->chip.dev = &pdev->dev; s3c->chip.ops = &s3c_pwm_ops; s3c->chip.base = -1; s3c->chip.npwm = 1; -- GitLab From 2ffdc9a64824a373d09f3417ae4377ec83cd9d16 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 3 Aug 2012 21:43:54 +0800 Subject: [PATCH 5561/5711] pwm: Remove a redundant error message when devm_request_and_ioremap fails The implementation in devm_request_and_ioremap() already shows error message, so no need to show dev_err again if devm_request_and_ioremap() fails. Signed-off-by: Axel Lin Cc: Stephen Warren Cc: Philip, Avinash Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tegra.c | 4 +--- drivers/pwm/pwm-tiecap.c | 4 +--- drivers/pwm/pwm-tiehrpwm.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 02ce18d5e49a..057465e0553c 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -187,10 +187,8 @@ static int tegra_pwm_probe(struct platform_device *pdev) } pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pwm->mmio_base) { - dev_err(&pdev->dev, "failed to ioremap() region\n"); + if (!pwm->mmio_base) return -EADDRNOTAVAIL; - } platform_set_drvdata(pdev, pwm); diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 3c2ad284ee3e..0b66d0f25922 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -192,10 +192,8 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev) } pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pc->mmio_base) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); + if (!pc->mmio_base) return -EADDRNOTAVAIL; - } ret = pwmchip_add(&pc->chip); if (ret < 0) { diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 010d232cb0c8..c3756d1be194 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -371,10 +371,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) } pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pc->mmio_base) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); + if (!pc->mmio_base) return -EADDRNOTAVAIL; - } ret = pwmchip_add(&pc->chip); if (ret < 0) { -- GitLab From eba7cbe5d8bbc3bc24f46973e44f1566f81d1f56 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 10 Aug 2012 10:12:09 +0530 Subject: [PATCH 5562/5711] pwm: vt8500: Fix coding style issue Fixes the following: WARNING: Prefer pr_warn(... to pr_warning(... pr_warning("Waiting for status bits 0x%x to clear timed out\n", Signed-off-by: Sachin Kamat Signed-off-by: Thierry Reding --- drivers/pwm/pwm-vt8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index 548021439f0c..ad14389b7144 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -41,7 +41,7 @@ static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) cpu_relax(); if (unlikely(!loops)) - pr_warning("Waiting for status bits 0x%x to clear timed out\n", + pr_warn("Waiting for status bits 0x%x to clear timed out\n", bitmask); } -- GitLab From e50d3523ff45646a48666ebbd3d8aeb0c75084ed Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 10 Aug 2012 16:41:13 +0530 Subject: [PATCH 5563/5711] pwm: core: Fix coding style issues Fixes the following: WARNING: line over 80 characters ERROR: spaces required around that ':' (ctx:VxW) WARNING: Prefer pr_warn(... to pr_warning(... Signed-off-by: Sachin Kamat Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 4a8bdfa79e7f..c6e05078d3ad 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -129,8 +129,8 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) return 0; } -static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, - const struct of_phandle_args *args) +static struct pwm_device * +of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) { struct pwm_device *pwm; @@ -527,7 +527,7 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num) struct pwm_device *pwm_get(struct device *dev, const char *con_id) { struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); - const char *dev_id = dev ? dev_name(dev): NULL; + const char *dev_id = dev ? dev_name(dev) : NULL; struct pwm_chip *chip = NULL; unsigned int index = 0; unsigned int best = 0; @@ -609,7 +609,7 @@ void pwm_put(struct pwm_device *pwm) mutex_lock(&pwm_lock); if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { - pr_warning("PWM device already freed\n"); + pr_warn("PWM device already freed\n"); goto out; } -- GitLab From 7a4c5de27efa4c2ecca87af0a3deea63446367e2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 10 Aug 2012 13:57:52 -0400 Subject: [PATCH 5564/5711] ext4: don't call ext4_error while block group is locked While in ext4_validate_block_bitmap(), if an block allocation bitmap is found to be invalid, we call ext4_error() while the block group is still locked. This causes ext4_commit_super() to call a function which might sleep while in an atomic context. There's no need to keep the block group locked at this point, so hoist the ext4_error() call up to ext4_validate_block_bitmap() and release the block group spinlock before calling ext4_error(). The reported stack trace can be found at: http://article.gmane.org/gmane.comp.file-systems.ext4/33731 Reported-by: Dave Jones Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/balloc.c | 62 +++++++++++++++++++++++++++++------------------- fs/ext4/bitmap.c | 1 - 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index d23b31ca9d7a..1b5089067d01 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, return desc; } -static int ext4_valid_block_bitmap(struct super_block *sb, - struct ext4_group_desc *desc, - unsigned int block_group, - struct buffer_head *bh) +/* + * Return the block number which was discovered to be invalid, or 0 if + * the block bitmap is valid. + */ +static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, + struct ext4_group_desc *desc, + unsigned int block_group, + struct buffer_head *bh) { ext4_grpblk_t offset; ext4_grpblk_t next_zero_bit; - ext4_fsblk_t bitmap_blk; + ext4_fsblk_t blk; ext4_fsblk_t group_first_block; if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { @@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb, * or it has to also read the block group where the bitmaps * are located to verify they are set. */ - return 1; + return 0; } group_first_block = ext4_group_first_block_no(sb, block_group); /* check whether block bitmap block number is set */ - bitmap_blk = ext4_block_bitmap(sb, desc); - offset = bitmap_blk - group_first_block; + blk = ext4_block_bitmap(sb, desc); + offset = blk - group_first_block; if (!ext4_test_bit(offset, bh->b_data)) /* bad block bitmap */ - goto err_out; + return blk; /* check whether the inode bitmap block number is set */ - bitmap_blk = ext4_inode_bitmap(sb, desc); - offset = bitmap_blk - group_first_block; + blk = ext4_inode_bitmap(sb, desc); + offset = blk - group_first_block; if (!ext4_test_bit(offset, bh->b_data)) /* bad block bitmap */ - goto err_out; + return blk; /* check whether the inode table block number is set */ - bitmap_blk = ext4_inode_table(sb, desc); - offset = bitmap_blk - group_first_block; + blk = ext4_inode_table(sb, desc); + offset = blk - group_first_block; next_zero_bit = ext4_find_next_zero_bit(bh->b_data, offset + EXT4_SB(sb)->s_itb_per_group, offset); - if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) - /* good bitmap for inode tables */ - return 1; - -err_out: - ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", - block_group, bitmap_blk); + if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) + /* bad bitmap for inode tables */ + return blk; return 0; } @@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb, unsigned int block_group, struct buffer_head *bh) { + ext4_fsblk_t blk; + if (buffer_verified(bh)) return; ext4_lock_group(sb, block_group); - if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && - ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8)) - set_buffer_verified(bh); + blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); + if (unlikely(blk != 0)) { + ext4_unlock_group(sb, block_group); + ext4_error(sb, "bg %u: block %llu: invalid block bitmap", + block_group, blk); + return; + } + if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, + desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { + ext4_unlock_group(sb, block_group); + ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); + return; + } + set_buffer_verified(bh); ext4_unlock_group(sb, block_group); } diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index f8716eab9995..5c2d1813ebe9 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, if (provided == calculated) return 1; - ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group); return 0; } -- GitLab From 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 16 Aug 2012 11:59:04 -0400 Subject: [PATCH 5565/5711] ext4: fix long mount times on very big file systems Commit 8aeb00ff85a: "ext4: fix overhead calculation used by ext4_statfs()" introduced a O(n**2) calculation which makes very large file systems take forever to mount. Fix this with an optimization for non-bigalloc file systems. (For bigalloc file systems the overhead needs to be set in the the superblock.) Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 56bcaec9149c..598498904035 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3120,6 +3120,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, ext4_group_t i, ngroups = ext4_get_groups_count(sb); int s, j, count = 0; + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + + sbi->s_itb_per_group + 2); + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + (grp * EXT4_BLOCKS_PER_GROUP(sb)); last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; -- GitLab From 89a4e48f8479f8145eca9698f39fe188c982212f Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 17 Aug 2012 08:54:52 -0400 Subject: [PATCH 5566/5711] ext4: fix kernel BUG on large-scale rm -rf commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 968dee7722: "ext4: fix hole punch failure when depth is greater than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel crashes when users ran run "rm -rf" on large directory hierarchy on ext4 filesystems on RAID devices: BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710) Call Trace: [] ? __ext4_handle_dirty_metadata+0x83/0x110 [] ext4_ext_truncate+0x193/0x1d0 [] ? ext4_mark_inode_dirty+0x7f/0x1f0 [] ext4_truncate+0xf5/0x100 [] ext4_evict_inode+0x461/0x490 [] evict+0xa2/0x1a0 [] iput+0x103/0x1f0 [] do_unlinkat+0x154/0x1c0 [] ? sys_newfstatat+0x2a/0x40 [] sys_unlinkat+0x1b/0x50 [] system_call_fastpath+0x16/0x1b Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00 RIP [] ext4_ext_remove_space+0xa34/0xdf0 This could be reproduced as follows: The problem in commit 968dee7722 was that caused the variable 'i' to be left uninitialized if the truncate required more space than was available in the journal. This resulted in the function ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused ext4_ext_remove_space() to restart the truncate operation after starting a new jbd2 handle. Reported-by: Maciej Żenczykowski Reported-by: Marti Raudsepp Tested-by: Fengguang Wu Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/extents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index cd0c7ed06772..aabbb3f53683 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2662,6 +2662,7 @@ cont: } path[0].p_depth = depth; path[0].p_hdr = ext_inode_hdr(inode); + i = 0; if (ext4_ext_check(inode, path[0].p_hdr, depth)) { err = -EIO; -- GitLab From d807ff838f48e7778996e577e2a57a5796c32e84 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 17 Aug 2012 11:09:04 +0800 Subject: [PATCH 5567/5711] autofs4 - fix expire check In some cases when an autofs indirect mount is contained in a file system that is marked as shared (such as when systemd does the equivalent of "mount --make-rshared /" early in the boot), mounts stop expiring. When this happens the first expiry check on a mountpoint dentry in autofs_expire_indirect() sees a mountpoint dentry with a higher than minimal reference count. Consequently the dentry is condidered busy and the actual expiry check is never done. This particular check was originally meant as an optimisation to detect a path walk in progress but with the addition of rcu-walk it can be ineffective anyway. Removing the test allows automounts to expire again since the actual expire check doesn't rely on the dentry reference count. Signed-off-by: Ian Kent Signed-off-by: Linus Torvalds --- fs/autofs4/expire.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 8c0e56d92938..842d00048a65 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -399,11 +399,6 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, DPRINTK("checking mountpoint %p %.*s", dentry, (int)dentry->d_name.len, dentry->d_name.name); - /* Path walk currently on this dentry? */ - ino_count = atomic_read(&ino->count) + 2; - if (dentry->d_count > ino_count) - goto next; - /* Can we umount this guy */ if (autofs4_mount_busy(mnt, dentry)) goto next; -- GitLab From 0df7c0e3a73f5d12bca24d81ee5ed52947b372b6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 16 Aug 2012 16:23:20 -0700 Subject: [PATCH 5568/5711] scripts/kernel-doc: fix fatal script error Fix fatal error in scripts/kernel-doc by ignoring the "__weak" attribute: Error(drivers/pci/pci.c:2820): cannot understand prototype: 'char * __weak pcibios_setup(char *str) ' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- scripts/kernel-doc | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9b0c0b8b4ab4..8fd107a3fac4 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1786,6 +1786,7 @@ sub dump_function($$) { $prototype =~ s/__init +//; $prototype =~ s/__init_or_module +//; $prototype =~ s/__must_check +//; + $prototype =~ s/__weak +//; $prototype =~ s/^#\s*define\s+//; #ak added $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; -- GitLab From 7f321c26c04807834fef4c524d2b21573423fc74 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 21:31:45 +0200 Subject: [PATCH 5569/5711] PM / Runtime: Fix rpm_resume() return value for power.no_callbacks set For devices whose power.no_callbacks flag is set, rpm_resume() should return 1 if the device's parent is already active, so that the callers of pm_runtime_get() don't think that they have to wait for the device to resume (asynchronously) in that case (the core won't queue up an asynchronous resume in that case, so there's nothing to wait for anyway). Modify the code accordingly (and make sure that an idle notification will be queued up on success, even if 1 is to be returned). Signed-off-by: Rafael J. Wysocki Acked-by: Alan Stern Cc: stable@vger.kernel.org --- drivers/base/power/runtime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 59894873a3b3..9891a8559203 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -584,6 +584,7 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); + retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -664,7 +665,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (!retval) + if (retval >= 0) rpm_idle(dev, RPM_ASYNC); out: -- GitLab From 58a34de7b1a920d287d17d2ca08bc9aaf7e6d35b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 21:31:55 +0200 Subject: [PATCH 5570/5711] PM / Runtime: Clear power.deferred_resume on success in rpm_suspend() The power.deferred_resume can only be set if the runtime PM status of device is RPM_SUSPENDING and it should be cleared after its status has been changed, regardless of whether or not the runtime suspend has been successful. However, it only is cleared on suspend failure, while it may remain set on successful suspend and is happily leaked to rpm_resume() executed in that case. That shouldn't happen, so if power.deferred_resume is set in rpm_suspend() after the status has been changed to RPM_SUSPENDED, clear it before calling rpm_resume(). Then, it doesn't need to be cleared before changing the status to RPM_SUSPENDING any more, because it's always cleared after the status has been changed to either RPM_SUSPENDED (on success) or RPM_ACTIVE (on failure). Signed-off-by: Rafael J. Wysocki Acked-by: Alan Stern Cc: stable@vger.kernel.org --- drivers/base/power/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 9891a8559203..b6e9d9b7982d 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -388,7 +388,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } - dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -440,6 +439,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { + dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; -- GitLab From 55d7ec4520e86d735d178c15d7df33d507bd43c6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 21:32:04 +0200 Subject: [PATCH 5571/5711] PM / Runtime: Check device PM QoS setting before "no callbacks" check If __dev_pm_qos_read_value(dev) returns a negative value, rpm_suspend() should return -EPERM for dev even if its power.no_callbacks flag is set. For this to happen, the device's power.no_callbacks flag has to be checked after the PM QoS check, so move the PM QoS check to rpm_check_suspend_allowed() (this will make it cover idle notifications as well as runtime suspend too). Signed-off-by: Rafael J. Wysocki Acked-by: Alan Stern Cc: stable@vger.kernel.org --- drivers/base/power/runtime.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index b6e9d9b7982d..7d9c1cb1c39a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev) || (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME)) retval = -EAGAIN; + else if (__dev_pm_qos_read_value(dev) < 0) + retval = -EPERM; else if (dev->power.runtime_status == RPM_SUSPENDED) retval = 1; @@ -402,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto out; } - if (__dev_pm_qos_read_value(dev) < 0) { - /* Negative PM QoS constraint means "never suspend". */ - retval = -EPERM; - goto out; - } - __update_runtime_status(dev, RPM_SUSPENDING); if (dev->pm_domain) -- GitLab From 63c6ba4352009a5f85b32307c001abeb5baebd28 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 15 Aug 2012 22:10:50 +0200 Subject: [PATCH 5572/5711] cpuidle: coupled: fix sleeping while atomic in cpu notifier The cpu hotplug notifier gets called in both atomic and non-atomic contexts, it is not always safe to lock a mutex. Filter out all events except the six necessary ones, which are all sleepable, before taking the mutex. Signed-off-by: Colin Cross Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/coupled.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index 2c9bf2692232..c24dda03c143 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -678,6 +678,18 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, int cpu = (unsigned long)hcpu; struct cpuidle_device *dev; + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + case CPU_DOWN_PREPARE: + case CPU_ONLINE: + case CPU_DEAD: + case CPU_UP_CANCELED: + case CPU_DOWN_FAILED: + break; + default: + return NOTIFY_OK; + } + mutex_lock(&cpuidle_lock); dev = per_cpu(cpuidle_devices, cpu); -- GitLab From 5fbbb90dfdedb9a258550e4e5debd3013266372e Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Wed, 15 Aug 2012 22:11:00 +0200 Subject: [PATCH 5573/5711] cpuidle: Prevent null pointer dereference in cpuidle_coupled_cpu_notify When a kernel is built to support multiple hardware types it's possible that CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is set but the hardware the kernel is run on doesn't support cpuidle and therefore doesn't load a driver for it. In this case, when the system is shut down, cpuidle_coupled_cpu_notify() gets called with cpuidle_devices set to NULL. There are quite possibly other circumstances where this situation can also occur and we should check for it. Signed-off-by: Jon Medhurst Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/coupled.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index c24dda03c143..3265844839bf 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -693,7 +693,7 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, mutex_lock(&cpuidle_lock); dev = per_cpu(cpuidle_devices, cpu); - if (!dev->coupled) + if (!dev || !dev->coupled) goto out; switch (action & ~CPU_TASKS_FROZEN) { -- GitLab From 3735d524da64b70b41c764359da36f88aded3610 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Aug 2012 22:06:55 +0200 Subject: [PATCH 5574/5711] intel_idle: Check cpu_idle_get_driver() for NULL before dereferencing it. If the machine is booted without any cpu_idle driver set (b/c disable_cpuidle() has been called) we should follow other users of cpu_idle API and check the return value for NULL before using it. Reported-and-tested-by: Mark van Dijk Suggested-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Rafael J. Wysocki --- drivers/idle/intel_idle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index f559088869f6..e8726177d103 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -606,8 +606,9 @@ static int __init intel_idle_init(void) intel_idle_cpuidle_driver_init(); retval = cpuidle_register_driver(&intel_idle_driver); if (retval) { + struct cpuidle_driver *drv = cpuidle_get_driver(); printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", - cpuidle_get_driver()->name); + drv ? drv->name : "none"); return retval; } -- GitLab From 7e30ed6bdd91ae73c34fc37b57fcccc8640641f9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 9 Aug 2012 12:47:00 -0400 Subject: [PATCH 5575/5711] gmux: Add generic write32 function Move the special-cased backlight update function to a generic gmux_write32 function. Signed-off-by: Matthew Garrett Cc: Seth Forshee --- drivers/platform/x86/apple-gmux.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 905fa01ac8df..c9db50729f6f 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -75,6 +75,18 @@ static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) return inl(gmux_data->iostart + port); } +static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + int i; + u8 tmpval; + + for (i = 0; i < 4; i++) { + tmpval = (val >> (i * 8)) & 0xff; + outb(tmpval, port + i); + } +} + static int gmux_get_brightness(struct backlight_device *bd) { struct apple_gmux_data *gmux_data = bl_get_data(bd); @@ -90,16 +102,7 @@ static int gmux_update_status(struct backlight_device *bd) if (bd->props.state & BL_CORE_SUSPENDED) return 0; - /* - * Older gmux versions require writing out lower bytes first then - * setting the upper byte to 0 to flush the values. Newer versions - * accept a single u32 write, but the old method also works, so we - * just use the old method for all gmux versions. - */ - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0); + gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); return 0; } -- GitLab From 96ff705638e3d61b1e45a047c0f9f3bb622fa32f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 9 Aug 2012 13:45:01 -0400 Subject: [PATCH 5576/5711] apple_gmux: Add support for newer hardware New gmux devices have a different method for accessing the registers. Update the driver to cope. Incorporates feedback from Bernhard Froemel. Signed-off-by: Matthew Garrett Cc: Bernhard Froemel Cc: Seth Forshee --- drivers/platform/x86/apple-gmux.c | 179 +++++++++++++++++++++++++++--- 1 file changed, 165 insertions(+), 14 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index c9db50729f6f..0d140e1879e7 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -18,12 +18,15 @@ #include #include #include +#include #include #include struct apple_gmux_data { unsigned long iostart; unsigned long iolen; + bool indexed; + struct mutex index_lock; struct backlight_device *bdev; }; @@ -45,6 +48,9 @@ struct apple_gmux_data { #define GMUX_PORT_DISCRETE_POWER 0x50 #define GMUX_PORT_MAX_BRIGHTNESS 0x70 #define GMUX_PORT_BRIGHTNESS 0x74 +#define GMUX_PORT_VALUE 0xc2 +#define GMUX_PORT_READ 0xd0 +#define GMUX_PORT_WRITE 0xd4 #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) @@ -59,24 +65,24 @@ struct apple_gmux_data { #define GMUX_BRIGHTNESS_MASK 0x00ffffff #define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK -static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) { return inb(gmux_data->iostart + port); } -static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port, +static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port, u8 val) { outb(val, gmux_data->iostart + port); } -static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port) { return inl(gmux_data->iostart + port); } -static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port, - u32 val) +static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) { int i; u8 tmpval; @@ -87,6 +93,144 @@ static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port, } } +static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data) +{ + int i = 200; + u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + + while (i && (gwr & 0x01)) { + inb(gmux_data->iostart + GMUX_PORT_READ); + gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + udelay(100); + i--; + } + + return !!i; +} + +static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data) +{ + int i = 200; + u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + + while (i && !(gwr & 0x01)) { + gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + udelay(100); + i--; + } + + if (gwr & 0x01) + inb(gmux_data->iostart + GMUX_PORT_READ); + + return !!i; +} + +static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) +{ + u8 val; + + mutex_lock(&gmux_data->index_lock); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_ready(gmux_data); + val = inb(gmux_data->iostart + GMUX_PORT_VALUE); + mutex_unlock(&gmux_data->index_lock); + + return val; +} + +static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port, + u8 val) +{ + mutex_lock(&gmux_data->index_lock); + outb(val, gmux_data->iostart + GMUX_PORT_VALUE); + gmux_index_wait_ready(gmux_data); + outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); + gmux_index_wait_complete(gmux_data); + mutex_unlock(&gmux_data->index_lock); +} + +static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) +{ + u32 val; + + mutex_lock(&gmux_data->index_lock); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_ready(gmux_data); + val = inl(gmux_data->iostart + GMUX_PORT_VALUE); + mutex_unlock(&gmux_data->index_lock); + + return val; +} + +static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + int i; + u8 tmpval; + + mutex_lock(&gmux_data->index_lock); + + for (i = 0; i < 4; i++) { + tmpval = (val >> (i * 8)) & 0xff; + outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); + } + + gmux_index_wait_ready(gmux_data); + outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); + gmux_index_wait_complete(gmux_data); + mutex_unlock(&gmux_data->index_lock); +} + +static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +{ + if (gmux_data->indexed) + return gmux_index_read8(gmux_data, port); + else + return gmux_pio_read8(gmux_data, port); +} + +static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) +{ + if (gmux_data->indexed) + gmux_index_write8(gmux_data, port, val); + else + gmux_pio_write8(gmux_data, port, val); +} + +static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +{ + if (gmux_data->indexed) + return gmux_index_read32(gmux_data, port); + else + return gmux_pio_read32(gmux_data, port); +} + +static void gmux_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + if (gmux_data->indexed) + gmux_index_write32(gmux_data, port, val); + else + gmux_pio_write32(gmux_data, port, val); +} + +static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) +{ + u16 val; + + outb(0xaa, gmux_data->iostart + 0xcc); + outb(0x55, gmux_data->iostart + 0xcd); + outb(0x00, gmux_data->iostart + 0xce); + + val = inb(gmux_data->iostart + 0xcc) | + (inb(gmux_data->iostart + 0xcd) << 8); + + if (val == 0x55aa) + return true; + + return false; +} + static int gmux_get_brightness(struct backlight_device *bd) { struct apple_gmux_data *gmux_data = bl_get_data(bd); @@ -150,22 +294,29 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, } /* - * On some machines the gmux is in ACPI even thought the machine - * doesn't really have a gmux. Check for invalid version information - * to detect this. + * Invalid version information may indicate either that the gmux + * device isn't present or that it's a new one that uses indexed + * io */ + ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { - pr_info("gmux device not present\n"); - ret = -ENODEV; - goto err_release; + if (gmux_is_indexed(gmux_data)) { + mutex_init(&gmux_data->index_lock); + gmux_data->indexed = true; + } else { + pr_info("gmux device not present\n"); + ret = -ENODEV; + goto err_release; + } + pr_info("Found indexed gmux\n"); + } else { + pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, + ver_release); } - pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, - ver_release); - memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); -- GitLab From 9f6f955ae4994dd4ad5513a0d959468763a45fa5 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 17 Aug 2012 16:57:20 -0400 Subject: [PATCH 5577/5711] apple_gmux: Fix ACPI video unregister We were only calling acpi_video_unregister() if ACPI video support was built in, not if it was a module. Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 0d140e1879e7..85e1bfbd1121 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -348,7 +348,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * Disable the other backlight choices. */ acpi_video_dmi_promote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_unregister(); #endif apple_bl_unregister(); @@ -371,7 +371,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) kfree(gmux_data); acpi_video_dmi_demote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_register(); #endif apple_bl_register(); -- GitLab From a50bd128f28cf81c1250874fc53728e113f12957 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Thu, 26 Jul 2012 17:13:31 +0800 Subject: [PATCH 5578/5711] asus-wmi: record wlan status while controlled by userapp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the user bit is set, that mean BIOS can't set and record the wlan status, it will report the value read from id ASUS_WMI_DEVID_WLAN_LED (0x00010012) while we query the wlan status by id ASUS_WMI_DEVID_WLAN (0x00010011) through WMI. So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED (0x00010012) while setting the wlan status through WMI. This is also the behavior that windows app will do. Quote from ASUS application engineer === When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return (1) 0x00050001 (On) (2) 0x00050000 (Off) (3) 0x00030001 (On) (4) 0x00030000 (Off) (5) 0x00000002 (Unknown) (1), (2) means that the model has hardware GPIO for WLAN, you can call WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off. (3), (4) means that the model doesn’t have hardware GPIO, you need to use API or driver library to turn WLAN on/off, and call WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status. After you set WLAN LED status, you can see the WLAN status is changed with WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly (ex: Windows), you can use it for synchronization. (5) means that the model doesn’t have WLAN device. WLAN is the ONLY special case with upper rule. For other device, like Bluetooth, you just need use WMIMethod(DSTS, 0x00010013) to get, and WMIMethod(DEVS, 0x00010013, 1 or 0) to set. === Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 21 ++++++++++++++++++++- drivers/platform/x86/asus-wmi.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c7a36f6b0580..2eb9fe8e8efd 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -101,6 +101,7 @@ MODULE_LICENSE("GPL"); #define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002 #define ASUS_WMI_DEVID_CWAP 0x00010003 #define ASUS_WMI_DEVID_WLAN 0x00010011 +#define ASUS_WMI_DEVID_WLAN_LED 0x00010012 #define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 #define ASUS_WMI_DEVID_GPS 0x00010015 #define ASUS_WMI_DEVID_WIMAX 0x00010017 @@ -731,8 +732,21 @@ static int asus_rfkill_set(void *data, bool blocked) { struct asus_rfkill *priv = data; u32 ctrl_param = !blocked; + u32 dev_id = priv->dev_id; - return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL); + /* + * If the user bit is set, BIOS can't set and record the wlan status, + * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED + * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN). + * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED + * while setting the wlan status through WMI. + * This is also the behavior that windows app will do. + */ + if ((dev_id == ASUS_WMI_DEVID_WLAN) && + priv->asus->driver->wlan_ctrl_by_user) + dev_id = ASUS_WMI_DEVID_WLAN_LED; + + return asus_wmi_set_devstate(dev_id, ctrl_param, NULL); } static void asus_rfkill_query(struct rfkill *rfkill, void *data) @@ -1653,6 +1667,7 @@ static int asus_wmi_add(struct platform_device *pdev) struct asus_wmi *asus; acpi_status status; int err; + u32 result; asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL); if (!asus) @@ -1711,6 +1726,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_debugfs; + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); + if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) + asus->driver->wlan_ctrl_by_user = 1; + return 0; fail_debugfs: diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 9c1da8b81bea..4c9bd38bb0a2 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -46,6 +46,7 @@ struct quirk_entry { struct asus_wmi_driver { int brightness; int panel_power; + int wlan_ctrl_by_user; const char *name; struct module *owner; -- GitLab From f94f0f103c440f1dbe5d89a28c92fd1a9bdf7012 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Thu, 2 Aug 2012 12:15:14 -0500 Subject: [PATCH 5579/5711] apple-gmux: Fix kconfig dependencies Fix the dependencies of apple-gmux to prevent it from being built-in when one or more of its dependencies is built as a module. Otherwise it can fail to build due to missing symbols. v2: Add dependency on ACPI to fix build failure when ACPI=n Reported-by: Arun Raghavan Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 2a262f5c5c0c..637074d89790 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -758,8 +758,11 @@ config SAMSUNG_Q10 config APPLE_GMUX tristate "Apple Gmux Driver" + depends on ACPI depends on PNP - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE + depends on ACPI_VIDEO=n || ACPI_VIDEO ---help--- This driver provides support for the gmux device found on many Apple laptops, which controls the display mux for the hybrid -- GitLab From 76b487dd5187a4d7cc6eccd452f65467a8c7768b Mon Sep 17 00:00:00 2001 From: Andreas Heider Date: Fri, 17 Aug 2012 11:17:04 -0500 Subject: [PATCH 5580/5711] apple-gmux: Add display mux support Add support for the gmux display muxing functionality and register a mux handler with vga_switcheroo. Signed-off-by: Andreas Heider Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 224 ++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 85e1bfbd1121..dfb1a92ce949 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -2,6 +2,7 @@ * Gmux driver for Apple laptops * * Copyright (C) Canonical Ltd. + * Copyright (C) 2010-2012 Andreas Heider * * 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 @@ -19,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -29,8 +32,17 @@ struct apple_gmux_data { struct mutex index_lock; struct backlight_device *bdev; + + /* switcheroo data */ + acpi_handle dhandle; + int gpe; + enum vga_switcheroo_client_id resume_client_id; + enum vga_switcheroo_state power_state; + struct completion powerchange_done; }; +static struct apple_gmux_data *apple_gmux_data; + /* * gmux port offsets. Many of these are not yet used, but may be in the * future, and it's useful to have them documented here anyhow. @@ -257,6 +269,146 @@ static const struct backlight_ops gmux_bl_ops = { .update_status = gmux_update_status, }; +static int gmux_switchto(enum vga_switcheroo_client_id id) +{ + if (id == VGA_SWITCHEROO_IGD) { + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); + } else { + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); + } + + return 0; +} + +static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data, + enum vga_switcheroo_state state) +{ + INIT_COMPLETION(gmux_data->powerchange_done); + + if (state == VGA_SWITCHEROO_ON) { + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3); + pr_debug("Discrete card powered up\n"); + } else { + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); + pr_debug("Discrete card powered down\n"); + } + + gmux_data->power_state = state; + + if (gmux_data->gpe >= 0 && + !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, + msecs_to_jiffies(200))) + pr_warn("Timeout waiting for gmux switch to complete\n"); + + return 0; +} + +static int gmux_set_power_state(enum vga_switcheroo_client_id id, + enum vga_switcheroo_state state) +{ + if (id == VGA_SWITCHEROO_IGD) + return 0; + + return gmux_set_discrete_state(apple_gmux_data, state); +} + +static int gmux_get_client_id(struct pci_dev *pdev) +{ + /* + * Early Macbook Pros with switchable graphics use nvidia + * integrated graphics. Hardcode that the 9400M is integrated. + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + return VGA_SWITCHEROO_IGD; + else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && + pdev->device == 0x0863) + return VGA_SWITCHEROO_IGD; + else + return VGA_SWITCHEROO_DIS; +} + +static enum vga_switcheroo_client_id +gmux_active_client(struct apple_gmux_data *gmux_data) +{ + if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) + return VGA_SWITCHEROO_IGD; + + return VGA_SWITCHEROO_DIS; +} + +static struct vga_switcheroo_handler gmux_handler = { + .switchto = gmux_switchto, + .power_state = gmux_set_power_state, + .get_client_id = gmux_get_client_id, +}; + +static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data) +{ + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, + GMUX_INTERRUPT_DISABLE); +} + +static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data) +{ + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, + GMUX_INTERRUPT_ENABLE); +} + +static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data) +{ + return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS); +} + +static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data) +{ + u8 status; + + /* to clear interrupts write back current status */ + status = gmux_interrupt_get_status(gmux_data); + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status); +} + +static void gmux_notify_handler(acpi_handle device, u32 value, void *context) +{ + u8 status; + struct pnp_dev *pnp = (struct pnp_dev *)context; + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + + status = gmux_interrupt_get_status(gmux_data); + gmux_disable_interrupts(gmux_data); + pr_debug("Notify handler called: status %d\n", status); + + gmux_clear_interrupts(gmux_data); + gmux_enable_interrupts(gmux_data); + + if (status & GMUX_INTERRUPT_STATUS_POWER) + complete(&gmux_data->powerchange_done); +} + +static int gmux_suspend(struct pnp_dev *pnp, pm_message_t state) +{ + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + gmux_data->resume_client_id = gmux_active_client(gmux_data); + gmux_disable_interrupts(gmux_data); + return 0; +} + +static int gmux_resume(struct pnp_dev *pnp) +{ + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + gmux_enable_interrupts(gmux_data); + gmux_switchto(gmux_data->resume_client_id); + if (gmux_data->power_state == VGA_SWITCHEROO_OFF) + gmux_set_discrete_state(gmux_data, gmux_data->power_state); + return 0; +} + static int __devinit gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) { @@ -266,6 +418,11 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, struct backlight_device *bdev; u8 ver_major, ver_minor, ver_release; int ret = -ENXIO; + acpi_status status; + unsigned long long gpe; + + if (apple_gmux_data) + return -EBUSY; gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); if (!gmux_data) @@ -353,8 +510,62 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, #endif apple_bl_unregister(); + gmux_data->power_state = VGA_SWITCHEROO_ON; + + gmux_data->dhandle = DEVICE_ACPI_HANDLE(&pnp->dev); + if (!gmux_data->dhandle) { + pr_err("Cannot find acpi handle for pnp device %s\n", + dev_name(&pnp->dev)); + ret = -ENODEV; + goto err_notify; + } + + status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); + if (ACPI_SUCCESS(status)) { + gmux_data->gpe = (int)gpe; + + status = acpi_install_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler, pnp); + if (ACPI_FAILURE(status)) { + pr_err("Install notify handler failed: %s\n", + acpi_format_exception(status)); + ret = -ENODEV; + goto err_notify; + } + + status = acpi_enable_gpe(NULL, gmux_data->gpe); + if (ACPI_FAILURE(status)) { + pr_err("Cannot enable gpe: %s\n", + acpi_format_exception(status)); + goto err_enable_gpe; + } + } else { + pr_warn("No GPE found for gmux\n"); + gmux_data->gpe = -1; + } + + if (vga_switcheroo_register_handler(&gmux_handler)) { + ret = -ENODEV; + goto err_register_handler; + } + + init_completion(&gmux_data->powerchange_done); + apple_gmux_data = gmux_data; + gmux_enable_interrupts(gmux_data); + return 0; +err_register_handler: + if (gmux_data->gpe >= 0) + acpi_disable_gpe(NULL, gmux_data->gpe); +err_enable_gpe: + if (gmux_data->gpe >= 0) + acpi_remove_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler); +err_notify: + backlight_device_unregister(bdev); err_release: release_region(gmux_data->iostart, gmux_data->iolen); err_free: @@ -366,8 +577,19 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) { struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + vga_switcheroo_unregister_handler(); + gmux_disable_interrupts(gmux_data); + if (gmux_data->gpe >= 0) { + acpi_disable_gpe(NULL, gmux_data->gpe); + acpi_remove_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler); + } + backlight_device_unregister(gmux_data->bdev); + release_region(gmux_data->iostart, gmux_data->iolen); + apple_gmux_data = NULL; kfree(gmux_data); acpi_video_dmi_demote_vendor(); @@ -387,6 +609,8 @@ static struct pnp_driver gmux_pnp_driver = { .probe = gmux_probe, .remove = __devexit_p(gmux_remove), .id_table = gmux_device_ids, + .suspend = gmux_suspend, + .resume = gmux_resume }; static int __init apple_gmux_init(void) -- GitLab From 36704c0c4c64f889d77158d497f6a7e596d1341c Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Fri, 17 Aug 2012 11:17:03 -0500 Subject: [PATCH 5581/5711] vga_switcheroo: Remove assumptions about registration/unregistration ordering vga_switcheroo assumes that the handler will be registered before the last client, otherwise switching will not be enabled. Likewise it's assumed that the handler will not be unregistered without at least one client also being unregistered, otherwise switching will remain enabled despite no longer having a handler. These assumptions cannot be enforced if the handler is in a separate driver from both clients, as with the gmux found in Apple laptops. Remove this assumption. Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/gpu/vga/vga_switcheroo.c | 58 ++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d135dc9..e10ba3755dfa 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -70,27 +70,12 @@ static struct vgasr_priv vgasr_priv = { .clients = LIST_HEAD_INIT(vgasr_priv.clients), }; -int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) -{ - mutex_lock(&vgasr_mutex); - if (vgasr_priv.handler) { - mutex_unlock(&vgasr_mutex); - return -EINVAL; - } - - vgasr_priv.handler = handler; - mutex_unlock(&vgasr_mutex); - return 0; -} -EXPORT_SYMBOL(vga_switcheroo_register_handler); - -void vga_switcheroo_unregister_handler(void) +static bool vga_switcheroo_ready(void) { - mutex_lock(&vgasr_mutex); - vgasr_priv.handler = NULL; - mutex_unlock(&vgasr_mutex); + /* we're ready if we get two clients + handler */ + return !vgasr_priv.active && + vgasr_priv.registered_clients == 2 && vgasr_priv.handler; } -EXPORT_SYMBOL(vga_switcheroo_unregister_handler); static void vga_switcheroo_enable(void) { @@ -113,6 +98,37 @@ static void vga_switcheroo_enable(void) vgasr_priv.active = true; } +int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) +{ + mutex_lock(&vgasr_mutex); + if (vgasr_priv.handler) { + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } + + vgasr_priv.handler = handler; + if (vga_switcheroo_ready()) { + printk(KERN_INFO "vga_switcheroo: enabled\n"); + vga_switcheroo_enable(); + } + mutex_unlock(&vgasr_mutex); + return 0; +} +EXPORT_SYMBOL(vga_switcheroo_register_handler); + +void vga_switcheroo_unregister_handler(void) +{ + mutex_lock(&vgasr_mutex); + vgasr_priv.handler = NULL; + if (vgasr_priv.active) { + pr_info("vga_switcheroo: disabled\n"); + vga_switcheroo_debugfs_fini(&vgasr_priv); + vgasr_priv.active = false; + } + mutex_unlock(&vgasr_mutex); +} +EXPORT_SYMBOL(vga_switcheroo_unregister_handler); + static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, int id, bool active) @@ -134,9 +150,7 @@ static int register_client(struct pci_dev *pdev, if (client_is_vga(client)) vgasr_priv.registered_clients++; - /* if we get two clients + handler */ - if (!vgasr_priv.active && - vgasr_priv.registered_clients == 2 && vgasr_priv.handler) { + if (vga_switcheroo_ready()) { printk(KERN_INFO "vga_switcheroo: enabled\n"); vga_switcheroo_enable(); } -- GitLab From e99eac5e4ea3bd8671bb1cedad10c3fec90ec0de Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Fri, 17 Aug 2012 11:17:02 -0500 Subject: [PATCH 5582/5711] vga_switcheroo: Don't require handler init callback This callback is a no-op in nouveau, and the upcoming apple-gmux switcheroo support won't require it either. Rather than forcing drivers to stub it out, just make it optional and remove the callback from nouveau. Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 6 ------ drivers/gpu/vga/vga_switcheroo.c | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index fc841e87b343..26ebffebe710 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -211,11 +211,6 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } -static int nouveau_dsm_init(void) -{ - return 0; -} - static int nouveau_dsm_get_client_id(struct pci_dev *pdev) { /* easy option one - intel vendor ID means Integrated */ @@ -232,7 +227,6 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev) static struct vga_switcheroo_handler nouveau_dsm_handler = { .switchto = nouveau_dsm_switchto, .power_state = nouveau_dsm_power_state, - .init = nouveau_dsm_init, .get_client_id = nouveau_dsm_get_client_id, }; diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index e10ba3755dfa..e25cf31faab2 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -83,7 +83,8 @@ static void vga_switcheroo_enable(void) struct vga_switcheroo_client *client; /* call the handler to init */ - vgasr_priv.handler->init(); + if (vgasr_priv.handler->init) + vgasr_priv.handler->init(); list_for_each_entry(client, &vgasr_priv.clients, list) { if (client->id != -1) -- GitLab From a2174ba29a3026d50aa0b59297821ea9cccd75cc Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Mon, 6 Aug 2012 09:48:58 +0800 Subject: [PATCH 5583/5711] dell-laptop: Fixed typo in touchpad LED quirk Fixed the typo introduced from the below commit 5f1e88f dell-laptop: Add 6 machines to touchpad led quirk Reported-by: Carlos Alberto Lopez Perez Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 4e96e8c0b60f..927c33af67ec 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -211,7 +211,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -220,7 +220,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -229,7 +229,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5720"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -247,7 +247,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -256,7 +256,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7720"), }, .driver_data = &quirk_dell_vostro_v130, }, -- GitLab From a4f46bb9fa84642e356898ee44b670989622f8bb Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Mon, 6 Aug 2012 18:15:37 -0500 Subject: [PATCH 5584/5711] thinkpad-acpi: recognize latest V-Series using DMI_BIOS_VENDOR In the latest V-series bios DMI_PRODUCT_VERSION does not contain the string Lenovo or Thinkpad, but is set to the model number, this causes the thinkpad_acpi module to fail to load. Recognize laptop as Lenovo using DMI_BIOS_VENDOR instead, which is set to Lenovo. Test on V490u ============= == After the patch == [ 1350.295757] thinkpad_acpi: ThinkPad ACPI Extras v0.24 [ 1350.295760] thinkpad_acpi: http://ibm-acpi.sf.net/ [ 1350.295761] thinkpad_acpi: ThinkPad BIOS H7ET21WW (1.00 ), EC unknown [ 1350.295763] thinkpad_acpi: Lenovo LENOVO, model LV5DXXX [ 1350.296086] thinkpad_acpi: detected a 8-level brightness capable ThinkPad [ 1350.296694] thinkpad_acpi: radio switch found; radios are enabled [ 1350.296703] thinkpad_acpi: possible tablet mode switch found; ThinkPad in laptop mode [ 1350.306466] thinkpad_acpi: rfkill switch tpacpi_bluetooth_sw: radio is unblocked [ 1350.307082] Registered led device: tpacpi::thinklight [ 1350.307215] Registered led device: tpacpi::power [ 1350.307255] Registered led device: tpacpi::standby [ 1350.307294] Registered led device: tpacpi::thinkvantage [ 1350.308160] thinkpad_acpi: Standard ACPI backlight interface available, not loading native one [ 1350.308333] thinkpad_acpi: Console audio control enabled, mode: monitor (read only) [ 1350.312287] input: ThinkPad Extra Buttons as /devices/platform/thinkpad_acpi/input/input14 == Before the patch == sudo modprobe thinkpad_acpi FATAL: Error inserting thinkpad_acpi (/lib/modules/3.2.0-27-generic/kernel/drivers/platform/x86/thinkpad_acpi.ko): No such device Test on B485 ============= This patch was also test in a B485 where the thinkpad_acpi module does not have any issues loading. But, I tested it to make sure this patch does not break on already functioning models of Lenovo products. [13486.746359] thinkpad_acpi: ThinkPad ACPI Extras v0.24 [13486.746364] thinkpad_acpi: http://ibm-acpi.sf.net/ [13486.746368] thinkpad_acpi: ThinkPad BIOS HJET15WW(1.01), EC unknown [13486.746373] thinkpad_acpi: Lenovo Lenovo LB485, model 814TR01 [13486.747300] thinkpad_acpi: detected a 8-level brightness capable ThinkPad [13486.752435] thinkpad_acpi: rfkill switch tpacpi_bluetooth_sw: radio is unblocked [13486.752883] Registered led device: tpacpi::thinklight [13486.752915] thinkpad_acpi: Standard ACPI backlight interface available, not loading native one [13486.753216] thinkpad_acpi: Console audio control enabled, mode: monitor (read only) [13486.757147] input: ThinkPad Extra Buttons as /devices/platform/thinkpad_acpi/input/input15 Signed-off-by: Manoj Iyer Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f28f36ccdcf4..80e377949314 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8664,6 +8664,13 @@ static int __must_check __init get_thinkpad_model_data( tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; + } else { + s = dmi_get_system_info(DMI_BIOS_VENDOR); + if (s && !(strnicmp(s, "Lenovo", 6))) { + tp->model_str = kstrdup(s, GFP_KERNEL); + if (!tp->model_str) + return -ENOMEM; + } } s = dmi_get_system_info(DMI_PRODUCT_NAME); -- GitLab From ad20c73b05ea40cfdb42758506fb6b6befa3c9e5 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Lopez Perez Date: Thu, 2 Aug 2012 19:50:21 +0200 Subject: [PATCH 5585/5711] classmate-laptop: always call input_sync() after input_report_switch() Due to commit cdda911c34006f1089f3c87b1a1f31ab3a4722f2 evdev only becomes readable when the buffer contains an EV_SYN/SYN_REPORT event. So in order to read the tablet sensor data as it happens we need to ensure that we always call input_sync() after input_report_switch() Signed-off-by: Carlos Alberto Lopez Perez Signed-off-by: Matthew Garrett --- drivers/platform/x86/classmate-laptop.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index cd33add118ce..c87ff16873f9 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -725,8 +725,10 @@ static void cmpc_tablet_handler(struct acpi_device *dev, u32 event) struct input_dev *inputdev = dev_get_drvdata(&dev->dev); if (event == 0x81) { - if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } } } @@ -739,8 +741,10 @@ static void cmpc_tablet_idev_init(struct input_dev *inputdev) set_bit(SW_TABLET_MODE, inputdev->swbit); acpi = to_acpi_device(inputdev->dev.parent); - if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } } static int cmpc_tablet_add(struct acpi_device *acpi) @@ -760,8 +764,10 @@ static int cmpc_tablet_resume(struct device *dev) struct input_dev *inputdev = dev_get_drvdata(dev); unsigned long long val = 0; - if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } return 0; } #endif -- GitLab From 939d5044b117302cabdd30833685d9f214e9bff6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 13:08:23 +0100 Subject: [PATCH 5586/5711] ASoC: wm5102: Remove DRC2 It will be removed from future device revisions. Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 496ce9a9d8be..e33d327396ad 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -128,13 +128,9 @@ SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), -ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), -ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), -SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, - ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), @@ -236,8 +232,6 @@ ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); -ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); -ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); @@ -349,10 +343,6 @@ SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, - NULL, 0), SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, NULL, 0), @@ -466,8 +456,6 @@ ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), -ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), -ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), @@ -553,8 +541,6 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), { name, "EQ4", "EQ4" }, \ { name, "DRC1L", "DRC1L" }, \ { name, "DRC1R", "DRC1R" }, \ - { name, "DRC2L", "DRC2L" }, \ - { name, "DRC2R", "DRC2R" }, \ { name, "LHPF1", "LHPF1" }, \ { name, "LHPF2", "LHPF2" }, \ { name, "LHPF3", "LHPF3" }, \ @@ -684,8 +670,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), - ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), - ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), -- GitLab From ccf795847a38235ee4a56a24129ce75147d6ba8f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 22:36:04 +0100 Subject: [PATCH 5587/5711] ASoC: wm9712: Fix microphone source selection Currently the microphone input source is not selectable as while there is a DAPM widget it's not connected to anything so it won't be properly instantiated. Add something more correct for the input structure to get things going, even though it's not hooked into the rest of the routing map and so won't actually achieve anything except allowing the relevant register bits to be written. Reported-by: Christop Fritz Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm9712.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index f16fb361a4eb..fd74b8843d34 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -272,7 +272,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]); /* Mic select */ static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[7]); +SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]); /* diff select */ static const struct snd_kcontrol_new wm9712_diff_sel_controls = @@ -291,7 +291,9 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectl_controls), SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, +SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0, + &wm9712_mic_src_controls), +SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, &wm9712_mic_src_controls), SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, &wm9712_diff_sel_controls), @@ -319,6 +321,7 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0), SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0), SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0), SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), +SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1), SND_SOC_DAPM_OUTPUT("MONOOUT"), SND_SOC_DAPM_OUTPUT("HPOUTL"), @@ -379,6 +382,18 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { {"Mic PGA", NULL, "MIC1"}, {"Mic PGA", NULL, "MIC2"}, + /* microphones */ + {"Differential Mic", NULL, "MIC1"}, + {"Differential Mic", NULL, "MIC2"}, + {"Left Mic Select Source", "Mic 1", "MIC1"}, + {"Left Mic Select Source", "Mic 2", "MIC2"}, + {"Left Mic Select Source", "Stereo", "MIC1"}, + {"Left Mic Select Source", "Differential", "Differential Mic"}, + {"Right Mic Select Source", "Mic 1", "MIC1"}, + {"Right Mic Select Source", "Mic 2", "MIC2"}, + {"Right Mic Select Source", "Stereo", "MIC2"}, + {"Right Mic Select Source", "Differential", "Differential Mic"}, + /* left capture selector */ {"Left Capture Select", "Mic", "MIC1"}, {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, -- GitLab From 28c42c28309244d0b15d1b385e33429d59997679 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:28 +0100 Subject: [PATCH 5588/5711] ASoC: wm9712: Fix inverted capture volume The capture volume increases with the register value so it shouldn't be flagged as inverted. Reported-by: Christoph Fritz Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index fd74b8843d34..c6d2076a796b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -148,7 +148,7 @@ SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), -SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), +SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), -- GitLab From 6887237cd7da904184dab2750504040c68f3a080 Mon Sep 17 00:00:00 2001 From: Michel JAOUEN Date: Fri, 17 Aug 2012 17:28:41 +0200 Subject: [PATCH 5589/5711] spi/pl022: fix spi-pl022 pm enable at probe amba drivers does not need to enable pm runtime at probe. amba_probe already enables pm runtime. This rids this warning in the ux500 boot log: ssp-pl022 ssp0: Unbalanced pm_runtime_enable! Signed-off-by: Michel JAOUEN Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index aab518ec2bbc..6abbe23c39b4 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2053,7 +2053,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); - pm_runtime_enable(dev); pm_runtime_resume(dev); pl022->clk = clk_get(&adev->dev, NULL); -- GitLab From a0c3652caa357b8f4e76efe401646ef298483cd9 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 16 Aug 2012 20:25:59 -0700 Subject: [PATCH 5590/5711] spi: spi-coldfire-qspi: Drop extra spi_master_put in device remove function The call sequence spi_alloc_master/spi_register_master/spi_unregister_master is complete; it reduces the device reference count to zero, which and results in device memory being freed. The subsequent call to spi_master_put is unnecessary and results in an access to free memory. Drop it. Signed-off-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index b2d4b9e4e010..1a30b47465cb 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -533,7 +533,6 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) iounmap(mcfqspi->iobase); release_mem_region(res->start, resource_size(res)); spi_unregister_master(master); - spi_master_put(master); return 0; } -- GitLab From af36107968f1b5faab0e4a0cc44fa4498c63f017 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 16 Aug 2012 20:26:00 -0700 Subject: [PATCH 5591/5711] spi/coldfire-qspi: Drop extra calls to spi_master_get in suspend/resume functions Suspend and resume functions call spi_master_get() without matching spi_master_put(). The extra references are unnecessary and cause subsequent module unload attempts to fail, so drop the calls. Signed-off-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 1a30b47465cb..764bfee75920 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -540,7 +540,7 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int mcfqspi_suspend(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_suspend(master); @@ -552,7 +552,7 @@ static int mcfqspi_suspend(struct device *dev) static int mcfqspi_resume(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_resume(master); -- GitLab From e0ee778528bbaad28a5c69d2e219269a3a096607 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 18 Aug 2012 09:51:42 +1000 Subject: [PATCH 5592/5711] md/raid10: fix problem with on-stack allocation of r10bio structure. A 'struct r10bio' has an array of per-copy information at the end. This array is declared with size [0] and r10bio_pool_alloc allocates enough extra space to store the per-copy information depending on the number of copies needed. So declaring a 'struct r10bio on the stack isn't going to work. It won't allocate enough space, and memory corruption will ensue. So in the two places where this is done, declare a sufficiently large structure and use that instead. The two call-sites of this bug were introduced in 3.4 and 3.5 so this is suitable for both those kernels. The patch will have to be modified for 3.4 as it only has one bug. Cc: stable@vger.kernel.org Reported-by: Ivan Vasilyev Tested-by: Ivan Vasilyev Signed-off-by: NeilBrown --- drivers/md/raid10.c | 30 +++++++++++++++++++----------- drivers/md/raid10.h | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index de5ed6fd8806..1c2eb38f3c51 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -659,7 +659,11 @@ static int raid10_mergeable_bvec(struct request_queue *q, max = biovec->bv_len; if (mddev->merge_check_needed) { - struct r10bio r10_bio; + struct { + struct r10bio r10_bio; + struct r10dev devs[conf->copies]; + } on_stack; + struct r10bio *r10_bio = &on_stack.r10_bio; int s; if (conf->reshape_progress != MaxSector) { /* Cannot give any guidance during reshape */ @@ -667,18 +671,18 @@ static int raid10_mergeable_bvec(struct request_queue *q, return biovec->bv_len; return 0; } - r10_bio.sector = sector; - raid10_find_phys(conf, &r10_bio); + r10_bio->sector = sector; + raid10_find_phys(conf, r10_bio); rcu_read_lock(); for (s = 0; s < conf->copies; s++) { - int disk = r10_bio.devs[s].devnum; + int disk = r10_bio->devs[s].devnum; struct md_rdev *rdev = rcu_dereference( conf->mirrors[disk].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio.devs[s].addr + bvm->bi_sector = r10_bio->devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( @@ -690,7 +694,7 @@ static int raid10_mergeable_bvec(struct request_queue *q, struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio.devs[s].addr + bvm->bi_sector = r10_bio->devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( @@ -4414,14 +4418,18 @@ static int handle_reshape_read_error(struct mddev *mddev, { /* Use sync reads to get the blocks from somewhere else */ int sectors = r10_bio->sectors; - struct r10bio r10b; struct r10conf *conf = mddev->private; + struct { + struct r10bio r10_bio; + struct r10dev devs[conf->copies]; + } on_stack; + struct r10bio *r10b = &on_stack.r10_bio; int slot = 0; int idx = 0; struct bio_vec *bvec = r10_bio->master_bio->bi_io_vec; - r10b.sector = r10_bio->sector; - __raid10_find_phys(&conf->prev, &r10b); + r10b->sector = r10_bio->sector; + __raid10_find_phys(&conf->prev, r10b); while (sectors) { int s = sectors; @@ -4432,7 +4440,7 @@ static int handle_reshape_read_error(struct mddev *mddev, s = PAGE_SIZE >> 9; while (!success) { - int d = r10b.devs[slot].devnum; + int d = r10b->devs[slot].devnum; struct md_rdev *rdev = conf->mirrors[d].rdev; sector_t addr; if (rdev == NULL || @@ -4440,7 +4448,7 @@ static int handle_reshape_read_error(struct mddev *mddev, !test_bit(In_sync, &rdev->flags)) goto failed; - addr = r10b.devs[slot].addr + idx * PAGE_SIZE; + addr = r10b->devs[slot].addr + idx * PAGE_SIZE; success = sync_page_io(rdev, addr, s << 9, diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 007c2c68dd83..1054cf602345 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -110,7 +110,7 @@ struct r10bio { * We choose the number when they are allocated. * We sometimes need an extra bio to write to the replacement. */ - struct { + struct r10dev { struct bio *bio; union { struct bio *repl_bio; /* used for resync and -- GitLab From 74f4cf290918f05b6489aa732dfb08aa5606b9d6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 16 Aug 2012 17:06:41 -0700 Subject: [PATCH 5593/5711] target: Fix regression bug with handling of zero-length data CDBs This patch fixes a regression bug with the handling of zero-length data CDBs within transport_generic_new_cmd() code. The bug was introduced with the following commit as part of the single task conversion work: commit 4101f0a89d4eb13f04cb0344d59a335b862ca5f9 Author: Christoph Hellwig Date: Tue Apr 24 00:25:03 2012 -0400 target: always allocate a single task where the zero-length check for SCF_SCSI_DATA_SG_IO_CDB was incorrectly changed to SCF_SCSI_CONTROL_SG_IO_CDB because of the seperate comment in transport_generic_new_cmd() wrt to control CDBs zero-length handling introduced in: commit 91ec1d3535b2acf12c599045cc19ad9be3c6a47b Author: Nicholas Bellinger Date: Fri Jan 13 12:01:34 2012 -0800 target: Add workaround for zero-length control CDB handling So go ahead and change transport_generic_new_cmd() to handle control+data zero-length CDBs in the same manner for this special case. Tested with iscsi-target + loopback fabric port LUNs on 3.6-rc0 code. This patch will also need to be picked up for 3.5-stable. (hch: Add proper comment in transport_generic_new_cmd) Cc: Christoph Hellwig Cc: Roland Dreier Cc: Andy Grover Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index a7589ccdb6f3..ea9a3d2e4f55 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2323,9 +2323,12 @@ int transport_generic_new_cmd(struct se_cmd *cmd) if (ret < 0) goto out_fail; } - - /* Workaround for handling zero-length control CDBs */ - if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) { + /* + * If this command doesn't have any payload and we don't have to call + * into the fabric for data transfers, go ahead and complete it right + * away. + */ + if (!cmd->data_length) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; -- GitLab From d04dbd1c0ec17a13326c8f2279399c225836a79f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:26 -0700 Subject: [PATCH 5594/5711] USB: smsusb: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Mauro Carvalho Chehab CC: Michael Krufky CC: Paul Gortmaker CC: Doron Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/siano/smsusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 664e460f247b..aac622200e99 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } -static const struct usb_device_id smsusb_id_table[] __devinitconst = { +static const struct usb_device_id smsusb_id_table[] = { { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), -- GitLab From ec063351684298e295dc9444d143ddfd6ab02df8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:27 -0700 Subject: [PATCH 5595/5711] USB: jl2005bcd: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Hans de Goede CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/jl2005bcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c index cf9d9fca5b84..234777116e5f 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -512,7 +512,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0227)}, {} }; -- GitLab From e694d518886c7afedcdd1732477832b2e32744e4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:27 -0700 Subject: [PATCH 5596/5711] USB: spca506: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Hans de Goede CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/spca506.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 969bb5a4cd93..bab01c86c315 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -579,7 +579,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ -- GitLab From b9c4167cbbafddac3462134013bc15e63e4c53ef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:28 -0700 Subject: [PATCH 5597/5711] USB: p54usb: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Christian Lamparter CC: "John W. Linville" Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 7f207b6e9552..effb044a8a9d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -42,7 +42,7 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ -- GitLab From a3433179d0822ccfa8e80aa4d1d52843bd2dcc63 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:29 -0700 Subject: [PATCH 5598/5711] USB: rtl8187: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Herton Ronaldo Krzesinski CC: Hin-Tak Leung CC: Larry Finger CC: "John W. Linville" Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl818x/rtl8187/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 71a30b026089..533024095c43 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger "); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ -- GitLab From 4d088876f24887cd15a29db923f5f37db6a99f21 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:33 -0700 Subject: [PATCH 5599/5711] USB: vt6656: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Forest Bond CC: Marcos Paulo de Souza CC: "David S. Miller" CC: Jesper Juhl CC: Jiri Pirko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b06fd5b723fa..d536756549e6 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -189,7 +189,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode"); // Static vars definitions // -static struct usb_device_id vt6656_table[] __devinitdata = { +static struct usb_device_id vt6656_table[] = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; -- GitLab From 43a34695d9cd79c6659f09da6d3b0624f3dd169f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:37 -0700 Subject: [PATCH 5600/5711] USB: winbond: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Pavel Machek CC: Paul Gortmaker CC: "John W. Linville" CC: Eliad Peller CC: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/wbusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index ef360547ecec..0ca857ac473e 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] __devinitconst = { +static const struct usb_device_id wb35_table[] = { { USB_DEVICE(0x0416, 0x0035) }, { USB_DEVICE(0x18E8, 0x6201) }, { USB_DEVICE(0x18E8, 0x6206) }, -- GitLab From 83957df21dd94655d2b026e0944a69ff37b83988 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:41 -0700 Subject: [PATCH 5601/5711] USB: emi62: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork Cc: stable CC: Paul Gortmaker CC: Andrew Morton CC: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi62.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index ff08015b230c..ae794b90766b 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -232,7 +232,7 @@ wraperr: return err; } -static const struct usb_device_id id_table[] __devinitconst = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; -- GitLab From 99f347caa4568cb803862730b3b1f1942639523f Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Fri, 17 Aug 2012 21:43:43 +0200 Subject: [PATCH 5602/5711] USB: CDC ACM: Fix NULL pointer dereference If a device specifies zero endpoints in its interface descriptor, the kernel oopses in acm_probe(). Even though that's clearly an invalid descriptor, we should test wether we have all endpoints. This is especially bad as this oops can be triggered by just plugging a USB device in. Signed-off-by: Sven Schnelle Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 56d6bf668488..f763ed7ba91e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1104,7 +1104,8 @@ skip_normal_probe: } - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || + control_interface->cur_altsetting->desc.bNumEndpoints == 0) return -EINVAL; epctrl = &control_interface->cur_altsetting->endpoint[0].desc; -- GitLab From b007a3ef958413736a9e2ba698ad6675a9d519ab Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 7 Aug 2012 12:27:24 +0100 Subject: [PATCH 5603/5711] i2c: nomadik: Add default configuration into the Nomadik I2C driver At this moment in time there is only one known configuration for the Nomadik I2C driver. By not holding that configuration in the driver adds some unnecessary overhead in platform code. The configuration has already been removed from platform code, this patch checks for any over-riding configurations. If there aren't any, the default is used. [LinusW says: "Right now this is causing boot regressions so we need it badly..."] Acked-by: srinidhi kasagar Acked-by: Linus Walleij Signed-off-by: Lee Jones Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5e6f1eed4f83..61b00edacb08 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -350,10 +350,6 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) i2c_clk = clk_get_rate(dev->clk); - /* fallback to std. mode if machine has not provided it */ - if (dev->cfg.clk_freq == 0) - dev->cfg.clk_freq = 100000; - /* * The spec says, in case of std. mode the divider is * 2 whereas it is 3 for fast and fastplus mode of @@ -911,20 +907,32 @@ static const struct i2c_algorithm nmk_i2c_algo = { .functionality = nmk_i2c_functionality }; +static struct nmk_i2c_controller u8500_i2c = { + /* + * Slave data setup time; 250ns, 100ns, and 10ns, which + * is 14, 6 and 2 respectively for a 48Mhz i2c clock. + */ + .slsu = 0xe, + .tft = 1, /* Tx FIFO threshold */ + .rft = 8, /* Rx FIFO threshold */ + .clk_freq = 400000, /* fast mode operation */ + .timeout = 200, /* Slave response timeout(ms) */ + .sm = I2C_FREQ_MODE_FAST, +}; + static atomic_t adapter_id = ATOMIC_INIT(0); static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - struct nmk_i2c_controller *pdata = - adev->dev.platform_data; + struct nmk_i2c_controller *pdata = adev->dev.platform_data; struct nmk_i2c_dev *dev; struct i2c_adapter *adap; - if (!pdata) { - dev_warn(&adev->dev, "no platform data\n"); - return -ENODEV; - } + if (!pdata) + /* No i2c configuration found, using the default. */ + pdata = &u8500_i2c; + dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); if (!dev) { dev_err(&adev->dev, "cannot allocate memory\n"); -- GitLab From 33ec5e818b7b0d0d02864a9586050c6f9a6a8b98 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 26 Jun 2012 18:45:32 -0700 Subject: [PATCH 5604/5711] I2C: OMAP: xfer: fix runtime PM get/put balance on error In omap_i2c_xfer(), ensure pm_runtime_put() is called, even on failure. Without this, after a failed xfer, the runtime PM usecount will have been incremented, but not decremented causing the usecount to never reach zero after a failure. This keeps the device always runtime PM enabled which keeps the enclosing power domain active, and prevents full-chip retention/off from happening during idle. Signed-off-by: Kevin Hilman Reviewed-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6849635b268a..5d19a49803c1 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -584,7 +584,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) r = pm_runtime_get_sync(dev->dev); if (IS_ERR_VALUE(r)) - return r; + goto out; r = omap_i2c_wait_for_bb(dev); if (r < 0) -- GitLab From ab5625c30a0a3c8a8491b641c939575c84bc0dbb Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 9 Aug 2012 08:47:20 -0700 Subject: [PATCH 5605/5711] i2c: diolan-u2c: Fix master_xfer return code The master_xfer function returns 0 on success. It should return the number of successful transactions. Signed-off-by: Guenter Roeck Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-diolan-u2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index aedb94f34bf7..dae3ddfe7619 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -405,6 +405,7 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, } } } + ret = num; abort: sret = diolan_i2c_stop(dev); if (sret < 0 && ret >= 0) -- GitLab From 371e67c9e1a82b5fd8110b9a25e36bbc3a99e8c7 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sat, 18 Aug 2012 17:49:58 +0530 Subject: [PATCH 5606/5711] i2c: tegra: protect suspend/resume callbacks with CONFIG_PM_SLEEP The CONFIG_PM doesn't actually enable any of the PM callbacks, it only allows to enable CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. This means if CONFIG_PM is used to protect system sleep callbacks then it may end up unreferenced if only runtime PM is enabled. Hence protecting sleep callbacks with CONFIG_PM_SLEEP. Signed-off-by: Laxman Dewangan Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53fac202..9a08c57bc936 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -712,7 +712,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tegra_i2c_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); -- GitLab From 312b90fbed0e07f61d2f060789440a83df6bba23 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 6 Aug 2012 10:18:17 +0400 Subject: [PATCH 5607/5711] mqueue: lift mnt_want_write() outside ->i_mutex, clean up a bit the way it abuses ->d_fsdata still needs to be killed, but that's a separate story. Signed-off-by: Al Viro --- ipc/mqueue.c | 61 ++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index f8e54f5b9080..9a08acc9e649 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -726,7 +726,6 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, struct mq_attr *attr) { const struct cred *cred = current_cred(); - struct file *result; int ret; if (attr) { @@ -748,21 +747,11 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, } mode &= ~current_umask(); - ret = mnt_want_write(path->mnt); - if (ret) - return ERR_PTR(ret); ret = vfs_create(dir, path->dentry, mode, true); path->dentry->d_fsdata = NULL; - if (!ret) - result = dentry_open(path, oflag, cred); - else - result = ERR_PTR(ret); - /* - * dentry_open() took a persistent mnt_want_write(), - * so we can now drop this one. - */ - mnt_drop_write(path->mnt); - return result; + if (ret) + return ERR_PTR(ret); + return dentry_open(path, oflag, cred); } /* Opens existing queue */ @@ -788,7 +777,9 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, struct mq_attr attr; int fd, error; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - struct dentry *root = ipc_ns->mq_mnt->mnt_root; + struct vfsmount *mnt = ipc_ns->mq_mnt; + struct dentry *root = mnt->mnt_root; + int ro; if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) return -EFAULT; @@ -802,6 +793,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, if (fd < 0) goto out_putname; + ro = mnt_want_write(mnt); /* we'll drop it in any case */ error = 0; mutex_lock(&root->d_inode->i_mutex); path.dentry = lookup_one_len(name, root, strlen(name)); @@ -809,7 +801,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, error = PTR_ERR(path.dentry); goto out_putfd; } - path.mnt = mntget(ipc_ns->mq_mnt); + path.mnt = mntget(mnt); if (oflag & O_CREAT) { if (path.dentry->d_inode) { /* entry already exists */ @@ -820,6 +812,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, } filp = do_open(&path, oflag); } else { + if (ro) { + error = ro; + goto out; + } filp = do_create(ipc_ns, root->d_inode, &path, oflag, mode, u_attr ? &attr : NULL); @@ -845,6 +841,7 @@ out_putfd: fd = error; } mutex_unlock(&root->d_inode->i_mutex); + mnt_drop_write(mnt); out_putname: putname(name); return fd; @@ -857,40 +854,38 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) struct dentry *dentry; struct inode *inode = NULL; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; + struct vfsmount *mnt = ipc_ns->mq_mnt; name = getname(u_name); if (IS_ERR(name)) return PTR_ERR(name); - mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex, - I_MUTEX_PARENT); - dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); + err = mnt_want_write(mnt); + if (err) + goto out_name; + mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); + dentry = lookup_one_len(name, mnt->mnt_root, strlen(name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); goto out_unlock; } - if (!dentry->d_inode) { - err = -ENOENT; - goto out_err; - } - inode = dentry->d_inode; - if (inode) + if (!inode) { + err = -ENOENT; + } else { ihold(inode); - err = mnt_want_write(ipc_ns->mq_mnt); - if (err) - goto out_err; - err = vfs_unlink(dentry->d_parent->d_inode, dentry); - mnt_drop_write(ipc_ns->mq_mnt); -out_err: + err = vfs_unlink(dentry->d_parent->d_inode, dentry); + } dput(dentry); out_unlock: - mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); - putname(name); + mutex_unlock(&mnt->mnt_root->d_inode->i_mutex); if (inode) iput(inode); + mnt_drop_write(mnt); +out_name: + putname(name); return err; } -- GitLab From 515c7af85ed92696c311c53d53cb4898ff32d784 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 18 Aug 2012 16:11:37 -0400 Subject: [PATCH 5608/5711] x32: Use compat shims for {g,s}etsockopt Some of the arguments to {g,s}etsockopt are passed in userland pointers. If we try to use the 64bit entry point, we end up sometimes failing. For example, dhcpcd doesn't run in x32: # dhcpcd eth0 dhcpcd[1979]: version 5.5.6 starting dhcpcd[1979]: eth0: broadcasting for a lease dhcpcd[1979]: eth0: open_socket: Invalid argument dhcpcd[1979]: eth0: send_raw_packet: Bad file descriptor The code in particular is getting back EINVAL when doing: struct sock_fprog pf; setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)); Diving into the kernel code, we can see: include/linux/filter.h: struct sock_fprog { unsigned short len; struct sock_filter __user *filter; }; net/core/sock.c: case SO_ATTACH_FILTER: ret = -EINVAL; if (optlen == sizeof(struct sock_fprog)) { struct sock_fprog fprog; ret = -EFAULT; if (copy_from_user(&fprog, optval, sizeof(fprog))) break; ret = sk_attach_filter(&fprog, sk); } break; arch/x86/syscalls/syscall_64.tbl: 54 common setsockopt sys_setsockopt 55 common getsockopt sys_getsockopt So for x64, sizeof(sock_fprog) is 16 bytes. For x86/x32, it's 8 bytes. This comes down to the pointer being 32bit for x32, which means we need to do structure size translation. But since x32 comes in directly to sys_setsockopt, it doesn't get translated like x86. After changing the syscall table and rebuilding glibc with the new kernel headers, dhcp runs fine in an x32 userland. Oddly, it seems like Linus noted the same thing during the initial port, but I guess that was missed/lost along the way: https://lkml.org/lkml/2011/8/26/452 [ hpa: tagging for -stable since this is an ABI fix. ] Bugzilla: https://bugs.gentoo.org/423649 Reported-by: Mads Signed-off-by: Mike Frysinger Link: http://lkml.kernel.org/r/1345320697-15713-1-git-send-email-vapier@gentoo.org Cc: H. J. Lu Cc: v3.4..v3.5 Signed-off-by: H. Peter Anvin --- arch/x86/syscalls/syscall_64.tbl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 29aed7ac2c02..a582bfed95bb 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -60,8 +60,8 @@ 51 common getsockname sys_getsockname 52 common getpeername sys_getpeername 53 common socketpair sys_socketpair -54 common setsockopt sys_setsockopt -55 common getsockopt sys_getsockopt +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt 56 common clone stub_clone 57 common fork stub_fork 58 common vfork stub_vfork @@ -353,3 +353,5 @@ 538 x32 sendmmsg compat_sys_sendmmsg 539 x32 process_vm_readv compat_sys_process_vm_readv 540 x32 process_vm_writev compat_sys_process_vm_writev +541 x32 setsockopt compat_sys_setsockopt +542 x32 getsockopt compat_sys_getsockopt -- GitLab From 64f503076f9921fc714a2c79fb0fa520869d2c08 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 18 Aug 2012 10:30:05 -0700 Subject: [PATCH 5609/5711] sections: Fix section conflicts in drivers/hwmon Signed-off-by: Andi Kleen Signed-off-by: Guenter Roeck --- drivers/hwmon/coretemp.c | 2 +- drivers/hwmon/w83627hf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index faa16f80db9c..0fa356fe82cc 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -196,7 +196,7 @@ struct tjmax { int tjmax; }; -static struct tjmax __cpuinitconst tjmax_table[] = { +static const struct tjmax __cpuinitconst tjmax_table[] = { { "CPU D410", 100000 }, { "CPU D425", 100000 }, { "CPU D510", 100000 }, diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index ab4825205a9d..5b1a6a666441 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1206,7 +1206,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, int err = -ENODEV; u16 val; - static const __initdata char *names[] = { + static __initconst char *const names[] = { "W83627HF", "W83627THF", "W83697HF", -- GitLab From ebdc82899ec5ed35af1c79ed6a4eeda69dad9b90 Mon Sep 17 00:00:00 2001 From: Markus Trippelsdorf Date: Sat, 18 Aug 2012 18:35:51 -0600 Subject: [PATCH 5610/5711] dyndbg: fix for SOH in logging messages commit af7f2158fde was done against master, and clashed with structured logging's change of KERN_LEVEL to SOH. Bisected and fixed by Markus Trippelsdorf. Reported-by: Markus Trippelsdorf Signed-off-by: Jim Cromie Cc: Linus Torvalds Cc: Andrew Morton Cc: Jason Baron Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index cdd01c52c629..5e6e00bc1652 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1912,8 +1912,8 @@ int __dev_printk(const char *level, const struct device *dev, "DEVICE=+%s:%s", subsys, dev_name(dev)); } skip: - if (level[3]) - level_extra = &level[3]; /* skip past "" */ + if (level[2]) + level_extra = &level[2]; /* skip past KERN_SOH "L" */ return printk_emit(0, level[1] - '0', dictlen ? dict : NULL, dictlen, -- GitLab From a2fa3ccd7b43665fe14cb562761a6c3d26a1d13f Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Aug 2012 14:40:56 +1200 Subject: [PATCH 5611/5711] alpha: Don't export SOCK_NONBLOCK to user space. Currently we export SOCK_NONBLOCK to user space but that conflicts with the definition from glibc leading to compilation errors in user programs (e.g. see Debian bug #658460). The generic socket.h restricts the definition of SOCK_NONBLOCK to the kernel, as does the MIPS specific socket.h, so let's do the same on Alpha. Signed-off-by: Michael Cree Acked-by: Matt Turner Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/socket.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index dcb221a4b5be..7d2f75be932e 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h @@ -76,9 +76,11 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define SO_NOFCS 43 +#ifdef __KERNEL__ /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 +#endif /* __KERNEL__ */ #endif /* _ASM_SOCKET_H */ -- GitLab From d8d5da129857bfd54b603771fca5409062167392 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Aug 2012 14:40:57 +1200 Subject: [PATCH 5612/5711] alpha: Wire up cross memory attach syscalls Add sys_process_vm_readv and sys_process_vm_writev to Alpha. Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/unistd.h | 4 +++- arch/alpha/kernel/systbls.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 633b23b0664a..a31a78eac9b9 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -465,10 +465,12 @@ #define __NR_setns 501 #define __NR_accept4 502 #define __NR_sendmmsg 503 +#define __NR_process_vm_readv 504 +#define __NR_process_vm_writev 505 #ifdef __KERNEL__ -#define NR_SYSCALLS 504 +#define NR_SYSCALLS 506 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 87835235f114..b64157c98e02 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -522,6 +522,8 @@ sys_call_table: .quad sys_setns .quad sys_accept4 .quad sys_sendmmsg + .quad sys_process_vm_readv + .quad sys_process_vm_writev /* 505 */ .size sys_call_table, . - sys_call_table .type sys_call_table, @object -- GitLab From f2db633d301b4b50f5f93de0e8314cc81e9bc7de Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Aug 2012 14:40:58 +1200 Subject: [PATCH 5613/5711] alpha: Use new generic strncpy_from_user() and strnlen_user() Similar to x86/sparc/powerpc implementations except: 1) we implement an extremely efficient has_zero()/find_zero() sequence with both prep_zero_mask() and create_zero_mask() no-operations. 2) Our output from prep_zero_mask() differs in that only the lowest eight bits are used to represent the zero bytes nevertheless it can be safely ORed with other similar masks from prep_zero_mask() and forms input to create_zero_mask(), the two fundamental properties prep_zero_mask() must satisfy. Tests on EV67 and EV68 CPUs revealed that the generic code is essentially as fast (to within 0.5% of CPU cycles) of the old Alpha specific code for large quadword-aligned strings, despite the 30% extra CPU instructions executed. In contrast, the generic code for unaligned strings is substantially slower (by more than a factor of 3) than the old Alpha specific code. Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/Kconfig | 2 + arch/alpha/include/asm/uaccess.h | 34 +- arch/alpha/include/asm/word-at-a-time.h | 55 +++ arch/alpha/kernel/alpha_ksyms.c | 2 - arch/alpha/lib/Makefile | 2 - arch/alpha/lib/ev6-strncpy_from_user.S | 424 ------------------------ arch/alpha/lib/ev67-strlen_user.S | 107 ------ arch/alpha/lib/strlen_user.S | 91 ----- arch/alpha/lib/strncpy_from_user.S | 339 ------------------- 9 files changed, 62 insertions(+), 994 deletions(-) create mode 100644 arch/alpha/include/asm/word-at-a-time.h delete mode 100644 arch/alpha/lib/ev6-strncpy_from_user.S delete mode 100644 arch/alpha/lib/ev67-strlen_user.S delete mode 100644 arch/alpha/lib/strlen_user.S delete mode 100644 arch/alpha/lib/strncpy_from_user.S diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index d5b9b5e645cc..9944dedee5b1 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -18,6 +18,8 @@ config ALPHA select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_SMP_IDLE_THREAD select GENERIC_CMOS_UPDATE + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER help The Alpha is a 64-bit general-purpose processor designed and marketed by the Digital Equipment Corporation of blessed memory, diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index b49ec2f8d6e3..766fdfde2b7a 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -433,36 +433,12 @@ clear_user(void __user *to, long len) #undef __module_address #undef __module_call -/* Returns: -EFAULT if exception before terminator, N if the entire - buffer filled, else strlen. */ +#define user_addr_max() \ + (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) -extern long __strncpy_from_user(char *__to, const char __user *__from, long __to_len); - -extern inline long -strncpy_from_user(char *to, const char __user *from, long n) -{ - long ret = -EFAULT; - if (__access_ok((unsigned long)from, 0, get_fs())) - ret = __strncpy_from_user(to, from, n); - return ret; -} - -/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ -extern long __strlen_user(const char __user *); - -extern inline long strlen_user(const char __user *str) -{ - return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0; -} - -/* Returns: 0 if exception before NUL or reaching the supplied limit (N), - * a value greater than N if the limit would be exceeded, else strlen. */ -extern long __strnlen_user(const char __user *, long); - -extern inline long strnlen_user(const char __user *str, long n) -{ - return access_ok(VERIFY_READ,str,0) ? __strnlen_user(str, n) : 0; -} +extern long strncpy_from_user(char *dest, const char __user *src, long count); +extern __must_check long strlen_user(const char __user *str); +extern __must_check long strnlen_user(const char __user *str, long n); /* * About the exception table: diff --git a/arch/alpha/include/asm/word-at-a-time.h b/arch/alpha/include/asm/word-at-a-time.h new file mode 100644 index 000000000000..6b340d0f1521 --- /dev/null +++ b/arch/alpha/include/asm/word-at-a-time.h @@ -0,0 +1,55 @@ +#ifndef _ASM_WORD_AT_A_TIME_H +#define _ASM_WORD_AT_A_TIME_H + +#include + +/* + * word-at-a-time interface for Alpha. + */ + +/* + * We do not use the word_at_a_time struct on Alpha, but it needs to be + * implemented to humour the generic code. + */ +struct word_at_a_time { + const unsigned long unused; +}; + +#define WORD_AT_A_TIME_CONSTANTS { 0 } + +/* Return nonzero if val has a zero */ +static inline unsigned long has_zero(unsigned long val, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long zero_locations = __kernel_cmpbge(0, val); + *bits = zero_locations; + return zero_locations; +} + +static inline unsigned long prep_zero_mask(unsigned long val, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +#define create_zero_mask(bits) (bits) + +static inline unsigned long find_zero(unsigned long bits) +{ +#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) + /* Simple if have CIX instructions */ + return __kernel_cttz(bits); +#else + unsigned long t1, t2, t3; + /* Retain lowest set bit only */ + bits &= -bits; + /* Binary search for lowest set bit */ + t1 = bits & 0xf0; + t2 = bits & 0xcc; + t3 = bits & 0xaa; + if (t1) t1 = 4; + if (t2) t2 = 2; + if (t3) t3 = 1; + return t1 + t2 + t3; +#endif +} + +#endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index d96e742d4dc2..a354277bbaa7 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -74,8 +74,6 @@ EXPORT_SYMBOL(alpha_fp_emul); */ EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__do_clear_user); -EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(__strnlen_user); /* * SMP-specific symbols. diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index c0a83ab62b78..59660743237c 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -31,8 +31,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ $(ev6-y)memchr.o \ $(ev6-y)copy_user.o \ $(ev6-y)clear_user.o \ - $(ev6-y)strncpy_from_user.o \ - $(ev67-y)strlen_user.o \ $(ev6-y)csum_ipv6_magic.o \ $(ev6-y)clear_page.o \ $(ev6-y)copy_page.o \ diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S deleted file mode 100644 index d2e28178cacc..000000000000 --- a/arch/alpha/lib/ev6-strncpy_from_user.S +++ /dev/null @@ -1,424 +0,0 @@ -/* - * arch/alpha/lib/ev6-strncpy_from_user.S - * 21264 version contributed by Rick Gorton - * - * Just like strncpy except in the return value: - * - * -EFAULT if an exception occurs before the terminator is copied. - * N if the buffer filled. - * - * Otherwise the length of the string is returned. - * - * Much of the information about 21264 scheduling/coding comes from: - * Compiler Writer's Guide for the Alpha 21264 - * abbreviated as 'CWG' in other comments here - * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html - * Scheduling notation: - * E - either cluster - * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 - * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 - * A bunch of instructions got moved and temp registers were changed - * to aid in scheduling. Control flow was also re-arranged to eliminate - * branches, and to provide longer code sequences to enable better scheduling. - * A total rewrite (using byte load/stores for start & tail sequences) - * is desirable, but very difficult to do without a from-scratch rewrite. - * Save that for the future. - */ - - -#include -#include - - -/* Allow an exception for an insn; exit if we get one. */ -#define EX(x,y...) \ - 99: x,##y; \ - .section __ex_table,"a"; \ - .long 99b - .; \ - lda $31, $exception-99b($0); \ - .previous - - - .set noat - .set noreorder - .text - - .globl __strncpy_from_user - .ent __strncpy_from_user - .frame $30, 0, $26 - .prologue 0 - - .align 4 -__strncpy_from_user: - and a0, 7, t3 # E : find dest misalignment - beq a2, $zerolength # U : - - /* Are source and destination co-aligned? */ - mov a0, v0 # E : save the string start - xor a0, a1, t4 # E : - EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword - ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword - - addq a2, t3, a2 # E : bias count by dest misalignment - subq a2, 1, a3 # E : - addq zero, 1, t10 # E : - and t4, 7, t4 # E : misalignment between the two - - and a3, 7, t6 # E : number of tail bytes - sll t10, t6, t10 # E : t10 = bitmask of last count byte - bne t4, $unaligned # U : - lda t2, -1 # E : build a mask against false zero - - /* - * We are co-aligned; take care of a partial first word. - * On entry to this basic block: - * t0 == the first destination word for masking back in - * t1 == the first source word. - */ - - srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8 - addq a1, 8, a1 # E : - mskqh t2, a1, t2 # U : detection in the src word - nop - - /* Create the 1st output word and detect 0's in the 1st input word. */ - mskqh t1, a1, t3 # U : - mskql t0, a1, t0 # U : assemble the first output word - ornot t1, t2, t2 # E : - nop - - cmpbge zero, t2, t8 # E : bits set iff null found - or t0, t3, t0 # E : - beq a2, $a_eoc # U : - bne t8, $a_eos # U : 2nd branch in a quad. Bad. - - /* On entry to this basic block: - * t0 == a source quad not containing a null. - * a0 - current aligned destination address - * a1 - current aligned source address - * a2 - count of quadwords to move. - * NOTE: Loop improvement - unrolling this is going to be - * a huge win, since we're going to stall otherwise. - * Fix this later. For _really_ large copies, look - * at using wh64 on a look-ahead basis. See the code - * in clear_user.S and copy_user.S. - * Presumably, since (a0) and (a1) do not overlap (by C definition) - * Lots of nops here: - * - Separate loads from stores - * - Keep it to 1 branch/quadpack so the branch predictor - * can train. - */ -$a_loop: - stq_u t0, 0(a0) # L : - addq a0, 8, a0 # E : - nop - subq a2, 1, a2 # E : - - EX( ldq_u t0, 0(a1) ) # L : - addq a1, 8, a1 # E : - cmpbge zero, t0, t8 # E : Stall 2 cycles on t0 - beq a2, $a_eoc # U : - - beq t8, $a_loop # U : - nop - nop - nop - - /* Take care of the final (partial) word store. At this point - * the end-of-count bit is set in t8 iff it applies. - * - * On entry to this basic block we have: - * t0 == the source word containing the null - * t8 == the cmpbge mask that found it. - */ -$a_eos: - negq t8, t12 # E : find low bit set - and t8, t12, t12 # E : - - /* We're doing a partial word store and so need to combine - our source and original destination words. */ - ldq_u t1, 0(a0) # L : - subq t12, 1, t6 # E : - - or t12, t6, t8 # E : - zapnot t0, t8, t0 # U : clear src bytes > null - zap t1, t8, t1 # U : clear dst bytes <= null - or t0, t1, t0 # E : - - stq_u t0, 0(a0) # L : - br $finish_up # L0 : - nop - nop - - /* Add the end-of-count bit to the eos detection bitmask. */ - .align 4 -$a_eoc: - or t10, t8, t8 - br $a_eos - nop - nop - - -/* The source and destination are not co-aligned. Align the destination - and cope. We have to be very careful about not reading too much and - causing a SEGV. */ - - .align 4 -$u_head: - /* We know just enough now to be able to assemble the first - full source word. We can still find a zero at the end of it - that prevents us from outputting the whole thing. - - On entry to this basic block: - t0 == the first dest word, unmasked - t1 == the shifted low bits of the first source word - t6 == bytemask that is -1 in dest word bytes */ - - EX( ldq_u t2, 8(a1) ) # L : load second src word - addq a1, 8, a1 # E : - mskql t0, a0, t0 # U : mask trailing garbage in dst - extqh t2, a1, t4 # U : - - or t1, t4, t1 # E : first aligned src word complete - mskqh t1, a0, t1 # U : mask leading garbage in src - or t0, t1, t0 # E : first output word complete - or t0, t6, t6 # E : mask original data for zero test - - cmpbge zero, t6, t8 # E : - beq a2, $u_eocfin # U : - bne t8, $u_final # U : bad news - 2nd branch in a quad - lda t6, -1 # E : mask out the bits we have - - mskql t6, a1, t6 # U : already seen - stq_u t0, 0(a0) # L : store first output word - or t6, t2, t2 # E : - cmpbge zero, t2, t8 # E : find nulls in second partial - - addq a0, 8, a0 # E : - subq a2, 1, a2 # E : - bne t8, $u_late_head_exit # U : - nop - - /* Finally, we've got all the stupid leading edge cases taken care - of and we can set up to enter the main loop. */ - - extql t2, a1, t1 # U : position hi-bits of lo word - EX( ldq_u t2, 8(a1) ) # L : read next high-order source word - addq a1, 8, a1 # E : - cmpbge zero, t2, t8 # E : - - beq a2, $u_eoc # U : - bne t8, $u_eos # U : - nop - nop - - /* Unaligned copy main loop. In order to avoid reading too much, - the loop is structured to detect zeros in aligned source words. - This has, unfortunately, effectively pulled half of a loop - iteration out into the head and half into the tail, but it does - prevent nastiness from accumulating in the very thing we want - to run as fast as possible. - - On entry to this basic block: - t1 == the shifted high-order bits from the previous source word - t2 == the unshifted current source word - - We further know that t2 does not contain a null terminator. */ - - /* - * Extra nops here: - * separate load quads from store quads - * only one branch/quad to permit predictor training - */ - - .align 4 -$u_loop: - extqh t2, a1, t0 # U : extract high bits for current word - addq a1, 8, a1 # E : - extql t2, a1, t3 # U : extract low bits for next time - addq a0, 8, a0 # E : - - or t0, t1, t0 # E : current dst word now complete - EX( ldq_u t2, 0(a1) ) # L : load high word for next time - subq a2, 1, a2 # E : - nop - - stq_u t0, -8(a0) # L : save the current word - mov t3, t1 # E : - cmpbge zero, t2, t8 # E : test new word for eos - beq a2, $u_eoc # U : - - beq t8, $u_loop # U : - nop - nop - nop - - /* We've found a zero somewhere in the source word we just read. - If it resides in the lower half, we have one (probably partial) - word to write out, and if it resides in the upper half, we - have one full and one partial word left to write out. - - On entry to this basic block: - t1 == the shifted high-order bits from the previous source word - t2 == the unshifted current source word. */ - .align 4 -$u_eos: - extqh t2, a1, t0 # U : - or t0, t1, t0 # E : first (partial) source word complete - cmpbge zero, t0, t8 # E : is the null in this first bit? - nop - - bne t8, $u_final # U : - stq_u t0, 0(a0) # L : the null was in the high-order bits - addq a0, 8, a0 # E : - subq a2, 1, a2 # E : - - .align 4 -$u_late_head_exit: - extql t2, a1, t0 # U : - cmpbge zero, t0, t8 # E : - or t8, t10, t6 # E : - cmoveq a2, t6, t8 # E : - - /* Take care of a final (probably partial) result word. - On entry to this basic block: - t0 == assembled source word - t8 == cmpbge mask that found the null. */ - .align 4 -$u_final: - negq t8, t6 # E : isolate low bit set - and t6, t8, t12 # E : - ldq_u t1, 0(a0) # L : - subq t12, 1, t6 # E : - - or t6, t12, t8 # E : - zapnot t0, t8, t0 # U : kill source bytes > null - zap t1, t8, t1 # U : kill dest bytes <= null - or t0, t1, t0 # E : - - stq_u t0, 0(a0) # E : - br $finish_up # U : - nop - nop - - .align 4 -$u_eoc: # end-of-count - extqh t2, a1, t0 # U : - or t0, t1, t0 # E : - cmpbge zero, t0, t8 # E : - nop - - .align 4 -$u_eocfin: # end-of-count, final word - or t10, t8, t8 # E : - br $u_final # U : - nop - nop - - /* Unaligned copy entry point. */ - .align 4 -$unaligned: - - srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8 - and a0, 7, t4 # E : find dest misalignment - and a1, 7, t5 # E : find src misalignment - mov zero, t0 # E : - - /* Conditionally load the first destination word and a bytemask - with 0xff indicating that the destination byte is sacrosanct. */ - - mov zero, t6 # E : - beq t4, 1f # U : - ldq_u t0, 0(a0) # L : - lda t6, -1 # E : - - mskql t6, a0, t6 # E : - nop - nop - nop - - .align 4 -1: - subq a1, t4, a1 # E : sub dest misalignment from src addr - /* If source misalignment is larger than dest misalignment, we need - extra startup checks to avoid SEGV. */ - cmplt t4, t5, t12 # E : - extql t1, a1, t1 # U : shift src into place - lda t2, -1 # E : for creating masks later - - beq t12, $u_head # U : - mskqh t2, t5, t2 # U : begin src byte validity mask - cmpbge zero, t1, t8 # E : is there a zero? - nop - - extql t2, a1, t2 # U : - or t8, t10, t5 # E : test for end-of-count too - cmpbge zero, t2, t3 # E : - cmoveq a2, t5, t8 # E : Latency=2, extra map slot - - nop # E : goes with cmov - andnot t8, t3, t8 # E : - beq t8, $u_head # U : - nop - - /* At this point we've found a zero in the first partial word of - the source. We need to isolate the valid source data and mask - it into the original destination data. (Incidentally, we know - that we'll need at least one byte of that original dest word.) */ - - ldq_u t0, 0(a0) # L : - negq t8, t6 # E : build bitmask of bytes <= zero - mskqh t1, t4, t1 # U : - and t6, t8, t12 # E : - - subq t12, 1, t6 # E : - or t6, t12, t8 # E : - zapnot t2, t8, t2 # U : prepare source word; mirror changes - zapnot t1, t8, t1 # U : to source validity mask - - andnot t0, t2, t0 # E : zero place for source to reside - or t0, t1, t0 # E : and put it there - stq_u t0, 0(a0) # L : - nop - - .align 4 -$finish_up: - zapnot t0, t12, t4 # U : was last byte written null? - and t12, 0xf0, t3 # E : binary search for the address of the - cmovne t4, 1, t4 # E : Latency=2, extra map slot - nop # E : with cmovne - - and t12, 0xcc, t2 # E : last byte written - and t12, 0xaa, t1 # E : - cmovne t3, 4, t3 # E : Latency=2, extra map slot - nop # E : with cmovne - - bic a0, 7, t0 - cmovne t2, 2, t2 # E : Latency=2, extra map slot - nop # E : with cmovne - nop - - cmovne t1, 1, t1 # E : Latency=2, extra map slot - nop # E : with cmovne - addq t0, t3, t0 # E : - addq t1, t2, t1 # E : - - addq t0, t1, t0 # E : - addq t0, t4, t0 # add one if we filled the buffer - subq t0, v0, v0 # find string length - ret # L0 : - - .align 4 -$zerolength: - nop - nop - nop - clr v0 - -$exception: - nop - nop - nop - ret - - .end __strncpy_from_user diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S deleted file mode 100644 index 57e0d77b81a6..000000000000 --- a/arch/alpha/lib/ev67-strlen_user.S +++ /dev/null @@ -1,107 +0,0 @@ -/* - * arch/alpha/lib/ev67-strlen_user.S - * 21264 version contributed by Rick Gorton - * - * Return the length of the string including the NULL terminator - * (strlen+1) or zero if an error occurred. - * - * In places where it is critical to limit the processing time, - * and the data is not trusted, strnlen_user() should be used. - * It will return a value greater than its second argument if - * that limit would be exceeded. This implementation is allowed - * to access memory beyond the limit, but will not cross a page - * boundary when doing so. - * - * Much of the information about 21264 scheduling/coding comes from: - * Compiler Writer's Guide for the Alpha 21264 - * abbreviated as 'CWG' in other comments here - * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html - * Scheduling notation: - * E - either cluster - * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 - * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 - * Try not to change the actual algorithm if possible for consistency. - */ - -#include - - -/* Allow an exception for an insn; exit if we get one. */ -#define EX(x,y...) \ - 99: x,##y; \ - .section __ex_table,"a"; \ - .long 99b - .; \ - lda v0, $exception-99b(zero); \ - .previous - - - .set noreorder - .set noat - .text - - .globl __strlen_user - .ent __strlen_user - .frame sp, 0, ra - - .align 4 -__strlen_user: - ldah a1, 32767(zero) # do not use plain strlen_user() for strings - # that might be almost 2 GB long; you should - # be using strnlen_user() instead - nop - nop - nop - - .globl __strnlen_user - - .align 4 -__strnlen_user: - .prologue 0 - EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned) - lda t1, -1(zero) # E : - - insqh t1, a0, t1 # U : - andnot a0, 7, v0 # E : - or t1, t0, t0 # E : - subq a0, 1, a0 # E : get our +1 for the return - - cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0 - subq a1, 7, t2 # E : - subq a0, v0, t0 # E : - bne t1, $found # U : - - addq t2, t0, t2 # E : - addq a1, 1, a1 # E : - nop # E : - nop # E : - - .align 4 -$loop: ble t2, $limit # U : - EX( ldq t0, 8(v0) ) # L : - nop # E : - nop # E : - - cmpbge zero, t0, t1 # E : - subq t2, 8, t2 # E : - addq v0, 8, v0 # E : addr += 8 - beq t1, $loop # U : - -$found: cttz t1, t2 # U0 : - addq v0, t2, v0 # E : - subq v0, a0, v0 # E : - ret # L0 : - -$exception: - nop - nop - nop - ret - - .align 4 # currently redundant -$limit: - nop - nop - subq a1, t2, v0 - ret - - .end __strlen_user diff --git a/arch/alpha/lib/strlen_user.S b/arch/alpha/lib/strlen_user.S deleted file mode 100644 index 508a18e96479..000000000000 --- a/arch/alpha/lib/strlen_user.S +++ /dev/null @@ -1,91 +0,0 @@ -/* - * arch/alpha/lib/strlen_user.S - * - * Return the length of the string including the NUL terminator - * (strlen+1) or zero if an error occurred. - * - * In places where it is critical to limit the processing time, - * and the data is not trusted, strnlen_user() should be used. - * It will return a value greater than its second argument if - * that limit would be exceeded. This implementation is allowed - * to access memory beyond the limit, but will not cross a page - * boundary when doing so. - */ - -#include - - -/* Allow an exception for an insn; exit if we get one. */ -#define EX(x,y...) \ - 99: x,##y; \ - .section __ex_table,"a"; \ - .long 99b - .; \ - lda v0, $exception-99b(zero); \ - .previous - - - .set noreorder - .set noat - .text - - .globl __strlen_user - .ent __strlen_user - .frame sp, 0, ra - - .align 3 -__strlen_user: - ldah a1, 32767(zero) # do not use plain strlen_user() for strings - # that might be almost 2 GB long; you should - # be using strnlen_user() instead - - .globl __strnlen_user - - .align 3 -__strnlen_user: - .prologue 0 - - EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned) - lda t1, -1(zero) - insqh t1, a0, t1 - andnot a0, 7, v0 - or t1, t0, t0 - subq a0, 1, a0 # get our +1 for the return - cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0 - subq a1, 7, t2 - subq a0, v0, t0 - bne t1, $found - - addq t2, t0, t2 - addq a1, 1, a1 - - .align 3 -$loop: ble t2, $limit - EX( ldq t0, 8(v0) ) - subq t2, 8, t2 - addq v0, 8, v0 # addr += 8 - cmpbge zero, t0, t1 - beq t1, $loop - -$found: negq t1, t2 # clear all but least set bit - and t1, t2, t1 - - and t1, 0xf0, t2 # binary search for that set bit - and t1, 0xcc, t3 - and t1, 0xaa, t4 - cmovne t2, 4, t2 - cmovne t3, 2, t3 - cmovne t4, 1, t4 - addq t2, t3, t2 - addq v0, t4, v0 - addq v0, t2, v0 - nop # dual issue next two on ev4 and ev5 - subq v0, a0, v0 -$exception: - ret - - .align 3 # currently redundant -$limit: - subq a1, t2, v0 - ret - - .end __strlen_user diff --git a/arch/alpha/lib/strncpy_from_user.S b/arch/alpha/lib/strncpy_from_user.S deleted file mode 100644 index 73ee21160ff7..000000000000 --- a/arch/alpha/lib/strncpy_from_user.S +++ /dev/null @@ -1,339 +0,0 @@ -/* - * arch/alpha/lib/strncpy_from_user.S - * Contributed by Richard Henderson (rth@tamu.edu) - * - * Just like strncpy except in the return value: - * - * -EFAULT if an exception occurs before the terminator is copied. - * N if the buffer filled. - * - * Otherwise the length of the string is returned. - */ - - -#include -#include - - -/* Allow an exception for an insn; exit if we get one. */ -#define EX(x,y...) \ - 99: x,##y; \ - .section __ex_table,"a"; \ - .long 99b - .; \ - lda $31, $exception-99b($0); \ - .previous - - - .set noat - .set noreorder - .text - - .globl __strncpy_from_user - .ent __strncpy_from_user - .frame $30, 0, $26 - .prologue 0 - - .align 3 -$aligned: - /* On entry to this basic block: - t0 == the first destination word for masking back in - t1 == the first source word. */ - - /* Create the 1st output word and detect 0's in the 1st input word. */ - lda t2, -1 # e1 : build a mask against false zero - mskqh t2, a1, t2 # e0 : detection in the src word - mskqh t1, a1, t3 # e0 : - ornot t1, t2, t2 # .. e1 : - mskql t0, a1, t0 # e0 : assemble the first output word - cmpbge zero, t2, t8 # .. e1 : bits set iff null found - or t0, t3, t0 # e0 : - beq a2, $a_eoc # .. e1 : - bne t8, $a_eos # .. e1 : - - /* On entry to this basic block: - t0 == a source word not containing a null. */ - -$a_loop: - stq_u t0, 0(a0) # e0 : - addq a0, 8, a0 # .. e1 : - EX( ldq_u t0, 0(a1) ) # e0 : - addq a1, 8, a1 # .. e1 : - subq a2, 1, a2 # e0 : - cmpbge zero, t0, t8 # .. e1 (stall) - beq a2, $a_eoc # e1 : - beq t8, $a_loop # e1 : - - /* Take care of the final (partial) word store. At this point - the end-of-count bit is set in t8 iff it applies. - - On entry to this basic block we have: - t0 == the source word containing the null - t8 == the cmpbge mask that found it. */ - -$a_eos: - negq t8, t12 # e0 : find low bit set - and t8, t12, t12 # e1 (stall) - - /* For the sake of the cache, don't read a destination word - if we're not going to need it. */ - and t12, 0x80, t6 # e0 : - bne t6, 1f # .. e1 (zdb) - - /* We're doing a partial word store and so need to combine - our source and original destination words. */ - ldq_u t1, 0(a0) # e0 : - subq t12, 1, t6 # .. e1 : - or t12, t6, t8 # e0 : - unop # - zapnot t0, t8, t0 # e0 : clear src bytes > null - zap t1, t8, t1 # .. e1 : clear dst bytes <= null - or t0, t1, t0 # e1 : - -1: stq_u t0, 0(a0) - br $finish_up - - /* Add the end-of-count bit to the eos detection bitmask. */ -$a_eoc: - or t10, t8, t8 - br $a_eos - - /*** The Function Entry Point ***/ - .align 3 -__strncpy_from_user: - mov a0, v0 # save the string start - beq a2, $zerolength - - /* Are source and destination co-aligned? */ - xor a0, a1, t1 # e0 : - and a0, 7, t0 # .. e1 : find dest misalignment - and t1, 7, t1 # e0 : - addq a2, t0, a2 # .. e1 : bias count by dest misalignment - subq a2, 1, a2 # e0 : - and a2, 7, t2 # e1 : - srl a2, 3, a2 # e0 : a2 = loop counter = (count - 1)/8 - addq zero, 1, t10 # .. e1 : - sll t10, t2, t10 # e0 : t10 = bitmask of last count byte - bne t1, $unaligned # .. e1 : - - /* We are co-aligned; take care of a partial first word. */ - - EX( ldq_u t1, 0(a1) ) # e0 : load first src word - addq a1, 8, a1 # .. e1 : - - beq t0, $aligned # avoid loading dest word if not needed - ldq_u t0, 0(a0) # e0 : - br $aligned # .. e1 : - - -/* The source and destination are not co-aligned. Align the destination - and cope. We have to be very careful about not reading too much and - causing a SEGV. */ - - .align 3 -$u_head: - /* We know just enough now to be able to assemble the first - full source word. We can still find a zero at the end of it - that prevents us from outputting the whole thing. - - On entry to this basic block: - t0 == the first dest word, unmasked - t1 == the shifted low bits of the first source word - t6 == bytemask that is -1 in dest word bytes */ - - EX( ldq_u t2, 8(a1) ) # e0 : load second src word - addq a1, 8, a1 # .. e1 : - mskql t0, a0, t0 # e0 : mask trailing garbage in dst - extqh t2, a1, t4 # e0 : - or t1, t4, t1 # e1 : first aligned src word complete - mskqh t1, a0, t1 # e0 : mask leading garbage in src - or t0, t1, t0 # e0 : first output word complete - or t0, t6, t6 # e1 : mask original data for zero test - cmpbge zero, t6, t8 # e0 : - beq a2, $u_eocfin # .. e1 : - bne t8, $u_final # e1 : - - lda t6, -1 # e1 : mask out the bits we have - mskql t6, a1, t6 # e0 : already seen - stq_u t0, 0(a0) # e0 : store first output word - or t6, t2, t2 # .. e1 : - cmpbge zero, t2, t8 # e0 : find nulls in second partial - addq a0, 8, a0 # .. e1 : - subq a2, 1, a2 # e0 : - bne t8, $u_late_head_exit # .. e1 : - - /* Finally, we've got all the stupid leading edge cases taken care - of and we can set up to enter the main loop. */ - - extql t2, a1, t1 # e0 : position hi-bits of lo word - EX( ldq_u t2, 8(a1) ) # .. e1 : read next high-order source word - addq a1, 8, a1 # e0 : - cmpbge zero, t2, t8 # e1 (stall) - beq a2, $u_eoc # e1 : - bne t8, $u_eos # e1 : - - /* Unaligned copy main loop. In order to avoid reading too much, - the loop is structured to detect zeros in aligned source words. - This has, unfortunately, effectively pulled half of a loop - iteration out into the head and half into the tail, but it does - prevent nastiness from accumulating in the very thing we want - to run as fast as possible. - - On entry to this basic block: - t1 == the shifted high-order bits from the previous source word - t2 == the unshifted current source word - - We further know that t2 does not contain a null terminator. */ - - .align 3 -$u_loop: - extqh t2, a1, t0 # e0 : extract high bits for current word - addq a1, 8, a1 # .. e1 : - extql t2, a1, t3 # e0 : extract low bits for next time - addq a0, 8, a0 # .. e1 : - or t0, t1, t0 # e0 : current dst word now complete - EX( ldq_u t2, 0(a1) ) # .. e1 : load high word for next time - stq_u t0, -8(a0) # e0 : save the current word - mov t3, t1 # .. e1 : - subq a2, 1, a2 # e0 : - cmpbge zero, t2, t8 # .. e1 : test new word for eos - beq a2, $u_eoc # e1 : - beq t8, $u_loop # e1 : - - /* We've found a zero somewhere in the source word we just read. - If it resides in the lower half, we have one (probably partial) - word to write out, and if it resides in the upper half, we - have one full and one partial word left to write out. - - On entry to this basic block: - t1 == the shifted high-order bits from the previous source word - t2 == the unshifted current source word. */ -$u_eos: - extqh t2, a1, t0 # e0 : - or t0, t1, t0 # e1 : first (partial) source word complete - - cmpbge zero, t0, t8 # e0 : is the null in this first bit? - bne t8, $u_final # .. e1 (zdb) - - stq_u t0, 0(a0) # e0 : the null was in the high-order bits - addq a0, 8, a0 # .. e1 : - subq a2, 1, a2 # e1 : - -$u_late_head_exit: - extql t2, a1, t0 # .. e0 : - cmpbge zero, t0, t8 # e0 : - or t8, t10, t6 # e1 : - cmoveq a2, t6, t8 # e0 : - nop # .. e1 : - - /* Take care of a final (probably partial) result word. - On entry to this basic block: - t0 == assembled source word - t8 == cmpbge mask that found the null. */ -$u_final: - negq t8, t6 # e0 : isolate low bit set - and t6, t8, t12 # e1 : - - and t12, 0x80, t6 # e0 : avoid dest word load if we can - bne t6, 1f # .. e1 (zdb) - - ldq_u t1, 0(a0) # e0 : - subq t12, 1, t6 # .. e1 : - or t6, t12, t8 # e0 : - zapnot t0, t8, t0 # .. e1 : kill source bytes > null - zap t1, t8, t1 # e0 : kill dest bytes <= null - or t0, t1, t0 # e1 : - -1: stq_u t0, 0(a0) # e0 : - br $finish_up - -$u_eoc: # end-of-count - extqh t2, a1, t0 - or t0, t1, t0 - cmpbge zero, t0, t8 - -$u_eocfin: # end-of-count, final word - or t10, t8, t8 - br $u_final - - /* Unaligned copy entry point. */ - .align 3 -$unaligned: - - EX( ldq_u t1, 0(a1) ) # e0 : load first source word - - and a0, 7, t4 # .. e1 : find dest misalignment - and a1, 7, t5 # e0 : find src misalignment - - /* Conditionally load the first destination word and a bytemask - with 0xff indicating that the destination byte is sacrosanct. */ - - mov zero, t0 # .. e1 : - mov zero, t6 # e0 : - beq t4, 1f # .. e1 : - ldq_u t0, 0(a0) # e0 : - lda t6, -1 # .. e1 : - mskql t6, a0, t6 # e0 : -1: - subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr - - /* If source misalignment is larger than dest misalignment, we need - extra startup checks to avoid SEGV. */ - - cmplt t4, t5, t12 # e1 : - extql t1, a1, t1 # .. e0 : shift src into place - lda t2, -1 # e0 : for creating masks later - beq t12, $u_head # e1 : - - mskqh t2, t5, t2 # e0 : begin src byte validity mask - cmpbge zero, t1, t8 # .. e1 : is there a zero? - extql t2, a1, t2 # e0 : - or t8, t10, t5 # .. e1 : test for end-of-count too - cmpbge zero, t2, t3 # e0 : - cmoveq a2, t5, t8 # .. e1 : - andnot t8, t3, t8 # e0 : - beq t8, $u_head # .. e1 (zdb) - - /* At this point we've found a zero in the first partial word of - the source. We need to isolate the valid source data and mask - it into the original destination data. (Incidentally, we know - that we'll need at least one byte of that original dest word.) */ - - ldq_u t0, 0(a0) # e0 : - negq t8, t6 # .. e1 : build bitmask of bytes <= zero - mskqh t1, t4, t1 # e0 : - and t6, t8, t12 # .. e1 : - subq t12, 1, t6 # e0 : - or t6, t12, t8 # e1 : - - zapnot t2, t8, t2 # e0 : prepare source word; mirror changes - zapnot t1, t8, t1 # .. e1 : to source validity mask - - andnot t0, t2, t0 # e0 : zero place for source to reside - or t0, t1, t0 # e1 : and put it there - stq_u t0, 0(a0) # e0 : - -$finish_up: - zapnot t0, t12, t4 # was last byte written null? - cmovne t4, 1, t4 - - and t12, 0xf0, t3 # binary search for the address of the - and t12, 0xcc, t2 # last byte written - and t12, 0xaa, t1 - bic a0, 7, t0 - cmovne t3, 4, t3 - cmovne t2, 2, t2 - cmovne t1, 1, t1 - addq t0, t3, t0 - addq t1, t2, t1 - addq t0, t1, t0 - addq t0, t4, t0 # add one if we filled the buffer - - subq t0, v0, v0 # find string length - ret - -$zerolength: - clr v0 -$exception: - ret - - .end __strncpy_from_user -- GitLab From be53db6e4edd9dc013b21a929ad2b142dea8b9c0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Aug 2012 14:40:59 +1200 Subject: [PATCH 5614/5711] alpha: take a bunch of syscalls into osf_sys.c New helper: current_thread_info(). Allows to do a bunch of odd syscalls in C. While we are at it, there had never been a reason to do osf_getpriority() in assembler. We also get "namespace"-aware (read: consistent with getuid(2), etc.) behaviour from getx?id() syscalls now. Signed-off-by: Al Viro Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/ptrace.h | 5 +- arch/alpha/kernel/entry.S | 109 -------------------------------- arch/alpha/kernel/osf_sys.c | 49 ++++++++++++++ arch/alpha/kernel/systbls.S | 2 +- kernel/timer.c | 9 --- 5 files changed, 54 insertions(+), 120 deletions(-) diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h index fd698a174f26..b87755a19554 100644 --- a/arch/alpha/include/asm/ptrace.h +++ b/arch/alpha/include/asm/ptrace.h @@ -76,7 +76,10 @@ struct switch_stack { #define task_pt_regs(task) \ ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1) -#define force_successful_syscall_return() (task_pt_regs(current)->r0 = 0) +#define current_pt_regs() \ + ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) + +#define force_successful_syscall_return() (current_pt_regs()->r0 = 0) #endif diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 6d159cee5f2f..22b0c4d414a7 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -796,115 +796,6 @@ sys_rt_sigreturn: br ret_from_sys_call .end sys_rt_sigreturn - .align 4 - .globl sys_sethae - .ent sys_sethae -sys_sethae: - .prologue 0 - stq $16, 152($sp) - ret -.end sys_sethae - - .align 4 - .globl osf_getpriority - .ent osf_getpriority -osf_getpriority: - lda $sp, -16($sp) - stq $26, 0($sp) - .prologue 0 - - jsr $26, sys_getpriority - - ldq $26, 0($sp) - blt $0, 1f - - /* Return value is the unbiased priority, i.e. 20 - prio. - This does result in negative return values, so signal - no error by writing into the R0 slot. */ - lda $1, 20 - stq $31, 16($sp) - subl $1, $0, $0 - unop - -1: lda $sp, 16($sp) - ret -.end osf_getpriority - - .align 4 - .globl sys_getxuid - .ent sys_getxuid -sys_getxuid: - .prologue 0 - ldq $2, TI_TASK($8) - ldq $3, TASK_CRED($2) - ldl $0, CRED_UID($3) - ldl $1, CRED_EUID($3) - stq $1, 80($sp) - ret -.end sys_getxuid - - .align 4 - .globl sys_getxgid - .ent sys_getxgid -sys_getxgid: - .prologue 0 - ldq $2, TI_TASK($8) - ldq $3, TASK_CRED($2) - ldl $0, CRED_GID($3) - ldl $1, CRED_EGID($3) - stq $1, 80($sp) - ret -.end sys_getxgid - - .align 4 - .globl sys_getxpid - .ent sys_getxpid -sys_getxpid: - .prologue 0 - ldq $2, TI_TASK($8) - - /* See linux/kernel/timer.c sys_getppid for discussion - about this loop. */ - ldq $3, TASK_GROUP_LEADER($2) - ldq $4, TASK_REAL_PARENT($3) - ldl $0, TASK_TGID($2) -1: ldl $1, TASK_TGID($4) -#ifdef CONFIG_SMP - mov $4, $5 - mb - ldq $3, TASK_GROUP_LEADER($2) - ldq $4, TASK_REAL_PARENT($3) - cmpeq $4, $5, $5 - beq $5, 1b -#endif - stq $1, 80($sp) - ret -.end sys_getxpid - - .align 4 - .globl sys_alpha_pipe - .ent sys_alpha_pipe -sys_alpha_pipe: - lda $sp, -16($sp) - stq $26, 0($sp) - .prologue 0 - - mov $31, $17 - lda $16, 8($sp) - jsr $26, do_pipe_flags - - ldq $26, 0($sp) - bne $0, 1f - - /* The return values are in $0 and $20. */ - ldl $1, 12($sp) - ldl $0, 8($sp) - - stq $1, 80+16($sp) -1: lda $sp, 16($sp) - ret -.end sys_alpha_pipe - .align 4 .globl sys_execve .ent sys_execve diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 98a103621af6..bc1acdda7a5e 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1404,3 +1404,52 @@ SYSCALL_DEFINE3(osf_writev, unsigned long, fd, } #endif + +SYSCALL_DEFINE2(osf_getpriority, int, which, int, who) +{ + int prio = sys_getpriority(which, who); + if (prio >= 0) { + /* Return value is the unbiased priority, i.e. 20 - prio. + This does result in negative return values, so signal + no error */ + force_successful_syscall_return(); + prio = 20 - prio; + } + return prio; +} + +SYSCALL_DEFINE0(getxuid) +{ + current_pt_regs()->r20 = sys_geteuid(); + return sys_getuid(); +} + +SYSCALL_DEFINE0(getxgid) +{ + current_pt_regs()->r20 = sys_getegid(); + return sys_getgid(); +} + +SYSCALL_DEFINE0(getxpid) +{ + current_pt_regs()->r20 = sys_getppid(); + return sys_getpid(); +} + +SYSCALL_DEFINE0(alpha_pipe) +{ + int fd[2]; + int res = do_pipe_flags(fd, 0); + if (!res) { + /* The return values are in $0 and $20. */ + current_pt_regs()->r20 = fd[1]; + res = fd[0]; + } + return res; +} + +SYSCALL_DEFINE1(sethae, unsigned long, val) +{ + current_pt_regs()->hae = val; + return 0; +} diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index b64157c98e02..2ac6b45c3e00 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -111,7 +111,7 @@ sys_call_table: .quad sys_socket .quad sys_connect .quad sys_accept - .quad osf_getpriority /* 100 */ + .quad sys_osf_getpriority /* 100 */ .quad sys_send .quad sys_recv .quad sys_sigreturn diff --git a/kernel/timer.c b/kernel/timer.c index a61c09374eba..8c5e7b908c68 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1407,13 +1407,6 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds) #endif -#ifndef __alpha__ - -/* - * The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this - * should be moved into arch/i386 instead? - */ - /** * sys_getpid - return the thread group id of the current process * @@ -1469,8 +1462,6 @@ SYSCALL_DEFINE0(getegid) return from_kgid_munged(current_user_ns(), current_egid()); } -#endif - static void process_timeout(unsigned long __data) { wake_up_process((struct task_struct *)__data); -- GitLab From 28d353d9891c28496e366bebe4e65233f59ad1f6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Aug 2012 14:41:00 +1200 Subject: [PATCH 5615/5711] alpha: take kernel_execve() out of entry.S Signed-off-by: Al Viro Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/kernel/alpha_ksyms.c | 1 - arch/alpha/kernel/entry.S | 52 --------------------------------- arch/alpha/kernel/process.c | 19 ++++++++++++ 3 files changed, 19 insertions(+), 53 deletions(-) diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index a354277bbaa7..15fa821d09cd 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -52,7 +52,6 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s); /* entry.S */ EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(kernel_execve); /* Networking helper routines. */ EXPORT_SYMBOL(csum_tcpudp_magic); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 22b0c4d414a7..ec0da0567ab5 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -663,58 +663,6 @@ kernel_thread: br ret_to_kernel .end kernel_thread -/* - * kernel_execve(path, argv, envp) - */ - .align 4 - .globl kernel_execve - .ent kernel_execve -kernel_execve: - /* We can be called from a module. */ - ldgp $gp, 0($27) - lda $sp, -(32+SIZEOF_PT_REGS+8)($sp) - .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0 - stq $26, 0($sp) - stq $16, 8($sp) - stq $17, 16($sp) - stq $18, 24($sp) - .prologue 1 - - lda $16, 32($sp) - lda $17, 0 - lda $18, SIZEOF_PT_REGS - bsr $26, memset !samegp - - /* Avoid the HAE being gratuitously wrong, which would cause us - to do the whole turn off interrupts thing and restore it. */ - ldq $2, alpha_mv+HAE_CACHE - stq $2, 152+32($sp) - - ldq $16, 8($sp) - ldq $17, 16($sp) - ldq $18, 24($sp) - lda $19, 32($sp) - bsr $26, do_execve !samegp - - ldq $26, 0($sp) - bne $0, 1f /* error! */ - - /* Move the temporary pt_regs struct from its current location - to the top of the kernel stack frame. See copy_thread for - details for a normal process. */ - lda $16, 0x4000 - SIZEOF_PT_REGS($8) - lda $17, 32($sp) - lda $18, SIZEOF_PT_REGS - bsr $26, memmove !samegp - - /* Take that over as our new stack frame and visit userland! */ - lda $sp, 0x4000 - SIZEOF_PT_REGS($8) - br $31, ret_from_sys_call - -1: lda $sp, 32+SIZEOF_PT_REGS+8($sp) - ret -.end kernel_execve - /* * Special system calls. Most of these are special in that they either diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 153d3fce3e8e..d6fde98b74b3 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -455,3 +455,22 @@ get_wchan(struct task_struct *p) } return pc; } + +int kernel_execve(const char *path, const char *const argv[], const char *const envp[]) +{ + /* Avoid the HAE being gratuitously wrong, which would cause us + to do the whole turn off interrupts thing and restore it. */ + struct pt_regs regs = {.hae = alpha_mv.hae_cache}; + int err = do_execve(path, argv, envp, ®s); + if (!err) { + struct pt_regs *p = current_pt_regs(); + /* copy regs to normal position and off to userland we go... */ + *p = regs; + __asm__ __volatile__ ( + "mov %0, $sp;" + "br $31, ret_from_sys_call" + : : "r"(p)); + } + return err; +} +EXPORT_SYMBOL(kernel_execve); -- GitLab From 0bcc426b1defa6b629dfa722537cab38876a3ce4 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Sun, 19 Aug 2012 14:41:01 +1200 Subject: [PATCH 5616/5711] alpha/mm/fault.c: Port OOM changes to do_page_fault Commit d065bd810b6d ("mm: retry page fault when blocking on disk transfer") and 37b23e0525d3 ("x86,mm: make pagefault killable") introduced changes into the x86 pagefault handler for making the page fault handler retryable as well as killable. These changes reduce the mmap_sem hold time, which is crucial during OOM killer invocation. Port these changes to ALPHA. Signed-off-by: Mohd. Faris Signed-off-by: Kautuk Consul Acked-by: Matt Turner Signed-off-by: Michael Cree Signed-off-by: Linus Torvalds --- arch/alpha/mm/fault.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 5eecab1a84ef..0c4132dd3507 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -89,6 +89,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr, const struct exception_table_entry *fixup; int fault, si_code = SEGV_MAPERR; siginfo_t info; + unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | + (cause > 0 ? FAULT_FLAG_WRITE : 0)); /* As of EV6, a load into $31/$f31 is a prefetch, and never faults (or is suppressed by the PALcode). Support that for older CPUs @@ -114,6 +116,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, goto vmalloc_fault; #endif +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -144,8 +147,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* If for any reason at all we couldn't handle the fault, make sure we exit gracefully rather than endlessly redo the fault. */ - fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); - up_read(&mm->mmap_sem); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return; + if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; @@ -153,10 +159,26 @@ do_page_fault(unsigned long address, unsigned long mmcsr, goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; + + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + + /* No need to up_read(&mm->mmap_sem) as we would + * have already released it in __lock_page_or_retry + * in mm/filemap.c. + */ + + goto retry; + } + } + + up_read(&mm->mmap_sem); + return; /* Something tried to access memory that isn't in our memory map. @@ -186,12 +208,14 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* We ran out of memory, or some other thing happened to us that made us unable to handle the page fault gracefully. */ out_of_memory: + up_read(&mm->mmap_sem); if (!user_mode(regs)) goto no_context; pagefault_out_of_memory(); return; do_sigbus: + up_read(&mm->mmap_sem); /* Send a sigbus, regardless of whether we were in kernel or user mode. */ info.si_signo = SIGBUS; -- GitLab From 0be421862b857e61964435ffcaa7499cf77a5e5a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 19 Aug 2012 14:41:02 +1200 Subject: [PATCH 5617/5711] alpha: fix fpu.h usage in userspace After commit ec2212088c42 ("Disintegrate asm/system.h for Alpha"), the fpu.h header which we install for userland started depending on special_insns.h which is not installed. However, fpu.h only uses that for __KERNEL__ code, so protect the inclusion the same way to avoid build breakage in glibc: /usr/include/asm/fpu.h:4:31: fatal error: asm/special_insns.h: No such file or directory Cc: stable@vger.kernel.org Reported-by: Matt Turner Signed-off-by: Mike Frysinger Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/fpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/alpha/include/asm/fpu.h b/arch/alpha/include/asm/fpu.h index db00f7885faa..e477bcd5b94a 100644 --- a/arch/alpha/include/asm/fpu.h +++ b/arch/alpha/include/asm/fpu.h @@ -1,7 +1,9 @@ #ifndef __ASM_ALPHA_FPU_H #define __ASM_ALPHA_FPU_H +#ifdef __KERNEL__ #include +#endif /* * Alpha floating-point control register defines: -- GitLab From 67a806d9499353fabd5b5ff07337f3aa88a1c3ba Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Sun, 19 Aug 2012 14:41:03 +1200 Subject: [PATCH 5618/5711] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts The following build error occurred during an alpha build: net/core/sock.c:274:36: error: initializer element is not constant Dave Anglin says: > Here is the line in sock.i: > > struct static_key memalloc_socks = ((struct static_key) { .enabled = > ((atomic_t) { (0) }) }); The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression. The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions. Cc: Signed-off-by: Mel Gorman Signed-off-by: Fengguang Wu Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 3bb7ffeae3bc..c2cbe4fc391c 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -14,8 +14,8 @@ */ -#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) -#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) -- GitLab From d1b5153f3ec83789b71d64efaf2a880c8fe6358e Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Aug 2012 14:41:04 +1200 Subject: [PATCH 5619/5711] alpha: Fix fall-out from disintegrating asm/system.h Commit ec2212088c42 ("Disintegrate asm/system.h for Alpha") removed asm/system.h however arch/alpha/oprofile/common.c requires definitions that were shifted from asm/system.h to asm/special_insns.h. Include that. Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds --- arch/alpha/oprofile/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c index a0a5d27aa215..b8ce18f485d3 100644 --- a/arch/alpha/oprofile/common.c +++ b/arch/alpha/oprofile/common.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "op_impl.h" -- GitLab From 94f3ec6b2222eb5c0af0c784f0656ff5b909d870 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 18 Aug 2012 18:55:15 +0300 Subject: [PATCH 5620/5711] sound: oss/sb_audio: prevent divide by zero bug Speed comes from get_user() in audio_ioctl(). We use it to set the "s" variable before clamping it to valid values so it could lead to a divide by zero bug. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/oss/sb_audio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c index 733b014ec7d1..b2b3c014221a 100644 --- a/sound/oss/sb_audio.c +++ b/sound/oss/sb_audio.c @@ -575,13 +575,15 @@ static int jazz16_audio_set_speed(int dev, int speed) if (speed > 0) { int tmp; - int s = speed * devc->channels; + int s; if (speed < 5000) speed = 5000; if (speed > 44100) speed = 44100; + s = speed * devc->channels; + devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff; tmp = 256 - devc->tconst; -- GitLab From 8513915accc611e576dbebb93422c257e7e68be8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 17:43:05 -0700 Subject: [PATCH 5621/5711] ALSA: fix pcm.h kernel-doc warning and notation Fix kernel-doc warning in and add function name to make the kernel-doc notation complete. Warning(include/sound/pcm.h:1081): No description found for parameter 'substream' Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c75c0d1a85e2..cdca2ab1e711 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1075,7 +1075,8 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); /** - * Get a string naming the direction of a stream + * snd_pcm_stream_str - Get a string naming the direction of a stream + * @substream: the pcm substream instance */ static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) { -- GitLab From aaf265c22e48f10c94ad04d23b6ab0c88f554d35 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:58 +0200 Subject: [PATCH 5622/5711] ALSA: sound/atmel/abdac.c: fix error return code Initialize retval before returning from a failed call to ioremap. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/atmel/abdac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index 98554f4882b7..277ebce23a45 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -452,6 +452,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) dac->regs = ioremap(regs->start, resource_size(regs)); if (!dac->regs) { dev_dbg(&pdev->dev, "could not remap register memory\n"); + retval = -ENOMEM; goto out_free_card; } -- GitLab From 0c23e46eb4878422c25351ff54ab0fe80c643809 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:57 +0200 Subject: [PATCH 5623/5711] ALSA: sound/atmel/ac97c.c: fix error return code In the first case, the second test of whether retval is negative is redundant. It is dropped and the previous and subsequent tests are combined. In the second case, add an initialization of retval on failure of ioremap. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/atmel/ac97c.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 3c8d3ba7ddfc..9052aff37f64 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -278,14 +278,9 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, if (retval < 0) return retval; /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000()) { - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); - } + if (cpu_is_at32ap7000() && retval == 1) + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.rx_chan); /* Set restrictions to params. */ mutex_lock(&opened_mutex); @@ -980,6 +975,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) if (!chip->regs) { dev_dbg(&pdev->dev, "could not remap register memory\n"); + retval = -ENOMEM; goto err_ioremap; } -- GitLab From 4d8ce1c9966663bad69e738952179f3cc52710bf Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:56 +0200 Subject: [PATCH 5624/5711] ALSA: sound/pci/ctxfi/ctatc.c: fix error return code Initialize err before returning on failure, as done elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/ctatc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 8e40262d4117..2f6e9c762d3f 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1725,8 +1725,10 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, atc_connect_resources(atc); atc->timer = ct_timer_new(atc); - if (!atc->timer) + if (!atc->timer) { + err = -ENOMEM; goto error1; + } err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops); if (err < 0) -- GitLab From ae970eb45d8a1ea4506be23c3f776225b9575d0e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:55 +0200 Subject: [PATCH 5625/5711] ALSA: sound/pci/sis7019.c: fix error return code Initialize rc before returning on failure, as done elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/sis7019.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 512434efcc31..805ab6e9a78f 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1377,8 +1377,9 @@ static int __devinit sis_chip_create(struct snd_card *card, if (rc) goto error_out_cleanup; - if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, - sis)) { + rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, + sis); + if (rc) { dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq); goto error_out_cleanup; } -- GitLab From b17cbdd85f84c8323189416da6e9701d2793b0e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:54 +0200 Subject: [PATCH 5626/5711] ALSA: sound/pci/rme9652/hdspm.c: fix error return code Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index b8ac8710f47f..b12308b5ba2a 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6585,7 +6585,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, snd_printk(KERN_ERR "HDSPM: " "unable to kmalloc Mixer memory of %d Bytes\n", (int)sizeof(struct hdspm_mixer)); - return err; + return -ENOMEM; } hdspm->port_names_in = NULL; -- GitLab From c86b93628e5649fd7bb0574b570a51b2b02d586c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:59 +0200 Subject: [PATCH 5627/5711] ALSA: sound/ppc/snd_ps3.c: fix error return code Initialize ret before returning on failure, as done elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/ppc/snd_ps3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 1aa52eff526a..9b18b5243a56 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -1040,6 +1040,7 @@ static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) GFP_KERNEL); if (!the_card.null_buffer_start_vaddr) { pr_info("%s: nullbuffer alloc failed\n", __func__); + ret = -ENOMEM; goto clean_preallocate; } pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, -- GitLab From 3296193d1421c2d6f9e49e181cecfd917f0f5764 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 14 Aug 2012 13:20:23 +0000 Subject: [PATCH 5628/5711] dt: introduce for_each_available_child_of_node, of_get_next_available_child Macro for_each_child_of_node() makes it easy to iterate over all of the children for a given device tree node, including those nodes that are marked as unavailable (i.e. status = "disabled"). Introduce for_each_available_child_of_node(), which is like for_each_child_of_node(), but it automatically skips unavailable nodes. This also requires the introduction of helper function of_get_next_available_child(), which returns the next available child node. Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/of/base.c | 27 +++++++++++++++++++++++++++ include/linux/of.h | 7 +++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index c181b94abc36..d4a1c9a043e1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -363,6 +363,33 @@ struct device_node *of_get_next_child(const struct device_node *node, } EXPORT_SYMBOL(of_get_next_child); +/** + * of_get_next_available_child - Find the next available child node + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * This function is like of_get_next_child(), except that it + * automatically skips any disabled nodes (i.e. status = "disabled"). + */ +struct device_node *of_get_next_available_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + read_lock(&devtree_lock); + next = prev ? prev->sibling : node->child; + for (; next; next = next->sibling) { + if (!of_device_is_available(next)) + continue; + if (of_node_get(next)) + break; + } + of_node_put(prev); + read_unlock(&devtree_lock); + return next; +} +EXPORT_SYMBOL(of_get_next_available_child); + /** * of_find_node_by_path - Find a node matching a full OF path * @path: The full path to match diff --git a/include/linux/of.h b/include/linux/of.h index 5919ee33f2b7..1b1163225f3b 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -190,10 +190,17 @@ extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_parent(struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); +extern struct device_node *of_get_next_available_child( + const struct device_node *node, struct device_node *prev); + #define for_each_child_of_node(parent, child) \ for (child = of_get_next_child(parent, NULL); child != NULL; \ child = of_get_next_child(parent, child)) +#define for_each_available_child_of_node(parent, child) \ + for (child = of_get_next_available_child(parent, NULL); child != NULL; \ + child = of_get_next_available_child(parent, child)) + static inline int of_get_child_count(const struct device_node *np) { struct device_node *child; -- GitLab From 61abcb7b058853900a3092f2c21988a444e3aaea Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 14 Aug 2012 13:20:24 +0000 Subject: [PATCH 5629/5711] netdev/phy: skip disabled mdio-mux nodes The mdio-mux driver scans all child mdio nodes, without regard to whether the node is actually used. Some device trees include all possible mdio-mux nodes and rely on the boot loader to disable those that are not present, based on some run-time configuration. Those nodes need to be skipped. Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 5c120189ec86..4d4d25efc1e1 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -132,7 +132,7 @@ int mdio_mux_init(struct device *dev, pb->mii_bus = parent_bus; ret_val = -ENODEV; - for_each_child_of_node(dev->of_node, child_bus_node) { + for_each_available_child_of_node(dev->of_node, child_bus_node) { u32 v; r = of_property_read_u32(child_bus_node, "reg", &v); -- GitLab From d0418bb7123f44b23d69ac349eec7daf9103472f Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 14 Aug 2012 20:33:29 +0000 Subject: [PATCH 5630/5711] net: sh_eth: Add eth support for R8A7779 device Signed-off-by: Phil Edworthy Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/Kconfig | 4 ++-- drivers/net/ethernet/renesas/sh_eth.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 46df3a04030c..24c2305d7948 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -8,7 +8,7 @@ config SH_ETH (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ - CPU_SUBTYPE_SH7757 || ARCH_R8A7740) + CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779) select CRC32 select NET_CORE select MII @@ -18,4 +18,4 @@ config SH_ETH Renesas SuperH Ethernet device driver. This driver supporting CPUs are: - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, - and R8A7740. + R8A7740 and R8A7779. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index af0b867a6cf6..bad8f2eec9b4 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev) #endif /* There is CPU dependent code */ -#if defined(CONFIG_CPU_SUBTYPE_SH7724) +#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779) #define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_duplex(struct net_device *ndev) { @@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev) static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); + unsigned int bits = ECMR_RTM; + +#if defined(CONFIG_ARCH_R8A7779) + bits |= ECMR_ELB; +#endif switch (mdp->speed) { case 10: /* 10BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR); break; case 100:/* 100BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR); break; default: break; -- GitLab From 10cbc1d97a7c7f9ae862fffe27b771ef0da9c461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 15 Aug 2012 03:42:57 +0000 Subject: [PATCH 5631/5711] net: qmi_wwan: new devices: UML290 and K5006-Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newer firmware versions for the Pantech UML290 use a different subclass ID. The Windows driver match on both IDs, so we do that as well. The ZTE (Vodafone) K5006-Z is a new device. Cc: Dan Williams Cc: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index aaa061b7355d..328397c66730 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -373,6 +373,10 @@ static const struct usb_device_id products[] = { USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), .driver_info = (unsigned long)&qmi_wwan_shared, }, + { /* Pantech UML290 - newer firmware */ + USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), + .driver_info = (unsigned long)&qmi_wwan_shared, + }, /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ @@ -382,6 +386,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ -- GitLab From b3f0db1c772ca8f08feabe9d2636dcc1103c5cb8 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 15 Aug 2012 21:53:38 +0000 Subject: [PATCH 5632/5711] smsc75xx: add missing entry to MAINTAINERS Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f87589075552..560bd30b1d7f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7289,6 +7289,12 @@ W: http://www.connecttech.com S: Supported F: drivers/usb/serial/whiteheat* +USB SMSC75XX ETHERNET DRIVER +M: Steve Glendinning +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/usb/smsc75xx.* + USB SMSC95XX ETHERNET DRIVER M: Steve Glendinning L: netdev@vger.kernel.org -- GitLab From 82a820e8d75f7f3fcd1af24609da79d7d89d5450 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 16 Aug 2012 21:46:56 +0000 Subject: [PATCH 5633/5711] drivers/net/wimax/i2400m/fw.c: fix error return code Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e1,e2; @@ if (ret < 0) { ... return ret; } ... when != ret = e1 when forall *if(...) { ... when != ret = e2 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/fw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 283237f6f074..def12b38cbf7 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -326,8 +326,10 @@ int i2400m_barker_db_init(const char *_options) unsigned barker; options_orig = kstrdup(_options, GFP_KERNEL); - if (options_orig == NULL) + if (options_orig == NULL) { + result = -ENOMEM; goto error_parse; + } options = options_orig; while ((token = strsep(&options, ",")) != NULL) { -- GitLab From 623d896b361f404de5ed24e312a58646ee04207d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 16 Aug 2012 21:46:57 +0000 Subject: [PATCH 5634/5711] drivers/net/wan/dscc4.c: fix error return code Move up the initialization of rc so that failure of pci_alloc_consistent returns -ENOMEM as well. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e1,e2; @@ if (ret < 0) { ... return ret; } ... when != ret = e1 when forall *if(...) { ... when != ret = e2 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/wan/dscc4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 9eb6479306d6..ef36cafd44b7 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -774,14 +774,15 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, } /* Global interrupt queue */ writel((u32)(((IRQ_RING_SIZE >> 5) - 1) << 20), ioaddr + IQLENR1); + + rc = -ENOMEM; + priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(__le32), &priv->iqcfg_dma); if (!priv->iqcfg) goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); - rc = -ENOMEM; - /* * SCC 0-3 private rx/tx irq structures * IQRX/TXi needs to be set soon. Learned it the hard way... -- GitLab From 9915e67eb1134b4710a4888a3e041c757869e0e2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 16 Aug 2012 21:46:58 +0000 Subject: [PATCH 5635/5711] drivers/net/irda: fix error return code Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e1,e2; @@ if (ret < 0) { ... return ret; } ... when != ret = e1 when forall *if(...) { ... when != ret = e2 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/irda/ks959-sir.c | 1 + drivers/net/irda/ksdazzle-sir.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 824e2a93fe8a..5f3aeac3f86d 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -542,6 +542,7 @@ static int ks959_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { + err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 5a278ab83c2f..2d4b6a1ab202 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -436,6 +436,7 @@ static int ksdazzle_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { + err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } -- GitLab From c41999a23929f30808bae6009d8065052d4d73fd Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 20 Aug 2012 11:17:00 +0200 Subject: [PATCH 5636/5711] ALSA: hda - don't create dysfunctional mixer controls for ca0132 It's possible that these amps are settable somehow, e g through secret codec verbs, but for now, don't create the controls (as they won't be working anyway, and cause errors in amixer). Cc: stable@kernel.org BugLink: https://bugs.launchpad.net/bugs/1038651 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 9c0ec0a55bef..49750a96d649 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -275,6 +275,10 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { + snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } @@ -286,6 +290,10 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { + snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } -- GitLab From c0de08d04215031d68fa13af36f347a6cfa252ca Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 16 Aug 2012 22:02:58 +0000 Subject: [PATCH 5637/5711] af_packet: don't emit packet on orig fanout group If a packet is emitted on one socket in one group of fanout sockets, it is transmitted again. It is thus read again on one of the sockets of the fanout group. This result in a loop for software which generate packets when receiving one. This retransmission is not the intended behavior: a fanout group must behave like a single socket. The packet should not be transmitted on a socket if it originates from a socket belonging to the same fanout group. This patch fixes the issue by changing the transmission check to take fanout group info account. Reported-by: Aleksandr Kotov Signed-off-by: Eric Leblond Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 16 ++++++++++++++-- net/packet/af_packet.c | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3560d688161e..59dc05f38247 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1522,6 +1522,8 @@ struct packet_type { struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); int (*gro_complete)(struct sk_buff *skb); + bool (*id_match)(struct packet_type *ptype, + struct sock *sk); void *af_packet_priv; struct list_head list; }; diff --git a/net/core/dev.c b/net/core/dev.c index a39354ee1432..debd9372472f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1642,6 +1642,19 @@ static inline int deliver_skb(struct sk_buff *skb, return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } +static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) +{ + if (ptype->af_packet_priv == NULL) + return false; + + if (ptype->id_match) + return ptype->id_match(ptype, skb->sk); + else if ((struct sock *)ptype->af_packet_priv == skb->sk) + return true; + + return false; +} + /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -1659,8 +1672,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) * they originated from - MvS (miquels@drinkel.ow.org) */ if ((ptype->dev == dev || !ptype->dev) && - (ptype->af_packet_priv == NULL || - (struct sock *)ptype->af_packet_priv != skb->sk)) { + (!skb_loop_sk(ptype, skb))) { if (pt_prev) { deliver_skb(skb2, pt_prev, skb->dev); pt_prev = ptype; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8ac890a1a4c0..aee7196aac36 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1273,6 +1273,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) spin_unlock(&f->lock); } +bool match_fanout_group(struct packet_type *ptype, struct sock * sk) +{ + if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) + return true; + + return false; +} + static int fanout_add(struct sock *sk, u16 id, u16 type_flags) { struct packet_sock *po = pkt_sk(sk); @@ -1325,6 +1333,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) match->prot_hook.dev = po->prot_hook.dev; match->prot_hook.func = packet_rcv_fanout; match->prot_hook.af_packet_priv = match; + match->prot_hook.id_match = match_fanout_group; dev_add_pack(&match->prot_hook); list_add(&match->list, &fanout_list); } -- GitLab From d92c7f8aabae913de16eb855b19cd2002c341896 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 17 Aug 2012 10:33:12 +0000 Subject: [PATCH 5638/5711] caif: Do not dereference NULL in chnl_recv_cb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In net/caif/chnl_net.c::chnl_recv_cb() we call skb_header_pointer() which may return NULL, but we do not check for a NULL pointer before dereferencing it. This patch adds such a NULL check and properly free's allocated memory and return an error (-EINVAL) on failure - much better than crashing.. Signed-off-by: Jesper Juhl Acked-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/chnl_net.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 69771c04ba8f..e597733affb8 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -94,6 +94,10 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) /* check the version of IP */ ip_version = skb_header_pointer(skb, 0, 1, &buf); + if (!ip_version) { + kfree_skb(skb); + return -EINVAL; + } switch (*ip_version >> 4) { case 4: -- GitLab From ae4d8cf299dbea4ce387a01da6f723c4050b31a7 Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Sat, 18 Aug 2012 00:16:23 +0000 Subject: [PATCH 5639/5711] net/stmmac: fix issue of clk_get for Loongson1B. When getting clock, give a chance to the CPUs without DT support, which use Common Clock Framework, such as Loongson1B. Signed-off-by: Kelvin Cheung Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fd8882f9602a..c136162e6473 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2077,7 +2077,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, goto error_netdev_register; } - priv->stmmac_clk = clk_get(priv->device, NULL); + priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); if (IS_ERR(priv->stmmac_clk)) { pr_warning("%s: warning: cannot get CSR clock\n", __func__); goto error_clk_get; -- GitLab From 9d7b0fc1ef1f17aff57c0dc9a59453d8fca255c3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Aug 2012 02:56:56 -0700 Subject: [PATCH 5640/5711] net: ipv6: fix oops in inet_putpeer() Commit 97bab73f (inet: Hide route peer accesses behind helpers.) introduced a bug in xfrm6_policy_destroy(). The xfrm_dst's _rt6i_peer member is not initialized, causing a false positive result from inetpeer_ptr_is_peer(), which in turn causes a NULL pointer dereference in inet_putpeer(). Pid: 314, comm: kworker/0:1 Not tainted 3.6.0-rc1+ #17 To Be Filled By O.E.M. To Be Filled By O.E.M./P4S800D-X EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at inet_putpeer+0xe/0x16 EAX: 00000000 EBX: f3481700 ECX: 00000000 EDX: 000dd641 ESI: f3481700 EDI: c05e949c EBP: f551def4 ESP: f551def4 DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 CR0: 8005003b CR2: 00000070 CR3: 3243d000 CR4: 00000750 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 f551df04 c0423de1 00000000 f3481700 f551df18 c038d5f7 f254b9f8 f551df28 f34f85d8 f551df20 c03ef48d f551df3c c0396870 f30697e8 f24e1738 c05e98f4 f5509540 c05cd2b4 f551df7c c0142d2b c043feb5 f5509540 00000000 c05cd2e8 [] xfrm6_dst_destroy+0x42/0xdb [] dst_destroy+0x1d/0xa4 [] xfrm_bundle_flo_delete+0x2b/0x36 [] flow_cache_gc_task+0x85/0x9f [] process_one_work+0x122/0x441 [] ? apic_timer_interrupt+0x31/0x38 [] ? flow_cache_new_hashrnd+0x2b/0x2b [] worker_thread+0x113/0x3cc Fix by adding a init_dst() callback to struct xfrm_policy_afinfo to properly initialize the dst's peer pointer. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 ++ net/ipv6/xfrm6_policy.c | 8 ++++++++ net/xfrm/xfrm_policy.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 62b619e82a90..976a81abe1a2 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -292,6 +292,8 @@ struct xfrm_policy_afinfo { struct flowi *fl, int reverse); int (*get_tos)(const struct flowi *fl); + void (*init_dst)(struct net *net, + struct xfrm_dst *dst); int (*init_path)(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ef39812107b1..f8c4c08ffb60 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -73,6 +73,13 @@ static int xfrm6_get_tos(const struct flowi *fl) return 0; } +static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) +{ + struct rt6_info *rt = (struct rt6_info *)xdst; + + rt6_init_peer(rt, net->ipv6.peers); +} + static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len) { @@ -286,6 +293,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { .get_saddr = xfrm6_get_saddr, .decode_session = _decode_session6, .get_tos = xfrm6_get_tos, + .init_dst = xfrm6_init_dst, .init_path = xfrm6_init_path, .fill_dst = xfrm6_fill_dst, .blackhole_route = ip6_blackhole_route, diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c5a5165a5927..5a2aa17e4d3c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1357,6 +1357,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); xdst->flo.ops = &xfrm_bundle_fc_ops; + if (afinfo->init_dst) + afinfo->init_dst(net, xdst); } else xdst = ERR_PTR(-ENOBUFS); -- GitLab From b817bf5c72774556345a9043c6b0c497cdcb7295 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 16 Aug 2012 08:01:21 +0200 Subject: [PATCH 5641/5711] pwm: Improve Kconfig help text The Kconfig help text should help the user understand what functionality is provided by an option. This is especially true for new subsystems. An improved help text is provided by this commit in the hopes of clarifying the usefulness of the PWM framework. Signed-off-by: Thierry Reding Acked-by: Borislav Petkov --- drivers/pwm/Kconfig | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8fc3808d7a3e..90c5c7357a50 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -1,12 +1,31 @@ menuconfig PWM - bool "PWM Support" + bool "Pulse-Width Modulation (PWM) Support" depends on !MACH_JZ4740 && !PUV3_PWM help - This enables PWM support through the generic PWM framework. - You only need to enable this, if you also want to enable - one or more of the PWM drivers below. - - If unsure, say N. + Generic Pulse-Width Modulation (PWM) support. + + In Pulse-Width Modulation, a variation of the width of pulses + in a rectangular pulse signal is used as a means to alter the + average power of the signal. Applications include efficient + power delivery and voltage regulation. In computer systems, + PWMs are commonly used to control fans or the brightness of + display backlights. + + This framework provides a generic interface to PWM devices + within the Linux kernel. On the driver side it provides an API + to register and unregister a PWM chip, an abstraction of a PWM + controller, that supports one or more PWM devices. Client + drivers can request PWM devices and use the generic framework + to configure as well as enable and disable them. + + This generic framework replaces the legacy PWM framework which + allows only a single driver implementing the required API. Not + all legacy implementations have been ported to the framework + yet. The framework provides an API that is backward compatible + with the legacy framework so that existing client drivers + continue to work as expected. + + If unsure, say no. if PWM -- GitLab From 72d3eb13b5c0abe7d63efac41f39c5b644c7bbaa Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Sat, 18 Aug 2012 07:02:20 +0000 Subject: [PATCH 5642/5711] netconsole: remove a redundant netconsole_target_put() This netconsole_target_put() is obviously redundant, and it causes a kernel segfault when removing a bridge device which has netconsole running on it. This is caused by: commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 Author: Amerigo Wang Date: Thu May 19 21:39:10 2011 +0000 netpoll: disable netpoll when enslave a device Cc: David Miller (for all 3.x stable releases) Cc: stable@vger.kernel.org Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f0ad56c13933..b3321129a83c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -643,7 +643,6 @@ static int netconsole_netdev_event(struct notifier_block *this, __netpoll_cleanup(&nt->np); dev_put(nt->np.dev); nt->np.dev = NULL; - netconsole_target_put(nt); } nt->enabled = 0; stopped = true; -- GitLab From 3de7a37b02f607716753dc669c1dca4f71db08fc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 14:36:44 +0000 Subject: [PATCH 5643/5711] net/core/dev.c: fix kernel-doc warning Fix kernel-doc warning: Warning(net/core/dev.c:5745): No description found for parameter 'dev' Signed-off-by: Randy Dunlap Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index debd9372472f..83988362805e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5744,6 +5744,7 @@ EXPORT_SYMBOL(netdev_refcnt_read); /** * netdev_wait_allrefs - wait until all references are gone. + * @dev: target net_device * * This is called when unregistering network devices. * -- GitLab From fae6ef87faeb8853896920c68ee703d715799d28 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sun, 19 Aug 2012 03:30:38 +0000 Subject: [PATCH 5644/5711] net: tcp: move sk_rx_dst_set call after tcp_create_openreq_child() This commit removes the sk_rx_dst_set calls from tcp_create_openreq_child(), because at that point the icsk_af_ops field of ipv6_mapped TCP sockets has not been set to its proper final value. Instead, to make sure we get the right sk_rx_dst_set variant appropriate for the address family of the new connection, we have tcp_v{4,6}_syn_recv_sock() directly call the appropriate function shortly after the call to tcp_create_openreq_child() returns. This also moves inet6_sk_rx_dst_set() to avoid a forward declaration with the new approach. Signed-off-by: Neal Cardwell Reported-by: Artem Savkov Cc: Eric Dumazet Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_minisocks.c | 2 -- net/ipv6/tcp_ipv6.c | 25 +++++++++++++------------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 767823764016..5bf2040b25b1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1462,6 +1462,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, goto exit_nonewsk; newsk->sk_gso_type = SKB_GSO_TCPV4; + inet_sk_rx_dst_set(newsk, skb); newtp = tcp_sk(newsk); newinet = inet_sk(newsk); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index d9c9dcef2de3..6ff7f10dce9d 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -387,8 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct tcp_sock *oldtp = tcp_sk(sk); struct tcp_cookie_values *oldcvp = oldtp->cookie_values; - newicsk->icsk_af_ops->sk_rx_dst_set(newsk, skb); - /* TCP Cookie Transactions require space for the cookie pair, * as it differs for each connection. There is no need to * copy any s_data_payload stored at the original socket. diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bb9ce2b2f377..a3e60cc04a8a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -94,6 +94,18 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, } #endif +static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + const struct rt6_info *rt = (const struct rt6_info *)dst; + + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + if (rt->rt6i_node) + inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; +} + static void tcp_v6_hash(struct sock *sk) { if (sk->sk_state != TCP_CLOSE) { @@ -1270,6 +1282,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newsk->sk_gso_type = SKB_GSO_TCPV6; __ip6_dst_store(newsk, dst, NULL, NULL); + inet6_sk_rx_dst_set(newsk, skb); newtcp6sk = (struct tcp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1729,18 +1742,6 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_destructor= tcp_twsk_destructor, }; -static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - const struct rt6_info *rt = (const struct rt6_info *)dst; - - dst_hold(dst); - sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; - if (rt->rt6i_node) - inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; -} - static const struct inet_connection_sock_af_ops ipv6_specific = { .queue_xmit = inet6_csk_xmit, .send_check = tcp_v6_send_check, -- GitLab From 5efcc76c13a745f98e7b6604d6aca49761be1970 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 17 Aug 2012 14:40:04 -0400 Subject: [PATCH 5645/5711] drm/radeon: avoid turning off spread spectrum for used pll If spread spectrum is enabled and in use for a given pll we should not turn it off as it will lead to turning off display for crtc that use the pll (this behavior was observed on chelsea edp). Signed-off-by: Jerome Glisse Cc: stable@vger.kernel.org Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_crtc.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c6fcb5b86a45..cb18813c7df0 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -444,11 +444,28 @@ union atom_enable_ss { static void atombios_crtc_program_ss(struct radeon_device *rdev, int enable, int pll_id, + int crtc_id, struct radeon_atom_ss *ss) { + unsigned i; int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; + if (!enable) { + for (i = 0; i < 6; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != crtc_id && + pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off spread spectrum as it might turn off + * display on active crtc + */ + return; + } + } + } + memset(&args, 0, sizeof(args)); if (ASIC_IS_DCE5(rdev)) { @@ -1028,7 +1045,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, &ref_div, &post_div); - atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1051,7 +1068,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ss.step = step_size; } - atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); } } @@ -1572,11 +1589,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) ASIC_INTERNAL_SS_ON_DCPLL, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); /* XXX: DCE5, make sure voltage, dispclk is high enough */ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); } } -- GitLab From 48c0ac9911839daf188e4a0b6b132ac31050a241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 20 Aug 2012 15:38:47 +0200 Subject: [PATCH 5646/5711] drm/radeon: init lockup timeout on ring init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reset the lockup timeout on ring (re-)initialisation. Otherwise we get error messages like this on gpu resets: [ 1559.949177] radeon 0000:01:00.0: GPU lockup CP stall for more than 1482270msec Signed-off-by: Christian König cc: stable@vger.kernel.org Reviewed-by: Michel Dänzer --- drivers/gpu/drm/radeon/radeon_ring.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index ec79b3750430..43c431a2686d 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -706,6 +706,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig if (radeon_debugfs_ring_init(rdev, ring)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } + radeon_ring_lockup_update(ring); return 0; } -- GitLab From c116cc94969447f44fd7205a027084ceebe90d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 19 Aug 2012 02:22:09 +0200 Subject: [PATCH 5647/5711] drm/radeon: allow CMASK and FMASK in the CS checker on r600-r700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MSAA is impossible without them. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse --- drivers/gpu/drm/radeon/r600_cs.c | 94 ++++++++++++++++++++++++---- drivers/gpu/drm/radeon/r600d.h | 17 +++++ drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/reg_srcs/r600 | 8 --- 4 files changed, 101 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 3dab49cb1d4a..1bec5b8bba18 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -47,13 +47,17 @@ struct r600_cs_track { u32 npipes; /* value we track */ u32 sq_config; + u32 log_nsamples; u32 nsamples; u32 cb_color_base_last[8]; struct radeon_bo *cb_color_bo[8]; u64 cb_color_bo_mc[8]; - u32 cb_color_bo_offset[8]; - struct radeon_bo *cb_color_frag_bo[8]; /* unused */ - struct radeon_bo *cb_color_tile_bo[8]; /* unused */ + u64 cb_color_bo_offset[8]; + struct radeon_bo *cb_color_frag_bo[8]; + u64 cb_color_frag_offset[8]; + struct radeon_bo *cb_color_tile_bo[8]; + u64 cb_color_tile_offset[8]; + u32 cb_color_mask[8]; u32 cb_color_info[8]; u32 cb_color_view[8]; u32 cb_color_size_idx[8]; /* unused */ @@ -349,10 +353,6 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) unsigned array_mode; u32 format; - if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { - dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); - return -EINVAL; - } size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; format = G_0280A0_FORMAT(track->cb_color_info[i]); if (!r600_fmt_is_valid_color(format)) { @@ -441,7 +441,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) * broken userspace. */ } else { - dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", + dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n", __func__, i, array_mode, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]), @@ -458,6 +458,51 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) | S_028060_SLICE_TILE_MAX(slice_tile_max - 1); ib[track->cb_color_size_idx[i]] = tmp; + + /* FMASK/CMASK */ + switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { + case V_0280A0_TILE_DISABLE: + break; + case V_0280A0_FRAG_ENABLE: + if (track->nsamples > 1) { + uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); + /* the tile size is 8x8, but the size is in units of bits. + * for bytes, do just * 8. */ + uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1); + + if (bytes + track->cb_color_frag_offset[i] > + radeon_bo_size(track->cb_color_frag_bo[i])) { + dev_warn(p->dev, "%s FMASK_TILE_MAX too large " + "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", + __func__, tile_max, bytes, + track->cb_color_frag_offset[i], + radeon_bo_size(track->cb_color_frag_bo[i])); + return -EINVAL; + } + } + /* fall through */ + case V_0280A0_CLEAR_ENABLE: + { + uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); + /* One block = 128x128 pixels, one 8x8 tile has 4 bits.. + * (128*128) / (8*8) / 2 = 128 bytes per block. */ + uint32_t bytes = (block_max + 1) * 128; + + if (bytes + track->cb_color_tile_offset[i] > + radeon_bo_size(track->cb_color_tile_bo[i])) { + dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large " + "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", + __func__, block_max, bytes, + track->cb_color_tile_offset[i], + radeon_bo_size(track->cb_color_tile_bo[i])); + return -EINVAL; + } + break; + } + default: + dev_warn(p->dev, "%s invalid tile mode\n", __func__); + return -EINVAL; + } return 0; } @@ -1231,6 +1276,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) break; case R_028C04_PA_SC_AA_CONFIG: tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); + track->log_nsamples = tmp; track->nsamples = 1 << tmp; track->cb_dirty = true; break; @@ -1312,16 +1358,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL; } - ib[idx] = track->cb_color_base_last[tmp]; track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; + track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp]; + ib[idx] = track->cb_color_base_last[tmp]; } else { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL; } - ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); track->cb_color_frag_bo[tmp] = reloc->robj; + track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; } break; case R_0280C0_CB_COLOR0_TILE: @@ -1338,16 +1389,35 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL; } - ib[idx] = track->cb_color_base_last[tmp]; track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; + track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp]; + ib[idx] = track->cb_color_base_last[tmp]; } else { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL; } - ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); track->cb_color_tile_bo[tmp] = reloc->robj; + track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; + } + break; + case R_028100_CB_COLOR0_MASK: + case R_028104_CB_COLOR1_MASK: + case R_028108_CB_COLOR2_MASK: + case R_02810C_CB_COLOR3_MASK: + case R_028110_CB_COLOR4_MASK: + case R_028114_CB_COLOR5_MASK: + case R_028118_CB_COLOR6_MASK: + case R_02811C_CB_COLOR7_MASK: + tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; + track->cb_color_mask[tmp] = ib[idx]; + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; } break; case CB_COLOR0_BASE: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index fd328f4c3ea8..bdb69a63062f 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -92,6 +92,20 @@ #define R_028094_CB_COLOR5_VIEW 0x028094 #define R_028098_CB_COLOR6_VIEW 0x028098 #define R_02809C_CB_COLOR7_VIEW 0x02809C +#define R_028100_CB_COLOR0_MASK 0x028100 +#define S_028100_CMASK_BLOCK_MAX(x) (((x) & 0xFFF) << 0) +#define G_028100_CMASK_BLOCK_MAX(x) (((x) >> 0) & 0xFFF) +#define C_028100_CMASK_BLOCK_MAX 0xFFFFF000 +#define S_028100_FMASK_TILE_MAX(x) (((x) & 0xFFFFF) << 12) +#define G_028100_FMASK_TILE_MAX(x) (((x) >> 12) & 0xFFFFF) +#define C_028100_FMASK_TILE_MAX 0x00000FFF +#define R_028104_CB_COLOR1_MASK 0x028104 +#define R_028108_CB_COLOR2_MASK 0x028108 +#define R_02810C_CB_COLOR3_MASK 0x02810C +#define R_028110_CB_COLOR4_MASK 0x028110 +#define R_028114_CB_COLOR5_MASK 0x028114 +#define R_028118_CB_COLOR6_MASK 0x028118 +#define R_02811C_CB_COLOR7_MASK 0x02811C #define CB_COLOR0_INFO 0x280a0 # define CB_FORMAT(x) ((x) << 2) # define CB_ARRAY_MODE(x) ((x) << 8) @@ -1400,6 +1414,9 @@ #define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18) #define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3) #define C_0280A0_TILE_MODE 0xFFF3FFFF +#define V_0280A0_TILE_DISABLE 0 +#define V_0280A0_CLEAR_ENABLE 1 +#define V_0280A0_FRAG_ENABLE 2 #define S_0280A0_BLEND_CLAMP(x) (((x) & 0x1) << 20) #define G_0280A0_BLEND_CLAMP(x) (((x) >> 20) & 0x1) #define C_0280A0_BLEND_CLAMP 0xFFEFFFFF diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d7269f48d37c..27d22d709c90 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -62,9 +62,10 @@ * 2.18.0 - r600-eg: allow "invalid" DB formats * 2.19.0 - r600-eg: MSAA textures * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query + * 2.21.0 - r600-r700: FMASK and CMASK */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 20 +#define KMS_DRIVER_MINOR 21 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 5e659b034d9a..f93e45d869f4 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,14 +744,6 @@ r600 0x9400 0x00028C38 CB_CLRCMP_DST 0x00028C3C CB_CLRCMP_MSK 0x00028C34 CB_CLRCMP_SRC -0x00028100 CB_COLOR0_MASK -0x00028104 CB_COLOR1_MASK -0x00028108 CB_COLOR2_MASK -0x0002810C CB_COLOR3_MASK -0x00028110 CB_COLOR4_MASK -0x00028114 CB_COLOR5_MASK -0x00028118 CB_COLOR6_MASK -0x0002811C CB_COLOR7_MASK 0x00028808 CB_COLOR_CONTROL 0x0002842C CB_FOG_BLUE 0x00028428 CB_FOG_GREEN -- GitLab From fcdeefe4df5c0fa457f2dc181ef4e3b2b26de781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 19 Aug 2012 21:23:26 +0200 Subject: [PATCH 5648/5711] drm/radeon: fix checking of MSAA renderbuffers on r600-r700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MSAA checking was mostly unimplemented on r600-r700. The userspace submits GPU commands and the kernel driver computes how much memory the GPU will access and checks if it's all within buffer bounds the userspace allocated. This patch fixes the computations of the size of MSAA surfaces in memory. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 1bec5b8bba18..ab74e6b149e7 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -420,7 +420,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) } /* check offset */ - tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); + tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * + r600_fmt_get_blocksize(format) * track->nsamples; switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -611,7 +612,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p) ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; - tmp = ntiles * bpe * 64 * nviews; + tmp = ntiles * bpe * 64 * nviews * track->nsamples; if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", array_mode, @@ -1562,7 +1563,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level) } static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, - unsigned w0, unsigned h0, unsigned d0, unsigned format, + unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format, unsigned block_align, unsigned height_align, unsigned base_align, unsigned *l0_size, unsigned *mipmap_size) { @@ -1590,7 +1591,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, depth = r600_mip_minify(d0, i); - size = nbx * nby * blocksize; + size = nbx * nby * blocksize * nsamples; if (nfaces) size *= nfaces; else @@ -1742,7 +1743,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, nfaces = larray - barray + 1; } - r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, + r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format, pitch_align, height_align, base_align, &l0_size, &mipmap_size); /* using get ib will give us the offset into the texture bo */ -- GitLab From 52e9b39d9a89ae33662596bd30e62dd56bddbe73 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Aug 2012 15:16:04 +0100 Subject: [PATCH 5649/5711] drm/radeon/kms: extend the Fujitsu D3003-S2 board connector quirk to cover later silicon stepping There is a more recent APU stepping with a new PCI ID shipping in the same board by Fujitsu which needs the same quirk to correctly mark the back plane connectors. Signed-off-by: Tvrtko Ursulin Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_atombios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f9c21f9d16bc..d67d4f3eb6f4 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ - if ((dev->pdev->device == 0x9802) && + if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && (dev->pdev->subsystem_vendor == 0x1734) && (dev->pdev->subsystem_device == 0x11bd)) { if (*connector_type == DRM_MODE_CONNECTOR_VGA) { -- GitLab From 268ba0a99f89a84dc5eb312470896113d0709c74 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 16 Aug 2012 15:45:20 -0400 Subject: [PATCH 5650/5711] drm/radeon: implement ACPI VFCT vbios fetch (v3) This is required for pure UEFI systems. The vbios is stored in ACPI rather than at the legacy vga location. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26891 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f4881e5aa..a32232fc7bd3 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@ #include #include +#include /* * BIOS. */ @@ -476,6 +477,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -483,6 +541,8 @@ bool radeon_get_bios(struct radeon_device *rdev) uint16_t tmp; r = radeon_atrm_get_bios(rdev); + if (r == false) + r = radeon_acpi_vfct_bios(rdev); if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) -- GitLab From 4f81f986761a7663db7d24d24cd6ae68008f1fc2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Aug 2012 10:57:22 -0400 Subject: [PATCH 5651/5711] ACPI: export symbol acpi_get_table_with_size We need it in the radeon drm module to fetch and verify the vbios image on UEFI systems. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/acpi/acpica/tbxface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ea4c6d52605a..29e51bc01383 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status acpi_get_table(char *signature, -- GitLab From 7c3906d04a4587dceaa78cc1ae6b14e6454ee02a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Aug 2012 11:06:21 -0400 Subject: [PATCH 5652/5711] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size Allows us to verify the table size. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index a32232fc7bd3..ab0b2f7292ae 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -482,13 +482,12 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { bool ret = false; struct acpi_table_header *hdr; - /* acpi_get_table_with_size is not exported :( */ - acpi_size tbl_size = 0x7fffffff; + acpi_size tbl_size; UEFI_ACPI_VFCT *vfct; GOP_VBIOS_CONTENT *vbios; VFCT_IMAGE_HEADER *vhdr; - if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) return false; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); @@ -525,7 +524,6 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) ret = !!rdev->bios; out_unmap: - /* uh, no idea what to do here... */ return ret; } #else -- GitLab From c61e2775873f603148e8e998a938721b7d222d24 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Aug 2012 15:39:09 -0400 Subject: [PATCH 5653/5711] drm/radeon: split ATRM support out from the ATPX handler (v3) There are systems that use ATRM, but not ATPX. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41265 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 15 ---- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +------------- drivers/gpu/drm/radeon/radeon_bios.c | 80 +++++++++++++++++++- 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 99304194a65c..59a15315ae9f 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -142,21 +142,6 @@ struct radeon_device; /* * BIOS. */ -#define ATRM_BIOS_PAGE 4096 - -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_atrm_supported(struct pci_dev *pdev); -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); -#else -static inline bool radeon_atrm_supported(struct pci_dev *pdev) -{ - return false; -} - -static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ - return -EINVAL; -} -#endif bool radeon_get_bios(struct radeon_device *rdev); /* diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fcb0088..2a2cf0b88a28 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,57 +30,8 @@ static struct radeon_atpx_priv { /* handle for device - and atpx */ acpi_handle dhandle; acpi_handle atpx_handle; - acpi_handle atrm_handle; } radeon_atpx_priv; -/* retrieve the ROM in 4k blocks */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, - int offset, int len) -{ - acpi_status status; - union acpi_object atrm_arg_elements[2], *obj; - struct acpi_object_list atrm_arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - - atrm_arg.count = 2; - atrm_arg.pointer = &atrm_arg_elements[0]; - - atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[0].integer.value = offset; - - atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[1].integer.value = len; - - status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); - if (ACPI_FAILURE(status)) { - printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); - return -ENODEV; - } - - obj = (union acpi_object *)buffer.pointer; - memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); - len = obj->buffer.length; - kfree(buffer.pointer); - return len; -} - -bool radeon_atrm_supported(struct pci_dev *pdev) -{ - /* get the discrete ROM only via ATRM */ - if (!radeon_atpx_priv.atpx_detected) - return false; - - if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) - return false; - return true; -} - - -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) -{ - return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); -} - static int radeon_atpx_get_version(acpi_handle handle) { acpi_status status; @@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) { - acpi_handle dhandle, atpx_handle, atrm_handle; + acpi_handle dhandle, atpx_handle; acpi_status status; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) if (ACPI_FAILURE(status)) return false; - status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); - if (ACPI_FAILURE(status)) - return false; - radeon_atpx_priv.dhandle = dhandle; radeon_atpx_priv.atpx_handle = atpx_handle; - radeon_atpx_priv.atrm_handle = atrm_handle; return true; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index ab0b2f7292ae..d306cc8fdeaa 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -99,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev) return true; } +#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems. */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + static bool radeon_atrm_get_bios(struct radeon_device *rdev) { int ret; int size = 256 * 1024; int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; - if (!radeon_atrm_supported(rdev->pdev)) + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + + if (!found) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -118,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { - ret = radeon_atrm_get_bios_chunk(rdev->bios, - (i * ATRM_BIOS_PAGE), - ATRM_BIOS_PAGE); + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break; } @@ -131,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { -- GitLab From 7653f6ff4ebab2a094e65b60fb19ee66ed2f78e7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Aug 2012 12:12:29 -0400 Subject: [PATCH 5654/5711] NFSv4: Ensure that nfs4_alloc_client cleans up on error. Any pointer that was allocated through nfs_alloc_client() needs to be freed via a call to nfs_free_client(). Reported-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust --- fs/nfs/nfs4client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index cbcdfaf32505..24eb663f8ed5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -74,7 +74,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) return clp; error: - kfree(clp); + nfs_free_client(clp); return ERR_PTR(err); } -- GitLab From 296f9fe05d916e3d791dcd166aa41c1dadca4735 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Fri, 6 Jul 2012 16:07:50 +0800 Subject: [PATCH 5655/5711] ideapad: add Lenovo IdeaPad Z570 support (part 1) The patch adds support for Lenovo IdeaPad Z570 laptop. It makes all special keys working, adds possibility to control fan like Windows does, controls Touchpad Disabled LED, toggles touchpad state via keyboard controller and corrects touchpad behavior on resume from suspend. It is new, modified version of patch. Now it does not depend on psmouse and does not need patching of input subsystem. Signed-off-by: Maxim Mikityanskiy This is part 1 for special button handling. Signed-off-by: Ike Panhc Signed-off-by: Matthew Garrett --- drivers/platform/x86/ideapad-laptop.c | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 17f6dfd8dbfb..2396242e8418 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -65,6 +65,7 @@ enum { VPCCMD_R_ODD, /* 0x21 */ VPCCMD_R_RF = 0x23, VPCCMD_W_RF, + VPCCMD_R_SPECIAL_BUTTONS = 0x31, VPCCMD_W_BL_POWER = 0x33, }; @@ -518,9 +519,13 @@ static void ideapad_platform_exit(struct ideapad_private *priv) */ static const struct key_entry ideapad_keymap[] = { { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 7, { KEY_CAMERA } }, + { KE_KEY, 11, { KEY_F16 } }, { KE_KEY, 13, { KEY_WLAN } }, { KE_KEY, 16, { KEY_PROG1 } }, { KE_KEY, 17, { KEY_PROG2 } }, + { KE_KEY, 64, { KEY_PROG3 } }, + { KE_KEY, 65, { KEY_PROG4 } }, { KE_END, 0 }, }; @@ -587,6 +592,28 @@ static void ideapad_input_novokey(struct ideapad_private *priv) ideapad_input_report(priv, 16); } +static void ideapad_check_special_buttons(struct ideapad_private *priv) +{ + unsigned long bit, value; + + read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); + + for (bit = 0; bit < 16; bit++) { + if (test_bit(bit, &value)) { + switch (bit) { + case 6: + /* Thermal Management button */ + ideapad_input_report(priv, 65); + break; + case 1: + /* OneKey Theater button */ + ideapad_input_report(priv, 64); + break; + } + } + } +} + /* * backlight */ @@ -785,6 +812,8 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_sync_rfk_state(priv); break; case 13: + case 11: + case 7: case 6: ideapad_input_report(priv, vpc_bit); break; @@ -797,6 +826,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 2: ideapad_backlight_notify_power(priv); break; + case 0: + ideapad_check_special_buttons(priv); + break; default: pr_info("Unknown event: %lu\n", vpc_bit); } -- GitLab From 07a4a4fc83dd95bc7eb842cf9510ddcb45691a88 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Fri, 6 Jul 2012 16:08:00 +0800 Subject: [PATCH 5656/5711] ideapad: add Lenovo IdeaPad Z570 support (part 2) The patch adds support for Lenovo IdeaPad Z570 laptop. It makes all special keys working, adds possibility to control fan like Windows does, controls Touchpad Disabled LED, toggles touchpad state via keyboard controller and corrects touchpad behavior on resume from suspend. It is new, modified version of patch. Now it does not depend on psmouse and does not need patching of input subsystem. Signed-off-by: Maxim Mikityanskiy This is part 2 for touchpad toggle Signed-off-by: Ike Panhc Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/ideapad-laptop.c | 35 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 637074d89790..c86bae828c28 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -289,6 +289,7 @@ config IDEAPAD_LAPTOP tristate "Lenovo IdeaPad Laptop Extras" depends on ACPI depends on RFKILL && INPUT + depends on SERIO_I8042 select INPUT_SPARSEKMAP help This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 2396242e8418..7bc1b6c60e56 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -36,6 +36,7 @@ #include #include #include +#include #define IDEAPAD_RFKILL_DEV_NUM (3) @@ -526,6 +527,8 @@ static const struct key_entry ideapad_keymap[] = { { KE_KEY, 17, { KEY_PROG2 } }, { KE_KEY, 64, { KEY_PROG3 } }, { KE_KEY, 65, { KEY_PROG4 } }, + { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, + { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, { KE_END, 0 }, }; @@ -718,6 +721,24 @@ static const struct acpi_device_id ideapad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); +static void ideapad_sync_touchpad_state(struct acpi_device *adevice) +{ + struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + unsigned long value; + + /* Without reading from EC touchpad LED doesn't switch state */ + if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { + /* Some IdeaPads don't really turn off touchpad - they only + * switch the LED state. We (de)activate KBC AUX port to turn + * touchpad off and on. We send KEY_TOUCHPAD_OFF and + * KEY_TOUCHPAD_ON to not to get out of sync with LED */ + unsigned char param; + i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : + I8042_CMD_AUX_DISABLE); + ideapad_input_report(priv, value ? 67 : 66); + } +} + static int __devinit ideapad_acpi_add(struct acpi_device *adevice) { int ret, i; @@ -754,6 +775,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) priv->rfk[i] = NULL; } ideapad_sync_rfk_state(priv); + ideapad_sync_touchpad_state(adevice); if (!acpi_video_backlight_support()) { ret = ideapad_backlight_init(priv); @@ -817,6 +839,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 6: ideapad_input_report(priv, vpc_bit); break; + case 5: + ideapad_sync_touchpad_state(adevice); + break; case 4: ideapad_backlight_notify_brightness(priv); break; @@ -836,6 +861,15 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) } } +static int ideapad_acpi_resume(struct device *device) +{ + ideapad_sync_rfk_state(ideapad_priv); + ideapad_sync_touchpad_state(to_acpi_device(device)); + return 0; +} + +static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); + static struct acpi_driver ideapad_acpi_driver = { .name = "ideapad_acpi", .class = "IdeaPad", @@ -843,6 +877,7 @@ static struct acpi_driver ideapad_acpi_driver = { .ops.add = ideapad_acpi_add, .ops.remove = ideapad_acpi_remove, .ops.notify = ideapad_acpi_notify, + .drv.pm = &ideapad_pm, .owner = THIS_MODULE, }; -- GitLab From 0c7bbeb9f1373cea9e8efb43221118be2102a01c Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Fri, 6 Jul 2012 16:08:11 +0800 Subject: [PATCH 5657/5711] ideapad: add Lenovo IdeaPad Z570 support (part 3) The patch adds support for Lenovo IdeaPad Z570 laptop. It makes all special keys working, adds possibility to control fan like Windows does, controls Touchpad Disabled LED, toggles touchpad state via keyboard controller and corrects touchpad behavior on resume from suspend. It is new, modified version of patch. Now it does not depend on psmouse and does not need patching of input subsystem. Signed-off-by: Maxim Mikityanskiy This is the part 3 for fan control Signed-off-by: Ike Panhc Signed-off-by: Matthew Garrett --- .../ABI/testing/sysfs-platform-ideapad-laptop | 11 +++++ drivers/platform/x86/ideapad-laptop.c | 43 +++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop index 814b01354c41..b31e782bd985 100644 --- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop +++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop @@ -5,4 +5,15 @@ Contact: "Ike Panhc " Description: Control the power of camera module. 1 means on, 0 means off. +What: /sys/devices/platform/ideapad/fan_mode +Date: June 2012 +KernelVersion: 3.6 +Contact: "Maxim Mikityanskiy " +Description: + Change fan mode + There are four available modes: + * 0 -> Super Silent Mode + * 1 -> Standard Mode + * 2 -> Dust Cleaning + * 4 -> Efficient Thermal Dissipation Mode diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 7bc1b6c60e56..dae7abe1d711 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -64,8 +64,10 @@ enum { VPCCMD_R_3G, VPCCMD_W_3G, VPCCMD_R_ODD, /* 0x21 */ - VPCCMD_R_RF = 0x23, + VPCCMD_W_FAN, + VPCCMD_R_RF, VPCCMD_W_RF, + VPCCMD_R_FAN = 0x2B, VPCCMD_R_SPECIAL_BUTTONS = 0x31, VPCCMD_W_BL_POWER = 0x33, }; @@ -358,14 +360,46 @@ static ssize_t store_ideapad_cam(struct device *dev, return -EINVAL; ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); if (ret < 0) - return ret; + return -EIO; return count; } static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); +static ssize_t show_ideapad_fan(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned long result; + + if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) + return sprintf(buf, "-1\n"); + return sprintf(buf, "%lu\n", result); +} + +static ssize_t store_ideapad_fan(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret, state; + + if (!count) + return 0; + if (sscanf(buf, "%i", &state) != 1) + return -EINVAL; + if (state < 0 || state > 4 || state == 3) + return -EINVAL; + ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); + if (ret < 0) + return -EIO; + return count; +} + +static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan); + static struct attribute *ideapad_attributes[] = { &dev_attr_camera_power.attr, + &dev_attr_fan_mode.attr, NULL }; @@ -379,7 +413,10 @@ static umode_t ideapad_is_visible(struct kobject *kobj, if (attr == &dev_attr_camera_power.attr) supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); - else + else if (attr == &dev_attr_fan_mode.attr) { + unsigned long value; + supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); + } else supported = true; return supported ? attr->mode : 0; -- GitLab From 086600430493e04b802bee6e5b3ce0458e4eb77f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Aug 2012 12:42:15 -0400 Subject: [PATCH 5658/5711] NFSv3: Ensure that do_proc_get_root() reports errors correctly If the rpc call to NFS3PROC_FSINFO fails, then we need to report that error so that the mount fails. Otherwise we can end up with a superblock with completely unusable values for block sizes, maxfilesize, etc. Reported-by: Yuanming Chen Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust --- fs/nfs/nfs3proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 0952c791df36..d6b3b5f2d779 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, nfs_fattr_init(info->fattr); status = rpc_call_sync(client, &msg, 0); dprintk("%s: reply fsinfo: %d\n", __func__, status); - if (!(info->fattr->valid & NFS_ATTR_FATTR)) { + if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; msg.rpc_resp = info->fattr; status = rpc_call_sync(client, &msg, 0); -- GitLab From d1c338a509cea5378df59629ad47382810c38623 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 19 Aug 2012 12:29:16 -0700 Subject: [PATCH 5659/5711] libceph: delay debugfs initialization until we learn global_id The debugfs directory includes the cluster fsid and our unique global_id. We need to delay the initialization of the debug entry until we have learned both the fsid and our global_id from the monitor or else the second client can't create its debugfs entry and will fail (and multiple client instances aren't properly reflected in debugfs). Reported by: Yan, Zheng Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh --- fs/ceph/debugfs.c | 1 + net/ceph/ceph_common.c | 1 - net/ceph/debugfs.c | 4 ++++ net/ceph/mon_client.c | 51 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdacee..6d59006bfa27 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) int err = -ENOMEM; dout("ceph_fs_debugfs_init\n"); + BUG_ON(!fsc->client->debugfs_dir); fsc->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 0600, diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 69e38db28e5f..a8020293f342 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) return -1; } } else { - pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); } return 0; diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 54b531a01121..38b5dc1823d4 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c @@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, client->monc.auth->global_id); + dout("ceph_debugfs_client_init %p %s\n", client, name); + + BUG_ON(client->debugfs_dir); client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); if (!client->debugfs_dir) goto out; @@ -234,6 +237,7 @@ out: void ceph_debugfs_client_cleanup(struct ceph_client *client) { + dout("ceph_debugfs_client_cleanup %p\n", client); debugfs_remove(client->debugfs_osdmap); debugfs_remove(client->debugfs_monmap); debugfs_remove(client->osdc.debugfs_file); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 105d533b55f3..900ea0f043fc 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -310,6 +310,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) } EXPORT_SYMBOL(ceph_monc_open_session); +/* + * We require the fsid and global_id in order to initialize our + * debugfs dir. + */ +static bool have_debugfs_info(struct ceph_mon_client *monc) +{ + dout("have_debugfs_info fsid %d globalid %lld\n", + (int)monc->client->have_fsid, monc->auth->global_id); + return monc->client->have_fsid && monc->auth->global_id > 0; +} + /* * The monitor responds with mount ack indicate mount success. The * included client ticket allows the client to talk to MDSs and OSDs. @@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, struct ceph_client *client = monc->client; struct ceph_monmap *monmap = NULL, *old = monc->monmap; void *p, *end; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); + dout("handle_monmap\n"); p = msg->front.iov_base; end = p + msg->front.iov_len; @@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, if (!client->have_fsid) { client->have_fsid = true; + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); - /* - * do debugfs initialization without mutex to avoid - * creating a locking dependency - */ - ceph_debugfs_client_init(client); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } + goto out_unlocked; } out: @@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, { int ret; int was_auth = 0; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); if (monc->auth->ops) was_auth = monc->auth->ops->is_authenticated(monc->auth); monc->pending_auth = 0; @@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc, __send_subscribe(monc); __resend_generic_request(monc); } + + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } } static int __validate_auth(struct ceph_mon_client *monc) -- GitLab From 0e665d5d1125f9f4ccff56a75e814f10f88861a2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Aug 2012 15:28:00 +0100 Subject: [PATCH 5660/5711] vfs: missed source of ->f_pos races compat_sys_{read,write}v() need the same "pass a copy of file->f_pos" thing as sys_{read,write}{,v}(). Signed-off-by: Al Viro Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- fs/compat.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index 6161255fac45..1bdb350ea5d3 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1155,11 +1155,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_readv(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_readv(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } @@ -1221,11 +1224,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_writev(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_writev(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } -- GitLab From 1ee9ae3244c4789f3184c5123f3b2d7e405b3f4c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 15 Aug 2012 10:41:45 +0200 Subject: [PATCH 5661/5711] drm/i915: use hsw rps tuning values everywhere on gen6+ James Bottomley reported [1] a massive power regression, due to the enabling of semaphores by default in 3.5. A workaround for him is to again disable semaphores. And indeed, his system has a very hard time to enter rc6 with semaphores enabled. Ben Widawsky run around with a kill-a-watt a lot and noticed: - There are indeed a few rare systems that seem to have a hard time entering rc6 when desktop-idle. - One machine, The Indestructible Toshiba regressed in this behaviour between 3.5 and 3.6 in a merge commit! So rc6 behaviour with the current setting seems to be highly timing dependent and not robust at all. - The behaviour James reported wrt semaphores seems to be a freak timing thing that only happens on his specific machine, confirming that enabling semaphores shouldn't reduce rc6 residency. Now furthermore the Google ChromeOS guys reported [2] a while ago that at least on some machines a simply a blinking cursor can keep the gpu turbo at the highest frequency. This is because the current rps limits used on snb/ivb are highly asymmetric. On the theory that gpu turbo and rc6 tuning values are related, we've tried whether the much saner looking (since much less asymmetric) rps tuning values used for hsw would also help entering rc6 more robustly. And it seems to mostly work, and we don't really have the resources to through-roughly tune things in any better way: The values from the ChromeOS ppl seem to fare a bit worse for James' machine, so I guess we better stick with something vpg (the gpu hw/windows group) provided, hoping that they've done their jobs. Reference[1]: http://lists.freedesktop.org/archives/dri-devel/2012-July/025675.html Reference[2]: http://lists.freedesktop.org/archives/intel-gfx/2012-July/018692.html Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=53393 Tested-by: Ben Widawsky Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 58c07cdafb7e..1881c8c83f0e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2441,17 +2441,10 @@ static void gen6_enable_rps(struct drm_device *dev) dev_priv->max_delay << 24 | dev_priv->min_delay << 16); - if (IS_HASWELL(dev)) { - I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); - I915_WRITE(GEN6_RP_UP_EI, 66000); - I915_WRITE(GEN6_RP_DOWN_EI, 350000); - } else { - I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); - I915_WRITE(GEN6_RP_UP_EI, 100000); - I915_WRITE(GEN6_RP_DOWN_EI, 5000000); - } + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); I915_WRITE(GEN6_RP_CONTROL, -- GitLab From 8f057d7bca549e8f7c1f8e750c75598986f5d9aa Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 20 Aug 2012 11:23:16 -0700 Subject: [PATCH 5662/5711] gpu/mfd/usb: Fix USB randconfig problems Fix config warning: warning: ( ... && DRM_USB) selects USB which has unmet direct dependencies (USB_SUPPORT && USB_ARCH_HAS_HCD) and build error: ERROR: "usb_speed_string" [drivers/usb/core/usbcore.ko] undefined! by adding the missing dependency on USB_ARCH_HAS_HCD to DRM_UDL and DRM_USB. This exposes: drivers/video/Kconfig:36:error: recursive dependency detected! drivers/video/Kconfig:36: symbol FB is selected by DRM_KMS_HELPER drivers/gpu/drm/Kconfig:28: symbol DRM_KMS_HELPER is selected by DRM_UDL drivers/gpu/drm/udl/Kconfig:1: symbol DRM_UDL depends on USB_ARCH_HAS_HCD drivers/usb/Kconfig:78: symbol USB_ARCH_HAS_HCD depends on USB_ARCH_HAS_OHCI drivers/usb/Kconfig:16: symbol USB_ARCH_HAS_OHCI depends on I2C drivers/i2c/Kconfig:5: symbol I2C is selected by FB_DDC drivers/video/Kconfig:86: symbol FB_DDC is selected by FB_CYBER2000_DDC drivers/video/Kconfig:385: symbol FB_CYBER2000_DDC depends on FB_CYBER2000 drivers/video/Kconfig:373: symbol FB_CYBER2000 depends on FB which is due to drivers/usb/Kconfig: config USB_ARCH_HAS_OHCI ... default y if ARCH_PNX4008 && I2C Fix by dropping I2C from the above dependency; logic is that this is not a platform dependency but a configuration dependency: the _architecture_ still supports USB even is I2C is not selected. This exposes: drivers/video/Kconfig:36:error: recursive dependency detected! drivers/video/Kconfig:36: symbol FB is selected by DRM_KMS_HELPER drivers/gpu/drm/Kconfig:28: symbol DRM_KMS_HELPER is selected by DRM_UDL drivers/gpu/drm/udl/Kconfig:1: symbol DRM_UDL depends on USB_ARCH_HAS_HCD drivers/usb/Kconfig:78: symbol USB_ARCH_HAS_HCD depends on USB_ARCH_HAS_OHCI drivers/usb/Kconfig:17: symbol USB_ARCH_HAS_OHCI depends on MFD_TC6393XB drivers/mfd/Kconfig:396: symbol MFD_TC6393XB depends on GPIOLIB drivers/gpio/Kconfig:35: symbol GPIOLIB is selected by FB_VIA drivers/video/Kconfig:1560: symbol FB_VIA depends on FB which can be fixed by having MFD_TC6393XB select GPIOLIB instead of depending on it. Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/udl/Kconfig | 1 + drivers/mfd/Kconfig | 3 ++- drivers/usb/Kconfig | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 23120c00a881..90e28081712d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -22,6 +22,7 @@ menuconfig DRM config DRM_USB tristate depends on DRM + depends on USB_ARCH_HAS_HCD select USB config DRM_KMS_HELPER diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig index 0b5e096d39a6..56e0bf31d425 100644 --- a/drivers/gpu/drm/udl/Kconfig +++ b/drivers/gpu/drm/udl/Kconfig @@ -1,6 +1,7 @@ config DRM_UDL tristate "DisplayLink" depends on DRM && EXPERIMENTAL + depends on USB_ARCH_HAS_HCD select DRM_USB select FB_SYS_FILLRECT select FB_SYS_COPYAREA diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d1facef28a60..b1a146205c08 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -395,7 +395,8 @@ config MFD_TC6387XB config MFD_TC6393XB bool "Support Toshiba TC6393XB" - depends on GPIOLIB && ARM && HAVE_CLK + depends on ARM && HAVE_CLK + select GPIOLIB select MFD_CORE select MFD_TMIO help diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index a7773a3e02b1..7065df6036ca 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -13,7 +13,7 @@ config USB_ARCH_HAS_OHCI default y if PXA3xx default y if ARCH_EP93XX default y if ARCH_AT91 - default y if ARCH_PNX4008 && I2C + default y if ARCH_PNX4008 default y if MFD_TC6393XB default y if ARCH_W90X900 default y if ARCH_DAVINCI_DA8XX -- GitLab From 535b6c51fe8293c88ce919cdfc4390c67a1cb6d1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Aug 2012 21:25:22 +0200 Subject: [PATCH 5663/5711] ALSA: hda - Fix leftover codec->power_transition When the codec turn-on operation is canceled by the immediate power-on, the driver left the power_transition flag as is. This caused the persistent avoidance of power-save behavior. Cc: [v3.5+] Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c3077d5dec6e..f560051a949e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4454,6 +4454,8 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) * then there is no need to go through power up here. */ if (codec->power_on) { + if (codec->power_transition < 0) + codec->power_transition = 0; spin_unlock(&codec->power_lock); return; } -- GitLab From 7c3ea4859ae132d61594320e148b0348f03c0edc Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 18 Aug 2012 13:23:49 -0300 Subject: [PATCH 5664/5711] [IA64] defconfig: Remove CONFIG_MISC_DEVICES commit 7c5763b845 (drivers:misc: Remove MISC_DEVICES config option) removed CONFIG_MISC_DEVICES option, so remove the occurrences from the config files as well. Signed-off-by: Fabio Estevam Signed-off-by: Tony Luck --- arch/ia64/configs/generic_defconfig | 1 - arch/ia64/configs/gensparse_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index 954d81e2e837..7913695b2fcb 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -234,5 +234,4 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_T10DIF=y -CONFIG_MISC_DEVICES=y CONFIG_INTEL_IOMMU=y diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 91c41ecfa6d9..f8e913365423 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -209,4 +209,3 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y CONFIG_CRYPTO_MD5=y -CONFIG_MISC_DEVICES=y -- GitLab From 6de7145ca3db231a84b7516a6cb25878da6ebb19 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sat, 18 Aug 2012 15:44:09 -0700 Subject: [PATCH 5665/5711] tcm_vhost: Fix vhost_scsi_target structure alignment Here TRANSPORT_IQN_LEN is 224, which is a multiple of 4. Since vhost_tpgt is 2 bytes and abi_version is 4, the total size would be 230. But gcc needs struct size be aligned to first field size, which is 4 bytes, so it pads the structure by extra 2 bytes to the total of 232. This padding is very undesirable in an ABI: - it can not be initialized easily - it can not be checked easily - it can leak information between kernel and userspace Simplest solution is probably just to make the padding explicit. (v2: Add check for zero'ed backend->reserved field for VHOST_SCSI_SET_ENDPOINT and VHOST_SCSI_CLEAR_ENDPOINT ops as requested by MST) Reported-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Signed-off-by: Nicholas Bellinger --- drivers/vhost/tcm_vhost.c | 4 ++++ drivers/vhost/tcm_vhost.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index 74b2edaaf1f6..ed8e2e6c8df2 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -995,11 +995,15 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, case VHOST_SCSI_SET_ENDPOINT: if (copy_from_user(&backend, argp, sizeof backend)) return -EFAULT; + if (backend.reserved != 0) + return -EOPNOTSUPP; return vhost_scsi_set_endpoint(vs, &backend); case VHOST_SCSI_CLEAR_ENDPOINT: if (copy_from_user(&backend, argp, sizeof backend)) return -EFAULT; + if (backend.reserved != 0) + return -EOPNOTSUPP; return vhost_scsi_clear_endpoint(vs, &backend); case VHOST_SCSI_GET_ABI_VERSION: diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h index e9d5c020fb39..d9e93557d669 100644 --- a/drivers/vhost/tcm_vhost.h +++ b/drivers/vhost/tcm_vhost.h @@ -93,6 +93,7 @@ struct vhost_scsi_target { int abi_version; char vhost_wwpn[TRANSPORT_IQN_LEN]; unsigned short vhost_tpgt; + unsigned short reserved; }; /* VHOST_SCSI specific defines */ -- GitLab From 08a16208c8cb2ce1f79fea24f21dd7a8df4f12b6 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Sat, 18 Aug 2012 16:10:31 +0400 Subject: [PATCH 5666/5711] tcm_fc: rcu_deref outside rcu lock/unlock section Use rcu_dereference_protected in order to prevent lockdep complaint. Sequel of the patch 863555be Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Denis Efremov Acked-by: Mark D. Rustad Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_sess.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 87901fa74dd7..3c9e5b57caab 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -456,7 +456,9 @@ static void ft_prlo(struct fc_rport_priv *rdata) struct ft_tport *tport; mutex_lock(&ft_lport_lock); - tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); + tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], + lockdep_is_held(&ft_lport_lock)); + if (!tport) { mutex_unlock(&ft_lport_lock); return; -- GitLab From 53e1719f3da0f095b8db1461bd12dd79f3246b84 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 20 Aug 2012 21:50:13 +0200 Subject: [PATCH 5667/5711] ALSA: snd-als100: fix suspend/resume snd_card_als100_probe() does not set pcm field in struct snd_sb. As a result, PCM is not suspended and applications don't know that they need to resume the playback. Tested with Labway A381-F20 card (ALS120). Signed-off-by: Ondrej Zary Signed-off-by: Takashi Iwai --- sound/isa/als100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 2d67c78c9f4b..f7cdaf51512d 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -233,7 +233,7 @@ static int __devinit snd_card_als100_probe(int dev, irq[dev], dma8[dev], dma16[dev]); } - if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { + if ((error = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) { snd_card_free(card); return error; } -- GitLab From 676bc2e1e4f9072f7a640d5b7c99ffdf9709a6e7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 09:55:01 -0400 Subject: [PATCH 5668/5711] Revert "drm/radeon: fix bo creation retry path" This reverts commit d1c7871ddb1f588b8eb35affd9ee1a3d5e11cd0c. ttm_bo_init() destroys the BO on failure. So this patch makes the retry path work with freed memory. This ends up causing kernel panics when this path is hit. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_object.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1cb014b571ab..9024e7222839 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -132,6 +132,7 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); +retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -145,8 +146,6 @@ int radeon_bo_create(struct radeon_device *rdev, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->va); - -retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ down_read(&rdev->pm.mclk_lock); -- GitLab From ec5da7f8dc023fc4dcbdd42e87dad231d2c2812d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 21 Aug 2012 16:40:07 +1000 Subject: [PATCH 5669/5711] fbcon: fix race condition between console lock and cursor timer So we've had a fair few reports of fbcon handover breakage between efi/vesafb and i915 surface recently, so I dedicated a couple of days to finding the problem. Essentially the last thing we saw was the conflicting framebuffer message and that was all. So after much tracing with direct netconsole writes (printks under console_lock not so useful), I think I found the race. Thread A (driver load) Thread B (timer thread) unbind_con_driver -> | bind_con_driver -> | vc->vc_sw->con_deinit -> | fbcon_deinit -> | console_lock() | | | | fbcon_flashcursor timer fires | console_lock() <- blocked for A | | fbcon_del_cursor_timer -> del_timer_sync (BOOM) Of course because all of this is under the console lock, we never see anything, also since we also just unbound the active console guess what we never see anything. Hopefully this fixes the problem for anyone seeing vesafb->kms driver handoff. Signed-off-by: David Airlie Acked-by: Alan Cox Cc: stable@vger.kernel.org Tested-by: Josh Boyer Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e471c22abf5..f8a79fca4a22 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -372,8 +372,12 @@ static void fb_flashcursor(struct work_struct *work) struct vc_data *vc = NULL; int c; int mode; + int ret; + + ret = console_trylock(); + if (ret == 0) + return; - console_lock(); if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; -- GitLab From f341861fb0b701139849f8a85c2d3cdff466e8e8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Aug 2012 15:05:14 +0200 Subject: [PATCH 5670/5711] task_work: add a scheduling point in task_work_run() It seems commit 4a9d4b024a31 ("switch fput to task_work_add") re- introduced the problem addressed in 944be0b22472 ("close_files(): add scheduling point") If a server process with a lot of files (say 2 million tcp sockets) is killed, we can spend a lot of time in task_work_run() and trigger a soft lockup. Signed-off-by: Eric Dumazet Signed-off-by: Linus Torvalds --- kernel/task_work.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/task_work.c b/kernel/task_work.c index 91d4e1742a0c..d320d44903bd 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -75,6 +75,7 @@ void task_work_run(void) p = q->next; q->func(q); q = p; + cond_resched(); } } } -- GitLab From af74115eed22698f771fec1287a864975c9a6671 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 15 Aug 2012 21:24:52 -0700 Subject: [PATCH 5671/5711] target: Remove unused se_cmd.cmd_spdtl This was originally for helping fabrics to determine overflow/underflow status, and has been superceeded by SCF_OVERFLOW_BIT + SCF_UNDERFLOW_BIT. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 2 -- include/target/target_core_base.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ea9a3d2e4f55..4de3186dc44e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1165,8 +1165,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) " 0x%02x\n", cmd->se_tfo->get_fabric_name(), cmd->data_length, size, cmd->t_task_cdb[0]); - cmd->cmd_spdtl = size; - if (cmd->data_direction == DMA_TO_DEVICE) { pr_err("Rejecting underflow/overflow" " WRITE data\n"); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 128ce46fa48a..015cea01ae39 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -503,8 +503,6 @@ struct se_cmd { u32 se_ordered_id; /* Total size in bytes associated with command */ u32 data_length; - /* SCSI Presented Data Transfer Length */ - u32 cmd_spdtl; u32 residual_count; u32 orig_fe_lun; /* Persistent Reservation key */ -- GitLab From 144d56e91044181ec0ef67aeca91e9a8b5718348 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 Aug 2012 00:22:46 +0000 Subject: [PATCH 5672/5711] tcp: fix possible socket refcount problem Commit 6f458dfb40 (tcp: improve latencies of timer triggered events) added bug leading to following trace : [ 2866.131281] IPv4: Attempt to release TCP socket in state 1 ffff880019ec0000 [ 2866.131726] [ 2866.132188] ========================= [ 2866.132281] [ BUG: held lock freed! ] [ 2866.132281] 3.6.0-rc1+ #622 Not tainted [ 2866.132281] ------------------------- [ 2866.132281] kworker/0:1/652 is freeing memory ffff880019ec0000-ffff880019ec0a1f, with a lock still held there! [ 2866.132281] (sk_lock-AF_INET-RPC){+.+...}, at: [] tcp_sendmsg+0x29/0xcc6 [ 2866.132281] 4 locks held by kworker/0:1/652: [ 2866.132281] #0: (rpciod){.+.+.+}, at: [] process_one_work+0x1de/0x47f [ 2866.132281] #1: ((&task->u.tk_work)){+.+.+.}, at: [] process_one_work+0x1de/0x47f [ 2866.132281] #2: (sk_lock-AF_INET-RPC){+.+...}, at: [] tcp_sendmsg+0x29/0xcc6 [ 2866.132281] #3: (&icsk->icsk_retransmit_timer){+.-...}, at: [] run_timer_softirq+0x1ad/0x35f [ 2866.132281] [ 2866.132281] stack backtrace: [ 2866.132281] Pid: 652, comm: kworker/0:1 Not tainted 3.6.0-rc1+ #622 [ 2866.132281] Call Trace: [ 2866.132281] [] debug_check_no_locks_freed+0x112/0x159 [ 2866.132281] [] ? __sk_free+0xfd/0x114 [ 2866.132281] [] kmem_cache_free+0x6b/0x13a [ 2866.132281] [] __sk_free+0xfd/0x114 [ 2866.132281] [] sk_free+0x1c/0x1e [ 2866.132281] [] tcp_write_timer+0x51/0x56 [ 2866.132281] [] run_timer_softirq+0x218/0x35f [ 2866.132281] [] ? run_timer_softirq+0x1ad/0x35f [ 2866.132281] [] ? rb_commit+0x58/0x85 [ 2866.132281] [] ? tcp_write_timer_handler+0x148/0x148 [ 2866.132281] [] __do_softirq+0xcb/0x1f9 [ 2866.132281] [] ? _raw_spin_unlock+0x29/0x2e [ 2866.132281] [] call_softirq+0x1c/0x30 [ 2866.132281] [] do_softirq+0x4a/0xa6 [ 2866.132281] [] irq_exit+0x51/0xad [ 2866.132281] [] do_IRQ+0x9d/0xb4 [ 2866.132281] [] common_interrupt+0x6f/0x6f [ 2866.132281] [] ? sched_clock_cpu+0x58/0xd1 [ 2866.132281] [] ? _raw_spin_unlock_irqrestore+0x4c/0x56 [ 2866.132281] [] mod_timer+0x178/0x1a9 [ 2866.132281] [] sk_reset_timer+0x19/0x26 [ 2866.132281] [] tcp_rearm_rto+0x99/0xa4 [ 2866.132281] [] tcp_event_new_data_sent+0x6e/0x70 [ 2866.132281] [] tcp_write_xmit+0x7de/0x8e4 [ 2866.132281] [] ? __alloc_skb+0xa0/0x1a1 [ 2866.132281] [] __tcp_push_pending_frames+0x2e/0x8a [ 2866.132281] [] tcp_sendmsg+0xb32/0xcc6 [ 2866.132281] [] inet_sendmsg+0xaa/0xd5 [ 2866.132281] [] ? inet_autobind+0x5f/0x5f [ 2866.132281] [] ? trace_clock_local+0x9/0xb [ 2866.132281] [] sock_sendmsg+0xa3/0xc4 [ 2866.132281] [] ? rb_reserve_next_event+0x26f/0x2d5 [ 2866.132281] [] ? native_sched_clock+0x29/0x6f [ 2866.132281] [] ? sched_clock+0x9/0xd [ 2866.132281] [] ? trace_clock_local+0x9/0xb [ 2866.132281] [] kernel_sendmsg+0x37/0x43 [ 2866.132281] [] xs_send_kvec+0x77/0x80 [ 2866.132281] [] xs_sendpages+0x6f/0x1a0 [ 2866.132281] [] ? try_to_del_timer_sync+0x55/0x61 [ 2866.132281] [] xs_tcp_send_request+0x55/0xf1 [ 2866.132281] [] xprt_transmit+0x89/0x1db [ 2866.132281] [] ? call_connect+0x3c/0x3c [ 2866.132281] [] call_transmit+0x1c5/0x20e [ 2866.132281] [] __rpc_execute+0x6f/0x225 [ 2866.132281] [] ? call_connect+0x3c/0x3c [ 2866.132281] [] rpc_async_schedule+0x28/0x34 [ 2866.132281] [] process_one_work+0x24d/0x47f [ 2866.132281] [] ? process_one_work+0x1de/0x47f [ 2866.132281] [] ? __rpc_execute+0x225/0x225 [ 2866.132281] [] worker_thread+0x236/0x317 [ 2866.132281] [] ? process_scheduled_works+0x2f/0x2f [ 2866.132281] [] kthread+0x9a/0xa2 [ 2866.132281] [] kernel_thread_helper+0x4/0x10 [ 2866.132281] [] ? retint_restore_args+0x13/0x13 [ 2866.132281] [] ? __init_kthread_worker+0x5a/0x5a [ 2866.132281] [] ? gs_change+0x13/0x13 [ 2866.308506] IPv4: Attempt to release TCP socket in state 1 ffff880019ec0000 [ 2866.309689] ============================================================================= [ 2866.310254] BUG TCP (Not tainted): Object already free [ 2866.310254] ----------------------------------------------------------------------------- [ 2866.310254] The bug comes from the fact that timer set in sk_reset_timer() can run before we actually do the sock_hold(). socket refcount reaches zero and we free the socket too soon. timer handler is not allowed to reduce socket refcnt if socket is owned by the user, or we need to change sk_reset_timer() implementation. We should take a reference on the socket in case TCP_DELACK_TIMER_DEFERRED or TCP_DELACK_TIMER_DEFERRED bit are set in tsq_flags Also fix a typo in tcp_delack_timer(), where TCP_WRITE_TIMER_DEFERRED was used instead of TCP_DELACK_TIMER_DEFERRED. For consistency, use same socket refcount change for TCP_MTU_REDUCED_DEFERRED, even if not fired from a timer. Reported-by: Fengguang Wu Tested-by: Fengguang Wu Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 8 +++++--- net/ipv4/tcp_output.c | 14 +++++++++----- net/ipv4/tcp_timer.c | 6 ++++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5bf2040b25b1..00a748d14062 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -417,10 +417,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ tp->mtu_info = info; - if (!sock_owned_by_user(sk)) + if (!sock_owned_by_user(sk)) { tcp_v4_mtu_reduced(sk); - else - set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); + } else { + if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags)) + sock_hold(sk); + } goto out; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 20dfd892c86f..d04632673a9e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -910,14 +910,18 @@ void tcp_release_cb(struct sock *sk) if (flags & (1UL << TCP_TSQ_DEFERRED)) tcp_tsq_handler(sk); - if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) + if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { tcp_write_timer_handler(sk); - - if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) + __sock_put(sk); + } + if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) { tcp_delack_timer_handler(sk); - - if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) + __sock_put(sk); + } + if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { sk->sk_prot->mtu_reduced(sk); + __sock_put(sk); + } } EXPORT_SYMBOL(tcp_release_cb); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6df36ad55a38..b774a03bd1dc 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -252,7 +252,8 @@ static void tcp_delack_timer(unsigned long data) inet_csk(sk)->icsk_ack.blocked = 1; NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); /* deleguate our work to tcp_release_cb() */ - set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); + if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) + sock_hold(sk); } bh_unlock_sock(sk); sock_put(sk); @@ -481,7 +482,8 @@ static void tcp_write_timer(unsigned long data) tcp_write_timer_handler(sk); } else { /* deleguate our work to tcp_release_cb() */ - set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); + if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) + sock_hold(sk); } bh_unlock_sock(sk); sock_put(sk); -- GitLab From 1a7b27c97ce675b42eeb7bfaf6e15c34f35c8f95 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Mon, 20 Aug 2012 02:52:09 +0000 Subject: [PATCH 5673/5711] ipv4: Use newinet->inet_opt in inet_csk_route_child_sock() Since 0e734419923bd ("ipv4: Use inet_csk_route_child_sock() in DCCP and TCP."), inet_csk_route_child_sock() is called instead of inet_csk_route_req(). However, after creating the child-sock in tcp/dccp_v4_syn_recv_sock(), ireq->opt is set to NULL, before calling inet_csk_route_child_sock(). Thus, inside inet_csk_route_child_sock() opt is always NULL and the SRR-options are not respected anymore. Packets sent by the server won't have the correct destination-IP. This patch fixes it by accessing newinet->inet_opt instead of ireq->opt inside inet_csk_route_child_sock(). Reported-by: Luca Boccassi Signed-off-by: Christoph Paasch Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index db0cf17c00f7..7f75f21d7b83 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -404,12 +404,15 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, { const struct inet_request_sock *ireq = inet_rsk(req); struct inet_sock *newinet = inet_sk(newsk); - struct ip_options_rcu *opt = ireq->opt; + struct ip_options_rcu *opt; struct net *net = sock_net(sk); struct flowi4 *fl4; struct rtable *rt; fl4 = &newinet->cork.fl.u.ip4; + + rcu_read_lock(); + opt = rcu_dereference(newinet->inet_opt); flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), @@ -421,11 +424,13 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, goto no_route; if (opt && opt->opt.is_strictroute && rt->rt_gateway) goto route_err; + rcu_read_unlock(); return &rt->dst; route_err: ip_rt_put(rt); no_route: + rcu_read_unlock(); IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } -- GitLab From a9915a1b52df52ad87f3b33422da95cf25372f09 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 Aug 2012 07:26:45 +0000 Subject: [PATCH 5674/5711] ipv4: fix ip header ident selection in __ip_make_skb() Christian Casteyde reported a kmemcheck 32-bit read from uninitialized memory in __ip_select_ident(). It turns out that __ip_make_skb() called ip_select_ident() before properly initializing iph->daddr. This is a bug uncovered by commit 1d861aa4b3fb (inet: Minimize use of cached route inetpeer.) Addresses https://bugzilla.kernel.org/show_bug.cgi?id=46131 Reported-by: Christian Casteyde Signed-off-by: Eric Dumazet Cc: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 147ccc3e93db..c196d749daf2 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1338,10 +1338,10 @@ struct sk_buff *__ip_make_skb(struct sock *sk, iph->ihl = 5; iph->tos = inet->tos; iph->frag_off = df; - ip_select_ident(iph, &rt->dst, sk); iph->ttl = ttl; iph->protocol = sk->sk_protocol; ip_copy_addrs(iph, fl4); + ip_select_ident(iph, &rt->dst, sk); if (opt) { iph->ihl += opt->optlen>>2; -- GitLab From e0e3cea46d31d23dc40df0a49a7a2c04fe8edfea Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Aug 2012 06:21:17 +0000 Subject: [PATCH 5675/5711] af_netlink: force credentials passing [CVE-2012-3520] Pablo Neira Ayuso discovered that avahi and potentially NetworkManager accept spoofed Netlink messages because of a kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data to the receiver if the sender did not provide such data, instead of not including any such data at all or including the correct data from the peer (as it is the case with AF_UNIX). This bug was introduced in commit 16e572626961 (af_unix: dont send SCM_CREDENTIALS by default) This patch forces passing credentials for netlink, as before the regression. Another fix would be to not add SCM_CREDENTIALS in netlink messages if not provided by the sender, but it might break some programs. With help from Florian Weimer & Petr Matousek This issue is designated as CVE-2012-3520 Signed-off-by: Eric Dumazet Cc: Petr Matousek Cc: Florian Weimer Cc: Pablo Neira Ayuso Signed-off-by: David S. Miller --- include/net/scm.h | 4 +++- net/netlink/af_netlink.c | 2 +- net/unix/af_unix.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/scm.h b/include/net/scm.h index 079d7887dac1..7dc0854f0b38 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) } static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, - struct scm_cookie *scm) + struct scm_cookie *scm, bool forcecreds) { memset(scm, 0, sizeof(*scm)); + if (forcecreds) + scm_set_cred(scm, task_tgid(current), current_cred()); unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5463969da45b..1445d73533ed 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &scm; - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, true); if (err < 0) return err; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e4768c180da2..c5ee4ff61364 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, false); if (err < 0) return err; @@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, false); if (err < 0) return err; -- GitLab From 5317670692f61675394db2eb6713484b67383750 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 18:52:56 -0400 Subject: [PATCH 5676/5711] drm/radeon/ss: use num_crtc rather than hardcoded 6 When checking if a pll is in use. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index cb18813c7df0..f4d4505fe831 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -452,7 +452,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, union atom_enable_ss args; if (!enable) { - for (i = 0; i < 6; i++) { + for (i = 0; i < rdev->num_crtc; i++) { if (rdev->mode_info.crtcs[i] && rdev->mode_info.crtcs[i]->enabled && i != crtc_id && -- GitLab From 6c5e50fa614fea5325a2973be06f7ec6f1055316 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 21 Aug 2012 15:55:25 -0700 Subject: [PATCH 5677/5711] ceph: tolerate (and warn on) extraneous dentry from mds If the MDS gives us a dentry and we weren't prepared to handle it, WARN_ON_ONCE instead of crashing. Reported-by: Yan, Zheng Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- fs/ceph/inode.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e4..4b5762ef7c2b 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, if (rinfo->head->is_dentry) { struct inode *dir = req->r_locked_dir; - err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, - session, req->r_request_started, -1, - &req->r_caps_reservation); - if (err < 0) - return err; + if (dir) { + err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, + session, req->r_request_started, -1, + &req->r_caps_reservation); + if (err < 0) + return err; + } else { + WARN_ON_ONCE(1); + } } /* @@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, * will have trouble splicing in the virtual snapdir later */ if (rinfo->head->is_dentry && !req->r_aborted && + req->r_locked_dir && (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, fsc->mount_options->snapdir_name, req->r_dentry->d_name.len))) { -- GitLab From 6d4221b53707486dfad3f5bfe568d2ce7f4c9863 Mon Sep 17 00:00:00 2001 From: Jim Schutt Date: Fri, 10 Aug 2012 10:37:38 -0700 Subject: [PATCH 5678/5711] libceph: avoid truncation due to racing banners Because the Ceph client messenger uses a non-blocking connect, it is possible for the sending of the client banner to race with the arrival of the banner sent by the peer. When ceph_sock_state_change() notices the connect has completed, it schedules work to process the socket via con_work(). During this time the peer is writing its banner, and arrival of the peer banner races with con_work(). If con_work() calls try_read() before the peer banner arrives, there is nothing for it to do, after which con_work() calls try_write() to send the client's banner. In this case Ceph's protocol negotiation can complete succesfully. The server-side messenger immediately sends its banner and addresses after accepting a connect request, *before* actually attempting to read or verify the banner from the client. As a result, it is possible for the banner from the server to arrive before con_work() calls try_read(). If that happens, try_read() will read the banner and prepare protocol negotiation info via prepare_write_connect(). prepare_write_connect() calls con_out_kvec_reset(), which discards the as-yet-unsent client banner. Next, con_work() calls try_write(), which sends the protocol negotiation info rather than the banner that the peer is expecting. The result is that the peer sees an invalid banner, and the client reports "negotiation failed". Fix this by moving con_out_kvec_reset() out of prepare_write_connect() to its callers at all locations except the one where the banner might still need to be sent. [elder@inktak.com: added note about server-side behavior] Signed-off-by: Jim Schutt Reviewed-by: Alex Elder --- net/ceph/messenger.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b9796750034a..24c5eea8c45b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; - con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) @@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_reply.global_seq)); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -2135,7 +2138,11 @@ more: BUG_ON(con->state != CON_STATE_CONNECTING); con->state = CON_STATE_NEGOTIATING; - /* Banner is good, exchange connection info */ + /* + * Received banner is good, exchange connection info. + * Do not reset out_kvec, as sending our banner raced + * with receiving peer banner after connect completed. + */ ret = prepare_write_connect(con); if (ret < 0) goto out; -- GitLab From 45f2e081f573526977abfa781a12728f83e9641f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 21 Aug 2012 12:11:51 -0700 Subject: [PATCH 5679/5711] ceph: avoid divide by zero in __validate_layout() If "l->stripe_unit" is zero the the mod on the next line will cause a divide by zero bug. This comes from the copy_from_user() in ceph_ioctl_set_layout_policy(). Passing 0 is valid, though (it means "do not change") so avoid the % check in that case. Reported-by: Dan Carpenter Signed-off-by: Sage Weil Reviewed-by: Alex Elder --- fs/ceph/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8e3fb69fbe62..1396ceb46797 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc, /* validate striping parameters */ if ((l->object_size & ~PAGE_MASK) || (l->stripe_unit & ~PAGE_MASK) || - ((unsigned)l->object_size % (unsigned)l->stripe_unit)) + (l->stripe_unit != 0 && + ((unsigned)l->object_size % (unsigned)l->stripe_unit))) return -EINVAL; /* make sure it's a valid data pool */ -- GitLab From f5869a8308f77e3dfdc2e3640842b285aa788ff8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 20 Aug 2012 14:44:52 +0000 Subject: [PATCH 5680/5711] drm: stop vmgfx driver explosion If you do a page flip with no flags set then event is NULL. If event is NULL then the vmw_gfx driver likes to go digging into NULL and extracts NULL->base.file_priv. On a modern kernel with NULL mapping protection it's just another oops, without it there are some "intriguing" possibilities. What it should do is an open question but that for the driver owners to sort out. Signed-off-by: Alan Cox Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 6b0078ffa763..c50724bd30f6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,15 +1688,19 @@ int vmw_du_page_flip(struct drm_crtc *crtc, struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); - struct drm_file *file_priv = event->base.file_priv; + struct drm_file *file_priv ; struct vmw_fence_obj *fence = NULL; struct drm_clip_rect clips; int ret; + if (event == NULL) + return -EINVAL; + /* require ScreenObject support for page flipping */ if (!dev_priv->sou_priv) return -ENOSYS; + file_priv = event->base.file_priv; if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) return -EINVAL; -- GitLab From 04ccfe77f132b973659f11954443214659014072 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 17 Aug 2012 14:20:02 +0000 Subject: [PATCH 5681/5711] drm: Remove two unused fields from struct drm_display_mode Signed-off-by: Damien Lespiau Reviewed-by: Jani Nikula Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_modes.c | 3 --- include/drm/drm_crtc.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index b7adb4a967fd..28637c181b15 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -706,9 +706,6 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); - - p->crtc_hadjusted = false; - p->crtc_vadjusted = false; } EXPORT_SYMBOL(drm_mode_set_crtcinfo); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a1a0386e0160..ced362533e3c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -166,8 +166,6 @@ struct drm_display_mode { int crtc_vsync_start; int crtc_vsync_end; int crtc_vtotal; - int crtc_hadjusted; - int crtc_vadjusted; /* Driver private mode info */ int private_size; -- GitLab From d5c2c20e356ddcb597ee7099dc874bdac774884b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 17 Aug 2012 02:55:48 +0000 Subject: [PATCH 5682/5711] drm/udl: dpms off the crtc when disabled. This turns off the crtc when its been disabled, fixes it not turning off properly the whole time. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- drivers/gpu/drm/udl/udl_modeset.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index f5dd89e891de..9159d48d1dfd 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -354,8 +354,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, static void udl_crtc_disable(struct drm_crtc *crtc) { - - + udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void udl_crtc_destroy(struct drm_crtc *crtc) -- GitLab From 27fc4f1c0be917b1e5cef934783f9b09e28e92ea Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 1 Aug 2012 17:15:30 +0530 Subject: [PATCH 5683/5711] drm: Add missing static storage class specifiers in drm_proc.c file Fixes the following sparse warning: drivers/gpu/drm/drm_proc.c:92:5: warning: symbol 'drm_proc_create_files' was not declared. Should it be static? drivers/gpu/drm/drm_proc.c:175:5: warning: symbol 'drm_proc_remove_files' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index 371c695322d9..da457b18eaaf 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -89,7 +89,7 @@ static const struct file_operations drm_proc_fops = { * Create a given set of proc files represented by an array of * gdm_proc_lists in the given root directory. */ -int drm_proc_create_files(struct drm_info_list *files, int count, +static int drm_proc_create_files(struct drm_info_list *files, int count, struct proc_dir_entry *root, struct drm_minor *minor) { struct drm_device *dev = minor->dev; @@ -172,7 +172,7 @@ int drm_proc_init(struct drm_minor *minor, int minor_id, return 0; } -int drm_proc_remove_files(struct drm_info_list *files, int count, +static int drm_proc_remove_files(struct drm_info_list *files, int count, struct drm_minor *minor) { struct list_head *pos, *q; -- GitLab From 61e01be22e954f53a4bbac8066015d9f4ab9e42d Mon Sep 17 00:00:00 2001 From: Jens Rottmann Date: Tue, 21 Aug 2012 16:15:43 -0700 Subject: [PATCH 5684/5711] cs5535-clockevt: typo, it's MFGPT, not MFPGT Signed-off-by: Jens Rottmann Cc: Thomas Gleixner Cc: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clocksource/cs5535-clockevt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index 540795cd0760..d9279385304d 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -53,7 +53,7 @@ static struct cs5535_mfgpt_timer *cs5535_event_clock; #define MFGPT_PERIODIC (MFGPT_HZ / HZ) /* - * The MFPGT timers on the CS5536 provide us with suitable timers to use + * The MFGPT timers on the CS5536 provide us with suitable timers to use * as clock event sources - not as good as a HPET or APIC, but certainly * better than the PIT. This isn't a general purpose MFGPT driver, but * a simplified one designed specifically to act as a clock event source. @@ -144,7 +144,7 @@ static int __init cs5535_mfgpt_init(void) timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); if (!timer) { - printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n"); + printk(KERN_ERR DRV_NAME ": Could not allocate MFGPT timer\n"); return -ENODEV; } cs5535_event_clock = timer; -- GitLab From f9aed62a2b12a8e04077737c9942111e14ed738e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 21 Aug 2012 16:15:45 -0700 Subject: [PATCH 5685/5711] mm: change nr_ptes BUG_ON to WARN_ON Occasionally an isolated BUG_ON(mm->nr_ptes) gets reported, indicating that not all the page tables allocated could be found and freed when exit_mmap() tore down the user address space. There's usually nothing we can say about it, beyond that it's probably a sign of some bad memory or memory corruption; though it might still indicate a bug in vma or page table management (and did recently reveal a race in THP, fixed a few months ago). But one overdue change we can make is from BUG_ON to WARN_ON. It's fairly likely that the system will crash shortly afterwards in some other way (for example, the BUG_ON(page_mapped(page)) in __delete_from_page_cache(), once an inode mapped into the lost page tables gets evicted); but might tell us more before that. Change the BUG_ON(page_mapped) to WARN_ON too? Later perhaps: I'm less eager, since that one has several times led to fixes. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mmap.c b/mm/mmap.c index e3e86914f11a..9adee9fc0d8a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2309,7 +2309,7 @@ void exit_mmap(struct mm_struct *mm) } vm_unacct_memory(nr_accounted); - BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); + WARN_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); } /* Insert vm structure into process list sorted by address -- GitLab From d65226e2bfe9dd96f193d61892e20fcda9524d22 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 21 Aug 2012 16:15:46 -0700 Subject: [PATCH 5686/5711] Documentation: update mount option in filesystem/vfat.txt Update two mount options(discard, nfs) in vfat.txt. Signed-off-by: Namjae Jeon Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/vfat.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index ead764b2728f..de1e6c4dccff 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -137,6 +137,17 @@ errors=panic|continue|remount-ro without doing anything or remount the partition in read-only mode (default behavior). +discard -- If set, issues discard/TRIM commands to the block + device when blocks are freed. This is useful for SSD devices + and sparse/thinly-provisoned LUNs. + +nfs -- This option maintains an index (cache) of directory + inodes by i_logstart which is used by the nfs-related code to + improve look-ups. + + Enable this only if you want to export the FAT filesystem + over NFS + : 0,1,yes,no,true,false TODO -- GitLab From b0cf0b118c90477d1a6811f2cd2307f6a5578362 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Tue, 21 Aug 2012 16:15:49 -0700 Subject: [PATCH 5687/5711] cciss: fix incorrect scsi status reporting Delete code which sets SCSI status incorrectly as it's already been set correctly above this incorrect code. The bug was introduced in 2009 by commit b0e15f6db111 ("cciss: fix typo that causes scsi status to be lost.") Signed-off-by: Stephen M. Cameron Reported-by: Roel van Meer Tested-by: Roel van Meer Cc: Jens Axboe Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss_scsi.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index acda773b3720..38aa6dda6b81 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, { case CMD_TARGET_STATUS: /* Pass it up to the upper layers... */ - if( ei->ScsiStatus) - { -#if 0 - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - c, ei->ScsiStatus); -#endif - cmd->result |= (ei->ScsiStatus << 1); - } - else { /* scsi status is zero??? How??? */ + if (!ei->ScsiStatus) { /* Ordinarily, this case should never happen, but there is a bug in some released firmware revisions that allows it to happen -- GitLab From eb48c071464757414538c68a6033c8f8c15196f8 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 21 Aug 2012 16:15:52 -0700 Subject: [PATCH 5688/5711] mm: hugetlbfs: correctly populate shared pmd Each page mapped in a process's address space must be correctly accounted for in _mapcount. Normally the rules for this are straightforward but hugetlbfs page table sharing is different. The page table pages at the PMD level are reference counted while the mapcount remains the same. If this accounting is wrong, it causes bugs like this one reported by Larry Woodman: kernel BUG at mm/filemap.c:135! invalid opcode: 0000 [#1] SMP CPU 22 Modules linked in: bridge stp llc sunrpc binfmt_misc dcdbas microcode pcspkr acpi_pad acpi] Pid: 18001, comm: mpitest Tainted: G W 3.3.0+ #4 Dell Inc. PowerEdge R620/07NDJ2 RIP: 0010:[] [] __delete_from_page_cache+0x15d/0x170 Process mpitest (pid: 18001, threadinfo ffff880428972000, task ffff880428b5cc20) Call Trace: delete_from_page_cache+0x40/0x80 truncate_hugepages+0x115/0x1f0 hugetlbfs_evict_inode+0x18/0x30 evict+0x9f/0x1b0 iput_final+0xe3/0x1e0 iput+0x3e/0x50 d_kill+0xf8/0x110 dput+0xe2/0x1b0 __fput+0x162/0x240 During fork(), copy_hugetlb_page_range() detects if huge_pte_alloc() shared page tables with the check dst_pte == src_pte. The logic is if the PMD page is the same, they must be shared. This assumes that the sharing is between the parent and child. However, if the sharing is with a different process entirely then this check fails as in this diagram: parent | ------------>pmd src_pte----------> data page ^ other--------->pmd--------------------| ^ child-----------| dst_pte For this situation to occur, it must be possible for Parent and Other to have faulted and failed to share page tables with each other. This is possible due to the following style of race. PROC A PROC B copy_hugetlb_page_range copy_hugetlb_page_range src_pte == huge_pte_offset src_pte == huge_pte_offset !src_pte so no sharing !src_pte so no sharing (time passes) hugetlb_fault hugetlb_fault huge_pte_alloc huge_pte_alloc huge_pmd_share huge_pmd_share LOCK(i_mmap_mutex) find nothing, no sharing UNLOCK(i_mmap_mutex) LOCK(i_mmap_mutex) find nothing, no sharing UNLOCK(i_mmap_mutex) pmd_alloc pmd_alloc LOCK(instantiation_mutex) fault UNLOCK(instantiation_mutex) LOCK(instantiation_mutex) fault UNLOCK(instantiation_mutex) These two processes are not poing to the same data page but are not sharing page tables because the opportunity was missed. When either process later forks, the src_pte == dst pte is potentially insufficient. As the check falls through, the wrong PTE information is copied in (harmless but wrong) and the mapcount is bumped for a page mapped by a shared page table leading to the BUG_ON. This patch addresses the issue by moving pmd_alloc into huge_pmd_share which guarantees that the shared pud is populated in the same critical section as pmd. This also means that huge_pte_offset test in huge_pmd_share is serialized correctly now which in turn means that the success of the sharing will be higher as the racing tasks see the pud and pmd populated together. Race identified and changelog written mostly by Mel Gorman. {akpm@linux-foundation.org: attempt to make the huge_pmd_share() comment comprehensible, clean up coding style] Reported-by: Larry Woodman Tested-by: Larry Woodman Reviewed-by: Mel Gorman Signed-off-by: Michal Hocko Reviewed-by: Rik van Riel Cc: David Gibson Cc: Ken Chen Cc: Cong Wang Cc: Hillf Danton Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/mm/hugetlbpage.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index f6679a7fb8ca..b91e48512425 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr) } /* - * search for a shareable pmd page for hugetlb. + * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() + * and returns the corresponding pte. While this is not necessary for the + * !shared pmd case because we can allocate the pmd later as well, it makes the + * code much cleaner. pmd allocation is essential for the shared case because + * pud has to be populated inside the same i_mmap_mutex section - otherwise + * racing tasks could either miss the sharing (see huge_pte_offset) or select a + * bad pmd for sharing. */ -static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +static pte_t * +huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) { struct vm_area_struct *vma = find_vma(mm, addr); struct address_space *mapping = vma->vm_file->f_mapping; @@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) struct vm_area_struct *svma; unsigned long saddr; pte_t *spte = NULL; + pte_t *pte; if (!vma_shareable(vma, addr)) - return; + return (pte_t *)pmd_alloc(mm, pud, addr); mutex_lock(&mapping->i_mmap_mutex); vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { @@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) put_page(virt_to_page(spte)); spin_unlock(&mm->page_table_lock); out: + pte = (pte_t *)pmd_alloc(mm, pud, addr); mutex_unlock(&mapping->i_mmap_mutex); + return pte; } /* @@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, } else { BUG_ON(sz != PMD_SIZE); if (pud_none(*pud)) - huge_pmd_share(mm, addr, pud); - pte = (pte_t *) pmd_alloc(mm, pud, addr); + pte = huge_pmd_share(mm, addr, pud); + else + pte = (pte_t *)pmd_alloc(mm, pud, addr); } } BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); -- GitLab From ac8e97f8a742828daa1d9de37f6e635888f8d71e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 21 Aug 2012 16:15:53 -0700 Subject: [PATCH 5689/5711] checkpatch: add control statement test to SINGLE_STATEMENT_DO_WHILE_MACRO Commit b13edf7ff2dd ("checkpatch: add checks for do {} while (0) macro misuses") added a test that is overly simplistic for single statement macros. Macros that start with control tests should be enclosed in a do {} while (0) loop. Add the necessary control tests to the check. Signed-off-by: Joe Perches Acked-by: Andy Whitcroft Tested-by: Franz Schrober Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 913d6bdfdda3..ca05ba217f5f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3016,7 +3016,8 @@ sub process { $herectx .= raw_line($linenr, $n) . "\n"; } - if (($stmts =~ tr/;/;/) == 1) { + if (($stmts =~ tr/;/;/) == 1 && + $stmts !~ /^\s*(if|while|for|switch)\b/) { WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); } -- GitLab From d46f3d86fdc9248b4a8497a7da229812a15ba670 Mon Sep 17 00:00:00 2001 From: Zhouping Liu Date: Tue, 21 Aug 2012 16:15:57 -0700 Subject: [PATCH 5690/5711] hugetlb: update hugetlbpage.txt Commit f0f57b2b1488 ("mm: move hugepage test examples to tools/testing/selftests/vm") moved map_hugetlb.c, hugepage-shm.c and hugepage-mmap.c tests into tools/testing/selftests/vm/ directory, but it didn't update hugetlbpage.txt Signed-off-by: Zhouping Liu Acked-by: Dave Young Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/hugetlbpage.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index f8551b3879f8..4ac359b7aa17 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -299,11 +299,17 @@ map_hugetlb.c. ******************************************************************* /* - * hugepage-shm: see Documentation/vm/hugepage-shm.c + * map_hugetlb: see tools/testing/selftests/vm/map_hugetlb.c */ ******************************************************************* /* - * hugepage-mmap: see Documentation/vm/hugepage-mmap.c + * hugepage-shm: see tools/testing/selftests/vm/hugepage-shm.c + */ + +******************************************************************* + +/* + * hugepage-mmap: see tools/testing/selftests/vm/hugepage-mmap.c */ -- GitLab From c3a5ce0416b6c172a23bc8a3760d8704d3d1535b Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 21 Aug 2012 16:16:00 -0700 Subject: [PATCH 5691/5711] string: do not export memweight() to userspace Fix the following warning: usr/include/linux/string.h:8: userspace cannot reference function or variable defined in the kernel Signed-off-by: WANG Cong Acked-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/string.h b/include/linux/string.h index ffe0442e18d2..b9178812d9df 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -144,8 +144,8 @@ static inline bool strstarts(const char *str, const char *prefix) { return strncmp(str, prefix, strlen(prefix)) == 0; } -#endif extern size_t memweight(const void *ptr, size_t bytes); +#endif /* __KERNEL__ */ #endif /* _LINUX_STRING_H_ */ -- GitLab From 7838f994b4fceff24c343f4e26a6cf4393869579 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 21 Aug 2012 16:16:02 -0700 Subject: [PATCH 5692/5711] drivers/misc/sgi-xp/xpc_uv.c: SGI XPC fails to load when cpu 0 is out of IRQ resources On many of our larger systems, CPU 0 has had all of its IRQ resources consumed before XPC loads. Worst cases on machines with multiple 10 GigE cards and multiple IB cards have depleted the entire first socket of IRQs. This patch makes selecting the node upon which IRQs are allocated (as well as all the other GRU Message Queue structures) specifiable as a module load param and has a default behavior of searching all nodes/cpus for an available resources. [akpm@linux-foundation.org: fix build: include cpu.h and module.h] Signed-off-by: Robin Holt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xpc_uv.c | 84 ++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 87b251ab6ec5..b9e2000969f0 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; XPC_NOTIFY_MSG_SIZE_UV) #define XPC_NOTIFY_IRQ_NAME "xpc_notify" +static int xpc_mq_node = -1; + static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) #if defined CONFIG_X86_64 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, UV_AFFINITY_CPU); - if (mq->irq < 0) { - dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", - -mq->irq); + if (mq->irq < 0) return mq->irq; - } mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, - pg_order); + page = alloc_pages_exact_node(nid, + GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = { .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, }; +static int +xpc_init_mq_node(int nid) +{ + int cpu; + + get_online_cpus(); + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_activate_mq_uv = + xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, + XPC_ACTIVATE_IRQ_NAME, + xpc_handle_activate_IRQ_uv); + if (!IS_ERR(xpc_activate_mq_uv)) + break; + } + if (IS_ERR(xpc_activate_mq_uv)) { + put_online_cpus(); + return PTR_ERR(xpc_activate_mq_uv); + } + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_notify_mq_uv = + xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, + XPC_NOTIFY_IRQ_NAME, + xpc_handle_notify_IRQ_uv); + if (!IS_ERR(xpc_notify_mq_uv)) + break; + } + if (IS_ERR(xpc_notify_mq_uv)) { + xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); + put_online_cpus(); + return PTR_ERR(xpc_notify_mq_uv); + } + + put_online_cpus(); + return 0; +} + int xpc_init_uv(void) { + int nid; + int ret = 0; + xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void) return -E2BIG; } - xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, - XPC_ACTIVATE_IRQ_NAME, - xpc_handle_activate_IRQ_uv); - if (IS_ERR(xpc_activate_mq_uv)) - return PTR_ERR(xpc_activate_mq_uv); + if (xpc_mq_node < 0) + for_each_online_node(nid) { + ret = xpc_init_mq_node(nid); - xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, - XPC_NOTIFY_IRQ_NAME, - xpc_handle_notify_IRQ_uv); - if (IS_ERR(xpc_notify_mq_uv)) { - xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); - return PTR_ERR(xpc_notify_mq_uv); - } + if (!ret) + break; + } + else + ret = xpc_init_mq_node(xpc_mq_node); - return 0; + if (ret < 0) + dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", + -ret); + + return ret; } void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void) xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); -- GitLab From c81758fbe0fdbbc0c74b37798f55bd9c91d5c068 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 21 Aug 2012 16:16:03 -0700 Subject: [PATCH 5693/5711] mm/compaction.c: fix deferring compaction mistake Commit aff622495c9a ("vmscan: only defer compaction for failed order and higher") fixed bad deferring policy but made mistake about checking compact_order_failed in __compact_pgdat(). So it can't update compact_order_failed with the new order. This ends up preventing correct operation of policy deferral. This patch fixes it. Signed-off-by: Minchan Kim Reviewed-by: Rik van Riel Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/compaction.c b/mm/compaction.c index e78cb9688421..b6984e234fdf 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -861,7 +861,7 @@ static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc) if (cc->order > 0) { int ok = zone_watermark_ok(zone, cc->order, low_wmark_pages(zone), 0, 0); - if (ok && cc->order > zone->compact_order_failed) + if (ok && cc->order >= zone->compact_order_failed) zone->compact_order_failed = cc->order + 1; /* Currently async compaction is never deferred. */ else if (!ok && cc->sync) -- GitLab From 5ed12f12825c6c0451d703bfe918a7fc190e2738 Mon Sep 17 00:00:00 2001 From: Ilya Shchepetkov Date: Tue, 21 Aug 2012 16:16:06 -0700 Subject: [PATCH 5694/5711] drivers/rtc/rtc-pcf2123.c: initialize dynamic sysfs attributes Dynamically allocated sysfs attributes must be initialized using sysfs_attr_init(), otherwise lockdep complains: BUG: key
not in .data! Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Ilya Shchepetkov Cc: Chris Verges Cc: Christian Pellegrin Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf2123.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 836118795c0b..13e4df63974f 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -43,6 +43,7 @@ #include #include #include +#include #define DRV_VERSION "0.6" @@ -292,6 +293,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; for (i = 0; i < 16; i++) { + sysfs_attr_init(&pdata->regs[i].attr.attr); sprintf(pdata->regs[i].name, "%1x", i); pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; pdata->regs[i].attr.attr.name = pdata->regs[i].name; -- GitLab From b121186ab1b12e2a96a945d88eae0735b4542158 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Tue, 21 Aug 2012 16:16:08 -0700 Subject: [PATCH 5695/5711] mm: correct page->pfmemalloc to fix deactivate_slab regression Commit cfd19c5a9ecf ("mm: only set page->pfmemalloc when ALLOC_NO_WATERMARKS was used") tried to narrow down page->pfmemalloc setting, but it missed some places the pfmemalloc should be set. So, in __slab_alloc, the unalignment pfmemalloc and ALLOC_NO_WATERMARKS cause incorrect deactivate_slab() on our core2 server: 64.73% fio [kernel.kallsyms] [k] _raw_spin_lock | --- _raw_spin_lock | |---0.34%-- deactivate_slab | __slab_alloc | kmem_cache_alloc | | That causes our fio sync write performance to have a 40% regression. Move the checking in get_page_from_freelist() which resolves this issue. Signed-off-by: Alex Shi Acked-by: Mel Gorman Cc: David Miller Tested-by: Eric Dumazet Tested-by: Sage Weil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 009ac285fea7..07f19248acb5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1928,6 +1928,17 @@ this_zone_full: zlc_active = 0; goto zonelist_scan; } + + if (page) + /* + * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was + * necessary to allocate the page. The expectation is + * that the caller is taking steps that will free more + * memory. The caller should avoid the page being used + * for !PFMEMALLOC purposes. + */ + page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); + return page; } @@ -2389,14 +2400,6 @@ rebalance: zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); if (page) { - /* - * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was - * necessary to allocate the page. The expectation is - * that the caller is taking steps that will free more - * memory. The caller should avoid the page being used - * for !PFMEMALLOC purposes. - */ - page->pfmemalloc = true; goto got_pg; } } @@ -2569,8 +2572,6 @@ retry_cpuset: page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); - else - page->pfmemalloc = false; trace_mm_page_alloc(page, order, gfp_mask, migratetype); -- GitLab From 7dbfb315b2aaef0a115765946bf3026d074c33a7 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 21 Aug 2012 16:16:10 -0700 Subject: [PATCH 5696/5711] drivers/rtc/rtc-rs5c348.c: fix hour decoding in 12-hour mode Correct the offset by subtracting 20 from tm_hour before taking the modulo 12. [ "Why 20?" I hear you ask. Or at least I did. Here's the reason why: RS5C348_BIT_PM is 32, and is - stupidly - included in the RS5C348_HOURS_MASK define. So it's really subtracting out that bit to get "hour+12". But then because it does things modulo 12, it needs to add the 12 in again afterwards anyway. This code is confused. It would be much clearer if RS5C348_HOURS_MASK just didn't include the RS5C348_BIT_PM bit at all, then it wouldn't need to do the silly subtract either. Whatever. It's all just math, the end result is the same. - Linus ] Reported-by: James Nute Tested-by: James Nute Signed-off-by: Atsushi Nemoto Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-rs5c348.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 77074ccd2850..fd5c7af04ae5 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); if (!pdata->rtc_24h) { - tm->tm_hour %= 12; - if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { + tm->tm_hour -= 20; + tm->tm_hour %= 12; tm->tm_hour += 12; + } else + tm->tm_hour %= 12; } tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); -- GitLab From 3670e7e12e582c6d67761275d148171feb7a9004 Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Tue, 21 Aug 2012 16:16:11 -0700 Subject: [PATCH 5697/5711] rapidio/tsi721: fix inbound doorbell interrupt handling Make sure that there is no doorbell messages left behind due to disabled interrupts during inbound doorbell processing. The most common case for this bug is loss of rionet JOIN messages in systems with three or more rionet participants and MSI or MSI-X enabled. As result, requests for packet transfers may finish with "destination unreachable" error message. This patch is applicable to kernel versions starting from v3.2. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/devices/tsi721.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 722246cf20ab..c0d6a049cbd6 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -435,6 +435,9 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } + + wr_ptr = ioread32(priv->regs + + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -445,6 +448,10 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + if (wr_ptr != rd_ptr) + schedule_work(&priv->idb_work); } /** -- GitLab From 9a9a9a7adafe62a34de8b4fb48936c1c5f9bafa5 Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Tue, 21 Aug 2012 16:16:12 -0700 Subject: [PATCH 5698/5711] rapidio/tsi721: fix unused variable compiler warning Fix unused variable compiler warning when built with CONFIG_RAPIDIO_DEBUG option off. This patch is applicable to kernel versions starting from v3.2 Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/devices/tsi721.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index c0d6a049cbd6..5d44252b7342 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2219,7 +2219,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i, cap; + int cap; int err; u32 regval; @@ -2239,12 +2239,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG + { + int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } + } #endif /* * Verify BAR configuration -- GitLab From de74f1cc3b1e9730d9b58580cd11361d30cd182d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 21 Aug 2012 16:16:15 -0700 Subject: [PATCH 5699/5711] mm: have order > 0 compaction start near a pageblock with free pages Commit 7db8889ab05b ("mm: have order > 0 compaction start off where it left") introduced a caching mechanism to reduce the amount work the free page scanner does in compaction. However, it has a problem. Consider two process simultaneously scanning free pages C Process A M S F |---------------------------------------| Process B M FS C is zone->compact_cached_free_pfn S is cc->start_pfree_pfn M is cc->migrate_pfn F is cc->free_pfn In this diagram, Process A has just reached its migrate scanner, wrapped around and updated compact_cached_free_pfn accordingly. Simultaneously, Process B finishes isolating in a block and updates compact_cached_free_pfn again to the location of its free scanner. Process A moves to "end_of_zone - one_pageblock" and runs this check if (cc->order > 0 && (!cc->wrapped || zone->compact_cached_free_pfn > cc->start_free_pfn)) pfn = min(pfn, zone->compact_cached_free_pfn); compact_cached_free_pfn is above where it started so the free scanner skips almost the entire space it should have scanned. When there are multiple processes compacting it can end in a situation where the entire zone is not being scanned at all. Further, it is possible for two processes to ping-pong update to compact_cached_free_pfn which is just random. Overall, the end result wrecks allocation success rates. There is not an obvious way around this problem without introducing new locking and state so this patch takes a different approach. First, it gets rid of the skip logic because it's not clear that it matters if two free scanners happen to be in the same block but with racing updates it's too easy for it to skip over blocks it should not. Second, it updates compact_cached_free_pfn in a more limited set of circumstances. If a scanner has wrapped, it updates compact_cached_free_pfn to the end of the zone. When a wrapped scanner isolates a page, it updates compact_cached_free_pfn to point to the highest pageblock it can isolate pages from. If a scanner has not wrapped when it has finished isolated pages it checks if compact_cached_free_pfn is pointing to the end of the zone. If so, the value is updated to point to the highest pageblock that pages were isolated from. This value will not be updated again until a free page scanner wraps and resets compact_cached_free_pfn. This is not optimal and it can still race but the compact_cached_free_pfn will be pointing to or very near a pageblock with free pages. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Reviewed-by: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 54 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index b6984e234fdf..bcce7897e17a 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -383,6 +383,20 @@ static bool suitable_migration_target(struct page *page) return false; } +/* + * Returns the start pfn of the last page block in a zone. This is the starting + * point for full compaction of a zone. Compaction searches for free pages from + * the end of each zone, while isolate_freepages_block scans forward inside each + * page block. + */ +static unsigned long start_free_pfn(struct zone *zone) +{ + unsigned long free_pfn; + free_pfn = zone->zone_start_pfn + zone->spanned_pages; + free_pfn &= ~(pageblock_nr_pages-1); + return free_pfn; +} + /* * Based on information in the current compact_control, find blocks * suitable for isolating free pages from and then isolate them. @@ -422,17 +436,6 @@ static void isolate_freepages(struct zone *zone, pfn -= pageblock_nr_pages) { unsigned long isolated; - /* - * Skip ahead if another thread is compacting in the area - * simultaneously. If we wrapped around, we can only skip - * ahead if zone->compact_cached_free_pfn also wrapped to - * above our starting point. - */ - if (cc->order > 0 && (!cc->wrapped || - zone->compact_cached_free_pfn > - cc->start_free_pfn)) - pfn = min(pfn, zone->compact_cached_free_pfn); - if (!pfn_valid(pfn)) continue; @@ -474,7 +477,15 @@ static void isolate_freepages(struct zone *zone, */ if (isolated) { high_pfn = max(high_pfn, pfn); - if (cc->order > 0) + + /* + * If the free scanner has wrapped, update + * compact_cached_free_pfn to point to the highest + * pageblock with free pages. This reduces excessive + * scanning of full pageblocks near the end of the + * zone + */ + if (cc->order > 0 && cc->wrapped) zone->compact_cached_free_pfn = high_pfn; } } @@ -484,6 +495,11 @@ static void isolate_freepages(struct zone *zone, cc->free_pfn = high_pfn; cc->nr_freepages = nr_freepages; + + /* If compact_cached_free_pfn is reset then set it now */ + if (cc->order > 0 && !cc->wrapped && + zone->compact_cached_free_pfn == start_free_pfn(zone)) + zone->compact_cached_free_pfn = high_pfn; } /* @@ -570,20 +586,6 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, return ISOLATE_SUCCESS; } -/* - * Returns the start pfn of the last page block in a zone. This is the starting - * point for full compaction of a zone. Compaction searches for free pages from - * the end of each zone, while isolate_freepages_block scans forward inside each - * page block. - */ -static unsigned long start_free_pfn(struct zone *zone) -{ - unsigned long free_pfn; - free_pfn = zone->zone_start_pfn + zone->spanned_pages; - free_pfn &= ~(pageblock_nr_pages-1); - return free_pfn; -} - static int compact_finished(struct zone *zone, struct compact_control *cc) { -- GitLab From c67fe3752abe6ab47639e2f9b836900c3dc3da84 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 21 Aug 2012 16:16:17 -0700 Subject: [PATCH 5700/5711] mm: compaction: Abort async compaction if locks are contended or taking too long Jim Schutt reported a problem that pointed at compaction contending heavily on locks. The workload is straight-forward and in his own words; The systems in question have 24 SAS drives spread across 3 HBAs, running 24 Ceph OSD instances, one per drive. FWIW these servers are dual-socket Intel 5675 Xeons w/48 GB memory. I've got ~160 Ceph Linux clients doing dd simultaneously to a Ceph file system backed by 12 of these servers. Early in the test everything looks fine procs -------------------memory------------------ ---swap-- -----io---- --system-- -----cpu------- r b swpd free buff cache si so bi bo in cs us sy id wa st 31 15 0 287216 576 38606628 0 0 2 1158 2 14 1 3 95 0 0 27 15 0 225288 576 38583384 0 0 18 2222016 203357 134876 11 56 17 15 0 28 17 0 219256 576 38544736 0 0 11 2305932 203141 146296 11 49 23 17 0 6 18 0 215596 576 38552872 0 0 7 2363207 215264 166502 12 45 22 20 0 22 18 0 226984 576 38596404 0 0 3 2445741 223114 179527 12 43 23 22 0 and then it goes to pot procs -------------------memory------------------ ---swap-- -----io---- --system-- -----cpu------- r b swpd free buff cache si so bi bo in cs us sy id wa st 163 8 0 464308 576 36791368 0 0 11 22210 866 536 3 13 79 4 0 207 14 0 917752 576 36181928 0 0 712 1345376 134598 47367 7 90 1 2 0 123 12 0 685516 576 36296148 0 0 429 1386615 158494 60077 8 84 5 3 0 123 12 0 598572 576 36333728 0 0 1107 1233281 147542 62351 7 84 5 4 0 622 7 0 660768 576 36118264 0 0 557 1345548 151394 59353 7 85 4 3 0 223 11 0 283960 576 36463868 0 0 46 1107160 121846 33006 6 93 1 1 0 Note that system CPU usage is very high blocks being written out has dropped by 42%. He analysed this with perf and found perf record -g -a sleep 10 perf report --sort symbol --call-graph fractal,5 34.63% [k] _raw_spin_lock_irqsave | |--97.30%-- isolate_freepages | compaction_alloc | unmap_and_move | migrate_pages | compact_zone | compact_zone_order | try_to_compact_pages | __alloc_pages_direct_compact | __alloc_pages_slowpath | __alloc_pages_nodemask | alloc_pages_vma | do_huge_pmd_anonymous_page | handle_mm_fault | do_page_fault | page_fault | | | |--87.39%-- skb_copy_datagram_iovec | | tcp_recvmsg | | inet_recvmsg | | sock_recvmsg | | sys_recvfrom | | system_call | | __recv | | | | | --100.00%-- (nil) | | | --12.61%-- memcpy --2.70%-- [...] There was other data but primarily it is all showing that compaction is contended heavily on the zone->lock and zone->lru_lock. commit [b2eef8c0: mm: compaction: minimise the time IRQs are disabled while isolating pages for migration] noted that it was possible for migration to hold the lru_lock for an excessive amount of time. Very broadly speaking this patch expands the concept. This patch introduces compact_checklock_irqsave() to check if a lock is contended or the process needs to be scheduled. If either condition is true then async compaction is aborted and the caller is informed. The page allocator will fail a THP allocation if compaction failed due to contention. This patch also introduces compact_trylock_irqsave() which will acquire the lock only if it is not contended and the process does not need to schedule. Reported-by: Jim Schutt Tested-by: Jim Schutt Signed-off-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compaction.h | 4 +- mm/compaction.c | 100 +++++++++++++++++++++++++++++-------- mm/internal.h | 1 + mm/page_alloc.c | 17 ++++--- 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 133ddcf83397..ef658147e4e8 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, extern int fragmentation_index(struct zone *zone, unsigned int order); extern unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *mask, - bool sync); + bool sync, bool *contended); extern int compact_pgdat(pg_data_t *pgdat, int order); extern unsigned long compaction_suitable(struct zone *zone, int order); @@ -64,7 +64,7 @@ static inline bool compaction_deferred(struct zone *zone, int order) #else static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync) + bool sync, bool *contended) { return COMPACT_CONTINUE; } diff --git a/mm/compaction.c b/mm/compaction.c index bcce7897e17a..7fcd3a52e68d 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -50,6 +50,47 @@ static inline bool migrate_async_suitable(int migratetype) return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE; } +/* + * Compaction requires the taking of some coarse locks that are potentially + * very heavily contended. Check if the process needs to be scheduled or + * if the lock is contended. For async compaction, back out in the event + * if contention is severe. For sync compaction, schedule. + * + * Returns true if the lock is held. + * Returns false if the lock is released and compaction should abort + */ +static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, + bool locked, struct compact_control *cc) +{ + if (need_resched() || spin_is_contended(lock)) { + if (locked) { + spin_unlock_irqrestore(lock, *flags); + locked = false; + } + + /* async aborts if taking too long or contended */ + if (!cc->sync) { + if (cc->contended) + *cc->contended = true; + return false; + } + + cond_resched(); + if (fatal_signal_pending(current)) + return false; + } + + if (!locked) + spin_lock_irqsave(lock, *flags); + return true; +} + +static inline bool compact_trylock_irqsave(spinlock_t *lock, + unsigned long *flags, struct compact_control *cc) +{ + return compact_checklock_irqsave(lock, flags, false, cc); +} + /* * Isolate free pages onto a private freelist. Caller must hold zone->lock. * If @strict is true, will abort returning 0 on any invalid PFNs or non-free @@ -173,7 +214,7 @@ isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn) } /* Update the number of anon and file isolated pages in the zone */ -static void acct_isolated(struct zone *zone, struct compact_control *cc) +static void acct_isolated(struct zone *zone, bool locked, struct compact_control *cc) { struct page *page; unsigned int count[2] = { 0, }; @@ -181,8 +222,14 @@ static void acct_isolated(struct zone *zone, struct compact_control *cc) list_for_each_entry(page, &cc->migratepages, lru) count[!!page_is_file_cache(page)]++; - __mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); - __mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); + /* If locked we can use the interrupt unsafe versions */ + if (locked) { + __mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); + __mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); + } else { + mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); + mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); + } } /* Similar to reclaim, but different enough that they don't share logic */ @@ -228,6 +275,8 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, struct list_head *migratelist = &cc->migratepages; isolate_mode_t mode = 0; struct lruvec *lruvec; + unsigned long flags; + bool locked; /* * Ensure that there are not too many pages isolated from the LRU @@ -247,25 +296,22 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, /* Time to isolate some pages for migration */ cond_resched(); - spin_lock_irq(&zone->lru_lock); + spin_lock_irqsave(&zone->lru_lock, flags); + locked = true; for (; low_pfn < end_pfn; low_pfn++) { struct page *page; - bool locked = true; /* give a chance to irqs before checking need_resched() */ if (!((low_pfn+1) % SWAP_CLUSTER_MAX)) { - spin_unlock_irq(&zone->lru_lock); + spin_unlock_irqrestore(&zone->lru_lock, flags); locked = false; } - if (need_resched() || spin_is_contended(&zone->lru_lock)) { - if (locked) - spin_unlock_irq(&zone->lru_lock); - cond_resched(); - spin_lock_irq(&zone->lru_lock); - if (fatal_signal_pending(current)) - break; - } else if (!locked) - spin_lock_irq(&zone->lru_lock); + + /* Check if it is ok to still hold the lock */ + locked = compact_checklock_irqsave(&zone->lru_lock, &flags, + locked, cc); + if (!locked) + break; /* * migrate_pfn does not necessarily start aligned to a @@ -349,9 +395,10 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, } } - acct_isolated(zone, cc); + acct_isolated(zone, locked, cc); - spin_unlock_irq(&zone->lru_lock); + if (locked) + spin_unlock_irqrestore(&zone->lru_lock, flags); trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); @@ -461,7 +508,16 @@ static void isolate_freepages(struct zone *zone, * are disabled */ isolated = 0; - spin_lock_irqsave(&zone->lock, flags); + + /* + * The zone lock must be held to isolate freepages. This + * unfortunately this is a very coarse lock and can be + * heavily contended if there are parallel allocations + * or parallel compactions. For async compaction do not + * spin on the lock + */ + if (!compact_trylock_irqsave(&zone->lock, &flags, cc)) + break; if (suitable_migration_target(page)) { end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn); isolated = isolate_freepages_block(pfn, end_pfn, @@ -773,7 +829,7 @@ out: static unsigned long compact_zone_order(struct zone *zone, int order, gfp_t gfp_mask, - bool sync) + bool sync, bool *contended) { struct compact_control cc = { .nr_freepages = 0, @@ -782,6 +838,7 @@ static unsigned long compact_zone_order(struct zone *zone, .migratetype = allocflags_to_migratetype(gfp_mask), .zone = zone, .sync = sync, + .contended = contended, }; INIT_LIST_HEAD(&cc.freepages); INIT_LIST_HEAD(&cc.migratepages); @@ -803,7 +860,7 @@ int sysctl_extfrag_threshold = 500; */ unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync) + bool sync, bool *contended) { enum zone_type high_zoneidx = gfp_zone(gfp_mask); int may_enter_fs = gfp_mask & __GFP_FS; @@ -827,7 +884,8 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, nodemask) { int status; - status = compact_zone_order(zone, order, gfp_mask, sync); + status = compact_zone_order(zone, order, gfp_mask, sync, + contended); rc = max(status, rc); /* If a normal allocation would succeed, stop compacting */ diff --git a/mm/internal.h b/mm/internal.h index 3314f79d775a..b8c91b342e24 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -130,6 +130,7 @@ struct compact_control { int order; /* order a direct compactor needs */ int migratetype; /* MOVABLE, RECLAIMABLE etc */ struct zone *zone; + bool *contended; /* True if a lock was contended */ }; unsigned long diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 07f19248acb5..c66fb875104a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2102,7 +2102,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, int migratetype, bool sync_migration, - bool *deferred_compaction, + bool *contended_compaction, bool *deferred_compaction, unsigned long *did_some_progress) { struct page *page; @@ -2117,7 +2117,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, current->flags |= PF_MEMALLOC; *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, - nodemask, sync_migration); + nodemask, sync_migration, + contended_compaction); current->flags &= ~PF_MEMALLOC; if (*did_some_progress != COMPACT_SKIPPED) { @@ -2163,7 +2164,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, int migratetype, bool sync_migration, - bool *deferred_compaction, + bool *contended_compaction, bool *deferred_compaction, unsigned long *did_some_progress) { return NULL; @@ -2336,6 +2337,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, unsigned long did_some_progress; bool sync_migration = false; bool deferred_compaction = false; + bool contended_compaction = false; /* * In the slowpath, we sanity check order to avoid ever trying to @@ -2425,6 +2427,7 @@ rebalance: nodemask, alloc_flags, preferred_zone, migratetype, sync_migration, + &contended_compaction, &deferred_compaction, &did_some_progress); if (page) @@ -2434,10 +2437,11 @@ rebalance: /* * If compaction is deferred for high-order allocations, it is because * sync compaction recently failed. In this is the case and the caller - * has requested the system not be heavily disrupted, fail the - * allocation now instead of entering direct reclaim + * requested a movable allocation that does not heavily disrupt the + * system then fail the allocation instead of entering direct reclaim. */ - if (deferred_compaction && (gfp_mask & __GFP_NO_KSWAPD)) + if ((deferred_compaction || contended_compaction) && + (gfp_mask & __GFP_NO_KSWAPD)) goto nopage; /* Try direct reclaim and then allocating */ @@ -2508,6 +2512,7 @@ rebalance: nodemask, alloc_flags, preferred_zone, migratetype, sync_migration, + &contended_compaction, &deferred_compaction, &did_some_progress); if (page) -- GitLab From d8636a2717bb3da2a7ce2154bf08de90bb8c87b0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 21 Aug 2012 16:29:47 +1000 Subject: [PATCH 5701/5711] fbcon: fix race condition between console lock and cursor timer (v1.1) So we've had a fair few reports of fbcon handover breakage between efi/vesafb and i915 surface recently, so I dedicated a couple of days to finding the problem. Essentially the last thing we saw was the conflicting framebuffer message and that was all. So after much tracing with direct netconsole writes (printks under console_lock not so useful), I think I found the race. Thread A (driver load) Thread B (timer thread) unbind_con_driver -> | bind_con_driver -> | vc->vc_sw->con_deinit -> | fbcon_deinit -> | console_lock() | | | | fbcon_flashcursor timer fires | console_lock() <- blocked for A | | fbcon_del_cursor_timer -> del_timer_sync (BOOM) Of course because all of this is under the console lock, we never see anything, also since we also just unbound the active console guess what we never see anything. Hopefully this fixes the problem for anyone seeing vesafb->kms driver handoff. v1.1: add comment suggestion from Alan. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/video/console/fbcon.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e471c22abf5..88e92041d8f0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -372,8 +372,15 @@ static void fb_flashcursor(struct work_struct *work) struct vc_data *vc = NULL; int c; int mode; + int ret; + + /* FIXME: we should sort out the unbind locking instead */ + /* instead we just fail to flash the cursor if we can't get + * the lock instead of blocking fbcon deinit */ + ret = console_trylock(); + if (ret == 0) + return; - console_lock(); if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; -- GitLab From 934ad4c235f87dcb9206abdfa22922358999afab Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 19:49:09 -0400 Subject: [PATCH 5702/5711] vfio: don't dereference after kfree... Acked-by: Alex Williamson Signed-off-by: Al Viro --- drivers/vfio/vfio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 9591e2b509d7..0b025d58de81 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -416,8 +416,9 @@ static void vfio_device_release(struct kref *kref) /* Device reference always implies a group reference */ static void vfio_device_put(struct vfio_device *device) { + struct vfio_group *group = device->group; kref_put(&device->kref, vfio_device_release); - vfio_group_put(device->group); + vfio_group_put(group); } static void vfio_device_get(struct vfio_device *device) -- GitLab From 8ad5db8a8ddbe3bd33078863a027011e28f1f4ee Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 20:10:46 -0400 Subject: [PATCH 5703/5711] introduce kref_put_mutex() equivalent of mutex_lock(mutex); if (!kref_put(kref, release)) mutex_unlock(mutex); Signed-off-by: Al Viro --- include/linux/kref.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/linux/kref.h b/include/linux/kref.h index 9c07dcebded7..65af6887872f 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -18,6 +18,7 @@ #include #include #include +#include struct kref { atomic_t refcount; @@ -93,4 +94,21 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref) { return kref_sub(kref, 1, release); } + +static inline int kref_put_mutex(struct kref *kref, + void (*release)(struct kref *kref), + struct mutex *lock) +{ + WARN_ON(release == NULL); + if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { + mutex_lock(lock); + if (unlikely(!atomic_dec_and_test(&kref->refcount))) { + mutex_unlock(lock); + return 0; + } + release(kref); + return 1; + } + return 0; +} #endif /* _KREF_H_ */ -- GitLab From 6d2cd3ce815b302e885b44ca1bdbe3c7db321c7a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 21:27:32 -0400 Subject: [PATCH 5704/5711] vfio: get rid of open-coding kref_put_mutex Acked-by: Alex Williamson Signed-off-by: Al Viro --- drivers/vfio/vfio.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 0b025d58de81..92b85676e6be 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -264,6 +264,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) return group; } +/* called with vfio.group_lock held */ static void vfio_group_release(struct kref *kref) { struct vfio_group *group = container_of(kref, struct vfio_group, kref); @@ -287,13 +288,7 @@ static void vfio_group_release(struct kref *kref) static void vfio_group_put(struct vfio_group *group) { - mutex_lock(&vfio.group_lock); - /* - * Release needs to unlock to unregister the notifier, so only - * unlock if not released. - */ - if (!kref_put(&group->kref, vfio_group_release)) - mutex_unlock(&vfio.group_lock); + kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); } /* Assume group_lock or group reference is held */ -- GitLab From 90b1253e4139776e8257914ae9e2292d0de2fecc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 21:29:06 -0400 Subject: [PATCH 5705/5711] vfio: get rid of vfio_device_put()/vfio_group_get_device* races we really need to make sure that dropping the last reference happens under the group->device_lock; otherwise a loop (under device_lock) might find vfio_device instance that is being freed right now, has already dropped the last reference and waits on device_lock to exclude the sucker from the list. Acked-by: Alex Williamson Signed-off-by: Al Viro --- drivers/vfio/vfio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 92b85676e6be..887ae43276bb 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -396,7 +396,6 @@ static void vfio_device_release(struct kref *kref) struct vfio_device, kref); struct vfio_group *group = device->group; - mutex_lock(&group->device_lock); list_del(&device->group_next); mutex_unlock(&group->device_lock); @@ -412,7 +411,7 @@ static void vfio_device_release(struct kref *kref) static void vfio_device_put(struct vfio_device *device) { struct vfio_group *group = device->group; - kref_put(&device->kref, vfio_device_release); + kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock); vfio_group_put(group); } -- GitLab From 31605debdf5459cc8aacabf192a911a803a81c26 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 21:32:56 -0400 Subject: [PATCH 5706/5711] vfio: grab vfio_device reference *before* exposing the sucker via fd_install() It's not critical (anymore) since another thread closing the file will block on ->device_lock before it gets to dropping the final reference, but it's definitely cleaner that way... Acked-by: Alex Williamson Signed-off-by: Al Viro --- drivers/vfio/vfio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 887ae43276bb..17830c9c7cc6 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1111,10 +1111,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) */ filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); - fd_install(ret, filep); - vfio_device_get(device); atomic_inc(&group->container_users); + + fd_install(ret, filep); break; } mutex_unlock(&group->device_lock); -- GitLab From 98022748f6c7bce85b9f123fd4d1a621219dd8d9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Aug 2012 22:42:36 -0400 Subject: [PATCH 5707/5711] eventpoll: use-after-possible-free in epoll_create1() As soon as we'd installed the file into descriptor table, it can get closed by another thread. Freeing ep in process... Signed-off-by: Al Viro --- fs/eventpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 1c8b55670804..eedec84c1809 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1654,8 +1654,8 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) error = PTR_ERR(file); goto out_free_fd; } - fd_install(fd, file); ep->file = file; + fd_install(fd, file); return fd; out_free_fd: -- GitLab From 55852635a8e2803cbc22d0e143d727813f0fcdb5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 17:39:25 -0700 Subject: [PATCH 5708/5711] fs: fix fs/namei.c kernel-doc warnings Fix kernel-doc warnings in fs/namei.c: Warning(fs/namei.c:360): No description found for parameter 'inode' Warning(fs/namei.c:672): No description found for parameter 'nd' Signed-off-by: Randy Dunlap Cc: Alexander Viro Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/namei.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index db76b866a097..dd1ed1b8e98e 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -352,6 +352,7 @@ int __inode_permission(struct inode *inode, int mask) /** * sb_permission - Check superblock-level permissions * @sb: Superblock of inode to check permission on + * @inode: Inode to check permission on * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) * * Separate out file-system wide checks from inode-specific permission checks. @@ -656,6 +657,7 @@ int sysctl_protected_hardlinks __read_mostly = 1; /** * may_follow_link - Check symlink following for unsafe situations * @link: The path of the symlink + * @nd: nameidata pathwalk data * * In the case of the sysctl_protected_symlinks sysctl being enabled, * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is -- GitLab From 88ec2789d856056344161aa20420dd37e893b0fe Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Aug 2012 15:05:14 +0200 Subject: [PATCH 5709/5711] task_work: add a scheduling point in task_work_run() It seems commit 4a9d4b02 (switch fput to task_work_add) reintroduced the problem addressed in commit 944be0b2 (close_files(): add scheduling point) If a server process with a lot of files (say 2 million tcp sockets) is killed, we can spend a lot of time in task_work_run() and trigger a soft lockup. Signed-off-by: Eric Dumazet Signed-off-by: Al Viro --- kernel/task_work.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/task_work.c b/kernel/task_work.c index 91d4e1742a0c..d320d44903bd 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -75,6 +75,7 @@ void task_work_run(void) p = q->next; q->func(q); q = p; + cond_resched(); } } } -- GitLab From 53c84983549230495156d7da666cd1acdb9c9015 Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Wed, 22 Aug 2012 11:17:17 +0100 Subject: [PATCH 5710/5711] HID: Remove QUANTA from special drivers list This QUANTA device is driven by the generic hid-multitouch.ko driver, and therefore shouldn't be in the special drivers list. This has been an oversight in 4fa3a58 ("HID: hid-multitouch: Switch to device groups"). Signed-off-by: Simon Farnsworth Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 500844f04f93..78f0ee74b853 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1624,7 +1624,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, -- GitLab From fea7a08acb13524b47711625eebea40a0ede69a0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Aug 2012 13:29:06 -0700 Subject: [PATCH 5711/5711] Linux 3.6-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9cc77acfc881..354026873b13 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- GitLab